diff --git a/[refs] b/[refs] index 31257197628e..3c1d0df46a6c 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: bf8c80a6a5153e7f170f240731c650eeed6d78ff +refs/heads/master: 1709775828de83b099554176b6d4971ebc772962 diff --git a/trunk/Documentation/ABI/testing/debugfs-pktcdvd b/trunk/Documentation/ABI/testing/debugfs-pktcdvd new file mode 100644 index 000000000000..03dbd883cc41 --- /dev/null +++ b/trunk/Documentation/ABI/testing/debugfs-pktcdvd @@ -0,0 +1,20 @@ +What: /debug/pktcdvd/pktcdvd[0-7] +Date: Oct. 2006 +KernelVersion: 2.6.19 +Contact: Thomas Maier +Description: + +debugfs interface +----------------- + +The pktcdvd module (packet writing driver) creates +these files in debugfs: + +/debug/pktcdvd/pktcdvd[0-7]/ + info (0444) Lots of human readable driver + statistics and infos. Multiple lines! + +Example: +------- + +cat /debug/pktcdvd/pktcdvd0/info diff --git a/trunk/Documentation/ABI/testing/sysfs-class-pktcdvd b/trunk/Documentation/ABI/testing/sysfs-class-pktcdvd new file mode 100644 index 000000000000..c4c55edc9a5c --- /dev/null +++ b/trunk/Documentation/ABI/testing/sysfs-class-pktcdvd @@ -0,0 +1,72 @@ +What: /sys/class/pktcdvd/ +Date: Oct. 2006 +KernelVersion: 2.6.19 +Contact: Thomas Maier +Description: + +sysfs interface +--------------- + +The pktcdvd module (packet writing driver) creates +these files in the sysfs: +( is in format major:minor ) + +/sys/class/pktcdvd/ + add (0200) Write a block device id (major:minor) + to create a new pktcdvd device and map + it to the block device. + + remove (0200) Write the pktcdvd device id (major:minor) + to it to remove the pktcdvd device. + + device_map (0444) Shows the device mapping in format: + pktcdvd[0-7] + +/sys/class/pktcdvd/pktcdvd[0-7]/ + dev (0444) Device id + uevent (0200) To send an uevent. + +/sys/class/pktcdvd/pktcdvd[0-7]/stat/ + packets_started (0444) Number of started packets. + packets_finished (0444) Number of finished packets. + + kb_written (0444) kBytes written. + kb_read (0444) kBytes read. + kb_read_gather (0444) kBytes read to fill write packets. + + reset (0200) Write any value to it to reset + pktcdvd device statistic values, like + bytes read/written. + +/sys/class/pktcdvd/pktcdvd[0-7]/write_queue/ + size (0444) Contains the size of the bio write + queue. + + congestion_off (0644) If bio write queue size is below + this mark, accept new bio requests + from the block layer. + + congestion_on (0644) If bio write queue size is higher + as this mark, do no longer accept + bio write requests from the block + layer and wait till the pktcdvd + device has processed enough bio's + so that bio write queue size is + below congestion off mark. + A value of <= 0 disables congestion + control. + + +Example: +-------- +To use the pktcdvd sysfs interface directly, you can do: + +# create a new pktcdvd device mapped to /dev/hdc +echo "22:0" >/sys/class/pktcdvd/add +cat /sys/class/pktcdvd/device_map +# assuming device pktcdvd0 was created, look at stat's +cat /sys/class/pktcdvd/pktcdvd0/stat/kb_written +# print the device id of the mapped block device +fgrep pktcdvd0 /sys/class/pktcdvd/device_map +# remove device, using pktcdvd0 device id 253:0 +echo "253:0" >/sys/class/pktcdvd/remove diff --git a/trunk/Documentation/DMA-API.txt b/trunk/Documentation/DMA-API.txt index 05431621c861..805db4b2cba6 100644 --- a/trunk/Documentation/DMA-API.txt +++ b/trunk/Documentation/DMA-API.txt @@ -77,7 +77,7 @@ To get this part of the dma_ API, you must #include Many drivers need lots of small dma-coherent memory regions for DMA descriptors or I/O buffers. Rather than allocating in units of a page or more using dma_alloc_coherent(), you can use DMA pools. These work -much like a kmem_cache_t, except that they use the dma-coherent allocator +much like a struct kmem_cache, except that they use the dma-coherent allocator not __get_free_pages(). Also, they understand common hardware constraints for alignment, like queue heads needing to be aligned on N byte boundaries. @@ -94,7 +94,7 @@ The pool create() routines initialize a pool of dma-coherent buffers for use with a given device. It must be called in a context which can sleep. -The "name" is for diagnostics (like a kmem_cache_t name); dev and size +The "name" is for diagnostics (like a struct kmem_cache name); dev and size are like what you'd pass to dma_alloc_coherent(). The device's hardware alignment requirement for this type of data is "align" (which is expressed in bytes, and must be a power of two). If your device has no boundary @@ -431,10 +431,10 @@ be identical to those passed in (and returned by dma_alloc_noncoherent()). int -dma_is_consistent(dma_addr_t dma_handle) +dma_is_consistent(struct device *dev, dma_addr_t dma_handle) -returns true if the memory pointed to by the dma_handle is actually -consistent. +returns true if the device dev is performing consistent DMA on the memory +area pointed to by the dma_handle. int dma_get_cache_alignment(void) @@ -459,7 +459,7 @@ anything like this. You must also be extra careful about accessing memory you intend to sync partially. void -dma_cache_sync(void *vaddr, size_t size, +dma_cache_sync(struct device *dev, void *vaddr, size_t size, enum dma_data_direction direction) Do a partial sync of memory that was allocated by diff --git a/trunk/Documentation/DocBook/Makefile b/trunk/Documentation/DocBook/Makefile index db9499adbed4..36526a1e76d7 100644 --- a/trunk/Documentation/DocBook/Makefile +++ b/trunk/Documentation/DocBook/Makefile @@ -190,9 +190,13 @@ quiet_cmd_fig2png = FIG2PNG $@ ### # Help targets as used by the top-level makefile dochelp: - @echo ' Linux kernel internal documentation in different formats:' - @echo ' xmldocs (XML DocBook), psdocs (Postscript), pdfdocs (PDF)' - @echo ' htmldocs (HTML), mandocs (man pages, use installmandocs to install)' + @echo ' Linux kernel internal documentation in different formats:' + @echo ' htmldocs - HTML' + @echo ' installmandocs - install man pages generated by mandocs' + @echo ' mandocs - man pages' + @echo ' pdfdocs - PDF' + @echo ' psdocs - Postscript' + @echo ' xmldocs - XML DocBook' ### # Temporary files left by various tools diff --git a/trunk/Documentation/DocBook/kernel-api.tmpl b/trunk/Documentation/DocBook/kernel-api.tmpl index a166675c4303..3fa0c4b4541e 100644 --- a/trunk/Documentation/DocBook/kernel-api.tmpl +++ b/trunk/Documentation/DocBook/kernel-api.tmpl @@ -418,9 +418,35 @@ X!Edrivers/pnp/system.c !Idrivers/parport/daisy.c - - Video4Linux -!Edrivers/media/video/videodev.c + + Message-based devices + Fusion message devices +!Edrivers/message/fusion/mptbase.c +!Idrivers/message/fusion/mptbase.c +!Edrivers/message/fusion/mptscsih.c +!Idrivers/message/fusion/mptscsih.c +!Idrivers/message/fusion/mptctl.c +!Idrivers/message/fusion/mptspi.c +!Idrivers/message/fusion/mptfc.c +!Idrivers/message/fusion/mptlan.c + + I2O message devices +!Iinclude/linux/i2o.h +!Idrivers/message/i2o/core.h +!Edrivers/message/i2o/iop.c +!Idrivers/message/i2o/iop.c +!Idrivers/message/i2o/config-osm.c +!Edrivers/message/i2o/exec-osm.c +!Idrivers/message/i2o/exec-osm.c +!Idrivers/message/i2o/bus-osm.c +!Edrivers/message/i2o/device.c +!Idrivers/message/i2o/device.c +!Idrivers/message/i2o/driver.c +!Idrivers/message/i2o/pci.c +!Idrivers/message/i2o/i2o_block.c +!Idrivers/message/i2o/i2o_scsi.c +!Idrivers/message/i2o/i2o_proc.c + @@ -533,4 +559,12 @@ X!Idrivers/video/console/fonts.c --> + + + Input Subsystem +!Iinclude/linux/input.h +!Edrivers/input/input.c +!Edrivers/input/ff-core.c +!Edrivers/input/ff-memless.c + diff --git a/trunk/Documentation/IPMI.txt b/trunk/Documentation/IPMI.txt index 0e3924ecd76b..24dc3fcf1594 100644 --- a/trunk/Documentation/IPMI.txt +++ b/trunk/Documentation/IPMI.txt @@ -365,6 +365,7 @@ You can change this at module load time (for a module) with: regshifts=,,... slave_addrs=,,... force_kipmid=,,... + unload_when_empty=[0|1] Each of these except si_trydefaults is a list, the first item for the first interface, second item for the second interface, etc. @@ -416,6 +417,11 @@ by the driver, but systems with broken interrupts might need an enable, or users that don't want the daemon (don't need the performance, don't want the CPU hit) can disable it. +If unload_when_empty is set to 1, the driver will be unloaded if it +doesn't find any interfaces or all the interfaces fail to work. The +default is one. Setting to 0 is useful with the hotmod, but is +obviously only useful for modules. + When compiled into the kernel, the parameters can be specified on the kernel command line as: @@ -441,6 +447,25 @@ have high-res timers enabled in the kernel and you don't have interrupts enabled, the driver will run VERY slowly. Don't blame me, these interfaces suck. +The driver supports a hot add and remove of interfaces. This way, +interfaces can be added or removed after the kernel is up and running. +This is done using /sys/modules/ipmi_si/hotmod, which is a write-only +parameter. You write a string to this interface. The string has the +format: + [:op2[:op3...]] +The "op"s are: + add|remove,kcs|bt|smic,mem|i/o,
[,[,[,...]]] +You can specify more than one interface on the line. The "opt"s are: + rsp= + rsi= + rsh= + irq= + ipmb= +and these have the same meanings as discussed above. Note that you +can also use this on the kernel command line for a more compact format +for specifying an interface. Note that when removing an interface, +only the first three parameters (si type, address type, and address) +are used for the comparison. Any options are ignored for removing. The SMBus Driver ---------------- @@ -502,7 +527,10 @@ used to control it: modprobe ipmi_watchdog timeout= pretimeout= action= preaction= preop= start_now=x - nowayout=x + nowayout=x ifnum_to_use=n + +ifnum_to_use specifies which interface the watchdog timer should use. +The default is -1, which means to pick the first one registered. The timeout is the number of seconds to the action, and the pretimeout is the amount of seconds before the reset that the pre-timeout panic will @@ -624,5 +652,9 @@ command line. The parameter is also available via the proc filesystem in /proc/sys/dev/ipmi/poweroff_powercycle. Note that if the system does not support power cycling, it will always do the power off. +The "ifnum_to_use" parameter specifies which interface the poweroff +code should use. The default is -1, which means to pick the first one +registered. + Note that if you have ACPI enabled, the system will prefer using ACPI to power off. diff --git a/trunk/Documentation/block/as-iosched.txt b/trunk/Documentation/block/as-iosched.txt index e2a66f8143c5..a598fe10a297 100644 --- a/trunk/Documentation/block/as-iosched.txt +++ b/trunk/Documentation/block/as-iosched.txt @@ -24,8 +24,10 @@ very similar behavior to the deadline IO scheduler. Selecting IO schedulers ----------------------- To choose IO schedulers at boot time, use the argument 'elevator=deadline'. -'noop' and 'as' (the default) are also available. IO schedulers are assigned -globally at boot time only presently. +'noop', 'as' and 'cfq' (the default) are also available. IO schedulers are +assigned globally at boot time only presently. It's also possible to change +the IO scheduler for a determined device on the fly, as described in +Documentation/block/switching-sched.txt. Anticipatory IO scheduler Policies diff --git a/trunk/Documentation/cdrom/packet-writing.txt b/trunk/Documentation/cdrom/packet-writing.txt index 3d44c561fe6d..7715d2247c4d 100644 --- a/trunk/Documentation/cdrom/packet-writing.txt +++ b/trunk/Documentation/cdrom/packet-writing.txt @@ -90,6 +90,41 @@ Notes to create an ext2 filesystem on the disc. +Using the pktcdvd sysfs interface +--------------------------------- + +Since Linux 2.6.19, the pktcdvd module has a sysfs interface +and can be controlled by it. For example the "pktcdvd" tool uses +this interface. (see http://people.freenet.de/BalaGi#pktcdvd ) + +"pktcdvd" works similar to "pktsetup", e.g.: + + # pktcdvd -a dev_name /dev/hdc + # mkudffs /dev/pktcdvd/dev_name + # mount -t udf -o rw,noatime /dev/pktcdvd/dev_name /dvdram + # cp files /dvdram + # umount /dvdram + # pktcdvd -r dev_name + + +For a description of the sysfs interface look into the file: + + Documentation/ABI/testing/sysfs-block-pktcdvd + + +Using the pktcdvd debugfs interface +----------------------------------- + +To read pktcdvd device infos in human readable form, do: + + # cat /debug/pktcdvd/pktcdvd[0-7]/info + +For a description of the debugfs interface look into the file: + + Documentation/ABI/testing/debugfs-pktcdvd + + + Links ----- diff --git a/trunk/Documentation/devices.txt b/trunk/Documentation/devices.txt index 70690f1a14af..8de132a02ba9 100644 --- a/trunk/Documentation/devices.txt +++ b/trunk/Documentation/devices.txt @@ -3,7 +3,7 @@ Maintained by Torben Mathiasen - Last revised: 15 May 2006 + Last revised: 29 November 2006 This list is the Linux Device List, the official registry of allocated device numbers and /dev directory nodes for the Linux operating @@ -94,6 +94,7 @@ Your cooperation is appreciated. 9 = /dev/urandom Faster, less secure random number gen. 10 = /dev/aio Asynchronous I/O notification interface 11 = /dev/kmsg Writes to this come out as printk's + 1 block RAM disk 0 = /dev/ram0 First RAM disk 1 = /dev/ram1 Second RAM disk @@ -122,7 +123,7 @@ Your cooperation is appreciated. devices are on major 128 and above and use the PTY master multiplex (/dev/ptmx) to acquire a PTY on demand. - + 2 block Floppy disks 0 = /dev/fd0 Controller 0, drive 0, autodetect 1 = /dev/fd1 Controller 0, drive 1, autodetect @@ -257,7 +258,7 @@ Your cooperation is appreciated. 129 = /dev/vcsa1 tty1 text/attribute contents ... 191 = /dev/vcsa63 tty63 text/attribute contents - + NOTE: These devices permit both read and write access. 7 block Loopback devices @@ -411,7 +412,7 @@ Your cooperation is appreciated. 207 = /dev/video/em8300_sp EM8300 DVD decoder subpicture 208 = /dev/compaq/cpqphpc Compaq PCI Hot Plug Controller 209 = /dev/compaq/cpqrid Compaq Remote Insight Driver - 210 = /dev/impi/bt IMPI coprocessor block transfer + 210 = /dev/impi/bt IMPI coprocessor block transfer 211 = /dev/impi/smic IMPI coprocessor stream interface 212 = /dev/watchdogs/0 First watchdog device 213 = /dev/watchdogs/1 Second watchdog device @@ -506,6 +507,7 @@ Your cooperation is appreciated. 33 = /dev/patmgr1 Sequencer patch manager 34 = /dev/midi02 Third MIDI port 50 = /dev/midi03 Fourth MIDI port + 14 block BIOS harddrive callback support {2.6} 0 = /dev/dos_hda First BIOS harddrive whole disk 64 = /dev/dos_hdb Second BIOS harddrive whole disk @@ -527,6 +529,7 @@ Your cooperation is appreciated. 16 char Non-SCSI scanners 0 = /dev/gs4500 Genius 4500 handheld scanner + 16 block GoldStar CD-ROM 0 = /dev/gscd GoldStar CD-ROM @@ -548,6 +551,7 @@ Your cooperation is appreciated. 0 = /dev/ttyC0 First Cyclades port ... 31 = /dev/ttyC31 32nd Cyclades port + 19 block "Double" compressed disk 0 = /dev/double0 First compressed disk ... @@ -563,6 +567,7 @@ Your cooperation is appreciated. 0 = /dev/cub0 Callout device for ttyC0 ... 31 = /dev/cub31 Callout device for ttyC31 + 20 block Hitachi CD-ROM (under development) 0 = /dev/hitcd Hitachi CD-ROM @@ -582,7 +587,7 @@ Your cooperation is appreciated. This device is used on the ARM-based Acorn RiscPC. Partitions are handled the same way as for IDE disks - (see major number 3). + (see major number 3). 22 char Digiboard serial card 0 = /dev/ttyD0 First Digiboard port @@ -591,7 +596,7 @@ Your cooperation is appreciated. 22 block Second IDE hard disk/CD-ROM interface 0 = /dev/hdc Master: whole disk (or CD-ROM) 64 = /dev/hdd Slave: whole disk (or CD-ROM) - + Partitions are handled the same way as for the first interface (see major number 3). @@ -639,6 +644,7 @@ Your cooperation is appreciated. 26 char Quanta WinVision frame grabber {2.6} 0 = /dev/wvisfgrab Quanta WinVision frame grabber + 26 block Second Matsushita (Panasonic/SoundBlaster) CD-ROM 0 = /dev/sbpcd4 Panasonic CD-ROM controller 1 unit 0 1 = /dev/sbpcd5 Panasonic CD-ROM controller 1 unit 1 @@ -670,6 +676,7 @@ Your cooperation is appreciated. 37 = /dev/nrawqft1 Unit 1, no rewind-on-close, no file marks 38 = /dev/nrawqft2 Unit 2, no rewind-on-close, no file marks 39 = /dev/nrawqft3 Unit 3, no rewind-on-close, no file marks + 27 block Third Matsushita (Panasonic/SoundBlaster) CD-ROM 0 = /dev/sbpcd8 Panasonic CD-ROM controller 2 unit 0 1 = /dev/sbpcd9 Panasonic CD-ROM controller 2 unit 1 @@ -681,6 +688,7 @@ Your cooperation is appreciated. 1 = /dev/staliomem1 Second Stallion card I/O memory 2 = /dev/staliomem2 Third Stallion card I/O memory 3 = /dev/staliomem3 Fourth Stallion card I/O memory + 28 char Atari SLM ACSI laser printer (68k/Atari) 0 = /dev/slm0 First SLM laser printer 1 = /dev/slm1 Second SLM laser printer @@ -690,6 +698,7 @@ Your cooperation is appreciated. 1 = /dev/sbpcd13 Panasonic CD-ROM controller 3 unit 1 2 = /dev/sbpcd14 Panasonic CD-ROM controller 3 unit 2 3 = /dev/sbpcd15 Panasonic CD-ROM controller 3 unit 3 + 28 block ACSI disk (68k/Atari) 0 = /dev/ada First ACSI disk whole disk 16 = /dev/adb Second ACSI disk whole disk @@ -750,6 +759,7 @@ Your cooperation is appreciated. 31 char MPU-401 MIDI 0 = /dev/mpu401data MPU-401 data port 1 = /dev/mpu401stat MPU-401 status port + 31 block ROM/flash memory card 0 = /dev/rom0 First ROM card (rw) ... @@ -801,7 +811,7 @@ Your cooperation is appreciated. 34 block Fourth IDE hard disk/CD-ROM interface 0 = /dev/hdg Master: whole disk (or CD-ROM) 64 = /dev/hdh Slave: whole disk (or CD-ROM) - + Partitions are handled the same way as for the first interface (see major number 3). @@ -818,6 +828,7 @@ Your cooperation is appreciated. 129 = /dev/smpte1 Second MIDI port, SMPTE timed 130 = /dev/smpte2 Third MIDI port, SMPTE timed 131 = /dev/smpte3 Fourth MIDI port, SMPTE timed + 35 block Slow memory ramdisk 0 = /dev/slram Slow memory ramdisk @@ -828,6 +839,7 @@ Your cooperation is appreciated. 16 = /dev/tap0 First Ethertap device ... 31 = /dev/tap15 16th Ethertap device + 36 block MCA ESDI hard disk 0 = /dev/eda First ESDI disk whole disk 64 = /dev/edb Second ESDI disk whole disk @@ -882,6 +894,7 @@ Your cooperation is appreciated. 40 char Matrox Meteor frame grabber {2.6} 0 = /dev/mmetfgrab Matrox Meteor frame grabber + 40 block Syquest EZ135 parallel port removable drive 0 = /dev/eza Parallel EZ135 drive, whole disk @@ -893,6 +906,7 @@ Your cooperation is appreciated. 41 char Yet Another Micro Monitor 0 = /dev/yamm Yet Another Micro Monitor + 41 block MicroSolutions BackPack parallel port CD-ROM 0 = /dev/bpcd BackPack CD-ROM @@ -901,6 +915,7 @@ Your cooperation is appreciated. the parallel port ATAPI CD-ROM driver at major number 46. 42 char Demo/sample use + 42 block Demo/sample use This number is intended for use in sample code, as @@ -918,6 +933,7 @@ Your cooperation is appreciated. 0 = /dev/ttyI0 First virtual modem ... 63 = /dev/ttyI63 64th virtual modem + 43 block Network block devices 0 = /dev/nb0 First network block device 1 = /dev/nb1 Second network block device @@ -934,12 +950,13 @@ Your cooperation is appreciated. 0 = /dev/cui0 Callout device for ttyI0 ... 63 = /dev/cui63 Callout device for ttyI63 + 44 block Flash Translation Layer (FTL) filesystems 0 = /dev/ftla FTL on first Memory Technology Device 16 = /dev/ftlb FTL on second Memory Technology Device 32 = /dev/ftlc FTL on third Memory Technology Device ... - 240 = /dev/ftlp FTL on 16th Memory Technology Device + 240 = /dev/ftlp FTL on 16th Memory Technology Device Partitions are handled in the same way as for IDE disks (see major number 3) except that the partition @@ -958,6 +975,7 @@ Your cooperation is appreciated. 191 = /dev/ippp63 64th SyncPPP device 255 = /dev/isdninfo ISDN monitor interface + 45 block Parallel port IDE disk devices 0 = /dev/pda First parallel port IDE disk 16 = /dev/pdb Second parallel port IDE disk @@ -1044,6 +1062,7 @@ Your cooperation is appreciated. 1 = /dev/dcbri1 Second DataComm card 2 = /dev/dcbri2 Third DataComm card 3 = /dev/dcbri3 Fourth DataComm card + 52 block Mylex DAC960 PCI RAID controller; fifth controller 0 = /dev/rd/c4d0 First disk, whole disk 8 = /dev/rd/c4d1 Second disk, whole disk @@ -1093,6 +1112,7 @@ Your cooperation is appreciated. 55 char DSP56001 digital signal processor 0 = /dev/dsp56k First DSP56001 + 55 block Mylex DAC960 PCI RAID controller; eighth controller 0 = /dev/rd/c7d0 First disk, whole disk 8 = /dev/rd/c7d1 Second disk, whole disk @@ -1130,6 +1150,7 @@ Your cooperation is appreciated. 0 = /dev/cup0 Callout device for ttyP0 1 = /dev/cup1 Callout device for ttyP1 ... + 58 block Reserved for logical volume manager 59 char sf firewall package @@ -1149,6 +1170,7 @@ Your cooperation is appreciated. NAMING CONFLICT -- PROPOSED REVISED NAME /dev/rpda0 etc 60-63 char LOCAL/EXPERIMENTAL USE + 60-63 block LOCAL/EXPERIMENTAL USE Allocated for local/experimental use. For devices not assigned official numbers, these ranges should be @@ -1434,7 +1456,6 @@ Your cooperation is appreciated. DAC960 (see major number 48) except that the limit on partitions is 15. - 78 char PAM Software's multimodem boards 0 = /dev/ttyM0 First PAM modem 1 = /dev/ttyM1 Second PAM modem @@ -1450,7 +1471,6 @@ Your cooperation is appreciated. DAC960 (see major number 48) except that the limit on partitions is 15. - 79 char PAM Software's multimodem boards - alternate devices 0 = /dev/cum0 Callout device for ttyM0 1 = /dev/cum1 Callout device for ttyM1 @@ -1466,7 +1486,6 @@ Your cooperation is appreciated. DAC960 (see major number 48) except that the limit on partitions is 15. - 80 char Photometrics AT200 CCD camera 0 = /dev/at200 Photometrics AT200 CCD camera @@ -1679,7 +1698,7 @@ Your cooperation is appreciated. 1 = /dev/dcxx1 Second capture card ... - 94 block IBM S/390 DASD block storage + 94 block IBM S/390 DASD block storage 0 = /dev/dasda First DASD device, major 1 = /dev/dasda1 First DASD device, block 1 2 = /dev/dasda2 First DASD device, block 2 @@ -1695,7 +1714,7 @@ Your cooperation is appreciated. 1 = /dev/ipnat NAT control device/log file 2 = /dev/ipstate State information log file 3 = /dev/ipauth Authentication control device/log file - ... + ... 96 char Parallel port ATAPI tape devices 0 = /dev/pt0 First parallel port ATAPI tape @@ -1705,7 +1724,7 @@ Your cooperation is appreciated. 129 = /dev/npt1 Second p.p. ATAPI tape, no rewind ... - 96 block Inverse NAND Flash Translation Layer + 96 block Inverse NAND Flash Translation Layer 0 = /dev/inftla First INFTL layer 16 = /dev/inftlb Second INFTL layer ... @@ -1937,7 +1956,6 @@ Your cooperation is appreciated. ... 113 block IBM iSeries virtual CD-ROM - 0 = /dev/iseries/vcda First virtual CD-ROM 1 = /dev/iseries/vcdb Second virtual CD-ROM ... @@ -2059,11 +2077,12 @@ Your cooperation is appreciated. ... 119 char VMware virtual network control - 0 = /dev/vnet0 1st virtual network - 1 = /dev/vnet1 2nd virtual network + 0 = /dev/vmnet0 1st virtual network + 1 = /dev/vmnet1 2nd virtual network ... 120-127 char LOCAL/EXPERIMENTAL USE + 120-127 block LOCAL/EXPERIMENTAL USE Allocated for local/experimental use. For devices not assigned official numbers, these ranges should be @@ -2075,7 +2094,6 @@ Your cooperation is appreciated. nodes; instead they should be accessed through the /dev/ptmx cloning interface. - 128 block SCSI disk devices (128-143) 0 = /dev/sddy 129th SCSI disk whole disk 16 = /dev/sddz 130th SCSI disk whole disk @@ -2087,7 +2105,6 @@ Your cooperation is appreciated. disks (see major number 3) except that the limit on partitions is 15. - 129 block SCSI disk devices (144-159) 0 = /dev/sdeo 145th SCSI disk whole disk 16 = /dev/sdep 146th SCSI disk whole disk @@ -2123,7 +2140,6 @@ Your cooperation is appreciated. disks (see major number 3) except that the limit on partitions is 15. - 132 block SCSI disk devices (192-207) 0 = /dev/sdgk 193rd SCSI disk whole disk 16 = /dev/sdgl 194th SCSI disk whole disk @@ -2135,7 +2151,6 @@ Your cooperation is appreciated. disks (see major number 3) except that the limit on partitions is 15. - 133 block SCSI disk devices (208-223) 0 = /dev/sdha 209th SCSI disk whole disk 16 = /dev/sdhb 210th SCSI disk whole disk @@ -2147,7 +2162,6 @@ Your cooperation is appreciated. disks (see major number 3) except that the limit on partitions is 15. - 134 block SCSI disk devices (224-239) 0 = /dev/sdhq 225th SCSI disk whole disk 16 = /dev/sdhr 226th SCSI disk whole disk @@ -2159,7 +2173,6 @@ Your cooperation is appreciated. disks (see major number 3) except that the limit on partitions is 15. - 135 block SCSI disk devices (240-255) 0 = /dev/sdig 241st SCSI disk whole disk 16 = /dev/sdih 242nd SCSI disk whole disk @@ -2171,7 +2184,6 @@ Your cooperation is appreciated. disks (see major number 3) except that the limit on partitions is 15. - 136-143 char Unix98 PTY slaves 0 = /dev/pts/0 First Unix98 pseudo-TTY 1 = /dev/pts/1 Second Unix98 pesudo-TTY @@ -2384,6 +2396,7 @@ Your cooperation is appreciated. ... 159 char RESERVED + 159 block RESERVED 160 char General Purpose Instrument Bus (GPIB) @@ -2427,7 +2440,7 @@ Your cooperation is appreciated. Partitions are handled in the same way as for IDE disks (see major number 3) except that the limit on - partitions is 31. + partitions is 31. 162 char Raw block device interface 0 = /dev/rawctl Raw I/O control device @@ -2483,7 +2496,6 @@ Your cooperation is appreciated. 171 char Reserved for IEEE 1394 (Firewire) - 172 char Moxa Intellio serial card 0 = /dev/ttyMX0 First Moxa port 1 = /dev/ttyMX1 Second Moxa port @@ -2543,9 +2555,6 @@ Your cooperation is appreciated. 64 = /dev/usb/rio500 Diamond Rio 500 65 = /dev/usb/usblcd USBLCD Interface (info@usblcd.de) 66 = /dev/usb/cpad0 Synaptics cPad (mouse/LCD) - 67 = /dev/usb/adutux0 1st Ontrak ADU device - ... - 76 = /dev/usb/adutux10 10th Ontrak ADU device 96 = /dev/usb/hiddev0 1st USB HID device ... 111 = /dev/usb/hiddev15 16th USB HID device @@ -2558,7 +2567,7 @@ Your cooperation is appreciated. 132 = /dev/usb/idmouse ID Mouse (fingerprint scanner) device 133 = /dev/usb/sisusbvga1 First SiSUSB VGA device ... - 140 = /dev/usb/sisusbvga8 Eigth SISUSB VGA device + 140 = /dev/usb/sisusbvga8 Eighth SISUSB VGA device 144 = /dev/usb/lcd USB LCD device 160 = /dev/usb/legousbtower0 1st USB Legotower device ... @@ -2571,7 +2580,7 @@ Your cooperation is appreciated. 0 = /dev/uba First USB block device 8 = /dev/ubb Second USB block device 16 = /dev/ubc Third USB block device - ... + ... 181 char Conrad Electronic parallel port radio clocks 0 = /dev/pcfclock0 First Conrad radio clock @@ -2657,7 +2666,7 @@ Your cooperation is appreciated. 32 = /dev/mvideo/status2 Third device ... ... - 240 = /dev/mvideo/status15 16th device + 240 = /dev/mvideo/status15 16th device ... 195 char Nvidia graphics devices @@ -2795,6 +2804,10 @@ Your cooperation is appreciated. ... 185 = /dev/ttyNX15 Hilscher netX serial port 15 186 = /dev/ttyJ0 JTAG1 DCC protocol based serial port emulation + 187 = /dev/ttyUL0 Xilinx uartlite - port 0 + ... + 190 = /dev/ttyUL3 Xilinx uartlite - port 3 + 191 = /dev/xvc0 Xen virtual console - port 0 205 char Low-density serial ports (alternate device) 0 = /dev/culu0 Callout device for ttyLU0 @@ -2832,7 +2845,6 @@ Your cooperation is appreciated. 82 = /dev/cuvr0 Callout device for ttyVR0 83 = /dev/cuvr1 Callout device for ttyVR1 - 206 char OnStream SC-x0 tape devices 0 = /dev/osst0 First OnStream SCSI tape, mode 0 1 = /dev/osst1 Second OnStream SCSI tape, mode 0 @@ -2922,7 +2934,6 @@ Your cooperation is appreciated. ... 212 char LinuxTV.org DVB driver subsystem - 0 = /dev/dvb/adapter0/video0 first video decoder of first card 1 = /dev/dvb/adapter0/audio0 first audio decoder of first card 2 = /dev/dvb/adapter0/sec0 (obsolete/unused) @@ -3008,9 +3019,9 @@ Your cooperation is appreciated. 2 = /dev/3270/tub2 Second 3270 terminal ... -229 char IBM iSeries virtual console - 0 = /dev/iseries/vtty0 First console port - 1 = /dev/iseries/vtty1 Second console port +229 char IBM iSeries/pSeries virtual console + 0 = /dev/hvc0 First console port + 1 = /dev/hvc1 Second console port ... 230 char IBM iSeries virtual tape @@ -3083,12 +3094,14 @@ Your cooperation is appreciated. 234-239 UNASSIGNED 240-254 char LOCAL/EXPERIMENTAL USE + 240-254 block LOCAL/EXPERIMENTAL USE Allocated for local/experimental use. For devices not assigned official numbers, these ranges should be used in order to avoid conflicting with future assignments. 255 char RESERVED + 255 block RESERVED This major is reserved to assist the expansion to a @@ -3115,7 +3128,20 @@ Your cooperation is appreciated. 257 char Phoenix Technologies Cryptographic Services Driver 0 = /dev/ptlsec Crypto Services Driver - +257 block SSFDC Flash Translation Layer filesystem + 0 = /dev/ssfdca First SSFDC layer + 8 = /dev/ssfdcb Second SSFDC layer + 16 = /dev/ssfdcc Third SSFDC layer + 24 = /dev/ssfdcd 4th SSFDC layer + 32 = /dev/ssfdce 5th SSFDC layer + 40 = /dev/ssfdcf 6th SSFDC layer + 48 = /dev/ssfdcg 7th SSFDC layer + 56 = /dev/ssfdch 8th SSFDC layer + +258 block ROM/Flash read-only translation layer + 0 = /dev/blockrom0 First ROM card's translation layer interface + 1 = /dev/blockrom1 Second ROM card's translation layer interface + ... **** ADDITIONAL /dev DIRECTORY ENTRIES diff --git a/trunk/Documentation/fault-injection/failcmd.sh b/trunk/Documentation/fault-injection/failcmd.sh new file mode 100644 index 000000000000..63177aba8106 --- /dev/null +++ b/trunk/Documentation/fault-injection/failcmd.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +echo 1 > /proc/self/make-it-fail +exec $* diff --git a/trunk/Documentation/fault-injection/failmodule.sh b/trunk/Documentation/fault-injection/failmodule.sh new file mode 100644 index 000000000000..474a8b971f9c --- /dev/null +++ b/trunk/Documentation/fault-injection/failmodule.sh @@ -0,0 +1,31 @@ +#!/bin/bash +# +# Usage: failmodule [stacktrace-depth] +# +# : "failslab", "fail_alloc_page", or "fail_make_request" +# +# : module name that you want to inject faults. +# +# [stacktrace-depth]: the maximum number of stacktrace walking allowed +# + +STACKTRACE_DEPTH=5 +if [ $# -gt 2 ]; then + STACKTRACE_DEPTH=$3 +fi + +if [ ! -d /debug/$1 ]; then + echo "Fault-injection $1 does not exist" >&2 + exit 1 +fi +if [ ! -d /sys/module/$2 ]; then + echo "Module $2 does not exist" >&2 + exit 1 +fi + +# Disable any fault injection +echo 0 > /debug/$1/stacktrace-depth + +echo `cat /sys/module/$2/sections/.text` > /debug/$1/require-start +echo `cat /sys/module/$2/sections/.exit.text` > /debug/$1/require-end +echo $STACKTRACE_DEPTH > /debug/$1/stacktrace-depth diff --git a/trunk/Documentation/fault-injection/fault-injection.txt b/trunk/Documentation/fault-injection/fault-injection.txt new file mode 100644 index 000000000000..b7ca560b9340 --- /dev/null +++ b/trunk/Documentation/fault-injection/fault-injection.txt @@ -0,0 +1,225 @@ +Fault injection capabilities infrastructure +=========================================== + +See also drivers/md/faulty.c and "every_nth" module option for scsi_debug. + + +Available fault injection capabilities +-------------------------------------- + +o failslab + + injects slab allocation failures. (kmalloc(), kmem_cache_alloc(), ...) + +o fail_page_alloc + + injects page allocation failures. (alloc_pages(), get_free_pages(), ...) + +o fail_make_request + + injects disk IO errors on devices permitted by setting + /sys/block//make-it-fail or + /sys/block///make-it-fail. (generic_make_request()) + +Configure fault-injection capabilities behavior +----------------------------------------------- + +o debugfs entries + +fault-inject-debugfs kernel module provides some debugfs entries for runtime +configuration of fault-injection capabilities. + +- /debug/fail*/probability: + + likelihood of failure injection, in percent. + Format: + + Note that one-failure-per-hundred is a very high error rate + for some testcases. Consider setting probability=100 and configure + /debug/fail*/interval for such testcases. + +- /debug/fail*/interval: + + specifies the interval between failures, for calls to + should_fail() that pass all the other tests. + + Note that if you enable this, by setting interval>1, you will + probably want to set probability=100. + +- /debug/fail*/times: + + specifies how many times failures may happen at most. + A value of -1 means "no limit". + +- /debug/fail*/space: + + specifies an initial resource "budget", decremented by "size" + on each call to should_fail(,size). Failure injection is + suppressed until "space" reaches zero. + +- /debug/fail*/verbose + + Format: { 0 | 1 | 2 } + specifies the verbosity of the messages when failure is + injected. '0' means no messages; '1' will print only a single + log line per failure; '2' will print a call trace too -- useful + to debug the problems revealed by fault injection. + +- /debug/fail*/task-filter: + + Format: { 'Y' | 'N' } + A value of 'N' disables filtering by process (default). + Any positive value limits failures to only processes indicated by + /proc//make-it-fail==1. + +- /debug/fail*/require-start: +- /debug/fail*/require-end: +- /debug/fail*/reject-start: +- /debug/fail*/reject-end: + + specifies the range of virtual addresses tested during + stacktrace walking. Failure is injected only if some caller + in the walked stacktrace lies within the required range, and + none lies within the rejected range. + Default required range is [0,ULONG_MAX) (whole of virtual address space). + Default rejected range is [0,0). + +- /debug/fail*/stacktrace-depth: + + specifies the maximum stacktrace depth walked during search + for a caller within [require-start,require-end) OR + [reject-start,reject-end). + +- /debug/fail_page_alloc/ignore-gfp-highmem: + + Format: { 'Y' | 'N' } + default is 'N', setting it to 'Y' won't inject failures into + highmem/user allocations. + +- /debug/failslab/ignore-gfp-wait: +- /debug/fail_page_alloc/ignore-gfp-wait: + + Format: { 'Y' | 'N' } + default is 'N', setting it to 'Y' will inject failures + only into non-sleep allocations (GFP_ATOMIC allocations). + +o Boot option + +In order to inject faults while debugfs is not available (early boot time), +use the boot option: + + failslab= + fail_page_alloc= + fail_make_request=,,, + +How to add new fault injection capability +----------------------------------------- + +o #include + +o define the fault attributes + + DECLARE_FAULT_INJECTION(name); + + Please see the definition of struct fault_attr in fault-inject.h + for details. + +o provide a way to configure fault attributes + +- boot option + + If you need to enable the fault injection capability from boot time, you can + provide boot option to configure it. There is a helper function for it: + + setup_fault_attr(attr, str); + +- debugfs entries + + failslab, fail_page_alloc, and fail_make_request use this way. + Helper functions: + + init_fault_attr_entries(entries, attr, name); + void cleanup_fault_attr_entries(entries); + +- module parameters + + If the scope of the fault injection capability is limited to a + single kernel module, it is better to provide module parameters to + configure the fault attributes. + +o add a hook to insert failures + + Upon should_fail() returning true, client code should inject a failure. + + should_fail(attr, size); + +Application Examples +-------------------- + +o inject slab allocation failures into module init/cleanup code + +------------------------------------------------------------------------------ +#!/bin/bash + +FAILCMD=Documentation/fault-injection/failcmd.sh +BLACKLIST="root_plug evbug" + +FAILNAME=failslab +echo Y > /debug/$FAILNAME/task-filter +echo 10 > /debug/$FAILNAME/probability +echo 100 > /debug/$FAILNAME/interval +echo -1 > /debug/$FAILNAME/times +echo 2 > /debug/$FAILNAME/verbose +echo 1 > /debug/$FAILNAME/ignore-gfp-wait + +blacklist() +{ + echo $BLACKLIST | grep $1 > /dev/null 2>&1 +} + +oops() +{ + dmesg | grep BUG > /dev/null 2>&1 +} + +find /lib/modules/`uname -r` -name '*.ko' -exec basename {} .ko \; | + while read i + do + oops && exit 1 + + if ! blacklist $i + then + echo inserting $i... + bash $FAILCMD modprobe $i + fi + done + +lsmod | awk '{ if ($3 == 0) { print $1 } }' | + while read i + do + oops && exit 1 + + if ! blacklist $i + then + echo removing $i... + bash $FAILCMD modprobe -r $i + fi + done + +------------------------------------------------------------------------------ + +o inject slab allocation failures only for a specific module + +------------------------------------------------------------------------------ +#!/bin/bash + +FAILMOD=Documentation/fault-injection/failmodule.sh + +echo injecting errors into the module $1... + +modprobe $1 +bash $FAILMOD failslab $1 10 +echo 25 > /debug/failslab/probability + +------------------------------------------------------------------------------ + diff --git a/trunk/Documentation/feature-removal-schedule.txt b/trunk/Documentation/feature-removal-schedule.txt index 226ecf2ffd56..46f2a559b27c 100644 --- a/trunk/Documentation/feature-removal-schedule.txt +++ b/trunk/Documentation/feature-removal-schedule.txt @@ -30,11 +30,39 @@ Who: Adrian Bunk --------------------------- What: raw1394: requests of type RAW1394_REQ_ISO_SEND, RAW1394_REQ_ISO_LISTEN -When: November 2006 -Why: Deprecated in favour of the new ioctl-based rawiso interface, which is - more efficient. You should really be using libraw1394 for raw1394 - access anyway. -Who: Jody McIntyre +When: June 2007 +Why: Deprecated in favour of the more efficient and robust rawiso interface. + Affected are applications which use the deprecated part of libraw1394 + (raw1394_iso_write, raw1394_start_iso_write, raw1394_start_iso_rcv, + raw1394_stop_iso_rcv) or bypass libraw1394. +Who: Dan Dennedy , Stefan Richter + +--------------------------- + +What: dv1394 driver (CONFIG_IEEE1394_DV1394) +When: June 2007 +Why: Replaced by raw1394 + userspace libraries, notably libiec61883. This + shift of application support has been indicated on www.linux1394.org + and developers' mailinglists for quite some time. Major applications + have been converted, with the exception of ffmpeg and hence xine. + Piped output of dvgrab2 is a partial equivalent to dv1394. +Who: Dan Dennedy , Stefan Richter + +--------------------------- + +What: ieee1394 core's unused exports (CONFIG_IEEE1394_EXPORT_FULL_API) +When: January 2007 +Why: There are no projects known to use these exported symbols, except + dfg1394 (uses one symbol whose functionality is core-internal now). +Who: Stefan Richter + +--------------------------- + +What: ieee1394's *_oui sysfs attributes (CONFIG_IEEE1394_OUI_DB) +When: January 2007 +Files: drivers/ieee1394/: oui.db, oui2c.sh +Why: big size, little value +Who: Stefan Richter --------------------------- diff --git a/trunk/Documentation/filesystems/Locking b/trunk/Documentation/filesystems/Locking index eb1a6cad21e6..790ef6fbe495 100644 --- a/trunk/Documentation/filesystems/Locking +++ b/trunk/Documentation/filesystems/Locking @@ -124,7 +124,7 @@ sync_fs: no no read write_super_lockfs: ? unlockfs: ? statfs: no no no -remount_fs: no yes maybe (see below) +remount_fs: yes yes maybe (see below) clear_inode: no umount_begin: yes no no show_options: no (vfsmount->sem) diff --git a/trunk/Documentation/filesystems/fuse.txt b/trunk/Documentation/filesystems/fuse.txt index 3d7447738958..345392c4caeb 100644 --- a/trunk/Documentation/filesystems/fuse.txt +++ b/trunk/Documentation/filesystems/fuse.txt @@ -51,6 +51,22 @@ homepage: http://fuse.sourceforge.net/ +Filesystem type +~~~~~~~~~~~~~~~ + +The filesystem type given to mount(2) can be one of the following: + +'fuse' + + This is the usual way to mount a FUSE filesystem. The first + argument of the mount system call may contain an arbitrary string, + which is not interpreted by the kernel. + +'fuseblk' + + The filesystem is block device based. The first argument of the + mount system call is interpreted as the name of the device. + Mount options ~~~~~~~~~~~~~ @@ -94,6 +110,11 @@ Mount options The default is infinite. Note that the size of read requests is limited anyway to 32 pages (which is 128kbyte on i386). +'blksize=N' + + Set the block size for the filesystem. The default is 512. This + option is only valid for 'fuseblk' type mounts. + Control filesystem ~~~~~~~~~~~~~~~~~~ diff --git a/trunk/Documentation/filesystems/sysv-fs.txt b/trunk/Documentation/filesystems/sysv-fs.txt index d81722418010..253b50d1328e 100644 --- a/trunk/Documentation/filesystems/sysv-fs.txt +++ b/trunk/Documentation/filesystems/sysv-fs.txt @@ -1,11 +1,8 @@ -This is the implementation of the SystemV/Coherent filesystem for Linux. It implements all of - Xenix FS, - SystemV/386 FS, - Coherent FS. -This is version beta 4. - To install: * Answer the 'System V and Coherent filesystem support' question with 'y' when configuring the kernel. @@ -28,11 +25,173 @@ Bugs in the present implementation: for this FS on hard disk yet. -Please report any bugs and suggestions to - Bruno Haible - Pascal Haible - Krzysztof G. Baranowski +These filesystems are rather similar. Here is a comparison with Minix FS: + +* Linux fdisk reports on partitions + - Minix FS 0x81 Linux/Minix + - Xenix FS ?? + - SystemV FS ?? + - Coherent FS 0x08 AIX bootable + +* Size of a block or zone (data allocation unit on disk) + - Minix FS 1024 + - Xenix FS 1024 (also 512 ??) + - SystemV FS 1024 (also 512 and 2048) + - Coherent FS 512 + +* General layout: all have one boot block, one super block and + separate areas for inodes and for directories/data. + On SystemV Release 2 FS (e.g. Microport) the first track is reserved and + all the block numbers (including the super block) are offset by one track. + +* Byte ordering of "short" (16 bit entities) on disk: + - Minix FS little endian 0 1 + - Xenix FS little endian 0 1 + - SystemV FS little endian 0 1 + - Coherent FS little endian 0 1 + Of course, this affects only the file system, not the data of files on it! + +* Byte ordering of "long" (32 bit entities) on disk: + - Minix FS little endian 0 1 2 3 + - Xenix FS little endian 0 1 2 3 + - SystemV FS little endian 0 1 2 3 + - Coherent FS PDP-11 2 3 0 1 + Of course, this affects only the file system, not the data of files on it! + +* Inode on disk: "short", 0 means non-existent, the root dir ino is: + - Minix FS 1 + - Xenix FS, SystemV FS, Coherent FS 2 + +* Maximum number of hard links to a file: + - Minix FS 250 + - Xenix FS ?? + - SystemV FS ?? + - Coherent FS >=10000 + +* Free inode management: + - Minix FS a bitmap + - Xenix FS, SystemV FS, Coherent FS + There is a cache of a certain number of free inodes in the super-block. + When it is exhausted, new free inodes are found using a linear search. + +* Free block management: + - Minix FS a bitmap + - Xenix FS, SystemV FS, Coherent FS + Free blocks are organized in a "free list". Maybe a misleading term, + since it is not true that every free block contains a pointer to + the next free block. Rather, the free blocks are organized in chunks + of limited size, and every now and then a free block contains pointers + to the free blocks pertaining to the next chunk; the first of these + contains pointers and so on. The list terminates with a "block number" + 0 on Xenix FS and SystemV FS, with a block zeroed out on Coherent FS. + +* Super-block location: + - Minix FS block 1 = bytes 1024..2047 + - Xenix FS block 1 = bytes 1024..2047 + - SystemV FS bytes 512..1023 + - Coherent FS block 1 = bytes 512..1023 + +* Super-block layout: + - Minix FS + unsigned short s_ninodes; + unsigned short s_nzones; + unsigned short s_imap_blocks; + unsigned short s_zmap_blocks; + unsigned short s_firstdatazone; + unsigned short s_log_zone_size; + unsigned long s_max_size; + unsigned short s_magic; + - Xenix FS, SystemV FS, Coherent FS + unsigned short s_firstdatazone; + unsigned long s_nzones; + unsigned short s_fzone_count; + unsigned long s_fzones[NICFREE]; + unsigned short s_finode_count; + unsigned short s_finodes[NICINOD]; + char s_flock; + char s_ilock; + char s_modified; + char s_rdonly; + unsigned long s_time; + short s_dinfo[4]; -- SystemV FS only + unsigned long s_free_zones; + unsigned short s_free_inodes; + short s_dinfo[4]; -- Xenix FS only + unsigned short s_interleave_m,s_interleave_n; -- Coherent FS only + char s_fname[6]; + char s_fpack[6]; + then they differ considerably: + Xenix FS + char s_clean; + char s_fill[371]; + long s_magic; + long s_type; + SystemV FS + long s_fill[12 or 14]; + long s_state; + long s_magic; + long s_type; + Coherent FS + unsigned long s_unique; + Note that Coherent FS has no magic. + +* Inode layout: + - Minix FS + unsigned short i_mode; + unsigned short i_uid; + unsigned long i_size; + unsigned long i_time; + unsigned char i_gid; + unsigned char i_nlinks; + unsigned short i_zone[7+1+1]; + - Xenix FS, SystemV FS, Coherent FS + unsigned short i_mode; + unsigned short i_nlink; + unsigned short i_uid; + unsigned short i_gid; + unsigned long i_size; + unsigned char i_zone[3*(10+1+1+1)]; + unsigned long i_atime; + unsigned long i_mtime; + unsigned long i_ctime; + +* Regular file data blocks are organized as + - Minix FS + 7 direct blocks + 1 indirect block (pointers to blocks) + 1 double-indirect block (pointer to pointers to blocks) + - Xenix FS, SystemV FS, Coherent FS + 10 direct blocks + 1 indirect block (pointers to blocks) + 1 double-indirect block (pointer to pointers to blocks) + 1 triple-indirect block (pointer to pointers to pointers to blocks) + +* Inode size, inodes per block + - Minix FS 32 32 + - Xenix FS 64 16 + - SystemV FS 64 16 + - Coherent FS 64 8 + +* Directory entry on disk + - Minix FS + unsigned short inode; + char name[14/30]; + - Xenix FS, SystemV FS, Coherent FS + unsigned short inode; + char name[14]; + +* Dir entry size, dir entries per block + - Minix FS 16/32 64/32 + - Xenix FS 16 64 + - SystemV FS 16 64 + - Coherent FS 16 32 + +* How to implement symbolic links such that the host fsck doesn't scream: + - Minix FS normal + - Xenix FS kludge: as regular files with chmod 1000 + - SystemV FS ?? + - Coherent FS kludge: as regular files with chmod 1000 -Bruno Haible - +Notation: We often speak of a "block" but mean a zone (the allocation unit) +and not the disk driver's notion of "block". diff --git a/trunk/Documentation/i386/boot.txt b/trunk/Documentation/i386/boot.txt index c51314b1a463..9575de300a61 100644 --- a/trunk/Documentation/i386/boot.txt +++ b/trunk/Documentation/i386/boot.txt @@ -2,7 +2,7 @@ ---------------------------- H. Peter Anvin - Last update 2005-09-02 + Last update 2006-11-17 On the i386 platform, the Linux kernel uses a rather complicated boot convention. This has evolved partially due to historical aspects, as @@ -35,6 +35,8 @@ Protocol 2.03: (Kernel 2.4.18-pre1) Explicitly makes the highest possible initrd address available to the bootloader. Protocol 2.04: (Kernel 2.6.14) Extend the syssize field to four bytes. +Protocol 2.05: (Kernel 2.6.20) Make protected mode kernel relocatable. + Introduce relocatable_kernel and kernel_alignment fields. **** MEMORY LAYOUT @@ -129,6 +131,8 @@ Offset Proto Name Meaning 0226/2 N/A pad1 Unused 0228/4 2.02+ cmd_line_ptr 32-bit pointer to the kernel command line 022C/4 2.03+ initrd_addr_max Highest legal initrd address +0230/4 2.05+ kernel_alignment Physical addr alignment required for kernel +0234/1 2.05+ relocatable_kernel Whether kernel is relocatable or not (1) For backwards compatibility, if the setup_sects field contains 0, the real value is 4. diff --git a/trunk/Documentation/ioctl-number.txt b/trunk/Documentation/ioctl-number.txt index edc04d74ae23..5a8bd5bd88ef 100644 --- a/trunk/Documentation/ioctl-number.txt +++ b/trunk/Documentation/ioctl-number.txt @@ -191,3 +191,5 @@ Code Seq# Include File Comments 0xF3 00-3F video/sisfb.h sisfb (in development) +0xF4 00-1F video/mbxfb.h mbxfb + diff --git a/trunk/Documentation/kernel-parameters.txt b/trunk/Documentation/kernel-parameters.txt index 15e4fed127f6..d8323b8893c3 100644 --- a/trunk/Documentation/kernel-parameters.txt +++ b/trunk/Documentation/kernel-parameters.txt @@ -548,6 +548,13 @@ and is between 256 and 4096 characters. It is defined in the file eurwdt= [HW,WDT] Eurotech CPU-1220/1410 onboard watchdog. Format: [,] + failslab= + fail_page_alloc= + fail_make_request=[KNL] + General fault injection mechanism. + Format: ,,, + See also /Documentation/fault-injection/. + fd_mcs= [HW,SCSI] See header of drivers/scsi/fd_mcs.c. @@ -599,8 +606,6 @@ and is between 256 and 4096 characters. It is defined in the file hugepages= [HW,IA-32,IA-64] Maximal number of HugeTLB pages. - noirqbalance [IA-32,SMP,KNL] Disable kernel irq balancing - i8042.direct [HW] Put keyboard port into non-translated mode i8042.dumbkbd [HW] Pretend that controller can only read data from keyboard and cannot control its state @@ -650,6 +655,10 @@ and is between 256 and 4096 characters. It is defined in the file idle= [HW] Format: idle=poll or idle=halt + ignore_loglevel [KNL] + Ignore loglevel setting - this will print /all/ + kernel messages to the console. Useful for debugging. + ihash_entries= [KNL] Set number of hash buckets for inode cache. @@ -714,7 +723,12 @@ and is between 256 and 4096 characters. It is defined in the file Format: ,,, isolcpus= [KNL,SMP] Isolate CPUs from the general scheduler. - Format: ,..., + Format: + ,..., + or + - (must be a positive range in ascending order) + or a mixture + ,...,- This option can be used to specify one or more CPUs to isolate from the general SMP balancing and scheduling algorithms. The only way to move a process onto or off @@ -1012,6 +1026,10 @@ and is between 256 and 4096 characters. It is defined in the file emulation library even if a 387 maths coprocessor is present. + noaliencache [MM, NUMA] Disables the allcoation of alien caches in + the slab allocator. Saves per-node memory, but will + impact performance on real NUMA hardware. + noalign [KNL,ARM] noapic [SMP,APIC] Tells the kernel to not make use of any @@ -1052,9 +1070,14 @@ and is between 256 and 4096 characters. It is defined in the file in certain environments such as networked servers or real-time systems. + noirqbalance [IA-32,SMP,KNL] Disable kernel irq balancing + noirqdebug [IA-32] Disables the code which attempts to detect and disable unhandled interrupt sources. + no_timer_check [IA-32,X86_64,APIC] Disables the code which tests for + broken timer IRQ sources. + noisapnp [ISAPNP] Disables ISA PnP code. noinitrd [RAM] Tells the kernel not to load any configured @@ -1285,6 +1308,7 @@ and is between 256 and 4096 characters. It is defined in the file Param: "schedule" - profile schedule points. Param: - step/bucket size as a power of 2 for statistical time based profiling. + Param: "sleep" - profile D-state sleeping (millisecs) processor.max_cstate= [HW,ACPI] Limit processor to maximum C-state @@ -1366,6 +1390,12 @@ and is between 256 and 4096 characters. It is defined in the file resume= [SWSUSP] Specify the partition device for software suspend + resume_offset= [SWSUSP] + Specify the offset from the beginning of the partition + given by "resume=" at which the swap header is located, + in units (needed only for swap files). + See Documentation/power/swsusp-and-swap-files.txt + rhash_entries= [KNL,NET] Set number of hash buckets for route cache @@ -1416,6 +1446,11 @@ and is between 256 and 4096 characters. It is defined in the file scsi_logging= [SCSI] + scsi_mod.scan= [SCSI] sync (default) scans SCSI busses as they are + discovered. async scans them in kernel threads, + allowing boot to proceed. none ignores them, expecting + user space to do the scan. + selinux [SELINUX] Disable or enable SELinux at boot time. Format: { "0" | "1" } See security/selinux/Kconfig help text. @@ -1727,6 +1762,9 @@ and is between 256 and 4096 characters. It is defined in the file norandmaps Don't use address space randomization Equivalent to echo 0 > /proc/sys/kernel/randomize_va_space + unwind_debug=N N > 0 will enable dwarf2 unwinder debugging + This is useful to get more information why + you got a "dwarf2 unwinder stuck" ______________________________________________________________________ diff --git a/trunk/Documentation/networking/00-INDEX b/trunk/Documentation/networking/00-INDEX index b1181ce232d9..e06b6e3c1db5 100644 --- a/trunk/Documentation/networking/00-INDEX +++ b/trunk/Documentation/networking/00-INDEX @@ -58,6 +58,8 @@ fore200e.txt - FORE Systems PCA-200E/SBA-200E ATM NIC driver info. framerelay.txt - info on using Frame Relay/Data Link Connection Identifier (DLCI). +generic_netlink.txt + - info on Generic Netlink ip-sysctl.txt - /proc/sys/net/ipv4/* variables ip_dynaddr.txt diff --git a/trunk/Documentation/networking/generic_netlink.txt b/trunk/Documentation/networking/generic_netlink.txt new file mode 100644 index 000000000000..d4f8b8b9b53c --- /dev/null +++ b/trunk/Documentation/networking/generic_netlink.txt @@ -0,0 +1,3 @@ +A wiki document on how to use Generic Netlink can be found here: + + * http://linux-net.osdl.org/index.php/Generic_Netlink_HOWTO diff --git a/trunk/Documentation/power/s2ram.txt b/trunk/Documentation/power/s2ram.txt new file mode 100644 index 000000000000..b05f512130ea --- /dev/null +++ b/trunk/Documentation/power/s2ram.txt @@ -0,0 +1,56 @@ + How to get s2ram working + ~~~~~~~~~~~~~~~~~~~~~~~~ + 2006 Linus Torvalds + 2006 Pavel Machek + +1) Check suspend.sf.net, program s2ram there has long whitelist of + "known ok" machines, along with tricks to use on each one. + +2) If that does not help, try reading tricks.txt and + video.txt. Perhaps problem is as simple as broken module, and + simple module unload can fix it. + +3) You can use Linus' TRACE_RESUME infrastructure, described below. + + Using TRACE_RESUME + ~~~~~~~~~~~~~~~~~~ + +I've been working at making the machines I have able to STR, and almost +always it's a driver that is buggy. Thank God for the suspend/resume +debugging - the thing that Chuck tried to disable. That's often the _only_ +way to debug these things, and it's actually pretty powerful (but +time-consuming - having to insert TRACE_RESUME() markers into the device +driver that doesn't resume and recompile and reboot). + +Anyway, the way to debug this for people who are interested (have a +machine that doesn't boot) is: + + - enable PM_DEBUG, and PM_TRACE + + - use a script like this: + + #!/bin/sh + sync + echo 1 > /sys/power/pm_trace + echo mem > /sys/power/state + + to suspend + + - if it doesn't come back up (which is usually the problem), reboot by + holding the power button down, and look at the dmesg output for things + like + + Magic number: 4:156:725 + hash matches drivers/base/power/resume.c:28 + hash matches device 0000:01:00.0 + + which means that the last trace event was just before trying to resume + device 0000:01:00.0. Then figure out what driver is controlling that + device (lspci and /sys/devices/pci* is your friend), and see if you can + fix it, disable it, or trace into its resume function. + +For example, the above happens to be the VGA device on my EVO, which I +used to run with "radeonfb" (it's an ATI Radeon mobility). It turns out +that "radeonfb" simply cannot resume that device - it tries to set the +PLL's, and it just _hangs_. Using the regular VGA console and letting X +resume it instead works fine. diff --git a/trunk/Documentation/power/swsusp-and-swap-files.txt b/trunk/Documentation/power/swsusp-and-swap-files.txt new file mode 100644 index 000000000000..06f911a5f885 --- /dev/null +++ b/trunk/Documentation/power/swsusp-and-swap-files.txt @@ -0,0 +1,60 @@ +Using swap files with software suspend (swsusp) + (C) 2006 Rafael J. Wysocki + +The Linux kernel handles swap files almost in the same way as it handles swap +partitions and there are only two differences between these two types of swap +areas: +(1) swap files need not be contiguous, +(2) the header of a swap file is not in the first block of the partition that +holds it. From the swsusp's point of view (1) is not a problem, because it is +already taken care of by the swap-handling code, but (2) has to be taken into +consideration. + +In principle the location of a swap file's header may be determined with the +help of appropriate filesystem driver. Unfortunately, however, it requires the +filesystem holding the swap file to be mounted, and if this filesystem is +journaled, it cannot be mounted during resume from disk. For this reason to +identify a swap file swsusp uses the name of the partition that holds the file +and the offset from the beginning of the partition at which the swap file's +header is located. For convenience, this offset is expressed in +units. + +In order to use a swap file with swsusp, you need to: + +1) Create the swap file and make it active, eg. + +# dd if=/dev/zero of= bs=1024 count= +# mkswap +# swapon + +2) Use an application that will bmap the swap file with the help of the +FIBMAP ioctl and determine the location of the file's swap header, as the +offset, in units, from the beginning of the partition which +holds the swap file. + +3) Add the following parameters to the kernel command line: + +resume= resume_offset= + +where is the partition on which the swap file is located +and is the offset of the swap header determined by the +application in 2) (of course, this step may be carried out automatically +by the same application that determies the swap file's header offset using the +FIBMAP ioctl) + +OR + +Use a userland suspend application that will set the partition and offset +with the help of the SNAPSHOT_SET_SWAP_AREA ioctl described in +Documentation/power/userland-swsusp.txt (this is the only method to suspend +to a swap file allowing the resume to be initiated from an initrd or initramfs +image). + +Now, swsusp will use the swap file in the same way in which it would use a swap +partition. In particular, the swap file has to be active (ie. be present in +/proc/swaps) so that it can be used for suspending. + +Note that if the swap file used for suspending is deleted and recreated, +the location of its header need not be the same as before. Thus every time +this happens the value of the "resume_offset=" kernel command line parameter +has to be updated. diff --git a/trunk/Documentation/power/swsusp.txt b/trunk/Documentation/power/swsusp.txt index e635e6f1e316..0761ff6c57ed 100644 --- a/trunk/Documentation/power/swsusp.txt +++ b/trunk/Documentation/power/swsusp.txt @@ -297,20 +297,12 @@ system is shut down or suspended. Additionally use the encrypted suspend image to prevent sensitive data from being stolen after resume. -Q: Why can't we suspend to a swap file? +Q: Can I suspend to a swap file? -A: Because accessing swap file needs the filesystem mounted, and -filesystem might do something wrong (like replaying the journal) -during mount. - -There are few ways to get that fixed: - -1) Probably could be solved by modifying every filesystem to support -some kind of "really read-only!" option. Patches welcome. - -2) suspend2 gets around that by storing absolute positions in on-disk -image (and blocksize), with resume parameter pointing directly to -suspend header. +A: Generally, yes, you can. However, it requires you to use the "resume=" and +"resume_offset=" kernel command line parameters, so the resume from a swap file +cannot be initiated from an initrd or initramfs image. See +swsusp-and-swap-files.txt for details. Q: Is there a maximum system RAM size that is supported by swsusp? diff --git a/trunk/Documentation/power/userland-swsusp.txt b/trunk/Documentation/power/userland-swsusp.txt index 64755e9285db..000556c932e9 100644 --- a/trunk/Documentation/power/userland-swsusp.txt +++ b/trunk/Documentation/power/userland-swsusp.txt @@ -9,9 +9,8 @@ done it already. Now, to use the userland interface for software suspend you need special utilities that will read/write the system memory snapshot from/to the kernel. Such utilities are available, for example, from -. You may want to have -a look at them if you are going to develop your own suspend/resume -utilities. +. You may want to have a look at them if you +are going to develop your own suspend/resume utilities. The interface consists of a character device providing the open(), release(), read(), and write() operations as well as several ioctl() @@ -21,9 +20,9 @@ be read from /sys/class/misc/snapshot/dev. The device can be open either for reading or for writing. If open for reading, it is considered to be in the suspend mode. Otherwise it is -assumed to be in the resume mode. The device cannot be open for reading -and writing. It is also impossible to have the device open more than once -at a time. +assumed to be in the resume mode. The device cannot be open for simultaneous +reading and writing. It is also impossible to have the device open more than +once at a time. The ioctl() commands recognized by the device are: @@ -69,9 +68,46 @@ SNAPSHOT_FREE_SWAP_PAGES - free all swap pages allocated with SNAPSHOT_SET_SWAP_FILE - set the resume partition (the last ioctl() argument should specify the device's major and minor numbers in the old two-byte format, as returned by the stat() function in the .st_rdev - member of the stat structure); it is recommended to always use this - call, because the code to set the resume partition could be removed from - future kernels + member of the stat structure) + +SNAPSHOT_SET_SWAP_AREA - set the resume partition and the offset (in + units) from the beginning of the partition at which the swap header is + located (the last ioctl() argument should point to a struct + resume_swap_area, as defined in kernel/power/power.h, containing the + resume device specification, as for the SNAPSHOT_SET_SWAP_FILE ioctl(), + and the offset); for swap partitions the offset is always 0, but it is + different to zero for swap files (please see + Documentation/swsusp-and-swap-files.txt for details). + The SNAPSHOT_SET_SWAP_AREA ioctl() is considered as a replacement for + SNAPSHOT_SET_SWAP_FILE which is regarded as obsolete. It is + recommended to always use this call, because the code to set the resume + partition may be removed from future kernels + +SNAPSHOT_S2RAM - suspend to RAM; using this call causes the kernel to + immediately enter the suspend-to-RAM state, so this call must always + be preceded by the SNAPSHOT_FREEZE call and it is also necessary + to use the SNAPSHOT_UNFREEZE call after the system wakes up. This call + is needed to implement the suspend-to-both mechanism in which the + suspend image is first created, as though the system had been suspended + to disk, and then the system is suspended to RAM (this makes it possible + to resume the system from RAM if there's enough battery power or restore + its state on the basis of the saved suspend image otherwise) + +SNAPSHOT_PMOPS - enable the usage of the pmops->prepare, pmops->enter and + pmops->finish methods (the in-kernel swsusp knows these as the "platform + method") which are needed on many machines to (among others) speed up + the resume by letting the BIOS skip some steps or to let the system + recognise the correct state of the hardware after the resume (in + particular on many machines this ensures that unplugged AC + adapters get correctly detected and that kacpid does not run wild after + the resume). The last ioctl() argument can take one of the three + values, defined in kernel/power/power.h: + PMOPS_PREPARE - make the kernel carry out the + pm_ops->prepare(PM_SUSPEND_DISK) operation + PMOPS_ENTER - make the kernel power off the system by calling + pm_ops->enter(PM_SUSPEND_DISK) + PMOPS_FINISH - make the kernel carry out the + pm_ops->finish(PM_SUSPEND_DISK) operation The device's read() operation can be used to transfer the snapshot image from the kernel. It has the following limitations: @@ -91,10 +127,12 @@ unfreeze user space processes frozen by SNAPSHOT_UNFREEZE if they are still frozen when the device is being closed). Currently it is assumed that the userland utilities reading/writing the -snapshot image from/to the kernel will use a swap partition, called the resume -partition, as storage space. However, this is not really required, as they -can use, for example, a special (blank) suspend partition or a file on a partition -that is unmounted before SNAPSHOT_ATOMIC_SNAPSHOT and mounted afterwards. +snapshot image from/to the kernel will use a swap parition, called the resume +partition, or a swap file as storage space (if a swap file is used, the resume +partition is the partition that holds this file). However, this is not really +required, as they can use, for example, a special (blank) suspend partition or +a file on a partition that is unmounted before SNAPSHOT_ATOMIC_SNAPSHOT and +mounted afterwards. These utilities SHOULD NOT make any assumptions regarding the ordering of data within the snapshot image, except for the image header that MAY be diff --git a/trunk/Documentation/scsi/scsi_mid_low_api.txt b/trunk/Documentation/scsi/scsi_mid_low_api.txt index 75a535a975c3..6f70f2b9327e 100644 --- a/trunk/Documentation/scsi/scsi_mid_low_api.txt +++ b/trunk/Documentation/scsi/scsi_mid_low_api.txt @@ -375,7 +375,6 @@ Summary: scsi_add_device - creates new scsi device (lu) instance scsi_add_host - perform sysfs registration and set up transport class scsi_adjust_queue_depth - change the queue depth on a SCSI device - scsi_assign_lock - replace default host_lock with given lock scsi_bios_ptable - return copy of block device's partition table scsi_block_requests - prevent further commands being queued to given host scsi_deactivate_tcq - turn off tag command queueing @@ -488,20 +487,6 @@ void scsi_adjust_queue_depth(struct scsi_device * sdev, int tagged, int tags) -/** - * scsi_assign_lock - replace default host_lock with given lock - * @shost: a pointer to a scsi host instance - * @lock: pointer to lock to replace host_lock for this host - * - * Returns nothing - * - * Might block: no - * - * Defined in: include/scsi/scsi_host.h . - **/ -void scsi_assign_lock(struct Scsi_Host *shost, spinlock_t *lock) - - /** * scsi_bios_ptable - return copy of block device's partition table * @dev: pointer to block device @@ -1366,17 +1351,11 @@ Locks Each struct Scsi_Host instance has a spin_lock called struct Scsi_Host::default_lock which is initialized in scsi_host_alloc() [found in hosts.c]. Within the same function the struct Scsi_Host::host_lock pointer -is initialized to point at default_lock with the scsi_assign_lock() function. -Thereafter lock and unlock operations performed by the mid level use the -struct Scsi_Host::host_lock pointer. - -LLDs can override the use of struct Scsi_Host::default_lock by -using scsi_assign_lock(). The earliest opportunity to do this would -be in the detect() function after it has invoked scsi_register(). It -could be replaced by a coarser grain lock (e.g. per driver) or a -lock of equal granularity (i.e. per host). Using finer grain locks -(e.g. per SCSI device) may be possible by juggling locks in -queuecommand(). +is initialized to point at default_lock. Thereafter lock and unlock +operations performed by the mid level use the struct Scsi_Host::host_lock +pointer. Previously drivers could override the host_lock pointer but +this is not allowed anymore. + Autosense ========= diff --git a/trunk/Documentation/stable_api_nonsense.txt b/trunk/Documentation/stable_api_nonsense.txt index f39c9d714db3..a2afca3b2bab 100644 --- a/trunk/Documentation/stable_api_nonsense.txt +++ b/trunk/Documentation/stable_api_nonsense.txt @@ -62,9 +62,6 @@ consider the following facts about the Linux kernel: - different structures can contain different fields - Some functions may not be implemented at all, (i.e. some locks compile away to nothing for non-SMP builds.) - - Parameter passing of variables from function to function can be - done in different ways (the CONFIG_REGPARM option controls - this.) - Memory within the kernel can be aligned in different ways, depending on the build options. - Linux runs on a wide range of different processor architectures. diff --git a/trunk/Documentation/sysctl/kernel.txt b/trunk/Documentation/sysctl/kernel.txt index 0bc7f1e3c9e6..5922e84d9133 100644 --- a/trunk/Documentation/sysctl/kernel.txt +++ b/trunk/Documentation/sysctl/kernel.txt @@ -27,6 +27,7 @@ show up in /proc/sys/kernel: - hotplug - java-appletviewer [ binfmt_java, obsolete ] - java-interpreter [ binfmt_java, obsolete ] +- kstack_depth_to_print [ X86 only ] - l2cr [ PPC only ] - modprobe ==> Documentation/kmod.txt - msgmax @@ -170,6 +171,13 @@ This flag controls the L2 cache of G3 processor boards. If ============================================================== +kstack_depth_to_print: (X86 only) + +Controls the number of words to print when dumping the raw +kernel stack. + +============================================================== + osrelease, ostype & version: # cat osrelease diff --git a/trunk/Documentation/x86_64/boot-options.txt b/trunk/Documentation/x86_64/boot-options.txt index f3c57f43ba64..dbdcaf68e3ea 100644 --- a/trunk/Documentation/x86_64/boot-options.txt +++ b/trunk/Documentation/x86_64/boot-options.txt @@ -52,10 +52,6 @@ APICs apicmaintimer. Useful when your PIT timer is totally broken. - disable_8254_timer / enable_8254_timer - Enable interrupt 0 timer routing over the 8254 in addition to over - the IO-APIC. The kernel tries to set a sensible default. - Early Console syntax: earlyprintk=vga @@ -183,7 +179,7 @@ PCI IOMMU iommu=[size][,noagp][,off][,force][,noforce][,leak][,memaper[=order]][,merge] - [,forcesac][,fullflush][,nomerge][,noaperture] + [,forcesac][,fullflush][,nomerge][,noaperture][,calgary] size set size of iommu (in bytes) noagp don't initialize the AGP driver and use full aperture. off don't use the IOMMU @@ -204,6 +200,7 @@ IOMMU buffering. nodac Forbid DMA >4GB panic Always panic when IOMMU overflows + calgary Use the Calgary IOMMU if it is available swiotlb=pages[,force] diff --git a/trunk/MAINTAINERS b/trunk/MAINTAINERS index 5dff26814a06..dbf449ba240c 100644 --- a/trunk/MAINTAINERS +++ b/trunk/MAINTAINERS @@ -348,6 +348,13 @@ P: Ian Molton M: spyro@f2s.com S: Maintained +ARM/ATMEL AT91RM9200 ARM ARCHITECTURE +P: Andrew Victor +M: andrew@sanpeople.com +L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) +W: http://maxim.org.za/at91_26.html +S: Maintained + ARM/CORGI MACHINE SUPPORT P: Richard Purdie M: rpurdie@rpsys.net @@ -677,7 +684,7 @@ S: Supported CIRRUS LOGIC GENERIC FBDEV DRIVER P: Jeff Garzik M: jgarzik@pobox.com -L: linux-fbdev-devel@lists.sourceforge.net +L: linux-fbdev-devel@lists.sourceforge.net (subscribers-only) S: Odd Fixes CIRRUS LOGIC CS4280/CS461x SOUNDDRIVER @@ -784,7 +791,7 @@ S: Maintained CYBLAFB FRAMEBUFFER DRIVER P: Knut Petersen M: Knut_Petersen@t-online.de -L: linux-fbdev-devel@lists.sourceforge.net +L: linux-fbdev-devel@lists.sourceforge.net (subscribers-only) S: Maintained CYCLADES 2X SYNC CARD DRIVER @@ -1091,13 +1098,19 @@ M: miku@iki.fi S: Maintained EXT2 FILE SYSTEM -L: ext2-devel@lists.sourceforge.net +L: linux-ext4@vger.kernel.org S: Maintained EXT3 FILE SYSTEM P: Stephen Tweedie, Andrew Morton M: sct@redhat.com, akpm@osdl.org, adilger@clusterfs.com -L: ext2-devel@lists.sourceforge.net +L: linux-ext4@vger.kernel.org +S: Maintained + +EXT4 FILE SYSTEM +P: Stephen Tweedie, Andrew Morton +M: sct@redhat.com, akpm@osdl.org, adilger@clusterfs.com +L: linux-ext4@vger.kernel.org S: Maintained F71805F HARDWARE MONITORING DRIVER @@ -1115,7 +1128,7 @@ S: Supported FRAMEBUFFER LAYER P: Antonino Daplas M: adaplas@pol.net -L: linux-fbdev-devel@lists.sourceforge.net +L: linux-fbdev-devel@lists.sourceforge.net (subscribers-only) W: http://linux-fbdev.sourceforge.net/ S: Maintained @@ -1214,7 +1227,8 @@ HARDWARE MONITORING P: Jean Delvare M: khali@linux-fr.org L: lm-sensors@lm-sensors.org -W: http://www.lm-sensors.nu/ +W: http://www.lm-sensors.org/ +T: quilt http://khali.linux-fr.org/devel/linux-2.6/jdelvare-hwmon/ S: Maintained HARDWARE RANDOM NUMBER GENERATOR CORE @@ -1340,8 +1354,7 @@ I2C SUBSYSTEM P: Jean Delvare M: khali@linux-fr.org L: i2c@lm-sensors.org -W: http://www.lm-sensors.nu/ -T: quilt kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/ +T: quilt http://khali.linux-fr.org/devel/linux-2.6/jdelvare-i2c/ S: Maintained I2O @@ -1466,7 +1479,7 @@ S: Maintained IMS TWINTURBO FRAMEBUFFER DRIVER P: Paul Mundt M: lethal@chaoticdreams.org -L: linux-fbdev-devel@lists.sourceforge.net +L: linux-fbdev-devel@lists.sourceforge.net (subscribers-only) S: Maintained INFINIBAND SUBSYSTEM @@ -1499,13 +1512,13 @@ S: Maintained INTEL FRAMEBUFFER DRIVER (excluding 810 and 815) P: Sylvain Meyer M: sylvain.meyer@worldonline.fr -L: linux-fbdev-devel@lists.sourceforge.net +L: linux-fbdev-devel@lists.sourceforge.net (subscribers-only) S: Maintained INTEL 810/815 FRAMEBUFFER DRIVER P: Antonino Daplas M: adaplas@pol.net -L: linux-fbdev-devel@lists.sourceforge.net +L: linux-fbdev-devel@lists.sourceforge.net (subscribers-only) S: Maintained INTEL APIC/IOAPIC, LOWLEVEL X86 SMP SUPPORT @@ -1673,7 +1686,7 @@ S: Supported JOURNALLING LAYER FOR BLOCK DEVICES (JBD) P: Stephen Tweedie, Andrew Morton M: sct@redhat.com, akpm@osdl.org -L: ext2-devel@lists.sourceforge.net +L: linux-ext4@vger.kernel.org S: Maintained K8TEMP HARDWARE MONITORING DRIVER @@ -1951,7 +1964,7 @@ S: Odd Fixes for 2.4; Maintained for 2.6. MATROX FRAMEBUFFER DRIVER P: Petr Vandrovec M: vandrove@vc.cvut.cz -L: linux-fbdev-devel@lists.sourceforge.net +L: linux-fbdev-devel@lists.sourceforge.net (subscribers-only) S: Maintained MEGARAID SCSI DRIVERS @@ -2012,6 +2025,12 @@ M: rubini@ipvvis.unipv.it L: linux-kernel@vger.kernel.org S: Maintained +MOXA SMARTIO/INDUSTIO SERIAL CARD (MXSER 2.0) +P: Jiri Slaby +M: jirislaby@gmail.com +L: linux-kernel@vger.kernel.org +S: Maintained + MSI LAPTOP SUPPORT P: Lennart Poettering M: mzxreary@0pointer.de @@ -2037,6 +2056,12 @@ P: Andrew Veliath M: andrewtv@usa.net S: Maintained +MULTITECH MULTIPORT CARD (ISICOM) +P: Jiri Slaby +M: jirislaby@gmail.com +L: linux-kernel@vger.kernel.org +S: Maintained + NATSEMI ETHERNET DRIVER (DP8381x) P: Tim Hockin M: thockin@hockin.org @@ -2197,7 +2222,7 @@ S: Maintained NVIDIA (rivafb and nvidiafb) FRAMEBUFFER DRIVER P: Antonino Daplas M: adaplas@pol.net -L: linux-fbdev-devel@lists.sourceforge.net +L: linux-fbdev-devel@lists.sourceforge.net (subscribers-only) S: Maintained OPENCORES I2C BUS DRIVER @@ -2481,13 +2506,13 @@ S: Maintained RADEON FRAMEBUFFER DISPLAY DRIVER P: Benjamin Herrenschmidt M: benh@kernel.crashing.org -L: linux-fbdev-devel@lists.sourceforge.net +L: linux-fbdev-devel@lists.sourceforge.net (subscribers-only) S: Maintained RAGE128 FRAMEBUFFER DISPLAY DRIVER P: Paul Mackerras M: paulus@samba.org -L: linux-fbdev-devel@lists.sourceforge.net +L: linux-fbdev-devel@lists.sourceforge.net (subscribers-only) S: Maintained RAYLINK/WEBGEAR 802.11 WIRELESS LAN DRIVER @@ -2557,7 +2582,7 @@ S: Orphan S3 SAVAGE FRAMEBUFFER DRIVER P: Antonino Daplas M: adaplas@pol.net -L: linux-fbdev-devel@lists.sourceforge.net +L: linux-fbdev-devel@lists.sourceforge.net (subscribers-only) S: Maintained S390 @@ -2913,7 +2938,6 @@ S: Maintained SUN3/3X P: Sam Creasey M: sammy@sammy.net -L: sun3-list@redhat.com W: http://sammy.net/sun3/ S: Maintained @@ -3454,6 +3478,12 @@ W: http://oss.sgi.com/projects/xfs T: git git://oss.sgi.com:8090/xfs/xfs-2.6 S: Supported +XILINX UARTLITE SERIAL DRIVER +P: Peter Korsgaard +M: jacmet@sunsite.dk +L: linux-serial@vger.kernel.org +S: Maintained + X86 3-LEVEL PAGING (PAE) SUPPORT P: Ingo Molnar M: mingo@redhat.com diff --git a/trunk/README b/trunk/README index 3e264723b863..c05561523029 100644 --- a/trunk/README +++ b/trunk/README @@ -1,4 +1,4 @@ - Linux kernel release 2.6.xx + Linux kernel release 2.6.xx These are the release notes for Linux version 2.6. Read them carefully, as they tell you what this is all about, explain how to install the @@ -22,15 +22,17 @@ ON WHAT HARDWARE DOES IT RUN? Although originally developed first for 32-bit x86-based PCs (386 or higher), today Linux also runs on (at least) the Compaq Alpha AXP, Sun SPARC and - UltraSPARC, Motorola 68000, PowerPC, PowerPC64, ARM, Hitachi SuperH, + UltraSPARC, Motorola 68000, PowerPC, PowerPC64, ARM, Hitachi SuperH, Cell, IBM S/390, MIPS, HP PA-RISC, Intel IA-64, DEC VAX, AMD x86-64, AXIS CRIS, - and Renesas M32R architectures. + Cris, Xtensa, AVR32 and Renesas M32R architectures. Linux is easily portable to most general-purpose 32- or 64-bit architectures as long as they have a paged memory management unit (PMMU) and a port of the GNU C compiler (gcc) (part of The GNU Compiler Collection, GCC). Linux has also been ported to a number of architectures without a PMMU, although functionality is then obviously somewhat limited. + Linux has also been ported to itself. You can now run the kernel as a + userspace application - this is called UserMode Linux (UML). DOCUMENTATION: @@ -113,6 +115,7 @@ INSTALLING the kernel: version 2.6.12.2 and want to jump to 2.6.12.3, you must first reverse the 2.6.12.2 patch (that is, patch -R) _before_ applying the 2.6.12.3 patch. + You can read more on this in Documentation/applying-patches.txt - Make sure you have no stale .o files and dependencies lying around: @@ -161,6 +164,7 @@ CONFIGURING the kernel: only ask you for the answers to new questions. - Alternate configuration commands are: + "make config" Plain text interface. "make menuconfig" Text based color menus, radiolists & dialogs. "make xconfig" X windows (Qt) based configuration tool. "make gconfig" X windows (Gtk) based configuration tool. @@ -303,8 +307,9 @@ IF SOMETHING GOES WRONG: - If you compiled the kernel with CONFIG_KALLSYMS you can send the dump as is, otherwise you will have to use the "ksymoops" program to make - sense of the dump. This utility can be downloaded from - ftp://ftp..kernel.org/pub/linux/utils/kernel/ksymoops. + sense of the dump (but compiling with CONFIG_KALLSYMS is usually preferred). + This utility can be downloaded from + ftp://ftp..kernel.org/pub/linux/utils/kernel/ksymoops/ . Alternately you can do the dump lookup by hand: - In debugging dumps like the above, it helps enormously if you can @@ -336,7 +341,7 @@ IF SOMETHING GOES WRONG: If you for some reason cannot do the above (you have a pre-compiled kernel image or similar), telling me as much about your setup as - possible will help. + possible will help. Please read the REPORTING-BUGS document for details. - Alternately, you can use gdb on a running kernel. (read-only; i.e. you cannot change values or set break points.) To do this, first compile the diff --git a/trunk/REPORTING-BUGS b/trunk/REPORTING-BUGS index f9da827a0c18..ac02e42a2627 100644 --- a/trunk/REPORTING-BUGS +++ b/trunk/REPORTING-BUGS @@ -40,7 +40,9 @@ summary from [1.]>" for easy identification by the developers. [1.] One line summary of the problem: [2.] Full description of the problem/report: [3.] Keywords (i.e., modules, networking, kernel): -[4.] Kernel version (from /proc/version): +[4.] Kernel information +[4.1.] Kernel version (from /proc/version): +[4.2.] Kernel .config file: [5.] Most recent kernel version which did not have the bug: [6.] Output of Oops.. message (if applicable) with symbolic information resolved (see Documentation/oops-tracing.txt) diff --git a/trunk/arch/alpha/Kconfig b/trunk/arch/alpha/Kconfig index 7e55ea66c6d4..84caf50725b5 100644 --- a/trunk/arch/alpha/Kconfig +++ b/trunk/arch/alpha/Kconfig @@ -25,6 +25,14 @@ config RWSEM_XCHGADD_ALGORITHM bool default y +config ARCH_HAS_ILOG2_U32 + bool + default n + +config ARCH_HAS_ILOG2_U64 + bool + default n + config GENERIC_FIND_NEXT_BIT bool default y diff --git a/trunk/arch/alpha/kernel/osf_sys.c b/trunk/arch/alpha/kernel/osf_sys.c index ad6173651995..fb804043b320 100644 --- a/trunk/arch/alpha/kernel/osf_sys.c +++ b/trunk/arch/alpha/kernel/osf_sys.c @@ -277,7 +277,7 @@ osf_fstatfs(unsigned long fd, struct osf_statfs __user *buffer, unsigned long bu retval = -EBADF; file = fget(fd); if (file) { - retval = do_osf_statfs(file->f_dentry, buffer, bufsiz); + retval = do_osf_statfs(file->f_path.dentry, buffer, bufsiz); fput(file); } return retval; diff --git a/trunk/arch/alpha/kernel/pci.c b/trunk/arch/alpha/kernel/pci.c index ffb7d5423cc0..3c10b9a1ddf5 100644 --- a/trunk/arch/alpha/kernel/pci.c +++ b/trunk/arch/alpha/kernel/pci.c @@ -516,10 +516,11 @@ sys_pciconfig_iobase(long which, unsigned long bus, unsigned long dfn) if (bus == 0 && dfn == 0) { hose = pci_isa_hose; } else { - dev = pci_find_slot(bus, dfn); + dev = pci_get_bus_and_slot(bus, dfn); if (!dev) return -ENODEV; hose = dev->sysdata; + pci_dev_put(dev); } } diff --git a/trunk/arch/alpha/kernel/sys_miata.c b/trunk/arch/alpha/kernel/sys_miata.c index b8b817feb1ee..910b43cd63e8 100644 --- a/trunk/arch/alpha/kernel/sys_miata.c +++ b/trunk/arch/alpha/kernel/sys_miata.c @@ -183,11 +183,15 @@ miata_map_irq(struct pci_dev *dev, u8 slot, u8 pin) if((slot == 7) && (PCI_FUNC(dev->devfn) == 3)) { u8 irq=0; - - if(pci_read_config_byte(pci_find_slot(dev->bus->number, dev->devfn & ~(7)), 0x40,&irq)!=PCIBIOS_SUCCESSFUL) + struct pci_dev *pdev = pci_get_slot(dev->bus, dev->devfn & ~7); + if(pdev == NULL || pci_read_config_byte(pdev, 0x40,&irq) != PCIBIOS_SUCCESSFUL) { + pci_dev_put(pdev); return -1; - else + } + else { + pci_dev_put(pdev); return irq; + } } return COMMON_TABLE_LOOKUP; diff --git a/trunk/arch/alpha/kernel/sys_nautilus.c b/trunk/arch/alpha/kernel/sys_nautilus.c index 93744bab73fb..e7594a7cf585 100644 --- a/trunk/arch/alpha/kernel/sys_nautilus.c +++ b/trunk/arch/alpha/kernel/sys_nautilus.c @@ -200,7 +200,7 @@ nautilus_init_pci(void) bus = pci_scan_bus(0, alpha_mv.pci_ops, hose); hose->bus = bus; - irongate = pci_find_slot(0, 0); + irongate = pci_get_bus_and_slot(0, 0); bus->self = irongate; bus->resource[1] = &irongate_mem; diff --git a/trunk/arch/alpha/mm/fault.c b/trunk/arch/alpha/mm/fault.c index 8871529a34e2..8aa9db834c11 100644 --- a/trunk/arch/alpha/mm/fault.c +++ b/trunk/arch/alpha/mm/fault.c @@ -108,7 +108,7 @@ do_page_fault(unsigned long address, unsigned long mmcsr, /* If we're in an interrupt context, or have no user context, we must not take the fault. */ - if (!mm || in_interrupt()) + if (!mm || in_atomic()) goto no_context; #ifdef CONFIG_ALPHA_LARGE_VMALLOC diff --git a/trunk/arch/arm/Kconfig b/trunk/arch/arm/Kconfig index ce00c570459d..aa1d400d721a 100644 --- a/trunk/arch/arm/Kconfig +++ b/trunk/arch/arm/Kconfig @@ -74,6 +74,14 @@ config RWSEM_GENERIC_SPINLOCK config RWSEM_XCHGADD_ALGORITHM bool +config ARCH_HAS_ILOG2_U32 + bool + default n + +config ARCH_HAS_ILOG2_U64 + bool + default n + config GENERIC_HWEIGHT bool default y @@ -223,6 +231,12 @@ config ARCH_IOP33X help Support for Intel's IOP33X (XScale) family of processors. +config ARCH_IOP13XX + bool "IOP13xx-based" + select PCI + help + Support for Intel's IOP13XX (XScale) family of processors. + config ARCH_IXP4XX bool "IXP4xx-based" depends on MMU @@ -331,6 +345,8 @@ source "arch/arm/mach-iop32x/Kconfig" source "arch/arm/mach-iop33x/Kconfig" +source "arch/arm/mach-iop13xx/Kconfig" + source "arch/arm/mach-ixp4xx/Kconfig" source "arch/arm/mach-ixp2000/Kconfig" @@ -374,6 +390,14 @@ config PLAT_IOP source arch/arm/mm/Kconfig +config IWMMXT + bool "Enable iWMMXt support" + depends CPU_XSCALE || CPU_XSC3 + default y if PXA27x + help + Enable support for iWMMXt context switching at run time if + running on a CPU that supports it. + # bool 'Use XScale PMU as timer source' CONFIG_XSCALE_PMU_TIMER config XSCALE_PMU bool @@ -583,7 +607,7 @@ config LEDS ARCH_LUBBOCK || MACH_MAINSTONE || ARCH_NETWINDER || \ ARCH_OMAP || ARCH_P720T || ARCH_PXA_IDP || \ ARCH_SA1100 || ARCH_SHARK || ARCH_VERSATILE || \ - ARCH_AT91RM9200 || MACH_TRIZEPS4 + ARCH_AT91 || MACH_TRIZEPS4 help If you say Y here, the LEDs on your machine will be used to provide useful information about your current system status. diff --git a/trunk/arch/arm/Kconfig.debug b/trunk/arch/arm/Kconfig.debug index d22f38b957db..40c5eb1f55c7 100644 --- a/trunk/arch/arm/Kconfig.debug +++ b/trunk/arch/arm/Kconfig.debug @@ -32,10 +32,6 @@ config DEBUG_USER 8 - SIGSEGV faults 16 - SIGBUS faults -config DEBUG_WAITQ - bool "Wait queue debugging" - depends on DEBUG_KERNEL - config DEBUG_ERRORS bool "Verbose kernel error messages" depends on DEBUG_KERNEL diff --git a/trunk/arch/arm/Makefile b/trunk/arch/arm/Makefile index 6f4f8bf36071..000f1100b553 100644 --- a/trunk/arch/arm/Makefile +++ b/trunk/arch/arm/Makefile @@ -15,6 +15,8 @@ CPPFLAGS_vmlinux.lds = -DTEXT_OFFSET=$(TEXT_OFFSET) OBJCOPYFLAGS :=-O binary -R .note -R .comment -S GZFLAGS :=-9 #CFLAGS +=-pipe +# Explicitly specifiy 32-bit ARM ISA since toolchain default can be -mthumb: +CFLAGS +=$(call cc-option,-marm,) # Do not use arch/arm/defconfig - it's always outdated. # Select a platform tht is kept up-to-date @@ -108,6 +110,7 @@ endif machine-$(CONFIG_ARCH_CLPS711X) := clps711x machine-$(CONFIG_ARCH_IOP32X) := iop32x machine-$(CONFIG_ARCH_IOP33X) := iop33x + machine-$(CONFIG_ARCH_IOP13XX) := iop13xx machine-$(CONFIG_ARCH_IXP4XX) := ixp4xx machine-$(CONFIG_ARCH_IXP2000) := ixp2000 machine-$(CONFIG_ARCH_IXP23XX) := ixp23xx diff --git a/trunk/arch/arm/common/gic.c b/trunk/arch/arm/common/gic.c index f3e020f2227f..09b9d1b6844c 100644 --- a/trunk/arch/arm/common/gic.c +++ b/trunk/arch/arm/common/gic.c @@ -160,7 +160,7 @@ void __init gic_dist_init(void __iomem *base) */ for (i = 29; i < max_irq; i++) { set_irq_chip(i, &gic_chip); - set_irq_handler(i, do_level_IRQ); + set_irq_handler(i, handle_level_irq); set_irq_flags(i, IRQF_VALID | IRQF_PROBE); } diff --git a/trunk/arch/arm/common/locomo.c b/trunk/arch/arm/common/locomo.c index 80a72c75214f..cfe6f4650bc9 100644 --- a/trunk/arch/arm/common/locomo.c +++ b/trunk/arch/arm/common/locomo.c @@ -163,11 +163,11 @@ static struct locomo_dev_info locomo_devices[] = { #define LOCOMO_IRQ_LT_START (IRQ_LOCOMO_LT) #define LOCOMO_IRQ_SPI_START (IRQ_LOCOMO_SPI_RFR) -static void locomo_handler(unsigned int irq, struct irqdesc *desc) +static void locomo_handler(unsigned int irq, struct irq_desc *desc) { int req, i; - struct irqdesc *d; - void __iomem *mapbase = get_irq_chipdata(irq); + struct irq_desc *d; + void __iomem *mapbase = get_irq_chip_data(irq); /* Acknowledge the parent IRQ */ desc->chip->ack(irq); @@ -194,7 +194,7 @@ static void locomo_ack_irq(unsigned int irq) static void locomo_mask_irq(unsigned int irq) { - void __iomem *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chip_data(irq); unsigned int r; r = locomo_readl(mapbase + LOCOMO_ICR); r &= ~(0x0010 << (irq - LOCOMO_IRQ_START)); @@ -203,7 +203,7 @@ static void locomo_mask_irq(unsigned int irq) static void locomo_unmask_irq(unsigned int irq) { - void __iomem *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chip_data(irq); unsigned int r; r = locomo_readl(mapbase + LOCOMO_ICR); r |= (0x0010 << (irq - LOCOMO_IRQ_START)); @@ -217,10 +217,10 @@ static struct irq_chip locomo_chip = { .unmask = locomo_unmask_irq, }; -static void locomo_key_handler(unsigned int irq, struct irqdesc *desc) +static void locomo_key_handler(unsigned int irq, struct irq_desc *desc) { - struct irqdesc *d; - void __iomem *mapbase = get_irq_chipdata(irq); + struct irq_desc *d; + void __iomem *mapbase = get_irq_chip_data(irq); if (locomo_readl(mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC) & 0x0001) { d = irq_desc + LOCOMO_IRQ_KEY_START; @@ -230,7 +230,7 @@ static void locomo_key_handler(unsigned int irq, struct irqdesc *desc) static void locomo_key_ack_irq(unsigned int irq) { - void __iomem *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chip_data(irq); unsigned int r; r = locomo_readl(mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC); r &= ~(0x0100 << (irq - LOCOMO_IRQ_KEY_START)); @@ -239,7 +239,7 @@ static void locomo_key_ack_irq(unsigned int irq) static void locomo_key_mask_irq(unsigned int irq) { - void __iomem *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chip_data(irq); unsigned int r; r = locomo_readl(mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC); r &= ~(0x0010 << (irq - LOCOMO_IRQ_KEY_START)); @@ -248,7 +248,7 @@ static void locomo_key_mask_irq(unsigned int irq) static void locomo_key_unmask_irq(unsigned int irq) { - void __iomem *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chip_data(irq); unsigned int r; r = locomo_readl(mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC); r |= (0x0010 << (irq - LOCOMO_IRQ_KEY_START)); @@ -262,11 +262,11 @@ static struct irq_chip locomo_key_chip = { .unmask = locomo_key_unmask_irq, }; -static void locomo_gpio_handler(unsigned int irq, struct irqdesc *desc) +static void locomo_gpio_handler(unsigned int irq, struct irq_desc *desc) { int req, i; - struct irqdesc *d; - void __iomem *mapbase = get_irq_chipdata(irq); + struct irq_desc *d; + void __iomem *mapbase = get_irq_chip_data(irq); req = locomo_readl(mapbase + LOCOMO_GIR) & locomo_readl(mapbase + LOCOMO_GPD) & @@ -285,7 +285,7 @@ static void locomo_gpio_handler(unsigned int irq, struct irqdesc *desc) static void locomo_gpio_ack_irq(unsigned int irq) { - void __iomem *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chip_data(irq); unsigned int r; r = locomo_readl(mapbase + LOCOMO_GWE); r |= (0x0001 << (irq - LOCOMO_IRQ_GPIO_START)); @@ -302,7 +302,7 @@ static void locomo_gpio_ack_irq(unsigned int irq) static void locomo_gpio_mask_irq(unsigned int irq) { - void __iomem *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chip_data(irq); unsigned int r; r = locomo_readl(mapbase + LOCOMO_GIE); r &= ~(0x0001 << (irq - LOCOMO_IRQ_GPIO_START)); @@ -311,7 +311,7 @@ static void locomo_gpio_mask_irq(unsigned int irq) static void locomo_gpio_unmask_irq(unsigned int irq) { - void __iomem *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chip_data(irq); unsigned int r; r = locomo_readl(mapbase + LOCOMO_GIE); r |= (0x0001 << (irq - LOCOMO_IRQ_GPIO_START)); @@ -325,10 +325,10 @@ static struct irq_chip locomo_gpio_chip = { .unmask = locomo_gpio_unmask_irq, }; -static void locomo_lt_handler(unsigned int irq, struct irqdesc *desc) +static void locomo_lt_handler(unsigned int irq, struct irq_desc *desc) { - struct irqdesc *d; - void __iomem *mapbase = get_irq_chipdata(irq); + struct irq_desc *d; + void __iomem *mapbase = get_irq_chip_data(irq); if (locomo_readl(mapbase + LOCOMO_LTINT) & 0x0001) { d = irq_desc + LOCOMO_IRQ_LT_START; @@ -338,7 +338,7 @@ static void locomo_lt_handler(unsigned int irq, struct irqdesc *desc) static void locomo_lt_ack_irq(unsigned int irq) { - void __iomem *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chip_data(irq); unsigned int r; r = locomo_readl(mapbase + LOCOMO_LTINT); r &= ~(0x0100 << (irq - LOCOMO_IRQ_LT_START)); @@ -347,7 +347,7 @@ static void locomo_lt_ack_irq(unsigned int irq) static void locomo_lt_mask_irq(unsigned int irq) { - void __iomem *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chip_data(irq); unsigned int r; r = locomo_readl(mapbase + LOCOMO_LTINT); r &= ~(0x0010 << (irq - LOCOMO_IRQ_LT_START)); @@ -356,7 +356,7 @@ static void locomo_lt_mask_irq(unsigned int irq) static void locomo_lt_unmask_irq(unsigned int irq) { - void __iomem *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chip_data(irq); unsigned int r; r = locomo_readl(mapbase + LOCOMO_LTINT); r |= (0x0010 << (irq - LOCOMO_IRQ_LT_START)); @@ -370,11 +370,11 @@ static struct irq_chip locomo_lt_chip = { .unmask = locomo_lt_unmask_irq, }; -static void locomo_spi_handler(unsigned int irq, struct irqdesc *desc) +static void locomo_spi_handler(unsigned int irq, struct irq_desc *desc) { int req, i; - struct irqdesc *d; - void __iomem *mapbase = get_irq_chipdata(irq); + struct irq_desc *d; + void __iomem *mapbase = get_irq_chip_data(irq); req = locomo_readl(mapbase + LOCOMO_SPI + LOCOMO_SPIIR) & 0x000F; if (req) { @@ -391,7 +391,7 @@ static void locomo_spi_handler(unsigned int irq, struct irqdesc *desc) static void locomo_spi_ack_irq(unsigned int irq) { - void __iomem *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chip_data(irq); unsigned int r; r = locomo_readl(mapbase + LOCOMO_SPI + LOCOMO_SPIWE); r |= (0x0001 << (irq - LOCOMO_IRQ_SPI_START)); @@ -408,7 +408,7 @@ static void locomo_spi_ack_irq(unsigned int irq) static void locomo_spi_mask_irq(unsigned int irq) { - void __iomem *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chip_data(irq); unsigned int r; r = locomo_readl(mapbase + LOCOMO_SPI + LOCOMO_SPIIE); r &= ~(0x0001 << (irq - LOCOMO_IRQ_SPI_START)); @@ -417,7 +417,7 @@ static void locomo_spi_mask_irq(unsigned int irq) static void locomo_spi_unmask_irq(unsigned int irq) { - void __iomem *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chip_data(irq); unsigned int r; r = locomo_readl(mapbase + LOCOMO_SPI + LOCOMO_SPIIE); r |= (0x0001 << (irq - LOCOMO_IRQ_SPI_START)); @@ -440,55 +440,55 @@ static void locomo_setup_irq(struct locomo *lchip) * Install handler for IRQ_LOCOMO_HW. */ set_irq_type(lchip->irq, IRQT_FALLING); - set_irq_chipdata(lchip->irq, irqbase); + set_irq_chip_data(lchip->irq, irqbase); set_irq_chained_handler(lchip->irq, locomo_handler); /* Install handlers for IRQ_LOCOMO_*_BASE */ set_irq_chip(IRQ_LOCOMO_KEY_BASE, &locomo_chip); - set_irq_chipdata(IRQ_LOCOMO_KEY_BASE, irqbase); + set_irq_chip_data(IRQ_LOCOMO_KEY_BASE, irqbase); set_irq_chained_handler(IRQ_LOCOMO_KEY_BASE, locomo_key_handler); set_irq_flags(IRQ_LOCOMO_KEY_BASE, IRQF_VALID | IRQF_PROBE); set_irq_chip(IRQ_LOCOMO_GPIO_BASE, &locomo_chip); - set_irq_chipdata(IRQ_LOCOMO_GPIO_BASE, irqbase); + set_irq_chip_data(IRQ_LOCOMO_GPIO_BASE, irqbase); set_irq_chained_handler(IRQ_LOCOMO_GPIO_BASE, locomo_gpio_handler); set_irq_flags(IRQ_LOCOMO_GPIO_BASE, IRQF_VALID | IRQF_PROBE); set_irq_chip(IRQ_LOCOMO_LT_BASE, &locomo_chip); - set_irq_chipdata(IRQ_LOCOMO_LT_BASE, irqbase); + set_irq_chip_data(IRQ_LOCOMO_LT_BASE, irqbase); set_irq_chained_handler(IRQ_LOCOMO_LT_BASE, locomo_lt_handler); set_irq_flags(IRQ_LOCOMO_LT_BASE, IRQF_VALID | IRQF_PROBE); set_irq_chip(IRQ_LOCOMO_SPI_BASE, &locomo_chip); - set_irq_chipdata(IRQ_LOCOMO_SPI_BASE, irqbase); + set_irq_chip_data(IRQ_LOCOMO_SPI_BASE, irqbase); set_irq_chained_handler(IRQ_LOCOMO_SPI_BASE, locomo_spi_handler); set_irq_flags(IRQ_LOCOMO_SPI_BASE, IRQF_VALID | IRQF_PROBE); /* install handlers for IRQ_LOCOMO_KEY_BASE generated interrupts */ set_irq_chip(LOCOMO_IRQ_KEY_START, &locomo_key_chip); - set_irq_chipdata(LOCOMO_IRQ_KEY_START, irqbase); - set_irq_handler(LOCOMO_IRQ_KEY_START, do_edge_IRQ); + set_irq_chip_data(LOCOMO_IRQ_KEY_START, irqbase); + set_irq_handler(LOCOMO_IRQ_KEY_START, handle_edge_irq); set_irq_flags(LOCOMO_IRQ_KEY_START, IRQF_VALID | IRQF_PROBE); /* install handlers for IRQ_LOCOMO_GPIO_BASE generated interrupts */ for (irq = LOCOMO_IRQ_GPIO_START; irq < LOCOMO_IRQ_GPIO_START + 16; irq++) { set_irq_chip(irq, &locomo_gpio_chip); - set_irq_chipdata(irq, irqbase); - set_irq_handler(irq, do_edge_IRQ); + set_irq_chip_data(irq, irqbase); + set_irq_handler(irq, handle_edge_irq); set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); } /* install handlers for IRQ_LOCOMO_LT_BASE generated interrupts */ set_irq_chip(LOCOMO_IRQ_LT_START, &locomo_lt_chip); - set_irq_chipdata(LOCOMO_IRQ_LT_START, irqbase); - set_irq_handler(LOCOMO_IRQ_LT_START, do_edge_IRQ); + set_irq_chip_data(LOCOMO_IRQ_LT_START, irqbase); + set_irq_handler(LOCOMO_IRQ_LT_START, handle_edge_irq); set_irq_flags(LOCOMO_IRQ_LT_START, IRQF_VALID | IRQF_PROBE); /* install handlers for IRQ_LOCOMO_SPI_BASE generated interrupts */ for (irq = LOCOMO_IRQ_SPI_START; irq < LOCOMO_IRQ_SPI_START + 3; irq++) { set_irq_chip(irq, &locomo_spi_chip); - set_irq_chipdata(irq, irqbase); - set_irq_handler(irq, do_edge_IRQ); + set_irq_chip_data(irq, irqbase); + set_irq_handler(irq, handle_edge_irq); set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); } } diff --git a/trunk/arch/arm/common/sa1111.c b/trunk/arch/arm/common/sa1111.c index d5f72010a6f3..fe3f05901a23 100644 --- a/trunk/arch/arm/common/sa1111.c +++ b/trunk/arch/arm/common/sa1111.c @@ -147,7 +147,7 @@ void __init sa1111_adjust_zones(int node, unsigned long *size, unsigned long *ho * will call us again if there are more interrupts to process. */ static void -sa1111_irq_handler(unsigned int irq, struct irqdesc *desc) +sa1111_irq_handler(unsigned int irq, struct irq_desc *desc) { unsigned int stat0, stat1, i; void __iomem *base = get_irq_data(irq); @@ -187,7 +187,7 @@ static void sa1111_ack_irq(unsigned int irq) static void sa1111_mask_lowirq(unsigned int irq) { - void __iomem *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chip_data(irq); unsigned long ie0; ie0 = sa1111_readl(mapbase + SA1111_INTEN0); @@ -197,7 +197,7 @@ static void sa1111_mask_lowirq(unsigned int irq) static void sa1111_unmask_lowirq(unsigned int irq) { - void __iomem *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chip_data(irq); unsigned long ie0; ie0 = sa1111_readl(mapbase + SA1111_INTEN0); @@ -215,7 +215,7 @@ static void sa1111_unmask_lowirq(unsigned int irq) static int sa1111_retrigger_lowirq(unsigned int irq) { unsigned int mask = SA1111_IRQMASK_LO(irq); - void __iomem *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chip_data(irq); unsigned long ip0; int i; @@ -236,7 +236,7 @@ static int sa1111_retrigger_lowirq(unsigned int irq) static int sa1111_type_lowirq(unsigned int irq, unsigned int flags) { unsigned int mask = SA1111_IRQMASK_LO(irq); - void __iomem *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chip_data(irq); unsigned long ip0; if (flags == IRQT_PROBE) @@ -259,7 +259,7 @@ static int sa1111_type_lowirq(unsigned int irq, unsigned int flags) static int sa1111_wake_lowirq(unsigned int irq, unsigned int on) { unsigned int mask = SA1111_IRQMASK_LO(irq); - void __iomem *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chip_data(irq); unsigned long we0; we0 = sa1111_readl(mapbase + SA1111_WAKEEN0); @@ -284,7 +284,7 @@ static struct irq_chip sa1111_low_chip = { static void sa1111_mask_highirq(unsigned int irq) { - void __iomem *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chip_data(irq); unsigned long ie1; ie1 = sa1111_readl(mapbase + SA1111_INTEN1); @@ -294,7 +294,7 @@ static void sa1111_mask_highirq(unsigned int irq) static void sa1111_unmask_highirq(unsigned int irq) { - void __iomem *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chip_data(irq); unsigned long ie1; ie1 = sa1111_readl(mapbase + SA1111_INTEN1); @@ -312,7 +312,7 @@ static void sa1111_unmask_highirq(unsigned int irq) static int sa1111_retrigger_highirq(unsigned int irq) { unsigned int mask = SA1111_IRQMASK_HI(irq); - void __iomem *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chip_data(irq); unsigned long ip1; int i; @@ -333,7 +333,7 @@ static int sa1111_retrigger_highirq(unsigned int irq) static int sa1111_type_highirq(unsigned int irq, unsigned int flags) { unsigned int mask = SA1111_IRQMASK_HI(irq); - void __iomem *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chip_data(irq); unsigned long ip1; if (flags == IRQT_PROBE) @@ -356,7 +356,7 @@ static int sa1111_type_highirq(unsigned int irq, unsigned int flags) static int sa1111_wake_highirq(unsigned int irq, unsigned int on) { unsigned int mask = SA1111_IRQMASK_HI(irq); - void __iomem *mapbase = get_irq_chipdata(irq); + void __iomem *mapbase = get_irq_chip_data(irq); unsigned long we1; we1 = sa1111_readl(mapbase + SA1111_WAKEEN1); @@ -410,15 +410,15 @@ static void sa1111_setup_irq(struct sa1111 *sachip) for (irq = IRQ_GPAIN0; irq <= SSPROR; irq++) { set_irq_chip(irq, &sa1111_low_chip); - set_irq_chipdata(irq, irqbase); - set_irq_handler(irq, do_edge_IRQ); + set_irq_chip_data(irq, irqbase); + set_irq_handler(irq, handle_edge_irq); set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); } for (irq = AUDXMTDMADONEA; irq <= IRQ_S1_BVD1_STSCHG; irq++) { set_irq_chip(irq, &sa1111_high_chip); - set_irq_chipdata(irq, irqbase); - set_irq_handler(irq, do_edge_IRQ); + set_irq_chip_data(irq, irqbase); + set_irq_handler(irq, handle_edge_irq); set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); } diff --git a/trunk/arch/arm/common/sharpsl_pm.c b/trunk/arch/arm/common/sharpsl_pm.c index 605dedf96790..b3599743093b 100644 --- a/trunk/arch/arm/common/sharpsl_pm.c +++ b/trunk/arch/arm/common/sharpsl_pm.c @@ -60,16 +60,16 @@ static int sharpsl_ac_check(void); static int sharpsl_fatal_check(void); static int sharpsl_average_value(int ad); static void sharpsl_average_clear(void); -static void sharpsl_charge_toggle(void *private_); -static void sharpsl_battery_thread(void *private_); +static void sharpsl_charge_toggle(struct work_struct *private_); +static void sharpsl_battery_thread(struct work_struct *private_); /* * Variables */ struct sharpsl_pm_status sharpsl_pm; -DECLARE_WORK(toggle_charger, sharpsl_charge_toggle, NULL); -DECLARE_WORK(sharpsl_bat, sharpsl_battery_thread, NULL); +DECLARE_DELAYED_WORK(toggle_charger, sharpsl_charge_toggle); +DECLARE_DELAYED_WORK(sharpsl_bat, sharpsl_battery_thread); DEFINE_LED_TRIGGER(sharpsl_charge_led_trigger); @@ -116,7 +116,7 @@ void sharpsl_battery_kick(void) EXPORT_SYMBOL(sharpsl_battery_kick); -static void sharpsl_battery_thread(void *private_) +static void sharpsl_battery_thread(struct work_struct *private_) { int voltage, percent, apm_status, i = 0; @@ -128,7 +128,7 @@ static void sharpsl_battery_thread(void *private_) /* Corgi cannot confirm when battery fully charged so periodically kick! */ if (!sharpsl_pm.machinfo->batfull_irq && (sharpsl_pm.charge_mode == CHRG_ON) && time_after(jiffies, sharpsl_pm.charge_start_time + SHARPSL_CHARGE_ON_TIME_INTERVAL)) - schedule_work(&toggle_charger); + schedule_delayed_work(&toggle_charger, 0); while(1) { voltage = sharpsl_pm.machinfo->read_devdata(SHARPSL_BATT_VOLT); @@ -212,7 +212,7 @@ static void sharpsl_charge_off(void) sharpsl_pm_led(SHARPSL_LED_OFF); sharpsl_pm.charge_mode = CHRG_OFF; - schedule_work(&sharpsl_bat); + schedule_delayed_work(&sharpsl_bat, 0); } static void sharpsl_charge_error(void) @@ -222,7 +222,7 @@ static void sharpsl_charge_error(void) sharpsl_pm.charge_mode = CHRG_ERROR; } -static void sharpsl_charge_toggle(void *private_) +static void sharpsl_charge_toggle(struct work_struct *private_) { dev_dbg(sharpsl_pm.dev, "Toogling Charger at time: %lx\n", jiffies); @@ -254,7 +254,7 @@ static void sharpsl_ac_timer(unsigned long data) else if (sharpsl_pm.charge_mode == CHRG_ON) sharpsl_charge_off(); - schedule_work(&sharpsl_bat); + schedule_delayed_work(&sharpsl_bat, 0); } @@ -279,10 +279,10 @@ static void sharpsl_chrg_full_timer(unsigned long data) sharpsl_charge_off(); } else if (sharpsl_pm.full_count < 2) { dev_dbg(sharpsl_pm.dev, "Charge Full: Count too low\n"); - schedule_work(&toggle_charger); + schedule_delayed_work(&toggle_charger, 0); } else if (time_after(jiffies, sharpsl_pm.charge_start_time + SHARPSL_CHARGE_FINISH_TIME)) { dev_dbg(sharpsl_pm.dev, "Charge Full: Interrupt generated too slowly - retry.\n"); - schedule_work(&toggle_charger); + schedule_delayed_work(&toggle_charger, 0); } else { sharpsl_charge_off(); sharpsl_pm.charge_mode = CHRG_DONE; diff --git a/trunk/arch/arm/common/vic.c b/trunk/arch/arm/common/vic.c index 43d278134521..c026fa2214a3 100644 --- a/trunk/arch/arm/common/vic.c +++ b/trunk/arch/arm/common/vic.c @@ -27,14 +27,14 @@ static void vic_mask_irq(unsigned int irq) { - void __iomem *base = get_irq_chipdata(irq); + void __iomem *base = get_irq_chip_data(irq); irq &= 31; writel(1 << irq, base + VIC_INT_ENABLE_CLEAR); } static void vic_unmask_irq(unsigned int irq) { - void __iomem *base = get_irq_chipdata(irq); + void __iomem *base = get_irq_chip_data(irq); irq &= 31; writel(1 << irq, base + VIC_INT_ENABLE); } @@ -88,10 +88,10 @@ void __init vic_init(void __iomem *base, unsigned int irq_start, unsigned int irq = irq_start + i; set_irq_chip(irq, &vic_chip); - set_irq_chipdata(irq, base); + set_irq_chip_data(irq, base); if (vic_sources & (1 << i)) { - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); } } diff --git a/trunk/arch/arm/configs/at91rm9200dk_defconfig b/trunk/arch/arm/configs/at91rm9200dk_defconfig index b43041476e02..e10d003566d6 100644 --- a/trunk/arch/arm/configs/at91rm9200dk_defconfig +++ b/trunk/arch/arm/configs/at91rm9200dk_defconfig @@ -357,9 +357,9 @@ CONFIG_MTD_CFI_UTIL=y # # CONFIG_MTD_COMPLEX_MAPPINGS is not set CONFIG_MTD_PHYSMAP=y -CONFIG_MTD_PHYSMAP_START=0x10000000 -CONFIG_MTD_PHYSMAP_LEN=0x200000 -CONFIG_MTD_PHYSMAP_BANKWIDTH=2 +CONFIG_MTD_PHYSMAP_START=0 +CONFIG_MTD_PHYSMAP_LEN=0 +CONFIG_MTD_PHYSMAP_BANKWIDTH=0 # CONFIG_MTD_ARM_INTEGRATOR is not set # CONFIG_MTD_IMPA7 is not set # CONFIG_MTD_PLATRAM is not set @@ -585,7 +585,9 @@ CONFIG_AT91RM9200_WATCHDOG=y # CONFIG_USBPCWATCHDOG is not set # CONFIG_NVRAM is not set # CONFIG_RTC is not set -CONFIG_AT91_RTC=y +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_AT91RM9200=y # CONFIG_DTLK is not set # CONFIG_R3964 is not set @@ -979,7 +981,6 @@ CONFIG_DEBUG_BUGVERBOSE=y CONFIG_FRAME_POINTER=y # CONFIG_RCU_TORTURE_TEST is not set CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_WAITQ is not set # CONFIG_DEBUG_ERRORS is not set CONFIG_DEBUG_LL=y # CONFIG_DEBUG_ICEDCC is not set diff --git a/trunk/arch/arm/configs/at91rm9200ek_defconfig b/trunk/arch/arm/configs/at91rm9200ek_defconfig index d96fc8386e2f..834dddb51314 100644 --- a/trunk/arch/arm/configs/at91rm9200ek_defconfig +++ b/trunk/arch/arm/configs/at91rm9200ek_defconfig @@ -348,9 +348,9 @@ CONFIG_MTD_CFI_UTIL=y # # CONFIG_MTD_COMPLEX_MAPPINGS is not set CONFIG_MTD_PHYSMAP=y -CONFIG_MTD_PHYSMAP_START=0x10000000 -CONFIG_MTD_PHYSMAP_LEN=0x800000 -CONFIG_MTD_PHYSMAP_BANKWIDTH=2 +CONFIG_MTD_PHYSMAP_START=0 +CONFIG_MTD_PHYSMAP_LEN=0 +CONFIG_MTD_PHYSMAP_BANKWIDTH=0 # CONFIG_MTD_ARM_INTEGRATOR is not set # CONFIG_MTD_IMPA7 is not set # CONFIG_MTD_PLATRAM is not set @@ -566,7 +566,9 @@ CONFIG_AT91RM9200_WATCHDOG=y # CONFIG_USBPCWATCHDOG is not set # CONFIG_NVRAM is not set # CONFIG_RTC is not set -CONFIG_AT91_RTC=y +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_AT91RM9200=y # CONFIG_DTLK is not set # CONFIG_R3964 is not set @@ -968,7 +970,6 @@ CONFIG_DEBUG_BUGVERBOSE=y CONFIG_FRAME_POINTER=y # CONFIG_RCU_TORTURE_TEST is not set CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_WAITQ is not set # CONFIG_DEBUG_ERRORS is not set CONFIG_DEBUG_LL=y # CONFIG_DEBUG_ICEDCC is not set diff --git a/trunk/arch/arm/configs/at91sam9260ek_defconfig b/trunk/arch/arm/configs/at91sam9260ek_defconfig new file mode 100644 index 000000000000..79049206dfa5 --- /dev/null +++ b/trunk/arch/arm/configs/at91sam9260ek_defconfig @@ -0,0 +1,950 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.19-rc6 +# Fri Nov 17 18:42:21 2006 +# +CONFIG_ARM=y +# CONFIG_GENERIC_TIME is not set +CONFIG_MMU=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_VECTORS_BASE=0xffff0000 +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +# CONFIG_SWAP is not set +CONFIG_SYSVIPC=y +# CONFIG_IPC_NS is not set +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_TASKSTATS is not set +# CONFIG_UTS_NS is not set +# CONFIG_AUDIT is not set +# CONFIG_IKCONFIG is not set +# CONFIG_RELAY is not set +CONFIG_INITRAMFS_SOURCE="" +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +# CONFIG_EMBEDDED is not set +CONFIG_UID16=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SHMEM=y +CONFIG_SLAB=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_RT_MUTEXES=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_KMOD=y + +# +# Block layer +# +CONFIG_BLOCK=y +# CONFIG_BLK_DEV_IO_TRACE is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +# CONFIG_IOSCHED_DEADLINE is not set +# CONFIG_IOSCHED_CFQ is not set +CONFIG_DEFAULT_AS=y +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="anticipatory" + +# +# System Type +# +# CONFIG_ARCH_AAEC2000 is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +CONFIG_ARCH_AT91=y +# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_CO285 is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_PNX4008 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_OMAP is not set + +# +# Atmel AT91 System-on-Chip +# +# CONFIG_ARCH_AT91RM9200 is not set +CONFIG_ARCH_AT91SAM9260=y +# CONFIG_ARCH_AT91SAM9261 is not set + +# +# AT91SAM9260 Board Type +# +CONFIG_MACH_AT91SAM9260EK=y + +# +# AT91 Board Options +# +# CONFIG_MTD_NAND_AT91_BUSWIDTH_16 is not set + +# +# AT91 Feature Selections +# +# CONFIG_AT91_PROGRAMMABLE_CLOCKS is not set + +# +# Processor Type +# +CONFIG_CPU_32=y +CONFIG_CPU_ARM926T=y +CONFIG_CPU_32v5=y +CONFIG_CPU_ABRT_EV5TJ=y +CONFIG_CPU_CACHE_VIVT=y +CONFIG_CPU_COPY_V4WB=y +CONFIG_CPU_TLB_V4WBI=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y + +# +# Processor Features +# +# CONFIG_ARM_THUMB is not set +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_WRITETHROUGH is not set +# CONFIG_CPU_CACHE_ROUND_ROBIN is not set + +# +# Bus support +# + +# +# PCCARD (PCMCIA/CardBus) support +# +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +# CONFIG_PREEMPT is not set +# CONFIG_NO_IDLE_HZ is not set +CONFIG_HZ=100 +# CONFIG_AEABI is not set +# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4096 +# CONFIG_RESOURCES_64BIT is not set +# CONFIG_LEDS is not set +CONFIG_ALIGNMENT_TRAP=y + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="mem=64M console=ttyS0,115200 initrd=0x21100000,3145728 root=/dev/ram0 rw" +# CONFIG_XIP_KERNEL is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +CONFIG_FPE_NWFPE=y +# CONFIG_FPE_NWFPE_XP is not set +# CONFIG_FPE_FASTFPE is not set +# CONFIG_VFP is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_AOUT is not set +# CONFIG_BINFMT_MISC is not set +# CONFIG_ARTHUR is not set + +# +# Power management options +# +# CONFIG_PM is not set +# CONFIG_APM is not set + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_IPV6 is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETFILTER is not set + +# +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set + +# +# TIPC Configuration (EXPERIMENTAL) +# +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_IEEE80211 is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_FW_LOADER is not set +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_SYS_HYPERVISOR is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +# CONFIG_CONNECTOR is not set + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_COW_COMMON is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_UB is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=8192 +CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 +CONFIG_BLK_DEV_INITRD=y +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=y +# CONFIG_SCSI_NETLINK is not set +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +# CONFIG_CHR_DEV_SG is not set +# CONFIG_CHR_DEV_SCH is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +CONFIG_SCSI_MULTI_LUN=y +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set + +# +# SCSI Transports +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set + +# +# SCSI low-level drivers +# +# CONFIG_ISCSI_TCP is not set +# CONFIG_SCSI_DEBUG is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# + +# +# I2O device support +# + +# +# Network device support +# +# CONFIG_NETDEVICES is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_ATMEL=y +CONFIG_SERIAL_ATMEL_CONSOLE=y +# CONFIG_SERIAL_ATMEL_TTYAT is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +CONFIG_WATCHDOG=y +CONFIG_WATCHDOG_NOWAYOUT=y + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set + +# +# USB-based Watchdog Cards +# +# CONFIG_USBPCWATCHDOG is not set +CONFIG_HW_RANDOM=y +# CONFIG_NVRAM is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# +# CONFIG_TCG_TPM is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + +# +# Hardware Monitoring support +# +# CONFIG_HWMON is not set +# CONFIG_HWMON_VID is not set + +# +# Misc devices +# +# CONFIG_TIFM_CORE is not set + +# +# LED devices +# +# CONFIG_NEW_LEDS is not set + +# +# LED drivers +# + +# +# LED Triggers +# + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set +# CONFIG_USB_DABUSB is not set + +# +# Graphics support +# +# CONFIG_FIRMWARE_EDID is not set +# CONFIG_FB is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +# CONFIG_USB_ARCH_HAS_EHCI is not set +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +# CONFIG_USB_BANDWIDTH is not set +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_OTG is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_ISP116X_HCD is not set +CONFIG_USB_OHCI_HCD=y +# CONFIG_USB_OHCI_BIG_ENDIAN is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +# CONFIG_USB_SL811_HCD is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# may also be needed; see USB_STORAGE Help for more information +# +CONFIG_USB_STORAGE=y +CONFIG_USB_STORAGE_DEBUG=y +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_DPCM is not set +# CONFIG_USB_STORAGE_USBAT is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_STORAGE_KARMA is not set +# CONFIG_USB_LIBUSUAL is not set + +# +# USB Input Devices +# +# CONFIG_USB_HID is not set + +# +# USB HID Boot Protocol drivers +# +# CONFIG_USB_KBD is not set +# CONFIG_USB_MOUSE is not set +# CONFIG_USB_AIPTEK is not set +# CONFIG_USB_WACOM is not set +# CONFIG_USB_ACECAD is not set +# CONFIG_USB_KBTAB is not set +# CONFIG_USB_POWERMATE is not set +# CONFIG_USB_TOUCHSCREEN is not set +# CONFIG_USB_YEALINK is not set +# CONFIG_USB_XPAD is not set +# CONFIG_USB_ATI_REMOTE is not set +# CONFIG_USB_ATI_REMOTE2 is not set +# CONFIG_USB_KEYSPAN_REMOTE is not set +# CONFIG_USB_APPLETOUCH is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set + +# +# USB Network Adapters +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET_MII is not set +# CONFIG_USB_USBNET is not set +CONFIG_USB_MON=y + +# +# USB port drivers +# + +# +# USB Serial Converter support +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_AUERSWALD is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_PHIDGET is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_TEST is not set + +# +# USB DSL modem support +# + +# +# USB Gadget Support +# +CONFIG_USB_GADGET=y +# CONFIG_USB_GADGET_DEBUG_FILES is not set +CONFIG_USB_GADGET_SELECTED=y +# CONFIG_USB_GADGET_NET2280 is not set +# CONFIG_USB_GADGET_PXA2XX is not set +# CONFIG_USB_GADGET_GOKU is not set +# CONFIG_USB_GADGET_LH7A40X is not set +# CONFIG_USB_GADGET_OMAP is not set +CONFIG_USB_GADGET_AT91=y +CONFIG_USB_AT91=y +# CONFIG_USB_GADGET_DUMMY_HCD is not set +# CONFIG_USB_GADGET_DUALSPEED is not set +CONFIG_USB_ZERO=m +# CONFIG_USB_ETH is not set +CONFIG_USB_GADGETFS=m +CONFIG_USB_FILE_STORAGE=m +# CONFIG_USB_FILE_STORAGE_TEST is not set +CONFIG_USB_G_SERIAL=m +# CONFIG_USB_MIDI_GADGET is not set + +# +# MMC/SD Card support +# +# CONFIG_MMC is not set + +# +# Real Time Clock +# +CONFIG_RTC_LIB=y +# CONFIG_RTC_CLASS is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set +# CONFIG_EXT3_FS is not set +# CONFIG_EXT4DEV_FS is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +# CONFIG_MSDOS_FS is not set +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_CRAMFS=y +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +# CONFIG_NFS_FS is not set +# CONFIG_NFSD is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +CONFIG_NLS_CODEPAGE_850=y +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set + +# +# Profiling support +# +# CONFIG_PROFILING is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_MUST_CHECK=y +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_KERNEL=y +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_RWSEMS is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_BUGVERBOSE=y +# CONFIG_DEBUG_INFO is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_LIST is not set +CONFIG_FRAME_POINTER=y +CONFIG_FORCED_INLINING=y +# CONFIG_HEADERS_CHECK is not set +# CONFIG_RCU_TORTURE_TEST is not set +CONFIG_DEBUG_USER=y +# CONFIG_DEBUG_WAITQ is not set +# CONFIG_DEBUG_ERRORS is not set +CONFIG_DEBUG_LL=y +# CONFIG_DEBUG_ICEDCC is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Library routines +# +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_PLIST=y diff --git a/trunk/arch/arm/configs/at91sam9261ek_defconfig b/trunk/arch/arm/configs/at91sam9261ek_defconfig new file mode 100644 index 000000000000..784ad7c0186d --- /dev/null +++ b/trunk/arch/arm/configs/at91sam9261ek_defconfig @@ -0,0 +1,1106 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.19-rc6 +# Fri Nov 17 18:00:38 2006 +# +CONFIG_ARM=y +# CONFIG_GENERIC_TIME is not set +CONFIG_MMU=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_VECTORS_BASE=0xffff0000 +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +# CONFIG_SWAP is not set +CONFIG_SYSVIPC=y +# CONFIG_IPC_NS is not set +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_TASKSTATS is not set +# CONFIG_UTS_NS is not set +# CONFIG_AUDIT is not set +# CONFIG_IKCONFIG is not set +# CONFIG_RELAY is not set +CONFIG_INITRAMFS_SOURCE="" +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +# CONFIG_EMBEDDED is not set +CONFIG_UID16=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SHMEM=y +CONFIG_SLAB=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_RT_MUTEXES=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_KMOD=y + +# +# Block layer +# +CONFIG_BLOCK=y +# CONFIG_BLK_DEV_IO_TRACE is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +# CONFIG_IOSCHED_DEADLINE is not set +# CONFIG_IOSCHED_CFQ is not set +CONFIG_DEFAULT_AS=y +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="anticipatory" + +# +# System Type +# +# CONFIG_ARCH_AAEC2000 is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +CONFIG_ARCH_AT91=y +# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_CO285 is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_PNX4008 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_OMAP is not set + +# +# Atmel AT91 System-on-Chip +# +# CONFIG_ARCH_AT91RM9200 is not set +# CONFIG_ARCH_AT91SAM9260 is not set +CONFIG_ARCH_AT91SAM9261=y + +# +# AT91SAM9261 Board Type +# +CONFIG_MACH_AT91SAM9261EK=y + +# +# AT91 Board Options +# +# CONFIG_MTD_NAND_AT91_BUSWIDTH_16 is not set + +# +# AT91 Feature Selections +# +# CONFIG_AT91_PROGRAMMABLE_CLOCKS is not set + +# +# Processor Type +# +CONFIG_CPU_32=y +CONFIG_CPU_ARM926T=y +CONFIG_CPU_32v5=y +CONFIG_CPU_ABRT_EV5TJ=y +CONFIG_CPU_CACHE_VIVT=y +CONFIG_CPU_COPY_V4WB=y +CONFIG_CPU_TLB_V4WBI=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y + +# +# Processor Features +# +# CONFIG_ARM_THUMB is not set +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_WRITETHROUGH is not set +# CONFIG_CPU_CACHE_ROUND_ROBIN is not set + +# +# Bus support +# + +# +# PCCARD (PCMCIA/CardBus) support +# +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +# CONFIG_PREEMPT is not set +# CONFIG_NO_IDLE_HZ is not set +CONFIG_HZ=100 +# CONFIG_AEABI is not set +# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4096 +# CONFIG_RESOURCES_64BIT is not set +# CONFIG_LEDS is not set +CONFIG_ALIGNMENT_TRAP=y + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="mem=64M console=ttyS0,115200 initrd=0x21100000,3145728 root=/dev/ram0 rw" +# CONFIG_XIP_KERNEL is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +CONFIG_FPE_NWFPE=y +# CONFIG_FPE_NWFPE_XP is not set +# CONFIG_FPE_FASTFPE is not set +# CONFIG_VFP is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_AOUT is not set +# CONFIG_BINFMT_MISC is not set +# CONFIG_ARTHUR is not set + +# +# Power management options +# +# CONFIG_PM is not set +# CONFIG_APM is not set + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_IPV6 is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETFILTER is not set + +# +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set + +# +# TIPC Configuration (EXPERIMENTAL) +# +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_IEEE80211 is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_FW_LOADER is not set +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_SYS_HYPERVISOR is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +# CONFIG_CONNECTOR is not set + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_REDBOOT_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y +# CONFIG_MTD_AFS_PARTS is not set + +# +# User Modules And Translation Layers +# +# CONFIG_MTD_CHAR is not set +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set + +# +# RAM/ROM/Flash chip drivers +# +# CONFIG_MTD_CFI is not set +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set +# CONFIG_MTD_OBSOLETE_CHIPS is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set + +# +# NAND Flash Device Drivers +# +CONFIG_MTD_NAND=y +# CONFIG_MTD_NAND_VERIFY_WRITE is not set +# CONFIG_MTD_NAND_ECC_SMC is not set +CONFIG_MTD_NAND_IDS=y +# CONFIG_MTD_NAND_DISKONCHIP is not set +CONFIG_MTD_NAND_AT91=y +# CONFIG_MTD_NAND_NANDSIM is not set + +# +# OneNAND Flash Device Drivers +# +# CONFIG_MTD_ONENAND is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_COW_COMMON is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_UB is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=8192 +CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 +CONFIG_BLK_DEV_INITRD=y +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=y +# CONFIG_SCSI_NETLINK is not set +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +# CONFIG_CHR_DEV_SG is not set +# CONFIG_CHR_DEV_SCH is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +CONFIG_SCSI_MULTI_LUN=y +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set + +# +# SCSI Transports +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set + +# +# SCSI low-level drivers +# +# CONFIG_ISCSI_TCP is not set +# CONFIG_SCSI_DEBUG is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# + +# +# I2O device support +# + +# +# Network device support +# +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# PHY device support +# +# CONFIG_PHYLIB is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_SMC91X is not set +CONFIG_DM9000=y + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# + +# +# Token Ring devices +# + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_ATMEL=y +CONFIG_SERIAL_ATMEL_CONSOLE=y +# CONFIG_SERIAL_ATMEL_TTYAT is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +CONFIG_WATCHDOG=y +CONFIG_WATCHDOG_NOWAYOUT=y + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set + +# +# USB-based Watchdog Cards +# +# CONFIG_USBPCWATCHDOG is not set +CONFIG_HW_RANDOM=y +# CONFIG_NVRAM is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# +# CONFIG_TCG_TPM is not set + +# +# I2C support +# +CONFIG_I2C=y +CONFIG_I2C_CHARDEV=y + +# +# I2C Algorithms +# +# CONFIG_I2C_ALGOBIT is not set +# CONFIG_I2C_ALGOPCF is not set +# CONFIG_I2C_ALGOPCA is not set + +# +# I2C Hardware Bus support +# +CONFIG_I2C_AT91=y +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_PCA is not set +# CONFIG_I2C_PCA_ISA is not set + +# +# Miscellaneous I2C Chip support +# +# CONFIG_SENSORS_DS1337 is not set +# CONFIG_SENSORS_DS1374 is not set +# CONFIG_SENSORS_EEPROM is not set +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + +# +# Hardware Monitoring support +# +# CONFIG_HWMON is not set +# CONFIG_HWMON_VID is not set + +# +# Misc devices +# +# CONFIG_TIFM_CORE is not set + +# +# LED devices +# +# CONFIG_NEW_LEDS is not set + +# +# LED drivers +# + +# +# LED Triggers +# + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set +# CONFIG_USB_DABUSB is not set + +# +# Graphics support +# +# CONFIG_FIRMWARE_EDID is not set +# CONFIG_FB is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +# CONFIG_USB_ARCH_HAS_EHCI is not set +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +# CONFIG_USB_BANDWIDTH is not set +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_OTG is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_ISP116X_HCD is not set +CONFIG_USB_OHCI_HCD=y +# CONFIG_USB_OHCI_BIG_ENDIAN is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +# CONFIG_USB_SL811_HCD is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# may also be needed; see USB_STORAGE Help for more information +# +CONFIG_USB_STORAGE=y +CONFIG_USB_STORAGE_DEBUG=y +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_DPCM is not set +# CONFIG_USB_STORAGE_USBAT is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_STORAGE_KARMA is not set +# CONFIG_USB_LIBUSUAL is not set + +# +# USB Input Devices +# +# CONFIG_USB_HID is not set + +# +# USB HID Boot Protocol drivers +# +# CONFIG_USB_KBD is not set +# CONFIG_USB_MOUSE is not set +# CONFIG_USB_AIPTEK is not set +# CONFIG_USB_WACOM is not set +# CONFIG_USB_ACECAD is not set +# CONFIG_USB_KBTAB is not set +# CONFIG_USB_POWERMATE is not set +# CONFIG_USB_TOUCHSCREEN is not set +# CONFIG_USB_YEALINK is not set +# CONFIG_USB_XPAD is not set +# CONFIG_USB_ATI_REMOTE is not set +# CONFIG_USB_ATI_REMOTE2 is not set +# CONFIG_USB_KEYSPAN_REMOTE is not set +# CONFIG_USB_APPLETOUCH is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set + +# +# USB Network Adapters +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET_MII is not set +# CONFIG_USB_USBNET is not set +CONFIG_USB_MON=y + +# +# USB port drivers +# + +# +# USB Serial Converter support +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_AUERSWALD is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_PHIDGET is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_TEST is not set + +# +# USB DSL modem support +# + +# +# USB Gadget Support +# +CONFIG_USB_GADGET=y +# CONFIG_USB_GADGET_DEBUG_FILES is not set +CONFIG_USB_GADGET_SELECTED=y +# CONFIG_USB_GADGET_NET2280 is not set +# CONFIG_USB_GADGET_PXA2XX is not set +# CONFIG_USB_GADGET_GOKU is not set +# CONFIG_USB_GADGET_LH7A40X is not set +# CONFIG_USB_GADGET_OMAP is not set +CONFIG_USB_GADGET_AT91=y +CONFIG_USB_AT91=y +# CONFIG_USB_GADGET_DUMMY_HCD is not set +# CONFIG_USB_GADGET_DUALSPEED is not set +CONFIG_USB_ZERO=m +# CONFIG_USB_ETH is not set +CONFIG_USB_GADGETFS=m +CONFIG_USB_FILE_STORAGE=m +# CONFIG_USB_FILE_STORAGE_TEST is not set +CONFIG_USB_G_SERIAL=m +# CONFIG_USB_MIDI_GADGET is not set + +# +# MMC/SD Card support +# +CONFIG_MMC=y +# CONFIG_MMC_DEBUG is not set +CONFIG_MMC_BLOCK=y +CONFIG_MMC_AT91=m +# CONFIG_MMC_TIFM_SD is not set + +# +# Real Time Clock +# +CONFIG_RTC_LIB=y +# CONFIG_RTC_CLASS is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set +# CONFIG_EXT3_FS is not set +# CONFIG_EXT4DEV_FS is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +# CONFIG_MSDOS_FS is not set +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +# CONFIG_JFFS2_FS is not set +CONFIG_CRAMFS=y +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +# CONFIG_NFS_FS is not set +# CONFIG_NFSD is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +CONFIG_NLS_CODEPAGE_850=y +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set + +# +# Profiling support +# +# CONFIG_PROFILING is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_MUST_CHECK=y +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_KERNEL=y +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_RWSEMS is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_BUGVERBOSE=y +# CONFIG_DEBUG_INFO is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_LIST is not set +CONFIG_FRAME_POINTER=y +CONFIG_FORCED_INLINING=y +# CONFIG_HEADERS_CHECK is not set +# CONFIG_RCU_TORTURE_TEST is not set +CONFIG_DEBUG_USER=y +# CONFIG_DEBUG_WAITQ is not set +# CONFIG_DEBUG_ERRORS is not set +CONFIG_DEBUG_LL=y +# CONFIG_DEBUG_ICEDCC is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Library routines +# +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_PLIST=y diff --git a/trunk/arch/arm/configs/badge4_defconfig b/trunk/arch/arm/configs/badge4_defconfig index cfe6bd8e81cd..821865f75605 100644 --- a/trunk/arch/arm/configs/badge4_defconfig +++ b/trunk/arch/arm/configs/badge4_defconfig @@ -1216,7 +1216,6 @@ CONFIG_DEBUG_INFO=y # CONFIG_DEBUG_FS is not set CONFIG_FRAME_POINTER=y CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_WAITQ is not set CONFIG_DEBUG_ERRORS=y CONFIG_DEBUG_LL=y # CONFIG_DEBUG_ICEDCC is not set diff --git a/trunk/arch/arm/configs/carmeva_defconfig b/trunk/arch/arm/configs/carmeva_defconfig index d24ae8777c35..d392833b31fb 100644 --- a/trunk/arch/arm/configs/carmeva_defconfig +++ b/trunk/arch/arm/configs/carmeva_defconfig @@ -474,7 +474,7 @@ CONFIG_LEGACY_PTY_COUNT=256 # CONFIG_WATCHDOG is not set # CONFIG_NVRAM is not set # CONFIG_RTC is not set -# CONFIG_AT91_RTC is not set +# CONFIG_AT91RM9200_RTC is not set # CONFIG_DTLK is not set # CONFIG_R3964 is not set diff --git a/trunk/arch/arm/configs/cerfcube_defconfig b/trunk/arch/arm/configs/cerfcube_defconfig index 09b7acd7f647..ee130b528bd4 100644 --- a/trunk/arch/arm/configs/cerfcube_defconfig +++ b/trunk/arch/arm/configs/cerfcube_defconfig @@ -851,7 +851,6 @@ CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_FS is not set CONFIG_FRAME_POINTER=y CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_WAITQ is not set CONFIG_DEBUG_ERRORS=y CONFIG_DEBUG_LL=y # CONFIG_DEBUG_ICEDCC is not set diff --git a/trunk/arch/arm/configs/collie_defconfig b/trunk/arch/arm/configs/collie_defconfig index a3758913c0bb..970c8c772eb7 100644 --- a/trunk/arch/arm/configs/collie_defconfig +++ b/trunk/arch/arm/configs/collie_defconfig @@ -934,7 +934,6 @@ CONFIG_FRAME_POINTER=y CONFIG_FORCED_INLINING=y # CONFIG_RCU_TORTURE_TEST is not set # CONFIG_DEBUG_USER is not set -# CONFIG_DEBUG_WAITQ is not set CONFIG_DEBUG_ERRORS=y # CONFIG_DEBUG_LL is not set diff --git a/trunk/arch/arm/configs/corgi_defconfig b/trunk/arch/arm/configs/corgi_defconfig index c41c04fa5020..e8980a9bb893 100644 --- a/trunk/arch/arm/configs/corgi_defconfig +++ b/trunk/arch/arm/configs/corgi_defconfig @@ -1513,7 +1513,6 @@ CONFIG_DEBUG_BUGVERBOSE=y CONFIG_FRAME_POINTER=y # CONFIG_RCU_TORTURE_TEST is not set # CONFIG_DEBUG_USER is not set -# CONFIG_DEBUG_WAITQ is not set CONFIG_DEBUG_ERRORS=y CONFIG_DEBUG_LL=y # CONFIG_DEBUG_ICEDCC is not set diff --git a/trunk/arch/arm/configs/csb337_defconfig b/trunk/arch/arm/configs/csb337_defconfig index 20e68250d835..2cadd51506bb 100644 --- a/trunk/arch/arm/configs/csb337_defconfig +++ b/trunk/arch/arm/configs/csb337_defconfig @@ -1113,7 +1113,6 @@ CONFIG_DEBUG_BUGVERBOSE=y CONFIG_FRAME_POINTER=y # CONFIG_RCU_TORTURE_TEST is not set CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_WAITQ is not set # CONFIG_DEBUG_ERRORS is not set CONFIG_DEBUG_LL=y # CONFIG_DEBUG_ICEDCC is not set diff --git a/trunk/arch/arm/configs/csb637_defconfig b/trunk/arch/arm/configs/csb637_defconfig index df8595ac031f..94908c1df4cf 100644 --- a/trunk/arch/arm/configs/csb637_defconfig +++ b/trunk/arch/arm/configs/csb637_defconfig @@ -623,7 +623,7 @@ CONFIG_AT91RM9200_WATCHDOG=y # CONFIG_USBPCWATCHDOG is not set # CONFIG_NVRAM is not set CONFIG_RTC=y -# CONFIG_AT91_RTC is not set +# CONFIG_AT91RM9200_RTC is not set # CONFIG_DTLK is not set # CONFIG_R3964 is not set @@ -1062,7 +1062,6 @@ CONFIG_DEBUG_BUGVERBOSE=y CONFIG_FRAME_POINTER=y # CONFIG_RCU_TORTURE_TEST is not set CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_WAITQ is not set # CONFIG_DEBUG_ERRORS is not set CONFIG_DEBUG_LL=y # CONFIG_DEBUG_ICEDCC is not set diff --git a/trunk/arch/arm/configs/ep93xx_defconfig b/trunk/arch/arm/configs/ep93xx_defconfig index 3b4802a849e4..f8a66b72ad5d 100644 --- a/trunk/arch/arm/configs/ep93xx_defconfig +++ b/trunk/arch/arm/configs/ep93xx_defconfig @@ -125,6 +125,7 @@ CONFIG_CRUNCH=y # # EP93xx Platforms # +CONFIG_MACH_ADSSPHERE=y CONFIG_MACH_EDB9302=y CONFIG_MACH_EDB9312=y CONFIG_MACH_EDB9315=y @@ -1134,7 +1135,6 @@ CONFIG_FRAME_POINTER=y CONFIG_FORCED_INLINING=y # CONFIG_RCU_TORTURE_TEST is not set CONFIG_DEBUG_USER=y -CONFIG_DEBUG_WAITQ=y CONFIG_DEBUG_ERRORS=y CONFIG_DEBUG_LL=y # CONFIG_DEBUG_ICEDCC is not set diff --git a/trunk/arch/arm/configs/h7202_defconfig b/trunk/arch/arm/configs/h7202_defconfig index 9d62ed16bf57..0e739af52713 100644 --- a/trunk/arch/arm/configs/h7202_defconfig +++ b/trunk/arch/arm/configs/h7202_defconfig @@ -702,7 +702,6 @@ CONFIG_DEBUG_INFO=y # CONFIG_DEBUG_FS is not set CONFIG_FRAME_POINTER=y CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_WAITQ is not set # CONFIG_DEBUG_ERRORS is not set # CONFIG_DEBUG_LL is not set diff --git a/trunk/arch/arm/configs/hackkit_defconfig b/trunk/arch/arm/configs/hackkit_defconfig index a45b57582b86..1c8fb89a6730 100644 --- a/trunk/arch/arm/configs/hackkit_defconfig +++ b/trunk/arch/arm/configs/hackkit_defconfig @@ -740,7 +740,6 @@ CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_FS is not set CONFIG_FRAME_POINTER=y CONFIG_DEBUG_USER=y -CONFIG_DEBUG_WAITQ=y CONFIG_DEBUG_ERRORS=y CONFIG_DEBUG_LL=y # CONFIG_DEBUG_ICEDCC is not set diff --git a/trunk/arch/arm/configs/integrator_defconfig b/trunk/arch/arm/configs/integrator_defconfig index 692ab57ba1ca..3ce96e60b409 100644 --- a/trunk/arch/arm/configs/integrator_defconfig +++ b/trunk/arch/arm/configs/integrator_defconfig @@ -835,7 +835,6 @@ CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_FS is not set CONFIG_FRAME_POINTER=y # CONFIG_DEBUG_USER is not set -# CONFIG_DEBUG_WAITQ is not set CONFIG_DEBUG_ERRORS=y # CONFIG_DEBUG_LL is not set diff --git a/trunk/arch/arm/configs/iop13xx_defconfig b/trunk/arch/arm/configs/iop13xx_defconfig new file mode 100644 index 000000000000..f6e46193fd26 --- /dev/null +++ b/trunk/arch/arm/configs/iop13xx_defconfig @@ -0,0 +1,1134 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.19 +# Fri Dec 1 10:51:01 2006 +# +CONFIG_ARM=y +# CONFIG_GENERIC_TIME is not set +CONFIG_MMU=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_VECTORS_BASE=0xffff0000 +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_IPC_NS is not set +CONFIG_POSIX_MQUEUE=y +CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set +# CONFIG_TASKSTATS is not set +# CONFIG_UTS_NS is not set +# CONFIG_AUDIT is not set +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +# CONFIG_RELAY is not set +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SYSCTL=y +# CONFIG_EMBEDDED is not set +CONFIG_UID16=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SHMEM=y +CONFIG_SLAB=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_RT_MUTEXES=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_MODVERSIONS=y +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_KMOD=y + +# +# Block layer +# +CONFIG_BLOCK=y +# CONFIG_BLK_DEV_IO_TRACE is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +# CONFIG_IOSCHED_AS is not set +CONFIG_IOSCHED_DEADLINE=y +# CONFIG_IOSCHED_CFQ is not set +# CONFIG_DEFAULT_AS is not set +CONFIG_DEFAULT_DEADLINE=y +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="deadline" + +# +# System Type +# +# CONFIG_ARCH_AAEC2000 is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_AT91 is not set +# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_CO285 is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set +CONFIG_ARCH_IOP13XX=y +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_PNX4008 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_OMAP is not set + +# +# IOP13XX Implementation Options +# + +# +# IOP13XX Platform Support +# +CONFIG_MACH_IQ81340SC=y +CONFIG_MACH_IQ81340MC=y + +# +# Processor Type +# +CONFIG_CPU_32=y +CONFIG_CPU_XSC3=y +CONFIG_CPU_32v5=y +CONFIG_CPU_ABRT_EV5T=y +CONFIG_CPU_CACHE_VIVT=y +CONFIG_CPU_TLB_V4WBI=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y +CONFIG_IO_36=y + +# +# Processor Features +# +CONFIG_ARM_THUMB=y +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_BPREDICT_DISABLE is not set + +# +# Bus support +# +CONFIG_PCI=y + +# +# PCCARD (PCMCIA/CardBus) support +# +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +# CONFIG_PREEMPT is not set +# CONFIG_NO_IDLE_HZ is not set +CONFIG_HZ=100 +# CONFIG_AEABI is not set +# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4096 +# CONFIG_RESOURCES_64BIT is not set +CONFIG_ALIGNMENT_TRAP=y + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="ip=bootp root=nfs console=ttyS0,115200 nfsroot=,tcp,v3,wsize=8192,rsize=8192" +# CONFIG_XIP_KERNEL is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +CONFIG_FPE_NWFPE=y +# CONFIG_FPE_NWFPE_XP is not set +# CONFIG_FPE_FASTFPE is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +CONFIG_BINFMT_AOUT=y +# CONFIG_BINFMT_MISC is not set +# CONFIG_ARTHUR is not set + +# +# Power management options +# +# CONFIG_PM is not set +# CONFIG_APM is not set + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_XFRM_SUB_POLICY is not set +CONFIG_NET_KEY=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_IPV6 is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETFILTER is not set + +# +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set + +# +# TIPC Configuration (EXPERIMENTAL) +# +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_IEEE80211 is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_FW_LOADER is not set +# CONFIG_SYS_HYPERVISOR is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +# CONFIG_CONNECTOR is not set + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_PARTITIONS=y +CONFIG_MTD_REDBOOT_PARTS=y +CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1 +CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y +CONFIG_MTD_REDBOOT_PARTS_READONLY=y +# CONFIG_MTD_CMDLINE_PARTS is not set +# CONFIG_MTD_AFS_PARTS is not set + +# +# User Modules And Translation Layers +# +# CONFIG_MTD_CHAR is not set +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +CONFIG_MTD_CFI_ADV_OPTIONS=y +CONFIG_MTD_CFI_NOSWAP=y +# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set +# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set +# CONFIG_MTD_CFI_GEOMETRY is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_OTP is not set +CONFIG_MTD_CFI_INTELEXT=y +# CONFIG_MTD_CFI_AMDSTD is not set +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set +# CONFIG_MTD_OBSOLETE_CHIPS is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +CONFIG_MTD_PHYSMAP=y +CONFIG_MTD_PHYSMAP_START=0xfa000000 +CONFIG_MTD_PHYSMAP_LEN=0x0 +CONFIG_MTD_PHYSMAP_BANKWIDTH=2 +# CONFIG_MTD_ARM_INTEGRATOR is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_PMC551 is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set + +# +# NAND Flash Device Drivers +# +# CONFIG_MTD_NAND is not set + +# +# OneNAND Flash Device Drivers +# +# CONFIG_MTD_ONENAND is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_COW_COMMON is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_SX8 is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=2 +CONFIG_BLK_DEV_RAM_SIZE=8192 +CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 +CONFIG_BLK_DEV_INITRD=y +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=y +# CONFIG_SCSI_NETLINK is not set +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +CONFIG_CHR_DEV_SG=y +# CONFIG_CHR_DEV_SCH is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +# CONFIG_SCSI_MULTI_LUN is not set +CONFIG_SCSI_CONSTANTS=y +# CONFIG_SCSI_LOGGING is not set + +# +# SCSI Transports +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +CONFIG_SCSI_ISCSI_ATTRS=y +CONFIG_SCSI_SAS_ATTRS=y +# CONFIG_SCSI_SAS_LIBSAS is not set + +# +# SCSI low-level drivers +# +# CONFIG_ISCSI_TCP is not set +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_SCSI_3W_9XXX is not set +# CONFIG_SCSI_ACARD is not set +# CONFIG_SCSI_AACRAID is not set +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_AIC79XX is not set +# CONFIG_SCSI_AIC94XX is not set +# CONFIG_SCSI_DPT_I2O is not set +# CONFIG_SCSI_ARCMSR is not set +# CONFIG_MEGARAID_NEWGEN is not set +# CONFIG_MEGARAID_LEGACY is not set +# CONFIG_MEGARAID_SAS is not set +# CONFIG_SCSI_HPTIOP is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +# CONFIG_SCSI_IPS is not set +# CONFIG_SCSI_INITIO is not set +# CONFIG_SCSI_INIA100 is not set +# CONFIG_SCSI_STEX is not set +# CONFIG_SCSI_SYM53C8XX_2 is not set +# CONFIG_SCSI_QLOGIC_1280 is not set +# CONFIG_SCSI_QLA_FC is not set +# CONFIG_SCSI_QLA_ISCSI is not set +# CONFIG_SCSI_LPFC is not set +# CONFIG_SCSI_DC395x is not set +# CONFIG_SCSI_DC390T is not set +# CONFIG_SCSI_NSP32 is not set +# CONFIG_SCSI_DEBUG is not set + +# +# Serial ATA (prod) and Parallel ATA (experimental) drivers +# +# CONFIG_ATA is not set + +# +# Multi-device support (RAID and LVM) +# +CONFIG_MD=y +CONFIG_BLK_DEV_MD=y +# CONFIG_MD_LINEAR is not set +CONFIG_MD_RAID0=y +CONFIG_MD_RAID1=y +CONFIG_MD_RAID10=y +CONFIG_MD_RAID456=y +# CONFIG_MD_RAID5_RESHAPE is not set +# CONFIG_MD_MULTIPATH is not set +# CONFIG_MD_FAULTY is not set +CONFIG_BLK_DEV_DM=y +# CONFIG_DM_DEBUG is not set +# CONFIG_DM_CRYPT is not set +# CONFIG_DM_SNAPSHOT is not set +# CONFIG_DM_MIRROR is not set +# CONFIG_DM_ZERO is not set +# CONFIG_DM_MULTIPATH is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set +# CONFIG_FUSION_SPI is not set +# CONFIG_FUSION_FC is not set +# CONFIG_FUSION_SAS is not set + +# +# IEEE 1394 (FireWire) support +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Network device support +# +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# +# PHY device support +# + +# +# Ethernet (10 or 100Mbit) +# +# CONFIG_NET_ETHERNET is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +CONFIG_E1000=y +CONFIG_E1000_NAPI=y +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SIS190 is not set +# CONFIG_SKGE is not set +# CONFIG_SKY2 is not set +# CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set +# CONFIG_BNX2 is not set +# CONFIG_QLA3XXX is not set + +# +# Ethernet (10000 Mbit) +# +# CONFIG_CHELSIO_T1 is not set +# CONFIG_IXGB is not set +# CONFIG_S2IO is not set +# CONFIG_MYRI10GE is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_NET_FC is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_PCI=y +CONFIG_SERIAL_8250_NR_UARTS=2 +CONFIG_SERIAL_8250_RUNTIME_UARTS=2 +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_JSM is not set +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +CONFIG_HW_RANDOM=y +# CONFIG_NVRAM is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# +# CONFIG_TCG_TPM is not set + +# +# I2C support +# +CONFIG_I2C=y +# CONFIG_I2C_CHARDEV is not set + +# +# I2C Algorithms +# +CONFIG_I2C_ALGOBIT=m +CONFIG_I2C_ALGOPCF=m +CONFIG_I2C_ALGOPCA=m + +# +# I2C Hardware Bus support +# +# CONFIG_I2C_ALI1535 is not set +# CONFIG_I2C_ALI1563 is not set +# CONFIG_I2C_ALI15X3 is not set +# CONFIG_I2C_AMD756 is not set +# CONFIG_I2C_AMD8111 is not set +# CONFIG_I2C_I801 is not set +# CONFIG_I2C_I810 is not set +# CONFIG_I2C_PIIX4 is not set +CONFIG_I2C_IOP3XX=y +# CONFIG_I2C_NFORCE2 is not set +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_PROSAVAGE is not set +# CONFIG_I2C_SAVAGE4 is not set +# CONFIG_I2C_SIS5595 is not set +# CONFIG_I2C_SIS630 is not set +# CONFIG_I2C_SIS96X is not set +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_VIA is not set +# CONFIG_I2C_VIAPRO is not set +# CONFIG_I2C_VOODOO3 is not set +# CONFIG_I2C_PCA_ISA is not set + +# +# Miscellaneous I2C Chip support +# +# CONFIG_SENSORS_DS1337 is not set +# CONFIG_SENSORS_DS1374 is not set +# CONFIG_SENSORS_EEPROM is not set +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + +# +# Hardware Monitoring support +# +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_SENSORS_ABITUGURU is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ASB100 is not set +# CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_DS1621 is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_FSCHER is not set +# CONFIG_SENSORS_FSCPOS is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_LM63 is not set +# CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM77 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set +# CONFIG_SENSORS_LM83 is not set +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_SIS5595 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47M192 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_VIA686A is not set +# CONFIG_SENSORS_VT1211 is not set +# CONFIG_SENSORS_VT8231 is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83791D is not set +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Misc devices +# +# CONFIG_SGI_IOC4 is not set +# CONFIG_TIFM_CORE is not set + +# +# LED devices +# +# CONFIG_NEW_LEDS is not set + +# +# LED drivers +# + +# +# LED Triggers +# + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# +CONFIG_FIRMWARE_EDID=y +# CONFIG_FB is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y +# CONFIG_USB is not set + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +# CONFIG_MMC is not set + +# +# Real Time Clock +# +CONFIG_RTC_LIB=y +# CONFIG_RTC_CLASS is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +# CONFIG_EXT3_FS_SECURITY is not set +# CONFIG_EXT4DEV_FS is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_SUMMARY is not set +# CONFIG_JFFS2_FS_XATTR is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +CONFIG_NFSD=y +CONFIG_NFSD_V3=y +# CONFIG_NFSD_V3_ACL is not set +# CONFIG_NFSD_V4 is not set +CONFIG_NFSD_TCP=y +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set +CONFIG_SMB_FS=m +# CONFIG_SMB_NLS_DEFAULT is not set +CONFIG_CIFS=m +# CONFIG_CIFS_STATS is not set +# CONFIG_CIFS_WEAK_PW_HASH is not set +# CONFIG_CIFS_XATTR is not set +# CONFIG_CIFS_DEBUG2 is not set +# CONFIG_CIFS_EXPERIMENTAL is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +# CONFIG_EFI_PARTITION is not set + +# +# Native Language Support +# +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +# CONFIG_NLS_CODEPAGE_437 is not set +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set +# CONFIG_NLS_ISO8859_1 is not set +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set + +# +# Profiling support +# +# CONFIG_PROFILING is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_MUST_CHECK=y +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_DEBUG_KERNEL is not set +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_DEBUG_BUGVERBOSE=y +# CONFIG_DEBUG_FS is not set +CONFIG_FRAME_POINTER=y +# CONFIG_HEADERS_CHECK is not set +CONFIG_DEBUG_USER=y + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Library routines +# +CONFIG_CRC_CCITT=y +# CONFIG_CRC16 is not set +CONFIG_CRC32=y +CONFIG_LIBCRC32C=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_PLIST=y diff --git a/trunk/arch/arm/configs/iop32x_defconfig b/trunk/arch/arm/configs/iop32x_defconfig index 0d67f66e78c2..b275c53728ec 100644 --- a/trunk/arch/arm/configs/iop32x_defconfig +++ b/trunk/arch/arm/configs/iop32x_defconfig @@ -1204,7 +1204,6 @@ CONFIG_FRAME_POINTER=y # CONFIG_FORCED_INLINING is not set # CONFIG_RCU_TORTURE_TEST is not set CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_WAITQ is not set # CONFIG_DEBUG_ERRORS is not set CONFIG_DEBUG_LL=y # CONFIG_DEBUG_ICEDCC is not set diff --git a/trunk/arch/arm/configs/iop33x_defconfig b/trunk/arch/arm/configs/iop33x_defconfig index 2a8fc153969d..848e3ace9069 100644 --- a/trunk/arch/arm/configs/iop33x_defconfig +++ b/trunk/arch/arm/configs/iop33x_defconfig @@ -1051,7 +1051,6 @@ CONFIG_FRAME_POINTER=y # CONFIG_FORCED_INLINING is not set # CONFIG_RCU_TORTURE_TEST is not set CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_WAITQ is not set # CONFIG_DEBUG_ERRORS is not set CONFIG_DEBUG_LL=y # CONFIG_DEBUG_ICEDCC is not set diff --git a/trunk/arch/arm/configs/ixp2000_defconfig b/trunk/arch/arm/configs/ixp2000_defconfig index 27b3e31a8ad8..bbd2dcf91e52 100644 --- a/trunk/arch/arm/configs/ixp2000_defconfig +++ b/trunk/arch/arm/configs/ixp2000_defconfig @@ -1026,7 +1026,6 @@ CONFIG_FRAME_POINTER=y CONFIG_FORCED_INLINING=y # CONFIG_RCU_TORTURE_TEST is not set CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_WAITQ is not set CONFIG_DEBUG_ERRORS=y CONFIG_DEBUG_LL=y # CONFIG_DEBUG_ICEDCC is not set diff --git a/trunk/arch/arm/configs/ixp23xx_defconfig b/trunk/arch/arm/configs/ixp23xx_defconfig index 7b18997083ce..06deefaec1d2 100644 --- a/trunk/arch/arm/configs/ixp23xx_defconfig +++ b/trunk/arch/arm/configs/ixp23xx_defconfig @@ -1305,7 +1305,6 @@ CONFIG_FRAME_POINTER=y CONFIG_FORCED_INLINING=y # CONFIG_RCU_TORTURE_TEST is not set CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_WAITQ is not set CONFIG_DEBUG_ERRORS=y CONFIG_DEBUG_LL=y # CONFIG_DEBUG_ICEDCC is not set diff --git a/trunk/arch/arm/configs/ixp4xx_defconfig b/trunk/arch/arm/configs/ixp4xx_defconfig index fac7c3b240c0..fabf74c51a88 100644 --- a/trunk/arch/arm/configs/ixp4xx_defconfig +++ b/trunk/arch/arm/configs/ixp4xx_defconfig @@ -1243,7 +1243,6 @@ CONFIG_DEBUG_BUGVERBOSE=y CONFIG_FRAME_POINTER=y # CONFIG_RCU_TORTURE_TEST is not set # CONFIG_DEBUG_USER is not set -# CONFIG_DEBUG_WAITQ is not set CONFIG_DEBUG_ERRORS=y CONFIG_DEBUG_LL=y # CONFIG_DEBUG_ICEDCC is not set diff --git a/trunk/arch/arm/configs/jornada720_defconfig b/trunk/arch/arm/configs/jornada720_defconfig index 80a6fd97eb32..0c556289a3f4 100644 --- a/trunk/arch/arm/configs/jornada720_defconfig +++ b/trunk/arch/arm/configs/jornada720_defconfig @@ -889,7 +889,6 @@ CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_FS is not set CONFIG_FRAME_POINTER=y # CONFIG_DEBUG_USER is not set -# CONFIG_DEBUG_WAITQ is not set CONFIG_DEBUG_ERRORS=y CONFIG_DEBUG_LL=y # CONFIG_DEBUG_ICEDCC is not set diff --git a/trunk/arch/arm/configs/kb9202_defconfig b/trunk/arch/arm/configs/kb9202_defconfig index b4cd4b414836..c16537d9d67a 100644 --- a/trunk/arch/arm/configs/kb9202_defconfig +++ b/trunk/arch/arm/configs/kb9202_defconfig @@ -437,7 +437,7 @@ CONFIG_LEGACY_PTY_COUNT=256 # CONFIG_WATCHDOG is not set # CONFIG_NVRAM is not set # CONFIG_RTC is not set -# CONFIG_AT91_RTC is not set +# CONFIG_AT91RM9200_RTC is not set # CONFIG_DTLK is not set # CONFIG_R3964 is not set @@ -753,7 +753,6 @@ CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_FS is not set CONFIG_FRAME_POINTER=y CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_WAITQ is not set CONFIG_DEBUG_ERRORS=y CONFIG_DEBUG_LL=y # CONFIG_DEBUG_ICEDCC is not set diff --git a/trunk/arch/arm/configs/lpd270_defconfig b/trunk/arch/arm/configs/lpd270_defconfig index 4b29e099640d..e146189ab54f 100644 --- a/trunk/arch/arm/configs/lpd270_defconfig +++ b/trunk/arch/arm/configs/lpd270_defconfig @@ -949,7 +949,6 @@ CONFIG_FRAME_POINTER=y CONFIG_FORCED_INLINING=y # CONFIG_RCU_TORTURE_TEST is not set CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_WAITQ is not set CONFIG_DEBUG_ERRORS=y CONFIG_DEBUG_LL=y # CONFIG_DEBUG_ICEDCC is not set diff --git a/trunk/arch/arm/configs/lpd7a400_defconfig b/trunk/arch/arm/configs/lpd7a400_defconfig index bf9cf9c6d2df..f8ac29d5c654 100644 --- a/trunk/arch/arm/configs/lpd7a400_defconfig +++ b/trunk/arch/arm/configs/lpd7a400_defconfig @@ -850,7 +850,6 @@ CONFIG_DEBUG_INFO=y # CONFIG_DEBUG_FS is not set CONFIG_FRAME_POINTER=y CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_WAITQ is not set CONFIG_DEBUG_ERRORS=y # CONFIG_DEBUG_LL is not set diff --git a/trunk/arch/arm/configs/lpd7a404_defconfig b/trunk/arch/arm/configs/lpd7a404_defconfig index 3a57be32e849..46a0f7fe1fa5 100644 --- a/trunk/arch/arm/configs/lpd7a404_defconfig +++ b/trunk/arch/arm/configs/lpd7a404_defconfig @@ -1100,7 +1100,6 @@ CONFIG_FRAME_POINTER=y CONFIG_FORCED_INLINING=y # CONFIG_RCU_TORTURE_TEST is not set CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_WAITQ is not set CONFIG_DEBUG_ERRORS=y # CONFIG_DEBUG_LL is not set diff --git a/trunk/arch/arm/configs/lubbock_defconfig b/trunk/arch/arm/configs/lubbock_defconfig index 81daadcbe0ba..e544bfbbde5d 100644 --- a/trunk/arch/arm/configs/lubbock_defconfig +++ b/trunk/arch/arm/configs/lubbock_defconfig @@ -772,7 +772,6 @@ CONFIG_DEBUG_INFO=y # CONFIG_DEBUG_FS is not set CONFIG_FRAME_POINTER=y CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_WAITQ is not set CONFIG_DEBUG_ERRORS=y CONFIG_DEBUG_LL=y # CONFIG_DEBUG_ICEDCC is not set diff --git a/trunk/arch/arm/configs/mainstone_defconfig b/trunk/arch/arm/configs/mainstone_defconfig index b112bd75bda2..cc8c95b99292 100644 --- a/trunk/arch/arm/configs/mainstone_defconfig +++ b/trunk/arch/arm/configs/mainstone_defconfig @@ -766,7 +766,6 @@ CONFIG_DEBUG_INFO=y # CONFIG_DEBUG_FS is not set CONFIG_FRAME_POINTER=y CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_WAITQ is not set CONFIG_DEBUG_ERRORS=y CONFIG_DEBUG_LL=y # CONFIG_DEBUG_ICEDCC is not set diff --git a/trunk/arch/arm/configs/mx1ads_defconfig b/trunk/arch/arm/configs/mx1ads_defconfig index d16f6cd6e039..577d7e1b5d42 100644 --- a/trunk/arch/arm/configs/mx1ads_defconfig +++ b/trunk/arch/arm/configs/mx1ads_defconfig @@ -691,7 +691,6 @@ CONFIG_DEBUG_INFO=y # CONFIG_DEBUG_FS is not set CONFIG_FRAME_POINTER=y CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_WAITQ is not set CONFIG_DEBUG_ERRORS=y # CONFIG_DEBUG_LL is not set diff --git a/trunk/arch/arm/configs/neponset_defconfig b/trunk/arch/arm/configs/neponset_defconfig index df8168e57b7c..e86794a10fc0 100644 --- a/trunk/arch/arm/configs/neponset_defconfig +++ b/trunk/arch/arm/configs/neponset_defconfig @@ -1115,7 +1115,6 @@ CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_FS is not set CONFIG_FRAME_POINTER=y CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_WAITQ is not set CONFIG_DEBUG_ERRORS=y CONFIG_DEBUG_LL=y # CONFIG_DEBUG_ICEDCC is not set diff --git a/trunk/arch/arm/configs/netwinder_defconfig b/trunk/arch/arm/configs/netwinder_defconfig index 2cae1ead9f9b..c1a63a35c58d 100644 --- a/trunk/arch/arm/configs/netwinder_defconfig +++ b/trunk/arch/arm/configs/netwinder_defconfig @@ -994,7 +994,6 @@ CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_FS is not set CONFIG_FRAME_POINTER=y CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_WAITQ is not set # CONFIG_DEBUG_ERRORS is not set # CONFIG_DEBUG_LL is not set diff --git a/trunk/arch/arm/configs/netx_defconfig b/trunk/arch/arm/configs/netx_defconfig index 61115a773382..57f32f39d0ff 100644 --- a/trunk/arch/arm/configs/netx_defconfig +++ b/trunk/arch/arm/configs/netx_defconfig @@ -872,7 +872,6 @@ CONFIG_FRAME_POINTER=y CONFIG_FORCED_INLINING=y # CONFIG_RCU_TORTURE_TEST is not set # CONFIG_DEBUG_USER is not set -# CONFIG_DEBUG_WAITQ is not set CONFIG_DEBUG_ERRORS=y # CONFIG_DEBUG_LL is not set diff --git a/trunk/arch/arm/configs/onearm_defconfig b/trunk/arch/arm/configs/onearm_defconfig index 9b9f2155af35..0498ebd7d5de 100644 --- a/trunk/arch/arm/configs/onearm_defconfig +++ b/trunk/arch/arm/configs/onearm_defconfig @@ -1045,7 +1045,6 @@ CONFIG_FRAME_POINTER=y CONFIG_FORCED_INLINING=y # CONFIG_RCU_TORTURE_TEST is not set CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_WAITQ is not set # CONFIG_DEBUG_ERRORS is not set CONFIG_DEBUG_LL=y # CONFIG_DEBUG_ICEDCC is not set diff --git a/trunk/arch/arm/configs/pleb_defconfig b/trunk/arch/arm/configs/pleb_defconfig index 24e8bdd4cb91..a6b47ea8e465 100644 --- a/trunk/arch/arm/configs/pleb_defconfig +++ b/trunk/arch/arm/configs/pleb_defconfig @@ -721,7 +721,6 @@ CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_FS is not set CONFIG_FRAME_POINTER=y # CONFIG_DEBUG_USER is not set -# CONFIG_DEBUG_WAITQ is not set # CONFIG_DEBUG_ERRORS is not set # CONFIG_DEBUG_LL is not set diff --git a/trunk/arch/arm/configs/pnx4008_defconfig b/trunk/arch/arm/configs/pnx4008_defconfig index a4989f44baaa..b5e11aa2e290 100644 --- a/trunk/arch/arm/configs/pnx4008_defconfig +++ b/trunk/arch/arm/configs/pnx4008_defconfig @@ -1604,7 +1604,6 @@ CONFIG_FRAME_POINTER=y CONFIG_FORCED_INLINING=y # CONFIG_RCU_TORTURE_TEST is not set # CONFIG_DEBUG_USER is not set -# CONFIG_DEBUG_WAITQ is not set # CONFIG_DEBUG_ERRORS is not set # CONFIG_DEBUG_LL is not set diff --git a/trunk/arch/arm/configs/pxa255-idp_defconfig b/trunk/arch/arm/configs/pxa255-idp_defconfig index b71d31a4bb56..46e5089df0ae 100644 --- a/trunk/arch/arm/configs/pxa255-idp_defconfig +++ b/trunk/arch/arm/configs/pxa255-idp_defconfig @@ -768,7 +768,6 @@ CONFIG_DEBUG_INFO=y # CONFIG_DEBUG_FS is not set CONFIG_FRAME_POINTER=y CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_WAITQ is not set CONFIG_DEBUG_ERRORS=y CONFIG_DEBUG_LL=y # CONFIG_DEBUG_ICEDCC is not set diff --git a/trunk/arch/arm/configs/realview-smp_defconfig b/trunk/arch/arm/configs/realview-smp_defconfig index ffd905ff19f1..fc39ba1a89f3 100644 --- a/trunk/arch/arm/configs/realview-smp_defconfig +++ b/trunk/arch/arm/configs/realview-smp_defconfig @@ -967,7 +967,6 @@ CONFIG_FORCED_INLINING=y # CONFIG_HEADERS_CHECK is not set # CONFIG_RCU_TORTURE_TEST is not set CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_WAITQ is not set CONFIG_DEBUG_ERRORS=y CONFIG_DEBUG_LL=y # CONFIG_DEBUG_ICEDCC is not set diff --git a/trunk/arch/arm/configs/realview_defconfig b/trunk/arch/arm/configs/realview_defconfig index 3f1ec4e304f7..accbf529ce5b 100644 --- a/trunk/arch/arm/configs/realview_defconfig +++ b/trunk/arch/arm/configs/realview_defconfig @@ -759,7 +759,6 @@ CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_FS is not set CONFIG_FRAME_POINTER=y CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_WAITQ is not set CONFIG_DEBUG_ERRORS=y # CONFIG_DEBUG_LL is not set diff --git a/trunk/arch/arm/configs/rpc_defconfig b/trunk/arch/arm/configs/rpc_defconfig index b498afdc03b6..bc091264d354 100644 --- a/trunk/arch/arm/configs/rpc_defconfig +++ b/trunk/arch/arm/configs/rpc_defconfig @@ -910,7 +910,6 @@ CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_FS is not set CONFIG_FRAME_POINTER=y CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_WAITQ is not set CONFIG_DEBUG_ERRORS=y CONFIG_DEBUG_LL=y # CONFIG_DEBUG_ICEDCC is not set diff --git a/trunk/arch/arm/configs/s3c2410_defconfig b/trunk/arch/arm/configs/s3c2410_defconfig index c0152393e494..3b31a33d0080 100644 --- a/trunk/arch/arm/configs/s3c2410_defconfig +++ b/trunk/arch/arm/configs/s3c2410_defconfig @@ -1319,7 +1319,6 @@ CONFIG_FORCED_INLINING=y # CONFIG_HEADERS_CHECK is not set # CONFIG_RCU_TORTURE_TEST is not set CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_WAITQ is not set # CONFIG_DEBUG_ERRORS is not set CONFIG_DEBUG_LL=y # CONFIG_DEBUG_ICEDCC is not set diff --git a/trunk/arch/arm/configs/shark_defconfig b/trunk/arch/arm/configs/shark_defconfig index c48d17062262..9b6561d119af 100644 --- a/trunk/arch/arm/configs/shark_defconfig +++ b/trunk/arch/arm/configs/shark_defconfig @@ -965,7 +965,6 @@ CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_FS is not set CONFIG_FRAME_POINTER=y CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_WAITQ is not set # CONFIG_DEBUG_ERRORS is not set # CONFIG_DEBUG_LL is not set diff --git a/trunk/arch/arm/configs/simpad_defconfig b/trunk/arch/arm/configs/simpad_defconfig index 140056a3507f..03f783e696b3 100644 --- a/trunk/arch/arm/configs/simpad_defconfig +++ b/trunk/arch/arm/configs/simpad_defconfig @@ -934,7 +934,6 @@ CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_FS is not set CONFIG_FRAME_POINTER=y CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_WAITQ is not set CONFIG_DEBUG_ERRORS=y CONFIG_DEBUG_LL=y # CONFIG_DEBUG_ICEDCC is not set diff --git a/trunk/arch/arm/configs/spitz_defconfig b/trunk/arch/arm/configs/spitz_defconfig index bd03238968c1..aa7a01179500 100644 --- a/trunk/arch/arm/configs/spitz_defconfig +++ b/trunk/arch/arm/configs/spitz_defconfig @@ -1406,7 +1406,6 @@ CONFIG_DEBUG_BUGVERBOSE=y CONFIG_FRAME_POINTER=y # CONFIG_RCU_TORTURE_TEST is not set # CONFIG_DEBUG_USER is not set -# CONFIG_DEBUG_WAITQ is not set CONFIG_DEBUG_ERRORS=y CONFIG_DEBUG_LL=y # CONFIG_DEBUG_ICEDCC is not set diff --git a/trunk/arch/arm/configs/versatile_defconfig b/trunk/arch/arm/configs/versatile_defconfig index f7bf6ef27d19..48dca69addae 100644 --- a/trunk/arch/arm/configs/versatile_defconfig +++ b/trunk/arch/arm/configs/versatile_defconfig @@ -972,7 +972,6 @@ CONFIG_FRAME_POINTER=y CONFIG_FORCED_INLINING=y # CONFIG_RCU_TORTURE_TEST is not set CONFIG_DEBUG_USER=y -# CONFIG_DEBUG_WAITQ is not set CONFIG_DEBUG_ERRORS=y CONFIG_DEBUG_LL=y # CONFIG_DEBUG_ICEDCC is not set diff --git a/trunk/arch/arm/kernel/Makefile b/trunk/arch/arm/kernel/Makefile index 1320a0efca73..ab06a86e85d5 100644 --- a/trunk/arch/arm/kernel/Makefile +++ b/trunk/arch/arm/kernel/Makefile @@ -24,7 +24,9 @@ obj-$(CONFIG_OABI_COMPAT) += sys_oabi-compat.o obj-$(CONFIG_CRUNCH) += crunch.o crunch-bits.o AFLAGS_crunch-bits.o := -Wa,-mcpu=ep9312 -obj-$(CONFIG_IWMMXT) += iwmmxt.o iwmmxt-notifier.o +obj-$(CONFIG_CPU_XSCALE) += xscale-cp0.o +obj-$(CONFIG_CPU_XSC3) += xscale-cp0.o +obj-$(CONFIG_IWMMXT) += iwmmxt.o AFLAGS_iwmmxt.o := -Wa,-mcpu=iwmmxt ifneq ($(CONFIG_ARCH_EBSA110),y) diff --git a/trunk/arch/arm/kernel/apm.c b/trunk/arch/arm/kernel/apm.c index ecf4f9472d94..a11fb9a40c04 100644 --- a/trunk/arch/arm/kernel/apm.c +++ b/trunk/arch/arm/kernel/apm.c @@ -12,7 +12,6 @@ */ #include #include -#include #include #include #include @@ -26,6 +25,7 @@ #include #include #include +#include #include /* apm_power_info */ #include @@ -71,7 +71,8 @@ struct apm_user { #define SUSPEND_PENDING 1 /* suspend pending read */ #define SUSPEND_READ 2 /* suspend read, pending ack */ #define SUSPEND_ACKED 3 /* suspend acked */ -#define SUSPEND_DONE 4 /* suspend completed */ +#define SUSPEND_WAIT 4 /* waiting for suspend */ +#define SUSPEND_DONE 5 /* suspend completed */ struct apm_queue queue; }; @@ -101,6 +102,7 @@ static DECLARE_WAIT_QUEUE_HEAD(kapmd_wait); static DEFINE_SPINLOCK(kapmd_queue_lock); static struct apm_queue kapmd_queue; +static DEFINE_MUTEX(state_lock); static const char driver_version[] = "1.13"; /* no spaces */ @@ -148,38 +150,60 @@ static void queue_add_event(struct apm_queue *q, apm_event_t event) q->events[q->event_head] = event; } -static void queue_event_one_user(struct apm_user *as, apm_event_t event) +static void queue_event(apm_event_t event) { - if (as->suser && as->writer) { - switch (event) { - case APM_SYS_SUSPEND: - case APM_USER_SUSPEND: - /* - * If this user already has a suspend pending, - * don't queue another one. - */ - if (as->suspend_state != SUSPEND_NONE) - return; + struct apm_user *as; - as->suspend_state = SUSPEND_PENDING; - suspends_pending++; - break; - } + down_read(&user_list_lock); + list_for_each_entry(as, &apm_user_list, list) { + if (as->reader) + queue_add_event(&as->queue, event); } - queue_add_event(&as->queue, event); + up_read(&user_list_lock); + wake_up_interruptible(&apm_waitqueue); } -static void queue_event(apm_event_t event, struct apm_user *sender) +/* + * queue_suspend_event - queue an APM suspend event. + * + * Check that we're in a state where we can suspend. If not, + * return -EBUSY. Otherwise, queue an event to all "writer" + * users. If there are no "writer" users, return '1' to + * indicate that we can immediately suspend. + */ +static int queue_suspend_event(apm_event_t event, struct apm_user *sender) { struct apm_user *as; + int ret = 1; + mutex_lock(&state_lock); down_read(&user_list_lock); + + /* + * If a thread is still processing, we can't suspend, so reject + * the request. + */ list_for_each_entry(as, &apm_user_list, list) { - if (as != sender && as->reader) - queue_event_one_user(as, event); + if (as != sender && as->reader && as->writer && as->suser && + as->suspend_state != SUSPEND_NONE) { + ret = -EBUSY; + goto out; + } } + + list_for_each_entry(as, &apm_user_list, list) { + if (as != sender && as->reader && as->writer && as->suser) { + as->suspend_state = SUSPEND_PENDING; + suspends_pending++; + queue_add_event(&as->queue, event); + ret = 0; + } + } + out: up_read(&user_list_lock); + mutex_unlock(&state_lock); wake_up_interruptible(&apm_waitqueue); + return ret; } static void apm_suspend(void) @@ -191,17 +215,22 @@ static void apm_suspend(void) * Anyone on the APM queues will think we're still suspended. * Send a message so everyone knows we're now awake again. */ - queue_event(APM_NORMAL_RESUME, NULL); + queue_event(APM_NORMAL_RESUME); /* * Finally, wake up anyone who is sleeping on the suspend. */ + mutex_lock(&state_lock); down_read(&user_list_lock); list_for_each_entry(as, &apm_user_list, list) { - as->suspend_result = err; - as->suspend_state = SUSPEND_DONE; + if (as->suspend_state == SUSPEND_WAIT || + as->suspend_state == SUSPEND_ACKED) { + as->suspend_result = err; + as->suspend_state = SUSPEND_DONE; + } } up_read(&user_list_lock); + mutex_unlock(&state_lock); wake_up(&apm_suspend_waitqueue); } @@ -227,8 +256,11 @@ static ssize_t apm_read(struct file *fp, char __user *buf, size_t count, loff_t if (copy_to_user(buf, &event, sizeof(event))) break; - if (event == APM_SYS_SUSPEND || event == APM_USER_SUSPEND) + mutex_lock(&state_lock); + if (as->suspend_state == SUSPEND_PENDING && + (event == APM_SYS_SUSPEND || event == APM_USER_SUSPEND)) as->suspend_state = SUSPEND_READ; + mutex_unlock(&state_lock); buf += sizeof(event); i -= sizeof(event); @@ -270,9 +302,13 @@ apm_ioctl(struct inode * inode, struct file *filp, u_int cmd, u_long arg) switch (cmd) { case APM_IOC_SUSPEND: + mutex_lock(&state_lock); + as->suspend_result = -EINTR; if (as->suspend_state == SUSPEND_READ) { + int pending; + /* * If we read a suspend command from /dev/apm_bios, * then the corresponding APM_IOC_SUSPEND ioctl is @@ -280,47 +316,73 @@ apm_ioctl(struct inode * inode, struct file *filp, u_int cmd, u_long arg) */ as->suspend_state = SUSPEND_ACKED; suspends_pending--; + pending = suspends_pending == 0; + mutex_unlock(&state_lock); + + /* + * If there are no further acknowledges required, + * suspend the system. + */ + if (pending) + apm_suspend(); + + /* + * Wait for the suspend/resume to complete. If there + * are pending acknowledges, we wait here for them. + * + * Note: we need to ensure that the PM subsystem does + * not kick us out of the wait when it suspends the + * threads. + */ + flags = current->flags; + current->flags |= PF_NOFREEZE; + + wait_event(apm_suspend_waitqueue, + as->suspend_state == SUSPEND_DONE); } else { + as->suspend_state = SUSPEND_WAIT; + mutex_unlock(&state_lock); + /* * Otherwise it is a request to suspend the system. * Queue an event for all readers, and expect an * acknowledge from all writers who haven't already * acknowledged. */ - queue_event(APM_USER_SUSPEND, as); - } - - /* - * If there are no further acknowledges required, suspend - * the system. - */ - if (suspends_pending == 0) - apm_suspend(); + err = queue_suspend_event(APM_USER_SUSPEND, as); + if (err < 0) { + /* + * Avoid taking the lock here - this + * should be fine. + */ + as->suspend_state = SUSPEND_NONE; + break; + } + + if (err > 0) + apm_suspend(); - /* - * Wait for the suspend/resume to complete. If there are - * pending acknowledges, we wait here for them. - * - * Note that we need to ensure that the PM subsystem does - * not kick us out of the wait when it suspends the threads. - */ - flags = current->flags; - current->flags |= PF_NOFREEZE; + /* + * Wait for the suspend/resume to complete. If there + * are pending acknowledges, we wait here for them. + * + * Note: we need to ensure that the PM subsystem does + * not kick us out of the wait when it suspends the + * threads. + */ + flags = current->flags; + current->flags |= PF_NOFREEZE; - /* - * Note: do not allow a thread which is acking the suspend - * to escape until the resume is complete. - */ - if (as->suspend_state == SUSPEND_ACKED) - wait_event(apm_suspend_waitqueue, - as->suspend_state == SUSPEND_DONE); - else wait_event_interruptible(apm_suspend_waitqueue, as->suspend_state == SUSPEND_DONE); + } current->flags = flags; + + mutex_lock(&state_lock); err = as->suspend_result; as->suspend_state = SUSPEND_NONE; + mutex_unlock(&state_lock); break; } @@ -330,6 +392,8 @@ apm_ioctl(struct inode * inode, struct file *filp, u_int cmd, u_long arg) static int apm_release(struct inode * inode, struct file * filp) { struct apm_user *as = filp->private_data; + int pending = 0; + filp->private_data = NULL; down_write(&user_list_lock); @@ -342,11 +406,14 @@ static int apm_release(struct inode * inode, struct file * filp) * need to balance suspends_pending, which means the * possibility of sleeping. */ + mutex_lock(&state_lock); if (as->suspend_state != SUSPEND_NONE) { suspends_pending -= 1; - if (suspends_pending == 0) - apm_suspend(); + pending = suspends_pending == 0; } + mutex_unlock(&state_lock); + if (pending) + apm_suspend(); kfree(as); return 0; @@ -470,6 +537,7 @@ static int kapmd(void *arg) { do { apm_event_t event; + int ret; wait_event_interruptible(kapmd_wait, !queue_empty(&kapmd_queue) || kthread_should_stop()); @@ -489,13 +557,20 @@ static int kapmd(void *arg) case APM_LOW_BATTERY: case APM_POWER_STATUS_CHANGE: - queue_event(event, NULL); + queue_event(event); break; case APM_USER_SUSPEND: case APM_SYS_SUSPEND: - queue_event(event, NULL); - if (suspends_pending == 0) + ret = queue_suspend_event(event, NULL); + if (ret < 0) { + /* + * We were busy. Try again in 50ms. + */ + queue_add_event(&kapmd_queue, event); + msleep(50); + } + if (ret > 0) apm_suspend(); break; diff --git a/trunk/arch/arm/kernel/asm-offsets.c b/trunk/arch/arm/kernel/asm-offsets.c index cc2d58d028e1..3c078e346753 100644 --- a/trunk/arch/arm/kernel/asm-offsets.c +++ b/trunk/arch/arm/kernel/asm-offsets.c @@ -15,6 +15,7 @@ #include #include #include +#include /* * Make sure that the compiler and target are compatible. diff --git a/trunk/arch/arm/kernel/ecard.c b/trunk/arch/arm/kernel/ecard.c index b27513a0f11e..a786f769035d 100644 --- a/trunk/arch/arm/kernel/ecard.c +++ b/trunk/arch/arm/kernel/ecard.c @@ -529,7 +529,7 @@ static void ecard_dump_irq_state(void) } } -static void ecard_check_lockup(struct irqdesc *desc) +static void ecard_check_lockup(struct irq_desc *desc) { static unsigned long last; static int lockup; @@ -567,7 +567,7 @@ static void ecard_check_lockup(struct irqdesc *desc) } static void -ecard_irq_handler(unsigned int irq, struct irqdesc *desc) +ecard_irq_handler(unsigned int irq, struct irq_desc *desc) { ecard_t *ec; int called = 0; @@ -585,7 +585,7 @@ ecard_irq_handler(unsigned int irq, struct irqdesc *desc) pending = ecard_default_ops.irqpending(ec); if (pending) { - struct irqdesc *d = irq_desc + ec->irq; + struct irq_desc *d = irq_desc + ec->irq; desc_handle_irq(ec->irq, d); called ++; } @@ -609,7 +609,7 @@ static unsigned char first_set[] = }; static void -ecard_irqexp_handler(unsigned int irq, struct irqdesc *desc) +ecard_irqexp_handler(unsigned int irq, struct irq_desc *desc) { const unsigned int statusmask = 15; unsigned int status; @@ -1022,7 +1022,7 @@ ecard_probe(int slot, card_type_t type) if (slot < 8) { ec->irq = 32 + slot; set_irq_chip(ec->irq, &ecard_chip); - set_irq_handler(ec->irq, do_level_IRQ); + set_irq_handler(ec->irq, handle_level_irq); set_irq_flags(ec->irq, IRQF_VALID); } diff --git a/trunk/arch/arm/kernel/entry-armv.S b/trunk/arch/arm/kernel/entry-armv.S index bd623b73445f..2db42b18f53f 100644 --- a/trunk/arch/arm/kernel/entry-armv.S +++ b/trunk/arch/arm/kernel/entry-armv.S @@ -589,10 +589,6 @@ ENTRY(__switch_to) strex r5, r4, [ip] @ Clear exclusive monitor #endif #endif -#if defined(CONFIG_CPU_XSCALE) && !defined(CONFIG_IWMMXT) - mra r4, r5, acc0 - stmia ip, {r4, r5} -#endif #if defined(CONFIG_HAS_TLS_REG) mcr p15, 0, r3, c13, c0, 3 @ set TLS register #elif !defined(CONFIG_TLS_REG_EMUL) @@ -601,11 +597,6 @@ ENTRY(__switch_to) #endif #ifdef CONFIG_MMU mcr p15, 0, r6, c3, c0, 0 @ Set domain register -#endif -#if defined(CONFIG_CPU_XSCALE) && !defined(CONFIG_IWMMXT) - add r4, r2, #TI_CPU_DOMAIN + 40 @ cpu_context_save->extra - ldmib r4, {r4, r5} - mar acc0, r4, r5 #endif mov r5, r0 add r4, r2, #TI_CPU_SAVE diff --git a/trunk/arch/arm/kernel/head-nommu.S b/trunk/arch/arm/kernel/head-nommu.S index f359a189dcf2..0119c0d5f978 100644 --- a/trunk/arch/arm/kernel/head-nommu.S +++ b/trunk/arch/arm/kernel/head-nommu.S @@ -16,7 +16,6 @@ #include #include -#include #include #include #include diff --git a/trunk/arch/arm/kernel/head.S b/trunk/arch/arm/kernel/head.S index ebc3e74a7947..bda0748ffb00 100644 --- a/trunk/arch/arm/kernel/head.S +++ b/trunk/arch/arm/kernel/head.S @@ -16,7 +16,6 @@ #include #include -#include #include #include #include diff --git a/trunk/arch/arm/kernel/irq.c b/trunk/arch/arm/kernel/irq.c index 2c4ff1cbe334..ec01f08f5642 100644 --- a/trunk/arch/arm/kernel/irq.c +++ b/trunk/arch/arm/kernel/irq.c @@ -112,7 +112,7 @@ static struct irq_desc bad_irq_desc = { asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs) { struct pt_regs *old_regs = set_irq_regs(regs); - struct irqdesc *desc = irq_desc + irq; + struct irq_desc *desc = irq_desc + irq; /* * Some hardware gives randomly wrong interrupts. Rather @@ -134,7 +134,7 @@ asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs) void set_irq_flags(unsigned int irq, unsigned int iflags) { - struct irqdesc *desc; + struct irq_desc *desc; unsigned long flags; if (irq >= NR_IRQS) { @@ -171,7 +171,7 @@ void __init init_IRQ(void) #ifdef CONFIG_HOTPLUG_CPU -static void route_irq(struct irqdesc *desc, unsigned int irq, unsigned int cpu) +static void route_irq(struct irq_desc *desc, unsigned int irq, unsigned int cpu) { pr_debug("IRQ%u: moving from cpu%u to cpu%u\n", irq, desc->cpu, cpu); @@ -190,7 +190,7 @@ void migrate_irqs(void) unsigned int i, cpu = smp_processor_id(); for (i = 0; i < NR_IRQS; i++) { - struct irqdesc *desc = irq_desc + i; + struct irq_desc *desc = irq_desc + i; if (desc->cpu == cpu) { unsigned int newcpu = any_online_cpu(desc->affinity); diff --git a/trunk/arch/arm/kernel/iwmmxt-notifier.c b/trunk/arch/arm/kernel/iwmmxt-notifier.c deleted file mode 100644 index 0d1a1db40062..000000000000 --- a/trunk/arch/arm/kernel/iwmmxt-notifier.c +++ /dev/null @@ -1,63 +0,0 @@ -/* - * linux/arch/arm/kernel/iwmmxt-notifier.c - * - * XScale iWMMXt (Concan) context switching and handling - * - * Initial code: - * Copyright (c) 2003, Intel Corporation - * - * Full lazy switching support, optimizations and more, by Nicolas Pitre - * Copyright (c) 2003-2004, MontaVista Software, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -static int iwmmxt_do(struct notifier_block *self, unsigned long cmd, void *t) -{ - struct thread_info *thread = t; - - switch (cmd) { - case THREAD_NOTIFY_FLUSH: - /* - * flush_thread() zeroes thread->fpstate, so no need - * to do anything here. - * - * FALLTHROUGH: Ensure we don't try to overwrite our newly - * initialised state information on the first fault. - */ - - case THREAD_NOTIFY_RELEASE: - iwmmxt_task_release(thread); - break; - - case THREAD_NOTIFY_SWITCH: - iwmmxt_task_switch(thread); - break; - } - - return NOTIFY_DONE; -} - -static struct notifier_block iwmmxt_notifier_block = { - .notifier_call = iwmmxt_do, -}; - -static int __init iwmmxt_init(void) -{ - thread_register_notifier(&iwmmxt_notifier_block); - - return 0; -} - -late_initcall(iwmmxt_init); diff --git a/trunk/arch/arm/kernel/process.c b/trunk/arch/arm/kernel/process.c index bf35c178a877..a9e8f7e55fd6 100644 --- a/trunk/arch/arm/kernel/process.c +++ b/trunk/arch/arm/kernel/process.c @@ -280,67 +280,6 @@ void show_fpregs(struct user_fp *regs) (unsigned long)regs->fpcr); } -/* - * Task structure and kernel stack allocation. - */ -struct thread_info_list { - unsigned long *head; - unsigned int nr; -}; - -static DEFINE_PER_CPU(struct thread_info_list, thread_info_list) = { NULL, 0 }; - -#define EXTRA_TASK_STRUCT 4 - -struct thread_info *alloc_thread_info(struct task_struct *task) -{ - struct thread_info *thread = NULL; - - if (EXTRA_TASK_STRUCT) { - struct thread_info_list *th = &get_cpu_var(thread_info_list); - unsigned long *p = th->head; - - if (p) { - th->head = (unsigned long *)p[0]; - th->nr -= 1; - } - put_cpu_var(thread_info_list); - - thread = (struct thread_info *)p; - } - - if (!thread) - thread = (struct thread_info *) - __get_free_pages(GFP_KERNEL, THREAD_SIZE_ORDER); - -#ifdef CONFIG_DEBUG_STACK_USAGE - /* - * The stack must be cleared if you want SYSRQ-T to - * give sensible stack usage information - */ - if (thread) - memzero(thread, THREAD_SIZE); -#endif - return thread; -} - -void free_thread_info(struct thread_info *thread) -{ - if (EXTRA_TASK_STRUCT) { - struct thread_info_list *th = &get_cpu_var(thread_info_list); - if (th->nr < EXTRA_TASK_STRUCT) { - unsigned long *p = (unsigned long *)thread; - p[0] = (unsigned long)th->head; - th->head = p; - th->nr += 1; - put_cpu_var(thread_info_list); - return; - } - put_cpu_var(thread_info_list); - } - free_pages((unsigned long)thread, THREAD_SIZE_ORDER); -} - /* * Free current thread data structures etc.. */ diff --git a/trunk/arch/arm/kernel/setup.c b/trunk/arch/arm/kernel/setup.c index 29efc9f82057..238dd9b6db84 100644 --- a/trunk/arch/arm/kernel/setup.c +++ b/trunk/arch/arm/kernel/setup.c @@ -357,9 +357,6 @@ static void __init setup_processor(void) #ifndef CONFIG_VFP elf_hwcap &= ~HWCAP_VFP; #endif -#ifndef CONFIG_IWMMXT - elf_hwcap &= ~HWCAP_IWMMXT; -#endif cpu_proc_init(); } @@ -441,16 +438,19 @@ __early_param("initrd=", early_initrd); static void __init arm_add_memory(unsigned long start, unsigned long size) { + struct membank *bank; + /* * Ensure that start/size are aligned to a page boundary. * Size is appropriately rounded down, start is rounded up. */ size -= start & ~PAGE_MASK; - meminfo.bank[meminfo.nr_banks].start = PAGE_ALIGN(start); - meminfo.bank[meminfo.nr_banks].size = size & PAGE_MASK; - meminfo.bank[meminfo.nr_banks].node = PHYS_TO_NID(start); - meminfo.nr_banks += 1; + bank = &meminfo.bank[meminfo.nr_banks++]; + + bank->start = PAGE_ALIGN(start); + bank->size = size & PAGE_MASK; + bank->node = PHYS_TO_NID(start); } /* diff --git a/trunk/arch/arm/kernel/signal.c b/trunk/arch/arm/kernel/signal.c index 48cf7fffddf2..3843d3bab2dd 100644 --- a/trunk/arch/arm/kernel/signal.c +++ b/trunk/arch/arm/kernel/signal.c @@ -11,7 +11,9 @@ #include #include #include +#include +#include #include #include #include diff --git a/trunk/arch/arm/kernel/traps.c b/trunk/arch/arm/kernel/traps.c index bede380c07a9..042a12982e98 100644 --- a/trunk/arch/arm/kernel/traps.c +++ b/trunk/arch/arm/kernel/traps.c @@ -631,12 +631,9 @@ baddataabort(int code, unsigned long instr, struct pt_regs *regs) notify_die("unknown data abort code", regs, &info, instr, 0); } -void __attribute__((noreturn)) __bug(const char *file, int line, void *data) +void __attribute__((noreturn)) __bug(const char *file, int line) { - printk(KERN_CRIT"kernel BUG at %s:%d!", file, line); - if (data) - printk(" - extra data = %p", data); - printk("\n"); + printk(KERN_CRIT"kernel BUG at %s:%d!\n", file, line); *(int *)0 = 0; /* Avoid "noreturn function does return" */ diff --git a/trunk/arch/arm/kernel/xscale-cp0.c b/trunk/arch/arm/kernel/xscale-cp0.c new file mode 100644 index 000000000000..180000bfdc8f --- /dev/null +++ b/trunk/arch/arm/kernel/xscale-cp0.c @@ -0,0 +1,179 @@ +/* + * linux/arch/arm/kernel/xscale-cp0.c + * + * XScale DSP and iWMMXt coprocessor context switching and handling + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static inline void dsp_save_state(u32 *state) +{ + __asm__ __volatile__ ( + "mrrc p0, 0, %0, %1, c0\n" + : "=r" (state[0]), "=r" (state[1])); +} + +static inline void dsp_load_state(u32 *state) +{ + __asm__ __volatile__ ( + "mcrr p0, 0, %0, %1, c0\n" + : : "r" (state[0]), "r" (state[1])); +} + +static int dsp_do(struct notifier_block *self, unsigned long cmd, void *t) +{ + struct thread_info *thread = t; + + switch (cmd) { + case THREAD_NOTIFY_FLUSH: + thread->cpu_context.extra[0] = 0; + thread->cpu_context.extra[1] = 0; + break; + + case THREAD_NOTIFY_SWITCH: + dsp_save_state(current_thread_info()->cpu_context.extra); + dsp_load_state(thread->cpu_context.extra); + break; + } + + return NOTIFY_DONE; +} + +static struct notifier_block dsp_notifier_block = { + .notifier_call = dsp_do, +}; + + +#ifdef CONFIG_IWMMXT +static int iwmmxt_do(struct notifier_block *self, unsigned long cmd, void *t) +{ + struct thread_info *thread = t; + + switch (cmd) { + case THREAD_NOTIFY_FLUSH: + /* + * flush_thread() zeroes thread->fpstate, so no need + * to do anything here. + * + * FALLTHROUGH: Ensure we don't try to overwrite our newly + * initialised state information on the first fault. + */ + + case THREAD_NOTIFY_RELEASE: + iwmmxt_task_release(thread); + break; + + case THREAD_NOTIFY_SWITCH: + iwmmxt_task_switch(thread); + break; + } + + return NOTIFY_DONE; +} + +static struct notifier_block iwmmxt_notifier_block = { + .notifier_call = iwmmxt_do, +}; +#endif + + +static u32 __init xscale_cp_access_read(void) +{ + u32 value; + + __asm__ __volatile__ ( + "mrc p15, 0, %0, c15, c1, 0\n\t" + : "=r" (value)); + + return value; +} + +static void __init xscale_cp_access_write(u32 value) +{ + u32 temp; + + __asm__ __volatile__ ( + "mcr p15, 0, %1, c15, c1, 0\n\t" + "mrc p15, 0, %0, c15, c1, 0\n\t" + "mov %0, %0\n\t" + "sub pc, pc, #4\n\t" + : "=r" (temp) : "r" (value)); +} + +/* + * Detect whether we have a MAC coprocessor (40 bit register) or an + * iWMMXt coprocessor (64 bit registers) by loading 00000100:00000000 + * into a coprocessor register and reading it back, and checking + * whether the upper word survived intact. + */ +static int __init cpu_has_iwmmxt(void) +{ + u32 lo; + u32 hi; + + /* + * This sequence is interpreted by the DSP coprocessor as: + * mar acc0, %2, %3 + * mra %0, %1, acc0 + * + * And by the iWMMXt coprocessor as: + * tmcrr wR0, %2, %3 + * tmrrc %0, %1, wR0 + */ + __asm__ __volatile__ ( + "mcrr p0, 0, %2, %3, c0\n" + "mrrc p0, 0, %0, %1, c0\n" + : "=r" (lo), "=r" (hi) + : "r" (0), "r" (0x100)); + + return !!hi; +} + + +/* + * If we detect that the CPU has iWMMXt (and CONFIG_IWMMXT=y), we + * disable CP0/CP1 on boot, and let call_fpe() and the iWMMXt lazy + * switch code handle iWMMXt context switching. If on the other + * hand the CPU has a DSP coprocessor, we keep access to CP0 enabled + * all the time, and save/restore acc0 on context switch in non-lazy + * fashion. + */ +static int __init xscale_cp0_init(void) +{ + u32 cp_access; + + cp_access = xscale_cp_access_read() & ~3; + xscale_cp_access_write(cp_access | 1); + + if (cpu_has_iwmmxt()) { +#ifndef CONFIG_IWMMXT + printk(KERN_WARNING "CAUTION: XScale iWMMXt coprocessor " + "detected, but kernel support is missing.\n"); +#else + printk(KERN_INFO "XScale iWMMXt coprocessor detected.\n"); + elf_hwcap |= HWCAP_IWMMXT; + thread_register_notifier(&iwmmxt_notifier_block); +#endif + } else { + printk(KERN_INFO "XScale DSP coprocessor detected.\n"); + thread_register_notifier(&dsp_notifier_block); + cp_access |= 1; + } + + xscale_cp_access_write(cp_access); + + return 0; +} + +late_initcall(xscale_cp0_init); diff --git a/trunk/arch/arm/mach-aaec2000/core.c b/trunk/arch/arm/mach-aaec2000/core.c index fe3d297d682d..a950160fcfb6 100644 --- a/trunk/arch/arm/mach-aaec2000/core.c +++ b/trunk/arch/arm/mach-aaec2000/core.c @@ -82,7 +82,7 @@ static void aaec2000_int_unmask(unsigned int irq) IRQ_INTENS |= (1 << irq); } -static struct irqchip aaec2000_irq_chip = { +static struct irq_chip aaec2000_irq_chip = { .ack = aaec2000_int_ack, .mask = aaec2000_int_mask, .unmask = aaec2000_int_unmask, @@ -93,7 +93,7 @@ void __init aaec2000_init_irq(void) unsigned int i; for (i = 0; i < NR_IRQS; i++) { - set_irq_handler(i, do_level_IRQ); + set_irq_handler(i, handle_level_irq); set_irq_chip(i, &aaec2000_irq_chip); set_irq_flags(i, IRQF_VALID); } diff --git a/trunk/arch/arm/mach-at91rm9200/Kconfig b/trunk/arch/arm/mach-at91rm9200/Kconfig index 2f85e8693b1b..9f11db8af233 100644 --- a/trunk/arch/arm/mach-at91rm9200/Kconfig +++ b/trunk/arch/arm/mach-at91rm9200/Kconfig @@ -2,7 +2,8 @@ if ARCH_AT91 menu "Atmel AT91 System-on-Chip" -comment "Atmel AT91 Processors" +choice + prompt "Atmel AT91 Processor" config ARCH_AT91RM9200 bool "AT91RM9200" @@ -13,6 +14,8 @@ config ARCH_AT91SAM9260 config ARCH_AT91SAM9261 bool "AT91SAM9261" +endchoice + # ---------------------------------------------------------- if ARCH_AT91RM9200 @@ -33,7 +36,6 @@ config ARCH_AT91RM9200DK Select this if you are using Atmel's AT91RM9200-DK Development board. (Discontinued) - config MACH_AT91RM9200EK bool "Atmel AT91RM9200-EK Evaluation Kit" depends on ARCH_AT91RM9200 @@ -90,6 +92,13 @@ if ARCH_AT91SAM9260 comment "AT91SAM9260 Board Type" +config MACH_AT91SAM9260EK + bool "Atmel AT91SAM9260-EK Evaluation Kit" + depends on ARCH_AT91SAM9260 + help + Select this if you are using Atmel's AT91SAM9260-EK Evaluation Kit. + + endif # ---------------------------------------------------------- @@ -98,8 +107,31 @@ if ARCH_AT91SAM9261 comment "AT91SAM9261 Board Type" +config MACH_AT91SAM9261EK + bool "Atmel AT91SAM9261-EK Evaluation Kit" + depends on ARCH_AT91SAM9261 + help + Select this if you are using Atmel's AT91SAM9261-EK Evaluation Kit. + + endif +# ---------------------------------------------------------- + +comment "AT91 Board Options" + +config MTD_AT91_DATAFLASH_CARD + bool "Enable DataFlash Card support" + depends on (ARCH_AT91RM9200DK || MACH_AT91RM9200EK || MACH_AT91SAM9260EK || MACH_AT91SAM9261EK) + help + Enable support for the DataFlash card. + +config MTD_NAND_AT91_BUSWIDTH_16 + bool "Enable 16-bit data bus interface to NAND flash" + depends on (MACH_AT91SAM9261EK || MACH_AT91SAM9260EK) + help + On AT91SAM926x boards both types of NAND flash can be present + (8 and 16 bit data bus width). # ---------------------------------------------------------- diff --git a/trunk/arch/arm/mach-at91rm9200/Makefile b/trunk/arch/arm/mach-at91rm9200/Makefile index c174805c24e5..cf777007847a 100644 --- a/trunk/arch/arm/mach-at91rm9200/Makefile +++ b/trunk/arch/arm/mach-at91rm9200/Makefile @@ -2,7 +2,7 @@ # Makefile for the linux kernel. # -obj-y := clock.o irq.o gpio.o devices.o +obj-y := clock.o irq.o gpio.o obj-m := obj-n := obj- := @@ -10,11 +10,11 @@ obj- := obj-$(CONFIG_PM) += pm.o # CPU-specific support -obj-$(CONFIG_ARCH_AT91RM9200) += at91rm9200.o at91rm9200_time.o -obj-$(CONFIG_ARCH_AT91SAM9260) += -obj-$(CONFIG_ARCH_AT91SAM9261) += +obj-$(CONFIG_ARCH_AT91RM9200) += at91rm9200.o at91rm9200_time.o at91rm9200_devices.o +obj-$(CONFIG_ARCH_AT91SAM9260) += at91sam9260.o at91sam926x_time.o at91sam9260_devices.o +obj-$(CONFIG_ARCH_AT91SAM9261) += at91sam9261.o at91sam926x_time.o at91sam9261_devices.o -# AT91RM9200 Board-specific support +# AT91RM9200 board-specific support obj-$(CONFIG_MACH_ONEARM) += board-1arm.o obj-$(CONFIG_ARCH_AT91RM9200DK) += board-dk.o obj-$(CONFIG_MACH_AT91RM9200EK) += board-ek.o @@ -26,8 +26,10 @@ obj-$(CONFIG_MACH_ATEB9200) += board-eb9200.o obj-$(CONFIG_MACH_KAFA) += board-kafa.o # AT91SAM9260 board-specific support +obj-$(CONFIG_MACH_AT91SAM9260EK) += board-sam9260ek.o # AT91SAM9261 board-specific support +obj-$(CONFIG_MACH_AT91SAM9261EK) += board-sam9261ek.o # LEDs support led-$(CONFIG_ARCH_AT91RM9200DK) += leds.o diff --git a/trunk/arch/arm/mach-at91rm9200/at91rm9200.c b/trunk/arch/arm/mach-at91rm9200/at91rm9200.c index dcf6136fedf9..a92e9a495b07 100644 --- a/trunk/arch/arm/mach-at91rm9200/at91rm9200.c +++ b/trunk/arch/arm/mach-at91rm9200/at91rm9200.c @@ -14,8 +14,10 @@ #include #include +#include +#include +#include -#include #include "generic.h" #include "clock.h" @@ -25,33 +27,13 @@ static struct map_desc at91rm9200_io_desc[] __initdata = { .pfn = __phys_to_pfn(AT91_BASE_SYS), .length = SZ_4K, .type = MT_DEVICE, - }, { - .virtual = AT91_VA_BASE_SPI, - .pfn = __phys_to_pfn(AT91RM9200_BASE_SPI), - .length = SZ_16K, - .type = MT_DEVICE, }, { .virtual = AT91_VA_BASE_EMAC, .pfn = __phys_to_pfn(AT91RM9200_BASE_EMAC), .length = SZ_16K, .type = MT_DEVICE, }, { - .virtual = AT91_VA_BASE_TWI, - .pfn = __phys_to_pfn(AT91RM9200_BASE_TWI), - .length = SZ_16K, - .type = MT_DEVICE, - }, { - .virtual = AT91_VA_BASE_MCI, - .pfn = __phys_to_pfn(AT91RM9200_BASE_MCI), - .length = SZ_16K, - .type = MT_DEVICE, - }, { - .virtual = AT91_VA_BASE_UDP, - .pfn = __phys_to_pfn(AT91RM9200_BASE_UDP), - .length = SZ_16K, - .type = MT_DEVICE, - }, { - .virtual = AT91_SRAM_VIRT_BASE, + .virtual = AT91_IO_VIRT_BASE - AT91RM9200_SRAM_SIZE, .pfn = __phys_to_pfn(AT91RM9200_SRAM_BASE), .length = AT91RM9200_SRAM_SIZE, .type = MT_DEVICE, @@ -222,6 +204,16 @@ static struct at91_gpio_bank at91rm9200_gpio[] = { } }; +static void at91rm9200_reset(void) +{ + /* + * Perform a hardware reset with the use of the Watchdog timer. + */ + at91_sys_write(AT91_ST_WDMR, AT91_ST_RSTEN | AT91_ST_EXTEN | 1); + at91_sys_write(AT91_ST_CR, AT91_ST_WDRST); +} + + /* -------------------------------------------------------------------- * AT91RM9200 processor initialization * -------------------------------------------------------------------- */ @@ -230,6 +222,12 @@ void __init at91rm9200_initialize(unsigned long main_clock, unsigned short banks /* Map peripherals */ iotable_init(at91rm9200_io_desc, ARRAY_SIZE(at91rm9200_io_desc)); + at91_arch_reset = at91rm9200_reset; + at91_extern_irq = (1 << AT91RM9200_ID_IRQ0) | (1 << AT91RM9200_ID_IRQ1) + | (1 << AT91RM9200_ID_IRQ2) | (1 << AT91RM9200_ID_IRQ3) + | (1 << AT91RM9200_ID_IRQ4) | (1 << AT91RM9200_ID_IRQ5) + | (1 << AT91RM9200_ID_IRQ6); + /* Init clock subsystem */ at91_clock_init(main_clock); diff --git a/trunk/arch/arm/mach-at91rm9200/devices.c b/trunk/arch/arm/mach-at91rm9200/at91rm9200_devices.c similarity index 83% rename from trunk/arch/arm/mach-at91rm9200/devices.c rename to trunk/arch/arm/mach-at91rm9200/at91rm9200_devices.c index 059824376629..4641b99db0ee 100644 --- a/trunk/arch/arm/mach-at91rm9200/devices.c +++ b/trunk/arch/arm/mach-at91rm9200/at91rm9200_devices.c @@ -1,5 +1,5 @@ /* - * arch/arm/mach-at91rm9200/devices.c + * arch/arm/mach-at91rm9200/at91rm9200_devices.c * * Copyright (C) 2005 Thibaut VARENE * Copyright (C) 2005 David Brownell @@ -15,9 +15,10 @@ #include -#include #include #include +#include +#include #include "generic.h" @@ -33,7 +34,7 @@ static u64 ohci_dmamask = 0xffffffffUL; static struct at91_usbh_data usbh_data; -static struct resource at91_usbh_resources[] = { +static struct resource usbh_resources[] = { [0] = { .start = AT91RM9200_UHP_BASE, .end = AT91RM9200_UHP_BASE + SZ_1M - 1, @@ -54,8 +55,8 @@ static struct platform_device at91rm9200_usbh_device = { .coherent_dma_mask = 0xffffffff, .platform_data = &usbh_data, }, - .resource = at91_usbh_resources, - .num_resources = ARRAY_SIZE(at91_usbh_resources), + .resource = usbh_resources, + .num_resources = ARRAY_SIZE(usbh_resources), }; void __init at91_add_device_usbh(struct at91_usbh_data *data) @@ -78,7 +79,7 @@ void __init at91_add_device_usbh(struct at91_usbh_data *data) {} #ifdef CONFIG_USB_GADGET_AT91 static struct at91_udc_data udc_data; -static struct resource at91_udc_resources[] = { +static struct resource udc_resources[] = { [0] = { .start = AT91RM9200_BASE_UDP, .end = AT91RM9200_BASE_UDP + SZ_16K - 1, @@ -97,8 +98,8 @@ static struct platform_device at91rm9200_udc_device = { .dev = { .platform_data = &udc_data, }, - .resource = at91_udc_resources, - .num_resources = ARRAY_SIZE(at91_udc_resources), + .resource = udc_resources, + .num_resources = ARRAY_SIZE(udc_resources), }; void __init at91_add_device_udc(struct at91_udc_data *data) @@ -129,7 +130,7 @@ void __init at91_add_device_udc(struct at91_udc_data *data) {} static u64 eth_dmamask = 0xffffffffUL; static struct at91_eth_data eth_data; -static struct resource at91_eth_resources[] = { +static struct resource eth_resources[] = { [0] = { .start = AT91_VA_BASE_EMAC, .end = AT91_VA_BASE_EMAC + SZ_16K - 1, @@ -150,8 +151,8 @@ static struct platform_device at91rm9200_eth_device = { .coherent_dma_mask = 0xffffffff, .platform_data = ð_data, }, - .resource = at91_eth_resources, - .num_resources = ARRAY_SIZE(at91_eth_resources), + .resource = eth_resources, + .num_resources = ARRAY_SIZE(eth_resources), }; void __init at91_add_device_eth(struct at91_eth_data *data) @@ -202,11 +203,13 @@ void __init at91_add_device_eth(struct at91_eth_data *data) {} #if defined(CONFIG_AT91_CF) || defined(CONFIG_AT91_CF_MODULE) static struct at91_cf_data cf_data; -static struct resource at91_cf_resources[] = { +#define CF_BASE AT91_CHIPSELECT_4 + +static struct resource cf_resources[] = { [0] = { - .start = AT91_CF_BASE, + .start = CF_BASE, /* ties up CS4, CS5 and CS6 */ - .end = AT91_CF_BASE + (0x30000000 - 1), + .end = CF_BASE + (0x30000000 - 1), .flags = IORESOURCE_MEM | IORESOURCE_MEM_8AND16BIT, }, }; @@ -217,15 +220,38 @@ static struct platform_device at91rm9200_cf_device = { .dev = { .platform_data = &cf_data, }, - .resource = at91_cf_resources, - .num_resources = ARRAY_SIZE(at91_cf_resources), + .resource = cf_resources, + .num_resources = ARRAY_SIZE(cf_resources), }; void __init at91_add_device_cf(struct at91_cf_data *data) { + unsigned int csa; + if (!data) return; + data->chipselect = 4; /* can only use EBI ChipSelect 4 */ + + /* CF takes over CS4, CS5, CS6 */ + csa = at91_sys_read(AT91_EBI_CSA); + at91_sys_write(AT91_EBI_CSA, csa | AT91_EBI_CS4A_SMC_COMPACTFLASH); + + /* + * Static memory controller timing adjustments. + * REVISIT: these timings are in terms of MCK cycles, so + * when MCK changes (cpufreq etc) so must these values... + */ + at91_sys_write(AT91_SMC_CSR(4), + AT91_SMC_ACSS_STD + | AT91_SMC_DBW_16 + | AT91_SMC_BAT + | AT91_SMC_WSEN + | AT91_SMC_NWS_(32) /* wait states */ + | AT91_SMC_RWSETUP_(6) /* setup time */ + | AT91_SMC_RWHOLD_(4) /* hold time */ + ); + /* input/irq */ if (data->irq_pin) { at91_set_gpio_input(data->irq_pin, 1); @@ -245,6 +271,9 @@ void __init at91_add_device_cf(struct at91_cf_data *data) at91_set_A_periph(AT91_PIN_PC11, 0); /* NCS5/CFCE1 */ at91_set_A_periph(AT91_PIN_PC12, 0); /* NCS6/CFCE2 */ + /* nWAIT is _not_ a default setting */ + at91_set_A_periph(AT91_PIN_PC6, 1); /* nWAIT */ + cf_data = *data; platform_device_register(&at91rm9200_cf_device); } @@ -257,11 +286,11 @@ void __init at91_add_device_cf(struct at91_cf_data *data) {} * MMC / SD * -------------------------------------------------------------------- */ -#if defined(CONFIG_MMC_AT91RM9200) || defined(CONFIG_MMC_AT91RM9200_MODULE) +#if defined(CONFIG_MMC_AT91) || defined(CONFIG_MMC_AT91_MODULE) static u64 mmc_dmamask = 0xffffffffUL; static struct at91_mmc_data mmc_data; -static struct resource at91_mmc_resources[] = { +static struct resource mmc_resources[] = { [0] = { .start = AT91RM9200_BASE_MCI, .end = AT91RM9200_BASE_MCI + SZ_16K - 1, @@ -282,8 +311,8 @@ static struct platform_device at91rm9200_mmc_device = { .coherent_dma_mask = 0xffffffff, .platform_data = &mmc_data, }, - .resource = at91_mmc_resources, - .num_resources = ARRAY_SIZE(at91_mmc_resources), + .resource = mmc_resources, + .num_resources = ARRAY_SIZE(mmc_resources), }; void __init at91_add_device_mmc(struct at91_mmc_data *data) @@ -298,31 +327,33 @@ void __init at91_add_device_mmc(struct at91_mmc_data *data) } if (data->wp_pin) at91_set_gpio_input(data->wp_pin, 1); + if (data->vcc_pin) + at91_set_gpio_output(data->vcc_pin, 0); /* CLK */ at91_set_A_periph(AT91_PIN_PA27, 0); - if (data->is_b) { + if (data->slot_b) { /* CMD */ - at91_set_B_periph(AT91_PIN_PA8, 0); + at91_set_B_periph(AT91_PIN_PA8, 1); /* DAT0, maybe DAT1..DAT3 */ - at91_set_B_periph(AT91_PIN_PA9, 0); + at91_set_B_periph(AT91_PIN_PA9, 1); if (data->wire4) { - at91_set_B_periph(AT91_PIN_PA10, 0); - at91_set_B_periph(AT91_PIN_PA11, 0); - at91_set_B_periph(AT91_PIN_PA12, 0); + at91_set_B_periph(AT91_PIN_PA10, 1); + at91_set_B_periph(AT91_PIN_PA11, 1); + at91_set_B_periph(AT91_PIN_PA12, 1); } } else { /* CMD */ - at91_set_A_periph(AT91_PIN_PA28, 0); + at91_set_A_periph(AT91_PIN_PA28, 1); /* DAT0, maybe DAT1..DAT3 */ - at91_set_A_periph(AT91_PIN_PA29, 0); + at91_set_A_periph(AT91_PIN_PA29, 1); if (data->wire4) { - at91_set_B_periph(AT91_PIN_PB3, 0); - at91_set_B_periph(AT91_PIN_PB4, 0); - at91_set_B_periph(AT91_PIN_PB5, 0); + at91_set_B_periph(AT91_PIN_PB3, 1); + at91_set_B_periph(AT91_PIN_PB4, 1); + at91_set_B_periph(AT91_PIN_PB5, 1); } } @@ -341,29 +372,45 @@ void __init at91_add_device_mmc(struct at91_mmc_data *data) {} #if defined(CONFIG_MTD_NAND_AT91) || defined(CONFIG_MTD_NAND_AT91_MODULE) static struct at91_nand_data nand_data; -static struct resource at91_nand_resources[] = { +#define NAND_BASE AT91_CHIPSELECT_3 + +static struct resource nand_resources[] = { { - .start = AT91_SMARTMEDIA_BASE, - .end = AT91_SMARTMEDIA_BASE + SZ_8M - 1, + .start = NAND_BASE, + .end = NAND_BASE + SZ_8M - 1, .flags = IORESOURCE_MEM, } }; -static struct platform_device at91_nand_device = { +static struct platform_device at91rm9200_nand_device = { .name = "at91_nand", .id = -1, .dev = { .platform_data = &nand_data, }, - .resource = at91_nand_resources, - .num_resources = ARRAY_SIZE(at91_nand_resources), + .resource = nand_resources, + .num_resources = ARRAY_SIZE(nand_resources), }; void __init at91_add_device_nand(struct at91_nand_data *data) { + unsigned int csa; + if (!data) return; + /* enable the address range of CS3 */ + csa = at91_sys_read(AT91_EBI_CSA); + at91_sys_write(AT91_EBI_CSA, csa | AT91_EBI_CS3A_SMC_SMARTMEDIA); + + /* set the bus interface characteristics */ + at91_sys_write(AT91_SMC_CSR(3), AT91_SMC_ACSS_STD | AT91_SMC_DBW_8 | AT91_SMC_WSEN + | AT91_SMC_NWS_(5) + | AT91_SMC_TDF_(1) + | AT91_SMC_RWSETUP_(0) /* tDS Data Set up Time 30 - ns */ + | AT91_SMC_RWHOLD_(1) /* tDH Data Hold Time 20 - ns */ + ); + /* enable pin */ if (data->enable_pin) at91_set_gpio_output(data->enable_pin, 1); @@ -380,7 +427,7 @@ void __init at91_add_device_nand(struct at91_nand_data *data) at91_set_A_periph(AT91_PIN_PC3, 0); /* SMWE */ nand_data = *data; - platform_device_register(&at91_nand_device); + platform_device_register(&at91rm9200_nand_device); } #else void __init at91_add_device_nand(struct at91_nand_data *data) {} @@ -392,10 +439,25 @@ void __init at91_add_device_nand(struct at91_nand_data *data) {} * -------------------------------------------------------------------- */ #if defined(CONFIG_I2C_AT91) || defined(CONFIG_I2C_AT91_MODULE) + +static struct resource twi_resources[] = { + [0] = { + .start = AT91RM9200_BASE_TWI, + .end = AT91RM9200_BASE_TWI + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91RM9200_ID_TWI, + .end = AT91RM9200_ID_TWI, + .flags = IORESOURCE_IRQ, + }, +}; + static struct platform_device at91rm9200_twi_device = { .name = "at91_i2c", .id = -1, - .num_resources = 0, + .resource = twi_resources, + .num_resources = ARRAY_SIZE(twi_resources), }; void __init at91_add_device_i2c(void) @@ -421,7 +483,7 @@ void __init at91_add_device_i2c(void) {} #if defined(CONFIG_SPI_AT91) || defined(CONFIG_SPI_AT91_MODULE) || defined(CONFIG_AT91_SPI) || defined(CONFIG_AT91_SPI_MODULE) static u64 spi_dmamask = 0xffffffffUL; -static struct resource at91_spi_resources[] = { +static struct resource spi_resources[] = { [0] = { .start = AT91RM9200_BASE_SPI, .end = AT91RM9200_BASE_SPI + SZ_16K - 1, @@ -438,14 +500,14 @@ static struct platform_device at91rm9200_spi_device = { .name = "at91_spi", .id = 0, .dev = { - .dma_mask = &spi_dmamask, - .coherent_dma_mask = 0xffffffff, + .dma_mask = &spi_dmamask, + .coherent_dma_mask = 0xffffffff, }, - .resource = at91_spi_resources, - .num_resources = ARRAY_SIZE(at91_spi_resources), + .resource = spi_resources, + .num_resources = ARRAY_SIZE(spi_resources), }; -static const unsigned at91_spi_standard_cs[4] = { AT91_PIN_PA3, AT91_PIN_PA4, AT91_PIN_PA5, AT91_PIN_PA6 }; +static const unsigned spi_standard_cs[4] = { AT91_PIN_PA3, AT91_PIN_PA4, AT91_PIN_PA5, AT91_PIN_PA6 }; void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) { @@ -461,7 +523,7 @@ void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) if (devices[i].controller_data) cs_pin = (unsigned long) devices[i].controller_data; else - cs_pin = at91_spi_standard_cs[devices[i].chip_select]; + cs_pin = spi_standard_cs[devices[i].chip_select]; #ifdef CONFIG_SPI_AT91_MANUAL_CS at91_set_gpio_output(cs_pin, 1); @@ -474,7 +536,7 @@ void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) } spi_register_board_info(devices, nr_devices); - at91_clock_associate("spi0_clk", &at91rm9200_spi_device.dev, "spi"); + at91_clock_associate("spi_clk", &at91rm9200_spi_device.dev, "spi"); platform_device_register(&at91rm9200_spi_device); } #else @@ -486,7 +548,7 @@ void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) * RTC * -------------------------------------------------------------------- */ -#if defined(CONFIG_RTC_DRV_AT91) || defined(CONFIG_RTC_DRV_AT91_MODULE) +#if defined(CONFIG_RTC_DRV_AT91RM9200) || defined(CONFIG_RTC_DRV_AT91RM9200_MODULE) static struct platform_device at91rm9200_rtc_device = { .name = "at91_rtc", .id = -1, @@ -506,7 +568,7 @@ static void __init at91_add_device_rtc(void) {} * Watchdog * -------------------------------------------------------------------- */ -#if defined(CONFIG_AT91_WATCHDOG) || defined(CONFIG_AT91_WATCHDOG_MODULE) +#if defined(CONFIG_AT91RM9200_WATCHDOG) || defined(CONFIG_AT91RM9200_WATCHDOG_MODULE) static struct platform_device at91rm9200_wdt_device = { .name = "at91_wdt", .id = -1, diff --git a/trunk/arch/arm/mach-at91rm9200/at91rm9200_time.c b/trunk/arch/arm/mach-at91rm9200/at91rm9200_time.c index 07c9cea8961d..b999e192a7e9 100644 --- a/trunk/arch/arm/mach-at91rm9200/at91rm9200_time.c +++ b/trunk/arch/arm/mach-at91rm9200/at91rm9200_time.c @@ -30,6 +30,8 @@ #include #include +#include + static unsigned long last_crtr; /* @@ -99,6 +101,9 @@ void at91rm9200_timer_reset(void) /* Set Period Interval timer */ at91_sys_write(AT91_ST_PIMR, LATCH); + /* Clear any pending interrupts */ + (void) at91_sys_read(AT91_ST_SR); + /* Enable Period Interval Timer interrupt */ at91_sys_write(AT91_ST_IER, AT91_ST_PITS); } diff --git a/trunk/arch/arm/mach-at91rm9200/at91sam9260.c b/trunk/arch/arm/mach-at91rm9200/at91sam9260.c new file mode 100644 index 000000000000..203f073a53e6 --- /dev/null +++ b/trunk/arch/arm/mach-at91rm9200/at91sam9260.c @@ -0,0 +1,294 @@ +/* + * arch/arm/mach-at91rm9200/at91sam9260.c + * + * Copyright (C) 2006 SAN People + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#include + +#include +#include +#include +#include + +#include "generic.h" +#include "clock.h" + +static struct map_desc at91sam9260_io_desc[] __initdata = { + { + .virtual = AT91_VA_BASE_SYS, + .pfn = __phys_to_pfn(AT91_BASE_SYS), + .length = SZ_16K, + .type = MT_DEVICE, + }, { + .virtual = AT91_IO_VIRT_BASE - AT91SAM9260_SRAM0_SIZE, + .pfn = __phys_to_pfn(AT91SAM9260_SRAM0_BASE), + .length = AT91SAM9260_SRAM0_SIZE, + .type = MT_DEVICE, + }, { + .virtual = AT91_IO_VIRT_BASE - AT91SAM9260_SRAM0_SIZE - AT91SAM9260_SRAM1_SIZE, + .pfn = __phys_to_pfn(AT91SAM9260_SRAM1_BASE), + .length = AT91SAM9260_SRAM1_SIZE, + .type = MT_DEVICE, + }, +}; + +/* -------------------------------------------------------------------- + * Clocks + * -------------------------------------------------------------------- */ + +/* + * The peripheral clocks. + */ +static struct clk pioA_clk = { + .name = "pioA_clk", + .pmc_mask = 1 << AT91SAM9260_ID_PIOA, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk pioB_clk = { + .name = "pioB_clk", + .pmc_mask = 1 << AT91SAM9260_ID_PIOB, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk pioC_clk = { + .name = "pioC_clk", + .pmc_mask = 1 << AT91SAM9260_ID_PIOC, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk adc_clk = { + .name = "adc_clk", + .pmc_mask = 1 << AT91SAM9260_ID_ADC, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk usart0_clk = { + .name = "usart0_clk", + .pmc_mask = 1 << AT91SAM9260_ID_US0, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk usart1_clk = { + .name = "usart1_clk", + .pmc_mask = 1 << AT91SAM9260_ID_US1, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk usart2_clk = { + .name = "usart2_clk", + .pmc_mask = 1 << AT91SAM9260_ID_US2, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk mmc_clk = { + .name = "mci_clk", + .pmc_mask = 1 << AT91SAM9260_ID_MCI, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk udc_clk = { + .name = "udc_clk", + .pmc_mask = 1 << AT91SAM9260_ID_UDP, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk twi_clk = { + .name = "twi_clk", + .pmc_mask = 1 << AT91SAM9260_ID_TWI, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk spi0_clk = { + .name = "spi0_clk", + .pmc_mask = 1 << AT91SAM9260_ID_SPI0, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk spi1_clk = { + .name = "spi1_clk", + .pmc_mask = 1 << AT91SAM9260_ID_SPI1, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk ohci_clk = { + .name = "ohci_clk", + .pmc_mask = 1 << AT91SAM9260_ID_UHP, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk ether_clk = { + .name = "ether_clk", + .pmc_mask = 1 << AT91SAM9260_ID_EMAC, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk isi_clk = { + .name = "isi_clk", + .pmc_mask = 1 << AT91SAM9260_ID_ISI, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk usart3_clk = { + .name = "usart3_clk", + .pmc_mask = 1 << AT91SAM9260_ID_US3, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk usart4_clk = { + .name = "usart4_clk", + .pmc_mask = 1 << AT91SAM9260_ID_US4, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk usart5_clk = { + .name = "usart5_clk", + .pmc_mask = 1 << AT91SAM9260_ID_US5, + .type = CLK_TYPE_PERIPHERAL, +}; + +static struct clk *periph_clocks[] __initdata = { + &pioA_clk, + &pioB_clk, + &pioC_clk, + &adc_clk, + &usart0_clk, + &usart1_clk, + &usart2_clk, + &mmc_clk, + &udc_clk, + &twi_clk, + &spi0_clk, + &spi1_clk, + // ssc + // tc0 .. tc2 + &ohci_clk, + ðer_clk, + &isi_clk, + &usart3_clk, + &usart4_clk, + &usart5_clk, + // tc3 .. tc5 + // irq0 .. irq2 +}; + +/* + * The two programmable clocks. + * You must configure pin multiplexing to bring these signals out. + */ +static struct clk pck0 = { + .name = "pck0", + .pmc_mask = AT91_PMC_PCK0, + .type = CLK_TYPE_PROGRAMMABLE, + .id = 0, +}; +static struct clk pck1 = { + .name = "pck1", + .pmc_mask = AT91_PMC_PCK1, + .type = CLK_TYPE_PROGRAMMABLE, + .id = 1, +}; + +static void __init at91sam9260_register_clocks(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(periph_clocks); i++) + clk_register(periph_clocks[i]); + + clk_register(&pck0); + clk_register(&pck1); +} + +/* -------------------------------------------------------------------- + * GPIO + * -------------------------------------------------------------------- */ + +static struct at91_gpio_bank at91sam9260_gpio[] = { + { + .id = AT91SAM9260_ID_PIOA, + .offset = AT91_PIOA, + .clock = &pioA_clk, + }, { + .id = AT91SAM9260_ID_PIOB, + .offset = AT91_PIOB, + .clock = &pioB_clk, + }, { + .id = AT91SAM9260_ID_PIOC, + .offset = AT91_PIOC, + .clock = &pioC_clk, + } +}; + +static void at91sam9260_reset(void) +{ +#warning "Implement CPU reset" +} + + +/* -------------------------------------------------------------------- + * AT91SAM9260 processor initialization + * -------------------------------------------------------------------- */ + +void __init at91sam9260_initialize(unsigned long main_clock) +{ + /* Map peripherals */ + iotable_init(at91sam9260_io_desc, ARRAY_SIZE(at91sam9260_io_desc)); + + at91_arch_reset = at91sam9260_reset; + at91_extern_irq = (1 << AT91SAM9260_ID_IRQ0) | (1 << AT91SAM9260_ID_IRQ1) + | (1 << AT91SAM9260_ID_IRQ2); + + /* Init clock subsystem */ + at91_clock_init(main_clock); + + /* Register the processor-specific clocks */ + at91sam9260_register_clocks(); + + /* Register GPIO subsystem */ + at91_gpio_init(at91sam9260_gpio, 3); +} + +/* -------------------------------------------------------------------- + * Interrupt initialization + * -------------------------------------------------------------------- */ + +/* + * The default interrupt priority levels (0 = lowest, 7 = highest). + */ +static unsigned int at91sam9260_default_irq_priority[NR_AIC_IRQS] __initdata = { + 7, /* Advanced Interrupt Controller */ + 7, /* System Peripherals */ + 0, /* Parallel IO Controller A */ + 0, /* Parallel IO Controller B */ + 0, /* Parallel IO Controller C */ + 0, /* Analog-to-Digital Converter */ + 6, /* USART 0 */ + 6, /* USART 1 */ + 6, /* USART 2 */ + 0, /* Multimedia Card Interface */ + 4, /* USB Device Port */ + 0, /* Two-Wire Interface */ + 6, /* Serial Peripheral Interface 0 */ + 6, /* Serial Peripheral Interface 1 */ + 5, /* Serial Synchronous Controller */ + 0, + 0, + 0, /* Timer Counter 0 */ + 0, /* Timer Counter 1 */ + 0, /* Timer Counter 2 */ + 3, /* USB Host port */ + 3, /* Ethernet */ + 0, /* Image Sensor Interface */ + 6, /* USART 3 */ + 6, /* USART 4 */ + 6, /* USART 5 */ + 0, /* Timer Counter 3 */ + 0, /* Timer Counter 4 */ + 0, /* Timer Counter 5 */ + 0, /* Advanced Interrupt Controller */ + 0, /* Advanced Interrupt Controller */ + 0, /* Advanced Interrupt Controller */ +}; + +void __init at91sam9260_init_interrupts(unsigned int priority[NR_AIC_IRQS]) +{ + if (!priority) + priority = at91sam9260_default_irq_priority; + + /* Initialize the AIC interrupt controller */ + at91_aic_init(priority); + + /* Enable GPIO interrupts */ + at91_gpio_irq_setup(); +} diff --git a/trunk/arch/arm/mach-at91rm9200/at91sam9260_devices.c b/trunk/arch/arm/mach-at91rm9200/at91sam9260_devices.c new file mode 100644 index 000000000000..a6c596dc4516 --- /dev/null +++ b/trunk/arch/arm/mach-at91rm9200/at91sam9260_devices.c @@ -0,0 +1,866 @@ +/* + * arch/arm/mach-at91rm9200/at91sam9260_devices.c + * + * Copyright (C) 2006 Atmel + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ +#include +#include + +#include + +#include +#include +#include +#include + +#include "generic.h" + +#define SZ_512 0x00000200 +#define SZ_256 0x00000100 +#define SZ_16 0x00000010 + +/* -------------------------------------------------------------------- + * USB Host + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) +static u64 ohci_dmamask = 0xffffffffUL; +static struct at91_usbh_data usbh_data; + +static struct resource usbh_resources[] = { + [0] = { + .start = AT91SAM9260_UHP_BASE, + .end = AT91SAM9260_UHP_BASE + SZ_1M - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9260_ID_UHP, + .end = AT91SAM9260_ID_UHP, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91_usbh_device = { + .name = "at91_ohci", + .id = -1, + .dev = { + .dma_mask = &ohci_dmamask, + .coherent_dma_mask = 0xffffffff, + .platform_data = &usbh_data, + }, + .resource = usbh_resources, + .num_resources = ARRAY_SIZE(usbh_resources), +}; + +void __init at91_add_device_usbh(struct at91_usbh_data *data) +{ + if (!data) + return; + + usbh_data = *data; + platform_device_register(&at91_usbh_device); +} +#else +void __init at91_add_device_usbh(struct at91_usbh_data *data) {} +#endif + + +/* -------------------------------------------------------------------- + * USB Device (Gadget) + * -------------------------------------------------------------------- */ + +#ifdef CONFIG_USB_GADGET_AT91 +static struct at91_udc_data udc_data; + +static struct resource udc_resources[] = { + [0] = { + .start = AT91SAM9260_BASE_UDP, + .end = AT91SAM9260_BASE_UDP + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9260_ID_UDP, + .end = AT91SAM9260_ID_UDP, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91_udc_device = { + .name = "at91_udc", + .id = -1, + .dev = { + .platform_data = &udc_data, + }, + .resource = udc_resources, + .num_resources = ARRAY_SIZE(udc_resources), +}; + +void __init at91_add_device_udc(struct at91_udc_data *data) +{ + if (!data) + return; + + if (data->vbus_pin) { + at91_set_gpio_input(data->vbus_pin, 0); + at91_set_deglitch(data->vbus_pin, 1); + } + + /* Pullup pin is handled internally by USB device peripheral */ + + udc_data = *data; + platform_device_register(&at91_udc_device); +} +#else +void __init at91_add_device_udc(struct at91_udc_data *data) {} +#endif + + +/* -------------------------------------------------------------------- + * Ethernet + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_MACB) || defined(CONFIG_MACB_MODULE) +static u64 eth_dmamask = 0xffffffffUL; +static struct eth_platform_data eth_data; + +static struct resource eth_resources[] = { + [0] = { + .start = AT91SAM9260_BASE_EMAC, + .end = AT91SAM9260_BASE_EMAC + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9260_ID_EMAC, + .end = AT91SAM9260_ID_EMAC, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91sam9260_eth_device = { + .name = "macb", + .id = -1, + .dev = { + .dma_mask = ð_dmamask, + .coherent_dma_mask = 0xffffffff, + .platform_data = ð_data, + }, + .resource = eth_resources, + .num_resources = ARRAY_SIZE(eth_resources), +}; + +void __init at91_add_device_eth(struct eth_platform_data *data) +{ + if (!data) + return; + + if (data->phy_irq_pin) { + at91_set_gpio_input(data->phy_irq_pin, 0); + at91_set_deglitch(data->phy_irq_pin, 1); + } + + /* Pins used for MII and RMII */ + at91_set_A_periph(AT91_PIN_PA19, 0); /* ETXCK_EREFCK */ + at91_set_A_periph(AT91_PIN_PA17, 0); /* ERXDV */ + at91_set_A_periph(AT91_PIN_PA14, 0); /* ERX0 */ + at91_set_A_periph(AT91_PIN_PA15, 0); /* ERX1 */ + at91_set_A_periph(AT91_PIN_PA18, 0); /* ERXER */ + at91_set_A_periph(AT91_PIN_PA16, 0); /* ETXEN */ + at91_set_A_periph(AT91_PIN_PA12, 0); /* ETX0 */ + at91_set_A_periph(AT91_PIN_PA13, 0); /* ETX1 */ + at91_set_A_periph(AT91_PIN_PA21, 0); /* EMDIO */ + at91_set_A_periph(AT91_PIN_PA20, 0); /* EMDC */ + + if (!data->is_rmii) { + at91_set_B_periph(AT91_PIN_PA28, 0); /* ECRS */ + at91_set_B_periph(AT91_PIN_PA29, 0); /* ECOL */ + at91_set_B_periph(AT91_PIN_PA25, 0); /* ERX2 */ + at91_set_B_periph(AT91_PIN_PA26, 0); /* ERX3 */ + at91_set_B_periph(AT91_PIN_PA27, 0); /* ERXCK */ + at91_set_B_periph(AT91_PIN_PA23, 0); /* ETX2 */ + at91_set_B_periph(AT91_PIN_PA24, 0); /* ETX3 */ + at91_set_B_periph(AT91_PIN_PA22, 0); /* ETXER */ + } + + eth_data = *data; + platform_device_register(&at91sam9260_eth_device); +} +#else +void __init at91_add_device_eth(struct eth_platform_data *data) {} +#endif + + +/* -------------------------------------------------------------------- + * MMC / SD + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_MMC_AT91) || defined(CONFIG_MMC_AT91_MODULE) +static u64 mmc_dmamask = 0xffffffffUL; +static struct at91_mmc_data mmc_data; + +static struct resource mmc_resources[] = { + [0] = { + .start = AT91SAM9260_BASE_MCI, + .end = AT91SAM9260_BASE_MCI + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9260_ID_MCI, + .end = AT91SAM9260_ID_MCI, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91sam9260_mmc_device = { + .name = "at91_mci", + .id = -1, + .dev = { + .dma_mask = &mmc_dmamask, + .coherent_dma_mask = 0xffffffff, + .platform_data = &mmc_data, + }, + .resource = mmc_resources, + .num_resources = ARRAY_SIZE(mmc_resources), +}; + +void __init at91_add_device_mmc(struct at91_mmc_data *data) +{ + if (!data) + return; + + /* input/irq */ + if (data->det_pin) { + at91_set_gpio_input(data->det_pin, 1); + at91_set_deglitch(data->det_pin, 1); + } + if (data->wp_pin) + at91_set_gpio_input(data->wp_pin, 1); + if (data->vcc_pin) + at91_set_gpio_output(data->vcc_pin, 0); + + /* CLK */ + at91_set_A_periph(AT91_PIN_PA8, 0); + + if (data->slot_b) { + /* CMD */ + at91_set_B_periph(AT91_PIN_PA1, 1); + + /* DAT0, maybe DAT1..DAT3 */ + at91_set_B_periph(AT91_PIN_PA0, 1); + if (data->wire4) { + at91_set_B_periph(AT91_PIN_PA5, 1); + at91_set_B_periph(AT91_PIN_PA4, 1); + at91_set_B_periph(AT91_PIN_PA3, 1); + } + } else { + /* CMD */ + at91_set_A_periph(AT91_PIN_PA7, 1); + + /* DAT0, maybe DAT1..DAT3 */ + at91_set_A_periph(AT91_PIN_PA6, 1); + if (data->wire4) { + at91_set_A_periph(AT91_PIN_PA9, 1); + at91_set_A_periph(AT91_PIN_PA10, 1); + at91_set_A_periph(AT91_PIN_PA11, 1); + } + } + + mmc_data = *data; + platform_device_register(&at91sam9260_mmc_device); +} +#else +void __init at91_add_device_mmc(struct at91_mmc_data *data) {} +#endif + + +/* -------------------------------------------------------------------- + * NAND / SmartMedia + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_MTD_NAND_AT91) || defined(CONFIG_MTD_NAND_AT91_MODULE) +static struct at91_nand_data nand_data; + +#define NAND_BASE AT91_CHIPSELECT_3 + +static struct resource nand_resources[] = { + { + .start = NAND_BASE, + .end = NAND_BASE + SZ_8M - 1, + .flags = IORESOURCE_MEM, + } +}; + +static struct platform_device at91sam9260_nand_device = { + .name = "at91_nand", + .id = -1, + .dev = { + .platform_data = &nand_data, + }, + .resource = nand_resources, + .num_resources = ARRAY_SIZE(nand_resources), +}; + +void __init at91_add_device_nand(struct at91_nand_data *data) +{ + unsigned long csa, mode; + + if (!data) + return; + + csa = at91_sys_read(AT91_MATRIX_EBICSA); + at91_sys_write(AT91_MATRIX_EBICSA, csa | AT91_MATRIX_CS3A_SMC); + + /* set the bus interface characteristics */ + at91_sys_write(AT91_SMC_SETUP(3), AT91_SMC_NWESETUP_(0) | AT91_SMC_NCS_WRSETUP_(0) + | AT91_SMC_NRDSETUP_(0) | AT91_SMC_NCS_RDSETUP_(0)); + + at91_sys_write(AT91_SMC_PULSE(3), AT91_SMC_NWEPULSE_(2) | AT91_SMC_NCS_WRPULSE_(5) + | AT91_SMC_NRDPULSE_(2) | AT91_SMC_NCS_RDPULSE_(5)); + + at91_sys_write(AT91_SMC_CYCLE(3), AT91_SMC_NWECYCLE_(7) | AT91_SMC_NRDCYCLE_(7)); + + if (data->bus_width_16) + mode = AT91_SMC_DBW_16; + else + mode = AT91_SMC_DBW_8; + at91_sys_write(AT91_SMC_MODE(3), mode | AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_TDF_(1)); + + /* enable pin */ + if (data->enable_pin) + at91_set_gpio_output(data->enable_pin, 1); + + /* ready/busy pin */ + if (data->rdy_pin) + at91_set_gpio_input(data->rdy_pin, 1); + + /* card detect pin */ + if (data->det_pin) + at91_set_gpio_input(data->det_pin, 1); + + nand_data = *data; + platform_device_register(&at91sam9260_nand_device); +} +#else +void __init at91_add_device_nand(struct at91_nand_data *data) {} +#endif + + +/* -------------------------------------------------------------------- + * TWI (i2c) + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_I2C_AT91) || defined(CONFIG_I2C_AT91_MODULE) + +static struct resource twi_resources[] = { + [0] = { + .start = AT91SAM9260_BASE_TWI, + .end = AT91SAM9260_BASE_TWI + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9260_ID_TWI, + .end = AT91SAM9260_ID_TWI, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91sam9260_twi_device = { + .name = "at91_i2c", + .id = -1, + .resource = twi_resources, + .num_resources = ARRAY_SIZE(twi_resources), +}; + +void __init at91_add_device_i2c(void) +{ + /* pins used for TWI interface */ + at91_set_A_periph(AT91_PIN_PA23, 0); /* TWD */ + at91_set_multi_drive(AT91_PIN_PA23, 1); + + at91_set_A_periph(AT91_PIN_PA24, 0); /* TWCK */ + at91_set_multi_drive(AT91_PIN_PA24, 1); + + platform_device_register(&at91sam9260_twi_device); +} +#else +void __init at91_add_device_i2c(void) {} +#endif + + +/* -------------------------------------------------------------------- + * SPI + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_SPI_ATMEL) || defined(CONFIG_SPI_ATMEL_MODULE) +static u64 spi_dmamask = 0xffffffffUL; + +static struct resource spi0_resources[] = { + [0] = { + .start = AT91SAM9260_BASE_SPI0, + .end = AT91SAM9260_BASE_SPI0 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9260_ID_SPI0, + .end = AT91SAM9260_ID_SPI0, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91sam9260_spi0_device = { + .name = "atmel_spi", + .id = 0, + .dev = { + .dma_mask = &spi_dmamask, + .coherent_dma_mask = 0xffffffff, + }, + .resource = spi0_resources, + .num_resources = ARRAY_SIZE(spi0_resources), +}; + +static const unsigned spi0_standard_cs[4] = { AT91_PIN_PA3, AT91_PIN_PC11, AT91_PIN_PC16, AT91_PIN_PC17 }; + +static struct resource spi1_resources[] = { + [0] = { + .start = AT91SAM9260_BASE_SPI1, + .end = AT91SAM9260_BASE_SPI1 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9260_ID_SPI1, + .end = AT91SAM9260_ID_SPI1, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91sam9260_spi1_device = { + .name = "atmel_spi", + .id = 1, + .dev = { + .dma_mask = &spi_dmamask, + .coherent_dma_mask = 0xffffffff, + }, + .resource = spi1_resources, + .num_resources = ARRAY_SIZE(spi1_resources), +}; + +static const unsigned spi1_standard_cs[4] = { AT91_PIN_PB3, AT91_PIN_PC5, AT91_PIN_PC4, AT91_PIN_PC3 }; + +void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) +{ + int i; + unsigned long cs_pin; + short enable_spi0 = 0; + short enable_spi1 = 0; + + /* Choose SPI chip-selects */ + for (i = 0; i < nr_devices; i++) { + if (devices[i].controller_data) + cs_pin = (unsigned long) devices[i].controller_data; + else if (devices[i].bus_num == 0) + cs_pin = spi0_standard_cs[devices[i].chip_select]; + else + cs_pin = spi1_standard_cs[devices[i].chip_select]; + + if (devices[i].bus_num == 0) + enable_spi0 = 1; + else + enable_spi1 = 1; + + /* enable chip-select pin */ + at91_set_gpio_output(cs_pin, 1); + + /* pass chip-select pin to driver */ + devices[i].controller_data = (void *) cs_pin; + } + + spi_register_board_info(devices, nr_devices); + + /* Configure SPI bus(es) */ + if (enable_spi0) { + at91_set_A_periph(AT91_PIN_PA0, 0); /* SPI0_MISO */ + at91_set_A_periph(AT91_PIN_PA1, 0); /* SPI0_MOSI */ + at91_set_A_periph(AT91_PIN_PA2, 0); /* SPI1_SPCK */ + + at91_clock_associate("spi0_clk", &at91sam9260_spi0_device.dev, "spi_clk"); + platform_device_register(&at91sam9260_spi0_device); + } + if (enable_spi1) { + at91_set_A_periph(AT91_PIN_PB0, 0); /* SPI1_MISO */ + at91_set_A_periph(AT91_PIN_PB1, 0); /* SPI1_MOSI */ + at91_set_A_periph(AT91_PIN_PB2, 0); /* SPI1_SPCK */ + + at91_clock_associate("spi1_clk", &at91sam9260_spi1_device.dev, "spi_clk"); + platform_device_register(&at91sam9260_spi1_device); + } +} +#else +void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) {} +#endif + + +/* -------------------------------------------------------------------- + * LEDs + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_LEDS) +u8 at91_leds_cpu; +u8 at91_leds_timer; + +void __init at91_init_leds(u8 cpu_led, u8 timer_led) +{ + at91_leds_cpu = cpu_led; + at91_leds_timer = timer_led; +} +#else +void __init at91_init_leds(u8 cpu_led, u8 timer_led) {} +#endif + + +/* -------------------------------------------------------------------- + * UART + * -------------------------------------------------------------------- */ +#if defined(CONFIG_SERIAL_ATMEL) +static struct resource dbgu_resources[] = { + [0] = { + .start = AT91_VA_BASE_SYS + AT91_DBGU, + .end = AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91_ID_SYS, + .end = AT91_ID_SYS, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct atmel_uart_data dbgu_data = { + .use_dma_tx = 0, + .use_dma_rx = 0, /* DBGU not capable of receive DMA */ + .regs = (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU), +}; + +static struct platform_device at91sam9260_dbgu_device = { + .name = "atmel_usart", + .id = 0, + .dev = { + .platform_data = &dbgu_data, + .coherent_dma_mask = 0xffffffff, + }, + .resource = dbgu_resources, + .num_resources = ARRAY_SIZE(dbgu_resources), +}; + +static inline void configure_dbgu_pins(void) +{ + at91_set_A_periph(AT91_PIN_PB14, 0); /* DRXD */ + at91_set_A_periph(AT91_PIN_PB15, 1); /* DTXD */ +} + +static struct resource uart0_resources[] = { + [0] = { + .start = AT91SAM9260_BASE_US0, + .end = AT91SAM9260_BASE_US0 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9260_ID_US0, + .end = AT91SAM9260_ID_US0, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct atmel_uart_data uart0_data = { + .use_dma_tx = 1, + .use_dma_rx = 1, +}; + +static struct platform_device at91sam9260_uart0_device = { + .name = "atmel_usart", + .id = 1, + .dev = { + .platform_data = &uart0_data, + .coherent_dma_mask = 0xffffffff, + }, + .resource = uart0_resources, + .num_resources = ARRAY_SIZE(uart0_resources), +}; + +static inline void configure_usart0_pins(void) +{ + at91_set_A_periph(AT91_PIN_PB4, 1); /* TXD0 */ + at91_set_A_periph(AT91_PIN_PB5, 0); /* RXD0 */ + at91_set_A_periph(AT91_PIN_PB26, 0); /* RTS0 */ + at91_set_A_periph(AT91_PIN_PB27, 0); /* CTS0 */ + at91_set_A_periph(AT91_PIN_PB24, 0); /* DTR0 */ + at91_set_A_periph(AT91_PIN_PB22, 0); /* DSR0 */ + at91_set_A_periph(AT91_PIN_PB23, 0); /* DCD0 */ + at91_set_A_periph(AT91_PIN_PB25, 0); /* RI0 */ +} + +static struct resource uart1_resources[] = { + [0] = { + .start = AT91SAM9260_BASE_US1, + .end = AT91SAM9260_BASE_US1 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9260_ID_US1, + .end = AT91SAM9260_ID_US1, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct atmel_uart_data uart1_data = { + .use_dma_tx = 1, + .use_dma_rx = 1, +}; + +static struct platform_device at91sam9260_uart1_device = { + .name = "atmel_usart", + .id = 2, + .dev = { + .platform_data = &uart1_data, + .coherent_dma_mask = 0xffffffff, + }, + .resource = uart1_resources, + .num_resources = ARRAY_SIZE(uart1_resources), +}; + +static inline void configure_usart1_pins(void) +{ + at91_set_A_periph(AT91_PIN_PB6, 1); /* TXD1 */ + at91_set_A_periph(AT91_PIN_PB7, 0); /* RXD1 */ + at91_set_A_periph(AT91_PIN_PB28, 0); /* RTS1 */ + at91_set_A_periph(AT91_PIN_PB29, 0); /* CTS1 */ +} + +static struct resource uart2_resources[] = { + [0] = { + .start = AT91SAM9260_BASE_US2, + .end = AT91SAM9260_BASE_US2 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9260_ID_US2, + .end = AT91SAM9260_ID_US2, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct atmel_uart_data uart2_data = { + .use_dma_tx = 1, + .use_dma_rx = 1, +}; + +static struct platform_device at91sam9260_uart2_device = { + .name = "atmel_usart", + .id = 3, + .dev = { + .platform_data = &uart2_data, + .coherent_dma_mask = 0xffffffff, + }, + .resource = uart2_resources, + .num_resources = ARRAY_SIZE(uart2_resources), +}; + +static inline void configure_usart2_pins(void) +{ + at91_set_A_periph(AT91_PIN_PB8, 1); /* TXD2 */ + at91_set_A_periph(AT91_PIN_PB9, 0); /* RXD2 */ +} + +static struct resource uart3_resources[] = { + [0] = { + .start = AT91SAM9260_BASE_US3, + .end = AT91SAM9260_BASE_US3 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9260_ID_US3, + .end = AT91SAM9260_ID_US3, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct atmel_uart_data uart3_data = { + .use_dma_tx = 1, + .use_dma_rx = 1, +}; + +static struct platform_device at91sam9260_uart3_device = { + .name = "atmel_usart", + .id = 4, + .dev = { + .platform_data = &uart3_data, + .coherent_dma_mask = 0xffffffff, + }, + .resource = uart3_resources, + .num_resources = ARRAY_SIZE(uart3_resources), +}; + +static inline void configure_usart3_pins(void) +{ + at91_set_A_periph(AT91_PIN_PB10, 1); /* TXD3 */ + at91_set_A_periph(AT91_PIN_PB11, 0); /* RXD3 */ +} + +static struct resource uart4_resources[] = { + [0] = { + .start = AT91SAM9260_BASE_US4, + .end = AT91SAM9260_BASE_US4 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9260_ID_US4, + .end = AT91SAM9260_ID_US4, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct atmel_uart_data uart4_data = { + .use_dma_tx = 1, + .use_dma_rx = 1, +}; + +static struct platform_device at91sam9260_uart4_device = { + .name = "atmel_usart", + .id = 5, + .dev = { + .platform_data = &uart4_data, + .coherent_dma_mask = 0xffffffff, + }, + .resource = uart4_resources, + .num_resources = ARRAY_SIZE(uart4_resources), +}; + +static inline void configure_usart4_pins(void) +{ + at91_set_B_periph(AT91_PIN_PA31, 1); /* TXD4 */ + at91_set_B_periph(AT91_PIN_PA30, 0); /* RXD4 */ +} + +static struct resource uart5_resources[] = { + [0] = { + .start = AT91SAM9260_BASE_US5, + .end = AT91SAM9260_BASE_US5 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9260_ID_US5, + .end = AT91SAM9260_ID_US5, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct atmel_uart_data uart5_data = { + .use_dma_tx = 1, + .use_dma_rx = 1, +}; + +static struct platform_device at91sam9260_uart5_device = { + .name = "atmel_usart", + .id = 6, + .dev = { + .platform_data = &uart5_data, + .coherent_dma_mask = 0xffffffff, + }, + .resource = uart5_resources, + .num_resources = ARRAY_SIZE(uart5_resources), +}; + +static inline void configure_usart5_pins(void) +{ + at91_set_A_periph(AT91_PIN_PB12, 1); /* TXD5 */ + at91_set_A_periph(AT91_PIN_PB13, 0); /* RXD5 */ +} + +struct platform_device *at91_uarts[ATMEL_MAX_UART]; /* the UARTs to use */ +struct platform_device *atmel_default_console_device; /* the serial console device */ + +void __init at91_init_serial(struct at91_uart_config *config) +{ + int i; + + /* Fill in list of supported UARTs */ + for (i = 0; i < config->nr_tty; i++) { + switch (config->tty_map[i]) { + case 0: + configure_usart0_pins(); + at91_uarts[i] = &at91sam9260_uart0_device; + at91_clock_associate("usart0_clk", &at91sam9260_uart0_device.dev, "usart"); + break; + case 1: + configure_usart1_pins(); + at91_uarts[i] = &at91sam9260_uart1_device; + at91_clock_associate("usart1_clk", &at91sam9260_uart1_device.dev, "usart"); + break; + case 2: + configure_usart2_pins(); + at91_uarts[i] = &at91sam9260_uart2_device; + at91_clock_associate("usart2_clk", &at91sam9260_uart2_device.dev, "usart"); + break; + case 3: + configure_usart3_pins(); + at91_uarts[i] = &at91sam9260_uart3_device; + at91_clock_associate("usart3_clk", &at91sam9260_uart3_device.dev, "usart"); + break; + case 4: + configure_usart4_pins(); + at91_uarts[i] = &at91sam9260_uart4_device; + at91_clock_associate("usart4_clk", &at91sam9260_uart4_device.dev, "usart"); + break; + case 5: + configure_usart5_pins(); + at91_uarts[i] = &at91sam9260_uart5_device; + at91_clock_associate("usart5_clk", &at91sam9260_uart5_device.dev, "usart"); + break; + case 6: + configure_dbgu_pins(); + at91_uarts[i] = &at91sam9260_dbgu_device; + at91_clock_associate("mck", &at91sam9260_dbgu_device.dev, "usart"); + break; + default: + continue; + } + at91_uarts[i]->id = i; /* update ID number to mapped ID */ + } + + /* Set serial console device */ + if (config->console_tty < ATMEL_MAX_UART) + atmel_default_console_device = at91_uarts[config->console_tty]; + if (!atmel_default_console_device) + printk(KERN_INFO "AT91: No default serial console defined.\n"); +} + +void __init at91_add_device_serial(void) +{ + int i; + + for (i = 0; i < ATMEL_MAX_UART; i++) { + if (at91_uarts[i]) + platform_device_register(at91_uarts[i]); + } +} +#else +void __init at91_init_serial(struct at91_uart_config *config) {} +void __init at91_add_device_serial(void) {} +#endif + + +/* -------------------------------------------------------------------- */ +/* + * These devices are always present and don't need any board-specific + * setup. + */ +static int __init at91_add_standard_devices(void) +{ + return 0; +} + +arch_initcall(at91_add_standard_devices); diff --git a/trunk/arch/arm/mach-at91rm9200/at91sam9261.c b/trunk/arch/arm/mach-at91rm9200/at91sam9261.c new file mode 100644 index 000000000000..5a82f35da2e9 --- /dev/null +++ b/trunk/arch/arm/mach-at91rm9200/at91sam9261.c @@ -0,0 +1,289 @@ +/* + * arch/arm/mach-at91rm9200/at91sam9261.c + * + * Copyright (C) 2005 SAN People + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#include + +#include +#include +#include +#include + +#include "generic.h" +#include "clock.h" + +static struct map_desc at91sam9261_io_desc[] __initdata = { + { + .virtual = AT91_VA_BASE_SYS, + .pfn = __phys_to_pfn(AT91_BASE_SYS), + .length = SZ_16K, + .type = MT_DEVICE, + }, { + .virtual = AT91_IO_VIRT_BASE - AT91SAM9261_SRAM_SIZE, + .pfn = __phys_to_pfn(AT91SAM9261_SRAM_BASE), + .length = AT91SAM9261_SRAM_SIZE, + .type = MT_DEVICE, + }, +}; + +/* -------------------------------------------------------------------- + * Clocks + * -------------------------------------------------------------------- */ + +/* + * The peripheral clocks. + */ +static struct clk pioA_clk = { + .name = "pioA_clk", + .pmc_mask = 1 << AT91SAM9261_ID_PIOA, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk pioB_clk = { + .name = "pioB_clk", + .pmc_mask = 1 << AT91SAM9261_ID_PIOB, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk pioC_clk = { + .name = "pioC_clk", + .pmc_mask = 1 << AT91SAM9261_ID_PIOC, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk usart0_clk = { + .name = "usart0_clk", + .pmc_mask = 1 << AT91SAM9261_ID_US0, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk usart1_clk = { + .name = "usart1_clk", + .pmc_mask = 1 << AT91SAM9261_ID_US1, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk usart2_clk = { + .name = "usart2_clk", + .pmc_mask = 1 << AT91SAM9261_ID_US2, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk mmc_clk = { + .name = "mci_clk", + .pmc_mask = 1 << AT91SAM9261_ID_MCI, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk udc_clk = { + .name = "udc_clk", + .pmc_mask = 1 << AT91SAM9261_ID_UDP, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk twi_clk = { + .name = "twi_clk", + .pmc_mask = 1 << AT91SAM9261_ID_TWI, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk spi0_clk = { + .name = "spi0_clk", + .pmc_mask = 1 << AT91SAM9261_ID_SPI0, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk spi1_clk = { + .name = "spi1_clk", + .pmc_mask = 1 << AT91SAM9261_ID_SPI1, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk ohci_clk = { + .name = "ohci_clk", + .pmc_mask = 1 << AT91SAM9261_ID_UHP, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk lcdc_clk = { + .name = "lcdc_clk", + .pmc_mask = 1 << AT91SAM9261_ID_LCDC, + .type = CLK_TYPE_PERIPHERAL, +}; + +static struct clk *periph_clocks[] __initdata = { + &pioA_clk, + &pioB_clk, + &pioC_clk, + &usart0_clk, + &usart1_clk, + &usart2_clk, + &mmc_clk, + &udc_clk, + &twi_clk, + &spi0_clk, + &spi1_clk, + // ssc 0 .. ssc2 + // tc0 .. tc2 + &ohci_clk, + &lcdc_clk, + // irq0 .. irq2 +}; + +/* + * The four programmable clocks. + * You must configure pin multiplexing to bring these signals out. + */ +static struct clk pck0 = { + .name = "pck0", + .pmc_mask = AT91_PMC_PCK0, + .type = CLK_TYPE_PROGRAMMABLE, + .id = 0, +}; +static struct clk pck1 = { + .name = "pck1", + .pmc_mask = AT91_PMC_PCK1, + .type = CLK_TYPE_PROGRAMMABLE, + .id = 1, +}; +static struct clk pck2 = { + .name = "pck2", + .pmc_mask = AT91_PMC_PCK2, + .type = CLK_TYPE_PROGRAMMABLE, + .id = 2, +}; +static struct clk pck3 = { + .name = "pck3", + .pmc_mask = AT91_PMC_PCK3, + .type = CLK_TYPE_PROGRAMMABLE, + .id = 3, +}; + +/* HClocks */ +static struct clk hck0 = { + .name = "hck0", + .pmc_mask = AT91_PMC_HCK0, + .type = CLK_TYPE_SYSTEM, + .id = 0, +}; +static struct clk hck1 = { + .name = "hck1", + .pmc_mask = AT91_PMC_HCK1, + .type = CLK_TYPE_SYSTEM, + .id = 1, +}; + +static void __init at91sam9261_register_clocks(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(periph_clocks); i++) + clk_register(periph_clocks[i]); + + clk_register(&pck0); + clk_register(&pck1); + clk_register(&pck2); + clk_register(&pck3); + + clk_register(&hck0); + clk_register(&hck1); +} + +/* -------------------------------------------------------------------- + * GPIO + * -------------------------------------------------------------------- */ + +static struct at91_gpio_bank at91sam9261_gpio[] = { + { + .id = AT91SAM9261_ID_PIOA, + .offset = AT91_PIOA, + .clock = &pioA_clk, + }, { + .id = AT91SAM9261_ID_PIOB, + .offset = AT91_PIOB, + .clock = &pioB_clk, + }, { + .id = AT91SAM9261_ID_PIOC, + .offset = AT91_PIOC, + .clock = &pioC_clk, + } +}; + +static void at91sam9261_reset(void) +{ +#warning "Implement CPU reset" +} + + +/* -------------------------------------------------------------------- + * AT91SAM9261 processor initialization + * -------------------------------------------------------------------- */ + +void __init at91sam9261_initialize(unsigned long main_clock) +{ + /* Map peripherals */ + iotable_init(at91sam9261_io_desc, ARRAY_SIZE(at91sam9261_io_desc)); + + at91_arch_reset = at91sam9261_reset; + at91_extern_irq = (1 << AT91SAM9261_ID_IRQ0) | (1 << AT91SAM9261_ID_IRQ1) + | (1 << AT91SAM9261_ID_IRQ2); + + /* Init clock subsystem */ + at91_clock_init(main_clock); + + /* Register the processor-specific clocks */ + at91sam9261_register_clocks(); + + /* Register GPIO subsystem */ + at91_gpio_init(at91sam9261_gpio, 3); +} + +/* -------------------------------------------------------------------- + * Interrupt initialization + * -------------------------------------------------------------------- */ + +/* + * The default interrupt priority levels (0 = lowest, 7 = highest). + */ +static unsigned int at91sam9261_default_irq_priority[NR_AIC_IRQS] __initdata = { + 7, /* Advanced Interrupt Controller */ + 7, /* System Peripherals */ + 0, /* Parallel IO Controller A */ + 0, /* Parallel IO Controller B */ + 0, /* Parallel IO Controller C */ + 0, + 6, /* USART 0 */ + 6, /* USART 1 */ + 6, /* USART 2 */ + 0, /* Multimedia Card Interface */ + 4, /* USB Device Port */ + 0, /* Two-Wire Interface */ + 6, /* Serial Peripheral Interface 0 */ + 6, /* Serial Peripheral Interface 1 */ + 5, /* Serial Synchronous Controller 0 */ + 5, /* Serial Synchronous Controller 1 */ + 5, /* Serial Synchronous Controller 2 */ + 0, /* Timer Counter 0 */ + 0, /* Timer Counter 1 */ + 0, /* Timer Counter 2 */ + 3, /* USB Host port */ + 3, /* LCD Controller */ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, /* Advanced Interrupt Controller */ + 0, /* Advanced Interrupt Controller */ + 0, /* Advanced Interrupt Controller */ +}; + +void __init at91sam9261_init_interrupts(unsigned int priority[NR_AIC_IRQS]) +{ + if (!priority) + priority = at91sam9261_default_irq_priority; + + /* Initialize the AIC interrupt controller */ + at91_aic_init(priority); + + /* Enable GPIO interrupts */ + at91_gpio_irq_setup(); +} diff --git a/trunk/arch/arm/mach-at91rm9200/at91sam9261_devices.c b/trunk/arch/arm/mach-at91rm9200/at91sam9261_devices.c new file mode 100644 index 000000000000..ed1d79081b35 --- /dev/null +++ b/trunk/arch/arm/mach-at91rm9200/at91sam9261_devices.c @@ -0,0 +1,741 @@ +/* + * arch/arm/mach-at91rm9200/at91sam9261_devices.c + * + * Copyright (C) 2005 Thibaut VARENE + * Copyright (C) 2005 David Brownell + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include "generic.h" + +#define SZ_512 0x00000200 +#define SZ_256 0x00000100 +#define SZ_16 0x00000010 + +/* -------------------------------------------------------------------- + * USB Host + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) +static u64 ohci_dmamask = 0xffffffffUL; +static struct at91_usbh_data usbh_data; + +static struct resource usbh_resources[] = { + [0] = { + .start = AT91SAM9261_UHP_BASE, + .end = AT91SAM9261_UHP_BASE + SZ_1M - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9261_ID_UHP, + .end = AT91SAM9261_ID_UHP, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91sam9261_usbh_device = { + .name = "at91_ohci", + .id = -1, + .dev = { + .dma_mask = &ohci_dmamask, + .coherent_dma_mask = 0xffffffff, + .platform_data = &usbh_data, + }, + .resource = usbh_resources, + .num_resources = ARRAY_SIZE(usbh_resources), +}; + +void __init at91_add_device_usbh(struct at91_usbh_data *data) +{ + if (!data) + return; + + usbh_data = *data; + platform_device_register(&at91sam9261_usbh_device); +} +#else +void __init at91_add_device_usbh(struct at91_usbh_data *data) {} +#endif + + +/* -------------------------------------------------------------------- + * USB Device (Gadget) + * -------------------------------------------------------------------- */ + +#ifdef CONFIG_USB_GADGET_AT91 +static struct at91_udc_data udc_data; + +static struct resource udc_resources[] = { + [0] = { + .start = AT91SAM9261_BASE_UDP, + .end = AT91SAM9261_BASE_UDP + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9261_ID_UDP, + .end = AT91SAM9261_ID_UDP, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91sam9261_udc_device = { + .name = "at91_udc", + .id = -1, + .dev = { + .platform_data = &udc_data, + }, + .resource = udc_resources, + .num_resources = ARRAY_SIZE(udc_resources), +}; + +void __init at91_add_device_udc(struct at91_udc_data *data) +{ + unsigned long x; + + if (!data) + return; + + if (data->vbus_pin) { + at91_set_gpio_input(data->vbus_pin, 0); + at91_set_deglitch(data->vbus_pin, 1); + } + + /* Pullup pin is handled internally */ + x = at91_sys_read(AT91_MATRIX_USBPUCR); + at91_sys_write(AT91_MATRIX_USBPUCR, x | AT91_MATRIX_USBPUCR_PUON); + + udc_data = *data; + platform_device_register(&at91sam9261_udc_device); +} +#else +void __init at91_add_device_udc(struct at91_udc_data *data) {} +#endif + +/* -------------------------------------------------------------------- + * MMC / SD + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_MMC_AT91) || defined(CONFIG_MMC_AT91_MODULE) +static u64 mmc_dmamask = 0xffffffffUL; +static struct at91_mmc_data mmc_data; + +static struct resource mmc_resources[] = { + [0] = { + .start = AT91SAM9261_BASE_MCI, + .end = AT91SAM9261_BASE_MCI + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9261_ID_MCI, + .end = AT91SAM9261_ID_MCI, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91sam9261_mmc_device = { + .name = "at91_mci", + .id = -1, + .dev = { + .dma_mask = &mmc_dmamask, + .coherent_dma_mask = 0xffffffff, + .platform_data = &mmc_data, + }, + .resource = mmc_resources, + .num_resources = ARRAY_SIZE(mmc_resources), +}; + +void __init at91_add_device_mmc(struct at91_mmc_data *data) +{ + if (!data) + return; + + /* input/irq */ + if (data->det_pin) { + at91_set_gpio_input(data->det_pin, 1); + at91_set_deglitch(data->det_pin, 1); + } + if (data->wp_pin) + at91_set_gpio_input(data->wp_pin, 1); + if (data->vcc_pin) + at91_set_gpio_output(data->vcc_pin, 0); + + /* CLK */ + at91_set_B_periph(AT91_PIN_PA2, 0); + + /* CMD */ + at91_set_B_periph(AT91_PIN_PA1, 1); + + /* DAT0, maybe DAT1..DAT3 */ + at91_set_B_periph(AT91_PIN_PA0, 1); + if (data->wire4) { + at91_set_B_periph(AT91_PIN_PA4, 1); + at91_set_B_periph(AT91_PIN_PA5, 1); + at91_set_B_periph(AT91_PIN_PA6, 1); + } + + mmc_data = *data; + platform_device_register(&at91sam9261_mmc_device); +} +#else +void __init at91_add_device_mmc(struct at91_mmc_data *data) {} +#endif + + +/* -------------------------------------------------------------------- + * NAND / SmartMedia + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_MTD_NAND_AT91) || defined(CONFIG_MTD_NAND_AT91_MODULE) +static struct at91_nand_data nand_data; + +#define NAND_BASE AT91_CHIPSELECT_3 + +static struct resource nand_resources[] = { + { + .start = NAND_BASE, + .end = NAND_BASE + SZ_256M - 1, + .flags = IORESOURCE_MEM, + } +}; + +static struct platform_device at91_nand_device = { + .name = "at91_nand", + .id = -1, + .dev = { + .platform_data = &nand_data, + }, + .resource = nand_resources, + .num_resources = ARRAY_SIZE(nand_resources), +}; + +void __init at91_add_device_nand(struct at91_nand_data *data) +{ + unsigned long csa, mode; + + if (!data) + return; + + csa = at91_sys_read(AT91_MATRIX_EBICSA); + at91_sys_write(AT91_MATRIX_EBICSA, csa | AT91_MATRIX_CS3A_SMC); + + /* set the bus interface characteristics */ + at91_sys_write(AT91_SMC_SETUP(3), AT91_SMC_NWESETUP_(0) | AT91_SMC_NCS_WRSETUP_(0) + | AT91_SMC_NRDSETUP_(0) | AT91_SMC_NCS_RDSETUP_(0)); + + at91_sys_write(AT91_SMC_PULSE(3), AT91_SMC_NWEPULSE_(2) | AT91_SMC_NCS_WRPULSE_(5) + | AT91_SMC_NRDPULSE_(2) | AT91_SMC_NCS_RDPULSE_(5)); + + at91_sys_write(AT91_SMC_CYCLE(3), AT91_SMC_NWECYCLE_(7) | AT91_SMC_NRDCYCLE_(7)); + + if (data->bus_width_16) + mode = AT91_SMC_DBW_16; + else + mode = AT91_SMC_DBW_8; + at91_sys_write(AT91_SMC_MODE(3), mode | AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_TDF_(1)); + + /* enable pin */ + if (data->enable_pin) + at91_set_gpio_output(data->enable_pin, 1); + + /* ready/busy pin */ + if (data->rdy_pin) + at91_set_gpio_input(data->rdy_pin, 1); + + /* card detect pin */ + if (data->det_pin) + at91_set_gpio_input(data->det_pin, 1); + + at91_set_A_periph(AT91_PIN_PC0, 0); /* NANDOE */ + at91_set_A_periph(AT91_PIN_PC1, 0); /* NANDWE */ + + nand_data = *data; + platform_device_register(&at91_nand_device); +} + +#else +void __init at91_add_device_nand(struct at91_nand_data *data) {} +#endif + + +/* -------------------------------------------------------------------- + * TWI (i2c) + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_I2C_AT91) || defined(CONFIG_I2C_AT91_MODULE) + +static struct resource twi_resources[] = { + [0] = { + .start = AT91SAM9261_BASE_TWI, + .end = AT91SAM9261_BASE_TWI + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9261_ID_TWI, + .end = AT91SAM9261_ID_TWI, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91sam9261_twi_device = { + .name = "at91_i2c", + .id = -1, + .resource = twi_resources, + .num_resources = ARRAY_SIZE(twi_resources), +}; + +void __init at91_add_device_i2c(void) +{ + /* pins used for TWI interface */ + at91_set_A_periph(AT91_PIN_PA7, 0); /* TWD */ + at91_set_multi_drive(AT91_PIN_PA7, 1); + + at91_set_A_periph(AT91_PIN_PA8, 0); /* TWCK */ + at91_set_multi_drive(AT91_PIN_PA8, 1); + + platform_device_register(&at91sam9261_twi_device); +} +#else +void __init at91_add_device_i2c(void) {} +#endif + + +/* -------------------------------------------------------------------- + * SPI + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_SPI_ATMEL) || defined(CONFIG_SPI_ATMEL_MODULE) +static u64 spi_dmamask = 0xffffffffUL; + +static struct resource spi0_resources[] = { + [0] = { + .start = AT91SAM9261_BASE_SPI0, + .end = AT91SAM9261_BASE_SPI0 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9261_ID_SPI0, + .end = AT91SAM9261_ID_SPI0, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91sam9261_spi0_device = { + .name = "atmel_spi", + .id = 0, + .dev = { + .dma_mask = &spi_dmamask, + .coherent_dma_mask = 0xffffffff, + }, + .resource = spi0_resources, + .num_resources = ARRAY_SIZE(spi0_resources), +}; + +static const unsigned spi0_standard_cs[4] = { AT91_PIN_PA3, AT91_PIN_PA4, AT91_PIN_PA5, AT91_PIN_PA6 }; + +static struct resource spi1_resources[] = { + [0] = { + .start = AT91SAM9261_BASE_SPI1, + .end = AT91SAM9261_BASE_SPI1 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9261_ID_SPI1, + .end = AT91SAM9261_ID_SPI1, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91sam9261_spi1_device = { + .name = "atmel_spi", + .id = 1, + .dev = { + .dma_mask = &spi_dmamask, + .coherent_dma_mask = 0xffffffff, + }, + .resource = spi1_resources, + .num_resources = ARRAY_SIZE(spi1_resources), +}; + +static const unsigned spi1_standard_cs[4] = { AT91_PIN_PB28, AT91_PIN_PA24, AT91_PIN_PA25, AT91_PIN_PA26 }; + +void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) +{ + int i; + unsigned long cs_pin; + short enable_spi0 = 0; + short enable_spi1 = 0; + + /* Choose SPI chip-selects */ + for (i = 0; i < nr_devices; i++) { + if (devices[i].controller_data) + cs_pin = (unsigned long) devices[i].controller_data; + else if (devices[i].bus_num == 0) + cs_pin = spi0_standard_cs[devices[i].chip_select]; + else + cs_pin = spi1_standard_cs[devices[i].chip_select]; + + if (devices[i].bus_num == 0) + enable_spi0 = 1; + else + enable_spi1 = 1; + + /* enable chip-select pin */ + at91_set_gpio_output(cs_pin, 1); + + /* pass chip-select pin to driver */ + devices[i].controller_data = (void *) cs_pin; + } + + spi_register_board_info(devices, nr_devices); + + /* Configure SPI bus(es) */ + if (enable_spi0) { + at91_set_A_periph(AT91_PIN_PA0, 0); /* SPI0_MISO */ + at91_set_A_periph(AT91_PIN_PA1, 0); /* SPI0_MOSI */ + at91_set_A_periph(AT91_PIN_PA2, 0); /* SPI0_SPCK */ + + at91_clock_associate("spi0_clk", &at91sam9261_spi0_device.dev, "spi_clk"); + platform_device_register(&at91sam9261_spi0_device); + } + if (enable_spi1) { + at91_set_A_periph(AT91_PIN_PB30, 0); /* SPI1_MISO */ + at91_set_A_periph(AT91_PIN_PB31, 0); /* SPI1_MOSI */ + at91_set_A_periph(AT91_PIN_PB29, 0); /* SPI1_SPCK */ + + at91_clock_associate("spi1_clk", &at91sam9261_spi1_device.dev, "spi_clk"); + platform_device_register(&at91sam9261_spi1_device); + } +} +#else +void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) {} +#endif + + +/* -------------------------------------------------------------------- + * LCD Controller + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_FB_AT91) || defined(CONFIG_FB_AT91_MODULE) +static u64 lcdc_dmamask = 0xffffffffUL; +static struct at91fb_info lcdc_data; + +static struct resource lcdc_resources[] = { + [0] = { + .start = AT91SAM9261_LCDC_BASE, + .end = AT91SAM9261_LCDC_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9261_ID_LCDC, + .end = AT91SAM9261_ID_LCDC, + .flags = IORESOURCE_IRQ, + }, +#if defined(CONFIG_FB_INTSRAM) + [2] = { + .start = AT91SAM9261_SRAM_BASE, + .end = AT91SAM9261_SRAM_BASE + AT91SAM9261_SRAM_SIZE - 1, + .flags = IORESOURCE_MEM, + }, +#endif +}; + +static struct platform_device at91_lcdc_device = { + .name = "at91-fb", + .id = 0, + .dev = { + .dma_mask = &lcdc_dmamask, + .coherent_dma_mask = 0xffffffff, + .platform_data = &lcdc_data, + }, + .resource = lcdc_resources, + .num_resources = ARRAY_SIZE(lcdc_resources), +}; + +void __init at91_add_device_lcdc(struct at91fb_info *data) +{ + if (!data) { + return; + } + + at91_set_A_periph(AT91_PIN_PB1, 0); /* LCDHSYNC */ + at91_set_A_periph(AT91_PIN_PB2, 0); /* LCDDOTCK */ + at91_set_A_periph(AT91_PIN_PB3, 0); /* LCDDEN */ + at91_set_A_periph(AT91_PIN_PB4, 0); /* LCDCC */ + at91_set_A_periph(AT91_PIN_PB7, 0); /* LCDD2 */ + at91_set_A_periph(AT91_PIN_PB8, 0); /* LCDD3 */ + at91_set_A_periph(AT91_PIN_PB9, 0); /* LCDD4 */ + at91_set_A_periph(AT91_PIN_PB10, 0); /* LCDD5 */ + at91_set_A_periph(AT91_PIN_PB11, 0); /* LCDD6 */ + at91_set_A_periph(AT91_PIN_PB12, 0); /* LCDD7 */ + at91_set_A_periph(AT91_PIN_PB15, 0); /* LCDD10 */ + at91_set_A_periph(AT91_PIN_PB16, 0); /* LCDD11 */ + at91_set_A_periph(AT91_PIN_PB17, 0); /* LCDD12 */ + at91_set_A_periph(AT91_PIN_PB18, 0); /* LCDD13 */ + at91_set_A_periph(AT91_PIN_PB19, 0); /* LCDD14 */ + at91_set_A_periph(AT91_PIN_PB20, 0); /* LCDD15 */ + at91_set_B_periph(AT91_PIN_PB23, 0); /* LCDD18 */ + at91_set_B_periph(AT91_PIN_PB24, 0); /* LCDD19 */ + at91_set_B_periph(AT91_PIN_PB25, 0); /* LCDD20 */ + at91_set_B_periph(AT91_PIN_PB26, 0); /* LCDD21 */ + at91_set_B_periph(AT91_PIN_PB27, 0); /* LCDD22 */ + at91_set_B_periph(AT91_PIN_PB28, 0); /* LCDD23 */ + + lcdc_data = *data; + platform_device_register(&at91_lcdc_device); +} +#else +void __init at91_add_device_lcdc(struct at91fb_info *data) {} +#endif + + +/* -------------------------------------------------------------------- + * LEDs + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_LEDS) +u8 at91_leds_cpu; +u8 at91_leds_timer; + +void __init at91_init_leds(u8 cpu_led, u8 timer_led) +{ + at91_leds_cpu = cpu_led; + at91_leds_timer = timer_led; +} +#else +void __init at91_init_leds(u8 cpu_led, u8 timer_led) {} +#endif + + +/* -------------------------------------------------------------------- + * UART + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_SERIAL_ATMEL) +static struct resource dbgu_resources[] = { + [0] = { + .start = AT91_VA_BASE_SYS + AT91_DBGU, + .end = AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91_ID_SYS, + .end = AT91_ID_SYS, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct atmel_uart_data dbgu_data = { + .use_dma_tx = 0, + .use_dma_rx = 0, /* DBGU not capable of receive DMA */ + .regs = (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU), +}; + +static struct platform_device at91sam9261_dbgu_device = { + .name = "atmel_usart", + .id = 0, + .dev = { + .platform_data = &dbgu_data, + .coherent_dma_mask = 0xffffffff, + }, + .resource = dbgu_resources, + .num_resources = ARRAY_SIZE(dbgu_resources), +}; + +static inline void configure_dbgu_pins(void) +{ + at91_set_A_periph(AT91_PIN_PA9, 0); /* DRXD */ + at91_set_A_periph(AT91_PIN_PA10, 1); /* DTXD */ +} + +static struct resource uart0_resources[] = { + [0] = { + .start = AT91SAM9261_BASE_US0, + .end = AT91SAM9261_BASE_US0 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9261_ID_US0, + .end = AT91SAM9261_ID_US0, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct atmel_uart_data uart0_data = { + .use_dma_tx = 1, + .use_dma_rx = 1, +}; + +static struct platform_device at91sam9261_uart0_device = { + .name = "atmel_usart", + .id = 1, + .dev = { + .platform_data = &uart0_data, + .coherent_dma_mask = 0xffffffff, + }, + .resource = uart0_resources, + .num_resources = ARRAY_SIZE(uart0_resources), +}; + +static inline void configure_usart0_pins(void) +{ + at91_set_A_periph(AT91_PIN_PC8, 1); /* TXD0 */ + at91_set_A_periph(AT91_PIN_PC9, 0); /* RXD0 */ + at91_set_A_periph(AT91_PIN_PC10, 0); /* RTS0 */ + at91_set_A_periph(AT91_PIN_PC11, 0); /* CTS0 */ +} + +static struct resource uart1_resources[] = { + [0] = { + .start = AT91SAM9261_BASE_US1, + .end = AT91SAM9261_BASE_US1 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9261_ID_US1, + .end = AT91SAM9261_ID_US1, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct atmel_uart_data uart1_data = { + .use_dma_tx = 1, + .use_dma_rx = 1, +}; + +static struct platform_device at91sam9261_uart1_device = { + .name = "atmel_usart", + .id = 2, + .dev = { + .platform_data = &uart1_data, + .coherent_dma_mask = 0xffffffff, + }, + .resource = uart1_resources, + .num_resources = ARRAY_SIZE(uart1_resources), +}; + +static inline void configure_usart1_pins(void) +{ + at91_set_A_periph(AT91_PIN_PC12, 1); /* TXD1 */ + at91_set_A_periph(AT91_PIN_PC13, 0); /* RXD1 */ +} + +static struct resource uart2_resources[] = { + [0] = { + .start = AT91SAM9261_BASE_US2, + .end = AT91SAM9261_BASE_US2 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9261_ID_US2, + .end = AT91SAM9261_ID_US2, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct atmel_uart_data uart2_data = { + .use_dma_tx = 1, + .use_dma_rx = 1, +}; + +static struct platform_device at91sam9261_uart2_device = { + .name = "atmel_usart", + .id = 3, + .dev = { + .platform_data = &uart2_data, + .coherent_dma_mask = 0xffffffff, + }, + .resource = uart2_resources, + .num_resources = ARRAY_SIZE(uart2_resources), +}; + +static inline void configure_usart2_pins(void) +{ + at91_set_A_periph(AT91_PIN_PC15, 0); /* RXD2 */ + at91_set_A_periph(AT91_PIN_PC14, 1); /* TXD2 */ +} + +struct platform_device *at91_uarts[ATMEL_MAX_UART]; /* the UARTs to use */ +struct platform_device *atmel_default_console_device; /* the serial console device */ + +void __init at91_init_serial(struct at91_uart_config *config) +{ + int i; + + /* Fill in list of supported UARTs */ + for (i = 0; i < config->nr_tty; i++) { + switch (config->tty_map[i]) { + case 0: + configure_usart0_pins(); + at91_uarts[i] = &at91sam9261_uart0_device; + at91_clock_associate("usart0_clk", &at91sam9261_uart0_device.dev, "usart"); + break; + case 1: + configure_usart1_pins(); + at91_uarts[i] = &at91sam9261_uart1_device; + at91_clock_associate("usart1_clk", &at91sam9261_uart1_device.dev, "usart"); + break; + case 2: + configure_usart2_pins(); + at91_uarts[i] = &at91sam9261_uart2_device; + at91_clock_associate("usart2_clk", &at91sam9261_uart2_device.dev, "usart"); + break; + case 3: + configure_dbgu_pins(); + at91_uarts[i] = &at91sam9261_dbgu_device; + at91_clock_associate("mck", &at91sam9261_dbgu_device.dev, "usart"); + break; + default: + continue; + } + at91_uarts[i]->id = i; /* update ID number to mapped ID */ + } + + /* Set serial console device */ + if (config->console_tty < ATMEL_MAX_UART) + atmel_default_console_device = at91_uarts[config->console_tty]; + if (!atmel_default_console_device) + printk(KERN_INFO "AT91: No default serial console defined.\n"); +} + +void __init at91_add_device_serial(void) +{ + int i; + + for (i = 0; i < ATMEL_MAX_UART; i++) { + if (at91_uarts[i]) + platform_device_register(at91_uarts[i]); + } +} +#else +void __init at91_init_serial(struct at91_uart_config *config) {} +void __init at91_add_device_serial(void) {} +#endif + + +/* -------------------------------------------------------------------- */ + +/* + * These devices are always present and don't need any board-specific + * setup. + */ +static int __init at91_add_standard_devices(void) +{ + return 0; +} + +arch_initcall(at91_add_standard_devices); diff --git a/trunk/arch/arm/mach-at91rm9200/at91sam926x_time.c b/trunk/arch/arm/mach-at91rm9200/at91sam926x_time.c new file mode 100644 index 000000000000..99df5f6ee42e --- /dev/null +++ b/trunk/arch/arm/mach-at91rm9200/at91sam926x_time.c @@ -0,0 +1,114 @@ +/* + * linux/arch/arm/mach-at91rm9200/at91sam926x_time.c + * + * Copyright (C) 2005-2006 M. Amine SAYA, ATMEL Rousset, France + * Revision 2005 M. Nicolas Diremdjian, ATMEL Rousset, France + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + + +#define PIT_CPIV(x) ((x) & AT91_PIT_CPIV) +#define PIT_PICNT(x) (((x) & AT91_PIT_PICNT) >> 20) + +/* + * Returns number of microseconds since last timer interrupt. Note that interrupts + * will have been disabled by do_gettimeofday() + * 'LATCH' is hwclock ticks (see CLOCK_TICK_RATE in timex.h) per jiffy. + * 'tick' is usecs per jiffy (linux/timex.h). + */ +static unsigned long at91sam926x_gettimeoffset(void) +{ + unsigned long elapsed; + unsigned long t = at91_sys_read(AT91_PIT_PIIR); + + elapsed = (PIT_PICNT(t) * LATCH) + PIT_CPIV(t); /* hardware clock cycles */ + + return (unsigned long)(elapsed * 1000000) / LATCH; +} + +/* + * IRQ handler for the timer. + */ +static irqreturn_t at91sam926x_timer_interrupt(int irq, void *dev_id) +{ + volatile long nr_ticks; + + if (at91_sys_read(AT91_PIT_SR) & AT91_PIT_PITS) { /* This is a shared interrupt */ + write_seqlock(&xtime_lock); + + /* Get number to ticks performed before interrupt and clear PIT interrupt */ + nr_ticks = PIT_PICNT(at91_sys_read(AT91_PIT_PIVR)); + do { + timer_tick(); + nr_ticks--; + } while (nr_ticks); + + write_sequnlock(&xtime_lock); + return IRQ_HANDLED; + } else + return IRQ_NONE; /* not handled */ +} + +static struct irqaction at91sam926x_timer_irq = { + .name = "at91_tick", + .flags = IRQF_SHARED | IRQF_DISABLED | IRQF_TIMER, + .handler = at91sam926x_timer_interrupt +}; + +void at91sam926x_timer_reset(void) +{ + /* Disable timer */ + at91_sys_write(AT91_PIT_MR, 0); + + /* Clear any pending interrupts */ + (void) at91_sys_read(AT91_PIT_PIVR); + + /* Set Period Interval timer and enable its interrupt */ + at91_sys_write(AT91_PIT_MR, (LATCH & AT91_PIT_PIV) | AT91_PIT_PITIEN | AT91_PIT_PITEN); +} + +/* + * Set up timer interrupt. + */ +void __init at91sam926x_timer_init(void) +{ + /* Initialize and enable the timer */ + at91sam926x_timer_reset(); + + /* Make IRQs happen for the system timer. */ + setup_irq(AT91_ID_SYS, &at91sam926x_timer_irq); +} + +#ifdef CONFIG_PM +static void at91sam926x_timer_suspend(void) +{ + /* Disable timer */ + at91_sys_write(AT91_PIT_MR, 0); +} +#else +#define at91sam926x_timer_suspend NULL +#endif + +struct sys_timer at91sam926x_timer = { + .init = at91sam926x_timer_init, + .offset = at91sam926x_gettimeoffset, + .suspend = at91sam926x_timer_suspend, + .resume = at91sam926x_timer_reset, +}; + diff --git a/trunk/arch/arm/mach-at91rm9200/board-carmeva.c b/trunk/arch/arm/mach-at91rm9200/board-carmeva.c index 98208740e7c5..654f0379550a 100644 --- a/trunk/arch/arm/mach-at91rm9200/board-carmeva.c +++ b/trunk/arch/arm/mach-at91rm9200/board-carmeva.c @@ -65,7 +65,6 @@ static void __init carmeva_init_irq(void) at91rm9200_init_interrupts(NULL); } - static struct at91_eth_data __initdata carmeva_eth_data = { .phy_irq_pin = AT91_PIN_PC4, .is_rmii = 1, @@ -89,8 +88,33 @@ static struct at91_udc_data __initdata carmeva_udc_data = { // }; static struct at91_mmc_data __initdata carmeva_mmc_data = { - .is_b = 0, + .slot_b = 0, .wire4 = 1, + .det_pin = AT91_PIN_PB10, + .wp_pin = AT91_PIN_PC14, +}; + +static struct spi_board_info carmeva_spi_devices[] = { + { /* DataFlash chip */ + .modalias = "mtd_dataflash", + .chip_select = 0, + .max_speed_hz = 10 * 1000 * 1000, + }, + { /* User accessable spi - cs1 (250KHz) */ + .modalias = "spi-cs1", + .chip_select = 1, + .max_speed_hz = 250 * 1000, + }, + { /* User accessable spi - cs2 (1MHz) */ + .modalias = "spi-cs2", + .chip_select = 2, + .max_speed_hz = 1 * 1000 * 1000, + }, + { /* User accessable spi - cs3 (10MHz) */ + .modalias = "spi-cs3", + .chip_select = 3, + .max_speed_hz = 10 * 1000 * 1000, + }, }; static void __init carmeva_board_init(void) @@ -105,10 +129,10 @@ static void __init carmeva_board_init(void) at91_add_device_udc(&carmeva_udc_data); /* I2C */ at91_add_device_i2c(); + /* SPI */ + at91_add_device_spi(carmeva_spi_devices, ARRAY_SIZE(carmeva_spi_devices)); /* Compact Flash */ // at91_add_device_cf(&carmeva_cf_data); - /* SPI */ -// at91_add_device_spi(NULL, 0); /* MMC */ at91_add_device_mmc(&carmeva_mmc_data); } diff --git a/trunk/arch/arm/mach-at91rm9200/board-csb337.c b/trunk/arch/arm/mach-at91rm9200/board-csb337.c index 8eeae491ce71..b8bb8052607a 100644 --- a/trunk/arch/arm/mach-at91rm9200/board-csb337.c +++ b/trunk/arch/arm/mach-at91rm9200/board-csb337.c @@ -99,7 +99,7 @@ static struct at91_cf_data __initdata csb337_cf_data = { static struct at91_mmc_data __initdata csb337_mmc_data = { .det_pin = AT91_PIN_PD5, - .is_b = 0, + .slot_b = 0, .wire4 = 1, .wp_pin = AT91_PIN_PD6, }; diff --git a/trunk/arch/arm/mach-at91rm9200/board-dk.c b/trunk/arch/arm/mach-at91rm9200/board-dk.c index c699f3984d4b..7522bf91bce8 100644 --- a/trunk/arch/arm/mach-at91rm9200/board-dk.c +++ b/trunk/arch/arm/mach-at91rm9200/board-dk.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -39,6 +40,7 @@ #include #include +#include #include "generic.h" @@ -93,7 +95,7 @@ static struct at91_cf_data __initdata dk_cf_data = { }; static struct at91_mmc_data __initdata dk_mmc_data = { - .is_b = 0, + .slot_b = 0, .wire4 = 1, }; @@ -145,6 +147,30 @@ static struct at91_nand_data __initdata dk_nand_data = { .partition_info = nand_partitions, }; +#define DK_FLASH_BASE AT91_CHIPSELECT_0 +#define DK_FLASH_SIZE 0x200000 + +static struct physmap_flash_data dk_flash_data = { + .width = 2, +}; + +static struct resource dk_flash_resource = { + .start = DK_FLASH_BASE, + .end = DK_FLASH_BASE + DK_FLASH_SIZE - 1, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device dk_flash = { + .name = "physmap-flash", + .id = 0, + .dev = { + .platform_data = &dk_flash_data, + }, + .resource = &dk_flash_resource, + .num_resources = 1, +}; + + static void __init dk_board_init(void) { /* Serial */ @@ -172,6 +198,8 @@ static void __init dk_board_init(void) #endif /* NAND */ at91_add_device_nand(&dk_nand_data); + /* NOR Flash */ + platform_device_register(&dk_flash); /* VGA */ // dk_add_device_video(); } diff --git a/trunk/arch/arm/mach-at91rm9200/board-eb9200.c b/trunk/arch/arm/mach-at91rm9200/board-eb9200.c index 65e867ba2df3..80b72cf7264c 100644 --- a/trunk/arch/arm/mach-at91rm9200/board-eb9200.c +++ b/trunk/arch/arm/mach-at91rm9200/board-eb9200.c @@ -87,7 +87,7 @@ static struct at91_cf_data __initdata eb9200_cf_data = { }; static struct at91_mmc_data __initdata eb9200_mmc_data = { - .is_b = 0, + .slot_b = 0, .wire4 = 1, }; diff --git a/trunk/arch/arm/mach-at91rm9200/board-ek.c b/trunk/arch/arm/mach-at91rm9200/board-ek.c index 830eb7932178..c4fdb415f20e 100644 --- a/trunk/arch/arm/mach-at91rm9200/board-ek.c +++ b/trunk/arch/arm/mach-at91rm9200/board-ek.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -39,6 +40,7 @@ #include #include +#include #include "generic.h" @@ -87,7 +89,7 @@ static struct at91_udc_data __initdata ek_udc_data = { static struct at91_mmc_data __initdata ek_mmc_data = { .det_pin = AT91_PIN_PB27, - .is_b = 0, + .slot_b = 0, .wire4 = 1, .wp_pin = AT91_PIN_PA17, }; @@ -107,6 +109,30 @@ static struct spi_board_info ek_spi_devices[] = { #endif }; +#define EK_FLASH_BASE AT91_CHIPSELECT_0 +#define EK_FLASH_SIZE 0x200000 + +static struct physmap_flash_data ek_flash_data = { + .width = 2, +}; + +static struct resource ek_flash_resource = { + .start = EK_FLASH_BASE, + .end = EK_FLASH_BASE + EK_FLASH_SIZE - 1, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device ek_flash = { + .name = "physmap-flash", + .id = 0, + .dev = { + .platform_data = &ek_flash_data, + }, + .resource = &ek_flash_resource, + .num_resources = 1, +}; + + static void __init ek_board_init(void) { /* Serial */ @@ -130,6 +156,8 @@ static void __init ek_board_init(void) at91_set_gpio_output(AT91_PIN_PB22, 1); /* this MMC card slot can optionally use SPI signaling (CS3). */ at91_add_device_mmc(&ek_mmc_data); #endif + /* NOR Flash */ + platform_device_register(&ek_flash); /* VGA */ // ek_add_device_video(); } diff --git a/trunk/arch/arm/mach-at91rm9200/board-kb9202.c b/trunk/arch/arm/mach-at91rm9200/board-kb9202.c index 35a954a44b1b..759d8191854f 100644 --- a/trunk/arch/arm/mach-at91rm9200/board-kb9202.c +++ b/trunk/arch/arm/mach-at91rm9200/board-kb9202.c @@ -84,7 +84,7 @@ static struct at91_udc_data __initdata kb9202_udc_data = { static struct at91_mmc_data __initdata kb9202_mmc_data = { .det_pin = AT91_PIN_PB2, - .is_b = 0, + .slot_b = 0, .wire4 = 1, }; diff --git a/trunk/arch/arm/mach-at91rm9200/board-sam9260ek.c b/trunk/arch/arm/mach-at91rm9200/board-sam9260ek.c new file mode 100644 index 000000000000..ffca9bdec37b --- /dev/null +++ b/trunk/arch/arm/mach-at91rm9200/board-sam9260ek.c @@ -0,0 +1,201 @@ +/* + * linux/arch/arm/mach-at91rm9200/board-ek.c + * + * Copyright (C) 2005 SAN People + * Copyright (C) 2006 Atmel + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include "generic.h" + + +/* + * Serial port configuration. + * 0 .. 5 = USART0 .. USART5 + * 6 = DBGU + */ +static struct at91_uart_config __initdata ek_uart_config = { + .console_tty = 0, /* ttyS0 */ + .nr_tty = 3, + .tty_map = { 6, 0, 1, -1, -1, -1, -1 } /* ttyS0, ..., ttyS6 */ +}; + +static void __init ek_map_io(void) +{ + /* Initialize processor: 18.432 MHz crystal */ + at91sam9260_initialize(18432000); + + /* Setup the serial ports and console */ + at91_init_serial(&ek_uart_config); +} + +static void __init ek_init_irq(void) +{ + at91sam9260_init_interrupts(NULL); +} + + +/* + * USB Host port + */ +static struct at91_usbh_data __initdata ek_usbh_data = { + .ports = 2, +}; + +/* + * USB Device port + */ +static struct at91_udc_data __initdata ek_udc_data = { + .vbus_pin = AT91_PIN_PC5, + .pullup_pin = 0, /* pull-up driven by UDC */ +}; + + +/* + * SPI devices. + */ +static struct spi_board_info ek_spi_devices[] = { +#if !defined(CONFIG_MMC_AT91) + { /* DataFlash chip */ + .modalias = "mtd_dataflash", + .chip_select = 1, + .max_speed_hz = 15 * 1000 * 1000, + .bus_num = 0, + }, +#if defined(CONFIG_MTD_AT91_DATAFLASH_CARD) + { /* DataFlash card */ + .modalias = "mtd_dataflash", + .chip_select = 0, + .max_speed_hz = 15 * 1000 * 1000, + .bus_num = 0, + }, +#endif +#endif +#if defined(CONFIG_SND_AT73C213) + { /* AT73C213 DAC */ + .modalias = "snd_at73c213", + .chip_select = 0, + .max_speed_hz = 10 * 1000 * 1000, + .bus_num = 1, + }, +#endif +}; + + +/* + * MACB Ethernet device + */ +static struct __initdata eth_platform_data ek_macb_data = { + .is_rmii = 1, +}; + + +/* + * NAND flash + */ +static struct mtd_partition __initdata ek_nand_partition[] = { + { + .name = "Partition 1", + .offset = 0, + .size = 256 * 1024, + }, + { + .name = "Partition 2", + .offset = 256 * 1024, + .size = MTDPART_SIZ_FULL, + }, +}; + +static struct mtd_partition *nand_partitions(int size, int *num_partitions) +{ + *num_partitions = ARRAY_SIZE(ek_nand_partition); + return ek_nand_partition; +} + +static struct at91_nand_data __initdata ek_nand_data = { + .ale = 21, + .cle = 22, +// .det_pin = ... not connected + .rdy_pin = AT91_PIN_PC13, + .enable_pin = AT91_PIN_PC14, + .partition_info = nand_partitions, +#if defined(CONFIG_MTD_NAND_AT91_BUSWIDTH_16) + .bus_width_16 = 1, +#else + .bus_width_16 = 0, +#endif +}; + + +/* + * MCI (SD/MMC) + */ +static struct at91_mmc_data __initdata ek_mmc_data = { + .slot_b = 1, + .wire4 = 1, +// .det_pin = ... not connected +// .wp_pin = ... not connected +// .vcc_pin = ... not connected +}; + +static void __init ek_board_init(void) +{ + /* Serial */ + at91_add_device_serial(); + /* USB Host */ + at91_add_device_usbh(&ek_usbh_data); + /* USB Device */ + at91_add_device_udc(&ek_udc_data); + /* SPI */ + at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices)); + /* NAND */ + at91_add_device_nand(&ek_nand_data); + /* Ethernet */ + at91_add_device_eth(&ek_macb_data); + /* MMC */ + at91_add_device_mmc(&ek_mmc_data); +} + +MACHINE_START(AT91SAM9260EK, "Atmel AT91SAM9260-EK") + /* Maintainer: Atmel */ + .phys_io = AT91_BASE_SYS, + .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc, + .boot_params = AT91_SDRAM_BASE + 0x100, + .timer = &at91sam926x_timer, + .map_io = ek_map_io, + .init_irq = ek_init_irq, + .init_machine = ek_board_init, +MACHINE_END diff --git a/trunk/arch/arm/mach-at91rm9200/board-sam9261ek.c b/trunk/arch/arm/mach-at91rm9200/board-sam9261ek.c new file mode 100644 index 000000000000..30b490d8886b --- /dev/null +++ b/trunk/arch/arm/mach-at91rm9200/board-sam9261ek.c @@ -0,0 +1,259 @@ +/* + * linux/arch/arm/mach-at91rm9200/board-ek.c + * + * Copyright (C) 2005 SAN People + * Copyright (C) 2006 Atmel + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include "generic.h" + + +/* + * Serial port configuration. + * 0 .. 2 = USART0 .. USART2 + * 3 = DBGU + */ +static struct at91_uart_config __initdata ek_uart_config = { + .console_tty = 0, /* ttyS0 */ + .nr_tty = 1, + .tty_map = { 3, -1, -1, -1 } /* ttyS0, ..., ttyS3 */ +}; + +static void __init ek_map_io(void) +{ + /* Initialize processor: 18.432 MHz crystal */ + at91sam9261_initialize(18432000); + + /* Setup the serial ports and console */ + at91_init_serial(&ek_uart_config); +} + +static void __init ek_init_irq(void) +{ + at91sam9261_init_interrupts(NULL); +} + + +/* + * DM9000 ethernet device + */ +#if defined(CONFIG_DM9000) +static struct resource at91sam9261_dm9000_resource[] = { + [0] = { + .start = AT91_CHIPSELECT_2, + .end = AT91_CHIPSELECT_2 + 3, + .flags = IORESOURCE_MEM + }, + [1] = { + .start = AT91_CHIPSELECT_2 + 0x44, + .end = AT91_CHIPSELECT_2 + 0xFF, + .flags = IORESOURCE_MEM + }, + [2] = { + .start = AT91_PIN_PC11, + .end = AT91_PIN_PC11, + .flags = IORESOURCE_IRQ + } +}; + +static struct dm9000_plat_data dm9000_platdata = { + .flags = DM9000_PLATF_16BITONLY, +}; + +static struct platform_device at91sam9261_dm9000_device = { + .name = "dm9000", + .id = 0, + .num_resources = ARRAY_SIZE(at91sam9261_dm9000_resource), + .resource = at91sam9261_dm9000_resource, + .dev = { + .platform_data = &dm9000_platdata, + } +}; + +static void __init ek_add_device_dm9000(void) +{ + /* + * Configure Chip-Select 2 on SMC for the DM9000. + * Note: These timings were calculated for MASTER_CLOCK = 100000000 + * according to the DM9000 timings. + */ + at91_sys_write(AT91_SMC_SETUP(2), AT91_SMC_NWESETUP_(2) | AT91_SMC_NCS_WRSETUP_(0) | AT91_SMC_NRDSETUP_(2) | AT91_SMC_NCS_RDSETUP_(0)); + at91_sys_write(AT91_SMC_PULSE(2), AT91_SMC_NWEPULSE_(4) | AT91_SMC_NCS_WRPULSE_(8) | AT91_SMC_NRDPULSE_(4) | AT91_SMC_NCS_RDPULSE_(8)); + at91_sys_write(AT91_SMC_CYCLE(2), AT91_SMC_NWECYCLE_(16) | AT91_SMC_NRDCYCLE_(16)); + at91_sys_write(AT91_SMC_MODE(2), AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_BAT_WRITE | AT91_SMC_DBW_16 | AT91_SMC_TDF_(1)); + + /* Configure Reset signal as output */ + at91_set_gpio_output(AT91_PIN_PC10, 0); + + /* Configure Interrupt pin as input, no pull-up */ + at91_set_gpio_input(AT91_PIN_PC11, 0); + + platform_device_register(&at91sam9261_dm9000_device); +} +#else +static void __init ek_add_device_dm9000(void) {} +#endif /* CONFIG_DM9000 */ + + +/* + * USB Host Port + */ +static struct at91_usbh_data __initdata ek_usbh_data = { + .ports = 2, +}; + + +/* + * USB Device Port + */ +static struct at91_udc_data __initdata ek_udc_data = { + .vbus_pin = AT91_PIN_PB29, + .pullup_pin = 0, /* pull-up driven by UDC */ +}; + + +/* + * MCI (SD/MMC) + */ +static struct at91_mmc_data __initdata ek_mmc_data = { + .wire4 = 1, +// .det_pin = ... not connected +// .wp_pin = ... not connected +// .vcc_pin = ... not connected +}; + + +/* + * NAND flash + */ +static struct mtd_partition __initdata ek_nand_partition[] = { + { + .name = "Partition 1", + .offset = 0, + .size = 256 * 1024, + }, + { + .name = "Partition 2", + .offset = 256 * 1024 , + .size = MTDPART_SIZ_FULL, + }, +}; + +static struct mtd_partition *nand_partitions(int size, int *num_partitions) +{ + *num_partitions = ARRAY_SIZE(ek_nand_partition); + return ek_nand_partition; +} + +static struct at91_nand_data __initdata ek_nand_data = { + .ale = 22, + .cle = 21, +// .det_pin = ... not connected + .rdy_pin = AT91_PIN_PC15, + .enable_pin = AT91_PIN_PC14, + .partition_info = nand_partitions, +#if defined(CONFIG_MTD_NAND_AT91_BUSWIDTH_16) + .bus_width_16 = 1, +#else + .bus_width_16 = 0, +#endif +}; + +/* + * SPI devices + */ +static struct spi_board_info ek_spi_devices[] = { + { /* DataFlash chip */ + .modalias = "mtd_dataflash", + .chip_select = 0, + .max_speed_hz = 15 * 1000 * 1000, + .bus_num = 0, + }, +#if defined(CONFIG_MTD_AT91_DATAFLASH_CARD) + { /* DataFlash card - jumper (J12) configurable to CS3 or CS0 */ + .modalias = "mtd_dataflash", + .chip_select = 3, + .max_speed_hz = 15 * 1000 * 1000, + .bus_num = 0, + }, +#elif defined(CONFIG_SND_AT73C213) + { /* AT73C213 DAC */ + .modalias = "snd_at73c213", + .chip_select = 3, + .max_speed_hz = 10 * 1000 * 1000, + .bus_num = 0, + }, +#endif +}; + + +static void __init ek_board_init(void) +{ + /* Serial */ + at91_add_device_serial(); + /* USB Host */ + at91_add_device_usbh(&ek_usbh_data); + /* USB Device */ + at91_add_device_udc(&ek_udc_data); + /* I2C */ + at91_add_device_i2c(); + /* NAND */ + at91_add_device_nand(&ek_nand_data); + /* DM9000 ethernet */ + ek_add_device_dm9000(); + + /* spi0 and mmc/sd share the same PIO pins */ +#if defined(CONFIG_SPI_ATMEL) || defined(CONFIG_SPI_ATMEL_MODULE) + /* SPI */ + at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices)); +#else + /* MMC */ + at91_add_device_mmc(&ek_mmc_data); +#endif +} + +MACHINE_START(AT91SAM9261EK, "Atmel AT91SAM9261-EK") + /* Maintainer: Atmel */ + .phys_io = AT91_BASE_SYS, + .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc, + .boot_params = AT91_SDRAM_BASE + 0x100, + .timer = &at91sam926x_timer, + .map_io = ek_map_io, + .init_irq = ek_init_irq, + .init_machine = ek_board_init, +MACHINE_END diff --git a/trunk/arch/arm/mach-at91rm9200/clock.c b/trunk/arch/arm/mach-at91rm9200/clock.c index a43b061a7c85..4dee21fefe5a 100644 --- a/trunk/arch/arm/mach-at91rm9200/clock.c +++ b/trunk/arch/arm/mach-at91rm9200/clock.c @@ -28,6 +28,8 @@ #include #include +#include +#include #include "clock.h" @@ -41,6 +43,7 @@ #define clk_is_primary(x) ((x)->type & CLK_TYPE_PRIMARY) #define clk_is_programmable(x) ((x)->type & CLK_TYPE_PROGRAMMABLE) #define clk_is_peripheral(x) ((x)->type & CLK_TYPE_PERIPHERAL) +#define clk_is_sys(x) ((x)->type & CLK_TYPE_SYSTEM) static LIST_HEAD(clocks); @@ -114,13 +117,11 @@ static void pmc_sys_mode(struct clk *clk, int is_on) static struct clk udpck = { .name = "udpck", .parent = &pllb, - .pmc_mask = AT91_PMC_UDP, .mode = pmc_sys_mode, }; static struct clk uhpck = { .name = "uhpck", .parent = &pllb, - .pmc_mask = AT91_PMC_UHP, .mode = pmc_sys_mode, }; @@ -434,6 +435,12 @@ int __init clk_register(struct clk *clk) clk->mode = pmc_periph_mode; list_add_tail(&clk->node, &clocks); } + else if (clk_is_sys(clk)) { + clk->parent = &mck; + clk->mode = pmc_sys_mode; + + list_add_tail(&clk->node, &clocks); + } #ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS else if (clk_is_programmable(clk)) { clk->mode = pmc_sys_mode; @@ -586,9 +593,21 @@ int __init at91_clock_init(unsigned long main_clock) */ at91_pllb_usb_init = at91_pll_calc(main_clock, 48000000 * 2) | AT91_PMC_USB96M; pllb.rate_hz = at91_pll_rate(&pllb, main_clock, at91_pllb_usb_init); - at91_sys_write(AT91_PMC_SCDR, AT91_PMC_UHP | AT91_PMC_UDP); + if (cpu_is_at91rm9200()) { + uhpck.pmc_mask = AT91RM9200_PMC_UHP; + udpck.pmc_mask = AT91RM9200_PMC_UDP; + at91_sys_write(AT91_PMC_SCDR, AT91RM9200_PMC_UHP | AT91RM9200_PMC_UDP); + at91_sys_write(AT91_PMC_SCER, AT91RM9200_PMC_MCKUDP); + } else if (cpu_is_at91sam9260()) { + uhpck.pmc_mask = AT91SAM926x_PMC_UHP; + udpck.pmc_mask = AT91SAM926x_PMC_UDP; + at91_sys_write(AT91_PMC_SCDR, AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP); + } else if (cpu_is_at91sam9261()) { + uhpck.pmc_mask = (AT91SAM926x_PMC_UHP | AT91_PMC_HCK0); + udpck.pmc_mask = AT91SAM926x_PMC_UDP; + at91_sys_write(AT91_PMC_SCDR, AT91SAM926x_PMC_UHP | AT91_PMC_HCK0 | AT91SAM926x_PMC_UDP); + } at91_sys_write(AT91_CKGR_PLLBR, 0); - at91_sys_write(AT91_PMC_SCER, AT91_PMC_MCKUDP); udpck.rate_hz = at91_usb_rate(&pllb, pllb.rate_hz, at91_pllb_usb_init); uhpck.rate_hz = at91_usb_rate(&pllb, pllb.rate_hz, at91_pllb_usb_init); diff --git a/trunk/arch/arm/mach-at91rm9200/clock.h b/trunk/arch/arm/mach-at91rm9200/clock.h index 0592e662ab37..b5c7a2eb2d1d 100644 --- a/trunk/arch/arm/mach-at91rm9200/clock.h +++ b/trunk/arch/arm/mach-at91rm9200/clock.h @@ -10,6 +10,7 @@ #define CLK_TYPE_PLL 0x2 #define CLK_TYPE_PROGRAMMABLE 0x4 #define CLK_TYPE_PERIPHERAL 0x8 +#define CLK_TYPE_SYSTEM 0x10 struct clk { diff --git a/trunk/arch/arm/mach-at91rm9200/generic.h b/trunk/arch/arm/mach-at91rm9200/generic.h index 694e411e285f..8c4d5a77d485 100644 --- a/trunk/arch/arm/mach-at91rm9200/generic.h +++ b/trunk/arch/arm/mach-at91rm9200/generic.h @@ -10,14 +10,19 @@ /* Processors */ extern void __init at91rm9200_initialize(unsigned long main_clock, unsigned short banks); +extern void __init at91sam9260_initialize(unsigned long main_clock); +extern void __init at91sam9261_initialize(unsigned long main_clock); /* Interrupts */ extern void __init at91rm9200_init_interrupts(unsigned int priority[]); +extern void __init at91sam9260_init_interrupts(unsigned int priority[]); +extern void __init at91sam9261_init_interrupts(unsigned int priority[]); extern void __init at91_aic_init(unsigned int priority[]); /* Timer */ struct sys_timer; extern struct sys_timer at91rm9200_timer; +extern struct sys_timer at91sam926x_timer; /* Clocks */ extern int __init at91_clock_init(unsigned long main_clock); @@ -39,3 +44,6 @@ struct at91_gpio_bank { }; extern void __init at91_gpio_init(struct at91_gpio_bank *, int nr_banks); extern void __init at91_gpio_irq_setup(void); + +extern void (*at91_arch_reset)(void); +extern int at91_extern_irq; diff --git a/trunk/arch/arm/mach-at91rm9200/gpio.c b/trunk/arch/arm/mach-at91rm9200/gpio.c index 7467d644f0a3..3f188508c391 100644 --- a/trunk/arch/arm/mach-at91rm9200/gpio.c +++ b/trunk/arch/arm/mach-at91rm9200/gpio.c @@ -19,6 +19,8 @@ #include #include +#include +#include #include #include "generic.h" @@ -332,10 +334,10 @@ static struct irq_chip gpio_irqchip = { .set_wake = gpio_irq_set_wake, }; -static void gpio_irq_handler(unsigned irq, struct irqdesc *desc) +static void gpio_irq_handler(unsigned irq, struct irq_desc *desc) { unsigned pin; - struct irqdesc *gpio; + struct irq_desc *gpio; void __iomem *pio; u32 isr; @@ -396,7 +398,7 @@ void __init at91_gpio_irq_setup(void) __raw_writel(~0, controller + PIO_IDR); set_irq_data(id, (void *) pin); - set_irq_chipdata(id, controller); + set_irq_chip_data(id, controller); for (i = 0; i < 32; i++, pin++) { /* @@ -404,7 +406,7 @@ void __init at91_gpio_irq_setup(void) * shorter, and the AIC handles interupts sanely. */ set_irq_chip(pin, &gpio_irqchip); - set_irq_handler(pin, do_simple_IRQ); + set_irq_handler(pin, handle_simple_irq); set_irq_flags(pin, IRQF_VALID); } diff --git a/trunk/arch/arm/mach-at91rm9200/irq.c b/trunk/arch/arm/mach-at91rm9200/irq.c index 3e488117ca91..2148daafd29c 100644 --- a/trunk/arch/arm/mach-at91rm9200/irq.c +++ b/trunk/arch/arm/mach-at91rm9200/irq.c @@ -47,6 +47,10 @@ static void at91_aic_unmask_irq(unsigned int irq) at91_sys_write(AT91_AIC_IECR, 1 << irq); } +unsigned int at91_extern_irq; + +#define is_extern_irq(irq) ((1 << (irq)) & at91_extern_irq) + static int at91_aic_set_type(unsigned irq, unsigned type) { unsigned int smr, srctype; @@ -59,14 +63,16 @@ static int at91_aic_set_type(unsigned irq, unsigned type) srctype = AT91_AIC_SRCTYPE_RISING; break; case IRQT_LOW: - if ((irq > AT91_ID_FIQ) && (irq < AT91RM9200_ID_IRQ0)) /* only supported on external interrupts */ + if ((irq == AT91_ID_FIQ) || is_extern_irq(irq)) /* only supported on external interrupts */ + srctype = AT91_AIC_SRCTYPE_LOW; + else return -EINVAL; - srctype = AT91_AIC_SRCTYPE_LOW; break; case IRQT_FALLING: - if ((irq > AT91_ID_FIQ) && (irq < AT91RM9200_ID_IRQ0)) /* only supported on external interrupts */ + if ((irq == AT91_ID_FIQ) || is_extern_irq(irq)) /* only supported on external interrupts */ + srctype = AT91_AIC_SRCTYPE_FALLING; + else return -EINVAL; - srctype = AT91_AIC_SRCTYPE_FALLING; break; default: return -EINVAL; @@ -139,7 +145,7 @@ void __init at91_aic_init(unsigned int priority[NR_AIC_IRQS]) at91_sys_write(AT91_AIC_SMR(i), AT91_AIC_SRCTYPE_LOW | priority[i]); set_irq_chip(i, &at91_aic_chip); - set_irq_handler(i, do_level_IRQ); + set_irq_handler(i, handle_level_irq); set_irq_flags(i, IRQF_VALID | IRQF_PROBE); /* Perform 8 End Of Interrupt Command to make sure AIC will not Lock out nIRQ */ diff --git a/trunk/arch/arm/mach-at91rm9200/pm.c b/trunk/arch/arm/mach-at91rm9200/pm.c index 32c95d8eaacf..67aa5572a3ea 100644 --- a/trunk/arch/arm/mach-at91rm9200/pm.c +++ b/trunk/arch/arm/mach-at91rm9200/pm.c @@ -26,7 +26,10 @@ #include #include +#include +#include #include +#include #include "generic.h" @@ -68,9 +71,15 @@ static int at91_pm_verify_clocks(void) scsr = at91_sys_read(AT91_PMC_SCSR); /* USB must not be using PLLB */ - if ((scsr & (AT91_PMC_UHP | AT91_PMC_UDP)) != 0) { - pr_debug("AT91: PM - Suspend-to-RAM with USB still active\n"); - return 0; + if (cpu_is_at91rm9200()) { + if ((scsr & (AT91RM9200_PMC_UHP | AT91RM9200_PMC_UDP)) != 0) { + pr_debug("AT91: PM - Suspend-to-RAM with USB still active\n"); + return 0; + } + } else if (cpu_is_at91sam9260()) { +#warning "Check SAM9260 USB clocks" + } else if (cpu_is_at91sam9261()) { +#warning "Check SAM9261 USB clocks" } #ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS @@ -112,7 +121,6 @@ EXPORT_SYMBOL(at91_suspend_entering_slow_clock); static void (*slow_clock)(void); - static int at91_pm_enter(suspend_state_t state) { at91_gpio_suspend(); @@ -123,13 +131,7 @@ static int at91_pm_enter(suspend_state_t state) (at91_sys_read(AT91_PMC_PCSR) | (1 << AT91_ID_FIQ) | (1 << AT91_ID_SYS) - | (1 << AT91RM9200_ID_IRQ0) - | (1 << AT91RM9200_ID_IRQ1) - | (1 << AT91RM9200_ID_IRQ2) - | (1 << AT91RM9200_ID_IRQ3) - | (1 << AT91RM9200_ID_IRQ4) - | (1 << AT91RM9200_ID_IRQ5) - | (1 << AT91RM9200_ID_IRQ6)) + | (at91_extern_irq)) & at91_sys_read(AT91_AIC_IMR), state); diff --git a/trunk/arch/arm/mach-clps711x/irq.c b/trunk/arch/arm/mach-clps711x/irq.c index 7ee926e5bad2..ca102960f528 100644 --- a/trunk/arch/arm/mach-clps711x/irq.c +++ b/trunk/arch/arm/mach-clps711x/irq.c @@ -63,7 +63,7 @@ static void int1_unmask(unsigned int irq) clps_writel(intmr1, INTMR1); } -static struct irqchip int1_chip = { +static struct irq_chip int1_chip = { .ack = int1_ack, .mask = int1_mask, .unmask = int1_unmask, @@ -100,7 +100,7 @@ static void int2_unmask(unsigned int irq) clps_writel(intmr2, INTMR2); } -static struct irqchip int2_chip = { +static struct irq_chip int2_chip = { .ack = int2_ack, .mask = int2_mask, .unmask = int2_unmask, @@ -112,12 +112,12 @@ void __init clps711x_init_irq(void) for (i = 0; i < NR_IRQS; i++) { if (INT1_IRQS & (1 << i)) { - set_irq_handler(i, do_level_IRQ); + set_irq_handler(i, handle_level_irq); set_irq_chip(i, &int1_chip); set_irq_flags(i, IRQF_VALID | IRQF_PROBE); } if (INT2_IRQS & (1 << i)) { - set_irq_handler(i, do_level_IRQ); + set_irq_handler(i, handle_level_irq); set_irq_chip(i, &int2_chip); set_irq_flags(i, IRQF_VALID | IRQF_PROBE); } diff --git a/trunk/arch/arm/mach-clps7500/core.c b/trunk/arch/arm/mach-clps7500/core.c index fb10cf252588..231b90004736 100644 --- a/trunk/arch/arm/mach-clps7500/core.c +++ b/trunk/arch/arm/mach-clps7500/core.c @@ -57,7 +57,7 @@ static void cl7500_unmask_irq_a(unsigned int irq) iomd_writeb(val | mask, IOMD_IRQMASKA); } -static struct irqchip clps7500_a_chip = { +static struct irq_chip clps7500_a_chip = { .ack = cl7500_ack_irq_a, .mask = cl7500_mask_irq_a, .unmask = cl7500_unmask_irq_a, @@ -81,7 +81,7 @@ static void cl7500_unmask_irq_b(unsigned int irq) iomd_writeb(val | mask, IOMD_IRQMASKB); } -static struct irqchip clps7500_b_chip = { +static struct irq_chip clps7500_b_chip = { .ack = cl7500_mask_irq_b, .mask = cl7500_mask_irq_b, .unmask = cl7500_unmask_irq_b, @@ -105,7 +105,7 @@ static void cl7500_unmask_irq_c(unsigned int irq) iomd_writeb(val | mask, IOMD_IRQMASKC); } -static struct irqchip clps7500_c_chip = { +static struct irq_chip clps7500_c_chip = { .ack = cl7500_mask_irq_c, .mask = cl7500_mask_irq_c, .unmask = cl7500_unmask_irq_c, @@ -129,7 +129,7 @@ static void cl7500_unmask_irq_d(unsigned int irq) iomd_writeb(val | mask, IOMD_IRQMASKD); } -static struct irqchip clps7500_d_chip = { +static struct irq_chip clps7500_d_chip = { .ack = cl7500_mask_irq_d, .mask = cl7500_mask_irq_d, .unmask = cl7500_unmask_irq_d, @@ -153,7 +153,7 @@ static void cl7500_unmask_irq_dma(unsigned int irq) iomd_writeb(val | mask, IOMD_DMAMASK); } -static struct irqchip clps7500_dma_chip = { +static struct irq_chip clps7500_dma_chip = { .ack = cl7500_mask_irq_dma, .mask = cl7500_mask_irq_dma, .unmask = cl7500_unmask_irq_dma, @@ -177,7 +177,7 @@ static void cl7500_unmask_irq_fiq(unsigned int irq) iomd_writeb(val | mask, IOMD_FIQMASK); } -static struct irqchip clps7500_fiq_chip = { +static struct irq_chip clps7500_fiq_chip = { .ack = cl7500_mask_irq_fiq, .mask = cl7500_mask_irq_fiq, .unmask = cl7500_unmask_irq_fiq, @@ -187,7 +187,7 @@ static void cl7500_no_action(unsigned int irq) { } -static struct irqchip clps7500_no_chip = { +static struct irq_chip clps7500_no_chip = { .ack = cl7500_no_action, .mask = cl7500_no_action, .unmask = cl7500_no_action, @@ -214,43 +214,43 @@ static void __init clps7500_init_irq(void) switch (irq) { case 0 ... 7: set_irq_chip(irq, &clps7500_a_chip); - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); set_irq_flags(irq, flags); break; case 8 ... 15: set_irq_chip(irq, &clps7500_b_chip); - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); set_irq_flags(irq, flags); break; case 16 ... 22: set_irq_chip(irq, &clps7500_dma_chip); - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); set_irq_flags(irq, flags); break; case 24 ... 31: set_irq_chip(irq, &clps7500_c_chip); - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); set_irq_flags(irq, flags); break; case 40 ... 47: set_irq_chip(irq, &clps7500_d_chip); - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); set_irq_flags(irq, flags); break; case 48 ... 55: set_irq_chip(irq, &clps7500_no_chip); - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); set_irq_flags(irq, flags); break; case 64 ... 72: set_irq_chip(irq, &clps7500_fiq_chip); - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); set_irq_flags(irq, flags); break; } diff --git a/trunk/arch/arm/mach-ebsa110/core.c b/trunk/arch/arm/mach-ebsa110/core.c index 90103ab373a6..8459431cfd71 100644 --- a/trunk/arch/arm/mach-ebsa110/core.c +++ b/trunk/arch/arm/mach-ebsa110/core.c @@ -45,7 +45,7 @@ static void ebsa110_unmask_irq(unsigned int irq) __raw_writeb(1 << irq, IRQ_MSET); } -static struct irqchip ebsa110_irq_chip = { +static struct irq_chip ebsa110_irq_chip = { .ack = ebsa110_mask_irq, .mask = ebsa110_mask_irq, .unmask = ebsa110_unmask_irq, @@ -67,7 +67,7 @@ static void __init ebsa110_init_irq(void) for (irq = 0; irq < NR_IRQS; irq++) { set_irq_chip(irq, &ebsa110_irq_chip); - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); } } diff --git a/trunk/arch/arm/mach-ep93xx/Kconfig b/trunk/arch/arm/mach-ep93xx/Kconfig index e346b03cd921..af7904b3d0a8 100644 --- a/trunk/arch/arm/mach-ep93xx/Kconfig +++ b/trunk/arch/arm/mach-ep93xx/Kconfig @@ -9,12 +9,24 @@ config CRUNCH comment "EP93xx Platforms" +config MACH_ADSSPHERE + bool "Support ADS Sphere" + help + Say 'Y' here if you want your kernel to support the ADS + Sphere board. + config MACH_EDB9302 bool "Support Cirrus Logic EDB9302" help Say 'Y' here if you want your kernel to support the Cirrus Logic EDB9302 Evaluation Board. +config MACH_EDB9302A + bool "Support Cirrus Logic EDB9302A" + help + Say 'Y' here if you want your kernel to support the Cirrus + Logic EDB9302A Evaluation Board. + config MACH_EDB9312 bool "Support Cirrus Logic EDB9312" help diff --git a/trunk/arch/arm/mach-ep93xx/Makefile b/trunk/arch/arm/mach-ep93xx/Makefile index c2eb18b530c2..b06641dd450d 100644 --- a/trunk/arch/arm/mach-ep93xx/Makefile +++ b/trunk/arch/arm/mach-ep93xx/Makefile @@ -6,7 +6,9 @@ obj-m := obj-n := obj- := +obj-$(CONFIG_MACH_ADSSPHERE) += adssphere.o obj-$(CONFIG_MACH_EDB9302) += edb9302.o +obj-$(CONFIG_MACH_EDB9302A) += edb9302a.o obj-$(CONFIG_MACH_EDB9312) += edb9312.o obj-$(CONFIG_MACH_EDB9315) += edb9315.o obj-$(CONFIG_MACH_EDB9315A) += edb9315a.o diff --git a/trunk/arch/arm/mach-ep93xx/adssphere.c b/trunk/arch/arm/mach-ep93xx/adssphere.c new file mode 100644 index 000000000000..ac5d5818eb7b --- /dev/null +++ b/trunk/arch/arm/mach-ep93xx/adssphere.c @@ -0,0 +1,91 @@ +/* + * arch/arm/mach-ep93xx/adssphere.c + * ADS Sphere support. + * + * Copyright (C) 2006 Lennert Buytenhek + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct physmap_flash_data adssphere_flash_data = { + .width = 4, +}; + +static struct resource adssphere_flash_resource = { + .start = 0x60000000, + .end = 0x61ffffff, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device adssphere_flash = { + .name = "physmap-flash", + .id = 0, + .dev = { + .platform_data = &adssphere_flash_data, + }, + .num_resources = 1, + .resource = &adssphere_flash_resource, +}; + +static struct ep93xx_eth_data adssphere_eth_data = { + .phy_id = 1, +}; + +static struct resource adssphere_eth_resource[] = { + { + .start = EP93XX_ETHERNET_PHYS_BASE, + .end = EP93XX_ETHERNET_PHYS_BASE + 0xffff, + .flags = IORESOURCE_MEM, + }, { + .start = IRQ_EP93XX_ETHERNET, + .end = IRQ_EP93XX_ETHERNET, + .flags = IORESOURCE_IRQ, + } +}; + +static struct platform_device adssphere_eth_device = { + .name = "ep93xx-eth", + .id = -1, + .dev = { + .platform_data = &adssphere_eth_data, + }, + .num_resources = 2, + .resource = adssphere_eth_resource, +}; + +static void __init adssphere_init_machine(void) +{ + ep93xx_init_devices(); + platform_device_register(&adssphere_flash); + + memcpy(adssphere_eth_data.dev_addr, + (void *)(EP93XX_ETHERNET_BASE + 0x50), 6); + platform_device_register(&adssphere_eth_device); +} + +MACHINE_START(ADSSPHERE, "ADS Sphere board") + /* Maintainer: Lennert Buytenhek */ + .phys_io = EP93XX_APB_PHYS_BASE, + .io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc, + .boot_params = 0x00000100, + .map_io = ep93xx_map_io, + .init_irq = ep93xx_init_irq, + .timer = &ep93xx_timer, + .init_machine = adssphere_init_machine, +MACHINE_END diff --git a/trunk/arch/arm/mach-ep93xx/core.c b/trunk/arch/arm/mach-ep93xx/core.c index e3fd1ab6adcc..d649b39711d4 100644 --- a/trunk/arch/arm/mach-ep93xx/core.c +++ b/trunk/arch/arm/mach-ep93xx/core.c @@ -245,7 +245,7 @@ EXPORT_SYMBOL(gpio_line_set); * EP93xx IRQ handling *************************************************************************/ static void ep93xx_gpio_ab_irq_handler(unsigned int irq, - struct irqdesc *desc) + struct irq_desc *desc) { unsigned char status; int i; @@ -335,7 +335,7 @@ static int ep93xx_gpio_ab_irq_type(unsigned int irq, unsigned int type) return 0; } -static struct irqchip ep93xx_gpio_ab_irq_chip = { +static struct irq_chip ep93xx_gpio_ab_irq_chip = { .ack = ep93xx_gpio_ab_irq_mask_ack, .mask = ep93xx_gpio_ab_irq_mask, .unmask = ep93xx_gpio_ab_irq_unmask, @@ -352,7 +352,7 @@ void __init ep93xx_init_irq(void) for (irq = IRQ_EP93XX_GPIO(0) ; irq <= IRQ_EP93XX_GPIO(15); irq++) { set_irq_chip(irq, &ep93xx_gpio_ab_irq_chip); - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); set_irq_flags(irq, IRQF_VALID); } set_irq_chained_handler(IRQ_EP93XX_GPIO_AB, ep93xx_gpio_ab_irq_handler); diff --git a/trunk/arch/arm/mach-ep93xx/edb9302a.c b/trunk/arch/arm/mach-ep93xx/edb9302a.c new file mode 100644 index 000000000000..62e064bab1d2 --- /dev/null +++ b/trunk/arch/arm/mach-ep93xx/edb9302a.c @@ -0,0 +1,91 @@ +/* + * arch/arm/mach-ep93xx/edb9302a.c + * Cirrus Logic EDB9302A support. + * + * Copyright (C) 2006 Lennert Buytenhek + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct physmap_flash_data edb9302a_flash_data = { + .width = 2, +}; + +static struct resource edb9302a_flash_resource = { + .start = 0x60000000, + .end = 0x60ffffff, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device edb9302a_flash = { + .name = "physmap-flash", + .id = 0, + .dev = { + .platform_data = &edb9302a_flash_data, + }, + .num_resources = 1, + .resource = &edb9302a_flash_resource, +}; + +static struct ep93xx_eth_data edb9302a_eth_data = { + .phy_id = 1, +}; + +static struct resource edb9302a_eth_resource[] = { + { + .start = EP93XX_ETHERNET_PHYS_BASE, + .end = EP93XX_ETHERNET_PHYS_BASE + 0xffff, + .flags = IORESOURCE_MEM, + }, { + .start = IRQ_EP93XX_ETHERNET, + .end = IRQ_EP93XX_ETHERNET, + .flags = IORESOURCE_IRQ, + } +}; + +static struct platform_device edb9302a_eth_device = { + .name = "ep93xx-eth", + .id = -1, + .dev = { + .platform_data = &edb9302a_eth_data, + }, + .num_resources = 2, + .resource = edb9302a_eth_resource, +}; + +static void __init edb9302a_init_machine(void) +{ + ep93xx_init_devices(); + platform_device_register(&edb9302a_flash); + + memcpy(edb9302a_eth_data.dev_addr, + (void *)(EP93XX_ETHERNET_BASE + 0x50), 6); + platform_device_register(&edb9302a_eth_device); +} + +MACHINE_START(EDB9302A, "Cirrus Logic EDB9302A Evaluation Board") + /* Maintainer: Lennert Buytenhek */ + .phys_io = EP93XX_APB_PHYS_BASE, + .io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc, + .boot_params = 0xc0000100, + .map_io = ep93xx_map_io, + .init_irq = ep93xx_init_irq, + .timer = &ep93xx_timer, + .init_machine = edb9302a_init_machine, +MACHINE_END diff --git a/trunk/arch/arm/mach-footbridge/common.c b/trunk/arch/arm/mach-footbridge/common.c index af900f4755a4..ef29fc34ce65 100644 --- a/trunk/arch/arm/mach-footbridge/common.c +++ b/trunk/arch/arm/mach-footbridge/common.c @@ -78,7 +78,7 @@ static void fb_unmask_irq(unsigned int irq) *CSR_IRQ_ENABLE = fb_irq_mask[_DC21285_INR(irq)]; } -static struct irqchip fb_chip = { +static struct irq_chip fb_chip = { .ack = fb_mask_irq, .mask = fb_mask_irq, .unmask = fb_unmask_irq, @@ -96,7 +96,7 @@ static void __init __fb_init_irq(void) for (irq = _DC21285_IRQ(0); irq < _DC21285_IRQ(20); irq++) { set_irq_chip(irq, &fb_chip); - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); } } diff --git a/trunk/arch/arm/mach-footbridge/isa-irq.c b/trunk/arch/arm/mach-footbridge/isa-irq.c index 888dedd501b9..79443ffc8916 100644 --- a/trunk/arch/arm/mach-footbridge/isa-irq.c +++ b/trunk/arch/arm/mach-footbridge/isa-irq.c @@ -49,7 +49,7 @@ static void isa_unmask_pic_lo_irq(unsigned int irq) outb(inb(PIC_MASK_LO) & ~mask, PIC_MASK_LO); } -static struct irqchip isa_lo_chip = { +static struct irq_chip isa_lo_chip = { .ack = isa_ack_pic_lo_irq, .mask = isa_mask_pic_lo_irq, .unmask = isa_unmask_pic_lo_irq, @@ -78,14 +78,14 @@ static void isa_unmask_pic_hi_irq(unsigned int irq) outb(inb(PIC_MASK_HI) & ~mask, PIC_MASK_HI); } -static struct irqchip isa_hi_chip = { +static struct irq_chip isa_hi_chip = { .ack = isa_ack_pic_hi_irq, .mask = isa_mask_pic_hi_irq, .unmask = isa_unmask_pic_hi_irq, }; static void -isa_irq_handler(unsigned int irq, struct irqdesc *desc) +isa_irq_handler(unsigned int irq, struct irq_desc *desc) { unsigned int isa_irq = *(unsigned char *)PCIIACK_BASE; @@ -150,13 +150,13 @@ void __init isa_init_irq(unsigned int host_irq) if (host_irq != (unsigned int)-1) { for (irq = _ISA_IRQ(0); irq < _ISA_IRQ(8); irq++) { set_irq_chip(irq, &isa_lo_chip); - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); } for (irq = _ISA_IRQ(8); irq < _ISA_IRQ(16); irq++) { set_irq_chip(irq, &isa_hi_chip); - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); } diff --git a/trunk/arch/arm/mach-h720x/common.c b/trunk/arch/arm/mach-h720x/common.c index 4719229a1a78..7f31816896ad 100644 --- a/trunk/arch/arm/mach-h720x/common.c +++ b/trunk/arch/arm/mach-h720x/common.c @@ -101,7 +101,7 @@ static void inline unmask_gpio_irq(u32 irq) static void h720x_gpio_handler(unsigned int mask, unsigned int irq, - struct irqdesc *desc) + struct irq_desc *desc) { IRQDBG("%s irq: %d\n",__FUNCTION__,irq); desc = irq_desc + irq; @@ -117,7 +117,7 @@ h720x_gpio_handler(unsigned int mask, unsigned int irq, } static void -h720x_gpioa_demux_handler(unsigned int irq_unused, struct irqdesc *desc) +h720x_gpioa_demux_handler(unsigned int irq_unused, struct irq_desc *desc) { unsigned int mask, irq; @@ -128,7 +128,7 @@ h720x_gpioa_demux_handler(unsigned int irq_unused, struct irqdesc *desc) } static void -h720x_gpiob_demux_handler(unsigned int irq_unused, struct irqdesc *desc) +h720x_gpiob_demux_handler(unsigned int irq_unused, struct irq_desc *desc) { unsigned int mask, irq; mask = CPU_REG(GPIO_B_VIRT,GPIO_STAT); @@ -138,7 +138,7 @@ h720x_gpiob_demux_handler(unsigned int irq_unused, struct irqdesc *desc) } static void -h720x_gpioc_demux_handler(unsigned int irq_unused, struct irqdesc *desc) +h720x_gpioc_demux_handler(unsigned int irq_unused, struct irq_desc *desc) { unsigned int mask, irq; @@ -149,7 +149,7 @@ h720x_gpioc_demux_handler(unsigned int irq_unused, struct irqdesc *desc) } static void -h720x_gpiod_demux_handler(unsigned int irq_unused, struct irqdesc *desc) +h720x_gpiod_demux_handler(unsigned int irq_unused, struct irq_desc *desc) { unsigned int mask, irq; @@ -161,7 +161,7 @@ h720x_gpiod_demux_handler(unsigned int irq_unused, struct irqdesc *desc) #ifdef CONFIG_CPU_H7202 static void -h720x_gpioe_demux_handler(unsigned int irq_unused, struct irqdesc *desc) +h720x_gpioe_demux_handler(unsigned int irq_unused, struct irq_desc *desc) { unsigned int mask, irq; @@ -172,13 +172,13 @@ h720x_gpioe_demux_handler(unsigned int irq_unused, struct irqdesc *desc) } #endif -static struct irqchip h720x_global_chip = { +static struct irq_chip h720x_global_chip = { .ack = mask_global_irq, .mask = mask_global_irq, .unmask = unmask_global_irq, }; -static struct irqchip h720x_gpio_chip = { +static struct irq_chip h720x_gpio_chip = { .ack = ack_gpio_irq, .mask = mask_gpio_irq, .unmask = unmask_gpio_irq, @@ -203,14 +203,14 @@ void __init h720x_init_irq (void) /* Initialize global IRQ's, fast path */ for (irq = 0; irq < NR_GLBL_IRQS; irq++) { set_irq_chip(irq, &h720x_global_chip); - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); } /* Initialize multiplexed IRQ's, slow path */ for (irq = IRQ_CHAINED_GPIOA(0) ; irq <= IRQ_CHAINED_GPIOD(31); irq++) { set_irq_chip(irq, &h720x_gpio_chip); - set_irq_handler(irq, do_edge_IRQ); + set_irq_handler(irq, handle_edge_irq); set_irq_flags(irq, IRQF_VALID ); } set_irq_chained_handler(IRQ_GPIOA, h720x_gpioa_demux_handler); @@ -221,7 +221,7 @@ void __init h720x_init_irq (void) #ifdef CONFIG_CPU_H7202 for (irq = IRQ_CHAINED_GPIOE(0) ; irq <= IRQ_CHAINED_GPIOE(31); irq++) { set_irq_chip(irq, &h720x_gpio_chip); - set_irq_handler(irq, do_edge_IRQ); + set_irq_handler(irq, handle_edge_irq); set_irq_flags(irq, IRQF_VALID ); } set_irq_chained_handler(IRQ_GPIOE, h720x_gpioe_demux_handler); diff --git a/trunk/arch/arm/mach-h720x/cpu-h7202.c b/trunk/arch/arm/mach-h720x/cpu-h7202.c index 06fecaefd8dc..703870f30adf 100644 --- a/trunk/arch/arm/mach-h720x/cpu-h7202.c +++ b/trunk/arch/arm/mach-h720x/cpu-h7202.c @@ -106,7 +106,7 @@ static struct platform_device *devices[] __initdata = { * we have to handle all timer interrupts in one place. */ static void -h7202_timerx_demux_handler(unsigned int irq_unused, struct irqdesc *desc) +h7202_timerx_demux_handler(unsigned int irq_unused, struct irq_desc *desc) { unsigned int mask, irq; @@ -162,7 +162,7 @@ static void inline unmask_timerx_irq (u32 irq) CPU_REG (TIMER_VIRT, TIMER_TOPCTRL) |= bit; } -static struct irqchip h7202_timerx_chip = { +static struct irq_chip h7202_timerx_chip = { .ack = mask_timerx_irq, .mask = mask_timerx_irq, .unmask = unmask_timerx_irq, @@ -202,7 +202,7 @@ void __init h7202_init_irq (void) irq < IRQ_CHAINED_TIMERX(NR_TIMERX_IRQS); irq++) { mask_timerx_irq(irq); set_irq_chip(irq, &h7202_timerx_chip); - set_irq_handler(irq, do_edge_IRQ); + set_irq_handler(irq, handle_edge_irq); set_irq_flags(irq, IRQF_VALID ); } set_irq_chained_handler(IRQ_TIMERX, h7202_timerx_demux_handler); diff --git a/trunk/arch/arm/mach-imx/generic.c b/trunk/arch/arm/mach-imx/generic.c index 12ea58a3b84f..b5aa49d00ca3 100644 --- a/trunk/arch/arm/mach-imx/generic.c +++ b/trunk/arch/arm/mach-imx/generic.c @@ -104,6 +104,9 @@ EXPORT_SYMBOL(imx_gpio_mode); */ static unsigned int imx_decode_pll(unsigned int pll) { + unsigned long long ll; + unsigned long quot; + u32 mfi = (pll >> 10) & 0xf; u32 mfn = pll & 0x3ff; u32 mfd = (pll >> 16) & 0x3ff; @@ -112,7 +115,11 @@ static unsigned int imx_decode_pll(unsigned int pll) mfi = mfi <= 5 ? 5 : mfi; - return (2 * (f_ref>>10) * ( (mfi<<10) + (mfn<<10) / (mfd+1) )) / (pd+1); + ll = 2 * (unsigned long long)f_ref * ( (mfi<<16) + (mfn<<16) / (mfd+1) ); + quot = (pd+1) * (1<<16); + ll += quot / 2; + do_div(ll, quot); + return (unsigned int) ll; } unsigned int imx_get_system_clk(void) diff --git a/trunk/arch/arm/mach-imx/irq.c b/trunk/arch/arm/mach-imx/irq.c index 368b13b058ab..0791b56caecc 100644 --- a/trunk/arch/arm/mach-imx/irq.c +++ b/trunk/arch/arm/mach-imx/irq.c @@ -146,7 +146,7 @@ imx_gpio_unmask_irq(unsigned int irq) static void imx_gpio_handler(unsigned int mask, unsigned int irq, - struct irqdesc *desc) + struct irq_desc *desc) { desc = irq_desc + irq; while (mask) { @@ -161,7 +161,7 @@ imx_gpio_handler(unsigned int mask, unsigned int irq, } static void -imx_gpioa_demux_handler(unsigned int irq_unused, struct irqdesc *desc) +imx_gpioa_demux_handler(unsigned int irq_unused, struct irq_desc *desc) { unsigned int mask, irq; @@ -171,7 +171,7 @@ imx_gpioa_demux_handler(unsigned int irq_unused, struct irqdesc *desc) } static void -imx_gpiob_demux_handler(unsigned int irq_unused, struct irqdesc *desc) +imx_gpiob_demux_handler(unsigned int irq_unused, struct irq_desc *desc) { unsigned int mask, irq; @@ -181,7 +181,7 @@ imx_gpiob_demux_handler(unsigned int irq_unused, struct irqdesc *desc) } static void -imx_gpioc_demux_handler(unsigned int irq_unused, struct irqdesc *desc) +imx_gpioc_demux_handler(unsigned int irq_unused, struct irq_desc *desc) { unsigned int mask, irq; @@ -191,7 +191,7 @@ imx_gpioc_demux_handler(unsigned int irq_unused, struct irqdesc *desc) } static void -imx_gpiod_demux_handler(unsigned int irq_unused, struct irqdesc *desc) +imx_gpiod_demux_handler(unsigned int irq_unused, struct irq_desc *desc) { unsigned int mask, irq; @@ -230,13 +230,13 @@ imx_init_irq(void) for (irq = 0; irq < IMX_IRQS; irq++) { set_irq_chip(irq, &imx_internal_chip); - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); set_irq_flags(irq, IRQF_VALID); } for (irq = IRQ_GPIOA(0); irq < IRQ_GPIOD(32); irq++) { set_irq_chip(irq, &imx_gpio_chip); - set_irq_handler(irq, do_edge_IRQ); + set_irq_handler(irq, handle_edge_irq); set_irq_flags(irq, IRQF_VALID); } diff --git a/trunk/arch/arm/mach-imx/time.c b/trunk/arch/arm/mach-imx/time.c index 8ae4a2c5066f..40039b2a90b3 100644 --- a/trunk/arch/arm/mach-imx/time.c +++ b/trunk/arch/arm/mach-imx/time.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -24,33 +25,7 @@ /* Use timer 1 as system timer */ #define TIMER_BASE IMX_TIM1_BASE -/* - * Returns number of us since last clock interrupt. Note that interrupts - * will have been disabled by do_gettimeoffset() - */ -static unsigned long imx_gettimeoffset(void) -{ - unsigned long ticks; - - /* - * Get the current number of ticks. Note that there is a race - * condition between us reading the timer and checking for - * an interrupt. We get around this by ensuring that the - * counter has not reloaded between our two reads. - */ - ticks = IMX_TCN(TIMER_BASE); - - /* - * Interrupt pending? If so, we've reloaded once already. - */ - if (IMX_TSTAT(TIMER_BASE) & TSTAT_COMP) - ticks += LATCH; - - /* - * Convert the ticks to usecs - */ - return (1000000 / CLK32) * ticks; -} +static unsigned long evt_diff; /* * IRQ handler for the timer @@ -58,14 +33,23 @@ static unsigned long imx_gettimeoffset(void) static irqreturn_t imx_timer_interrupt(int irq, void *dev_id) { - write_seqlock(&xtime_lock); + uint32_t tstat; /* clear the interrupt */ - if (IMX_TSTAT(TIMER_BASE)) - IMX_TSTAT(TIMER_BASE) = 0; + tstat = IMX_TSTAT(TIMER_BASE); + IMX_TSTAT(TIMER_BASE) = 0; + + if (tstat & TSTAT_COMP) { + do { + + write_seqlock(&xtime_lock); + timer_tick(); + write_sequnlock(&xtime_lock); + IMX_TCMP(TIMER_BASE) += evt_diff; - timer_tick(); - write_sequnlock(&xtime_lock); + } while (unlikely((int32_t)(IMX_TCMP(TIMER_BASE) + - IMX_TCN(TIMER_BASE)) < 0)); + } return IRQ_HANDLED; } @@ -77,9 +61,9 @@ static struct irqaction imx_timer_irq = { }; /* - * Set up timer interrupt, and return the current time in seconds. + * Set up timer hardware into expected mode and state. */ -static void __init imx_timer_init(void) +static void __init imx_timer_hardware_init(void) { /* * Initialise to a known state (all timers off, and timing reset) @@ -87,7 +71,38 @@ static void __init imx_timer_init(void) IMX_TCTL(TIMER_BASE) = 0; IMX_TPRER(TIMER_BASE) = 0; IMX_TCMP(TIMER_BASE) = LATCH - 1; - IMX_TCTL(TIMER_BASE) = TCTL_CLK_32 | TCTL_IRQEN | TCTL_TEN; + + IMX_TCTL(TIMER_BASE) = TCTL_FRR | TCTL_CLK_PCLK1 | TCTL_IRQEN | TCTL_TEN; + evt_diff = LATCH; +} + +cycle_t imx_get_cycles(void) +{ + return IMX_TCN(TIMER_BASE); +} + +static struct clocksource clocksource_imx = { + .name = "imx_timer1", + .rating = 200, + .read = imx_get_cycles, + .mask = 0xFFFFFFFF, + .shift = 20, + .is_continuous = 1, +}; + +static int __init imx_clocksource_init(void) +{ + clocksource_imx.mult = + clocksource_hz2mult(imx_get_perclk1(), clocksource_imx.shift); + clocksource_register(&clocksource_imx); + + return 0; +} + +static void __init imx_timer_init(void) +{ + imx_timer_hardware_init(); + imx_clocksource_init(); /* * Make irqs happen for the system timer @@ -97,5 +112,4 @@ static void __init imx_timer_init(void) struct sys_timer imx_timer = { .init = imx_timer_init, - .offset = imx_gettimeoffset, }; diff --git a/trunk/arch/arm/mach-integrator/integrator_ap.c b/trunk/arch/arm/mach-integrator/integrator_ap.c index 191c57a3b997..72280754354d 100644 --- a/trunk/arch/arm/mach-integrator/integrator_ap.c +++ b/trunk/arch/arm/mach-integrator/integrator_ap.c @@ -183,7 +183,7 @@ static void __init ap_init_irq(void) for (i = 0; i < NR_IRQS; i++) { if (((1 << i) & INTEGRATOR_SC_VALID_INT) != 0) { set_irq_chip(i, &sc_chip); - set_irq_handler(i, do_level_IRQ); + set_irq_handler(i, handle_level_irq); set_irq_flags(i, IRQF_VALID | IRQF_PROBE); } } diff --git a/trunk/arch/arm/mach-integrator/integrator_cp.c b/trunk/arch/arm/mach-integrator/integrator_cp.c index 771b65bffe69..913f64b22405 100644 --- a/trunk/arch/arm/mach-integrator/integrator_cp.c +++ b/trunk/arch/arm/mach-integrator/integrator_cp.c @@ -202,7 +202,7 @@ static struct irq_chip sic_chip = { }; static void -sic_handle_irq(unsigned int irq, struct irqdesc *desc) +sic_handle_irq(unsigned int irq, struct irq_desc *desc) { unsigned long status = sic_readl(INTCP_VA_SIC_BASE + IRQ_STATUS); @@ -238,7 +238,7 @@ static void __init intcp_init_irq(void) if (i == 29) break; set_irq_chip(i, &pic_chip); - set_irq_handler(i, do_level_IRQ); + set_irq_handler(i, handle_level_irq); set_irq_flags(i, IRQF_VALID | IRQF_PROBE); } @@ -247,7 +247,7 @@ static void __init intcp_init_irq(void) for (i = IRQ_CIC_START; i <= IRQ_CIC_END; i++) { set_irq_chip(i, &cic_chip); - set_irq_handler(i, do_level_IRQ); + set_irq_handler(i, handle_level_irq); set_irq_flags(i, IRQF_VALID); } @@ -256,7 +256,7 @@ static void __init intcp_init_irq(void) for (i = IRQ_SIC_START; i <= IRQ_SIC_END; i++) { set_irq_chip(i, &sic_chip); - set_irq_handler(i, do_level_IRQ); + set_irq_handler(i, handle_level_irq); set_irq_flags(i, IRQF_VALID | IRQF_PROBE); } diff --git a/trunk/arch/arm/mach-integrator/platsmp.c b/trunk/arch/arm/mach-integrator/platsmp.c index 1bc8534ef0c6..613b841a10f3 100644 --- a/trunk/arch/arm/mach-integrator/platsmp.c +++ b/trunk/arch/arm/mach-integrator/platsmp.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include diff --git a/trunk/arch/arm/mach-iop13xx/Kconfig b/trunk/arch/arm/mach-iop13xx/Kconfig new file mode 100644 index 000000000000..40c2d689f2eb --- /dev/null +++ b/trunk/arch/arm/mach-iop13xx/Kconfig @@ -0,0 +1,20 @@ +if ARCH_IOP13XX + +menu "IOP13XX Implementation Options" + +comment "IOP13XX Platform Support" + +config MACH_IQ81340SC + bool "Enable IQ81340SC Hardware Support" + help + Say Y here if you want to support running on the Intel IQ81340SC + evaluation kit. + +config MACH_IQ81340MC + bool "Enable IQ81340MC Hardware Support" + help + Say Y here if you want to support running on the Intel IQ81340MC + evaluation kit. + +endmenu +endif diff --git a/trunk/arch/arm/mach-iop13xx/Makefile b/trunk/arch/arm/mach-iop13xx/Makefile new file mode 100644 index 000000000000..c3d6c08f2d4c --- /dev/null +++ b/trunk/arch/arm/mach-iop13xx/Makefile @@ -0,0 +1,12 @@ +obj-y := +obj-m := +obj-n := +obj- := + +obj-$(CONFIG_ARCH_IOP13XX) += setup.o +obj-$(CONFIG_ARCH_IOP13XX) += irq.o +obj-$(CONFIG_ARCH_IOP13XX) += time.o +obj-$(CONFIG_ARCH_IOP13XX) += pci.o +obj-$(CONFIG_ARCH_IOP13XX) += io.o +obj-$(CONFIG_MACH_IQ81340SC) += iq81340sc.o +obj-$(CONFIG_MACH_IQ81340MC) += iq81340mc.o diff --git a/trunk/arch/arm/mach-iop13xx/Makefile.boot b/trunk/arch/arm/mach-iop13xx/Makefile.boot new file mode 100644 index 000000000000..0b0e19fdfe6c --- /dev/null +++ b/trunk/arch/arm/mach-iop13xx/Makefile.boot @@ -0,0 +1,3 @@ + zreladdr-y := 0x00008000 +params_phys-y := 0x00000100 +initrd_phys-y := 0x00800000 diff --git a/trunk/arch/arm/mach-iop13xx/io.c b/trunk/arch/arm/mach-iop13xx/io.c new file mode 100644 index 000000000000..fbf9f88e46ea --- /dev/null +++ b/trunk/arch/arm/mach-iop13xx/io.c @@ -0,0 +1,93 @@ +/* + * iop13xx custom ioremap implementation + * Copyright (c) 2005-2006, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place - Suite 330, Boston, MA 02111-1307 USA. + * + */ +#include +#include +#include +#include + +void * __iomem __iop13xx_ioremap(unsigned long cookie, size_t size, + unsigned long flags) +{ + void __iomem * retval; + + switch (cookie) { + case IOP13XX_PCIX_LOWER_MEM_RA ... IOP13XX_PCIX_UPPER_MEM_RA: + if (unlikely(!iop13xx_atux_mem_base)) + retval = NULL; + else + retval = (void *)(iop13xx_atux_mem_base + + (cookie - IOP13XX_PCIX_LOWER_MEM_RA)); + break; + case IOP13XX_PCIE_LOWER_MEM_RA ... IOP13XX_PCIE_UPPER_MEM_RA: + if (unlikely(!iop13xx_atue_mem_base)) + retval = NULL; + else + retval = (void *)(iop13xx_atue_mem_base + + (cookie - IOP13XX_PCIE_LOWER_MEM_RA)); + break; + case IOP13XX_PBI_LOWER_MEM_RA ... IOP13XX_PBI_UPPER_MEM_RA: + retval = __ioremap(IOP13XX_PBI_LOWER_MEM_PA + + (cookie - IOP13XX_PBI_LOWER_MEM_RA), + size, flags); + break; + case IOP13XX_PCIE_LOWER_IO_PA ... IOP13XX_PCIE_UPPER_IO_PA: + retval = (void *) IOP13XX_PCIE_IO_PHYS_TO_VIRT(cookie); + break; + case IOP13XX_PCIX_LOWER_IO_PA ... IOP13XX_PCIX_UPPER_IO_PA: + retval = (void *) IOP13XX_PCIX_IO_PHYS_TO_VIRT(cookie); + break; + case IOP13XX_PMMR_PHYS_MEM_BASE ... IOP13XX_PMMR_UPPER_MEM_PA: + retval = (void *) IOP13XX_PMMR_PHYS_TO_VIRT(cookie); + break; + default: + retval = __ioremap(cookie, size, flags); + } + + return retval; +} +EXPORT_SYMBOL(__iop13xx_ioremap); + +void __iop13xx_iounmap(void __iomem *addr) +{ + extern void __iounmap(volatile void __iomem *addr); + + if (iop13xx_atue_mem_base) + if (addr >= (void __iomem *) iop13xx_atue_mem_base && + addr < (void __iomem *) (iop13xx_atue_mem_base + + iop13xx_atue_mem_size)) + goto skip; + + if (iop13xx_atux_mem_base) + if (addr >= (void __iomem *) iop13xx_atux_mem_base && + addr < (void __iomem *) (iop13xx_atux_mem_base + + iop13xx_atux_mem_size)) + goto skip; + + switch ((u32) addr) { + case IOP13XX_PCIE_LOWER_IO_VA ... IOP13XX_PCIE_UPPER_IO_VA: + case IOP13XX_PCIX_LOWER_IO_VA ... IOP13XX_PCIX_UPPER_IO_VA: + case IOP13XX_PMMR_VIRT_MEM_BASE ... IOP13XX_PMMR_UPPER_MEM_VA: + goto skip; + } + __iounmap(addr); + +skip: + return; +} +EXPORT_SYMBOL(__iop13xx_iounmap); diff --git a/trunk/arch/arm/mach-iop13xx/iq81340mc.c b/trunk/arch/arm/mach-iop13xx/iq81340mc.c new file mode 100644 index 000000000000..ee595786cd22 --- /dev/null +++ b/trunk/arch/arm/mach-iop13xx/iq81340mc.c @@ -0,0 +1,98 @@ +/* + * iq81340mc board support + * Copyright (c) 2005-2006, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place - Suite 330, Boston, MA 02111-1307 USA. + * + */ +#include + +#include +#include +#include +#include +#include +#include +#include + +extern int init_atu; /* Flag to select which ATU(s) to initialize / disable */ + +static int __init +iq81340mc_pcix_map_irq(struct pci_dev *dev, u8 idsel, u8 pin) +{ + switch (idsel) { + case 1: + switch (pin) { + case 1: return ATUX_INTB; + case 2: return ATUX_INTC; + case 3: return ATUX_INTD; + case 4: return ATUX_INTA; + default: return -1; + } + case 2: + switch (pin) { + case 1: return ATUX_INTC; + case 2: return ATUX_INTD; + case 3: return ATUX_INTC; + case 4: return ATUX_INTD; + default: return -1; + } + default: return -1; + } +} + +static struct hw_pci iq81340mc_pci __initdata = { + .swizzle = pci_std_swizzle, + .nr_controllers = 0, + .setup = iop13xx_pci_setup, + .map_irq = iq81340mc_pcix_map_irq, + .scan = iop13xx_scan_bus, + .preinit = iop13xx_pci_init, +}; + +static int __init iq81340mc_pci_init(void) +{ + iop13xx_atu_select(&iq81340mc_pci); + pci_common_init(&iq81340mc_pci); + iop13xx_map_pci_memory(); + + return 0; +} + +static void __init iq81340mc_init(void) +{ + iop13xx_platform_init(); + iq81340mc_pci_init(); +} + +static void __init iq81340mc_timer_init(void) +{ + iop13xx_init_time(400000000); +} + +static struct sys_timer iq81340mc_timer = { + .init = iq81340mc_timer_init, + .offset = iop13xx_gettimeoffset, +}; + +MACHINE_START(IQ81340MC, "Intel IQ81340MC") + /* Maintainer: Dan Williams */ + .phys_io = PHYS_IO, + .io_pg_offst = IO_PG_OFFSET, + .map_io = iop13xx_map_io, + .init_irq = iop13xx_init_irq, + .timer = &iq81340mc_timer, + .boot_params = BOOT_PARAM_OFFSET, + .init_machine = iq81340mc_init, +MACHINE_END diff --git a/trunk/arch/arm/mach-iop13xx/iq81340sc.c b/trunk/arch/arm/mach-iop13xx/iq81340sc.c new file mode 100644 index 000000000000..6677e14b61bf --- /dev/null +++ b/trunk/arch/arm/mach-iop13xx/iq81340sc.c @@ -0,0 +1,100 @@ +/* + * iq81340sc board support + * Copyright (c) 2005-2006, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place - Suite 330, Boston, MA 02111-1307 USA. + * + */ +#include + +#include +#include +#include +#include +#include +#include +#include + +extern int init_atu; + +static int __init +iq81340sc_atux_map_irq(struct pci_dev *dev, u8 idsel, u8 pin) +{ + WARN_ON(idsel < 1 || idsel > 2); + + switch (idsel) { + case 1: + switch (pin) { + case 1: return ATUX_INTB; + case 2: return ATUX_INTC; + case 3: return ATUX_INTD; + case 4: return ATUX_INTA; + default: return -1; + } + case 2: + switch (pin) { + case 1: return ATUX_INTC; + case 2: return ATUX_INTC; + case 3: return ATUX_INTC; + case 4: return ATUX_INTC; + default: return -1; + } + default: return -1; + } +} + +static struct hw_pci iq81340sc_pci __initdata = { + .swizzle = pci_std_swizzle, + .nr_controllers = 0, + .setup = iop13xx_pci_setup, + .scan = iop13xx_scan_bus, + .map_irq = iq81340sc_atux_map_irq, + .preinit = iop13xx_pci_init +}; + +static int __init iq81340sc_pci_init(void) +{ + iop13xx_atu_select(&iq81340sc_pci); + pci_common_init(&iq81340sc_pci); + iop13xx_map_pci_memory(); + + return 0; +} + +static void __init iq81340sc_init(void) +{ + iop13xx_platform_init(); + iq81340sc_pci_init(); +} + +static void __init iq81340sc_timer_init(void) +{ + iop13xx_init_time(400000000); +} + +static struct sys_timer iq81340sc_timer = { + .init = iq81340sc_timer_init, + .offset = iop13xx_gettimeoffset, +}; + +MACHINE_START(IQ81340SC, "Intel IQ81340SC") + /* Maintainer: Dan Williams */ + .phys_io = PHYS_IO, + .io_pg_offst = IO_PG_OFFSET, + .map_io = iop13xx_map_io, + .init_irq = iop13xx_init_irq, + .timer = &iq81340sc_timer, + .boot_params = BOOT_PARAM_OFFSET, + .init_machine = iq81340sc_init, +MACHINE_END diff --git a/trunk/arch/arm/mach-iop13xx/irq.c b/trunk/arch/arm/mach-iop13xx/irq.c new file mode 100644 index 000000000000..c4d9c8c5579c --- /dev/null +++ b/trunk/arch/arm/mach-iop13xx/irq.c @@ -0,0 +1,286 @@ +/* + * iop13xx IRQ handling / support functions + * Copyright (c) 2005-2006, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place - Suite 330, Boston, MA 02111-1307 USA. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* INTCTL0 CP6 R0 Page 4 + */ +static inline u32 read_intctl_0(void) +{ + u32 val; + asm volatile("mrc p6, 0, %0, c0, c4, 0":"=r" (val)); + return val; +} +static inline void write_intctl_0(u32 val) +{ + asm volatile("mcr p6, 0, %0, c0, c4, 0"::"r" (val)); +} + +/* INTCTL1 CP6 R1 Page 4 + */ +static inline u32 read_intctl_1(void) +{ + u32 val; + asm volatile("mrc p6, 0, %0, c1, c4, 0":"=r" (val)); + return val; +} +static inline void write_intctl_1(u32 val) +{ + asm volatile("mcr p6, 0, %0, c1, c4, 0"::"r" (val)); +} + +/* INTCTL2 CP6 R2 Page 4 + */ +static inline u32 read_intctl_2(void) +{ + u32 val; + asm volatile("mrc p6, 0, %0, c2, c4, 0":"=r" (val)); + return val; +} +static inline void write_intctl_2(u32 val) +{ + asm volatile("mcr p6, 0, %0, c2, c4, 0"::"r" (val)); +} + +/* INTCTL3 CP6 R3 Page 4 + */ +static inline u32 read_intctl_3(void) +{ + u32 val; + asm volatile("mrc p6, 0, %0, c3, c4, 0":"=r" (val)); + return val; +} +static inline void write_intctl_3(u32 val) +{ + asm volatile("mcr p6, 0, %0, c3, c4, 0"::"r" (val)); +} + +/* INTSTR0 CP6 R0 Page 5 + */ +static inline u32 read_intstr_0(void) +{ + u32 val; + asm volatile("mrc p6, 0, %0, c0, c5, 0":"=r" (val)); + return val; +} +static inline void write_intstr_0(u32 val) +{ + asm volatile("mcr p6, 0, %0, c0, c5, 0"::"r" (val)); +} + +/* INTSTR1 CP6 R1 Page 5 + */ +static inline u32 read_intstr_1(void) +{ + u32 val; + asm volatile("mrc p6, 0, %0, c1, c5, 0":"=r" (val)); + return val; +} +static void write_intstr_1(u32 val) +{ + asm volatile("mcr p6, 0, %0, c1, c5, 0"::"r" (val)); +} + +/* INTSTR2 CP6 R2 Page 5 + */ +static inline u32 read_intstr_2(void) +{ + u32 val; + asm volatile("mrc p6, 0, %0, c2, c5, 0":"=r" (val)); + return val; +} +static void write_intstr_2(u32 val) +{ + asm volatile("mcr p6, 0, %0, c2, c5, 0"::"r" (val)); +} + +/* INTSTR3 CP6 R3 Page 5 + */ +static inline u32 read_intstr_3(void) +{ + u32 val; + asm volatile("mrc p6, 0, %0, c3, c5, 0":"=r" (val)); + return val; +} +static void write_intstr_3(u32 val) +{ + asm volatile("mcr p6, 0, %0, c3, c5, 0"::"r" (val)); +} + +/* INTBASE CP6 R0 Page 2 + */ +static inline u32 read_intbase(void) +{ + u32 val; + asm volatile("mrc p6, 0, %0, c0, c2, 0":"=r" (val)); + return val; +} +static void write_intbase(u32 val) +{ + asm volatile("mcr p6, 0, %0, c0, c2, 0"::"r" (val)); +} + +/* INTSIZE CP6 R2 Page 2 + */ +static inline u32 read_intsize(void) +{ + u32 val; + asm volatile("mrc p6, 0, %0, c2, c2, 0":"=r" (val)); + return val; +} +static void write_intsize(u32 val) +{ + asm volatile("mcr p6, 0, %0, c2, c2, 0"::"r" (val)); +} + +/* 0 = Interrupt Masked and 1 = Interrupt not masked */ +static void +iop13xx_irq_mask0 (unsigned int irq) +{ + u32 cp_flags = iop13xx_cp6_save(); + write_intctl_0(read_intctl_0() & ~(1 << (irq - 0))); + iop13xx_cp6_restore(cp_flags); +} + +static void +iop13xx_irq_mask1 (unsigned int irq) +{ + u32 cp_flags = iop13xx_cp6_save(); + write_intctl_1(read_intctl_1() & ~(1 << (irq - 32))); + iop13xx_cp6_restore(cp_flags); +} + +static void +iop13xx_irq_mask2 (unsigned int irq) +{ + u32 cp_flags = iop13xx_cp6_save(); + write_intctl_2(read_intctl_2() & ~(1 << (irq - 64))); + iop13xx_cp6_restore(cp_flags); +} + +static void +iop13xx_irq_mask3 (unsigned int irq) +{ + u32 cp_flags = iop13xx_cp6_save(); + write_intctl_3(read_intctl_3() & ~(1 << (irq - 96))); + iop13xx_cp6_restore(cp_flags); +} + +static void +iop13xx_irq_unmask0(unsigned int irq) +{ + u32 cp_flags = iop13xx_cp6_save(); + write_intctl_0(read_intctl_0() | (1 << (irq - 0))); + iop13xx_cp6_restore(cp_flags); +} + +static void +iop13xx_irq_unmask1(unsigned int irq) +{ + u32 cp_flags = iop13xx_cp6_save(); + write_intctl_1(read_intctl_1() | (1 << (irq - 32))); + iop13xx_cp6_restore(cp_flags); +} + +static void +iop13xx_irq_unmask2(unsigned int irq) +{ + u32 cp_flags = iop13xx_cp6_save(); + write_intctl_2(read_intctl_2() | (1 << (irq - 64))); + iop13xx_cp6_restore(cp_flags); +} + +static void +iop13xx_irq_unmask3(unsigned int irq) +{ + u32 cp_flags = iop13xx_cp6_save(); + write_intctl_3(read_intctl_3() | (1 << (irq - 96))); + iop13xx_cp6_restore(cp_flags); +} + +static struct irqchip iop13xx_irqchip0 = { + .ack = iop13xx_irq_mask0, + .mask = iop13xx_irq_mask0, + .unmask = iop13xx_irq_unmask0, +}; + +static struct irqchip iop13xx_irqchip1 = { + .ack = iop13xx_irq_mask1, + .mask = iop13xx_irq_mask1, + .unmask = iop13xx_irq_unmask1, +}; + +static struct irqchip iop13xx_irqchip2 = { + .ack = iop13xx_irq_mask2, + .mask = iop13xx_irq_mask2, + .unmask = iop13xx_irq_unmask2, +}; + +static struct irqchip iop13xx_irqchip3 = { + .ack = iop13xx_irq_mask3, + .mask = iop13xx_irq_mask3, + .unmask = iop13xx_irq_unmask3, +}; + +void __init iop13xx_init_irq(void) +{ + unsigned int i; + + u32 cp_flags = iop13xx_cp6_save(); + + /* disable all interrupts */ + write_intctl_0(0); + write_intctl_1(0); + write_intctl_2(0); + write_intctl_3(0); + + /* treat all as IRQ */ + write_intstr_0(0); + write_intstr_1(0); + write_intstr_2(0); + write_intstr_3(0); + + /* initialize the interrupt vector generator */ + write_intbase(INTBASE); + write_intsize(INTSIZE_4); + + for(i = 0; i < NR_IOP13XX_IRQS; i++) { + if (i < 32) + set_irq_chip(i, &iop13xx_irqchip0); + else if (i < 64) + set_irq_chip(i, &iop13xx_irqchip1); + else if (i < 96) + set_irq_chip(i, &iop13xx_irqchip2); + else + set_irq_chip(i, &iop13xx_irqchip3); + + set_irq_handler(i, do_level_IRQ); + set_irq_flags(i, IRQF_VALID | IRQF_PROBE); + } + + iop13xx_cp6_restore(cp_flags); +} diff --git a/trunk/arch/arm/mach-iop13xx/pci.c b/trunk/arch/arm/mach-iop13xx/pci.c new file mode 100644 index 000000000000..89ec70ea3187 --- /dev/null +++ b/trunk/arch/arm/mach-iop13xx/pci.c @@ -0,0 +1,1113 @@ +/* + * iop13xx PCI support + * Copyright (c) 2005-2006, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place - Suite 330, Boston, MA 02111-1307 USA. + * + */ + +#include +#include + +#include +#include +#include +#include +#include + +#define IOP13XX_PCI_DEBUG 0 +#define PRINTK(x...) ((void)(IOP13XX_PCI_DEBUG && printk(x))) + +u32 iop13xx_atux_pmmr_offset; /* This offset can change based on strapping */ +u32 iop13xx_atue_pmmr_offset; /* This offset can change based on strapping */ +static struct pci_bus *pci_bus_atux = 0; +static struct pci_bus *pci_bus_atue = 0; +u32 iop13xx_atue_mem_base; +u32 iop13xx_atux_mem_base; +size_t iop13xx_atue_mem_size; +size_t iop13xx_atux_mem_size; +unsigned long iop13xx_pcibios_min_io = 0; +unsigned long iop13xx_pcibios_min_mem = 0; + +EXPORT_SYMBOL(iop13xx_atue_mem_base); +EXPORT_SYMBOL(iop13xx_atux_mem_base); +EXPORT_SYMBOL(iop13xx_atue_mem_size); +EXPORT_SYMBOL(iop13xx_atux_mem_size); + +int init_atu = 0; /* Flag to select which ATU(s) to initialize / disable */ +static unsigned long atux_trhfa_timeout = 0; /* Trhfa = RST# high to first + access */ + +/* Scan the initialized busses and ioremap the requested memory range + */ +void iop13xx_map_pci_memory(void) +{ + int atu; + struct pci_bus *bus; + struct pci_dev *dev; + resource_size_t end = 0; + + for (atu = 0; atu < 2; atu++) { + bus = atu ? pci_bus_atue : pci_bus_atux; + if (bus) { + list_for_each_entry(dev, &bus->devices, bus_list) { + int i; + int max = 7; + + if (dev->subordinate) + max = DEVICE_COUNT_RESOURCE; + + for (i = 0; i < max; i++) { + struct resource *res = &dev->resource[i]; + if (res->flags & IORESOURCE_MEM) + end = max(res->end, end); + } + } + + switch(atu) { + case 0: + iop13xx_atux_mem_size = + (end - IOP13XX_PCIX_LOWER_MEM_RA) + 1; + + /* 16MB align the request */ + if (iop13xx_atux_mem_size & (SZ_16M - 1)) { + iop13xx_atux_mem_size &= ~(SZ_16M - 1); + iop13xx_atux_mem_size += SZ_16M; + } + + if (end) { + iop13xx_atux_mem_base = + (u32) __ioremap_pfn( + __phys_to_pfn(IOP13XX_PCIX_LOWER_MEM_PA) + , 0, iop13xx_atux_mem_size, 0); + if (!iop13xx_atux_mem_base) { + printk("%s: atux allocation " + "failed\n", __FUNCTION__); + BUG(); + } + } else + iop13xx_atux_mem_size = 0; + PRINTK("%s: atu: %d bus_size: %d mem_base: %x\n", + __FUNCTION__, atu, iop13xx_atux_mem_size, + iop13xx_atux_mem_base); + break; + case 1: + iop13xx_atue_mem_size = + (end - IOP13XX_PCIE_LOWER_MEM_RA) + 1; + + /* 16MB align the request */ + if (iop13xx_atue_mem_size & (SZ_16M - 1)) { + iop13xx_atue_mem_size &= ~(SZ_16M - 1); + iop13xx_atue_mem_size += SZ_16M; + } + + if (end) { + iop13xx_atue_mem_base = + (u32) __ioremap_pfn( + __phys_to_pfn(IOP13XX_PCIE_LOWER_MEM_PA) + , 0, iop13xx_atue_mem_size, 0); + if (!iop13xx_atue_mem_base) { + printk("%s: atue allocation " + "failed\n", __FUNCTION__); + BUG(); + } + } else + iop13xx_atue_mem_size = 0; + PRINTK("%s: atu: %d bus_size: %d mem_base: %x\n", + __FUNCTION__, atu, iop13xx_atue_mem_size, + iop13xx_atue_mem_base); + break; + } + + printk("%s: Initialized (%uM @ resource/virtual: %08lx/%08x)\n", + atu ? "ATUE" : "ATUX", + (atu ? iop13xx_atue_mem_size : iop13xx_atux_mem_size) / + SZ_1M, + atu ? IOP13XX_PCIE_LOWER_MEM_RA : + IOP13XX_PCIX_LOWER_MEM_RA, + atu ? iop13xx_atue_mem_base : + iop13xx_atux_mem_base); + end = 0; + } + + } +} + +static inline int iop13xx_atu_function(int atu) +{ + int func = 0; + /* the function number depends on the value of the + * IOP13XX_INTERFACE_SEL_PCIX reset strap + * see C-Spec section 3.17 + */ + switch(atu) { + case IOP13XX_INIT_ATU_ATUX: + if (__raw_readl(IOP13XX_ESSR0) & IOP13XX_INTERFACE_SEL_PCIX) + func = 5; + else + func = 0; + break; + case IOP13XX_INIT_ATU_ATUE: + if (__raw_readl(IOP13XX_ESSR0) & IOP13XX_INTERFACE_SEL_PCIX) + func = 0; + else + func = 5; + break; + default: + BUG(); + } + + return func; +} + +/* iop13xx_atux_cfg_address - format a configuration address for atux + * @bus: Target bus to access + * @devfn: Combined device number and function number + * @where: Desired register's address offset + * + * Convert the parameters to a configuration address formatted + * according the PCI-X 2.0 specification + */ +static u32 iop13xx_atux_cfg_address(struct pci_bus *bus, int devfn, int where) +{ + struct pci_sys_data *sys = bus->sysdata; + u32 addr; + + if (sys->busnr == bus->number) + addr = 1 << (PCI_SLOT(devfn) + 16) | (PCI_SLOT(devfn) << 11); + else + addr = bus->number << 16 | PCI_SLOT(devfn) << 11 | 1; + + addr |= PCI_FUNC(devfn) << 8 | ((where & 0xff) & ~3); + addr |= ((where & 0xf00) >> 8) << 24; /* upper register number */ + + return addr; +} + +/* iop13xx_atue_cfg_address - format a configuration address for atue + * @bus: Target bus to access + * @devfn: Combined device number and function number + * @where: Desired register's address offset + * + * Convert the parameters to an address usable by the ATUE_OCCAR + */ +static u32 iop13xx_atue_cfg_address(struct pci_bus *bus, int devfn, int where) +{ + struct pci_sys_data *sys = bus->sysdata; + u32 addr; + + PRINTK("iop13xx_atue_cfg_address: bus: %d dev: %d func: %d", + bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn)); + addr = ((u32) bus->number) << IOP13XX_ATUE_OCCAR_BUS_NUM | + ((u32) PCI_SLOT(devfn)) << IOP13XX_ATUE_OCCAR_DEV_NUM | + ((u32) PCI_FUNC(devfn)) << IOP13XX_ATUE_OCCAR_FUNC_NUM | + (where & ~0x3); + + if (sys->busnr != bus->number) + addr |= 1; /* type 1 access */ + + return addr; +} + +/* This routine checks the status of the last configuration cycle. If an error + * was detected it returns >0, else it returns a 0. The errors being checked + * are parity, master abort, target abort (master and target). These types of + * errors occure during a config cycle where there is no device, like during + * the discovery stage. + */ +static int iop13xx_atux_pci_status(int clear) +{ + unsigned int status; + int err = 0; + + /* + * Check the status registers. + */ + status = __raw_readw(IOP13XX_ATUX_ATUSR); + if (status & IOP_PCI_STATUS_ERROR) + { + PRINTK("\t\t\tPCI error: ATUSR %#08x", status); + if(clear) + __raw_writew(status & IOP_PCI_STATUS_ERROR, + IOP13XX_ATUX_ATUSR); + err = 1; + } + status = __raw_readl(IOP13XX_ATUX_ATUISR); + if (status & IOP13XX_ATUX_ATUISR_ERROR) + { + PRINTK("\t\t\tPCI error interrupt: ATUISR %#08x", status); + if(clear) + __raw_writel(status & IOP13XX_ATUX_ATUISR_ERROR, + IOP13XX_ATUX_ATUISR); + err = 1; + } + return err; +} + +/* Simply write the address register and read the configuration + * data. Note that the data dependency on %0 encourages an abort + * to be detected before we return. + */ +static inline u32 iop13xx_atux_read(unsigned long addr) +{ + u32 val; + + __asm__ __volatile__( + "str %1, [%2]\n\t" + "ldr %0, [%3]\n\t" + "mov %0, %0\n\t" + : "=r" (val) + : "r" (addr), "r" (IOP13XX_ATUX_OCCAR), "r" (IOP13XX_ATUX_OCCDR)); + + return val; +} + +/* The read routines must check the error status of the last configuration + * cycle. If there was an error, the routine returns all hex f's. + */ +static int +iop13xx_atux_read_config(struct pci_bus *bus, unsigned int devfn, int where, + int size, u32 *value) +{ + unsigned long addr = iop13xx_atux_cfg_address(bus, devfn, where); + u32 val = iop13xx_atux_read(addr) >> ((where & 3) * 8); + + if (iop13xx_atux_pci_status(1) || is_atux_occdr_error()) { + __raw_writel(__raw_readl(IOP13XX_XBG_BECSR) & 3, + IOP13XX_XBG_BECSR); + val = 0xffffffff; + } + + *value = val; + + return PCIBIOS_SUCCESSFUL; +} + +static int +iop13xx_atux_write_config(struct pci_bus *bus, unsigned int devfn, int where, + int size, u32 value) +{ + unsigned long addr = iop13xx_atux_cfg_address(bus, devfn, where); + u32 val; + + if (size != 4) { + val = iop13xx_atux_read(addr); + if (!iop13xx_atux_pci_status(1) == 0) + return PCIBIOS_SUCCESSFUL; + + where = (where & 3) * 8; + + if (size == 1) + val &= ~(0xff << where); + else + val &= ~(0xffff << where); + + __raw_writel(val | value << where, IOP13XX_ATUX_OCCDR); + } else { + __raw_writel(addr, IOP13XX_ATUX_OCCAR); + __raw_writel(value, IOP13XX_ATUX_OCCDR); + } + + return PCIBIOS_SUCCESSFUL; +} + +static struct pci_ops iop13xx_atux_ops = { + .read = iop13xx_atux_read_config, + .write = iop13xx_atux_write_config, +}; + +/* This routine checks the status of the last configuration cycle. If an error + * was detected it returns >0, else it returns a 0. The errors being checked + * are parity, master abort, target abort (master and target). These types of + * errors occure during a config cycle where there is no device, like during + * the discovery stage. + */ +static int iop13xx_atue_pci_status(int clear) +{ + unsigned int status; + int err = 0; + + /* + * Check the status registers. + */ + + /* standard pci status register */ + status = __raw_readw(IOP13XX_ATUE_ATUSR); + if (status & IOP_PCI_STATUS_ERROR) { + PRINTK("\t\t\tPCI error: ATUSR %#08x", status); + if(clear) + __raw_writew(status & IOP_PCI_STATUS_ERROR, + IOP13XX_ATUE_ATUSR); + err++; + } + + /* check the normal status bits in the ATUISR */ + status = __raw_readl(IOP13XX_ATUE_ATUISR); + if (status & IOP13XX_ATUE_ATUISR_ERROR) { + PRINTK("\t\t\tPCI error: ATUISR %#08x", status); + if (clear) + __raw_writew(status & IOP13XX_ATUE_ATUISR_ERROR, + IOP13XX_ATUE_ATUISR); + err++; + + /* check the PCI-E status if the ATUISR reports an interface error */ + if (status & IOP13XX_ATUE_STAT_PCI_IFACE_ERR) { + /* get the unmasked errors */ + status = __raw_readl(IOP13XX_ATUE_PIE_STS) & + ~(__raw_readl(IOP13XX_ATUE_PIE_MSK)); + + if (status) { + PRINTK("\t\t\tPCI-E error: ATUE_PIE_STS %#08x", + __raw_readl(IOP13XX_ATUE_PIE_STS)); + err++; + } else { + PRINTK("\t\t\tPCI-E error: ATUE_PIE_STS %#08x", + __raw_readl(IOP13XX_ATUE_PIE_STS)); + PRINTK("\t\t\tPCI-E error: ATUE_PIE_MSK %#08x", + __raw_readl(IOP13XX_ATUE_PIE_MSK)); + BUG(); + } + + if(clear) + __raw_writel(status, IOP13XX_ATUE_PIE_STS); + } + } + + return err; +} + +static inline int __init +iop13xx_pcie_map_irq(struct pci_dev *dev, u8 idsel, u8 pin) +{ + WARN_ON(idsel != 0); + + switch (pin) { + case 1: return ATUE_INTA; + case 2: return ATUE_INTB; + case 3: return ATUE_INTC; + case 4: return ATUE_INTD; + default: return -1; + } +} + +static inline u32 iop13xx_atue_read(unsigned long addr) +{ + u32 val; + + __raw_writel(addr, IOP13XX_ATUE_OCCAR); + val = __raw_readl(IOP13XX_ATUE_OCCDR); + + rmb(); + + return val; +} + +/* The read routines must check the error status of the last configuration + * cycle. If there was an error, the routine returns all hex f's. + */ +static int +iop13xx_atue_read_config(struct pci_bus *bus, unsigned int devfn, int where, + int size, u32 *value) +{ + u32 val; + unsigned long addr = iop13xx_atue_cfg_address(bus, devfn, where); + + /* Hide device numbers > 0 on the local PCI-E bus (Type 0 access) */ + if (!PCI_SLOT(devfn) || (addr & 1)) { + val = iop13xx_atue_read(addr) >> ((where & 3) * 8); + if( iop13xx_atue_pci_status(1) || is_atue_occdr_error() ) { + __raw_writel(__raw_readl(IOP13XX_XBG_BECSR) & 3, + IOP13XX_XBG_BECSR); + val = 0xffffffff; + } + + PRINTK("addr=%#0lx, val=%#010x", addr, val); + } else + val = 0xffffffff; + + *value = val; + + return PCIBIOS_SUCCESSFUL; +} + +static int +iop13xx_atue_write_config(struct pci_bus *bus, unsigned int devfn, int where, + int size, u32 value) +{ + unsigned long addr = iop13xx_atue_cfg_address(bus, devfn, where); + u32 val; + + if (size != 4) { + val = iop13xx_atue_read(addr); + if (!iop13xx_atue_pci_status(1) == 0) + return PCIBIOS_SUCCESSFUL; + + where = (where & 3) * 8; + + if (size == 1) + val &= ~(0xff << where); + else + val &= ~(0xffff << where); + + __raw_writel(val | value << where, IOP13XX_ATUE_OCCDR); + } else { + __raw_writel(addr, IOP13XX_ATUE_OCCAR); + __raw_writel(value, IOP13XX_ATUE_OCCDR); + } + + return PCIBIOS_SUCCESSFUL; +} + +static struct pci_ops iop13xx_atue_ops = { + .read = iop13xx_atue_read_config, + .write = iop13xx_atue_write_config, +}; + +/* When a PCI device does not exist during config cycles, the XScale gets a + * bus error instead of returning 0xffffffff. We can't rely on the ATU status + * bits to tell us that it was indeed a configuration cycle that caused this + * error especially in the case when the ATUE link is down. Instead we rely + * on data from the south XSI bridge to validate the abort + */ +int +iop13xx_pci_abort(unsigned long addr, unsigned int fsr, struct pt_regs *regs) +{ + PRINTK("Data abort: address = 0x%08lx " + "fsr = 0x%03x PC = 0x%08lx LR = 0x%08lx", + addr, fsr, regs->ARM_pc, regs->ARM_lr); + + PRINTK("IOP13XX_XBG_BECSR: %#10x", __raw_readl(IOP13XX_XBG_BECSR)); + PRINTK("IOP13XX_XBG_BERAR: %#10x", __raw_readl(IOP13XX_XBG_BERAR)); + PRINTK("IOP13XX_XBG_BERUAR: %#10x", __raw_readl(IOP13XX_XBG_BERUAR)); + + /* If it was an imprecise abort, then we need to correct the + * return address to be _after_ the instruction. + */ + if (fsr & (1 << 10)) + regs->ARM_pc += 4; + + if (is_atue_occdr_error() || is_atux_occdr_error()) + return 0; + else + return 1; +} + +/* Scan an IOP13XX PCI bus. nr selects which ATU we use. + */ +struct pci_bus *iop13xx_scan_bus(int nr, struct pci_sys_data *sys) +{ + int which_atu; + struct pci_bus *bus = NULL; + + switch (init_atu) { + case IOP13XX_INIT_ATU_ATUX: + which_atu = nr ? 0 : IOP13XX_INIT_ATU_ATUX; + break; + case IOP13XX_INIT_ATU_ATUE: + which_atu = nr ? 0 : IOP13XX_INIT_ATU_ATUE; + break; + case (IOP13XX_INIT_ATU_ATUX | IOP13XX_INIT_ATU_ATUE): + which_atu = nr ? IOP13XX_INIT_ATU_ATUE : IOP13XX_INIT_ATU_ATUX; + break; + default: + which_atu = 0; + } + + if (!which_atu) { + BUG(); + return NULL; + } + + switch (which_atu) { + case IOP13XX_INIT_ATU_ATUX: + if (time_after_eq(jiffies + msecs_to_jiffies(1000), + atux_trhfa_timeout)) /* ensure not wrap */ + while(time_before(jiffies, atux_trhfa_timeout)) + udelay(100); + + bus = pci_bus_atux = pci_scan_bus(sys->busnr, + &iop13xx_atux_ops, + sys); + break; + case IOP13XX_INIT_ATU_ATUE: + bus = pci_bus_atue = pci_scan_bus(sys->busnr, + &iop13xx_atue_ops, + sys); + break; + } + + return bus; +} + +/* This function is called from iop13xx_pci_init() after assigning valid + * values to iop13xx_atue_pmmr_offset. This is the location for common + * setup of ATUE for all IOP13XX implementations. + */ +void __init iop13xx_atue_setup(void) +{ + int func = iop13xx_atu_function(IOP13XX_INIT_ATU_ATUE); + u32 reg_val; + + /* BAR 1 (1:1 mapping with Physical RAM) */ + /* Set limit and enable */ + __raw_writel(~(IOP13XX_MAX_RAM_SIZE - PHYS_OFFSET - 1) & ~0x1, + IOP13XX_ATUE_IALR1); + __raw_writel(0x0, IOP13XX_ATUE_IAUBAR1); + + /* Set base at the top of the reserved address space */ + __raw_writel(PHYS_OFFSET | PCI_BASE_ADDRESS_MEM_TYPE_64 | + PCI_BASE_ADDRESS_MEM_PREFETCH, IOP13XX_ATUE_IABAR1); + + /* 1:1 mapping with physical ram + * (leave big endian byte swap disabled) + */ + __raw_writel(0x0, IOP13XX_ATUE_IAUTVR1); + __raw_writel(PHYS_OFFSET, IOP13XX_ATUE_IATVR1); + + /* Outbound window 1 (PCIX/PCIE memory window) */ + /* 32 bit Address Space */ + __raw_writel(0x0, IOP13XX_ATUE_OUMWTVR1); + /* PA[35:32] */ + __raw_writel(IOP13XX_ATUE_OUMBAR_ENABLE | + (IOP13XX_PCIE_MEM_PHYS_OFFSET >> 32), + IOP13XX_ATUE_OUMBAR1); + + /* Setup the I/O Bar + * A[35-16] in 31-12 + */ + __raw_writel(((IOP13XX_PCIE_LOWER_IO_PA >> 0x4) & 0xfffff000), + IOP13XX_ATUE_OIOBAR); + __raw_writel(IOP13XX_PCIE_LOWER_IO_BA, IOP13XX_ATUE_OIOWTVR); + + /* clear startup errors */ + iop13xx_atue_pci_status(1); + + /* OIOBAR function number + */ + reg_val = __raw_readl(IOP13XX_ATUE_OIOBAR); + reg_val &= ~0x7; + reg_val |= func; + __raw_writel(reg_val, IOP13XX_ATUE_OIOBAR); + + /* OUMBAR function numbers + */ + reg_val = __raw_readl(IOP13XX_ATUE_OUMBAR0); + reg_val &= ~(IOP13XX_ATU_OUMBAR_FUNC_NUM_MASK << + IOP13XX_ATU_OUMBAR_FUNC_NUM); + reg_val |= func << IOP13XX_ATU_OUMBAR_FUNC_NUM; + __raw_writel(reg_val, IOP13XX_ATUE_OUMBAR0); + + reg_val = __raw_readl(IOP13XX_ATUE_OUMBAR1); + reg_val &= ~(IOP13XX_ATU_OUMBAR_FUNC_NUM_MASK << + IOP13XX_ATU_OUMBAR_FUNC_NUM); + reg_val |= func << IOP13XX_ATU_OUMBAR_FUNC_NUM; + __raw_writel(reg_val, IOP13XX_ATUE_OUMBAR1); + + reg_val = __raw_readl(IOP13XX_ATUE_OUMBAR2); + reg_val &= ~(IOP13XX_ATU_OUMBAR_FUNC_NUM_MASK << + IOP13XX_ATU_OUMBAR_FUNC_NUM); + reg_val |= func << IOP13XX_ATU_OUMBAR_FUNC_NUM; + __raw_writel(reg_val, IOP13XX_ATUE_OUMBAR2); + + reg_val = __raw_readl(IOP13XX_ATUE_OUMBAR3); + reg_val &= ~(IOP13XX_ATU_OUMBAR_FUNC_NUM_MASK << + IOP13XX_ATU_OUMBAR_FUNC_NUM); + reg_val |= func << IOP13XX_ATU_OUMBAR_FUNC_NUM; + __raw_writel(reg_val, IOP13XX_ATUE_OUMBAR3); + + /* Enable inbound and outbound cycles + */ + reg_val = __raw_readw(IOP13XX_ATUE_ATUCMD); + reg_val |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | + PCI_COMMAND_PARITY | PCI_COMMAND_SERR; + __raw_writew(reg_val, IOP13XX_ATUE_ATUCMD); + + reg_val = __raw_readl(IOP13XX_ATUE_ATUCR); + reg_val |= IOP13XX_ATUE_ATUCR_OUT_EN | + IOP13XX_ATUE_ATUCR_IVM; + __raw_writel(reg_val, IOP13XX_ATUE_ATUCR); +} + +void __init iop13xx_atue_disable(void) +{ + u32 reg_val; + + __raw_writew(0x0, IOP13XX_ATUE_ATUCMD); + __raw_writel(IOP13XX_ATUE_ATUCR_IVM, IOP13XX_ATUE_ATUCR); + + /* wait for cycles to quiesce */ + while (__raw_readl(IOP13XX_ATUE_PCSR) & (IOP13XX_ATUE_PCSR_OUT_Q_BUSY | + IOP13XX_ATUE_PCSR_IN_Q_BUSY | + IOP13XX_ATUE_PCSR_LLRB_BUSY)) + cpu_relax(); + + /* BAR 0 ( Disabled ) */ + __raw_writel(0x0, IOP13XX_ATUE_IAUBAR0); + __raw_writel(0x0, IOP13XX_ATUE_IABAR0); + __raw_writel(0x0, IOP13XX_ATUE_IAUTVR0); + __raw_writel(0x0, IOP13XX_ATUE_IATVR0); + __raw_writel(0x0, IOP13XX_ATUE_IALR0); + reg_val = __raw_readl(IOP13XX_ATUE_OUMBAR0); + reg_val &= ~IOP13XX_ATUE_OUMBAR_ENABLE; + __raw_writel(reg_val, IOP13XX_ATUE_OUMBAR0); + + /* BAR 1 ( Disabled ) */ + __raw_writel(0x0, IOP13XX_ATUE_IAUBAR1); + __raw_writel(0x0, IOP13XX_ATUE_IABAR1); + __raw_writel(0x0, IOP13XX_ATUE_IAUTVR1); + __raw_writel(0x0, IOP13XX_ATUE_IATVR1); + __raw_writel(0x0, IOP13XX_ATUE_IALR1); + reg_val = __raw_readl(IOP13XX_ATUE_OUMBAR1); + reg_val &= ~IOP13XX_ATUE_OUMBAR_ENABLE; + __raw_writel(reg_val, IOP13XX_ATUE_OUMBAR1); + + /* BAR 2 ( Disabled ) */ + __raw_writel(0x0, IOP13XX_ATUE_IAUBAR2); + __raw_writel(0x0, IOP13XX_ATUE_IABAR2); + __raw_writel(0x0, IOP13XX_ATUE_IAUTVR2); + __raw_writel(0x0, IOP13XX_ATUE_IATVR2); + __raw_writel(0x0, IOP13XX_ATUE_IALR2); + reg_val = __raw_readl(IOP13XX_ATUE_OUMBAR2); + reg_val &= ~IOP13XX_ATUE_OUMBAR_ENABLE; + __raw_writel(reg_val, IOP13XX_ATUE_OUMBAR2); + + /* BAR 3 ( Disabled ) */ + reg_val = __raw_readl(IOP13XX_ATUE_OUMBAR3); + reg_val &= ~IOP13XX_ATUE_OUMBAR_ENABLE; + __raw_writel(reg_val, IOP13XX_ATUE_OUMBAR3); + + /* Setup the I/O Bar + * A[35-16] in 31-12 + */ + __raw_writel((IOP13XX_PCIE_LOWER_IO_PA >> 0x4) & 0xfffff000, + IOP13XX_ATUE_OIOBAR); + __raw_writel(IOP13XX_PCIE_LOWER_IO_BA, IOP13XX_ATUE_OIOWTVR); +} + +/* This function is called from iop13xx_pci_init() after assigning valid + * values to iop13xx_atux_pmmr_offset. This is the location for common + * setup of ATUX for all IOP13XX implementations. + */ +void __init iop13xx_atux_setup(void) +{ + u32 reg_val; + int func = iop13xx_atu_function(IOP13XX_INIT_ATU_ATUX); + + /* Take PCI-X bus out of reset if bootloader hasn't already. + * According to spec, we should wait for 2^25 PCI clocks to meet + * the PCI timing parameter Trhfa (RST# high to first access). + * This is rarely necessary and often ignored. + */ + reg_val = __raw_readl(IOP13XX_ATUX_PCSR); + if (reg_val & IOP13XX_ATUX_PCSR_P_RSTOUT) { + int msec = (reg_val >> IOP13XX_ATUX_PCSR_FREQ_OFFSET) & 0x7; + msec = 1000 / (8-msec); /* bits 100=133MHz, 111=>33MHz */ + __raw_writel(reg_val & ~IOP13XX_ATUX_PCSR_P_RSTOUT, + IOP13XX_ATUX_PCSR); + atux_trhfa_timeout = jiffies + msecs_to_jiffies(msec); + } + else + atux_trhfa_timeout = jiffies; + + /* BAR 1 (1:1 mapping with Physical RAM) */ + /* Set limit and enable */ + __raw_writel(~(IOP13XX_MAX_RAM_SIZE - PHYS_OFFSET - 1) & ~0x1, + IOP13XX_ATUX_IALR1); + __raw_writel(0x0, IOP13XX_ATUX_IAUBAR1); + + /* Set base at the top of the reserved address space */ + __raw_writel(PHYS_OFFSET | PCI_BASE_ADDRESS_MEM_TYPE_64 | + PCI_BASE_ADDRESS_MEM_PREFETCH, IOP13XX_ATUX_IABAR1); + + /* 1:1 mapping with physical ram + * (leave big endian byte swap disabled) + */ + __raw_writel(0x0, IOP13XX_ATUX_IAUTVR1); + __raw_writel(PHYS_OFFSET, IOP13XX_ATUX_IATVR1); + + /* Outbound window 1 (PCIX/PCIE memory window) */ + /* 32 bit Address Space */ + __raw_writel(0x0, IOP13XX_ATUX_OUMWTVR1); + /* PA[35:32] */ + __raw_writel(IOP13XX_ATUX_OUMBAR_ENABLE | + IOP13XX_PCIX_MEM_PHYS_OFFSET >> 32, + IOP13XX_ATUX_OUMBAR1); + + /* Setup the I/O Bar + * A[35-16] in 31-12 + */ + __raw_writel((IOP13XX_PCIX_LOWER_IO_PA >> 0x4) & 0xfffff000, + IOP13XX_ATUX_OIOBAR); + __raw_writel(IOP13XX_PCIX_LOWER_IO_BA, IOP13XX_ATUX_OIOWTVR); + + /* clear startup errors */ + iop13xx_atux_pci_status(1); + + /* OIOBAR function number + */ + reg_val = __raw_readl(IOP13XX_ATUX_OIOBAR); + reg_val &= ~0x7; + reg_val |= func; + __raw_writel(reg_val, IOP13XX_ATUX_OIOBAR); + + /* OUMBAR function numbers + */ + reg_val = __raw_readl(IOP13XX_ATUX_OUMBAR0); + reg_val &= ~(IOP13XX_ATU_OUMBAR_FUNC_NUM_MASK << + IOP13XX_ATU_OUMBAR_FUNC_NUM); + reg_val |= func << IOP13XX_ATU_OUMBAR_FUNC_NUM; + __raw_writel(reg_val, IOP13XX_ATUX_OUMBAR0); + + reg_val = __raw_readl(IOP13XX_ATUX_OUMBAR1); + reg_val &= ~(IOP13XX_ATU_OUMBAR_FUNC_NUM_MASK << + IOP13XX_ATU_OUMBAR_FUNC_NUM); + reg_val |= func << IOP13XX_ATU_OUMBAR_FUNC_NUM; + __raw_writel(reg_val, IOP13XX_ATUX_OUMBAR1); + + reg_val = __raw_readl(IOP13XX_ATUX_OUMBAR2); + reg_val &= ~(IOP13XX_ATU_OUMBAR_FUNC_NUM_MASK << + IOP13XX_ATU_OUMBAR_FUNC_NUM); + reg_val |= func << IOP13XX_ATU_OUMBAR_FUNC_NUM; + __raw_writel(reg_val, IOP13XX_ATUX_OUMBAR2); + + reg_val = __raw_readl(IOP13XX_ATUX_OUMBAR3); + reg_val &= ~(IOP13XX_ATU_OUMBAR_FUNC_NUM_MASK << + IOP13XX_ATU_OUMBAR_FUNC_NUM); + reg_val |= func << IOP13XX_ATU_OUMBAR_FUNC_NUM; + __raw_writel(reg_val, IOP13XX_ATUX_OUMBAR3); + + /* Enable inbound and outbound cycles + */ + reg_val = __raw_readw(IOP13XX_ATUX_ATUCMD); + reg_val |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | + PCI_COMMAND_PARITY | PCI_COMMAND_SERR; + __raw_writew(reg_val, IOP13XX_ATUX_ATUCMD); + + reg_val = __raw_readl(IOP13XX_ATUX_ATUCR); + reg_val |= IOP13XX_ATUX_ATUCR_OUT_EN; + __raw_writel(reg_val, IOP13XX_ATUX_ATUCR); +} + +void __init iop13xx_atux_disable(void) +{ + u32 reg_val; + + __raw_writew(0x0, IOP13XX_ATUX_ATUCMD); + __raw_writel(0x0, IOP13XX_ATUX_ATUCR); + + /* wait for cycles to quiesce */ + while (__raw_readl(IOP13XX_ATUX_PCSR) & (IOP13XX_ATUX_PCSR_OUT_Q_BUSY | + IOP13XX_ATUX_PCSR_IN_Q_BUSY)) + cpu_relax(); + + /* BAR 0 ( Disabled ) */ + __raw_writel(0x0, IOP13XX_ATUX_IAUBAR0); + __raw_writel(0x0, IOP13XX_ATUX_IABAR0); + __raw_writel(0x0, IOP13XX_ATUX_IAUTVR0); + __raw_writel(0x0, IOP13XX_ATUX_IATVR0); + __raw_writel(0x0, IOP13XX_ATUX_IALR0); + reg_val = __raw_readl(IOP13XX_ATUX_OUMBAR0); + reg_val &= ~IOP13XX_ATUX_OUMBAR_ENABLE; + __raw_writel(reg_val, IOP13XX_ATUX_OUMBAR0); + + /* BAR 1 ( Disabled ) */ + __raw_writel(0x0, IOP13XX_ATUX_IAUBAR1); + __raw_writel(0x0, IOP13XX_ATUX_IABAR1); + __raw_writel(0x0, IOP13XX_ATUX_IAUTVR1); + __raw_writel(0x0, IOP13XX_ATUX_IATVR1); + __raw_writel(0x0, IOP13XX_ATUX_IALR1); + reg_val = __raw_readl(IOP13XX_ATUX_OUMBAR1); + reg_val &= ~IOP13XX_ATUX_OUMBAR_ENABLE; + __raw_writel(reg_val, IOP13XX_ATUX_OUMBAR1); + + /* BAR 2 ( Disabled ) */ + __raw_writel(0x0, IOP13XX_ATUX_IAUBAR2); + __raw_writel(0x0, IOP13XX_ATUX_IABAR2); + __raw_writel(0x0, IOP13XX_ATUX_IAUTVR2); + __raw_writel(0x0, IOP13XX_ATUX_IATVR2); + __raw_writel(0x0, IOP13XX_ATUX_IALR2); + reg_val = __raw_readl(IOP13XX_ATUX_OUMBAR2); + reg_val &= ~IOP13XX_ATUX_OUMBAR_ENABLE; + __raw_writel(reg_val, IOP13XX_ATUX_OUMBAR2); + + /* BAR 3 ( Disabled ) */ + __raw_writel(0x0, IOP13XX_ATUX_IAUBAR3); + __raw_writel(0x0, IOP13XX_ATUX_IABAR3); + __raw_writel(0x0, IOP13XX_ATUX_IAUTVR3); + __raw_writel(0x0, IOP13XX_ATUX_IATVR3); + __raw_writel(0x0, IOP13XX_ATUX_IALR3); + reg_val = __raw_readl(IOP13XX_ATUX_OUMBAR3); + reg_val &= ~IOP13XX_ATUX_OUMBAR_ENABLE; + __raw_writel(reg_val, IOP13XX_ATUX_OUMBAR3); + + /* Setup the I/O Bar + * A[35-16] in 31-12 + */ + __raw_writel((IOP13XX_PCIX_LOWER_IO_PA >> 0x4) & 0xfffff000, + IOP13XX_ATUX_OIOBAR); + __raw_writel(IOP13XX_PCIX_LOWER_IO_BA, IOP13XX_ATUX_OIOWTVR); +} + +void __init iop13xx_set_atu_mmr_bases(void) +{ + /* Based on ESSR0, determine the ATU X/E offsets */ + switch(__raw_readl(IOP13XX_ESSR0) & + (IOP13XX_CONTROLLER_ONLY | IOP13XX_INTERFACE_SEL_PCIX)) { + /* both asserted */ + case 0: + iop13xx_atux_pmmr_offset = IOP13XX_ATU1_PMMR_OFFSET; + iop13xx_atue_pmmr_offset = IOP13XX_ATU2_PMMR_OFFSET; + break; + /* IOP13XX_CONTROLLER_ONLY = deasserted + * IOP13XX_INTERFACE_SEL_PCIX = asserted + */ + case IOP13XX_CONTROLLER_ONLY: + iop13xx_atux_pmmr_offset = IOP13XX_ATU0_PMMR_OFFSET; + iop13xx_atue_pmmr_offset = IOP13XX_ATU2_PMMR_OFFSET; + break; + /* IOP13XX_CONTROLLER_ONLY = asserted + * IOP13XX_INTERFACE_SEL_PCIX = deasserted + */ + case IOP13XX_INTERFACE_SEL_PCIX: + iop13xx_atux_pmmr_offset = IOP13XX_ATU1_PMMR_OFFSET; + iop13xx_atue_pmmr_offset = IOP13XX_ATU2_PMMR_OFFSET; + break; + /* both deasserted */ + case IOP13XX_CONTROLLER_ONLY | IOP13XX_INTERFACE_SEL_PCIX: + iop13xx_atux_pmmr_offset = IOP13XX_ATU2_PMMR_OFFSET; + iop13xx_atue_pmmr_offset = IOP13XX_ATU0_PMMR_OFFSET; + break; + default: + BUG(); + } +} + +void __init iop13xx_atu_select(struct hw_pci *plat_pci) +{ + int i; + + /* set system defaults + * note: if "iop13xx_init_atu=" is specified this autodetect + * sequence will be bypassed + */ + if (init_atu == IOP13XX_INIT_ATU_DEFAULT) { + /* check for single/dual interface */ + if (__raw_readl(IOP13XX_ESSR0) & IOP13XX_INTERFACE_SEL_PCIX) { + /* ATUE must be present check the device id + * to see if ATUX is present. + */ + init_atu |= IOP13XX_INIT_ATU_ATUE; + switch (__raw_readw(IOP13XX_ATUE_DID) & 0xf0) { + case 0x70: + case 0x80: + case 0xc0: + init_atu |= IOP13XX_INIT_ATU_ATUX; + break; + } + } else { + /* ATUX must be present check the device id + * to see if ATUE is present. + */ + init_atu |= IOP13XX_INIT_ATU_ATUX; + switch (__raw_readw(IOP13XX_ATUX_DID) & 0xf0) { + case 0x70: + case 0x80: + case 0xc0: + init_atu |= IOP13XX_INIT_ATU_ATUE; + break; + } + } + + /* check central resource and root complex capability */ + if (init_atu & IOP13XX_INIT_ATU_ATUX) + if (!(__raw_readl(IOP13XX_ATUX_PCSR) & + IOP13XX_ATUX_PCSR_CENTRAL_RES)) + init_atu &= ~IOP13XX_INIT_ATU_ATUX; + + if (init_atu & IOP13XX_INIT_ATU_ATUE) + if (__raw_readl(IOP13XX_ATUE_PCSR) & + IOP13XX_ATUE_PCSR_END_POINT) + init_atu &= ~IOP13XX_INIT_ATU_ATUE; + } + + for (i = 0; i < 2; i++) { + if((init_atu & (1 << i)) == (1 << i)) + plat_pci->nr_controllers++; + } +} + +void __init iop13xx_pci_init(void) +{ + /* clear pre-existing south bridge errors */ + __raw_writel(__raw_readl(IOP13XX_XBG_BECSR) & 3, IOP13XX_XBG_BECSR); + + /* Setup the Min Address for PCI memory... */ + iop13xx_pcibios_min_mem = IOP13XX_PCIX_LOWER_MEM_BA; + + /* if Linux is given control of an ATU + * clear out its prior configuration, + * otherwise do not touch the registers + */ + if (init_atu & IOP13XX_INIT_ATU_ATUE) { + iop13xx_atue_disable(); + iop13xx_atue_setup(); + } + + if (init_atu & IOP13XX_INIT_ATU_ATUX) { + iop13xx_atux_disable(); + iop13xx_atux_setup(); + } + + hook_fault_code(16+6, iop13xx_pci_abort, SIGBUS, + "imprecise external abort"); +} + +/* intialize the pci memory space. handle any combination of + * atue and atux enabled/disabled + */ +int iop13xx_pci_setup(int nr, struct pci_sys_data *sys) +{ + struct resource *res; + int which_atu; + u32 pcixsr, pcsr; + + if (nr > 1) + return 0; + + res = kmalloc(sizeof(struct resource) * 2, GFP_KERNEL); + if (!res) + panic("PCI: unable to alloc resources"); + + memset(res, 0, sizeof(struct resource) * 2); + + /* 'nr' assumptions: + * ATUX is always 0 + * ATUE is 1 when ATUX is also enabled + * ATUE is 0 when ATUX is disabled + */ + switch(init_atu) { + case IOP13XX_INIT_ATU_ATUX: + which_atu = nr ? 0 : IOP13XX_INIT_ATU_ATUX; + break; + case IOP13XX_INIT_ATU_ATUE: + which_atu = nr ? 0 : IOP13XX_INIT_ATU_ATUE; + break; + case (IOP13XX_INIT_ATU_ATUX | IOP13XX_INIT_ATU_ATUE): + which_atu = nr ? IOP13XX_INIT_ATU_ATUE : IOP13XX_INIT_ATU_ATUX; + break; + default: + which_atu = 0; + } + + if (!which_atu) + return 0; + + switch(which_atu) { + case IOP13XX_INIT_ATU_ATUX: + pcixsr = __raw_readl(IOP13XX_ATUX_PCIXSR); + pcixsr &= ~0xffff; + pcixsr |= sys->busnr << IOP13XX_ATUX_PCIXSR_BUS_NUM | + 0 << IOP13XX_ATUX_PCIXSR_DEV_NUM | + iop13xx_atu_function(IOP13XX_INIT_ATU_ATUX) + << IOP13XX_ATUX_PCIXSR_FUNC_NUM; + __raw_writel(pcixsr, IOP13XX_ATUX_PCIXSR); + + res[0].start = IOP13XX_PCIX_LOWER_IO_PA; + res[0].end = IOP13XX_PCIX_UPPER_IO_PA; + res[0].name = "IQ81340 ATUX PCI I/O Space"; + res[0].flags = IORESOURCE_IO; + + res[1].start = IOP13XX_PCIX_LOWER_MEM_RA; + res[1].end = IOP13XX_PCIX_UPPER_MEM_RA; + res[1].name = "IQ81340 ATUX PCI Memory Space"; + res[1].flags = IORESOURCE_MEM; + sys->mem_offset = IOP13XX_PCIX_MEM_OFFSET; + sys->io_offset = IOP13XX_PCIX_IO_OFFSET; + break; + case IOP13XX_INIT_ATU_ATUE: + /* Note: the function number field in the PCSR is ro */ + pcsr = __raw_readl(IOP13XX_ATUE_PCSR); + pcsr &= ~(0xfff8 << 16); + pcsr |= sys->busnr << IOP13XX_ATUE_PCSR_BUS_NUM | + 0 << IOP13XX_ATUE_PCSR_DEV_NUM; + + __raw_writel(pcsr, IOP13XX_ATUE_PCSR); + + res[0].start = IOP13XX_PCIE_LOWER_IO_PA; + res[0].end = IOP13XX_PCIE_UPPER_IO_PA; + res[0].name = "IQ81340 ATUE PCI I/O Space"; + res[0].flags = IORESOURCE_IO; + + res[1].start = IOP13XX_PCIE_LOWER_MEM_RA; + res[1].end = IOP13XX_PCIE_UPPER_MEM_RA; + res[1].name = "IQ81340 ATUE PCI Memory Space"; + res[1].flags = IORESOURCE_MEM; + sys->mem_offset = IOP13XX_PCIE_MEM_OFFSET; + sys->io_offset = IOP13XX_PCIE_IO_OFFSET; + sys->map_irq = iop13xx_pcie_map_irq; + break; + default: + return 0; + } + + request_resource(&ioport_resource, &res[0]); + request_resource(&iomem_resource, &res[1]); + + sys->resource[0] = &res[0]; + sys->resource[1] = &res[1]; + sys->resource[2] = NULL; + + return 1; +} + +u16 iop13xx_dev_id(void) +{ + if (__raw_readl(IOP13XX_ESSR0) & IOP13XX_INTERFACE_SEL_PCIX) + return __raw_readw(IOP13XX_ATUE_DID); + else + return __raw_readw(IOP13XX_ATUX_DID); +} + +static int __init iop13xx_init_atu_setup(char *str) +{ + init_atu = IOP13XX_INIT_ATU_NONE; + if (str) { + while (*str != '\0') { + switch (*str) { + case 'x': + case 'X': + init_atu |= IOP13XX_INIT_ATU_ATUX; + init_atu &= ~IOP13XX_INIT_ATU_NONE; + break; + case 'e': + case 'E': + init_atu |= IOP13XX_INIT_ATU_ATUE; + init_atu &= ~IOP13XX_INIT_ATU_NONE; + break; + case ',': + case '=': + break; + default: + PRINTK("\"iop13xx_init_atu\" malformed at " + "character: \'%c\'", *str); + *(str + 1) = '\0'; + init_atu = IOP13XX_INIT_ATU_DEFAULT; + } + str++; + } + } + return 1; +} + +__setup("iop13xx_init_atu", iop13xx_init_atu_setup); diff --git a/trunk/arch/arm/mach-iop13xx/setup.c b/trunk/arch/arm/mach-iop13xx/setup.c new file mode 100644 index 000000000000..3756d2ccb1a7 --- /dev/null +++ b/trunk/arch/arm/mach-iop13xx/setup.c @@ -0,0 +1,406 @@ +/* + * iop13xx platform Initialization + * Copyright (c) 2005-2006, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place - Suite 330, Boston, MA 02111-1307 USA. + * + */ + +#include +#ifdef CONFIG_MTD_PHYSMAP +#include +#endif +#include +#include +#include + +#define IOP13XX_UART_XTAL 33334000 +#define IOP13XX_SETUP_DEBUG 0 +#define PRINTK(x...) ((void)(IOP13XX_SETUP_DEBUG && printk(x))) + +/* Standard IO mapping for all IOP13XX based systems + */ +static struct map_desc iop13xx_std_desc[] __initdata = { + { /* mem mapped registers */ + .virtual = IOP13XX_PMMR_VIRT_MEM_BASE, + .pfn = __phys_to_pfn(IOP13XX_PMMR_PHYS_MEM_BASE), + .length = IOP13XX_PMMR_SIZE, + .type = MT_DEVICE, + }, { /* PCIE IO space */ + .virtual = IOP13XX_PCIE_LOWER_IO_VA, + .pfn = __phys_to_pfn(IOP13XX_PCIE_LOWER_IO_PA), + .length = IOP13XX_PCIX_IO_WINDOW_SIZE, + .type = MT_DEVICE, + }, { /* PCIX IO space */ + .virtual = IOP13XX_PCIX_LOWER_IO_VA, + .pfn = __phys_to_pfn(IOP13XX_PCIX_LOWER_IO_PA), + .length = IOP13XX_PCIX_IO_WINDOW_SIZE, + .type = MT_DEVICE, + }, +}; + +static struct resource iop13xx_uart0_resources[] = { + [0] = { + .start = IOP13XX_UART0_PHYS, + .end = IOP13XX_UART0_PHYS + 0x3f, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_IOP13XX_UART0, + .end = IRQ_IOP13XX_UART0, + .flags = IORESOURCE_IRQ + } +}; + +static struct resource iop13xx_uart1_resources[] = { + [0] = { + .start = IOP13XX_UART1_PHYS, + .end = IOP13XX_UART1_PHYS + 0x3f, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_IOP13XX_UART1, + .end = IRQ_IOP13XX_UART1, + .flags = IORESOURCE_IRQ + } +}; + +static struct plat_serial8250_port iop13xx_uart0_data[] = { + { + .membase = (char*)(IOP13XX_UART0_VIRT), + .mapbase = (IOP13XX_UART0_PHYS), + .irq = IRQ_IOP13XX_UART0, + .uartclk = IOP13XX_UART_XTAL, + .regshift = 2, + .iotype = UPIO_MEM, + .flags = UPF_SKIP_TEST, + }, + { }, +}; + +static struct plat_serial8250_port iop13xx_uart1_data[] = { + { + .membase = (char*)(IOP13XX_UART1_VIRT), + .mapbase = (IOP13XX_UART1_PHYS), + .irq = IRQ_IOP13XX_UART1, + .uartclk = IOP13XX_UART_XTAL, + .regshift = 2, + .iotype = UPIO_MEM, + .flags = UPF_SKIP_TEST, + }, + { }, +}; + +/* The ids are fixed up later in iop13xx_platform_init */ +static struct platform_device iop13xx_uart0 = { + .name = "serial8250", + .id = 0, + .dev.platform_data = iop13xx_uart0_data, + .num_resources = 2, + .resource = iop13xx_uart0_resources, +}; + +static struct platform_device iop13xx_uart1 = { + .name = "serial8250", + .id = 0, + .dev.platform_data = iop13xx_uart1_data, + .num_resources = 2, + .resource = iop13xx_uart1_resources +}; + +static struct resource iop13xx_i2c_0_resources[] = { + [0] = { + .start = IOP13XX_I2C0_PHYS, + .end = IOP13XX_I2C0_PHYS + 0x18, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_IOP13XX_I2C_0, + .end = IRQ_IOP13XX_I2C_0, + .flags = IORESOURCE_IRQ + } +}; + +static struct resource iop13xx_i2c_1_resources[] = { + [0] = { + .start = IOP13XX_I2C1_PHYS, + .end = IOP13XX_I2C1_PHYS + 0x18, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_IOP13XX_I2C_1, + .end = IRQ_IOP13XX_I2C_1, + .flags = IORESOURCE_IRQ + } +}; + +static struct resource iop13xx_i2c_2_resources[] = { + [0] = { + .start = IOP13XX_I2C2_PHYS, + .end = IOP13XX_I2C2_PHYS + 0x18, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_IOP13XX_I2C_2, + .end = IRQ_IOP13XX_I2C_2, + .flags = IORESOURCE_IRQ + } +}; + +/* I2C controllers. The IOP13XX uses the same block as the IOP3xx, so + * we just use the same device name. + */ + +/* The ids are fixed up later in iop13xx_platform_init */ +static struct platform_device iop13xx_i2c_0_controller = { + .name = "IOP3xx-I2C", + .id = 0, + .num_resources = 2, + .resource = iop13xx_i2c_0_resources +}; + +static struct platform_device iop13xx_i2c_1_controller = { + .name = "IOP3xx-I2C", + .id = 0, + .num_resources = 2, + .resource = iop13xx_i2c_1_resources +}; + +static struct platform_device iop13xx_i2c_2_controller = { + .name = "IOP3xx-I2C", + .id = 0, + .num_resources = 2, + .resource = iop13xx_i2c_2_resources +}; + +#ifdef CONFIG_MTD_PHYSMAP +/* PBI Flash Device + */ +static struct physmap_flash_data iq8134x_flash_data = { + .width = 2, +}; + +static struct resource iq8134x_flash_resource = { + .start = IQ81340_FLASHBASE, + .end = 0, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device iq8134x_flash = { + .name = "physmap-flash", + .id = 0, + .dev = { .platform_data = &iq8134x_flash_data, }, + .num_resources = 1, + .resource = &iq8134x_flash_resource, +}; + +static unsigned long iq8134x_probe_flash_size(void) +{ + uint8_t __iomem *flash_addr = ioremap(IQ81340_FLASHBASE, PAGE_SIZE); + int i; + char query[3]; + unsigned long size = 0; + int width = iq8134x_flash_data.width; + + if (flash_addr) { + /* send CFI 'query' command */ + writew(0x98, flash_addr); + + /* check for CFI compliance */ + for (i = 0; i < 3 * width; i += width) + query[i / width] = readb(flash_addr + (0x10 * width) + i); + + /* read the size */ + if (memcmp(query, "QRY", 3) == 0) + size = 1 << readb(flash_addr + (0x27 * width)); + + /* send CFI 'read array' command */ + writew(0xff, flash_addr); + + iounmap(flash_addr); + } + + return size; +} +#endif + +void __init iop13xx_map_io(void) +{ + /* Initialize the Static Page Table maps */ + iotable_init(iop13xx_std_desc, ARRAY_SIZE(iop13xx_std_desc)); +} + +static int init_uart = 0; +static int init_i2c = 0; + +void __init iop13xx_platform_init(void) +{ + int i; + u32 uart_idx, i2c_idx, plat_idx; + struct platform_device *iop13xx_devices[IQ81340_MAX_PLAT_DEVICES]; + + /* set the bases so we can read the device id */ + iop13xx_set_atu_mmr_bases(); + + memset(iop13xx_devices, 0, sizeof(iop13xx_devices)); + + if (init_uart == IOP13XX_INIT_UART_DEFAULT) { + switch (iop13xx_dev_id()) { + /* enable both uarts on iop341 and iop342 */ + case 0x3380: + case 0x3384: + case 0x3388: + case 0x338c: + case 0x3382: + case 0x3386: + case 0x338a: + case 0x338e: + init_uart |= IOP13XX_INIT_UART_0; + init_uart |= IOP13XX_INIT_UART_1; + break; + /* only enable uart 1 */ + default: + init_uart |= IOP13XX_INIT_UART_1; + } + } + + if (init_i2c == IOP13XX_INIT_I2C_DEFAULT) { + switch (iop13xx_dev_id()) { + /* enable all i2c units on iop341 and iop342 */ + case 0x3380: + case 0x3384: + case 0x3388: + case 0x338c: + case 0x3382: + case 0x3386: + case 0x338a: + case 0x338e: + init_i2c |= IOP13XX_INIT_I2C_0; + init_i2c |= IOP13XX_INIT_I2C_1; + init_i2c |= IOP13XX_INIT_I2C_2; + break; + /* only enable i2c 1 and 2 */ + default: + init_i2c |= IOP13XX_INIT_I2C_1; + init_i2c |= IOP13XX_INIT_I2C_2; + } + } + + plat_idx = 0; + uart_idx = 0; + i2c_idx = 0; + + /* uart 1 (if enabled) is ttyS0 */ + if (init_uart & IOP13XX_INIT_UART_1) { + PRINTK("Adding uart1 to platform device list\n"); + iop13xx_uart1.id = uart_idx++; + iop13xx_devices[plat_idx++] = &iop13xx_uart1; + } + if (init_uart & IOP13XX_INIT_UART_0) { + PRINTK("Adding uart0 to platform device list\n"); + iop13xx_uart0.id = uart_idx++; + iop13xx_devices[plat_idx++] = &iop13xx_uart0; + } + + for(i = 0; i < IQ81340_NUM_I2C; i++) { + if ((init_i2c & (1 << i)) && IOP13XX_SETUP_DEBUG) + printk("Adding i2c%d to platform device list\n", i); + switch(init_i2c & (1 << i)) { + case IOP13XX_INIT_I2C_0: + iop13xx_i2c_0_controller.id = i2c_idx++; + iop13xx_devices[plat_idx++] = + &iop13xx_i2c_0_controller; + break; + case IOP13XX_INIT_I2C_1: + iop13xx_i2c_1_controller.id = i2c_idx++; + iop13xx_devices[plat_idx++] = + &iop13xx_i2c_1_controller; + break; + case IOP13XX_INIT_I2C_2: + iop13xx_i2c_2_controller.id = i2c_idx++; + iop13xx_devices[plat_idx++] = + &iop13xx_i2c_2_controller; + break; + } + } + +#ifdef CONFIG_MTD_PHYSMAP + iq8134x_flash_resource.end = iq8134x_flash_resource.start + + iq8134x_probe_flash_size(); + if (iq8134x_flash_resource.end > iq8134x_flash_resource.start) + iop13xx_devices[plat_idx++] = &iq8134x_flash; + else + printk(KERN_ERR "%s: Failed to probe flash size\n", __FUNCTION__); +#endif + + platform_add_devices(iop13xx_devices, plat_idx); +} + +static int __init iop13xx_init_uart_setup(char *str) +{ + if (str) { + while (*str != '\0') { + switch(*str) { + case '0': + init_uart |= IOP13XX_INIT_UART_0; + break; + case '1': + init_uart |= IOP13XX_INIT_UART_1; + break; + case ',': + case '=': + break; + default: + PRINTK("\"iop13xx_init_uart\" malformed" + " at character: \'%c\'", *str); + *(str + 1) = '\0'; + init_uart = IOP13XX_INIT_UART_DEFAULT; + } + str++; + } + } + return 1; +} + +static int __init iop13xx_init_i2c_setup(char *str) +{ + if (str) { + while (*str != '\0') { + switch(*str) { + case '0': + init_i2c |= IOP13XX_INIT_I2C_0; + break; + case '1': + init_i2c |= IOP13XX_INIT_I2C_1; + break; + case '2': + init_i2c |= IOP13XX_INIT_I2C_2; + break; + case ',': + case '=': + break; + default: + PRINTK("\"iop13xx_init_i2c\" malformed" + " at character: \'%c\'", *str); + *(str + 1) = '\0'; + init_i2c = IOP13XX_INIT_I2C_DEFAULT; + } + str++; + } + } + return 1; +} + +__setup("iop13xx_init_uart", iop13xx_init_uart_setup); +__setup("iop13xx_init_i2c", iop13xx_init_i2c_setup); diff --git a/trunk/arch/arm/mach-iop13xx/time.c b/trunk/arch/arm/mach-iop13xx/time.c new file mode 100644 index 000000000000..8b21365f653f --- /dev/null +++ b/trunk/arch/arm/mach-iop13xx/time.c @@ -0,0 +1,102 @@ +/* + * arch/arm/mach-iop13xx/time.c + * + * Timer code for IOP13xx (copied from IOP32x/IOP33x implementation) + * + * Author: Deepak Saxena + * + * Copyright 2002-2003 MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static unsigned long ticks_per_jiffy; +static unsigned long ticks_per_usec; +static unsigned long next_jiffy_time; + +static inline u32 read_tcr1(void) +{ + u32 val; + asm volatile("mrc p6, 0, %0, c3, c9, 0" : "=r" (val)); + return val; +} + +unsigned long iop13xx_gettimeoffset(void) +{ + unsigned long offset; + u32 cp_flags; + + cp_flags = iop13xx_cp6_save(); + offset = next_jiffy_time - read_tcr1(); + iop13xx_cp6_restore(cp_flags); + + return offset / ticks_per_usec; +} + +static irqreturn_t +iop13xx_timer_interrupt(int irq, void *dev_id) +{ + u32 cp_flags = iop13xx_cp6_save(); + + write_seqlock(&xtime_lock); + + asm volatile("mcr p6, 0, %0, c6, c9, 0" : : "r" (1)); + + while ((signed long)(next_jiffy_time - read_tcr1()) + >= ticks_per_jiffy) { + timer_tick(); + next_jiffy_time -= ticks_per_jiffy; + } + + write_sequnlock(&xtime_lock); + + iop13xx_cp6_restore(cp_flags); + + return IRQ_HANDLED; +} + +static struct irqaction iop13xx_timer_irq = { + .name = "IOP13XX Timer Tick", + .handler = iop13xx_timer_interrupt, + .flags = IRQF_DISABLED | IRQF_TIMER, +}; + +void __init iop13xx_init_time(unsigned long tick_rate) +{ + u32 timer_ctl; + u32 cp_flags; + + ticks_per_jiffy = (tick_rate + HZ/2) / HZ; + ticks_per_usec = tick_rate / 1000000; + next_jiffy_time = 0xffffffff; + + timer_ctl = IOP13XX_TMR_EN | IOP13XX_TMR_PRIVILEGED | + IOP13XX_TMR_RELOAD | IOP13XX_TMR_RATIO_1_1; + + /* + * We use timer 0 for our timer interrupt, and timer 1 as + * monotonic counter for tracking missed jiffies. + */ + cp_flags = iop13xx_cp6_save(); + asm volatile("mcr p6, 0, %0, c4, c9, 0" : : "r" (ticks_per_jiffy - 1)); + asm volatile("mcr p6, 0, %0, c0, c9, 0" : : "r" (timer_ctl)); + asm volatile("mcr p6, 0, %0, c5, c9, 0" : : "r" (0xffffffff)); + asm volatile("mcr p6, 0, %0, c1, c9, 0" : : "r" (timer_ctl)); + iop13xx_cp6_restore(cp_flags); + + setup_irq(IRQ_IOP13XX_TIMER0, &iop13xx_timer_irq); +} diff --git a/trunk/arch/arm/mach-iop32x/irq.c b/trunk/arch/arm/mach-iop32x/irq.c index 69d6302f40cf..3ec1cd5c4f99 100644 --- a/trunk/arch/arm/mach-iop32x/irq.c +++ b/trunk/arch/arm/mach-iop32x/irq.c @@ -70,7 +70,7 @@ void __init iop32x_init_irq(void) for (i = 0; i < NR_IRQS; i++) { set_irq_chip(i, &ext_chip); - set_irq_handler(i, do_level_IRQ); + set_irq_handler(i, handle_level_irq); set_irq_flags(i, IRQF_VALID | IRQF_PROBE); } } diff --git a/trunk/arch/arm/mach-iop33x/irq.c b/trunk/arch/arm/mach-iop33x/irq.c index 63304b3d0d76..00b37f32d72e 100644 --- a/trunk/arch/arm/mach-iop33x/irq.c +++ b/trunk/arch/arm/mach-iop33x/irq.c @@ -121,7 +121,7 @@ void __init iop33x_init_irq(void) for (i = 0; i < NR_IRQS; i++) { set_irq_chip(i, (i < 32) ? &iop33x_irqchip1 : &iop33x_irqchip2); - set_irq_handler(i, do_level_IRQ); + set_irq_handler(i, handle_level_irq); set_irq_flags(i, IRQF_VALID | IRQF_PROBE); } } diff --git a/trunk/arch/arm/mach-ixp2000/core.c b/trunk/arch/arm/mach-ixp2000/core.c index 22c98e9dad28..27b7480f4afe 100644 --- a/trunk/arch/arm/mach-ixp2000/core.c +++ b/trunk/arch/arm/mach-ixp2000/core.c @@ -308,7 +308,7 @@ EXPORT_SYMBOL(gpio_line_config); /************************************************************************* * IRQ handling IXP2000 *************************************************************************/ -static void ixp2000_GPIO_irq_handler(unsigned int irq, struct irqdesc *desc) +static void ixp2000_GPIO_irq_handler(unsigned int irq, struct irq_desc *desc) { int i; unsigned long status = *IXP2000_GPIO_INST; @@ -373,7 +373,7 @@ static void ixp2000_GPIO_irq_unmask(unsigned int irq) ixp2000_reg_write(IXP2000_GPIO_INSR, (1 << (irq - IRQ_IXP2000_GPIO0))); } -static struct irqchip ixp2000_GPIO_irq_chip = { +static struct irq_chip ixp2000_GPIO_irq_chip = { .ack = ixp2000_GPIO_irq_mask_ack, .mask = ixp2000_GPIO_irq_mask, .unmask = ixp2000_GPIO_irq_unmask, @@ -401,7 +401,7 @@ static void ixp2000_pci_irq_unmask(unsigned int irq) /* * Error interrupts. These are used extensively by the microengine drivers */ -static void ixp2000_err_irq_handler(unsigned int irq, struct irqdesc *desc) +static void ixp2000_err_irq_handler(unsigned int irq, struct irq_desc *desc) { int i; unsigned long status = *IXP2000_IRQ_ERR_STATUS; @@ -426,13 +426,13 @@ static void ixp2000_err_irq_unmask(unsigned int irq) (1 << (irq - IRQ_IXP2000_DRAM0_MIN_ERR))); } -static struct irqchip ixp2000_err_irq_chip = { +static struct irq_chip ixp2000_err_irq_chip = { .ack = ixp2000_err_irq_mask, .mask = ixp2000_err_irq_mask, .unmask = ixp2000_err_irq_unmask }; -static struct irqchip ixp2000_pci_irq_chip = { +static struct irq_chip ixp2000_pci_irq_chip = { .ack = ixp2000_pci_irq_mask, .mask = ixp2000_pci_irq_mask, .unmask = ixp2000_pci_irq_unmask @@ -448,7 +448,7 @@ static void ixp2000_irq_unmask(unsigned int irq) ixp2000_reg_write(IXP2000_IRQ_ENABLE_SET, (1 << irq)); } -static struct irqchip ixp2000_irq_chip = { +static struct irq_chip ixp2000_irq_chip = { .ack = ixp2000_irq_mask, .mask = ixp2000_irq_mask, .unmask = ixp2000_irq_unmask @@ -484,7 +484,7 @@ void __init ixp2000_init_irq(void) for (irq = IRQ_IXP2000_SOFT_INT; irq <= IRQ_IXP2000_THDB3; irq++) { if ((1 << irq) & IXP2000_VALID_IRQ_MASK) { set_irq_chip(irq, &ixp2000_irq_chip); - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); set_irq_flags(irq, IRQF_VALID); } else set_irq_flags(irq, 0); } @@ -493,7 +493,7 @@ void __init ixp2000_init_irq(void) if((1 << (irq - IRQ_IXP2000_DRAM0_MIN_ERR)) & IXP2000_VALID_ERR_IRQ_MASK) { set_irq_chip(irq, &ixp2000_err_irq_chip); - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); set_irq_flags(irq, IRQF_VALID); } else @@ -503,7 +503,7 @@ void __init ixp2000_init_irq(void) for (irq = IRQ_IXP2000_GPIO0; irq <= IRQ_IXP2000_GPIO7; irq++) { set_irq_chip(irq, &ixp2000_GPIO_irq_chip); - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); set_irq_flags(irq, IRQF_VALID); } set_irq_chained_handler(IRQ_IXP2000_GPIO, ixp2000_GPIO_irq_handler); @@ -516,7 +516,7 @@ void __init ixp2000_init_irq(void) ixp2000_reg_write(IXP2000_IRQ_ENABLE_SET, (1 << IRQ_IXP2000_PCI)); for (irq = IRQ_IXP2000_PCIA; irq <= IRQ_IXP2000_PCIB; irq++) { set_irq_chip(irq, &ixp2000_pci_irq_chip); - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); set_irq_flags(irq, IRQF_VALID); } } diff --git a/trunk/arch/arm/mach-ixp2000/ixdp2x00.c b/trunk/arch/arm/mach-ixp2000/ixdp2x00.c index aa2655092d2d..52b368b34346 100644 --- a/trunk/arch/arm/mach-ixp2000/ixdp2x00.c +++ b/trunk/arch/arm/mach-ixp2000/ixdp2x00.c @@ -106,7 +106,7 @@ static void ixdp2x00_irq_unmask(unsigned int irq) ixp2000_release_slowport(&old_cfg); } -static void ixdp2x00_irq_handler(unsigned int irq, struct irqdesc *desc) +static void ixdp2x00_irq_handler(unsigned int irq, struct irq_desc *desc) { volatile u32 ex_interrupt = 0; static struct slowport_cfg old_cfg; @@ -129,7 +129,7 @@ static void ixdp2x00_irq_handler(unsigned int irq, struct irqdesc *desc) for(i = 0; i < board_irq_count; i++) { if(ex_interrupt & (1 << i)) { - struct irqdesc *cpld_desc; + struct irq_desc *cpld_desc; int cpld_irq = IXP2000_BOARD_IRQ(0) + i; cpld_desc = irq_desc + cpld_irq; desc_handle_irq(cpld_irq, cpld_desc); @@ -139,7 +139,7 @@ static void ixdp2x00_irq_handler(unsigned int irq, struct irqdesc *desc) desc->chip->unmask(irq); } -static struct irqchip ixdp2x00_cpld_irq_chip = { +static struct irq_chip ixdp2x00_cpld_irq_chip = { .ack = ixdp2x00_irq_mask, .mask = ixdp2x00_irq_mask, .unmask = ixdp2x00_irq_unmask @@ -162,7 +162,7 @@ void ixdp2x00_init_irq(volatile unsigned long *stat_reg, volatile unsigned long for(irq = IXP2000_BOARD_IRQ(0); irq < IXP2000_BOARD_IRQ(board_irq_count); irq++) { set_irq_chip(irq, &ixdp2x00_cpld_irq_chip); - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); set_irq_flags(irq, IRQF_VALID); } diff --git a/trunk/arch/arm/mach-ixp2000/ixdp2x01.c b/trunk/arch/arm/mach-ixp2000/ixdp2x01.c index 9ccae9e63f70..3084a5fa751c 100644 --- a/trunk/arch/arm/mach-ixp2000/ixdp2x01.c +++ b/trunk/arch/arm/mach-ixp2000/ixdp2x01.c @@ -63,7 +63,7 @@ static void ixdp2x01_irq_unmask(unsigned int irq) static u32 valid_irq_mask; -static void ixdp2x01_irq_handler(unsigned int irq, struct irqdesc *desc) +static void ixdp2x01_irq_handler(unsigned int irq, struct irq_desc *desc) { u32 ex_interrupt; int i; @@ -79,7 +79,7 @@ static void ixdp2x01_irq_handler(unsigned int irq, struct irqdesc *desc) for (i = 0; i < IXP2000_BOARD_IRQS; i++) { if (ex_interrupt & (1 << i)) { - struct irqdesc *cpld_desc; + struct irq_desc *cpld_desc; int cpld_irq = IXP2000_BOARD_IRQ(0) + i; cpld_desc = irq_desc + cpld_irq; desc_handle_irq(cpld_irq, cpld_desc); @@ -89,7 +89,7 @@ static void ixdp2x01_irq_handler(unsigned int irq, struct irqdesc *desc) desc->chip->unmask(irq); } -static struct irqchip ixdp2x01_irq_chip = { +static struct irq_chip ixdp2x01_irq_chip = { .mask = ixdp2x01_irq_mask, .ack = ixdp2x01_irq_mask, .unmask = ixdp2x01_irq_unmask @@ -119,7 +119,7 @@ void __init ixdp2x01_init_irq(void) for (irq = NR_IXP2000_IRQS; irq < NR_IXDP2X01_IRQS; irq++) { if (irq & valid_irq_mask) { set_irq_chip(irq, &ixdp2x01_irq_chip); - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); set_irq_flags(irq, IRQF_VALID); } else { set_irq_flags(irq, 0); diff --git a/trunk/arch/arm/mach-ixp2000/pci.c b/trunk/arch/arm/mach-ixp2000/pci.c index d4bf1e1c0031..5a09a90c08fb 100644 --- a/trunk/arch/arm/mach-ixp2000/pci.c +++ b/trunk/arch/arm/mach-ixp2000/pci.c @@ -32,7 +32,7 @@ #include -static int pci_master_aborts = 0; +static volatile int pci_master_aborts = 0; static int clear_master_aborts(void); diff --git a/trunk/arch/arm/mach-ixp23xx/core.c b/trunk/arch/arm/mach-ixp23xx/core.c index a704a1820048..ce6ad635a00c 100644 --- a/trunk/arch/arm/mach-ixp23xx/core.c +++ b/trunk/arch/arm/mach-ixp23xx/core.c @@ -224,14 +224,14 @@ static void ixp23xx_irq_edge_unmask(unsigned int irq) *intr_reg |= (1 << (irq % 32)); } -static struct irqchip ixp23xx_irq_level_chip = { +static struct irq_chip ixp23xx_irq_level_chip = { .ack = ixp23xx_irq_mask, .mask = ixp23xx_irq_mask, .unmask = ixp23xx_irq_level_unmask, .set_type = ixp23xx_irq_set_type }; -static struct irqchip ixp23xx_irq_edge_chip = { +static struct irq_chip ixp23xx_irq_edge_chip = { .ack = ixp23xx_irq_ack, .mask = ixp23xx_irq_mask, .unmask = ixp23xx_irq_edge_unmask, @@ -251,11 +251,11 @@ static void ixp23xx_pci_irq_unmask(unsigned int irq) /* * TODO: Should this just be done at ASM level? */ -static void pci_handler(unsigned int irq, struct irqdesc *desc) +static void pci_handler(unsigned int irq, struct irq_desc *desc) { u32 pci_interrupt; unsigned int irqno; - struct irqdesc *int_desc; + struct irq_desc *int_desc; pci_interrupt = *IXP23XX_PCI_XSCALE_INT_STATUS; @@ -276,7 +276,7 @@ static void pci_handler(unsigned int irq, struct irqdesc *desc) desc->chip->unmask(irq); } -static struct irqchip ixp23xx_pci_irq_chip = { +static struct irq_chip ixp23xx_pci_irq_chip = { .ack = ixp23xx_pci_irq_mask, .mask = ixp23xx_pci_irq_mask, .unmask = ixp23xx_pci_irq_unmask @@ -287,11 +287,11 @@ static void ixp23xx_config_irq(unsigned int irq, enum ixp23xx_irq_type type) switch (type) { case IXP23XX_IRQ_LEVEL: set_irq_chip(irq, &ixp23xx_irq_level_chip); - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); break; case IXP23XX_IRQ_EDGE: set_irq_chip(irq, &ixp23xx_irq_edge_chip); - set_irq_handler(irq, do_edge_IRQ); + set_irq_handler(irq, handle_edge_irq); break; } set_irq_flags(irq, IRQF_VALID); @@ -322,7 +322,7 @@ void __init ixp23xx_init_irq(void) for (irq = IRQ_IXP23XX_INTA; irq <= IRQ_IXP23XX_INTB; irq++) { set_irq_chip(irq, &ixp23xx_pci_irq_chip); - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); set_irq_flags(irq, IRQF_VALID); } diff --git a/trunk/arch/arm/mach-ixp23xx/ixdp2351.c b/trunk/arch/arm/mach-ixp23xx/ixdp2351.c index b6ab0e8bb5e8..7a86a2516eaa 100644 --- a/trunk/arch/arm/mach-ixp23xx/ixdp2351.c +++ b/trunk/arch/arm/mach-ixp23xx/ixdp2351.c @@ -60,7 +60,7 @@ static void ixdp2351_inta_unmask(unsigned int irq) *IXDP2351_CPLD_INTA_MASK_CLR_REG = IXDP2351_INTA_IRQ_MASK(irq); } -static void ixdp2351_inta_handler(unsigned int irq, struct irqdesc *desc) +static void ixdp2351_inta_handler(unsigned int irq, struct irq_desc *desc) { u16 ex_interrupt = *IXDP2351_CPLD_INTA_STAT_REG & IXDP2351_INTA_IRQ_VALID; @@ -70,7 +70,7 @@ static void ixdp2351_inta_handler(unsigned int irq, struct irqdesc *desc) for (i = 0; i < IXDP2351_INTA_IRQ_NUM; i++) { if (ex_interrupt & (1 << i)) { - struct irqdesc *cpld_desc; + struct irq_desc *cpld_desc; int cpld_irq = IXP23XX_MACH_IRQ(IXDP2351_INTA_IRQ_BASE + i); cpld_desc = irq_desc + cpld_irq; @@ -81,7 +81,7 @@ static void ixdp2351_inta_handler(unsigned int irq, struct irqdesc *desc) desc->chip->unmask(irq); } -static struct irqchip ixdp2351_inta_chip = { +static struct irq_chip ixdp2351_inta_chip = { .ack = ixdp2351_inta_mask, .mask = ixdp2351_inta_mask, .unmask = ixdp2351_inta_unmask @@ -97,7 +97,7 @@ static void ixdp2351_intb_unmask(unsigned int irq) *IXDP2351_CPLD_INTB_MASK_CLR_REG = IXDP2351_INTB_IRQ_MASK(irq); } -static void ixdp2351_intb_handler(unsigned int irq, struct irqdesc *desc) +static void ixdp2351_intb_handler(unsigned int irq, struct irq_desc *desc) { u16 ex_interrupt = *IXDP2351_CPLD_INTB_STAT_REG & IXDP2351_INTB_IRQ_VALID; @@ -107,7 +107,7 @@ static void ixdp2351_intb_handler(unsigned int irq, struct irqdesc *desc) for (i = 0; i < IXDP2351_INTB_IRQ_NUM; i++) { if (ex_interrupt & (1 << i)) { - struct irqdesc *cpld_desc; + struct irq_desc *cpld_desc; int cpld_irq = IXP23XX_MACH_IRQ(IXDP2351_INTB_IRQ_BASE + i); cpld_desc = irq_desc + cpld_irq; @@ -118,7 +118,7 @@ static void ixdp2351_intb_handler(unsigned int irq, struct irqdesc *desc) desc->chip->unmask(irq); } -static struct irqchip ixdp2351_intb_chip = { +static struct irq_chip ixdp2351_intb_chip = { .ack = ixdp2351_intb_mask, .mask = ixdp2351_intb_mask, .unmask = ixdp2351_intb_unmask @@ -142,7 +142,7 @@ void ixdp2351_init_irq(void) irq++) { if (IXDP2351_INTA_IRQ_MASK(irq) & IXDP2351_INTA_IRQ_VALID) { set_irq_flags(irq, IRQF_VALID); - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); set_irq_chip(irq, &ixdp2351_inta_chip); } } @@ -153,7 +153,7 @@ void ixdp2351_init_irq(void) irq++) { if (IXDP2351_INTB_IRQ_MASK(irq) & IXDP2351_INTB_IRQ_VALID) { set_irq_flags(irq, IRQF_VALID); - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); set_irq_chip(irq, &ixdp2351_intb_chip); } } diff --git a/trunk/arch/arm/mach-ixp23xx/pci.c b/trunk/arch/arm/mach-ixp23xx/pci.c index 3b34fa35e36b..ac7d43d23c28 100644 --- a/trunk/arch/arm/mach-ixp23xx/pci.c +++ b/trunk/arch/arm/mach-ixp23xx/pci.c @@ -36,7 +36,7 @@ extern int (*external_fault) (unsigned long, struct pt_regs *); -static int pci_master_aborts = 0; +static volatile int pci_master_aborts = 0; #ifdef DEBUG #define DBG(x...) printk(x) diff --git a/trunk/arch/arm/mach-ixp4xx/common.c b/trunk/arch/arm/mach-ixp4xx/common.c index fbe288a8da65..2ec9a9e9a04d 100644 --- a/trunk/arch/arm/mach-ixp4xx/common.c +++ b/trunk/arch/arm/mach-ixp4xx/common.c @@ -28,6 +28,7 @@ #include #include +#include #include #include #include @@ -39,6 +40,8 @@ #include #include +static int __init ixp4xx_clocksource_init(void); + /************************************************************************* * IXP4xx chipset I/O mapping *************************************************************************/ @@ -195,7 +198,7 @@ static void ixp4xx_irq_unmask(unsigned int irq) *IXP4XX_ICMR |= (1 << irq); } -static struct irqchip ixp4xx_irq_chip = { +static struct irq_chip ixp4xx_irq_chip = { .name = "IXP4xx", .ack = ixp4xx_irq_ack, .mask = ixp4xx_irq_mask, @@ -224,7 +227,7 @@ void __init ixp4xx_init_irq(void) /* Default to all level triggered */ for(i = 0; i < NR_IRQS; i++) { set_irq_chip(i, &ixp4xx_irq_chip); - set_irq_handler(i, do_level_IRQ); + set_irq_handler(i, handle_level_irq); set_irq_flags(i, IRQF_VALID); } } @@ -280,12 +283,52 @@ static void __init ixp4xx_timer_init(void) /* Connect the interrupt handler and enable the interrupt */ setup_irq(IRQ_IXP4XX_TIMER1, &ixp4xx_timer_irq); + + ixp4xx_clocksource_init(); } struct sys_timer ixp4xx_timer = { .init = ixp4xx_timer_init, }; +static struct pxa2xx_udc_mach_info ixp4xx_udc_info; + +void __init ixp4xx_set_udc_info(struct pxa2xx_udc_mach_info *info) +{ + memcpy(&ixp4xx_udc_info, info, sizeof *info); +} + +static struct resource ixp4xx_udc_resources[] = { + [0] = { + .start = 0xc800b000, + .end = 0xc800bfff, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_IXP4XX_USB, + .end = IRQ_IXP4XX_USB, + .flags = IORESOURCE_IRQ, + }, +}; + +/* + * USB device controller. The IXP4xx uses the same controller as PXA2XX, + * so we just use the same device. + */ +static struct platform_device ixp4xx_udc_device = { + .name = "pxa2xx-udc", + .id = -1, + .num_resources = 2, + .resource = ixp4xx_udc_resources, + .dev = { + .platform_data = &ixp4xx_udc_info, + }, +}; + +static struct platform_device *ixp4xx_devices[] __initdata = { + &ixp4xx_udc_device, +}; + static struct resource ixp46x_i2c_resources[] = { [0] = { .start = 0xc8011000, @@ -321,6 +364,8 @@ void __init ixp4xx_sys_init(void) { ixp4xx_exp_bus_size = SZ_16M; + platform_add_devices(ixp4xx_devices, ARRAY_SIZE(ixp4xx_devices)); + if (cpu_is_ixp46x()) { int region; @@ -363,5 +408,3 @@ static int __init ixp4xx_clocksource_init(void) return 0; } - -device_initcall(ixp4xx_clocksource_init); diff --git a/trunk/arch/arm/mach-l7200/core.c b/trunk/arch/arm/mach-l7200/core.c index b7af5640ea7b..561a0fe7095d 100644 --- a/trunk/arch/arm/mach-l7200/core.c +++ b/trunk/arch/arm/mach-l7200/core.c @@ -55,7 +55,7 @@ static void l7200_unmask_irq(unsigned int irq) IRQ_ENABLE = 1 << irq; } -static struct irqchip l7200_irq_chip = { +static struct irq_chip l7200_irq_chip = { .ack = l7200_mask_irq, .mask = l7200_mask_irq, .unmask = l7200_unmask_irq @@ -71,7 +71,7 @@ static void __init l7200_init_irq(void) for (irq = 0; irq < NR_IRQS; irq++) { set_irq_chip(irq, &l7200_irq_chip); set_irq_flags(irq, IRQF_VALID); - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); } init_FIQ(); diff --git a/trunk/arch/arm/mach-lh7a40x/arch-kev7a400.c b/trunk/arch/arm/mach-lh7a40x/arch-kev7a400.c index 15fbcc911fe7..6d26661d99f6 100644 --- a/trunk/arch/arm/mach-lh7a40x/arch-kev7a400.c +++ b/trunk/arch/arm/mach-lh7a40x/arch-kev7a400.c @@ -71,7 +71,7 @@ static struct irq_chip kev7a400_cpld_chip = { }; -static void kev7a400_cpld_handler (unsigned int irq, struct irqdesc *desc) +static void kev7a400_cpld_handler (unsigned int irq, struct irq_desc *desc) { u32 mask = CPLD_LATCHED_INTS; irq = IRQ_KEV7A400_CPLD; @@ -88,7 +88,7 @@ void __init lh7a40x_init_board_irq (void) for (irq = IRQ_KEV7A400_CPLD; irq < IRQ_KEV7A400_CPLD + NR_IRQ_BOARD; ++irq) { set_irq_chip (irq, &kev7a400_cpld_chip); - set_irq_handler (irq, do_edge_IRQ); + set_irq_handler (irq, handle_edge_irq); set_irq_flags (irq, IRQF_VALID); } set_irq_chained_handler (IRQ_CPLD, kev7a400_cpld_handler); diff --git a/trunk/arch/arm/mach-lh7a40x/arch-lpd7a40x.c b/trunk/arch/arm/mach-lh7a40x/arch-lpd7a40x.c index 8441e0a156cb..fe64946f9e18 100644 --- a/trunk/arch/arm/mach-lh7a40x/arch-lpd7a40x.c +++ b/trunk/arch/arm/mach-lh7a40x/arch-lpd7a40x.c @@ -207,7 +207,7 @@ static struct irq_chip lpd7a40x_cpld_chip = { .unmask = lh7a40x_unmask_cpld_irq, }; -static void lpd7a40x_cpld_handler (unsigned int irq, struct irqdesc *desc) +static void lpd7a40x_cpld_handler (unsigned int irq, struct irq_desc *desc) { unsigned int mask = CPLD_INTERRUPTS; @@ -279,7 +279,7 @@ void __init lh7a40x_init_board_irq (void) for (irq = IRQ_BOARD_START; irq < IRQ_BOARD_START + NR_IRQ_BOARD; ++irq) { set_irq_chip (irq, &lpd7a40x_cpld_chip); - set_irq_handler (irq, do_level_IRQ); + set_irq_handler (irq, handle_level_irq); set_irq_flags (irq, IRQF_VALID); } diff --git a/trunk/arch/arm/mach-lh7a40x/irq-kev7a400.c b/trunk/arch/arm/mach-lh7a40x/irq-kev7a400.c index 646071334b8f..c7433b3c5812 100644 --- a/trunk/arch/arm/mach-lh7a40x/irq-kev7a400.c +++ b/trunk/arch/arm/mach-lh7a40x/irq-kev7a400.c @@ -51,7 +51,7 @@ irq_chip lh7a400_cpld_chip = { }; static void -lh7a400_cpld_handler (unsigned int irq, struct irqdesc *desc) +lh7a400_cpld_handler (unsigned int irq, struct irq_desc *desc) { u32 mask = CPLD_LATCHED_INTS; irq = IRQ_KEV_7A400_CPLD; @@ -71,7 +71,7 @@ lh7a400_init_board_irq (void) for (irq = IRQ_KEV7A400_CPLD; irq < IRQ_KEV7A400_CPLD + NR_IRQ_KEV7A400_CPLD; ++irq) { set_irq_chip (irq, &lh7a400_cpld_chip); - set_irq_handler (irq, do_edge_IRQ); + set_irq_handler (irq, handle_edge_irq); set_irq_flags (irq, IRQF_VALID); } set_irq_chained_handler (IRQ_CPLD, kev7a400_cpld_handler); diff --git a/trunk/arch/arm/mach-lh7a40x/irq-lh7a400.c b/trunk/arch/arm/mach-lh7a40x/irq-lh7a400.c index 091b2dc58d25..0b938e8b4d98 100644 --- a/trunk/arch/arm/mach-lh7a40x/irq-lh7a400.c +++ b/trunk/arch/arm/mach-lh7a40x/irq-lh7a400.c @@ -74,11 +74,11 @@ void __init lh7a400_init_irq (void) case IRQ_GPIO6INTR: case IRQ_GPIO7INTR: set_irq_chip (irq, &lh7a400_gpio_chip); - set_irq_handler (irq, do_level_IRQ); /* OK default */ + set_irq_handler (irq, handle_level_irq); /* OK default */ break; default: set_irq_chip (irq, &lh7a400_internal_chip); - set_irq_handler (irq, do_level_IRQ); + set_irq_handler (irq, handle_level_irq); } set_irq_flags (irq, IRQF_VALID); } diff --git a/trunk/arch/arm/mach-lh7a40x/irq-lh7a404.c b/trunk/arch/arm/mach-lh7a40x/irq-lh7a404.c index 7059b983724f..5760f8c53e89 100644 --- a/trunk/arch/arm/mach-lh7a40x/irq-lh7a404.c +++ b/trunk/arch/arm/mach-lh7a40x/irq-lh7a404.c @@ -161,13 +161,13 @@ void __init lh7a404_init_irq (void) set_irq_chip (irq, irq < 32 ? &lh7a404_gpio_vic1_chip : &lh7a404_gpio_vic2_chip); - set_irq_handler (irq, do_level_IRQ); /* OK default */ + set_irq_handler (irq, handle_level_irq); /* OK default */ break; default: set_irq_chip (irq, irq < 32 ? &lh7a404_vic1_chip : &lh7a404_vic2_chip); - set_irq_handler (irq, do_level_IRQ); + set_irq_handler (irq, handle_level_irq); } set_irq_flags (irq, IRQF_VALID); } diff --git a/trunk/arch/arm/mach-lh7a40x/irq-lpd7a40x.c b/trunk/arch/arm/mach-lh7a40x/irq-lpd7a40x.c index b20376804bbb..15b9577023c9 100644 --- a/trunk/arch/arm/mach-lh7a40x/irq-lpd7a40x.c +++ b/trunk/arch/arm/mach-lh7a40x/irq-lpd7a40x.c @@ -57,7 +57,7 @@ static struct irq_chip lh7a40x_cpld_chip = { .unmask = lh7a40x_unmask_cpld_irq, }; -static void lh7a40x_cpld_handler (unsigned int irq, struct irqdesc *desc) +static void lh7a40x_cpld_handler (unsigned int irq, struct irq_desc *desc) { unsigned int mask = CPLD_INTERRUPTS; @@ -118,7 +118,7 @@ void __init lh7a40x_init_board_irq (void) for (irq = IRQ_BOARD_START; irq < IRQ_BOARD_START + NR_IRQ_BOARD; ++irq) { set_irq_chip (irq, &lh7a40x_cpld_chip); - set_irq_handler (irq, do_edge_IRQ); + set_irq_handler (irq, handle_edge_irq); set_irq_flags (irq, IRQF_VALID); } diff --git a/trunk/arch/arm/mach-netx/generic.c b/trunk/arch/arm/mach-netx/generic.c index edbbbdc3b06b..b9ca8f98265d 100644 --- a/trunk/arch/arm/mach-netx/generic.c +++ b/trunk/arch/arm/mach-netx/generic.c @@ -69,7 +69,7 @@ static struct platform_device *devices[] __initdata = { #endif static void -netx_hif_demux_handler(unsigned int irq_unused, struct irqdesc *desc) +netx_hif_demux_handler(unsigned int irq_unused, struct irq_desc *desc) { unsigned int irq = NETX_IRQ_HIF_CHAINED(0); unsigned int stat; @@ -160,7 +160,7 @@ netx_hif_unmask_irq(unsigned int _irq) DEBUG_IRQ("%s: irq %d\n", __FUNCTION__, _irq); } -static struct irqchip netx_hif_chip = { +static struct irq_chip netx_hif_chip = { .ack = netx_hif_ack_irq, .mask = netx_hif_mask_irq, .unmask = netx_hif_unmask_irq, @@ -175,7 +175,7 @@ void __init netx_init_irq(void) for (irq = NETX_IRQ_HIF_CHAINED(0); irq <= NETX_IRQ_HIF_LAST; irq++) { set_irq_chip(irq, &netx_hif_chip); - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); set_irq_flags(irq, IRQF_VALID); } diff --git a/trunk/arch/arm/mach-omap1/board-h3.c b/trunk/arch/arm/mach-omap1/board-h3.c index f225a083dee1..9d2346fb68f4 100644 --- a/trunk/arch/arm/mach-omap1/board-h3.c +++ b/trunk/arch/arm/mach-omap1/board-h3.c @@ -323,7 +323,8 @@ static int h3_transceiver_mode(struct device *dev, int mode) cancel_delayed_work(&irda_config->gpio_expa); PREPARE_WORK(&irda_config->gpio_expa, set_trans_mode, &mode); - schedule_work(&irda_config->gpio_expa); +#error this is not permitted - mode is an argument variable + schedule_delayed_work(&irda_config->gpio_expa, 0); return 0; } diff --git a/trunk/arch/arm/mach-omap1/board-nokia770.c b/trunk/arch/arm/mach-omap1/board-nokia770.c index dbc555d209ff..cbe909bad79b 100644 --- a/trunk/arch/arm/mach-omap1/board-nokia770.c +++ b/trunk/arch/arm/mach-omap1/board-nokia770.c @@ -74,7 +74,7 @@ static struct omap_kp_platform_data nokia770_kp_data = { .rows = 8, .cols = 8, .keymap = nokia770_keymap, - .keymapsize = ARRAY_SIZE(nokia770_keymap) + .keymapsize = ARRAY_SIZE(nokia770_keymap), .delay = 4, }; @@ -191,7 +191,7 @@ static void nokia770_audio_pwr_up(void) printk("HP connected\n"); } -static void codec_delayed_power_down(void *arg) +static void codec_delayed_power_down(struct work_struct *work) { down(&audio_pwr_sem); if (audio_pwr_state == -1) @@ -200,7 +200,7 @@ static void codec_delayed_power_down(void *arg) up(&audio_pwr_sem); } -static DECLARE_WORK(codec_power_down_work, codec_delayed_power_down, NULL); +static DECLARE_DELAYED_WORK(codec_power_down_work, codec_delayed_power_down); static void nokia770_audio_pwr_down(void) { diff --git a/trunk/arch/arm/mach-omap1/devices.c b/trunk/arch/arm/mach-omap1/devices.c index a611c3b63954..6dcd10ab4496 100644 --- a/trunk/arch/arm/mach-omap1/devices.c +++ b/trunk/arch/arm/mach-omap1/devices.c @@ -55,7 +55,7 @@ static inline void omap_init_irda(void) {} /*-------------------------------------------------------------------------*/ -#if defined(CONFIG_OMAP_RTC) || defined(CONFIG_OMAP_RTC) +#if defined(CONFIG_RTC_DRV_OMAP) || defined(CONFIG_RTC_DRV_OMAP_MODULE) #define OMAP_RTC_BASE 0xfffb4800 diff --git a/trunk/arch/arm/mach-omap1/fpga.c b/trunk/arch/arm/mach-omap1/fpga.c index 8e40208b10bb..30e188109046 100644 --- a/trunk/arch/arm/mach-omap1/fpga.c +++ b/trunk/arch/arm/mach-omap1/fpga.c @@ -84,9 +84,9 @@ static void fpga_mask_ack_irq(unsigned int irq) fpga_ack_irq(irq); } -void innovator_fpga_IRQ_demux(unsigned int irq, struct irqdesc *desc) +void innovator_fpga_IRQ_demux(unsigned int irq, struct irq_desc *desc) { - struct irqdesc *d; + struct irq_desc *d; u32 stat; int fpga_irq; @@ -168,7 +168,7 @@ void omap1510_fpga_init_irq(void) set_irq_chip(i, &omap_fpga_irq); } - set_irq_handler(i, do_edge_IRQ); + set_irq_handler(i, handle_edge_irq); set_irq_flags(i, IRQF_VALID); } diff --git a/trunk/arch/arm/mach-omap1/irq.c b/trunk/arch/arm/mach-omap1/irq.c index 3ea140bb9eba..6383a12ad970 100644 --- a/trunk/arch/arm/mach-omap1/irq.c +++ b/trunk/arch/arm/mach-omap1/irq.c @@ -229,7 +229,7 @@ void __init omap_init_irq(void) omap_irq_set_cfg(j, 0, 0, irq_trigger); set_irq_chip(j, &omap_irq_chip); - set_irq_handler(j, do_level_IRQ); + set_irq_handler(j, handle_level_irq); set_irq_flags(j, IRQF_VALID); } } diff --git a/trunk/arch/arm/mach-omap1/leds-osk.c b/trunk/arch/arm/mach-omap1/leds-osk.c index 3b29e59b0e6f..0cbf1b0071f8 100644 --- a/trunk/arch/arm/mach-omap1/leds-osk.c +++ b/trunk/arch/arm/mach-omap1/leds-osk.c @@ -35,7 +35,7 @@ static u8 hw_led_state; static u8 tps_leds_change; -static void tps_work(void *unused) +static void tps_work(struct work_struct *unused) { for (;;) { u8 leds; @@ -61,7 +61,7 @@ static void tps_work(void *unused) } } -static DECLARE_WORK(work, tps_work, NULL); +static DECLARE_WORK(work, tps_work); #ifdef CONFIG_OMAP_OSK_MISTRAL diff --git a/trunk/arch/arm/mach-omap2/board-h4.c b/trunk/arch/arm/mach-omap2/board-h4.c index 26a95a642ad7..3b1ad1d981a3 100644 --- a/trunk/arch/arm/mach-omap2/board-h4.c +++ b/trunk/arch/arm/mach-omap2/board-h4.c @@ -206,7 +206,8 @@ static int h4_transceiver_mode(struct device *dev, int mode) cancel_delayed_work(&irda_config->gpio_expa); PREPARE_WORK(&irda_config->gpio_expa, set_trans_mode, &mode); - schedule_work(&irda_config->gpio_expa); +#error this is not permitted - mode is an argument variable + schedule_delayed_work(&irda_config->gpio_expa, 0); return 0; } diff --git a/trunk/arch/arm/mach-omap2/irq.c b/trunk/arch/arm/mach-omap2/irq.c index 11870093d7a1..a39d30680300 100644 --- a/trunk/arch/arm/mach-omap2/irq.c +++ b/trunk/arch/arm/mach-omap2/irq.c @@ -130,7 +130,7 @@ void __init omap_init_irq(void) for (i = 0; i < nr_irqs; i++) { set_irq_chip(i, &omap_irq_chip); - set_irq_handler(i, do_level_IRQ); + set_irq_handler(i, handle_level_irq); set_irq_flags(i, IRQF_VALID); } } diff --git a/trunk/arch/arm/mach-pnx4008/irq.c b/trunk/arch/arm/mach-pnx4008/irq.c index 3a4bcf3d91fa..968d0b027597 100644 --- a/trunk/arch/arm/mach-pnx4008/irq.c +++ b/trunk/arch/arm/mach-pnx4008/irq.c @@ -59,22 +59,22 @@ static int pnx4008_set_irq_type(unsigned int irq, unsigned int type) case IRQT_RISING: __raw_writel(__raw_readl(INTC_ATR(irq)) | INTC_BIT(irq), INTC_ATR(irq)); /*edge sensitive */ __raw_writel(__raw_readl(INTC_APR(irq)) | INTC_BIT(irq), INTC_APR(irq)); /*rising edge */ - set_irq_handler(irq, do_edge_IRQ); + set_irq_handler(irq, handle_edge_irq); break; case IRQT_FALLING: __raw_writel(__raw_readl(INTC_ATR(irq)) | INTC_BIT(irq), INTC_ATR(irq)); /*edge sensitive */ __raw_writel(__raw_readl(INTC_APR(irq)) & ~INTC_BIT(irq), INTC_APR(irq)); /*falling edge */ - set_irq_handler(irq, do_edge_IRQ); + set_irq_handler(irq, handle_edge_irq); break; case IRQT_LOW: __raw_writel(__raw_readl(INTC_ATR(irq)) & ~INTC_BIT(irq), INTC_ATR(irq)); /*level sensitive */ __raw_writel(__raw_readl(INTC_APR(irq)) & ~INTC_BIT(irq), INTC_APR(irq)); /*low level */ - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); break; case IRQT_HIGH: __raw_writel(__raw_readl(INTC_ATR(irq)) & ~INTC_BIT(irq), INTC_ATR(irq)); /*level sensitive */ __raw_writel(__raw_readl(INTC_APR(irq)) | INTC_BIT(irq), INTC_APR(irq)); /* high level */ - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); break; /* IRQT_BOTHEDGE is not supported */ @@ -85,7 +85,7 @@ static int pnx4008_set_irq_type(unsigned int irq, unsigned int type) return 0; } -static struct irqchip pnx4008_irq_chip = { +static struct irq_chip pnx4008_irq_chip = { .ack = pnx4008_mask_ack_irq, .mask = pnx4008_mask_irq, .unmask = pnx4008_unmask_irq, diff --git a/trunk/arch/arm/mach-pxa/Kconfig b/trunk/arch/arm/mach-pxa/Kconfig index 03d07cae26c8..9e3d0bdcba07 100644 --- a/trunk/arch/arm/mach-pxa/Kconfig +++ b/trunk/arch/arm/mach-pxa/Kconfig @@ -13,12 +13,10 @@ config ARCH_LUBBOCK config MACH_LOGICPD_PXA270 bool "LogicPD PXA270 Card Engine Development Platform" select PXA27x - select IWMMXT config MACH_MAINSTONE bool "Intel HCDDBBVA0 Development Platform" select PXA27x - select IWMMXT config ARCH_PXA_IDP bool "Accelent Xscale IDP" @@ -53,7 +51,6 @@ config PXA_SHARPSL_25x config PXA_SHARPSL_27x bool "Sharp PXA270 models (SL-Cxx00)" select PXA27x - select IWMMXT endchoice @@ -129,11 +126,6 @@ config PXA27x help Select code specific to PXA27x variants -config IWMMXT - bool - help - Enable support for iWMMXt - config PXA_SHARP_C7xx bool select PXA_SSP diff --git a/trunk/arch/arm/mach-pxa/akita-ioexp.c b/trunk/arch/arm/mach-pxa/akita-ioexp.c index 1b398742ab56..12d2fe0ceff6 100644 --- a/trunk/arch/arm/mach-pxa/akita-ioexp.c +++ b/trunk/arch/arm/mach-pxa/akita-ioexp.c @@ -36,11 +36,11 @@ I2C_CLIENT_INSMOD; static int max7310_write(struct i2c_client *client, int address, int data); static struct i2c_client max7310_template; -static void akita_ioexp_work(void *private_); +static void akita_ioexp_work(struct work_struct *private_); static struct device *akita_ioexp_device; static unsigned char ioexp_output_value = AKITA_IOEXP_IO_OUT; -DECLARE_WORK(akita_ioexp, akita_ioexp_work, NULL); +DECLARE_WORK(akita_ioexp, akita_ioexp_work); /* @@ -158,7 +158,7 @@ void akita_reset_ioexp(struct device *dev, unsigned char bit) EXPORT_SYMBOL(akita_set_ioexp); EXPORT_SYMBOL(akita_reset_ioexp); -static void akita_ioexp_work(void *private_) +static void akita_ioexp_work(struct work_struct *private_) { if (akita_ioexp_device) max7310_set_ouputs(akita_ioexp_device, ioexp_output_value); diff --git a/trunk/arch/arm/mach-pxa/generic.c b/trunk/arch/arm/mach-pxa/generic.c index 45fb2c3bcf82..6ae605857ca9 100644 --- a/trunk/arch/arm/mach-pxa/generic.c +++ b/trunk/arch/arm/mach-pxa/generic.c @@ -25,6 +25,10 @@ #include #include +#include +#include +#include + #include #include #include @@ -40,6 +44,62 @@ #include "generic.h" +/* + * This is the PXA2xx sched_clock implementation. This has a resolution + * of at least 308ns and a maximum value that depends on the value of + * CLOCK_TICK_RATE. + * + * The return value is guaranteed to be monotonic in that range as + * long as there is always less than 582 seconds between successive + * calls to this function. + */ +unsigned long long sched_clock(void) +{ + unsigned long long v = cnt32_to_63(OSCR); + /* Note: top bit ov v needs cleared unless multiplier is even. */ + +#if CLOCK_TICK_RATE == 3686400 + /* 1E9 / 3686400 => 78125 / 288, max value = 32025597s (370 days). */ + /* The <<1 is used to get rid of tick.hi top bit */ + v *= 78125<<1; + do_div(v, 288<<1); +#elif CLOCK_TICK_RATE == 3250000 + /* 1E9 / 3250000 => 4000 / 13, max value = 709490156s (8211 days) */ + v *= 4000; + do_div(v, 13); +#elif CLOCK_TICK_RATE == 3249600 + /* 1E9 / 3249600 => 625000 / 2031, max value = 4541295s (52 days) */ + v *= 625000; + do_div(v, 2031); +#else +#warning "consider fixing sched_clock for your value of CLOCK_TICK_RATE" + /* + * 96-bit math to perform tick * NSEC_PER_SEC / CLOCK_TICK_RATE for + * any value of CLOCK_TICK_RATE. Max value is in the 80 thousand + * years range which is nice, but with higher computation cost. + */ + { + union { + unsigned long long val; + struct { unsigned long lo, hi; }; + } x; + unsigned long long y; + + x.val = v; + x.hi &= 0x7fffffff; + y = (unsigned long long)x.lo * NSEC_PER_SEC; + x.lo = y; + y = (y >> 32) + (unsigned long long)x.hi * NSEC_PER_SEC; + x.hi = do_div(y, CLOCK_TICK_RATE); + do_div(x.val, CLOCK_TICK_RATE); + x.hi += y; + v = x.val; + } +#endif + + return v; +} + /* * Handy function to set GPIO alternate functions */ diff --git a/trunk/arch/arm/mach-pxa/irq.c b/trunk/arch/arm/mach-pxa/irq.c index ab1a16025d51..f815678a9d63 100644 --- a/trunk/arch/arm/mach-pxa/irq.c +++ b/trunk/arch/arm/mach-pxa/irq.c @@ -143,7 +143,7 @@ static struct irq_chip pxa_low_gpio_chip = { * Demux handler for GPIO>=2 edge detect interrupts */ -static void pxa_gpio_demux_handler(unsigned int irq, struct irqdesc *desc) +static void pxa_gpio_demux_handler(unsigned int irq, struct irq_desc *desc) { unsigned int mask; int loop; @@ -286,27 +286,27 @@ void __init pxa_init_irq(void) for (irq = PXA_IRQ(PXA_IRQ_SKIP); irq <= PXA_IRQ(31); irq++) { set_irq_chip(irq, &pxa_internal_chip_low); - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); set_irq_flags(irq, IRQF_VALID); } #if PXA_INTERNAL_IRQS > 32 for (irq = PXA_IRQ(32); irq < PXA_IRQ(PXA_INTERNAL_IRQS); irq++) { set_irq_chip(irq, &pxa_internal_chip_high); - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); set_irq_flags(irq, IRQF_VALID); } #endif for (irq = IRQ_GPIO0; irq <= IRQ_GPIO1; irq++) { set_irq_chip(irq, &pxa_low_gpio_chip); - set_irq_handler(irq, do_edge_IRQ); + set_irq_handler(irq, handle_edge_irq); set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); } for (irq = IRQ_GPIO(2); irq <= IRQ_GPIO(PXA_LAST_GPIO); irq++) { set_irq_chip(irq, &pxa_muxed_gpio_chip); - set_irq_handler(irq, do_edge_IRQ); + set_irq_handler(irq, handle_edge_irq); set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); } diff --git a/trunk/arch/arm/mach-pxa/lpd270.c b/trunk/arch/arm/mach-pxa/lpd270.c index 5749f6b72e12..8e27a64fa9f4 100644 --- a/trunk/arch/arm/mach-pxa/lpd270.c +++ b/trunk/arch/arm/mach-pxa/lpd270.c @@ -75,7 +75,7 @@ static struct irq_chip lpd270_irq_chip = { .unmask = lpd270_unmask_irq, }; -static void lpd270_irq_handler(unsigned int irq, struct irqdesc *desc) +static void lpd270_irq_handler(unsigned int irq, struct irq_desc *desc) { unsigned long pending; @@ -105,7 +105,7 @@ static void __init lpd270_init_irq(void) /* setup extra LogicPD PXA270 irqs */ for (irq = LPD270_IRQ(2); irq <= LPD270_IRQ(4); irq++) { set_irq_chip(irq, &lpd270_irq_chip); - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); } set_irq_chained_handler(IRQ_GPIO(0), lpd270_irq_handler); diff --git a/trunk/arch/arm/mach-pxa/lubbock.c b/trunk/arch/arm/mach-pxa/lubbock.c index 142c33c3dff5..055de7f4f00a 100644 --- a/trunk/arch/arm/mach-pxa/lubbock.c +++ b/trunk/arch/arm/mach-pxa/lubbock.c @@ -85,7 +85,7 @@ static struct irq_chip lubbock_irq_chip = { .unmask = lubbock_unmask_irq, }; -static void lubbock_irq_handler(unsigned int irq, struct irqdesc *desc) +static void lubbock_irq_handler(unsigned int irq, struct irq_desc *desc) { unsigned long pending = LUB_IRQ_SET_CLR & lubbock_irq_enabled; do { @@ -108,7 +108,7 @@ static void __init lubbock_init_irq(void) /* setup extra lubbock irqs */ for (irq = LUBBOCK_IRQ(0); irq <= LUBBOCK_LAST_IRQ; irq++) { set_irq_chip(irq, &lubbock_irq_chip); - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); } diff --git a/trunk/arch/arm/mach-pxa/mainstone.c b/trunk/arch/arm/mach-pxa/mainstone.c index 49c34d94a9fe..56d94d88d5ca 100644 --- a/trunk/arch/arm/mach-pxa/mainstone.c +++ b/trunk/arch/arm/mach-pxa/mainstone.c @@ -71,7 +71,7 @@ static struct irq_chip mainstone_irq_chip = { .unmask = mainstone_unmask_irq, }; -static void mainstone_irq_handler(unsigned int irq, struct irqdesc *desc) +static void mainstone_irq_handler(unsigned int irq, struct irq_desc *desc) { unsigned long pending = MST_INTSETCLR & mainstone_irq_enabled; do { @@ -94,7 +94,7 @@ static void __init mainstone_init_irq(void) /* setup extra Mainstone irqs */ for(irq = MAINSTONE_IRQ(0); irq <= MAINSTONE_IRQ(15); irq++) { set_irq_chip(irq, &mainstone_irq_chip); - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); if (irq == MAINSTONE_IRQ(10) || irq == MAINSTONE_IRQ(14)) set_irq_flags(irq, IRQF_VALID | IRQF_PROBE | IRQF_NOAUTOEN); else diff --git a/trunk/arch/arm/mach-pxa/pm.c b/trunk/arch/arm/mach-pxa/pm.c index 2112c414f0e2..b4d8276d6050 100644 --- a/trunk/arch/arm/mach-pxa/pm.c +++ b/trunk/arch/arm/mach-pxa/pm.c @@ -83,7 +83,8 @@ int pxa_pm_enter(suspend_state_t state) #ifdef CONFIG_IWMMXT /* force any iWMMXt context to ram **/ - iwmmxt_task_disable(NULL); + if (elf_hwcap & HWCAP_IWMMXT) + iwmmxt_task_disable(NULL); #endif /* preserve current time */ diff --git a/trunk/arch/arm/mach-pxa/time.c b/trunk/arch/arm/mach-pxa/time.c index 3ac268fa419b..b91466861029 100644 --- a/trunk/arch/arm/mach-pxa/time.c +++ b/trunk/arch/arm/mach-pxa/time.c @@ -124,6 +124,7 @@ static struct irqaction pxa_timer_irq = { static void __init pxa_timer_init(void) { struct timespec tv; + unsigned long flags; set_rtc = pxa_set_rtc; @@ -132,12 +133,12 @@ static void __init pxa_timer_init(void) do_settimeofday(&tv); OIER = 0; /* disable any timer interrupts */ - OSCR = LATCH*2; /* push OSCR out of the way */ - OSMR0 = LATCH; /* set initial match */ OSSR = 0xf; /* clear status on all timers */ setup_irq(IRQ_OST0, &pxa_timer_irq); + local_irq_save(flags); OIER = OIER_E0; /* enable match on timer 0 to cause interrupts */ - OSCR = 0; /* initialize free-running timer */ + OSMR0 = OSCR + LATCH; /* set initial match */ + local_irq_restore(flags); } #ifdef CONFIG_NO_IDLE_HZ diff --git a/trunk/arch/arm/mach-rpc/irq.c b/trunk/arch/arm/mach-rpc/irq.c index 56b2716f8cf5..7a029621db43 100644 --- a/trunk/arch/arm/mach-rpc/irq.c +++ b/trunk/arch/arm/mach-rpc/irq.c @@ -34,7 +34,7 @@ static void iomd_unmask_irq_a(unsigned int irq) iomd_writeb(val | mask, IOMD_IRQMASKA); } -static struct irqchip iomd_a_chip = { +static struct irq_chip iomd_a_chip = { .ack = iomd_ack_irq_a, .mask = iomd_mask_irq_a, .unmask = iomd_unmask_irq_a, @@ -58,7 +58,7 @@ static void iomd_unmask_irq_b(unsigned int irq) iomd_writeb(val | mask, IOMD_IRQMASKB); } -static struct irqchip iomd_b_chip = { +static struct irq_chip iomd_b_chip = { .ack = iomd_mask_irq_b, .mask = iomd_mask_irq_b, .unmask = iomd_unmask_irq_b, @@ -82,7 +82,7 @@ static void iomd_unmask_irq_dma(unsigned int irq) iomd_writeb(val | mask, IOMD_DMAMASK); } -static struct irqchip iomd_dma_chip = { +static struct irq_chip iomd_dma_chip = { .ack = iomd_mask_irq_dma, .mask = iomd_mask_irq_dma, .unmask = iomd_unmask_irq_dma, @@ -106,7 +106,7 @@ static void iomd_unmask_irq_fiq(unsigned int irq) iomd_writeb(val | mask, IOMD_FIQMASK); } -static struct irqchip iomd_fiq_chip = { +static struct irq_chip iomd_fiq_chip = { .ack = iomd_mask_irq_fiq, .mask = iomd_mask_irq_fiq, .unmask = iomd_unmask_irq_fiq, @@ -134,19 +134,19 @@ void __init rpc_init_irq(void) switch (irq) { case 0 ... 7: set_irq_chip(irq, &iomd_a_chip); - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); set_irq_flags(irq, flags); break; case 8 ... 15: set_irq_chip(irq, &iomd_b_chip); - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); set_irq_flags(irq, flags); break; case 16 ... 21: set_irq_chip(irq, &iomd_dma_chip); - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); set_irq_flags(irq, flags); break; diff --git a/trunk/arch/arm/mach-s3c2410/Kconfig b/trunk/arch/arm/mach-s3c2410/Kconfig index 9aa26b99045d..9f46bf330bc8 100644 --- a/trunk/arch/arm/mach-s3c2410/Kconfig +++ b/trunk/arch/arm/mach-s3c2410/Kconfig @@ -41,9 +41,16 @@ config BAST_PC104_IRQ Say Y here to enable the PC104 IRQ routing on the Simtec BAST (EB2410ITX) +config PM_H1940 + bool + depends on PM + help + Internal node for H1940 and related PM + config ARCH_H1940 bool "IPAQ H1940" select CPU_S3C2410 + select PM_H1940 help Say Y here if you are using the HP IPAQ H1940 @@ -115,6 +122,7 @@ config MACH_VR1000 config MACH_RX3715 bool "HP iPAQ rx3715" select CPU_S3C2440 + select PM_H1940 help Say Y here if you are using the HP iPAQ rx3715. diff --git a/trunk/arch/arm/mach-s3c2410/Makefile b/trunk/arch/arm/mach-s3c2410/Makefile index d66013365b6b..27663e28cc88 100644 --- a/trunk/arch/arm/mach-s3c2410/Makefile +++ b/trunk/arch/arm/mach-s3c2410/Makefile @@ -31,6 +31,7 @@ obj-$(CONFIG_CPU_S3C2410_DMA) += s3c2410-dma.o obj-$(CONFIG_PM) += pm.o sleep.o obj-$(CONFIG_PM_SIMTEC) += pm-simtec.o +obj-$(CONFIG_PM_H1940) += pm-h1940.o # S3C2412 support obj-$(CONFIG_CPU_S3C2412) += s3c2412.o diff --git a/trunk/arch/arm/mach-s3c2410/bast-irq.c b/trunk/arch/arm/mach-s3c2410/bast-irq.c index 23d5beea5568..379efe70778c 100644 --- a/trunk/arch/arm/mach-s3c2410/bast-irq.c +++ b/trunk/arch/arm/mach-s3c2410/bast-irq.c @@ -88,7 +88,7 @@ bast_pc104_mask(unsigned int irqno) static void bast_pc104_maskack(unsigned int irqno) { - struct irqdesc *desc = irq_desc + IRQ_ISA; + struct irq_desc *desc = irq_desc + IRQ_ISA; bast_pc104_mask(irqno); desc->chip->ack(IRQ_ISA); @@ -104,7 +104,7 @@ bast_pc104_unmask(unsigned int irqno) __raw_writeb(temp, BAST_VA_PC104_IRQMASK); } -static struct irqchip bast_pc104_chip = { +static struct irq_chip bast_pc104_chip = { .mask = bast_pc104_mask, .unmask = bast_pc104_unmask, .ack = bast_pc104_maskack @@ -112,7 +112,7 @@ static struct irqchip bast_pc104_chip = { static void bast_irq_pc104_demux(unsigned int irq, - struct irqdesc *desc) + struct irq_desc *desc) { unsigned int stat; unsigned int irqno; @@ -157,7 +157,7 @@ static __init int bast_irq_init(void) unsigned int irqno = bast_pc104_irqs[i]; set_irq_chip(irqno, &bast_pc104_chip); - set_irq_handler(irqno, do_level_IRQ); + set_irq_handler(irqno, handle_level_irq); set_irq_flags(irqno, IRQF_VALID); } } diff --git a/trunk/arch/arm/mach-s3c2410/dma.c b/trunk/arch/arm/mach-s3c2410/dma.c index 3d211dc2f2f9..01abb0ace234 100644 --- a/trunk/arch/arm/mach-s3c2410/dma.c +++ b/trunk/arch/arm/mach-s3c2410/dma.c @@ -40,7 +40,7 @@ /* io map for dma */ static void __iomem *dma_base; -static kmem_cache_t *dma_kmem; +static struct kmem_cache *dma_kmem; struct s3c24xx_dma_selection dma_sel; @@ -1271,7 +1271,7 @@ struct sysdev_class dma_sysclass = { /* kmem cache implementation */ -static void s3c2410_dma_cache_ctor(void *p, kmem_cache_t *c, unsigned long f) +static void s3c2410_dma_cache_ctor(void *p, struct kmem_cache *c, unsigned long f) { memset(p, 0, sizeof(struct s3c2410_dma_buf)); } diff --git a/trunk/arch/arm/mach-s3c2410/irq.c b/trunk/arch/arm/mach-s3c2410/irq.c index 683b3491ba3c..3c0ed7871c55 100644 --- a/trunk/arch/arm/mach-s3c2410/irq.c +++ b/trunk/arch/arm/mach-s3c2410/irq.c @@ -180,7 +180,7 @@ s3c_irq_unmask(unsigned int irqno) __raw_writel(mask, S3C2410_INTMSK); } -struct irqchip s3c_irq_level_chip = { +struct irq_chip s3c_irq_level_chip = { .name = "s3c-level", .ack = s3c_irq_maskack, .mask = s3c_irq_mask, @@ -188,7 +188,7 @@ struct irqchip s3c_irq_level_chip = { .set_wake = s3c_irq_wake }; -static struct irqchip s3c_irq_chip = { +static struct irq_chip s3c_irq_chip = { .name = "s3c", .ack = s3c_irq_ack, .mask = s3c_irq_mask, @@ -206,18 +206,6 @@ s3c_irqext_mask(unsigned int irqno) mask = __raw_readl(S3C24XX_EINTMASK); mask |= ( 1UL << irqno); __raw_writel(mask, S3C24XX_EINTMASK); - - if (irqno <= (IRQ_EINT7 - EXTINT_OFF)) { - /* check to see if all need masking */ - - if ((mask & (0xf << 4)) == (0xf << 4)) { - /* all masked, mask the parent */ - s3c_irq_mask(IRQ_EINT4t7); - } - } else { - /* todo: the same check as above for the rest of the irq regs...*/ - - } } static void @@ -229,7 +217,6 @@ s3c_irqext_ack(unsigned int irqno) bit = 1UL << (irqno - EXTINT_OFF); - mask = __raw_readl(S3C24XX_EINTMASK); __raw_writel(bit, S3C24XX_EINTPEND); @@ -258,8 +245,6 @@ s3c_irqext_unmask(unsigned int irqno) mask = __raw_readl(S3C24XX_EINTMASK); mask &= ~( 1UL << irqno); __raw_writel(mask, S3C24XX_EINTMASK); - - s3c_irq_unmask((irqno <= (IRQ_EINT7 - EXTINT_OFF)) ? IRQ_EINT4t7 : IRQ_EINT8t23); } int @@ -344,7 +329,7 @@ s3c_irqext_type(unsigned int irq, unsigned int type) return 0; } -static struct irqchip s3c_irqext_chip = { +static struct irq_chip s3c_irqext_chip = { .name = "s3c-ext", .mask = s3c_irqext_mask, .unmask = s3c_irqext_unmask, @@ -353,7 +338,7 @@ static struct irqchip s3c_irqext_chip = { .set_wake = s3c_irqext_wake }; -static struct irqchip s3c_irq_eint0t4 = { +static struct irq_chip s3c_irq_eint0t4 = { .name = "s3c-ext0", .ack = s3c_irq_ack, .mask = s3c_irq_mask, @@ -390,7 +375,7 @@ s3c_irq_uart0_ack(unsigned int irqno) s3c_irqsub_maskack(irqno, INTMSK_UART0, 7); } -static struct irqchip s3c_irq_uart0 = { +static struct irq_chip s3c_irq_uart0 = { .name = "s3c-uart0", .mask = s3c_irq_uart0_mask, .unmask = s3c_irq_uart0_unmask, @@ -417,7 +402,7 @@ s3c_irq_uart1_ack(unsigned int irqno) s3c_irqsub_maskack(irqno, INTMSK_UART1, 7 << 3); } -static struct irqchip s3c_irq_uart1 = { +static struct irq_chip s3c_irq_uart1 = { .name = "s3c-uart1", .mask = s3c_irq_uart1_mask, .unmask = s3c_irq_uart1_unmask, @@ -444,7 +429,7 @@ s3c_irq_uart2_ack(unsigned int irqno) s3c_irqsub_maskack(irqno, INTMSK_UART2, 7 << 6); } -static struct irqchip s3c_irq_uart2 = { +static struct irq_chip s3c_irq_uart2 = { .name = "s3c-uart2", .mask = s3c_irq_uart2_mask, .unmask = s3c_irq_uart2_unmask, @@ -471,7 +456,7 @@ s3c_irq_adc_ack(unsigned int irqno) s3c_irqsub_ack(irqno, INTMSK_ADCPARENT, 3 << 9); } -static struct irqchip s3c_irq_adc = { +static struct irq_chip s3c_irq_adc = { .name = "s3c-adc", .mask = s3c_irq_adc_mask, .unmask = s3c_irq_adc_unmask, @@ -480,11 +465,11 @@ static struct irqchip s3c_irq_adc = { /* irq demux for adc */ static void s3c_irq_demux_adc(unsigned int irq, - struct irqdesc *desc) + struct irq_desc *desc) { unsigned int subsrc, submsk; unsigned int offset = 9; - struct irqdesc *mydesc; + struct irq_desc *mydesc; /* read the current pending interrupts, and the mask * for what it is available */ @@ -512,7 +497,7 @@ static void s3c_irq_demux_uart(unsigned int start) { unsigned int subsrc, submsk; unsigned int offset = start - IRQ_S3CUART_RX0; - struct irqdesc *desc; + struct irq_desc *desc; /* read the current pending interrupts, and the mask * for what it is available */ @@ -549,7 +534,7 @@ static void s3c_irq_demux_uart(unsigned int start) static void s3c_irq_demux_uart0(unsigned int irq, - struct irqdesc *desc) + struct irq_desc *desc) { irq = irq; s3c_irq_demux_uart(IRQ_S3CUART_RX0); @@ -557,7 +542,7 @@ s3c_irq_demux_uart0(unsigned int irq, static void s3c_irq_demux_uart1(unsigned int irq, - struct irqdesc *desc) + struct irq_desc *desc) { irq = irq; s3c_irq_demux_uart(IRQ_S3CUART_RX1); @@ -565,7 +550,7 @@ s3c_irq_demux_uart1(unsigned int irq, static void s3c_irq_demux_uart2(unsigned int irq, - struct irqdesc *desc) + struct irq_desc *desc) { irq = irq; s3c_irq_demux_uart(IRQ_S3CUART_RX2); @@ -573,7 +558,7 @@ s3c_irq_demux_uart2(unsigned int irq, static void s3c_irq_demux_extint8(unsigned int irq, - struct irqdesc *desc) + struct irq_desc *desc) { unsigned long eintpnd = __raw_readl(S3C24XX_EINTPEND); unsigned long eintmsk = __raw_readl(S3C24XX_EINTMASK); @@ -595,7 +580,7 @@ s3c_irq_demux_extint8(unsigned int irq, static void s3c_irq_demux_extint4t7(unsigned int irq, - struct irqdesc *desc) + struct irq_desc *desc) { unsigned long eintpnd = __raw_readl(S3C24XX_EINTPEND); unsigned long eintmsk = __raw_readl(S3C24XX_EINTMASK); @@ -738,7 +723,7 @@ void __init s3c24xx_init_irq(void) case IRQ_UART2: case IRQ_ADCPARENT: set_irq_chip(irqno, &s3c_irq_level_chip); - set_irq_handler(irqno, do_level_IRQ); + set_irq_handler(irqno, handle_level_irq); break; case IRQ_RESERVED6: @@ -749,7 +734,7 @@ void __init s3c24xx_init_irq(void) default: //irqdbf("registering irq %d (s3c irq)\n", irqno); set_irq_chip(irqno, &s3c_irq_chip); - set_irq_handler(irqno, do_edge_IRQ); + set_irq_handler(irqno, handle_edge_irq); set_irq_flags(irqno, IRQF_VALID); } } @@ -769,14 +754,14 @@ void __init s3c24xx_init_irq(void) for (irqno = IRQ_EINT0; irqno <= IRQ_EINT3; irqno++) { irqdbf("registering irq %d (ext int)\n", irqno); set_irq_chip(irqno, &s3c_irq_eint0t4); - set_irq_handler(irqno, do_edge_IRQ); + set_irq_handler(irqno, handle_edge_irq); set_irq_flags(irqno, IRQF_VALID); } for (irqno = IRQ_EINT4; irqno <= IRQ_EINT23; irqno++) { irqdbf("registering irq %d (extended s3c irq)\n", irqno); set_irq_chip(irqno, &s3c_irqext_chip); - set_irq_handler(irqno, do_edge_IRQ); + set_irq_handler(irqno, handle_edge_irq); set_irq_flags(irqno, IRQF_VALID); } @@ -787,28 +772,28 @@ void __init s3c24xx_init_irq(void) for (irqno = IRQ_S3CUART_RX0; irqno <= IRQ_S3CUART_ERR0; irqno++) { irqdbf("registering irq %d (s3c uart0 irq)\n", irqno); set_irq_chip(irqno, &s3c_irq_uart0); - set_irq_handler(irqno, do_level_IRQ); + set_irq_handler(irqno, handle_level_irq); set_irq_flags(irqno, IRQF_VALID); } for (irqno = IRQ_S3CUART_RX1; irqno <= IRQ_S3CUART_ERR1; irqno++) { irqdbf("registering irq %d (s3c uart1 irq)\n", irqno); set_irq_chip(irqno, &s3c_irq_uart1); - set_irq_handler(irqno, do_level_IRQ); + set_irq_handler(irqno, handle_level_irq); set_irq_flags(irqno, IRQF_VALID); } for (irqno = IRQ_S3CUART_RX2; irqno <= IRQ_S3CUART_ERR2; irqno++) { irqdbf("registering irq %d (s3c uart2 irq)\n", irqno); set_irq_chip(irqno, &s3c_irq_uart2); - set_irq_handler(irqno, do_level_IRQ); + set_irq_handler(irqno, handle_level_irq); set_irq_flags(irqno, IRQF_VALID); } for (irqno = IRQ_TC; irqno <= IRQ_ADC; irqno++) { irqdbf("registering irq %d (s3c adc irq)\n", irqno); set_irq_chip(irqno, &s3c_irq_adc); - set_irq_handler(irqno, do_edge_IRQ); + set_irq_handler(irqno, handle_edge_irq); set_irq_flags(irqno, IRQF_VALID); } diff --git a/trunk/arch/arm/mach-s3c2410/irq.h b/trunk/arch/arm/mach-s3c2410/irq.h index 842a9f42c97b..3686a0082245 100644 --- a/trunk/arch/arm/mach-s3c2410/irq.h +++ b/trunk/arch/arm/mach-s3c2410/irq.h @@ -17,7 +17,7 @@ #define EXTINT_OFF (IRQ_EINT4 - 4) -extern struct irqchip s3c_irq_level_chip; +extern struct irq_chip s3c_irq_level_chip; static inline void s3c_irqsub_mask(unsigned int irqno, unsigned int parentbit, diff --git a/trunk/arch/arm/mach-s3c2410/mach-h1940.c b/trunk/arch/arm/mach-s3c2410/mach-h1940.c index 8c895c077d22..f5b98099a5d9 100644 --- a/trunk/arch/arm/mach-s3c2410/mach-h1940.c +++ b/trunk/arch/arm/mach-s3c2410/mach-h1940.c @@ -33,6 +33,7 @@ #include #include +#include #include #include @@ -41,6 +42,7 @@ #include "clock.h" #include "devs.h" #include "cpu.h" +#include "pm.h" static struct map_desc h1940_iodesc[] __initdata = { [0] = { @@ -164,12 +166,16 @@ static void __init h1940_map_io(void) s3c24xx_init_clocks(0); s3c24xx_init_uarts(h1940_uartcfgs, ARRAY_SIZE(h1940_uartcfgs)); s3c24xx_set_board(&h1940_board); + + /* setup PM */ + + memcpy(phys_to_virt(H1940_SUSPEND_RESUMEAT), h1940_pm_return, 1024); + s3c2410_pm_init(); } static void __init h1940_init_irq(void) { s3c24xx_init_irq(); - } static void __init h1940_init(void) diff --git a/trunk/arch/arm/mach-s3c2410/mach-osiris.c b/trunk/arch/arm/mach-s3c2410/mach-osiris.c index e193ba69e652..a4ab144e7292 100644 --- a/trunk/arch/arm/mach-s3c2410/mach-osiris.c +++ b/trunk/arch/arm/mach-s3c2410/mach-osiris.c @@ -114,6 +114,15 @@ static struct s3c2410_uartcfg osiris_uartcfgs[] __initdata = { .clocks = osiris_serial_clocks, .clocks_size = ARRAY_SIZE(osiris_serial_clocks), }, + [2] = { + .hwport = 2, + .flags = 0, + .ucon = UCON, + .ulcon = ULCON, + .ufcon = UFCON, + .clocks = osiris_serial_clocks, + .clocks_size = ARRAY_SIZE(osiris_serial_clocks), + } }; /* NAND Flash on Osiris board */ diff --git a/trunk/arch/arm/mach-s3c2410/mach-rx3715.c b/trunk/arch/arm/mach-s3c2410/mach-rx3715.c index 23d7c052013c..ecbcdf79d739 100644 --- a/trunk/arch/arm/mach-s3c2410/mach-rx3715.c +++ b/trunk/arch/arm/mach-s3c2410/mach-rx3715.c @@ -42,6 +42,7 @@ #include #include +#include #include #include @@ -224,7 +225,9 @@ static void __init rx3715_init_irq(void) static void __init rx3715_init_machine(void) { + memcpy(phys_to_virt(H1940_SUSPEND_RESUMEAT), h1940_pm_return, 1024); s3c2410_pm_init(); + s3c24xx_fb_set_platdata(&rx3715_lcdcfg); } diff --git a/trunk/arch/arm/mach-s3c2410/mach-vr1000.c b/trunk/arch/arm/mach-s3c2410/mach-vr1000.c index a0d7692cdb2b..e2eda3937ab0 100644 --- a/trunk/arch/arm/mach-s3c2410/mach-vr1000.c +++ b/trunk/arch/arm/mach-s3c2410/mach-vr1000.c @@ -41,6 +41,7 @@ #include #include +#include #include "clock.h" #include "devs.h" @@ -313,6 +314,50 @@ static struct platform_device vr1000_dm9k1 = { } }; +/* LEDS */ + +static struct s3c24xx_led_platdata vr1000_led1_pdata = { + .name = "led1", + .gpio = S3C2410_GPB0, + .def_trigger = "", +}; + +static struct s3c24xx_led_platdata vr1000_led2_pdata = { + .name = "led2", + .gpio = S3C2410_GPB1, + .def_trigger = "", +}; + +static struct s3c24xx_led_platdata vr1000_led3_pdata = { + .name = "led3", + .gpio = S3C2410_GPB2, + .def_trigger = "", +}; + +static struct platform_device vr1000_led1 = { + .name = "s3c24xx_led", + .id = 1, + .dev = { + .platform_data = &vr1000_led1_pdata, + }, +}; + +static struct platform_device vr1000_led2 = { + .name = "s3c24xx_led", + .id = 2, + .dev = { + .platform_data = &vr1000_led2_pdata, + }, +}; + +static struct platform_device vr1000_led3 = { + .name = "s3c24xx_led", + .id = 1, + .dev = { + .platform_data = &vr1000_led3_pdata, + }, +}; + /* devices for this board */ static struct platform_device *vr1000_devices[] __initdata = { @@ -325,7 +370,10 @@ static struct platform_device *vr1000_devices[] __initdata = { &serial_device, &vr1000_nor, &vr1000_dm9k0, - &vr1000_dm9k1 + &vr1000_dm9k1, + &vr1000_led1, + &vr1000_led2, + &vr1000_led3, }; static struct clk *vr1000_clocks[] = { diff --git a/trunk/arch/arm/mach-s3c2410/pm-h1940.S b/trunk/arch/arm/mach-s3c2410/pm-h1940.S new file mode 100644 index 000000000000..7d66de7ff7db --- /dev/null +++ b/trunk/arch/arm/mach-s3c2410/pm-h1940.S @@ -0,0 +1,33 @@ +/* linux/arch/arm/mach-s3c2410/pm-h1940.S + * + * Copyright (c) 2006 Ben Dooks + * + * H1940 Suspend to RAM + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include +#include +#include + +#include + + .text + .global h1940_pm_return + +h1940_pm_return: + mov r0, #S3C2410_PA_GPIO + ldr pc, [ r0, #S3C2410_GSTATUS3 - S3C24XX_VA_GPIO ] diff --git a/trunk/arch/arm/mach-s3c2410/s3c2410-pm.c b/trunk/arch/arm/mach-s3c2410/s3c2410-pm.c index e51d76669512..77c6814c0f05 100644 --- a/trunk/arch/arm/mach-s3c2410/s3c2410-pm.c +++ b/trunk/arch/arm/mach-s3c2410/s3c2410-pm.c @@ -32,6 +32,7 @@ #include #include +#include #include "cpu.h" #include "pm.h" @@ -52,6 +53,35 @@ static void s3c2410_pm_prepare(void) DBG("GSTATUS3 0x%08x\n", __raw_readl(S3C2410_GSTATUS3)); DBG("GSTATUS4 0x%08x\n", __raw_readl(S3C2410_GSTATUS4)); + if (machine_is_h1940()) { + void *base = phys_to_virt(H1940_SUSPEND_CHECK); + unsigned long ptr; + unsigned long calc = 0; + + /* generate check for the bootloader to check on resume */ + + for (ptr = 0; ptr < 0x40000; ptr += 0x400) + calc += __raw_readl(base+ptr); + + __raw_writel(calc, phys_to_virt(H1940_SUSPEND_CHECKSUM)); + } + + /* the RX3715 uses similar code and the same H1940 and the + * same offsets for resume and checksum pointers */ + + if (machine_is_rx3715()) { + void *base = phys_to_virt(H1940_SUSPEND_CHECK); + unsigned long ptr; + unsigned long calc = 0; + + /* generate check for the bootloader to check on resume */ + + for (ptr = 0; ptr < 0x40000; ptr += 0x4) + calc += __raw_readl(base+ptr); + + __raw_writel(calc, phys_to_virt(H1940_SUSPEND_CHECKSUM)); + } + if ( machine_is_aml_m5900() ) s3c2410_gpio_setpin(S3C2410_GPF2, 1); diff --git a/trunk/arch/arm/mach-s3c2410/s3c2412-irq.c b/trunk/arch/arm/mach-s3c2410/s3c2412-irq.c index 7f741547658f..ffcc30b23a80 100644 --- a/trunk/arch/arm/mach-s3c2410/s3c2412-irq.c +++ b/trunk/arch/arm/mach-s3c2410/s3c2412-irq.c @@ -98,7 +98,7 @@ s3c2412_irq_unmask(unsigned int irqno) __raw_writel(mask & ~bitval, S3C2410_INTMSK); } -static struct irqchip s3c2412_irq_eint0t4 = { +static struct irq_chip s3c2412_irq_eint0t4 = { .ack = s3c2412_irq_ack, .mask = s3c2412_irq_mask, .unmask = s3c2412_irq_unmask, @@ -112,7 +112,7 @@ static int s3c2412_irq_add(struct sys_device *sysdev) for (irqno = IRQ_EINT0; irqno <= IRQ_EINT3; irqno++) { set_irq_chip(irqno, &s3c2412_irq_eint0t4); - set_irq_handler(irqno, do_edge_IRQ); + set_irq_handler(irqno, handle_edge_irq); set_irq_flags(irqno, IRQF_VALID); } diff --git a/trunk/arch/arm/mach-s3c2410/s3c2440-irq.c b/trunk/arch/arm/mach-s3c2410/s3c2440-irq.c index 39db0752d53b..1ba19b27ab05 100644 --- a/trunk/arch/arm/mach-s3c2410/s3c2440-irq.c +++ b/trunk/arch/arm/mach-s3c2410/s3c2440-irq.c @@ -42,10 +42,10 @@ /* WDT/AC97 */ static void s3c_irq_demux_wdtac97(unsigned int irq, - struct irqdesc *desc) + struct irq_desc *desc) { unsigned int subsrc, submsk; - struct irqdesc *mydesc; + struct irq_desc *mydesc; /* read the current pending interrupts, and the mask * for what it is available */ @@ -90,7 +90,7 @@ s3c_irq_wdtac97_ack(unsigned int irqno) s3c_irqsub_maskack(irqno, INTMSK_WDT, 3<<13); } -static struct irqchip s3c_irq_wdtac97 = { +static struct irq_chip s3c_irq_wdtac97 = { .mask = s3c_irq_wdtac97_mask, .unmask = s3c_irq_wdtac97_unmask, .ack = s3c_irq_wdtac97_ack, @@ -105,12 +105,12 @@ static int s3c2440_irq_add(struct sys_device *sysdev) /* add new chained handler for wdt, ac7 */ set_irq_chip(IRQ_WDT, &s3c_irq_level_chip); - set_irq_handler(IRQ_WDT, do_level_IRQ); + set_irq_handler(IRQ_WDT, handle_level_irq); set_irq_chained_handler(IRQ_WDT, s3c_irq_demux_wdtac97); for (irqno = IRQ_S3C2440_WDT; irqno <= IRQ_S3C2440_AC97; irqno++) { set_irq_chip(irqno, &s3c_irq_wdtac97); - set_irq_handler(irqno, do_level_IRQ); + set_irq_handler(irqno, handle_level_irq); set_irq_flags(irqno, IRQF_VALID); } diff --git a/trunk/arch/arm/mach-s3c2410/s3c244x-irq.c b/trunk/arch/arm/mach-s3c2410/s3c244x-irq.c index 146f2109dd90..ede94636a72a 100644 --- a/trunk/arch/arm/mach-s3c2410/s3c244x-irq.c +++ b/trunk/arch/arm/mach-s3c2410/s3c244x-irq.c @@ -42,10 +42,10 @@ /* camera irq */ static void s3c_irq_demux_cam(unsigned int irq, - struct irqdesc *desc) + struct irq_desc *desc) { unsigned int subsrc, submsk; - struct irqdesc *mydesc; + struct irq_desc *mydesc; /* read the current pending interrupts, and the mask * for what it is available */ @@ -89,7 +89,7 @@ s3c_irq_cam_ack(unsigned int irqno) s3c_irqsub_maskack(irqno, INTMSK_CAM, 3<<11); } -static struct irqchip s3c_irq_cam = { +static struct irq_chip s3c_irq_cam = { .mask = s3c_irq_cam_mask, .unmask = s3c_irq_cam_unmask, .ack = s3c_irq_cam_ack, @@ -100,18 +100,18 @@ static int s3c244x_irq_add(struct sys_device *sysdev) unsigned int irqno; set_irq_chip(IRQ_NFCON, &s3c_irq_level_chip); - set_irq_handler(IRQ_NFCON, do_level_IRQ); + set_irq_handler(IRQ_NFCON, handle_level_irq); set_irq_flags(IRQ_NFCON, IRQF_VALID); /* add chained handler for camera */ set_irq_chip(IRQ_CAM, &s3c_irq_level_chip); - set_irq_handler(IRQ_CAM, do_level_IRQ); + set_irq_handler(IRQ_CAM, handle_level_irq); set_irq_chained_handler(IRQ_CAM, s3c_irq_demux_cam); for (irqno = IRQ_S3C2440_CAM_C; irqno <= IRQ_S3C2440_CAM_P; irqno++) { set_irq_chip(irqno, &s3c_irq_cam); - set_irq_handler(irqno, do_level_IRQ); + set_irq_handler(irqno, handle_level_irq); set_irq_flags(irqno, IRQF_VALID); } diff --git a/trunk/arch/arm/mach-sa1100/generic.c b/trunk/arch/arm/mach-sa1100/generic.c index 4575f316e141..e510295c2580 100644 --- a/trunk/arch/arm/mach-sa1100/generic.c +++ b/trunk/arch/arm/mach-sa1100/generic.c @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -118,15 +119,21 @@ EXPORT_SYMBOL(cpufreq_get); /* * This is the SA11x0 sched_clock implementation. This has - * a resolution of 271ns, and a maximum value of 1165s. + * a resolution of 271ns, and a maximum value of 32025597s (370 days). + * + * The return value is guaranteed to be monotonic in that range as + * long as there is always less than 582 seconds between successive + * calls to this function. + * * ( * 1E9 / 3686400 => * 78125 / 288) */ unsigned long long sched_clock(void) { - unsigned long long v; + unsigned long long v = cnt32_to_63(OSCR); - v = (unsigned long long)OSCR * 78125; - do_div(v, 288); + /* the <<1 gets rid of the cnt_32_to_63 top bit saving on a bic insn */ + v *= 78125<<1; + do_div(v, 288<<1); return v; } diff --git a/trunk/arch/arm/mach-sa1100/h3600.c b/trunk/arch/arm/mach-sa1100/h3600.c index fa6dc71bd6ad..b034ad69a324 100644 --- a/trunk/arch/arm/mach-sa1100/h3600.c +++ b/trunk/arch/arm/mach-sa1100/h3600.c @@ -702,7 +702,7 @@ static u32 gpio_irq_mask[] = { GPIO2_SD_CON_SLT, }; -static void h3800_IRQ_demux(unsigned int irq, struct irqdesc *desc) +static void h3800_IRQ_demux(unsigned int irq, struct irq_desc *desc) { int i; @@ -719,14 +719,14 @@ static void h3800_IRQ_demux(unsigned int irq, struct irqdesc *desc) if (0) printk("%s KPIO 0x%08X\n", __FUNCTION__, irq); for (j = 0; j < H3800_KPIO_IRQ_COUNT; j++) if (irq & kpio_irq_mask[j]) - do_edge_IRQ(H3800_KPIO_IRQ_COUNT + j, irq_desc + H3800_KPIO_IRQ_COUNT + j); + handle_edge_irq(H3800_KPIO_IRQ_COUNT + j, irq_desc + H3800_KPIO_IRQ_COUNT + j); /* GPIO2 */ irq = H3800_ASIC2_GPIINTFLAG; if (0) printk("%s GPIO 0x%08X\n", __FUNCTION__, irq); for (j = 0; j < H3800_GPIO_IRQ_COUNT; j++) if (irq & gpio_irq_mask[j]) - do_edge_IRQ(H3800_GPIO_IRQ_COUNT + j, irq_desc + H3800_GPIO_IRQ_COUNT + j); + handle_edge_irq(H3800_GPIO_IRQ_COUNT + j, irq_desc + H3800_GPIO_IRQ_COUNT + j); } if (i >= MAX_ASIC_ISR_LOOPS) diff --git a/trunk/arch/arm/mach-sa1100/irq.c b/trunk/arch/arm/mach-sa1100/irq.c index f4c6322ca33e..5642aeca079e 100644 --- a/trunk/arch/arm/mach-sa1100/irq.c +++ b/trunk/arch/arm/mach-sa1100/irq.c @@ -110,7 +110,7 @@ static struct irq_chip sa1100_low_gpio_chip = { * and call the handler. */ static void -sa1100_high_gpio_handler(unsigned int irq, struct irqdesc *desc) +sa1100_high_gpio_handler(unsigned int irq, struct irq_desc *desc) { unsigned int mask; @@ -327,19 +327,19 @@ void __init sa1100_init_irq(void) for (irq = 0; irq <= 10; irq++) { set_irq_chip(irq, &sa1100_low_gpio_chip); - set_irq_handler(irq, do_edge_IRQ); + set_irq_handler(irq, handle_edge_irq); set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); } for (irq = 12; irq <= 31; irq++) { set_irq_chip(irq, &sa1100_normal_chip); - set_irq_handler(irq, do_level_IRQ); + set_irq_handler(irq, handle_level_irq); set_irq_flags(irq, IRQF_VALID); } for (irq = 32; irq <= 48; irq++) { set_irq_chip(irq, &sa1100_high_gpio_chip); - set_irq_handler(irq, do_edge_IRQ); + set_irq_handler(irq, handle_edge_irq); set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); } diff --git a/trunk/arch/arm/mach-sa1100/neponset.c b/trunk/arch/arm/mach-sa1100/neponset.c index 354d5e91da59..075d4d1d63be 100644 --- a/trunk/arch/arm/mach-sa1100/neponset.c +++ b/trunk/arch/arm/mach-sa1100/neponset.c @@ -29,12 +29,12 @@ * is rather unfortunate. */ static void -neponset_irq_handler(unsigned int irq, struct irqdesc *desc) +neponset_irq_handler(unsigned int irq, struct irq_desc *desc) { unsigned int irr; while (1) { - struct irqdesc *d; + struct irq_desc *d; /* * Acknowledge the parent IRQ. @@ -168,9 +168,9 @@ static int neponset_probe(struct platform_device *dev) * Setup other Neponset IRQs. SA1111 will be done by the * generic SA1111 code. */ - set_irq_handler(IRQ_NEPONSET_SMC9196, do_simple_IRQ); + set_irq_handler(IRQ_NEPONSET_SMC9196, handle_simple_irq); set_irq_flags(IRQ_NEPONSET_SMC9196, IRQF_VALID | IRQF_PROBE); - set_irq_handler(IRQ_NEPONSET_USAR, do_simple_IRQ); + set_irq_handler(IRQ_NEPONSET_USAR, handle_simple_irq); set_irq_flags(IRQ_NEPONSET_USAR, IRQF_VALID | IRQF_PROBE); /* diff --git a/trunk/arch/arm/mach-sa1100/time.c b/trunk/arch/arm/mach-sa1100/time.c index 4284bd6f7a1f..29c89f9eb2ce 100644 --- a/trunk/arch/arm/mach-sa1100/time.c +++ b/trunk/arch/arm/mach-sa1100/time.c @@ -118,6 +118,7 @@ static struct irqaction sa1100_timer_irq = { static void __init sa1100_timer_init(void) { struct timespec tv; + unsigned long flags; set_rtc = sa1100_set_rtc; @@ -126,12 +127,12 @@ static void __init sa1100_timer_init(void) do_settimeofday(&tv); OIER = 0; /* disable any timer interrupts */ - OSCR = LATCH*2; /* push OSCR out of the way */ - OSMR0 = LATCH; /* set initial match */ OSSR = 0xf; /* clear status on all timers */ setup_irq(IRQ_OST0, &sa1100_timer_irq); + local_irq_save(flags); OIER = OIER_E0; /* enable match on timer 0 to cause interrupts */ - OSCR = 0; /* initialize free-running timer */ + OSMR0 = OSCR + LATCH; /* set initial match */ + local_irq_restore(flags); } #ifdef CONFIG_NO_IDLE_HZ diff --git a/trunk/arch/arm/mach-shark/irq.c b/trunk/arch/arm/mach-shark/irq.c index 297ecf130650..00a6c1466867 100644 --- a/trunk/arch/arm/mach-shark/irq.c +++ b/trunk/arch/arm/mach-shark/irq.c @@ -82,7 +82,7 @@ void __init shark_init_irq(void) for (irq = 0; irq < NR_IRQS; irq++) { set_irq_chip(irq, &fb_chip); - set_irq_handler(irq, do_edge_IRQ); + set_irq_handler(irq, handle_edge_irq); set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); } diff --git a/trunk/arch/arm/mach-versatile/core.c b/trunk/arch/arm/mach-versatile/core.c index 3b8576111c16..57196947559f 100644 --- a/trunk/arch/arm/mach-versatile/core.c +++ b/trunk/arch/arm/mach-versatile/core.c @@ -27,6 +27,7 @@ #include #include +#include #include #include #include @@ -77,7 +78,7 @@ static struct irq_chip sic_chip = { }; static void -sic_handle_irq(unsigned int irq, struct irqdesc *desc) +sic_handle_irq(unsigned int irq, struct irq_desc *desc) { unsigned long status = readl(VA_SIC_BASE + SIC_IRQ_STATUS); @@ -123,7 +124,7 @@ void __init versatile_init_irq(void) for (i = IRQ_SIC_START; i <= IRQ_SIC_END; i++) { if ((PIC_MASK & (1 << (i - IRQ_SIC_START))) == 0) { set_irq_chip(i, &sic_chip); - set_irq_handler(i, do_level_IRQ); + set_irq_handler(i, handle_level_irq); set_irq_flags(i, IRQF_VALID | IRQF_PROBE); } } @@ -228,14 +229,19 @@ void __init versatile_map_io(void) /* * This is the Versatile sched_clock implementation. This has - * a resolution of 41.7ns, and a maximum value of about 179s. + * a resolution of 41.7ns, and a maximum value of about 35583 days. + * + * The return value is guaranteed to be monotonic in that range as + * long as there is always less than 89 seconds between successive + * calls to this function. */ unsigned long long sched_clock(void) { - unsigned long long v; + unsigned long long v = cnt32_to_63(readl(VERSATILE_REFCOUNTER)); - v = (unsigned long long)readl(VERSATILE_REFCOUNTER) * 125; - do_div(v, 3); + /* the <<1 gets rid of the cnt_32_to_63 top bit saving on a bic insn */ + v *= 125<<1; + do_div(v, 3<<1); return v; } diff --git a/trunk/arch/arm/mach-versatile/versatile_pb.c b/trunk/arch/arm/mach-versatile/versatile_pb.c index 503725b166fc..be439bb9d450 100644 --- a/trunk/arch/arm/mach-versatile/versatile_pb.c +++ b/trunk/arch/arm/mach-versatile/versatile_pb.c @@ -81,22 +81,18 @@ static struct amba_device *amba_devs[] __initdata = { &mmc1_device, }; -static int __init versatile_pb_init(void) +static void __init versatile_pb_init(void) { int i; - if (machine_is_versatile_pb()) { - for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { - struct amba_device *d = amba_devs[i]; - amba_device_register(d, &iomem_resource); - } - } + versatile_init(); - return 0; + for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { + struct amba_device *d = amba_devs[i]; + amba_device_register(d, &iomem_resource); + } } -arch_initcall(versatile_pb_init); - MACHINE_START(VERSATILE_PB, "ARM-Versatile PB") /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */ .phys_io = 0x101f1000, @@ -105,5 +101,5 @@ MACHINE_START(VERSATILE_PB, "ARM-Versatile PB") .map_io = versatile_map_io, .init_irq = versatile_init_irq, .timer = &versatile_timer, - .init_machine = versatile_init, + .init_machine = versatile_pb_init, MACHINE_END diff --git a/trunk/arch/arm/mm/Kconfig b/trunk/arch/arm/mm/Kconfig index b09a19f87d68..aade2f72c920 100644 --- a/trunk/arch/arm/mm/Kconfig +++ b/trunk/arch/arm/mm/Kconfig @@ -333,7 +333,7 @@ config CPU_XSCALE # XScale Core Version 3 config CPU_XSC3 bool - depends on ARCH_IXP23XX + depends on ARCH_IXP23XX || ARCH_IOP13XX default y select CPU_32v5 select CPU_ABRT_EV5T @@ -580,7 +580,7 @@ config CPU_CACHE_ROUND_ROBIN config CPU_BPREDICT_DISABLE bool "Disable branch prediction" - depends on CPU_ARM1020 || CPU_V6 + depends on CPU_ARM1020 || CPU_V6 || CPU_XSC3 help Say Y here to disable branch prediction. If unsure, say N. diff --git a/trunk/arch/arm/mm/fault.c b/trunk/arch/arm/mm/fault.c index 5e658a874498..9fd6d2eafb40 100644 --- a/trunk/arch/arm/mm/fault.c +++ b/trunk/arch/arm/mm/fault.c @@ -230,7 +230,7 @@ do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs) * If we're in an interrupt or have no user * context, we must not take the fault.. */ - if (in_interrupt() || !mm) + if (in_atomic() || !mm) goto no_context; /* diff --git a/trunk/arch/arm/mm/mm.h b/trunk/arch/arm/mm/mm.h index bb2bc9ab6bd3..a44e30970635 100644 --- a/trunk/arch/arm/mm/mm.h +++ b/trunk/arch/arm/mm/mm.h @@ -1,4 +1,7 @@ /* the upper-most page table pointer */ + +#ifdef CONFIG_MMU + extern pmd_t *top_pmd; #define TOP_PTE(x) pte_offset_kernel(top_pmd, x) @@ -13,6 +16,8 @@ static inline pmd_t *pmd_off_k(unsigned long virt) return pmd_off(pgd_offset_k(virt), virt); } +#endif + struct map_desc; struct meminfo; struct pglist_data; diff --git a/trunk/arch/arm/mm/mmu.c b/trunk/arch/arm/mm/mmu.c index f866bf6b97d4..b7f194af20b4 100644 --- a/trunk/arch/arm/mm/mmu.c +++ b/trunk/arch/arm/mm/mmu.c @@ -265,7 +265,7 @@ static void __init build_mem_type_table(void) if (arch_is_coherent()) { if (cpu_is_xsc3()) { mem_types[MT_MEMORY].prot_sect |= PMD_SECT_S; - mem_types[MT_MEMORY].prot_pte |= L_PTE_COHERENT; + mem_types[MT_MEMORY].prot_pte |= L_PTE_SHARED; } } @@ -619,6 +619,13 @@ void __init reserve_node_zero(pg_data_t *pgdat) if (machine_is_p720t()) res_size = 0x00014000; + /* H1940 and RX3715 need to reserve this for suspend */ + + if (machine_is_h1940() || machine_is_rx3715()) { + reserve_bootmem_node(pgdat, 0x30003000, 0x1000); + reserve_bootmem_node(pgdat, 0x30081000, 0x1000); + } + #ifdef CONFIG_SA1111 /* * Because of the SA1111 DMA bug, we want to preserve our diff --git a/trunk/arch/arm/mm/nommu.c b/trunk/arch/arm/mm/nommu.c index d0e66424a597..05818fc0c705 100644 --- a/trunk/arch/arm/mm/nommu.c +++ b/trunk/arch/arm/mm/nommu.c @@ -6,10 +6,12 @@ #include #include #include +#include #include #include #include +#include #include "mm.h" @@ -76,7 +78,7 @@ void __iomem *__ioremap(unsigned long phys_addr, size_t size, } EXPORT_SYMBOL(__ioremap); -void __iounmap(void __iomem *addr) +void __iounmap(volatile void __iomem *addr) { } EXPORT_SYMBOL(__iounmap); diff --git a/trunk/arch/arm/mm/proc-arm1020.S b/trunk/arch/arm/mm/proc-arm1020.S index 1d8316f3cecf..289b8e6f504d 100644 --- a/trunk/arch/arm/mm/proc-arm1020.S +++ b/trunk/arch/arm/mm/proc-arm1020.S @@ -29,9 +29,9 @@ #include #include #include +#include #include #include -#include #include #include "proc-macros.S" diff --git a/trunk/arch/arm/mm/proc-arm1020e.S b/trunk/arch/arm/mm/proc-arm1020e.S index 89b1d6d3d7c0..bed9db6ba582 100644 --- a/trunk/arch/arm/mm/proc-arm1020e.S +++ b/trunk/arch/arm/mm/proc-arm1020e.S @@ -29,9 +29,9 @@ #include #include #include +#include #include #include -#include #include #include "proc-macros.S" diff --git a/trunk/arch/arm/mm/proc-arm1022.S b/trunk/arch/arm/mm/proc-arm1022.S index a089528e6bce..d2a7c1b9cab9 100644 --- a/trunk/arch/arm/mm/proc-arm1022.S +++ b/trunk/arch/arm/mm/proc-arm1022.S @@ -18,9 +18,9 @@ #include #include #include +#include #include #include -#include #include #include "proc-macros.S" diff --git a/trunk/arch/arm/mm/proc-arm1026.S b/trunk/arch/arm/mm/proc-arm1026.S index d6d84d92c7c7..3247ce5c0177 100644 --- a/trunk/arch/arm/mm/proc-arm1026.S +++ b/trunk/arch/arm/mm/proc-arm1026.S @@ -18,9 +18,9 @@ #include #include #include +#include #include #include -#include #include #include "proc-macros.S" diff --git a/trunk/arch/arm/mm/proc-arm6_7.S b/trunk/arch/arm/mm/proc-arm6_7.S index 0432e4806888..ce4f9eef763c 100644 --- a/trunk/arch/arm/mm/proc-arm6_7.S +++ b/trunk/arch/arm/mm/proc-arm6_7.S @@ -15,9 +15,9 @@ #include #include #include +#include #include #include -#include #include ENTRY(cpu_arm6_dcache_clean_area) diff --git a/trunk/arch/arm/mm/proc-arm720.S b/trunk/arch/arm/mm/proc-arm720.S index c2f0705bfd49..c04c194da785 100644 --- a/trunk/arch/arm/mm/proc-arm720.S +++ b/trunk/arch/arm/mm/proc-arm720.S @@ -36,9 +36,9 @@ #include #include #include +#include #include #include -#include #include #include "proc-macros.S" diff --git a/trunk/arch/arm/mm/proc-arm740.S b/trunk/arch/arm/mm/proc-arm740.S index 40713818a87b..7069f495cf9b 100644 --- a/trunk/arch/arm/mm/proc-arm740.S +++ b/trunk/arch/arm/mm/proc-arm740.S @@ -12,9 +12,9 @@ #include #include #include +#include #include #include -#include #include .text diff --git a/trunk/arch/arm/mm/proc-arm7tdmi.S b/trunk/arch/arm/mm/proc-arm7tdmi.S index 22d7e3100ea6..d091c2571823 100644 --- a/trunk/arch/arm/mm/proc-arm7tdmi.S +++ b/trunk/arch/arm/mm/proc-arm7tdmi.S @@ -12,9 +12,9 @@ #include #include #include +#include #include #include -#include #include .text diff --git a/trunk/arch/arm/mm/proc-arm920.S b/trunk/arch/arm/mm/proc-arm920.S index 4adb46b3a4e0..65cbb2851bff 100644 --- a/trunk/arch/arm/mm/proc-arm920.S +++ b/trunk/arch/arm/mm/proc-arm920.S @@ -28,9 +28,9 @@ #include #include #include +#include #include #include -#include #include #include #include "proc-macros.S" diff --git a/trunk/arch/arm/mm/proc-arm922.S b/trunk/arch/arm/mm/proc-arm922.S index 571f082f0247..52761b70d735 100644 --- a/trunk/arch/arm/mm/proc-arm922.S +++ b/trunk/arch/arm/mm/proc-arm922.S @@ -29,9 +29,9 @@ #include #include #include +#include #include #include -#include #include #include #include "proc-macros.S" diff --git a/trunk/arch/arm/mm/proc-arm925.S b/trunk/arch/arm/mm/proc-arm925.S index 8d9a9f93b011..5b74339d1588 100644 --- a/trunk/arch/arm/mm/proc-arm925.S +++ b/trunk/arch/arm/mm/proc-arm925.S @@ -52,9 +52,9 @@ #include #include #include +#include #include #include -#include #include #include #include "proc-macros.S" diff --git a/trunk/arch/arm/mm/proc-arm926.S b/trunk/arch/arm/mm/proc-arm926.S index 44a7a652d625..8628ed29a955 100644 --- a/trunk/arch/arm/mm/proc-arm926.S +++ b/trunk/arch/arm/mm/proc-arm926.S @@ -28,9 +28,9 @@ #include #include #include +#include #include #include -#include #include #include #include "proc-macros.S" diff --git a/trunk/arch/arm/mm/proc-arm940.S b/trunk/arch/arm/mm/proc-arm940.S index 2397f4b6e151..786c593778f0 100644 --- a/trunk/arch/arm/mm/proc-arm940.S +++ b/trunk/arch/arm/mm/proc-arm940.S @@ -11,9 +11,9 @@ #include #include #include +#include #include #include -#include #include /* ARM940T has a 4KB DCache comprising 256 lines of 4 words */ diff --git a/trunk/arch/arm/mm/proc-arm946.S b/trunk/arch/arm/mm/proc-arm946.S index e18617564421..a60c1421d450 100644 --- a/trunk/arch/arm/mm/proc-arm946.S +++ b/trunk/arch/arm/mm/proc-arm946.S @@ -13,9 +13,9 @@ #include #include #include +#include #include #include -#include #include /* diff --git a/trunk/arch/arm/mm/proc-arm9tdmi.S b/trunk/arch/arm/mm/proc-arm9tdmi.S index 918ebf65d4f6..4848eeac86b6 100644 --- a/trunk/arch/arm/mm/proc-arm9tdmi.S +++ b/trunk/arch/arm/mm/proc-arm9tdmi.S @@ -12,9 +12,9 @@ #include #include #include +#include #include #include -#include #include .text diff --git a/trunk/arch/arm/mm/proc-sa110.S b/trunk/arch/arm/mm/proc-sa110.S index c878064e9b88..cd7d865c9d19 100644 --- a/trunk/arch/arm/mm/proc-sa110.S +++ b/trunk/arch/arm/mm/proc-sa110.S @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/trunk/arch/arm/mm/proc-sa1100.S b/trunk/arch/arm/mm/proc-sa1100.S index b23b66a6155a..b776653cc31c 100644 --- a/trunk/arch/arm/mm/proc-sa1100.S +++ b/trunk/arch/arm/mm/proc-sa1100.S @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/trunk/arch/arm/mm/proc-v6.S b/trunk/arch/arm/mm/proc-v6.S index 6f72549f8843..b440c8a1d345 100644 --- a/trunk/arch/arm/mm/proc-v6.S +++ b/trunk/arch/arm/mm/proc-v6.S @@ -13,8 +13,8 @@ #include #include #include +#include #include -#include #include #include diff --git a/trunk/arch/arm/mm/proc-xsc3.S b/trunk/arch/arm/mm/proc-xsc3.S index 4ace2d8090c7..1ef564d0957f 100644 --- a/trunk/arch/arm/mm/proc-xsc3.S +++ b/trunk/arch/arm/mm/proc-xsc3.S @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include #include #include @@ -56,11 +56,6 @@ */ #define L2_CACHE_ENABLE 1 -/* - * Enable the Branch Target Buffer (can cause crashes, see erratum #42.) - */ -#define BTB_ENABLE 0 - /* * This macro is used to wait for a CP15 write and is needed * when we have to ensure that the last operation to the co-pro @@ -371,8 +366,10 @@ ENTRY(cpu_xsc3_switch_mm) ENTRY(cpu_xsc3_set_pte) str r1, [r0], #-2048 @ linux version - bic r2, r1, #0xdf0 @ Keep C, B, coherency bits + bic r2, r1, #0xff0 @ Keep C, B bits orr r2, r2, #PTE_TYPE_EXT @ extended page + tst r1, #L_PTE_SHARED @ Shared? + orrne r2, r2, #0x200 eor r3, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_WRITE | L_PTE_DIRTY @@ -432,9 +429,7 @@ __xsc3_setup: mrc p15, 0, r0, c1, c0, 0 @ get control register bic r0, r0, r5 @ .... .... .... ..A. orr r0, r0, r6 @ .... .... .... .C.M -#if BTB_ENABLE orr r0, r0, #0x00000800 @ ..VI Z..S .... .... -#endif #if L2_CACHE_ENABLE orr r0, r0, #0x04000000 @ L2 enable #endif diff --git a/trunk/arch/arm/mm/proc-xscale.S b/trunk/arch/arm/mm/proc-xscale.S index 2749c1f88d7d..cc1004b3e511 100644 --- a/trunk/arch/arm/mm/proc-xscale.S +++ b/trunk/arch/arm/mm/proc-xscale.S @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include #include #include @@ -491,12 +491,7 @@ __xscale_setup: mcr p15, 0, ip, c7, c7, 0 @ invalidate I, D caches & BTB mcr p15, 0, ip, c7, c10, 4 @ Drain Write (& Fill) Buffer mcr p15, 0, ip, c8, c7, 0 @ invalidate I, D TLBs -#ifdef CONFIG_IWMMXT - mov r0, #0 @ initially disallow access to CP0/CP1 -#else - mov r0, #1 @ Allow access to CP0 -#endif - orr r0, r0, #1 << 6 @ cp6 for IOP3xx and Bulverde + mov r0, #1 << 6 @ cp6 for IOP3xx and Bulverde orr r0, r0, #1 << 13 @ Its undefined whether this mcr p15, 0, r0, c15, c1, 0 @ affects USR or SVC modes @@ -909,7 +904,7 @@ __pxa270_proc_info: b __xscale_setup .long cpu_arch_name .long cpu_elf_name - .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP|HWCAP_IWMMXT + .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP .long cpu_pxa270_name .long xscale_processor_functions .long v4wbi_tlb_fns diff --git a/trunk/arch/arm/plat-omap/gpio.c b/trunk/arch/arm/plat-omap/gpio.c index 8162eed8b500..4f2fd5591337 100644 --- a/trunk/arch/arm/plat-omap/gpio.c +++ b/trunk/arch/arm/plat-omap/gpio.c @@ -410,7 +410,7 @@ static inline void set_24xx_gpio_triggering(void __iomem *base, int gpio, int tr trigger & __IRQT_RISEDGE); MOD_REG_BIT(OMAP24XX_GPIO_FALLINGDETECT, gpio_bit, trigger & __IRQT_FALEDGE); - /* FIXME: Possibly do 'set_irq_handler(j, do_level_IRQ)' if only level + /* FIXME: Possibly do 'set_irq_handler(j, handle_level_irq)' if only level * triggering requested. */ } @@ -783,7 +783,7 @@ void omap_free_gpio(int gpio) * line's interrupt handler has been run, we may miss some nested * interrupts. */ -static void gpio_irq_handler(unsigned int irq, struct irqdesc *desc) +static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc) { void __iomem *isr_reg = NULL; u32 isr; @@ -853,7 +853,7 @@ static void gpio_irq_handler(unsigned int irq, struct irqdesc *desc) gpio_irq = bank->virtual_irq_start; for (; isr != 0; isr >>= 1, gpio_irq++) { - struct irqdesc *d; + struct irq_desc *d; int irq_mask; if (!(isr & 1)) continue; @@ -1092,7 +1092,7 @@ static int __init _omap_gpio_init(void) set_irq_chip(j, &mpuio_irq_chip); else set_irq_chip(j, &gpio_irq_chip); - set_irq_handler(j, do_simple_IRQ); + set_irq_handler(j, handle_simple_irq); set_irq_flags(j, IRQF_VALID); } set_irq_chained_handler(bank->irq, gpio_irq_handler); diff --git a/trunk/arch/arm/tools/mach-types b/trunk/arch/arm/tools/mach-types index 579c69ae9ff7..8bcb838e5444 100644 --- a/trunk/arch/arm/tools/mach-types +++ b/trunk/arch/arm/tools/mach-types @@ -12,7 +12,7 @@ # # http://www.arm.linux.org.uk/developer/machines/?action=new # -# Last update: Mon Oct 16 21:13:36 2006 +# Last update: Thu Dec 7 17:19:20 2006 # # machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number # @@ -79,7 +79,7 @@ psionw ARCH_PSIONW PSIONW 60 aln SA1100_ALN ALN 61 epxa ARCH_CAMELOT CAMELOT 62 gds2200 SA1100_GDS2200 GDS2200 63 -psion_series7 SA1100_PSION_SERIES7 PSION_SERIES7 64 +netbook SA1100_PSION_SERIES7 PSION_SERIES7 64 xfile SA1100_XFILE XFILE 65 accelent_ep9312 ARCH_ACCELENT_EP9312 ACCELENT_EP9312 66 ic200 ARCH_IC200 IC200 67 @@ -810,9 +810,9 @@ sb3010 MACH_SB3010 SB3010 795 rm9200 MACH_RM9200 RM9200 796 dma03 MACH_DMA03 DMA03 797 road_s101 MACH_ROAD_S101 ROAD_S101 798 -iq_nextgen_a MACH_IQ_NEXTGEN_A IQ_NEXTGEN_A 799 +iq81340sc MACH_IQ81340SC IQ81340SC 799 iq_nextgen_b MACH_IQ_NEXTGEN_B IQ_NEXTGEN_B 800 -iq_nextgen_c MACH_IQ_NEXTGEN_C IQ_NEXTGEN_C 801 +iq81340mc MACH_IQ81340MC IQ81340MC 801 iq_nextgen_d MACH_IQ_NEXTGEN_D IQ_NEXTGEN_D 802 iq_nextgen_e MACH_IQ_NEXTGEN_E IQ_NEXTGEN_E 803 mallow_at91 MACH_MALLOW_AT91 MALLOW_AT91 804 @@ -1165,9 +1165,57 @@ pnx4010 MACH_PNX4010 PNX4010 1151 oxnas MACH_OXNAS OXNAS 1152 fiori MACH_FIORI FIORI 1153 ml1200 MACH_ML1200 ML1200 1154 -cactus MACH_CACTUS CACTUS 1155 +pecos MACH_PECOS PECOS 1155 nb2xxx MACH_NB2XXX NB2XXX 1156 hw6900 MACH_HW6900 HW6900 1157 cdcs_quoll MACH_CDCS_QUOLL CDCS_QUOLL 1158 quicksilver MACH_QUICKSILVER QUICKSILVER 1159 uplat926 MACH_UPLAT926 UPLAT926 1160 +dep2410_dep2410 MACH_DEP2410_THOMAS DEP2410_THOMAS 1161 +dtk2410 MACH_DTK2410 DTK2410 1162 +chili MACH_CHILI CHILI 1163 +demeter MACH_DEMETER DEMETER 1164 +dionysus MACH_DIONYSUS DIONYSUS 1165 +as352x MACH_AS352X AS352X 1166 +service MACH_SERVICE SERVICE 1167 +cs_e9301 MACH_CS_E9301 CS_E9301 1168 +micro9m MACH_MICRO9M MICRO9M 1169 +ia_mospck MACH_IA_MOSPCK IA_MOSPCK 1170 +ql201b MACH_QL201B QL201B 1171 +bbm MACH_BBM BBM 1174 +exxx MACH_EXXX EXXX 1175 +wma11b MACH_WMA11B WMA11B 1176 +pelco_atlas MACH_PELCO_ATLAS PELCO_ATLAS 1177 +g500 MACH_G500 G500 1178 +bug MACH_BUG BUG 1179 +mx33ads MACH_MX33ADS MX33ADS 1180 +chub MACH_CHUB CHUB 1181 +gta01 MACH_GTA01 GTA01 1182 +w90n740 MACH_W90N740 W90N740 1183 +medallion_sa2410 MACH_MEDALLION_SA2410 MEDALLION_SA2410 1184 +ia_cpu_9200_2 MACH_IA_CPU_9200_2 IA_CPU_9200_2 1185 +dimmrm9200 MACH_DIMMRM9200 DIMMRM9200 1186 +pm9261 MACH_PM9261 PM9261 1187 +mx21 MACH_MX21 MX21 1188 +ml7304 MACH_ML7304 ML7304 1189 +ucp250 MACH_UCP250 UCP250 1190 +intboard MACH_INTBOARD INTBOARD 1191 +gulfstream MACH_GULFSTREAM GULFSTREAM 1192 +labquest MACH_LABQUEST LABQUEST 1193 +vcmx313 MACH_VCMX313 VCMX313 1194 +urg200 MACH_URG200 URG200 1195 +cpux255lcdnet MACH_CPUX255LCDNET CPUX255LCDNET 1196 +netdcu9 MACH_NETDCU9 NETDCU9 1197 +netdcu10 MACH_NETDCU10 NETDCU10 1198 +dspg_dga MACH_DSPG_DGA DSPG_DGA 1199 +dspg_dvw MACH_DSPG_DVW DSPG_DVW 1200 +solos MACH_SOLOS SOLOS 1201 +at91sam9263ek MACH_AT91SAM9263EK AT91SAM9263EK 1202 +osstbox MACH_OSSTBOX OSSTBOX 1203 +kbat9261 MACH_KBAT9261 KBAT9261 1204 +ct1100 MACH_CT1100 CT1100 1205 +akcppxa MACH_AKCPPXA AKCPPXA 1206 +zevio_1020 MACH_ZEVIO_1020 ZEVIO_1020 1207 +hitrack MACH_HITRACK HITRACK 1208 +syme1 MACH_SYME1 SYME1 1209 +syhl1 MACH_SYHL1 SYHL1 1210 diff --git a/trunk/arch/arm26/Kconfig b/trunk/arch/arm26/Kconfig index c14fe918bc4c..74eba8b5a8ca 100644 --- a/trunk/arch/arm26/Kconfig +++ b/trunk/arch/arm26/Kconfig @@ -41,6 +41,14 @@ config RWSEM_GENERIC_SPINLOCK config RWSEM_XCHGADD_ALGORITHM bool +config ARCH_HAS_ILOG2_U32 + bool + default n + +config ARCH_HAS_ILOG2_U64 + bool + default n + config GENERIC_HWEIGHT bool default y diff --git a/trunk/arch/arm26/kernel/ecard.c b/trunk/arch/arm26/kernel/ecard.c index 047d0a408b9d..43dd41be71fb 100644 --- a/trunk/arch/arm26/kernel/ecard.c +++ b/trunk/arch/arm26/kernel/ecard.c @@ -620,12 +620,10 @@ ecard_probe(int slot, card_type_t type) struct ex_ecid cid; int i, rc = -ENOMEM; - ec = kmalloc(sizeof(ecard_t), GFP_KERNEL); + ec = kzalloc(sizeof(ecard_t), GFP_KERNEL); if (!ec) goto nomem; - memset(ec, 0, sizeof(ecard_t)); - ec->slot_no = slot; ec->type = type; ec->irq = NO_IRQ; diff --git a/trunk/arch/arm26/mm/fault.c b/trunk/arch/arm26/mm/fault.c index a1f6d8a9cc32..93c0cee0fb5e 100644 --- a/trunk/arch/arm26/mm/fault.c +++ b/trunk/arch/arm26/mm/fault.c @@ -215,7 +215,7 @@ int do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs) * If we're in an interrupt or have no user * context, we must not take the fault.. */ - if (in_interrupt() || !mm) + if (in_atomic() || !mm) goto no_context; down_read(&mm->mmap_sem); diff --git a/trunk/arch/arm26/mm/memc.c b/trunk/arch/arm26/mm/memc.c index 34def6397c3c..f2901581d4da 100644 --- a/trunk/arch/arm26/mm/memc.c +++ b/trunk/arch/arm26/mm/memc.c @@ -24,7 +24,7 @@ #define MEMC_TABLE_SIZE (256*sizeof(unsigned long)) -kmem_cache_t *pte_cache, *pgd_cache; +struct kmem_cache *pte_cache, *pgd_cache; int page_nr; /* @@ -162,12 +162,12 @@ void __init create_memmap_holes(struct meminfo *mi) { } -static void pte_cache_ctor(void *pte, kmem_cache_t *cache, unsigned long flags) +static void pte_cache_ctor(void *pte, struct kmem_cache *cache, unsigned long flags) { memzero(pte, sizeof(pte_t) * PTRS_PER_PTE); } -static void pgd_cache_ctor(void *pgd, kmem_cache_t *cache, unsigned long flags) +static void pgd_cache_ctor(void *pgd, struct kmem_cache *cache, unsigned long flags) { memzero(pgd + MEMC_TABLE_SIZE, USER_PTRS_PER_PGD * sizeof(pgd_t)); } diff --git a/trunk/arch/avr32/Kconfig b/trunk/arch/avr32/Kconfig index 5f1694eea842..bb059a4e1df9 100644 --- a/trunk/arch/avr32/Kconfig +++ b/trunk/arch/avr32/Kconfig @@ -45,6 +45,14 @@ config GENERIC_TIME config RWSEM_XCHGADD_ALGORITHM bool +config ARCH_HAS_ILOG2_U32 + bool + default n + +config ARCH_HAS_ILOG2_U64 + bool + default n + config GENERIC_BUST_SPINLOCK bool diff --git a/trunk/arch/avr32/kernel/kprobes.c b/trunk/arch/avr32/kernel/kprobes.c index ca41fc1edbe1..d0abbcaf1c1e 100644 --- a/trunk/arch/avr32/kernel/kprobes.c +++ b/trunk/arch/avr32/kernel/kprobes.c @@ -154,6 +154,7 @@ static int __kprobes kprobe_handler(struct pt_regs *regs) return 1; no_kprobe: + preempt_enable_no_resched(); return ret; } diff --git a/trunk/arch/avr32/kernel/signal.c b/trunk/arch/avr32/kernel/signal.c index 33096651c24f..0ec14854a200 100644 --- a/trunk/arch/avr32/kernel/signal.c +++ b/trunk/arch/avr32/kernel/signal.c @@ -15,7 +15,7 @@ #include #include #include -#include +#include #include #include diff --git a/trunk/arch/avr32/mm/dma-coherent.c b/trunk/arch/avr32/mm/dma-coherent.c index 44ab8a7bdae2..b68d669f823d 100644 --- a/trunk/arch/avr32/mm/dma-coherent.c +++ b/trunk/arch/avr32/mm/dma-coherent.c @@ -11,7 +11,7 @@ #include #include -void dma_cache_sync(void *vaddr, size_t size, int direction) +void dma_cache_sync(struct device *dev, void *vaddr, size_t size, int direction) { /* * No need to sync an uncached area diff --git a/trunk/arch/cris/Kconfig b/trunk/arch/cris/Kconfig index 6a1238a29d6c..3474309e049c 100644 --- a/trunk/arch/cris/Kconfig +++ b/trunk/arch/cris/Kconfig @@ -16,6 +16,14 @@ config RWSEM_GENERIC_SPINLOCK config RWSEM_XCHGADD_ALGORITHM bool +config ARCH_HAS_ILOG2_U32 + bool + default n + +config ARCH_HAS_ILOG2_U64 + bool + default n + config GENERIC_FIND_NEXT_BIT bool default y diff --git a/trunk/arch/cris/arch-v32/drivers/sync_serial.c b/trunk/arch/cris/arch-v32/drivers/sync_serial.c index e067806b2208..424eb0eb1cd5 100644 --- a/trunk/arch/cris/arch-v32/drivers/sync_serial.c +++ b/trunk/arch/cris/arch-v32/drivers/sync_serial.c @@ -504,7 +504,7 @@ static int sync_serial_release(struct inode *inode, struct file *file) static unsigned int sync_serial_poll(struct file *file, poll_table *wait) { - int dev = iminor(file->f_dentry->d_inode); + int dev = iminor(file->f_path.dentry->d_inode); unsigned int mask = 0; sync_port* port; DEBUGPOLL( static unsigned int prev_mask = 0; ); @@ -531,7 +531,7 @@ static int sync_serial_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { int return_val = 0; - int dev = iminor(file->f_dentry->d_inode); + int dev = iminor(file->f_path.dentry->d_inode); sync_port* port; reg_sser_rw_tr_cfg tr_cfg; reg_sser_rw_rec_cfg rec_cfg; @@ -789,7 +789,7 @@ static int sync_serial_ioctl(struct inode *inode, struct file *file, static ssize_t sync_serial_write(struct file * file, const char * buf, size_t count, loff_t *ppos) { - int dev = iminor(file->f_dentry->d_inode); + int dev = iminor(file->f_path.dentry->d_inode); DECLARE_WAITQUEUE(wait, current); sync_port *port; unsigned long c, c1; @@ -919,7 +919,7 @@ static ssize_t sync_serial_write(struct file * file, const char * buf, static ssize_t sync_serial_read(struct file * file, char * buf, size_t count, loff_t *ppos) { - int dev = iminor(file->f_dentry->d_inode); + int dev = iminor(file->f_path.dentry->d_inode); int avail; sync_port *port; unsigned char* start; diff --git a/trunk/arch/cris/mm/fault.c b/trunk/arch/cris/mm/fault.c index 934c51078cce..c73e91f1299a 100644 --- a/trunk/arch/cris/mm/fault.c +++ b/trunk/arch/cris/mm/fault.c @@ -232,7 +232,7 @@ do_page_fault(unsigned long address, struct pt_regs *regs, * context, we must not take the fault.. */ - if (in_interrupt() || !mm) + if (in_atomic() || !mm) goto no_context; down_read(&mm->mmap_sem); diff --git a/trunk/arch/frv/Kconfig b/trunk/arch/frv/Kconfig index cf1c446e003a..7561d7b72e75 100644 --- a/trunk/arch/frv/Kconfig +++ b/trunk/arch/frv/Kconfig @@ -41,6 +41,14 @@ config TIME_LOW_RES bool default y +config ARCH_HAS_ILOG2_U32 + bool + default y + +config ARCH_HAS_ILOG2_U64 + bool + default y + mainmenu "Fujitsu FR-V Kernel Configuration" source "init/Kconfig" diff --git a/trunk/arch/frv/kernel/futex.c b/trunk/arch/frv/kernel/futex.c index eae874a970c6..14f64b054c7e 100644 --- a/trunk/arch/frv/kernel/futex.c +++ b/trunk/arch/frv/kernel/futex.c @@ -10,9 +10,9 @@ */ #include +#include #include #include -#include /* * the various futex operations; MMU fault checking is ignored under no-MMU @@ -200,7 +200,7 @@ int futex_atomic_op_inuser(int encoded_op, int __user *uaddr) if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) return -EFAULT; - inc_preempt_count(); + pagefault_disable(); switch (op) { case FUTEX_OP_SET: @@ -223,7 +223,7 @@ int futex_atomic_op_inuser(int encoded_op, int __user *uaddr) break; } - dec_preempt_count(); + pagefault_enable(); if (!ret) { switch (cmp) { diff --git a/trunk/arch/frv/kernel/setup.c b/trunk/arch/frv/kernel/setup.c index a8c61dac1cee..1a5eb6c301c9 100644 --- a/trunk/arch/frv/kernel/setup.c +++ b/trunk/arch/frv/kernel/setup.c @@ -947,7 +947,7 @@ static void __init setup_linux_memory(void) if (LOADER_TYPE && INITRD_START) { if (INITRD_START + INITRD_SIZE <= (low_top_pfn << PAGE_SHIFT)) { reserve_bootmem(INITRD_START, INITRD_SIZE); - initrd_start = INITRD_START ? INITRD_START + PAGE_OFFSET : 0; + initrd_start = INITRD_START + PAGE_OFFSET; initrd_end = initrd_start + INITRD_SIZE; } else { diff --git a/trunk/arch/frv/kernel/signal.c b/trunk/arch/frv/kernel/signal.c index b8a5882b8625..85baeae9666a 100644 --- a/trunk/arch/frv/kernel/signal.c +++ b/trunk/arch/frv/kernel/signal.c @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/trunk/arch/frv/mm/elf-fdpic.c b/trunk/arch/frv/mm/elf-fdpic.c index f5a653033fe0..9477ccce070e 100644 --- a/trunk/arch/frv/mm/elf-fdpic.c +++ b/trunk/arch/frv/mm/elf-fdpic.c @@ -110,14 +110,14 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi #if 0 printk("[area] l=%lx (ENOMEM) f='%s'\n", - len, filp ? filp->f_dentry->d_name.name : ""); + len, filp ? filp->f_path.dentry->d_name.name : ""); #endif return -ENOMEM; success: #if 0 printk("[area] l=%lx ad=%lx f='%s'\n", - len, addr, filp ? filp->f_dentry->d_name.name : ""); + len, addr, filp ? filp->f_path.dentry->d_name.name : ""); #endif return addr; } /* end arch_get_unmapped_area() */ diff --git a/trunk/arch/frv/mm/fault.c b/trunk/arch/frv/mm/fault.c index 8b3eb50c5105..3f12296c3688 100644 --- a/trunk/arch/frv/mm/fault.c +++ b/trunk/arch/frv/mm/fault.c @@ -78,7 +78,7 @@ asmlinkage void do_page_fault(int datammu, unsigned long esr0, unsigned long ear * If we're in an interrupt or have no user * context, we must not take the fault.. */ - if (in_interrupt() || !mm) + if (in_atomic() || !mm) goto no_context; down_read(&mm->mmap_sem); diff --git a/trunk/arch/frv/mm/pgalloc.c b/trunk/arch/frv/mm/pgalloc.c index f76dd03ddd99..19b13be114a2 100644 --- a/trunk/arch/frv/mm/pgalloc.c +++ b/trunk/arch/frv/mm/pgalloc.c @@ -18,7 +18,7 @@ #include pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__((aligned(PAGE_SIZE))); -kmem_cache_t *pgd_cache; +struct kmem_cache *pgd_cache; pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address) { @@ -100,7 +100,7 @@ static inline void pgd_list_del(pgd_t *pgd) set_page_private(next, (unsigned long) pprev); } -void pgd_ctor(void *pgd, kmem_cache_t *cache, unsigned long unused) +void pgd_ctor(void *pgd, struct kmem_cache *cache, unsigned long unused) { unsigned long flags; @@ -120,7 +120,7 @@ void pgd_ctor(void *pgd, kmem_cache_t *cache, unsigned long unused) } /* never called when PTRS_PER_PMD > 1 */ -void pgd_dtor(void *pgd, kmem_cache_t *cache, unsigned long unused) +void pgd_dtor(void *pgd, struct kmem_cache *cache, unsigned long unused) { unsigned long flags; /* can be called from interrupt context */ diff --git a/trunk/arch/h8300/Kconfig b/trunk/arch/h8300/Kconfig index cabf0bfffc53..34a84bc4baf5 100644 --- a/trunk/arch/h8300/Kconfig +++ b/trunk/arch/h8300/Kconfig @@ -29,6 +29,14 @@ config RWSEM_XCHGADD_ALGORITHM bool default n +config ARCH_HAS_ILOG2_U32 + bool + default n + +config ARCH_HAS_ILOG2_U64 + bool + default n + config GENERIC_FIND_NEXT_BIT bool default y diff --git a/trunk/arch/h8300/kernel/setup.c b/trunk/arch/h8300/kernel/setup.c index 1077b71d5226..6adf8f41d2a1 100644 --- a/trunk/arch/h8300/kernel/setup.c +++ b/trunk/arch/h8300/kernel/setup.c @@ -116,7 +116,7 @@ void __init setup_arch(char **cmdline_p) #endif #else if ((memory_end < CONFIG_BLKDEV_RESERVE_ADDRESS) && - (memory_end > CONFIG_BLKDEV_RESERVE_ADDRESS) + (memory_end > CONFIG_BLKDEV_RESERVE_ADDRESS)) /* overlap userarea */ memory_end = CONFIG_BLKDEV_RESERVE_ADDRESS; #endif diff --git a/trunk/arch/h8300/kernel/signal.c b/trunk/arch/h8300/kernel/signal.c index 7787f70a05bb..02955604d760 100644 --- a/trunk/arch/h8300/kernel/signal.c +++ b/trunk/arch/h8300/kernel/signal.c @@ -38,7 +38,7 @@ #include #include #include -#include +#include #include #include diff --git a/trunk/arch/h8300/kernel/vmlinux.lds.S b/trunk/arch/h8300/kernel/vmlinux.lds.S index 756325dd480e..f05288be8878 100644 --- a/trunk/arch/h8300/kernel/vmlinux.lds.S +++ b/trunk/arch/h8300/kernel/vmlinux.lds.S @@ -70,6 +70,7 @@ SECTIONS #endif .text : { + _text = .; #if defined(CONFIG_ROMKERNEL) *(.int_redirect) #endif diff --git a/trunk/arch/i386/Kconfig b/trunk/arch/i386/Kconfig index 8ff1c6fb5aa1..c2362c7ba749 100644 --- a/trunk/arch/i386/Kconfig +++ b/trunk/arch/i386/Kconfig @@ -49,6 +49,11 @@ config GENERIC_IOMAP bool default y +config GENERIC_BUG + bool + default y + depends on BUG + config GENERIC_HWEIGHT bool default y @@ -182,6 +187,17 @@ config X86_ES7000 endchoice +config PARAVIRT + bool "Paravirtualization support (EXPERIMENTAL)" + depends on EXPERIMENTAL + help + Paravirtualization is a way of running multiple instances of + Linux on the same machine, under a hypervisor. This option + changes the kernel so it can modify itself when it is run + under a hypervisor, improving performance significantly. + However, when run without a hypervisor the kernel is + theoretically slower. If in doubt, say N. + config ACPI_SRAT bool default y @@ -443,7 +459,8 @@ source "drivers/firmware/Kconfig" choice prompt "High Memory Support" - default NOHIGHMEM + default HIGHMEM4G if !X86_NUMAQ + default HIGHMEM64G if X86_NUMAQ config NOHIGHMEM bool "off" @@ -710,20 +727,6 @@ config BOOT_IOREMAP depends on (((X86_SUMMIT || X86_GENERICARCH) && NUMA) || (X86 && EFI)) default y -config REGPARM - bool "Use register arguments" - default y - help - Compile the kernel with -mregparm=3. This instructs gcc to use - a more efficient function call ABI which passes the first three - arguments of a function call via registers, which results in denser - and faster code. - - If this option is disabled, then the default ABI of passing - arguments via the stack is used. - - If unsure, say Y. - config SECCOMP bool "Enable seccomp to safely compute untrusted bytecode" depends on PROC_FS @@ -773,23 +776,39 @@ config CRASH_DUMP PHYSICAL_START. For more details see Documentation/kdump/kdump.txt -config PHYSICAL_START - hex "Physical address where the kernel is loaded" if (EMBEDDED || CRASH_DUMP) +config RELOCATABLE + bool "Build a relocatable kernel(EXPERIMENTAL)" + depends on EXPERIMENTAL + help + This build a kernel image that retains relocation information + so it can be loaded someplace besides the default 1MB. + The relocations tend to the kernel binary about 10% larger, + but are discarded at runtime. + + One use is for the kexec on panic case where the recovery kernel + must live at a different physical address than the primary + kernel. - default "0x1000000" if CRASH_DUMP +config PHYSICAL_ALIGN + hex "Alignment value to which kernel should be aligned" default "0x100000" + range 0x2000 0x400000 help - This gives the physical address where the kernel is loaded. Normally - for regular kernels this value is 0x100000 (1MB). But in the case - of kexec on panic the fail safe kernel needs to run at a different - address than the panic-ed kernel. This option is used to set the load - address for kernels used to capture crash dump on being kexec'ed - after panic. The default value for crash dump kernels is - 0x1000000 (16MB). This can also be set based on the "X" value as - specified in the "crashkernel=YM@XM" command line boot parameter - passed to the panic-ed kernel. Typically this parameter is set as - crashkernel=64M@16M. Please take a look at - Documentation/kdump/kdump.txt for more details about crash dumps. + This value puts the alignment restrictions on physical address + where kernel is loaded and run from. Kernel is compiled for an + address which meets above alignment restriction. + + If bootloader loads the kernel at a non-aligned address and + CONFIG_RELOCATABLE is set, kernel will move itself to nearest + address aligned to above value and run from there. + + If bootloader loads the kernel at a non-aligned address and + CONFIG_RELOCATABLE is not set, kernel will ignore the run time + load address and decompress itself to the address it has been + compiled for and run from there. The address for which kernel is + compiled already meets above alignment restrictions. Hence the + end result is that kernel runs from a physical address meeting + above alignment restrictions. Don't change this unless you know what you are doing. diff --git a/trunk/arch/i386/Kconfig.cpu b/trunk/arch/i386/Kconfig.cpu index fc4f2abccf06..2aecfba4ac4f 100644 --- a/trunk/arch/i386/Kconfig.cpu +++ b/trunk/arch/i386/Kconfig.cpu @@ -103,8 +103,15 @@ config MPENTIUMM Select this for Intel Pentium M (not Pentium-4 M) notebook chips. +config MCORE2 + bool "Core 2/newer Xeon" + help + Select this for Intel Core 2 and newer Core 2 Xeons (Xeon 51xx and 53xx) + CPUs. You can distingush newer from older Xeons by the CPU family + in /proc/cpuinfo. Newer ones have 6. + config MPENTIUM4 - bool "Pentium-4/Celeron(P4-based)/Pentium-4 M/Xeon" + bool "Pentium-4/Celeron(P4-based)/Pentium-4 M/older Xeon" help Select this for Intel Pentium 4 chips. This includes the Pentium 4, P4-based Celeron and Xeon, and Pentium-4 M @@ -229,7 +236,7 @@ config X86_L1_CACHE_SHIFT default "7" if MPENTIUM4 || X86_GENERIC default "4" if X86_ELAN || M486 || M386 || MGEODEGX1 default "5" if MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCRUSOE || MEFFICEON || MCYRIXIII || MK6 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || M586 || MVIAC3_2 || MGEODE_LX - default "6" if MK7 || MK8 || MPENTIUMM + default "6" if MK7 || MK8 || MPENTIUMM || MCORE2 config RWSEM_GENERIC_SPINLOCK bool @@ -241,6 +248,14 @@ config RWSEM_XCHGADD_ALGORITHM depends on !M386 default y +config ARCH_HAS_ILOG2_U32 + bool + default n + +config ARCH_HAS_ILOG2_U64 + bool + default n + config GENERIC_CALIBRATE_DELAY bool default y @@ -287,17 +302,17 @@ config X86_ALIGNMENT_16 config X86_GOOD_APIC bool - depends on MK7 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || MK8 || MEFFICEON + depends on MK7 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || MK8 || MEFFICEON || MCORE2 default y config X86_INTEL_USERCOPY bool - depends on MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M586MMX || X86_GENERIC || MK8 || MK7 || MEFFICEON + depends on MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M586MMX || X86_GENERIC || MK8 || MK7 || MEFFICEON || MCORE2 default y config X86_USE_PPRO_CHECKSUM bool - depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MK8 || MVIAC3_2 || MEFFICEON || MGEODE_LX + depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MK8 || MVIAC3_2 || MEFFICEON || MGEODE_LX || MCORE2 default y config X86_USE_3DNOW @@ -312,5 +327,5 @@ config X86_OOSTORE config X86_TSC bool - depends on (MWINCHIP3D || MWINCHIP2 || MCRUSOE || MEFFICEON || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2 || MGEODEGX1 || MGEODE_LX) && !X86_NUMAQ + depends on (MWINCHIP3D || MWINCHIP2 || MCRUSOE || MEFFICEON || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2 || MGEODEGX1 || MGEODE_LX || MCORE2) && !X86_NUMAQ default y diff --git a/trunk/arch/i386/Kconfig.debug b/trunk/arch/i386/Kconfig.debug index b31c0802e1cc..f68cc6f215f8 100644 --- a/trunk/arch/i386/Kconfig.debug +++ b/trunk/arch/i386/Kconfig.debug @@ -85,4 +85,14 @@ config DOUBLEFAULT option saves about 4k and might cause you much additional grey hair. +config DEBUG_PARAVIRT + bool "Enable some paravirtualization debugging" + default y + depends on PARAVIRT && DEBUG_KERNEL + help + Currently deliberately clobbers regs which are allowed to be + clobbered in inlined paravirt hooks, even in native mode. + If turning this off solves a problem, then DISABLE_INTERRUPTS() or + ENABLE_INTERRUPTS() is lying about what registers can be clobbered. + endmenu diff --git a/trunk/arch/i386/Makefile b/trunk/arch/i386/Makefile index 0677908dfa06..f7ac1aea1d8a 100644 --- a/trunk/arch/i386/Makefile +++ b/trunk/arch/i386/Makefile @@ -26,10 +26,12 @@ endif LDFLAGS := -m elf_i386 OBJCOPYFLAGS := -O binary -R .note -R .comment -S -LDFLAGS_vmlinux := +ifdef CONFIG_RELOCATABLE +LDFLAGS_vmlinux := --emit-relocs +endif CHECKFLAGS += -D__i386__ -CFLAGS += -pipe -msoft-float +CFLAGS += -pipe -msoft-float -mregparm=3 # prevent gcc from keeping the stack 16 byte aligned CFLAGS += $(call cc-option,-mpreferred-stack-boundary=2) @@ -37,8 +39,6 @@ CFLAGS += $(call cc-option,-mpreferred-stack-boundary=2) # CPU-specific tuning. Anything which can be shared with UML should go here. include $(srctree)/arch/i386/Makefile.cpu -cflags-$(CONFIG_REGPARM) += -mregparm=3 - # temporary until string.h is fixed cflags-y += -ffreestanding diff --git a/trunk/arch/i386/Makefile.cpu b/trunk/arch/i386/Makefile.cpu index a11befba26d5..a32c031c90d7 100644 --- a/trunk/arch/i386/Makefile.cpu +++ b/trunk/arch/i386/Makefile.cpu @@ -32,6 +32,7 @@ cflags-$(CONFIG_MWINCHIP2) += $(call cc-option,-march=winchip2,-march=i586) cflags-$(CONFIG_MWINCHIP3D) += $(call cc-option,-march=winchip2,-march=i586) cflags-$(CONFIG_MCYRIXIII) += $(call cc-option,-march=c3,-march=i486) $(align)-functions=0 $(align)-jumps=0 $(align)-loops=0 cflags-$(CONFIG_MVIAC3_2) += $(call cc-option,-march=c3-2,-march=i686) +cflags-$(CONFIG_MCORE2) += -march=i686 $(call cc-option,-mtune=core2,$(call cc-option,-mtune=generic,-mtune=i686)) # AMD Elan support cflags-$(CONFIG_X86_ELAN) += -march=i486 diff --git a/trunk/arch/i386/boot/compressed/Makefile b/trunk/arch/i386/boot/compressed/Makefile index 258ea95224f6..a661217f33ec 100644 --- a/trunk/arch/i386/boot/compressed/Makefile +++ b/trunk/arch/i386/boot/compressed/Makefile @@ -4,22 +4,42 @@ # create a compressed vmlinux image from the original vmlinux # -targets := vmlinux vmlinux.bin vmlinux.bin.gz head.o misc.o piggy.o +targets := vmlinux vmlinux.bin vmlinux.bin.gz head.o misc.o piggy.o \ + vmlinux.bin.all vmlinux.relocs EXTRA_AFLAGS := -traditional -LDFLAGS_vmlinux := -Ttext $(IMAGE_OFFSET) -e startup_32 +LDFLAGS_vmlinux := -T +CFLAGS_misc.o += -fPIC +hostprogs-y := relocs -$(obj)/vmlinux: $(obj)/head.o $(obj)/misc.o $(obj)/piggy.o FORCE +$(obj)/vmlinux: $(src)/vmlinux.lds $(obj)/head.o $(obj)/misc.o $(obj)/piggy.o FORCE $(call if_changed,ld) @: $(obj)/vmlinux.bin: vmlinux FORCE $(call if_changed,objcopy) +quiet_cmd_relocs = RELOCS $@ + cmd_relocs = $(obj)/relocs $< > $@;$(obj)/relocs --abs-relocs $< +$(obj)/vmlinux.relocs: vmlinux $(obj)/relocs FORCE + $(call if_changed,relocs) + +vmlinux.bin.all-y := $(obj)/vmlinux.bin +vmlinux.bin.all-$(CONFIG_RELOCATABLE) += $(obj)/vmlinux.relocs +quiet_cmd_relocbin = BUILD $@ + cmd_relocbin = cat $(filter-out FORCE,$^) > $@ +$(obj)/vmlinux.bin.all: $(vmlinux.bin.all-y) FORCE + $(call if_changed,relocbin) + +ifdef CONFIG_RELOCATABLE +$(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin.all FORCE + $(call if_changed,gzip) +else $(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE $(call if_changed,gzip) +endif LDFLAGS_piggy.o := -r --format binary --oformat elf32-i386 -T -$(obj)/piggy.o: $(obj)/vmlinux.scr $(obj)/vmlinux.bin.gz FORCE +$(obj)/piggy.o: $(src)/vmlinux.scr $(obj)/vmlinux.bin.gz FORCE $(call if_changed,ld) diff --git a/trunk/arch/i386/boot/compressed/head.S b/trunk/arch/i386/boot/compressed/head.S index b5893e4ecd37..f395a4bb38bb 100644 --- a/trunk/arch/i386/boot/compressed/head.S +++ b/trunk/arch/i386/boot/compressed/head.S @@ -26,9 +26,11 @@ #include #include #include +#include +.section ".text.head" .globl startup_32 - + startup_32: cld cli @@ -37,93 +39,142 @@ startup_32: movl %eax,%es movl %eax,%fs movl %eax,%gs + movl %eax,%ss - lss stack_start,%esp - xorl %eax,%eax -1: incl %eax # check that A20 really IS enabled - movl %eax,0x000000 # loop forever if it isn't - cmpl %eax,0x100000 - je 1b +/* Calculate the delta between where we were compiled to run + * at and where we were actually loaded at. This can only be done + * with a short local call on x86. Nothing else will tell us what + * address we are running at. The reserved chunk of the real-mode + * data at 0x34-0x3f are used as the stack for this calculation. + * Only 4 bytes are needed. + */ + leal 0x40(%esi), %esp + call 1f +1: popl %ebp + subl $1b, %ebp + +/* %ebp contains the address we are loaded at by the boot loader and %ebx + * contains the address where we should move the kernel image temporarily + * for safe in-place decompression. + */ + +#ifdef CONFIG_RELOCATABLE + movl %ebp, %ebx + addl $(CONFIG_PHYSICAL_ALIGN - 1), %ebx + andl $(~(CONFIG_PHYSICAL_ALIGN - 1)), %ebx +#else + movl $LOAD_PHYSICAL_ADDR, %ebx +#endif + + /* Replace the compressed data size with the uncompressed size */ + subl input_len(%ebp), %ebx + movl output_len(%ebp), %eax + addl %eax, %ebx + /* Add 8 bytes for every 32K input block */ + shrl $12, %eax + addl %eax, %ebx + /* Add 32K + 18 bytes of extra slack */ + addl $(32768 + 18), %ebx + /* Align on a 4K boundary */ + addl $4095, %ebx + andl $~4095, %ebx + +/* Copy the compressed kernel to the end of our buffer + * where decompression in place becomes safe. + */ + pushl %esi + leal _end(%ebp), %esi + leal _end(%ebx), %edi + movl $(_end - startup_32), %ecx + std + rep + movsb + cld + popl %esi + +/* Compute the kernel start address. + */ +#ifdef CONFIG_RELOCATABLE + addl $(CONFIG_PHYSICAL_ALIGN - 1), %ebp + andl $(~(CONFIG_PHYSICAL_ALIGN - 1)), %ebp +#else + movl $LOAD_PHYSICAL_ADDR, %ebp +#endif /* - * Initialize eflags. Some BIOS's leave bits like NT set. This would - * confuse the debugger if this code is traced. - * XXX - best to initialize before switching to protected mode. + * Jump to the relocated address. */ - pushl $0 - popfl + leal relocated(%ebx), %eax + jmp *%eax +.section ".text" +relocated: + /* * Clear BSS */ xorl %eax,%eax - movl $_edata,%edi - movl $_end,%ecx + leal _edata(%ebx),%edi + leal _end(%ebx), %ecx subl %edi,%ecx cld rep stosb + +/* + * Setup the stack for the decompressor + */ + leal stack_end(%ebx), %esp + /* * Do the decompression, and jump to the new kernel.. */ - subl $16,%esp # place for structure on the stack - movl %esp,%eax + movl output_len(%ebx), %eax + pushl %eax + pushl %ebp # output address + movl input_len(%ebx), %eax + pushl %eax # input_len + leal input_data(%ebx), %eax + pushl %eax # input_data + leal _end(%ebx), %eax + pushl %eax # end of the image as third argument pushl %esi # real mode pointer as second arg - pushl %eax # address of structure as first arg call decompress_kernel - orl %eax,%eax - jnz 3f - popl %esi # discard address - popl %esi # real mode pointer - xorl %ebx,%ebx - ljmp $(__BOOT_CS), $__PHYSICAL_START + addl $20, %esp + popl %ecx +#if CONFIG_RELOCATABLE +/* Find the address of the relocations. + */ + movl %ebp, %edi + addl %ecx, %edi + +/* Calculate the delta between where vmlinux was compiled to run + * and where it was actually loaded. + */ + movl %ebp, %ebx + subl $LOAD_PHYSICAL_ADDR, %ebx + jz 2f /* Nothing to be done if loaded at compiled addr. */ /* - * We come here, if we were loaded high. - * We need to move the move-in-place routine down to 0x1000 - * and then start it with the buffer addresses in registers, - * which we got from the stack. + * Process relocations. */ -3: - movl $move_routine_start,%esi - movl $0x1000,%edi - movl $move_routine_end,%ecx - subl %esi,%ecx - addl $3,%ecx - shrl $2,%ecx - cld - rep - movsl - - popl %esi # discard the address - popl %ebx # real mode pointer - popl %esi # low_buffer_start - popl %ecx # lcount - popl %edx # high_buffer_start - popl %eax # hcount - movl $__PHYSICAL_START,%edi - cli # make sure we don't get interrupted - ljmp $(__BOOT_CS), $0x1000 # and jump to the move routine + +1: subl $4, %edi + movl 0(%edi), %ecx + testl %ecx, %ecx + jz 2f + addl %ebx, -__PAGE_OFFSET(%ebx, %ecx) + jmp 1b +2: +#endif /* - * Routine (template) for moving the decompressed kernel in place, - * if we were high loaded. This _must_ PIC-code ! + * Jump to the decompressed kernel. */ -move_routine_start: - movl %ecx,%ebp - shrl $2,%ecx - rep - movsl - movl %ebp,%ecx - andl $3,%ecx - rep - movsb - movl %edx,%esi - movl %eax,%ecx # NOTE: rep movsb won't move if %ecx == 0 - addl $3,%ecx - shrl $2,%ecx - rep - movsl - movl %ebx,%esi # Restore setup pointer xorl %ebx,%ebx - ljmp $(__BOOT_CS), $__PHYSICAL_START -move_routine_end: + jmp *%ebp + +.bss +.balign 4 +stack: + .fill 4096, 1, 0 +stack_end: diff --git a/trunk/arch/i386/boot/compressed/misc.c b/trunk/arch/i386/boot/compressed/misc.c index b2ccd543410d..1ce7017fd627 100644 --- a/trunk/arch/i386/boot/compressed/misc.c +++ b/trunk/arch/i386/boot/compressed/misc.c @@ -9,11 +9,94 @@ * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996 */ +#undef CONFIG_PARAVIRT #include #include #include #include #include +#include + +/* WARNING!! + * This code is compiled with -fPIC and it is relocated dynamically + * at run time, but no relocation processing is performed. + * This means that it is not safe to place pointers in static structures. + */ + +/* + * Getting to provable safe in place decompression is hard. + * Worst case behaviours need to be analized. + * Background information: + * + * The file layout is: + * magic[2] + * method[1] + * flags[1] + * timestamp[4] + * extraflags[1] + * os[1] + * compressed data blocks[N] + * crc[4] orig_len[4] + * + * resulting in 18 bytes of non compressed data overhead. + * + * Files divided into blocks + * 1 bit (last block flag) + * 2 bits (block type) + * + * 1 block occurs every 32K -1 bytes or when there 50% compression has been achieved. + * The smallest block type encoding is always used. + * + * stored: + * 32 bits length in bytes. + * + * fixed: + * magic fixed tree. + * symbols. + * + * dynamic: + * dynamic tree encoding. + * symbols. + * + * + * The buffer for decompression in place is the length of the + * uncompressed data, plus a small amount extra to keep the algorithm safe. + * The compressed data is placed at the end of the buffer. The output + * pointer is placed at the start of the buffer and the input pointer + * is placed where the compressed data starts. Problems will occur + * when the output pointer overruns the input pointer. + * + * The output pointer can only overrun the input pointer if the input + * pointer is moving faster than the output pointer. A condition only + * triggered by data whose compressed form is larger than the uncompressed + * form. + * + * The worst case at the block level is a growth of the compressed data + * of 5 bytes per 32767 bytes. + * + * The worst case internal to a compressed block is very hard to figure. + * The worst case can at least be boundined by having one bit that represents + * 32764 bytes and then all of the rest of the bytes representing the very + * very last byte. + * + * All of which is enough to compute an amount of extra data that is required + * to be safe. To avoid problems at the block level allocating 5 extra bytes + * per 32767 bytes of data is sufficient. To avoind problems internal to a block + * adding an extra 32767 bytes (the worst case uncompressed block size) is + * sufficient, to ensure that in the worst case the decompressed data for + * block will stop the byte before the compressed data for a block begins. + * To avoid problems with the compressed data's meta information an extra 18 + * bytes are needed. Leading to the formula: + * + * extra_bytes = (uncompressed_size >> 12) + 32768 + 18 + decompressor_size. + * + * Adding 8 bytes per 32K is a bit excessive but much easier to calculate. + * Adding 32768 instead of 32767 just makes for round numbers. + * Adding the decompressor_size is necessary as it musht live after all + * of the data as well. Last I measured the decompressor is about 14K. + * 10K of actuall data and 4K of bss. + * + */ /* * gzip declarations @@ -30,15 +113,20 @@ typedef unsigned char uch; typedef unsigned short ush; typedef unsigned long ulg; -#define WSIZE 0x8000 /* Window size must be at least 32k, */ - /* and a power of two */ +#define WSIZE 0x80000000 /* Window size must be at least 32k, + * and a power of two + * We don't actually have a window just + * a huge output buffer so I report + * a 2G windows size, as that should + * always be larger than our output buffer. + */ -static uch *inbuf; /* input buffer */ -static uch window[WSIZE]; /* Sliding window buffer */ +static uch *inbuf; /* input buffer */ +static uch *window; /* Sliding window buffer, (and final output buffer) */ -static unsigned insize = 0; /* valid bytes in inbuf */ -static unsigned inptr = 0; /* index of next byte to be processed in inbuf */ -static unsigned outcnt = 0; /* bytes in output buffer */ +static unsigned insize; /* valid bytes in inbuf */ +static unsigned inptr; /* index of next byte to be processed in inbuf */ +static unsigned outcnt; /* bytes in output buffer */ /* gzip flag byte */ #define ASCII_FLAG 0x01 /* bit 0 set: file probably ASCII text */ @@ -89,8 +177,6 @@ extern unsigned char input_data[]; extern int input_len; static long bytes_out = 0; -static uch *output_data; -static unsigned long output_ptr = 0; static void *malloc(int size); static void free(void *where); @@ -100,24 +186,17 @@ static void *memcpy(void *dest, const void *src, unsigned n); static void putstr(const char *); -extern int end; -static long free_mem_ptr = (long)&end; -static long free_mem_end_ptr; +static unsigned long free_mem_ptr; +static unsigned long free_mem_end_ptr; -#define INPLACE_MOVE_ROUTINE 0x1000 -#define LOW_BUFFER_START 0x2000 -#define LOW_BUFFER_MAX 0x90000 #define HEAP_SIZE 0x3000 -static unsigned int low_buffer_end, low_buffer_size; -static int high_loaded =0; -static uch *high_buffer_start /* = (uch *)(((ulg)&end) + HEAP_SIZE)*/; static char *vidmem = (char *)0xb8000; static int vidport; static int lines, cols; #ifdef CONFIG_X86_NUMAQ -static void * xquad_portio = NULL; +void *xquad_portio; #endif #include "../../../../lib/inflate.c" @@ -151,7 +230,7 @@ static void gzip_mark(void **ptr) static void gzip_release(void **ptr) { - free_mem_ptr = (long) *ptr; + free_mem_ptr = (unsigned long) *ptr; } static void scroll(void) @@ -179,7 +258,7 @@ static void putstr(const char *s) y--; } } else { - vidmem [ ( x + cols * y ) * 2 ] = c; + vidmem [ ( x + cols * y ) * 2 ] = c; if ( ++x >= cols ) { x = 0; if ( ++y >= lines ) { @@ -224,58 +303,31 @@ static void* memcpy(void* dest, const void* src, unsigned n) */ static int fill_inbuf(void) { - if (insize != 0) { - error("ran out of input data"); - } - - inbuf = input_data; - insize = input_len; - inptr = 1; - return inbuf[0]; + error("ran out of input data"); + return 0; } /* =========================================================================== * Write the output window window[0..outcnt-1] and update crc and bytes_out. * (Used for the decompressed data only.) */ -static void flush_window_low(void) -{ - ulg c = crc; /* temporary variable */ - unsigned n; - uch *in, *out, ch; - - in = window; - out = &output_data[output_ptr]; - for (n = 0; n < outcnt; n++) { - ch = *out++ = *in++; - c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8); - } - crc = c; - bytes_out += (ulg)outcnt; - output_ptr += (ulg)outcnt; - outcnt = 0; -} - -static void flush_window_high(void) -{ - ulg c = crc; /* temporary variable */ - unsigned n; - uch *in, ch; - in = window; - for (n = 0; n < outcnt; n++) { - ch = *output_data++ = *in++; - if ((ulg)output_data == low_buffer_end) output_data=high_buffer_start; - c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8); - } - crc = c; - bytes_out += (ulg)outcnt; - outcnt = 0; -} - static void flush_window(void) { - if (high_loaded) flush_window_high(); - else flush_window_low(); + /* With my window equal to my output buffer + * I only need to compute the crc here. + */ + ulg c = crc; /* temporary variable */ + unsigned n; + uch *in, ch; + + in = window; + for (n = 0; n < outcnt; n++) { + ch = *in++; + c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8); + } + crc = c; + bytes_out += (ulg)outcnt; + outcnt = 0; } static void error(char *x) @@ -287,66 +339,8 @@ static void error(char *x) while(1); /* Halt */ } -#define STACK_SIZE (4096) - -long user_stack [STACK_SIZE]; - -struct { - long * a; - short b; - } stack_start = { & user_stack [STACK_SIZE] , __BOOT_DS }; - -static void setup_normal_output_buffer(void) -{ -#ifdef STANDARD_MEMORY_BIOS_CALL - if (RM_EXT_MEM_K < 1024) error("Less than 2MB of memory"); -#else - if ((RM_ALT_MEM_K > RM_EXT_MEM_K ? RM_ALT_MEM_K : RM_EXT_MEM_K) < 1024) error("Less than 2MB of memory"); -#endif - output_data = (unsigned char *)__PHYSICAL_START; /* Normally Points to 1M */ - free_mem_end_ptr = (long)real_mode; -} - -struct moveparams { - uch *low_buffer_start; int lcount; - uch *high_buffer_start; int hcount; -}; - -static void setup_output_buffer_if_we_run_high(struct moveparams *mv) -{ - high_buffer_start = (uch *)(((ulg)&end) + HEAP_SIZE); -#ifdef STANDARD_MEMORY_BIOS_CALL - if (RM_EXT_MEM_K < (3*1024)) error("Less than 4MB of memory"); -#else - if ((RM_ALT_MEM_K > RM_EXT_MEM_K ? RM_ALT_MEM_K : RM_EXT_MEM_K) < (3*1024)) error("Less than 4MB of memory"); -#endif - mv->low_buffer_start = output_data = (unsigned char *)LOW_BUFFER_START; - low_buffer_end = ((unsigned int)real_mode > LOW_BUFFER_MAX - ? LOW_BUFFER_MAX : (unsigned int)real_mode) & ~0xfff; - low_buffer_size = low_buffer_end - LOW_BUFFER_START; - high_loaded = 1; - free_mem_end_ptr = (long)high_buffer_start; - if ( (__PHYSICAL_START + low_buffer_size) > ((ulg)high_buffer_start)) { - high_buffer_start = (uch *)(__PHYSICAL_START + low_buffer_size); - mv->hcount = 0; /* say: we need not to move high_buffer */ - } - else mv->hcount = -1; - mv->high_buffer_start = high_buffer_start; -} - -static void close_output_buffer_if_we_run_high(struct moveparams *mv) -{ - if (bytes_out > low_buffer_size) { - mv->lcount = low_buffer_size; - if (mv->hcount) - mv->hcount = bytes_out - low_buffer_size; - } else { - mv->lcount = bytes_out; - mv->hcount = 0; - } -} - -asmlinkage int decompress_kernel(struct moveparams *mv, void *rmode) +asmlinkage void decompress_kernel(void *rmode, unsigned long end, + uch *input_data, unsigned long input_len, uch *output) { real_mode = rmode; @@ -361,13 +355,25 @@ asmlinkage int decompress_kernel(struct moveparams *mv, void *rmode) lines = RM_SCREEN_INFO.orig_video_lines; cols = RM_SCREEN_INFO.orig_video_cols; - if (free_mem_ptr < 0x100000) setup_normal_output_buffer(); - else setup_output_buffer_if_we_run_high(mv); + window = output; /* Output buffer (Normally at 1M) */ + free_mem_ptr = end; /* Heap */ + free_mem_end_ptr = end + HEAP_SIZE; + inbuf = input_data; /* Input buffer */ + insize = input_len; + inptr = 0; + + if ((u32)output & (CONFIG_PHYSICAL_ALIGN -1)) + error("Destination address not CONFIG_PHYSICAL_ALIGN aligned"); + if (end > ((-__PAGE_OFFSET-(512 <<20)-1) & 0x7fffffff)) + error("Destination address too large"); +#ifndef CONFIG_RELOCATABLE + if ((u32)output != LOAD_PHYSICAL_ADDR) + error("Wrong destination address"); +#endif makecrc(); putstr("Uncompressing Linux... "); gunzip(); putstr("Ok, booting the kernel.\n"); - if (high_loaded) close_output_buffer_if_we_run_high(mv); - return high_loaded; + return; } diff --git a/trunk/arch/i386/boot/compressed/relocs.c b/trunk/arch/i386/boot/compressed/relocs.c new file mode 100644 index 000000000000..468da89153c4 --- /dev/null +++ b/trunk/arch/i386/boot/compressed/relocs.c @@ -0,0 +1,625 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define USE_BSD +#include + +#define MAX_SHDRS 100 +static Elf32_Ehdr ehdr; +static Elf32_Shdr shdr[MAX_SHDRS]; +static Elf32_Sym *symtab[MAX_SHDRS]; +static Elf32_Rel *reltab[MAX_SHDRS]; +static char *strtab[MAX_SHDRS]; +static unsigned long reloc_count, reloc_idx; +static unsigned long *relocs; + +/* + * Following symbols have been audited. There values are constant and do + * not change if bzImage is loaded at a different physical address than + * the address for which it has been compiled. Don't warn user about + * absolute relocations present w.r.t these symbols. + */ +static const char* safe_abs_relocs[] = { + "__kernel_vsyscall", + "__kernel_rt_sigreturn", + "__kernel_sigreturn", + "SYSENTER_RETURN", +}; + +static int is_safe_abs_reloc(const char* sym_name) +{ + int i, array_size; + + array_size = sizeof(safe_abs_relocs)/sizeof(char*); + + for(i = 0; i < array_size; i++) { + if (!strcmp(sym_name, safe_abs_relocs[i])) + /* Match found */ + return 1; + } + return 0; +} + +static void die(char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + exit(1); +} + +static const char *sym_type(unsigned type) +{ + static const char *type_name[] = { +#define SYM_TYPE(X) [X] = #X + SYM_TYPE(STT_NOTYPE), + SYM_TYPE(STT_OBJECT), + SYM_TYPE(STT_FUNC), + SYM_TYPE(STT_SECTION), + SYM_TYPE(STT_FILE), + SYM_TYPE(STT_COMMON), + SYM_TYPE(STT_TLS), +#undef SYM_TYPE + }; + const char *name = "unknown sym type name"; + if (type < sizeof(type_name)/sizeof(type_name[0])) { + name = type_name[type]; + } + return name; +} + +static const char *sym_bind(unsigned bind) +{ + static const char *bind_name[] = { +#define SYM_BIND(X) [X] = #X + SYM_BIND(STB_LOCAL), + SYM_BIND(STB_GLOBAL), + SYM_BIND(STB_WEAK), +#undef SYM_BIND + }; + const char *name = "unknown sym bind name"; + if (bind < sizeof(bind_name)/sizeof(bind_name[0])) { + name = bind_name[bind]; + } + return name; +} + +static const char *sym_visibility(unsigned visibility) +{ + static const char *visibility_name[] = { +#define SYM_VISIBILITY(X) [X] = #X + SYM_VISIBILITY(STV_DEFAULT), + SYM_VISIBILITY(STV_INTERNAL), + SYM_VISIBILITY(STV_HIDDEN), + SYM_VISIBILITY(STV_PROTECTED), +#undef SYM_VISIBILITY + }; + const char *name = "unknown sym visibility name"; + if (visibility < sizeof(visibility_name)/sizeof(visibility_name[0])) { + name = visibility_name[visibility]; + } + return name; +} + +static const char *rel_type(unsigned type) +{ + static const char *type_name[] = { +#define REL_TYPE(X) [X] = #X + REL_TYPE(R_386_NONE), + REL_TYPE(R_386_32), + REL_TYPE(R_386_PC32), + REL_TYPE(R_386_GOT32), + REL_TYPE(R_386_PLT32), + REL_TYPE(R_386_COPY), + REL_TYPE(R_386_GLOB_DAT), + REL_TYPE(R_386_JMP_SLOT), + REL_TYPE(R_386_RELATIVE), + REL_TYPE(R_386_GOTOFF), + REL_TYPE(R_386_GOTPC), +#undef REL_TYPE + }; + const char *name = "unknown type rel type name"; + if (type < sizeof(type_name)/sizeof(type_name[0])) { + name = type_name[type]; + } + return name; +} + +static const char *sec_name(unsigned shndx) +{ + const char *sec_strtab; + const char *name; + sec_strtab = strtab[ehdr.e_shstrndx]; + name = ""; + if (shndx < ehdr.e_shnum) { + name = sec_strtab + shdr[shndx].sh_name; + } + else if (shndx == SHN_ABS) { + name = "ABSOLUTE"; + } + else if (shndx == SHN_COMMON) { + name = "COMMON"; + } + return name; +} + +static const char *sym_name(const char *sym_strtab, Elf32_Sym *sym) +{ + const char *name; + name = ""; + if (sym->st_name) { + name = sym_strtab + sym->st_name; + } + else { + name = sec_name(shdr[sym->st_shndx].sh_name); + } + return name; +} + + + +#if BYTE_ORDER == LITTLE_ENDIAN +#define le16_to_cpu(val) (val) +#define le32_to_cpu(val) (val) +#endif +#if BYTE_ORDER == BIG_ENDIAN +#define le16_to_cpu(val) bswap_16(val) +#define le32_to_cpu(val) bswap_32(val) +#endif + +static uint16_t elf16_to_cpu(uint16_t val) +{ + return le16_to_cpu(val); +} + +static uint32_t elf32_to_cpu(uint32_t val) +{ + return le32_to_cpu(val); +} + +static void read_ehdr(FILE *fp) +{ + if (fread(&ehdr, sizeof(ehdr), 1, fp) != 1) { + die("Cannot read ELF header: %s\n", + strerror(errno)); + } + if (memcmp(ehdr.e_ident, ELFMAG, 4) != 0) { + die("No ELF magic\n"); + } + if (ehdr.e_ident[EI_CLASS] != ELFCLASS32) { + die("Not a 32 bit executable\n"); + } + if (ehdr.e_ident[EI_DATA] != ELFDATA2LSB) { + die("Not a LSB ELF executable\n"); + } + if (ehdr.e_ident[EI_VERSION] != EV_CURRENT) { + die("Unknown ELF version\n"); + } + /* Convert the fields to native endian */ + ehdr.e_type = elf16_to_cpu(ehdr.e_type); + ehdr.e_machine = elf16_to_cpu(ehdr.e_machine); + ehdr.e_version = elf32_to_cpu(ehdr.e_version); + ehdr.e_entry = elf32_to_cpu(ehdr.e_entry); + ehdr.e_phoff = elf32_to_cpu(ehdr.e_phoff); + ehdr.e_shoff = elf32_to_cpu(ehdr.e_shoff); + ehdr.e_flags = elf32_to_cpu(ehdr.e_flags); + ehdr.e_ehsize = elf16_to_cpu(ehdr.e_ehsize); + ehdr.e_phentsize = elf16_to_cpu(ehdr.e_phentsize); + ehdr.e_phnum = elf16_to_cpu(ehdr.e_phnum); + ehdr.e_shentsize = elf16_to_cpu(ehdr.e_shentsize); + ehdr.e_shnum = elf16_to_cpu(ehdr.e_shnum); + ehdr.e_shstrndx = elf16_to_cpu(ehdr.e_shstrndx); + + if ((ehdr.e_type != ET_EXEC) && (ehdr.e_type != ET_DYN)) { + die("Unsupported ELF header type\n"); + } + if (ehdr.e_machine != EM_386) { + die("Not for x86\n"); + } + if (ehdr.e_version != EV_CURRENT) { + die("Unknown ELF version\n"); + } + if (ehdr.e_ehsize != sizeof(Elf32_Ehdr)) { + die("Bad Elf header size\n"); + } + if (ehdr.e_phentsize != sizeof(Elf32_Phdr)) { + die("Bad program header entry\n"); + } + if (ehdr.e_shentsize != sizeof(Elf32_Shdr)) { + die("Bad section header entry\n"); + } + if (ehdr.e_shstrndx >= ehdr.e_shnum) { + die("String table index out of bounds\n"); + } +} + +static void read_shdrs(FILE *fp) +{ + int i; + if (ehdr.e_shnum > MAX_SHDRS) { + die("%d section headers supported: %d\n", + ehdr.e_shnum, MAX_SHDRS); + } + if (fseek(fp, ehdr.e_shoff, SEEK_SET) < 0) { + die("Seek to %d failed: %s\n", + ehdr.e_shoff, strerror(errno)); + } + if (fread(&shdr, sizeof(shdr[0]), ehdr.e_shnum, fp) != ehdr.e_shnum) { + die("Cannot read ELF section headers: %s\n", + strerror(errno)); + } + for(i = 0; i < ehdr.e_shnum; i++) { + shdr[i].sh_name = elf32_to_cpu(shdr[i].sh_name); + shdr[i].sh_type = elf32_to_cpu(shdr[i].sh_type); + shdr[i].sh_flags = elf32_to_cpu(shdr[i].sh_flags); + shdr[i].sh_addr = elf32_to_cpu(shdr[i].sh_addr); + shdr[i].sh_offset = elf32_to_cpu(shdr[i].sh_offset); + shdr[i].sh_size = elf32_to_cpu(shdr[i].sh_size); + shdr[i].sh_link = elf32_to_cpu(shdr[i].sh_link); + shdr[i].sh_info = elf32_to_cpu(shdr[i].sh_info); + shdr[i].sh_addralign = elf32_to_cpu(shdr[i].sh_addralign); + shdr[i].sh_entsize = elf32_to_cpu(shdr[i].sh_entsize); + } + +} + +static void read_strtabs(FILE *fp) +{ + int i; + for(i = 0; i < ehdr.e_shnum; i++) { + if (shdr[i].sh_type != SHT_STRTAB) { + continue; + } + strtab[i] = malloc(shdr[i].sh_size); + if (!strtab[i]) { + die("malloc of %d bytes for strtab failed\n", + shdr[i].sh_size); + } + if (fseek(fp, shdr[i].sh_offset, SEEK_SET) < 0) { + die("Seek to %d failed: %s\n", + shdr[i].sh_offset, strerror(errno)); + } + if (fread(strtab[i], 1, shdr[i].sh_size, fp) != shdr[i].sh_size) { + die("Cannot read symbol table: %s\n", + strerror(errno)); + } + } +} + +static void read_symtabs(FILE *fp) +{ + int i,j; + for(i = 0; i < ehdr.e_shnum; i++) { + if (shdr[i].sh_type != SHT_SYMTAB) { + continue; + } + symtab[i] = malloc(shdr[i].sh_size); + if (!symtab[i]) { + die("malloc of %d bytes for symtab failed\n", + shdr[i].sh_size); + } + if (fseek(fp, shdr[i].sh_offset, SEEK_SET) < 0) { + die("Seek to %d failed: %s\n", + shdr[i].sh_offset, strerror(errno)); + } + if (fread(symtab[i], 1, shdr[i].sh_size, fp) != shdr[i].sh_size) { + die("Cannot read symbol table: %s\n", + strerror(errno)); + } + for(j = 0; j < shdr[i].sh_size/sizeof(symtab[i][0]); j++) { + symtab[i][j].st_name = elf32_to_cpu(symtab[i][j].st_name); + symtab[i][j].st_value = elf32_to_cpu(symtab[i][j].st_value); + symtab[i][j].st_size = elf32_to_cpu(symtab[i][j].st_size); + symtab[i][j].st_shndx = elf16_to_cpu(symtab[i][j].st_shndx); + } + } +} + + +static void read_relocs(FILE *fp) +{ + int i,j; + for(i = 0; i < ehdr.e_shnum; i++) { + if (shdr[i].sh_type != SHT_REL) { + continue; + } + reltab[i] = malloc(shdr[i].sh_size); + if (!reltab[i]) { + die("malloc of %d bytes for relocs failed\n", + shdr[i].sh_size); + } + if (fseek(fp, shdr[i].sh_offset, SEEK_SET) < 0) { + die("Seek to %d failed: %s\n", + shdr[i].sh_offset, strerror(errno)); + } + if (fread(reltab[i], 1, shdr[i].sh_size, fp) != shdr[i].sh_size) { + die("Cannot read symbol table: %s\n", + strerror(errno)); + } + for(j = 0; j < shdr[i].sh_size/sizeof(reltab[0][0]); j++) { + reltab[i][j].r_offset = elf32_to_cpu(reltab[i][j].r_offset); + reltab[i][j].r_info = elf32_to_cpu(reltab[i][j].r_info); + } + } +} + + +static void print_absolute_symbols(void) +{ + int i; + printf("Absolute symbols\n"); + printf(" Num: Value Size Type Bind Visibility Name\n"); + for(i = 0; i < ehdr.e_shnum; i++) { + char *sym_strtab; + Elf32_Sym *sh_symtab; + int j; + if (shdr[i].sh_type != SHT_SYMTAB) { + continue; + } + sh_symtab = symtab[i]; + sym_strtab = strtab[shdr[i].sh_link]; + for(j = 0; j < shdr[i].sh_size/sizeof(symtab[0][0]); j++) { + Elf32_Sym *sym; + const char *name; + sym = &symtab[i][j]; + name = sym_name(sym_strtab, sym); + if (sym->st_shndx != SHN_ABS) { + continue; + } + printf("%5d %08x %5d %10s %10s %12s %s\n", + j, sym->st_value, sym->st_size, + sym_type(ELF32_ST_TYPE(sym->st_info)), + sym_bind(ELF32_ST_BIND(sym->st_info)), + sym_visibility(ELF32_ST_VISIBILITY(sym->st_other)), + name); + } + } + printf("\n"); +} + +static void print_absolute_relocs(void) +{ + int i, printed = 0; + + for(i = 0; i < ehdr.e_shnum; i++) { + char *sym_strtab; + Elf32_Sym *sh_symtab; + unsigned sec_applies, sec_symtab; + int j; + if (shdr[i].sh_type != SHT_REL) { + continue; + } + sec_symtab = shdr[i].sh_link; + sec_applies = shdr[i].sh_info; + if (!(shdr[sec_applies].sh_flags & SHF_ALLOC)) { + continue; + } + sh_symtab = symtab[sec_symtab]; + sym_strtab = strtab[shdr[sec_symtab].sh_link]; + for(j = 0; j < shdr[i].sh_size/sizeof(reltab[0][0]); j++) { + Elf32_Rel *rel; + Elf32_Sym *sym; + const char *name; + rel = &reltab[i][j]; + sym = &sh_symtab[ELF32_R_SYM(rel->r_info)]; + name = sym_name(sym_strtab, sym); + if (sym->st_shndx != SHN_ABS) { + continue; + } + + /* Absolute symbols are not relocated if bzImage is + * loaded at a non-compiled address. Display a warning + * to user at compile time about the absolute + * relocations present. + * + * User need to audit the code to make sure + * some symbols which should have been section + * relative have not become absolute because of some + * linker optimization or wrong programming usage. + * + * Before warning check if this absolute symbol + * relocation is harmless. + */ + if (is_safe_abs_reloc(name)) + continue; + + if (!printed) { + printf("WARNING: Absolute relocations" + " present\n"); + printf("Offset Info Type Sym.Value " + "Sym.Name\n"); + printed = 1; + } + + printf("%08x %08x %10s %08x %s\n", + rel->r_offset, + rel->r_info, + rel_type(ELF32_R_TYPE(rel->r_info)), + sym->st_value, + name); + } + } + + if (printed) + printf("\n"); +} + +static void walk_relocs(void (*visit)(Elf32_Rel *rel, Elf32_Sym *sym)) +{ + int i; + /* Walk through the relocations */ + for(i = 0; i < ehdr.e_shnum; i++) { + char *sym_strtab; + Elf32_Sym *sh_symtab; + unsigned sec_applies, sec_symtab; + int j; + if (shdr[i].sh_type != SHT_REL) { + continue; + } + sec_symtab = shdr[i].sh_link; + sec_applies = shdr[i].sh_info; + if (!(shdr[sec_applies].sh_flags & SHF_ALLOC)) { + continue; + } + sh_symtab = symtab[sec_symtab]; + sym_strtab = strtab[shdr[sec_symtab].sh_link]; + for(j = 0; j < shdr[i].sh_size/sizeof(reltab[0][0]); j++) { + Elf32_Rel *rel; + Elf32_Sym *sym; + unsigned r_type; + rel = &reltab[i][j]; + sym = &sh_symtab[ELF32_R_SYM(rel->r_info)]; + r_type = ELF32_R_TYPE(rel->r_info); + /* Don't visit relocations to absolute symbols */ + if (sym->st_shndx == SHN_ABS) { + continue; + } + if (r_type == R_386_PC32) { + /* PC relative relocations don't need to be adjusted */ + } + else if (r_type == R_386_32) { + /* Visit relocations that need to be adjusted */ + visit(rel, sym); + } + else { + die("Unsupported relocation type: %d\n", r_type); + } + } + } +} + +static void count_reloc(Elf32_Rel *rel, Elf32_Sym *sym) +{ + reloc_count += 1; +} + +static void collect_reloc(Elf32_Rel *rel, Elf32_Sym *sym) +{ + /* Remember the address that needs to be adjusted. */ + relocs[reloc_idx++] = rel->r_offset; +} + +static int cmp_relocs(const void *va, const void *vb) +{ + const unsigned long *a, *b; + a = va; b = vb; + return (*a == *b)? 0 : (*a > *b)? 1 : -1; +} + +static void emit_relocs(int as_text) +{ + int i; + /* Count how many relocations I have and allocate space for them. */ + reloc_count = 0; + walk_relocs(count_reloc); + relocs = malloc(reloc_count * sizeof(relocs[0])); + if (!relocs) { + die("malloc of %d entries for relocs failed\n", + reloc_count); + } + /* Collect up the relocations */ + reloc_idx = 0; + walk_relocs(collect_reloc); + + /* Order the relocations for more efficient processing */ + qsort(relocs, reloc_count, sizeof(relocs[0]), cmp_relocs); + + /* Print the relocations */ + if (as_text) { + /* Print the relocations in a form suitable that + * gas will like. + */ + printf(".section \".data.reloc\",\"a\"\n"); + printf(".balign 4\n"); + for(i = 0; i < reloc_count; i++) { + printf("\t .long 0x%08lx\n", relocs[i]); + } + printf("\n"); + } + else { + unsigned char buf[4]; + buf[0] = buf[1] = buf[2] = buf[3] = 0; + /* Print a stop */ + printf("%c%c%c%c", buf[0], buf[1], buf[2], buf[3]); + /* Now print each relocation */ + for(i = 0; i < reloc_count; i++) { + buf[0] = (relocs[i] >> 0) & 0xff; + buf[1] = (relocs[i] >> 8) & 0xff; + buf[2] = (relocs[i] >> 16) & 0xff; + buf[3] = (relocs[i] >> 24) & 0xff; + printf("%c%c%c%c", buf[0], buf[1], buf[2], buf[3]); + } + } +} + +static void usage(void) +{ + die("relocs [--abs-syms |--abs-relocs | --text] vmlinux\n"); +} + +int main(int argc, char **argv) +{ + int show_absolute_syms, show_absolute_relocs; + int as_text; + const char *fname; + FILE *fp; + int i; + + show_absolute_syms = 0; + show_absolute_relocs = 0; + as_text = 0; + fname = NULL; + for(i = 1; i < argc; i++) { + char *arg = argv[i]; + if (*arg == '-') { + if (strcmp(argv[1], "--abs-syms") == 0) { + show_absolute_syms = 1; + continue; + } + + if (strcmp(argv[1], "--abs-relocs") == 0) { + show_absolute_relocs = 1; + continue; + } + else if (strcmp(argv[1], "--text") == 0) { + as_text = 1; + continue; + } + } + else if (!fname) { + fname = arg; + continue; + } + usage(); + } + if (!fname) { + usage(); + } + fp = fopen(fname, "r"); + if (!fp) { + die("Cannot open %s: %s\n", + fname, strerror(errno)); + } + read_ehdr(fp); + read_shdrs(fp); + read_strtabs(fp); + read_symtabs(fp); + read_relocs(fp); + if (show_absolute_syms) { + print_absolute_symbols(); + return 0; + } + if (show_absolute_relocs) { + print_absolute_relocs(); + return 0; + } + emit_relocs(as_text); + return 0; +} diff --git a/trunk/arch/i386/boot/compressed/vmlinux.lds b/trunk/arch/i386/boot/compressed/vmlinux.lds new file mode 100644 index 000000000000..cc4854f6c6c1 --- /dev/null +++ b/trunk/arch/i386/boot/compressed/vmlinux.lds @@ -0,0 +1,43 @@ +OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") +OUTPUT_ARCH(i386) +ENTRY(startup_32) +SECTIONS +{ + /* Be careful parts of head.S assume startup_32 is at + * address 0. + */ + . = 0 ; + .text.head : { + _head = . ; + *(.text.head) + _ehead = . ; + } + .data.compressed : { + *(.data.compressed) + } + .text : { + _text = .; /* Text */ + *(.text) + *(.text.*) + _etext = . ; + } + .rodata : { + _rodata = . ; + *(.rodata) /* read-only data */ + *(.rodata.*) + _erodata = . ; + } + .data : { + _data = . ; + *(.data) + *(.data.*) + _edata = . ; + } + .bss : { + _bss = . ; + *(.bss) + *(.bss.*) + *(COMMON) + _end = . ; + } +} diff --git a/trunk/arch/i386/boot/compressed/vmlinux.scr b/trunk/arch/i386/boot/compressed/vmlinux.scr index 1ed9d791f863..707a88f7f29e 100644 --- a/trunk/arch/i386/boot/compressed/vmlinux.scr +++ b/trunk/arch/i386/boot/compressed/vmlinux.scr @@ -1,9 +1,10 @@ SECTIONS { - .data : { + .data.compressed : { input_len = .; LONG(input_data_end - input_data) input_data = .; *(.data) + output_len = . - 4; input_data_end = .; } } diff --git a/trunk/arch/i386/boot/setup.S b/trunk/arch/i386/boot/setup.S index 3aec4538a113..06edf1c66242 100644 --- a/trunk/arch/i386/boot/setup.S +++ b/trunk/arch/i386/boot/setup.S @@ -81,7 +81,7 @@ start: # This is the setup header, and it must start at %cs:2 (old 0x9020:2) .ascii "HdrS" # header signature - .word 0x0204 # header version number (>= 0x0105) + .word 0x0205 # header version number (>= 0x0105) # or else old loadlin-1.5 will fail) realmode_swtch: .word 0, 0 # default_switch, SETUPSEG start_sys_seg: .word SYSSEG @@ -160,6 +160,17 @@ ramdisk_max: .long (-__PAGE_OFFSET-(512 << 20)-1) & 0x7fffffff # The highest safe address for # the contents of an initrd +kernel_alignment: .long CONFIG_PHYSICAL_ALIGN #physical addr alignment + #required for protected mode + #kernel +#ifdef CONFIG_RELOCATABLE +relocatable_kernel: .byte 1 +#else +relocatable_kernel: .byte 0 +#endif +pad2: .byte 0 +pad3: .word 0 + trampoline: call start_of_setup .align 16 # The offset at this point is 0x240 @@ -588,11 +599,6 @@ rmodeswtch_normal: call default_switch rmodeswtch_end: -# we get the code32 start address and modify the below 'jmpi' -# (loader may have changed it) - movl %cs:code32_start, %eax - movl %eax, %cs:code32 - # Now we move the system to its rightful place ... but we check if we have a # big-kernel. In that case we *must* not move it ... testb $LOADED_HIGH, %cs:loadflags @@ -788,11 +794,12 @@ a20_err_msg: a20_done: #endif /* CONFIG_X86_VOYAGER */ -# set up gdt and idt +# set up gdt and idt and 32bit start address lidt idt_48 # load idt with 0,0 xorl %eax, %eax # Compute gdt_base movw %ds, %ax # (Convert %ds:gdt to a linear ptr) shll $4, %eax + addl %eax, code32 addl $gdt, %eax movl %eax, (gdt_48+2) lgdt gdt_48 # load gdt with whatever is @@ -851,9 +858,26 @@ flush_instr: # Manual, Mixing 16-bit and 32-bit code, page 16-6) .byte 0x66, 0xea # prefix + jmpi-opcode -code32: .long 0x1000 # will be set to 0x100000 - # for big kernels +code32: .long startup_32 # will be set to %cs+startup_32 .word __BOOT_CS +.code32 +startup_32: + movl $(__BOOT_DS), %eax + movl %eax, %ds + movl %eax, %es + movl %eax, %fs + movl %eax, %gs + movl %eax, %ss + + xorl %eax, %eax +1: incl %eax # check that A20 really IS enabled + movl %eax, 0x00000000 # loop forever if it isn't + cmpl %eax, 0x00100000 + je 1b + + # Jump to the 32bit entry point + jmpl *(code32_start - start + (DELTA_INITSEG << 4))(%esi) +.code16 # Here's a bunch of information about your current kernel.. kernel_version: .ascii UTS_RELEASE diff --git a/trunk/arch/i386/defconfig b/trunk/arch/i386/defconfig index 97aacd6bd7d8..65891f11aced 100644 --- a/trunk/arch/i386/defconfig +++ b/trunk/arch/i386/defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.19-rc2-git4 -# Sat Oct 21 03:38:56 2006 +# Linux kernel version: 2.6.19-git7 +# Wed Dec 6 23:50:49 2006 # CONFIG_X86_32=y CONFIG_GENERIC_TIME=y @@ -40,13 +40,14 @@ CONFIG_POSIX_MQUEUE=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y # CONFIG_CPUSETS is not set +CONFIG_SYSFS_DEPRECATED=y # CONFIG_RELAY is not set CONFIG_INITRAMFS_SOURCE="" CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_SYSCTL=y # CONFIG_EMBEDDED is not set CONFIG_UID16=y -# CONFIG_SYSCTL_SYSCALL is not set +CONFIG_SYSCTL_SYSCALL=y CONFIG_KALLSYMS=y CONFIG_KALLSYMS_ALL=y # CONFIG_KALLSYMS_EXTRA_PASS is not set @@ -110,6 +111,7 @@ CONFIG_SMP=y # CONFIG_X86_VISWS is not set CONFIG_X86_GENERICARCH=y # CONFIG_X86_ES7000 is not set +# CONFIG_PARAVIRT is not set CONFIG_X86_CYCLONE_TIMER=y # CONFIG_M386 is not set # CONFIG_M486 is not set @@ -120,6 +122,7 @@ CONFIG_X86_CYCLONE_TIMER=y # CONFIG_MPENTIUMII is not set CONFIG_MPENTIUMIII=y # CONFIG_MPENTIUMM is not set +# CONFIG_MCORE2 is not set # CONFIG_MPENTIUM4 is not set # CONFIG_MK6 is not set # CONFIG_MK7 is not set @@ -197,7 +200,6 @@ CONFIG_RESOURCES_64BIT=y CONFIG_MTRR=y # CONFIG_EFI is not set # CONFIG_IRQBALANCE is not set -CONFIG_REGPARM=y CONFIG_SECCOMP=y # CONFIG_HZ_100 is not set CONFIG_HZ_250=y @@ -205,7 +207,8 @@ CONFIG_HZ_250=y CONFIG_HZ=250 # CONFIG_KEXEC is not set # CONFIG_CRASH_DUMP is not set -CONFIG_PHYSICAL_START=0x100000 +# CONFIG_RELOCATABLE is not set +CONFIG_PHYSICAL_ALIGN=0x100000 # CONFIG_HOTPLUG_CPU is not set CONFIG_COMPAT_VDSO=y CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y @@ -367,6 +370,7 @@ CONFIG_INET_TCP_DIAG=y # CONFIG_TCP_CONG_ADVANCED is not set CONFIG_TCP_CONG_CUBIC=y CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set CONFIG_IPV6=y # CONFIG_IPV6_PRIVACY is not set # CONFIG_IPV6_ROUTER_PREF is not set @@ -677,6 +681,7 @@ CONFIG_SATA_INTEL_COMBINED=y # CONFIG_PATA_IT821X is not set # CONFIG_PATA_JMICRON is not set # CONFIG_PATA_TRIFLEX is not set +# CONFIG_PATA_MARVELL is not set # CONFIG_PATA_MPIIX is not set # CONFIG_PATA_OLDPIIX is not set # CONFIG_PATA_NETCELL is not set @@ -850,6 +855,7 @@ CONFIG_BNX2=y # CONFIG_IXGB is not set # CONFIG_S2IO is not set # CONFIG_MYRI10GE is not set +# CONFIG_NETXEN_NIC is not set # # Token Ring devices @@ -984,10 +990,6 @@ CONFIG_RTC=y # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set # CONFIG_SONYPI is not set - -# -# Ftape, the floppy tape device driver -# CONFIG_AGP=y # CONFIG_AGP_ALI is not set # CONFIG_AGP_ATI is not set @@ -1108,6 +1110,7 @@ CONFIG_USB_DEVICEFS=y # CONFIG_USB_BANDWIDTH is not set # CONFIG_USB_DYNAMIC_MINORS is not set # CONFIG_USB_SUSPEND is not set +# CONFIG_USB_MULTITHREAD_PROBE is not set # CONFIG_USB_OTG is not set # @@ -1185,6 +1188,7 @@ CONFIG_USB_HIDINPUT=y # CONFIG_USB_KAWETH is not set # CONFIG_USB_PEGASUS is not set # CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET_MII is not set # CONFIG_USB_USBNET is not set CONFIG_USB_MON=y diff --git a/trunk/arch/i386/kernel/Makefile b/trunk/arch/i386/kernel/Makefile index 1a884b6e6e5c..1e8988e558c5 100644 --- a/trunk/arch/i386/kernel/Makefile +++ b/trunk/arch/i386/kernel/Makefile @@ -6,7 +6,7 @@ extra-y := head.o init_task.o vmlinux.lds obj-y := process.o signal.o entry.o traps.o irq.o \ ptrace.o time.o ioport.o ldt.o setup.o i8259.o sys_i386.o \ - pci-dma.o i386_ksyms.o i387.o bootflag.o \ + pci-dma.o i386_ksyms.o i387.o bootflag.o e820.o\ quirks.o i8237.o topology.o alternative.o i8253.o tsc.o obj-$(CONFIG_STACKTRACE) += stacktrace.o @@ -40,6 +40,9 @@ obj-$(CONFIG_EARLY_PRINTK) += early_printk.o obj-$(CONFIG_HPET_TIMER) += hpet.o obj-$(CONFIG_K8_NB) += k8.o +# Make sure this is linked after any other paravirt_ops structs: see head.S +obj-$(CONFIG_PARAVIRT) += paravirt.o + EXTRA_AFLAGS := -traditional obj-$(CONFIG_SCx200) += scx200.o diff --git a/trunk/arch/i386/kernel/acpi/cstate.c b/trunk/arch/i386/kernel/acpi/cstate.c index 4664b55f623e..12e937c1ce4b 100644 --- a/trunk/arch/i386/kernel/acpi/cstate.c +++ b/trunk/arch/i386/kernel/acpi/cstate.c @@ -156,10 +156,8 @@ static int __init ffh_cstate_init(void) static void __exit ffh_cstate_exit(void) { - if (cpu_cstate_entry) { - free_percpu(cpu_cstate_entry); - cpu_cstate_entry = NULL; - } + free_percpu(cpu_cstate_entry); + cpu_cstate_entry = NULL; } arch_initcall(ffh_cstate_init); diff --git a/trunk/arch/i386/kernel/acpi/earlyquirk.c b/trunk/arch/i386/kernel/acpi/earlyquirk.c index c9841692bb7c..4b60af7f91dd 100644 --- a/trunk/arch/i386/kernel/acpi/earlyquirk.c +++ b/trunk/arch/i386/kernel/acpi/earlyquirk.c @@ -10,6 +10,7 @@ #include #include #include +#include #ifdef CONFIG_ACPI @@ -49,6 +50,24 @@ static int __init check_bridge(int vendor, int device) return 0; } +static void check_intel(void) +{ + u16 vendor, device; + + vendor = read_pci_config_16(0, 0, 0, PCI_VENDOR_ID); + + if (vendor != PCI_VENDOR_ID_INTEL) + return; + + device = read_pci_config_16(0, 0, 0, PCI_DEVICE_ID); +#ifdef CONFIG_SMP + if (device == PCI_DEVICE_ID_INTEL_E7320_MCH || + device == PCI_DEVICE_ID_INTEL_E7520_MCH || + device == PCI_DEVICE_ID_INTEL_E7525_MCH) + quirk_intel_irqbalance(); +#endif +} + void __init check_acpi_pci(void) { int num, slot, func; @@ -60,6 +79,8 @@ void __init check_acpi_pci(void) if (!early_pci_allowed()) return; + check_intel(); + /* Poor man's PCI discovery */ for (num = 0; num < 32; num++) { for (slot = 0; slot < 32; slot++) { diff --git a/trunk/arch/i386/kernel/alternative.c b/trunk/arch/i386/kernel/alternative.c index 535f9794fba1..9eca21b49f6b 100644 --- a/trunk/arch/i386/kernel/alternative.c +++ b/trunk/arch/i386/kernel/alternative.c @@ -124,6 +124,20 @@ static unsigned char** find_nop_table(void) #endif /* CONFIG_X86_64 */ +static void nop_out(void *insns, unsigned int len) +{ + unsigned char **noptable = find_nop_table(); + + while (len > 0) { + unsigned int noplen = len; + if (noplen > ASM_NOP_MAX) + noplen = ASM_NOP_MAX; + memcpy(insns, noptable[noplen], noplen); + insns += noplen; + len -= noplen; + } +} + extern struct alt_instr __alt_instructions[], __alt_instructions_end[]; extern struct alt_instr __smp_alt_instructions[], __smp_alt_instructions_end[]; extern u8 *__smp_locks[], *__smp_locks_end[]; @@ -138,10 +152,9 @@ extern u8 __smp_alt_begin[], __smp_alt_end[]; void apply_alternatives(struct alt_instr *start, struct alt_instr *end) { - unsigned char **noptable = find_nop_table(); struct alt_instr *a; u8 *instr; - int diff, i, k; + int diff; DPRINTK("%s: alt table %p -> %p\n", __FUNCTION__, start, end); for (a = start; a < end; a++) { @@ -159,13 +172,7 @@ void apply_alternatives(struct alt_instr *start, struct alt_instr *end) #endif memcpy(instr, a->replacement, a->replacementlen); diff = a->instrlen - a->replacementlen; - /* Pad the rest with nops */ - for (i = a->replacementlen; diff > 0; diff -= k, i += k) { - k = diff; - if (k > ASM_NOP_MAX) - k = ASM_NOP_MAX; - memcpy(a->instr + i, noptable[k], k); - } + nop_out(instr + a->replacementlen, diff); } } @@ -209,7 +216,6 @@ static void alternatives_smp_lock(u8 **start, u8 **end, u8 *text, u8 *text_end) static void alternatives_smp_unlock(u8 **start, u8 **end, u8 *text, u8 *text_end) { - unsigned char **noptable = find_nop_table(); u8 **ptr; for (ptr = start; ptr < end; ptr++) { @@ -217,7 +223,7 @@ static void alternatives_smp_unlock(u8 **start, u8 **end, u8 *text, u8 *text_end continue; if (*ptr > text_end) continue; - **ptr = noptable[1][0]; + nop_out(*ptr, 1); }; } @@ -343,6 +349,40 @@ void alternatives_smp_switch(int smp) #endif +#ifdef CONFIG_PARAVIRT +void apply_paravirt(struct paravirt_patch *start, struct paravirt_patch *end) +{ + struct paravirt_patch *p; + + for (p = start; p < end; p++) { + unsigned int used; + + used = paravirt_ops.patch(p->instrtype, p->clobbers, p->instr, + p->len); +#ifdef CONFIG_DEBUG_PARAVIRT + { + int i; + /* Deliberately clobber regs using "not %reg" to find bugs. */ + for (i = 0; i < 3; i++) { + if (p->len - used >= 2 && (p->clobbers & (1 << i))) { + memcpy(p->instr + used, "\xf7\xd0", 2); + p->instr[used+1] |= i; + used += 2; + } + } + } +#endif + /* Pad the rest with nops */ + nop_out(p->instr + used, p->len - used); + } + + /* Sync to be conservative, in case we patched following instructions */ + sync_core(); +} +extern struct paravirt_patch __start_parainstructions[], + __stop_parainstructions[]; +#endif /* CONFIG_PARAVIRT */ + void __init alternative_instructions(void) { unsigned long flags; @@ -390,5 +430,6 @@ void __init alternative_instructions(void) alternatives_smp_switch(0); } #endif + apply_paravirt(__start_parainstructions, __stop_parainstructions); local_irq_restore(flags); } diff --git a/trunk/arch/i386/kernel/apic.c b/trunk/arch/i386/kernel/apic.c index 2fd4b7d927c2..776d9be26af9 100644 --- a/trunk/arch/i386/kernel/apic.c +++ b/trunk/arch/i386/kernel/apic.c @@ -647,23 +647,30 @@ static struct { static int lapic_suspend(struct sys_device *dev, pm_message_t state) { unsigned long flags; + int maxlvt; if (!apic_pm_state.active) return 0; + maxlvt = get_maxlvt(); + apic_pm_state.apic_id = apic_read(APIC_ID); apic_pm_state.apic_taskpri = apic_read(APIC_TASKPRI); apic_pm_state.apic_ldr = apic_read(APIC_LDR); apic_pm_state.apic_dfr = apic_read(APIC_DFR); apic_pm_state.apic_spiv = apic_read(APIC_SPIV); apic_pm_state.apic_lvtt = apic_read(APIC_LVTT); - apic_pm_state.apic_lvtpc = apic_read(APIC_LVTPC); + if (maxlvt >= 4) + apic_pm_state.apic_lvtpc = apic_read(APIC_LVTPC); apic_pm_state.apic_lvt0 = apic_read(APIC_LVT0); apic_pm_state.apic_lvt1 = apic_read(APIC_LVT1); apic_pm_state.apic_lvterr = apic_read(APIC_LVTERR); apic_pm_state.apic_tmict = apic_read(APIC_TMICT); apic_pm_state.apic_tdcr = apic_read(APIC_TDCR); - apic_pm_state.apic_thmr = apic_read(APIC_LVTTHMR); +#ifdef CONFIG_X86_MCE_P4THERMAL + if (maxlvt >= 5) + apic_pm_state.apic_thmr = apic_read(APIC_LVTTHMR); +#endif local_irq_save(flags); disable_local_APIC(); @@ -675,10 +682,13 @@ static int lapic_resume(struct sys_device *dev) { unsigned int l, h; unsigned long flags; + int maxlvt; if (!apic_pm_state.active) return 0; + maxlvt = get_maxlvt(); + local_irq_save(flags); /* @@ -700,8 +710,12 @@ static int lapic_resume(struct sys_device *dev) apic_write(APIC_SPIV, apic_pm_state.apic_spiv); apic_write(APIC_LVT0, apic_pm_state.apic_lvt0); apic_write(APIC_LVT1, apic_pm_state.apic_lvt1); - apic_write(APIC_LVTTHMR, apic_pm_state.apic_thmr); - apic_write(APIC_LVTPC, apic_pm_state.apic_lvtpc); +#ifdef CONFIG_X86_MCE_P4THERMAL + if (maxlvt >= 5) + apic_write(APIC_LVTTHMR, apic_pm_state.apic_thmr); +#endif + if (maxlvt >= 4) + apic_write(APIC_LVTPC, apic_pm_state.apic_lvtpc); apic_write(APIC_LVTT, apic_pm_state.apic_lvtt); apic_write(APIC_TDCR, apic_pm_state.apic_tdcr); apic_write(APIC_TMICT, apic_pm_state.apic_tmict); diff --git a/trunk/arch/i386/kernel/apm.c b/trunk/arch/i386/kernel/apm.c index a60358fe9a49..a97847da9ed5 100644 --- a/trunk/arch/i386/kernel/apm.c +++ b/trunk/arch/i386/kernel/apm.c @@ -231,6 +231,7 @@ #include #include #include +#include #include "io_ports.h" @@ -2235,7 +2236,7 @@ static int __init apm_init(void) dmi_check_system(apm_dmi_table); - if (apm_info.bios.version == 0) { + if (apm_info.bios.version == 0 || paravirt_enabled()) { printk(KERN_INFO "apm: BIOS not found.\n"); return -ENODEV; } diff --git a/trunk/arch/i386/kernel/asm-offsets.c b/trunk/arch/i386/kernel/asm-offsets.c index c80271f8f084..1b2f3cd33270 100644 --- a/trunk/arch/i386/kernel/asm-offsets.c +++ b/trunk/arch/i386/kernel/asm-offsets.c @@ -15,6 +15,7 @@ #include #include #include +#include #define DEFINE(sym, val) \ asm volatile("\n->" #sym " %0 " #val : : "i" (val)) @@ -51,13 +52,35 @@ void foo(void) OFFSET(TI_exec_domain, thread_info, exec_domain); OFFSET(TI_flags, thread_info, flags); OFFSET(TI_status, thread_info, status); - OFFSET(TI_cpu, thread_info, cpu); OFFSET(TI_preempt_count, thread_info, preempt_count); OFFSET(TI_addr_limit, thread_info, addr_limit); OFFSET(TI_restart_block, thread_info, restart_block); OFFSET(TI_sysenter_return, thread_info, sysenter_return); BLANK(); + OFFSET(GDS_size, Xgt_desc_struct, size); + OFFSET(GDS_address, Xgt_desc_struct, address); + OFFSET(GDS_pad, Xgt_desc_struct, pad); + BLANK(); + + OFFSET(PT_EBX, pt_regs, ebx); + OFFSET(PT_ECX, pt_regs, ecx); + OFFSET(PT_EDX, pt_regs, edx); + OFFSET(PT_ESI, pt_regs, esi); + OFFSET(PT_EDI, pt_regs, edi); + OFFSET(PT_EBP, pt_regs, ebp); + OFFSET(PT_EAX, pt_regs, eax); + OFFSET(PT_DS, pt_regs, xds); + OFFSET(PT_ES, pt_regs, xes); + OFFSET(PT_GS, pt_regs, xgs); + OFFSET(PT_ORIG_EAX, pt_regs, orig_eax); + OFFSET(PT_EIP, pt_regs, eip); + OFFSET(PT_CS, pt_regs, xcs); + OFFSET(PT_EFLAGS, pt_regs, eflags); + OFFSET(PT_OLDESP, pt_regs, esp); + OFFSET(PT_OLDSS, pt_regs, xss); + BLANK(); + OFFSET(EXEC_DOMAIN_handler, exec_domain, handler); OFFSET(RT_SIGFRAME_sigcontext, rt_sigframe, uc.uc_mcontext); BLANK(); @@ -74,4 +97,18 @@ void foo(void) DEFINE(VDSO_PRELINK, VDSO_PRELINK); OFFSET(crypto_tfm_ctx_offset, crypto_tfm, __crt_ctx); + + BLANK(); + OFFSET(PDA_cpu, i386_pda, cpu_number); + OFFSET(PDA_pcurrent, i386_pda, pcurrent); + +#ifdef CONFIG_PARAVIRT + BLANK(); + OFFSET(PARAVIRT_enabled, paravirt_ops, paravirt_enabled); + OFFSET(PARAVIRT_irq_disable, paravirt_ops, irq_disable); + OFFSET(PARAVIRT_irq_enable, paravirt_ops, irq_enable); + OFFSET(PARAVIRT_irq_enable_sysexit, paravirt_ops, irq_enable_sysexit); + OFFSET(PARAVIRT_iret, paravirt_ops, iret); + OFFSET(PARAVIRT_read_cr0, paravirt_ops, read_cr0); +#endif } diff --git a/trunk/arch/i386/kernel/cpu/amd.c b/trunk/arch/i386/kernel/cpu/amd.c index e4758095d87a..41cfea57232b 100644 --- a/trunk/arch/i386/kernel/cpu/amd.c +++ b/trunk/arch/i386/kernel/cpu/amd.c @@ -104,10 +104,7 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c) f_vide(); rdtscl(d2); d = d2-d; - - /* Knock these two lines out if it debugs out ok */ - printk(KERN_INFO "AMD K6 stepping B detected - "); - /* -- cut here -- */ + if (d > 20*K6_BUG_LOOP) printk("system stability may be impaired when more than 32 MB are used.\n"); else diff --git a/trunk/arch/i386/kernel/cpu/common.c b/trunk/arch/i386/kernel/cpu/common.c index d9f3e3c31f05..1b34c56f8123 100644 --- a/trunk/arch/i386/kernel/cpu/common.c +++ b/trunk/arch/i386/kernel/cpu/common.c @@ -18,14 +18,15 @@ #include #include #endif +#include #include "cpu.h" DEFINE_PER_CPU(struct Xgt_desc_struct, cpu_gdt_descr); EXPORT_PER_CPU_SYMBOL(cpu_gdt_descr); -DEFINE_PER_CPU(unsigned char, cpu_16bit_stack[CPU_16BIT_STACK_SIZE]); -EXPORT_PER_CPU_SYMBOL(cpu_16bit_stack); +struct i386_pda *_cpu_pda[NR_CPUS] __read_mostly; +EXPORT_SYMBOL(_cpu_pda); static int cachesize_override __cpuinitdata = -1; static int disable_x86_fxsr __cpuinitdata; @@ -235,29 +236,14 @@ static int __cpuinit have_cpuid_p(void) return flag_is_changeable_p(X86_EFLAGS_ID); } -/* Do minimum CPU detection early. - Fields really needed: vendor, cpuid_level, family, model, mask, cache alignment. - The others are not touched to avoid unwanted side effects. - - WARNING: this function is only called on the BP. Don't add code here - that is supposed to run on all CPUs. */ -static void __init early_cpu_detect(void) +void __init cpu_detect(struct cpuinfo_x86 *c) { - struct cpuinfo_x86 *c = &boot_cpu_data; - - c->x86_cache_alignment = 32; - - if (!have_cpuid_p()) - return; - /* Get vendor name */ cpuid(0x00000000, &c->cpuid_level, (int *)&c->x86_vendor_id[0], (int *)&c->x86_vendor_id[8], (int *)&c->x86_vendor_id[4]); - get_cpu_vendor(c, 1); - c->x86 = 4; if (c->cpuid_level >= 0x00000001) { u32 junk, tfms, cap0, misc; @@ -274,6 +260,26 @@ static void __init early_cpu_detect(void) } } +/* Do minimum CPU detection early. + Fields really needed: vendor, cpuid_level, family, model, mask, cache alignment. + The others are not touched to avoid unwanted side effects. + + WARNING: this function is only called on the BP. Don't add code here + that is supposed to run on all CPUs. */ +static void __init early_cpu_detect(void) +{ + struct cpuinfo_x86 *c = &boot_cpu_data; + + c->x86_cache_alignment = 32; + + if (!have_cpuid_p()) + return; + + cpu_detect(c); + + get_cpu_vendor(c, 1); +} + static void __cpuinit generic_identify(struct cpuinfo_x86 * c) { u32 tfms, xlvl; @@ -308,6 +314,8 @@ static void __cpuinit generic_identify(struct cpuinfo_x86 * c) #else c->apicid = (ebx >> 24) & 0xFF; #endif + if (c->x86_capability[0] & (1<<19)) + c->x86_clflush_size = ((ebx >> 8) & 0xff) * 8; } else { /* Have CPUID level 0 only - unheard of */ c->x86 = 4; @@ -372,6 +380,7 @@ void __cpuinit identify_cpu(struct cpuinfo_x86 *c) c->x86_vendor_id[0] = '\0'; /* Unset */ c->x86_model_id[0] = '\0'; /* Unset */ c->x86_max_cores = 1; + c->x86_clflush_size = 32; memset(&c->x86_capability, 0, sizeof c->x86_capability); if (!have_cpuid_p()) { @@ -591,42 +600,24 @@ void __init early_cpu_init(void) disable_pse = 1; #endif } -/* - * cpu_init() initializes state that is per-CPU. Some data is already - * initialized (naturally) in the bootstrap process, such as the GDT - * and IDT. We reload them nevertheless, this function acts as a - * 'CPU state barrier', nothing should get across. - */ -void __cpuinit cpu_init(void) + +/* Make sure %gs is initialized properly in idle threads */ +struct pt_regs * __devinit idle_regs(struct pt_regs *regs) { - int cpu = smp_processor_id(); - struct tss_struct * t = &per_cpu(init_tss, cpu); - struct thread_struct *thread = ¤t->thread; - struct desc_struct *gdt; - __u32 stk16_off = (__u32)&per_cpu(cpu_16bit_stack, cpu); - struct Xgt_desc_struct *cpu_gdt_descr = &per_cpu(cpu_gdt_descr, cpu); + memset(regs, 0, sizeof(struct pt_regs)); + regs->xgs = __KERNEL_PDA; + return regs; +} - if (cpu_test_and_set(cpu, cpu_initialized)) { - printk(KERN_WARNING "CPU#%d already initialized!\n", cpu); - for (;;) local_irq_enable(); - } - printk(KERN_INFO "Initializing CPU#%d\n", cpu); +static __cpuinit int alloc_gdt(int cpu) +{ + struct Xgt_desc_struct *cpu_gdt_descr = &per_cpu(cpu_gdt_descr, cpu); + struct desc_struct *gdt; + struct i386_pda *pda; - if (cpu_has_vme || cpu_has_tsc || cpu_has_de) - clear_in_cr4(X86_CR4_VME|X86_CR4_PVI|X86_CR4_TSD|X86_CR4_DE); - if (tsc_disable && cpu_has_tsc) { - printk(KERN_NOTICE "Disabling TSC...\n"); - /**** FIX-HPA: DOES THIS REALLY BELONG HERE? ****/ - clear_bit(X86_FEATURE_TSC, boot_cpu_data.x86_capability); - set_in_cr4(X86_CR4_TSD); - } + gdt = (struct desc_struct *)cpu_gdt_descr->address; + pda = cpu_pda(cpu); - /* The CPU hotplug case */ - if (cpu_gdt_descr->address) { - gdt = (struct desc_struct *)cpu_gdt_descr->address; - memset(gdt, 0, PAGE_SIZE); - goto old_gdt; - } /* * This is a horrible hack to allocate the GDT. The problem * is that cpu_init() is called really early for the boot CPU @@ -634,43 +625,130 @@ void __cpuinit cpu_init(void) * CPUs, when bootmem will have gone away */ if (NODE_DATA(0)->bdata->node_bootmem_map) { - gdt = (struct desc_struct *)alloc_bootmem_pages(PAGE_SIZE); - /* alloc_bootmem_pages panics on failure, so no check */ + BUG_ON(gdt != NULL || pda != NULL); + + gdt = alloc_bootmem_pages(PAGE_SIZE); + pda = alloc_bootmem(sizeof(*pda)); + /* alloc_bootmem(_pages) panics on failure, so no check */ + memset(gdt, 0, PAGE_SIZE); + memset(pda, 0, sizeof(*pda)); } else { - gdt = (struct desc_struct *)get_zeroed_page(GFP_KERNEL); - if (unlikely(!gdt)) { - printk(KERN_CRIT "CPU%d failed to allocate GDT\n", cpu); - for (;;) - local_irq_enable(); + /* GDT and PDA might already have been allocated if + this is a CPU hotplug re-insertion. */ + if (gdt == NULL) + gdt = (struct desc_struct *)get_zeroed_page(GFP_KERNEL); + + if (pda == NULL) + pda = kmalloc_node(sizeof(*pda), GFP_KERNEL, cpu_to_node(cpu)); + + if (unlikely(!gdt || !pda)) { + free_pages((unsigned long)gdt, 0); + kfree(pda); + return 0; } } -old_gdt: + + cpu_gdt_descr->address = (unsigned long)gdt; + cpu_pda(cpu) = pda; + + return 1; +} + +/* Initial PDA used by boot CPU */ +struct i386_pda boot_pda = { + ._pda = &boot_pda, + .cpu_number = 0, + .pcurrent = &init_task, +}; + +static inline void set_kernel_gs(void) +{ + /* Set %gs for this CPU's PDA. Memory clobber is to create a + barrier with respect to any PDA operations, so the compiler + doesn't move any before here. */ + asm volatile ("mov %0, %%gs" : : "r" (__KERNEL_PDA) : "memory"); +} + +/* Initialize the CPU's GDT and PDA. The boot CPU does this for + itself, but secondaries find this done for them. */ +__cpuinit int init_gdt(int cpu, struct task_struct *idle) +{ + struct Xgt_desc_struct *cpu_gdt_descr = &per_cpu(cpu_gdt_descr, cpu); + struct desc_struct *gdt; + struct i386_pda *pda; + + /* For non-boot CPUs, the GDT and PDA should already have been + allocated. */ + if (!alloc_gdt(cpu)) { + printk(KERN_CRIT "CPU%d failed to allocate GDT or PDA\n", cpu); + return 0; + } + + gdt = (struct desc_struct *)cpu_gdt_descr->address; + pda = cpu_pda(cpu); + + BUG_ON(gdt == NULL || pda == NULL); + /* * Initialize the per-CPU GDT with the boot GDT, * and set up the GDT descriptor: */ memcpy(gdt, cpu_gdt_table, GDT_SIZE); + cpu_gdt_descr->size = GDT_SIZE - 1; - /* Set up GDT entry for 16bit stack */ - *(__u64 *)(&gdt[GDT_ENTRY_ESPFIX_SS]) |= - ((((__u64)stk16_off) << 16) & 0x000000ffffff0000ULL) | - ((((__u64)stk16_off) << 32) & 0xff00000000000000ULL) | - (CPU_16BIT_STACK_SIZE - 1); + pack_descriptor((u32 *)&gdt[GDT_ENTRY_PDA].a, + (u32 *)&gdt[GDT_ENTRY_PDA].b, + (unsigned long)pda, sizeof(*pda) - 1, + 0x80 | DESCTYPE_S | 0x2, 0); /* present read-write data segment */ - cpu_gdt_descr->size = GDT_SIZE - 1; - cpu_gdt_descr->address = (unsigned long)gdt; + memset(pda, 0, sizeof(*pda)); + pda->_pda = pda; + pda->cpu_number = cpu; + pda->pcurrent = idle; + + return 1; +} + +/* Common CPU init for both boot and secondary CPUs */ +static void __cpuinit _cpu_init(int cpu, struct task_struct *curr) +{ + struct tss_struct * t = &per_cpu(init_tss, cpu); + struct thread_struct *thread = &curr->thread; + struct Xgt_desc_struct *cpu_gdt_descr = &per_cpu(cpu_gdt_descr, cpu); + /* Reinit these anyway, even if they've already been done (on + the boot CPU, this will transition from the boot gdt+pda to + the real ones). */ load_gdt(cpu_gdt_descr); + set_kernel_gs(); + + if (cpu_test_and_set(cpu, cpu_initialized)) { + printk(KERN_WARNING "CPU#%d already initialized!\n", cpu); + for (;;) local_irq_enable(); + } + + printk(KERN_INFO "Initializing CPU#%d\n", cpu); + + if (cpu_has_vme || cpu_has_tsc || cpu_has_de) + clear_in_cr4(X86_CR4_VME|X86_CR4_PVI|X86_CR4_TSD|X86_CR4_DE); + if (tsc_disable && cpu_has_tsc) { + printk(KERN_NOTICE "Disabling TSC...\n"); + /**** FIX-HPA: DOES THIS REALLY BELONG HERE? ****/ + clear_bit(X86_FEATURE_TSC, boot_cpu_data.x86_capability); + set_in_cr4(X86_CR4_TSD); + } + load_idt(&idt_descr); /* * Set up and load the per-CPU TSS and LDT */ atomic_inc(&init_mm.mm_count); - current->active_mm = &init_mm; - BUG_ON(current->mm); - enter_lazy_tlb(&init_mm, current); + curr->active_mm = &init_mm; + if (curr->mm) + BUG(); + enter_lazy_tlb(&init_mm, curr); load_esp0(t, thread); set_tss_desc(cpu,t); @@ -682,8 +760,8 @@ void __cpuinit cpu_init(void) __set_tss_desc(cpu, GDT_ENTRY_DOUBLEFAULT_TSS, &doublefault_tss); #endif - /* Clear %fs and %gs. */ - asm volatile ("movl %0, %%fs; movl %0, %%gs" : : "r" (0)); + /* Clear %fs. */ + asm volatile ("mov %0, %%fs" : : "r" (0)); /* Clear all 6 debug registers: */ set_debugreg(0, 0); @@ -701,6 +779,37 @@ void __cpuinit cpu_init(void) mxcsr_feature_mask_init(); } +/* Entrypoint to initialize secondary CPU */ +void __cpuinit secondary_cpu_init(void) +{ + int cpu = smp_processor_id(); + struct task_struct *curr = current; + + _cpu_init(cpu, curr); +} + +/* + * cpu_init() initializes state that is per-CPU. Some data is already + * initialized (naturally) in the bootstrap process, such as the GDT + * and IDT. We reload them nevertheless, this function acts as a + * 'CPU state barrier', nothing should get across. + */ +void __cpuinit cpu_init(void) +{ + int cpu = smp_processor_id(); + struct task_struct *curr = current; + + /* Set up the real GDT and PDA, so we can transition from the + boot versions. */ + if (!init_gdt(cpu, curr)) { + /* failed to allocate something; not much we can do... */ + for (;;) + local_irq_enable(); + } + + _cpu_init(cpu, curr); +} + #ifdef CONFIG_HOTPLUG_CPU void __cpuinit cpu_uninit(void) { diff --git a/trunk/arch/i386/kernel/cpu/intel.c b/trunk/arch/i386/kernel/cpu/intel.c index 94a95aa5227e..56fe26584957 100644 --- a/trunk/arch/i386/kernel/cpu/intel.c +++ b/trunk/arch/i386/kernel/cpu/intel.c @@ -107,7 +107,7 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c) * Note that the workaround only should be initialized once... */ c->f00f_bug = 0; - if ( c->x86 == 5 ) { + if (!paravirt_enabled() && c->x86 == 5) { static int f00f_workaround_enabled = 0; c->f00f_bug = 1; @@ -195,8 +195,16 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c) if ((c->x86 == 0xf && c->x86_model >= 0x03) || (c->x86 == 0x6 && c->x86_model >= 0x0e)) set_bit(X86_FEATURE_CONSTANT_TSC, c->x86_capability); -} + if (cpu_has_ds) { + unsigned int l1; + rdmsr(MSR_IA32_MISC_ENABLE, l1, l2); + if (!(l1 & (1<<11))) + set_bit(X86_FEATURE_BTS, c->x86_capability); + if (!(l1 & (1<<12))) + set_bit(X86_FEATURE_PEBS, c->x86_capability); + } +} static unsigned int __cpuinit intel_size_cache(struct cpuinfo_x86 * c, unsigned int size) { diff --git a/trunk/arch/i386/kernel/cpu/intel_cacheinfo.c b/trunk/arch/i386/kernel/cpu/intel_cacheinfo.c index 5c43be47587f..80b4c5d421b1 100644 --- a/trunk/arch/i386/kernel/cpu/intel_cacheinfo.c +++ b/trunk/arch/i386/kernel/cpu/intel_cacheinfo.c @@ -480,12 +480,10 @@ static int __cpuinit detect_cache_attributes(unsigned int cpu) if (num_cache_leaves == 0) return -ENOENT; - cpuid4_info[cpu] = kmalloc( + cpuid4_info[cpu] = kzalloc( sizeof(struct _cpuid4_info) * num_cache_leaves, GFP_KERNEL); if (unlikely(cpuid4_info[cpu] == NULL)) return -ENOMEM; - memset(cpuid4_info[cpu], 0, - sizeof(struct _cpuid4_info) * num_cache_leaves); oldmask = current->cpus_allowed; retval = set_cpus_allowed(current, cpumask_of_cpu(cpu)); @@ -658,17 +656,14 @@ static int __cpuinit cpuid4_cache_sysfs_init(unsigned int cpu) return -ENOENT; /* Allocate all required memory */ - cache_kobject[cpu] = kmalloc(sizeof(struct kobject), GFP_KERNEL); + cache_kobject[cpu] = kzalloc(sizeof(struct kobject), GFP_KERNEL); if (unlikely(cache_kobject[cpu] == NULL)) goto err_out; - memset(cache_kobject[cpu], 0, sizeof(struct kobject)); - index_kobject[cpu] = kmalloc( + index_kobject[cpu] = kzalloc( sizeof(struct _index_kobject ) * num_cache_leaves, GFP_KERNEL); if (unlikely(index_kobject[cpu] == NULL)) goto err_out; - memset(index_kobject[cpu], 0, - sizeof(struct _index_kobject) * num_cache_leaves); return 0; diff --git a/trunk/arch/i386/kernel/cpu/mcheck/non-fatal.c b/trunk/arch/i386/kernel/cpu/mcheck/non-fatal.c index 1f9153ae5b03..6b5d3518a1c0 100644 --- a/trunk/arch/i386/kernel/cpu/mcheck/non-fatal.c +++ b/trunk/arch/i386/kernel/cpu/mcheck/non-fatal.c @@ -51,10 +51,10 @@ static void mce_checkregs (void *info) } } -static void mce_work_fn(void *data); -static DECLARE_WORK(mce_work, mce_work_fn, NULL); +static void mce_work_fn(struct work_struct *work); +static DECLARE_DELAYED_WORK(mce_work, mce_work_fn); -static void mce_work_fn(void *data) +static void mce_work_fn(struct work_struct *work) { on_each_cpu(mce_checkregs, NULL, 1, 1); schedule_delayed_work(&mce_work, MCE_RATE); diff --git a/trunk/arch/i386/kernel/cpu/mcheck/therm_throt.c b/trunk/arch/i386/kernel/cpu/mcheck/therm_throt.c index bad8b4420709..065005c3f168 100644 --- a/trunk/arch/i386/kernel/cpu/mcheck/therm_throt.c +++ b/trunk/arch/i386/kernel/cpu/mcheck/therm_throt.c @@ -116,7 +116,6 @@ static __cpuinit int thermal_throttle_add_dev(struct sys_device *sys_dev) return sysfs_create_group(&sys_dev->kobj, &thermal_throttle_attr_group); } -#ifdef CONFIG_HOTPLUG_CPU static __cpuinit void thermal_throttle_remove_dev(struct sys_device *sys_dev) { return sysfs_remove_group(&sys_dev->kobj, &thermal_throttle_attr_group); @@ -153,7 +152,6 @@ static struct notifier_block thermal_throttle_cpu_notifier = { .notifier_call = thermal_throttle_cpu_callback, }; -#endif /* CONFIG_HOTPLUG_CPU */ static __init int thermal_throttle_init_device(void) { diff --git a/trunk/arch/i386/kernel/cpu/mtrr/Makefile b/trunk/arch/i386/kernel/cpu/mtrr/Makefile index a25b701ab84e..191fc0533649 100644 --- a/trunk/arch/i386/kernel/cpu/mtrr/Makefile +++ b/trunk/arch/i386/kernel/cpu/mtrr/Makefile @@ -1,5 +1,3 @@ obj-y := main.o if.o generic.o state.o -obj-y += amd.o -obj-y += cyrix.o -obj-y += centaur.o +obj-$(CONFIG_X86_32) += amd.o cyrix.o centaur.o diff --git a/trunk/arch/i386/kernel/cpu/mtrr/amd.c b/trunk/arch/i386/kernel/cpu/mtrr/amd.c index 1a1e04b6fd00..0949cdbf848a 100644 --- a/trunk/arch/i386/kernel/cpu/mtrr/amd.c +++ b/trunk/arch/i386/kernel/cpu/mtrr/amd.c @@ -7,7 +7,7 @@ static void amd_get_mtrr(unsigned int reg, unsigned long *base, - unsigned int *size, mtrr_type * type) + unsigned long *size, mtrr_type * type) { unsigned long low, high; diff --git a/trunk/arch/i386/kernel/cpu/mtrr/centaur.c b/trunk/arch/i386/kernel/cpu/mtrr/centaur.c index 33f00ac314ef..cb9aa3a7a7ab 100644 --- a/trunk/arch/i386/kernel/cpu/mtrr/centaur.c +++ b/trunk/arch/i386/kernel/cpu/mtrr/centaur.c @@ -17,7 +17,7 @@ static u8 centaur_mcr_type; /* 0 for winchip, 1 for winchip2 */ */ static int -centaur_get_free_region(unsigned long base, unsigned long size) +centaur_get_free_region(unsigned long base, unsigned long size, int replace_reg) /* [SUMMARY] Get a free MTRR. The starting (base) address of the region. The size (in bytes) of the region. @@ -26,10 +26,11 @@ centaur_get_free_region(unsigned long base, unsigned long size) { int i, max; mtrr_type ltype; - unsigned long lbase; - unsigned int lsize; + unsigned long lbase, lsize; max = num_var_ranges; + if (replace_reg >= 0 && replace_reg < max) + return replace_reg; for (i = 0; i < max; ++i) { if (centaur_mcr_reserved & (1 << i)) continue; @@ -49,7 +50,7 @@ mtrr_centaur_report_mcr(int mcr, u32 lo, u32 hi) static void centaur_get_mcr(unsigned int reg, unsigned long *base, - unsigned int *size, mtrr_type * type) + unsigned long *size, mtrr_type * type) { *base = centaur_mcr[reg].high >> PAGE_SHIFT; *size = -(centaur_mcr[reg].low & 0xfffff000) >> PAGE_SHIFT; diff --git a/trunk/arch/i386/kernel/cpu/mtrr/cyrix.c b/trunk/arch/i386/kernel/cpu/mtrr/cyrix.c index 9027a987006b..0737a596db43 100644 --- a/trunk/arch/i386/kernel/cpu/mtrr/cyrix.c +++ b/trunk/arch/i386/kernel/cpu/mtrr/cyrix.c @@ -9,7 +9,7 @@ int arr3_protected; static void cyrix_get_arr(unsigned int reg, unsigned long *base, - unsigned int *size, mtrr_type * type) + unsigned long *size, mtrr_type * type) { unsigned long flags; unsigned char arr, ccr3, rcr, shift; @@ -77,7 +77,7 @@ cyrix_get_arr(unsigned int reg, unsigned long *base, } static int -cyrix_get_free_region(unsigned long base, unsigned long size) +cyrix_get_free_region(unsigned long base, unsigned long size, int replace_reg) /* [SUMMARY] Get a free ARR. The starting (base) address of the region. The size (in bytes) of the region. @@ -86,9 +86,24 @@ cyrix_get_free_region(unsigned long base, unsigned long size) { int i; mtrr_type ltype; - unsigned long lbase; - unsigned int lsize; + unsigned long lbase, lsize; + switch (replace_reg) { + case 7: + if (size < 0x40) + break; + case 6: + case 5: + case 4: + return replace_reg; + case 3: + if (arr3_protected) + break; + case 2: + case 1: + case 0: + return replace_reg; + } /* If we are to set up a region >32M then look at ARR7 immediately */ if (size > 0x2000) { cyrix_get_arr(7, &lbase, &lsize, <ype); @@ -214,7 +229,7 @@ static void cyrix_set_arr(unsigned int reg, unsigned long base, typedef struct { unsigned long base; - unsigned int size; + unsigned long size; mtrr_type type; } arr_state_t; diff --git a/trunk/arch/i386/kernel/cpu/mtrr/generic.c b/trunk/arch/i386/kernel/cpu/mtrr/generic.c index 0b61eed8bbd8..f77fc53db654 100644 --- a/trunk/arch/i386/kernel/cpu/mtrr/generic.c +++ b/trunk/arch/i386/kernel/cpu/mtrr/generic.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -15,12 +16,19 @@ struct mtrr_state { struct mtrr_var_range *var_ranges; mtrr_type fixed_ranges[NUM_FIXED_RANGES]; unsigned char enabled; + unsigned char have_fixed; mtrr_type def_type; }; static unsigned long smp_changes_mask; static struct mtrr_state mtrr_state = {}; +#undef MODULE_PARAM_PREFIX +#define MODULE_PARAM_PREFIX "mtrr." + +static __initdata int mtrr_show; +module_param_named(show, mtrr_show, bool, 0); + /* Get the MSR pair relating to a var range */ static void __init get_mtrr_var_range(unsigned int index, struct mtrr_var_range *vr) @@ -43,6 +51,14 @@ get_fixed_ranges(mtrr_type * frs) rdmsr(MTRRfix4K_C0000_MSR + i, p[6 + i * 2], p[7 + i * 2]); } +static void __init print_fixed(unsigned base, unsigned step, const mtrr_type*types) +{ + unsigned i; + + for (i = 0; i < 8; ++i, ++types, base += step) + printk(KERN_INFO "MTRR %05X-%05X %s\n", base, base + step - 1, mtrr_attrib_to_str(*types)); +} + /* Grab all of the MTRR state for this CPU into *state */ void __init get_mtrr_state(void) { @@ -58,13 +74,49 @@ void __init get_mtrr_state(void) } vrs = mtrr_state.var_ranges; + rdmsr(MTRRcap_MSR, lo, dummy); + mtrr_state.have_fixed = (lo >> 8) & 1; + for (i = 0; i < num_var_ranges; i++) get_mtrr_var_range(i, &vrs[i]); - get_fixed_ranges(mtrr_state.fixed_ranges); + if (mtrr_state.have_fixed) + get_fixed_ranges(mtrr_state.fixed_ranges); rdmsr(MTRRdefType_MSR, lo, dummy); mtrr_state.def_type = (lo & 0xff); mtrr_state.enabled = (lo & 0xc00) >> 10; + + if (mtrr_show) { + int high_width; + + printk(KERN_INFO "MTRR default type: %s\n", mtrr_attrib_to_str(mtrr_state.def_type)); + if (mtrr_state.have_fixed) { + printk(KERN_INFO "MTRR fixed ranges %sabled:\n", + mtrr_state.enabled & 1 ? "en" : "dis"); + print_fixed(0x00000, 0x10000, mtrr_state.fixed_ranges + 0); + for (i = 0; i < 2; ++i) + print_fixed(0x80000 + i * 0x20000, 0x04000, mtrr_state.fixed_ranges + (i + 1) * 8); + for (i = 0; i < 8; ++i) + print_fixed(0xC0000 + i * 0x08000, 0x01000, mtrr_state.fixed_ranges + (i + 3) * 8); + } + printk(KERN_INFO "MTRR variable ranges %sabled:\n", + mtrr_state.enabled & 2 ? "en" : "dis"); + high_width = ((size_or_mask ? ffs(size_or_mask) - 1 : 32) - (32 - PAGE_SHIFT) + 3) / 4; + for (i = 0; i < num_var_ranges; ++i) { + if (mtrr_state.var_ranges[i].mask_lo & (1 << 11)) + printk(KERN_INFO "MTRR %u base %0*X%05X000 mask %0*X%05X000 %s\n", + i, + high_width, + mtrr_state.var_ranges[i].base_hi, + mtrr_state.var_ranges[i].base_lo >> 12, + high_width, + mtrr_state.var_ranges[i].mask_hi, + mtrr_state.var_ranges[i].mask_lo >> 12, + mtrr_attrib_to_str(mtrr_state.var_ranges[i].base_lo & 0xff)); + else + printk(KERN_INFO "MTRR %u disabled\n", i); + } + } } /* Some BIOS's are fucked and don't set all MTRRs the same! */ @@ -95,7 +147,7 @@ void mtrr_wrmsr(unsigned msr, unsigned a, unsigned b) smp_processor_id(), msr, a, b); } -int generic_get_free_region(unsigned long base, unsigned long size) +int generic_get_free_region(unsigned long base, unsigned long size, int replace_reg) /* [SUMMARY] Get a free MTRR. The starting (base) address of the region. The size (in bytes) of the region. @@ -104,10 +156,11 @@ int generic_get_free_region(unsigned long base, unsigned long size) { int i, max; mtrr_type ltype; - unsigned long lbase; - unsigned lsize; + unsigned long lbase, lsize; max = num_var_ranges; + if (replace_reg >= 0 && replace_reg < max) + return replace_reg; for (i = 0; i < max; ++i) { mtrr_if->get(i, &lbase, &lsize, <ype); if (lsize == 0) @@ -117,7 +170,7 @@ int generic_get_free_region(unsigned long base, unsigned long size) } static void generic_get_mtrr(unsigned int reg, unsigned long *base, - unsigned int *size, mtrr_type * type) + unsigned long *size, mtrr_type *type) { unsigned int mask_lo, mask_hi, base_lo, base_hi; @@ -202,7 +255,9 @@ static int set_mtrr_var_ranges(unsigned int index, struct mtrr_var_range *vr) return changed; } -static unsigned long set_mtrr_state(u32 deftype_lo, u32 deftype_hi) +static u32 deftype_lo, deftype_hi; + +static unsigned long set_mtrr_state(void) /* [SUMMARY] Set the MTRR state for this CPU. The MTRR state information to read. Some relevant CPU context. @@ -217,14 +272,14 @@ static unsigned long set_mtrr_state(u32 deftype_lo, u32 deftype_hi) if (set_mtrr_var_ranges(i, &mtrr_state.var_ranges[i])) change_mask |= MTRR_CHANGE_MASK_VARIABLE; - if (set_fixed_ranges(mtrr_state.fixed_ranges)) + if (mtrr_state.have_fixed && set_fixed_ranges(mtrr_state.fixed_ranges)) change_mask |= MTRR_CHANGE_MASK_FIXED; /* Set_mtrr_restore restores the old value of MTRRdefType, so to set it we fiddle with the saved value */ if ((deftype_lo & 0xff) != mtrr_state.def_type || ((deftype_lo & 0xc00) >> 10) != mtrr_state.enabled) { - deftype_lo |= (mtrr_state.def_type | mtrr_state.enabled << 10); + deftype_lo = (deftype_lo & ~0xcff) | mtrr_state.def_type | (mtrr_state.enabled << 10); change_mask |= MTRR_CHANGE_MASK_DEFTYPE; } @@ -233,7 +288,6 @@ static unsigned long set_mtrr_state(u32 deftype_lo, u32 deftype_hi) static unsigned long cr4 = 0; -static u32 deftype_lo, deftype_hi; static DEFINE_SPINLOCK(set_atomicity_lock); /* @@ -271,7 +325,7 @@ static void prepare_set(void) __acquires(set_atomicity_lock) rdmsr(MTRRdefType_MSR, deftype_lo, deftype_hi); /* Disable MTRRs, and set the default type to uncached */ - mtrr_wrmsr(MTRRdefType_MSR, deftype_lo & 0xf300UL, deftype_hi); + mtrr_wrmsr(MTRRdefType_MSR, deftype_lo & ~0xcff, deftype_hi); } static void post_set(void) __releases(set_atomicity_lock) @@ -300,7 +354,7 @@ static void generic_set_all(void) prepare_set(); /* Actually set the state */ - mask = set_mtrr_state(deftype_lo,deftype_hi); + mask = set_mtrr_state(); post_set(); local_irq_restore(flags); @@ -366,7 +420,7 @@ int generic_validate_add_page(unsigned long base, unsigned long size, unsigned i printk(KERN_WARNING "mtrr: base(0x%lx000) is not 4 MiB aligned\n", base); return -EINVAL; } - if (!(base + size < 0x70000000 || base > 0x7003FFFF) && + if (!(base + size < 0x70000 || base > 0x7003F) && (type == MTRR_TYPE_WRCOMB || type == MTRR_TYPE_WRBACK)) { printk(KERN_WARNING "mtrr: writable mtrr between 0x70000000 and 0x7003FFFF may hang the CPU.\n"); diff --git a/trunk/arch/i386/kernel/cpu/mtrr/if.c b/trunk/arch/i386/kernel/cpu/mtrr/if.c index 5ac051bb9d55..5ae1705eafa6 100644 --- a/trunk/arch/i386/kernel/cpu/mtrr/if.c +++ b/trunk/arch/i386/kernel/cpu/mtrr/if.c @@ -17,7 +17,7 @@ extern unsigned int *usage_table; #define FILE_FCOUNT(f) (((struct seq_file *)((f)->private_data))->private) -static char *mtrr_strings[MTRR_NUM_TYPES] = +static const char *const mtrr_strings[MTRR_NUM_TYPES] = { "uncachable", /* 0 */ "write-combining", /* 1 */ @@ -28,7 +28,7 @@ static char *mtrr_strings[MTRR_NUM_TYPES] = "write-back", /* 6 */ }; -char *mtrr_attrib_to_str(int x) +const char *mtrr_attrib_to_str(int x) { return (x <= 6) ? mtrr_strings[x] : "?"; } @@ -44,10 +44,9 @@ mtrr_file_add(unsigned long base, unsigned long size, max = num_var_ranges; if (fcount == NULL) { - fcount = kmalloc(max * sizeof *fcount, GFP_KERNEL); + fcount = kzalloc(max * sizeof *fcount, GFP_KERNEL); if (!fcount) return -ENOMEM; - memset(fcount, 0, max * sizeof *fcount); FILE_FCOUNT(file) = fcount; } if (!page) { @@ -155,6 +154,7 @@ mtrr_ioctl(struct file *file, unsigned int cmd, unsigned long __arg) { int err = 0; mtrr_type type; + unsigned long size; struct mtrr_sentry sentry; struct mtrr_gentry gentry; void __user *arg = (void __user *) __arg; @@ -235,15 +235,15 @@ mtrr_ioctl(struct file *file, unsigned int cmd, unsigned long __arg) case MTRRIOC_GET_ENTRY: if (gentry.regnum >= num_var_ranges) return -EINVAL; - mtrr_if->get(gentry.regnum, &gentry.base, &gentry.size, &type); + mtrr_if->get(gentry.regnum, &gentry.base, &size, &type); /* Hide entries that go above 4GB */ - if (gentry.base + gentry.size > 0x100000 - || gentry.size == 0x100000) + if (gentry.base + size - 1 >= (1UL << (8 * sizeof(gentry.size) - PAGE_SHIFT)) + || size >= (1UL << (8 * sizeof(gentry.size) - PAGE_SHIFT))) gentry.base = gentry.size = gentry.type = 0; else { gentry.base <<= PAGE_SHIFT; - gentry.size <<= PAGE_SHIFT; + gentry.size = size << PAGE_SHIFT; gentry.type = type; } @@ -273,8 +273,14 @@ mtrr_ioctl(struct file *file, unsigned int cmd, unsigned long __arg) case MTRRIOC_GET_PAGE_ENTRY: if (gentry.regnum >= num_var_ranges) return -EINVAL; - mtrr_if->get(gentry.regnum, &gentry.base, &gentry.size, &type); - gentry.type = type; + mtrr_if->get(gentry.regnum, &gentry.base, &size, &type); + /* Hide entries that would overflow */ + if (size != (__typeof__(gentry.size))size) + gentry.base = gentry.size = gentry.type = 0; + else { + gentry.size = size; + gentry.type = type; + } break; } @@ -353,8 +359,7 @@ static int mtrr_seq_show(struct seq_file *seq, void *offset) char factor; int i, max, len; mtrr_type type; - unsigned long base; - unsigned int size; + unsigned long base, size; len = 0; max = num_var_ranges; @@ -373,7 +378,7 @@ static int mtrr_seq_show(struct seq_file *seq, void *offset) } /* RED-PEN: base can be > 32bit */ len += seq_printf(seq, - "reg%02i: base=0x%05lx000 (%4liMB), size=%4i%cB: %s, count=%d\n", + "reg%02i: base=0x%05lx000 (%4luMB), size=%4lu%cB: %s, count=%d\n", i, base, base >> (20 - PAGE_SHIFT), size, factor, mtrr_attrib_to_str(type), usage_table[i]); } diff --git a/trunk/arch/i386/kernel/cpu/mtrr/main.c b/trunk/arch/i386/kernel/cpu/mtrr/main.c index fff90bda4733..16bb7ea87145 100644 --- a/trunk/arch/i386/kernel/cpu/mtrr/main.c +++ b/trunk/arch/i386/kernel/cpu/mtrr/main.c @@ -59,7 +59,11 @@ struct mtrr_ops * mtrr_if = NULL; static void set_mtrr(unsigned int reg, unsigned long base, unsigned long size, mtrr_type type); +#ifndef CONFIG_X86_64 extern int arr3_protected; +#else +#define arr3_protected 0 +#endif void set_mtrr_ops(struct mtrr_ops * ops) { @@ -168,6 +172,13 @@ static void ipi_handler(void *info) #endif +static inline int types_compatible(mtrr_type type1, mtrr_type type2) { + return type1 == MTRR_TYPE_UNCACHABLE || + type2 == MTRR_TYPE_UNCACHABLE || + (type1 == MTRR_TYPE_WRTHROUGH && type2 == MTRR_TYPE_WRBACK) || + (type1 == MTRR_TYPE_WRBACK && type2 == MTRR_TYPE_WRTHROUGH); +} + /** * set_mtrr - update mtrrs on all processors * @reg: mtrr in question @@ -263,8 +274,8 @@ static void set_mtrr(unsigned int reg, unsigned long base, /** * mtrr_add_page - Add a memory type region - * @base: Physical base address of region in pages (4 KB) - * @size: Physical size of region in pages (4 KB) + * @base: Physical base address of region in pages (in units of 4 kB!) + * @size: Physical size of region in pages (4 kB) * @type: Type of MTRR desired * @increment: If this is true do usage counting on the region * @@ -300,11 +311,9 @@ static void set_mtrr(unsigned int reg, unsigned long base, int mtrr_add_page(unsigned long base, unsigned long size, unsigned int type, char increment) { - int i; + int i, replace, error; mtrr_type ltype; - unsigned long lbase; - unsigned int lsize; - int error; + unsigned long lbase, lsize; if (!mtrr_if) return -ENXIO; @@ -324,12 +333,18 @@ int mtrr_add_page(unsigned long base, unsigned long size, return -ENOSYS; } + if (!size) { + printk(KERN_WARNING "mtrr: zero sized request\n"); + return -EINVAL; + } + if (base & size_or_mask || size & size_or_mask) { printk(KERN_WARNING "mtrr: base or size exceeds the MTRR width\n"); return -EINVAL; } error = -EINVAL; + replace = -1; /* No CPU hotplug when we change MTRR entries */ lock_cpu_hotplug(); @@ -337,21 +352,28 @@ int mtrr_add_page(unsigned long base, unsigned long size, mutex_lock(&mtrr_mutex); for (i = 0; i < num_var_ranges; ++i) { mtrr_if->get(i, &lbase, &lsize, <ype); - if (base >= lbase + lsize) - continue; - if ((base < lbase) && (base + size <= lbase)) + if (!lsize || base > lbase + lsize - 1 || base + size - 1 < lbase) continue; /* At this point we know there is some kind of overlap/enclosure */ - if ((base < lbase) || (base + size > lbase + lsize)) { + if (base < lbase || base + size - 1 > lbase + lsize - 1) { + if (base <= lbase && base + size - 1 >= lbase + lsize - 1) { + /* New region encloses an existing region */ + if (type == ltype) { + replace = replace == -1 ? i : -2; + continue; + } + else if (types_compatible(type, ltype)) + continue; + } printk(KERN_WARNING "mtrr: 0x%lx000,0x%lx000 overlaps existing" - " 0x%lx000,0x%x000\n", base, size, lbase, + " 0x%lx000,0x%lx000\n", base, size, lbase, lsize); goto out; } /* New region is enclosed by an existing region */ if (ltype != type) { - if (type == MTRR_TYPE_UNCACHABLE) + if (types_compatible(type, ltype)) continue; printk (KERN_WARNING "mtrr: type mismatch for %lx000,%lx000 old: %s new: %s\n", base, size, mtrr_attrib_to_str(ltype), @@ -364,10 +386,18 @@ int mtrr_add_page(unsigned long base, unsigned long size, goto out; } /* Search for an empty MTRR */ - i = mtrr_if->get_free_region(base, size); + i = mtrr_if->get_free_region(base, size, replace); if (i >= 0) { set_mtrr(i, base, size, type); - usage_table[i] = 1; + if (likely(replace < 0)) + usage_table[i] = 1; + else { + usage_table[i] = usage_table[replace] + !!increment; + if (unlikely(replace != i)) { + set_mtrr(replace, 0, 0, 0); + usage_table[replace] = 0; + } + } } else printk(KERN_INFO "mtrr: no more MTRRs available\n"); error = i; @@ -455,8 +485,7 @@ int mtrr_del_page(int reg, unsigned long base, unsigned long size) { int i, max; mtrr_type ltype; - unsigned long lbase; - unsigned int lsize; + unsigned long lbase, lsize; int error = -EINVAL; if (!mtrr_if) @@ -544,9 +573,11 @@ extern void centaur_init_mtrr(void); static void __init init_ifs(void) { +#ifndef CONFIG_X86_64 amd_init_mtrr(); cyrix_init_mtrr(); centaur_init_mtrr(); +#endif } /* The suspend/resume methods are only for CPU without MTRR. CPU using generic @@ -555,7 +586,7 @@ static void __init init_ifs(void) struct mtrr_value { mtrr_type ltype; unsigned long lbase; - unsigned int lsize; + unsigned long lsize; }; static struct mtrr_value * mtrr_state; @@ -565,10 +596,8 @@ static int mtrr_save(struct sys_device * sysdev, pm_message_t state) int i; int size = num_var_ranges * sizeof(struct mtrr_value); - mtrr_state = kmalloc(size,GFP_ATOMIC); - if (mtrr_state) - memset(mtrr_state,0,size); - else + mtrr_state = kzalloc(size,GFP_ATOMIC); + if (!mtrr_state) return -ENOMEM; for (i = 0; i < num_var_ranges; i++) { diff --git a/trunk/arch/i386/kernel/cpu/mtrr/mtrr.h b/trunk/arch/i386/kernel/cpu/mtrr/mtrr.h index 99c9f2682041..d61ea9db6cfe 100644 --- a/trunk/arch/i386/kernel/cpu/mtrr/mtrr.h +++ b/trunk/arch/i386/kernel/cpu/mtrr/mtrr.h @@ -43,15 +43,16 @@ struct mtrr_ops { void (*set_all)(void); void (*get)(unsigned int reg, unsigned long *base, - unsigned int *size, mtrr_type * type); - int (*get_free_region) (unsigned long base, unsigned long size); - + unsigned long *size, mtrr_type * type); + int (*get_free_region)(unsigned long base, unsigned long size, + int replace_reg); int (*validate_add_page)(unsigned long base, unsigned long size, unsigned int type); int (*have_wrcomb)(void); }; -extern int generic_get_free_region(unsigned long base, unsigned long size); +extern int generic_get_free_region(unsigned long base, unsigned long size, + int replace_reg); extern int generic_validate_add_page(unsigned long base, unsigned long size, unsigned int type); @@ -62,17 +63,17 @@ extern int positive_have_wrcomb(void); /* library functions for processor-specific routines */ struct set_mtrr_context { unsigned long flags; - unsigned long deftype_lo; - unsigned long deftype_hi; unsigned long cr4val; - unsigned long ccr3; + u32 deftype_lo; + u32 deftype_hi; + u32 ccr3; }; struct mtrr_var_range { - unsigned long base_lo; - unsigned long base_hi; - unsigned long mask_lo; - unsigned long mask_hi; + u32 base_lo; + u32 base_hi; + u32 mask_lo; + u32 mask_hi; }; void set_mtrr_done(struct set_mtrr_context *ctxt); @@ -92,6 +93,6 @@ extern struct mtrr_ops * mtrr_if; extern unsigned int num_var_ranges; void mtrr_state_warn(void); -char *mtrr_attrib_to_str(int x); +const char *mtrr_attrib_to_str(int x); void mtrr_wrmsr(unsigned, unsigned, unsigned); diff --git a/trunk/arch/i386/kernel/cpu/proc.c b/trunk/arch/i386/kernel/cpu/proc.c index 76aac088a323..6624d8583c42 100644 --- a/trunk/arch/i386/kernel/cpu/proc.c +++ b/trunk/arch/i386/kernel/cpu/proc.c @@ -152,9 +152,10 @@ static int show_cpuinfo(struct seq_file *m, void *v) seq_printf(m, " [%d]", i); } - seq_printf(m, "\nbogomips\t: %lu.%02lu\n\n", + seq_printf(m, "\nbogomips\t: %lu.%02lu\n", c->loops_per_jiffy/(500000/HZ), (c->loops_per_jiffy/(5000/HZ)) % 100); + seq_printf(m, "clflush size\t: %u\n\n", c->x86_clflush_size); return 0; } diff --git a/trunk/arch/i386/kernel/cpuid.c b/trunk/arch/i386/kernel/cpuid.c index ab0c327e79dc..51130b39cd2e 100644 --- a/trunk/arch/i386/kernel/cpuid.c +++ b/trunk/arch/i386/kernel/cpuid.c @@ -34,7 +34,6 @@ #include #include #include -#include #include #include #include @@ -117,7 +116,7 @@ static ssize_t cpuid_read(struct file *file, char __user *buf, char __user *tmp = buf; u32 data[4]; u32 reg = *ppos; - int cpu = iminor(file->f_dentry->d_inode); + int cpu = iminor(file->f_path.dentry->d_inode); if (count % 16) return -EINVAL; /* Invalid chunk size */ @@ -135,7 +134,7 @@ static ssize_t cpuid_read(struct file *file, char __user *buf, static int cpuid_open(struct inode *inode, struct file *file) { - unsigned int cpu = iminor(file->f_dentry->d_inode); + unsigned int cpu = iminor(file->f_path.dentry->d_inode); struct cpuinfo_x86 *c = &(cpu_data)[cpu]; if (cpu >= NR_CPUS || !cpu_online(cpu)) @@ -167,7 +166,6 @@ static int cpuid_device_create(int i) return err; } -#ifdef CONFIG_HOTPLUG_CPU static int cpuid_class_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { unsigned int cpu = (unsigned long)hcpu; @@ -187,7 +185,6 @@ static struct notifier_block __cpuinitdata cpuid_class_cpu_notifier = { .notifier_call = cpuid_class_cpu_callback, }; -#endif /* !CONFIG_HOTPLUG_CPU */ static int __init cpuid_init(void) { diff --git a/trunk/arch/i386/kernel/crash.c b/trunk/arch/i386/kernel/crash.c index 144b43288965..a5e0e990ea95 100644 --- a/trunk/arch/i386/kernel/crash.c +++ b/trunk/arch/i386/kernel/crash.c @@ -31,68 +31,6 @@ /* This keeps a track of which one is crashing cpu. */ static int crashing_cpu; -static u32 *append_elf_note(u32 *buf, char *name, unsigned type, void *data, - size_t data_len) -{ - struct elf_note note; - - note.n_namesz = strlen(name) + 1; - note.n_descsz = data_len; - note.n_type = type; - memcpy(buf, ¬e, sizeof(note)); - buf += (sizeof(note) +3)/4; - memcpy(buf, name, note.n_namesz); - buf += (note.n_namesz + 3)/4; - memcpy(buf, data, note.n_descsz); - buf += (note.n_descsz + 3)/4; - - return buf; -} - -static void final_note(u32 *buf) -{ - struct elf_note note; - - note.n_namesz = 0; - note.n_descsz = 0; - note.n_type = 0; - memcpy(buf, ¬e, sizeof(note)); -} - -static void crash_save_this_cpu(struct pt_regs *regs, int cpu) -{ - struct elf_prstatus prstatus; - u32 *buf; - - if ((cpu < 0) || (cpu >= NR_CPUS)) - return; - - /* Using ELF notes here is opportunistic. - * I need a well defined structure format - * for the data I pass, and I need tags - * on the data to indicate what information I have - * squirrelled away. ELF notes happen to provide - * all of that, so there is no need to invent something new. - */ - buf = (u32*)per_cpu_ptr(crash_notes, cpu); - if (!buf) - return; - memset(&prstatus, 0, sizeof(prstatus)); - prstatus.pr_pid = current->pid; - elf_core_copy_regs(&prstatus.pr_reg, regs); - buf = append_elf_note(buf, "CORE", NT_PRSTATUS, &prstatus, - sizeof(prstatus)); - final_note(buf); -} - -static void crash_save_self(struct pt_regs *regs) -{ - int cpu; - - cpu = safe_smp_processor_id(); - crash_save_this_cpu(regs, cpu); -} - #if defined(CONFIG_SMP) && defined(CONFIG_X86_LOCAL_APIC) static atomic_t waiting_for_crash_ipi; @@ -121,7 +59,7 @@ static int crash_nmi_callback(struct notifier_block *self, crash_fixup_ss_esp(&fixed_regs, regs); regs = &fixed_regs; } - crash_save_this_cpu(regs, cpu); + crash_save_cpu(regs, cpu); disable_local_APIC(); atomic_dec(&waiting_for_crash_ipi); /* Assume hlt works */ @@ -195,5 +133,5 @@ void machine_crash_shutdown(struct pt_regs *regs) #if defined(CONFIG_X86_IO_APIC) disable_IO_APIC(); #endif - crash_save_self(regs); + crash_save_cpu(regs, safe_smp_processor_id()); } diff --git a/trunk/arch/i386/kernel/e820.c b/trunk/arch/i386/kernel/e820.c new file mode 100644 index 000000000000..2f7d0a92fd7c --- /dev/null +++ b/trunk/arch/i386/kernel/e820.c @@ -0,0 +1,894 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#ifdef CONFIG_EFI +int efi_enabled = 0; +EXPORT_SYMBOL(efi_enabled); +#endif + +struct e820map e820; +struct change_member { + struct e820entry *pbios; /* pointer to original bios entry */ + unsigned long long addr; /* address for this change point */ +}; +static struct change_member change_point_list[2*E820MAX] __initdata; +static struct change_member *change_point[2*E820MAX] __initdata; +static struct e820entry *overlap_list[E820MAX] __initdata; +static struct e820entry new_bios[E820MAX] __initdata; +/* For PCI or other memory-mapped resources */ +unsigned long pci_mem_start = 0x10000000; +#ifdef CONFIG_PCI +EXPORT_SYMBOL(pci_mem_start); +#endif +extern int user_defined_memmap; +struct resource data_resource = { + .name = "Kernel data", + .start = 0, + .end = 0, + .flags = IORESOURCE_BUSY | IORESOURCE_MEM +}; + +struct resource code_resource = { + .name = "Kernel code", + .start = 0, + .end = 0, + .flags = IORESOURCE_BUSY | IORESOURCE_MEM +}; + +static struct resource system_rom_resource = { + .name = "System ROM", + .start = 0xf0000, + .end = 0xfffff, + .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM +}; + +static struct resource extension_rom_resource = { + .name = "Extension ROM", + .start = 0xe0000, + .end = 0xeffff, + .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM +}; + +static struct resource adapter_rom_resources[] = { { + .name = "Adapter ROM", + .start = 0xc8000, + .end = 0, + .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM +}, { + .name = "Adapter ROM", + .start = 0, + .end = 0, + .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM +}, { + .name = "Adapter ROM", + .start = 0, + .end = 0, + .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM +}, { + .name = "Adapter ROM", + .start = 0, + .end = 0, + .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM +}, { + .name = "Adapter ROM", + .start = 0, + .end = 0, + .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM +}, { + .name = "Adapter ROM", + .start = 0, + .end = 0, + .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM +} }; + +static struct resource video_rom_resource = { + .name = "Video ROM", + .start = 0xc0000, + .end = 0xc7fff, + .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM +}; + +static struct resource video_ram_resource = { + .name = "Video RAM area", + .start = 0xa0000, + .end = 0xbffff, + .flags = IORESOURCE_BUSY | IORESOURCE_MEM +}; + +static struct resource standard_io_resources[] = { { + .name = "dma1", + .start = 0x0000, + .end = 0x001f, + .flags = IORESOURCE_BUSY | IORESOURCE_IO +}, { + .name = "pic1", + .start = 0x0020, + .end = 0x0021, + .flags = IORESOURCE_BUSY | IORESOURCE_IO +}, { + .name = "timer0", + .start = 0x0040, + .end = 0x0043, + .flags = IORESOURCE_BUSY | IORESOURCE_IO +}, { + .name = "timer1", + .start = 0x0050, + .end = 0x0053, + .flags = IORESOURCE_BUSY | IORESOURCE_IO +}, { + .name = "keyboard", + .start = 0x0060, + .end = 0x006f, + .flags = IORESOURCE_BUSY | IORESOURCE_IO +}, { + .name = "dma page reg", + .start = 0x0080, + .end = 0x008f, + .flags = IORESOURCE_BUSY | IORESOURCE_IO +}, { + .name = "pic2", + .start = 0x00a0, + .end = 0x00a1, + .flags = IORESOURCE_BUSY | IORESOURCE_IO +}, { + .name = "dma2", + .start = 0x00c0, + .end = 0x00df, + .flags = IORESOURCE_BUSY | IORESOURCE_IO +}, { + .name = "fpu", + .start = 0x00f0, + .end = 0x00ff, + .flags = IORESOURCE_BUSY | IORESOURCE_IO +} }; + +static int romsignature(const unsigned char *x) +{ + unsigned short sig; + int ret = 0; + if (probe_kernel_address((const unsigned short *)x, sig) == 0) + ret = (sig == 0xaa55); + return ret; +} + +static int __init romchecksum(unsigned char *rom, unsigned long length) +{ + unsigned char *p, sum = 0; + + for (p = rom; p < rom + length; p++) + sum += *p; + return sum == 0; +} + +static void __init probe_roms(void) +{ + unsigned long start, length, upper; + unsigned char *rom; + int i; + + /* video rom */ + upper = adapter_rom_resources[0].start; + for (start = video_rom_resource.start; start < upper; start += 2048) { + rom = isa_bus_to_virt(start); + if (!romsignature(rom)) + continue; + + video_rom_resource.start = start; + + /* 0 < length <= 0x7f * 512, historically */ + length = rom[2] * 512; + + /* if checksum okay, trust length byte */ + if (length && romchecksum(rom, length)) + video_rom_resource.end = start + length - 1; + + request_resource(&iomem_resource, &video_rom_resource); + break; + } + + start = (video_rom_resource.end + 1 + 2047) & ~2047UL; + if (start < upper) + start = upper; + + /* system rom */ + request_resource(&iomem_resource, &system_rom_resource); + upper = system_rom_resource.start; + + /* check for extension rom (ignore length byte!) */ + rom = isa_bus_to_virt(extension_rom_resource.start); + if (romsignature(rom)) { + length = extension_rom_resource.end - extension_rom_resource.start + 1; + if (romchecksum(rom, length)) { + request_resource(&iomem_resource, &extension_rom_resource); + upper = extension_rom_resource.start; + } + } + + /* check for adapter roms on 2k boundaries */ + for (i = 0; i < ARRAY_SIZE(adapter_rom_resources) && start < upper; start += 2048) { + rom = isa_bus_to_virt(start); + if (!romsignature(rom)) + continue; + + /* 0 < length <= 0x7f * 512, historically */ + length = rom[2] * 512; + + /* but accept any length that fits if checksum okay */ + if (!length || start + length > upper || !romchecksum(rom, length)) + continue; + + adapter_rom_resources[i].start = start; + adapter_rom_resources[i].end = start + length - 1; + request_resource(&iomem_resource, &adapter_rom_resources[i]); + + start = adapter_rom_resources[i++].end & ~2047UL; + } +} + +/* + * Request address space for all standard RAM and ROM resources + * and also for regions reported as reserved by the e820. + */ +static void __init +legacy_init_iomem_resources(struct resource *code_resource, struct resource *data_resource) +{ + int i; + + probe_roms(); + for (i = 0; i < e820.nr_map; i++) { + struct resource *res; +#ifndef CONFIG_RESOURCES_64BIT + if (e820.map[i].addr + e820.map[i].size > 0x100000000ULL) + continue; +#endif + res = kzalloc(sizeof(struct resource), GFP_ATOMIC); + switch (e820.map[i].type) { + case E820_RAM: res->name = "System RAM"; break; + case E820_ACPI: res->name = "ACPI Tables"; break; + case E820_NVS: res->name = "ACPI Non-volatile Storage"; break; + default: res->name = "reserved"; + } + res->start = e820.map[i].addr; + res->end = res->start + e820.map[i].size - 1; + res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; + if (request_resource(&iomem_resource, res)) { + kfree(res); + continue; + } + if (e820.map[i].type == E820_RAM) { + /* + * We don't know which RAM region contains kernel data, + * so we try it repeatedly and let the resource manager + * test it. + */ + request_resource(res, code_resource); + request_resource(res, data_resource); +#ifdef CONFIG_KEXEC + request_resource(res, &crashk_res); +#endif + } + } +} + +/* + * Request address space for all standard resources + * + * This is called just before pcibios_init(), which is also a + * subsys_initcall, but is linked in later (in arch/i386/pci/common.c). + */ +static int __init request_standard_resources(void) +{ + int i; + + printk("Setting up standard PCI resources\n"); + if (efi_enabled) + efi_initialize_iomem_resources(&code_resource, &data_resource); + else + legacy_init_iomem_resources(&code_resource, &data_resource); + + /* EFI systems may still have VGA */ + request_resource(&iomem_resource, &video_ram_resource); + + /* request I/O space for devices used on all i[345]86 PCs */ + for (i = 0; i < ARRAY_SIZE(standard_io_resources); i++) + request_resource(&ioport_resource, &standard_io_resources[i]); + return 0; +} + +subsys_initcall(request_standard_resources); + +void __init add_memory_region(unsigned long long start, + unsigned long long size, int type) +{ + int x; + + if (!efi_enabled) { + x = e820.nr_map; + + if (x == E820MAX) { + printk(KERN_ERR "Ooops! Too many entries in the memory map!\n"); + return; + } + + e820.map[x].addr = start; + e820.map[x].size = size; + e820.map[x].type = type; + e820.nr_map++; + } +} /* add_memory_region */ + +/* + * Sanitize the BIOS e820 map. + * + * Some e820 responses include overlapping entries. The following + * replaces the original e820 map with a new one, removing overlaps. + * + */ +int __init sanitize_e820_map(struct e820entry * biosmap, char * pnr_map) +{ + struct change_member *change_tmp; + unsigned long current_type, last_type; + unsigned long long last_addr; + int chgidx, still_changing; + int overlap_entries; + int new_bios_entry; + int old_nr, new_nr, chg_nr; + int i; + + /* + Visually we're performing the following (1,2,3,4 = memory types)... + + Sample memory map (w/overlaps): + ____22__________________ + ______________________4_ + ____1111________________ + _44_____________________ + 11111111________________ + ____________________33__ + ___________44___________ + __________33333_________ + ______________22________ + ___________________2222_ + _________111111111______ + _____________________11_ + _________________4______ + + Sanitized equivalent (no overlap): + 1_______________________ + _44_____________________ + ___1____________________ + ____22__________________ + ______11________________ + _________1______________ + __________3_____________ + ___________44___________ + _____________33_________ + _______________2________ + ________________1_______ + _________________4______ + ___________________2____ + ____________________33__ + ______________________4_ + */ + printk("sanitize start\n"); + /* if there's only one memory region, don't bother */ + if (*pnr_map < 2) { + printk("sanitize bail 0\n"); + return -1; + } + + old_nr = *pnr_map; + + /* bail out if we find any unreasonable addresses in bios map */ + for (i=0; iaddr = biosmap[i].addr; + change_point[chgidx++]->pbios = &biosmap[i]; + change_point[chgidx]->addr = biosmap[i].addr + biosmap[i].size; + change_point[chgidx++]->pbios = &biosmap[i]; + } + } + chg_nr = chgidx; /* true number of change-points */ + + /* sort change-point list by memory addresses (low -> high) */ + still_changing = 1; + while (still_changing) { + still_changing = 0; + for (i=1; i < chg_nr; i++) { + /* if > , swap */ + /* or, if current= & last=, swap */ + if ((change_point[i]->addr < change_point[i-1]->addr) || + ((change_point[i]->addr == change_point[i-1]->addr) && + (change_point[i]->addr == change_point[i]->pbios->addr) && + (change_point[i-1]->addr != change_point[i-1]->pbios->addr)) + ) + { + change_tmp = change_point[i]; + change_point[i] = change_point[i-1]; + change_point[i-1] = change_tmp; + still_changing=1; + } + } + } + + /* create a new bios memory map, removing overlaps */ + overlap_entries=0; /* number of entries in the overlap table */ + new_bios_entry=0; /* index for creating new bios map entries */ + last_type = 0; /* start with undefined memory type */ + last_addr = 0; /* start with 0 as last starting address */ + /* loop through change-points, determining affect on the new bios map */ + for (chgidx=0; chgidx < chg_nr; chgidx++) + { + /* keep track of all overlapping bios entries */ + if (change_point[chgidx]->addr == change_point[chgidx]->pbios->addr) + { + /* add map entry to overlap list (> 1 entry implies an overlap) */ + overlap_list[overlap_entries++]=change_point[chgidx]->pbios; + } + else + { + /* remove entry from list (order independent, so swap with last) */ + for (i=0; ipbios) + overlap_list[i] = overlap_list[overlap_entries-1]; + } + overlap_entries--; + } + /* if there are overlapping entries, decide which "type" to use */ + /* (larger value takes precedence -- 1=usable, 2,3,4,4+=unusable) */ + current_type = 0; + for (i=0; itype > current_type) + current_type = overlap_list[i]->type; + /* continue building up new bios map based on this information */ + if (current_type != last_type) { + if (last_type != 0) { + new_bios[new_bios_entry].size = + change_point[chgidx]->addr - last_addr; + /* move forward only if the new size was non-zero */ + if (new_bios[new_bios_entry].size != 0) + if (++new_bios_entry >= E820MAX) + break; /* no more space left for new bios entries */ + } + if (current_type != 0) { + new_bios[new_bios_entry].addr = change_point[chgidx]->addr; + new_bios[new_bios_entry].type = current_type; + last_addr=change_point[chgidx]->addr; + } + last_type = current_type; + } + } + new_nr = new_bios_entry; /* retain count for new bios entries */ + + /* copy new bios mapping into original location */ + memcpy(biosmap, new_bios, new_nr*sizeof(struct e820entry)); + *pnr_map = new_nr; + + printk("sanitize end\n"); + return 0; +} + +/* + * Copy the BIOS e820 map into a safe place. + * + * Sanity-check it while we're at it.. + * + * If we're lucky and live on a modern system, the setup code + * will have given us a memory map that we can use to properly + * set up memory. If we aren't, we'll fake a memory map. + * + * We check to see that the memory map contains at least 2 elements + * before we'll use it, because the detection code in setup.S may + * not be perfect and most every PC known to man has two memory + * regions: one from 0 to 640k, and one from 1mb up. (The IBM + * thinkpad 560x, for example, does not cooperate with the memory + * detection code.) + */ +int __init copy_e820_map(struct e820entry * biosmap, int nr_map) +{ + /* Only one memory region (or negative)? Ignore it */ + if (nr_map < 2) + return -1; + + do { + unsigned long long start = biosmap->addr; + unsigned long long size = biosmap->size; + unsigned long long end = start + size; + unsigned long type = biosmap->type; + printk("copy_e820_map() start: %016Lx size: %016Lx end: %016Lx type: %ld\n", start, size, end, type); + + /* Overflow in 64 bits? Ignore the memory map. */ + if (start > end) + return -1; + + /* + * Some BIOSes claim RAM in the 640k - 1M region. + * Not right. Fix it up. + */ + if (type == E820_RAM) { + printk("copy_e820_map() type is E820_RAM\n"); + if (start < 0x100000ULL && end > 0xA0000ULL) { + printk("copy_e820_map() lies in range...\n"); + if (start < 0xA0000ULL) { + printk("copy_e820_map() start < 0xA0000ULL\n"); + add_memory_region(start, 0xA0000ULL-start, type); + } + if (end <= 0x100000ULL) { + printk("copy_e820_map() end <= 0x100000ULL\n"); + continue; + } + start = 0x100000ULL; + size = end - start; + } + } + add_memory_region(start, size, type); + } while (biosmap++,--nr_map); + return 0; +} + +/* + * Callback for efi_memory_walk. + */ +static int __init +efi_find_max_pfn(unsigned long start, unsigned long end, void *arg) +{ + unsigned long *max_pfn = arg, pfn; + + if (start < end) { + pfn = PFN_UP(end -1); + if (pfn > *max_pfn) + *max_pfn = pfn; + } + return 0; +} + +static int __init +efi_memory_present_wrapper(unsigned long start, unsigned long end, void *arg) +{ + memory_present(0, PFN_UP(start), PFN_DOWN(end)); + return 0; +} + +/* + * Find the highest page frame number we have available + */ +void __init find_max_pfn(void) +{ + int i; + + max_pfn = 0; + if (efi_enabled) { + efi_memmap_walk(efi_find_max_pfn, &max_pfn); + efi_memmap_walk(efi_memory_present_wrapper, NULL); + return; + } + + for (i = 0; i < e820.nr_map; i++) { + unsigned long start, end; + /* RAM? */ + if (e820.map[i].type != E820_RAM) + continue; + start = PFN_UP(e820.map[i].addr); + end = PFN_DOWN(e820.map[i].addr + e820.map[i].size); + if (start >= end) + continue; + if (end > max_pfn) + max_pfn = end; + memory_present(0, start, end); + } +} + +/* + * Free all available memory for boot time allocation. Used + * as a callback function by efi_memory_walk() + */ + +static int __init +free_available_memory(unsigned long start, unsigned long end, void *arg) +{ + /* check max_low_pfn */ + if (start >= (max_low_pfn << PAGE_SHIFT)) + return 0; + if (end >= (max_low_pfn << PAGE_SHIFT)) + end = max_low_pfn << PAGE_SHIFT; + if (start < end) + free_bootmem(start, end - start); + + return 0; +} +/* + * Register fully available low RAM pages with the bootmem allocator. + */ +void __init register_bootmem_low_pages(unsigned long max_low_pfn) +{ + int i; + + if (efi_enabled) { + efi_memmap_walk(free_available_memory, NULL); + return; + } + for (i = 0; i < e820.nr_map; i++) { + unsigned long curr_pfn, last_pfn, size; + /* + * Reserve usable low memory + */ + if (e820.map[i].type != E820_RAM) + continue; + /* + * We are rounding up the start address of usable memory: + */ + curr_pfn = PFN_UP(e820.map[i].addr); + if (curr_pfn >= max_low_pfn) + continue; + /* + * ... and at the end of the usable range downwards: + */ + last_pfn = PFN_DOWN(e820.map[i].addr + e820.map[i].size); + + if (last_pfn > max_low_pfn) + last_pfn = max_low_pfn; + + /* + * .. finally, did all the rounding and playing + * around just make the area go away? + */ + if (last_pfn <= curr_pfn) + continue; + + size = last_pfn - curr_pfn; + free_bootmem(PFN_PHYS(curr_pfn), PFN_PHYS(size)); + } +} + +void __init register_memory(void) +{ + unsigned long gapstart, gapsize, round; + unsigned long long last; + int i; + + /* + * Search for the bigest gap in the low 32 bits of the e820 + * memory space. + */ + last = 0x100000000ull; + gapstart = 0x10000000; + gapsize = 0x400000; + i = e820.nr_map; + while (--i >= 0) { + unsigned long long start = e820.map[i].addr; + unsigned long long end = start + e820.map[i].size; + + /* + * Since "last" is at most 4GB, we know we'll + * fit in 32 bits if this condition is true + */ + if (last > end) { + unsigned long gap = last - end; + + if (gap > gapsize) { + gapsize = gap; + gapstart = end; + } + } + if (start < last) + last = start; + } + + /* + * See how much we want to round up: start off with + * rounding to the next 1MB area. + */ + round = 0x100000; + while ((gapsize >> 4) > round) + round += round; + /* Fun with two's complement */ + pci_mem_start = (gapstart + round) & -round; + + printk("Allocating PCI resources starting at %08lx (gap: %08lx:%08lx)\n", + pci_mem_start, gapstart, gapsize); +} + +void __init print_memory_map(char *who) +{ + int i; + + for (i = 0; i < e820.nr_map; i++) { + printk(" %s: %016Lx - %016Lx ", who, + e820.map[i].addr, + e820.map[i].addr + e820.map[i].size); + switch (e820.map[i].type) { + case E820_RAM: printk("(usable)\n"); + break; + case E820_RESERVED: + printk("(reserved)\n"); + break; + case E820_ACPI: + printk("(ACPI data)\n"); + break; + case E820_NVS: + printk("(ACPI NVS)\n"); + break; + default: printk("type %lu\n", e820.map[i].type); + break; + } + } +} + +static __init __always_inline void efi_limit_regions(unsigned long long size) +{ + unsigned long long current_addr = 0; + efi_memory_desc_t *md, *next_md; + void *p, *p1; + int i, j; + + j = 0; + p1 = memmap.map; + for (p = p1, i = 0; p < memmap.map_end; p += memmap.desc_size, i++) { + md = p; + next_md = p1; + current_addr = md->phys_addr + + PFN_PHYS(md->num_pages); + if (is_available_memory(md)) { + if (md->phys_addr >= size) continue; + memcpy(next_md, md, memmap.desc_size); + if (current_addr >= size) { + next_md->num_pages -= + PFN_UP(current_addr-size); + } + p1 += memmap.desc_size; + next_md = p1; + j++; + } else if ((md->attribute & EFI_MEMORY_RUNTIME) == + EFI_MEMORY_RUNTIME) { + /* In order to make runtime services + * available we have to include runtime + * memory regions in memory map */ + memcpy(next_md, md, memmap.desc_size); + p1 += memmap.desc_size; + next_md = p1; + j++; + } + } + memmap.nr_map = j; + memmap.map_end = memmap.map + + (memmap.nr_map * memmap.desc_size); +} + +void __init limit_regions(unsigned long long size) +{ + unsigned long long current_addr; + int i; + + print_memory_map("limit_regions start"); + if (efi_enabled) { + efi_limit_regions(size); + return; + } + for (i = 0; i < e820.nr_map; i++) { + current_addr = e820.map[i].addr + e820.map[i].size; + if (current_addr < size) + continue; + + if (e820.map[i].type != E820_RAM) + continue; + + if (e820.map[i].addr >= size) { + /* + * This region starts past the end of the + * requested size, skip it completely. + */ + e820.nr_map = i; + } else { + e820.nr_map = i + 1; + e820.map[i].size -= current_addr - size; + } + print_memory_map("limit_regions endfor"); + return; + } + print_memory_map("limit_regions endfunc"); +} + + /* + * This function checks if the entire range is mapped with type. + * + * Note: this function only works correct if the e820 table is sorted and + * not-overlapping, which is the case + */ +int __init +e820_all_mapped(unsigned long s, unsigned long e, unsigned type) +{ + u64 start = s; + u64 end = e; + int i; + for (i = 0; i < e820.nr_map; i++) { + struct e820entry *ei = &e820.map[i]; + if (type && ei->type != type) + continue; + /* is the region (part) in overlap with the current region ?*/ + if (ei->addr >= end || ei->addr + ei->size <= start) + continue; + /* if the region is at the beginning of we move + * start to the end of the region since it's ok until there + */ + if (ei->addr <= start) + start = ei->addr + ei->size; + /* if start is now at or beyond end, we're done, full + * coverage */ + if (start >= end) + return 1; /* we're done */ + } + return 0; +} + +static int __init parse_memmap(char *arg) +{ + if (!arg) + return -EINVAL; + + if (strcmp(arg, "exactmap") == 0) { +#ifdef CONFIG_CRASH_DUMP + /* If we are doing a crash dump, we + * still need to know the real mem + * size before original memory map is + * reset. + */ + find_max_pfn(); + saved_max_pfn = max_pfn; +#endif + e820.nr_map = 0; + user_defined_memmap = 1; + } else { + /* If the user specifies memory size, we + * limit the BIOS-provided memory map to + * that size. exactmap can be used to specify + * the exact map. mem=number can be used to + * trim the existing memory map. + */ + unsigned long long start_at, mem_size; + + mem_size = memparse(arg, &arg); + if (*arg == '@') { + start_at = memparse(arg+1, &arg); + add_memory_region(start_at, mem_size, E820_RAM); + } else if (*arg == '#') { + start_at = memparse(arg+1, &arg); + add_memory_region(start_at, mem_size, E820_ACPI); + } else if (*arg == '$') { + start_at = memparse(arg+1, &arg); + add_memory_region(start_at, mem_size, E820_RESERVED); + } else { + limit_regions(mem_size); + user_defined_memmap = 1; + } + } + return 0; +} +early_param("memmap", parse_memmap); diff --git a/trunk/arch/i386/kernel/efi.c b/trunk/arch/i386/kernel/efi.c index 8b40648d0ef0..b92c7f0a358a 100644 --- a/trunk/arch/i386/kernel/efi.c +++ b/trunk/arch/i386/kernel/efi.c @@ -194,17 +194,24 @@ inline int efi_set_rtc_mmss(unsigned long nowtime) return 0; } /* - * This should only be used during kernel init and before runtime - * services have been remapped, therefore, we'll need to call in physical - * mode. Note, this call isn't used later, so mark it __init. + * This is used during kernel init before runtime + * services have been remapped and also during suspend, therefore, + * we'll need to call both in physical and virtual modes. */ -inline unsigned long __init efi_get_time(void) +inline unsigned long efi_get_time(void) { efi_status_t status; efi_time_t eft; efi_time_cap_t cap; - status = phys_efi_get_time(&eft, &cap); + if (efi.get_time) { + /* if we are in virtual mode use remapped function */ + status = efi.get_time(&eft, &cap); + } else { + /* we are in physical mode */ + status = phys_efi_get_time(&eft, &cap); + } + if (status != EFI_SUCCESS) printk("Oops: efitime: can't read time status: 0x%lx\n",status); diff --git a/trunk/arch/i386/kernel/entry.S b/trunk/arch/i386/kernel/entry.S index 5a63d6fdb70e..de34b7fed3c1 100644 --- a/trunk/arch/i386/kernel/entry.S +++ b/trunk/arch/i386/kernel/entry.S @@ -30,12 +30,13 @@ * 18(%esp) - %eax * 1C(%esp) - %ds * 20(%esp) - %es - * 24(%esp) - orig_eax - * 28(%esp) - %eip - * 2C(%esp) - %cs - * 30(%esp) - %eflags - * 34(%esp) - %oldesp - * 38(%esp) - %oldss + * 24(%esp) - %gs + * 28(%esp) - orig_eax + * 2C(%esp) - %eip + * 30(%esp) - %cs + * 34(%esp) - %eflags + * 38(%esp) - %oldesp + * 3C(%esp) - %oldss * * "current" is in register %ebx during any slow entries. */ @@ -48,26 +49,24 @@ #include #include #include +#include #include #include "irq_vectors.h" -#define nr_syscalls ((syscall_table_size)/4) +/* + * We use macros for low-level operations which need to be overridden + * for paravirtualization. The following will never clobber any registers: + * INTERRUPT_RETURN (aka. "iret") + * GET_CR0_INTO_EAX (aka. "movl %cr0, %eax") + * ENABLE_INTERRUPTS_SYSEXIT (aka "sti; sysexit"). + * + * For DISABLE_INTERRUPTS/ENABLE_INTERRUPTS (aka "cli"/"sti"), you must + * specify what registers can be overwritten (CLBR_NONE, CLBR_EAX/EDX/ECX/ANY). + * Allowing a register to be clobbered can shrink the paravirt replacement + * enough to patch inline, increasing performance. + */ -EBX = 0x00 -ECX = 0x04 -EDX = 0x08 -ESI = 0x0C -EDI = 0x10 -EBP = 0x14 -EAX = 0x18 -DS = 0x1C -ES = 0x20 -ORIG_EAX = 0x24 -EIP = 0x28 -CS = 0x2C -EFLAGS = 0x30 -OLDESP = 0x34 -OLDSS = 0x38 +#define nr_syscalls ((syscall_table_size)/4) CF_MASK = 0x00000001 TF_MASK = 0x00000100 @@ -76,23 +75,16 @@ DF_MASK = 0x00000400 NT_MASK = 0x00004000 VM_MASK = 0x00020000 -/* These are replaces for paravirtualization */ -#define DISABLE_INTERRUPTS cli -#define ENABLE_INTERRUPTS sti -#define ENABLE_INTERRUPTS_SYSEXIT sti; sysexit -#define INTERRUPT_RETURN iret -#define GET_CR0_INTO_EAX movl %cr0, %eax - #ifdef CONFIG_PREEMPT -#define preempt_stop DISABLE_INTERRUPTS; TRACE_IRQS_OFF +#define preempt_stop(clobbers) DISABLE_INTERRUPTS(clobbers); TRACE_IRQS_OFF #else -#define preempt_stop +#define preempt_stop(clobbers) #define resume_kernel restore_nocheck #endif .macro TRACE_IRQS_IRET #ifdef CONFIG_TRACE_IRQFLAGS - testl $IF_MASK,EFLAGS(%esp) # interrupts off? + testl $IF_MASK,PT_EFLAGS(%esp) # interrupts off? jz 1f TRACE_IRQS_ON 1: @@ -107,6 +99,9 @@ VM_MASK = 0x00020000 #define SAVE_ALL \ cld; \ + pushl %gs; \ + CFI_ADJUST_CFA_OFFSET 4;\ + /*CFI_REL_OFFSET gs, 0;*/\ pushl %es; \ CFI_ADJUST_CFA_OFFSET 4;\ /*CFI_REL_OFFSET es, 0;*/\ @@ -136,7 +131,9 @@ VM_MASK = 0x00020000 CFI_REL_OFFSET ebx, 0;\ movl $(__USER_DS), %edx; \ movl %edx, %ds; \ - movl %edx, %es; + movl %edx, %es; \ + movl $(__KERNEL_PDA), %edx; \ + movl %edx, %gs #define RESTORE_INT_REGS \ popl %ebx; \ @@ -169,17 +166,22 @@ VM_MASK = 0x00020000 2: popl %es; \ CFI_ADJUST_CFA_OFFSET -4;\ /*CFI_RESTORE es;*/\ -.section .fixup,"ax"; \ -3: movl $0,(%esp); \ - jmp 1b; \ +3: popl %gs; \ + CFI_ADJUST_CFA_OFFSET -4;\ + /*CFI_RESTORE gs;*/\ +.pushsection .fixup,"ax"; \ 4: movl $0,(%esp); \ + jmp 1b; \ +5: movl $0,(%esp); \ jmp 2b; \ -.previous; \ +6: movl $0,(%esp); \ + jmp 3b; \ .section __ex_table,"a";\ .align 4; \ - .long 1b,3b; \ - .long 2b,4b; \ -.previous + .long 1b,4b; \ + .long 2b,5b; \ + .long 3b,6b; \ +.popsection #define RING0_INT_FRAME \ CFI_STARTPROC simple;\ @@ -198,18 +200,18 @@ VM_MASK = 0x00020000 #define RING0_PTREGS_FRAME \ CFI_STARTPROC simple;\ CFI_SIGNAL_FRAME;\ - CFI_DEF_CFA esp, OLDESP-EBX;\ - /*CFI_OFFSET cs, CS-OLDESP;*/\ - CFI_OFFSET eip, EIP-OLDESP;\ - /*CFI_OFFSET es, ES-OLDESP;*/\ - /*CFI_OFFSET ds, DS-OLDESP;*/\ - CFI_OFFSET eax, EAX-OLDESP;\ - CFI_OFFSET ebp, EBP-OLDESP;\ - CFI_OFFSET edi, EDI-OLDESP;\ - CFI_OFFSET esi, ESI-OLDESP;\ - CFI_OFFSET edx, EDX-OLDESP;\ - CFI_OFFSET ecx, ECX-OLDESP;\ - CFI_OFFSET ebx, EBX-OLDESP + CFI_DEF_CFA esp, PT_OLDESP-PT_EBX;\ + /*CFI_OFFSET cs, PT_CS-PT_OLDESP;*/\ + CFI_OFFSET eip, PT_EIP-PT_OLDESP;\ + /*CFI_OFFSET es, PT_ES-PT_OLDESP;*/\ + /*CFI_OFFSET ds, PT_DS-PT_OLDESP;*/\ + CFI_OFFSET eax, PT_EAX-PT_OLDESP;\ + CFI_OFFSET ebp, PT_EBP-PT_OLDESP;\ + CFI_OFFSET edi, PT_EDI-PT_OLDESP;\ + CFI_OFFSET esi, PT_ESI-PT_OLDESP;\ + CFI_OFFSET edx, PT_EDX-PT_OLDESP;\ + CFI_OFFSET ecx, PT_ECX-PT_OLDESP;\ + CFI_OFFSET ebx, PT_EBX-PT_OLDESP ENTRY(ret_from_fork) CFI_STARTPROC @@ -237,17 +239,18 @@ ENTRY(ret_from_fork) ALIGN RING0_PTREGS_FRAME ret_from_exception: - preempt_stop + preempt_stop(CLBR_ANY) ret_from_intr: GET_THREAD_INFO(%ebp) check_userspace: - movl EFLAGS(%esp), %eax # mix EFLAGS and CS - movb CS(%esp), %al + movl PT_EFLAGS(%esp), %eax # mix EFLAGS and CS + movb PT_CS(%esp), %al andl $(VM_MASK | SEGMENT_RPL_MASK), %eax cmpl $USER_RPL, %eax jb resume_kernel # not returning to v8086 or userspace + ENTRY(resume_userspace) - DISABLE_INTERRUPTS # make sure we don't miss an interrupt + DISABLE_INTERRUPTS(CLBR_ANY) # make sure we don't miss an interrupt # setting need_resched or sigpending # between sampling and the iret movl TI_flags(%ebp), %ecx @@ -258,14 +261,14 @@ ENTRY(resume_userspace) #ifdef CONFIG_PREEMPT ENTRY(resume_kernel) - DISABLE_INTERRUPTS + DISABLE_INTERRUPTS(CLBR_ANY) cmpl $0,TI_preempt_count(%ebp) # non-zero preempt_count ? jnz restore_nocheck need_resched: movl TI_flags(%ebp), %ecx # need_resched set ? testb $_TIF_NEED_RESCHED, %cl jz restore_all - testl $IF_MASK,EFLAGS(%esp) # interrupts off (exception path) ? + testl $IF_MASK,PT_EFLAGS(%esp) # interrupts off (exception path) ? jz restore_all call preempt_schedule_irq jmp need_resched @@ -287,7 +290,7 @@ sysenter_past_esp: * No need to follow this irqs on/off section: the syscall * disabled irqs and here we enable it straight after entry: */ - ENABLE_INTERRUPTS + ENABLE_INTERRUPTS(CLBR_NONE) pushl $(__USER_DS) CFI_ADJUST_CFA_OFFSET 4 /*CFI_REL_OFFSET ss, 0*/ @@ -331,20 +334,27 @@ sysenter_past_esp: cmpl $(nr_syscalls), %eax jae syscall_badsys call *sys_call_table(,%eax,4) - movl %eax,EAX(%esp) - DISABLE_INTERRUPTS + movl %eax,PT_EAX(%esp) + DISABLE_INTERRUPTS(CLBR_ECX|CLBR_EDX) TRACE_IRQS_OFF movl TI_flags(%ebp), %ecx testw $_TIF_ALLWORK_MASK, %cx jne syscall_exit_work /* if something modifies registers it must also disable sysexit */ - movl EIP(%esp), %edx - movl OLDESP(%esp), %ecx + movl PT_EIP(%esp), %edx + movl PT_OLDESP(%esp), %ecx xorl %ebp,%ebp TRACE_IRQS_ON +1: mov PT_GS(%esp), %gs ENABLE_INTERRUPTS_SYSEXIT CFI_ENDPROC - +.pushsection .fixup,"ax" +2: movl $0,PT_GS(%esp) + jmp 1b +.section __ex_table,"a" + .align 4 + .long 1b,2b +.popsection # system call handler stub ENTRY(system_call) @@ -353,7 +363,7 @@ ENTRY(system_call) CFI_ADJUST_CFA_OFFSET 4 SAVE_ALL GET_THREAD_INFO(%ebp) - testl $TF_MASK,EFLAGS(%esp) + testl $TF_MASK,PT_EFLAGS(%esp) jz no_singlestep orl $_TIF_SINGLESTEP,TI_flags(%ebp) no_singlestep: @@ -365,9 +375,9 @@ no_singlestep: jae syscall_badsys syscall_call: call *sys_call_table(,%eax,4) - movl %eax,EAX(%esp) # store the return value + movl %eax,PT_EAX(%esp) # store the return value syscall_exit: - DISABLE_INTERRUPTS # make sure we don't miss an interrupt + DISABLE_INTERRUPTS(CLBR_ANY) # make sure we don't miss an interrupt # setting need_resched or sigpending # between sampling and the iret TRACE_IRQS_OFF @@ -376,12 +386,12 @@ syscall_exit: jne syscall_exit_work restore_all: - movl EFLAGS(%esp), %eax # mix EFLAGS, SS and CS - # Warning: OLDSS(%esp) contains the wrong/random values if we + movl PT_EFLAGS(%esp), %eax # mix EFLAGS, SS and CS + # Warning: PT_OLDSS(%esp) contains the wrong/random values if we # are returning to the kernel. # See comments in process.c:copy_thread() for details. - movb OLDSS(%esp), %ah - movb CS(%esp), %al + movb PT_OLDSS(%esp), %ah + movb PT_CS(%esp), %al andl $(VM_MASK | (SEGMENT_TI_MASK << 8) | SEGMENT_RPL_MASK), %eax cmpl $((SEGMENT_LDT << 8) | USER_RPL), %eax CFI_REMEMBER_STATE @@ -390,13 +400,13 @@ restore_nocheck: TRACE_IRQS_IRET restore_nocheck_notrace: RESTORE_REGS - addl $4, %esp + addl $4, %esp # skip orig_eax/error_code CFI_ADJUST_CFA_OFFSET -4 1: INTERRUPT_RETURN .section .fixup,"ax" iret_exc: TRACE_IRQS_ON - ENABLE_INTERRUPTS + ENABLE_INTERRUPTS(CLBR_NONE) pushl $0 # no error code pushl $do_iret_error jmp error_code @@ -408,33 +418,42 @@ iret_exc: CFI_RESTORE_STATE ldt_ss: - larl OLDSS(%esp), %eax + larl PT_OLDSS(%esp), %eax jnz restore_nocheck testl $0x00400000, %eax # returning to 32bit stack? jnz restore_nocheck # allright, normal return + +#ifdef CONFIG_PARAVIRT + /* + * The kernel can't run on a non-flat stack if paravirt mode + * is active. Rather than try to fixup the high bits of + * ESP, bypass this code entirely. This may break DOSemu + * and/or Wine support in a paravirt VM, although the option + * is still available to implement the setting of the high + * 16-bits in the INTERRUPT_RETURN paravirt-op. + */ + cmpl $0, paravirt_ops+PARAVIRT_enabled + jne restore_nocheck +#endif + /* If returning to userspace with 16bit stack, * try to fix the higher word of ESP, as the CPU * won't restore it. * This is an "official" bug of all the x86-compatible * CPUs, which we can try to work around to make * dosemu and wine happy. */ - subl $8, %esp # reserve space for switch16 pointer - CFI_ADJUST_CFA_OFFSET 8 - DISABLE_INTERRUPTS + movl PT_OLDESP(%esp), %eax + movl %esp, %edx + call patch_espfix_desc + pushl $__ESPFIX_SS + CFI_ADJUST_CFA_OFFSET 4 + pushl %eax + CFI_ADJUST_CFA_OFFSET 4 + DISABLE_INTERRUPTS(CLBR_EAX) TRACE_IRQS_OFF - movl %esp, %eax - /* Set up the 16bit stack frame with switch32 pointer on top, - * and a switch16 pointer on top of the current frame. */ - call setup_x86_bogus_stack - CFI_ADJUST_CFA_OFFSET -8 # frame has moved - TRACE_IRQS_IRET - RESTORE_REGS - lss 20+4(%esp), %esp # switch to 16bit stack -1: INTERRUPT_RETURN -.section __ex_table,"a" - .align 4 - .long 1b,iret_exc -.previous + lss (%esp), %esp + CFI_ADJUST_CFA_OFFSET -8 + jmp restore_nocheck CFI_ENDPROC # perform work that needs to be done immediately before resumption @@ -445,7 +464,7 @@ work_pending: jz work_notifysig work_resched: call schedule - DISABLE_INTERRUPTS # make sure we don't miss an interrupt + DISABLE_INTERRUPTS(CLBR_ANY) # make sure we don't miss an interrupt # setting need_resched or sigpending # between sampling and the iret TRACE_IRQS_OFF @@ -458,7 +477,8 @@ work_resched: work_notifysig: # deal with pending signals and # notify-resume requests - testl $VM_MASK, EFLAGS(%esp) +#ifdef CONFIG_VM86 + testl $VM_MASK, PT_EFLAGS(%esp) movl %esp, %eax jne work_notifysig_v86 # returning to kernel-space or # vm86-space @@ -468,29 +488,30 @@ work_notifysig: # deal with pending signals and ALIGN work_notifysig_v86: -#ifdef CONFIG_VM86 pushl %ecx # save ti_flags for do_notify_resume CFI_ADJUST_CFA_OFFSET 4 call save_v86_state # %eax contains pt_regs pointer popl %ecx CFI_ADJUST_CFA_OFFSET -4 movl %eax, %esp +#else + movl %esp, %eax +#endif xorl %edx, %edx call do_notify_resume jmp resume_userspace_sig -#endif # perform syscall exit tracing ALIGN syscall_trace_entry: - movl $-ENOSYS,EAX(%esp) + movl $-ENOSYS,PT_EAX(%esp) movl %esp, %eax xorl %edx,%edx call do_syscall_trace cmpl $0, %eax jne resume_userspace # ret != 0 -> running under PTRACE_SYSEMU, # so must skip actual syscall - movl ORIG_EAX(%esp), %eax + movl PT_ORIG_EAX(%esp), %eax cmpl $(nr_syscalls), %eax jnae syscall_call jmp syscall_exit @@ -501,7 +522,7 @@ syscall_exit_work: testb $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP), %cl jz work_pending TRACE_IRQS_ON - ENABLE_INTERRUPTS # could let do_syscall_trace() call + ENABLE_INTERRUPTS(CLBR_ANY) # could let do_syscall_trace() call # schedule() instead movl %esp, %eax movl $1, %edx @@ -515,39 +536,38 @@ syscall_fault: CFI_ADJUST_CFA_OFFSET 4 SAVE_ALL GET_THREAD_INFO(%ebp) - movl $-EFAULT,EAX(%esp) + movl $-EFAULT,PT_EAX(%esp) jmp resume_userspace syscall_badsys: - movl $-ENOSYS,EAX(%esp) + movl $-ENOSYS,PT_EAX(%esp) jmp resume_userspace CFI_ENDPROC #define FIXUP_ESPFIX_STACK \ - movl %esp, %eax; \ - /* switch to 32bit stack using the pointer on top of 16bit stack */ \ - lss %ss:CPU_16BIT_STACK_SIZE-8, %esp; \ - /* copy data from 16bit stack to 32bit stack */ \ - call fixup_x86_bogus_stack; \ - /* put ESP to the proper location */ \ - movl %eax, %esp; -#define UNWIND_ESPFIX_STACK \ + /* since we are on a wrong stack, we cant make it a C code :( */ \ + movl %gs:PDA_cpu, %ebx; \ + PER_CPU(cpu_gdt_descr, %ebx); \ + movl GDS_address(%ebx), %ebx; \ + GET_DESC_BASE(GDT_ENTRY_ESPFIX_SS, %ebx, %eax, %ax, %al, %ah); \ + addl %esp, %eax; \ + pushl $__KERNEL_DS; \ + CFI_ADJUST_CFA_OFFSET 4; \ pushl %eax; \ CFI_ADJUST_CFA_OFFSET 4; \ + lss (%esp), %esp; \ + CFI_ADJUST_CFA_OFFSET -8; +#define UNWIND_ESPFIX_STACK \ movl %ss, %eax; \ - /* see if on 16bit stack */ \ + /* see if on espfix stack */ \ cmpw $__ESPFIX_SS, %ax; \ - je 28f; \ -27: popl %eax; \ - CFI_ADJUST_CFA_OFFSET -4; \ -.section .fixup,"ax"; \ -28: movl $__KERNEL_DS, %eax; \ + jne 27f; \ + movl $__KERNEL_DS, %eax; \ movl %eax, %ds; \ movl %eax, %es; \ - /* switch to 32bit stack */ \ + /* switch to normal stack */ \ FIXUP_ESPFIX_STACK; \ - jmp 27b; \ -.previous +27:; /* * Build the entry stubs and pointer table with @@ -608,13 +628,16 @@ KPROBE_ENTRY(page_fault) CFI_ADJUST_CFA_OFFSET 4 ALIGN error_code: + /* the function address is in %gs's slot on the stack */ + pushl %es + CFI_ADJUST_CFA_OFFSET 4 + /*CFI_REL_OFFSET es, 0*/ pushl %ds CFI_ADJUST_CFA_OFFSET 4 /*CFI_REL_OFFSET ds, 0*/ pushl %eax CFI_ADJUST_CFA_OFFSET 4 CFI_REL_OFFSET eax, 0 - xorl %eax, %eax pushl %ebp CFI_ADJUST_CFA_OFFSET 4 CFI_REL_OFFSET ebp, 0 @@ -627,7 +650,6 @@ error_code: pushl %edx CFI_ADJUST_CFA_OFFSET 4 CFI_REL_OFFSET edx, 0 - decl %eax # eax = -1 pushl %ecx CFI_ADJUST_CFA_OFFSET 4 CFI_REL_OFFSET ecx, 0 @@ -635,18 +657,20 @@ error_code: CFI_ADJUST_CFA_OFFSET 4 CFI_REL_OFFSET ebx, 0 cld - pushl %es + pushl %gs CFI_ADJUST_CFA_OFFSET 4 - /*CFI_REL_OFFSET es, 0*/ + /*CFI_REL_OFFSET gs, 0*/ + movl $(__KERNEL_PDA), %ecx + movl %ecx, %gs UNWIND_ESPFIX_STACK popl %ecx CFI_ADJUST_CFA_OFFSET -4 /*CFI_REGISTER es, ecx*/ - movl ES(%esp), %edi # get the function address - movl ORIG_EAX(%esp), %edx # get the error code - movl %eax, ORIG_EAX(%esp) - movl %ecx, ES(%esp) - /*CFI_REL_OFFSET es, ES*/ + movl PT_GS(%esp), %edi # get the function address + movl PT_ORIG_EAX(%esp), %edx # get the error code + movl $-1, PT_ORIG_EAX(%esp) # no syscall to restart + mov %ecx, PT_GS(%esp) + /*CFI_REL_OFFSET gs, ES*/ movl $(__USER_DS), %ecx movl %ecx, %ds movl %ecx, %es @@ -682,7 +706,7 @@ ENTRY(device_not_available) GET_CR0_INTO_EAX testl $0x4, %eax # EM (math emulation bit) jne device_not_available_emulate - preempt_stop + preempt_stop(CLBR_ANY) call math_state_restore jmp ret_from_exception device_not_available_emulate: @@ -754,7 +778,7 @@ KPROBE_ENTRY(nmi) cmpw $__ESPFIX_SS, %ax popl %eax CFI_ADJUST_CFA_OFFSET -4 - je nmi_16bit_stack + je nmi_espfix_stack cmpl $sysenter_entry,(%esp) je nmi_stack_fixup pushl %eax @@ -797,7 +821,7 @@ nmi_debug_stack_check: FIX_STACK(24,nmi_stack_correct, 1) jmp nmi_stack_correct -nmi_16bit_stack: +nmi_espfix_stack: /* We have a RING0_INT_FRAME here. * * create the pointer to lss back @@ -806,7 +830,6 @@ nmi_16bit_stack: CFI_ADJUST_CFA_OFFSET 4 pushl %esp CFI_ADJUST_CFA_OFFSET 4 - movzwl %sp, %esp addw $4, (%esp) /* copy the iret frame of 12 bytes */ .rept 3 @@ -817,11 +840,11 @@ nmi_16bit_stack: CFI_ADJUST_CFA_OFFSET 4 SAVE_ALL FIXUP_ESPFIX_STACK # %eax == %esp - CFI_ADJUST_CFA_OFFSET -20 # the frame has now moved xorl %edx,%edx # zero error code call do_nmi RESTORE_REGS - lss 12+4(%esp), %esp # back to 16bit stack + lss 12+4(%esp), %esp # back to espfix stack + CFI_ADJUST_CFA_OFFSET -24 1: INTERRUPT_RETURN CFI_ENDPROC .section __ex_table,"a" @@ -830,6 +853,19 @@ nmi_16bit_stack: .previous KPROBE_END(nmi) +#ifdef CONFIG_PARAVIRT +ENTRY(native_iret) +1: iret +.section __ex_table,"a" + .align 4 + .long 1b,iret_exc +.previous + +ENTRY(native_irq_enable_sysexit) + sti + sysexit +#endif + KPROBE_ENTRY(int3) RING0_INT_FRAME pushl $-1 # mark this as an int @@ -949,26 +985,27 @@ ENTRY(arch_unwind_init_running) movl 4(%esp), %edx movl (%esp), %ecx leal 4(%esp), %eax - movl %ebx, EBX(%edx) + movl %ebx, PT_EBX(%edx) xorl %ebx, %ebx - movl %ebx, ECX(%edx) - movl %ebx, EDX(%edx) - movl %esi, ESI(%edx) - movl %edi, EDI(%edx) - movl %ebp, EBP(%edx) - movl %ebx, EAX(%edx) - movl $__USER_DS, DS(%edx) - movl $__USER_DS, ES(%edx) - movl %ebx, ORIG_EAX(%edx) - movl %ecx, EIP(%edx) + movl %ebx, PT_ECX(%edx) + movl %ebx, PT_EDX(%edx) + movl %esi, PT_ESI(%edx) + movl %edi, PT_EDI(%edx) + movl %ebp, PT_EBP(%edx) + movl %ebx, PT_EAX(%edx) + movl $__USER_DS, PT_DS(%edx) + movl $__USER_DS, PT_ES(%edx) + movl $0, PT_GS(%edx) + movl %ebx, PT_ORIG_EAX(%edx) + movl %ecx, PT_EIP(%edx) movl 12(%esp), %ecx - movl $__KERNEL_CS, CS(%edx) - movl %ebx, EFLAGS(%edx) - movl %eax, OLDESP(%edx) + movl $__KERNEL_CS, PT_CS(%edx) + movl %ebx, PT_EFLAGS(%edx) + movl %eax, PT_OLDESP(%edx) movl 8(%esp), %eax movl %ecx, 8(%esp) - movl EBX(%edx), %ebx - movl $__KERNEL_DS, OLDSS(%edx) + movl PT_EBX(%edx), %ebx + movl $__KERNEL_DS, PT_OLDSS(%edx) jmpl *%eax CFI_ENDPROC ENDPROC(arch_unwind_init_running) diff --git a/trunk/arch/i386/kernel/head.S b/trunk/arch/i386/kernel/head.S index ca31f18d277c..edef5084ce17 100644 --- a/trunk/arch/i386/kernel/head.S +++ b/trunk/arch/i386/kernel/head.S @@ -55,6 +55,12 @@ */ ENTRY(startup_32) +#ifdef CONFIG_PARAVIRT + movl %cs, %eax + testl $0x3, %eax + jnz startup_paravirt +#endif + /* * Set segments to known values. */ @@ -302,6 +308,7 @@ is386: movl $2,%ecx # set MP movl %eax,%cr0 call check_x87 + call setup_pda lgdt cpu_gdt_descr lidt idt_descr ljmp $(__KERNEL_CS),$1f @@ -312,10 +319,13 @@ is386: movl $2,%ecx # set MP movl %eax,%ds movl %eax,%es - xorl %eax,%eax # Clear FS/GS and LDT + xorl %eax,%eax # Clear FS and LDT movl %eax,%fs - movl %eax,%gs lldt %ax + + movl $(__KERNEL_PDA),%eax + mov %eax,%gs + cld # gcc2 wants the direction flag cleared at all times pushl $0 # fake return address for unwinder #ifdef CONFIG_SMP @@ -345,6 +355,23 @@ check_x87: .byte 0xDB,0xE4 /* fsetpm for 287, ignored by 387 */ ret +/* + * Point the GDT at this CPU's PDA. On boot this will be + * cpu_gdt_table and boot_pda; for secondary CPUs, these will be + * that CPU's GDT and PDA. + */ +setup_pda: + /* get the PDA pointer */ + movl start_pda, %eax + + /* slot the PDA address into the GDT */ + mov cpu_gdt_descr+2, %ecx + mov %ax, (__KERNEL_PDA+0+2)(%ecx) /* base & 0x0000ffff */ + shr $16, %eax + mov %al, (__KERNEL_PDA+4+0)(%ecx) /* base & 0x00ff0000 */ + mov %ah, (__KERNEL_PDA+4+3)(%ecx) /* base & 0xff000000 */ + ret + /* * setup_idt * @@ -465,6 +492,33 @@ ignore_int: #endif iret +#ifdef CONFIG_PARAVIRT +startup_paravirt: + cld + movl $(init_thread_union+THREAD_SIZE),%esp + + /* We take pains to preserve all the regs. */ + pushl %edx + pushl %ecx + pushl %eax + + /* paravirt.o is last in link, and that probe fn never returns */ + pushl $__start_paravirtprobe +1: + movl 0(%esp), %eax + pushl (%eax) + movl 8(%esp), %eax + call *(%esp) + popl %eax + + movl 4(%esp), %eax + movl 8(%esp), %ecx + movl 12(%esp), %edx + + addl $4, (%esp) + jmp 1b +#endif + /* * Real beginning of normal "text" segment */ @@ -484,6 +538,8 @@ ENTRY(empty_zero_page) * This starts the data section. */ .data +ENTRY(start_pda) + .long boot_pda ENTRY(stack_start) .long init_thread_union+THREAD_SIZE @@ -525,7 +581,7 @@ idt_descr: # boot GDT descriptor (later on used by CPU#0): .word 0 # 32 bit align gdt_desc.address -cpu_gdt_descr: +ENTRY(cpu_gdt_descr) .word GDT_ENTRIES*8-1 .long cpu_gdt_table @@ -584,8 +640,8 @@ ENTRY(cpu_gdt_table) .quad 0x00009a000000ffff /* 0xc0 APM CS 16 code (16 bit) */ .quad 0x004092000000ffff /* 0xc8 APM DS data */ - .quad 0x0000920000000000 /* 0xd0 - ESPFIX 16-bit SS */ - .quad 0x0000000000000000 /* 0xd8 - unused */ + .quad 0x00c0920000000000 /* 0xd0 - ESPFIX SS */ + .quad 0x00cf92000000ffff /* 0xd8 - PDA */ .quad 0x0000000000000000 /* 0xe0 - unused */ .quad 0x0000000000000000 /* 0xe8 - unused */ .quad 0x0000000000000000 /* 0xf0 - unused */ diff --git a/trunk/arch/i386/kernel/hpet.c b/trunk/arch/i386/kernel/hpet.c index 17647a530b2f..45a8685bb60b 100644 --- a/trunk/arch/i386/kernel/hpet.c +++ b/trunk/arch/i386/kernel/hpet.c @@ -34,6 +34,7 @@ static int __init init_hpet_clocksource(void) unsigned long hpet_period; void __iomem* hpet_base; u64 tmp; + int err; if (!is_hpet_enabled()) return -ENODEV; @@ -61,7 +62,11 @@ static int __init init_hpet_clocksource(void) do_div(tmp, FSEC_PER_NSEC); clocksource_hpet.mult = (u32)tmp; - return clocksource_register(&clocksource_hpet); + err = clocksource_register(&clocksource_hpet); + if (err) + iounmap(hpet_base); + + return err; } module_init(init_hpet_clocksource); diff --git a/trunk/arch/i386/kernel/i8259.c b/trunk/arch/i386/kernel/i8259.c index 62996cd17084..c8d45821c788 100644 --- a/trunk/arch/i386/kernel/i8259.c +++ b/trunk/arch/i386/kernel/i8259.c @@ -381,7 +381,10 @@ void __init init_ISA_irqs (void) } } -void __init init_IRQ(void) +/* Overridden in paravirt.c */ +void init_IRQ(void) __attribute__((weak, alias("native_init_IRQ"))); + +void __init native_init_IRQ(void) { int i; diff --git a/trunk/arch/i386/kernel/io_apic.c b/trunk/arch/i386/kernel/io_apic.c index 3b7a63e0ed1a..e21dcde0790e 100644 --- a/trunk/arch/i386/kernel/io_apic.c +++ b/trunk/arch/i386/kernel/io_apic.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -153,14 +154,20 @@ static struct IO_APIC_route_entry ioapic_read_entry(int apic, int pin) * the interrupt, and we need to make sure the entry is fully populated * before that happens. */ -static void ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e) +static void +__ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e) { - unsigned long flags; union entry_union eu; eu.entry = e; - spin_lock_irqsave(&ioapic_lock, flags); io_apic_write(apic, 0x11 + 2*pin, eu.w2); io_apic_write(apic, 0x10 + 2*pin, eu.w1); +} + +static void ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e) +{ + unsigned long flags; + spin_lock_irqsave(&ioapic_lock, flags); + __ioapic_write_entry(apic, pin, e); spin_unlock_irqrestore(&ioapic_lock, flags); } @@ -836,8 +843,7 @@ static int __init find_isa_irq_pin(int irq, int type) if ((mp_bus_id_to_type[lbus] == MP_BUS_ISA || mp_bus_id_to_type[lbus] == MP_BUS_EISA || - mp_bus_id_to_type[lbus] == MP_BUS_MCA || - mp_bus_id_to_type[lbus] == MP_BUS_NEC98 + mp_bus_id_to_type[lbus] == MP_BUS_MCA ) && (mp_irqs[i].mpc_irqtype == type) && (mp_irqs[i].mpc_srcbusirq == irq)) @@ -856,8 +862,7 @@ static int __init find_isa_irq_apic(int irq, int type) if ((mp_bus_id_to_type[lbus] == MP_BUS_ISA || mp_bus_id_to_type[lbus] == MP_BUS_EISA || - mp_bus_id_to_type[lbus] == MP_BUS_MCA || - mp_bus_id_to_type[lbus] == MP_BUS_NEC98 + mp_bus_id_to_type[lbus] == MP_BUS_MCA ) && (mp_irqs[i].mpc_irqtype == type) && (mp_irqs[i].mpc_srcbusirq == irq)) @@ -987,12 +992,6 @@ static int EISA_ELCR(unsigned int irq) #define default_MCA_trigger(idx) (1) #define default_MCA_polarity(idx) (0) -/* NEC98 interrupts are always polarity zero edge triggered, - * when listed as conforming in the MP table. */ - -#define default_NEC98_trigger(idx) (0) -#define default_NEC98_polarity(idx) (0) - static int __init MPBIOS_polarity(int idx) { int bus = mp_irqs[idx].mpc_srcbus; @@ -1027,11 +1026,6 @@ static int __init MPBIOS_polarity(int idx) polarity = default_MCA_polarity(idx); break; } - case MP_BUS_NEC98: /* NEC 98 pin */ - { - polarity = default_NEC98_polarity(idx); - break; - } default: { printk(KERN_WARNING "broken BIOS!!\n"); @@ -1101,11 +1095,6 @@ static int MPBIOS_trigger(int idx) trigger = default_MCA_trigger(idx); break; } - case MP_BUS_NEC98: /* NEC 98 pin */ - { - trigger = default_NEC98_trigger(idx); - break; - } default: { printk(KERN_WARNING "broken BIOS!!\n"); @@ -1167,7 +1156,6 @@ static int pin_2_irq(int idx, int apic, int pin) case MP_BUS_ISA: /* ISA pin */ case MP_BUS_EISA: case MP_BUS_MCA: - case MP_BUS_NEC98: { irq = mp_irqs[idx].mpc_srcbusirq; break; @@ -1235,7 +1223,7 @@ static inline int IO_APIC_irq_trigger(int irq) } /* irq_vectors is indexed by the sum of all RTEs in all I/O APICs. */ -u8 irq_vector[NR_IRQ_VECTORS] __read_mostly = { FIRST_DEVICE_VECTOR , 0 }; +static u8 irq_vector[NR_IRQ_VECTORS] __read_mostly = { FIRST_DEVICE_VECTOR , 0 }; static int __assign_irq_vector(int irq) { @@ -1360,8 +1348,8 @@ static void __init setup_IO_APIC_irqs(void) if (!apic && (irq < 16)) disable_8259A_irq(irq); } - ioapic_write_entry(apic, pin, entry); spin_lock_irqsave(&ioapic_lock, flags); + __ioapic_write_entry(apic, pin, entry); set_native_irq_info(irq, TARGET_CPUS); spin_unlock_irqrestore(&ioapic_lock, flags); } @@ -1926,6 +1914,15 @@ static void __init setup_ioapic_ids_from_mpc(void) static void __init setup_ioapic_ids_from_mpc(void) { } #endif +static int no_timer_check __initdata; + +static int __init notimercheck(char *s) +{ + no_timer_check = 1; + return 1; +} +__setup("no_timer_check", notimercheck); + /* * There is a nasty bug in some older SMP boards, their mptable lies * about the timer IRQ. We do the following to work around the situation: @@ -1934,10 +1931,13 @@ static void __init setup_ioapic_ids_from_mpc(void) { } * - if this function detects that timer IRQs are defunct, then we fall * back to ISA timer IRQs */ -static int __init timer_irq_works(void) +int __init timer_irq_works(void) { unsigned long t1 = jiffies; + if (no_timer_check) + return 1; + local_irq_enable(); /* Let ten ticks pass... */ mdelay((10 * 1000) / HZ); @@ -2161,9 +2161,15 @@ static inline void unlock_ExtINT_logic(void) unsigned char save_control, save_freq_select; pin = find_isa_irq_pin(8, mp_INT); + if (pin == -1) { + WARN_ON_ONCE(1); + return; + } apic = find_isa_irq_apic(8, mp_INT); - if (pin == -1) + if (apic == -1) { + WARN_ON_ONCE(1); return; + } entry0 = ioapic_read_entry(apic, pin); clear_IO_APIC_pin(apic, pin); @@ -2208,7 +2214,7 @@ int timer_uses_ioapic_pin_0; * is so screwy. Thanks to Brian Perkins for testing/hacking this beast * fanatically on his truly buggy board. */ -static inline void check_timer(void) +static inline void __init check_timer(void) { int apic1, pin1, apic2, pin2; int vector; @@ -2856,8 +2862,8 @@ int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int a if (!ioapic && (irq < 16)) disable_8259A_irq(irq); - ioapic_write_entry(ioapic, pin, entry); spin_lock_irqsave(&ioapic_lock, flags); + __ioapic_write_entry(ioapic, pin, entry); set_native_irq_info(irq, TARGET_CPUS); spin_unlock_irqrestore(&ioapic_lock, flags); diff --git a/trunk/arch/i386/kernel/kprobes.c b/trunk/arch/i386/kernel/kprobes.c index fc79e1e859c4..af1d53344993 100644 --- a/trunk/arch/i386/kernel/kprobes.c +++ b/trunk/arch/i386/kernel/kprobes.c @@ -184,7 +184,7 @@ void __kprobes arch_disarm_kprobe(struct kprobe *p) void __kprobes arch_remove_kprobe(struct kprobe *p) { mutex_lock(&kprobe_mutex); - free_insn_slot(p->ainsn.insn); + free_insn_slot(p->ainsn.insn, (p->ainsn.boostable == 1)); mutex_unlock(&kprobe_mutex); } @@ -333,7 +333,7 @@ static int __kprobes kprobe_handler(struct pt_regs *regs) return 1; ss_probe: -#ifndef CONFIG_PREEMPT +#if !defined(CONFIG_PREEMPT) || defined(CONFIG_PM) if (p->ainsn.boostable == 1 && !p->post_handler){ /* Boost up -- we can execute copied instructions directly */ reset_current_kprobe(); diff --git a/trunk/arch/i386/kernel/ldt.c b/trunk/arch/i386/kernel/ldt.c index 445211eb2d57..b410e5fb034f 100644 --- a/trunk/arch/i386/kernel/ldt.c +++ b/trunk/arch/i386/kernel/ldt.c @@ -160,16 +160,14 @@ static int read_default_ldt(void __user * ptr, unsigned long bytecount) { int err; unsigned long size; - void *address; err = 0; - address = &default_ldt[0]; size = 5*sizeof(struct desc_struct); if (size > bytecount) size = bytecount; err = size; - if (copy_to_user(ptr, address, size)) + if (clear_user(ptr, size)) err = -EFAULT; return err; diff --git a/trunk/arch/i386/kernel/mca.c b/trunk/arch/i386/kernel/mca.c index eb57a851789d..b83672b89527 100644 --- a/trunk/arch/i386/kernel/mca.c +++ b/trunk/arch/i386/kernel/mca.c @@ -283,10 +283,9 @@ static int __init mca_init(void) bus->f.mca_transform_memory = mca_dummy_transform_memory; /* get the motherboard device */ - mca_dev = kmalloc(sizeof(struct mca_device), GFP_KERNEL); + mca_dev = kzalloc(sizeof(struct mca_device), GFP_KERNEL); if(unlikely(!mca_dev)) goto out_nomem; - memset(mca_dev, 0, sizeof(struct mca_device)); /* * We do not expect many MCA interrupts during initialization, @@ -310,11 +309,9 @@ static int __init mca_init(void) mca_dev->slot = MCA_MOTHERBOARD; mca_register_device(MCA_PRIMARY_BUS, mca_dev); - mca_dev = kmalloc(sizeof(struct mca_device), GFP_ATOMIC); + mca_dev = kzalloc(sizeof(struct mca_device), GFP_ATOMIC); if(unlikely(!mca_dev)) goto out_unlock_nomem; - memset(mca_dev, 0, sizeof(struct mca_device)); - /* Put motherboard into video setup mode, read integrated video * POS registers, and turn motherboard setup off. @@ -349,10 +346,9 @@ static int __init mca_init(void) } if(which_scsi) { /* found a scsi card */ - mca_dev = kmalloc(sizeof(struct mca_device), GFP_ATOMIC); + mca_dev = kzalloc(sizeof(struct mca_device), GFP_ATOMIC); if(unlikely(!mca_dev)) goto out_unlock_nomem; - memset(mca_dev, 0, sizeof(struct mca_device)); for(j = 0; j < 8; j++) mca_dev->pos[j] = pos[j]; @@ -378,10 +374,9 @@ static int __init mca_init(void) if(!mca_read_and_store_pos(pos)) continue; - mca_dev = kmalloc(sizeof(struct mca_device), GFP_ATOMIC); + mca_dev = kzalloc(sizeof(struct mca_device), GFP_ATOMIC); if(unlikely(!mca_dev)) goto out_unlock_nomem; - memset(mca_dev, 0, sizeof(struct mca_device)); for(j=0; j<8; j++) mca_dev->pos[j]=pos[j]; diff --git a/trunk/arch/i386/kernel/microcode.c b/trunk/arch/i386/kernel/microcode.c index 23f5984d0654..972346604f9d 100644 --- a/trunk/arch/i386/kernel/microcode.c +++ b/trunk/arch/i386/kernel/microcode.c @@ -703,7 +703,6 @@ static struct sysdev_driver mc_sysdev_driver = { .resume = mc_sysdev_resume, }; -#ifdef CONFIG_HOTPLUG_CPU static __cpuinit int mc_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu) { @@ -726,7 +725,6 @@ mc_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu) static struct notifier_block mc_cpu_notifier = { .notifier_call = mc_cpu_callback, }; -#endif static int __init microcode_init (void) { diff --git a/trunk/arch/i386/kernel/module.c b/trunk/arch/i386/kernel/module.c index 470cf97e7cd3..3db0a5442eb1 100644 --- a/trunk/arch/i386/kernel/module.c +++ b/trunk/arch/i386/kernel/module.c @@ -21,6 +21,7 @@ #include #include #include +#include #if 0 #define DEBUGP printk @@ -108,7 +109,8 @@ int module_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs, struct module *me) { - const Elf_Shdr *s, *text = NULL, *alt = NULL, *locks = NULL; + const Elf_Shdr *s, *text = NULL, *alt = NULL, *locks = NULL, + *para = NULL; char *secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; for (s = sechdrs; s < sechdrs + hdr->e_shnum; s++) { @@ -118,6 +120,8 @@ int module_finalize(const Elf_Ehdr *hdr, alt = s; if (!strcmp(".smp_locks", secstrings + s->sh_name)) locks= s; + if (!strcmp(".parainstructions", secstrings + s->sh_name)) + para = s; } if (alt) { @@ -132,10 +136,17 @@ int module_finalize(const Elf_Ehdr *hdr, lseg, lseg + locks->sh_size, tseg, tseg + text->sh_size); } - return 0; + + if (para) { + void *pseg = (void *)para->sh_addr; + apply_paravirt(pseg, pseg + para->sh_size); + } + + return module_bug_finalize(hdr, sechdrs, me); } void module_arch_cleanup(struct module *mod) { alternatives_smp_module_del(mod); + module_bug_cleanup(mod); } diff --git a/trunk/arch/i386/kernel/mpparse.c b/trunk/arch/i386/kernel/mpparse.c index 442aaf8c77eb..2ce67228dff8 100644 --- a/trunk/arch/i386/kernel/mpparse.c +++ b/trunk/arch/i386/kernel/mpparse.c @@ -249,8 +249,6 @@ static void __init MP_bus_info (struct mpc_config_bus *m) mp_current_pci_id++; } else if (strncmp(str, BUSTYPE_MCA, sizeof(BUSTYPE_MCA)-1) == 0) { mp_bus_id_to_type[m->mpc_busid] = MP_BUS_MCA; - } else if (strncmp(str, BUSTYPE_NEC98, sizeof(BUSTYPE_NEC98)-1) == 0) { - mp_bus_id_to_type[m->mpc_busid] = MP_BUS_NEC98; } else { printk(KERN_WARNING "Unknown bustype %s - ignoring\n", str); } diff --git a/trunk/arch/i386/kernel/msr.c b/trunk/arch/i386/kernel/msr.c index a773f776c9ea..4a472a17d1c6 100644 --- a/trunk/arch/i386/kernel/msr.c +++ b/trunk/arch/i386/kernel/msr.c @@ -172,7 +172,7 @@ static ssize_t msr_read(struct file *file, char __user * buf, u32 __user *tmp = (u32 __user *) buf; u32 data[2]; u32 reg = *ppos; - int cpu = iminor(file->f_dentry->d_inode); + int cpu = iminor(file->f_path.dentry->d_inode); int err; if (count % 8) @@ -195,15 +195,14 @@ static ssize_t msr_write(struct file *file, const char __user *buf, { const u32 __user *tmp = (const u32 __user *)buf; u32 data[2]; - size_t rv; u32 reg = *ppos; - int cpu = iminor(file->f_dentry->d_inode); + int cpu = iminor(file->f_path.dentry->d_inode); int err; if (count % 8) return -EINVAL; /* Invalid chunk size */ - for (rv = 0; count; count -= 8) { + for (; count; count -= 8) { if (copy_from_user(&data, tmp, 8)) return -EFAULT; err = do_wrmsr(cpu, reg, data[0], data[1]); @@ -217,7 +216,7 @@ static ssize_t msr_write(struct file *file, const char __user *buf, static int msr_open(struct inode *inode, struct file *file) { - unsigned int cpu = iminor(file->f_dentry->d_inode); + unsigned int cpu = iminor(file->f_path.dentry->d_inode); struct cpuinfo_x86 *c = &(cpu_data)[cpu]; if (cpu >= NR_CPUS || !cpu_online(cpu)) @@ -250,7 +249,6 @@ static int msr_device_create(int i) return err; } -#ifdef CONFIG_HOTPLUG_CPU static int msr_class_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { @@ -271,7 +269,6 @@ static struct notifier_block __cpuinitdata msr_class_cpu_notifier = { .notifier_call = msr_class_cpu_callback, }; -#endif static int __init msr_init(void) { diff --git a/trunk/arch/i386/kernel/nmi.c b/trunk/arch/i386/kernel/nmi.c index eaafe233a5da..f5bc7e1be801 100644 --- a/trunk/arch/i386/kernel/nmi.c +++ b/trunk/arch/i386/kernel/nmi.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -42,6 +43,8 @@ int nmi_watchdog_enabled; static DEFINE_PER_CPU(unsigned long, perfctr_nmi_owner); static DEFINE_PER_CPU(unsigned long, evntsel_nmi_owner[3]); +static cpumask_t backtrace_mask = CPU_MASK_NONE; + /* this number is calculated from Intel's MSR_P4_CRU_ESCR5 register and it's * offset from MSR_P4_BSU_ESCR0. It will be the max for all platforms (for now) */ @@ -867,14 +870,16 @@ static unsigned int void touch_nmi_watchdog (void) { - int i; + if (nmi_watchdog > 0) { + unsigned cpu; - /* - * Just reset the alert counters, (other CPUs might be - * spinning on locks we hold): - */ - for_each_possible_cpu(i) - alert_counter[i] = 0; + /* + * Just reset the alert counters, (other CPUs might be + * spinning on locks we hold): + */ + for_each_present_cpu (cpu) + alert_counter[cpu] = 0; + } /* * Tickle the softlockup detector too: @@ -907,6 +912,16 @@ __kprobes int nmi_watchdog_tick(struct pt_regs * regs, unsigned reason) touched = 1; } + if (cpu_isset(cpu, backtrace_mask)) { + static DEFINE_SPINLOCK(lock); /* Serialise the printks */ + + spin_lock(&lock); + printk("NMI backtrace for cpu %d\n", cpu); + dump_stack(); + spin_unlock(&lock); + cpu_clear(cpu, backtrace_mask); + } + sum = per_cpu(irq_stat, cpu).apic_timer_irqs; /* if the apic timer isn't firing, this cpu isn't doing much */ @@ -1033,6 +1048,19 @@ int proc_nmi_enabled(struct ctl_table *table, int write, struct file *file, #endif +void __trigger_all_cpu_backtrace(void) +{ + int i; + + backtrace_mask = cpu_online_map; + /* Wait for up to 10 seconds for all CPUs to do the backtrace */ + for (i = 0; i < 10 * 1000; i++) { + if (cpus_empty(backtrace_mask)) + break; + mdelay(1); + } +} + EXPORT_SYMBOL(nmi_active); EXPORT_SYMBOL(nmi_watchdog); EXPORT_SYMBOL(avail_to_resrv_perfctr_nmi); diff --git a/trunk/arch/i386/kernel/paravirt.c b/trunk/arch/i386/kernel/paravirt.c new file mode 100644 index 000000000000..3dceab5828f1 --- /dev/null +++ b/trunk/arch/i386/kernel/paravirt.c @@ -0,0 +1,569 @@ +/* Paravirtualization interfaces + Copyright (C) 2006 Rusty Russell IBM Corporation + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* nop stub */ +static void native_nop(void) +{ +} + +static void __init default_banner(void) +{ + printk(KERN_INFO "Booting paravirtualized kernel on %s\n", + paravirt_ops.name); +} + +char *memory_setup(void) +{ + return paravirt_ops.memory_setup(); +} + +/* Simple instruction patching code. */ +#define DEF_NATIVE(name, code) \ + extern const char start_##name[], end_##name[]; \ + asm("start_" #name ": " code "; end_" #name ":") +DEF_NATIVE(cli, "cli"); +DEF_NATIVE(sti, "sti"); +DEF_NATIVE(popf, "push %eax; popf"); +DEF_NATIVE(pushf, "pushf; pop %eax"); +DEF_NATIVE(pushf_cli, "pushf; pop %eax; cli"); +DEF_NATIVE(iret, "iret"); +DEF_NATIVE(sti_sysexit, "sti; sysexit"); + +static const struct native_insns +{ + const char *start, *end; +} native_insns[] = { + [PARAVIRT_IRQ_DISABLE] = { start_cli, end_cli }, + [PARAVIRT_IRQ_ENABLE] = { start_sti, end_sti }, + [PARAVIRT_RESTORE_FLAGS] = { start_popf, end_popf }, + [PARAVIRT_SAVE_FLAGS] = { start_pushf, end_pushf }, + [PARAVIRT_SAVE_FLAGS_IRQ_DISABLE] = { start_pushf_cli, end_pushf_cli }, + [PARAVIRT_INTERRUPT_RETURN] = { start_iret, end_iret }, + [PARAVIRT_STI_SYSEXIT] = { start_sti_sysexit, end_sti_sysexit }, +}; + +static unsigned native_patch(u8 type, u16 clobbers, void *insns, unsigned len) +{ + unsigned int insn_len; + + /* Don't touch it if we don't have a replacement */ + if (type >= ARRAY_SIZE(native_insns) || !native_insns[type].start) + return len; + + insn_len = native_insns[type].end - native_insns[type].start; + + /* Similarly if we can't fit replacement. */ + if (len < insn_len) + return len; + + memcpy(insns, native_insns[type].start, insn_len); + return insn_len; +} + +static fastcall unsigned long native_get_debugreg(int regno) +{ + unsigned long val = 0; /* Damn you, gcc! */ + + switch (regno) { + case 0: + asm("movl %%db0, %0" :"=r" (val)); break; + case 1: + asm("movl %%db1, %0" :"=r" (val)); break; + case 2: + asm("movl %%db2, %0" :"=r" (val)); break; + case 3: + asm("movl %%db3, %0" :"=r" (val)); break; + case 6: + asm("movl %%db6, %0" :"=r" (val)); break; + case 7: + asm("movl %%db7, %0" :"=r" (val)); break; + default: + BUG(); + } + return val; +} + +static fastcall void native_set_debugreg(int regno, unsigned long value) +{ + switch (regno) { + case 0: + asm("movl %0,%%db0" : /* no output */ :"r" (value)); + break; + case 1: + asm("movl %0,%%db1" : /* no output */ :"r" (value)); + break; + case 2: + asm("movl %0,%%db2" : /* no output */ :"r" (value)); + break; + case 3: + asm("movl %0,%%db3" : /* no output */ :"r" (value)); + break; + case 6: + asm("movl %0,%%db6" : /* no output */ :"r" (value)); + break; + case 7: + asm("movl %0,%%db7" : /* no output */ :"r" (value)); + break; + default: + BUG(); + } +} + +void init_IRQ(void) +{ + paravirt_ops.init_IRQ(); +} + +static fastcall void native_clts(void) +{ + asm volatile ("clts"); +} + +static fastcall unsigned long native_read_cr0(void) +{ + unsigned long val; + asm volatile("movl %%cr0,%0\n\t" :"=r" (val)); + return val; +} + +static fastcall void native_write_cr0(unsigned long val) +{ + asm volatile("movl %0,%%cr0": :"r" (val)); +} + +static fastcall unsigned long native_read_cr2(void) +{ + unsigned long val; + asm volatile("movl %%cr2,%0\n\t" :"=r" (val)); + return val; +} + +static fastcall void native_write_cr2(unsigned long val) +{ + asm volatile("movl %0,%%cr2": :"r" (val)); +} + +static fastcall unsigned long native_read_cr3(void) +{ + unsigned long val; + asm volatile("movl %%cr3,%0\n\t" :"=r" (val)); + return val; +} + +static fastcall void native_write_cr3(unsigned long val) +{ + asm volatile("movl %0,%%cr3": :"r" (val)); +} + +static fastcall unsigned long native_read_cr4(void) +{ + unsigned long val; + asm volatile("movl %%cr4,%0\n\t" :"=r" (val)); + return val; +} + +static fastcall unsigned long native_read_cr4_safe(void) +{ + unsigned long val; + /* This could fault if %cr4 does not exist */ + asm("1: movl %%cr4, %0 \n" + "2: \n" + ".section __ex_table,\"a\" \n" + ".long 1b,2b \n" + ".previous \n" + : "=r" (val): "0" (0)); + return val; +} + +static fastcall void native_write_cr4(unsigned long val) +{ + asm volatile("movl %0,%%cr4": :"r" (val)); +} + +static fastcall unsigned long native_save_fl(void) +{ + unsigned long f; + asm volatile("pushfl ; popl %0":"=g" (f): /* no input */); + return f; +} + +static fastcall void native_restore_fl(unsigned long f) +{ + asm volatile("pushl %0 ; popfl": /* no output */ + :"g" (f) + :"memory", "cc"); +} + +static fastcall void native_irq_disable(void) +{ + asm volatile("cli": : :"memory"); +} + +static fastcall void native_irq_enable(void) +{ + asm volatile("sti": : :"memory"); +} + +static fastcall void native_safe_halt(void) +{ + asm volatile("sti; hlt": : :"memory"); +} + +static fastcall void native_halt(void) +{ + asm volatile("hlt": : :"memory"); +} + +static fastcall void native_wbinvd(void) +{ + asm volatile("wbinvd": : :"memory"); +} + +static fastcall unsigned long long native_read_msr(unsigned int msr, int *err) +{ + unsigned long long val; + + asm volatile("2: rdmsr ; xorl %0,%0\n" + "1:\n\t" + ".section .fixup,\"ax\"\n\t" + "3: movl %3,%0 ; jmp 1b\n\t" + ".previous\n\t" + ".section __ex_table,\"a\"\n" + " .align 4\n\t" + " .long 2b,3b\n\t" + ".previous" + : "=r" (*err), "=A" (val) + : "c" (msr), "i" (-EFAULT)); + + return val; +} + +static fastcall int native_write_msr(unsigned int msr, unsigned long long val) +{ + int err; + asm volatile("2: wrmsr ; xorl %0,%0\n" + "1:\n\t" + ".section .fixup,\"ax\"\n\t" + "3: movl %4,%0 ; jmp 1b\n\t" + ".previous\n\t" + ".section __ex_table,\"a\"\n" + " .align 4\n\t" + " .long 2b,3b\n\t" + ".previous" + : "=a" (err) + : "c" (msr), "0" ((u32)val), "d" ((u32)(val>>32)), + "i" (-EFAULT)); + return err; +} + +static fastcall unsigned long long native_read_tsc(void) +{ + unsigned long long val; + asm volatile("rdtsc" : "=A" (val)); + return val; +} + +static fastcall unsigned long long native_read_pmc(void) +{ + unsigned long long val; + asm volatile("rdpmc" : "=A" (val)); + return val; +} + +static fastcall void native_load_tr_desc(void) +{ + asm volatile("ltr %w0"::"q" (GDT_ENTRY_TSS*8)); +} + +static fastcall void native_load_gdt(const struct Xgt_desc_struct *dtr) +{ + asm volatile("lgdt %0"::"m" (*dtr)); +} + +static fastcall void native_load_idt(const struct Xgt_desc_struct *dtr) +{ + asm volatile("lidt %0"::"m" (*dtr)); +} + +static fastcall void native_store_gdt(struct Xgt_desc_struct *dtr) +{ + asm ("sgdt %0":"=m" (*dtr)); +} + +static fastcall void native_store_idt(struct Xgt_desc_struct *dtr) +{ + asm ("sidt %0":"=m" (*dtr)); +} + +static fastcall unsigned long native_store_tr(void) +{ + unsigned long tr; + asm ("str %0":"=r" (tr)); + return tr; +} + +static fastcall void native_load_tls(struct thread_struct *t, unsigned int cpu) +{ +#define C(i) get_cpu_gdt_table(cpu)[GDT_ENTRY_TLS_MIN + i] = t->tls_array[i] + C(0); C(1); C(2); +#undef C +} + +static inline void native_write_dt_entry(void *dt, int entry, u32 entry_low, u32 entry_high) +{ + u32 *lp = (u32 *)((char *)dt + entry*8); + lp[0] = entry_low; + lp[1] = entry_high; +} + +static fastcall void native_write_ldt_entry(void *dt, int entrynum, u32 low, u32 high) +{ + native_write_dt_entry(dt, entrynum, low, high); +} + +static fastcall void native_write_gdt_entry(void *dt, int entrynum, u32 low, u32 high) +{ + native_write_dt_entry(dt, entrynum, low, high); +} + +static fastcall void native_write_idt_entry(void *dt, int entrynum, u32 low, u32 high) +{ + native_write_dt_entry(dt, entrynum, low, high); +} + +static fastcall void native_load_esp0(struct tss_struct *tss, + struct thread_struct *thread) +{ + tss->esp0 = thread->esp0; + + /* This can only happen when SEP is enabled, no need to test "SEP"arately */ + if (unlikely(tss->ss1 != thread->sysenter_cs)) { + tss->ss1 = thread->sysenter_cs; + wrmsr(MSR_IA32_SYSENTER_CS, thread->sysenter_cs, 0); + } +} + +static fastcall void native_io_delay(void) +{ + asm volatile("outb %al,$0x80"); +} + +static fastcall void native_flush_tlb(void) +{ + __native_flush_tlb(); +} + +/* + * Global pages have to be flushed a bit differently. Not a real + * performance problem because this does not happen often. + */ +static fastcall void native_flush_tlb_global(void) +{ + __native_flush_tlb_global(); +} + +static fastcall void native_flush_tlb_single(u32 addr) +{ + __native_flush_tlb_single(addr); +} + +#ifndef CONFIG_X86_PAE +static fastcall void native_set_pte(pte_t *ptep, pte_t pteval) +{ + *ptep = pteval; +} + +static fastcall void native_set_pte_at(struct mm_struct *mm, u32 addr, pte_t *ptep, pte_t pteval) +{ + *ptep = pteval; +} + +static fastcall void native_set_pmd(pmd_t *pmdp, pmd_t pmdval) +{ + *pmdp = pmdval; +} + +#else /* CONFIG_X86_PAE */ + +static fastcall void native_set_pte(pte_t *ptep, pte_t pte) +{ + ptep->pte_high = pte.pte_high; + smp_wmb(); + ptep->pte_low = pte.pte_low; +} + +static fastcall void native_set_pte_at(struct mm_struct *mm, u32 addr, pte_t *ptep, pte_t pte) +{ + ptep->pte_high = pte.pte_high; + smp_wmb(); + ptep->pte_low = pte.pte_low; +} + +static fastcall void native_set_pte_present(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pte) +{ + ptep->pte_low = 0; + smp_wmb(); + ptep->pte_high = pte.pte_high; + smp_wmb(); + ptep->pte_low = pte.pte_low; +} + +static fastcall void native_set_pte_atomic(pte_t *ptep, pte_t pteval) +{ + set_64bit((unsigned long long *)ptep,pte_val(pteval)); +} + +static fastcall void native_set_pmd(pmd_t *pmdp, pmd_t pmdval) +{ + set_64bit((unsigned long long *)pmdp,pmd_val(pmdval)); +} + +static fastcall void native_set_pud(pud_t *pudp, pud_t pudval) +{ + *pudp = pudval; +} + +static fastcall void native_pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) +{ + ptep->pte_low = 0; + smp_wmb(); + ptep->pte_high = 0; +} + +static fastcall void native_pmd_clear(pmd_t *pmd) +{ + u32 *tmp = (u32 *)pmd; + *tmp = 0; + smp_wmb(); + *(tmp + 1) = 0; +} +#endif /* CONFIG_X86_PAE */ + +/* These are in entry.S */ +extern fastcall void native_iret(void); +extern fastcall void native_irq_enable_sysexit(void); + +static int __init print_banner(void) +{ + paravirt_ops.banner(); + return 0; +} +core_initcall(print_banner); + +/* We simply declare start_kernel to be the paravirt probe of last resort. */ +paravirt_probe(start_kernel); + +struct paravirt_ops paravirt_ops = { + .name = "bare hardware", + .paravirt_enabled = 0, + .kernel_rpl = 0, + + .patch = native_patch, + .banner = default_banner, + .arch_setup = native_nop, + .memory_setup = machine_specific_memory_setup, + .get_wallclock = native_get_wallclock, + .set_wallclock = native_set_wallclock, + .time_init = time_init_hook, + .init_IRQ = native_init_IRQ, + + .cpuid = native_cpuid, + .get_debugreg = native_get_debugreg, + .set_debugreg = native_set_debugreg, + .clts = native_clts, + .read_cr0 = native_read_cr0, + .write_cr0 = native_write_cr0, + .read_cr2 = native_read_cr2, + .write_cr2 = native_write_cr2, + .read_cr3 = native_read_cr3, + .write_cr3 = native_write_cr3, + .read_cr4 = native_read_cr4, + .read_cr4_safe = native_read_cr4_safe, + .write_cr4 = native_write_cr4, + .save_fl = native_save_fl, + .restore_fl = native_restore_fl, + .irq_disable = native_irq_disable, + .irq_enable = native_irq_enable, + .safe_halt = native_safe_halt, + .halt = native_halt, + .wbinvd = native_wbinvd, + .read_msr = native_read_msr, + .write_msr = native_write_msr, + .read_tsc = native_read_tsc, + .read_pmc = native_read_pmc, + .load_tr_desc = native_load_tr_desc, + .set_ldt = native_set_ldt, + .load_gdt = native_load_gdt, + .load_idt = native_load_idt, + .store_gdt = native_store_gdt, + .store_idt = native_store_idt, + .store_tr = native_store_tr, + .load_tls = native_load_tls, + .write_ldt_entry = native_write_ldt_entry, + .write_gdt_entry = native_write_gdt_entry, + .write_idt_entry = native_write_idt_entry, + .load_esp0 = native_load_esp0, + + .set_iopl_mask = native_set_iopl_mask, + .io_delay = native_io_delay, + .const_udelay = __const_udelay, + +#ifdef CONFIG_X86_LOCAL_APIC + .apic_write = native_apic_write, + .apic_write_atomic = native_apic_write_atomic, + .apic_read = native_apic_read, +#endif + + .flush_tlb_user = native_flush_tlb, + .flush_tlb_kernel = native_flush_tlb_global, + .flush_tlb_single = native_flush_tlb_single, + + .set_pte = native_set_pte, + .set_pte_at = native_set_pte_at, + .set_pmd = native_set_pmd, + .pte_update = (void *)native_nop, + .pte_update_defer = (void *)native_nop, +#ifdef CONFIG_X86_PAE + .set_pte_atomic = native_set_pte_atomic, + .set_pte_present = native_set_pte_present, + .set_pud = native_set_pud, + .pte_clear = native_pte_clear, + .pmd_clear = native_pmd_clear, +#endif + + .irq_enable_sysexit = native_irq_enable_sysexit, + .iret = native_iret, +}; +EXPORT_SYMBOL(paravirt_ops); diff --git a/trunk/arch/i386/kernel/pci-dma.c b/trunk/arch/i386/kernel/pci-dma.c index 5c8c6ef1fc5e..41af692c1584 100644 --- a/trunk/arch/i386/kernel/pci-dma.c +++ b/trunk/arch/i386/kernel/pci-dma.c @@ -92,14 +92,12 @@ int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr, if (!mem_base) goto out; - dev->dma_mem = kmalloc(sizeof(struct dma_coherent_mem), GFP_KERNEL); + dev->dma_mem = kzalloc(sizeof(struct dma_coherent_mem), GFP_KERNEL); if (!dev->dma_mem) goto out; - memset(dev->dma_mem, 0, sizeof(struct dma_coherent_mem)); - dev->dma_mem->bitmap = kmalloc(bitmap_size, GFP_KERNEL); + dev->dma_mem->bitmap = kzalloc(bitmap_size, GFP_KERNEL); if (!dev->dma_mem->bitmap) goto free1_out; - memset(dev->dma_mem->bitmap, 0, bitmap_size); dev->dma_mem->virt_base = mem_base; dev->dma_mem->device_base = device_addr; diff --git a/trunk/arch/i386/kernel/process.c b/trunk/arch/i386/kernel/process.c index dd53c58f64f1..99308510a17c 100644 --- a/trunk/arch/i386/kernel/process.c +++ b/trunk/arch/i386/kernel/process.c @@ -56,6 +56,7 @@ #include #include +#include asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); @@ -99,22 +100,18 @@ EXPORT_SYMBOL(enable_hlt); */ void default_idle(void) { - local_irq_enable(); - if (!hlt_counter && boot_cpu_data.hlt_works_ok) { current_thread_info()->status &= ~TS_POLLING; smp_mb__after_clear_bit(); - while (!need_resched()) { - local_irq_disable(); - if (!need_resched()) - safe_halt(); - else - local_irq_enable(); - } + local_irq_disable(); + if (!need_resched()) + safe_halt(); /* enables interrupts racelessly */ + else + local_irq_enable(); current_thread_info()->status |= TS_POLLING; } else { - while (!need_resched()) - cpu_relax(); + /* loop is done by the caller */ + cpu_relax(); } } #ifdef CONFIG_APM_MODULE @@ -128,14 +125,7 @@ EXPORT_SYMBOL(default_idle); */ static void poll_idle (void) { - local_irq_enable(); - - asm volatile( - "2:" - "testl %0, %1;" - "rep; nop;" - "je 2b;" - : : "i"(_TIF_NEED_RESCHED), "m" (current_thread_info()->flags)); + cpu_relax(); } #ifdef CONFIG_HOTPLUG_CPU @@ -256,8 +246,7 @@ void mwait_idle_with_hints(unsigned long eax, unsigned long ecx) static void mwait_idle(void) { local_irq_enable(); - while (!need_resched()) - mwait_idle_with_hints(0, 0); + mwait_idle_with_hints(0, 0); } void __devinit select_idle_routine(const struct cpuinfo_x86 *c) @@ -314,8 +303,8 @@ void show_regs(struct pt_regs * regs) regs->eax,regs->ebx,regs->ecx,regs->edx); printk("ESI: %08lx EDI: %08lx EBP: %08lx", regs->esi, regs->edi, regs->ebp); - printk(" DS: %04x ES: %04x\n", - 0xffff & regs->xds,0xffff & regs->xes); + printk(" DS: %04x ES: %04x GS: %04x\n", + 0xffff & regs->xds,0xffff & regs->xes, 0xffff & regs->xgs); cr0 = read_cr0(); cr2 = read_cr2(); @@ -346,6 +335,7 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) regs.xds = __USER_DS; regs.xes = __USER_DS; + regs.xgs = __KERNEL_PDA; regs.orig_eax = -1; regs.eip = (unsigned long) kernel_thread_helper; regs.xcs = __KERNEL_CS | get_kernel_rpl(); @@ -431,7 +421,6 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long esp, p->thread.eip = (unsigned long) ret_from_fork; savesegment(fs,p->thread.fs); - savesegment(gs,p->thread.gs); tsk = current; if (unlikely(test_tsk_thread_flag(tsk, TIF_IO_BITMAP))) { @@ -508,7 +497,7 @@ void dump_thread(struct pt_regs * regs, struct user * dump) dump->regs.ds = regs->xds; dump->regs.es = regs->xes; savesegment(fs,dump->regs.fs); - savesegment(gs,dump->regs.gs); + dump->regs.gs = regs->xgs; dump->regs.orig_eax = regs->orig_eax; dump->regs.eip = regs->eip; dump->regs.cs = regs->xcs; @@ -648,22 +637,27 @@ struct task_struct fastcall * __switch_to(struct task_struct *prev_p, struct tas __unlazy_fpu(prev_p); + + /* we're going to use this soon, after a few expensive things */ + if (next_p->fpu_counter > 5) + prefetch(&next->i387.fxsave); + /* * Reload esp0. */ load_esp0(tss, next); /* - * Save away %fs and %gs. No need to save %es and %ds, as - * those are always kernel segments while inside the kernel. - * Doing this before setting the new TLS descriptors avoids - * the situation where we temporarily have non-reloadable - * segments in %fs and %gs. This could be an issue if the - * NMI handler ever used %fs or %gs (it does not today), or - * if the kernel is running inside of a hypervisor layer. + * Save away %fs. No need to save %gs, as it was saved on the + * stack on entry. No need to save %es and %ds, as those are + * always kernel segments while inside the kernel. Doing this + * before setting the new TLS descriptors avoids the situation + * where we temporarily have non-reloadable segments in %fs + * and %gs. This could be an issue if the NMI handler ever + * used %fs or %gs (it does not today), or if the kernel is + * running inside of a hypervisor layer. */ savesegment(fs, prev->fs); - savesegment(gs, prev->gs); /* * Load the per-thread Thread-Local Storage descriptor. @@ -671,22 +665,14 @@ struct task_struct fastcall * __switch_to(struct task_struct *prev_p, struct tas load_TLS(next, cpu); /* - * Restore %fs and %gs if needed. + * Restore %fs if needed. * - * Glibc normally makes %fs be zero, and %gs is one of - * the TLS segments. + * Glibc normally makes %fs be zero. */ if (unlikely(prev->fs | next->fs)) loadsegment(fs, next->fs); - if (prev->gs | next->gs) - loadsegment(gs, next->gs); - - /* - * Restore IOPL if needed. - */ - if (unlikely(prev->iopl != next->iopl)) - set_iopl_mask(next->iopl); + write_pda(pcurrent, next_p); /* * Now maybe handle debug registers and/or IO bitmaps @@ -697,6 +683,13 @@ struct task_struct fastcall * __switch_to(struct task_struct *prev_p, struct tas disable_tsc(prev_p, next_p); + /* If the task has used fpu the last 5 timeslices, just do a full + * restore of the math state immediately to avoid the trap; the + * chances of needing FPU soon are obviously high now + */ + if (next_p->fpu_counter > 5) + math_state_restore(); + return prev_p; } diff --git a/trunk/arch/i386/kernel/ptrace.c b/trunk/arch/i386/kernel/ptrace.c index 775f50e9395b..f3f94ac5736a 100644 --- a/trunk/arch/i386/kernel/ptrace.c +++ b/trunk/arch/i386/kernel/ptrace.c @@ -94,13 +94,9 @@ static int putreg(struct task_struct *child, return -EIO; child->thread.fs = value; return 0; - case GS: - if (value && (value & 3) != 3) - return -EIO; - child->thread.gs = value; - return 0; case DS: case ES: + case GS: if (value && (value & 3) != 3) return -EIO; value &= 0xffff; @@ -116,8 +112,8 @@ static int putreg(struct task_struct *child, value |= get_stack_long(child, EFL_OFFSET) & ~FLAG_MASK; break; } - if (regno > GS*4) - regno -= 2*4; + if (regno > ES*4) + regno -= 1*4; put_stack_long(child, regno - sizeof(struct pt_regs), value); return 0; } @@ -131,18 +127,16 @@ static unsigned long getreg(struct task_struct *child, case FS: retval = child->thread.fs; break; - case GS: - retval = child->thread.gs; - break; case DS: case ES: + case GS: case SS: case CS: retval = 0xffff; /* fall through */ default: - if (regno > GS*4) - regno -= 2*4; + if (regno > ES*4) + regno -= 1*4; regno = regno - sizeof(struct pt_regs); retval &= get_stack_long(child, regno); } diff --git a/trunk/arch/i386/kernel/quirks.c b/trunk/arch/i386/kernel/quirks.c index 9f6ab1789bb0..a01320a7b636 100644 --- a/trunk/arch/i386/kernel/quirks.c +++ b/trunk/arch/i386/kernel/quirks.c @@ -3,10 +3,23 @@ */ #include #include +#include +#include +#include #if defined(CONFIG_X86_IO_APIC) && defined(CONFIG_SMP) && defined(CONFIG_PCI) +static void __devinit verify_quirk_intel_irqbalance(struct pci_dev *dev) +{ +#ifdef CONFIG_X86_64 + if (genapic != &apic_flat) + panic("APIC mode must be flat on this system\n"); +#elif defined(CONFIG_X86_GENERICARCH) + if (genapic != &apic_default) + panic("APIC mode must be default(flat) on this system. Use apic=default\n"); +#endif +} -static void __devinit quirk_intel_irqbalance(struct pci_dev *dev) +void __init quirk_intel_irqbalance(void) { u8 config, rev; u32 word; @@ -16,18 +29,18 @@ static void __devinit quirk_intel_irqbalance(struct pci_dev *dev) * based platforms. * Disable SW irqbalance/affinity on those platforms. */ - pci_read_config_byte(dev, PCI_CLASS_REVISION, &rev); + rev = read_pci_config_byte(0, 0, 0, PCI_CLASS_REVISION); if (rev > 0x9) return; printk(KERN_INFO "Intel E7520/7320/7525 detected."); - /* enable access to config space*/ - pci_read_config_byte(dev, 0xf4, &config); - pci_write_config_byte(dev, 0xf4, config|0x2); + /* enable access to config space */ + config = read_pci_config_byte(0, 0, 0, 0xf4); + write_pci_config_byte(0, 0, 0, 0xf4, config|0x2); /* read xTPR register */ - raw_pci_ops->read(0, 0, 0x40, 0x4c, 2, &word); + word = read_pci_config_16(0, 0, 0x40, 0x4c); if (!(word & (1 << 13))) { printk(KERN_INFO "Disabling irq balancing and affinity\n"); @@ -37,14 +50,25 @@ static void __devinit quirk_intel_irqbalance(struct pci_dev *dev) noirqdebug_setup(""); #ifdef CONFIG_PROC_FS no_irq_affinity = 1; +#endif +#ifdef CONFIG_HOTPLUG_CPU + printk(KERN_INFO "Disabling cpu hotplug control\n"); + enable_cpu_hotplug = 0; +#endif +#ifdef CONFIG_X86_64 + /* force the genapic selection to flat mode so that + * interrupts can be redirected to more than one CPU. + */ + genapic_force = &apic_flat; #endif } - /* put back the original value for config space*/ + /* put back the original value for config space */ if (!(config & 0x2)) - pci_write_config_byte(dev, 0xf4, config); + write_pci_config_byte(0, 0, 0, 0xf4, config); } -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7320_MCH, quirk_intel_irqbalance); -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7525_MCH, quirk_intel_irqbalance); -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7520_MCH, quirk_intel_irqbalance); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7320_MCH, verify_quirk_intel_irqbalance); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7525_MCH, verify_quirk_intel_irqbalance); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7520_MCH, verify_quirk_intel_irqbalance); + #endif diff --git a/trunk/arch/i386/kernel/reboot.c b/trunk/arch/i386/kernel/reboot.c index 84278e0093a2..3514b4153f7f 100644 --- a/trunk/arch/i386/kernel/reboot.c +++ b/trunk/arch/i386/kernel/reboot.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include diff --git a/trunk/arch/i386/kernel/setup.c b/trunk/arch/i386/kernel/setup.c index 141041dde74d..79df6e612dbd 100644 --- a/trunk/arch/i386/kernel/setup.c +++ b/trunk/arch/i386/kernel/setup.c @@ -63,9 +63,6 @@ #include #include -/* Forward Declaration. */ -void __init find_max_pfn(void); - /* This value is set up by the early boot code to point to the value immediately after the boot time page tables. It contains a *physical* address, and must not be in the .bss segment! */ @@ -76,11 +73,8 @@ int disable_pse __devinitdata = 0; /* * Machine setup.. */ - -#ifdef CONFIG_EFI -int efi_enabled = 0; -EXPORT_SYMBOL(efi_enabled); -#endif +extern struct resource code_resource; +extern struct resource data_resource; /* cpu data as detected by the assembly code in head.S */ struct cpuinfo_x86 new_cpu_data __initdata = { 0, 0, 0, 0, -1, 1, 0, 0, -1 }; @@ -99,12 +93,6 @@ unsigned int machine_submodel_id; unsigned int BIOS_revision; unsigned int mca_pentium_flag; -/* For PCI or other memory-mapped resources */ -unsigned long pci_mem_start = 0x10000000; -#ifdef CONFIG_PCI -EXPORT_SYMBOL(pci_mem_start); -#endif - /* Boot loader ID as an integer, for the benefit of proc_dointvec */ int bootloader_type; @@ -134,7 +122,6 @@ struct ist_info ist_info; defined(CONFIG_X86_SPEEDSTEP_SMI_MODULE) EXPORT_SYMBOL(ist_info); #endif -struct e820map e820; extern void early_cpu_init(void); extern int root_mountflags; @@ -149,516 +136,6 @@ static char command_line[COMMAND_LINE_SIZE]; unsigned char __initdata boot_params[PARAM_SIZE]; -static struct resource data_resource = { - .name = "Kernel data", - .start = 0, - .end = 0, - .flags = IORESOURCE_BUSY | IORESOURCE_MEM -}; - -static struct resource code_resource = { - .name = "Kernel code", - .start = 0, - .end = 0, - .flags = IORESOURCE_BUSY | IORESOURCE_MEM -}; - -static struct resource system_rom_resource = { - .name = "System ROM", - .start = 0xf0000, - .end = 0xfffff, - .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM -}; - -static struct resource extension_rom_resource = { - .name = "Extension ROM", - .start = 0xe0000, - .end = 0xeffff, - .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM -}; - -static struct resource adapter_rom_resources[] = { { - .name = "Adapter ROM", - .start = 0xc8000, - .end = 0, - .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM -}, { - .name = "Adapter ROM", - .start = 0, - .end = 0, - .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM -}, { - .name = "Adapter ROM", - .start = 0, - .end = 0, - .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM -}, { - .name = "Adapter ROM", - .start = 0, - .end = 0, - .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM -}, { - .name = "Adapter ROM", - .start = 0, - .end = 0, - .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM -}, { - .name = "Adapter ROM", - .start = 0, - .end = 0, - .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM -} }; - -static struct resource video_rom_resource = { - .name = "Video ROM", - .start = 0xc0000, - .end = 0xc7fff, - .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM -}; - -static struct resource video_ram_resource = { - .name = "Video RAM area", - .start = 0xa0000, - .end = 0xbffff, - .flags = IORESOURCE_BUSY | IORESOURCE_MEM -}; - -static struct resource standard_io_resources[] = { { - .name = "dma1", - .start = 0x0000, - .end = 0x001f, - .flags = IORESOURCE_BUSY | IORESOURCE_IO -}, { - .name = "pic1", - .start = 0x0020, - .end = 0x0021, - .flags = IORESOURCE_BUSY | IORESOURCE_IO -}, { - .name = "timer0", - .start = 0x0040, - .end = 0x0043, - .flags = IORESOURCE_BUSY | IORESOURCE_IO -}, { - .name = "timer1", - .start = 0x0050, - .end = 0x0053, - .flags = IORESOURCE_BUSY | IORESOURCE_IO -}, { - .name = "keyboard", - .start = 0x0060, - .end = 0x006f, - .flags = IORESOURCE_BUSY | IORESOURCE_IO -}, { - .name = "dma page reg", - .start = 0x0080, - .end = 0x008f, - .flags = IORESOURCE_BUSY | IORESOURCE_IO -}, { - .name = "pic2", - .start = 0x00a0, - .end = 0x00a1, - .flags = IORESOURCE_BUSY | IORESOURCE_IO -}, { - .name = "dma2", - .start = 0x00c0, - .end = 0x00df, - .flags = IORESOURCE_BUSY | IORESOURCE_IO -}, { - .name = "fpu", - .start = 0x00f0, - .end = 0x00ff, - .flags = IORESOURCE_BUSY | IORESOURCE_IO -} }; - -#define romsignature(x) (*(unsigned short *)(x) == 0xaa55) - -static int __init romchecksum(unsigned char *rom, unsigned long length) -{ - unsigned char *p, sum = 0; - - for (p = rom; p < rom + length; p++) - sum += *p; - return sum == 0; -} - -static void __init probe_roms(void) -{ - unsigned long start, length, upper; - unsigned char *rom; - int i; - - /* video rom */ - upper = adapter_rom_resources[0].start; - for (start = video_rom_resource.start; start < upper; start += 2048) { - rom = isa_bus_to_virt(start); - if (!romsignature(rom)) - continue; - - video_rom_resource.start = start; - - /* 0 < length <= 0x7f * 512, historically */ - length = rom[2] * 512; - - /* if checksum okay, trust length byte */ - if (length && romchecksum(rom, length)) - video_rom_resource.end = start + length - 1; - - request_resource(&iomem_resource, &video_rom_resource); - break; - } - - start = (video_rom_resource.end + 1 + 2047) & ~2047UL; - if (start < upper) - start = upper; - - /* system rom */ - request_resource(&iomem_resource, &system_rom_resource); - upper = system_rom_resource.start; - - /* check for extension rom (ignore length byte!) */ - rom = isa_bus_to_virt(extension_rom_resource.start); - if (romsignature(rom)) { - length = extension_rom_resource.end - extension_rom_resource.start + 1; - if (romchecksum(rom, length)) { - request_resource(&iomem_resource, &extension_rom_resource); - upper = extension_rom_resource.start; - } - } - - /* check for adapter roms on 2k boundaries */ - for (i = 0; i < ARRAY_SIZE(adapter_rom_resources) && start < upper; start += 2048) { - rom = isa_bus_to_virt(start); - if (!romsignature(rom)) - continue; - - /* 0 < length <= 0x7f * 512, historically */ - length = rom[2] * 512; - - /* but accept any length that fits if checksum okay */ - if (!length || start + length > upper || !romchecksum(rom, length)) - continue; - - adapter_rom_resources[i].start = start; - adapter_rom_resources[i].end = start + length - 1; - request_resource(&iomem_resource, &adapter_rom_resources[i]); - - start = adapter_rom_resources[i++].end & ~2047UL; - } -} - -static void __init limit_regions(unsigned long long size) -{ - unsigned long long current_addr = 0; - int i; - - if (efi_enabled) { - efi_memory_desc_t *md; - void *p; - - for (p = memmap.map, i = 0; p < memmap.map_end; - p += memmap.desc_size, i++) { - md = p; - current_addr = md->phys_addr + (md->num_pages << 12); - if (md->type == EFI_CONVENTIONAL_MEMORY) { - if (current_addr >= size) { - md->num_pages -= - (((current_addr-size) + PAGE_SIZE-1) >> PAGE_SHIFT); - memmap.nr_map = i + 1; - return; - } - } - } - } - for (i = 0; i < e820.nr_map; i++) { - current_addr = e820.map[i].addr + e820.map[i].size; - if (current_addr < size) - continue; - - if (e820.map[i].type != E820_RAM) - continue; - - if (e820.map[i].addr >= size) { - /* - * This region starts past the end of the - * requested size, skip it completely. - */ - e820.nr_map = i; - } else { - e820.nr_map = i + 1; - e820.map[i].size -= current_addr - size; - } - return; - } -} - -void __init add_memory_region(unsigned long long start, - unsigned long long size, int type) -{ - int x; - - if (!efi_enabled) { - x = e820.nr_map; - - if (x == E820MAX) { - printk(KERN_ERR "Ooops! Too many entries in the memory map!\n"); - return; - } - - e820.map[x].addr = start; - e820.map[x].size = size; - e820.map[x].type = type; - e820.nr_map++; - } -} /* add_memory_region */ - -#define E820_DEBUG 1 - -static void __init print_memory_map(char *who) -{ - int i; - - for (i = 0; i < e820.nr_map; i++) { - printk(" %s: %016Lx - %016Lx ", who, - e820.map[i].addr, - e820.map[i].addr + e820.map[i].size); - switch (e820.map[i].type) { - case E820_RAM: printk("(usable)\n"); - break; - case E820_RESERVED: - printk("(reserved)\n"); - break; - case E820_ACPI: - printk("(ACPI data)\n"); - break; - case E820_NVS: - printk("(ACPI NVS)\n"); - break; - default: printk("type %lu\n", e820.map[i].type); - break; - } - } -} - -/* - * Sanitize the BIOS e820 map. - * - * Some e820 responses include overlapping entries. The following - * replaces the original e820 map with a new one, removing overlaps. - * - */ -struct change_member { - struct e820entry *pbios; /* pointer to original bios entry */ - unsigned long long addr; /* address for this change point */ -}; -static struct change_member change_point_list[2*E820MAX] __initdata; -static struct change_member *change_point[2*E820MAX] __initdata; -static struct e820entry *overlap_list[E820MAX] __initdata; -static struct e820entry new_bios[E820MAX] __initdata; - -int __init sanitize_e820_map(struct e820entry * biosmap, char * pnr_map) -{ - struct change_member *change_tmp; - unsigned long current_type, last_type; - unsigned long long last_addr; - int chgidx, still_changing; - int overlap_entries; - int new_bios_entry; - int old_nr, new_nr, chg_nr; - int i; - - /* - Visually we're performing the following (1,2,3,4 = memory types)... - - Sample memory map (w/overlaps): - ____22__________________ - ______________________4_ - ____1111________________ - _44_____________________ - 11111111________________ - ____________________33__ - ___________44___________ - __________33333_________ - ______________22________ - ___________________2222_ - _________111111111______ - _____________________11_ - _________________4______ - - Sanitized equivalent (no overlap): - 1_______________________ - _44_____________________ - ___1____________________ - ____22__________________ - ______11________________ - _________1______________ - __________3_____________ - ___________44___________ - _____________33_________ - _______________2________ - ________________1_______ - _________________4______ - ___________________2____ - ____________________33__ - ______________________4_ - */ - - /* if there's only one memory region, don't bother */ - if (*pnr_map < 2) - return -1; - - old_nr = *pnr_map; - - /* bail out if we find any unreasonable addresses in bios map */ - for (i=0; iaddr = biosmap[i].addr; - change_point[chgidx++]->pbios = &biosmap[i]; - change_point[chgidx]->addr = biosmap[i].addr + biosmap[i].size; - change_point[chgidx++]->pbios = &biosmap[i]; - } - } - chg_nr = chgidx; /* true number of change-points */ - - /* sort change-point list by memory addresses (low -> high) */ - still_changing = 1; - while (still_changing) { - still_changing = 0; - for (i=1; i < chg_nr; i++) { - /* if > , swap */ - /* or, if current= & last=, swap */ - if ((change_point[i]->addr < change_point[i-1]->addr) || - ((change_point[i]->addr == change_point[i-1]->addr) && - (change_point[i]->addr == change_point[i]->pbios->addr) && - (change_point[i-1]->addr != change_point[i-1]->pbios->addr)) - ) - { - change_tmp = change_point[i]; - change_point[i] = change_point[i-1]; - change_point[i-1] = change_tmp; - still_changing=1; - } - } - } - - /* create a new bios memory map, removing overlaps */ - overlap_entries=0; /* number of entries in the overlap table */ - new_bios_entry=0; /* index for creating new bios map entries */ - last_type = 0; /* start with undefined memory type */ - last_addr = 0; /* start with 0 as last starting address */ - /* loop through change-points, determining affect on the new bios map */ - for (chgidx=0; chgidx < chg_nr; chgidx++) - { - /* keep track of all overlapping bios entries */ - if (change_point[chgidx]->addr == change_point[chgidx]->pbios->addr) - { - /* add map entry to overlap list (> 1 entry implies an overlap) */ - overlap_list[overlap_entries++]=change_point[chgidx]->pbios; - } - else - { - /* remove entry from list (order independent, so swap with last) */ - for (i=0; ipbios) - overlap_list[i] = overlap_list[overlap_entries-1]; - } - overlap_entries--; - } - /* if there are overlapping entries, decide which "type" to use */ - /* (larger value takes precedence -- 1=usable, 2,3,4,4+=unusable) */ - current_type = 0; - for (i=0; itype > current_type) - current_type = overlap_list[i]->type; - /* continue building up new bios map based on this information */ - if (current_type != last_type) { - if (last_type != 0) { - new_bios[new_bios_entry].size = - change_point[chgidx]->addr - last_addr; - /* move forward only if the new size was non-zero */ - if (new_bios[new_bios_entry].size != 0) - if (++new_bios_entry >= E820MAX) - break; /* no more space left for new bios entries */ - } - if (current_type != 0) { - new_bios[new_bios_entry].addr = change_point[chgidx]->addr; - new_bios[new_bios_entry].type = current_type; - last_addr=change_point[chgidx]->addr; - } - last_type = current_type; - } - } - new_nr = new_bios_entry; /* retain count for new bios entries */ - - /* copy new bios mapping into original location */ - memcpy(biosmap, new_bios, new_nr*sizeof(struct e820entry)); - *pnr_map = new_nr; - - return 0; -} - -/* - * Copy the BIOS e820 map into a safe place. - * - * Sanity-check it while we're at it.. - * - * If we're lucky and live on a modern system, the setup code - * will have given us a memory map that we can use to properly - * set up memory. If we aren't, we'll fake a memory map. - * - * We check to see that the memory map contains at least 2 elements - * before we'll use it, because the detection code in setup.S may - * not be perfect and most every PC known to man has two memory - * regions: one from 0 to 640k, and one from 1mb up. (The IBM - * thinkpad 560x, for example, does not cooperate with the memory - * detection code.) - */ -int __init copy_e820_map(struct e820entry * biosmap, int nr_map) -{ - /* Only one memory region (or negative)? Ignore it */ - if (nr_map < 2) - return -1; - - do { - unsigned long long start = biosmap->addr; - unsigned long long size = biosmap->size; - unsigned long long end = start + size; - unsigned long type = biosmap->type; - - /* Overflow in 64 bits? Ignore the memory map. */ - if (start > end) - return -1; - - /* - * Some BIOSes claim RAM in the 640k - 1M region. - * Not right. Fix it up. - */ - if (type == E820_RAM) { - if (start < 0x100000ULL && end > 0xA0000ULL) { - if (start < 0xA0000ULL) - add_memory_region(start, 0xA0000ULL-start, type); - if (end <= 0x100000ULL) - continue; - start = 0x100000ULL; - size = end - start; - } - } - add_memory_region(start, size, type); - } while (biosmap++,--nr_map); - return 0; -} - #if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE) struct edd edd; #ifdef CONFIG_EDD_MODULE @@ -682,7 +159,7 @@ static inline void copy_edd(void) } #endif -static int __initdata user_defined_memmap = 0; +int __initdata user_defined_memmap = 0; /* * "mem=nopentium" disables the 4MB page tables. @@ -719,51 +196,6 @@ static int __init parse_mem(char *arg) } early_param("mem", parse_mem); -static int __init parse_memmap(char *arg) -{ - if (!arg) - return -EINVAL; - - if (strcmp(arg, "exactmap") == 0) { -#ifdef CONFIG_CRASH_DUMP - /* If we are doing a crash dump, we - * still need to know the real mem - * size before original memory map is - * reset. - */ - find_max_pfn(); - saved_max_pfn = max_pfn; -#endif - e820.nr_map = 0; - user_defined_memmap = 1; - } else { - /* If the user specifies memory size, we - * limit the BIOS-provided memory map to - * that size. exactmap can be used to specify - * the exact map. mem=number can be used to - * trim the existing memory map. - */ - unsigned long long start_at, mem_size; - - mem_size = memparse(arg, &arg); - if (*arg == '@') { - start_at = memparse(arg+1, &arg); - add_memory_region(start_at, mem_size, E820_RAM); - } else if (*arg == '#') { - start_at = memparse(arg+1, &arg); - add_memory_region(start_at, mem_size, E820_ACPI); - } else if (*arg == '$') { - start_at = memparse(arg+1, &arg); - add_memory_region(start_at, mem_size, E820_RESERVED); - } else { - limit_regions(mem_size); - user_defined_memmap = 1; - } - } - return 0; -} -early_param("memmap", parse_memmap); - #ifdef CONFIG_PROC_VMCORE /* elfcorehdr= specifies the location of elf core header * stored by the crashed kernel. @@ -827,90 +259,6 @@ static int __init parse_reservetop(char *arg) } early_param("reservetop", parse_reservetop); -/* - * Callback for efi_memory_walk. - */ -static int __init -efi_find_max_pfn(unsigned long start, unsigned long end, void *arg) -{ - unsigned long *max_pfn = arg, pfn; - - if (start < end) { - pfn = PFN_UP(end -1); - if (pfn > *max_pfn) - *max_pfn = pfn; - } - return 0; -} - -static int __init -efi_memory_present_wrapper(unsigned long start, unsigned long end, void *arg) -{ - memory_present(0, PFN_UP(start), PFN_DOWN(end)); - return 0; -} - - /* - * This function checks if the entire range is mapped with type. - * - * Note: this function only works correct if the e820 table is sorted and - * not-overlapping, which is the case - */ -int __init -e820_all_mapped(unsigned long s, unsigned long e, unsigned type) -{ - u64 start = s; - u64 end = e; - int i; - for (i = 0; i < e820.nr_map; i++) { - struct e820entry *ei = &e820.map[i]; - if (type && ei->type != type) - continue; - /* is the region (part) in overlap with the current region ?*/ - if (ei->addr >= end || ei->addr + ei->size <= start) - continue; - /* if the region is at the beginning of we move - * start to the end of the region since it's ok until there - */ - if (ei->addr <= start) - start = ei->addr + ei->size; - /* if start is now at or beyond end, we're done, full - * coverage */ - if (start >= end) - return 1; /* we're done */ - } - return 0; -} - -/* - * Find the highest page frame number we have available - */ -void __init find_max_pfn(void) -{ - int i; - - max_pfn = 0; - if (efi_enabled) { - efi_memmap_walk(efi_find_max_pfn, &max_pfn); - efi_memmap_walk(efi_memory_present_wrapper, NULL); - return; - } - - for (i = 0; i < e820.nr_map; i++) { - unsigned long start, end; - /* RAM? */ - if (e820.map[i].type != E820_RAM) - continue; - start = PFN_UP(e820.map[i].addr); - end = PFN_DOWN(e820.map[i].addr + e820.map[i].size); - if (start >= end) - continue; - if (end > max_pfn) - max_pfn = end; - memory_present(0, start, end); - } -} - /* * Determine low and high memory ranges: */ @@ -970,68 +318,6 @@ unsigned long __init find_max_low_pfn(void) return max_low_pfn; } -/* - * Free all available memory for boot time allocation. Used - * as a callback function by efi_memory_walk() - */ - -static int __init -free_available_memory(unsigned long start, unsigned long end, void *arg) -{ - /* check max_low_pfn */ - if (start >= (max_low_pfn << PAGE_SHIFT)) - return 0; - if (end >= (max_low_pfn << PAGE_SHIFT)) - end = max_low_pfn << PAGE_SHIFT; - if (start < end) - free_bootmem(start, end - start); - - return 0; -} -/* - * Register fully available low RAM pages with the bootmem allocator. - */ -static void __init register_bootmem_low_pages(unsigned long max_low_pfn) -{ - int i; - - if (efi_enabled) { - efi_memmap_walk(free_available_memory, NULL); - return; - } - for (i = 0; i < e820.nr_map; i++) { - unsigned long curr_pfn, last_pfn, size; - /* - * Reserve usable low memory - */ - if (e820.map[i].type != E820_RAM) - continue; - /* - * We are rounding up the start address of usable memory: - */ - curr_pfn = PFN_UP(e820.map[i].addr); - if (curr_pfn >= max_low_pfn) - continue; - /* - * ... and at the end of the usable range downwards: - */ - last_pfn = PFN_DOWN(e820.map[i].addr + e820.map[i].size); - - if (last_pfn > max_low_pfn) - last_pfn = max_low_pfn; - - /* - * .. finally, did all the rounding and playing - * around just make the area go away? - */ - if (last_pfn <= curr_pfn) - continue; - - size = last_pfn - curr_pfn; - free_bootmem(PFN_PHYS(curr_pfn), PFN_PHYS(size)); - } -} - /* * workaround for Dell systems that neglect to reserve EBDA */ @@ -1118,8 +404,8 @@ void __init setup_bootmem_allocator(void) * the (very unlikely) case of us accidentally initializing the * bootmem allocator with an invalid RAM area. */ - reserve_bootmem(__PHYSICAL_START, (PFN_PHYS(min_low_pfn) + - bootmap_size + PAGE_SIZE-1) - (__PHYSICAL_START)); + reserve_bootmem(__pa_symbol(_text), (PFN_PHYS(min_low_pfn) + + bootmap_size + PAGE_SIZE-1) - __pa_symbol(_text)); /* * reserve physical page 0 - it's a special BIOS page on many boxes, @@ -1162,8 +448,7 @@ void __init setup_bootmem_allocator(void) if (LOADER_TYPE && INITRD_START) { if (INITRD_START + INITRD_SIZE <= (max_low_pfn << PAGE_SHIFT)) { reserve_bootmem(INITRD_START, INITRD_SIZE); - initrd_start = - INITRD_START ? INITRD_START + PAGE_OFFSET : 0; + initrd_start = INITRD_START + PAGE_OFFSET; initrd_end = initrd_start+INITRD_SIZE; } else { @@ -1200,126 +485,6 @@ void __init remapped_pgdat_init(void) } } -/* - * Request address space for all standard RAM and ROM resources - * and also for regions reported as reserved by the e820. - */ -static void __init -legacy_init_iomem_resources(struct resource *code_resource, struct resource *data_resource) -{ - int i; - - probe_roms(); - for (i = 0; i < e820.nr_map; i++) { - struct resource *res; -#ifndef CONFIG_RESOURCES_64BIT - if (e820.map[i].addr + e820.map[i].size > 0x100000000ULL) - continue; -#endif - res = kzalloc(sizeof(struct resource), GFP_ATOMIC); - switch (e820.map[i].type) { - case E820_RAM: res->name = "System RAM"; break; - case E820_ACPI: res->name = "ACPI Tables"; break; - case E820_NVS: res->name = "ACPI Non-volatile Storage"; break; - default: res->name = "reserved"; - } - res->start = e820.map[i].addr; - res->end = res->start + e820.map[i].size - 1; - res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; - if (request_resource(&iomem_resource, res)) { - kfree(res); - continue; - } - if (e820.map[i].type == E820_RAM) { - /* - * We don't know which RAM region contains kernel data, - * so we try it repeatedly and let the resource manager - * test it. - */ - request_resource(res, code_resource); - request_resource(res, data_resource); -#ifdef CONFIG_KEXEC - request_resource(res, &crashk_res); -#endif - } - } -} - -/* - * Request address space for all standard resources - * - * This is called just before pcibios_init(), which is also a - * subsys_initcall, but is linked in later (in arch/i386/pci/common.c). - */ -static int __init request_standard_resources(void) -{ - int i; - - printk("Setting up standard PCI resources\n"); - if (efi_enabled) - efi_initialize_iomem_resources(&code_resource, &data_resource); - else - legacy_init_iomem_resources(&code_resource, &data_resource); - - /* EFI systems may still have VGA */ - request_resource(&iomem_resource, &video_ram_resource); - - /* request I/O space for devices used on all i[345]86 PCs */ - for (i = 0; i < ARRAY_SIZE(standard_io_resources); i++) - request_resource(&ioport_resource, &standard_io_resources[i]); - return 0; -} - -subsys_initcall(request_standard_resources); - -static void __init register_memory(void) -{ - unsigned long gapstart, gapsize, round; - unsigned long long last; - int i; - - /* - * Search for the bigest gap in the low 32 bits of the e820 - * memory space. - */ - last = 0x100000000ull; - gapstart = 0x10000000; - gapsize = 0x400000; - i = e820.nr_map; - while (--i >= 0) { - unsigned long long start = e820.map[i].addr; - unsigned long long end = start + e820.map[i].size; - - /* - * Since "last" is at most 4GB, we know we'll - * fit in 32 bits if this condition is true - */ - if (last > end) { - unsigned long gap = last - end; - - if (gap > gapsize) { - gapsize = gap; - gapstart = end; - } - } - if (start < last) - last = start; - } - - /* - * See how much we want to round up: start off with - * rounding to the next 1MB area. - */ - round = 0x100000; - while ((gapsize >> 4) > round) - round += round; - /* Fun with two's complement */ - pci_mem_start = (gapstart + round) & -round; - - printk("Allocating PCI resources starting at %08lx (gap: %08lx:%08lx)\n", - pci_mem_start, gapstart, gapsize); -} - #ifdef CONFIG_MCA static void set_mca_bus(int x) { @@ -1329,6 +494,12 @@ static void set_mca_bus(int x) static void set_mca_bus(int x) { } #endif +/* Overridden in paravirt.c if CONFIG_PARAVIRT */ +char * __attribute__((weak)) memory_setup(void) +{ + return machine_specific_memory_setup(); +} + /* * Determine if we were loaded by an EFI loader. If so, then we have also been * passed the efi memmap, systab, etc., so we should use these data structures @@ -1381,7 +552,7 @@ void __init setup_arch(char **cmdline_p) efi_init(); else { printk(KERN_INFO "BIOS-provided physical RAM map:\n"); - print_memory_map(machine_specific_memory_setup()); + print_memory_map(memory_setup()); } copy_edd(); diff --git a/trunk/arch/i386/kernel/signal.c b/trunk/arch/i386/kernel/signal.c index 43002cfb40c4..65d7620eaa09 100644 --- a/trunk/arch/i386/kernel/signal.c +++ b/trunk/arch/i386/kernel/signal.c @@ -128,7 +128,7 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, int *peax X86_EFLAGS_TF | X86_EFLAGS_SF | X86_EFLAGS_ZF | \ X86_EFLAGS_AF | X86_EFLAGS_PF | X86_EFLAGS_CF) - GET_SEG(gs); + COPY_SEG(gs); GET_SEG(fs); COPY_SEG(es); COPY_SEG(ds); @@ -244,9 +244,7 @@ setup_sigcontext(struct sigcontext __user *sc, struct _fpstate __user *fpstate, { int tmp, err = 0; - tmp = 0; - savesegment(gs, tmp); - err |= __put_user(tmp, (unsigned int __user *)&sc->gs); + err |= __put_user(regs->xgs, (unsigned int __user *)&sc->gs); savesegment(fs, tmp); err |= __put_user(tmp, (unsigned int __user *)&sc->fs); diff --git a/trunk/arch/i386/kernel/smp.c b/trunk/arch/i386/kernel/smp.c index 31e5c6573aae..5285aff8367f 100644 --- a/trunk/arch/i386/kernel/smp.c +++ b/trunk/arch/i386/kernel/smp.c @@ -321,7 +321,6 @@ static inline void leave_mm (unsigned long cpu) fastcall void smp_invalidate_interrupt(struct pt_regs *regs) { - struct pt_regs *old_regs = set_irq_regs(regs); unsigned long cpu; cpu = get_cpu(); @@ -352,7 +351,6 @@ fastcall void smp_invalidate_interrupt(struct pt_regs *regs) smp_mb__after_clear_bit(); out: put_cpu_no_resched(); - set_irq_regs(old_regs); } static void flush_tlb_others(cpumask_t cpumask, struct mm_struct *mm, @@ -607,14 +605,11 @@ void smp_send_stop(void) */ fastcall void smp_reschedule_interrupt(struct pt_regs *regs) { - struct pt_regs *old_regs = set_irq_regs(regs); ack_APIC_irq(); - set_irq_regs(old_regs); } fastcall void smp_call_function_interrupt(struct pt_regs *regs) { - struct pt_regs *old_regs = set_irq_regs(regs); void (*func) (void *info) = call_data->func; void *info = call_data->info; int wait = call_data->wait; @@ -637,7 +632,6 @@ fastcall void smp_call_function_interrupt(struct pt_regs *regs) mb(); atomic_inc(&call_data->finished); } - set_irq_regs(old_regs); } /* @@ -699,6 +693,10 @@ int smp_call_function_single(int cpu, void (*func) (void *info), void *info, put_cpu(); return -EBUSY; } + + /* Can deadlock when called with interrupts disabled */ + WARN_ON(irqs_disabled()); + spin_lock_bh(&call_lock); __smp_call_function_single(cpu, func, info, nonatomic, wait); spin_unlock_bh(&call_lock); diff --git a/trunk/arch/i386/kernel/smpboot.c b/trunk/arch/i386/kernel/smpboot.c index 4bb8b77cd65b..1e00b03163b9 100644 --- a/trunk/arch/i386/kernel/smpboot.c +++ b/trunk/arch/i386/kernel/smpboot.c @@ -33,6 +33,11 @@ * Dave Jones : Report invalid combinations of Athlon CPUs. * Rusty Russell : Hacked into shape for new "hotplug" boot process. */ + +/* SMP boot always wants to use real time delay to allow sufficient time for + * the APs to come online */ +#define USE_REAL_TIME_DELAY + #include #include #include @@ -52,6 +57,8 @@ #include #include #include +#include +#include #include #include @@ -536,11 +543,11 @@ set_cpu_sibling_map(int cpu) static void __devinit start_secondary(void *unused) { /* - * Dont put anything before smp_callin(), SMP + * Don't put *anything* before secondary_cpu_init(), SMP * booting is too fragile that we want to limit the * things done here to the most necessary things. */ - cpu_init(); + secondary_cpu_init(); preempt_disable(); smp_callin(); while (!cpu_isset(smp_processor_id(), smp_commenced_mask)) @@ -599,13 +606,16 @@ void __devinit initialize_secondary(void) "movl %0,%%esp\n\t" "jmp *%1" : - :"r" (current->thread.esp),"r" (current->thread.eip)); + :"m" (current->thread.esp),"m" (current->thread.eip)); } +/* Static state in head.S used to set up a CPU */ extern struct { void * esp; unsigned short ss; } stack_start; +extern struct i386_pda *start_pda; +extern struct Xgt_desc_struct cpu_gdt_descr; #ifdef CONFIG_NUMA @@ -936,9 +946,6 @@ static int __devinit do_boot_cpu(int apicid, int cpu) unsigned long start_eip; unsigned short nmi_high = 0, nmi_low = 0; - ++cpucount; - alternatives_smp_switch(1); - /* * We can't use kernel_thread since we must avoid to * reschedule the child. @@ -946,15 +953,30 @@ static int __devinit do_boot_cpu(int apicid, int cpu) idle = alloc_idle_task(cpu); if (IS_ERR(idle)) panic("failed fork for CPU %d", cpu); + + /* Pre-allocate and initialize the CPU's GDT and PDA so it + doesn't have to do any memory allocation during the + delicate CPU-bringup phase. */ + if (!init_gdt(cpu, idle)) { + printk(KERN_INFO "Couldn't allocate GDT/PDA for CPU %d\n", cpu); + return -1; /* ? */ + } + idle->thread.eip = (unsigned long) start_secondary; /* start_eip had better be page-aligned! */ start_eip = setup_trampoline(); + ++cpucount; + alternatives_smp_switch(1); + /* So we see what's up */ printk("Booting processor %d/%d eip %lx\n", cpu, apicid, start_eip); /* Stack for startup_32 can be just as for start_secondary onwards */ stack_start.esp = (void *) idle->thread.esp; + start_pda = cpu_pda(cpu); + cpu_gdt_descr = per_cpu(cpu_gdt_descr, cpu); + irq_ctx_init(cpu); x86_cpu_to_apicid[cpu] = apicid; @@ -1049,13 +1071,15 @@ void cpu_exit_clear(void) struct warm_boot_cpu_info { struct completion *complete; + struct work_struct task; int apicid; int cpu; }; -static void __cpuinit do_warm_boot_cpu(void *p) +static void __cpuinit do_warm_boot_cpu(struct work_struct *work) { - struct warm_boot_cpu_info *info = p; + struct warm_boot_cpu_info *info = + container_of(work, struct warm_boot_cpu_info, task); do_boot_cpu(info->apicid, info->cpu); complete(info->complete); } @@ -1064,7 +1088,6 @@ static int __cpuinit __smp_prepare_cpu(int cpu) { DECLARE_COMPLETION_ONSTACK(done); struct warm_boot_cpu_info info; - struct work_struct task; int apicid, ret; struct Xgt_desc_struct *cpu_gdt_descr = &per_cpu(cpu_gdt_descr, cpu); @@ -1089,15 +1112,15 @@ static int __cpuinit __smp_prepare_cpu(int cpu) info.complete = &done; info.apicid = apicid; info.cpu = cpu; - INIT_WORK(&task, do_warm_boot_cpu, &info); + INIT_WORK(&info.task, do_warm_boot_cpu); tsc_sync_disabled = 1; /* init low mem mapping */ clone_pgd_range(swapper_pg_dir, swapper_pg_dir + USER_PGD_PTRS, - KERNEL_PGD_PTRS); + min_t(unsigned long, KERNEL_PGD_PTRS, USER_PGD_PTRS)); flush_tlb_all(); - schedule_work(&task); + schedule_work(&info.task); wait_for_completion(&done); tsc_sync_disabled = 0; @@ -1108,34 +1131,15 @@ static int __cpuinit __smp_prepare_cpu(int cpu) } #endif -static void smp_tune_scheduling (void) +static void smp_tune_scheduling(void) { unsigned long cachesize; /* kB */ - unsigned long bandwidth = 350; /* MB/s */ - /* - * Rough estimation for SMP scheduling, this is the number of - * cycles it takes for a fully memory-limited process to flush - * the SMP-local cache. - * - * (For a P5 this pretty much means we will choose another idle - * CPU almost always at wakeup time (this is due to the small - * L1 cache), on PIIs it's around 50-100 usecs, depending on - * the cache size) - */ - if (!cpu_khz) { - /* - * this basically disables processor-affinity - * scheduling on SMP without a TSC. - */ - return; - } else { + if (cpu_khz) { cachesize = boot_cpu_data.x86_cache_size; - if (cachesize == -1) { - cachesize = 16; /* Pentiums, 2x8kB cache */ - bandwidth = 100; - } - max_cache_size = cachesize * 1024; + + if (cachesize > 0) + max_cache_size = cachesize * 1024; } } @@ -1461,6 +1465,12 @@ int __devinit __cpu_up(unsigned int cpu) cpu_set(cpu, smp_commenced_mask); while (!cpu_isset(cpu, cpu_online_map)) cpu_relax(); + +#ifdef CONFIG_X86_GENERICARCH + if (num_online_cpus() > 8 && genapic == &apic_default) + panic("Default flat APIC routing can't be used with > 8 cpus\n"); +#endif + return 0; } diff --git a/trunk/arch/i386/kernel/sysenter.c b/trunk/arch/i386/kernel/sysenter.c index 713ba39d32c6..7de9117b5a3a 100644 --- a/trunk/arch/i386/kernel/sysenter.c +++ b/trunk/arch/i386/kernel/sysenter.c @@ -27,7 +27,11 @@ * Should the kernel map a VDSO page into processes and pass its * address down to glibc upon exec()? */ +#ifdef CONFIG_PARAVIRT +unsigned int __read_mostly vdso_enabled = 0; +#else unsigned int __read_mostly vdso_enabled = 1; +#endif EXPORT_SYMBOL_GPL(vdso_enabled); @@ -132,7 +136,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int exstack) goto up_fail; } - vma = kmem_cache_zalloc(vm_area_cachep, SLAB_KERNEL); + vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL); if (!vma) { ret = -ENOMEM; goto up_fail; diff --git a/trunk/arch/i386/kernel/time.c b/trunk/arch/i386/kernel/time.c index 78af572fd17c..c505b16c0990 100644 --- a/trunk/arch/i386/kernel/time.c +++ b/trunk/arch/i386/kernel/time.c @@ -56,6 +56,7 @@ #include #include #include +#include #include "mach_time.h" @@ -116,10 +117,7 @@ static int set_rtc_mmss(unsigned long nowtime) /* gets recalled with irq locally disabled */ /* XXX - does irqsave resolve this? -johnstul */ spin_lock_irqsave(&rtc_lock, flags); - if (efi_enabled) - retval = efi_set_rtc_mmss(nowtime); - else - retval = mach_set_rtc_mmss(nowtime); + retval = set_wallclock(nowtime); spin_unlock_irqrestore(&rtc_lock, flags); return retval; @@ -223,10 +221,7 @@ unsigned long get_cmos_time(void) spin_lock_irqsave(&rtc_lock, flags); - if (efi_enabled) - retval = efi_get_time(); - else - retval = mach_get_cmos_time(); + retval = get_wallclock(); spin_unlock_irqrestore(&rtc_lock, flags); @@ -370,7 +365,7 @@ static void __init hpet_time_init(void) printk("Using HPET for base-timer\n"); } - time_init_hook(); + do_time_init(); } #endif @@ -392,5 +387,5 @@ void __init time_init(void) do_settimeofday(&ts); - time_init_hook(); + do_time_init(); } diff --git a/trunk/arch/i386/kernel/time_hpet.c b/trunk/arch/i386/kernel/time_hpet.c index 1a2a979cf6a3..1e4702dfcd01 100644 --- a/trunk/arch/i386/kernel/time_hpet.c +++ b/trunk/arch/i386/kernel/time_hpet.c @@ -132,14 +132,20 @@ int __init hpet_enable(void) * the single HPET timer for system time. */ #ifdef CONFIG_HPET_EMULATE_RTC - if (!(id & HPET_ID_NUMBER)) + if (!(id & HPET_ID_NUMBER)) { + iounmap(hpet_virt_address); + hpet_virt_address = NULL; return -1; + } #endif hpet_period = hpet_readl(HPET_PERIOD); - if ((hpet_period < HPET_MIN_PERIOD) || (hpet_period > HPET_MAX_PERIOD)) + if ((hpet_period < HPET_MIN_PERIOD) || (hpet_period > HPET_MAX_PERIOD)) { + iounmap(hpet_virt_address); + hpet_virt_address = NULL; return -1; + } /* * 64 bit math @@ -156,8 +162,11 @@ int __init hpet_enable(void) hpet_use_timer = id & HPET_ID_LEGSUP; - if (hpet_timer_stop_set_go(hpet_tick)) + if (hpet_timer_stop_set_go(hpet_tick)) { + iounmap(hpet_virt_address); + hpet_virt_address = NULL; return -1; + } use_hpet = 1; diff --git a/trunk/arch/i386/kernel/topology.c b/trunk/arch/i386/kernel/topology.c index 07d6da36a825..79cf608e14ca 100644 --- a/trunk/arch/i386/kernel/topology.c +++ b/trunk/arch/i386/kernel/topology.c @@ -40,14 +40,18 @@ int arch_register_cpu(int num) * restrictions and assumptions in kernel. This basically * doesnt add a control file, one cannot attempt to offline * BSP. + * + * Also certain PCI quirks require not to enable hotplug control + * for all CPU's. */ - if (!num) - cpu_devices[num].cpu.no_control = 1; + if (num && enable_cpu_hotplug) + cpu_devices[num].cpu.hotpluggable = 1; return register_cpu(&cpu_devices[num].cpu, num); } #ifdef CONFIG_HOTPLUG_CPU +int enable_cpu_hotplug = 1; void arch_unregister_cpu(int num) { return unregister_cpu(&cpu_devices[num].cpu); diff --git a/trunk/arch/i386/kernel/traps.c b/trunk/arch/i386/kernel/traps.c index fe9c5e8e7e6f..2b30dbf8d117 100644 --- a/trunk/arch/i386/kernel/traps.c +++ b/trunk/arch/i386/kernel/traps.c @@ -29,6 +29,8 @@ #include #include #include +#include +#include #ifdef CONFIG_EISA #include @@ -61,9 +63,6 @@ int panic_on_unrecovered_nmi; asmlinkage int system_call(void); -struct desc_struct default_ldt[] = { { 0, 0 }, { 0, 0 }, { 0, 0 }, - { 0, 0 }, { 0, 0 } }; - /* Do we ignore FPU interrupts ? */ char ignore_fpu_irq = 0; @@ -94,7 +93,7 @@ asmlinkage void alignment_check(void); asmlinkage void spurious_interrupt_bug(void); asmlinkage void machine_check(void); -static int kstack_depth_to_print = 24; +int kstack_depth_to_print = 24; #ifdef CONFIG_STACK_UNWIND static int call_trace = 1; #else @@ -163,16 +162,25 @@ dump_trace_unwind(struct unwind_frame_info *info, void *data) { struct ops_and_data *oad = (struct ops_and_data *)data; int n = 0; + unsigned long sp = UNW_SP(info); + if (arch_unw_user_mode(info)) + return -1; while (unwind(info) == 0 && UNW_PC(info)) { n++; oad->ops->address(oad->data, UNW_PC(info)); if (arch_unw_user_mode(info)) break; + if ((sp & ~(PAGE_SIZE - 1)) == (UNW_SP(info) & ~(PAGE_SIZE - 1)) + && sp > UNW_SP(info)) + break; + sp = UNW_SP(info); } return n; } +#define MSG(msg) ops->warning(data, msg) + void dump_trace(struct task_struct *task, struct pt_regs *regs, unsigned long *stack, struct stacktrace_ops *ops, void *data) @@ -191,29 +199,31 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs, if (unwind_init_frame_info(&info, task, regs) == 0) unw_ret = dump_trace_unwind(&info, &oad); } else if (task == current) - unw_ret = unwind_init_running(&info, dump_trace_unwind, &oad); + unw_ret = unwind_init_running(&info, dump_trace_unwind, + &oad); else { if (unwind_init_blocked(&info, task) == 0) unw_ret = dump_trace_unwind(&info, &oad); } if (unw_ret > 0) { if (call_trace == 1 && !arch_unw_user_mode(&info)) { - ops->warning_symbol(data, "DWARF2 unwinder stuck at %s\n", + ops->warning_symbol(data, + "DWARF2 unwinder stuck at %s", UNW_PC(&info)); if (UNW_SP(&info) >= PAGE_OFFSET) { - ops->warning(data, "Leftover inexact backtrace:\n"); + MSG("Leftover inexact backtrace:"); stack = (void *)UNW_SP(&info); if (!stack) return; ebp = UNW_FP(&info); } else - ops->warning(data, "Full inexact backtrace again:\n"); + MSG("Full inexact backtrace again:"); } else if (call_trace >= 1) return; else - ops->warning(data, "Full inexact backtrace again:\n"); + MSG("Full inexact backtrace again:"); } else - ops->warning(data, "Inexact backtrace:\n"); + MSG("Inexact backtrace:"); } if (!stack) { unsigned long dummy; @@ -247,6 +257,7 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs, stack = (unsigned long*)context->previous_esp; if (!stack) break; + touch_nmi_watchdog(); } } EXPORT_SYMBOL(dump_trace); @@ -379,7 +390,7 @@ void show_registers(struct pt_regs *regs) * time of the fault.. */ if (in_kernel) { - u8 __user *eip; + u8 *eip; int code_bytes = 64; unsigned char c; @@ -388,18 +399,20 @@ void show_registers(struct pt_regs *regs) printk(KERN_EMERG "Code: "); - eip = (u8 __user *)regs->eip - 43; - if (eip < (u8 __user *)PAGE_OFFSET || __get_user(c, eip)) { + eip = (u8 *)regs->eip - 43; + if (eip < (u8 *)PAGE_OFFSET || + probe_kernel_address(eip, c)) { /* try starting at EIP */ - eip = (u8 __user *)regs->eip; + eip = (u8 *)regs->eip; code_bytes = 32; } for (i = 0; i < code_bytes; i++, eip++) { - if (eip < (u8 __user *)PAGE_OFFSET || __get_user(c, eip)) { + if (eip < (u8 *)PAGE_OFFSET || + probe_kernel_address(eip, c)) { printk(" Bad EIP value."); break; } - if (eip == (u8 __user *)regs->eip) + if (eip == (u8 *)regs->eip) printk("<%02x> ", c); else printk("%02x ", c); @@ -408,43 +421,22 @@ void show_registers(struct pt_regs *regs) printk("\n"); } -static void handle_BUG(struct pt_regs *regs) +int is_valid_bugaddr(unsigned long eip) { - unsigned long eip = regs->eip; unsigned short ud2; if (eip < PAGE_OFFSET) - return; - if (probe_kernel_address((unsigned short __user *)eip, ud2)) - return; - if (ud2 != 0x0b0f) - return; - - printk(KERN_EMERG "------------[ cut here ]------------\n"); - -#ifdef CONFIG_DEBUG_BUGVERBOSE - do { - unsigned short line; - char *file; - char c; - - if (probe_kernel_address((unsigned short __user *)(eip + 2), - line)) - break; - if (__get_user(file, (char * __user *)(eip + 4)) || - (unsigned long)file < PAGE_OFFSET || __get_user(c, file)) - file = ""; + return 0; + if (probe_kernel_address((unsigned short *)eip, ud2)) + return 0; - printk(KERN_EMERG "kernel BUG at %s:%d!\n", file, line); - return; - } while (0); -#endif - printk(KERN_EMERG "Kernel BUG at [verbose debug info unavailable]\n"); + return ud2 == 0x0b0f; } -/* This is gone through when something in the kernel - * has done something bad and is about to be terminated. -*/ +/* + * This is gone through when something in the kernel has done something bad and + * is about to be terminated. + */ void die(const char * str, struct pt_regs * regs, long err) { static struct { @@ -452,7 +444,7 @@ void die(const char * str, struct pt_regs * regs, long err) u32 lock_owner; int lock_owner_depth; } die = { - .lock = SPIN_LOCK_UNLOCKED, + .lock = __SPIN_LOCK_UNLOCKED(die.lock), .lock_owner = -1, .lock_owner_depth = 0 }; @@ -476,7 +468,8 @@ void die(const char * str, struct pt_regs * regs, long err) unsigned long esp; unsigned short ss; - handle_BUG(regs); + report_bug(regs->eip); + printk(KERN_EMERG "%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter); #ifdef CONFIG_PREEMPT printk(KERN_EMERG "PREEMPT "); @@ -707,8 +700,7 @@ mem_parity_error(unsigned char reason, struct pt_regs * regs) { printk(KERN_EMERG "Uhhuh. NMI received for unknown reason %02x on " "CPU %d.\n", reason, smp_processor_id()); - printk(KERN_EMERG "You probably have a hardware problem with your RAM " - "chips\n"); + printk(KERN_EMERG "You have some hardware problem, likely on the PCI bus.\n"); if (panic_on_unrecovered_nmi) panic("NMI: Not continuing"); @@ -773,7 +765,6 @@ void __kprobes die_nmi(struct pt_regs *regs, const char *msg) printk(" on CPU%d, eip %08lx, registers:\n", smp_processor_id(), regs->eip); show_registers(regs); - printk(KERN_EMERG "console shuts up ...\n"); console_silent(); spin_unlock(&nmi_print_lock); bust_spinlocks(0); @@ -1088,49 +1079,24 @@ fastcall void do_spurious_interrupt_bug(struct pt_regs * regs, #endif } -fastcall void setup_x86_bogus_stack(unsigned char * stk) -{ - unsigned long *switch16_ptr, *switch32_ptr; - struct pt_regs *regs; - unsigned long stack_top, stack_bot; - unsigned short iret_frame16_off; - int cpu = smp_processor_id(); - /* reserve the space on 32bit stack for the magic switch16 pointer */ - memmove(stk, stk + 8, sizeof(struct pt_regs)); - switch16_ptr = (unsigned long *)(stk + sizeof(struct pt_regs)); - regs = (struct pt_regs *)stk; - /* now the switch32 on 16bit stack */ - stack_bot = (unsigned long)&per_cpu(cpu_16bit_stack, cpu); - stack_top = stack_bot + CPU_16BIT_STACK_SIZE; - switch32_ptr = (unsigned long *)(stack_top - 8); - iret_frame16_off = CPU_16BIT_STACK_SIZE - 8 - 20; - /* copy iret frame on 16bit stack */ - memcpy((void *)(stack_bot + iret_frame16_off), ®s->eip, 20); - /* fill in the switch pointers */ - switch16_ptr[0] = (regs->esp & 0xffff0000) | iret_frame16_off; - switch16_ptr[1] = __ESPFIX_SS; - switch32_ptr[0] = (unsigned long)stk + sizeof(struct pt_regs) + - 8 - CPU_16BIT_STACK_SIZE; - switch32_ptr[1] = __KERNEL_DS; -} - -fastcall unsigned char * fixup_x86_bogus_stack(unsigned short sp) +fastcall unsigned long patch_espfix_desc(unsigned long uesp, + unsigned long kesp) { - unsigned long *switch32_ptr; - unsigned char *stack16, *stack32; - unsigned long stack_top, stack_bot; - int len; int cpu = smp_processor_id(); - stack_bot = (unsigned long)&per_cpu(cpu_16bit_stack, cpu); - stack_top = stack_bot + CPU_16BIT_STACK_SIZE; - switch32_ptr = (unsigned long *)(stack_top - 8); - /* copy the data from 16bit stack to 32bit stack */ - len = CPU_16BIT_STACK_SIZE - 8 - sp; - stack16 = (unsigned char *)(stack_bot + sp); - stack32 = (unsigned char *) - (switch32_ptr[0] + CPU_16BIT_STACK_SIZE - 8 - len); - memcpy(stack32, stack16, len); - return stack32; + struct Xgt_desc_struct *cpu_gdt_descr = &per_cpu(cpu_gdt_descr, cpu); + struct desc_struct *gdt = (struct desc_struct *)cpu_gdt_descr->address; + unsigned long base = (kesp - uesp) & -THREAD_SIZE; + unsigned long new_kesp = kesp - base; + unsigned long lim_pages = (new_kesp | (THREAD_SIZE - 1)) >> PAGE_SHIFT; + __u64 desc = *(__u64 *)&gdt[GDT_ENTRY_ESPFIX_SS]; + /* Set up base for espfix segment */ + desc &= 0x00f0ff0000000000ULL; + desc |= ((((__u64)base) << 16) & 0x000000ffffff0000ULL) | + ((((__u64)base) << 32) & 0xff00000000000000ULL) | + ((((__u64)lim_pages) << 32) & 0x000f000000000000ULL) | + (lim_pages & 0xffff); + *(__u64 *)&gdt[GDT_ENTRY_ESPFIX_SS] = desc; + return new_kesp; } /* @@ -1143,7 +1109,7 @@ fastcall unsigned char * fixup_x86_bogus_stack(unsigned short sp) * Must be called with kernel preemption disabled (in this case, * local interrupts are disabled at the call-site in entry.S). */ -asmlinkage void math_state_restore(struct pt_regs regs) +asmlinkage void math_state_restore(void) { struct thread_info *thread = current_thread_info(); struct task_struct *tsk = thread->task; @@ -1153,6 +1119,7 @@ asmlinkage void math_state_restore(struct pt_regs regs) init_fpu(tsk); restore_fpu(tsk); thread->status |= TS_USEDFPU; /* So we fnsave on switch_to() */ + tsk->fpu_counter++; } #ifndef CONFIG_MATH_EMULATION diff --git a/trunk/arch/i386/kernel/tsc.c b/trunk/arch/i386/kernel/tsc.c index fbc95828cd74..1bbe45dca7a0 100644 --- a/trunk/arch/i386/kernel/tsc.c +++ b/trunk/arch/i386/kernel/tsc.c @@ -13,7 +13,6 @@ #include #include -#include #include #include "mach_timer.h" @@ -217,7 +216,7 @@ static unsigned int cpufreq_delayed_issched = 0; static unsigned int cpufreq_init = 0; static struct work_struct cpufreq_delayed_get_work; -static void handle_cpufreq_delayed_get(void *v) +static void handle_cpufreq_delayed_get(struct work_struct *work) { unsigned int cpu; @@ -306,7 +305,7 @@ static int __init cpufreq_tsc(void) { int ret; - INIT_WORK(&cpufreq_delayed_get_work, handle_cpufreq_delayed_get, NULL); + INIT_WORK(&cpufreq_delayed_get_work, handle_cpufreq_delayed_get); ret = cpufreq_register_notifier(&time_cpufreq_notifier_block, CPUFREQ_TRANSITION_NOTIFIER); if (!ret) diff --git a/trunk/arch/i386/kernel/vm86.c b/trunk/arch/i386/kernel/vm86.c index cbcd61d6120b..be2f96e67f78 100644 --- a/trunk/arch/i386/kernel/vm86.c +++ b/trunk/arch/i386/kernel/vm86.c @@ -43,6 +43,7 @@ #include #include #include +#include #include #include @@ -72,10 +73,10 @@ /* * 8- and 16-bit register defines.. */ -#define AL(regs) (((unsigned char *)&((regs)->eax))[0]) -#define AH(regs) (((unsigned char *)&((regs)->eax))[1]) -#define IP(regs) (*(unsigned short *)&((regs)->eip)) -#define SP(regs) (*(unsigned short *)&((regs)->esp)) +#define AL(regs) (((unsigned char *)&((regs)->pt.eax))[0]) +#define AH(regs) (((unsigned char *)&((regs)->pt.eax))[1]) +#define IP(regs) (*(unsigned short *)&((regs)->pt.eip)) +#define SP(regs) (*(unsigned short *)&((regs)->pt.esp)) /* * virtual flags (16 and 32-bit versions) @@ -89,10 +90,37 @@ #define SAFE_MASK (0xDD5) #define RETURN_MASK (0xDFF) -#define VM86_REGS_PART2 orig_eax -#define VM86_REGS_SIZE1 \ - ( (unsigned)( & (((struct kernel_vm86_regs *)0)->VM86_REGS_PART2) ) ) -#define VM86_REGS_SIZE2 (sizeof(struct kernel_vm86_regs) - VM86_REGS_SIZE1) +/* convert kernel_vm86_regs to vm86_regs */ +static int copy_vm86_regs_to_user(struct vm86_regs __user *user, + const struct kernel_vm86_regs *regs) +{ + int ret = 0; + + /* kernel_vm86_regs is missing xfs, so copy everything up to + (but not including) xgs, and then rest after xgs. */ + ret += copy_to_user(user, regs, offsetof(struct kernel_vm86_regs, pt.xgs)); + ret += copy_to_user(&user->__null_gs, ®s->pt.xgs, + sizeof(struct kernel_vm86_regs) - + offsetof(struct kernel_vm86_regs, pt.xgs)); + + return ret; +} + +/* convert vm86_regs to kernel_vm86_regs */ +static int copy_vm86_regs_from_user(struct kernel_vm86_regs *regs, + const struct vm86_regs __user *user, + unsigned extra) +{ + int ret = 0; + + ret += copy_from_user(regs, user, offsetof(struct kernel_vm86_regs, pt.xgs)); + ret += copy_from_user(®s->pt.xgs, &user->__null_gs, + sizeof(struct kernel_vm86_regs) - + offsetof(struct kernel_vm86_regs, pt.xgs) + + extra); + + return ret; +} struct pt_regs * FASTCALL(save_v86_state(struct kernel_vm86_regs * regs)); struct pt_regs * fastcall save_v86_state(struct kernel_vm86_regs * regs) @@ -112,10 +140,8 @@ struct pt_regs * fastcall save_v86_state(struct kernel_vm86_regs * regs) printk("no vm86_info: BAD\n"); do_exit(SIGSEGV); } - set_flags(regs->eflags, VEFLAGS, VIF_MASK | current->thread.v86mask); - tmp = copy_to_user(¤t->thread.vm86_info->regs,regs, VM86_REGS_SIZE1); - tmp += copy_to_user(¤t->thread.vm86_info->regs.VM86_REGS_PART2, - ®s->VM86_REGS_PART2, VM86_REGS_SIZE2); + set_flags(regs->pt.eflags, VEFLAGS, VIF_MASK | current->thread.v86mask); + tmp = copy_vm86_regs_to_user(¤t->thread.vm86_info->regs,regs); tmp += put_user(current->thread.screen_bitmap,¤t->thread.vm86_info->screen_bitmap); if (tmp) { printk("vm86: could not access userspace vm86_info\n"); @@ -129,9 +155,11 @@ struct pt_regs * fastcall save_v86_state(struct kernel_vm86_regs * regs) current->thread.saved_esp0 = 0; put_cpu(); - loadsegment(fs, current->thread.saved_fs); - loadsegment(gs, current->thread.saved_gs); ret = KVM86->regs32; + + loadsegment(fs, current->thread.saved_fs); + ret->xgs = current->thread.saved_gs; + return ret; } @@ -183,9 +211,9 @@ asmlinkage int sys_vm86old(struct pt_regs regs) tsk = current; if (tsk->thread.saved_esp0) goto out; - tmp = copy_from_user(&info, v86, VM86_REGS_SIZE1); - tmp += copy_from_user(&info.regs.VM86_REGS_PART2, &v86->regs.VM86_REGS_PART2, - (long)&info.vm86plus - (long)&info.regs.VM86_REGS_PART2); + tmp = copy_vm86_regs_from_user(&info.regs, &v86->regs, + offsetof(struct kernel_vm86_struct, vm86plus) - + sizeof(info.regs)); ret = -EFAULT; if (tmp) goto out; @@ -233,9 +261,9 @@ asmlinkage int sys_vm86(struct pt_regs regs) if (tsk->thread.saved_esp0) goto out; v86 = (struct vm86plus_struct __user *)regs.ecx; - tmp = copy_from_user(&info, v86, VM86_REGS_SIZE1); - tmp += copy_from_user(&info.regs.VM86_REGS_PART2, &v86->regs.VM86_REGS_PART2, - (long)&info.regs32 - (long)&info.regs.VM86_REGS_PART2); + tmp = copy_vm86_regs_from_user(&info.regs, &v86->regs, + offsetof(struct kernel_vm86_struct, regs32) - + sizeof(info.regs)); ret = -EFAULT; if (tmp) goto out; @@ -252,15 +280,15 @@ asmlinkage int sys_vm86(struct pt_regs regs) static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk) { struct tss_struct *tss; - long eax; /* * make sure the vm86() system call doesn't try to do anything silly */ - info->regs.__null_ds = 0; - info->regs.__null_es = 0; + info->regs.pt.xds = 0; + info->regs.pt.xes = 0; + info->regs.pt.xgs = 0; -/* we are clearing fs,gs later just before "jmp resume_userspace", - * because starting with Linux 2.1.x they aren't no longer saved/restored +/* we are clearing fs later just before "jmp resume_userspace", + * because it is not saved/restored. */ /* @@ -268,10 +296,10 @@ static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk * has set it up safely, so this makes sure interrupt etc flags are * inherited from protected mode. */ - VEFLAGS = info->regs.eflags; - info->regs.eflags &= SAFE_MASK; - info->regs.eflags |= info->regs32->eflags & ~SAFE_MASK; - info->regs.eflags |= VM_MASK; + VEFLAGS = info->regs.pt.eflags; + info->regs.pt.eflags &= SAFE_MASK; + info->regs.pt.eflags |= info->regs32->eflags & ~SAFE_MASK; + info->regs.pt.eflags |= VM_MASK; switch (info->cpu_type) { case CPU_286: @@ -294,7 +322,7 @@ static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk info->regs32->eax = 0; tsk->thread.saved_esp0 = tsk->thread.esp0; savesegment(fs, tsk->thread.saved_fs); - savesegment(gs, tsk->thread.saved_gs); + tsk->thread.saved_gs = info->regs32->xgs; tss = &per_cpu(init_tss, get_cpu()); tsk->thread.esp0 = (unsigned long) &info->VM86_TSS_ESP0; @@ -306,19 +334,18 @@ static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk tsk->thread.screen_bitmap = info->screen_bitmap; if (info->flags & VM86_SCREEN_BITMAP) mark_screen_rdonly(tsk->mm); - __asm__ __volatile__("xorl %eax,%eax; movl %eax,%fs; movl %eax,%gs\n\t"); - __asm__ __volatile__("movl %%eax, %0\n" :"=r"(eax)); /*call audit_syscall_exit since we do not exit via the normal paths */ if (unlikely(current->audit_context)) - audit_syscall_exit(AUDITSC_RESULT(eax), eax); + audit_syscall_exit(AUDITSC_RESULT(0), 0); __asm__ __volatile__( "movl %0,%%esp\n\t" "movl %1,%%ebp\n\t" + "mov %2, %%fs\n\t" "jmp resume_userspace" : /* no outputs */ - :"r" (&info->regs), "r" (task_thread_info(tsk))); + :"r" (&info->regs), "r" (task_thread_info(tsk)), "r" (0)); /* we never return here */ } @@ -348,12 +375,12 @@ static inline void clear_IF(struct kernel_vm86_regs * regs) static inline void clear_TF(struct kernel_vm86_regs * regs) { - regs->eflags &= ~TF_MASK; + regs->pt.eflags &= ~TF_MASK; } static inline void clear_AC(struct kernel_vm86_regs * regs) { - regs->eflags &= ~AC_MASK; + regs->pt.eflags &= ~AC_MASK; } /* It is correct to call set_IF(regs) from the set_vflags_* @@ -370,7 +397,7 @@ static inline void clear_AC(struct kernel_vm86_regs * regs) static inline void set_vflags_long(unsigned long eflags, struct kernel_vm86_regs * regs) { set_flags(VEFLAGS, eflags, current->thread.v86mask); - set_flags(regs->eflags, eflags, SAFE_MASK); + set_flags(regs->pt.eflags, eflags, SAFE_MASK); if (eflags & IF_MASK) set_IF(regs); else @@ -380,7 +407,7 @@ static inline void set_vflags_long(unsigned long eflags, struct kernel_vm86_regs static inline void set_vflags_short(unsigned short flags, struct kernel_vm86_regs * regs) { set_flags(VFLAGS, flags, current->thread.v86mask); - set_flags(regs->eflags, flags, SAFE_MASK); + set_flags(regs->pt.eflags, flags, SAFE_MASK); if (flags & IF_MASK) set_IF(regs); else @@ -389,7 +416,7 @@ static inline void set_vflags_short(unsigned short flags, struct kernel_vm86_reg static inline unsigned long get_vflags(struct kernel_vm86_regs * regs) { - unsigned long flags = regs->eflags & RETURN_MASK; + unsigned long flags = regs->pt.eflags & RETURN_MASK; if (VEFLAGS & VIF_MASK) flags |= IF_MASK; @@ -493,7 +520,7 @@ static void do_int(struct kernel_vm86_regs *regs, int i, unsigned long __user *intr_ptr; unsigned long segoffs; - if (regs->cs == BIOSSEG) + if (regs->pt.xcs == BIOSSEG) goto cannot_handle; if (is_revectored(i, &KVM86->int_revectored)) goto cannot_handle; @@ -505,9 +532,9 @@ static void do_int(struct kernel_vm86_regs *regs, int i, if ((segoffs >> 16) == BIOSSEG) goto cannot_handle; pushw(ssp, sp, get_vflags(regs), cannot_handle); - pushw(ssp, sp, regs->cs, cannot_handle); + pushw(ssp, sp, regs->pt.xcs, cannot_handle); pushw(ssp, sp, IP(regs), cannot_handle); - regs->cs = segoffs >> 16; + regs->pt.xcs = segoffs >> 16; SP(regs) -= 6; IP(regs) = segoffs & 0xffff; clear_TF(regs); @@ -524,7 +551,7 @@ int handle_vm86_trap(struct kernel_vm86_regs * regs, long error_code, int trapno if (VMPI.is_vm86pus) { if ( (trapno==3) || (trapno==1) ) return_to_32bit(regs, VM86_TRAP + (trapno << 8)); - do_int(regs, trapno, (unsigned char __user *) (regs->ss << 4), SP(regs)); + do_int(regs, trapno, (unsigned char __user *) (regs->pt.xss << 4), SP(regs)); return 0; } if (trapno !=1) @@ -560,10 +587,10 @@ void handle_vm86_fault(struct kernel_vm86_regs * regs, long error_code) handle_vm86_trap(regs, 0, 1); \ return; } while (0) - orig_flags = *(unsigned short *)®s->eflags; + orig_flags = *(unsigned short *)®s->pt.eflags; - csp = (unsigned char __user *) (regs->cs << 4); - ssp = (unsigned char __user *) (regs->ss << 4); + csp = (unsigned char __user *) (regs->pt.xcs << 4); + ssp = (unsigned char __user *) (regs->pt.xss << 4); sp = SP(regs); ip = IP(regs); @@ -650,7 +677,7 @@ void handle_vm86_fault(struct kernel_vm86_regs * regs, long error_code) SP(regs) += 6; } IP(regs) = newip; - regs->cs = newcs; + regs->pt.xcs = newcs; CHECK_IF_IN_TRAP; if (data32) { set_vflags_long(newflags, regs); diff --git a/trunk/arch/i386/kernel/vmlinux.lds.S b/trunk/arch/i386/kernel/vmlinux.lds.S index c6f84a0322ba..16d3c7133ad7 100644 --- a/trunk/arch/i386/kernel/vmlinux.lds.S +++ b/trunk/arch/i386/kernel/vmlinux.lds.S @@ -1,13 +1,26 @@ /* ld script to make i386 Linux kernel * Written by Martin Mares ; + * + * Don't define absolute symbols until and unless you know that symbol + * value is should remain constant even if kernel image is relocated + * at run time. Absolute symbols are not relocated. If symbol value should + * change if kernel is relocated, make the symbol section relative and + * put it inside the section definition. */ +/* Don't define absolute symbols until and unless you know that symbol + * value is should remain constant even if kernel image is relocated + * at run time. Absolute symbols are not relocated. If symbol value should + * change if kernel is relocated, make the symbol section relative and + * put it inside the section definition. + */ #define LOAD_OFFSET __PAGE_OFFSET #include #include #include #include +#include OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") OUTPUT_ARCH(i386) @@ -21,34 +34,37 @@ PHDRS { } SECTIONS { - . = __KERNEL_START; + . = LOAD_OFFSET + LOAD_PHYSICAL_ADDR; phys_startup_32 = startup_32 - LOAD_OFFSET; /* read-only */ - _text = .; /* Text and read-only data */ .text : AT(ADDR(.text) - LOAD_OFFSET) { + _text = .; /* Text and read-only data */ *(.text) SCHED_TEXT LOCK_TEXT KPROBES_TEXT *(.fixup) *(.gnu.warning) - } :text = 0x9090 - - _etext = .; /* End of text section */ + _etext = .; /* End of text section */ + } :text = 0x9090 . = ALIGN(16); /* Exception table */ - __start___ex_table = .; - __ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) { *(__ex_table) } - __stop___ex_table = .; + __ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) { + __start___ex_table = .; + *(__ex_table) + __stop___ex_table = .; + } RODATA + BUG_TABLE + . = ALIGN(4); - __tracedata_start = .; .tracedata : AT(ADDR(.tracedata) - LOAD_OFFSET) { + __tracedata_start = .; *(.tracedata) + __tracedata_end = .; } - __tracedata_end = .; /* writeable */ . = ALIGN(4096); @@ -57,11 +73,19 @@ SECTIONS CONSTRUCTORS } :data + .paravirtprobe : AT(ADDR(.paravirtprobe) - LOAD_OFFSET) { + __start_paravirtprobe = .; + *(.paravirtprobe) + __stop_paravirtprobe = .; + } + . = ALIGN(4096); - __nosave_begin = .; - .data_nosave : AT(ADDR(.data_nosave) - LOAD_OFFSET) { *(.data.nosave) } - . = ALIGN(4096); - __nosave_end = .; + .data_nosave : AT(ADDR(.data_nosave) - LOAD_OFFSET) { + __nosave_begin = .; + *(.data.nosave) + . = ALIGN(4096); + __nosave_end = .; + } . = ALIGN(4096); .data.page_aligned : AT(ADDR(.data.page_aligned) - LOAD_OFFSET) { @@ -75,17 +99,10 @@ SECTIONS /* rarely changed data like cpu maps */ . = ALIGN(32); - .data.read_mostly : AT(ADDR(.data.read_mostly) - LOAD_OFFSET) { *(.data.read_mostly) } - _edata = .; /* End of data section */ - -#ifdef CONFIG_STACK_UNWIND - . = ALIGN(4); - .eh_frame : AT(ADDR(.eh_frame) - LOAD_OFFSET) { - __start_unwind = .; - *(.eh_frame) - __end_unwind = .; + .data.read_mostly : AT(ADDR(.data.read_mostly) - LOAD_OFFSET) { + *(.data.read_mostly) + _edata = .; /* End of data section */ } -#endif . = ALIGN(THREAD_SIZE); /* init_task */ .data.init_task : AT(ADDR(.data.init_task) - LOAD_OFFSET) { @@ -94,88 +111,102 @@ SECTIONS /* might get freed after init */ . = ALIGN(4096); - __smp_alt_begin = .; - __smp_alt_instructions = .; .smp_altinstructions : AT(ADDR(.smp_altinstructions) - LOAD_OFFSET) { + __smp_alt_begin = .; + __smp_alt_instructions = .; *(.smp_altinstructions) + __smp_alt_instructions_end = .; } - __smp_alt_instructions_end = .; . = ALIGN(4); - __smp_locks = .; .smp_locks : AT(ADDR(.smp_locks) - LOAD_OFFSET) { + __smp_locks = .; *(.smp_locks) + __smp_locks_end = .; } - __smp_locks_end = .; .smp_altinstr_replacement : AT(ADDR(.smp_altinstr_replacement) - LOAD_OFFSET) { *(.smp_altinstr_replacement) + __smp_alt_end = .; } + /* will be freed after init + * Following ALIGN() is required to make sure no other data falls on the + * same page where __smp_alt_end is pointing as that page might be freed + * after boot. Always make sure that ALIGN() directive is present after + * the section which contains __smp_alt_end. + */ . = ALIGN(4096); - __smp_alt_end = .; /* will be freed after init */ . = ALIGN(4096); /* Init code and data */ - __init_begin = .; .init.text : AT(ADDR(.init.text) - LOAD_OFFSET) { + __init_begin = .; _sinittext = .; *(.init.text) _einittext = .; } .init.data : AT(ADDR(.init.data) - LOAD_OFFSET) { *(.init.data) } . = ALIGN(16); - __setup_start = .; - .init.setup : AT(ADDR(.init.setup) - LOAD_OFFSET) { *(.init.setup) } - __setup_end = .; - __initcall_start = .; + .init.setup : AT(ADDR(.init.setup) - LOAD_OFFSET) { + __setup_start = .; + *(.init.setup) + __setup_end = .; + } .initcall.init : AT(ADDR(.initcall.init) - LOAD_OFFSET) { + __initcall_start = .; INITCALLS + __initcall_end = .; } - __initcall_end = .; - __con_initcall_start = .; .con_initcall.init : AT(ADDR(.con_initcall.init) - LOAD_OFFSET) { + __con_initcall_start = .; *(.con_initcall.init) + __con_initcall_end = .; } - __con_initcall_end = .; SECURITY_INIT . = ALIGN(4); - __alt_instructions = .; .altinstructions : AT(ADDR(.altinstructions) - LOAD_OFFSET) { + __alt_instructions = .; *(.altinstructions) + __alt_instructions_end = .; } - __alt_instructions_end = .; .altinstr_replacement : AT(ADDR(.altinstr_replacement) - LOAD_OFFSET) { *(.altinstr_replacement) } + . = ALIGN(4); + .parainstructions : AT(ADDR(.parainstructions) - LOAD_OFFSET) { + __start_parainstructions = .; + *(.parainstructions) + __stop_parainstructions = .; + } /* .exit.text is discard at runtime, not link time, to deal with references from .altinstructions and .eh_frame */ .exit.text : AT(ADDR(.exit.text) - LOAD_OFFSET) { *(.exit.text) } .exit.data : AT(ADDR(.exit.data) - LOAD_OFFSET) { *(.exit.data) } . = ALIGN(4096); - __initramfs_start = .; - .init.ramfs : AT(ADDR(.init.ramfs) - LOAD_OFFSET) { *(.init.ramfs) } - __initramfs_end = .; + .init.ramfs : AT(ADDR(.init.ramfs) - LOAD_OFFSET) { + __initramfs_start = .; + *(.init.ramfs) + __initramfs_end = .; + } . = ALIGN(L1_CACHE_BYTES); - __per_cpu_start = .; - .data.percpu : AT(ADDR(.data.percpu) - LOAD_OFFSET) { *(.data.percpu) } - __per_cpu_end = .; + .data.percpu : AT(ADDR(.data.percpu) - LOAD_OFFSET) { + __per_cpu_start = .; + *(.data.percpu) + __per_cpu_end = .; + } . = ALIGN(4096); - __init_end = .; /* freed after init ends here */ - __bss_start = .; /* BSS */ - .bss.page_aligned : AT(ADDR(.bss.page_aligned) - LOAD_OFFSET) { - *(.bss.page_aligned) - } .bss : AT(ADDR(.bss) - LOAD_OFFSET) { + __init_end = .; + __bss_start = .; /* BSS */ + *(.bss.page_aligned) *(.bss) + . = ALIGN(4); + __bss_stop = .; + _end = . ; + /* This is where the kernel creates the early boot page tables */ + . = ALIGN(4096); + pg0 = . ; } - . = ALIGN(4); - __bss_stop = .; - - _end = . ; - - /* This is where the kernel creates the early boot page tables */ - . = ALIGN(4096); - pg0 = .; /* Sections to be discarded */ /DISCARD/ : { diff --git a/trunk/arch/i386/mach-generic/probe.c b/trunk/arch/i386/mach-generic/probe.c index 94b1fd9cbe3c..a7b3999bb37a 100644 --- a/trunk/arch/i386/mach-generic/probe.c +++ b/trunk/arch/i386/mach-generic/probe.c @@ -45,7 +45,9 @@ static int __init parse_apic(char *arg) return 0; } } - return -ENOENT; + + /* Parsed again by __setup for debug/verbose */ + return 0; } early_param("apic", parse_apic); diff --git a/trunk/arch/i386/mach-visws/setup.c b/trunk/arch/i386/mach-visws/setup.c index 885c7cbfd478..233ee20907b9 100644 --- a/trunk/arch/i386/mach-visws/setup.c +++ b/trunk/arch/i386/mach-visws/setup.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -142,6 +143,8 @@ void __init time_init_hook(void) unsigned long sgivwfb_mem_phys; unsigned long sgivwfb_mem_size; +EXPORT_SYMBOL(sgivwfb_mem_phys); +EXPORT_SYMBOL(sgivwfb_mem_size); long long mem_size __initdata = 0; diff --git a/trunk/arch/i386/mach-voyager/voyager_cat.c b/trunk/arch/i386/mach-voyager/voyager_cat.c index f50c6c6ad680..943a9473b138 100644 --- a/trunk/arch/i386/mach-voyager/voyager_cat.c +++ b/trunk/arch/i386/mach-voyager/voyager_cat.c @@ -776,7 +776,7 @@ voyager_cat_init(void) for(asic=0; asic < (*modpp)->num_asics; asic++) { int j; voyager_asic_t *asicp = *asicpp - = kmalloc(sizeof(voyager_asic_t), GFP_KERNEL); /*&voyager_asic_storage[asic_count++];*/ + = kzalloc(sizeof(voyager_asic_t), GFP_KERNEL); /*&voyager_asic_storage[asic_count++];*/ voyager_sp_table_t *sp_table; voyager_at_t *asic_table; voyager_jtt_t *jtag_table; @@ -785,7 +785,6 @@ voyager_cat_init(void) printk("**WARNING** kmalloc failure in cat_init\n"); continue; } - memset(asicp, 0, sizeof(voyager_asic_t)); asicpp = &(asicp->next); asicp->asic_location = asic; sp_table = (voyager_sp_table_t *)(eprom_buf + sp_offset); @@ -851,8 +850,7 @@ voyager_cat_init(void) #endif { - struct resource *res = kmalloc(sizeof(struct resource),GFP_KERNEL); - memset(res, 0, sizeof(struct resource)); + struct resource *res = kzalloc(sizeof(struct resource),GFP_KERNEL); res->name = kmalloc(128, GFP_KERNEL); sprintf((char *)res->name, "Voyager %s Quad CPI", cat_module_name(i)); res->start = qic_addr; diff --git a/trunk/arch/i386/mach-voyager/voyager_smp.c b/trunk/arch/i386/mach-voyager/voyager_smp.c index f3fea2ad50fe..55428e656a3f 100644 --- a/trunk/arch/i386/mach-voyager/voyager_smp.c +++ b/trunk/arch/i386/mach-voyager/voyager_smp.c @@ -28,6 +28,7 @@ #include #include #include +#include /* TLB state -- visible externally, indexed physically */ DEFINE_PER_CPU(struct tlb_state, cpu_tlbstate) ____cacheline_aligned = { &init_mm, 0 }; @@ -422,6 +423,7 @@ find_smp_config(void) VOYAGER_SUS_IN_CONTROL_PORT); current_thread_info()->cpu = boot_cpu_id; + write_pda(cpu_number, boot_cpu_id); } /* @@ -458,7 +460,7 @@ start_secondary(void *unused) /* external functions not defined in the headers */ extern void calibrate_delay(void); - cpu_init(); + secondary_cpu_init(); /* OK, we're in the routine */ ack_CPI(VIC_CPU_BOOT_CPI); @@ -578,6 +580,15 @@ do_boot_cpu(__u8 cpu) /* init_tasks (in sched.c) is indexed logically */ stack_start.esp = (void *) idle->thread.esp; + /* Pre-allocate and initialize the CPU's GDT and PDA so it + doesn't have to do any memory allocation during the + delicate CPU-bringup phase. */ + if (!init_gdt(cpu, idle)) { + printk(KERN_INFO "Couldn't allocate GDT/PDA for CPU %d\n", cpu); + cpucount--; + return; + } + irq_ctx_init(cpu); /* Note: Don't modify initial ss override */ @@ -1963,4 +1974,5 @@ void __init smp_setup_processor_id(void) { current_thread_info()->cpu = hard_smp_processor_id(); + write_pda(cpu_number, hard_smp_processor_id()); } diff --git a/trunk/arch/i386/math-emu/fpu_emu.h b/trunk/arch/i386/math-emu/fpu_emu.h index d62b20a3e660..65120f523853 100644 --- a/trunk/arch/i386/math-emu/fpu_emu.h +++ b/trunk/arch/i386/math-emu/fpu_emu.h @@ -57,6 +57,7 @@ #define TAG_Special Const(2) /* De-normal, + or - infinity, or Not a Number */ #define TAG_Empty Const(3) /* empty */ +#define TAG_Error Const(0x80) /* probably need to abort */ #define LOADED_DATA Const(10101) /* Special st() number to identify loaded data (not on stack). */ diff --git a/trunk/arch/i386/math-emu/fpu_entry.c b/trunk/arch/i386/math-emu/fpu_entry.c index d93f16ef828f..ddf8fa3bbd01 100644 --- a/trunk/arch/i386/math-emu/fpu_entry.c +++ b/trunk/arch/i386/math-emu/fpu_entry.c @@ -742,7 +742,8 @@ int save_i387_soft(void *s387, struct _fpstate __user * buf) S387->fcs &= ~0xf8000000; S387->fos |= 0xffff0000; #endif /* PECULIAR_486 */ - __copy_to_user(d, &S387->cwd, 7*4); + if (__copy_to_user(d, &S387->cwd, 7*4)) + return -1; RE_ENTRANT_CHECK_ON; d += 7*4; diff --git a/trunk/arch/i386/math-emu/fpu_system.h b/trunk/arch/i386/math-emu/fpu_system.h index bf26341c8bde..a3ae28c49ddd 100644 --- a/trunk/arch/i386/math-emu/fpu_system.h +++ b/trunk/arch/i386/math-emu/fpu_system.h @@ -68,6 +68,7 @@ #define FPU_access_ok(x,y,z) if ( !access_ok(x,y,z) ) \ math_abort(FPU_info,SIGSEGV) +#define FPU_abort math_abort(FPU_info, SIGSEGV) #undef FPU_IGNORE_CODE_SEGV #ifdef FPU_IGNORE_CODE_SEGV diff --git a/trunk/arch/i386/math-emu/load_store.c b/trunk/arch/i386/math-emu/load_store.c index 85314be2fef8..eebd6fb1c8a8 100644 --- a/trunk/arch/i386/math-emu/load_store.c +++ b/trunk/arch/i386/math-emu/load_store.c @@ -227,6 +227,8 @@ int FPU_load_store(u_char type, fpu_addr_modes addr_modes, case 027: /* fild m64int */ clear_C1(); loaded_tag = FPU_load_int64((long long __user *)data_address); + if (loaded_tag == TAG_Error) + return 0; FPU_settag0(loaded_tag); break; case 030: /* fstenv m14/28byte */ diff --git a/trunk/arch/i386/math-emu/reg_ld_str.c b/trunk/arch/i386/math-emu/reg_ld_str.c index f06ed41d191d..e976caef6498 100644 --- a/trunk/arch/i386/math-emu/reg_ld_str.c +++ b/trunk/arch/i386/math-emu/reg_ld_str.c @@ -244,7 +244,8 @@ int FPU_load_int64(long long __user *_s) RE_ENTRANT_CHECK_OFF; FPU_access_ok(VERIFY_READ, _s, 8); - copy_from_user(&s,_s,8); + if (copy_from_user(&s,_s,8)) + FPU_abort; RE_ENTRANT_CHECK_ON; if (s == 0) @@ -907,7 +908,8 @@ int FPU_store_int64(FPU_REG *st0_ptr, u_char st0_tag, long long __user *d) RE_ENTRANT_CHECK_OFF; FPU_access_ok(VERIFY_WRITE,d,8); - copy_to_user(d, &tll, 8); + if (copy_to_user(d, &tll, 8)) + FPU_abort; RE_ENTRANT_CHECK_ON; return 1; @@ -1336,7 +1338,8 @@ u_char __user *fstenv(fpu_addr_modes addr_modes, u_char __user *d) I387.soft.fcs &= ~0xf8000000; I387.soft.fos |= 0xffff0000; #endif /* PECULIAR_486 */ - __copy_to_user(d, &control_word, 7*4); + if (__copy_to_user(d, &control_word, 7*4)) + FPU_abort; RE_ENTRANT_CHECK_ON; d += 0x1c; } @@ -1359,9 +1362,11 @@ void fsave(fpu_addr_modes addr_modes, u_char __user *data_address) FPU_access_ok(VERIFY_WRITE,d,80); /* Copy all registers in stack order. */ - __copy_to_user(d, register_base+offset, other); + if (__copy_to_user(d, register_base+offset, other)) + FPU_abort; if ( offset ) - __copy_to_user(d+other, register_base, offset); + if (__copy_to_user(d+other, register_base, offset)) + FPU_abort; RE_ENTRANT_CHECK_ON; finit(); diff --git a/trunk/arch/i386/mm/boot_ioremap.c b/trunk/arch/i386/mm/boot_ioremap.c index 4de11f508c3a..4de95a17a7d4 100644 --- a/trunk/arch/i386/mm/boot_ioremap.c +++ b/trunk/arch/i386/mm/boot_ioremap.c @@ -16,6 +16,7 @@ */ #undef CONFIG_X86_PAE +#undef CONFIG_PARAVIRT #include #include #include diff --git a/trunk/arch/i386/mm/discontig.c b/trunk/arch/i386/mm/discontig.c index ddbdb0336f28..103b76e56a94 100644 --- a/trunk/arch/i386/mm/discontig.c +++ b/trunk/arch/i386/mm/discontig.c @@ -168,7 +168,7 @@ static void __init allocate_pgdat(int nid) if (nid && node_has_online_mem(nid)) NODE_DATA(nid) = (pg_data_t *)node_remap_start_vaddr[nid]; else { - NODE_DATA(nid) = (pg_data_t *)(__va(min_low_pfn << PAGE_SHIFT)); + NODE_DATA(nid) = (pg_data_t *)(pfn_to_kaddr(min_low_pfn)); min_low_pfn += PFN_UP(sizeof(pg_data_t)); } } diff --git a/trunk/arch/i386/mm/fault.c b/trunk/arch/i386/mm/fault.c index 2581575786c1..aaaa4d225f7e 100644 --- a/trunk/arch/i386/mm/fault.c +++ b/trunk/arch/i386/mm/fault.c @@ -22,9 +22,9 @@ #include #include #include +#include #include -#include #include #include #include @@ -167,7 +167,7 @@ static inline unsigned long get_segment_eip(struct pt_regs *regs, static int __is_prefetch(struct pt_regs *regs, unsigned long addr) { unsigned long limit; - unsigned long instr = get_segment_eip (regs, &limit); + unsigned char *instr = (unsigned char *)get_segment_eip (regs, &limit); int scan_more = 1; int prefetch = 0; int i; @@ -177,9 +177,9 @@ static int __is_prefetch(struct pt_regs *regs, unsigned long addr) unsigned char instr_hi; unsigned char instr_lo; - if (instr > limit) + if (instr > (unsigned char *)limit) break; - if (__get_user(opcode, (unsigned char __user *) instr)) + if (probe_kernel_address(instr, opcode)) break; instr_hi = opcode & 0xf0; @@ -204,9 +204,9 @@ static int __is_prefetch(struct pt_regs *regs, unsigned long addr) case 0x00: /* Prefetch instruction is 0x0F0D or 0x0F18 */ scan_more = 0; - if (instr > limit) + if (instr > (unsigned char *)limit) break; - if (__get_user(opcode, (unsigned char __user *) instr)) + if (probe_kernel_address(instr, opcode)) break; prefetch = (instr_lo == 0xF) && (opcode == 0x0D || opcode == 0x18); diff --git a/trunk/arch/i386/mm/highmem.c b/trunk/arch/i386/mm/highmem.c index f9f647cdbc7b..e0fa6cb655a8 100644 --- a/trunk/arch/i386/mm/highmem.c +++ b/trunk/arch/i386/mm/highmem.c @@ -32,7 +32,7 @@ void *kmap_atomic(struct page *page, enum km_type type) unsigned long vaddr; /* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */ - inc_preempt_count(); + pagefault_disable(); if (!PageHighMem(page)) return page_address(page); @@ -50,26 +50,22 @@ void kunmap_atomic(void *kvaddr, enum km_type type) unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK; enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id(); -#ifdef CONFIG_DEBUG_HIGHMEM - if (vaddr >= PAGE_OFFSET && vaddr < (unsigned long)high_memory) { - dec_preempt_count(); - preempt_check_resched(); - return; - } - - if (vaddr != __fix_to_virt(FIX_KMAP_BEGIN+idx)) - BUG(); -#endif /* * Force other mappings to Oops if they'll try to access this pte * without first remap it. Keeping stale mappings around is a bad idea * also, in case the page changes cacheability attributes or becomes * a protected page in a hypervisor. */ - kpte_clear_flush(kmap_pte-idx, vaddr); + if (vaddr == __fix_to_virt(FIX_KMAP_BEGIN+idx)) + kpte_clear_flush(kmap_pte-idx, vaddr); + else { +#ifdef CONFIG_DEBUG_HIGHMEM + BUG_ON(vaddr < PAGE_OFFSET); + BUG_ON(vaddr >= (unsigned long)high_memory); +#endif + } - dec_preempt_count(); - preempt_check_resched(); + pagefault_enable(); } /* This is the same as kmap_atomic() but can map memory that doesn't @@ -80,7 +76,7 @@ void *kmap_atomic_pfn(unsigned long pfn, enum km_type type) enum fixed_addresses idx; unsigned long vaddr; - inc_preempt_count(); + pagefault_disable(); idx = type + KM_TYPE_NR*smp_processor_id(); vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); diff --git a/trunk/arch/i386/mm/hugetlbpage.c b/trunk/arch/i386/mm/hugetlbpage.c index 1719a8141f81..34728e4afe48 100644 --- a/trunk/arch/i386/mm/hugetlbpage.c +++ b/trunk/arch/i386/mm/hugetlbpage.c @@ -17,6 +17,113 @@ #include #include +static unsigned long page_table_shareable(struct vm_area_struct *svma, + struct vm_area_struct *vma, + unsigned long addr, pgoff_t idx) +{ + unsigned long saddr = ((idx - svma->vm_pgoff) << PAGE_SHIFT) + + svma->vm_start; + unsigned long sbase = saddr & PUD_MASK; + unsigned long s_end = sbase + PUD_SIZE; + + /* + * match the virtual addresses, permission and the alignment of the + * page table page. + */ + if (pmd_index(addr) != pmd_index(saddr) || + vma->vm_flags != svma->vm_flags || + sbase < svma->vm_start || svma->vm_end < s_end) + return 0; + + return saddr; +} + +static int vma_shareable(struct vm_area_struct *vma, unsigned long addr) +{ + unsigned long base = addr & PUD_MASK; + unsigned long end = base + PUD_SIZE; + + /* + * check on proper vm_flags and page table alignment + */ + if (vma->vm_flags & VM_MAYSHARE && + vma->vm_start <= base && end <= vma->vm_end) + return 1; + return 0; +} + +/* + * search for a shareable pmd page for hugetlb. + */ +static void huge_pmd_share(struct mm_struct *mm, unsigned long addr, pud_t *pud) +{ + struct vm_area_struct *vma = find_vma(mm, addr); + struct address_space *mapping = vma->vm_file->f_mapping; + pgoff_t idx = ((addr - vma->vm_start) >> PAGE_SHIFT) + + vma->vm_pgoff; + struct prio_tree_iter iter; + struct vm_area_struct *svma; + unsigned long saddr; + pte_t *spte = NULL; + + if (!vma_shareable(vma, addr)) + return; + + spin_lock(&mapping->i_mmap_lock); + vma_prio_tree_foreach(svma, &iter, &mapping->i_mmap, idx, idx) { + if (svma == vma) + continue; + + saddr = page_table_shareable(svma, vma, addr, idx); + if (saddr) { + spte = huge_pte_offset(svma->vm_mm, saddr); + if (spte) { + get_page(virt_to_page(spte)); + break; + } + } + } + + if (!spte) + goto out; + + spin_lock(&mm->page_table_lock); + if (pud_none(*pud)) + pud_populate(mm, pud, (unsigned long) spte & PAGE_MASK); + else + put_page(virt_to_page(spte)); + spin_unlock(&mm->page_table_lock); +out: + spin_unlock(&mapping->i_mmap_lock); +} + +/* + * unmap huge page backed by shared pte. + * + * Hugetlb pte page is ref counted at the time of mapping. If pte is shared + * indicated by page_count > 1, unmap is achieved by clearing pud and + * decrementing the ref count. If count == 1, the pte page is not shared. + * + * called with vma->vm_mm->page_table_lock held. + * + * returns: 1 successfully unmapped a shared pte page + * 0 the underlying pte page is not shared, or it is the last user + */ +int huge_pmd_unshare(struct mm_struct *mm, unsigned long *addr, pte_t *ptep) +{ + pgd_t *pgd = pgd_offset(mm, *addr); + pud_t *pud = pud_offset(pgd, *addr); + + BUG_ON(page_count(virt_to_page(ptep)) == 0); + if (page_count(virt_to_page(ptep)) == 1) + return 0; + + pud_clear(pud); + put_page(virt_to_page(ptep)); + *addr = ALIGN(*addr, HPAGE_SIZE * PTRS_PER_PTE) - HPAGE_SIZE; + return 1; +} + pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr) { pgd_t *pgd; @@ -25,8 +132,11 @@ pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr) pgd = pgd_offset(mm, addr); pud = pud_alloc(mm, pgd, addr); - if (pud) + if (pud) { + if (pud_none(*pud)) + huge_pmd_share(mm, addr, pud); pte = (pte_t *) pmd_alloc(mm, pud, addr); + } BUG_ON(pte && !pte_none(*pte) && !pte_huge(*pte)); return pte; diff --git a/trunk/arch/i386/mm/init.c b/trunk/arch/i386/mm/init.c index 167416155ee4..84697dfc7348 100644 --- a/trunk/arch/i386/mm/init.c +++ b/trunk/arch/i386/mm/init.c @@ -192,8 +192,6 @@ static inline int page_kills_ppro(unsigned long pagenr) return 0; } -extern int is_available_memory(efi_memory_desc_t *); - int page_is_ram(unsigned long pagenr) { int i; @@ -699,8 +697,8 @@ int remove_memory(u64 start, u64 size) #endif #endif -kmem_cache_t *pgd_cache; -kmem_cache_t *pmd_cache; +struct kmem_cache *pgd_cache; +struct kmem_cache *pmd_cache; void __init pgtable_cache_init(void) { diff --git a/trunk/arch/i386/mm/pageattr.c b/trunk/arch/i386/mm/pageattr.c index 8564b6ae17e3..ad91528bdc14 100644 --- a/trunk/arch/i386/mm/pageattr.c +++ b/trunk/arch/i386/mm/pageattr.c @@ -67,11 +67,17 @@ static struct page *split_large_page(unsigned long address, pgprot_t prot, return base; } -static void flush_kernel_map(void *dummy) +static void flush_kernel_map(void *arg) { - /* Could use CLFLUSH here if the CPU supports it (Hammer,P4) */ - if (boot_cpu_data.x86_model >= 4) + unsigned long adr = (unsigned long)arg; + + if (adr && cpu_has_clflush) { + int i; + for (i = 0; i < PAGE_SIZE; i += boot_cpu_data.x86_clflush_size) + asm volatile("clflush (%0)" :: "r" (adr + i)); + } else if (boot_cpu_data.x86_model >= 4) wbinvd(); + /* Flush all to work around Errata in early athlons regarding * large page flushing. */ @@ -173,9 +179,9 @@ __change_page_attr(struct page *page, pgprot_t prot) return 0; } -static inline void flush_map(void) +static inline void flush_map(void *adr) { - on_each_cpu(flush_kernel_map, NULL, 1, 1); + on_each_cpu(flush_kernel_map, adr, 1, 1); } /* @@ -217,9 +223,13 @@ void global_flush_tlb(void) spin_lock_irq(&cpa_lock); list_replace_init(&df_list, &l); spin_unlock_irq(&cpa_lock); - flush_map(); - list_for_each_entry_safe(pg, next, &l, lru) + if (!cpu_has_clflush) + flush_map(0); + list_for_each_entry_safe(pg, next, &l, lru) { + if (cpu_has_clflush) + flush_map(page_address(pg)); __free_page(pg); + } } #ifdef CONFIG_DEBUG_PAGEALLOC diff --git a/trunk/arch/i386/mm/pgtable.c b/trunk/arch/i386/mm/pgtable.c index 10126e3f8174..f349eaf450b0 100644 --- a/trunk/arch/i386/mm/pgtable.c +++ b/trunk/arch/i386/mm/pgtable.c @@ -95,8 +95,11 @@ static void set_pte_pfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags) return; } pte = pte_offset_kernel(pmd, vaddr); - /* stored as-is, to permit clearing entries */ - set_pte(pte, pfn_pte(pfn, flags)); + if (pgprot_val(flags)) + /* stored as-is, to permit clearing entries */ + set_pte(pte, pfn_pte(pfn, flags)); + else + pte_clear(&init_mm, vaddr, pte); /* * It's enough to flush this one mapping. @@ -193,7 +196,7 @@ struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address) return pte; } -void pmd_ctor(void *pmd, kmem_cache_t *cache, unsigned long flags) +void pmd_ctor(void *pmd, struct kmem_cache *cache, unsigned long flags) { memset(pmd, 0, PTRS_PER_PMD*sizeof(pmd_t)); } @@ -233,7 +236,7 @@ static inline void pgd_list_del(pgd_t *pgd) set_page_private(next, (unsigned long)pprev); } -void pgd_ctor(void *pgd, kmem_cache_t *cache, unsigned long unused) +void pgd_ctor(void *pgd, struct kmem_cache *cache, unsigned long unused) { unsigned long flags; @@ -253,7 +256,7 @@ void pgd_ctor(void *pgd, kmem_cache_t *cache, unsigned long unused) } /* never called when PTRS_PER_PMD > 1 */ -void pgd_dtor(void *pgd, kmem_cache_t *cache, unsigned long unused) +void pgd_dtor(void *pgd, struct kmem_cache *cache, unsigned long unused) { unsigned long flags; /* can be called from interrupt context */ diff --git a/trunk/arch/i386/pci/early.c b/trunk/arch/i386/pci/early.c index 713d6c866cae..42df4b6606df 100644 --- a/trunk/arch/i386/pci/early.c +++ b/trunk/arch/i386/pci/early.c @@ -45,6 +45,13 @@ void write_pci_config(u8 bus, u8 slot, u8 func, u8 offset, outl(val, 0xcfc); } +void write_pci_config_byte(u8 bus, u8 slot, u8 func, u8 offset, u8 val) +{ + PDprintk("%x writing to %x: %x\n", slot, offset, val); + outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8); + outb(val, 0xcfc); +} + int early_pci_allowed(void) { return (pci_probe & (PCI_PROBE_CONF1|PCI_PROBE_NOEARLY)) == diff --git a/trunk/arch/i386/pci/irq.c b/trunk/arch/i386/pci/irq.c index e65551cd8216..f2cb942f8281 100644 --- a/trunk/arch/i386/pci/irq.c +++ b/trunk/arch/i386/pci/irq.c @@ -764,7 +764,7 @@ static void __init pirq_find_router(struct irq_router *r) DBG(KERN_DEBUG "PCI: Attempting to find IRQ router for %04x:%04x\n", rt->rtr_vendor, rt->rtr_device); - pirq_router_dev = pci_find_slot(rt->rtr_bus, rt->rtr_devfn); + pirq_router_dev = pci_get_bus_and_slot(rt->rtr_bus, rt->rtr_devfn); if (!pirq_router_dev) { DBG(KERN_DEBUG "PCI: Interrupt router not found at " "%02x:%02x\n", rt->rtr_bus, rt->rtr_devfn); @@ -784,6 +784,8 @@ static void __init pirq_find_router(struct irq_router *r) pirq_router_dev->vendor, pirq_router_dev->device, pci_name(pirq_router_dev)); + + /* The device remains referenced for the kernel lifetime */ } static struct irq_info *pirq_get_info(struct pci_dev *dev) diff --git a/trunk/arch/i386/pci/pcbios.c b/trunk/arch/i386/pci/pcbios.c index ed1512a175ab..5f5193401bea 100644 --- a/trunk/arch/i386/pci/pcbios.c +++ b/trunk/arch/i386/pci/pcbios.c @@ -5,6 +5,7 @@ #include #include #include +#include #include "pci.h" #include "pci-functions.h" @@ -314,6 +315,10 @@ static struct pci_raw_ops * __devinit pci_find_bios(void) for (check = (union bios32 *) __va(0xe0000); check <= (union bios32 *) __va(0xffff0); ++check) { + long sig; + if (probe_kernel_address(&check->fields.signature, sig)) + continue; + if (check->fields.signature != BIOS32_SIGNATURE) continue; length = check->fields.length * 16; @@ -331,11 +336,13 @@ static struct pci_raw_ops * __devinit pci_find_bios(void) } DBG("PCI: BIOS32 Service Directory structure at 0x%p\n", check); if (check->fields.entry >= 0x100000) { - printk("PCI: BIOS32 entry (0x%p) in high memory, cannot use.\n", check); + printk("PCI: BIOS32 entry (0x%p) in high memory, " + "cannot use.\n", check); return NULL; } else { unsigned long bios32_entry = check->fields.entry; - DBG("PCI: BIOS32 Service Directory entry at 0x%lx\n", bios32_entry); + DBG("PCI: BIOS32 Service Directory entry at 0x%lx\n", + bios32_entry); bios32_indirect.address = bios32_entry + PAGE_OFFSET; if (check_pcibios()) return &pci_bios_access; diff --git a/trunk/arch/i386/power/Makefile b/trunk/arch/i386/power/Makefile index 8cfa4e8a719d..2de7bbf03cd7 100644 --- a/trunk/arch/i386/power/Makefile +++ b/trunk/arch/i386/power/Makefile @@ -1,2 +1,2 @@ obj-$(CONFIG_PM) += cpu.o -obj-$(CONFIG_SOFTWARE_SUSPEND) += swsusp.o +obj-$(CONFIG_SOFTWARE_SUSPEND) += swsusp.o suspend.o diff --git a/trunk/arch/i386/power/cpu.c b/trunk/arch/i386/power/cpu.c index 5a1abeff033b..2c15500f8713 100644 --- a/trunk/arch/i386/power/cpu.c +++ b/trunk/arch/i386/power/cpu.c @@ -26,8 +26,8 @@ void __save_processor_state(struct saved_context *ctxt) /* * descriptor tables */ - store_gdt(&ctxt->gdt_limit); - store_idt(&ctxt->idt_limit); + store_gdt(&ctxt->gdt); + store_idt(&ctxt->idt); store_tr(ctxt->tr); /* @@ -99,8 +99,8 @@ void __restore_processor_state(struct saved_context *ctxt) * now restore the descriptor tables to their proper values * ltr is done i fix_processor_context(). */ - load_gdt(&ctxt->gdt_limit); - load_idt(&ctxt->idt_limit); + load_gdt(&ctxt->gdt); + load_idt(&ctxt->idt); /* * segment registers diff --git a/trunk/arch/i386/power/suspend.c b/trunk/arch/i386/power/suspend.c new file mode 100644 index 000000000000..db5e98d2eb73 --- /dev/null +++ b/trunk/arch/i386/power/suspend.c @@ -0,0 +1,158 @@ +/* + * Suspend support specific for i386 - temporary page tables + * + * Distribute under GPLv2 + * + * Copyright (c) 2006 Rafael J. Wysocki + */ + +#include +#include + +#include +#include +#include + +/* Defined in arch/i386/power/swsusp.S */ +extern int restore_image(void); + +/* Pointer to the temporary resume page tables */ +pgd_t *resume_pg_dir; + +/* The following three functions are based on the analogous code in + * arch/i386/mm/init.c + */ + +/* + * Create a middle page table on a resume-safe page and put a pointer to it in + * the given global directory entry. This only returns the gd entry + * in non-PAE compilation mode, since the middle layer is folded. + */ +static pmd_t *resume_one_md_table_init(pgd_t *pgd) +{ + pud_t *pud; + pmd_t *pmd_table; + +#ifdef CONFIG_X86_PAE + pmd_table = (pmd_t *)get_safe_page(GFP_ATOMIC); + if (!pmd_table) + return NULL; + + set_pgd(pgd, __pgd(__pa(pmd_table) | _PAGE_PRESENT)); + pud = pud_offset(pgd, 0); + + BUG_ON(pmd_table != pmd_offset(pud, 0)); +#else + pud = pud_offset(pgd, 0); + pmd_table = pmd_offset(pud, 0); +#endif + + return pmd_table; +} + +/* + * Create a page table on a resume-safe page and place a pointer to it in + * a middle page directory entry. + */ +static pte_t *resume_one_page_table_init(pmd_t *pmd) +{ + if (pmd_none(*pmd)) { + pte_t *page_table = (pte_t *)get_safe_page(GFP_ATOMIC); + if (!page_table) + return NULL; + + set_pmd(pmd, __pmd(__pa(page_table) | _PAGE_TABLE)); + + BUG_ON(page_table != pte_offset_kernel(pmd, 0)); + + return page_table; + } + + return pte_offset_kernel(pmd, 0); +} + +/* + * This maps the physical memory to kernel virtual address space, a total + * of max_low_pfn pages, by creating page tables starting from address + * PAGE_OFFSET. The page tables are allocated out of resume-safe pages. + */ +static int resume_physical_mapping_init(pgd_t *pgd_base) +{ + unsigned long pfn; + pgd_t *pgd; + pmd_t *pmd; + pte_t *pte; + int pgd_idx, pmd_idx; + + pgd_idx = pgd_index(PAGE_OFFSET); + pgd = pgd_base + pgd_idx; + pfn = 0; + + for (; pgd_idx < PTRS_PER_PGD; pgd++, pgd_idx++) { + pmd = resume_one_md_table_init(pgd); + if (!pmd) + return -ENOMEM; + + if (pfn >= max_low_pfn) + continue; + + for (pmd_idx = 0; pmd_idx < PTRS_PER_PMD; pmd++, pmd_idx++) { + if (pfn >= max_low_pfn) + break; + + /* Map with big pages if possible, otherwise create + * normal page tables. + * NOTE: We can mark everything as executable here + */ + if (cpu_has_pse) { + set_pmd(pmd, pfn_pmd(pfn, PAGE_KERNEL_LARGE_EXEC)); + pfn += PTRS_PER_PTE; + } else { + pte_t *max_pte; + + pte = resume_one_page_table_init(pmd); + if (!pte) + return -ENOMEM; + + max_pte = pte + PTRS_PER_PTE; + for (; pte < max_pte; pte++, pfn++) { + if (pfn >= max_low_pfn) + break; + + set_pte(pte, pfn_pte(pfn, PAGE_KERNEL_EXEC)); + } + } + } + } + return 0; +} + +static inline void resume_init_first_level_page_table(pgd_t *pg_dir) +{ +#ifdef CONFIG_X86_PAE + int i; + + /* Init entries of the first-level page table to the zero page */ + for (i = 0; i < PTRS_PER_PGD; i++) + set_pgd(pg_dir + i, + __pgd(__pa(empty_zero_page) | _PAGE_PRESENT)); +#endif +} + +int swsusp_arch_resume(void) +{ + int error; + + resume_pg_dir = (pgd_t *)get_safe_page(GFP_ATOMIC); + if (!resume_pg_dir) + return -ENOMEM; + + resume_init_first_level_page_table(resume_pg_dir); + error = resume_physical_mapping_init(resume_pg_dir); + if (error) + return error; + + /* We have got enough memory and from now on we cannot recover */ + restore_image(); + return 0; +} diff --git a/trunk/arch/i386/power/swsusp.S b/trunk/arch/i386/power/swsusp.S index 8a2b50a0aaad..53662e05b393 100644 --- a/trunk/arch/i386/power/swsusp.S +++ b/trunk/arch/i386/power/swsusp.S @@ -28,8 +28,9 @@ ENTRY(swsusp_arch_suspend) call swsusp_save ret -ENTRY(swsusp_arch_resume) - movl $swsusp_pg_dir-__PAGE_OFFSET, %ecx +ENTRY(restore_image) + movl resume_pg_dir, %ecx + subl $__PAGE_OFFSET, %ecx movl %ecx, %cr3 movl restore_pblist, %edx @@ -51,6 +52,10 @@ copy_loop: .p2align 4,,7 done: + /* go back to the original page tables */ + movl $swapper_pg_dir, %ecx + subl $__PAGE_OFFSET, %ecx + movl %ecx, %cr3 /* Flush TLB, including "global" things (vmalloc) */ movl mmu_cr4_features, %eax movl %eax, %edx diff --git a/trunk/arch/ia64/Kconfig b/trunk/arch/ia64/Kconfig index 683b12c6f76c..fcacfe291b9b 100644 --- a/trunk/arch/ia64/Kconfig +++ b/trunk/arch/ia64/Kconfig @@ -34,6 +34,14 @@ config RWSEM_XCHGADD_ALGORITHM bool default y +config ARCH_HAS_ILOG2_U32 + bool + default n + +config ARCH_HAS_ILOG2_U64 + bool + default n + config GENERIC_FIND_NEXT_BIT bool default y @@ -434,6 +442,29 @@ config IA64_ESI source "drivers/sn/Kconfig" +config KEXEC + bool "kexec system call (EXPERIMENTAL)" + depends on EXPERIMENTAL && !IA64_HP_SIM && (!SMP || HOTPLUG_CPU) + help + kexec is a system call that implements the ability to shutdown your + current kernel, and to start another kernel. It is like a reboot + but it is indepedent of the system firmware. And like a reboot + you can start any kernel with it, not just Linux. + + The name comes from the similiarity to the exec system call. + + It is an ongoing process to be certain the hardware in a machine + is properly shutdown, so do not be surprised if this code does not + initially work for you. It may help to enable device hotplugging + support. As of this writing the exact hardware interface is + strongly in flux, so no good recommendation can be made. + +config CRASH_DUMP + bool "kernel crash dumps (EXPERIMENTAL)" + depends on EXPERIMENTAL && IA64_MCA_RECOVERY && !IA64_HP_SIM && (!SMP || HOTPLUG_CPU) + help + Generate crash dump after being started by kexec. + source "drivers/firmware/Kconfig" source "fs/Kconfig.binfmt" diff --git a/trunk/arch/ia64/hp/common/sba_iommu.c b/trunk/arch/ia64/hp/common/sba_iommu.c index 14691cda05c3..ce49fe3a3b56 100644 --- a/trunk/arch/ia64/hp/common/sba_iommu.c +++ b/trunk/arch/ia64/hp/common/sba_iommu.c @@ -1672,15 +1672,13 @@ ioc_sac_init(struct ioc *ioc) * SAC (single address cycle) addressable, so allocate a * pseudo-device to enforce that. */ - sac = kmalloc(sizeof(*sac), GFP_KERNEL); + sac = kzalloc(sizeof(*sac), GFP_KERNEL); if (!sac) panic(PFX "Couldn't allocate struct pci_dev"); - memset(sac, 0, sizeof(*sac)); - controller = kmalloc(sizeof(*controller), GFP_KERNEL); + controller = kzalloc(sizeof(*controller), GFP_KERNEL); if (!controller) panic(PFX "Couldn't allocate struct pci_controller"); - memset(controller, 0, sizeof(*controller)); controller->iommu = ioc; sac->sysdata = controller; @@ -1737,12 +1735,10 @@ ioc_init(u64 hpa, void *handle) struct ioc *ioc; struct ioc_iommu *info; - ioc = kmalloc(sizeof(*ioc), GFP_KERNEL); + ioc = kzalloc(sizeof(*ioc), GFP_KERNEL); if (!ioc) return NULL; - memset(ioc, 0, sizeof(*ioc)); - ioc->next = ioc_list; ioc_list = ioc; diff --git a/trunk/arch/ia64/hp/sim/simserial.c b/trunk/arch/ia64/hp/sim/simserial.c index caab986af70c..1f16ebb9a800 100644 --- a/trunk/arch/ia64/hp/sim/simserial.c +++ b/trunk/arch/ia64/hp/sim/simserial.c @@ -209,7 +209,7 @@ static void do_serial_bh(void) } #endif -static void do_softint(void *private_) +static void do_softint(struct work_struct *private_) { printk(KERN_ERR "simserial: do_softint called\n"); } @@ -684,12 +684,11 @@ static int get_async_struct(int line, struct async_struct **ret_info) *ret_info = sstate->info; return 0; } - info = kmalloc(sizeof(struct async_struct), GFP_KERNEL); + info = kzalloc(sizeof(struct async_struct), GFP_KERNEL); if (!info) { sstate->count--; return -ENOMEM; } - memset(info, 0, sizeof(struct async_struct)); init_waitqueue_head(&info->open_wait); init_waitqueue_head(&info->close_wait); init_waitqueue_head(&info->delta_msr_wait); @@ -698,7 +697,7 @@ static int get_async_struct(int line, struct async_struct **ret_info) info->flags = sstate->flags; info->xmit_fifo_size = sstate->xmit_fifo_size; info->line = line; - INIT_WORK(&info->work, do_softint, info); + INIT_WORK(&info->work, do_softint); info->state = sstate; if (sstate->info) { kfree(info); diff --git a/trunk/arch/ia64/ia32/binfmt_elf32.c b/trunk/arch/ia64/ia32/binfmt_elf32.c index daa6b91bc921..578737ec7629 100644 --- a/trunk/arch/ia64/ia32/binfmt_elf32.c +++ b/trunk/arch/ia64/ia32/binfmt_elf32.c @@ -91,7 +91,7 @@ ia64_elf32_init (struct pt_regs *regs) * it with privilege level 3 because the IVE uses non-privileged accesses to these * tables. IA-32 segmentation is used to protect against IA-32 accesses to them. */ - vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL); + vma = kmem_cache_alloc(vm_area_cachep, GFP_KERNEL); if (vma) { memset(vma, 0, sizeof(*vma)); vma->vm_mm = current->mm; @@ -117,7 +117,7 @@ ia64_elf32_init (struct pt_regs *regs) * code is locked in specific gate page, which is pointed by pretcode * when setup_frame_ia32 */ - vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL); + vma = kmem_cache_alloc(vm_area_cachep, GFP_KERNEL); if (vma) { memset(vma, 0, sizeof(*vma)); vma->vm_mm = current->mm; @@ -142,7 +142,7 @@ ia64_elf32_init (struct pt_regs *regs) * Install LDT as anonymous memory. This gives us all-zero segment descriptors * until a task modifies them via modify_ldt(). */ - vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL); + vma = kmem_cache_alloc(vm_area_cachep, GFP_KERNEL); if (vma) { memset(vma, 0, sizeof(*vma)); vma->vm_mm = current->mm; @@ -214,7 +214,7 @@ ia32_setup_arg_pages (struct linux_binprm *bprm, int executable_stack) bprm->loader += stack_base; bprm->exec += stack_base; - mpnt = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL); + mpnt = kmem_cache_alloc(vm_area_cachep, GFP_KERNEL); if (!mpnt) return -ENOMEM; diff --git a/trunk/arch/ia64/ia32/ia32_support.c b/trunk/arch/ia64/ia32/ia32_support.c index c187743965a0..6af400a12ca1 100644 --- a/trunk/arch/ia64/ia32/ia32_support.c +++ b/trunk/arch/ia64/ia32/ia32_support.c @@ -249,7 +249,7 @@ ia32_init (void) #if PAGE_SHIFT > IA32_PAGE_SHIFT { - extern kmem_cache_t *partial_page_cachep; + extern struct kmem_cache *partial_page_cachep; partial_page_cachep = kmem_cache_create("partial_page_cache", sizeof(struct partial_page), 0, 0, diff --git a/trunk/arch/ia64/ia32/ia32priv.h b/trunk/arch/ia64/ia32/ia32priv.h index 703a67c934f8..cfa0bc0026b5 100644 --- a/trunk/arch/ia64/ia32/ia32priv.h +++ b/trunk/arch/ia64/ia32/ia32priv.h @@ -330,8 +330,6 @@ struct old_linux32_dirent { void ia64_elf32_init(struct pt_regs *regs); #define ELF_PLAT_INIT(_r, load_addr) ia64_elf32_init(_r) -#define elf_addr_t u32 - /* This macro yields a bitmask that programs can use to figure out what instruction set this CPU supports. */ #define ELF_HWCAP 0 diff --git a/trunk/arch/ia64/ia32/sys_ia32.c b/trunk/arch/ia64/ia32/sys_ia32.c index 9d6a3f210148..957681c39ad9 100644 --- a/trunk/arch/ia64/ia32/sys_ia32.c +++ b/trunk/arch/ia64/ia32/sys_ia32.c @@ -235,7 +235,7 @@ mmap_subpage (struct file *file, unsigned long start, unsigned long end, int pro if (!(flags & MAP_ANONYMOUS)) { /* read the file contents */ - inode = file->f_dentry->d_inode; + inode = file->f_path.dentry->d_inode; if (!inode->i_fop || !file->f_op->read || ((*file->f_op->read)(file, (char __user *) start, end - start, &off) < 0)) { @@ -254,7 +254,7 @@ mmap_subpage (struct file *file, unsigned long start, unsigned long end, int pro } /* SLAB cache for partial_page structures */ -kmem_cache_t *partial_page_cachep; +struct kmem_cache *partial_page_cachep; /* * init partial_page_list. @@ -837,7 +837,7 @@ emulate_mmap (struct file *file, unsigned long start, unsigned long len, int pro if (!is_congruent) { /* read the file contents */ - inode = file->f_dentry->d_inode; + inode = file->f_path.dentry->d_inode; if (!inode->i_fop || !file->f_op->read || ((*file->f_op->read)(file, (char __user *) pstart, pend - pstart, &poff) < 0)) diff --git a/trunk/arch/ia64/kernel/Makefile b/trunk/arch/ia64/kernel/Makefile index cfa099b04cda..8ae384eb5357 100644 --- a/trunk/arch/ia64/kernel/Makefile +++ b/trunk/arch/ia64/kernel/Makefile @@ -28,6 +28,7 @@ obj-$(CONFIG_IA64_CYCLONE) += cyclone.o obj-$(CONFIG_CPU_FREQ) += cpufreq/ obj-$(CONFIG_IA64_MCA_RECOVERY) += mca_recovery.o obj-$(CONFIG_KPROBES) += kprobes.o jprobes.o +obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o crash.o obj-$(CONFIG_IA64_UNCACHED_ALLOCATOR) += uncached.o obj-$(CONFIG_AUDIT) += audit.o obj-$(CONFIG_PCI_MSI) += msi_ia64.o diff --git a/trunk/arch/ia64/kernel/cpufreq/acpi-cpufreq.c b/trunk/arch/ia64/kernel/cpufreq/acpi-cpufreq.c index 86faf221a070..088f130197ae 100644 --- a/trunk/arch/ia64/kernel/cpufreq/acpi-cpufreq.c +++ b/trunk/arch/ia64/kernel/cpufreq/acpi-cpufreq.c @@ -68,7 +68,8 @@ processor_get_pstate ( dprintk("processor_get_pstate\n"); - retval = ia64_pal_get_pstate(&pstate_index); + retval = ia64_pal_get_pstate(&pstate_index, + PAL_GET_PSTATE_TYPE_INSTANT); *value = (u32) pstate_index; if (retval) @@ -91,7 +92,7 @@ extract_clock ( dprintk("extract_clock\n"); for (i = 0; i < data->acpi_data.state_count; i++) { - if (value >= data->acpi_data.states[i].control) + if (value == data->acpi_data.states[i].status) return data->acpi_data.states[i].core_frequency; } return data->acpi_data.states[i-1].core_frequency; @@ -117,11 +118,7 @@ processor_get_freq ( goto migrate_end; } - /* - * processor_get_pstate gets the average frequency since the - * last get. So, do two PAL_get_freq()... - */ - ret = processor_get_pstate(&value); + /* processor_get_pstate gets the instantaneous frequency */ ret = processor_get_pstate(&value); if (ret) { diff --git a/trunk/arch/ia64/kernel/crash.c b/trunk/arch/ia64/kernel/crash.c new file mode 100644 index 000000000000..0aabedf95dad --- /dev/null +++ b/trunk/arch/ia64/kernel/crash.c @@ -0,0 +1,245 @@ +/* + * arch/ia64/kernel/crash.c + * + * Architecture specific (ia64) functions for kexec based crash dumps. + * + * Created by: Khalid Aziz + * Copyright (C) 2005 Hewlett-Packard Development Company, L.P. + * Copyright (C) 2005 Intel Corp Zou Nan hai + * + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +int kdump_status[NR_CPUS]; +atomic_t kdump_cpu_freezed; +atomic_t kdump_in_progress; +int kdump_on_init = 1; +ssize_t +copy_oldmem_page(unsigned long pfn, char *buf, + size_t csize, unsigned long offset, int userbuf) +{ + void *vaddr; + + if (!csize) + return 0; + vaddr = __va(pfn<n_namesz = strlen(name) + 1; + note->n_descsz = data_len; + note->n_type = type; + buf += (sizeof(*note) + 3)/4; + memcpy(buf, name, note->n_namesz); + buf += (note->n_namesz + 3)/4; + memcpy(buf, data, data_len); + buf += (data_len + 3)/4; + return buf; +} + +static void +final_note(void *buf) +{ + memset(buf, 0, sizeof(struct elf_note)); +} + +extern void ia64_dump_cpu_regs(void *); + +static DEFINE_PER_CPU(struct elf_prstatus, elf_prstatus); + +void +crash_save_this_cpu() +{ + void *buf; + unsigned long cfm, sof, sol; + + int cpu = smp_processor_id(); + struct elf_prstatus *prstatus = &per_cpu(elf_prstatus, cpu); + + elf_greg_t *dst = (elf_greg_t *)&(prstatus->pr_reg); + memset(prstatus, 0, sizeof(*prstatus)); + prstatus->pr_pid = current->pid; + + ia64_dump_cpu_regs(dst); + cfm = dst[43]; + sol = (cfm >> 7) & 0x7f; + sof = cfm & 0x7f; + dst[46] = (unsigned long)ia64_rse_skip_regs((unsigned long *)dst[46], + sof - sol); + + buf = (u64 *) per_cpu_ptr(crash_notes, cpu); + if (!buf) + return; + buf = append_elf_note(buf, "CORE", NT_PRSTATUS, prstatus, + sizeof(*prstatus)); + final_note(buf); +} + +static int +kdump_wait_cpu_freeze(void) +{ + int cpu_num = num_online_cpus() - 1; + int timeout = 1000; + while(timeout-- > 0) { + if (atomic_read(&kdump_cpu_freezed) == cpu_num) + return 0; + udelay(1000); + } + return 1; +} + +void +machine_crash_shutdown(struct pt_regs *pt) +{ + /* This function is only called after the system + * has paniced or is otherwise in a critical state. + * The minimum amount of code to allow a kexec'd kernel + * to run successfully needs to happen here. + * + * In practice this means shooting down the other cpus in + * an SMP system. + */ + kexec_disable_iosapic(); +#ifdef CONFIG_SMP + kdump_smp_send_stop(); + if (kdump_wait_cpu_freeze() && kdump_on_init) { + //not all cpu response to IPI, send INIT to freeze them + kdump_smp_send_init(); + } +#endif +} + +static void +machine_kdump_on_init(void) +{ + local_irq_disable(); + kexec_disable_iosapic(); + machine_kexec(ia64_kimage); +} + +void +kdump_cpu_freeze(struct unw_frame_info *info, void *arg) +{ + int cpuid; + local_irq_disable(); + cpuid = smp_processor_id(); + crash_save_this_cpu(); + current->thread.ksp = (__u64)info->sw - 16; + atomic_inc(&kdump_cpu_freezed); + kdump_status[cpuid] = 1; + mb(); + if (cpuid == 0) { + for (;;) + cpu_relax(); + } else + ia64_jump_to_sal(&sal_boot_rendez_state[cpuid]); +} + +static int +kdump_init_notifier(struct notifier_block *self, unsigned long val, void *data) +{ + struct ia64_mca_notify_die *nd; + struct die_args *args = data; + + if (!kdump_on_init) + return NOTIFY_DONE; + + if (val != DIE_INIT_MONARCH_ENTER && + val != DIE_INIT_SLAVE_ENTER && + val != DIE_MCA_RENDZVOUS_LEAVE && + val != DIE_MCA_MONARCH_LEAVE) + return NOTIFY_DONE; + + nd = (struct ia64_mca_notify_die *)args->err; + /* Reason code 1 means machine check rendezous*/ + if ((val == DIE_INIT_MONARCH_ENTER || DIE_INIT_SLAVE_ENTER) && + nd->sos->rv_rc == 1) + return NOTIFY_DONE; + + switch (val) { + case DIE_INIT_MONARCH_ENTER: + machine_kdump_on_init(); + break; + case DIE_INIT_SLAVE_ENTER: + unw_init_running(kdump_cpu_freeze, NULL); + break; + case DIE_MCA_RENDZVOUS_LEAVE: + if (atomic_read(&kdump_in_progress)) + unw_init_running(kdump_cpu_freeze, NULL); + break; + case DIE_MCA_MONARCH_LEAVE: + /* die_register->signr indicate if MCA is recoverable */ + if (!args->signr) + machine_kdump_on_init(); + break; + } + return NOTIFY_DONE; +} + +#ifdef CONFIG_SYSCTL +static ctl_table kdump_on_init_table[] = { + { + .ctl_name = CTL_UNNUMBERED, + .procname = "kdump_on_init", + .data = &kdump_on_init, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, + { .ctl_name = 0 } +}; + +static ctl_table sys_table[] = { + { + .ctl_name = CTL_KERN, + .procname = "kernel", + .mode = 0555, + .child = kdump_on_init_table, + }, + { .ctl_name = 0 } +}; +#endif + +static int +machine_crash_setup(void) +{ + char *from = strstr(saved_command_line, "elfcorehdr="); + static struct notifier_block kdump_init_notifier_nb = { + .notifier_call = kdump_init_notifier, + }; + int ret; + if (from) + elfcorehdr_addr = memparse(from+11, &from); + saved_max_pfn = (unsigned long)-1; + if((ret = register_die_notifier(&kdump_init_notifier_nb)) != 0) + return ret; +#ifdef CONFIG_SYSCTL + register_sysctl_table(sys_table, 0); +#endif + return 0; +} + +__initcall(machine_crash_setup); + diff --git a/trunk/arch/ia64/kernel/efi.c b/trunk/arch/ia64/kernel/efi.c index bb8770a177b5..0b25a7d4e1e4 100644 --- a/trunk/arch/ia64/kernel/efi.c +++ b/trunk/arch/ia64/kernel/efi.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -41,7 +42,7 @@ extern efi_status_t efi_call_phys (void *, ...); struct efi efi; EXPORT_SYMBOL(efi); static efi_runtime_services_t *runtime; -static unsigned long mem_limit = ~0UL, max_addr = ~0UL; +static unsigned long mem_limit = ~0UL, max_addr = ~0UL, min_addr = 0UL; #define efi_call_virt(f, args...) (*(f))(args) @@ -224,7 +225,7 @@ efi_gettimeofday (struct timespec *ts) } static int -is_available_memory (efi_memory_desc_t *md) +is_memory_available (efi_memory_desc_t *md) { if (!(md->attribute & EFI_MEMORY_WB)) return 0; @@ -421,6 +422,8 @@ efi_init (void) mem_limit = memparse(cp + 4, &cp); } else if (memcmp(cp, "max_addr=", 9) == 0) { max_addr = GRANULEROUNDDOWN(memparse(cp + 9, &cp)); + } else if (memcmp(cp, "min_addr=", 9) == 0) { + min_addr = GRANULEROUNDDOWN(memparse(cp + 9, &cp)); } else { while (*cp != ' ' && *cp) ++cp; @@ -428,6 +431,8 @@ efi_init (void) ++cp; } } + if (min_addr != 0UL) + printk(KERN_INFO "Ignoring memory below %luMB\n", min_addr >> 20); if (max_addr != ~0UL) printk(KERN_INFO "Ignoring memory above %luMB\n", max_addr >> 20); @@ -887,14 +892,15 @@ find_memmap_space (void) } contig_high = GRANULEROUNDDOWN(contig_high); } - if (!is_available_memory(md) || md->type == EFI_LOADER_DATA) + if (!is_memory_available(md) || md->type == EFI_LOADER_DATA) continue; /* Round ends inward to granule boundaries */ as = max(contig_low, md->phys_addr); ae = min(contig_high, efi_md_end(md)); - /* keep within max_addr= command line arg */ + /* keep within max_addr= and min_addr= command line arg */ + as = max(as, min_addr); ae = min(ae, max_addr); if (ae <= as) continue; @@ -962,7 +968,7 @@ efi_memmap_init(unsigned long *s, unsigned long *e) } contig_high = GRANULEROUNDDOWN(contig_high); } - if (!is_available_memory(md)) + if (!is_memory_available(md)) continue; /* @@ -1004,7 +1010,8 @@ efi_memmap_init(unsigned long *s, unsigned long *e) } else ae = efi_md_end(md); - /* keep within max_addr= command line arg */ + /* keep within max_addr= and min_addr= command line arg */ + as = max(as, min_addr); ae = min(ae, max_addr); if (ae <= as) continue; @@ -1116,6 +1123,58 @@ efi_initialize_iomem_resources(struct resource *code_resource, */ insert_resource(res, code_resource); insert_resource(res, data_resource); +#ifdef CONFIG_KEXEC + insert_resource(res, &efi_memmap_res); + insert_resource(res, &boot_param_res); + if (crashk_res.end > crashk_res.start) + insert_resource(res, &crashk_res); +#endif } } } + +#ifdef CONFIG_KEXEC +/* find a block of memory aligned to 64M exclude reserved regions + rsvd_regions are sorted + */ +unsigned long +kdump_find_rsvd_region (unsigned long size, + struct rsvd_region *r, int n) +{ + int i; + u64 start, end; + u64 alignment = 1UL << _PAGE_SIZE_64M; + void *efi_map_start, *efi_map_end, *p; + efi_memory_desc_t *md; + u64 efi_desc_size; + + efi_map_start = __va(ia64_boot_param->efi_memmap); + efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size; + efi_desc_size = ia64_boot_param->efi_memdesc_size; + + for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) { + md = p; + if (!efi_wb(md)) + continue; + start = ALIGN(md->phys_addr, alignment); + end = efi_md_end(md); + for (i = 0; i < n; i++) { + if (__pa(r[i].start) >= start && __pa(r[i].end) < end) { + if (__pa(r[i].start) > start + size) + return start; + start = ALIGN(__pa(r[i].end), alignment); + if (i < n-1 && __pa(r[i+1].start) < start + size) + continue; + else + break; + } + } + if (end > start + size) + return start; + } + + printk(KERN_WARNING "Cannot reserve 0x%lx byte of memory for crashdump\n", + size); + return ~0UL; +} +#endif diff --git a/trunk/arch/ia64/kernel/entry.S b/trunk/arch/ia64/kernel/entry.S index 3390b7c5a63f..15234ed3a341 100644 --- a/trunk/arch/ia64/kernel/entry.S +++ b/trunk/arch/ia64/kernel/entry.S @@ -1575,7 +1575,7 @@ sys_call_table: data8 sys_mq_timedreceive // 1265 data8 sys_mq_notify data8 sys_mq_getsetattr - data8 sys_ni_syscall // reserved for kexec_load + data8 sys_kexec_load data8 sys_ni_syscall // reserved for vserver data8 sys_waitid // 1270 data8 sys_add_key diff --git a/trunk/arch/ia64/kernel/ia64_ksyms.c b/trunk/arch/ia64/kernel/ia64_ksyms.c index 879c1817bd1c..bd17190bebb6 100644 --- a/trunk/arch/ia64/kernel/ia64_ksyms.c +++ b/trunk/arch/ia64/kernel/ia64_ksyms.c @@ -14,6 +14,7 @@ EXPORT_SYMBOL(strlen); #include EXPORT_SYMBOL(ip_fast_csum); /* hand-coded assembly */ +EXPORT_SYMBOL(csum_ipv6_magic); #include EXPORT_SYMBOL(__down); diff --git a/trunk/arch/ia64/kernel/iosapic.c b/trunk/arch/ia64/kernel/iosapic.c index 60d64950e3c2..0fc5fb7865cf 100644 --- a/trunk/arch/ia64/kernel/iosapic.c +++ b/trunk/arch/ia64/kernel/iosapic.c @@ -288,6 +288,27 @@ nop (unsigned int irq) /* do nothing... */ } + +#ifdef CONFIG_KEXEC +void +kexec_disable_iosapic(void) +{ + struct iosapic_intr_info *info; + struct iosapic_rte_info *rte; + u8 vec = 0; + for (info = iosapic_intr_info; info < + iosapic_intr_info + IA64_NUM_VECTORS; ++info, ++vec) { + list_for_each_entry(rte, &info->rtes, + rte_list) { + iosapic_write(rte->addr, + IOSAPIC_RTE_LOW(rte->rte_index), + IOSAPIC_MASK|vec); + iosapic_eoi(rte->addr, vec); + } + } +} +#endif + static void mask_irq (unsigned int irq) { diff --git a/trunk/arch/ia64/kernel/kprobes.c b/trunk/arch/ia64/kernel/kprobes.c index 51217d63285e..76e778951e20 100644 --- a/trunk/arch/ia64/kernel/kprobes.c +++ b/trunk/arch/ia64/kernel/kprobes.c @@ -481,7 +481,7 @@ void __kprobes arch_disarm_kprobe(struct kprobe *p) void __kprobes arch_remove_kprobe(struct kprobe *p) { mutex_lock(&kprobe_mutex); - free_insn_slot(p->ainsn.insn); + free_insn_slot(p->ainsn.insn, 0); mutex_unlock(&kprobe_mutex); } /* @@ -851,7 +851,7 @@ static void ia64_get_bsp_cfm(struct unw_frame_info *info, void *arg) return; } } while (unw_unwind(info) >= 0); - lp->bsp = 0; + lp->bsp = NULL; lp->cfm = 0; return; } diff --git a/trunk/arch/ia64/kernel/machine_kexec.c b/trunk/arch/ia64/kernel/machine_kexec.c new file mode 100644 index 000000000000..468233fa2cee --- /dev/null +++ b/trunk/arch/ia64/kernel/machine_kexec.c @@ -0,0 +1,133 @@ +/* + * arch/ia64/kernel/machine_kexec.c + * + * Handle transition of Linux booting another kernel + * Copyright (C) 2005 Hewlett-Packard Development Comapny, L.P. + * Copyright (C) 2005 Khalid Aziz + * Copyright (C) 2006 Intel Corp, Zou Nan hai + * + * This source code is licensed under the GNU General Public License, + * Version 2. See the file COPYING for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +typedef void (*relocate_new_kernel_t)(unsigned long, unsigned long, + struct ia64_boot_param *, unsigned long); + +struct kimage *ia64_kimage; + +struct resource efi_memmap_res = { + .name = "EFI Memory Map", + .start = 0, + .end = 0, + .flags = IORESOURCE_BUSY | IORESOURCE_MEM +}; + +struct resource boot_param_res = { + .name = "Boot parameter", + .start = 0, + .end = 0, + .flags = IORESOURCE_BUSY | IORESOURCE_MEM +}; + + +/* + * Do what every setup is needed on image and the + * reboot code buffer to allow us to avoid allocations + * later. + */ +int machine_kexec_prepare(struct kimage *image) +{ + void *control_code_buffer; + const unsigned long *func; + + func = (unsigned long *)&relocate_new_kernel; + /* Pre-load control code buffer to minimize work in kexec path */ + control_code_buffer = page_address(image->control_code_page); + memcpy((void *)control_code_buffer, (const void *)func[0], + relocate_new_kernel_size); + flush_icache_range((unsigned long)control_code_buffer, + (unsigned long)control_code_buffer + relocate_new_kernel_size); + ia64_kimage = image; + + return 0; +} + +void machine_kexec_cleanup(struct kimage *image) +{ +} + +void machine_shutdown(void) +{ + int cpu; + + for_each_online_cpu(cpu) { + if (cpu != smp_processor_id()) + cpu_down(cpu); + } + kexec_disable_iosapic(); +} + +/* + * Do not allocate memory (or fail in any way) in machine_kexec(). + * We are past the point of no return, committed to rebooting now. + */ +extern void *efi_get_pal_addr(void); +static void ia64_machine_kexec(struct unw_frame_info *info, void *arg) +{ + struct kimage *image = arg; + relocate_new_kernel_t rnk; + void *pal_addr = efi_get_pal_addr(); + unsigned long code_addr = (unsigned long)page_address(image->control_code_page); + unsigned long vector; + int ii; + + if (image->type == KEXEC_TYPE_CRASH) { + crash_save_this_cpu(); + current->thread.ksp = (__u64)info->sw - 16; + } + + /* Interrupts aren't acceptable while we reboot */ + local_irq_disable(); + + /* Mask CMC and Performance Monitor interrupts */ + ia64_setreg(_IA64_REG_CR_PMV, 1 << 16); + ia64_setreg(_IA64_REG_CR_CMCV, 1 << 16); + + /* Mask ITV and Local Redirect Registers */ + ia64_set_itv(1 << 16); + ia64_set_lrr0(1 << 16); + ia64_set_lrr1(1 << 16); + + /* terminate possible nested in-service interrupts */ + for (ii = 0; ii < 16; ii++) + ia64_eoi(); + + /* unmask TPR and clear any pending interrupts */ + ia64_setreg(_IA64_REG_CR_TPR, 0); + ia64_srlz_d(); + vector = ia64_get_ivr(); + while (vector != IA64_SPURIOUS_INT_VECTOR) { + ia64_eoi(); + vector = ia64_get_ivr(); + } + platform_kernel_launch_event(); + rnk = (relocate_new_kernel_t)&code_addr; + (*rnk)(image->head, image->start, ia64_boot_param, + GRANULEROUNDDOWN((unsigned long) pal_addr)); + BUG(); +} + +void machine_kexec(struct kimage *image) +{ + unw_init_running(ia64_machine_kexec, image); + for(;;); +} diff --git a/trunk/arch/ia64/kernel/mca.c b/trunk/arch/ia64/kernel/mca.c index 7cfa63a98cb3..87c1c4f42872 100644 --- a/trunk/arch/ia64/kernel/mca.c +++ b/trunk/arch/ia64/kernel/mca.c @@ -82,6 +82,7 @@ #include #include #include +#include #include #include @@ -678,7 +679,7 @@ ia64_mca_cmc_vector_enable (void *dummy) * disable the cmc interrupt vector. */ static void -ia64_mca_cmc_vector_disable_keventd(void *unused) +ia64_mca_cmc_vector_disable_keventd(struct work_struct *unused) { on_each_cpu(ia64_mca_cmc_vector_disable, NULL, 1, 0); } @@ -690,7 +691,7 @@ ia64_mca_cmc_vector_disable_keventd(void *unused) * enable the cmc interrupt vector. */ static void -ia64_mca_cmc_vector_enable_keventd(void *unused) +ia64_mca_cmc_vector_enable_keventd(struct work_struct *unused) { on_each_cpu(ia64_mca_cmc_vector_enable, NULL, 1, 0); } @@ -1238,6 +1239,10 @@ ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw, } else { /* Dump buffered message to console */ ia64_mlogbuf_finish(1); +#ifdef CONFIG_CRASH_DUMP + atomic_set(&kdump_in_progress, 1); + monarch_cpu = -1; +#endif } if (notify_die(DIE_MCA_MONARCH_LEAVE, "MCA", regs, (long)&nd, 0, recover) == NOTIFY_STOP) @@ -1247,8 +1252,8 @@ ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw, monarch_cpu = -1; } -static DECLARE_WORK(cmc_disable_work, ia64_mca_cmc_vector_disable_keventd, NULL); -static DECLARE_WORK(cmc_enable_work, ia64_mca_cmc_vector_enable_keventd, NULL); +static DECLARE_WORK(cmc_disable_work, ia64_mca_cmc_vector_disable_keventd); +static DECLARE_WORK(cmc_enable_work, ia64_mca_cmc_vector_enable_keventd); /* * ia64_mca_cmc_int_handler diff --git a/trunk/arch/ia64/kernel/palinfo.c b/trunk/arch/ia64/kernel/palinfo.c index 0b546e2b36ac..a71df9ae0397 100644 --- a/trunk/arch/ia64/kernel/palinfo.c +++ b/trunk/arch/ia64/kernel/palinfo.c @@ -16,6 +16,7 @@ * 02/05/2001 S.Eranian fixed module support * 10/23/2001 S.Eranian updated pal_perf_mon_info bug fixes * 03/24/2004 Ashok Raj updated to work with CPU Hotplug + * 10/26/2006 Russ Anderson updated processor features to rev 2.2 spec */ #include #include @@ -314,13 +315,20 @@ vm_info(char *page) "Protection Key Registers(PKR) : %d\n" "Implemented bits in PKR.key : %d\n" "Hash Tag ID : 0x%x\n" - "Size of RR.rid : %d\n", + "Size of RR.rid : %d\n" + "Max Purges : ", vm_info_1.pal_vm_info_1_s.phys_add_size, vm_info_2.pal_vm_info_2_s.impl_va_msb+1, vm_info_1.pal_vm_info_1_s.max_pkr+1, vm_info_1.pal_vm_info_1_s.key_size, vm_info_1.pal_vm_info_1_s.hash_tag_id, vm_info_2.pal_vm_info_2_s.rid_size); + if (vm_info_2.pal_vm_info_2_s.max_purges == PAL_MAX_PURGES) + p += sprintf(p, "unlimited\n"); + else + p += sprintf(p, "%d\n", + vm_info_2.pal_vm_info_2_s.max_purges ? + vm_info_2.pal_vm_info_2_s.max_purges : 1); } if (ia64_pal_mem_attrib(&attrib) == 0) { @@ -467,7 +475,11 @@ static const char *proc_features[]={ NULL,NULL,NULL,NULL,NULL,NULL,NULL, NULL,NULL, NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, NULL,NULL,NULL,NULL,NULL, NULL,NULL,NULL,NULL, - NULL,NULL,NULL,NULL,NULL, + "Unimplemented instruction address fault", + "INIT, PMI, and LINT pins", + "Simple unimplemented instr addresses", + "Variable P-state performance", + "Virtual machine features implemented", "XIP,XPSR,XFS implemented", "XR1-XR3 implemented", "Disable dynamic predicate prediction", @@ -475,7 +487,11 @@ static const char *proc_features[]={ "Disable dynamic data cache prefetch", "Disable dynamic inst cache prefetch", "Disable dynamic branch prediction", - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + "Disable P-states", + "Enable MCA on Data Poisoning", + "Enable vmsw instruction", + "Enable extern environmental notification", "Disable BINIT on processor time-out", "Disable dynamic power management (DPM)", "Disable coherency", @@ -952,7 +968,6 @@ remove_palinfo_proc_entries(unsigned int hcpu) } } -#ifdef CONFIG_HOTPLUG_CPU static int palinfo_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { @@ -974,7 +989,6 @@ static struct notifier_block palinfo_cpu_notifier = .notifier_call = palinfo_cpu_callback, .priority = 0, }; -#endif static int __init palinfo_init(void) diff --git a/trunk/arch/ia64/kernel/perfmon.c b/trunk/arch/ia64/kernel/perfmon.c index 3aaede0d6981..aa94f60fa8e7 100644 --- a/trunk/arch/ia64/kernel/perfmon.c +++ b/trunk/arch/ia64/kernel/perfmon.c @@ -853,9 +853,8 @@ pfm_context_alloc(void) * allocate context descriptor * must be able to free with interrupts disabled */ - ctx = kmalloc(sizeof(pfm_context_t), GFP_KERNEL); + ctx = kzalloc(sizeof(pfm_context_t), GFP_KERNEL); if (ctx) { - memset(ctx, 0, sizeof(pfm_context_t)); DPRINT(("alloc ctx @%p\n", ctx)); } return ctx; @@ -2189,13 +2188,13 @@ pfm_alloc_fd(struct file **cfile) /* * allocate a new dcache entry */ - file->f_dentry = d_alloc(pfmfs_mnt->mnt_sb->s_root, &this); - if (!file->f_dentry) goto out; + file->f_path.dentry = d_alloc(pfmfs_mnt->mnt_sb->s_root, &this); + if (!file->f_path.dentry) goto out; - file->f_dentry->d_op = &pfmfs_dentry_operations; + file->f_path.dentry->d_op = &pfmfs_dentry_operations; - d_add(file->f_dentry, inode); - file->f_vfsmnt = mntget(pfmfs_mnt); + d_add(file->f_path.dentry, inode); + file->f_path.mnt = mntget(pfmfs_mnt); file->f_mapping = inode->i_mapping; file->f_op = &pfm_file_ops; @@ -2302,7 +2301,7 @@ pfm_smpl_buffer_alloc(struct task_struct *task, pfm_context_t *ctx, unsigned lon DPRINT(("smpl_buf @%p\n", smpl_buf)); /* allocate vma */ - vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL); + vma = kmem_cache_alloc(vm_area_cachep, GFP_KERNEL); if (!vma) { DPRINT(("Cannot allocate vma\n")); goto error_kmem; diff --git a/trunk/arch/ia64/kernel/perfmon_montecito.h b/trunk/arch/ia64/kernel/perfmon_montecito.h index cd06ac6a686c..7f8da4c7ca67 100644 --- a/trunk/arch/ia64/kernel/perfmon_montecito.h +++ b/trunk/arch/ia64/kernel/perfmon_montecito.h @@ -45,16 +45,16 @@ static pfm_reg_desc_t pfm_mont_pmc_desc[PMU_MAX_PMCS]={ /* pmc29 */ { PFM_REG_NOTIMPL, }, /* pmc30 */ { PFM_REG_NOTIMPL, }, /* pmc31 */ { PFM_REG_NOTIMPL, }, -/* pmc32 */ { PFM_REG_CONFIG, 0, 0x30f01ffffffffff, 0x30f01ffffffffff, NULL, pfm_mont_pmc_check, {0,0, 0, 0}, {0,0, 0, 0}}, -/* pmc33 */ { PFM_REG_CONFIG, 0, 0x0, 0x1ffffffffff, NULL, pfm_mont_pmc_check, {0,0, 0, 0}, {0,0, 0, 0}}, -/* pmc34 */ { PFM_REG_CONFIG, 0, 0xf01ffffffffff, 0xf01ffffffffff, NULL, pfm_mont_pmc_check, {0,0, 0, 0}, {0,0, 0, 0}}, -/* pmc35 */ { PFM_REG_CONFIG, 0, 0x0, 0x1ffffffffff, NULL, pfm_mont_pmc_check, {0,0, 0, 0}, {0,0, 0, 0}}, +/* pmc32 */ { PFM_REG_CONFIG, 0, 0x30f01ffffffffffUL, 0x30f01ffffffffffUL, NULL, pfm_mont_pmc_check, {0,0, 0, 0}, {0,0, 0, 0}}, +/* pmc33 */ { PFM_REG_CONFIG, 0, 0x0, 0x1ffffffffffUL, NULL, pfm_mont_pmc_check, {0,0, 0, 0}, {0,0, 0, 0}}, +/* pmc34 */ { PFM_REG_CONFIG, 0, 0xf01ffffffffffUL, 0xf01ffffffffffUL, NULL, pfm_mont_pmc_check, {0,0, 0, 0}, {0,0, 0, 0}}, +/* pmc35 */ { PFM_REG_CONFIG, 0, 0x0, 0x1ffffffffffUL, NULL, pfm_mont_pmc_check, {0,0, 0, 0}, {0,0, 0, 0}}, /* pmc36 */ { PFM_REG_CONFIG, 0, 0xfffffff0, 0xf, NULL, pfm_mont_pmc_check, {0,0, 0, 0}, {0,0, 0, 0}}, /* pmc37 */ { PFM_REG_MONITOR, 4, 0x0, 0x3fff, NULL, pfm_mont_pmc_check, {RDEP_MONT_IEAR, 0, 0, 0}, {0, 0, 0, 0}}, /* pmc38 */ { PFM_REG_CONFIG, 0, 0xdb6, 0x2492, NULL, pfm_mont_pmc_check, {0,0, 0, 0}, {0,0, 0, 0}}, /* pmc39 */ { PFM_REG_MONITOR, 6, 0x0, 0xffcf, NULL, pfm_mont_pmc_check, {RDEP_MONT_ETB,0, 0, 0}, {0,0, 0, 0}}, /* pmc40 */ { PFM_REG_MONITOR, 6, 0x2000000, 0xf01cf, NULL, pfm_mont_pmc_check, {RDEP_MONT_DEAR,0, 0, 0}, {0,0, 0, 0}}, -/* pmc41 */ { PFM_REG_CONFIG, 0, 0x00002078fefefefe, 0x1e00018181818, NULL, pfm_mont_pmc_check, {0,0, 0, 0}, {0,0, 0, 0}}, +/* pmc41 */ { PFM_REG_CONFIG, 0, 0x00002078fefefefeUL, 0x1e00018181818UL, NULL, pfm_mont_pmc_check, {0,0, 0, 0}, {0,0, 0, 0}}, /* pmc42 */ { PFM_REG_MONITOR, 6, 0x0, 0x7ff4f, NULL, pfm_mont_pmc_check, {RDEP_MONT_ETB,0, 0, 0}, {0,0, 0, 0}}, { PFM_REG_END , 0, 0x0, -1, NULL, NULL, {0,}, {0,}}, /* end marker */ }; @@ -185,7 +185,7 @@ pfm_mont_pmc_check(struct task_struct *task, pfm_context_t *ctx, unsigned int cn DPRINT(("cnum=%u val=0x%lx, using_dbreg=%d loaded=%d\n", cnum, tmpval, ctx->ctx_fl_using_dbreg, is_loaded)); if (cnum == 41 && is_loaded - && (tmpval & 0x1e00000000000) && (tmpval & 0x18181818UL) != 0x18181818UL && ctx->ctx_fl_using_dbreg == 0) { + && (tmpval & 0x1e00000000000UL) && (tmpval & 0x18181818UL) != 0x18181818UL && ctx->ctx_fl_using_dbreg == 0) { DPRINT(("pmc[%d]=0x%lx has active pmc41 settings, clearing dbr\n", cnum, tmpval)); diff --git a/trunk/arch/ia64/kernel/relocate_kernel.S b/trunk/arch/ia64/kernel/relocate_kernel.S new file mode 100644 index 000000000000..ae473e3f2a0d --- /dev/null +++ b/trunk/arch/ia64/kernel/relocate_kernel.S @@ -0,0 +1,334 @@ +/* + * arch/ia64/kernel/relocate_kernel.S + * + * Relocate kexec'able kernel and start it + * + * Copyright (C) 2005 Hewlett-Packard Development Company, L.P. + * Copyright (C) 2005 Khalid Aziz + * Copyright (C) 2005 Intel Corp, Zou Nan hai + * + * This source code is licensed under the GNU General Public License, + * Version 2. See the file COPYING for more details. + */ +#include +#include +#include +#include +#include + + /* Must be relocatable PIC code callable as a C function + */ +GLOBAL_ENTRY(relocate_new_kernel) + .prologue + alloc r31=ar.pfs,4,0,0,0 + .body +.reloc_entry: +{ + rsm psr.i| psr.ic + mov r2=ip +} + ;; +{ + flushrs // must be first insn in group + srlz.i +} + ;; + dep r2=0,r2,61,3 //to physical address + ;; + //first switch to physical mode + add r3=1f-.reloc_entry, r2 + movl r16 = IA64_PSR_AC|IA64_PSR_BN|IA64_PSR_IC + mov ar.rsc=0 // put RSE in enforced lazy mode + ;; + add sp=(memory_stack_end - 16 - .reloc_entry),r2 + add r8=(register_stack - .reloc_entry),r2 + ;; + mov r18=ar.rnat + mov ar.bspstore=r8 + ;; + mov cr.ipsr=r16 + mov cr.iip=r3 + mov cr.ifs=r0 + srlz.i + ;; + mov ar.rnat=r18 + rfi + ;; +1: + //physical mode code begin + mov b6=in1 + dep r28=0,in2,61,3 //to physical address + + // purge all TC entries +#define O(member) IA64_CPUINFO_##member##_OFFSET + GET_THIS_PADDR(r2, cpu_info) // load phys addr of cpu_info into r2 + ;; + addl r17=O(PTCE_STRIDE),r2 + addl r2=O(PTCE_BASE),r2 + ;; + ld8 r18=[r2],(O(PTCE_COUNT)-O(PTCE_BASE));; // r18=ptce_base + ld4 r19=[r2],4 // r19=ptce_count[0] + ld4 r21=[r17],4 // r21=ptce_stride[0] + ;; + ld4 r20=[r2] // r20=ptce_count[1] + ld4 r22=[r17] // r22=ptce_stride[1] + mov r24=r0 + ;; + adds r20=-1,r20 + ;; +#undef O +2: + cmp.ltu p6,p7=r24,r19 +(p7) br.cond.dpnt.few 4f + mov ar.lc=r20 +3: + ptc.e r18 + ;; + add r18=r22,r18 + br.cloop.sptk.few 3b + ;; + add r18=r21,r18 + add r24=1,r24 + ;; + br.sptk.few 2b +4: + srlz.i + ;; + //purge TR entry for kernel text and data + movl r16=KERNEL_START + mov r18=KERNEL_TR_PAGE_SHIFT<<2 + ;; + ptr.i r16, r18 + ptr.d r16, r18 + ;; + srlz.i + ;; + + // purge TR entry for percpu data + movl r16=PERCPU_ADDR + mov r18=PERCPU_PAGE_SHIFT<<2 + ;; + ptr.d r16,r18 + ;; + srlz.d + ;; + + // purge TR entry for pal code + mov r16=in3 + mov r18=IA64_GRANULE_SHIFT<<2 + ;; + ptr.i r16,r18 + ;; + srlz.i + ;; + + // purge TR entry for stack + mov r16=IA64_KR(CURRENT_STACK) + ;; + shl r16=r16,IA64_GRANULE_SHIFT + movl r19=PAGE_OFFSET + ;; + add r16=r19,r16 + mov r18=IA64_GRANULE_SHIFT<<2 + ;; + ptr.d r16,r18 + ;; + srlz.i + ;; + + //copy segments + movl r16=PAGE_MASK + mov r30=in0 // in0 is page_list + br.sptk.few .dest_page + ;; +.loop: + ld8 r30=[in0], 8;; +.dest_page: + tbit.z p0, p6=r30, 0;; // 0x1 dest page +(p6) and r17=r30, r16 +(p6) br.cond.sptk.few .loop;; + + tbit.z p0, p6=r30, 1;; // 0x2 indirect page +(p6) and in0=r30, r16 +(p6) br.cond.sptk.few .loop;; + + tbit.z p0, p6=r30, 2;; // 0x4 end flag +(p6) br.cond.sptk.few .end_loop;; + + tbit.z p6, p0=r30, 3;; // 0x8 source page +(p6) br.cond.sptk.few .loop + + and r18=r30, r16 + + // simple copy page, may optimize later + movl r14=PAGE_SIZE/8 - 1;; + mov ar.lc=r14;; +1: + ld8 r14=[r18], 8;; + st8 [r17]=r14;; + fc.i r17 + add r17=8, r17 + br.ctop.sptk.few 1b + br.sptk.few .loop + ;; + +.end_loop: + sync.i // for fc.i + ;; + srlz.i + ;; + srlz.d + ;; + br.call.sptk.many b0=b6;; + +.align 32 +memory_stack: + .fill 8192, 1, 0 +memory_stack_end: +register_stack: + .fill 8192, 1, 0 +register_stack_end: +relocate_new_kernel_end: +END(relocate_new_kernel) + +.global relocate_new_kernel_size +relocate_new_kernel_size: + data8 relocate_new_kernel_end - relocate_new_kernel + +GLOBAL_ENTRY(ia64_dump_cpu_regs) + .prologue + alloc loc0=ar.pfs,1,2,0,0 + .body + mov ar.rsc=0 // put RSE in enforced lazy mode + add loc1=4*8, in0 // save r4 and r5 first + ;; +{ + flushrs // flush dirty regs to backing store + srlz.i +} + st8 [loc1]=r4, 8 + ;; + st8 [loc1]=r5, 8 + ;; + add loc1=32*8, in0 + mov r4=ar.rnat + ;; + st8 [in0]=r0, 8 // r0 + st8 [loc1]=r4, 8 // rnat + mov r5=pr + ;; + st8 [in0]=r1, 8 // r1 + st8 [loc1]=r5, 8 // pr + mov r4=b0 + ;; + st8 [in0]=r2, 8 // r2 + st8 [loc1]=r4, 8 // b0 + mov r5=b1; + ;; + st8 [in0]=r3, 24 // r3 + st8 [loc1]=r5, 8 // b1 + mov r4=b2 + ;; + st8 [in0]=r6, 8 // r6 + st8 [loc1]=r4, 8 // b2 + mov r5=b3 + ;; + st8 [in0]=r7, 8 // r7 + st8 [loc1]=r5, 8 // b3 + mov r4=b4 + ;; + st8 [in0]=r8, 8 // r8 + st8 [loc1]=r4, 8 // b4 + mov r5=b5 + ;; + st8 [in0]=r9, 8 // r9 + st8 [loc1]=r5, 8 // b5 + mov r4=b6 + ;; + st8 [in0]=r10, 8 // r10 + st8 [loc1]=r5, 8 // b6 + mov r5=b7 + ;; + st8 [in0]=r11, 8 // r11 + st8 [loc1]=r5, 8 // b7 + mov r4=b0 + ;; + st8 [in0]=r12, 8 // r12 + st8 [loc1]=r4, 8 // ip + mov r5=loc0 + ;; + st8 [in0]=r13, 8 // r13 + extr.u r5=r5, 0, 38 // ar.pfs.pfm + mov r4=r0 // user mask + ;; + st8 [in0]=r14, 8 // r14 + st8 [loc1]=r5, 8 // cfm + ;; + st8 [in0]=r15, 8 // r15 + st8 [loc1]=r4, 8 // user mask + mov r5=ar.rsc + ;; + st8 [in0]=r16, 8 // r16 + st8 [loc1]=r5, 8 // ar.rsc + mov r4=ar.bsp + ;; + st8 [in0]=r17, 8 // r17 + st8 [loc1]=r4, 8 // ar.bsp + mov r5=ar.bspstore + ;; + st8 [in0]=r18, 8 // r18 + st8 [loc1]=r5, 8 // ar.bspstore + mov r4=ar.rnat + ;; + st8 [in0]=r19, 8 // r19 + st8 [loc1]=r4, 8 // ar.rnat + mov r5=ar.ccv + ;; + st8 [in0]=r20, 8 // r20 + st8 [loc1]=r5, 8 // ar.ccv + mov r4=ar.unat + ;; + st8 [in0]=r21, 8 // r21 + st8 [loc1]=r4, 8 // ar.unat + mov r5 = ar.fpsr + ;; + st8 [in0]=r22, 8 // r22 + st8 [loc1]=r5, 8 // ar.fpsr + mov r4 = ar.unat + ;; + st8 [in0]=r23, 8 // r23 + st8 [loc1]=r4, 8 // unat + mov r5 = ar.fpsr + ;; + st8 [in0]=r24, 8 // r24 + st8 [loc1]=r5, 8 // fpsr + mov r4 = ar.pfs + ;; + st8 [in0]=r25, 8 // r25 + st8 [loc1]=r4, 8 // ar.pfs + mov r5 = ar.lc + ;; + st8 [in0]=r26, 8 // r26 + st8 [loc1]=r5, 8 // ar.lc + mov r4 = ar.ec + ;; + st8 [in0]=r27, 8 // r27 + st8 [loc1]=r4, 8 // ar.ec + mov r5 = ar.csd + ;; + st8 [in0]=r28, 8 // r28 + st8 [loc1]=r5, 8 // ar.csd + mov r4 = ar.ssd + ;; + st8 [in0]=r29, 8 // r29 + st8 [loc1]=r4, 8 // ar.ssd + ;; + st8 [in0]=r30, 8 // r30 + ;; + st8 [in0]=r31, 8 // r31 + mov ar.pfs=loc0 + ;; + br.ret.sptk.many rp +END(ia64_dump_cpu_regs) + + diff --git a/trunk/arch/ia64/kernel/salinfo.c b/trunk/arch/ia64/kernel/salinfo.c index e63b8ca5344a..e375a2f0f2c3 100644 --- a/trunk/arch/ia64/kernel/salinfo.c +++ b/trunk/arch/ia64/kernel/salinfo.c @@ -302,7 +302,7 @@ salinfo_event_open(struct inode *inode, struct file *file) static ssize_t salinfo_event_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) { - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; struct proc_dir_entry *entry = PDE(inode); struct salinfo_data *data = entry->data; char cmd[32]; @@ -464,7 +464,7 @@ salinfo_log_new_read(int cpu, struct salinfo_data *data) static ssize_t salinfo_log_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) { - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; struct proc_dir_entry *entry = PDE(inode); struct salinfo_data *data = entry->data; u8 *buf; @@ -525,7 +525,7 @@ salinfo_log_clear(struct salinfo_data *data, int cpu) static ssize_t salinfo_log_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) { - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; struct proc_dir_entry *entry = PDE(inode); struct salinfo_data *data = entry->data; char cmd[32]; @@ -575,7 +575,6 @@ static struct file_operations salinfo_data_fops = { .write = salinfo_log_write, }; -#ifdef CONFIG_HOTPLUG_CPU static int __devinit salinfo_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu) { @@ -620,7 +619,6 @@ static struct notifier_block salinfo_cpu_notifier = .notifier_call = salinfo_cpu_callback, .priority = 0, }; -#endif /* CONFIG_HOTPLUG_CPU */ static int __init salinfo_init(void) diff --git a/trunk/arch/ia64/kernel/setup.c b/trunk/arch/ia64/kernel/setup.c index d10404a41756..14e1200376a9 100644 --- a/trunk/arch/ia64/kernel/setup.c +++ b/trunk/arch/ia64/kernel/setup.c @@ -43,6 +43,8 @@ #include #include #include +#include +#include #include #include @@ -252,6 +254,41 @@ reserve_memory (void) efi_memmap_init(&rsvd_region[n].start, &rsvd_region[n].end); n++; +#ifdef CONFIG_KEXEC + /* crashkernel=size@offset specifies the size to reserve for a crash + * kernel.(offset is ingored for keep compatibility with other archs) + * By reserving this memory we guarantee that linux never set's it + * up as a DMA target.Useful for holding code to do something + * appropriate after a kernel panic. + */ + { + char *from = strstr(saved_command_line, "crashkernel="); + unsigned long base, size; + if (from) { + size = memparse(from + 12, &from); + if (size) { + sort_regions(rsvd_region, n); + base = kdump_find_rsvd_region(size, + rsvd_region, n); + if (base != ~0UL) { + rsvd_region[n].start = + (unsigned long)__va(base); + rsvd_region[n].end = + (unsigned long)__va(base + size); + n++; + crashk_res.start = base; + crashk_res.end = base + size - 1; + } + } + } + efi_memmap_res.start = ia64_boot_param->efi_memmap; + efi_memmap_res.end = efi_memmap_res.start + + ia64_boot_param->efi_memmap_size; + boot_param_res.start = __pa(ia64_boot_param); + boot_param_res.end = boot_param_res.start + + sizeof(*ia64_boot_param); + } +#endif /* end of memory marker */ rsvd_region[n].start = ~0UL; rsvd_region[n].end = ~0UL; @@ -263,6 +300,7 @@ reserve_memory (void) sort_regions(rsvd_region, num_rsvd_regions); } + /** * find_initrd - get initrd parameters from the boot parameter structure * diff --git a/trunk/arch/ia64/kernel/smp.c b/trunk/arch/ia64/kernel/smp.c index 6ab95ceaf9d4..b1b9aa4364b9 100644 --- a/trunk/arch/ia64/kernel/smp.c +++ b/trunk/arch/ia64/kernel/smp.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -66,6 +67,7 @@ static volatile struct call_data_struct *call_data; #define IPI_CALL_FUNC 0 #define IPI_CPU_STOP 1 +#define IPI_KDUMP_CPU_STOP 3 /* This needs to be cacheline aligned because it is written to by *other* CPUs. */ static DEFINE_PER_CPU(u64, ipi_operation) ____cacheline_aligned; @@ -155,7 +157,11 @@ handle_IPI (int irq, void *dev_id) case IPI_CPU_STOP: stop_this_cpu(); break; - +#ifdef CONFIG_CRASH_DUMP + case IPI_KDUMP_CPU_STOP: + unw_init_running(kdump_cpu_freeze, NULL); + break; +#endif default: printk(KERN_CRIT "Unknown IPI on CPU %d: %lu\n", this_cpu, which); break; @@ -213,6 +219,26 @@ send_IPI_self (int op) send_IPI_single(smp_processor_id(), op); } +#ifdef CONFIG_CRASH_DUMP +void +kdump_smp_send_stop() +{ + send_IPI_allbutself(IPI_KDUMP_CPU_STOP); +} + +void +kdump_smp_send_init() +{ + unsigned int cpu, self_cpu; + self_cpu = smp_processor_id(); + for_each_online_cpu(cpu) { + if (cpu != self_cpu) { + if(kdump_status[cpu] == 0) + platform_send_ipi(cpu, 0, IA64_IPI_DM_INIT, 0); + } + } +} +#endif /* * Called with preeemption disabled. */ diff --git a/trunk/arch/ia64/kernel/smpboot.c b/trunk/arch/ia64/kernel/smpboot.c index f7d7f5668144..b21ddecea943 100644 --- a/trunk/arch/ia64/kernel/smpboot.c +++ b/trunk/arch/ia64/kernel/smpboot.c @@ -463,15 +463,17 @@ struct pt_regs * __devinit idle_regs(struct pt_regs *regs) } struct create_idle { + struct work_struct work; struct task_struct *idle; struct completion done; int cpu; }; void -do_fork_idle(void *_c_idle) +do_fork_idle(struct work_struct *work) { - struct create_idle *c_idle = _c_idle; + struct create_idle *c_idle = + container_of(work, struct create_idle, work); c_idle->idle = fork_idle(c_idle->cpu); complete(&c_idle->done); @@ -482,10 +484,10 @@ do_boot_cpu (int sapicid, int cpu) { int timeout; struct create_idle c_idle = { + .work = __WORK_INITIALIZER(c_idle.work, do_fork_idle), .cpu = cpu, .done = COMPLETION_INITIALIZER(c_idle.done), }; - DECLARE_WORK(work, do_fork_idle, &c_idle); c_idle.idle = get_idle_for_cpu(cpu); if (c_idle.idle) { @@ -497,9 +499,9 @@ do_boot_cpu (int sapicid, int cpu) * We can't use kernel_thread since we must avoid to reschedule the child. */ if (!keventd_up() || current_is_keventd()) - work.func(work.data); + c_idle.work.func(&c_idle.work); else { - schedule_work(&work); + schedule_work(&c_idle.work); wait_for_completion(&c_idle.done); } diff --git a/trunk/arch/ia64/kernel/topology.c b/trunk/arch/ia64/kernel/topology.c index 5629b45e89c6..687500ddb4b8 100644 --- a/trunk/arch/ia64/kernel/topology.c +++ b/trunk/arch/ia64/kernel/topology.c @@ -31,11 +31,11 @@ int arch_register_cpu(int num) { #if defined (CONFIG_ACPI) && defined (CONFIG_HOTPLUG_CPU) /* - * If CPEI cannot be re-targetted, and this is - * CPEI target, then dont create the control file + * If CPEI can be re-targetted or if this is not + * CPEI target, then it is hotpluggable */ - if (!can_cpei_retarget() && is_cpu_cpei_target(num)) - sysfs_cpus[num].cpu.no_control = 1; + if (can_cpei_retarget() || !is_cpu_cpei_target(num)) + sysfs_cpus[num].cpu.hotpluggable = 1; map_cpu_to_node(num, node_cpuid[num].nid); #endif diff --git a/trunk/arch/ia64/lib/ip_fast_csum.S b/trunk/arch/ia64/lib/ip_fast_csum.S index 19674ca2acfc..1f86aeb2c948 100644 --- a/trunk/arch/ia64/lib/ip_fast_csum.S +++ b/trunk/arch/ia64/lib/ip_fast_csum.S @@ -8,8 +8,8 @@ * in0: address of buffer to checksum (char *) * in1: length of the buffer (int) * - * Copyright (C) 2002 Intel Corp. - * Copyright (C) 2002 Ken Chen + * Copyright (C) 2002, 2006 Intel Corp. + * Copyright (C) 2002, 2006 Ken Chen */ #include @@ -25,6 +25,9 @@ #define in0 r32 #define in1 r33 +#define in2 r34 +#define in3 r35 +#define in4 r36 #define ret0 r8 GLOBAL_ENTRY(ip_fast_csum) @@ -65,8 +68,9 @@ GLOBAL_ENTRY(ip_fast_csum) zxt2 r20=r20 ;; add r20=ret0,r20 + mov r9=0xffff ;; - andcm ret0=-1,r20 + andcm ret0=r9,r20 .restore sp // reset frame state br.ret.sptk.many b0 ;; @@ -88,3 +92,51 @@ GLOBAL_ENTRY(ip_fast_csum) mov b0=r34 br.ret.sptk.many b0 END(ip_fast_csum) + +GLOBAL_ENTRY(csum_ipv6_magic) + ld4 r20=[in0],4 + ld4 r21=[in1],4 + dep r15=in3,in2,32,16 + ;; + ld4 r22=[in0],4 + ld4 r23=[in1],4 + mux1 r15=r15,@rev + ;; + ld4 r24=[in0],4 + ld4 r25=[in1],4 + shr.u r15=r15,16 + add r16=r20,r21 + add r17=r22,r23 + ;; + ld4 r26=[in0],4 + ld4 r27=[in1],4 + add r18=r24,r25 + add r8=r16,r17 + ;; + add r19=r26,r27 + add r8=r8,r18 + ;; + add r8=r8,r19 + add r15=r15,in4 + ;; + add r8=r8,r15 + ;; + shr.u r10=r8,32 // now fold sum into short + zxt4 r11=r8 + ;; + add r8=r10,r11 + ;; + shr.u r10=r8,16 // yeah, keep it rolling + zxt2 r11=r8 + ;; + add r8=r10,r11 + ;; + shr.u r10=r8,16 // three times lucky + zxt2 r11=r8 + ;; + add r8=r10,r11 + mov r9=0xffff + ;; + andcm r8=r9,r8 + br.ret.sptk.many b0 +END(csum_ipv6_magic) diff --git a/trunk/arch/ia64/mm/hugetlbpage.c b/trunk/arch/ia64/mm/hugetlbpage.c index f3a9585e98a8..0c7e94edc20e 100644 --- a/trunk/arch/ia64/mm/hugetlbpage.c +++ b/trunk/arch/ia64/mm/hugetlbpage.c @@ -64,6 +64,11 @@ huge_pte_offset (struct mm_struct *mm, unsigned long addr) return pte; } +int huge_pmd_unshare(struct mm_struct *mm, unsigned long *addr, pte_t *ptep) +{ + return 0; +} + #define mk_pte_huge(entry) { pte_val(entry) |= _PAGE_P; } /* diff --git a/trunk/arch/ia64/mm/init.c b/trunk/arch/ia64/mm/init.c index ff87a5cba399..56dc2024220e 100644 --- a/trunk/arch/ia64/mm/init.c +++ b/trunk/arch/ia64/mm/init.c @@ -156,7 +156,7 @@ ia64_init_addr_space (void) * the problem. When the process attempts to write to the register backing store * for the first time, it will get a SEGFAULT in this case. */ - vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL); + vma = kmem_cache_alloc(vm_area_cachep, GFP_KERNEL); if (vma) { memset(vma, 0, sizeof(*vma)); vma->vm_mm = current->mm; @@ -175,7 +175,7 @@ ia64_init_addr_space (void) /* map NaT-page at address zero to speed up speculative dereferencing of NULL: */ if (!(current->personality & MMAP_PAGE_ZERO)) { - vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL); + vma = kmem_cache_alloc(vm_area_cachep, GFP_KERNEL); if (vma) { memset(vma, 0, sizeof(*vma)); vma->vm_mm = current->mm; diff --git a/trunk/arch/ia64/pci/pci.c b/trunk/arch/ia64/pci/pci.c index f4edfbf27134..474d179966dc 100644 --- a/trunk/arch/ia64/pci/pci.c +++ b/trunk/arch/ia64/pci/pci.c @@ -125,11 +125,10 @@ alloc_pci_controller (int seg) { struct pci_controller *controller; - controller = kmalloc(sizeof(*controller), GFP_KERNEL); + controller = kzalloc(sizeof(*controller), GFP_KERNEL); if (!controller) return NULL; - memset(controller, 0, sizeof(*controller)); controller->segment = seg; controller->node = -1; return controller; @@ -564,8 +563,8 @@ pcibios_enable_device (struct pci_dev *dev, int mask) void pcibios_disable_device (struct pci_dev *dev) { - if (dev->is_enabled) - acpi_pci_irq_disable(dev); + BUG_ON(atomic_read(&dev->enable_cnt)); + acpi_pci_irq_disable(dev); } void diff --git a/trunk/arch/ia64/sn/kernel/irq.c b/trunk/arch/ia64/sn/kernel/irq.c index 0b49459a878a..8c5bee01eaa2 100644 --- a/trunk/arch/ia64/sn/kernel/irq.c +++ b/trunk/arch/ia64/sn/kernel/irq.c @@ -117,7 +117,10 @@ struct sn_irq_info *sn_retarget_vector(struct sn_irq_info *sn_irq_info, nasid_t nasid, int slice) { int vector; + int cpuid; +#ifdef CONFIG_SMP int cpuphys; +#endif int64_t bridge; int local_widget, status; nasid_t local_nasid; @@ -146,7 +149,6 @@ struct sn_irq_info *sn_retarget_vector(struct sn_irq_info *sn_irq_info, vector = sn_irq_info->irq_irq; /* Free the old PROM new_irq_info structure */ sn_intr_free(local_nasid, local_widget, new_irq_info); - /* Update kernels new_irq_info with new target info */ unregister_intr_pda(new_irq_info); /* allocate a new PROM new_irq_info struct */ @@ -160,8 +162,10 @@ struct sn_irq_info *sn_retarget_vector(struct sn_irq_info *sn_irq_info, return NULL; } - cpuphys = nasid_slice_to_cpuid(nasid, slice); - new_irq_info->irq_cpuid = cpuphys; + /* Update kernels new_irq_info with new target info */ + cpuid = nasid_slice_to_cpuid(new_irq_info->irq_nasid, + new_irq_info->irq_slice); + new_irq_info->irq_cpuid = cpuid; register_intr_pda(new_irq_info); pci_provider = sn_pci_provider[new_irq_info->irq_bridge_type]; @@ -180,6 +184,7 @@ struct sn_irq_info *sn_retarget_vector(struct sn_irq_info *sn_irq_info, call_rcu(&sn_irq_info->rcu, sn_irq_info_free); #ifdef CONFIG_SMP + cpuphys = cpu_physical_id(cpuid); set_irq_affinity_info((vector & 0xff), cpuphys, 0); #endif @@ -299,6 +304,9 @@ void sn_irq_fixup(struct pci_dev *pci_dev, struct sn_irq_info *sn_irq_info) nasid_t nasid = sn_irq_info->irq_nasid; int slice = sn_irq_info->irq_slice; int cpu = nasid_slice_to_cpuid(nasid, slice); +#ifdef CONFIG_SMP + int cpuphys; +#endif pci_dev_get(pci_dev); sn_irq_info->irq_cpuid = cpu; @@ -311,6 +319,10 @@ void sn_irq_fixup(struct pci_dev *pci_dev, struct sn_irq_info *sn_irq_info) spin_unlock(&sn_irq_info_lock); register_intr_pda(sn_irq_info); +#ifdef CONFIG_SMP + cpuphys = cpu_physical_id(cpu); + set_irq_affinity_info(sn_irq_info->irq_irq, cpuphys, 0); +#endif } void sn_irq_unfixup(struct pci_dev *pci_dev) diff --git a/trunk/arch/ia64/sn/kernel/msi_sn.c b/trunk/arch/ia64/sn/kernel/msi_sn.c index 6ffd1f850d41..b3a435fd70fb 100644 --- a/trunk/arch/ia64/sn/kernel/msi_sn.c +++ b/trunk/arch/ia64/sn/kernel/msi_sn.c @@ -136,10 +136,6 @@ int sn_setup_msi_irq(unsigned int irq, struct pci_dev *pdev) */ msg.data = 0x100 + irq; -#ifdef CONFIG_SMP - set_irq_affinity_info(irq, sn_irq_info->irq_cpuid, 0); -#endif - write_msi_msg(irq, &msg); set_irq_chip_and_handler(irq, &sn_msi_chip, handle_edge_irq); diff --git a/trunk/arch/ia64/sn/kernel/setup.c b/trunk/arch/ia64/sn/kernel/setup.c index 1d009f93244d..a934ad069425 100644 --- a/trunk/arch/ia64/sn/kernel/setup.c +++ b/trunk/arch/ia64/sn/kernel/setup.c @@ -769,5 +769,13 @@ int sn_prom_feature_available(int id) return 0; return test_bit(id, sn_prom_features); } + +void +sn_kernel_launch_event(void) +{ + /* ignore status until we understand possible failure, if any*/ + if (ia64_sn_kernel_launch_event()) + printk(KERN_ERR "KEXEC is not supported in this PROM, Please update the PROM.\n"); +} EXPORT_SYMBOL(sn_prom_feature_available); diff --git a/trunk/arch/m32r/Kconfig b/trunk/arch/m32r/Kconfig index 41fd490af3b4..f383dab973f5 100644 --- a/trunk/arch/m32r/Kconfig +++ b/trunk/arch/m32r/Kconfig @@ -214,6 +214,14 @@ config RWSEM_XCHGADD_ALGORITHM bool default n +config ARCH_HAS_ILOG2_U32 + bool + default n + +config ARCH_HAS_ILOG2_U64 + bool + default n + config GENERIC_FIND_NEXT_BIT bool default y diff --git a/trunk/arch/m32r/boot/compressed/m32r_sio.c b/trunk/arch/m32r/boot/compressed/m32r_sio.c index bce8af5e3bb2..ee3c8be12fa0 100644 --- a/trunk/arch/m32r/boot/compressed/m32r_sio.c +++ b/trunk/arch/m32r/boot/compressed/m32r_sio.c @@ -2,6 +2,7 @@ * arch/m32r/boot/compressed/m32r_sio.c * * 2003-02-12: Takeo Takahashi + * 2006-11-30: OPSPUT support by Kazuhiro Inaoka * */ @@ -16,7 +17,7 @@ static int puts(const char *s) return 0; } -#if defined(CONFIG_PLAT_M32700UT_Alpha) || defined(CONFIG_PLAT_M32700UT) +#if defined(CONFIG_PLAT_M32700UT_Alpha) || defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_OPSPUT) #include #include @@ -31,7 +32,11 @@ static int puts(const char *s) #define BOOT_SIO0TXB (volatile unsigned short *)(0x02c00000 + 0x2000c) #else #undef PLD_BASE +#if defined(CONFIG_PLAT_OPSPUT) +#define PLD_BASE 0x1cc00000 +#else #define PLD_BASE 0xa4c00000 +#endif #define BOOT_SIO0STS PLD_ESIO0STS #define BOOT_SIO0TXB PLD_ESIO0TXB #endif diff --git a/trunk/arch/m32r/kernel/entry.S b/trunk/arch/m32r/kernel/entry.S index ac6d840b382b..a2c472c0549f 100644 --- a/trunk/arch/m32r/kernel/entry.S +++ b/trunk/arch/m32r/kernel/entry.S @@ -23,35 +23,35 @@ * updated in fork.c:copy_thread, signal.c:do_signal, * ptrace.c and ptrace.h * - * M32Rx/M32R2 M32R - * @(sp) - r4 ditto - * @(0x04,sp) - r5 ditto - * @(0x08,sp) - r6 ditto - * @(0x0c,sp) - *pt_regs ditto - * @(0x10,sp) - r0 ditto - * @(0x14,sp) - r1 ditto - * @(0x18,sp) - r2 ditto - * @(0x1c,sp) - r3 ditto - * @(0x20,sp) - r7 ditto - * @(0x24,sp) - r8 ditto - * @(0x28,sp) - r9 ditto - * @(0x2c,sp) - r10 ditto - * @(0x30,sp) - r11 ditto - * @(0x34,sp) - r12 ditto - * @(0x38,sp) - syscall_nr ditto - * @(0x3c,sp) - acc0h @(0x3c,sp) - acch - * @(0x40,sp) - acc0l @(0x40,sp) - accl - * @(0x44,sp) - acc1h @(0x44,sp) - dummy_acc1h - * @(0x48,sp) - acc1l @(0x48,sp) - dummy_acc1l - * @(0x4c,sp) - psw ditto - * @(0x50,sp) - bpc ditto - * @(0x54,sp) - bbpsw ditto - * @(0x58,sp) - bbpc ditto - * @(0x5c,sp) - spu (cr3) ditto - * @(0x60,sp) - fp (r13) ditto - * @(0x64,sp) - lr (r14) ditto - * @(0x68,sp) - spi (cr2) ditto - * @(0x6c,sp) - orig_r0 ditto + * M32R/M32Rx/M32R2 + * @(sp) - r4 + * @(0x04,sp) - r5 + * @(0x08,sp) - r6 + * @(0x0c,sp) - *pt_regs + * @(0x10,sp) - r0 + * @(0x14,sp) - r1 + * @(0x18,sp) - r2 + * @(0x1c,sp) - r3 + * @(0x20,sp) - r7 + * @(0x24,sp) - r8 + * @(0x28,sp) - r9 + * @(0x2c,sp) - r10 + * @(0x30,sp) - r11 + * @(0x34,sp) - r12 + * @(0x38,sp) - syscall_nr + * @(0x3c,sp) - acc0h + * @(0x40,sp) - acc0l + * @(0x44,sp) - acc1h ; ISA_DSP_LEVEL2 only + * @(0x48,sp) - acc1l ; ISA_DSP_LEVEL2 only + * @(0x4c,sp) - psw + * @(0x50,sp) - bpc + * @(0x54,sp) - bbpsw + * @(0x58,sp) - bbpc + * @(0x5c,sp) - spu (cr3) + * @(0x60,sp) - fp (r13) + * @(0x64,sp) - lr (r14) + * @(0x68,sp) - spi (cr2) + * @(0x6c,sp) - orig_r0 */ #include @@ -95,17 +95,10 @@ #define R11(reg) @(0x30,reg) #define R12(reg) @(0x34,reg) #define SYSCALL_NR(reg) @(0x38,reg) -#if defined(CONFIG_ISA_M32R2) && defined(CONFIG_ISA_DSP_LEVEL2) #define ACC0H(reg) @(0x3C,reg) #define ACC0L(reg) @(0x40,reg) #define ACC1H(reg) @(0x44,reg) #define ACC1L(reg) @(0x48,reg) -#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R) -#define ACCH(reg) @(0x3C,reg) -#define ACCL(reg) @(0x40,reg) -#else -#error unknown isa configuration -#endif #define PSW(reg) @(0x4C,reg) #define BPC(reg) @(0x50,reg) #define BBPSW(reg) @(0x54,reg) @@ -603,8 +596,6 @@ ENTRY(ace_handler) beqz r1, inst oprand: ld r2, @(low(MDEVA_offset),r2) ; set address - srli r2, #12 - slli r2, #12 srli r1, #1 bra 1f inst: diff --git a/trunk/arch/m32r/kernel/io_opsput.c b/trunk/arch/m32r/kernel/io_opsput.c index da6c5f5c1f82..3cbb1f717e50 100644 --- a/trunk/arch/m32r/kernel/io_opsput.c +++ b/trunk/arch/m32r/kernel/io_opsput.c @@ -30,14 +30,34 @@ extern void pcc_iowrite_byte(int, unsigned long, void *, size_t, size_t, int); extern void pcc_iowrite_word(int, unsigned long, void *, size_t, size_t, int); #endif /* CONFIG_PCMCIA && CONFIG_M32R_CFC */ -#define PORT2ADDR(port) _port2addr(port) -#define PORT2ADDR_USB(port) _port2addr_usb(port) +#define PORT2ADDR(port) _port2addr(port) +#define PORT2ADDR_USB(port) _port2addr_usb(port) static inline void *_port2addr(unsigned long port) { return (void *)(port | NONCACHE_OFFSET); } +#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC) +static inline void *__port2addr_ata(unsigned long port) +{ + static int dummy_reg; + + switch (port) { + case 0x1f0: return (void *)(0x0c002000 | NONCACHE_OFFSET); + case 0x1f1: return (void *)(0x0c012800 | NONCACHE_OFFSET); + case 0x1f2: return (void *)(0x0c012002 | NONCACHE_OFFSET); + case 0x1f3: return (void *)(0x0c012802 | NONCACHE_OFFSET); + case 0x1f4: return (void *)(0x0c012004 | NONCACHE_OFFSET); + case 0x1f5: return (void *)(0x0c012804 | NONCACHE_OFFSET); + case 0x1f6: return (void *)(0x0c012006 | NONCACHE_OFFSET); + case 0x1f7: return (void *)(0x0c012806 | NONCACHE_OFFSET); + case 0x3f6: return (void *)(0x0c01200e | NONCACHE_OFFSET); + default: return (void *)&dummy_reg; + } +} +#endif + /* * OPSPUT-LAN is located in the extended bus space * from 0x10000000 to 0x13ffffff on physical address. @@ -97,6 +117,12 @@ unsigned char _inb(unsigned long port) { if (port >= LAN_IOSTART && port < LAN_IOEND) return _ne_inb(PORT2ADDR_NE(port)); + +#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC) + else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) { + return *(volatile unsigned char *)__port2addr_ata(port); + } +#endif #if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC) else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { unsigned char b; @@ -112,6 +138,11 @@ unsigned short _inw(unsigned long port) { if (port >= LAN_IOSTART && port < LAN_IOEND) return _ne_inw(PORT2ADDR_NE(port)); +#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC) + else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) { + return *(volatile unsigned short *)__port2addr_ata(port); + } +#endif #if defined(CONFIG_USB) else if(port >= 0x340 && port < 0x3a0) return *(volatile unsigned short *)PORT2ADDR_USB(port); @@ -164,6 +195,11 @@ void _outb(unsigned char b, unsigned long port) if (port >= LAN_IOSTART && port < LAN_IOEND) _ne_outb(b, PORT2ADDR_NE(port)); else +#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC) + if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) { + *(volatile unsigned char *)__port2addr_ata(port) = b; + } else +#endif #if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC) if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { pcc_iowrite_byte(0, port, &b, sizeof(b), 1, 0); @@ -177,6 +213,11 @@ void _outw(unsigned short w, unsigned long port) if (port >= LAN_IOSTART && port < LAN_IOEND) _ne_outw(w, PORT2ADDR_NE(port)); else +#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC) + if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) { + *(volatile unsigned short *)__port2addr_ata(port) = w; + } else +#endif #if defined(CONFIG_USB) if(port >= 0x340 && port < 0x3a0) *(volatile unsigned short *)PORT2ADDR_USB(port) = w; @@ -222,6 +263,14 @@ void _insb(unsigned int port, void *addr, unsigned long count) { if (port >= LAN_IOSTART && port < LAN_IOEND) _ne_insb(PORT2ADDR_NE(port), addr, count); +#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC) + else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) { + unsigned char *buf = addr; + unsigned char *portp = __port2addr_ata(port); + while (count--) + *buf++ = *(volatile unsigned char *)portp; + } +#endif #if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC) else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { pcc_ioread_byte(0, port, (void *)addr, sizeof(unsigned char), @@ -253,6 +302,12 @@ void _insw(unsigned int port, void *addr, unsigned long count) } else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { pcc_ioread_word(9, port, (void *)addr, sizeof(unsigned short), count, 1); +#endif +#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC) + } else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) { + portp = __port2addr_ata(port); + while (count--) + *buf++ = *(volatile unsigned short *)portp; #endif } else { portp = PORT2ADDR(port); @@ -280,6 +335,12 @@ void _outsb(unsigned int port, const void *addr, unsigned long count) portp = PORT2ADDR_NE(port); while (count--) _ne_outb(*buf++, portp); +#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC) + } else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) { + portp = __port2addr_ata(port); + while (count--) + *(volatile unsigned char *)portp = *buf++; +#endif #if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC) } else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { pcc_iowrite_byte(0, port, (void *)addr, sizeof(unsigned char), @@ -305,6 +366,12 @@ void _outsw(unsigned int port, const void *addr, unsigned long count) portp = PORT2ADDR_NE(port); while (count--) *(volatile unsigned short *)portp = *buf++; +#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC) + } else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) { + portp = __port2addr_ata(port); + while (count--) + *(volatile unsigned short *)portp = *buf++; +#endif #if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC) } else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { pcc_iowrite_word(9, port, (void *)addr, sizeof(unsigned short), diff --git a/trunk/arch/m32r/kernel/setup.c b/trunk/arch/m32r/kernel/setup.c index 0e7778be33cc..936205f7aba0 100644 --- a/trunk/arch/m32r/kernel/setup.c +++ b/trunk/arch/m32r/kernel/setup.c @@ -196,9 +196,7 @@ static unsigned long __init setup_memory(void) if (LOADER_TYPE && INITRD_START) { if (INITRD_START + INITRD_SIZE <= (max_low_pfn << PAGE_SHIFT)) { reserve_bootmem(INITRD_START, INITRD_SIZE); - initrd_start = INITRD_START ? - INITRD_START + PAGE_OFFSET : 0; - + initrd_start = INITRD_START + PAGE_OFFSET; initrd_end = initrd_start + INITRD_SIZE; printk("initrd:start[%08lx],size[%08lx]\n", initrd_start, INITRD_SIZE); diff --git a/trunk/arch/m32r/kernel/setup_opsput.c b/trunk/arch/m32r/kernel/setup_opsput.c index 61d3b01cbe07..62d6b71de45f 100644 --- a/trunk/arch/m32r/kernel/setup_opsput.c +++ b/trunk/arch/m32r/kernel/setup_opsput.c @@ -218,13 +218,13 @@ static void shutdown_opsput_lanpld_irq(unsigned int irq) static struct hw_interrupt_type opsput_lanpld_irq_type = { - "OPSPUT-PLD-LAN-IRQ", - startup_opsput_lanpld_irq, - shutdown_opsput_lanpld_irq, - enable_opsput_lanpld_irq, - disable_opsput_lanpld_irq, - mask_and_ack_opsput_lanpld, - end_opsput_lanpld_irq + .typename = "OPSPUT-PLD-LAN-IRQ", + .startup = startup_opsput_lanpld_irq, + .shutdown = shutdown_opsput_lanpld_irq, + .enable = enable_opsput_lanpld_irq, + .disable = disable_opsput_lanpld_irq, + .ack = mask_and_ack_opsput_lanpld, + .end = end_opsput_lanpld_irq }; /* @@ -374,7 +374,6 @@ void __init init_IRQ(void) disable_opsput_pld_irq(PLD_IRQ_SIO0_SND); #endif /* CONFIG_SERIAL_M32R_PLDSIO */ -#if defined(CONFIG_M32R_CFC) /* INT#1: CFC IREQ on PLD */ irq_desc[PLD_IRQ_CFIREQ].status = IRQ_DISABLED; irq_desc[PLD_IRQ_CFIREQ].chip = &opsput_pld_irq_type; @@ -398,8 +397,6 @@ void __init init_IRQ(void) irq_desc[PLD_IRQ_CFC_EJECT].depth = 1; /* disable nested irq */ pld_icu_data[irq2pldirq(PLD_IRQ_CFC_EJECT)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD02; /* 'H' edge sense */ disable_opsput_pld_irq(PLD_IRQ_CFC_EJECT); -#endif /* CONFIG_M32R_CFC */ - /* * INT0# is used for LAN, DIO diff --git a/trunk/arch/m32r/kernel/signal.c b/trunk/arch/m32r/kernel/signal.c index b60cea4aebaa..092ea86bb079 100644 --- a/trunk/arch/m32r/kernel/signal.c +++ b/trunk/arch/m32r/kernel/signal.c @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/trunk/arch/m32r/mm/discontig.c b/trunk/arch/m32r/mm/discontig.c index abb34ccd5986..c7efdb0aefc5 100644 --- a/trunk/arch/m32r/mm/discontig.c +++ b/trunk/arch/m32r/mm/discontig.c @@ -105,9 +105,7 @@ unsigned long __init setup_memory(void) if (INITRD_START + INITRD_SIZE <= PFN_PHYS(max_low_pfn)) { reserve_bootmem_node(NODE_DATA(0), INITRD_START, INITRD_SIZE); - initrd_start = INITRD_START ? - INITRD_START + PAGE_OFFSET : 0; - + initrd_start = INITRD_START + PAGE_OFFSET; initrd_end = initrd_start + INITRD_SIZE; printk("initrd:start[%08lx],size[%08lx]\n", initrd_start, INITRD_SIZE); diff --git a/trunk/arch/m32r/mm/fault.c b/trunk/arch/m32r/mm/fault.c index 8d5f551b5754..9b9feb0f1610 100644 --- a/trunk/arch/m32r/mm/fault.c +++ b/trunk/arch/m32r/mm/fault.c @@ -173,7 +173,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code, goto good_area; if (!(vma->vm_flags & VM_GROWSDOWN)) goto bad_area; -#if 0 + if (error_code & ACE_USERMODE) { /* * accessing the stack below "spu" is always a bug. @@ -184,7 +184,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code, if (address + 4 < regs->spu) goto bad_area; } -#endif + if (expand_stack(vma, address)) goto bad_area; /* diff --git a/trunk/arch/m68k/Kconfig b/trunk/arch/m68k/Kconfig index 7bc14461a6ac..70a577c89c7c 100644 --- a/trunk/arch/m68k/Kconfig +++ b/trunk/arch/m68k/Kconfig @@ -17,6 +17,14 @@ config RWSEM_GENERIC_SPINLOCK config RWSEM_XCHGADD_ALGORITHM bool +config ARCH_HAS_ILOG2_U32 + bool + default n + +config ARCH_HAS_ILOG2_U64 + bool + default n + config GENERIC_HWEIGHT bool default y diff --git a/trunk/arch/m68k/amiga/chipram.c b/trunk/arch/m68k/amiga/chipram.c index de1304c91112..fa015d801617 100644 --- a/trunk/arch/m68k/amiga/chipram.c +++ b/trunk/arch/m68k/amiga/chipram.c @@ -52,10 +52,9 @@ void *amiga_chip_alloc(unsigned long size, const char *name) #ifdef DEBUG printk("amiga_chip_alloc: allocate %ld bytes\n", size); #endif - res = kmalloc(sizeof(struct resource), GFP_KERNEL); + res = kzalloc(sizeof(struct resource), GFP_KERNEL); if (!res) return NULL; - memset(res, 0, sizeof(struct resource)); res->name = name; if (allocate_resource(&chipram_res, res, size, 0, UINT_MAX, PAGE_SIZE, NULL, NULL) < 0) { diff --git a/trunk/arch/m68k/atari/hades-pci.c b/trunk/arch/m68k/atari/hades-pci.c index 6ca57b6564da..bee2b1443e36 100644 --- a/trunk/arch/m68k/atari/hades-pci.c +++ b/trunk/arch/m68k/atari/hades-pci.c @@ -375,10 +375,9 @@ struct pci_bus_info * __init init_hades_pci(void) * Allocate memory for bus info structure. */ - bus = kmalloc(sizeof(struct pci_bus_info), GFP_KERNEL); + bus = kzalloc(sizeof(struct pci_bus_info), GFP_KERNEL); if (!bus) return NULL; - memset(bus, 0, sizeof(struct pci_bus_info)); /* * Claim resources. The m68k has no separate I/O space, both diff --git a/trunk/arch/m68k/mm/fault.c b/trunk/arch/m68k/mm/fault.c index 911f2ce3f53e..2adbeb16e1b8 100644 --- a/trunk/arch/m68k/mm/fault.c +++ b/trunk/arch/m68k/mm/fault.c @@ -99,7 +99,7 @@ int do_page_fault(struct pt_regs *regs, unsigned long address, * If we're in an interrupt or have no user * context, we must not take the fault.. */ - if (in_interrupt() || !mm) + if (in_atomic() || !mm) goto no_context; down_read(&mm->mmap_sem); diff --git a/trunk/arch/m68knommu/Kconfig b/trunk/arch/m68knommu/Kconfig index aa70dde54228..25993c2a8fbb 100644 --- a/trunk/arch/m68knommu/Kconfig +++ b/trunk/arch/m68knommu/Kconfig @@ -25,6 +25,14 @@ config RWSEM_XCHGADD_ALGORITHM bool default n +config ARCH_HAS_ILOG2_U32 + bool + default n + +config ARCH_HAS_ILOG2_U64 + bool + default n + config GENERIC_FIND_NEXT_BIT bool default y diff --git a/trunk/arch/m68knommu/kernel/vmlinux.lds.S b/trunk/arch/m68knommu/kernel/vmlinux.lds.S index 58afa8be604e..2b2a10da64a4 100644 --- a/trunk/arch/m68knommu/kernel/vmlinux.lds.S +++ b/trunk/arch/m68knommu/kernel/vmlinux.lds.S @@ -60,6 +60,7 @@ SECTIONS { #endif .text : { + _text = .; _stext = . ; *(.text) SCHED_TEXT diff --git a/trunk/arch/m68knommu/platform/5307/timers.c b/trunk/arch/m68knommu/platform/5307/timers.c index 24781f009337..e5668af19789 100644 --- a/trunk/arch/m68knommu/platform/5307/timers.c +++ b/trunk/arch/m68knommu/platform/5307/timers.c @@ -3,7 +3,7 @@ /* * timers.c -- generic ColdFire hardware timer support. * - * Copyright (C) 1999-2003, Greg Ungerer (gerg@snapgear.com) + * Copyright (C) 1999-2006, Greg Ungerer (gerg@snapgear.com) */ /***************************************************************************/ @@ -44,6 +44,14 @@ unsigned int mcf_timerlevel = 5; extern void mcf_settimericr(int timer, int level); extern int mcf_timerirqpending(int timer); +#if defined(CONFIG_M532x) +#define __raw_readtrr __raw_readl +#define __raw_writetrr __raw_writel +#else +#define __raw_readtrr __raw_readw +#define __raw_writetrr __raw_writew +#endif + /***************************************************************************/ void coldfire_tick(void) @@ -57,7 +65,7 @@ void coldfire_tick(void) void coldfire_timer_init(irqreturn_t (*handler)(int, void *, struct pt_regs *)) { __raw_writew(MCFTIMER_TMR_DISABLE, TA(MCFTIMER_TMR)); - __raw_writew(((MCF_BUSCLK / 16) / HZ), TA(MCFTIMER_TRR)); + __raw_writetrr(((MCF_BUSCLK / 16) / HZ), TA(MCFTIMER_TRR)); __raw_writew(MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 | MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE, TA(MCFTIMER_TMR)); @@ -76,7 +84,7 @@ unsigned long coldfire_timer_offset(void) unsigned long trr, tcn, offset; tcn = __raw_readw(TA(MCFTIMER_TCN)); - trr = __raw_readw(TA(MCFTIMER_TRR)); + trr = __raw_readtrr(TA(MCFTIMER_TRR)); offset = (tcn * (1000000 / HZ)) / trr; /* Check if we just wrapped the counters and maybe missed a tick */ @@ -120,7 +128,7 @@ void coldfire_profile_init(void) /* Set up TIMER 2 as high speed profile clock */ __raw_writew(MCFTIMER_TMR_DISABLE, PA(MCFTIMER_TMR)); - __raw_writew(((MCF_CLK / 16) / PROFILEHZ), PA(MCFTIMER_TRR)); + __raw_writetrr(((MCF_CLK / 16) / PROFILEHZ), PA(MCFTIMER_TRR)); __raw_writew(MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 | MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE, PA(MCFTIMER_TMR)); diff --git a/trunk/arch/m68knommu/platform/68360/config.c b/trunk/arch/m68knommu/platform/68360/config.c index c5482e3622eb..1b36f6261764 100644 --- a/trunk/arch/m68knommu/platform/68360/config.c +++ b/trunk/arch/m68knommu/platform/68360/config.c @@ -114,7 +114,7 @@ void BSP_gettod (int *yearp, int *monp, int *dayp, { } -int BSP_hwclk(int op, struct hwclk_time *t) +int BSP_hwclk(int op, struct rtc_time *t) { if (!op) { /* read */ diff --git a/trunk/arch/mips/Kconfig b/trunk/arch/mips/Kconfig index 4d64960be035..57af8d8cf46f 100644 --- a/trunk/arch/mips/Kconfig +++ b/trunk/arch/mips/Kconfig @@ -242,6 +242,7 @@ config LASAT select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL select SYS_SUPPORTS_LITTLE_ENDIAN + select GENERIC_HARDIRQS_NO__DO_IRQ config MIPS_ATLAS bool "MIPS Atlas board" @@ -265,6 +266,7 @@ config MIPS_ATLAS select SYS_SUPPORTS_BIG_ENDIAN select SYS_SUPPORTS_LITTLE_ENDIAN select SYS_SUPPORTS_MULTITHREADING if EXPERIMENTAL + select GENERIC_HARDIRQS_NO__DO_IRQ help This enables support for the MIPS Technologies Atlas evaluation board. @@ -419,6 +421,7 @@ config MOMENCO_OCELOT_C select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_64BIT_KERNEL select SYS_SUPPORTS_BIG_ENDIAN + select GENERIC_HARDIRQS_NO__DO_IRQ help The Ocelot is a MIPS-based Single Board Computer (SBC) made by Momentum Computer . @@ -569,6 +572,7 @@ config SGI_IP27 select SYS_SUPPORTS_BIG_ENDIAN select SYS_SUPPORTS_NUMA select SYS_SUPPORTS_SMP + select GENERIC_HARDIRQS_NO__DO_IRQ help This are the SGI Origin 200, Origin 2000 and Onyx 2 Graphics workstations. To compile a Linux kernel that runs on these, say Y @@ -815,6 +819,14 @@ config RWSEM_GENERIC_SPINLOCK config RWSEM_XCHGADD_ALGORITHM bool +config ARCH_HAS_ILOG2_U32 + bool + default n + +config ARCH_HAS_ILOG2_U64 + bool + default n + config GENERIC_FIND_NEXT_BIT bool default y @@ -835,6 +847,10 @@ config SCHED_NO_NO_OMIT_FRAME_POINTER bool default y +config GENERIC_HARDIRQS_NO__DO_IRQ + bool + default n + # # Select some configuration options automatically based on user selections. # @@ -996,6 +1012,7 @@ config SOC_PNX8550 select HW_HAS_PCI select SYS_HAS_CPU_MIPS32_R1 select SYS_SUPPORTS_32BIT_KERNEL + select GENERIC_HARDIRQS_NO__DO_IRQ config SWAP_IO_SPACE bool diff --git a/trunk/arch/mips/dec/ecc-berr.c b/trunk/arch/mips/dec/ecc-berr.c index c8430c07355e..6d55e8aab668 100644 --- a/trunk/arch/mips/dec/ecc-berr.c +++ b/trunk/arch/mips/dec/ecc-berr.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include diff --git a/trunk/arch/mips/dec/ioasic-irq.c b/trunk/arch/mips/dec/ioasic-irq.c index 269b22b34313..4c7cb4048d35 100644 --- a/trunk/arch/mips/dec/ioasic-irq.c +++ b/trunk/arch/mips/dec/ioasic-irq.c @@ -67,7 +67,6 @@ static struct irq_chip ioasic_irq_type = { .mask = mask_ioasic_irq, .mask_ack = ack_ioasic_irq, .unmask = unmask_ioasic_irq, - .end = end_ioasic_irq, }; @@ -106,8 +105,7 @@ void __init init_ioasic_irqs(int base) set_irq_chip_and_handler(i, &ioasic_irq_type, handle_level_irq); for (; i < base + IO_IRQ_LINES; i++) - set_irq_chip_and_handler(i, &ioasic_dma_irq_type, - handle_level_irq); + set_irq_chip(i, &ioasic_dma_irq_type); ioasic_irq_base = base; } diff --git a/trunk/arch/mips/dec/kn01-berr.c b/trunk/arch/mips/dec/kn01-berr.c index f19b4617a0a6..d3b8002bf1e7 100644 --- a/trunk/arch/mips/dec/kn01-berr.c +++ b/trunk/arch/mips/dec/kn01-berr.c @@ -20,8 +20,10 @@ #include #include +#include #include #include +#include #include #include #include diff --git a/trunk/arch/mips/dec/kn02-irq.c b/trunk/arch/mips/dec/kn02-irq.c index 5a9be4c93584..916e46b8ccd8 100644 --- a/trunk/arch/mips/dec/kn02-irq.c +++ b/trunk/arch/mips/dec/kn02-irq.c @@ -57,19 +57,12 @@ static void ack_kn02_irq(unsigned int irq) iob(); } -static void end_kn02_irq(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) - unmask_kn02_irq(irq); -} - static struct irq_chip kn02_irq_type = { .typename = "KN02-CSR", .ack = ack_kn02_irq, .mask = mask_kn02_irq, .mask_ack = ack_kn02_irq, .unmask = unmask_kn02_irq, - .end = end_kn02_irq, }; diff --git a/trunk/arch/mips/emma2rh/common/irq_emma2rh.c b/trunk/arch/mips/emma2rh/common/irq_emma2rh.c index 59b98299c896..8d880f0b06ec 100644 --- a/trunk/arch/mips/emma2rh/common/irq_emma2rh.c +++ b/trunk/arch/mips/emma2rh/common/irq_emma2rh.c @@ -56,19 +56,12 @@ static void emma2rh_irq_disable(unsigned int irq) ll_emma2rh_irq_disable(irq - emma2rh_irq_base); } -static void emma2rh_irq_end(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) - ll_emma2rh_irq_enable(irq - emma2rh_irq_base); -} - struct irq_chip emma2rh_irq_controller = { .typename = "emma2rh_irq", .ack = emma2rh_irq_disable, .mask = emma2rh_irq_disable, .mask_ack = emma2rh_irq_disable, .unmask = emma2rh_irq_enable, - .end = emma2rh_irq_end, }; void emma2rh_irq_init(u32 irq_base) diff --git a/trunk/arch/mips/emma2rh/markeins/irq_markeins.c b/trunk/arch/mips/emma2rh/markeins/irq_markeins.c index 3ac4e405ecdc..2116d9be5fa9 100644 --- a/trunk/arch/mips/emma2rh/markeins/irq_markeins.c +++ b/trunk/arch/mips/emma2rh/markeins/irq_markeins.c @@ -48,19 +48,12 @@ static void emma2rh_sw_irq_disable(unsigned int irq) ll_emma2rh_sw_irq_disable(irq - emma2rh_sw_irq_base); } -static void emma2rh_sw_irq_end(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) - ll_emma2rh_sw_irq_enable(irq - emma2rh_sw_irq_base); -} - struct irq_chip emma2rh_sw_irq_controller = { .typename = "emma2rh_sw_irq", .ack = emma2rh_sw_irq_disable, .mask = emma2rh_sw_irq_disable, .mask_ack = emma2rh_sw_irq_disable, .unmask = emma2rh_sw_irq_enable, - .end = emma2rh_sw_irq_end, }; void emma2rh_sw_irq_init(u32 irq_base) diff --git a/trunk/arch/mips/jazz/irq.c b/trunk/arch/mips/jazz/irq.c index 5c4f50cdf157..f8d417b5c2bb 100644 --- a/trunk/arch/mips/jazz/irq.c +++ b/trunk/arch/mips/jazz/irq.c @@ -39,19 +39,12 @@ void disable_r4030_irq(unsigned int irq) spin_unlock_irqrestore(&r4030_lock, flags); } -static void end_r4030_irq(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) - enable_r4030_irq(irq); -} - static struct irq_chip r4030_irq_type = { .typename = "R4030", .ack = disable_r4030_irq, .mask = disable_r4030_irq, .mask_ack = disable_r4030_irq, .unmask = enable_r4030_irq, - .end = end_r4030_irq, }; void __init init_r4030_ints(void) diff --git a/trunk/arch/mips/kernel/binfmt_elfn32.c b/trunk/arch/mips/kernel/binfmt_elfn32.c index 4a9f1ecefaf2..9b34238d41c0 100644 --- a/trunk/arch/mips/kernel/binfmt_elfn32.c +++ b/trunk/arch/mips/kernel/binfmt_elfn32.c @@ -90,7 +90,6 @@ struct elf_prpsinfo32 char pr_psargs[ELF_PRARGSZ]; /* initial part of arg list */ }; -#define elf_addr_t u32 #define elf_caddr_t u32 #define init_elf_binfmt init_elfn32_binfmt diff --git a/trunk/arch/mips/kernel/binfmt_elfo32.c b/trunk/arch/mips/kernel/binfmt_elfo32.c index e31813779895..993f7ec70f35 100644 --- a/trunk/arch/mips/kernel/binfmt_elfo32.c +++ b/trunk/arch/mips/kernel/binfmt_elfo32.c @@ -92,7 +92,6 @@ struct elf_prpsinfo32 char pr_psargs[ELF_PRARGSZ]; /* initial part of arg list */ }; -#define elf_addr_t u32 #define elf_caddr_t u32 #define init_elf_binfmt init_elf32_binfmt diff --git a/trunk/arch/mips/kernel/i8259.c b/trunk/arch/mips/kernel/i8259.c index 2526c0ca4d81..b59a676c6d0e 100644 --- a/trunk/arch/mips/kernel/i8259.c +++ b/trunk/arch/mips/kernel/i8259.c @@ -19,9 +19,6 @@ #include #include -void enable_8259A_irq(unsigned int irq); -void disable_8259A_irq(unsigned int irq); - /* * This is the 'legacy' 8259A Programmable Interrupt Controller, * present in the majority of PC/AT boxes. @@ -31,23 +28,16 @@ void disable_8259A_irq(unsigned int irq); * moves to arch independent land */ +static int i8259A_auto_eoi; DEFINE_SPINLOCK(i8259A_lock); - -static void end_8259A_irq (unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)) && - irq_desc[irq].action) - enable_8259A_irq(irq); -} - +/* some platforms call this... */ void mask_and_ack_8259A(unsigned int); -static struct irq_chip i8259A_irq_type = { - .typename = "XT-PIC", - .enable = enable_8259A_irq, - .disable = disable_8259A_irq, - .ack = mask_and_ack_8259A, - .end = end_8259A_irq, +static struct irq_chip i8259A_chip = { + .name = "XT-PIC", + .mask = disable_8259A_irq, + .unmask = enable_8259A_irq, + .mask_ack = mask_and_ack_8259A, }; /* @@ -59,8 +49,8 @@ static struct irq_chip i8259A_irq_type = { */ static unsigned int cached_irq_mask = 0xffff; -#define cached_21 (cached_irq_mask) -#define cached_A1 (cached_irq_mask >> 8) +#define cached_master_mask (cached_irq_mask) +#define cached_slave_mask (cached_irq_mask >> 8) void disable_8259A_irq(unsigned int irq) { @@ -70,9 +60,9 @@ void disable_8259A_irq(unsigned int irq) spin_lock_irqsave(&i8259A_lock, flags); cached_irq_mask |= mask; if (irq & 8) - outb(cached_A1,0xA1); + outb(cached_slave_mask, PIC_SLAVE_IMR); else - outb(cached_21,0x21); + outb(cached_master_mask, PIC_MASTER_IMR); spin_unlock_irqrestore(&i8259A_lock, flags); } @@ -84,9 +74,9 @@ void enable_8259A_irq(unsigned int irq) spin_lock_irqsave(&i8259A_lock, flags); cached_irq_mask &= mask; if (irq & 8) - outb(cached_A1,0xA1); + outb(cached_slave_mask, PIC_SLAVE_IMR); else - outb(cached_21,0x21); + outb(cached_master_mask, PIC_MASTER_IMR); spin_unlock_irqrestore(&i8259A_lock, flags); } @@ -98,9 +88,9 @@ int i8259A_irq_pending(unsigned int irq) spin_lock_irqsave(&i8259A_lock, flags); if (irq < 8) - ret = inb(0x20) & mask; + ret = inb(PIC_MASTER_CMD) & mask; else - ret = inb(0xA0) & (mask >> 8); + ret = inb(PIC_SLAVE_CMD) & (mask >> 8); spin_unlock_irqrestore(&i8259A_lock, flags); return ret; @@ -109,7 +99,7 @@ int i8259A_irq_pending(unsigned int irq) void make_8259A_irq(unsigned int irq) { disable_irq_nosync(irq); - set_irq_chip(irq, &i8259A_irq_type); + set_irq_chip_and_handler(irq, &i8259A_chip, handle_level_irq); enable_irq(irq); } @@ -125,14 +115,14 @@ static inline int i8259A_irq_real(unsigned int irq) int irqmask = 1 << irq; if (irq < 8) { - outb(0x0B,0x20); /* ISR register */ - value = inb(0x20) & irqmask; - outb(0x0A,0x20); /* back to the IRR register */ + outb(0x0B,PIC_MASTER_CMD); /* ISR register */ + value = inb(PIC_MASTER_CMD) & irqmask; + outb(0x0A,PIC_MASTER_CMD); /* back to the IRR register */ return value; } - outb(0x0B,0xA0); /* ISR register */ - value = inb(0xA0) & (irqmask >> 8); - outb(0x0A,0xA0); /* back to the IRR register */ + outb(0x0B,PIC_SLAVE_CMD); /* ISR register */ + value = inb(PIC_SLAVE_CMD) & (irqmask >> 8); + outb(0x0A,PIC_SLAVE_CMD); /* back to the IRR register */ return value; } @@ -149,17 +139,19 @@ void mask_and_ack_8259A(unsigned int irq) spin_lock_irqsave(&i8259A_lock, flags); /* - * Lightweight spurious IRQ detection. We do not want to overdo - * spurious IRQ handling - it's usually a sign of hardware problems, so - * we only do the checks we can do without slowing down good hardware - * nnecesserily. + * Lightweight spurious IRQ detection. We do not want + * to overdo spurious IRQ handling - it's usually a sign + * of hardware problems, so we only do the checks we can + * do without slowing down good hardware unnecessarily. * - * Note that IRQ7 and IRQ15 (the two spurious IRQs usually resulting - * rom the 8259A-1|2 PICs) occur even if the IRQ is masked in the 8259A. - * Thus we can check spurious 8259A IRQs without doing the quite slow - * i8259A_irq_real() call for every IRQ. This does not cover 100% of - * spurious interrupts, but should be enough to warn the user that - * there is something bad going on ... + * Note that IRQ7 and IRQ15 (the two spurious IRQs + * usually resulting from the 8259A-1|2 PICs) occur + * even if the IRQ is masked in the 8259A. Thus we + * can check spurious 8259A IRQs without doing the + * quite slow i8259A_irq_real() call for every IRQ. + * This does not cover 100% of spurious interrupts, + * but should be enough to warn the user that there + * is something bad going on ... */ if (cached_irq_mask & irqmask) goto spurious_8259A_irq; @@ -167,14 +159,14 @@ void mask_and_ack_8259A(unsigned int irq) handle_real_irq: if (irq & 8) { - inb(0xA1); /* DUMMY - (do we need this?) */ - outb(cached_A1,0xA1); - outb(0x60+(irq&7),0xA0);/* 'Specific EOI' to slave */ - outb(0x62,0x20); /* 'Specific EOI' to master-IRQ2 */ + inb(PIC_SLAVE_IMR); /* DUMMY - (do we need this?) */ + outb(cached_slave_mask, PIC_SLAVE_IMR); + outb(0x60+(irq&7),PIC_SLAVE_CMD);/* 'Specific EOI' to slave */ + outb(0x60+PIC_CASCADE_IR,PIC_MASTER_CMD); /* 'Specific EOI' to master-IRQ2 */ } else { - inb(0x21); /* DUMMY - (do we need this?) */ - outb(cached_21,0x21); - outb(0x60+irq,0x20); /* 'Specific EOI' to master */ + inb(PIC_MASTER_IMR); /* DUMMY - (do we need this?) */ + outb(cached_master_mask, PIC_MASTER_IMR); + outb(0x60+irq,PIC_MASTER_CMD); /* 'Specific EOI to master */ } #ifdef CONFIG_MIPS_MT_SMTC if (irq_hwmask[irq] & ST0_IM) @@ -195,7 +187,7 @@ void mask_and_ack_8259A(unsigned int irq) goto handle_real_irq; { - static int spurious_irq_mask = 0; + static int spurious_irq_mask; /* * At this point we can be sure the IRQ is spurious, * lets ACK and report it. [once per IRQ] @@ -216,13 +208,25 @@ void mask_and_ack_8259A(unsigned int irq) static int i8259A_resume(struct sys_device *dev) { - init_8259A(0); + init_8259A(i8259A_auto_eoi); + return 0; +} + +static int i8259A_shutdown(struct sys_device *dev) +{ + /* Put the i8259A into a quiescent state that + * the kernel initialization code can get it + * out of. + */ + outb(0xff, PIC_MASTER_IMR); /* mask all of 8259A-1 */ + outb(0xff, PIC_SLAVE_IMR); /* mask all of 8259A-1 */ return 0; } static struct sysdev_class i8259_sysdev_class = { set_kset_name("i8259"), .resume = i8259A_resume, + .shutdown = i8259A_shutdown, }; static struct sys_device device_i8259A = { @@ -244,41 +248,41 @@ void __init init_8259A(int auto_eoi) { unsigned long flags; + i8259A_auto_eoi = auto_eoi; + spin_lock_irqsave(&i8259A_lock, flags); - outb(0xff, 0x21); /* mask all of 8259A-1 */ - outb(0xff, 0xA1); /* mask all of 8259A-2 */ + outb(0xff, PIC_MASTER_IMR); /* mask all of 8259A-1 */ + outb(0xff, PIC_SLAVE_IMR); /* mask all of 8259A-2 */ /* * outb_p - this has to work on a wide range of PC hardware. */ - outb_p(0x11, 0x20); /* ICW1: select 8259A-1 init */ - outb_p(0x00, 0x21); /* ICW2: 8259A-1 IR0-7 mapped to 0x00-0x07 */ - outb_p(0x04, 0x21); /* 8259A-1 (the master) has a slave on IR2 */ - if (auto_eoi) - outb_p(0x03, 0x21); /* master does Auto EOI */ - else - outb_p(0x01, 0x21); /* master expects normal EOI */ - - outb_p(0x11, 0xA0); /* ICW1: select 8259A-2 init */ - outb_p(0x08, 0xA1); /* ICW2: 8259A-2 IR0-7 mapped to 0x08-0x0f */ - outb_p(0x02, 0xA1); /* 8259A-2 is a slave on master's IR2 */ - outb_p(0x01, 0xA1); /* (slave's support for AEOI in flat mode - is to be investigated) */ - + outb_p(0x11, PIC_MASTER_CMD); /* ICW1: select 8259A-1 init */ + outb_p(I8259A_IRQ_BASE + 0, PIC_MASTER_IMR); /* ICW2: 8259A-1 IR0 mapped to I8259A_IRQ_BASE + 0x00 */ + outb_p(1U << PIC_CASCADE_IR, PIC_MASTER_IMR); /* 8259A-1 (the master) has a slave on IR2 */ + if (auto_eoi) /* master does Auto EOI */ + outb_p(MASTER_ICW4_DEFAULT | PIC_ICW4_AEOI, PIC_MASTER_IMR); + else /* master expects normal EOI */ + outb_p(MASTER_ICW4_DEFAULT, PIC_MASTER_IMR); + + outb_p(0x11, PIC_SLAVE_CMD); /* ICW1: select 8259A-2 init */ + outb_p(I8259A_IRQ_BASE + 8, PIC_SLAVE_IMR); /* ICW2: 8259A-2 IR0 mapped to I8259A_IRQ_BASE + 0x08 */ + outb_p(PIC_CASCADE_IR, PIC_SLAVE_IMR); /* 8259A-2 is a slave on master's IR2 */ + outb_p(SLAVE_ICW4_DEFAULT, PIC_SLAVE_IMR); /* (slave's support for AEOI in flat mode is to be investigated) */ if (auto_eoi) /* - * in AEOI mode we just have to mask the interrupt + * In AEOI mode we just have to mask the interrupt * when acking. */ - i8259A_irq_type.ack = disable_8259A_irq; + i8259A_chip.mask_ack = disable_8259A_irq; else - i8259A_irq_type.ack = mask_and_ack_8259A; + i8259A_chip.mask_ack = mask_and_ack_8259A; udelay(100); /* wait for 8259A to initialize */ - outb(cached_21, 0x21); /* restore master IRQ mask */ - outb(cached_A1, 0xA1); /* restore slave IRQ mask */ + outb(cached_master_mask, PIC_MASTER_IMR); /* restore master IRQ mask */ + outb(cached_slave_mask, PIC_SLAVE_IMR); /* restore slave IRQ mask */ spin_unlock_irqrestore(&i8259A_lock, flags); } @@ -291,11 +295,17 @@ static struct irqaction irq2 = { }; static struct resource pic1_io_resource = { - .name = "pic1", .start = 0x20, .end = 0x21, .flags = IORESOURCE_BUSY + .name = "pic1", + .start = PIC_MASTER_CMD, + .end = PIC_MASTER_IMR, + .flags = IORESOURCE_BUSY }; static struct resource pic2_io_resource = { - .name = "pic2", .start = 0xa0, .end = 0xa1, .flags = IORESOURCE_BUSY + .name = "pic2", + .start = PIC_SLAVE_CMD, + .end = PIC_SLAVE_IMR, + .flags = IORESOURCE_BUSY }; /* @@ -313,7 +323,7 @@ void __init init_i8259_irqs (void) init_8259A(0); for (i = 0; i < 16; i++) - set_irq_chip(i, &i8259A_irq_type); + set_irq_chip_and_handler(i, &i8259A_chip, handle_level_irq); - setup_irq(2, &irq2); + setup_irq(PIC_CASCADE_IR, &irq2); } diff --git a/trunk/arch/mips/kernel/irixelf.c b/trunk/arch/mips/kernel/irixelf.c index ab12c8f01518..37cad5de515c 100644 --- a/trunk/arch/mips/kernel/irixelf.c +++ b/trunk/arch/mips/kernel/irixelf.c @@ -52,10 +52,6 @@ static struct linux_binfmt irix_format = { irix_core_dump, PAGE_SIZE }; -#ifndef elf_addr_t -#define elf_addr_t unsigned long -#endif - #ifdef DEBUG /* Debugging routines. */ static char *get_elf_p_type(Elf32_Word p_type) @@ -1013,7 +1009,7 @@ static int notesize(struct memelfnote *en) int sz; sz = sizeof(struct elf_note); - sz += roundup(strlen(en->name), 4); + sz += roundup(strlen(en->name) + 1, 4); sz += roundup(en->datasz, 4); return sz; @@ -1032,7 +1028,7 @@ static int writenote(struct memelfnote *men, struct file *file) { struct elf_note en; - en.n_namesz = strlen(men->name); + en.n_namesz = strlen(men->name) + 1; en.n_descsz = men->datasz; en.n_type = men->type; @@ -1149,7 +1145,7 @@ static int irix_core_dump(long signr, struct pt_regs * regs, struct file *file) psinfo.pr_pid = prstatus.pr_pid = current->pid; psinfo.pr_ppid = prstatus.pr_ppid = current->parent->pid; psinfo.pr_pgrp = prstatus.pr_pgrp = process_group(current); - psinfo.pr_sid = prstatus.pr_sid = current->signal->session; + psinfo.pr_sid = prstatus.pr_sid = process_session(current); if (current->pid == current->tgid) { /* * This is the record for the group leader. Add in the diff --git a/trunk/arch/mips/kernel/irq-mv6434x.c b/trunk/arch/mips/kernel/irq-mv6434x.c index 6cfb31cafde2..efbd219845b5 100644 --- a/trunk/arch/mips/kernel/irq-mv6434x.c +++ b/trunk/arch/mips/kernel/irq-mv6434x.c @@ -66,15 +66,6 @@ static inline void unmask_mv64340_irq(unsigned int irq) } } -/* - * End IRQ processing - */ -static void end_mv64340_irq(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) - unmask_mv64340_irq(irq); -} - /* * Interrupt handler for interrupts coming from the Marvell chip. * It could be built in ethernet ports etc... @@ -106,7 +97,6 @@ struct irq_chip mv64340_irq_type = { .mask = mask_mv64340_irq, .mask_ack = mask_mv64340_irq, .unmask = unmask_mv64340_irq, - .end = end_mv64340_irq, }; void __init mv64340_irq_init(unsigned int base) diff --git a/trunk/arch/mips/kernel/irq-rm7000.c b/trunk/arch/mips/kernel/irq-rm7000.c index ddcc2a5f8a06..123324ba8c14 100644 --- a/trunk/arch/mips/kernel/irq-rm7000.c +++ b/trunk/arch/mips/kernel/irq-rm7000.c @@ -29,19 +29,12 @@ static inline void mask_rm7k_irq(unsigned int irq) clear_c0_intcontrol(0x100 << (irq - irq_base)); } -static void rm7k_cpu_irq_end(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) - unmask_rm7k_irq(irq); -} - static struct irq_chip rm7k_irq_controller = { .typename = "RM7000", .ack = mask_rm7k_irq, .mask = mask_rm7k_irq, .mask_ack = mask_rm7k_irq, .unmask = unmask_rm7k_irq, - .end = rm7k_cpu_irq_end, }; void __init rm7k_cpu_irq_init(int base) diff --git a/trunk/arch/mips/kernel/irq-rm9000.c b/trunk/arch/mips/kernel/irq-rm9000.c index ba6440c88abd..0e6f4c5349d2 100644 --- a/trunk/arch/mips/kernel/irq-rm9000.c +++ b/trunk/arch/mips/kernel/irq-rm9000.c @@ -80,19 +80,12 @@ static void rm9k_perfcounter_irq_shutdown(unsigned int irq) on_each_cpu(local_rm9k_perfcounter_irq_shutdown, (void *) irq, 0, 1); } -static void rm9k_cpu_irq_end(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) - unmask_rm9k_irq(irq); -} - static struct irq_chip rm9k_irq_controller = { .typename = "RM9000", .ack = mask_rm9k_irq, .mask = mask_rm9k_irq, .mask_ack = mask_rm9k_irq, .unmask = unmask_rm9k_irq, - .end = rm9k_cpu_irq_end, }; static struct irq_chip rm9k_perfcounter_irq = { @@ -103,7 +96,6 @@ static struct irq_chip rm9k_perfcounter_irq = { .mask = mask_rm9k_irq, .mask_ack = mask_rm9k_irq, .unmask = unmask_rm9k_irq, - .end = rm9k_cpu_irq_end, }; unsigned int rm9000_perfcount_irq; diff --git a/trunk/arch/mips/kernel/irq.c b/trunk/arch/mips/kernel/irq.c index b339798b3172..2fe4c868a801 100644 --- a/trunk/arch/mips/kernel/irq.c +++ b/trunk/arch/mips/kernel/irq.c @@ -117,7 +117,7 @@ int show_interrupts(struct seq_file *p, void *v) for_each_online_cpu(j) seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]); #endif - seq_printf(p, " %14s", irq_desc[i].chip->typename); + seq_printf(p, " %14s", irq_desc[i].chip->name); seq_printf(p, " %s", action->name); for (action=action->next; action; action = action->next) diff --git a/trunk/arch/mips/kernel/irq_cpu.c b/trunk/arch/mips/kernel/irq_cpu.c index be5ac23d3812..fcc86b96ccf6 100644 --- a/trunk/arch/mips/kernel/irq_cpu.c +++ b/trunk/arch/mips/kernel/irq_cpu.c @@ -50,12 +50,6 @@ static inline void mask_mips_irq(unsigned int irq) irq_disable_hazard(); } -static void mips_cpu_irq_end(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) - unmask_mips_irq(irq); -} - static struct irq_chip mips_cpu_irq_controller = { .typename = "MIPS", .ack = mask_mips_irq, @@ -63,7 +57,6 @@ static struct irq_chip mips_cpu_irq_controller = { .mask_ack = mask_mips_irq, .unmask = unmask_mips_irq, .eoi = unmask_mips_irq, - .end = mips_cpu_irq_end, }; /* @@ -96,8 +89,6 @@ static void mips_mt_cpu_irq_ack(unsigned int irq) mask_mips_mt_irq(irq); } -#define mips_mt_cpu_irq_end mips_cpu_irq_end - static struct irq_chip mips_mt_cpu_irq_controller = { .typename = "MIPS", .startup = mips_mt_cpu_irq_startup, @@ -106,7 +97,6 @@ static struct irq_chip mips_mt_cpu_irq_controller = { .mask_ack = mips_mt_cpu_irq_ack, .unmask = unmask_mips_mt_irq, .eoi = unmask_mips_mt_irq, - .end = mips_mt_cpu_irq_end, }; void __init mips_cpu_irq_init(int irq_base) diff --git a/trunk/arch/mips/kernel/kspd.c b/trunk/arch/mips/kernel/kspd.c index f06a144c7881..2c82412b9efe 100644 --- a/trunk/arch/mips/kernel/kspd.c +++ b/trunk/arch/mips/kernel/kspd.c @@ -319,7 +319,7 @@ static void sp_cleanup(void) static int channel_open = 0; /* the work handler */ -static void sp_work(void *data) +static void sp_work(struct work_struct *unused) { if (!channel_open) { if( rtlx_open(RTLX_CHANNEL_SYSIO, 1) != 0) { @@ -354,7 +354,7 @@ static void startwork(int vpe) return; } - INIT_WORK(&work, sp_work, NULL); + INIT_WORK(&work, sp_work); queue_work(workqueue, &work); } else queue_work(workqueue, &work); diff --git a/trunk/arch/mips/kernel/rtlx.c b/trunk/arch/mips/kernel/rtlx.c index 8c8c8324f775..5a99e3e0c96d 100644 --- a/trunk/arch/mips/kernel/rtlx.c +++ b/trunk/arch/mips/kernel/rtlx.c @@ -415,7 +415,7 @@ static unsigned int file_poll(struct file *file, poll_table * wait) int minor; unsigned int mask = 0; - minor = iminor(file->f_dentry->d_inode); + minor = iminor(file->f_path.dentry->d_inode); poll_wait(file, &channel_wqs[minor].rt_queue, wait); poll_wait(file, &channel_wqs[minor].lx_queue, wait); @@ -437,7 +437,7 @@ static unsigned int file_poll(struct file *file, poll_table * wait) static ssize_t file_read(struct file *file, char __user * buffer, size_t count, loff_t * ppos) { - int minor = iminor(file->f_dentry->d_inode); + int minor = iminor(file->f_path.dentry->d_inode); /* data available? */ if (!rtlx_read_poll(minor, (file->f_flags & O_NONBLOCK) ? 0 : 1)) { @@ -454,7 +454,7 @@ static ssize_t file_write(struct file *file, const char __user * buffer, struct rtlx_channel *rt; DECLARE_WAITQUEUE(wait, current); - minor = iminor(file->f_dentry->d_inode); + minor = iminor(file->f_path.dentry->d_inode); rt = &rtlx->channel[minor]; /* any space left... */ diff --git a/trunk/arch/mips/kernel/sysirix.c b/trunk/arch/mips/kernel/sysirix.c index 93c74fefff76..6c2406a93f2b 100644 --- a/trunk/arch/mips/kernel/sysirix.c +++ b/trunk/arch/mips/kernel/sysirix.c @@ -732,7 +732,7 @@ asmlinkage int irix_fstatfs(unsigned int fd, struct irix_statfs __user *buf) goto out; } - error = vfs_statfs(file->f_dentry, &kbuf); + error = vfs_statfs(file->f_path.dentry, &kbuf); if (error) goto out_f; @@ -1041,7 +1041,7 @@ asmlinkage unsigned long irix_mmap32(unsigned long addr, size_t len, int prot, unsigned long old_pos; long max_size = offset + len; - if (max_size > file->f_dentry->d_inode->i_size) { + if (max_size > file->f_path.dentry->d_inode->i_size) { old_pos = sys_lseek (fd, max_size - 1, 0); sys_write (fd, (void __user *) "", 1); sys_lseek (fd, old_pos, 0); @@ -1406,7 +1406,7 @@ asmlinkage int irix_fstatvfs(int fd, struct irix_statvfs __user *buf) error = -EBADF; goto out; } - error = vfs_statfs(file->f_dentry, &kbuf); + error = vfs_statfs(file->f_path.dentry, &kbuf); if (error) goto out_f; @@ -1526,7 +1526,7 @@ asmlinkage int irix_mmap64(struct pt_regs *regs) unsigned long old_pos; long max_size = off2 + len; - if (max_size > file->f_dentry->d_inode->i_size) { + if (max_size > file->f_path.dentry->d_inode->i_size) { old_pos = sys_lseek (fd, max_size - 1, 0); sys_write (fd, (void __user *) "", 1); sys_lseek (fd, old_pos, 0); @@ -1658,7 +1658,7 @@ asmlinkage int irix_fstatvfs64(int fd, struct irix_statvfs __user *buf) error = -EBADF; goto out; } - error = vfs_statfs(file->f_dentry, &kbuf); + error = vfs_statfs(file->f_path.dentry, &kbuf); if (error) goto out_f; diff --git a/trunk/arch/mips/kernel/vpe.c b/trunk/arch/mips/kernel/vpe.c index 51ddd2166898..666bef484dcb 100644 --- a/trunk/arch/mips/kernel/vpe.c +++ b/trunk/arch/mips/kernel/vpe.c @@ -1179,7 +1179,7 @@ static ssize_t vpe_write(struct file *file, const char __user * buffer, size_t ret = count; struct vpe *v; - minor = iminor(file->f_dentry->d_inode); + minor = iminor(file->f_path.dentry->d_inode); if ((v = get_vpe(minor)) == NULL) return -ENODEV; diff --git a/trunk/arch/mips/lasat/interrupt.c b/trunk/arch/mips/lasat/interrupt.c index 4a84a7beac53..2affa5ff171c 100644 --- a/trunk/arch/mips/lasat/interrupt.c +++ b/trunk/arch/mips/lasat/interrupt.c @@ -44,19 +44,12 @@ void enable_lasat_irq(unsigned int irq_nr) *lasat_int_mask |= (1 << irq_nr) << lasat_int_mask_shift; } -static void end_lasat_irq(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) - enable_lasat_irq(irq); -} - static struct irq_chip lasat_irq_type = { .typename = "Lasat", .ack = disable_lasat_irq, .mask = disable_lasat_irq, .mask_ack = disable_lasat_irq, .unmask = enable_lasat_irq, - .end = end_lasat_irq, }; static inline int ls1bit32(unsigned int x) diff --git a/trunk/arch/mips/lasat/sysctl.c b/trunk/arch/mips/lasat/sysctl.c index 6dd7ae1b7c25..da35d4555491 100644 --- a/trunk/arch/mips/lasat/sysctl.c +++ b/trunk/arch/mips/lasat/sysctl.c @@ -286,11 +286,11 @@ int proc_lasat_eeprom_value(ctl_table *table, int write, struct file *filp, mutex_unlock(&lasat_info_mutex); return r; } - if (filp && filp->f_dentry) + if (filp && filp->f_path.dentry) { - if (!strcmp(filp->f_dentry->d_name.name, "prid")) + if (!strcmp(filp->f_path.dentry->d_name.name, "prid")) lasat_board_info.li_eeprom_info.prid = lasat_board_info.li_prid; - if (!strcmp(filp->f_dentry->d_name.name, "debugaccess")) + if (!strcmp(filp->f_path.dentry->d_name.name, "debugaccess")) lasat_board_info.li_eeprom_info.debugaccess = lasat_board_info.li_debugaccess; } lasat_write_eeprom_info(); diff --git a/trunk/arch/mips/mm/dma-coherent.c b/trunk/arch/mips/mm/dma-coherent.c index 7fa5fd16e46b..5697c6e250a3 100644 --- a/trunk/arch/mips/mm/dma-coherent.c +++ b/trunk/arch/mips/mm/dma-coherent.c @@ -190,14 +190,14 @@ int dma_supported(struct device *dev, u64 mask) EXPORT_SYMBOL(dma_supported); -int dma_is_consistent(dma_addr_t dma_addr) +int dma_is_consistent(struct device *dev, dma_addr_t dma_addr) { return 1; } EXPORT_SYMBOL(dma_is_consistent); -void dma_cache_sync(void *vaddr, size_t size, +void dma_cache_sync(struct device *dev, void *vaddr, size_t size, enum dma_data_direction direction) { BUG_ON(direction == DMA_NONE); diff --git a/trunk/arch/mips/mm/dma-ip27.c b/trunk/arch/mips/mm/dma-ip27.c index 8da19fd22ac6..f088344db465 100644 --- a/trunk/arch/mips/mm/dma-ip27.c +++ b/trunk/arch/mips/mm/dma-ip27.c @@ -197,14 +197,14 @@ int dma_supported(struct device *dev, u64 mask) EXPORT_SYMBOL(dma_supported); -int dma_is_consistent(dma_addr_t dma_addr) +int dma_is_consistent(struct device *dev, dma_addr_t dma_addr) { return 1; } EXPORT_SYMBOL(dma_is_consistent); -void dma_cache_sync(void *vaddr, size_t size, +void dma_cache_sync(struct device *dev, void *vaddr, size_t size, enum dma_data_direction direction) { BUG_ON(direction == DMA_NONE); diff --git a/trunk/arch/mips/mm/dma-ip32.c b/trunk/arch/mips/mm/dma-ip32.c index ec54ed0d26ff..b42b6f7456e6 100644 --- a/trunk/arch/mips/mm/dma-ip32.c +++ b/trunk/arch/mips/mm/dma-ip32.c @@ -363,14 +363,15 @@ int dma_supported(struct device *dev, u64 mask) EXPORT_SYMBOL(dma_supported); -int dma_is_consistent(dma_addr_t dma_addr) +int dma_is_consistent(struct device *dev, dma_addr_t dma_addr) { return 1; } EXPORT_SYMBOL(dma_is_consistent); -void dma_cache_sync(void *vaddr, size_t size, enum dma_data_direction direction) +void dma_cache_sync(struct device *dev, void *vaddr, size_t size, + enum dma_data_direction direction) { if (direction == DMA_NONE) return; diff --git a/trunk/arch/mips/mm/dma-noncoherent.c b/trunk/arch/mips/mm/dma-noncoherent.c index 2eeffe5c2a3a..8cecef0957c3 100644 --- a/trunk/arch/mips/mm/dma-noncoherent.c +++ b/trunk/arch/mips/mm/dma-noncoherent.c @@ -299,14 +299,15 @@ int dma_supported(struct device *dev, u64 mask) EXPORT_SYMBOL(dma_supported); -int dma_is_consistent(dma_addr_t dma_addr) +int dma_is_consistent(struct device *dev, dma_addr_t dma_addr) { return 1; } EXPORT_SYMBOL(dma_is_consistent); -void dma_cache_sync(void *vaddr, size_t size, enum dma_data_direction direction) +void dma_cache_sync(struct device *dev, void *vaddr, size_t size, + enum dma_data_direction direction) { if (direction == DMA_NONE) return; diff --git a/trunk/arch/mips/mm/highmem.c b/trunk/arch/mips/mm/highmem.c index 99ebf3ccc222..675502ada5a2 100644 --- a/trunk/arch/mips/mm/highmem.c +++ b/trunk/arch/mips/mm/highmem.c @@ -39,7 +39,7 @@ void *__kmap_atomic(struct page *page, enum km_type type) unsigned long vaddr; /* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */ - inc_preempt_count(); + pagefault_disable(); if (!PageHighMem(page)) return page_address(page); @@ -62,8 +62,7 @@ void __kunmap_atomic(void *kvaddr, enum km_type type) enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id(); if (vaddr < FIXADDR_START) { // FIXME - dec_preempt_count(); - preempt_check_resched(); + pagefault_enable(); return; } @@ -78,8 +77,7 @@ void __kunmap_atomic(void *kvaddr, enum km_type type) local_flush_tlb_one(vaddr); #endif - dec_preempt_count(); - preempt_check_resched(); + pagefault_enable(); } #ifndef CONFIG_LIMITED_DMA @@ -92,7 +90,7 @@ void *kmap_atomic_pfn(unsigned long pfn, enum km_type type) enum fixed_addresses idx; unsigned long vaddr; - inc_preempt_count(); + pagefault_disable(); idx = type + KM_TYPE_NR*smp_processor_id(); vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); diff --git a/trunk/arch/mips/mm/ioremap.c b/trunk/arch/mips/mm/ioremap.c index cea7d0ea36e4..fc2c96f0a1fd 100644 --- a/trunk/arch/mips/mm/ioremap.c +++ b/trunk/arch/mips/mm/ioremap.c @@ -6,98 +6,13 @@ * (C) Copyright 1995 1996 Linus Torvalds * (C) Copyright 2001, 2002 Ralf Baechle */ +#include #include #include #include #include -#include -#include -#include - -static inline void remap_area_pte(pte_t * pte, unsigned long address, - phys_t size, phys_t phys_addr, unsigned long flags) -{ - phys_t end; - unsigned long pfn; - pgprot_t pgprot = __pgprot(_PAGE_GLOBAL | _PAGE_PRESENT | __READABLE - | __WRITEABLE | flags); - - address &= ~PMD_MASK; - end = address + size; - if (end > PMD_SIZE) - end = PMD_SIZE; - if (address >= end) - BUG(); - pfn = phys_addr >> PAGE_SHIFT; - do { - if (!pte_none(*pte)) { - printk("remap_area_pte: page already exists\n"); - BUG(); - } - set_pte(pte, pfn_pte(pfn, pgprot)); - address += PAGE_SIZE; - pfn++; - pte++; - } while (address && (address < end)); -} - -static inline int remap_area_pmd(pmd_t * pmd, unsigned long address, - phys_t size, phys_t phys_addr, unsigned long flags) -{ - phys_t end; - - address &= ~PGDIR_MASK; - end = address + size; - if (end > PGDIR_SIZE) - end = PGDIR_SIZE; - phys_addr -= address; - if (address >= end) - BUG(); - do { - pte_t * pte = pte_alloc_kernel(pmd, address); - if (!pte) - return -ENOMEM; - remap_area_pte(pte, address, end - address, address + phys_addr, flags); - address = (address + PMD_SIZE) & PMD_MASK; - pmd++; - } while (address && (address < end)); - return 0; -} - -static int remap_area_pages(unsigned long address, phys_t phys_addr, - phys_t size, unsigned long flags) -{ - int error; - pgd_t * dir; - unsigned long end = address + size; - - phys_addr -= address; - dir = pgd_offset(&init_mm, address); - flush_cache_all(); - if (address >= end) - BUG(); - do { - pud_t *pud; - pmd_t *pmd; - - error = -ENOMEM; - pud = pud_alloc(&init_mm, dir, address); - if (!pud) - break; - pmd = pmd_alloc(&init_mm, pud, address); - if (!pmd) - break; - if (remap_area_pmd(pmd, address, end - address, - phys_addr + address, flags)) - break; - error = 0; - address = (address + PGDIR_SIZE) & PGDIR_MASK; - dir++; - } while (address && (address < end)); - flush_tlb_all(); - return error; -} +#include /* * Generic mapping function (not visible outside): @@ -121,6 +36,7 @@ void __iomem * __ioremap(phys_t phys_addr, phys_t size, unsigned long flags) unsigned long offset; phys_t last_addr; void * addr; + pgprot_t pgprot; phys_addr = fixup_bigphys_addr(phys_addr, size); @@ -152,6 +68,9 @@ void __iomem * __ioremap(phys_t phys_addr, phys_t size, unsigned long flags) return NULL; } + pgprot = __pgprot(_PAGE_GLOBAL | _PAGE_PRESENT | __READABLE + | __WRITEABLE | flags); + /* * Mappings have to be page-aligned */ @@ -166,7 +85,8 @@ void __iomem * __ioremap(phys_t phys_addr, phys_t size, unsigned long flags) if (!area) return NULL; addr = area->addr; - if (remap_area_pages((unsigned long) addr, phys_addr, size, flags)) { + if (ioremap_page_range((unsigned long)addr, (unsigned long)addr + size, + phys_addr, pgprot)) { vunmap(addr); return NULL; } diff --git a/trunk/arch/mips/momentum/ocelot_c/cpci-irq.c b/trunk/arch/mips/momentum/ocelot_c/cpci-irq.c index e5a4a0a8a7f0..bb11fef08472 100644 --- a/trunk/arch/mips/momentum/ocelot_c/cpci-irq.c +++ b/trunk/arch/mips/momentum/ocelot_c/cpci-irq.c @@ -65,15 +65,6 @@ static inline void unmask_cpci_irq(unsigned int irq) value = OCELOT_FPGA_READ(INTMASK); } -/* - * End IRQ processing - */ -static void end_cpci_irq(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) - unmask_cpci_irq(irq); -} - /* * Interrupt handler for interrupts coming from the FPGA chip. * It could be built in ethernet ports etc... @@ -98,7 +89,6 @@ struct irq_chip cpci_irq_type = { .mask = mask_cpci_irq, .mask_ack = mask_cpci_irq, .unmask = unmask_cpci_irq, - .end = end_cpci_irq, }; void cpci_irq_init(void) diff --git a/trunk/arch/mips/momentum/ocelot_c/uart-irq.c b/trunk/arch/mips/momentum/ocelot_c/uart-irq.c index 0029f0008dea..a7a80c0da569 100644 --- a/trunk/arch/mips/momentum/ocelot_c/uart-irq.c +++ b/trunk/arch/mips/momentum/ocelot_c/uart-irq.c @@ -59,15 +59,6 @@ static inline void unmask_uart_irq(unsigned int irq) value = OCELOT_FPGA_READ(UART_INTMASK); } -/* - * End IRQ processing - */ -static void end_uart_irq(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) - unmask_uart_irq(irq); -} - /* * Interrupt handler for interrupts coming from the FPGA chip. */ @@ -91,7 +82,6 @@ struct irq_chip uart_irq_type = { .mask = mask_uart_irq, .mask_ack = mask_uart_irq, .unmask = unmask_uart_irq, - .end = end_uart_irq, }; void uart_irq_init(void) diff --git a/trunk/arch/mips/philips/pnx8550/common/int.c b/trunk/arch/mips/philips/pnx8550/common/int.c index 0dc23930edbd..2c36c108c4d6 100644 --- a/trunk/arch/mips/philips/pnx8550/common/int.c +++ b/trunk/arch/mips/philips/pnx8550/common/int.c @@ -158,20 +158,12 @@ int pnx8550_set_gic_priority(int irq, int priority) return prev_priority; } -static void end_irq(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) { - unmask_irq(irq); - } -} - static struct irq_chip level_irq_type = { .typename = "PNX Level IRQ", .ack = mask_irq, .mask = mask_irq, .mask_ack = mask_irq, .unmask = unmask_irq, - .end = end_irq, }; static struct irqaction gic_action = { diff --git a/trunk/arch/mips/sgi-ip22/ip22-int.c b/trunk/arch/mips/sgi-ip22/ip22-int.c index c7b138053159..c44f8be0644f 100644 --- a/trunk/arch/mips/sgi-ip22/ip22-int.c +++ b/trunk/arch/mips/sgi-ip22/ip22-int.c @@ -51,19 +51,12 @@ static void disable_local0_irq(unsigned int irq) sgint->imask0 &= ~(1 << (irq - SGINT_LOCAL0)); } -static void end_local0_irq (unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) - enable_local0_irq(irq); -} - static struct irq_chip ip22_local0_irq_type = { .typename = "IP22 local 0", .ack = disable_local0_irq, .mask = disable_local0_irq, .mask_ack = disable_local0_irq, .unmask = enable_local0_irq, - .end = end_local0_irq, }; static void enable_local1_irq(unsigned int irq) @@ -79,19 +72,12 @@ void disable_local1_irq(unsigned int irq) sgint->imask1 &= ~(1 << (irq - SGINT_LOCAL1)); } -static void end_local1_irq (unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) - enable_local1_irq(irq); -} - static struct irq_chip ip22_local1_irq_type = { .typename = "IP22 local 1", .ack = disable_local1_irq, .mask = disable_local1_irq, .mask_ack = disable_local1_irq, .unmask = enable_local1_irq, - .end = end_local1_irq, }; static void enable_local2_irq(unsigned int irq) @@ -107,19 +93,12 @@ void disable_local2_irq(unsigned int irq) sgint->imask0 &= ~(1 << (SGI_MAP_0_IRQ - SGINT_LOCAL0)); } -static void end_local2_irq (unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) - enable_local2_irq(irq); -} - static struct irq_chip ip22_local2_irq_type = { .typename = "IP22 local 2", .ack = disable_local2_irq, .mask = disable_local2_irq, .mask_ack = disable_local2_irq, .unmask = enable_local2_irq, - .end = end_local2_irq, }; static void enable_local3_irq(unsigned int irq) @@ -135,19 +114,12 @@ void disable_local3_irq(unsigned int irq) sgint->imask1 &= ~(1 << (SGI_MAP_1_IRQ - SGINT_LOCAL1)); } -static void end_local3_irq (unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) - enable_local3_irq(irq); -} - static struct irq_chip ip22_local3_irq_type = { .typename = "IP22 local 3", .ack = disable_local3_irq, .mask = disable_local3_irq, .mask_ack = disable_local3_irq, .unmask = enable_local3_irq, - .end = end_local3_irq, }; static void indy_local0_irqdispatch(void) diff --git a/trunk/arch/mips/sgi-ip27/ip27-irq.c b/trunk/arch/mips/sgi-ip27/ip27-irq.c index 5f8835b4e84a..319f8803ef6f 100644 --- a/trunk/arch/mips/sgi-ip27/ip27-irq.c +++ b/trunk/arch/mips/sgi-ip27/ip27-irq.c @@ -332,13 +332,6 @@ static inline void disable_bridge_irq(unsigned int irq) intr_disconnect_level(cpu, swlevel); } -static void end_bridge_irq(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)) && - irq_desc[irq].action) - enable_bridge_irq(irq); -} - static struct irq_chip bridge_irq_type = { .typename = "bridge", .startup = startup_bridge_irq, @@ -347,7 +340,6 @@ static struct irq_chip bridge_irq_type = { .mask = disable_bridge_irq, .mask_ack = disable_bridge_irq, .unmask = enable_bridge_irq, - .end = end_bridge_irq, }; void __devinit register_bridge_irq(unsigned int irq) diff --git a/trunk/arch/mips/sgi-ip27/ip27-timer.c b/trunk/arch/mips/sgi-ip27/ip27-timer.c index 7d361726bbfb..c20e9899b34b 100644 --- a/trunk/arch/mips/sgi-ip27/ip27-timer.c +++ b/trunk/arch/mips/sgi-ip27/ip27-timer.c @@ -180,10 +180,6 @@ static void disable_rt_irq(unsigned int irq) { } -static void end_rt_irq(unsigned int irq) -{ -} - static struct irq_chip rt_irq_type = { .typename = "SN HUB RT timer", .ack = disable_rt_irq, @@ -191,7 +187,6 @@ static struct irq_chip rt_irq_type = { .mask_ack = disable_rt_irq, .unmask = enable_rt_irq, .eoi = enable_rt_irq, - .end = end_rt_irq, }; static struct irqaction rt_irqaction = { diff --git a/trunk/arch/mips/tx4927/common/tx4927_irq.c b/trunk/arch/mips/tx4927/common/tx4927_irq.c index 21873de49aa8..ed4a19adf361 100644 --- a/trunk/arch/mips/tx4927/common/tx4927_irq.c +++ b/trunk/arch/mips/tx4927/common/tx4927_irq.c @@ -66,12 +66,10 @@ #define TX4927_IRQ_CP0_INIT ( 1 << 10 ) #define TX4927_IRQ_CP0_ENABLE ( 1 << 13 ) #define TX4927_IRQ_CP0_DISABLE ( 1 << 14 ) -#define TX4927_IRQ_CP0_ENDIRQ ( 1 << 16 ) #define TX4927_IRQ_PIC_INIT ( 1 << 20 ) #define TX4927_IRQ_PIC_ENABLE ( 1 << 23 ) #define TX4927_IRQ_PIC_DISABLE ( 1 << 24 ) -#define TX4927_IRQ_PIC_ENDIRQ ( 1 << 26 ) #define TX4927_IRQ_ALL 0xffffffff #endif @@ -82,12 +80,10 @@ static const u32 tx4927_irq_debug_flag = (TX4927_IRQ_NONE | TX4927_IRQ_WARN | TX4927_IRQ_EROR // | TX4927_IRQ_CP0_INIT // | TX4927_IRQ_CP0_ENABLE -// | TX4927_IRQ_CP0_DISABLE // | TX4927_IRQ_CP0_ENDIRQ // | TX4927_IRQ_PIC_INIT // | TX4927_IRQ_PIC_ENABLE // | TX4927_IRQ_PIC_DISABLE -// | TX4927_IRQ_PIC_ENDIRQ // | TX4927_IRQ_INIT // | TX4927_IRQ_NEST1 // | TX4927_IRQ_NEST2 @@ -114,11 +110,9 @@ static const u32 tx4927_irq_debug_flag = (TX4927_IRQ_NONE static void tx4927_irq_cp0_enable(unsigned int irq); static void tx4927_irq_cp0_disable(unsigned int irq); -static void tx4927_irq_cp0_end(unsigned int irq); static void tx4927_irq_pic_enable(unsigned int irq); static void tx4927_irq_pic_disable(unsigned int irq); -static void tx4927_irq_pic_end(unsigned int irq); /* * Kernel structs for all pic's @@ -131,7 +125,6 @@ static struct irq_chip tx4927_irq_cp0_type = { .mask = tx4927_irq_cp0_disable, .mask_ack = tx4927_irq_cp0_disable, .unmask = tx4927_irq_cp0_enable, - .end = tx4927_irq_cp0_end, }; #define TX4927_PIC_NAME "TX4927-PIC" @@ -141,7 +134,6 @@ static struct irq_chip tx4927_irq_pic_type = { .mask = tx4927_irq_pic_disable, .mask_ack = tx4927_irq_pic_disable, .unmask = tx4927_irq_pic_enable, - .end = tx4927_irq_pic_end, }; #define TX4927_PIC_ACTION(s) { no_action, 0, CPU_MASK_NONE, s, NULL, NULL } @@ -214,15 +206,6 @@ static void tx4927_irq_cp0_disable(unsigned int irq) tx4927_irq_cp0_modify(CCP0_STATUS, tx4927_irq_cp0_mask(irq), 0); } -static void tx4927_irq_cp0_end(unsigned int irq) -{ - TX4927_IRQ_DPRINTK(TX4927_IRQ_CP0_ENDIRQ, "irq=%d \n", irq); - - if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) { - tx4927_irq_cp0_enable(irq); - } -} - /* * Functions for pic */ @@ -376,15 +359,6 @@ static void tx4927_irq_pic_disable(unsigned int irq) tx4927_irq_pic_mask(irq), 0); } -static void tx4927_irq_pic_end(unsigned int irq) -{ - TX4927_IRQ_DPRINTK(TX4927_IRQ_PIC_ENDIRQ, "irq=%d\n", irq); - - if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) { - tx4927_irq_pic_enable(irq); - } -} - /* * Main init functions */ diff --git a/trunk/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c b/trunk/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c index 34cdb2a240e9..5a5ea6c0b9f6 100644 --- a/trunk/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c +++ b/trunk/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c @@ -153,7 +153,6 @@ JP7 is not bus master -- do NOT use -- only 4 pci bus master's allowed -- SouthB #define TOSHIBA_RBTX4927_IRQ_IOC_INIT ( 1 << 10 ) #define TOSHIBA_RBTX4927_IRQ_IOC_ENABLE ( 1 << 13 ) #define TOSHIBA_RBTX4927_IRQ_IOC_DISABLE ( 1 << 14 ) -#define TOSHIBA_RBTX4927_IRQ_IOC_ENDIRQ ( 1 << 16 ) #define TOSHIBA_RBTX4927_IRQ_ISA_INIT ( 1 << 20 ) #define TOSHIBA_RBTX4927_IRQ_ISA_ENABLE ( 1 << 23 ) @@ -172,7 +171,6 @@ static const u32 toshiba_rbtx4927_irq_debug_flag = // | TOSHIBA_RBTX4927_IRQ_IOC_INIT // | TOSHIBA_RBTX4927_IRQ_IOC_ENABLE // | TOSHIBA_RBTX4927_IRQ_IOC_DISABLE -// | TOSHIBA_RBTX4927_IRQ_IOC_ENDIRQ // | TOSHIBA_RBTX4927_IRQ_ISA_INIT // | TOSHIBA_RBTX4927_IRQ_ISA_ENABLE // | TOSHIBA_RBTX4927_IRQ_ISA_DISABLE @@ -223,7 +221,6 @@ extern void mask_and_ack_8259A(unsigned int irq); static void toshiba_rbtx4927_irq_ioc_enable(unsigned int irq); static void toshiba_rbtx4927_irq_ioc_disable(unsigned int irq); -static void toshiba_rbtx4927_irq_ioc_end(unsigned int irq); #ifdef CONFIG_TOSHIBA_FPCIB0 static void toshiba_rbtx4927_irq_isa_enable(unsigned int irq); @@ -239,7 +236,6 @@ static struct irq_chip toshiba_rbtx4927_irq_ioc_type = { .mask = toshiba_rbtx4927_irq_ioc_disable, .mask_ack = toshiba_rbtx4927_irq_ioc_disable, .unmask = toshiba_rbtx4927_irq_ioc_enable, - .end = toshiba_rbtx4927_irq_ioc_end, }; #define TOSHIBA_RBTX4927_IOC_INTR_ENAB 0xbc002000 #define TOSHIBA_RBTX4927_IOC_INTR_STAT 0xbc002006 @@ -388,23 +384,6 @@ static void toshiba_rbtx4927_irq_ioc_disable(unsigned int irq) TOSHIBA_RBTX4927_WR08(TOSHIBA_RBTX4927_IOC_INTR_ENAB, v); } -static void toshiba_rbtx4927_irq_ioc_end(unsigned int irq) -{ - TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_IOC_ENDIRQ, - "irq=%d\n", irq); - - if (irq < TOSHIBA_RBTX4927_IRQ_IOC_BEG - || irq > TOSHIBA_RBTX4927_IRQ_IOC_END) { - TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_EROR, - "bad irq=%d\n", irq); - panic("\n"); - } - - if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) { - toshiba_rbtx4927_irq_ioc_enable(irq); - } -} - /**********************************************************************************/ /* Functions for isa */ diff --git a/trunk/arch/mips/tx4938/common/irq.c b/trunk/arch/mips/tx4938/common/irq.c index 42e127683ae9..a347b424d91c 100644 --- a/trunk/arch/mips/tx4938/common/irq.c +++ b/trunk/arch/mips/tx4938/common/irq.c @@ -39,11 +39,9 @@ static void tx4938_irq_cp0_enable(unsigned int irq); static void tx4938_irq_cp0_disable(unsigned int irq); -static void tx4938_irq_cp0_end(unsigned int irq); static void tx4938_irq_pic_enable(unsigned int irq); static void tx4938_irq_pic_disable(unsigned int irq); -static void tx4938_irq_pic_end(unsigned int irq); /**********************************************************************************/ /* Kernel structs for all pic's */ @@ -56,7 +54,6 @@ static struct irq_chip tx4938_irq_cp0_type = { .mask = tx4938_irq_cp0_disable, .mask_ack = tx4938_irq_cp0_disable, .unmask = tx4938_irq_cp0_enable, - .end = tx4938_irq_cp0_end, }; #define TX4938_PIC_NAME "TX4938-PIC" @@ -66,7 +63,6 @@ static struct irq_chip tx4938_irq_pic_type = { .mask = tx4938_irq_pic_disable, .mask_ack = tx4938_irq_pic_disable, .unmask = tx4938_irq_pic_enable, - .end = tx4938_irq_pic_end, }; static struct irqaction tx4938_irq_pic_action = { @@ -104,14 +100,6 @@ tx4938_irq_cp0_disable(unsigned int irq) clear_c0_status(tx4938_irq_cp0_mask(irq)); } -static void -tx4938_irq_cp0_end(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) { - tx4938_irq_cp0_enable(irq); - } -} - /**********************************************************************************/ /* Functions for pic */ /**********************************************************************************/ @@ -269,14 +257,6 @@ tx4938_irq_pic_disable(unsigned int irq) tx4938_irq_pic_mask(irq), 0); } -static void -tx4938_irq_pic_end(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) { - tx4938_irq_pic_enable(irq); - } -} - /**********************************************************************************/ /* Main init functions */ /**********************************************************************************/ diff --git a/trunk/arch/mips/tx4938/toshiba_rbtx4938/irq.c b/trunk/arch/mips/tx4938/toshiba_rbtx4938/irq.c index 8c87a35f3068..b6f363d08011 100644 --- a/trunk/arch/mips/tx4938/toshiba_rbtx4938/irq.c +++ b/trunk/arch/mips/tx4938/toshiba_rbtx4938/irq.c @@ -89,7 +89,6 @@ IRQ Device static void toshiba_rbtx4938_irq_ioc_enable(unsigned int irq); static void toshiba_rbtx4938_irq_ioc_disable(unsigned int irq); -static void toshiba_rbtx4938_irq_ioc_end(unsigned int irq); #define TOSHIBA_RBTX4938_IOC_NAME "RBTX4938-IOC" static struct irq_chip toshiba_rbtx4938_irq_ioc_type = { @@ -98,7 +97,6 @@ static struct irq_chip toshiba_rbtx4938_irq_ioc_type = { .mask = toshiba_rbtx4938_irq_ioc_disable, .mask_ack = toshiba_rbtx4938_irq_ioc_disable, .unmask = toshiba_rbtx4938_irq_ioc_enable, - .end = toshiba_rbtx4938_irq_ioc_end, }; #define TOSHIBA_RBTX4938_IOC_INTR_ENAB 0xb7f02000 @@ -167,14 +165,6 @@ toshiba_rbtx4938_irq_ioc_disable(unsigned int irq) TX4938_RD08(TOSHIBA_RBTX4938_IOC_INTR_ENAB); } -static void -toshiba_rbtx4938_irq_ioc_end(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) { - toshiba_rbtx4938_irq_ioc_enable(irq); - } -} - extern void __init txx9_spi_irqinit(int irc_irq); void __init arch_init_irq(void) diff --git a/trunk/arch/mips/vr41xx/Kconfig b/trunk/arch/mips/vr41xx/Kconfig index 92f41f6f934a..c8dfd8092cab 100644 --- a/trunk/arch/mips/vr41xx/Kconfig +++ b/trunk/arch/mips/vr41xx/Kconfig @@ -6,6 +6,7 @@ config CASIO_E55 select ISA select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_LITTLE_ENDIAN + select GENERIC_HARDIRQS_NO__DO_IRQ config IBM_WORKPAD bool "Support for IBM WorkPad z50" @@ -15,6 +16,7 @@ config IBM_WORKPAD select ISA select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_LITTLE_ENDIAN + select GENERIC_HARDIRQS_NO__DO_IRQ config NEC_CMBVR4133 bool "Support for NEC CMB-VR4133" @@ -39,6 +41,7 @@ config TANBAC_TB022X select IRQ_CPU select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_LITTLE_ENDIAN + select GENERIC_HARDIRQS_NO__DO_IRQ help The TANBAC VR4131 multichip module(TB0225) and the TANBAC VR4131DIMM(TB0229) are MIPS-based platforms @@ -71,6 +74,7 @@ config VICTOR_MPC30X select IRQ_CPU select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_LITTLE_ENDIAN + select GENERIC_HARDIRQS_NO__DO_IRQ config ZAO_CAPCELLA bool "Support for ZAO Networks Capcella" @@ -80,6 +84,7 @@ config ZAO_CAPCELLA select IRQ_CPU select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_LITTLE_ENDIAN + select GENERIC_HARDIRQS_NO__DO_IRQ config PCI_VR41XX bool "Add PCI control unit support of NEC VR4100 series" diff --git a/trunk/arch/mips/vr41xx/common/icu.c b/trunk/arch/mips/vr41xx/common/icu.c index 54b92a74c7ac..c075261976c5 100644 --- a/trunk/arch/mips/vr41xx/common/icu.c +++ b/trunk/arch/mips/vr41xx/common/icu.c @@ -427,19 +427,12 @@ static void enable_sysint1_irq(unsigned int irq) icu1_set(MSYSINT1REG, 1 << SYSINT1_IRQ_TO_PIN(irq)); } -static void end_sysint1_irq(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) - icu1_set(MSYSINT1REG, 1 << SYSINT1_IRQ_TO_PIN(irq)); -} - static struct irq_chip sysint1_irq_type = { .typename = "SYSINT1", .ack = disable_sysint1_irq, .mask = disable_sysint1_irq, .mask_ack = disable_sysint1_irq, .unmask = enable_sysint1_irq, - .end = end_sysint1_irq, }; static void disable_sysint2_irq(unsigned int irq) @@ -452,19 +445,12 @@ static void enable_sysint2_irq(unsigned int irq) icu2_set(MSYSINT2REG, 1 << SYSINT2_IRQ_TO_PIN(irq)); } -static void end_sysint2_irq(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) - icu2_set(MSYSINT2REG, 1 << SYSINT2_IRQ_TO_PIN(irq)); -} - static struct irq_chip sysint2_irq_type = { .typename = "SYSINT2", .ack = disable_sysint2_irq, .mask = disable_sysint2_irq, .mask_ack = disable_sysint2_irq, .unmask = enable_sysint2_irq, - .end = end_sysint2_irq, }; static inline int set_sysint1_assign(unsigned int irq, unsigned char assign) diff --git a/trunk/arch/parisc/Kconfig b/trunk/arch/parisc/Kconfig index d2101237442e..0f9ff618c6d7 100644 --- a/trunk/arch/parisc/Kconfig +++ b/trunk/arch/parisc/Kconfig @@ -25,6 +25,14 @@ config RWSEM_GENERIC_SPINLOCK config RWSEM_XCHGADD_ALGORITHM bool +config ARCH_HAS_ILOG2_U32 + bool + default n + +config ARCH_HAS_ILOG2_U64 + bool + default n + config GENERIC_FIND_NEXT_BIT bool default y diff --git a/trunk/arch/parisc/hpux/sys_hpux.c b/trunk/arch/parisc/hpux/sys_hpux.c index 2e2dc4f2c853..d88309209f56 100644 --- a/trunk/arch/parisc/hpux/sys_hpux.c +++ b/trunk/arch/parisc/hpux/sys_hpux.c @@ -237,7 +237,7 @@ asmlinkage long hpux_fstatfs(unsigned int fd, struct hpux_statfs __user * buf) file = fget(fd); if (!file) goto out; - error = vfs_statfs_hpux(file->f_dentry, &tmp); + error = vfs_statfs_hpux(file->f_path.dentry, &tmp); if (!error && copy_to_user(buf, &tmp, sizeof(tmp))) error = -EFAULT; fput(file); diff --git a/trunk/arch/parisc/kernel/binfmt_elf32.c b/trunk/arch/parisc/kernel/binfmt_elf32.c index 1e64e7b88110..ecb10a4f63c6 100644 --- a/trunk/arch/parisc/kernel/binfmt_elf32.c +++ b/trunk/arch/parisc/kernel/binfmt_elf32.c @@ -75,7 +75,6 @@ struct elf_prpsinfo32 char pr_psargs[ELF_PRARGSZ]; /* initial part of arg list */ }; -#define elf_addr_t unsigned int #define init_elf_binfmt init_elf32_binfmt #define ELF_PLATFORM ("PARISC32\0") diff --git a/trunk/arch/parisc/mm/fault.c b/trunk/arch/parisc/mm/fault.c index 64785e46f93b..641f9c920eee 100644 --- a/trunk/arch/parisc/mm/fault.c +++ b/trunk/arch/parisc/mm/fault.c @@ -152,7 +152,7 @@ void do_page_fault(struct pt_regs *regs, unsigned long code, const struct exception_table_entry *fix; unsigned long acc_type; - if (in_interrupt() || !mm) + if (in_atomic() || !mm) goto no_context; down_read(&mm->mmap_sem); diff --git a/trunk/arch/parisc/mm/ioremap.c b/trunk/arch/parisc/mm/ioremap.c index 47a1d2ac9419..44b42c7f639d 100644 --- a/trunk/arch/parisc/mm/ioremap.c +++ b/trunk/arch/parisc/mm/ioremap.c @@ -9,110 +9,8 @@ #include #include #include -#include +#include #include -#include -#include - -static inline void -remap_area_pte(pte_t *pte, unsigned long address, unsigned long size, - unsigned long phys_addr, unsigned long flags) -{ - unsigned long end, pfn; - pgprot_t pgprot = __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | - _PAGE_ACCESSED | flags); - - address &= ~PMD_MASK; - - end = address + size; - if (end > PMD_SIZE) - end = PMD_SIZE; - - BUG_ON(address >= end); - - pfn = phys_addr >> PAGE_SHIFT; - do { - BUG_ON(!pte_none(*pte)); - - set_pte(pte, pfn_pte(pfn, pgprot)); - - address += PAGE_SIZE; - pfn++; - pte++; - } while (address && (address < end)); -} - -static inline int -remap_area_pmd(pmd_t *pmd, unsigned long address, unsigned long size, - unsigned long phys_addr, unsigned long flags) -{ - unsigned long end; - - address &= ~PGDIR_MASK; - - end = address + size; - if (end > PGDIR_SIZE) - end = PGDIR_SIZE; - - BUG_ON(address >= end); - - phys_addr -= address; - do { - pte_t *pte = pte_alloc_kernel(pmd, address); - if (!pte) - return -ENOMEM; - - remap_area_pte(pte, address, end - address, - address + phys_addr, flags); - - address = (address + PMD_SIZE) & PMD_MASK; - pmd++; - } while (address && (address < end)); - - return 0; -} - -static int -remap_area_pages(unsigned long address, unsigned long phys_addr, - unsigned long size, unsigned long flags) -{ - pgd_t *dir; - int error = 0; - unsigned long end = address + size; - - BUG_ON(address >= end); - - phys_addr -= address; - dir = pgd_offset_k(address); - - flush_cache_all(); - - do { - pud_t *pud; - pmd_t *pmd; - - error = -ENOMEM; - pud = pud_alloc(&init_mm, dir, address); - if (!pud) - break; - - pmd = pmd_alloc(&init_mm, pud, address); - if (!pmd) - break; - - if (remap_area_pmd(pmd, address, end - address, - phys_addr + address, flags)) - break; - - error = 0; - address = (address + PGDIR_SIZE) & PGDIR_MASK; - dir++; - } while (address && (address < end)); - - flush_tlb_all(); - - return error; -} /* * Generic mapping function (not visible outside): @@ -131,6 +29,7 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l void *addr; struct vm_struct *area; unsigned long offset, last_addr; + pgprot_t pgprot; #ifdef CONFIG_EISA unsigned long end = phys_addr + size - 1; @@ -164,6 +63,9 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l } } + pgprot = __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | + _PAGE_ACCESSED | flags); + /* * Mappings have to be page-aligned */ @@ -179,7 +81,8 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l return NULL; addr = area->addr; - if (remap_area_pages((unsigned long) addr, phys_addr, size, flags)) { + if (ioremap_page_range((unsigned long)addr, (unsigned long)addr + size, + phys_addr, pgprot)) { vfree(addr); return NULL; } diff --git a/trunk/arch/powerpc/Kconfig b/trunk/arch/powerpc/Kconfig index 291c95ac4b31..56c3c4065eb0 100644 --- a/trunk/arch/powerpc/Kconfig +++ b/trunk/arch/powerpc/Kconfig @@ -41,6 +41,14 @@ config RWSEM_XCHGADD_ALGORITHM bool default y +config ARCH_HAS_ILOG2_U32 + bool + default y + +config ARCH_HAS_ILOG2_U64 + bool + default y if 64BIT + config GENERIC_HWEIGHT bool default y diff --git a/trunk/arch/powerpc/kernel/crash.c b/trunk/arch/powerpc/kernel/crash.c index 89b03c8da9d2..d3f2080d2eee 100644 --- a/trunk/arch/powerpc/kernel/crash.c +++ b/trunk/arch/powerpc/kernel/crash.c @@ -46,61 +46,6 @@ int crashing_cpu = -1; static cpumask_t cpus_in_crash = CPU_MASK_NONE; cpumask_t cpus_in_sr = CPU_MASK_NONE; -static u32 *append_elf_note(u32 *buf, char *name, unsigned type, void *data, - size_t data_len) -{ - struct elf_note note; - - note.n_namesz = strlen(name) + 1; - note.n_descsz = data_len; - note.n_type = type; - memcpy(buf, ¬e, sizeof(note)); - buf += (sizeof(note) +3)/4; - memcpy(buf, name, note.n_namesz); - buf += (note.n_namesz + 3)/4; - memcpy(buf, data, note.n_descsz); - buf += (note.n_descsz + 3)/4; - - return buf; -} - -static void final_note(u32 *buf) -{ - struct elf_note note; - - note.n_namesz = 0; - note.n_descsz = 0; - note.n_type = 0; - memcpy(buf, ¬e, sizeof(note)); -} - -static void crash_save_this_cpu(struct pt_regs *regs, int cpu) -{ - struct elf_prstatus prstatus; - u32 *buf; - - if ((cpu < 0) || (cpu >= NR_CPUS)) - return; - - /* Using ELF notes here is opportunistic. - * I need a well defined structure format - * for the data I pass, and I need tags - * on the data to indicate what information I have - * squirrelled away. ELF notes happen to provide - * all of that that no need to invent something new. - */ - buf = (u32*)per_cpu_ptr(crash_notes, cpu); - if (!buf) - return; - - memset(&prstatus, 0, sizeof(prstatus)); - prstatus.pr_pid = current->pid; - elf_core_copy_regs(&prstatus.pr_reg, regs); - buf = append_elf_note(buf, "CORE", NT_PRSTATUS, &prstatus, - sizeof(prstatus)); - final_note(buf); -} - #ifdef CONFIG_SMP static atomic_t enter_on_soft_reset = ATOMIC_INIT(0); @@ -113,7 +58,7 @@ void crash_ipi_callback(struct pt_regs *regs) hard_irq_disable(); if (!cpu_isset(cpu, cpus_in_crash)) - crash_save_this_cpu(regs, cpu); + crash_save_cpu(regs, cpu); cpu_set(cpu, cpus_in_crash); /* @@ -306,7 +251,7 @@ void default_machine_crash_shutdown(struct pt_regs *regs) * such that another IPI will not be sent. */ crashing_cpu = smp_processor_id(); - crash_save_this_cpu(regs, crashing_cpu); + crash_save_cpu(regs, crashing_cpu); crash_kexec_prepare_cpus(crashing_cpu); cpu_set(crashing_cpu, cpus_in_crash); if (ppc_md.kexec_cpu_down) diff --git a/trunk/arch/powerpc/kernel/kprobes.c b/trunk/arch/powerpc/kernel/kprobes.c index 7b8d12b9026c..4657563f8813 100644 --- a/trunk/arch/powerpc/kernel/kprobes.c +++ b/trunk/arch/powerpc/kernel/kprobes.c @@ -85,7 +85,7 @@ void __kprobes arch_disarm_kprobe(struct kprobe *p) void __kprobes arch_remove_kprobe(struct kprobe *p) { mutex_lock(&kprobe_mutex); - free_insn_slot(p->ainsn.insn); + free_insn_slot(p->ainsn.insn, 0); mutex_unlock(&kprobe_mutex); } diff --git a/trunk/arch/powerpc/kernel/proc_ppc64.c b/trunk/arch/powerpc/kernel/proc_ppc64.c index f598cb519539..dd7001cacf75 100644 --- a/trunk/arch/powerpc/kernel/proc_ppc64.c +++ b/trunk/arch/powerpc/kernel/proc_ppc64.c @@ -83,7 +83,7 @@ __initcall(proc_ppc64_init); static loff_t page_map_seek( struct file *file, loff_t off, int whence) { loff_t new; - struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode); + struct proc_dir_entry *dp = PDE(file->f_path.dentry->d_inode); switch(whence) { case 0: @@ -106,13 +106,13 @@ static loff_t page_map_seek( struct file *file, loff_t off, int whence) static ssize_t page_map_read( struct file *file, char __user *buf, size_t nbytes, loff_t *ppos) { - struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode); + struct proc_dir_entry *dp = PDE(file->f_path.dentry->d_inode); return simple_read_from_buffer(buf, nbytes, ppos, dp->data, dp->size); } static int page_map_mmap( struct file *file, struct vm_area_struct *vma ) { - struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode); + struct proc_dir_entry *dp = PDE(file->f_path.dentry->d_inode); if ((vma->vm_end - vma->vm_start) > dp->size) return -EINVAL; diff --git a/trunk/arch/powerpc/kernel/rtas_flash.c b/trunk/arch/powerpc/kernel/rtas_flash.c index b9561d300516..0c4fcd34bfe5 100644 --- a/trunk/arch/powerpc/kernel/rtas_flash.c +++ b/trunk/arch/powerpc/kernel/rtas_flash.c @@ -101,7 +101,7 @@ struct flash_block_list_header { /* just the header of flash_block_list */ static struct flash_block_list_header rtas_firmware_flash_list = {0, NULL}; /* Use slab cache to guarantee 4k alignment */ -static kmem_cache_t *flash_block_cache = NULL; +static struct kmem_cache *flash_block_cache = NULL; #define FLASH_BLOCK_LIST_VERSION (1UL) @@ -193,7 +193,7 @@ static void free_flash_list(struct flash_block_list *f) static int rtas_flash_release(struct inode *inode, struct file *file) { - struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode); + struct proc_dir_entry *dp = PDE(file->f_path.dentry->d_inode); struct rtas_update_flash_t *uf; uf = (struct rtas_update_flash_t *) dp->data; @@ -255,7 +255,7 @@ static void get_flash_status_msg(int status, char *buf) static ssize_t rtas_flash_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { - struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode); + struct proc_dir_entry *dp = PDE(file->f_path.dentry->d_inode); struct rtas_update_flash_t *uf; char msg[RTAS_MSG_MAXLEN]; int msglen; @@ -286,7 +286,7 @@ static ssize_t rtas_flash_read(struct file *file, char __user *buf, } /* constructor for flash_block_cache */ -void rtas_block_ctor(void *ptr, kmem_cache_t *cache, unsigned long flags) +void rtas_block_ctor(void *ptr, struct kmem_cache *cache, unsigned long flags) { memset(ptr, 0, RTAS_BLK_SIZE); } @@ -299,7 +299,7 @@ void rtas_block_ctor(void *ptr, kmem_cache_t *cache, unsigned long flags) static ssize_t rtas_flash_write(struct file *file, const char __user *buffer, size_t count, loff_t *off) { - struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode); + struct proc_dir_entry *dp = PDE(file->f_path.dentry->d_inode); struct rtas_update_flash_t *uf; char *p; int next_free; @@ -391,7 +391,7 @@ static void manage_flash(struct rtas_manage_flash_t *args_buf) static ssize_t manage_flash_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { - struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode); + struct proc_dir_entry *dp = PDE(file->f_path.dentry->d_inode); struct rtas_manage_flash_t *args_buf; char msg[RTAS_MSG_MAXLEN]; int msglen; @@ -421,7 +421,7 @@ static ssize_t manage_flash_read(struct file *file, char __user *buf, static ssize_t manage_flash_write(struct file *file, const char __user *buf, size_t count, loff_t *off) { - struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode); + struct proc_dir_entry *dp = PDE(file->f_path.dentry->d_inode); struct rtas_manage_flash_t *args_buf; const char reject_str[] = "0"; const char commit_str[] = "1"; @@ -492,7 +492,7 @@ static int get_validate_flash_msg(struct rtas_validate_flash_t *args_buf, static ssize_t validate_flash_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { - struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode); + struct proc_dir_entry *dp = PDE(file->f_path.dentry->d_inode); struct rtas_validate_flash_t *args_buf; char msg[RTAS_MSG_MAXLEN]; int msglen; @@ -520,7 +520,7 @@ static ssize_t validate_flash_read(struct file *file, char __user *buf, static ssize_t validate_flash_write(struct file *file, const char __user *buf, size_t count, loff_t *off) { - struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode); + struct proc_dir_entry *dp = PDE(file->f_path.dentry->d_inode); struct rtas_validate_flash_t *args_buf; int rc; @@ -569,7 +569,7 @@ static ssize_t validate_flash_write(struct file *file, const char __user *buf, static int validate_flash_release(struct inode *inode, struct file *file) { - struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode); + struct proc_dir_entry *dp = PDE(file->f_path.dentry->d_inode); struct rtas_validate_flash_t *args_buf; args_buf = (struct rtas_validate_flash_t *) dp->data; diff --git a/trunk/arch/powerpc/kernel/signal_32.c b/trunk/arch/powerpc/kernel/signal_32.c index 320353f0926f..e4ebe1a6228e 100644 --- a/trunk/arch/powerpc/kernel/signal_32.c +++ b/trunk/arch/powerpc/kernel/signal_32.c @@ -36,7 +36,7 @@ #include #include #include -#include +#include #endif #include diff --git a/trunk/arch/powerpc/kernel/sysfs.c b/trunk/arch/powerpc/kernel/sysfs.c index 22123a0d5416..63ed265b7f09 100644 --- a/trunk/arch/powerpc/kernel/sysfs.c +++ b/trunk/arch/powerpc/kernel/sysfs.c @@ -239,7 +239,7 @@ static void unregister_cpu_online(unsigned int cpu) struct cpu *c = &per_cpu(cpu_devices, cpu); struct sys_device *s = &c->sysdev; - BUG_ON(c->no_control); + BUG_ON(!c->hotpluggable); if (!firmware_has_feature(FW_FEATURE_ISERIES) && cpu_has_feature(CPU_FTR_SMT)) @@ -424,10 +424,10 @@ static int __init topology_init(void) * CPU. For instance, the boot cpu might never be valid * for hotplugging. */ - if (!ppc_md.cpu_die) - c->no_control = 1; + if (ppc_md.cpu_die) + c->hotpluggable = 1; - if (cpu_online(cpu) || (c->no_control == 0)) { + if (cpu_online(cpu) || c->hotpluggable) { register_cpu(c, cpu); sysdev_create_file(&c->sysdev, &attr_physical_id); diff --git a/trunk/arch/powerpc/kernel/vdso.c b/trunk/arch/powerpc/kernel/vdso.c index c913ad5cad29..a4b28c73bba0 100644 --- a/trunk/arch/powerpc/kernel/vdso.c +++ b/trunk/arch/powerpc/kernel/vdso.c @@ -264,7 +264,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, /* Allocate a VMA structure and fill it up */ - vma = kmem_cache_zalloc(vm_area_cachep, SLAB_KERNEL); + vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL); if (vma == NULL) { rc = -ENOMEM; goto fail_mmapsem; diff --git a/trunk/arch/powerpc/kernel/vmlinux.lds.S b/trunk/arch/powerpc/kernel/vmlinux.lds.S index e8342d867536..04b98671a060 100644 --- a/trunk/arch/powerpc/kernel/vmlinux.lds.S +++ b/trunk/arch/powerpc/kernel/vmlinux.lds.S @@ -33,6 +33,7 @@ SECTIONS /* Text and gots */ .text : { + _text = .; *(.text .text.*) SCHED_TEXT LOCK_TEXT diff --git a/trunk/arch/powerpc/mm/hugetlbpage.c b/trunk/arch/powerpc/mm/hugetlbpage.c index 506d89768d45..89c836d54809 100644 --- a/trunk/arch/powerpc/mm/hugetlbpage.c +++ b/trunk/arch/powerpc/mm/hugetlbpage.c @@ -146,6 +146,11 @@ pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr) return hugepte_offset(hpdp, addr); } +int huge_pmd_unshare(struct mm_struct *mm, unsigned long *addr, pte_t *ptep) +{ + return 0; +} + static void free_hugepte_range(struct mmu_gather *tlb, hugepd_t *hpdp) { pte_t *hugepte = hugepd_page(*hpdp); @@ -1042,7 +1047,7 @@ int hash_huge_page(struct mm_struct *mm, unsigned long access, return err; } -static void zero_ctor(void *addr, kmem_cache_t *cache, unsigned long flags) +static void zero_ctor(void *addr, struct kmem_cache *cache, unsigned long flags) { memset(addr, 0, kmem_cache_size(cache)); } diff --git a/trunk/arch/powerpc/mm/init_64.c b/trunk/arch/powerpc/mm/init_64.c index 9a178549cbcf..d12a87ec5ae9 100644 --- a/trunk/arch/powerpc/mm/init_64.c +++ b/trunk/arch/powerpc/mm/init_64.c @@ -141,7 +141,7 @@ static int __init setup_kcore(void) } module_init(setup_kcore); -static void zero_ctor(void *addr, kmem_cache_t *cache, unsigned long flags) +static void zero_ctor(void *addr, struct kmem_cache *cache, unsigned long flags) { memset(addr, 0, kmem_cache_size(cache)); } @@ -166,9 +166,9 @@ static const char *pgtable_cache_name[ARRAY_SIZE(pgtable_cache_size)] = { /* Hugepages need one extra cache, initialized in hugetlbpage.c. We * can't put into the tables above, because HPAGE_SHIFT is not compile * time constant. */ -kmem_cache_t *pgtable_cache[ARRAY_SIZE(pgtable_cache_size)+1]; +struct kmem_cache *pgtable_cache[ARRAY_SIZE(pgtable_cache_size)+1]; #else -kmem_cache_t *pgtable_cache[ARRAY_SIZE(pgtable_cache_size)]; +struct kmem_cache *pgtable_cache[ARRAY_SIZE(pgtable_cache_size)]; #endif void pgtable_cache_init(void) diff --git a/trunk/arch/powerpc/platforms/cell/spufs/inode.c b/trunk/arch/powerpc/platforms/cell/spufs/inode.c index c7d010749a18..738b9244382f 100644 --- a/trunk/arch/powerpc/platforms/cell/spufs/inode.c +++ b/trunk/arch/powerpc/platforms/cell/spufs/inode.c @@ -40,7 +40,7 @@ #include "spufs.h" -static kmem_cache_t *spufs_inode_cache; +static struct kmem_cache *spufs_inode_cache; char *isolated_loader; static struct inode * @@ -48,7 +48,7 @@ spufs_alloc_inode(struct super_block *sb) { struct spufs_inode_info *ei; - ei = kmem_cache_alloc(spufs_inode_cache, SLAB_KERNEL); + ei = kmem_cache_alloc(spufs_inode_cache, GFP_KERNEL); if (!ei) return NULL; @@ -65,7 +65,7 @@ spufs_destroy_inode(struct inode *inode) } static void -spufs_init_once(void *p, kmem_cache_t * cachep, unsigned long flags) +spufs_init_once(void *p, struct kmem_cache * cachep, unsigned long flags) { struct spufs_inode_info *ei = p; @@ -205,7 +205,7 @@ static int spufs_dir_close(struct inode *inode, struct file *file) struct dentry *dir; int ret; - dir = file->f_dentry; + dir = file->f_path.dentry; parent = dir->d_parent->d_inode; ctx = SPUFS_I(dir->d_inode)->i_ctx; @@ -363,7 +363,7 @@ static int spufs_gang_close(struct inode *inode, struct file *file) struct dentry *dir; int ret; - dir = file->f_dentry; + dir = file->f_path.dentry; parent = dir->d_parent->d_inode; ret = spufs_rmgang(parent, dir); diff --git a/trunk/arch/powerpc/platforms/cell/spufs/syscalls.c b/trunk/arch/powerpc/platforms/cell/spufs/syscalls.c index a6d1ae4dc2a3..8e37bdf4dfda 100644 --- a/trunk/arch/powerpc/platforms/cell/spufs/syscalls.c +++ b/trunk/arch/powerpc/platforms/cell/spufs/syscalls.c @@ -46,7 +46,7 @@ static long do_spu_run(struct file *filp, if (filp->f_op != &spufs_context_fops) goto out; - i = SPUFS_I(filp->f_dentry->d_inode); + i = SPUFS_I(filp->f_path.dentry->d_inode); ret = spufs_run_spu(filp, i->i_ctx, &npc, &status); if (put_user(npc, unpc)) diff --git a/trunk/arch/powerpc/platforms/embedded6xx/ls_uart.c b/trunk/arch/powerpc/platforms/embedded6xx/ls_uart.c index 31bcdae84823..0e837762cc5b 100644 --- a/trunk/arch/powerpc/platforms/embedded6xx/ls_uart.c +++ b/trunk/arch/powerpc/platforms/embedded6xx/ls_uart.c @@ -14,7 +14,7 @@ static unsigned long avr_clock; static struct work_struct wd_work; -static void wd_stop(void *unused) +static void wd_stop(struct work_struct *unused) { const char string[] = "AAAAFFFFJJJJ>>>>VVVV>>>>ZZZZVVVVKKKK"; int i = 0, rescue = 8; @@ -122,7 +122,7 @@ static int __init ls_uarts_init(void) ls_uart_init(); - INIT_WORK(&wd_work, wd_stop, NULL); + INIT_WORK(&wd_work, wd_stop); schedule_work(&wd_work); return 0; diff --git a/trunk/arch/powerpc/platforms/iseries/mf.c b/trunk/arch/powerpc/platforms/iseries/mf.c index b5737d68d6c4..cff15ae24f6b 100644 --- a/trunk/arch/powerpc/platforms/iseries/mf.c +++ b/trunk/arch/powerpc/platforms/iseries/mf.c @@ -1178,7 +1178,7 @@ static ssize_t proc_mf_change_vmlinux(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { - struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode); + struct proc_dir_entry *dp = PDE(file->f_path.dentry->d_inode); ssize_t rc; dma_addr_t dma_addr; char *page; diff --git a/trunk/arch/powerpc/platforms/powermac/backlight.c b/trunk/arch/powerpc/platforms/powermac/backlight.c index afa593a8544a..c3a89414ddc0 100644 --- a/trunk/arch/powerpc/platforms/powermac/backlight.c +++ b/trunk/arch/powerpc/platforms/powermac/backlight.c @@ -18,11 +18,11 @@ #define OLD_BACKLIGHT_MAX 15 -static void pmac_backlight_key_worker(void *data); -static void pmac_backlight_set_legacy_worker(void *data); +static void pmac_backlight_key_worker(struct work_struct *work); +static void pmac_backlight_set_legacy_worker(struct work_struct *work); -static DECLARE_WORK(pmac_backlight_key_work, pmac_backlight_key_worker, NULL); -static DECLARE_WORK(pmac_backlight_set_legacy_work, pmac_backlight_set_legacy_worker, NULL); +static DECLARE_WORK(pmac_backlight_key_work, pmac_backlight_key_worker); +static DECLARE_WORK(pmac_backlight_set_legacy_work, pmac_backlight_set_legacy_worker); /* Although these variables are used in interrupt context, it makes no sense to * protect them. No user is able to produce enough key events per second and @@ -94,7 +94,7 @@ int pmac_backlight_curve_lookup(struct fb_info *info, int value) return level; } -static void pmac_backlight_key_worker(void *data) +static void pmac_backlight_key_worker(struct work_struct *work) { if (atomic_read(&kernel_backlight_disabled)) return; @@ -166,7 +166,7 @@ static int __pmac_backlight_set_legacy_brightness(int brightness) return error; } -static void pmac_backlight_set_legacy_worker(void *data) +static void pmac_backlight_set_legacy_worker(struct work_struct *work) { if (atomic_read(&kernel_backlight_disabled)) return; diff --git a/trunk/arch/powerpc/platforms/pseries/eeh_event.c b/trunk/arch/powerpc/platforms/pseries/eeh_event.c index 137077451316..49037edf7d39 100644 --- a/trunk/arch/powerpc/platforms/pseries/eeh_event.c +++ b/trunk/arch/powerpc/platforms/pseries/eeh_event.c @@ -37,8 +37,8 @@ /* EEH event workqueue setup. */ static DEFINE_SPINLOCK(eeh_eventlist_lock); LIST_HEAD(eeh_eventlist); -static void eeh_thread_launcher(void *); -DECLARE_WORK(eeh_event_wq, eeh_thread_launcher, NULL); +static void eeh_thread_launcher(struct work_struct *); +DECLARE_WORK(eeh_event_wq, eeh_thread_launcher); /* Serialize reset sequences for a given pci device */ DEFINE_MUTEX(eeh_event_mutex); @@ -103,7 +103,7 @@ static int eeh_event_handler(void * dummy) * eeh_thread_launcher * @dummy - unused */ -static void eeh_thread_launcher(void *dummy) +static void eeh_thread_launcher(struct work_struct *dummy) { if (kernel_thread(eeh_event_handler, NULL, CLONE_KERNEL) < 0) printk(KERN_ERR "Failed to start EEH daemon\n"); diff --git a/trunk/arch/powerpc/platforms/pseries/hvCall_inst.c b/trunk/arch/powerpc/platforms/pseries/hvCall_inst.c index 446e17d162a5..80181c4c49eb 100644 --- a/trunk/arch/powerpc/platforms/pseries/hvCall_inst.c +++ b/trunk/arch/powerpc/platforms/pseries/hvCall_inst.c @@ -85,7 +85,7 @@ static int hcall_inst_seq_open(struct inode *inode, struct file *file) rc = seq_open(file, &hcall_inst_seq_ops); seq = file->private_data; - seq->private = file->f_dentry->d_inode->i_private; + seq->private = file->f_path.dentry->d_inode->i_private; return rc; } diff --git a/trunk/arch/powerpc/platforms/pseries/scanlog.c b/trunk/arch/powerpc/platforms/pseries/scanlog.c index 77a5bb1d9c30..45368a57d7dd 100644 --- a/trunk/arch/powerpc/platforms/pseries/scanlog.c +++ b/trunk/arch/powerpc/platforms/pseries/scanlog.c @@ -47,7 +47,7 @@ static struct proc_dir_entry *proc_ppc64_scan_log_dump; /* The proc file */ static ssize_t scanlog_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { - struct inode * inode = file->f_dentry->d_inode; + struct inode * inode = file->f_path.dentry->d_inode; struct proc_dir_entry *dp; unsigned int *data; int status; diff --git a/trunk/arch/ppc/8260_io/fcc_enet.c b/trunk/arch/ppc/8260_io/fcc_enet.c index 2e1943e27819..709952c25f29 100644 --- a/trunk/arch/ppc/8260_io/fcc_enet.c +++ b/trunk/arch/ppc/8260_io/fcc_enet.c @@ -385,6 +385,7 @@ struct fcc_enet_private { phy_info_t *phy; struct work_struct phy_relink; struct work_struct phy_display_config; + struct net_device *dev; uint sequence_done; @@ -1391,10 +1392,11 @@ static phy_info_t *phy_info[] = { NULL }; -static void mii_display_status(void *data) +static void mii_display_status(struct work_struct *work) { - struct net_device *dev = data; - volatile struct fcc_enet_private *fep = dev->priv; + volatile struct fcc_enet_private *fep = + container_of(work, struct fcc_enet_private, phy_relink); + struct net_device *dev = fep->dev; uint s = fep->phy_status; if (!fep->link && !fep->old_link) { @@ -1428,10 +1430,12 @@ static void mii_display_status(void *data) printk(".\n"); } -static void mii_display_config(void *data) +static void mii_display_config(struct work_struct *work) { - struct net_device *dev = data; - volatile struct fcc_enet_private *fep = dev->priv; + volatile struct fcc_enet_private *fep = + container_of(work, struct fcc_enet_private, + phy_display_config); + struct net_device *dev = fep->dev; uint s = fep->phy_status; printk("%s: config: auto-negotiation ", dev->name); @@ -1758,8 +1762,9 @@ static int __init fec_enet_init(void) cep->phy_id_done = 0; cep->phy_addr = fip->fc_phyaddr; mii_queue(dev, mk_mii_read(MII_PHYSID1), mii_discover_phy); - INIT_WORK(&cep->phy_relink, mii_display_status, dev); - INIT_WORK(&cep->phy_display_config, mii_display_config, dev); + INIT_WORK(&cep->phy_relink, mii_display_status); + INIT_WORK(&cep->phy_display_config, mii_display_config); + cep->dev = dev; #endif /* CONFIG_USE_MDIO */ fip++; diff --git a/trunk/arch/ppc/8xx_io/cs4218_tdm.c b/trunk/arch/ppc/8xx_io/cs4218_tdm.c index 959d31c26cbb..c71ef3c2e7bf 100644 --- a/trunk/arch/ppc/8xx_io/cs4218_tdm.c +++ b/trunk/arch/ppc/8xx_io/cs4218_tdm.c @@ -2165,7 +2165,7 @@ static int sq_release(struct inode *inode, struct file *file) int rc = 0; if (sq.busy) - rc = sq_fsync(file, file->f_dentry); + rc = sq_fsync(file, file->f_path.dentry); sound.soft = sound.dsp; sound.hard = sound.dsp; sound_silence(); @@ -2218,25 +2218,25 @@ static int sq_ioctl(struct inode *inode, struct file *file, u_int cmd, return 0; case SNDCTL_DSP_POST: case SNDCTL_DSP_SYNC: - return sq_fsync(file, file->f_dentry); + return sq_fsync(file, file->f_path.dentry); /* ++TeSche: before changing any of these it's * probably wise to wait until sound playing has * settled down. */ case SNDCTL_DSP_SPEED: - sq_fsync(file, file->f_dentry); + sq_fsync(file, file->f_path.dentry); IOCTL_IN(arg, data); return IOCTL_OUT(arg, sound_set_speed(data)); case SNDCTL_DSP_STEREO: - sq_fsync(file, file->f_dentry); + sq_fsync(file, file->f_path.dentry); IOCTL_IN(arg, data); return IOCTL_OUT(arg, sound_set_stereo(data)); case SOUND_PCM_WRITE_CHANNELS: - sq_fsync(file, file->f_dentry); + sq_fsync(file, file->f_path.dentry); IOCTL_IN(arg, data); return IOCTL_OUT(arg, sound_set_stereo(data-1)+1); case SNDCTL_DSP_SETFMT: - sq_fsync(file, file->f_dentry); + sq_fsync(file, file->f_path.dentry); IOCTL_IN(arg, data); return IOCTL_OUT(arg, sound_set_format(data)); case SNDCTL_DSP_GETFMTS: diff --git a/trunk/arch/ppc/8xx_io/fec.c b/trunk/arch/ppc/8xx_io/fec.c index 2f9fa9e3d331..e6c28fb423b2 100644 --- a/trunk/arch/ppc/8xx_io/fec.c +++ b/trunk/arch/ppc/8xx_io/fec.c @@ -173,6 +173,7 @@ struct fec_enet_private { uint phy_speed; phy_info_t *phy; struct work_struct phy_task; + struct net_device *dev; uint sequence_done; @@ -1263,10 +1264,11 @@ static void mii_display_status(struct net_device *dev) printk(".\n"); } -static void mii_display_config(void *priv) +static void mii_display_config(struct work_struct *work) { - struct net_device *dev = (struct net_device *)priv; - struct fec_enet_private *fep = dev->priv; + struct fec_enet_private *fep = + container_of(work, struct fec_enet_private, phy_task); + struct net_device *dev = fep->dev; volatile uint *s = &(fep->phy_status); printk("%s: config: auto-negotiation ", dev->name); @@ -1295,10 +1297,11 @@ static void mii_display_config(void *priv) fep->sequence_done = 1; } -static void mii_relink(void *priv) +static void mii_relink(struct work_struct *work) { - struct net_device *dev = (struct net_device *)priv; - struct fec_enet_private *fep = dev->priv; + struct fec_enet_private *fep = + container_of(work, struct fec_enet_private, phy_task); + struct net_device *dev = fep->dev; int duplex; fep->link = (fep->phy_status & PHY_STAT_LINK) ? 1 : 0; @@ -1325,7 +1328,8 @@ static void mii_queue_relink(uint mii_reg, struct net_device *dev) { struct fec_enet_private *fep = dev->priv; - INIT_WORK(&fep->phy_task, mii_relink, (void *)dev); + fep->dev = dev; + INIT_WORK(&fep->phy_task, mii_relink); schedule_work(&fep->phy_task); } @@ -1333,7 +1337,8 @@ static void mii_queue_config(uint mii_reg, struct net_device *dev) { struct fec_enet_private *fep = dev->priv; - INIT_WORK(&fep->phy_task, mii_display_config, (void *)dev); + fep->dev = dev; + INIT_WORK(&fep->phy_task, mii_display_config); schedule_work(&fep->phy_task); } diff --git a/trunk/arch/ppc/Kconfig b/trunk/arch/ppc/Kconfig index edf71a4ecc95..692b5ba53209 100644 --- a/trunk/arch/ppc/Kconfig +++ b/trunk/arch/ppc/Kconfig @@ -19,6 +19,14 @@ config RWSEM_XCHGADD_ALGORITHM bool default y +config ARCH_HAS_ILOG2_U32 + bool + default y + +config ARCH_HAS_ILOG2_U64 + bool + default n + config GENERIC_HWEIGHT bool default y @@ -52,6 +60,11 @@ config ARCH_MAY_HAVE_PC_FDC bool default y +config GENERIC_BUG + bool + default y + depends on BUG + source "init/Kconfig" menu "Processor" diff --git a/trunk/arch/ppc/kernel/traps.c b/trunk/arch/ppc/kernel/traps.c index 2f835b9e95e4..810f7aa72e92 100644 --- a/trunk/arch/ppc/kernel/traps.c +++ b/trunk/arch/ppc/kernel/traps.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -559,64 +560,9 @@ static void emulate_single_step(struct pt_regs *regs) } } -/* - * Look through the list of trap instructions that are used for BUG(), - * BUG_ON() and WARN_ON() and see if we hit one. At this point we know - * that the exception was caused by a trap instruction of some kind. - * Returns 1 if we should continue (i.e. it was a WARN_ON) or 0 - * otherwise. - */ -extern struct bug_entry __start___bug_table[], __stop___bug_table[]; - -#ifndef CONFIG_MODULES -#define module_find_bug(x) NULL -#endif - -struct bug_entry *find_bug(unsigned long bugaddr) -{ - struct bug_entry *bug; - - for (bug = __start___bug_table; bug < __stop___bug_table; ++bug) - if (bugaddr == bug->bug_addr) - return bug; - return module_find_bug(bugaddr); -} - -int check_bug_trap(struct pt_regs *regs) +int is_valid_bugaddr(unsigned long addr) { - struct bug_entry *bug; - unsigned long addr; - - if (regs->msr & MSR_PR) - return 0; /* not in kernel */ - addr = regs->nip; /* address of trap instruction */ - if (addr < PAGE_OFFSET) - return 0; - bug = find_bug(regs->nip); - if (bug == NULL) - return 0; - if (bug->line & BUG_WARNING_TRAP) { - /* this is a WARN_ON rather than BUG/BUG_ON */ -#ifdef CONFIG_XMON - xmon_printf(KERN_ERR "Badness in %s at %s:%ld\n", - bug->function, bug->file, - bug->line & ~BUG_WARNING_TRAP); -#endif /* CONFIG_XMON */ - printk(KERN_ERR "Badness in %s at %s:%ld\n", - bug->function, bug->file, - bug->line & ~BUG_WARNING_TRAP); - dump_stack(); - return 1; - } -#ifdef CONFIG_XMON - xmon_printf(KERN_CRIT "kernel BUG in %s at %s:%ld!\n", - bug->function, bug->file, bug->line); - xmon(regs); -#endif /* CONFIG_XMON */ - printk(KERN_CRIT "kernel BUG in %s at %s:%ld!\n", - bug->function, bug->file, bug->line); - - return 0; + return addr >= PAGE_OFFSET; } void program_check_exception(struct pt_regs *regs) @@ -671,7 +617,9 @@ void program_check_exception(struct pt_regs *regs) /* trap exception */ if (debugger_bpt(regs)) return; - if (check_bug_trap(regs)) { + + if (!(regs->msr & MSR_PR) && /* not user-mode */ + report_bug(regs->nip) == BUG_TRAP_TYPE_WARN) { regs->nip += 4; return; } diff --git a/trunk/arch/ppc/kernel/vmlinux.lds.S b/trunk/arch/ppc/kernel/vmlinux.lds.S index 16e8661e1fec..61921268a0d0 100644 --- a/trunk/arch/ppc/kernel/vmlinux.lds.S +++ b/trunk/arch/ppc/kernel/vmlinux.lds.S @@ -31,6 +31,7 @@ SECTIONS .plt : { *(.plt) } .text : { + _text = .; *(.text) SCHED_TEXT LOCK_TEXT diff --git a/trunk/arch/s390/Kconfig b/trunk/arch/s390/Kconfig index 583d9ff0a571..45e47bfb68a9 100644 --- a/trunk/arch/s390/Kconfig +++ b/trunk/arch/s390/Kconfig @@ -22,6 +22,14 @@ config RWSEM_XCHGADD_ALGORITHM bool default y +config ARCH_HAS_ILOG2_U32 + bool + default n + +config ARCH_HAS_ILOG2_U64 + bool + default n + config GENERIC_HWEIGHT bool default y diff --git a/trunk/arch/s390/appldata/appldata_base.c b/trunk/arch/s390/appldata/appldata_base.c index af1e8fc7d985..b8c237290263 100644 --- a/trunk/arch/s390/appldata/appldata_base.c +++ b/trunk/arch/s390/appldata/appldata_base.c @@ -92,8 +92,8 @@ static int appldata_timer_active; * Work queue */ static struct workqueue_struct *appldata_wq; -static void appldata_work_fn(void *data); -static DECLARE_WORK(appldata_work, appldata_work_fn, NULL); +static void appldata_work_fn(struct work_struct *work); +static DECLARE_WORK(appldata_work, appldata_work_fn); /* @@ -125,7 +125,7 @@ static void appldata_timer_function(unsigned long data) * * call data gathering function for each (active) module */ -static void appldata_work_fn(void *data) +static void appldata_work_fn(struct work_struct *work) { struct list_head *lh; struct appldata_ops *ops; @@ -561,7 +561,6 @@ appldata_offline_cpu(int cpu) spin_unlock(&appldata_timer_lock); } -#ifdef CONFIG_HOTPLUG_CPU static int __cpuinit appldata_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu) @@ -582,7 +581,6 @@ appldata_cpu_notify(struct notifier_block *self, static struct notifier_block appldata_nb = { .notifier_call = appldata_cpu_notify, }; -#endif /* * appldata_init() diff --git a/trunk/arch/s390/hypfs/inode.c b/trunk/arch/s390/hypfs/inode.c index cd702ae45d6d..b6716c4b9934 100644 --- a/trunk/arch/s390/hypfs/inode.c +++ b/trunk/arch/s390/hypfs/inode.c @@ -109,7 +109,7 @@ static void hypfs_drop_inode(struct inode *inode) static int hypfs_open(struct inode *inode, struct file *filp) { - char *data = filp->f_dentry->d_inode->i_private; + char *data = filp->f_path.dentry->d_inode->i_private; struct hypfs_sb_info *fs_info; if (filp->f_mode & FMODE_WRITE) { @@ -174,7 +174,7 @@ static ssize_t hypfs_aio_write(struct kiocb *iocb, const struct iovec *iov, struct hypfs_sb_info *fs_info; size_t count = iov_length(iov, nr_segs); - sb = iocb->ki_filp->f_dentry->d_inode->i_sb; + sb = iocb->ki_filp->f_path.dentry->d_inode->i_sb; fs_info = sb->s_fs_info; /* * Currently we only allow one update per second for two reasons: diff --git a/trunk/arch/s390/kernel/binfmt_elf32.c b/trunk/arch/s390/kernel/binfmt_elf32.c index 9565a2dcfadc..5c46054195cb 100644 --- a/trunk/arch/s390/kernel/binfmt_elf32.c +++ b/trunk/arch/s390/kernel/binfmt_elf32.c @@ -176,7 +176,6 @@ struct elf_prpsinfo32 #include -#define elf_addr_t u32 /* #define init_elf_binfmt init_elf32_binfmt */ diff --git a/trunk/arch/s390/kernel/debug.c b/trunk/arch/s390/kernel/debug.c index 43f3d0c7e132..ef5266fbce62 100644 --- a/trunk/arch/s390/kernel/debug.c +++ b/trunk/arch/s390/kernel/debug.c @@ -603,13 +603,13 @@ debug_open(struct inode *inode, struct file *file) debug_info_t *debug_info, *debug_info_snapshot; down(&debug_lock); - debug_info = file->f_dentry->d_inode->i_private; + debug_info = file->f_path.dentry->d_inode->i_private; /* find debug view */ for (i = 0; i < DEBUG_MAX_VIEWS; i++) { if (!debug_info->views[i]) continue; else if (debug_info->debugfs_entries[i] == - file->f_dentry) { + file->f_path.dentry) { goto found; /* found view ! */ } } diff --git a/trunk/arch/s390/kernel/kprobes.c b/trunk/arch/s390/kernel/kprobes.c index 67914fe7f317..576368c4f605 100644 --- a/trunk/arch/s390/kernel/kprobes.c +++ b/trunk/arch/s390/kernel/kprobes.c @@ -200,7 +200,7 @@ void __kprobes arch_disarm_kprobe(struct kprobe *p) void __kprobes arch_remove_kprobe(struct kprobe *p) { mutex_lock(&kprobe_mutex); - free_insn_slot(p->ainsn.insn); + free_insn_slot(p->ainsn.insn, 0); mutex_unlock(&kprobe_mutex); } diff --git a/trunk/arch/s390/lib/uaccess_std.c b/trunk/arch/s390/lib/uaccess_std.c index 2d549ed2e113..bbaca66fa293 100644 --- a/trunk/arch/s390/lib/uaccess_std.c +++ b/trunk/arch/s390/lib/uaccess_std.c @@ -11,7 +11,7 @@ #include #include -#include +#include #include #ifndef __s390x__ @@ -258,7 +258,7 @@ int futex_atomic_op(int op, int __user *uaddr, int oparg, int *old) { int oldval = 0, newval, ret; - inc_preempt_count(); + pagefault_disable(); switch (op) { case FUTEX_OP_SET: @@ -284,7 +284,7 @@ int futex_atomic_op(int op, int __user *uaddr, int oparg, int *old) default: ret = -ENOSYS; } - dec_preempt_count(); + pagefault_enable(); *old = oldval; return ret; } diff --git a/trunk/arch/s390/mm/ioremap.c b/trunk/arch/s390/mm/ioremap.c index 0f6e9ecbefe2..3d2100a4e209 100644 --- a/trunk/arch/s390/mm/ioremap.c +++ b/trunk/arch/s390/mm/ioremap.c @@ -15,87 +15,8 @@ #include #include -#include +#include #include -#include -#include - -static inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned long size, - unsigned long phys_addr, unsigned long flags) -{ - unsigned long end; - unsigned long pfn; - - address &= ~PMD_MASK; - end = address + size; - if (end > PMD_SIZE) - end = PMD_SIZE; - if (address >= end) - BUG(); - pfn = phys_addr >> PAGE_SHIFT; - do { - if (!pte_none(*pte)) { - printk("remap_area_pte: page already exists\n"); - BUG(); - } - set_pte(pte, pfn_pte(pfn, __pgprot(flags))); - address += PAGE_SIZE; - pfn++; - pte++; - } while (address && (address < end)); -} - -static inline int remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size, - unsigned long phys_addr, unsigned long flags) -{ - unsigned long end; - - address &= ~PGDIR_MASK; - end = address + size; - if (end > PGDIR_SIZE) - end = PGDIR_SIZE; - phys_addr -= address; - if (address >= end) - BUG(); - do { - pte_t * pte = pte_alloc_kernel(pmd, address); - if (!pte) - return -ENOMEM; - remap_area_pte(pte, address, end - address, address + phys_addr, flags); - address = (address + PMD_SIZE) & PMD_MASK; - pmd++; - } while (address && (address < end)); - return 0; -} - -static int remap_area_pages(unsigned long address, unsigned long phys_addr, - unsigned long size, unsigned long flags) -{ - int error; - pgd_t * dir; - unsigned long end = address + size; - - phys_addr -= address; - dir = pgd_offset(&init_mm, address); - flush_cache_all(); - if (address >= end) - BUG(); - do { - pmd_t *pmd; - pmd = pmd_alloc(&init_mm, dir, address); - error = -ENOMEM; - if (!pmd) - break; - if (remap_area_pmd(pmd, address, end - address, - phys_addr + address, flags)) - break; - error = 0; - address = (address + PGDIR_SIZE) & PGDIR_MASK; - dir++; - } while (address && (address < end)); - flush_tlb_all(); - return 0; -} /* * Generic mapping function (not visible outside): @@ -122,7 +43,8 @@ void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flag if (!area) return NULL; addr = area->addr; - if (remap_area_pages((unsigned long) addr, phys_addr, size, flags)) { + if (ioremap_page_range((unsigned long)addr, (unsigned long)addr + size, + phys_addr, __pgprot(flags))) { vfree(addr); return NULL; } diff --git a/trunk/arch/sh/Kconfig b/trunk/arch/sh/Kconfig index bffc7e176970..8e24c40662e3 100644 --- a/trunk/arch/sh/Kconfig +++ b/trunk/arch/sh/Kconfig @@ -51,6 +51,22 @@ config GENERIC_TIME config ARCH_MAY_HAVE_PC_FDC bool +config STACKTRACE_SUPPORT + bool + default y + +config LOCKDEP_SUPPORT + bool + default y + +config ARCH_HAS_ILOG2_U32 + bool + default n + +config ARCH_HAS_ILOG2_U64 + bool + default n + source "init/Kconfig" menu "System type" @@ -219,6 +235,20 @@ config SH_SHMIN help Select SHMIN if configuring for the SHMIN board. +config SH_7206_SOLUTION_ENGINE + bool "SolutionEngine7206" + select CPU_SUBTYPE_SH7206 + help + Select 7206 SolutionEngine if configuring for a Hitachi SH7206 + evaluation board. + +config SH_7619_SOLUTION_ENGINE + bool "SolutionEngine7619" + select CPU_SUBTYPE_SH7619 + help + Select 7619 SolutionEngine if configuring for a Hitachi SH7619 + evaluation board. + config SH_UNKNOWN bool "BareCPU" help @@ -280,12 +310,20 @@ config CF_BASE_ADDR menu "Processor features" -config CPU_LITTLE_ENDIAN - bool "Little Endian" +choice + prompt "Endianess selection" + default CPU_LITTLE_ENDIAN help Some SuperH machines can be configured for either little or big - endian byte order. These modes require different kernels. Say Y if - your machine is little endian, N if it's a big endian machine. + endian byte order. These modes require different kernels. + +config CPU_LITTLE_ENDIAN + bool "Little Endian" + +config CPU_BIG_ENDIAN + bool "Big Endian" + +endchoice config SH_FPU bool "FPU support" @@ -345,6 +383,9 @@ config CPU_HAS_MASKREG_IRQ config CPU_HAS_INTC2_IRQ bool +config CPU_HAS_IPR_IRQ + bool + config CPU_HAS_SR_RB bool "CPU has SR.RB" depends on CPU_SH3 || CPU_SH4 @@ -357,6 +398,9 @@ config CPU_HAS_SR_RB See for further information on SR.RB and register banking in the kernel in general. +config CPU_HAS_PTEA + bool + endmenu menu "Timer support" @@ -364,10 +408,25 @@ depends on !GENERIC_TIME config SH_TMU bool "TMU timer support" + depends on CPU_SH3 || CPU_SH4 default y help This enables the use of the TMU as the system timer. +config SH_CMT + bool "CMT timer support" + depends on CPU_SH2 + default y + help + This enables the use of the CMT as the system timer. + +config SH_MTU2 + bool "MTU2 timer support" + depends on CPU_SH2A + default n + help + This enables the use of the MTU2 as the system timer. + endmenu source "arch/sh/boards/renesas/hs7751rvoip/Kconfig" @@ -376,19 +435,52 @@ source "arch/sh/boards/renesas/rts7751r2d/Kconfig" source "arch/sh/boards/renesas/r7780rp/Kconfig" +config SH_TIMER_IRQ + int + default "28" if CPU_SUBTYPE_SH7780 + default "86" if CPU_SUBTYPE_SH7619 + default "140" if CPU_SUBTYPE_SH7206 + default "16" + +config NO_IDLE_HZ + bool "Dynamic tick timer" + help + Select this option if you want to disable continuous timer ticks + and have them programmed to occur as required. This option saves + power as the system can remain in idle state for longer. + + By default dynamic tick is disabled during the boot, and can be + manually enabled with: + + echo 1 > /sys/devices/system/timer/timer0/dyn_tick + + Alternatively, if you want dynamic tick automatically enabled + during boot, pass "dyntick=enable" via the kernel command string. + + Please note that dynamic tick may affect the accuracy of + timekeeping on some platforms depending on the implementation. + config SH_PCLK_FREQ int "Peripheral clock frequency (in Hz)" + default "27000000" if CPU_SUBTYPE_SH73180 || CPU_SUBTYPE_SH7343 + default "31250000" if CPU_SUBTYPE_SH7619 + default "33333333" if CPU_SUBTYPE_SH7300 || CPU_SUBTYPE_SH7770 || \ + CPU_SUBTYPE_SH7760 || CPU_SUBTYPE_SH7705 || \ + CPU_SUBTYPE_SH7206 default "50000000" if CPU_SUBTYPE_SH7750 || CPU_SUBTYPE_SH7780 default "60000000" if CPU_SUBTYPE_SH7751 - default "33333333" if CPU_SUBTYPE_SH7300 || CPU_SUBTYPE_SH7770 || \ - CPU_SUBTYPE_SH7760 || CPU_SUBTYPE_SH7705 - default "27000000" if CPU_SUBTYPE_SH73180 || CPU_SUBTYPE_SH7343 default "66000000" if CPU_SUBTYPE_SH4_202 help This option is used to specify the peripheral clock frequency. This is necessary for determining the reference clock value on platforms lacking an RTC. +config SH_CLK_MD + int "CPU Mode Pin Setting" + depends on CPU_SUBTYPE_SH7619 || CPU_SUBTYPE_SH7206 + help + MD2 - MD0 Setting. + menu "CPU Frequency scaling" source "drivers/cpufreq/Kconfig" @@ -421,6 +513,8 @@ config HEARTBEAT behavior is platform-dependent, but normally the flash frequency is a hyperbolic function of the 5-minute load average. +source "arch/sh/drivers/Kconfig" + endmenu config ISA_DMA_API diff --git a/trunk/arch/sh/Kconfig.debug b/trunk/arch/sh/Kconfig.debug index 48479e014dac..66a25ef4ef1b 100644 --- a/trunk/arch/sh/Kconfig.debug +++ b/trunk/arch/sh/Kconfig.debug @@ -1,5 +1,9 @@ menu "Kernel hacking" +config TRACE_IRQFLAGS_SUPPORT + bool + default y + source "lib/Kconfig.debug" config SH_STANDARD_BIOS @@ -17,7 +21,18 @@ config SH_STANDARD_BIOS config EARLY_SCIF_CONSOLE bool "Use early SCIF console" - depends on CPU_SH4 || CPU_SH2A && !SH_STANDARD_BIOS + help + This enables an early console using a fixed SCIF port. This can + be used by platforms that are either not running the SH + standard BIOS, or do not wish to use the BIOS callbacks for the + serial I/O. + +config EARLY_SCIF_CONSOLE_PORT + hex "SCIF port for early console" + depends on EARLY_SCIF_CONSOLE + default "0xffe00000" if CPU_SUBTYPE_SH7780 + default "0xfffe9800" if CPU_SUBTYPE_SH72060 + default "0xffe80000" if CPU_SH4 config EARLY_PRINTK bool "Early printk support" @@ -30,6 +45,11 @@ config EARLY_PRINTK when the kernel may crash or hang before the serial console is initialised. If unsure, say N. + On devices that are running SH-IPL and want to keep the port + initialization consistent while not using the BIOS callbacks, + select both the EARLY_SCIF_CONSOLE and SH_STANDARD_BIOS, using + the kernel command line option to toggle back and forth. + config DEBUG_STACKOVERFLOW bool "Check for stack overflows" depends on DEBUG_KERNEL diff --git a/trunk/arch/sh/Makefile b/trunk/arch/sh/Makefile index 26d62ff51a64..d10bba5e1074 100644 --- a/trunk/arch/sh/Makefile +++ b/trunk/arch/sh/Makefile @@ -13,10 +13,6 @@ # for "archclean" and "archdep" for cleaning up and making dependencies for # this architecture # - -cflags-y := -mb -cflags-$(CONFIG_CPU_LITTLE_ENDIAN) := -ml - isa-y := any isa-$(CONFIG_SH_DSP) := sh isa-$(CONFIG_CPU_SH2) := sh2 @@ -38,13 +34,16 @@ isa-y := $(isa-y)-nofpu endif endif -cflags-y += $(call as-option,-Wa$(comma)-isa=$(isa-y),) - -cflags-$(CONFIG_CPU_SH2) += -m2 -cflags-$(CONFIG_CPU_SH3) += -m3 -cflags-$(CONFIG_CPU_SH4) += -m4 \ +cflags-$(CONFIG_CPU_SH2) := -m2 +cflags-$(CONFIG_CPU_SH3) := -m3 +cflags-$(CONFIG_CPU_SH4) := -m4 \ $(call cc-option,-mno-implicit-fp,-m4-nofpu) -cflags-$(CONFIG_CPU_SH4A) += $(call cc-option,-m4a-nofpu,) +cflags-$(CONFIG_CPU_SH4A) := -m4a $(call cc-option,-m4a-nofpu,) + +cflags-$(CONFIG_CPU_BIG_ENDIAN) += -mb +cflags-$(CONFIG_CPU_LITTLE_ENDIAN) += -ml + +cflags-y += $(call as-option,-Wa$(comma)-isa=$(isa-y),) -ffreestanding cflags-$(CONFIG_SH_DSP) += -Wa,-dsp cflags-$(CONFIG_SH_KGDB) += -g @@ -59,7 +58,9 @@ OBJCOPYFLAGS := -O binary -R .note -R .comment -R .stab -R .stabstr -S # never be used by anyone. Use a board-specific defconfig that has a # reasonable chance of being current instead. # -KBUILD_DEFCONFIG := rts7751r2d_defconfig +KBUILD_DEFCONFIG := r7780rp_defconfig + +KBUILD_IMAGE := arch/sh/boot/zImage # # Choosing incompatible machines durings configuration will result in @@ -109,6 +110,8 @@ machdir-$(CONFIG_SH_SH4202_MICRODEV) := superh/microdev machdir-$(CONFIG_SH_LANDISK) := landisk machdir-$(CONFIG_SH_TITAN) := titan machdir-$(CONFIG_SH_SHMIN) := shmin +machdir-$(CONFIG_SH_7206_SOLUTION_ENGINE) := se/7206 +machdir-$(CONFIG_SH_7619_SOLUTION_ENGINE) := se/7619 machdir-$(CONFIG_SH_UNKNOWN) := unknown incdir-y := $(notdir $(machdir-y)) @@ -124,6 +127,7 @@ core-$(CONFIG_HD64465) += arch/sh/cchips/hd6446x/hd64465/ core-$(CONFIG_VOYAGERGX) += arch/sh/cchips/voyagergx/ cpuincdir-$(CONFIG_CPU_SH2) := cpu-sh2 +cpuincdir-$(CONFIG_CPU_SH2A) := cpu-sh2a cpuincdir-$(CONFIG_CPU_SH3) := cpu-sh3 cpuincdir-$(CONFIG_CPU_SH4) := cpu-sh4 diff --git a/trunk/arch/sh/boards/renesas/r7780rp/Makefile b/trunk/arch/sh/boards/renesas/r7780rp/Makefile index f1776d027978..574b0316ed56 100644 --- a/trunk/arch/sh/boards/renesas/r7780rp/Makefile +++ b/trunk/arch/sh/boards/renesas/r7780rp/Makefile @@ -3,4 +3,6 @@ # obj-y := setup.o io.o irq.o -obj-$(CONFIG_HEARTBEAT) += led.o + +obj-$(CONFIG_HEARTBEAT) += led.o +obj-$(CONFIG_PUSH_SWITCH) += psw.o diff --git a/trunk/arch/sh/boards/renesas/r7780rp/irq.c b/trunk/arch/sh/boards/renesas/r7780rp/irq.c index aa15ec5bc69e..cc381e197783 100644 --- a/trunk/arch/sh/boards/renesas/r7780rp/irq.c +++ b/trunk/arch/sh/boards/renesas/r7780rp/irq.c @@ -10,6 +10,7 @@ */ #include #include +#include #include #include diff --git a/trunk/arch/sh/boards/renesas/r7780rp/psw.c b/trunk/arch/sh/boards/renesas/r7780rp/psw.c new file mode 100644 index 000000000000..c844dfa5d58d --- /dev/null +++ b/trunk/arch/sh/boards/renesas/r7780rp/psw.c @@ -0,0 +1,122 @@ +/* + * arch/sh/boards/renesas/r7780rp/psw.c + * + * push switch support for RDBRP-1/RDBREVRP-1 debug boards. + * + * Copyright (C) 2006 Paul Mundt + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include +#include +#include +#include + +static irqreturn_t psw_irq_handler(int irq, void *arg) +{ + struct platform_device *pdev = arg; + struct push_switch *psw = platform_get_drvdata(pdev); + struct push_switch_platform_info *psw_info = pdev->dev.platform_data; + unsigned int l, mask; + int ret = 0; + + l = ctrl_inw(PA_DBSW); + + /* Nothing to do if there's no state change */ + if (psw->state) { + ret = 1; + goto out; + } + + mask = l & 0x70; + /* Figure out who raised it */ + if (mask & (1 << psw_info->bit)) { + psw->state = !!(mask & (1 << psw_info->bit)); + if (psw->state) /* debounce */ + mod_timer(&psw->debounce, jiffies + 50); + + ret = 1; + } + +out: + /* Clear the switch IRQs */ + l |= (0x7 << 12); + ctrl_outw(l, PA_DBSW); + + return IRQ_RETVAL(ret); +} + +static struct resource psw_resources[] = { + [0] = { + .start = IRQ_PSW, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct push_switch_platform_info s2_platform_data = { + .name = "s2", + .bit = 6, + .irq_flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | + IRQF_SHARED, + .irq_handler = psw_irq_handler, +}; + +static struct platform_device s2_switch_device = { + .name = "push-switch", + .id = 0, + .num_resources = ARRAY_SIZE(psw_resources), + .resource = psw_resources, + .dev = { + .platform_data = &s2_platform_data, + }, +}; + +static struct push_switch_platform_info s3_platform_data = { + .name = "s3", + .bit = 5, + .irq_flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | + IRQF_SHARED, + .irq_handler = psw_irq_handler, +}; + +static struct platform_device s3_switch_device = { + .name = "push-switch", + .id = 1, + .num_resources = ARRAY_SIZE(psw_resources), + .resource = psw_resources, + .dev = { + .platform_data = &s3_platform_data, + }, +}; + +static struct push_switch_platform_info s4_platform_data = { + .name = "s4", + .bit = 4, + .irq_flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | + IRQF_SHARED, + .irq_handler = psw_irq_handler, +}; + +static struct platform_device s4_switch_device = { + .name = "push-switch", + .id = 2, + .num_resources = ARRAY_SIZE(psw_resources), + .resource = psw_resources, + .dev = { + .platform_data = &s4_platform_data, + }, +}; + +static struct platform_device *psw_devices[] = { + &s2_switch_device, &s3_switch_device, &s4_switch_device, +}; + +static int __init psw_init(void) +{ + return platform_add_devices(psw_devices, ARRAY_SIZE(psw_devices)); +} +module_init(psw_init); diff --git a/trunk/arch/sh/boards/renesas/r7780rp/setup.c b/trunk/arch/sh/boards/renesas/r7780rp/setup.c index c331caeb694b..9f89c8de9db9 100644 --- a/trunk/arch/sh/boards/renesas/r7780rp/setup.c +++ b/trunk/arch/sh/boards/renesas/r7780rp/setup.c @@ -44,8 +44,37 @@ static struct platform_device m66596_usb_host_device = { .resource = m66596_usb_host_resources, }; +static struct resource cf_ide_resources[] = { + [0] = { + .start = 0x1f0, + .end = 0x1f0 + 8, + .flags = IORESOURCE_IO, + }, + [1] = { + .start = 0x1f0 + 0x206, + .end = 0x1f0 + 8 + 0x206 + 8, + .flags = IORESOURCE_IO, + }, + [2] = { +#ifdef CONFIG_SH_R7780MP + .start = 1, +#else + .start = 4, +#endif + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device cf_ide_device = { + .name = "pata_platform", + .id = -1, + .num_resources = ARRAY_SIZE(cf_ide_resources), + .resource = cf_ide_resources, +}; + static struct platform_device *r7780rp_devices[] __initdata = { &m66596_usb_host_device, + &cf_ide_device, }; static int __init r7780rp_devices_setup(void) diff --git a/trunk/arch/sh/boards/se/7206/Makefile b/trunk/arch/sh/boards/se/7206/Makefile new file mode 100644 index 000000000000..63950f4f2453 --- /dev/null +++ b/trunk/arch/sh/boards/se/7206/Makefile @@ -0,0 +1,7 @@ +# +# Makefile for the 7206 SolutionEngine specific parts of the kernel +# + +obj-y := setup.o io.o irq.o +obj-$(CONFIG_HEARTBEAT) += led.o + diff --git a/trunk/arch/sh/boards/se/7206/io.c b/trunk/arch/sh/boards/se/7206/io.c new file mode 100644 index 000000000000..b557273e0cbe --- /dev/null +++ b/trunk/arch/sh/boards/se/7206/io.c @@ -0,0 +1,123 @@ +/* $Id: io.c,v 1.5 2004/02/22 23:08:43 kkojima Exp $ + * + * linux/arch/sh/boards/se/7206/io.c + * + * Copyright (C) 2006 Yoshinori Sato + * + * I/O routine for Hitachi 7206 SolutionEngine. + * + */ + +#include +#include +#include +#include + + +static inline void delay(void) +{ + ctrl_inw(0x20000000); /* P2 ROM Area */ +} + +/* MS7750 requires special versions of in*, out* routines, since + PC-like io ports are located at upper half byte of 16-bit word which + can be accessed only with 16-bit wide. */ + +static inline volatile __u16 * +port2adr(unsigned int port) +{ + if (port >= 0x2000) + return (volatile __u16 *) (PA_MRSHPC + (port - 0x2000)); + else if (port >= 0x300 || port < 0x310) + return (volatile __u16 *) (PA_SMSC + (port - 0x300)); +} + +unsigned char se7206_inb(unsigned long port) +{ + return (*port2adr(port))&0xff; +} + +unsigned char se7206_inb_p(unsigned long port) +{ + unsigned long v; + + v = (*port2adr(port))&0xff; + delay(); + return v; +} + +unsigned short se7206_inw(unsigned long port) +{ + return *port2adr(port);; +} + +unsigned int se7206_inl(unsigned long port) +{ + maybebadio(port); + return 0; +} + +void se7206_outb(unsigned char value, unsigned long port) +{ + *(port2adr(port)) = value; +} + +void se7206_outb_p(unsigned char value, unsigned long port) +{ + *(port2adr(port)) = value; + delay(); +} + +void se7206_outw(unsigned short value, unsigned long port) +{ + *port2adr(port) = value; +} + +void se7206_outl(unsigned int value, unsigned long port) +{ + maybebadio(port); +} + +void se7206_insb(unsigned long port, void *addr, unsigned long count) +{ + volatile __u16 *p = port2adr(port); + __u8 *ap = addr; + + while (count--) + *ap++ = *p; +} + +void se7206_insw(unsigned long port, void *addr, unsigned long count) +{ + volatile __u16 *p = port2adr(port); + __u16 *ap = addr; + while (count--) + *ap++ = *p; +} + +void se7206_insl(unsigned long port, void *addr, unsigned long count) +{ + maybebadio(port); +} + +void se7206_outsb(unsigned long port, const void *addr, unsigned long count) +{ + volatile __u16 *p = port2adr(port); + const __u8 *ap = addr; + + while (count--) + *p = *ap++; +} + +void se7206_outsw(unsigned long port, const void *addr, unsigned long count) +{ + volatile __u16 *p = port2adr(port); + const __u16 *ap = addr; + while (count--) + *p = *ap++; +} + +void se7206_outsl(unsigned long port, const void *addr, unsigned long count) +{ + maybebadio(port); +} diff --git a/trunk/arch/sh/boards/se/7206/irq.c b/trunk/arch/sh/boards/se/7206/irq.c new file mode 100644 index 000000000000..3fb0c5f5b23a --- /dev/null +++ b/trunk/arch/sh/boards/se/7206/irq.c @@ -0,0 +1,139 @@ +/* + * linux/arch/sh/boards/se/7206/irq.c + * + * Copyright (C) 2005,2006 Yoshinori Sato + * + * Hitachi SolutionEngine Support. + * + */ +#include +#include +#include +#include +#include + +#define INTSTS0 0x31800000 +#define INTSTS1 0x31800002 +#define INTMSK0 0x31800004 +#define INTMSK1 0x31800006 +#define INTSEL 0x31800008 + +static void disable_se7206_irq(unsigned int irq) +{ + unsigned short val; + unsigned short mask = 0xffff ^ (0x0f << 4 * (3 - (IRQ0_IRQ - irq))); + unsigned short msk0,msk1; + + /* Set the priority in IPR to 0 */ + val = ctrl_inw(INTC_IPR01); + val &= mask; + ctrl_outw(val, INTC_IPR01); + /* FPGA mask set */ + msk0 = ctrl_inw(INTMSK0); + msk1 = ctrl_inw(INTMSK1); + + switch (irq) { + case IRQ0_IRQ: + msk0 |= 0x0010; + break; + case IRQ1_IRQ: + msk0 |= 0x000f; + break; + case IRQ2_IRQ: + msk0 |= 0x0f00; + msk1 |= 0x00ff; + break; + } + ctrl_outw(msk0, INTMSK0); + ctrl_outw(msk1, INTMSK1); +} + +static void enable_se7206_irq(unsigned int irq) +{ + unsigned short val; + unsigned short value = (0x0001 << 4 * (3 - (IRQ0_IRQ - irq))); + unsigned short msk0,msk1; + + /* Set priority in IPR back to original value */ + val = ctrl_inw(INTC_IPR01); + val |= value; + ctrl_outw(val, INTC_IPR01); + + /* FPGA mask reset */ + msk0 = ctrl_inw(INTMSK0); + msk1 = ctrl_inw(INTMSK1); + + switch (irq) { + case IRQ0_IRQ: + msk0 &= ~0x0010; + break; + case IRQ1_IRQ: + msk0 &= ~0x000f; + break; + case IRQ2_IRQ: + msk0 &= ~0x0f00; + msk1 &= ~0x00ff; + break; + } + ctrl_outw(msk0, INTMSK0); + ctrl_outw(msk1, INTMSK1); +} + +static void eoi_se7206_irq(unsigned int irq) +{ + unsigned short sts0,sts1; + + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + enable_se7206_irq(irq); + /* FPGA isr clear */ + sts0 = ctrl_inw(INTSTS0); + sts1 = ctrl_inw(INTSTS1); + + switch (irq) { + case IRQ0_IRQ: + sts0 &= ~0x0010; + break; + case IRQ1_IRQ: + sts0 &= ~0x000f; + break; + case IRQ2_IRQ: + sts0 &= ~0x0f00; + sts1 &= ~0x00ff; + break; + } + ctrl_outw(sts0, INTSTS0); + ctrl_outw(sts1, INTSTS1); +} + +static struct irq_chip se7206_irq_chip __read_mostly = { + .name = "SE7206-FPGA-IRQ", + .mask = disable_se7206_irq, + .unmask = enable_se7206_irq, + .mask_ack = disable_se7206_irq, + .eoi = eoi_se7206_irq, +}; + +static void make_se7206_irq(unsigned int irq) +{ + disable_irq_nosync(irq); + set_irq_chip_and_handler_name(irq, &se7206_irq_chip, + handle_level_irq, "level"); + disable_se7206_irq(irq); +} + +/* + * Initialize IRQ setting + */ +void __init init_se7206_IRQ(void) +{ + make_se7206_irq(IRQ0_IRQ); /* SMC91C111 */ + make_se7206_irq(IRQ1_IRQ); /* ATA */ + make_se7206_irq(IRQ3_IRQ); /* SLOT / PCM */ + ctrl_outw(inw(INTC_ICR1) | 0x000b ,INTC_ICR1 ) ; /* ICR1 */ + + /* FPGA System register setup*/ + ctrl_outw(0x0000,INTSTS0); /* Clear INTSTS0 */ + ctrl_outw(0x0000,INTSTS1); /* Clear INTSTS1 */ + /* IRQ0=LAN, IRQ1=ATA, IRQ3=SLT,PCM */ + ctrl_outw(0x0001,INTSEL); +} diff --git a/trunk/arch/sh/boards/se/7206/led.c b/trunk/arch/sh/boards/se/7206/led.c new file mode 100644 index 000000000000..ef794601ab86 --- /dev/null +++ b/trunk/arch/sh/boards/se/7206/led.c @@ -0,0 +1,57 @@ +/* + * linux/arch/sh/kernel/led_se.c + * + * Copyright (C) 2000 Stuart Menefy + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * This file contains Solution Engine specific LED code. + */ + +#include +#include + +#ifdef CONFIG_HEARTBEAT + +#include + +/* Cycle the LED's in the clasic Knightrider/Sun pattern */ +void heartbeat_se(void) +{ + static unsigned int cnt = 0, period = 0; + volatile unsigned short* p = (volatile unsigned short*)PA_LED; + static unsigned bit = 0, up = 1; + + cnt += 1; + if (cnt < period) { + return; + } + + cnt = 0; + + /* Go through the points (roughly!): + * f(0)=10, f(1)=16, f(2)=20, f(5)=35,f(inf)->110 + */ + period = 110 - ( (300< +#include +#include +#include +#include + +static struct resource smc91x_resources[] = { + [0] = { + .start = 0x300, + .end = 0x300 + 0x020 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = 64, + .end = 64, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device smc91x_device = { + .name = "smc91x", + .id = -1, + .num_resources = ARRAY_SIZE(smc91x_resources), + .resource = smc91x_resources, +}; + +static int __init se7206_devices_setup(void) +{ + return platform_device_register(&smc91x_device); +} + +__initcall(se7206_devices_setup); + +void heartbeat_se(void); + +/* + * The Machine Vector + */ + +struct sh_machine_vector mv_se __initmv = { + .mv_name = "SolutionEngine", + .mv_nr_irqs = 256, + .mv_inb = se7206_inb, + .mv_inw = se7206_inw, + .mv_inl = se7206_inl, + .mv_outb = se7206_outb, + .mv_outw = se7206_outw, + .mv_outl = se7206_outl, + + .mv_inb_p = se7206_inb_p, + .mv_inw_p = se7206_inw, + .mv_inl_p = se7206_inl, + .mv_outb_p = se7206_outb_p, + .mv_outw_p = se7206_outw, + .mv_outl_p = se7206_outl, + + .mv_insb = se7206_insb, + .mv_insw = se7206_insw, + .mv_insl = se7206_insl, + .mv_outsb = se7206_outsb, + .mv_outsw = se7206_outsw, + .mv_outsl = se7206_outsl, + + .mv_init_irq = init_se7206_IRQ, +#ifdef CONFIG_HEARTBEAT + .mv_heartbeat = heartbeat_se, +#endif +}; +ALIAS_MV(se) diff --git a/trunk/arch/sh/boards/se/7619/Makefile b/trunk/arch/sh/boards/se/7619/Makefile new file mode 100644 index 000000000000..3666eca8a658 --- /dev/null +++ b/trunk/arch/sh/boards/se/7619/Makefile @@ -0,0 +1,5 @@ +# +# Makefile for the 7619 SolutionEngine specific parts of the kernel +# + +obj-y := setup.o io.o diff --git a/trunk/arch/sh/boards/se/7619/io.c b/trunk/arch/sh/boards/se/7619/io.c new file mode 100644 index 000000000000..176f1f39cd9d --- /dev/null +++ b/trunk/arch/sh/boards/se/7619/io.c @@ -0,0 +1,102 @@ +/* + * + * linux/arch/sh/boards/se/7619/io.c + * + * Copyright (C) 2006 Yoshinori Sato + * + * I/O routine for Hitachi 7619 SolutionEngine. + * + */ + +#include +#include +#include +#include +#include + +/* FIXME: M3A-ZAB7 Compact Flash Slot support */ + +static inline void delay(void) +{ + ctrl_inw(0xa0000000); /* Uncached ROM area (P2) */ +} + +#define badio(name,port) \ + printk("bad I/O operation (%s) for port 0x%lx at 0x%08x\n", \ + #name, (port), (__u32) __builtin_return_address(0)) + +unsigned char se7619___inb(unsigned long port) +{ + badio(inb, port); + return 0; +} + +unsigned char se7619___inb_p(unsigned long port) +{ + badio(inb_p, port); + delay(); + return 0; +} + +unsigned short se7619___inw(unsigned long port) +{ + badio(inw, port); + return 0; +} + +unsigned int se7619___inl(unsigned long port) +{ + badio(inl, port); + return 0; +} + +void se7619___outb(unsigned char value, unsigned long port) +{ + badio(outb, port); +} + +void se7619___outb_p(unsigned char value, unsigned long port) +{ + badio(outb_p, port); + delay(); +} + +void se7619___outw(unsigned short value, unsigned long port) +{ + badio(outw, port); +} + +void se7619___outl(unsigned int value, unsigned long port) +{ + badio(outl, port); +} + +void se7619___insb(unsigned long port, void *addr, unsigned long count) +{ + badio(inw, port); +} + +void se7619___insw(unsigned long port, void *addr, unsigned long count) +{ + badio(inw, port); +} + +void se7619___insl(unsigned long port, void *addr, unsigned long count) +{ + badio(insl, port); +} + +void se7619___outsb(unsigned long port, const void *addr, unsigned long count) +{ + badio(insl, port); +} + +void se7619___outsw(unsigned long port, const void *addr, unsigned long count) +{ + badio(insl, port); +} + +void se7619___outsl(unsigned long port, const void *addr, unsigned long count) +{ + badio(outsw, port); +} diff --git a/trunk/arch/sh/boards/se/7619/setup.c b/trunk/arch/sh/boards/se/7619/setup.c new file mode 100644 index 000000000000..e627b26de0d0 --- /dev/null +++ b/trunk/arch/sh/boards/se/7619/setup.c @@ -0,0 +1,43 @@ +/* + * arch/sh/boards/se/7619/setup.c + * + * Copyright (C) 2006 Yoshinori Sato + * + * Hitachi SH7619 SolutionEngine Support. + */ + +#include +#include +#include +#include +#include + +/* + * The Machine Vector + */ + +struct sh_machine_vector mv_se __initmv = { + .mv_name = "SolutionEngine", + .mv_nr_irqs = 108, + .mv_inb = se7619___inb, + .mv_inw = se7619___inw, + .mv_inl = se7619___inl, + .mv_outb = se7619___outb, + .mv_outw = se7619___outw, + .mv_outl = se7619___outl, + + .mv_inb_p = se7619___inb_p, + .mv_inw_p = se7619___inw, + .mv_inl_p = se7619___inl, + .mv_outb_p = se7619___outb_p, + .mv_outw_p = se7619___outw, + .mv_outl_p = se7619___outl, + + .mv_insb = se7619___insb, + .mv_insw = se7619___insw, + .mv_insl = se7619___insl, + .mv_outsb = se7619___outsb, + .mv_outsw = se7619___outsw, + .mv_outsl = se7619___outsl, +}; +ALIAS_MV(se) diff --git a/trunk/arch/sh/boards/titan/setup.c b/trunk/arch/sh/boards/titan/setup.c index a6046d93758b..6bcd939bfaed 100644 --- a/trunk/arch/sh/boards/titan/setup.c +++ b/trunk/arch/sh/boards/titan/setup.c @@ -1,26 +1,30 @@ /* - * Setup for Titan + * arch/sh/boards/titan/setup.c - Setup for Titan + * + * Copyright (C) 2006 Jamie Lenehan + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. */ - #include -#include +#include #include #include -extern void __init pcibios_init_platform(void); - static struct ipr_data titan_ipr_map[] = { - { TITAN_IRQ_WAN, IRL0_IPR_ADDR, IRL0_IPR_POS, IRL0_PRIORITY }, - { TITAN_IRQ_LAN, IRL1_IPR_ADDR, IRL1_IPR_POS, IRL1_PRIORITY }, - { TITAN_IRQ_MPCIA, IRL2_IPR_ADDR, IRL2_IPR_POS, IRL2_PRIORITY }, - { TITAN_IRQ_USB, IRL3_IPR_ADDR, IRL3_IPR_POS, IRL3_PRIORITY }, + /* IRQ, IPR idx, shift, prio */ + { TITAN_IRQ_WAN, 3, 12, 8 }, /* eth0 (WAN) */ + { TITAN_IRQ_LAN, 3, 8, 8 }, /* eth1 (LAN) */ + { TITAN_IRQ_MPCIA, 3, 4, 8 }, /* mPCI A (top) */ + { TITAN_IRQ_USB, 3, 0, 8 }, /* mPCI B (bottom), USB */ }; static void __init init_titan_irq(void) { /* enable individual interrupt mode for externals */ - ctrl_outw(ctrl_inw(INTC_ICR) | INTC_ICR_IRLM, INTC_ICR); - + ipr_irq_enable_irlm(); + /* register ipr irqs */ make_ipr_irq(titan_ipr_map, ARRAY_SIZE(titan_ipr_map)); } @@ -47,6 +51,5 @@ struct sh_machine_vector mv_titan __initmv = { .mv_ioport_map = titan_ioport_map, .mv_init_irq = init_titan_irq, - .mv_init_pci = pcibios_init_platform, }; ALIAS_MV(titan) diff --git a/trunk/arch/sh/boot/compressed/misc.c b/trunk/arch/sh/boot/compressed/misc.c index f2fed5ce5cc3..35452d85b7f7 100644 --- a/trunk/arch/sh/boot/compressed/misc.c +++ b/trunk/arch/sh/boot/compressed/misc.c @@ -12,6 +12,7 @@ */ #include +#include #ifdef CONFIG_SH_STANDARD_BIOS #include #endif @@ -228,7 +229,7 @@ long* stack_start = &user_stack[STACK_SIZE]; void decompress_kernel(void) { output_data = 0; - output_ptr = (unsigned long)&_text+0x20001000; + output_ptr = P2SEGADDR((unsigned long)&_text+0x1000); free_mem_ptr = (unsigned long)&_end; free_mem_end_ptr = free_mem_ptr + HEAP_SIZE; diff --git a/trunk/arch/sh/configs/r7780rp_defconfig b/trunk/arch/sh/configs/r7780rp_defconfig index 34e2046c3213..2b75b4896ba5 100644 --- a/trunk/arch/sh/configs/r7780rp_defconfig +++ b/trunk/arch/sh/configs/r7780rp_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.19-rc3 -# Tue Oct 31 12:32:06 2006 +# Linux kernel version: 2.6.19 +# Wed Dec 6 11:59:38 2006 # CONFIG_SUPERH=y CONFIG_RWSEM_GENERIC_SPINLOCK=y @@ -11,6 +11,8 @@ CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_IRQ_PROBE=y CONFIG_GENERIC_CALIBRATE_DELAY=y # CONFIG_GENERIC_TIME is not set +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" # @@ -37,6 +39,7 @@ CONFIG_BSD_PROCESS_ACCT=y # CONFIG_AUDIT is not set CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y +# CONFIG_SYSFS_DEPRECATED is not set # CONFIG_RELAY is not set CONFIG_INITRAMFS_SOURCE="" CONFIG_CC_OPTIMIZE_FOR_SIZE=y @@ -118,6 +121,8 @@ CONFIG_SH_R7780RP=y # CONFIG_SH_LANDISK is not set # CONFIG_SH_TITAN is not set # CONFIG_SH_SHMIN is not set +# CONFIG_SH_7206_SOLUTION_ENGINE is not set +# CONFIG_SH_7619_SOLUTION_ENGINE is not set # CONFIG_SH_UNKNOWN is not set # @@ -130,6 +135,12 @@ CONFIG_CPU_SH4A=y # SH-2 Processor Support # # CONFIG_CPU_SUBTYPE_SH7604 is not set +# CONFIG_CPU_SUBTYPE_SH7619 is not set + +# +# SH-2A Processor Support +# +# CONFIG_CPU_SUBTYPE_SH7206 is not set # # SH-3 Processor Support @@ -165,6 +176,7 @@ CONFIG_CPU_SH4A=y # # CONFIG_CPU_SUBTYPE_SH7770 is not set CONFIG_CPU_SUBTYPE_SH7780=y +# CONFIG_CPU_SUBTYPE_SH7785 is not set # # SH4AL-DSP Processor Support @@ -181,8 +193,14 @@ CONFIG_MEMORY_START=0x08000000 CONFIG_MEMORY_SIZE=0x08000000 # CONFIG_32BIT is not set CONFIG_VSYSCALL=y +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_8KB is not set +# CONFIG_PAGE_SIZE_64KB is not set CONFIG_HUGETLB_PAGE_SIZE_64K=y +# CONFIG_HUGETLB_PAGE_SIZE_256K is not set # CONFIG_HUGETLB_PAGE_SIZE_1MB is not set +# CONFIG_HUGETLB_PAGE_SIZE_4MB is not set +# CONFIG_HUGETLB_PAGE_SIZE_64MB is not set CONFIG_SELECT_MEMORY_MODEL=y CONFIG_FLATMEM_MANUAL=y # CONFIG_DISCONTIGMEM_MANUAL is not set @@ -204,12 +222,14 @@ CONFIG_SPLIT_PTLOCK_CPUS=4 # Processor features # CONFIG_CPU_LITTLE_ENDIAN=y +# CONFIG_CPU_BIG_ENDIAN is not set CONFIG_SH_FPU=y # CONFIG_SH_DSP is not set CONFIG_SH_STORE_QUEUES=y CONFIG_CPU_HAS_INTEVT=y CONFIG_CPU_HAS_INTC2_IRQ=y CONFIG_CPU_HAS_SR_RB=y +CONFIG_CPU_HAS_PTEA=y # # Timer support @@ -220,6 +240,8 @@ CONFIG_SH_TMU=y # R7780RP options # CONFIG_SH_R7780MP=y +CONFIG_SH_TIMER_IRQ=28 +CONFIG_NO_IDLE_HZ=y CONFIG_SH_PCLK_FREQ=32000000 # @@ -237,6 +259,11 @@ CONFIG_SH_PCLK_FREQ=32000000 # # CONFIG_HD6446X_SERIES is not set +# +# Additional SuperH Device Drivers +# +CONFIG_PUSH_SWITCH=y + # # Kernel features # @@ -244,7 +271,7 @@ CONFIG_SH_PCLK_FREQ=32000000 CONFIG_HZ_250=y # CONFIG_HZ_1000 is not set CONFIG_HZ=250 -# CONFIG_KEXEC is not set +CONFIG_KEXEC=y # CONFIG_SMP is not set # CONFIG_PREEMPT_NONE is not set # CONFIG_PREEMPT_VOLUNTARY is not set @@ -278,10 +305,7 @@ CONFIG_PCI_AUTO_UPDATE_RESOURCES=y # # PCI Hotplug Support # -CONFIG_HOTPLUG_PCI=y -# CONFIG_HOTPLUG_PCI_FAKE is not set -# CONFIG_HOTPLUG_PCI_CPCI is not set -# CONFIG_HOTPLUG_PCI_SHPC is not set +# CONFIG_HOTPLUG_PCI is not set # # Executable file formats @@ -341,6 +365,7 @@ CONFIG_INET_TCP_DIAG=y # CONFIG_TCP_CONG_ADVANCED is not set CONFIG_TCP_CONG_CUBIC=y CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set # CONFIG_IPV6 is not set # CONFIG_INET6_XFRM_TUNNEL is not set # CONFIG_INET6_TUNNEL is not set @@ -556,6 +581,7 @@ CONFIG_SATA_SIL=y # CONFIG_PATA_IT821X is not set # CONFIG_PATA_JMICRON is not set # CONFIG_PATA_TRIFLEX is not set +# CONFIG_PATA_MARVELL is not set # CONFIG_PATA_MPIIX is not set # CONFIG_PATA_OLDPIIX is not set # CONFIG_PATA_NETCELL is not set @@ -572,6 +598,7 @@ CONFIG_SATA_SIL=y # CONFIG_PATA_SIS is not set # CONFIG_PATA_VIA is not set # CONFIG_PATA_WINBOND is not set +CONFIG_PATA_PLATFORM=y # # Multi-device support (RAID and LVM) @@ -688,6 +715,7 @@ CONFIG_R8169=y # CONFIG_IXGB is not set # CONFIG_S2IO is not set # CONFIG_MYRI10GE is not set +# CONFIG_NETXEN_NIC is not set # # Token Ring devices @@ -830,10 +858,6 @@ CONFIG_HW_RANDOM=y # CONFIG_DTLK is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set - -# -# Ftape, the floppy tape device driver -# # CONFIG_DRM is not set # CONFIG_RAW_DRIVER is not set @@ -1020,7 +1044,7 @@ CONFIG_INOTIFY_USER=y CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set -# CONFIG_FUSE_FS is not set +CONFIG_FUSE_FS=m # # CD-ROM/DVD Filesystems @@ -1052,7 +1076,7 @@ CONFIG_TMPFS=y CONFIG_HUGETLBFS=y CONFIG_HUGETLB_PAGE=y CONFIG_RAMFS=y -# CONFIG_CONFIGFS_FS is not set +CONFIG_CONFIGFS_FS=m # # Miscellaneous filesystems @@ -1153,28 +1177,33 @@ CONFIG_NLS_ISO8859_1=y # # Profiling support # -# CONFIG_PROFILING is not set +CONFIG_PROFILING=y +CONFIG_OPROFILE=m # # Kernel hacking # -# CONFIG_PRINTK_TIME is not set +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_PRINTK_TIME=y CONFIG_ENABLE_MUST_CHECK=y -# CONFIG_MAGIC_SYSRQ is not set +CONFIG_MAGIC_SYSRQ=y # CONFIG_UNUSED_SYMBOLS is not set CONFIG_DEBUG_KERNEL=y CONFIG_LOG_BUF_SHIFT=14 CONFIG_DETECT_SOFTLOCKUP=y # CONFIG_SCHEDSTATS is not set # CONFIG_DEBUG_SLAB is not set -CONFIG_DEBUG_SPINLOCK=y +# CONFIG_DEBUG_PREEMPT is not set +# CONFIG_DEBUG_SPINLOCK is not set # CONFIG_DEBUG_MUTEXES is not set # CONFIG_DEBUG_RWSEMS is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set # CONFIG_DEBUG_SPINLOCK_SLEEP is not set # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set # CONFIG_DEBUG_KOBJECT is not set -# CONFIG_DEBUG_BUGVERBOSE is not set -# CONFIG_DEBUG_INFO is not set +CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_INFO=y CONFIG_DEBUG_FS=y # CONFIG_DEBUG_VM is not set # CONFIG_DEBUG_LIST is not set @@ -1184,7 +1213,7 @@ CONFIG_FORCED_INLINING=y # CONFIG_RCU_TORTURE_TEST is not set # CONFIG_SH_STANDARD_BIOS is not set # CONFIG_EARLY_SCIF_CONSOLE is not set -# CONFIG_DEBUG_STACKOVERFLOW is not set +CONFIG_DEBUG_STACKOVERFLOW=y # CONFIG_DEBUG_STACK_USAGE is not set # CONFIG_4KSTACKS is not set # CONFIG_KGDB is not set diff --git a/trunk/arch/sh/configs/se7206_defconfig b/trunk/arch/sh/configs/se7206_defconfig new file mode 100644 index 000000000000..36cec0b6e7c1 --- /dev/null +++ b/trunk/arch/sh/configs/se7206_defconfig @@ -0,0 +1,826 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.19-rc4 +# Sun Nov 5 16:20:10 2006 +# +CONFIG_SUPERH=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_FIND_NEXT_BIT=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +# CONFIG_GENERIC_TIME is not set +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +# CONFIG_SYSVIPC is not set +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_TASKSTATS is not set +# CONFIG_UTS_NS is not set +# CONFIG_AUDIT is not set +# CONFIG_IKCONFIG is not set +# CONFIG_RELAY is not set +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SYSCTL=y +CONFIG_EMBEDDED=y +CONFIG_UID16=y +# CONFIG_SYSCTL_SYSCALL is not set +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_EXTRA_PASS is not set +# CONFIG_HOTPLUG is not set +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +# CONFIG_FUTEX is not set +# CONFIG_EPOLL is not set +CONFIG_SLAB=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_TINY_SHMEM=y +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set + +# +# Loadable module support +# +# CONFIG_MODULES is not set + +# +# Block layer +# +CONFIG_BLOCK=y +# CONFIG_LBD is not set +# CONFIG_LSF is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +# CONFIG_IOSCHED_AS is not set +# CONFIG_IOSCHED_DEADLINE is not set +# CONFIG_IOSCHED_CFQ is not set +# CONFIG_DEFAULT_AS is not set +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +CONFIG_DEFAULT_NOOP=y +CONFIG_DEFAULT_IOSCHED="noop" + +# +# System type +# +# CONFIG_SH_SOLUTION_ENGINE is not set +# CONFIG_SH_7751_SOLUTION_ENGINE is not set +# CONFIG_SH_7300_SOLUTION_ENGINE is not set +# CONFIG_SH_7343_SOLUTION_ENGINE is not set +# CONFIG_SH_73180_SOLUTION_ENGINE is not set +# CONFIG_SH_7751_SYSTEMH is not set +# CONFIG_SH_HP6XX is not set +# CONFIG_SH_EC3104 is not set +# CONFIG_SH_SATURN is not set +# CONFIG_SH_DREAMCAST is not set +# CONFIG_SH_BIGSUR is not set +# CONFIG_SH_MPC1211 is not set +# CONFIG_SH_SH03 is not set +# CONFIG_SH_SECUREEDGE5410 is not set +# CONFIG_SH_HS7751RVOIP is not set +# CONFIG_SH_7710VOIPGW is not set +# CONFIG_SH_RTS7751R2D is not set +# CONFIG_SH_R7780RP is not set +# CONFIG_SH_EDOSK7705 is not set +# CONFIG_SH_SH4202_MICRODEV is not set +# CONFIG_SH_LANDISK is not set +# CONFIG_SH_TITAN is not set +# CONFIG_SH_SHMIN is not set +CONFIG_SH_7206_SOLUTION_ENGINE=y +# CONFIG_SH_7619_SOLUTION_ENGINE is not set +# CONFIG_SH_UNKNOWN is not set + +# +# Processor selection +# +CONFIG_CPU_SH2=y +CONFIG_CPU_SH2A=y + +# +# SH-2 Processor Support +# +# CONFIG_CPU_SUBTYPE_SH7604 is not set +# CONFIG_CPU_SUBTYPE_SH7619 is not set + +# +# SH-2A Processor Support +# +CONFIG_CPU_SUBTYPE_SH7206=y + +# +# SH-3 Processor Support +# +# CONFIG_CPU_SUBTYPE_SH7300 is not set +# CONFIG_CPU_SUBTYPE_SH7705 is not set +# CONFIG_CPU_SUBTYPE_SH7706 is not set +# CONFIG_CPU_SUBTYPE_SH7707 is not set +# CONFIG_CPU_SUBTYPE_SH7708 is not set +# CONFIG_CPU_SUBTYPE_SH7709 is not set +# CONFIG_CPU_SUBTYPE_SH7710 is not set + +# +# SH-4 Processor Support +# +# CONFIG_CPU_SUBTYPE_SH7750 is not set +# CONFIG_CPU_SUBTYPE_SH7091 is not set +# CONFIG_CPU_SUBTYPE_SH7750R is not set +# CONFIG_CPU_SUBTYPE_SH7750S is not set +# CONFIG_CPU_SUBTYPE_SH7751 is not set +# CONFIG_CPU_SUBTYPE_SH7751R is not set +# CONFIG_CPU_SUBTYPE_SH7760 is not set +# CONFIG_CPU_SUBTYPE_SH4_202 is not set + +# +# ST40 Processor Support +# +# CONFIG_CPU_SUBTYPE_ST40STB1 is not set +# CONFIG_CPU_SUBTYPE_ST40GX1 is not set + +# +# SH-4A Processor Support +# +# CONFIG_CPU_SUBTYPE_SH7770 is not set +# CONFIG_CPU_SUBTYPE_SH7780 is not set + +# +# SH4AL-DSP Processor Support +# +# CONFIG_CPU_SUBTYPE_SH73180 is not set +# CONFIG_CPU_SUBTYPE_SH7343 is not set + +# +# Memory management options +# +CONFIG_PAGE_OFFSET=0x00000000 +CONFIG_MEMORY_START=0x0c000000 +CONFIG_MEMORY_SIZE=0x02000000 +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_RESOURCES_64BIT is not set + +# +# Cache configuration +# +# CONFIG_SH_DIRECT_MAPPED is not set +# CONFIG_SH_WRITETHROUGH is not set +# CONFIG_SH_OCRAM is not set + +# +# Processor features +# +# CONFIG_CPU_LITTLE_ENDIAN is not set +# CONFIG_SH_FPU is not set +# CONFIG_SH_FPU_EMU is not set +# CONFIG_SH_DSP is not set + +# +# Timer support +# +CONFIG_SH_CMT=y +# CONFIG_SH_MTU2 is not set +CONFIG_SH_PCLK_FREQ=33333333 +CONFIG_SH_CLK_MD=6 + +# +# CPU Frequency scaling +# +# CONFIG_CPU_FREQ is not set + +# +# DMA support +# +# CONFIG_SH_DMA is not set + +# +# Companion Chips +# +# CONFIG_HD6446X_SERIES is not set + +# +# Kernel features +# +CONFIG_HZ_100=y +# CONFIG_HZ_250 is not set +# CONFIG_HZ_1000 is not set +CONFIG_HZ=100 +# CONFIG_KEXEC is not set +# CONFIG_SMP is not set +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PREEMPT is not set + +# +# Boot options +# +CONFIG_ZERO_PAGE_OFFSET=0x00001000 +CONFIG_BOOT_LINK_OFFSET=0x00800000 +# CONFIG_UBC_WAKEUP is not set +# CONFIG_CMDLINE_BOOL is not set + +# +# Bus options +# +# CONFIG_PCI is not set + +# +# PCCARD (PCMCIA/CardBus) support +# + +# +# PCI Hotplug Support +# + +# +# Executable file formats +# +CONFIG_BINFMT_FLAT=y +CONFIG_BINFMT_ZFLAT=y +# CONFIG_BINFMT_SHARED_FLAT is not set +# CONFIG_BINFMT_MISC is not set + +# +# Power management options (EXPERIMENTAL) +# +# CONFIG_PM is not set + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +# CONFIG_PACKET is not set +# CONFIG_UNIX is not set +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +# CONFIG_IP_PNP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y +# CONFIG_INET_DIAG is not set +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_IPV6 is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETFILTER is not set + +# +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set + +# +# TIPC Configuration (EXPERIMENTAL) +# +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_IEEE80211 is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +# CONFIG_STANDALONE is not set +# CONFIG_PREVENT_FIRMWARE_BUILD is not set +# CONFIG_SYS_HYPERVISOR is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +# CONFIG_CONNECTOR is not set + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_PARTITIONS=y +CONFIG_MTD_REDBOOT_PARTS=y +CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1 +# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set +# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set +# CONFIG_MTD_CMDLINE_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_CFI_INTELEXT is not set +CONFIG_MTD_CFI_AMDSTD=y +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set +# CONFIG_MTD_OBSOLETE_CHIPS is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +CONFIG_MTD_PHYSMAP=y +CONFIG_MTD_PHYSMAP_START=0x20000000 +CONFIG_MTD_PHYSMAP_LEN=0x1000000 +CONFIG_MTD_PHYSMAP_BANKWIDTH=4 +# CONFIG_MTD_SOLUTIONENGINE is not set +# CONFIG_MTD_UCLINUX is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set + +# +# NAND Flash Device Drivers +# +# CONFIG_MTD_NAND is not set + +# +# OneNAND Flash Device Drivers +# +# CONFIG_MTD_ONENAND is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_COW_COMMON is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 +# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set + +# +# Misc devices +# +# CONFIG_TIFM_CORE is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +# CONFIG_SCSI is not set +# CONFIG_SCSI_NETLINK is not set + +# +# Serial ATA (prod) and Parallel ATA (experimental) drivers +# +# CONFIG_ATA is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# + +# +# I2O device support +# + +# +# Network device support +# +# CONFIG_NETDEVICES is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +# CONFIG_INPUT is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +# CONFIG_VT is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_SH_SCI=y +CONFIG_SERIAL_SH_SCI_NR_UARTS=4 +CONFIG_SERIAL_SH_SCI_CONSOLE=y +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_UNIX98_PTYS is not set +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +CONFIG_HW_RANDOM=y +# CONFIG_GEN_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# +# CONFIG_TCG_TPM is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + +# +# Hardware Monitoring support +# +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_SENSORS_ABITUGURU is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_VT1211 is not set +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# +CONFIG_FIRMWARE_EDID=y +# CONFIG_FB is not set + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB_ARCH_HAS_HCD is not set +# CONFIG_USB_ARCH_HAS_OHCI is not set +# CONFIG_USB_ARCH_HAS_EHCI is not set + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +# CONFIG_MMC is not set + +# +# LED devices +# +# CONFIG_NEW_LEDS is not set + +# +# LED drivers +# + +# +# LED Triggers +# + +# +# InfiniBand support +# + +# +# EDAC - error detection and reporting (RAS) (EXPERIMENTAL) +# + +# +# Real Time Clock +# +# CONFIG_RTC_CLASS is not set + +# +# DMA Engine support +# +# CONFIG_DMA_ENGINE is not set + +# +# DMA Clients +# + +# +# DMA Devices +# + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT3_FS is not set +# CONFIG_EXT4DEV_FS is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set +# CONFIG_MINIX_FS is not set +CONFIG_ROMFS_FS=y +# CONFIG_INOTIFY is not set +# CONFIG_QUOTA is not set +# CONFIG_DNOTIFY is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +# CONFIG_SYSFS is not set +# CONFIG_TMPFS is not set +# CONFIG_HUGETLBFS is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +# CONFIG_JFFS2_FS is not set +CONFIG_CRAMFS=y +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +# CONFIG_NFS_FS is not set +# CONFIG_NFSD is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +# CONFIG_NLS is not set + +# +# Profiling support +# +# CONFIG_PROFILING is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_MUST_CHECK=y +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_DEBUG_KERNEL is not set +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_DEBUG_BUGVERBOSE is not set +# CONFIG_UNWIND_INFO is not set +# CONFIG_HEADERS_CHECK is not set +# CONFIG_SH_STANDARD_BIOS is not set +# CONFIG_EARLY_SCIF_CONSOLE is not set +# CONFIG_KGDB is not set + +# +# Security options +# +# CONFIG_KEYS is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Library routines +# +CONFIG_CRC_CCITT=y +# CONFIG_CRC16 is not set +CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y diff --git a/trunk/arch/sh/drivers/Kconfig b/trunk/arch/sh/drivers/Kconfig new file mode 100644 index 000000000000..c54c758e6243 --- /dev/null +++ b/trunk/arch/sh/drivers/Kconfig @@ -0,0 +1,9 @@ +menu "Additional SuperH Device Drivers" + +config PUSH_SWITCH + tristate "Push switch support" + help + This enables support for the push switch framework, a simple + framework that allows for sysfs driven switch status reporting. + +endmenu diff --git a/trunk/arch/sh/drivers/Makefile b/trunk/arch/sh/drivers/Makefile index 338c3729d270..bf18dbfb6787 100644 --- a/trunk/arch/sh/drivers/Makefile +++ b/trunk/arch/sh/drivers/Makefile @@ -5,4 +5,4 @@ obj-$(CONFIG_PCI) += pci/ obj-$(CONFIG_SH_DMA) += dma/ obj-$(CONFIG_SUPERHYWAY) += superhyway/ - +obj-$(CONFIG_PUSH_SWITCH) += push-switch.o diff --git a/trunk/arch/sh/drivers/dma/Makefile b/trunk/arch/sh/drivers/dma/Makefile index 065d4c90970e..db1295d32268 100644 --- a/trunk/arch/sh/drivers/dma/Makefile +++ b/trunk/arch/sh/drivers/dma/Makefile @@ -2,8 +2,8 @@ # Makefile for the SuperH DMA specific kernel interface routines under Linux. # -obj-y += dma-api.o dma-isa.o +obj-y += dma-api.o +obj-$(CONFIG_ISA_DMA_API) += dma-isa.o obj-$(CONFIG_SYSFS) += dma-sysfs.o obj-$(CONFIG_SH_DMA) += dma-sh.o obj-$(CONFIG_SH_DREAMCAST) += dma-pvr2.o dma-g2.o - diff --git a/trunk/arch/sh/drivers/dma/dma-api.c b/trunk/arch/sh/drivers/dma/dma-api.c index 47c3e837599b..e062067edd24 100644 --- a/trunk/arch/sh/drivers/dma/dma-api.c +++ b/trunk/arch/sh/drivers/dma/dma-api.c @@ -11,61 +11,27 @@ */ #include #include -#include #include #include #include #include +#include #include DEFINE_SPINLOCK(dma_spin_lock); static LIST_HEAD(registered_dmac_list); -/* - * A brief note about the reasons for this API as it stands. - * - * For starters, the old ISA DMA API didn't work for us for a number of - * reasons, for one, the vast majority of channels on the SH DMAC are - * dual-address mode only, and both the new and the old DMA APIs are after the - * concept of managing a DMA buffer, which doesn't overly fit this model very - * well. In addition to which, the new API is largely geared at IOMMUs and - * GARTs, and doesn't even support the channel notion very well. - * - * The other thing that's a marginal issue, is the sheer number of random DMA - * engines that are present (ie, in boards like the Dreamcast), some of which - * cascade off of the SH DMAC, and others do not. As such, there was a real - * need for a scalable subsystem that could deal with both single and - * dual-address mode usage, in addition to interoperating with cascaded DMACs. - * - * There really isn't any reason why this needs to be SH specific, though I'm - * not aware of too many other processors (with the exception of some MIPS) - * that have the same concept of a dual address mode, or any real desire to - * actually make use of the DMAC even if such a subsystem were exposed - * elsewhere. - * - * The idea for this was derived from the ARM port, which acted as an excellent - * reference when trying to address these issues. - * - * It should also be noted that the decision to add Yet Another DMA API(tm) to - * the kernel wasn't made easily, and was only decided upon after conferring - * with jejb with regards to the state of the old and new APIs as they applied - * to these circumstances. Philip Blundell was also a great help in figuring - * out some single-address mode DMA semantics that were otherwise rather - * confusing. - */ - struct dma_info *get_dma_info(unsigned int chan) { struct dma_info *info; - unsigned int total = 0; /* * Look for each DMAC's range to determine who the owner of * the channel is. */ list_for_each_entry(info, ®istered_dmac_list, list) { - total += info->nr_channels; - if (chan > total) + if ((chan < info->first_channel_nr) || + (chan >= info->first_channel_nr + info->nr_channels)) continue; return info; @@ -73,6 +39,22 @@ struct dma_info *get_dma_info(unsigned int chan) return NULL; } +EXPORT_SYMBOL(get_dma_info); + +struct dma_info *get_dma_info_by_name(const char *dmac_name) +{ + struct dma_info *info; + + list_for_each_entry(info, ®istered_dmac_list, list) { + if (dmac_name && (strcmp(dmac_name, info->name) != 0)) + continue; + else + return info; + } + + return NULL; +} +EXPORT_SYMBOL(get_dma_info_by_name); static unsigned int get_nr_channels(void) { @@ -91,63 +73,161 @@ static unsigned int get_nr_channels(void) struct dma_channel *get_dma_channel(unsigned int chan) { struct dma_info *info = get_dma_info(chan); + struct dma_channel *channel; + int i; - if (!info) + if (unlikely(!info)) return ERR_PTR(-EINVAL); - return info->channels + chan; + for (i = 0; i < info->nr_channels; i++) { + channel = &info->channels[i]; + if (channel->chan == chan) + return channel; + } + + return NULL; } +EXPORT_SYMBOL(get_dma_channel); int get_dma_residue(unsigned int chan) { struct dma_info *info = get_dma_info(chan); - struct dma_channel *channel = &info->channels[chan]; + struct dma_channel *channel = get_dma_channel(chan); if (info->ops->get_residue) return info->ops->get_residue(channel); return 0; } +EXPORT_SYMBOL(get_dma_residue); -int request_dma(unsigned int chan, const char *dev_id) +static int search_cap(const char **haystack, const char *needle) { - struct dma_info *info = get_dma_info(chan); - struct dma_channel *channel = &info->channels[chan]; + const char **p; + + for (p = haystack; *p; p++) + if (strcmp(*p, needle) == 0) + return 1; + + return 0; +} + +/** + * request_dma_bycap - Allocate a DMA channel based on its capabilities + * @dmac: List of DMA controllers to search + * @caps: List of capabilites + * + * Search all channels of all DMA controllers to find a channel which + * matches the requested capabilities. The result is the channel + * number if a match is found, or %-ENODEV if no match is found. + * + * Note that not all DMA controllers export capabilities, in which + * case they can never be allocated using this API, and so + * request_dma() must be used specifying the channel number. + */ +int request_dma_bycap(const char **dmac, const char **caps, const char *dev_id) +{ + unsigned int found = 0; + struct dma_info *info; + const char **p; + int i; + + BUG_ON(!dmac || !caps); + + list_for_each_entry(info, ®istered_dmac_list, list) + if (strcmp(*dmac, info->name) == 0) { + found = 1; + break; + } + + if (!found) + return -ENODEV; + + for (i = 0; i < info->nr_channels; i++) { + struct dma_channel *channel = &info->channels[i]; + + if (unlikely(!channel->caps)) + continue; + + for (p = caps; *p; p++) { + if (!search_cap(channel->caps, *p)) + break; + if (request_dma(channel->chan, dev_id) == 0) + return channel->chan; + } + } + + return -EINVAL; +} +EXPORT_SYMBOL(request_dma_bycap); + +int dmac_search_free_channel(const char *dev_id) +{ + struct dma_channel *channel = { 0 }; + struct dma_info *info = get_dma_info(0); + int i; + + for (i = 0; i < info->nr_channels; i++) { + channel = &info->channels[i]; + if (unlikely(!channel)) + return -ENODEV; + + if (atomic_read(&channel->busy) == 0) + break; + } - down(&channel->sem); + if (info->ops->request) { + int result = info->ops->request(channel); + if (result) + return result; - if (!info->ops || chan >= MAX_DMA_CHANNELS) { - up(&channel->sem); - return -EINVAL; + atomic_set(&channel->busy, 1); + return channel->chan; } - atomic_set(&channel->busy, 1); + return -ENOSYS; +} + +int request_dma(unsigned int chan, const char *dev_id) +{ + struct dma_channel *channel = { 0 }; + struct dma_info *info = get_dma_info(chan); + int result; + + channel = get_dma_channel(chan); + if (atomic_xchg(&channel->busy, 1)) + return -EBUSY; strlcpy(channel->dev_id, dev_id, sizeof(channel->dev_id)); - up(&channel->sem); + if (info->ops->request) { + result = info->ops->request(channel); + if (result) + atomic_set(&channel->busy, 0); - if (info->ops->request) - return info->ops->request(channel); + return result; + } return 0; } +EXPORT_SYMBOL(request_dma); void free_dma(unsigned int chan) { struct dma_info *info = get_dma_info(chan); - struct dma_channel *channel = &info->channels[chan]; + struct dma_channel *channel = get_dma_channel(chan); if (info->ops->free) info->ops->free(channel); atomic_set(&channel->busy, 0); } +EXPORT_SYMBOL(free_dma); void dma_wait_for_completion(unsigned int chan) { struct dma_info *info = get_dma_info(chan); - struct dma_channel *channel = &info->channels[chan]; + struct dma_channel *channel = get_dma_channel(chan); if (channel->flags & DMA_TEI_CAPABLE) { wait_event(channel->wait_queue, @@ -158,21 +238,52 @@ void dma_wait_for_completion(unsigned int chan) while (info->ops->get_residue(channel)) cpu_relax(); } +EXPORT_SYMBOL(dma_wait_for_completion); + +int register_chan_caps(const char *dmac, struct dma_chan_caps *caps) +{ + struct dma_info *info; + unsigned int found = 0; + int i; + + list_for_each_entry(info, ®istered_dmac_list, list) + if (strcmp(dmac, info->name) == 0) { + found = 1; + break; + } + + if (unlikely(!found)) + return -ENODEV; + + for (i = 0; i < info->nr_channels; i++, caps++) { + struct dma_channel *channel; + + if ((info->first_channel_nr + i) != caps->ch_num) + return -EINVAL; + + channel = &info->channels[i]; + channel->caps = caps->caplist; + } + + return 0; +} +EXPORT_SYMBOL(register_chan_caps); void dma_configure_channel(unsigned int chan, unsigned long flags) { struct dma_info *info = get_dma_info(chan); - struct dma_channel *channel = &info->channels[chan]; + struct dma_channel *channel = get_dma_channel(chan); if (info->ops->configure) info->ops->configure(channel, flags); } +EXPORT_SYMBOL(dma_configure_channel); int dma_xfer(unsigned int chan, unsigned long from, unsigned long to, size_t size, unsigned int mode) { struct dma_info *info = get_dma_info(chan); - struct dma_channel *channel = &info->channels[chan]; + struct dma_channel *channel = get_dma_channel(chan); channel->sar = from; channel->dar = to; @@ -181,8 +292,20 @@ int dma_xfer(unsigned int chan, unsigned long from, return info->ops->xfer(channel); } +EXPORT_SYMBOL(dma_xfer); + +int dma_extend(unsigned int chan, unsigned long op, void *param) +{ + struct dma_info *info = get_dma_info(chan); + struct dma_channel *channel = get_dma_channel(chan); + + if (info->ops->extend) + return info->ops->extend(channel, op, param); + + return -ENOSYS; +} +EXPORT_SYMBOL(dma_extend); -#ifdef CONFIG_PROC_FS static int dma_read_proc(char *buf, char **start, off_t off, int len, int *eof, void *data) { @@ -214,8 +337,6 @@ static int dma_read_proc(char *buf, char **start, off_t off, return p - buf; } -#endif - int register_dmac(struct dma_info *info) { @@ -224,8 +345,7 @@ int register_dmac(struct dma_info *info) INIT_LIST_HEAD(&info->list); printk(KERN_INFO "DMA: Registering %s handler (%d channel%s).\n", - info->name, info->nr_channels, - info->nr_channels > 1 ? "s" : ""); + info->name, info->nr_channels, info->nr_channels > 1 ? "s" : ""); BUG_ON((info->flags & DMAC_CHANNELS_CONFIGURED) && !info->channels); @@ -242,28 +362,26 @@ int register_dmac(struct dma_info *info) size = sizeof(struct dma_channel) * info->nr_channels; - info->channels = kmalloc(size, GFP_KERNEL); + info->channels = kzalloc(size, GFP_KERNEL); if (!info->channels) return -ENOMEM; - - memset(info->channels, 0, size); } total_channels = get_nr_channels(); for (i = 0; i < info->nr_channels; i++) { - struct dma_channel *chan = info->channels + i; + struct dma_channel *chan = &info->channels[i]; + + atomic_set(&chan->busy, 0); - chan->chan = i; - chan->vchan = i + total_channels; + chan->chan = info->first_channel_nr + i; + chan->vchan = info->first_channel_nr + i + total_channels; memcpy(chan->dev_id, "Unused", 7); if (info->flags & DMAC_CHANNELS_TEI_CAPABLE) chan->flags |= DMA_TEI_CAPABLE; - init_MUTEX(&chan->sem); init_waitqueue_head(&chan->wait_queue); - dma_create_sysfs_files(chan, info); } @@ -271,6 +389,7 @@ int register_dmac(struct dma_info *info) return 0; } +EXPORT_SYMBOL(register_dmac); void unregister_dmac(struct dma_info *info) { @@ -285,31 +404,16 @@ void unregister_dmac(struct dma_info *info) list_del(&info->list); platform_device_unregister(info->pdev); } +EXPORT_SYMBOL(unregister_dmac); static int __init dma_api_init(void) { - printk("DMA: Registering DMA API.\n"); - -#ifdef CONFIG_PROC_FS + printk(KERN_NOTICE "DMA: Registering DMA API.\n"); create_proc_read_entry("dma", 0, 0, dma_read_proc, 0); -#endif - return 0; } - subsys_initcall(dma_api_init); MODULE_AUTHOR("Paul Mundt "); MODULE_DESCRIPTION("DMA API for SuperH"); MODULE_LICENSE("GPL"); - -EXPORT_SYMBOL(request_dma); -EXPORT_SYMBOL(free_dma); -EXPORT_SYMBOL(register_dmac); -EXPORT_SYMBOL(get_dma_residue); -EXPORT_SYMBOL(get_dma_info); -EXPORT_SYMBOL(get_dma_channel); -EXPORT_SYMBOL(dma_xfer); -EXPORT_SYMBOL(dma_wait_for_completion); -EXPORT_SYMBOL(dma_configure_channel); - diff --git a/trunk/arch/sh/drivers/dma/dma-sh.c b/trunk/arch/sh/drivers/dma/dma-sh.c index 660786013350..f63721ed86c2 100644 --- a/trunk/arch/sh/drivers/dma/dma-sh.c +++ b/trunk/arch/sh/drivers/dma/dma-sh.c @@ -94,20 +94,13 @@ static int sh_dmac_request_dma(struct dma_channel *chan) if (unlikely(!chan->flags & DMA_TEI_CAPABLE)) return 0; - chan->name = kzalloc(32, GFP_KERNEL); - if (unlikely(chan->name == NULL)) - return -ENOMEM; - snprintf(chan->name, 32, "DMAC Transfer End (Channel %d)", - chan->chan); - return request_irq(get_dmte_irq(chan->chan), dma_tei, - IRQF_DISABLED, chan->name, chan); + IRQF_DISABLED, chan->dev_id, chan); } static void sh_dmac_free_dma(struct dma_channel *chan) { free_irq(get_dmte_irq(chan->chan), chan); - kfree(chan->name); } static void diff --git a/trunk/arch/sh/drivers/dma/dma-sysfs.c b/trunk/arch/sh/drivers/dma/dma-sysfs.c index 29b8ef9873d1..eebcd4768bbf 100644 --- a/trunk/arch/sh/drivers/dma/dma-sysfs.c +++ b/trunk/arch/sh/drivers/dma/dma-sysfs.c @@ -3,7 +3,7 @@ * * sysfs interface for SH DMA API * - * Copyright (C) 2004, 2005 Paul Mundt + * Copyright (C) 2004 - 2006 Paul Mundt * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive @@ -21,7 +21,6 @@ static struct sysdev_class dma_sysclass = { set_kset_name("dma"), }; - EXPORT_SYMBOL(dma_sysclass); static ssize_t dma_show_devices(struct sys_device *dev, char *buf) @@ -31,7 +30,10 @@ static ssize_t dma_show_devices(struct sys_device *dev, char *buf) for (i = 0; i < MAX_DMA_CHANNELS; i++) { struct dma_info *info = get_dma_info(i); - struct dma_channel *channel = &info->channels[i]; + struct dma_channel *channel = get_dma_channel(i); + + if (unlikely(!info) || !channel) + continue; len += sprintf(buf + len, "%2d: %14s %s\n", channel->chan, info->name, @@ -125,11 +127,16 @@ int dma_create_sysfs_files(struct dma_channel *chan, struct dma_info *info) if (ret) return ret; - sysdev_create_file(dev, &attr_dev_id); - sysdev_create_file(dev, &attr_count); - sysdev_create_file(dev, &attr_mode); - sysdev_create_file(dev, &attr_flags); - sysdev_create_file(dev, &attr_config); + ret |= sysdev_create_file(dev, &attr_dev_id); + ret |= sysdev_create_file(dev, &attr_count); + ret |= sysdev_create_file(dev, &attr_mode); + ret |= sysdev_create_file(dev, &attr_flags); + ret |= sysdev_create_file(dev, &attr_config); + + if (unlikely(ret)) { + dev_err(&info->pdev->dev, "Failed creating attrs\n"); + return ret; + } snprintf(name, sizeof(name), "dma%d", chan->chan); return sysfs_create_link(&info->pdev->dev.kobj, &dev->kobj, name); diff --git a/trunk/arch/sh/drivers/pci/ops-titan.c b/trunk/arch/sh/drivers/pci/ops-titan.c index cd56d53375e7..ac8ee2312cd8 100644 --- a/trunk/arch/sh/drivers/pci/ops-titan.c +++ b/trunk/arch/sh/drivers/pci/ops-titan.c @@ -15,25 +15,21 @@ #include #include #include -#include +#include #include #include "pci-sh4.h" +static char titan_irq_tab[] __initdata = { + TITAN_IRQ_WAN, + TITAN_IRQ_LAN, + TITAN_IRQ_MPCIA, + TITAN_IRQ_MPCIB, + TITAN_IRQ_USB, +}; + int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin) { - int irq = -1; - - switch (slot) { - case 0: irq = TITAN_IRQ_WAN; break; /* eth0 (WAN) */ - case 1: irq = TITAN_IRQ_LAN; break; /* eth1 (LAN) */ - case 2: irq = TITAN_IRQ_MPCIA; break; /* mPCI A */ - case 3: irq = TITAN_IRQ_MPCIB; break; /* mPCI B */ - case 4: irq = TITAN_IRQ_USB; break; /* USB */ - default: - printk(KERN_INFO "PCI: Bad IRQ mapping " - "request for slot %d\n", slot); - return -1; - } + int irq = titan_irq_tab[slot]; printk("PCI: Mapping TITAN IRQ for slot %d, pin %c to irq %d\n", slot, pin - 1 + 'A', irq); diff --git a/trunk/arch/sh/drivers/pci/pci-sh7780.c b/trunk/arch/sh/drivers/pci/pci-sh7780.c index d6e635296534..602b644c35ad 100644 --- a/trunk/arch/sh/drivers/pci/pci-sh7780.c +++ b/trunk/arch/sh/drivers/pci/pci-sh7780.c @@ -22,6 +22,20 @@ #include #include "pci-sh4.h" +#define INTC_BASE 0xffd00000 +#define INTC_ICR0 (INTC_BASE+0x0) +#define INTC_ICR1 (INTC_BASE+0x1c) +#define INTC_INTPRI (INTC_BASE+0x10) +#define INTC_INTREQ (INTC_BASE+0x24) +#define INTC_INTMSK0 (INTC_BASE+0x44) +#define INTC_INTMSK1 (INTC_BASE+0x48) +#define INTC_INTMSK2 (INTC_BASE+0x40080) +#define INTC_INTMSKCLR0 (INTC_BASE+0x64) +#define INTC_INTMSKCLR1 (INTC_BASE+0x68) +#define INTC_INTMSKCLR2 (INTC_BASE+0x40084) +#define INTC_INT2MSKR (INTC_BASE+0x40038) +#define INTC_INT2MSKCR (INTC_BASE+0x4003c) + /* * Initialization. Try all known PCI access methods. Note that we support * using both PCI BIOS and direct access: in such cases, we use I/O ports diff --git a/trunk/arch/sh/drivers/push-switch.c b/trunk/arch/sh/drivers/push-switch.c new file mode 100644 index 000000000000..f2b9157c314f --- /dev/null +++ b/trunk/arch/sh/drivers/push-switch.c @@ -0,0 +1,138 @@ +/* + * Generic push-switch framework + * + * Copyright (C) 2006 Paul Mundt + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include +#include +#include + +#define DRV_NAME "push-switch" +#define DRV_VERSION "0.1.0" + +static ssize_t switch_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct push_switch_platform_info *psw_info = dev->platform_data; + return sprintf(buf, "%s\n", psw_info->name); +} +static DEVICE_ATTR(switch, S_IRUGO, switch_show, NULL); + +static void switch_timer(unsigned long data) +{ + struct push_switch *psw = (struct push_switch *)data; + + schedule_work(&psw->work); +} + +static void switch_work_handler(void *data) +{ + struct platform_device *pdev = data; + struct push_switch *psw = platform_get_drvdata(pdev); + + psw->state = 0; + + kobject_uevent(&pdev->dev.kobj, KOBJ_CHANGE); +} + +static int switch_drv_probe(struct platform_device *pdev) +{ + struct push_switch_platform_info *psw_info; + struct push_switch *psw; + int ret, irq; + + psw = kzalloc(sizeof(struct push_switch), GFP_KERNEL); + if (unlikely(!psw)) + return -ENOMEM; + + irq = platform_get_irq(pdev, 0); + if (unlikely(irq < 0)) { + ret = -ENODEV; + goto err; + } + + psw_info = pdev->dev.platform_data; + BUG_ON(!psw_info); + + ret = request_irq(irq, psw_info->irq_handler, + IRQF_DISABLED | psw_info->irq_flags, + psw_info->name ? psw_info->name : DRV_NAME, pdev); + if (unlikely(ret < 0)) + goto err; + + if (psw_info->name) { + ret = device_create_file(&pdev->dev, &dev_attr_switch); + if (unlikely(ret)) { + dev_err(&pdev->dev, "Failed creating device attrs\n"); + ret = -EINVAL; + goto err_irq; + } + } + + INIT_WORK(&psw->work, switch_work_handler, pdev); + init_timer(&psw->debounce); + + psw->debounce.function = switch_timer; + psw->debounce.data = (unsigned long)psw; + + platform_set_drvdata(pdev, psw); + + return 0; + +err_irq: + free_irq(irq, pdev); +err: + kfree(psw); + return ret; +} + +static int switch_drv_remove(struct platform_device *pdev) +{ + struct push_switch *psw = platform_get_drvdata(pdev); + struct push_switch_platform_info *psw_info = pdev->dev.platform_data; + int irq = platform_get_irq(pdev, 0); + + if (psw_info->name) + device_remove_file(&pdev->dev, &dev_attr_switch); + + platform_set_drvdata(pdev, NULL); + flush_scheduled_work(); + del_timer_sync(&psw->debounce); + free_irq(irq, pdev); + + kfree(psw); + + return 0; +} + +static struct platform_driver switch_driver = { + .probe = switch_drv_probe, + .remove = switch_drv_remove, + .driver = { + .name = DRV_NAME, + }, +}; + +static int __init switch_init(void) +{ + printk(KERN_NOTICE DRV_NAME ": version %s loaded\n", DRV_VERSION); + return platform_driver_register(&switch_driver); +} + +static void __exit switch_exit(void) +{ + platform_driver_unregister(&switch_driver); +} +module_init(switch_init); +module_exit(switch_exit); + +MODULE_VERSION(DRV_VERSION); +MODULE_AUTHOR("Paul Mundt"); +MODULE_LICENSE("GPLv2"); diff --git a/trunk/arch/sh/kernel/Makefile b/trunk/arch/sh/kernel/Makefile index 5da88a43d350..99c7e5249f7a 100644 --- a/trunk/arch/sh/kernel/Makefile +++ b/trunk/arch/sh/kernel/Makefile @@ -4,7 +4,7 @@ extra-y := head.o init_task.o vmlinux.lds -obj-y := process.o signal.o entry.o traps.o irq.o \ +obj-y := process.o signal.o traps.o irq.o \ ptrace.o setup.o time.o sys_sh.o semaphore.o \ io.o io_generic.o sh_ksyms.o syscalls.o @@ -21,3 +21,4 @@ obj-$(CONFIG_EARLY_PRINTK) += early_printk.o obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o obj-$(CONFIG_APM) += apm.o obj-$(CONFIG_PM) += pm.o +obj-$(CONFIG_STACKTRACE) += stacktrace.o diff --git a/trunk/arch/sh/kernel/cpu/Makefile b/trunk/arch/sh/kernel/cpu/Makefile index fb5dac069382..0582e6712b79 100644 --- a/trunk/arch/sh/kernel/cpu/Makefile +++ b/trunk/arch/sh/kernel/cpu/Makefile @@ -2,11 +2,12 @@ # Makefile for the Linux/SuperH CPU-specifc backends. # -obj-y += irq/ init.o clock.o - -obj-$(CONFIG_CPU_SH2) += sh2/ -obj-$(CONFIG_CPU_SH3) += sh3/ -obj-$(CONFIG_CPU_SH4) += sh4/ +obj-$(CONFIG_CPU_SH2) = sh2/ +obj-$(CONFIG_CPU_SH2A) = sh2a/ +obj-$(CONFIG_CPU_SH3) = sh3/ +obj-$(CONFIG_CPU_SH4) = sh4/ obj-$(CONFIG_UBC_WAKEUP) += ubc.o obj-$(CONFIG_SH_ADC) += adc.o + +obj-y += irq/ init.o clock.o diff --git a/trunk/arch/sh/kernel/cpu/clock.c b/trunk/arch/sh/kernel/cpu/clock.c index 51ec64cdf348..abb586b12565 100644 --- a/trunk/arch/sh/kernel/cpu/clock.c +++ b/trunk/arch/sh/kernel/cpu/clock.c @@ -5,9 +5,11 @@ * * This clock framework is derived from the OMAP version by: * - * Copyright (C) 2004 Nokia Corporation + * Copyright (C) 2004 - 2005 Nokia Corporation * Written by Tuukka Tikkanen * + * Modified for omap shared clock framework by Tony Lindgren + * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. @@ -20,6 +22,7 @@ #include #include #include +#include #include #include @@ -195,17 +198,37 @@ void clk_recalc_rate(struct clk *clk) propagate_rate(clk); } -struct clk *clk_get(const char *id) +/* + * Returns a clock. Note that we first try to use device id on the bus + * and clock name. If this fails, we try to use clock name only. + */ +struct clk *clk_get(struct device *dev, const char *id) { struct clk *p, *clk = ERR_PTR(-ENOENT); + int idno; + + if (dev == NULL || dev->bus != &platform_bus_type) + idno = -1; + else + idno = to_platform_device(dev)->id; mutex_lock(&clock_list_sem); + list_for_each_entry(p, &clock_list, node) { + if (p->id == idno && + strcmp(id, p->name) == 0 && try_module_get(p->owner)) { + clk = p; + goto found; + } + } + list_for_each_entry(p, &clock_list, node) { if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) { clk = p; break; } } + +found: mutex_unlock(&clock_list_sem); return clk; diff --git a/trunk/arch/sh/kernel/cpu/init.c b/trunk/arch/sh/kernel/cpu/init.c index bfb90eb0b7a6..48121766e8d2 100644 --- a/trunk/arch/sh/kernel/cpu/init.c +++ b/trunk/arch/sh/kernel/cpu/init.c @@ -68,12 +68,14 @@ static void __init cache_init(void) waysize = cpu_data->dcache.sets; +#ifdef CCR_CACHE_ORA /* * If the OC is already in RAM mode, we only have * half of the entries to flush.. */ if (ccr & CCR_CACHE_ORA) waysize >>= 1; +#endif waysize <<= cpu_data->dcache.entry_shift; diff --git a/trunk/arch/sh/kernel/cpu/irq/Makefile b/trunk/arch/sh/kernel/cpu/irq/Makefile index 1c034c283f59..0049d217561a 100644 --- a/trunk/arch/sh/kernel/cpu/irq/Makefile +++ b/trunk/arch/sh/kernel/cpu/irq/Makefile @@ -1,8 +1,9 @@ # # Makefile for the Linux/SuperH CPU-specifc IRQ handlers. # -obj-y += ipr.o imask.o +obj-y += imask.o +obj-$(CONFIG_CPU_HAS_IPR_IRQ) += ipr.o obj-$(CONFIG_CPU_HAS_PINT_IRQ) += pint.o obj-$(CONFIG_CPU_HAS_MASKREG_IRQ) += maskreg.o obj-$(CONFIG_CPU_HAS_INTC2_IRQ) += intc2.o diff --git a/trunk/arch/sh/kernel/cpu/irq/imask.c b/trunk/arch/sh/kernel/cpu/irq/imask.c index a33ae3e0a5a5..301b505c4278 100644 --- a/trunk/arch/sh/kernel/cpu/irq/imask.c +++ b/trunk/arch/sh/kernel/cpu/irq/imask.c @@ -53,7 +53,10 @@ void static inline set_interrupt_registers(int ip) { unsigned long __dummy; - asm volatile("ldc %2, r6_bank\n\t" + asm volatile( +#ifdef CONFIG_CPU_HAS_SR_RB + "ldc %2, r6_bank\n\t" +#endif "stc sr, %0\n\t" "and #0xf0, %0\n\t" "shlr2 %0\n\t" diff --git a/trunk/arch/sh/kernel/cpu/irq/intc2.c b/trunk/arch/sh/kernel/cpu/irq/intc2.c index 74ca576a7ce5..74defe76a058 100644 --- a/trunk/arch/sh/kernel/cpu/irq/intc2.c +++ b/trunk/arch/sh/kernel/cpu/irq/intc2.c @@ -11,22 +11,29 @@ * Hitachi 7751, the STM ST40 STB1, SH7760, and SH7780. */ #include -#include +#include #include -#include + +#if defined(CONFIG_CPU_SUBTYPE_SH7760) +#define INTC2_BASE 0xfe080000 +#define INTC2_INTMSK (INTC2_BASE + 0x40) +#define INTC2_INTMSKCLR (INTC2_BASE + 0x60) +#elif defined(CONFIG_CPU_SUBTYPE_SH7780) +#define INTC2_BASE 0xffd40000 +#define INTC2_INTMSK (INTC2_BASE + 0x38) +#define INTC2_INTMSKCLR (INTC2_BASE + 0x3c) +#endif static void disable_intc2_irq(unsigned int irq) { struct intc2_data *p = get_irq_chip_data(irq); - ctrl_outl(1 << p->msk_shift, - INTC2_BASE + INTC2_INTMSK_OFFSET + p->msk_offset); + ctrl_outl(1 << p->msk_shift, INTC2_INTMSK + p->msk_offset); } static void enable_intc2_irq(unsigned int irq) { struct intc2_data *p = get_irq_chip_data(irq); - ctrl_outl(1 << p->msk_shift, - INTC2_BASE + INTC2_INTMSKCLR_OFFSET + p->msk_offset); + ctrl_outl(1 << p->msk_shift, INTC2_INTMSKCLR + p->msk_offset); } static struct irq_chip intc2_irq_chip = { @@ -61,12 +68,10 @@ void make_intc2_irq(struct intc2_data *table, unsigned int nr_irqs) /* Set the priority level */ local_irq_save(flags); - ipr = ctrl_inl(INTC2_BASE + INTC2_INTPRI_OFFSET + - p->ipr_offset); + ipr = ctrl_inl(INTC2_BASE + p->ipr_offset); ipr &= ~(0xf << p->ipr_shift); ipr |= p->priority << p->ipr_shift; - ctrl_outl(ipr, INTC2_BASE + INTC2_INTPRI_OFFSET + - p->ipr_offset); + ctrl_outl(ipr, INTC2_BASE + p->ipr_offset); local_irq_restore(flags); diff --git a/trunk/arch/sh/kernel/cpu/irq/ipr.c b/trunk/arch/sh/kernel/cpu/irq/ipr.c index a0089563cbfc..35eb5751a3aa 100644 --- a/trunk/arch/sh/kernel/cpu/irq/ipr.c +++ b/trunk/arch/sh/kernel/cpu/irq/ipr.c @@ -19,25 +19,21 @@ #include #include #include -#include -#include -#include - +#include +#include static void disable_ipr_irq(unsigned int irq) { struct ipr_data *p = get_irq_chip_data(irq); - int shift = p->shift*4; /* Set the priority in IPR to 0 */ - ctrl_outw(ctrl_inw(p->addr) & (0xffff ^ (0xf << shift)), p->addr); + ctrl_outw(ctrl_inw(p->addr) & (0xffff ^ (0xf << p->shift)), p->addr); } static void enable_ipr_irq(unsigned int irq) { struct ipr_data *p = get_irq_chip_data(irq); - int shift = p->shift*4; /* Set priority in IPR back to original value */ - ctrl_outw(ctrl_inw(p->addr) | (p->priority << shift), p->addr); + ctrl_outw(ctrl_inw(p->addr) | (p->priority << p->shift), p->addr); } static struct irq_chip ipr_irq_chip = { @@ -53,6 +49,10 @@ void make_ipr_irq(struct ipr_data *table, unsigned int nr_irqs) for (i = 0; i < nr_irqs; i++) { unsigned int irq = table[i].irq; + table[i].addr = map_ipridx_to_addr(table[i].ipr_idx); + /* could the IPR index be mapped, if not we ignore this */ + if (table[i].addr == 0) + continue; disable_irq_nosync(irq); set_irq_chip_and_handler_name(irq, &ipr_irq_chip, handle_level_irq, "level"); @@ -62,83 +62,6 @@ void make_ipr_irq(struct ipr_data *table, unsigned int nr_irqs) } EXPORT_SYMBOL(make_ipr_irq); -static struct ipr_data sys_ipr_map[] = { -#ifndef CONFIG_CPU_SUBTYPE_SH7780 - { TIMER_IRQ, TIMER_IPR_ADDR, TIMER_IPR_POS, TIMER_PRIORITY }, - { TIMER1_IRQ, TIMER1_IPR_ADDR, TIMER1_IPR_POS, TIMER1_PRIORITY }, -#ifdef RTC_IRQ - { RTC_IRQ, RTC_IPR_ADDR, RTC_IPR_POS, RTC_PRIORITY }, -#endif -#ifdef SCI_ERI_IRQ - { SCI_ERI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY }, - { SCI_RXI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY }, - { SCI_TXI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY }, -#endif -#ifdef SCIF1_ERI_IRQ - { SCIF1_ERI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY }, - { SCIF1_RXI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY }, - { SCIF1_BRI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY }, - { SCIF1_TXI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY }, -#endif -#if defined(CONFIG_CPU_SUBTYPE_SH7300) - { SCIF0_IRQ, SCIF0_IPR_ADDR, SCIF0_IPR_POS, SCIF0_PRIORITY }, - { DMTE2_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY }, - { DMTE3_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY }, - { VIO_IRQ, VIO_IPR_ADDR, VIO_IPR_POS, VIO_PRIORITY }, -#endif -#ifdef SCIF_ERI_IRQ - { SCIF_ERI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY }, - { SCIF_RXI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY }, - { SCIF_BRI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY }, - { SCIF_TXI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY }, -#endif -#ifdef IRDA_ERI_IRQ - { IRDA_ERI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY }, - { IRDA_RXI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY }, - { IRDA_BRI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY }, - { IRDA_TXI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY }, -#endif -#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) || \ - defined(CONFIG_CPU_SUBTYPE_SH7706) || \ - defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7705) - /* - * Initialize the Interrupt Controller (INTC) - * registers to their power on values - */ - - /* - * Enable external irq (INTC IRQ mode). - * You should set corresponding bits of PFC to "00" - * to enable these interrupts. - */ - { IRQ0_IRQ, IRQ0_IPR_ADDR, IRQ0_IPR_POS, IRQ0_PRIORITY }, - { IRQ1_IRQ, IRQ1_IPR_ADDR, IRQ1_IPR_POS, IRQ1_PRIORITY }, - { IRQ2_IRQ, IRQ2_IPR_ADDR, IRQ2_IPR_POS, IRQ2_PRIORITY }, - { IRQ3_IRQ, IRQ3_IPR_ADDR, IRQ3_IPR_POS, IRQ3_PRIORITY }, - { IRQ4_IRQ, IRQ4_IPR_ADDR, IRQ4_IPR_POS, IRQ4_PRIORITY }, - { IRQ5_IRQ, IRQ5_IPR_ADDR, IRQ5_IPR_POS, IRQ5_PRIORITY }, -#endif -#endif -}; - -void __init init_IRQ(void) -{ - make_ipr_irq(sys_ipr_map, ARRAY_SIZE(sys_ipr_map)); - -#ifdef CONFIG_CPU_HAS_PINT_IRQ - init_IRQ_pint(); -#endif - -#ifdef CONFIG_CPU_HAS_INTC2_IRQ - init_IRQ_intc2(); -#endif - /* Perform the machine specific initialisation */ - if (sh_mv.mv_init_irq != NULL) - sh_mv.mv_init_irq(); - - irq_ctx_init(smp_processor_id()); -} - #if !defined(CONFIG_CPU_HAS_PINT_IRQ) int ipr_irq_demux(int irq) { diff --git a/trunk/arch/sh/kernel/cpu/sh2/Makefile b/trunk/arch/sh/kernel/cpu/sh2/Makefile index 389353fba608..f0f059acfcfb 100644 --- a/trunk/arch/sh/kernel/cpu/sh2/Makefile +++ b/trunk/arch/sh/kernel/cpu/sh2/Makefile @@ -2,5 +2,6 @@ # Makefile for the Linux/SuperH SH-2 backends. # -obj-y := probe.o +obj-y := ex.o probe.o entry.o +obj-$(CONFIG_CPU_SUBTYPE_SH7619) += setup-sh7619.o clock-sh7619.o diff --git a/trunk/arch/sh/kernel/cpu/sh2/clock-sh7619.c b/trunk/arch/sh/kernel/cpu/sh2/clock-sh7619.c new file mode 100644 index 000000000000..d0440b269702 --- /dev/null +++ b/trunk/arch/sh/kernel/cpu/sh2/clock-sh7619.c @@ -0,0 +1,81 @@ +/* + * arch/sh/kernel/cpu/sh2/clock-sh7619.c + * + * SH7619 support for the clock framework + * + * Copyright (C) 2006 Yoshinori Sato + * + * Based on clock-sh4.c + * Copyright (C) 2005 Paul Mundt + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include +#include +#include + +const static int pll1rate[]={1,2}; +const static int pfc_divisors[]={1,2,0,4}; + +#if (CONFIG_SH_CLK_MD == 1) || (CONFIG_SH_CLK_MD == 2) +#define PLL2 (4) +#elif (CONFIG_SH_CLK_MD == 5) || (CONFIG_SH_CLK_MD == 6) +#define PLL2 (2) +#else +#error "Illigal Clock Mode!" +#endif + +static void master_clk_init(struct clk *clk) +{ + clk->rate *= PLL2 * pll1rate[(ctrl_inw(FREQCR) >> 8) & 7]; +} + +static struct clk_ops sh7619_master_clk_ops = { + .init = master_clk_init, +}; + +static void module_clk_recalc(struct clk *clk) +{ + int idx = (ctrl_inw(FREQCR) & 0x0007); + clk->rate = clk->parent->rate / pfc_divisors[idx]; +} + +static struct clk_ops sh7619_module_clk_ops = { + .recalc = module_clk_recalc, +}; + +static void bus_clk_recalc(struct clk *clk) +{ + clk->rate = clk->parent->rate / pll1rate[(ctrl_inw(FREQCR) >> 8) & 7]; +} + +static struct clk_ops sh7619_bus_clk_ops = { + .recalc = bus_clk_recalc, +}; + +static void cpu_clk_recalc(struct clk *clk) +{ + clk->rate = clk->parent->rate; +} + +static struct clk_ops sh7619_cpu_clk_ops = { + .recalc = cpu_clk_recalc, +}; + +static struct clk_ops *sh7619_clk_ops[] = { + &sh7619_master_clk_ops, + &sh7619_module_clk_ops, + &sh7619_bus_clk_ops, + &sh7619_cpu_clk_ops, +}; + +void __init arch_init_clk_ops(struct clk_ops **ops, int idx) +{ + if (idx < ARRAY_SIZE(sh7619_clk_ops)) + *ops = sh7619_clk_ops[idx]; +} + diff --git a/trunk/arch/sh/kernel/cpu/sh2/entry.S b/trunk/arch/sh/kernel/cpu/sh2/entry.S new file mode 100644 index 000000000000..34d51b3745ea --- /dev/null +++ b/trunk/arch/sh/kernel/cpu/sh2/entry.S @@ -0,0 +1,341 @@ +/* + * arch/sh/kernel/cpu/sh2/entry.S + * + * The SH-2 exception entry + * + * Copyright (C) 2005,2006 Yoshinori Sato + * Copyright (C) 2005 AXE,Inc. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ + +#include +#include +#include +#include +#include +#include +#include + +/* Offsets to the stack */ +OFF_R0 = 0 /* Return value. New ABI also arg4 */ +OFF_R1 = 4 /* New ABI: arg5 */ +OFF_R2 = 8 /* New ABI: arg6 */ +OFF_R3 = 12 /* New ABI: syscall_nr */ +OFF_R4 = 16 /* New ABI: arg0 */ +OFF_R5 = 20 /* New ABI: arg1 */ +OFF_R6 = 24 /* New ABI: arg2 */ +OFF_R7 = 28 /* New ABI: arg3 */ +OFF_SP = (15*4) +OFF_PC = (16*4) +OFF_SR = (16*4+2*4) +OFF_TRA = (16*4+6*4) + +#include + +ENTRY(exception_handler) + ! already saved r0/r1 + mov.l r2,@-sp + mov.l r3,@-sp + mov r0,r1 + cli + mov.l $cpu_mode,r2 + mov.l @r2,r0 + mov.l @(5*4,r15),r3 ! previous SR + shll2 r3 ! set "S" flag + rotl r0 ! T <- "S" flag + rotl r0 ! "S" flag is LSB + rotcr r3 ! T -> r3:b30 + shlr r3 + shlr r0 + bt/s 1f + mov.l r3,@(5*4,r15) ! copy cpu mode to SR + ! switch to kernel mode + mov #1,r0 + rotr r0 + rotr r0 + mov.l r0,@r2 ! enter kernel mode + mov.l $current_thread_info,r2 + mov.l @r2,r2 + mov #0x20,r0 + shll8 r0 + add r2,r0 + mov r15,r2 ! r2 = user stack top + mov r0,r15 ! switch kernel stack + add #-4,r15 ! dummy + mov.l r1,@-r15 ! TRA + sts.l macl, @-r15 + sts.l mach, @-r15 + stc.l gbr, @-r15 + mov.l @(4*4,r2),r0 + mov.l @(5*4,r2),r1 + mov.l r1,@-r15 ! original SR + sts.l pr,@-r15 + mov.l r0,@-r15 ! original PC + mov r2,r3 + add #(4+2)*4,r3 ! rewind r0 - r3 + exception frame + mov.l r3,@-r15 ! original SP + mov.l r14,@-r15 + mov.l r13,@-r15 + mov.l r12,@-r15 + mov.l r11,@-r15 + mov.l r10,@-r15 + mov.l r9,@-r15 + mov.l r8,@-r15 + mov.l r7,@-r15 + mov.l r6,@-r15 + mov.l r5,@-r15 + mov.l r4,@-r15 + mov r2,r8 ! copy user -> kernel stack + mov.l @r8+,r3 + mov.l r3,@-r15 + mov.l @r8+,r2 + mov.l r2,@-r15 + mov.l @r8+,r1 + mov.l r1,@-r15 + mov.l @r8+,r0 + bra 2f + mov.l r0,@-r15 +1: + ! in kernel exception + mov #(22-4-4-1)*4+4,r0 + mov r15,r2 + sub r0,r15 + mov.l @r2+,r0 ! old R3 + mov.l r0,@-r15 + mov.l @r2+,r0 ! old R2 + mov.l r0,@-r15 + mov.l @r2+,r0 ! old R1 + mov.l r0,@-r15 + mov.l @r2+,r0 ! old R0 + mov.l r0,@-r15 + mov.l @r2+,r3 ! old PC + mov.l @r2+,r0 ! old SR + add #-4,r2 ! exception frame stub (sr) + mov.l r1,@-r2 ! TRA + sts.l macl, @-r2 + sts.l mach, @-r2 + stc.l gbr, @-r2 + mov.l r0,@-r2 ! save old SR + sts.l pr,@-r2 + mov.l r3,@-r2 ! save old PC + mov r2,r0 + add #8*4,r0 + mov.l r0,@-r2 ! save old SP + mov.l r14,@-r2 + mov.l r13,@-r2 + mov.l r12,@-r2 + mov.l r11,@-r2 + mov.l r10,@-r2 + mov.l r9,@-r2 + mov.l r8,@-r2 + mov.l r7,@-r2 + mov.l r6,@-r2 + mov.l r5,@-r2 + mov.l r4,@-r2 + mov.l @(OFF_R0,r15),r0 + mov.l @(OFF_R1,r15),r1 + mov.l @(OFF_R2,r15),r2 + mov.l @(OFF_R3,r15),r3 +2: + mov #OFF_TRA,r8 + add r15,r8 + mov.l @r8,r9 + mov #64,r8 + cmp/hs r8,r9 + bt interrupt_entry ! vec >= 64 is interrupt + mov #32,r8 + cmp/hs r8,r9 + bt trap_entry ! 64 > vec >= 32 is trap + mov.l 4f,r8 + mov r9,r4 + shll2 r9 + add r9,r8 + mov.l @r8,r8 + mov #0,r9 + cmp/eq r9,r8 + bf 3f + mov.l 8f,r8 ! unhandled exception +3: + mov.l 5f,r10 + jmp @r8 + lds r10,pr + +interrupt_entry: + mov r9,r4 + mov.l 6f,r9 + mov.l 7f,r8 + jmp @r8 + lds r9,pr + + .align 2 +4: .long exception_handling_table +5: .long ret_from_exception +6: .long ret_from_irq +7: .long do_IRQ +8: .long do_exception_error + +trap_entry: + add #-0x10,r9 + shll2 r9 ! TRA + mov #OFF_TRA,r8 + add r15,r8 + mov.l r9,@r8 + mov r9,r8 +#ifdef CONFIG_TRACE_IRQFLAGS + mov.l 5f, r9 + jsr @r9 + nop +#endif + sti + bra system_call + nop + + .align 2 +1: .long syscall_exit +2: .long break_point_trap_software +3: .long NR_syscalls +4: .long sys_call_table +#ifdef CONFIG_TRACE_IRQFLAGS +5: .long trace_hardirqs_on +#endif + +#if defined(CONFIG_SH_STANDARD_BIOS) + /* Unwind the stack and jmp to the debug entry */ +debug_kernel_fw: + mov r15,r0 + add #(22-4)*4-4,r0 + ldc.l @r0+,gbr + lds.l @r0+,mach + lds.l @r0+,macl + mov r15,r0 + mov.l @(OFF_SP,r0),r1 + mov #OFF_SR,r2 + mov.l @(r0,r2),r3 + mov.l r3,@-r1 + mov #OFF_SP,r2 + mov.l @(r0,r2),r3 + mov.l r3,@-r1 + mov r15,r0 + add #(22-4)*4-8,r0 + mov.l 1f,r2 + mov.l @r2,r2 + stc sr,r3 + mov.l r2,@r0 + mov.l r3,@r0 + mov.l r1,@(8,r0) + mov.l @r15+, r0 + mov.l @r15+, r1 + mov.l @r15+, r2 + mov.l @r15+, r3 + mov.l @r15+, r4 + mov.l @r15+, r5 + mov.l @r15+, r6 + mov.l @r15+, r7 + mov.l @r15+, r8 + mov.l @r15+, r9 + mov.l @r15+, r10 + mov.l @r15+, r11 + mov.l @r15+, r12 + mov.l @r15+, r13 + mov.l @r15+, r14 + add #8,r15 + lds.l @r15+, pr + rte + mov.l @r15+,r15 + .align 2 +1: .long gdb_vbr_vector +#endif /* CONFIG_SH_STANDARD_BIOS */ + +ENTRY(address_error_handler) + mov r15,r4 ! regs + add #4,r4 + mov #OFF_PC,r0 + mov.l @(r0,r15),r6 ! pc + mov.l 1f,r0 + jmp @r0 + mov #0,r5 ! writeaccess is unknown + .align 2 + +1: .long do_address_error + +restore_all: + cli +#ifdef CONFIG_TRACE_IRQFLAGS + mov.l 3f, r0 + jsr @r0 + nop +#endif + mov r15,r0 + mov.l $cpu_mode,r2 + mov #OFF_SR,r3 + mov.l @(r0,r3),r1 + mov.l r1,@r2 + shll2 r1 ! clear MD bit + shlr2 r1 + mov.l @(OFF_SP,r0),r2 + add #-8,r2 + mov.l r2,@(OFF_SP,r0) ! point exception frame top + mov.l r1,@(4,r2) ! set sr + mov #OFF_PC,r3 + mov.l @(r0,r3),r1 + mov.l r1,@r2 ! set pc + add #4*16+4,r0 + lds.l @r0+,pr + add #4,r0 ! skip sr + ldc.l @r0+,gbr + lds.l @r0+,mach + lds.l @r0+,macl + get_current_thread_info r0, r1 + mov.l $current_thread_info,r1 + mov.l r0,@r1 + mov.l @r15+,r0 + mov.l @r15+,r1 + mov.l @r15+,r2 + mov.l @r15+,r3 + mov.l @r15+,r4 + mov.l @r15+,r5 + mov.l @r15+,r6 + mov.l @r15+,r7 + mov.l @r15+,r8 + mov.l @r15+,r9 + mov.l @r15+,r10 + mov.l @r15+,r11 + mov.l @r15+,r12 + mov.l @r15+,r13 + mov.l @r15+,r14 + mov.l @r15,r15 + rte + nop +2: + mov.l 1f,r8 + mov.l 2f,r9 + jmp @r9 + lds r8,pr + + .align 2 +$current_thread_info: + .long __current_thread_info +$cpu_mode: + .long __cpu_mode +#ifdef CONFIG_TRACE_IRQFLAGS +3: .long trace_hardirqs_off +#endif + +! common exception handler +#include "../../entry-common.S" + + .data +! cpu operation mode +! bit30 = MD (compatible SH3/4) +__cpu_mode: + .long 0x40000000 + + .section .bss +__current_thread_info: + .long 0 + +ENTRY(exception_handling_table) + .space 4*32 diff --git a/trunk/arch/sh/kernel/cpu/sh2/ex.S b/trunk/arch/sh/kernel/cpu/sh2/ex.S new file mode 100644 index 000000000000..6d285af7846c --- /dev/null +++ b/trunk/arch/sh/kernel/cpu/sh2/ex.S @@ -0,0 +1,46 @@ +/* + * arch/sh/kernel/cpu/sh2/ex.S + * + * The SH-2 exception vector table + * + * Copyright (C) 2005 Yoshinori Sato + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ + +#include + +! +! convert Exception Vector to Exception Number +! +exception_entry: +no = 0 + .rept 256 + mov.l r0,@-sp + mov #no,r0 + bra exception_trampoline + and #0xff,r0 +no = no + 1 + .endr +exception_trampoline: + mov.l r1,@-sp + mov.l $exception_handler,r1 + jmp @r1 + + .align 2 +$exception_entry: + .long exception_entry +$exception_handler: + .long exception_handler +! +! Exception Vector Base +! + .align 2 +ENTRY(vbr_base) +vector = 0 + .rept 256 + .long exception_entry + vector * 8 +vector = vector + 1 + .endr diff --git a/trunk/arch/sh/kernel/cpu/sh2/probe.c b/trunk/arch/sh/kernel/cpu/sh2/probe.c index f17a2a0d588e..ba527d9b5024 100644 --- a/trunk/arch/sh/kernel/cpu/sh2/probe.c +++ b/trunk/arch/sh/kernel/cpu/sh2/probe.c @@ -17,17 +17,23 @@ int __init detect_cpu_and_cache_system(void) { - /* - * For now, assume SH7604 .. fix this later. - */ +#if defined(CONFIG_CPU_SUBTYPE_SH7604) cpu_data->type = CPU_SH7604; cpu_data->dcache.ways = 4; - cpu_data->dcache.way_shift = 6; + cpu_data->dcache.way_incr = (1<<10); cpu_data->dcache.sets = 64; cpu_data->dcache.entry_shift = 4; cpu_data->dcache.linesz = L1_CACHE_BYTES; cpu_data->dcache.flags = 0; - +#elif defined(CONFIG_CPU_SUBTYPE_SH7619) + cpu_data->type = CPU_SH7619; + cpu_data->dcache.ways = 4; + cpu_data->dcache.way_incr = (1<<12); + cpu_data->dcache.sets = 256; + cpu_data->dcache.entry_shift = 4; + cpu_data->dcache.linesz = L1_CACHE_BYTES; + cpu_data->dcache.flags = 0; +#endif /* * SH-2 doesn't have separate caches */ diff --git a/trunk/arch/sh/kernel/cpu/sh2/setup-sh7619.c b/trunk/arch/sh/kernel/cpu/sh2/setup-sh7619.c new file mode 100644 index 000000000000..82c2d905152f --- /dev/null +++ b/trunk/arch/sh/kernel/cpu/sh2/setup-sh7619.c @@ -0,0 +1,53 @@ +/* + * SH7619 Setup + * + * Copyright (C) 2006 Yoshinori Sato + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include +#include + +static struct plat_sci_port sci_platform_data[] = { + { + .mapbase = 0xf8400000, + .flags = UPF_BOOT_AUTOCONF, + .type = PORT_SCIF, + .irqs = { 88, 89, 91, 90}, + }, { + .mapbase = 0xf8410000, + .flags = UPF_BOOT_AUTOCONF, + .type = PORT_SCIF, + .irqs = { 92, 93, 95, 94}, + }, { + .mapbase = 0xf8420000, + .flags = UPF_BOOT_AUTOCONF, + .type = PORT_SCIF, + .irqs = { 96, 97, 99, 98}, + }, { + .flags = 0, + } +}; + +static struct platform_device sci_device = { + .name = "sh-sci", + .id = -1, + .dev = { + .platform_data = sci_platform_data, + }, +}; + +static struct platform_device *sh7619_devices[] __initdata = { + &sci_device, +}; + +static int __init sh7619_devices_setup(void) +{ + return platform_add_devices(sh7619_devices, + ARRAY_SIZE(sh7619_devices)); +} +__initcall(sh7619_devices_setup); diff --git a/trunk/arch/sh/kernel/cpu/sh2a/Makefile b/trunk/arch/sh/kernel/cpu/sh2a/Makefile new file mode 100644 index 000000000000..350972ae9410 --- /dev/null +++ b/trunk/arch/sh/kernel/cpu/sh2a/Makefile @@ -0,0 +1,10 @@ +# +# Makefile for the Linux/SuperH SH-2A backends. +# + +obj-y := common.o probe.o + +common-y += $(addprefix ../sh2/, ex.o) +common-y += $(addprefix ../sh2/, entry.o) + +obj-$(CONFIG_CPU_SUBTYPE_SH7206) += setup-sh7206.o clock-sh7206.o diff --git a/trunk/arch/sh/kernel/cpu/sh2a/clock-sh7206.c b/trunk/arch/sh/kernel/cpu/sh2a/clock-sh7206.c new file mode 100644 index 000000000000..a9ad309c6a33 --- /dev/null +++ b/trunk/arch/sh/kernel/cpu/sh2a/clock-sh7206.c @@ -0,0 +1,85 @@ +/* + * arch/sh/kernel/cpu/sh2a/clock-sh7206.c + * + * SH7206 support for the clock framework + * + * Copyright (C) 2006 Yoshinori Sato + * + * Based on clock-sh4.c + * Copyright (C) 2005 Paul Mundt + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include +#include +#include + +const static int pll1rate[]={1,2,3,4,6,8}; +const static int pfc_divisors[]={1,2,3,4,6,8,12}; +#define ifc_divisors pfc_divisors + +#if (CONFIG_SH_CLK_MD == 2) +#define PLL2 (4) +#elif (CONFIG_SH_CLK_MD == 6) +#define PLL2 (2) +#elif (CONFIG_SH_CLK_MD == 7) +#define PLL2 (1) +#else +#error "Illigal Clock Mode!" +#endif + +static void master_clk_init(struct clk *clk) +{ + clk->rate *= PLL2 * pll1rate[(ctrl_inw(FREQCR) >> 8) & 0x0007]; +} + +static struct clk_ops sh7206_master_clk_ops = { + .init = master_clk_init, +}; + +static void module_clk_recalc(struct clk *clk) +{ + int idx = (ctrl_inw(FREQCR) & 0x0007); + clk->rate = clk->parent->rate / pfc_divisors[idx]; +} + +static struct clk_ops sh7206_module_clk_ops = { + .recalc = module_clk_recalc, +}; + +static void bus_clk_recalc(struct clk *clk) +{ + clk->rate = clk->parent->rate / pll1rate[(ctrl_inw(FREQCR) >> 8) & 0x0007]; +} + +static struct clk_ops sh7206_bus_clk_ops = { + .recalc = bus_clk_recalc, +}; + +static void cpu_clk_recalc(struct clk *clk) +{ + int idx = (ctrl_inw(FREQCR) & 0x0007); + clk->rate = clk->parent->rate / ifc_divisors[idx]; +} + +static struct clk_ops sh7206_cpu_clk_ops = { + .recalc = cpu_clk_recalc, +}; + +static struct clk_ops *sh7206_clk_ops[] = { + &sh7206_master_clk_ops, + &sh7206_module_clk_ops, + &sh7206_bus_clk_ops, + &sh7206_cpu_clk_ops, +}; + +void __init arch_init_clk_ops(struct clk_ops **ops, int idx) +{ + if (idx < ARRAY_SIZE(sh7206_clk_ops)) + *ops = sh7206_clk_ops[idx]; +} + diff --git a/trunk/arch/sh/kernel/cpu/sh2a/probe.c b/trunk/arch/sh/kernel/cpu/sh2a/probe.c new file mode 100644 index 000000000000..87c6c0542089 --- /dev/null +++ b/trunk/arch/sh/kernel/cpu/sh2a/probe.c @@ -0,0 +1,39 @@ +/* + * arch/sh/kernel/cpu/sh2a/probe.c + * + * CPU Subtype Probing for SH-2A. + * + * Copyright (C) 2004, 2005 Paul Mundt + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ + +#include +#include +#include + +int __init detect_cpu_and_cache_system(void) +{ + /* Just SH7206 for now .. */ + cpu_data->type = CPU_SH7206; + + cpu_data->dcache.ways = 4; + cpu_data->dcache.way_incr = (1 << 11); + cpu_data->dcache.sets = 128; + cpu_data->dcache.entry_shift = 4; + cpu_data->dcache.linesz = L1_CACHE_BYTES; + cpu_data->dcache.flags = 0; + + /* + * The icache is the same as the dcache as far as this setup is + * concerned. The only real difference in hardware is that the icache + * lacks the U bit that the dcache has, none of this has any bearing + * on the cache info. + */ + cpu_data->icache = cpu_data->dcache; + + return 0; +} + diff --git a/trunk/arch/sh/kernel/cpu/sh2a/setup-sh7206.c b/trunk/arch/sh/kernel/cpu/sh2a/setup-sh7206.c new file mode 100644 index 000000000000..cdfeef49e62e --- /dev/null +++ b/trunk/arch/sh/kernel/cpu/sh2a/setup-sh7206.c @@ -0,0 +1,58 @@ +/* + * SH7206 Setup + * + * Copyright (C) 2006 Yoshinori Sato + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include +#include + +static struct plat_sci_port sci_platform_data[] = { + { + .mapbase = 0xfffe8000, + .flags = UPF_BOOT_AUTOCONF, + .type = PORT_SCIF, + .irqs = { 240, 241, 242, 243}, + }, { + .mapbase = 0xfffe8800, + .flags = UPF_BOOT_AUTOCONF, + .type = PORT_SCIF, + .irqs = { 244, 245, 246, 247}, + }, { + .mapbase = 0xfffe9000, + .flags = UPF_BOOT_AUTOCONF, + .type = PORT_SCIF, + .irqs = { 248, 249, 250, 251}, + }, { + .mapbase = 0xfffe9800, + .flags = UPF_BOOT_AUTOCONF, + .type = PORT_SCIF, + .irqs = { 252, 253, 254, 255}, + }, { + .flags = 0, + } +}; + +static struct platform_device sci_device = { + .name = "sh-sci", + .id = -1, + .dev = { + .platform_data = sci_platform_data, + }, +}; + +static struct platform_device *sh7206_devices[] __initdata = { + &sci_device, +}; + +static int __init sh7206_devices_setup(void) +{ + return platform_add_devices(sh7206_devices, + ARRAY_SIZE(sh7206_devices)); +} +__initcall(sh7206_devices_setup); diff --git a/trunk/arch/sh/kernel/cpu/sh3/Makefile b/trunk/arch/sh/kernel/cpu/sh3/Makefile index 58d3815695ff..83905e4e4387 100644 --- a/trunk/arch/sh/kernel/cpu/sh3/Makefile +++ b/trunk/arch/sh/kernel/cpu/sh3/Makefile @@ -2,7 +2,7 @@ # Makefile for the Linux/SuperH SH-3 backends. # -obj-y := ex.o probe.o +obj-y := ex.o probe.o entry.o # CPU subtype setup obj-$(CONFIG_CPU_SUBTYPE_SH7705) += setup-sh7705.o diff --git a/trunk/arch/sh/kernel/cpu/sh3/clock-sh7709.c b/trunk/arch/sh/kernel/cpu/sh3/clock-sh7709.c index 10461a745e5f..b791a29fdb62 100644 --- a/trunk/arch/sh/kernel/cpu/sh3/clock-sh7709.c +++ b/trunk/arch/sh/kernel/cpu/sh3/clock-sh7709.c @@ -24,7 +24,7 @@ static int pfc_divisors[] = { 1, 2, 4, 1, 3, 6, 1, 1 }; static void set_bus_parent(struct clk *clk) { - struct clk *bus_clk = clk_get("bus_clk"); + struct clk *bus_clk = clk_get(NULL, "bus_clk"); clk->parent = bus_clk; clk_put(bus_clk); } diff --git a/trunk/arch/sh/kernel/entry.S b/trunk/arch/sh/kernel/cpu/sh3/entry.S similarity index 58% rename from trunk/arch/sh/kernel/entry.S rename to trunk/arch/sh/kernel/cpu/sh3/entry.S index 39aaefb2d83f..8c0dc2700c69 100644 --- a/trunk/arch/sh/kernel/entry.S +++ b/trunk/arch/sh/kernel/cpu/sh3/entry.S @@ -1,5 +1,5 @@ /* - * linux/arch/sh/entry.S + * arch/sh/kernel/entry.S * * Copyright (C) 1999, 2000, 2002 Niibe Yutaka * Copyright (C) 2003 - 2006 Paul Mundt @@ -7,15 +7,16 @@ * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. - * */ #include #include #include #include #include -#include #include +#include +#include +#include ! NOTE: ! GNU as (as of 2.9.1) changes bf/s into bt/s and bra, when the address @@ -81,6 +82,8 @@ OFF_TRA = (16*4+6*4) #define k_g_imask r6_bank /* r6_bank1 */ #define current r7 /* r7_bank1 */ +#include + /* * Kernel mode register usage: * k0 scratch @@ -107,26 +110,6 @@ OFF_TRA = (16*4+6*4) ! this first version depends *much* on C implementation. ! -#define CLI() \ - stc sr, r0; \ - or #0xf0, r0; \ - ldc r0, sr - -#define STI() \ - mov.l __INV_IMASK, r11; \ - stc sr, r10; \ - and r11, r10; \ - stc k_g_imask, r11; \ - or r11, r10; \ - ldc r10, sr - -#if defined(CONFIG_PREEMPT) -# define preempt_stop() CLI() -#else -# define preempt_stop() -# define resume_kernel restore_all -#endif - #if defined(CONFIG_MMU) .align 2 ENTRY(tlb_miss_load) @@ -155,29 +138,14 @@ ENTRY(tlb_protection_violation_store) call_dpf: mov.l 1f, r0 - mov r5, r8 - mov.l @r0, r6 - mov r6, r9 - mov.l 2f, r0 - sts pr, r10 - jsr @r0 - mov r15, r4 - ! - tst r0, r0 - bf/s 0f - lds r10, pr - rts - nop -0: STI() + mov.l @r0, r6 ! address mov.l 3f, r0 - mov r9, r6 - mov r8, r5 + jmp @r0 - mov r15, r4 + mov r15, r4 ! regs .align 2 1: .long MMU_TEA -2: .long __do_page_fault 3: .long do_page_fault .align 2 @@ -203,32 +171,6 @@ call_dae: 2: .long do_address_error #endif /* CONFIG_MMU */ -#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB) -! Handle kernel debug if either kgdb (SW) or gdb-stub (FW) is present. -! If both are configured, handle the debug traps (breakpoints) in SW, -! but still allow BIOS traps to FW. - - .align 2 -debug_kernel: -#if defined(CONFIG_SH_STANDARD_BIOS) && defined(CONFIG_SH_KGDB) - /* Force BIOS call to FW (debug_trap put TRA in r8) */ - mov r8,r0 - shlr2 r0 - cmp/eq #0x3f,r0 - bt debug_kernel_fw -#endif /* CONFIG_SH_STANDARD_BIOS && CONFIG_SH_KGDB */ - -debug_enter: -#if defined(CONFIG_SH_KGDB) - /* Jump to kgdb, pass stacked regs as arg */ -debug_kernel_sw: - mov.l 3f, r0 - jmp @r0 - mov r15, r4 - .align 2 -3: .long kgdb_handle_exception -#endif /* CONFIG_SH_KGDB */ - #if defined(CONFIG_SH_STANDARD_BIOS) /* Unwind the stack and jmp to the debug entry */ debug_kernel_fw: @@ -269,276 +211,6 @@ debug_kernel_fw: 2: .long gdb_vbr_vector #endif /* CONFIG_SH_STANDARD_BIOS */ -#endif /* CONFIG_SH_STANDARD_BIOS || CONFIG_SH_KGDB */ - - - .align 2 -debug_trap: -#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB) - mov #OFF_SR, r0 - mov.l @(r0,r15), r0 ! get status register - shll r0 - shll r0 ! kernel space? - bt/s debug_kernel -#endif - mov.l @r15, r0 ! Restore R0 value - mov.l 1f, r8 - jmp @r8 - nop - - .align 2 -ENTRY(exception_error) - ! - STI() - mov.l 2f, r0 - jmp @r0 - nop - -! - .align 2 -1: .long break_point_trap_software -2: .long do_exception_error - - .align 2 -ret_from_exception: - preempt_stop() -ENTRY(ret_from_irq) - ! - mov #OFF_SR, r0 - mov.l @(r0,r15), r0 ! get status register - shll r0 - shll r0 ! kernel space? - bt/s resume_kernel ! Yes, it's from kernel, go back soon - GET_THREAD_INFO(r8) - -#ifdef CONFIG_PREEMPT - bra resume_userspace - nop -ENTRY(resume_kernel) - mov.l @(TI_PRE_COUNT,r8), r0 ! current_thread_info->preempt_count - tst r0, r0 - bf noresched -need_resched: - mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags - tst #_TIF_NEED_RESCHED, r0 ! need_resched set? - bt noresched - - mov #OFF_SR, r0 - mov.l @(r0,r15), r0 ! get status register - and #0xf0, r0 ! interrupts off (exception path)? - cmp/eq #0xf0, r0 - bt noresched - - mov.l 1f, r0 - mov.l r0, @(TI_PRE_COUNT,r8) - - STI() - mov.l 2f, r0 - jsr @r0 - nop - mov #0, r0 - mov.l r0, @(TI_PRE_COUNT,r8) - CLI() - - bra need_resched - nop -noresched: - bra restore_all - nop - - .align 2 -1: .long PREEMPT_ACTIVE -2: .long schedule -#endif - -ENTRY(resume_userspace) - ! r8: current_thread_info - CLI() - mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags - tst #_TIF_WORK_MASK, r0 - bt/s restore_all - tst #_TIF_NEED_RESCHED, r0 - - .align 2 -work_pending: - ! r0: current_thread_info->flags - ! r8: current_thread_info - ! t: result of "tst #_TIF_NEED_RESCHED, r0" - bf/s work_resched - tst #(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK), r0 -work_notifysig: - bt/s restore_all - mov r15, r4 - mov r12, r5 ! set arg1(save_r0) - mov r0, r6 - mov.l 2f, r1 - mova restore_all, r0 - jmp @r1 - lds r0, pr -work_resched: -#ifndef CONFIG_PREEMPT - ! gUSA handling - mov.l @(OFF_SP,r15), r0 ! get user space stack pointer - mov r0, r1 - shll r0 - bf/s 1f - shll r0 - bf/s 1f - mov #OFF_PC, r0 - ! SP >= 0xc0000000 : gUSA mark - mov.l @(r0,r15), r2 ! get user space PC (program counter) - mov.l @(OFF_R0,r15), r3 ! end point - cmp/hs r3, r2 ! r2 >= r3? - bt 1f - add r3, r1 ! rewind point #2 - mov.l r1, @(r0,r15) ! reset PC to rewind point #2 - ! -1: -#endif - mov.l 1f, r1 - jsr @r1 ! schedule - nop - CLI() - ! - mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags - tst #_TIF_WORK_MASK, r0 - bt restore_all - bra work_pending - tst #_TIF_NEED_RESCHED, r0 - - .align 2 -1: .long schedule -2: .long do_notify_resume - - .align 2 -syscall_exit_work: - ! r0: current_thread_info->flags - ! r8: current_thread_info - tst #_TIF_SYSCALL_TRACE, r0 - bt/s work_pending - tst #_TIF_NEED_RESCHED, r0 - STI() - ! XXX setup arguments... - mov.l 4f, r0 ! do_syscall_trace - jsr @r0 - nop - bra resume_userspace - nop - - .align 2 -syscall_trace_entry: - ! Yes it is traced. - ! XXX setup arguments... - mov.l 4f, r11 ! Call do_syscall_trace which notifies - jsr @r11 ! superior (will chomp R[0-7]) - nop - ! Reload R0-R4 from kernel stack, where the - ! parent may have modified them using - ! ptrace(POKEUSR). (Note that R0-R2 are - ! used by the system call handler directly - ! from the kernel stack anyway, so don't need - ! to be reloaded here.) This allows the parent - ! to rewrite system calls and args on the fly. - mov.l @(OFF_R4,r15), r4 ! arg0 - mov.l @(OFF_R5,r15), r5 - mov.l @(OFF_R6,r15), r6 - mov.l @(OFF_R7,r15), r7 ! arg3 - mov.l @(OFF_R3,r15), r3 ! syscall_nr - ! Arrange for do_syscall_trace to be called - ! again as the system call returns. - mov.l 2f, r10 ! Number of syscalls - cmp/hs r10, r3 - bf syscall_call - mov #-ENOSYS, r0 - bra syscall_exit - mov.l r0, @(OFF_R0,r15) ! Return value - -/* - * Syscall interface: - * - * Syscall #: R3 - * Arguments #0 to #3: R4--R7 - * Arguments #4 to #6: R0, R1, R2 - * TRA: (number of arguments + 0x10) x 4 - * - * This code also handles delegating other traps to the BIOS/gdb stub - * according to: - * - * Trap number - * (TRA>>2) Purpose - * -------- ------- - * 0x0-0xf old syscall ABI - * 0x10-0x1f new syscall ABI - * 0x20-0xff delegated through debug_trap to BIOS/gdb stub. - * - * Note: When we're first called, the TRA value must be shifted - * right 2 bits in order to get the value that was used as the "trapa" - * argument. - */ - - .align 2 - .globl ret_from_fork -ret_from_fork: - mov.l 1f, r8 - jsr @r8 - mov r0, r4 - bra syscall_exit - nop - .align 2 -1: .long schedule_tail - ! -ENTRY(system_call) - mov.l 1f, r9 - mov.l @r9, r8 ! Read from TRA (Trap Address) Register - ! - ! Is the trap argument >= 0x20? (TRA will be >= 0x80) - mov #0x7f, r9 - cmp/hi r9, r8 - bt/s 0f - mov #OFF_TRA, r9 - add r15, r9 - ! - mov.l r8, @r9 ! set TRA value to tra - STI() - ! Call the system call handler through the table. - ! First check for bad syscall number - mov r3, r9 - mov.l 2f, r8 ! Number of syscalls - cmp/hs r8, r9 - bf/s good_system_call - GET_THREAD_INFO(r8) -syscall_badsys: ! Bad syscall number - mov #-ENOSYS, r0 - bra resume_userspace - mov.l r0, @(OFF_R0,r15) ! Return value - ! -0: - bra debug_trap - nop - ! -good_system_call: ! Good syscall number - mov.l @(TI_FLAGS,r8), r8 - mov #_TIF_SYSCALL_TRACE, r10 - tst r10, r8 - bf syscall_trace_entry - ! -syscall_call: - shll2 r9 ! x4 - mov.l 3f, r8 ! Load the address of sys_call_table - add r8, r9 - mov.l @r9, r8 - jsr @r8 ! jump to specific syscall handler - nop - mov.l @(OFF_R0,r15), r12 ! save r0 - mov.l r0, @(OFF_R0,r15) ! save the return value - ! -syscall_exit: - CLI() - ! - GET_THREAD_INFO(r8) - mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags - tst #_TIF_ALLWORK_MASK, r0 - bf syscall_exit_work restore_all: mov.l @r15+, r0 mov.l @r15+, r1 @@ -606,7 +278,9 @@ skip_restore: ! ! Calculate new SR value mov k3, k2 ! original SR value - mov.l 9f, k1 + mov #0xf0, k1 + extu.b k1, k1 + not k1, k1 and k1, k2 ! Mask orignal SR value ! mov k3, k0 ! Calculate IMASK-bits @@ -632,16 +306,12 @@ skip_restore: nop .align 2 -1: .long TRA -2: .long NR_syscalls -3: .long sys_call_table -4: .long do_syscall_trace 5: .long 0x00001000 ! DSP 7: .long 0x30000000 -9: -__INV_IMASK: - .long 0xffffff0f ! ~(IMASK) +! common exception handler +#include "../../entry-common.S" + ! Exception Vector Base ! ! Should be aligned page boundary. @@ -661,9 +331,176 @@ general_exception: 2: .long ret_from_exception ! ! + +/* This code makes some assumptions to improve performance. + * Make sure they are stil true. */ +#if PTRS_PER_PGD != PTRS_PER_PTE +#error PGD and PTE sizes don't match +#endif + +/* gas doesn't flag impossible values for mov #immediate as an error */ +#if (_PAGE_PRESENT >> 2) > 0x7f +#error cannot load PAGE_PRESENT as an immediate +#endif +#if _PAGE_DIRTY > 0x7f +#error cannot load PAGE_DIRTY as an immediate +#endif +#if (_PAGE_PRESENT << 2) != _PAGE_ACCESSED +#error cannot derive PAGE_ACCESSED from PAGE_PRESENT +#endif + +#if defined(CONFIG_CPU_SH4) +#define ldmmupteh(r) mov.l 8f, r +#else +#define ldmmupteh(r) mov #MMU_PTEH, r +#endif + .balign 1024,0,1024 tlb_miss: - mov.l 1f, k2 +#ifdef COUNT_EXCEPTIONS + ! Increment the counts + mov.l 9f, k1 + mov.l @k1, k2 + add #1, k2 + mov.l k2, @k1 +#endif + + ! k0 scratch + ! k1 pgd and pte pointers + ! k2 faulting address + ! k3 pgd and pte index masks + ! k4 shift + + ! Load up the pgd entry (k1) + + ldmmupteh(k0) ! 9 LS (latency=2) MMU_PTEH + + mov.w 4f, k3 ! 8 LS (latency=2) (PTRS_PER_PGD-1) << 2 + mov #-(PGDIR_SHIFT-2), k4 ! 6 EX + + mov.l @(MMU_TEA-MMU_PTEH,k0), k2 ! 18 LS (latency=2) + + mov.l @(MMU_TTB-MMU_PTEH,k0), k1 ! 18 LS (latency=2) + + mov k2, k0 ! 5 MT (latency=0) + shld k4, k0 ! 99 EX + + and k3, k0 ! 78 EX + + mov.l @(k0, k1), k1 ! 21 LS (latency=2) + mov #-(PAGE_SHIFT-2), k4 ! 6 EX + + ! Load up the pte entry (k2) + + mov k2, k0 ! 5 MT (latency=0) + shld k4, k0 ! 99 EX + + tst k1, k1 ! 86 MT + + bt 20f ! 110 BR + + and k3, k0 ! 78 EX + mov.w 5f, k4 ! 8 LS (latency=2) _PAGE_PRESENT + + mov.l @(k0, k1), k2 ! 21 LS (latency=2) + add k0, k1 ! 49 EX + +#ifdef CONFIG_CPU_HAS_PTEA + ! Test the entry for present and _PAGE_ACCESSED + + mov #-28, k3 ! 6 EX + mov k2, k0 ! 5 MT (latency=0) + + tst k4, k2 ! 68 MT + shld k3, k0 ! 99 EX + + bt 20f ! 110 BR + + ! Set PTEA register + ! MMU_PTEA = ((pteval >> 28) & 0xe) | (pteval & 0x1) + ! + ! k0=pte>>28, k1=pte*, k2=pte, k3=, k4=_PAGE_PRESENT + + and #0xe, k0 ! 79 EX + + mov k0, k3 ! 5 MT (latency=0) + mov k2, k0 ! 5 MT (latency=0) + + and #1, k0 ! 79 EX + + or k0, k3 ! 82 EX + + ldmmupteh(k0) ! 9 LS (latency=2) + shll2 k4 ! 101 EX _PAGE_ACCESSED + + tst k4, k2 ! 68 MT + + mov.l k3, @(MMU_PTEA-MMU_PTEH,k0) ! 27 LS + + mov.l 7f, k3 ! 9 LS (latency=2) _PAGE_FLAGS_HARDWARE_MASK + + ! k0=MMU_PTEH, k1=pte*, k2=pte, k3=_PAGE_FLAGS_HARDWARE, k4=_PAGE_ACCESSED +#else + + ! Test the entry for present and _PAGE_ACCESSED + + mov.l 7f, k3 ! 9 LS (latency=2) _PAGE_FLAGS_HARDWARE_MASK + tst k4, k2 ! 68 MT + + shll2 k4 ! 101 EX _PAGE_ACCESSED + ldmmupteh(k0) ! 9 LS (latency=2) + + bt 20f ! 110 BR + tst k4, k2 ! 68 MT + + ! k0=MMU_PTEH, k1=pte*, k2=pte, k3=_PAGE_FLAGS_HARDWARE, k4=_PAGE_ACCESSED + +#endif + + ! Set up the entry + + and k2, k3 ! 78 EX + bt/s 10f ! 108 BR + + mov.l k3, @(MMU_PTEL-MMU_PTEH,k0) ! 27 LS + + ldtlb ! 128 CO + + ! At least one instruction between ldtlb and rte + nop ! 119 NOP + + rte ! 126 CO + + nop ! 119 NOP + + +10: or k4, k2 ! 82 EX + + ldtlb ! 128 CO + + ! At least one instruction between ldtlb and rte + mov.l k2, @k1 ! 27 LS + + rte ! 126 CO + + ! Note we cannot execute mov here, because it is executed after + ! restoring SSR, so would be executed in user space. + nop ! 119 NOP + + + .align 5 + ! Once cache line if possible... +1: .long swapper_pg_dir +4: .short (PTRS_PER_PGD-1) << 2 +5: .short _PAGE_PRESENT +7: .long _PAGE_FLAGS_HARDWARE_MASK +8: .long MMU_PTEH +#ifdef COUNT_EXCEPTIONS +9: .long exception_count_miss +#endif + + ! Either pgd or pte not present +20: mov.l 1f, k2 mov.l 4f, k3 bra handle_exception mov.l @k2, k2 @@ -710,8 +547,9 @@ ENTRY(handle_exception) bt/s 1f ! It's a kernel to kernel transition. mov r15, k0 ! save original stack to k0 /* User space to kernel */ - mov #(THREAD_SIZE >> 8), k1 + mov #(THREAD_SIZE >> 10), k1 shll8 k1 ! k1 := THREAD_SIZE + shll2 k1 add current, k1 mov k1, r15 ! change to kernel stack ! @@ -761,7 +599,7 @@ skip_save: ! Save the user registers on the stack. mov.l k2, @-r15 ! EXPEVT - mov #-1, k4 + mov #-1, k4 mov.l k4, @-r15 ! set TRA (default: -1) ! sts.l macl, @-r15 @@ -813,6 +651,15 @@ skip_save: bf interrupt_exception shlr2 r8 shlr r8 + +#ifdef COUNT_EXCEPTIONS + mov.l 5f, r9 + add r8, r9 + mov.l @r9, r10 + add #1, r10 + mov.l r10, @r9 +#endif + mov.l 4f, r9 add r8, r9 mov.l @r9, r9 @@ -826,6 +673,9 @@ skip_save: 2: .long 0x000080f0 ! FD=1, IMASK=15 3: .long 0xcfffffff ! RB=0, BL=0 4: .long exception_handling_table +#ifdef COUNT_EXCEPTIONS +5: .long exception_count_table +#endif interrupt_exception: mov.l 1f, r9 diff --git a/trunk/arch/sh/kernel/cpu/sh4/Makefile b/trunk/arch/sh/kernel/cpu/sh4/Makefile index 8dbf3895ece7..6e415baf04b4 100644 --- a/trunk/arch/sh/kernel/cpu/sh4/Makefile +++ b/trunk/arch/sh/kernel/cpu/sh4/Makefile @@ -2,7 +2,8 @@ # Makefile for the Linux/SuperH SH-4 backends. # -obj-y := ex.o probe.o +obj-y := ex.o probe.o common.o +common-y += $(addprefix ../sh3/, entry.o) obj-$(CONFIG_SH_FPU) += fpu.o obj-$(CONFIG_SH_STORE_QUEUES) += sq.o diff --git a/trunk/arch/sh/kernel/cpu/sh4/clock-sh4-202.c b/trunk/arch/sh/kernel/cpu/sh4/clock-sh4-202.c index bfdf5fe8d948..fa2019aabd74 100644 --- a/trunk/arch/sh/kernel/cpu/sh4/clock-sh4-202.c +++ b/trunk/arch/sh/kernel/cpu/sh4/clock-sh4-202.c @@ -97,7 +97,7 @@ static void shoc_clk_recalc(struct clk *clk) static int shoc_clk_verify_rate(struct clk *clk, unsigned long rate) { - struct clk *bclk = clk_get("bus_clk"); + struct clk *bclk = clk_get(NULL, "bus_clk"); unsigned long bclk_rate = clk_get_rate(bclk); clk_put(bclk); @@ -151,7 +151,7 @@ static struct clk *sh4202_onchip_clocks[] = { static int __init sh4202_clk_init(void) { - struct clk *clk = clk_get("master_clk"); + struct clk *clk = clk_get(NULL, "master_clk"); int i; for (i = 0; i < ARRAY_SIZE(sh4202_onchip_clocks); i++) { diff --git a/trunk/arch/sh/kernel/cpu/sh4/clock-sh7780.c b/trunk/arch/sh/kernel/cpu/sh4/clock-sh7780.c index 93ad367342c9..9e6a216750c8 100644 --- a/trunk/arch/sh/kernel/cpu/sh4/clock-sh7780.c +++ b/trunk/arch/sh/kernel/cpu/sh4/clock-sh7780.c @@ -98,7 +98,7 @@ static struct clk *sh7780_onchip_clocks[] = { static int __init sh7780_clk_init(void) { - struct clk *clk = clk_get("master_clk"); + struct clk *clk = clk_get(NULL, "master_clk"); int i; for (i = 0; i < ARRAY_SIZE(sh7780_onchip_clocks); i++) { diff --git a/trunk/arch/sh/kernel/cpu/sh4/fpu.c b/trunk/arch/sh/kernel/cpu/sh4/fpu.c index f486c07e10e2..7624677f6628 100644 --- a/trunk/arch/sh/kernel/cpu/sh4/fpu.c +++ b/trunk/arch/sh/kernel/cpu/sh4/fpu.c @@ -282,11 +282,8 @@ ieee_fpe_handler (struct pt_regs *regs) grab_fpu(regs); restore_fpu(tsk); set_tsk_thread_flag(tsk, TIF_USEDFPU); - } else { - tsk->thread.trap_no = 11; - tsk->thread.error_code = 0; + } else force_sig(SIGFPE, tsk); - } regs->pc = nextpc; return 1; @@ -296,29 +293,29 @@ ieee_fpe_handler (struct pt_regs *regs) } asmlinkage void -do_fpu_error(unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7, - struct pt_regs regs) +do_fpu_error(unsigned long r4, unsigned long r5, unsigned long r6, + unsigned long r7, struct pt_regs __regs) { + struct pt_regs *regs = RELOC_HIDE(&__regs, 0); struct task_struct *tsk = current; - if (ieee_fpe_handler (®s)) + if (ieee_fpe_handler(regs)) return; - regs.pc += 2; - save_fpu(tsk, ®s); - tsk->thread.trap_no = 11; - tsk->thread.error_code = 0; + regs->pc += 2; + save_fpu(tsk, regs); force_sig(SIGFPE, tsk); } asmlinkage void do_fpu_state_restore(unsigned long r4, unsigned long r5, unsigned long r6, - unsigned long r7, struct pt_regs regs) + unsigned long r7, struct pt_regs __regs) { + struct pt_regs *regs = RELOC_HIDE(&__regs, 0); struct task_struct *tsk = current; - grab_fpu(®s); - if (!user_mode(®s)) { + grab_fpu(regs); + if (!user_mode(regs)) { printk(KERN_ERR "BUG: FPU is used in kernel mode.\n"); return; } diff --git a/trunk/arch/sh/kernel/cpu/sh4/probe.c b/trunk/arch/sh/kernel/cpu/sh4/probe.c index c294de1e14a3..afe0f1b1c030 100644 --- a/trunk/arch/sh/kernel/cpu/sh4/probe.c +++ b/trunk/arch/sh/kernel/cpu/sh4/probe.c @@ -79,16 +79,16 @@ int __init detect_cpu_and_cache_system(void) case 0x205: cpu_data->type = CPU_SH7750; cpu_data->flags |= CPU_HAS_P2_FLUSH_BUG | CPU_HAS_FPU | - CPU_HAS_PERF_COUNTER | CPU_HAS_PTEA; + CPU_HAS_PERF_COUNTER; break; case 0x206: cpu_data->type = CPU_SH7750S; cpu_data->flags |= CPU_HAS_P2_FLUSH_BUG | CPU_HAS_FPU | - CPU_HAS_PERF_COUNTER | CPU_HAS_PTEA; + CPU_HAS_PERF_COUNTER; break; case 0x1100: cpu_data->type = CPU_SH7751; - cpu_data->flags |= CPU_HAS_FPU | CPU_HAS_PTEA; + cpu_data->flags |= CPU_HAS_FPU; break; case 0x2000: cpu_data->type = CPU_SH73180; @@ -126,23 +126,22 @@ int __init detect_cpu_and_cache_system(void) break; case 0x8000: cpu_data->type = CPU_ST40RA; - cpu_data->flags |= CPU_HAS_FPU | CPU_HAS_PTEA; + cpu_data->flags |= CPU_HAS_FPU; break; case 0x8100: cpu_data->type = CPU_ST40GX1; - cpu_data->flags |= CPU_HAS_FPU | CPU_HAS_PTEA; + cpu_data->flags |= CPU_HAS_FPU; break; case 0x700: cpu_data->type = CPU_SH4_501; cpu_data->icache.ways = 2; cpu_data->dcache.ways = 2; - cpu_data->flags |= CPU_HAS_PTEA; break; case 0x600: cpu_data->type = CPU_SH4_202; cpu_data->icache.ways = 2; cpu_data->dcache.ways = 2; - cpu_data->flags |= CPU_HAS_FPU | CPU_HAS_PTEA; + cpu_data->flags |= CPU_HAS_FPU; break; case 0x500 ... 0x501: switch (prr) { @@ -160,7 +159,7 @@ int __init detect_cpu_and_cache_system(void) cpu_data->icache.ways = 2; cpu_data->dcache.ways = 2; - cpu_data->flags |= CPU_HAS_FPU | CPU_HAS_PTEA; + cpu_data->flags |= CPU_HAS_FPU; break; default: @@ -173,6 +172,10 @@ int __init detect_cpu_and_cache_system(void) cpu_data->dcache.ways = 1; #endif +#ifdef CONFIG_CPU_HAS_PTEA + cpu_data->flags |= CPU_HAS_PTEA; +#endif + /* * On anything that's not a direct-mapped cache, look to the CVR * for I/D-cache specifics. diff --git a/trunk/arch/sh/kernel/cpu/sh4/setup-sh7750.c b/trunk/arch/sh/kernel/cpu/sh4/setup-sh7750.c index 50812d57c1c1..bbcb06f18b04 100644 --- a/trunk/arch/sh/kernel/cpu/sh4/setup-sh7750.c +++ b/trunk/arch/sh/kernel/cpu/sh4/setup-sh7750.c @@ -2,6 +2,7 @@ * SH7750/SH7751 Setup * * Copyright (C) 2006 Paul Mundt + * Copyright (C) 2006 Jamie Lenehan * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive @@ -10,6 +11,7 @@ #include #include #include +#include #include static struct plat_sci_port sci_platform_data[] = { @@ -46,3 +48,71 @@ static int __init sh7750_devices_setup(void) ARRAY_SIZE(sh7750_devices)); } __initcall(sh7750_devices_setup); + +static struct ipr_data sh7750_ipr_map[] = { + /* IRQ, IPR-idx, shift, priority */ + { 16, 0, 12, 2 }, /* TMU0 TUNI*/ + { 17, 0, 12, 2 }, /* TMU1 TUNI */ + { 18, 0, 4, 2 }, /* TMU2 TUNI */ + { 19, 0, 4, 2 }, /* TMU2 TIPCI */ + { 27, 1, 12, 2 }, /* WDT ITI */ + { 20, 0, 0, 2 }, /* RTC ATI (alarm) */ + { 21, 0, 0, 2 }, /* RTC PRI (period) */ + { 22, 0, 0, 2 }, /* RTC CUI (carry) */ + { 23, 1, 4, 3 }, /* SCI ERI */ + { 24, 1, 4, 3 }, /* SCI RXI */ + { 25, 1, 4, 3 }, /* SCI TXI */ + { 40, 2, 4, 3 }, /* SCIF ERI */ + { 41, 2, 4, 3 }, /* SCIF RXI */ + { 42, 2, 4, 3 }, /* SCIF BRI */ + { 43, 2, 4, 3 }, /* SCIF TXI */ + { 34, 2, 8, 7 }, /* DMAC DMTE0 */ + { 35, 2, 8, 7 }, /* DMAC DMTE1 */ + { 36, 2, 8, 7 }, /* DMAC DMTE2 */ + { 37, 2, 8, 7 }, /* DMAC DMTE3 */ + { 28, 2, 8, 7 }, /* DMAC DMAE */ +}; + +static struct ipr_data sh7751_ipr_map[] = { + { 44, 2, 8, 7 }, /* DMAC DMTE4 */ + { 45, 2, 8, 7 }, /* DMAC DMTE5 */ + { 46, 2, 8, 7 }, /* DMAC DMTE6 */ + { 47, 2, 8, 7 }, /* DMAC DMTE7 */ + /* The following use INTC_INPRI00 for masking, which is a 32-bit + register, not a 16-bit register like the IPRx registers, so it + would need special support */ + /*{ 72, INTPRI00, 8, ? },*/ /* TMU3 TUNI */ + /*{ 76, INTPRI00, 12, ? },*/ /* TMU4 TUNI */ +}; + +static unsigned long ipr_offsets[] = { + 0xffd00004UL, /* 0: IPRA */ + 0xffd00008UL, /* 1: IPRB */ + 0xffd0000cUL, /* 2: IPRC */ + 0xffd00010UL, /* 3: IPRD */ +}; + +/* given the IPR index return the address of the IPR register */ +unsigned int map_ipridx_to_addr(int idx) +{ + if (idx >= ARRAY_SIZE(ipr_offsets)) + return 0; + return ipr_offsets[idx]; +} + +#define INTC_ICR 0xffd00000UL +#define INTC_ICR_IRLM (1<<7) + +/* enable individual interrupt mode for external interupts */ +void ipr_irq_enable_irlm(void) +{ + ctrl_outw(ctrl_inw(INTC_ICR) | INTC_ICR_IRLM, INTC_ICR); +} + +void __init init_IRQ_ipr() +{ + make_ipr_irq(sh7750_ipr_map, ARRAY_SIZE(sh7750_ipr_map)); +#ifdef CONFIG_CPU_SUBTYPE_SH7751 + make_ipr_irq(sh7751_ipr_map, ARRAY_SIZE(sh7751_ipr_map)); +#endif +} diff --git a/trunk/arch/sh/kernel/cpu/sh4/setup-sh7780.c b/trunk/arch/sh/kernel/cpu/sh4/setup-sh7780.c index 814ddb226531..9aeaa2ddaa28 100644 --- a/trunk/arch/sh/kernel/cpu/sh4/setup-sh7780.c +++ b/trunk/arch/sh/kernel/cpu/sh4/setup-sh7780.c @@ -79,25 +79,27 @@ static int __init sh7780_devices_setup(void) __initcall(sh7780_devices_setup); static struct intc2_data intc2_irq_table[] = { - { TIMER_IRQ, 0, 24, 0, INTC_TMU0_MSK, 2 }, - { 21, 1, 0, 0, INTC_RTC_MSK, TIMER_PRIORITY }, - { 22, 1, 1, 0, INTC_RTC_MSK, TIMER_PRIORITY }, - { 23, 1, 2, 0, INTC_RTC_MSK, TIMER_PRIORITY }, - { SCIF0_ERI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY }, - { SCIF0_RXI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY }, - { SCIF0_BRI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY }, - { SCIF0_TXI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY }, + { 28, 0, 24, 0, 0, 2 }, /* TMU0 */ - { SCIF1_ERI_IRQ, 8, 16, 0, INTC_SCIF1_MSK, SCIF1_PRIORITY }, - { SCIF1_RXI_IRQ, 8, 16, 0, INTC_SCIF1_MSK, SCIF1_PRIORITY }, - { SCIF1_BRI_IRQ, 8, 16, 0, INTC_SCIF1_MSK, SCIF1_PRIORITY }, - { SCIF1_TXI_IRQ, 8, 16, 0, INTC_SCIF1_MSK, SCIF1_PRIORITY }, + { 21, 1, 0, 0, 2, 2 }, + { 22, 1, 1, 0, 2, 2 }, + { 23, 1, 2, 0, 2, 2 }, - { PCIC0_IRQ, 0x10, 8, 0, INTC_PCIC0_MSK, PCIC0_PRIORITY }, - { PCIC1_IRQ, 0x10, 0, 0, INTC_PCIC1_MSK, PCIC1_PRIORITY }, - { PCIC2_IRQ, 0x14, 24, 0, INTC_PCIC2_MSK, PCIC2_PRIORITY }, - { PCIC3_IRQ, 0x14, 16, 0, INTC_PCIC3_MSK, PCIC3_PRIORITY }, - { PCIC4_IRQ, 0x14, 8, 0, INTC_PCIC4_MSK, PCIC4_PRIORITY }, + { 40, 8, 24, 0, 3, 3 }, /* SCIF0 ERI */ + { 41, 8, 24, 0, 3, 3 }, /* SCIF0 RXI */ + { 42, 8, 24, 0, 3, 3 }, /* SCIF0 BRI */ + { 43, 8, 24, 0, 3, 3 }, /* SCIF0 TXI */ + + { 76, 8, 16, 0, 4, 3 }, /* SCIF1 ERI */ + { 77, 8, 16, 0, 4, 3 }, /* SCIF1 RXI */ + { 78, 8, 16, 0, 4, 3 }, /* SCIF1 BRI */ + { 79, 8, 16, 0, 4, 3 }, /* SCIF1 TXI */ + + { 64, 0x10, 8, 0, 14, 2 }, /* PCIC0 */ + { 65, 0x10, 0, 0, 15, 2 }, /* PCIC1 */ + { 66, 0x14, 24, 0, 16, 2 }, /* PCIC2 */ + { 67, 0x14, 16, 0, 17, 2 }, /* PCIC3 */ + { 68, 0x14, 8, 0, 18, 2 }, /* PCIC4 */ }; void __init init_IRQ_intc2(void) diff --git a/trunk/arch/sh/kernel/cpu/sh4/sq.c b/trunk/arch/sh/kernel/cpu/sh4/sq.c index 7bcc73f9b8df..0c9ea38d2caa 100644 --- a/trunk/arch/sh/kernel/cpu/sh4/sq.c +++ b/trunk/arch/sh/kernel/cpu/sh4/sq.c @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include #include #include @@ -38,7 +38,7 @@ struct sq_mapping { static struct sq_mapping *sq_mapping_list; static DEFINE_SPINLOCK(sq_mapping_lock); -static kmem_cache_t *sq_cache; +static struct kmem_cache *sq_cache; static unsigned long *sq_bitmap; #define store_queue_barrier() \ @@ -67,6 +67,7 @@ void sq_flush_range(unsigned long start, unsigned int len) /* Wait for completion */ store_queue_barrier(); } +EXPORT_SYMBOL(sq_flush_range); static inline void sq_mapping_list_add(struct sq_mapping *map) { @@ -166,7 +167,7 @@ unsigned long sq_remap(unsigned long phys, unsigned int size, map->size = size; map->name = name; - page = bitmap_find_free_region(sq_bitmap, 0x04000000, + page = bitmap_find_free_region(sq_bitmap, 0x04000000 >> PAGE_SHIFT, get_order(map->size)); if (unlikely(page < 0)) { ret = -ENOSPC; @@ -193,6 +194,7 @@ unsigned long sq_remap(unsigned long phys, unsigned int size, kmem_cache_free(sq_cache, map); return ret; } +EXPORT_SYMBOL(sq_remap); /** * sq_unmap - Unmap a Store Queue allocation @@ -234,6 +236,7 @@ void sq_unmap(unsigned long vaddr) kmem_cache_free(sq_cache, map); } +EXPORT_SYMBOL(sq_unmap); /* * Needlessly complex sysfs interface. Unfortunately it doesn't seem like @@ -402,7 +405,3 @@ module_exit(sq_api_exit); MODULE_AUTHOR("Paul Mundt , M. R. Brown "); MODULE_DESCRIPTION("Simple API for SH-4 integrated Store Queues"); MODULE_LICENSE("GPL"); - -EXPORT_SYMBOL(sq_remap); -EXPORT_SYMBOL(sq_unmap); -EXPORT_SYMBOL(sq_flush_range); diff --git a/trunk/arch/sh/kernel/early_printk.c b/trunk/arch/sh/kernel/early_printk.c index a00022722e9e..60340823798a 100644 --- a/trunk/arch/sh/kernel/early_printk.c +++ b/trunk/arch/sh/kernel/early_printk.c @@ -12,7 +12,7 @@ #include #include #include -#include +#include #ifdef CONFIG_SH_STANDARD_BIOS #include @@ -62,17 +62,9 @@ static struct console bios_console = { #include #include "../../../drivers/serial/sh-sci.h" -#ifdef CONFIG_CPU_SH4 -#define SCIF_REG 0xffe80000 -#elif defined(CONFIG_CPU_SUBTYPE_SH72060) -#define SCIF_REG 0xfffe9800 -#else -#error "Undefined SCIF for this subtype" -#endif - static struct uart_port scif_port = { - .mapbase = SCIF_REG, - .membase = (char __iomem *)SCIF_REG, + .mapbase = CONFIG_EARLY_SCIF_CONSOLE_PORT, + .membase = (char __iomem *)CONFIG_EARLY_SCIF_CONSOLE_PORT, }; static void scif_sercon_putc(int c) @@ -113,23 +105,29 @@ static struct console scif_console = { .index = -1, }; +#if defined(CONFIG_CPU_SH4) && !defined(CONFIG_SH_STANDARD_BIOS) +/* + * Simple SCIF init, primarily aimed at SH7750 and other similar SH-4 + * devices that aren't using sh-ipl+g. + */ static void scif_sercon_init(int baud) { - ctrl_outw(0, SCIF_REG + 8); - ctrl_outw(0, SCIF_REG); + ctrl_outw(0, scif_port.mapbase + 8); + ctrl_outw(0, scif_port.mapbase); /* Set baud rate */ ctrl_outb((CONFIG_SH_PCLK_FREQ + 16 * baud) / - (32 * baud) - 1, SCIF_REG + 4); - - ctrl_outw(12, SCIF_REG + 24); - ctrl_outw(8, SCIF_REG + 24); - ctrl_outw(0, SCIF_REG + 32); - ctrl_outw(0x60, SCIF_REG + 16); - ctrl_outw(0, SCIF_REG + 36); - ctrl_outw(0x30, SCIF_REG + 8); + (32 * baud) - 1, scif_port.mapbase + 4); + + ctrl_outw(12, scif_port.mapbase + 24); + ctrl_outw(8, scif_port.mapbase + 24); + ctrl_outw(0, scif_port.mapbase + 32); + ctrl_outw(0x60, scif_port.mapbase + 16); + ctrl_outw(0, scif_port.mapbase + 36); + ctrl_outw(0x30, scif_port.mapbase + 8); } -#endif +#endif /* CONFIG_CPU_SH4 && !CONFIG_SH_STANDARD_BIOS */ +#endif /* CONFIG_EARLY_SCIF_CONSOLE */ /* * Setup a default console, if more than one is compiled in, rely on the @@ -168,7 +166,7 @@ int __init setup_early_printk(char *opt) if (!strncmp(buf, "serial", 6)) { early_console = &scif_console; -#ifdef CONFIG_CPU_SH4 +#if defined(CONFIG_CPU_SH4) && !defined(CONFIG_SH_STANDARD_BIOS) scif_sercon_init(115200); #endif } diff --git a/trunk/arch/sh/kernel/entry-common.S b/trunk/arch/sh/kernel/entry-common.S new file mode 100644 index 000000000000..29136a35d7c7 --- /dev/null +++ b/trunk/arch/sh/kernel/entry-common.S @@ -0,0 +1,433 @@ +/* $Id: entry.S,v 1.37 2004/06/11 13:02:46 doyu Exp $ + * + * linux/arch/sh/entry.S + * + * Copyright (C) 1999, 2000, 2002 Niibe Yutaka + * Copyright (C) 2003 Paul Mundt + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + */ + +! NOTE: +! GNU as (as of 2.9.1) changes bf/s into bt/s and bra, when the address +! to be jumped is too far, but it causes illegal slot exception. + +/* + * entry.S contains the system-call and fault low-level handling routines. + * This also contains the timer-interrupt handler, as well as all interrupts + * and faults that can result in a task-switch. + * + * NOTE: This code handles signal-recognition, which happens every time + * after a timer-interrupt and after each system call. + * + * NOTE: This code uses a convention that instructions in the delay slot + * of a transfer-control instruction are indented by an extra space, thus: + * + * jmp @k0 ! control-transfer instruction + * ldc k1, ssr ! delay slot + * + * Stack layout in 'ret_from_syscall': + * ptrace needs to have all regs on the stack. + * if the order here is changed, it needs to be + * updated in ptrace.c and ptrace.h + * + * r0 + * ... + * r15 = stack pointer + * spc + * pr + * ssr + * gbr + * mach + * macl + * syscall # + * + */ + +#if defined(CONFIG_PREEMPT) +# define preempt_stop() cli +#else +# define preempt_stop() +# define resume_kernel __restore_all +#endif + +#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB) +! Handle kernel debug if either kgdb (SW) or gdb-stub (FW) is present. +! If both are configured, handle the debug traps (breakpoints) in SW, +! but still allow BIOS traps to FW. + + .align 2 +debug_kernel: +#if defined(CONFIG_SH_STANDARD_BIOS) && defined(CONFIG_SH_KGDB) + /* Force BIOS call to FW (debug_trap put TRA in r8) */ + mov r8,r0 + shlr2 r0 + cmp/eq #0x3f,r0 + bt debug_kernel_fw +#endif /* CONFIG_SH_STANDARD_BIOS && CONFIG_SH_KGDB */ + +debug_enter: +#if defined(CONFIG_SH_KGDB) + /* Jump to kgdb, pass stacked regs as arg */ +debug_kernel_sw: + mov.l 3f, r0 + jmp @r0 + mov r15, r4 + .align 2 +3: .long kgdb_handle_exception +#endif /* CONFIG_SH_KGDB */ + +#endif /* CONFIG_SH_STANDARD_BIOS || CONFIG_SH_KGDB */ + + + .align 2 +debug_trap: +#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB) + mov #OFF_SR, r0 + mov.l @(r0,r15), r0 ! get status register + shll r0 + shll r0 ! kernel space? + bt/s debug_kernel +#endif + mov.l @r15, r0 ! Restore R0 value + mov.l 1f, r8 + jmp @r8 + nop + + .align 2 +ENTRY(exception_error) + ! +#ifdef CONFIG_TRACE_IRQFLAGS + mov.l 3f, r0 + jsr @r0 + nop +#endif + sti + mov.l 2f, r0 + jmp @r0 + nop + +! + .align 2 +1: .long break_point_trap_software +2: .long do_exception_error +#ifdef CONFIG_TRACE_IRQFLAGS +3: .long trace_hardirqs_on +#endif + + .align 2 +ret_from_exception: + preempt_stop() +#ifdef CONFIG_TRACE_IRQFLAGS + mov.l 4f, r0 + jsr @r0 + nop +#endif +ENTRY(ret_from_irq) + ! + mov #OFF_SR, r0 + mov.l @(r0,r15), r0 ! get status register + shll r0 + shll r0 ! kernel space? + get_current_thread_info r8, r0 + bt resume_kernel ! Yes, it's from kernel, go back soon + +#ifdef CONFIG_PREEMPT + bra resume_userspace + nop +ENTRY(resume_kernel) + mov.l @(TI_PRE_COUNT,r8), r0 ! current_thread_info->preempt_count + tst r0, r0 + bf noresched +need_resched: + mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags + tst #_TIF_NEED_RESCHED, r0 ! need_resched set? + bt noresched + + mov #OFF_SR, r0 + mov.l @(r0,r15), r0 ! get status register + and #0xf0, r0 ! interrupts off (exception path)? + cmp/eq #0xf0, r0 + bt noresched + + mov.l 1f, r0 + mov.l r0, @(TI_PRE_COUNT,r8) + +#ifdef CONFIG_TRACE_IRQFLAGS + mov.l 3f, r0 + jsr @r0 + nop +#endif + sti + mov.l 2f, r0 + jsr @r0 + nop + mov #0, r0 + mov.l r0, @(TI_PRE_COUNT,r8) + cli +#ifdef CONFIG_TRACE_IRQFLAGS + mov.l 4f, r0 + jsr @r0 + nop +#endif + + bra need_resched + nop + +noresched: + bra __restore_all + nop + + .align 2 +1: .long PREEMPT_ACTIVE +2: .long schedule +#ifdef CONFIG_TRACE_IRQFLAGS +3: .long trace_hardirqs_on +4: .long trace_hardirqs_off +#endif +#endif + +ENTRY(resume_userspace) + ! r8: current_thread_info + cli +#ifdef CONFIG_TRACE_IRQFLAGS + mov.l 5f, r0 + jsr @r0 + nop +#endif + mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags + tst #_TIF_WORK_MASK, r0 + bt/s __restore_all + tst #_TIF_NEED_RESCHED, r0 + + .align 2 +work_pending: + ! r0: current_thread_info->flags + ! r8: current_thread_info + ! t: result of "tst #_TIF_NEED_RESCHED, r0" + bf/s work_resched + tst #(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK), r0 +work_notifysig: + bt/s __restore_all + mov r15, r4 + mov r12, r5 ! set arg1(save_r0) + mov r0, r6 + mov.l 2f, r1 + mov.l 3f, r0 + jmp @r1 + lds r0, pr +work_resched: +#ifndef CONFIG_PREEMPT + ! gUSA handling + mov.l @(OFF_SP,r15), r0 ! get user space stack pointer + mov r0, r1 + shll r0 + bf/s 1f + shll r0 + bf/s 1f + mov #OFF_PC, r0 + ! SP >= 0xc0000000 : gUSA mark + mov.l @(r0,r15), r2 ! get user space PC (program counter) + mov.l @(OFF_R0,r15), r3 ! end point + cmp/hs r3, r2 ! r2 >= r3? + bt 1f + add r3, r1 ! rewind point #2 + mov.l r1, @(r0,r15) ! reset PC to rewind point #2 + ! +1: +#endif + mov.l 1f, r1 + jsr @r1 ! schedule + nop + cli +#ifdef CONFIG_TRACE_IRQFLAGS + mov.l 5f, r0 + jsr @r0 + nop +#endif + ! + mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags + tst #_TIF_WORK_MASK, r0 + bt __restore_all + bra work_pending + tst #_TIF_NEED_RESCHED, r0 + + .align 2 +1: .long schedule +2: .long do_notify_resume +3: .long restore_all +#ifdef CONFIG_TRACE_IRQFLAGS +4: .long trace_hardirqs_on +5: .long trace_hardirqs_off +#endif + + .align 2 +syscall_exit_work: + ! r0: current_thread_info->flags + ! r8: current_thread_info + tst #_TIF_SYSCALL_TRACE, r0 + bt/s work_pending + tst #_TIF_NEED_RESCHED, r0 +#ifdef CONFIG_TRACE_IRQFLAGS + mov.l 5f, r0 + jsr @r0 + nop +#endif + sti + ! XXX setup arguments... + mov.l 4f, r0 ! do_syscall_trace + jsr @r0 + nop + bra resume_userspace + nop + + .align 2 +syscall_trace_entry: + ! Yes it is traced. + ! XXX setup arguments... + mov.l 4f, r11 ! Call do_syscall_trace which notifies + jsr @r11 ! superior (will chomp R[0-7]) + nop + ! Reload R0-R4 from kernel stack, where the + ! parent may have modified them using + ! ptrace(POKEUSR). (Note that R0-R2 are + ! used by the system call handler directly + ! from the kernel stack anyway, so don't need + ! to be reloaded here.) This allows the parent + ! to rewrite system calls and args on the fly. + mov.l @(OFF_R4,r15), r4 ! arg0 + mov.l @(OFF_R5,r15), r5 + mov.l @(OFF_R6,r15), r6 + mov.l @(OFF_R7,r15), r7 ! arg3 + mov.l @(OFF_R3,r15), r3 ! syscall_nr + ! + mov.l 2f, r10 ! Number of syscalls + cmp/hs r10, r3 + bf syscall_call + mov #-ENOSYS, r0 + bra syscall_exit + mov.l r0, @(OFF_R0,r15) ! Return value + +__restore_all: + mov.l 1f, r0 + jmp @r0 + nop + + .align 2 +1: .long restore_all + + .align 2 +not_syscall_tra: + bra debug_trap + nop + + .align 2 +syscall_badsys: ! Bad syscall number + mov #-ENOSYS, r0 + bra resume_userspace + mov.l r0, @(OFF_R0,r15) ! Return value + + +/* + * Syscall interface: + * + * Syscall #: R3 + * Arguments #0 to #3: R4--R7 + * Arguments #4 to #6: R0, R1, R2 + * TRA: (number of arguments + 0x10) x 4 + * + * This code also handles delegating other traps to the BIOS/gdb stub + * according to: + * + * Trap number + * (TRA>>2) Purpose + * -------- ------- + * 0x0-0xf old syscall ABI + * 0x10-0x1f new syscall ABI + * 0x20-0xff delegated through debug_trap to BIOS/gdb stub. + * + * Note: When we're first called, the TRA value must be shifted + * right 2 bits in order to get the value that was used as the "trapa" + * argument. + */ + + .align 2 + .globl ret_from_fork +ret_from_fork: + mov.l 1f, r8 + jsr @r8 + mov r0, r4 + bra syscall_exit + nop + .align 2 +1: .long schedule_tail + ! +ENTRY(system_call) +#if !defined(CONFIG_CPU_SH2) + mov.l 1f, r9 + mov.l @r9, r8 ! Read from TRA (Trap Address) Register +#endif + ! + ! Is the trap argument >= 0x20? (TRA will be >= 0x80) + mov #0x7f, r9 + cmp/hi r9, r8 + bt/s not_syscall_tra + mov #OFF_TRA, r9 + add r15, r9 + mov.l r8, @r9 ! set TRA value to tra +#ifdef CONFIG_TRACE_IRQFLAGS + mov.l 5f, r10 + jsr @r10 + nop +#endif + sti + + ! + get_current_thread_info r8, r10 + mov.l @(TI_FLAGS,r8), r8 + mov #_TIF_SYSCALL_TRACE, r10 + tst r10, r8 + bf syscall_trace_entry + ! + mov.l 2f, r8 ! Number of syscalls + cmp/hs r8, r3 + bt syscall_badsys + ! +syscall_call: + shll2 r3 ! x4 + mov.l 3f, r8 ! Load the address of sys_call_table + add r8, r3 + mov.l @r3, r8 + jsr @r8 ! jump to specific syscall handler + nop + mov.l @(OFF_R0,r15), r12 ! save r0 + mov.l r0, @(OFF_R0,r15) ! save the return value + ! +syscall_exit: + cli +#ifdef CONFIG_TRACE_IRQFLAGS + mov.l 6f, r0 + jsr @r0 + nop +#endif + ! + get_current_thread_info r8, r0 + mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags + tst #_TIF_ALLWORK_MASK, r0 + bf syscall_exit_work + bra __restore_all + nop + .align 2 +#if !defined(CONFIG_CPU_SH2) +1: .long TRA +#endif +2: .long NR_syscalls +3: .long sys_call_table +4: .long do_syscall_trace +#ifdef CONFIG_TRACE_IRQFLAGS +5: .long trace_hardirqs_on +6: .long trace_hardirqs_off +#endif diff --git a/trunk/arch/sh/kernel/head.S b/trunk/arch/sh/kernel/head.S index f5f53d14f245..6aca4bc6ec5d 100644 --- a/trunk/arch/sh/kernel/head.S +++ b/trunk/arch/sh/kernel/head.S @@ -33,7 +33,7 @@ ENTRY(empty_zero_page) .long 0x00360000 /* INITRD_START */ .long 0x000a0000 /* INITRD_SIZE */ .long 0 - .balign 4096,0,4096 + .balign PAGE_SIZE,0,PAGE_SIZE .text /* @@ -53,8 +53,10 @@ ENTRY(_stext) ldc r0, sr ! Initialize global interrupt mask mov #0, r0 +#ifdef CONFIG_CPU_HAS_SR_RB ldc r0, r6_bank - +#endif + /* * Prefetch if possible to reduce cache miss penalty. * @@ -68,11 +70,14 @@ ENTRY(_stext) ! mov.l 2f, r0 mov r0, r15 ! Set initial r15 (stack pointer) - mov #(THREAD_SIZE >> 8), r1 + mov #(THREAD_SIZE >> 10), r1 shll8 r1 ! r1 = THREAD_SIZE + shll2 r1 sub r1, r0 ! +#ifdef CONFIG_CPU_HAS_SR_RB ldc r0, r7_bank ! ... and initial thread_info - +#endif + ! Clear BSS area mov.l 3f, r1 add #4, r1 @@ -95,7 +100,11 @@ ENTRY(_stext) nop .balign 4 +#if defined(CONFIG_CPU_SH2) +1: .long 0x000000F0 ! IMASK=0xF +#else 1: .long 0x400080F0 ! MD=1, RB=0, BL=0, FD=1, IMASK=0xF +#endif 2: .long init_thread_union+THREAD_SIZE 3: .long __bss_start 4: .long _end diff --git a/trunk/arch/sh/kernel/irq.c b/trunk/arch/sh/kernel/irq.c index 944128ce9706..67be2b6e8cd1 100644 --- a/trunk/arch/sh/kernel/irq.c +++ b/trunk/arch/sh/kernel/irq.c @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include #include #include @@ -78,15 +78,16 @@ union irq_ctx { u32 stack[THREAD_SIZE/sizeof(u32)]; }; -static union irq_ctx *hardirq_ctx[NR_CPUS]; -static union irq_ctx *softirq_ctx[NR_CPUS]; +static union irq_ctx *hardirq_ctx[NR_CPUS] __read_mostly; +static union irq_ctx *softirq_ctx[NR_CPUS] __read_mostly; #endif asmlinkage int do_IRQ(unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7, - struct pt_regs regs) + struct pt_regs __regs) { - struct pt_regs *old_regs = set_irq_regs(®s); + struct pt_regs *regs = RELOC_HIDE(&__regs, 0); + struct pt_regs *old_regs = set_irq_regs(regs); int irq; #ifdef CONFIG_4KSTACKS union irq_ctx *curctx, *irqctx; @@ -111,7 +112,7 @@ asmlinkage int do_IRQ(unsigned long r4, unsigned long r5, #endif #ifdef CONFIG_CPU_HAS_INTEVT - irq = (ctrl_inl(INTEVT) >> 5) - 16; + irq = evt2irq(ctrl_inl(INTEVT)); #else irq = r4; #endif @@ -135,17 +136,24 @@ asmlinkage int do_IRQ(unsigned long r4, unsigned long r5, irqctx->tinfo.task = curctx->tinfo.task; irqctx->tinfo.previous_sp = current_stack_pointer; + /* + * Copy the softirq bits in preempt_count so that the + * softirq checks work in the hardirq context. + */ + irqctx->tinfo.preempt_count = + (irqctx->tinfo.preempt_count & ~SOFTIRQ_MASK) | + (curctx->tinfo.preempt_count & SOFTIRQ_MASK); + __asm__ __volatile__ ( "mov %0, r4 \n" - "mov r15, r9 \n" + "mov r15, r8 \n" "jsr @%1 \n" /* swith to the irq stack */ " mov %2, r15 \n" /* restore the stack (ring zero) */ - "mov r9, r15 \n" + "mov r8, r15 \n" : /* no outputs */ : "r" (irq), "r" (generic_handle_irq), "r" (isp) - /* XXX: A somewhat excessive clobber list? -PFM */ : "memory", "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "t", "pr" ); @@ -193,7 +201,7 @@ void irq_ctx_init(int cpu) irqctx->tinfo.task = NULL; irqctx->tinfo.exec_domain = NULL; irqctx->tinfo.cpu = cpu; - irqctx->tinfo.preempt_count = SOFTIRQ_OFFSET; + irqctx->tinfo.preempt_count = 0; irqctx->tinfo.addr_limit = MAKE_MM_SEG(0); softirq_ctx[cpu] = irqctx; @@ -239,13 +247,38 @@ asmlinkage void do_softirq(void) "mov r9, r15 \n" : /* no outputs */ : "r" (__do_softirq), "r" (isp) - /* XXX: A somewhat excessive clobber list? -PFM */ : "memory", "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r15", "t", "pr" ); + + /* + * Shouldnt happen, we returned above if in_interrupt(): + */ + WARN_ON_ONCE(softirq_count()); } local_irq_restore(flags); } EXPORT_SYMBOL(do_softirq); #endif + +void __init init_IRQ(void) +{ +#ifdef CONFIG_CPU_HAS_PINT_IRQ + init_IRQ_pint(); +#endif + +#ifdef CONFIG_CPU_HAS_INTC2_IRQ + init_IRQ_intc2(); +#endif + +#ifdef CONFIG_CPU_HAS_IPR_IRQ + init_IRQ_ipr(); +#endif + + /* Perform the machine specific initialisation */ + if (sh_mv.mv_init_irq) + sh_mv.mv_init_irq(); + + irq_ctx_init(smp_processor_id()); +} diff --git a/trunk/arch/sh/kernel/process.c b/trunk/arch/sh/kernel/process.c index a52b13ac6b7f..f3e2631be144 100644 --- a/trunk/arch/sh/kernel/process.c +++ b/trunk/arch/sh/kernel/process.c @@ -385,10 +385,11 @@ struct task_struct *__switch_to(struct task_struct *prev, struct task_struct *ne asmlinkage int sys_fork(unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7, - struct pt_regs regs) + struct pt_regs __regs) { + struct pt_regs *regs = RELOC_HIDE(&__regs, 0); #ifdef CONFIG_MMU - return do_fork(SIGCHLD, regs.regs[15], ®s, 0, NULL, NULL); + return do_fork(SIGCHLD, regs->regs[15], regs, 0, NULL, NULL); #else /* fork almost works, enough to trick you into looking elsewhere :-( */ return -EINVAL; @@ -398,11 +399,12 @@ asmlinkage int sys_fork(unsigned long r4, unsigned long r5, asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, unsigned long parent_tidptr, unsigned long child_tidptr, - struct pt_regs regs) + struct pt_regs __regs) { + struct pt_regs *regs = RELOC_HIDE(&__regs, 0); if (!newsp) - newsp = regs.regs[15]; - return do_fork(clone_flags, newsp, ®s, 0, + newsp = regs->regs[15]; + return do_fork(clone_flags, newsp, regs, 0, (int __user *)parent_tidptr, (int __user *)child_tidptr); } @@ -418,9 +420,10 @@ asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, */ asmlinkage int sys_vfork(unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7, - struct pt_regs regs) + struct pt_regs __regs) { - return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.regs[15], ®s, + struct pt_regs *regs = RELOC_HIDE(&__regs, 0); + return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->regs[15], regs, 0, NULL, NULL); } @@ -429,8 +432,9 @@ asmlinkage int sys_vfork(unsigned long r4, unsigned long r5, */ asmlinkage int sys_execve(char *ufilename, char **uargv, char **uenvp, unsigned long r7, - struct pt_regs regs) + struct pt_regs __regs) { + struct pt_regs *regs = RELOC_HIDE(&__regs, 0); int error; char *filename; @@ -442,7 +446,7 @@ asmlinkage int sys_execve(char *ufilename, char **uargv, error = do_execve(filename, (char __user * __user *)uargv, (char __user * __user *)uenvp, - ®s); + regs); if (error == 0) { task_lock(current); current->ptrace &= ~PT_DTRACE; @@ -472,9 +476,7 @@ unsigned long get_wchan(struct task_struct *p) return pc; } -asmlinkage void break_point_trap(unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7, - struct pt_regs regs) +asmlinkage void break_point_trap(void) { /* Clear tracing. */ #if defined(CONFIG_CPU_SH4A) @@ -492,8 +494,10 @@ asmlinkage void break_point_trap(unsigned long r4, unsigned long r5, asmlinkage void break_point_trap_software(unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7, - struct pt_regs regs) + struct pt_regs __regs) { - regs.pc -= 2; + struct pt_regs *regs = RELOC_HIDE(&__regs, 0); + + regs->pc -= 2; force_sig(SIGTRAP, current); } diff --git a/trunk/arch/sh/kernel/relocate_kernel.S b/trunk/arch/sh/kernel/relocate_kernel.S index 8221b37c9773..c66cb3209db5 100644 --- a/trunk/arch/sh/kernel/relocate_kernel.S +++ b/trunk/arch/sh/kernel/relocate_kernel.S @@ -7,11 +7,9 @@ * This source code is licensed under the GNU General Public License, * Version 2. See the file COPYING for more details. */ - #include - -#define PAGE_SIZE 4096 /* must be same value as in */ - +#include +#include .globl relocate_new_kernel relocate_new_kernel: @@ -20,8 +18,8 @@ relocate_new_kernel: /* r6 = start_address */ /* r7 = vbr_reg */ - mov.l 10f,r8 /* 4096 */ - mov.l 11f,r9 /* 0xa0000000 */ + mov.l 10f,r8 /* PAGE_SIZE */ + mov.l 11f,r9 /* P2SEG */ /* stack setting */ add r8,r5 @@ -32,7 +30,7 @@ relocate_new_kernel: 0: mov.l @r4+,r0 /* cmd = *ind++ */ -1: /* addr = (cmd | 0xa0000000) & 0xfffffff0 */ +1: /* addr = (cmd | P2SEG) & 0xfffffff0 */ mov r0,r2 or r9,r2 mov #-16,r1 @@ -92,7 +90,7 @@ relocate_new_kernel: 10: .long PAGE_SIZE 11: - .long 0xa0000000 + .long P2SEG relocate_new_kernel_end: diff --git a/trunk/arch/sh/kernel/setup.c b/trunk/arch/sh/kernel/setup.c index 36d86f9ac38a..f8dd6b7bfab0 100644 --- a/trunk/arch/sh/kernel/setup.c +++ b/trunk/arch/sh/kernel/setup.c @@ -332,8 +332,7 @@ void __init setup_arch(char **cmdline_p) if (LOADER_TYPE && INITRD_START) { if (INITRD_START + INITRD_SIZE <= (max_low_pfn << PAGE_SHIFT)) { reserve_bootmem_node(NODE_DATA(0), INITRD_START+__MEMORY_START, INITRD_SIZE); - initrd_start = - INITRD_START ? INITRD_START + PAGE_OFFSET + __MEMORY_START : 0; + initrd_start = INITRD_START + PAGE_OFFSET + __MEMORY_START; initrd_end = initrd_start + INITRD_SIZE; } else { printk("initrd extends beyond end of memory " @@ -392,6 +391,7 @@ static int __init topology_init(void) subsys_initcall(topology_init); static const char *cpu_name[] = { + [CPU_SH7206] = "SH7206", [CPU_SH7619] = "SH7619", [CPU_SH7604] = "SH7604", [CPU_SH7300] = "SH7300", [CPU_SH7705] = "SH7705", [CPU_SH7706] = "SH7706", [CPU_SH7707] = "SH7707", [CPU_SH7708] = "SH7708", @@ -404,6 +404,7 @@ static const char *cpu_name[] = { [CPU_SH4_202] = "SH4-202", [CPU_SH4_501] = "SH4-501", [CPU_SH7770] = "SH7770", [CPU_SH7780] = "SH7780", [CPU_SH7781] = "SH7781", [CPU_SH7343] = "SH7343", + [CPU_SH7785] = "SH7785", [CPU_SH_NONE] = "Unknown" }; diff --git a/trunk/arch/sh/kernel/sh_ksyms.c b/trunk/arch/sh/kernel/sh_ksyms.c index 8a2fd19dc9eb..ceee79143401 100644 --- a/trunk/arch/sh/kernel/sh_ksyms.c +++ b/trunk/arch/sh/kernel/sh_ksyms.c @@ -73,8 +73,6 @@ DECLARE_EXPORT(__lshrdi3); DECLARE_EXPORT(__movstr); DECLARE_EXPORT(__movstrSI16); -EXPORT_SYMBOL(strcpy); - #ifdef CONFIG_CPU_SH4 DECLARE_EXPORT(__movstr_i4_even); DECLARE_EXPORT(__movstr_i4_odd); @@ -101,10 +99,6 @@ EXPORT_SYMBOL(__down_trylock); EXPORT_SYMBOL(synchronize_irq); #endif -#ifdef CONFIG_PM -EXPORT_SYMBOL(pm_suspend); -#endif - EXPORT_SYMBOL(csum_partial); #ifdef CONFIG_IPV6 EXPORT_SYMBOL(csum_ipv6_magic); diff --git a/trunk/arch/sh/kernel/signal.c b/trunk/arch/sh/kernel/signal.c index 5213f5bc6ce0..bb1c480a59c7 100644 --- a/trunk/arch/sh/kernel/signal.c +++ b/trunk/arch/sh/kernel/signal.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -37,7 +38,7 @@ asmlinkage int sys_sigsuspend(old_sigset_t mask, unsigned long r5, unsigned long r6, unsigned long r7, - struct pt_regs regs) + struct pt_regs __regs) { mask &= _BLOCKABLE; spin_lock_irq(¤t->sighand->siglock); @@ -52,7 +53,7 @@ sys_sigsuspend(old_sigset_t mask, return -ERESTARTNOHAND; } -asmlinkage int +asmlinkage int sys_sigaction(int sig, const struct old_sigaction __user *act, struct old_sigaction __user *oact) { @@ -87,9 +88,11 @@ sys_sigaction(int sig, const struct old_sigaction __user *act, asmlinkage int sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, unsigned long r6, unsigned long r7, - struct pt_regs regs) + struct pt_regs __regs) { - return do_sigaltstack(uss, uoss, regs.regs[15]); + struct pt_regs *regs = RELOC_HIDE(&__regs, 0); + + return do_sigaltstack(uss, uoss, regs->regs[15]); } @@ -98,7 +101,11 @@ sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, */ #define MOVW(n) (0x9300|((n)-2)) /* Move mem word at PC+n to R3 */ -#define TRAP16 0xc310 /* Syscall w/no args (NR in R3) */ +#if defined(CONFIG_CPU_SH2) || defined(CONFIG_CPU_SH2A) +#define TRAP_NOARG 0xc320 /* Syscall w/no args (NR in R3) */ +#else +#define TRAP_NOARG 0xc310 /* Syscall w/no args (NR in R3) */ +#endif #define OR_R0_R0 0x200b /* or r0,r0 (insert to avoid hardware bug) */ struct sigframe @@ -194,9 +201,10 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, int *r0_p asmlinkage int sys_sigreturn(unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7, - struct pt_regs regs) + struct pt_regs __regs) { - struct sigframe __user *frame = (struct sigframe __user *)regs.regs[15]; + struct pt_regs *regs = RELOC_HIDE(&__regs, 0); + struct sigframe __user *frame = (struct sigframe __user *)regs->regs[15]; sigset_t set; int r0; @@ -216,7 +224,7 @@ asmlinkage int sys_sigreturn(unsigned long r4, unsigned long r5, recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); - if (restore_sigcontext(®s, &frame->sc, &r0)) + if (restore_sigcontext(regs, &frame->sc, &r0)) goto badframe; return r0; @@ -227,9 +235,10 @@ asmlinkage int sys_sigreturn(unsigned long r4, unsigned long r5, asmlinkage int sys_rt_sigreturn(unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7, - struct pt_regs regs) + struct pt_regs __regs) { - struct rt_sigframe __user *frame = (struct rt_sigframe __user *)regs.regs[15]; + struct pt_regs *regs = RELOC_HIDE(&__regs, 0); + struct rt_sigframe __user *frame = (struct rt_sigframe __user *)regs->regs[15]; sigset_t set; stack_t st; int r0; @@ -246,14 +255,14 @@ asmlinkage int sys_rt_sigreturn(unsigned long r4, unsigned long r5, recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); - if (restore_sigcontext(®s, &frame->uc.uc_mcontext, &r0)) + if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0)) goto badframe; if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st))) goto badframe; /* It is more difficult to avoid calling this function than to call it and ignore errors. */ - do_sigaltstack(&st, NULL, regs.regs[15]); + do_sigaltstack(&st, NULL, regs->regs[15]); return r0; @@ -350,7 +359,7 @@ static int setup_frame(int sig, struct k_sigaction *ka, } else { /* Generate return code (system call to sigreturn) */ err |= __put_user(MOVW(7), &frame->retcode[0]); - err |= __put_user(TRAP16, &frame->retcode[1]); + err |= __put_user(TRAP_NOARG, &frame->retcode[1]); err |= __put_user(OR_R0_R0, &frame->retcode[2]); err |= __put_user(OR_R0_R0, &frame->retcode[3]); err |= __put_user(OR_R0_R0, &frame->retcode[4]); @@ -430,7 +439,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, } else { /* Generate return code (system call to rt_sigreturn) */ err |= __put_user(MOVW(7), &frame->retcode[0]); - err |= __put_user(TRAP16, &frame->retcode[1]); + err |= __put_user(TRAP_NOARG, &frame->retcode[1]); err |= __put_user(OR_R0_R0, &frame->retcode[2]); err |= __put_user(OR_R0_R0, &frame->retcode[3]); err |= __put_user(OR_R0_R0, &frame->retcode[4]); diff --git a/trunk/arch/sh/kernel/stacktrace.c b/trunk/arch/sh/kernel/stacktrace.c new file mode 100644 index 000000000000..0d5268afe80f --- /dev/null +++ b/trunk/arch/sh/kernel/stacktrace.c @@ -0,0 +1,43 @@ +/* + * arch/sh/kernel/stacktrace.c + * + * Stack trace management functions + * + * Copyright (C) 2006 Paul Mundt + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include +#include + +/* + * Save stack-backtrace addresses into a stack_trace buffer. + */ +void save_stack_trace(struct stack_trace *trace, struct task_struct *task) +{ + unsigned long *sp; + + if (!task) + task = current; + if (task == current) + sp = (unsigned long *)current_stack_pointer; + else + sp = (unsigned long *)task->thread.sp; + + while (!kstack_end(sp)) { + unsigned long addr = *sp++; + + if (__kernel_text_address(addr)) { + if (trace->skip > 0) + trace->skip--; + else + trace->entries[trace->nr_entries++] = addr; + if (trace->nr_entries >= trace->max_entries) + break; + } + } +} diff --git a/trunk/arch/sh/kernel/sys_sh.c b/trunk/arch/sh/kernel/sys_sh.c index 8fde95001c34..5083b6ed4b39 100644 --- a/trunk/arch/sh/kernel/sys_sh.c +++ b/trunk/arch/sh/kernel/sys_sh.c @@ -33,14 +33,15 @@ */ asmlinkage int sys_pipe(unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7, - struct pt_regs regs) + struct pt_regs __regs) { + struct pt_regs *regs = RELOC_HIDE(&__regs, 0); int fd[2]; int error; error = do_pipe(fd); if (!error) { - regs.regs[1] = fd[1]; + regs->regs[1] = fd[1]; return fd[0]; } return error; @@ -50,6 +51,7 @@ unsigned long shm_align_mask = PAGE_SIZE - 1; /* Sane caches */ EXPORT_SYMBOL(shm_align_mask); +#ifdef CONFIG_MMU /* * To avoid cache aliases, we map the shared page with same color. */ @@ -135,6 +137,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, addr = COLOUR_ALIGN(addr, pgoff); } } +#endif /* CONFIG_MMU */ static inline long do_mmap2(unsigned long addr, unsigned long len, unsigned long prot, diff --git a/trunk/arch/sh/kernel/time.c b/trunk/arch/sh/kernel/time.c index 57e708d7b52d..c206c9504c4b 100644 --- a/trunk/arch/sh/kernel/time.c +++ b/trunk/arch/sh/kernel/time.c @@ -13,6 +13,8 @@ #include #include #include +#include +#include #include #include #include @@ -50,15 +52,20 @@ unsigned long long __attribute__ ((weak)) sched_clock(void) #ifndef CONFIG_GENERIC_TIME void do_gettimeofday(struct timeval *tv) { + unsigned long flags; unsigned long seq; unsigned long usec, sec; do { - seq = read_seqbegin(&xtime_lock); + /* + * Turn off IRQs when grabbing xtime_lock, so that + * the sys_timer get_offset code doesn't have to handle it. + */ + seq = read_seqbegin_irqsave(&xtime_lock, flags); usec = get_timer_offset(); sec = xtime.tv_sec; - usec += xtime.tv_nsec / 1000; - } while (read_seqretry(&xtime_lock, seq)); + usec += xtime.tv_nsec / NSEC_PER_USEC; + } while (read_seqretry_irqrestore(&xtime_lock, seq, flags)); while (usec >= 1000000) { usec -= 1000000; @@ -85,7 +92,7 @@ int do_settimeofday(struct timespec *tv) * wall time. Discover what correction gettimeofday() would have * made, and then undo it! */ - nsec -= 1000 * get_timer_offset(); + nsec -= get_timer_offset() * NSEC_PER_USEC; wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec); wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec); @@ -169,6 +176,108 @@ static struct sysdev_class timer_sysclass = { .resume = timer_resume, }; +#ifdef CONFIG_NO_IDLE_HZ +static int timer_dyn_tick_enable(void) +{ + struct dyn_tick_timer *dyn_tick = sys_timer->dyn_tick; + unsigned long flags; + int ret = -ENODEV; + + if (dyn_tick) { + spin_lock_irqsave(&dyn_tick->lock, flags); + ret = 0; + if (!(dyn_tick->state & DYN_TICK_ENABLED)) { + ret = dyn_tick->enable(); + + if (ret == 0) + dyn_tick->state |= DYN_TICK_ENABLED; + } + spin_unlock_irqrestore(&dyn_tick->lock, flags); + } + + return ret; +} + +static int timer_dyn_tick_disable(void) +{ + struct dyn_tick_timer *dyn_tick = sys_timer->dyn_tick; + unsigned long flags; + int ret = -ENODEV; + + if (dyn_tick) { + spin_lock_irqsave(&dyn_tick->lock, flags); + ret = 0; + if (dyn_tick->state & DYN_TICK_ENABLED) { + ret = dyn_tick->disable(); + + if (ret == 0) + dyn_tick->state &= ~DYN_TICK_ENABLED; + } + spin_unlock_irqrestore(&dyn_tick->lock, flags); + } + + return ret; +} + +/* + * Reprogram the system timer for at least the calculated time interval. + * This function should be called from the idle thread with IRQs disabled, + * immediately before sleeping. + */ +void timer_dyn_reprogram(void) +{ + struct dyn_tick_timer *dyn_tick = sys_timer->dyn_tick; + unsigned long next, seq, flags; + + if (!dyn_tick) + return; + + spin_lock_irqsave(&dyn_tick->lock, flags); + if (dyn_tick->state & DYN_TICK_ENABLED) { + next = next_timer_interrupt(); + do { + seq = read_seqbegin(&xtime_lock); + dyn_tick->reprogram(next - jiffies); + } while (read_seqretry(&xtime_lock, seq)); + } + spin_unlock_irqrestore(&dyn_tick->lock, flags); +} + +static ssize_t timer_show_dyn_tick(struct sys_device *dev, char *buf) +{ + return sprintf(buf, "%i\n", + (sys_timer->dyn_tick->state & DYN_TICK_ENABLED) >> 1); +} + +static ssize_t timer_set_dyn_tick(struct sys_device *dev, const char *buf, + size_t count) +{ + unsigned int enable = simple_strtoul(buf, NULL, 2); + + if (enable) + timer_dyn_tick_enable(); + else + timer_dyn_tick_disable(); + + return count; +} +static SYSDEV_ATTR(dyn_tick, 0644, timer_show_dyn_tick, timer_set_dyn_tick); + +/* + * dyntick=enable|disable + */ +static char dyntick_str[4] __initdata = ""; + +static int __init dyntick_setup(char *str) +{ + if (str) + strlcpy(dyntick_str, str, sizeof(dyntick_str)); + return 1; +} + +__setup("dyntick=", dyntick_setup); +#endif + static int __init timer_init_sysfs(void) { int ret = sysdev_class_register(&timer_sysclass); @@ -176,7 +285,22 @@ static int __init timer_init_sysfs(void) return ret; sys_timer->dev.cls = &timer_sysclass; - return sysdev_register(&sys_timer->dev); + ret = sysdev_register(&sys_timer->dev); + +#ifdef CONFIG_NO_IDLE_HZ + if (ret == 0 && sys_timer->dyn_tick) { + ret = sysdev_create_file(&sys_timer->dev, &attr_dyn_tick); + + /* + * Turn on dynamic tick after calibrate delay + * for correct bogomips + */ + if (ret == 0 && dyntick_str[0] == 'e') + ret = timer_dyn_tick_enable(); + } +#endif + + return ret; } device_initcall(timer_init_sysfs); @@ -200,6 +324,11 @@ void __init time_init(void) sys_timer = get_sys_timer(); printk(KERN_INFO "Using %s for system timer\n", sys_timer->name); +#ifdef CONFIG_NO_IDLE_HZ + if (sys_timer->dyn_tick) + spin_lock_init(&sys_timer->dyn_tick->lock); +#endif + #if defined(CONFIG_SH_KGDB) /* * Set up kgdb as requested. We do it here because the serial diff --git a/trunk/arch/sh/kernel/timers/Makefile b/trunk/arch/sh/kernel/timers/Makefile index 151a6a304cec..bcf244ff6a12 100644 --- a/trunk/arch/sh/kernel/timers/Makefile +++ b/trunk/arch/sh/kernel/timers/Makefile @@ -5,4 +5,6 @@ obj-y := timer.o obj-$(CONFIG_SH_TMU) += timer-tmu.o +obj-$(CONFIG_SH_MTU2) += timer-mtu2.o +obj-$(CONFIG_SH_CMT) += timer-cmt.o diff --git a/trunk/arch/sh/kernel/timers/timer-cmt.c b/trunk/arch/sh/kernel/timers/timer-cmt.c new file mode 100644 index 000000000000..a574b93a4e7b --- /dev/null +++ b/trunk/arch/sh/kernel/timers/timer-cmt.c @@ -0,0 +1,196 @@ +/* + * arch/sh/kernel/timers/timer-cmt.c - CMT Timer Support + * + * Copyright (C) 2005 Yoshinori Sato + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(CONFIG_CPU_SUBTYPE_SH7619) +#define CMT_CMSTR 0xf84a0070 +#define CMT_CMCSR_0 0xf84a0072 +#define CMT_CMCNT_0 0xf84a0074 +#define CMT_CMCOR_0 0xf84a0076 +#define CMT_CMCSR_1 0xf84a0078 +#define CMT_CMCNT_1 0xf84a007a +#define CMT_CMCOR_1 0xf84a007c + +#define STBCR3 0xf80a0000 +#define cmt_clock_enable() do { ctrl_outb(ctrl_inb(STBCR3) & ~0x10, STBCR3); } while(0) +#define CMT_CMCSR_INIT 0x0040 +#define CMT_CMCSR_CALIB 0x0000 +#elif defined(CONFIG_CPU_SUBTYPE_SH7206) +#define CMT_CMSTR 0xfffec000 +#define CMT_CMCSR_0 0xfffec002 +#define CMT_CMCNT_0 0xfffec004 +#define CMT_CMCOR_0 0xfffec006 + +#define STBCR4 0xfffe040c +#define cmt_clock_enable() do { ctrl_outb(ctrl_inb(STBCR4) & ~0x04, STBCR4); } while(0) +#define CMT_CMCSR_INIT 0x0040 +#define CMT_CMCSR_CALIB 0x0000 +#else +#error "Unknown CPU SUBTYPE" +#endif + +static unsigned long cmt_timer_get_offset(void) +{ + int count; + static unsigned short count_p = 0xffff; /* for the first call after boot */ + static unsigned long jiffies_p = 0; + + /* + * cache volatile jiffies temporarily; we have IRQs turned off. + */ + unsigned long jiffies_t; + + /* timer count may underflow right here */ + count = ctrl_inw(CMT_CMCOR_0); + count -= ctrl_inw(CMT_CMCNT_0); + + jiffies_t = jiffies; + + /* + * avoiding timer inconsistencies (they are rare, but they happen)... + * there is one kind of problem that must be avoided here: + * 1. the timer counter underflows + */ + + if (jiffies_t == jiffies_p) { + if (count > count_p) { + /* the nutcase */ + if (ctrl_inw(CMT_CMCSR_0) & 0x80) { /* Check CMF bit */ + count -= LATCH; + } else { + printk("%s (): hardware timer problem?\n", + __FUNCTION__); + } + } + } else + jiffies_p = jiffies_t; + + count_p = count; + + count = ((LATCH-1) - count) * TICK_SIZE; + count = (count + LATCH/2) / LATCH; + + return count; +} + +static irqreturn_t cmt_timer_interrupt(int irq, void *dev_id) +{ + unsigned long timer_status; + + /* Clear CMF bit */ + timer_status = ctrl_inw(CMT_CMCSR_0); + timer_status &= ~0x80; + ctrl_outw(timer_status, CMT_CMCSR_0); + + /* + * Here we are in the timer irq handler. We just have irqs locally + * disabled but we don't know if the timer_bh is running on the other + * CPU. We need to avoid to SMP race with it. NOTE: we don' t need + * the irq version of write_lock because as just said we have irq + * locally disabled. -arca + */ + write_seqlock(&xtime_lock); + handle_timer_tick(); + write_sequnlock(&xtime_lock); + + return IRQ_HANDLED; +} + +static struct irqaction cmt_irq = { + .name = "timer", + .handler = cmt_timer_interrupt, + .flags = IRQF_DISABLED | IRQF_TIMER, + .mask = CPU_MASK_NONE, +}; + +static void cmt_clk_init(struct clk *clk) +{ + u8 divisor = CMT_CMCSR_INIT & 0x3; + ctrl_inw(CMT_CMCSR_0); + ctrl_outw(CMT_CMCSR_INIT, CMT_CMCSR_0); + clk->parent = clk_get(NULL, "module_clk"); + clk->rate = clk->parent->rate / (8 << (divisor << 1)); +} + +static void cmt_clk_recalc(struct clk *clk) +{ + u8 divisor = ctrl_inw(CMT_CMCSR_0) & 0x3; + clk->rate = clk->parent->rate / (8 << (divisor << 1)); +} + +static struct clk_ops cmt_clk_ops = { + .init = cmt_clk_init, + .recalc = cmt_clk_recalc, +}; + +static struct clk cmt0_clk = { + .name = "cmt0_clk", + .ops = &cmt_clk_ops, +}; + +static int cmt_timer_start(void) +{ + ctrl_outw(ctrl_inw(CMT_CMSTR) | 0x01, CMT_CMSTR); + return 0; +} + +static int cmt_timer_stop(void) +{ + ctrl_outw(ctrl_inw(CMT_CMSTR) & ~0x01, CMT_CMSTR); + return 0; +} + +static int cmt_timer_init(void) +{ + unsigned long interval; + + cmt_clock_enable(); + + setup_irq(CONFIG_SH_TIMER_IRQ, &cmt_irq); + + cmt0_clk.parent = clk_get(NULL, "module_clk"); + + cmt_timer_stop(); + + interval = cmt0_clk.parent->rate / 8 / HZ; + printk(KERN_INFO "Interval = %ld\n", interval); + + ctrl_outw(interval, CMT_CMCOR_0); + + clk_register(&cmt0_clk); + clk_enable(&cmt0_clk); + + cmt_timer_start(); + + return 0; +} + +struct sys_timer_ops cmt_timer_ops = { + .init = cmt_timer_init, + .start = cmt_timer_start, + .stop = cmt_timer_stop, +#ifndef CONFIG_GENERIC_TIME + .get_offset = cmt_timer_get_offset, +#endif +}; + +struct sys_timer cmt_timer = { + .name = "cmt", + .ops = &cmt_timer_ops, +}; diff --git a/trunk/arch/sh/kernel/timers/timer-mtu2.c b/trunk/arch/sh/kernel/timers/timer-mtu2.c new file mode 100644 index 000000000000..fffcd1c09873 --- /dev/null +++ b/trunk/arch/sh/kernel/timers/timer-mtu2.c @@ -0,0 +1,200 @@ +/* + * arch/sh/kernel/timers/timer-mtu2.c - MTU2 Timer Support + * + * Copyright (C) 2005 Paul Mundt + * + * Based off of arch/sh/kernel/timers/timer-tmu.c + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * We use channel 1 for our lowly system timer. Channel 2 would be the other + * likely candidate, but we leave it alone as it has higher divisors that + * would be of more use to other more interesting applications. + * + * TODO: Presently we only implement a 16-bit single-channel system timer. + * However, we can implement channel cascade if we go the overflow route and + * get away with using 2 MTU2 channels as a 32-bit timer. + */ +#define MTU2_TSTR 0xfffe4280 +#define MTU2_TCR_1 0xfffe4380 +#define MTU2_TMDR_1 0xfffe4381 +#define MTU2_TIOR_1 0xfffe4382 +#define MTU2_TIER_1 0xfffe4384 +#define MTU2_TSR_1 0xfffe4385 +#define MTU2_TCNT_1 0xfffe4386 /* 16-bit counter */ +#define MTU2_TGRA_1 0xfffe438a + +#define STBCR3 0xfffe0408 + +#define MTU2_TSTR_CST1 (1 << 1) /* Counter Start 1 */ + +#define MTU2_TSR_TGFA (1 << 0) /* GRA compare match */ + +#define MTU2_TIER_TGIEA (1 << 0) /* GRA compare match interrupt enable */ + +#define MTU2_TCR_INIT 0x22 + +#define MTU2_TCR_CALIB 0x00 + +static unsigned long mtu2_timer_get_offset(void) +{ + int count; + static int count_p = 0x7fff; /* for the first call after boot */ + static unsigned long jiffies_p = 0; + + /* + * cache volatile jiffies temporarily; we have IRQs turned off. + */ + unsigned long jiffies_t; + + /* timer count may underflow right here */ + count = ctrl_inw(MTU2_TCNT_1); /* read the latched count */ + + jiffies_t = jiffies; + + /* + * avoiding timer inconsistencies (they are rare, but they happen)... + * there is one kind of problem that must be avoided here: + * 1. the timer counter underflows + */ + + if (jiffies_t == jiffies_p) { + if (count > count_p) { + if (ctrl_inb(MTU2_TSR_1) & MTU2_TSR_TGFA) { + count -= LATCH; + } else { + printk("%s (): hardware timer problem?\n", + __FUNCTION__); + } + } + } else + jiffies_p = jiffies_t; + + count_p = count; + + count = ((LATCH-1) - count) * TICK_SIZE; + count = (count + LATCH/2) / LATCH; + + return count; +} + +static irqreturn_t mtu2_timer_interrupt(int irq, void *dev_id) +{ + unsigned long timer_status; + + /* Clear TGFA bit */ + timer_status = ctrl_inb(MTU2_TSR_1); + timer_status &= ~MTU2_TSR_TGFA; + ctrl_outb(timer_status, MTU2_TSR_1); + + /* Do timer tick */ + write_seqlock(&xtime_lock); + handle_timer_tick(); + write_sequnlock(&xtime_lock); + + return IRQ_HANDLED; +} + +static struct irqaction mtu2_irq = { + .name = "timer", + .handler = mtu2_timer_interrupt, + .flags = IRQF_DISABLED | IRQF_TIMER, + .mask = CPU_MASK_NONE, +}; + +static unsigned int divisors[] = { 1, 4, 16, 64, 1, 1, 256 }; + +static void mtu2_clk_init(struct clk *clk) +{ + u8 idx = MTU2_TCR_INIT & 0x7; + + clk->rate = clk->parent->rate / divisors[idx]; + /* Start TCNT counting */ + ctrl_outb(ctrl_inb(MTU2_TSTR) | MTU2_TSTR_CST1, MTU2_TSTR); + +} + +static void mtu2_clk_recalc(struct clk *clk) +{ + u8 idx = ctrl_inb(MTU2_TCR_1) & 0x7; + clk->rate = clk->parent->rate / divisors[idx]; +} + +static struct clk_ops mtu2_clk_ops = { + .init = mtu2_clk_init, + .recalc = mtu2_clk_recalc, +}; + +static struct clk mtu2_clk1 = { + .name = "mtu2_clk1", + .ops = &mtu2_clk_ops, +}; + +static int mtu2_timer_start(void) +{ + ctrl_outb(ctrl_inb(MTU2_TSTR) | MTU2_TSTR_CST1, MTU2_TSTR); + return 0; +} + +static int mtu2_timer_stop(void) +{ + ctrl_outb(ctrl_inb(MTU2_TSTR) & ~MTU2_TSTR_CST1, MTU2_TSTR); + return 0; +} + +static int mtu2_timer_init(void) +{ + u8 tmp; + unsigned long interval; + + setup_irq(CONFIG_SH_TIMER_IRQ, &mtu2_irq); + + mtu2_clk1.parent = clk_get(NULL, "module_clk"); + + ctrl_outb(ctrl_inb(STBCR3) & (~0x20), STBCR3); + + /* Normal operation */ + ctrl_outb(0, MTU2_TMDR_1); + ctrl_outb(MTU2_TCR_INIT, MTU2_TCR_1); + ctrl_outb(0x01, MTU2_TIOR_1); + + /* Enable underflow interrupt */ + ctrl_outb(ctrl_inb(MTU2_TIER_1) | MTU2_TIER_TGIEA, MTU2_TIER_1); + + interval = CONFIG_SH_PCLK_FREQ / 16 / HZ; + printk(KERN_INFO "Interval = %ld\n", interval); + + ctrl_outw(interval, MTU2_TGRA_1); + ctrl_outw(0, MTU2_TCNT_1); + + clk_register(&mtu2_clk1); + clk_enable(&mtu2_clk1); + + return 0; +} + +struct sys_timer_ops mtu2_timer_ops = { + .init = mtu2_timer_init, + .start = mtu2_timer_start, + .stop = mtu2_timer_stop, +#ifndef CONFIG_GENERIC_TIME + .get_offset = mtu2_timer_get_offset, +#endif +}; + +struct sys_timer mtu2_timer = { + .name = "mtu2", + .ops = &mtu2_timer_ops, +}; diff --git a/trunk/arch/sh/kernel/timers/timer-tmu.c b/trunk/arch/sh/kernel/timers/timer-tmu.c index 24927015dc31..e060e71d0785 100644 --- a/trunk/arch/sh/kernel/timers/timer-tmu.c +++ b/trunk/arch/sh/kernel/timers/timer-tmu.c @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include @@ -31,13 +30,9 @@ #define TMU0_TCR_CALIB 0x0000 -static DEFINE_SPINLOCK(tmu0_lock); - static unsigned long tmu_timer_get_offset(void) { int count; - unsigned long flags; - static int count_p = 0x7fffffff; /* for the first call after boot */ static unsigned long jiffies_p = 0; @@ -46,7 +41,6 @@ static unsigned long tmu_timer_get_offset(void) */ unsigned long jiffies_t; - spin_lock_irqsave(&tmu0_lock, flags); /* timer count may underflow right here */ count = ctrl_inl(TMU0_TCNT); /* read the latched count */ @@ -72,7 +66,6 @@ static unsigned long tmu_timer_get_offset(void) jiffies_p = jiffies_t; count_p = count; - spin_unlock_irqrestore(&tmu0_lock, flags); count = ((LATCH-1) - count) * TICK_SIZE; count = (count + LATCH/2) / LATCH; @@ -106,7 +99,7 @@ static irqreturn_t tmu_timer_interrupt(int irq, void *dummy) static struct irqaction tmu_irq = { .name = "timer", .handler = tmu_timer_interrupt, - .flags = IRQF_DISABLED, + .flags = IRQF_DISABLED | IRQF_TIMER, .mask = CPU_MASK_NONE, }; @@ -149,9 +142,9 @@ static int tmu_timer_init(void) { unsigned long interval; - setup_irq(TIMER_IRQ, &tmu_irq); + setup_irq(CONFIG_SH_TIMER_IRQ, &tmu_irq); - tmu0_clk.parent = clk_get("module_clk"); + tmu0_clk.parent = clk_get(NULL, "module_clk"); /* Start TMU0 */ tmu_timer_stop(); diff --git a/trunk/arch/sh/kernel/timers/timer.c b/trunk/arch/sh/kernel/timers/timer.c index dc1f631053a8..a6bcc913d25e 100644 --- a/trunk/arch/sh/kernel/timers/timer.c +++ b/trunk/arch/sh/kernel/timers/timer.c @@ -16,6 +16,12 @@ static struct sys_timer *sys_timers[] __initdata = { #ifdef CONFIG_SH_TMU &tmu_timer, +#endif +#ifdef CONFIG_SH_MTU2 + &mtu2_timer, +#endif +#ifdef CONFIG_SH_CMT + &cmt_timer, #endif NULL, }; diff --git a/trunk/arch/sh/kernel/traps.c b/trunk/arch/sh/kernel/traps.c index 53dfa55f3156..3762d9dc2046 100644 --- a/trunk/arch/sh/kernel/traps.c +++ b/trunk/arch/sh/kernel/traps.c @@ -18,13 +18,14 @@ #include #include #include +#include #include #include #ifdef CONFIG_SH_KGDB #include -#define CHK_REMOTE_DEBUG(regs) \ -{ \ +#define CHK_REMOTE_DEBUG(regs) \ +{ \ if (kgdb_debug_hook && !user_mode(regs))\ (*kgdb_debug_hook)(regs); \ } @@ -33,8 +34,13 @@ #endif #ifdef CONFIG_CPU_SH2 -#define TRAP_RESERVED_INST 4 -#define TRAP_ILLEGAL_SLOT_INST 6 +# define TRAP_RESERVED_INST 4 +# define TRAP_ILLEGAL_SLOT_INST 6 +# define TRAP_ADDRESS_ERROR 9 +# ifdef CONFIG_CPU_SH2A +# define TRAP_DIVZERO_ERROR 17 +# define TRAP_DIVOVF_ERROR 18 +# endif #else #define TRAP_RESERVED_INST 12 #define TRAP_ILLEGAL_SLOT_INST 13 @@ -88,7 +94,7 @@ void die(const char * str, struct pt_regs * regs, long err) if (!user_mode(regs) || in_interrupt()) dump_mem("Stack: ", regs->regs[15], THREAD_SIZE + - (unsigned long)task_stack_page(current)); + (unsigned long)task_stack_page(current)); bust_spinlocks(0); spin_unlock_irq(&die_lock); @@ -102,8 +108,6 @@ static inline void die_if_kernel(const char *str, struct pt_regs *regs, die(str, regs, err); } -static int handle_unaligned_notify_count = 10; - /* * try and fix up kernelspace address errors * - userspace errors just cause EFAULT to be returned, resulting in SEGV @@ -198,7 +202,7 @@ static int handle_unaligned_ins(u16 instruction, struct pt_regs *regs) if (copy_to_user(dst,src,4)) goto fetch_fault; ret = 0; - break; + break; case 2: /* mov.[bwl] to memory, possibly with pre-decrement */ if (instruction & 4) @@ -222,7 +226,7 @@ static int handle_unaligned_ins(u16 instruction, struct pt_regs *regs) if (copy_from_user(dst,src,4)) goto fetch_fault; ret = 0; - break; + break; case 6: /* mov.[bwl] from memory, possibly with post-increment */ src = (unsigned char*) *rm; @@ -230,7 +234,7 @@ static int handle_unaligned_ins(u16 instruction, struct pt_regs *regs) *rm += count; dst = (unsigned char*) rn; *(unsigned long*)dst = 0; - + #ifdef __LITTLE_ENDIAN__ if (copy_from_user(dst, src, count)) goto fetch_fault; @@ -241,7 +245,7 @@ static int handle_unaligned_ins(u16 instruction, struct pt_regs *regs) } #else dst += 4-count; - + if (copy_from_user(dst, src, count)) goto fetch_fault; @@ -320,7 +324,8 @@ static inline int handle_unaligned_delayslot(struct pt_regs *regs) return -EFAULT; /* kernel */ - die("delay-slot-insn faulting in handle_unaligned_delayslot", regs, 0); + die("delay-slot-insn faulting in handle_unaligned_delayslot", + regs, 0); } return handle_unaligned_ins(instruction,regs); @@ -342,6 +347,13 @@ static inline int handle_unaligned_delayslot(struct pt_regs *regs) #define SH_PC_8BIT_OFFSET(instr) ((((signed char)(instr))*2) + 4) #define SH_PC_12BIT_OFFSET(instr) ((((signed short)(instr<<4))>>3) + 4) +/* + * XXX: SH-2A needs this too, but it needs an overhaul thanks to mixed 32-bit + * opcodes.. + */ +#ifndef CONFIG_CPU_SH2A +static int handle_unaligned_notify_count = 10; + static int handle_unaligned_access(u16 instruction, struct pt_regs *regs) { u_int rm; @@ -354,7 +366,8 @@ static int handle_unaligned_access(u16 instruction, struct pt_regs *regs) if (user_mode(regs) && handle_unaligned_notify_count>0) { handle_unaligned_notify_count--; - printk("Fixing up unaligned userspace access in \"%s\" pid=%d pc=0x%p ins=0x%04hx\n", + printk(KERN_NOTICE "Fixing up unaligned userspace access " + "in \"%s\" pid=%d pc=0x%p ins=0x%04hx\n", current->comm,current->pid,(u16*)regs->pc,instruction); } @@ -478,32 +491,58 @@ static int handle_unaligned_access(u16 instruction, struct pt_regs *regs) regs->pc += 2; return ret; } +#endif /* CONFIG_CPU_SH2A */ + +#ifdef CONFIG_CPU_HAS_SR_RB +#define lookup_exception_vector(x) \ + __asm__ __volatile__ ("stc r2_bank, %0\n\t" : "=r" ((x))) +#else +#define lookup_exception_vector(x) \ + __asm__ __volatile__ ("mov r4, %0\n\t" : "=r" ((x))) +#endif /* - * Handle various address error exceptions + * Handle various address error exceptions: + * - instruction address error: + * misaligned PC + * PC >= 0x80000000 in user mode + * - data address error (read and write) + * misaligned data access + * access to >= 0x80000000 is user mode + * Unfortuntaly we can't distinguish between instruction address error + * and data address errors caused by read acceses. */ -asmlinkage void do_address_error(struct pt_regs *regs, +asmlinkage void do_address_error(struct pt_regs *regs, unsigned long writeaccess, unsigned long address) { - unsigned long error_code; + unsigned long error_code = 0; mm_segment_t oldfs; + siginfo_t info; +#ifndef CONFIG_CPU_SH2A u16 instruction; int tmp; +#endif - asm volatile("stc r2_bank,%0": "=r" (error_code)); + /* Intentional ifdef */ +#ifdef CONFIG_CPU_HAS_SR_RB + lookup_exception_vector(error_code); +#endif oldfs = get_fs(); if (user_mode(regs)) { + int si_code = BUS_ADRERR; + local_irq_enable(); - current->thread.error_code = error_code; - current->thread.trap_no = (writeaccess) ? 8 : 7; /* bad PC is not something we can fix */ - if (regs->pc & 1) + if (regs->pc & 1) { + si_code = BUS_ADRALN; goto uspace_segv; + } +#ifndef CONFIG_CPU_SH2A set_fs(USER_DS); if (copy_from_user(&instruction, (u16 *)(regs->pc), 2)) { /* Argh. Fault on the instruction itself. @@ -518,14 +557,23 @@ asmlinkage void do_address_error(struct pt_regs *regs, if (tmp==0) return; /* sorted */ +#endif - uspace_segv: - printk(KERN_NOTICE "Killing process \"%s\" due to unaligned access\n", current->comm); - force_sig(SIGSEGV, current); +uspace_segv: + printk(KERN_NOTICE "Sending SIGBUS to \"%s\" due to unaligned " + "access (PC %lx PR %lx)\n", current->comm, regs->pc, + regs->pr); + + info.si_signo = SIGBUS; + info.si_errno = 0; + info.si_code = si_code; + info.si_addr = (void *) address; + force_sig_info(SIGBUS, &info, current); } else { if (regs->pc & 1) die("unaligned program counter", regs, error_code); +#ifndef CONFIG_CPU_SH2A set_fs(KERNEL_DS); if (copy_from_user(&instruction, (u16 *)(regs->pc), 2)) { /* Argh. Fault on the instruction itself. @@ -537,6 +585,12 @@ asmlinkage void do_address_error(struct pt_regs *regs, handle_unaligned_access(instruction, regs); set_fs(oldfs); +#else + printk(KERN_NOTICE "Killing process \"%s\" due to unaligned " + "access\n", current->comm); + + force_sig(SIGSEGV, current); +#endif } } @@ -548,7 +602,7 @@ int is_dsp_inst(struct pt_regs *regs) { unsigned short inst; - /* + /* * Safe guard if DSP mode is already enabled or we're lacking * the DSP altogether. */ @@ -569,27 +623,49 @@ int is_dsp_inst(struct pt_regs *regs) #define is_dsp_inst(regs) (0) #endif /* CONFIG_SH_DSP */ +#ifdef CONFIG_CPU_SH2A +asmlinkage void do_divide_error(unsigned long r4, unsigned long r5, + unsigned long r6, unsigned long r7, + struct pt_regs __regs) +{ + struct pt_regs *regs = RELOC_HIDE(&__regs, 0); + siginfo_t info; + + switch (r4) { + case TRAP_DIVZERO_ERROR: + info.si_code = FPE_INTDIV; + break; + case TRAP_DIVOVF_ERROR: + info.si_code = FPE_INTOVF; + break; + } + + force_sig_info(SIGFPE, &info, current); +} +#endif + /* arch/sh/kernel/cpu/sh4/fpu.c */ extern int do_fpu_inst(unsigned short, struct pt_regs *); extern asmlinkage void do_fpu_state_restore(unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7, struct pt_regs regs); + unsigned long r6, unsigned long r7, struct pt_regs __regs); asmlinkage void do_reserved_inst(unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7, - struct pt_regs regs) + struct pt_regs __regs) { + struct pt_regs *regs = RELOC_HIDE(&__regs, 0); unsigned long error_code; struct task_struct *tsk = current; #ifdef CONFIG_SH_FPU_EMU - unsigned short inst; + unsigned short inst = 0; int err; - get_user(inst, (unsigned short*)regs.pc); + get_user(inst, (unsigned short*)regs->pc); - err = do_fpu_inst(inst, ®s); + err = do_fpu_inst(inst, regs); if (!err) { - regs.pc += 2; + regs->pc += 2; return; } /* not a FPU inst. */ @@ -597,20 +673,19 @@ asmlinkage void do_reserved_inst(unsigned long r4, unsigned long r5, #ifdef CONFIG_SH_DSP /* Check if it's a DSP instruction */ - if (is_dsp_inst(®s)) { + if (is_dsp_inst(regs)) { /* Enable DSP mode, and restart instruction. */ - regs.sr |= SR_DSP; + regs->sr |= SR_DSP; return; } #endif - asm volatile("stc r2_bank, %0": "=r" (error_code)); + lookup_exception_vector(error_code); + local_irq_enable(); - tsk->thread.error_code = error_code; - tsk->thread.trap_no = TRAP_RESERVED_INST; - CHK_REMOTE_DEBUG(®s); + CHK_REMOTE_DEBUG(regs); force_sig(SIGILL, tsk); - die_if_no_fixup("reserved instruction", ®s, error_code); + die_if_no_fixup("reserved instruction", regs, error_code); } #ifdef CONFIG_SH_FPU_EMU @@ -658,39 +733,41 @@ static int emulate_branch(unsigned short inst, struct pt_regs* regs) asmlinkage void do_illegal_slot_inst(unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7, - struct pt_regs regs) + struct pt_regs __regs) { + struct pt_regs *regs = RELOC_HIDE(&__regs, 0); unsigned long error_code; struct task_struct *tsk = current; #ifdef CONFIG_SH_FPU_EMU - unsigned short inst; + unsigned short inst = 0; - get_user(inst, (unsigned short *)regs.pc + 1); - if (!do_fpu_inst(inst, ®s)) { - get_user(inst, (unsigned short *)regs.pc); - if (!emulate_branch(inst, ®s)) + get_user(inst, (unsigned short *)regs->pc + 1); + if (!do_fpu_inst(inst, regs)) { + get_user(inst, (unsigned short *)regs->pc); + if (!emulate_branch(inst, regs)) return; /* fault in branch.*/ } /* not a FPU inst. */ #endif - asm volatile("stc r2_bank, %0": "=r" (error_code)); + lookup_exception_vector(error_code); + local_irq_enable(); - tsk->thread.error_code = error_code; - tsk->thread.trap_no = TRAP_RESERVED_INST; - CHK_REMOTE_DEBUG(®s); + CHK_REMOTE_DEBUG(regs); force_sig(SIGILL, tsk); - die_if_no_fixup("illegal slot instruction", ®s, error_code); + die_if_no_fixup("illegal slot instruction", regs, error_code); } asmlinkage void do_exception_error(unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7, - struct pt_regs regs) + struct pt_regs __regs) { + struct pt_regs *regs = RELOC_HIDE(&__regs, 0); long ex; - asm volatile("stc r2_bank, %0" : "=r" (ex)); - die_if_kernel("exception", ®s, ex); + + lookup_exception_vector(ex); + die_if_kernel("exception", regs, ex); } #if defined(CONFIG_SH_STANDARD_BIOS) @@ -735,12 +812,16 @@ void *set_exception_table_vec(unsigned int vec, void *handler) { extern void *exception_handling_table[]; void *old_handler; - + old_handler = exception_handling_table[vec]; exception_handling_table[vec] = handler; return old_handler; } +extern asmlinkage void address_error_handler(unsigned long r4, unsigned long r5, + unsigned long r6, unsigned long r7, + struct pt_regs __regs); + void __init trap_init(void) { set_exception_table_vec(TRAP_RESERVED_INST, do_reserved_inst); @@ -759,7 +840,15 @@ void __init trap_init(void) set_exception_table_evt(0x800, do_fpu_state_restore); set_exception_table_evt(0x820, do_fpu_state_restore); #endif - + +#ifdef CONFIG_CPU_SH2 + set_exception_table_vec(TRAP_ADDRESS_ERROR, address_error_handler); +#endif +#ifdef CONFIG_CPU_SH2A + set_exception_table_vec(TRAP_DIVZERO_ERROR, do_divide_error); + set_exception_table_vec(TRAP_DIVOVF_ERROR, do_divide_error); +#endif + /* Setup VBR for boot cpu */ per_cpu_trap_init(); } @@ -784,6 +873,11 @@ void show_trace(struct task_struct *tsk, unsigned long *sp, } printk("\n"); + + if (!tsk) + tsk = current; + + debug_show_held_locks(tsk); } void show_stack(struct task_struct *tsk, unsigned long *sp) diff --git a/trunk/arch/sh/kernel/vsyscall/vsyscall.c b/trunk/arch/sh/kernel/vsyscall/vsyscall.c index 075d6cc1a2d7..deb46941f315 100644 --- a/trunk/arch/sh/kernel/vsyscall/vsyscall.c +++ b/trunk/arch/sh/kernel/vsyscall/vsyscall.c @@ -97,7 +97,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, goto up_fail; } - vma = kmem_cache_zalloc(vm_area_cachep, SLAB_KERNEL); + vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL); if (!vma) { ret = -ENOMEM; goto up_fail; diff --git a/trunk/arch/sh/mm/Kconfig b/trunk/arch/sh/mm/Kconfig index 9dd606464d23..4e0362f50384 100644 --- a/trunk/arch/sh/mm/Kconfig +++ b/trunk/arch/sh/mm/Kconfig @@ -4,8 +4,12 @@ menu "Processor selection" # Processor families # config CPU_SH2 + select SH_WRITETHROUGH if !CPU_SH2A bool - select SH_WRITETHROUGH + +config CPU_SH2A + bool + select CPU_SH2 config CPU_SH3 bool @@ -16,6 +20,7 @@ config CPU_SH4 bool select CPU_HAS_INTEVT select CPU_HAS_SR_RB + select CPU_HAS_PTEA if !CPU_SUBTYPE_ST40 config CPU_SH4A bool @@ -40,6 +45,16 @@ config CPU_SUBTYPE_SH7604 bool "Support SH7604 processor" select CPU_SH2 +config CPU_SUBTYPE_SH7619 + bool "Support SH7619 processor" + select CPU_SH2 + +comment "SH-2A Processor Support" + +config CPU_SUBTYPE_SH7206 + bool "Support SH7206 processor" + select CPU_SH2A + comment "SH-3 Processor Support" config CPU_SUBTYPE_SH7300 @@ -89,6 +104,7 @@ comment "SH-4 Processor Support" config CPU_SUBTYPE_SH7750 bool "Support SH7750 processor" select CPU_SH4 + select CPU_HAS_IPR_IRQ help Select SH7750 if you have a 200 Mhz SH-4 HD6417750 CPU. @@ -104,15 +120,18 @@ config CPU_SUBTYPE_SH7750R bool "Support SH7750R processor" select CPU_SH4 select CPU_SUBTYPE_SH7750 + select CPU_HAS_IPR_IRQ config CPU_SUBTYPE_SH7750S bool "Support SH7750S processor" select CPU_SH4 select CPU_SUBTYPE_SH7750 + select CPU_HAS_IPR_IRQ config CPU_SUBTYPE_SH7751 bool "Support SH7751 processor" select CPU_SH4 + select CPU_HAS_IPR_IRQ help Select SH7751 if you have a 166 Mhz SH-4 HD6417751 CPU, or if you have a HD6417751R CPU. @@ -121,6 +140,7 @@ config CPU_SUBTYPE_SH7751R bool "Support SH7751R processor" select CPU_SH4 select CPU_SUBTYPE_SH7751 + select CPU_HAS_IPR_IRQ config CPU_SUBTYPE_SH7760 bool "Support SH7760 processor" @@ -157,6 +177,11 @@ config CPU_SUBTYPE_SH7780 select CPU_SH4A select CPU_HAS_INTC2_IRQ +config CPU_SUBTYPE_SH7785 + bool "Support SH7785 processor" + select CPU_SH4A + select CPU_HAS_INTC2_IRQ + comment "SH4AL-DSP Processor Support" config CPU_SUBTYPE_SH73180 @@ -216,13 +241,22 @@ config MEMORY_SIZE config 32BIT bool "Support 32-bit physical addressing through PMB" - depends on CPU_SH4A && MMU + depends on CPU_SH4A && MMU && (!X2TLB || BROKEN) default y help If you say Y here, physical addressing will be extended to 32-bits through the SH-4A PMB. If this is not set, legacy 29-bit physical addressing will be used. +config X2TLB + bool "Enable extended TLB mode" + depends on CPU_SUBTYPE_SH7785 && MMU && EXPERIMENTAL + help + Selecting this option will enable the extended mode of the SH-X2 + TLB. For legacy SH-X behaviour and interoperability, say N. For + all of the fun new features and a willingless to submit bug reports, + say Y. + config VSYSCALL bool "Support vsyscall page" depends on MMU @@ -236,17 +270,53 @@ config VSYSCALL For systems with an MMU that can afford to give up a page, (the default value) say Y. +choice + prompt "Kernel page size" + default PAGE_SIZE_4KB + +config PAGE_SIZE_4KB + bool "4kB" + help + This is the default page size used by all SuperH CPUs. + +config PAGE_SIZE_8KB + bool "8kB" + depends on EXPERIMENTAL && X2TLB + help + This enables 8kB pages as supported by SH-X2 and later MMUs. + +config PAGE_SIZE_64KB + bool "64kB" + depends on EXPERIMENTAL && CPU_SH4 + help + This enables support for 64kB pages, possible on all SH-4 + CPUs and later. Highly experimental, not recommended. + +endchoice + choice prompt "HugeTLB page size" depends on HUGETLB_PAGE && CPU_SH4 && MMU default HUGETLB_PAGE_SIZE_64K config HUGETLB_PAGE_SIZE_64K - bool "64K" + bool "64kB" + +config HUGETLB_PAGE_SIZE_256K + bool "256kB" + depends on X2TLB config HUGETLB_PAGE_SIZE_1MB bool "1MB" +config HUGETLB_PAGE_SIZE_4MB + bool "4MB" + depends on X2TLB + +config HUGETLB_PAGE_SIZE_64MB + bool "64MB" + depends on X2TLB + endchoice source "mm/Kconfig" @@ -274,7 +344,6 @@ config SH_DIRECT_MAPPED config SH_WRITETHROUGH bool "Use write-through caching" - default y if CPU_SH2 help Selecting this option will configure the caches in write-through mode, as opposed to the default write-back configuration. diff --git a/trunk/arch/sh/mm/cache-sh2.c b/trunk/arch/sh/mm/cache-sh2.c index 2689cb24ea2b..6614033f6be9 100644 --- a/trunk/arch/sh/mm/cache-sh2.c +++ b/trunk/arch/sh/mm/cache-sh2.c @@ -5,6 +5,7 @@ * * Released under the terms of the GNU GPL v2.0. */ + #include #include @@ -14,37 +15,43 @@ #include #include -/* - * Calculate the OC address and set the way bit on the SH-2. - * - * We must have already jump_to_P2()'ed prior to calling this - * function, since we rely on CCR manipulation to do the - * Right Thing(tm). - */ -unsigned long __get_oc_addr(unsigned long set, unsigned long way) +void __flush_wback_region(void *start, int size) { - unsigned long ccr; - - /* - * On SH-2 the way bit isn't tracked in the address field - * if we're doing address array access .. instead, we need - * to manually switch out the way in the CCR. - */ - ccr = ctrl_inl(CCR); - ccr &= ~0x00c0; - ccr |= way << cpu_data->dcache.way_shift; - - /* - * Despite the number of sets being halved, we end up losing - * the first 2 ways to OCRAM instead of the last 2 (if we're - * 4-way). As a result, forcibly setting the W1 bit handily - * bumps us up 2 ways. - */ - if (ccr & CCR_CACHE_ORA) - ccr |= 1 << (cpu_data->dcache.way_shift + 1); - - ctrl_outl(ccr, CCR); - - return CACHE_OC_ADDRESS_ARRAY | (set << cpu_data->dcache.entry_shift); + unsigned long v; + unsigned long begin, end; + + begin = (unsigned long)start & ~(L1_CACHE_BYTES-1); + end = ((unsigned long)start + size + L1_CACHE_BYTES-1) + & ~(L1_CACHE_BYTES-1); + for (v = begin; v < end; v+=L1_CACHE_BYTES) { + /* FIXME cache purge */ + ctrl_outl((v & 0x1ffffc00), (v & 0x00000ff0) | 0x00000008); + } +} + +void __flush_purge_region(void *start, int size) +{ + unsigned long v; + unsigned long begin, end; + + begin = (unsigned long)start & ~(L1_CACHE_BYTES-1); + end = ((unsigned long)start + size + L1_CACHE_BYTES-1) + & ~(L1_CACHE_BYTES-1); + for (v = begin; v < end; v+=L1_CACHE_BYTES) { + ctrl_outl((v & 0x1ffffc00), (v & 0x00000ff0) | 0x00000008); + } +} + +void __flush_invalidate_region(void *start, int size) +{ + unsigned long v; + unsigned long begin, end; + + begin = (unsigned long)start & ~(L1_CACHE_BYTES-1); + end = ((unsigned long)start + size + L1_CACHE_BYTES-1) + & ~(L1_CACHE_BYTES-1); + for (v = begin; v < end; v+=L1_CACHE_BYTES) { + ctrl_outl((v & 0x1ffffc00), (v & 0x00000ff0) | 0x00000008); + } } diff --git a/trunk/arch/sh/mm/cache-sh4.c b/trunk/arch/sh/mm/cache-sh4.c index e48cc22724d9..ae531affccbd 100644 --- a/trunk/arch/sh/mm/cache-sh4.c +++ b/trunk/arch/sh/mm/cache-sh4.c @@ -11,12 +11,8 @@ */ #include #include -#include -#include -#include -#include -#include -#include +#include +#include #include #include @@ -83,9 +79,9 @@ static void __init emit_cache_params(void) */ /* Worst case assumed to be 64k cache, direct-mapped i.e. 4 synonym bits. */ -#define MAX_P3_SEMAPHORES 16 +#define MAX_P3_MUTEXES 16 -struct semaphore p3map_sem[MAX_P3_SEMAPHORES]; +struct mutex p3map_mutex[MAX_P3_MUTEXES]; void __init p3_cache_init(void) { @@ -115,7 +111,7 @@ void __init p3_cache_init(void) panic("%s failed.", __FUNCTION__); for (i = 0; i < cpu_data->dcache.n_aliases; i++) - sema_init(&p3map_sem[i], 1); + mutex_init(&p3map_mutex[i]); } /* @@ -229,7 +225,7 @@ static inline void flush_cache_4096(unsigned long start, */ if ((cpu_data->flags & CPU_HAS_P2_FLUSH_BUG) || (start < CACHE_OC_ADDRESS_ARRAY)) - exec_offset = 0x20000000; + exec_offset = 0x20000000; local_irq_save(flags); __flush_cache_4096(start | SH_CACHE_ASSOC, @@ -250,7 +246,7 @@ void flush_dcache_page(struct page *page) /* Loop all the D-cache */ n = cpu_data->dcache.n_aliases; - for (i = 0; i < n; i++, addr += PAGE_SIZE) + for (i = 0; i < n; i++, addr += 4096) flush_cache_4096(addr, phys); } diff --git a/trunk/arch/sh/mm/clear_page.S b/trunk/arch/sh/mm/clear_page.S index 7b96425ae270..8a706131e521 100644 --- a/trunk/arch/sh/mm/clear_page.S +++ b/trunk/arch/sh/mm/clear_page.S @@ -1,12 +1,12 @@ -/* $Id: clear_page.S,v 1.13 2003/08/25 17:03:10 lethal Exp $ - * +/* * __clear_user_page, __clear_user, clear_page implementation of SuperH * * Copyright (C) 2001 Kaz Kojima * Copyright (C) 2001, 2002 Niibe Yutaka - * + * Copyright (C) 2006 Paul Mundt */ #include +#include /* * clear_page_slow @@ -18,11 +18,11 @@ /* * r0 --- scratch * r4 --- to - * r5 --- to + 4096 + * r5 --- to + PAGE_SIZE */ ENTRY(clear_page_slow) mov r4,r5 - mov.w .Llimit,r0 + mov.l .Llimit,r0 add r0,r5 mov #0,r0 ! @@ -50,7 +50,7 @@ ENTRY(clear_page_slow) ! rts nop -.Llimit: .word (4096-28) +.Llimit: .long (PAGE_SIZE-28) ENTRY(__clear_user) ! @@ -164,10 +164,10 @@ ENTRY(__clear_user) * r0 --- scratch * r4 --- to * r5 --- orig_to - * r6 --- to + 4096 + * r6 --- to + PAGE_SIZE */ ENTRY(__clear_user_page) - mov.w .L4096,r0 + mov.l .Lpsz,r0 mov r4,r6 add r0,r6 mov #0,r0 @@ -191,7 +191,7 @@ ENTRY(__clear_user_page) ! rts nop -.L4096: .word 4096 +.Lpsz: .long PAGE_SIZE #endif diff --git a/trunk/arch/sh/mm/copy_page.S b/trunk/arch/sh/mm/copy_page.S index 1addffe117c3..397c94c97315 100644 --- a/trunk/arch/sh/mm/copy_page.S +++ b/trunk/arch/sh/mm/copy_page.S @@ -1,12 +1,12 @@ -/* $Id: copy_page.S,v 1.8 2003/08/25 17:03:10 lethal Exp $ - * +/* * copy_page, __copy_user_page, __copy_user implementation of SuperH * * Copyright (C) 2001 Niibe Yutaka & Kaz Kojima * Copyright (C) 2002 Toshinobu Sugioka - * + * Copyright (C) 2006 Paul Mundt */ #include +#include /* * copy_page_slow @@ -18,7 +18,7 @@ /* * r0, r1, r2, r3, r4, r5, r6, r7 --- scratch - * r8 --- from + 4096 + * r8 --- from + PAGE_SIZE * r9 --- not used * r10 --- to * r11 --- from @@ -30,7 +30,7 @@ ENTRY(copy_page_slow) mov r4,r10 mov r5,r11 mov r5,r8 - mov.w .L4096,r0 + mov.l .Lpsz,r0 add r0,r8 ! 1: mov.l @r11+,r0 @@ -80,7 +80,7 @@ ENTRY(copy_page_slow) /* * r0, r1, r2, r3, r4, r5, r6, r7 --- scratch - * r8 --- from + 4096 + * r8 --- from + PAGE_SIZE * r9 --- orig_to * r10 --- to * r11 --- from @@ -94,7 +94,7 @@ ENTRY(__copy_user_page) mov r5,r11 mov r6,r9 mov r5,r8 - mov.w .L4096,r0 + mov.l .Lpsz,r0 add r0,r8 ! 1: ocbi @r9 @@ -129,7 +129,7 @@ ENTRY(__copy_user_page) rts nop #endif -.L4096: .word 4096 +.Lpsz: .long PAGE_SIZE /* * __kernel_size_t __copy_user(void *to, const void *from, __kernel_size_t n); * Return the number of bytes NOT copied diff --git a/trunk/arch/sh/mm/fault.c b/trunk/arch/sh/mm/fault.c index 68663b8f99ae..716ebf568af2 100644 --- a/trunk/arch/sh/mm/fault.c +++ b/trunk/arch/sh/mm/fault.c @@ -26,13 +26,19 @@ extern void die(const char *,struct pt_regs *,long); * and the problem, and then passes it off to one of the appropriate * routines. */ -asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long writeaccess, - unsigned long address) +asmlinkage void __kprobes do_page_fault(struct pt_regs *regs, + unsigned long writeaccess, + unsigned long address) { struct task_struct *tsk; struct mm_struct *mm; struct vm_area_struct * vma; unsigned long page; + int si_code; + siginfo_t info; + + trace_hardirqs_on(); + local_irq_enable(); #ifdef CONFIG_SH_KGDB if (kgdb_nofault && kgdb_bus_err_hook) @@ -41,6 +47,46 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long writeaccess, tsk = current; mm = tsk->mm; + si_code = SEGV_MAPERR; + + if (unlikely(address >= TASK_SIZE)) { + /* + * Synchronize this task's top level page-table + * with the 'reference' page table. + * + * Do _not_ use "tsk" here. We might be inside + * an interrupt in the middle of a task switch.. + */ + int offset = pgd_index(address); + pgd_t *pgd, *pgd_k; + pud_t *pud, *pud_k; + pmd_t *pmd, *pmd_k; + + pgd = get_TTB() + offset; + pgd_k = swapper_pg_dir + offset; + + /* This will never happen with the folded page table. */ + if (!pgd_present(*pgd)) { + if (!pgd_present(*pgd_k)) + goto bad_area_nosemaphore; + set_pgd(pgd, *pgd_k); + return; + } + + pud = pud_offset(pgd, address); + pud_k = pud_offset(pgd_k, address); + if (pud_present(*pud) || !pud_present(*pud_k)) + goto bad_area_nosemaphore; + set_pud(pud, *pud_k); + + pmd = pmd_offset(pud, address); + pmd_k = pmd_offset(pud_k, address); + if (pmd_present(*pmd) || !pmd_present(*pmd_k)) + goto bad_area_nosemaphore; + set_pmd(pmd, *pmd_k); + + return; + } /* * If we're in an interrupt or have no user @@ -65,6 +111,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long writeaccess, * we can handle it.. */ good_area: + si_code = SEGV_ACCERR; if (writeaccess) { if (!(vma->vm_flags & VM_WRITE)) goto bad_area; @@ -104,10 +151,13 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long writeaccess, bad_area: up_read(&mm->mmap_sem); +bad_area_nosemaphore: if (user_mode(regs)) { - tsk->thread.address = address; - tsk->thread.error_code = writeaccess; - force_sig(SIGSEGV, tsk); + info.si_signo = SIGSEGV; + info.si_errno = 0; + info.si_code = si_code; + info.si_addr = (void *) address; + force_sig_info(SIGSEGV, &info, tsk); return; } @@ -127,11 +177,9 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long writeaccess, printk(KERN_ALERT "Unable to handle kernel paging request"); printk(" at virtual address %08lx\n", address); printk(KERN_ALERT "pc = %08lx\n", regs->pc); - asm volatile("mov.l %1, %0" - : "=r" (page) - : "m" (__m(MMU_TTB))); + page = (unsigned long)get_TTB(); if (page) { - page = ((unsigned long *) page)[address >> 22]; + page = ((unsigned long *) page)[address >> PGDIR_SHIFT]; printk(KERN_ALERT "*pde = %08lx\n", page); if (page & _PAGE_PRESENT) { page &= PAGE_MASK; @@ -166,98 +214,13 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long writeaccess, * Send a sigbus, regardless of whether we were in kernel * or user mode. */ - tsk->thread.address = address; - tsk->thread.error_code = writeaccess; - tsk->thread.trap_no = 14; - force_sig(SIGBUS, tsk); + info.si_signo = SIGBUS; + info.si_errno = 0; + info.si_code = BUS_ADRERR; + info.si_addr = (void *)address; + force_sig_info(SIGBUS, &info, tsk); /* Kernel mode? Handle exceptions or die */ if (!user_mode(regs)) goto no_context; } - -#ifdef CONFIG_SH_STORE_QUEUES -/* - * This is a special case for the SH-4 store queues, as pages for this - * space still need to be faulted in before it's possible to flush the - * store queue cache for writeout to the remapped region. - */ -#define P3_ADDR_MAX (P4SEG_STORE_QUE + 0x04000000) -#else -#define P3_ADDR_MAX P4SEG -#endif - -/* - * Called with interrupts disabled. - */ -asmlinkage int __kprobes __do_page_fault(struct pt_regs *regs, - unsigned long writeaccess, - unsigned long address) -{ - pgd_t *pgd; - pud_t *pud; - pmd_t *pmd; - pte_t *pte; - pte_t entry; - struct mm_struct *mm = current->mm; - spinlock_t *ptl; - int ret = 1; - -#ifdef CONFIG_SH_KGDB - if (kgdb_nofault && kgdb_bus_err_hook) - kgdb_bus_err_hook(); -#endif - - /* - * We don't take page faults for P1, P2, and parts of P4, these - * are always mapped, whether it be due to legacy behaviour in - * 29-bit mode, or due to PMB configuration in 32-bit mode. - */ - if (address >= P3SEG && address < P3_ADDR_MAX) { - pgd = pgd_offset_k(address); - mm = NULL; - } else { - if (unlikely(address >= TASK_SIZE || !mm)) - return 1; - - pgd = pgd_offset(mm, address); - } - - pud = pud_offset(pgd, address); - if (pud_none_or_clear_bad(pud)) - return 1; - pmd = pmd_offset(pud, address); - if (pmd_none_or_clear_bad(pmd)) - return 1; - - if (mm) - pte = pte_offset_map_lock(mm, pmd, address, &ptl); - else - pte = pte_offset_kernel(pmd, address); - - entry = *pte; - if (unlikely(pte_none(entry) || pte_not_present(entry))) - goto unlock; - if (unlikely(writeaccess && !pte_write(entry))) - goto unlock; - - if (writeaccess) - entry = pte_mkdirty(entry); - entry = pte_mkyoung(entry); - -#ifdef CONFIG_CPU_SH4 - /* - * ITLB is not affected by "ldtlb" instruction. - * So, we need to flush the entry by ourselves. - */ - __flush_tlb_page(get_asid(), address & PAGE_MASK); -#endif - - set_pte(pte, entry); - update_mmu_cache(NULL, address, entry); - ret = 0; -unlock: - if (mm) - pte_unmap_unlock(pte, ptl); - return ret; -} diff --git a/trunk/arch/sh/mm/hugetlbpage.c b/trunk/arch/sh/mm/hugetlbpage.c index 329059d6b54a..cf2c2ee35a37 100644 --- a/trunk/arch/sh/mm/hugetlbpage.c +++ b/trunk/arch/sh/mm/hugetlbpage.c @@ -63,6 +63,11 @@ pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr) return pte; } +int huge_pmd_unshare(struct mm_struct *mm, unsigned long *addr, pte_t *ptep) +{ + return 0; +} + struct page *follow_huge_addr(struct mm_struct *mm, unsigned long address, int write) { diff --git a/trunk/arch/sh/mm/init.c b/trunk/arch/sh/mm/init.c index 7154d1ce9785..59f4cc18235b 100644 --- a/trunk/arch/sh/mm/init.c +++ b/trunk/arch/sh/mm/init.c @@ -84,30 +84,22 @@ static void set_pte_phys(unsigned long addr, unsigned long phys, pgprot_t prot) pmd_t *pmd; pte_t *pte; - pgd = swapper_pg_dir + pgd_index(addr); + pgd = pgd_offset_k(addr); if (pgd_none(*pgd)) { pgd_ERROR(*pgd); return; } - pud = pud_offset(pgd, addr); - if (pud_none(*pud)) { - pmd = (pmd_t *)get_zeroed_page(GFP_ATOMIC); - set_pud(pud, __pud(__pa(pmd) | _KERNPG_TABLE | _PAGE_USER)); - if (pmd != pmd_offset(pud, 0)) { - pud_ERROR(*pud); - return; - } + pud = pud_alloc(NULL, pgd, addr); + if (unlikely(!pud)) { + pud_ERROR(*pud); + return; } - pmd = pmd_offset(pud, addr); - if (pmd_none(*pmd)) { - pte = (pte_t *)get_zeroed_page(GFP_ATOMIC); - set_pmd(pmd, __pmd(__pa(pte) | _KERNPG_TABLE | _PAGE_USER)); - if (pte != pte_offset_kernel(pmd, 0)) { - pmd_ERROR(*pmd); - return; - } + pmd = pmd_alloc(NULL, pud, addr); + if (unlikely(!pmd)) { + pmd_ERROR(*pmd); + return; } pte = pte_offset_kernel(pmd, addr); @@ -155,9 +147,6 @@ extern char __init_begin, __init_end; /* * paging_init() sets up the page tables - * - * This routines also unmaps the page at virtual kernel address 0, so - * that we can trap those pesky NULL-reference errors in the kernel. */ void __init paging_init(void) { @@ -180,14 +169,11 @@ void __init paging_init(void) */ { unsigned long max_dma, low, start_pfn; - pgd_t *pg_dir; - int i; - - /* We don't need kernel mapping as hardware support that. */ - pg_dir = swapper_pg_dir; - for (i = 0; i < PTRS_PER_PGD; i++) - pgd_val(pg_dir[i]) = 0; + /* We don't need to map the kernel through the TLB, as + * it is permanatly mapped using P1. So clear the + * entire pgd. */ + memset(swapper_pg_dir, 0, sizeof(swapper_pg_dir)); /* Turn on the MMU */ enable_mmu(); @@ -206,6 +192,10 @@ void __init paging_init(void) } } + /* Set an initial value for the MMU.TTB so we don't have to + * check for a null value. */ + set_TTB(swapper_pg_dir); + #elif defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH4) /* * If we don't have CONFIG_MMU set and the processor in question @@ -227,7 +217,6 @@ static struct kcore_list kcore_mem, kcore_vmalloc; void __init mem_init(void) { - extern unsigned long empty_zero_page[1024]; int codesize, reservedpages, datasize, initsize; int tmp; extern unsigned long memory_start; diff --git a/trunk/arch/sh/mm/ioremap.c b/trunk/arch/sh/mm/ioremap.c index a9fe80cfc233..90b494a0cf45 100644 --- a/trunk/arch/sh/mm/ioremap.c +++ b/trunk/arch/sh/mm/ioremap.c @@ -16,99 +16,13 @@ #include #include #include -#include +#include #include #include #include #include #include -static inline void remap_area_pte(pte_t * pte, unsigned long address, - unsigned long size, unsigned long phys_addr, unsigned long flags) -{ - unsigned long end; - unsigned long pfn; - pgprot_t pgprot = __pgprot(_PAGE_PRESENT | _PAGE_RW | - _PAGE_DIRTY | _PAGE_ACCESSED | - _PAGE_HW_SHARED | _PAGE_FLAGS_HARD | flags); - - address &= ~PMD_MASK; - end = address + size; - if (end > PMD_SIZE) - end = PMD_SIZE; - if (address >= end) - BUG(); - pfn = phys_addr >> PAGE_SHIFT; - do { - if (!pte_none(*pte)) { - printk("remap_area_pte: page already exists\n"); - BUG(); - } - set_pte(pte, pfn_pte(pfn, pgprot)); - address += PAGE_SIZE; - pfn++; - pte++; - } while (address && (address < end)); -} - -static inline int remap_area_pmd(pmd_t * pmd, unsigned long address, - unsigned long size, unsigned long phys_addr, unsigned long flags) -{ - unsigned long end; - - address &= ~PGDIR_MASK; - end = address + size; - if (end > PGDIR_SIZE) - end = PGDIR_SIZE; - phys_addr -= address; - if (address >= end) - BUG(); - do { - pte_t * pte = pte_alloc_kernel(pmd, address); - if (!pte) - return -ENOMEM; - remap_area_pte(pte, address, end - address, address + phys_addr, flags); - address = (address + PMD_SIZE) & PMD_MASK; - pmd++; - } while (address && (address < end)); - return 0; -} - -int remap_area_pages(unsigned long address, unsigned long phys_addr, - unsigned long size, unsigned long flags) -{ - int error; - pgd_t * dir; - unsigned long end = address + size; - - phys_addr -= address; - dir = pgd_offset_k(address); - flush_cache_all(); - if (address >= end) - BUG(); - do { - pud_t *pud; - pmd_t *pmd; - - error = -ENOMEM; - - pud = pud_alloc(&init_mm, dir, address); - if (!pud) - break; - pmd = pmd_alloc(&init_mm, pud, address); - if (!pmd) - break; - if (remap_area_pmd(pmd, address, end - address, - phys_addr + address, flags)) - break; - error = 0; - address = (address + PGDIR_SIZE) & PGDIR_MASK; - dir++; - } while (address && (address < end)); - flush_tlb_all(); - return error; -} - /* * Remap an arbitrary physical address space into the kernel virtual * address space. Needed when the kernel wants to access high addresses @@ -123,6 +37,7 @@ void __iomem *__ioremap(unsigned long phys_addr, unsigned long size, { struct vm_struct * area; unsigned long offset, last_addr, addr, orig_addr; + pgprot_t pgprot; /* Don't allow wraparound or zero size */ last_addr = phys_addr + size - 1; @@ -192,8 +107,9 @@ void __iomem *__ioremap(unsigned long phys_addr, unsigned long size, } #endif + pgprot = __pgprot(pgprot_val(PAGE_KERNEL_NOCACHE) | flags); if (likely(size)) - if (remap_area_pages(addr, phys_addr, size, flags)) { + if (ioremap_page_range(addr, addr + size, phys_addr, pgprot)) { vunmap((void *)orig_addr); return NULL; } diff --git a/trunk/arch/sh/mm/pg-dma.c b/trunk/arch/sh/mm/pg-dma.c index 1406d2e348ca..bb23679369d6 100644 --- a/trunk/arch/sh/mm/pg-dma.c +++ b/trunk/arch/sh/mm/pg-dma.c @@ -39,8 +39,6 @@ static void copy_page_dma(void *to, void *from) static void clear_page_dma(void *to) { - extern unsigned long empty_zero_page[1024]; - /* * We get invoked quite early on, if the DMAC hasn't been initialized * yet, fall back on the slow manual implementation. diff --git a/trunk/arch/sh/mm/pg-sh4.c b/trunk/arch/sh/mm/pg-sh4.c index 07371ed7a313..3f98d2a4f936 100644 --- a/trunk/arch/sh/mm/pg-sh4.c +++ b/trunk/arch/sh/mm/pg-sh4.c @@ -6,22 +6,12 @@ * * Released under the terms of the GNU GPL v2.0. */ -#include -#include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include #include #include -extern struct semaphore p3map_sem[]; +extern struct mutex p3map_mutex[]; #define CACHE_ALIAS (cpu_data->dcache.alias_mask) @@ -37,10 +27,6 @@ void clear_user_page(void *to, unsigned long address, struct page *page) if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0) clear_page(to); else { - pgprot_t pgprot = __pgprot(_PAGE_PRESENT | - _PAGE_RW | _PAGE_CACHABLE | - _PAGE_DIRTY | _PAGE_ACCESSED | - _PAGE_HW_SHARED | _PAGE_FLAGS_HARD); unsigned long phys_addr = PHYSADDR(to); unsigned long p3_addr = P3SEG + (address & CACHE_ALIAS); pgd_t *pgd = pgd_offset_k(p3_addr); @@ -50,8 +36,8 @@ void clear_user_page(void *to, unsigned long address, struct page *page) pte_t entry; unsigned long flags; - entry = pfn_pte(phys_addr >> PAGE_SHIFT, pgprot); - down(&p3map_sem[(address & CACHE_ALIAS)>>12]); + entry = pfn_pte(phys_addr >> PAGE_SHIFT, PAGE_KERNEL); + mutex_lock(&p3map_mutex[(address & CACHE_ALIAS)>>12]); set_pte(pte, entry); local_irq_save(flags); __flush_tlb_page(get_asid(), p3_addr); @@ -59,7 +45,7 @@ void clear_user_page(void *to, unsigned long address, struct page *page) update_mmu_cache(NULL, p3_addr, entry); __clear_user_page((void *)p3_addr, to); pte_clear(&init_mm, p3_addr, pte); - up(&p3map_sem[(address & CACHE_ALIAS)>>12]); + mutex_unlock(&p3map_mutex[(address & CACHE_ALIAS)>>12]); } } @@ -77,10 +63,6 @@ void copy_user_page(void *to, void *from, unsigned long address, if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0) copy_page(to, from); else { - pgprot_t pgprot = __pgprot(_PAGE_PRESENT | - _PAGE_RW | _PAGE_CACHABLE | - _PAGE_DIRTY | _PAGE_ACCESSED | - _PAGE_HW_SHARED | _PAGE_FLAGS_HARD); unsigned long phys_addr = PHYSADDR(to); unsigned long p3_addr = P3SEG + (address & CACHE_ALIAS); pgd_t *pgd = pgd_offset_k(p3_addr); @@ -90,8 +72,8 @@ void copy_user_page(void *to, void *from, unsigned long address, pte_t entry; unsigned long flags; - entry = pfn_pte(phys_addr >> PAGE_SHIFT, pgprot); - down(&p3map_sem[(address & CACHE_ALIAS)>>12]); + entry = pfn_pte(phys_addr >> PAGE_SHIFT, PAGE_KERNEL); + mutex_lock(&p3map_mutex[(address & CACHE_ALIAS)>>12]); set_pte(pte, entry); local_irq_save(flags); __flush_tlb_page(get_asid(), p3_addr); @@ -99,7 +81,7 @@ void copy_user_page(void *to, void *from, unsigned long address, update_mmu_cache(NULL, p3_addr, entry); __copy_user_page((void *)p3_addr, from, to); pte_clear(&init_mm, p3_addr, pte); - up(&p3map_sem[(address & CACHE_ALIAS)>>12]); + mutex_unlock(&p3map_mutex[(address & CACHE_ALIAS)>>12]); } } @@ -122,4 +104,3 @@ inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t } return pte; } - diff --git a/trunk/arch/sh/mm/pmb.c b/trunk/arch/sh/mm/pmb.c index 92e745341e4d..b60ad83a7635 100644 --- a/trunk/arch/sh/mm/pmb.c +++ b/trunk/arch/sh/mm/pmb.c @@ -30,7 +30,7 @@ #define NR_PMB_ENTRIES 16 -static kmem_cache_t *pmb_cache; +static struct kmem_cache *pmb_cache; static unsigned long pmb_map; static struct pmb_entry pmb_init_map[] = { @@ -283,7 +283,7 @@ void pmb_unmap(unsigned long addr) } while (pmbe); } -static void pmb_cache_ctor(void *pmb, kmem_cache_t *cachep, unsigned long flags) +static void pmb_cache_ctor(void *pmb, struct kmem_cache *cachep, unsigned long flags) { struct pmb_entry *pmbe = pmb; @@ -297,7 +297,7 @@ static void pmb_cache_ctor(void *pmb, kmem_cache_t *cachep, unsigned long flags) spin_unlock_irq(&pmb_list_lock); } -static void pmb_cache_dtor(void *pmb, kmem_cache_t *cachep, unsigned long flags) +static void pmb_cache_dtor(void *pmb, struct kmem_cache *cachep, unsigned long flags) { spin_lock_irq(&pmb_list_lock); pmb_list_del(pmb); diff --git a/trunk/arch/sh/oprofile/op_model_sh7750.c b/trunk/arch/sh/oprofile/op_model_sh7750.c index c265185b22a7..60402eec4b4d 100644 --- a/trunk/arch/sh/oprofile/op_model_sh7750.c +++ b/trunk/arch/sh/oprofile/op_model_sh7750.c @@ -142,7 +142,7 @@ static u64 sh7750_read_counter(int counter) */ static inline int to_counter(struct file *file) { - const unsigned char *name = file->f_dentry->d_parent->d_name.name; + const unsigned char *name = file->f_path.dentry->d_parent->d_name.name; return (int)simple_strtol(name, NULL, 10); } diff --git a/trunk/arch/sh/tools/mach-types b/trunk/arch/sh/tools/mach-types index ac57638977ee..0571755e9a84 100644 --- a/trunk/arch/sh/tools/mach-types +++ b/trunk/arch/sh/tools/mach-types @@ -30,3 +30,5 @@ R7780MP SH_R7780MP TITAN SH_TITAN SHMIN SH_SHMIN 7710VOIPGW SH_7710VOIPGW +7206SE SH_7206_SOLUTION_ENGINE +7619SE SH_7619_SOLUTION_ENGINE diff --git a/trunk/arch/sh64/Kconfig b/trunk/arch/sh64/Kconfig index 58c678e06667..7bc0744b7ab6 100644 --- a/trunk/arch/sh64/Kconfig +++ b/trunk/arch/sh64/Kconfig @@ -39,6 +39,14 @@ config RWSEM_XCHGADD_ALGORITHM config GENERIC_ISA_DMA bool +config ARCH_HAS_ILOG2_U32 + bool + default n + +config ARCH_HAS_ILOG2_U64 + bool + default n + source init/Kconfig menu "System type" diff --git a/trunk/arch/sh64/kernel/setup.c b/trunk/arch/sh64/kernel/setup.c index ffb310e33cef..b9e7d54d7b85 100644 --- a/trunk/arch/sh64/kernel/setup.c +++ b/trunk/arch/sh64/kernel/setup.c @@ -243,9 +243,7 @@ void __init setup_arch(char **cmdline_p) if (INITRD_START + INITRD_SIZE <= (PFN_PHYS(last_pfn))) { reserve_bootmem_node(NODE_DATA(0), INITRD_START + __MEMORY_START, INITRD_SIZE); - initrd_start = - (long) INITRD_START ? INITRD_START + PAGE_OFFSET + __MEMORY_START : 0; - + initrd_start = (long) INITRD_START + PAGE_OFFSET + __MEMORY_START; initrd_end = initrd_start + INITRD_SIZE; } else { printk("initrd extends beyond end of memory " diff --git a/trunk/arch/sh64/kernel/signal.c b/trunk/arch/sh64/kernel/signal.c index 9e2ffc45c0e0..1666d3efb52e 100644 --- a/trunk/arch/sh64/kernel/signal.c +++ b/trunk/arch/sh64/kernel/signal.c @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/trunk/arch/sh64/mm/fault.c b/trunk/arch/sh64/mm/fault.c index 8e2f6c28b739..4f72ab33bb2b 100644 --- a/trunk/arch/sh64/mm/fault.c +++ b/trunk/arch/sh64/mm/fault.c @@ -154,7 +154,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long writeaccess, * If we're in an interrupt or have no user * context, we must not take the fault.. */ - if (in_interrupt() || !mm) + if (in_atomic() || !mm) goto no_context; /* TLB misses upon some cache flushes get done under cli() */ diff --git a/trunk/arch/sh64/mm/hugetlbpage.c b/trunk/arch/sh64/mm/hugetlbpage.c index 187cf01750b8..4b455f611146 100644 --- a/trunk/arch/sh64/mm/hugetlbpage.c +++ b/trunk/arch/sh64/mm/hugetlbpage.c @@ -53,6 +53,11 @@ pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr) return pte; } +int huge_pmd_unshare(struct mm_struct *mm, unsigned long *addr, pte_t *ptep) +{ + return 0; +} + void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t entry) { diff --git a/trunk/arch/sh64/mm/ioremap.c b/trunk/arch/sh64/mm/ioremap.c index 80c56754f513..ff26c02511aa 100644 --- a/trunk/arch/sh64/mm/ioremap.c +++ b/trunk/arch/sh64/mm/ioremap.c @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include #include #include @@ -28,96 +28,6 @@ static void shmedia_mapioaddr(unsigned long, unsigned long); static unsigned long shmedia_ioremap(struct resource *, u32, int); -static inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned long size, - unsigned long phys_addr, unsigned long flags) -{ - unsigned long end; - unsigned long pfn; - pgprot_t pgprot = __pgprot(_PAGE_PRESENT | _PAGE_READ | - _PAGE_WRITE | _PAGE_DIRTY | - _PAGE_ACCESSED | _PAGE_SHARED | flags); - - address &= ~PMD_MASK; - end = address + size; - if (end > PMD_SIZE) - end = PMD_SIZE; - if (address >= end) - BUG(); - - pfn = phys_addr >> PAGE_SHIFT; - - pr_debug(" %s: pte %p address %lx size %lx phys_addr %lx\n", - __FUNCTION__,pte,address,size,phys_addr); - - do { - if (!pte_none(*pte)) { - printk("remap_area_pte: page already exists\n"); - BUG(); - } - - set_pte(pte, pfn_pte(pfn, pgprot)); - address += PAGE_SIZE; - pfn++; - pte++; - } while (address && (address < end)); -} - -static inline int remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size, - unsigned long phys_addr, unsigned long flags) -{ - unsigned long end; - - address &= ~PGDIR_MASK; - end = address + size; - - if (end > PGDIR_SIZE) - end = PGDIR_SIZE; - - phys_addr -= address; - - if (address >= end) - BUG(); - - do { - pte_t * pte = pte_alloc_kernel(pmd, address); - if (!pte) - return -ENOMEM; - remap_area_pte(pte, address, end - address, address + phys_addr, flags); - address = (address + PMD_SIZE) & PMD_MASK; - pmd++; - } while (address && (address < end)); - return 0; -} - -static int remap_area_pages(unsigned long address, unsigned long phys_addr, - unsigned long size, unsigned long flags) -{ - int error; - pgd_t * dir; - unsigned long end = address + size; - - phys_addr -= address; - dir = pgd_offset_k(address); - flush_cache_all(); - if (address >= end) - BUG(); - do { - pmd_t *pmd = pmd_alloc(&init_mm, dir, address); - error = -ENOMEM; - if (!pmd) - break; - if (remap_area_pmd(pmd, address, end - address, - phys_addr + address, flags)) { - break; - } - error = 0; - address = (address + PGDIR_SIZE) & PGDIR_MASK; - dir++; - } while (address && (address < end)); - flush_tlb_all(); - return 0; -} - /* * Generic mapping function (not visible outside): */ @@ -136,12 +46,17 @@ void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flag void * addr; struct vm_struct * area; unsigned long offset, last_addr; + pgprot_t pgprot; /* Don't allow wraparound or zero size */ last_addr = phys_addr + size - 1; if (!size || last_addr < phys_addr) return NULL; + pgprot = __pgprot(_PAGE_PRESENT | _PAGE_READ | + _PAGE_WRITE | _PAGE_DIRTY | + _PAGE_ACCESSED | _PAGE_SHARED | flags); + /* * Mappings have to be page-aligned */ @@ -158,7 +73,8 @@ void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flag return NULL; area->phys_addr = phys_addr; addr = area->addr; - if (remap_area_pages((unsigned long)addr, phys_addr, size, flags)) { + if (ioremap_page_range((unsigned long)addr, (unsigned long)addr + size, + phys_addr, pgprot)) { vunmap(addr); return NULL; } diff --git a/trunk/arch/sparc/Kconfig b/trunk/arch/sparc/Kconfig index 92a7c8a636d3..d0dec1ea2eed 100644 --- a/trunk/arch/sparc/Kconfig +++ b/trunk/arch/sparc/Kconfig @@ -166,6 +166,14 @@ config ARCH_MAY_HAVE_PC_FDC bool default y +config ARCH_HAS_ILOG2_U32 + bool + default n + +config ARCH_HAS_ILOG2_U64 + bool + default n + config SUN_PM bool default y diff --git a/trunk/arch/sparc/kernel/sys_sunos.c b/trunk/arch/sparc/kernel/sys_sunos.c index 6f3ac548ee66..0bf8c165fc92 100644 --- a/trunk/arch/sparc/kernel/sys_sunos.c +++ b/trunk/arch/sparc/kernel/sys_sunos.c @@ -94,8 +94,8 @@ asmlinkage unsigned long sunos_mmap(unsigned long addr, unsigned long len, * SunOS is so stupid some times... hmph! */ if (file) { - if (imajor(file->f_dentry->d_inode) == MEM_MAJOR && - iminor(file->f_dentry->d_inode) == 5) { + if (imajor(file->f_path.dentry->d_inode) == MEM_MAJOR && + iminor(file->f_path.dentry->d_inode) == 5) { flags |= MAP_ANONYMOUS; fput(file); file = NULL; @@ -655,7 +655,7 @@ sunos_nfs_get_server_fd (int fd, struct sockaddr_in *addr) if (!file) goto out; - inode = file->f_dentry->d_inode; + inode = file->f_path.dentry->d_inode; socket = SOCKET_I(inode); local.sin_family = AF_INET; diff --git a/trunk/arch/sparc/kernel/vmlinux.lds.S b/trunk/arch/sparc/kernel/vmlinux.lds.S index 5cc5ff7f8824..b73e6b9067ed 100644 --- a/trunk/arch/sparc/kernel/vmlinux.lds.S +++ b/trunk/arch/sparc/kernel/vmlinux.lds.S @@ -11,6 +11,7 @@ SECTIONS . = 0x10000 + SIZEOF_HEADERS; .text 0xf0004000 : { + _text = .; *(.text) SCHED_TEXT LOCK_TEXT diff --git a/trunk/arch/sparc/mm/highmem.c b/trunk/arch/sparc/mm/highmem.c index 4d8ed9c65182..01fc6c254292 100644 --- a/trunk/arch/sparc/mm/highmem.c +++ b/trunk/arch/sparc/mm/highmem.c @@ -35,7 +35,7 @@ void *kmap_atomic(struct page *page, enum km_type type) unsigned long vaddr; /* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */ - inc_preempt_count(); + pagefault_disable(); if (!PageHighMem(page)) return page_address(page); @@ -70,8 +70,7 @@ void kunmap_atomic(void *kvaddr, enum km_type type) unsigned long idx = type + KM_TYPE_NR*smp_processor_id(); if (vaddr < FIXADDR_START) { // FIXME - dec_preempt_count(); - preempt_check_resched(); + pagefault_enable(); return; } @@ -97,8 +96,7 @@ void kunmap_atomic(void *kvaddr, enum km_type type) #endif #endif - dec_preempt_count(); - preempt_check_resched(); + pagefault_enable(); } /* We may be fed a pagetable here by ptep_to_xxx and others. */ diff --git a/trunk/arch/sparc64/Kconfig b/trunk/arch/sparc64/Kconfig index b627f8dbcaad..d391d11f245a 100644 --- a/trunk/arch/sparc64/Kconfig +++ b/trunk/arch/sparc64/Kconfig @@ -34,6 +34,14 @@ config ARCH_MAY_HAVE_PC_FDC bool default y +config ARCH_HAS_ILOG2_U32 + bool + default n + +config ARCH_HAS_ILOG2_U64 + bool + default n + config AUDIT_ARCH bool default y diff --git a/trunk/arch/sparc64/kernel/binfmt_aout32.c b/trunk/arch/sparc64/kernel/binfmt_aout32.c index d7caa60a0074..f205fc7cbcd0 100644 --- a/trunk/arch/sparc64/kernel/binfmt_aout32.c +++ b/trunk/arch/sparc64/kernel/binfmt_aout32.c @@ -209,7 +209,7 @@ static int load_aout32_binary(struct linux_binprm * bprm, struct pt_regs * regs) if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != OMAGIC && N_MAGIC(ex) != QMAGIC && N_MAGIC(ex) != NMAGIC) || N_TRSIZE(ex) || N_DRSIZE(ex) || - bprm->file->f_dentry->d_inode->i_size < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) { + bprm->file->f_path.dentry->d_inode->i_size < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) { return -ENOEXEC; } @@ -349,7 +349,7 @@ static int load_aout32_library(struct file *file) int retval; struct exec ex; - inode = file->f_dentry->d_inode; + inode = file->f_path.dentry->d_inode; retval = -ENOEXEC; error = kernel_read(file, 0, (char *) &ex, sizeof(ex)); diff --git a/trunk/arch/sparc64/kernel/binfmt_elf32.c b/trunk/arch/sparc64/kernel/binfmt_elf32.c index a98f3ae175a3..9ad84ff10a17 100644 --- a/trunk/arch/sparc64/kernel/binfmt_elf32.c +++ b/trunk/arch/sparc64/kernel/binfmt_elf32.c @@ -141,7 +141,6 @@ cputime_to_compat_timeval(const cputime_t cputime, struct compat_timeval *value) value->tv_sec = jiffies / HZ; } -#define elf_addr_t u32 #undef start_thread #define start_thread start_thread32 #define init_elf_binfmt init_elf32_binfmt diff --git a/trunk/arch/sparc64/kernel/sys_sunos32.c b/trunk/arch/sparc64/kernel/sys_sunos32.c index 7da72d3b322a..4446f66590fa 100644 --- a/trunk/arch/sparc64/kernel/sys_sunos32.c +++ b/trunk/arch/sparc64/kernel/sys_sunos32.c @@ -83,7 +83,7 @@ asmlinkage u32 sunos_mmap(u32 addr, u32 len, u32 prot, u32 flags, u32 fd, u32 of file = fget(fd); if (!file) goto out; - inode = file->f_dentry->d_inode; + inode = file->f_path.dentry->d_inode; if (imajor(inode) == MEM_MAJOR && iminor(inode) == 5) { flags |= MAP_ANONYMOUS; fput(file); @@ -615,7 +615,7 @@ sunos_nfs_get_server_fd (int fd, struct sockaddr_in *addr) if (!file) return 0; - inode = file->f_dentry->d_inode; + inode = file->f_path.dentry->d_inode; socket = SOCKET_I(inode); local.sin_family = AF_INET; diff --git a/trunk/arch/sparc64/kernel/vmlinux.lds.S b/trunk/arch/sparc64/kernel/vmlinux.lds.S index bd9de8c2a2aa..4a6063f33e7a 100644 --- a/trunk/arch/sparc64/kernel/vmlinux.lds.S +++ b/trunk/arch/sparc64/kernel/vmlinux.lds.S @@ -13,6 +13,7 @@ SECTIONS . = 0x4000; .text 0x0000000000404000 : { + _text = .; *(.text) SCHED_TEXT LOCK_TEXT diff --git a/trunk/arch/sparc64/mm/hugetlbpage.c b/trunk/arch/sparc64/mm/hugetlbpage.c index 53b9b1f528e5..33fd0b265e70 100644 --- a/trunk/arch/sparc64/mm/hugetlbpage.c +++ b/trunk/arch/sparc64/mm/hugetlbpage.c @@ -235,6 +235,11 @@ pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr) return pte; } +int huge_pmd_unshare(struct mm_struct *mm, unsigned long *addr, pte_t *ptep) +{ + return 0; +} + void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t entry) { diff --git a/trunk/arch/sparc64/mm/init.c b/trunk/arch/sparc64/mm/init.c index 09cb7fccc03a..a8e8802eed4d 100644 --- a/trunk/arch/sparc64/mm/init.c +++ b/trunk/arch/sparc64/mm/init.c @@ -176,9 +176,9 @@ unsigned long sparc64_kern_sec_context __read_mostly; int bigkernel = 0; -kmem_cache_t *pgtable_cache __read_mostly; +struct kmem_cache *pgtable_cache __read_mostly; -static void zero_ctor(void *addr, kmem_cache_t *cache, unsigned long flags) +static void zero_ctor(void *addr, struct kmem_cache *cache, unsigned long flags) { clear_page(addr); } diff --git a/trunk/arch/sparc64/mm/tsb.c b/trunk/arch/sparc64/mm/tsb.c index beaa02810f0e..236d02f41a01 100644 --- a/trunk/arch/sparc64/mm/tsb.c +++ b/trunk/arch/sparc64/mm/tsb.c @@ -239,7 +239,7 @@ static void setup_tsb_params(struct mm_struct *mm, unsigned long tsb_idx, unsign } } -static kmem_cache_t *tsb_caches[8] __read_mostly; +static struct kmem_cache *tsb_caches[8] __read_mostly; static const char *tsb_cache_names[8] = { "tsb_8KB", diff --git a/trunk/arch/sparc64/solaris/fs.c b/trunk/arch/sparc64/solaris/fs.c index 12a940cc791f..61be597bf430 100644 --- a/trunk/arch/sparc64/solaris/fs.c +++ b/trunk/arch/sparc64/solaris/fs.c @@ -449,7 +449,7 @@ asmlinkage int solaris_fstatvfs(unsigned int fd, u32 buf) error = -EBADF; file = fget(fd); if (file) { - error = report_statvfs(file->f_vfsmnt, file->f_dentry->d_inode, buf); + error = report_statvfs(file->f_path.mnt, file->f_path.dentry->d_inode, buf); fput(file); } @@ -481,7 +481,7 @@ asmlinkage int solaris_fstatvfs64(unsigned int fd, u32 buf) file = fget(fd); if (file) { lock_kernel(); - error = report_statvfs64(file->f_vfsmnt, file->f_dentry->d_inode, buf); + error = report_statvfs64(file->f_path.mnt, file->f_path.dentry->d_inode, buf); unlock_kernel(); fput(file); } diff --git a/trunk/arch/sparc64/solaris/ioctl.c b/trunk/arch/sparc64/solaris/ioctl.c index be0a054e3ed6..330743c5b3d8 100644 --- a/trunk/arch/sparc64/solaris/ioctl.c +++ b/trunk/arch/sparc64/solaris/ioctl.c @@ -299,8 +299,8 @@ static inline int solaris_sockmod(unsigned int fd, unsigned int cmd, u32 arg) rcu_read_lock(); fdt = files_fdtable(current->files); if (! fdt->fd[fd] || - ! fdt->fd[fd]->f_dentry || - ! (ino = fdt->fd[fd]->f_dentry->d_inode) || + ! fdt->fd[fd]->f_path.dentry || + ! (ino = fdt->fd[fd]->f_path.dentry->d_inode) || ! S_ISSOCK(ino->i_mode)) { rcu_read_unlock(); return TBADF; @@ -480,7 +480,7 @@ static inline int solaris_S(struct file *filp, unsigned int fd, unsigned int cmd struct sol_socket_struct *sock; struct module_info *mi; - ino = filp->f_dentry->d_inode; + ino = filp->f_path.dentry->d_inode; if (!S_ISSOCK(ino->i_mode)) return -EBADF; sock = filp->private_data; diff --git a/trunk/arch/sparc64/solaris/misc.c b/trunk/arch/sparc64/solaris/misc.c index 9ed997982f8d..bca16e8c95c3 100644 --- a/trunk/arch/sparc64/solaris/misc.c +++ b/trunk/arch/sparc64/solaris/misc.c @@ -77,7 +77,7 @@ static u32 do_solaris_mmap(u32 addr, u32 len, u32 prot, u32 flags, u32 fd, u64 o if (!file) goto out; else { - struct inode * inode = file->f_dentry->d_inode; + struct inode * inode = file->f_path.dentry->d_inode; if(imajor(inode) == MEM_MAJOR && iminor(inode) == 5) { flags |= MAP_ANONYMOUS; @@ -423,9 +423,7 @@ asmlinkage int solaris_procids(int cmd, s32 pid, s32 pgid) Solaris setpgrp and setsid? */ ret = sys_setpgid(0, 0); if (ret) return ret; - mutex_lock(&tty_mutex); - current->signal->tty = NULL; - mutex_unlock(&tty_mutex); + proc_clear_tty(current); return process_group(current); } case 2: /* getsid */ diff --git a/trunk/arch/sparc64/solaris/socksys.c b/trunk/arch/sparc64/solaris/socksys.c index 7c90e41fd3be..89a4757f192f 100644 --- a/trunk/arch/sparc64/solaris/socksys.c +++ b/trunk/arch/sparc64/solaris/socksys.c @@ -96,13 +96,13 @@ static int socksys_open(struct inode * inode, struct file * filp) * No shit. WTF is it supposed to do, anyway? * * Try instead: - * d_delete(filp->f_dentry), then d_instantiate with sock inode + * d_delete(filp->f_path.dentry), then d_instantiate with sock inode */ - dentry = filp->f_dentry; - filp->f_dentry = dget(fcheck(fd)->f_dentry); - filp->f_dentry->d_inode->i_rdev = inode->i_rdev; - filp->f_dentry->d_inode->i_flock = inode->i_flock; - SOCKET_I(filp->f_dentry->d_inode)->file = filp; + dentry = filp->f_path.dentry; + filp->f_path.dentry = dget(fcheck(fd)->f_path.dentry); + filp->f_path.dentry->d_inode->i_rdev = inode->i_rdev; + filp->f_path.dentry->d_inode->i_flock = inode->i_flock; + SOCKET_I(filp->f_path.dentry->d_inode)->file = filp; filp->f_op = &socksys_file_ops; sock = (struct sol_socket_struct*) mykmalloc(sizeof(struct sol_socket_struct), GFP_KERNEL); @@ -148,7 +148,7 @@ static unsigned int socksys_poll(struct file * filp, poll_table * wait) struct inode *ino; unsigned int mask = 0; - ino=filp->f_dentry->d_inode; + ino=filp->f_path.dentry->d_inode; if (ino && S_ISSOCK(ino->i_mode)) { struct sol_socket_struct *sock; sock = (struct sol_socket_struct*)filp->private_data; diff --git a/trunk/arch/sparc64/solaris/timod.c b/trunk/arch/sparc64/solaris/timod.c index b84e5456b025..a9d32ceabf26 100644 --- a/trunk/arch/sparc64/solaris/timod.c +++ b/trunk/arch/sparc64/solaris/timod.c @@ -147,7 +147,7 @@ static void timod_wake_socket(unsigned int fd) SOLD("wakeing socket"); fdt = files_fdtable(current->files); - sock = SOCKET_I(fdt->fd[fd]->f_dentry->d_inode); + sock = SOCKET_I(fdt->fd[fd]->f_path.dentry->d_inode); wake_up_interruptible(&sock->wait); read_lock(&sock->sk->sk_callback_lock); if (sock->fasync_list && !test_bit(SOCK_ASYNC_WAITDATA, &sock->flags)) @@ -361,7 +361,7 @@ int timod_putmsg(unsigned int fd, char __user *ctl_buf, int ctl_len, fdt = files_fdtable(current->files); filp = fdt->fd[fd]; - ino = filp->f_dentry->d_inode; + ino = filp->f_path.dentry->d_inode; sock = (struct sol_socket_struct *)filp->private_data; SOLD("entry"); if (get_user(ret, (int __user *)A(ctl_buf))) @@ -644,7 +644,7 @@ int timod_getmsg(unsigned int fd, char __user *ctl_buf, int ctl_maxlen, s32 __us SOLDD(("%u %p %d %p %p %d %p %d\n", fd, ctl_buf, ctl_maxlen, ctl_len, data_buf, data_maxlen, data_len, *flags_p)); fdt = files_fdtable(current->files); filp = fdt->fd[fd]; - ino = filp->f_dentry->d_inode; + ino = filp->f_path.dentry->d_inode; sock = (struct sol_socket_struct *)filp->private_data; SOLDD(("%p %p\n", sock->pfirst, sock->pfirst ? sock->pfirst->next : NULL)); if ( ctl_maxlen > 0 && !sock->pfirst && SOCKET_I(ino)->type == SOCK_STREAM @@ -865,7 +865,7 @@ asmlinkage int solaris_getmsg(unsigned int fd, u32 arg1, u32 arg2, u32 arg3) filp = fdt->fd[fd]; if(!filp) goto out; - ino = filp->f_dentry->d_inode; + ino = filp->f_path.dentry->d_inode; if (!ino || !S_ISSOCK(ino->i_mode)) goto out; @@ -933,7 +933,7 @@ asmlinkage int solaris_putmsg(unsigned int fd, u32 arg1, u32 arg2, u32 arg3) filp = fdt->fd[fd]; if(!filp) goto out; - ino = filp->f_dentry->d_inode; + ino = filp->f_path.dentry->d_inode; if (!ino) goto out; if (!S_ISSOCK(ino->i_mode) && diff --git a/trunk/arch/um/Kconfig b/trunk/arch/um/Kconfig index 5ac1f2963ae3..d32a80e6668c 100644 --- a/trunk/arch/um/Kconfig +++ b/trunk/arch/um/Kconfig @@ -47,6 +47,11 @@ config GENERIC_CALIBRATE_DELAY bool default y +config GENERIC_BUG + bool + default y + depends on BUG + # Used in kernel/irq/manage.c and include/linux/irq.h config IRQ_RELEASE_METHOD bool diff --git a/trunk/arch/um/drivers/chan_kern.c b/trunk/arch/um/drivers/chan_kern.c index 3576b3cc505e..7d4190e55654 100644 --- a/trunk/arch/um/drivers/chan_kern.c +++ b/trunk/arch/um/drivers/chan_kern.c @@ -638,7 +638,7 @@ int chan_out_fd(struct list_head *chans) return -1; } -void chan_interrupt(struct list_head *chans, struct work_struct *task, +void chan_interrupt(struct list_head *chans, struct delayed_work *task, struct tty_struct *tty, int irq) { struct list_head *ele, *next; diff --git a/trunk/arch/um/drivers/daemon_kern.c b/trunk/arch/um/drivers/daemon_kern.c index 824386974f88..9c2e7a758f21 100644 --- a/trunk/arch/um/drivers/daemon_kern.c +++ b/trunk/arch/um/drivers/daemon_kern.c @@ -98,4 +98,4 @@ static int register_daemon(void) return 0; } -__initcall(register_daemon); +late_initcall(register_daemon); diff --git a/trunk/arch/um/drivers/line.c b/trunk/arch/um/drivers/line.c index 426633e5d6e3..83301e1ef67c 100644 --- a/trunk/arch/um/drivers/line.c +++ b/trunk/arch/um/drivers/line.c @@ -31,9 +31,9 @@ static irqreturn_t line_interrupt(int irq, void *data) return IRQ_HANDLED; } -static void line_timer_cb(void *arg) +static void line_timer_cb(struct work_struct *work) { - struct line *line = arg; + struct line *line = container_of(work, struct line, task.work); if(!line->throttled) chan_interrupt(&line->chan_list, &line->task, line->tty, @@ -246,7 +246,7 @@ int line_write(struct tty_struct *tty, const unsigned char *buf, int len) return ret; } -void line_set_termios(struct tty_struct *tty, struct termios * old) +void line_set_termios(struct tty_struct *tty, struct ktermios * old) { /* nothing */ } @@ -443,7 +443,7 @@ int line_open(struct line *lines, struct tty_struct *tty) * is registered. */ enable_chan(line); - INIT_WORK(&line->task, line_timer_cb, line); + INIT_DELAYED_WORK(&line->task, line_timer_cb); if(!line->sigio){ chan_enable_winch(&line->chan_list, tty); diff --git a/trunk/arch/um/drivers/mcast_kern.c b/trunk/arch/um/drivers/mcast_kern.c index c090fbd464e7..52ccb7b53cd2 100644 --- a/trunk/arch/um/drivers/mcast_kern.c +++ b/trunk/arch/um/drivers/mcast_kern.c @@ -127,4 +127,4 @@ static int register_mcast(void) return 0; } -__initcall(register_mcast); +late_initcall(register_mcast); diff --git a/trunk/arch/um/drivers/mconsole_kern.c b/trunk/arch/um/drivers/mconsole_kern.c index 7b172160fe04..96f0189327af 100644 --- a/trunk/arch/um/drivers/mconsole_kern.c +++ b/trunk/arch/um/drivers/mconsole_kern.c @@ -56,7 +56,7 @@ static struct notifier_block reboot_notifier = { static LIST_HEAD(mc_requests); -static void mc_work_proc(void *unused) +static void mc_work_proc(struct work_struct *unused) { struct mconsole_entry *req; unsigned long flags; @@ -72,7 +72,7 @@ static void mc_work_proc(void *unused) } } -static DECLARE_WORK(mconsole_work, mc_work_proc, NULL); +static DECLARE_WORK(mconsole_work, mc_work_proc); static irqreturn_t mconsole_interrupt(int irq, void *dev_id) { diff --git a/trunk/arch/um/drivers/net_kern.c b/trunk/arch/um/drivers/net_kern.c index ec9eb8bd9432..286bc0b3207f 100644 --- a/trunk/arch/um/drivers/net_kern.c +++ b/trunk/arch/um/drivers/net_kern.c @@ -99,6 +99,7 @@ irqreturn_t uml_net_interrupt(int irq, void *dev_id) * same device, since it tests for (dev->flags & IFF_UP). So * there's no harm in delaying the device shutdown. */ schedule_work(&close_work); +#error this is not permitted - close_work will go out of scope goto out; } reactivate_fd(lp->fd, UM_ETH_IRQ); diff --git a/trunk/arch/um/drivers/pcap_kern.c b/trunk/arch/um/drivers/pcap_kern.c index 6e1ef8558283..e67362acf0e7 100644 --- a/trunk/arch/um/drivers/pcap_kern.c +++ b/trunk/arch/um/drivers/pcap_kern.c @@ -109,4 +109,4 @@ static int register_pcap(void) return 0; } -__initcall(register_pcap); +late_initcall(register_pcap); diff --git a/trunk/arch/um/drivers/port_kern.c b/trunk/arch/um/drivers/port_kern.c index ce9f3733f73e..6dfe632f1c14 100644 --- a/trunk/arch/um/drivers/port_kern.c +++ b/trunk/arch/um/drivers/port_kern.c @@ -132,7 +132,7 @@ static int port_accept(struct port_list *port) DECLARE_MUTEX(ports_sem); struct list_head ports = LIST_HEAD_INIT(ports); -void port_work_proc(void *unused) +void port_work_proc(struct work_struct *unused) { struct port_list *port; struct list_head *ele; @@ -150,7 +150,7 @@ void port_work_proc(void *unused) local_irq_restore(flags); } -DECLARE_WORK(port_work, port_work_proc, NULL); +DECLARE_WORK(port_work, port_work_proc); static irqreturn_t port_interrupt(int irq, void *data) { diff --git a/trunk/arch/um/drivers/slip_kern.c b/trunk/arch/um/drivers/slip_kern.c index 788da5439a2d..25634bd1f585 100644 --- a/trunk/arch/um/drivers/slip_kern.c +++ b/trunk/arch/um/drivers/slip_kern.c @@ -95,4 +95,4 @@ static int register_slip(void) return 0; } -__initcall(register_slip); +late_initcall(register_slip); diff --git a/trunk/arch/um/drivers/slirp_kern.c b/trunk/arch/um/drivers/slirp_kern.c index ae322e1c8a87..b3ed8fb874ab 100644 --- a/trunk/arch/um/drivers/slirp_kern.c +++ b/trunk/arch/um/drivers/slirp_kern.c @@ -119,4 +119,4 @@ static int register_slirp(void) return 0; } -__initcall(register_slirp); +late_initcall(register_slirp); diff --git a/trunk/arch/um/include/chan_kern.h b/trunk/arch/um/include/chan_kern.h index 572d286ed2c6..9003a343e148 100644 --- a/trunk/arch/um/include/chan_kern.h +++ b/trunk/arch/um/include/chan_kern.h @@ -27,7 +27,7 @@ struct chan { void *data; }; -extern void chan_interrupt(struct list_head *chans, struct work_struct *task, +extern void chan_interrupt(struct list_head *chans, struct delayed_work *task, struct tty_struct *tty, int irq); extern int parse_chan_pair(char *str, struct line *line, int device, const struct chan_opts *opts); diff --git a/trunk/arch/um/include/line.h b/trunk/arch/um/include/line.h index 7be24811bb30..5f232ae89fbb 100644 --- a/trunk/arch/um/include/line.h +++ b/trunk/arch/um/include/line.h @@ -51,7 +51,7 @@ struct line { char *tail; int sigio; - struct work_struct task; + struct delayed_work task; const struct line_driver *driver; int have_irq; }; @@ -76,7 +76,7 @@ extern int line_setup(struct line *lines, unsigned int sizeof_lines, extern int line_write(struct tty_struct *tty, const unsigned char *buf, int len); extern void line_put_char(struct tty_struct *tty, unsigned char ch); -extern void line_set_termios(struct tty_struct *tty, struct termios * old); +extern void line_set_termios(struct tty_struct *tty, struct ktermios * old); extern int line_chars_in_buffer(struct tty_struct *tty); extern void line_flush_buffer(struct tty_struct *tty); extern void line_flush_chars(struct tty_struct *tty); diff --git a/trunk/arch/um/include/sysdep-i386/ptrace.h b/trunk/arch/um/include/sysdep-i386/ptrace.h index 6670cc992ecb..52b398bcafcf 100644 --- a/trunk/arch/um/include/sysdep-i386/ptrace.h +++ b/trunk/arch/um/include/sysdep-i386/ptrace.h @@ -75,7 +75,7 @@ union uml_pt_regs { #endif #ifdef UML_CONFIG_MODE_SKAS struct skas_regs { - unsigned long regs[HOST_FRAME_SIZE]; + unsigned long regs[MAX_REG_NR]; unsigned long fp[HOST_FP_SIZE]; unsigned long xfp[HOST_XFP_SIZE]; struct faultinfo faultinfo; diff --git a/trunk/arch/um/include/sysdep-i386/stub.h b/trunk/arch/um/include/sysdep-i386/stub.h index b492b12b4a10..4fffae75ba53 100644 --- a/trunk/arch/um/include/sysdep-i386/stub.h +++ b/trunk/arch/um/include/sysdep-i386/stub.h @@ -9,6 +9,7 @@ #include #include #include +#include #include "stub-data.h" #include "kern_constants.h" #include "uml-config.h" diff --git a/trunk/arch/um/include/sysdep-x86_64/ptrace.h b/trunk/arch/um/include/sysdep-x86_64/ptrace.h index 617bb9efc934..66cb400c2c92 100644 --- a/trunk/arch/um/include/sysdep-x86_64/ptrace.h +++ b/trunk/arch/um/include/sysdep-x86_64/ptrace.h @@ -108,7 +108,7 @@ union uml_pt_regs { * file size, while i386 uses FRAME_SIZE. Therefore, we need * to use UM_FRAME_SIZE here instead of HOST_FRAME_SIZE. */ - unsigned long regs[UM_FRAME_SIZE]; + unsigned long regs[MAX_REG_NR]; unsigned long fp[HOST_FP_SIZE]; struct faultinfo faultinfo; long syscall; diff --git a/trunk/arch/um/kernel/exec.c b/trunk/arch/um/kernel/exec.c index 0561c43b4685..8d56ec6cca79 100644 --- a/trunk/arch/um/kernel/exec.c +++ b/trunk/arch/um/kernel/exec.c @@ -39,12 +39,13 @@ static long execve1(char *file, char __user * __user *argv, char __user *__user *env) { long error; + struct tty_struct *tty; #ifdef CONFIG_TTY_LOG mutex_lock(&tty_mutex); - task_lock(current); /* FIXME: is this needed ? */ - log_exec(argv, current->signal->tty); - task_unlock(current); + tty = get_current_tty(); + if (tty) + log_exec(argv, tty); mutex_unlock(&tty_mutex); #endif error = do_execve(file, argv, env, ¤t->thread.regs); diff --git a/trunk/arch/um/os-Linux/drivers/ethertap_kern.c b/trunk/arch/um/os-Linux/drivers/ethertap_kern.c index 16385e2ada85..70541821775f 100644 --- a/trunk/arch/um/os-Linux/drivers/ethertap_kern.c +++ b/trunk/arch/um/os-Linux/drivers/ethertap_kern.c @@ -105,4 +105,4 @@ static int register_ethertap(void) return 0; } -__initcall(register_ethertap); +late_initcall(register_ethertap); diff --git a/trunk/arch/um/os-Linux/drivers/tuntap_kern.c b/trunk/arch/um/os-Linux/drivers/tuntap_kern.c index 0edbac63c527..76570a2c25c3 100644 --- a/trunk/arch/um/os-Linux/drivers/tuntap_kern.c +++ b/trunk/arch/um/os-Linux/drivers/tuntap_kern.c @@ -90,4 +90,4 @@ static int register_tuntap(void) return 0; } -__initcall(register_tuntap); +late_initcall(register_tuntap); diff --git a/trunk/arch/um/sys-i386/Makefile b/trunk/arch/um/sys-i386/Makefile index 0e32adf03be1..098720be019a 100644 --- a/trunk/arch/um/sys-i386/Makefile +++ b/trunk/arch/um/sys-i386/Makefile @@ -1,4 +1,4 @@ -obj-y = bugs.o checksum.o delay.o fault.o ksyms.o ldt.o ptrace.o \ +obj-y = bug.o bugs.o checksum.o delay.o fault.o ksyms.o ldt.o ptrace.o \ ptrace_user.o setjmp.o signal.o sigcontext.o syscalls.o sysrq.o \ sys_call_table.o tls.o diff --git a/trunk/arch/um/sys-i386/bug.c b/trunk/arch/um/sys-i386/bug.c new file mode 100644 index 000000000000..200c8ba2879b --- /dev/null +++ b/trunk/arch/um/sys-i386/bug.c @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2006 Jeff Dike (jdike@addtoit.com) + * Licensed under the GPL V2 + */ + +#include + +/* Mostly copied from i386/x86_86 - eliminated the eip < PAGE_OFFSET because + * that's not relevent in skas mode. + */ + +int is_valid_bugaddr(unsigned long eip) +{ + unsigned short ud2; + + if (probe_kernel_address((unsigned short __user *)eip, ud2)) + return 0; + + return ud2 == 0x0b0f; +} diff --git a/trunk/arch/um/sys-i386/ldt.c b/trunk/arch/um/sys-i386/ldt.c index e299ee5a753d..49057d8bc668 100644 --- a/trunk/arch/um/sys-i386/ldt.c +++ b/trunk/arch/um/sys-i386/ldt.c @@ -3,7 +3,6 @@ * Licensed under the GPL */ -#include "linux/stddef.h" #include "linux/sched.h" #include "linux/slab.h" #include "linux/types.h" diff --git a/trunk/arch/um/sys-i386/ptrace_user.c b/trunk/arch/um/sys-i386/ptrace_user.c index 5f3cc6685820..01212c88fcc4 100644 --- a/trunk/arch/um/sys-i386/ptrace_user.c +++ b/trunk/arch/um/sys-i386/ptrace_user.c @@ -4,9 +4,9 @@ */ #include +#include #include #include -#include #include "ptrace_user.h" /* Grr, asm/user.h includes asm/ptrace.h, so has to follow ptrace_user.h */ #include diff --git a/trunk/arch/um/sys-i386/user-offsets.c b/trunk/arch/um/sys-i386/user-offsets.c index 6f4ef2b7fa4a..447306b20aea 100644 --- a/trunk/arch/um/sys-i386/user-offsets.c +++ b/trunk/arch/um/sys-i386/user-offsets.c @@ -2,7 +2,7 @@ #include #include #include -#include +#include #include #define DEFINE(sym, val) \ diff --git a/trunk/arch/um/sys-x86_64/Makefile b/trunk/arch/um/sys-x86_64/Makefile index f41768b8e25e..4d9e5efa6fb9 100644 --- a/trunk/arch/um/sys-x86_64/Makefile +++ b/trunk/arch/um/sys-x86_64/Makefile @@ -4,7 +4,7 @@ # Licensed under the GPL # -obj-y = bugs.o delay.o fault.o ldt.o mem.o ptrace.o ptrace_user.o \ +obj-y = bug.o bugs.o delay.o fault.o ldt.o mem.o ptrace.o ptrace_user.o \ setjmp.o sigcontext.o signal.o syscalls.o syscall_table.o sysrq.o \ ksyms.o tls.o diff --git a/trunk/arch/um/sys-x86_64/bug.c b/trunk/arch/um/sys-x86_64/bug.c new file mode 100644 index 000000000000..200c8ba2879b --- /dev/null +++ b/trunk/arch/um/sys-x86_64/bug.c @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2006 Jeff Dike (jdike@addtoit.com) + * Licensed under the GPL V2 + */ + +#include + +/* Mostly copied from i386/x86_86 - eliminated the eip < PAGE_OFFSET because + * that's not relevent in skas mode. + */ + +int is_valid_bugaddr(unsigned long eip) +{ + unsigned short ud2; + + if (probe_kernel_address((unsigned short __user *)eip, ud2)) + return 0; + + return ud2 == 0x0b0f; +} diff --git a/trunk/arch/v850/Kconfig b/trunk/arch/v850/Kconfig index 37ec644603ab..bcf825875d17 100644 --- a/trunk/arch/v850/Kconfig +++ b/trunk/arch/v850/Kconfig @@ -38,6 +38,14 @@ config TIME_LOW_RES bool default y +config ARCH_HAS_ILOG2_U32 + bool + default n + +config ARCH_HAS_ILOG2_U64 + bool + default n + # Turn off some random 386 crap that can affect device config config ISA bool diff --git a/trunk/arch/v850/kernel/vmlinux.lds.S b/trunk/arch/v850/kernel/vmlinux.lds.S index 88d087f527c9..3a5fd07fe064 100644 --- a/trunk/arch/v850/kernel/vmlinux.lds.S +++ b/trunk/arch/v850/kernel/vmlinux.lds.S @@ -90,6 +90,7 @@ /* Kernel text segment, and some constant data areas. */ #define TEXT_CONTENTS \ + _text = .; \ __stext = . ; \ *(.text) \ SCHED_TEXT \ diff --git a/trunk/arch/x86_64/Kconfig b/trunk/arch/x86_64/Kconfig index 010d2265f1cf..3ac581d17202 100644 --- a/trunk/arch/x86_64/Kconfig +++ b/trunk/arch/x86_64/Kconfig @@ -96,6 +96,19 @@ config AUDIT_ARCH bool default y +config GENERIC_BUG + bool + default y + depends on BUG + +config ARCH_HAS_ILOG2_U32 + bool + default n + +config ARCH_HAS_ILOG2_U64 + bool + default n + source "init/Kconfig" @@ -122,7 +135,7 @@ endchoice choice prompt "Processor family" - default MK8 + default GENERIC_CPU config MK8 bool "AMD-Opteron/Athlon64" @@ -130,16 +143,31 @@ config MK8 Optimize for AMD Opteron/Athlon64/Hammer/K8 CPUs. config MPSC - bool "Intel EM64T" + bool "Intel P4 / older Netburst based Xeon" help - Optimize for Intel Pentium 4 and Xeon CPUs with Intel - Extended Memory 64 Technology(EM64T). For details see + Optimize for Intel Pentium 4 and older Nocona/Dempsey Xeon CPUs + with Intel Extended Memory 64 Technology(EM64T). For details see . + Note the the latest Xeons (Xeon 51xx and 53xx) are not based on the + Netburst core and shouldn't use this option. You can distingush them + using the cpu family field + in /proc/cpuinfo. Family 15 is a older Xeon, Family 6 a newer one + (this rule only applies to system that support EM64T) + +config MCORE2 + bool "Intel Core2 / newer Xeon" + help + Optimize for Intel Core2 and newer Xeons (51xx) + You can distingush the newer Xeons from the older ones using + the cpu family field in /proc/cpuinfo. 15 is a older Xeon + (use CONFIG_MPSC then), 6 is a newer one. This rule only + applies to CPUs that support EM64T. config GENERIC_CPU bool "Generic-x86-64" help Generic x86-64 CPU. + Run equally well on all x86-64 CPUs. endchoice @@ -149,12 +177,12 @@ endchoice config X86_L1_CACHE_BYTES int default "128" if GENERIC_CPU || MPSC - default "64" if MK8 + default "64" if MK8 || MCORE2 config X86_L1_CACHE_SHIFT int default "7" if GENERIC_CPU || MPSC - default "6" if MK8 + default "6" if MK8 || MCORE2 config X86_INTERNODE_CACHE_BYTES int @@ -344,11 +372,6 @@ config ARCH_DISCONTIGMEM_ENABLE depends on NUMA default y - -config ARCH_DISCONTIGMEM_ENABLE - def_bool y - depends on NUMA - config ARCH_DISCONTIGMEM_DEFAULT def_bool y depends on NUMA @@ -455,6 +478,17 @@ config CALGARY_IOMMU Normally the kernel will make the right choice by itself. If unsure, say Y. +config CALGARY_IOMMU_ENABLED_BY_DEFAULT + bool "Should Calgary be enabled by default?" + default y + depends on CALGARY_IOMMU + help + Should Calgary be enabled by default? if you choose 'y', Calgary + will be used (if it exists). If you choose 'n', Calgary will not be + used even if it exists. If you choose 'n' and would like to use + Calgary anyway, pass 'iommu=calgary' on the kernel command line. + If unsure, say Y. + # need this always selected by IOMMU for the VIA workaround config SWIOTLB bool diff --git a/trunk/arch/x86_64/Makefile b/trunk/arch/x86_64/Makefile index 6e38d4daeed7..b471b8550d03 100644 --- a/trunk/arch/x86_64/Makefile +++ b/trunk/arch/x86_64/Makefile @@ -30,6 +30,10 @@ cflags-y := cflags-kernel-y := cflags-$(CONFIG_MK8) += $(call cc-option,-march=k8) cflags-$(CONFIG_MPSC) += $(call cc-option,-march=nocona) +# gcc doesn't support -march=core2 yet as of gcc 4.3, but I hope it +# will eventually. Use -mtune=generic as fallback +cflags-$(CONFIG_MCORE2) += \ + $(call cc-option,-march=core2,$(call cc-option,-mtune=generic)) cflags-$(CONFIG_GENERIC_CPU) += $(call cc-option,-mtune=generic) cflags-y += -m64 diff --git a/trunk/arch/x86_64/defconfig b/trunk/arch/x86_64/defconfig index 0f5d44e86be5..96f226cfb339 100644 --- a/trunk/arch/x86_64/defconfig +++ b/trunk/arch/x86_64/defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.19-rc2-git4 -# Sat Oct 21 03:38:52 2006 +# Linux kernel version: 2.6.19-git7 +# Wed Dec 6 23:50:47 2006 # CONFIG_X86_64=y CONFIG_64BIT=y @@ -47,13 +47,14 @@ CONFIG_POSIX_MQUEUE=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y # CONFIG_CPUSETS is not set +CONFIG_SYSFS_DEPRECATED=y # CONFIG_RELAY is not set CONFIG_INITRAMFS_SOURCE="" CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_SYSCTL=y # CONFIG_EMBEDDED is not set CONFIG_UID16=y -# CONFIG_SYSCTL_SYSCALL is not set +CONFIG_SYSCTL_SYSCALL=y CONFIG_KALLSYMS=y CONFIG_KALLSYMS_ALL=y # CONFIG_KALLSYMS_EXTRA_PASS is not set @@ -87,9 +88,7 @@ CONFIG_STOP_MACHINE=y # Block layer # CONFIG_BLOCK=y -CONFIG_LBD=y # CONFIG_BLK_DEV_IO_TRACE is not set -# CONFIG_LSF is not set # # IO Schedulers @@ -111,10 +110,11 @@ CONFIG_X86_PC=y # CONFIG_X86_VSMP is not set # CONFIG_MK8 is not set # CONFIG_MPSC is not set -CONFIG_GENERIC_CPU=y -CONFIG_X86_L1_CACHE_BYTES=128 -CONFIG_X86_L1_CACHE_SHIFT=7 -CONFIG_X86_INTERNODE_CACHE_BYTES=128 +CONFIG_MCORE2=y +# CONFIG_GENERIC_CPU is not set +CONFIG_X86_L1_CACHE_BYTES=64 +CONFIG_X86_L1_CACHE_SHIFT=6 +CONFIG_X86_INTERNODE_CACHE_BYTES=64 CONFIG_X86_TSC=y CONFIG_X86_GOOD_APIC=y # CONFIG_MICROCODE is not set @@ -322,6 +322,7 @@ CONFIG_INET_TCP_DIAG=y # CONFIG_TCP_CONG_ADVANCED is not set CONFIG_TCP_CONG_CUBIC=y CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set CONFIG_IPV6=y # CONFIG_IPV6_PRIVACY is not set # CONFIG_IPV6_ROUTER_PREF is not set @@ -624,6 +625,7 @@ CONFIG_SATA_INTEL_COMBINED=y # CONFIG_PATA_IT821X is not set # CONFIG_PATA_JMICRON is not set # CONFIG_PATA_TRIFLEX is not set +# CONFIG_PATA_MARVELL is not set # CONFIG_PATA_MPIIX is not set # CONFIG_PATA_OLDPIIX is not set # CONFIG_PATA_NETCELL is not set @@ -795,6 +797,7 @@ CONFIG_BNX2=y CONFIG_S2IO=m # CONFIG_S2IO_NAPI is not set # CONFIG_MYRI10GE is not set +# CONFIG_NETXEN_NIC is not set # # Token Ring devices @@ -927,10 +930,6 @@ CONFIG_RTC=y # CONFIG_DTLK is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set - -# -# Ftape, the floppy tape device driver -# CONFIG_AGP=y CONFIG_AGP_AMD64=y CONFIG_AGP_INTEL=y @@ -1135,6 +1134,7 @@ CONFIG_USB_DEVICEFS=y # CONFIG_USB_BANDWIDTH is not set # CONFIG_USB_DYNAMIC_MINORS is not set # CONFIG_USB_SUSPEND is not set +# CONFIG_USB_MULTITHREAD_PROBE is not set # CONFIG_USB_OTG is not set # @@ -1212,6 +1212,7 @@ CONFIG_USB_HIDINPUT=y # CONFIG_USB_KAWETH is not set # CONFIG_USB_PEGASUS is not set # CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET_MII is not set # CONFIG_USB_USBNET is not set CONFIG_USB_MON=y diff --git a/trunk/arch/x86_64/ia32/ia32_aout.c b/trunk/arch/x86_64/ia32/ia32_aout.c index 396d3c100011..be87df506f39 100644 --- a/trunk/arch/x86_64/ia32/ia32_aout.c +++ b/trunk/arch/x86_64/ia32/ia32_aout.c @@ -272,7 +272,7 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs) if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != OMAGIC && N_MAGIC(ex) != QMAGIC && N_MAGIC(ex) != NMAGIC) || N_TRSIZE(ex) || N_DRSIZE(ex) || - i_size_read(bprm->file->f_dentry->d_inode) < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) { + i_size_read(bprm->file->f_path.dentry->d_inode) < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) { return -ENOEXEC; } @@ -357,7 +357,7 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs) { printk(KERN_WARNING "fd_offset is not page aligned. Please convert program: %s\n", - bprm->file->f_dentry->d_name.name); + bprm->file->f_path.dentry->d_name.name); error_time = jiffies; } #endif @@ -440,7 +440,7 @@ static int load_aout_library(struct file *file) int retval; struct exec ex; - inode = file->f_dentry->d_inode; + inode = file->f_path.dentry->d_inode; retval = -ENOEXEC; error = kernel_read(file, 0, (char *) &ex, sizeof(ex)); @@ -471,7 +471,7 @@ static int load_aout_library(struct file *file) { printk(KERN_WARNING "N_TXTOFF is not page aligned. Please convert library: %s\n", - file->f_dentry->d_name.name); + file->f_path.dentry->d_name.name); error_time = jiffies; } #endif diff --git a/trunk/arch/x86_64/ia32/ia32_binfmt.c b/trunk/arch/x86_64/ia32/ia32_binfmt.c index 82ef182de6ae..543ef4f405e9 100644 --- a/trunk/arch/x86_64/ia32/ia32_binfmt.c +++ b/trunk/arch/x86_64/ia32/ia32_binfmt.c @@ -305,8 +305,6 @@ MODULE_AUTHOR("Eric Youngdale, Andi Kleen"); #undef MODULE_DESCRIPTION #undef MODULE_AUTHOR -#define elf_addr_t __u32 - static void elf32_init(struct pt_regs *); #define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1 @@ -351,7 +349,7 @@ int ia32_setup_arg_pages(struct linux_binprm *bprm, unsigned long stack_top, bprm->loader += stack_base; bprm->exec += stack_base; - mpnt = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL); + mpnt = kmem_cache_alloc(vm_area_cachep, GFP_KERNEL); if (!mpnt) return -ENOMEM; diff --git a/trunk/arch/x86_64/ia32/ia32_signal.c b/trunk/arch/x86_64/ia32/ia32_signal.c index 0e0a266d976f..ff499ef2a1ba 100644 --- a/trunk/arch/x86_64/ia32/ia32_signal.c +++ b/trunk/arch/x86_64/ia32/ia32_signal.c @@ -584,6 +584,11 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, regs->rdx = (unsigned long) &frame->info; regs->rcx = (unsigned long) &frame->uc; + /* Make -mregparm=3 work */ + regs->rax = sig; + regs->rdx = (unsigned long) &frame->info; + regs->rcx = (unsigned long) &frame->uc; + asm volatile("movl %0,%%ds" :: "r" (__USER32_DS)); asm volatile("movl %0,%%es" :: "r" (__USER32_DS)); diff --git a/trunk/arch/x86_64/ia32/syscall32.c b/trunk/arch/x86_64/ia32/syscall32.c index 3a01329473ab..3e5ed20cba45 100644 --- a/trunk/arch/x86_64/ia32/syscall32.c +++ b/trunk/arch/x86_64/ia32/syscall32.c @@ -49,7 +49,7 @@ int syscall32_setup_pages(struct linux_binprm *bprm, int exstack) struct mm_struct *mm = current->mm; int ret; - vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL); + vma = kmem_cache_alloc(vm_area_cachep, GFP_KERNEL); if (!vma) return -ENOMEM; diff --git a/trunk/arch/x86_64/kernel/apic.c b/trunk/arch/x86_64/kernel/apic.c index 4d9d5ed942b2..124b2d27b4ac 100644 --- a/trunk/arch/x86_64/kernel/apic.c +++ b/trunk/arch/x86_64/kernel/apic.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -45,6 +46,12 @@ int apic_calibrate_pmtmr __initdata; int disable_apic_timer __initdata; +static struct resource *ioapic_resources; +static struct resource lapic_resource = { + .name = "Local APIC", + .flags = IORESOURCE_MEM | IORESOURCE_BUSY, +}; + /* * cpu_mask that denotes the CPUs that needs timer interrupt coming in as * IPIs in place of local APIC timers @@ -133,7 +140,6 @@ void clear_local_APIC(void) apic_write(APIC_LVTERR, APIC_LVT_MASKED); if (maxlvt >= 4) apic_write(APIC_LVTPC, APIC_LVT_MASKED); - v = GET_APIC_VERSION(apic_read(APIC_LVR)); apic_write(APIC_ESR, 0); apic_read(APIC_ESR); } @@ -452,23 +458,30 @@ static struct { static int lapic_suspend(struct sys_device *dev, pm_message_t state) { unsigned long flags; + int maxlvt; if (!apic_pm_state.active) return 0; + maxlvt = get_maxlvt(); + apic_pm_state.apic_id = apic_read(APIC_ID); apic_pm_state.apic_taskpri = apic_read(APIC_TASKPRI); apic_pm_state.apic_ldr = apic_read(APIC_LDR); apic_pm_state.apic_dfr = apic_read(APIC_DFR); apic_pm_state.apic_spiv = apic_read(APIC_SPIV); apic_pm_state.apic_lvtt = apic_read(APIC_LVTT); - apic_pm_state.apic_lvtpc = apic_read(APIC_LVTPC); + if (maxlvt >= 4) + apic_pm_state.apic_lvtpc = apic_read(APIC_LVTPC); apic_pm_state.apic_lvt0 = apic_read(APIC_LVT0); apic_pm_state.apic_lvt1 = apic_read(APIC_LVT1); apic_pm_state.apic_lvterr = apic_read(APIC_LVTERR); apic_pm_state.apic_tmict = apic_read(APIC_TMICT); apic_pm_state.apic_tdcr = apic_read(APIC_TDCR); - apic_pm_state.apic_thmr = apic_read(APIC_LVTTHMR); +#ifdef CONFIG_X86_MCE_INTEL + if (maxlvt >= 5) + apic_pm_state.apic_thmr = apic_read(APIC_LVTTHMR); +#endif local_irq_save(flags); disable_local_APIC(); local_irq_restore(flags); @@ -479,10 +492,13 @@ static int lapic_resume(struct sys_device *dev) { unsigned int l, h; unsigned long flags; + int maxlvt; if (!apic_pm_state.active) return 0; + maxlvt = get_maxlvt(); + local_irq_save(flags); rdmsr(MSR_IA32_APICBASE, l, h); l &= ~MSR_IA32_APICBASE_BASE; @@ -496,8 +512,12 @@ static int lapic_resume(struct sys_device *dev) apic_write(APIC_SPIV, apic_pm_state.apic_spiv); apic_write(APIC_LVT0, apic_pm_state.apic_lvt0); apic_write(APIC_LVT1, apic_pm_state.apic_lvt1); - apic_write(APIC_LVTTHMR, apic_pm_state.apic_thmr); - apic_write(APIC_LVTPC, apic_pm_state.apic_lvtpc); +#ifdef CONFIG_X86_MCE_INTEL + if (maxlvt >= 5) + apic_write(APIC_LVTTHMR, apic_pm_state.apic_thmr); +#endif + if (maxlvt >= 4) + apic_write(APIC_LVTPC, apic_pm_state.apic_lvtpc); apic_write(APIC_LVTT, apic_pm_state.apic_lvtt); apic_write(APIC_TDCR, apic_pm_state.apic_tdcr); apic_write(APIC_TMICT, apic_pm_state.apic_tmict); @@ -585,6 +605,64 @@ static int __init detect_init_APIC (void) return 0; } +#ifdef CONFIG_X86_IO_APIC +static struct resource * __init ioapic_setup_resources(void) +{ +#define IOAPIC_RESOURCE_NAME_SIZE 11 + unsigned long n; + struct resource *res; + char *mem; + int i; + + if (nr_ioapics <= 0) + return NULL; + + n = IOAPIC_RESOURCE_NAME_SIZE + sizeof(struct resource); + n *= nr_ioapics; + + mem = alloc_bootmem(n); + res = (void *)mem; + + if (mem != NULL) { + memset(mem, 0, n); + mem += sizeof(struct resource) * nr_ioapics; + + for (i = 0; i < nr_ioapics; i++) { + res[i].name = mem; + res[i].flags = IORESOURCE_MEM | IORESOURCE_BUSY; + sprintf(mem, "IOAPIC %u", i); + mem += IOAPIC_RESOURCE_NAME_SIZE; + } + } + + ioapic_resources = res; + + return res; +} + +static int __init ioapic_insert_resources(void) +{ + int i; + struct resource *r = ioapic_resources; + + if (!r) { + printk("IO APIC resources could be not be allocated.\n"); + return -1; + } + + for (i = 0; i < nr_ioapics; i++) { + insert_resource(&iomem_resource, r); + r++; + } + + return 0; +} + +/* Insert the IO APIC resources after PCI initialization has occured to handle + * IO APICS that are mapped in on a BAR in PCI space. */ +late_initcall(ioapic_insert_resources); +#endif + void __init init_apic_mappings(void) { unsigned long apic_phys; @@ -604,6 +682,11 @@ void __init init_apic_mappings(void) apic_mapped = 1; apic_printk(APIC_VERBOSE,"mapped APIC to %16lx (%16lx)\n", APIC_BASE, apic_phys); + /* Put local APIC into the resource map. */ + lapic_resource.start = apic_phys; + lapic_resource.end = lapic_resource.start + PAGE_SIZE - 1; + insert_resource(&iomem_resource, &lapic_resource); + /* * Fetch the APIC ID of the BSP in case we have a * default configuration (or the MP table is broken). @@ -613,7 +696,9 @@ void __init init_apic_mappings(void) { unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0; int i; + struct resource *ioapic_res; + ioapic_res = ioapic_setup_resources(); for (i = 0; i < nr_ioapics; i++) { if (smp_found_config) { ioapic_phys = mp_ioapics[i].mpc_apicaddr; @@ -625,6 +710,12 @@ void __init init_apic_mappings(void) apic_printk(APIC_VERBOSE,"mapped IOAPIC to %016lx (%016lx)\n", __fix_to_virt(idx), ioapic_phys); idx++; + + if (ioapic_res != NULL) { + ioapic_res->start = ioapic_phys; + ioapic_res->end = ioapic_phys + (4 * 1024) - 1; + ioapic_res++; + } } } } @@ -644,10 +735,9 @@ void __init init_apic_mappings(void) static void __setup_APIC_LVTT(unsigned int clocks) { - unsigned int lvtt_value, tmp_value, ver; + unsigned int lvtt_value, tmp_value; int cpu = smp_processor_id(); - ver = GET_APIC_VERSION(apic_read(APIC_LVR)); lvtt_value = APIC_LVT_TIMER_PERIODIC | LOCAL_TIMER_VECTOR; if (cpu_isset(cpu, timer_interrupt_broadcast_ipi_mask)) diff --git a/trunk/arch/x86_64/kernel/crash.c b/trunk/arch/x86_64/kernel/crash.c index 3525f884af82..95a7a2c13131 100644 --- a/trunk/arch/x86_64/kernel/crash.c +++ b/trunk/arch/x86_64/kernel/crash.c @@ -28,71 +28,6 @@ /* This keeps a track of which one is crashing cpu. */ static int crashing_cpu; -static u32 *append_elf_note(u32 *buf, char *name, unsigned type, - void *data, size_t data_len) -{ - struct elf_note note; - - note.n_namesz = strlen(name) + 1; - note.n_descsz = data_len; - note.n_type = type; - memcpy(buf, ¬e, sizeof(note)); - buf += (sizeof(note) +3)/4; - memcpy(buf, name, note.n_namesz); - buf += (note.n_namesz + 3)/4; - memcpy(buf, data, note.n_descsz); - buf += (note.n_descsz + 3)/4; - - return buf; -} - -static void final_note(u32 *buf) -{ - struct elf_note note; - - note.n_namesz = 0; - note.n_descsz = 0; - note.n_type = 0; - memcpy(buf, ¬e, sizeof(note)); -} - -static void crash_save_this_cpu(struct pt_regs *regs, int cpu) -{ - struct elf_prstatus prstatus; - u32 *buf; - - if ((cpu < 0) || (cpu >= NR_CPUS)) - return; - - /* Using ELF notes here is opportunistic. - * I need a well defined structure format - * for the data I pass, and I need tags - * on the data to indicate what information I have - * squirrelled away. ELF notes happen to provide - * all of that, no need to invent something new. - */ - - buf = (u32*)per_cpu_ptr(crash_notes, cpu); - - if (!buf) - return; - - memset(&prstatus, 0, sizeof(prstatus)); - prstatus.pr_pid = current->pid; - elf_core_copy_regs(&prstatus.pr_reg, regs); - buf = append_elf_note(buf, "CORE", NT_PRSTATUS, &prstatus, - sizeof(prstatus)); - final_note(buf); -} - -static void crash_save_self(struct pt_regs *regs) -{ - int cpu; - - cpu = smp_processor_id(); - crash_save_this_cpu(regs, cpu); -} - #ifdef CONFIG_SMP static atomic_t waiting_for_crash_ipi; @@ -117,7 +52,7 @@ static int crash_nmi_callback(struct notifier_block *self, return NOTIFY_STOP; local_irq_disable(); - crash_save_this_cpu(regs, cpu); + crash_save_cpu(regs, cpu); disable_local_APIC(); atomic_dec(&waiting_for_crash_ipi); /* Assume hlt works */ @@ -196,5 +131,5 @@ void machine_crash_shutdown(struct pt_regs *regs) disable_IO_APIC(); - crash_save_self(regs); + crash_save_cpu(regs, smp_processor_id()); } diff --git a/trunk/arch/x86_64/kernel/early-quirks.c b/trunk/arch/x86_64/kernel/early-quirks.c index 68273bff58cc..829698f6d049 100644 --- a/trunk/arch/x86_64/kernel/early-quirks.c +++ b/trunk/arch/x86_64/kernel/early-quirks.c @@ -69,11 +69,18 @@ static void nvidia_bugs(void) static void ati_bugs(void) { - if (timer_over_8254 == 1) { - timer_over_8254 = 0; - printk(KERN_INFO - "ATI board detected. Disabling timer routing over 8254.\n"); - } +} + +static void intel_bugs(void) +{ + u16 device = read_pci_config_16(0, 0, 0, PCI_DEVICE_ID); + +#ifdef CONFIG_SMP + if (device == PCI_DEVICE_ID_INTEL_E7320_MCH || + device == PCI_DEVICE_ID_INTEL_E7520_MCH || + device == PCI_DEVICE_ID_INTEL_E7525_MCH) + quirk_intel_irqbalance(); +#endif } struct chipset { @@ -85,6 +92,7 @@ static struct chipset early_qrk[] = { { PCI_VENDOR_ID_NVIDIA, nvidia_bugs }, { PCI_VENDOR_ID_VIA, via_bugs }, { PCI_VENDOR_ID_ATI, ati_bugs }, + { PCI_VENDOR_ID_INTEL, intel_bugs}, {} }; diff --git a/trunk/arch/x86_64/kernel/entry.S b/trunk/arch/x86_64/kernel/entry.S index 7d401b00d822..601d332c4b79 100644 --- a/trunk/arch/x86_64/kernel/entry.S +++ b/trunk/arch/x86_64/kernel/entry.S @@ -230,7 +230,6 @@ ENTRY(system_call) CFI_REL_OFFSET rip,RIP-ARGOFFSET GET_THREAD_INFO(%rcx) testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),threadinfo_flags(%rcx) - CFI_REMEMBER_STATE jnz tracesys cmpq $__NR_syscall_max,%rax ja badsys @@ -241,7 +240,6 @@ ENTRY(system_call) * Syscall return path ending with SYSRET (fast path) * Has incomplete stack frame and undefined top of stack. */ - .globl ret_from_sys_call ret_from_sys_call: movl $_TIF_ALLWORK_MASK,%edi /* edi: flagmask */ @@ -251,8 +249,8 @@ sysret_check: TRACE_IRQS_OFF movl threadinfo_flags(%rcx),%edx andl %edi,%edx - CFI_REMEMBER_STATE jnz sysret_careful + CFI_REMEMBER_STATE /* * sysretq will re-enable interrupts: */ @@ -265,10 +263,10 @@ sysret_check: swapgs sysretq + CFI_RESTORE_STATE /* Handle reschedules */ /* edx: work, edi: workmask */ sysret_careful: - CFI_RESTORE_STATE bt $TIF_NEED_RESCHED,%edx jnc sysret_signal TRACE_IRQS_ON @@ -306,7 +304,6 @@ badsys: /* Do syscall tracing */ tracesys: - CFI_RESTORE_STATE SAVE_REST movq $-ENOSYS,RAX(%rsp) FIXUP_TOP_OF_STACK %rdi @@ -322,32 +319,13 @@ tracesys: call *sys_call_table(,%rax,8) 1: movq %rax,RAX-ARGOFFSET(%rsp) /* Use IRET because user could have changed frame */ - jmp int_ret_from_sys_call - CFI_ENDPROC -END(system_call) /* * Syscall return path ending with IRET. * Has correct top of stack, but partial stack frame. - */ -ENTRY(int_ret_from_sys_call) - CFI_STARTPROC simple - CFI_SIGNAL_FRAME - CFI_DEF_CFA rsp,SS+8-ARGOFFSET - /*CFI_REL_OFFSET ss,SS-ARGOFFSET*/ - CFI_REL_OFFSET rsp,RSP-ARGOFFSET - /*CFI_REL_OFFSET rflags,EFLAGS-ARGOFFSET*/ - /*CFI_REL_OFFSET cs,CS-ARGOFFSET*/ - CFI_REL_OFFSET rip,RIP-ARGOFFSET - CFI_REL_OFFSET rdx,RDX-ARGOFFSET - CFI_REL_OFFSET rcx,RCX-ARGOFFSET - CFI_REL_OFFSET rax,RAX-ARGOFFSET - CFI_REL_OFFSET rdi,RDI-ARGOFFSET - CFI_REL_OFFSET rsi,RSI-ARGOFFSET - CFI_REL_OFFSET r8,R8-ARGOFFSET - CFI_REL_OFFSET r9,R9-ARGOFFSET - CFI_REL_OFFSET r10,R10-ARGOFFSET - CFI_REL_OFFSET r11,R11-ARGOFFSET + */ + .globl int_ret_from_sys_call +int_ret_from_sys_call: cli TRACE_IRQS_OFF testl $3,CS-ARGOFFSET(%rsp) @@ -394,8 +372,6 @@ int_very_careful: popq %rdi CFI_ADJUST_CFA_OFFSET -8 andl $~(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP),%edi - cli - TRACE_IRQS_OFF jmp int_restore_rest int_signal: @@ -411,7 +387,7 @@ int_restore_rest: TRACE_IRQS_OFF jmp int_with_check CFI_ENDPROC -END(int_ret_from_sys_call) +END(system_call) /* * Certain special system calls that need to save a complete full stack frame. diff --git a/trunk/arch/x86_64/kernel/genapic.c b/trunk/arch/x86_64/kernel/genapic.c index 8e78a75d1866..b007433f96bb 100644 --- a/trunk/arch/x86_64/kernel/genapic.c +++ b/trunk/arch/x86_64/kernel/genapic.c @@ -33,7 +33,7 @@ extern struct genapic apic_flat; extern struct genapic apic_physflat; struct genapic *genapic = &apic_flat; - +struct genapic *genapic_force; /* * Check the APIC IDs in bios_cpu_apicid and choose the APIC mode. @@ -46,6 +46,13 @@ void __init clustered_apic_check(void) u8 cluster_cnt[NUM_APIC_CLUSTERS]; int max_apic = 0; + /* genapic selection can be forced because of certain quirks. + */ + if (genapic_force) { + genapic = genapic_force; + goto print; + } + #if defined(CONFIG_ACPI) /* * Some x86_64 machines use physical APIC mode regardless of how many diff --git a/trunk/arch/x86_64/kernel/head64.c b/trunk/arch/x86_64/kernel/head64.c index 9561eb3c5b5c..cc230b93cd1c 100644 --- a/trunk/arch/x86_64/kernel/head64.c +++ b/trunk/arch/x86_64/kernel/head64.c @@ -57,10 +57,12 @@ void __init x86_64_start_kernel(char * real_mode_data) { int i; - for (i = 0; i < 256; i++) + /* clear bss before set_intr_gate with early_idt_handler */ + clear_bss(); + + for (i = 0; i < IDT_ENTRIES; i++) set_intr_gate(i, early_idt_handler); asm volatile("lidt %0" :: "m" (idt_descr)); - clear_bss(); early_printk("Kernel alive\n"); diff --git a/trunk/arch/x86_64/kernel/i387.c b/trunk/arch/x86_64/kernel/i387.c index 3aa1e9bb781d..1d58c13bc6bc 100644 --- a/trunk/arch/x86_64/kernel/i387.c +++ b/trunk/arch/x86_64/kernel/i387.c @@ -82,11 +82,8 @@ int save_i387(struct _fpstate __user *buf) struct task_struct *tsk = current; int err = 0; - { - extern void bad_user_i387_struct(void); - if (sizeof(struct user_i387_struct) != sizeof(tsk->thread.i387.fxsave)) - bad_user_i387_struct(); - } + BUILD_BUG_ON(sizeof(struct user_i387_struct) != + sizeof(tsk->thread.i387.fxsave)); if ((unsigned long)buf % 16) printk("save_i387: bad fpstate %p\n",buf); diff --git a/trunk/arch/x86_64/kernel/i8259.c b/trunk/arch/x86_64/kernel/i8259.c index c4ef801b765b..d73c79e821f1 100644 --- a/trunk/arch/x86_64/kernel/i8259.c +++ b/trunk/arch/x86_64/kernel/i8259.c @@ -76,7 +76,8 @@ BUILD_16_IRQS(0xc) BUILD_16_IRQS(0xd) BUILD_16_IRQS(0xe) BUILD_16_IRQS(0xf) IRQ(x,8), IRQ(x,9), IRQ(x,a), IRQ(x,b), \ IRQ(x,c), IRQ(x,d), IRQ(x,e), IRQ(x,f) -void (*interrupt[NR_IRQS])(void) = { +/* for the irq vectors */ +static void (*interrupt[NR_VECTORS - FIRST_EXTERNAL_VECTOR])(void) = { IRQLIST_16(0x2), IRQLIST_16(0x3), IRQLIST_16(0x4), IRQLIST_16(0x5), IRQLIST_16(0x6), IRQLIST_16(0x7), IRQLIST_16(0x8), IRQLIST_16(0x9), IRQLIST_16(0xa), IRQLIST_16(0xb), diff --git a/trunk/arch/x86_64/kernel/io_apic.c b/trunk/arch/x86_64/kernel/io_apic.c index c80081a6ba41..2a1dcd5f69c2 100644 --- a/trunk/arch/x86_64/kernel/io_apic.c +++ b/trunk/arch/x86_64/kernel/io_apic.c @@ -55,10 +55,6 @@ int sis_apic_bug; /* not actually supported, dummy for compile */ static int no_timer_check; -static int disable_timer_pin_1 __initdata; - -int timer_over_8254 __initdata = 1; - /* Where if anywhere is the i8259 connect in external int mode */ static struct { int pin, apic; } ioapic_i8259 = { -1, -1 }; @@ -178,14 +174,20 @@ static struct IO_APIC_route_entry ioapic_read_entry(int apic, int pin) * the interrupt, and we need to make sure the entry is fully populated * before that happens. */ -static void ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e) +static void +__ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e) { - unsigned long flags; union entry_union eu; eu.entry = e; - spin_lock_irqsave(&ioapic_lock, flags); io_apic_write(apic, 0x11 + 2*pin, eu.w2); io_apic_write(apic, 0x10 + 2*pin, eu.w1); +} + +static void ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e) +{ + unsigned long flags; + spin_lock_irqsave(&ioapic_lock, flags); + __ioapic_write_entry(apic, pin, e); spin_unlock_irqrestore(&ioapic_lock, flags); } @@ -348,29 +350,6 @@ static int __init disable_ioapic_setup(char *str) } early_param("noapic", disable_ioapic_setup); -/* Actually the next is obsolete, but keep it for paranoid reasons -AK */ -static int __init disable_timer_pin_setup(char *arg) -{ - disable_timer_pin_1 = 1; - return 1; -} -__setup("disable_timer_pin_1", disable_timer_pin_setup); - -static int __init setup_disable_8254_timer(char *s) -{ - timer_over_8254 = -1; - return 1; -} -static int __init setup_enable_8254_timer(char *s) -{ - timer_over_8254 = 2; - return 1; -} - -__setup("disable_8254_timer", setup_disable_8254_timer); -__setup("enable_8254_timer", setup_enable_8254_timer); - - /* * Find the IRQ entry number of a certain pin. */ @@ -750,6 +729,22 @@ static int assign_irq_vector(int irq, cpumask_t mask, cpumask_t *result) return vector; } +static void __clear_irq_vector(int irq) +{ + cpumask_t mask; + int cpu, vector; + + BUG_ON(!irq_vector[irq]); + + vector = irq_vector[irq]; + cpus_and(mask, irq_domain[irq], cpu_online_map); + for_each_cpu_mask(cpu, mask) + per_cpu(vector_irq, cpu)[vector] = -1; + + irq_vector[irq] = 0; + irq_domain[irq] = CPU_MASK_NONE; +} + void __setup_vector_irq(int cpu) { /* Initialize vector_irq on a new cpu */ @@ -794,27 +789,65 @@ static void ioapic_register_intr(int irq, int vector, unsigned long trigger) handle_edge_irq, "edge"); } } - -static void __init setup_IO_APIC_irqs(void) +static void __init setup_IO_APIC_irq(int apic, int pin, int idx, int irq) { struct IO_APIC_route_entry entry; - int apic, pin, idx, irq, first_notcon = 1, vector; + int vector; unsigned long flags; - apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n"); - for (apic = 0; apic < nr_ioapics; apic++) { - for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) { + /* + * add it to the IO-APIC irq-routing table: + */ + memset(&entry,0,sizeof(entry)); - /* - * add it to the IO-APIC irq-routing table: - */ - memset(&entry,0,sizeof(entry)); + entry.delivery_mode = INT_DELIVERY_MODE; + entry.dest_mode = INT_DEST_MODE; + entry.mask = 0; /* enable IRQ */ + entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS); + + entry.trigger = irq_trigger(idx); + entry.polarity = irq_polarity(idx); - entry.delivery_mode = INT_DELIVERY_MODE; - entry.dest_mode = INT_DEST_MODE; - entry.mask = 0; /* enable IRQ */ + if (irq_trigger(idx)) { + entry.trigger = 1; + entry.mask = 1; entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS); + } + + if (!apic && !IO_APIC_IRQ(irq)) + return; + + if (IO_APIC_IRQ(irq)) { + cpumask_t mask; + vector = assign_irq_vector(irq, TARGET_CPUS, &mask); + if (vector < 0) + return; + + entry.dest.logical.logical_dest = cpu_mask_to_apicid(mask); + entry.vector = vector; + + ioapic_register_intr(irq, vector, IOAPIC_AUTO); + if (!apic && (irq < 16)) + disable_8259A_irq(irq); + } + + ioapic_write_entry(apic, pin, entry); + + spin_lock_irqsave(&ioapic_lock, flags); + set_native_irq_info(irq, TARGET_CPUS); + spin_unlock_irqrestore(&ioapic_lock, flags); + +} + +static void __init setup_IO_APIC_irqs(void) +{ + int apic, pin, idx, irq, first_notcon = 1; + + apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n"); + + for (apic = 0; apic < nr_ioapics; apic++) { + for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) { idx = find_irq_entry(apic,pin,mp_INT); if (idx == -1) { @@ -826,39 +859,11 @@ static void __init setup_IO_APIC_irqs(void) continue; } - entry.trigger = irq_trigger(idx); - entry.polarity = irq_polarity(idx); - - if (irq_trigger(idx)) { - entry.trigger = 1; - entry.mask = 1; - entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS); - } - irq = pin_2_irq(idx, apic, pin); add_pin_to_irq(irq, apic, pin); - if (!apic && !IO_APIC_IRQ(irq)) - continue; - - if (IO_APIC_IRQ(irq)) { - cpumask_t mask; - vector = assign_irq_vector(irq, TARGET_CPUS, &mask); - if (vector < 0) - continue; - - entry.dest.logical.logical_dest = cpu_mask_to_apicid(mask); - entry.vector = vector; - - ioapic_register_intr(irq, vector, IOAPIC_AUTO); - if (!apic && (irq < 16)) - disable_8259A_irq(irq); - } - ioapic_write_entry(apic, pin, entry); + setup_IO_APIC_irq(apic, pin, idx, irq); - spin_lock_irqsave(&ioapic_lock, flags); - set_native_irq_info(irq, TARGET_CPUS); - spin_unlock_irqrestore(&ioapic_lock, flags); } } @@ -1563,10 +1568,33 @@ static inline void unlock_ExtINT_logic(void) * a wide range of boards and BIOS bugs. Fortunately only the timer IRQ * is so screwy. Thanks to Brian Perkins for testing/hacking this beast * fanatically on his truly buggy board. - * - * FIXME: really need to revamp this for modern platforms only. */ -static inline void check_timer(void) + +static int try_apic_pin(int apic, int pin, char *msg) +{ + apic_printk(APIC_VERBOSE, KERN_INFO + "..TIMER: trying IO-APIC=%d PIN=%d %s", + apic, pin, msg); + + /* + * Ok, does IRQ0 through the IOAPIC work? + */ + if (!no_timer_check && timer_irq_works()) { + nmi_watchdog_default(); + if (nmi_watchdog == NMI_IO_APIC) { + disable_8259A_irq(0); + setup_nmi(); + enable_8259A_irq(0); + } + return 1; + } + clear_IO_APIC_pin(apic, pin); + apic_printk(APIC_QUIET, KERN_ERR " .. failed\n"); + return 0; +} + +/* The function from hell */ +static void check_timer(void) { int apic1, pin1, apic2, pin2; int vector; @@ -1587,61 +1615,43 @@ static inline void check_timer(void) */ apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT); init_8259A(1); - if (timer_over_8254 > 0) - enable_8259A_irq(0); pin1 = find_isa_irq_pin(0, mp_INT); apic1 = find_isa_irq_apic(0, mp_INT); pin2 = ioapic_i8259.pin; apic2 = ioapic_i8259.apic; - apic_printk(APIC_VERBOSE,KERN_INFO "..TIMER: vector=0x%02X apic1=%d pin1=%d apic2=%d pin2=%d\n", - vector, apic1, pin1, apic2, pin2); + /* Do this first, otherwise we get double interrupts on ATI boards */ + if ((pin1 != -1) && try_apic_pin(apic1, pin1,"with 8259 IRQ0 disabled")) + return; - if (pin1 != -1) { - /* - * Ok, does IRQ0 through the IOAPIC work? - */ - unmask_IO_APIC_irq(0); - if (!no_timer_check && timer_irq_works()) { - nmi_watchdog_default(); - if (nmi_watchdog == NMI_IO_APIC) { - disable_8259A_irq(0); - setup_nmi(); - enable_8259A_irq(0); - } - if (disable_timer_pin_1 > 0) - clear_IO_APIC_pin(0, pin1); - return; - } - clear_IO_APIC_pin(apic1, pin1); - apic_printk(APIC_QUIET,KERN_ERR "..MP-BIOS bug: 8254 timer not " - "connected to IO-APIC\n"); - } + /* Now try again with IRQ0 8259A enabled. + Assumes timer is on IO-APIC 0 ?!? */ + enable_8259A_irq(0); + unmask_IO_APIC_irq(0); + if (try_apic_pin(apic1, pin1, "with 8259 IRQ0 enabled")) + return; + disable_8259A_irq(0); + + /* Always try pin0 and pin2 on APIC 0 to handle buggy timer overrides + on Nvidia boards */ + if (!(apic1 == 0 && pin1 == 0) && + try_apic_pin(0, 0, "fallback with 8259 IRQ0 disabled")) + return; + if (!(apic1 == 0 && pin1 == 2) && + try_apic_pin(0, 2, "fallback with 8259 IRQ0 disabled")) + return; - apic_printk(APIC_VERBOSE,KERN_INFO "...trying to set up timer (IRQ0) " - "through the 8259A ... "); + /* Then try pure 8259A routing on the 8259 as reported by BIOS*/ + enable_8259A_irq(0); if (pin2 != -1) { - apic_printk(APIC_VERBOSE,"\n..... (found apic %d pin %d) ...", - apic2, pin2); - /* - * legacy devices should be connected to IO APIC #0 - */ setup_ExtINT_IRQ0_pin(apic2, pin2, vector); - if (timer_irq_works()) { - apic_printk(APIC_VERBOSE," works.\n"); - nmi_watchdog_default(); - if (nmi_watchdog == NMI_IO_APIC) { - setup_nmi(); - } + if (try_apic_pin(apic2,pin2,"8259A broadcast ExtINT from BIOS")) return; - } - /* - * Cleanup, just in case ... - */ - clear_IO_APIC_pin(apic2, pin2); } - apic_printk(APIC_VERBOSE," failed.\n"); + + /* Tried all possibilities to go through the IO-APIC. Now come the + really cheesy fallbacks. */ if (nmi_watchdog == NMI_IO_APIC) { printk(KERN_WARNING "timer doesn't work through the IO-APIC - disabling NMI Watchdog!\n"); @@ -1837,7 +1847,7 @@ void destroy_irq(unsigned int irq) dynamic_irq_cleanup(irq); spin_lock_irqsave(&vector_lock, flags); - irq_vector[irq] = 0; + __clear_irq_vector(irq); spin_unlock_irqrestore(&vector_lock, flags); } @@ -2139,7 +2149,15 @@ void __init setup_ioapic_dest(void) if (irq_entry == -1) continue; irq = pin_2_irq(irq_entry, ioapic, pin); - set_ioapic_affinity_irq(irq, TARGET_CPUS); + + /* setup_IO_APIC_irqs could fail to get vector for some device + * when you have too many devices, because at that time only boot + * cpu is online. + */ + if(!irq_vector[irq]) + setup_IO_APIC_irq(ioapic, pin, irq_entry, irq); + else + set_ioapic_affinity_irq(irq, TARGET_CPUS); } } diff --git a/trunk/arch/x86_64/kernel/irq.c b/trunk/arch/x86_64/kernel/irq.c index e46c55856d40..0c06af6c13bc 100644 --- a/trunk/arch/x86_64/kernel/irq.c +++ b/trunk/arch/x86_64/kernel/irq.c @@ -120,7 +120,7 @@ asmlinkage unsigned int do_IRQ(struct pt_regs *regs) if (likely(irq < NR_IRQS)) generic_handle_irq(irq); - else + else if (printk_ratelimit()) printk(KERN_EMERG "%s: %d.%d No irq handler for vector\n", __func__, smp_processor_id(), vector); diff --git a/trunk/arch/x86_64/kernel/kprobes.c b/trunk/arch/x86_64/kernel/kprobes.c index ac241567e682..209c8c0bec71 100644 --- a/trunk/arch/x86_64/kernel/kprobes.c +++ b/trunk/arch/x86_64/kernel/kprobes.c @@ -224,7 +224,7 @@ void __kprobes arch_disarm_kprobe(struct kprobe *p) void __kprobes arch_remove_kprobe(struct kprobe *p) { mutex_lock(&kprobe_mutex); - free_insn_slot(p->ainsn.insn); + free_insn_slot(p->ainsn.insn, 0); mutex_unlock(&kprobe_mutex); } diff --git a/trunk/arch/x86_64/kernel/mce.c b/trunk/arch/x86_64/kernel/mce.c index bbea88801d88..ac085038af29 100644 --- a/trunk/arch/x86_64/kernel/mce.c +++ b/trunk/arch/x86_64/kernel/mce.c @@ -306,8 +306,8 @@ void mce_log_therm_throt_event(unsigned int cpu, __u64 status) */ static int check_interval = 5 * 60; /* 5 minutes */ -static void mcheck_timer(void *data); -static DECLARE_WORK(mcheck_work, mcheck_timer, NULL); +static void mcheck_timer(struct work_struct *work); +static DECLARE_DELAYED_WORK(mcheck_work, mcheck_timer); static void mcheck_check_cpu(void *info) { @@ -315,7 +315,7 @@ static void mcheck_check_cpu(void *info) do_machine_check(NULL, 0); } -static void mcheck_timer(void *data) +static void mcheck_timer(struct work_struct *work) { on_each_cpu(mcheck_check_cpu, NULL, 1, 1); schedule_delayed_work(&mcheck_work, check_interval * HZ); @@ -641,7 +641,6 @@ static __cpuinit int mce_create_device(unsigned int cpu) return err; } -#ifdef CONFIG_HOTPLUG_CPU static void mce_remove_device(unsigned int cpu) { int i; @@ -652,6 +651,7 @@ static void mce_remove_device(unsigned int cpu) sysdev_remove_file(&per_cpu(device_mce,cpu), &attr_tolerant); sysdev_remove_file(&per_cpu(device_mce,cpu), &attr_check_interval); sysdev_unregister(&per_cpu(device_mce,cpu)); + memset(&per_cpu(device_mce, cpu).kobj, 0, sizeof(struct kobject)); } /* Get notified when a cpu comes on/off. Be hotplug friendly. */ @@ -674,7 +674,6 @@ mce_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) static struct notifier_block mce_cpu_notifier = { .notifier_call = mce_cpu_callback, }; -#endif static __init int mce_init_device(void) { diff --git a/trunk/arch/x86_64/kernel/mce_amd.c b/trunk/arch/x86_64/kernel/mce_amd.c index 883fe747f64c..fa09debad4b7 100644 --- a/trunk/arch/x86_64/kernel/mce_amd.c +++ b/trunk/arch/x86_64/kernel/mce_amd.c @@ -551,7 +551,6 @@ static __cpuinit int threshold_create_device(unsigned int cpu) return err; } -#ifdef CONFIG_HOTPLUG_CPU /* * let's be hotplug friendly. * in case of multiple core processors, the first core always takes ownership @@ -594,12 +593,14 @@ static void threshold_remove_bank(unsigned int cpu, int bank) sprintf(name, "threshold_bank%i", bank); +#ifdef CONFIG_SMP /* sibling symlink */ if (shared_bank[bank] && b->blocks->cpu != cpu) { sysfs_remove_link(&per_cpu(device_mce, cpu).kobj, name); per_cpu(threshold_banks, cpu)[bank] = NULL; return; } +#endif /* remove all sibling symlinks before unregistering */ for_each_cpu_mask(i, b->cpus) { @@ -656,7 +657,6 @@ static int threshold_cpu_callback(struct notifier_block *nfb, static struct notifier_block threshold_cpu_notifier = { .notifier_call = threshold_cpu_callback, }; -#endif /* CONFIG_HOTPLUG_CPU */ static __init int threshold_init_device(void) { diff --git a/trunk/arch/x86_64/kernel/module.c b/trunk/arch/x86_64/kernel/module.c index 9d0958ff547f..a888e67f5874 100644 --- a/trunk/arch/x86_64/kernel/module.c +++ b/trunk/arch/x86_64/kernel/module.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -173,10 +174,12 @@ int module_finalize(const Elf_Ehdr *hdr, lseg, lseg + locks->sh_size, tseg, tseg + text->sh_size); } - return 0; + + return module_bug_finalize(hdr, sechdrs, me); } void module_arch_cleanup(struct module *mod) { alternatives_smp_module_del(mod); + module_bug_cleanup(mod); } diff --git a/trunk/arch/x86_64/kernel/mpparse.c b/trunk/arch/x86_64/kernel/mpparse.c index b147ab19fbd4..08072568847d 100644 --- a/trunk/arch/x86_64/kernel/mpparse.c +++ b/trunk/arch/x86_64/kernel/mpparse.c @@ -35,8 +35,6 @@ int smp_found_config; unsigned int __initdata maxcpus = NR_CPUS; -int acpi_found_madt; - /* * Various Linux-internal data structures created from the * MP-table. diff --git a/trunk/arch/x86_64/kernel/nmi.c b/trunk/arch/x86_64/kernel/nmi.c index 7af9cb3e2d99..27e95e7922c1 100644 --- a/trunk/arch/x86_64/kernel/nmi.c +++ b/trunk/arch/x86_64/kernel/nmi.c @@ -12,14 +12,15 @@ * Mikael Pettersson : PM converted to driver model. Disable/enable API. */ +#include #include #include #include #include #include -#include #include #include +#include #include #include @@ -41,6 +42,8 @@ int panic_on_unrecovered_nmi; static DEFINE_PER_CPU(unsigned, perfctr_nmi_owner); static DEFINE_PER_CPU(unsigned, evntsel_nmi_owner[2]); +static cpumask_t backtrace_mask = CPU_MASK_NONE; + /* this number is calculated from Intel's MSR_P4_CRU_ESCR5 register and it's * offset from MSR_P4_BSU_ESCR0. It will be the max for all platforms (for now) */ @@ -782,6 +785,7 @@ int __kprobes nmi_watchdog_tick(struct pt_regs * regs, unsigned reason) { int sum; int touched = 0; + int cpu = smp_processor_id(); struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk); u64 dummy; int rc=0; @@ -799,6 +803,16 @@ int __kprobes nmi_watchdog_tick(struct pt_regs * regs, unsigned reason) touched = 1; } + if (cpu_isset(cpu, backtrace_mask)) { + static DEFINE_SPINLOCK(lock); /* Serialise the printks */ + + spin_lock(&lock); + printk("NMI backtrace for cpu %d\n", cpu); + dump_stack(); + spin_unlock(&lock); + cpu_clear(cpu, backtrace_mask); + } + #ifdef CONFIG_X86_MCE /* Could check oops_in_progress here too, but it's safer not too */ @@ -931,6 +945,19 @@ int proc_nmi_enabled(struct ctl_table *table, int write, struct file *file, #endif +void __trigger_all_cpu_backtrace(void) +{ + int i; + + backtrace_mask = cpu_online_map; + /* Wait for up to 10 seconds for all CPUs to do the backtrace */ + for (i = 0; i < 10 * 1000; i++) { + if (cpus_empty(backtrace_mask)) + break; + mdelay(1); + } +} + EXPORT_SYMBOL(nmi_active); EXPORT_SYMBOL(nmi_watchdog); EXPORT_SYMBOL(avail_to_resrv_perfctr_nmi); diff --git a/trunk/arch/x86_64/kernel/pci-calgary.c b/trunk/arch/x86_64/kernel/pci-calgary.c index 37a770859e71..3215675ab128 100644 --- a/trunk/arch/x86_64/kernel/pci-calgary.c +++ b/trunk/arch/x86_64/kernel/pci-calgary.c @@ -41,6 +41,13 @@ #include #include #include +#include + +#ifdef CONFIG_CALGARY_IOMMU_ENABLED_BY_DEFAULT +int use_calgary __read_mostly = 1; +#else +int use_calgary __read_mostly = 0; +#endif /* CONFIG_CALGARY_DEFAULT_ENABLED */ #define PCI_DEVICE_ID_IBM_CALGARY 0x02a1 #define PCI_VENDOR_DEVICE_ID_CALGARY \ @@ -115,14 +122,35 @@ static const unsigned long phb_offsets[] = { 0xB000 /* PHB3 */ }; +/* PHB debug registers */ + +static const unsigned long phb_debug_offsets[] = { + 0x4000 /* PHB 0 DEBUG */, + 0x5000 /* PHB 1 DEBUG */, + 0x6000 /* PHB 2 DEBUG */, + 0x7000 /* PHB 3 DEBUG */ +}; + +/* + * STUFF register for each debug PHB, + * byte 1 = start bus number, byte 2 = end bus number + */ + +#define PHB_DEBUG_STUFF_OFFSET 0x0020 + unsigned int specified_table_size = TCE_TABLE_SIZE_UNSPECIFIED; static int translate_empty_slots __read_mostly = 0; static int calgary_detected __read_mostly = 0; +static struct rio_table_hdr *rio_table_hdr __initdata; +static struct scal_detail *scal_devs[MAX_NUMNODES] __initdata; +static struct rio_detail *rio_devs[MAX_NUMNODES * 4] __initdata; + struct calgary_bus_info { void *tce_space; unsigned char translation_disabled; signed char phbid; + void __iomem *bbar; }; static struct calgary_bus_info bus_info[MAX_PHB_BUS_NUM] = { { NULL, 0, 0 }, }; @@ -475,6 +503,11 @@ static struct dma_mapping_ops calgary_dma_ops = { .unmap_sg = calgary_unmap_sg, }; +static inline void __iomem * busno_to_bbar(unsigned char num) +{ + return bus_info[num].bbar; +} + static inline int busno_to_phbid(unsigned char num) { return bus_info[num].phbid; @@ -620,14 +653,9 @@ static void __init calgary_reserve_peripheral_mem_2(struct pci_dev *dev) static void __init calgary_reserve_regions(struct pci_dev *dev) { unsigned int npages; - void __iomem *bbar; - unsigned char busnum; u64 start; struct iommu_table *tbl = dev->sysdata; - bbar = tbl->bbar; - busnum = dev->bus->number; - /* reserve bad_dma_address in case it's a legal address */ iommu_range_reserve(tbl, bad_dma_address, 1); @@ -740,7 +768,7 @@ static void __init calgary_increase_split_completion_timeout(void __iomem *bbar, { u64 val64; void __iomem *target; - unsigned long phb_shift = -1; + unsigned int phb_shift = ~0; /* silence gcc */ u64 mask; switch (busno_to_phbid(busnum)) { @@ -828,33 +856,6 @@ static void __init calgary_disable_translation(struct pci_dev *dev) del_timer_sync(&tbl->watchdog_timer); } -static inline unsigned int __init locate_register_space(struct pci_dev *dev) -{ - int rionodeid; - u32 address; - - /* - * Each Calgary has four busses. The first four busses (first Calgary) - * have RIO node ID 2, then the next four (second Calgary) have RIO - * node ID 3, the next four (third Calgary) have node ID 2 again, etc. - * We use a gross hack - relying on the dev->bus->number ordering, - * modulo 14 - to decide which Calgary a given bus is on. Busses 0, 1, - * 2 and 4 are on the first Calgary (id 2), 6, 8, a and c are on the - * second (id 3), and then it repeats modulo 14. - */ - rionodeid = (dev->bus->number % 14 > 4) ? 3 : 2; - /* - * register space address calculation as follows: - * FE0MB-8MB*OneBasedChassisNumber+1MB*(RioNodeId-ChassisBase) - * ChassisBase is always zero for x366/x260/x460 - * RioNodeId is 2 for first Calgary, 3 for second Calgary - */ - address = START_ADDRESS - - (0x800000 * (ONE_BASED_CHASSIS_NUM + dev->bus->number / 14)) + - (0x100000) * (rionodeid - CHASSIS_BASE); - return address; -} - static void __init calgary_init_one_nontraslated(struct pci_dev *dev) { pci_dev_get(dev); @@ -864,23 +865,15 @@ static void __init calgary_init_one_nontraslated(struct pci_dev *dev) static int __init calgary_init_one(struct pci_dev *dev) { - u32 address; void __iomem *bbar; int ret; BUG_ON(dev->bus->number >= MAX_PHB_BUS_NUM); - address = locate_register_space(dev); - /* map entire 1MB of Calgary config space */ - bbar = ioremap_nocache(address, 1024 * 1024); - if (!bbar) { - ret = -ENODATA; - goto done; - } - + bbar = busno_to_bbar(dev->bus->number); ret = calgary_setup_tar(dev, bbar); if (ret) - goto iounmap; + goto done; pci_dev_get(dev); dev->bus->self = dev; @@ -888,17 +881,66 @@ static int __init calgary_init_one(struct pci_dev *dev) return 0; -iounmap: - iounmap(bbar); done: return ret; } +static int __init calgary_locate_bbars(void) +{ + int ret; + int rioidx, phb, bus; + void __iomem *bbar; + void __iomem *target; + unsigned long offset; + u8 start_bus, end_bus; + u32 val; + + ret = -ENODATA; + for (rioidx = 0; rioidx < rio_table_hdr->num_rio_dev; rioidx++) { + struct rio_detail *rio = rio_devs[rioidx]; + + if ((rio->type != COMPAT_CALGARY) && (rio->type != ALT_CALGARY)) + continue; + + /* map entire 1MB of Calgary config space */ + bbar = ioremap_nocache(rio->BBAR, 1024 * 1024); + if (!bbar) + goto error; + + for (phb = 0; phb < PHBS_PER_CALGARY; phb++) { + offset = phb_debug_offsets[phb] | PHB_DEBUG_STUFF_OFFSET; + target = calgary_reg(bbar, offset); + + val = be32_to_cpu(readl(target)); + start_bus = (u8)((val & 0x00FF0000) >> 16); + end_bus = (u8)((val & 0x0000FF00) >> 8); + for (bus = start_bus; bus <= end_bus; bus++) { + bus_info[bus].bbar = bbar; + bus_info[bus].phbid = phb; + } + } + } + + return 0; + +error: + /* scan bus_info and iounmap any bbars we previously ioremap'd */ + for (bus = 0; bus < ARRAY_SIZE(bus_info); bus++) + if (bus_info[bus].bbar) + iounmap(bus_info[bus].bbar); + + return ret; +} + static int __init calgary_init(void) { - int ret = -ENODEV; + int ret; struct pci_dev *dev = NULL; + ret = calgary_locate_bbars(); + if (ret) + return ret; + do { dev = pci_get_device(PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CALGARY, @@ -921,7 +963,7 @@ static int __init calgary_init(void) error: do { - dev = pci_find_device_reverse(PCI_VENDOR_ID_IBM, + dev = pci_get_device_reverse(PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CALGARY, dev); if (!dev) @@ -962,13 +1004,56 @@ static inline int __init determine_tce_table_size(u64 ram) return ret; } +static int __init build_detail_arrays(void) +{ + unsigned long ptr; + int i, scal_detail_size, rio_detail_size; + + if (rio_table_hdr->num_scal_dev > MAX_NUMNODES){ + printk(KERN_WARNING + "Calgary: MAX_NUMNODES too low! Defined as %d, " + "but system has %d nodes.\n", + MAX_NUMNODES, rio_table_hdr->num_scal_dev); + return -ENODEV; + } + + switch (rio_table_hdr->version){ + case 2: + scal_detail_size = 11; + rio_detail_size = 13; + break; + case 3: + scal_detail_size = 12; + rio_detail_size = 15; + break; + default: + printk(KERN_WARNING + "Calgary: Invalid Rio Grande Table Version: %d\n", + rio_table_hdr->version); + return -EPROTO; + } + + ptr = ((unsigned long)rio_table_hdr) + 3; + for (i = 0; i < rio_table_hdr->num_scal_dev; + i++, ptr += scal_detail_size) + scal_devs[i] = (struct scal_detail *)ptr; + + for (i = 0; i < rio_table_hdr->num_rio_dev; + i++, ptr += rio_detail_size) + rio_devs[i] = (struct rio_detail *)ptr; + + return 0; +} + void __init detect_calgary(void) { u32 val; int bus; void *tbl; int calgary_found = 0; - int phb = -1; + unsigned long ptr; + int offset; + int ret; /* * if the user specified iommu=off or iommu=soft or we found @@ -977,25 +1062,47 @@ void __init detect_calgary(void) if (swiotlb || no_iommu || iommu_detected) return; + if (!use_calgary) + return; + if (!early_pci_allowed()) return; + ptr = (unsigned long)phys_to_virt(get_bios_ebda()); + + rio_table_hdr = NULL; + offset = 0x180; + while (offset) { + /* The block id is stored in the 2nd word */ + if (*((unsigned short *)(ptr + offset + 2)) == 0x4752){ + /* set the pointer past the offset & block id */ + rio_table_hdr = (struct rio_table_hdr *)(ptr + offset + 4); + break; + } + /* The next offset is stored in the 1st word. 0 means no more */ + offset = *((unsigned short *)(ptr + offset)); + } + if (!rio_table_hdr) { + printk(KERN_ERR "Calgary: Unable to locate " + "Rio Grande Table in EBDA - bailing!\n"); + return; + } + + ret = build_detail_arrays(); + if (ret) { + printk(KERN_ERR "Calgary: build_detail_arrays ret %d\n", ret); + return; + } + specified_table_size = determine_tce_table_size(end_pfn * PAGE_SIZE); for (bus = 0; bus < MAX_PHB_BUS_NUM; bus++) { int dev; struct calgary_bus_info *info = &bus_info[bus]; - info->phbid = -1; if (read_pci_config(bus, 0, 0, 0) != PCI_VENDOR_DEVICE_ID_CALGARY) continue; - /* - * There are 4 PHBs per Calgary chip. Set phb to which phb (0-3) - * it is connected to releative to the clagary chip. - */ - phb = (phb + 1) % PHBS_PER_CALGARY; - if (info->translation_disabled) continue; @@ -1010,7 +1117,6 @@ void __init detect_calgary(void) if (!tbl) goto cleanup; info->tce_space = tbl; - info->phbid = phb; calgary_found = 1; break; } diff --git a/trunk/arch/x86_64/kernel/pci-dma.c b/trunk/arch/x86_64/kernel/pci-dma.c index f8d857453f8a..683b7a5c1ab3 100644 --- a/trunk/arch/x86_64/kernel/pci-dma.c +++ b/trunk/arch/x86_64/kernel/pci-dma.c @@ -296,6 +296,11 @@ __init int iommu_setup(char *p) gart_parse_options(p); #endif +#ifdef CONFIG_CALGARY_IOMMU + if (!strncmp(p, "calgary", 7)) + use_calgary = 1; +#endif /* CONFIG_CALGARY_IOMMU */ + p += strcspn(p, ","); if (*p == ',') ++p; diff --git a/trunk/arch/x86_64/kernel/pci-gart.c b/trunk/arch/x86_64/kernel/pci-gart.c index 16261a8a3303..fc1960f1f243 100644 --- a/trunk/arch/x86_64/kernel/pci-gart.c +++ b/trunk/arch/x86_64/kernel/pci-gart.c @@ -601,10 +601,9 @@ void __init gart_iommu_init(void) (!force_iommu && end_pfn <= MAX_DMA32_PFN) || !iommu_aperture || (no_agp && init_k8_gatt(&info) < 0)) { - printk(KERN_INFO "PCI-DMA: Disabling IOMMU.\n"); if (end_pfn > MAX_DMA32_PFN) { printk(KERN_ERR "WARNING more than 4GB of memory " - "but IOMMU not available.\n" + "but GART IOMMU not available.\n" KERN_ERR "WARNING 32bit PCI may malfunction.\n"); } return; diff --git a/trunk/arch/x86_64/kernel/process.c b/trunk/arch/x86_64/kernel/process.c index 7451a4c43c16..a418ee4c8c62 100644 --- a/trunk/arch/x86_64/kernel/process.c +++ b/trunk/arch/x86_64/kernel/process.c @@ -108,17 +108,15 @@ void exit_idle(void) */ static void default_idle(void) { - local_irq_enable(); - current_thread_info()->status &= ~TS_POLLING; smp_mb__after_clear_bit(); - while (!need_resched()) { - local_irq_disable(); - if (!need_resched()) - safe_halt(); - else - local_irq_enable(); - } + local_irq_disable(); + if (!need_resched()) { + /* Enables interrupts one instruction before HLT. + x86 special cases this so there is no race. */ + safe_halt(); + } else + local_irq_enable(); current_thread_info()->status |= TS_POLLING; } @@ -130,15 +128,7 @@ static void default_idle(void) static void poll_idle (void) { local_irq_enable(); - - asm volatile( - "2:" - "testl %0,%1;" - "rep; nop;" - "je 2b;" - : : - "i" (_TIF_NEED_RESCHED), - "m" (current_thread_info()->flags)); + cpu_relax(); } void cpu_idle_wait(void) @@ -219,6 +209,12 @@ void cpu_idle (void) idle = default_idle; if (cpu_is_offline(smp_processor_id())) play_dead(); + /* + * Idle routines should keep interrupts disabled + * from here on, until they go to idle. + * Otherwise, idle callbacks can misfire. + */ + local_irq_disable(); enter_idle(); idle(); /* In many cases the interrupt that ended idle @@ -256,9 +252,16 @@ void mwait_idle_with_hints(unsigned long eax, unsigned long ecx) /* Default MONITOR/MWAIT with no hints, used for default C1 state */ static void mwait_idle(void) { - local_irq_enable(); - while (!need_resched()) - mwait_idle_with_hints(0,0); + if (!need_resched()) { + __monitor((void *)¤t_thread_info()->flags, 0, 0); + smp_mb(); + if (!need_resched()) + __sti_mwait(0, 0); + else + local_irq_enable(); + } else { + local_irq_enable(); + } } void __cpuinit select_idle_routine(const struct cpuinfo_x86 *c) diff --git a/trunk/arch/x86_64/kernel/setup.c b/trunk/arch/x86_64/kernel/setup.c index fc944b5e8f4a..af425a8049fb 100644 --- a/trunk/arch/x86_64/kernel/setup.c +++ b/trunk/arch/x86_64/kernel/setup.c @@ -471,8 +471,7 @@ void __init setup_arch(char **cmdline_p) if (LOADER_TYPE && INITRD_START) { if (INITRD_START + INITRD_SIZE <= (end_pfn << PAGE_SHIFT)) { reserve_bootmem_generic(INITRD_START, INITRD_SIZE); - initrd_start = - INITRD_START ? INITRD_START + PAGE_OFFSET : 0; + initrd_start = INITRD_START + PAGE_OFFSET; initrd_end = initrd_start+INITRD_SIZE; } else { @@ -732,11 +731,8 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c) /* Fix cpuid4 emulation for more */ num_cache_leaves = 3; - /* When there is only one core no need to synchronize RDTSC */ - if (num_possible_cpus() == 1) - set_bit(X86_FEATURE_SYNC_RDTSC, &c->x86_capability); - else - clear_bit(X86_FEATURE_SYNC_RDTSC, &c->x86_capability); + /* RDTSC can be speculated around */ + clear_bit(X86_FEATURE_SYNC_RDTSC, &c->x86_capability); } static void __cpuinit detect_ht(struct cpuinfo_x86 *c) @@ -835,6 +831,15 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c) set_bit(X86_FEATURE_ARCH_PERFMON, &c->x86_capability); } + if (cpu_has_ds) { + unsigned int l1, l2; + rdmsr(MSR_IA32_MISC_ENABLE, l1, l2); + if (!(l1 & (1<<11))) + set_bit(X86_FEATURE_BTS, c->x86_capability); + if (!(l1 & (1<<12))) + set_bit(X86_FEATURE_PEBS, c->x86_capability); + } + n = c->extended_cpuid_level; if (n >= 0x80000008) { unsigned eax = cpuid_eax(0x80000008); @@ -854,7 +859,10 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c) set_bit(X86_FEATURE_CONSTANT_TSC, &c->x86_capability); if (c->x86 == 6) set_bit(X86_FEATURE_REP_GOOD, &c->x86_capability); - set_bit(X86_FEATURE_SYNC_RDTSC, &c->x86_capability); + if (c->x86 == 15) + set_bit(X86_FEATURE_SYNC_RDTSC, &c->x86_capability); + else + clear_bit(X86_FEATURE_SYNC_RDTSC, &c->x86_capability); c->x86_max_cores = intel_num_cpu_cores(c); srat_detect_node(); diff --git a/trunk/arch/x86_64/kernel/smp.c b/trunk/arch/x86_64/kernel/smp.c index 9f74c883568c..af1ec4d23cf8 100644 --- a/trunk/arch/x86_64/kernel/smp.c +++ b/trunk/arch/x86_64/kernel/smp.c @@ -379,12 +379,17 @@ int smp_call_function_single (int cpu, void (*func) (void *info), void *info, put_cpu(); return 0; } + + /* Can deadlock when called with interrupts disabled */ + WARN_ON(irqs_disabled()); + spin_lock_bh(&call_lock); __smp_call_function_single(cpu, func, info, nonatomic, wait); spin_unlock_bh(&call_lock); put_cpu(); return 0; } +EXPORT_SYMBOL(smp_call_function_single); /* * this function sends a 'generic call function' IPI to all other CPUs diff --git a/trunk/arch/x86_64/kernel/smpboot.c b/trunk/arch/x86_64/kernel/smpboot.c index 62c2e747af58..daf19332f0dd 100644 --- a/trunk/arch/x86_64/kernel/smpboot.c +++ b/trunk/arch/x86_64/kernel/smpboot.c @@ -60,6 +60,7 @@ #include #include #include +#include /* Number of siblings per CPU package */ int smp_num_siblings = 1; @@ -753,14 +754,16 @@ static int __cpuinit wakeup_secondary_via_INIT(int phys_apicid, unsigned int sta } struct create_idle { + struct work_struct work; struct task_struct *idle; struct completion done; int cpu; }; -void do_fork_idle(void *_c_idle) +void do_fork_idle(struct work_struct *work) { - struct create_idle *c_idle = _c_idle; + struct create_idle *c_idle = + container_of(work, struct create_idle, work); c_idle->idle = fork_idle(c_idle->cpu); complete(&c_idle->done); @@ -775,10 +778,10 @@ static int __cpuinit do_boot_cpu(int cpu, int apicid) int timeout; unsigned long start_rip; struct create_idle c_idle = { + .work = __WORK_INITIALIZER(c_idle.work, do_fork_idle), .cpu = cpu, .done = COMPLETION_INITIALIZER_ONSTACK(c_idle.done), }; - DECLARE_WORK(work, do_fork_idle, &c_idle); /* allocate memory for gdts of secondary cpus. Hotplug is considered */ if (!cpu_gdt_descr[cpu].address && @@ -825,9 +828,9 @@ static int __cpuinit do_boot_cpu(int cpu, int apicid) * thread. */ if (!keventd_up() || current_is_keventd()) - work.func(work.data); + c_idle.work.func(&c_idle.work); else { - schedule_work(&work); + schedule_work(&c_idle.work); wait_for_completion(&c_idle.done); } @@ -1167,6 +1170,13 @@ int __cpuinit __cpu_up(unsigned int cpu) while (!cpu_isset(cpu, cpu_online_map)) cpu_relax(); + + if (num_online_cpus() > 8 && genapic == &apic_flat) { + printk(KERN_WARNING + "flat APIC routing can't be used with > 8 cpus\n"); + BUG(); + } + err = 0; return err; diff --git a/trunk/arch/x86_64/kernel/time.c b/trunk/arch/x86_64/kernel/time.c index e3ef544d2cfb..9f05bc9b2dad 100644 --- a/trunk/arch/x86_64/kernel/time.c +++ b/trunk/arch/x86_64/kernel/time.c @@ -563,7 +563,7 @@ static unsigned int cpufreq_delayed_issched = 0; static unsigned int cpufreq_init = 0; static struct work_struct cpufreq_delayed_get_work; -static void handle_cpufreq_delayed_get(void *v) +static void handle_cpufreq_delayed_get(struct work_struct *v) { unsigned int cpu; for_each_online_cpu(cpu) { @@ -639,7 +639,7 @@ static struct notifier_block time_cpufreq_notifier_block = { static int __init cpufreq_tsc(void) { - INIT_WORK(&cpufreq_delayed_get_work, handle_cpufreq_delayed_get, NULL); + INIT_WORK(&cpufreq_delayed_get_work, handle_cpufreq_delayed_get); if (!cpufreq_register_notifier(&time_cpufreq_notifier_block, CPUFREQ_TRANSITION_NOTIFIER)) cpufreq_init = 1; diff --git a/trunk/arch/x86_64/kernel/traps.c b/trunk/arch/x86_64/kernel/traps.c index 0d65b22f229c..b54ccc07f379 100644 --- a/trunk/arch/x86_64/kernel/traps.c +++ b/trunk/arch/x86_64/kernel/traps.c @@ -30,9 +30,10 @@ #include #include #include +#include +#include #include -#include #include #include #include @@ -108,7 +109,7 @@ static inline void preempt_conditional_cli(struct pt_regs *regs) preempt_enable_no_resched(); } -static int kstack_depth_to_print = 12; +int kstack_depth_to_print = 12; #ifdef CONFIG_STACK_UNWIND static int call_trace = 1; #else @@ -225,16 +226,25 @@ static int dump_trace_unwind(struct unwind_frame_info *info, void *context) { struct ops_and_data *oad = (struct ops_and_data *)context; int n = 0; + unsigned long sp = UNW_SP(info); + if (arch_unw_user_mode(info)) + return -1; while (unwind(info) == 0 && UNW_PC(info)) { n++; oad->ops->address(oad->data, UNW_PC(info)); if (arch_unw_user_mode(info)) break; + if ((sp & ~(PAGE_SIZE - 1)) == (UNW_SP(info) & ~(PAGE_SIZE - 1)) + && sp > UNW_SP(info)) + break; + sp = UNW_SP(info); } return n; } +#define MSG(txt) ops->warning(data, txt) + /* * x86-64 can have upto three kernel stacks: * process stack @@ -248,11 +258,12 @@ static inline int valid_stack_ptr(struct thread_info *tinfo, void *p) return p > t && p < t + THREAD_SIZE - 3; } -void dump_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long * stack, +void dump_trace(struct task_struct *tsk, struct pt_regs *regs, + unsigned long *stack, struct stacktrace_ops *ops, void *data) { - const unsigned cpu = smp_processor_id(); - unsigned long *irqstack_end = (unsigned long *)cpu_pda(cpu)->irqstackptr; + const unsigned cpu = get_cpu(); + unsigned long *irqstack_end = (unsigned long*)cpu_pda(cpu)->irqstackptr; unsigned used = 0; struct thread_info *tinfo; @@ -268,28 +279,30 @@ void dump_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long * s if (unwind_init_frame_info(&info, tsk, regs) == 0) unw_ret = dump_trace_unwind(&info, &oad); } else if (tsk == current) - unw_ret = unwind_init_running(&info, dump_trace_unwind, &oad); + unw_ret = unwind_init_running(&info, dump_trace_unwind, + &oad); else { if (unwind_init_blocked(&info, tsk) == 0) unw_ret = dump_trace_unwind(&info, &oad); } if (unw_ret > 0) { if (call_trace == 1 && !arch_unw_user_mode(&info)) { - ops->warning_symbol(data, "DWARF2 unwinder stuck at %s\n", + ops->warning_symbol(data, + "DWARF2 unwinder stuck at %s", UNW_PC(&info)); if ((long)UNW_SP(&info) < 0) { - ops->warning(data, "Leftover inexact backtrace:\n"); + MSG("Leftover inexact backtrace:"); stack = (unsigned long *)UNW_SP(&info); if (!stack) - return; + goto out; } else - ops->warning(data, "Full inexact backtrace again:\n"); + MSG("Full inexact backtrace again:"); } else if (call_trace >= 1) - return; + goto out; else - ops->warning(data, "Full inexact backtrace again:\n"); + MSG("Full inexact backtrace again:"); } else - ops->warning(data, "Inexact backtrace:\n"); + MSG("Inexact backtrace:"); } if (!stack) { unsigned long dummy; @@ -297,12 +310,6 @@ void dump_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long * s if (tsk && tsk != current) stack = (unsigned long *)tsk->thread.rsp; } - /* - * Align the stack pointer on word boundary, later loops - * rely on that (and corruption / debug info bugs can cause - * unaligned values here): - */ - stack = (unsigned long *)((unsigned long)stack & ~(sizeof(long)-1)); /* * Print function call entries within a stack. 'cond' is the @@ -312,9 +319,9 @@ void dump_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long * s #define HANDLE_STACK(cond) \ do while (cond) { \ unsigned long addr = *stack++; \ - if (oops_in_progress ? \ - __kernel_text_address(addr) : \ - kernel_text_address(addr)) { \ + /* Use unlocked access here because except for NMIs \ + we should be already protected against module unloads */ \ + if (__kernel_text_address(addr)) { \ /* \ * If the address is either in the text segment of the \ * kernel, or in the region which contains vmalloc'ed \ @@ -380,6 +387,8 @@ void dump_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long * s tinfo = current_thread_info(); HANDLE_STACK (valid_stack_ptr(tinfo, stack)); #undef HANDLE_STACK +out: + put_cpu(); } EXPORT_SYMBOL(dump_trace); @@ -516,30 +525,15 @@ void show_registers(struct pt_regs *regs) printk("\n"); } -void handle_BUG(struct pt_regs *regs) -{ - struct bug_frame f; - long len; - const char *prefix = ""; +int is_valid_bugaddr(unsigned long rip) +{ + unsigned short ud2; - if (user_mode(regs)) - return; - if (__copy_from_user(&f, (const void __user *) regs->rip, - sizeof(struct bug_frame))) - return; - if (f.filename >= 0 || - f.ud2[0] != 0x0f || f.ud2[1] != 0x0b) - return; - len = __strnlen_user((char *)(long)f.filename, PATH_MAX) - 1; - if (len < 0 || len >= PATH_MAX) - f.filename = (int)(long)"unmapped filename"; - else if (len > 50) { - f.filename += len - 50; - prefix = "..."; - } - printk("----------- [cut here ] --------- [please bite here ] ---------\n"); - printk(KERN_ALERT "Kernel BUG at %s%.50s:%d\n", prefix, (char *)(long)f.filename, f.line); -} + if (__copy_from_user(&ud2, (const void __user *) rip, sizeof(ud2))) + return 0; + + return ud2 == 0x0b0f; +} #ifdef CONFIG_BUG void out_of_line_bug(void) @@ -619,7 +613,9 @@ void die(const char * str, struct pt_regs * regs, long err) { unsigned long flags = oops_begin(); - handle_BUG(regs); + if (!user_mode(regs)) + report_bug(regs->rip); + __die(str, regs, err); oops_end(flags); do_exit(SIGSEGV); @@ -786,8 +782,7 @@ mem_parity_error(unsigned char reason, struct pt_regs * regs) { printk(KERN_EMERG "Uhhuh. NMI received for unknown reason %02x.\n", reason); - printk(KERN_EMERG "You probably have a hardware problem with your " - "RAM chips\n"); + printk(KERN_EMERG "You have some hardware problem, likely on the PCI bus.\n"); if (panic_on_unrecovered_nmi) panic("NMI: Not continuing"); diff --git a/trunk/arch/x86_64/kernel/vmlinux.lds.S b/trunk/arch/x86_64/kernel/vmlinux.lds.S index d9534e750d4f..6c417788c54b 100644 --- a/trunk/arch/x86_64/kernel/vmlinux.lds.S +++ b/trunk/arch/x86_64/kernel/vmlinux.lds.S @@ -51,14 +51,7 @@ SECTIONS RODATA -#ifdef CONFIG_STACK_UNWIND - . = ALIGN(8); - .eh_frame : AT(ADDR(.eh_frame) - LOAD_OFFSET) { - __start_unwind = .; - *(.eh_frame) - __end_unwind = .; - } -#endif + BUG_TABLE . = ALIGN(PAGE_SIZE); /* Align data segment to page size boundary */ /* Data */ diff --git a/trunk/arch/x86_64/kernel/vsyscall.c b/trunk/arch/x86_64/kernel/vsyscall.c index 92546c1526f1..4a673f5397a0 100644 --- a/trunk/arch/x86_64/kernel/vsyscall.c +++ b/trunk/arch/x86_64/kernel/vsyscall.c @@ -42,6 +42,7 @@ #include #define __vsyscall(nr) __attribute__ ((unused,__section__(".vsyscall_" #nr))) +#define __syscall_clobber "r11","rcx","memory" int __sysctl_vsyscall __section_sysctl_vsyscall = 1; seqlock_t __xtime_lock __section_xtime_lock = SEQLOCK_UNLOCKED; @@ -274,7 +275,6 @@ static void __cpuinit cpu_vsyscall_init(void *arg) vsyscall_set_cpu(raw_smp_processor_id()); } -#ifdef CONFIG_HOTPLUG_CPU static int __cpuinit cpu_vsyscall_notifier(struct notifier_block *n, unsigned long action, void *arg) { @@ -283,13 +283,13 @@ cpu_vsyscall_notifier(struct notifier_block *n, unsigned long action, void *arg) smp_call_function_single(cpu, cpu_vsyscall_init, NULL, 0, 1); return NOTIFY_DONE; } -#endif static void __init map_vsyscall(void) { extern char __vsyscall_0; unsigned long physaddr_page0 = __pa_symbol(&__vsyscall_0); + /* Note that VSYSCALL_MAPPED_PAGES must agree with the code below. */ __set_fixmap(VSYSCALL_FIRST_PAGE, physaddr_page0, PAGE_KERNEL_VSYSCALL); } diff --git a/trunk/arch/x86_64/lib/csum-partial.c b/trunk/arch/x86_64/lib/csum-partial.c index 06ae630de82b..bc503f506903 100644 --- a/trunk/arch/x86_64/lib/csum-partial.c +++ b/trunk/arch/x86_64/lib/csum-partial.c @@ -9,8 +9,6 @@ #include #include -#define __force_inline inline __attribute__((always_inline)) - static inline unsigned short from32to16(unsigned a) { unsigned short b = a >> 16; @@ -33,7 +31,7 @@ static inline unsigned short from32to16(unsigned a) * Unrolling to an 128 bytes inner loop. * Using interleaving with more registers to break the carry chains. */ -static __force_inline unsigned do_csum(const unsigned char *buff, unsigned len) +static unsigned do_csum(const unsigned char *buff, unsigned len) { unsigned odd, count; unsigned long result = 0; diff --git a/trunk/arch/x86_64/lib/delay.c b/trunk/arch/x86_64/lib/delay.c index 50be90975d04..2dbebd308347 100644 --- a/trunk/arch/x86_64/lib/delay.c +++ b/trunk/arch/x86_64/lib/delay.c @@ -40,13 +40,13 @@ EXPORT_SYMBOL(__delay); inline void __const_udelay(unsigned long xloops) { - __delay((xloops * HZ * cpu_data[raw_smp_processor_id()].loops_per_jiffy) >> 32); + __delay(((xloops * HZ * cpu_data[raw_smp_processor_id()].loops_per_jiffy) >> 32) + 1); } EXPORT_SYMBOL(__const_udelay); void __udelay(unsigned long usecs) { - __const_udelay(usecs * 0x000010c6); /* 2**32 / 1000000 */ + __const_udelay(usecs * 0x000010c7); /* 2**32 / 1000000 (rounded up) */ } EXPORT_SYMBOL(__udelay); diff --git a/trunk/arch/x86_64/mm/fault.c b/trunk/arch/x86_64/mm/fault.c index 3751b4788e28..a65fc6f1dcaf 100644 --- a/trunk/arch/x86_64/mm/fault.c +++ b/trunk/arch/x86_64/mm/fault.c @@ -23,9 +23,9 @@ #include #include #include +#include #include -#include #include #include #include @@ -96,7 +96,7 @@ void bust_spinlocks(int yes) static noinline int is_prefetch(struct pt_regs *regs, unsigned long addr, unsigned long error_code) { - unsigned char __user *instr; + unsigned char *instr; int scan_more = 1; int prefetch = 0; unsigned char *max_instr; @@ -116,7 +116,7 @@ static noinline int is_prefetch(struct pt_regs *regs, unsigned long addr, unsigned char instr_hi; unsigned char instr_lo; - if (__get_user(opcode, (char __user *)instr)) + if (probe_kernel_address(instr, opcode)) break; instr_hi = opcode & 0xf0; @@ -154,7 +154,7 @@ static noinline int is_prefetch(struct pt_regs *regs, unsigned long addr, case 0x00: /* Prefetch instruction is 0x0F0D or 0x0F18 */ scan_more = 0; - if (__get_user(opcode, (char __user *)instr)) + if (probe_kernel_address(instr, opcode)) break; prefetch = (instr_lo == 0xF) && (opcode == 0x0D || opcode == 0x18); @@ -170,7 +170,7 @@ static noinline int is_prefetch(struct pt_regs *regs, unsigned long addr, static int bad_address(void *p) { unsigned long dummy; - return __get_user(dummy, (unsigned long __user *)p); + return probe_kernel_address((unsigned long *)p, dummy); } void dump_pagetable(unsigned long address) diff --git a/trunk/arch/x86_64/mm/init.c b/trunk/arch/x86_64/mm/init.c index 4c0c00ef3ca7..2968b90ef8ad 100644 --- a/trunk/arch/x86_64/mm/init.c +++ b/trunk/arch/x86_64/mm/init.c @@ -730,14 +730,15 @@ static __init int x8664_sysctl_init(void) __initcall(x8664_sysctl_init); #endif -/* A pseudo VMAs to allow ptrace access for the vsyscall page. This only +/* A pseudo VMA to allow ptrace access for the vsyscall page. This only covers the 64bit vsyscall page now. 32bit has a real VMA now and does not need special handling anymore. */ static struct vm_area_struct gate_vma = { .vm_start = VSYSCALL_START, - .vm_end = VSYSCALL_END, - .vm_page_prot = PAGE_READONLY + .vm_end = VSYSCALL_START + (VSYSCALL_MAPPED_PAGES << PAGE_SHIFT), + .vm_page_prot = PAGE_READONLY_EXEC, + .vm_flags = VM_READ | VM_EXEC }; struct vm_area_struct *get_gate_vma(struct task_struct *tsk) diff --git a/trunk/arch/x86_64/mm/pageattr.c b/trunk/arch/x86_64/mm/pageattr.c index 3e231d762aaa..ccb91dd996a9 100644 --- a/trunk/arch/x86_64/mm/pageattr.c +++ b/trunk/arch/x86_64/mm/pageattr.c @@ -61,34 +61,40 @@ static struct page *split_large_page(unsigned long address, pgprot_t prot, return base; } - -static void flush_kernel_map(void *address) +static void cache_flush_page(void *adr) { - if (0 && address && cpu_has_clflush) { - /* is this worth it? */ - int i; - for (i = 0; i < PAGE_SIZE; i += boot_cpu_data.x86_clflush_size) - asm volatile("clflush (%0)" :: "r" (address + i)); - } else - asm volatile("wbinvd":::"memory"); - if (address) - __flush_tlb_one(address); - else - __flush_tlb_all(); + int i; + for (i = 0; i < PAGE_SIZE; i += boot_cpu_data.x86_clflush_size) + asm volatile("clflush (%0)" :: "r" (adr + i)); } +static void flush_kernel_map(void *arg) +{ + struct list_head *l = (struct list_head *)arg; + struct page *pg; + + /* When clflush is available always use it because it is + much cheaper than WBINVD */ + if (!cpu_has_clflush) + asm volatile("wbinvd" ::: "memory"); + list_for_each_entry(pg, l, lru) { + void *adr = page_address(pg); + if (cpu_has_clflush) + cache_flush_page(adr); + __flush_tlb_one(adr); + } +} -static inline void flush_map(unsigned long address) +static inline void flush_map(struct list_head *l) { - on_each_cpu(flush_kernel_map, (void *)address, 1, 1); + on_each_cpu(flush_kernel_map, l, 1, 1); } -static struct page *deferred_pages; /* protected by init_mm.mmap_sem */ +static LIST_HEAD(deferred_pages); /* protected by init_mm.mmap_sem */ static inline void save_page(struct page *fpage) { - fpage->lru.next = (struct list_head *)deferred_pages; - deferred_pages = fpage; + list_add(&fpage->lru, &deferred_pages); } /* @@ -207,18 +213,18 @@ int change_page_attr(struct page *page, int numpages, pgprot_t prot) void global_flush_tlb(void) { - struct page *dpage; + struct page *pg, *next; + struct list_head l; down_read(&init_mm.mmap_sem); - dpage = xchg(&deferred_pages, NULL); + list_replace_init(&deferred_pages, &l); up_read(&init_mm.mmap_sem); - flush_map((dpage && !dpage->lru.next) ? (unsigned long)page_address(dpage) : 0); - while (dpage) { - struct page *tmp = dpage; - dpage = (struct page *)dpage->lru.next; - ClearPagePrivate(tmp); - __free_page(tmp); + flush_map(&l); + + list_for_each_entry_safe(pg, next, &l, lru) { + ClearPagePrivate(pg); + __free_page(pg); } } diff --git a/trunk/arch/xtensa/Kconfig b/trunk/arch/xtensa/Kconfig index c1e69a1f92a4..9eccfbd1b536 100644 --- a/trunk/arch/xtensa/Kconfig +++ b/trunk/arch/xtensa/Kconfig @@ -34,6 +34,14 @@ config GENERIC_HARDIRQS bool default y +config ARCH_HAS_ILOG2_U32 + bool + default n + +config ARCH_HAS_ILOG2_U64 + bool + default n + source "init/Kconfig" menu "Processor type and features" diff --git a/trunk/block/as-iosched.c b/trunk/block/as-iosched.c index 00242111a457..5934c4bfd52a 100644 --- a/trunk/block/as-iosched.c +++ b/trunk/block/as-iosched.c @@ -1274,9 +1274,10 @@ static void as_merged_requests(request_queue_t *q, struct request *req, * * FIXME! dispatch queue is not a queue at all! */ -static void as_work_handler(void *data) +static void as_work_handler(struct work_struct *work) { - struct request_queue *q = data; + struct as_data *ad = container_of(work, struct as_data, antic_work); + struct request_queue *q = ad->q; unsigned long flags; spin_lock_irqsave(q->queue_lock, flags); @@ -1332,7 +1333,7 @@ static void *as_init_queue(request_queue_t *q) ad->antic_timer.function = as_antic_timeout; ad->antic_timer.data = (unsigned long)q; init_timer(&ad->antic_timer); - INIT_WORK(&ad->antic_work, as_work_handler, q); + INIT_WORK(&ad->antic_work, as_work_handler); INIT_LIST_HEAD(&ad->fifo_list[REQ_SYNC]); INIT_LIST_HEAD(&ad->fifo_list[REQ_ASYNC]); diff --git a/trunk/block/blktrace.c b/trunk/block/blktrace.c index 74e02c04b2da..d3679dd1d220 100644 --- a/trunk/block/blktrace.c +++ b/trunk/block/blktrace.c @@ -394,8 +394,7 @@ static int blk_trace_setup(request_queue_t *q, struct block_device *bdev, if (bt) { if (bt->dropped_file) debugfs_remove(bt->dropped_file); - if (bt->sequence) - free_percpu(bt->sequence); + free_percpu(bt->sequence); if (bt->rchan) relay_close(bt->rchan); kfree(bt); diff --git a/trunk/block/cfq-iosched.c b/trunk/block/cfq-iosched.c index e9019ed39b73..78c6b312bd30 100644 --- a/trunk/block/cfq-iosched.c +++ b/trunk/block/cfq-iosched.c @@ -43,8 +43,8 @@ static int cfq_slice_idle = HZ / 125; #define RQ_CIC(rq) ((struct cfq_io_context*)(rq)->elevator_private) #define RQ_CFQQ(rq) ((rq)->elevator_private2) -static kmem_cache_t *cfq_pool; -static kmem_cache_t *cfq_ioc_pool; +static struct kmem_cache *cfq_pool; +static struct kmem_cache *cfq_ioc_pool; static DEFINE_PER_CPU(unsigned long, ioc_count); static struct completion *ioc_gone; @@ -1840,9 +1840,11 @@ cfq_set_request(request_queue_t *q, struct request *rq, gfp_t gfp_mask) return 1; } -static void cfq_kick_queue(void *data) +static void cfq_kick_queue(struct work_struct *work) { - request_queue_t *q = data; + struct cfq_data *cfqd = + container_of(work, struct cfq_data, unplug_work); + request_queue_t *q = cfqd->queue; unsigned long flags; spin_lock_irqsave(q->queue_lock, flags); @@ -1986,7 +1988,7 @@ static void *cfq_init_queue(request_queue_t *q) cfqd->idle_class_timer.function = cfq_idle_class_timer; cfqd->idle_class_timer.data = (unsigned long) cfqd; - INIT_WORK(&cfqd->unplug_work, cfq_kick_queue, q); + INIT_WORK(&cfqd->unplug_work, cfq_kick_queue); cfqd->cfq_quantum = cfq_quantum; cfqd->cfq_fifo_expire[0] = cfq_fifo_expire[0]; diff --git a/trunk/block/genhd.c b/trunk/block/genhd.c index 653919d50cd4..457fdac4c17d 100644 --- a/trunk/block/genhd.c +++ b/trunk/block/genhd.c @@ -417,6 +417,34 @@ static struct disk_attribute disk_attr_stat = { .show = disk_stats_read }; +#ifdef CONFIG_FAIL_MAKE_REQUEST + +static ssize_t disk_fail_store(struct gendisk * disk, + const char *buf, size_t count) +{ + int i; + + if (count > 0 && sscanf(buf, "%d", &i) > 0) { + if (i == 0) + disk->flags &= ~GENHD_FL_FAIL; + else + disk->flags |= GENHD_FL_FAIL; + } + + return count; +} +static ssize_t disk_fail_read(struct gendisk * disk, char *page) +{ + return sprintf(page, "%d\n", disk->flags & GENHD_FL_FAIL ? 1 : 0); +} +static struct disk_attribute disk_attr_fail = { + .attr = {.name = "make-it-fail", .mode = S_IRUGO | S_IWUSR }, + .store = disk_fail_store, + .show = disk_fail_read +}; + +#endif + static struct attribute * default_attrs[] = { &disk_attr_uevent.attr, &disk_attr_dev.attr, @@ -424,6 +452,9 @@ static struct attribute * default_attrs[] = { &disk_attr_removable.attr, &disk_attr_size.attr, &disk_attr_stat.attr, +#ifdef CONFIG_FAIL_MAKE_REQUEST + &disk_attr_fail.attr, +#endif NULL, }; diff --git a/trunk/block/ioctl.c b/trunk/block/ioctl.c index 58aab630dfc1..f6962b64660e 100644 --- a/trunk/block/ioctl.c +++ b/trunk/block/ioctl.c @@ -72,7 +72,7 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user bdevp = bdget_disk(disk, part); if (!bdevp) return -ENOMEM; - mutex_lock_nested(&bdevp->bd_mutex, BD_MUTEX_PARTITION); + mutex_lock(&bdevp->bd_mutex); if (bdevp->bd_openers) { mutex_unlock(&bdevp->bd_mutex); bdput(bdevp); @@ -82,7 +82,7 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user fsync_bdev(bdevp); invalidate_bdev(bdevp, 0); - mutex_lock_nested(&bdev->bd_mutex, BD_MUTEX_WHOLE); + mutex_lock(&bdev->bd_mutex); delete_partition(disk, part); mutex_unlock(&bdev->bd_mutex); mutex_unlock(&bdevp->bd_mutex); @@ -290,7 +290,7 @@ int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd, ENOIOCTLCMD for unknown ioctls. */ long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg) { - struct block_device *bdev = file->f_dentry->d_inode->i_bdev; + struct block_device *bdev = file->f_path.dentry->d_inode->i_bdev; struct gendisk *disk = bdev->bd_disk; int ret = -ENOIOCTLCMD; if (disk->fops->compat_ioctl) { diff --git a/trunk/block/ll_rw_blk.c b/trunk/block/ll_rw_blk.c index 0f82e12f7b67..4f83fd922377 100644 --- a/trunk/block/ll_rw_blk.c +++ b/trunk/block/ll_rw_blk.c @@ -28,13 +28,14 @@ #include #include #include +#include /* * for max sense size */ #include -static void blk_unplug_work(void *data); +static void blk_unplug_work(struct work_struct *work); static void blk_unplug_timeout(unsigned long data); static void drive_stat_acct(struct request *rq, int nr_sectors, int new_io); static void init_request_from_bio(struct request *req, struct bio *bio); @@ -44,17 +45,17 @@ static struct io_context *current_io_context(gfp_t gfp_flags, int node); /* * For the allocated request tables */ -static kmem_cache_t *request_cachep; +static struct kmem_cache *request_cachep; /* * For queue allocation */ -static kmem_cache_t *requestq_cachep; +static struct kmem_cache *requestq_cachep; /* * For io context allocations */ -static kmem_cache_t *iocontext_cachep; +static struct kmem_cache *iocontext_cachep; /* * Controlling structure to kblockd @@ -227,7 +228,7 @@ void blk_queue_make_request(request_queue_t * q, make_request_fn * mfn) if (q->unplug_delay == 0) q->unplug_delay = 1; - INIT_WORK(&q->unplug_work, blk_unplug_work, q); + INIT_WORK(&q->unplug_work, blk_unplug_work); q->unplug_timer.function = blk_unplug_timeout; q->unplug_timer.data = (unsigned long)q; @@ -1631,9 +1632,9 @@ static void blk_backing_dev_unplug(struct backing_dev_info *bdi, } } -static void blk_unplug_work(void *data) +static void blk_unplug_work(struct work_struct *work) { - request_queue_t *q = data; + request_queue_t *q = container_of(work, request_queue_t, unplug_work); blk_add_trace_pdu_int(q, BLK_TA_UNPLUG_IO, NULL, q->rq.count[READ] + q->rq.count[WRITE]); @@ -3056,6 +3057,42 @@ static void handle_bad_sector(struct bio *bio) set_bit(BIO_EOF, &bio->bi_flags); } +#ifdef CONFIG_FAIL_MAKE_REQUEST + +static DECLARE_FAULT_ATTR(fail_make_request); + +static int __init setup_fail_make_request(char *str) +{ + return setup_fault_attr(&fail_make_request, str); +} +__setup("fail_make_request=", setup_fail_make_request); + +static int should_fail_request(struct bio *bio) +{ + if ((bio->bi_bdev->bd_disk->flags & GENHD_FL_FAIL) || + (bio->bi_bdev->bd_part && bio->bi_bdev->bd_part->make_it_fail)) + return should_fail(&fail_make_request, bio->bi_size); + + return 0; +} + +static int __init fail_make_request_debugfs(void) +{ + return init_fault_attr_dentries(&fail_make_request, + "fail_make_request"); +} + +late_initcall(fail_make_request_debugfs); + +#else /* CONFIG_FAIL_MAKE_REQUEST */ + +static inline int should_fail_request(struct bio *bio) +{ + return 0; +} + +#endif /* CONFIG_FAIL_MAKE_REQUEST */ + /** * generic_make_request: hand a buffer to its device driver for I/O * @bio: The bio describing the location in memory and on the device. @@ -3141,6 +3178,9 @@ void generic_make_request(struct bio *bio) if (unlikely(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags))) goto end_io; + if (should_fail_request(bio)) + goto end_io; + /* * If this device has partitions, remap block n * of partition p to block n+start(p) of the disk. @@ -3459,8 +3499,6 @@ static void blk_done_softirq(struct softirq_action *h) } } -#ifdef CONFIG_HOTPLUG_CPU - static int blk_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu) { @@ -3486,8 +3524,6 @@ static struct notifier_block __devinitdata blk_cpu_notifier = { .notifier_call = blk_cpu_notify, }; -#endif /* CONFIG_HOTPLUG_CPU */ - /** * blk_complete_request - end I/O on a request * @req: the request being processed diff --git a/trunk/block/scsi_ioctl.c b/trunk/block/scsi_ioctl.c index 5493c2fbbab1..b3e210723a71 100644 --- a/trunk/block/scsi_ioctl.c +++ b/trunk/block/scsi_ioctl.c @@ -277,7 +277,7 @@ static int sg_io(struct file *file, request_queue_t *q, if (rq->bio) blk_queue_bounce(q, &rq->bio); - rq->timeout = (hdr->timeout * HZ) / 1000; + rq->timeout = jiffies_to_msecs(hdr->timeout); if (!rq->timeout) rq->timeout = q->sg_timeout; if (!rq->timeout) diff --git a/trunk/crypto/Kconfig b/trunk/crypto/Kconfig index cbae8392ce11..92ba249f3a5b 100644 --- a/trunk/crypto/Kconfig +++ b/trunk/crypto/Kconfig @@ -39,6 +39,17 @@ config CRYPTO_HMAC HMAC: Keyed-Hashing for Message Authentication (RFC2104). This is required for IPSec. +config CRYPTO_XCBC + tristate "XCBC support" + depends on EXPERIMENTAL + select CRYPTO_HASH + select CRYPTO_MANAGER + help + XCBC: Keyed-Hashing with encryption algorithm + http://www.ietf.org/rfc/rfc3566.txt + http://csrc.nist.gov/encryption/modes/proposedmodes/ + xcbc-mac/xcbc-mac-spec.pdf + config CRYPTO_NULL tristate "Null algorithms" select CRYPTO_ALGAPI @@ -128,6 +139,16 @@ config CRYPTO_TGR192 See also: . +config CRYPTO_GF128MUL + tristate "GF(2^128) multiplication functions (EXPERIMENTAL)" + depends on EXPERIMENTAL + help + Efficient table driven implementation of multiplications in the + field GF(2^128). This is needed by some cypher modes. This + option will be selected automatically if you select such a + cipher mode. Only select this option by hand if you expect to load + an external module that requires these functions. + config CRYPTO_ECB tristate "ECB support" select CRYPTO_BLKCIPHER @@ -147,6 +168,19 @@ config CRYPTO_CBC CBC: Cipher Block Chaining mode This block cipher algorithm is required for IPSec. +config CRYPTO_LRW + tristate "LRW support (EXPERIMENTAL)" + depends on EXPERIMENTAL + select CRYPTO_BLKCIPHER + select CRYPTO_MANAGER + select CRYPTO_GF128MUL + help + LRW: Liskov Rivest Wagner, a tweakable, non malleable, non movable + narrow block cipher mode for dm-crypt. Use it with cipher + specification string aes-lrw-benbi, the key must be 256, 320 or 384. + The first 128, 192 or 256 bits in the key are used for AES and the + rest is used to tie each cipher block to its logical position. + config CRYPTO_DES tristate "DES and Triple DES EDE cipher algorithms" select CRYPTO_ALGAPI diff --git a/trunk/crypto/Makefile b/trunk/crypto/Makefile index 72366208e291..60e3d24f61f5 100644 --- a/trunk/crypto/Makefile +++ b/trunk/crypto/Makefile @@ -15,6 +15,7 @@ obj-$(CONFIG_CRYPTO_HASH) += crypto_hash.o obj-$(CONFIG_CRYPTO_MANAGER) += cryptomgr.o obj-$(CONFIG_CRYPTO_HMAC) += hmac.o +obj-$(CONFIG_CRYPTO_XCBC) += xcbc.o obj-$(CONFIG_CRYPTO_NULL) += crypto_null.o obj-$(CONFIG_CRYPTO_MD4) += md4.o obj-$(CONFIG_CRYPTO_MD5) += md5.o @@ -23,8 +24,10 @@ obj-$(CONFIG_CRYPTO_SHA256) += sha256.o obj-$(CONFIG_CRYPTO_SHA512) += sha512.o obj-$(CONFIG_CRYPTO_WP512) += wp512.o obj-$(CONFIG_CRYPTO_TGR192) += tgr192.o +obj-$(CONFIG_CRYPTO_GF128MUL) += gf128mul.o obj-$(CONFIG_CRYPTO_ECB) += ecb.o obj-$(CONFIG_CRYPTO_CBC) += cbc.o +obj-$(CONFIG_CRYPTO_LRW) += lrw.o obj-$(CONFIG_CRYPTO_DES) += des.o obj-$(CONFIG_CRYPTO_BLOWFISH) += blowfish.o obj-$(CONFIG_CRYPTO_TWOFISH) += twofish.o diff --git a/trunk/crypto/api.c b/trunk/crypto/api.c index 4fb7fa45cb0d..8c446871cd5b 100644 --- a/trunk/crypto/api.c +++ b/trunk/crypto/api.c @@ -466,23 +466,8 @@ void crypto_free_tfm(struct crypto_tfm *tfm) kfree(tfm); } -int crypto_alg_available(const char *name, u32 flags) -{ - int ret = 0; - struct crypto_alg *alg = crypto_alg_mod_lookup(name, 0, - CRYPTO_ALG_ASYNC); - - if (!IS_ERR(alg)) { - crypto_mod_put(alg); - ret = 1; - } - - return ret; -} - EXPORT_SYMBOL_GPL(crypto_alloc_tfm); EXPORT_SYMBOL_GPL(crypto_free_tfm); -EXPORT_SYMBOL_GPL(crypto_alg_available); int crypto_has_alg(const char *name, u32 type, u32 mask) { diff --git a/trunk/crypto/cryptomgr.c b/trunk/crypto/cryptomgr.c index 9b5b15601068..2ebffb84f1d9 100644 --- a/trunk/crypto/cryptomgr.c +++ b/trunk/crypto/cryptomgr.c @@ -40,9 +40,10 @@ struct cryptomgr_param { char template[CRYPTO_MAX_ALG_NAME]; }; -static void cryptomgr_probe(void *data) +static void cryptomgr_probe(struct work_struct *work) { - struct cryptomgr_param *param = data; + struct cryptomgr_param *param = + container_of(work, struct cryptomgr_param, work); struct crypto_template *tmpl; struct crypto_instance *inst; int err; @@ -112,7 +113,7 @@ static int cryptomgr_schedule_probe(struct crypto_larval *larval) param->larval.type = larval->alg.cra_flags; param->larval.mask = larval->mask; - INIT_WORK(¶m->work, cryptomgr_probe, param); + INIT_WORK(¶m->work, cryptomgr_probe); schedule_work(¶m->work); return NOTIFY_STOP; diff --git a/trunk/crypto/digest.c b/trunk/crypto/digest.c index 0155a94e4b15..8f4593268ce0 100644 --- a/trunk/crypto/digest.c +++ b/trunk/crypto/digest.c @@ -21,54 +21,6 @@ #include "internal.h" #include "scatterwalk.h" -void crypto_digest_init(struct crypto_tfm *tfm) -{ - struct crypto_hash *hash = crypto_hash_cast(tfm); - struct hash_desc desc = { .tfm = hash, .flags = tfm->crt_flags }; - - crypto_hash_init(&desc); -} -EXPORT_SYMBOL_GPL(crypto_digest_init); - -void crypto_digest_update(struct crypto_tfm *tfm, - struct scatterlist *sg, unsigned int nsg) -{ - struct crypto_hash *hash = crypto_hash_cast(tfm); - struct hash_desc desc = { .tfm = hash, .flags = tfm->crt_flags }; - unsigned int nbytes = 0; - unsigned int i; - - for (i = 0; i < nsg; i++) - nbytes += sg[i].length; - - crypto_hash_update(&desc, sg, nbytes); -} -EXPORT_SYMBOL_GPL(crypto_digest_update); - -void crypto_digest_final(struct crypto_tfm *tfm, u8 *out) -{ - struct crypto_hash *hash = crypto_hash_cast(tfm); - struct hash_desc desc = { .tfm = hash, .flags = tfm->crt_flags }; - - crypto_hash_final(&desc, out); -} -EXPORT_SYMBOL_GPL(crypto_digest_final); - -void crypto_digest_digest(struct crypto_tfm *tfm, - struct scatterlist *sg, unsigned int nsg, u8 *out) -{ - struct crypto_hash *hash = crypto_hash_cast(tfm); - struct hash_desc desc = { .tfm = hash, .flags = tfm->crt_flags }; - unsigned int nbytes = 0; - unsigned int i; - - for (i = 0; i < nsg; i++) - nbytes += sg[i].length; - - crypto_hash_digest(&desc, sg, nbytes, out); -} -EXPORT_SYMBOL_GPL(crypto_digest_digest); - static int init(struct hash_desc *desc) { struct crypto_tfm *tfm = crypto_hash_tfm(desc->tfm); diff --git a/trunk/crypto/gf128mul.c b/trunk/crypto/gf128mul.c new file mode 100644 index 000000000000..0a2aadfa1d85 --- /dev/null +++ b/trunk/crypto/gf128mul.c @@ -0,0 +1,466 @@ +/* gf128mul.c - GF(2^128) multiplication functions + * + * Copyright (c) 2003, Dr Brian Gladman, Worcester, UK. + * Copyright (c) 2006, Rik Snel + * + * Based on Dr Brian Gladman's (GPL'd) work published at + * http://fp.gladman.plus.com/cryptography_technology/index.htm + * See the original copyright notice below. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + */ + +/* + --------------------------------------------------------------------------- + Copyright (c) 2003, Dr Brian Gladman, Worcester, UK. All rights reserved. + + LICENSE TERMS + + The free distribution and use of this software in both source and binary + form is allowed (with or without changes) provided that: + + 1. distributions of this source code include the above copyright + notice, this list of conditions and the following disclaimer; + + 2. distributions in binary form include the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other associated materials; + + 3. the copyright holder's name is not used to endorse products + built using this software without specific written permission. + + ALTERNATIVELY, provided that this notice is retained in full, this product + may be distributed under the terms of the GNU General Public License (GPL), + in which case the provisions of the GPL apply INSTEAD OF those given above. + + DISCLAIMER + + This software is provided 'as is' with no explicit or implied warranties + in respect of its properties, including, but not limited to, correctness + and/or fitness for purpose. + --------------------------------------------------------------------------- + Issue 31/01/2006 + + This file provides fast multiplication in GF(128) as required by several + cryptographic authentication modes +*/ + +#include +#include +#include +#include + +#define gf128mul_dat(q) { \ + q(0x00), q(0x01), q(0x02), q(0x03), q(0x04), q(0x05), q(0x06), q(0x07),\ + q(0x08), q(0x09), q(0x0a), q(0x0b), q(0x0c), q(0x0d), q(0x0e), q(0x0f),\ + q(0x10), q(0x11), q(0x12), q(0x13), q(0x14), q(0x15), q(0x16), q(0x17),\ + q(0x18), q(0x19), q(0x1a), q(0x1b), q(0x1c), q(0x1d), q(0x1e), q(0x1f),\ + q(0x20), q(0x21), q(0x22), q(0x23), q(0x24), q(0x25), q(0x26), q(0x27),\ + q(0x28), q(0x29), q(0x2a), q(0x2b), q(0x2c), q(0x2d), q(0x2e), q(0x2f),\ + q(0x30), q(0x31), q(0x32), q(0x33), q(0x34), q(0x35), q(0x36), q(0x37),\ + q(0x38), q(0x39), q(0x3a), q(0x3b), q(0x3c), q(0x3d), q(0x3e), q(0x3f),\ + q(0x40), q(0x41), q(0x42), q(0x43), q(0x44), q(0x45), q(0x46), q(0x47),\ + q(0x48), q(0x49), q(0x4a), q(0x4b), q(0x4c), q(0x4d), q(0x4e), q(0x4f),\ + q(0x50), q(0x51), q(0x52), q(0x53), q(0x54), q(0x55), q(0x56), q(0x57),\ + q(0x58), q(0x59), q(0x5a), q(0x5b), q(0x5c), q(0x5d), q(0x5e), q(0x5f),\ + q(0x60), q(0x61), q(0x62), q(0x63), q(0x64), q(0x65), q(0x66), q(0x67),\ + q(0x68), q(0x69), q(0x6a), q(0x6b), q(0x6c), q(0x6d), q(0x6e), q(0x6f),\ + q(0x70), q(0x71), q(0x72), q(0x73), q(0x74), q(0x75), q(0x76), q(0x77),\ + q(0x78), q(0x79), q(0x7a), q(0x7b), q(0x7c), q(0x7d), q(0x7e), q(0x7f),\ + q(0x80), q(0x81), q(0x82), q(0x83), q(0x84), q(0x85), q(0x86), q(0x87),\ + q(0x88), q(0x89), q(0x8a), q(0x8b), q(0x8c), q(0x8d), q(0x8e), q(0x8f),\ + q(0x90), q(0x91), q(0x92), q(0x93), q(0x94), q(0x95), q(0x96), q(0x97),\ + q(0x98), q(0x99), q(0x9a), q(0x9b), q(0x9c), q(0x9d), q(0x9e), q(0x9f),\ + q(0xa0), q(0xa1), q(0xa2), q(0xa3), q(0xa4), q(0xa5), q(0xa6), q(0xa7),\ + q(0xa8), q(0xa9), q(0xaa), q(0xab), q(0xac), q(0xad), q(0xae), q(0xaf),\ + q(0xb0), q(0xb1), q(0xb2), q(0xb3), q(0xb4), q(0xb5), q(0xb6), q(0xb7),\ + q(0xb8), q(0xb9), q(0xba), q(0xbb), q(0xbc), q(0xbd), q(0xbe), q(0xbf),\ + q(0xc0), q(0xc1), q(0xc2), q(0xc3), q(0xc4), q(0xc5), q(0xc6), q(0xc7),\ + q(0xc8), q(0xc9), q(0xca), q(0xcb), q(0xcc), q(0xcd), q(0xce), q(0xcf),\ + q(0xd0), q(0xd1), q(0xd2), q(0xd3), q(0xd4), q(0xd5), q(0xd6), q(0xd7),\ + q(0xd8), q(0xd9), q(0xda), q(0xdb), q(0xdc), q(0xdd), q(0xde), q(0xdf),\ + q(0xe0), q(0xe1), q(0xe2), q(0xe3), q(0xe4), q(0xe5), q(0xe6), q(0xe7),\ + q(0xe8), q(0xe9), q(0xea), q(0xeb), q(0xec), q(0xed), q(0xee), q(0xef),\ + q(0xf0), q(0xf1), q(0xf2), q(0xf3), q(0xf4), q(0xf5), q(0xf6), q(0xf7),\ + q(0xf8), q(0xf9), q(0xfa), q(0xfb), q(0xfc), q(0xfd), q(0xfe), q(0xff) \ +} + +/* Given the value i in 0..255 as the byte overflow when a field element + in GHASH is multipled by x^8, this function will return the values that + are generated in the lo 16-bit word of the field value by applying the + modular polynomial. The values lo_byte and hi_byte are returned via the + macro xp_fun(lo_byte, hi_byte) so that the values can be assembled into + memory as required by a suitable definition of this macro operating on + the table above +*/ + +#define xx(p, q) 0x##p##q + +#define xda_bbe(i) ( \ + (i & 0x80 ? xx(43, 80) : 0) ^ (i & 0x40 ? xx(21, c0) : 0) ^ \ + (i & 0x20 ? xx(10, e0) : 0) ^ (i & 0x10 ? xx(08, 70) : 0) ^ \ + (i & 0x08 ? xx(04, 38) : 0) ^ (i & 0x04 ? xx(02, 1c) : 0) ^ \ + (i & 0x02 ? xx(01, 0e) : 0) ^ (i & 0x01 ? xx(00, 87) : 0) \ +) + +#define xda_lle(i) ( \ + (i & 0x80 ? xx(e1, 00) : 0) ^ (i & 0x40 ? xx(70, 80) : 0) ^ \ + (i & 0x20 ? xx(38, 40) : 0) ^ (i & 0x10 ? xx(1c, 20) : 0) ^ \ + (i & 0x08 ? xx(0e, 10) : 0) ^ (i & 0x04 ? xx(07, 08) : 0) ^ \ + (i & 0x02 ? xx(03, 84) : 0) ^ (i & 0x01 ? xx(01, c2) : 0) \ +) + +static const u16 gf128mul_table_lle[256] = gf128mul_dat(xda_lle); +static const u16 gf128mul_table_bbe[256] = gf128mul_dat(xda_bbe); + +/* These functions multiply a field element by x, by x^4 and by x^8 + * in the polynomial field representation. It uses 32-bit word operations + * to gain speed but compensates for machine endianess and hence works + * correctly on both styles of machine. + */ + +static void gf128mul_x_lle(be128 *r, const be128 *x) +{ + u64 a = be64_to_cpu(x->a); + u64 b = be64_to_cpu(x->b); + u64 _tt = gf128mul_table_lle[(b << 7) & 0xff]; + + r->b = cpu_to_be64((b >> 1) | (a << 63)); + r->a = cpu_to_be64((a >> 1) ^ (_tt << 48)); +} + +static void gf128mul_x_bbe(be128 *r, const be128 *x) +{ + u64 a = be64_to_cpu(x->a); + u64 b = be64_to_cpu(x->b); + u64 _tt = gf128mul_table_bbe[a >> 63]; + + r->a = cpu_to_be64((a << 1) | (b >> 63)); + r->b = cpu_to_be64((b << 1) ^ _tt); +} + +static void gf128mul_x8_lle(be128 *x) +{ + u64 a = be64_to_cpu(x->a); + u64 b = be64_to_cpu(x->b); + u64 _tt = gf128mul_table_lle[b & 0xff]; + + x->b = cpu_to_be64((b >> 8) | (a << 56)); + x->a = cpu_to_be64((a >> 8) ^ (_tt << 48)); +} + +static void gf128mul_x8_bbe(be128 *x) +{ + u64 a = be64_to_cpu(x->a); + u64 b = be64_to_cpu(x->b); + u64 _tt = gf128mul_table_bbe[a >> 56]; + + x->a = cpu_to_be64((a << 8) | (b >> 56)); + x->b = cpu_to_be64((b << 8) ^ _tt); +} + +void gf128mul_lle(be128 *r, const be128 *b) +{ + be128 p[8]; + int i; + + p[0] = *r; + for (i = 0; i < 7; ++i) + gf128mul_x_lle(&p[i + 1], &p[i]); + + memset(r, 0, sizeof(r)); + for (i = 0;;) { + u8 ch = ((u8 *)b)[15 - i]; + + if (ch & 0x80) + be128_xor(r, r, &p[0]); + if (ch & 0x40) + be128_xor(r, r, &p[1]); + if (ch & 0x20) + be128_xor(r, r, &p[2]); + if (ch & 0x10) + be128_xor(r, r, &p[3]); + if (ch & 0x08) + be128_xor(r, r, &p[4]); + if (ch & 0x04) + be128_xor(r, r, &p[5]); + if (ch & 0x02) + be128_xor(r, r, &p[6]); + if (ch & 0x01) + be128_xor(r, r, &p[7]); + + if (++i >= 16) + break; + + gf128mul_x8_lle(r); + } +} +EXPORT_SYMBOL(gf128mul_lle); + +void gf128mul_bbe(be128 *r, const be128 *b) +{ + be128 p[8]; + int i; + + p[0] = *r; + for (i = 0; i < 7; ++i) + gf128mul_x_bbe(&p[i + 1], &p[i]); + + memset(r, 0, sizeof(r)); + for (i = 0;;) { + u8 ch = ((u8 *)b)[i]; + + if (ch & 0x80) + be128_xor(r, r, &p[7]); + if (ch & 0x40) + be128_xor(r, r, &p[6]); + if (ch & 0x20) + be128_xor(r, r, &p[5]); + if (ch & 0x10) + be128_xor(r, r, &p[4]); + if (ch & 0x08) + be128_xor(r, r, &p[3]); + if (ch & 0x04) + be128_xor(r, r, &p[2]); + if (ch & 0x02) + be128_xor(r, r, &p[1]); + if (ch & 0x01) + be128_xor(r, r, &p[0]); + + if (++i >= 16) + break; + + gf128mul_x8_bbe(r); + } +} +EXPORT_SYMBOL(gf128mul_bbe); + +/* This version uses 64k bytes of table space. + A 16 byte buffer has to be multiplied by a 16 byte key + value in GF(128). If we consider a GF(128) value in + the buffer's lowest byte, we can construct a table of + the 256 16 byte values that result from the 256 values + of this byte. This requires 4096 bytes. But we also + need tables for each of the 16 higher bytes in the + buffer as well, which makes 64 kbytes in total. +*/ +/* additional explanation + * t[0][BYTE] contains g*BYTE + * t[1][BYTE] contains g*x^8*BYTE + * .. + * t[15][BYTE] contains g*x^120*BYTE */ +struct gf128mul_64k *gf128mul_init_64k_lle(const be128 *g) +{ + struct gf128mul_64k *t; + int i, j, k; + + t = kzalloc(sizeof(*t), GFP_KERNEL); + if (!t) + goto out; + + for (i = 0; i < 16; i++) { + t->t[i] = kzalloc(sizeof(*t->t[i]), GFP_KERNEL); + if (!t->t[i]) { + gf128mul_free_64k(t); + t = NULL; + goto out; + } + } + + t->t[0]->t[128] = *g; + for (j = 64; j > 0; j >>= 1) + gf128mul_x_lle(&t->t[0]->t[j], &t->t[0]->t[j + j]); + + for (i = 0;;) { + for (j = 2; j < 256; j += j) + for (k = 1; k < j; ++k) + be128_xor(&t->t[i]->t[j + k], + &t->t[i]->t[j], &t->t[i]->t[k]); + + if (++i >= 16) + break; + + for (j = 128; j > 0; j >>= 1) { + t->t[i]->t[j] = t->t[i - 1]->t[j]; + gf128mul_x8_lle(&t->t[i]->t[j]); + } + } + +out: + return t; +} +EXPORT_SYMBOL(gf128mul_init_64k_lle); + +struct gf128mul_64k *gf128mul_init_64k_bbe(const be128 *g) +{ + struct gf128mul_64k *t; + int i, j, k; + + t = kzalloc(sizeof(*t), GFP_KERNEL); + if (!t) + goto out; + + for (i = 0; i < 16; i++) { + t->t[i] = kzalloc(sizeof(*t->t[i]), GFP_KERNEL); + if (!t->t[i]) { + gf128mul_free_64k(t); + t = NULL; + goto out; + } + } + + t->t[0]->t[1] = *g; + for (j = 1; j <= 64; j <<= 1) + gf128mul_x_bbe(&t->t[0]->t[j + j], &t->t[0]->t[j]); + + for (i = 0;;) { + for (j = 2; j < 256; j += j) + for (k = 1; k < j; ++k) + be128_xor(&t->t[i]->t[j + k], + &t->t[i]->t[j], &t->t[i]->t[k]); + + if (++i >= 16) + break; + + for (j = 128; j > 0; j >>= 1) { + t->t[i]->t[j] = t->t[i - 1]->t[j]; + gf128mul_x8_bbe(&t->t[i]->t[j]); + } + } + +out: + return t; +} +EXPORT_SYMBOL(gf128mul_init_64k_bbe); + +void gf128mul_free_64k(struct gf128mul_64k *t) +{ + int i; + + for (i = 0; i < 16; i++) + kfree(t->t[i]); + kfree(t); +} +EXPORT_SYMBOL(gf128mul_free_64k); + +void gf128mul_64k_lle(be128 *a, struct gf128mul_64k *t) +{ + u8 *ap = (u8 *)a; + be128 r[1]; + int i; + + *r = t->t[0]->t[ap[0]]; + for (i = 1; i < 16; ++i) + be128_xor(r, r, &t->t[i]->t[ap[i]]); + *a = *r; +} +EXPORT_SYMBOL(gf128mul_64k_lle); + +void gf128mul_64k_bbe(be128 *a, struct gf128mul_64k *t) +{ + u8 *ap = (u8 *)a; + be128 r[1]; + int i; + + *r = t->t[0]->t[ap[15]]; + for (i = 1; i < 16; ++i) + be128_xor(r, r, &t->t[i]->t[ap[15 - i]]); + *a = *r; +} +EXPORT_SYMBOL(gf128mul_64k_bbe); + +/* This version uses 4k bytes of table space. + A 16 byte buffer has to be multiplied by a 16 byte key + value in GF(128). If we consider a GF(128) value in a + single byte, we can construct a table of the 256 16 byte + values that result from the 256 values of this byte. + This requires 4096 bytes. If we take the highest byte in + the buffer and use this table to get the result, we then + have to multiply by x^120 to get the final value. For the + next highest byte the result has to be multiplied by x^112 + and so on. But we can do this by accumulating the result + in an accumulator starting with the result for the top + byte. We repeatedly multiply the accumulator value by + x^8 and then add in (i.e. xor) the 16 bytes of the next + lower byte in the buffer, stopping when we reach the + lowest byte. This requires a 4096 byte table. +*/ +struct gf128mul_4k *gf128mul_init_4k_lle(const be128 *g) +{ + struct gf128mul_4k *t; + int j, k; + + t = kzalloc(sizeof(*t), GFP_KERNEL); + if (!t) + goto out; + + t->t[128] = *g; + for (j = 64; j > 0; j >>= 1) + gf128mul_x_lle(&t->t[j], &t->t[j+j]); + + for (j = 2; j < 256; j += j) + for (k = 1; k < j; ++k) + be128_xor(&t->t[j + k], &t->t[j], &t->t[k]); + +out: + return t; +} +EXPORT_SYMBOL(gf128mul_init_4k_lle); + +struct gf128mul_4k *gf128mul_init_4k_bbe(const be128 *g) +{ + struct gf128mul_4k *t; + int j, k; + + t = kzalloc(sizeof(*t), GFP_KERNEL); + if (!t) + goto out; + + t->t[1] = *g; + for (j = 1; j <= 64; j <<= 1) + gf128mul_x_bbe(&t->t[j + j], &t->t[j]); + + for (j = 2; j < 256; j += j) + for (k = 1; k < j; ++k) + be128_xor(&t->t[j + k], &t->t[j], &t->t[k]); + +out: + return t; +} +EXPORT_SYMBOL(gf128mul_init_4k_bbe); + +void gf128mul_4k_lle(be128 *a, struct gf128mul_4k *t) +{ + u8 *ap = (u8 *)a; + be128 r[1]; + int i = 15; + + *r = t->t[ap[15]]; + while (i--) { + gf128mul_x8_lle(r); + be128_xor(r, r, &t->t[ap[i]]); + } + *a = *r; +} +EXPORT_SYMBOL(gf128mul_4k_lle); + +void gf128mul_4k_bbe(be128 *a, struct gf128mul_4k *t) +{ + u8 *ap = (u8 *)a; + be128 r[1]; + int i = 0; + + *r = t->t[ap[0]]; + while (++i < 16) { + gf128mul_x8_bbe(r); + be128_xor(r, r, &t->t[ap[i]]); + } + *a = *r; +} +EXPORT_SYMBOL(gf128mul_4k_bbe); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Functions for multiplying elements of GF(2^128)"); diff --git a/trunk/crypto/lrw.c b/trunk/crypto/lrw.c new file mode 100644 index 000000000000..56642586d84f --- /dev/null +++ b/trunk/crypto/lrw.c @@ -0,0 +1,301 @@ +/* LRW: as defined by Cyril Guyot in + * http://grouper.ieee.org/groups/1619/email/pdf00017.pdf + * + * Copyright (c) 2006 Rik Snel + * + * Based om ecb.c + * Copyright (c) 2006 Herbert Xu + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + */ +/* This implementation is checked against the test vectors in the above + * document and by a test vector provided by Ken Buchanan at + * http://www.mail-archive.com/stds-p1619@listserv.ieee.org/msg00173.html + * + * The test vectors are included in the testing module tcrypt.[ch] */ +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +struct priv { + struct crypto_cipher *child; + /* optimizes multiplying a random (non incrementing, as at the + * start of a new sector) value with key2, we could also have + * used 4k optimization tables or no optimization at all. In the + * latter case we would have to store key2 here */ + struct gf128mul_64k *table; + /* stores: + * key2*{ 0,0,...0,0,0,0,1 }, key2*{ 0,0,...0,0,0,1,1 }, + * key2*{ 0,0,...0,0,1,1,1 }, key2*{ 0,0,...0,1,1,1,1 } + * key2*{ 0,0,...1,1,1,1,1 }, etc + * needed for optimized multiplication of incrementing values + * with key2 */ + be128 mulinc[128]; +}; + +static inline void setbit128_bbe(void *b, int bit) +{ + __set_bit(bit ^ 0x78, b); +} + +static int setkey(struct crypto_tfm *parent, const u8 *key, + unsigned int keylen) +{ + struct priv *ctx = crypto_tfm_ctx(parent); + struct crypto_cipher *child = ctx->child; + int err, i; + be128 tmp = { 0 }; + int bsize = crypto_cipher_blocksize(child); + + crypto_cipher_clear_flags(child, CRYPTO_TFM_REQ_MASK); + crypto_cipher_set_flags(child, crypto_tfm_get_flags(parent) & + CRYPTO_TFM_REQ_MASK); + if ((err = crypto_cipher_setkey(child, key, keylen - bsize))) + return err; + crypto_tfm_set_flags(parent, crypto_cipher_get_flags(child) & + CRYPTO_TFM_RES_MASK); + + if (ctx->table) + gf128mul_free_64k(ctx->table); + + /* initialize multiplication table for Key2 */ + ctx->table = gf128mul_init_64k_bbe((be128 *)(key + keylen - bsize)); + if (!ctx->table) + return -ENOMEM; + + /* initialize optimization table */ + for (i = 0; i < 128; i++) { + setbit128_bbe(&tmp, i); + ctx->mulinc[i] = tmp; + gf128mul_64k_bbe(&ctx->mulinc[i], ctx->table); + } + + return 0; +} + +struct sinfo { + be128 t; + struct crypto_tfm *tfm; + void (*fn)(struct crypto_tfm *, u8 *, const u8 *); +}; + +static inline void inc(be128 *iv) +{ + if (!(iv->b = cpu_to_be64(be64_to_cpu(iv->b) + 1))) + iv->a = cpu_to_be64(be64_to_cpu(iv->a) + 1); +} + +static inline void lrw_round(struct sinfo *s, void *dst, const void *src) +{ + be128_xor(dst, &s->t, src); /* PP <- T xor P */ + s->fn(s->tfm, dst, dst); /* CC <- E(Key2,PP) */ + be128_xor(dst, dst, &s->t); /* C <- T xor CC */ +} + +/* this returns the number of consequative 1 bits starting + * from the right, get_index128(00 00 00 00 00 00 ... 00 00 10 FB) = 2 */ +static inline int get_index128(be128 *block) +{ + int x; + __be32 *p = (__be32 *) block; + + for (p += 3, x = 0; x < 128; p--, x += 32) { + u32 val = be32_to_cpup(p); + + if (!~val) + continue; + + return x + ffz(val); + } + + return x; +} + +static int crypt(struct blkcipher_desc *d, + struct blkcipher_walk *w, struct priv *ctx, + void (*fn)(struct crypto_tfm *, u8 *, const u8 *)) +{ + int err; + unsigned int avail; + const int bs = crypto_cipher_blocksize(ctx->child); + struct sinfo s = { + .tfm = crypto_cipher_tfm(ctx->child), + .fn = fn + }; + be128 *iv; + u8 *wsrc; + u8 *wdst; + + err = blkcipher_walk_virt(d, w); + if (!(avail = w->nbytes)) + return err; + + wsrc = w->src.virt.addr; + wdst = w->dst.virt.addr; + + /* calculate first value of T */ + iv = (be128 *)w->iv; + s.t = *iv; + + /* T <- I*Key2 */ + gf128mul_64k_bbe(&s.t, ctx->table); + + goto first; + + for (;;) { + do { + /* T <- I*Key2, using the optimization + * discussed in the specification */ + be128_xor(&s.t, &s.t, &ctx->mulinc[get_index128(iv)]); + inc(iv); + +first: + lrw_round(&s, wdst, wsrc); + + wsrc += bs; + wdst += bs; + } while ((avail -= bs) >= bs); + + err = blkcipher_walk_done(d, w, avail); + if (!(avail = w->nbytes)) + break; + + wsrc = w->src.virt.addr; + wdst = w->dst.virt.addr; + } + + return err; +} + +static int encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes) +{ + struct priv *ctx = crypto_blkcipher_ctx(desc->tfm); + struct blkcipher_walk w; + + blkcipher_walk_init(&w, dst, src, nbytes); + return crypt(desc, &w, ctx, + crypto_cipher_alg(ctx->child)->cia_encrypt); +} + +static int decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes) +{ + struct priv *ctx = crypto_blkcipher_ctx(desc->tfm); + struct blkcipher_walk w; + + blkcipher_walk_init(&w, dst, src, nbytes); + return crypt(desc, &w, ctx, + crypto_cipher_alg(ctx->child)->cia_decrypt); +} + +static int init_tfm(struct crypto_tfm *tfm) +{ + struct crypto_instance *inst = (void *)tfm->__crt_alg; + struct crypto_spawn *spawn = crypto_instance_ctx(inst); + struct priv *ctx = crypto_tfm_ctx(tfm); + u32 *flags = &tfm->crt_flags; + + tfm = crypto_spawn_tfm(spawn); + if (IS_ERR(tfm)) + return PTR_ERR(tfm); + + if (crypto_tfm_alg_blocksize(tfm) != 16) { + *flags |= CRYPTO_TFM_RES_BAD_BLOCK_LEN; + return -EINVAL; + } + + ctx->child = crypto_cipher_cast(tfm); + return 0; +} + +static void exit_tfm(struct crypto_tfm *tfm) +{ + struct priv *ctx = crypto_tfm_ctx(tfm); + if (ctx->table) + gf128mul_free_64k(ctx->table); + crypto_free_cipher(ctx->child); +} + +static struct crypto_instance *alloc(void *param, unsigned int len) +{ + struct crypto_instance *inst; + struct crypto_alg *alg; + + alg = crypto_get_attr_alg(param, len, CRYPTO_ALG_TYPE_CIPHER, + CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC); + if (IS_ERR(alg)) + return ERR_PTR(PTR_ERR(alg)); + + inst = crypto_alloc_instance("lrw", alg); + if (IS_ERR(inst)) + goto out_put_alg; + + inst->alg.cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER; + inst->alg.cra_priority = alg->cra_priority; + inst->alg.cra_blocksize = alg->cra_blocksize; + + if (alg->cra_alignmask < 7) inst->alg.cra_alignmask = 7; + else inst->alg.cra_alignmask = alg->cra_alignmask; + inst->alg.cra_type = &crypto_blkcipher_type; + + if (!(alg->cra_blocksize % 4)) + inst->alg.cra_alignmask |= 3; + inst->alg.cra_blkcipher.ivsize = alg->cra_blocksize; + inst->alg.cra_blkcipher.min_keysize = + alg->cra_cipher.cia_min_keysize + alg->cra_blocksize; + inst->alg.cra_blkcipher.max_keysize = + alg->cra_cipher.cia_max_keysize + alg->cra_blocksize; + + inst->alg.cra_ctxsize = sizeof(struct priv); + + inst->alg.cra_init = init_tfm; + inst->alg.cra_exit = exit_tfm; + + inst->alg.cra_blkcipher.setkey = setkey; + inst->alg.cra_blkcipher.encrypt = encrypt; + inst->alg.cra_blkcipher.decrypt = decrypt; + +out_put_alg: + crypto_mod_put(alg); + return inst; +} + +static void free(struct crypto_instance *inst) +{ + crypto_drop_spawn(crypto_instance_ctx(inst)); + kfree(inst); +} + +static struct crypto_template crypto_tmpl = { + .name = "lrw", + .alloc = alloc, + .free = free, + .module = THIS_MODULE, +}; + +static int __init crypto_module_init(void) +{ + return crypto_register_template(&crypto_tmpl); +} + +static void __exit crypto_module_exit(void) +{ + crypto_unregister_template(&crypto_tmpl); +} + +module_init(crypto_module_init); +module_exit(crypto_module_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("LRW block cipher mode"); diff --git a/trunk/crypto/tcrypt.c b/trunk/crypto/tcrypt.c index 83307420d31c..d671e8942b1f 100644 --- a/trunk/crypto/tcrypt.c +++ b/trunk/crypto/tcrypt.c @@ -906,6 +906,10 @@ static void do_test(void) AES_CBC_ENC_TEST_VECTORS); test_cipher("cbc(aes)", DECRYPT, aes_cbc_dec_tv_template, AES_CBC_DEC_TEST_VECTORS); + test_cipher("lrw(aes)", ENCRYPT, aes_lrw_enc_tv_template, + AES_LRW_ENC_TEST_VECTORS); + test_cipher("lrw(aes)", DECRYPT, aes_lrw_dec_tv_template, + AES_LRW_DEC_TEST_VECTORS); //CAST5 test_cipher("ecb(cast5)", ENCRYPT, cast5_enc_tv_template, @@ -977,6 +981,9 @@ static void do_test(void) test_hash("hmac(sha256)", hmac_sha256_tv_template, HMAC_SHA256_TEST_VECTORS); + test_hash("xcbc(aes)", aes_xcbc128_tv_template, + XCBC_AES_TEST_VECTORS); + test_hash("michael_mic", michael_mic_tv_template, MICHAEL_MIC_TEST_VECTORS); break; @@ -1052,6 +1059,10 @@ static void do_test(void) AES_CBC_ENC_TEST_VECTORS); test_cipher("cbc(aes)", DECRYPT, aes_cbc_dec_tv_template, AES_CBC_DEC_TEST_VECTORS); + test_cipher("lrw(aes)", ENCRYPT, aes_lrw_enc_tv_template, + AES_LRW_ENC_TEST_VECTORS); + test_cipher("lrw(aes)", DECRYPT, aes_lrw_dec_tv_template, + AES_LRW_DEC_TEST_VECTORS); break; case 11: @@ -1191,6 +1202,10 @@ static void do_test(void) aes_speed_template); test_cipher_speed("cbc(aes)", DECRYPT, sec, NULL, 0, aes_speed_template); + test_cipher_speed("lrw(aes)", ENCRYPT, sec, NULL, 0, + aes_lrw_speed_template); + test_cipher_speed("lrw(aes)", DECRYPT, sec, NULL, 0, + aes_lrw_speed_template); break; case 201: diff --git a/trunk/crypto/tcrypt.h b/trunk/crypto/tcrypt.h index a40c4411729e..48a81362cb85 100644 --- a/trunk/crypto/tcrypt.h +++ b/trunk/crypto/tcrypt.h @@ -39,15 +39,15 @@ struct hash_testvec { struct cipher_testvec { char key[MAX_KEYLEN] __attribute__ ((__aligned__(4))); char iv[MAX_IVLEN]; - char input[48]; - char result[48]; + char input[512]; + char result[512]; unsigned char tap[MAX_TAP]; int np; unsigned char fail; unsigned char wk; /* weak key flag */ unsigned char klen; - unsigned char ilen; - unsigned char rlen; + unsigned short ilen; + unsigned short rlen; }; struct cipher_speed { @@ -933,6 +933,74 @@ static struct hash_testvec hmac_sha256_tv_template[] = { }, }; +#define XCBC_AES_TEST_VECTORS 6 + +static struct hash_testvec aes_xcbc128_tv_template[] = { + { + .key = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + .plaintext = { [0 ... 15] = 0 }, + .digest = { 0x75, 0xf0, 0x25, 0x1d, 0x52, 0x8a, 0xc0, 0x1c, + 0x45, 0x73, 0xdf, 0xd5, 0x84, 0xd7, 0x9f, 0x29 }, + .psize = 0, + .ksize = 16, + }, { + .key = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + .plaintext = { 0x00, 0x01, 0x02 }, + .digest = { 0x5b, 0x37, 0x65, 0x80, 0xae, 0x2f, 0x19, 0xaf, + 0xe7, 0x21, 0x9c, 0xee, 0xf1, 0x72, 0x75, 0x6f }, + .psize = 3, + .ksize = 16, + } , { + .key = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + .plaintext = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + .digest = { 0xd2, 0xa2, 0x46, 0xfa, 0x34, 0x9b, 0x68, 0xa7, + 0x99, 0x98, 0xa4, 0x39, 0x4f, 0xf7, 0xa2, 0x63 }, + .psize = 16, + .ksize = 16, + }, { + .key = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + .plaintext = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13 }, + .digest = { 0x47, 0xf5, 0x1b, 0x45, 0x64, 0x96, 0x62, 0x15, + 0xb8, 0x98, 0x5c, 0x63, 0x05, 0x5e, 0xd3, 0x08 }, + .tap = { 10, 10 }, + .psize = 20, + .np = 2, + .ksize = 16, + }, { + .key = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + .plaintext = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f }, + .digest = { 0xf5, 0x4f, 0x0e, 0xc8, 0xd2, 0xb9, 0xf3, 0xd3, + 0x68, 0x07, 0x73, 0x4b, 0xd5, 0x28, 0x3f, 0xd4 }, + .psize = 32, + .ksize = 16, + }, { + .key = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + .plaintext = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21 }, + .digest = { 0xbe, 0xcb, 0xb3, 0xbc, 0xcd, 0xb5, 0x18, 0xa3, + 0x06, 0x77, 0xd5, 0x48, 0x1f, 0xb6, 0xb4, 0xd8 }, + .tap = { 17, 17 }, + .psize = 34, + .np = 2, + .ksize = 16, + } +}; + /* * DES test vectors. */ @@ -1831,6 +1899,8 @@ static struct cipher_testvec cast6_dec_tv_template[] = { #define AES_DEC_TEST_VECTORS 3 #define AES_CBC_ENC_TEST_VECTORS 2 #define AES_CBC_DEC_TEST_VECTORS 2 +#define AES_LRW_ENC_TEST_VECTORS 8 +#define AES_LRW_DEC_TEST_VECTORS 8 static struct cipher_testvec aes_enc_tv_template[] = { { /* From FIPS-197 */ @@ -1968,6 +2038,509 @@ static struct cipher_testvec aes_cbc_dec_tv_template[] = { }, }; +static struct cipher_testvec aes_lrw_enc_tv_template[] = { + /* from http://grouper.ieee.org/groups/1619/email/pdf00017.pdf */ + { /* LRW-32-AES 1 */ + .key = { 0x45, 0x62, 0xac, 0x25, 0xf8, 0x28, 0x17, 0x6d, + 0x4c, 0x26, 0x84, 0x14, 0xb5, 0x68, 0x01, 0x85, + 0x25, 0x8e, 0x2a, 0x05, 0xe7, 0x3e, 0x9d, 0x03, + 0xee, 0x5a, 0x83, 0x0c, 0xcc, 0x09, 0x4c, 0x87 }, + .klen = 32, + .iv = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, + .input = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 }, + .ilen = 16, + .result = { 0xf1, 0xb2, 0x73, 0xcd, 0x65, 0xa3, 0xdf, 0x5f, + 0xe9, 0x5d, 0x48, 0x92, 0x54, 0x63, 0x4e, 0xb8 }, + .rlen = 16, + }, { /* LRW-32-AES 2 */ + .key = { 0x59, 0x70, 0x47, 0x14, 0xf5, 0x57, 0x47, 0x8c, + 0xd7, 0x79, 0xe8, 0x0f, 0x54, 0x88, 0x79, 0x44, + 0x0d, 0x48, 0xf0, 0xb7, 0xb1, 0x5a, 0x53, 0xea, + 0x1c, 0xaa, 0x6b, 0x29, 0xc2, 0xca, 0xfb, 0xaf + }, + .klen = 32, + .iv = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 }, + .input = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 }, + .ilen = 16, + .result = { 0x00, 0xc8, 0x2b, 0xae, 0x95, 0xbb, 0xcd, 0xe5, + 0x27, 0x4f, 0x07, 0x69, 0xb2, 0x60, 0xe1, 0x36 }, + .rlen = 16, + }, { /* LRW-32-AES 3 */ + .key = { 0xd8, 0x2a, 0x91, 0x34, 0xb2, 0x6a, 0x56, 0x50, + 0x30, 0xfe, 0x69, 0xe2, 0x37, 0x7f, 0x98, 0x47, + 0xcd, 0xf9, 0x0b, 0x16, 0x0c, 0x64, 0x8f, 0xb6, + 0xb0, 0x0d, 0x0d, 0x1b, 0xae, 0x85, 0x87, 0x1f }, + .klen = 32, + .iv = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00 }, + .input = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 }, + .ilen = 16, + .result = { 0x76, 0x32, 0x21, 0x83, 0xed, 0x8f, 0xf1, 0x82, + 0xf9, 0x59, 0x62, 0x03, 0x69, 0x0e, 0x5e, 0x01 }, + .rlen = 16, + }, { /* LRW-32-AES 4 */ + .key = { 0x0f, 0x6a, 0xef, 0xf8, 0xd3, 0xd2, 0xbb, 0x15, + 0x25, 0x83, 0xf7, 0x3c, 0x1f, 0x01, 0x28, 0x74, + 0xca, 0xc6, 0xbc, 0x35, 0x4d, 0x4a, 0x65, 0x54, + 0x90, 0xae, 0x61, 0xcf, 0x7b, 0xae, 0xbd, 0xcc, + 0xad, 0xe4, 0x94, 0xc5, 0x4a, 0x29, 0xae, 0x70 }, + .klen = 40, + .iv = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, + .input = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 }, + .ilen = 16, + .result = { 0x9c, 0x0f, 0x15, 0x2f, 0x55, 0xa2, 0xd8, 0xf0, + 0xd6, 0x7b, 0x8f, 0x9e, 0x28, 0x22, 0xbc, 0x41 }, + .rlen = 16, + }, { /* LRW-32-AES 5 */ + .key = { 0x8a, 0xd4, 0xee, 0x10, 0x2f, 0xbd, 0x81, 0xff, + 0xf8, 0x86, 0xce, 0xac, 0x93, 0xc5, 0xad, 0xc6, + 0xa0, 0x19, 0x07, 0xc0, 0x9d, 0xf7, 0xbb, 0xdd, + 0x52, 0x13, 0xb2, 0xb7, 0xf0, 0xff, 0x11, 0xd8, + 0xd6, 0x08, 0xd0, 0xcd, 0x2e, 0xb1, 0x17, 0x6f }, + .klen = 40, + .iv = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00 }, + .input = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 }, + .ilen = 16, + .result = { 0xd4, 0x27, 0x6a, 0x7f, 0x14, 0x91, 0x3d, 0x65, + 0xc8, 0x60, 0x48, 0x02, 0x87, 0xe3, 0x34, 0x06 }, + .rlen = 16, + }, { /* LRW-32-AES 6 */ + .key = { 0xf8, 0xd4, 0x76, 0xff, 0xd6, 0x46, 0xee, 0x6c, + 0x23, 0x84, 0xcb, 0x1c, 0x77, 0xd6, 0x19, 0x5d, + 0xfe, 0xf1, 0xa9, 0xf3, 0x7b, 0xbc, 0x8d, 0x21, + 0xa7, 0x9c, 0x21, 0xf8, 0xcb, 0x90, 0x02, 0x89, + 0xa8, 0x45, 0x34, 0x8e, 0xc8, 0xc5, 0xb5, 0xf1, + 0x26, 0xf5, 0x0e, 0x76, 0xfe, 0xfd, 0x1b, 0x1e }, + .klen = 48, + .iv = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, + .input = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 }, + .ilen = 16, + .result = { 0xbd, 0x06, 0xb8, 0xe1, 0xdb, 0x98, 0x89, 0x9e, + 0xc4, 0x98, 0xe4, 0x91, 0xcf, 0x1c, 0x70, 0x2b }, + .rlen = 16, + }, { /* LRW-32-AES 7 */ + .key = { 0xfb, 0x76, 0x15, 0xb2, 0x3d, 0x80, 0x89, 0x1d, + 0xd4, 0x70, 0x98, 0x0b, 0xc7, 0x95, 0x84, 0xc8, + 0xb2, 0xfb, 0x64, 0xce, 0x60, 0x97, 0x87, 0x8d, + 0x17, 0xfc, 0xe4, 0x5a, 0x49, 0xe8, 0x30, 0xb7, + 0x6e, 0x78, 0x17, 0xe7, 0x2d, 0x5e, 0x12, 0xd4, + 0x60, 0x64, 0x04, 0x7a, 0xf1, 0x2f, 0x9e, 0x0c }, + .klen = 48, + .iv = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00 }, + .input = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 }, + .ilen = 16, + .result = { 0x5b, 0x90, 0x8e, 0xc1, 0xab, 0xdd, 0x67, 0x5f, + 0x3d, 0x69, 0x8a, 0x95, 0x53, 0xc8, 0x9c, 0xe5 }, + .rlen = 16, + }, { +/* http://www.mail-archive.com/stds-p1619@listserv.ieee.org/msg00173.html */ + .key = { 0xf8, 0xd4, 0x76, 0xff, 0xd6, 0x46, 0xee, 0x6c, + 0x23, 0x84, 0xcb, 0x1c, 0x77, 0xd6, 0x19, 0x5d, + 0xfe, 0xf1, 0xa9, 0xf3, 0x7b, 0xbc, 0x8d, 0x21, + 0xa7, 0x9c, 0x21, 0xf8, 0xcb, 0x90, 0x02, 0x89, + 0xa8, 0x45, 0x34, 0x8e, 0xc8, 0xc5, 0xb5, 0xf1, + 0x26, 0xf5, 0x0e, 0x76, 0xfe, 0xfd, 0x1b, 0x1e }, + .klen = 48, + .iv = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, + .input = { 0x05, 0x11, 0xb7, 0x18, 0xab, 0xc6, 0x2d, 0xac, + 0x70, 0x5d, 0xf6, 0x22, 0x94, 0xcd, 0xe5, 0x6c, + 0x17, 0x6b, 0xf6, 0x1c, 0xf0, 0xf3, 0x6e, 0xf8, + 0x50, 0x38, 0x1f, 0x71, 0x49, 0xb6, 0x57, 0xd6, + 0x8f, 0xcb, 0x8d, 0x6b, 0xe3, 0xa6, 0x29, 0x90, + 0xfe, 0x2a, 0x62, 0x82, 0xae, 0x6d, 0x8b, 0xf6, + 0xad, 0x1e, 0x9e, 0x20, 0x5f, 0x38, 0xbe, 0x04, + 0xda, 0x10, 0x8e, 0xed, 0xa2, 0xa4, 0x87, 0xab, + 0xda, 0x6b, 0xb4, 0x0c, 0x75, 0xba, 0xd3, 0x7c, + 0xc9, 0xac, 0x42, 0x31, 0x95, 0x7c, 0xc9, 0x04, + 0xeb, 0xd5, 0x6e, 0x32, 0x69, 0x8a, 0xdb, 0xa6, + 0x15, 0xd7, 0x3f, 0x4f, 0x2f, 0x66, 0x69, 0x03, + 0x9c, 0x1f, 0x54, 0x0f, 0xde, 0x1f, 0xf3, 0x65, + 0x4c, 0x96, 0x12, 0xed, 0x7c, 0x92, 0x03, 0x01, + 0x6f, 0xbc, 0x35, 0x93, 0xac, 0xf1, 0x27, 0xf1, + 0xb4, 0x96, 0x82, 0x5a, 0x5f, 0xb0, 0xa0, 0x50, + 0x89, 0xa4, 0x8e, 0x66, 0x44, 0x85, 0xcc, 0xfd, + 0x33, 0x14, 0x70, 0xe3, 0x96, 0xb2, 0xc3, 0xd3, + 0xbb, 0x54, 0x5a, 0x1a, 0xf9, 0x74, 0xa2, 0xc5, + 0x2d, 0x64, 0x75, 0xdd, 0xb4, 0x54, 0xe6, 0x74, + 0x8c, 0xd3, 0x9d, 0x9e, 0x86, 0xab, 0x51, 0x53, + 0xb7, 0x93, 0x3e, 0x6f, 0xd0, 0x4e, 0x2c, 0x40, + 0xf6, 0xa8, 0x2e, 0x3e, 0x9d, 0xf4, 0x66, 0xa5, + 0x76, 0x12, 0x73, 0x44, 0x1a, 0x56, 0xd7, 0x72, + 0x88, 0xcd, 0x21, 0x8c, 0x4c, 0x0f, 0xfe, 0xda, + 0x95, 0xe0, 0x3a, 0xa6, 0xa5, 0x84, 0x46, 0xcd, + 0xd5, 0x3e, 0x9d, 0x3a, 0xe2, 0x67, 0xe6, 0x60, + 0x1a, 0xe2, 0x70, 0x85, 0x58, 0xc2, 0x1b, 0x09, + 0xe1, 0xd7, 0x2c, 0xca, 0xad, 0xa8, 0x8f, 0xf9, + 0xac, 0xb3, 0x0e, 0xdb, 0xca, 0x2e, 0xe2, 0xb8, + 0x51, 0x71, 0xd9, 0x3c, 0x6c, 0xf1, 0x56, 0xf8, + 0xea, 0x9c, 0xf1, 0xfb, 0x0c, 0xe6, 0xb7, 0x10, + 0x1c, 0xf8, 0xa9, 0x7c, 0xe8, 0x53, 0x35, 0xc1, + 0x90, 0x3e, 0x76, 0x4a, 0x74, 0xa4, 0x21, 0x2c, + 0xf6, 0x2c, 0x4e, 0x0f, 0x94, 0x3a, 0x88, 0x2e, + 0x41, 0x09, 0x6a, 0x33, 0x7d, 0xf6, 0xdd, 0x3f, + 0x8d, 0x23, 0x31, 0x74, 0x84, 0xeb, 0x88, 0x6e, + 0xcc, 0xb9, 0xbc, 0x22, 0x83, 0x19, 0x07, 0x22, + 0xa5, 0x2d, 0xdf, 0xa5, 0xf3, 0x80, 0x85, 0x78, + 0x84, 0x39, 0x6a, 0x6d, 0x6a, 0x99, 0x4f, 0xa5, + 0x15, 0xfe, 0x46, 0xb0, 0xe4, 0x6c, 0xa5, 0x41, + 0x3c, 0xce, 0x8f, 0x42, 0x60, 0x71, 0xa7, 0x75, + 0x08, 0x40, 0x65, 0x8a, 0x82, 0xbf, 0xf5, 0x43, + 0x71, 0x96, 0xa9, 0x4d, 0x44, 0x8a, 0x20, 0xbe, + 0xfa, 0x4d, 0xbb, 0xc0, 0x7d, 0x31, 0x96, 0x65, + 0xe7, 0x75, 0xe5, 0x3e, 0xfd, 0x92, 0x3b, 0xc9, + 0x55, 0xbb, 0x16, 0x7e, 0xf7, 0xc2, 0x8c, 0xa4, + 0x40, 0x1d, 0xe5, 0xef, 0x0e, 0xdf, 0xe4, 0x9a, + 0x62, 0x73, 0x65, 0xfd, 0x46, 0x63, 0x25, 0x3d, + 0x2b, 0xaf, 0xe5, 0x64, 0xfe, 0xa5, 0x5c, 0xcf, + 0x24, 0xf3, 0xb4, 0xac, 0x64, 0xba, 0xdf, 0x4b, + 0xc6, 0x96, 0x7d, 0x81, 0x2d, 0x8d, 0x97, 0xf7, + 0xc5, 0x68, 0x77, 0x84, 0x32, 0x2b, 0xcc, 0x85, + 0x74, 0x96, 0xf0, 0x12, 0x77, 0x61, 0xb9, 0xeb, + 0x71, 0xaa, 0x82, 0xcb, 0x1c, 0xdb, 0x89, 0xc8, + 0xc6, 0xb5, 0xe3, 0x5c, 0x7d, 0x39, 0x07, 0x24, + 0xda, 0x39, 0x87, 0x45, 0xc0, 0x2b, 0xbb, 0x01, + 0xac, 0xbc, 0x2a, 0x5c, 0x7f, 0xfc, 0xe8, 0xce, + 0x6d, 0x9c, 0x6f, 0xed, 0xd3, 0xc1, 0xa1, 0xd6, + 0xc5, 0x55, 0xa9, 0x66, 0x2f, 0xe1, 0xc8, 0x32, + 0xa6, 0x5d, 0xa4, 0x3a, 0x98, 0x73, 0xe8, 0x45, + 0xa4, 0xc7, 0xa8, 0xb4, 0xf6, 0x13, 0x03, 0xf6, + 0xe9, 0x2e, 0xc4, 0x29, 0x0f, 0x84, 0xdb, 0xc4, + 0x21, 0xc4, 0xc2, 0x75, 0x67, 0x89, 0x37, 0x0a }, + .ilen = 512, + .result = { 0x1a, 0x1d, 0xa9, 0x30, 0xad, 0xf9, 0x2f, 0x9b, + 0xb6, 0x1d, 0xae, 0xef, 0xf0, 0x2f, 0xf8, 0x5a, + 0x39, 0x3c, 0xbf, 0x2a, 0xb2, 0x45, 0xb2, 0x23, + 0x1b, 0x63, 0x3c, 0xcf, 0xaa, 0xbe, 0xcf, 0x4e, + 0xfa, 0xe8, 0x29, 0xc2, 0x20, 0x68, 0x2b, 0x3c, + 0x2e, 0x8b, 0xf7, 0x6e, 0x25, 0xbd, 0xe3, 0x3d, + 0x66, 0x27, 0xd6, 0xaf, 0xd6, 0x64, 0x3e, 0xe3, + 0xe8, 0x58, 0x46, 0x97, 0x39, 0x51, 0x07, 0xde, + 0xcb, 0x37, 0xbc, 0xa9, 0xc0, 0x5f, 0x75, 0xc3, + 0x0e, 0x84, 0x23, 0x1d, 0x16, 0xd4, 0x1c, 0x59, + 0x9c, 0x1a, 0x02, 0x55, 0xab, 0x3a, 0x97, 0x1d, + 0xdf, 0xdd, 0xc7, 0x06, 0x51, 0xd7, 0x70, 0xae, + 0x23, 0xc6, 0x8c, 0xf5, 0x1e, 0xa0, 0xe5, 0x82, + 0xb8, 0xb2, 0xbf, 0x04, 0xa0, 0x32, 0x8e, 0x68, + 0xeb, 0xaf, 0x6e, 0x2d, 0x94, 0x22, 0x2f, 0xce, + 0x4c, 0xb5, 0x59, 0xe2, 0xa2, 0x2f, 0xa0, 0x98, + 0x1a, 0x97, 0xc6, 0xd4, 0xb5, 0x00, 0x59, 0xf2, + 0x84, 0x14, 0x72, 0xb1, 0x9a, 0x6e, 0xa3, 0x7f, + 0xea, 0x20, 0xe7, 0xcb, 0x65, 0x77, 0x3a, 0xdf, + 0xc8, 0x97, 0x67, 0x15, 0xc2, 0x2a, 0x27, 0xcc, + 0x18, 0x55, 0xa1, 0x24, 0x0b, 0x24, 0x24, 0xaf, + 0x5b, 0xec, 0x68, 0xb8, 0xc8, 0xf5, 0xba, 0x63, + 0xff, 0xed, 0x89, 0xce, 0xd5, 0x3d, 0x88, 0xf3, + 0x25, 0xef, 0x05, 0x7c, 0x3a, 0xef, 0xeb, 0xd8, + 0x7a, 0x32, 0x0d, 0xd1, 0x1e, 0x58, 0x59, 0x99, + 0x90, 0x25, 0xb5, 0x26, 0xb0, 0xe3, 0x2b, 0x6c, + 0x4c, 0xa9, 0x8b, 0x84, 0x4f, 0x5e, 0x01, 0x50, + 0x41, 0x30, 0x58, 0xc5, 0x62, 0x74, 0x52, 0x1d, + 0x45, 0x24, 0x6a, 0x42, 0x64, 0x4f, 0x97, 0x1c, + 0xa8, 0x66, 0xb5, 0x6d, 0x79, 0xd4, 0x0d, 0x48, + 0xc5, 0x5f, 0xf3, 0x90, 0x32, 0xdd, 0xdd, 0xe1, + 0xe4, 0xa9, 0x9f, 0xfc, 0xc3, 0x52, 0x5a, 0x46, + 0xe4, 0x81, 0x84, 0x95, 0x36, 0x59, 0x7a, 0x6b, + 0xaa, 0xb3, 0x60, 0xad, 0xce, 0x9f, 0x9f, 0x28, + 0xe0, 0x01, 0x75, 0x22, 0xc4, 0x4e, 0xa9, 0x62, + 0x5c, 0x62, 0x0d, 0x00, 0xcb, 0x13, 0xe8, 0x43, + 0x72, 0xd4, 0x2d, 0x53, 0x46, 0xb5, 0xd1, 0x16, + 0x22, 0x18, 0xdf, 0x34, 0x33, 0xf5, 0xd6, 0x1c, + 0xb8, 0x79, 0x78, 0x97, 0x94, 0xff, 0x72, 0x13, + 0x4c, 0x27, 0xfc, 0xcb, 0xbf, 0x01, 0x53, 0xa6, + 0xb4, 0x50, 0x6e, 0xde, 0xdf, 0xb5, 0x43, 0xa4, + 0x59, 0xdf, 0x52, 0xf9, 0x7c, 0xe0, 0x11, 0x6f, + 0x2d, 0x14, 0x8e, 0x24, 0x61, 0x2c, 0xe1, 0x17, + 0xcc, 0xce, 0x51, 0x0c, 0x19, 0x8a, 0x82, 0x30, + 0x94, 0xd5, 0x3d, 0x6a, 0x53, 0x06, 0x5e, 0xbd, + 0xb7, 0xeb, 0xfa, 0xfd, 0x27, 0x51, 0xde, 0x85, + 0x1e, 0x86, 0x53, 0x11, 0x53, 0x94, 0x00, 0xee, + 0x2b, 0x8c, 0x08, 0x2a, 0xbf, 0xdd, 0xae, 0x11, + 0xcb, 0x1e, 0xa2, 0x07, 0x9a, 0x80, 0xcf, 0x62, + 0x9b, 0x09, 0xdc, 0x95, 0x3c, 0x96, 0x8e, 0xb1, + 0x09, 0xbd, 0xe4, 0xeb, 0xdb, 0xca, 0x70, 0x7a, + 0x9e, 0xfa, 0x31, 0x18, 0x45, 0x3c, 0x21, 0x33, + 0xb0, 0xb3, 0x2b, 0xea, 0xf3, 0x71, 0x2d, 0xe1, + 0x03, 0xad, 0x1b, 0x48, 0xd4, 0x67, 0x27, 0xf0, + 0x62, 0xe4, 0x3d, 0xfb, 0x9b, 0x08, 0x76, 0xe7, + 0xdd, 0x2b, 0x01, 0x39, 0x04, 0x5a, 0x58, 0x7a, + 0xf7, 0x11, 0x90, 0xec, 0xbd, 0x51, 0x5c, 0x32, + 0x6b, 0xd7, 0x35, 0x39, 0x02, 0x6b, 0xf2, 0xa6, + 0xd0, 0x0d, 0x07, 0xe1, 0x06, 0xc4, 0x5b, 0x7d, + 0xe4, 0x6a, 0xd7, 0xee, 0x15, 0x1f, 0x83, 0xb4, + 0xa3, 0xa7, 0x5e, 0xc3, 0x90, 0xb7, 0xef, 0xd3, + 0xb7, 0x4f, 0xf8, 0x92, 0x4c, 0xb7, 0x3c, 0x29, + 0xcd, 0x7e, 0x2b, 0x5d, 0x43, 0xea, 0x42, 0xe7, + 0x74, 0x3f, 0x7d, 0x58, 0x88, 0x75, 0xde, 0x3e }, + .rlen = 512, + } +}; + +static struct cipher_testvec aes_lrw_dec_tv_template[] = { + /* from http://grouper.ieee.org/groups/1619/email/pdf00017.pdf */ + /* same as enc vectors with input and result reversed */ + { /* LRW-32-AES 1 */ + .key = { 0x45, 0x62, 0xac, 0x25, 0xf8, 0x28, 0x17, 0x6d, + 0x4c, 0x26, 0x84, 0x14, 0xb5, 0x68, 0x01, 0x85, + 0x25, 0x8e, 0x2a, 0x05, 0xe7, 0x3e, 0x9d, 0x03, + 0xee, 0x5a, 0x83, 0x0c, 0xcc, 0x09, 0x4c, 0x87 }, + .klen = 32, + .iv = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, + .input = { 0xf1, 0xb2, 0x73, 0xcd, 0x65, 0xa3, 0xdf, 0x5f, + 0xe9, 0x5d, 0x48, 0x92, 0x54, 0x63, 0x4e, 0xb8 }, + .ilen = 16, + .result = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 }, + .rlen = 16, + }, { /* LRW-32-AES 2 */ + .key = { 0x59, 0x70, 0x47, 0x14, 0xf5, 0x57, 0x47, 0x8c, + 0xd7, 0x79, 0xe8, 0x0f, 0x54, 0x88, 0x79, 0x44, + 0x0d, 0x48, 0xf0, 0xb7, 0xb1, 0x5a, 0x53, 0xea, + 0x1c, 0xaa, 0x6b, 0x29, 0xc2, 0xca, 0xfb, 0xaf + }, + .klen = 32, + .iv = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 }, + .input = { 0x00, 0xc8, 0x2b, 0xae, 0x95, 0xbb, 0xcd, 0xe5, + 0x27, 0x4f, 0x07, 0x69, 0xb2, 0x60, 0xe1, 0x36 }, + .ilen = 16, + .result = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 }, + .rlen = 16, + }, { /* LRW-32-AES 3 */ + .key = { 0xd8, 0x2a, 0x91, 0x34, 0xb2, 0x6a, 0x56, 0x50, + 0x30, 0xfe, 0x69, 0xe2, 0x37, 0x7f, 0x98, 0x47, + 0xcd, 0xf9, 0x0b, 0x16, 0x0c, 0x64, 0x8f, 0xb6, + 0xb0, 0x0d, 0x0d, 0x1b, 0xae, 0x85, 0x87, 0x1f }, + .klen = 32, + .iv = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00 }, + .input = { 0x76, 0x32, 0x21, 0x83, 0xed, 0x8f, 0xf1, 0x82, + 0xf9, 0x59, 0x62, 0x03, 0x69, 0x0e, 0x5e, 0x01 }, + .ilen = 16, + .result = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 }, + .rlen = 16, + }, { /* LRW-32-AES 4 */ + .key = { 0x0f, 0x6a, 0xef, 0xf8, 0xd3, 0xd2, 0xbb, 0x15, + 0x25, 0x83, 0xf7, 0x3c, 0x1f, 0x01, 0x28, 0x74, + 0xca, 0xc6, 0xbc, 0x35, 0x4d, 0x4a, 0x65, 0x54, + 0x90, 0xae, 0x61, 0xcf, 0x7b, 0xae, 0xbd, 0xcc, + 0xad, 0xe4, 0x94, 0xc5, 0x4a, 0x29, 0xae, 0x70 }, + .klen = 40, + .iv = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, + .input = { 0x9c, 0x0f, 0x15, 0x2f, 0x55, 0xa2, 0xd8, 0xf0, + 0xd6, 0x7b, 0x8f, 0x9e, 0x28, 0x22, 0xbc, 0x41 }, + .ilen = 16, + .result = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 }, + .rlen = 16, + }, { /* LRW-32-AES 5 */ + .key = { 0x8a, 0xd4, 0xee, 0x10, 0x2f, 0xbd, 0x81, 0xff, + 0xf8, 0x86, 0xce, 0xac, 0x93, 0xc5, 0xad, 0xc6, + 0xa0, 0x19, 0x07, 0xc0, 0x9d, 0xf7, 0xbb, 0xdd, + 0x52, 0x13, 0xb2, 0xb7, 0xf0, 0xff, 0x11, 0xd8, + 0xd6, 0x08, 0xd0, 0xcd, 0x2e, 0xb1, 0x17, 0x6f }, + .klen = 40, + .iv = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00 }, + .input = { 0xd4, 0x27, 0x6a, 0x7f, 0x14, 0x91, 0x3d, 0x65, + 0xc8, 0x60, 0x48, 0x02, 0x87, 0xe3, 0x34, 0x06 }, + .ilen = 16, + .result = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 }, + .rlen = 16, + }, { /* LRW-32-AES 6 */ + .key = { 0xf8, 0xd4, 0x76, 0xff, 0xd6, 0x46, 0xee, 0x6c, + 0x23, 0x84, 0xcb, 0x1c, 0x77, 0xd6, 0x19, 0x5d, + 0xfe, 0xf1, 0xa9, 0xf3, 0x7b, 0xbc, 0x8d, 0x21, + 0xa7, 0x9c, 0x21, 0xf8, 0xcb, 0x90, 0x02, 0x89, + 0xa8, 0x45, 0x34, 0x8e, 0xc8, 0xc5, 0xb5, 0xf1, + 0x26, 0xf5, 0x0e, 0x76, 0xfe, 0xfd, 0x1b, 0x1e }, + .klen = 48, + .iv = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, + .input = { 0xbd, 0x06, 0xb8, 0xe1, 0xdb, 0x98, 0x89, 0x9e, + 0xc4, 0x98, 0xe4, 0x91, 0xcf, 0x1c, 0x70, 0x2b }, + .ilen = 16, + .result = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 }, + .rlen = 16, + }, { /* LRW-32-AES 7 */ + .key = { 0xfb, 0x76, 0x15, 0xb2, 0x3d, 0x80, 0x89, 0x1d, + 0xd4, 0x70, 0x98, 0x0b, 0xc7, 0x95, 0x84, 0xc8, + 0xb2, 0xfb, 0x64, 0xce, 0x60, 0x97, 0x87, 0x8d, + 0x17, 0xfc, 0xe4, 0x5a, 0x49, 0xe8, 0x30, 0xb7, + 0x6e, 0x78, 0x17, 0xe7, 0x2d, 0x5e, 0x12, 0xd4, + 0x60, 0x64, 0x04, 0x7a, 0xf1, 0x2f, 0x9e, 0x0c }, + .klen = 48, + .iv = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00 }, + .input = { 0x5b, 0x90, 0x8e, 0xc1, 0xab, 0xdd, 0x67, 0x5f, + 0x3d, 0x69, 0x8a, 0x95, 0x53, 0xc8, 0x9c, 0xe5 }, + .ilen = 16, + .result = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 }, + .rlen = 16, + }, { +/* http://www.mail-archive.com/stds-p1619@listserv.ieee.org/msg00173.html */ + .key = { 0xf8, 0xd4, 0x76, 0xff, 0xd6, 0x46, 0xee, 0x6c, + 0x23, 0x84, 0xcb, 0x1c, 0x77, 0xd6, 0x19, 0x5d, + 0xfe, 0xf1, 0xa9, 0xf3, 0x7b, 0xbc, 0x8d, 0x21, + 0xa7, 0x9c, 0x21, 0xf8, 0xcb, 0x90, 0x02, 0x89, + 0xa8, 0x45, 0x34, 0x8e, 0xc8, 0xc5, 0xb5, 0xf1, + 0x26, 0xf5, 0x0e, 0x76, 0xfe, 0xfd, 0x1b, 0x1e }, + .klen = 48, + .iv = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, + .input = { 0x1a, 0x1d, 0xa9, 0x30, 0xad, 0xf9, 0x2f, 0x9b, + 0xb6, 0x1d, 0xae, 0xef, 0xf0, 0x2f, 0xf8, 0x5a, + 0x39, 0x3c, 0xbf, 0x2a, 0xb2, 0x45, 0xb2, 0x23, + 0x1b, 0x63, 0x3c, 0xcf, 0xaa, 0xbe, 0xcf, 0x4e, + 0xfa, 0xe8, 0x29, 0xc2, 0x20, 0x68, 0x2b, 0x3c, + 0x2e, 0x8b, 0xf7, 0x6e, 0x25, 0xbd, 0xe3, 0x3d, + 0x66, 0x27, 0xd6, 0xaf, 0xd6, 0x64, 0x3e, 0xe3, + 0xe8, 0x58, 0x46, 0x97, 0x39, 0x51, 0x07, 0xde, + 0xcb, 0x37, 0xbc, 0xa9, 0xc0, 0x5f, 0x75, 0xc3, + 0x0e, 0x84, 0x23, 0x1d, 0x16, 0xd4, 0x1c, 0x59, + 0x9c, 0x1a, 0x02, 0x55, 0xab, 0x3a, 0x97, 0x1d, + 0xdf, 0xdd, 0xc7, 0x06, 0x51, 0xd7, 0x70, 0xae, + 0x23, 0xc6, 0x8c, 0xf5, 0x1e, 0xa0, 0xe5, 0x82, + 0xb8, 0xb2, 0xbf, 0x04, 0xa0, 0x32, 0x8e, 0x68, + 0xeb, 0xaf, 0x6e, 0x2d, 0x94, 0x22, 0x2f, 0xce, + 0x4c, 0xb5, 0x59, 0xe2, 0xa2, 0x2f, 0xa0, 0x98, + 0x1a, 0x97, 0xc6, 0xd4, 0xb5, 0x00, 0x59, 0xf2, + 0x84, 0x14, 0x72, 0xb1, 0x9a, 0x6e, 0xa3, 0x7f, + 0xea, 0x20, 0xe7, 0xcb, 0x65, 0x77, 0x3a, 0xdf, + 0xc8, 0x97, 0x67, 0x15, 0xc2, 0x2a, 0x27, 0xcc, + 0x18, 0x55, 0xa1, 0x24, 0x0b, 0x24, 0x24, 0xaf, + 0x5b, 0xec, 0x68, 0xb8, 0xc8, 0xf5, 0xba, 0x63, + 0xff, 0xed, 0x89, 0xce, 0xd5, 0x3d, 0x88, 0xf3, + 0x25, 0xef, 0x05, 0x7c, 0x3a, 0xef, 0xeb, 0xd8, + 0x7a, 0x32, 0x0d, 0xd1, 0x1e, 0x58, 0x59, 0x99, + 0x90, 0x25, 0xb5, 0x26, 0xb0, 0xe3, 0x2b, 0x6c, + 0x4c, 0xa9, 0x8b, 0x84, 0x4f, 0x5e, 0x01, 0x50, + 0x41, 0x30, 0x58, 0xc5, 0x62, 0x74, 0x52, 0x1d, + 0x45, 0x24, 0x6a, 0x42, 0x64, 0x4f, 0x97, 0x1c, + 0xa8, 0x66, 0xb5, 0x6d, 0x79, 0xd4, 0x0d, 0x48, + 0xc5, 0x5f, 0xf3, 0x90, 0x32, 0xdd, 0xdd, 0xe1, + 0xe4, 0xa9, 0x9f, 0xfc, 0xc3, 0x52, 0x5a, 0x46, + 0xe4, 0x81, 0x84, 0x95, 0x36, 0x59, 0x7a, 0x6b, + 0xaa, 0xb3, 0x60, 0xad, 0xce, 0x9f, 0x9f, 0x28, + 0xe0, 0x01, 0x75, 0x22, 0xc4, 0x4e, 0xa9, 0x62, + 0x5c, 0x62, 0x0d, 0x00, 0xcb, 0x13, 0xe8, 0x43, + 0x72, 0xd4, 0x2d, 0x53, 0x46, 0xb5, 0xd1, 0x16, + 0x22, 0x18, 0xdf, 0x34, 0x33, 0xf5, 0xd6, 0x1c, + 0xb8, 0x79, 0x78, 0x97, 0x94, 0xff, 0x72, 0x13, + 0x4c, 0x27, 0xfc, 0xcb, 0xbf, 0x01, 0x53, 0xa6, + 0xb4, 0x50, 0x6e, 0xde, 0xdf, 0xb5, 0x43, 0xa4, + 0x59, 0xdf, 0x52, 0xf9, 0x7c, 0xe0, 0x11, 0x6f, + 0x2d, 0x14, 0x8e, 0x24, 0x61, 0x2c, 0xe1, 0x17, + 0xcc, 0xce, 0x51, 0x0c, 0x19, 0x8a, 0x82, 0x30, + 0x94, 0xd5, 0x3d, 0x6a, 0x53, 0x06, 0x5e, 0xbd, + 0xb7, 0xeb, 0xfa, 0xfd, 0x27, 0x51, 0xde, 0x85, + 0x1e, 0x86, 0x53, 0x11, 0x53, 0x94, 0x00, 0xee, + 0x2b, 0x8c, 0x08, 0x2a, 0xbf, 0xdd, 0xae, 0x11, + 0xcb, 0x1e, 0xa2, 0x07, 0x9a, 0x80, 0xcf, 0x62, + 0x9b, 0x09, 0xdc, 0x95, 0x3c, 0x96, 0x8e, 0xb1, + 0x09, 0xbd, 0xe4, 0xeb, 0xdb, 0xca, 0x70, 0x7a, + 0x9e, 0xfa, 0x31, 0x18, 0x45, 0x3c, 0x21, 0x33, + 0xb0, 0xb3, 0x2b, 0xea, 0xf3, 0x71, 0x2d, 0xe1, + 0x03, 0xad, 0x1b, 0x48, 0xd4, 0x67, 0x27, 0xf0, + 0x62, 0xe4, 0x3d, 0xfb, 0x9b, 0x08, 0x76, 0xe7, + 0xdd, 0x2b, 0x01, 0x39, 0x04, 0x5a, 0x58, 0x7a, + 0xf7, 0x11, 0x90, 0xec, 0xbd, 0x51, 0x5c, 0x32, + 0x6b, 0xd7, 0x35, 0x39, 0x02, 0x6b, 0xf2, 0xa6, + 0xd0, 0x0d, 0x07, 0xe1, 0x06, 0xc4, 0x5b, 0x7d, + 0xe4, 0x6a, 0xd7, 0xee, 0x15, 0x1f, 0x83, 0xb4, + 0xa3, 0xa7, 0x5e, 0xc3, 0x90, 0xb7, 0xef, 0xd3, + 0xb7, 0x4f, 0xf8, 0x92, 0x4c, 0xb7, 0x3c, 0x29, + 0xcd, 0x7e, 0x2b, 0x5d, 0x43, 0xea, 0x42, 0xe7, + 0x74, 0x3f, 0x7d, 0x58, 0x88, 0x75, 0xde, 0x3e }, + .ilen = 512, + .result = { 0x05, 0x11, 0xb7, 0x18, 0xab, 0xc6, 0x2d, 0xac, + 0x70, 0x5d, 0xf6, 0x22, 0x94, 0xcd, 0xe5, 0x6c, + 0x17, 0x6b, 0xf6, 0x1c, 0xf0, 0xf3, 0x6e, 0xf8, + 0x50, 0x38, 0x1f, 0x71, 0x49, 0xb6, 0x57, 0xd6, + 0x8f, 0xcb, 0x8d, 0x6b, 0xe3, 0xa6, 0x29, 0x90, + 0xfe, 0x2a, 0x62, 0x82, 0xae, 0x6d, 0x8b, 0xf6, + 0xad, 0x1e, 0x9e, 0x20, 0x5f, 0x38, 0xbe, 0x04, + 0xda, 0x10, 0x8e, 0xed, 0xa2, 0xa4, 0x87, 0xab, + 0xda, 0x6b, 0xb4, 0x0c, 0x75, 0xba, 0xd3, 0x7c, + 0xc9, 0xac, 0x42, 0x31, 0x95, 0x7c, 0xc9, 0x04, + 0xeb, 0xd5, 0x6e, 0x32, 0x69, 0x8a, 0xdb, 0xa6, + 0x15, 0xd7, 0x3f, 0x4f, 0x2f, 0x66, 0x69, 0x03, + 0x9c, 0x1f, 0x54, 0x0f, 0xde, 0x1f, 0xf3, 0x65, + 0x4c, 0x96, 0x12, 0xed, 0x7c, 0x92, 0x03, 0x01, + 0x6f, 0xbc, 0x35, 0x93, 0xac, 0xf1, 0x27, 0xf1, + 0xb4, 0x96, 0x82, 0x5a, 0x5f, 0xb0, 0xa0, 0x50, + 0x89, 0xa4, 0x8e, 0x66, 0x44, 0x85, 0xcc, 0xfd, + 0x33, 0x14, 0x70, 0xe3, 0x96, 0xb2, 0xc3, 0xd3, + 0xbb, 0x54, 0x5a, 0x1a, 0xf9, 0x74, 0xa2, 0xc5, + 0x2d, 0x64, 0x75, 0xdd, 0xb4, 0x54, 0xe6, 0x74, + 0x8c, 0xd3, 0x9d, 0x9e, 0x86, 0xab, 0x51, 0x53, + 0xb7, 0x93, 0x3e, 0x6f, 0xd0, 0x4e, 0x2c, 0x40, + 0xf6, 0xa8, 0x2e, 0x3e, 0x9d, 0xf4, 0x66, 0xa5, + 0x76, 0x12, 0x73, 0x44, 0x1a, 0x56, 0xd7, 0x72, + 0x88, 0xcd, 0x21, 0x8c, 0x4c, 0x0f, 0xfe, 0xda, + 0x95, 0xe0, 0x3a, 0xa6, 0xa5, 0x84, 0x46, 0xcd, + 0xd5, 0x3e, 0x9d, 0x3a, 0xe2, 0x67, 0xe6, 0x60, + 0x1a, 0xe2, 0x70, 0x85, 0x58, 0xc2, 0x1b, 0x09, + 0xe1, 0xd7, 0x2c, 0xca, 0xad, 0xa8, 0x8f, 0xf9, + 0xac, 0xb3, 0x0e, 0xdb, 0xca, 0x2e, 0xe2, 0xb8, + 0x51, 0x71, 0xd9, 0x3c, 0x6c, 0xf1, 0x56, 0xf8, + 0xea, 0x9c, 0xf1, 0xfb, 0x0c, 0xe6, 0xb7, 0x10, + 0x1c, 0xf8, 0xa9, 0x7c, 0xe8, 0x53, 0x35, 0xc1, + 0x90, 0x3e, 0x76, 0x4a, 0x74, 0xa4, 0x21, 0x2c, + 0xf6, 0x2c, 0x4e, 0x0f, 0x94, 0x3a, 0x88, 0x2e, + 0x41, 0x09, 0x6a, 0x33, 0x7d, 0xf6, 0xdd, 0x3f, + 0x8d, 0x23, 0x31, 0x74, 0x84, 0xeb, 0x88, 0x6e, + 0xcc, 0xb9, 0xbc, 0x22, 0x83, 0x19, 0x07, 0x22, + 0xa5, 0x2d, 0xdf, 0xa5, 0xf3, 0x80, 0x85, 0x78, + 0x84, 0x39, 0x6a, 0x6d, 0x6a, 0x99, 0x4f, 0xa5, + 0x15, 0xfe, 0x46, 0xb0, 0xe4, 0x6c, 0xa5, 0x41, + 0x3c, 0xce, 0x8f, 0x42, 0x60, 0x71, 0xa7, 0x75, + 0x08, 0x40, 0x65, 0x8a, 0x82, 0xbf, 0xf5, 0x43, + 0x71, 0x96, 0xa9, 0x4d, 0x44, 0x8a, 0x20, 0xbe, + 0xfa, 0x4d, 0xbb, 0xc0, 0x7d, 0x31, 0x96, 0x65, + 0xe7, 0x75, 0xe5, 0x3e, 0xfd, 0x92, 0x3b, 0xc9, + 0x55, 0xbb, 0x16, 0x7e, 0xf7, 0xc2, 0x8c, 0xa4, + 0x40, 0x1d, 0xe5, 0xef, 0x0e, 0xdf, 0xe4, 0x9a, + 0x62, 0x73, 0x65, 0xfd, 0x46, 0x63, 0x25, 0x3d, + 0x2b, 0xaf, 0xe5, 0x64, 0xfe, 0xa5, 0x5c, 0xcf, + 0x24, 0xf3, 0xb4, 0xac, 0x64, 0xba, 0xdf, 0x4b, + 0xc6, 0x96, 0x7d, 0x81, 0x2d, 0x8d, 0x97, 0xf7, + 0xc5, 0x68, 0x77, 0x84, 0x32, 0x2b, 0xcc, 0x85, + 0x74, 0x96, 0xf0, 0x12, 0x77, 0x61, 0xb9, 0xeb, + 0x71, 0xaa, 0x82, 0xcb, 0x1c, 0xdb, 0x89, 0xc8, + 0xc6, 0xb5, 0xe3, 0x5c, 0x7d, 0x39, 0x07, 0x24, + 0xda, 0x39, 0x87, 0x45, 0xc0, 0x2b, 0xbb, 0x01, + 0xac, 0xbc, 0x2a, 0x5c, 0x7f, 0xfc, 0xe8, 0xce, + 0x6d, 0x9c, 0x6f, 0xed, 0xd3, 0xc1, 0xa1, 0xd6, + 0xc5, 0x55, 0xa9, 0x66, 0x2f, 0xe1, 0xc8, 0x32, + 0xa6, 0x5d, 0xa4, 0x3a, 0x98, 0x73, 0xe8, 0x45, + 0xa4, 0xc7, 0xa8, 0xb4, 0xf6, 0x13, 0x03, 0xf6, + 0xe9, 0x2e, 0xc4, 0x29, 0x0f, 0x84, 0xdb, 0xc4, + 0x21, 0xc4, 0xc2, 0x75, 0x67, 0x89, 0x37, 0x0a }, + .rlen = 512, + } +}; + /* Cast5 test vectors from RFC 2144 */ #define CAST5_ENC_TEST_VECTORS 3 #define CAST5_DEC_TEST_VECTORS 3 @@ -3084,6 +3657,27 @@ static struct cipher_speed aes_speed_template[] = { { .klen = 0, .blen = 0, } }; +static struct cipher_speed aes_lrw_speed_template[] = { + { .klen = 32, .blen = 16, }, + { .klen = 32, .blen = 64, }, + { .klen = 32, .blen = 256, }, + { .klen = 32, .blen = 1024, }, + { .klen = 32, .blen = 8192, }, + { .klen = 40, .blen = 16, }, + { .klen = 40, .blen = 64, }, + { .klen = 40, .blen = 256, }, + { .klen = 40, .blen = 1024, }, + { .klen = 40, .blen = 8192, }, + { .klen = 48, .blen = 16, }, + { .klen = 48, .blen = 64, }, + { .klen = 48, .blen = 256, }, + { .klen = 48, .blen = 1024, }, + { .klen = 48, .blen = 8192, }, + + /* End marker */ + { .klen = 0, .blen = 0, } +}; + static struct cipher_speed des3_ede_speed_template[] = { { .klen = 24, .blen = 16, }, { .klen = 24, .blen = 64, }, diff --git a/trunk/crypto/xcbc.c b/trunk/crypto/xcbc.c new file mode 100644 index 000000000000..9347eb6bcf69 --- /dev/null +++ b/trunk/crypto/xcbc.c @@ -0,0 +1,348 @@ +/* + * Copyright (C)2006 USAGI/WIDE Project + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: + * Kazunori Miyazawa + */ + +#include +#include +#include +#include +#include +#include +#include +#include "internal.h" + +static u_int32_t ks[12] = {0x01010101, 0x01010101, 0x01010101, 0x01010101, + 0x02020202, 0x02020202, 0x02020202, 0x02020202, + 0x03030303, 0x03030303, 0x03030303, 0x03030303}; +/* + * +------------------------ + * | + * +------------------------ + * | crypto_xcbc_ctx + * +------------------------ + * | odds (block size) + * +------------------------ + * | prev (block size) + * +------------------------ + * | key (block size) + * +------------------------ + * | consts (block size * 3) + * +------------------------ + */ +struct crypto_xcbc_ctx { + struct crypto_tfm *child; + u8 *odds; + u8 *prev; + u8 *key; + u8 *consts; + void (*xor)(u8 *a, const u8 *b, unsigned int bs); + unsigned int keylen; + unsigned int len; +}; + +static void xor_128(u8 *a, const u8 *b, unsigned int bs) +{ + ((u32 *)a)[0] ^= ((u32 *)b)[0]; + ((u32 *)a)[1] ^= ((u32 *)b)[1]; + ((u32 *)a)[2] ^= ((u32 *)b)[2]; + ((u32 *)a)[3] ^= ((u32 *)b)[3]; +} + +static int _crypto_xcbc_digest_setkey(struct crypto_hash *parent, + struct crypto_xcbc_ctx *ctx) +{ + int bs = crypto_hash_blocksize(parent); + int err = 0; + u8 key1[bs]; + + if ((err = crypto_cipher_setkey(ctx->child, ctx->key, ctx->keylen))) + return err; + + ctx->child->__crt_alg->cra_cipher.cia_encrypt(ctx->child, key1, + ctx->consts); + + return crypto_cipher_setkey(ctx->child, key1, bs); +} + +static int crypto_xcbc_digest_setkey(struct crypto_hash *parent, + const u8 *inkey, unsigned int keylen) +{ + struct crypto_xcbc_ctx *ctx = crypto_hash_ctx_aligned(parent); + + if (keylen != crypto_tfm_alg_blocksize(ctx->child)) + return -EINVAL; + + ctx->keylen = keylen; + memcpy(ctx->key, inkey, keylen); + ctx->consts = (u8*)ks; + + return _crypto_xcbc_digest_setkey(parent, ctx); +} + +static int crypto_xcbc_digest_init(struct hash_desc *pdesc) +{ + struct crypto_xcbc_ctx *ctx = crypto_hash_ctx_aligned(pdesc->tfm); + int bs = crypto_hash_blocksize(pdesc->tfm); + + ctx->len = 0; + memset(ctx->odds, 0, bs); + memset(ctx->prev, 0, bs); + + return 0; +} + +static int crypto_xcbc_digest_update(struct hash_desc *pdesc, + struct scatterlist *sg, + unsigned int nbytes) +{ + struct crypto_hash *parent = pdesc->tfm; + struct crypto_xcbc_ctx *ctx = crypto_hash_ctx_aligned(parent); + struct crypto_tfm *tfm = ctx->child; + int bs = crypto_hash_blocksize(parent); + unsigned int i = 0; + + do { + + struct page *pg = sg[i].page; + unsigned int offset = sg[i].offset; + unsigned int slen = sg[i].length; + + while (slen > 0) { + unsigned int len = min(slen, ((unsigned int)(PAGE_SIZE)) - offset); + char *p = crypto_kmap(pg, 0) + offset; + + /* checking the data can fill the block */ + if ((ctx->len + len) <= bs) { + memcpy(ctx->odds + ctx->len, p, len); + ctx->len += len; + slen -= len; + + /* checking the rest of the page */ + if (len + offset >= PAGE_SIZE) { + offset = 0; + pg++; + } else + offset += len; + + crypto_kunmap(p, 0); + crypto_yield(tfm->crt_flags); + continue; + } + + /* filling odds with new data and encrypting it */ + memcpy(ctx->odds + ctx->len, p, bs - ctx->len); + len -= bs - ctx->len; + p += bs - ctx->len; + + ctx->xor(ctx->prev, ctx->odds, bs); + tfm->__crt_alg->cra_cipher.cia_encrypt(tfm, ctx->prev, ctx->prev); + + /* clearing the length */ + ctx->len = 0; + + /* encrypting the rest of data */ + while (len > bs) { + ctx->xor(ctx->prev, p, bs); + tfm->__crt_alg->cra_cipher.cia_encrypt(tfm, ctx->prev, ctx->prev); + p += bs; + len -= bs; + } + + /* keeping the surplus of blocksize */ + if (len) { + memcpy(ctx->odds, p, len); + ctx->len = len; + } + crypto_kunmap(p, 0); + crypto_yield(tfm->crt_flags); + slen -= min(slen, ((unsigned int)(PAGE_SIZE)) - offset); + offset = 0; + pg++; + } + nbytes-=sg[i].length; + i++; + } while (nbytes>0); + + return 0; +} + +static int crypto_xcbc_digest_final(struct hash_desc *pdesc, u8 *out) +{ + struct crypto_hash *parent = pdesc->tfm; + struct crypto_xcbc_ctx *ctx = crypto_hash_ctx_aligned(parent); + struct crypto_tfm *tfm = ctx->child; + int bs = crypto_hash_blocksize(parent); + int err = 0; + + if (ctx->len == bs) { + u8 key2[bs]; + + if ((err = crypto_cipher_setkey(tfm, ctx->key, ctx->keylen)) != 0) + return err; + + tfm->__crt_alg->cra_cipher.cia_encrypt(tfm, key2, (const u8*)(ctx->consts+bs)); + + ctx->xor(ctx->prev, ctx->odds, bs); + ctx->xor(ctx->prev, key2, bs); + _crypto_xcbc_digest_setkey(parent, ctx); + + tfm->__crt_alg->cra_cipher.cia_encrypt(tfm, out, ctx->prev); + } else { + u8 key3[bs]; + unsigned int rlen; + u8 *p = ctx->odds + ctx->len; + *p = 0x80; + p++; + + rlen = bs - ctx->len -1; + if (rlen) + memset(p, 0, rlen); + + if ((err = crypto_cipher_setkey(tfm, ctx->key, ctx->keylen)) != 0) + return err; + + tfm->__crt_alg->cra_cipher.cia_encrypt(tfm, key3, (const u8*)(ctx->consts+bs*2)); + + ctx->xor(ctx->prev, ctx->odds, bs); + ctx->xor(ctx->prev, key3, bs); + + _crypto_xcbc_digest_setkey(parent, ctx); + + tfm->__crt_alg->cra_cipher.cia_encrypt(tfm, out, ctx->prev); + } + + return 0; +} + +static int crypto_xcbc_digest(struct hash_desc *pdesc, + struct scatterlist *sg, unsigned int nbytes, u8 *out) +{ + crypto_xcbc_digest_init(pdesc); + crypto_xcbc_digest_update(pdesc, sg, nbytes); + return crypto_xcbc_digest_final(pdesc, out); +} + +static int xcbc_init_tfm(struct crypto_tfm *tfm) +{ + struct crypto_instance *inst = (void *)tfm->__crt_alg; + struct crypto_spawn *spawn = crypto_instance_ctx(inst); + struct crypto_xcbc_ctx *ctx = crypto_hash_ctx_aligned(__crypto_hash_cast(tfm)); + int bs = crypto_hash_blocksize(__crypto_hash_cast(tfm)); + + tfm = crypto_spawn_tfm(spawn); + if (IS_ERR(tfm)) + return PTR_ERR(tfm); + + switch(bs) { + case 16: + ctx->xor = xor_128; + break; + default: + return -EINVAL; + } + + ctx->child = crypto_cipher_cast(tfm); + ctx->odds = (u8*)(ctx+1); + ctx->prev = ctx->odds + bs; + ctx->key = ctx->prev + bs; + + return 0; +}; + +static void xcbc_exit_tfm(struct crypto_tfm *tfm) +{ + struct crypto_xcbc_ctx *ctx = crypto_hash_ctx_aligned(__crypto_hash_cast(tfm)); + crypto_free_cipher(ctx->child); +} + +static struct crypto_instance *xcbc_alloc(void *param, unsigned int len) +{ + struct crypto_instance *inst; + struct crypto_alg *alg; + alg = crypto_get_attr_alg(param, len, CRYPTO_ALG_TYPE_CIPHER, + CRYPTO_ALG_TYPE_HASH_MASK | CRYPTO_ALG_ASYNC); + if (IS_ERR(alg)) + return ERR_PTR(PTR_ERR(alg)); + + switch(alg->cra_blocksize) { + case 16: + break; + default: + return ERR_PTR(PTR_ERR(alg)); + } + + inst = crypto_alloc_instance("xcbc", alg); + if (IS_ERR(inst)) + goto out_put_alg; + + inst->alg.cra_flags = CRYPTO_ALG_TYPE_HASH; + inst->alg.cra_priority = alg->cra_priority; + inst->alg.cra_blocksize = alg->cra_blocksize; + inst->alg.cra_alignmask = alg->cra_alignmask; + inst->alg.cra_type = &crypto_hash_type; + + inst->alg.cra_hash.digestsize = + (alg->cra_flags & CRYPTO_ALG_TYPE_MASK) == + CRYPTO_ALG_TYPE_HASH ? alg->cra_hash.digestsize : + alg->cra_blocksize; + inst->alg.cra_ctxsize = sizeof(struct crypto_xcbc_ctx) + + ALIGN(inst->alg.cra_blocksize * 3, sizeof(void *)); + inst->alg.cra_init = xcbc_init_tfm; + inst->alg.cra_exit = xcbc_exit_tfm; + + inst->alg.cra_hash.init = crypto_xcbc_digest_init; + inst->alg.cra_hash.update = crypto_xcbc_digest_update; + inst->alg.cra_hash.final = crypto_xcbc_digest_final; + inst->alg.cra_hash.digest = crypto_xcbc_digest; + inst->alg.cra_hash.setkey = crypto_xcbc_digest_setkey; + +out_put_alg: + crypto_mod_put(alg); + return inst; +} + +static void xcbc_free(struct crypto_instance *inst) +{ + crypto_drop_spawn(crypto_instance_ctx(inst)); + kfree(inst); +} + +static struct crypto_template crypto_xcbc_tmpl = { + .name = "xcbc", + .alloc = xcbc_alloc, + .free = xcbc_free, + .module = THIS_MODULE, +}; + +static int __init crypto_xcbc_module_init(void) +{ + return crypto_register_template(&crypto_xcbc_tmpl); +} + +static void __exit crypto_xcbc_module_exit(void) +{ + crypto_unregister_template(&crypto_xcbc_tmpl); +} + +module_init(crypto_xcbc_module_init); +module_exit(crypto_xcbc_module_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("XCBC keyed hash algorithm"); diff --git a/trunk/drivers/acpi/osl.c b/trunk/drivers/acpi/osl.c index 068fe4f100b0..02b30ae6a68e 100644 --- a/trunk/drivers/acpi/osl.c +++ b/trunk/drivers/acpi/osl.c @@ -50,6 +50,7 @@ ACPI_MODULE_NAME("osl") struct acpi_os_dpc { acpi_osd_exec_callback function; void *context; + struct work_struct work; }; #ifdef CONFIG_ACPI_CUSTOM_DSDT @@ -564,12 +565,9 @@ void acpi_os_derive_pci_id(acpi_handle rhandle, /* upper bound */ acpi_os_derive_pci_id_2(rhandle, chandle, id, &is_bridge, &bus_number); } -static void acpi_os_execute_deferred(void *context) +static void acpi_os_execute_deferred(struct work_struct *work) { - struct acpi_os_dpc *dpc = NULL; - - - dpc = (struct acpi_os_dpc *)context; + struct acpi_os_dpc *dpc = container_of(work, struct acpi_os_dpc, work); if (!dpc) { printk(KERN_ERR PREFIX "Invalid (NULL) context\n"); return; @@ -602,7 +600,6 @@ acpi_status acpi_os_execute(acpi_execute_type type, { acpi_status status = AE_OK; struct acpi_os_dpc *dpc; - struct work_struct *task; ACPI_FUNCTION_TRACE("os_queue_for_execution"); @@ -615,28 +612,22 @@ acpi_status acpi_os_execute(acpi_execute_type type, /* * Allocate/initialize DPC structure. Note that this memory will be - * freed by the callee. The kernel handles the tq_struct list in a + * freed by the callee. The kernel handles the work_struct list in a * way that allows us to also free its memory inside the callee. * Because we may want to schedule several tasks with different * parameters we can't use the approach some kernel code uses of - * having a static tq_struct. - * We can save time and code by allocating the DPC and tq_structs - * from the same memory. + * having a static work_struct. */ - dpc = - kmalloc(sizeof(struct acpi_os_dpc) + sizeof(struct work_struct), - GFP_ATOMIC); + dpc = kmalloc(sizeof(struct acpi_os_dpc), GFP_ATOMIC); if (!dpc) return_ACPI_STATUS(AE_NO_MEMORY); dpc->function = function; dpc->context = context; - task = (void *)(dpc + 1); - INIT_WORK(task, acpi_os_execute_deferred, (void *)dpc); - - if (!queue_work(kacpid_wq, task)) { + INIT_WORK(&dpc->work, acpi_os_execute_deferred); + if (!queue_work(kacpid_wq, &dpc->work)) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Call to queue_work() failed.\n")); kfree(dpc); diff --git a/trunk/drivers/amba/bus.c b/trunk/drivers/amba/bus.c index 9e3e2a69c03a..fd5475071acc 100644 --- a/trunk/drivers/amba/bus.c +++ b/trunk/drivers/amba/bus.c @@ -80,12 +80,38 @@ static int amba_resume(struct device *dev) return ret; } +#define amba_attr_func(name,fmt,arg...) \ +static ssize_t name##_show(struct device *_dev, \ + struct device_attribute *attr, char *buf) \ +{ \ + struct amba_device *dev = to_amba_device(_dev); \ + return sprintf(buf, fmt, arg); \ +} + +#define amba_attr(name,fmt,arg...) \ +amba_attr_func(name,fmt,arg) \ +static DEVICE_ATTR(name, S_IRUGO, name##_show, NULL) + +amba_attr_func(id, "%08x\n", dev->periphid); +amba_attr(irq0, "%u\n", dev->irq[0]); +amba_attr(irq1, "%u\n", dev->irq[1]); +amba_attr_func(resource, "\t%016llx\t%016llx\t%016lx\n", + (unsigned long long)dev->res.start, (unsigned long long)dev->res.end, + dev->res.flags); + +static struct device_attribute amba_dev_attrs[] = { + __ATTR_RO(id), + __ATTR_RO(resource), + __ATTR_NULL, +}; + /* * Primecells are part of the Advanced Microcontroller Bus Architecture, * so we call the bus "amba". */ static struct bus_type amba_bustype = { .name = "amba", + .dev_attrs = amba_dev_attrs, .match = amba_match, .uevent = amba_uevent, .suspend = amba_suspend, @@ -169,21 +195,6 @@ static void amba_device_release(struct device *dev) kfree(d); } -#define amba_attr(name,fmt,arg...) \ -static ssize_t show_##name(struct device *_dev, struct device_attribute *attr, char *buf) \ -{ \ - struct amba_device *dev = to_amba_device(_dev); \ - return sprintf(buf, fmt, arg); \ -} \ -static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL) - -amba_attr(id, "%08x\n", dev->periphid); -amba_attr(irq0, "%u\n", dev->irq[0]); -amba_attr(irq1, "%u\n", dev->irq[1]); -amba_attr(resource, "\t%016llx\t%016llx\t%016lx\n", - (unsigned long long)dev->res.start, (unsigned long long)dev->res.end, - dev->res.flags); - /** * amba_device_register - register an AMBA device * @dev: AMBA device to register @@ -208,40 +219,46 @@ int amba_device_register(struct amba_device *dev, struct resource *parent) dev_warn(&dev->dev, "coherent dma mask is unset\n"); ret = request_resource(parent, &dev->res); - if (ret == 0) { - tmp = ioremap(dev->res.start, SZ_4K); - if (!tmp) { - ret = -ENOMEM; - goto out; - } - - for (pid = 0, i = 0; i < 4; i++) - pid |= (readl(tmp + 0xfe0 + 4 * i) & 255) << (i * 8); - for (cid = 0, i = 0; i < 4; i++) - cid |= (readl(tmp + 0xff0 + 4 * i) & 255) << (i * 8); - - iounmap(tmp); - - if (cid == 0xb105f00d) - dev->periphid = pid; - - if (dev->periphid) - ret = device_register(&dev->dev); - else - ret = -ENODEV; - - if (ret == 0) { - device_create_file(&dev->dev, &dev_attr_id); - if (dev->irq[0] != NO_IRQ) - device_create_file(&dev->dev, &dev_attr_irq0); - if (dev->irq[1] != NO_IRQ) - device_create_file(&dev->dev, &dev_attr_irq1); - device_create_file(&dev->dev, &dev_attr_resource); - } else { - out: - release_resource(&dev->res); - } + if (ret) + goto err_out; + + tmp = ioremap(dev->res.start, SZ_4K); + if (!tmp) { + ret = -ENOMEM; + goto err_release; } + + for (pid = 0, i = 0; i < 4; i++) + pid |= (readl(tmp + 0xfe0 + 4 * i) & 255) << (i * 8); + for (cid = 0, i = 0; i < 4; i++) + cid |= (readl(tmp + 0xff0 + 4 * i) & 255) << (i * 8); + + iounmap(tmp); + + if (cid == 0xb105f00d) + dev->periphid = pid; + + if (!dev->periphid) { + ret = -ENODEV; + goto err_release; + } + + ret = device_register(&dev->dev); + if (ret) + goto err_release; + + if (dev->irq[0] != NO_IRQ) + ret = device_create_file(&dev->dev, &dev_attr_irq0); + if (ret == 0 && dev->irq[1] != NO_IRQ) + ret = device_create_file(&dev->dev, &dev_attr_irq1); + if (ret == 0) + return ret; + + device_unregister(&dev->dev); + + err_release: + release_resource(&dev->res); + err_out: return ret; } diff --git a/trunk/drivers/ata/libata-core.c b/trunk/drivers/ata/libata-core.c index f8ec3896b793..011c0a8a2dcc 100644 --- a/trunk/drivers/ata/libata-core.c +++ b/trunk/drivers/ata/libata-core.c @@ -1081,7 +1081,7 @@ static unsigned int ata_id_xfermask(const u16 *id) * ata_port_queue_task - Queue port_task * @ap: The ata_port to queue port_task for * @fn: workqueue function to be scheduled - * @data: data value to pass to workqueue function + * @data: data for @fn to use * @delay: delay time for workqueue function * * Schedule @fn(@data) for execution after @delay jiffies using @@ -1096,7 +1096,7 @@ static unsigned int ata_id_xfermask(const u16 *id) * LOCKING: * Inherited from caller. */ -void ata_port_queue_task(struct ata_port *ap, void (*fn)(void *), void *data, +void ata_port_queue_task(struct ata_port *ap, work_func_t fn, void *data, unsigned long delay) { int rc; @@ -1104,12 +1104,10 @@ void ata_port_queue_task(struct ata_port *ap, void (*fn)(void *), void *data, if (ap->pflags & ATA_PFLAG_FLUSH_PORT_TASK) return; - PREPARE_WORK(&ap->port_task, fn, data); + PREPARE_DELAYED_WORK(&ap->port_task, fn); + ap->port_task_data = data; - if (!delay) - rc = queue_work(ata_wq, &ap->port_task); - else - rc = queue_delayed_work(ata_wq, &ap->port_task, delay); + rc = queue_delayed_work(ata_wq, &ap->port_task, delay); /* rc == 0 means that another user is using port task */ WARN_ON(rc == 0); @@ -2305,7 +2303,7 @@ int ata_timing_compute(struct ata_device *adev, unsigned short speed, * DMA cycle timing is slower/equal than the fastest PIO timing. */ - if (speed > XFER_PIO_4) { + if (speed > XFER_PIO_6) { ata_timing_compute(adev, adev->pio_mode, &p, T, UT); ata_timing_merge(&p, t, t, ATA_TIMING_ALL); } @@ -4588,10 +4586,11 @@ int ata_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc, return poll_next; } -static void ata_pio_task(void *_data) +static void ata_pio_task(struct work_struct *work) { - struct ata_queued_cmd *qc = _data; - struct ata_port *ap = qc->ap; + struct ata_port *ap = + container_of(work, struct ata_port, port_task.work); + struct ata_queued_cmd *qc = ap->port_task_data; u8 status; int poll_next; @@ -4961,6 +4960,7 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc) if (ap->flags & ATA_FLAG_PIO_POLLING) { switch (qc->tf.protocol) { case ATA_PROT_PIO: + case ATA_PROT_NODATA: case ATA_PROT_ATAPI: case ATA_PROT_ATAPI_NODATA: qc->tf.flags |= ATA_TFLAG_POLLING; @@ -5635,9 +5635,9 @@ void ata_port_init(struct ata_port *ap, struct ata_host *host, ap->msg_enable = ATA_MSG_DRV | ATA_MSG_ERR | ATA_MSG_WARN; #endif - INIT_WORK(&ap->port_task, NULL, NULL); - INIT_WORK(&ap->hotplug_task, ata_scsi_hotplug, ap); - INIT_WORK(&ap->scsi_rescan_task, ata_scsi_dev_rescan, ap); + INIT_DELAYED_WORK(&ap->port_task, NULL); + INIT_DELAYED_WORK(&ap->hotplug_task, ata_scsi_hotplug); + INIT_WORK(&ap->scsi_rescan_task, ata_scsi_dev_rescan); INIT_LIST_HEAD(&ap->eh_done_q); init_waitqueue_head(&ap->eh_wait_q); diff --git a/trunk/drivers/ata/libata-eh.c b/trunk/drivers/ata/libata-eh.c index 76a85dfb7307..08ad44b3e48f 100644 --- a/trunk/drivers/ata/libata-eh.c +++ b/trunk/drivers/ata/libata-eh.c @@ -332,7 +332,7 @@ void ata_scsi_error(struct Scsi_Host *host) if (ap->pflags & ATA_PFLAG_LOADING) ap->pflags &= ~ATA_PFLAG_LOADING; else if (ap->pflags & ATA_PFLAG_SCSI_HOTPLUG) - queue_work(ata_aux_wq, &ap->hotplug_task); + queue_delayed_work(ata_aux_wq, &ap->hotplug_task, 0); if (ap->pflags & ATA_PFLAG_RECOVERED) ata_port_printk(ap, KERN_INFO, "EH complete\n"); diff --git a/trunk/drivers/ata/libata-scsi.c b/trunk/drivers/ata/libata-scsi.c index 8eaace94d963..664e1377b54c 100644 --- a/trunk/drivers/ata/libata-scsi.c +++ b/trunk/drivers/ata/libata-scsi.c @@ -2963,7 +2963,7 @@ static void ata_scsi_remove_dev(struct ata_device *dev) /** * ata_scsi_hotplug - SCSI part of hotplug - * @data: Pointer to ATA port to perform SCSI hotplug on + * @work: Pointer to ATA port to perform SCSI hotplug on * * Perform SCSI part of hotplug. It's executed from a separate * workqueue after EH completes. This is necessary because SCSI @@ -2973,9 +2973,10 @@ static void ata_scsi_remove_dev(struct ata_device *dev) * LOCKING: * Kernel thread context (may sleep). */ -void ata_scsi_hotplug(void *data) +void ata_scsi_hotplug(struct work_struct *work) { - struct ata_port *ap = data; + struct ata_port *ap = + container_of(work, struct ata_port, hotplug_task.work); int i; if (ap->pflags & ATA_PFLAG_UNLOADING) { @@ -3076,7 +3077,7 @@ static int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel, /** * ata_scsi_dev_rescan - initiate scsi_rescan_device() - * @data: Pointer to ATA port to perform scsi_rescan_device() + * @work: Pointer to ATA port to perform scsi_rescan_device() * * After ATA pass thru (SAT) commands are executed successfully, * libata need to propagate the changes to SCSI layer. This @@ -3086,9 +3087,10 @@ static int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel, * LOCKING: * Kernel thread context (may sleep). */ -void ata_scsi_dev_rescan(void *data) +void ata_scsi_dev_rescan(struct work_struct *work) { - struct ata_port *ap = data; + struct ata_port *ap = + container_of(work, struct ata_port, scsi_rescan_task); unsigned long flags; unsigned int i; diff --git a/trunk/drivers/ata/libata.h b/trunk/drivers/ata/libata.h index 107b2b565229..81ae41d5f23f 100644 --- a/trunk/drivers/ata/libata.h +++ b/trunk/drivers/ata/libata.h @@ -94,7 +94,7 @@ extern struct scsi_transport_template ata_scsi_transport_template; extern void ata_scsi_scan_host(struct ata_port *ap); extern int ata_scsi_offline_dev(struct ata_device *dev); -extern void ata_scsi_hotplug(void *data); +extern void ata_scsi_hotplug(struct work_struct *work); extern unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf, unsigned int buflen); @@ -124,7 +124,7 @@ extern void ata_scsi_rbuf_fill(struct ata_scsi_args *args, unsigned int (*actor) (struct ata_scsi_args *args, u8 *rbuf, unsigned int buflen)); extern void ata_schedule_scsi_eh(struct Scsi_Host *shost); -extern void ata_scsi_dev_rescan(void *data); +extern void ata_scsi_dev_rescan(struct work_struct *work); extern int ata_bus_probe(struct ata_port *ap); /* libata-eh.c */ diff --git a/trunk/drivers/ata/pata_pcmcia.c b/trunk/drivers/ata/pata_pcmcia.c index 4ca6fa5dcb42..9ed7f58424a3 100644 --- a/trunk/drivers/ata/pata_pcmcia.c +++ b/trunk/drivers/ata/pata_pcmcia.c @@ -154,19 +154,12 @@ static int pcmcia_init_one(struct pcmcia_device *pdev) tuple.TupleOffset = 0; tuple.TupleDataMax = 255; tuple.Attributes = 0; - tuple.DesiredTuple = CISTPL_CONFIG; - - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(pdev, &tuple)); - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(pdev, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(pdev, &tuple, &stk->parse)); - pdev->conf.ConfigBase = stk->parse.config.base; - pdev->conf.Present = stk->parse.config.rmask[0]; /* See if we have a manufacturer identifier. Use it to set is_kme for vendor quirks */ - tuple.DesiredTuple = CISTPL_MANFID; - if (!pcmcia_get_first_tuple(pdev, &tuple) && !pcmcia_get_tuple_data(pdev, &tuple) && !pcmcia_parse_tuple(pdev, &tuple, &stk->parse)) - is_kme = ((stk->parse.manfid.manf == MANFID_KME) && ((stk->parse.manfid.card == PRODID_KME_KXLC005_A) || (stk->parse.manfid.card == PRODID_KME_KXLC005_B))); + is_kme = ((pdev->manf_id == MANFID_KME) && + ((pdev->card_id == PRODID_KME_KXLC005_A) || + (pdev->card_id == PRODID_KME_KXLC005_B))); /* Not sure if this is right... look up the current Vcc */ CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(pdev, &stk->conf)); @@ -356,8 +349,10 @@ static struct pcmcia_device_id pcmcia_devices[] = { PCMCIA_DEVICE_PROD_ID12("SMI VENDOR", "SMI PRODUCT", 0x30896c92, 0x703cc5f6), PCMCIA_DEVICE_PROD_ID12("TOSHIBA", "MK2001MPL", 0xb4585a1a, 0x3489e003), PCMCIA_DEVICE_PROD_ID1("TRANSCEND 512M ", 0xd0909443), + PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS1GCF80", 0x709b1bf1, 0x2a54d4b1), PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS4GCF120", 0x709b1bf1, 0xf54a91c8), PCMCIA_DEVICE_PROD_ID12("WIT", "IDE16", 0x244e5994, 0x3e232852), + PCMCIA_DEVICE_PROD_ID12("WEIDA", "TWTTI", 0xcc7cf69c, 0x212bb918), PCMCIA_DEVICE_PROD_ID1("STI Flash", 0xe4a13209), PCMCIA_DEVICE_PROD_ID12("STI", "Flash 5.0", 0xbf2df18d, 0x8cb57a0e), PCMCIA_MFC_DEVICE_PROD_ID12(1, "SanDisk", "ConnectPlus", 0x7a954bd9, 0x74be00c6), diff --git a/trunk/drivers/ata/sata_promise.c b/trunk/drivers/ata/sata_promise.c index a2778cf016bc..f055874a6ec5 100644 --- a/trunk/drivers/ata/sata_promise.c +++ b/trunk/drivers/ata/sata_promise.c @@ -66,15 +66,17 @@ enum { board_2037x = 0, /* FastTrak S150 TX2plus */ board_20319 = 1, /* FastTrak S150 TX4 */ board_20619 = 2, /* FastTrak TX4000 */ - board_20771 = 3, /* FastTrak TX2300 */ - board_2057x = 4, /* SATAII150 Tx2plus */ - board_40518 = 5, /* SATAII150 Tx4 */ + board_2057x = 3, /* SATAII150 Tx2plus */ + board_40518 = 4, /* SATAII150 Tx4 */ PDC_HAS_PATA = (1 << 1), /* PDC20375/20575 has PATA */ + /* PDC_CTLSTAT bit definitions */ + PDC_DMA_ENABLE = (1 << 7), + PDC_IRQ_DISABLE = (1 << 10), PDC_RESET = (1 << 11), /* HDMA reset */ - PDC_COMMON_FLAGS = ATA_FLAG_NO_LEGACY | ATA_FLAG_SRST | + PDC_COMMON_FLAGS = ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO | ATA_FLAG_NO_ATAPI | ATA_FLAG_PIO_POLLING, @@ -90,7 +92,6 @@ struct pdc_port_priv { struct pdc_host_priv { unsigned long flags; - int hotplug_offset; }; static u32 pdc_sata_scr_read (struct ata_port *ap, unsigned int sc_reg); @@ -101,13 +102,16 @@ static void pdc_eng_timeout(struct ata_port *ap); static int pdc_port_start(struct ata_port *ap); static void pdc_port_stop(struct ata_port *ap); static void pdc_pata_phy_reset(struct ata_port *ap); -static void pdc_sata_phy_reset(struct ata_port *ap); static void pdc_qc_prep(struct ata_queued_cmd *qc); static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf); static void pdc_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf); static void pdc_irq_clear(struct ata_port *ap); static unsigned int pdc_qc_issue_prot(struct ata_queued_cmd *qc); static void pdc_host_stop(struct ata_host *host); +static void pdc_freeze(struct ata_port *ap); +static void pdc_thaw(struct ata_port *ap); +static void pdc_error_handler(struct ata_port *ap); +static void pdc_post_internal_cmd(struct ata_queued_cmd *qc); static struct scsi_host_template pdc_ata_sht = { @@ -136,11 +140,12 @@ static const struct ata_port_operations pdc_sata_ops = { .exec_command = pdc_exec_command_mmio, .dev_select = ata_std_dev_select, - .phy_reset = pdc_sata_phy_reset, - .qc_prep = pdc_qc_prep, .qc_issue = pdc_qc_issue_prot, - .eng_timeout = pdc_eng_timeout, + .freeze = pdc_freeze, + .thaw = pdc_thaw, + .error_handler = pdc_error_handler, + .post_internal_cmd = pdc_post_internal_cmd, .data_xfer = ata_mmio_data_xfer, .irq_handler = pdc_interrupt, .irq_clear = pdc_irq_clear, @@ -198,23 +203,13 @@ static const struct ata_port_info pdc_port_info[] = { /* board_20619 */ { .sht = &pdc_ata_sht, - .flags = PDC_COMMON_FLAGS | ATA_FLAG_SLAVE_POSS, + .flags = PDC_COMMON_FLAGS | ATA_FLAG_SRST | ATA_FLAG_SLAVE_POSS, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x7f, /* udma0-6 ; FIXME */ .port_ops = &pdc_pata_ops, }, - /* board_20771 */ - { - .sht = &pdc_ata_sht, - .flags = PDC_COMMON_FLAGS | ATA_FLAG_SATA, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ - .udma_mask = 0x7f, /* udma0-6 ; FIXME */ - .port_ops = &pdc_sata_ops, - }, - /* board_2057x */ { .sht = &pdc_ata_sht, @@ -244,6 +239,7 @@ static const struct pci_device_id pdc_ata_pci_tbl[] = { { PCI_VDEVICE(PROMISE, 0x3570), board_2057x }, { PCI_VDEVICE(PROMISE, 0x3571), board_2057x }, { PCI_VDEVICE(PROMISE, 0x3574), board_2057x }, + { PCI_VDEVICE(PROMISE, 0x3577), board_2057x }, { PCI_VDEVICE(PROMISE, 0x3d73), board_2057x }, { PCI_VDEVICE(PROMISE, 0x3d75), board_2057x }, @@ -256,15 +252,6 @@ static const struct pci_device_id pdc_ata_pci_tbl[] = { { PCI_VDEVICE(PROMISE, 0x6629), board_20619 }, -/* TODO: remove all associated board_20771 code, as it completely - * duplicates board_2037x code, unless reason for separation can be - * divined. - */ -#if 0 - { PCI_VDEVICE(PROMISE, 0x3570), board_20771 }, -#endif - { PCI_VDEVICE(PROMISE, 0x3577), board_20771 }, - { } /* terminate list */ }; @@ -366,12 +353,6 @@ static void pdc_reset_port(struct ata_port *ap) readl(mmio); /* flush */ } -static void pdc_sata_phy_reset(struct ata_port *ap) -{ - pdc_reset_port(ap); - sata_phy_reset(ap); -} - static void pdc_pata_cbl_detect(struct ata_port *ap) { u8 tmp; @@ -439,6 +420,61 @@ static void pdc_qc_prep(struct ata_queued_cmd *qc) } } +static void pdc_freeze(struct ata_port *ap) +{ + void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr; + u32 tmp; + + tmp = readl(mmio + PDC_CTLSTAT); + tmp |= PDC_IRQ_DISABLE; + tmp &= ~PDC_DMA_ENABLE; + writel(tmp, mmio + PDC_CTLSTAT); + readl(mmio + PDC_CTLSTAT); /* flush */ +} + +static void pdc_thaw(struct ata_port *ap) +{ + void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr; + u32 tmp; + + /* clear IRQ */ + readl(mmio + PDC_INT_SEQMASK); + + /* turn IRQ back on */ + tmp = readl(mmio + PDC_CTLSTAT); + tmp &= ~PDC_IRQ_DISABLE; + writel(tmp, mmio + PDC_CTLSTAT); + readl(mmio + PDC_CTLSTAT); /* flush */ +} + +static void pdc_error_handler(struct ata_port *ap) +{ + ata_reset_fn_t hardreset; + + if (!(ap->pflags & ATA_PFLAG_FROZEN)) + pdc_reset_port(ap); + + hardreset = NULL; + if (sata_scr_valid(ap)) + hardreset = sata_std_hardreset; + + /* perform recovery */ + ata_do_eh(ap, ata_std_prereset, ata_std_softreset, hardreset, + ata_std_postreset); +} + +static void pdc_post_internal_cmd(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + + if (qc->flags & ATA_QCFLAG_FAILED) + qc->err_mask |= AC_ERR_OTHER; + + /* make DMA engine forget about the failed command */ + if (qc->err_mask) + pdc_reset_port(ap); +} + static void pdc_eng_timeout(struct ata_port *ap) { struct ata_host *host = ap->host; @@ -645,9 +681,14 @@ static void pdc_host_init(unsigned int chip_id, struct ata_probe_ent *pe) { void __iomem *mmio = pe->mmio_base; struct pdc_host_priv *hp = pe->private_data; - int hotplug_offset = hp->hotplug_offset; + int hotplug_offset; u32 tmp; + if (hp->flags & PDC_FLAG_GEN_II) + hotplug_offset = PDC2_SATA_PLUG_CSR; + else + hotplug_offset = PDC_SATA_PLUG_CSR; + /* * Except for the hotplug stuff, this is voodoo from the * Promise driver. Label this entire section @@ -742,8 +783,6 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e goto err_out_free_ent; } - /* Set default hotplug offset */ - hp->hotplug_offset = PDC_SATA_PLUG_CSR; probe_ent->private_data = hp; probe_ent->sht = pdc_port_info[board_idx].sht; @@ -767,8 +806,6 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e switch (board_idx) { case board_40518: hp->flags |= PDC_FLAG_GEN_II; - /* Override hotplug offset for SATAII150 */ - hp->hotplug_offset = PDC2_SATA_PLUG_CSR; /* Fall through */ case board_20319: probe_ent->n_ports = 4; @@ -780,10 +817,7 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e probe_ent->port[3].scr_addr = base + 0x700; break; case board_2057x: - case board_20771: hp->flags |= PDC_FLAG_GEN_II; - /* Override hotplug offset for SATAII150 */ - hp->hotplug_offset = PDC2_SATA_PLUG_CSR; /* Fall through */ case board_2037x: probe_ent->n_ports = 2; diff --git a/trunk/drivers/atm/Kconfig b/trunk/drivers/atm/Kconfig index cfa5af883e13..2ddd76fdbc43 100644 --- a/trunk/drivers/atm/Kconfig +++ b/trunk/drivers/atm/Kconfig @@ -242,6 +242,7 @@ config ATM_IDT77252_USE_SUNI config ATM_AMBASSADOR tristate "Madge Ambassador (Collage PCI 155 Server)" depends on PCI && ATM + select BITREVERSE help This is a driver for ATMizer based ATM card produced by Madge Networks Ltd. Say Y (or M to compile as a module named ambassador) diff --git a/trunk/drivers/atm/Makefile b/trunk/drivers/atm/Makefile index b5077ce8cb40..1b16f8166b09 100644 --- a/trunk/drivers/atm/Makefile +++ b/trunk/drivers/atm/Makefile @@ -41,7 +41,7 @@ ifeq ($(CONFIG_ATM_FORE200E_PCA),y) # guess the target endianess to choose the right PCA-200E firmware image ifeq ($(CONFIG_ATM_FORE200E_PCA_DEFAULT_FW),y) byteorder.h := include$(if $(patsubst $(srctree),,$(objtree)),2)/asm/byteorder.h - CONFIG_ATM_FORE200E_PCA_FW := $(obj)/pca200e$(if $(shell $(CC) -E -dM $(byteorder.h) | grep ' __LITTLE_ENDIAN '),.bin,_ecd.bin2) + CONFIG_ATM_FORE200E_PCA_FW := $(obj)/pca200e$(if $(shell $(CC) $(CPPFLAGS) -E -dM $(byteorder.h) | grep ' __LITTLE_ENDIAN '),.bin,_ecd.bin2) endif endif diff --git a/trunk/drivers/atm/ambassador.c b/trunk/drivers/atm/ambassador.c index afa7d750a593..3c372e08f77d 100644 --- a/trunk/drivers/atm/ambassador.c +++ b/trunk/drivers/atm/ambassador.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -2068,18 +2069,6 @@ static void __devinit amb_ucode_version (amb_dev * dev) { PRINTK (KERN_INFO, "microcode version is %u.%u", major, minor); } -// swap bits within byte to get Ethernet ordering -static u8 bit_swap (u8 byte) -{ - const u8 swap[] = { - 0x0, 0x8, 0x4, 0xc, - 0x2, 0xa, 0x6, 0xe, - 0x1, 0x9, 0x5, 0xd, - 0x3, 0xb, 0x7, 0xf - }; - return ((swap[byte & 0xf]<<4) | swap[byte>>4]); -} - // get end station address static void __devinit amb_esi (amb_dev * dev, u8 * esi) { u32 lower4; @@ -2101,9 +2090,9 @@ static void __devinit amb_esi (amb_dev * dev, u8 * esi) { PRINTDB (DBG_INIT, "ESI:"); for (i = 0; i < ESI_LEN; ++i) { if (i < 4) - esi[i] = bit_swap (lower4>>(8*i)); + esi[i] = bitrev8(lower4>>(8*i)); else - esi[i] = bit_swap (upper2>>(8*(i-4))); + esi[i] = bitrev8(upper2>>(8*(i-4))); PRINTDM (DBG_INIT, " %02x", esi[i]); } diff --git a/trunk/drivers/atm/he.c b/trunk/drivers/atm/he.c index c7314a79da0f..7d9b4e52f0bf 100644 --- a/trunk/drivers/atm/he.c +++ b/trunk/drivers/atm/he.c @@ -820,7 +820,7 @@ he_init_group(struct he_dev *he_dev, int group) void *cpuaddr; #ifdef USE_RBPS_POOL - cpuaddr = pci_pool_alloc(he_dev->rbps_pool, SLAB_KERNEL|SLAB_DMA, &dma_handle); + cpuaddr = pci_pool_alloc(he_dev->rbps_pool, GFP_KERNEL|GFP_DMA, &dma_handle); if (cpuaddr == NULL) return -ENOMEM; #else @@ -884,7 +884,7 @@ he_init_group(struct he_dev *he_dev, int group) void *cpuaddr; #ifdef USE_RBPL_POOL - cpuaddr = pci_pool_alloc(he_dev->rbpl_pool, SLAB_KERNEL|SLAB_DMA, &dma_handle); + cpuaddr = pci_pool_alloc(he_dev->rbpl_pool, GFP_KERNEL|GFP_DMA, &dma_handle); if (cpuaddr == NULL) return -ENOMEM; #else @@ -1724,7 +1724,7 @@ __alloc_tpd(struct he_dev *he_dev) struct he_tpd *tpd; dma_addr_t dma_handle; - tpd = pci_pool_alloc(he_dev->tpd_pool, SLAB_ATOMIC|SLAB_DMA, &dma_handle); + tpd = pci_pool_alloc(he_dev->tpd_pool, GFP_ATOMIC|GFP_DMA, &dma_handle); if (tpd == NULL) return NULL; diff --git a/trunk/drivers/atm/idt77252.c b/trunk/drivers/atm/idt77252.c index 87b17c33b3f9..f40786121948 100644 --- a/trunk/drivers/atm/idt77252.c +++ b/trunk/drivers/atm/idt77252.c @@ -135,7 +135,7 @@ static int idt77252_change_qos(struct atm_vcc *vcc, struct atm_qos *qos, int flags); static int idt77252_proc_read(struct atm_dev *dev, loff_t * pos, char *page); -static void idt77252_softint(void *dev_id); +static void idt77252_softint(struct work_struct *work); static struct atmdev_ops idt77252_ops = @@ -2866,9 +2866,10 @@ idt77252_interrupt(int irq, void *dev_id) } static void -idt77252_softint(void *dev_id) +idt77252_softint(struct work_struct *work) { - struct idt77252_dev *card = dev_id; + struct idt77252_dev *card = + container_of(work, struct idt77252_dev, tqueue); u32 stat; int done; @@ -3697,7 +3698,7 @@ idt77252_init_one(struct pci_dev *pcidev, const struct pci_device_id *id) card->pcidev = pcidev; sprintf(card->name, "idt77252-%d", card->index); - INIT_WORK(&card->tqueue, idt77252_softint, (void *)card); + INIT_WORK(&card->tqueue, idt77252_softint); membase = pci_resource_start(pcidev, 1); srambase = pci_resource_start(pcidev, 2); diff --git a/trunk/drivers/base/core.c b/trunk/drivers/base/core.c index e4b530ef757d..67b79a7592a9 100644 --- a/trunk/drivers/base/core.c +++ b/trunk/drivers/base/core.c @@ -386,6 +386,7 @@ void device_initialize(struct device *dev) INIT_LIST_HEAD(&dev->node); init_MUTEX(&dev->sem); device_init_wakeup(dev, 0); + set_dev_node(dev, -1); } #ifdef CONFIG_SYSFS_DEPRECATED diff --git a/trunk/drivers/base/cpu.c b/trunk/drivers/base/cpu.c index 1f745f12f94e..7fd095efaebd 100644 --- a/trunk/drivers/base/cpu.c +++ b/trunk/drivers/base/cpu.c @@ -104,8 +104,8 @@ static SYSDEV_ATTR(crash_notes, 0400, show_crash_notes, NULL); /* * register_cpu - Setup a driverfs device for a CPU. - * @cpu - Callers can set the cpu->no_control field to 1, to indicate not to - * generate a control file in sysfs for this CPU. + * @cpu - cpu->hotpluggable field set to 1 will generate a control file in + * sysfs for this CPU. * @num - CPU number to use when creating the device. * * Initialize and register the CPU device. @@ -119,7 +119,7 @@ int __devinit register_cpu(struct cpu *cpu, int num) error = sysdev_register(&cpu->sysdev); - if (!error && !cpu->no_control) + if (!error && cpu->hotpluggable) register_cpu_control(cpu); if (!error) cpu_sys_devices[num] = &cpu->sysdev; diff --git a/trunk/drivers/base/dmapool.c b/trunk/drivers/base/dmapool.c index b2efbd4cf710..dbe0735f8c9e 100644 --- a/trunk/drivers/base/dmapool.c +++ b/trunk/drivers/base/dmapool.c @@ -126,7 +126,7 @@ dma_pool_create (const char *name, struct device *dev, } else if (allocation < size) return NULL; - if (!(retval = kmalloc (sizeof *retval, SLAB_KERNEL))) + if (!(retval = kmalloc (sizeof *retval, GFP_KERNEL))) return retval; strlcpy (retval->name, name, sizeof retval->name); @@ -297,7 +297,7 @@ dma_pool_alloc (struct dma_pool *pool, gfp_t mem_flags, dma_addr_t *handle) } } } - if (!(page = pool_alloc_page (pool, SLAB_ATOMIC))) { + if (!(page = pool_alloc_page (pool, GFP_ATOMIC))) { if (mem_flags & __GFP_WAIT) { DECLARE_WAITQUEUE (wait, current); diff --git a/trunk/drivers/base/memory.c b/trunk/drivers/base/memory.c index c6b7d9c4b651..74b96795d2f5 100644 --- a/trunk/drivers/base/memory.c +++ b/trunk/drivers/base/memory.c @@ -290,9 +290,8 @@ static CLASS_ATTR(block_size_bytes, 0444, print_block_size, NULL); static int block_size_init(void) { - sysfs_create_file(&memory_sysdev_class.kset.kobj, - &class_attr_block_size_bytes.attr); - return 0; + return sysfs_create_file(&memory_sysdev_class.kset.kobj, + &class_attr_block_size_bytes.attr); } /* @@ -323,12 +322,14 @@ static CLASS_ATTR(probe, 0700, NULL, memory_probe_store); static int memory_probe_init(void) { - sysfs_create_file(&memory_sysdev_class.kset.kobj, - &class_attr_probe.attr); - return 0; + return sysfs_create_file(&memory_sysdev_class.kset.kobj, + &class_attr_probe.attr); } #else -#define memory_probe_init(...) do {} while (0) +static inline int memory_probe_init(void) +{ + return 0; +} #endif /* @@ -431,9 +432,12 @@ int __init memory_dev_init(void) { unsigned int i; int ret; + int err; memory_sysdev_class.kset.uevent_ops = &memory_uevent_ops; ret = sysdev_class_register(&memory_sysdev_class); + if (ret) + goto out; /* * Create entries for memory sections that were found @@ -442,11 +446,19 @@ int __init memory_dev_init(void) for (i = 0; i < NR_MEM_SECTIONS; i++) { if (!valid_section_nr(i)) continue; - add_memory_block(0, __nr_to_section(i), MEM_ONLINE, 0); + err = add_memory_block(0, __nr_to_section(i), MEM_ONLINE, 0); + if (!ret) + ret = err; } - memory_probe_init(); - block_size_init(); - + err = memory_probe_init(); + if (!ret) + ret = err; + err = block_size_init(); + if (!ret) + ret = err; +out: + if (ret) + printk(KERN_ERR "%s() failed: %d\n", __FUNCTION__, ret); return ret; } diff --git a/trunk/drivers/base/topology.c b/trunk/drivers/base/topology.c index 3d12b85b0962..067a9e8bc377 100644 --- a/trunk/drivers/base/topology.c +++ b/trunk/drivers/base/topology.c @@ -108,7 +108,6 @@ static int __cpuinit topology_add_dev(unsigned int cpu) return rc; } -#ifdef CONFIG_HOTPLUG_CPU static void __cpuinit topology_remove_dev(unsigned int cpu) { struct sys_device *sys_dev = get_cpu_sysdev(cpu); @@ -136,7 +135,6 @@ static int __cpuinit topology_cpu_callback(struct notifier_block *nfb, } return rc ? NOTIFY_BAD : NOTIFY_OK; } -#endif static int __cpuinit topology_sysfs_init(void) { diff --git a/trunk/drivers/block/DAC960.c b/trunk/drivers/block/DAC960.c index 742d07403101..8d81a3a64c07 100644 --- a/trunk/drivers/block/DAC960.c +++ b/trunk/drivers/block/DAC960.c @@ -324,13 +324,13 @@ static boolean DAC960_CreateAuxiliaryStructures(DAC960_Controller_T *Controller) Command->Next = Controller->FreeCommands; Controller->FreeCommands = Command; Controller->Commands[CommandIdentifier-1] = Command; - ScatterGatherCPU = pci_pool_alloc(ScatterGatherPool, SLAB_ATOMIC, + ScatterGatherCPU = pci_pool_alloc(ScatterGatherPool, GFP_ATOMIC, &ScatterGatherDMA); if (ScatterGatherCPU == NULL) return DAC960_Failure(Controller, "AUXILIARY STRUCTURE CREATION"); if (RequestSensePool != NULL) { - RequestSenseCPU = pci_pool_alloc(RequestSensePool, SLAB_ATOMIC, + RequestSenseCPU = pci_pool_alloc(RequestSensePool, GFP_ATOMIC, &RequestSenseDMA); if (RequestSenseCPU == NULL) { pci_pool_free(ScatterGatherPool, ScatterGatherCPU, diff --git a/trunk/drivers/block/Kconfig b/trunk/drivers/block/Kconfig index 17dc22282e14..ce9cfcb6071c 100644 --- a/trunk/drivers/block/Kconfig +++ b/trunk/drivers/block/Kconfig @@ -168,7 +168,8 @@ config BLK_CPQ_CISS_DA config CISS_SCSI_TAPE bool "SCSI tape drive support for Smart Array 5xxx" - depends on BLK_CPQ_CISS_DA && SCSI && PROC_FS + depends on BLK_CPQ_CISS_DA && PROC_FS + depends on SCSI=y || SCSI=BLK_CPQ_CISS_DA help When enabled (Y), this option allows SCSI tape drives and SCSI medium changers (tape robots) to be accessed via a Compaq 5xxx array @@ -305,6 +306,7 @@ config BLK_DEV_LOOP config BLK_DEV_CRYPTOLOOP tristate "Cryptoloop Support" select CRYPTO + select CRYPTO_CBC depends on BLK_DEV_LOOP ---help--- Say Y here if you want to be able to use the ciphers that are @@ -429,14 +431,18 @@ config CDROM_PKTCDVD tristate "Packet writing on CD/DVD media" depends on !UML help - If you have a CDROM drive that supports packet writing, say Y to - include preliminary support. It should work with any MMC/Mt Fuji - compliant ATAPI or SCSI drive, which is just about any newer CD - writer. + If you have a CDROM/DVD drive that supports packet writing, say + Y to include support. It should work with any MMC/Mt Fuji + compliant ATAPI or SCSI drive, which is just about any newer + DVD/CD writer. - Currently only writing to CD-RW, DVD-RW and DVD+RW discs is possible. + Currently only writing to CD-RW, DVD-RW, DVD+RW and DVDRAM discs + is possible. DVD-RW disks must be in restricted overwrite mode. + See the file + for further information on the use of this driver. + To compile this driver as a module, choose M here: the module will be called pktcdvd. diff --git a/trunk/drivers/block/acsi_slm.c b/trunk/drivers/block/acsi_slm.c index 8e41c87b026e..e04be94d195c 100644 --- a/trunk/drivers/block/acsi_slm.c +++ b/trunk/drivers/block/acsi_slm.c @@ -363,7 +363,7 @@ static ssize_t slm_read( struct file *file, char *buf, size_t count, loff_t *ppos ) { - struct inode *node = file->f_dentry->d_inode; + struct inode *node = file->f_path.dentry->d_inode; unsigned long page; int length; int end; @@ -618,7 +618,7 @@ static ssize_t slm_write( struct file *file, const char *buf, size_t count, loff_t *ppos ) { - struct inode *node = file->f_dentry->d_inode; + struct inode *node = file->f_path.dentry->d_inode; int device = iminor(node); int n, filled, w, h; diff --git a/trunk/drivers/block/aoe/aoe.h b/trunk/drivers/block/aoe/aoe.h index 6d111228cfac..2308e83e5f33 100644 --- a/trunk/drivers/block/aoe/aoe.h +++ b/trunk/drivers/block/aoe/aoe.h @@ -159,7 +159,7 @@ void aoecmd_work(struct aoedev *d); void aoecmd_cfg(ushort aoemajor, unsigned char aoeminor); void aoecmd_ata_rsp(struct sk_buff *); void aoecmd_cfg_rsp(struct sk_buff *); -void aoecmd_sleepwork(void *vp); +void aoecmd_sleepwork(struct work_struct *); struct sk_buff *new_skb(ulong); int aoedev_init(void); diff --git a/trunk/drivers/block/aoe/aoeblk.c b/trunk/drivers/block/aoe/aoeblk.c index aa25f8b09fe3..478489c568a4 100644 --- a/trunk/drivers/block/aoe/aoeblk.c +++ b/trunk/drivers/block/aoe/aoeblk.c @@ -12,7 +12,7 @@ #include #include "aoe.h" -static kmem_cache_t *buf_pool_cache; +static struct kmem_cache *buf_pool_cache; static ssize_t aoedisk_show_state(struct gendisk * disk, char *page) { diff --git a/trunk/drivers/block/aoe/aoecmd.c b/trunk/drivers/block/aoe/aoecmd.c index 8a13b1af8bab..97f7f535f412 100644 --- a/trunk/drivers/block/aoe/aoecmd.c +++ b/trunk/drivers/block/aoe/aoecmd.c @@ -408,9 +408,9 @@ rexmit_timer(ulong vp) /* this function performs work that has been deferred until sleeping is OK */ void -aoecmd_sleepwork(void *vp) +aoecmd_sleepwork(struct work_struct *work) { - struct aoedev *d = (struct aoedev *) vp; + struct aoedev *d = container_of(work, struct aoedev, work); if (d->flags & DEVFL_GDALLOC) aoeblk_gdalloc(d); diff --git a/trunk/drivers/block/aoe/aoedev.c b/trunk/drivers/block/aoe/aoedev.c index 6125921bbec4..05a97197c918 100644 --- a/trunk/drivers/block/aoe/aoedev.c +++ b/trunk/drivers/block/aoe/aoedev.c @@ -88,7 +88,7 @@ aoedev_newdev(ulong nframes) kfree(d); return NULL; } - INIT_WORK(&d->work, aoecmd_sleepwork, d); + INIT_WORK(&d->work, aoecmd_sleepwork); spin_lock_init(&d->lock); init_timer(&d->timer); d->timer.data = (ulong) d; diff --git a/trunk/drivers/block/cciss.c b/trunk/drivers/block/cciss.c index 4105c3bf3476..ee159edb6b88 100644 --- a/trunk/drivers/block/cciss.c +++ b/trunk/drivers/block/cciss.c @@ -47,14 +47,15 @@ #include #define CCISS_DRIVER_VERSION(maj,min,submin) ((maj<<16)|(min<<8)|(submin)) -#define DRIVER_NAME "HP CISS Driver (v 3.6.10)" -#define DRIVER_VERSION CCISS_DRIVER_VERSION(3,6,10) +#define DRIVER_NAME "HP CISS Driver (v 3.6.14)" +#define DRIVER_VERSION CCISS_DRIVER_VERSION(3,6,14) /* Embedded module documentation macros - see modules.h */ MODULE_AUTHOR("Hewlett-Packard Company"); -MODULE_DESCRIPTION("Driver for HP Controller SA5xxx SA6xxx version 3.6.10"); +MODULE_DESCRIPTION("Driver for HP Controller SA5xxx SA6xxx version 3.6.14"); MODULE_SUPPORTED_DEVICE("HP SA5i SA5i+ SA532 SA5300 SA5312 SA641 SA642 SA6400" " SA6i P600 P800 P400 P400i E200 E200i E500"); +MODULE_VERSION("3.6.14"); MODULE_LICENSE("GPL"); #include "cciss_cmd.h" @@ -81,7 +82,9 @@ static const struct pci_device_id cciss_pci_device_id[] = { {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD, 0x103C, 0x3213}, {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD, 0x103C, 0x3214}, {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD, 0x103C, 0x3215}, - {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSC, 0x103C, 0x3233}, + {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSC, 0x103C, 0x3237}, + {PCI_VENDOR_ID_HP, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, + PCI_CLASS_STORAGE_RAID << 8, 0xffff << 8, 0}, {0,} }; @@ -90,27 +93,29 @@ MODULE_DEVICE_TABLE(pci, cciss_pci_device_id); /* board_id = Subsystem Device ID & Vendor ID * product = Marketing Name for the board * access = Address of the struct of function pointers + * nr_cmds = Number of commands supported by controller */ static struct board_type products[] = { - {0x40700E11, "Smart Array 5300", &SA5_access}, - {0x40800E11, "Smart Array 5i", &SA5B_access}, - {0x40820E11, "Smart Array 532", &SA5B_access}, - {0x40830E11, "Smart Array 5312", &SA5B_access}, - {0x409A0E11, "Smart Array 641", &SA5_access}, - {0x409B0E11, "Smart Array 642", &SA5_access}, - {0x409C0E11, "Smart Array 6400", &SA5_access}, - {0x409D0E11, "Smart Array 6400 EM", &SA5_access}, - {0x40910E11, "Smart Array 6i", &SA5_access}, - {0x3225103C, "Smart Array P600", &SA5_access}, - {0x3223103C, "Smart Array P800", &SA5_access}, - {0x3234103C, "Smart Array P400", &SA5_access}, - {0x3235103C, "Smart Array P400i", &SA5_access}, - {0x3211103C, "Smart Array E200i", &SA5_access}, - {0x3212103C, "Smart Array E200", &SA5_access}, - {0x3213103C, "Smart Array E200i", &SA5_access}, - {0x3214103C, "Smart Array E200i", &SA5_access}, - {0x3215103C, "Smart Array E200i", &SA5_access}, - {0x3233103C, "Smart Array E500", &SA5_access}, + {0x40700E11, "Smart Array 5300", &SA5_access, 512}, + {0x40800E11, "Smart Array 5i", &SA5B_access, 512}, + {0x40820E11, "Smart Array 532", &SA5B_access, 512}, + {0x40830E11, "Smart Array 5312", &SA5B_access, 512}, + {0x409A0E11, "Smart Array 641", &SA5_access, 512}, + {0x409B0E11, "Smart Array 642", &SA5_access, 512}, + {0x409C0E11, "Smart Array 6400", &SA5_access, 512}, + {0x409D0E11, "Smart Array 6400 EM", &SA5_access, 512}, + {0x40910E11, "Smart Array 6i", &SA5_access, 512}, + {0x3225103C, "Smart Array P600", &SA5_access, 512}, + {0x3223103C, "Smart Array P800", &SA5_access, 512}, + {0x3234103C, "Smart Array P400", &SA5_access, 512}, + {0x3235103C, "Smart Array P400i", &SA5_access, 512}, + {0x3211103C, "Smart Array E200i", &SA5_access, 120}, + {0x3212103C, "Smart Array E200", &SA5_access, 120}, + {0x3213103C, "Smart Array E200i", &SA5_access, 120}, + {0x3214103C, "Smart Array E200i", &SA5_access, 120}, + {0x3215103C, "Smart Array E200i", &SA5_access, 120}, + {0x3237103C, "Smart Array E500", &SA5_access, 512}, + {0xFFFF103C, "Unknown Smart Array", &SA5_access, 120}, }; /* How long to wait (in milliseconds) for board to go into simple mode */ @@ -121,7 +126,6 @@ static struct board_type products[] = { #define MAX_CMD_RETRIES 3 #define READ_AHEAD 1024 -#define NR_CMDS 384 /* #commands that can be outstanding */ #define MAX_CTLR 32 /* Originally cciss driver only supports 8 major numbers */ @@ -137,7 +141,6 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, unsigned long arg); static int cciss_getgeo(struct block_device *bdev, struct hd_geometry *geo); -static int revalidate_allvol(ctlr_info_t *host); static int cciss_revalidate(struct gendisk *disk); static int rebuild_lun_table(ctlr_info_t *h, struct gendisk *del_disk); static int deregister_disk(struct gendisk *disk, drive_info_struct *drv, @@ -265,6 +268,7 @@ static int cciss_proc_get_info(char *buffer, char **start, off_t offset, "Firmware Version: %c%c%c%c\n" "IRQ: %d\n" "Logical drives: %d\n" + "Max sectors: %d\n" "Current Q depth: %d\n" "Current # commands on controller: %d\n" "Max Q depth since init: %d\n" @@ -275,7 +279,9 @@ static int cciss_proc_get_info(char *buffer, char **start, off_t offset, (unsigned long)h->board_id, h->firm_ver[0], h->firm_ver[1], h->firm_ver[2], h->firm_ver[3], (unsigned int)h->intr[SIMPLE_MODE_INT], - h->num_luns, h->Qdepth, h->commands_outstanding, + h->num_luns, + h->cciss_max_sectors, + h->Qdepth, h->commands_outstanding, h->maxQsinceinit, h->max_outstanding, h->maxSG); pos += size; @@ -400,8 +406,8 @@ static CommandList_struct *cmd_alloc(ctlr_info_t *h, int get_from_pool) } else { /* get it out of the controllers pool */ do { - i = find_first_zero_bit(h->cmd_pool_bits, NR_CMDS); - if (i == NR_CMDS) + i = find_first_zero_bit(h->cmd_pool_bits, h->nr_cmds); + if (i == h->nr_cmds) return NULL; } while (test_and_set_bit (i & (BITS_PER_LONG - 1), @@ -487,7 +493,7 @@ static int cciss_open(struct inode *inode, struct file *filep) * but I'm already using way to many device nodes to claim another one * for "raw controller". */ - if (drv->nr_blocks == 0) { + if (drv->heads == 0) { if (iminor(inode) != 0) { /* not node 0? */ /* if not node 0 make sure it is a partition = 0 */ if (iminor(inode) & 0x0f) { @@ -529,7 +535,7 @@ static int do_ioctl(struct file *f, unsigned cmd, unsigned long arg) { int ret; lock_kernel(); - ret = cciss_ioctl(f->f_dentry->d_inode, f, cmd, arg); + ret = cciss_ioctl(f->f_path.dentry->d_inode, f, cmd, arg); unlock_kernel(); return ret; } @@ -850,9 +856,7 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, } case CCISS_REVALIDVOLS: - if (bdev != bdev->bd_contains || drv != host->drv) - return -ENXIO; - return revalidate_allvol(host); + return rebuild_lun_table(host, NULL); case CCISS_GETLUNINFO:{ LogvolInfo_struct luninfo; @@ -1152,75 +1156,6 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, } } -/* - * revalidate_allvol is for online array config utilities. After a - * utility reconfigures the drives in the array, it can use this function - * (through an ioctl) to make the driver zap any previous disk structs for - * that controller and get new ones. - * - * Right now I'm using the getgeometry() function to do this, but this - * function should probably be finer grained and allow you to revalidate one - * particular logical volume (instead of all of them on a particular - * controller). - */ -static int revalidate_allvol(ctlr_info_t *host) -{ - int ctlr = host->ctlr, i; - unsigned long flags; - - spin_lock_irqsave(CCISS_LOCK(ctlr), flags); - if (host->usage_count > 1) { - spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags); - printk(KERN_WARNING "cciss: Device busy for volume" - " revalidation (usage=%d)\n", host->usage_count); - return -EBUSY; - } - host->usage_count++; - spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags); - - for (i = 0; i < NWD; i++) { - struct gendisk *disk = host->gendisk[i]; - if (disk) { - request_queue_t *q = disk->queue; - - if (disk->flags & GENHD_FL_UP) - del_gendisk(disk); - if (q) - blk_cleanup_queue(q); - } - } - - /* - * Set the partition and block size structures for all volumes - * on this controller to zero. We will reread all of this data - */ - memset(host->drv, 0, sizeof(drive_info_struct) - * CISS_MAX_LUN); - /* - * Tell the array controller not to give us any interrupts while - * we check the new geometry. Then turn interrupts back on when - * we're done. - */ - host->access.set_intr_mask(host, CCISS_INTR_OFF); - cciss_getgeometry(ctlr); - host->access.set_intr_mask(host, CCISS_INTR_ON); - - /* Loop through each real device */ - for (i = 0; i < NWD; i++) { - struct gendisk *disk = host->gendisk[i]; - drive_info_struct *drv = &(host->drv[i]); - /* we must register the controller even if no disks exist */ - /* this is for the online array utilities */ - if (!drv->heads && i) - continue; - blk_queue_hardsect_size(drv->queue, drv->block_size); - set_capacity(disk, drv->nr_blocks); - add_disk(disk); - } - host->usage_count--; - return 0; -} - static inline void complete_buffers(struct bio *bio, int status) { while (bio) { @@ -1243,7 +1178,7 @@ static void cciss_check_queues(ctlr_info_t *h) * in case the interrupt we serviced was from an ioctl and did not * free any new commands. */ - if ((find_first_zero_bit(h->cmd_pool_bits, NR_CMDS)) == NR_CMDS) + if ((find_first_zero_bit(h->cmd_pool_bits, h->nr_cmds)) == h->nr_cmds) return; /* We have room on the queue for more commands. Now we need to queue @@ -1262,7 +1197,7 @@ static void cciss_check_queues(ctlr_info_t *h) /* check to see if we have maxed out the number of commands * that can be placed on the queue. */ - if ((find_first_zero_bit(h->cmd_pool_bits, NR_CMDS)) == NR_CMDS) { + if ((find_first_zero_bit(h->cmd_pool_bits, h->nr_cmds)) == h->nr_cmds) { if (curr_queue == start_queue) { h->next_to_run = (start_queue + 1) % (h->highest_lun + 1); @@ -1380,6 +1315,11 @@ static void cciss_update_drive_info(int ctlr, int drv_index) /* if it's the controller it's already added */ if (drv_index) { disk->queue = blk_init_queue(do_cciss_request, &h->lock); + sprintf(disk->disk_name, "cciss/c%dd%d", ctlr, drv_index); + disk->major = h->major; + disk->first_minor = drv_index << NWD_SHIFT; + disk->fops = &cciss_fops; + disk->private_data = &h->drv[drv_index]; /* Set up queue information */ disk->queue->backing_dev_info.ra_pages = READ_AHEAD; @@ -1391,7 +1331,7 @@ static void cciss_update_drive_info(int ctlr, int drv_index) /* This is a limit in the driver and could be eliminated. */ blk_queue_max_phys_segments(disk->queue, MAXSGENTRIES); - blk_queue_max_sectors(disk->queue, 512); + blk_queue_max_sectors(disk->queue, h->cciss_max_sectors); blk_queue_softirq_done(disk->queue, cciss_softirq_done); @@ -1458,11 +1398,6 @@ static int rebuild_lun_table(ctlr_info_t *h, struct gendisk *del_disk) /* Set busy_configuring flag for this operation */ spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags); - if (h->num_luns >= CISS_MAX_LUN) { - spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); - return -EINVAL; - } - if (h->busy_configuring) { spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); return -EBUSY; @@ -1495,17 +1430,8 @@ static int rebuild_lun_table(ctlr_info_t *h, struct gendisk *del_disk) 0, 0, TYPE_CMD); if (return_code == IO_OK) { - listlength |= - (0xff & (unsigned int)(ld_buff->LUNListLength[0])) - << 24; - listlength |= - (0xff & (unsigned int)(ld_buff->LUNListLength[1])) - << 16; - listlength |= - (0xff & (unsigned int)(ld_buff->LUNListLength[2])) - << 8; - listlength |= - 0xff & (unsigned int)(ld_buff->LUNListLength[3]); + listlength = + be32_to_cpu(*(__u32 *) ld_buff->LUNListLength); } else { /* reading number of logical volumes failed */ printk(KERN_WARNING "cciss: report logical volume" " command failed\n"); @@ -1556,6 +1482,14 @@ static int rebuild_lun_table(ctlr_info_t *h, struct gendisk *del_disk) if (drv_index == -1) goto freeret; + /*Check if the gendisk needs to be allocated */ + if (!h->gendisk[drv_index]){ + h->gendisk[drv_index] = alloc_disk(1 << NWD_SHIFT); + if (!h->gendisk[drv_index]){ + printk(KERN_ERR "cciss: could not allocate new disk %d\n", drv_index); + goto mem_msg; + } + } } h->drv[drv_index].LunID = lunid; cciss_update_drive_info(ctlr, drv_index); @@ -1593,6 +1527,7 @@ static int rebuild_lun_table(ctlr_info_t *h, struct gendisk *del_disk) static int deregister_disk(struct gendisk *disk, drive_info_struct *drv, int clear_all) { + int i; ctlr_info_t *h = get_host(disk); if (!capable(CAP_SYS_RAWIO)) @@ -1616,9 +1551,35 @@ static int deregister_disk(struct gendisk *disk, drive_info_struct *drv, del_gendisk(disk); if (q) { blk_cleanup_queue(q); + /* Set drv->queue to NULL so that we do not try + * to call blk_start_queue on this queue in the + * interrupt handler + */ drv->queue = NULL; } + /* If clear_all is set then we are deleting the logical + * drive, not just refreshing its info. For drives + * other than disk 0 we will call put_disk. We do not + * do this for disk 0 as we need it to be able to + * configure the controller. + */ + if (clear_all){ + /* This isn't pretty, but we need to find the + * disk in our array and NULL our the pointer. + * This is so that we will call alloc_disk if + * this index is used again later. + */ + for (i=0; i < CISS_MAX_LUN; i++){ + if(h->gendisk[i] == disk){ + h->gendisk[i] = NULL; + break; + } + } + put_disk(disk); + } } + } else { + set_capacity(disk, 0); } --h->num_luns; @@ -2136,7 +2097,7 @@ static int add_sendcmd_reject(__u8 cmd, int ctlr, unsigned long complete) /* We've sent down an abort or reset, but something else has completed */ - if (srl->ncompletions >= (NR_CMDS + 2)) { + if (srl->ncompletions >= (hba[ctlr]->nr_cmds + 2)) { /* Uh oh. No room to save it for later... */ printk(KERN_WARNING "cciss%d: Sendcmd: Invalid command addr, " "reject list overflow, command lost!\n", ctlr); @@ -2673,7 +2634,7 @@ static irqreturn_t do_cciss_intr(int irq, void *dev_id) a1 = a; if ((a & 0x04)) { a2 = (a >> 3); - if (a2 >= NR_CMDS) { + if (a2 >= h->nr_cmds) { printk(KERN_WARNING "cciss: controller cciss%d failed, stopping.\n", h->ctlr); @@ -2827,23 +2788,21 @@ static void __devinit cciss_interrupt_mode(ctlr_info_t *c, if (err > 0) { printk(KERN_WARNING "cciss: only %d MSI-X vectors " "available\n", err); + goto default_int_mode; } else { printk(KERN_WARNING "cciss: MSI-X init failed %d\n", err); + goto default_int_mode; } } if (pci_find_capability(pdev, PCI_CAP_ID_MSI)) { if (!pci_enable_msi(pdev)) { - c->intr[SIMPLE_MODE_INT] = pdev->irq; c->msi_vector = 1; - return; } else { printk(KERN_WARNING "cciss: MSI init failed\n"); - c->intr[SIMPLE_MODE_INT] = pdev->irq; - return; } } - default_int_mode: +default_int_mode: #endif /* CONFIG_PCI_MSI */ /* if we get here we're going to use the default interrupt mode */ c->intr[SIMPLE_MODE_INT] = pdev->irq; @@ -2956,16 +2915,10 @@ static int cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev) if (board_id == products[i].board_id) { c->product_name = products[i].product_name; c->access = *(products[i].access); + c->nr_cmds = products[i].nr_cmds; break; } } - if (i == ARRAY_SIZE(products)) { - printk(KERN_WARNING "cciss: Sorry, I don't know how" - " to access the Smart Array controller %08lx\n", - (unsigned long)board_id); - err = -ENODEV; - goto err_out_free_res; - } if ((readb(&c->cfgtable->Signature[0]) != 'C') || (readb(&c->cfgtable->Signature[1]) != 'I') || (readb(&c->cfgtable->Signature[2]) != 'S') || @@ -2974,6 +2927,27 @@ static int cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev) err = -ENODEV; goto err_out_free_res; } + /* We didn't find the controller in our list. We know the + * signature is valid. If it's an HP device let's try to + * bind to the device and fire it up. Otherwise we bail. + */ + if (i == ARRAY_SIZE(products)) { + if (subsystem_vendor_id == PCI_VENDOR_ID_HP) { + c->product_name = products[i-1].product_name; + c->access = *(products[i-1].access); + c->nr_cmds = products[i-1].nr_cmds; + printk(KERN_WARNING "cciss: This is an unknown " + "Smart Array controller.\n" + "cciss: Please update to the latest driver " + "available from www.hp.com.\n"); + } else { + printk(KERN_WARNING "cciss: Sorry, I don't know how" + " to access the Smart Array controller %08lx\n" + , (unsigned long)board_id); + err = -ENODEV; + goto err_out_free_res; + } + } #ifdef CONFIG_X86 { /* Need to enable prefetch in the SCSI core for 6400 in x86 */ @@ -2984,6 +2958,17 @@ static int cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev) } #endif + /* Disabling DMA prefetch for the P600 + * An ASIC bug may result in a prefetch beyond + * physical memory. + */ + if(board_id == 0x3225103C) { + __u32 dma_prefetch; + dma_prefetch = readl(c->vaddr + I2O_DMA1_CFG); + dma_prefetch |= 0x8000; + writel(dma_prefetch, c->vaddr + I2O_DMA1_CFG); + } + #ifdef CCISS_DEBUG printk("Trying to put board into Simple mode\n"); #endif /* CCISS_DEBUG */ @@ -3158,13 +3143,7 @@ static void cciss_getgeometry(int cntl_num) /* Returns -1 if no free entries are left. */ static int alloc_cciss_hba(void) { - struct gendisk *disk[NWD]; - int i, n; - for (n = 0; n < NWD; n++) { - disk[n] = alloc_disk(1 << NWD_SHIFT); - if (!disk[n]) - goto out; - } + int i; for (i = 0; i < MAX_CTLR; i++) { if (!hba[i]) { @@ -3172,20 +3151,18 @@ static int alloc_cciss_hba(void) p = kzalloc(sizeof(ctlr_info_t), GFP_KERNEL); if (!p) goto Enomem; - for (n = 0; n < NWD; n++) - p->gendisk[n] = disk[n]; + p->gendisk[0] = alloc_disk(1 << NWD_SHIFT); + if (!p->gendisk[0]) + goto Enomem; hba[i] = p; return i; } } printk(KERN_WARNING "cciss: This driver supports a maximum" " of %d controllers.\n", MAX_CTLR); - goto out; - Enomem: + return -1; +Enomem: printk(KERN_ERR "cciss: out of memory.\n"); - out: - while (n--) - put_disk(disk[n]); return -1; } @@ -3195,7 +3172,7 @@ static void free_hba(int i) int n; hba[i] = NULL; - for (n = 0; n < NWD; n++) + for (n = 0; n < CISS_MAX_LUN; n++) put_disk(p->gendisk[n]); kfree(p); } @@ -3208,9 +3185,8 @@ static void free_hba(int i) static int __devinit cciss_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { - request_queue_t *q; int i; - int j; + int j = 0; int rc; int dac; @@ -3269,15 +3245,15 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, hba[i]->intr[SIMPLE_MODE_INT], dac ? "" : " not"); hba[i]->cmd_pool_bits = - kmalloc(((NR_CMDS + BITS_PER_LONG - + kmalloc(((hba[i]->nr_cmds + BITS_PER_LONG - 1) / BITS_PER_LONG) * sizeof(unsigned long), GFP_KERNEL); hba[i]->cmd_pool = (CommandList_struct *) pci_alloc_consistent(hba[i]->pdev, - NR_CMDS * sizeof(CommandList_struct), + hba[i]->nr_cmds * sizeof(CommandList_struct), &(hba[i]->cmd_pool_dhandle)); hba[i]->errinfo_pool = (ErrorInfo_struct *) pci_alloc_consistent(hba[i]->pdev, - NR_CMDS * sizeof(ErrorInfo_struct), + hba[i]->nr_cmds * sizeof(ErrorInfo_struct), &(hba[i]->errinfo_pool_dhandle)); if ((hba[i]->cmd_pool_bits == NULL) || (hba[i]->cmd_pool == NULL) @@ -3288,7 +3264,7 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, #ifdef CONFIG_CISS_SCSI_TAPE hba[i]->scsi_rejects.complete = kmalloc(sizeof(hba[i]->scsi_rejects.complete[0]) * - (NR_CMDS + 5), GFP_KERNEL); + (hba[i]->nr_cmds + 5), GFP_KERNEL); if (hba[i]->scsi_rejects.complete == NULL) { printk(KERN_ERR "cciss: out of memory"); goto clean4; @@ -3302,7 +3278,7 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, /* command and error info recs zeroed out before they are used */ memset(hba[i]->cmd_pool_bits, 0, - ((NR_CMDS + BITS_PER_LONG - + ((hba[i]->nr_cmds + BITS_PER_LONG - 1) / BITS_PER_LONG) * sizeof(unsigned long)); #ifdef CCISS_DEBUG @@ -3317,18 +3293,34 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, hba[i]->access.set_intr_mask(hba[i], CCISS_INTR_ON); cciss_procinit(i); + + hba[i]->cciss_max_sectors = 2048; + hba[i]->busy_initializing = 0; - for (j = 0; j < NWD; j++) { /* mfm */ + do { drive_info_struct *drv = &(hba[i]->drv[j]); struct gendisk *disk = hba[i]->gendisk[j]; + request_queue_t *q; + + /* Check if the disk was allocated already */ + if (!disk){ + hba[i]->gendisk[j] = alloc_disk(1 << NWD_SHIFT); + disk = hba[i]->gendisk[j]; + } + + /* Check that the disk was able to be allocated */ + if (!disk) { + printk(KERN_ERR "cciss: unable to allocate memory for disk %d\n", j); + goto clean4; + } q = blk_init_queue(do_cciss_request, &hba[i]->lock); if (!q) { printk(KERN_ERR "cciss: unable to allocate queue for disk %d\n", j); - break; + goto clean4; } drv->queue = q; @@ -3341,7 +3333,7 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, /* This is a limit in the driver and could be eliminated. */ blk_queue_max_phys_segments(q, MAXSGENTRIES); - blk_queue_max_sectors(q, 512); + blk_queue_max_sectors(q, hba[i]->cciss_max_sectors); blk_queue_softirq_done(q, cciss_softirq_done); @@ -3360,7 +3352,8 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, blk_queue_hardsect_size(q, drv->block_size); set_capacity(disk, drv->nr_blocks); add_disk(disk); - } + j++; + } while (j <= hba[i]->highest_lun); return 1; @@ -3371,11 +3364,11 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, kfree(hba[i]->cmd_pool_bits); if (hba[i]->cmd_pool) pci_free_consistent(hba[i]->pdev, - NR_CMDS * sizeof(CommandList_struct), + hba[i]->nr_cmds * sizeof(CommandList_struct), hba[i]->cmd_pool, hba[i]->cmd_pool_dhandle); if (hba[i]->errinfo_pool) pci_free_consistent(hba[i]->pdev, - NR_CMDS * sizeof(ErrorInfo_struct), + hba[i]->nr_cmds * sizeof(ErrorInfo_struct), hba[i]->errinfo_pool, hba[i]->errinfo_pool_dhandle); free_irq(hba[i]->intr[SIMPLE_MODE_INT], hba[i]); @@ -3383,6 +3376,15 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, unregister_blkdev(hba[i]->major, hba[i]->devname); clean1: hba[i]->busy_initializing = 0; + /* cleanup any queues that may have been initialized */ + for (j=0; j <= hba[i]->highest_lun; j++){ + drive_info_struct *drv = &(hba[i]->drv[j]); + if (drv->queue) + blk_cleanup_queue(drv->queue); + } + pci_release_regions(pdev); + pci_disable_device(pdev); + pci_set_drvdata(pdev, NULL); free_hba(i); return -1; } @@ -3430,7 +3432,7 @@ static void __devexit cciss_remove_one(struct pci_dev *pdev) remove_proc_entry(hba[i]->devname, proc_cciss); /* remove it from the disk list */ - for (j = 0; j < NWD; j++) { + for (j = 0; j < CISS_MAX_LUN; j++) { struct gendisk *disk = hba[i]->gendisk[j]; if (disk) { request_queue_t *q = disk->queue; @@ -3442,9 +3444,9 @@ static void __devexit cciss_remove_one(struct pci_dev *pdev) } } - pci_free_consistent(hba[i]->pdev, NR_CMDS * sizeof(CommandList_struct), + pci_free_consistent(hba[i]->pdev, hba[i]->nr_cmds * sizeof(CommandList_struct), hba[i]->cmd_pool, hba[i]->cmd_pool_dhandle); - pci_free_consistent(hba[i]->pdev, NR_CMDS * sizeof(ErrorInfo_struct), + pci_free_consistent(hba[i]->pdev, hba[i]->nr_cmds * sizeof(ErrorInfo_struct), hba[i]->errinfo_pool, hba[i]->errinfo_pool_dhandle); kfree(hba[i]->cmd_pool_bits); #ifdef CONFIG_CISS_SCSI_TAPE diff --git a/trunk/drivers/block/cciss.h b/trunk/drivers/block/cciss.h index 562235c1445a..b70988dd33ec 100644 --- a/trunk/drivers/block/cciss.h +++ b/trunk/drivers/block/cciss.h @@ -6,7 +6,6 @@ #include "cciss_cmd.h" -#define NWD 16 #define NWD_SHIFT 4 #define MAX_PART (1 << NWD_SHIFT) @@ -60,6 +59,7 @@ struct ctlr_info __u32 board_id; void __iomem *vaddr; unsigned long paddr; + int nr_cmds; /* Number of commands allowed on this controller */ CfgTable_struct __iomem *cfgtable; int interrupts_enabled; int major; @@ -76,6 +76,7 @@ struct ctlr_info unsigned int intr[4]; unsigned int msix_vector; unsigned int msi_vector; + int cciss_max_sectors; BYTE cciss_read; BYTE cciss_write; BYTE cciss_read_capacity; @@ -110,7 +111,7 @@ struct ctlr_info int next_to_run; // Disk structures we need to pass back - struct gendisk *gendisk[NWD]; + struct gendisk *gendisk[CISS_MAX_LUN]; #ifdef CONFIG_CISS_SCSI_TAPE void *scsi_ctlr; /* ptr to structure containing scsi related stuff */ /* list of block side commands the scsi error handling sucked up */ @@ -282,6 +283,7 @@ struct board_type { __u32 board_id; char *product_name; struct access_method *access; + int nr_cmds; /* Max cmds this kind of ctlr can handle. */ }; #define CCISS_LOCK(i) (&hba[i]->lock) diff --git a/trunk/drivers/block/cciss_cmd.h b/trunk/drivers/block/cciss_cmd.h index 4af7c4c0c7af..43bf5593b59b 100644 --- a/trunk/drivers/block/cciss_cmd.h +++ b/trunk/drivers/block/cciss_cmd.h @@ -55,6 +55,7 @@ #define I2O_INT_MASK 0x34 #define I2O_IBPOST_Q 0x40 #define I2O_OBPOST_Q 0x44 +#define I2O_DMA1_CFG 0x214 //Configuration Table #define CFGTBL_ChangeReq 0x00000001l @@ -88,7 +89,7 @@ typedef union _u64bit //########################################################################### //STRUCTURES //########################################################################### -#define CISS_MAX_LUN 16 +#define CISS_MAX_LUN 1024 #define CISS_MAX_PHYS_LUN 1024 // SCSI-3 Cmmands diff --git a/trunk/drivers/block/floppy.c b/trunk/drivers/block/floppy.c index 9e6d3a87cbe3..3f1b38276e96 100644 --- a/trunk/drivers/block/floppy.c +++ b/trunk/drivers/block/floppy.c @@ -992,11 +992,11 @@ static void empty(void) { } -static DECLARE_WORK(floppy_work, NULL, NULL); +static DECLARE_WORK(floppy_work, NULL); static void schedule_bh(void (*handler) (void)) { - PREPARE_WORK(&floppy_work, (void (*)(void *))handler, NULL); + PREPARE_WORK(&floppy_work, (work_func_t)handler); schedule_work(&floppy_work); } @@ -1008,7 +1008,7 @@ static void cancel_activity(void) spin_lock_irqsave(&floppy_lock, flags); do_floppy = NULL; - PREPARE_WORK(&floppy_work, (void *)empty, NULL); + PREPARE_WORK(&floppy_work, (work_func_t)empty); del_timer(&fd_timer); spin_unlock_irqrestore(&floppy_lock, flags); } @@ -1868,7 +1868,7 @@ static void show_floppy(void) printk("fdc_busy=%lu\n", fdc_busy); if (do_floppy) printk("do_floppy=%p\n", do_floppy); - if (floppy_work.pending) + if (work_pending(&floppy_work)) printk("floppy_work.func=%p\n", floppy_work.func); if (timer_pending(&fd_timer)) printk("fd_timer.function=%p\n", fd_timer.function); @@ -4498,7 +4498,7 @@ static void floppy_release_irq_and_dma(void) printk("floppy timer still active:%s\n", timeout_message); if (timer_pending(&fd_timer)) printk("auxiliary floppy timer still active\n"); - if (floppy_work.pending) + if (work_pending(&floppy_work)) printk("work still pending\n"); #endif old_fdc = fdc; diff --git a/trunk/drivers/block/loop.c b/trunk/drivers/block/loop.c index beab6d2643cb..6b5b64207407 100644 --- a/trunk/drivers/block/loop.c +++ b/trunk/drivers/block/loop.c @@ -1000,7 +1000,7 @@ loop_get_status(struct loop_device *lo, struct loop_info64 *info) if (lo->lo_state != Lo_bound) return -ENXIO; - error = vfs_getattr(file->f_vfsmnt, file->f_dentry, &stat); + error = vfs_getattr(file->f_path.mnt, file->f_path.dentry, &stat); if (error) return error; memset(info, 0, sizeof(*info)); @@ -1287,7 +1287,7 @@ loop_get_status_compat(struct loop_device *lo, static long lo_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; struct loop_device *lo = inode->i_bdev->bd_disk->private_data; int err; diff --git a/trunk/drivers/block/nbd.c b/trunk/drivers/block/nbd.c index 9d1035e8d9d8..090796bef78f 100644 --- a/trunk/drivers/block/nbd.c +++ b/trunk/drivers/block/nbd.c @@ -355,14 +355,30 @@ static struct request *nbd_read_stat(struct nbd_device *lo) return NULL; } +static ssize_t pid_show(struct gendisk *disk, char *page) +{ + return sprintf(page, "%ld\n", + (long) ((struct nbd_device *)disk->private_data)->pid); +} + +static struct disk_attribute pid_attr = { + .attr = { .name = "pid", .mode = S_IRUGO }, + .show = pid_show, +}; + static void nbd_do_it(struct nbd_device *lo) { struct request *req; BUG_ON(lo->magic != LO_MAGIC); + lo->pid = current->pid; + sysfs_create_file(&lo->disk->kobj, &pid_attr.attr); + while ((req = nbd_read_stat(lo)) != NULL) nbd_end_request(req); + + sysfs_remove_file(&lo->disk->kobj, &pid_attr.attr); return; } @@ -521,7 +537,7 @@ static int nbd_ioctl(struct inode *inode, struct file *file, error = -EINVAL; file = fget(arg); if (file) { - inode = file->f_dentry->d_inode; + inode = file->f_path.dentry->d_inode; if (S_ISSOCK(inode->i_mode)) { lo->file = file; lo->sock = SOCKET_I(inode); diff --git a/trunk/drivers/block/paride/aten.c b/trunk/drivers/block/paride/aten.c index c4d696d43dc1..2695465568ad 100644 --- a/trunk/drivers/block/paride/aten.c +++ b/trunk/drivers/block/paride/aten.c @@ -149,12 +149,12 @@ static struct pi_protocol aten = { static int __init aten_init(void) { - return pi_register(&aten)-1; + return paride_register(&aten); } static void __exit aten_exit(void) { - pi_unregister( &aten ); + paride_unregister( &aten ); } MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/block/paride/bpck.c b/trunk/drivers/block/paride/bpck.c index d462ff6b139d..4f27e7392e38 100644 --- a/trunk/drivers/block/paride/bpck.c +++ b/trunk/drivers/block/paride/bpck.c @@ -464,12 +464,12 @@ static struct pi_protocol bpck = { static int __init bpck_init(void) { - return pi_register(&bpck)-1; + return paride_register(&bpck); } static void __exit bpck_exit(void) { - pi_unregister(&bpck); + paride_unregister(&bpck); } MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/block/paride/bpck6.c b/trunk/drivers/block/paride/bpck6.c index 41a237c5957d..ad124525ac23 100644 --- a/trunk/drivers/block/paride/bpck6.c +++ b/trunk/drivers/block/paride/bpck6.c @@ -31,10 +31,7 @@ static int verbose; /* set this to 1 to see debugging messages and whatnot */ #include #include #include - -#if defined(CONFIG_PARPORT_MODULE)||defined(CONFIG_PARPORT) #include -#endif #include "ppc6lnx.c" #include "paride.h" @@ -139,11 +136,6 @@ static int bpck6_test_port ( PIA *pi ) /* check for 8-bit port */ PPCSTRUCT(pi)->ppc_id=pi->unit; PPCSTRUCT(pi)->lpt_addr=pi->port; -#ifdef CONFIG_PARPORT_PC_MODULE -#define CONFIG_PARPORT_PC -#endif - -#ifdef CONFIG_PARPORT_PC /* look at the parport device to see if what modes we can use */ if(((struct pardevice *)(pi->pardev))->port->modes & (PARPORT_MODE_EPP) @@ -161,11 +153,6 @@ static int bpck6_test_port ( PIA *pi ) /* check for 8-bit port */ { return 1; } -#else - /* there is no way of knowing what kind of port we have - default to the highest mode possible */ - return 5; -#endif } static int bpck6_probe_unit ( PIA *pi ) @@ -265,12 +252,12 @@ static int __init bpck6_init(void) printk(KERN_INFO "bpck6: Copyright 2001 by Micro Solutions, Inc., DeKalb IL. USA\n"); if(verbose) printk(KERN_DEBUG "bpck6: verbose debug enabled.\n"); - return pi_register(&bpck6) - 1; + return paride_register(&bpck6); } static void __exit bpck6_exit(void) { - pi_unregister(&bpck6); + paride_unregister(&bpck6); } MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/block/paride/comm.c b/trunk/drivers/block/paride/comm.c index 43d61359d8ec..9bcd35495323 100644 --- a/trunk/drivers/block/paride/comm.c +++ b/trunk/drivers/block/paride/comm.c @@ -205,12 +205,12 @@ static struct pi_protocol comm = { static int __init comm_init(void) { - return pi_register(&comm)-1; + return paride_register(&comm); } static void __exit comm_exit(void) { - pi_unregister(&comm); + paride_unregister(&comm); } MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/block/paride/dstr.c b/trunk/drivers/block/paride/dstr.c index 04d53bf58e8c..accc5c777cbb 100644 --- a/trunk/drivers/block/paride/dstr.c +++ b/trunk/drivers/block/paride/dstr.c @@ -220,12 +220,12 @@ static struct pi_protocol dstr = { static int __init dstr_init(void) { - return pi_register(&dstr)-1; + return paride_register(&dstr); } static void __exit dstr_exit(void) { - pi_unregister(&dstr); + paride_unregister(&dstr); } MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/block/paride/epat.c b/trunk/drivers/block/paride/epat.c index 55d1c0a1fb90..1bcdff77322e 100644 --- a/trunk/drivers/block/paride/epat.c +++ b/trunk/drivers/block/paride/epat.c @@ -327,12 +327,12 @@ static int __init epat_init(void) #ifdef CONFIG_PARIDE_EPATC8 epatc8 = 1; #endif - return pi_register(&epat)-1; + return paride_register(&epat); } static void __exit epat_exit(void) { - pi_unregister(&epat); + paride_unregister(&epat); } MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/block/paride/epia.c b/trunk/drivers/block/paride/epia.c index 0f2e0c292d82..fb0e782d055e 100644 --- a/trunk/drivers/block/paride/epia.c +++ b/trunk/drivers/block/paride/epia.c @@ -303,12 +303,12 @@ static struct pi_protocol epia = { static int __init epia_init(void) { - return pi_register(&epia)-1; + return paride_register(&epia); } static void __exit epia_exit(void) { - pi_unregister(&epia); + paride_unregister(&epia); } MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/block/paride/fit2.c b/trunk/drivers/block/paride/fit2.c index e0f0691d8bc2..381283753ae4 100644 --- a/trunk/drivers/block/paride/fit2.c +++ b/trunk/drivers/block/paride/fit2.c @@ -138,12 +138,12 @@ static struct pi_protocol fit2 = { static int __init fit2_init(void) { - return pi_register(&fit2)-1; + return paride_register(&fit2); } static void __exit fit2_exit(void) { - pi_unregister(&fit2); + paride_unregister(&fit2); } MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/block/paride/fit3.c b/trunk/drivers/block/paride/fit3.c index 15400e7bc666..275d269458eb 100644 --- a/trunk/drivers/block/paride/fit3.c +++ b/trunk/drivers/block/paride/fit3.c @@ -198,12 +198,12 @@ static struct pi_protocol fit3 = { static int __init fit3_init(void) { - return pi_register(&fit3)-1; + return paride_register(&fit3); } static void __exit fit3_exit(void) { - pi_unregister(&fit3); + paride_unregister(&fit3); } MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/block/paride/friq.c b/trunk/drivers/block/paride/friq.c index 5ea2904d2815..4f2ba244689b 100644 --- a/trunk/drivers/block/paride/friq.c +++ b/trunk/drivers/block/paride/friq.c @@ -263,12 +263,12 @@ static struct pi_protocol friq = { static int __init friq_init(void) { - return pi_register(&friq)-1; + return paride_register(&friq); } static void __exit friq_exit(void) { - pi_unregister(&friq); + paride_unregister(&friq); } MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/block/paride/frpw.c b/trunk/drivers/block/paride/frpw.c index 56b3824b1538..c3cde364603a 100644 --- a/trunk/drivers/block/paride/frpw.c +++ b/trunk/drivers/block/paride/frpw.c @@ -300,12 +300,12 @@ static struct pi_protocol frpw = { static int __init frpw_init(void) { - return pi_register(&frpw)-1; + return paride_register(&frpw); } static void __exit frpw_exit(void) { - pi_unregister(&frpw); + paride_unregister(&frpw); } MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/block/paride/jumbo b/trunk/drivers/block/paride/jumbo deleted file mode 100644 index e793b9cb7e72..000000000000 --- a/trunk/drivers/block/paride/jumbo +++ /dev/null @@ -1,70 +0,0 @@ -#!/bin/sh -# -# This script can be used to build "jumbo" modules that contain the -# base PARIDE support, one protocol module and one high-level driver. -# -echo -n "High level driver [pcd] : " -read X -HLD=${X:-pcd} -# -echo -n "Protocol module [bpck] : " -read X -PROTO=${X:-bpck} -# -echo -n "Use MODVERSIONS [y] ? " -read X -UMODV=${X:-y} -# -echo -n "For SMP kernel [n] ? " -read X -USMP=${X:-n} -# -echo -n "Support PARPORT [n] ? " -read X -UPARP=${X:-n} -# -echo -# -case $USMP in - y* | Y* ) FSMP="-DCONFIG_SMP" - ;; - *) FSMP="" - ;; -esac -# -MODI="-include ../../../include/linux/modversions.h" -# -case $UMODV in - y* | Y* ) FMODV="-DMODVERSIONS $MODI" - ;; - *) FMODV="" - ;; -esac -# -case $UPARP in - y* | Y* ) FPARP="-DCONFIG_PARPORT" - ;; - *) FPARP="" - ;; -esac -# -TARG=$HLD-$PROTO.o -FPROTO=-DCONFIG_PARIDE_`echo "$PROTO" | tr [a-z] [A-Z]` -FK="-D__KERNEL__ -I ../../../include" -FLCH=-D_LINUX_CONFIG_H -# -echo cc $FK $FSMP $FLCH $FPARP $FPROTO $FMODV -Wall -O2 -o Jb.o -c paride.c -cc $FK $FSMP $FLCH $FPARP $FPROTO $FMODV -Wall -O2 -o Jb.o -c paride.c -# -echo cc $FK $FSMP $FMODV -Wall -O2 -o Jp.o -c $PROTO.c -cc $FK $FSMP $FMODV -Wall -O2 -o Jp.o -c $PROTO.c -# -echo cc $FK $FSMP $FMODV -DMODULE -DPARIDE_JUMBO -Wall -O2 -o Jd.o -c $HLD.c -cc $FK $FSMP $FMODV -DMODULE -DPARIDE_JUMBO -Wall -O2 -o Jd.o -c $HLD.c -# -echo ld -r -o $TARG Jp.o Jb.o Jd.o -ld -r -o $TARG Jp.o Jb.o Jd.o -# -# -rm Jp.o Jb.o Jd.o -# diff --git a/trunk/drivers/block/paride/kbic.c b/trunk/drivers/block/paride/kbic.c index d983bcea76fe..35999c415ee3 100644 --- a/trunk/drivers/block/paride/kbic.c +++ b/trunk/drivers/block/paride/kbic.c @@ -283,13 +283,21 @@ static struct pi_protocol k971 = { static int __init kbic_init(void) { - return (pi_register(&k951)||pi_register(&k971))-1; + int rv; + + rv = paride_register(&k951); + if (rv < 0) + return rv; + rv = paride_register(&k971); + if (rv < 0) + paride_unregister(&k951); + return rv; } static void __exit kbic_exit(void) { - pi_unregister(&k951); - pi_unregister(&k971); + paride_unregister(&k951); + paride_unregister(&k971); } MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/block/paride/ktti.c b/trunk/drivers/block/paride/ktti.c index 6c7edbfba9a0..117ab0e8ccf0 100644 --- a/trunk/drivers/block/paride/ktti.c +++ b/trunk/drivers/block/paride/ktti.c @@ -115,12 +115,12 @@ static struct pi_protocol ktti = { static int __init ktti_init(void) { - return pi_register(&ktti)-1; + return paride_register(&ktti); } static void __exit ktti_exit(void) { - pi_unregister(&ktti); + paride_unregister(&ktti); } MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/block/paride/on20.c b/trunk/drivers/block/paride/on20.c index 9f8e01096809..0173697a1a4d 100644 --- a/trunk/drivers/block/paride/on20.c +++ b/trunk/drivers/block/paride/on20.c @@ -140,12 +140,12 @@ static struct pi_protocol on20 = { static int __init on20_init(void) { - return pi_register(&on20)-1; + return paride_register(&on20); } static void __exit on20_exit(void) { - pi_unregister(&on20); + paride_unregister(&on20); } MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/block/paride/on26.c b/trunk/drivers/block/paride/on26.c index 0f833caa2101..95ba256921f2 100644 --- a/trunk/drivers/block/paride/on26.c +++ b/trunk/drivers/block/paride/on26.c @@ -306,12 +306,12 @@ static struct pi_protocol on26 = { static int __init on26_init(void) { - return pi_register(&on26)-1; + return paride_register(&on26); } static void __exit on26_exit(void) { - pi_unregister(&on26); + paride_unregister(&on26); } MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/block/paride/paride.c b/trunk/drivers/block/paride/paride.c index 4b258f7836f3..48c50f11f63b 100644 --- a/trunk/drivers/block/paride/paride.c +++ b/trunk/drivers/block/paride/paride.c @@ -29,14 +29,7 @@ #include #include #include /* TASK_* */ - -#ifdef CONFIG_PARPORT_MODULE -#define CONFIG_PARPORT -#endif - -#ifdef CONFIG_PARPORT #include -#endif #include "paride.h" @@ -76,8 +69,6 @@ void pi_read_block(PIA * pi, char *buf, int count) EXPORT_SYMBOL(pi_read_block); -#ifdef CONFIG_PARPORT - static void pi_wake_up(void *p) { PIA *pi = (PIA *) p; @@ -100,11 +91,8 @@ static void pi_wake_up(void *p) cont(); } -#endif - int pi_schedule_claimed(PIA * pi, void (*cont) (void)) { -#ifdef CONFIG_PARPORT unsigned long flags; spin_lock_irqsave(&pi_spinlock, flags); @@ -115,7 +103,6 @@ int pi_schedule_claimed(PIA * pi, void (*cont) (void)) } pi->claimed = 1; spin_unlock_irqrestore(&pi_spinlock, flags); -#endif return 1; } EXPORT_SYMBOL(pi_schedule_claimed); @@ -133,20 +120,16 @@ static void pi_claim(PIA * pi) if (pi->claimed) return; pi->claimed = 1; -#ifdef CONFIG_PARPORT if (pi->pardev) wait_event(pi->parq, !parport_claim((struct pardevice *) pi->pardev)); -#endif } static void pi_unclaim(PIA * pi) { pi->claimed = 0; -#ifdef CONFIG_PARPORT if (pi->pardev) parport_release((struct pardevice *) (pi->pardev)); -#endif } void pi_connect(PIA * pi) @@ -167,21 +150,15 @@ EXPORT_SYMBOL(pi_disconnect); static void pi_unregister_parport(PIA * pi) { -#ifdef CONFIG_PARPORT if (pi->pardev) { parport_unregister_device((struct pardevice *) (pi->pardev)); pi->pardev = NULL; } -#endif } void pi_release(PIA * pi) { pi_unregister_parport(pi); -#ifndef CONFIG_PARPORT - if (pi->reserved) - release_region(pi->port, pi->reserved); -#endif /* !CONFIG_PARPORT */ if (pi->proto->release_proto) pi->proto->release_proto(pi); module_put(pi->proto->owner); @@ -229,7 +206,7 @@ static int pi_test_proto(PIA * pi, char *scratch, int verbose) return res; } -int pi_register(PIP * pr) +int paride_register(PIP * pr) { int k; @@ -237,24 +214,24 @@ int pi_register(PIP * pr) if (protocols[k] && !strcmp(pr->name, protocols[k]->name)) { printk("paride: %s protocol already registered\n", pr->name); - return 0; + return -1; } k = 0; while ((k < MAX_PROTOS) && (protocols[k])) k++; if (k == MAX_PROTOS) { printk("paride: protocol table full\n"); - return 0; + return -1; } protocols[k] = pr; pr->index = k; printk("paride: %s registered as protocol %d\n", pr->name, k); - return 1; + return 0; } -EXPORT_SYMBOL(pi_register); +EXPORT_SYMBOL(paride_register); -void pi_unregister(PIP * pr) +void paride_unregister(PIP * pr) { if (!pr) return; @@ -265,12 +242,10 @@ void pi_unregister(PIP * pr) protocols[pr->index] = NULL; } -EXPORT_SYMBOL(pi_unregister); +EXPORT_SYMBOL(paride_unregister); static int pi_register_parport(PIA * pi, int verbose) { -#ifdef CONFIG_PARPORT - struct parport *port; port = parport_find_base(pi->port); @@ -290,7 +265,6 @@ static int pi_register_parport(PIA * pi, int verbose) printk("%s: 0x%x is %s\n", pi->device, pi->port, port->name); pi->parname = (char *) port->name; -#endif return 1; } @@ -447,13 +421,6 @@ int pi_init(PIA * pi, int autoprobe, int port, int mode, printk("%s: Adapter not found\n", device); return 0; } -#ifndef CONFIG_PARPORT - if (!request_region(pi->port, pi->reserved, pi->device)) { - printk(KERN_WARNING "paride: Unable to request region 0x%x\n", - pi->port); - return 0; - } -#endif /* !CONFIG_PARPORT */ if (pi->parname) printk("%s: Sharing %s at 0x%x\n", pi->device, diff --git a/trunk/drivers/block/paride/paride.h b/trunk/drivers/block/paride/paride.h index c6d98ef09e48..2bddbf45518b 100644 --- a/trunk/drivers/block/paride/paride.h +++ b/trunk/drivers/block/paride/paride.h @@ -163,8 +163,8 @@ struct pi_protocol { typedef struct pi_protocol PIP; -extern int pi_register( PIP * ); -extern void pi_unregister ( PIP * ); +extern int paride_register( PIP * ); +extern void paride_unregister ( PIP * ); #endif /* __DRIVERS_PARIDE_H__ */ /* end of paride.h */ diff --git a/trunk/drivers/block/paride/pcd.c b/trunk/drivers/block/paride/pcd.c index ac5ba462710b..c852eed91e4b 100644 --- a/trunk/drivers/block/paride/pcd.c +++ b/trunk/drivers/block/paride/pcd.c @@ -912,12 +912,12 @@ static int __init pcd_init(void) int unit; if (disable) - return -1; + return -EINVAL; pcd_init_units(); if (pcd_detect()) - return -1; + return -ENODEV; /* get the atapi capabilities page */ pcd_probe_capabilities(); @@ -925,7 +925,7 @@ static int __init pcd_init(void) if (register_blkdev(major, name)) { for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) put_disk(cd->disk); - return -1; + return -EBUSY; } pcd_queue = blk_init_queue(do_pcd_request, &pcd_lock); @@ -933,7 +933,7 @@ static int __init pcd_init(void) unregister_blkdev(major, name); for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) put_disk(cd->disk); - return -1; + return -ENOMEM; } for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) { diff --git a/trunk/drivers/block/paride/pd.c b/trunk/drivers/block/paride/pd.c index 40a11e567970..9d9bff23f426 100644 --- a/trunk/drivers/block/paride/pd.c +++ b/trunk/drivers/block/paride/pd.c @@ -352,19 +352,19 @@ static enum action (*phase)(void); static void run_fsm(void); -static void ps_tq_int( void *data); +static void ps_tq_int(struct work_struct *work); -static DECLARE_WORK(fsm_tq, ps_tq_int, NULL); +static DECLARE_DELAYED_WORK(fsm_tq, ps_tq_int); static void schedule_fsm(void) { if (!nice) - schedule_work(&fsm_tq); + schedule_delayed_work(&fsm_tq, 0); else schedule_delayed_work(&fsm_tq, nice-1); } -static void ps_tq_int(void *data) +static void ps_tq_int(struct work_struct *work) { run_fsm(); } diff --git a/trunk/drivers/block/paride/pf.c b/trunk/drivers/block/paride/pf.c index 1a9dee19efcf..7cdaa1951260 100644 --- a/trunk/drivers/block/paride/pf.c +++ b/trunk/drivers/block/paride/pf.c @@ -933,25 +933,25 @@ static int __init pf_init(void) int unit; if (disable) - return -1; + return -EINVAL; pf_init_units(); if (pf_detect()) - return -1; + return -ENODEV; pf_busy = 0; if (register_blkdev(major, name)) { for (pf = units, unit = 0; unit < PF_UNITS; pf++, unit++) put_disk(pf->disk); - return -1; + return -EBUSY; } pf_queue = blk_init_queue(do_pf_request, &pf_spin_lock); if (!pf_queue) { unregister_blkdev(major, name); for (pf = units, unit = 0; unit < PF_UNITS; pf++, unit++) put_disk(pf->disk); - return -1; + return -ENOMEM; } blk_queue_max_phys_segments(pf_queue, cluster); diff --git a/trunk/drivers/block/paride/pg.c b/trunk/drivers/block/paride/pg.c index 13f998aa1cd3..9970aedbb5d9 100644 --- a/trunk/drivers/block/paride/pg.c +++ b/trunk/drivers/block/paride/pg.c @@ -646,14 +646,14 @@ static int __init pg_init(void) int err; if (disable){ - err = -1; + err = -EINVAL; goto out; } pg_init_units(); if (pg_detect()) { - err = -1; + err = -ENODEV; goto out; } diff --git a/trunk/drivers/block/paride/pseudo.h b/trunk/drivers/block/paride/pseudo.h index 932342d7a8eb..bc3703294143 100644 --- a/trunk/drivers/block/paride/pseudo.h +++ b/trunk/drivers/block/paride/pseudo.h @@ -35,7 +35,7 @@ #include #include -static void ps_tq_int( void *data); +static void ps_tq_int(struct work_struct *work); static void (* ps_continuation)(void); static int (* ps_ready)(void); @@ -45,7 +45,7 @@ static int ps_nice = 0; static DEFINE_SPINLOCK(ps_spinlock __attribute__((unused))); -static DECLARE_WORK(ps_tq, ps_tq_int, NULL); +static DECLARE_DELAYED_WORK(ps_tq, ps_tq_int); static void ps_set_intr(void (*continuation)(void), int (*ready)(void), @@ -63,14 +63,14 @@ static void ps_set_intr(void (*continuation)(void), if (!ps_tq_active) { ps_tq_active = 1; if (!ps_nice) - schedule_work(&ps_tq); + schedule_delayed_work(&ps_tq, 0); else schedule_delayed_work(&ps_tq, ps_nice-1); } spin_unlock_irqrestore(&ps_spinlock,flags); } -static void ps_tq_int(void *data) +static void ps_tq_int(struct work_struct *work) { void (*con)(void); unsigned long flags; @@ -92,7 +92,7 @@ static void ps_tq_int(void *data) } ps_tq_active = 1; if (!ps_nice) - schedule_work(&ps_tq); + schedule_delayed_work(&ps_tq, 0); else schedule_delayed_work(&ps_tq, ps_nice-1); spin_unlock_irqrestore(&ps_spinlock,flags); diff --git a/trunk/drivers/block/paride/pt.c b/trunk/drivers/block/paride/pt.c index 35fb26636721..c902b25e4869 100644 --- a/trunk/drivers/block/paride/pt.c +++ b/trunk/drivers/block/paride/pt.c @@ -946,12 +946,12 @@ static int __init pt_init(void) int err; if (disable) { - err = -1; + err = -EINVAL; goto out; } if (pt_detect()) { - err = -1; + err = -ENODEV; goto out; } diff --git a/trunk/drivers/block/pktcdvd.c b/trunk/drivers/block/pktcdvd.c index f2904f67af47..7c95c762950f 100644 --- a/trunk/drivers/block/pktcdvd.c +++ b/trunk/drivers/block/pktcdvd.c @@ -1,6 +1,7 @@ /* * Copyright (C) 2000 Jens Axboe * Copyright (C) 2001-2004 Peter Osterlund + * Copyright (C) 2006 Thomas Maier * * May be copied or modified under the terms of the GNU General Public * License. See linux/COPYING for more information. @@ -54,11 +55,13 @@ #include #include #include -#include +#include #include #include #include #include +#include +#include #include @@ -83,9 +86,424 @@ static struct pktcdvd_device *pkt_devs[MAX_WRITERS]; static struct proc_dir_entry *pkt_proc; static int pktdev_major; +static int write_congestion_on = PKT_WRITE_CONGESTION_ON; +static int write_congestion_off = PKT_WRITE_CONGESTION_OFF; static struct mutex ctl_mutex; /* Serialize open/close/setup/teardown */ static mempool_t *psd_pool; +static struct class *class_pktcdvd = NULL; /* /sys/class/pktcdvd */ +static struct dentry *pkt_debugfs_root = NULL; /* /debug/pktcdvd */ + +/* forward declaration */ +static int pkt_setup_dev(dev_t dev, dev_t* pkt_dev); +static int pkt_remove_dev(dev_t pkt_dev); +static int pkt_seq_show(struct seq_file *m, void *p); + + + +/* + * create and register a pktcdvd kernel object. + */ +static struct pktcdvd_kobj* pkt_kobj_create(struct pktcdvd_device *pd, + const char* name, + struct kobject* parent, + struct kobj_type* ktype) +{ + struct pktcdvd_kobj *p; + p = kzalloc(sizeof(*p), GFP_KERNEL); + if (!p) + return NULL; + kobject_set_name(&p->kobj, "%s", name); + p->kobj.parent = parent; + p->kobj.ktype = ktype; + p->pd = pd; + if (kobject_register(&p->kobj) != 0) + return NULL; + return p; +} +/* + * remove a pktcdvd kernel object. + */ +static void pkt_kobj_remove(struct pktcdvd_kobj *p) +{ + if (p) + kobject_unregister(&p->kobj); +} +/* + * default release function for pktcdvd kernel objects. + */ +static void pkt_kobj_release(struct kobject *kobj) +{ + kfree(to_pktcdvdkobj(kobj)); +} + + +/********************************************************** + * + * sysfs interface for pktcdvd + * by (C) 2006 Thomas Maier + * + **********************************************************/ + +#define DEF_ATTR(_obj,_name,_mode) \ + static struct attribute _obj = { \ + .name = _name, .owner = THIS_MODULE, .mode = _mode } + +/********************************************************** + /sys/class/pktcdvd/pktcdvd[0-7]/ + stat/reset + stat/packets_started + stat/packets_finished + stat/kb_written + stat/kb_read + stat/kb_read_gather + write_queue/size + write_queue/congestion_off + write_queue/congestion_on + **********************************************************/ + +DEF_ATTR(kobj_pkt_attr_st1, "reset", 0200); +DEF_ATTR(kobj_pkt_attr_st2, "packets_started", 0444); +DEF_ATTR(kobj_pkt_attr_st3, "packets_finished", 0444); +DEF_ATTR(kobj_pkt_attr_st4, "kb_written", 0444); +DEF_ATTR(kobj_pkt_attr_st5, "kb_read", 0444); +DEF_ATTR(kobj_pkt_attr_st6, "kb_read_gather", 0444); + +static struct attribute *kobj_pkt_attrs_stat[] = { + &kobj_pkt_attr_st1, + &kobj_pkt_attr_st2, + &kobj_pkt_attr_st3, + &kobj_pkt_attr_st4, + &kobj_pkt_attr_st5, + &kobj_pkt_attr_st6, + NULL +}; + +DEF_ATTR(kobj_pkt_attr_wq1, "size", 0444); +DEF_ATTR(kobj_pkt_attr_wq2, "congestion_off", 0644); +DEF_ATTR(kobj_pkt_attr_wq3, "congestion_on", 0644); + +static struct attribute *kobj_pkt_attrs_wqueue[] = { + &kobj_pkt_attr_wq1, + &kobj_pkt_attr_wq2, + &kobj_pkt_attr_wq3, + NULL +}; + +/* declares a char buffer[64] _dbuf, copies data from + * _b with length _l into it and ensures that _dbuf ends + * with a \0 character. + */ +#define DECLARE_BUF_AS_STRING(_dbuf, _b, _l) \ + char _dbuf[64]; int dlen = (_l) < 0 ? 0 : (_l); \ + if (dlen >= sizeof(_dbuf)) dlen = sizeof(_dbuf)-1; \ + memcpy(_dbuf, _b, dlen); _dbuf[dlen] = 0 + +static ssize_t kobj_pkt_show(struct kobject *kobj, + struct attribute *attr, char *data) +{ + struct pktcdvd_device *pd = to_pktcdvdkobj(kobj)->pd; + int n = 0; + int v; + if (strcmp(attr->name, "packets_started") == 0) { + n = sprintf(data, "%lu\n", pd->stats.pkt_started); + + } else if (strcmp(attr->name, "packets_finished") == 0) { + n = sprintf(data, "%lu\n", pd->stats.pkt_ended); + + } else if (strcmp(attr->name, "kb_written") == 0) { + n = sprintf(data, "%lu\n", pd->stats.secs_w >> 1); + + } else if (strcmp(attr->name, "kb_read") == 0) { + n = sprintf(data, "%lu\n", pd->stats.secs_r >> 1); + + } else if (strcmp(attr->name, "kb_read_gather") == 0) { + n = sprintf(data, "%lu\n", pd->stats.secs_rg >> 1); + + } else if (strcmp(attr->name, "size") == 0) { + spin_lock(&pd->lock); + v = pd->bio_queue_size; + spin_unlock(&pd->lock); + n = sprintf(data, "%d\n", v); + + } else if (strcmp(attr->name, "congestion_off") == 0) { + spin_lock(&pd->lock); + v = pd->write_congestion_off; + spin_unlock(&pd->lock); + n = sprintf(data, "%d\n", v); + + } else if (strcmp(attr->name, "congestion_on") == 0) { + spin_lock(&pd->lock); + v = pd->write_congestion_on; + spin_unlock(&pd->lock); + n = sprintf(data, "%d\n", v); + } + return n; +} + +static void init_write_congestion_marks(int* lo, int* hi) +{ + if (*hi > 0) { + *hi = max(*hi, 500); + *hi = min(*hi, 1000000); + if (*lo <= 0) + *lo = *hi - 100; + else { + *lo = min(*lo, *hi - 100); + *lo = max(*lo, 100); + } + } else { + *hi = -1; + *lo = -1; + } +} + +static ssize_t kobj_pkt_store(struct kobject *kobj, + struct attribute *attr, + const char *data, size_t len) +{ + struct pktcdvd_device *pd = to_pktcdvdkobj(kobj)->pd; + int val; + DECLARE_BUF_AS_STRING(dbuf, data, len); /* ensure sscanf scans a string */ + + if (strcmp(attr->name, "reset") == 0 && dlen > 0) { + pd->stats.pkt_started = 0; + pd->stats.pkt_ended = 0; + pd->stats.secs_w = 0; + pd->stats.secs_rg = 0; + pd->stats.secs_r = 0; + + } else if (strcmp(attr->name, "congestion_off") == 0 + && sscanf(dbuf, "%d", &val) == 1) { + spin_lock(&pd->lock); + pd->write_congestion_off = val; + init_write_congestion_marks(&pd->write_congestion_off, + &pd->write_congestion_on); + spin_unlock(&pd->lock); + + } else if (strcmp(attr->name, "congestion_on") == 0 + && sscanf(dbuf, "%d", &val) == 1) { + spin_lock(&pd->lock); + pd->write_congestion_on = val; + init_write_congestion_marks(&pd->write_congestion_off, + &pd->write_congestion_on); + spin_unlock(&pd->lock); + } + return len; +} + +static struct sysfs_ops kobj_pkt_ops = { + .show = kobj_pkt_show, + .store = kobj_pkt_store +}; +static struct kobj_type kobj_pkt_type_stat = { + .release = pkt_kobj_release, + .sysfs_ops = &kobj_pkt_ops, + .default_attrs = kobj_pkt_attrs_stat +}; +static struct kobj_type kobj_pkt_type_wqueue = { + .release = pkt_kobj_release, + .sysfs_ops = &kobj_pkt_ops, + .default_attrs = kobj_pkt_attrs_wqueue +}; + +static void pkt_sysfs_dev_new(struct pktcdvd_device *pd) +{ + if (class_pktcdvd) { + pd->clsdev = class_device_create(class_pktcdvd, + NULL, pd->pkt_dev, + NULL, "%s", pd->name); + if (IS_ERR(pd->clsdev)) + pd->clsdev = NULL; + } + if (pd->clsdev) { + pd->kobj_stat = pkt_kobj_create(pd, "stat", + &pd->clsdev->kobj, + &kobj_pkt_type_stat); + pd->kobj_wqueue = pkt_kobj_create(pd, "write_queue", + &pd->clsdev->kobj, + &kobj_pkt_type_wqueue); + } +} + +static void pkt_sysfs_dev_remove(struct pktcdvd_device *pd) +{ + pkt_kobj_remove(pd->kobj_stat); + pkt_kobj_remove(pd->kobj_wqueue); + if (class_pktcdvd) + class_device_destroy(class_pktcdvd, pd->pkt_dev); +} + + +/******************************************************************** + /sys/class/pktcdvd/ + add map block device + remove unmap packet dev + device_map show mappings + *******************************************************************/ + +static void class_pktcdvd_release(struct class *cls) +{ + kfree(cls); +} +static ssize_t class_pktcdvd_show_map(struct class *c, char *data) +{ + int n = 0; + int idx; + mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); + for (idx = 0; idx < MAX_WRITERS; idx++) { + struct pktcdvd_device *pd = pkt_devs[idx]; + if (!pd) + continue; + n += sprintf(data+n, "%s %u:%u %u:%u\n", + pd->name, + MAJOR(pd->pkt_dev), MINOR(pd->pkt_dev), + MAJOR(pd->bdev->bd_dev), + MINOR(pd->bdev->bd_dev)); + } + mutex_unlock(&ctl_mutex); + return n; +} + +static ssize_t class_pktcdvd_store_add(struct class *c, const char *buf, + size_t count) +{ + unsigned int major, minor; + DECLARE_BUF_AS_STRING(dbuf, buf, count); + if (sscanf(dbuf, "%u:%u", &major, &minor) == 2) { + pkt_setup_dev(MKDEV(major, minor), NULL); + return count; + } + return -EINVAL; +} + +static ssize_t class_pktcdvd_store_remove(struct class *c, const char *buf, + size_t count) +{ + unsigned int major, minor; + DECLARE_BUF_AS_STRING(dbuf, buf, count); + if (sscanf(dbuf, "%u:%u", &major, &minor) == 2) { + pkt_remove_dev(MKDEV(major, minor)); + return count; + } + return -EINVAL; +} + +static struct class_attribute class_pktcdvd_attrs[] = { + __ATTR(add, 0200, NULL, class_pktcdvd_store_add), + __ATTR(remove, 0200, NULL, class_pktcdvd_store_remove), + __ATTR(device_map, 0444, class_pktcdvd_show_map, NULL), + __ATTR_NULL +}; + + +static int pkt_sysfs_init(void) +{ + int ret = 0; + + /* + * create control files in sysfs + * /sys/class/pktcdvd/... + */ + class_pktcdvd = kzalloc(sizeof(*class_pktcdvd), GFP_KERNEL); + if (!class_pktcdvd) + return -ENOMEM; + class_pktcdvd->name = DRIVER_NAME; + class_pktcdvd->owner = THIS_MODULE; + class_pktcdvd->class_release = class_pktcdvd_release; + class_pktcdvd->class_attrs = class_pktcdvd_attrs; + ret = class_register(class_pktcdvd); + if (ret) { + kfree(class_pktcdvd); + class_pktcdvd = NULL; + printk(DRIVER_NAME": failed to create class pktcdvd\n"); + return ret; + } + return 0; +} + +static void pkt_sysfs_cleanup(void) +{ + if (class_pktcdvd) + class_destroy(class_pktcdvd); + class_pktcdvd = NULL; +} + +/******************************************************************** + entries in debugfs + + /debugfs/pktcdvd[0-7]/ + info + + *******************************************************************/ + +static int pkt_debugfs_seq_show(struct seq_file *m, void *p) +{ + return pkt_seq_show(m, p); +} + +static int pkt_debugfs_fops_open(struct inode *inode, struct file *file) +{ + return single_open(file, pkt_debugfs_seq_show, inode->i_private); +} + +static struct file_operations debug_fops = { + .open = pkt_debugfs_fops_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + +static void pkt_debugfs_dev_new(struct pktcdvd_device *pd) +{ + if (!pkt_debugfs_root) + return; + pd->dfs_f_info = NULL; + pd->dfs_d_root = debugfs_create_dir(pd->name, pkt_debugfs_root); + if (IS_ERR(pd->dfs_d_root)) { + pd->dfs_d_root = NULL; + return; + } + pd->dfs_f_info = debugfs_create_file("info", S_IRUGO, + pd->dfs_d_root, pd, &debug_fops); + if (IS_ERR(pd->dfs_f_info)) { + pd->dfs_f_info = NULL; + return; + } +} + +static void pkt_debugfs_dev_remove(struct pktcdvd_device *pd) +{ + if (!pkt_debugfs_root) + return; + if (pd->dfs_f_info) + debugfs_remove(pd->dfs_f_info); + pd->dfs_f_info = NULL; + if (pd->dfs_d_root) + debugfs_remove(pd->dfs_d_root); + pd->dfs_d_root = NULL; +} + +static void pkt_debugfs_init(void) +{ + pkt_debugfs_root = debugfs_create_dir(DRIVER_NAME, NULL); + if (IS_ERR(pkt_debugfs_root)) { + pkt_debugfs_root = NULL; + return; + } +} + +static void pkt_debugfs_cleanup(void) +{ + if (!pkt_debugfs_root) + return; + debugfs_remove(pkt_debugfs_root); + pkt_debugfs_root = NULL; +} + +/* ----------------------------------------------------------*/ + static void pkt_bio_finished(struct pktcdvd_device *pd) { @@ -893,6 +1311,7 @@ static int pkt_handle_queue(struct pktcdvd_device *pd) sector_t zone = 0; /* Suppress gcc warning */ struct pkt_rb_node *node, *first_node; struct rb_node *n; + int wakeup; VPRINTK("handle_queue\n"); @@ -965,7 +1384,13 @@ static int pkt_handle_queue(struct pktcdvd_device *pd) pkt->write_size += bio->bi_size / CD_FRAMESIZE; spin_unlock(&pkt->lock); } + /* check write congestion marks, and if bio_queue_size is + below, wake up any waiters */ + wakeup = (pd->write_congestion_on > 0 + && pd->bio_queue_size <= pd->write_congestion_off); spin_unlock(&pd->lock); + if (wakeup) + blk_clear_queue_congested(pd->disk->queue, WRITE); pkt->sleep_time = max(PACKET_WAIT_TIME, 1); pkt_set_state(pkt, PACKET_WAITING_STATE); @@ -2178,6 +2603,23 @@ static int pkt_make_request(request_queue_t *q, struct bio *bio) } spin_unlock(&pd->cdrw.active_list_lock); + /* + * Test if there is enough room left in the bio work queue + * (queue size >= congestion on mark). + * If not, wait till the work queue size is below the congestion off mark. + */ + spin_lock(&pd->lock); + if (pd->write_congestion_on > 0 + && pd->bio_queue_size >= pd->write_congestion_on) { + blk_set_queue_congested(q, WRITE); + do { + spin_unlock(&pd->lock); + congestion_wait(WRITE, HZ); + spin_lock(&pd->lock); + } while(pd->bio_queue_size > pd->write_congestion_off); + } + spin_unlock(&pd->lock); + /* * No matching packet found. Store the bio in the work queue. */ @@ -2297,6 +2739,9 @@ static int pkt_seq_show(struct seq_file *m, void *p) seq_printf(m, "\tstate:\t\t\ti:%d ow:%d rw:%d ww:%d rec:%d fin:%d\n", states[0], states[1], states[2], states[3], states[4], states[5]); + seq_printf(m, "\twrite congestion marks:\toff=%d on=%d\n", + pd->write_congestion_off, + pd->write_congestion_on); return 0; } @@ -2436,36 +2881,33 @@ static struct block_device_operations pktcdvd_ops = { /* * Set up mapping from pktcdvd device to CD-ROM device. */ -static int pkt_setup_dev(struct pkt_ctrl_command *ctrl_cmd) +static int pkt_setup_dev(dev_t dev, dev_t* pkt_dev) { int idx; int ret = -ENOMEM; struct pktcdvd_device *pd; struct gendisk *disk; - dev_t dev = new_decode_dev(ctrl_cmd->dev); + + mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); for (idx = 0; idx < MAX_WRITERS; idx++) if (!pkt_devs[idx]) break; if (idx == MAX_WRITERS) { printk(DRIVER_NAME": max %d writers supported\n", MAX_WRITERS); - return -EBUSY; + ret = -EBUSY; + goto out_mutex; } pd = kzalloc(sizeof(struct pktcdvd_device), GFP_KERNEL); if (!pd) - return ret; + goto out_mutex; pd->rb_pool = mempool_create_kmalloc_pool(PKT_RB_POOL_SIZE, sizeof(struct pkt_rb_node)); if (!pd->rb_pool) goto out_mem; - disk = alloc_disk(1); - if (!disk) - goto out_mem; - pd->disk = disk; - INIT_LIST_HEAD(&pd->cdrw.pkt_free_list); INIT_LIST_HEAD(&pd->cdrw.pkt_active_list); spin_lock_init(&pd->cdrw.active_list_lock); @@ -2476,11 +2918,18 @@ static int pkt_setup_dev(struct pkt_ctrl_command *ctrl_cmd) init_waitqueue_head(&pd->wqueue); pd->bio_queue = RB_ROOT; + pd->write_congestion_on = write_congestion_on; + pd->write_congestion_off = write_congestion_off; + + disk = alloc_disk(1); + if (!disk) + goto out_mem; + pd->disk = disk; disk->major = pktdev_major; disk->first_minor = idx; disk->fops = &pktcdvd_ops; disk->flags = GENHD_FL_REMOVABLE; - sprintf(disk->disk_name, DRIVER_NAME"%d", idx); + strcpy(disk->disk_name, pd->name); disk->private_data = pd; disk->queue = blk_alloc_queue(GFP_KERNEL); if (!disk->queue) @@ -2492,8 +2941,15 @@ static int pkt_setup_dev(struct pkt_ctrl_command *ctrl_cmd) goto out_new_dev; add_disk(disk); + + pkt_sysfs_dev_new(pd); + pkt_debugfs_dev_new(pd); + pkt_devs[idx] = pd; - ctrl_cmd->pkt_dev = new_encode_dev(pd->pkt_dev); + if (pkt_dev) + *pkt_dev = pd->pkt_dev; + + mutex_unlock(&ctl_mutex); return 0; out_new_dev: @@ -2504,17 +2960,22 @@ static int pkt_setup_dev(struct pkt_ctrl_command *ctrl_cmd) if (pd->rb_pool) mempool_destroy(pd->rb_pool); kfree(pd); +out_mutex: + mutex_unlock(&ctl_mutex); + printk(DRIVER_NAME": setup of pktcdvd device failed\n"); return ret; } /* * Tear down mapping from pktcdvd device to CD-ROM device. */ -static int pkt_remove_dev(struct pkt_ctrl_command *ctrl_cmd) +static int pkt_remove_dev(dev_t pkt_dev) { struct pktcdvd_device *pd; int idx; - dev_t pkt_dev = new_decode_dev(ctrl_cmd->pkt_dev); + int ret = 0; + + mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); for (idx = 0; idx < MAX_WRITERS; idx++) { pd = pkt_devs[idx]; @@ -2523,15 +2984,22 @@ static int pkt_remove_dev(struct pkt_ctrl_command *ctrl_cmd) } if (idx == MAX_WRITERS) { DPRINTK(DRIVER_NAME": dev not setup\n"); - return -ENXIO; + ret = -ENXIO; + goto out; } - if (pd->refcnt > 0) - return -EBUSY; - + if (pd->refcnt > 0) { + ret = -EBUSY; + goto out; + } if (!IS_ERR(pd->cdrw.thread)) kthread_stop(pd->cdrw.thread); + pkt_devs[idx] = NULL; + + pkt_debugfs_dev_remove(pd); + pkt_sysfs_dev_remove(pd); + blkdev_put(pd->bdev); remove_proc_entry(pd->name, pkt_proc); @@ -2541,18 +3009,24 @@ static int pkt_remove_dev(struct pkt_ctrl_command *ctrl_cmd) blk_cleanup_queue(pd->disk->queue); put_disk(pd->disk); - pkt_devs[idx] = NULL; mempool_destroy(pd->rb_pool); kfree(pd); /* This is safe: open() is still holding a reference. */ module_put(THIS_MODULE); - return 0; + +out: + mutex_unlock(&ctl_mutex); + return ret; } static void pkt_get_status(struct pkt_ctrl_command *ctrl_cmd) { - struct pktcdvd_device *pd = pkt_find_dev_from_minor(ctrl_cmd->dev_index); + struct pktcdvd_device *pd; + + mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); + + pd = pkt_find_dev_from_minor(ctrl_cmd->dev_index); if (pd) { ctrl_cmd->dev = new_encode_dev(pd->bdev->bd_dev); ctrl_cmd->pkt_dev = new_encode_dev(pd->pkt_dev); @@ -2561,6 +3035,8 @@ static void pkt_get_status(struct pkt_ctrl_command *ctrl_cmd) ctrl_cmd->pkt_dev = 0; } ctrl_cmd->num_devices = MAX_WRITERS; + + mutex_unlock(&ctl_mutex); } static int pkt_ctl_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) @@ -2568,6 +3044,7 @@ static int pkt_ctl_ioctl(struct inode *inode, struct file *file, unsigned int cm void __user *argp = (void __user *)arg; struct pkt_ctrl_command ctrl_cmd; int ret = 0; + dev_t pkt_dev = 0; if (cmd != PACKET_CTRL_CMD) return -ENOTTY; @@ -2579,21 +3056,16 @@ static int pkt_ctl_ioctl(struct inode *inode, struct file *file, unsigned int cm case PKT_CTRL_CMD_SETUP: if (!capable(CAP_SYS_ADMIN)) return -EPERM; - mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); - ret = pkt_setup_dev(&ctrl_cmd); - mutex_unlock(&ctl_mutex); + ret = pkt_setup_dev(new_decode_dev(ctrl_cmd.dev), &pkt_dev); + ctrl_cmd.pkt_dev = new_encode_dev(pkt_dev); break; case PKT_CTRL_CMD_TEARDOWN: if (!capable(CAP_SYS_ADMIN)) return -EPERM; - mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); - ret = pkt_remove_dev(&ctrl_cmd); - mutex_unlock(&ctl_mutex); + ret = pkt_remove_dev(new_decode_dev(ctrl_cmd.pkt_dev)); break; case PKT_CTRL_CMD_STATUS: - mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); pkt_get_status(&ctrl_cmd); - mutex_unlock(&ctl_mutex); break; default: return -ENOTTY; @@ -2620,6 +3092,8 @@ static int __init pkt_init(void) { int ret; + mutex_init(&ctl_mutex); + psd_pool = mempool_create_kmalloc_pool(PSD_POOL_SIZE, sizeof(struct packet_stacked_data)); if (!psd_pool) @@ -2633,18 +3107,25 @@ static int __init pkt_init(void) if (!pktdev_major) pktdev_major = ret; + ret = pkt_sysfs_init(); + if (ret) + goto out; + + pkt_debugfs_init(); + ret = misc_register(&pkt_misc); if (ret) { printk(DRIVER_NAME": Unable to register misc device\n"); - goto out; + goto out_misc; } - mutex_init(&ctl_mutex); - pkt_proc = proc_mkdir(DRIVER_NAME, proc_root_driver); return 0; +out_misc: + pkt_debugfs_cleanup(); + pkt_sysfs_cleanup(); out: unregister_blkdev(pktdev_major, DRIVER_NAME); out2: @@ -2656,6 +3137,10 @@ static void __exit pkt_exit(void) { remove_proc_entry(DRIVER_NAME, proc_root_driver); misc_deregister(&pkt_misc); + + pkt_debugfs_cleanup(); + pkt_sysfs_cleanup(); + unregister_blkdev(pktdev_major, DRIVER_NAME); mempool_destroy(psd_pool); } diff --git a/trunk/drivers/block/sx8.c b/trunk/drivers/block/sx8.c index 47d6975268ff..54509eb3391b 100644 --- a/trunk/drivers/block/sx8.c +++ b/trunk/drivers/block/sx8.c @@ -1244,9 +1244,10 @@ static irqreturn_t carm_interrupt(int irq, void *__host) return IRQ_RETVAL(handled); } -static void carm_fsm_task (void *_data) +static void carm_fsm_task (struct work_struct *work) { - struct carm_host *host = _data; + struct carm_host *host = + container_of(work, struct carm_host, fsm_task); unsigned long flags; unsigned int state; int rc, i, next_dev; @@ -1619,7 +1620,7 @@ static int carm_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) host->pdev = pdev; host->flags = pci_dac ? FL_DAC : 0; spin_lock_init(&host->lock); - INIT_WORK(&host->fsm_task, carm_fsm_task, host); + INIT_WORK(&host->fsm_task, carm_fsm_task); init_completion(&host->probe_comp); for (i = 0; i < ARRAY_SIZE(host->req); i++) diff --git a/trunk/drivers/block/ub.c b/trunk/drivers/block/ub.c index 0d5c73f07265..2098eff91e14 100644 --- a/trunk/drivers/block/ub.c +++ b/trunk/drivers/block/ub.c @@ -376,7 +376,7 @@ static int ub_submit_clear_stall(struct ub_dev *sc, struct ub_scsi_cmd *cmd, int stalled_pipe); static void ub_top_sense_done(struct ub_dev *sc, struct ub_scsi_cmd *scmd); static void ub_reset_enter(struct ub_dev *sc, int try); -static void ub_reset_task(void *arg); +static void ub_reset_task(struct work_struct *work); static int ub_sync_tur(struct ub_dev *sc, struct ub_lun *lun); static int ub_sync_read_cap(struct ub_dev *sc, struct ub_lun *lun, struct ub_capacity *ret); @@ -1558,9 +1558,9 @@ static void ub_reset_enter(struct ub_dev *sc, int try) schedule_work(&sc->reset_work); } -static void ub_reset_task(void *arg) +static void ub_reset_task(struct work_struct *work) { - struct ub_dev *sc = arg; + struct ub_dev *sc = container_of(work, struct ub_dev, reset_work); unsigned long flags; struct list_head *p; struct ub_lun *lun; @@ -2179,7 +2179,7 @@ static int ub_probe(struct usb_interface *intf, usb_init_urb(&sc->work_urb); tasklet_init(&sc->tasklet, ub_scsi_action, (unsigned long)sc); atomic_set(&sc->poison, 0); - INIT_WORK(&sc->reset_work, ub_reset_task, sc); + INIT_WORK(&sc->reset_work, ub_reset_task); init_waitqueue_head(&sc->reset_wait); init_timer(&sc->work_timer); diff --git a/trunk/drivers/bluetooth/bcm203x.c b/trunk/drivers/bluetooth/bcm203x.c index 516751754aa9..9256985cbe36 100644 --- a/trunk/drivers/bluetooth/bcm203x.c +++ b/trunk/drivers/bluetooth/bcm203x.c @@ -157,9 +157,10 @@ static void bcm203x_complete(struct urb *urb) } } -static void bcm203x_work(void *user_data) +static void bcm203x_work(struct work_struct *work) { - struct bcm203x_data *data = user_data; + struct bcm203x_data *data = + container_of(work, struct bcm203x_data, work); if (usb_submit_urb(data->urb, GFP_ATOMIC) < 0) BT_ERR("Can't submit URB"); @@ -246,7 +247,7 @@ static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id release_firmware(firmware); - INIT_WORK(&data->work, bcm203x_work, (void *) data); + INIT_WORK(&data->work, bcm203x_work); usb_set_intfdata(intf, data); diff --git a/trunk/drivers/bluetooth/bluecard_cs.c b/trunk/drivers/bluetooth/bluecard_cs.c index cbc07250b898..acfb6a430dcc 100644 --- a/trunk/drivers/bluetooth/bluecard_cs.c +++ b/trunk/drivers/bluetooth/bluecard_cs.c @@ -892,43 +892,10 @@ static void bluecard_detach(struct pcmcia_device *link) } -static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse) -{ - int i; - - i = pcmcia_get_first_tuple(handle, tuple); - if (i != CS_SUCCESS) - return CS_NO_MORE_ITEMS; - - i = pcmcia_get_tuple_data(handle, tuple); - if (i != CS_SUCCESS) - return i; - - return pcmcia_parse_tuple(handle, tuple, parse); -} - static int bluecard_config(struct pcmcia_device *link) { bluecard_info_t *info = link->priv; - tuple_t tuple; - u_short buf[256]; - cisparse_t parse; - int i, n, last_ret, last_fn; - - tuple.TupleData = (cisdata_t *)buf; - tuple.TupleOffset = 0; - tuple.TupleDataMax = 255; - tuple.Attributes = 0; - - /* Get configuration register information */ - tuple.DesiredTuple = CISTPL_CONFIG; - last_ret = first_tuple(link, &tuple, &parse); - if (last_ret != CS_SUCCESS) { - last_fn = ParseTuple; - goto cs_failed; - } - link->conf.ConfigBase = parse.config.base; - link->conf.Present = parse.config.rmask[0]; + int i, n; link->conf.ConfigIndex = 0x20; link->io.NumPorts1 = 64; @@ -966,9 +933,6 @@ static int bluecard_config(struct pcmcia_device *link) return 0; -cs_failed: - cs_error(link, last_fn, last_ret); - failed: bluecard_release(link); return -ENODEV; diff --git a/trunk/drivers/bluetooth/bt3c_cs.c b/trunk/drivers/bluetooth/bt3c_cs.c index 3a96a0babc6a..aae3abace586 100644 --- a/trunk/drivers/bluetooth/bt3c_cs.c +++ b/trunk/drivers/bluetooth/bt3c_cs.c @@ -713,22 +713,7 @@ static int bt3c_config(struct pcmcia_device *link) u_short buf[256]; cisparse_t parse; cistpl_cftable_entry_t *cf = &parse.cftable_entry; - int i, j, try, last_ret, last_fn; - - tuple.TupleData = (cisdata_t *)buf; - tuple.TupleOffset = 0; - tuple.TupleDataMax = 255; - tuple.Attributes = 0; - - /* Get configuration register information */ - tuple.DesiredTuple = CISTPL_CONFIG; - last_ret = first_tuple(link, &tuple, &parse); - if (last_ret != CS_SUCCESS) { - last_fn = ParseTuple; - goto cs_failed; - } - link->conf.ConfigBase = parse.config.base; - link->conf.Present = parse.config.rmask[0]; + int i, j, try; /* First pass: look for a config entry that looks normal. */ tuple.TupleData = (cisdata_t *)buf; @@ -802,9 +787,6 @@ static int bt3c_config(struct pcmcia_device *link) return 0; -cs_failed: - cs_error(link, last_fn, last_ret); - failed: bt3c_release(link); return -ENODEV; diff --git a/trunk/drivers/bluetooth/btuart_cs.c b/trunk/drivers/bluetooth/btuart_cs.c index 3b29086b7c3f..92648ef2f5d0 100644 --- a/trunk/drivers/bluetooth/btuart_cs.c +++ b/trunk/drivers/bluetooth/btuart_cs.c @@ -644,22 +644,7 @@ static int btuart_config(struct pcmcia_device *link) u_short buf[256]; cisparse_t parse; cistpl_cftable_entry_t *cf = &parse.cftable_entry; - int i, j, try, last_ret, last_fn; - - tuple.TupleData = (cisdata_t *)buf; - tuple.TupleOffset = 0; - tuple.TupleDataMax = 255; - tuple.Attributes = 0; - - /* Get configuration register information */ - tuple.DesiredTuple = CISTPL_CONFIG; - last_ret = first_tuple(link, &tuple, &parse); - if (last_ret != CS_SUCCESS) { - last_fn = ParseTuple; - goto cs_failed; - } - link->conf.ConfigBase = parse.config.base; - link->conf.Present = parse.config.rmask[0]; + int i, j, try; /* First pass: look for a config entry that looks normal. */ tuple.TupleData = (cisdata_t *) buf; @@ -734,9 +719,6 @@ static int btuart_config(struct pcmcia_device *link) return 0; -cs_failed: - cs_error(link, last_fn, last_ret); - failed: btuart_release(link); return -ENODEV; diff --git a/trunk/drivers/bluetooth/dtl1_cs.c b/trunk/drivers/bluetooth/dtl1_cs.c index 07eafbc5dc3a..77b99eecbc49 100644 --- a/trunk/drivers/bluetooth/dtl1_cs.c +++ b/trunk/drivers/bluetooth/dtl1_cs.c @@ -626,22 +626,7 @@ static int dtl1_config(struct pcmcia_device *link) u_short buf[256]; cisparse_t parse; cistpl_cftable_entry_t *cf = &parse.cftable_entry; - int i, last_ret, last_fn; - - tuple.TupleData = (cisdata_t *)buf; - tuple.TupleOffset = 0; - tuple.TupleDataMax = 255; - tuple.Attributes = 0; - - /* Get configuration register information */ - tuple.DesiredTuple = CISTPL_CONFIG; - last_ret = first_tuple(link, &tuple, &parse); - if (last_ret != CS_SUCCESS) { - last_fn = ParseTuple; - goto cs_failed; - } - link->conf.ConfigBase = parse.config.base; - link->conf.Present = parse.config.rmask[0]; + int i; tuple.TupleData = (cisdata_t *)buf; tuple.TupleOffset = 0; @@ -690,9 +675,6 @@ static int dtl1_config(struct pcmcia_device *link) return 0; -cs_failed: - cs_error(link, last_fn, last_ret); - failed: dtl1_release(link); return -ENODEV; diff --git a/trunk/drivers/bluetooth/hci_bcsp.c b/trunk/drivers/bluetooth/hci_bcsp.c index d0cface535fb..5e2c31882003 100644 --- a/trunk/drivers/bluetooth/hci_bcsp.c +++ b/trunk/drivers/bluetooth/hci_bcsp.c @@ -330,7 +330,7 @@ static struct sk_buff *bcsp_dequeue(struct hci_uart *hu) reliable packet if the number of packets sent but not yet ack'ed is < than the winsize */ - spin_lock_irqsave(&bcsp->unack.lock, flags); + spin_lock_irqsave_nested(&bcsp->unack.lock, flags, SINGLE_DEPTH_NESTING); if (bcsp->unack.qlen < BCSP_TXWINSIZE && (skb = skb_dequeue(&bcsp->rel)) != NULL) { struct sk_buff *nskb = bcsp_prepare_pkt(bcsp, skb->data, skb->len, bt_cb(skb)->pkt_type); @@ -696,7 +696,7 @@ static void bcsp_timed_event(unsigned long arg) BT_DBG("hu %p retransmitting %u pkts", hu, bcsp->unack.qlen); - spin_lock_irqsave(&bcsp->unack.lock, flags); + spin_lock_irqsave_nested(&bcsp->unack.lock, flags, SINGLE_DEPTH_NESTING); while ((skb = __skb_dequeue_tail(&bcsp->unack)) != NULL) { bcsp->msgq_txseq = (bcsp->msgq_txseq - 1) & 0x07; diff --git a/trunk/drivers/cdrom/optcd.c b/trunk/drivers/cdrom/optcd.c index 25032d7edc55..3541690a77d4 100644 --- a/trunk/drivers/cdrom/optcd.c +++ b/trunk/drivers/cdrom/optcd.c @@ -101,7 +101,7 @@ static void debug(int debug_this, const char* fmt, ...) return; va_start(args, fmt); - vsprintf(s, fmt, args); + vsnprintf(s, sizeof(s), fmt, args); printk(KERN_DEBUG "optcd: %s\n", s); va_end(args); } diff --git a/trunk/drivers/cdrom/sbpcd.c b/trunk/drivers/cdrom/sbpcd.c index ba50e5a712f2..a1283b1ef989 100644 --- a/trunk/drivers/cdrom/sbpcd.c +++ b/trunk/drivers/cdrom/sbpcd.c @@ -770,11 +770,10 @@ static void msg(int level, const char *fmt, ...) msgnum++; if (msgnum>99) msgnum=0; - sprintf(buf, MSG_LEVEL "%s-%d [%02d]: ", major_name, current_drive - D_S, msgnum); va_start(args, fmt); - vsprintf(&buf[18], fmt, args); + vsnprintf(buf, sizeof(buf), fmt, args); va_end(args); - printk(buf); + printk(MSG_LEVEL "%s-%d [%02d]: %s", major_name, current_drive - D_S, msgnum, buf); #if KLOGD_PAUSE sbp_sleep(KLOGD_PAUSE); /* else messages get lost */ #endif /* KLOGD_PAUSE */ diff --git a/trunk/drivers/char/Kconfig b/trunk/drivers/char/Kconfig index 24f922f12783..b10f4d8fdc7f 100644 --- a/trunk/drivers/char/Kconfig +++ b/trunk/drivers/char/Kconfig @@ -201,6 +201,21 @@ config MOXA_SMARTIO The module will be called mxser. If you want to do that, say M here. +config MOXA_SMARTIO_NEW + tristate "Moxa SmartIO support v. 2.0 (EXPERIMENTAL)" + depends on SERIAL_NONSTANDARD + help + Say Y here if you have a Moxa SmartIO multiport serial card and/or + want to help develop a new version of this driver. + + This is upgraded (1.9.1) driver from original Moxa drivers with + changes finally resulting in PCI probing. + + Use at your own risk. + + This driver can also be built as a module. The module will be called + mxser_new. If you want to do that, say M here. + config ISI tristate "Multi-Tech multiport card support (EXPERIMENTAL)" depends on SERIAL_NONSTANDARD diff --git a/trunk/drivers/char/Makefile b/trunk/drivers/char/Makefile index b1fcdab90947..fc110637ced6 100644 --- a/trunk/drivers/char/Makefile +++ b/trunk/drivers/char/Makefile @@ -31,6 +31,7 @@ obj-$(CONFIG_MOXA_INTELLIO) += moxa.o obj-$(CONFIG_A2232) += ser_a2232.o generic_serial.o obj-$(CONFIG_ATARI_DSP56K) += dsp56k.o obj-$(CONFIG_MOXA_SMARTIO) += mxser.o +obj-$(CONFIG_MOXA_SMARTIO_NEW) += mxser_new.o obj-$(CONFIG_COMPUTONE) += ip2/ obj-$(CONFIG_RISCOM8) += riscom8.o obj-$(CONFIG_ISI) += isicom.o diff --git a/trunk/drivers/char/agp/amd64-agp.c b/trunk/drivers/char/agp/amd64-agp.c index 00b17ae39736..2f2c4efff8a3 100644 --- a/trunk/drivers/char/agp/amd64-agp.c +++ b/trunk/drivers/char/agp/amd64-agp.c @@ -459,7 +459,7 @@ static const struct aper_size_info_32 nforce3_sizes[5] = /* Handle shadow device of the Nvidia NForce3 */ /* CHECK-ME original 2.4 version set up some IORRs. Check if that is needed. */ -static int __devinit nforce3_agp_init(struct pci_dev *pdev) +static int nforce3_agp_init(struct pci_dev *pdev) { u32 tmp, apbase, apbar, aplimit; struct pci_dev *dev1; diff --git a/trunk/drivers/char/amiserial.c b/trunk/drivers/char/amiserial.c index 66086fa2d59a..feb4ac802a0d 100644 --- a/trunk/drivers/char/amiserial.c +++ b/trunk/drivers/char/amiserial.c @@ -104,7 +104,7 @@ static struct async_struct *IRQ_ports; static unsigned char current_ctl_bits; -static void change_speed(struct async_struct *info, struct termios *old); +static void change_speed(struct async_struct *info, struct ktermios *old); static void rs_wait_until_sent(struct tty_struct *tty, int timeout); @@ -694,7 +694,7 @@ static void shutdown(struct async_struct * info) * the specified baud rate for a serial port. */ static void change_speed(struct async_struct *info, - struct termios *old_termios) + struct ktermios *old_termios) { int quot = 0, baud_base, baud; unsigned cflag, cval = 0; @@ -1365,7 +1365,7 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file, return 0; } -static void rs_set_termios(struct tty_struct *tty, struct termios *old_termios) +static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { struct async_struct *info = (struct async_struct *)tty->driver_data; unsigned long flags; diff --git a/trunk/drivers/char/cs5535_gpio.c b/trunk/drivers/char/cs5535_gpio.c index 8ce3f34cfc22..c02d9e99e050 100644 --- a/trunk/drivers/char/cs5535_gpio.c +++ b/trunk/drivers/char/cs5535_gpio.c @@ -82,7 +82,7 @@ static inline u32 cs5535_lowhigh_base(int reg) static ssize_t cs5535_gpio_write(struct file *file, const char __user *data, size_t len, loff_t *ppos) { - u32 m = iminor(file->f_dentry->d_inode); + u32 m = iminor(file->f_path.dentry->d_inode); int i, j; u32 base = gpio_base + cs5535_lowhigh_base(m); u32 m0, m1; @@ -117,7 +117,7 @@ static ssize_t cs5535_gpio_write(struct file *file, const char __user *data, static ssize_t cs5535_gpio_read(struct file *file, char __user *buf, size_t len, loff_t *ppos) { - u32 m = iminor(file->f_dentry->d_inode); + u32 m = iminor(file->f_path.dentry->d_inode); u32 base = gpio_base + cs5535_lowhigh_base(m); int rd_bit = 1 << (m & 0x0f); int i; diff --git a/trunk/drivers/char/cyclades.c b/trunk/drivers/char/cyclades.c index e608dadece2f..3ffa0807754c 100644 --- a/trunk/drivers/char/cyclades.c +++ b/trunk/drivers/char/cyclades.c @@ -1,8 +1,6 @@ #undef BLOCKMOVE #define Z_WAKE #undef Z_EXT_CHARS_IN_BUFFER -static char rcsid[] = -"$Revision: 2.3.2.20 $$Date: 2004/02/25 18:14:16 $"; /* * linux/drivers/char/cyclades.c @@ -593,18 +591,20 @@ static char rcsid[] = * */ +#define CY_VERSION "2.4" + /* If you need to install more boards than NR_CARDS, change the constant in the definition below. No other change is necessary to support up to eight boards. Beyond that you'll have to extend cy_isa_addresses. */ -#define NR_CARDS 4 +#define NR_CARDS 4 /* If the total number of ports is larger than NR_PORTS, change this constant in the definition below. No other change is necessary to support more boards/ports. */ -#define NR_PORTS 256 +#define NR_PORTS 256 #define ZE_V1_NPORTS 64 #define ZO_V1 0 @@ -625,9 +625,9 @@ static char rcsid[] = #undef CY_PCI_DEBUG #if 0 -#define PAUSE __asm__("nop"); +#define PAUSE __asm__("nop") #else -#define PAUSE ; +#define PAUSE do {} while (0) #endif /* @@ -663,7 +663,7 @@ static char rcsid[] = do { \ spin_lock_irqsave(&cy_card[info->card].card_lock, flags); \ } while (0) - + #define CY_UNLOCK(info,flags) \ do { \ spin_unlock_irqrestore(&cy_card[info->card].card_lock, flags); \ @@ -676,14 +676,14 @@ static char rcsid[] = #include #include -static void cy_throttle (struct tty_struct *tty); -static void cy_send_xchar (struct tty_struct *tty, char ch); +static void cy_throttle(struct tty_struct *tty); +static void cy_send_xchar(struct tty_struct *tty, char ch); #define IS_CYC_Z(card) ((card).num_chips == -1) #define Z_FPGA_CHECK(card) \ - ((cy_readl(&((struct RUNTIME_9060 __iomem *) \ - ((card).ctl_addr))->init_ctrl) & (1<<17)) != 0) + ((cy_readl(&((struct RUNTIME_9060 __iomem *) \ + ((card).ctl_addr))->init_ctrl) & (1<<17)) != 0) #define ISZLOADED(card) (((ZO_V1==cy_readl(&((struct RUNTIME_9060 __iomem *) \ ((card).ctl_addr))->mail_box_0)) || \ @@ -698,8 +698,6 @@ static void cy_send_xchar (struct tty_struct *tty, char ch); #define STD_COM_FLAGS (0) -#define JIFFIES_DIFF(n, j) ((j) - (n)) - static struct tty_driver *cy_serial_driver; #ifdef CONFIG_ISA @@ -713,27 +711,28 @@ static struct tty_driver *cy_serial_driver; */ static unsigned int cy_isa_addresses[] = { - 0xD0000, - 0xD2000, - 0xD4000, - 0xD6000, - 0xD8000, - 0xDA000, - 0xDC000, - 0xDE000, - 0,0,0,0,0,0,0,0 + 0xD0000, + 0xD2000, + 0xD4000, + 0xD6000, + 0xD8000, + 0xDA000, + 0xDC000, + 0xDE000, + 0, 0, 0, 0, 0, 0, 0, 0 }; + #define NR_ISA_ADDRS ARRAY_SIZE(cy_isa_addresses) #ifdef MODULE static long maddr[NR_CARDS] = { 0, }; -static int irq[NR_CARDS] = { 0, }; +static int irq[NR_CARDS] = { 0, }; module_param_array(maddr, long, NULL, 0); module_param_array(irq, int, NULL, 0); #endif -#endif /* CONFIG_ISA */ +#endif /* CONFIG_ISA */ /* This is the per-card data structure containing address, irq, number of channels, etc. This driver supports a maximum of NR_CARDS cards. @@ -745,7 +744,7 @@ static struct cyclades_card cy_card[NR_CARDS]; */ static struct cyclades_port cy_port[NR_PORTS]; -static int cy_next_channel; /* next minor available */ +static int cy_next_channel; /* next minor available */ /* * This is used to look up the divisor speeds and the timeouts @@ -757,36 +756,42 @@ static int cy_next_channel; /* next minor available */ * 20 */ static int baud_table[] = { - 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, - 1800, 2400, 4800, 9600, 19200, 38400, 57600, 76800,115200,150000, - 230400, 0}; - -static char baud_co_25[] = { /* 25 MHz clock option table */ - /* value => 00 01 02 03 04 */ - /* divide by 8 32 128 512 2048 */ - 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x02, - 0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - -static char baud_bpr_25[] = { /* 25 MHz baud rate period table */ - 0x00, 0xf5, 0xa3, 0x6f, 0x5c, 0x51, 0xf5, 0xa3, 0x51, 0xa3, - 0x6d, 0x51, 0xa3, 0x51, 0xa3, 0x51, 0x36, 0x29, 0x1b, 0x15}; - -static char baud_co_60[] = { /* 60 MHz clock option table (CD1400 J) */ - /* value => 00 01 02 03 04 */ - /* divide by 8 32 128 512 2048 */ - 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, - 0x03, 0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00}; - -static char baud_bpr_60[] = { /* 60 MHz baud rate period table (CD1400 J) */ - 0x00, 0x82, 0x21, 0xff, 0xdb, 0xc3, 0x92, 0x62, 0xc3, 0x62, - 0x41, 0xc3, 0x62, 0xc3, 0x62, 0xc3, 0x82, 0x62, 0x41, 0x32, - 0x21}; - -static char baud_cor3[] = { /* receive threshold */ - 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, - 0x0a, 0x0a, 0x0a, 0x09, 0x09, 0x08, 0x08, 0x08, 0x08, 0x07, - 0x07}; + 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, + 1800, 2400, 4800, 9600, 19200, 38400, 57600, 76800, 115200, 150000, + 230400, 0 +}; + +static char baud_co_25[] = { /* 25 MHz clock option table */ + /* value => 00 01 02 03 04 */ + /* divide by 8 32 128 512 2048 */ + 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x02, + 0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static char baud_bpr_25[] = { /* 25 MHz baud rate period table */ + 0x00, 0xf5, 0xa3, 0x6f, 0x5c, 0x51, 0xf5, 0xa3, 0x51, 0xa3, + 0x6d, 0x51, 0xa3, 0x51, 0xa3, 0x51, 0x36, 0x29, 0x1b, 0x15 +}; + +static char baud_co_60[] = { /* 60 MHz clock option table (CD1400 J) */ + /* value => 00 01 02 03 04 */ + /* divide by 8 32 128 512 2048 */ + 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, + 0x03, 0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00 +}; + +static char baud_bpr_60[] = { /* 60 MHz baud rate period table (CD1400 J) */ + 0x00, 0x82, 0x21, 0xff, 0xdb, 0xc3, 0x92, 0x62, 0xc3, 0x62, + 0x41, 0xc3, 0x62, 0xc3, 0x62, 0xc3, 0x82, 0x62, 0x41, 0x32, + 0x21 +}; + +static char baud_cor3[] = { /* receive threshold */ + 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, + 0x0a, 0x0a, 0x0a, 0x09, 0x09, 0x08, 0x08, 0x08, 0x08, 0x07, + 0x07 +}; /* * The Cyclades driver implements HW flow control as any serial driver. @@ -799,42 +804,42 @@ static char baud_cor3[] = { /* receive threshold */ * cables. */ -static char rflow_thr[] = { /* rflow threshold */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, - 0x0a}; +static char rflow_thr[] = { /* rflow threshold */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, + 0x0a +}; /* The Cyclom-Ye has placed the sequential chips in non-sequential * address order. This look-up table overcomes that problem. */ -static int cy_chip_offset [] = - { 0x0000, - 0x0400, - 0x0800, - 0x0C00, - 0x0200, - 0x0600, - 0x0A00, - 0x0E00 - }; +static int cy_chip_offset[] = { 0x0000, + 0x0400, + 0x0800, + 0x0C00, + 0x0200, + 0x0600, + 0x0A00, + 0x0E00 +}; /* PCI related definitions */ -static unsigned short cy_pci_nboard; -static unsigned short cy_isa_nboard; -static unsigned short cy_nboard; +static unsigned short cy_pci_nboard; +static unsigned short cy_isa_nboard; +static unsigned short cy_nboard; #ifdef CONFIG_PCI -static unsigned short cy_pci_dev_id[] = { - PCI_DEVICE_ID_CYCLOM_Y_Lo, /* PCI < 1Mb */ - PCI_DEVICE_ID_CYCLOM_Y_Hi, /* PCI > 1Mb */ - PCI_DEVICE_ID_CYCLOM_4Y_Lo, /* 4Y PCI < 1Mb */ - PCI_DEVICE_ID_CYCLOM_4Y_Hi, /* 4Y PCI > 1Mb */ - PCI_DEVICE_ID_CYCLOM_8Y_Lo, /* 8Y PCI < 1Mb */ - PCI_DEVICE_ID_CYCLOM_8Y_Hi, /* 8Y PCI > 1Mb */ - PCI_DEVICE_ID_CYCLOM_Z_Lo, /* Z PCI < 1Mb */ - PCI_DEVICE_ID_CYCLOM_Z_Hi, /* Z PCI > 1Mb */ - 0 /* end of table */ - }; +static unsigned short cy_pci_dev_id[] = { + PCI_DEVICE_ID_CYCLOM_Y_Lo, /* PCI < 1Mb */ + PCI_DEVICE_ID_CYCLOM_Y_Hi, /* PCI > 1Mb */ + PCI_DEVICE_ID_CYCLOM_4Y_Lo, /* 4Y PCI < 1Mb */ + PCI_DEVICE_ID_CYCLOM_4Y_Hi, /* 4Y PCI > 1Mb */ + PCI_DEVICE_ID_CYCLOM_8Y_Lo, /* 8Y PCI < 1Mb */ + PCI_DEVICE_ID_CYCLOM_8Y_Hi, /* 8Y PCI > 1Mb */ + PCI_DEVICE_ID_CYCLOM_Z_Lo, /* Z PCI < 1Mb */ + PCI_DEVICE_ID_CYCLOM_Z_Hi, /* Z PCI > 1Mb */ + 0 /* end of table */ +}; #endif static void cy_start(struct tty_struct *); @@ -842,9 +847,9 @@ static void set_line_char(struct cyclades_port *); static int cyz_issue_cmd(struct cyclades_card *, uclong, ucchar, uclong); #ifdef CONFIG_ISA static unsigned detect_isa_irq(void __iomem *); -#endif /* CONFIG_ISA */ +#endif /* CONFIG_ISA */ -static int cyclades_get_proc_info(char *, char **, off_t , int , int *, void *); +static int cyclades_get_proc_info(char *, char **, off_t, int, int *, void *); #ifndef CONFIG_CYZ_INTR static void cyz_poll(unsigned long); @@ -855,41 +860,36 @@ static long cyz_polling_cycle = CZ_DEF_POLL; static int cyz_timeron = 0; static DEFINE_TIMER(cyz_timerlist, cyz_poll, 0, 0); -#else /* CONFIG_CYZ_INTR */ +#else /* CONFIG_CYZ_INTR */ static void cyz_rx_restart(unsigned long); static struct timer_list cyz_rx_full_timer[NR_PORTS]; -#endif /* CONFIG_CYZ_INTR */ +#endif /* CONFIG_CYZ_INTR */ -static inline int -serial_paranoia_check(struct cyclades_port *info, - char *name, const char *routine) +static inline int serial_paranoia_check(struct cyclades_port *info, + char *name, const char *routine) { #ifdef SERIAL_PARANOIA_CHECK - static const char *badmagic = - "cyc Warning: bad magic number for serial struct (%s) in %s\n"; - static const char *badinfo = - "cyc Warning: null cyclades_port for (%s) in %s\n"; - static const char *badrange = - "cyc Warning: cyclades_port out of range for (%s) in %s\n"; - - if (!info) { - printk(badinfo, name, routine); - return 1; - } - - if( (long)info < (long)(&cy_port[0]) - || (long)(&cy_port[NR_PORTS]) < (long)info ){ - printk(badrange, name, routine); - return 1; - } - - if (info->magic != CYCLADES_MAGIC) { - printk(badmagic, name, routine); - return 1; - } + if (!info) { + printk("cyc Warning: null cyclades_port for (%s) in %s\n", + name, routine); + return 1; + } + + if ((long)info < (long)(&cy_port[0]) || + (long)(&cy_port[NR_PORTS]) < (long)info) { + printk("cyc Warning: cyclades_port out of range for (%s) in " + "%s\n", name, routine); + return 1; + } + + if (info->magic != CYCLADES_MAGIC) { + printk("cyc Warning: bad magic number for serial struct (%s) " + "in %s\n", name, routine); + return 1; + } #endif - return 0; -} /* serial_paranoia_check */ + return 0; +} /* serial_paranoia_check */ /* * This routine is used by the interrupt handler to schedule @@ -897,13 +897,11 @@ serial_paranoia_check(struct cyclades_port *info, * (also known as the "bottom half"). This can be called any * number of times for any channel without harm. */ -static inline void -cy_sched_event(struct cyclades_port *info, int event) +static inline void cy_sched_event(struct cyclades_port *info, int event) { - info->event |= 1 << event; /* remember what kind of event and who */ - schedule_work(&info->tqueue); -} /* cy_sched_event */ - + info->event |= 1 << event; /* remember what kind of event and who */ + schedule_work(&info->tqueue); +} /* cy_sched_event */ /* * This routine is used to handle the "bottom half" processing for the @@ -926,44 +924,40 @@ cy_sched_event(struct cyclades_port *info, int event) * had to poll every port to see if that port needed servicing. */ static void -do_softint(void *private_) +do_softint(struct work_struct *work) { - struct cyclades_port *info = (struct cyclades_port *) private_; - struct tty_struct *tty; - - tty = info->tty; - if (!tty) - return; - - if (test_and_clear_bit(Cy_EVENT_HANGUP, &info->event)) { - tty_hangup(info->tty); - wake_up_interruptible(&info->open_wait); - info->flags &= ~ASYNC_NORMAL_ACTIVE; - } - if (test_and_clear_bit(Cy_EVENT_OPEN_WAKEUP, &info->event)) { - wake_up_interruptible(&info->open_wait); - } + struct cyclades_port *info = + container_of(work, struct cyclades_port, tqueue); + struct tty_struct *tty; + + tty = info->tty; + if (!tty) + return; + + if (test_and_clear_bit(Cy_EVENT_HANGUP, &info->event)) { + tty_hangup(info->tty); + wake_up_interruptible(&info->open_wait); + info->flags &= ~ASYNC_NORMAL_ACTIVE; + } + if (test_and_clear_bit(Cy_EVENT_OPEN_WAKEUP, &info->event)) + wake_up_interruptible(&info->open_wait); #ifdef CONFIG_CYZ_INTR - if (test_and_clear_bit(Cy_EVENT_Z_RX_FULL, &info->event)) { - if (cyz_rx_full_timer[info->line].function == NULL) { - cyz_rx_full_timer[info->line].expires = jiffies + 1; - cyz_rx_full_timer[info->line].function = cyz_rx_restart; - cyz_rx_full_timer[info->line].data = (unsigned long)info; - add_timer(&cyz_rx_full_timer[info->line]); + if (test_and_clear_bit(Cy_EVENT_Z_RX_FULL, &info->event)) { + if (cyz_rx_full_timer[info->line].function == NULL) { + cyz_rx_full_timer[info->line].expires = jiffies + 1; + cyz_rx_full_timer[info->line].function = cyz_rx_restart; + cyz_rx_full_timer[info->line].data = + (unsigned long)info; + add_timer(&cyz_rx_full_timer[info->line]); + } } - } #endif - if (test_and_clear_bit(Cy_EVENT_DELTA_WAKEUP, &info->event)) { - wake_up_interruptible(&info->delta_msr_wait); - } - if (test_and_clear_bit(Cy_EVENT_WRITE_WAKEUP, &info->event)) { - tty_wakeup(tty); - wake_up_interruptible(&tty->write_wait); - } + if (test_and_clear_bit(Cy_EVENT_DELTA_WAKEUP, &info->event)) + wake_up_interruptible(&info->delta_msr_wait); + tty_wakeup(tty); #ifdef Z_WAKE - if (test_and_clear_bit(Cy_EVENT_SHUTDOWN_WAKEUP, &info->event)) { - wake_up_interruptible(&info->shutdown_wait); - } + if (test_and_clear_bit(Cy_EVENT_SHUTDOWN_WAKEUP, &info->event)) + wake_up_interruptible(&info->shutdown_wait); #endif } /* do_softint */ @@ -978,341 +972,339 @@ do_softint(void *private_) This function is only called from inside spinlock-protected code. */ -static int -cyy_issue_cmd(void __iomem *base_addr, u_char cmd, int index) +static int cyy_issue_cmd(void __iomem * base_addr, u_char cmd, int index) { - volatile int i; + volatile int i; - /* Check to see that the previous command has completed */ - for(i = 0 ; i < 100 ; i++){ - if (cy_readb(base_addr+(CyCCR< 0)? irq : 0; + int irq; + unsigned long irqs, flags; + int save_xir, save_car; + int index = 0; /* IRQ probing is only for ISA */ + + /* forget possible initially masked and pending IRQ */ + irq = probe_irq_off(probe_irq_on()); + + /* Clear interrupts on the board first */ + cy_writeb(address + (Cy_ClrIntr << index), 0); + /* Cy_ClrIntr is 0x1800 */ + + irqs = probe_irq_on(); + /* Wait ... */ + udelay(5000L); + + /* Enable the Tx interrupts on the CD1400 */ + local_irq_save(flags); + cy_writeb(address + (CyCAR << index), 0); + cyy_issue_cmd(address, CyCHAN_CTL | CyENB_XMTR, index); + + cy_writeb(address + (CyCAR << index), 0); + cy_writeb(address + (CySRER << index), + cy_readb(address + (CySRER << index)) | CyTxRdy); + local_irq_restore(flags); + + /* Wait ... */ + udelay(5000L); + + /* Check which interrupt is in use */ + irq = probe_irq_off(irqs); + + /* Clean up */ + save_xir = (u_char) cy_readb(address + (CyTIR << index)); + save_car = cy_readb(address + (CyCAR << index)); + cy_writeb(address + (CyCAR << index), (save_xir & 0x3)); + cy_writeb(address + (CySRER << index), + cy_readb(address + (CySRER << index)) & ~CyTxRdy); + cy_writeb(address + (CyTIR << index), (save_xir & 0x3f)); + cy_writeb(address + (CyCAR << index), (save_car)); + cy_writeb(address + (Cy_ClrIntr << index), 0); + /* Cy_ClrIntr is 0x1800 */ + + return (irq > 0) ? irq : 0; } -#endif /* CONFIG_ISA */ +#endif /* CONFIG_ISA */ -/* The real interrupt service routine is called - whenever the card wants its hand held--chars - received, out buffer empty, modem change, etc. - */ -static irqreturn_t -cyy_interrupt(int irq, void *dev_id) +static void cyy_intr_chip(struct cyclades_card *cinfo, int chip, + void __iomem * base_addr, int status, int index) { - struct tty_struct *tty; - int status; - struct cyclades_card *cinfo; - struct cyclades_port *info; - void __iomem *base_addr, *card_base_addr; - int chip; - int save_xir, channel, save_car; - char data; - volatile int char_count; - int outch; - int i,j,index; - int too_many; - int had_work; - int mdm_change; - int mdm_status; - int len; - if((cinfo = (struct cyclades_card *)dev_id) == 0){ -#ifdef CY_DEBUG_INTERRUPTS - printk("cyy_interrupt: spurious interrupt %d\n\r", irq); -#endif - return IRQ_NONE; /* spurious interrupt */ - } - - card_base_addr = cinfo->base_addr; - index = cinfo->bus_index; - - - /* This loop checks all chips in the card. Make a note whenever - _any_ chip had some work to do, as this is considered an - indication that there will be more to do. Only when no chip - has any work does this outermost loop exit. - */ - do{ - had_work = 0; - for ( chip = 0 ; chip < cinfo->num_chips ; chip ++) { - base_addr = cinfo->base_addr + (cy_chip_offset[chip]<card_lock); - save_xir = (u_char) cy_readb(base_addr+(CyRIR<first_line; - info = &cy_port[i]; - info->last_active = jiffies; - save_car = cy_readb(base_addr+(CyCAR<tty == 0){ - j = (cy_readb(base_addr+(CyRIVR<tty; - j = (cy_readb(base_addr+(CyRIVR<icount.brk++; - else if(data & CyFRAME) - info->icount.frame++; - else if(data & CyPARITY) - info->icount.parity++; - else if(data & CyOVERRUN) - info->icount.overrun++; - - if(data & info->ignore_status_mask){ - info->icount.rx++; - continue; - } - if (tty_buffer_request_room(tty, 1)) { - if (data & info->read_status_mask){ - if(data & CyBREAK){ - tty_insert_flip_char(tty, cy_readb(base_addr+(CyRDSR<icount.rx++; - if (info->flags & ASYNC_SAK){ - do_SAK(tty); - } - }else if(data & CyFRAME){ - tty_insert_flip_char(tty, cy_readb(base_addr+(CyRDSR<icount.rx++; - info->idle_stats.frame_errs++; - }else if(data & CyPARITY){ - /* Pieces of seven... */ - tty_insert_flip_char(tty, cy_readb(base_addr+(CyRDSR<icount.rx++; - info->idle_stats.parity_errs++; - }else if(data & CyOVERRUN){ - tty_insert_flip_char(tty, 0, TTY_OVERRUN); + /* determine the channel & change to that context */ + spin_lock(&cinfo->card_lock); + save_xir = (u_char) cy_readb(base_addr + (CyRIR << index)); + channel = (u_short) (save_xir & CyIRChannel); + i = channel + chip * 4 + cinfo->first_line; + info = &cy_port[i]; + info->last_active = jiffies; + save_car = cy_readb(base_addr + (CyCAR << index)); + cy_writeb(base_addr + (CyCAR << index), save_xir); + + /* if there is nowhere to put the data, discard it */ + if (info->tty == 0) { + j = (cy_readb(base_addr + (CyRIVR << index)) & + CyIVRMask); + if (j == CyIVRRxEx) { /* exception */ + data = cy_readb(base_addr + (CyRDSR << index)); + } else { /* normal character reception */ + char_count = cy_readb(base_addr + + (CyRDCR << index)); + while (char_count--) { + data = cy_readb(base_addr + + (CyRDSR << index)); + } + } + } else { /* there is an open port for this data */ + tty = info->tty; + j = (cy_readb(base_addr + (CyRIVR << index)) & + CyIVRMask); + if (j == CyIVRRxEx) { /* exception */ + data = cy_readb(base_addr + (CyRDSR << index)); + + /* For statistics only */ + if (data & CyBREAK) + info->icount.brk++; + else if (data & CyFRAME) + info->icount.frame++; + else if (data & CyPARITY) + info->icount.parity++; + else if (data & CyOVERRUN) + info->icount.overrun++; + + if (data & info->ignore_status_mask) { info->icount.rx++; - /* If the flip buffer itself is - overflowing, we still lose - the next incoming character. - */ - tty_insert_flip_char(tty, cy_readb(base_addr+(CyRDSR<icount.rx++; + return; + } + if (tty_buffer_request_room(tty, 1)) { + if (data & info->read_status_mask) { + if (data & CyBREAK) { + tty_insert_flip_char( + tty, + cy_readb( + base_addr + + (CyRDSR << + index)), + TTY_BREAK); + info->icount.rx++; + if (info->flags & + ASYNC_SAK) { + do_SAK(tty); + } + } else if (data & CyFRAME) { + tty_insert_flip_char( + tty, + cy_readb( + base_addr + + (CyRDSR << + index)), + TTY_FRAME); + info->icount.rx++; + info->idle_stats. + frame_errs++; + } else if (data & CyPARITY) { + /* Pieces of seven... */ + tty_insert_flip_char( + tty, + cy_readb( + base_addr + + (CyRDSR << + index)), + TTY_PARITY); + info->icount.rx++; + info->idle_stats. + parity_errs++; + } else if (data & CyOVERRUN) { + tty_insert_flip_char( + tty, 0, + TTY_OVERRUN); + info->icount.rx++; + /* If the flip buffer itself is + overflowing, we still lose + the next incoming character. + */ + tty_insert_flip_char( + tty, + cy_readb( + base_addr + + (CyRDSR << + index)), + TTY_FRAME); + info->icount.rx++; + info->idle_stats. + overruns++; + /* These two conditions may imply */ + /* a normal read should be done. */ + /* }else if(data & CyTIMEOUT){ */ + /* }else if(data & CySPECHAR){ */ + } else { + tty_insert_flip_char( + tty, 0, + TTY_NORMAL); + info->icount.rx++; + } + } else { + tty_insert_flip_char(tty, 0, + TTY_NORMAL); + info->icount.rx++; + } + } else { + /* there was a software buffer + overrun and nothing could be + done about it!!! */ + info->icount.buf_overrun++; info->idle_stats.overruns++; - /* These two conditions may imply */ - /* a normal read should be done. */ - /* }else if(data & CyTIMEOUT){ */ - /* }else if(data & CySPECHAR){ */ - }else { - tty_insert_flip_char(tty, 0, TTY_NORMAL); - info->icount.rx++; - } - }else{ - tty_insert_flip_char(tty, 0, TTY_NORMAL); - info->icount.rx++; - } - }else{ - /* there was a software buffer - overrun and nothing could be - done about it!!! */ - info->icount.buf_overrun++; - info->idle_stats.overruns++; - } - } else { /* normal character reception */ - /* load # chars available from the chip */ - char_count = cy_readb(base_addr+(CyRDCR<mon.int_count; - info->mon.char_count += char_count; - if (char_count > info->mon.char_max) - info->mon.char_max = char_count; - info->mon.char_last = char_count; + ++info->mon.int_count; + info->mon.char_count += char_count; + if (char_count > info->mon.char_max) + info->mon.char_max = char_count; + info->mon.char_last = char_count; #endif - len = tty_buffer_request_room(tty, char_count); - while(len--){ - data = cy_readb(base_addr+(CyRDSR<idle_stats.recv_bytes++; - info->icount.rx++; + len = tty_buffer_request_room(tty, char_count); + while (len--) { + data = cy_readb(base_addr + + (CyRDSR << index)); + tty_insert_flip_char(tty, data, + TTY_NORMAL); + info->idle_stats.recv_bytes++; + info->icount.rx++; #ifdef CY_16Y_HACK - udelay(10L); + udelay(10L); #endif - } - info->idle_stats.recv_idle = jiffies; - } + } + info->idle_stats.recv_idle = jiffies; + } tty_schedule_flip(tty); - } - /* end of service */ - cy_writeb(base_addr+(CyRIR<card_lock); - } - - - if (status & CySRTransmit) { /* transmission interrupt */ - /* Since we only get here when the transmit buffer - is empty, we know we can always stuff a dozen - characters. */ + } + /* end of service */ + cy_writeb(base_addr + (CyRIR << index), (save_xir & 0x3f)); + cy_writeb(base_addr + (CyCAR << index), (save_car)); + spin_unlock(&cinfo->card_lock); + } + + if (status & CySRTransmit) { /* transmission interrupt */ + /* Since we only get here when the transmit buffer + is empty, we know we can always stuff a dozen + characters. */ #ifdef CY_DEBUG_INTERRUPTS - printk("cyy_interrupt: xmit intr, chip %d\n\r", chip); + printk("cyy_interrupt: xmit intr, chip %d\n\r", chip); #endif - /* determine the channel & change to that context */ - spin_lock(&cinfo->card_lock); - save_xir = (u_char) cy_readb(base_addr+(CyTIR<first_line; - save_car = cy_readb(base_addr+(CyCAR<last_active = jiffies; - if(info->tty == 0){ - cy_writeb(base_addr+(CySRER<xmit_fifo_size; - - if(info->x_char) { /* send special char */ - outch = info->x_char; - cy_writeb(base_addr+(CyTDR<card_lock); + save_xir = (u_char) cy_readb(base_addr + (CyTIR << index)); + channel = (u_short) (save_xir & CyIRChannel); + i = channel + chip * 4 + cinfo->first_line; + save_car = cy_readb(base_addr + (CyCAR << index)); + cy_writeb(base_addr + (CyCAR << index), save_xir); + + /* validate the port# (as configured and open) */ + if ((i < 0) || (NR_PORTS <= i)) { + cy_writeb(base_addr + (CySRER << index), + cy_readb(base_addr + (CySRER << index)) & + ~CyTxRdy); + goto txend; + } + info = &cy_port[i]; + info->last_active = jiffies; + if (info->tty == 0) { + cy_writeb(base_addr + (CySRER << index), + cy_readb(base_addr + (CySRER << index)) & + ~CyTxRdy); + goto txdone; + } + + /* load the on-chip space for outbound data */ + char_count = info->xmit_fifo_size; + + if (info->x_char) { /* send special char */ + outch = info->x_char; + cy_writeb(base_addr + (CyTDR << index), outch); + char_count--; info->icount.tx++; - info->x_char = 0; - } + info->x_char = 0; + } - if (info->breakon || info->breakoff) { + if (info->breakon || info->breakoff) { if (info->breakon) { - cy_writeb(base_addr + (CyTDR<breakon = 0; - char_count -= 2; + cy_writeb(base_addr + (CyTDR << index), 0); + cy_writeb(base_addr + (CyTDR << index), 0x81); + info->breakon = 0; + char_count -= 2; } if (info->breakoff) { - cy_writeb(base_addr + (CyTDR<breakoff = 0; - char_count -= 2; + cy_writeb(base_addr + (CyTDR << index), 0); + cy_writeb(base_addr + (CyTDR << index), 0x83); + info->breakoff = 0; + char_count -= 2; } - } - - while (char_count-- > 0){ - if (!info->xmit_cnt){ - if (cy_readb(base_addr+(CySRER< 0) { + if (!info->xmit_cnt) { + if (cy_readb(base_addr + (CySRER << index)) & + CyTxMpty) { + cy_writeb(base_addr + (CySRER << index), + cy_readb(base_addr + + (CySRER << index)) & + ~CyTxMpty); + } else { + cy_writeb(base_addr + (CySRER << index), + (cy_readb(base_addr + + (CySRER << index)) & + ~CyTxRdy) | CyTxMpty); + } + goto txdone; } - if (info->xmit_buf == 0){ - cy_writeb(base_addr+(CySRER<xmit_buf == 0) { + cy_writeb(base_addr + (CySRER << index), + cy_readb(base_addr + (CySRER << index))& ~CyTxRdy); - goto txdone; + goto txdone; } - if (info->tty->stopped || info->tty->hw_stopped){ - cy_writeb(base_addr+(CySRER<tty->stopped || info->tty->hw_stopped) { + cy_writeb(base_addr + (CySRER << index), + cy_readb(base_addr + (CySRER << index))& ~CyTxRdy); - goto txdone; + goto txdone; } - /* Because the Embedded Transmit Commands have - been enabled, we must check to see if the + /* Because the Embedded Transmit Commands have + been enabled, we must check to see if the escape character, NULL, is being sent. If it is, we must ensure that there is room for it to be doubled in the output stream. Therefore @@ -1321,125 +1313,182 @@ cyy_interrupt(int irq, void *dev_id) after the check for a NULL output character. This is necessary because there may not be room for the two chars needed to send a NULL.) - */ - outch = info->xmit_buf[info->xmit_tail]; - if( outch ){ - info->xmit_cnt--; - info->xmit_tail = (info->xmit_tail + 1) - & (SERIAL_XMIT_SIZE - 1); - cy_writeb(base_addr+(CyTDR<icount.tx++; - }else{ - if(char_count > 1){ - info->xmit_cnt--; - info->xmit_tail = (info->xmit_tail + 1) - & (SERIAL_XMIT_SIZE - 1); - cy_writeb(base_addr+(CyTDR<xmit_buf[info->xmit_tail]; + if (outch) { + info->xmit_cnt--; + info->xmit_tail = (info->xmit_tail + 1) & + (SERIAL_XMIT_SIZE - 1); + cy_writeb(base_addr + (CyTDR << index), outch); info->icount.tx++; - char_count--; - }else{ - } - } - } - - txdone: - if (info->xmit_cnt < WAKEUP_CHARS) { - cy_sched_event(info, Cy_EVENT_WRITE_WAKEUP); - } - txend: - /* end of service */ - cy_writeb(base_addr+(CyTIR<card_lock); - } - - if (status & CySRModem) { /* modem interrupt */ - - /* determine the channel & change to that context */ - spin_lock(&cinfo->card_lock); - save_xir = (u_char) cy_readb(base_addr+(CyMIR<first_line]; - info->last_active = jiffies; - save_car = cy_readb(base_addr+(CyCAR<tty == 0){/* no place for data, ignore it*/ - ; - }else{ + } else { + if (char_count > 1) { + info->xmit_cnt--; + info->xmit_tail = (info->xmit_tail + 1)& + (SERIAL_XMIT_SIZE - 1); + cy_writeb(base_addr + (CyTDR << index), + outch); + cy_writeb(base_addr + (CyTDR << index), + 0); + info->icount.tx++; + char_count--; + } else { + } + } + } + +txdone: + if (info->xmit_cnt < WAKEUP_CHARS) { + cy_sched_event(info, Cy_EVENT_WRITE_WAKEUP); + } +txend: + /* end of service */ + cy_writeb(base_addr + (CyTIR << index), (save_xir & 0x3f)); + cy_writeb(base_addr + (CyCAR << index), (save_car)); + spin_unlock(&cinfo->card_lock); + } + + if (status & CySRModem) { /* modem interrupt */ + + /* determine the channel & change to that context */ + spin_lock(&cinfo->card_lock); + save_xir = (u_char) cy_readb(base_addr + (CyMIR << index)); + channel = (u_short) (save_xir & CyIRChannel); + info = &cy_port[channel + chip * 4 + cinfo->first_line]; + info->last_active = jiffies; + save_car = cy_readb(base_addr + (CyCAR << index)); + cy_writeb(base_addr + (CyCAR << index), save_xir); + + mdm_change = cy_readb(base_addr + (CyMISR << index)); + mdm_status = cy_readb(base_addr + (CyMSVR1 << index)); + + if (info->tty == 0) { /* no place for data, ignore it */ + ; + } else { if (mdm_change & CyANY_DELTA) { - /* For statistics only */ - if (mdm_change & CyDCD) info->icount.dcd++; - if (mdm_change & CyCTS) info->icount.cts++; - if (mdm_change & CyDSR) info->icount.dsr++; - if (mdm_change & CyRI) info->icount.rng++; + /* For statistics only */ + if (mdm_change & CyDCD) + info->icount.dcd++; + if (mdm_change & CyCTS) + info->icount.cts++; + if (mdm_change & CyDSR) + info->icount.dsr++; + if (mdm_change & CyRI) + info->icount.rng++; + + cy_sched_event(info, Cy_EVENT_DELTA_WAKEUP); + } + + if ((mdm_change & CyDCD) && + (info->flags & ASYNC_CHECK_CD)) { + if (mdm_status & CyDCD) { + cy_sched_event(info, + Cy_EVENT_OPEN_WAKEUP); + } else { + cy_sched_event(info, Cy_EVENT_HANGUP); + } + } + if ((mdm_change & CyCTS) && + (info->flags & ASYNC_CTS_FLOW)) { + if (info->tty->hw_stopped) { + if (mdm_status & CyCTS) { + /* cy_start isn't used + because... !!! */ + info->tty->hw_stopped = 0; + cy_writeb(base_addr + + (CySRER << index), + cy_readb(base_addr + + (CySRER << + index))| + CyTxRdy); + cy_sched_event(info, + Cy_EVENT_WRITE_WAKEUP); + } + } else { + if (!(mdm_status & CyCTS)) { + /* cy_stop isn't used + because ... !!! */ + info->tty->hw_stopped = 1; + cy_writeb(base_addr + + (CySRER << index), + cy_readb(base_addr + + (CySRER << + index)) & + ~CyTxRdy); + } + } + } + if (mdm_change & CyDSR) { + } + if (mdm_change & CyRI) { + } + } + /* end of service */ + cy_writeb(base_addr + (CyMIR << index), (save_xir & 0x3f)); + cy_writeb(base_addr + (CyCAR << index), save_car); + spin_unlock(&cinfo->card_lock); + } +} - cy_sched_event(info, Cy_EVENT_DELTA_WAKEUP); +/* The real interrupt service routine is called + whenever the card wants its hand held--chars + received, out buffer empty, modem change, etc. + */ +static irqreturn_t cyy_interrupt(int irq, void *dev_id) +{ + int status; + struct cyclades_card *cinfo; + void __iomem *base_addr, *card_base_addr; + int chip; + int index; + int too_many; + int had_work; + + if ((cinfo = (struct cyclades_card *)dev_id) == 0) { +#ifdef CY_DEBUG_INTERRUPTS + printk("cyy_interrupt: spurious interrupt %d\n\r", irq); +#endif + return IRQ_NONE; /* spurious interrupt */ + } + + card_base_addr = cinfo->base_addr; + index = cinfo->bus_index; + + /* This loop checks all chips in the card. Make a note whenever + _any_ chip had some work to do, as this is considered an + indication that there will be more to do. Only when no chip + has any work does this outermost loop exit. + */ + do { + had_work = 0; + for (chip = 0; chip < cinfo->num_chips; chip++) { + base_addr = cinfo->base_addr + + (cy_chip_offset[chip] << index); + too_many = 0; + while ((status = cy_readb(base_addr + + (CySVRR << index))) != 0x00) { + had_work++; + /* The purpose of the following test is to ensure that + no chip can monopolize the driver. This forces the + chips to be checked in a round-robin fashion (after + draining each of a bunch (1000) of characters). + */ + if (1000 < too_many++) { + break; + } + cyy_intr_chip(cinfo, chip, base_addr, status, + index); } + } + } while (had_work); - if((mdm_change & CyDCD) - && (info->flags & ASYNC_CHECK_CD)){ - if(mdm_status & CyDCD){ - cy_sched_event(info, - Cy_EVENT_OPEN_WAKEUP); - }else{ - cy_sched_event(info, - Cy_EVENT_HANGUP); - } - } - if((mdm_change & CyCTS) - && (info->flags & ASYNC_CTS_FLOW)){ - if(info->tty->hw_stopped){ - if(mdm_status & CyCTS){ - /* cy_start isn't used - because... !!! */ - info->tty->hw_stopped = 0; - cy_writeb(base_addr+(CySRER<tty->hw_stopped = 1; - cy_writeb(base_addr+(CySRER<card_lock); - } - } /* end while status != 0 */ - } /* end loop for chips... */ - } while(had_work); - - /* clear interrupts */ - spin_lock(&cinfo->card_lock); - cy_writeb(card_base_addr + (Cy_ClrIntr<card_lock); - return IRQ_HANDLED; -} /* cyy_interrupt */ + /* clear interrupts */ + spin_lock(&cinfo->card_lock); + cy_writeb(card_base_addr + (Cy_ClrIntr << index), 0); + /* Cy_ClrIntr is 0x1800 */ + spin_unlock(&cinfo->card_lock); + return IRQ_HANDLED; +} /* cyy_interrupt */ /***********************************************************/ /********* End of block of Cyclom-Y specific code **********/ @@ -1447,643 +1496,655 @@ cyy_interrupt(int irq, void *dev_id) /***********************************************************/ static int -cyz_fetch_msg( struct cyclades_card *cinfo, - uclong *channel, ucchar *cmd, uclong *param) +cyz_fetch_msg(struct cyclades_card *cinfo, + uclong * channel, ucchar * cmd, uclong * param) { - struct FIRM_ID __iomem *firm_id; - struct ZFW_CTRL __iomem *zfw_ctrl; - struct BOARD_CTRL __iomem *board_ctrl; - unsigned long loc_doorbell; - - firm_id = cinfo->base_addr + ID_ADDRESS; - if (!ISZLOADED(*cinfo)){ - return (-1); - } - zfw_ctrl = cinfo->base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff); - board_ctrl = &zfw_ctrl->board_ctrl; - - loc_doorbell = cy_readl(&((struct RUNTIME_9060 __iomem *) - (cinfo->ctl_addr))->loc_doorbell); - if (loc_doorbell){ - *cmd = (char)(0xff & loc_doorbell); - *channel = cy_readl(&board_ctrl->fwcmd_channel); - *param = (uclong)cy_readl(&board_ctrl->fwcmd_param); - cy_writel(&((struct RUNTIME_9060 __iomem *)(cinfo->ctl_addr))->loc_doorbell, - 0xffffffff); - return 1; - } - return 0; -} /* cyz_fetch_msg */ + struct FIRM_ID __iomem *firm_id; + struct ZFW_CTRL __iomem *zfw_ctrl; + struct BOARD_CTRL __iomem *board_ctrl; + unsigned long loc_doorbell; + + firm_id = cinfo->base_addr + ID_ADDRESS; + if (!ISZLOADED(*cinfo)) { + return -1; + } + zfw_ctrl = cinfo->base_addr + (cy_readl(&firm_id->zfwctrl_addr) & + 0xfffff); + board_ctrl = &zfw_ctrl->board_ctrl; + + loc_doorbell = cy_readl(&((struct RUNTIME_9060 __iomem *) + (cinfo->ctl_addr))->loc_doorbell); + if (loc_doorbell) { + *cmd = (char)(0xff & loc_doorbell); + *channel = cy_readl(&board_ctrl->fwcmd_channel); + *param = (uclong) cy_readl(&board_ctrl->fwcmd_param); + cy_writel(&((struct RUNTIME_9060 __iomem *)(cinfo->ctl_addr))-> + loc_doorbell, 0xffffffff); + return 1; + } + return 0; +} /* cyz_fetch_msg */ static int -cyz_issue_cmd( struct cyclades_card *cinfo, - uclong channel, ucchar cmd, uclong param) +cyz_issue_cmd(struct cyclades_card *cinfo, + uclong channel, ucchar cmd, uclong param) { - struct FIRM_ID __iomem *firm_id; - struct ZFW_CTRL __iomem *zfw_ctrl; - struct BOARD_CTRL __iomem *board_ctrl; - unsigned long __iomem *pci_doorbell; - int index; - - firm_id = cinfo->base_addr + ID_ADDRESS; - if (!ISZLOADED(*cinfo)){ - return (-1); - } - zfw_ctrl = cinfo->base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff); - board_ctrl = &zfw_ctrl->board_ctrl; - - index = 0; - pci_doorbell = &((struct RUNTIME_9060 __iomem *) (cinfo->ctl_addr))->pci_doorbell; - while( (cy_readl(pci_doorbell) & 0xff) != 0){ - if (index++ == 1000){ - return((int)(cy_readl(pci_doorbell) & 0xff)); - } - udelay(50L); - } - cy_writel(&board_ctrl->hcmd_channel, channel); - cy_writel(&board_ctrl->hcmd_param , param); - cy_writel(pci_doorbell, (long)cmd); - - return(0); -} /* cyz_issue_cmd */ + struct FIRM_ID __iomem *firm_id; + struct ZFW_CTRL __iomem *zfw_ctrl; + struct BOARD_CTRL __iomem *board_ctrl; + unsigned long __iomem *pci_doorbell; + int index; + + firm_id = cinfo->base_addr + ID_ADDRESS; + if (!ISZLOADED(*cinfo)) { + return -1; + } + zfw_ctrl = cinfo->base_addr + (cy_readl(&firm_id->zfwctrl_addr) & + 0xfffff); + board_ctrl = &zfw_ctrl->board_ctrl; + + index = 0; + pci_doorbell = + &((struct RUNTIME_9060 __iomem *)(cinfo->ctl_addr))->pci_doorbell; + while ((cy_readl(pci_doorbell) & 0xff) != 0) { + if (index++ == 1000) { + return (int)(cy_readl(pci_doorbell) & 0xff); + } + udelay(50L); + } + cy_writel(&board_ctrl->hcmd_channel, channel); + cy_writel(&board_ctrl->hcmd_param, param); + cy_writel(pci_doorbell, (long)cmd); + + return 0; +} /* cyz_issue_cmd */ static void cyz_handle_rx(struct cyclades_port *info, - volatile struct CH_CTRL __iomem *ch_ctrl, - volatile struct BUF_CTRL __iomem *buf_ctrl) + volatile struct CH_CTRL __iomem * ch_ctrl, + volatile struct BUF_CTRL __iomem * buf_ctrl) { - struct cyclades_card *cinfo = &cy_card[info->card]; - struct tty_struct *tty = info->tty; - volatile int char_count; - int len; + struct cyclades_card *cinfo = &cy_card[info->card]; + struct tty_struct *tty = info->tty; + volatile int char_count; + int len; #ifdef BLOCKMOVE - int small_count; + int small_count; #else - char data; + char data; #endif - volatile uclong rx_put, rx_get, new_rx_get, rx_bufsize, rx_bufaddr; + volatile uclong rx_put, rx_get, new_rx_get, rx_bufsize, rx_bufaddr; - rx_get = new_rx_get = cy_readl(&buf_ctrl->rx_get); - rx_put = cy_readl(&buf_ctrl->rx_put); - rx_bufsize = cy_readl(&buf_ctrl->rx_bufsize); - rx_bufaddr = cy_readl(&buf_ctrl->rx_bufaddr); - if (rx_put >= rx_get) - char_count = rx_put - rx_get; - else - char_count = rx_put - rx_get + rx_bufsize; + rx_get = new_rx_get = cy_readl(&buf_ctrl->rx_get); + rx_put = cy_readl(&buf_ctrl->rx_put); + rx_bufsize = cy_readl(&buf_ctrl->rx_bufsize); + rx_bufaddr = cy_readl(&buf_ctrl->rx_bufaddr); + if (rx_put >= rx_get) + char_count = rx_put - rx_get; + else + char_count = rx_put - rx_get + rx_bufsize; - if ( char_count ) { - info->last_active = jiffies; - info->jiffies[1] = jiffies; + if (char_count) { + info->last_active = jiffies; + info->jiffies[1] = jiffies; #ifdef CY_ENABLE_MONITORING - info->mon.int_count++; - info->mon.char_count += char_count; - if (char_count > info->mon.char_max) - info->mon.char_max = char_count; - info->mon.char_last = char_count; + info->mon.int_count++; + info->mon.char_count += char_count; + if (char_count > info->mon.char_max) + info->mon.char_max = char_count; + info->mon.char_last = char_count; #endif - if(tty == 0){ - /* flush received characters */ - new_rx_get = (new_rx_get + char_count) & (rx_bufsize - 1); - info->rflush_count++; - }else{ + if (tty == 0) { + /* flush received characters */ + new_rx_get = (new_rx_get + char_count) & + (rx_bufsize - 1); + info->rflush_count++; + } else { #ifdef BLOCKMOVE - /* we'd like to use memcpy(t, f, n) and memset(s, c, count) - for performance, but because of buffer boundaries, there - may be several steps to the operation */ - while(0 < (small_count = - min_t(unsigned int, (rx_bufsize - new_rx_get), - min_t(unsigned int, (TTY_FLIPBUF_SIZE - tty->flip.count), char_count)) - )) { - memcpy_fromio(tty->flip.char_buf_ptr, - (char *)(cinfo->base_addr - + rx_bufaddr + new_rx_get), - small_count); - - tty->flip.char_buf_ptr += small_count; - memset(tty->flip.flag_buf_ptr, TTY_NORMAL, small_count); - tty->flip.flag_buf_ptr += small_count; - new_rx_get = (new_rx_get + small_count) & (rx_bufsize - 1); - char_count -= small_count; - info->icount.rx += small_count; - info->idle_stats.recv_bytes += small_count; - tty->flip.count += small_count; - } + /* we'd like to use memcpy(t, f, n) and memset(s, c, count) + for performance, but because of buffer boundaries, there + may be several steps to the operation */ + while (0 < (small_count = min_t(unsigned int, + rx_bufsize - new_rx_get, + min_t(unsigned int, TTY_FLIPBUF_SIZE - + tty->flip.count, char_count)))){ + memcpy_fromio(tty->flip.char_buf_ptr, + (char *)(cinfo->base_addr + rx_bufaddr + + new_rx_get), + small_count); + + tty->flip.char_buf_ptr += small_count; + memset(tty->flip.flag_buf_ptr, TTY_NORMAL, + small_count); + tty->flip.flag_buf_ptr += small_count; + new_rx_get = (new_rx_get + small_count) & + (rx_bufsize - 1); + char_count -= small_count; + info->icount.rx += small_count; + info->idle_stats.recv_bytes += small_count; + tty->flip.count += small_count; + } #else - len = tty_buffer_request_room(tty, char_count); - while(len--){ - data = cy_readb(cinfo->base_addr + rx_bufaddr + new_rx_get); - new_rx_get = (new_rx_get + 1) & (rx_bufsize - 1); - tty_insert_flip_char(tty, data, TTY_NORMAL); - info->idle_stats.recv_bytes++; - info->icount.rx++; - } + len = tty_buffer_request_room(tty, char_count); + while (len--) { + data = cy_readb(cinfo->base_addr + rx_bufaddr + + new_rx_get); + new_rx_get = (new_rx_get + 1)& (rx_bufsize - 1); + tty_insert_flip_char(tty, data, TTY_NORMAL); + info->idle_stats.recv_bytes++; + info->icount.rx++; + } #endif #ifdef CONFIG_CYZ_INTR - /* Recalculate the number of chars in the RX buffer and issue - a cmd in case it's higher than the RX high water mark */ - rx_put = cy_readl(&buf_ctrl->rx_put); - if (rx_put >= rx_get) - char_count = rx_put - rx_get; - else - char_count = rx_put - rx_get + rx_bufsize; - if(char_count >= cy_readl(&buf_ctrl->rx_threshold)) { - cy_sched_event(info, Cy_EVENT_Z_RX_FULL); - } + /* Recalculate the number of chars in the RX buffer and issue + a cmd in case it's higher than the RX high water mark */ + rx_put = cy_readl(&buf_ctrl->rx_put); + if (rx_put >= rx_get) + char_count = rx_put - rx_get; + else + char_count = rx_put - rx_get + rx_bufsize; + if (char_count >= (int)cy_readl(&buf_ctrl-> + rx_threshold)) { + cy_sched_event(info, Cy_EVENT_Z_RX_FULL); + } #endif - info->idle_stats.recv_idle = jiffies; - tty_schedule_flip(tty); + info->idle_stats.recv_idle = jiffies; + tty_schedule_flip(tty); + } + /* Update rx_get */ + cy_writel(&buf_ctrl->rx_get, new_rx_get); } - /* Update rx_get */ - cy_writel(&buf_ctrl->rx_get, new_rx_get); - } } static void cyz_handle_tx(struct cyclades_port *info, - volatile struct CH_CTRL __iomem *ch_ctrl, - volatile struct BUF_CTRL __iomem *buf_ctrl) + volatile struct CH_CTRL __iomem * ch_ctrl, + volatile struct BUF_CTRL __iomem * buf_ctrl) { - struct cyclades_card *cinfo = &cy_card[info->card]; - struct tty_struct *tty = info->tty; - char data; - volatile int char_count; + struct cyclades_card *cinfo = &cy_card[info->card]; + struct tty_struct *tty = info->tty; + char data; + volatile int char_count; #ifdef BLOCKMOVE - int small_count; + int small_count; #endif - volatile uclong tx_put, tx_get, tx_bufsize, tx_bufaddr; + volatile uclong tx_put, tx_get, tx_bufsize, tx_bufaddr; - if (info->xmit_cnt <= 0) /* Nothing to transmit */ - return; + if (info->xmit_cnt <= 0) /* Nothing to transmit */ + return; - tx_get = cy_readl(&buf_ctrl->tx_get); - tx_put = cy_readl(&buf_ctrl->tx_put); - tx_bufsize = cy_readl(&buf_ctrl->tx_bufsize); - tx_bufaddr = cy_readl(&buf_ctrl->tx_bufaddr); - if (tx_put >= tx_get) - char_count = tx_get - tx_put - 1 + tx_bufsize; - else - char_count = tx_get - tx_put - 1; + tx_get = cy_readl(&buf_ctrl->tx_get); + tx_put = cy_readl(&buf_ctrl->tx_put); + tx_bufsize = cy_readl(&buf_ctrl->tx_bufsize); + tx_bufaddr = cy_readl(&buf_ctrl->tx_bufaddr); + if (tx_put >= tx_get) + char_count = tx_get - tx_put - 1 + tx_bufsize; + else + char_count = tx_get - tx_put - 1; - if ( char_count ) { + if (char_count) { - if( tty == 0 ){ - goto ztxdone; - } + if (tty == 0) { + goto ztxdone; + } - if(info->x_char) { /* send special char */ - data = info->x_char; + if (info->x_char) { /* send special char */ + data = info->x_char; - cy_writeb((cinfo->base_addr + tx_bufaddr + tx_put), data); - tx_put = (tx_put + 1) & (tx_bufsize - 1); - info->x_char = 0; - char_count--; - info->icount.tx++; - info->last_active = jiffies; - info->jiffies[2] = jiffies; - } + cy_writeb(cinfo->base_addr + tx_bufaddr + tx_put, data); + tx_put = (tx_put + 1) & (tx_bufsize - 1); + info->x_char = 0; + char_count--; + info->icount.tx++; + info->last_active = jiffies; + info->jiffies[2] = jiffies; + } #ifdef BLOCKMOVE - while(0 < (small_count = - min_t(unsigned int, (tx_bufsize - tx_put), - min_t(unsigned int, (SERIAL_XMIT_SIZE - info->xmit_tail), - min_t(unsigned int, info->xmit_cnt, char_count))))) { - - memcpy_toio((char *)(cinfo->base_addr + tx_bufaddr + tx_put), - &info->xmit_buf[info->xmit_tail], - small_count); - - tx_put = (tx_put + small_count) & (tx_bufsize - 1); - char_count -= small_count; - info->icount.tx += small_count; - info->xmit_cnt -= small_count; - info->xmit_tail = - (info->xmit_tail + small_count) & (SERIAL_XMIT_SIZE - 1); - info->last_active = jiffies; - info->jiffies[2] = jiffies; - } + while (0 < (small_count = min_t(unsigned int, + tx_bufsize - tx_put, min_t(unsigned int, + (SERIAL_XMIT_SIZE - info->xmit_tail), + min_t(unsigned int, info->xmit_cnt, + char_count))))) { + + memcpy_toio((char *)(cinfo->base_addr + tx_bufaddr + + tx_put), + &info->xmit_buf[info->xmit_tail], + small_count); + + tx_put = (tx_put + small_count) & (tx_bufsize - 1); + char_count -= small_count; + info->icount.tx += small_count; + info->xmit_cnt -= small_count; + info->xmit_tail = (info->xmit_tail + small_count) & + (SERIAL_XMIT_SIZE - 1); + info->last_active = jiffies; + info->jiffies[2] = jiffies; + } #else - while (info->xmit_cnt && char_count){ - data = info->xmit_buf[info->xmit_tail]; - info->xmit_cnt--; - info->xmit_tail = (info->xmit_tail + 1) & (SERIAL_XMIT_SIZE - 1); - - cy_writeb(cinfo->base_addr + tx_bufaddr + tx_put, data); - tx_put = (tx_put + 1) & (tx_bufsize - 1); - char_count--; - info->icount.tx++; - info->last_active = jiffies; - info->jiffies[2] = jiffies; - } + while (info->xmit_cnt && char_count) { + data = info->xmit_buf[info->xmit_tail]; + info->xmit_cnt--; + info->xmit_tail = (info->xmit_tail + 1) & + (SERIAL_XMIT_SIZE - 1); + + cy_writeb(cinfo->base_addr + tx_bufaddr + tx_put, data); + tx_put = (tx_put + 1) & (tx_bufsize - 1); + char_count--; + info->icount.tx++; + info->last_active = jiffies; + info->jiffies[2] = jiffies; + } #endif - ztxdone: - if (info->xmit_cnt < WAKEUP_CHARS) { - cy_sched_event(info, Cy_EVENT_WRITE_WAKEUP); +ztxdone: + if (info->xmit_cnt < WAKEUP_CHARS) { + cy_sched_event(info, Cy_EVENT_WRITE_WAKEUP); + } + /* Update tx_put */ + cy_writel(&buf_ctrl->tx_put, tx_put); } - /* Update tx_put */ - cy_writel(&buf_ctrl->tx_put, tx_put); - } } -static void -cyz_handle_cmd(struct cyclades_card *cinfo) +static void cyz_handle_cmd(struct cyclades_card *cinfo) { - struct tty_struct *tty; - struct cyclades_port *info; - static volatile struct FIRM_ID __iomem *firm_id; - static volatile struct ZFW_CTRL __iomem *zfw_ctrl; - static volatile struct BOARD_CTRL __iomem *board_ctrl; - static volatile struct CH_CTRL __iomem *ch_ctrl; - static volatile struct BUF_CTRL __iomem *buf_ctrl; - uclong channel; - ucchar cmd; - uclong param; - uclong hw_ver, fw_ver; - int special_count; - int delta_count; - - firm_id = cinfo->base_addr + ID_ADDRESS; - zfw_ctrl = cinfo->base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff); - board_ctrl = &zfw_ctrl->board_ctrl; - fw_ver = cy_readl(&board_ctrl->fw_version); - hw_ver = cy_readl(&((struct RUNTIME_9060 __iomem *)(cinfo->ctl_addr))->mail_box_0); - - - while(cyz_fetch_msg(cinfo, &channel, &cmd, ¶m) == 1) { - special_count = 0; - delta_count = 0; - info = &cy_port[channel + cinfo->first_line]; - if((tty = info->tty) == 0) { - continue; - } - ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]); - buf_ctrl = &(zfw_ctrl->buf_ctrl[channel]); - - switch(cmd) { - case C_CM_PR_ERROR: - tty_insert_flip_char(tty, 0, TTY_PARITY); - info->icount.rx++; - special_count++; - break; - case C_CM_FR_ERROR: - tty_insert_flip_char(tty, 0, TTY_FRAME); - info->icount.rx++; - special_count++; - break; - case C_CM_RXBRK: - tty_insert_flip_char(tty, 0, TTY_BREAK); - info->icount.rx++; - special_count++; - break; - case C_CM_MDCD: - info->icount.dcd++; - delta_count++; - if (info->flags & ASYNC_CHECK_CD){ - if ((fw_ver > 241 ? - ((u_long)param) : - cy_readl(&ch_ctrl->rs_status)) & C_RS_DCD) { - cy_sched_event(info, Cy_EVENT_OPEN_WAKEUP); - }else{ - cy_sched_event(info, Cy_EVENT_HANGUP); - } + struct tty_struct *tty; + struct cyclades_port *info; + static volatile struct FIRM_ID __iomem *firm_id; + static volatile struct ZFW_CTRL __iomem *zfw_ctrl; + static volatile struct BOARD_CTRL __iomem *board_ctrl; + static volatile struct CH_CTRL __iomem *ch_ctrl; + static volatile struct BUF_CTRL __iomem *buf_ctrl; + uclong channel; + ucchar cmd; + uclong param; + uclong hw_ver, fw_ver; + int special_count; + int delta_count; + + firm_id = cinfo->base_addr + ID_ADDRESS; + zfw_ctrl = cinfo->base_addr + (cy_readl(&firm_id->zfwctrl_addr) & + 0xfffff); + board_ctrl = &zfw_ctrl->board_ctrl; + fw_ver = cy_readl(&board_ctrl->fw_version); + hw_ver = cy_readl(&((struct RUNTIME_9060 __iomem *)(cinfo->ctl_addr))-> + mail_box_0); + + while (cyz_fetch_msg(cinfo, &channel, &cmd, ¶m) == 1) { + special_count = 0; + delta_count = 0; + info = &cy_port[channel + cinfo->first_line]; + if ((tty = info->tty) == 0) { + continue; } - break; - case C_CM_MCTS: - info->icount.cts++; - delta_count++; - break; - case C_CM_MRI: - info->icount.rng++; - delta_count++; - break; - case C_CM_MDSR: - info->icount.dsr++; - delta_count++; - break; + ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]); + buf_ctrl = &(zfw_ctrl->buf_ctrl[channel]); + + switch (cmd) { + case C_CM_PR_ERROR: + tty_insert_flip_char(tty, 0, TTY_PARITY); + info->icount.rx++; + special_count++; + break; + case C_CM_FR_ERROR: + tty_insert_flip_char(tty, 0, TTY_FRAME); + info->icount.rx++; + special_count++; + break; + case C_CM_RXBRK: + tty_insert_flip_char(tty, 0, TTY_BREAK); + info->icount.rx++; + special_count++; + break; + case C_CM_MDCD: + info->icount.dcd++; + delta_count++; + if (info->flags & ASYNC_CHECK_CD) { + if ((fw_ver > 241 ? ((u_long) param) : + cy_readl(&ch_ctrl->rs_status)) & + C_RS_DCD) { + cy_sched_event(info, + Cy_EVENT_OPEN_WAKEUP); + } else { + cy_sched_event(info, Cy_EVENT_HANGUP); + } + } + break; + case C_CM_MCTS: + info->icount.cts++; + delta_count++; + break; + case C_CM_MRI: + info->icount.rng++; + delta_count++; + break; + case C_CM_MDSR: + info->icount.dsr++; + delta_count++; + break; #ifdef Z_WAKE - case C_CM_IOCTLW: - cy_sched_event(info, Cy_EVENT_SHUTDOWN_WAKEUP); - break; + case C_CM_IOCTLW: + cy_sched_event(info, Cy_EVENT_SHUTDOWN_WAKEUP); + break; #endif #ifdef CONFIG_CYZ_INTR - case C_CM_RXHIWM: - case C_CM_RXNNDT: - case C_CM_INTBACK2: - /* Reception Interrupt */ + case C_CM_RXHIWM: + case C_CM_RXNNDT: + case C_CM_INTBACK2: + /* Reception Interrupt */ #ifdef CY_DEBUG_INTERRUPTS - printk("cyz_interrupt: rcvd intr, card %d, port %ld\n\r", - info->card, channel); + printk("cyz_interrupt: rcvd intr, card %d, " + "port %ld\n\r", info->card, channel); #endif - cyz_handle_rx(info, ch_ctrl, buf_ctrl); - break; - case C_CM_TXBEMPTY: - case C_CM_TXLOWWM: - case C_CM_INTBACK: - /* Transmission Interrupt */ + cyz_handle_rx(info, ch_ctrl, buf_ctrl); + break; + case C_CM_TXBEMPTY: + case C_CM_TXLOWWM: + case C_CM_INTBACK: + /* Transmission Interrupt */ #ifdef CY_DEBUG_INTERRUPTS - printk("cyz_interrupt: xmit intr, card %d, port %ld\n\r", - info->card, channel); + printk("cyz_interrupt: xmit intr, card %d, " + "port %ld\n\r", info->card, channel); #endif - cyz_handle_tx(info, ch_ctrl, buf_ctrl); - break; -#endif /* CONFIG_CYZ_INTR */ - case C_CM_FATAL: - /* should do something with this !!! */ - break; - default: - break; + cyz_handle_tx(info, ch_ctrl, buf_ctrl); + break; +#endif /* CONFIG_CYZ_INTR */ + case C_CM_FATAL: + /* should do something with this !!! */ + break; + default: + break; + } + if (delta_count) + cy_sched_event(info, Cy_EVENT_DELTA_WAKEUP); + if (special_count) + tty_schedule_flip(tty); } - if(delta_count) - cy_sched_event(info, Cy_EVENT_DELTA_WAKEUP); - if(special_count) - tty_schedule_flip(tty); - } } #ifdef CONFIG_CYZ_INTR -static irqreturn_t -cyz_interrupt(int irq, void *dev_id) +static irqreturn_t cyz_interrupt(int irq, void *dev_id) { - struct cyclades_card *cinfo; + struct cyclades_card *cinfo; - if((cinfo = (struct cyclades_card *)dev_id) == 0){ + if ((cinfo = (struct cyclades_card *)dev_id) == 0) { #ifdef CY_DEBUG_INTERRUPTS - printk("cyz_interrupt: spurious interrupt %d\n\r", irq); + printk("cyz_interrupt: spurious interrupt %d\n\r", irq); #endif - return IRQ_NONE; /* spurious interrupt */ - } + return IRQ_NONE; /* spurious interrupt */ + } - if (!ISZLOADED(*cinfo)) { + if (!ISZLOADED(*cinfo)) { #ifdef CY_DEBUG_INTERRUPTS - printk("cyz_interrupt: board not yet loaded (IRQ%d).\n\r", irq); + printk("cyz_interrupt: board not yet loaded (IRQ%d).\n\r", irq); #endif - return IRQ_NONE; - } + return IRQ_NONE; + } - /* Handle the interrupts */ - cyz_handle_cmd(cinfo); + /* Handle the interrupts */ + cyz_handle_cmd(cinfo); - return IRQ_HANDLED; -} /* cyz_interrupt */ + return IRQ_HANDLED; +} /* cyz_interrupt */ -static void -cyz_rx_restart(unsigned long arg) +static void cyz_rx_restart(unsigned long arg) { - struct cyclades_port *info = (struct cyclades_port *)arg; - int retval; - int card = info->card; - uclong channel = (info->line) - (cy_card[card].first_line); - unsigned long flags; - - CY_LOCK(info, flags); - retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_INTBACK2, 0L); - if (retval != 0){ - printk("cyc:cyz_rx_restart retval on ttyC%d was %x\n", - info->line, retval); - } - cyz_rx_full_timer[info->line].function = NULL; - CY_UNLOCK(info, flags); + struct cyclades_port *info = (struct cyclades_port *)arg; + int retval; + int card = info->card; + uclong channel = (info->line) - (cy_card[card].first_line); + unsigned long flags; + + CY_LOCK(info, flags); + retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_INTBACK2, 0L); + if (retval != 0) { + printk("cyc:cyz_rx_restart retval on ttyC%d was %x\n", + info->line, retval); + } + cyz_rx_full_timer[info->line].function = NULL; + CY_UNLOCK(info, flags); } -#else /* CONFIG_CYZ_INTR */ +#else /* CONFIG_CYZ_INTR */ -static void -cyz_poll(unsigned long arg) +static void cyz_poll(unsigned long arg) { - struct cyclades_card *cinfo; - struct cyclades_port *info; - struct tty_struct *tty; - static volatile struct FIRM_ID *firm_id; - static volatile struct ZFW_CTRL *zfw_ctrl; - static volatile struct BOARD_CTRL *board_ctrl; - static volatile struct CH_CTRL *ch_ctrl; - static volatile struct BUF_CTRL *buf_ctrl; - int card, port; - - cyz_timerlist.expires = jiffies + (HZ); - for (card = 0 ; card < NR_CARDS ; card++){ - cinfo = &cy_card[card]; - - if (!IS_CYC_Z(*cinfo)) continue; - if (!ISZLOADED(*cinfo)) continue; + struct cyclades_card *cinfo; + struct cyclades_port *info; + struct tty_struct *tty; + static volatile struct FIRM_ID *firm_id; + static volatile struct ZFW_CTRL *zfw_ctrl; + static volatile struct BOARD_CTRL *board_ctrl; + static volatile struct CH_CTRL *ch_ctrl; + static volatile struct BUF_CTRL *buf_ctrl; + int card, port; - firm_id = cinfo->base_addr + ID_ADDRESS; - zfw_ctrl = cinfo->base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff); - board_ctrl = &(zfw_ctrl->board_ctrl); + cyz_timerlist.expires = jiffies + (HZ); + for (card = 0; card < NR_CARDS; card++) { + cinfo = &cy_card[card]; + + if (!IS_CYC_Z(*cinfo)) + continue; + if (!ISZLOADED(*cinfo)) + continue; + + firm_id = cinfo->base_addr + ID_ADDRESS; + zfw_ctrl = cinfo->base_addr + + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff); + board_ctrl = &(zfw_ctrl->board_ctrl); /* Skip first polling cycle to avoid racing conditions with the FW */ - if (!cinfo->intr_enabled) { - cinfo->nports = (int) cy_readl(&board_ctrl->n_channel); - cinfo->intr_enabled = 1; - continue; - } + if (!cinfo->intr_enabled) { + cinfo->nports = (int)cy_readl(&board_ctrl->n_channel); + cinfo->intr_enabled = 1; + continue; + } - cyz_handle_cmd(cinfo); + cyz_handle_cmd(cinfo); - for (port = 0 ; port < cinfo->nports ; port++) { - info = &cy_port[ port + cinfo->first_line ]; - tty = info->tty; - ch_ctrl = &(zfw_ctrl->ch_ctrl[port]); - buf_ctrl = &(zfw_ctrl->buf_ctrl[port]); + for (port = 0; port < cinfo->nports; port++) { + info = &cy_port[port + cinfo->first_line]; + tty = info->tty; + ch_ctrl = &(zfw_ctrl->ch_ctrl[port]); + buf_ctrl = &(zfw_ctrl->buf_ctrl[port]); - if (!info->throttle) - cyz_handle_rx(info, ch_ctrl, buf_ctrl); - cyz_handle_tx(info, ch_ctrl, buf_ctrl); + if (!info->throttle) + cyz_handle_rx(info, ch_ctrl, buf_ctrl); + cyz_handle_tx(info, ch_ctrl, buf_ctrl); + } + /* poll every 'cyz_polling_cycle' period */ + cyz_timerlist.expires = jiffies + cyz_polling_cycle; } - /* poll every 'cyz_polling_cycle' period */ - cyz_timerlist.expires = jiffies + cyz_polling_cycle; - } - add_timer(&cyz_timerlist); - - return; -} /* cyz_poll */ + add_timer(&cyz_timerlist); +} /* cyz_poll */ -#endif /* CONFIG_CYZ_INTR */ +#endif /* CONFIG_CYZ_INTR */ /********** End of block of Cyclades-Z specific code *********/ /***********************************************************/ - /* This is called whenever a port becomes active; interrupts are enabled and DTR & RTS are turned on. */ -static int -startup(struct cyclades_port * info) +static int startup(struct cyclades_port *info) { - unsigned long flags; - int retval = 0; - void __iomem *base_addr; - int card,chip,channel,index; - unsigned long page; + unsigned long flags; + int retval = 0; + void __iomem *base_addr; + int card, chip, channel, index; + unsigned long page; - card = info->card; - channel = (info->line) - (cy_card[card].first_line); + card = info->card; + channel = (info->line) - (cy_card[card].first_line); - page = get_zeroed_page(GFP_KERNEL); - if (!page) - return -ENOMEM; + page = get_zeroed_page(GFP_KERNEL); + if (!page) + return -ENOMEM; - CY_LOCK(info, flags); + CY_LOCK(info, flags); - if (info->flags & ASYNC_INITIALIZED){ - free_page(page); - goto errout; - } + if (info->flags & ASYNC_INITIALIZED) { + free_page(page); + goto errout; + } - if (!info->type){ - if (info->tty){ - set_bit(TTY_IO_ERROR, &info->tty->flags); - } - free_page(page); - goto errout; - } + if (!info->type) { + if (info->tty) { + set_bit(TTY_IO_ERROR, &info->tty->flags); + } + free_page(page); + goto errout; + } - if (info->xmit_buf) - free_page(page); - else - info->xmit_buf = (unsigned char *) page; + if (info->xmit_buf) + free_page(page); + else + info->xmit_buf = (unsigned char *)page; - CY_UNLOCK(info, flags); + CY_UNLOCK(info, flags); - set_line_char(info); + set_line_char(info); - if (!IS_CYC_Z(cy_card[card])) { - chip = channel>>2; - channel &= 0x03; - index = cy_card[card].bus_index; - base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<> 2; + channel &= 0x03; + index = cy_card[card].bus_index; + base_addr = cy_card[card].base_addr + + (cy_chip_offset[chip] << index); #ifdef CY_DEBUG_OPEN - printk("cyc startup card %d, chip %d, channel %d, base_addr %lx\n", - card, chip, channel, (long)base_addr);/**/ + printk("cyc startup card %d, chip %d, channel %d, " + "base_addr %lx\n", + card, chip, channel, (long)base_addr); + /**/ #endif + CY_LOCK(info, flags); - CY_LOCK(info, flags); - - cy_writeb(base_addr+(CyCAR<default_timeout - ? info->default_timeout : 0x02)); /* 10ms rx timeout */ + cy_writeb(base_addr + (CyRTPR << index), + (info->default_timeout ? info->default_timeout : 0x02)); + /* 10ms rx timeout */ - cyy_issue_cmd(base_addr,CyCHAN_CTL|CyENB_RCVR|CyENB_XMTR,index); + cyy_issue_cmd(base_addr, CyCHAN_CTL | CyENB_RCVR | CyENB_XMTR, + index); - cy_writeb(base_addr+(CyCAR<flags |= ASYNC_INITIALIZED; + cy_writeb(base_addr + (CySRER << index), + cy_readb(base_addr + (CySRER << index)) | CyRxData); + info->flags |= ASYNC_INITIALIZED; - if (info->tty){ - clear_bit(TTY_IO_ERROR, &info->tty->flags); - } - info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; - info->breakon = info->breakoff = 0; - memset((char *)&info->idle_stats, 0, sizeof(info->idle_stats)); - info->idle_stats.in_use = - info->idle_stats.recv_idle = - info->idle_stats.xmit_idle = jiffies; + if (info->tty) { + clear_bit(TTY_IO_ERROR, &info->tty->flags); + } + info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; + info->breakon = info->breakoff = 0; + memset((char *)&info->idle_stats, 0, sizeof(info->idle_stats)); + info->idle_stats.in_use = + info->idle_stats.recv_idle = + info->idle_stats.xmit_idle = jiffies; - CY_UNLOCK(info, flags); + CY_UNLOCK(info, flags); - } else { - struct FIRM_ID __iomem *firm_id; - struct ZFW_CTRL __iomem *zfw_ctrl; - struct BOARD_CTRL __iomem *board_ctrl; - struct CH_CTRL __iomem *ch_ctrl; - int retval; + } else { + struct FIRM_ID __iomem *firm_id; + struct ZFW_CTRL __iomem *zfw_ctrl; + struct BOARD_CTRL __iomem *board_ctrl; + struct CH_CTRL __iomem *ch_ctrl; + int retval; - base_addr = cy_card[card].base_addr; + base_addr = cy_card[card].base_addr; - firm_id = base_addr + ID_ADDRESS; - if (!ISZLOADED(cy_card[card])){ - return -ENODEV; - } + firm_id = base_addr + ID_ADDRESS; + if (!ISZLOADED(cy_card[card])) { + return -ENODEV; + } - zfw_ctrl = cy_card[card].base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff); - board_ctrl = &zfw_ctrl->board_ctrl; - ch_ctrl = zfw_ctrl->ch_ctrl; + zfw_ctrl = cy_card[card].base_addr + + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff); + board_ctrl = &zfw_ctrl->board_ctrl; + ch_ctrl = zfw_ctrl->ch_ctrl; #ifdef CY_DEBUG_OPEN - printk("cyc startup Z card %d, channel %d, base_addr %lx\n", - card, channel, (long)base_addr);/**/ + printk("cyc startup Z card %d, channel %d, base_addr %lx\n", + card, channel, (long)base_addr); + /**/ #endif + CY_LOCK(info, flags); - CY_LOCK(info, flags); - - cy_writel(&ch_ctrl[channel].op_mode, C_CH_ENABLE); + cy_writel(&ch_ctrl[channel].op_mode, C_CH_ENABLE); #ifdef Z_WAKE #ifdef CONFIG_CYZ_INTR - cy_writel(&ch_ctrl[channel].intr_enable, - C_IN_TXBEMPTY|C_IN_TXLOWWM|C_IN_RXHIWM|C_IN_RXNNDT| - C_IN_IOCTLW| - C_IN_MDCD); + cy_writel(&ch_ctrl[channel].intr_enable, + C_IN_TXBEMPTY | C_IN_TXLOWWM | C_IN_RXHIWM | + C_IN_RXNNDT | C_IN_IOCTLW | C_IN_MDCD); #else - cy_writel(&ch_ctrl[channel].intr_enable, - C_IN_IOCTLW| - C_IN_MDCD); -#endif /* CONFIG_CYZ_INTR */ + cy_writel(&ch_ctrl[channel].intr_enable, + C_IN_IOCTLW | C_IN_MDCD); +#endif /* CONFIG_CYZ_INTR */ #else #ifdef CONFIG_CYZ_INTR - cy_writel(&ch_ctrl[channel].intr_enable, - C_IN_TXBEMPTY|C_IN_TXLOWWM|C_IN_RXHIWM|C_IN_RXNNDT| - C_IN_MDCD); + cy_writel(&ch_ctrl[channel].intr_enable, + C_IN_TXBEMPTY | C_IN_TXLOWWM | C_IN_RXHIWM | + C_IN_RXNNDT | C_IN_MDCD); #else - cy_writel(&ch_ctrl[channel].intr_enable, - C_IN_MDCD); -#endif /* CONFIG_CYZ_INTR */ -#endif /* Z_WAKE */ - - retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_IOCTL, 0L); - if (retval != 0){ - printk("cyc:startup(1) retval on ttyC%d was %x\n", - info->line, retval); - } + cy_writel(&ch_ctrl[channel].intr_enable, C_IN_MDCD); +#endif /* CONFIG_CYZ_INTR */ +#endif /* Z_WAKE */ + + retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_IOCTL, 0L); + if (retval != 0) { + printk("cyc:startup(1) retval on ttyC%d was %x\n", + info->line, retval); + } - /* Flush RX buffers before raising DTR and RTS */ - retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_FLUSH_RX, 0L); - if (retval != 0){ - printk("cyc:startup(2) retval on ttyC%d was %x\n", - info->line, retval); - } + /* Flush RX buffers before raising DTR and RTS */ + retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_FLUSH_RX, + 0L); + if (retval != 0) { + printk("cyc:startup(2) retval on ttyC%d was %x\n", + info->line, retval); + } - /* set timeout !!! */ - /* set RTS and DTR !!! */ - cy_writel(&ch_ctrl[channel].rs_control, - cy_readl(&ch_ctrl[channel].rs_control) | C_RS_RTS | C_RS_DTR) ; - retval = cyz_issue_cmd(&cy_card[info->card], - channel, C_CM_IOCTLM, 0L); - if (retval != 0){ - printk("cyc:startup(3) retval on ttyC%d was %x\n", - info->line, retval); - } + /* set timeout !!! */ + /* set RTS and DTR !!! */ + cy_writel(&ch_ctrl[channel].rs_control, + cy_readl(&ch_ctrl[channel].rs_control) | C_RS_RTS | + C_RS_DTR); + retval = cyz_issue_cmd(&cy_card[info->card], channel, + C_CM_IOCTLM, 0L); + if (retval != 0) { + printk("cyc:startup(3) retval on ttyC%d was %x\n", + info->line, retval); + } #ifdef CY_DEBUG_DTR - printk("cyc:startup raising Z DTR\n"); + printk("cyc:startup raising Z DTR\n"); #endif - /* enable send, recv, modem !!! */ + /* enable send, recv, modem !!! */ - info->flags |= ASYNC_INITIALIZED; - if (info->tty){ - clear_bit(TTY_IO_ERROR, &info->tty->flags); - } - info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; - info->breakon = info->breakoff = 0; - memset((char *)&info->idle_stats, 0, sizeof(info->idle_stats)); - info->idle_stats.in_use = - info->idle_stats.recv_idle = - info->idle_stats.xmit_idle = jiffies; + info->flags |= ASYNC_INITIALIZED; + if (info->tty) { + clear_bit(TTY_IO_ERROR, &info->tty->flags); + } + info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; + info->breakon = info->breakoff = 0; + memset((char *)&info->idle_stats, 0, sizeof(info->idle_stats)); + info->idle_stats.in_use = + info->idle_stats.recv_idle = + info->idle_stats.xmit_idle = jiffies; - CY_UNLOCK(info, flags); - } + CY_UNLOCK(info, flags); + } #ifdef CY_DEBUG_OPEN printk(" cyc startup done\n"); @@ -2093,165 +2154,165 @@ startup(struct cyclades_port * info) errout: CY_UNLOCK(info, flags); return retval; -} /* startup */ - +} /* startup */ -static void -start_xmit( struct cyclades_port *info ) +static void start_xmit(struct cyclades_port *info) { - unsigned long flags; - void __iomem *base_addr; - int card,chip,channel,index; - - card = info->card; - channel = (info->line) - (cy_card[card].first_line); - if (!IS_CYC_Z(cy_card[card])) { - chip = channel>>2; - channel &= 0x03; - index = cy_card[card].bus_index; - base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<card; + channel = (info->line) - (cy_card[card].first_line); + if (!IS_CYC_Z(cy_card[card])) { + chip = channel >> 2; + channel &= 0x03; + index = cy_card[card].bus_index; + base_addr = cy_card[card].base_addr + + (cy_chip_offset[chip] << index); - CY_LOCK(info, flags); - retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_INTBACK, 0L); - if (retval != 0){ - printk("cyc:start_xmit retval on ttyC%d was %x\n", - info->line, retval); - } - CY_UNLOCK(info, flags); -#else /* CONFIG_CYZ_INTR */ - /* Don't have to do anything at this time */ -#endif /* CONFIG_CYZ_INTR */ - } -} /* start_xmit */ + CY_LOCK(info, flags); + cy_writeb(base_addr + (CyCAR << index), channel); + cy_writeb(base_addr + (CySRER << index), + cy_readb(base_addr + (CySRER << index)) | CyTxRdy); + CY_UNLOCK(info, flags); + } else { +#ifdef CONFIG_CYZ_INTR + int retval; + + CY_LOCK(info, flags); + retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_INTBACK, + 0L); + if (retval != 0) { + printk("cyc:start_xmit retval on ttyC%d was %x\n", + info->line, retval); + } + CY_UNLOCK(info, flags); +#else /* CONFIG_CYZ_INTR */ + /* Don't have to do anything at this time */ +#endif /* CONFIG_CYZ_INTR */ + } +} /* start_xmit */ /* * This routine shuts down a serial port; interrupts are disabled, * and DTR is dropped if the hangup on close termio flag is on. */ -static void -shutdown(struct cyclades_port * info) +static void shutdown(struct cyclades_port *info) { - unsigned long flags; - void __iomem *base_addr; - int card,chip,channel,index; - - if (!(info->flags & ASYNC_INITIALIZED)){ - return; - } - - card = info->card; - channel = info->line - cy_card[card].first_line; - if (!IS_CYC_Z(cy_card[card])) { - chip = channel>>2; - channel &= 0x03; - index = cy_card[card].bus_index; - base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<flags & ASYNC_INITIALIZED)) { + return; + } + + card = info->card; + channel = info->line - cy_card[card].first_line; + if (!IS_CYC_Z(cy_card[card])) { + chip = channel >> 2; + channel &= 0x03; + index = cy_card[card].bus_index; + base_addr = cy_card[card].base_addr + + (cy_chip_offset[chip] << index); #ifdef CY_DEBUG_OPEN - printk("cyc shutdown Y card %d, chip %d, channel %d, base_addr %lx\n", - card, chip, channel, (long)base_addr); + printk("cyc shutdown Y card %d, chip %d, channel %d, " + "base_addr %lx\n", + card, chip, channel, (long)base_addr); #endif - CY_LOCK(info, flags); + CY_LOCK(info, flags); + + /* Clear delta_msr_wait queue to avoid mem leaks. */ + wake_up_interruptible(&info->delta_msr_wait); - /* Clear delta_msr_wait queue to avoid mem leaks. */ - wake_up_interruptible(&info->delta_msr_wait); - - if (info->xmit_buf){ - unsigned char * temp; - temp = info->xmit_buf; - info->xmit_buf = NULL; - free_page((unsigned long) temp); - } - cy_writeb(base_addr+(CyCAR<tty || (info->tty->termios->c_cflag & HUPCL)) { - cy_writeb(base_addr+(CyMSVR1<xmit_buf) { + unsigned char *temp; + temp = info->xmit_buf; + info->xmit_buf = NULL; + free_page((unsigned long)temp); + } + cy_writeb(base_addr + (CyCAR << index), (u_char) channel); + if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) { + cy_writeb(base_addr + (CyMSVR1 << index), ~CyRTS); + cy_writeb(base_addr + (CyMSVR2 << index), ~CyDTR); #ifdef CY_DEBUG_DTR - printk("cyc shutdown dropping DTR\n"); - printk(" status: 0x%x, 0x%x\n", - cy_readb(base_addr+(CyMSVR1<tty){ - set_bit(TTY_IO_ERROR, &info->tty->flags); - } - info->flags &= ~ASYNC_INITIALIZED; - CY_UNLOCK(info, flags); - } else { - struct FIRM_ID __iomem *firm_id; - struct ZFW_CTRL __iomem *zfw_ctrl; - struct BOARD_CTRL __iomem *board_ctrl; - struct CH_CTRL __iomem *ch_ctrl; - int retval; - - base_addr = cy_card[card].base_addr; + } + cyy_issue_cmd(base_addr, CyCHAN_CTL | CyDIS_RCVR, index); + /* it may be appropriate to clear _XMIT at + some later date (after testing)!!! */ + + if (info->tty) { + set_bit(TTY_IO_ERROR, &info->tty->flags); + } + info->flags &= ~ASYNC_INITIALIZED; + CY_UNLOCK(info, flags); + } else { + struct FIRM_ID __iomem *firm_id; + struct ZFW_CTRL __iomem *zfw_ctrl; + struct BOARD_CTRL __iomem *board_ctrl; + struct CH_CTRL __iomem *ch_ctrl; + int retval; + + base_addr = cy_card[card].base_addr; #ifdef CY_DEBUG_OPEN - printk("cyc shutdown Z card %d, channel %d, base_addr %lx\n", - card, channel, (long)base_addr); + printk("cyc shutdown Z card %d, channel %d, base_addr %lx\n", + card, channel, (long)base_addr); #endif - firm_id = base_addr + ID_ADDRESS; - if (!ISZLOADED(cy_card[card])) { - return; - } + firm_id = base_addr + ID_ADDRESS; + if (!ISZLOADED(cy_card[card])) { + return; + } - zfw_ctrl = cy_card[card].base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff); - board_ctrl = &zfw_ctrl->board_ctrl; - ch_ctrl = zfw_ctrl->ch_ctrl; + zfw_ctrl = cy_card[card].base_addr + + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff); + board_ctrl = &zfw_ctrl->board_ctrl; + ch_ctrl = zfw_ctrl->ch_ctrl; - CY_LOCK(info, flags); + CY_LOCK(info, flags); - if (info->xmit_buf){ - unsigned char * temp; - temp = info->xmit_buf; - info->xmit_buf = NULL; - free_page((unsigned long) temp); - } - - if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) { - cy_writel(&ch_ctrl[channel].rs_control, - (uclong)(cy_readl(&ch_ctrl[channel].rs_control) & - ~(C_RS_RTS | C_RS_DTR))); - retval = cyz_issue_cmd(&cy_card[info->card], - channel, C_CM_IOCTLM, 0L); - if (retval != 0){ - printk("cyc:shutdown retval on ttyC%d was %x\n", - info->line, retval); + if (info->xmit_buf) { + unsigned char *temp; + temp = info->xmit_buf; + info->xmit_buf = NULL; + free_page((unsigned long)temp); } + + if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) { + cy_writel(&ch_ctrl[channel].rs_control, + (uclong)(cy_readl(&ch_ctrl[channel].rs_control)& + ~(C_RS_RTS | C_RS_DTR))); + retval = cyz_issue_cmd(&cy_card[info->card], channel, + C_CM_IOCTLM, 0L); + if (retval != 0) { + printk("cyc:shutdown retval on ttyC%d was %x\n", + info->line, retval); + } #ifdef CY_DEBUG_DTR - printk("cyc:shutdown dropping Z DTR\n"); + printk("cyc:shutdown dropping Z DTR\n"); #endif - } - - if (info->tty){ - set_bit(TTY_IO_ERROR, &info->tty->flags); - } - info->flags &= ~ASYNC_INITIALIZED; + } - CY_UNLOCK(info, flags); - } + if (info->tty) { + set_bit(TTY_IO_ERROR, &info->tty->flags); + } + info->flags &= ~ASYNC_INITIALIZED; + + CY_UNLOCK(info, flags); + } #ifdef CY_DEBUG_OPEN - printk(" cyc shutdown done\n"); + printk(" cyc shutdown done\n"); #endif - return; -} /* shutdown */ - +} /* shutdown */ /* * ------------------------------------------------------------ @@ -2260,527 +2321,546 @@ shutdown(struct cyclades_port * info) */ static int -block_til_ready(struct tty_struct *tty, struct file * filp, - struct cyclades_port *info) +block_til_ready(struct tty_struct *tty, struct file *filp, + struct cyclades_port *info) { - DECLARE_WAITQUEUE(wait, current); - struct cyclades_card *cinfo; - unsigned long flags; - int chip, channel,index; - int retval; - void __iomem *base_addr; - - cinfo = &cy_card[info->card]; - channel = info->line - cinfo->first_line; - - /* - * If the device is in the middle of being closed, then block - * until it's done, and then try again. - */ - if (tty_hung_up_p(filp) || (info->flags & ASYNC_CLOSING)) { - if (info->flags & ASYNC_CLOSING) { - interruptible_sleep_on(&info->close_wait); + DECLARE_WAITQUEUE(wait, current); + struct cyclades_card *cinfo; + unsigned long flags; + int chip, channel, index; + int retval; + void __iomem *base_addr; + + cinfo = &cy_card[info->card]; + channel = info->line - cinfo->first_line; + + /* + * If the device is in the middle of being closed, then block + * until it's done, and then try again. + */ + if (tty_hung_up_p(filp) || (info->flags & ASYNC_CLOSING)) { + if (info->flags & ASYNC_CLOSING) { + interruptible_sleep_on(&info->close_wait); + } + return (info->flags & ASYNC_HUP_NOTIFY) ? -EAGAIN: -ERESTARTSYS; } - return ((info->flags & ASYNC_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS); - } - - /* - * If non-blocking mode is set, then make the check up front - * and then exit. - */ - if ((filp->f_flags & O_NONBLOCK) || - (tty->flags & (1 << TTY_IO_ERROR))) { - info->flags |= ASYNC_NORMAL_ACTIVE; - return 0; - } - - /* - * Block waiting for the carrier detect and the line to become - * free (i.e., not in use by the callout). While we are in - * this loop, info->count is dropped by one, so that - * cy_close() knows when to free things. We restore it upon - * exit, either normal or abnormal. - */ - retval = 0; - add_wait_queue(&info->open_wait, &wait); + + /* + * If non-blocking mode is set, then make the check up front + * and then exit. + */ + if ((filp->f_flags & O_NONBLOCK) || (tty->flags & (1 << TTY_IO_ERROR))) { + info->flags |= ASYNC_NORMAL_ACTIVE; + return 0; + } + + /* + * Block waiting for the carrier detect and the line to become + * free (i.e., not in use by the callout). While we are in + * this loop, info->count is dropped by one, so that + * cy_close() knows when to free things. We restore it upon + * exit, either normal or abnormal. + */ + retval = 0; + add_wait_queue(&info->open_wait, &wait); #ifdef CY_DEBUG_OPEN - printk("cyc block_til_ready before block: ttyC%d, count = %d\n", - info->line, info->count);/**/ + printk("cyc block_til_ready before block: ttyC%d, count = %d\n", + info->line, info->count); + /**/ #endif - CY_LOCK(info, flags); - if (!tty_hung_up_p(filp)) - info->count--; - CY_UNLOCK(info, flags); + CY_LOCK(info, flags); + if (!tty_hung_up_p(filp)) + info->count--; + CY_UNLOCK(info, flags); #ifdef CY_DEBUG_COUNT - printk("cyc block_til_ready: (%d): decrementing count to %d\n", - current->pid, info->count); + printk("cyc block_til_ready: (%d): decrementing count to %d\n", + current->pid, info->count); #endif - info->blocked_open++; - - if (!IS_CYC_Z(*cinfo)) { - chip = channel>>2; - channel &= 0x03; - index = cinfo->bus_index; - base_addr = cinfo->base_addr + (cy_chip_offset[chip]<termios->c_cflag & CBAUD)){ - cy_writeb(base_addr+(CyCAR<blocked_open++; + + if (!IS_CYC_Z(*cinfo)) { + chip = channel >> 2; + channel &= 0x03; + index = cinfo->bus_index; + base_addr = cinfo->base_addr + (cy_chip_offset[chip] << index); + + while (1) { + CY_LOCK(info, flags); + if ((tty->termios->c_cflag & CBAUD)) { + cy_writeb(base_addr + (CyCAR << index), + (u_char) channel); + cy_writeb(base_addr + (CyMSVR1 << index), + CyRTS); + cy_writeb(base_addr + (CyMSVR2 << index), + CyDTR); #ifdef CY_DEBUG_DTR - printk("cyc:block_til_ready raising DTR\n"); - printk(" status: 0x%x, 0x%x\n", - cy_readb(base_addr+(CyMSVR1<flags & ASYNC_INITIALIZED) ){ - retval = ((info->flags & ASYNC_HUP_NOTIFY) ? - -EAGAIN : -ERESTARTSYS); - break; - } + set_current_state(TASK_INTERRUPTIBLE); + if (tty_hung_up_p(filp) || + !(info->flags & ASYNC_INITIALIZED)) { + retval = ((info->flags & ASYNC_HUP_NOTIFY) ? + -EAGAIN : -ERESTARTSYS); + break; + } - CY_LOCK(info, flags); - cy_writeb(base_addr+(CyCAR<flags & ASYNC_CLOSING) - && (C_CLOCAL(tty) - || (cy_readb(base_addr+(CyMSVR1<flags & ASYNC_CLOSING) && (C_CLOCAL(tty) || + (cy_readb(base_addr + + (CyMSVR1 << index)) & CyDCD))) { + CY_UNLOCK(info, flags); + break; + } CY_UNLOCK(info, flags); - break; - } - CY_UNLOCK(info, flags); - if (signal_pending(current)) { - retval = -ERESTARTSYS; - break; - } + if (signal_pending(current)) { + retval = -ERESTARTSYS; + break; + } #ifdef CY_DEBUG_OPEN - printk("cyc block_til_ready blocking: ttyC%d, count = %d\n", - info->line, info->count);/**/ + printk("cyc block_til_ready blocking: ttyC%d, " + "count = %d\n", + info->line, info->count); + /**/ #endif - schedule(); - } - } else { - struct FIRM_ID __iomem *firm_id; - struct ZFW_CTRL __iomem *zfw_ctrl; - struct BOARD_CTRL __iomem *board_ctrl; - struct CH_CTRL __iomem *ch_ctrl; - int retval; - - base_addr = cinfo->base_addr; - firm_id = base_addr + ID_ADDRESS; - if (!ISZLOADED(*cinfo)){ - current->state = TASK_RUNNING; - remove_wait_queue(&info->open_wait, &wait); - return -EINVAL; - } - - zfw_ctrl = base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff); - board_ctrl = &zfw_ctrl->board_ctrl; - ch_ctrl = zfw_ctrl->ch_ctrl; - - while (1) { - if ((tty->termios->c_cflag & CBAUD)){ - cy_writel(&ch_ctrl[channel].rs_control, - cy_readl(&ch_ctrl[channel].rs_control) | - (C_RS_RTS | C_RS_DTR)); - retval = cyz_issue_cmd(&cy_card[info->card], - channel, C_CM_IOCTLM, 0L); - if (retval != 0){ - printk("cyc:block_til_ready retval on ttyC%d was %x\n", - info->line, retval); + schedule(); + } + } else { + struct FIRM_ID __iomem *firm_id; + struct ZFW_CTRL __iomem *zfw_ctrl; + struct BOARD_CTRL __iomem *board_ctrl; + struct CH_CTRL __iomem *ch_ctrl; + int retval; + + base_addr = cinfo->base_addr; + firm_id = base_addr + ID_ADDRESS; + if (!ISZLOADED(*cinfo)) { + current->state = TASK_RUNNING; + remove_wait_queue(&info->open_wait, &wait); + return -EINVAL; } + + zfw_ctrl = base_addr + (cy_readl(&firm_id->zfwctrl_addr) & + 0xfffff); + board_ctrl = &zfw_ctrl->board_ctrl; + ch_ctrl = zfw_ctrl->ch_ctrl; + + while (1) { + if ((tty->termios->c_cflag & CBAUD)) { + cy_writel(&ch_ctrl[channel].rs_control, + cy_readl(&ch_ctrl[channel]. + rs_control) | (C_RS_RTS | + C_RS_DTR)); + retval = cyz_issue_cmd(&cy_card[info->card], + channel, C_CM_IOCTLM, 0L); + if (retval != 0) { + printk("cyc:block_til_ready retval on " + "ttyC%d was %x\n", + info->line, retval); + } #ifdef CY_DEBUG_DTR - printk("cyc:block_til_ready raising Z DTR\n"); + printk("cyc:block_til_ready raising Z DTR\n"); #endif - } + } - set_current_state(TASK_INTERRUPTIBLE); - if (tty_hung_up_p(filp) - || !(info->flags & ASYNC_INITIALIZED) ){ - retval = ((info->flags & ASYNC_HUP_NOTIFY) ? - -EAGAIN : -ERESTARTSYS); - break; - } - if (!(info->flags & ASYNC_CLOSING) - && (C_CLOCAL(tty) - || (cy_readl(&ch_ctrl[channel].rs_status) & C_RS_DCD))) { - break; - } - if (signal_pending(current)) { - retval = -ERESTARTSYS; - break; - } + set_current_state(TASK_INTERRUPTIBLE); + if (tty_hung_up_p(filp) || + !(info->flags & ASYNC_INITIALIZED)) { + retval = ((info->flags & ASYNC_HUP_NOTIFY) ? + -EAGAIN : -ERESTARTSYS); + break; + } + if (!(info->flags & ASYNC_CLOSING) && (C_CLOCAL(tty) || + (cy_readl(&ch_ctrl[channel].rs_status) & + C_RS_DCD))) { + break; + } + if (signal_pending(current)) { + retval = -ERESTARTSYS; + break; + } #ifdef CY_DEBUG_OPEN - printk("cyc block_til_ready blocking: ttyC%d, count = %d\n", - info->line, info->count);/**/ + printk("cyc block_til_ready blocking: ttyC%d, " + "count = %d\n", + info->line, info->count); + /**/ #endif - schedule(); + schedule(); + } } - } - current->state = TASK_RUNNING; - remove_wait_queue(&info->open_wait, &wait); - if (!tty_hung_up_p(filp)){ - info->count++; + current->state = TASK_RUNNING; + remove_wait_queue(&info->open_wait, &wait); + if (!tty_hung_up_p(filp)) { + info->count++; #ifdef CY_DEBUG_COUNT - printk("cyc:block_til_ready (%d): incrementing count to %d\n", - current->pid, info->count); + printk("cyc:block_til_ready (%d): incrementing count to %d\n", + current->pid, info->count); #endif - } - info->blocked_open--; + } + info->blocked_open--; #ifdef CY_DEBUG_OPEN - printk("cyc:block_til_ready after blocking: ttyC%d, count = %d\n", - info->line, info->count);/**/ + printk("cyc:block_til_ready after blocking: ttyC%d, count = %d\n", + info->line, info->count); + /**/ #endif - if (retval) - return retval; - info->flags |= ASYNC_NORMAL_ACTIVE; - return 0; -} /* block_til_ready */ - + if (retval) + return retval; + info->flags |= ASYNC_NORMAL_ACTIVE; + return 0; +} /* block_til_ready */ /* * This routine is called whenever a serial port is opened. It * performs the serial-specific initialization for the tty structure. */ -static int -cy_open(struct tty_struct *tty, struct file * filp) +static int cy_open(struct tty_struct *tty, struct file *filp) { - struct cyclades_port *info; - int retval, line; - - line = tty->index; - if ((line < 0) || (NR_PORTS <= line)){ - return -ENODEV; - } - info = &cy_port[line]; - if (info->line < 0){ - return -ENODEV; - } - - /* If the card's firmware hasn't been loaded, - treat it as absent from the system. This - will make the user pay attention. - */ - if (IS_CYC_Z(cy_card[info->card])) { - struct cyclades_card *cinfo = &cy_card[info->card]; - struct FIRM_ID __iomem *firm_id = cinfo->base_addr + ID_ADDRESS; - - if (!ISZLOADED(*cinfo)) { - if (((ZE_V1 ==cy_readl(&((struct RUNTIME_9060 __iomem *) - (cinfo->ctl_addr))->mail_box_0)) && - Z_FPGA_CHECK (*cinfo)) && - (ZFIRM_HLT == cy_readl (&firm_id->signature))) - { - printk ("cyc:Cyclades-Z Error: you need an external power supply for this number of ports.\n\rFirmware halted.\r\n"); - } else { - printk("cyc:Cyclades-Z firmware not yet loaded\n"); - } - return -ENODEV; - } -#ifdef CONFIG_CYZ_INTR - else { - /* In case this Z board is operating in interrupt mode, its - interrupts should be enabled as soon as the first open happens - to one of its ports. */ - if (!cinfo->intr_enabled) { - struct ZFW_CTRL __iomem *zfw_ctrl; - struct BOARD_CTRL __iomem *board_ctrl; - - zfw_ctrl = cinfo->base_addr + (cy_readl (&firm_id->zfwctrl_addr) & 0xfffff); + struct cyclades_port *info; + int retval, line; - board_ctrl = &zfw_ctrl->board_ctrl; + line = tty->index; + if ((line < 0) || (NR_PORTS <= line)) { + return -ENODEV; + } + info = &cy_port[line]; + if (info->line < 0) { + return -ENODEV; + } - /* Enable interrupts on the PLX chip */ - cy_writew(cinfo->ctl_addr+0x68, - cy_readw(cinfo->ctl_addr+0x68)|0x0900); - /* Enable interrupts on the FW */ - retval = cyz_issue_cmd(cinfo, - 0, C_CM_IRQ_ENBL, 0L); - if (retval != 0){ - printk("cyc:IRQ enable retval was %x\n", retval); + /* If the card's firmware hasn't been loaded, + treat it as absent from the system. This + will make the user pay attention. + */ + if (IS_CYC_Z(cy_card[info->card])) { + struct cyclades_card *cinfo = &cy_card[info->card]; + struct FIRM_ID __iomem *firm_id = cinfo->base_addr + ID_ADDRESS; + + if (!ISZLOADED(*cinfo)) { + if (((ZE_V1 == cy_readl( + &((struct RUNTIME_9060 __iomem *) + (cinfo->ctl_addr))->mail_box_0)) && + Z_FPGA_CHECK(*cinfo)) && + (ZFIRM_HLT == cy_readl( + &firm_id->signature))) { + printk("cyc:Cyclades-Z Error: you need an " + "external power supply for this number " + "of ports.\n\rFirmware halted.\r\n"); + } else { + printk("cyc:Cyclades-Z firmware not yet " + "loaded\n"); + } + return -ENODEV; } - cinfo->nports = (int) cy_readl (&board_ctrl->n_channel); - cinfo->intr_enabled = 1; - } +#ifdef CONFIG_CYZ_INTR + else { + /* In case this Z board is operating in interrupt mode, its + interrupts should be enabled as soon as the first open + happens to one of its ports. */ + if (!cinfo->intr_enabled) { + struct ZFW_CTRL __iomem *zfw_ctrl; + struct BOARD_CTRL __iomem *board_ctrl; + + zfw_ctrl = cinfo->base_addr + + (cy_readl(&firm_id->zfwctrl_addr) & + 0xfffff); + + board_ctrl = &zfw_ctrl->board_ctrl; + + /* Enable interrupts on the PLX chip */ + cy_writew(cinfo->ctl_addr + 0x68, + cy_readw(cinfo->ctl_addr + + 0x68) | 0x0900); + /* Enable interrupts on the FW */ + retval = cyz_issue_cmd(cinfo, 0, + C_CM_IRQ_ENBL, 0L); + if (retval != 0) { + printk("cyc:IRQ enable retval was %x\n", + retval); + } + cinfo->nports = + (int)cy_readl(&board_ctrl->n_channel); + cinfo->intr_enabled = 1; + } + } +#endif /* CONFIG_CYZ_INTR */ + /* Make sure this Z port really exists in hardware */ + if (info->line > (cinfo->first_line + cinfo->nports - 1)) + return -ENODEV; } -#endif /* CONFIG_CYZ_INTR */ - /* Make sure this Z port really exists in hardware */ - if (info->line > (cinfo->first_line + cinfo->nports - 1)) - return -ENODEV; - } #ifdef CY_DEBUG_OTHER - printk("cyc:cy_open ttyC%d\n", info->line); /* */ + printk("cyc:cy_open ttyC%d\n", info->line); /* */ #endif - tty->driver_data = info; - info->tty = tty; - if (serial_paranoia_check(info, tty->name, "cy_open")){ - return -ENODEV; - } + tty->driver_data = info; + info->tty = tty; + if (serial_paranoia_check(info, tty->name, "cy_open")) { + return -ENODEV; + } #ifdef CY_DEBUG_OPEN - printk("cyc:cy_open ttyC%d, count = %d\n", - info->line, info->count);/**/ + printk("cyc:cy_open ttyC%d, count = %d\n", info->line, info->count); + /**/ #endif - info->count++; + info->count++; #ifdef CY_DEBUG_COUNT - printk("cyc:cy_open (%d): incrementing count to %d\n", - current->pid, info->count); + printk("cyc:cy_open (%d): incrementing count to %d\n", + current->pid, info->count); #endif - /* - * If the port is the middle of closing, bail out now - */ - if (tty_hung_up_p(filp) || (info->flags & ASYNC_CLOSING)) { - if (info->flags & ASYNC_CLOSING) - interruptible_sleep_on(&info->close_wait); - return ((info->flags & ASYNC_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS); - } - - /* - * Start up serial port - */ - retval = startup(info); - if (retval){ - return retval; - } - - retval = block_til_ready(tty, filp, info); - if (retval) { -#ifdef CY_DEBUG_OPEN - printk("cyc:cy_open returning after block_til_ready with %d\n", - retval); -#endif - return retval; - } + /* + * If the port is the middle of closing, bail out now + */ + if (tty_hung_up_p(filp) || (info->flags & ASYNC_CLOSING)) { + if (info->flags & ASYNC_CLOSING) + interruptible_sleep_on(&info->close_wait); + return (info->flags & ASYNC_HUP_NOTIFY) ? -EAGAIN: -ERESTARTSYS; + } - info->throttle = 0; + /* + * Start up serial port + */ + retval = startup(info); + if (retval) { + return retval; + } + retval = block_til_ready(tty, filp, info); + if (retval) { #ifdef CY_DEBUG_OPEN - printk(" cyc:cy_open done\n");/**/ + printk("cyc:cy_open returning after block_til_ready with %d\n", + retval); #endif + return retval; + } - return 0; -} /* cy_open */ + info->throttle = 0; +#ifdef CY_DEBUG_OPEN + printk(" cyc:cy_open done\n"); + /**/ +#endif + return 0; +} /* cy_open */ /* * cy_wait_until_sent() --- wait until the transmitter is empty */ -static void -cy_wait_until_sent(struct tty_struct *tty, int timeout) +static void cy_wait_until_sent(struct tty_struct *tty, int timeout) { - struct cyclades_port * info = (struct cyclades_port *)tty->driver_data; - void __iomem *base_addr; - int card,chip,channel,index; - unsigned long orig_jiffies; - int char_time; - - if (serial_paranoia_check(info, tty->name, "cy_wait_until_sent")) - return; - - if (info->xmit_fifo_size == 0) - return; /* Just in case.... */ - - - orig_jiffies = jiffies; - /* - * Set the check interval to be 1/5 of the estimated time to - * send a single character, and make it at least 1. The check - * interval should also be less than the timeout. - * - * Note: we have to use pretty tight timings here to satisfy - * the NIST-PCTS. - */ - char_time = (info->timeout - HZ/50) / info->xmit_fifo_size; - char_time = char_time / 5; - if (char_time <= 0) - char_time = 1; - if (timeout < 0) - timeout = 0; - if (timeout) - char_time = min(char_time, timeout); - /* - * If the transmitter hasn't cleared in twice the approximate - * amount of time to send the entire FIFO, it probably won't - * ever clear. This assumes the UART isn't doing flow - * control, which is currently the case. Hence, if it ever - * takes longer than info->timeout, this is probably due to a - * UART bug of some kind. So, we clamp the timeout parameter at - * 2*info->timeout. - */ - if (!timeout || timeout > 2*info->timeout) - timeout = 2*info->timeout; + struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; + void __iomem *base_addr; + int card, chip, channel, index; + unsigned long orig_jiffies; + int char_time; + + if (serial_paranoia_check(info, tty->name, "cy_wait_until_sent")) + return; + + if (info->xmit_fifo_size == 0) + return; /* Just in case.... */ + + orig_jiffies = jiffies; + /* + * Set the check interval to be 1/5 of the estimated time to + * send a single character, and make it at least 1. The check + * interval should also be less than the timeout. + * + * Note: we have to use pretty tight timings here to satisfy + * the NIST-PCTS. + */ + char_time = (info->timeout - HZ / 50) / info->xmit_fifo_size; + char_time = char_time / 5; + if (char_time <= 0) + char_time = 1; + if (timeout < 0) + timeout = 0; + if (timeout) + char_time = min(char_time, timeout); + /* + * If the transmitter hasn't cleared in twice the approximate + * amount of time to send the entire FIFO, it probably won't + * ever clear. This assumes the UART isn't doing flow + * control, which is currently the case. Hence, if it ever + * takes longer than info->timeout, this is probably due to a + * UART bug of some kind. So, we clamp the timeout parameter at + * 2*info->timeout. + */ + if (!timeout || timeout > 2 * info->timeout) + timeout = 2 * info->timeout; #ifdef CY_DEBUG_WAIT_UNTIL_SENT - printk("In cy_wait_until_sent(%d) check=%lu...", timeout, char_time); - printk("jiff=%lu...", jiffies); + printk("In cy_wait_until_sent(%d) check=%lu...", timeout, char_time); + printk("jiff=%lu...", jiffies); #endif - card = info->card; - channel = (info->line) - (cy_card[card].first_line); - if (!IS_CYC_Z(cy_card[card])) { - chip = channel>>2; - channel &= 0x03; - index = cy_card[card].bus_index; - base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<card; + channel = (info->line) - (cy_card[card].first_line); + if (!IS_CYC_Z(cy_card[card])) { + chip = channel >> 2; + channel &= 0x03; + index = cy_card[card].bus_index; + base_addr = + cy_card[card].base_addr + (cy_chip_offset[chip] << index); + while (cy_readb(base_addr + (CySRER << index)) & CyTxRdy) { #ifdef CY_DEBUG_WAIT_UNTIL_SENT - printk("Not clean (jiff=%lu)...", jiffies); + printk("Not clean (jiff=%lu)...", jiffies); #endif - if (msleep_interruptible(jiffies_to_msecs(char_time))) - break; - if (timeout && time_after(jiffies, orig_jiffies + timeout)) - break; + if (msleep_interruptible(jiffies_to_msecs(char_time))) + break; + if (timeout && time_after(jiffies, orig_jiffies + + timeout)) + break; + } + } else { + /* Nothing to do! */ } - } else { - // Nothing to do! - } - /* Run one more char cycle */ - msleep_interruptible(jiffies_to_msecs(char_time * 5)); + /* Run one more char cycle */ + msleep_interruptible(jiffies_to_msecs(char_time * 5)); #ifdef CY_DEBUG_WAIT_UNTIL_SENT - printk("Clean (jiff=%lu)...done\n", jiffies); + printk("Clean (jiff=%lu)...done\n", jiffies); #endif } /* * This routine is called when a particular tty device is closed. */ -static void -cy_close(struct tty_struct *tty, struct file *filp) +static void cy_close(struct tty_struct *tty, struct file *filp) { - struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; - unsigned long flags; + struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; + unsigned long flags; #ifdef CY_DEBUG_OTHER - printk("cyc:cy_close ttyC%d\n", info->line); + printk("cyc:cy_close ttyC%d\n", info->line); #endif - if (!info || serial_paranoia_check(info, tty->name, "cy_close")){ - return; - } + if (!info || serial_paranoia_check(info, tty->name, "cy_close")) { + return; + } - CY_LOCK(info, flags); - /* If the TTY is being hung up, nothing to do */ - if (tty_hung_up_p(filp)) { - CY_UNLOCK(info, flags); - return; - } - + CY_LOCK(info, flags); + /* If the TTY is being hung up, nothing to do */ + if (tty_hung_up_p(filp)) { + CY_UNLOCK(info, flags); + return; + } #ifdef CY_DEBUG_OPEN - printk("cyc:cy_close ttyC%d, count = %d\n", info->line, info->count); + printk("cyc:cy_close ttyC%d, count = %d\n", info->line, info->count); #endif - if ((tty->count == 1) && (info->count != 1)) { - /* - * Uh, oh. tty->count is 1, which means that the tty - * structure will be freed. Info->count should always - * be one in these conditions. If it's greater than - * one, we've got real problems, since it means the - * serial port won't be shutdown. - */ - printk("cyc:cy_close: bad serial port count; tty->count is 1, " - "info->count is %d\n", info->count); - info->count = 1; - } + if ((tty->count == 1) && (info->count != 1)) { + /* + * Uh, oh. tty->count is 1, which means that the tty + * structure will be freed. Info->count should always + * be one in these conditions. If it's greater than + * one, we've got real problems, since it means the + * serial port won't be shutdown. + */ + printk("cyc:cy_close: bad serial port count; tty->count is 1, " + "info->count is %d\n", info->count); + info->count = 1; + } #ifdef CY_DEBUG_COUNT - printk("cyc:cy_close at (%d): decrementing count to %d\n", - current->pid, info->count - 1); + printk("cyc:cy_close at (%d): decrementing count to %d\n", + current->pid, info->count - 1); #endif - if (--info->count < 0) { + if (--info->count < 0) { #ifdef CY_DEBUG_COUNT - printk("cyc:cyc_close setting count to 0\n"); + printk("cyc:cyc_close setting count to 0\n"); #endif - info->count = 0; - } - if (info->count) { - CY_UNLOCK(info, flags); - return; - } - info->flags |= ASYNC_CLOSING; - - /* - * Now we wait for the transmit buffer to clear; and we notify - * the line discipline to only process XON/XOFF characters. - */ - tty->closing = 1; - CY_UNLOCK(info, flags); - if (info->closing_wait != CY_CLOSING_WAIT_NONE) { - tty_wait_until_sent(tty, info->closing_wait); - } - CY_LOCK(info, flags); - - if (!IS_CYC_Z(cy_card[info->card])) { - int channel = info->line - cy_card[info->card].first_line; - int index = cy_card[info->card].bus_index; - void __iomem *base_addr = cy_card[info->card].base_addr + (cy_chip_offset[channel>>2] << index); - /* Stop accepting input */ - channel &= 0x03; - cy_writeb(base_addr+(CyCAR<flags & ASYNC_INITIALIZED) { - /* Waiting for on-board buffers to be empty before closing - the port */ - CY_UNLOCK(info, flags); - cy_wait_until_sent(tty, info->timeout); - CY_LOCK(info, flags); + info->count = 0; } - } else { -#ifdef Z_WAKE - /* Waiting for on-board buffers to be empty before closing the port */ - void __iomem *base_addr = cy_card[info->card].base_addr; - struct FIRM_ID __iomem *firm_id = base_addr + ID_ADDRESS; - struct ZFW_CTRL __iomem *zfw_ctrl = base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff); - struct CH_CTRL __iomem *ch_ctrl = zfw_ctrl->ch_ctrl; - int channel = info->line - cy_card[info->card].first_line; - int retval; + if (info->count) { + CY_UNLOCK(info, flags); + return; + } + info->flags |= ASYNC_CLOSING; - if (cy_readl(&ch_ctrl[channel].flow_status) != C_FS_TXIDLE) { - retval = cyz_issue_cmd(&cy_card[info->card], channel, - C_CM_IOCTLW, 0L); - if (retval != 0){ - printk("cyc:cy_close retval on ttyC%d was %x\n", - info->line, retval); - } - CY_UNLOCK(info, flags); - interruptible_sleep_on(&info->shutdown_wait); - CY_LOCK(info, flags); + /* + * Now we wait for the transmit buffer to clear; and we notify + * the line discipline to only process XON/XOFF characters. + */ + tty->closing = 1; + CY_UNLOCK(info, flags); + if (info->closing_wait != CY_CLOSING_WAIT_NONE) { + tty_wait_until_sent(tty, info->closing_wait); } + CY_LOCK(info, flags); + + if (!IS_CYC_Z(cy_card[info->card])) { + int channel = info->line - cy_card[info->card].first_line; + int index = cy_card[info->card].bus_index; + void __iomem *base_addr = cy_card[info->card].base_addr + + (cy_chip_offset[channel >> 2] << index); + /* Stop accepting input */ + channel &= 0x03; + cy_writeb(base_addr + (CyCAR << index), (u_char) channel); + cy_writeb(base_addr + (CySRER << index), + cy_readb(base_addr + (CySRER << index)) & ~CyRxData); + if (info->flags & ASYNC_INITIALIZED) { + /* Waiting for on-board buffers to be empty before closing + the port */ + CY_UNLOCK(info, flags); + cy_wait_until_sent(tty, info->timeout); + CY_LOCK(info, flags); + } + } else { +#ifdef Z_WAKE + /* Waiting for on-board buffers to be empty before closing the port */ + void __iomem *base_addr = cy_card[info->card].base_addr; + struct FIRM_ID __iomem *firm_id = base_addr + ID_ADDRESS; + struct ZFW_CTRL __iomem *zfw_ctrl = + base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff); + struct CH_CTRL __iomem *ch_ctrl = zfw_ctrl->ch_ctrl; + int channel = info->line - cy_card[info->card].first_line; + int retval; + + if (cy_readl(&ch_ctrl[channel].flow_status) != C_FS_TXIDLE) { + retval = cyz_issue_cmd(&cy_card[info->card], channel, + C_CM_IOCTLW, 0L); + if (retval != 0) { + printk("cyc:cy_close retval on ttyC%d was %x\n", + info->line, retval); + } + CY_UNLOCK(info, flags); + interruptible_sleep_on(&info->shutdown_wait); + CY_LOCK(info, flags); + } #endif - } - - CY_UNLOCK(info, flags); - shutdown(info); - if (tty->driver->flush_buffer) - tty->driver->flush_buffer(tty); - tty_ldisc_flush(tty); - CY_LOCK(info, flags); - - tty->closing = 0; - info->event = 0; - info->tty = NULL; - if (info->blocked_open) { + } + CY_UNLOCK(info, flags); - if (info->close_delay) { - msleep_interruptible(jiffies_to_msecs(info->close_delay)); - } - wake_up_interruptible(&info->open_wait); + shutdown(info); + if (tty->driver->flush_buffer) + tty->driver->flush_buffer(tty); + tty_ldisc_flush(tty); CY_LOCK(info, flags); - } - info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); - wake_up_interruptible(&info->close_wait); + + tty->closing = 0; + info->event = 0; + info->tty = NULL; + if (info->blocked_open) { + CY_UNLOCK(info, flags); + if (info->close_delay) { + msleep_interruptible(jiffies_to_msecs + (info->close_delay)); + } + wake_up_interruptible(&info->open_wait); + CY_LOCK(info, flags); + } + info->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING); + wake_up_interruptible(&info->close_wait); #ifdef CY_DEBUG_OTHER - printk(" cyc:cy_close done\n"); + printk(" cyc:cy_close done\n"); #endif - CY_UNLOCK(info, flags); - return; -} /* cy_close */ - + CY_UNLOCK(info, flags); +} /* cy_close */ /* This routine gets called when tty_write has put something into * the write_queue. The characters may come from user space or @@ -2795,50 +2875,49 @@ cy_close(struct tty_struct *tty, struct file *filp) * If the port is already active, there is no need to kick it. * */ -static int -cy_write(struct tty_struct * tty, const unsigned char *buf, int count) +static int cy_write(struct tty_struct *tty, const unsigned char *buf, int count) { - struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; - unsigned long flags; - int c, ret = 0; + struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; + unsigned long flags; + int c, ret = 0; #ifdef CY_DEBUG_IO - printk("cyc:cy_write ttyC%d\n", info->line); /* */ + printk("cyc:cy_write ttyC%d\n", info->line); /* */ #endif - if (serial_paranoia_check(info, tty->name, "cy_write")){ - return 0; - } - - if (!info->xmit_buf) - return 0; + if (serial_paranoia_check(info, tty->name, "cy_write")) { + return 0; + } + + if (!info->xmit_buf) + return 0; + + CY_LOCK(info, flags); + while (1) { + c = min(count, min((int)(SERIAL_XMIT_SIZE - info->xmit_cnt - 1), + (int)(SERIAL_XMIT_SIZE - info->xmit_head))); + + if (c <= 0) + break; + + memcpy(info->xmit_buf + info->xmit_head, buf, c); + info->xmit_head = (info->xmit_head + c) & + (SERIAL_XMIT_SIZE - 1); + info->xmit_cnt += c; + buf += c; + count -= c; + ret += c; + } + CY_UNLOCK(info, flags); - CY_LOCK(info, flags); - while (1) { - c = min(count, min((int)(SERIAL_XMIT_SIZE - info->xmit_cnt - 1), - (int)(SERIAL_XMIT_SIZE - info->xmit_head))); - - if (c <= 0) - break; - - memcpy(info->xmit_buf + info->xmit_head, buf, c); - info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1); - info->xmit_cnt += c; - buf += c; - count -= c; - ret += c; - } - CY_UNLOCK(info, flags); - - info->idle_stats.xmit_bytes += ret; - info->idle_stats.xmit_idle = jiffies; - - if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped) { - start_xmit(info); - } - return ret; -} /* cy_write */ + info->idle_stats.xmit_bytes += ret; + info->idle_stats.xmit_idle = jiffies; + if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped) { + start_xmit(info); + } + return ret; +} /* cy_write */ /* * This routine is called by the kernel to write a single @@ -2847,60 +2926,56 @@ cy_write(struct tty_struct * tty, const unsigned char *buf, int count) * done stuffing characters into the driver. If there is no room * in the queue, the character is ignored. */ -static void -cy_put_char(struct tty_struct *tty, unsigned char ch) +static void cy_put_char(struct tty_struct *tty, unsigned char ch) { - struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; - unsigned long flags; + struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; + unsigned long flags; #ifdef CY_DEBUG_IO - printk("cyc:cy_put_char ttyC%d\n", info->line); + printk("cyc:cy_put_char ttyC%d\n", info->line); #endif - if (serial_paranoia_check(info, tty->name, "cy_put_char")) - return; + if (serial_paranoia_check(info, tty->name, "cy_put_char")) + return; - if (!info->xmit_buf) - return; + if (!info->xmit_buf) + return; - CY_LOCK(info, flags); - if (info->xmit_cnt >= SERIAL_XMIT_SIZE - 1) { - CY_UNLOCK(info, flags); - return; - } + CY_LOCK(info, flags); + if (info->xmit_cnt >= (int)(SERIAL_XMIT_SIZE - 1)) { + CY_UNLOCK(info, flags); + return; + } - info->xmit_buf[info->xmit_head++] = ch; - info->xmit_head &= SERIAL_XMIT_SIZE - 1; - info->xmit_cnt++; + info->xmit_buf[info->xmit_head++] = ch; + info->xmit_head &= SERIAL_XMIT_SIZE - 1; + info->xmit_cnt++; info->idle_stats.xmit_bytes++; info->idle_stats.xmit_idle = jiffies; - CY_UNLOCK(info, flags); -} /* cy_put_char */ - + CY_UNLOCK(info, flags); +} /* cy_put_char */ /* * This routine is called by the kernel after it has written a * series of characters to the tty device using put_char(). */ -static void -cy_flush_chars(struct tty_struct *tty) +static void cy_flush_chars(struct tty_struct *tty) { - struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; - + struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; + #ifdef CY_DEBUG_IO - printk("cyc:cy_flush_chars ttyC%d\n", info->line); /* */ + printk("cyc:cy_flush_chars ttyC%d\n", info->line); /* */ #endif - if (serial_paranoia_check(info, tty->name, "cy_flush_chars")) - return; - - if (info->xmit_cnt <= 0 || tty->stopped - || tty->hw_stopped || !info->xmit_buf) - return; + if (serial_paranoia_check(info, tty->name, "cy_flush_chars")) + return; - start_xmit(info); -} /* cy_flush_chars */ + if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped || + !info->xmit_buf) + return; + start_xmit(info); +} /* cy_flush_chars */ /* * This routine returns the numbers of characters the tty driver @@ -2908,75 +2983,70 @@ cy_flush_chars(struct tty_struct *tty) * to change as output buffers get emptied, or if the output flow * control is activated. */ -static int -cy_write_room(struct tty_struct *tty) +static int cy_write_room(struct tty_struct *tty) { - struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; - int ret; - + struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; + int ret; + #ifdef CY_DEBUG_IO - printk("cyc:cy_write_room ttyC%d\n", info->line); /* */ + printk("cyc:cy_write_room ttyC%d\n", info->line); /* */ #endif - if (serial_paranoia_check(info, tty->name, "cy_write_room")) - return 0; - ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1; - if (ret < 0) - ret = 0; - return ret; -} /* cy_write_room */ + if (serial_paranoia_check(info, tty->name, "cy_write_room")) + return 0; + ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1; + if (ret < 0) + ret = 0; + return ret; +} /* cy_write_room */ - -static int -cy_chars_in_buffer(struct tty_struct *tty) +static int cy_chars_in_buffer(struct tty_struct *tty) { - struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; - int card, channel; - - if (serial_paranoia_check(info, tty->name, "cy_chars_in_buffer")) - return 0; + struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; + int card, channel; - card = info->card; - channel = (info->line) - (cy_card[card].first_line); + if (serial_paranoia_check(info, tty->name, "cy_chars_in_buffer")) + return 0; + + card = info->card; + channel = (info->line) - (cy_card[card].first_line); #ifdef Z_EXT_CHARS_IN_BUFFER - if (!IS_CYC_Z(cy_card[card])) { -#endif /* Z_EXT_CHARS_IN_BUFFER */ + if (!IS_CYC_Z(cy_card[card])) { +#endif /* Z_EXT_CHARS_IN_BUFFER */ #ifdef CY_DEBUG_IO - printk("cyc:cy_chars_in_buffer ttyC%d %d\n", - info->line, info->xmit_cnt); /* */ + printk("cyc:cy_chars_in_buffer ttyC%d %d\n", info->line, info->xmit_cnt); /* */ #endif - return info->xmit_cnt; + return info->xmit_cnt; #ifdef Z_EXT_CHARS_IN_BUFFER - } else { - static volatile struct FIRM_ID *firm_id; - static volatile struct ZFW_CTRL *zfw_ctrl; - static volatile struct CH_CTRL *ch_ctrl; - static volatile struct BUF_CTRL *buf_ctrl; - int char_count; - volatile uclong tx_put, tx_get, tx_bufsize; - - firm_id = cy_card[card].base_addr + ID_ADDRESS; - zfw_ctrl = cy_card[card].base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff); - ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]); - buf_ctrl = &(zfw_ctrl->buf_ctrl[channel]); - - tx_get = cy_readl(&buf_ctrl->tx_get); - tx_put = cy_readl(&buf_ctrl->tx_put); - tx_bufsize = cy_readl(&buf_ctrl->tx_bufsize); - if (tx_put >= tx_get) - char_count = tx_put - tx_get; - else - char_count = tx_put - tx_get + tx_bufsize; + } else { + static volatile struct FIRM_ID *firm_id; + static volatile struct ZFW_CTRL *zfw_ctrl; + static volatile struct CH_CTRL *ch_ctrl; + static volatile struct BUF_CTRL *buf_ctrl; + int char_count; + volatile uclong tx_put, tx_get, tx_bufsize; + + firm_id = cy_card[card].base_addr + ID_ADDRESS; + zfw_ctrl = cy_card[card].base_addr + + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff); + ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]); + buf_ctrl = &(zfw_ctrl->buf_ctrl[channel]); + + tx_get = cy_readl(&buf_ctrl->tx_get); + tx_put = cy_readl(&buf_ctrl->tx_put); + tx_bufsize = cy_readl(&buf_ctrl->tx_bufsize); + if (tx_put >= tx_get) + char_count = tx_put - tx_get; + else + char_count = tx_put - tx_get + tx_bufsize; #ifdef CY_DEBUG_IO - printk("cyc:cy_chars_in_buffer ttyC%d %d\n", - info->line, info->xmit_cnt + char_count); /* */ + printk("cyc:cy_chars_in_buffer ttyC%d %d\n", info->line, info->xmit_cnt + char_count); /* */ #endif - return (info->xmit_cnt + char_count); - } -#endif /* Z_EXT_CHARS_IN_BUFFER */ -} /* cy_chars_in_buffer */ - + return info->xmit_cnt + char_count; + } +#endif /* Z_EXT_CHARS_IN_BUFFER */ +} /* cy_chars_in_buffer */ /* * ------------------------------------------------------------ @@ -2984,178 +3054,179 @@ cy_chars_in_buffer(struct tty_struct *tty) * ------------------------------------------------------------ */ -static void -cyy_baud_calc(struct cyclades_port *info, uclong baud) +static void cyy_baud_calc(struct cyclades_port *info, uclong baud) { - int co, co_val, bpr; - uclong cy_clock = ((info->chip_rev >= CD1400_REV_J) ? 60000000 : 25000000); - - if (baud == 0) { - info->tbpr = info->tco = info->rbpr = info->rco = 0; - return; - } - - /* determine which prescaler to use */ - for (co = 4, co_val = 2048; co; co--, co_val >>= 2) { - if (cy_clock / co_val / baud > 63) - break; - } - - bpr = (cy_clock / co_val * 2 / baud + 1) / 2; - if (bpr > 255) - bpr = 255; - - info->tbpr = info->rbpr = bpr; - info->tco = info->rco = co; + int co, co_val, bpr; + uclong cy_clock = ((info->chip_rev >= CD1400_REV_J) ? 60000000 : + 25000000); + + if (baud == 0) { + info->tbpr = info->tco = info->rbpr = info->rco = 0; + return; + } + + /* determine which prescaler to use */ + for (co = 4, co_val = 2048; co; co--, co_val >>= 2) { + if (cy_clock / co_val / baud > 63) + break; + } + + bpr = (cy_clock / co_val * 2 / baud + 1) / 2; + if (bpr > 255) + bpr = 255; + + info->tbpr = info->rbpr = bpr; + info->tco = info->rco = co; } /* * This routine finds or computes the various line characteristics. * It used to be called config_setup */ -static void -set_line_char(struct cyclades_port * info) +static void set_line_char(struct cyclades_port *info) { - unsigned long flags; - void __iomem *base_addr; - int card,chip,channel,index; - unsigned cflag, iflag; - unsigned short chip_number; - int baud, baud_rate = 0; - int i; - - - if (!info->tty || !info->tty->termios){ - return; - } - if (info->line == -1){ - return; - } - cflag = info->tty->termios->c_cflag; - iflag = info->tty->termios->c_iflag; - - /* - * Set up the tty->alt_speed kludge - */ - if (info->tty) { - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) - info->tty->alt_speed = 57600; - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) - info->tty->alt_speed = 115200; - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) - info->tty->alt_speed = 230400; - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) - info->tty->alt_speed = 460800; - } - - card = info->card; - channel = (info->line) - (cy_card[card].first_line); - chip_number = channel / 4; - - if (!IS_CYC_Z(cy_card[card])) { - - index = cy_card[card].bus_index; - - /* baud rate */ - baud = tty_get_baud_rate(info->tty); - if ((baud == 38400) && - ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)) { - if (info->custom_divisor) - baud_rate = info->baud / info->custom_divisor; - else - baud_rate = info->baud; - } else if (baud > CD1400_MAX_SPEED) { - baud = CD1400_MAX_SPEED; + unsigned long flags; + void __iomem *base_addr; + int card, chip, channel, index; + unsigned cflag, iflag; + unsigned short chip_number; + int baud, baud_rate = 0; + int i; + + if (!info->tty || !info->tty->termios) { + return; } - /* find the baud index */ - for (i = 0; i < 20; i++) { - if (baud == baud_table[i]) { - break; - } + if (info->line == -1) { + return; } - if (i == 20) { - i = 19; /* CD1400_MAX_SPEED */ - } + cflag = info->tty->termios->c_cflag; + iflag = info->tty->termios->c_iflag; - if ((baud == 38400) && - ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)) { - cyy_baud_calc(info, baud_rate); - } else { - if(info->chip_rev >= CD1400_REV_J) { - /* It is a CD1400 rev. J or later */ - info->tbpr = baud_bpr_60[i]; /* Tx BPR */ - info->tco = baud_co_60[i]; /* Tx CO */ - info->rbpr = baud_bpr_60[i]; /* Rx BPR */ - info->rco = baud_co_60[i]; /* Rx CO */ - } else { - info->tbpr = baud_bpr_25[i]; /* Tx BPR */ - info->tco = baud_co_25[i]; /* Tx CO */ - info->rbpr = baud_bpr_25[i]; /* Rx BPR */ - info->rco = baud_co_25[i]; /* Rx CO */ - } - } - if (baud_table[i] == 134) { - /* get it right for 134.5 baud */ - info->timeout = (info->xmit_fifo_size*HZ*30/269) + 2; - } else if ((baud == 38400) && - ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)) { - info->timeout = (info->xmit_fifo_size*HZ*15/baud_rate) + 2; - } else if (baud_table[i]) { - info->timeout = (info->xmit_fifo_size*HZ*15/baud_table[i]) + 2; - /* this needs to be propagated into the card info */ - } else { - info->timeout = 0; - } - /* By tradition (is it a standard?) a baud rate of zero - implies the line should be/has been closed. A bit - later in this routine such a test is performed. */ - - /* byte size and parity */ - info->cor5 = 0; - info->cor4 = 0; - info->cor3 = (info->default_threshold - ? info->default_threshold - : baud_cor3[i]); /* receive threshold */ - info->cor2 = CyETC; - switch(cflag & CSIZE){ - case CS5: - info->cor1 = Cy_5_BITS; - break; - case CS6: - info->cor1 = Cy_6_BITS; - break; - case CS7: - info->cor1 = Cy_7_BITS; - break; - case CS8: - info->cor1 = Cy_8_BITS; - break; - } - if(cflag & CSTOPB){ - info->cor1 |= Cy_2_STOP; - } - if (cflag & PARENB){ - if (cflag & PARODD){ - info->cor1 |= CyPARITY_O; - }else{ - info->cor1 |= CyPARITY_E; - } - }else{ - info->cor1 |= CyPARITY_NONE; - } - - /* CTS flow control flag */ - if (cflag & CRTSCTS){ - info->flags |= ASYNC_CTS_FLOW; - info->cor2 |= CyCtsAE; - }else{ - info->flags &= ~ASYNC_CTS_FLOW; - info->cor2 &= ~CyCtsAE; + /* + * Set up the tty->alt_speed kludge + */ + if (info->tty) { + if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) + info->tty->alt_speed = 57600; + if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) + info->tty->alt_speed = 115200; + if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) + info->tty->alt_speed = 230400; + if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) + info->tty->alt_speed = 460800; } - if (cflag & CLOCAL) - info->flags &= ~ASYNC_CHECK_CD; - else - info->flags |= ASYNC_CHECK_CD; + + card = info->card; + channel = (info->line) - (cy_card[card].first_line); + chip_number = channel / 4; + + if (!IS_CYC_Z(cy_card[card])) { + + index = cy_card[card].bus_index; + + /* baud rate */ + baud = tty_get_baud_rate(info->tty); + if (baud == 38400 && (info->flags & ASYNC_SPD_MASK) == + ASYNC_SPD_CUST) { + if (info->custom_divisor) + baud_rate = info->baud / info->custom_divisor; + else + baud_rate = info->baud; + } else if (baud > CD1400_MAX_SPEED) { + baud = CD1400_MAX_SPEED; + } + /* find the baud index */ + for (i = 0; i < 20; i++) { + if (baud == baud_table[i]) { + break; + } + } + if (i == 20) { + i = 19; /* CD1400_MAX_SPEED */ + } + + if (baud == 38400 && (info->flags & ASYNC_SPD_MASK) == + ASYNC_SPD_CUST) { + cyy_baud_calc(info, baud_rate); + } else { + if (info->chip_rev >= CD1400_REV_J) { + /* It is a CD1400 rev. J or later */ + info->tbpr = baud_bpr_60[i]; /* Tx BPR */ + info->tco = baud_co_60[i]; /* Tx CO */ + info->rbpr = baud_bpr_60[i]; /* Rx BPR */ + info->rco = baud_co_60[i]; /* Rx CO */ + } else { + info->tbpr = baud_bpr_25[i]; /* Tx BPR */ + info->tco = baud_co_25[i]; /* Tx CO */ + info->rbpr = baud_bpr_25[i]; /* Rx BPR */ + info->rco = baud_co_25[i]; /* Rx CO */ + } + } + if (baud_table[i] == 134) { + /* get it right for 134.5 baud */ + info->timeout = (info->xmit_fifo_size * HZ * 30 / 269) + + 2; + } else if (baud == 38400 && (info->flags & ASYNC_SPD_MASK) == + ASYNC_SPD_CUST) { + info->timeout = (info->xmit_fifo_size * HZ * 15 / + baud_rate) + 2; + } else if (baud_table[i]) { + info->timeout = (info->xmit_fifo_size * HZ * 15 / + baud_table[i]) + 2; + /* this needs to be propagated into the card info */ + } else { + info->timeout = 0; + } + /* By tradition (is it a standard?) a baud rate of zero + implies the line should be/has been closed. A bit + later in this routine such a test is performed. */ + + /* byte size and parity */ + info->cor5 = 0; + info->cor4 = 0; + /* receive threshold */ + info->cor3 = (info->default_threshold ? + info->default_threshold : baud_cor3[i]); + info->cor2 = CyETC; + switch (cflag & CSIZE) { + case CS5: + info->cor1 = Cy_5_BITS; + break; + case CS6: + info->cor1 = Cy_6_BITS; + break; + case CS7: + info->cor1 = Cy_7_BITS; + break; + case CS8: + info->cor1 = Cy_8_BITS; + break; + } + if (cflag & CSTOPB) { + info->cor1 |= Cy_2_STOP; + } + if (cflag & PARENB) { + if (cflag & PARODD) { + info->cor1 |= CyPARITY_O; + } else { + info->cor1 |= CyPARITY_E; + } + } else { + info->cor1 |= CyPARITY_NONE; + } + + /* CTS flow control flag */ + if (cflag & CRTSCTS) { + info->flags |= ASYNC_CTS_FLOW; + info->cor2 |= CyCtsAE; + } else { + info->flags &= ~ASYNC_CTS_FLOW; + info->cor2 &= ~CyCtsAE; + } + if (cflag & CLOCAL) + info->flags &= ~ASYNC_CHECK_CD; + else + info->flags |= ASYNC_CHECK_CD; /*********************************************** The hardware option, CyRtsAO, presents RTS when @@ -3167,300 +3238,319 @@ set_line_char(struct cyclades_port * info) cable. Contact Marcio Saito for details. ***********************************************/ - chip = channel>>2; - channel &= 0x03; - base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<> 2; + channel &= 0x03; + base_addr = cy_card[card].base_addr + + (cy_chip_offset[chip] << index); - CY_LOCK(info, flags); - cy_writeb(base_addr+(CyCAR<tco); - cy_writeb(base_addr+(CyTBPR<tbpr); - cy_writeb(base_addr+(CyRCOR<rco); - cy_writeb(base_addr+(CyRBPR<rbpr); - - /* set line characteristics according configuration */ - - cy_writeb(base_addr+(CySCHR1<tty)); - cy_writeb(base_addr+(CySCHR2<tty)); - cy_writeb(base_addr+(CyCOR1<cor1); - cy_writeb(base_addr+(CyCOR2<cor2); - cy_writeb(base_addr+(CyCOR3<cor3); - cy_writeb(base_addr+(CyCOR4<cor4); - cy_writeb(base_addr+(CyCOR5<cor5); - - cyy_issue_cmd(base_addr, - CyCOR_CHANGE|CyCOR1ch|CyCOR2ch|CyCOR3ch,index); - - cy_writeb(base_addr+(CyCAR<default_timeout - ? info->default_timeout - : 0x02)); /* 10ms rx timeout */ - - if (C_CLOCAL(info->tty)) { - /* without modem intr */ - cy_writeb(base_addr+(CySRER<0 modem transitions */ - if ((cflag & CRTSCTS) && info->rflow) { - cy_writeb(base_addr+(CyMCOR1<1 modem transitions */ - cy_writeb(base_addr+(CyMCOR2<0 modem transitions */ - if ((cflag & CRTSCTS) && info->rflow) { - cy_writeb(base_addr+(CyMCOR1<1 modem transitions */ - cy_writeb(base_addr+(CyMCOR2<rtsdtr_inv) { - cy_writeb(base_addr+(CyMSVR1<tco); + cy_writeb(base_addr + (CyTBPR << index), info->tbpr); + cy_writeb(base_addr + (CyRCOR << index), info->rco); + cy_writeb(base_addr + (CyRBPR << index), info->rbpr); + + /* set line characteristics according configuration */ + + cy_writeb(base_addr + (CySCHR1 << index), + START_CHAR(info->tty)); + cy_writeb(base_addr + (CySCHR2 << index), STOP_CHAR(info->tty)); + cy_writeb(base_addr + (CyCOR1 << index), info->cor1); + cy_writeb(base_addr + (CyCOR2 << index), info->cor2); + cy_writeb(base_addr + (CyCOR3 << index), info->cor3); + cy_writeb(base_addr + (CyCOR4 << index), info->cor4); + cy_writeb(base_addr + (CyCOR5 << index), info->cor5); + + cyy_issue_cmd(base_addr, CyCOR_CHANGE | CyCOR1ch | CyCOR2ch | + CyCOR3ch, index); + + cy_writeb(base_addr + (CyCAR << index), (u_char) channel); /* !!! Is this needed? */ + cy_writeb(base_addr + (CyRTPR << index), + (info->default_timeout ? info->default_timeout : 0x02)); + /* 10ms rx timeout */ + + if (C_CLOCAL(info->tty)) { + /* without modem intr */ + cy_writeb(base_addr + (CySRER << index), + cy_readb(base_addr + + (CySRER << index)) | CyMdmCh); + /* act on 1->0 modem transitions */ + if ((cflag & CRTSCTS) && info->rflow) { + cy_writeb(base_addr + (CyMCOR1 << index), + (CyCTS | rflow_thr[i])); + } else { + cy_writeb(base_addr + (CyMCOR1 << index), + CyCTS); + } + /* act on 0->1 modem transitions */ + cy_writeb(base_addr + (CyMCOR2 << index), CyCTS); } else { - cy_writeb(base_addr+(CyMSVR2<0 modem transitions */ + if ((cflag & CRTSCTS) && info->rflow) { + cy_writeb(base_addr + (CyMCOR1 << index), + (CyDSR | CyCTS | CyRI | CyDCD | + rflow_thr[i])); + } else { + cy_writeb(base_addr + (CyMCOR1 << index), + CyDSR | CyCTS | CyRI | CyDCD); + } + /* act on 0->1 modem transitions */ + cy_writeb(base_addr + (CyMCOR2 << index), + CyDSR | CyCTS | CyRI | CyDCD); } + + if (i == 0) { /* baud rate is zero, turn off line */ + if (info->rtsdtr_inv) { + cy_writeb(base_addr + (CyMSVR1 << index), + ~CyRTS); + } else { + cy_writeb(base_addr + (CyMSVR2 << index), + ~CyDTR); + } #ifdef CY_DEBUG_DTR - printk("cyc:set_line_char dropping DTR\n"); - printk(" status: 0x%x, 0x%x\n", - cy_readb(base_addr+(CyMSVR1<rtsdtr_inv) { - cy_writeb(base_addr+(CyMSVR1<rtsdtr_inv) { + cy_writeb(base_addr + (CyMSVR1 << index), + CyRTS); + } else { + cy_writeb(base_addr + (CyMSVR2 << index), + CyDTR); + } #ifdef CY_DEBUG_DTR - printk("cyc:set_line_char raising DTR\n"); - printk(" status: 0x%x, 0x%x\n", - cy_readb(base_addr+(CyMSVR1<tty){ - clear_bit(TTY_IO_ERROR, &info->tty->flags); - } - CY_UNLOCK(info, flags); + } - } else { - struct FIRM_ID __iomem *firm_id; - struct ZFW_CTRL __iomem *zfw_ctrl; - struct BOARD_CTRL __iomem *board_ctrl; - struct CH_CTRL __iomem *ch_ctrl; - struct BUF_CTRL __iomem *buf_ctrl; - uclong sw_flow; - int retval; - - firm_id = cy_card[card].base_addr + ID_ADDRESS; - if (!ISZLOADED(cy_card[card])) { - return; - } + if (info->tty) { + clear_bit(TTY_IO_ERROR, &info->tty->flags); + } + CY_UNLOCK(info, flags); - zfw_ctrl = cy_card[card].base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff); - board_ctrl = &zfw_ctrl->board_ctrl; - ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]); - buf_ctrl = &zfw_ctrl->buf_ctrl[channel]; - - /* baud rate */ - baud = tty_get_baud_rate(info->tty); - if ((baud == 38400) && - ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)) { - if (info->custom_divisor) - baud_rate = info->baud / info->custom_divisor; - else - baud_rate = info->baud; - } else if (baud > CYZ_MAX_SPEED) { - baud = CYZ_MAX_SPEED; - } - cy_writel(&ch_ctrl->comm_baud , baud); - - if (baud == 134) { - /* get it right for 134.5 baud */ - info->timeout = (info->xmit_fifo_size*HZ*30/269) + 2; - } else if ((baud == 38400) && - ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)) { - info->timeout = (info->xmit_fifo_size*HZ*15/baud_rate) + 2; - } else if (baud) { - info->timeout = (info->xmit_fifo_size*HZ*15/baud) + 2; - /* this needs to be propagated into the card info */ } else { - info->timeout = 0; - } + struct FIRM_ID __iomem *firm_id; + struct ZFW_CTRL __iomem *zfw_ctrl; + struct BOARD_CTRL __iomem *board_ctrl; + struct CH_CTRL __iomem *ch_ctrl; + struct BUF_CTRL __iomem *buf_ctrl; + uclong sw_flow; + int retval; + + firm_id = cy_card[card].base_addr + ID_ADDRESS; + if (!ISZLOADED(cy_card[card])) { + return; + } - /* byte size and parity */ - switch(cflag & CSIZE){ - case CS5: cy_writel(&ch_ctrl->comm_data_l , C_DL_CS5); break; - case CS6: cy_writel(&ch_ctrl->comm_data_l , C_DL_CS6); break; - case CS7: cy_writel(&ch_ctrl->comm_data_l , C_DL_CS7); break; - case CS8: cy_writel(&ch_ctrl->comm_data_l , C_DL_CS8); break; - } - if(cflag & CSTOPB){ - cy_writel(&ch_ctrl->comm_data_l, - cy_readl(&ch_ctrl->comm_data_l) | C_DL_2STOP); - }else{ - cy_writel(&ch_ctrl->comm_data_l, - cy_readl(&ch_ctrl->comm_data_l) | C_DL_1STOP); - } - if (cflag & PARENB){ - if (cflag & PARODD){ - cy_writel(&ch_ctrl->comm_parity , C_PR_ODD); - }else{ - cy_writel(&ch_ctrl->comm_parity , C_PR_EVEN); - } - }else{ - cy_writel(&ch_ctrl->comm_parity , C_PR_NONE); - } + zfw_ctrl = cy_card[card].base_addr + + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff); + board_ctrl = &zfw_ctrl->board_ctrl; + ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]); + buf_ctrl = &zfw_ctrl->buf_ctrl[channel]; + + /* baud rate */ + baud = tty_get_baud_rate(info->tty); + if (baud == 38400 && (info->flags & ASYNC_SPD_MASK) == + ASYNC_SPD_CUST) { + if (info->custom_divisor) + baud_rate = info->baud / info->custom_divisor; + else + baud_rate = info->baud; + } else if (baud > CYZ_MAX_SPEED) { + baud = CYZ_MAX_SPEED; + } + cy_writel(&ch_ctrl->comm_baud, baud); + + if (baud == 134) { + /* get it right for 134.5 baud */ + info->timeout = (info->xmit_fifo_size * HZ * 30 / 269) + + 2; + } else if (baud == 38400 && (info->flags & ASYNC_SPD_MASK) == + ASYNC_SPD_CUST) { + info->timeout = (info->xmit_fifo_size * HZ * 15 / + baud_rate) + 2; + } else if (baud) { + info->timeout = (info->xmit_fifo_size * HZ * 15 / + baud) + 2; + /* this needs to be propagated into the card info */ + } else { + info->timeout = 0; + } - /* CTS flow control flag */ - if (cflag & CRTSCTS){ - cy_writel(&ch_ctrl->hw_flow, - cy_readl(&ch_ctrl->hw_flow) | C_RS_CTS | C_RS_RTS); - }else{ - cy_writel(&ch_ctrl->hw_flow, - cy_readl(&ch_ctrl->hw_flow) & ~(C_RS_CTS | C_RS_RTS)); - } - /* As the HW flow control is done in firmware, the driver doesn't - need to care about it */ - info->flags &= ~ASYNC_CTS_FLOW; - - /* XON/XOFF/XANY flow control flags */ - sw_flow = 0; - if (iflag & IXON){ - sw_flow |= C_FL_OXX; - if (iflag & IXANY) - sw_flow |= C_FL_OIXANY; - } - cy_writel(&ch_ctrl->sw_flow, sw_flow); + /* byte size and parity */ + switch (cflag & CSIZE) { + case CS5: + cy_writel(&ch_ctrl->comm_data_l, C_DL_CS5); + break; + case CS6: + cy_writel(&ch_ctrl->comm_data_l, C_DL_CS6); + break; + case CS7: + cy_writel(&ch_ctrl->comm_data_l, C_DL_CS7); + break; + case CS8: + cy_writel(&ch_ctrl->comm_data_l, C_DL_CS8); + break; + } + if (cflag & CSTOPB) { + cy_writel(&ch_ctrl->comm_data_l, + cy_readl(&ch_ctrl->comm_data_l) | C_DL_2STOP); + } else { + cy_writel(&ch_ctrl->comm_data_l, + cy_readl(&ch_ctrl->comm_data_l) | C_DL_1STOP); + } + if (cflag & PARENB) { + if (cflag & PARODD) { + cy_writel(&ch_ctrl->comm_parity, C_PR_ODD); + } else { + cy_writel(&ch_ctrl->comm_parity, C_PR_EVEN); + } + } else { + cy_writel(&ch_ctrl->comm_parity, C_PR_NONE); + } - retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_IOCTL, 0L); - if (retval != 0){ - printk("cyc:set_line_char retval on ttyC%d was %x\n", - info->line, retval); - } + /* CTS flow control flag */ + if (cflag & CRTSCTS) { + cy_writel(&ch_ctrl->hw_flow, + cy_readl(&ch_ctrl-> + hw_flow) | C_RS_CTS | C_RS_RTS); + } else { + cy_writel(&ch_ctrl->hw_flow, + cy_readl(&ch_ctrl-> + hw_flow) & ~(C_RS_CTS | C_RS_RTS)); + } + /* As the HW flow control is done in firmware, the driver + doesn't need to care about it */ + info->flags &= ~ASYNC_CTS_FLOW; + + /* XON/XOFF/XANY flow control flags */ + sw_flow = 0; + if (iflag & IXON) { + sw_flow |= C_FL_OXX; + if (iflag & IXANY) + sw_flow |= C_FL_OIXANY; + } + cy_writel(&ch_ctrl->sw_flow, sw_flow); - /* CD sensitivity */ - if (cflag & CLOCAL){ - info->flags &= ~ASYNC_CHECK_CD; - }else{ - info->flags |= ASYNC_CHECK_CD; - } + retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_IOCTL, 0L); + if (retval != 0) { + printk("cyc:set_line_char retval on ttyC%d was %x\n", + info->line, retval); + } + + /* CD sensitivity */ + if (cflag & CLOCAL) { + info->flags &= ~ASYNC_CHECK_CD; + } else { + info->flags |= ASYNC_CHECK_CD; + } - if(baud == 0){ /* baud rate is zero, turn off line */ - cy_writel(&ch_ctrl->rs_control, - cy_readl(&ch_ctrl->rs_control) & ~C_RS_DTR); + if (baud == 0) { /* baud rate is zero, turn off line */ + cy_writel(&ch_ctrl->rs_control, + cy_readl(&ch_ctrl->rs_control) & ~C_RS_DTR); #ifdef CY_DEBUG_DTR - printk("cyc:set_line_char dropping Z DTR\n"); + printk("cyc:set_line_char dropping Z DTR\n"); #endif - }else{ - cy_writel(&ch_ctrl->rs_control, - cy_readl(&ch_ctrl->rs_control) | C_RS_DTR); + } else { + cy_writel(&ch_ctrl->rs_control, + cy_readl(&ch_ctrl->rs_control) | C_RS_DTR); #ifdef CY_DEBUG_DTR - printk("cyc:set_line_char raising Z DTR\n"); + printk("cyc:set_line_char raising Z DTR\n"); #endif - } + } - retval = cyz_issue_cmd( &cy_card[card], channel, C_CM_IOCTLM, 0L); - if (retval != 0){ - printk("cyc:set_line_char(2) retval on ttyC%d was %x\n", - info->line, retval); - } + retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_IOCTLM,0L); + if (retval != 0) { + printk("cyc:set_line_char(2) retval on ttyC%d was %x\n", + info->line, retval); + } - if (info->tty){ - clear_bit(TTY_IO_ERROR, &info->tty->flags); + if (info->tty) { + clear_bit(TTY_IO_ERROR, &info->tty->flags); + } } - } -} /* set_line_char */ - +} /* set_line_char */ static int -get_serial_info(struct cyclades_port * info, - struct serial_struct __user * retinfo) +get_serial_info(struct cyclades_port *info, + struct serial_struct __user * retinfo) { - struct serial_struct tmp; - struct cyclades_card *cinfo = &cy_card[info->card]; - - if (!retinfo) - return -EFAULT; - memset(&tmp, 0, sizeof(tmp)); - tmp.type = info->type; - tmp.line = info->line; - tmp.port = info->card * 0x100 + info->line - cinfo->first_line; - tmp.irq = cinfo->irq; - tmp.flags = info->flags; - tmp.close_delay = info->close_delay; - tmp.baud_base = info->baud; - tmp.custom_divisor = info->custom_divisor; - tmp.hub6 = 0; /*!!!*/ - return copy_to_user(retinfo,&tmp,sizeof(*retinfo))?-EFAULT:0; -} /* get_serial_info */ + struct serial_struct tmp; + struct cyclades_card *cinfo = &cy_card[info->card]; + if (!retinfo) + return -EFAULT; + memset(&tmp, 0, sizeof(tmp)); + tmp.type = info->type; + tmp.line = info->line; + tmp.port = info->card * 0x100 + info->line - cinfo->first_line; + tmp.irq = cinfo->irq; + tmp.flags = info->flags; + tmp.close_delay = info->close_delay; + tmp.baud_base = info->baud; + tmp.custom_divisor = info->custom_divisor; + tmp.hub6 = 0; /*!!! */ + return copy_to_user(retinfo, &tmp, sizeof(*retinfo)) ? -EFAULT : 0; +} /* get_serial_info */ static int -set_serial_info(struct cyclades_port * info, - struct serial_struct __user * new_info) +set_serial_info(struct cyclades_port *info, + struct serial_struct __user * new_info) { - struct serial_struct new_serial; - struct cyclades_port old_info; - - if (copy_from_user(&new_serial,new_info,sizeof(new_serial))) - return -EFAULT; - old_info = *info; - - if (!capable(CAP_SYS_ADMIN)) { - if ((new_serial.close_delay != info->close_delay) || - (new_serial.baud_base != info->baud) || - ((new_serial.flags & ASYNC_FLAGS & ~ASYNC_USR_MASK) != - (info->flags & ASYNC_FLAGS & ~ASYNC_USR_MASK))) - return -EPERM; - info->flags = ((info->flags & ~ASYNC_USR_MASK) | - (new_serial.flags & ASYNC_USR_MASK)); - info->baud = new_serial.baud_base; - info->custom_divisor = new_serial.custom_divisor; - goto check_and_exit; - } - - - /* - * OK, past this point, all the error checking has been done. - * At this point, we start making changes..... - */ - - info->baud = new_serial.baud_base; - info->custom_divisor = new_serial.custom_divisor; - info->flags = ((info->flags & ~ASYNC_FLAGS) | - (new_serial.flags & ASYNC_FLAGS)); - info->close_delay = new_serial.close_delay * HZ/100; - info->closing_wait = new_serial.closing_wait * HZ/100; + struct serial_struct new_serial; + struct cyclades_port old_info; + + if (copy_from_user(&new_serial, new_info, sizeof(new_serial))) + return -EFAULT; + old_info = *info; + + if (!capable(CAP_SYS_ADMIN)) { + if (new_serial.close_delay != info->close_delay || + new_serial.baud_base != info->baud || + (new_serial.flags & ASYNC_FLAGS & + ~ASYNC_USR_MASK) != + (info->flags & ASYNC_FLAGS & ~ASYNC_USR_MASK)) + return -EPERM; + info->flags = (info->flags & ~ASYNC_USR_MASK) | + (new_serial.flags & ASYNC_USR_MASK); + info->baud = new_serial.baud_base; + info->custom_divisor = new_serial.custom_divisor; + goto check_and_exit; + } + + /* + * OK, past this point, all the error checking has been done. + * At this point, we start making changes..... + */ + + info->baud = new_serial.baud_base; + info->custom_divisor = new_serial.custom_divisor; + info->flags = (info->flags & ~ASYNC_FLAGS) | + (new_serial.flags & ASYNC_FLAGS); + info->close_delay = new_serial.close_delay * HZ / 100; + info->closing_wait = new_serial.closing_wait * HZ / 100; check_and_exit: - if (info->flags & ASYNC_INITIALIZED){ - set_line_char(info); - return 0; - }else{ - return startup(info); - } -} /* set_serial_info */ + if (info->flags & ASYNC_INITIALIZED) { + set_line_char(info); + return 0; + } else { + return startup(info); + } +} /* set_serial_info */ /* * get_lsr_info - get line status register info @@ -3472,441 +3562,452 @@ set_serial_info(struct cyclades_port * info, * transmit holding register is empty. This functionality * allows an RS485 driver to be written in user space. */ -static int get_lsr_info(struct cyclades_port *info, unsigned int __user *value) +static int get_lsr_info(struct cyclades_port *info, unsigned int __user * value) { - int card, chip, channel, index; - unsigned char status; - unsigned int result; - unsigned long flags; - void __iomem *base_addr; - - card = info->card; - channel = (info->line) - (cy_card[card].first_line); - if (!IS_CYC_Z(cy_card[card])) { - chip = channel>>2; - channel &= 0x03; - index = cy_card[card].bus_index; - base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<card; + channel = (info->line) - (cy_card[card].first_line); + if (!IS_CYC_Z(cy_card[card])) { + chip = channel >> 2; + channel &= 0x03; + index = cy_card[card].bus_index; + base_addr = + cy_card[card].base_addr + (cy_chip_offset[chip] << index); + + CY_LOCK(info, flags); + status = cy_readb(base_addr + (CySRER << index)) & + (CyTxRdy | CyTxMpty); + CY_UNLOCK(info, flags); + result = (status ? 0 : TIOCSER_TEMT); + } else { + /* Not supported yet */ + return -EINVAL; + } + return put_user(result, (unsigned long __user *)value); } -static int -cy_tiocmget(struct tty_struct *tty, struct file *file) +static int cy_tiocmget(struct tty_struct *tty, struct file *file) { - struct cyclades_port * info = (struct cyclades_port *)tty->driver_data; - int card,chip,channel,index; - void __iomem *base_addr; - unsigned long flags; - unsigned char status; - unsigned long lstatus; - unsigned int result; - struct FIRM_ID __iomem *firm_id; - struct ZFW_CTRL __iomem *zfw_ctrl; - struct BOARD_CTRL __iomem *board_ctrl; - struct CH_CTRL __iomem *ch_ctrl; - - if (serial_paranoia_check(info, tty->name, __FUNCTION__)) - return -ENODEV; - - card = info->card; - channel = (info->line) - (cy_card[card].first_line); - if (!IS_CYC_Z(cy_card[card])) { - chip = channel>>2; - channel &= 0x03; - index = cy_card[card].bus_index; - base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<driver_data; + int card, chip, channel, index; + void __iomem *base_addr; + unsigned long flags; + unsigned char status; + unsigned long lstatus; + unsigned int result; + struct FIRM_ID __iomem *firm_id; + struct ZFW_CTRL __iomem *zfw_ctrl; + struct BOARD_CTRL __iomem *board_ctrl; + struct CH_CTRL __iomem *ch_ctrl; + + if (serial_paranoia_check(info, tty->name, __FUNCTION__)) + return -ENODEV; - CY_LOCK(info, flags); - cy_writeb(base_addr+(CyCAR<card; + channel = (info->line) - (cy_card[card].first_line); + if (!IS_CYC_Z(cy_card[card])) { + chip = channel >> 2; + channel &= 0x03; + index = cy_card[card].bus_index; + base_addr = + cy_card[card].base_addr + (cy_chip_offset[chip] << index); - if (info->rtsdtr_inv) { - result = ((status & CyRTS) ? TIOCM_DTR : 0) - | ((status & CyDTR) ? TIOCM_RTS : 0); + CY_LOCK(info, flags); + cy_writeb(base_addr + (CyCAR << index), (u_char) channel); + status = cy_readb(base_addr + (CyMSVR1 << index)); + status |= cy_readb(base_addr + (CyMSVR2 << index)); + CY_UNLOCK(info, flags); + + if (info->rtsdtr_inv) { + result = ((status & CyRTS) ? TIOCM_DTR : 0) | + ((status & CyDTR) ? TIOCM_RTS : 0); + } else { + result = ((status & CyRTS) ? TIOCM_RTS : 0) | + ((status & CyDTR) ? TIOCM_DTR : 0); + } + result |= ((status & CyDCD) ? TIOCM_CAR : 0) | + ((status & CyRI) ? TIOCM_RNG : 0) | + ((status & CyDSR) ? TIOCM_DSR : 0) | + ((status & CyCTS) ? TIOCM_CTS : 0); } else { - result = ((status & CyRTS) ? TIOCM_RTS : 0) - | ((status & CyDTR) ? TIOCM_DTR : 0); - } - result |= ((status & CyDCD) ? TIOCM_CAR : 0) - | ((status & CyRI) ? TIOCM_RNG : 0) - | ((status & CyDSR) ? TIOCM_DSR : 0) - | ((status & CyCTS) ? TIOCM_CTS : 0); - } else { - base_addr = cy_card[card].base_addr; - - if (cy_card[card].num_chips != -1){ - return -EINVAL; - } + base_addr = cy_card[card].base_addr; - firm_id = cy_card[card].base_addr + ID_ADDRESS; - if (ISZLOADED(cy_card[card])) { - zfw_ctrl = cy_card[card].base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff); - board_ctrl = &zfw_ctrl->board_ctrl; - ch_ctrl = zfw_ctrl->ch_ctrl; - lstatus = cy_readl(&ch_ctrl[channel].rs_status); - result = ((lstatus & C_RS_RTS) ? TIOCM_RTS : 0) - | ((lstatus & C_RS_DTR) ? TIOCM_DTR : 0) - | ((lstatus & C_RS_DCD) ? TIOCM_CAR : 0) - | ((lstatus & C_RS_RI) ? TIOCM_RNG : 0) - | ((lstatus & C_RS_DSR) ? TIOCM_DSR : 0) - | ((lstatus & C_RS_CTS) ? TIOCM_CTS : 0); - }else{ - result = 0; - return -ENODEV; - } + if (cy_card[card].num_chips != -1) { + return -EINVAL; + } - } - return result; -} /* cy_tiomget */ + firm_id = cy_card[card].base_addr + ID_ADDRESS; + if (ISZLOADED(cy_card[card])) { + zfw_ctrl = cy_card[card].base_addr + + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff); + board_ctrl = &zfw_ctrl->board_ctrl; + ch_ctrl = zfw_ctrl->ch_ctrl; + lstatus = cy_readl(&ch_ctrl[channel].rs_status); + result = ((lstatus & C_RS_RTS) ? TIOCM_RTS : 0) | + ((lstatus & C_RS_DTR) ? TIOCM_DTR : 0) | + ((lstatus & C_RS_DCD) ? TIOCM_CAR : 0) | + ((lstatus & C_RS_RI) ? TIOCM_RNG : 0) | + ((lstatus & C_RS_DSR) ? TIOCM_DSR : 0) | + ((lstatus & C_RS_CTS) ? TIOCM_CTS : 0); + } else { + result = 0; + return -ENODEV; + } + } + return result; +} /* cy_tiomget */ static int cy_tiocmset(struct tty_struct *tty, struct file *file, - unsigned int set, unsigned int clear) + unsigned int set, unsigned int clear) { - struct cyclades_port * info = (struct cyclades_port *)tty->driver_data; - int card,chip,channel,index; - void __iomem *base_addr; - unsigned long flags; - struct FIRM_ID __iomem *firm_id; - struct ZFW_CTRL __iomem *zfw_ctrl; - struct BOARD_CTRL __iomem *board_ctrl; - struct CH_CTRL __iomem *ch_ctrl; - int retval; - - if (serial_paranoia_check(info, tty->name, __FUNCTION__)) - return -ENODEV; - - card = info->card; - channel = (info->line) - (cy_card[card].first_line); - if (!IS_CYC_Z(cy_card[card])) { - chip = channel>>2; - channel &= 0x03; - index = cy_card[card].bus_index; - base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<rtsdtr_inv) { - cy_writeb(base_addr+(CyMSVR2<rtsdtr_inv) { - cy_writeb(base_addr+(CyMSVR2<rtsdtr_inv) { - cy_writeb(base_addr+(CyMSVR1<driver_data; + int card, chip, channel, index; + void __iomem *base_addr; + unsigned long flags; + struct FIRM_ID __iomem *firm_id; + struct ZFW_CTRL __iomem *zfw_ctrl; + struct BOARD_CTRL __iomem *board_ctrl; + struct CH_CTRL __iomem *ch_ctrl; + int retval; + + if (serial_paranoia_check(info, tty->name, __FUNCTION__)) + return -ENODEV; + + card = info->card; + channel = (info->line) - (cy_card[card].first_line); + if (!IS_CYC_Z(cy_card[card])) { + chip = channel >> 2; + channel &= 0x03; + index = cy_card[card].bus_index; + base_addr = + cy_card[card].base_addr + (cy_chip_offset[chip] << index); + + if (set & TIOCM_RTS) { + CY_LOCK(info, flags); + cy_writeb(base_addr + (CyCAR << index), + (u_char) channel); + if (info->rtsdtr_inv) { + cy_writeb(base_addr + (CyMSVR2 << index), + CyDTR); + } else { + cy_writeb(base_addr + (CyMSVR1 << index), + CyRTS); + } + CY_UNLOCK(info, flags); + } + if (clear & TIOCM_RTS) { + CY_LOCK(info, flags); + cy_writeb(base_addr + (CyCAR << index), + (u_char) channel); + if (info->rtsdtr_inv) { + cy_writeb(base_addr + (CyMSVR2 << index), + ~CyDTR); + } else { + cy_writeb(base_addr + (CyMSVR1 << index), + ~CyRTS); + } + CY_UNLOCK(info, flags); + } + if (set & TIOCM_DTR) { + CY_LOCK(info, flags); + cy_writeb(base_addr + (CyCAR << index), + (u_char) channel); + if (info->rtsdtr_inv) { + cy_writeb(base_addr + (CyMSVR1 << index), + CyRTS); + } else { + cy_writeb(base_addr + (CyMSVR2 << index), + CyDTR); + } #ifdef CY_DEBUG_DTR - printk("cyc:set_modem_info raising DTR\n"); - printk(" status: 0x%x, 0x%x\n", - cy_readb(base_addr+(CyMSVR1<rtsdtr_inv) { - cy_writeb(base_addr+(CyMSVR1<rtsdtr_inv) { + cy_writeb(base_addr + (CyMSVR1 << index), + ~CyRTS); + } else { + cy_writeb(base_addr + (CyMSVR2 << index), + ~CyDTR); + } #ifdef CY_DEBUG_DTR - printk("cyc:set_modem_info dropping DTR\n"); - printk(" status: 0x%x, 0x%x\n", - cy_readb(base_addr+(CyMSVR1<zfwctrl_addr) & 0xfffff); - board_ctrl = &zfw_ctrl->board_ctrl; - ch_ctrl = zfw_ctrl->ch_ctrl; - - if (set & TIOCM_RTS){ - CY_LOCK(info, flags); - cy_writel(&ch_ctrl[channel].rs_control, - cy_readl(&ch_ctrl[channel].rs_control) | C_RS_RTS); - CY_UNLOCK(info, flags); - } - if (clear & TIOCM_RTS) { - CY_LOCK(info, flags); - cy_writel(&ch_ctrl[channel].rs_control, - cy_readl(&ch_ctrl[channel].rs_control) & ~C_RS_RTS); - CY_UNLOCK(info, flags); - } - if (set & TIOCM_DTR){ - CY_LOCK(info, flags); - cy_writel(&ch_ctrl[channel].rs_control, - cy_readl(&ch_ctrl[channel].rs_control) | C_RS_DTR); + CY_UNLOCK(info, flags); + } + } else { + base_addr = cy_card[card].base_addr; + + firm_id = cy_card[card].base_addr + ID_ADDRESS; + if (ISZLOADED(cy_card[card])) { + zfw_ctrl = cy_card[card].base_addr + + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff); + board_ctrl = &zfw_ctrl->board_ctrl; + ch_ctrl = zfw_ctrl->ch_ctrl; + + if (set & TIOCM_RTS) { + CY_LOCK(info, flags); + cy_writel(&ch_ctrl[channel].rs_control, + cy_readl(&ch_ctrl[channel]. + rs_control) | C_RS_RTS); + CY_UNLOCK(info, flags); + } + if (clear & TIOCM_RTS) { + CY_LOCK(info, flags); + cy_writel(&ch_ctrl[channel].rs_control, + cy_readl(&ch_ctrl[channel]. + rs_control) & ~C_RS_RTS); + CY_UNLOCK(info, flags); + } + if (set & TIOCM_DTR) { + CY_LOCK(info, flags); + cy_writel(&ch_ctrl[channel].rs_control, + cy_readl(&ch_ctrl[channel]. + rs_control) | C_RS_DTR); #ifdef CY_DEBUG_DTR - printk("cyc:set_modem_info raising Z DTR\n"); + printk("cyc:set_modem_info raising Z DTR\n"); #endif - CY_UNLOCK(info, flags); - } - if (clear & TIOCM_DTR) { - CY_LOCK(info, flags); - cy_writel(&ch_ctrl[channel].rs_control, - cy_readl(&ch_ctrl[channel].rs_control) & ~C_RS_DTR); + CY_UNLOCK(info, flags); + } + if (clear & TIOCM_DTR) { + CY_LOCK(info, flags); + cy_writel(&ch_ctrl[channel].rs_control, + cy_readl(&ch_ctrl[channel]. + rs_control) & ~C_RS_DTR); #ifdef CY_DEBUG_DTR - printk("cyc:set_modem_info clearing Z DTR\n"); + printk("cyc:set_modem_info clearing Z DTR\n"); #endif - CY_UNLOCK(info, flags); - } - }else{ - return -ENODEV; - } - CY_LOCK(info, flags); - retval = cyz_issue_cmd(&cy_card[info->card], - channel, C_CM_IOCTLM,0L); - if (retval != 0){ - printk("cyc:set_modem_info retval on ttyC%d was %x\n", - info->line, retval); + CY_UNLOCK(info, flags); + } + } else { + return -ENODEV; + } + CY_LOCK(info, flags); + retval = cyz_issue_cmd(&cy_card[info->card], + channel, C_CM_IOCTLM, 0L); + if (retval != 0) { + printk("cyc:set_modem_info retval on ttyC%d was %x\n", + info->line, retval); + } + CY_UNLOCK(info, flags); } - CY_UNLOCK(info, flags); - } - return 0; -} /* cy_tiocmset */ + return 0; +} /* cy_tiocmset */ /* * cy_break() --- routine which turns the break handling on or off */ -static void -cy_break(struct tty_struct *tty, int break_state) +static void cy_break(struct tty_struct *tty, int break_state) { - struct cyclades_port * info = (struct cyclades_port *)tty->driver_data; - unsigned long flags; - - if (serial_paranoia_check(info, tty->name, "cy_break")) - return; - - CY_LOCK(info, flags); - if (!IS_CYC_Z(cy_card[info->card])) { - /* Let the transmit ISR take care of this (since it - requires stuffing characters into the output stream). - */ - if (break_state == -1) { - if (!info->breakon) { - info->breakon = 1; - if (!info->xmit_cnt) { - CY_UNLOCK(info, flags); - start_xmit(info); - CY_LOCK(info, flags); + struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; + unsigned long flags; + + if (serial_paranoia_check(info, tty->name, "cy_break")) + return; + + CY_LOCK(info, flags); + if (!IS_CYC_Z(cy_card[info->card])) { + /* Let the transmit ISR take care of this (since it + requires stuffing characters into the output stream). + */ + if (break_state == -1) { + if (!info->breakon) { + info->breakon = 1; + if (!info->xmit_cnt) { + CY_UNLOCK(info, flags); + start_xmit(info); + CY_LOCK(info, flags); + } + } + } else { + if (!info->breakoff) { + info->breakoff = 1; + if (!info->xmit_cnt) { + CY_UNLOCK(info, flags); + start_xmit(info); + CY_LOCK(info, flags); + } + } } - } } else { - if (!info->breakoff) { - info->breakoff = 1; - if (!info->xmit_cnt) { - CY_UNLOCK(info, flags); - start_xmit(info); - CY_LOCK(info, flags); + int retval; + + if (break_state == -1) { + retval = cyz_issue_cmd(&cy_card[info->card], + info->line - cy_card[info->card].first_line, + C_CM_SET_BREAK, 0L); + if (retval != 0) { + printk("cyc:cy_break (set) retval on ttyC%d " + "was %x\n", info->line, retval); + } + } else { + retval = cyz_issue_cmd(&cy_card[info->card], + info->line - cy_card[info->card].first_line, + C_CM_CLR_BREAK, 0L); + if (retval != 0) { + printk("cyc:cy_break (clr) retval on ttyC%d " + "was %x\n", info->line, retval); + } } - } } - } else { - int retval; - - if (break_state == -1) { - retval = cyz_issue_cmd(&cy_card[info->card], - (info->line) - (cy_card[info->card].first_line), - C_CM_SET_BREAK, 0L); - if (retval != 0) { - printk("cyc:cy_break (set) retval on ttyC%d was %x\n", - info->line, retval); - } - } else { - retval = cyz_issue_cmd(&cy_card[info->card], - (info->line) - (cy_card[info->card].first_line), - C_CM_CLR_BREAK, 0L); - if (retval != 0) { - printk("cyc:cy_break (clr) retval on ttyC%d was %x\n", - info->line, retval); - } - } - } - CY_UNLOCK(info, flags); -} /* cy_break */ + CY_UNLOCK(info, flags); +} /* cy_break */ static int -get_mon_info(struct cyclades_port * info, struct cyclades_monitor __user * mon) +get_mon_info(struct cyclades_port *info, struct cyclades_monitor __user * mon) { - if(copy_to_user(mon, &info->mon, sizeof(struct cyclades_monitor))) - return -EFAULT; - info->mon.int_count = 0; - info->mon.char_count = 0; - info->mon.char_max = 0; - info->mon.char_last = 0; - return 0; -}/* get_mon_info */ - + if (copy_to_user(mon, &info->mon, sizeof(struct cyclades_monitor))) + return -EFAULT; + info->mon.int_count = 0; + info->mon.char_count = 0; + info->mon.char_max = 0; + info->mon.char_last = 0; + return 0; +} /* get_mon_info */ -static int -set_threshold(struct cyclades_port * info, unsigned long value) +static int set_threshold(struct cyclades_port *info, unsigned long value) { - void __iomem *base_addr; - int card,channel,chip,index; - unsigned long flags; - - card = info->card; - channel = info->line - cy_card[card].first_line; - if (!IS_CYC_Z(cy_card[card])) { - chip = channel>>2; - channel &= 0x03; - index = cy_card[card].bus_index; - base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<cor3 &= ~CyREC_FIFO; - info->cor3 |= value & CyREC_FIFO; + void __iomem *base_addr; + int card, channel, chip, index; + unsigned long flags; - CY_LOCK(info, flags); - cy_writeb(base_addr+(CyCOR3<cor3); - cyy_issue_cmd(base_addr,CyCOR_CHANGE|CyCOR3ch,index); - CY_UNLOCK(info, flags); - } else { - // Nothing to do! - } - return 0; -}/* set_threshold */ + card = info->card; + channel = info->line - cy_card[card].first_line; + if (!IS_CYC_Z(cy_card[card])) { + chip = channel >> 2; + channel &= 0x03; + index = cy_card[card].bus_index; + base_addr = + cy_card[card].base_addr + (cy_chip_offset[chip] << index); + info->cor3 &= ~CyREC_FIFO; + info->cor3 |= value & CyREC_FIFO; -static int -get_threshold(struct cyclades_port * info, unsigned long __user *value) -{ - void __iomem *base_addr; - int card,channel,chip,index; - unsigned long tmp; - - card = info->card; - channel = info->line - cy_card[card].first_line; - if (!IS_CYC_Z(cy_card[card])) { - chip = channel>>2; - channel &= 0x03; - index = cy_card[card].bus_index; - base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<cor3); + cyy_issue_cmd(base_addr, CyCOR_CHANGE | CyCOR3ch, index); + CY_UNLOCK(info, flags); + } else { + /* Nothing to do! */ + } return 0; - } -}/* get_threshold */ - +} /* set_threshold */ static int -set_default_threshold(struct cyclades_port * info, unsigned long value) +get_threshold(struct cyclades_port *info, unsigned long __user * value) { - info->default_threshold = value & 0x0f; - return 0; -}/* set_default_threshold */ + void __iomem *base_addr; + int card, channel, chip, index; + unsigned long tmp; + card = info->card; + channel = info->line - cy_card[card].first_line; + if (!IS_CYC_Z(cy_card[card])) { + chip = channel >> 2; + channel &= 0x03; + index = cy_card[card].bus_index; + base_addr = + cy_card[card].base_addr + (cy_chip_offset[chip] << index); + + tmp = cy_readb(base_addr + (CyCOR3 << index)) & CyREC_FIFO; + return put_user(tmp, value); + } else { + /* Nothing to do! */ + return 0; + } +} /* get_threshold */ static int -get_default_threshold(struct cyclades_port * info, unsigned long __user *value) +set_default_threshold(struct cyclades_port *info, unsigned long value) { - return put_user(info->default_threshold,value); -}/* get_default_threshold */ - + info->default_threshold = value & 0x0f; + return 0; +} /* set_default_threshold */ static int -set_timeout(struct cyclades_port * info, unsigned long value) +get_default_threshold(struct cyclades_port *info, unsigned long __user * value) { - void __iomem *base_addr; - int card,channel,chip,index; - unsigned long flags; - - card = info->card; - channel = info->line - cy_card[card].first_line; - if (!IS_CYC_Z(cy_card[card])) { - chip = channel>>2; - channel &= 0x03; - index = cy_card[card].bus_index; - base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<default_threshold, value); +} /* get_default_threshold */ - CY_LOCK(info, flags); - cy_writeb(base_addr+(CyRTPR<card; + channel = info->line - cy_card[card].first_line; + if (!IS_CYC_Z(cy_card[card])) { + chip = channel >> 2; + channel &= 0x03; + index = cy_card[card].bus_index; + base_addr = + cy_card[card].base_addr + (cy_chip_offset[chip] << index); -static int -get_timeout(struct cyclades_port * info, unsigned long __user *value) -{ - void __iomem *base_addr; - int card,channel,chip,index; - unsigned long tmp; - - card = info->card; - channel = info->line - cy_card[card].first_line; - if (!IS_CYC_Z(cy_card[card])) { - chip = channel>>2; - channel &= 0x03; - index = cy_card[card].bus_index; - base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<default_timeout = value & 0xff; - return 0; -}/* set_default_timeout */ + void __iomem *base_addr; + int card, channel, chip, index; + unsigned long tmp; + + card = info->card; + channel = info->line - cy_card[card].first_line; + if (!IS_CYC_Z(cy_card[card])) { + chip = channel >> 2; + channel &= 0x03; + index = cy_card[card].bus_index; + base_addr = + cy_card[card].base_addr + (cy_chip_offset[chip] << index); + + tmp = cy_readb(base_addr + (CyRTPR << index)); + return put_user(tmp, value); + } else { + /* Nothing to do! */ + return 0; + } +} /* get_timeout */ +static int set_default_timeout(struct cyclades_port *info, unsigned long value) +{ + info->default_timeout = value & 0xff; + return 0; +} /* set_default_timeout */ static int -get_default_timeout(struct cyclades_port * info, unsigned long __user *value) +get_default_timeout(struct cyclades_port *info, unsigned long __user * value) { - return put_user(info->default_timeout,value); -}/* get_default_timeout */ + return put_user(info->default_timeout, value); +} /* get_default_timeout */ /* * This routine allows the tty driver to implement device- @@ -3914,184 +4015,193 @@ get_default_timeout(struct cyclades_port * info, unsigned long __user *value) * not recognized by the driver, it should return ENOIOCTLCMD. */ static int -cy_ioctl(struct tty_struct *tty, struct file * file, - unsigned int cmd, unsigned long arg) +cy_ioctl(struct tty_struct *tty, struct file *file, + unsigned int cmd, unsigned long arg) { - struct cyclades_port * info = (struct cyclades_port *)tty->driver_data; - struct cyclades_icount cprev, cnow; /* kernel counter temps */ - struct serial_icounter_struct __user *p_cuser; /* user space */ - int ret_val = 0; - unsigned long flags; - void __user *argp = (void __user *)arg; - - if (serial_paranoia_check(info, tty->name, "cy_ioctl")) - return -ENODEV; + struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; + struct cyclades_icount cprev, cnow; /* kernel counter temps */ + struct serial_icounter_struct __user *p_cuser; /* user space */ + int ret_val = 0; + unsigned long flags; + void __user *argp = (void __user *)arg; + + if (serial_paranoia_check(info, tty->name, "cy_ioctl")) + return -ENODEV; #ifdef CY_DEBUG_OTHER - printk("cyc:cy_ioctl ttyC%d, cmd = %x arg = %lx\n", - info->line, cmd, arg); /* */ + printk("cyc:cy_ioctl ttyC%d, cmd = %x arg = %lx\n", info->line, cmd, arg); /* */ #endif - switch (cmd) { - case CYGETMON: - ret_val = get_mon_info(info, argp); - break; - case CYGETTHRESH: - ret_val = get_threshold(info, argp); - break; - case CYSETTHRESH: - ret_val = set_threshold(info, arg); - break; - case CYGETDEFTHRESH: - ret_val = get_default_threshold(info, argp); - break; - case CYSETDEFTHRESH: - ret_val = set_default_threshold(info, arg); - break; - case CYGETTIMEOUT: - ret_val = get_timeout(info, argp); - break; - case CYSETTIMEOUT: - ret_val = set_timeout(info, arg); - break; - case CYGETDEFTIMEOUT: - ret_val = get_default_timeout(info, argp); - break; - case CYSETDEFTIMEOUT: - ret_val = set_default_timeout(info, arg); - break; + switch (cmd) { + case CYGETMON: + ret_val = get_mon_info(info, argp); + break; + case CYGETTHRESH: + ret_val = get_threshold(info, argp); + break; + case CYSETTHRESH: + ret_val = set_threshold(info, arg); + break; + case CYGETDEFTHRESH: + ret_val = get_default_threshold(info, argp); + break; + case CYSETDEFTHRESH: + ret_val = set_default_threshold(info, arg); + break; + case CYGETTIMEOUT: + ret_val = get_timeout(info, argp); + break; + case CYSETTIMEOUT: + ret_val = set_timeout(info, arg); + break; + case CYGETDEFTIMEOUT: + ret_val = get_default_timeout(info, argp); + break; + case CYSETDEFTIMEOUT: + ret_val = set_default_timeout(info, arg); + break; case CYSETRFLOW: - info->rflow = (int)arg; - ret_val = 0; - break; + info->rflow = (int)arg; + ret_val = 0; + break; case CYGETRFLOW: - ret_val = info->rflow; - break; + ret_val = info->rflow; + break; case CYSETRTSDTR_INV: - info->rtsdtr_inv = (int)arg; - ret_val = 0; - break; + info->rtsdtr_inv = (int)arg; + ret_val = 0; + break; case CYGETRTSDTR_INV: - ret_val = info->rtsdtr_inv; - break; + ret_val = info->rtsdtr_inv; + break; case CYGETCARDINFO: - if (copy_to_user(argp, &cy_card[info->card], - sizeof (struct cyclades_card))) { - ret_val = -EFAULT; + if (copy_to_user(argp, &cy_card[info->card], + sizeof(struct cyclades_card))) { + ret_val = -EFAULT; + break; + } + ret_val = 0; break; - } - ret_val = 0; - break; case CYGETCD1400VER: - ret_val = info->chip_rev; - break; + ret_val = info->chip_rev; + break; #ifndef CONFIG_CYZ_INTR case CYZSETPOLLCYCLE: - cyz_polling_cycle = (arg * HZ) / 1000; - ret_val = 0; - break; + cyz_polling_cycle = (arg * HZ) / 1000; + ret_val = 0; + break; case CYZGETPOLLCYCLE: - ret_val = (cyz_polling_cycle * 1000) / HZ; - break; -#endif /* CONFIG_CYZ_INTR */ + ret_val = (cyz_polling_cycle * 1000) / HZ; + break; +#endif /* CONFIG_CYZ_INTR */ case CYSETWAIT: - info->closing_wait = (unsigned short)arg * HZ/100; - ret_val = 0; - break; + info->closing_wait = (unsigned short)arg *HZ / 100; + ret_val = 0; + break; case CYGETWAIT: - ret_val = info->closing_wait / (HZ/100); - break; - case TIOCGSERIAL: - ret_val = get_serial_info(info, argp); - break; - case TIOCSSERIAL: - ret_val = set_serial_info(info, argp); - break; - case TIOCSERGETLSR: /* Get line status register */ - ret_val = get_lsr_info(info, argp); - break; - /* - * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change - * - mask passed in arg for lines of interest - * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking) - * Caller should use TIOCGICOUNT to see which one it was - */ + ret_val = info->closing_wait / (HZ / 100); + break; + case TIOCGSERIAL: + ret_val = get_serial_info(info, argp); + break; + case TIOCSSERIAL: + ret_val = set_serial_info(info, argp); + break; + case TIOCSERGETLSR: /* Get line status register */ + ret_val = get_lsr_info(info, argp); + break; + /* + * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change + * - mask passed in arg for lines of interest + * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking) + * Caller should use TIOCGICOUNT to see which one it was + */ case TIOCMIWAIT: - CY_LOCK(info, flags); - /* note the counters on entry */ - cprev = info->icount; - CY_UNLOCK(info, flags); - while (1) { - interruptible_sleep_on(&info->delta_msr_wait); - /* see if a signal did it */ - if (signal_pending(current)) { - return -ERESTARTSYS; - } - CY_LOCK(info, flags); - cnow = info->icount; /* atomic copy */ + /* note the counters on entry */ + cprev = info->icount; CY_UNLOCK(info, flags); + while (1) { + interruptible_sleep_on(&info->delta_msr_wait); + /* see if a signal did it */ + if (signal_pending(current)) { + return -ERESTARTSYS; + } - if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && - cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) { - return -EIO; /* no change => error */ - } - if ( ((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || - ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || - ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || - ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) { - return 0; - } - cprev = cnow; - } - /* NOTREACHED */ + CY_LOCK(info, flags); + cnow = info->icount; /* atomic copy */ + CY_UNLOCK(info, flags); - /* - * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) - * Return: write counters to the user passed counter struct - * NB: both 1->0 and 0->1 transitions are counted except for - * RI where only 0->1 is counted. - */ + if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && + cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) { + return -EIO; /* no change => error */ + } + if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || + ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || + ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || + ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) { + return 0; + } + cprev = cnow; + } + /* NOTREACHED */ + + /* + * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) + * Return: write counters to the user passed counter struct + * NB: both 1->0 and 0->1 transitions are counted except for + * RI where only 0->1 is counted. + */ case TIOCGICOUNT: - CY_LOCK(info, flags); - cnow = info->icount; - CY_UNLOCK(info, flags); - p_cuser = argp; - ret_val = put_user(cnow.cts, &p_cuser->cts); - if (ret_val) return ret_val; - ret_val = put_user(cnow.dsr, &p_cuser->dsr); - if (ret_val) return ret_val; - ret_val = put_user(cnow.rng, &p_cuser->rng); - if (ret_val) return ret_val; - ret_val = put_user(cnow.dcd, &p_cuser->dcd); - if (ret_val) return ret_val; - ret_val = put_user(cnow.rx, &p_cuser->rx); - if (ret_val) return ret_val; - ret_val = put_user(cnow.tx, &p_cuser->tx); - if (ret_val) return ret_val; - ret_val = put_user(cnow.frame, &p_cuser->frame); - if (ret_val) return ret_val; - ret_val = put_user(cnow.overrun, &p_cuser->overrun); - if (ret_val) return ret_val; - ret_val = put_user(cnow.parity, &p_cuser->parity); - if (ret_val) return ret_val; - ret_val = put_user(cnow.brk, &p_cuser->brk); - if (ret_val) return ret_val; - ret_val = put_user(cnow.buf_overrun, &p_cuser->buf_overrun); - if (ret_val) return ret_val; - ret_val = 0; - break; - default: - ret_val = -ENOIOCTLCMD; - } + CY_LOCK(info, flags); + cnow = info->icount; + CY_UNLOCK(info, flags); + p_cuser = argp; + ret_val = put_user(cnow.cts, &p_cuser->cts); + if (ret_val) + return ret_val; + ret_val = put_user(cnow.dsr, &p_cuser->dsr); + if (ret_val) + return ret_val; + ret_val = put_user(cnow.rng, &p_cuser->rng); + if (ret_val) + return ret_val; + ret_val = put_user(cnow.dcd, &p_cuser->dcd); + if (ret_val) + return ret_val; + ret_val = put_user(cnow.rx, &p_cuser->rx); + if (ret_val) + return ret_val; + ret_val = put_user(cnow.tx, &p_cuser->tx); + if (ret_val) + return ret_val; + ret_val = put_user(cnow.frame, &p_cuser->frame); + if (ret_val) + return ret_val; + ret_val = put_user(cnow.overrun, &p_cuser->overrun); + if (ret_val) + return ret_val; + ret_val = put_user(cnow.parity, &p_cuser->parity); + if (ret_val) + return ret_val; + ret_val = put_user(cnow.brk, &p_cuser->brk); + if (ret_val) + return ret_val; + ret_val = put_user(cnow.buf_overrun, &p_cuser->buf_overrun); + if (ret_val) + return ret_val; + ret_val = 0; + break; + default: + ret_val = -ENOIOCTLCMD; + } #ifdef CY_DEBUG_OTHER - printk(" cyc:cy_ioctl done\n"); + printk(" cyc:cy_ioctl done\n"); #endif - return ret_val; -} /* cy_ioctl */ - + return ret_val; +} /* cy_ioctl */ /* * This routine allows the tty driver to be notified when @@ -4099,66 +4209,64 @@ cy_ioctl(struct tty_struct *tty, struct file * file, * well-designed tty driver should be prepared to accept the case * where old == NULL, and try to do something rational. */ -static void -cy_set_termios(struct tty_struct *tty, struct termios * old_termios) +static void cy_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { - struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; + struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; #ifdef CY_DEBUG_OTHER - printk("cyc:cy_set_termios ttyC%d\n", info->line); + printk("cyc:cy_set_termios ttyC%d\n", info->line); #endif - if ((tty->termios->c_cflag == old_termios->c_cflag) && - ((tty->termios->c_iflag & (IXON|IXANY)) == - (old_termios->c_iflag & (IXON|IXANY)))) - return; - set_line_char(info); - - if ((old_termios->c_cflag & CRTSCTS) && - !(tty->termios->c_cflag & CRTSCTS)) { - tty->hw_stopped = 0; - cy_start(tty); - } + if (tty->termios->c_cflag == old_termios->c_cflag && + (tty->termios->c_iflag & (IXON | IXANY)) == + (old_termios->c_iflag & (IXON | IXANY))) + return; + set_line_char(info); + + if ((old_termios->c_cflag & CRTSCTS) && + !(tty->termios->c_cflag & CRTSCTS)) { + tty->hw_stopped = 0; + cy_start(tty); + } #if 0 - /* - * No need to wake up processes in open wait, since they - * sample the CLOCAL flag once, and don't recheck it. - * XXX It's not clear whether the current behavior is correct - * or not. Hence, this may change..... - */ - if (!(old_termios->c_cflag & CLOCAL) && - (tty->termios->c_cflag & CLOCAL)) - wake_up_interruptible(&info->open_wait); + /* + * No need to wake up processes in open wait, since they + * sample the CLOCAL flag once, and don't recheck it. + * XXX It's not clear whether the current behavior is correct + * or not. Hence, this may change..... + */ + if (!(old_termios->c_cflag & CLOCAL) && + (tty->termios->c_cflag & CLOCAL)) + wake_up_interruptible(&info->open_wait); #endif - - return; -} /* cy_set_termios */ +} /* cy_set_termios */ /* This function is used to send a high-priority XON/XOFF character to the device. */ -static void -cy_send_xchar (struct tty_struct *tty, char ch) +static void cy_send_xchar(struct tty_struct *tty, char ch) { - struct cyclades_port *info = (struct cyclades_port *) tty->driver_data; + struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; int card, channel; - if (serial_paranoia_check (info, tty->name, "cy_send_xchar")) + if (serial_paranoia_check(info, tty->name, "cy_send_xchar")) return; - info->x_char = ch; + info->x_char = ch; if (ch) - cy_start (tty); + cy_start(tty); card = info->card; channel = info->line - cy_card[card].first_line; - if (IS_CYC_Z (cy_card[card])) { - if (ch == STOP_CHAR (tty)) - cyz_issue_cmd (&cy_card[card], channel, C_CM_SENDXOFF, 0L); - else if (ch == START_CHAR (tty)) - cyz_issue_cmd (&cy_card[card], channel, C_CM_SENDXON, 0L); + if (IS_CYC_Z(cy_card[card])) { + if (ch == STOP_CHAR(tty)) + cyz_issue_cmd(&cy_card[card], channel, C_CM_SENDXOFF, + 0L); + else if (ch == START_CHAR(tty)) + cyz_issue_cmd(&cy_card[card], channel, C_CM_SENDXON, + 0L); } } @@ -4166,260 +4274,248 @@ cy_send_xchar (struct tty_struct *tty, char ch) that incoming characters should be throttled because the input buffers are close to full. */ -static void -cy_throttle(struct tty_struct * tty) +static void cy_throttle(struct tty_struct *tty) { - struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; - unsigned long flags; - void __iomem *base_addr; - int card,chip,channel,index; + struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; + unsigned long flags; + void __iomem *base_addr; + int card, chip, channel, index; #ifdef CY_DEBUG_THROTTLE - char buf[64]; + char buf[64]; - printk("cyc:throttle %s: %d....ttyC%d\n", - tty_name(tty, buf), - tty->ldisc.chars_in_buffer(tty), info->line); + printk("cyc:throttle %s: %d....ttyC%d\n", tty_name(tty, buf), + tty->ldisc.chars_in_buffer(tty), info->line); #endif - if (serial_paranoia_check(info, tty->name, "cy_throttle")){ - return; - } - - card = info->card; - - if (I_IXOFF(tty)) { - if (!IS_CYC_Z (cy_card[card])) - cy_send_xchar (tty, STOP_CHAR (tty)); - else - info->throttle = 1; - } - - if (tty->termios->c_cflag & CRTSCTS) { - channel = info->line - cy_card[card].first_line; - if (!IS_CYC_Z(cy_card[card])) { - chip = channel>>2; - channel &= 0x03; - index = cy_card[card].bus_index; - base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<rtsdtr_inv) { - cy_writeb(base_addr+(CyMSVR2<throttle = 1; - } - } + if (serial_paranoia_check(info, tty->name, "cy_throttle")) { + return; + } + + card = info->card; - return; -} /* cy_throttle */ + if (I_IXOFF(tty)) { + if (!IS_CYC_Z(cy_card[card])) + cy_send_xchar(tty, STOP_CHAR(tty)); + else + info->throttle = 1; + } + if (tty->termios->c_cflag & CRTSCTS) { + channel = info->line - cy_card[card].first_line; + if (!IS_CYC_Z(cy_card[card])) { + chip = channel >> 2; + channel &= 0x03; + index = cy_card[card].bus_index; + base_addr = cy_card[card].base_addr + + (cy_chip_offset[chip] << index); + + CY_LOCK(info, flags); + cy_writeb(base_addr + (CyCAR << index), + (u_char) channel); + if (info->rtsdtr_inv) { + cy_writeb(base_addr + (CyMSVR2 << index), + ~CyDTR); + } else { + cy_writeb(base_addr + (CyMSVR1 << index), + ~CyRTS); + } + CY_UNLOCK(info, flags); + } else { + info->throttle = 1; + } + } +} /* cy_throttle */ /* * This routine notifies the tty driver that it should signal * that characters can now be sent to the tty without fear of * overrunning the input buffers of the line disciplines. */ -static void -cy_unthrottle(struct tty_struct * tty) +static void cy_unthrottle(struct tty_struct *tty) { - struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; - unsigned long flags; - void __iomem *base_addr; - int card,chip,channel,index; + struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; + unsigned long flags; + void __iomem *base_addr; + int card, chip, channel, index; #ifdef CY_DEBUG_THROTTLE - char buf[64]; - - printk("cyc:unthrottle %s: %d....ttyC%d\n", - tty_name(tty, buf), - tty->ldisc.chars_in_buffer(tty), info->line); -#endif + char buf[64]; - if (serial_paranoia_check(info, tty->name, "cy_unthrottle")){ - return; - } + printk("cyc:unthrottle %s: %d....ttyC%d\n", tty_name(tty, buf), + tty->ldisc.chars_in_buffer(tty), info->line); +#endif - if (I_IXOFF(tty)) { - if (info->x_char) - info->x_char = 0; - else - cy_send_xchar (tty, START_CHAR (tty)); - } - - if (tty->termios->c_cflag & CRTSCTS) { - card = info->card; - channel = info->line - cy_card[card].first_line; - if (!IS_CYC_Z(cy_card[card])) { - chip = channel>>2; - channel &= 0x03; - index = cy_card[card].bus_index; - base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<rtsdtr_inv) { - cy_writeb(base_addr+(CyMSVR2<throttle = 0; + if (serial_paranoia_check(info, tty->name, "cy_unthrottle")) { + return; } - } - return; -} /* cy_unthrottle */ + if (I_IXOFF(tty)) { + if (info->x_char) + info->x_char = 0; + else + cy_send_xchar(tty, START_CHAR(tty)); + } + if (tty->termios->c_cflag & CRTSCTS) { + card = info->card; + channel = info->line - cy_card[card].first_line; + if (!IS_CYC_Z(cy_card[card])) { + chip = channel >> 2; + channel &= 0x03; + index = cy_card[card].bus_index; + base_addr = cy_card[card].base_addr + + (cy_chip_offset[chip] << index); + + CY_LOCK(info, flags); + cy_writeb(base_addr + (CyCAR << index), + (u_char) channel); + if (info->rtsdtr_inv) { + cy_writeb(base_addr + (CyMSVR2 << index), + CyDTR); + } else { + cy_writeb(base_addr + (CyMSVR1 << index), + CyRTS); + } + CY_UNLOCK(info, flags); + } else { + info->throttle = 0; + } + } +} /* cy_unthrottle */ /* cy_start and cy_stop provide software output flow control as a function of XON/XOFF, software CTS, and other such stuff. */ -static void -cy_stop(struct tty_struct *tty) +static void cy_stop(struct tty_struct *tty) { - struct cyclades_card *cinfo; - struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; - void __iomem *base_addr; - int chip,channel,index; - unsigned long flags; + struct cyclades_card *cinfo; + struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; + void __iomem *base_addr; + int chip, channel, index; + unsigned long flags; #ifdef CY_DEBUG_OTHER - printk("cyc:cy_stop ttyC%d\n", info->line); /* */ + printk("cyc:cy_stop ttyC%d\n", info->line); /* */ #endif - if (serial_paranoia_check(info, tty->name, "cy_stop")) - return; - - cinfo = &cy_card[info->card]; - channel = info->line - cinfo->first_line; - if (!IS_CYC_Z(*cinfo)) { - index = cinfo->bus_index; - chip = channel>>2; - channel &= 0x03; - base_addr = cy_card[info->card].base_addr + (cy_chip_offset[chip]<name, "cy_stop")) + return; - return; -} /* cy_stop */ + cinfo = &cy_card[info->card]; + channel = info->line - cinfo->first_line; + if (!IS_CYC_Z(*cinfo)) { + index = cinfo->bus_index; + chip = channel >> 2; + channel &= 0x03; + base_addr = cy_card[info->card].base_addr + + (cy_chip_offset[chip] << index); + CY_LOCK(info, flags); + cy_writeb(base_addr + (CyCAR << index), + (u_char)(channel & 0x0003)); /* index channel */ + cy_writeb(base_addr + (CySRER << index), + cy_readb(base_addr + (CySRER << index)) & ~CyTxRdy); + CY_UNLOCK(info, flags); + } else { + /* Nothing to do! */ + } +} /* cy_stop */ -static void -cy_start(struct tty_struct *tty) +static void cy_start(struct tty_struct *tty) { - struct cyclades_card *cinfo; - struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; - void __iomem *base_addr; - int chip,channel,index; - unsigned long flags; + struct cyclades_card *cinfo; + struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; + void __iomem *base_addr; + int chip, channel, index; + unsigned long flags; #ifdef CY_DEBUG_OTHER - printk("cyc:cy_start ttyC%d\n", info->line); /* */ + printk("cyc:cy_start ttyC%d\n", info->line); /* */ #endif - if (serial_paranoia_check(info, tty->name, "cy_start")) - return; - - cinfo = &cy_card[info->card]; - channel = info->line - cinfo->first_line; - index = cinfo->bus_index; - if (!IS_CYC_Z(*cinfo)) { - chip = channel>>2; - channel &= 0x03; - base_addr = cy_card[info->card].base_addr + (cy_chip_offset[chip]<name, "cy_start")) + return; - return; -} /* cy_start */ + cinfo = &cy_card[info->card]; + channel = info->line - cinfo->first_line; + index = cinfo->bus_index; + if (!IS_CYC_Z(*cinfo)) { + chip = channel >> 2; + channel &= 0x03; + base_addr = cy_card[info->card].base_addr + + (cy_chip_offset[chip] << index); + CY_LOCK(info, flags); + cy_writeb(base_addr + (CyCAR << index), (u_char) (channel & 0x0003)); /* index channel */ + cy_writeb(base_addr + (CySRER << index), + cy_readb(base_addr + (CySRER << index)) | CyTxRdy); + CY_UNLOCK(info, flags); + } else { + /* Nothing to do! */ + } +} /* cy_start */ -static void -cy_flush_buffer(struct tty_struct *tty) +static void cy_flush_buffer(struct tty_struct *tty) { - struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; - int card, channel, retval; - unsigned long flags; - + struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; + int card, channel, retval; + unsigned long flags; + #ifdef CY_DEBUG_IO - printk("cyc:cy_flush_buffer ttyC%d\n", info->line); /* */ + printk("cyc:cy_flush_buffer ttyC%d\n", info->line); /* */ #endif - if (serial_paranoia_check(info, tty->name, "cy_flush_buffer")) - return; - - card = info->card; - channel = (info->line) - (cy_card[card].first_line); + if (serial_paranoia_check(info, tty->name, "cy_flush_buffer")) + return; - CY_LOCK(info, flags); - info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; - CY_UNLOCK(info, flags); + card = info->card; + channel = (info->line) - (cy_card[card].first_line); - if (IS_CYC_Z(cy_card[card])) { /* If it is a Z card, flush the on-board - buffers as well */ CY_LOCK(info, flags); - retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_FLUSH_TX, 0L); - if (retval != 0) { - printk("cyc: flush_buffer retval on ttyC%d was %x\n", - info->line, retval); - } + info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; CY_UNLOCK(info, flags); - } - tty_wakeup(tty); - wake_up_interruptible(&tty->write_wait); -} /* cy_flush_buffer */ + if (IS_CYC_Z(cy_card[card])) { /* If it is a Z card, flush the on-board + buffers as well */ + CY_LOCK(info, flags); + retval = + cyz_issue_cmd(&cy_card[card], channel, C_CM_FLUSH_TX, 0L); + if (retval != 0) { + printk("cyc: flush_buffer retval on ttyC%d was %x\n", + info->line, retval); + } + CY_UNLOCK(info, flags); + } + tty_wakeup(tty); + wake_up_interruptible(&tty->write_wait); +} /* cy_flush_buffer */ /* * cy_hangup() --- called by tty_hangup() when a hangup is signaled. */ -static void -cy_hangup(struct tty_struct *tty) +static void cy_hangup(struct tty_struct *tty) { - struct cyclades_port * info = (struct cyclades_port *)tty->driver_data; - + struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; + #ifdef CY_DEBUG_OTHER - printk("cyc:cy_hangup ttyC%d\n", info->line); /* */ + printk("cyc:cy_hangup ttyC%d\n", info->line); /* */ #endif - if (serial_paranoia_check(info, tty->name, "cy_hangup")) - return; + if (serial_paranoia_check(info, tty->name, "cy_hangup")) + return; - cy_flush_buffer(tty); - shutdown(info); - info->event = 0; - info->count = 0; + cy_flush_buffer(tty); + shutdown(info); + info->event = 0; + info->count = 0; #ifdef CY_DEBUG_COUNT - printk("cyc:cy_hangup (%d): setting count to 0\n", current->pid); + printk("cyc:cy_hangup (%d): setting count to 0\n", current->pid); #endif - info->tty = NULL; - info->flags &= ~ASYNC_NORMAL_ACTIVE; - wake_up_interruptible(&info->open_wait); -} /* cy_hangup */ - + info->tty = NULL; + info->flags &= ~ASYNC_NORMAL_ACTIVE; + wake_up_interruptible(&info->open_wait); +} /* cy_hangup */ /* * --------------------------------------------------------------------- @@ -4432,82 +4528,84 @@ cy_hangup(struct tty_struct *tty) /* initialize chips on Cyclom-Y card -- return number of valid chips (which is number of ports/4) */ static unsigned short __init -cyy_init_card(void __iomem *true_base_addr,int index) +cyy_init_card(void __iomem * true_base_addr, int index) { - unsigned int chip_number; - void __iomem *base_addr; - - cy_writeb(true_base_addr+(Cy_HwReset<= CD1400_REV_J){ - /* It is a CD1400 rev. J or later */ - /* Impossible to reach 5ms with this chip. - Changed to 2ms instead (f = 500 Hz). */ - cy_writeb(base_addr+(CyPPR<= CD1400_REV_J) { + /* It is a CD1400 rev. J or later */ + /* Impossible to reach 5ms with this chip. + Changed to 2ms instead (f = 500 Hz). */ + cy_writeb(base_addr + (CyPPR << index), CyCLOCK_60_2MS); + } else { + /* f = 200 Hz */ + cy_writeb(base_addr + (CyPPR << index), CyCLOCK_25_5MS); + } - /* - printk(" chip #%d at %#6lx is rev 0x%2x\n", - chip_number, (unsigned long)base_addr, - cy_readb(base_addr+(CyGFRCR< NR_PORTS) { - printk("Cyclom-Y/ISA found at 0x%lx ", - (unsigned long) cy_isa_address); - printk("but no more channels are available.\n"); - printk("Change NR_PORTS in cyclades.c and recompile kernel.\n"); - return(nboard); - } - /* fill the next cy_card structure available */ - for (j = 0 ; j < NR_CARDS ; j++) { - if (cy_card[j].base_addr == 0) break; - } - if (j == NR_CARDS) { /* no more cy_cards available */ - printk("Cyclom-Y/ISA found at 0x%lx ", - (unsigned long) cy_isa_address); - printk("but no more cards can be used .\n"); - printk("Change NR_CARDS in cyclades.c and recompile kernel.\n"); - return(nboard); - } - - /* allocate IRQ */ - if(request_irq(cy_isa_irq, cyy_interrupt, - IRQF_DISABLED, "Cyclom-Y", &cy_card[j])) - { - printk("Cyclom-Y/ISA found at 0x%lx ", - (unsigned long) cy_isa_address); - printk("but could not allocate IRQ#%d.\n", - cy_isa_irq); - return(nboard); - } - - /* set cy_card */ - cy_card[j].base_addr = cy_isa_address; - cy_card[j].ctl_addr = NULL; - cy_card[j].irq = (int) cy_isa_irq; - cy_card[j].bus_index = 0; - cy_card[j].first_line = cy_next_channel; - cy_card[j].num_chips = cy_isa_nchan/4; - nboard++; - - /* print message */ - printk("Cyclom-Y/ISA #%d: 0x%lx-0x%lx, IRQ%d, ", - j+1, (unsigned long) cy_isa_address, - (unsigned long)(cy_isa_address + (CyISA_Ywin - 1)), - cy_isa_irq); - printk("%d channels starting from port %d.\n", - cy_isa_nchan, cy_next_channel); - cy_next_channel += cy_isa_nchan; - } - return(nboard); + /* find out the board's irq by probing */ + cy_isa_irq = detect_isa_irq(cy_isa_address); + if (cy_isa_irq == 0) { + printk("Cyclom-Y/ISA found at 0x%lx ", + (unsigned long)cy_isa_address); + printk("but the IRQ could not be detected.\n"); + continue; + } + + if ((cy_next_channel + cy_isa_nchan) > NR_PORTS) { + printk("Cyclom-Y/ISA found at 0x%lx ", + (unsigned long)cy_isa_address); + printk("but no more channels are available.\n"); + printk("Change NR_PORTS in cyclades.c and recompile " + "kernel.\n"); + return nboard; + } + /* fill the next cy_card structure available */ + for (j = 0; j < NR_CARDS; j++) { + if (cy_card[j].base_addr == 0) + break; + } + if (j == NR_CARDS) { /* no more cy_cards available */ + printk("Cyclom-Y/ISA found at 0x%lx ", + (unsigned long)cy_isa_address); + printk("but no more cards can be used .\n"); + printk("Change NR_CARDS in cyclades.c and recompile " + "kernel.\n"); + return nboard; + } + + /* allocate IRQ */ + if (request_irq(cy_isa_irq, cyy_interrupt, + IRQF_DISABLED, "Cyclom-Y", &cy_card[j])) { + printk("Cyclom-Y/ISA found at 0x%lx ", + (unsigned long)cy_isa_address); + printk("but could not allocate IRQ#%d.\n", cy_isa_irq); + return nboard; + } + + /* set cy_card */ + cy_card[j].base_addr = cy_isa_address; + cy_card[j].ctl_addr = NULL; + cy_card[j].irq = (int)cy_isa_irq; + cy_card[j].bus_index = 0; + cy_card[j].first_line = cy_next_channel; + cy_card[j].num_chips = cy_isa_nchan / 4; + nboard++; + + /* print message */ + printk("Cyclom-Y/ISA #%d: 0x%lx-0x%lx, IRQ%d, ", + j + 1, (unsigned long)cy_isa_address, + (unsigned long)(cy_isa_address + (CyISA_Ywin - 1)), + cy_isa_irq); + printk("%d channels starting from port %d.\n", + cy_isa_nchan, cy_next_channel); + cy_next_channel += cy_isa_nchan; + } + return nboard; #else - return(0); -#endif /* CONFIG_ISA */ -} /* cy_detect_isa */ + return 0; +#endif /* CONFIG_ISA */ +} /* cy_detect_isa */ -static void -plx_init(void __iomem *addr, uclong initctl) +static void plx_init(void __iomem * addr, uclong initctl) { - /* Reset PLX */ - cy_writel(addr + initctl, cy_readl(addr + initctl) | 0x40000000); - udelay(100L); - cy_writel(addr + initctl, cy_readl(addr + initctl) & ~0x40000000); - - /* Reload Config. Registers from EEPROM */ - cy_writel(addr + initctl, cy_readl(addr + initctl) | 0x20000000); - udelay(100L); - cy_writel(addr + initctl, cy_readl(addr + initctl) & ~0x20000000); + /* Reset PLX */ + cy_writel(addr + initctl, cy_readl(addr + initctl) | 0x40000000); + udelay(100L); + cy_writel(addr + initctl, cy_readl(addr + initctl) & ~0x40000000); + + /* Reload Config. Registers from EEPROM */ + cy_writel(addr + initctl, cy_readl(addr + initctl) | 0x20000000); + udelay(100L); + cy_writel(addr + initctl, cy_readl(addr + initctl) & ~0x20000000); } /* @@ -4643,43 +4739,42 @@ plx_init(void __iomem *addr, uclong initctl) * sets global variables and return the number of PCI boards found. * --------------------------------------------------------------------- */ -static int __init -cy_detect_pci(void) +static int __init cy_detect_pci(void) { #ifdef CONFIG_PCI - struct pci_dev *pdev = NULL; - unsigned char cyy_rev_id; - unsigned char cy_pci_irq = 0; - uclong cy_pci_phys0, cy_pci_phys2; - void __iomem *cy_pci_addr0, *cy_pci_addr2; - unsigned short i,j,cy_pci_nchan, plx_ver; - unsigned short device_id,dev_index = 0; - uclong mailbox; - uclong ZeIndex = 0; - void __iomem *Ze_addr0[NR_CARDS], *Ze_addr2[NR_CARDS]; - uclong Ze_phys0[NR_CARDS], Ze_phys2[NR_CARDS]; - unsigned char Ze_irq[NR_CARDS]; - struct pci_dev *Ze_pdev[NR_CARDS]; - - for (i = 0; i < NR_CARDS; i++) { - /* look for a Cyclades card by vendor and device id */ - while((device_id = cy_pci_dev_id[dev_index]) != 0) { - if((pdev = pci_get_device(PCI_VENDOR_ID_CYCLADES, - device_id, pdev)) == NULL) { - dev_index++; /* try next device id */ - } else { - break; /* found a board */ - } - } + struct pci_dev *pdev = NULL; + unsigned char cyy_rev_id; + unsigned char cy_pci_irq = 0; + uclong cy_pci_phys0, cy_pci_phys2; + void __iomem *cy_pci_addr0, *cy_pci_addr2; + unsigned short i, j, cy_pci_nchan, plx_ver; + unsigned short device_id, dev_index = 0; + uclong mailbox; + uclong ZeIndex = 0; + void __iomem *Ze_addr0[NR_CARDS], *Ze_addr2[NR_CARDS]; + uclong Ze_phys0[NR_CARDS], Ze_phys2[NR_CARDS]; + unsigned char Ze_irq[NR_CARDS]; + struct pci_dev *Ze_pdev[NR_CARDS]; + + for (i = 0; i < NR_CARDS; i++) { + /* look for a Cyclades card by vendor and device id */ + while ((device_id = cy_pci_dev_id[dev_index]) != 0) { + if ((pdev = pci_get_device(PCI_VENDOR_ID_CYCLADES, + device_id, pdev)) == NULL) { + dev_index++; /* try next device id */ + } else { + break; /* found a board */ + } + } if (device_id == 0) - break; + break; if (pci_enable_device(pdev)) - continue; + continue; - /* read PCI configuration area */ + /* read PCI configuration area */ cy_pci_irq = pdev->irq; cy_pci_phys0 = pci_resource_start(pdev, 0); cy_pci_phys2 = pci_resource_start(pdev, 2); @@ -4687,482 +4782,497 @@ cy_detect_pci(void) device_id &= ~PCI_DEVICE_ID_MASK; - if ((device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo) - || (device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi)){ + if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo || + device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi) { #ifdef CY_PCI_DEBUG - printk("Cyclom-Y/PCI (bus=0x0%x, pci_id=0x%x, ", - pdev->bus->number, pdev->devfn); - printk("rev_id=%d) IRQ%d\n", - cyy_rev_id, (int)cy_pci_irq); - printk("Cyclom-Y/PCI:found winaddr=0x%lx ctladdr=0x%lx\n", - (ulong)cy_pci_phys2, (ulong)cy_pci_phys0); + printk("Cyclom-Y/PCI (bus=0x0%x, pci_id=0x%x, ", + pdev->bus->number, pdev->devfn); + printk("rev_id=%d) IRQ%d\n", + cyy_rev_id, (int)cy_pci_irq); + printk("Cyclom-Y/PCI:found winaddr=0x%lx " + "ctladdr=0x%lx\n", + (ulong)cy_pci_phys2, (ulong)cy_pci_phys0); #endif - if (pci_resource_flags(pdev, 2) & IORESOURCE_IO) { - printk(" Warning: PCI I/O bit incorrectly set. " - "Ignoring it...\n"); - pdev->resource[2].flags &= ~IORESOURCE_IO; - } - - /* Although we don't use this I/O region, we should - request it from the kernel anyway, to avoid problems - with other drivers accessing it. */ - if (pci_request_regions(pdev, "Cyclom-Y") != 0) { - printk(KERN_ERR "cyclades: failed to reserve PCI resources\n"); - continue; - } + if (pci_resource_flags(pdev, 2) & IORESOURCE_IO) { + printk(" Warning: PCI I/O bit incorrectly " + "set. Ignoring it...\n"); + pdev->resource[2].flags &= ~IORESOURCE_IO; + } + /* Although we don't use this I/O region, we should + request it from the kernel anyway, to avoid problems + with other drivers accessing it. */ + if (pci_request_regions(pdev, "Cyclom-Y") != 0) { + printk(KERN_ERR "cyclades: failed to reserve " + "PCI resources\n"); + continue; + } #if defined(__alpha__) - if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo) { /* below 1M? */ - printk("Cyclom-Y/PCI (bus=0x0%x, pci_id=0x%x, ", - pdev->bus->number, pdev->devfn); - printk("rev_id=%d) IRQ%d\n", - cyy_rev_id, (int)cy_pci_irq); - printk("Cyclom-Y/PCI:found winaddr=0x%lx ctladdr=0x%lx\n", - (ulong)cy_pci_phys2, (ulong)cy_pci_phys0); - printk("Cyclom-Y/PCI not supported for low addresses in " - "Alpha systems.\n"); - i--; - continue; - } + if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo) { /* below 1M? */ + printk("Cyclom-Y/PCI (bus=0x0%x, pci_id=0x%x, ", + pdev->bus->number, pdev->devfn); + printk("rev_id=%d) IRQ%d\n", + cyy_rev_id, (int)cy_pci_irq); + printk("Cyclom-Y/PCI:found winaddr=0x%lx " + "ctladdr=0x%lx\n", + (ulong)cy_pci_phys2, + (ulong)cy_pci_phys0); + printk("Cyclom-Y/PCI not supported for low " + "addresses in Alpha systems.\n"); + i--; + continue; + } #endif - cy_pci_addr0 = ioremap(cy_pci_phys0, CyPCI_Yctl); - cy_pci_addr2 = ioremap(cy_pci_phys2, CyPCI_Ywin); + cy_pci_addr0 = ioremap(cy_pci_phys0, CyPCI_Yctl); + cy_pci_addr2 = ioremap(cy_pci_phys2, CyPCI_Ywin); #ifdef CY_PCI_DEBUG - printk("Cyclom-Y/PCI: relocate winaddr=0x%lx ctladdr=0x%lx\n", - (u_long)cy_pci_addr2, (u_long)cy_pci_addr0); + printk("Cyclom-Y/PCI: relocate winaddr=0x%lx " + "ctladdr=0x%lx\n", + (u_long)cy_pci_addr2, (u_long)cy_pci_addr0); #endif - cy_pci_nchan = (unsigned short)(CyPORTS_PER_CHIP * - cyy_init_card(cy_pci_addr2, 1)); - if(cy_pci_nchan == 0) { - printk("Cyclom-Y PCI host card with "); - printk("no Serial-Modules at 0x%lx.\n", - (ulong) cy_pci_phys2); - i--; - continue; - } - if((cy_next_channel+cy_pci_nchan) > NR_PORTS) { - printk("Cyclom-Y/PCI found at 0x%lx ", - (ulong) cy_pci_phys2); - printk("but no channels are available.\n"); - printk("Change NR_PORTS in cyclades.c and recompile kernel.\n"); - return(i); - } - /* fill the next cy_card structure available */ - for (j = 0 ; j < NR_CARDS ; j++) { - if (cy_card[j].base_addr == 0) break; - } - if (j == NR_CARDS) { /* no more cy_cards available */ - printk("Cyclom-Y/PCI found at 0x%lx ", - (ulong) cy_pci_phys2); - printk("but no more cards can be used.\n"); - printk("Change NR_CARDS in cyclades.c and recompile kernel.\n"); - return(i); - } - - /* allocate IRQ */ - if(request_irq(cy_pci_irq, cyy_interrupt, - IRQF_SHARED, "Cyclom-Y", &cy_card[j])) - { - printk("Cyclom-Y/PCI found at 0x%lx ", - (ulong) cy_pci_phys2); - printk("but could not allocate IRQ%d.\n", - cy_pci_irq); - return(i); - } - - /* set cy_card */ - cy_card[j].base_phys = (ulong)cy_pci_phys2; - cy_card[j].ctl_phys = (ulong)cy_pci_phys0; - cy_card[j].base_addr = cy_pci_addr2; - cy_card[j].ctl_addr = cy_pci_addr0; - cy_card[j].irq = (int) cy_pci_irq; - cy_card[j].bus_index = 1; - cy_card[j].first_line = cy_next_channel; - cy_card[j].num_chips = cy_pci_nchan/4; - cy_card[j].pdev = pdev; - - /* enable interrupts in the PCI interface */ - plx_ver = cy_readb(cy_pci_addr2 + CyPLX_VER) & 0x0f; - switch (plx_ver) { - case PLX_9050: - - cy_writeb(cy_pci_addr0+0x4c, 0x43); - break; - - case PLX_9060: - case PLX_9080: - default: /* Old boards, use PLX_9060 */ - - plx_init(cy_pci_addr0, 0x6c); - /* For some yet unknown reason, once the PLX9060 reloads - the EEPROM, the IRQ is lost and, thus, we have to - re-write it to the PCI config. registers. - This will remain here until we find a permanent fix. */ - pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, cy_pci_irq); - - cy_writew(cy_pci_addr0+0x68, - cy_readw(cy_pci_addr0+0x68)|0x0900); - break; - } + cy_pci_nchan = (unsigned short)(CyPORTS_PER_CHIP * + cyy_init_card(cy_pci_addr2, 1)); + if (cy_pci_nchan == 0) { + printk("Cyclom-Y PCI host card with "); + printk("no Serial-Modules at 0x%lx.\n", + (ulong) cy_pci_phys2); + i--; + continue; + } + if ((cy_next_channel + cy_pci_nchan) > NR_PORTS) { + printk("Cyclom-Y/PCI found at 0x%lx ", + (ulong) cy_pci_phys2); + printk("but no channels are available.\n"); + printk("Change NR_PORTS in cyclades.c and " + "recompile kernel.\n"); + return i; + } + /* fill the next cy_card structure available */ + for (j = 0; j < NR_CARDS; j++) { + if (cy_card[j].base_addr == 0) + break; + } + if (j == NR_CARDS) { /* no more cy_cards available */ + printk("Cyclom-Y/PCI found at 0x%lx ", + (ulong) cy_pci_phys2); + printk("but no more cards can be used.\n"); + printk("Change NR_CARDS in cyclades.c and " + "recompile kernel.\n"); + return i; + } - /* print message */ - printk("Cyclom-Y/PCI #%d: 0x%lx-0x%lx, IRQ%d, ", - j+1, - (ulong)cy_pci_phys2, - (ulong)(cy_pci_phys2 + CyPCI_Ywin - 1), - (int)cy_pci_irq); - printk("%d channels starting from port %d.\n", - cy_pci_nchan, cy_next_channel); - - cy_next_channel += cy_pci_nchan; - }else if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Lo){ - /* print message */ - printk("Cyclades-Z/PCI (bus=0x0%x, pci_id=0x%x, ", - pdev->bus->number, pdev->devfn); - printk("rev_id=%d) IRQ%d\n", - cyy_rev_id, (int)cy_pci_irq); - printk("Cyclades-Z/PCI: found winaddr=0x%lx ctladdr=0x%lx\n", - (ulong)cy_pci_phys2, (ulong)cy_pci_phys0); - printk("Cyclades-Z/PCI not supported for low addresses\n"); - break; - }else if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Hi){ + /* allocate IRQ */ + if (request_irq(cy_pci_irq, cyy_interrupt, + IRQF_SHARED, "Cyclom-Y", &cy_card[j])) { + printk("Cyclom-Y/PCI found at 0x%lx ", + (ulong) cy_pci_phys2); + printk("but could not allocate IRQ%d.\n", + cy_pci_irq); + return i; + } + + /* set cy_card */ + cy_card[j].base_phys = (ulong) cy_pci_phys2; + cy_card[j].ctl_phys = (ulong) cy_pci_phys0; + cy_card[j].base_addr = cy_pci_addr2; + cy_card[j].ctl_addr = cy_pci_addr0; + cy_card[j].irq = (int)cy_pci_irq; + cy_card[j].bus_index = 1; + cy_card[j].first_line = cy_next_channel; + cy_card[j].num_chips = cy_pci_nchan / 4; + cy_card[j].pdev = pdev; + + /* enable interrupts in the PCI interface */ + plx_ver = cy_readb(cy_pci_addr2 + CyPLX_VER) & 0x0f; + switch (plx_ver) { + case PLX_9050: + + cy_writeb(cy_pci_addr0 + 0x4c, 0x43); + break; + + case PLX_9060: + case PLX_9080: + default: /* Old boards, use PLX_9060 */ + + plx_init(cy_pci_addr0, 0x6c); + /* For some yet unknown reason, once the PLX9060 reloads + the EEPROM, the IRQ is lost and, thus, we have to + re-write it to the PCI config. registers. + This will remain here until we find a permanent + fix. */ + pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, + cy_pci_irq); + + cy_writew(cy_pci_addr0 + 0x68, + cy_readw(cy_pci_addr0 + + 0x68) | 0x0900); + break; + } + + /* print message */ + printk("Cyclom-Y/PCI #%d: 0x%lx-0x%lx, IRQ%d, ", + j + 1, (ulong)cy_pci_phys2, + (ulong) (cy_pci_phys2 + CyPCI_Ywin - 1), + (int)cy_pci_irq); + printk("%d channels starting from port %d.\n", + cy_pci_nchan, cy_next_channel); + + cy_next_channel += cy_pci_nchan; + } else if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Lo) { + /* print message */ + printk("Cyclades-Z/PCI (bus=0x0%x, pci_id=0x%x, ", + pdev->bus->number, pdev->devfn); + printk("rev_id=%d) IRQ%d\n", + cyy_rev_id, (int)cy_pci_irq); + printk("Cyclades-Z/PCI: found winaddr=0x%lx " + "ctladdr=0x%lx\n", + (ulong)cy_pci_phys2, (ulong)cy_pci_phys0); + printk("Cyclades-Z/PCI not supported for low " + "addresses\n"); + break; + } else if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Hi) { #ifdef CY_PCI_DEBUG - printk("Cyclades-Z/PCI (bus=0x0%x, pci_id=0x%x, ", - pdev->bus->number, pdev->devfn); - printk("rev_id=%d) IRQ%d\n", - cyy_rev_id, (int)cy_pci_irq); - printk("Cyclades-Z/PCI: found winaddr=0x%lx ctladdr=0x%lx\n", - (ulong)cy_pci_phys2, (ulong)cy_pci_phys0); + printk("Cyclades-Z/PCI (bus=0x0%x, pci_id=0x%x, ", + pdev->bus->number, pdev->devfn); + printk("rev_id=%d) IRQ%d\n", + cyy_rev_id, (int)cy_pci_irq); + printk("Cyclades-Z/PCI: found winaddr=0x%lx " + "ctladdr=0x%lx\n", + (ulong) cy_pci_phys2, (ulong) cy_pci_phys0); #endif - cy_pci_addr0 = ioremap(cy_pci_phys0, CyPCI_Zctl); - - /* Disable interrupts on the PLX before resetting it */ - cy_writew(cy_pci_addr0+0x68, - cy_readw(cy_pci_addr0+0x68) & ~0x0900); - - plx_init(cy_pci_addr0, 0x6c); - /* For some yet unknown reason, once the PLX9060 reloads - the EEPROM, the IRQ is lost and, thus, we have to - re-write it to the PCI config. registers. - This will remain here until we find a permanent fix. */ - pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, cy_pci_irq); - - mailbox = (uclong)cy_readl(&((struct RUNTIME_9060 __iomem *) - cy_pci_addr0)->mail_box_0); - - if (pci_resource_flags(pdev, 2) & IORESOURCE_IO) { - printk(" Warning: PCI I/O bit incorrectly set. " - "Ignoring it...\n"); - pdev->resource[2].flags &= ~IORESOURCE_IO; - } + cy_pci_addr0 = ioremap(cy_pci_phys0, CyPCI_Zctl); + + /* Disable interrupts on the PLX before resetting it */ + cy_writew(cy_pci_addr0 + 0x68, + cy_readw(cy_pci_addr0 + 0x68) & ~0x0900); + + plx_init(cy_pci_addr0, 0x6c); + /* For some yet unknown reason, once the PLX9060 reloads + the EEPROM, the IRQ is lost and, thus, we have to + re-write it to the PCI config. registers. + This will remain here until we find a permanent + fix. */ + pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, + cy_pci_irq); + + mailbox = + (uclong)cy_readl(&((struct RUNTIME_9060 __iomem *) + cy_pci_addr0)->mail_box_0); + + if (pci_resource_flags(pdev, 2) & IORESOURCE_IO) { + printk(" Warning: PCI I/O bit incorrectly " + "set. Ignoring it...\n"); + pdev->resource[2].flags &= ~IORESOURCE_IO; + } - /* Although we don't use this I/O region, we should - request it from the kernel anyway, to avoid problems - with other drivers accessing it. */ - if (pci_request_regions(pdev, "Cyclades-Z") != 0) { - printk(KERN_ERR "cyclades: failed to reserve PCI resources\n"); - continue; - } - - if (mailbox == ZE_V1) { - cy_pci_addr2 = ioremap(cy_pci_phys2, CyPCI_Ze_win); - if (ZeIndex == NR_CARDS) { - printk("Cyclades-Ze/PCI found at 0x%lx ", - (ulong)cy_pci_phys2); - printk("but no more cards can be used.\n"); - printk("Change NR_CARDS in cyclades.c and recompile kernel.\n"); - } else { - Ze_phys0[ZeIndex] = cy_pci_phys0; - Ze_phys2[ZeIndex] = cy_pci_phys2; - Ze_addr0[ZeIndex] = cy_pci_addr0; - Ze_addr2[ZeIndex] = cy_pci_addr2; - Ze_irq[ZeIndex] = cy_pci_irq; - Ze_pdev[ZeIndex] = pdev; - ZeIndex++; - } - i--; - continue; - } else { - cy_pci_addr2 = ioremap(cy_pci_phys2, CyPCI_Zwin); - } + /* Although we don't use this I/O region, we should + request it from the kernel anyway, to avoid problems + with other drivers accessing it. */ + if (pci_request_regions(pdev, "Cyclades-Z") != 0) { + printk(KERN_ERR "cyclades: failed to reserve " + "PCI resources\n"); + continue; + } + + if (mailbox == ZE_V1) { + cy_pci_addr2 = ioremap(cy_pci_phys2, + CyPCI_Ze_win); + if (ZeIndex == NR_CARDS) { + printk("Cyclades-Ze/PCI found at " + "0x%lx but no more cards can " + "be used.\nChange NR_CARDS in " + "cyclades.c and recompile " + "kernel.\n", + (ulong)cy_pci_phys2); + } else { + Ze_phys0[ZeIndex] = cy_pci_phys0; + Ze_phys2[ZeIndex] = cy_pci_phys2; + Ze_addr0[ZeIndex] = cy_pci_addr0; + Ze_addr2[ZeIndex] = cy_pci_addr2; + Ze_irq[ZeIndex] = cy_pci_irq; + Ze_pdev[ZeIndex] = pdev; + ZeIndex++; + } + i--; + continue; + } else { + cy_pci_addr2 = ioremap(cy_pci_phys2,CyPCI_Zwin); + } #ifdef CY_PCI_DEBUG - printk("Cyclades-Z/PCI: relocate winaddr=0x%lx ctladdr=0x%lx\n", - (ulong)cy_pci_addr2, (ulong)cy_pci_addr0); - if (mailbox == ZO_V1) { - cy_writel(&((struct RUNTIME_9060 *) - (cy_pci_addr0))->loc_addr_base, WIN_CREG); - PAUSE - printk("Cyclades-8Zo/PCI: FPGA id %lx, ver %lx\n", - (ulong)(0xff & cy_readl(&((struct CUSTOM_REG *) - (cy_pci_addr2))->fpga_id)), - (ulong)(0xff & cy_readl(&((struct CUSTOM_REG *) - (cy_pci_addr2))->fpga_version))); - cy_writel(&((struct RUNTIME_9060 *) - (cy_pci_addr0))->loc_addr_base, WIN_RAM); - } else { - printk("Cyclades-Z/PCI: New Cyclades-Z board. FPGA not loaded\n"); - } + printk("Cyclades-Z/PCI: relocate winaddr=0x%lx " + "ctladdr=0x%lx\n", + (ulong) cy_pci_addr2, (ulong) cy_pci_addr0); + if (mailbox == ZO_V1) { + cy_writel(&((struct RUNTIME_9060 *) + (cy_pci_addr0))->loc_addr_base, + WIN_CREG); + PAUSE; + printk("Cyclades-8Zo/PCI: FPGA id %lx, ver " + "%lx\n", (ulong) (0xff & + cy_readl(&((struct CUSTOM_REG *) + (cy_pci_addr2))->fpga_id)), + (ulong)(0xff & + cy_readl(&((struct CUSTOM_REG *) + (cy_pci_addr2))-> + fpga_version))); + cy_writel(&((struct RUNTIME_9060 *) + (cy_pci_addr0))->loc_addr_base, + WIN_RAM); + } else { + printk("Cyclades-Z/PCI: New Cyclades-Z board. " + "FPGA not loaded\n"); + } #endif - /* The following clears the firmware id word. This ensures - that the driver will not attempt to talk to the board - until it has been properly initialized. - */ - PAUSE - if ((mailbox == ZO_V1) || (mailbox == ZO_V2)) - cy_writel(cy_pci_addr2 + ID_ADDRESS, 0L); - - /* This must be a Cyclades-8Zo/PCI. The extendable - version will have a different device_id and will - be allocated its maximum number of ports. */ - cy_pci_nchan = 8; - - if((cy_next_channel+cy_pci_nchan) > NR_PORTS) { - printk("Cyclades-8Zo/PCI found at 0x%lx ", - (ulong)cy_pci_phys2); - printk("but no channels are available.\n"); - printk("Change NR_PORTS in cyclades.c and recompile kernel.\n"); - return(i); - } - - /* fill the next cy_card structure available */ - for (j = 0 ; j < NR_CARDS ; j++) { - if (cy_card[j].base_addr == 0) break; - } - if (j == NR_CARDS) { /* no more cy_cards available */ - printk("Cyclades-8Zo/PCI found at 0x%lx ", - (ulong)cy_pci_phys2); - printk("but no more cards can be used.\n"); - printk("Change NR_CARDS in cyclades.c and recompile kernel.\n"); - return(i); - } + /* The following clears the firmware id word. This + ensures that the driver will not attempt to talk to + the board until it has been properly initialized. + */ + PAUSE; + if ((mailbox == ZO_V1) || (mailbox == ZO_V2)) + cy_writel(cy_pci_addr2 + ID_ADDRESS, 0L); + + /* This must be a Cyclades-8Zo/PCI. The extendable + version will have a different device_id and will + be allocated its maximum number of ports. */ + cy_pci_nchan = 8; + + if ((cy_next_channel + cy_pci_nchan) > NR_PORTS) { + printk("Cyclades-8Zo/PCI found at 0x%lx but" + "no channels are available.\nChange " + "NR_PORTS in cyclades.c and recompile " + "kernel.\n", (ulong)cy_pci_phys2); + return i; + } + /* fill the next cy_card structure available */ + for (j = 0; j < NR_CARDS; j++) { + if (cy_card[j].base_addr == 0) + break; + } + if (j == NR_CARDS) { /* no more cy_cards available */ + printk("Cyclades-8Zo/PCI found at 0x%lx but" + "no more cards can be used.\nChange " + "NR_CARDS in cyclades.c and recompile " + "kernel.\n", (ulong)cy_pci_phys2); + return i; + } +#ifdef CONFIG_CYZ_INTR + /* allocate IRQ only if board has an IRQ */ + if ((cy_pci_irq != 0) && (cy_pci_irq != 255)) { + if (request_irq(cy_pci_irq, cyz_interrupt, + IRQF_SHARED, "Cyclades-Z", + &cy_card[j])) { + printk("Cyclom-8Zo/PCI found at 0x%lx " + "but could not allocate " + "IRQ%d.\n", (ulong)cy_pci_phys2, + cy_pci_irq); + return i; + } + } +#endif /* CONFIG_CYZ_INTR */ + + /* set cy_card */ + cy_card[j].base_phys = cy_pci_phys2; + cy_card[j].ctl_phys = cy_pci_phys0; + cy_card[j].base_addr = cy_pci_addr2; + cy_card[j].ctl_addr = cy_pci_addr0; + cy_card[j].irq = (int)cy_pci_irq; + cy_card[j].bus_index = 1; + cy_card[j].first_line = cy_next_channel; + cy_card[j].num_chips = -1; + cy_card[j].pdev = pdev; + + /* print message */ #ifdef CONFIG_CYZ_INTR - /* allocate IRQ only if board has an IRQ */ - if( (cy_pci_irq != 0) && (cy_pci_irq != 255) ) { - if(request_irq(cy_pci_irq, cyz_interrupt, - IRQF_SHARED, "Cyclades-Z", &cy_card[j])) - { - printk("Cyclom-8Zo/PCI found at 0x%lx ", - (ulong) cy_pci_phys2); - printk("but could not allocate IRQ%d.\n", - cy_pci_irq); - return(i); - } + /* don't report IRQ if board is no IRQ */ + if ((cy_pci_irq != 0) && (cy_pci_irq != 255)) + printk("Cyclades-8Zo/PCI #%d: 0x%lx-0x%lx, " + "IRQ%d, ", j + 1, (ulong)cy_pci_phys2, + (ulong) (cy_pci_phys2 + CyPCI_Zwin - 1), + (int)cy_pci_irq); + else +#endif /* CONFIG_CYZ_INTR */ + printk("Cyclades-8Zo/PCI #%d: 0x%lx-0x%lx, ", + j + 1, (ulong)cy_pci_phys2, + (ulong)(cy_pci_phys2 + CyPCI_Zwin - 1)); + + printk("%d channels starting from port %d.\n", + cy_pci_nchan, cy_next_channel); + cy_next_channel += cy_pci_nchan; } -#endif /* CONFIG_CYZ_INTR */ - - - /* set cy_card */ - cy_card[j].base_phys = cy_pci_phys2; - cy_card[j].ctl_phys = cy_pci_phys0; - cy_card[j].base_addr = cy_pci_addr2; - cy_card[j].ctl_addr = cy_pci_addr0; - cy_card[j].irq = (int) cy_pci_irq; - cy_card[j].bus_index = 1; - cy_card[j].first_line = cy_next_channel; - cy_card[j].num_chips = -1; - cy_card[j].pdev = pdev; + } - /* print message */ -#ifdef CONFIG_CYZ_INTR - /* don't report IRQ if board is no IRQ */ - if( (cy_pci_irq != 0) && (cy_pci_irq != 255) ) - printk("Cyclades-8Zo/PCI #%d: 0x%lx-0x%lx, IRQ%d, ", - j+1,(ulong)cy_pci_phys2, - (ulong)(cy_pci_phys2 + CyPCI_Zwin - 1), - (int)cy_pci_irq); - else -#endif /* CONFIG_CYZ_INTR */ - printk("Cyclades-8Zo/PCI #%d: 0x%lx-0x%lx, ", - j+1,(ulong)cy_pci_phys2, - (ulong)(cy_pci_phys2 + CyPCI_Zwin - 1)); - - printk("%d channels starting from port %d.\n", - cy_pci_nchan,cy_next_channel); - cy_next_channel += cy_pci_nchan; - } - } - - for (; ZeIndex != 0 && i < NR_CARDS; i++) { - cy_pci_phys0 = Ze_phys0[0]; - cy_pci_phys2 = Ze_phys2[0]; - cy_pci_addr0 = Ze_addr0[0]; - cy_pci_addr2 = Ze_addr2[0]; - cy_pci_irq = Ze_irq[0]; - pdev = Ze_pdev[0]; - for (j = 0 ; j < ZeIndex-1 ; j++) { - Ze_phys0[j] = Ze_phys0[j+1]; - Ze_phys2[j] = Ze_phys2[j+1]; - Ze_addr0[j] = Ze_addr0[j+1]; - Ze_addr2[j] = Ze_addr2[j+1]; - Ze_irq[j] = Ze_irq[j+1]; - Ze_pdev[j] = Ze_pdev[j+1]; - } - ZeIndex--; - mailbox = (uclong)cy_readl(&((struct RUNTIME_9060 __iomem *) - cy_pci_addr0)->mail_box_0); + for (; ZeIndex != 0 && i < NR_CARDS; i++) { + cy_pci_phys0 = Ze_phys0[0]; + cy_pci_phys2 = Ze_phys2[0]; + cy_pci_addr0 = Ze_addr0[0]; + cy_pci_addr2 = Ze_addr2[0]; + cy_pci_irq = Ze_irq[0]; + pdev = Ze_pdev[0]; + for (j = 0; j < ZeIndex - 1; j++) { + Ze_phys0[j] = Ze_phys0[j + 1]; + Ze_phys2[j] = Ze_phys2[j + 1]; + Ze_addr0[j] = Ze_addr0[j + 1]; + Ze_addr2[j] = Ze_addr2[j + 1]; + Ze_irq[j] = Ze_irq[j + 1]; + Ze_pdev[j] = Ze_pdev[j + 1]; + } + ZeIndex--; + mailbox = (uclong)cy_readl(&((struct RUNTIME_9060 __iomem *) + cy_pci_addr0)->mail_box_0); #ifdef CY_PCI_DEBUG - printk("Cyclades-Z/PCI: relocate winaddr=0x%lx ctladdr=0x%lx\n", - (ulong)cy_pci_addr2, (ulong)cy_pci_addr0); - printk("Cyclades-Z/PCI: New Cyclades-Z board. FPGA not loaded\n"); + printk("Cyclades-Z/PCI: relocate winaddr=0x%lx ctladdr=0x%lx\n", + (ulong)cy_pci_addr2, (ulong)cy_pci_addr0); + printk("Cyclades-Z/PCI: New Cyclades-Z board. FPGA not " + "loaded\n"); #endif - PAUSE - /* This must be the new Cyclades-Ze/PCI. */ - cy_pci_nchan = ZE_V1_NPORTS; - - if((cy_next_channel+cy_pci_nchan) > NR_PORTS) { - printk("Cyclades-Ze/PCI found at 0x%lx ", - (ulong)cy_pci_phys2); - printk("but no channels are available.\n"); - printk("Change NR_PORTS in cyclades.c and recompile kernel.\n"); - return(i); - } - - /* fill the next cy_card structure available */ - for (j = 0 ; j < NR_CARDS ; j++) { - if (cy_card[j].base_addr == 0) break; - } - if (j == NR_CARDS) { /* no more cy_cards available */ - printk("Cyclades-Ze/PCI found at 0x%lx ", - (ulong)cy_pci_phys2); - printk("but no more cards can be used.\n"); - printk("Change NR_CARDS in cyclades.c and recompile kernel.\n"); - return(i); - } + PAUSE; + /* This must be the new Cyclades-Ze/PCI. */ + cy_pci_nchan = ZE_V1_NPORTS; + + if ((cy_next_channel + cy_pci_nchan) > NR_PORTS) { + printk("Cyclades-Ze/PCI found at 0x%lx but no channels " + "are available.\nChange NR_PORTS in cyclades.c " + "and recompile kernel.\n", + (ulong) cy_pci_phys2); + return i; + } + /* fill the next cy_card structure available */ + for (j = 0; j < NR_CARDS; j++) { + if (cy_card[j].base_addr == 0) + break; + } + if (j == NR_CARDS) { /* no more cy_cards available */ + printk("Cyclades-Ze/PCI found at 0x%lx but no more " + "cards can be used.\nChange NR_CARDS in " + "cyclades.c and recompile kernel.\n", + (ulong) cy_pci_phys2); + return i; + } #ifdef CONFIG_CYZ_INTR - /* allocate IRQ only if board has an IRQ */ - if( (cy_pci_irq != 0) && (cy_pci_irq != 255) ) { - if(request_irq(cy_pci_irq, cyz_interrupt, - IRQF_SHARED, "Cyclades-Z", &cy_card[j])) - { - printk("Cyclom-Ze/PCI found at 0x%lx ", - (ulong) cy_pci_phys2); - printk("but could not allocate IRQ%d.\n", - cy_pci_irq); - return(i); - } + /* allocate IRQ only if board has an IRQ */ + if ((cy_pci_irq != 0) && (cy_pci_irq != 255)) { + if (request_irq(cy_pci_irq, cyz_interrupt, + IRQF_SHARED, "Cyclades-Z", + &cy_card[j])) { + printk("Cyclom-Ze/PCI found at 0x%lx ", + (ulong) cy_pci_phys2); + printk("but could not allocate IRQ%d.\n", + cy_pci_irq); + return i; + } } -#endif /* CONFIG_CYZ_INTR */ - - /* set cy_card */ - cy_card[j].base_phys = cy_pci_phys2; - cy_card[j].ctl_phys = cy_pci_phys0; - cy_card[j].base_addr = cy_pci_addr2; - cy_card[j].ctl_addr = cy_pci_addr0; - cy_card[j].irq = (int) cy_pci_irq; - cy_card[j].bus_index = 1; - cy_card[j].first_line = cy_next_channel; - cy_card[j].num_chips = -1; +#endif /* CONFIG_CYZ_INTR */ + + /* set cy_card */ + cy_card[j].base_phys = cy_pci_phys2; + cy_card[j].ctl_phys = cy_pci_phys0; + cy_card[j].base_addr = cy_pci_addr2; + cy_card[j].ctl_addr = cy_pci_addr0; + cy_card[j].irq = (int)cy_pci_irq; + cy_card[j].bus_index = 1; + cy_card[j].first_line = cy_next_channel; + cy_card[j].num_chips = -1; cy_card[j].pdev = pdev; - /* print message */ + /* print message */ #ifdef CONFIG_CYZ_INTR /* don't report IRQ if board is no IRQ */ - if( (cy_pci_irq != 0) && (cy_pci_irq != 255) ) - printk("Cyclades-Ze/PCI #%d: 0x%lx-0x%lx, IRQ%d, ", - j+1,(ulong)cy_pci_phys2, - (ulong)(cy_pci_phys2 + CyPCI_Ze_win - 1), - (int)cy_pci_irq); + if ((cy_pci_irq != 0) && (cy_pci_irq != 255)) + printk("Cyclades-Ze/PCI #%d: 0x%lx-0x%lx, IRQ%d, ", + j + 1, (ulong) cy_pci_phys2, + (ulong) (cy_pci_phys2 + CyPCI_Ze_win - 1), + (int)cy_pci_irq); else -#endif /* CONFIG_CYZ_INTR */ - printk("Cyclades-Ze/PCI #%d: 0x%lx-0x%lx, ", - j+1,(ulong)cy_pci_phys2, - (ulong)(cy_pci_phys2 + CyPCI_Ze_win - 1)); - - printk("%d channels starting from port %d.\n", - cy_pci_nchan,cy_next_channel); - cy_next_channel += cy_pci_nchan; - } +#endif /* CONFIG_CYZ_INTR */ + printk("Cyclades-Ze/PCI #%d: 0x%lx-0x%lx, ", + j + 1, (ulong) cy_pci_phys2, + (ulong) (cy_pci_phys2 + CyPCI_Ze_win - 1)); + + printk("%d channels starting from port %d.\n", + cy_pci_nchan, cy_next_channel); + cy_next_channel += cy_pci_nchan; + } if (ZeIndex != 0) { - printk("Cyclades-Ze/PCI found at 0x%x ", - (unsigned int) Ze_phys2[0]); - printk("but no more cards can be used.\n"); - printk("Change NR_CARDS in cyclades.c and recompile kernel.\n"); + printk("Cyclades-Ze/PCI found at 0x%x but no more cards can be " + "used.\nChange NR_CARDS in cyclades.c and recompile " + "kernel.\n", (unsigned int)Ze_phys2[0]); } - return(i); + return i; #else - return(0); -#endif /* ifdef CONFIG_PCI */ -} /* cy_detect_pci */ - + return 0; +#endif /* ifdef CONFIG_PCI */ +} /* cy_detect_pci */ /* * This routine prints out the appropriate serial driver version number * and identifies which options were configured into this driver. */ -static inline void -show_version(void) +static inline void show_version(void) { - char *rcsvers, *rcsdate, *tmp; - rcsvers = strchr(rcsid, ' '); rcsvers++; - tmp = strchr(rcsvers, ' '); *tmp++ = '\0'; - rcsdate = strchr(tmp, ' '); rcsdate++; - tmp = strrchr(rcsdate, ' '); *tmp = '\0'; - printk("Cyclades driver %s %s\n", - rcsvers, rcsdate); - printk(" built %s %s\n", - __DATE__, __TIME__); -} /* show_version */ - -static int + printk("Cyclades driver " CY_VERSION "\n"); + printk(" built %s %s\n", __DATE__, __TIME__); +} /* show_version */ + +static int cyclades_get_proc_info(char *buf, char **start, off_t offset, int length, - int *eof, void *data) + int *eof, void *data) { - struct cyclades_port *info; - int i; - int len=0; - off_t begin=0; - off_t pos=0; - int size; - __u32 cur_jifs = jiffies; - - size = sprintf(buf, "Dev TimeOpen BytesOut IdleOut BytesIn IdleIn Overruns Ldisc\n"); - - pos += size; - len += size; - - /* Output one line for each known port */ - for (i = 0; i < NR_PORTS && cy_port[i].line >= 0; i++) { - info = &cy_port[i]; - - if (info->count) - size = sprintf(buf+len, - "%3d %8lu %10lu %8lu %10lu %8lu %9lu %6ld\n", - info->line, - JIFFIES_DIFF(info->idle_stats.in_use, cur_jifs) / HZ, - info->idle_stats.xmit_bytes, - JIFFIES_DIFF(info->idle_stats.xmit_idle, cur_jifs) / HZ, - info->idle_stats.recv_bytes, - JIFFIES_DIFF(info->idle_stats.recv_idle, cur_jifs) / HZ, - info->idle_stats.overruns, - (long) info->tty->ldisc.num); - else - size = sprintf(buf+len, - "%3d %8lu %10lu %8lu %10lu %8lu %9lu %6ld\n", - info->line, 0L, 0L, 0L, 0L, 0L, 0L, 0L); + struct cyclades_port *info; + int i; + int len = 0; + off_t begin = 0; + off_t pos = 0; + int size; + __u32 cur_jifs = jiffies; + + size = sprintf(buf, "Dev TimeOpen BytesOut IdleOut BytesIn " + "IdleIn Overruns Ldisc\n"); + + pos += size; len += size; - pos = begin + len; - if (pos < offset) { - len = 0; - begin = pos; + /* Output one line for each known port */ + for (i = 0; i < NR_PORTS && cy_port[i].line >= 0; i++) { + info = &cy_port[i]; + + if (info->count) + size = sprintf(buf + len, "%3d %8lu %10lu %8lu %10lu " + "%8lu %9lu %6ld\n", info->line, + (cur_jifs - info->idle_stats.in_use) / HZ, + info->idle_stats.xmit_bytes, + (cur_jifs - info->idle_stats.xmit_idle) / HZ, + info->idle_stats.recv_bytes, + (cur_jifs - info->idle_stats.recv_idle) / HZ, + info->idle_stats.overruns, + (long)info->tty->ldisc.num); + else + size = sprintf(buf + len, "%3d %8lu %10lu %8lu %10lu " + "%8lu %9lu %6ld\n", + info->line, 0L, 0L, 0L, 0L, 0L, 0L, 0L); + len += size; + pos = begin + len; + + if (pos < offset) { + len = 0; + begin = pos; + } + if (pos > offset + length) + goto done; } - if (pos > offset + length) - goto done; - } - *eof = 1; + *eof = 1; done: - *start = buf + (offset - begin); /* Start of wanted data */ - len -= (offset - begin); /* Start slop */ - if (len > length) - len = length; /* Ending slop */ - if (len < 0) - len = 0; - return len; + *start = buf + (offset - begin); /* Start of wanted data */ + len -= (offset - begin); /* Start slop */ + if (len > length) + len = length; /* Ending slop */ + if (len < 0) + len = 0; + return len; } /* The serial driver boot-time initialization code! @@ -5184,290 +5294,288 @@ cyclades_get_proc_info(char *buf, char **start, off_t offset, int length, */ static const struct tty_operations cy_ops = { - .open = cy_open, - .close = cy_close, - .write = cy_write, - .put_char = cy_put_char, - .flush_chars = cy_flush_chars, - .write_room = cy_write_room, - .chars_in_buffer = cy_chars_in_buffer, - .flush_buffer = cy_flush_buffer, - .ioctl = cy_ioctl, - .throttle = cy_throttle, - .unthrottle = cy_unthrottle, - .set_termios = cy_set_termios, - .stop = cy_stop, - .start = cy_start, - .hangup = cy_hangup, - .break_ctl = cy_break, - .wait_until_sent = cy_wait_until_sent, - .read_proc = cyclades_get_proc_info, - .tiocmget = cy_tiocmget, - .tiocmset = cy_tiocmset, + .open = cy_open, + .close = cy_close, + .write = cy_write, + .put_char = cy_put_char, + .flush_chars = cy_flush_chars, + .write_room = cy_write_room, + .chars_in_buffer = cy_chars_in_buffer, + .flush_buffer = cy_flush_buffer, + .ioctl = cy_ioctl, + .throttle = cy_throttle, + .unthrottle = cy_unthrottle, + .set_termios = cy_set_termios, + .stop = cy_stop, + .start = cy_start, + .hangup = cy_hangup, + .break_ctl = cy_break, + .wait_until_sent = cy_wait_until_sent, + .read_proc = cyclades_get_proc_info, + .tiocmget = cy_tiocmget, + .tiocmset = cy_tiocmset, }; -static int __init -cy_init(void) +static int __init cy_init(void) { - struct cyclades_port *info; - struct cyclades_card *cinfo; - int number_z_boards = 0; - int board,port,i,index; - unsigned long mailbox; - unsigned short chip_number; - int nports; - - cy_serial_driver = alloc_tty_driver(NR_PORTS); - if (!cy_serial_driver) - return -ENOMEM; - show_version(); - - /* Initialize the tty_driver structure */ - - cy_serial_driver->owner = THIS_MODULE; - cy_serial_driver->driver_name = "cyclades"; - cy_serial_driver->name = "ttyC"; - cy_serial_driver->major = CYCLADES_MAJOR; - cy_serial_driver->minor_start = 0; - cy_serial_driver->type = TTY_DRIVER_TYPE_SERIAL; - cy_serial_driver->subtype = SERIAL_TYPE_NORMAL; - cy_serial_driver->init_termios = tty_std_termios; - cy_serial_driver->init_termios.c_cflag = - B9600 | CS8 | CREAD | HUPCL | CLOCAL; - cy_serial_driver->flags = TTY_DRIVER_REAL_RAW; - tty_set_operations(cy_serial_driver, &cy_ops); - - if (tty_register_driver(cy_serial_driver)) - panic("Couldn't register Cyclades serial driver\n"); - - for (i = 0; i < NR_CARDS; i++) { - /* base_addr=0 indicates board not found */ - cy_card[i].base_addr = NULL; - } - - /* the code below is responsible to find the boards. Each different - type of board has its own detection routine. If a board is found, - the next cy_card structure available is set by the detection - routine. These functions are responsible for checking the - availability of cy_card and cy_port data structures and updating - the cy_next_channel. */ - - /* look for isa boards */ - cy_isa_nboard = cy_detect_isa(); - - /* look for pci boards */ - cy_pci_nboard = cy_detect_pci(); - - cy_nboard = cy_isa_nboard + cy_pci_nboard; - - /* invalidate remaining cy_card structures */ - for (i = 0 ; i < NR_CARDS ; i++) { - if (cy_card[i].base_addr == 0) { - cy_card[i].first_line = -1; - cy_card[i].ctl_addr = NULL; - cy_card[i].irq = 0; - cy_card[i].bus_index = 0; - cy_card[i].first_line = 0; - cy_card[i].num_chips = 0; - } - } - /* invalidate remaining cy_port structures */ - for (i = cy_next_channel ; i < NR_PORTS ; i++) { - cy_port[i].line = -1; - cy_port[i].magic = -1; - } - - /* initialize per-port data structures for each valid board found */ - for (board = 0 ; board < cy_nboard ; board++) { - cinfo = &cy_card[board]; - if (cinfo->num_chips == -1) { /* Cyclades-Z */ - number_z_boards++; - mailbox = cy_readl(&((struct RUNTIME_9060 __iomem *) - cy_card[board].ctl_addr)->mail_box_0); - nports = (mailbox == ZE_V1) ? ZE_V1_NPORTS : 8; - cinfo->intr_enabled = 0; - cinfo->nports = 0; /* Will be correctly set later, after - Z FW is loaded */ - spin_lock_init(&cinfo->card_lock); - for (port = cinfo->first_line ; - port < cinfo->first_line + nports; - port++) - { - info = &cy_port[port]; - info->magic = CYCLADES_MAGIC; - info->type = PORT_STARTECH; - info->card = board; - info->line = port; - info->chip_rev = 0; - info->flags = STD_COM_FLAGS; - info->tty = NULL; - if (mailbox == ZO_V1) - info->xmit_fifo_size = CYZ_FIFO_SIZE; - else - info->xmit_fifo_size = 4 * CYZ_FIFO_SIZE; - info->cor1 = 0; - info->cor2 = 0; - info->cor3 = 0; - info->cor4 = 0; - info->cor5 = 0; - info->tbpr = 0; - info->tco = 0; - info->rbpr = 0; - info->rco = 0; - info->custom_divisor = 0; - info->close_delay = 5*HZ/10; - info->closing_wait = CLOSING_WAIT_DELAY; - info->icount.cts = info->icount.dsr = - info->icount.rng = info->icount.dcd = 0; - info->icount.rx = info->icount.tx = 0; - info->icount.frame = info->icount.parity = 0; - info->icount.overrun = info->icount.brk = 0; - info->x_char = 0; - info->event = 0; - info->count = 0; - info->blocked_open = 0; - info->default_threshold = 0; - info->default_timeout = 0; - INIT_WORK(&info->tqueue, do_softint, info); - init_waitqueue_head(&info->open_wait); - init_waitqueue_head(&info->close_wait); - init_waitqueue_head(&info->shutdown_wait); - init_waitqueue_head(&info->delta_msr_wait); - /* info->session */ - /* info->pgrp */ - info->read_status_mask = 0; - /* info->timeout */ - /* Bentson's vars */ - info->jiffies[0] = 0; - info->jiffies[1] = 0; - info->jiffies[2] = 0; - info->rflush_count = 0; + struct cyclades_port *info; + struct cyclades_card *cinfo; + int number_z_boards = 0; + int board, port, i, index; + unsigned long mailbox; + unsigned short chip_number; + int nports; + + cy_serial_driver = alloc_tty_driver(NR_PORTS); + if (!cy_serial_driver) + return -ENOMEM; + show_version(); + + /* Initialize the tty_driver structure */ + + cy_serial_driver->owner = THIS_MODULE; + cy_serial_driver->driver_name = "cyclades"; + cy_serial_driver->name = "ttyC"; + cy_serial_driver->major = CYCLADES_MAJOR; + cy_serial_driver->minor_start = 0; + cy_serial_driver->type = TTY_DRIVER_TYPE_SERIAL; + cy_serial_driver->subtype = SERIAL_TYPE_NORMAL; + cy_serial_driver->init_termios = tty_std_termios; + cy_serial_driver->init_termios.c_cflag = + B9600 | CS8 | CREAD | HUPCL | CLOCAL; + cy_serial_driver->flags = TTY_DRIVER_REAL_RAW; + tty_set_operations(cy_serial_driver, &cy_ops); + + if (tty_register_driver(cy_serial_driver)) + panic("Couldn't register Cyclades serial driver\n"); + + for (i = 0; i < NR_CARDS; i++) { + /* base_addr=0 indicates board not found */ + cy_card[i].base_addr = NULL; + } + + /* the code below is responsible to find the boards. Each different + type of board has its own detection routine. If a board is found, + the next cy_card structure available is set by the detection + routine. These functions are responsible for checking the + availability of cy_card and cy_port data structures and updating + the cy_next_channel. */ + + /* look for isa boards */ + cy_isa_nboard = cy_detect_isa(); + + /* look for pci boards */ + cy_pci_nboard = cy_detect_pci(); + + cy_nboard = cy_isa_nboard + cy_pci_nboard; + + /* invalidate remaining cy_card structures */ + for (i = 0; i < NR_CARDS; i++) { + if (cy_card[i].base_addr == 0) { + cy_card[i].first_line = -1; + cy_card[i].ctl_addr = NULL; + cy_card[i].irq = 0; + cy_card[i].bus_index = 0; + cy_card[i].first_line = 0; + cy_card[i].num_chips = 0; + } + } + /* invalidate remaining cy_port structures */ + for (i = cy_next_channel; i < NR_PORTS; i++) { + cy_port[i].line = -1; + cy_port[i].magic = -1; + } + + /* initialize per-port data structures for each valid board found */ + for (board = 0; board < cy_nboard; board++) { + cinfo = &cy_card[board]; + if (cinfo->num_chips == -1) { /* Cyclades-Z */ + number_z_boards++; + mailbox = cy_readl(&((struct RUNTIME_9060 __iomem *) + cy_card[board].ctl_addr)-> + mail_box_0); + nports = (mailbox == ZE_V1) ? ZE_V1_NPORTS : 8; + cinfo->intr_enabled = 0; + cinfo->nports = 0; /* Will be correctly set later, after + Z FW is loaded */ + spin_lock_init(&cinfo->card_lock); + for (port = cinfo->first_line; + port < cinfo->first_line + nports; port++) { + info = &cy_port[port]; + info->magic = CYCLADES_MAGIC; + info->type = PORT_STARTECH; + info->card = board; + info->line = port; + info->chip_rev = 0; + info->flags = STD_COM_FLAGS; + info->tty = NULL; + if (mailbox == ZO_V1) + info->xmit_fifo_size = CYZ_FIFO_SIZE; + else + info->xmit_fifo_size = + 4 * CYZ_FIFO_SIZE; + info->cor1 = 0; + info->cor2 = 0; + info->cor3 = 0; + info->cor4 = 0; + info->cor5 = 0; + info->tbpr = 0; + info->tco = 0; + info->rbpr = 0; + info->rco = 0; + info->custom_divisor = 0; + info->close_delay = 5 * HZ / 10; + info->closing_wait = CLOSING_WAIT_DELAY; + info->icount.cts = info->icount.dsr = + info->icount.rng = info->icount.dcd = 0; + info->icount.rx = info->icount.tx = 0; + info->icount.frame = info->icount.parity = 0; + info->icount.overrun = info->icount.brk = 0; + info->x_char = 0; + info->event = 0; + info->count = 0; + info->blocked_open = 0; + info->default_threshold = 0; + info->default_timeout = 0; + INIT_WORK(&info->tqueue, do_softint); + init_waitqueue_head(&info->open_wait); + init_waitqueue_head(&info->close_wait); + init_waitqueue_head(&info->shutdown_wait); + init_waitqueue_head(&info->delta_msr_wait); + /* info->session */ + /* info->pgrp */ + info->read_status_mask = 0; + /* info->timeout */ + /* Bentson's vars */ + info->jiffies[0] = 0; + info->jiffies[1] = 0; + info->jiffies[2] = 0; + info->rflush_count = 0; #ifdef CONFIG_CYZ_INTR - init_timer(&cyz_rx_full_timer[port]); - cyz_rx_full_timer[port].function = NULL; + init_timer(&cyz_rx_full_timer[port]); + cyz_rx_full_timer[port].function = NULL; #endif - } - continue; - }else{ /* Cyclom-Y of some kind*/ - index = cinfo->bus_index; - spin_lock_init(&cinfo->card_lock); - cinfo->nports = CyPORTS_PER_CHIP * cinfo->num_chips; - for (port = cinfo->first_line ; - port < cinfo->first_line + cinfo->nports ; - port++) - { - info = &cy_port[port]; - info->magic = CYCLADES_MAGIC; - info->type = PORT_CIRRUS; - info->card = board; - info->line = port; - info->flags = STD_COM_FLAGS; - info->tty = NULL; - info->xmit_fifo_size = CyMAX_CHAR_FIFO; - info->cor1 = CyPARITY_NONE|Cy_1_STOP|Cy_8_BITS; - info->cor2 = CyETC; - info->cor3 = 0x08; /* _very_ small rcv threshold */ - info->cor4 = 0; - info->cor5 = 0; - info->custom_divisor = 0; - info->close_delay = 5*HZ/10; - info->closing_wait = CLOSING_WAIT_DELAY; - info->icount.cts = info->icount.dsr = - info->icount.rng = info->icount.dcd = 0; - info->icount.rx = info->icount.tx = 0; - info->icount.frame = info->icount.parity = 0; - info->icount.overrun = info->icount.brk = 0; - chip_number = (port - cinfo->first_line) / 4; - if ((info->chip_rev = - cy_readb(cinfo->base_addr + - (cy_chip_offset[chip_number]<= CD1400_REV_J) { - /* It is a CD1400 rev. J or later */ - info->tbpr = baud_bpr_60[13]; /* Tx BPR */ - info->tco = baud_co_60[13]; /* Tx CO */ - info->rbpr = baud_bpr_60[13]; /* Rx BPR */ - info->rco = baud_co_60[13]; /* Rx CO */ - info->rflow = 0; - info->rtsdtr_inv = 1; - } else { - info->tbpr = baud_bpr_25[13]; /* Tx BPR */ - info->tco = baud_co_25[13]; /* Tx CO */ - info->rbpr = baud_bpr_25[13]; /* Rx BPR */ - info->rco = baud_co_25[13]; /* Rx CO */ - info->rflow = 0; - info->rtsdtr_inv = 0; - } - info->x_char = 0; - info->event = 0; - info->count = 0; - info->blocked_open = 0; - info->default_threshold = 0; - info->default_timeout = 0; - INIT_WORK(&info->tqueue, do_softint, info); - init_waitqueue_head(&info->open_wait); - init_waitqueue_head(&info->close_wait); - init_waitqueue_head(&info->shutdown_wait); - init_waitqueue_head(&info->delta_msr_wait); - /* info->session */ - /* info->pgrp */ - info->read_status_mask = - CyTIMEOUT| CySPECHAR| CyBREAK - | CyPARITY| CyFRAME| CyOVERRUN; - /* info->timeout */ - } - } - } + } + continue; + } else { /* Cyclom-Y of some kind */ + index = cinfo->bus_index; + spin_lock_init(&cinfo->card_lock); + cinfo->nports = CyPORTS_PER_CHIP * cinfo->num_chips; + for (port = cinfo->first_line; + port < cinfo->first_line + cinfo->nports; port++) { + info = &cy_port[port]; + info->magic = CYCLADES_MAGIC; + info->type = PORT_CIRRUS; + info->card = board; + info->line = port; + info->flags = STD_COM_FLAGS; + info->tty = NULL; + info->xmit_fifo_size = CyMAX_CHAR_FIFO; + info->cor1 = + CyPARITY_NONE | Cy_1_STOP | Cy_8_BITS; + info->cor2 = CyETC; + info->cor3 = 0x08; /* _very_ small rcv threshold */ + info->cor4 = 0; + info->cor5 = 0; + info->custom_divisor = 0; + info->close_delay = 5 * HZ / 10; + info->closing_wait = CLOSING_WAIT_DELAY; + info->icount.cts = info->icount.dsr = + info->icount.rng = info->icount.dcd = 0; + info->icount.rx = info->icount.tx = 0; + info->icount.frame = info->icount.parity = 0; + info->icount.overrun = info->icount.brk = 0; + chip_number = (port - cinfo->first_line) / 4; + if ((info->chip_rev = + cy_readb(cinfo->base_addr + + (cy_chip_offset[chip_number] << + index) + (CyGFRCR << index))) >= + CD1400_REV_J) { + /* It is a CD1400 rev. J or later */ + info->tbpr = baud_bpr_60[13]; /* Tx BPR */ + info->tco = baud_co_60[13]; /* Tx CO */ + info->rbpr = baud_bpr_60[13]; /* Rx BPR */ + info->rco = baud_co_60[13]; /* Rx CO */ + info->rflow = 0; + info->rtsdtr_inv = 1; + } else { + info->tbpr = baud_bpr_25[13]; /* Tx BPR */ + info->tco = baud_co_25[13]; /* Tx CO */ + info->rbpr = baud_bpr_25[13]; /* Rx BPR */ + info->rco = baud_co_25[13]; /* Rx CO */ + info->rflow = 0; + info->rtsdtr_inv = 0; + } + info->x_char = 0; + info->event = 0; + info->count = 0; + info->blocked_open = 0; + info->default_threshold = 0; + info->default_timeout = 0; + INIT_WORK(&info->tqueue, do_softint); + init_waitqueue_head(&info->open_wait); + init_waitqueue_head(&info->close_wait); + init_waitqueue_head(&info->shutdown_wait); + init_waitqueue_head(&info->delta_msr_wait); + /* info->session */ + /* info->pgrp */ + info->read_status_mask = + CyTIMEOUT | CySPECHAR | CyBREAK + | CyPARITY | CyFRAME | CyOVERRUN; + /* info->timeout */ + } + } + } #ifndef CONFIG_CYZ_INTR - if (number_z_boards && !cyz_timeron){ - cyz_timeron++; - cyz_timerlist.expires = jiffies + 1; - add_timer(&cyz_timerlist); + if (number_z_boards && !cyz_timeron) { + cyz_timeron++; + cyz_timerlist.expires = jiffies + 1; + add_timer(&cyz_timerlist); #ifdef CY_PCI_DEBUG - printk("Cyclades-Z polling initialized\n"); + printk("Cyclades-Z polling initialized\n"); #endif - } -#endif /* CONFIG_CYZ_INTR */ + } +#endif /* CONFIG_CYZ_INTR */ + + return 0; - return 0; - -} /* cy_init */ +} /* cy_init */ -static void __exit -cy_cleanup_module(void) +static void __exit cy_cleanup_module(void) { - int i, e1; + int i, e1; #ifndef CONFIG_CYZ_INTR - if (cyz_timeron){ - cyz_timeron = 0; - del_timer(&cyz_timerlist); - } + if (cyz_timeron){ + cyz_timeron = 0; + del_timer(&cyz_timerlist); + } #endif /* CONFIG_CYZ_INTR */ - if ((e1 = tty_unregister_driver(cy_serial_driver))) - printk("cyc: failed to unregister Cyclades serial driver(%d)\n", - e1); + if ((e1 = tty_unregister_driver(cy_serial_driver))) + printk("cyc: failed to unregister Cyclades serial driver(%d)\n", + e1); - put_tty_driver(cy_serial_driver); + put_tty_driver(cy_serial_driver); - for (i = 0; i < NR_CARDS; i++) { - if (cy_card[i].base_addr) { - iounmap(cy_card[i].base_addr); - if (cy_card[i].ctl_addr) - iounmap(cy_card[i].ctl_addr); - if (cy_card[i].irq + for (i = 0; i < NR_CARDS; i++) { + if (cy_card[i].base_addr) { + iounmap(cy_card[i].base_addr); + if (cy_card[i].ctl_addr) + iounmap(cy_card[i].ctl_addr); + if (cy_card[i].irq #ifndef CONFIG_CYZ_INTR - && cy_card[i].num_chips != -1 /* not a Z card */ + && cy_card[i].num_chips != -1 /* not a Z card */ #endif /* CONFIG_CYZ_INTR */ - ) - free_irq(cy_card[i].irq, &cy_card[i]); + ) + free_irq(cy_card[i].irq, &cy_card[i]); #ifdef CONFIG_PCI - if (cy_card[i].pdev) - pci_release_regions(cy_card[i].pdev); + if (cy_card[i].pdev) + pci_release_regions(cy_card[i].pdev); #endif - } - } + } + } } /* cy_cleanup_module */ module_init(cy_init); diff --git a/trunk/drivers/char/decserial.c b/trunk/drivers/char/decserial.c index 85f404e25c73..8ea2bea2b183 100644 --- a/trunk/drivers/char/decserial.c +++ b/trunk/drivers/char/decserial.c @@ -23,20 +23,12 @@ extern int zs_init(void); #endif -#ifdef CONFIG_DZ -extern int dz_init(void); -#endif - #ifdef CONFIG_SERIAL_CONSOLE #ifdef CONFIG_ZS extern void zs_serial_console_init(void); #endif -#ifdef CONFIG_DZ -extern void dz_serial_console_init(void); -#endif - #endif /* rs_init - starts up the serial interface - @@ -46,23 +38,11 @@ extern void dz_serial_console_init(void); int __init rs_init(void) { - -#if defined(CONFIG_ZS) && defined(CONFIG_DZ) +#ifdef CONFIG_ZS if (IOASIC) return zs_init(); - else - return dz_init(); -#else - -#ifdef CONFIG_ZS - return zs_init(); -#endif - -#ifdef CONFIG_DZ - return dz_init(); -#endif - #endif + return -ENXIO; } __initcall(rs_init); @@ -76,21 +56,9 @@ __initcall(rs_init); */ static int __init decserial_console_init(void) { -#if defined(CONFIG_ZS) && defined(CONFIG_DZ) +#ifdef CONFIG_ZS if (IOASIC) zs_serial_console_init(); - else - dz_serial_console_init(); -#else - -#ifdef CONFIG_ZS - zs_serial_console_init(); -#endif - -#ifdef CONFIG_DZ - dz_serial_console_init(); -#endif - #endif return 0; } diff --git a/trunk/drivers/char/drm/drm_ioc32.c b/trunk/drivers/char/drm/drm_ioc32.c index d4f874520082..fafeb34f89d5 100644 --- a/trunk/drivers/char/drm/drm_ioc32.c +++ b/trunk/drivers/char/drm/drm_ioc32.c @@ -102,7 +102,7 @@ static int compat_drm_version(struct file *file, unsigned int cmd, &version->desc)) return -EFAULT; - err = drm_ioctl(file->f_dentry->d_inode, file, + err = drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_VERSION, (unsigned long)version); if (err) return err; @@ -143,7 +143,7 @@ static int compat_drm_getunique(struct file *file, unsigned int cmd, &u->unique)) return -EFAULT; - err = drm_ioctl(file->f_dentry->d_inode, file, + err = drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_GET_UNIQUE, (unsigned long)u); if (err) return err; @@ -172,7 +172,7 @@ static int compat_drm_setunique(struct file *file, unsigned int cmd, &u->unique)) return -EFAULT; - return drm_ioctl(file->f_dentry->d_inode, file, + return drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_SET_UNIQUE, (unsigned long)u); } @@ -203,7 +203,7 @@ static int compat_drm_getmap(struct file *file, unsigned int cmd, if (__put_user(idx, &map->offset)) return -EFAULT; - err = drm_ioctl(file->f_dentry->d_inode, file, + err = drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_GET_MAP, (unsigned long)map); if (err) return err; @@ -244,7 +244,7 @@ static int compat_drm_addmap(struct file *file, unsigned int cmd, || __put_user(m32.flags, &map->flags)) return -EFAULT; - err = drm_ioctl(file->f_dentry->d_inode, file, + err = drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_ADD_MAP, (unsigned long)map); if (err) return err; @@ -282,7 +282,7 @@ static int compat_drm_rmmap(struct file *file, unsigned int cmd, if (__put_user((void *)(unsigned long)handle, &map->handle)) return -EFAULT; - return drm_ioctl(file->f_dentry->d_inode, file, + return drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_RM_MAP, (unsigned long)map); } @@ -312,7 +312,7 @@ static int compat_drm_getclient(struct file *file, unsigned int cmd, if (__put_user(idx, &client->idx)) return -EFAULT; - err = drm_ioctl(file->f_dentry->d_inode, file, + err = drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_GET_CLIENT, (unsigned long)client); if (err) return err; @@ -349,7 +349,7 @@ static int compat_drm_getstats(struct file *file, unsigned int cmd, if (!access_ok(VERIFY_WRITE, stats, sizeof(*stats))) return -EFAULT; - err = drm_ioctl(file->f_dentry->d_inode, file, + err = drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_GET_STATS, (unsigned long)stats); if (err) return err; @@ -393,7 +393,7 @@ static int compat_drm_addbufs(struct file *file, unsigned int cmd, || __put_user(agp_start, &buf->agp_start)) return -EFAULT; - err = drm_ioctl(file->f_dentry->d_inode, file, + err = drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_ADD_BUFS, (unsigned long)buf); if (err) return err; @@ -425,7 +425,7 @@ static int compat_drm_markbufs(struct file *file, unsigned int cmd, || __put_user(b32.high_mark, &buf->high_mark)) return -EFAULT; - return drm_ioctl(file->f_dentry->d_inode, file, + return drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_MARK_BUFS, (unsigned long)buf); } @@ -467,7 +467,7 @@ static int compat_drm_infobufs(struct file *file, unsigned int cmd, || __put_user(list, &request->list)) return -EFAULT; - err = drm_ioctl(file->f_dentry->d_inode, file, + err = drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_INFO_BUFS, (unsigned long)request); if (err) return err; @@ -529,7 +529,7 @@ static int compat_drm_mapbufs(struct file *file, unsigned int cmd, || __put_user(list, &request->list)) return -EFAULT; - err = drm_ioctl(file->f_dentry->d_inode, file, + err = drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_MAP_BUFS, (unsigned long)request); if (err) return err; @@ -576,7 +576,7 @@ static int compat_drm_freebufs(struct file *file, unsigned int cmd, &request->list)) return -EFAULT; - return drm_ioctl(file->f_dentry->d_inode, file, + return drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_FREE_BUFS, (unsigned long)request); } @@ -603,7 +603,7 @@ static int compat_drm_setsareactx(struct file *file, unsigned int cmd, &request->handle)) return -EFAULT; - return drm_ioctl(file->f_dentry->d_inode, file, + return drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_SET_SAREA_CTX, (unsigned long)request); } @@ -626,7 +626,7 @@ static int compat_drm_getsareactx(struct file *file, unsigned int cmd, if (__put_user(ctx_id, &request->ctx_id)) return -EFAULT; - err = drm_ioctl(file->f_dentry->d_inode, file, + err = drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_GET_SAREA_CTX, (unsigned long)request); if (err) return err; @@ -662,7 +662,7 @@ static int compat_drm_resctx(struct file *file, unsigned int cmd, &res->contexts)) return -EFAULT; - err = drm_ioctl(file->f_dentry->d_inode, file, + err = drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_RES_CTX, (unsigned long)res); if (err) return err; @@ -716,7 +716,7 @@ static int compat_drm_dma(struct file *file, unsigned int cmd, &d->request_sizes)) return -EFAULT; - err = drm_ioctl(file->f_dentry->d_inode, file, + err = drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_DMA, (unsigned long)d); if (err) return err; @@ -749,7 +749,7 @@ static int compat_drm_agp_enable(struct file *file, unsigned int cmd, if (put_user(m32.mode, &mode->mode)) return -EFAULT; - return drm_ioctl(file->f_dentry->d_inode, file, + return drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_AGP_ENABLE, (unsigned long)mode); } @@ -779,7 +779,7 @@ static int compat_drm_agp_info(struct file *file, unsigned int cmd, if (!access_ok(VERIFY_WRITE, info, sizeof(*info))) return -EFAULT; - err = drm_ioctl(file->f_dentry->d_inode, file, + err = drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_AGP_INFO, (unsigned long)info); if (err) return err; @@ -825,7 +825,7 @@ static int compat_drm_agp_alloc(struct file *file, unsigned int cmd, || __put_user(req32.type, &request->type)) return -EFAULT; - err = drm_ioctl(file->f_dentry->d_inode, file, + err = drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_AGP_ALLOC, (unsigned long)request); if (err) return err; @@ -833,7 +833,7 @@ static int compat_drm_agp_alloc(struct file *file, unsigned int cmd, if (__get_user(req32.handle, &request->handle) || __get_user(req32.physical, &request->physical) || copy_to_user(argp, &req32, sizeof(req32))) { - drm_ioctl(file->f_dentry->d_inode, file, + drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_AGP_FREE, (unsigned long)request); return -EFAULT; } @@ -854,7 +854,7 @@ static int compat_drm_agp_free(struct file *file, unsigned int cmd, || __put_user(handle, &request->handle)) return -EFAULT; - return drm_ioctl(file->f_dentry->d_inode, file, + return drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_AGP_FREE, (unsigned long)request); } @@ -879,7 +879,7 @@ static int compat_drm_agp_bind(struct file *file, unsigned int cmd, || __put_user(req32.offset, &request->offset)) return -EFAULT; - return drm_ioctl(file->f_dentry->d_inode, file, + return drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_AGP_BIND, (unsigned long)request); } @@ -896,7 +896,7 @@ static int compat_drm_agp_unbind(struct file *file, unsigned int cmd, || __put_user(handle, &request->handle)) return -EFAULT; - return drm_ioctl(file->f_dentry->d_inode, file, + return drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_AGP_UNBIND, (unsigned long)request); } #endif /* __OS_HAS_AGP */ @@ -921,7 +921,7 @@ static int compat_drm_sg_alloc(struct file *file, unsigned int cmd, || __put_user(x, &request->size)) return -EFAULT; - err = drm_ioctl(file->f_dentry->d_inode, file, + err = drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_SG_ALLOC, (unsigned long)request); if (err) return err; @@ -948,7 +948,7 @@ static int compat_drm_sg_free(struct file *file, unsigned int cmd, || __put_user(x << PAGE_SHIFT, &request->handle)) return -EFAULT; - return drm_ioctl(file->f_dentry->d_inode, file, + return drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_SG_FREE, (unsigned long)request); } @@ -988,7 +988,7 @@ static int compat_drm_wait_vblank(struct file *file, unsigned int cmd, || __put_user(req32.request.signal, &request->request.signal)) return -EFAULT; - err = drm_ioctl(file->f_dentry->d_inode, file, + err = drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_WAIT_VBLANK, (unsigned long)request); if (err) return err; @@ -1060,7 +1060,7 @@ long drm_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (fn != NULL) ret = (*fn) (filp, cmd, arg); else - ret = drm_ioctl(filp->f_dentry->d_inode, filp, cmd, arg); + ret = drm_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg); unlock_kernel(); return ret; diff --git a/trunk/drivers/char/drm/drm_sman.c b/trunk/drivers/char/drm/drm_sman.c index 425c82336ee0..19c81d2e13d0 100644 --- a/trunk/drivers/char/drm/drm_sman.c +++ b/trunk/drivers/char/drm/drm_sman.c @@ -162,6 +162,7 @@ drm_sman_set_manager(drm_sman_t * sman, unsigned int manager, return 0; } +EXPORT_SYMBOL(drm_sman_set_manager); static drm_owner_item_t *drm_sman_get_owner_item(drm_sman_t * sman, unsigned long owner) diff --git a/trunk/drivers/char/drm/drm_vm.c b/trunk/drivers/char/drm/drm_vm.c index b40ae438f531..ae2691942ddb 100644 --- a/trunk/drivers/char/drm/drm_vm.c +++ b/trunk/drivers/char/drm/drm_vm.c @@ -147,14 +147,14 @@ static __inline__ struct page *drm_do_vm_shm_nopage(struct vm_area_struct *vma, if (address > vma->vm_end) return NOPAGE_SIGBUS; /* Disallow mremap */ if (!map) - return NOPAGE_OOM; /* Nothing allocated */ + return NOPAGE_SIGBUS; /* Nothing allocated */ offset = address - vma->vm_start; i = (unsigned long)map->handle + offset; page = (map->type == _DRM_CONSISTENT) ? virt_to_page((void *)i) : vmalloc_to_page((void *)i); if (!page) - return NOPAGE_OOM; + return NOPAGE_SIGBUS; get_page(page); DRM_DEBUG("shm_nopage 0x%lx\n", address); @@ -272,7 +272,7 @@ static __inline__ struct page *drm_do_vm_dma_nopage(struct vm_area_struct *vma, if (address > vma->vm_end) return NOPAGE_SIGBUS; /* Disallow mremap */ if (!dma->pagelist) - return NOPAGE_OOM; /* Nothing allocated */ + return NOPAGE_SIGBUS; /* Nothing allocated */ offset = address - vma->vm_start; /* vm_[pg]off[set] should be 0 */ page_nr = offset >> PAGE_SHIFT; @@ -310,7 +310,7 @@ static __inline__ struct page *drm_do_vm_sg_nopage(struct vm_area_struct *vma, if (address > vma->vm_end) return NOPAGE_SIGBUS; /* Disallow mremap */ if (!entry->pagelist) - return NOPAGE_OOM; /* Nothing allocated */ + return NOPAGE_SIGBUS; /* Nothing allocated */ offset = address - vma->vm_start; map_offset = map->offset - (unsigned long)dev->sg->virtual; diff --git a/trunk/drivers/char/drm/i915_ioc32.c b/trunk/drivers/char/drm/i915_ioc32.c index 296248cdc767..1fe68a251b75 100644 --- a/trunk/drivers/char/drm/i915_ioc32.c +++ b/trunk/drivers/char/drm/i915_ioc32.c @@ -66,7 +66,7 @@ static int compat_i915_batchbuffer(struct file *file, unsigned int cmd, &batchbuffer->cliprects)) return -EFAULT; - return drm_ioctl(file->f_dentry->d_inode, file, + return drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_I915_BATCHBUFFER, (unsigned long)batchbuffer); } @@ -102,7 +102,7 @@ static int compat_i915_cmdbuffer(struct file *file, unsigned int cmd, &cmdbuffer->cliprects)) return -EFAULT; - return drm_ioctl(file->f_dentry->d_inode, file, + return drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_I915_CMDBUFFER, (unsigned long)cmdbuffer); } @@ -125,7 +125,7 @@ static int compat_i915_irq_emit(struct file *file, unsigned int cmd, &request->irq_seq)) return -EFAULT; - return drm_ioctl(file->f_dentry->d_inode, file, + return drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_I915_IRQ_EMIT, (unsigned long)request); } typedef struct drm_i915_getparam32 { @@ -149,7 +149,7 @@ static int compat_i915_getparam(struct file *file, unsigned int cmd, &request->value)) return -EFAULT; - return drm_ioctl(file->f_dentry->d_inode, file, + return drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_I915_GETPARAM, (unsigned long)request); } @@ -178,7 +178,7 @@ static int compat_i915_alloc(struct file *file, unsigned int cmd, &request->region_offset)) return -EFAULT; - return drm_ioctl(file->f_dentry->d_inode, file, + return drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_I915_ALLOC, (unsigned long)request); } @@ -215,7 +215,7 @@ long i915_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (fn != NULL) ret = (*fn) (filp, cmd, arg); else - ret = drm_ioctl(filp->f_dentry->d_inode, filp, cmd, arg); + ret = drm_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg); unlock_kernel(); return ret; diff --git a/trunk/drivers/char/drm/mga_ioc32.c b/trunk/drivers/char/drm/mga_ioc32.c index 54a18eb2fc04..30d00478ddee 100644 --- a/trunk/drivers/char/drm/mga_ioc32.c +++ b/trunk/drivers/char/drm/mga_ioc32.c @@ -100,7 +100,7 @@ static int compat_mga_init(struct file *file, unsigned int cmd, if (err) return -EFAULT; - return drm_ioctl(file->f_dentry->d_inode, file, + return drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_MGA_INIT, (unsigned long)init); } @@ -125,7 +125,7 @@ static int compat_mga_getparam(struct file *file, unsigned int cmd, &getparam->value)) return -EFAULT; - return drm_ioctl(file->f_dentry->d_inode, file, + return drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_MGA_GETPARAM, (unsigned long)getparam); } @@ -166,7 +166,7 @@ static int compat_mga_dma_bootstrap(struct file *file, unsigned int cmd, || __put_user(dma_bootstrap32.agp_size, &dma_bootstrap->agp_size)) return -EFAULT; - err = drm_ioctl(file->f_dentry->d_inode, file, + err = drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_MGA_DMA_BOOTSTRAP, (unsigned long)dma_bootstrap); if (err) @@ -224,7 +224,7 @@ long mga_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (fn != NULL) ret = (*fn) (filp, cmd, arg); else - ret = drm_ioctl(filp->f_dentry->d_inode, filp, cmd, arg); + ret = drm_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg); unlock_kernel(); return ret; diff --git a/trunk/drivers/char/drm/r128_ioc32.c b/trunk/drivers/char/drm/r128_ioc32.c index 9dd6d4116e47..d3cb676eee84 100644 --- a/trunk/drivers/char/drm/r128_ioc32.c +++ b/trunk/drivers/char/drm/r128_ioc32.c @@ -95,7 +95,7 @@ static int compat_r128_init(struct file *file, unsigned int cmd, &init->agp_textures_offset)) return -EFAULT; - return drm_ioctl(file->f_dentry->d_inode, file, + return drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_R128_INIT, (unsigned long)init); } @@ -129,7 +129,7 @@ static int compat_r128_depth(struct file *file, unsigned int cmd, &depth->mask)) return -EFAULT; - return drm_ioctl(file->f_dentry->d_inode, file, + return drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_R128_DEPTH, (unsigned long)depth); } @@ -153,7 +153,7 @@ static int compat_r128_stipple(struct file *file, unsigned int cmd, &stipple->mask)) return -EFAULT; - return drm_ioctl(file->f_dentry->d_inode, file, + return drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_R128_STIPPLE, (unsigned long)stipple); } @@ -178,7 +178,7 @@ static int compat_r128_getparam(struct file *file, unsigned int cmd, &getparam->value)) return -EFAULT; - return drm_ioctl(file->f_dentry->d_inode, file, + return drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_R128_GETPARAM, (unsigned long)getparam); } @@ -214,7 +214,7 @@ long r128_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (fn != NULL) ret = (*fn) (filp, cmd, arg); else - ret = drm_ioctl(filp->f_dentry->d_inode, filp, cmd, arg); + ret = drm_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg); unlock_kernel(); return ret; diff --git a/trunk/drivers/char/drm/radeon_ioc32.c b/trunk/drivers/char/drm/radeon_ioc32.c index 0ccfd3618ff1..1f1f9cc055a4 100644 --- a/trunk/drivers/char/drm/radeon_ioc32.c +++ b/trunk/drivers/char/drm/radeon_ioc32.c @@ -92,7 +92,7 @@ static int compat_radeon_cp_init(struct file *file, unsigned int cmd, &init->gart_textures_offset)) return -EFAULT; - return drm_ioctl(file->f_dentry->d_inode, file, + return drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_RADEON_CP_INIT, (unsigned long)init); } @@ -125,7 +125,7 @@ static int compat_radeon_cp_clear(struct file *file, unsigned int cmd, &clr->depth_boxes)) return -EFAULT; - return drm_ioctl(file->f_dentry->d_inode, file, + return drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_RADEON_CLEAR, (unsigned long)clr); } @@ -149,7 +149,7 @@ static int compat_radeon_cp_stipple(struct file *file, unsigned int cmd, &request->mask)) return -EFAULT; - return drm_ioctl(file->f_dentry->d_inode, file, + return drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_RADEON_STIPPLE, (unsigned long)request); } @@ -204,7 +204,7 @@ static int compat_radeon_cp_texture(struct file *file, unsigned int cmd, &image->data)) return -EFAULT; - return drm_ioctl(file->f_dentry->d_inode, file, + return drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_RADEON_TEXTURE, (unsigned long)request); } @@ -238,7 +238,7 @@ static int compat_radeon_cp_vertex2(struct file *file, unsigned int cmd, &request->prim)) return -EFAULT; - return drm_ioctl(file->f_dentry->d_inode, file, + return drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_RADEON_VERTEX2, (unsigned long)request); } @@ -268,7 +268,7 @@ static int compat_radeon_cp_cmdbuf(struct file *file, unsigned int cmd, &request->boxes)) return -EFAULT; - return drm_ioctl(file->f_dentry->d_inode, file, + return drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_RADEON_CMDBUF, (unsigned long)request); } @@ -293,7 +293,7 @@ static int compat_radeon_cp_getparam(struct file *file, unsigned int cmd, &request->value)) return -EFAULT; - return drm_ioctl(file->f_dentry->d_inode, file, + return drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_RADEON_GETPARAM, (unsigned long)request); } @@ -322,7 +322,7 @@ static int compat_radeon_mem_alloc(struct file *file, unsigned int cmd, &request->region_offset)) return -EFAULT; - return drm_ioctl(file->f_dentry->d_inode, file, + return drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_RADEON_ALLOC, (unsigned long)request); } @@ -345,7 +345,7 @@ static int compat_radeon_irq_emit(struct file *file, unsigned int cmd, &request->irq_seq)) return -EFAULT; - return drm_ioctl(file->f_dentry->d_inode, file, + return drm_ioctl(file->f_path.dentry->d_inode, file, DRM_IOCTL_RADEON_IRQ_EMIT, (unsigned long)request); } @@ -386,7 +386,7 @@ long radeon_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (fn != NULL) ret = (*fn) (filp, cmd, arg); else - ret = drm_ioctl(filp->f_dentry->d_inode, filp, cmd, arg); + ret = drm_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg); unlock_kernel(); return ret; diff --git a/trunk/drivers/char/drm/via_dmablit.c b/trunk/drivers/char/drm/via_dmablit.c index 60c1695db300..806f9ce5f47b 100644 --- a/trunk/drivers/char/drm/via_dmablit.c +++ b/trunk/drivers/char/drm/via_dmablit.c @@ -500,9 +500,9 @@ via_dmablit_timer(unsigned long data) static void -via_dmablit_workqueue(void *data) +via_dmablit_workqueue(struct work_struct *work) { - drm_via_blitq_t *blitq = (drm_via_blitq_t *) data; + drm_via_blitq_t *blitq = container_of(work, drm_via_blitq_t, wq); drm_device_t *dev = blitq->dev; unsigned long irqsave; drm_via_sg_info_t *cur_sg; @@ -571,7 +571,7 @@ via_init_dmablit(drm_device_t *dev) DRM_INIT_WAITQUEUE(blitq->blit_queue + j); } DRM_INIT_WAITQUEUE(&blitq->busy_queue); - INIT_WORK(&blitq->wq, via_dmablit_workqueue, blitq); + INIT_WORK(&blitq->wq, via_dmablit_workqueue); init_timer(&blitq->poll_timer); blitq->poll_timer.function = &via_dmablit_timer; blitq->poll_timer.data = (unsigned long) blitq; diff --git a/trunk/drivers/char/dsp56k.c b/trunk/drivers/char/dsp56k.c index 9b1bf60ffbe7..06f2dbf17710 100644 --- a/trunk/drivers/char/dsp56k.c +++ b/trunk/drivers/char/dsp56k.c @@ -201,7 +201,7 @@ static int dsp56k_upload(u_char __user *bin, int len) static ssize_t dsp56k_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; int dev = iminor(inode) & 0x0f; switch(dev) @@ -264,7 +264,7 @@ static ssize_t dsp56k_read(struct file *file, char __user *buf, size_t count, static ssize_t dsp56k_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; int dev = iminor(inode) & 0x0f; switch(dev) @@ -420,7 +420,7 @@ static int dsp56k_ioctl(struct inode *inode, struct file *file, #if 0 static unsigned int dsp56k_poll(struct file *file, poll_table *wait) { - int dev = iminor(file->f_dentry->d_inode) & 0x0f; + int dev = iminor(file->f_path.dentry->d_inode) & 0x0f; switch(dev) { diff --git a/trunk/drivers/char/dtlk.c b/trunk/drivers/char/dtlk.c index 5e82c3bad2e3..d4005e94fe5f 100644 --- a/trunk/drivers/char/dtlk.c +++ b/trunk/drivers/char/dtlk.c @@ -122,7 +122,7 @@ static void dtlk_timer_tick(unsigned long data); static ssize_t dtlk_read(struct file *file, char __user *buf, size_t count, loff_t * ppos) { - unsigned int minor = iminor(file->f_dentry->d_inode); + unsigned int minor = iminor(file->f_path.dentry->d_inode); char ch; int i = 0, retries; @@ -174,7 +174,7 @@ static ssize_t dtlk_write(struct file *file, const char __user *buf, } #endif - if (iminor(file->f_dentry->d_inode) != DTLK_MINOR) + if (iminor(file->f_path.dentry->d_inode) != DTLK_MINOR) return -EINVAL; while (1) { diff --git a/trunk/drivers/char/epca.c b/trunk/drivers/char/epca.c index 706733c0b36a..a0f822c9d74d 100644 --- a/trunk/drivers/char/epca.c +++ b/trunk/drivers/char/epca.c @@ -199,8 +199,8 @@ static int pc_ioctl(struct tty_struct *, struct file *, unsigned int, unsigned long); static int info_ioctl(struct tty_struct *, struct file *, unsigned int, unsigned long); -static void pc_set_termios(struct tty_struct *, struct termios *); -static void do_softint(void *); +static void pc_set_termios(struct tty_struct *, struct ktermios *); +static void do_softint(struct work_struct *work); static void pc_stop(struct tty_struct *); static void pc_start(struct tty_struct *); static void pc_throttle(struct tty_struct * tty); @@ -1236,6 +1236,8 @@ static int __init pc_init(void) pc_driver->init_termios.c_oflag = 0; pc_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL; pc_driver->init_termios.c_lflag = 0; + pc_driver->init_termios.c_ispeed = 9600; + pc_driver->init_termios.c_ospeed = 9600; pc_driver->flags = TTY_DRIVER_REAL_RAW; tty_set_operations(pc_driver, &pc_ops); @@ -1250,6 +1252,8 @@ static int __init pc_init(void) pc_info->init_termios.c_oflag = 0; pc_info->init_termios.c_lflag = 0; pc_info->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL; + pc_info->init_termios.c_ispeed = 9600; + pc_info->init_termios.c_ospeed = 9600; pc_info->flags = TTY_DRIVER_REAL_RAW; tty_set_operations(pc_info, &info_ops); @@ -1505,7 +1509,7 @@ static void post_fep_init(unsigned int crd) ch->brdchan = bc; ch->mailbox = gd; - INIT_WORK(&ch->tqueue, do_softint, ch); + INIT_WORK(&ch->tqueue, do_softint); ch->board = &boards[crd]; spin_lock_irqsave(&epca_lock, flags); @@ -1999,7 +2003,7 @@ static void epcaparam(struct tty_struct *tty, struct channel *ch) { /* Begin epcaparam */ unsigned int cmdHead; - struct termios *ts; + struct ktermios *ts; struct board_chan __iomem *bc; unsigned mval, hflow, cflag, iflag; @@ -2114,7 +2118,7 @@ static void receive_data(struct channel *ch) { /* Begin receive_data */ unchar *rptr; - struct termios *ts = NULL; + struct ktermios *ts = NULL; struct tty_struct *tty; struct board_chan __iomem *bc; int dataToRead, wrapgap, bytesAvailable; @@ -2362,12 +2366,14 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file, switch (cmd) { /* Begin switch cmd */ +#if 0 /* Handled by calling layer properly */ case TCGETS: - if (copy_to_user(argp, tty->termios, sizeof(struct termios))) + if (copy_to_user(argp, tty->termios, sizeof(struct ktermios))) return -EFAULT; return 0; case TCGETA: return get_termio(tty, argp); +#endif case TCSBRK: /* SVID version: non-zero arg --> no break */ retval = tty_check_change(tty); if (retval) @@ -2536,7 +2542,7 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file, /* --------------------- Begin pc_set_termios ----------------------- */ -static void pc_set_termios(struct tty_struct *tty, struct termios *old_termios) +static void pc_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { /* Begin pc_set_termios */ struct channel *ch; @@ -2566,9 +2572,9 @@ static void pc_set_termios(struct tty_struct *tty, struct termios *old_termios) /* --------------------- Begin do_softint ----------------------- */ -static void do_softint(void *private_) +static void do_softint(struct work_struct *work) { /* Begin do_softint */ - struct channel *ch = (struct channel *) private_; + struct channel *ch = container_of(work, struct channel, tqueue); /* Called in response to a modem change event */ if (ch && ch->magic == EPCA_MAGIC) { /* Begin EPCA_MAGIC */ struct tty_struct *tty = ch->tty; diff --git a/trunk/drivers/char/esp.c b/trunk/drivers/char/esp.c index 15a4ea896328..d1bfbaa2aa02 100644 --- a/trunk/drivers/char/esp.c +++ b/trunk/drivers/char/esp.c @@ -723,9 +723,10 @@ static irqreturn_t rs_interrupt_single(int irq, void *dev_id) * ------------------------------------------------------------------- */ -static void do_softint(void *private_) +static void do_softint(struct work_struct *work) { - struct esp_struct *info = (struct esp_struct *) private_; + struct esp_struct *info = + container_of(work, struct esp_struct, tqueue); struct tty_struct *tty; tty = info->tty; @@ -746,9 +747,10 @@ static void do_softint(void *private_) * do_serial_hangup() -> tty->hangup() -> esp_hangup() * */ -static void do_serial_hangup(void *private_) +static void do_serial_hangup(struct work_struct *work) { - struct esp_struct *info = (struct esp_struct *) private_; + struct esp_struct *info = + container_of(work, struct esp_struct, tqueue_hangup); struct tty_struct *tty; tty = info->tty; @@ -1913,7 +1915,7 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file, return 0; } -static void rs_set_termios(struct tty_struct *tty, struct termios *old_termios) +static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { struct esp_struct *info = (struct esp_struct *)tty->driver_data; unsigned long flags; @@ -2501,8 +2503,8 @@ static int __init espserial_init(void) info->magic = ESP_MAGIC; info->close_delay = 5*HZ/10; info->closing_wait = 30*HZ; - INIT_WORK(&info->tqueue, do_softint, info); - INIT_WORK(&info->tqueue_hangup, do_serial_hangup, info); + INIT_WORK(&info->tqueue, do_softint); + INIT_WORK(&info->tqueue_hangup, do_serial_hangup); info->config.rx_timeout = rx_timeout; info->config.flow_on = flow_on; info->config.flow_off = flow_off; diff --git a/trunk/drivers/char/generic_serial.c b/trunk/drivers/char/generic_serial.c index 87127e49c0db..e769811e7417 100644 --- a/trunk/drivers/char/generic_serial.c +++ b/trunk/drivers/char/generic_serial.c @@ -718,11 +718,11 @@ static unsigned int gs_baudrates[] = { void gs_set_termios (struct tty_struct * tty, - struct termios * old_termios) + struct ktermios * old_termios) { struct gs_port *port; int baudrate, tmp, rv; - struct termios *tiosp; + struct ktermios *tiosp; func_enter(); diff --git a/trunk/drivers/char/genrtc.c b/trunk/drivers/char/genrtc.c index 817dc409ac20..23b25ada65ea 100644 --- a/trunk/drivers/char/genrtc.c +++ b/trunk/drivers/char/genrtc.c @@ -102,7 +102,7 @@ static void gen_rtc_interrupt(unsigned long arg); * Routine to poll RTC seconds field for change as often as possible, * after first RTC_UIE use timer to reduce polling */ -static void genrtc_troutine(void *data) +static void genrtc_troutine(struct work_struct *work) { unsigned int tmp = get_rtc_ss(); @@ -255,7 +255,7 @@ static inline int gen_set_rtc_irq_bit(unsigned char bit) irq_active = 1; stop_rtc_timers = 0; lostint = 0; - INIT_WORK(&genrtc_task, genrtc_troutine, NULL); + INIT_WORK(&genrtc_task, genrtc_troutine); oldsecs = get_rtc_ss(); init_timer(&timer_task); diff --git a/trunk/drivers/char/hvc_console.c b/trunk/drivers/char/hvc_console.c index 9902ffad3b12..cc2cd46bedc6 100644 --- a/trunk/drivers/char/hvc_console.c +++ b/trunk/drivers/char/hvc_console.c @@ -38,6 +38,7 @@ #include #include #include +#include #include diff --git a/trunk/drivers/char/hvcs.c b/trunk/drivers/char/hvcs.c index 8728255c9463..207f7343ba60 100644 --- a/trunk/drivers/char/hvcs.c +++ b/trunk/drivers/char/hvcs.c @@ -192,11 +192,13 @@ MODULE_VERSION(HVCS_DRIVER_VERSION); * that will cause echoing or we'll go into recursive loop echoing chars back * and forth with the console drivers. */ -static struct termios hvcs_tty_termios = { +static struct ktermios hvcs_tty_termios = { .c_iflag = IGNBRK | IGNPAR, .c_oflag = OPOST, .c_cflag = B38400 | CS8 | CREAD | HUPCL, - .c_cc = INIT_C_CC + .c_cc = INIT_C_CC, + .c_ispeed = 38400, + .c_ospeed = 38400 }; /* @@ -337,11 +339,6 @@ static int hvcs_open(struct tty_struct *tty, struct file *filp); static void hvcs_close(struct tty_struct *tty, struct file *filp); static void hvcs_hangup(struct tty_struct * tty); -static void hvcs_create_device_attrs(struct hvcs_struct *hvcsd); -static void hvcs_remove_device_attrs(struct vio_dev *vdev); -static void hvcs_create_driver_attrs(void); -static void hvcs_remove_driver_attrs(void); - static int __devinit hvcs_probe(struct vio_dev *dev, const struct vio_device_id *id); static int __devexit hvcs_remove(struct vio_dev *dev); @@ -353,6 +350,172 @@ static void __exit hvcs_module_exit(void); #define HVCS_TRY_WRITE 0x00000004 #define HVCS_READ_MASK (HVCS_SCHED_READ | HVCS_QUICK_READ) +static inline struct hvcs_struct *from_vio_dev(struct vio_dev *viod) +{ + return viod->dev.driver_data; +} +/* The sysfs interface for the driver and devices */ + +static ssize_t hvcs_partner_vtys_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct vio_dev *viod = to_vio_dev(dev); + struct hvcs_struct *hvcsd = from_vio_dev(viod); + unsigned long flags; + int retval; + + spin_lock_irqsave(&hvcsd->lock, flags); + retval = sprintf(buf, "%X\n", hvcsd->p_unit_address); + spin_unlock_irqrestore(&hvcsd->lock, flags); + return retval; +} +static DEVICE_ATTR(partner_vtys, S_IRUGO, hvcs_partner_vtys_show, NULL); + +static ssize_t hvcs_partner_clcs_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct vio_dev *viod = to_vio_dev(dev); + struct hvcs_struct *hvcsd = from_vio_dev(viod); + unsigned long flags; + int retval; + + spin_lock_irqsave(&hvcsd->lock, flags); + retval = sprintf(buf, "%s\n", &hvcsd->p_location_code[0]); + spin_unlock_irqrestore(&hvcsd->lock, flags); + return retval; +} +static DEVICE_ATTR(partner_clcs, S_IRUGO, hvcs_partner_clcs_show, NULL); + +static ssize_t hvcs_current_vty_store(struct device *dev, struct device_attribute *attr, const char * buf, + size_t count) +{ + /* + * Don't need this feature at the present time because firmware doesn't + * yet support multiple partners. + */ + printk(KERN_INFO "HVCS: Denied current_vty change: -EPERM.\n"); + return -EPERM; +} + +static ssize_t hvcs_current_vty_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct vio_dev *viod = to_vio_dev(dev); + struct hvcs_struct *hvcsd = from_vio_dev(viod); + unsigned long flags; + int retval; + + spin_lock_irqsave(&hvcsd->lock, flags); + retval = sprintf(buf, "%s\n", &hvcsd->p_location_code[0]); + spin_unlock_irqrestore(&hvcsd->lock, flags); + return retval; +} + +static DEVICE_ATTR(current_vty, + S_IRUGO | S_IWUSR, hvcs_current_vty_show, hvcs_current_vty_store); + +static ssize_t hvcs_vterm_state_store(struct device *dev, struct device_attribute *attr, const char *buf, + size_t count) +{ + struct vio_dev *viod = to_vio_dev(dev); + struct hvcs_struct *hvcsd = from_vio_dev(viod); + unsigned long flags; + + /* writing a '0' to this sysfs entry will result in the disconnect. */ + if (simple_strtol(buf, NULL, 0) != 0) + return -EINVAL; + + spin_lock_irqsave(&hvcsd->lock, flags); + + if (hvcsd->open_count > 0) { + spin_unlock_irqrestore(&hvcsd->lock, flags); + printk(KERN_INFO "HVCS: vterm state unchanged. " + "The hvcs device node is still in use.\n"); + return -EPERM; + } + + if (hvcsd->connected == 0) { + spin_unlock_irqrestore(&hvcsd->lock, flags); + printk(KERN_INFO "HVCS: vterm state unchanged. The" + " vty-server is not connected to a vty.\n"); + return -EPERM; + } + + hvcs_partner_free(hvcsd); + printk(KERN_INFO "HVCS: Closed vty-server@%X and" + " partner vty@%X:%d connection.\n", + hvcsd->vdev->unit_address, + hvcsd->p_unit_address, + (uint32_t)hvcsd->p_partition_ID); + + spin_unlock_irqrestore(&hvcsd->lock, flags); + return count; +} + +static ssize_t hvcs_vterm_state_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct vio_dev *viod = to_vio_dev(dev); + struct hvcs_struct *hvcsd = from_vio_dev(viod); + unsigned long flags; + int retval; + + spin_lock_irqsave(&hvcsd->lock, flags); + retval = sprintf(buf, "%d\n", hvcsd->connected); + spin_unlock_irqrestore(&hvcsd->lock, flags); + return retval; +} +static DEVICE_ATTR(vterm_state, S_IRUGO | S_IWUSR, + hvcs_vterm_state_show, hvcs_vterm_state_store); + +static ssize_t hvcs_index_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct vio_dev *viod = to_vio_dev(dev); + struct hvcs_struct *hvcsd = from_vio_dev(viod); + unsigned long flags; + int retval; + + spin_lock_irqsave(&hvcsd->lock, flags); + retval = sprintf(buf, "%d\n", hvcsd->index); + spin_unlock_irqrestore(&hvcsd->lock, flags); + return retval; +} + +static DEVICE_ATTR(index, S_IRUGO, hvcs_index_show, NULL); + +static struct attribute *hvcs_attrs[] = { + &dev_attr_partner_vtys.attr, + &dev_attr_partner_clcs.attr, + &dev_attr_current_vty.attr, + &dev_attr_vterm_state.attr, + &dev_attr_index.attr, + NULL, +}; + +static struct attribute_group hvcs_attr_group = { + .attrs = hvcs_attrs, +}; + +static ssize_t hvcs_rescan_show(struct device_driver *ddp, char *buf) +{ + /* A 1 means it is updating, a 0 means it is done updating */ + return snprintf(buf, PAGE_SIZE, "%d\n", hvcs_rescan_status); +} + +static ssize_t hvcs_rescan_store(struct device_driver *ddp, const char * buf, + size_t count) +{ + if ((simple_strtol(buf, NULL, 0) != 1) + && (hvcs_rescan_status != 0)) + return -EINVAL; + + hvcs_rescan_status = 1; + printk(KERN_INFO "HVCS: rescanning partner info for all" + " vty-servers.\n"); + hvcs_rescan_devices_list(); + hvcs_rescan_status = 0; + return count; +} + +static DRIVER_ATTR(rescan, + S_IRUGO | S_IWUSR, hvcs_rescan_show, hvcs_rescan_store); + static void hvcs_kick(void) { hvcs_kicked = 1; @@ -575,7 +738,7 @@ static void destroy_hvcs_struct(struct kobject *kobj) spin_unlock_irqrestore(&hvcsd->lock, flags); spin_unlock(&hvcs_structs_lock); - hvcs_remove_device_attrs(vdev); + sysfs_remove_group(&vdev->dev.kobj, &hvcs_attr_group); kfree(hvcsd); } @@ -608,6 +771,7 @@ static int __devinit hvcs_probe( { struct hvcs_struct *hvcsd; int index; + int retval; if (!dev || !id) { printk(KERN_ERR "HVCS: probed with invalid parameter.\n"); @@ -658,14 +822,16 @@ static int __devinit hvcs_probe( * the hvcs_struct has been added to the devices list then the user app * will get -ENODEV. */ - spin_lock(&hvcs_structs_lock); - list_add_tail(&(hvcsd->next), &hvcs_structs); - spin_unlock(&hvcs_structs_lock); - hvcs_create_device_attrs(hvcsd); + retval = sysfs_create_group(&dev->dev.kobj, &hvcs_attr_group); + if (retval) { + printk(KERN_ERR "HVCS: Can't create sysfs attrs for vty-server@%X\n", + hvcsd->vdev->unit_address); + return retval; + } printk(KERN_INFO "HVCS: vty-server@%X added to the vio bus.\n", dev->unit_address); @@ -1354,8 +1520,10 @@ static int __init hvcs_module_init(void) if (!hvcs_tty_driver) return -ENOMEM; - if (hvcs_alloc_index_list(num_ttys_to_alloc)) - return -ENOMEM; + if (hvcs_alloc_index_list(num_ttys_to_alloc)) { + rc = -ENOMEM; + goto index_fail; + } hvcs_tty_driver->owner = THIS_MODULE; @@ -1385,41 +1553,57 @@ static int __init hvcs_module_init(void) * dynamically assigned major and minor numbers for our devices. */ if (tty_register_driver(hvcs_tty_driver)) { - printk(KERN_ERR "HVCS: registration " - " as a tty driver failed.\n"); - hvcs_free_index_list(); - put_tty_driver(hvcs_tty_driver); - return -EIO; + printk(KERN_ERR "HVCS: registration as a tty driver failed.\n"); + rc = -EIO; + goto register_fail; } hvcs_pi_buff = kmalloc(PAGE_SIZE, GFP_KERNEL); if (!hvcs_pi_buff) { - tty_unregister_driver(hvcs_tty_driver); - hvcs_free_index_list(); - put_tty_driver(hvcs_tty_driver); - return -ENOMEM; + rc = -ENOMEM; + goto buff_alloc_fail; } hvcs_task = kthread_run(khvcsd, NULL, "khvcsd"); if (IS_ERR(hvcs_task)) { printk(KERN_ERR "HVCS: khvcsd creation failed. Driver not loaded.\n"); - kfree(hvcs_pi_buff); - tty_unregister_driver(hvcs_tty_driver); - hvcs_free_index_list(); - put_tty_driver(hvcs_tty_driver); - return -EIO; + rc = -EIO; + goto kthread_fail; } rc = vio_register_driver(&hvcs_vio_driver); + if (rc) { + printk(KERN_ERR "HVCS: can't register vio driver\n"); + goto vio_fail; + } /* * This needs to be done AFTER the vio_register_driver() call or else * the kobjects won't be initialized properly. */ - hvcs_create_driver_attrs(); + rc = driver_create_file(&(hvcs_vio_driver.driver), &driver_attr_rescan); + if (rc) { + printk(KERN_ERR "HVCS: sysfs attr create failed\n"); + goto attr_fail; + } printk(KERN_INFO "HVCS: driver module inserted.\n"); + return 0; + +attr_fail: + vio_unregister_driver(&hvcs_vio_driver); +vio_fail: + kthread_stop(hvcs_task); +kthread_fail: + kfree(hvcs_pi_buff); +buff_alloc_fail: + tty_unregister_driver(hvcs_tty_driver); +register_fail: + hvcs_free_index_list(); +index_fail: + put_tty_driver(hvcs_tty_driver); + hvcs_tty_driver = NULL; return rc; } @@ -1441,7 +1625,7 @@ static void __exit hvcs_module_exit(void) hvcs_pi_buff = NULL; spin_unlock(&hvcs_pi_lock); - hvcs_remove_driver_attrs(); + driver_remove_file(&hvcs_vio_driver.driver, &driver_attr_rescan); vio_unregister_driver(&hvcs_vio_driver); @@ -1456,191 +1640,3 @@ static void __exit hvcs_module_exit(void) module_init(hvcs_module_init); module_exit(hvcs_module_exit); - -static inline struct hvcs_struct *from_vio_dev(struct vio_dev *viod) -{ - return viod->dev.driver_data; -} -/* The sysfs interface for the driver and devices */ - -static ssize_t hvcs_partner_vtys_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct vio_dev *viod = to_vio_dev(dev); - struct hvcs_struct *hvcsd = from_vio_dev(viod); - unsigned long flags; - int retval; - - spin_lock_irqsave(&hvcsd->lock, flags); - retval = sprintf(buf, "%X\n", hvcsd->p_unit_address); - spin_unlock_irqrestore(&hvcsd->lock, flags); - return retval; -} -static DEVICE_ATTR(partner_vtys, S_IRUGO, hvcs_partner_vtys_show, NULL); - -static ssize_t hvcs_partner_clcs_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct vio_dev *viod = to_vio_dev(dev); - struct hvcs_struct *hvcsd = from_vio_dev(viod); - unsigned long flags; - int retval; - - spin_lock_irqsave(&hvcsd->lock, flags); - retval = sprintf(buf, "%s\n", &hvcsd->p_location_code[0]); - spin_unlock_irqrestore(&hvcsd->lock, flags); - return retval; -} -static DEVICE_ATTR(partner_clcs, S_IRUGO, hvcs_partner_clcs_show, NULL); - -static ssize_t hvcs_current_vty_store(struct device *dev, struct device_attribute *attr, const char * buf, - size_t count) -{ - /* - * Don't need this feature at the present time because firmware doesn't - * yet support multiple partners. - */ - printk(KERN_INFO "HVCS: Denied current_vty change: -EPERM.\n"); - return -EPERM; -} - -static ssize_t hvcs_current_vty_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct vio_dev *viod = to_vio_dev(dev); - struct hvcs_struct *hvcsd = from_vio_dev(viod); - unsigned long flags; - int retval; - - spin_lock_irqsave(&hvcsd->lock, flags); - retval = sprintf(buf, "%s\n", &hvcsd->p_location_code[0]); - spin_unlock_irqrestore(&hvcsd->lock, flags); - return retval; -} - -static DEVICE_ATTR(current_vty, - S_IRUGO | S_IWUSR, hvcs_current_vty_show, hvcs_current_vty_store); - -static ssize_t hvcs_vterm_state_store(struct device *dev, struct device_attribute *attr, const char *buf, - size_t count) -{ - struct vio_dev *viod = to_vio_dev(dev); - struct hvcs_struct *hvcsd = from_vio_dev(viod); - unsigned long flags; - - /* writing a '0' to this sysfs entry will result in the disconnect. */ - if (simple_strtol(buf, NULL, 0) != 0) - return -EINVAL; - - spin_lock_irqsave(&hvcsd->lock, flags); - - if (hvcsd->open_count > 0) { - spin_unlock_irqrestore(&hvcsd->lock, flags); - printk(KERN_INFO "HVCS: vterm state unchanged. " - "The hvcs device node is still in use.\n"); - return -EPERM; - } - - if (hvcsd->connected == 0) { - spin_unlock_irqrestore(&hvcsd->lock, flags); - printk(KERN_INFO "HVCS: vterm state unchanged. The" - " vty-server is not connected to a vty.\n"); - return -EPERM; - } - - hvcs_partner_free(hvcsd); - printk(KERN_INFO "HVCS: Closed vty-server@%X and" - " partner vty@%X:%d connection.\n", - hvcsd->vdev->unit_address, - hvcsd->p_unit_address, - (uint32_t)hvcsd->p_partition_ID); - - spin_unlock_irqrestore(&hvcsd->lock, flags); - return count; -} - -static ssize_t hvcs_vterm_state_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct vio_dev *viod = to_vio_dev(dev); - struct hvcs_struct *hvcsd = from_vio_dev(viod); - unsigned long flags; - int retval; - - spin_lock_irqsave(&hvcsd->lock, flags); - retval = sprintf(buf, "%d\n", hvcsd->connected); - spin_unlock_irqrestore(&hvcsd->lock, flags); - return retval; -} -static DEVICE_ATTR(vterm_state, S_IRUGO | S_IWUSR, - hvcs_vterm_state_show, hvcs_vterm_state_store); - -static ssize_t hvcs_index_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct vio_dev *viod = to_vio_dev(dev); - struct hvcs_struct *hvcsd = from_vio_dev(viod); - unsigned long flags; - int retval; - - spin_lock_irqsave(&hvcsd->lock, flags); - retval = sprintf(buf, "%d\n", hvcsd->index); - spin_unlock_irqrestore(&hvcsd->lock, flags); - return retval; -} - -static DEVICE_ATTR(index, S_IRUGO, hvcs_index_show, NULL); - -static struct attribute *hvcs_attrs[] = { - &dev_attr_partner_vtys.attr, - &dev_attr_partner_clcs.attr, - &dev_attr_current_vty.attr, - &dev_attr_vterm_state.attr, - &dev_attr_index.attr, - NULL, -}; - -static struct attribute_group hvcs_attr_group = { - .attrs = hvcs_attrs, -}; - -static void hvcs_create_device_attrs(struct hvcs_struct *hvcsd) -{ - struct vio_dev *vdev = hvcsd->vdev; - sysfs_create_group(&vdev->dev.kobj, &hvcs_attr_group); -} - -static void hvcs_remove_device_attrs(struct vio_dev *vdev) -{ - sysfs_remove_group(&vdev->dev.kobj, &hvcs_attr_group); -} - -static ssize_t hvcs_rescan_show(struct device_driver *ddp, char *buf) -{ - /* A 1 means it is updating, a 0 means it is done updating */ - return snprintf(buf, PAGE_SIZE, "%d\n", hvcs_rescan_status); -} - -static ssize_t hvcs_rescan_store(struct device_driver *ddp, const char * buf, - size_t count) -{ - if ((simple_strtol(buf, NULL, 0) != 1) - && (hvcs_rescan_status != 0)) - return -EINVAL; - - hvcs_rescan_status = 1; - printk(KERN_INFO "HVCS: rescanning partner info for all" - " vty-servers.\n"); - hvcs_rescan_devices_list(); - hvcs_rescan_status = 0; - return count; -} -static DRIVER_ATTR(rescan, - S_IRUGO | S_IWUSR, hvcs_rescan_show, hvcs_rescan_store); - -static void hvcs_create_driver_attrs(void) -{ - struct device_driver *driverfs = &(hvcs_vio_driver.driver); - driver_create_file(driverfs, &driver_attr_rescan); -} - -static void hvcs_remove_driver_attrs(void) -{ - struct device_driver *driverfs = &(hvcs_vio_driver.driver); - driver_remove_file(driverfs, &driver_attr_rescan); -} diff --git a/trunk/drivers/char/hvsi.c b/trunk/drivers/char/hvsi.c index 2cf63e7305a3..d7806834fc17 100644 --- a/trunk/drivers/char/hvsi.c +++ b/trunk/drivers/char/hvsi.c @@ -69,7 +69,7 @@ #define __ALIGNED__ __attribute__((__aligned__(sizeof(long)))) struct hvsi_struct { - struct work_struct writer; + struct delayed_work writer; struct work_struct handshaker; wait_queue_head_t emptyq; /* woken when outbuf is emptied */ wait_queue_head_t stateq; /* woken when HVSI state changes */ @@ -744,9 +744,10 @@ static int hvsi_handshake(struct hvsi_struct *hp) return 0; } -static void hvsi_handshaker(void *arg) +static void hvsi_handshaker(struct work_struct *work) { - struct hvsi_struct *hp = (struct hvsi_struct *)arg; + struct hvsi_struct *hp = + container_of(work, struct hvsi_struct, handshaker); if (hvsi_handshake(hp) >= 0) return; @@ -951,9 +952,10 @@ static void hvsi_push(struct hvsi_struct *hp) } /* hvsi_write_worker will keep rescheduling itself until outbuf is empty */ -static void hvsi_write_worker(void *arg) +static void hvsi_write_worker(struct work_struct *work) { - struct hvsi_struct *hp = (struct hvsi_struct *)arg; + struct hvsi_struct *hp = + container_of(work, struct hvsi_struct, writer.work); unsigned long flags; #ifdef DEBUG static long start_j = 0; @@ -1159,6 +1161,8 @@ static int __init hvsi_init(void) hvsi_driver->type = TTY_DRIVER_TYPE_SYSTEM; hvsi_driver->init_termios = tty_std_termios; hvsi_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL; + hvsi_driver->init_termios.c_ispeed = 9600; + hvsi_driver->init_termios.c_ospeed = 9600; hvsi_driver->flags = TTY_DRIVER_REAL_RAW; tty_set_operations(hvsi_driver, &hvsi_ops); @@ -1287,8 +1291,8 @@ static int __init hvsi_console_init(void) } hp = &hvsi_ports[hvsi_count]; - INIT_WORK(&hp->writer, hvsi_write_worker, hp); - INIT_WORK(&hp->handshaker, hvsi_handshaker, hp); + INIT_DELAYED_WORK(&hp->writer, hvsi_write_worker); + INIT_WORK(&hp->handshaker, hvsi_handshaker); init_waitqueue_head(&hp->emptyq); init_waitqueue_head(&hp->stateq); spin_lock_init(&hp->lock); diff --git a/trunk/drivers/char/hw_random/Kconfig b/trunk/drivers/char/hw_random/Kconfig index 9f7635f75178..5f3acd8e64b8 100644 --- a/trunk/drivers/char/hw_random/Kconfig +++ b/trunk/drivers/char/hw_random/Kconfig @@ -3,17 +3,20 @@ # config HW_RANDOM - bool "Hardware Random Number Generator Core support" - default y + tristate "Hardware Random Number Generator Core support" + default m ---help--- Hardware Random Number Generator Core infrastructure. + To compile this driver as a module, choose M here: the + module will be called rng-core. + If unsure, say Y. config HW_RANDOM_INTEL tristate "Intel HW Random Number Generator support" depends on HW_RANDOM && (X86 || IA64) && PCI - default y + default HW_RANDOM ---help--- This driver provides kernel-side support for the Random Number Generator hardware found on Intel i8xx-based motherboards. @@ -26,7 +29,7 @@ config HW_RANDOM_INTEL config HW_RANDOM_AMD tristate "AMD HW Random Number Generator support" depends on HW_RANDOM && X86 && PCI - default y + default HW_RANDOM ---help--- This driver provides kernel-side support for the Random Number Generator hardware found on AMD 76x-based motherboards. @@ -39,7 +42,7 @@ config HW_RANDOM_AMD config HW_RANDOM_GEODE tristate "AMD Geode HW Random Number Generator support" depends on HW_RANDOM && X86 && PCI - default y + default HW_RANDOM ---help--- This driver provides kernel-side support for the Random Number Generator hardware found on the AMD Geode LX. @@ -52,7 +55,7 @@ config HW_RANDOM_GEODE config HW_RANDOM_VIA tristate "VIA HW Random Number Generator support" depends on HW_RANDOM && X86_32 - default y + default HW_RANDOM ---help--- This driver provides kernel-side support for the Random Number Generator hardware found on VIA based motherboards. @@ -65,7 +68,7 @@ config HW_RANDOM_VIA config HW_RANDOM_IXP4XX tristate "Intel IXP4xx NPU HW Random Number Generator support" depends on HW_RANDOM && ARCH_IXP4XX - default y + default HW_RANDOM ---help--- This driver provides kernel-side support for the Random Number Generator hardware found on the Intel IXP4xx NPU. @@ -78,7 +81,7 @@ config HW_RANDOM_IXP4XX config HW_RANDOM_OMAP tristate "OMAP Random Number Generator support" depends on HW_RANDOM && (ARCH_OMAP16XX || ARCH_OMAP24XX) - default y + default HW_RANDOM ---help--- This driver provides kernel-side support for the Random Number Generator hardware found on OMAP16xx and OMAP24xx multimedia diff --git a/trunk/drivers/char/hw_random/Makefile b/trunk/drivers/char/hw_random/Makefile index e263ae96f940..c41fa19454e3 100644 --- a/trunk/drivers/char/hw_random/Makefile +++ b/trunk/drivers/char/hw_random/Makefile @@ -2,7 +2,8 @@ # Makefile for HW Random Number Generator (RNG) device drivers. # -obj-$(CONFIG_HW_RANDOM) += core.o +obj-$(CONFIG_HW_RANDOM) += rng-core.o +rng-core-y := core.o obj-$(CONFIG_HW_RANDOM_INTEL) += intel-rng.o obj-$(CONFIG_HW_RANDOM_AMD) += amd-rng.o obj-$(CONFIG_HW_RANDOM_GEODE) += geode-rng.o diff --git a/trunk/drivers/char/ip2/i2cmd.h b/trunk/drivers/char/ip2/i2cmd.h index baa4e721b758..29277ec6b8ed 100644 --- a/trunk/drivers/char/ip2/i2cmd.h +++ b/trunk/drivers/char/ip2/i2cmd.h @@ -367,11 +367,6 @@ static UCHAR cc02[]; #define CSE_NULL 3 // Replace with a null #define CSE_MARK 4 // Replace with a 3-character sequence (as Unix) -#define CMD_SET_REPLACEMENT(arg,ch) \ - (((cmdSyntaxPtr)(ct36a))->cmd[1] = (arg), \ - (((cmdSyntaxPtr)(ct36a))->cmd[2] = (ch), \ - (cmdSyntaxPtr)(ct36a)) - #define CSE_REPLACE 0x8 // Replace the errored character with the // replacement character defined here diff --git a/trunk/drivers/char/ip2/i2lib.c b/trunk/drivers/char/ip2/i2lib.c index 54d93f0345e8..78045767ec33 100644 --- a/trunk/drivers/char/ip2/i2lib.c +++ b/trunk/drivers/char/ip2/i2lib.c @@ -84,8 +84,8 @@ static void iiSendPendingMail(i2eBordStrPtr); static void serviceOutgoingFifo(i2eBordStrPtr); // Functions defined in ip2.c as part of interrupt handling -static void do_input(void *); -static void do_status(void *); +static void do_input(struct work_struct *); +static void do_status(struct work_struct *); //*************** //* Debug Data * @@ -331,8 +331,8 @@ i2InitChannels ( i2eBordStrPtr pB, int nChannels, i2ChanStrPtr pCh) pCh->ClosingWaitTime = 30*HZ; // Initialize task queue objects - INIT_WORK(&pCh->tqueue_input, do_input, pCh); - INIT_WORK(&pCh->tqueue_status, do_status, pCh); + INIT_WORK(&pCh->tqueue_input, do_input); + INIT_WORK(&pCh->tqueue_status, do_status); #ifdef IP2DEBUG_TRACE pCh->trace = ip2trace; @@ -1016,7 +1016,6 @@ i2Output(i2ChanStrPtr pCh, const char *pSource, int count) unsigned short channel; unsigned short stuffIndex; unsigned long flags; - int rc = 0; int bailout = 10; @@ -1573,7 +1572,7 @@ i2StripFifo(i2eBordStrPtr pB) #ifdef USE_IQ schedule_work(&pCh->tqueue_input); #else - do_input(pCh); + do_input(&pCh->tqueue_input); #endif // Note we do not need to maintain any flow-control credits at this @@ -1810,7 +1809,7 @@ i2StripFifo(i2eBordStrPtr pB) #ifdef USE_IQ schedule_work(&pCh->tqueue_status); #else - do_status(pCh); + do_status(&pCh->tqueue_status); #endif } } diff --git a/trunk/drivers/char/ip2/ip2main.c b/trunk/drivers/char/ip2/ip2main.c index a3f32d46d2f8..7c70310a49b5 100644 --- a/trunk/drivers/char/ip2/ip2main.c +++ b/trunk/drivers/char/ip2/ip2main.c @@ -177,7 +177,7 @@ static int ip2_write_room(PTTY); static int ip2_chars_in_buf(PTTY); static void ip2_flush_buffer(PTTY); static int ip2_ioctl(PTTY, struct file *, UINT, ULONG); -static void ip2_set_termios(PTTY, struct termios *); +static void ip2_set_termios(PTTY, struct ktermios *); static void ip2_set_line_discipline(PTTY); static void ip2_throttle(PTTY); static void ip2_unthrottle(PTTY); @@ -189,16 +189,16 @@ static int ip2_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear); static void set_irq(int, int); -static void ip2_interrupt_bh(i2eBordStrPtr pB); +static void ip2_interrupt_bh(struct work_struct *work); static irqreturn_t ip2_interrupt(int irq, void *dev_id); static void ip2_poll(unsigned long arg); static inline void service_all_boards(void); -static void do_input(void *p); -static void do_status(void *p); +static void do_input(struct work_struct *); +static void do_status(struct work_struct *); static void ip2_wait_until_sent(PTTY,int); -static void set_params (i2ChanStrPtr, struct termios *); +static void set_params (i2ChanStrPtr, struct ktermios *); static int get_serial_info(i2ChanStrPtr, struct serial_struct __user *); static int set_serial_info(i2ChanStrPtr, struct serial_struct __user *); @@ -918,7 +918,7 @@ ip2_init_board( int boardnum ) pCh++; } ex_exit: - INIT_WORK(&pB->tqueue_interrupt, (void(*)(void*)) ip2_interrupt_bh, pB); + INIT_WORK(&pB->tqueue_interrupt, ip2_interrupt_bh); return; err_release_region: @@ -1125,8 +1125,8 @@ service_all_boards(void) /******************************************************************************/ -/* Function: ip2_interrupt_bh(pB) */ -/* Parameters: pB - pointer to the board structure */ +/* Function: ip2_interrupt_bh(work) */ +/* Parameters: work - pointer to the board structure */ /* Returns: Nothing */ /* */ /* Description: */ @@ -1135,8 +1135,9 @@ service_all_boards(void) /* */ /******************************************************************************/ static void -ip2_interrupt_bh(i2eBordStrPtr pB) +ip2_interrupt_bh(struct work_struct *work) { + i2eBordStrPtr pB = container_of(work, i2eBordStr, tqueue_interrupt); // pB better well be set or we have a problem! We can only get // here from the IMMEDIATE queue. Here, we process the boards. // Checking pB doesn't cost much and it saves us from the sanity checkers. @@ -1245,9 +1246,9 @@ ip2_poll(unsigned long arg) ip2trace (ITRC_NO_PORT, ITRC_INTR, ITRC_RETURN, 0 ); } -static void do_input(void *p) +static void do_input(struct work_struct *work) { - i2ChanStrPtr pCh = p; + i2ChanStrPtr pCh = container_of(work, i2ChanStr, tqueue_input); unsigned long flags; ip2trace(CHANN, ITRC_INPUT, 21, 0 ); @@ -1279,9 +1280,9 @@ static inline void isig(int sig, struct tty_struct *tty, int flush) } } -static void do_status(void *p) +static void do_status(struct work_struct *work) { - i2ChanStrPtr pCh = p; + i2ChanStrPtr pCh = container_of(work, i2ChanStr, tqueue_status); int status; status = i2GetStatus( pCh, (I2_BRK|I2_PAR|I2_FRA|I2_OVR) ); @@ -2397,7 +2398,7 @@ set_serial_info( i2ChanStrPtr pCh, struct serial_struct __user *new_info ) /* */ /******************************************************************************/ static void -ip2_set_termios( PTTY tty, struct termios *old_termios ) +ip2_set_termios( PTTY tty, struct ktermios *old_termios ) { i2ChanStrPtr pCh = (i2ChanStrPtr)tty->driver_data; @@ -2439,11 +2440,11 @@ ip2_set_line_discipline ( PTTY tty ) /* change. */ /******************************************************************************/ static void -set_params( i2ChanStrPtr pCh, struct termios *o_tios ) +set_params( i2ChanStrPtr pCh, struct ktermios *o_tios ) { tcflag_t cflag, iflag, lflag; char stop_char, start_char; - struct termios dummy; + struct ktermios dummy; lflag = pCh->pTTY->termios->c_lflag; cflag = pCh->pTTY->termios->c_cflag; @@ -2699,7 +2700,7 @@ static ssize_t ip2_ipl_read(struct file *pFile, char __user *pData, size_t count, loff_t *off ) { - unsigned int minor = iminor(pFile->f_dentry->d_inode); + unsigned int minor = iminor(pFile->f_path.dentry->d_inode); int rc = 0; #ifdef IP2DEBUG_IPL diff --git a/trunk/drivers/char/ipmi/ipmi_bt_sm.c b/trunk/drivers/char/ipmi/ipmi_bt_sm.c index 0030cd8e2e95..6c59baa887a8 100644 --- a/trunk/drivers/char/ipmi/ipmi_bt_sm.c +++ b/trunk/drivers/char/ipmi/ipmi_bt_sm.c @@ -33,11 +33,13 @@ #include /* for completion codes */ #include "ipmi_si_sm.h" -static int bt_debug = 0x00; /* Production value 0, see following flags */ +#define BT_DEBUG_OFF 0 /* Used in production */ +#define BT_DEBUG_ENABLE 1 /* Generic messages */ +#define BT_DEBUG_MSG 2 /* Prints all request/response buffers */ +#define BT_DEBUG_STATES 4 /* Verbose look at state changes */ + +static int bt_debug = BT_DEBUG_OFF; -#define BT_DEBUG_ENABLE 1 -#define BT_DEBUG_MSG 2 -#define BT_DEBUG_STATES 4 module_param(bt_debug, int, 0644); MODULE_PARM_DESC(bt_debug, "debug bitmask, 1=enable, 2=messages, 4=states"); @@ -47,38 +49,54 @@ MODULE_PARM_DESC(bt_debug, "debug bitmask, 1=enable, 2=messages, 4=states"); Since the Open IPMI architecture is single-message oriented at this stage, the queue depth of BT is of no concern. */ -#define BT_NORMAL_TIMEOUT 5000000 /* seconds in microseconds */ -#define BT_RETRY_LIMIT 2 -#define BT_RESET_DELAY 6000000 /* 6 seconds after warm reset */ +#define BT_NORMAL_TIMEOUT 5 /* seconds */ +#define BT_NORMAL_RETRY_LIMIT 2 +#define BT_RESET_DELAY 6 /* seconds after warm reset */ + +/* States are written in chronological order and usually cover + multiple rows of the state table discussion in the IPMI spec. */ enum bt_states { - BT_STATE_IDLE, + BT_STATE_IDLE = 0, /* Order is critical in this list */ BT_STATE_XACTION_START, BT_STATE_WRITE_BYTES, - BT_STATE_WRITE_END, BT_STATE_WRITE_CONSUME, - BT_STATE_B2H_WAIT, - BT_STATE_READ_END, - BT_STATE_RESET1, /* These must come last */ + BT_STATE_READ_WAIT, + BT_STATE_CLEAR_B2H, + BT_STATE_READ_BYTES, + BT_STATE_RESET1, /* These must come last */ BT_STATE_RESET2, BT_STATE_RESET3, BT_STATE_RESTART, - BT_STATE_HOSED + BT_STATE_PRINTME, + BT_STATE_CAPABILITIES_BEGIN, + BT_STATE_CAPABILITIES_END, + BT_STATE_LONG_BUSY /* BT doesn't get hosed :-) */ }; +/* Macros seen at the end of state "case" blocks. They help with legibility + and debugging. */ + +#define BT_STATE_CHANGE(X,Y) { bt->state = X; return Y; } + +#define BT_SI_SM_RETURN(Y) { last_printed = BT_STATE_PRINTME; return Y; } + struct si_sm_data { enum bt_states state; - enum bt_states last_state; /* assist printing and resets */ unsigned char seq; /* BT sequence number */ struct si_sm_io *io; - unsigned char write_data[IPMI_MAX_MSG_LENGTH]; - int write_count; - unsigned char read_data[IPMI_MAX_MSG_LENGTH]; - int read_count; - int truncated; - long timeout; - unsigned int error_retries; /* end of "common" fields */ + unsigned char write_data[IPMI_MAX_MSG_LENGTH]; + int write_count; + unsigned char read_data[IPMI_MAX_MSG_LENGTH]; + int read_count; + int truncated; + long timeout; /* microseconds countdown */ + int error_retries; /* end of "common" fields */ int nonzero_status; /* hung BMCs stay all 0 */ + enum bt_states complete; /* to divert the state machine */ + int BT_CAP_outreqs; + long BT_CAP_req2rsp; + int BT_CAP_retries; /* Recommended retries */ }; #define BT_CLR_WR_PTR 0x01 /* See IPMI 1.5 table 11.6.4 */ @@ -111,86 +129,118 @@ struct si_sm_data { static char *state2txt(unsigned char state) { switch (state) { - case BT_STATE_IDLE: return("IDLE"); - case BT_STATE_XACTION_START: return("XACTION"); - case BT_STATE_WRITE_BYTES: return("WR_BYTES"); - case BT_STATE_WRITE_END: return("WR_END"); - case BT_STATE_WRITE_CONSUME: return("WR_CONSUME"); - case BT_STATE_B2H_WAIT: return("B2H_WAIT"); - case BT_STATE_READ_END: return("RD_END"); - case BT_STATE_RESET1: return("RESET1"); - case BT_STATE_RESET2: return("RESET2"); - case BT_STATE_RESET3: return("RESET3"); - case BT_STATE_RESTART: return("RESTART"); - case BT_STATE_HOSED: return("HOSED"); + case BT_STATE_IDLE: return("IDLE"); + case BT_STATE_XACTION_START: return("XACTION"); + case BT_STATE_WRITE_BYTES: return("WR_BYTES"); + case BT_STATE_WRITE_CONSUME: return("WR_CONSUME"); + case BT_STATE_READ_WAIT: return("RD_WAIT"); + case BT_STATE_CLEAR_B2H: return("CLEAR_B2H"); + case BT_STATE_READ_BYTES: return("RD_BYTES"); + case BT_STATE_RESET1: return("RESET1"); + case BT_STATE_RESET2: return("RESET2"); + case BT_STATE_RESET3: return("RESET3"); + case BT_STATE_RESTART: return("RESTART"); + case BT_STATE_LONG_BUSY: return("LONG_BUSY"); + case BT_STATE_CAPABILITIES_BEGIN: return("CAP_BEGIN"); + case BT_STATE_CAPABILITIES_END: return("CAP_END"); } return("BAD STATE"); } #define STATE2TXT state2txt(bt->state) -static char *status2txt(unsigned char status, char *buf) +static char *status2txt(unsigned char status) { + /* + * This cannot be called by two threads at the same time and + * the buffer is always consumed immediately, so the static is + * safe to use. + */ + static char buf[40]; + strcpy(buf, "[ "); - if (status & BT_B_BUSY) strcat(buf, "B_BUSY "); - if (status & BT_H_BUSY) strcat(buf, "H_BUSY "); - if (status & BT_OEM0) strcat(buf, "OEM0 "); - if (status & BT_SMS_ATN) strcat(buf, "SMS "); - if (status & BT_B2H_ATN) strcat(buf, "B2H "); - if (status & BT_H2B_ATN) strcat(buf, "H2B "); + if (status & BT_B_BUSY) + strcat(buf, "B_BUSY "); + if (status & BT_H_BUSY) + strcat(buf, "H_BUSY "); + if (status & BT_OEM0) + strcat(buf, "OEM0 "); + if (status & BT_SMS_ATN) + strcat(buf, "SMS "); + if (status & BT_B2H_ATN) + strcat(buf, "B2H "); + if (status & BT_H2B_ATN) + strcat(buf, "H2B "); strcat(buf, "]"); return buf; } -#define STATUS2TXT(buf) status2txt(status, buf) +#define STATUS2TXT status2txt(status) + +/* called externally at insmod time, and internally on cleanup */ -/* This will be called from within this module on a hosed condition */ -#define FIRST_SEQ 0 static unsigned int bt_init_data(struct si_sm_data *bt, struct si_sm_io *io) { - bt->state = BT_STATE_IDLE; - bt->last_state = BT_STATE_IDLE; - bt->seq = FIRST_SEQ; - bt->io = io; - bt->write_count = 0; - bt->read_count = 0; - bt->error_retries = 0; - bt->nonzero_status = 0; - bt->truncated = 0; - bt->timeout = BT_NORMAL_TIMEOUT; + memset(bt, 0, sizeof(struct si_sm_data)); + if (bt->io != io) { /* external: one-time only things */ + bt->io = io; + bt->seq = 0; + } + bt->state = BT_STATE_IDLE; /* start here */ + bt->complete = BT_STATE_IDLE; /* end here */ + bt->BT_CAP_req2rsp = BT_NORMAL_TIMEOUT * 1000000; + bt->BT_CAP_retries = BT_NORMAL_RETRY_LIMIT; + /* BT_CAP_outreqs == zero is a flag to read BT Capabilities */ return 3; /* We claim 3 bytes of space; ought to check SPMI table */ } +/* Jam a completion code (probably an error) into a response */ + +static void force_result(struct si_sm_data *bt, unsigned char completion_code) +{ + bt->read_data[0] = 4; /* # following bytes */ + bt->read_data[1] = bt->write_data[1] | 4; /* Odd NetFn/LUN */ + bt->read_data[2] = bt->write_data[2]; /* seq (ignored) */ + bt->read_data[3] = bt->write_data[3]; /* Command */ + bt->read_data[4] = completion_code; + bt->read_count = 5; +} + +/* The upper state machine starts here */ + static int bt_start_transaction(struct si_sm_data *bt, unsigned char *data, unsigned int size) { unsigned int i; - if ((size < 2) || (size > (IPMI_MAX_MSG_LENGTH - 2))) - return -1; + if (size < 2) + return IPMI_REQ_LEN_INVALID_ERR; + if (size > IPMI_MAX_MSG_LENGTH) + return IPMI_REQ_LEN_EXCEEDED_ERR; - if ((bt->state != BT_STATE_IDLE) && (bt->state != BT_STATE_HOSED)) - return -2; + if (bt->state == BT_STATE_LONG_BUSY) + return IPMI_NODE_BUSY_ERR; + + if (bt->state != BT_STATE_IDLE) + return IPMI_NOT_IN_MY_STATE_ERR; if (bt_debug & BT_DEBUG_MSG) { - printk(KERN_WARNING "+++++++++++++++++++++++++++++++++++++\n"); - printk(KERN_WARNING "BT: write seq=0x%02X:", bt->seq); + printk(KERN_WARNING "BT: +++++++++++++++++ New command\n"); + printk(KERN_WARNING "BT: NetFn/LUN CMD [%d data]:", size - 2); for (i = 0; i < size; i ++) - printk (" %02x", data[i]); + printk (" %02x", data[i]); printk("\n"); } bt->write_data[0] = size + 1; /* all data plus seq byte */ bt->write_data[1] = *data; /* NetFn/LUN */ - bt->write_data[2] = bt->seq; + bt->write_data[2] = bt->seq++; memcpy(bt->write_data + 3, data + 1, size - 1); bt->write_count = size + 2; - bt->error_retries = 0; bt->nonzero_status = 0; - bt->read_count = 0; bt->truncated = 0; bt->state = BT_STATE_XACTION_START; - bt->last_state = BT_STATE_IDLE; - bt->timeout = BT_NORMAL_TIMEOUT; + bt->timeout = bt->BT_CAP_req2rsp; + force_result(bt, IPMI_ERR_UNSPECIFIED); return 0; } @@ -198,38 +248,30 @@ static int bt_start_transaction(struct si_sm_data *bt, it calls this. Strip out the length and seq bytes. */ static int bt_get_result(struct si_sm_data *bt, - unsigned char *data, - unsigned int length) + unsigned char *data, + unsigned int length) { int i, msg_len; msg_len = bt->read_count - 2; /* account for length & seq */ - /* Always NetFn, Cmd, cCode */ if (msg_len < 3 || msg_len > IPMI_MAX_MSG_LENGTH) { - printk(KERN_DEBUG "BT results: bad msg_len = %d\n", msg_len); - data[0] = bt->write_data[1] | 0x4; /* Kludge a response */ - data[1] = bt->write_data[3]; - data[2] = IPMI_ERR_UNSPECIFIED; + force_result(bt, IPMI_ERR_UNSPECIFIED); msg_len = 3; - } else { - data[0] = bt->read_data[1]; - data[1] = bt->read_data[3]; - if (length < msg_len) - bt->truncated = 1; - if (bt->truncated) { /* can be set in read_all_bytes() */ - data[2] = IPMI_ERR_MSG_TRUNCATED; - msg_len = 3; - } else - memcpy(data + 2, bt->read_data + 4, msg_len - 2); + } + data[0] = bt->read_data[1]; + data[1] = bt->read_data[3]; + if (length < msg_len || bt->truncated) { + data[2] = IPMI_ERR_MSG_TRUNCATED; + msg_len = 3; + } else + memcpy(data + 2, bt->read_data + 4, msg_len - 2); - if (bt_debug & BT_DEBUG_MSG) { - printk (KERN_WARNING "BT: res (raw)"); - for (i = 0; i < msg_len; i++) - printk(" %02x", data[i]); - printk ("\n"); - } + if (bt_debug & BT_DEBUG_MSG) { + printk (KERN_WARNING "BT: result %d bytes:", msg_len); + for (i = 0; i < msg_len; i++) + printk(" %02x", data[i]); + printk ("\n"); } - bt->read_count = 0; /* paranoia */ return msg_len; } @@ -238,22 +280,40 @@ static int bt_get_result(struct si_sm_data *bt, static void reset_flags(struct si_sm_data *bt) { + if (bt_debug) + printk(KERN_WARNING "IPMI BT: flag reset %s\n", + status2txt(BT_STATUS)); if (BT_STATUS & BT_H_BUSY) - BT_CONTROL(BT_H_BUSY); - if (BT_STATUS & BT_B_BUSY) - BT_CONTROL(BT_B_BUSY); - BT_CONTROL(BT_CLR_WR_PTR); - BT_CONTROL(BT_SMS_ATN); - - if (BT_STATUS & BT_B2H_ATN) { - int i; - BT_CONTROL(BT_H_BUSY); - BT_CONTROL(BT_B2H_ATN); - BT_CONTROL(BT_CLR_RD_PTR); - for (i = 0; i < IPMI_MAX_MSG_LENGTH + 2; i++) - BMC2HOST; - BT_CONTROL(BT_H_BUSY); - } + BT_CONTROL(BT_H_BUSY); /* force clear */ + BT_CONTROL(BT_CLR_WR_PTR); /* always reset */ + BT_CONTROL(BT_SMS_ATN); /* always clear */ + BT_INTMASK_W(BT_BMC_HWRST); +} + +/* Get rid of an unwanted/stale response. This should only be needed for + BMCs that support multiple outstanding requests. */ + +static void drain_BMC2HOST(struct si_sm_data *bt) +{ + int i, size; + + if (!(BT_STATUS & BT_B2H_ATN)) /* Not signalling a response */ + return; + + BT_CONTROL(BT_H_BUSY); /* now set */ + BT_CONTROL(BT_B2H_ATN); /* always clear */ + BT_STATUS; /* pause */ + BT_CONTROL(BT_B2H_ATN); /* some BMCs are stubborn */ + BT_CONTROL(BT_CLR_RD_PTR); /* always reset */ + if (bt_debug) + printk(KERN_WARNING "IPMI BT: stale response %s; ", + status2txt(BT_STATUS)); + size = BMC2HOST; + for (i = 0; i < size ; i++) + BMC2HOST; + BT_CONTROL(BT_H_BUSY); /* now clear */ + if (bt_debug) + printk("drained %d bytes\n", size + 1); } static inline void write_all_bytes(struct si_sm_data *bt) @@ -261,201 +321,256 @@ static inline void write_all_bytes(struct si_sm_data *bt) int i; if (bt_debug & BT_DEBUG_MSG) { - printk(KERN_WARNING "BT: write %d bytes seq=0x%02X", + printk(KERN_WARNING "BT: write %d bytes seq=0x%02X", bt->write_count, bt->seq); for (i = 0; i < bt->write_count; i++) printk (" %02x", bt->write_data[i]); printk ("\n"); } for (i = 0; i < bt->write_count; i++) - HOST2BMC(bt->write_data[i]); + HOST2BMC(bt->write_data[i]); } static inline int read_all_bytes(struct si_sm_data *bt) { unsigned char i; + /* length is "framing info", minimum = 4: NetFn, Seq, Cmd, cCode. + Keep layout of first four bytes aligned with write_data[] */ + bt->read_data[0] = BMC2HOST; bt->read_count = bt->read_data[0]; - if (bt_debug & BT_DEBUG_MSG) - printk(KERN_WARNING "BT: read %d bytes:", bt->read_count); - /* minimum: length, NetFn, Seq, Cmd, cCode == 5 total, or 4 more - following the length byte. */ if (bt->read_count < 4 || bt->read_count >= IPMI_MAX_MSG_LENGTH) { if (bt_debug & BT_DEBUG_MSG) - printk("bad length %d\n", bt->read_count); + printk(KERN_WARNING "BT: bad raw rsp len=%d\n", + bt->read_count); bt->truncated = 1; return 1; /* let next XACTION START clean it up */ } for (i = 1; i <= bt->read_count; i++) - bt->read_data[i] = BMC2HOST; - bt->read_count++; /* account for the length byte */ + bt->read_data[i] = BMC2HOST; + bt->read_count++; /* Account internally for length byte */ if (bt_debug & BT_DEBUG_MSG) { - for (i = 0; i < bt->read_count; i++) + int max = bt->read_count; + + printk(KERN_WARNING "BT: got %d bytes seq=0x%02X", + max, bt->read_data[2]); + if (max > 16) + max = 16; + for (i = 0; i < max; i++) printk (" %02x", bt->read_data[i]); - printk ("\n"); + printk ("%s\n", bt->read_count == max ? "" : " ..."); } - if (bt->seq != bt->write_data[2]) /* idiot check */ - printk(KERN_DEBUG "BT: internal error: sequence mismatch\n"); - /* per the spec, the (NetFn, Seq, Cmd) tuples should match */ - if ((bt->read_data[3] == bt->write_data[3]) && /* Cmd */ - (bt->read_data[2] == bt->write_data[2]) && /* Sequence */ - ((bt->read_data[1] & 0xF8) == (bt->write_data[1] & 0xF8))) + /* per the spec, the (NetFn[1], Seq[2], Cmd[3]) tuples must match */ + if ((bt->read_data[3] == bt->write_data[3]) && + (bt->read_data[2] == bt->write_data[2]) && + ((bt->read_data[1] & 0xF8) == (bt->write_data[1] & 0xF8))) return 1; if (bt_debug & BT_DEBUG_MSG) - printk(KERN_WARNING "BT: bad packet: " + printk(KERN_WARNING "IPMI BT: bad packet: " "want 0x(%02X, %02X, %02X) got (%02X, %02X, %02X)\n", - bt->write_data[1], bt->write_data[2], bt->write_data[3], + bt->write_data[1] | 0x04, bt->write_data[2], bt->write_data[3], bt->read_data[1], bt->read_data[2], bt->read_data[3]); return 0; } -/* Modifies bt->state appropriately, need to get into the bt_event() switch */ +/* Restart if retries are left, or return an error completion code */ -static void error_recovery(struct si_sm_data *bt, char *reason) +static enum si_sm_result error_recovery(struct si_sm_data *bt, + unsigned char status, + unsigned char cCode) { - unsigned char status; - char buf[40]; /* For getting status */ + char *reason; - bt->timeout = BT_NORMAL_TIMEOUT; /* various places want to retry */ + bt->timeout = bt->BT_CAP_req2rsp; - status = BT_STATUS; - printk(KERN_DEBUG "BT: %s in %s %s\n", reason, STATE2TXT, - STATUS2TXT(buf)); + switch (cCode) { + case IPMI_TIMEOUT_ERR: + reason = "timeout"; + break; + default: + reason = "internal error"; + break; + } + + printk(KERN_WARNING "IPMI BT: %s in %s %s ", /* open-ended line */ + reason, STATE2TXT, STATUS2TXT); + /* Per the IPMI spec, retries are based on the sequence number + known only to this module, so manage a restart here. */ (bt->error_retries)++; - if (bt->error_retries > BT_RETRY_LIMIT) { - printk(KERN_DEBUG "retry limit (%d) exceeded\n", BT_RETRY_LIMIT); - bt->state = BT_STATE_HOSED; - if (!bt->nonzero_status) - printk(KERN_ERR "IPMI: BT stuck, try power cycle\n"); - else if (bt->error_retries <= BT_RETRY_LIMIT + 1) { - printk(KERN_DEBUG "IPMI: BT reset (takes 5 secs)\n"); - bt->state = BT_STATE_RESET1; - } - return; + if (bt->error_retries < bt->BT_CAP_retries) { + printk("%d retries left\n", + bt->BT_CAP_retries - bt->error_retries); + bt->state = BT_STATE_RESTART; + return SI_SM_CALL_WITHOUT_DELAY; } - /* Sometimes the BMC queues get in an "off-by-one" state...*/ - if ((bt->state == BT_STATE_B2H_WAIT) && (status & BT_B2H_ATN)) { - printk(KERN_DEBUG "retry B2H_WAIT\n"); - return; + printk("failed %d retries, sending error response\n", + bt->BT_CAP_retries); + if (!bt->nonzero_status) + printk(KERN_ERR "IPMI BT: stuck, try power cycle\n"); + + /* this is most likely during insmod */ + else if (bt->seq <= (unsigned char)(bt->BT_CAP_retries & 0xFF)) { + printk(KERN_WARNING "IPMI: BT reset (takes 5 secs)\n"); + bt->state = BT_STATE_RESET1; + return SI_SM_CALL_WITHOUT_DELAY; } - printk(KERN_DEBUG "restart command\n"); - bt->state = BT_STATE_RESTART; + /* Concoct a useful error message, set up the next state, and + be done with this sequence. */ + + bt->state = BT_STATE_IDLE; + switch (cCode) { + case IPMI_TIMEOUT_ERR: + if (status & BT_B_BUSY) { + cCode = IPMI_NODE_BUSY_ERR; + bt->state = BT_STATE_LONG_BUSY; + } + break; + default: + break; + } + force_result(bt, cCode); + return SI_SM_TRANSACTION_COMPLETE; } -/* Check the status and (possibly) advance the BT state machine. The - default return is SI_SM_CALL_WITH_DELAY. */ +/* Check status and (usually) take action and change this state machine. */ static enum si_sm_result bt_event(struct si_sm_data *bt, long time) { - unsigned char status; - char buf[40]; /* For getting status */ + unsigned char status, BT_CAP[8]; + static enum bt_states last_printed = BT_STATE_PRINTME; int i; status = BT_STATUS; bt->nonzero_status |= status; - - if ((bt_debug & BT_DEBUG_STATES) && (bt->state != bt->last_state)) + if ((bt_debug & BT_DEBUG_STATES) && (bt->state != last_printed)) { printk(KERN_WARNING "BT: %s %s TO=%ld - %ld \n", STATE2TXT, - STATUS2TXT(buf), + STATUS2TXT, bt->timeout, time); - bt->last_state = bt->state; + last_printed = bt->state; + } - if (bt->state == BT_STATE_HOSED) - return SI_SM_HOSED; + /* Commands that time out may still (eventually) provide a response. + This stale response will get in the way of a new response so remove + it if possible (hopefully during IDLE). Even if it comes up later + it will be rejected by its (now-forgotten) seq number. */ + + if ((bt->state < BT_STATE_WRITE_BYTES) && (status & BT_B2H_ATN)) { + drain_BMC2HOST(bt); + BT_SI_SM_RETURN(SI_SM_CALL_WITH_DELAY); + } - if (bt->state != BT_STATE_IDLE) { /* do timeout test */ + if ((bt->state != BT_STATE_IDLE) && + (bt->state < BT_STATE_PRINTME)) { /* check timeout */ bt->timeout -= time; - if ((bt->timeout < 0) && (bt->state < BT_STATE_RESET1)) { - error_recovery(bt, "timed out"); - return SI_SM_CALL_WITHOUT_DELAY; - } + if ((bt->timeout < 0) && (bt->state < BT_STATE_RESET1)) + return error_recovery(bt, + status, + IPMI_TIMEOUT_ERR); } switch (bt->state) { - case BT_STATE_IDLE: /* check for asynchronous messages */ + /* Idle state first checks for asynchronous messages from another + channel, then does some opportunistic housekeeping. */ + + case BT_STATE_IDLE: if (status & BT_SMS_ATN) { BT_CONTROL(BT_SMS_ATN); /* clear it */ return SI_SM_ATTN; } - return SI_SM_IDLE; - case BT_STATE_XACTION_START: - if (status & BT_H_BUSY) { + if (status & BT_H_BUSY) /* clear a leftover H_BUSY */ BT_CONTROL(BT_H_BUSY); - break; - } - if (status & BT_B2H_ATN) - break; - bt->state = BT_STATE_WRITE_BYTES; - return SI_SM_CALL_WITHOUT_DELAY; /* for logging */ - case BT_STATE_WRITE_BYTES: + /* Read BT capabilities if it hasn't been done yet */ + if (!bt->BT_CAP_outreqs) + BT_STATE_CHANGE(BT_STATE_CAPABILITIES_BEGIN, + SI_SM_CALL_WITHOUT_DELAY); + bt->timeout = bt->BT_CAP_req2rsp; + BT_SI_SM_RETURN(SI_SM_IDLE); + + case BT_STATE_XACTION_START: if (status & (BT_B_BUSY | BT_H2B_ATN)) - break; + BT_SI_SM_RETURN(SI_SM_CALL_WITH_DELAY); + if (BT_STATUS & BT_H_BUSY) + BT_CONTROL(BT_H_BUSY); /* force clear */ + BT_STATE_CHANGE(BT_STATE_WRITE_BYTES, + SI_SM_CALL_WITHOUT_DELAY); + + case BT_STATE_WRITE_BYTES: + if (status & BT_H_BUSY) + BT_CONTROL(BT_H_BUSY); /* clear */ BT_CONTROL(BT_CLR_WR_PTR); write_all_bytes(bt); - BT_CONTROL(BT_H2B_ATN); /* clears too fast to catch? */ - bt->state = BT_STATE_WRITE_CONSUME; - return SI_SM_CALL_WITHOUT_DELAY; /* it MIGHT sail through */ - - case BT_STATE_WRITE_CONSUME: /* BMCs usually blow right thru here */ - if (status & (BT_H2B_ATN | BT_B_BUSY)) - break; - bt->state = BT_STATE_B2H_WAIT; - /* fall through with status */ - - /* Stay in BT_STATE_B2H_WAIT until a packet matches. However, spinning - hard here, constantly reading status, seems to hold off the - generation of B2H_ATN so ALWAYS return CALL_WITH_DELAY. */ - - case BT_STATE_B2H_WAIT: - if (!(status & BT_B2H_ATN)) - break; - - /* Assume ordered, uncached writes: no need to wait */ - if (!(status & BT_H_BUSY)) - BT_CONTROL(BT_H_BUSY); /* set */ - BT_CONTROL(BT_B2H_ATN); /* clear it, ACK to the BMC */ - BT_CONTROL(BT_CLR_RD_PTR); /* reset the queue */ - i = read_all_bytes(bt); - BT_CONTROL(BT_H_BUSY); /* clear */ - if (!i) /* Try this state again */ - break; - bt->state = BT_STATE_READ_END; - return SI_SM_CALL_WITHOUT_DELAY; /* for logging */ - - case BT_STATE_READ_END: - - /* I could wait on BT_H_BUSY to go clear for a truly clean - exit. However, this is already done in XACTION_START - and the (possible) extra loop/status/possible wait affects - performance. So, as long as it works, just ignore H_BUSY */ - -#ifdef MAKE_THIS_TRUE_IF_NECESSARY + BT_CONTROL(BT_H2B_ATN); /* can clear too fast to catch */ + BT_STATE_CHANGE(BT_STATE_WRITE_CONSUME, + SI_SM_CALL_WITHOUT_DELAY); - if (status & BT_H_BUSY) - break; -#endif - bt->seq++; - bt->state = BT_STATE_IDLE; - return SI_SM_TRANSACTION_COMPLETE; + case BT_STATE_WRITE_CONSUME: + if (status & (BT_B_BUSY | BT_H2B_ATN)) + BT_SI_SM_RETURN(SI_SM_CALL_WITH_DELAY); + BT_STATE_CHANGE(BT_STATE_READ_WAIT, + SI_SM_CALL_WITHOUT_DELAY); + + /* Spinning hard can suppress B2H_ATN and force a timeout */ + + case BT_STATE_READ_WAIT: + if (!(status & BT_B2H_ATN)) + BT_SI_SM_RETURN(SI_SM_CALL_WITH_DELAY); + BT_CONTROL(BT_H_BUSY); /* set */ + + /* Uncached, ordered writes should just proceeed serially but + some BMCs don't clear B2H_ATN with one hit. Fast-path a + workaround without too much penalty to the general case. */ + + BT_CONTROL(BT_B2H_ATN); /* clear it to ACK the BMC */ + BT_STATE_CHANGE(BT_STATE_CLEAR_B2H, + SI_SM_CALL_WITHOUT_DELAY); + + case BT_STATE_CLEAR_B2H: + if (status & BT_B2H_ATN) { /* keep hitting it */ + BT_CONTROL(BT_B2H_ATN); + BT_SI_SM_RETURN(SI_SM_CALL_WITH_DELAY); + } + BT_STATE_CHANGE(BT_STATE_READ_BYTES, + SI_SM_CALL_WITHOUT_DELAY); + + case BT_STATE_READ_BYTES: + if (!(status & BT_H_BUSY)) /* check in case of retry */ + BT_CONTROL(BT_H_BUSY); + BT_CONTROL(BT_CLR_RD_PTR); /* start of BMC2HOST buffer */ + i = read_all_bytes(bt); /* true == packet seq match */ + BT_CONTROL(BT_H_BUSY); /* NOW clear */ + if (!i) /* Not my message */ + BT_STATE_CHANGE(BT_STATE_READ_WAIT, + SI_SM_CALL_WITHOUT_DELAY); + bt->state = bt->complete; + return bt->state == BT_STATE_IDLE ? /* where to next? */ + SI_SM_TRANSACTION_COMPLETE : /* normal */ + SI_SM_CALL_WITHOUT_DELAY; /* Startup magic */ + + case BT_STATE_LONG_BUSY: /* For example: after FW update */ + if (!(status & BT_B_BUSY)) { + reset_flags(bt); /* next state is now IDLE */ + bt_init_data(bt, bt->io); + } + return SI_SM_CALL_WITH_DELAY; /* No repeat printing */ case BT_STATE_RESET1: - reset_flags(bt); - bt->timeout = BT_RESET_DELAY; - bt->state = BT_STATE_RESET2; - break; + reset_flags(bt); + drain_BMC2HOST(bt); + BT_STATE_CHANGE(BT_STATE_RESET2, + SI_SM_CALL_WITH_DELAY); case BT_STATE_RESET2: /* Send a soft reset */ BT_CONTROL(BT_CLR_WR_PTR); @@ -464,29 +579,59 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time) HOST2BMC(42); /* Sequence number */ HOST2BMC(3); /* Cmd == Soft reset */ BT_CONTROL(BT_H2B_ATN); - bt->state = BT_STATE_RESET3; - break; + bt->timeout = BT_RESET_DELAY * 1000000; + BT_STATE_CHANGE(BT_STATE_RESET3, + SI_SM_CALL_WITH_DELAY); - case BT_STATE_RESET3: + case BT_STATE_RESET3: /* Hold off everything for a bit */ if (bt->timeout > 0) - return SI_SM_CALL_WITH_DELAY; - bt->state = BT_STATE_RESTART; /* printk in debug modes */ - break; + return SI_SM_CALL_WITH_DELAY; + drain_BMC2HOST(bt); + BT_STATE_CHANGE(BT_STATE_RESTART, + SI_SM_CALL_WITH_DELAY); - case BT_STATE_RESTART: /* don't reset retries! */ - reset_flags(bt); - bt->write_data[2] = ++bt->seq; + case BT_STATE_RESTART: /* don't reset retries or seq! */ bt->read_count = 0; bt->nonzero_status = 0; - bt->timeout = BT_NORMAL_TIMEOUT; - bt->state = BT_STATE_XACTION_START; - break; - - default: /* HOSED is supposed to be caught much earlier */ - error_recovery(bt, "internal logic error"); - break; - } - return SI_SM_CALL_WITH_DELAY; + bt->timeout = bt->BT_CAP_req2rsp; + BT_STATE_CHANGE(BT_STATE_XACTION_START, + SI_SM_CALL_WITH_DELAY); + + /* Get BT Capabilities, using timing of upper level state machine. + Set outreqs to prevent infinite loop on timeout. */ + case BT_STATE_CAPABILITIES_BEGIN: + bt->BT_CAP_outreqs = 1; + { + unsigned char GetBT_CAP[] = { 0x18, 0x36 }; + bt->state = BT_STATE_IDLE; + bt_start_transaction(bt, GetBT_CAP, sizeof(GetBT_CAP)); + } + bt->complete = BT_STATE_CAPABILITIES_END; + BT_STATE_CHANGE(BT_STATE_XACTION_START, + SI_SM_CALL_WITH_DELAY); + + case BT_STATE_CAPABILITIES_END: + i = bt_get_result(bt, BT_CAP, sizeof(BT_CAP)); + bt_init_data(bt, bt->io); + if ((i == 8) && !BT_CAP[2]) { + bt->BT_CAP_outreqs = BT_CAP[3]; + bt->BT_CAP_req2rsp = BT_CAP[6] * 1000000; + bt->BT_CAP_retries = BT_CAP[7]; + } else + printk(KERN_WARNING "IPMI BT: using default values\n"); + if (!bt->BT_CAP_outreqs) + bt->BT_CAP_outreqs = 1; + printk(KERN_WARNING "IPMI BT: req2rsp=%ld secs retries=%d\n", + bt->BT_CAP_req2rsp / 1000000L, bt->BT_CAP_retries); + bt->timeout = bt->BT_CAP_req2rsp; + return SI_SM_CALL_WITHOUT_DELAY; + + default: /* should never occur */ + return error_recovery(bt, + status, + IPMI_ERR_UNSPECIFIED); + } + return SI_SM_CALL_WITH_DELAY; } static int bt_detect(struct si_sm_data *bt) @@ -497,7 +642,7 @@ static int bt_detect(struct si_sm_data *bt) test that first. The calling routine uses negative logic. */ if ((BT_STATUS == 0xFF) && (BT_INTMASK_R == 0xFF)) - return 1; + return 1; reset_flags(bt); return 0; } @@ -513,11 +658,11 @@ static int bt_size(void) struct si_sm_handlers bt_smi_handlers = { - .init_data = bt_init_data, - .start_transaction = bt_start_transaction, - .get_result = bt_get_result, - .event = bt_event, - .detect = bt_detect, - .cleanup = bt_cleanup, - .size = bt_size, + .init_data = bt_init_data, + .start_transaction = bt_start_transaction, + .get_result = bt_get_result, + .event = bt_event, + .detect = bt_detect, + .cleanup = bt_cleanup, + .size = bt_size, }; diff --git a/trunk/drivers/char/ipmi/ipmi_devintf.c b/trunk/drivers/char/ipmi/ipmi_devintf.c index 81fcf0ce21d1..e257835a9a73 100644 --- a/trunk/drivers/char/ipmi/ipmi_devintf.c +++ b/trunk/drivers/char/ipmi/ipmi_devintf.c @@ -596,6 +596,31 @@ static int ipmi_ioctl(struct inode *inode, rv = 0; break; } + + case IPMICTL_GET_MAINTENANCE_MODE_CMD: + { + int mode; + + mode = ipmi_get_maintenance_mode(priv->user); + if (copy_to_user(arg, &mode, sizeof(mode))) { + rv = -EFAULT; + break; + } + rv = 0; + break; + } + + case IPMICTL_SET_MAINTENANCE_MODE_CMD: + { + int mode; + + if (copy_from_user(&mode, arg, sizeof(mode))) { + rv = -EFAULT; + break; + } + rv = ipmi_set_maintenance_mode(priv->user, mode); + break; + } } return rv; @@ -773,7 +798,7 @@ static long compat_ipmi_ioctl(struct file *filep, unsigned int cmd, if (copy_to_user(precv64, &recv64, sizeof(recv64))) return -EFAULT; - rc = ipmi_ioctl(filep->f_dentry->d_inode, filep, + rc = ipmi_ioctl(filep->f_path.dentry->d_inode, filep, ((cmd == COMPAT_IPMICTL_RECEIVE_MSG) ? IPMICTL_RECEIVE_MSG : IPMICTL_RECEIVE_MSG_TRUNC), @@ -790,7 +815,7 @@ static long compat_ipmi_ioctl(struct file *filep, unsigned int cmd, return rc; } default: - return ipmi_ioctl(filep->f_dentry->d_inode, filep, cmd, arg); + return ipmi_ioctl(filep->f_path.dentry->d_inode, filep, cmd, arg); } } #endif diff --git a/trunk/drivers/char/ipmi/ipmi_kcs_sm.c b/trunk/drivers/char/ipmi/ipmi_kcs_sm.c index 2062675f9e99..c1b8228cb7b6 100644 --- a/trunk/drivers/char/ipmi/ipmi_kcs_sm.c +++ b/trunk/drivers/char/ipmi/ipmi_kcs_sm.c @@ -93,8 +93,8 @@ enum kcs_states { state machine. */ }; -#define MAX_KCS_READ_SIZE 80 -#define MAX_KCS_WRITE_SIZE 80 +#define MAX_KCS_READ_SIZE IPMI_MAX_MSG_LENGTH +#define MAX_KCS_WRITE_SIZE IPMI_MAX_MSG_LENGTH /* Timeouts in microseconds. */ #define IBF_RETRY_TIMEOUT 1000000 @@ -261,12 +261,14 @@ static int start_kcs_transaction(struct si_sm_data *kcs, unsigned char *data, { unsigned int i; - if ((size < 2) || (size > MAX_KCS_WRITE_SIZE)) { - return -1; - } - if ((kcs->state != KCS_IDLE) && (kcs->state != KCS_HOSED)) { - return -2; - } + if (size < 2) + return IPMI_REQ_LEN_INVALID_ERR; + if (size > MAX_KCS_WRITE_SIZE) + return IPMI_REQ_LEN_EXCEEDED_ERR; + + if ((kcs->state != KCS_IDLE) && (kcs->state != KCS_HOSED)) + return IPMI_NOT_IN_MY_STATE_ERR; + if (kcs_debug & KCS_DEBUG_MSG) { printk(KERN_DEBUG "start_kcs_transaction -"); for (i = 0; i < size; i ++) { diff --git a/trunk/drivers/char/ipmi/ipmi_msghandler.c b/trunk/drivers/char/ipmi/ipmi_msghandler.c index c47add8e47df..5703ee28e1cc 100644 --- a/trunk/drivers/char/ipmi/ipmi_msghandler.c +++ b/trunk/drivers/char/ipmi/ipmi_msghandler.c @@ -48,7 +48,7 @@ #define PFX "IPMI message handler: " -#define IPMI_DRIVER_VERSION "39.0" +#define IPMI_DRIVER_VERSION "39.1" static struct ipmi_recv_msg *ipmi_alloc_recv_msg(void); static int ipmi_init_msghandler(void); @@ -59,6 +59,9 @@ static int initialized = 0; static struct proc_dir_entry *proc_ipmi_root = NULL; #endif /* CONFIG_PROC_FS */ +/* Remain in auto-maintenance mode for this amount of time (in ms). */ +#define IPMI_MAINTENANCE_MODE_TIMEOUT 30000 + #define MAX_EVENTS_IN_QUEUE 25 /* Don't let a message sit in a queue forever, always time it with at lest @@ -193,17 +196,28 @@ struct ipmi_smi struct kref refcount; + /* Used for a list of interfaces. */ + struct list_head link; + /* The list of upper layers that are using me. seq_lock * protects this. */ struct list_head users; + /* Information to supply to users. */ + unsigned char ipmi_version_major; + unsigned char ipmi_version_minor; + /* Used for wake ups at startup. */ wait_queue_head_t waitq; struct bmc_device *bmc; char *my_dev_name; + char *sysfs_name; - /* This is the lower-layer's sender routine. */ + /* This is the lower-layer's sender routine. Note that you + * must either be holding the ipmi_interfaces_mutex or be in + * an umpreemptible region to use this. You must fetch the + * value into a local variable and make sure it is not NULL. */ struct ipmi_smi_handlers *handlers; void *send_info; @@ -242,6 +256,7 @@ struct ipmi_smi spinlock_t events_lock; /* For dealing with event stuff. */ struct list_head waiting_events; unsigned int waiting_events_count; /* How many events in queue? */ + int delivering_events; /* The event receiver for my BMC, only really used at panic shutdown as a place to store this. */ @@ -250,6 +265,12 @@ struct ipmi_smi unsigned char local_sel_device; unsigned char local_event_generator; + /* For handling of maintenance mode. */ + int maintenance_mode; + int maintenance_mode_enable; + int auto_maintenance_timeout; + spinlock_t maintenance_mode_lock; /* Used in a timer... */ + /* A cheap hack, if this is non-null and a message to an interface comes in with a NULL user, call this routine with it. Note that the message will still be freed by the @@ -338,13 +359,6 @@ struct ipmi_smi }; #define to_si_intf_from_dev(device) container_of(device, struct ipmi_smi, dev) -/* Used to mark an interface entry that cannot be used but is not a - * free entry, either, primarily used at creation and deletion time so - * a slot doesn't get reused too quickly. */ -#define IPMI_INVALID_INTERFACE_ENTRY ((ipmi_smi_t) ((long) 1)) -#define IPMI_INVALID_INTERFACE(i) (((i) == NULL) \ - || (i == IPMI_INVALID_INTERFACE_ENTRY)) - /** * The driver model view of the IPMI messaging driver. */ @@ -354,16 +368,13 @@ static struct device_driver ipmidriver = { }; static DEFINE_MUTEX(ipmidriver_mutex); -#define MAX_IPMI_INTERFACES 4 -static ipmi_smi_t ipmi_interfaces[MAX_IPMI_INTERFACES]; - -/* Directly protects the ipmi_interfaces data structure. */ -static DEFINE_SPINLOCK(interfaces_lock); +static struct list_head ipmi_interfaces = LIST_HEAD_INIT(ipmi_interfaces); +static DEFINE_MUTEX(ipmi_interfaces_mutex); /* List of watchers that want to know when smi's are added and deleted. */ static struct list_head smi_watchers = LIST_HEAD_INIT(smi_watchers); -static DECLARE_RWSEM(smi_watchers_sem); +static DEFINE_MUTEX(smi_watchers_mutex); static void free_recv_msg_list(struct list_head *q) @@ -423,48 +434,84 @@ static void intf_free(struct kref *ref) kfree(intf); } +struct watcher_entry { + int intf_num; + ipmi_smi_t intf; + struct list_head link; +}; + int ipmi_smi_watcher_register(struct ipmi_smi_watcher *watcher) { - int i; - unsigned long flags; + ipmi_smi_t intf; + struct list_head to_deliver = LIST_HEAD_INIT(to_deliver); + struct watcher_entry *e, *e2; + + mutex_lock(&smi_watchers_mutex); + + mutex_lock(&ipmi_interfaces_mutex); - down_write(&smi_watchers_sem); - list_add(&(watcher->link), &smi_watchers); - up_write(&smi_watchers_sem); - spin_lock_irqsave(&interfaces_lock, flags); - for (i = 0; i < MAX_IPMI_INTERFACES; i++) { - ipmi_smi_t intf = ipmi_interfaces[i]; - if (IPMI_INVALID_INTERFACE(intf)) + /* Build a list of things to deliver. */ + list_for_each_entry_rcu(intf, &ipmi_interfaces, link) { + if (intf->intf_num == -1) continue; - spin_unlock_irqrestore(&interfaces_lock, flags); - watcher->new_smi(i, intf->si_dev); - spin_lock_irqsave(&interfaces_lock, flags); + e = kmalloc(sizeof(*e), GFP_KERNEL); + if (!e) + goto out_err; + kref_get(&intf->refcount); + e->intf = intf; + e->intf_num = intf->intf_num; + list_add_tail(&e->link, &to_deliver); } - spin_unlock_irqrestore(&interfaces_lock, flags); + + /* We will succeed, so add it to the list. */ + list_add(&watcher->link, &smi_watchers); + + mutex_unlock(&ipmi_interfaces_mutex); + + list_for_each_entry_safe(e, e2, &to_deliver, link) { + list_del(&e->link); + watcher->new_smi(e->intf_num, e->intf->si_dev); + kref_put(&e->intf->refcount, intf_free); + kfree(e); + } + + mutex_unlock(&smi_watchers_mutex); + return 0; + + out_err: + mutex_unlock(&ipmi_interfaces_mutex); + mutex_unlock(&smi_watchers_mutex); + list_for_each_entry_safe(e, e2, &to_deliver, link) { + list_del(&e->link); + kref_put(&e->intf->refcount, intf_free); + kfree(e); + } + return -ENOMEM; } int ipmi_smi_watcher_unregister(struct ipmi_smi_watcher *watcher) { - down_write(&smi_watchers_sem); + mutex_lock(&smi_watchers_mutex); list_del(&(watcher->link)); - up_write(&smi_watchers_sem); + mutex_unlock(&smi_watchers_mutex); return 0; } +/* + * Must be called with smi_watchers_mutex held. + */ static void call_smi_watchers(int i, struct device *dev) { struct ipmi_smi_watcher *w; - down_read(&smi_watchers_sem); list_for_each_entry(w, &smi_watchers, link) { if (try_module_get(w->owner)) { w->new_smi(i, dev); module_put(w->owner); } } - up_read(&smi_watchers_sem); } static int @@ -590,6 +637,17 @@ static void deliver_response(struct ipmi_recv_msg *msg) } } +static void +deliver_err_response(struct ipmi_recv_msg *msg, int err) +{ + msg->recv_type = IPMI_RESPONSE_RECV_TYPE; + msg->msg_data[0] = err; + msg->msg.netfn |= 1; /* Convert to a response. */ + msg->msg.data_len = 1; + msg->msg.data = msg->msg_data; + deliver_response(msg); +} + /* Find the next sequence number not being used and add the given message with the given timeout to the sequence table. This must be called with the interface's seq_lock held. */ @@ -727,14 +785,8 @@ static int intf_err_seq(ipmi_smi_t intf, } spin_unlock_irqrestore(&(intf->seq_lock), flags); - if (msg) { - msg->recv_type = IPMI_RESPONSE_RECV_TYPE; - msg->msg_data[0] = err; - msg->msg.netfn |= 1; /* Convert to a response. */ - msg->msg.data_len = 1; - msg->msg.data = msg->msg_data; - deliver_response(msg); - } + if (msg) + deliver_err_response(msg, err); return rv; } @@ -776,17 +828,18 @@ int ipmi_create_user(unsigned int if_num, if (!new_user) return -ENOMEM; - spin_lock_irqsave(&interfaces_lock, flags); - intf = ipmi_interfaces[if_num]; - if ((if_num >= MAX_IPMI_INTERFACES) || IPMI_INVALID_INTERFACE(intf)) { - spin_unlock_irqrestore(&interfaces_lock, flags); - rv = -EINVAL; - goto out_kfree; + mutex_lock(&ipmi_interfaces_mutex); + list_for_each_entry_rcu(intf, &ipmi_interfaces, link) { + if (intf->intf_num == if_num) + goto found; } + /* Not found, return an error */ + rv = -EINVAL; + goto out_kfree; + found: /* Note that each existing user holds a refcount to the interface. */ kref_get(&intf->refcount); - spin_unlock_irqrestore(&interfaces_lock, flags); kref_init(&new_user->refcount); new_user->handler = handler; @@ -807,6 +860,10 @@ int ipmi_create_user(unsigned int if_num, } } + /* Hold the lock so intf->handlers is guaranteed to be good + * until now */ + mutex_unlock(&ipmi_interfaces_mutex); + new_user->valid = 1; spin_lock_irqsave(&intf->seq_lock, flags); list_add_rcu(&new_user->link, &intf->users); @@ -817,6 +874,7 @@ int ipmi_create_user(unsigned int if_num, out_kref: kref_put(&intf->refcount, intf_free); out_kfree: + mutex_unlock(&ipmi_interfaces_mutex); kfree(new_user); return rv; } @@ -846,6 +904,7 @@ int ipmi_destroy_user(ipmi_user_t user) && (intf->seq_table[i].recv_msg->user == user)) { intf->seq_table[i].inuse = 0; + ipmi_free_recv_msg(intf->seq_table[i].recv_msg); } } spin_unlock_irqrestore(&intf->seq_lock, flags); @@ -872,9 +931,13 @@ int ipmi_destroy_user(ipmi_user_t user) kfree(rcvr); } - module_put(intf->handlers->owner); - if (intf->handlers->dec_usecount) - intf->handlers->dec_usecount(intf->send_info); + mutex_lock(&ipmi_interfaces_mutex); + if (intf->handlers) { + module_put(intf->handlers->owner); + if (intf->handlers->dec_usecount) + intf->handlers->dec_usecount(intf->send_info); + } + mutex_unlock(&ipmi_interfaces_mutex); kref_put(&intf->refcount, intf_free); @@ -887,8 +950,8 @@ void ipmi_get_version(ipmi_user_t user, unsigned char *major, unsigned char *minor) { - *major = ipmi_version_major(&user->intf->bmc->id); - *minor = ipmi_version_minor(&user->intf->bmc->id); + *major = user->intf->ipmi_version_major; + *minor = user->intf->ipmi_version_minor; } int ipmi_set_my_address(ipmi_user_t user, @@ -931,6 +994,65 @@ int ipmi_get_my_LUN(ipmi_user_t user, return 0; } +int ipmi_get_maintenance_mode(ipmi_user_t user) +{ + int mode; + unsigned long flags; + + spin_lock_irqsave(&user->intf->maintenance_mode_lock, flags); + mode = user->intf->maintenance_mode; + spin_unlock_irqrestore(&user->intf->maintenance_mode_lock, flags); + + return mode; +} +EXPORT_SYMBOL(ipmi_get_maintenance_mode); + +static void maintenance_mode_update(ipmi_smi_t intf) +{ + if (intf->handlers->set_maintenance_mode) + intf->handlers->set_maintenance_mode( + intf->send_info, intf->maintenance_mode_enable); +} + +int ipmi_set_maintenance_mode(ipmi_user_t user, int mode) +{ + int rv = 0; + unsigned long flags; + ipmi_smi_t intf = user->intf; + + spin_lock_irqsave(&intf->maintenance_mode_lock, flags); + if (intf->maintenance_mode != mode) { + switch (mode) { + case IPMI_MAINTENANCE_MODE_AUTO: + intf->maintenance_mode = mode; + intf->maintenance_mode_enable + = (intf->auto_maintenance_timeout > 0); + break; + + case IPMI_MAINTENANCE_MODE_OFF: + intf->maintenance_mode = mode; + intf->maintenance_mode_enable = 0; + break; + + case IPMI_MAINTENANCE_MODE_ON: + intf->maintenance_mode = mode; + intf->maintenance_mode_enable = 1; + break; + + default: + rv = -EINVAL; + goto out_unlock; + } + + maintenance_mode_update(intf); + } + out_unlock: + spin_unlock_irqrestore(&intf->maintenance_mode_lock, flags); + + return rv; +} +EXPORT_SYMBOL(ipmi_set_maintenance_mode); + int ipmi_set_gets_events(ipmi_user_t user, int val) { unsigned long flags; @@ -943,20 +1065,33 @@ int ipmi_set_gets_events(ipmi_user_t user, int val) spin_lock_irqsave(&intf->events_lock, flags); user->gets_events = val; - if (val) { - /* Deliver any queued events. */ + if (intf->delivering_events) + /* + * Another thread is delivering events for this, so + * let it handle any new events. + */ + goto out; + + /* Deliver any queued events. */ + while (user->gets_events && !list_empty(&intf->waiting_events)) { list_for_each_entry_safe(msg, msg2, &intf->waiting_events, link) list_move_tail(&msg->link, &msgs); intf->waiting_events_count = 0; - } - /* Hold the events lock while doing this to preserve order. */ - list_for_each_entry_safe(msg, msg2, &msgs, link) { - msg->user = user; - kref_get(&user->refcount); - deliver_response(msg); + intf->delivering_events = 1; + spin_unlock_irqrestore(&intf->events_lock, flags); + + list_for_each_entry_safe(msg, msg2, &msgs, link) { + msg->user = user; + kref_get(&user->refcount); + deliver_response(msg); + } + + spin_lock_irqsave(&intf->events_lock, flags); + intf->delivering_events = 0; } + out: spin_unlock_irqrestore(&intf->events_lock, flags); return 0; @@ -1067,7 +1202,8 @@ int ipmi_unregister_for_cmd(ipmi_user_t user, void ipmi_user_set_run_to_completion(ipmi_user_t user, int val) { ipmi_smi_t intf = user->intf; - intf->handlers->set_run_to_completion(intf->send_info, val); + if (intf->handlers) + intf->handlers->set_run_to_completion(intf->send_info, val); } static unsigned char @@ -1178,10 +1314,11 @@ static int i_ipmi_request(ipmi_user_t user, int retries, unsigned int retry_time_ms) { - int rv = 0; - struct ipmi_smi_msg *smi_msg; - struct ipmi_recv_msg *recv_msg; - unsigned long flags; + int rv = 0; + struct ipmi_smi_msg *smi_msg; + struct ipmi_recv_msg *recv_msg; + unsigned long flags; + struct ipmi_smi_handlers *handlers; if (supplied_recv) { @@ -1204,6 +1341,13 @@ static int i_ipmi_request(ipmi_user_t user, } } + rcu_read_lock(); + handlers = intf->handlers; + if (!handlers) { + rv = -ENODEV; + goto out_err; + } + recv_msg->user = user; if (user) kref_get(&user->refcount); @@ -1246,6 +1390,24 @@ static int i_ipmi_request(ipmi_user_t user, goto out_err; } + if (((msg->netfn == IPMI_NETFN_APP_REQUEST) + && ((msg->cmd == IPMI_COLD_RESET_CMD) + || (msg->cmd == IPMI_WARM_RESET_CMD))) + || (msg->netfn == IPMI_NETFN_FIRMWARE_REQUEST)) + { + spin_lock_irqsave(&intf->maintenance_mode_lock, flags); + intf->auto_maintenance_timeout + = IPMI_MAINTENANCE_MODE_TIMEOUT; + if (!intf->maintenance_mode + && !intf->maintenance_mode_enable) + { + intf->maintenance_mode_enable = 1; + maintenance_mode_update(intf); + } + spin_unlock_irqrestore(&intf->maintenance_mode_lock, + flags); + } + if ((msg->data_len + 2) > IPMI_MAX_MSG_LENGTH) { spin_lock_irqsave(&intf->counter_lock, flags); intf->sent_invalid_commands++; @@ -1520,11 +1682,14 @@ static int i_ipmi_request(ipmi_user_t user, printk("\n"); } #endif - intf->handlers->sender(intf->send_info, smi_msg, priority); + + handlers->sender(intf->send_info, smi_msg, priority); + rcu_read_unlock(); return 0; out_err: + rcu_read_unlock(); ipmi_free_smi_msg(smi_msg); ipmi_free_recv_msg(recv_msg); return rv; @@ -1604,6 +1769,7 @@ int ipmi_request_supply_msgs(ipmi_user_t user, -1, 0); } +#ifdef CONFIG_PROC_FS static int ipmb_file_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data) { @@ -1692,6 +1858,7 @@ static int stat_file_read_proc(char *page, char **start, off_t off, return (out - ((char *) page)); } +#endif /* CONFIG_PROC_FS */ int ipmi_smi_add_proc_entry(ipmi_smi_t smi, char *name, read_proc_t *read_proc, write_proc_t *write_proc, @@ -1817,13 +1984,12 @@ static int __find_bmc_prod_dev_id(struct device *dev, void *data) struct bmc_device *bmc = dev_get_drvdata(dev); return (bmc->id.product_id == id->product_id - && bmc->id.product_id == id->product_id && bmc->id.device_id == id->device_id); } static struct bmc_device *ipmi_find_bmc_prod_dev_id( struct device_driver *drv, - unsigned char product_id, unsigned char device_id) + unsigned int product_id, unsigned char device_id) { struct prod_dev_id id = { .product_id = product_id, @@ -1940,6 +2106,9 @@ static ssize_t guid_show(struct device *dev, struct device_attribute *attr, static void remove_files(struct bmc_device *bmc) { + if (!bmc->dev) + return; + device_remove_file(&bmc->dev->dev, &bmc->device_id_attr); device_remove_file(&bmc->dev->dev, @@ -1973,7 +2142,8 @@ cleanup_bmc_device(struct kref *ref) bmc = container_of(ref, struct bmc_device, refcount); remove_files(bmc); - platform_device_unregister(bmc->dev); + if (bmc->dev) + platform_device_unregister(bmc->dev); kfree(bmc); } @@ -1981,7 +2151,11 @@ static void ipmi_bmc_unregister(ipmi_smi_t intf) { struct bmc_device *bmc = intf->bmc; - sysfs_remove_link(&intf->si_dev->kobj, "bmc"); + if (intf->sysfs_name) { + sysfs_remove_link(&intf->si_dev->kobj, intf->sysfs_name); + kfree(intf->sysfs_name); + intf->sysfs_name = NULL; + } if (intf->my_dev_name) { sysfs_remove_link(&bmc->dev->dev.kobj, intf->my_dev_name); kfree(intf->my_dev_name); @@ -1990,6 +2164,7 @@ static void ipmi_bmc_unregister(ipmi_smi_t intf) mutex_lock(&ipmidriver_mutex); kref_put(&bmc->refcount, cleanup_bmc_device); + intf->bmc = NULL; mutex_unlock(&ipmidriver_mutex); } @@ -1997,6 +2172,56 @@ static int create_files(struct bmc_device *bmc) { int err; + bmc->device_id_attr.attr.name = "device_id"; + bmc->device_id_attr.attr.owner = THIS_MODULE; + bmc->device_id_attr.attr.mode = S_IRUGO; + bmc->device_id_attr.show = device_id_show; + + bmc->provides_dev_sdrs_attr.attr.name = "provides_device_sdrs"; + bmc->provides_dev_sdrs_attr.attr.owner = THIS_MODULE; + bmc->provides_dev_sdrs_attr.attr.mode = S_IRUGO; + bmc->provides_dev_sdrs_attr.show = provides_dev_sdrs_show; + + bmc->revision_attr.attr.name = "revision"; + bmc->revision_attr.attr.owner = THIS_MODULE; + bmc->revision_attr.attr.mode = S_IRUGO; + bmc->revision_attr.show = revision_show; + + bmc->firmware_rev_attr.attr.name = "firmware_revision"; + bmc->firmware_rev_attr.attr.owner = THIS_MODULE; + bmc->firmware_rev_attr.attr.mode = S_IRUGO; + bmc->firmware_rev_attr.show = firmware_rev_show; + + bmc->version_attr.attr.name = "ipmi_version"; + bmc->version_attr.attr.owner = THIS_MODULE; + bmc->version_attr.attr.mode = S_IRUGO; + bmc->version_attr.show = ipmi_version_show; + + bmc->add_dev_support_attr.attr.name = "additional_device_support"; + bmc->add_dev_support_attr.attr.owner = THIS_MODULE; + bmc->add_dev_support_attr.attr.mode = S_IRUGO; + bmc->add_dev_support_attr.show = add_dev_support_show; + + bmc->manufacturer_id_attr.attr.name = "manufacturer_id"; + bmc->manufacturer_id_attr.attr.owner = THIS_MODULE; + bmc->manufacturer_id_attr.attr.mode = S_IRUGO; + bmc->manufacturer_id_attr.show = manufacturer_id_show; + + bmc->product_id_attr.attr.name = "product_id"; + bmc->product_id_attr.attr.owner = THIS_MODULE; + bmc->product_id_attr.attr.mode = S_IRUGO; + bmc->product_id_attr.show = product_id_show; + + bmc->guid_attr.attr.name = "guid"; + bmc->guid_attr.attr.owner = THIS_MODULE; + bmc->guid_attr.attr.mode = S_IRUGO; + bmc->guid_attr.show = guid_show; + + bmc->aux_firmware_rev_attr.attr.name = "aux_firmware_revision"; + bmc->aux_firmware_rev_attr.attr.owner = THIS_MODULE; + bmc->aux_firmware_rev_attr.attr.mode = S_IRUGO; + bmc->aux_firmware_rev_attr.show = aux_firmware_rev_show; + err = device_create_file(&bmc->dev->dev, &bmc->device_id_attr); if (err) goto out; @@ -2066,7 +2291,8 @@ static int create_files(struct bmc_device *bmc) return err; } -static int ipmi_bmc_register(ipmi_smi_t intf) +static int ipmi_bmc_register(ipmi_smi_t intf, int ifnum, + const char *sysfs_name) { int rv; struct bmc_device *bmc = intf->bmc; @@ -2106,9 +2332,39 @@ static int ipmi_bmc_register(ipmi_smi_t intf) bmc->id.product_id, bmc->id.device_id); } else { - bmc->dev = platform_device_alloc("ipmi_bmc", - bmc->id.device_id); + char name[14]; + unsigned char orig_dev_id = bmc->id.device_id; + int warn_printed = 0; + + snprintf(name, sizeof(name), + "ipmi_bmc.%4.4x", bmc->id.product_id); + + while (ipmi_find_bmc_prod_dev_id(&ipmidriver, + bmc->id.product_id, + bmc->id.device_id)) + { + if (!warn_printed) { + printk(KERN_WARNING PFX + "This machine has two different BMCs" + " with the same product id and device" + " id. This is an error in the" + " firmware, but incrementing the" + " device id to work around the problem." + " Prod ID = 0x%x, Dev ID = 0x%x\n", + bmc->id.product_id, bmc->id.device_id); + warn_printed = 1; + } + bmc->id.device_id++; /* Wraps at 255 */ + if (bmc->id.device_id == orig_dev_id) { + printk(KERN_ERR PFX + "Out of device ids!\n"); + break; + } + } + + bmc->dev = platform_device_alloc(name, bmc->id.device_id); if (!bmc->dev) { + mutex_unlock(&ipmidriver_mutex); printk(KERN_ERR "ipmi_msghandler:" " Unable to allocate platform device\n"); @@ -2121,6 +2377,8 @@ static int ipmi_bmc_register(ipmi_smi_t intf) rv = platform_device_add(bmc->dev); mutex_unlock(&ipmidriver_mutex); if (rv) { + platform_device_put(bmc->dev); + bmc->dev = NULL; printk(KERN_ERR "ipmi_msghandler:" " Unable to register bmc device: %d\n", @@ -2130,57 +2388,6 @@ static int ipmi_bmc_register(ipmi_smi_t intf) return rv; } - bmc->device_id_attr.attr.name = "device_id"; - bmc->device_id_attr.attr.owner = THIS_MODULE; - bmc->device_id_attr.attr.mode = S_IRUGO; - bmc->device_id_attr.show = device_id_show; - - bmc->provides_dev_sdrs_attr.attr.name = "provides_device_sdrs"; - bmc->provides_dev_sdrs_attr.attr.owner = THIS_MODULE; - bmc->provides_dev_sdrs_attr.attr.mode = S_IRUGO; - bmc->provides_dev_sdrs_attr.show = provides_dev_sdrs_show; - - bmc->revision_attr.attr.name = "revision"; - bmc->revision_attr.attr.owner = THIS_MODULE; - bmc->revision_attr.attr.mode = S_IRUGO; - bmc->revision_attr.show = revision_show; - - bmc->firmware_rev_attr.attr.name = "firmware_revision"; - bmc->firmware_rev_attr.attr.owner = THIS_MODULE; - bmc->firmware_rev_attr.attr.mode = S_IRUGO; - bmc->firmware_rev_attr.show = firmware_rev_show; - - bmc->version_attr.attr.name = "ipmi_version"; - bmc->version_attr.attr.owner = THIS_MODULE; - bmc->version_attr.attr.mode = S_IRUGO; - bmc->version_attr.show = ipmi_version_show; - - bmc->add_dev_support_attr.attr.name - = "additional_device_support"; - bmc->add_dev_support_attr.attr.owner = THIS_MODULE; - bmc->add_dev_support_attr.attr.mode = S_IRUGO; - bmc->add_dev_support_attr.show = add_dev_support_show; - - bmc->manufacturer_id_attr.attr.name = "manufacturer_id"; - bmc->manufacturer_id_attr.attr.owner = THIS_MODULE; - bmc->manufacturer_id_attr.attr.mode = S_IRUGO; - bmc->manufacturer_id_attr.show = manufacturer_id_show; - - bmc->product_id_attr.attr.name = "product_id"; - bmc->product_id_attr.attr.owner = THIS_MODULE; - bmc->product_id_attr.attr.mode = S_IRUGO; - bmc->product_id_attr.show = product_id_show; - - bmc->guid_attr.attr.name = "guid"; - bmc->guid_attr.attr.owner = THIS_MODULE; - bmc->guid_attr.attr.mode = S_IRUGO; - bmc->guid_attr.show = guid_show; - - bmc->aux_firmware_rev_attr.attr.name = "aux_firmware_revision"; - bmc->aux_firmware_rev_attr.attr.owner = THIS_MODULE; - bmc->aux_firmware_rev_attr.attr.mode = S_IRUGO; - bmc->aux_firmware_rev_attr.show = aux_firmware_rev_show; - rv = create_files(bmc); if (rv) { mutex_lock(&ipmidriver_mutex); @@ -2202,29 +2409,44 @@ static int ipmi_bmc_register(ipmi_smi_t intf) * create symlink from system interface device to bmc device * and back. */ + intf->sysfs_name = kstrdup(sysfs_name, GFP_KERNEL); + if (!intf->sysfs_name) { + rv = -ENOMEM; + printk(KERN_ERR + "ipmi_msghandler: allocate link to BMC: %d\n", + rv); + goto out_err; + } + rv = sysfs_create_link(&intf->si_dev->kobj, - &bmc->dev->dev.kobj, "bmc"); + &bmc->dev->dev.kobj, intf->sysfs_name); if (rv) { + kfree(intf->sysfs_name); + intf->sysfs_name = NULL; printk(KERN_ERR "ipmi_msghandler: Unable to create bmc symlink: %d\n", rv); goto out_err; } - size = snprintf(dummy, 0, "ipmi%d", intf->intf_num); + size = snprintf(dummy, 0, "ipmi%d", ifnum); intf->my_dev_name = kmalloc(size+1, GFP_KERNEL); if (!intf->my_dev_name) { + kfree(intf->sysfs_name); + intf->sysfs_name = NULL; rv = -ENOMEM; printk(KERN_ERR "ipmi_msghandler: allocate link from BMC: %d\n", rv); goto out_err; } - snprintf(intf->my_dev_name, size+1, "ipmi%d", intf->intf_num); + snprintf(intf->my_dev_name, size+1, "ipmi%d", ifnum); rv = sysfs_create_link(&bmc->dev->dev.kobj, &intf->si_dev->kobj, intf->my_dev_name); if (rv) { + kfree(intf->sysfs_name); + intf->sysfs_name = NULL; kfree(intf->my_dev_name); intf->my_dev_name = NULL; printk(KERN_ERR @@ -2409,17 +2631,14 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers, void *send_info, struct ipmi_device_id *device_id, struct device *si_dev, + const char *sysfs_name, unsigned char slave_addr) { int i, j; int rv; ipmi_smi_t intf; - unsigned long flags; - int version_major; - int version_minor; - - version_major = ipmi_version_major(device_id); - version_minor = ipmi_version_minor(device_id); + ipmi_smi_t tintf; + struct list_head *link; /* Make sure the driver is actually initialized, this handles problems with initialization order. */ @@ -2437,12 +2656,16 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers, if (!intf) return -ENOMEM; memset(intf, 0, sizeof(*intf)); + + intf->ipmi_version_major = ipmi_version_major(device_id); + intf->ipmi_version_minor = ipmi_version_minor(device_id); + intf->bmc = kzalloc(sizeof(*intf->bmc), GFP_KERNEL); if (!intf->bmc) { kfree(intf); return -ENOMEM; } - intf->intf_num = -1; + intf->intf_num = -1; /* Mark it invalid for now. */ kref_init(&intf->refcount); intf->bmc->id = *device_id; intf->si_dev = si_dev; @@ -2470,26 +2693,30 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers, INIT_LIST_HEAD(&intf->waiting_events); intf->waiting_events_count = 0; mutex_init(&intf->cmd_rcvrs_mutex); + spin_lock_init(&intf->maintenance_mode_lock); INIT_LIST_HEAD(&intf->cmd_rcvrs); init_waitqueue_head(&intf->waitq); spin_lock_init(&intf->counter_lock); intf->proc_dir = NULL; - rv = -ENOMEM; - spin_lock_irqsave(&interfaces_lock, flags); - for (i = 0; i < MAX_IPMI_INTERFACES; i++) { - if (ipmi_interfaces[i] == NULL) { - intf->intf_num = i; - /* Reserve the entry till we are done. */ - ipmi_interfaces[i] = IPMI_INVALID_INTERFACE_ENTRY; - rv = 0; + mutex_lock(&smi_watchers_mutex); + mutex_lock(&ipmi_interfaces_mutex); + /* Look for a hole in the numbers. */ + i = 0; + link = &ipmi_interfaces; + list_for_each_entry_rcu(tintf, &ipmi_interfaces, link) { + if (tintf->intf_num != i) { + link = &tintf->link; break; } + i++; } - spin_unlock_irqrestore(&interfaces_lock, flags); - if (rv) - goto out; + /* Add the new interface in numeric order. */ + if (i == 0) + list_add_rcu(&intf->link, &ipmi_interfaces); + else + list_add_tail_rcu(&intf->link, link); rv = handlers->start_processing(send_info, intf); if (rv) @@ -2497,8 +2724,9 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers, get_guid(intf); - if ((version_major > 1) - || ((version_major == 1) && (version_minor >= 5))) + if ((intf->ipmi_version_major > 1) + || ((intf->ipmi_version_major == 1) + && (intf->ipmi_version_minor >= 5))) { /* Start scanning the channels to see what is available. */ @@ -2521,64 +2749,67 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers, if (rv == 0) rv = add_proc_entries(intf, i); - rv = ipmi_bmc_register(intf); + rv = ipmi_bmc_register(intf, i, sysfs_name); out: if (rv) { if (intf->proc_dir) remove_proc_entries(intf); + intf->handlers = NULL; + list_del_rcu(&intf->link); + mutex_unlock(&ipmi_interfaces_mutex); + mutex_unlock(&smi_watchers_mutex); + synchronize_rcu(); kref_put(&intf->refcount, intf_free); - if (i < MAX_IPMI_INTERFACES) { - spin_lock_irqsave(&interfaces_lock, flags); - ipmi_interfaces[i] = NULL; - spin_unlock_irqrestore(&interfaces_lock, flags); - } } else { - spin_lock_irqsave(&interfaces_lock, flags); - ipmi_interfaces[i] = intf; - spin_unlock_irqrestore(&interfaces_lock, flags); + /* After this point the interface is legal to use. */ + intf->intf_num = i; + mutex_unlock(&ipmi_interfaces_mutex); call_smi_watchers(i, intf->si_dev); + mutex_unlock(&smi_watchers_mutex); } return rv; } +static void cleanup_smi_msgs(ipmi_smi_t intf) +{ + int i; + struct seq_table *ent; + + /* No need for locks, the interface is down. */ + for (i = 0; i < IPMI_IPMB_NUM_SEQ; i++) { + ent = &(intf->seq_table[i]); + if (!ent->inuse) + continue; + deliver_err_response(ent->recv_msg, IPMI_ERR_UNSPECIFIED); + } +} + int ipmi_unregister_smi(ipmi_smi_t intf) { - int i; struct ipmi_smi_watcher *w; - unsigned long flags; + int intf_num = intf->intf_num; ipmi_bmc_unregister(intf); - spin_lock_irqsave(&interfaces_lock, flags); - for (i = 0; i < MAX_IPMI_INTERFACES; i++) { - if (ipmi_interfaces[i] == intf) { - /* Set the interface number reserved until we - * are done. */ - ipmi_interfaces[i] = IPMI_INVALID_INTERFACE_ENTRY; - intf->intf_num = -1; - break; - } - } - spin_unlock_irqrestore(&interfaces_lock,flags); + mutex_lock(&smi_watchers_mutex); + mutex_lock(&ipmi_interfaces_mutex); + intf->intf_num = -1; + intf->handlers = NULL; + list_del_rcu(&intf->link); + mutex_unlock(&ipmi_interfaces_mutex); + synchronize_rcu(); - if (i == MAX_IPMI_INTERFACES) - return -ENODEV; + cleanup_smi_msgs(intf); remove_proc_entries(intf); /* Call all the watcher interfaces to tell them that an interface is gone. */ - down_read(&smi_watchers_sem); list_for_each_entry(w, &smi_watchers, link) - w->smi_gone(i); - up_read(&smi_watchers_sem); - - /* Allow the entry to be reused now. */ - spin_lock_irqsave(&interfaces_lock, flags); - ipmi_interfaces[i] = NULL; - spin_unlock_irqrestore(&interfaces_lock,flags); + w->smi_gone(intf_num); + mutex_unlock(&smi_watchers_mutex); kref_put(&intf->refcount, intf_free); return 0; @@ -2660,6 +2891,7 @@ static int handle_ipmb_get_msg_cmd(ipmi_smi_t intf, struct ipmi_ipmb_addr *ipmb_addr; struct ipmi_recv_msg *recv_msg; unsigned long flags; + struct ipmi_smi_handlers *handlers; if (msg->rsp_size < 10) { /* Message not big enough, just ignore it. */ @@ -2716,10 +2948,16 @@ static int handle_ipmb_get_msg_cmd(ipmi_smi_t intf, printk("\n"); } #endif - intf->handlers->sender(intf->send_info, msg, 0); - - rv = -1; /* We used the message, so return the value that - causes it to not be freed or queued. */ + rcu_read_lock(); + handlers = intf->handlers; + if (handlers) { + handlers->sender(intf->send_info, msg, 0); + /* We used the message, so return the value + that causes it to not be freed or + queued. */ + rv = -1; + } + rcu_read_unlock(); } else { /* Deliver the message to the user. */ spin_lock_irqsave(&intf->counter_lock, flags); @@ -3309,16 +3547,6 @@ void ipmi_smi_watchdog_pretimeout(ipmi_smi_t intf) rcu_read_unlock(); } -static void -handle_msg_timeout(struct ipmi_recv_msg *msg) -{ - msg->recv_type = IPMI_RESPONSE_RECV_TYPE; - msg->msg_data[0] = IPMI_TIMEOUT_COMPLETION_CODE; - msg->msg.netfn |= 1; /* Convert to a response. */ - msg->msg.data_len = 1; - msg->msg.data = msg->msg_data; - deliver_response(msg); -} static struct ipmi_smi_msg * smi_from_recv_msg(ipmi_smi_t intf, struct ipmi_recv_msg *recv_msg, @@ -3350,7 +3578,11 @@ static void check_msg_timeout(ipmi_smi_t intf, struct seq_table *ent, struct list_head *timeouts, long timeout_period, int slot, unsigned long *flags) { - struct ipmi_recv_msg *msg; + struct ipmi_recv_msg *msg; + struct ipmi_smi_handlers *handlers; + + if (intf->intf_num == -1) + return; if (!ent->inuse) return; @@ -3393,13 +3625,19 @@ static void check_msg_timeout(ipmi_smi_t intf, struct seq_table *ent, return; spin_unlock_irqrestore(&intf->seq_lock, *flags); + /* Send the new message. We send with a zero * priority. It timed out, I doubt time is * that critical now, and high priority * messages are really only for messages to the * local MC, which don't get resent. */ - intf->handlers->sender(intf->send_info, - smi_msg, 0); + handlers = intf->handlers; + if (handlers) + intf->handlers->sender(intf->send_info, + smi_msg, 0); + else + ipmi_free_smi_msg(smi_msg); + spin_lock_irqsave(&intf->seq_lock, *flags); } } @@ -3411,18 +3649,12 @@ static void ipmi_timeout_handler(long timeout_period) struct ipmi_recv_msg *msg, *msg2; struct ipmi_smi_msg *smi_msg, *smi_msg2; unsigned long flags; - int i, j; + int i; INIT_LIST_HEAD(&timeouts); - spin_lock(&interfaces_lock); - for (i = 0; i < MAX_IPMI_INTERFACES; i++) { - intf = ipmi_interfaces[i]; - if (IPMI_INVALID_INTERFACE(intf)) - continue; - kref_get(&intf->refcount); - spin_unlock(&interfaces_lock); - + rcu_read_lock(); + list_for_each_entry_rcu(intf, &ipmi_interfaces, link) { /* See if any waiting messages need to be processed. */ spin_lock_irqsave(&intf->waiting_msgs_lock, flags); list_for_each_entry_safe(smi_msg, smi_msg2, @@ -3442,35 +3674,60 @@ static void ipmi_timeout_handler(long timeout_period) have timed out, putting them in the timeouts list. */ spin_lock_irqsave(&intf->seq_lock, flags); - for (j = 0; j < IPMI_IPMB_NUM_SEQ; j++) - check_msg_timeout(intf, &(intf->seq_table[j]), - &timeouts, timeout_period, j, + for (i = 0; i < IPMI_IPMB_NUM_SEQ; i++) + check_msg_timeout(intf, &(intf->seq_table[i]), + &timeouts, timeout_period, i, &flags); spin_unlock_irqrestore(&intf->seq_lock, flags); list_for_each_entry_safe(msg, msg2, &timeouts, link) - handle_msg_timeout(msg); - - kref_put(&intf->refcount, intf_free); - spin_lock(&interfaces_lock); + deliver_err_response(msg, IPMI_TIMEOUT_COMPLETION_CODE); + + /* + * Maintenance mode handling. Check the timeout + * optimistically before we claim the lock. It may + * mean a timeout gets missed occasionally, but that + * only means the timeout gets extended by one period + * in that case. No big deal, and it avoids the lock + * most of the time. + */ + if (intf->auto_maintenance_timeout > 0) { + spin_lock_irqsave(&intf->maintenance_mode_lock, flags); + if (intf->auto_maintenance_timeout > 0) { + intf->auto_maintenance_timeout + -= timeout_period; + if (!intf->maintenance_mode + && (intf->auto_maintenance_timeout <= 0)) + { + intf->maintenance_mode_enable = 0; + maintenance_mode_update(intf); + } + } + spin_unlock_irqrestore(&intf->maintenance_mode_lock, + flags); + } } - spin_unlock(&interfaces_lock); + rcu_read_unlock(); } static void ipmi_request_event(void) { - ipmi_smi_t intf; - int i; + ipmi_smi_t intf; + struct ipmi_smi_handlers *handlers; - spin_lock(&interfaces_lock); - for (i = 0; i < MAX_IPMI_INTERFACES; i++) { - intf = ipmi_interfaces[i]; - if (IPMI_INVALID_INTERFACE(intf)) + rcu_read_lock(); + /* Called from the timer, no need to check if handlers is + * valid. */ + list_for_each_entry_rcu(intf, &ipmi_interfaces, link) { + /* No event requests when in maintenance mode. */ + if (intf->maintenance_mode_enable) continue; - intf->handlers->request_events(intf->send_info); + handlers = intf->handlers; + if (handlers) + handlers->request_events(intf->send_info); } - spin_unlock(&interfaces_lock); + rcu_read_unlock(); } static struct timer_list ipmi_timer; @@ -3599,7 +3856,6 @@ static void send_panic_events(char *str) struct kernel_ipmi_msg msg; ipmi_smi_t intf; unsigned char data[16]; - int i; struct ipmi_system_interface_addr *si; struct ipmi_addr addr; struct ipmi_smi_msg smi_msg; @@ -3633,9 +3889,9 @@ static void send_panic_events(char *str) recv_msg.done = dummy_recv_done_handler; /* For every registered interface, send the event. */ - for (i = 0; i < MAX_IPMI_INTERFACES; i++) { - intf = ipmi_interfaces[i]; - if (IPMI_INVALID_INTERFACE(intf)) + list_for_each_entry_rcu(intf, &ipmi_interfaces, link) { + if (!intf->handlers) + /* Interface is not ready. */ continue; /* Send the event announcing the panic. */ @@ -3660,13 +3916,14 @@ static void send_panic_events(char *str) if (!str) return; - for (i = 0; i < MAX_IPMI_INTERFACES; i++) { + /* For every registered interface, send the event. */ + list_for_each_entry_rcu(intf, &ipmi_interfaces, link) { char *p = str; struct ipmi_ipmb_addr *ipmb; int j; - intf = ipmi_interfaces[i]; - if (IPMI_INVALID_INTERFACE(intf)) + if (intf->intf_num == -1) + /* Interface was not ready yet. */ continue; /* First job here is to figure out where to send the @@ -3792,7 +4049,6 @@ static int panic_event(struct notifier_block *this, unsigned long event, void *ptr) { - int i; ipmi_smi_t intf; if (has_panicked) @@ -3800,9 +4056,9 @@ static int panic_event(struct notifier_block *this, has_panicked = 1; /* For every registered interface, set it to run to completion. */ - for (i = 0; i < MAX_IPMI_INTERFACES; i++) { - intf = ipmi_interfaces[i]; - if (IPMI_INVALID_INTERFACE(intf)) + list_for_each_entry_rcu(intf, &ipmi_interfaces, link) { + if (!intf->handlers) + /* Interface is not ready. */ continue; intf->handlers->set_run_to_completion(intf->send_info, 1); @@ -3823,7 +4079,6 @@ static struct notifier_block panic_block = { static int ipmi_init_msghandler(void) { - int i; int rv; if (initialized) @@ -3838,9 +4093,6 @@ static int ipmi_init_msghandler(void) printk(KERN_INFO "ipmi message handler version " IPMI_DRIVER_VERSION "\n"); - for (i = 0; i < MAX_IPMI_INTERFACES; i++) - ipmi_interfaces[i] = NULL; - #ifdef CONFIG_PROC_FS proc_ipmi_root = proc_mkdir("ipmi", NULL); if (!proc_ipmi_root) { diff --git a/trunk/drivers/char/ipmi/ipmi_poweroff.c b/trunk/drivers/char/ipmi/ipmi_poweroff.c index 8d941db83457..597eb4f88b84 100644 --- a/trunk/drivers/char/ipmi/ipmi_poweroff.c +++ b/trunk/drivers/char/ipmi/ipmi_poweroff.c @@ -43,6 +43,9 @@ #define PFX "IPMI poweroff: " +static void ipmi_po_smi_gone(int if_num); +static void ipmi_po_new_smi(int if_num, struct device *device); + /* Definitions for controlling power off (if the system supports it). It * conveniently matches the IPMI chassis control values. */ #define IPMI_CHASSIS_POWER_DOWN 0 /* power down, the default. */ @@ -51,6 +54,37 @@ /* the IPMI data command */ static int poweroff_powercycle; +/* Which interface to use, -1 means the first we see. */ +static int ifnum_to_use = -1; + +/* Our local state. */ +static int ready = 0; +static ipmi_user_t ipmi_user; +static int ipmi_ifnum; +static void (*specific_poweroff_func)(ipmi_user_t user) = NULL; + +/* Holds the old poweroff function so we can restore it on removal. */ +static void (*old_poweroff_func)(void); + +static int set_param_ifnum(const char *val, struct kernel_param *kp) +{ + int rv = param_set_int(val, kp); + if (rv) + return rv; + if ((ifnum_to_use < 0) || (ifnum_to_use == ipmi_ifnum)) + return 0; + + ipmi_po_smi_gone(ipmi_ifnum); + ipmi_po_new_smi(ifnum_to_use, NULL); + return 0; +} + +module_param_call(ifnum_to_use, set_param_ifnum, param_get_int, + &ifnum_to_use, 0644); +MODULE_PARM_DESC(ifnum_to_use, "The interface number to use for the watchdog " + "timer. Setting to -1 defaults to the first registered " + "interface"); + /* parameter definition to allow user to flag power cycle */ module_param(poweroff_powercycle, int, 0644); MODULE_PARM_DESC(poweroff_powercycle, " Set to non-zero to enable power cycle instead of power down. Power cycle is contingent on hardware support, otherwise it defaults back to power down."); @@ -142,6 +176,42 @@ static int ipmi_request_in_rc_mode(ipmi_user_t user, #define IPMI_ATCA_GET_ADDR_INFO_CMD 0x01 #define IPMI_PICMG_ID 0 +#define IPMI_NETFN_OEM 0x2e +#define IPMI_ATCA_PPS_GRACEFUL_RESTART 0x11 +#define IPMI_ATCA_PPS_IANA "\x00\x40\x0A" +#define IPMI_MOTOROLA_MANUFACTURER_ID 0x0000A1 +#define IPMI_MOTOROLA_PPS_IPMC_PRODUCT_ID 0x0051 + +static void (*atca_oem_poweroff_hook)(ipmi_user_t user) = NULL; + +static void pps_poweroff_atca (ipmi_user_t user) +{ + struct ipmi_system_interface_addr smi_addr; + struct kernel_ipmi_msg send_msg; + int rv; + /* + * Configure IPMI address for local access + */ + smi_addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE; + smi_addr.channel = IPMI_BMC_CHANNEL; + smi_addr.lun = 0; + + printk(KERN_INFO PFX "PPS powerdown hook used"); + + send_msg.netfn = IPMI_NETFN_OEM; + send_msg.cmd = IPMI_ATCA_PPS_GRACEFUL_RESTART; + send_msg.data = IPMI_ATCA_PPS_IANA; + send_msg.data_len = 3; + rv = ipmi_request_in_rc_mode(user, + (struct ipmi_addr *) &smi_addr, + &send_msg); + if (rv && rv != IPMI_UNKNOWN_ERR_COMPLETION_CODE) { + printk(KERN_ERR PFX "Unable to send ATCA ," + " IPMI error 0x%x\n", rv); + } + return; +} + static int ipmi_atca_detect (ipmi_user_t user) { struct ipmi_system_interface_addr smi_addr; @@ -167,6 +237,13 @@ static int ipmi_atca_detect (ipmi_user_t user) rv = ipmi_request_wait_for_response(user, (struct ipmi_addr *) &smi_addr, &send_msg); + + printk(KERN_INFO PFX "ATCA Detect mfg 0x%X prod 0x%X\n", mfg_id, prod_id); + if((mfg_id == IPMI_MOTOROLA_MANUFACTURER_ID) + && (prod_id == IPMI_MOTOROLA_PPS_IPMC_PRODUCT_ID)) { + printk(KERN_INFO PFX "Installing Pigeon Point Systems Poweroff Hook\n"); + atca_oem_poweroff_hook = pps_poweroff_atca; + } return !rv; } @@ -200,12 +277,19 @@ static void ipmi_poweroff_atca (ipmi_user_t user) rv = ipmi_request_in_rc_mode(user, (struct ipmi_addr *) &smi_addr, &send_msg); - if (rv) { + /** At this point, the system may be shutting down, and most + ** serial drivers (if used) will have interrupts turned off + ** it may be better to ignore IPMI_UNKNOWN_ERR_COMPLETION_CODE + ** return code + **/ + if (rv && rv != IPMI_UNKNOWN_ERR_COMPLETION_CODE) { printk(KERN_ERR PFX "Unable to send ATCA powerdown message," " IPMI error 0x%x\n", rv); goto out; } + if(atca_oem_poweroff_hook) + return atca_oem_poweroff_hook(user); out: return; } @@ -440,15 +524,6 @@ static struct poweroff_function poweroff_functions[] = { / sizeof(struct poweroff_function)) -/* Our local state. */ -static int ready = 0; -static ipmi_user_t ipmi_user; -static void (*specific_poweroff_func)(ipmi_user_t user) = NULL; - -/* Holds the old poweroff function so we can restore it on removal. */ -static void (*old_poweroff_func)(void); - - /* Called on a powerdown request. */ static void ipmi_poweroff_function (void) { @@ -473,6 +548,9 @@ static void ipmi_po_new_smi(int if_num, struct device *device) if (ready) return; + if ((ifnum_to_use >= 0) && (ifnum_to_use != if_num)) + return; + rv = ipmi_create_user(if_num, &ipmi_poweroff_handler, NULL, &ipmi_user); if (rv) { @@ -481,6 +559,8 @@ static void ipmi_po_new_smi(int if_num, struct device *device) return; } + ipmi_ifnum = if_num; + /* * Do a get device ide and store some results, since this is * used by several functions. @@ -541,9 +621,15 @@ static void ipmi_po_new_smi(int if_num, struct device *device) static void ipmi_po_smi_gone(int if_num) { - /* This can never be called, because once poweroff driver is - registered, the interface can't go away until the power - driver is unregistered. */ + if (!ready) + return; + + if (ipmi_ifnum != if_num) + return; + + ready = 0; + ipmi_destroy_user(ipmi_user); + pm_power_off = old_poweroff_func; } static struct ipmi_smi_watcher smi_watcher = @@ -616,9 +702,9 @@ static int ipmi_poweroff_init (void) printk(KERN_ERR PFX "Unable to register SMI watcher: %d\n", rv); goto out_err; } -#endif out_err: +#endif return rv; } diff --git a/trunk/drivers/char/ipmi/ipmi_si_intf.c b/trunk/drivers/char/ipmi/ipmi_si_intf.c index bb1fac104fda..81a0c89598e7 100644 --- a/trunk/drivers/char/ipmi/ipmi_si_intf.c +++ b/trunk/drivers/char/ipmi/ipmi_si_intf.c @@ -61,6 +61,10 @@ #include "ipmi_si_sm.h" #include #include +#include +#include + +#define PFX "ipmi_si: " /* Measure times between events in the driver. */ #undef DEBUG_TIMING @@ -92,7 +96,7 @@ enum si_intf_state { enum si_type { SI_KCS, SI_SMIC, SI_BT }; -static char *si_to_str[] = { "KCS", "SMIC", "BT" }; +static char *si_to_str[] = { "kcs", "smic", "bt" }; #define DEVICE_NAME "ipmi_si" @@ -222,7 +226,10 @@ struct smi_info static int force_kipmid[SI_MAX_PARMS]; static int num_force_kipmid; +static int unload_when_empty = 1; + static int try_smi_init(struct smi_info *smi); +static void cleanup_one_si(struct smi_info *to_clean); static ATOMIC_NOTIFIER_HEAD(xaction_notifier_list); static int register_xaction_notifier(struct notifier_block * nb) @@ -240,14 +247,18 @@ static void deliver_recv_msg(struct smi_info *smi_info, spin_lock(&(smi_info->si_lock)); } -static void return_hosed_msg(struct smi_info *smi_info) +static void return_hosed_msg(struct smi_info *smi_info, int cCode) { struct ipmi_smi_msg *msg = smi_info->curr_msg; + if (cCode < 0 || cCode > IPMI_ERR_UNSPECIFIED) + cCode = IPMI_ERR_UNSPECIFIED; + /* else use it as is */ + /* Make it a reponse */ msg->rsp[0] = msg->data[0] | 4; msg->rsp[1] = msg->data[1]; - msg->rsp[2] = 0xFF; /* Unknown error. */ + msg->rsp[2] = cCode; msg->rsp_size = 3; smi_info->curr_msg = NULL; @@ -298,7 +309,7 @@ static enum si_sm_result start_next_msg(struct smi_info *smi_info) smi_info->curr_msg->data, smi_info->curr_msg->data_size); if (err) { - return_hosed_msg(smi_info); + return_hosed_msg(smi_info, err); } rv = SI_SM_CALL_WITHOUT_DELAY; @@ -640,7 +651,7 @@ static enum si_sm_result smi_event_handler(struct smi_info *smi_info, /* If we were handling a user message, format a response to send to the upper layer to tell it about the error. */ - return_hosed_msg(smi_info); + return_hosed_msg(smi_info, IPMI_ERR_UNSPECIFIED); } si_sm_result = smi_info->handlers->event(smi_info->si_sm, 0); } @@ -684,22 +695,24 @@ static enum si_sm_result smi_event_handler(struct smi_info *smi_info, { /* We are idle and the upper layer requested that I fetch events, so do so. */ - unsigned char msg[2]; + atomic_set(&smi_info->req_events, 0); - spin_lock(&smi_info->count_lock); - smi_info->flag_fetches++; - spin_unlock(&smi_info->count_lock); + smi_info->curr_msg = ipmi_alloc_smi_msg(); + if (!smi_info->curr_msg) + goto out; - atomic_set(&smi_info->req_events, 0); - msg[0] = (IPMI_NETFN_APP_REQUEST << 2); - msg[1] = IPMI_GET_MSG_FLAGS_CMD; + smi_info->curr_msg->data[0] = (IPMI_NETFN_APP_REQUEST << 2); + smi_info->curr_msg->data[1] = IPMI_READ_EVENT_MSG_BUFFER_CMD; + smi_info->curr_msg->data_size = 2; smi_info->handlers->start_transaction( - smi_info->si_sm, msg, 2); - smi_info->si_state = SI_GETTING_FLAGS; + smi_info->si_sm, + smi_info->curr_msg->data, + smi_info->curr_msg->data_size); + smi_info->si_state = SI_GETTING_EVENTS; goto restart; } - + out: return si_sm_result; } @@ -714,6 +727,15 @@ static void sender(void *send_info, struct timeval t; #endif + if (atomic_read(&smi_info->stop_operation)) { + msg->rsp[0] = msg->data[0] | 4; + msg->rsp[1] = msg->data[1]; + msg->rsp[2] = IPMI_ERR_UNSPECIFIED; + msg->rsp_size = 3; + deliver_recv_msg(smi_info, msg); + return; + } + spin_lock_irqsave(&(smi_info->msg_lock), flags); #ifdef DEBUG_TIMING do_gettimeofday(&t); @@ -805,13 +827,21 @@ static void poll(void *send_info) { struct smi_info *smi_info = send_info; - smi_event_handler(smi_info, 0); + /* + * Make sure there is some delay in the poll loop so we can + * drive time forward and timeout things. + */ + udelay(10); + smi_event_handler(smi_info, 10); } static void request_events(void *send_info) { struct smi_info *smi_info = send_info; + if (atomic_read(&smi_info->stop_operation)) + return; + atomic_set(&smi_info->req_events, 1); } @@ -949,12 +979,21 @@ static int smi_start_processing(void *send_info, return 0; } +static void set_maintenance_mode(void *send_info, int enable) +{ + struct smi_info *smi_info = send_info; + + if (!enable) + atomic_set(&smi_info->req_events, 0); +} + static struct ipmi_smi_handlers handlers = { .owner = THIS_MODULE, .start_processing = smi_start_processing, .sender = sender, .request_events = request_events, + .set_maintenance_mode = set_maintenance_mode, .set_run_to_completion = set_run_to_completion, .poll = poll, }; @@ -987,6 +1026,16 @@ static int num_regshifts = 0; static int slave_addrs[SI_MAX_PARMS]; static int num_slave_addrs = 0; +#define IPMI_IO_ADDR_SPACE 0 +#define IPMI_MEM_ADDR_SPACE 1 +static char *addr_space_to_str[] = { "I/O", "mem" }; + +static int hotmod_handler(const char *val, struct kernel_param *kp); + +module_param_call(hotmod, hotmod_handler, NULL, NULL, 0200); +MODULE_PARM_DESC(hotmod, "Add and remove interfaces. See" + " Documentation/IPMI.txt in the kernel sources for the" + " gory details."); module_param_named(trydefaults, si_trydefaults, bool, 0); MODULE_PARM_DESC(trydefaults, "Setting this to 'false' will disable the" @@ -1038,12 +1087,12 @@ module_param_array(force_kipmid, int, &num_force_kipmid, 0); MODULE_PARM_DESC(force_kipmid, "Force the kipmi daemon to be enabled (1) or" " disabled(0). Normally the IPMI driver auto-detects" " this, but the value may be overridden by this parm."); +module_param(unload_when_empty, int, 0); +MODULE_PARM_DESC(unload_when_empty, "Unload the module if no interfaces are" + " specified or found, default is 1. Setting to 0" + " is useful for hot add of devices using hotmod."); -#define IPMI_IO_ADDR_SPACE 0 -#define IPMI_MEM_ADDR_SPACE 1 -static char *addr_space_to_str[] = { "I/O", "memory" }; - static void std_irq_cleanup(struct smi_info *info) { if (info->si_type == SI_BT) @@ -1317,6 +1366,234 @@ static int mem_setup(struct smi_info *info) return 0; } +/* + * Parms come in as [:op2[:op3...]]. ops are: + * add|remove,kcs|bt|smic,mem|i/o,
[,[,[,...]]] + * Options are: + * rsp= + * rsi= + * rsh= + * irq= + * ipmb= + */ +enum hotmod_op { HM_ADD, HM_REMOVE }; +struct hotmod_vals { + char *name; + int val; +}; +static struct hotmod_vals hotmod_ops[] = { + { "add", HM_ADD }, + { "remove", HM_REMOVE }, + { NULL } +}; +static struct hotmod_vals hotmod_si[] = { + { "kcs", SI_KCS }, + { "smic", SI_SMIC }, + { "bt", SI_BT }, + { NULL } +}; +static struct hotmod_vals hotmod_as[] = { + { "mem", IPMI_MEM_ADDR_SPACE }, + { "i/o", IPMI_IO_ADDR_SPACE }, + { NULL } +}; +static int ipmi_strcasecmp(const char *s1, const char *s2) +{ + while (*s1 || *s2) { + if (!*s1) + return -1; + if (!*s2) + return 1; + if (*s1 != *s2) + return *s1 - *s2; + s1++; + s2++; + } + return 0; +} +static int parse_str(struct hotmod_vals *v, int *val, char *name, char **curr) +{ + char *s; + int i; + + s = strchr(*curr, ','); + if (!s) { + printk(KERN_WARNING PFX "No hotmod %s given.\n", name); + return -EINVAL; + } + *s = '\0'; + s++; + for (i = 0; hotmod_ops[i].name; i++) { + if (ipmi_strcasecmp(*curr, v[i].name) == 0) { + *val = v[i].val; + *curr = s; + return 0; + } + } + + printk(KERN_WARNING PFX "Invalid hotmod %s '%s'\n", name, *curr); + return -EINVAL; +} + +static int hotmod_handler(const char *val, struct kernel_param *kp) +{ + char *str = kstrdup(val, GFP_KERNEL); + int rv = -EINVAL; + char *next, *curr, *s, *n, *o; + enum hotmod_op op; + enum si_type si_type; + int addr_space; + unsigned long addr; + int regspacing; + int regsize; + int regshift; + int irq; + int ipmb; + int ival; + struct smi_info *info; + + if (!str) + return -ENOMEM; + + /* Kill any trailing spaces, as we can get a "\n" from echo. */ + ival = strlen(str) - 1; + while ((ival >= 0) && isspace(str[ival])) { + str[ival] = '\0'; + ival--; + } + + for (curr = str; curr; curr = next) { + regspacing = 1; + regsize = 1; + regshift = 0; + irq = 0; + ipmb = 0x20; + + next = strchr(curr, ':'); + if (next) { + *next = '\0'; + next++; + } + + rv = parse_str(hotmod_ops, &ival, "operation", &curr); + if (rv) + break; + op = ival; + + rv = parse_str(hotmod_si, &ival, "interface type", &curr); + if (rv) + break; + si_type = ival; + + rv = parse_str(hotmod_as, &addr_space, "address space", &curr); + if (rv) + break; + + s = strchr(curr, ','); + if (s) { + *s = '\0'; + s++; + } + addr = simple_strtoul(curr, &n, 0); + if ((*n != '\0') || (*curr == '\0')) { + printk(KERN_WARNING PFX "Invalid hotmod address" + " '%s'\n", curr); + break; + } + + while (s) { + curr = s; + s = strchr(curr, ','); + if (s) { + *s = '\0'; + s++; + } + o = strchr(curr, '='); + if (o) { + *o = '\0'; + o++; + } +#define HOTMOD_INT_OPT(name, val) \ + if (ipmi_strcasecmp(curr, name) == 0) { \ + if (!o) { \ + printk(KERN_WARNING PFX \ + "No option given for '%s'\n", \ + curr); \ + goto out; \ + } \ + val = simple_strtoul(o, &n, 0); \ + if ((*n != '\0') || (*o == '\0')) { \ + printk(KERN_WARNING PFX \ + "Bad option given for '%s'\n", \ + curr); \ + goto out; \ + } \ + } + + HOTMOD_INT_OPT("rsp", regspacing) + else HOTMOD_INT_OPT("rsi", regsize) + else HOTMOD_INT_OPT("rsh", regshift) + else HOTMOD_INT_OPT("irq", irq) + else HOTMOD_INT_OPT("ipmb", ipmb) + else { + printk(KERN_WARNING PFX + "Invalid hotmod option '%s'\n", + curr); + goto out; + } +#undef HOTMOD_INT_OPT + } + + if (op == HM_ADD) { + info = kzalloc(sizeof(*info), GFP_KERNEL); + if (!info) { + rv = -ENOMEM; + goto out; + } + + info->addr_source = "hotmod"; + info->si_type = si_type; + info->io.addr_data = addr; + info->io.addr_type = addr_space; + if (addr_space == IPMI_MEM_ADDR_SPACE) + info->io_setup = mem_setup; + else + info->io_setup = port_setup; + + info->io.addr = NULL; + info->io.regspacing = regspacing; + if (!info->io.regspacing) + info->io.regspacing = DEFAULT_REGSPACING; + info->io.regsize = regsize; + if (!info->io.regsize) + info->io.regsize = DEFAULT_REGSPACING; + info->io.regshift = regshift; + info->irq = irq; + if (info->irq) + info->irq_setup = std_irq_setup; + info->slave_addr = ipmb; + + try_smi_init(info); + } else { + /* remove */ + struct smi_info *e, *tmp_e; + + mutex_lock(&smi_infos_lock); + list_for_each_entry_safe(e, tmp_e, &smi_infos, link) { + if (e->io.addr_type != addr_space) + continue; + if (e->si_type != si_type) + continue; + if (e->io.addr_data == addr) + cleanup_one_si(e); + } + mutex_unlock(&smi_infos_lock); + } + } + out: + kfree(str); + return rv; +} static __devinit void hardcode_find_bmc(void) { @@ -1333,11 +1610,11 @@ static __devinit void hardcode_find_bmc(void) info->addr_source = "hardcoded"; - if (!si_type[i] || strcmp(si_type[i], "kcs") == 0) { + if (!si_type[i] || ipmi_strcasecmp(si_type[i], "kcs") == 0) { info->si_type = SI_KCS; - } else if (strcmp(si_type[i], "smic") == 0) { + } else if (ipmi_strcasecmp(si_type[i], "smic") == 0) { info->si_type = SI_SMIC; - } else if (strcmp(si_type[i], "bt") == 0) { + } else if (ipmi_strcasecmp(si_type[i], "bt") == 0) { info->si_type = SI_BT; } else { printk(KERN_WARNING @@ -1952,19 +2229,9 @@ static int try_get_dev_id(struct smi_info *smi_info) static int type_file_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data) { - char *out = (char *) page; struct smi_info *smi = data; - switch (smi->si_type) { - case SI_KCS: - return sprintf(out, "kcs\n"); - case SI_SMIC: - return sprintf(out, "smic\n"); - case SI_BT: - return sprintf(out, "bt\n"); - default: - return 0; - } + return sprintf(page, "%s\n", si_to_str[smi->si_type]); } static int stat_file_read_proc(char *page, char **start, off_t off, @@ -2000,7 +2267,24 @@ static int stat_file_read_proc(char *page, char **start, off_t off, out += sprintf(out, "incoming_messages: %ld\n", smi->incoming_messages); - return (out - ((char *) page)); + return out - page; +} + +static int param_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + struct smi_info *smi = data; + + return sprintf(page, + "%s,%s,0x%lx,rsp=%d,rsi=%d,rsh=%d,irq=%d,ipmb=%d\n", + si_to_str[smi->si_type], + addr_space_to_str[smi->io.addr_type], + smi->io.addr_data, + smi->io.regspacing, + smi->io.regsize, + smi->io.regshift, + smi->irq, + smi->slave_addr); } /* @@ -2362,6 +2646,7 @@ static int try_smi_init(struct smi_info *new_smi) new_smi, &new_smi->device_id, new_smi->dev, + "bmc", new_smi->slave_addr); if (rv) { printk(KERN_ERR @@ -2390,6 +2675,16 @@ static int try_smi_init(struct smi_info *new_smi) goto out_err_stop_timer; } + rv = ipmi_smi_add_proc_entry(new_smi->intf, "params", + param_read_proc, NULL, + new_smi, THIS_MODULE); + if (rv) { + printk(KERN_ERR + "ipmi_si: Unable to create proc entry: %d\n", + rv); + goto out_err_stop_timer; + } + list_add_tail(&new_smi->link, &smi_infos); mutex_unlock(&smi_infos_lock); @@ -2483,7 +2778,12 @@ static __devinit int init_ipmi_si(void) #endif #ifdef CONFIG_PCI - pci_module_init(&ipmi_pci_driver); + rv = pci_register_driver(&ipmi_pci_driver); + if (rv){ + printk(KERN_ERR + "init_ipmi_si: Unable to register PCI driver: %d\n", + rv); + } #endif if (si_trydefaults) { @@ -2498,7 +2798,7 @@ static __devinit int init_ipmi_si(void) } mutex_lock(&smi_infos_lock); - if (list_empty(&smi_infos)) { + if (unload_when_empty && list_empty(&smi_infos)) { mutex_unlock(&smi_infos_lock); #ifdef CONFIG_PCI pci_unregister_driver(&ipmi_pci_driver); @@ -2513,7 +2813,7 @@ static __devinit int init_ipmi_si(void) } module_init(init_ipmi_si); -static void __devexit cleanup_one_si(struct smi_info *to_clean) +static void cleanup_one_si(struct smi_info *to_clean) { int rv; unsigned long flags; diff --git a/trunk/drivers/char/ipmi/ipmi_smic_sm.c b/trunk/drivers/char/ipmi/ipmi_smic_sm.c index 39d7e5ef1a2b..e64ea7d25d24 100644 --- a/trunk/drivers/char/ipmi/ipmi_smic_sm.c +++ b/trunk/drivers/char/ipmi/ipmi_smic_sm.c @@ -141,12 +141,14 @@ static int start_smic_transaction(struct si_sm_data *smic, { unsigned int i; - if ((size < 2) || (size > MAX_SMIC_WRITE_SIZE)) { - return -1; - } - if ((smic->state != SMIC_IDLE) && (smic->state != SMIC_HOSED)) { - return -2; - } + if (size < 2) + return IPMI_REQ_LEN_INVALID_ERR; + if (size > MAX_SMIC_WRITE_SIZE) + return IPMI_REQ_LEN_EXCEEDED_ERR; + + if ((smic->state != SMIC_IDLE) && (smic->state != SMIC_HOSED)) + return IPMI_NOT_IN_MY_STATE_ERR; + if (smic_debug & SMIC_DEBUG_MSG) { printk(KERN_INFO "start_smic_transaction -"); for (i = 0; i < size; i ++) { diff --git a/trunk/drivers/char/ipmi/ipmi_watchdog.c b/trunk/drivers/char/ipmi/ipmi_watchdog.c index 73f759eaa5a6..90fb2a541916 100644 --- a/trunk/drivers/char/ipmi/ipmi_watchdog.c +++ b/trunk/drivers/char/ipmi/ipmi_watchdog.c @@ -135,6 +135,7 @@ static int nowayout = WATCHDOG_NOWAYOUT; static ipmi_user_t watchdog_user = NULL; +static int watchdog_ifnum; /* Default the timeout to 10 seconds. */ static int timeout = 10; @@ -161,6 +162,8 @@ static struct fasync_struct *fasync_q = NULL; static char pretimeout_since_last_heartbeat = 0; static char expect_close; +static int ifnum_to_use = -1; + static DECLARE_RWSEM(register_sem); /* Parameters to ipmi_set_timeout */ @@ -169,6 +172,8 @@ static DECLARE_RWSEM(register_sem); #define IPMI_SET_TIMEOUT_FORCE_HB 2 static int ipmi_set_timeout(int do_heartbeat); +static void ipmi_register_watchdog(int ipmi_intf); +static void ipmi_unregister_watchdog(int ipmi_intf); /* If true, the driver will start running as soon as it is configured and ready. */ @@ -245,6 +250,26 @@ static int get_param_str(char *buffer, struct kernel_param *kp) return strlen(buffer); } + +static int set_param_wdog_ifnum(const char *val, struct kernel_param *kp) +{ + int rv = param_set_int(val, kp); + if (rv) + return rv; + if ((ifnum_to_use < 0) || (ifnum_to_use == watchdog_ifnum)) + return 0; + + ipmi_unregister_watchdog(watchdog_ifnum); + ipmi_register_watchdog(ifnum_to_use); + return 0; +} + +module_param_call(ifnum_to_use, set_param_wdog_ifnum, get_param_int, + &ifnum_to_use, 0644); +MODULE_PARM_DESC(ifnum_to_use, "The interface number to use for the watchdog " + "timer. Setting to -1 defaults to the first registered " + "interface"); + module_param_call(timeout, set_param_int, get_param_int, &timeout, 0644); MODULE_PARM_DESC(timeout, "Timeout value in seconds."); @@ -263,12 +288,13 @@ module_param_call(preop, set_param_str, get_param_str, preop_op, 0644); MODULE_PARM_DESC(preop, "Pretimeout driver operation. One of: " "preop_none, preop_panic, preop_give_data."); -module_param(start_now, int, 0); +module_param(start_now, int, 0444); MODULE_PARM_DESC(start_now, "Set to 1 to start the watchdog as" "soon as the driver is loaded."); module_param(nowayout, int, 0644); -MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); +MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started " + "(default=CONFIG_WATCHDOG_NOWAYOUT)"); /* Default state of the timer. */ static unsigned char ipmi_watchdog_state = WDOG_TIMEOUT_NONE; @@ -872,6 +898,11 @@ static void ipmi_register_watchdog(int ipmi_intf) if (watchdog_user) goto out; + if ((ifnum_to_use >= 0) && (ifnum_to_use != ipmi_intf)) + goto out; + + watchdog_ifnum = ipmi_intf; + rv = ipmi_create_user(ipmi_intf, &ipmi_hndlrs, NULL, &watchdog_user); if (rv < 0) { printk(KERN_CRIT PFX "Unable to register with ipmi\n"); @@ -901,6 +932,39 @@ static void ipmi_register_watchdog(int ipmi_intf) } } +static void ipmi_unregister_watchdog(int ipmi_intf) +{ + int rv; + + down_write(®ister_sem); + + if (!watchdog_user) + goto out; + + if (watchdog_ifnum != ipmi_intf) + goto out; + + /* Make sure no one can call us any more. */ + misc_deregister(&ipmi_wdog_miscdev); + + /* Wait to make sure the message makes it out. The lower layer has + pointers to our buffers, we want to make sure they are done before + we release our memory. */ + while (atomic_read(&set_timeout_tofree)) + schedule_timeout_uninterruptible(1); + + /* Disconnect from IPMI. */ + rv = ipmi_destroy_user(watchdog_user); + if (rv) { + printk(KERN_WARNING PFX "error unlinking from IPMI: %d\n", + rv); + } + watchdog_user = NULL; + + out: + up_write(®ister_sem); +} + #ifdef HAVE_NMI_HANDLER static int ipmi_nmi(void *dev_id, int cpu, int handled) @@ -1004,9 +1068,7 @@ static void ipmi_new_smi(int if_num, struct device *device) static void ipmi_smi_gone(int if_num) { - /* This can never be called, because once the watchdog is - registered, the interface can't go away until the watchdog - is unregistered. */ + ipmi_unregister_watchdog(if_num); } static struct ipmi_smi_watcher smi_watcher = @@ -1148,30 +1210,32 @@ static int __init ipmi_wdog_init(void) check_parms(); + register_reboot_notifier(&wdog_reboot_notifier); + atomic_notifier_chain_register(&panic_notifier_list, + &wdog_panic_notifier); + rv = ipmi_smi_watcher_register(&smi_watcher); if (rv) { #ifdef HAVE_NMI_HANDLER if (preaction_val == WDOG_PRETIMEOUT_NMI) release_nmi(&ipmi_nmi_handler); #endif + atomic_notifier_chain_unregister(&panic_notifier_list, + &wdog_panic_notifier); + unregister_reboot_notifier(&wdog_reboot_notifier); printk(KERN_WARNING PFX "can't register smi watcher\n"); return rv; } - register_reboot_notifier(&wdog_reboot_notifier); - atomic_notifier_chain_register(&panic_notifier_list, - &wdog_panic_notifier); - printk(KERN_INFO PFX "driver initialized\n"); return 0; } -static __exit void ipmi_unregister_watchdog(void) +static void __exit ipmi_wdog_exit(void) { - int rv; - - down_write(®ister_sem); + ipmi_smi_watcher_unregister(&smi_watcher); + ipmi_unregister_watchdog(watchdog_ifnum); #ifdef HAVE_NMI_HANDLER if (nmi_handler_registered) @@ -1179,37 +1243,8 @@ static __exit void ipmi_unregister_watchdog(void) #endif atomic_notifier_chain_unregister(&panic_notifier_list, - &wdog_panic_notifier); + &wdog_panic_notifier); unregister_reboot_notifier(&wdog_reboot_notifier); - - if (! watchdog_user) - goto out; - - /* Make sure no one can call us any more. */ - misc_deregister(&ipmi_wdog_miscdev); - - /* Wait to make sure the message makes it out. The lower layer has - pointers to our buffers, we want to make sure they are done before - we release our memory. */ - while (atomic_read(&set_timeout_tofree)) - schedule_timeout_uninterruptible(1); - - /* Disconnect from IPMI. */ - rv = ipmi_destroy_user(watchdog_user); - if (rv) { - printk(KERN_WARNING PFX "error unlinking from IPMI: %d\n", - rv); - } - watchdog_user = NULL; - - out: - up_write(®ister_sem); -} - -static void __exit ipmi_wdog_exit(void) -{ - ipmi_smi_watcher_unregister(&smi_watcher); - ipmi_unregister_watchdog(); } module_exit(ipmi_wdog_exit); module_init(ipmi_wdog_init); diff --git a/trunk/drivers/char/isicom.c b/trunk/drivers/char/isicom.c index 58c955e390b3..5a747e685993 100644 --- a/trunk/drivers/char/isicom.c +++ b/trunk/drivers/char/isicom.c @@ -172,12 +172,14 @@ static struct pci_driver isicom_driver = { static int prev_card = 3; /* start servicing isi_card[0] */ static struct tty_driver *isicom_normal; -static struct timer_list tx; +static DECLARE_COMPLETION(isi_timerdone); static char re_schedule = 1; static void isicom_tx(unsigned long _data); static void isicom_start(struct tty_struct *tty); +static DEFINE_TIMER(tx, isicom_tx, 0, 0); + /* baud index mappings from linux defns to isi */ static signed char linuxb_to_isib[] = { @@ -193,9 +195,9 @@ struct isi_board { unsigned short shift_count; struct isi_port * ports; signed char count; - unsigned char isa; spinlock_t card_lock; /* Card wide lock 11/5/00 -sameer */ unsigned long flags; + unsigned int index; }; struct isi_port { @@ -514,25 +516,19 @@ static void isicom_tx(unsigned long _data) /* schedule another tx for hopefully in about 10ms */ sched_again: if (!re_schedule) { - re_schedule = 2; + complete(&isi_timerdone); return; } - init_timer(&tx); - tx.expires = jiffies + HZ/100; - tx.data = 0; - tx.function = isicom_tx; - add_timer(&tx); - - return; + mod_timer(&tx, jiffies + msecs_to_jiffies(10)); } /* Interrupt handlers */ -static void isicom_bottomhalf(void *data) +static void isicom_bottomhalf(struct work_struct *work) { - struct isi_port *port = (struct isi_port *) data; + struct isi_port *port = container_of(work, struct isi_port, bh_tqueue); struct tty_struct *tty = port->tty; if (!tty) @@ -562,14 +558,12 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id) base = card->base; spin_lock(&card->card_lock); - if (card->isa == NO) { - /* - * disable any interrupts from the PCI card and lower the - * interrupt line - */ - outw(0x8000, base+0x04); - ClearInterrupt(base); - } + /* + * disable any interrupts from the PCI card and lower the + * interrupt line + */ + outw(0x8000, base+0x04); + ClearInterrupt(base); inw(base); /* get the dummy word out */ header = inw(base); @@ -579,19 +573,13 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id) if (channel + 1 > card->port_count) { printk(KERN_WARNING "ISICOM: isicom_interrupt(0x%lx): " "%d(channel) > port_count.\n", base, channel+1); - if (card->isa) - ClearInterrupt(base); - else - outw(0x0000, base+0x04); /* enable interrupts */ + outw(0x0000, base+0x04); /* enable interrupts */ spin_unlock(&card->card_lock); return IRQ_HANDLED; } port = card->ports + channel; if (!(port->flags & ASYNC_INITIALIZED)) { - if (card->isa) - ClearInterrupt(base); - else - outw(0x0000, base+0x04); /* enable interrupts */ + outw(0x0000, base+0x04); /* enable interrupts */ return IRQ_HANDLED; } @@ -604,10 +592,7 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id) } if (byte_count & 0x01) inw(base); - if (card->isa == YES) - ClearInterrupt(base); - else - outw(0x0000, base+0x04); /* enable interrupts */ + outw(0x0000, base+0x04); /* enable interrupts */ spin_unlock(&card->card_lock); return IRQ_HANDLED; } @@ -708,10 +693,7 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id) } tty_flip_buffer_push(tty); } - if (card->isa == YES) - ClearInterrupt(base); - else - outw(0x0000, base+0x04); /* enable interrupts */ + outw(0x0000, base+0x04); /* enable interrupts */ return IRQ_HANDLED; } @@ -964,8 +946,8 @@ static int isicom_open(struct tty_struct *tty, struct file *filp) { struct isi_port *port; struct isi_board *card; - unsigned int line, board; - int error; + unsigned int board; + int error, line; line = tty->index; if (line < 0 || line > PORT_COUNT-1) @@ -1399,7 +1381,7 @@ static int isicom_ioctl(struct tty_struct *tty, struct file *filp, /* set_termios et all */ static void isicom_set_termios(struct tty_struct *tty, - struct termios *old_termios) + struct ktermios *old_termios) { struct isi_port *port = tty->driver_data; @@ -1474,9 +1456,9 @@ static void isicom_start(struct tty_struct *tty) } /* hangup et all */ -static void do_isicom_hangup(void *data) +static void do_isicom_hangup(struct work_struct *work) { - struct isi_port *port = data; + struct isi_port *port = container_of(work, struct isi_port, hangup_tq); struct tty_struct *tty; tty = port->tty; @@ -1520,37 +1502,6 @@ static void isicom_flush_buffer(struct tty_struct *tty) * Driver init and deinit functions */ -static int __devinit isicom_register_ioregion(struct pci_dev *pdev, - const unsigned int index) -{ - struct isi_board *board = pci_get_drvdata(pdev); - - if (!board->base) - return -EINVAL; - - if (!request_region(board->base, 16, ISICOM_NAME)) { - dev_dbg(&pdev->dev, "I/O Region 0x%lx-0x%lx is busy. Card%d " - "will be disabled.\n", board->base, board->base + 15, - index + 1); - return -EBUSY; - } - - return 0; -} - -static void isicom_unregister_ioregion(struct pci_dev *pdev) -{ - struct isi_board *board = pci_get_drvdata(pdev); - - if (!board->base) - return; - - release_region(board->base, 16); - dev_dbg(&pdev->dev, "I/O Region 0x%lx-0x%lx released.\n", - board->base, board->base + 15); - board->base = 0; -} - static const struct tty_operations isicom_ops = { .open = isicom_open, .close = isicom_close, @@ -1571,70 +1522,6 @@ static const struct tty_operations isicom_ops = { .tiocmset = isicom_tiocmset, }; -static int __devinit isicom_register_tty_driver(void) -{ - int error = -ENOMEM; - - /* tty driver structure initialization */ - isicom_normal = alloc_tty_driver(PORT_COUNT); - if (!isicom_normal) - goto end; - - isicom_normal->owner = THIS_MODULE; - isicom_normal->name = "ttyM"; - isicom_normal->major = ISICOM_NMAJOR; - isicom_normal->minor_start = 0; - isicom_normal->type = TTY_DRIVER_TYPE_SERIAL; - isicom_normal->subtype = SERIAL_TYPE_NORMAL; - isicom_normal->init_termios = tty_std_termios; - isicom_normal->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | - CLOCAL; - isicom_normal->flags = TTY_DRIVER_REAL_RAW; - tty_set_operations(isicom_normal, &isicom_ops); - - if ((error = tty_register_driver(isicom_normal))) { - pr_dbg("Couldn't register the dialin driver, error=%d\n", - error); - put_tty_driver(isicom_normal); - } -end: - return error; -} - -static void isicom_unregister_tty_driver(void) -{ - int error; - - if ((error = tty_unregister_driver(isicom_normal))) - pr_dbg("couldn't unregister normal driver, error=%d.\n", error); - - put_tty_driver(isicom_normal); -} - -static int __devinit isicom_register_isr(struct pci_dev *pdev, - const unsigned int index) -{ - struct isi_board *board = pci_get_drvdata(pdev); - unsigned long irqflags = IRQF_DISABLED; - int retval = -EINVAL; - - if (!board->base) - goto end; - - if (board->isa == NO) - irqflags |= IRQF_SHARED; - - retval = request_irq(board->irq, isicom_interrupt, irqflags, - ISICOM_NAME, board); - if (retval < 0) - dev_warn(&pdev->dev, "Could not install handler at Irq %d. " - "Card%d will be disabled.\n", board->irq, index + 1); - else - retval = 0; -end: - return retval; -} - static int __devinit reset_card(struct pci_dev *pdev, const unsigned int card, unsigned int *signature) { @@ -1656,36 +1543,23 @@ static int __devinit reset_card(struct pci_dev *pdev, *signature = inw(base + 0x4) & 0xff; - if (board->isa == YES) { - if (!(inw(base + 0xe) & 0x1) || (inw(base + 0x2))) { - dev_dbg(&pdev->dev, "base+0x2=0x%lx, base+0xe=0x%lx\n", - inw(base + 0x2), inw(base + 0xe)); - dev_err(&pdev->dev, "ISILoad:ISA Card%d reset failure " - "(Possible bad I/O Port Address 0x%lx).\n", - card + 1, base); - retval = -EIO; - goto end; - } - } else { - portcount = inw(base + 0x2); - if (!(inw(base + 0xe) & 0x1) || ((portcount != 0) && - (portcount != 4) && (portcount != 8))) { - dev_dbg(&pdev->dev, "base+0x2=0x%lx, base+0xe=0x%lx\n", - inw(base + 0x2), inw(base + 0xe)); - dev_err(&pdev->dev, "ISILoad:PCI Card%d reset failure " - "(Possible bad I/O Port Address 0x%lx).\n", - card + 1, base); - retval = -EIO; - goto end; - } + portcount = inw(base + 0x2); + if (!(inw(base + 0xe) & 0x1) || ((portcount != 0) && + (portcount != 4) && (portcount != 8))) { + dev_dbg(&pdev->dev, "base+0x2=0x%lx, base+0xe=0x%lx\n", + inw(base + 0x2), inw(base + 0xe)); + dev_err(&pdev->dev, "ISILoad:PCI Card%d reset failure " + "(Possible bad I/O Port Address 0x%lx).\n", + card + 1, base); + retval = -EIO; + goto end; } switch (*signature) { case 0xa5: case 0xbb: case 0xdd: - board->port_count = (board->isa == NO && portcount == 4) ? 4 : - 8; + board->port_count = (portcount == 4) ? 4 : 8; board->shift_count = 12; break; case 0xcc: @@ -1831,6 +1705,11 @@ static int __devinit load_firmware(struct pci_dev *pdev, } data = kmalloc(word_count * 2, GFP_KERNEL); + if (data == NULL) { + dev_err(&pdev->dev, "Card%d, firmware upload " + "failed, not enough memory\n", index + 1); + goto errrelfw; + } inw(base); insw(base, data, word_count); InterruptTheCard(base); @@ -1879,8 +1758,6 @@ static int __devinit load_firmware(struct pci_dev *pdev, /* * Insmod can set static symbols so keep these static */ -static int io[4]; -static int irq[4]; static int card; static int __devinit isicom_probe(struct pci_dev *pdev, @@ -1906,20 +1783,29 @@ static int __devinit isicom_probe(struct pci_dev *pdev, break; } + board->index = index; board->base = ioaddr; board->irq = pciirq; - board->isa = NO; card++; pci_set_drvdata(pdev, board); - retval = isicom_register_ioregion(pdev, index); - if (retval < 0) + retval = pci_request_region(pdev, 3, ISICOM_NAME); + if (retval) { + dev_err(&pdev->dev, "I/O Region 0x%lx-0x%lx is busy. Card%d " + "will be disabled.\n", board->base, board->base + 15, + index + 1); + retval = -EBUSY; goto err; + } - retval = isicom_register_isr(pdev, index); - if (retval < 0) + retval = request_irq(board->irq, isicom_interrupt, + IRQF_SHARED | IRQF_DISABLED, ISICOM_NAME, board); + if (retval < 0) { + dev_err(&pdev->dev, "Could not install handler at Irq %d. " + "Card%d will be disabled.\n", board->irq, index + 1); goto errunrr; + } retval = reset_card(pdev, index, &signature); if (retval < 0) @@ -1929,12 +1815,16 @@ static int __devinit isicom_probe(struct pci_dev *pdev, if (retval < 0) goto errunri; + for (index = 0; index < board->port_count; index++) + tty_register_device(isicom_normal, board->index * 16 + index, + &pdev->dev); + return 0; errunri: free_irq(board->irq, board); errunrr: - isicom_unregister_ioregion(pdev); + pci_release_region(pdev, 3); err: board->base = 0; return retval; @@ -1943,18 +1833,21 @@ static int __devinit isicom_probe(struct pci_dev *pdev, static void __devexit isicom_remove(struct pci_dev *pdev) { struct isi_board *board = pci_get_drvdata(pdev); + unsigned int i; + + for (i = 0; i < board->port_count; i++) + tty_unregister_device(isicom_normal, board->index * 16 + i); free_irq(board->irq, board); - isicom_unregister_ioregion(pdev); + pci_release_region(pdev, 3); } -static int __devinit isicom_setup(void) +static int __init isicom_init(void) { int retval, idx, channel; struct isi_port *port; card = 0; - memset(isi_ports, 0, sizeof(isi_ports)); for(idx = 0; idx < BOARD_COUNT; idx++) { port = &isi_ports[idx * 16]; @@ -1966,8 +1859,8 @@ static int __devinit isicom_setup(void) port->channel = channel; port->close_delay = 50 * HZ/100; port->closing_wait = 3000 * HZ/100; - INIT_WORK(&port->hangup_tq, do_isicom_hangup, port); - INIT_WORK(&port->bh_tqueue, isicom_bottomhalf, port); + INIT_WORK(&port->hangup_tq, do_isicom_hangup); + INIT_WORK(&port->bh_tqueue, isicom_bottomhalf); port->status = 0; init_waitqueue_head(&port->open_wait); init_waitqueue_head(&port->close_wait); @@ -1975,66 +1868,65 @@ static int __devinit isicom_setup(void) } isi_card[idx].base = 0; isi_card[idx].irq = 0; - - if (!io[idx]) - continue; - - if (irq[idx] == 2 || irq[idx] == 3 || irq[idx] == 4 || - irq[idx] == 5 || irq[idx] == 7 || - irq[idx] == 10 || irq[idx] == 11 || - irq[idx] == 12 || irq[idx] == 15) { - printk(KERN_ERR "ISICOM: ISA not supported yet.\n"); - retval = -EINVAL; - goto error; - } else - printk(KERN_ERR "ISICOM: Irq %d unsupported. " - "Disabling Card%d...\n", irq[idx], idx + 1); } - retval = isicom_register_tty_driver(); - if (retval < 0) + /* tty driver structure initialization */ + isicom_normal = alloc_tty_driver(PORT_COUNT); + if (!isicom_normal) { + retval = -ENOMEM; goto error; + } + + isicom_normal->owner = THIS_MODULE; + isicom_normal->name = "ttyM"; + isicom_normal->major = ISICOM_NMAJOR; + isicom_normal->minor_start = 0; + isicom_normal->type = TTY_DRIVER_TYPE_SERIAL; + isicom_normal->subtype = SERIAL_TYPE_NORMAL; + isicom_normal->init_termios = tty_std_termios; + isicom_normal->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | + CLOCAL; + isicom_normal->flags = TTY_DRIVER_REAL_RAW | + TTY_DRIVER_DYNAMIC_DEV; + tty_set_operations(isicom_normal, &isicom_ops); + + retval = tty_register_driver(isicom_normal); + if (retval) { + pr_dbg("Couldn't register the dialin driver\n"); + goto err_puttty; + } retval = pci_register_driver(&isicom_driver); if (retval < 0) { printk(KERN_ERR "ISICOM: Unable to register pci driver.\n"); - goto errtty; + goto err_unrtty; } - init_timer(&tx); - tx.expires = jiffies + 1; - tx.data = 0; - tx.function = isicom_tx; - re_schedule = 1; - add_timer(&tx); + mod_timer(&tx, jiffies + 1); return 0; -errtty: - isicom_unregister_tty_driver(); +err_unrtty: + tty_unregister_driver(isicom_normal); +err_puttty: + put_tty_driver(isicom_normal); error: return retval; } static void __exit isicom_exit(void) { - unsigned int index = 0; - re_schedule = 0; - while (re_schedule != 2 && index++ < 100) - msleep(10); + wait_for_completion_timeout(&isi_timerdone, HZ); pci_unregister_driver(&isicom_driver); - isicom_unregister_tty_driver(); + tty_unregister_driver(isicom_normal); + put_tty_driver(isicom_normal); } -module_init(isicom_setup); +module_init(isicom_init); module_exit(isicom_exit); MODULE_AUTHOR("MultiTech"); MODULE_DESCRIPTION("Driver for the ISI series of cards by MultiTech"); MODULE_LICENSE("GPL"); -module_param_array(io, int, NULL, 0); -MODULE_PARM_DESC(io, "I/O ports for the cards"); -module_param_array(irq, int, NULL, 0); -MODULE_PARM_DESC(irq, "Interrupts for the cards"); diff --git a/trunk/drivers/char/istallion.c b/trunk/drivers/char/istallion.c index ffdf9df1a67a..68645d351873 100644 --- a/trunk/drivers/char/istallion.c +++ b/trunk/drivers/char/istallion.c @@ -14,14 +14,6 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /*****************************************************************************/ @@ -41,6 +33,7 @@ #include #include #include +#include #include #include @@ -61,21 +54,10 @@ #define BRD_BRUMBY4 2 #define BRD_ONBOARD2 3 #define BRD_ONBOARD 4 -#define BRD_BRUMBY8 5 -#define BRD_BRUMBY16 6 #define BRD_ONBOARDE 7 -#define BRD_ONBOARD32 9 -#define BRD_ONBOARD2_32 10 -#define BRD_ONBOARDRS 11 -#define BRD_EASYIO 20 -#define BRD_ECH 21 -#define BRD_ECHMC 22 #define BRD_ECP 23 #define BRD_ECPE 24 #define BRD_ECPMC 25 -#define BRD_ECHPCI 26 -#define BRD_ECH64PCI 27 -#define BRD_EASYIOPCI 28 #define BRD_ECPPCI 29 #define BRD_BRUMBY BRD_BRUMBY4 @@ -119,20 +101,16 @@ * interrupt is required. */ -typedef struct { +struct stlconf { int brdtype; int ioaddr1; int ioaddr2; unsigned long memaddr; int irq; int irqtype; -} stlconf_t; - -static stlconf_t stli_brdconf[] = { - /*{ BRD_ECP, 0x2a0, 0, 0xcc000, 0, 0 },*/ }; -static int stli_nrbrds = ARRAY_SIZE(stli_brdconf); +static unsigned int stli_nrbrds; /* stli_lock must NOT be taken holding brd_lock */ static spinlock_t stli_lock; /* TTY logic lock */ @@ -194,9 +172,11 @@ static struct tty_struct *stli_txcooktty; * with this termios initially. Basically all it defines is a raw port * at 9600 baud, 8 data bits, no parity, 1 stop bit. */ -static struct termios stli_deftermios = { +static struct ktermios stli_deftermios = { .c_cflag = (B9600 | CS8 | CREAD | HUPCL | CLOCAL), .c_cc = INIT_C_CC, + .c_ispeed = 9600, + .c_ospeed = 9600, }; /* @@ -205,13 +185,12 @@ static struct termios stli_deftermios = { */ static comstats_t stli_comstats; static combrd_t stli_brdstats; -static asystats_t stli_cdkstats; -static stlibrd_t stli_dummybrd; -static stliport_t stli_dummyport; +static struct asystats stli_cdkstats; /*****************************************************************************/ -static stlibrd_t *stli_brds[STL_MAXBRDS]; +static DEFINE_MUTEX(stli_brdslock); +static struct stlibrd *stli_brds[STL_MAXBRDS]; static int stli_shared; @@ -223,6 +202,7 @@ static int stli_shared; */ #define BST_FOUND 0x1 #define BST_STARTED 0x2 +#define BST_PROBED 0x4 /* * Define the set of port state flags. These are marked for internal @@ -255,18 +235,18 @@ static char *stli_brdnames[] = { "Brumby", "Brumby", "ONboard-EI", - (char *) NULL, + NULL, "ONboard", "ONboard-MC", "ONboard-MC", - (char *) NULL, - (char *) NULL, - (char *) NULL, - (char *) NULL, - (char *) NULL, - (char *) NULL, - (char *) NULL, - (char *) NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, "EasyIO", "EC8/32-AT", "EC8/32-MC", @@ -304,12 +284,10 @@ static char **stli_brdsp[] = { * parse any module arguments. */ -typedef struct stlibrdtype { +static struct stlibrdtype { char *name; int type; -} stlibrdtype_t; - -static stlibrdtype_t stli_brdstr[] = { +} stli_brdstr[] = { { "stallion", BRD_STALLION }, { "1", BRD_STALLION }, { "brumby", BRD_BRUMBY }, @@ -379,6 +357,7 @@ MODULE_PARM_DESC(board2, "Board 2 config -> name[,ioaddr[,memaddr]"); module_param_array(board3, charp, NULL, 0); MODULE_PARM_DESC(board3, "Board 3 config -> name[,ioaddr[,memaddr]"); +#if STLI_EISAPROBE != 0 /* * Set up a default memory address table for EISA board probing. * The default addresses are all bellow 1Mbyte, which has to be the @@ -396,14 +375,11 @@ static unsigned long stli_eisamemprobeaddrs[] = { }; static int stli_eisamempsize = ARRAY_SIZE(stli_eisamemprobeaddrs); +#endif /* * Define the Stallion PCI vendor and device IDs. */ -#ifdef CONFIG_PCI -#ifndef PCI_VENDOR_ID_STALLION -#define PCI_VENDOR_ID_STALLION 0x124d -#endif #ifndef PCI_DEVICE_ID_ECRA #define PCI_DEVICE_ID_ECRA 0x0004 #endif @@ -414,7 +390,7 @@ static struct pci_device_id istallion_pci_tbl[] = { }; MODULE_DEVICE_TABLE(pci, istallion_pci_tbl); -#endif /* CONFIG_PCI */ +static struct pci_driver stli_pcidriver; /*****************************************************************************/ @@ -614,23 +590,11 @@ MODULE_DEVICE_TABLE(pci, istallion_pci_tbl); /*****************************************************************************/ -/* - * Define some handy local macros... - */ -#undef MIN -#define MIN(a,b) (((a) <= (b)) ? (a) : (b)) - -#undef TOLOWER -#define TOLOWER(x) ((((x) >= 'A') && ((x) <= 'Z')) ? ((x) + 0x20) : (x)) - -/*****************************************************************************/ - /* * Prototype all functions in this driver! */ -static int stli_parsebrd(stlconf_t *confp, char **argp); -static int stli_init(void); +static int stli_parsebrd(struct stlconf *confp, char **argp); static int stli_open(struct tty_struct *tty, struct file *filp); static void stli_close(struct tty_struct *tty, struct file *filp); static int stli_write(struct tty_struct *tty, const unsigned char *buf, int count); @@ -639,7 +603,7 @@ static void stli_flushchars(struct tty_struct *tty); static int stli_writeroom(struct tty_struct *tty); static int stli_charsinbuffer(struct tty_struct *tty); static int stli_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg); -static void stli_settermios(struct tty_struct *tty, struct termios *old); +static void stli_settermios(struct tty_struct *tty, struct ktermios *old); static void stli_throttle(struct tty_struct *tty); static void stli_unthrottle(struct tty_struct *tty); static void stli_stop(struct tty_struct *tty); @@ -649,86 +613,84 @@ static void stli_breakctl(struct tty_struct *tty, int state); static void stli_waituntilsent(struct tty_struct *tty, int timeout); static void stli_sendxchar(struct tty_struct *tty, char ch); static void stli_hangup(struct tty_struct *tty); -static int stli_portinfo(stlibrd_t *brdp, stliport_t *portp, int portnr, char *pos); +static int stli_portinfo(struct stlibrd *brdp, struct stliport *portp, int portnr, char *pos); -static int stli_brdinit(stlibrd_t *brdp); -static int stli_startbrd(stlibrd_t *brdp); +static int stli_brdinit(struct stlibrd *brdp); +static int stli_startbrd(struct stlibrd *brdp); static ssize_t stli_memread(struct file *fp, char __user *buf, size_t count, loff_t *offp); static ssize_t stli_memwrite(struct file *fp, const char __user *buf, size_t count, loff_t *offp); static int stli_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg); -static void stli_brdpoll(stlibrd_t *brdp, cdkhdr_t __iomem *hdrp); +static void stli_brdpoll(struct stlibrd *brdp, cdkhdr_t __iomem *hdrp); static void stli_poll(unsigned long arg); -static int stli_hostcmd(stlibrd_t *brdp, stliport_t *portp); -static int stli_initopen(stlibrd_t *brdp, stliport_t *portp); -static int stli_rawopen(stlibrd_t *brdp, stliport_t *portp, unsigned long arg, int wait); -static int stli_rawclose(stlibrd_t *brdp, stliport_t *portp, unsigned long arg, int wait); -static int stli_waitcarrier(stlibrd_t *brdp, stliport_t *portp, struct file *filp); -static void stli_dohangup(void *arg); -static int stli_setport(stliport_t *portp); -static int stli_cmdwait(stlibrd_t *brdp, stliport_t *portp, unsigned long cmd, void *arg, int size, int copyback); -static void stli_sendcmd(stlibrd_t *brdp, stliport_t *portp, unsigned long cmd, void *arg, int size, int copyback); -static void __stli_sendcmd(stlibrd_t *brdp, stliport_t *portp, unsigned long cmd, void *arg, int size, int copyback); -static void stli_dodelaycmd(stliport_t *portp, cdkctrl_t __iomem *cp); -static void stli_mkasyport(stliport_t *portp, asyport_t *pp, struct termios *tiosp); +static int stli_hostcmd(struct stlibrd *brdp, struct stliport *portp); +static int stli_initopen(struct stlibrd *brdp, struct stliport *portp); +static int stli_rawopen(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait); +static int stli_rawclose(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait); +static int stli_waitcarrier(struct stlibrd *brdp, struct stliport *portp, struct file *filp); +static void stli_dohangup(struct work_struct *); +static int stli_setport(struct stliport *portp); +static int stli_cmdwait(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback); +static void stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback); +static void __stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback); +static void stli_dodelaycmd(struct stliport *portp, cdkctrl_t __iomem *cp); +static void stli_mkasyport(struct stliport *portp, asyport_t *pp, struct ktermios *tiosp); static void stli_mkasysigs(asysigs_t *sp, int dtr, int rts); static long stli_mktiocm(unsigned long sigvalue); -static void stli_read(stlibrd_t *brdp, stliport_t *portp); -static int stli_getserial(stliport_t *portp, struct serial_struct __user *sp); -static int stli_setserial(stliport_t *portp, struct serial_struct __user *sp); +static void stli_read(struct stlibrd *brdp, struct stliport *portp); +static int stli_getserial(struct stliport *portp, struct serial_struct __user *sp); +static int stli_setserial(struct stliport *portp, struct serial_struct __user *sp); static int stli_getbrdstats(combrd_t __user *bp); -static int stli_getportstats(stliport_t *portp, comstats_t __user *cp); -static int stli_portcmdstats(stliport_t *portp); -static int stli_clrportstats(stliport_t *portp, comstats_t __user *cp); -static int stli_getportstruct(stliport_t __user *arg); -static int stli_getbrdstruct(stlibrd_t __user *arg); -static stlibrd_t *stli_allocbrd(void); - -static void stli_ecpinit(stlibrd_t *brdp); -static void stli_ecpenable(stlibrd_t *brdp); -static void stli_ecpdisable(stlibrd_t *brdp); -static void __iomem *stli_ecpgetmemptr(stlibrd_t *brdp, unsigned long offset, int line); -static void stli_ecpreset(stlibrd_t *brdp); -static void stli_ecpintr(stlibrd_t *brdp); -static void stli_ecpeiinit(stlibrd_t *brdp); -static void stli_ecpeienable(stlibrd_t *brdp); -static void stli_ecpeidisable(stlibrd_t *brdp); -static void __iomem *stli_ecpeigetmemptr(stlibrd_t *brdp, unsigned long offset, int line); -static void stli_ecpeireset(stlibrd_t *brdp); -static void stli_ecpmcenable(stlibrd_t *brdp); -static void stli_ecpmcdisable(stlibrd_t *brdp); -static void __iomem *stli_ecpmcgetmemptr(stlibrd_t *brdp, unsigned long offset, int line); -static void stli_ecpmcreset(stlibrd_t *brdp); -static void stli_ecppciinit(stlibrd_t *brdp); -static void __iomem *stli_ecppcigetmemptr(stlibrd_t *brdp, unsigned long offset, int line); -static void stli_ecppcireset(stlibrd_t *brdp); - -static void stli_onbinit(stlibrd_t *brdp); -static void stli_onbenable(stlibrd_t *brdp); -static void stli_onbdisable(stlibrd_t *brdp); -static void __iomem *stli_onbgetmemptr(stlibrd_t *brdp, unsigned long offset, int line); -static void stli_onbreset(stlibrd_t *brdp); -static void stli_onbeinit(stlibrd_t *brdp); -static void stli_onbeenable(stlibrd_t *brdp); -static void stli_onbedisable(stlibrd_t *brdp); -static void __iomem *stli_onbegetmemptr(stlibrd_t *brdp, unsigned long offset, int line); -static void stli_onbereset(stlibrd_t *brdp); -static void stli_bbyinit(stlibrd_t *brdp); -static void __iomem *stli_bbygetmemptr(stlibrd_t *brdp, unsigned long offset, int line); -static void stli_bbyreset(stlibrd_t *brdp); -static void stli_stalinit(stlibrd_t *brdp); -static void __iomem *stli_stalgetmemptr(stlibrd_t *brdp, unsigned long offset, int line); -static void stli_stalreset(stlibrd_t *brdp); - -static stliport_t *stli_getport(int brdnr, int panelnr, int portnr); - -static int stli_initecp(stlibrd_t *brdp); -static int stli_initonb(stlibrd_t *brdp); -static int stli_eisamemprobe(stlibrd_t *brdp); -static int stli_initports(stlibrd_t *brdp); - -#ifdef CONFIG_PCI -static int stli_initpcibrd(int brdtype, struct pci_dev *devp); +static int stli_getportstats(struct stliport *portp, comstats_t __user *cp); +static int stli_portcmdstats(struct stliport *portp); +static int stli_clrportstats(struct stliport *portp, comstats_t __user *cp); +static int stli_getportstruct(struct stliport __user *arg); +static int stli_getbrdstruct(struct stlibrd __user *arg); +static struct stlibrd *stli_allocbrd(void); + +static void stli_ecpinit(struct stlibrd *brdp); +static void stli_ecpenable(struct stlibrd *brdp); +static void stli_ecpdisable(struct stlibrd *brdp); +static void __iomem *stli_ecpgetmemptr(struct stlibrd *brdp, unsigned long offset, int line); +static void stli_ecpreset(struct stlibrd *brdp); +static void stli_ecpintr(struct stlibrd *brdp); +static void stli_ecpeiinit(struct stlibrd *brdp); +static void stli_ecpeienable(struct stlibrd *brdp); +static void stli_ecpeidisable(struct stlibrd *brdp); +static void __iomem *stli_ecpeigetmemptr(struct stlibrd *brdp, unsigned long offset, int line); +static void stli_ecpeireset(struct stlibrd *brdp); +static void stli_ecpmcenable(struct stlibrd *brdp); +static void stli_ecpmcdisable(struct stlibrd *brdp); +static void __iomem *stli_ecpmcgetmemptr(struct stlibrd *brdp, unsigned long offset, int line); +static void stli_ecpmcreset(struct stlibrd *brdp); +static void stli_ecppciinit(struct stlibrd *brdp); +static void __iomem *stli_ecppcigetmemptr(struct stlibrd *brdp, unsigned long offset, int line); +static void stli_ecppcireset(struct stlibrd *brdp); + +static void stli_onbinit(struct stlibrd *brdp); +static void stli_onbenable(struct stlibrd *brdp); +static void stli_onbdisable(struct stlibrd *brdp); +static void __iomem *stli_onbgetmemptr(struct stlibrd *brdp, unsigned long offset, int line); +static void stli_onbreset(struct stlibrd *brdp); +static void stli_onbeinit(struct stlibrd *brdp); +static void stli_onbeenable(struct stlibrd *brdp); +static void stli_onbedisable(struct stlibrd *brdp); +static void __iomem *stli_onbegetmemptr(struct stlibrd *brdp, unsigned long offset, int line); +static void stli_onbereset(struct stlibrd *brdp); +static void stli_bbyinit(struct stlibrd *brdp); +static void __iomem *stli_bbygetmemptr(struct stlibrd *brdp, unsigned long offset, int line); +static void stli_bbyreset(struct stlibrd *brdp); +static void stli_stalinit(struct stlibrd *brdp); +static void __iomem *stli_stalgetmemptr(struct stlibrd *brdp, unsigned long offset, int line); +static void stli_stalreset(struct stlibrd *brdp); + +static struct stliport *stli_getport(unsigned int brdnr, unsigned int panelnr, unsigned int portnr); + +static int stli_initecp(struct stlibrd *brdp); +static int stli_initonb(struct stlibrd *brdp); +#if STLI_EISAPROBE != 0 +static int stli_eisamemprobe(struct stlibrd *brdp); #endif +static int stli_initports(struct stlibrd *brdp); /*****************************************************************************/ @@ -766,136 +728,19 @@ static int stli_timeron; static struct class *istallion_class; -/* - * Loadable module initialization stuff. - */ - -static int __init istallion_module_init(void) -{ - stli_init(); - return 0; -} - -/*****************************************************************************/ - -static void __exit istallion_module_exit(void) -{ - stlibrd_t *brdp; - stliport_t *portp; - int i, j; - - printk(KERN_INFO "Unloading %s: version %s\n", stli_drvtitle, - stli_drvversion); - - /* - * Free up all allocated resources used by the ports. This includes - * memory and interrupts. - */ - if (stli_timeron) { - stli_timeron = 0; - del_timer_sync(&stli_timerlist); - } - - i = tty_unregister_driver(stli_serial); - if (i) { - printk("STALLION: failed to un-register tty driver, " - "errno=%d\n", -i); - return; - } - put_tty_driver(stli_serial); - for (i = 0; i < 4; i++) - class_device_destroy(istallion_class, MKDEV(STL_SIOMEMMAJOR, i)); - class_destroy(istallion_class); - if ((i = unregister_chrdev(STL_SIOMEMMAJOR, "staliomem"))) - printk("STALLION: failed to un-register serial memory device, " - "errno=%d\n", -i); - - kfree(stli_txcookbuf); - - for (i = 0; (i < stli_nrbrds); i++) { - if ((brdp = stli_brds[i]) == NULL) - continue; - for (j = 0; (j < STL_MAXPORTS); j++) { - portp = brdp->ports[j]; - if (portp != NULL) { - if (portp->tty != NULL) - tty_hangup(portp->tty); - kfree(portp); - } - } - - iounmap(brdp->membase); - if (brdp->iosize > 0) - release_region(brdp->iobase, brdp->iosize); - kfree(brdp); - stli_brds[i] = NULL; - } -} - -module_init(istallion_module_init); -module_exit(istallion_module_exit); - -/*****************************************************************************/ - -/* - * Check for any arguments passed in on the module load command line. - */ - -static void stli_argbrds(void) -{ - stlconf_t conf; - stlibrd_t *brdp; - int i; - - for (i = stli_nrbrds; i < ARRAY_SIZE(stli_brdsp); i++) { - memset(&conf, 0, sizeof(conf)); - if (stli_parsebrd(&conf, stli_brdsp[i]) == 0) - continue; - if ((brdp = stli_allocbrd()) == NULL) - continue; - stli_nrbrds = i + 1; - brdp->brdnr = i; - brdp->brdtype = conf.brdtype; - brdp->iobase = conf.ioaddr1; - brdp->memaddr = conf.memaddr; - stli_brdinit(brdp); - } -} - -/*****************************************************************************/ - -/* - * Convert an ascii string number into an unsigned long. - */ - -static unsigned long stli_atol(char *str) +static void stli_cleanup_ports(struct stlibrd *brdp) { - unsigned long val; - int base, c; - char *sp; - - val = 0; - sp = str; - if ((*sp == '0') && (*(sp+1) == 'x')) { - base = 16; - sp += 2; - } else if (*sp == '0') { - base = 8; - sp++; - } else { - base = 10; - } - - for (; (*sp != 0); sp++) { - c = (*sp > '9') ? (TOLOWER(*sp) - 'a' + 10) : (*sp - '0'); - if ((c < 0) || (c >= base)) { - printk("STALLION: invalid argument %s\n", str); - val = 0; - break; + struct stliport *portp; + unsigned int j; + + for (j = 0; j < STL_MAXPORTS; j++) { + portp = brdp->ports[j]; + if (portp != NULL) { + if (portp->tty != NULL) + tty_hangup(portp->tty); + kfree(portp); } - val = (val * base) + c; } - return(val); } /*****************************************************************************/ @@ -904,16 +749,16 @@ static unsigned long stli_atol(char *str) * Parse the supplied argument string, into the board conf struct. */ -static int stli_parsebrd(stlconf_t *confp, char **argp) +static int stli_parsebrd(struct stlconf *confp, char **argp) { + unsigned int i; char *sp; - int i; if (argp[0] == NULL || *argp[0] == 0) return 0; for (sp = argp[0], i = 0; ((*sp != 0) && (i < 25)); sp++, i++) - *sp = TOLOWER(*sp); + *sp = tolower(*sp); for (i = 0; i < ARRAY_SIZE(stli_brdstr); i++) { if (strcmp(stli_brdstr[i].name, argp[0]) == 0) @@ -926,9 +771,9 @@ static int stli_parsebrd(stlconf_t *confp, char **argp) confp->brdtype = stli_brdstr[i].type; if (argp[1] != NULL && *argp[1] != 0) - confp->ioaddr1 = stli_atol(argp[1]); + confp->ioaddr1 = simple_strtoul(argp[1], NULL, 0); if (argp[2] != NULL && *argp[2] != 0) - confp->memaddr = stli_atol(argp[2]); + confp->memaddr = simple_strtoul(argp[2], NULL, 0); return(1); } @@ -936,10 +781,10 @@ static int stli_parsebrd(stlconf_t *confp, char **argp) static int stli_open(struct tty_struct *tty, struct file *filp) { - stlibrd_t *brdp; - stliport_t *portp; - unsigned int minordev; - int brdnr, portnr, rc; + struct stlibrd *brdp; + struct stliport *portp; + unsigned int minordev, brdnr, portnr; + int rc; minordev = tty->index; brdnr = MINOR2BRD(minordev); @@ -951,7 +796,7 @@ static int stli_open(struct tty_struct *tty, struct file *filp) if ((brdp->state & BST_STARTED) == 0) return -ENODEV; portnr = MINOR2PORT(minordev); - if ((portnr < 0) || (portnr > brdp->nrports)) + if (portnr > brdp->nrports) return -ENODEV; portp = brdp->ports[portnr]; @@ -1031,8 +876,8 @@ static int stli_open(struct tty_struct *tty, struct file *filp) static void stli_close(struct tty_struct *tty, struct file *filp) { - stlibrd_t *brdp; - stliport_t *portp; + struct stlibrd *brdp; + struct stliport *portp; unsigned long flags; portp = tty->driver_data; @@ -1109,7 +954,7 @@ static void stli_close(struct tty_struct *tty, struct file *filp) * this still all happens pretty quickly. */ -static int stli_initopen(stlibrd_t *brdp, stliport_t *portp) +static int stli_initopen(struct stlibrd *brdp, struct stliport *portp) { struct tty_struct *tty; asynotify_t nt; @@ -1157,7 +1002,7 @@ static int stli_initopen(stlibrd_t *brdp, stliport_t *portp) * to overlap. */ -static int stli_rawopen(stlibrd_t *brdp, stliport_t *portp, unsigned long arg, int wait) +static int stli_rawopen(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait) { cdkhdr_t __iomem *hdrp; cdkctrl_t __iomem *cp; @@ -1228,7 +1073,7 @@ static int stli_rawopen(stlibrd_t *brdp, stliport_t *portp, unsigned long arg, i * wait is true then must have user context (to sleep). */ -static int stli_rawclose(stlibrd_t *brdp, stliport_t *portp, unsigned long arg, int wait) +static int stli_rawclose(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait) { cdkhdr_t __iomem *hdrp; cdkctrl_t __iomem *cp; @@ -1292,7 +1137,7 @@ static int stli_rawclose(stlibrd_t *brdp, stliport_t *portp, unsigned long arg, * to complete (as opposed to initiating the command then returning). */ -static int stli_cmdwait(stlibrd_t *brdp, stliport_t *portp, unsigned long cmd, void *arg, int size, int copyback) +static int stli_cmdwait(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback) { wait_event_interruptible(portp->raw_wait, !test_bit(ST_CMDING, &portp->state)); @@ -1318,16 +1163,16 @@ static int stli_cmdwait(stlibrd_t *brdp, stliport_t *portp, unsigned long cmd, v * waiting for the command to complete - so must have user context. */ -static int stli_setport(stliport_t *portp) +static int stli_setport(struct stliport *portp) { - stlibrd_t *brdp; + struct stlibrd *brdp; asyport_t aport; if (portp == NULL) return -ENODEV; if (portp->tty == NULL) return -ENODEV; - if (portp->brdnr < 0 && portp->brdnr >= stli_nrbrds) + if (portp->brdnr >= stli_nrbrds) return -ENODEV; brdp = stli_brds[portp->brdnr]; if (brdp == NULL) @@ -1344,7 +1189,7 @@ static int stli_setport(stliport_t *portp) * maybe because if we are clocal then we don't need to wait... */ -static int stli_waitcarrier(stlibrd_t *brdp, stliport_t *portp, struct file *filp) +static int stli_waitcarrier(struct stlibrd *brdp, struct stliport *portp, struct file *filp) { unsigned long flags; int rc, doclocal; @@ -1409,8 +1254,8 @@ static int stli_write(struct tty_struct *tty, const unsigned char *buf, int coun unsigned char __iomem *bits; unsigned char __iomem *shbuf; unsigned char *chbuf; - stliport_t *portp; - stlibrd_t *brdp; + struct stliport *portp; + struct stlibrd *brdp; unsigned int len, stlen, head, tail, size; unsigned long flags; @@ -1419,7 +1264,7 @@ static int stli_write(struct tty_struct *tty, const unsigned char *buf, int coun portp = tty->driver_data; if (portp == NULL) return 0; - if ((portp->brdnr < 0) || (portp->brdnr >= stli_nrbrds)) + if (portp->brdnr >= stli_nrbrds) return 0; brdp = stli_brds[portp->brdnr]; if (brdp == NULL) @@ -1445,12 +1290,12 @@ static int stli_write(struct tty_struct *tty, const unsigned char *buf, int coun stlen = len; } - len = MIN(len, count); + len = min(len, (unsigned int)count); count = 0; shbuf = (char __iomem *) EBRDGETMEMPTR(brdp, portp->txoffset); while (len > 0) { - stlen = MIN(len, stlen); + stlen = min(len, stlen); memcpy_toio(shbuf + head, chbuf, stlen); chbuf += stlen; len -= stlen; @@ -1516,8 +1361,8 @@ static void stli_flushchars(struct tty_struct *tty) unsigned char __iomem *bits; cdkasy_t __iomem *ap; struct tty_struct *cooktty; - stliport_t *portp; - stlibrd_t *brdp; + struct stliport *portp; + struct stlibrd *brdp; unsigned int len, stlen, head, tail, size, count, cooksize; unsigned char *buf; unsigned char __iomem *shbuf; @@ -1541,7 +1386,7 @@ static void stli_flushchars(struct tty_struct *tty) portp = tty->driver_data; if (portp == NULL) return; - if ((portp->brdnr < 0) || (portp->brdnr >= stli_nrbrds)) + if (portp->brdnr >= stli_nrbrds) return; brdp = stli_brds[portp->brdnr]; if (brdp == NULL) @@ -1564,13 +1409,13 @@ static void stli_flushchars(struct tty_struct *tty) stlen = len; } - len = MIN(len, cooksize); + len = min(len, cooksize); count = 0; shbuf = EBRDGETMEMPTR(brdp, portp->txoffset); buf = stli_txcookbuf; while (len > 0) { - stlen = MIN(len, stlen); + stlen = min(len, stlen); memcpy_toio(shbuf + head, buf, stlen); buf += stlen; len -= stlen; @@ -1604,8 +1449,8 @@ static void stli_flushchars(struct tty_struct *tty) static int stli_writeroom(struct tty_struct *tty) { cdkasyrq_t __iomem *rp; - stliport_t *portp; - stlibrd_t *brdp; + struct stliport *portp; + struct stlibrd *brdp; unsigned int head, tail, len; unsigned long flags; @@ -1619,7 +1464,7 @@ static int stli_writeroom(struct tty_struct *tty) portp = tty->driver_data; if (portp == NULL) return 0; - if ((portp->brdnr < 0) || (portp->brdnr >= stli_nrbrds)) + if (portp->brdnr >= stli_nrbrds) return 0; brdp = stli_brds[portp->brdnr]; if (brdp == NULL) @@ -1657,8 +1502,8 @@ static int stli_writeroom(struct tty_struct *tty) static int stli_charsinbuffer(struct tty_struct *tty) { cdkasyrq_t __iomem *rp; - stliport_t *portp; - stlibrd_t *brdp; + struct stliport *portp; + struct stlibrd *brdp; unsigned int head, tail, len; unsigned long flags; @@ -1667,7 +1512,7 @@ static int stli_charsinbuffer(struct tty_struct *tty) portp = tty->driver_data; if (portp == NULL) return 0; - if ((portp->brdnr < 0) || (portp->brdnr >= stli_nrbrds)) + if (portp->brdnr >= stli_nrbrds) return 0; brdp = stli_brds[portp->brdnr]; if (brdp == NULL) @@ -1695,10 +1540,10 @@ static int stli_charsinbuffer(struct tty_struct *tty) * Generate the serial struct info. */ -static int stli_getserial(stliport_t *portp, struct serial_struct __user *sp) +static int stli_getserial(struct stliport *portp, struct serial_struct __user *sp) { struct serial_struct sio; - stlibrd_t *brdp; + struct stlibrd *brdp; memset(&sio, 0, sizeof(struct serial_struct)); sio.type = PORT_UNKNOWN; @@ -1728,7 +1573,7 @@ static int stli_getserial(stliport_t *portp, struct serial_struct __user *sp) * just quietly ignore any requests to change irq, etc. */ -static int stli_setserial(stliport_t *portp, struct serial_struct __user *sp) +static int stli_setserial(struct stliport *portp, struct serial_struct __user *sp) { struct serial_struct sio; int rc; @@ -1759,13 +1604,13 @@ static int stli_setserial(stliport_t *portp, struct serial_struct __user *sp) static int stli_tiocmget(struct tty_struct *tty, struct file *file) { - stliport_t *portp = tty->driver_data; - stlibrd_t *brdp; + struct stliport *portp = tty->driver_data; + struct stlibrd *brdp; int rc; if (portp == NULL) return -ENODEV; - if (portp->brdnr < 0 || portp->brdnr >= stli_nrbrds) + if (portp->brdnr >= stli_nrbrds) return 0; brdp = stli_brds[portp->brdnr]; if (brdp == NULL) @@ -1783,13 +1628,13 @@ static int stli_tiocmget(struct tty_struct *tty, struct file *file) static int stli_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear) { - stliport_t *portp = tty->driver_data; - stlibrd_t *brdp; + struct stliport *portp = tty->driver_data; + struct stlibrd *brdp; int rts = -1, dtr = -1; if (portp == NULL) return -ENODEV; - if (portp->brdnr < 0 || portp->brdnr >= stli_nrbrds) + if (portp->brdnr >= stli_nrbrds) return 0; brdp = stli_brds[portp->brdnr]; if (brdp == NULL) @@ -1814,8 +1659,8 @@ static int stli_tiocmset(struct tty_struct *tty, struct file *file, static int stli_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg) { - stliport_t *portp; - stlibrd_t *brdp; + struct stliport *portp; + struct stlibrd *brdp; unsigned int ival; int rc; void __user *argp = (void __user *)arg; @@ -1823,7 +1668,7 @@ static int stli_ioctl(struct tty_struct *tty, struct file *file, unsigned int cm portp = tty->driver_data; if (portp == NULL) return -ENODEV; - if (portp->brdnr < 0 || portp->brdnr >= stli_nrbrds) + if (portp->brdnr >= stli_nrbrds) return 0; brdp = stli_brds[portp->brdnr]; if (brdp == NULL) @@ -1889,11 +1734,11 @@ static int stli_ioctl(struct tty_struct *tty, struct file *file, unsigned int cm * Looks like it is true for the current ttys implementation..!! */ -static void stli_settermios(struct tty_struct *tty, struct termios *old) +static void stli_settermios(struct tty_struct *tty, struct ktermios *old) { - stliport_t *portp; - stlibrd_t *brdp; - struct termios *tiosp; + struct stliport *portp; + struct stlibrd *brdp; + struct ktermios *tiosp; asyport_t aport; if (tty == NULL) @@ -1901,7 +1746,7 @@ static void stli_settermios(struct tty_struct *tty, struct termios *old) portp = tty->driver_data; if (portp == NULL) return; - if (portp->brdnr < 0 || portp->brdnr >= stli_nrbrds) + if (portp->brdnr >= stli_nrbrds) return; brdp = stli_brds[portp->brdnr]; if (brdp == NULL) @@ -1937,7 +1782,7 @@ static void stli_settermios(struct tty_struct *tty, struct termios *old) static void stli_throttle(struct tty_struct *tty) { - stliport_t *portp = tty->driver_data; + struct stliport *portp = tty->driver_data; if (portp == NULL) return; set_bit(ST_RXSTOP, &portp->state); @@ -1953,7 +1798,7 @@ static void stli_throttle(struct tty_struct *tty) static void stli_unthrottle(struct tty_struct *tty) { - stliport_t *portp = tty->driver_data; + struct stliport *portp = tty->driver_data; if (portp == NULL) return; clear_bit(ST_RXSTOP, &portp->state); @@ -1990,9 +1835,9 @@ static void stli_start(struct tty_struct *tty) * aren't that time critical). */ -static void stli_dohangup(void *arg) +static void stli_dohangup(struct work_struct *ugly_api) { - stliport_t *portp = (stliport_t *) arg; + struct stliport *portp = container_of(ugly_api, struct stliport, tqhangup); if (portp->tty != NULL) { tty_hangup(portp->tty); } @@ -2009,14 +1854,14 @@ static void stli_dohangup(void *arg) static void stli_hangup(struct tty_struct *tty) { - stliport_t *portp; - stlibrd_t *brdp; + struct stliport *portp; + struct stlibrd *brdp; unsigned long flags; portp = tty->driver_data; if (portp == NULL) return; - if (portp->brdnr < 0 || portp->brdnr >= stli_nrbrds) + if (portp->brdnr >= stli_nrbrds) return; brdp = stli_brds[portp->brdnr]; if (brdp == NULL) @@ -2062,14 +1907,14 @@ static void stli_hangup(struct tty_struct *tty) static void stli_flushbuffer(struct tty_struct *tty) { - stliport_t *portp; - stlibrd_t *brdp; + struct stliport *portp; + struct stlibrd *brdp; unsigned long ftype, flags; portp = tty->driver_data; if (portp == NULL) return; - if (portp->brdnr < 0 || portp->brdnr >= stli_nrbrds) + if (portp->brdnr >= stli_nrbrds) return; brdp = stli_brds[portp->brdnr]; if (brdp == NULL) @@ -2099,14 +1944,14 @@ static void stli_flushbuffer(struct tty_struct *tty) static void stli_breakctl(struct tty_struct *tty, int state) { - stlibrd_t *brdp; - stliport_t *portp; + struct stlibrd *brdp; + struct stliport *portp; long arg; portp = tty->driver_data; if (portp == NULL) return; - if (portp->brdnr < 0 || portp->brdnr >= stli_nrbrds) + if (portp->brdnr >= stli_nrbrds) return; brdp = stli_brds[portp->brdnr]; if (brdp == NULL) @@ -2120,7 +1965,7 @@ static void stli_breakctl(struct tty_struct *tty, int state) static void stli_waituntilsent(struct tty_struct *tty, int timeout) { - stliport_t *portp; + struct stliport *portp; unsigned long tend; if (tty == NULL) @@ -2146,14 +1991,14 @@ static void stli_waituntilsent(struct tty_struct *tty, int timeout) static void stli_sendxchar(struct tty_struct *tty, char ch) { - stlibrd_t *brdp; - stliport_t *portp; + struct stlibrd *brdp; + struct stliport *portp; asyctrl_t actrl; portp = tty->driver_data; if (portp == NULL) return; - if (portp->brdnr < 0 || portp->brdnr >= stli_nrbrds) + if (portp->brdnr >= stli_nrbrds) return; brdp = stli_brds[portp->brdnr]; if (brdp == NULL) @@ -2181,7 +2026,7 @@ static void stli_sendxchar(struct tty_struct *tty, char ch) * short then padded with spaces). */ -static int stli_portinfo(stlibrd_t *brdp, stliport_t *portp, int portnr, char *pos) +static int stli_portinfo(struct stlibrd *brdp, struct stliport *portp, int portnr, char *pos) { char *sp, *uart; int rc, cnt; @@ -2244,9 +2089,9 @@ static int stli_portinfo(stlibrd_t *brdp, stliport_t *portp, int portnr, char *p static int stli_readproc(char *page, char **start, off_t off, int count, int *eof, void *data) { - stlibrd_t *brdp; - stliport_t *portp; - int brdnr, portnr, totalport; + struct stlibrd *brdp; + struct stliport *portp; + unsigned int brdnr, portnr, totalport; int curoff, maxoff; char *pos; @@ -2316,7 +2161,7 @@ static int stli_readproc(char *page, char **start, off_t off, int count, int *eo * entry point) */ -static void __stli_sendcmd(stlibrd_t *brdp, stliport_t *portp, unsigned long cmd, void *arg, int size, int copyback) +static void __stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback) { cdkhdr_t __iomem *hdrp; cdkctrl_t __iomem *cp; @@ -2352,7 +2197,7 @@ static void __stli_sendcmd(stlibrd_t *brdp, stliport_t *portp, unsigned long cmd spin_unlock_irqrestore(&brd_lock, flags); } -static void stli_sendcmd(stlibrd_t *brdp, stliport_t *portp, unsigned long cmd, void *arg, int size, int copyback) +static void stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback) { unsigned long flags; @@ -2371,7 +2216,7 @@ static void stli_sendcmd(stlibrd_t *brdp, stliport_t *portp, unsigned long cmd, * more chars to unload. */ -static void stli_read(stlibrd_t *brdp, stliport_t *portp) +static void stli_read(struct stlibrd *brdp, struct stliport *portp) { cdkasyrq_t __iomem *rp; char __iomem *shbuf; @@ -2406,7 +2251,7 @@ static void stli_read(stlibrd_t *brdp, stliport_t *portp) while (len > 0) { unsigned char *cptr; - stlen = MIN(len, stlen); + stlen = min(len, stlen); tty_prepare_flip_string(tty, &cptr, stlen); memcpy_fromio(cptr, shbuf + tail, stlen); len -= stlen; @@ -2433,7 +2278,7 @@ static void stli_read(stlibrd_t *brdp, stliport_t *portp) * difficult to deal with them here. */ -static void stli_dodelaycmd(stliport_t *portp, cdkctrl_t __iomem *cp) +static void stli_dodelaycmd(struct stliport *portp, cdkctrl_t __iomem *cp) { int cmd; @@ -2481,7 +2326,7 @@ static void stli_dodelaycmd(stliport_t *portp, cdkctrl_t __iomem *cp) * then port is still busy, otherwise no longer busy. */ -static int stli_hostcmd(stlibrd_t *brdp, stliport_t *portp) +static int stli_hostcmd(struct stlibrd *brdp, struct stliport *portp) { cdkasy_t __iomem *ap; cdkctrl_t __iomem *cp; @@ -2628,9 +2473,9 @@ static int stli_hostcmd(stlibrd_t *brdp, stliport_t *portp) * at the cdk header structure. */ -static void stli_brdpoll(stlibrd_t *brdp, cdkhdr_t __iomem *hdrp) +static void stli_brdpoll(struct stlibrd *brdp, cdkhdr_t __iomem *hdrp) { - stliport_t *portp; + struct stliport *portp; unsigned char hostbits[(STL_MAXCHANS / 8) + 1]; unsigned char slavebits[(STL_MAXCHANS / 8) + 1]; unsigned char __iomem *slavep; @@ -2697,11 +2542,10 @@ static void stli_brdpoll(stlibrd_t *brdp, cdkhdr_t __iomem *hdrp) static void stli_poll(unsigned long arg) { cdkhdr_t __iomem *hdrp; - stlibrd_t *brdp; - int brdnr; + struct stlibrd *brdp; + unsigned int brdnr; - stli_timerlist.expires = STLI_TIMEOUT; - add_timer(&stli_timerlist); + mod_timer(&stli_timerlist, STLI_TIMEOUT); /* * Check each board and do any servicing required. @@ -2730,7 +2574,7 @@ static void stli_poll(unsigned long arg) * the slave. */ -static void stli_mkasyport(stliport_t *portp, asyport_t *pp, struct termios *tiosp) +static void stli_mkasyport(struct stliport *portp, asyport_t *pp, struct ktermios *tiosp) { memset(pp, 0, sizeof(asyport_t)); @@ -2879,13 +2723,13 @@ static long stli_mktiocm(unsigned long sigvalue) * we need to do here is set up the appropriate per port data structures. */ -static int stli_initports(stlibrd_t *brdp) +static int stli_initports(struct stlibrd *brdp) { - stliport_t *portp; - int i, panelnr, panelport; + struct stliport *portp; + unsigned int i, panelnr, panelport; for (i = 0, panelnr = 0, panelport = 0; (i < brdp->nrports); i++) { - portp = kzalloc(sizeof(stliport_t), GFP_KERNEL); + portp = kzalloc(sizeof(struct stliport), GFP_KERNEL); if (!portp) { printk("STALLION: failed to allocate port structure\n"); continue; @@ -2898,7 +2742,7 @@ static int stli_initports(stlibrd_t *brdp) portp->baud_base = STL_BAUDBASE; portp->close_delay = STL_CLOSEDELAY; portp->closing_wait = 30 * HZ; - INIT_WORK(&portp->tqhangup, stli_dohangup, portp); + INIT_WORK(&portp->tqhangup, stli_dohangup); init_waitqueue_head(&portp->open_wait); init_waitqueue_head(&portp->close_wait); init_waitqueue_head(&portp->raw_wait); @@ -2919,7 +2763,7 @@ static int stli_initports(stlibrd_t *brdp) * All the following routines are board specific hardware operations. */ -static void stli_ecpinit(stlibrd_t *brdp) +static void stli_ecpinit(struct stlibrd *brdp) { unsigned long memconf; @@ -2934,21 +2778,21 @@ static void stli_ecpinit(stlibrd_t *brdp) /*****************************************************************************/ -static void stli_ecpenable(stlibrd_t *brdp) +static void stli_ecpenable(struct stlibrd *brdp) { outb(ECP_ATENABLE, (brdp->iobase + ECP_ATCONFR)); } /*****************************************************************************/ -static void stli_ecpdisable(stlibrd_t *brdp) +static void stli_ecpdisable(struct stlibrd *brdp) { outb(ECP_ATDISABLE, (brdp->iobase + ECP_ATCONFR)); } /*****************************************************************************/ -static void __iomem *stli_ecpgetmemptr(stlibrd_t *brdp, unsigned long offset, int line) +static void __iomem *stli_ecpgetmemptr(struct stlibrd *brdp, unsigned long offset, int line) { void __iomem *ptr; unsigned char val; @@ -2969,7 +2813,7 @@ static void __iomem *stli_ecpgetmemptr(stlibrd_t *brdp, unsigned long offset, in /*****************************************************************************/ -static void stli_ecpreset(stlibrd_t *brdp) +static void stli_ecpreset(struct stlibrd *brdp) { outb(ECP_ATSTOP, (brdp->iobase + ECP_ATCONFR)); udelay(10); @@ -2979,7 +2823,7 @@ static void stli_ecpreset(stlibrd_t *brdp) /*****************************************************************************/ -static void stli_ecpintr(stlibrd_t *brdp) +static void stli_ecpintr(struct stlibrd *brdp) { outb(0x1, brdp->iobase); } @@ -2990,7 +2834,7 @@ static void stli_ecpintr(stlibrd_t *brdp) * The following set of functions act on ECP EISA boards. */ -static void stli_ecpeiinit(stlibrd_t *brdp) +static void stli_ecpeiinit(struct stlibrd *brdp) { unsigned long memconf; @@ -3008,21 +2852,21 @@ static void stli_ecpeiinit(stlibrd_t *brdp) /*****************************************************************************/ -static void stli_ecpeienable(stlibrd_t *brdp) +static void stli_ecpeienable(struct stlibrd *brdp) { outb(ECP_EIENABLE, (brdp->iobase + ECP_EICONFR)); } /*****************************************************************************/ -static void stli_ecpeidisable(stlibrd_t *brdp) +static void stli_ecpeidisable(struct stlibrd *brdp) { outb(ECP_EIDISABLE, (brdp->iobase + ECP_EICONFR)); } /*****************************************************************************/ -static void __iomem *stli_ecpeigetmemptr(stlibrd_t *brdp, unsigned long offset, int line) +static void __iomem *stli_ecpeigetmemptr(struct stlibrd *brdp, unsigned long offset, int line) { void __iomem *ptr; unsigned char val; @@ -3046,7 +2890,7 @@ static void __iomem *stli_ecpeigetmemptr(stlibrd_t *brdp, unsigned long offset, /*****************************************************************************/ -static void stli_ecpeireset(stlibrd_t *brdp) +static void stli_ecpeireset(struct stlibrd *brdp) { outb(ECP_EISTOP, (brdp->iobase + ECP_EICONFR)); udelay(10); @@ -3060,21 +2904,21 @@ static void stli_ecpeireset(stlibrd_t *brdp) * The following set of functions act on ECP MCA boards. */ -static void stli_ecpmcenable(stlibrd_t *brdp) +static void stli_ecpmcenable(struct stlibrd *brdp) { outb(ECP_MCENABLE, (brdp->iobase + ECP_MCCONFR)); } /*****************************************************************************/ -static void stli_ecpmcdisable(stlibrd_t *brdp) +static void stli_ecpmcdisable(struct stlibrd *brdp) { outb(ECP_MCDISABLE, (brdp->iobase + ECP_MCCONFR)); } /*****************************************************************************/ -static void __iomem *stli_ecpmcgetmemptr(stlibrd_t *brdp, unsigned long offset, int line) +static void __iomem *stli_ecpmcgetmemptr(struct stlibrd *brdp, unsigned long offset, int line) { void __iomem *ptr; unsigned char val; @@ -3095,7 +2939,7 @@ static void __iomem *stli_ecpmcgetmemptr(stlibrd_t *brdp, unsigned long offset, /*****************************************************************************/ -static void stli_ecpmcreset(stlibrd_t *brdp) +static void stli_ecpmcreset(struct stlibrd *brdp) { outb(ECP_MCSTOP, (brdp->iobase + ECP_MCCONFR)); udelay(10); @@ -3109,7 +2953,7 @@ static void stli_ecpmcreset(stlibrd_t *brdp) * The following set of functions act on ECP PCI boards. */ -static void stli_ecppciinit(stlibrd_t *brdp) +static void stli_ecppciinit(struct stlibrd *brdp) { outb(ECP_PCISTOP, (brdp->iobase + ECP_PCICONFR)); udelay(10); @@ -3119,7 +2963,7 @@ static void stli_ecppciinit(stlibrd_t *brdp) /*****************************************************************************/ -static void __iomem *stli_ecppcigetmemptr(stlibrd_t *brdp, unsigned long offset, int line) +static void __iomem *stli_ecppcigetmemptr(struct stlibrd *brdp, unsigned long offset, int line) { void __iomem *ptr; unsigned char val; @@ -3140,7 +2984,7 @@ static void __iomem *stli_ecppcigetmemptr(stlibrd_t *brdp, unsigned long offset, /*****************************************************************************/ -static void stli_ecppcireset(stlibrd_t *brdp) +static void stli_ecppcireset(struct stlibrd *brdp) { outb(ECP_PCISTOP, (brdp->iobase + ECP_PCICONFR)); udelay(10); @@ -3154,7 +2998,7 @@ static void stli_ecppcireset(stlibrd_t *brdp) * The following routines act on ONboards. */ -static void stli_onbinit(stlibrd_t *brdp) +static void stli_onbinit(struct stlibrd *brdp) { unsigned long memconf; @@ -3171,21 +3015,21 @@ static void stli_onbinit(stlibrd_t *brdp) /*****************************************************************************/ -static void stli_onbenable(stlibrd_t *brdp) +static void stli_onbenable(struct stlibrd *brdp) { outb((brdp->enabval | ONB_ATENABLE), (brdp->iobase + ONB_ATCONFR)); } /*****************************************************************************/ -static void stli_onbdisable(stlibrd_t *brdp) +static void stli_onbdisable(struct stlibrd *brdp) { outb((brdp->enabval | ONB_ATDISABLE), (brdp->iobase + ONB_ATCONFR)); } /*****************************************************************************/ -static void __iomem *stli_onbgetmemptr(stlibrd_t *brdp, unsigned long offset, int line) +static void __iomem *stli_onbgetmemptr(struct stlibrd *brdp, unsigned long offset, int line) { void __iomem *ptr; @@ -3202,7 +3046,7 @@ static void __iomem *stli_onbgetmemptr(stlibrd_t *brdp, unsigned long offset, in /*****************************************************************************/ -static void stli_onbreset(stlibrd_t *brdp) +static void stli_onbreset(struct stlibrd *brdp) { outb(ONB_ATSTOP, (brdp->iobase + ONB_ATCONFR)); udelay(10); @@ -3216,7 +3060,7 @@ static void stli_onbreset(stlibrd_t *brdp) * The following routines act on ONboard EISA. */ -static void stli_onbeinit(stlibrd_t *brdp) +static void stli_onbeinit(struct stlibrd *brdp) { unsigned long memconf; @@ -3236,21 +3080,21 @@ static void stli_onbeinit(stlibrd_t *brdp) /*****************************************************************************/ -static void stli_onbeenable(stlibrd_t *brdp) +static void stli_onbeenable(struct stlibrd *brdp) { outb(ONB_EIENABLE, (brdp->iobase + ONB_EICONFR)); } /*****************************************************************************/ -static void stli_onbedisable(stlibrd_t *brdp) +static void stli_onbedisable(struct stlibrd *brdp) { outb(ONB_EIDISABLE, (brdp->iobase + ONB_EICONFR)); } /*****************************************************************************/ -static void __iomem *stli_onbegetmemptr(stlibrd_t *brdp, unsigned long offset, int line) +static void __iomem *stli_onbegetmemptr(struct stlibrd *brdp, unsigned long offset, int line) { void __iomem *ptr; unsigned char val; @@ -3274,7 +3118,7 @@ static void __iomem *stli_onbegetmemptr(stlibrd_t *brdp, unsigned long offset, i /*****************************************************************************/ -static void stli_onbereset(stlibrd_t *brdp) +static void stli_onbereset(struct stlibrd *brdp) { outb(ONB_EISTOP, (brdp->iobase + ONB_EICONFR)); udelay(10); @@ -3288,7 +3132,7 @@ static void stli_onbereset(stlibrd_t *brdp) * The following routines act on Brumby boards. */ -static void stli_bbyinit(stlibrd_t *brdp) +static void stli_bbyinit(struct stlibrd *brdp) { outb(BBY_ATSTOP, (brdp->iobase + BBY_ATCONFR)); udelay(10); @@ -3300,7 +3144,7 @@ static void stli_bbyinit(stlibrd_t *brdp) /*****************************************************************************/ -static void __iomem *stli_bbygetmemptr(stlibrd_t *brdp, unsigned long offset, int line) +static void __iomem *stli_bbygetmemptr(struct stlibrd *brdp, unsigned long offset, int line) { void __iomem *ptr; unsigned char val; @@ -3315,7 +3159,7 @@ static void __iomem *stli_bbygetmemptr(stlibrd_t *brdp, unsigned long offset, in /*****************************************************************************/ -static void stli_bbyreset(stlibrd_t *brdp) +static void stli_bbyreset(struct stlibrd *brdp) { outb(BBY_ATSTOP, (brdp->iobase + BBY_ATCONFR)); udelay(10); @@ -3329,7 +3173,7 @@ static void stli_bbyreset(stlibrd_t *brdp) * The following routines act on original old Stallion boards. */ -static void stli_stalinit(stlibrd_t *brdp) +static void stli_stalinit(struct stlibrd *brdp) { outb(0x1, brdp->iobase); mdelay(1000); @@ -3337,7 +3181,7 @@ static void stli_stalinit(stlibrd_t *brdp) /*****************************************************************************/ -static void __iomem *stli_stalgetmemptr(stlibrd_t *brdp, unsigned long offset, int line) +static void __iomem *stli_stalgetmemptr(struct stlibrd *brdp, unsigned long offset, int line) { BUG_ON(offset > brdp->memsize); return brdp->membase + (offset % STAL_PAGESIZE); @@ -3345,7 +3189,7 @@ static void __iomem *stli_stalgetmemptr(stlibrd_t *brdp, unsigned long offset, i /*****************************************************************************/ -static void stli_stalreset(stlibrd_t *brdp) +static void stli_stalreset(struct stlibrd *brdp) { u32 __iomem *vecp; @@ -3362,21 +3206,22 @@ static void stli_stalreset(stlibrd_t *brdp) * board types. */ -static int stli_initecp(stlibrd_t *brdp) +static int stli_initecp(struct stlibrd *brdp) { cdkecpsig_t sig; cdkecpsig_t __iomem *sigsp; unsigned int status, nxtid; char *name; - int panelnr, nrports; + int retval, panelnr, nrports; - if (!request_region(brdp->iobase, brdp->iosize, "istallion")) - return -EIO; - - if ((brdp->iobase == 0) || (brdp->memaddr == 0)) - { - release_region(brdp->iobase, brdp->iosize); - return -ENODEV; + if ((brdp->iobase == 0) || (brdp->memaddr == 0)) { + retval = -ENODEV; + goto err; + } + + if (!request_region(brdp->iobase, brdp->iosize, "istallion")) { + retval = -EIO; + goto err; } brdp->iosize = ECP_IOSIZE; @@ -3388,7 +3233,6 @@ static int stli_initecp(stlibrd_t *brdp) */ switch (brdp->brdtype) { case BRD_ECP: - brdp->membase = (void *) brdp->memaddr; brdp->memsize = ECP_MEMSIZE; brdp->pagesize = ECP_ATPAGESIZE; brdp->init = stli_ecpinit; @@ -3402,7 +3246,6 @@ static int stli_initecp(stlibrd_t *brdp) break; case BRD_ECPE: - brdp->membase = (void *) brdp->memaddr; brdp->memsize = ECP_MEMSIZE; brdp->pagesize = ECP_EIPAGESIZE; brdp->init = stli_ecpeiinit; @@ -3416,7 +3259,6 @@ static int stli_initecp(stlibrd_t *brdp) break; case BRD_ECPMC: - brdp->membase = (void *) brdp->memaddr; brdp->memsize = ECP_MEMSIZE; brdp->pagesize = ECP_MCPAGESIZE; brdp->init = NULL; @@ -3430,7 +3272,6 @@ static int stli_initecp(stlibrd_t *brdp) break; case BRD_ECPPCI: - brdp->membase = (void *) brdp->memaddr; brdp->memsize = ECP_PCIMEMSIZE; brdp->pagesize = ECP_PCIPAGESIZE; brdp->init = stli_ecppciinit; @@ -3444,8 +3285,8 @@ static int stli_initecp(stlibrd_t *brdp) break; default: - release_region(brdp->iobase, brdp->iosize); - return -EINVAL; + retval = -EINVAL; + goto err_reg; } /* @@ -3457,10 +3298,9 @@ static int stli_initecp(stlibrd_t *brdp) EBRDINIT(brdp); brdp->membase = ioremap(brdp->memaddr, brdp->memsize); - if (brdp->membase == NULL) - { - release_region(brdp->iobase, brdp->iosize); - return -ENOMEM; + if (brdp->membase == NULL) { + retval = -ENOMEM; + goto err_reg; } /* @@ -3473,10 +3313,9 @@ static int stli_initecp(stlibrd_t *brdp) memcpy_fromio(&sig, sigsp, sizeof(cdkecpsig_t)); EBRDDISABLE(brdp); - if (sig.magic != cpu_to_le32(ECP_MAGIC)) - { - release_region(brdp->iobase, brdp->iosize); - return -ENODEV; + if (sig.magic != cpu_to_le32(ECP_MAGIC)) { + retval = -ENODEV; + goto err_unmap; } /* @@ -3501,6 +3340,13 @@ static int stli_initecp(stlibrd_t *brdp) brdp->state |= BST_FOUND; return 0; +err_unmap: + iounmap(brdp->membase); + brdp->membase = NULL; +err_reg: + release_region(brdp->iobase, brdp->iosize); +err: + return retval; } /*****************************************************************************/ @@ -3510,23 +3356,27 @@ static int stli_initecp(stlibrd_t *brdp) * This handles only these board types. */ -static int stli_initonb(stlibrd_t *brdp) +static int stli_initonb(struct stlibrd *brdp) { cdkonbsig_t sig; cdkonbsig_t __iomem *sigsp; char *name; - int i; + int i, retval; /* * Do a basic sanity check on the IO and memory addresses. */ - if (brdp->iobase == 0 || brdp->memaddr == 0) - return -ENODEV; + if (brdp->iobase == 0 || brdp->memaddr == 0) { + retval = -ENODEV; + goto err; + } brdp->iosize = ONB_IOSIZE; - if (!request_region(brdp->iobase, brdp->iosize, "istallion")) - return -EIO; + if (!request_region(brdp->iobase, brdp->iosize, "istallion")) { + retval = -EIO; + goto err; + } /* * Based on the specific board type setup the common vars to access @@ -3535,10 +3385,7 @@ static int stli_initonb(stlibrd_t *brdp) */ switch (brdp->brdtype) { case BRD_ONBOARD: - case BRD_ONBOARD32: case BRD_ONBOARD2: - case BRD_ONBOARD2_32: - case BRD_ONBOARDRS: brdp->memsize = ONB_MEMSIZE; brdp->pagesize = ONB_ATPAGESIZE; brdp->init = stli_onbinit; @@ -3569,8 +3416,6 @@ static int stli_initonb(stlibrd_t *brdp) break; case BRD_BRUMBY4: - case BRD_BRUMBY8: - case BRD_BRUMBY16: brdp->memsize = BBY_MEMSIZE; brdp->pagesize = BBY_PAGESIZE; brdp->init = stli_bbyinit; @@ -3597,8 +3442,8 @@ static int stli_initonb(stlibrd_t *brdp) break; default: - release_region(brdp->iobase, brdp->iosize); - return -EINVAL; + retval = -EINVAL; + goto err_reg; } /* @@ -3610,10 +3455,9 @@ static int stli_initonb(stlibrd_t *brdp) EBRDINIT(brdp); brdp->membase = ioremap(brdp->memaddr, brdp->memsize); - if (brdp->membase == NULL) - { - release_region(brdp->iobase, brdp->iosize); - return -ENOMEM; + if (brdp->membase == NULL) { + retval = -ENOMEM; + goto err_reg; } /* @@ -3629,10 +3473,9 @@ static int stli_initonb(stlibrd_t *brdp) if (sig.magic0 != cpu_to_le16(ONB_MAGIC0) || sig.magic1 != cpu_to_le16(ONB_MAGIC1) || sig.magic2 != cpu_to_le16(ONB_MAGIC2) || - sig.magic3 != cpu_to_le16(ONB_MAGIC3)) - { - release_region(brdp->iobase, brdp->iosize); - return -ENODEV; + sig.magic3 != cpu_to_le16(ONB_MAGIC3)) { + retval = -ENODEV; + goto err_unmap; } /* @@ -3654,6 +3497,13 @@ static int stli_initonb(stlibrd_t *brdp) brdp->state |= BST_FOUND; return 0; +err_unmap: + iounmap(brdp->membase); + brdp->membase = NULL; +err_reg: + release_region(brdp->iobase, brdp->iosize); +err: + return retval; } /*****************************************************************************/ @@ -3664,14 +3514,15 @@ static int stli_initonb(stlibrd_t *brdp) * read in the memory map, and get the show on the road... */ -static int stli_startbrd(stlibrd_t *brdp) +static int stli_startbrd(struct stlibrd *brdp) { cdkhdr_t __iomem *hdrp; cdkmem_t __iomem *memp; cdkasy_t __iomem *ap; unsigned long flags; - stliport_t *portp; - int portnr, nrdevs, i, rc = 0; + unsigned int portnr, nrdevs, i; + struct stliport *portp; + int rc = 0; u32 memoff; spin_lock_irqsave(&brd_lock, flags); @@ -3758,8 +3609,7 @@ static int stli_startbrd(stlibrd_t *brdp) if (! stli_timeron) { stli_timeron++; - stli_timerlist.expires = STLI_TIMEOUT; - add_timer(&stli_timerlist); + mod_timer(&stli_timerlist, STLI_TIMEOUT); } return rc; @@ -3771,49 +3621,32 @@ static int stli_startbrd(stlibrd_t *brdp) * Probe and initialize the specified board. */ -static int __init stli_brdinit(stlibrd_t *brdp) +static int __devinit stli_brdinit(struct stlibrd *brdp) { - stli_brds[brdp->brdnr] = brdp; + int retval; switch (brdp->brdtype) { case BRD_ECP: case BRD_ECPE: case BRD_ECPMC: case BRD_ECPPCI: - stli_initecp(brdp); + retval = stli_initecp(brdp); break; case BRD_ONBOARD: case BRD_ONBOARDE: case BRD_ONBOARD2: - case BRD_ONBOARD32: - case BRD_ONBOARD2_32: - case BRD_ONBOARDRS: case BRD_BRUMBY4: - case BRD_BRUMBY8: - case BRD_BRUMBY16: case BRD_STALLION: - stli_initonb(brdp); + retval = stli_initonb(brdp); break; - case BRD_EASYIO: - case BRD_ECH: - case BRD_ECHMC: - case BRD_ECHPCI: - printk(KERN_ERR "STALLION: %s board type not supported in " - "this driver\n", stli_brdnames[brdp->brdtype]); - return -ENODEV; default: printk(KERN_ERR "STALLION: board=%d is unknown board " "type=%d\n", brdp->brdnr, brdp->brdtype); - return -ENODEV; + retval = -ENODEV; } - if ((brdp->state & BST_FOUND) == 0) { - printk(KERN_ERR "STALLION: %s board not found, board=%d " - "io=%x mem=%x\n", - stli_brdnames[brdp->brdtype], brdp->brdnr, - brdp->iobase, (int) brdp->memaddr); - return -ENODEV; - } + if (retval) + return retval; stli_initports(brdp); printk(KERN_INFO "STALLION: %s found, board=%d io=%x mem=%x " @@ -3823,6 +3656,7 @@ static int __init stli_brdinit(stlibrd_t *brdp) return 0; } +#if STLI_EISAPROBE != 0 /*****************************************************************************/ /* @@ -3830,7 +3664,7 @@ static int __init stli_brdinit(stlibrd_t *brdp) * might be. This is a bit if hack, but it is the best we can do. */ -static int stli_eisamemprobe(stlibrd_t *brdp) +static int stli_eisamemprobe(struct stlibrd *brdp) { cdkecpsig_t ecpsig, __iomem *ecpsigp; cdkonbsig_t onbsig, __iomem *onbsigp; @@ -3916,10 +3750,11 @@ static int stli_eisamemprobe(stlibrd_t *brdp) } return 0; } +#endif static int stli_getbrdnr(void) { - int i; + unsigned int i; for (i = 0; i < STL_MAXBRDS; i++) { if (!stli_brds[i]) { @@ -3931,6 +3766,7 @@ static int stli_getbrdnr(void) return -1; } +#if STLI_EISAPROBE != 0 /*****************************************************************************/ /* @@ -3945,9 +3781,9 @@ static int stli_getbrdnr(void) static int stli_findeisabrds(void) { - stlibrd_t *brdp; - unsigned int iobase, eid; - int i; + struct stlibrd *brdp; + unsigned int iobase, eid, i; + int brdnr, found = 0; /* * Firstly check if this is an EISA system. If this is not an EISA system then @@ -3985,9 +3821,11 @@ static int stli_findeisabrds(void) * Allocate a board structure and initialize it. */ if ((brdp = stli_allocbrd()) == NULL) - return -ENOMEM; - if ((brdp->brdnr = stli_getbrdnr()) < 0) - return -ENOMEM; + return found ? : -ENOMEM; + brdnr = stli_getbrdnr(); + if (brdnr < 0) + return found ? : -ENOMEM; + brdp->brdnr = (unsigned int)brdnr; eid = inb(iobase + 0xc82); if (eid == ECP_EISAID) brdp->brdtype = BRD_ECPE; @@ -3999,11 +3837,24 @@ static int stli_findeisabrds(void) outb(0x1, (iobase + 0xc84)); if (stli_eisamemprobe(brdp)) outb(0, (iobase + 0xc84)); - stli_brdinit(brdp); + if (stli_brdinit(brdp) < 0) { + kfree(brdp); + continue; + } + + stli_brds[brdp->brdnr] = brdp; + found++; + + for (i = 0; i < brdp->nrports; i++) + tty_register_device(stli_serial, + brdp->brdnr * STL_MAXPORTS + i, NULL); } - return 0; + return found; } +#else +static inline int stli_findeisabrds(void) { return 0; } +#endif /*****************************************************************************/ @@ -4013,72 +3864,104 @@ static int stli_findeisabrds(void) /*****************************************************************************/ -#ifdef CONFIG_PCI - /* * We have a Stallion board. Allocate a board structure and * initialize it. Read its IO and MEMORY resources from PCI * configuration space. */ -static int stli_initpcibrd(int brdtype, struct pci_dev *devp) +static int __devinit stli_pciprobe(struct pci_dev *pdev, + const struct pci_device_id *ent) { - stlibrd_t *brdp; - - if (pci_enable_device(devp)) - return -EIO; - if ((brdp = stli_allocbrd()) == NULL) - return -ENOMEM; - if ((brdp->brdnr = stli_getbrdnr()) < 0) { + struct stlibrd *brdp; + unsigned int i; + int brdnr, retval = -EIO; + + retval = pci_enable_device(pdev); + if (retval) + goto err; + brdp = stli_allocbrd(); + if (brdp == NULL) { + retval = -ENOMEM; + goto err; + } + mutex_lock(&stli_brdslock); + brdnr = stli_getbrdnr(); + if (brdnr < 0) { printk(KERN_INFO "STALLION: too many boards found, " "maximum supported %d\n", STL_MAXBRDS); - return 0; + mutex_unlock(&stli_brdslock); + retval = -EIO; + goto err_fr; } - brdp->brdtype = brdtype; + brdp->brdnr = (unsigned int)brdnr; + stli_brds[brdp->brdnr] = brdp; + mutex_unlock(&stli_brdslock); + brdp->brdtype = BRD_ECPPCI; /* * We have all resources from the board, so lets setup the actual * board structure now. */ - brdp->iobase = pci_resource_start(devp, 3); - brdp->memaddr = pci_resource_start(devp, 2); - stli_brdinit(brdp); + brdp->iobase = pci_resource_start(pdev, 3); + brdp->memaddr = pci_resource_start(pdev, 2); + retval = stli_brdinit(brdp); + if (retval) + goto err_null; + + brdp->state |= BST_PROBED; + pci_set_drvdata(pdev, brdp); + + EBRDENABLE(brdp); + brdp->enable = NULL; + brdp->disable = NULL; + + for (i = 0; i < brdp->nrports; i++) + tty_register_device(stli_serial, brdp->brdnr * STL_MAXPORTS + i, + &pdev->dev); return 0; +err_null: + stli_brds[brdp->brdnr] = NULL; +err_fr: + kfree(brdp); +err: + return retval; } -/*****************************************************************************/ +static void stli_pciremove(struct pci_dev *pdev) +{ + struct stlibrd *brdp = pci_get_drvdata(pdev); -/* - * Find all Stallion PCI boards that might be installed. Initialize each - * one as it is found. - */ + stli_cleanup_ports(brdp); -static int stli_findpcibrds(void) -{ - struct pci_dev *dev = NULL; + iounmap(brdp->membase); + if (brdp->iosize > 0) + release_region(brdp->iobase, brdp->iosize); - while ((dev = pci_get_device(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECRA, dev))) { - stli_initpcibrd(BRD_ECPPCI, dev); - } - return 0; + stli_brds[brdp->brdnr] = NULL; + kfree(brdp); } -#endif - +static struct pci_driver stli_pcidriver = { + .name = "istallion", + .id_table = istallion_pci_tbl, + .probe = stli_pciprobe, + .remove = __devexit_p(stli_pciremove) +}; /*****************************************************************************/ /* * Allocate a new board structure. Fill out the basic info in it. */ -static stlibrd_t *stli_allocbrd(void) +static struct stlibrd *stli_allocbrd(void) { - stlibrd_t *brdp; + struct stlibrd *brdp; - brdp = kzalloc(sizeof(stlibrd_t), GFP_KERNEL); + brdp = kzalloc(sizeof(struct stlibrd), GFP_KERNEL); if (!brdp) { printk(KERN_ERR "STALLION: failed to allocate memory " - "(size=%Zd)\n", sizeof(stlibrd_t)); + "(size=%Zd)\n", sizeof(struct stlibrd)); return NULL; } brdp->magic = STLI_BOARDMAGIC; @@ -4094,43 +3977,37 @@ static stlibrd_t *stli_allocbrd(void) static int stli_initbrds(void) { - stlibrd_t *brdp, *nxtbrdp; - stlconf_t *confp; - int i, j; - - if (stli_nrbrds > STL_MAXBRDS) { - printk(KERN_INFO "STALLION: too many boards in configuration " - "table, truncating to %d\n", STL_MAXBRDS); - stli_nrbrds = STL_MAXBRDS; - } + struct stlibrd *brdp, *nxtbrdp; + struct stlconf conf; + unsigned int i, j, found = 0; + int retval; -/* - * Firstly scan the list of static boards configured. Allocate - * resources and initialize the boards as found. If this is a - * module then let the module args override static configuration. - */ - for (i = 0; (i < stli_nrbrds); i++) { - confp = &stli_brdconf[i]; - stli_parsebrd(confp, stli_brdsp[i]); + for (stli_nrbrds = 0; stli_nrbrds < ARRAY_SIZE(stli_brdsp); + stli_nrbrds++) { + memset(&conf, 0, sizeof(conf)); + if (stli_parsebrd(&conf, stli_brdsp[stli_nrbrds]) == 0) + continue; if ((brdp = stli_allocbrd()) == NULL) - return -ENOMEM; - brdp->brdnr = i; - brdp->brdtype = confp->brdtype; - brdp->iobase = confp->ioaddr1; - brdp->memaddr = confp->memaddr; - stli_brdinit(brdp); + continue; + brdp->brdnr = stli_nrbrds; + brdp->brdtype = conf.brdtype; + brdp->iobase = conf.ioaddr1; + brdp->memaddr = conf.memaddr; + if (stli_brdinit(brdp) < 0) { + kfree(brdp); + continue; + } + stli_brds[brdp->brdnr] = brdp; + found++; + + for (i = 0; i < brdp->nrports; i++) + tty_register_device(stli_serial, + brdp->brdnr * STL_MAXPORTS + i, NULL); } -/* - * Static configuration table done, so now use dynamic methods to - * see if any more boards should be configured. - */ - stli_argbrds(); - if (STLI_EISAPROBE) - stli_findeisabrds(); -#ifdef CONFIG_PCI - stli_findpcibrds(); -#endif + retval = stli_findeisabrds(); + if (retval > 0) + found += retval; /* * All found boards are initialized. Now for a little optimization, if @@ -4170,7 +4047,16 @@ static int stli_initbrds(void) } } + retval = pci_register_driver(&stli_pcidriver); + if (retval && found == 0) { + printk(KERN_ERR "Neither isa nor eisa cards found nor pci " + "driver can be registered!\n"); + goto err; + } + return 0; +err: + return retval; } /*****************************************************************************/ @@ -4185,12 +4071,13 @@ static ssize_t stli_memread(struct file *fp, char __user *buf, size_t count, lof { unsigned long flags; void __iomem *memptr; - stlibrd_t *brdp; - int brdnr, size, n; + struct stlibrd *brdp; + unsigned int brdnr; + int size, n; void *p; loff_t off = *offp; - brdnr = iminor(fp->f_dentry->d_inode); + brdnr = iminor(fp->f_path.dentry->d_inode); if (brdnr >= stli_nrbrds) return -ENODEV; brdp = stli_brds[brdnr]; @@ -4201,7 +4088,7 @@ static ssize_t stli_memread(struct file *fp, char __user *buf, size_t count, lof if (off >= brdp->memsize || off + count < off) return 0; - size = MIN(count, (brdp->memsize - off)); + size = min(count, (size_t)(brdp->memsize - off)); /* * Copy the data a page at a time @@ -4215,8 +4102,8 @@ static ssize_t stli_memread(struct file *fp, char __user *buf, size_t count, lof spin_lock_irqsave(&brd_lock, flags); EBRDENABLE(brdp); memptr = EBRDGETMEMPTR(brdp, off); - n = MIN(size, (brdp->pagesize - (((unsigned long) off) % brdp->pagesize))); - n = MIN(n, PAGE_SIZE); + n = min(size, (int)(brdp->pagesize - (((unsigned long) off) % brdp->pagesize))); + n = min(n, (int)PAGE_SIZE); memcpy_fromio(p, memptr, n); EBRDDISABLE(brdp); spin_unlock_irqrestore(&brd_lock, flags); @@ -4248,13 +4135,14 @@ static ssize_t stli_memwrite(struct file *fp, const char __user *buf, size_t cou { unsigned long flags; void __iomem *memptr; - stlibrd_t *brdp; + struct stlibrd *brdp; char __user *chbuf; - int brdnr, size, n; + unsigned int brdnr; + int size, n; void *p; loff_t off = *offp; - brdnr = iminor(fp->f_dentry->d_inode); + brdnr = iminor(fp->f_path.dentry->d_inode); if (brdnr >= stli_nrbrds) return -ENODEV; @@ -4267,7 +4155,7 @@ static ssize_t stli_memwrite(struct file *fp, const char __user *buf, size_t cou return 0; chbuf = (char __user *) buf; - size = MIN(count, (brdp->memsize - off)); + size = min(count, (size_t)(brdp->memsize - off)); /* * Copy the data a page at a time @@ -4278,8 +4166,8 @@ static ssize_t stli_memwrite(struct file *fp, const char __user *buf, size_t cou return -ENOMEM; while (size > 0) { - n = MIN(size, (brdp->pagesize - (((unsigned long) off) % brdp->pagesize))); - n = MIN(n, PAGE_SIZE); + n = min(size, (int)(brdp->pagesize - (((unsigned long) off) % brdp->pagesize))); + n = min(n, (int)PAGE_SIZE); if (copy_from_user(p, chbuf, n)) { if (count == 0) count = -EFAULT; @@ -4309,8 +4197,8 @@ static ssize_t stli_memwrite(struct file *fp, const char __user *buf, size_t cou static int stli_getbrdstats(combrd_t __user *bp) { - stlibrd_t *brdp; - int i; + struct stlibrd *brdp; + unsigned int i; if (copy_from_user(&stli_brdstats, bp, sizeof(combrd_t))) return -EFAULT; @@ -4346,19 +4234,20 @@ static int stli_getbrdstats(combrd_t __user *bp) * Resolve the referenced port number into a port struct pointer. */ -static stliport_t *stli_getport(int brdnr, int panelnr, int portnr) +static struct stliport *stli_getport(unsigned int brdnr, unsigned int panelnr, + unsigned int portnr) { - stlibrd_t *brdp; - int i; + struct stlibrd *brdp; + unsigned int i; - if (brdnr < 0 || brdnr >= STL_MAXBRDS) + if (brdnr >= STL_MAXBRDS) return NULL; brdp = stli_brds[brdnr]; if (brdp == NULL) return NULL; for (i = 0; (i < panelnr); i++) portnr += brdp->panels[i]; - if ((portnr < 0) || (portnr >= brdp->nrports)) + if (portnr >= brdp->nrports) return NULL; return brdp->ports[portnr]; } @@ -4371,10 +4260,10 @@ static stliport_t *stli_getport(int brdnr, int panelnr, int portnr) * what port to get stats for (used through board control device). */ -static int stli_portcmdstats(stliport_t *portp) +static int stli_portcmdstats(struct stliport *portp) { unsigned long flags; - stlibrd_t *brdp; + struct stlibrd *brdp; int rc; memset(&stli_comstats, 0, sizeof(comstats_t)); @@ -4445,9 +4334,9 @@ static int stli_portcmdstats(stliport_t *portp) * what port to get stats for (used through board control device). */ -static int stli_getportstats(stliport_t *portp, comstats_t __user *cp) +static int stli_getportstats(struct stliport *portp, comstats_t __user *cp) { - stlibrd_t *brdp; + struct stlibrd *brdp; int rc; if (!portp) { @@ -4476,9 +4365,9 @@ static int stli_getportstats(stliport_t *portp, comstats_t __user *cp) * Clear the port stats structure. We also return it zeroed out... */ -static int stli_clrportstats(stliport_t *portp, comstats_t __user *cp) +static int stli_clrportstats(struct stliport *portp, comstats_t __user *cp) { - stlibrd_t *brdp; + struct stlibrd *brdp; int rc; if (!portp) { @@ -4515,17 +4404,18 @@ static int stli_clrportstats(stliport_t *portp, comstats_t __user *cp) * Return the entire driver ports structure to a user app. */ -static int stli_getportstruct(stliport_t __user *arg) +static int stli_getportstruct(struct stliport __user *arg) { - stliport_t *portp; + struct stliport stli_dummyport; + struct stliport *portp; - if (copy_from_user(&stli_dummyport, arg, sizeof(stliport_t))) + if (copy_from_user(&stli_dummyport, arg, sizeof(struct stliport))) return -EFAULT; portp = stli_getport(stli_dummyport.brdnr, stli_dummyport.panelnr, stli_dummyport.portnr); if (!portp) return -ENODEV; - if (copy_to_user(arg, portp, sizeof(stliport_t))) + if (copy_to_user(arg, portp, sizeof(struct stliport))) return -EFAULT; return 0; } @@ -4536,18 +4426,19 @@ static int stli_getportstruct(stliport_t __user *arg) * Return the entire driver board structure to a user app. */ -static int stli_getbrdstruct(stlibrd_t __user *arg) +static int stli_getbrdstruct(struct stlibrd __user *arg) { - stlibrd_t *brdp; + struct stlibrd stli_dummybrd; + struct stlibrd *brdp; - if (copy_from_user(&stli_dummybrd, arg, sizeof(stlibrd_t))) + if (copy_from_user(&stli_dummybrd, arg, sizeof(struct stlibrd))) return -EFAULT; - if ((stli_dummybrd.brdnr < 0) || (stli_dummybrd.brdnr >= STL_MAXBRDS)) + if (stli_dummybrd.brdnr >= STL_MAXBRDS) return -ENODEV; brdp = stli_brds[stli_dummybrd.brdnr]; if (!brdp) return -ENODEV; - if (copy_to_user(arg, brdp, sizeof(stlibrd_t))) + if (copy_to_user(arg, brdp, sizeof(struct stlibrd))) return -EFAULT; return 0; } @@ -4562,7 +4453,7 @@ static int stli_getbrdstruct(stlibrd_t __user *arg) static int stli_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg) { - stlibrd_t *brdp; + struct stlibrd *brdp; int brdnr, rc, done; void __user *argp = (void __user *)arg; @@ -4661,46 +4552,53 @@ static const struct tty_operations stli_ops = { }; /*****************************************************************************/ +/* + * Loadable module initialization stuff. + */ + +static void istallion_cleanup_isa(void) +{ + struct stlibrd *brdp; + unsigned int j; + + for (j = 0; (j < stli_nrbrds); j++) { + if ((brdp = stli_brds[j]) == NULL || (brdp->state & BST_PROBED)) + continue; -static int __init stli_init(void) + stli_cleanup_ports(brdp); + + iounmap(brdp->membase); + if (brdp->iosize > 0) + release_region(brdp->iobase, brdp->iosize); + kfree(brdp); + stli_brds[j] = NULL; + } +} + +static int __init istallion_module_init(void) { - int i; + unsigned int i; + int retval; + printk(KERN_INFO "%s: version %s\n", stli_drvtitle, stli_drvversion); spin_lock_init(&stli_lock); spin_lock_init(&brd_lock); - stli_initbrds(); - - stli_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS); - if (!stli_serial) - return -ENOMEM; - -/* - * Allocate a temporary write buffer. - */ stli_txcookbuf = kmalloc(STLI_TXBUFSIZE, GFP_KERNEL); - if (!stli_txcookbuf) + if (!stli_txcookbuf) { printk(KERN_ERR "STALLION: failed to allocate memory " "(size=%d)\n", STLI_TXBUFSIZE); + retval = -ENOMEM; + goto err; + } -/* - * Set up a character driver for the shared memory region. We need this - * to down load the slave code image. Also it is a useful debugging tool. - */ - if (register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stli_fsiomem)) - printk(KERN_ERR "STALLION: failed to register serial memory " - "device\n"); - - istallion_class = class_create(THIS_MODULE, "staliomem"); - for (i = 0; i < 4; i++) - class_device_create(istallion_class, NULL, - MKDEV(STL_SIOMEMMAJOR, i), - NULL, "staliomem%d", i); + stli_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS); + if (!stli_serial) { + retval = -ENOMEM; + goto err_free; + } -/* - * Set up the tty driver structure and register us as a driver. - */ stli_serial->owner = THIS_MODULE; stli_serial->driver_name = stli_drvname; stli_serial->name = stli_serialname; @@ -4709,15 +4607,79 @@ static int __init stli_init(void) stli_serial->type = TTY_DRIVER_TYPE_SERIAL; stli_serial->subtype = SERIAL_TYPE_NORMAL; stli_serial->init_termios = stli_deftermios; - stli_serial->flags = TTY_DRIVER_REAL_RAW; + stli_serial->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; tty_set_operations(stli_serial, &stli_ops); - if (tty_register_driver(stli_serial)) { - put_tty_driver(stli_serial); + retval = tty_register_driver(stli_serial); + if (retval) { printk(KERN_ERR "STALLION: failed to register serial driver\n"); - return -EBUSY; + goto err_ttyput; } + + retval = stli_initbrds(); + if (retval) + goto err_ttyunr; + +/* + * Set up a character driver for the shared memory region. We need this + * to down load the slave code image. Also it is a useful debugging tool. + */ + retval = register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stli_fsiomem); + if (retval) { + printk(KERN_ERR "STALLION: failed to register serial memory " + "device\n"); + goto err_deinit; + } + + istallion_class = class_create(THIS_MODULE, "staliomem"); + for (i = 0; i < 4; i++) + class_device_create(istallion_class, NULL, + MKDEV(STL_SIOMEMMAJOR, i), + NULL, "staliomem%d", i); + return 0; +err_deinit: + pci_unregister_driver(&stli_pcidriver); + istallion_cleanup_isa(); +err_ttyunr: + tty_unregister_driver(stli_serial); +err_ttyput: + put_tty_driver(stli_serial); +err_free: + kfree(stli_txcookbuf); +err: + return retval; } /*****************************************************************************/ + +static void __exit istallion_module_exit(void) +{ + unsigned int j; + + printk(KERN_INFO "Unloading %s: version %s\n", stli_drvtitle, + stli_drvversion); + + if (stli_timeron) { + stli_timeron = 0; + del_timer_sync(&stli_timerlist); + } + + unregister_chrdev(STL_SIOMEMMAJOR, "staliomem"); + + for (j = 0; j < 4; j++) + class_device_destroy(istallion_class, MKDEV(STL_SIOMEMMAJOR, + j)); + class_destroy(istallion_class); + + pci_unregister_driver(&stli_pcidriver); + istallion_cleanup_isa(); + + tty_unregister_driver(stli_serial); + put_tty_driver(stli_serial); + + kfree(stli_txcookbuf); +} + +module_init(istallion_module_init); +module_exit(istallion_module_exit); diff --git a/trunk/drivers/char/keyboard.c b/trunk/drivers/char/keyboard.c index 20b6c8b30248..7a6c1c0b7a95 100644 --- a/trunk/drivers/char/keyboard.c +++ b/trunk/drivers/char/keyboard.c @@ -710,7 +710,7 @@ static void k_fn(struct vc_data *vc, unsigned char value, char up_flag) static void k_cur(struct vc_data *vc, unsigned char value, char up_flag) { - static const char *cur_chars = "BDCA"; + static const char cur_chars[] = "BDCA"; if (up_flag) return; diff --git a/trunk/drivers/char/lp.c b/trunk/drivers/char/lp.c index 1ecea7d448f1..b70b5388b5a8 100644 --- a/trunk/drivers/char/lp.c +++ b/trunk/drivers/char/lp.c @@ -296,7 +296,7 @@ static int lp_wait_ready(int minor, int nonblock) static ssize_t lp_write(struct file * file, const char __user * buf, size_t count, loff_t *ppos) { - unsigned int minor = iminor(file->f_dentry->d_inode); + unsigned int minor = iminor(file->f_path.dentry->d_inode); struct parport *port = lp_table[minor].dev->port; char *kbuf = lp_table[minor].lp_buffer; ssize_t retv = 0; @@ -415,7 +415,7 @@ static ssize_t lp_read(struct file * file, char __user * buf, size_t count, loff_t *ppos) { DEFINE_WAIT(wait); - unsigned int minor=iminor(file->f_dentry->d_inode); + unsigned int minor=iminor(file->f_path.dentry->d_inode); struct parport *port = lp_table[minor].dev->port; ssize_t retval = 0; char *kbuf = lp_table[minor].lp_buffer; diff --git a/trunk/drivers/char/mem.c b/trunk/drivers/char/mem.c index e67eef4867ba..089020e0ee5a 100644 --- a/trunk/drivers/char/mem.c +++ b/trunk/drivers/char/mem.c @@ -774,7 +774,7 @@ static loff_t memory_lseek(struct file * file, loff_t offset, int orig) { loff_t ret; - mutex_lock(&file->f_dentry->d_inode->i_mutex); + mutex_lock(&file->f_path.dentry->d_inode->i_mutex); switch (orig) { case 0: file->f_pos = offset; @@ -789,7 +789,7 @@ static loff_t memory_lseek(struct file * file, loff_t offset, int orig) default: ret = -EINVAL; } - mutex_unlock(&file->f_dentry->d_inode->i_mutex); + mutex_unlock(&file->f_path.dentry->d_inode->i_mutex); return ret; } diff --git a/trunk/drivers/char/misc.c b/trunk/drivers/char/misc.c index 7a484fc7cb9e..7e975f606924 100644 --- a/trunk/drivers/char/misc.c +++ b/trunk/drivers/char/misc.c @@ -199,6 +199,8 @@ int misc_register(struct miscdevice * misc) dev_t dev; int err = 0; + INIT_LIST_HEAD(&misc->list); + down(&misc_sem); list_for_each_entry(c, &misc_list, list) { if (c->minor == misc->minor) { diff --git a/trunk/drivers/char/mmtimer.c b/trunk/drivers/char/mmtimer.c index 22b9905c1e52..c09160383a53 100644 --- a/trunk/drivers/char/mmtimer.c +++ b/trunk/drivers/char/mmtimer.c @@ -680,7 +680,7 @@ static int __init mmtimer_init(void) if (sn_rtc_cycles_per_second < 100000) { printk(KERN_ERR "%s: unable to determine clock frequency\n", MMTIMER_NAME); - return -1; + goto out1; } mmtimer_femtoperiod = ((unsigned long)1E15 + sn_rtc_cycles_per_second / @@ -689,13 +689,13 @@ static int __init mmtimer_init(void) if (request_irq(SGI_MMTIMER_VECTOR, mmtimer_interrupt, IRQF_PERCPU, MMTIMER_NAME, NULL)) { printk(KERN_WARNING "%s: unable to allocate interrupt.", MMTIMER_NAME); - return -1; + goto out1; } if (misc_register(&mmtimer_miscdev)) { printk(KERN_ERR "%s: failed to register device\n", MMTIMER_NAME); - return -1; + goto out2; } /* Get max numbered node, calculate slots needed */ @@ -709,16 +709,18 @@ static int __init mmtimer_init(void) if (timers == NULL) { printk(KERN_ERR "%s: failed to allocate memory for device\n", MMTIMER_NAME); - return -1; + goto out3; } + memset(timers,0,(sizeof(mmtimer_t *)*maxn)); + /* Allocate mmtimer_t's for each online node */ for_each_online_node(node) { timers[node] = kmalloc_node(sizeof(mmtimer_t)*NUM_COMPARATORS, GFP_KERNEL, node); if (timers[node] == NULL) { printk(KERN_ERR "%s: failed to allocate memory for device\n", MMTIMER_NAME); - return -1; + goto out4; } for (i=0; i< NUM_COMPARATORS; i++) { mmtimer_t * base = timers[node] + i; @@ -739,6 +741,17 @@ static int __init mmtimer_init(void) sn_rtc_cycles_per_second/(unsigned long)1E6); return 0; + +out4: + for_each_online_node(node) { + kfree(timers[node]); + } +out3: + misc_deregister(&mmtimer_miscdev); +out2: + free_irq(SGI_MMTIMER_VECTOR, NULL); +out1: + return -1; } module_init(mmtimer_init); diff --git a/trunk/drivers/char/moxa.c b/trunk/drivers/char/moxa.c index 96cb1f07332b..f391a24a1b44 100644 --- a/trunk/drivers/char/moxa.c +++ b/trunk/drivers/char/moxa.c @@ -222,7 +222,7 @@ static struct semaphore moxaBuffSem; /* * static functions: */ -static void do_moxa_softint(void *); +static void do_moxa_softint(struct work_struct *); static int moxa_open(struct tty_struct *, struct file *); static void moxa_close(struct tty_struct *, struct file *); static int moxa_write(struct tty_struct *, const unsigned char *, int); @@ -234,7 +234,7 @@ static void moxa_put_char(struct tty_struct *, unsigned char); static int moxa_ioctl(struct tty_struct *, struct file *, unsigned int, unsigned long); static void moxa_throttle(struct tty_struct *); static void moxa_unthrottle(struct tty_struct *); -static void moxa_set_termios(struct tty_struct *, struct termios *); +static void moxa_set_termios(struct tty_struct *, struct ktermios *); static void moxa_stop(struct tty_struct *); static void moxa_start(struct tty_struct *); static void moxa_hangup(struct tty_struct *); @@ -261,7 +261,7 @@ static void MoxaPortEnable(int); static void MoxaPortDisable(int); static long MoxaPortGetMaxBaud(int); static long MoxaPortSetBaud(int, long); -static int MoxaPortSetTermio(int, struct termios *, speed_t); +static int MoxaPortSetTermio(int, struct ktermios *, speed_t); static int MoxaPortGetLineOut(int, int *, int *); static void MoxaPortLineCtrl(int, int, int); static void MoxaPortFlowCtrl(int, int, int, int, int, int); @@ -355,6 +355,8 @@ static int __init moxa_init(void) moxaDriver->init_termios.c_oflag = 0; moxaDriver->init_termios.c_cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL; moxaDriver->init_termios.c_lflag = 0; + moxaDriver->init_termios.c_ispeed = 9600; + moxaDriver->init_termios.c_ospeed = 9600; moxaDriver->flags = TTY_DRIVER_REAL_RAW; tty_set_operations(moxaDriver, &moxa_ops); @@ -363,7 +365,7 @@ static int __init moxa_init(void) for (i = 0, ch = moxaChannels; i < MAX_PORTS; i++, ch++) { ch->type = PORT_16550A; ch->port = i; - INIT_WORK(&ch->tqueue, do_moxa_softint, ch); + INIT_WORK(&ch->tqueue, do_moxa_softint); ch->tty = NULL; ch->close_delay = 5 * HZ / 10; ch->closing_wait = 30 * HZ; @@ -498,9 +500,12 @@ static void __exit moxa_exit(void) printk("Couldn't unregister MOXA Intellio family serial driver\n"); put_tty_driver(moxaDriver); - for (i = 0; i < MAX_BOARDS; i++) + for (i = 0; i < MAX_BOARDS; i++) { + if (moxaBaseAddr[i]) + iounmap(moxaBaseAddr[i]); if (moxa_boards[i].busType == MOXA_BUS_TYPE_PCI) pci_dev_put(moxa_boards[i].pciInfo.pdev); + } if (verbose) printk("Done\n"); @@ -509,9 +514,9 @@ static void __exit moxa_exit(void) module_init(moxa_init); module_exit(moxa_exit); -static void do_moxa_softint(void *private_) +static void do_moxa_softint(struct work_struct *work) { - struct moxa_str *ch = (struct moxa_str *) private_; + struct moxa_str *ch = container_of(work, struct moxa_str, tqueue); struct tty_struct *tty; if (ch && (tty = ch->tty)) { @@ -861,7 +866,7 @@ static void moxa_unthrottle(struct tty_struct *tty) } static void moxa_set_termios(struct tty_struct *tty, - struct termios *old_termios) + struct ktermios *old_termios) { struct moxa_str *ch = (struct moxa_str *) tty->driver_data; @@ -975,7 +980,7 @@ static void moxa_poll(unsigned long ignored) static void set_tty_param(struct tty_struct *tty) { - register struct termios *ts; + register struct ktermios *ts; struct moxa_str *ch; int rts, cts, txflow, rxflow, xany; @@ -1146,7 +1151,7 @@ static void shut_down(struct moxa_str *ch) static void receive_data(struct moxa_str *ch) { struct tty_struct *tp; - struct termios *ts; + struct ktermios *ts; unsigned long flags; ts = NULL; @@ -1909,9 +1914,9 @@ int MoxaPortsOfCard(int cardno) * * Function 12: Configure the port. * Syntax: - * int MoxaPortSetTermio(int port, struct termios *termio, speed_t baud); + * int MoxaPortSetTermio(int port, struct ktermios *termio, speed_t baud); * int port : port number (0 - 127) - * struct termios * termio : termio structure pointer + * struct ktermios * termio : termio structure pointer * speed_t baud : baud rate * * return: -1 : this port is invalid or termio == NULL @@ -2192,7 +2197,7 @@ long MoxaPortSetBaud(int port, long baud) return (baud); } -int MoxaPortSetTermio(int port, struct termios *termio, speed_t baud) +int MoxaPortSetTermio(int port, struct ktermios *termio, speed_t baud) { void __iomem *ofsAddr; tcflag_t cflag; diff --git a/trunk/drivers/char/mxser.c b/trunk/drivers/char/mxser.c index 048d91142c17..c063359baf78 100644 --- a/trunk/drivers/char/mxser.c +++ b/trunk/drivers/char/mxser.c @@ -328,8 +328,8 @@ struct mxser_struct { int xmit_tail; int xmit_cnt; struct work_struct tqueue; - struct termios normal_termios; - struct termios callout_termios; + struct ktermios normal_termios; + struct ktermios callout_termios; wait_queue_head_t open_wait; wait_queue_head_t close_wait; wait_queue_head_t delta_msr_wait; @@ -364,8 +364,8 @@ static int mxserBoardCAP[MXSER_BOARDS] = { static struct tty_driver *mxvar_sdriver; static struct mxser_struct mxvar_table[MXSER_PORTS]; static struct tty_struct *mxvar_tty[MXSER_PORTS + 1]; -static struct termios *mxvar_termios[MXSER_PORTS + 1]; -static struct termios *mxvar_termios_locked[MXSER_PORTS + 1]; +static struct ktermios *mxvar_termios[MXSER_PORTS + 1]; +static struct ktermios *mxvar_termios_locked[MXSER_PORTS + 1]; static struct mxser_log mxvar_log; static int mxvar_diagflag; static unsigned char mxser_msr[MXSER_PORTS + 1]; @@ -389,7 +389,7 @@ static int mxser_init(void); /* static void mxser_poll(unsigned long); */ static int mxser_get_ISA_conf(int, struct mxser_hwconf *); static int mxser_get_PCI_conf(int, int, int, struct mxser_hwconf *); -static void mxser_do_softint(void *); +static void mxser_do_softint(struct work_struct *); static int mxser_open(struct tty_struct *, struct file *); static void mxser_close(struct tty_struct *, struct file *); static int mxser_write(struct tty_struct *, const unsigned char *, int); @@ -402,7 +402,7 @@ static int mxser_ioctl(struct tty_struct *, struct file *, uint, ulong); static int mxser_ioctl_special(unsigned int, void __user *); static void mxser_throttle(struct tty_struct *); static void mxser_unthrottle(struct tty_struct *); -static void mxser_set_termios(struct tty_struct *, struct termios *); +static void mxser_set_termios(struct tty_struct *, struct ktermios *); static void mxser_stop(struct tty_struct *); static void mxser_start(struct tty_struct *); static void mxser_hangup(struct tty_struct *); @@ -414,7 +414,7 @@ static void mxser_check_modem_status(struct mxser_struct *, int); static int mxser_block_til_ready(struct tty_struct *, struct file *, struct mxser_struct *); static int mxser_startup(struct mxser_struct *); static void mxser_shutdown(struct mxser_struct *); -static int mxser_change_speed(struct mxser_struct *, struct termios *old_termios); +static int mxser_change_speed(struct mxser_struct *, struct ktermios *old_termios); static int mxser_get_serial_info(struct mxser_struct *, struct serial_struct __user *); static int mxser_set_serial_info(struct mxser_struct *, struct serial_struct __user *); static int mxser_get_lsr_info(struct mxser_struct *, unsigned int __user *); @@ -515,6 +515,7 @@ static void __exit mxser_module_exit(void) if (pdev != NULL) { /* PCI */ release_region(pci_resource_start(pdev, 2), pci_resource_len(pdev, 2)); release_region(pci_resource_start(pdev, 3), pci_resource_len(pdev, 3)); + pci_dev_put(pdev); } else { release_region(mxsercfg[i].ioaddr[0], 8 * mxsercfg[i].ports); release_region(mxsercfg[i].vector, 1); @@ -556,7 +557,7 @@ static int mxser_initbrd(int board, struct mxser_hwconf *hwconf) n = board * MXSER_PORTS_PER_BOARD; info = &mxvar_table[n]; /*if (verbose) */ { - printk(KERN_DEBUG " ttyM%d - ttyM%d ", + printk(KERN_DEBUG " ttyMI%d - ttyMI%d ", n, n + hwconf->ports - 1); printk(" max. baud rate = %d bps.\n", hwconf->MaxCanSetBaudRate[0]); @@ -590,7 +591,7 @@ static int mxser_initbrd(int board, struct mxser_hwconf *hwconf) info->custom_divisor = hwconf->baud_base[i] * 16; info->close_delay = 5 * HZ / 10; info->closing_wait = 30 * HZ; - INIT_WORK(&info->tqueue, mxser_do_softint, info); + INIT_WORK(&info->tqueue, mxser_do_softint); info->normal_termios = mxvar_sdriver->init_termios; init_waitqueue_head(&info->open_wait); init_waitqueue_head(&info->close_wait); @@ -717,7 +718,7 @@ static int mxser_init(void) /* Initialize the tty_driver structure */ memset(mxvar_sdriver, 0, sizeof(struct tty_driver)); mxvar_sdriver->magic = TTY_DRIVER_MAGIC; - mxvar_sdriver->name = "ttyM"; + mxvar_sdriver->name = "ttyMI"; mxvar_sdriver->major = ttymajor; mxvar_sdriver->minor_start = 0; mxvar_sdriver->num = MXSER_PORTS + 1; @@ -725,6 +726,8 @@ static int mxser_init(void) mxvar_sdriver->subtype = SERIAL_TYPE_NORMAL; mxvar_sdriver->init_termios = tty_std_termios; mxvar_sdriver->init_termios.c_cflag = B9600|CS8|CREAD|HUPCL|CLOCAL; + mxvar_sdriver->init_termios.c_ispeed = 9600; + mxvar_sdriver->init_termios.c_ospeed = 9600; mxvar_sdriver->flags = TTY_DRIVER_REAL_RAW; tty_set_operations(mxvar_sdriver, &mxser_ops); mxvar_sdriver->ttys = mxvar_tty; @@ -839,9 +842,9 @@ static int mxser_init(void) index = 0; b = 0; while (b < n) { - pdev = pci_find_device(mxser_pcibrds[b].vendor, + pdev = pci_get_device(mxser_pcibrds[b].vendor, mxser_pcibrds[b].device, pdev); - if (pdev == NULL) { + if (pdev == NULL) { b++; continue; } @@ -893,6 +896,9 @@ static int mxser_init(void) if (mxser_initbrd(m, &hwconf) < 0) continue; m++; + /* Keep an extra reference if we succeeded. It will + be returned at unload time */ + pci_dev_get(pdev); } } #endif @@ -917,9 +923,10 @@ static int mxser_init(void) return 0; } -static void mxser_do_softint(void *private_) +static void mxser_do_softint(struct work_struct *work) { - struct mxser_struct *info = private_; + struct mxser_struct *info = + container_of(work, struct mxser_struct, tqueue); struct tty_struct *tty; tty = info->tty; @@ -993,7 +1000,7 @@ static int mxser_open(struct tty_struct *tty, struct file *filp) mxser_change_speed(info, NULL); } - info->session = current->signal->session; + info->session = process_session(current); info->pgrp = process_group(current); /* @@ -1744,7 +1751,7 @@ static void mxser_unthrottle(struct tty_struct *tty) /* MX_UNLOCK(&info->slock); */ } -static void mxser_set_termios(struct tty_struct *tty, struct termios *old_termios) +static void mxser_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { struct mxser_struct *info = tty->driver_data; unsigned long flags; @@ -2536,7 +2543,7 @@ static void mxser_shutdown(struct mxser_struct *info) * This routine is called to set the UART divisor registers to match * the specified baud rate for a serial port. */ -static int mxser_change_speed(struct mxser_struct *info, struct termios *old_termios) +static int mxser_change_speed(struct mxser_struct *info, struct ktermios *old_termios) { unsigned cflag, cval, fcr; int ret = 0; diff --git a/trunk/drivers/char/mxser_new.c b/trunk/drivers/char/mxser_new.c new file mode 100644 index 000000000000..efa8076c33e0 --- /dev/null +++ b/trunk/drivers/char/mxser_new.c @@ -0,0 +1,2804 @@ +/* + * mxser.c -- MOXA Smartio/Industio family multiport serial driver. + * + * Copyright (C) 1999-2006 Moxa Technologies (support@moxa.com.tw). + * Copyright (C) 2006 Jiri Slaby + * + * This code is loosely based on the 1.8 moxa driver which is based on + * Linux serial driver, written by Linus Torvalds, Theodore T'so and + * others. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Fed through a cleanup, indent and remove of non 2.6 code by Alan Cox + * . The original 1.8 code is available on www.moxa.com. + * - Fixed x86_64 cleanness + * - Fixed sleep with spinlock held in mxser_send_break + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "mxser_new.h" + +#define MXSER_VERSION "2.0" +#define MXSERMAJOR 174 +#define MXSERCUMAJOR 175 + +#define MXSER_EVENT_TXLOW 1 + +#define MXSER_BOARDS 4 /* Max. boards */ +#define MXSER_PORTS_PER_BOARD 8 /* Max. ports per board */ +#define MXSER_PORTS (MXSER_BOARDS * MXSER_PORTS_PER_BOARD) +#define MXSER_ISR_PASS_LIMIT 99999L + +#define MXSER_ERR_IOADDR -1 +#define MXSER_ERR_IRQ -2 +#define MXSER_ERR_IRQ_CONFLIT -3 +#define MXSER_ERR_VECTOR -4 + +#define WAKEUP_CHARS 256 + +#define UART_MCR_AFE 0x20 +#define UART_LSR_SPECIAL 0x1E + +#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK|\ + IXON|IXOFF)) + +#define C168_ASIC_ID 1 +#define C104_ASIC_ID 2 +#define C102_ASIC_ID 0xB +#define CI132_ASIC_ID 4 +#define CI134_ASIC_ID 3 +#define CI104J_ASIC_ID 5 + +#define MXSER_HIGHBAUD 1 +#define MXSER_HAS2 2 + +/* This is only for PCI */ +static const struct { + int type; + int tx_fifo; + int rx_fifo; + int xmit_fifo_size; + int rx_high_water; + int rx_trigger; + int rx_low_water; + long max_baud; +} Gpci_uart_info[] = { + {MOXA_OTHER_UART, 16, 16, 16, 14, 14, 1, 921600L}, + {MOXA_MUST_MU150_HWID, 64, 64, 64, 48, 48, 16, 230400L}, + {MOXA_MUST_MU860_HWID, 128, 128, 128, 96, 96, 32, 921600L} +}; +#define UART_INFO_NUM ARRAY_SIZE(Gpci_uart_info) + +struct mxser_cardinfo { + unsigned int nports; + char *name; + unsigned int flags; +}; + +static const struct mxser_cardinfo mxser_cards[] = { + { 8, "C168 series", }, /* C168-ISA */ + { 4, "C104 series", }, /* C104-ISA */ + { 4, "CI-104J series", }, /* CI104J */ + { 8, "C168H/PCI series", }, /* C168-PCI */ + { 4, "C104H/PCI series", }, /* C104-PCI */ + { 4, "C102 series", MXSER_HAS2 }, /* C102-ISA */ + { 4, "CI-132 series", MXSER_HAS2 }, /* CI132 */ + { 4, "CI-134 series", }, /* CI134 */ + { 2, "CP-132 series", }, /* CP132 */ + { 4, "CP-114 series", }, /* CP114 */ + { 4, "CT-114 series", }, /* CT114 */ + { 2, "CP-102 series", MXSER_HIGHBAUD }, /* CP102 */ + { 4, "CP-104U series", }, /* CP104U */ + { 8, "CP-168U series", }, /* CP168U */ + { 2, "CP-132U series", }, /* CP132U */ + { 4, "CP-134U series", }, /* CP134U */ + { 4, "CP-104JU series", }, /* CP104JU */ + { 8, "Moxa UC7000 Serial", }, /* RC7000 */ + { 8, "CP-118U series", }, /* CP118U */ + { 2, "CP-102UL series", }, /* CP102UL */ + { 2, "CP-102U series", }, /* CP102U */ + { 8, "CP-118EL series", }, /* CP118EL */ + { 8, "CP-168EL series", }, /* CP168EL */ + { 4, "CP-104EL series", } /* CP104EL */ +}; + +/* driver_data correspond to the lines in the structure above + see also ISA probe function before you change something */ +static struct pci_device_id mxser_pcibrds[] = { + { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_C168), + .driver_data = 3 }, + { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_C104), + .driver_data = 4 }, + { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP132), + .driver_data = 8 }, + { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP114), + .driver_data = 9 }, + { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CT114), + .driver_data = 10 }, + { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP102), + .driver_data = 11 }, + { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP104U), + .driver_data = 12 }, + { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP168U), + .driver_data = 13 }, + { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP132U), + .driver_data = 14 }, + { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP134U), + .driver_data = 15 }, + { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP104JU), + .driver_data = 16 }, + { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_RC7000), + .driver_data = 17 }, + { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP118U), + .driver_data = 18 }, + { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP102UL), + .driver_data = 19 }, + { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP102U), + .driver_data = 20 }, + { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP118EL), + .driver_data = 21 }, + { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP168EL), + .driver_data = 22 }, + { PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP104EL), + .driver_data = 23 }, + { } +}; +MODULE_DEVICE_TABLE(pci, mxser_pcibrds); + +static int ioaddr[MXSER_BOARDS] = { 0, 0, 0, 0 }; +static int ttymajor = MXSERMAJOR; +static int calloutmajor = MXSERCUMAJOR; + +/* Variables for insmod */ + +MODULE_AUTHOR("Casper Yang"); +MODULE_DESCRIPTION("MOXA Smartio/Industio Family Multiport Board Device Driver"); +module_param_array(ioaddr, int, NULL, 0); +module_param(ttymajor, int, 0); +MODULE_LICENSE("GPL"); + +struct mxser_log { + int tick; + unsigned long rxcnt[MXSER_PORTS]; + unsigned long txcnt[MXSER_PORTS]; +}; + + +struct mxser_mon { + unsigned long rxcnt; + unsigned long txcnt; + unsigned long up_rxcnt; + unsigned long up_txcnt; + int modem_status; + unsigned char hold_reason; +}; + +struct mxser_mon_ext { + unsigned long rx_cnt[32]; + unsigned long tx_cnt[32]; + unsigned long up_rxcnt[32]; + unsigned long up_txcnt[32]; + int modem_status[32]; + + long baudrate[32]; + int databits[32]; + int stopbits[32]; + int parity[32]; + int flowctrl[32]; + int fifo[32]; + int iftype[32]; +}; + +struct mxser_board; + +struct mxser_port { + struct mxser_board *board; + struct tty_struct *tty; + + unsigned long ioaddr; + unsigned long opmode_ioaddr; + int max_baud; + + int rx_high_water; + int rx_trigger; /* Rx fifo trigger level */ + int rx_low_water; + int baud_base; /* max. speed */ + long realbaud; + int type; /* UART type */ + int flags; /* defined in tty.h */ + long session; /* Session of opening process */ + long pgrp; /* pgrp of opening process */ + + int x_char; /* xon/xoff character */ + int IER; /* Interrupt Enable Register */ + int MCR; /* Modem control register */ + + unsigned char stop_rx; + unsigned char ldisc_stop_rx; + + int custom_divisor; + int close_delay; + unsigned short closing_wait; + unsigned char err_shadow; + unsigned long event; + + int count; /* # of fd on device */ + int blocked_open; /* # of blocked opens */ + struct async_icount icount; /* kernel counters for 4 input interrupts */ + int timeout; + + int read_status_mask; + int ignore_status_mask; + int xmit_fifo_size; + unsigned char *xmit_buf; + int xmit_head; + int xmit_tail; + int xmit_cnt; + + struct ktermios normal_termios; + struct ktermios callout_termios; + + struct mxser_mon mon_data; + + spinlock_t slock; + struct work_struct tqueue; + wait_queue_head_t open_wait; + wait_queue_head_t close_wait; + wait_queue_head_t delta_msr_wait; +}; + +struct mxser_board { + unsigned int idx; + int irq; + const struct mxser_cardinfo *info; + unsigned long vector; + unsigned long vector_mask; + + int chip_flag; + int uart_type; + + struct mxser_port ports[MXSER_PORTS_PER_BOARD]; +}; + +struct mxser_mstatus { + tcflag_t cflag; + int cts; + int dsr; + int ri; + int dcd; +}; + +static struct mxser_mstatus GMStatus[MXSER_PORTS]; + +static int mxserBoardCAP[MXSER_BOARDS] = { + 0, 0, 0, 0 + /* 0x180, 0x280, 0x200, 0x320 */ +}; + +static struct mxser_board mxser_boards[MXSER_BOARDS]; +static struct tty_driver *mxvar_sdriver; +static struct mxser_log mxvar_log; +static int mxvar_diagflag; +static unsigned char mxser_msr[MXSER_PORTS + 1]; +static struct mxser_mon_ext mon_data_ext; +static int mxser_set_baud_method[MXSER_PORTS + 1]; +static spinlock_t gm_lock; + +static int CheckIsMoxaMust(int io) +{ + u8 oldmcr, hwid; + int i; + + outb(0, io + UART_LCR); + DISABLE_MOXA_MUST_ENCHANCE_MODE(io); + oldmcr = inb(io + UART_MCR); + outb(0, io + UART_MCR); + SET_MOXA_MUST_XON1_VALUE(io, 0x11); + if ((hwid = inb(io + UART_MCR)) != 0) { + outb(oldmcr, io + UART_MCR); + return MOXA_OTHER_UART; + } + + GET_MOXA_MUST_HARDWARE_ID(io, &hwid); + for (i = 1; i < UART_INFO_NUM; i++) { /* 0 = OTHER_UART */ + if (hwid == Gpci_uart_info[i].type) + return (int)hwid; + } + return MOXA_OTHER_UART; +} + +static void process_txrx_fifo(struct mxser_port *info) +{ + int i; + + if ((info->type == PORT_16450) || (info->type == PORT_8250)) { + info->rx_trigger = 1; + info->rx_high_water = 1; + info->rx_low_water = 1; + info->xmit_fifo_size = 1; + } else + for (i = 0; i < UART_INFO_NUM; i++) + if (info->board->chip_flag == Gpci_uart_info[i].type) { + info->rx_trigger = Gpci_uart_info[i].rx_trigger; + info->rx_low_water = Gpci_uart_info[i].rx_low_water; + info->rx_high_water = Gpci_uart_info[i].rx_high_water; + info->xmit_fifo_size = Gpci_uart_info[i].xmit_fifo_size; + break; + } +} + +static void mxser_do_softint(struct work_struct *work) +{ + struct mxser_port *info = container_of(work, struct mxser_port, tqueue); + struct tty_struct *tty = info->tty; + + if (test_and_clear_bit(MXSER_EVENT_TXLOW, &info->event)) + tty_wakeup(tty); +} + +static unsigned char mxser_get_msr(int baseaddr, int mode, int port) +{ + unsigned char status = 0; + + status = inb(baseaddr + UART_MSR); + + mxser_msr[port] &= 0x0F; + mxser_msr[port] |= status; + status = mxser_msr[port]; + if (mode) + mxser_msr[port] = 0; + + return status; +} + +static int mxser_block_til_ready(struct tty_struct *tty, struct file *filp, + struct mxser_port *port) +{ + DECLARE_WAITQUEUE(wait, current); + int retval; + int do_clocal = 0; + unsigned long flags; + + /* + * If non-blocking mode is set, or the port is not enabled, + * then make the check up front and then exit. + */ + if ((filp->f_flags & O_NONBLOCK) || + test_bit(TTY_IO_ERROR, &tty->flags)) { + port->flags |= ASYNC_NORMAL_ACTIVE; + return 0; + } + + if (tty->termios->c_cflag & CLOCAL) + do_clocal = 1; + + /* + * Block waiting for the carrier detect and the line to become + * free (i.e., not in use by the callout). While we are in + * this loop, port->count is dropped by one, so that + * mxser_close() knows when to free things. We restore it upon + * exit, either normal or abnormal. + */ + retval = 0; + add_wait_queue(&port->open_wait, &wait); + + spin_lock_irqsave(&port->slock, flags); + if (!tty_hung_up_p(filp)) + port->count--; + spin_unlock_irqrestore(&port->slock, flags); + port->blocked_open++; + while (1) { + spin_lock_irqsave(&port->slock, flags); + outb(inb(port->ioaddr + UART_MCR) | + UART_MCR_DTR | UART_MCR_RTS, port->ioaddr + UART_MCR); + spin_unlock_irqrestore(&port->slock, flags); + set_current_state(TASK_INTERRUPTIBLE); + if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)) { + if (port->flags & ASYNC_HUP_NOTIFY) + retval = -EAGAIN; + else + retval = -ERESTARTSYS; + break; + } + if (!(port->flags & ASYNC_CLOSING) && + (do_clocal || + (inb(port->ioaddr + UART_MSR) & UART_MSR_DCD))) + break; + if (signal_pending(current)) { + retval = -ERESTARTSYS; + break; + } + schedule(); + } + set_current_state(TASK_RUNNING); + remove_wait_queue(&port->open_wait, &wait); + if (!tty_hung_up_p(filp)) + port->count++; + port->blocked_open--; + if (retval) + return retval; + port->flags |= ASYNC_NORMAL_ACTIVE; + return 0; +} + +static int mxser_set_baud(struct mxser_port *info, long newspd) +{ + int quot = 0; + unsigned char cval; + int ret = 0; + unsigned long flags; + + if (!info->tty || !info->tty->termios) + return ret; + + if (!(info->ioaddr)) + return ret; + + if (newspd > info->max_baud) + return 0; + + info->realbaud = newspd; + if (newspd == 134) { + quot = (2 * info->baud_base / 269); + } else if (newspd) { + quot = info->baud_base / newspd; + if (quot == 0) + quot = 1; + } else { + quot = 0; + } + + info->timeout = ((info->xmit_fifo_size * HZ * 10 * quot) / info->baud_base); + info->timeout += HZ / 50; /* Add .02 seconds of slop */ + + if (quot) { + spin_lock_irqsave(&info->slock, flags); + info->MCR |= UART_MCR_DTR; + outb(info->MCR, info->ioaddr + UART_MCR); + spin_unlock_irqrestore(&info->slock, flags); + } else { + spin_lock_irqsave(&info->slock, flags); + info->MCR &= ~UART_MCR_DTR; + outb(info->MCR, info->ioaddr + UART_MCR); + spin_unlock_irqrestore(&info->slock, flags); + return ret; + } + + cval = inb(info->ioaddr + UART_LCR); + + outb(cval | UART_LCR_DLAB, info->ioaddr + UART_LCR); /* set DLAB */ + + outb(quot & 0xff, info->ioaddr + UART_DLL); /* LS of divisor */ + outb(quot >> 8, info->ioaddr + UART_DLM); /* MS of divisor */ + outb(cval, info->ioaddr + UART_LCR); /* reset DLAB */ + + + return ret; +} + +/* + * This routine is called to set the UART divisor registers to match + * the specified baud rate for a serial port. + */ +static int mxser_change_speed(struct mxser_port *info, + struct ktermios *old_termios) +{ + unsigned cflag, cval, fcr; + int ret = 0; + unsigned char status; + long baud; + unsigned long flags; + + if (!info->tty || !info->tty->termios) + return ret; + cflag = info->tty->termios->c_cflag; + if (!(info->ioaddr)) + return ret; + + if (mxser_set_baud_method[info->tty->index] == 0) { + baud = tty_get_baud_rate(info->tty); + mxser_set_baud(info, baud); + } + + /* byte size and parity */ + switch (cflag & CSIZE) { + case CS5: + cval = 0x00; + break; + case CS6: + cval = 0x01; + break; + case CS7: + cval = 0x02; + break; + case CS8: + cval = 0x03; + break; + default: + cval = 0x00; + break; /* too keep GCC shut... */ + } + if (cflag & CSTOPB) + cval |= 0x04; + if (cflag & PARENB) + cval |= UART_LCR_PARITY; + if (!(cflag & PARODD)) + cval |= UART_LCR_EPAR; + if (cflag & CMSPAR) + cval |= UART_LCR_SPAR; + + if ((info->type == PORT_8250) || (info->type == PORT_16450)) { + if (info->board->chip_flag) { + fcr = UART_FCR_ENABLE_FIFO; + fcr |= MOXA_MUST_FCR_GDA_MODE_ENABLE; + SET_MOXA_MUST_FIFO_VALUE(info); + } else + fcr = 0; + } else { + fcr = UART_FCR_ENABLE_FIFO; + if (info->board->chip_flag) { + fcr |= MOXA_MUST_FCR_GDA_MODE_ENABLE; + SET_MOXA_MUST_FIFO_VALUE(info); + } else { + switch (info->rx_trigger) { + case 1: + fcr |= UART_FCR_TRIGGER_1; + break; + case 4: + fcr |= UART_FCR_TRIGGER_4; + break; + case 8: + fcr |= UART_FCR_TRIGGER_8; + break; + default: + fcr |= UART_FCR_TRIGGER_14; + break; + } + } + } + + /* CTS flow control flag and modem status interrupts */ + info->IER &= ~UART_IER_MSI; + info->MCR &= ~UART_MCR_AFE; + if (cflag & CRTSCTS) { + info->flags |= ASYNC_CTS_FLOW; + info->IER |= UART_IER_MSI; + if ((info->type == PORT_16550A) || (info->board->chip_flag)) { + info->MCR |= UART_MCR_AFE; + } else { + status = inb(info->ioaddr + UART_MSR); + if (info->tty->hw_stopped) { + if (status & UART_MSR_CTS) { + info->tty->hw_stopped = 0; + if (info->type != PORT_16550A && + !info->board->chip_flag) { + outb(info->IER & ~UART_IER_THRI, + info->ioaddr + + UART_IER); + info->IER |= UART_IER_THRI; + outb(info->IER, info->ioaddr + + UART_IER); + } + set_bit(MXSER_EVENT_TXLOW, &info->event); + schedule_work(&info->tqueue); } + } else { + if (!(status & UART_MSR_CTS)) { + info->tty->hw_stopped = 1; + if ((info->type != PORT_16550A) && + (!info->board->chip_flag)) { + info->IER &= ~UART_IER_THRI; + outb(info->IER, info->ioaddr + + UART_IER); + } + } + } + } + } else { + info->flags &= ~ASYNC_CTS_FLOW; + } + outb(info->MCR, info->ioaddr + UART_MCR); + if (cflag & CLOCAL) { + info->flags &= ~ASYNC_CHECK_CD; + } else { + info->flags |= ASYNC_CHECK_CD; + info->IER |= UART_IER_MSI; + } + outb(info->IER, info->ioaddr + UART_IER); + + /* + * Set up parity check flag + */ + info->read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR; + if (I_INPCK(info->tty)) + info->read_status_mask |= UART_LSR_FE | UART_LSR_PE; + if (I_BRKINT(info->tty) || I_PARMRK(info->tty)) + info->read_status_mask |= UART_LSR_BI; + + info->ignore_status_mask = 0; + + if (I_IGNBRK(info->tty)) { + info->ignore_status_mask |= UART_LSR_BI; + info->read_status_mask |= UART_LSR_BI; + /* + * If we're ignore parity and break indicators, ignore + * overruns too. (For real raw support). + */ + if (I_IGNPAR(info->tty)) { + info->ignore_status_mask |= + UART_LSR_OE | + UART_LSR_PE | + UART_LSR_FE; + info->read_status_mask |= + UART_LSR_OE | + UART_LSR_PE | + UART_LSR_FE; + } + } + if (info->board->chip_flag) { + spin_lock_irqsave(&info->slock, flags); + SET_MOXA_MUST_XON1_VALUE(info->ioaddr, START_CHAR(info->tty)); + SET_MOXA_MUST_XOFF1_VALUE(info->ioaddr, STOP_CHAR(info->tty)); + if (I_IXON(info->tty)) { + ENABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(info->ioaddr); + } else { + DISABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(info->ioaddr); + } + if (I_IXOFF(info->tty)) { + ENABLE_MOXA_MUST_TX_SOFTWARE_FLOW_CONTROL(info->ioaddr); + } else { + DISABLE_MOXA_MUST_TX_SOFTWARE_FLOW_CONTROL(info->ioaddr); + } + spin_unlock_irqrestore(&info->slock, flags); + } + + + outb(fcr, info->ioaddr + UART_FCR); /* set fcr */ + outb(cval, info->ioaddr + UART_LCR); + + return ret; +} + +static void mxser_check_modem_status(struct mxser_port *port, int status) +{ + /* update input line counters */ + if (status & UART_MSR_TERI) + port->icount.rng++; + if (status & UART_MSR_DDSR) + port->icount.dsr++; + if (status & UART_MSR_DDCD) + port->icount.dcd++; + if (status & UART_MSR_DCTS) + port->icount.cts++; + port->mon_data.modem_status = status; + wake_up_interruptible(&port->delta_msr_wait); + + if ((port->flags & ASYNC_CHECK_CD) && (status & UART_MSR_DDCD)) { + if (status & UART_MSR_DCD) + wake_up_interruptible(&port->open_wait); + schedule_work(&port->tqueue); + } + + if (port->flags & ASYNC_CTS_FLOW) { + if (port->tty->hw_stopped) { + if (status & UART_MSR_CTS) { + port->tty->hw_stopped = 0; + + if ((port->type != PORT_16550A) && + (!port->board->chip_flag)) { + outb(port->IER & ~UART_IER_THRI, + port->ioaddr + UART_IER); + port->IER |= UART_IER_THRI; + outb(port->IER, port->ioaddr + + UART_IER); + } + set_bit(MXSER_EVENT_TXLOW, &port->event); + schedule_work(&port->tqueue); + } + } else { + if (!(status & UART_MSR_CTS)) { + port->tty->hw_stopped = 1; + if (port->type != PORT_16550A && + !port->board->chip_flag) { + port->IER &= ~UART_IER_THRI; + outb(port->IER, port->ioaddr + + UART_IER); + } + } + } + } +} + +static int mxser_startup(struct mxser_port *info) +{ + unsigned long page; + unsigned long flags; + + page = __get_free_page(GFP_KERNEL); + if (!page) + return -ENOMEM; + + spin_lock_irqsave(&info->slock, flags); + + if (info->flags & ASYNC_INITIALIZED) { + free_page(page); + spin_unlock_irqrestore(&info->slock, flags); + return 0; + } + + if (!info->ioaddr || !info->type) { + if (info->tty) + set_bit(TTY_IO_ERROR, &info->tty->flags); + free_page(page); + spin_unlock_irqrestore(&info->slock, flags); + return 0; + } + if (info->xmit_buf) + free_page(page); + else + info->xmit_buf = (unsigned char *) page; + + /* + * Clear the FIFO buffers and disable them + * (they will be reenabled in mxser_change_speed()) + */ + if (info->board->chip_flag) + outb((UART_FCR_CLEAR_RCVR | + UART_FCR_CLEAR_XMIT | + MOXA_MUST_FCR_GDA_MODE_ENABLE), info->ioaddr + UART_FCR); + else + outb((UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT), + info->ioaddr + UART_FCR); + + /* + * At this point there's no way the LSR could still be 0xFF; + * if it is, then bail out, because there's likely no UART + * here. + */ + if (inb(info->ioaddr + UART_LSR) == 0xff) { + spin_unlock_irqrestore(&info->slock, flags); + if (capable(CAP_SYS_ADMIN)) { + if (info->tty) + set_bit(TTY_IO_ERROR, &info->tty->flags); + return 0; + } else + return -ENODEV; + } + + /* + * Clear the interrupt registers. + */ + (void) inb(info->ioaddr + UART_LSR); + (void) inb(info->ioaddr + UART_RX); + (void) inb(info->ioaddr + UART_IIR); + (void) inb(info->ioaddr + UART_MSR); + + /* + * Now, initialize the UART + */ + outb(UART_LCR_WLEN8, info->ioaddr + UART_LCR); /* reset DLAB */ + info->MCR = UART_MCR_DTR | UART_MCR_RTS; + outb(info->MCR, info->ioaddr + UART_MCR); + + /* + * Finally, enable interrupts + */ + info->IER = UART_IER_MSI | UART_IER_RLSI | UART_IER_RDI; + + if (info->board->chip_flag) + info->IER |= MOXA_MUST_IER_EGDAI; + outb(info->IER, info->ioaddr + UART_IER); /* enable interrupts */ + + /* + * And clear the interrupt registers again for luck. + */ + (void) inb(info->ioaddr + UART_LSR); + (void) inb(info->ioaddr + UART_RX); + (void) inb(info->ioaddr + UART_IIR); + (void) inb(info->ioaddr + UART_MSR); + + if (info->tty) + clear_bit(TTY_IO_ERROR, &info->tty->flags); + info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; + + /* + * and set the speed of the serial port + */ + spin_unlock_irqrestore(&info->slock, flags); + mxser_change_speed(info, NULL); + + info->flags |= ASYNC_INITIALIZED; + return 0; +} + +/* + * This routine will shutdown a serial port; interrupts maybe disabled, and + * DTR is dropped if the hangup on close termio flag is on. + */ +static void mxser_shutdown(struct mxser_port *info) +{ + unsigned long flags; + + if (!(info->flags & ASYNC_INITIALIZED)) + return; + + spin_lock_irqsave(&info->slock, flags); + + /* + * clear delta_msr_wait queue to avoid mem leaks: we may free the irq + * here so the queue might never be waken up + */ + wake_up_interruptible(&info->delta_msr_wait); + + /* + * Free the IRQ, if necessary + */ + if (info->xmit_buf) { + free_page((unsigned long) info->xmit_buf); + info->xmit_buf = NULL; + } + + info->IER = 0; + outb(0x00, info->ioaddr + UART_IER); + + if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) + info->MCR &= ~(UART_MCR_DTR | UART_MCR_RTS); + outb(info->MCR, info->ioaddr + UART_MCR); + + /* clear Rx/Tx FIFO's */ + if (info->board->chip_flag) + outb(UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT | + MOXA_MUST_FCR_GDA_MODE_ENABLE, + info->ioaddr + UART_FCR); + else + outb(UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT, + info->ioaddr + UART_FCR); + + /* read data port to reset things */ + (void) inb(info->ioaddr + UART_RX); + + if (info->tty) + set_bit(TTY_IO_ERROR, &info->tty->flags); + + info->flags &= ~ASYNC_INITIALIZED; + + if (info->board->chip_flag) + SET_MOXA_MUST_NO_SOFTWARE_FLOW_CONTROL(info->ioaddr); + + spin_unlock_irqrestore(&info->slock, flags); +} + +/* + * This routine is called whenever a serial port is opened. It + * enables interrupts for a serial port, linking in its async structure into + * the IRQ chain. It also performs the serial-specific + * initialization for the tty structure. + */ +static int mxser_open(struct tty_struct *tty, struct file *filp) +{ + struct mxser_port *info; + int retval, line; + + /* initialize driver_data in case something fails */ + tty->driver_data = NULL; + + line = tty->index; + if (line == MXSER_PORTS) + return 0; + if (line < 0 || line > MXSER_PORTS) + return -ENODEV; + info = &mxser_boards[line / MXSER_PORTS_PER_BOARD].ports[line % MXSER_PORTS_PER_BOARD]; + if (!info->ioaddr) + return -ENODEV; + + tty->driver_data = info; + info->tty = tty; + /* + * Start up serial port + */ + info->count++; + retval = mxser_startup(info); + if (retval) + return retval; + + retval = mxser_block_til_ready(tty, filp, info); + if (retval) + return retval; + + if ((info->count == 1) && (info->flags & ASYNC_SPLIT_TERMIOS)) { + if (tty->driver->subtype == SERIAL_TYPE_NORMAL) + *tty->termios = info->normal_termios; + else + *tty->termios = info->callout_termios; + mxser_change_speed(info, NULL); + } + + info->session = process_session(current); + info->pgrp = process_group(current); + + /* unmark here for very high baud rate (ex. 921600 bps) used */ + tty->low_latency = 1; + return 0; +} + +/* + * This routine is called when the serial port gets closed. First, we + * wait for the last remaining data to be sent. Then, we unlink its + * async structure from the interrupt chain if necessary, and we free + * that IRQ if nothing is left in the chain. + */ +static void mxser_close(struct tty_struct *tty, struct file *filp) +{ + struct mxser_port *info = tty->driver_data; + + unsigned long timeout; + unsigned long flags; + + if (tty->index == MXSER_PORTS) + return; + if (!info) + return; + + spin_lock_irqsave(&info->slock, flags); + + if (tty_hung_up_p(filp)) { + spin_unlock_irqrestore(&info->slock, flags); + return; + } + if ((tty->count == 1) && (info->count != 1)) { + /* + * Uh, oh. tty->count is 1, which means that the tty + * structure will be freed. Info->count should always + * be one in these conditions. If it's greater than + * one, we've got real problems, since it means the + * serial port won't be shutdown. + */ + printk(KERN_ERR "mxser_close: bad serial port count; " + "tty->count is 1, info->count is %d\n", info->count); + info->count = 1; + } + if (--info->count < 0) { + printk(KERN_ERR "mxser_close: bad serial port count for " + "ttys%d: %d\n", tty->index, info->count); + info->count = 0; + } + if (info->count) { + spin_unlock_irqrestore(&info->slock, flags); + return; + } + info->flags |= ASYNC_CLOSING; + spin_unlock_irqrestore(&info->slock, flags); + /* + * Save the termios structure, since this port may have + * separate termios for callout and dialin. + */ + if (info->flags & ASYNC_NORMAL_ACTIVE) + info->normal_termios = *tty->termios; + /* + * Now we wait for the transmit buffer to clear; and we notify + * the line discipline to only process XON/XOFF characters. + */ + tty->closing = 1; + if (info->closing_wait != ASYNC_CLOSING_WAIT_NONE) + tty_wait_until_sent(tty, info->closing_wait); + /* + * At this point we stop accepting input. To do this, we + * disable the receive line status interrupts, and tell the + * interrupt driver to stop checking the data ready bit in the + * line status register. + */ + info->IER &= ~UART_IER_RLSI; + if (info->board->chip_flag) + info->IER &= ~MOXA_MUST_RECV_ISR; + + if (info->flags & ASYNC_INITIALIZED) { + outb(info->IER, info->ioaddr + UART_IER); + /* + * Before we drop DTR, make sure the UART transmitter + * has completely drained; this is especially + * important if there is a transmit FIFO! + */ + timeout = jiffies + HZ; + while (!(inb(info->ioaddr + UART_LSR) & UART_LSR_TEMT)) { + schedule_timeout_interruptible(5); + if (time_after(jiffies, timeout)) + break; + } + } + mxser_shutdown(info); + + if (tty->driver->flush_buffer) + tty->driver->flush_buffer(tty); + + tty_ldisc_flush(tty); + + tty->closing = 0; + info->event = 0; + info->tty = NULL; + if (info->blocked_open) { + if (info->close_delay) + schedule_timeout_interruptible(info->close_delay); + wake_up_interruptible(&info->open_wait); + } + + info->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING); + wake_up_interruptible(&info->close_wait); + +} + +static int mxser_write(struct tty_struct *tty, const unsigned char *buf, int count) +{ + int c, total = 0; + struct mxser_port *info = tty->driver_data; + unsigned long flags; + + if (!info->xmit_buf) + return 0; + + while (1) { + c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, + SERIAL_XMIT_SIZE - info->xmit_head)); + if (c <= 0) + break; + + memcpy(info->xmit_buf + info->xmit_head, buf, c); + spin_lock_irqsave(&info->slock, flags); + info->xmit_head = (info->xmit_head + c) & + (SERIAL_XMIT_SIZE - 1); + info->xmit_cnt += c; + spin_unlock_irqrestore(&info->slock, flags); + + buf += c; + count -= c; + total += c; + } + + if (info->xmit_cnt && !tty->stopped) { + if (!tty->hw_stopped || + (info->type == PORT_16550A) || + (info->board->chip_flag)) { + spin_lock_irqsave(&info->slock, flags); + outb(info->IER & ~UART_IER_THRI, info->ioaddr + + UART_IER); + info->IER |= UART_IER_THRI; + outb(info->IER, info->ioaddr + UART_IER); + spin_unlock_irqrestore(&info->slock, flags); + } + } + return total; +} + +static void mxser_put_char(struct tty_struct *tty, unsigned char ch) +{ + struct mxser_port *info = tty->driver_data; + unsigned long flags; + + if (!info->xmit_buf) + return; + + if (info->xmit_cnt >= SERIAL_XMIT_SIZE - 1) + return; + + spin_lock_irqsave(&info->slock, flags); + info->xmit_buf[info->xmit_head++] = ch; + info->xmit_head &= SERIAL_XMIT_SIZE - 1; + info->xmit_cnt++; + spin_unlock_irqrestore(&info->slock, flags); + if (!tty->stopped) { + if (!tty->hw_stopped || + (info->type == PORT_16550A) || + info->board->chip_flag) { + spin_lock_irqsave(&info->slock, flags); + outb(info->IER & ~UART_IER_THRI, info->ioaddr + UART_IER); + info->IER |= UART_IER_THRI; + outb(info->IER, info->ioaddr + UART_IER); + spin_unlock_irqrestore(&info->slock, flags); + } + } +} + + +static void mxser_flush_chars(struct tty_struct *tty) +{ + struct mxser_port *info = tty->driver_data; + unsigned long flags; + + if (info->xmit_cnt <= 0 || + tty->stopped || + !info->xmit_buf || + (tty->hw_stopped && + (info->type != PORT_16550A) && + (!info->board->chip_flag) + )) + return; + + spin_lock_irqsave(&info->slock, flags); + + outb(info->IER & ~UART_IER_THRI, info->ioaddr + UART_IER); + info->IER |= UART_IER_THRI; + outb(info->IER, info->ioaddr + UART_IER); + + spin_unlock_irqrestore(&info->slock, flags); +} + +static int mxser_write_room(struct tty_struct *tty) +{ + struct mxser_port *info = tty->driver_data; + int ret; + + ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1; + if (ret < 0) + ret = 0; + return ret; +} + +static int mxser_chars_in_buffer(struct tty_struct *tty) +{ + struct mxser_port *info = tty->driver_data; + return info->xmit_cnt; +} + +static void mxser_flush_buffer(struct tty_struct *tty) +{ + struct mxser_port *info = tty->driver_data; + char fcr; + unsigned long flags; + + + spin_lock_irqsave(&info->slock, flags); + info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; + + fcr = inb(info->ioaddr + UART_FCR); + outb((fcr | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT), + info->ioaddr + UART_FCR); + outb(fcr, info->ioaddr + UART_FCR); + + spin_unlock_irqrestore(&info->slock, flags); + + tty_wakeup(tty); +} + +/* + * ------------------------------------------------------------ + * friends of mxser_ioctl() + * ------------------------------------------------------------ + */ +static int mxser_get_serial_info(struct mxser_port *info, + struct serial_struct __user *retinfo) +{ + struct serial_struct tmp; + + if (!retinfo) + return -EFAULT; + memset(&tmp, 0, sizeof(tmp)); + tmp.type = info->type; + tmp.line = info->tty->index; + tmp.port = info->ioaddr; + tmp.irq = info->board->irq; + tmp.flags = info->flags; + tmp.baud_base = info->baud_base; + tmp.close_delay = info->close_delay; + tmp.closing_wait = info->closing_wait; + tmp.custom_divisor = info->custom_divisor; + tmp.hub6 = 0; + if (copy_to_user(retinfo, &tmp, sizeof(*retinfo))) + return -EFAULT; + return 0; +} + +static int mxser_set_serial_info(struct mxser_port *info, + struct serial_struct __user *new_info) +{ + struct serial_struct new_serial; + unsigned int flags; + int retval = 0; + + if (!new_info || !info->ioaddr) + return -EFAULT; + if (copy_from_user(&new_serial, new_info, sizeof(new_serial))) + return -EFAULT; + + if ((new_serial.irq != info->board->irq) || + (new_serial.port != info->ioaddr) || + (new_serial.custom_divisor != info->custom_divisor) || + (new_serial.baud_base != info->baud_base)) + return -EPERM; + + flags = info->flags & ASYNC_SPD_MASK; + + if (!capable(CAP_SYS_ADMIN)) { + if ((new_serial.baud_base != info->baud_base) || + (new_serial.close_delay != info->close_delay) || + ((new_serial.flags & ~ASYNC_USR_MASK) != (info->flags & ~ASYNC_USR_MASK))) + return -EPERM; + info->flags = ((info->flags & ~ASYNC_USR_MASK) | + (new_serial.flags & ASYNC_USR_MASK)); + } else { + /* + * OK, past this point, all the error checking has been done. + * At this point, we start making changes..... + */ + info->flags = ((info->flags & ~ASYNC_FLAGS) | + (new_serial.flags & ASYNC_FLAGS)); + info->close_delay = new_serial.close_delay * HZ / 100; + info->closing_wait = new_serial.closing_wait * HZ / 100; + info->tty->low_latency = + (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; + info->tty->low_latency = 0; + } + + info->type = new_serial.type; + + process_txrx_fifo(info); + + if (info->flags & ASYNC_INITIALIZED) { + if (flags != (info->flags & ASYNC_SPD_MASK)) + mxser_change_speed(info, NULL); + } else + retval = mxser_startup(info); + + return retval; +} + +/* + * mxser_get_lsr_info - get line status register info + * + * Purpose: Let user call ioctl() to get info when the UART physically + * is emptied. On bus types like RS485, the transmitter must + * release the bus after transmitting. This must be done when + * the transmit shift register is empty, not be done when the + * transmit holding register is empty. This functionality + * allows an RS485 driver to be written in user space. + */ +static int mxser_get_lsr_info(struct mxser_port *info, + unsigned int __user *value) +{ + unsigned char status; + unsigned int result; + unsigned long flags; + + spin_lock_irqsave(&info->slock, flags); + status = inb(info->ioaddr + UART_LSR); + spin_unlock_irqrestore(&info->slock, flags); + result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0); + return put_user(result, value); +} + +/* + * This routine sends a break character out the serial port. + */ +static void mxser_send_break(struct mxser_port *info, int duration) +{ + unsigned long flags; + + if (!info->ioaddr) + return; + set_current_state(TASK_INTERRUPTIBLE); + spin_lock_irqsave(&info->slock, flags); + outb(inb(info->ioaddr + UART_LCR) | UART_LCR_SBC, + info->ioaddr + UART_LCR); + spin_unlock_irqrestore(&info->slock, flags); + schedule_timeout(duration); + spin_lock_irqsave(&info->slock, flags); + outb(inb(info->ioaddr + UART_LCR) & ~UART_LCR_SBC, + info->ioaddr + UART_LCR); + spin_unlock_irqrestore(&info->slock, flags); +} + +static int mxser_tiocmget(struct tty_struct *tty, struct file *file) +{ + struct mxser_port *info = tty->driver_data; + unsigned char control, status; + unsigned long flags; + + + if (tty->index == MXSER_PORTS) + return -ENOIOCTLCMD; + if (test_bit(TTY_IO_ERROR, &tty->flags)) + return -EIO; + + control = info->MCR; + + spin_lock_irqsave(&info->slock, flags); + status = inb(info->ioaddr + UART_MSR); + if (status & UART_MSR_ANY_DELTA) + mxser_check_modem_status(info, status); + spin_unlock_irqrestore(&info->slock, flags); + return ((control & UART_MCR_RTS) ? TIOCM_RTS : 0) | + ((control & UART_MCR_DTR) ? TIOCM_DTR : 0) | + ((status & UART_MSR_DCD) ? TIOCM_CAR : 0) | + ((status & UART_MSR_RI) ? TIOCM_RNG : 0) | + ((status & UART_MSR_DSR) ? TIOCM_DSR : 0) | + ((status & UART_MSR_CTS) ? TIOCM_CTS : 0); +} + +static int mxser_tiocmset(struct tty_struct *tty, struct file *file, + unsigned int set, unsigned int clear) +{ + struct mxser_port *info = tty->driver_data; + unsigned long flags; + + + if (tty->index == MXSER_PORTS) + return -ENOIOCTLCMD; + if (test_bit(TTY_IO_ERROR, &tty->flags)) + return -EIO; + + spin_lock_irqsave(&info->slock, flags); + + if (set & TIOCM_RTS) + info->MCR |= UART_MCR_RTS; + if (set & TIOCM_DTR) + info->MCR |= UART_MCR_DTR; + + if (clear & TIOCM_RTS) + info->MCR &= ~UART_MCR_RTS; + if (clear & TIOCM_DTR) + info->MCR &= ~UART_MCR_DTR; + + outb(info->MCR, info->ioaddr + UART_MCR); + spin_unlock_irqrestore(&info->slock, flags); + return 0; +} + +static int mxser_program_mode(int port) +{ + int id, i, j, n; + + spin_lock(&gm_lock); + outb(0, port); + outb(0, port); + outb(0, port); + (void)inb(port); + (void)inb(port); + outb(0, port); + (void)inb(port); + spin_unlock(&gm_lock); + + id = inb(port + 1) & 0x1F; + if ((id != C168_ASIC_ID) && + (id != C104_ASIC_ID) && + (id != C102_ASIC_ID) && + (id != CI132_ASIC_ID) && + (id != CI134_ASIC_ID) && + (id != CI104J_ASIC_ID)) + return -1; + for (i = 0, j = 0; i < 4; i++) { + n = inb(port + 2); + if (n == 'M') { + j = 1; + } else if ((j == 1) && (n == 1)) { + j = 2; + break; + } else + j = 0; + } + if (j != 2) + id = -2; + return id; +} + +static void mxser_normal_mode(int port) +{ + int i, n; + + outb(0xA5, port + 1); + outb(0x80, port + 3); + outb(12, port + 0); /* 9600 bps */ + outb(0, port + 1); + outb(0x03, port + 3); /* 8 data bits */ + outb(0x13, port + 4); /* loop back mode */ + for (i = 0; i < 16; i++) { + n = inb(port + 5); + if ((n & 0x61) == 0x60) + break; + if ((n & 1) == 1) + (void)inb(port); + } + outb(0x00, port + 4); +} + +#define CHIP_SK 0x01 /* Serial Data Clock in Eprom */ +#define CHIP_DO 0x02 /* Serial Data Output in Eprom */ +#define CHIP_CS 0x04 /* Serial Chip Select in Eprom */ +#define CHIP_DI 0x08 /* Serial Data Input in Eprom */ +#define EN_CCMD 0x000 /* Chip's command register */ +#define EN0_RSARLO 0x008 /* Remote start address reg 0 */ +#define EN0_RSARHI 0x009 /* Remote start address reg 1 */ +#define EN0_RCNTLO 0x00A /* Remote byte count reg WR */ +#define EN0_RCNTHI 0x00B /* Remote byte count reg WR */ +#define EN0_DCFG 0x00E /* Data configuration reg WR */ +#define EN0_PORT 0x010 /* Rcv missed frame error counter RD */ +#define ENC_PAGE0 0x000 /* Select page 0 of chip registers */ +#define ENC_PAGE3 0x0C0 /* Select page 3 of chip registers */ +static int mxser_read_register(int port, unsigned short *regs) +{ + int i, k, value, id; + unsigned int j; + + id = mxser_program_mode(port); + if (id < 0) + return id; + for (i = 0; i < 14; i++) { + k = (i & 0x3F) | 0x180; + for (j = 0x100; j > 0; j >>= 1) { + outb(CHIP_CS, port); + if (k & j) { + outb(CHIP_CS | CHIP_DO, port); + outb(CHIP_CS | CHIP_DO | CHIP_SK, port); /* A? bit of read */ + } else { + outb(CHIP_CS, port); + outb(CHIP_CS | CHIP_SK, port); /* A? bit of read */ + } + } + (void)inb(port); + value = 0; + for (k = 0, j = 0x8000; k < 16; k++, j >>= 1) { + outb(CHIP_CS, port); + outb(CHIP_CS | CHIP_SK, port); + if (inb(port) & CHIP_DI) + value |= j; + } + regs[i] = value; + outb(0, port); + } + mxser_normal_mode(port); + return id; +} + +static int mxser_ioctl_special(unsigned int cmd, void __user *argp) +{ + struct mxser_port *port; + int result, status; + unsigned int i, j; + + switch (cmd) { + case MOXA_GET_CONF: +/* if (copy_to_user(argp, mxsercfg, + sizeof(struct mxser_hwconf) * 4)) + return -EFAULT; + return 0;*/ + return -ENXIO; + case MOXA_GET_MAJOR: + if (copy_to_user(argp, &ttymajor, sizeof(int))) + return -EFAULT; + return 0; + + case MOXA_GET_CUMAJOR: + if (copy_to_user(argp, &calloutmajor, sizeof(int))) + return -EFAULT; + return 0; + + case MOXA_CHKPORTENABLE: + result = 0; + + for (i = 0; i < MXSER_BOARDS; i++) + for (j = 0; j < MXSER_PORTS_PER_BOARD; j++) + if (mxser_boards[i].ports[j].ioaddr) + result |= (1 << i); + + return put_user(result, (unsigned long __user *)argp); + case MOXA_GETDATACOUNT: + if (copy_to_user(argp, &mxvar_log, sizeof(mxvar_log))) + return -EFAULT; + return 0; + case MOXA_GETMSTATUS: + for (i = 0; i < MXSER_BOARDS; i++) + for (j = 0; j < MXSER_PORTS_PER_BOARD; j++) { + port = &mxser_boards[i].ports[j]; + + GMStatus[i].ri = 0; + if (!port->ioaddr) { + GMStatus[i].dcd = 0; + GMStatus[i].dsr = 0; + GMStatus[i].cts = 0; + continue; + } + + if (!port->tty || !port->tty->termios) + GMStatus[i].cflag = + port->normal_termios.c_cflag; + else + GMStatus[i].cflag = + port->tty->termios->c_cflag; + + status = inb(port->ioaddr + UART_MSR); + if (status & 0x80 /*UART_MSR_DCD */ ) + GMStatus[i].dcd = 1; + else + GMStatus[i].dcd = 0; + + if (status & 0x20 /*UART_MSR_DSR */ ) + GMStatus[i].dsr = 1; + else + GMStatus[i].dsr = 0; + + + if (status & 0x10 /*UART_MSR_CTS */ ) + GMStatus[i].cts = 1; + else + GMStatus[i].cts = 0; + } + if (copy_to_user(argp, GMStatus, + sizeof(struct mxser_mstatus) * MXSER_PORTS)) + return -EFAULT; + return 0; + case MOXA_ASPP_MON_EXT: { + int status, p, shiftbit; + unsigned long opmode; + unsigned cflag, iflag; + + for (i = 0; i < MXSER_BOARDS; i++) + for (j = 0; j < MXSER_PORTS_PER_BOARD; j++) { + port = &mxser_boards[i].ports[j]; + if (!port->ioaddr) + continue; + + status = mxser_get_msr(port->ioaddr, 0, i); + + if (status & UART_MSR_TERI) + port->icount.rng++; + if (status & UART_MSR_DDSR) + port->icount.dsr++; + if (status & UART_MSR_DDCD) + port->icount.dcd++; + if (status & UART_MSR_DCTS) + port->icount.cts++; + + port->mon_data.modem_status = status; + mon_data_ext.rx_cnt[i] = port->mon_data.rxcnt; + mon_data_ext.tx_cnt[i] = port->mon_data.txcnt; + mon_data_ext.up_rxcnt[i] = + port->mon_data.up_rxcnt; + mon_data_ext.up_txcnt[i] = + port->mon_data.up_txcnt; + mon_data_ext.modem_status[i] = + port->mon_data.modem_status; + mon_data_ext.baudrate[i] = port->realbaud; + + if (!port->tty || !port->tty->termios) { + cflag = port->normal_termios.c_cflag; + iflag = port->normal_termios.c_iflag; + } else { + cflag = port->tty->termios->c_cflag; + iflag = port->tty->termios->c_iflag; + } + + mon_data_ext.databits[i] = cflag & CSIZE; + + mon_data_ext.stopbits[i] = cflag & CSTOPB; + + mon_data_ext.parity[i] = + cflag & (PARENB | PARODD | CMSPAR); + + mon_data_ext.flowctrl[i] = 0x00; + + if (cflag & CRTSCTS) + mon_data_ext.flowctrl[i] |= 0x03; + + if (iflag & (IXON | IXOFF)) + mon_data_ext.flowctrl[i] |= 0x0C; + + if (port->type == PORT_16550A) + mon_data_ext.fifo[i] = 1; + else + mon_data_ext.fifo[i] = 0; + + p = i % 4; + shiftbit = p * 2; + opmode = inb(port->opmode_ioaddr) >> shiftbit; + opmode &= OP_MODE_MASK; + + mon_data_ext.iftype[i] = opmode; + + } + if (copy_to_user(argp, &mon_data_ext, + sizeof(mon_data_ext))) + return -EFAULT; + + return 0; + + } default: + return -ENOIOCTLCMD; + } + return 0; +} + +static int mxser_ioctl(struct tty_struct *tty, struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct mxser_port *info = tty->driver_data; + struct async_icount cprev, cnow; /* kernel counter temps */ + struct serial_icounter_struct __user *p_cuser; + unsigned long templ; + unsigned long flags; + void __user *argp = (void __user *)arg; + int retval; + + if (tty->index == MXSER_PORTS) + return mxser_ioctl_special(cmd, argp); + + if (cmd == MOXA_SET_OP_MODE || cmd == MOXA_GET_OP_MODE) { + int p; + unsigned long opmode; + static unsigned char ModeMask[] = { 0xfc, 0xf3, 0xcf, 0x3f }; + int shiftbit; + unsigned char val, mask; + + p = tty->index % 4; + if (cmd == MOXA_SET_OP_MODE) { + if (get_user(opmode, (int __user *) argp)) + return -EFAULT; + if (opmode != RS232_MODE && + opmode != RS485_2WIRE_MODE && + opmode != RS422_MODE && + opmode != RS485_4WIRE_MODE) + return -EFAULT; + mask = ModeMask[p]; + shiftbit = p * 2; + val = inb(info->opmode_ioaddr); + val &= mask; + val |= (opmode << shiftbit); + outb(val, info->opmode_ioaddr); + } else { + shiftbit = p * 2; + opmode = inb(info->opmode_ioaddr) >> shiftbit; + opmode &= OP_MODE_MASK; + if (copy_to_user(argp, &opmode, sizeof(int))) + return -EFAULT; + } + return 0; + } + + if (cmd != TIOCGSERIAL && cmd != TIOCMIWAIT && cmd != TIOCGICOUNT && + test_bit(TTY_IO_ERROR, &tty->flags)) + return -EIO; + + switch (cmd) { + case TCSBRK: /* SVID version: non-zero arg --> no break */ + retval = tty_check_change(tty); + if (retval) + return retval; + tty_wait_until_sent(tty, 0); + if (!arg) + mxser_send_break(info, HZ / 4); /* 1/4 second */ + return 0; + case TCSBRKP: /* support for POSIX tcsendbreak() */ + retval = tty_check_change(tty); + if (retval) + return retval; + tty_wait_until_sent(tty, 0); + mxser_send_break(info, arg ? arg * (HZ / 10) : HZ / 4); + return 0; + case TIOCGSOFTCAR: + return put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long __user *)argp); + case TIOCSSOFTCAR: + if (get_user(templ, (unsigned long __user *) argp)) + return -EFAULT; + arg = templ; + tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) | (arg ? CLOCAL : 0)); + return 0; + case TIOCGSERIAL: + return mxser_get_serial_info(info, argp); + case TIOCSSERIAL: + return mxser_set_serial_info(info, argp); + case TIOCSERGETLSR: /* Get line status register */ + return mxser_get_lsr_info(info, argp); + /* + * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change + * - mask passed in arg for lines of interest + * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking) + * Caller should use TIOCGICOUNT to see which one it was + */ + case TIOCMIWAIT: { + DECLARE_WAITQUEUE(wait, current); + int ret; + spin_lock_irqsave(&info->slock, flags); + cprev = info->icount; /* note the counters on entry */ + spin_unlock_irqrestore(&info->slock, flags); + + add_wait_queue(&info->delta_msr_wait, &wait); + while (1) { + spin_lock_irqsave(&info->slock, flags); + cnow = info->icount; /* atomic copy */ + spin_unlock_irqrestore(&info->slock, flags); + + set_current_state(TASK_INTERRUPTIBLE); + if (((arg & TIOCM_RNG) && + (cnow.rng != cprev.rng)) || + ((arg & TIOCM_DSR) && + (cnow.dsr != cprev.dsr)) || + ((arg & TIOCM_CD) && + (cnow.dcd != cprev.dcd)) || + ((arg & TIOCM_CTS) && + (cnow.cts != cprev.cts))) { + ret = 0; + break; + } + /* see if a signal did it */ + if (signal_pending(current)) { + ret = -ERESTARTSYS; + break; + } + cprev = cnow; + } + current->state = TASK_RUNNING; + remove_wait_queue(&info->delta_msr_wait, &wait); + break; + } + /* NOTREACHED */ + /* + * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) + * Return: write counters to the user passed counter struct + * NB: both 1->0 and 0->1 transitions are counted except for + * RI where only 0->1 is counted. + */ + case TIOCGICOUNT: + spin_lock_irqsave(&info->slock, flags); + cnow = info->icount; + spin_unlock_irqrestore(&info->slock, flags); + p_cuser = argp; + if (put_user(cnow.frame, &p_cuser->frame)) + return -EFAULT; + if (put_user(cnow.brk, &p_cuser->brk)) + return -EFAULT; + if (put_user(cnow.overrun, &p_cuser->overrun)) + return -EFAULT; + if (put_user(cnow.buf_overrun, &p_cuser->buf_overrun)) + return -EFAULT; + if (put_user(cnow.parity, &p_cuser->parity)) + return -EFAULT; + if (put_user(cnow.rx, &p_cuser->rx)) + return -EFAULT; + if (put_user(cnow.tx, &p_cuser->tx)) + return -EFAULT; + put_user(cnow.cts, &p_cuser->cts); + put_user(cnow.dsr, &p_cuser->dsr); + put_user(cnow.rng, &p_cuser->rng); + put_user(cnow.dcd, &p_cuser->dcd); + return 0; + case MOXA_HighSpeedOn: + return put_user(info->baud_base != 115200 ? 1 : 0, (int __user *)argp); + case MOXA_SDS_RSTICOUNTER: + info->mon_data.rxcnt = 0; + info->mon_data.txcnt = 0; + return 0; + case MOXA_ASPP_SETBAUD:{ + long baud; + if (get_user(baud, (long __user *)argp)) + return -EFAULT; + mxser_set_baud(info, baud); + return 0; + } + case MOXA_ASPP_GETBAUD: + if (copy_to_user(argp, &info->realbaud, sizeof(long))) + return -EFAULT; + + return 0; + + case MOXA_ASPP_OQUEUE:{ + int len, lsr; + + len = mxser_chars_in_buffer(tty); + + lsr = inb(info->ioaddr + UART_LSR) & UART_LSR_TEMT; + + len += (lsr ? 0 : 1); + + if (copy_to_user(argp, &len, sizeof(int))) + return -EFAULT; + + return 0; + } + case MOXA_ASPP_MON: { + int mcr, status; + + status = mxser_get_msr(info->ioaddr, 1, tty->index); + mxser_check_modem_status(info, status); + + mcr = inb(info->ioaddr + UART_MCR); + if (mcr & MOXA_MUST_MCR_XON_FLAG) + info->mon_data.hold_reason &= ~NPPI_NOTIFY_XOFFHOLD; + else + info->mon_data.hold_reason |= NPPI_NOTIFY_XOFFHOLD; + + if (mcr & MOXA_MUST_MCR_TX_XON) + info->mon_data.hold_reason &= ~NPPI_NOTIFY_XOFFXENT; + else + info->mon_data.hold_reason |= NPPI_NOTIFY_XOFFXENT; + + if (info->tty->hw_stopped) + info->mon_data.hold_reason |= NPPI_NOTIFY_CTSHOLD; + else + info->mon_data.hold_reason &= ~NPPI_NOTIFY_CTSHOLD; + + if (copy_to_user(argp, &info->mon_data, + sizeof(struct mxser_mon))) + return -EFAULT; + + return 0; + } + case MOXA_ASPP_LSTATUS: { + if (copy_to_user(argp, &info->err_shadow, + sizeof(unsigned char))) + return -EFAULT; + + info->err_shadow = 0; + return 0; + } + case MOXA_SET_BAUD_METHOD: { + int method; + + if (get_user(method, (int __user *)argp)) + return -EFAULT; + mxser_set_baud_method[tty->index] = method; + if (copy_to_user(argp, &method, sizeof(int))) + return -EFAULT; + + return 0; + } + default: + return -ENOIOCTLCMD; + } + return 0; +} + +static void mxser_stoprx(struct tty_struct *tty) +{ + struct mxser_port *info = tty->driver_data; + + info->ldisc_stop_rx = 1; + if (I_IXOFF(tty)) { + if (info->board->chip_flag) { + info->IER &= ~MOXA_MUST_RECV_ISR; + outb(info->IER, info->ioaddr + UART_IER); + } else { + info->x_char = STOP_CHAR(tty); + outb(0, info->ioaddr + UART_IER); + info->IER |= UART_IER_THRI; + outb(info->IER, info->ioaddr + UART_IER); + } + } + + if (info->tty->termios->c_cflag & CRTSCTS) { + info->MCR &= ~UART_MCR_RTS; + outb(info->MCR, info->ioaddr + UART_MCR); + } +} + +/* + * This routine is called by the upper-layer tty layer to signal that + * incoming characters should be throttled. + */ +static void mxser_throttle(struct tty_struct *tty) +{ + mxser_stoprx(tty); +} + +static void mxser_unthrottle(struct tty_struct *tty) +{ + struct mxser_port *info = tty->driver_data; + + /* startrx */ + info->ldisc_stop_rx = 0; + if (I_IXOFF(tty)) { + if (info->x_char) + info->x_char = 0; + else { + if (info->board->chip_flag) { + info->IER |= MOXA_MUST_RECV_ISR; + outb(info->IER, info->ioaddr + UART_IER); + } else { + info->x_char = START_CHAR(tty); + outb(0, info->ioaddr + UART_IER); + info->IER |= UART_IER_THRI; + outb(info->IER, info->ioaddr + UART_IER); + } + } + } + + if (info->tty->termios->c_cflag & CRTSCTS) { + info->MCR |= UART_MCR_RTS; + outb(info->MCR, info->ioaddr + UART_MCR); + } +} + +/* + * mxser_stop() and mxser_start() + * + * This routines are called before setting or resetting tty->stopped. + * They enable or disable transmitter interrupts, as necessary. + */ +static void mxser_stop(struct tty_struct *tty) +{ + struct mxser_port *info = tty->driver_data; + unsigned long flags; + + spin_lock_irqsave(&info->slock, flags); + if (info->IER & UART_IER_THRI) { + info->IER &= ~UART_IER_THRI; + outb(info->IER, info->ioaddr + UART_IER); + } + spin_unlock_irqrestore(&info->slock, flags); +} + +static void mxser_start(struct tty_struct *tty) +{ + struct mxser_port *info = tty->driver_data; + unsigned long flags; + + spin_lock_irqsave(&info->slock, flags); + if (info->xmit_cnt && info->xmit_buf) { + outb(info->IER & ~UART_IER_THRI, info->ioaddr + UART_IER); + info->IER |= UART_IER_THRI; + outb(info->IER, info->ioaddr + UART_IER); + } + spin_unlock_irqrestore(&info->slock, flags); +} + +static void mxser_set_termios(struct tty_struct *tty, struct ktermios *old_termios) +{ + struct mxser_port *info = tty->driver_data; + unsigned long flags; + + if ((tty->termios->c_cflag != old_termios->c_cflag) || + (RELEVANT_IFLAG(tty->termios->c_iflag) != RELEVANT_IFLAG(old_termios->c_iflag))) { + + mxser_change_speed(info, old_termios); + + if ((old_termios->c_cflag & CRTSCTS) && + !(tty->termios->c_cflag & CRTSCTS)) { + tty->hw_stopped = 0; + mxser_start(tty); + } + } + + /* Handle sw stopped */ + if ((old_termios->c_iflag & IXON) && + !(tty->termios->c_iflag & IXON)) { + tty->stopped = 0; + + if (info->board->chip_flag) { + spin_lock_irqsave(&info->slock, flags); + DISABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(info->ioaddr); + spin_unlock_irqrestore(&info->slock, flags); + } + + mxser_start(tty); + } +} + +/* + * mxser_wait_until_sent() --- wait until the transmitter is empty + */ +static void mxser_wait_until_sent(struct tty_struct *tty, int timeout) +{ + struct mxser_port *info = tty->driver_data; + unsigned long orig_jiffies, char_time; + int lsr; + + if (info->type == PORT_UNKNOWN) + return; + + if (info->xmit_fifo_size == 0) + return; /* Just in case.... */ + + orig_jiffies = jiffies; + /* + * Set the check interval to be 1/5 of the estimated time to + * send a single character, and make it at least 1. The check + * interval should also be less than the timeout. + * + * Note: we have to use pretty tight timings here to satisfy + * the NIST-PCTS. + */ + char_time = (info->timeout - HZ / 50) / info->xmit_fifo_size; + char_time = char_time / 5; + if (char_time == 0) + char_time = 1; + if (timeout && timeout < char_time) + char_time = timeout; + /* + * If the transmitter hasn't cleared in twice the approximate + * amount of time to send the entire FIFO, it probably won't + * ever clear. This assumes the UART isn't doing flow + * control, which is currently the case. Hence, if it ever + * takes longer than info->timeout, this is probably due to a + * UART bug of some kind. So, we clamp the timeout parameter at + * 2*info->timeout. + */ + if (!timeout || timeout > 2 * info->timeout) + timeout = 2 * info->timeout; +#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT + printk(KERN_DEBUG "In rs_wait_until_sent(%d) check=%lu...", + timeout, char_time); + printk("jiff=%lu...", jiffies); +#endif + while (!((lsr = inb(info->ioaddr + UART_LSR)) & UART_LSR_TEMT)) { +#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT + printk("lsr = %d (jiff=%lu)...", lsr, jiffies); +#endif + schedule_timeout_interruptible(char_time); + if (signal_pending(current)) + break; + if (timeout && time_after(jiffies, orig_jiffies + timeout)) + break; + } + set_current_state(TASK_RUNNING); + +#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT + printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies); +#endif +} + +/* + * This routine is called by tty_hangup() when a hangup is signaled. + */ +void mxser_hangup(struct tty_struct *tty) +{ + struct mxser_port *info = tty->driver_data; + + mxser_flush_buffer(tty); + mxser_shutdown(info); + info->event = 0; + info->count = 0; + info->flags &= ~ASYNC_NORMAL_ACTIVE; + info->tty = NULL; + wake_up_interruptible(&info->open_wait); +} + +/* + * mxser_rs_break() --- routine which turns the break handling on or off + */ +static void mxser_rs_break(struct tty_struct *tty, int break_state) +{ + struct mxser_port *info = tty->driver_data; + unsigned long flags; + + spin_lock_irqsave(&info->slock, flags); + if (break_state == -1) + outb(inb(info->ioaddr + UART_LCR) | UART_LCR_SBC, + info->ioaddr + UART_LCR); + else + outb(inb(info->ioaddr + UART_LCR) & ~UART_LCR_SBC, + info->ioaddr + UART_LCR); + spin_unlock_irqrestore(&info->slock, flags); +} + +static void mxser_receive_chars(struct mxser_port *port, int *status) +{ + struct tty_struct *tty = port->tty; + unsigned char ch, gdl; + int ignored = 0; + int cnt = 0; + int recv_room; + int max = 256; + unsigned long flags; + + spin_lock_irqsave(&port->slock, flags); + + recv_room = tty->receive_room; + if ((recv_room == 0) && (!port->ldisc_stop_rx)) + mxser_stoprx(tty); + + if (port->board->chip_flag != MOXA_OTHER_UART) { + + if (*status & UART_LSR_SPECIAL) + goto intr_old; + if (port->board->chip_flag == MOXA_MUST_MU860_HWID && + (*status & MOXA_MUST_LSR_RERR)) + goto intr_old; + if (*status & MOXA_MUST_LSR_RERR) + goto intr_old; + + gdl = inb(port->ioaddr + MOXA_MUST_GDL_REGISTER); + + if (port->board->chip_flag == MOXA_MUST_MU150_HWID) + gdl &= MOXA_MUST_GDL_MASK; + if (gdl >= recv_room) { + if (!port->ldisc_stop_rx) + mxser_stoprx(tty); + } + while (gdl--) { + ch = inb(port->ioaddr + UART_RX); + tty_insert_flip_char(tty, ch, 0); + cnt++; + } + goto end_intr; + } +intr_old: + + do { + if (max-- < 0) + break; + + ch = inb(port->ioaddr + UART_RX); + if (port->board->chip_flag && (*status & UART_LSR_OE)) + outb(0x23, port->ioaddr + UART_FCR); + *status &= port->read_status_mask; + if (*status & port->ignore_status_mask) { + if (++ignored > 100) + break; + } else { + char flag = 0; + if (*status & UART_LSR_SPECIAL) { + if (*status & UART_LSR_BI) { + flag = TTY_BREAK; + port->icount.brk++; + + if (port->flags & ASYNC_SAK) + do_SAK(tty); + } else if (*status & UART_LSR_PE) { + flag = TTY_PARITY; + port->icount.parity++; + } else if (*status & UART_LSR_FE) { + flag = TTY_FRAME; + port->icount.frame++; + } else if (*status & UART_LSR_OE) { + flag = TTY_OVERRUN; + port->icount.overrun++; + } + } + tty_insert_flip_char(tty, ch, flag); + cnt++; + if (cnt >= recv_room) { + if (!port->ldisc_stop_rx) + mxser_stoprx(tty); + break; + } + + } + + if (port->board->chip_flag) + break; + + *status = inb(port->ioaddr + UART_LSR); + } while (*status & UART_LSR_DR); + +end_intr: + mxvar_log.rxcnt[port->tty->index] += cnt; + port->mon_data.rxcnt += cnt; + port->mon_data.up_rxcnt += cnt; + spin_unlock_irqrestore(&port->slock, flags); + + tty_flip_buffer_push(tty); +} + +static void mxser_transmit_chars(struct mxser_port *port) +{ + int count, cnt; + unsigned long flags; + + spin_lock_irqsave(&port->slock, flags); + + if (port->x_char) { + outb(port->x_char, port->ioaddr + UART_TX); + port->x_char = 0; + mxvar_log.txcnt[port->tty->index]++; + port->mon_data.txcnt++; + port->mon_data.up_txcnt++; + port->icount.tx++; + goto unlock; + } + + if (port->xmit_buf == 0) + goto unlock; + + if ((port->xmit_cnt <= 0) || port->tty->stopped || + (port->tty->hw_stopped && + (port->type != PORT_16550A) && + (!port->board->chip_flag))) { + port->IER &= ~UART_IER_THRI; + outb(port->IER, port->ioaddr + UART_IER); + goto unlock; + } + + cnt = port->xmit_cnt; + count = port->xmit_fifo_size; + do { + outb(port->xmit_buf[port->xmit_tail++], + port->ioaddr + UART_TX); + port->xmit_tail = port->xmit_tail & (SERIAL_XMIT_SIZE - 1); + if (--port->xmit_cnt <= 0) + break; + } while (--count > 0); + mxvar_log.txcnt[port->tty->index] += (cnt - port->xmit_cnt); + + port->mon_data.txcnt += (cnt - port->xmit_cnt); + port->mon_data.up_txcnt += (cnt - port->xmit_cnt); + port->icount.tx += (cnt - port->xmit_cnt); + + if (port->xmit_cnt < WAKEUP_CHARS) { + set_bit(MXSER_EVENT_TXLOW, &port->event); + schedule_work(&port->tqueue); + } + if (port->xmit_cnt <= 0) { + port->IER &= ~UART_IER_THRI; + outb(port->IER, port->ioaddr + UART_IER); + } +unlock: + spin_unlock_irqrestore(&port->slock, flags); +} + +/* + * This is the serial driver's generic interrupt routine + */ +static irqreturn_t mxser_interrupt(int irq, void *dev_id) +{ + int status, iir, i; + struct mxser_board *brd = NULL; + struct mxser_port *port; + int max, irqbits, bits, msr; + int pass_counter = 0; + unsigned int int_cnt; + int handled = IRQ_NONE; + + for (i = 0; i < MXSER_BOARDS; i++) + if (dev_id == &mxser_boards[i]) { + brd = dev_id; + break; + } + + if (i == MXSER_BOARDS) + goto irq_stop; + if (brd == NULL) + goto irq_stop; + max = brd->info->nports; + while (1) { + irqbits = inb(brd->vector) & brd->vector_mask; + if (irqbits == brd->vector_mask) + break; + + handled = IRQ_HANDLED; + for (i = 0, bits = 1; i < max; i++, irqbits |= bits, bits <<= 1) { + if (irqbits == brd->vector_mask) + break; + if (bits & irqbits) + continue; + port = &brd->ports[i]; + + int_cnt = 0; + do { + iir = inb(port->ioaddr + UART_IIR); + if (iir & UART_IIR_NO_INT) + break; + iir &= MOXA_MUST_IIR_MASK; + if (!port->tty) { + status = inb(port->ioaddr + UART_LSR); + outb(0x27, port->ioaddr + UART_FCR); + inb(port->ioaddr + UART_MSR); + break; + } + + status = inb(port->ioaddr + UART_LSR); + + if (status & UART_LSR_PE) + port->err_shadow |= NPPI_NOTIFY_PARITY; + if (status & UART_LSR_FE) + port->err_shadow |= NPPI_NOTIFY_FRAMING; + if (status & UART_LSR_OE) + port->err_shadow |= + NPPI_NOTIFY_HW_OVERRUN; + if (status & UART_LSR_BI) + port->err_shadow |= NPPI_NOTIFY_BREAK; + + if (port->board->chip_flag) { + if (iir == MOXA_MUST_IIR_GDA || + iir == MOXA_MUST_IIR_RDA || + iir == MOXA_MUST_IIR_RTO || + iir == MOXA_MUST_IIR_LSR) + mxser_receive_chars(port, + &status); + + } else { + status &= port->read_status_mask; + if (status & UART_LSR_DR) + mxser_receive_chars(port, + &status); + } + msr = inb(port->ioaddr + UART_MSR); + if (msr & UART_MSR_ANY_DELTA) + mxser_check_modem_status(port, msr); + + if (port->board->chip_flag) { + if (iir == 0x02 && (status & + UART_LSR_THRE)) + mxser_transmit_chars(port); + } else { + if (status & UART_LSR_THRE) + mxser_transmit_chars(port); + } + } while (int_cnt++ < MXSER_ISR_PASS_LIMIT); + } + if (pass_counter++ > MXSER_ISR_PASS_LIMIT) + break; /* Prevent infinite loops */ + } + +irq_stop: + return handled; +} + +static const struct tty_operations mxser_ops = { + .open = mxser_open, + .close = mxser_close, + .write = mxser_write, + .put_char = mxser_put_char, + .flush_chars = mxser_flush_chars, + .write_room = mxser_write_room, + .chars_in_buffer = mxser_chars_in_buffer, + .flush_buffer = mxser_flush_buffer, + .ioctl = mxser_ioctl, + .throttle = mxser_throttle, + .unthrottle = mxser_unthrottle, + .set_termios = mxser_set_termios, + .stop = mxser_stop, + .start = mxser_start, + .hangup = mxser_hangup, + .break_ctl = mxser_rs_break, + .wait_until_sent = mxser_wait_until_sent, + .tiocmget = mxser_tiocmget, + .tiocmset = mxser_tiocmset, +}; + +/* + * The MOXA Smartio/Industio serial driver boot-time initialization code! + */ + +static void mxser_release_res(struct mxser_board *brd, struct pci_dev *pdev, + unsigned int irq) +{ + if (irq) + free_irq(brd->irq, brd); + if (pdev != NULL) { /* PCI */ + pci_release_region(pdev, 2); + pci_release_region(pdev, 3); + pci_dev_put(pdev); + } else { + release_region(brd->ports[0].ioaddr, 8 * brd->info->nports); + release_region(brd->vector, 1); + } +} + +static int __devinit mxser_initbrd(struct mxser_board *brd, + struct pci_dev *pdev) +{ + struct mxser_port *info; + unsigned int i; + int retval; + + printk(KERN_INFO "max. baud rate = %d bps.\n", brd->ports[0].max_baud); + + for (i = 0; i < brd->info->nports; i++) { + info = &brd->ports[i]; + info->board = brd; + info->stop_rx = 0; + info->ldisc_stop_rx = 0; + + /* Enhance mode enabled here */ + if (brd->chip_flag != MOXA_OTHER_UART) + ENABLE_MOXA_MUST_ENCHANCE_MODE(info->ioaddr); + + info->flags = ASYNC_SHARE_IRQ; + info->type = brd->uart_type; + + process_txrx_fifo(info); + + info->custom_divisor = info->baud_base * 16; + info->close_delay = 5 * HZ / 10; + info->closing_wait = 30 * HZ; + INIT_WORK(&info->tqueue, mxser_do_softint); + info->normal_termios = mxvar_sdriver->init_termios; + init_waitqueue_head(&info->open_wait); + init_waitqueue_head(&info->close_wait); + init_waitqueue_head(&info->delta_msr_wait); + memset(&info->mon_data, 0, sizeof(struct mxser_mon)); + info->err_shadow = 0; + spin_lock_init(&info->slock); + + /* before set INT ISR, disable all int */ + outb(inb(info->ioaddr + UART_IER) & 0xf0, + info->ioaddr + UART_IER); + } + /* + * Allocate the IRQ if necessary + */ + + retval = request_irq(brd->irq, mxser_interrupt, + (brd->ports[0].flags & ASYNC_SHARE_IRQ) ? IRQF_SHARED : + IRQF_DISABLED, "mxser", brd); + if (retval) { + printk(KERN_ERR "Board %s: Request irq failed, IRQ (%d) may " + "conflict with another device.\n", + brd->info->name, brd->irq); + /* We hold resources, we need to release them. */ + mxser_release_res(brd, pdev, 0); + return retval; + } + return 0; +} + +static int __init mxser_get_ISA_conf(int cap, struct mxser_board *brd) +{ + int id, i, bits; + unsigned short regs[16], irq; + unsigned char scratch, scratch2; + + brd->chip_flag = MOXA_OTHER_UART; + + id = mxser_read_register(cap, regs); + switch (id) { + case C168_ASIC_ID: + brd->info = &mxser_cards[0]; + break; + case C104_ASIC_ID: + brd->info = &mxser_cards[1]; + break; + case CI104J_ASIC_ID: + brd->info = &mxser_cards[2]; + break; + case C102_ASIC_ID: + brd->info = &mxser_cards[5]; + break; + case CI132_ASIC_ID: + brd->info = &mxser_cards[6]; + break; + case CI134_ASIC_ID: + brd->info = &mxser_cards[7]; + break; + default: + return 0; + } + + irq = 0; + /* some ISA cards have 2 ports, but we want to see them as 4-port (why?) + Flag-hack checks if configuration should be read as 2-port here. */ + if (brd->info->nports == 2 || (brd->info->flags & MXSER_HAS2)) { + irq = regs[9] & 0xF000; + irq = irq | (irq >> 4); + if (irq != (regs[9] & 0xFF00)) + return MXSER_ERR_IRQ_CONFLIT; + } else if (brd->info->nports == 4) { + irq = regs[9] & 0xF000; + irq = irq | (irq >> 4); + irq = irq | (irq >> 8); + if (irq != regs[9]) + return MXSER_ERR_IRQ_CONFLIT; + } else if (brd->info->nports == 8) { + irq = regs[9] & 0xF000; + irq = irq | (irq >> 4); + irq = irq | (irq >> 8); + if ((irq != regs[9]) || (irq != regs[10])) + return MXSER_ERR_IRQ_CONFLIT; + } + + if (!irq) + return MXSER_ERR_IRQ; + brd->irq = ((int)(irq & 0xF000) >> 12); + for (i = 0; i < 8; i++) + brd->ports[i].ioaddr = (int) regs[i + 1] & 0xFFF8; + if ((regs[12] & 0x80) == 0) + return MXSER_ERR_VECTOR; + brd->vector = (int)regs[11]; /* interrupt vector */ + if (id == 1) + brd->vector_mask = 0x00FF; + else + brd->vector_mask = 0x000F; + for (i = 7, bits = 0x0100; i >= 0; i--, bits <<= 1) { + if (regs[12] & bits) { + brd->ports[i].baud_base = 921600; + brd->ports[i].max_baud = 921600; + } else { + brd->ports[i].baud_base = 115200; + brd->ports[i].max_baud = 115200; + } + } + scratch2 = inb(cap + UART_LCR) & (~UART_LCR_DLAB); + outb(scratch2 | UART_LCR_DLAB, cap + UART_LCR); + outb(0, cap + UART_EFR); /* EFR is the same as FCR */ + outb(scratch2, cap + UART_LCR); + outb(UART_FCR_ENABLE_FIFO, cap + UART_FCR); + scratch = inb(cap + UART_IIR); + + if (scratch & 0xC0) + brd->uart_type = PORT_16550A; + else + brd->uart_type = PORT_16450; + if (!request_region(brd->ports[0].ioaddr, 8 * brd->info->nports, + "mxser(IO)")) + return MXSER_ERR_IOADDR; + if (!request_region(brd->vector, 1, "mxser(vector)")) { + release_region(brd->ports[0].ioaddr, 8 * brd->info->nports); + return MXSER_ERR_VECTOR; + } + return brd->info->nports; +} + +static int __devinit mxser_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + struct mxser_board *brd; + unsigned int i, j; + unsigned long ioaddress; + int retval = -EINVAL; + + for (i = 0; i < MXSER_BOARDS; i++) + if (mxser_boards[i].info == NULL) + break; + + if (i >= MXSER_BOARDS) { + printk(KERN_ERR "Too many Smartio/Industio family boards found " + "(maximum %d), board not configured\n", MXSER_BOARDS); + goto err; + } + + brd = &mxser_boards[i]; + brd->idx = i * MXSER_PORTS_PER_BOARD; + printk(KERN_INFO "Found MOXA %s board (BusNo=%d, DevNo=%d)\n", + mxser_cards[ent->driver_data].name, + pdev->bus->number, PCI_SLOT(pdev->devfn)); + + retval = pci_enable_device(pdev); + if (retval) { + printk(KERN_ERR "Moxa SmartI/O PCI enable fail !\n"); + goto err; + } + + /* io address */ + ioaddress = pci_resource_start(pdev, 2); + retval = pci_request_region(pdev, 2, "mxser(IO)"); + if (retval) + goto err; + + brd->info = &mxser_cards[ent->driver_data]; + for (i = 0; i < brd->info->nports; i++) + brd->ports[i].ioaddr = ioaddress + 8 * i; + + /* vector */ + ioaddress = pci_resource_start(pdev, 3); + retval = pci_request_region(pdev, 3, "mxser(vector)"); + if (retval) + goto err_relio; + brd->vector = ioaddress; + + /* irq */ + brd->irq = pdev->irq; + + brd->chip_flag = CheckIsMoxaMust(brd->ports[0].ioaddr); + brd->uart_type = PORT_16550A; + brd->vector_mask = 0; + + for (i = 0; i < brd->info->nports; i++) { + for (j = 0; j < UART_INFO_NUM; j++) { + if (Gpci_uart_info[j].type == brd->chip_flag) { + brd->ports[i].max_baud = + Gpci_uart_info[j].max_baud; + + /* exception....CP-102 */ + if (brd->info->flags & MXSER_HIGHBAUD) + brd->ports[i].max_baud = 921600; + break; + } + } + } + + if (brd->chip_flag == MOXA_MUST_MU860_HWID) { + for (i = 0; i < brd->info->nports; i++) { + if (i < 4) + brd->ports[i].opmode_ioaddr = ioaddress + 4; + else + brd->ports[i].opmode_ioaddr = ioaddress + 0x0c; + } + outb(0, ioaddress + 4); /* default set to RS232 mode */ + outb(0, ioaddress + 0x0c); /* default set to RS232 mode */ + } + + for (i = 0; i < brd->info->nports; i++) { + brd->vector_mask |= (1 << i); + brd->ports[i].baud_base = 921600; + } + + /* mxser_initbrd will hook ISR. */ + if (mxser_initbrd(brd, pdev) < 0) + goto err_relvec; + + for (i = 0; i < brd->info->nports; i++) + tty_register_device(mxvar_sdriver, brd->idx + i, &pdev->dev); + + pci_set_drvdata(pdev, brd); + + return 0; +err_relvec: + pci_release_region(pdev, 3); +err_relio: + pci_release_region(pdev, 2); + brd->info = NULL; +err: + return retval; +} + +static void __devexit mxser_remove(struct pci_dev *pdev) +{ + struct mxser_board *brd = pci_get_drvdata(pdev); + unsigned int i; + + for (i = 0; i < brd->info->nports; i++) + tty_unregister_device(mxvar_sdriver, brd->idx + i); + + mxser_release_res(brd, pdev, 1); +} + +static struct pci_driver mxser_driver = { + .name = "mxser", + .id_table = mxser_pcibrds, + .probe = mxser_probe, + .remove = __devexit_p(mxser_remove) +}; + +static int __init mxser_module_init(void) +{ + struct mxser_board *brd; + unsigned long cap; + unsigned int i, m, isaloop; + int retval, b; + + pr_debug("Loading module mxser ...\n"); + + mxvar_sdriver = alloc_tty_driver(MXSER_PORTS + 1); + if (!mxvar_sdriver) + return -ENOMEM; + spin_lock_init(&gm_lock); + + printk(KERN_INFO "MOXA Smartio/Industio family driver version %s\n", + MXSER_VERSION); + + /* Initialize the tty_driver structure */ + mxvar_sdriver->magic = TTY_DRIVER_MAGIC; + mxvar_sdriver->name = "ttyMI"; + mxvar_sdriver->major = ttymajor; + mxvar_sdriver->minor_start = 0; + mxvar_sdriver->num = MXSER_PORTS + 1; + mxvar_sdriver->type = TTY_DRIVER_TYPE_SERIAL; + mxvar_sdriver->subtype = SERIAL_TYPE_NORMAL; + mxvar_sdriver->init_termios = tty_std_termios; + mxvar_sdriver->init_termios.c_cflag = B9600|CS8|CREAD|HUPCL|CLOCAL; + mxvar_sdriver->flags = TTY_DRIVER_REAL_RAW|TTY_DRIVER_DYNAMIC_DEV; + tty_set_operations(mxvar_sdriver, &mxser_ops); + + retval = tty_register_driver(mxvar_sdriver); + if (retval) { + printk(KERN_ERR "Couldn't install MOXA Smartio/Industio family " + "tty driver !\n"); + goto err_put; + } + + mxvar_diagflag = 0; + + m = 0; + /* Start finding ISA boards here */ + for (isaloop = 0; isaloop < 2; isaloop++) + for (b = 0; b < MXSER_BOARDS && m < MXSER_BOARDS; b++) { + if (!isaloop) + cap = mxserBoardCAP[b]; /* predefined */ + else + cap = ioaddr[b]; /* module param */ + + if (!cap) + continue; + + brd = &mxser_boards[m]; + retval = mxser_get_ISA_conf(cap, brd); + + if (retval != 0) + printk(KERN_INFO "Found MOXA %s board " + "(CAP=0x%x)\n", + brd->info->name, ioaddr[b]); + + if (retval <= 0) { + if (retval == MXSER_ERR_IRQ) + printk(KERN_ERR "Invalid interrupt " + "number, board not " + "configured\n"); + else if (retval == MXSER_ERR_IRQ_CONFLIT) + printk(KERN_ERR "Invalid interrupt " + "number, board not " + "configured\n"); + else if (retval == MXSER_ERR_VECTOR) + printk(KERN_ERR "Invalid interrupt " + "vector, board not " + "configured\n"); + else if (retval == MXSER_ERR_IOADDR) + printk(KERN_ERR "Invalid I/O address, " + "board not configured\n"); + + brd->info = NULL; + continue; + } + + /* mxser_initbrd will hook ISR. */ + if (mxser_initbrd(brd, NULL) < 0) { + brd->info = NULL; + continue; + } + + brd->idx = m * MXSER_PORTS_PER_BOARD; + for (i = 0; i < brd->info->nports; i++) + tty_register_device(mxvar_sdriver, brd->idx + i, + NULL); + + m++; + } + + retval = pci_register_driver(&mxser_driver); + if (retval) { + printk(KERN_ERR "Can't register pci driver\n"); + if (!m) { + retval = -ENODEV; + goto err_unr; + } /* else: we have some ISA cards under control */ + } + + pr_debug("Done.\n"); + + return 0; +err_unr: + tty_unregister_driver(mxvar_sdriver); +err_put: + put_tty_driver(mxvar_sdriver); + return retval; +} + +static void __exit mxser_module_exit(void) +{ + unsigned int i, j; + + pr_debug("Unloading module mxser ...\n"); + + pci_unregister_driver(&mxser_driver); + + for (i = 0; i < MXSER_BOARDS; i++) /* ISA remains */ + if (mxser_boards[i].info != NULL) + for (j = 0; j < mxser_boards[i].info->nports; j++) + tty_unregister_device(mxvar_sdriver, + mxser_boards[i].idx + j); + tty_unregister_driver(mxvar_sdriver); + put_tty_driver(mxvar_sdriver); + + for (i = 0; i < MXSER_BOARDS; i++) + if (mxser_boards[i].info != NULL) + mxser_release_res(&mxser_boards[i], NULL, 1); + + pr_debug("Done.\n"); +} + +module_init(mxser_module_init); +module_exit(mxser_module_exit); diff --git a/trunk/drivers/char/mxser_new.h b/trunk/drivers/char/mxser_new.h new file mode 100644 index 000000000000..a08f0ecb09ba --- /dev/null +++ b/trunk/drivers/char/mxser_new.h @@ -0,0 +1,450 @@ +#ifndef _MXSER_H +#define _MXSER_H + +/* + * Semi-public control interfaces + */ + +/* + * MOXA ioctls + */ + +#define MOXA 0x400 +#define MOXA_GETDATACOUNT (MOXA + 23) +#define MOXA_GET_CONF (MOXA + 35) +#define MOXA_DIAGNOSE (MOXA + 50) +#define MOXA_CHKPORTENABLE (MOXA + 60) +#define MOXA_HighSpeedOn (MOXA + 61) +#define MOXA_GET_MAJOR (MOXA + 63) +#define MOXA_GET_CUMAJOR (MOXA + 64) +#define MOXA_GETMSTATUS (MOXA + 65) +#define MOXA_SET_OP_MODE (MOXA + 66) +#define MOXA_GET_OP_MODE (MOXA + 67) + +#define RS232_MODE 0 +#define RS485_2WIRE_MODE 1 +#define RS422_MODE 2 +#define RS485_4WIRE_MODE 3 +#define OP_MODE_MASK 3 +// above add by Victor Yu. 01-05-2004 + +#define TTY_THRESHOLD_THROTTLE 128 + +#define LO_WATER (TTY_FLIPBUF_SIZE) +#define HI_WATER (TTY_FLIPBUF_SIZE*2*3/4) + +// added by James. 03-11-2004. +#define MOXA_SDS_GETICOUNTER (MOXA + 68) +#define MOXA_SDS_RSTICOUNTER (MOXA + 69) +// (above) added by James. + +#define MOXA_ASPP_OQUEUE (MOXA + 70) +#define MOXA_ASPP_SETBAUD (MOXA + 71) +#define MOXA_ASPP_GETBAUD (MOXA + 72) +#define MOXA_ASPP_MON (MOXA + 73) +#define MOXA_ASPP_LSTATUS (MOXA + 74) +#define MOXA_ASPP_MON_EXT (MOXA + 75) +#define MOXA_SET_BAUD_METHOD (MOXA + 76) + + +/* --------------------------------------------------- */ + +#define NPPI_NOTIFY_PARITY 0x01 +#define NPPI_NOTIFY_FRAMING 0x02 +#define NPPI_NOTIFY_HW_OVERRUN 0x04 +#define NPPI_NOTIFY_SW_OVERRUN 0x08 +#define NPPI_NOTIFY_BREAK 0x10 + +#define NPPI_NOTIFY_CTSHOLD 0x01 // Tx hold by CTS low +#define NPPI_NOTIFY_DSRHOLD 0x02 // Tx hold by DSR low +#define NPPI_NOTIFY_XOFFHOLD 0x08 // Tx hold by Xoff received +#define NPPI_NOTIFY_XOFFXENT 0x10 // Xoff Sent + +//CheckIsMoxaMust return value +#define MOXA_OTHER_UART 0x00 +#define MOXA_MUST_MU150_HWID 0x01 +#define MOXA_MUST_MU860_HWID 0x02 + +// follow just for Moxa Must chip define. +// +// when LCR register (offset 0x03) write following value, +// the Must chip will enter enchance mode. And write value +// on EFR (offset 0x02) bit 6,7 to change bank. +#define MOXA_MUST_ENTER_ENCHANCE 0xBF + +// when enhance mode enable, access on general bank register +#define MOXA_MUST_GDL_REGISTER 0x07 +#define MOXA_MUST_GDL_MASK 0x7F +#define MOXA_MUST_GDL_HAS_BAD_DATA 0x80 + +#define MOXA_MUST_LSR_RERR 0x80 // error in receive FIFO +// enchance register bank select and enchance mode setting register +// when LCR register equal to 0xBF +#define MOXA_MUST_EFR_REGISTER 0x02 +// enchance mode enable +#define MOXA_MUST_EFR_EFRB_ENABLE 0x10 +// enchance reister bank set 0, 1, 2 +#define MOXA_MUST_EFR_BANK0 0x00 +#define MOXA_MUST_EFR_BANK1 0x40 +#define MOXA_MUST_EFR_BANK2 0x80 +#define MOXA_MUST_EFR_BANK3 0xC0 +#define MOXA_MUST_EFR_BANK_MASK 0xC0 + +// set XON1 value register, when LCR=0xBF and change to bank0 +#define MOXA_MUST_XON1_REGISTER 0x04 + +// set XON2 value register, when LCR=0xBF and change to bank0 +#define MOXA_MUST_XON2_REGISTER 0x05 + +// set XOFF1 value register, when LCR=0xBF and change to bank0 +#define MOXA_MUST_XOFF1_REGISTER 0x06 + +// set XOFF2 value register, when LCR=0xBF and change to bank0 +#define MOXA_MUST_XOFF2_REGISTER 0x07 + +#define MOXA_MUST_RBRTL_REGISTER 0x04 +#define MOXA_MUST_RBRTH_REGISTER 0x05 +#define MOXA_MUST_RBRTI_REGISTER 0x06 +#define MOXA_MUST_THRTL_REGISTER 0x07 +#define MOXA_MUST_ENUM_REGISTER 0x04 +#define MOXA_MUST_HWID_REGISTER 0x05 +#define MOXA_MUST_ECR_REGISTER 0x06 +#define MOXA_MUST_CSR_REGISTER 0x07 + +// good data mode enable +#define MOXA_MUST_FCR_GDA_MODE_ENABLE 0x20 +// only good data put into RxFIFO +#define MOXA_MUST_FCR_GDA_ONLY_ENABLE 0x10 + +// enable CTS interrupt +#define MOXA_MUST_IER_ECTSI 0x80 +// enable RTS interrupt +#define MOXA_MUST_IER_ERTSI 0x40 +// enable Xon/Xoff interrupt +#define MOXA_MUST_IER_XINT 0x20 +// enable GDA interrupt +#define MOXA_MUST_IER_EGDAI 0x10 + +#define MOXA_MUST_RECV_ISR (UART_IER_RDI | MOXA_MUST_IER_EGDAI) + +// GDA interrupt pending +#define MOXA_MUST_IIR_GDA 0x1C +#define MOXA_MUST_IIR_RDA 0x04 +#define MOXA_MUST_IIR_RTO 0x0C +#define MOXA_MUST_IIR_LSR 0x06 + +// recieved Xon/Xoff or specical interrupt pending +#define MOXA_MUST_IIR_XSC 0x10 + +// RTS/CTS change state interrupt pending +#define MOXA_MUST_IIR_RTSCTS 0x20 +#define MOXA_MUST_IIR_MASK 0x3E + +#define MOXA_MUST_MCR_XON_FLAG 0x40 +#define MOXA_MUST_MCR_XON_ANY 0x80 +#define MOXA_MUST_MCR_TX_XON 0x08 + + +// software flow control on chip mask value +#define MOXA_MUST_EFR_SF_MASK 0x0F +// send Xon1/Xoff1 +#define MOXA_MUST_EFR_SF_TX1 0x08 +// send Xon2/Xoff2 +#define MOXA_MUST_EFR_SF_TX2 0x04 +// send Xon1,Xon2/Xoff1,Xoff2 +#define MOXA_MUST_EFR_SF_TX12 0x0C +// don't send Xon/Xoff +#define MOXA_MUST_EFR_SF_TX_NO 0x00 +// Tx software flow control mask +#define MOXA_MUST_EFR_SF_TX_MASK 0x0C +// don't receive Xon/Xoff +#define MOXA_MUST_EFR_SF_RX_NO 0x00 +// receive Xon1/Xoff1 +#define MOXA_MUST_EFR_SF_RX1 0x02 +// receive Xon2/Xoff2 +#define MOXA_MUST_EFR_SF_RX2 0x01 +// receive Xon1,Xon2/Xoff1,Xoff2 +#define MOXA_MUST_EFR_SF_RX12 0x03 +// Rx software flow control mask +#define MOXA_MUST_EFR_SF_RX_MASK 0x03 + +//#define MOXA_MUST_MIN_XOFFLIMIT 66 +//#define MOXA_MUST_MIN_XONLIMIT 20 +//#define ID1_RX_TRIG 120 + + +#define CHECK_MOXA_MUST_XOFFLIMIT(info) { \ + if ( (info)->IsMoxaMustChipFlag && \ + (info)->HandFlow.XoffLimit < MOXA_MUST_MIN_XOFFLIMIT ) { \ + (info)->HandFlow.XoffLimit = MOXA_MUST_MIN_XOFFLIMIT; \ + (info)->HandFlow.XonLimit = MOXA_MUST_MIN_XONLIMIT; \ + } \ +} + +#define ENABLE_MOXA_MUST_ENCHANCE_MODE(baseio) { \ + u8 __oldlcr, __efr; \ + __oldlcr = inb((baseio)+UART_LCR); \ + outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ + __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ + __efr |= MOXA_MUST_EFR_EFRB_ENABLE; \ + outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ + outb(__oldlcr, (baseio)+UART_LCR); \ +} + +#define DISABLE_MOXA_MUST_ENCHANCE_MODE(baseio) { \ + u8 __oldlcr, __efr; \ + __oldlcr = inb((baseio)+UART_LCR); \ + outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ + __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ + __efr &= ~MOXA_MUST_EFR_EFRB_ENABLE; \ + outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ + outb(__oldlcr, (baseio)+UART_LCR); \ +} + +#define SET_MOXA_MUST_XON1_VALUE(baseio, Value) { \ + u8 __oldlcr, __efr; \ + __oldlcr = inb((baseio)+UART_LCR); \ + outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ + __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ + __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ + __efr |= MOXA_MUST_EFR_BANK0; \ + outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ + outb((u8)(Value), (baseio)+MOXA_MUST_XON1_REGISTER); \ + outb(__oldlcr, (baseio)+UART_LCR); \ +} + +#define SET_MOXA_MUST_XON2_VALUE(baseio, Value) { \ + u8 __oldlcr, __efr; \ + __oldlcr = inb((baseio)+UART_LCR); \ + outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ + __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ + __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ + __efr |= MOXA_MUST_EFR_BANK0; \ + outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ + outb((u8)(Value), (baseio)+MOXA_MUST_XON2_REGISTER); \ + outb(__oldlcr, (baseio)+UART_LCR); \ +} + +#define SET_MOXA_MUST_XOFF1_VALUE(baseio, Value) { \ + u8 __oldlcr, __efr; \ + __oldlcr = inb((baseio)+UART_LCR); \ + outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ + __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ + __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ + __efr |= MOXA_MUST_EFR_BANK0; \ + outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ + outb((u8)(Value), (baseio)+MOXA_MUST_XOFF1_REGISTER); \ + outb(__oldlcr, (baseio)+UART_LCR); \ +} + +#define SET_MOXA_MUST_XOFF2_VALUE(baseio, Value) { \ + u8 __oldlcr, __efr; \ + __oldlcr = inb((baseio)+UART_LCR); \ + outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ + __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ + __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ + __efr |= MOXA_MUST_EFR_BANK0; \ + outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ + outb((u8)(Value), (baseio)+MOXA_MUST_XOFF2_REGISTER); \ + outb(__oldlcr, (baseio)+UART_LCR); \ +} + +#define SET_MOXA_MUST_RBRTL_VALUE(baseio, Value) { \ + u8 __oldlcr, __efr; \ + __oldlcr = inb((baseio)+UART_LCR); \ + outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ + __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ + __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ + __efr |= MOXA_MUST_EFR_BANK1; \ + outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ + outb((u8)(Value), (baseio)+MOXA_MUST_RBRTL_REGISTER); \ + outb(__oldlcr, (baseio)+UART_LCR); \ +} + +#define SET_MOXA_MUST_RBRTH_VALUE(baseio, Value) { \ + u8 __oldlcr, __efr; \ + __oldlcr = inb((baseio)+UART_LCR); \ + outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ + __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ + __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ + __efr |= MOXA_MUST_EFR_BANK1; \ + outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ + outb((u8)(Value), (baseio)+MOXA_MUST_RBRTH_REGISTER); \ + outb(__oldlcr, (baseio)+UART_LCR); \ +} + +#define SET_MOXA_MUST_RBRTI_VALUE(baseio, Value) { \ + u8 __oldlcr, __efr; \ + __oldlcr = inb((baseio)+UART_LCR); \ + outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ + __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ + __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ + __efr |= MOXA_MUST_EFR_BANK1; \ + outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ + outb((u8)(Value), (baseio)+MOXA_MUST_RBRTI_REGISTER); \ + outb(__oldlcr, (baseio)+UART_LCR); \ +} + +#define SET_MOXA_MUST_THRTL_VALUE(baseio, Value) { \ + u8 __oldlcr, __efr; \ + __oldlcr = inb((baseio)+UART_LCR); \ + outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ + __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ + __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ + __efr |= MOXA_MUST_EFR_BANK1; \ + outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ + outb((u8)(Value), (baseio)+MOXA_MUST_THRTL_REGISTER); \ + outb(__oldlcr, (baseio)+UART_LCR); \ +} + +//#define MOXA_MUST_RBRL_VALUE 4 +#define SET_MOXA_MUST_FIFO_VALUE(info) { \ + u8 __oldlcr, __efr; \ + __oldlcr = inb((info)->ioaddr+UART_LCR); \ + outb(MOXA_MUST_ENTER_ENCHANCE, (info)->ioaddr+UART_LCR); \ + __efr = inb((info)->ioaddr+MOXA_MUST_EFR_REGISTER); \ + __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ + __efr |= MOXA_MUST_EFR_BANK1; \ + outb(__efr, (info)->ioaddr+MOXA_MUST_EFR_REGISTER); \ + outb((u8)((info)->rx_high_water), (info)->ioaddr+MOXA_MUST_RBRTH_REGISTER); \ + outb((u8)((info)->rx_trigger), (info)->ioaddr+MOXA_MUST_RBRTI_REGISTER); \ + outb((u8)((info)->rx_low_water), (info)->ioaddr+MOXA_MUST_RBRTL_REGISTER); \ + outb(__oldlcr, (info)->ioaddr+UART_LCR); \ +} + + + +#define SET_MOXA_MUST_ENUM_VALUE(baseio, Value) { \ + u8 __oldlcr, __efr; \ + __oldlcr = inb((baseio)+UART_LCR); \ + outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ + __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ + __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ + __efr |= MOXA_MUST_EFR_BANK2; \ + outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ + outb((u8)(Value), (baseio)+MOXA_MUST_ENUM_REGISTER); \ + outb(__oldlcr, (baseio)+UART_LCR); \ +} + +#define GET_MOXA_MUST_HARDWARE_ID(baseio, pId) { \ + u8 __oldlcr, __efr; \ + __oldlcr = inb((baseio)+UART_LCR); \ + outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ + __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ + __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ + __efr |= MOXA_MUST_EFR_BANK2; \ + outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ + *pId = inb((baseio)+MOXA_MUST_HWID_REGISTER); \ + outb(__oldlcr, (baseio)+UART_LCR); \ +} + +#define SET_MOXA_MUST_NO_SOFTWARE_FLOW_CONTROL(baseio) { \ + u8 __oldlcr, __efr; \ + __oldlcr = inb((baseio)+UART_LCR); \ + outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ + __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ + __efr &= ~MOXA_MUST_EFR_SF_MASK; \ + outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ + outb(__oldlcr, (baseio)+UART_LCR); \ +} + +#define SET_MOXA_MUST_JUST_TX_SOFTWARE_FLOW_CONTROL(baseio) { \ + u8 __oldlcr, __efr; \ + __oldlcr = inb((baseio)+UART_LCR); \ + outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ + __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ + __efr &= ~MOXA_MUST_EFR_SF_MASK; \ + __efr |= MOXA_MUST_EFR_SF_TX1; \ + outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ + outb(__oldlcr, (baseio)+UART_LCR); \ +} + +#define ENABLE_MOXA_MUST_TX_SOFTWARE_FLOW_CONTROL(baseio) { \ + u8 __oldlcr, __efr; \ + __oldlcr = inb((baseio)+UART_LCR); \ + outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ + __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ + __efr &= ~MOXA_MUST_EFR_SF_TX_MASK; \ + __efr |= MOXA_MUST_EFR_SF_TX1; \ + outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ + outb(__oldlcr, (baseio)+UART_LCR); \ +} + +#define DISABLE_MOXA_MUST_TX_SOFTWARE_FLOW_CONTROL(baseio) { \ + u8 __oldlcr, __efr; \ + __oldlcr = inb((baseio)+UART_LCR); \ + outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ + __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ + __efr &= ~MOXA_MUST_EFR_SF_TX_MASK; \ + outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ + outb(__oldlcr, (baseio)+UART_LCR); \ +} + +#define SET_MOXA_MUST_JUST_RX_SOFTWARE_FLOW_CONTROL(baseio) { \ + u8 __oldlcr, __efr; \ + __oldlcr = inb((baseio)+UART_LCR); \ + outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ + __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ + __efr &= ~MOXA_MUST_EFR_SF_MASK; \ + __efr |= MOXA_MUST_EFR_SF_RX1; \ + outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ + outb(__oldlcr, (baseio)+UART_LCR); \ +} + +#define ENABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(baseio) { \ + u8 __oldlcr, __efr; \ + __oldlcr = inb((baseio)+UART_LCR); \ + outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ + __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ + __efr &= ~MOXA_MUST_EFR_SF_RX_MASK; \ + __efr |= MOXA_MUST_EFR_SF_RX1; \ + outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ + outb(__oldlcr, (baseio)+UART_LCR); \ +} + +#define DISABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(baseio) { \ + u8 __oldlcr, __efr; \ + __oldlcr = inb((baseio)+UART_LCR); \ + outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ + __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ + __efr &= ~MOXA_MUST_EFR_SF_RX_MASK; \ + outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ + outb(__oldlcr, (baseio)+UART_LCR); \ +} + +#define ENABLE_MOXA_MUST_TX_RX_SOFTWARE_FLOW_CONTROL(baseio) { \ + u8 __oldlcr, __efr; \ + __oldlcr = inb((baseio)+UART_LCR); \ + outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ + __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ + __efr &= ~MOXA_MUST_EFR_SF_MASK; \ + __efr |= (MOXA_MUST_EFR_SF_RX1|MOXA_MUST_EFR_SF_TX1); \ + outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ + outb(__oldlcr, (baseio)+UART_LCR); \ +} + +#define ENABLE_MOXA_MUST_XON_ANY_FLOW_CONTROL(baseio) { \ + u8 __oldmcr; \ + __oldmcr = inb((baseio)+UART_MCR); \ + __oldmcr |= MOXA_MUST_MCR_XON_ANY; \ + outb(__oldmcr, (baseio)+UART_MCR); \ +} + +#define DISABLE_MOXA_MUST_XON_ANY_FLOW_CONTROL(baseio) { \ + u8 __oldmcr; \ + __oldmcr = inb((baseio)+UART_MCR); \ + __oldmcr &= ~MOXA_MUST_MCR_XON_ANY; \ + outb(__oldmcr, (baseio)+UART_MCR); \ +} + +#define READ_MOXA_MUST_GDL(baseio) inb((baseio)+MOXA_MUST_GDL_REGISTER) + + +#ifndef INIT_WORK +#define INIT_WORK(_work, _func, _data){ \ + _data->tqueue.routine = _func;\ + _data->tqueue.data = _data;\ + } +#endif + +#endif diff --git a/trunk/drivers/char/n_r3964.c b/trunk/drivers/char/n_r3964.c index 203dc2b661d5..103d338f21e2 100644 --- a/trunk/drivers/char/n_r3964.c +++ b/trunk/drivers/char/n_r3964.c @@ -142,7 +142,7 @@ static ssize_t r3964_write(struct tty_struct * tty, struct file * file, const unsigned char * buf, size_t nr); static int r3964_ioctl(struct tty_struct * tty, struct file * file, unsigned int cmd, unsigned long arg); -static void r3964_set_termios(struct tty_struct *tty, struct termios * old); +static void r3964_set_termios(struct tty_struct *tty, struct ktermios * old); static unsigned int r3964_poll(struct tty_struct * tty, struct file * file, struct poll_table_struct *wait); static void r3964_receive_buf(struct tty_struct *tty, const unsigned char *cp, @@ -1347,7 +1347,7 @@ static int r3964_ioctl(struct tty_struct * tty, struct file * file, } } -static void r3964_set_termios(struct tty_struct *tty, struct termios * old) +static void r3964_set_termios(struct tty_struct *tty, struct ktermios * old) { TRACE_L("set_termios"); } diff --git a/trunk/drivers/char/n_tty.c b/trunk/drivers/char/n_tty.c index 603b9ade5eb0..e96a00fe1389 100644 --- a/trunk/drivers/char/n_tty.c +++ b/trunk/drivers/char/n_tty.c @@ -994,7 +994,7 @@ int is_ignored(int sig) * when the ldisc is closed. */ -static void n_tty_set_termios(struct tty_struct *tty, struct termios * old) +static void n_tty_set_termios(struct tty_struct *tty, struct ktermios * old) { if (!tty) return; diff --git a/trunk/drivers/char/nsc_gpio.c b/trunk/drivers/char/nsc_gpio.c index 4d47d79bcea7..808d44e9a32a 100644 --- a/trunk/drivers/char/nsc_gpio.c +++ b/trunk/drivers/char/nsc_gpio.c @@ -41,7 +41,7 @@ void nsc_gpio_dump(struct nsc_gpio_ops *amp, unsigned index) ssize_t nsc_gpio_write(struct file *file, const char __user *data, size_t len, loff_t *ppos) { - unsigned m = iminor(file->f_dentry->d_inode); + unsigned m = iminor(file->f_path.dentry->d_inode); struct nsc_gpio_ops *amp = file->private_data; struct device *dev = amp->dev; size_t i; @@ -104,7 +104,7 @@ ssize_t nsc_gpio_write(struct file *file, const char __user *data, ssize_t nsc_gpio_read(struct file *file, char __user * buf, size_t len, loff_t * ppos) { - unsigned m = iminor(file->f_dentry->d_inode); + unsigned m = iminor(file->f_path.dentry->d_inode); int value; struct nsc_gpio_ops *amp = file->private_data; diff --git a/trunk/drivers/char/pcmcia/cm4000_cs.c b/trunk/drivers/char/pcmcia/cm4000_cs.c index 50d20aafeb18..211c93fda6fc 100644 --- a/trunk/drivers/char/pcmcia/cm4000_cs.c +++ b/trunk/drivers/char/pcmcia/cm4000_cs.c @@ -1764,29 +1764,11 @@ static int cm4000_config(struct pcmcia_device * link, int devno) int rc; /* read the config-tuples */ - tuple.DesiredTuple = CISTPL_CONFIG; tuple.Attributes = 0; tuple.TupleData = buf; tuple.TupleDataMax = sizeof(buf); tuple.TupleOffset = 0; - if ((fail_rc = pcmcia_get_first_tuple(link, &tuple)) != CS_SUCCESS) { - fail_fn = GetFirstTuple; - goto cs_failed; - } - if ((fail_rc = pcmcia_get_tuple_data(link, &tuple)) != CS_SUCCESS) { - fail_fn = GetTupleData; - goto cs_failed; - } - if ((fail_rc = - pcmcia_parse_tuple(link, &tuple, &parse)) != CS_SUCCESS) { - fail_fn = ParseTuple; - goto cs_failed; - } - - link->conf.ConfigBase = parse.config.base; - link->conf.Present = parse.config.rmask[0]; - link->io.BasePort2 = 0; link->io.NumPorts2 = 0; link->io.Attributes2 = 0; @@ -1841,8 +1823,6 @@ static int cm4000_config(struct pcmcia_device * link, int devno) return 0; -cs_failed: - cs_error(link, fail_fn, fail_rc); cs_release: cm4000_release(link); return -ENODEV; @@ -1973,14 +1953,14 @@ static int __init cmm_init(void) printk(KERN_INFO "%s\n", version); cmm_class = class_create(THIS_MODULE, "cardman_4000"); - if (!cmm_class) - return -1; + if (IS_ERR(cmm_class)) + return PTR_ERR(cmm_class); major = register_chrdev(0, DEVICE_NAME, &cm4000_fops); if (major < 0) { printk(KERN_WARNING MODULE_NAME ": could not get major number\n"); - return -1; + return major; } rc = pcmcia_register_driver(&cm4000_driver); diff --git a/trunk/drivers/char/pcmcia/cm4040_cs.c b/trunk/drivers/char/pcmcia/cm4040_cs.c index 55cf4be42976..9b1ff7e8f896 100644 --- a/trunk/drivers/char/pcmcia/cm4040_cs.c +++ b/trunk/drivers/char/pcmcia/cm4040_cs.c @@ -523,29 +523,11 @@ static int reader_config(struct pcmcia_device *link, int devno) int fail_fn, fail_rc; int rc; - tuple.DesiredTuple = CISTPL_CONFIG; tuple.Attributes = 0; tuple.TupleData = buf; tuple.TupleDataMax = sizeof(buf); tuple.TupleOffset = 0; - if ((fail_rc = pcmcia_get_first_tuple(link, &tuple)) != CS_SUCCESS) { - fail_fn = GetFirstTuple; - goto cs_failed; - } - if ((fail_rc = pcmcia_get_tuple_data(link, &tuple)) != CS_SUCCESS) { - fail_fn = GetTupleData; - goto cs_failed; - } - if ((fail_rc = pcmcia_parse_tuple(link, &tuple, &parse)) - != CS_SUCCESS) { - fail_fn = ParseTuple; - goto cs_failed; - } - - link->conf.ConfigBase = parse.config.base; - link->conf.Present = parse.config.rmask[0]; - link->io.BasePort2 = 0; link->io.NumPorts2 = 0; link->io.Attributes2 = 0; @@ -609,8 +591,6 @@ static int reader_config(struct pcmcia_device *link, int devno) return 0; -cs_failed: - cs_error(link, fail_fn, fail_rc); cs_release: reader_release(link); return -ENODEV; @@ -721,14 +701,14 @@ static int __init cm4040_init(void) printk(KERN_INFO "%s\n", version); cmx_class = class_create(THIS_MODULE, "cardman_4040"); - if (!cmx_class) - return -1; + if (IS_ERR(cmx_class)) + return PTR_ERR(cmx_class); major = register_chrdev(0, DEVICE_NAME, &reader_fops); if (major < 0) { printk(KERN_WARNING MODULE_NAME ": could not get major number\n"); - return -1; + return major; } rc = pcmcia_register_driver(&reader_driver); diff --git a/trunk/drivers/char/pcmcia/synclink_cs.c b/trunk/drivers/char/pcmcia/synclink_cs.c index 1a0bc30b79d1..5152cedd8878 100644 --- a/trunk/drivers/char/pcmcia/synclink_cs.c +++ b/trunk/drivers/char/pcmcia/synclink_cs.c @@ -75,8 +75,10 @@ #include #include -#ifdef CONFIG_HDLC_MODULE -#define CONFIG_HDLC 1 +#if defined(CONFIG_HDLC) || (defined(CONFIG_HDLC_MODULE) && defined(CONFIG_SYNCLINK_CS_MODULE)) +#define SYNCLINK_GENERIC_HDLC 1 +#else +#define SYNCLINK_GENERIC_HDLC 0 #endif #define GET_USER(error,value,addr) error = get_user(value,addr) @@ -235,7 +237,7 @@ typedef struct _mgslpc_info { int dosyncppp; spinlock_t netlock; -#ifdef CONFIG_HDLC +#if SYNCLINK_GENERIC_HDLC struct net_device *netdev; #endif @@ -392,7 +394,7 @@ static void tx_timeout(unsigned long context); static int ioctl_common(MGSLPC_INFO *info, unsigned int cmd, unsigned long arg); -#ifdef CONFIG_HDLC +#if SYNCLINK_GENERIC_HDLC #define dev_to_port(D) (dev_to_hdlc(D)->priv) static void hdlcdev_tx_done(MGSLPC_INFO *info); static void hdlcdev_rx(MGSLPC_INFO *info, char *buf, int size); @@ -421,7 +423,7 @@ static irqreturn_t mgslpc_isr(int irq, void *dev_id); /* * Bottom half interrupt handlers */ -static void bh_handler(void* Context); +static void bh_handler(struct work_struct *work); static void bh_transmit(MGSLPC_INFO *info); static void bh_status(MGSLPC_INFO *info); @@ -547,7 +549,7 @@ static int mgslpc_probe(struct pcmcia_device *link) memset(info, 0, sizeof(MGSLPC_INFO)); info->magic = MGSLPC_MAGIC; - INIT_WORK(&info->task, bh_handler, info); + INIT_WORK(&info->task, bh_handler); info->max_frame_size = 4096; info->close_delay = 5*HZ/10; info->closing_wait = 30*HZ; @@ -604,17 +606,10 @@ static int mgslpc_config(struct pcmcia_device *link) if (debug_level >= DEBUG_LEVEL_INFO) printk("mgslpc_config(0x%p)\n", link); - /* read CONFIG tuple to find its configuration registers */ - tuple.DesiredTuple = CISTPL_CONFIG; tuple.Attributes = 0; tuple.TupleData = buf; tuple.TupleDataMax = sizeof(buf); tuple.TupleOffset = 0; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); - link->conf.ConfigBase = parse.config.base; - link->conf.Present = parse.config.rmask[0]; /* get CIS configuration entry */ @@ -842,9 +837,9 @@ static int bh_action(MGSLPC_INFO *info) return rc; } -static void bh_handler(void* Context) +static void bh_handler(struct work_struct *work) { - MGSLPC_INFO *info = (MGSLPC_INFO*)Context; + MGSLPC_INFO *info = container_of(work, MGSLPC_INFO, task); int action; if (!info) @@ -1060,7 +1055,7 @@ static void tx_done(MGSLPC_INFO *info) info->drop_rts_on_tx_done = 0; } -#ifdef CONFIG_HDLC +#if SYNCLINK_GENERIC_HDLC if (info->netcount) hdlcdev_tx_done(info); else @@ -1171,7 +1166,7 @@ static void dcd_change(MGSLPC_INFO *info) } else info->input_signal_events.dcd_down++; -#ifdef CONFIG_HDLC +#if SYNCLINK_GENERIC_HDLC if (info->netcount) { if (info->serial_signals & SerialSignal_DCD) netif_carrier_on(info->netdev); @@ -2380,7 +2375,7 @@ static int ioctl_common(MGSLPC_INFO *info, unsigned int cmd, unsigned long arg) * tty pointer to tty structure * termios pointer to buffer to hold returned old termios */ -static void mgslpc_set_termios(struct tty_struct *tty, struct termios *old_termios) +static void mgslpc_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { MGSLPC_INFO *info = (MGSLPC_INFO *)tty->driver_data; unsigned long flags; @@ -2960,7 +2955,7 @@ static void mgslpc_add_device(MGSLPC_INFO *info) printk( "SyncLink PC Card %s:IO=%04X IRQ=%d\n", info->device_name, info->io_base, info->irq_level); -#ifdef CONFIG_HDLC +#if SYNCLINK_GENERIC_HDLC hdlcdev_init(info); #endif } @@ -2976,7 +2971,7 @@ static void mgslpc_remove_device(MGSLPC_INFO *remove_info) last->next_device = info->next_device; else mgslpc_device_list = info->next_device; -#ifdef CONFIG_HDLC +#if SYNCLINK_GENERIC_HDLC hdlcdev_exit(info); #endif release_resources(info); @@ -3908,7 +3903,7 @@ static int rx_get_frame(MGSLPC_INFO *info) return_frame = 1; } framesize = 0; -#ifdef CONFIG_HDLC +#if SYNCLINK_GENERIC_HDLC { struct net_device_stats *stats = hdlc_stats(info->netdev); stats->rx_errors++; @@ -3942,7 +3937,7 @@ static int rx_get_frame(MGSLPC_INFO *info) ++framesize; } -#ifdef CONFIG_HDLC +#if SYNCLINK_GENERIC_HDLC if (info->netcount) hdlcdev_rx(info, buf->data, framesize); else @@ -4098,7 +4093,7 @@ static void tx_timeout(unsigned long context) spin_unlock_irqrestore(&info->lock,flags); -#ifdef CONFIG_HDLC +#if SYNCLINK_GENERIC_HDLC if (info->netcount) hdlcdev_tx_done(info); else @@ -4106,7 +4101,7 @@ static void tx_timeout(unsigned long context) bh_transmit(info); } -#ifdef CONFIG_HDLC +#if SYNCLINK_GENERIC_HDLC /** * called by generic HDLC layer when protocol selected (PPP, frame relay, etc.) diff --git a/trunk/drivers/char/ppdev.c b/trunk/drivers/char/ppdev.c index c1e3dd837fc8..4abd1eff61d6 100644 --- a/trunk/drivers/char/ppdev.c +++ b/trunk/drivers/char/ppdev.c @@ -106,7 +106,7 @@ static inline void pp_enable_irq (struct pp_struct *pp) static ssize_t pp_read (struct file * file, char __user * buf, size_t count, loff_t * ppos) { - unsigned int minor = iminor(file->f_dentry->d_inode); + unsigned int minor = iminor(file->f_path.dentry->d_inode); struct pp_struct *pp = file->private_data; char * kbuffer; ssize_t bytes_read = 0; @@ -189,7 +189,7 @@ static ssize_t pp_read (struct file * file, char __user * buf, size_t count, static ssize_t pp_write (struct file * file, const char __user * buf, size_t count, loff_t * ppos) { - unsigned int minor = iminor(file->f_dentry->d_inode); + unsigned int minor = iminor(file->f_path.dentry->d_inode); struct pp_struct *pp = file->private_data; char * kbuffer; ssize_t bytes_written = 0; diff --git a/trunk/drivers/char/pty.c b/trunk/drivers/char/pty.c index 80d3eedd7f96..c07a1b5cd05d 100644 --- a/trunk/drivers/char/pty.c +++ b/trunk/drivers/char/pty.c @@ -218,7 +218,7 @@ static int pty_open(struct tty_struct *tty, struct file * filp) return retval; } -static void pty_set_termios(struct tty_struct *tty, struct termios *old_termios) +static void pty_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { tty->termios->c_cflag &= ~(CSIZE | PARENB); tty->termios->c_cflag |= (CS8 | CREAD); @@ -272,6 +272,8 @@ static void __init legacy_pty_init(void) pty_driver->init_termios.c_oflag = 0; pty_driver->init_termios.c_cflag = B38400 | CS8 | CREAD; pty_driver->init_termios.c_lflag = 0; + pty_driver->init_termios.c_ispeed = 38400; + pty_driver->init_termios.c_ospeed = 38400; pty_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW; pty_driver->other = pty_slave_driver; tty_set_operations(pty_driver, &pty_ops); @@ -286,6 +288,8 @@ static void __init legacy_pty_init(void) pty_slave_driver->subtype = PTY_TYPE_SLAVE; pty_slave_driver->init_termios = tty_std_termios; pty_slave_driver->init_termios.c_cflag = B38400 | CS8 | CREAD; + pty_slave_driver->init_termios.c_ispeed = 38400; + pty_slave_driver->init_termios.c_ospeed = 38400; pty_slave_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW; pty_slave_driver->other = pty_driver; @@ -366,6 +370,8 @@ static void __init unix98_pty_init(void) ptm_driver->init_termios.c_oflag = 0; ptm_driver->init_termios.c_cflag = B38400 | CS8 | CREAD; ptm_driver->init_termios.c_lflag = 0; + ptm_driver->init_termios.c_ispeed = 38400; + ptm_driver->init_termios.c_ospeed = 38400; ptm_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_DEVPTS_MEM; ptm_driver->other = pts_driver; @@ -381,6 +387,8 @@ static void __init unix98_pty_init(void) pts_driver->subtype = PTY_TYPE_SLAVE; pts_driver->init_termios = tty_std_termios; pts_driver->init_termios.c_cflag = B38400 | CS8 | CREAD; + pts_driver->init_termios.c_ispeed = 38400; + pts_driver->init_termios.c_ospeed = 38400; pts_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_DEVPTS_MEM; pts_driver->other = ptm_driver; diff --git a/trunk/drivers/char/random.c b/trunk/drivers/char/random.c index d40df30c2b10..092a01cc02da 100644 --- a/trunk/drivers/char/random.c +++ b/trunk/drivers/char/random.c @@ -1048,7 +1048,7 @@ random_write(struct file * file, const char __user * buffer, if (p == buffer) { return (ssize_t)ret; } else { - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; inode->i_mtime = current_fs_time(inode->i_sb); mark_inode_dirty(inode); return (ssize_t)(p - buffer); @@ -1422,9 +1422,9 @@ static struct keydata { static unsigned int ip_cnt; -static void rekey_seq_generator(void *private_); +static void rekey_seq_generator(struct work_struct *work); -static DECLARE_WORK(rekey_work, rekey_seq_generator, NULL); +static DECLARE_DELAYED_WORK(rekey_work, rekey_seq_generator); /* * Lock avoidance: @@ -1438,7 +1438,7 @@ static DECLARE_WORK(rekey_work, rekey_seq_generator, NULL); * happen, and even if that happens only a not perfectly compliant * ISN is generated, nothing fatal. */ -static void rekey_seq_generator(void *private_) +static void rekey_seq_generator(struct work_struct *work) { struct keydata *keyptr = &ip_keydata[1 ^ (ip_cnt & 1)]; diff --git a/trunk/drivers/char/raw.c b/trunk/drivers/char/raw.c index 3b32313f6eb4..645e20a06ece 100644 --- a/trunk/drivers/char/raw.c +++ b/trunk/drivers/char/raw.c @@ -75,7 +75,7 @@ static int raw_open(struct inode *inode, struct file *filp) filp->f_flags |= O_DIRECT; filp->f_mapping = bdev->bd_inode->i_mapping; if (++raw_devices[minor].inuse == 1) - filp->f_dentry->d_inode->i_mapping = + filp->f_path.dentry->d_inode->i_mapping = bdev->bd_inode->i_mapping; filp->private_data = bdev; mutex_unlock(&raw_mutex); diff --git a/trunk/drivers/char/rio/rio_linux.c b/trunk/drivers/char/rio/rio_linux.c index 7ac68cb3bedd..e79b2ede8510 100644 --- a/trunk/drivers/char/rio/rio_linux.c +++ b/trunk/drivers/char/rio/rio_linux.c @@ -1026,6 +1026,7 @@ static int __init rio_init(void) found++; } else { iounmap(p->RIOHosts[p->RIONumHosts].Caddr); + p->RIOHosts[p->RIONumHosts].Caddr = NULL; } } @@ -1078,6 +1079,7 @@ static int __init rio_init(void) found++; } else { iounmap(p->RIOHosts[p->RIONumHosts].Caddr); + p->RIOHosts[p->RIONumHosts].Caddr = NULL; } #else printk(KERN_ERR "Found an older RIO PCI card, but the driver is not " "compiled to support it.\n"); @@ -1117,8 +1119,10 @@ static int __init rio_init(void) } } - if (!okboard) + if (!okboard) { iounmap(hp->Caddr); + hp->Caddr = NULL; + } } } @@ -1188,6 +1192,8 @@ static void __exit rio_exit(void) } /* It is safe/allowed to del_timer a non-active timer */ del_timer(&hp->timer); + if (hp->Caddr) + iounmap(hp->Caddr); if (hp->Type == RIO_PCI) pci_dev_put(hp->pdev); } diff --git a/trunk/drivers/char/riscom8.c b/trunk/drivers/char/riscom8.c index 5ab32b38f45a..e2a94bfb2a43 100644 --- a/trunk/drivers/char/riscom8.c +++ b/trunk/drivers/char/riscom8.c @@ -82,11 +82,6 @@ static struct riscom_board * IRQ_to_board[16]; static struct tty_driver *riscom_driver; -static unsigned long baud_table[] = { - 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, - 9600, 19200, 38400, 57600, 76800, 0, -}; - static struct riscom_board rc_board[RC_NBOARD] = { { .base = RC_IOBASE1, @@ -1516,9 +1511,9 @@ static void rc_start(struct tty_struct * tty) * do_rc_hangup() -> tty->hangup() -> rc_hangup() * */ -static void do_rc_hangup(void *private_) +static void do_rc_hangup(struct work_struct *ugly_api) { - struct riscom_port *port = (struct riscom_port *) private_; + struct riscom_port *port = container_of(ugly_api, struct riscom_port, tqueue_hangup); struct tty_struct *tty; tty = port->tty; @@ -1544,7 +1539,7 @@ static void rc_hangup(struct tty_struct * tty) wake_up_interruptible(&port->open_wait); } -static void rc_set_termios(struct tty_struct * tty, struct termios * old_termios) +static void rc_set_termios(struct tty_struct * tty, struct ktermios * old_termios) { struct riscom_port *port = (struct riscom_port *)tty->driver_data; unsigned long flags; @@ -1567,9 +1562,9 @@ static void rc_set_termios(struct tty_struct * tty, struct termios * old_termios } } -static void do_softint(void *private_) +static void do_softint(struct work_struct *ugly_api) { - struct riscom_port *port = (struct riscom_port *) private_; + struct riscom_port *port = container_of(ugly_api, struct riscom_port, tqueue); struct tty_struct *tty; if(!(tty = port->tty)) @@ -1619,6 +1614,8 @@ static inline int rc_init_drivers(void) riscom_driver->init_termios = tty_std_termios; riscom_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; + riscom_driver->init_termios.c_ispeed = 9600; + riscom_driver->init_termios.c_ospeed = 9600; riscom_driver->flags = TTY_DRIVER_REAL_RAW; tty_set_operations(riscom_driver, &riscom_ops); if ((error = tty_register_driver(riscom_driver))) { @@ -1632,8 +1629,8 @@ static inline int rc_init_drivers(void) memset(rc_port, 0, sizeof(rc_port)); for (i = 0; i < RC_NPORT * RC_NBOARD; i++) { rc_port[i].magic = RISCOM8_MAGIC; - INIT_WORK(&rc_port[i].tqueue, do_softint, &rc_port[i]); - INIT_WORK(&rc_port[i].tqueue_hangup, do_rc_hangup, &rc_port[i]); + INIT_WORK(&rc_port[i].tqueue, do_softint); + INIT_WORK(&rc_port[i].tqueue_hangup, do_rc_hangup); rc_port[i].close_delay = 50 * HZ/100; rc_port[i].closing_wait = 3000 * HZ/100; init_waitqueue_head(&rc_port[i].open_wait); diff --git a/trunk/drivers/char/rocket.c b/trunk/drivers/char/rocket.c index bac80056f7e0..e94a62e30fc4 100644 --- a/trunk/drivers/char/rocket.c +++ b/trunk/drivers/char/rocket.c @@ -712,7 +712,7 @@ static void init_r_port(int board, int aiop, int chan, struct pci_dev *pci_dev) * user mode into the driver (exception handler). *info CD manipulation is spinlock protected. */ static void configure_r_port(struct r_port *info, - struct termios *old_termios) + struct ktermios *old_termios) { unsigned cflag; unsigned long flags; @@ -1017,7 +1017,7 @@ static int rp_open(struct tty_struct *tty, struct file *filp) /* * Info->count is now 1; so it's safe to sleep now. */ - info->session = current->signal->session; + info->session = process_session(current); info->pgrp = process_group(current); if ((info->flags & ROCKET_INITIALIZED) == 0) { @@ -1194,7 +1194,7 @@ static void rp_close(struct tty_struct *tty, struct file *filp) } static void rp_set_termios(struct tty_struct *tty, - struct termios *old_termios) + struct ktermios *old_termios) { struct r_port *info = (struct r_port *) tty->driver_data; CHANNEL_t *cp; @@ -2214,7 +2214,7 @@ static int __init init_PCI(int boards_found) int count = 0; /* Work through the PCI device list, pulling out ours */ - while ((dev = pci_find_device(PCI_VENDOR_ID_RP, PCI_ANY_ID, dev))) { + while ((dev = pci_get_device(PCI_VENDOR_ID_RP, PCI_ANY_ID, dev))) { if (register_PCI(count + boards_found, dev)) count++; } @@ -2436,6 +2436,8 @@ static int __init rp_init(void) rocket_driver->init_termios = tty_std_termios; rocket_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; + rocket_driver->init_termios.c_ispeed = 9600; + rocket_driver->init_termios.c_ospeed = 9600; #ifdef ROCKET_SOFT_FLOW rocket_driver->flags |= TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; #endif diff --git a/trunk/drivers/char/ser_a2232.c b/trunk/drivers/char/ser_a2232.c index 4217d38caef9..75de5f66517a 100644 --- a/trunk/drivers/char/ser_a2232.c +++ b/trunk/drivers/char/ser_a2232.c @@ -695,6 +695,8 @@ static int a2232_init_drivers(void) a2232_driver->init_termios = tty_std_termios; a2232_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; + a2232_driver->init_termios.c_ispeed = 9600; + a2232_driver->init_termios.c_ospeed = 9600; a2232_driver->flags = TTY_DRIVER_REAL_RAW; tty_set_operations(a2232_driver, &a2232_ops); if ((error = tty_register_driver(a2232_driver))) { diff --git a/trunk/drivers/char/serial167.c b/trunk/drivers/char/serial167.c index 3af7f0958c5d..af50d32ae2c7 100644 --- a/trunk/drivers/char/serial167.c +++ b/trunk/drivers/char/serial167.c @@ -706,9 +706,9 @@ cd2401_rx_interrupt(int irq, void *dev_id) * had to poll every port to see if that port needed servicing. */ static void -do_softint(void *private_) +do_softint(struct work_struct *ugly_api) { - struct cyclades_port *info = (struct cyclades_port *) private_; + struct cyclades_port *info = container_of(ugly_api, struct cyclades_port, tqueue); struct tty_struct *tty; tty = info->tty; @@ -1695,7 +1695,7 @@ cy_ioctl(struct tty_struct *tty, struct file * file, static void -cy_set_termios(struct tty_struct *tty, struct termios * old_termios) +cy_set_termios(struct tty_struct *tty, struct ktermios * old_termios) { struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; @@ -2273,7 +2273,7 @@ scrn[1] = '\0'; info->blocked_open = 0; info->default_threshold = 0; info->default_timeout = 0; - INIT_WORK(&info->tqueue, do_softint, info); + INIT_WORK(&info->tqueue, do_softint); init_waitqueue_head(&info->open_wait); init_waitqueue_head(&info->close_wait); /* info->session */ diff --git a/trunk/drivers/char/sonypi.c b/trunk/drivers/char/sonypi.c index c084149153de..17d54e1331b2 100644 --- a/trunk/drivers/char/sonypi.c +++ b/trunk/drivers/char/sonypi.c @@ -765,7 +765,7 @@ static void sonypi_setbluetoothpower(u8 state) sonypi_device.bluetooth_power = state; } -static void input_keyrelease(void *data) +static void input_keyrelease(struct work_struct *work) { struct sonypi_keypress kp; @@ -979,7 +979,7 @@ static ssize_t sonypi_misc_read(struct file *file, char __user *buf, } if (ret > 0) { - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; inode->i_atime = current_fs_time(inode->i_sb); } @@ -1412,7 +1412,7 @@ static int __devinit sonypi_probe(struct platform_device *dev) goto err_inpdev_unregister; } - INIT_WORK(&sonypi_device.input_work, input_keyrelease, NULL); + INIT_WORK(&sonypi_device.input_work, input_keyrelease); } sonypi_enable(0); diff --git a/trunk/drivers/char/specialix.c b/trunk/drivers/char/specialix.c index 7e1bd9562c2a..20946f5127e0 100644 --- a/trunk/drivers/char/specialix.c +++ b/trunk/drivers/char/specialix.c @@ -2261,9 +2261,10 @@ static void sx_start(struct tty_struct * tty) * do_sx_hangup() -> tty->hangup() -> sx_hangup() * */ -static void do_sx_hangup(void *private_) +static void do_sx_hangup(struct work_struct *work) { - struct specialix_port *port = (struct specialix_port *) private_; + struct specialix_port *port = + container_of(work, struct specialix_port, tqueue_hangup); struct tty_struct *tty; func_enter(); @@ -2310,7 +2311,7 @@ static void sx_hangup(struct tty_struct * tty) } -static void sx_set_termios(struct tty_struct * tty, struct termios * old_termios) +static void sx_set_termios(struct tty_struct * tty, struct ktermios * old_termios) { struct specialix_port *port = (struct specialix_port *)tty->driver_data; unsigned long flags; @@ -2336,9 +2337,10 @@ static void sx_set_termios(struct tty_struct * tty, struct termios * old_termios } -static void do_softint(void *private_) +static void do_softint(struct work_struct *work) { - struct specialix_port *port = (struct specialix_port *) private_; + struct specialix_port *port = + container_of(work, struct specialix_port, tqueue); struct tty_struct *tty; func_enter(); @@ -2398,6 +2400,8 @@ static int sx_init_drivers(void) specialix_driver->init_termios = tty_std_termios; specialix_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; + specialix_driver->init_termios.c_ispeed = 9600; + specialix_driver->init_termios.c_ospeed = 9600; specialix_driver->flags = TTY_DRIVER_REAL_RAW; tty_set_operations(specialix_driver, &sx_ops); @@ -2411,8 +2415,8 @@ static int sx_init_drivers(void) memset(sx_port, 0, sizeof(sx_port)); for (i = 0; i < SX_NPORT * SX_NBOARD; i++) { sx_port[i].magic = SPECIALIX_MAGIC; - INIT_WORK(&sx_port[i].tqueue, do_softint, &sx_port[i]); - INIT_WORK(&sx_port[i].tqueue_hangup, do_sx_hangup, &sx_port[i]); + INIT_WORK(&sx_port[i].tqueue, do_softint); + INIT_WORK(&sx_port[i].tqueue_hangup, do_sx_hangup); sx_port[i].close_delay = 50 * HZ/100; sx_port[i].closing_wait = 3000 * HZ/100; init_waitqueue_head(&sx_port[i].open_wait); @@ -2473,7 +2477,7 @@ static int __init specialix_init(void) i++; continue; } - pdev = pci_find_device (PCI_VENDOR_ID_SPECIALIX, + pdev = pci_get_device (PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_IO8, pdev); if (!pdev) break; @@ -2489,6 +2493,9 @@ static int __init specialix_init(void) if (!sx_probe(&sx_board[i])) found ++; } + /* May exit pci_get sequence early with lots of boards */ + if (pdev != NULL) + pci_dev_put(pdev); } #endif diff --git a/trunk/drivers/char/stallion.c b/trunk/drivers/char/stallion.c index 522e88e395cc..e45113a7a472 100644 --- a/trunk/drivers/char/stallion.c +++ b/trunk/drivers/char/stallion.c @@ -41,13 +41,12 @@ #include #include #include +#include #include #include -#ifdef CONFIG_PCI #include -#endif /*****************************************************************************/ @@ -63,45 +62,16 @@ #define BRD_ECH64PCI 27 #define BRD_EASYIOPCI 28 -/* - * Define a configuration structure to hold the board configuration. - * Need to set this up in the code (for now) with the boards that are - * to be configured into the system. This is what needs to be modified - * when adding/removing/modifying boards. Each line entry in the - * stl_brdconf[] array is a board. Each line contains io/irq/memory - * ranges for that board (as well as what type of board it is). - * Some examples: - * { BRD_EASYIO, 0x2a0, 0, 0, 10, 0 }, - * This line would configure an EasyIO board (4 or 8, no difference), - * at io address 2a0 and irq 10. - * Another example: - * { BRD_ECH, 0x2a8, 0x280, 0, 12, 0 }, - * This line will configure an EasyConnection 8/32 board at primary io - * address 2a8, secondary io address 280 and irq 12. - * Enter as many lines into this array as you want (only the first 4 - * will actually be used!). Any combination of EasyIO and EasyConnection - * boards can be specified. EasyConnection 8/32 boards can share their - * secondary io addresses between each other. - * - * NOTE: there is no need to put any entries in this table for PCI - * boards. They will be found automatically by the driver - provided - * PCI BIOS32 support is compiled into the kernel. - */ - -typedef struct { - int brdtype; +struct stlconf { + unsigned int brdtype; int ioaddr1; int ioaddr2; unsigned long memaddr; int irq; int irqtype; -} stlconf_t; - -static stlconf_t stl_brdconf[] = { - /*{ BRD_EASYIO, 0x2a0, 0, 0, 10, 0 },*/ }; -static int stl_nrbrds = ARRAY_SIZE(stl_brdconf); +static unsigned int stl_nrbrds; /*****************************************************************************/ @@ -143,20 +113,13 @@ static struct tty_driver *stl_serial; * with this termios initially. Basically all it defines is a raw port * at 9600, 8 data bits, 1 stop bit. */ -static struct termios stl_deftermios = { +static struct ktermios stl_deftermios = { .c_cflag = (B9600 | CS8 | CREAD | HUPCL | CLOCAL), .c_cc = INIT_C_CC, + .c_ispeed = 9600, + .c_ospeed = 9600, }; -/* - * Define global stats structures. Not used often, and can be - * re-used for each stats call. - */ -static comstats_t stl_comstats; -static combrd_t stl_brdstats; -static stlbrd_t stl_dummybrd; -static stlport_t stl_dummyport; - /* * Define global place to put buffer overflow characters. */ @@ -164,13 +127,16 @@ static char stl_unwanted[SC26198_RXFIFOSIZE]; /*****************************************************************************/ -static stlbrd_t *stl_brds[STL_MAXBRDS]; +static DEFINE_MUTEX(stl_brdslock); +static struct stlbrd *stl_brds[STL_MAXBRDS]; /* * Per board state flags. Used with the state field of the board struct. * Not really much here! */ #define BRD_FOUND 0x1 +#define STL_PROBED 0x2 + /* * Define the port structure istate flags. These set of flags are @@ -187,32 +153,32 @@ static stlbrd_t *stl_brds[STL_MAXBRDS]; * referencing boards when printing trace and stuff. */ static char *stl_brdnames[] = { - (char *) NULL, - (char *) NULL, - (char *) NULL, - (char *) NULL, - (char *) NULL, - (char *) NULL, - (char *) NULL, - (char *) NULL, - (char *) NULL, - (char *) NULL, - (char *) NULL, - (char *) NULL, - (char *) NULL, - (char *) NULL, - (char *) NULL, - (char *) NULL, - (char *) NULL, - (char *) NULL, - (char *) NULL, - (char *) NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, "EasyIO", "EC8/32-AT", "EC8/32-MC", - (char *) NULL, - (char *) NULL, - (char *) NULL, + NULL, + NULL, + NULL, "EC8/32-PCI", "EC8/64-PCI", "EasyIO-PCI", @@ -225,7 +191,7 @@ static char *stl_brdnames[] = { * load line. These allow for easy board definitions, and easy * modification of the io, memory and irq resoucres. */ -static int stl_nargs = 0; +static unsigned int stl_nargs; static char *board0[4]; static char *board1[4]; static char *board2[4]; @@ -243,12 +209,10 @@ static char **stl_brdsp[] = { * parse any module arguments. */ -typedef struct stlbrdtype { +static struct { char *name; int type; -} stlbrdtype_t; - -static stlbrdtype_t stl_brdstr[] = { +} stl_brdstr[] = { { "easyio", BRD_EASYIO }, { "eio", BRD_EASYIO }, { "20", BRD_EASYIO }, @@ -282,9 +246,6 @@ static stlbrdtype_t stl_brdstr[] = { /* * Define the module agruments. */ -MODULE_AUTHOR("Greg Ungerer"); -MODULE_DESCRIPTION("Stallion Multiport Serial Driver"); -MODULE_LICENSE("GPL"); module_param_array(board0, charp, &stl_nargs, 0); MODULE_PARM_DESC(board0, "Board 0 config -> name[,ioaddr[,ioaddr2][,irq]]"); @@ -386,8 +347,6 @@ static spinlock_t stallion_lock; /* Guard the tty driver */ /*****************************************************************************/ -#ifdef CONFIG_PCI - /* * Define the Stallion PCI vendor and device IDs. */ @@ -407,22 +366,19 @@ static spinlock_t stallion_lock; /* Guard the tty driver */ /* * Define structure to hold all Stallion PCI boards. */ -typedef struct stlpcibrd { - unsigned short vendid; - unsigned short devid; - int brdtype; -} stlpcibrd_t; - -static stlpcibrd_t stl_pcibrds[] = { - { PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECHPCI864, BRD_ECH64PCI }, - { PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_EIOPCI, BRD_EASYIOPCI }, - { PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECHPCI832, BRD_ECHPCI }, - { PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87410, BRD_ECHPCI }, -}; -static int stl_nrpcibrds = ARRAY_SIZE(stl_pcibrds); - -#endif +static struct pci_device_id stl_pcibrds[] = { + { PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECHPCI864), + .driver_data = BRD_ECH64PCI }, + { PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_EIOPCI), + .driver_data = BRD_EASYIOPCI }, + { PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECHPCI832), + .driver_data = BRD_ECHPCI }, + { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87410), + .driver_data = BRD_ECHPCI }, + { } +}; +MODULE_DEVICE_TABLE(pci, stl_pcibrds); /*****************************************************************************/ @@ -442,134 +398,74 @@ static unsigned int stl_baudrates[] = { 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600 }; -/* - * Define some handy local macros... - */ -#undef MIN -#define MIN(a,b) (((a) <= (b)) ? (a) : (b)) - -#undef TOLOWER -#define TOLOWER(x) ((((x) >= 'A') && ((x) <= 'Z')) ? ((x) + 0x20) : (x)) - /*****************************************************************************/ /* * Declare all those functions in this driver! */ -static void stl_argbrds(void); -static int stl_parsebrd(stlconf_t *confp, char **argp); - -static unsigned long stl_atol(char *str); - -static int stl_init(void); -static int stl_open(struct tty_struct *tty, struct file *filp); -static void stl_close(struct tty_struct *tty, struct file *filp); -static int stl_write(struct tty_struct *tty, const unsigned char *buf, int count); -static void stl_putchar(struct tty_struct *tty, unsigned char ch); -static void stl_flushchars(struct tty_struct *tty); -static int stl_writeroom(struct tty_struct *tty); -static int stl_charsinbuffer(struct tty_struct *tty); -static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg); -static void stl_settermios(struct tty_struct *tty, struct termios *old); -static void stl_throttle(struct tty_struct *tty); -static void stl_unthrottle(struct tty_struct *tty); -static void stl_stop(struct tty_struct *tty); -static void stl_start(struct tty_struct *tty); -static void stl_flushbuffer(struct tty_struct *tty); -static void stl_breakctl(struct tty_struct *tty, int state); -static void stl_waituntilsent(struct tty_struct *tty, int timeout); -static void stl_sendxchar(struct tty_struct *tty, char ch); -static void stl_hangup(struct tty_struct *tty); static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg); -static int stl_portinfo(stlport_t *portp, int portnr, char *pos); -static int stl_readproc(char *page, char **start, off_t off, int count, int *eof, void *data); - -static int stl_brdinit(stlbrd_t *brdp); -static int stl_initports(stlbrd_t *brdp, stlpanel_t *panelp); -static int stl_getserial(stlport_t *portp, struct serial_struct __user *sp); -static int stl_setserial(stlport_t *portp, struct serial_struct __user *sp); -static int stl_getbrdstats(combrd_t __user *bp); -static int stl_getportstats(stlport_t *portp, comstats_t __user *cp); -static int stl_clrportstats(stlport_t *portp, comstats_t __user *cp); -static int stl_getportstruct(stlport_t __user *arg); -static int stl_getbrdstruct(stlbrd_t __user *arg); -static int stl_waitcarrier(stlport_t *portp, struct file *filp); -static int stl_eiointr(stlbrd_t *brdp); -static int stl_echatintr(stlbrd_t *brdp); -static int stl_echmcaintr(stlbrd_t *brdp); -static int stl_echpciintr(stlbrd_t *brdp); -static int stl_echpci64intr(stlbrd_t *brdp); -static void stl_offintr(void *private); -static stlbrd_t *stl_allocbrd(void); -static stlport_t *stl_getport(int brdnr, int panelnr, int portnr); - -static inline int stl_initbrds(void); -static inline int stl_initeio(stlbrd_t *brdp); -static inline int stl_initech(stlbrd_t *brdp); -static inline int stl_getbrdnr(void); - -#ifdef CONFIG_PCI -static inline int stl_findpcibrds(void); -static inline int stl_initpcibrd(int brdtype, struct pci_dev *devp); -#endif +static int stl_brdinit(struct stlbrd *brdp); +static int stl_getportstats(struct stlport *portp, comstats_t __user *cp); +static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp); +static int stl_waitcarrier(struct stlport *portp, struct file *filp); /* * CD1400 uart specific handling functions. */ -static void stl_cd1400setreg(stlport_t *portp, int regnr, int value); -static int stl_cd1400getreg(stlport_t *portp, int regnr); -static int stl_cd1400updatereg(stlport_t *portp, int regnr, int value); -static int stl_cd1400panelinit(stlbrd_t *brdp, stlpanel_t *panelp); -static void stl_cd1400portinit(stlbrd_t *brdp, stlpanel_t *panelp, stlport_t *portp); -static void stl_cd1400setport(stlport_t *portp, struct termios *tiosp); -static int stl_cd1400getsignals(stlport_t *portp); -static void stl_cd1400setsignals(stlport_t *portp, int dtr, int rts); -static void stl_cd1400ccrwait(stlport_t *portp); -static void stl_cd1400enablerxtx(stlport_t *portp, int rx, int tx); -static void stl_cd1400startrxtx(stlport_t *portp, int rx, int tx); -static void stl_cd1400disableintrs(stlport_t *portp); -static void stl_cd1400sendbreak(stlport_t *portp, int len); -static void stl_cd1400flowctrl(stlport_t *portp, int state); -static void stl_cd1400sendflow(stlport_t *portp, int state); -static void stl_cd1400flush(stlport_t *portp); -static int stl_cd1400datastate(stlport_t *portp); -static void stl_cd1400eiointr(stlpanel_t *panelp, unsigned int iobase); -static void stl_cd1400echintr(stlpanel_t *panelp, unsigned int iobase); -static void stl_cd1400txisr(stlpanel_t *panelp, int ioaddr); -static void stl_cd1400rxisr(stlpanel_t *panelp, int ioaddr); -static void stl_cd1400mdmisr(stlpanel_t *panelp, int ioaddr); - -static inline int stl_cd1400breakisr(stlport_t *portp, int ioaddr); +static void stl_cd1400setreg(struct stlport *portp, int regnr, int value); +static int stl_cd1400getreg(struct stlport *portp, int regnr); +static int stl_cd1400updatereg(struct stlport *portp, int regnr, int value); +static int stl_cd1400panelinit(struct stlbrd *brdp, struct stlpanel *panelp); +static void stl_cd1400portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp); +static void stl_cd1400setport(struct stlport *portp, struct ktermios *tiosp); +static int stl_cd1400getsignals(struct stlport *portp); +static void stl_cd1400setsignals(struct stlport *portp, int dtr, int rts); +static void stl_cd1400ccrwait(struct stlport *portp); +static void stl_cd1400enablerxtx(struct stlport *portp, int rx, int tx); +static void stl_cd1400startrxtx(struct stlport *portp, int rx, int tx); +static void stl_cd1400disableintrs(struct stlport *portp); +static void stl_cd1400sendbreak(struct stlport *portp, int len); +static void stl_cd1400flowctrl(struct stlport *portp, int state); +static void stl_cd1400sendflow(struct stlport *portp, int state); +static void stl_cd1400flush(struct stlport *portp); +static int stl_cd1400datastate(struct stlport *portp); +static void stl_cd1400eiointr(struct stlpanel *panelp, unsigned int iobase); +static void stl_cd1400echintr(struct stlpanel *panelp, unsigned int iobase); +static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr); +static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr); +static void stl_cd1400mdmisr(struct stlpanel *panelp, int ioaddr); + +static inline int stl_cd1400breakisr(struct stlport *portp, int ioaddr); /* * SC26198 uart specific handling functions. */ -static void stl_sc26198setreg(stlport_t *portp, int regnr, int value); -static int stl_sc26198getreg(stlport_t *portp, int regnr); -static int stl_sc26198updatereg(stlport_t *portp, int regnr, int value); -static int stl_sc26198getglobreg(stlport_t *portp, int regnr); -static int stl_sc26198panelinit(stlbrd_t *brdp, stlpanel_t *panelp); -static void stl_sc26198portinit(stlbrd_t *brdp, stlpanel_t *panelp, stlport_t *portp); -static void stl_sc26198setport(stlport_t *portp, struct termios *tiosp); -static int stl_sc26198getsignals(stlport_t *portp); -static void stl_sc26198setsignals(stlport_t *portp, int dtr, int rts); -static void stl_sc26198enablerxtx(stlport_t *portp, int rx, int tx); -static void stl_sc26198startrxtx(stlport_t *portp, int rx, int tx); -static void stl_sc26198disableintrs(stlport_t *portp); -static void stl_sc26198sendbreak(stlport_t *portp, int len); -static void stl_sc26198flowctrl(stlport_t *portp, int state); -static void stl_sc26198sendflow(stlport_t *portp, int state); -static void stl_sc26198flush(stlport_t *portp); -static int stl_sc26198datastate(stlport_t *portp); -static void stl_sc26198wait(stlport_t *portp); -static void stl_sc26198txunflow(stlport_t *portp, struct tty_struct *tty); -static void stl_sc26198intr(stlpanel_t *panelp, unsigned int iobase); -static void stl_sc26198txisr(stlport_t *port); -static void stl_sc26198rxisr(stlport_t *port, unsigned int iack); -static void stl_sc26198rxbadch(stlport_t *portp, unsigned char status, char ch); -static void stl_sc26198rxbadchars(stlport_t *portp); -static void stl_sc26198otherisr(stlport_t *port, unsigned int iack); +static void stl_sc26198setreg(struct stlport *portp, int regnr, int value); +static int stl_sc26198getreg(struct stlport *portp, int regnr); +static int stl_sc26198updatereg(struct stlport *portp, int regnr, int value); +static int stl_sc26198getglobreg(struct stlport *portp, int regnr); +static int stl_sc26198panelinit(struct stlbrd *brdp, struct stlpanel *panelp); +static void stl_sc26198portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp); +static void stl_sc26198setport(struct stlport *portp, struct ktermios *tiosp); +static int stl_sc26198getsignals(struct stlport *portp); +static void stl_sc26198setsignals(struct stlport *portp, int dtr, int rts); +static void stl_sc26198enablerxtx(struct stlport *portp, int rx, int tx); +static void stl_sc26198startrxtx(struct stlport *portp, int rx, int tx); +static void stl_sc26198disableintrs(struct stlport *portp); +static void stl_sc26198sendbreak(struct stlport *portp, int len); +static void stl_sc26198flowctrl(struct stlport *portp, int state); +static void stl_sc26198sendflow(struct stlport *portp, int state); +static void stl_sc26198flush(struct stlport *portp); +static int stl_sc26198datastate(struct stlport *portp); +static void stl_sc26198wait(struct stlport *portp); +static void stl_sc26198txunflow(struct stlport *portp, struct tty_struct *tty); +static void stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase); +static void stl_sc26198txisr(struct stlport *port); +static void stl_sc26198rxisr(struct stlport *port, unsigned int iack); +static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char ch); +static void stl_sc26198rxbadchars(struct stlport *portp); +static void stl_sc26198otherisr(struct stlport *port, unsigned int iack); /*****************************************************************************/ @@ -577,20 +473,20 @@ static void stl_sc26198otherisr(stlport_t *port, unsigned int iack); * Generic UART support structure. */ typedef struct uart { - int (*panelinit)(stlbrd_t *brdp, stlpanel_t *panelp); - void (*portinit)(stlbrd_t *brdp, stlpanel_t *panelp, stlport_t *portp); - void (*setport)(stlport_t *portp, struct termios *tiosp); - int (*getsignals)(stlport_t *portp); - void (*setsignals)(stlport_t *portp, int dtr, int rts); - void (*enablerxtx)(stlport_t *portp, int rx, int tx); - void (*startrxtx)(stlport_t *portp, int rx, int tx); - void (*disableintrs)(stlport_t *portp); - void (*sendbreak)(stlport_t *portp, int len); - void (*flowctrl)(stlport_t *portp, int state); - void (*sendflow)(stlport_t *portp, int state); - void (*flush)(stlport_t *portp); - int (*datastate)(stlport_t *portp); - void (*intr)(stlpanel_t *panelp, unsigned int iobase); + int (*panelinit)(struct stlbrd *brdp, struct stlpanel *panelp); + void (*portinit)(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp); + void (*setport)(struct stlport *portp, struct ktermios *tiosp); + int (*getsignals)(struct stlport *portp); + void (*setsignals)(struct stlport *portp, int dtr, int rts); + void (*enablerxtx)(struct stlport *portp, int rx, int tx); + void (*startrxtx)(struct stlport *portp, int rx, int tx); + void (*disableintrs)(struct stlport *portp); + void (*sendbreak)(struct stlport *portp, int len); + void (*flowctrl)(struct stlport *portp, int state); + void (*sendflow)(struct stlport *portp, int state); + void (*flush)(struct stlport *portp); + int (*datastate)(struct stlport *portp); + void (*intr)(struct stlpanel *panelp, unsigned int iobase); } uart_t; /* @@ -712,184 +608,35 @@ static const struct file_operations stl_fsiomem = { .ioctl = stl_memioctl, }; -/*****************************************************************************/ - static struct class *stallion_class; -/* - * Loadable module initialization stuff. - */ - -static int __init stallion_module_init(void) -{ - stl_init(); - return 0; -} - -/*****************************************************************************/ - -static void __exit stallion_module_exit(void) -{ - stlbrd_t *brdp; - stlpanel_t *panelp; - stlport_t *portp; - int i, j, k; - -#ifdef DEBUG - printk("cleanup_module()\n"); -#endif - - printk(KERN_INFO "Unloading %s: version %s\n", stl_drvtitle, - stl_drvversion); - -/* - * Free up all allocated resources used by the ports. This includes - * memory and interrupts. As part of this process we will also do - * a hangup on every open port - to try to flush out any processes - * hanging onto ports. - */ - i = tty_unregister_driver(stl_serial); - put_tty_driver(stl_serial); - if (i) { - printk("STALLION: failed to un-register tty driver, " - "errno=%d\n", -i); - return; - } - for (i = 0; i < 4; i++) - class_device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i)); - if ((i = unregister_chrdev(STL_SIOMEMMAJOR, "staliomem"))) - printk("STALLION: failed to un-register serial memory device, " - "errno=%d\n", -i); - class_destroy(stallion_class); - - for (i = 0; (i < stl_nrbrds); i++) { - if ((brdp = stl_brds[i]) == (stlbrd_t *) NULL) - continue; - - free_irq(brdp->irq, brdp); - - for (j = 0; (j < STL_MAXPANELS); j++) { - panelp = brdp->panels[j]; - if (panelp == (stlpanel_t *) NULL) - continue; - for (k = 0; (k < STL_PORTSPERPANEL); k++) { - portp = panelp->ports[k]; - if (portp == (stlport_t *) NULL) - continue; - if (portp->tty != (struct tty_struct *) NULL) - stl_hangup(portp->tty); - kfree(portp->tx.buf); - kfree(portp); - } - kfree(panelp); - } - - release_region(brdp->ioaddr1, brdp->iosize1); - if (brdp->iosize2 > 0) - release_region(brdp->ioaddr2, brdp->iosize2); - - kfree(brdp); - stl_brds[i] = (stlbrd_t *) NULL; - } -} - -module_init(stallion_module_init); -module_exit(stallion_module_exit); - -/*****************************************************************************/ - /* * Check for any arguments passed in on the module load command line. */ -static void stl_argbrds(void) -{ - stlconf_t conf; - stlbrd_t *brdp; - int i; - -#ifdef DEBUG - printk("stl_argbrds()\n"); -#endif - - for (i = stl_nrbrds; (i < stl_nargs); i++) { - memset(&conf, 0, sizeof(conf)); - if (stl_parsebrd(&conf, stl_brdsp[i]) == 0) - continue; - if ((brdp = stl_allocbrd()) == (stlbrd_t *) NULL) - continue; - stl_nrbrds = i + 1; - brdp->brdnr = i; - brdp->brdtype = conf.brdtype; - brdp->ioaddr1 = conf.ioaddr1; - brdp->ioaddr2 = conf.ioaddr2; - brdp->irq = conf.irq; - brdp->irqtype = conf.irqtype; - stl_brdinit(brdp); - } -} - -/*****************************************************************************/ - -/* - * Convert an ascii string number into an unsigned long. - */ - -static unsigned long stl_atol(char *str) -{ - unsigned long val; - int base, c; - char *sp; - - val = 0; - sp = str; - if ((*sp == '0') && (*(sp+1) == 'x')) { - base = 16; - sp += 2; - } else if (*sp == '0') { - base = 8; - sp++; - } else { - base = 10; - } - - for (; (*sp != 0); sp++) { - c = (*sp > '9') ? (TOLOWER(*sp) - 'a' + 10) : (*sp - '0'); - if ((c < 0) || (c >= base)) { - printk("STALLION: invalid argument %s\n", str); - val = 0; - break; - } - val = (val * base) + c; - } - return val; -} - /*****************************************************************************/ /* * Parse the supplied argument string, into the board conf struct. */ -static int stl_parsebrd(stlconf_t *confp, char **argp) +static int __init stl_parsebrd(struct stlconf *confp, char **argp) { char *sp; - int i; + unsigned int i; -#ifdef DEBUG - printk("stl_parsebrd(confp=%x,argp=%x)\n", (int) confp, (int) argp); -#endif + pr_debug("stl_parsebrd(confp=%p,argp=%p)\n", confp, argp); - if ((argp[0] == (char *) NULL) || (*argp[0] == 0)) + if ((argp[0] == NULL) || (*argp[0] == 0)) return 0; - for (sp = argp[0], i = 0; ((*sp != 0) && (i < 25)); sp++, i++) - *sp = TOLOWER(*sp); + for (sp = argp[0], i = 0; (*sp != 0) && (i < 25); sp++, i++) + *sp = tolower(*sp); - for (i = 0; i < ARRAY_SIZE(stl_brdstr); i++) { + for (i = 0; i < ARRAY_SIZE(stl_brdstr); i++) if (strcmp(stl_brdstr[i].name, argp[0]) == 0) break; - } + if (i == ARRAY_SIZE(stl_brdstr)) { printk("STALLION: unknown board name, %s?\n", argp[0]); return 0; @@ -898,16 +645,16 @@ static int stl_parsebrd(stlconf_t *confp, char **argp) confp->brdtype = stl_brdstr[i].type; i = 1; - if ((argp[i] != (char *) NULL) && (*argp[i] != 0)) - confp->ioaddr1 = stl_atol(argp[i]); + if ((argp[i] != NULL) && (*argp[i] != 0)) + confp->ioaddr1 = simple_strtoul(argp[i], NULL, 0); i++; if (confp->brdtype == BRD_ECH) { - if ((argp[i] != (char *) NULL) && (*argp[i] != 0)) - confp->ioaddr2 = stl_atol(argp[i]); + if ((argp[i] != NULL) && (*argp[i] != 0)) + confp->ioaddr2 = simple_strtoul(argp[i], NULL, 0); i++; } - if ((argp[i] != (char *) NULL) && (*argp[i] != 0)) - confp->irq = stl_atol(argp[i]); + if ((argp[i] != NULL) && (*argp[i] != 0)) + confp->irq = simple_strtoul(argp[i], NULL, 0); return 1; } @@ -917,14 +664,14 @@ static int stl_parsebrd(stlconf_t *confp, char **argp) * Allocate a new board structure. Fill out the basic info in it. */ -static stlbrd_t *stl_allocbrd(void) +static struct stlbrd *stl_allocbrd(void) { - stlbrd_t *brdp; + struct stlbrd *brdp; - brdp = kzalloc(sizeof(stlbrd_t), GFP_KERNEL); + brdp = kzalloc(sizeof(struct stlbrd), GFP_KERNEL); if (!brdp) { printk("STALLION: failed to allocate memory (size=%Zd)\n", - sizeof(stlbrd_t)); + sizeof(struct stlbrd)); return NULL; } @@ -936,26 +683,23 @@ static stlbrd_t *stl_allocbrd(void) static int stl_open(struct tty_struct *tty, struct file *filp) { - stlport_t *portp; - stlbrd_t *brdp; - unsigned int minordev; - int brdnr, panelnr, portnr, rc; - -#ifdef DEBUG - printk("stl_open(tty=%x,filp=%x): device=%s\n", (int) tty, - (int) filp, tty->name); -#endif + struct stlport *portp; + struct stlbrd *brdp; + unsigned int minordev, brdnr, panelnr; + int portnr, rc; + + pr_debug("stl_open(tty=%p,filp=%p): device=%s\n", tty, filp, tty->name); minordev = tty->index; brdnr = MINOR2BRD(minordev); if (brdnr >= stl_nrbrds) return -ENODEV; brdp = stl_brds[brdnr]; - if (brdp == (stlbrd_t *) NULL) + if (brdp == NULL) return -ENODEV; minordev = MINOR2PORT(minordev); - for (portnr = -1, panelnr = 0; (panelnr < STL_MAXPANELS); panelnr++) { - if (brdp->panels[panelnr] == (stlpanel_t *) NULL) + for (portnr = -1, panelnr = 0; panelnr < STL_MAXPANELS; panelnr++) { + if (brdp->panels[panelnr] == NULL) break; if (minordev < brdp->panels[panelnr]->nrports) { portnr = minordev; @@ -967,7 +711,7 @@ static int stl_open(struct tty_struct *tty, struct file *filp) return -ENODEV; portp = brdp->panels[panelnr]->ports[portnr]; - if (portp == (stlport_t *) NULL) + if (portp == NULL) return -ENODEV; /* @@ -1013,10 +757,10 @@ static int stl_open(struct tty_struct *tty, struct file *filp) * previous opens still in effect. If we are a normal serial device * then also we might have to wait for carrier. */ - if (!(filp->f_flags & O_NONBLOCK)) { + if (!(filp->f_flags & O_NONBLOCK)) if ((rc = stl_waitcarrier(portp, filp)) != 0) return rc; - } + portp->flags |= ASYNC_NORMAL_ACTIVE; return 0; @@ -1029,14 +773,12 @@ static int stl_open(struct tty_struct *tty, struct file *filp) * maybe because if we are clocal then we don't need to wait... */ -static int stl_waitcarrier(stlport_t *portp, struct file *filp) +static int stl_waitcarrier(struct stlport *portp, struct file *filp) { unsigned long flags; int rc, doclocal; -#ifdef DEBUG - printk("stl_waitcarrier(portp=%x,filp=%x)\n", (int) portp, (int) filp); -#endif + pr_debug("stl_waitcarrier(portp=%p,filp=%p)\n", portp, filp); rc = 0; doclocal = 0; @@ -1062,9 +804,8 @@ static int stl_waitcarrier(stlport_t *portp, struct file *filp) break; } if (((portp->flags & ASYNC_CLOSING) == 0) && - (doclocal || (portp->sigs & TIOCM_CD))) { + (doclocal || (portp->sigs & TIOCM_CD))) break; - } if (signal_pending(current)) { rc = -ERESTARTSYS; break; @@ -1083,17 +824,61 @@ static int stl_waitcarrier(stlport_t *portp, struct file *filp) /*****************************************************************************/ +static void stl_flushbuffer(struct tty_struct *tty) +{ + struct stlport *portp; + + pr_debug("stl_flushbuffer(tty=%p)\n", tty); + + if (tty == NULL) + return; + portp = tty->driver_data; + if (portp == NULL) + return; + + stl_flush(portp); + tty_wakeup(tty); +} + +/*****************************************************************************/ + +static void stl_waituntilsent(struct tty_struct *tty, int timeout) +{ + struct stlport *portp; + unsigned long tend; + + pr_debug("stl_waituntilsent(tty=%p,timeout=%d)\n", tty, timeout); + + if (tty == NULL) + return; + portp = tty->driver_data; + if (portp == NULL) + return; + + if (timeout == 0) + timeout = HZ; + tend = jiffies + timeout; + + while (stl_datastate(portp)) { + if (signal_pending(current)) + break; + msleep_interruptible(20); + if (time_after_eq(jiffies, tend)) + break; + } +} + +/*****************************************************************************/ + static void stl_close(struct tty_struct *tty, struct file *filp) { - stlport_t *portp; + struct stlport *portp; unsigned long flags; -#ifdef DEBUG - printk("stl_close(tty=%x,filp=%x)\n", (int) tty, (int) filp); -#endif + pr_debug("stl_close(tty=%p,filp=%p)\n", tty, filp); portp = tty->driver_data; - if (portp == (stlport_t *) NULL) + if (portp == NULL) return; spin_lock_irqsave(&stallion_lock, flags); @@ -1136,17 +921,17 @@ static void stl_close(struct tty_struct *tty, struct file *filp) stl_enablerxtx(portp, 0, 0); stl_flushbuffer(tty); portp->istate = 0; - if (portp->tx.buf != (char *) NULL) { + if (portp->tx.buf != NULL) { kfree(portp->tx.buf); - portp->tx.buf = (char *) NULL; - portp->tx.head = (char *) NULL; - portp->tx.tail = (char *) NULL; + portp->tx.buf = NULL; + portp->tx.head = NULL; + portp->tx.tail = NULL; } set_bit(TTY_IO_ERROR, &tty->flags); tty_ldisc_flush(tty); tty->closing = 0; - portp->tty = (struct tty_struct *) NULL; + portp->tty = NULL; if (portp->openwaitcnt) { if (portp->close_delay) @@ -1167,20 +952,17 @@ static void stl_close(struct tty_struct *tty, struct file *filp) static int stl_write(struct tty_struct *tty, const unsigned char *buf, int count) { - stlport_t *portp; + struct stlport *portp; unsigned int len, stlen; unsigned char *chbuf; char *head, *tail; -#ifdef DEBUG - printk("stl_write(tty=%x,buf=%x,count=%d)\n", - (int) tty, (int) buf, count); -#endif + pr_debug("stl_write(tty=%p,buf=%p,count=%d)\n", tty, buf, count); portp = tty->driver_data; - if (portp == (stlport_t *) NULL) + if (portp == NULL) return 0; - if (portp->tx.buf == (char *) NULL) + if (portp->tx.buf == NULL) return 0; /* @@ -1201,10 +983,10 @@ static int stl_write(struct tty_struct *tty, const unsigned char *buf, int count stlen = len; } - len = MIN(len, count); + len = min(len, (unsigned int)count); count = 0; while (len > 0) { - stlen = MIN(len, stlen); + stlen = min(len, stlen); memcpy(head, chbuf, stlen); len -= stlen; chbuf += stlen; @@ -1227,20 +1009,18 @@ static int stl_write(struct tty_struct *tty, const unsigned char *buf, int count static void stl_putchar(struct tty_struct *tty, unsigned char ch) { - stlport_t *portp; + struct stlport *portp; unsigned int len; char *head, *tail; -#ifdef DEBUG - printk("stl_putchar(tty=%x,ch=%x)\n", (int) tty, (int) ch); -#endif + pr_debug("stl_putchar(tty=%p,ch=%x)\n", tty, ch); - if (tty == (struct tty_struct *) NULL) + if (tty == NULL) return; portp = tty->driver_data; - if (portp == (stlport_t *) NULL) + if (portp == NULL) return; - if (portp->tx.buf == (char *) NULL) + if (portp->tx.buf == NULL) return; head = portp->tx.head; @@ -1267,18 +1047,16 @@ static void stl_putchar(struct tty_struct *tty, unsigned char ch) static void stl_flushchars(struct tty_struct *tty) { - stlport_t *portp; + struct stlport *portp; -#ifdef DEBUG - printk("stl_flushchars(tty=%x)\n", (int) tty); -#endif + pr_debug("stl_flushchars(tty=%p)\n", tty); - if (tty == (struct tty_struct *) NULL) + if (tty == NULL) return; portp = tty->driver_data; - if (portp == (stlport_t *) NULL) + if (portp == NULL) return; - if (portp->tx.buf == (char *) NULL) + if (portp->tx.buf == NULL) return; stl_startrxtx(portp, -1, 1); @@ -1288,24 +1066,22 @@ static void stl_flushchars(struct tty_struct *tty) static int stl_writeroom(struct tty_struct *tty) { - stlport_t *portp; + struct stlport *portp; char *head, *tail; -#ifdef DEBUG - printk("stl_writeroom(tty=%x)\n", (int) tty); -#endif + pr_debug("stl_writeroom(tty=%p)\n", tty); - if (tty == (struct tty_struct *) NULL) + if (tty == NULL) return 0; portp = tty->driver_data; - if (portp == (stlport_t *) NULL) + if (portp == NULL) return 0; - if (portp->tx.buf == (char *) NULL) + if (portp->tx.buf == NULL) return 0; head = portp->tx.head; tail = portp->tx.tail; - return ((head >= tail) ? (STL_TXBUFSIZE - (head - tail) - 1) : (tail - head - 1)); + return (head >= tail) ? (STL_TXBUFSIZE - (head - tail) - 1) : (tail - head - 1); } /*****************************************************************************/ @@ -1321,20 +1097,18 @@ static int stl_writeroom(struct tty_struct *tty) static int stl_charsinbuffer(struct tty_struct *tty) { - stlport_t *portp; + struct stlport *portp; unsigned int size; char *head, *tail; -#ifdef DEBUG - printk("stl_charsinbuffer(tty=%x)\n", (int) tty); -#endif + pr_debug("stl_charsinbuffer(tty=%p)\n", tty); - if (tty == (struct tty_struct *) NULL) + if (tty == NULL) return 0; portp = tty->driver_data; - if (portp == (stlport_t *) NULL) + if (portp == NULL) return 0; - if (portp->tx.buf == (char *) NULL) + if (portp->tx.buf == NULL) return 0; head = portp->tx.head; @@ -1351,14 +1125,12 @@ static int stl_charsinbuffer(struct tty_struct *tty) * Generate the serial struct info. */ -static int stl_getserial(stlport_t *portp, struct serial_struct __user *sp) +static int stl_getserial(struct stlport *portp, struct serial_struct __user *sp) { struct serial_struct sio; - stlbrd_t *brdp; + struct stlbrd *brdp; -#ifdef DEBUG - printk("stl_getserial(portp=%x,sp=%x)\n", (int) portp, (int) sp); -#endif + pr_debug("stl_getserial(portp=%p,sp=%p)\n", portp, sp); memset(&sio, 0, sizeof(struct serial_struct)); sio.line = portp->portnr; @@ -1378,7 +1150,7 @@ static int stl_getserial(stlport_t *portp, struct serial_struct __user *sp) } brdp = stl_brds[portp->brdnr]; - if (brdp != (stlbrd_t *) NULL) + if (brdp != NULL) sio.irq = brdp->irq; return copy_to_user(sp, &sio, sizeof(struct serial_struct)) ? -EFAULT : 0; @@ -1392,13 +1164,11 @@ static int stl_getserial(stlport_t *portp, struct serial_struct __user *sp) * just quietly ignore any requests to change irq, etc. */ -static int stl_setserial(stlport_t *portp, struct serial_struct __user *sp) +static int stl_setserial(struct stlport *portp, struct serial_struct __user *sp) { struct serial_struct sio; -#ifdef DEBUG - printk("stl_setserial(portp=%x,sp=%x)\n", (int) portp, (int) sp); -#endif + pr_debug("stl_setserial(portp=%p,sp=%p)\n", portp, sp); if (copy_from_user(&sio, sp, sizeof(struct serial_struct))) return -EFAULT; @@ -1424,12 +1194,12 @@ static int stl_setserial(stlport_t *portp, struct serial_struct __user *sp) static int stl_tiocmget(struct tty_struct *tty, struct file *file) { - stlport_t *portp; + struct stlport *portp; - if (tty == (struct tty_struct *) NULL) + if (tty == NULL) return -ENODEV; portp = tty->driver_data; - if (portp == (stlport_t *) NULL) + if (portp == NULL) return -ENODEV; if (tty->flags & (1 << TTY_IO_ERROR)) return -EIO; @@ -1440,13 +1210,13 @@ static int stl_tiocmget(struct tty_struct *tty, struct file *file) static int stl_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear) { - stlport_t *portp; + struct stlport *portp; int rts = -1, dtr = -1; - if (tty == (struct tty_struct *) NULL) + if (tty == NULL) return -ENODEV; portp = tty->driver_data; - if (portp == (stlport_t *) NULL) + if (portp == NULL) return -ENODEV; if (tty->flags & (1 << TTY_IO_ERROR)) return -EIO; @@ -1466,27 +1236,24 @@ static int stl_tiocmset(struct tty_struct *tty, struct file *file, static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg) { - stlport_t *portp; + struct stlport *portp; unsigned int ival; int rc; void __user *argp = (void __user *)arg; -#ifdef DEBUG - printk("stl_ioctl(tty=%x,file=%x,cmd=%x,arg=%x)\n", - (int) tty, (int) file, cmd, (int) arg); -#endif + pr_debug("stl_ioctl(tty=%p,file=%p,cmd=%x,arg=%lx)\n", tty, file, cmd, + arg); - if (tty == (struct tty_struct *) NULL) + if (tty == NULL) return -ENODEV; portp = tty->driver_data; - if (portp == (stlport_t *) NULL) + if (portp == NULL) return -ENODEV; if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && - (cmd != COM_GETPORTSTATS) && (cmd != COM_CLRPORTSTATS)) { + (cmd != COM_GETPORTSTATS) && (cmd != COM_CLRPORTSTATS)) if (tty->flags & (1 << TTY_IO_ERROR)) return -EIO; - } rc = 0; @@ -1531,19 +1298,37 @@ static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd /*****************************************************************************/ -static void stl_settermios(struct tty_struct *tty, struct termios *old) +/* + * Start the transmitter again. Just turn TX interrupts back on. + */ + +static void stl_start(struct tty_struct *tty) { - stlport_t *portp; - struct termios *tiosp; + struct stlport *portp; -#ifdef DEBUG - printk("stl_settermios(tty=%x,old=%x)\n", (int) tty, (int) old); -#endif + pr_debug("stl_start(tty=%p)\n", tty); - if (tty == (struct tty_struct *) NULL) + if (tty == NULL) return; portp = tty->driver_data; - if (portp == (stlport_t *) NULL) + if (portp == NULL) + return; + stl_startrxtx(portp, -1, 1); +} + +/*****************************************************************************/ + +static void stl_settermios(struct tty_struct *tty, struct ktermios *old) +{ + struct stlport *portp; + struct ktermios *tiosp; + + pr_debug("stl_settermios(tty=%p,old=%p)\n", tty, old); + + if (tty == NULL) + return; + portp = tty->driver_data; + if (portp == NULL) return; tiosp = tty->termios; @@ -1571,16 +1356,14 @@ static void stl_settermios(struct tty_struct *tty, struct termios *old) static void stl_throttle(struct tty_struct *tty) { - stlport_t *portp; + struct stlport *portp; -#ifdef DEBUG - printk("stl_throttle(tty=%x)\n", (int) tty); -#endif + pr_debug("stl_throttle(tty=%p)\n", tty); - if (tty == (struct tty_struct *) NULL) + if (tty == NULL) return; portp = tty->driver_data; - if (portp == (stlport_t *) NULL) + if (portp == NULL) return; stl_flowctrl(portp, 0); } @@ -1593,16 +1376,14 @@ static void stl_throttle(struct tty_struct *tty) static void stl_unthrottle(struct tty_struct *tty) { - stlport_t *portp; + struct stlport *portp; -#ifdef DEBUG - printk("stl_unthrottle(tty=%x)\n", (int) tty); -#endif + pr_debug("stl_unthrottle(tty=%p)\n", tty); - if (tty == (struct tty_struct *) NULL) + if (tty == NULL) return; portp = tty->driver_data; - if (portp == (stlport_t *) NULL) + if (portp == NULL) return; stl_flowctrl(portp, 1); } @@ -1616,44 +1397,20 @@ static void stl_unthrottle(struct tty_struct *tty) static void stl_stop(struct tty_struct *tty) { - stlport_t *portp; + struct stlport *portp; -#ifdef DEBUG - printk("stl_stop(tty=%x)\n", (int) tty); -#endif + pr_debug("stl_stop(tty=%p)\n", tty); - if (tty == (struct tty_struct *) NULL) + if (tty == NULL) return; portp = tty->driver_data; - if (portp == (stlport_t *) NULL) + if (portp == NULL) return; stl_startrxtx(portp, -1, 0); } /*****************************************************************************/ -/* - * Start the transmitter again. Just turn TX interrupts back on. - */ - -static void stl_start(struct tty_struct *tty) -{ - stlport_t *portp; - -#ifdef DEBUG - printk("stl_start(tty=%x)\n", (int) tty); -#endif - - if (tty == (struct tty_struct *) NULL) - return; - portp = tty->driver_data; - if (portp == (stlport_t *) NULL) - return; - stl_startrxtx(portp, -1, 1); -} - -/*****************************************************************************/ - /* * Hangup this port. This is pretty much like closing the port, only * a little more brutal. No waiting for data to drain. Shutdown the @@ -1662,16 +1419,14 @@ static void stl_start(struct tty_struct *tty) static void stl_hangup(struct tty_struct *tty) { - stlport_t *portp; + struct stlport *portp; -#ifdef DEBUG - printk("stl_hangup(tty=%x)\n", (int) tty); -#endif + pr_debug("stl_hangup(tty=%p)\n", tty); - if (tty == (struct tty_struct *) NULL) + if (tty == NULL) return; portp = tty->driver_data; - if (portp == (stlport_t *) NULL) + if (portp == NULL) return; portp->flags &= ~ASYNC_INITIALIZED; @@ -1682,13 +1437,13 @@ static void stl_hangup(struct tty_struct *tty) stl_flushbuffer(tty); portp->istate = 0; set_bit(TTY_IO_ERROR, &tty->flags); - if (portp->tx.buf != (char *) NULL) { + if (portp->tx.buf != NULL) { kfree(portp->tx.buf); - portp->tx.buf = (char *) NULL; - portp->tx.head = (char *) NULL; - portp->tx.tail = (char *) NULL; + portp->tx.buf = NULL; + portp->tx.head = NULL; + portp->tx.tail = NULL; } - portp->tty = (struct tty_struct *) NULL; + portp->tty = NULL; portp->flags &= ~ASYNC_NORMAL_ACTIVE; portp->refcount = 0; wake_up_interruptible(&portp->open_wait); @@ -1696,38 +1451,16 @@ static void stl_hangup(struct tty_struct *tty) /*****************************************************************************/ -static void stl_flushbuffer(struct tty_struct *tty) -{ - stlport_t *portp; - -#ifdef DEBUG - printk("stl_flushbuffer(tty=%x)\n", (int) tty); -#endif - - if (tty == (struct tty_struct *) NULL) - return; - portp = tty->driver_data; - if (portp == (stlport_t *) NULL) - return; - - stl_flush(portp); - tty_wakeup(tty); -} - -/*****************************************************************************/ - static void stl_breakctl(struct tty_struct *tty, int state) { - stlport_t *portp; + struct stlport *portp; -#ifdef DEBUG - printk("stl_breakctl(tty=%x,state=%d)\n", (int) tty, state); -#endif + pr_debug("stl_breakctl(tty=%p,state=%d)\n", tty, state); - if (tty == (struct tty_struct *) NULL) + if (tty == NULL) return; portp = tty->driver_data; - if (portp == (stlport_t *) NULL) + if (portp == NULL) return; stl_sendbreak(portp, ((state == -1) ? 1 : 2)); @@ -1735,48 +1468,16 @@ static void stl_breakctl(struct tty_struct *tty, int state) /*****************************************************************************/ -static void stl_waituntilsent(struct tty_struct *tty, int timeout) -{ - stlport_t *portp; - unsigned long tend; - -#ifdef DEBUG - printk("stl_waituntilsent(tty=%x,timeout=%d)\n", (int) tty, timeout); -#endif - - if (tty == (struct tty_struct *) NULL) - return; - portp = tty->driver_data; - if (portp == (stlport_t *) NULL) - return; - - if (timeout == 0) - timeout = HZ; - tend = jiffies + timeout; - - while (stl_datastate(portp)) { - if (signal_pending(current)) - break; - msleep_interruptible(20); - if (time_after_eq(jiffies, tend)) - break; - } -} - -/*****************************************************************************/ - static void stl_sendxchar(struct tty_struct *tty, char ch) { - stlport_t *portp; + struct stlport *portp; -#ifdef DEBUG - printk("stl_sendxchar(tty=%x,ch=%x)\n", (int) tty, ch); -#endif + pr_debug("stl_sendxchar(tty=%p,ch=%x)\n", tty, ch); - if (tty == (struct tty_struct *) NULL) + if (tty == NULL) return; portp = tty->driver_data; - if (portp == (stlport_t *) NULL) + if (portp == NULL) return; if (ch == STOP_CHAR(tty)) @@ -1797,7 +1498,7 @@ static void stl_sendxchar(struct tty_struct *tty, char ch) * short then padded with spaces). */ -static int stl_portinfo(stlport_t *portp, int portnr, char *pos) +static int stl_portinfo(struct stlport *portp, int portnr, char *pos) { char *sp; int sigs, cnt; @@ -1826,7 +1527,7 @@ static int stl_portinfo(stlport_t *portp, int portnr, char *pos) *sp = ' '; sp += cnt; - for (cnt = (sp - pos); (cnt < (MAXLINE - 1)); cnt++) + for (cnt = sp - pos; cnt < (MAXLINE - 1); cnt++) *sp++ = ' '; if (cnt >= MAXLINE) pos[(MAXLINE - 2)] = '+'; @@ -1843,18 +1544,15 @@ static int stl_portinfo(stlport_t *portp, int portnr, char *pos) static int stl_readproc(char *page, char **start, off_t off, int count, int *eof, void *data) { - stlbrd_t *brdp; - stlpanel_t *panelp; - stlport_t *portp; - int brdnr, panelnr, portnr, totalport; - int curoff, maxoff; + struct stlbrd *brdp; + struct stlpanel *panelp; + struct stlport *portp; + unsigned int brdnr, panelnr, portnr; + int totalport, curoff, maxoff; char *pos; -#ifdef DEBUG - printk("stl_readproc(page=%x,start=%x,off=%x,count=%d,eof=%x," - "data=%x\n", (int) page, (int) start, (int) off, count, - (int) eof, (int) data); -#endif + pr_debug("stl_readproc(page=%p,start=%p,off=%lx,count=%d,eof=%p," + "data=%p\n", page, start, off, count, eof, data); pos = page; totalport = 0; @@ -1873,9 +1571,9 @@ static int stl_readproc(char *page, char **start, off_t off, int count, int *eof * We scan through for each board, panel and port. The offset is * calculated on the fly, and irrelevant ports are skipped. */ - for (brdnr = 0; (brdnr < stl_nrbrds); brdnr++) { + for (brdnr = 0; brdnr < stl_nrbrds; brdnr++) { brdp = stl_brds[brdnr]; - if (brdp == (stlbrd_t *) NULL) + if (brdp == NULL) continue; if (brdp->state == 0) continue; @@ -1887,9 +1585,9 @@ static int stl_readproc(char *page, char **start, off_t off, int count, int *eof } totalport = brdnr * STL_MAXPORTS; - for (panelnr = 0; (panelnr < brdp->nrpanels); panelnr++) { + for (panelnr = 0; panelnr < brdp->nrpanels; panelnr++) { panelp = brdp->panels[panelnr]; - if (panelp == (stlpanel_t *) NULL) + if (panelp == NULL) continue; maxoff = curoff + (panelp->nrports * MAXLINE); @@ -1899,10 +1597,10 @@ static int stl_readproc(char *page, char **start, off_t off, int count, int *eof continue; } - for (portnr = 0; (portnr < panelp->nrports); portnr++, + for (portnr = 0; portnr < panelp->nrports; portnr++, totalport++) { portp = panelp->ports[portnr]; - if (portp == (stlport_t *) NULL) + if (portp == NULL) continue; if (off >= (curoff += MAXLINE)) continue; @@ -1917,7 +1615,7 @@ static int stl_readproc(char *page, char **start, off_t off, int count, int *eof stl_readdone: *start = page; - return (pos - page); + return pos - page; } /*****************************************************************************/ @@ -1929,11 +1627,9 @@ static int stl_readproc(char *page, char **start, off_t off, int count, int *eof static irqreturn_t stl_intr(int irq, void *dev_id) { - stlbrd_t *brdp = (stlbrd_t *) dev_id; + struct stlbrd *brdp = dev_id; -#ifdef DEBUG - printk("stl_intr(brdp=%x,irq=%d)\n", (int) brdp, irq); -#endif + pr_debug("stl_intr(brdp=%p,irq=%d)\n", brdp, irq); return IRQ_RETVAL((* brdp->isr)(brdp)); } @@ -1944,9 +1640,9 @@ static irqreturn_t stl_intr(int irq, void *dev_id) * Interrupt service routine for EasyIO board types. */ -static int stl_eiointr(stlbrd_t *brdp) +static int stl_eiointr(struct stlbrd *brdp) { - stlpanel_t *panelp; + struct stlpanel *panelp; unsigned int iobase; int handled = 0; @@ -1967,18 +1663,17 @@ static int stl_eiointr(stlbrd_t *brdp) * Interrupt service routine for ECH-AT board types. */ -static int stl_echatintr(stlbrd_t *brdp) +static int stl_echatintr(struct stlbrd *brdp) { - stlpanel_t *panelp; - unsigned int ioaddr; - int bnknr; + struct stlpanel *panelp; + unsigned int ioaddr, bnknr; int handled = 0; outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl); while (inb(brdp->iostatus) & ECH_INTRPEND) { handled = 1; - for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) { + for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) { ioaddr = brdp->bnkstataddr[bnknr]; if (inb(ioaddr) & ECH_PNLINTRPEND) { panelp = brdp->bnk2panel[bnknr]; @@ -1998,16 +1693,15 @@ static int stl_echatintr(stlbrd_t *brdp) * Interrupt service routine for ECH-MCA board types. */ -static int stl_echmcaintr(stlbrd_t *brdp) +static int stl_echmcaintr(struct stlbrd *brdp) { - stlpanel_t *panelp; - unsigned int ioaddr; - int bnknr; + struct stlpanel *panelp; + unsigned int ioaddr, bnknr; int handled = 0; while (inb(brdp->iostatus) & ECH_INTRPEND) { handled = 1; - for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) { + for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) { ioaddr = brdp->bnkstataddr[bnknr]; if (inb(ioaddr) & ECH_PNLINTRPEND) { panelp = brdp->bnk2panel[bnknr]; @@ -2024,16 +1718,15 @@ static int stl_echmcaintr(stlbrd_t *brdp) * Interrupt service routine for ECH-PCI board types. */ -static int stl_echpciintr(stlbrd_t *brdp) +static int stl_echpciintr(struct stlbrd *brdp) { - stlpanel_t *panelp; - unsigned int ioaddr; - int bnknr, recheck; + struct stlpanel *panelp; + unsigned int ioaddr, bnknr, recheck; int handled = 0; while (1) { recheck = 0; - for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) { + for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) { outb(brdp->bnkpageaddr[bnknr], brdp->ioctrl); ioaddr = brdp->bnkstataddr[bnknr]; if (inb(ioaddr) & ECH_PNLINTRPEND) { @@ -2055,16 +1748,15 @@ static int stl_echpciintr(stlbrd_t *brdp) * Interrupt service routine for ECH-8/64-PCI board types. */ -static int stl_echpci64intr(stlbrd_t *brdp) +static int stl_echpci64intr(struct stlbrd *brdp) { - stlpanel_t *panelp; - unsigned int ioaddr; - int bnknr; + struct stlpanel *panelp; + unsigned int ioaddr, bnknr; int handled = 0; while (inb(brdp->ioctrl) & 0x1) { handled = 1; - for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) { + for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) { ioaddr = brdp->bnkstataddr[bnknr]; if (inb(ioaddr) & ECH_PNLINTRPEND) { panelp = brdp->bnk2panel[bnknr]; @@ -2081,39 +1773,34 @@ static int stl_echpci64intr(stlbrd_t *brdp) /* * Service an off-level request for some channel. */ -static void stl_offintr(void *private) +static void stl_offintr(struct work_struct *work) { - stlport_t *portp; + struct stlport *portp = container_of(work, struct stlport, tqueue); struct tty_struct *tty; unsigned int oldsigs; - portp = private; - -#ifdef DEBUG - printk("stl_offintr(portp=%x)\n", (int) portp); -#endif + pr_debug("stl_offintr(portp=%p)\n", portp); - if (portp == (stlport_t *) NULL) + if (portp == NULL) return; tty = portp->tty; - if (tty == (struct tty_struct *) NULL) + if (tty == NULL) return; lock_kernel(); - if (test_bit(ASYI_TXLOW, &portp->istate)) { + if (test_bit(ASYI_TXLOW, &portp->istate)) tty_wakeup(tty); - } + if (test_bit(ASYI_DCDCHANGE, &portp->istate)) { clear_bit(ASYI_DCDCHANGE, &portp->istate); oldsigs = portp->sigs; portp->sigs = stl_getsignals(portp); if ((portp->sigs & TIOCM_CD) && ((oldsigs & TIOCM_CD) == 0)) wake_up_interruptible(&portp->open_wait); - if ((oldsigs & TIOCM_CD) && ((portp->sigs & TIOCM_CD) == 0)) { + if ((oldsigs & TIOCM_CD) && ((portp->sigs & TIOCM_CD) == 0)) if (portp->flags & ASYNC_CHECK_CD) tty_hangup(tty); /* FIXME: module removal race here - AKPM */ - } } unlock_kernel(); } @@ -2124,14 +1811,13 @@ static void stl_offintr(void *private) * Initialize all the ports on a panel. */ -static int __init stl_initports(stlbrd_t *brdp, stlpanel_t *panelp) +static int __devinit stl_initports(struct stlbrd *brdp, struct stlpanel *panelp) { - stlport_t *portp; - int chipmask, i; + struct stlport *portp; + unsigned int i; + int chipmask; -#ifdef DEBUG - printk("stl_initports(brdp=%x,panelp=%x)\n", (int) brdp, (int) panelp); -#endif + pr_debug("stl_initports(brdp=%p,panelp=%p)\n", brdp, panelp); chipmask = stl_panelinit(brdp, panelp); @@ -2139,11 +1825,11 @@ static int __init stl_initports(stlbrd_t *brdp, stlpanel_t *panelp) * All UART's are initialized (if found!). Now go through and setup * each ports data structures. */ - for (i = 0; (i < panelp->nrports); i++) { - portp = kzalloc(sizeof(stlport_t), GFP_KERNEL); + for (i = 0; i < panelp->nrports; i++) { + portp = kzalloc(sizeof(struct stlport), GFP_KERNEL); if (!portp) { printk("STALLION: failed to allocate memory " - "(size=%Zd)\n", sizeof(stlport_t)); + "(size=%Zd)\n", sizeof(struct stlport)); break; } @@ -2156,7 +1842,7 @@ static int __init stl_initports(stlbrd_t *brdp, stlpanel_t *panelp) portp->baud_base = STL_BAUDBASE; portp->close_delay = STL_CLOSEDELAY; portp->closing_wait = 30 * HZ; - INIT_WORK(&portp->tqueue, stl_offintr, portp); + INIT_WORK(&portp->tqueue, stl_offintr); init_waitqueue_head(&portp->open_wait); init_waitqueue_head(&portp->close_wait); portp->stats.brd = portp->brdnr; @@ -2166,7 +1852,30 @@ static int __init stl_initports(stlbrd_t *brdp, stlpanel_t *panelp) stl_portinit(brdp, panelp, portp); } - return(0); + return 0; +} + +static void stl_cleanup_panels(struct stlbrd *brdp) +{ + struct stlpanel *panelp; + struct stlport *portp; + unsigned int j, k; + + for (j = 0; j < STL_MAXPANELS; j++) { + panelp = brdp->panels[j]; + if (panelp == NULL) + continue; + for (k = 0; k < STL_PORTSPERPANEL; k++) { + portp = panelp->ports[k]; + if (portp == NULL) + continue; + if (portp->tty != NULL) + stl_hangup(portp->tty); + kfree(portp->tx.buf); + kfree(portp); + } + kfree(panelp); + } } /*****************************************************************************/ @@ -2175,16 +1884,14 @@ static int __init stl_initports(stlbrd_t *brdp, stlpanel_t *panelp) * Try to find and initialize an EasyIO board. */ -static inline int stl_initeio(stlbrd_t *brdp) +static int __devinit stl_initeio(struct stlbrd *brdp) { - stlpanel_t *panelp; + struct stlpanel *panelp; unsigned int status; char *name; - int rc; + int retval; -#ifdef DEBUG - printk("stl_initeio(brdp=%x)\n", (int) brdp); -#endif + pr_debug("stl_initeio(brdp=%p)\n", brdp); brdp->ioctrl = brdp->ioaddr1 + 1; brdp->iostatus = brdp->ioaddr1 + 2; @@ -2209,18 +1916,20 @@ static inline int stl_initeio(stlbrd_t *brdp) (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) { printk("STALLION: invalid irq=%d for brd=%d\n", brdp->irq, brdp->brdnr); - return(-EINVAL); + retval = -EINVAL; + goto err; } outb((stl_vecmap[brdp->irq] | EIO_0WS | ((brdp->irqtype) ? EIO_INTLEVEL : EIO_INTEDGE)), brdp->ioctrl); } + retval = -EBUSY; if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) { printk(KERN_WARNING "STALLION: Warning, board %d I/O address " "%x conflicts with another device\n", brdp->brdnr, brdp->ioaddr1); - return(-EBUSY); + goto err; } if (brdp->iosize2 > 0) @@ -2231,8 +1940,7 @@ static inline int stl_initeio(stlbrd_t *brdp) printk(KERN_WARNING "STALLION: Warning, also " "releasing board %d I/O address %x \n", brdp->brdnr, brdp->ioaddr1); - release_region(brdp->ioaddr1, brdp->iosize1); - return(-EBUSY); + goto err_rel1; } /* @@ -2241,6 +1949,7 @@ static inline int stl_initeio(stlbrd_t *brdp) brdp->clk = CD1400_CLK; brdp->isr = stl_eiointr; + retval = -ENODEV; switch (status & EIO_IDBITMASK) { case EIO_8PORTM: brdp->clk = CD1400_CLK8M; @@ -2264,11 +1973,11 @@ static inline int stl_initeio(stlbrd_t *brdp) brdp->nrports = 16; break; default: - return(-ENODEV); + goto err_rel2; } break; default: - return(-ENODEV); + goto err_rel2; } /* @@ -2276,11 +1985,12 @@ static inline int stl_initeio(stlbrd_t *brdp) * can complete the setup. */ - panelp = kzalloc(sizeof(stlpanel_t), GFP_KERNEL); + panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL); if (!panelp) { printk(KERN_WARNING "STALLION: failed to allocate memory " - "(size=%Zd)\n", sizeof(stlpanel_t)); - return -ENOMEM; + "(size=%Zd)\n", sizeof(struct stlpanel)); + retval = -ENOMEM; + goto err_rel2; } panelp->magic = STL_PANELMAGIC; @@ -2290,10 +2000,10 @@ static inline int stl_initeio(stlbrd_t *brdp) panelp->iobase = brdp->ioaddr1; panelp->hwid = status; if ((status & EIO_IDBITMASK) == EIO_MK3) { - panelp->uartp = (void *) &stl_sc26198uart; + panelp->uartp = &stl_sc26198uart; panelp->isr = stl_sc26198intr; } else { - panelp->uartp = (void *) &stl_cd1400uart; + panelp->uartp = &stl_cd1400uart; panelp->isr = stl_cd1400eiointr; } @@ -2304,11 +2014,20 @@ static inline int stl_initeio(stlbrd_t *brdp) if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) { printk("STALLION: failed to register interrupt " "routine for %s irq=%d\n", name, brdp->irq); - rc = -ENODEV; - } else { - rc = 0; + retval = -ENODEV; + goto err_fr; } - return rc; + + return 0; +err_fr: + stl_cleanup_panels(brdp); +err_rel2: + if (brdp->iosize2 > 0) + release_region(brdp->ioaddr2, brdp->iosize2); +err_rel1: + release_region(brdp->ioaddr1, brdp->iosize1); +err: + return retval; } /*****************************************************************************/ @@ -2318,16 +2037,14 @@ static inline int stl_initeio(stlbrd_t *brdp) * dealing with all types of ECH board. */ -static inline int stl_initech(stlbrd_t *brdp) +static int __devinit stl_initech(struct stlbrd *brdp) { - stlpanel_t *panelp; - unsigned int status, nxtid, ioaddr, conflict; - int panelnr, banknr, i; + struct stlpanel *panelp; + unsigned int status, nxtid, ioaddr, conflict, panelnr, banknr, i; + int retval; char *name; -#ifdef DEBUG - printk("stl_initech(brdp=%x)\n", (int) brdp); -#endif + pr_debug("stl_initech(brdp=%p)\n", brdp); status = 0; conflict = 0; @@ -2344,20 +2061,23 @@ static inline int stl_initech(stlbrd_t *brdp) brdp->ioctrl = brdp->ioaddr1 + 1; brdp->iostatus = brdp->ioaddr1 + 1; status = inb(brdp->iostatus); - if ((status & ECH_IDBITMASK) != ECH_ID) - return(-ENODEV); + if ((status & ECH_IDBITMASK) != ECH_ID) { + retval = -ENODEV; + goto err; + } if ((brdp->irq < 0) || (brdp->irq > 15) || (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) { printk("STALLION: invalid irq=%d for brd=%d\n", brdp->irq, brdp->brdnr); - return(-EINVAL); + retval = -EINVAL; + goto err; } status = ((brdp->ioaddr2 & ECH_ADDR2MASK) >> 1); status |= (stl_vecmap[brdp->irq] << 1); outb((status | ECH_BRDRESET), brdp->ioaddr1); brdp->ioctrlval = ECH_INTENABLE | ((brdp->irqtype) ? ECH_INTLEVEL : ECH_INTEDGE); - for (i = 0; (i < 10); i++) + for (i = 0; i < 10; i++) outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl); brdp->iosize1 = 2; brdp->iosize2 = 32; @@ -2370,13 +2090,16 @@ static inline int stl_initech(stlbrd_t *brdp) brdp->ioctrl = brdp->ioaddr1 + 0x20; brdp->iostatus = brdp->ioctrl; status = inb(brdp->iostatus); - if ((status & ECH_IDBITMASK) != ECH_ID) - return(-ENODEV); + if ((status & ECH_IDBITMASK) != ECH_ID) { + retval = -ENODEV; + goto err; + } if ((brdp->irq < 0) || (brdp->irq > 15) || (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) { printk("STALLION: invalid irq=%d for brd=%d\n", brdp->irq, brdp->brdnr); - return(-EINVAL); + retval = -EINVAL; + goto err; } outb(ECHMC_BRDRESET, brdp->ioctrl); outb(ECHMC_INTENABLE, brdp->ioctrl); @@ -2403,19 +2126,20 @@ static inline int stl_initech(stlbrd_t *brdp) default: printk("STALLION: unknown board type=%d\n", brdp->brdtype); - return(-EINVAL); - break; + retval = -EINVAL; + goto err; } /* * Check boards for possible IO address conflicts and return fail status * if an IO conflict found. */ + retval = -EBUSY; if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) { printk(KERN_WARNING "STALLION: Warning, board %d I/O address " "%x conflicts with another device\n", brdp->brdnr, brdp->ioaddr1); - return(-EBUSY); + goto err; } if (brdp->iosize2 > 0) @@ -2426,8 +2150,7 @@ static inline int stl_initech(stlbrd_t *brdp) printk(KERN_WARNING "STALLION: Warning, also " "releasing board %d I/O address %x \n", brdp->brdnr, brdp->ioaddr1); - release_region(brdp->ioaddr1, brdp->iosize1); - return(-EBUSY); + goto err_rel1; } /* @@ -2442,19 +2165,19 @@ static inline int stl_initech(stlbrd_t *brdp) panelnr = 0; nxtid = 0; - for (i = 0; (i < STL_MAXPANELS); i++) { + for (i = 0; i < STL_MAXPANELS; i++) { if (brdp->brdtype == BRD_ECHPCI) { outb(nxtid, brdp->ioctrl); ioaddr = brdp->ioaddr2; } status = inb(ioaddr + ECH_PNLSTATUS); if ((status & ECH_PNLIDMASK) != nxtid) - break; - panelp = kzalloc(sizeof(stlpanel_t), GFP_KERNEL); + goto err_fr; + panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL); if (!panelp) { printk("STALLION: failed to allocate memory " - "(size=%Zd)\n", sizeof(stlpanel_t)); - break; + "(size=%Zd)\n", sizeof(struct stlpanel)); + goto err_fr; } panelp->magic = STL_PANELMAGIC; panelp->brdnr = brdp->brdnr; @@ -2467,7 +2190,7 @@ static inline int stl_initech(stlbrd_t *brdp) brdp->bnkstataddr[banknr++] = ioaddr + ECH_PNLSTATUS; if (status & ECH_PNLXPID) { - panelp->uartp = (void *) &stl_sc26198uart; + panelp->uartp = &stl_sc26198uart; panelp->isr = stl_sc26198intr; if (status & ECH_PNL16PORT) { panelp->nrports = 16; @@ -2475,11 +2198,10 @@ static inline int stl_initech(stlbrd_t *brdp) brdp->bnkpageaddr[banknr] = nxtid; brdp->bnkstataddr[banknr++] = ioaddr + 4 + ECH_PNLSTATUS; - } else { + } else panelp->nrports = 8; - } } else { - panelp->uartp = (void *) &stl_cd1400uart; + panelp->uartp = &stl_cd1400uart; panelp->isr = stl_cd1400echintr; if (status & ECH_PNL16PORT) { panelp->nrports = 16; @@ -2502,7 +2224,7 @@ static inline int stl_initech(stlbrd_t *brdp) brdp->panels[panelnr++] = panelp; if ((brdp->brdtype != BRD_ECHPCI) && (ioaddr >= (brdp->ioaddr2 + brdp->iosize2))) - break; + goto err_fr; } brdp->nrpanels = panelnr; @@ -2514,12 +2236,19 @@ static inline int stl_initech(stlbrd_t *brdp) if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) { printk("STALLION: failed to register interrupt " "routine for %s irq=%d\n", name, brdp->irq); - i = -ENODEV; - } else { - i = 0; + retval = -ENODEV; + goto err_fr; } - return(i); + return 0; +err_fr: + stl_cleanup_panels(brdp); + if (brdp->iosize2 > 0) + release_region(brdp->ioaddr2, brdp->iosize2); +err_rel1: + release_region(brdp->ioaddr1, brdp->iosize1); +err: + return retval; } /*****************************************************************************/ @@ -2531,48 +2260,61 @@ static inline int stl_initech(stlbrd_t *brdp) * since the initial search and setup is very different. */ -static int __init stl_brdinit(stlbrd_t *brdp) +static int __devinit stl_brdinit(struct stlbrd *brdp) { - int i; + int i, retval; -#ifdef DEBUG - printk("stl_brdinit(brdp=%x)\n", (int) brdp); -#endif + pr_debug("stl_brdinit(brdp=%p)\n", brdp); switch (brdp->brdtype) { case BRD_EASYIO: case BRD_EASYIOPCI: - stl_initeio(brdp); + retval = stl_initeio(brdp); + if (retval) + goto err; break; case BRD_ECH: case BRD_ECHMC: case BRD_ECHPCI: case BRD_ECH64PCI: - stl_initech(brdp); + retval = stl_initech(brdp); + if (retval) + goto err; break; default: printk("STALLION: board=%d is unknown board type=%d\n", brdp->brdnr, brdp->brdtype); - return(ENODEV); + retval = -ENODEV; + goto err; } - stl_brds[brdp->brdnr] = brdp; if ((brdp->state & BRD_FOUND) == 0) { printk("STALLION: %s board not found, board=%d io=%x irq=%d\n", stl_brdnames[brdp->brdtype], brdp->brdnr, brdp->ioaddr1, brdp->irq); - return(ENODEV); + goto err_free; } - for (i = 0; (i < STL_MAXPANELS); i++) - if (brdp->panels[i] != (stlpanel_t *) NULL) + for (i = 0; i < STL_MAXPANELS; i++) + if (brdp->panels[i] != NULL) stl_initports(brdp, brdp->panels[i]); printk("STALLION: %s found, board=%d io=%x irq=%d " "nrpanels=%d nrports=%d\n", stl_brdnames[brdp->brdtype], brdp->brdnr, brdp->ioaddr1, brdp->irq, brdp->nrpanels, brdp->nrports); - return(0); + + return 0; +err_free: + free_irq(brdp->irq, brdp); + + stl_cleanup_panels(brdp); + + release_region(brdp->ioaddr1, brdp->iosize1); + if (brdp->iosize2 > 0) + release_region(brdp->ioaddr2, brdp->iosize2); +err: + return retval; } /*****************************************************************************/ @@ -2581,59 +2323,62 @@ static int __init stl_brdinit(stlbrd_t *brdp) * Find the next available board number that is free. */ -static inline int stl_getbrdnr(void) +static int __devinit stl_getbrdnr(void) { - int i; + unsigned int i; - for (i = 0; (i < STL_MAXBRDS); i++) { - if (stl_brds[i] == (stlbrd_t *) NULL) { + for (i = 0; i < STL_MAXBRDS; i++) + if (stl_brds[i] == NULL) { if (i >= stl_nrbrds) stl_nrbrds = i + 1; - return(i); + return i; } - } - return(-1); + + return -1; } /*****************************************************************************/ - -#ifdef CONFIG_PCI - /* * We have a Stallion board. Allocate a board structure and * initialize it. Read its IO and IRQ resources from PCI * configuration space. */ -static inline int stl_initpcibrd(int brdtype, struct pci_dev *devp) +static int __devinit stl_pciprobe(struct pci_dev *pdev, + const struct pci_device_id *ent) { - stlbrd_t *brdp; - -#ifdef DEBUG - printk("stl_initpcibrd(brdtype=%d,busnr=%x,devnr=%x)\n", brdtype, - devp->bus->number, devp->devfn); -#endif - - if (pci_enable_device(devp)) - return(-EIO); - if ((brdp = stl_allocbrd()) == (stlbrd_t *) NULL) - return(-ENOMEM); - if ((brdp->brdnr = stl_getbrdnr()) < 0) { - printk("STALLION: too many boards found, " + struct stlbrd *brdp; + unsigned int i, brdtype = ent->driver_data; + int brdnr, retval = -ENODEV; + + if ((pdev->class >> 8) == PCI_CLASS_STORAGE_IDE) + goto err; + + dev_info(&pdev->dev, "please, report this to LKML: %x/%x/%x\n", + pdev->vendor, pdev->device, pdev->class); + + retval = pci_enable_device(pdev); + if (retval) + goto err; + brdp = stl_allocbrd(); + if (brdp == NULL) { + retval = -ENOMEM; + goto err; + } + mutex_lock(&stl_brdslock); + brdnr = stl_getbrdnr(); + if (brdnr < 0) { + dev_err(&pdev->dev, "too many boards found, " "maximum supported %d\n", STL_MAXBRDS); - return(0); + mutex_unlock(&stl_brdslock); + goto err_fr; } - brdp->brdtype = brdtype; + brdp->brdnr = (unsigned int)brdnr; + stl_brds[brdp->brdnr] = brdp; + mutex_unlock(&stl_brdslock); -/* - * Different Stallion boards use the BAR registers in different ways, - * so set up io addresses based on board type. - */ -#ifdef DEBUG - printk("%s(%d): BAR[]=%x,%x,%x,%x IRQ=%x\n", __FILE__, __LINE__, - pci_resource_start(devp, 0), pci_resource_start(devp, 1), - pci_resource_start(devp, 2), pci_resource_start(devp, 3), devp->irq); -#endif + brdp->brdtype = brdtype; + brdp->state |= STL_PROBED; /* * We have all resources from the board, so let's setup the actual @@ -2641,120 +2386,70 @@ static inline int stl_initpcibrd(int brdtype, struct pci_dev *devp) */ switch (brdtype) { case BRD_ECHPCI: - brdp->ioaddr2 = pci_resource_start(devp, 0); - brdp->ioaddr1 = pci_resource_start(devp, 1); + brdp->ioaddr2 = pci_resource_start(pdev, 0); + brdp->ioaddr1 = pci_resource_start(pdev, 1); break; case BRD_ECH64PCI: - brdp->ioaddr2 = pci_resource_start(devp, 2); - brdp->ioaddr1 = pci_resource_start(devp, 1); + brdp->ioaddr2 = pci_resource_start(pdev, 2); + brdp->ioaddr1 = pci_resource_start(pdev, 1); break; case BRD_EASYIOPCI: - brdp->ioaddr1 = pci_resource_start(devp, 2); - brdp->ioaddr2 = pci_resource_start(devp, 1); - break; - default: - printk("STALLION: unknown PCI board type=%d\n", brdtype); + brdp->ioaddr1 = pci_resource_start(pdev, 2); + brdp->ioaddr2 = pci_resource_start(pdev, 1); break; - } - - brdp->irq = devp->irq; - stl_brdinit(brdp); - - return(0); -} - -/*****************************************************************************/ - -/* - * Find all Stallion PCI boards that might be installed. Initialize each - * one as it is found. - */ - - -static inline int stl_findpcibrds(void) -{ - struct pci_dev *dev = NULL; - int i, rc; - -#ifdef DEBUG - printk("stl_findpcibrds()\n"); -#endif - - for (i = 0; (i < stl_nrpcibrds); i++) - while ((dev = pci_find_device(stl_pcibrds[i].vendid, - stl_pcibrds[i].devid, dev))) { - -/* - * Found a device on the PCI bus that has our vendor and - * device ID. Need to check now that it is really us. - */ - if ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE) - continue; - - rc = stl_initpcibrd(stl_pcibrds[i].brdtype, dev); - if (rc) - return(rc); - } + default: + dev_err(&pdev->dev, "unknown PCI board type=%u\n", brdtype); + break; + } - return(0); -} + brdp->irq = pdev->irq; + retval = stl_brdinit(brdp); + if (retval) + goto err_null; -#endif + pci_set_drvdata(pdev, brdp); -/*****************************************************************************/ + for (i = 0; i < brdp->nrports; i++) + tty_register_device(stl_serial, + brdp->brdnr * STL_MAXPORTS + i, &pdev->dev); -/* - * Scan through all the boards in the configuration and see what we - * can find. Handle EIO and the ECH boards a little differently here - * since the initial search and setup is too different. - */ + return 0; +err_null: + stl_brds[brdp->brdnr] = NULL; +err_fr: + kfree(brdp); +err: + return retval; +} -static inline int stl_initbrds(void) +static void __devexit stl_pciremove(struct pci_dev *pdev) { - stlbrd_t *brdp; - stlconf_t *confp; - int i; + struct stlbrd *brdp = pci_get_drvdata(pdev); + unsigned int i; -#ifdef DEBUG - printk("stl_initbrds()\n"); -#endif + free_irq(brdp->irq, brdp); - if (stl_nrbrds > STL_MAXBRDS) { - printk("STALLION: too many boards in configuration table, " - "truncating to %d\n", STL_MAXBRDS); - stl_nrbrds = STL_MAXBRDS; - } + stl_cleanup_panels(brdp); -/* - * Firstly scan the list of static boards configured. Allocate - * resources and initialize the boards as found. - */ - for (i = 0; (i < stl_nrbrds); i++) { - confp = &stl_brdconf[i]; - stl_parsebrd(confp, stl_brdsp[i]); - if ((brdp = stl_allocbrd()) == (stlbrd_t *) NULL) - return(-ENOMEM); - brdp->brdnr = i; - brdp->brdtype = confp->brdtype; - brdp->ioaddr1 = confp->ioaddr1; - brdp->ioaddr2 = confp->ioaddr2; - brdp->irq = confp->irq; - brdp->irqtype = confp->irqtype; - stl_brdinit(brdp); - } + release_region(brdp->ioaddr1, brdp->iosize1); + if (brdp->iosize2 > 0) + release_region(brdp->ioaddr2, brdp->iosize2); -/* - * Find any dynamically supported boards. That is via module load - * line options or auto-detected on the PCI bus. - */ - stl_argbrds(); -#ifdef CONFIG_PCI - stl_findpcibrds(); -#endif + for (i = 0; i < brdp->nrports; i++) + tty_unregister_device(stl_serial, + brdp->brdnr * STL_MAXPORTS + i); - return(0); + stl_brds[brdp->brdnr] = NULL; + kfree(brdp); } +static struct pci_driver stl_pcidriver = { + .name = "stallion", + .id_table = stl_pcibrds, + .probe = stl_pciprobe, + .remove = __devexit_p(stl_pciremove) +}; + /*****************************************************************************/ /* @@ -2763,17 +2458,18 @@ static inline int stl_initbrds(void) static int stl_getbrdstats(combrd_t __user *bp) { - stlbrd_t *brdp; - stlpanel_t *panelp; - int i; + combrd_t stl_brdstats; + struct stlbrd *brdp; + struct stlpanel *panelp; + unsigned int i; if (copy_from_user(&stl_brdstats, bp, sizeof(combrd_t))) return -EFAULT; if (stl_brdstats.brd >= STL_MAXBRDS) - return(-ENODEV); + return -ENODEV; brdp = stl_brds[stl_brdstats.brd]; - if (brdp == (stlbrd_t *) NULL) - return(-ENODEV); + if (brdp == NULL) + return -ENODEV; memset(&stl_brdstats, 0, sizeof(combrd_t)); stl_brdstats.brd = brdp->brdnr; @@ -2785,7 +2481,7 @@ static int stl_getbrdstats(combrd_t __user *bp) stl_brdstats.irq = brdp->irq; stl_brdstats.nrpanels = brdp->nrpanels; stl_brdstats.nrports = brdp->nrports; - for (i = 0; (i < brdp->nrpanels); i++) { + for (i = 0; i < brdp->nrpanels; i++) { panelp = brdp->panels[i]; stl_brdstats.panels[i].panel = i; stl_brdstats.panels[i].hwid = panelp->hwid; @@ -2801,24 +2497,24 @@ static int stl_getbrdstats(combrd_t __user *bp) * Resolve the referenced port number into a port struct pointer. */ -static stlport_t *stl_getport(int brdnr, int panelnr, int portnr) +static struct stlport *stl_getport(int brdnr, int panelnr, int portnr) { - stlbrd_t *brdp; - stlpanel_t *panelp; + struct stlbrd *brdp; + struct stlpanel *panelp; - if ((brdnr < 0) || (brdnr >= STL_MAXBRDS)) - return((stlport_t *) NULL); + if (brdnr < 0 || brdnr >= STL_MAXBRDS) + return NULL; brdp = stl_brds[brdnr]; - if (brdp == (stlbrd_t *) NULL) - return((stlport_t *) NULL); - if ((panelnr < 0) || (panelnr >= brdp->nrpanels)) - return((stlport_t *) NULL); + if (brdp == NULL) + return NULL; + if (panelnr < 0 || (unsigned int)panelnr >= brdp->nrpanels) + return NULL; panelp = brdp->panels[panelnr]; - if (panelp == (stlpanel_t *) NULL) - return((stlport_t *) NULL); - if ((portnr < 0) || (portnr >= panelp->nrports)) - return((stlport_t *) NULL); - return(panelp->ports[portnr]); + if (panelp == NULL) + return NULL; + if (portnr < 0 || (unsigned int)portnr >= panelp->nrports) + return NULL; + return panelp->ports[portnr]; } /*****************************************************************************/ @@ -2829,8 +2525,9 @@ static stlport_t *stl_getport(int brdnr, int panelnr, int portnr) * what port to get stats for (used through board control device). */ -static int stl_getportstats(stlport_t *portp, comstats_t __user *cp) +static int stl_getportstats(struct stlport *portp, comstats_t __user *cp) { + comstats_t stl_comstats; unsigned char *head, *tail; unsigned long flags; @@ -2839,8 +2536,8 @@ static int stl_getportstats(stlport_t *portp, comstats_t __user *cp) return -EFAULT; portp = stl_getport(stl_comstats.brd, stl_comstats.panel, stl_comstats.port); - if (portp == (stlport_t *) NULL) - return(-ENODEV); + if (portp == NULL) + return -ENODEV; } portp->stats.state = portp->istate; @@ -2855,25 +2552,24 @@ static int stl_getportstats(stlport_t *portp, comstats_t __user *cp) portp->stats.rxbuffered = 0; spin_lock_irqsave(&stallion_lock, flags); - if (portp->tty != (struct tty_struct *) NULL) { + if (portp->tty != NULL) if (portp->tty->driver_data == portp) { portp->stats.ttystate = portp->tty->flags; /* No longer available as a statistic */ portp->stats.rxbuffered = 1; /*portp->tty->flip.count; */ - if (portp->tty->termios != (struct termios *) NULL) { + if (portp->tty->termios != NULL) { portp->stats.cflags = portp->tty->termios->c_cflag; portp->stats.iflags = portp->tty->termios->c_iflag; portp->stats.oflags = portp->tty->termios->c_oflag; portp->stats.lflags = portp->tty->termios->c_lflag; } } - } spin_unlock_irqrestore(&stallion_lock, flags); head = portp->tx.head; tail = portp->tx.tail; - portp->stats.txbuffered = ((head >= tail) ? (head - tail) : - (STL_TXBUFSIZE - (tail - head))); + portp->stats.txbuffered = (head >= tail) ? (head - tail) : + (STL_TXBUFSIZE - (tail - head)); portp->stats.signals = (unsigned long) stl_getsignals(portp); @@ -2887,15 +2583,17 @@ static int stl_getportstats(stlport_t *portp, comstats_t __user *cp) * Clear the port stats structure. We also return it zeroed out... */ -static int stl_clrportstats(stlport_t *portp, comstats_t __user *cp) +static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp) { + comstats_t stl_comstats; + if (!portp) { if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t))) return -EFAULT; portp = stl_getport(stl_comstats.brd, stl_comstats.panel, stl_comstats.port); - if (portp == (stlport_t *) NULL) - return(-ENODEV); + if (portp == NULL) + return -ENODEV; } memset(&portp->stats, 0, sizeof(comstats_t)); @@ -2912,17 +2610,18 @@ static int stl_clrportstats(stlport_t *portp, comstats_t __user *cp) * Return the entire driver ports structure to a user app. */ -static int stl_getportstruct(stlport_t __user *arg) +static int stl_getportstruct(struct stlport __user *arg) { - stlport_t *portp; + struct stlport stl_dummyport; + struct stlport *portp; - if (copy_from_user(&stl_dummyport, arg, sizeof(stlport_t))) + if (copy_from_user(&stl_dummyport, arg, sizeof(struct stlport))) return -EFAULT; portp = stl_getport(stl_dummyport.brdnr, stl_dummyport.panelnr, stl_dummyport.portnr); if (!portp) return -ENODEV; - return copy_to_user(arg, portp, sizeof(stlport_t)) ? -EFAULT : 0; + return copy_to_user(arg, portp, sizeof(struct stlport)) ? -EFAULT : 0; } /*****************************************************************************/ @@ -2931,18 +2630,19 @@ static int stl_getportstruct(stlport_t __user *arg) * Return the entire driver board structure to a user app. */ -static int stl_getbrdstruct(stlbrd_t __user *arg) +static int stl_getbrdstruct(struct stlbrd __user *arg) { - stlbrd_t *brdp; + struct stlbrd stl_dummybrd; + struct stlbrd *brdp; - if (copy_from_user(&stl_dummybrd, arg, sizeof(stlbrd_t))) + if (copy_from_user(&stl_dummybrd, arg, sizeof(struct stlbrd))) return -EFAULT; - if ((stl_dummybrd.brdnr < 0) || (stl_dummybrd.brdnr >= STL_MAXBRDS)) + if (stl_dummybrd.brdnr >= STL_MAXBRDS) return -ENODEV; brdp = stl_brds[stl_dummybrd.brdnr]; if (!brdp) - return(-ENODEV); - return copy_to_user(arg, brdp, sizeof(stlbrd_t)) ? -EFAULT : 0; + return -ENODEV; + return copy_to_user(arg, brdp, sizeof(struct stlbrd)) ? -EFAULT : 0; } /*****************************************************************************/ @@ -2958,14 +2658,11 @@ static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, uns int brdnr, rc; void __user *argp = (void __user *)arg; -#ifdef DEBUG - printk("stl_memioctl(ip=%x,fp=%x,cmd=%x,arg=%x)\n", (int) ip, - (int) fp, cmd, (int) arg); -#endif + pr_debug("stl_memioctl(ip=%p,fp=%p,cmd=%x,arg=%lx)\n", ip, fp, cmd,arg); brdnr = iminor(ip); if (brdnr >= STL_MAXBRDS) - return(-ENODEV); + return -ENODEV; rc = 0; switch (cmd) { @@ -2989,7 +2686,7 @@ static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, uns break; } - return(rc); + return rc; } static const struct tty_operations stl_ops = { @@ -3016,55 +2713,6 @@ static const struct tty_operations stl_ops = { .tiocmset = stl_tiocmset, }; -/*****************************************************************************/ - -static int __init stl_init(void) -{ - int i; - printk(KERN_INFO "%s: version %s\n", stl_drvtitle, stl_drvversion); - - spin_lock_init(&stallion_lock); - spin_lock_init(&brd_lock); - - stl_initbrds(); - - stl_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS); - if (!stl_serial) - return -1; - -/* - * Set up a character driver for per board stuff. This is mainly used - * to do stats ioctls on the ports. - */ - if (register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stl_fsiomem)) - printk("STALLION: failed to register serial board device\n"); - - stallion_class = class_create(THIS_MODULE, "staliomem"); - for (i = 0; i < 4; i++) - class_device_create(stallion_class, NULL, - MKDEV(STL_SIOMEMMAJOR, i), NULL, - "staliomem%d", i); - - stl_serial->owner = THIS_MODULE; - stl_serial->driver_name = stl_drvname; - stl_serial->name = "ttyE"; - stl_serial->major = STL_SERIALMAJOR; - stl_serial->minor_start = 0; - stl_serial->type = TTY_DRIVER_TYPE_SERIAL; - stl_serial->subtype = SERIAL_TYPE_NORMAL; - stl_serial->init_termios = stl_deftermios; - stl_serial->flags = TTY_DRIVER_REAL_RAW; - tty_set_operations(stl_serial, &stl_ops); - - if (tty_register_driver(stl_serial)) { - put_tty_driver(stl_serial); - printk("STALLION: failed to register serial driver\n"); - return -1; - } - - return 0; -} - /*****************************************************************************/ /* CD1400 HARDWARE FUNCTIONS */ /*****************************************************************************/ @@ -3075,21 +2723,21 @@ static int __init stl_init(void) * (Maybe should make this inline...) */ -static int stl_cd1400getreg(stlport_t *portp, int regnr) +static int stl_cd1400getreg(struct stlport *portp, int regnr) { outb((regnr + portp->uartaddr), portp->ioaddr); return inb(portp->ioaddr + EREG_DATA); } -static void stl_cd1400setreg(stlport_t *portp, int regnr, int value) +static void stl_cd1400setreg(struct stlport *portp, int regnr, int value) { - outb((regnr + portp->uartaddr), portp->ioaddr); + outb(regnr + portp->uartaddr, portp->ioaddr); outb(value, portp->ioaddr + EREG_DATA); } -static int stl_cd1400updatereg(stlport_t *portp, int regnr, int value) +static int stl_cd1400updatereg(struct stlport *portp, int regnr, int value) { - outb((regnr + portp->uartaddr), portp->ioaddr); + outb(regnr + portp->uartaddr, portp->ioaddr); if (inb(portp->ioaddr + EREG_DATA) != value) { outb(value, portp->ioaddr + EREG_DATA); return 1; @@ -3105,16 +2753,14 @@ static int stl_cd1400updatereg(stlport_t *portp, int regnr, int value) * identical when dealing with ports. */ -static int stl_cd1400panelinit(stlbrd_t *brdp, stlpanel_t *panelp) +static int stl_cd1400panelinit(struct stlbrd *brdp, struct stlpanel *panelp) { unsigned int gfrcr; int chipmask, i, j; int nrchips, uartaddr, ioaddr; unsigned long flags; -#ifdef DEBUG - printk("stl_panelinit(brdp=%x,panelp=%x)\n", (int) brdp, (int) panelp); -#endif + pr_debug("stl_panelinit(brdp=%p,panelp=%p)\n", brdp, panelp); spin_lock_irqsave(&brd_lock, flags); BRDENABLE(panelp->brdnr, panelp->pagenr); @@ -3124,13 +2770,12 @@ static int stl_cd1400panelinit(stlbrd_t *brdp, stlpanel_t *panelp) */ chipmask = 0; nrchips = panelp->nrports / CD1400_PORTS; - for (i = 0; (i < nrchips); i++) { + for (i = 0; i < nrchips; i++) { if (brdp->brdtype == BRD_ECHPCI) { outb((panelp->pagenr + (i >> 1)), brdp->ioctrl); ioaddr = panelp->iobase; - } else { + } else ioaddr = panelp->iobase + (EREG_BANKSIZE * (i >> 1)); - } uartaddr = (i & 0x01) ? 0x080 : 0; outb((GFRCR + uartaddr), ioaddr); outb(0, (ioaddr + EREG_DATA)); @@ -3138,10 +2783,10 @@ static int stl_cd1400panelinit(stlbrd_t *brdp, stlpanel_t *panelp) outb(CCR_RESETFULL, (ioaddr + EREG_DATA)); outb(CCR_RESETFULL, (ioaddr + EREG_DATA)); outb((GFRCR + uartaddr), ioaddr); - for (j = 0; (j < CCR_MAXWAIT); j++) { + for (j = 0; j < CCR_MAXWAIT; j++) if ((gfrcr = inb(ioaddr + EREG_DATA)) != 0) break; - } + if ((j >= CCR_MAXWAIT) || (gfrcr < 0x40) || (gfrcr > 0x60)) { printk("STALLION: cd1400 not responding, " "brd=%d panel=%d chip=%d\n", @@ -3164,16 +2809,14 @@ static int stl_cd1400panelinit(stlbrd_t *brdp, stlpanel_t *panelp) * Initialize hardware specific port registers. */ -static void stl_cd1400portinit(stlbrd_t *brdp, stlpanel_t *panelp, stlport_t *portp) +static void stl_cd1400portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp) { unsigned long flags; -#ifdef DEBUG - printk("stl_cd1400portinit(brdp=%x,panelp=%x,portp=%x)\n", - (int) brdp, (int) panelp, (int) portp); -#endif + pr_debug("stl_cd1400portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp, + panelp, portp); - if ((brdp == (stlbrd_t *) NULL) || (panelp == (stlpanel_t *) NULL) || - (portp == (stlport_t *) NULL)) + if ((brdp == NULL) || (panelp == NULL) || + (portp == NULL)) return; spin_lock_irqsave(&brd_lock, flags); @@ -3197,15 +2840,13 @@ static void stl_cd1400portinit(stlbrd_t *brdp, stlpanel_t *panelp, stlport_t *po * since it won't usually take too long to be ready. */ -static void stl_cd1400ccrwait(stlport_t *portp) +static void stl_cd1400ccrwait(struct stlport *portp) { int i; - for (i = 0; (i < CCR_MAXWAIT); i++) { - if (stl_cd1400getreg(portp, CCR) == 0) { + for (i = 0; i < CCR_MAXWAIT; i++) + if (stl_cd1400getreg(portp, CCR) == 0) return; - } - } printk("STALLION: cd1400 not responding, port=%d panel=%d brd=%d\n", portp->portnr, portp->panelnr, portp->brdnr); @@ -3218,9 +2859,9 @@ static void stl_cd1400ccrwait(stlport_t *portp) * settings. */ -static void stl_cd1400setport(stlport_t *portp, struct termios *tiosp) +static void stl_cd1400setport(struct stlport *portp, struct ktermios *tiosp) { - stlbrd_t *brdp; + struct stlbrd *brdp; unsigned long flags; unsigned int clkdiv, baudrate; unsigned char cor1, cor2, cor3; @@ -3244,7 +2885,7 @@ static void stl_cd1400setport(stlport_t *portp, struct termios *tiosp) sreroff = 0; brdp = stl_brds[portp->brdnr]; - if (brdp == (stlbrd_t *) NULL) + if (brdp == NULL) return; /* @@ -3341,8 +2982,8 @@ static void stl_cd1400setport(stlport_t *portp, struct termios *tiosp) baudrate = STL_CD1400MAXBAUD; if (baudrate > 0) { - for (clk = 0; (clk < CD1400_NUMCLKS); clk++) { - clkdiv = ((portp->clk / stl_cd1400clkdivs[clk]) / baudrate); + for (clk = 0; clk < CD1400_NUMCLKS; clk++) { + clkdiv = (portp->clk / stl_cd1400clkdivs[clk]) / baudrate; if (clkdiv < 0x100) break; } @@ -3357,9 +2998,8 @@ static void stl_cd1400setport(stlport_t *portp, struct termios *tiosp) mcor2 |= MCOR2_DCD; sreron |= SRER_MODEM; portp->flags |= ASYNC_CHECK_CD; - } else { + } else portp->flags &= ~ASYNC_CHECK_CD; - } /* * Setup cd1400 enhanced modes if we can. In particular we want to @@ -3384,18 +3024,16 @@ static void stl_cd1400setport(stlport_t *portp, struct termios *tiosp) * them all up. */ -#ifdef DEBUG - printk("SETPORT: portnr=%d panelnr=%d brdnr=%d\n", + pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n", portp->portnr, portp->panelnr, portp->brdnr); - printk(" cor1=%x cor2=%x cor3=%x cor4=%x cor5=%x\n", + pr_debug(" cor1=%x cor2=%x cor3=%x cor4=%x cor5=%x\n", cor1, cor2, cor3, cor4, cor5); - printk(" mcor1=%x mcor2=%x rtpr=%x sreron=%x sreroff=%x\n", + pr_debug(" mcor1=%x mcor2=%x rtpr=%x sreron=%x sreroff=%x\n", mcor1, mcor2, rtpr, sreron, sreroff); - printk(" tcor=%x tbpr=%x rcor=%x rbpr=%x\n", clk, div, clk, div); - printk(" schr1=%x schr2=%x schr3=%x schr4=%x\n", + pr_debug(" tcor=%x tbpr=%x rcor=%x rbpr=%x\n", clk, div, clk, div); + pr_debug(" schr1=%x schr2=%x schr3=%x schr4=%x\n", tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP], tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]); -#endif spin_lock_irqsave(&brd_lock, flags); BRDENABLE(portp->brdnr, portp->pagenr); @@ -3443,15 +3081,13 @@ static void stl_cd1400setport(stlport_t *portp, struct termios *tiosp) * Set the state of the DTR and RTS signals. */ -static void stl_cd1400setsignals(stlport_t *portp, int dtr, int rts) +static void stl_cd1400setsignals(struct stlport *portp, int dtr, int rts) { unsigned char msvr1, msvr2; unsigned long flags; -#ifdef DEBUG - printk("stl_cd1400setsignals(portp=%x,dtr=%d,rts=%d)\n", - (int) portp, dtr, rts); -#endif + pr_debug("stl_cd1400setsignals(portp=%p,dtr=%d,rts=%d)\n", + portp, dtr, rts); msvr1 = 0; msvr2 = 0; @@ -3477,15 +3113,13 @@ static void stl_cd1400setsignals(stlport_t *portp, int dtr, int rts) * Return the state of the signals. */ -static int stl_cd1400getsignals(stlport_t *portp) +static int stl_cd1400getsignals(struct stlport *portp) { unsigned char msvr1, msvr2; unsigned long flags; int sigs; -#ifdef DEBUG - printk("stl_cd1400getsignals(portp=%x)\n", (int) portp); -#endif + pr_debug("stl_cd1400getsignals(portp=%p)\n", portp); spin_lock_irqsave(&brd_lock, flags); BRDENABLE(portp->brdnr, portp->pagenr); @@ -3515,15 +3149,13 @@ static int stl_cd1400getsignals(stlport_t *portp) * Enable/Disable the Transmitter and/or Receiver. */ -static void stl_cd1400enablerxtx(stlport_t *portp, int rx, int tx) +static void stl_cd1400enablerxtx(struct stlport *portp, int rx, int tx) { unsigned char ccr; unsigned long flags; -#ifdef DEBUG - printk("stl_cd1400enablerxtx(portp=%x,rx=%d,tx=%d)\n", - (int) portp, rx, tx); -#endif + pr_debug("stl_cd1400enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx); + ccr = 0; if (tx == 0) @@ -3551,15 +3183,12 @@ static void stl_cd1400enablerxtx(stlport_t *portp, int rx, int tx) * Start/stop the Transmitter and/or Receiver. */ -static void stl_cd1400startrxtx(stlport_t *portp, int rx, int tx) +static void stl_cd1400startrxtx(struct stlport *portp, int rx, int tx) { unsigned char sreron, sreroff; unsigned long flags; -#ifdef DEBUG - printk("stl_cd1400startrxtx(portp=%x,rx=%d,tx=%d)\n", - (int) portp, rx, tx); -#endif + pr_debug("stl_cd1400startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx); sreron = 0; sreroff = 0; @@ -3591,13 +3220,12 @@ static void stl_cd1400startrxtx(stlport_t *portp, int rx, int tx) * Disable all interrupts from this port. */ -static void stl_cd1400disableintrs(stlport_t *portp) +static void stl_cd1400disableintrs(struct stlport *portp) { unsigned long flags; -#ifdef DEBUG - printk("stl_cd1400disableintrs(portp=%x)\n", (int) portp); -#endif + pr_debug("stl_cd1400disableintrs(portp=%p)\n", portp); + spin_lock_irqsave(&brd_lock, flags); BRDENABLE(portp->brdnr, portp->pagenr); stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03)); @@ -3608,13 +3236,11 @@ static void stl_cd1400disableintrs(stlport_t *portp) /*****************************************************************************/ -static void stl_cd1400sendbreak(stlport_t *portp, int len) +static void stl_cd1400sendbreak(struct stlport *portp, int len) { unsigned long flags; -#ifdef DEBUG - printk("stl_cd1400sendbreak(portp=%x,len=%d)\n", (int) portp, len); -#endif + pr_debug("stl_cd1400sendbreak(portp=%p,len=%d)\n", portp, len); spin_lock_irqsave(&brd_lock, flags); BRDENABLE(portp->brdnr, portp->pagenr); @@ -3635,19 +3261,17 @@ static void stl_cd1400sendbreak(stlport_t *portp, int len) * Take flow control actions... */ -static void stl_cd1400flowctrl(stlport_t *portp, int state) +static void stl_cd1400flowctrl(struct stlport *portp, int state) { struct tty_struct *tty; unsigned long flags; -#ifdef DEBUG - printk("stl_cd1400flowctrl(portp=%x,state=%x)\n", (int) portp, state); -#endif + pr_debug("stl_cd1400flowctrl(portp=%p,state=%x)\n", portp, state); - if (portp == (stlport_t *) NULL) + if (portp == NULL) return; tty = portp->tty; - if (tty == (struct tty_struct *) NULL) + if (tty == NULL) return; spin_lock_irqsave(&brd_lock, flags); @@ -3699,19 +3323,17 @@ static void stl_cd1400flowctrl(stlport_t *portp, int state) * Send a flow control character... */ -static void stl_cd1400sendflow(stlport_t *portp, int state) +static void stl_cd1400sendflow(struct stlport *portp, int state) { struct tty_struct *tty; unsigned long flags; -#ifdef DEBUG - printk("stl_cd1400sendflow(portp=%x,state=%x)\n", (int) portp, state); -#endif + pr_debug("stl_cd1400sendflow(portp=%p,state=%x)\n", portp, state); - if (portp == (stlport_t *) NULL) + if (portp == NULL) return; tty = portp->tty; - if (tty == (struct tty_struct *) NULL) + if (tty == NULL) return; spin_lock_irqsave(&brd_lock, flags); @@ -3734,15 +3356,13 @@ static void stl_cd1400sendflow(stlport_t *portp, int state) /*****************************************************************************/ -static void stl_cd1400flush(stlport_t *portp) +static void stl_cd1400flush(struct stlport *portp) { unsigned long flags; -#ifdef DEBUG - printk("stl_cd1400flush(portp=%x)\n", (int) portp); -#endif + pr_debug("stl_cd1400flush(portp=%p)\n", portp); - if (portp == (stlport_t *) NULL) + if (portp == NULL) return; spin_lock_irqsave(&brd_lock, flags); @@ -3765,13 +3385,11 @@ static void stl_cd1400flush(stlport_t *portp) * maintains the busy port flag. */ -static int stl_cd1400datastate(stlport_t *portp) +static int stl_cd1400datastate(struct stlport *portp) { -#ifdef DEBUG - printk("stl_cd1400datastate(portp=%x)\n", (int) portp); -#endif + pr_debug("stl_cd1400datastate(portp=%p)\n", portp); - if (portp == (stlport_t *) NULL) + if (portp == NULL) return 0; return test_bit(ASYI_TXBUSY, &portp->istate) ? 1 : 0; @@ -3783,14 +3401,11 @@ static int stl_cd1400datastate(stlport_t *portp) * Interrupt service routine for cd1400 EasyIO boards. */ -static void stl_cd1400eiointr(stlpanel_t *panelp, unsigned int iobase) +static void stl_cd1400eiointr(struct stlpanel *panelp, unsigned int iobase) { unsigned char svrtype; -#ifdef DEBUG - printk("stl_cd1400eiointr(panelp=%x,iobase=%x)\n", - (int) panelp, iobase); -#endif + pr_debug("stl_cd1400eiointr(panelp=%p,iobase=%x)\n", panelp, iobase); spin_lock(&brd_lock); outb(SVRR, iobase); @@ -3816,14 +3431,11 @@ static void stl_cd1400eiointr(stlpanel_t *panelp, unsigned int iobase) * Interrupt service routine for cd1400 panels. */ -static void stl_cd1400echintr(stlpanel_t *panelp, unsigned int iobase) +static void stl_cd1400echintr(struct stlpanel *panelp, unsigned int iobase) { unsigned char svrtype; -#ifdef DEBUG - printk("stl_cd1400echintr(panelp=%x,iobase=%x)\n", (int) panelp, - iobase); -#endif + pr_debug("stl_cd1400echintr(panelp=%p,iobase=%x)\n", panelp, iobase); outb(SVRR, iobase); svrtype = inb(iobase + EREG_DATA); @@ -3845,7 +3457,7 @@ static void stl_cd1400echintr(stlpanel_t *panelp, unsigned int iobase) * this is the only way to generate them on the cd1400. */ -static inline int stl_cd1400breakisr(stlport_t *portp, int ioaddr) +static int stl_cd1400breakisr(struct stlport *portp, int ioaddr) { if (portp->brklen == 1) { outb((COR2 + portp->uartaddr), ioaddr); @@ -3887,16 +3499,14 @@ static inline int stl_cd1400breakisr(stlport_t *portp, int ioaddr) * be NULL if the buffer has been freed. */ -static void stl_cd1400txisr(stlpanel_t *panelp, int ioaddr) +static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr) { - stlport_t *portp; + struct stlport *portp; int len, stlen; char *head, *tail; unsigned char ioack, srer; -#ifdef DEBUG - printk("stl_cd1400txisr(panelp=%x,ioaddr=%x)\n", (int) panelp, ioaddr); -#endif + pr_debug("stl_cd1400txisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr); ioack = inb(ioaddr + EREG_TXACK); if (((ioack & panelp->ackmask) != 0) || @@ -3935,9 +3545,9 @@ static void stl_cd1400txisr(stlpanel_t *panelp, int ioaddr) } outb(srer, (ioaddr + EREG_DATA)); } else { - len = MIN(len, CD1400_TXFIFOSIZE); + len = min(len, CD1400_TXFIFOSIZE); portp->stats.txtotal += len; - stlen = MIN(len, ((portp->tx.buf + STL_TXBUFSIZE) - tail)); + stlen = min(len, ((portp->tx.buf + STL_TXBUFSIZE) - tail)); outb((TDR + portp->uartaddr), ioaddr); outsb((ioaddr + EREG_DATA), tail, stlen); len -= stlen; @@ -3968,17 +3578,15 @@ static void stl_cd1400txisr(stlpanel_t *panelp, int ioaddr) * shutdown a port not in user context. Need to handle this case. */ -static void stl_cd1400rxisr(stlpanel_t *panelp, int ioaddr) +static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr) { - stlport_t *portp; + struct stlport *portp; struct tty_struct *tty; unsigned int ioack, len, buflen; unsigned char status; char ch; -#ifdef DEBUG - printk("stl_cd1400rxisr(panelp=%x,ioaddr=%x)\n", (int) panelp, ioaddr); -#endif + pr_debug("stl_cd1400rxisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr); ioack = inb(ioaddr + EREG_RXACK); if ((ioack & panelp->ackmask) != 0) { @@ -3992,13 +3600,13 @@ static void stl_cd1400rxisr(stlpanel_t *panelp, int ioaddr) outb((RDCR + portp->uartaddr), ioaddr); len = inb(ioaddr + EREG_DATA); if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) { - len = MIN(len, sizeof(stl_unwanted)); + len = min(len, sizeof(stl_unwanted)); outb((RDSR + portp->uartaddr), ioaddr); insb((ioaddr + EREG_DATA), &stl_unwanted[0], len); portp->stats.rxlost += len; portp->stats.rxtotal += len; } else { - len = MIN(len, buflen); + len = min(len, buflen); if (len > 0) { unsigned char *ptr; outb((RDSR + portp->uartaddr), ioaddr); @@ -4035,18 +3643,16 @@ static void stl_cd1400rxisr(stlpanel_t *panelp, int ioaddr) do_SAK(tty); BRDENABLE(portp->brdnr, portp->pagenr); } - } else if (status & ST_PARITY) { + } else if (status & ST_PARITY) status = TTY_PARITY; - } else if (status & ST_FRAMING) { + else if (status & ST_FRAMING) status = TTY_FRAME; - } else if(status & ST_OVERRUN) { + else if(status & ST_OVERRUN) status = TTY_OVERRUN; - } else { + else status = 0; - } - } else { + } else status = 0; - } tty_insert_flip_char(tty, ch, status); tty_schedule_flip(tty); } @@ -4068,15 +3674,13 @@ static void stl_cd1400rxisr(stlpanel_t *panelp, int ioaddr) * processing routine. */ -static void stl_cd1400mdmisr(stlpanel_t *panelp, int ioaddr) +static void stl_cd1400mdmisr(struct stlpanel *panelp, int ioaddr) { - stlport_t *portp; + struct stlport *portp; unsigned int ioack; unsigned char misr; -#ifdef DEBUG - printk("stl_cd1400mdmisr(panelp=%x)\n", (int) panelp); -#endif + pr_debug("stl_cd1400mdmisr(panelp=%p)\n", panelp); ioack = inb(ioaddr + EREG_MDACK); if (((ioack & panelp->ackmask) != 0) || @@ -4108,19 +3712,19 @@ static void stl_cd1400mdmisr(stlpanel_t *panelp, int ioaddr) * (Maybe should make this inline...) */ -static int stl_sc26198getreg(stlport_t *portp, int regnr) +static int stl_sc26198getreg(struct stlport *portp, int regnr) { outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR)); return inb(portp->ioaddr + XP_DATA); } -static void stl_sc26198setreg(stlport_t *portp, int regnr, int value) +static void stl_sc26198setreg(struct stlport *portp, int regnr, int value) { outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR)); outb(value, (portp->ioaddr + XP_DATA)); } -static int stl_sc26198updatereg(stlport_t *portp, int regnr, int value) +static int stl_sc26198updatereg(struct stlport *portp, int regnr, int value) { outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR)); if (inb(portp->ioaddr + XP_DATA) != value) { @@ -4136,14 +3740,14 @@ static int stl_sc26198updatereg(stlport_t *portp, int regnr, int value) * Functions to get and set the sc26198 global registers. */ -static int stl_sc26198getglobreg(stlport_t *portp, int regnr) +static int stl_sc26198getglobreg(struct stlport *portp, int regnr) { outb(regnr, (portp->ioaddr + XP_ADDR)); return inb(portp->ioaddr + XP_DATA); } #if 0 -static void stl_sc26198setglobreg(stlport_t *portp, int regnr, int value) +static void stl_sc26198setglobreg(struct stlport *portp, int regnr, int value) { outb(regnr, (portp->ioaddr + XP_ADDR)); outb(value, (portp->ioaddr + XP_DATA)); @@ -4158,15 +3762,12 @@ static void stl_sc26198setglobreg(stlport_t *portp, int regnr, int value) * identical when dealing with ports. */ -static int stl_sc26198panelinit(stlbrd_t *brdp, stlpanel_t *panelp) +static int stl_sc26198panelinit(struct stlbrd *brdp, struct stlpanel *panelp) { int chipmask, i; int nrchips, ioaddr; -#ifdef DEBUG - printk("stl_sc26198panelinit(brdp=%x,panelp=%x)\n", - (int) brdp, (int) panelp); -#endif + pr_debug("stl_sc26198panelinit(brdp=%p,panelp=%p)\n", brdp, panelp); BRDENABLE(panelp->brdnr, panelp->pagenr); @@ -4178,7 +3779,7 @@ static int stl_sc26198panelinit(stlbrd_t *brdp, stlpanel_t *panelp) if (brdp->brdtype == BRD_ECHPCI) outb(panelp->pagenr, brdp->ioctrl); - for (i = 0; (i < nrchips); i++) { + for (i = 0; i < nrchips; i++) { ioaddr = panelp->iobase + (i * 4); outb(SCCR, (ioaddr + XP_ADDR)); outb(CR_RESETALL, (ioaddr + XP_DATA)); @@ -4206,15 +3807,13 @@ static int stl_sc26198panelinit(stlbrd_t *brdp, stlpanel_t *panelp) * Initialize hardware specific port registers. */ -static void stl_sc26198portinit(stlbrd_t *brdp, stlpanel_t *panelp, stlport_t *portp) +static void stl_sc26198portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp) { -#ifdef DEBUG - printk("stl_sc26198portinit(brdp=%x,panelp=%x,portp=%x)\n", - (int) brdp, (int) panelp, (int) portp); -#endif + pr_debug("stl_sc26198portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp, + panelp, portp); - if ((brdp == (stlbrd_t *) NULL) || (panelp == (stlpanel_t *) NULL) || - (portp == (stlport_t *) NULL)) + if ((brdp == NULL) || (panelp == NULL) || + (portp == NULL)) return; portp->ioaddr = panelp->iobase + ((portp->portnr < 8) ? 0 : 4); @@ -4234,9 +3833,9 @@ static void stl_sc26198portinit(stlbrd_t *brdp, stlpanel_t *panelp, stlport_t *p * settings. */ -static void stl_sc26198setport(stlport_t *portp, struct termios *tiosp) +static void stl_sc26198setport(struct stlport *portp, struct ktermios *tiosp) { - stlbrd_t *brdp; + struct stlbrd *brdp; unsigned long flags; unsigned int baudrate; unsigned char mr0, mr1, mr2, clk; @@ -4251,7 +3850,7 @@ static void stl_sc26198setport(stlport_t *portp, struct termios *tiosp) imroff = 0; brdp = stl_brds[portp->brdnr]; - if (brdp == (stlbrd_t *) NULL) + if (brdp == NULL) return; /* @@ -4300,9 +3899,8 @@ static void stl_sc26198setport(stlport_t *portp, struct termios *tiosp) mr1 |= (MR1_PARENB | MR1_PARODD); else mr1 |= (MR1_PARENB | MR1_PAREVEN); - } else { + } else mr1 |= MR1_PARNONE; - } mr1 |= MR1_ERRBLOCK; @@ -4342,12 +3940,10 @@ static void stl_sc26198setport(stlport_t *portp, struct termios *tiosp) if (baudrate > STL_SC26198MAXBAUD) baudrate = STL_SC26198MAXBAUD; - if (baudrate > 0) { - for (clk = 0; (clk < SC26198_NRBAUDS); clk++) { + if (baudrate > 0) + for (clk = 0; clk < SC26198_NRBAUDS; clk++) if (baudrate <= sc26198_baudtable[clk]) break; - } - } /* * Check what form of modem signaling is required and set it up. @@ -4369,9 +3965,9 @@ static void stl_sc26198setport(stlport_t *portp, struct termios *tiosp) if (tiosp->c_iflag & IXON) { mr0 |= MR0_SWFTX | MR0_SWFT; imron |= IR_XONXOFF; - } else { + } else imroff |= IR_XONXOFF; - } + if (tiosp->c_iflag & IXOFF) mr0 |= MR0_SWFRX; @@ -4385,15 +3981,13 @@ static void stl_sc26198setport(stlport_t *portp, struct termios *tiosp) * them all up. */ -#ifdef DEBUG - printk("SETPORT: portnr=%d panelnr=%d brdnr=%d\n", + pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n", portp->portnr, portp->panelnr, portp->brdnr); - printk(" mr0=%x mr1=%x mr2=%x clk=%x\n", mr0, mr1, mr2, clk); - printk(" iopr=%x imron=%x imroff=%x\n", iopr, imron, imroff); - printk(" schr1=%x schr2=%x schr3=%x schr4=%x\n", + pr_debug(" mr0=%x mr1=%x mr2=%x clk=%x\n", mr0, mr1, mr2, clk); + pr_debug(" iopr=%x imron=%x imroff=%x\n", iopr, imron, imroff); + pr_debug(" schr1=%x schr2=%x schr3=%x schr4=%x\n", tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP], tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]); -#endif spin_lock_irqsave(&brd_lock, flags); BRDENABLE(portp->brdnr, portp->pagenr); @@ -4431,15 +4025,13 @@ static void stl_sc26198setport(stlport_t *portp, struct termios *tiosp) * Set the state of the DTR and RTS signals. */ -static void stl_sc26198setsignals(stlport_t *portp, int dtr, int rts) +static void stl_sc26198setsignals(struct stlport *portp, int dtr, int rts) { unsigned char iopioron, iopioroff; unsigned long flags; -#ifdef DEBUG - printk("stl_sc26198setsignals(portp=%x,dtr=%d,rts=%d)\n", - (int) portp, dtr, rts); -#endif + pr_debug("stl_sc26198setsignals(portp=%p,dtr=%d,rts=%d)\n", portp, + dtr, rts); iopioron = 0; iopioroff = 0; @@ -4466,15 +4058,13 @@ static void stl_sc26198setsignals(stlport_t *portp, int dtr, int rts) * Return the state of the signals. */ -static int stl_sc26198getsignals(stlport_t *portp) +static int stl_sc26198getsignals(struct stlport *portp) { unsigned char ipr; unsigned long flags; int sigs; -#ifdef DEBUG - printk("stl_sc26198getsignals(portp=%x)\n", (int) portp); -#endif + pr_debug("stl_sc26198getsignals(portp=%p)\n", portp); spin_lock_irqsave(&brd_lock, flags); BRDENABLE(portp->brdnr, portp->pagenr); @@ -4497,15 +4087,12 @@ static int stl_sc26198getsignals(stlport_t *portp) * Enable/Disable the Transmitter and/or Receiver. */ -static void stl_sc26198enablerxtx(stlport_t *portp, int rx, int tx) +static void stl_sc26198enablerxtx(struct stlport *portp, int rx, int tx) { unsigned char ccr; unsigned long flags; -#ifdef DEBUG - printk("stl_sc26198enablerxtx(portp=%x,rx=%d,tx=%d)\n", - (int) portp, rx, tx); -#endif + pr_debug("stl_sc26198enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx,tx); ccr = portp->crenable; if (tx == 0) @@ -4531,15 +4118,12 @@ static void stl_sc26198enablerxtx(stlport_t *portp, int rx, int tx) * Start/stop the Transmitter and/or Receiver. */ -static void stl_sc26198startrxtx(stlport_t *portp, int rx, int tx) +static void stl_sc26198startrxtx(struct stlport *portp, int rx, int tx) { unsigned char imr; unsigned long flags; -#ifdef DEBUG - printk("stl_sc26198startrxtx(portp=%x,rx=%d,tx=%d)\n", - (int) portp, rx, tx); -#endif + pr_debug("stl_sc26198startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx); imr = portp->imr; if (tx == 0) @@ -4567,13 +4151,11 @@ static void stl_sc26198startrxtx(stlport_t *portp, int rx, int tx) * Disable all interrupts from this port. */ -static void stl_sc26198disableintrs(stlport_t *portp) +static void stl_sc26198disableintrs(struct stlport *portp) { unsigned long flags; -#ifdef DEBUG - printk("stl_sc26198disableintrs(portp=%x)\n", (int) portp); -#endif + pr_debug("stl_sc26198disableintrs(portp=%p)\n", portp); spin_lock_irqsave(&brd_lock, flags); BRDENABLE(portp->brdnr, portp->pagenr); @@ -4585,22 +4167,20 @@ static void stl_sc26198disableintrs(stlport_t *portp) /*****************************************************************************/ -static void stl_sc26198sendbreak(stlport_t *portp, int len) +static void stl_sc26198sendbreak(struct stlport *portp, int len) { unsigned long flags; -#ifdef DEBUG - printk("stl_sc26198sendbreak(portp=%x,len=%d)\n", (int) portp, len); -#endif + pr_debug("stl_sc26198sendbreak(portp=%p,len=%d)\n", portp, len); spin_lock_irqsave(&brd_lock, flags); BRDENABLE(portp->brdnr, portp->pagenr); if (len == 1) { stl_sc26198setreg(portp, SCCR, CR_TXSTARTBREAK); portp->stats.txbreaks++; - } else { + } else stl_sc26198setreg(portp, SCCR, CR_TXSTOPBREAK); - } + BRDDISABLE(portp->brdnr); spin_unlock_irqrestore(&brd_lock, flags); } @@ -4611,20 +4191,18 @@ static void stl_sc26198sendbreak(stlport_t *portp, int len) * Take flow control actions... */ -static void stl_sc26198flowctrl(stlport_t *portp, int state) +static void stl_sc26198flowctrl(struct stlport *portp, int state) { struct tty_struct *tty; unsigned long flags; unsigned char mr0; -#ifdef DEBUG - printk("stl_sc26198flowctrl(portp=%x,state=%x)\n", (int) portp, state); -#endif + pr_debug("stl_sc26198flowctrl(portp=%p,state=%x)\n", portp, state); - if (portp == (stlport_t *) NULL) + if (portp == NULL) return; tty = portp->tty; - if (tty == (struct tty_struct *) NULL) + if (tty == NULL) return; spin_lock_irqsave(&brd_lock, flags); @@ -4682,20 +4260,18 @@ static void stl_sc26198flowctrl(stlport_t *portp, int state) * Send a flow control character. */ -static void stl_sc26198sendflow(stlport_t *portp, int state) +static void stl_sc26198sendflow(struct stlport *portp, int state) { struct tty_struct *tty; unsigned long flags; unsigned char mr0; -#ifdef DEBUG - printk("stl_sc26198sendflow(portp=%x,state=%x)\n", (int) portp, state); -#endif + pr_debug("stl_sc26198sendflow(portp=%p,state=%x)\n", portp, state); - if (portp == (stlport_t *) NULL) + if (portp == NULL) return; tty = portp->tty; - if (tty == (struct tty_struct *) NULL) + if (tty == NULL) return; spin_lock_irqsave(&brd_lock, flags); @@ -4723,15 +4299,13 @@ static void stl_sc26198sendflow(stlport_t *portp, int state) /*****************************************************************************/ -static void stl_sc26198flush(stlport_t *portp) +static void stl_sc26198flush(struct stlport *portp) { unsigned long flags; -#ifdef DEBUG - printk("stl_sc26198flush(portp=%x)\n", (int) portp); -#endif + pr_debug("stl_sc26198flush(portp=%p)\n", portp); - if (portp == (stlport_t *) NULL) + if (portp == NULL) return; spin_lock_irqsave(&brd_lock, flags); @@ -4753,16 +4327,14 @@ static void stl_sc26198flush(stlport_t *portp) * check the port statusy register to be sure. */ -static int stl_sc26198datastate(stlport_t *portp) +static int stl_sc26198datastate(struct stlport *portp) { unsigned long flags; unsigned char sr; -#ifdef DEBUG - printk("stl_sc26198datastate(portp=%x)\n", (int) portp); -#endif + pr_debug("stl_sc26198datastate(portp=%p)\n", portp); - if (portp == (stlport_t *) NULL) + if (portp == NULL) return 0; if (test_bit(ASYI_TXBUSY, &portp->istate)) return 1; @@ -4783,18 +4355,16 @@ static int stl_sc26198datastate(stlport_t *portp) * to process a command... */ -static void stl_sc26198wait(stlport_t *portp) +static void stl_sc26198wait(struct stlport *portp) { int i; -#ifdef DEBUG - printk("stl_sc26198wait(portp=%x)\n", (int) portp); -#endif + pr_debug("stl_sc26198wait(portp=%p)\n", portp); - if (portp == (stlport_t *) NULL) + if (portp == NULL) return; - for (i = 0; (i < 20); i++) + for (i = 0; i < 20; i++) stl_sc26198getglobreg(portp, TSTR); } @@ -4806,7 +4376,7 @@ static void stl_sc26198wait(stlport_t *portp) * automatic flow control modes of the sc26198. */ -static inline void stl_sc26198txunflow(stlport_t *portp, struct tty_struct *tty) +static void stl_sc26198txunflow(struct stlport *portp, struct tty_struct *tty) { unsigned char mr0; @@ -4824,9 +4394,9 @@ static inline void stl_sc26198txunflow(stlport_t *portp, struct tty_struct *tty) * Interrupt service routine for sc26198 panels. */ -static void stl_sc26198intr(stlpanel_t *panelp, unsigned int iobase) +static void stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase) { - stlport_t *portp; + struct stlport *portp; unsigned int iack; spin_lock(&brd_lock); @@ -4862,16 +4432,14 @@ static void stl_sc26198intr(stlpanel_t *panelp, unsigned int iobase) * be NULL if the buffer has been freed. */ -static void stl_sc26198txisr(stlport_t *portp) +static void stl_sc26198txisr(struct stlport *portp) { unsigned int ioaddr; unsigned char mr0; int len, stlen; char *head, *tail; -#ifdef DEBUG - printk("stl_sc26198txisr(portp=%x)\n", (int) portp); -#endif + pr_debug("stl_sc26198txisr(portp=%p)\n", portp); ioaddr = portp->ioaddr; head = portp->tx.head; @@ -4896,9 +4464,9 @@ static void stl_sc26198txisr(stlport_t *portp) outb(mr0, (ioaddr + XP_DATA)); } } else { - len = MIN(len, SC26198_TXFIFOSIZE); + len = min(len, SC26198_TXFIFOSIZE); portp->stats.txtotal += len; - stlen = MIN(len, ((portp->tx.buf + STL_TXBUFSIZE) - tail)); + stlen = min(len, ((portp->tx.buf + STL_TXBUFSIZE) - tail)); outb(GTXFIFO, (ioaddr + XP_ADDR)); outsb((ioaddr + XP_DATA), tail, stlen); len -= stlen; @@ -4925,14 +4493,12 @@ static void stl_sc26198txisr(stlport_t *portp) * shutdown a port not in user context. Need to handle this case. */ -static void stl_sc26198rxisr(stlport_t *portp, unsigned int iack) +static void stl_sc26198rxisr(struct stlport *portp, unsigned int iack) { struct tty_struct *tty; unsigned int len, buflen, ioaddr; -#ifdef DEBUG - printk("stl_sc26198rxisr(portp=%x,iack=%x)\n", (int) portp, iack); -#endif + pr_debug("stl_sc26198rxisr(portp=%p,iack=%x)\n", portp, iack); tty = portp->tty; ioaddr = portp->ioaddr; @@ -4941,13 +4507,13 @@ static void stl_sc26198rxisr(stlport_t *portp, unsigned int iack) if ((iack & IVR_TYPEMASK) == IVR_RXDATA) { if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) { - len = MIN(len, sizeof(stl_unwanted)); + len = min(len, sizeof(stl_unwanted)); outb(GRXFIFO, (ioaddr + XP_ADDR)); insb((ioaddr + XP_DATA), &stl_unwanted[0], len); portp->stats.rxlost += len; portp->stats.rxtotal += len; } else { - len = MIN(len, buflen); + len = min(len, buflen); if (len > 0) { unsigned char *ptr; outb(GRXFIFO, (ioaddr + XP_ADDR)); @@ -4967,8 +4533,8 @@ static void stl_sc26198rxisr(stlport_t *portp, unsigned int iack) * flow control modes of the sc26198. */ if (test_bit(ASYI_TXFLOWED, &portp->istate)) { - if ((tty != (struct tty_struct *) NULL) && - (tty->termios != (struct termios *) NULL) && + if ((tty != NULL) && + (tty->termios != NULL) && (tty->termios->c_iflag & IXANY)) { stl_sc26198txunflow(portp, tty); } @@ -4981,7 +4547,7 @@ static void stl_sc26198rxisr(stlport_t *portp, unsigned int iack) * Process an RX bad character. */ -static inline void stl_sc26198rxbadch(stlport_t *portp, unsigned char status, char ch) +static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char ch) { struct tty_struct *tty; unsigned int ioaddr; @@ -4998,7 +4564,7 @@ static inline void stl_sc26198rxbadch(stlport_t *portp, unsigned char status, ch if (status & SR_RXBREAK) portp->stats.rxbreaks++; - if ((tty != (struct tty_struct *) NULL) && + if ((tty != NULL) && ((portp->rxignoremsk & status) == 0)) { if (portp->rxmarkmsk & status) { if (status & SR_RXBREAK) { @@ -5007,18 +4573,16 @@ static inline void stl_sc26198rxbadch(stlport_t *portp, unsigned char status, ch do_SAK(tty); BRDENABLE(portp->brdnr, portp->pagenr); } - } else if (status & SR_RXPARITY) { + } else if (status & SR_RXPARITY) status = TTY_PARITY; - } else if (status & SR_RXFRAMING) { + else if (status & SR_RXFRAMING) status = TTY_FRAME; - } else if(status & SR_RXOVERRUN) { + else if(status & SR_RXOVERRUN) status = TTY_OVERRUN; - } else { + else status = 0; - } - } else { + } else status = 0; - } tty_insert_flip_char(tty, ch, status); tty_schedule_flip(tty); @@ -5039,7 +4603,7 @@ static inline void stl_sc26198rxbadch(stlport_t *portp, unsigned char status, ch * the FIFO). */ -static void stl_sc26198rxbadchars(stlport_t *portp) +static void stl_sc26198rxbadchars(struct stlport *portp) { unsigned char status, mr1; char ch; @@ -5072,13 +4636,11 @@ static void stl_sc26198rxbadchars(stlport_t *portp) * processing time. */ -static void stl_sc26198otherisr(stlport_t *portp, unsigned int iack) +static void stl_sc26198otherisr(struct stlport *portp, unsigned int iack) { unsigned char cir, ipr, xisr; -#ifdef DEBUG - printk("stl_sc26198otherisr(portp=%x,iack=%x)\n", (int) portp, iack); -#endif + pr_debug("stl_sc26198otherisr(portp=%p,iack=%x)\n", portp, iack); cir = stl_sc26198getglobreg(portp, CIR); @@ -5111,4 +4673,172 @@ static void stl_sc26198otherisr(stlport_t *portp, unsigned int iack) } } -/*****************************************************************************/ +static void stl_free_isabrds(void) +{ + struct stlbrd *brdp; + unsigned int i; + + for (i = 0; i < stl_nrbrds; i++) { + if ((brdp = stl_brds[i]) == NULL || (brdp->state & STL_PROBED)) + continue; + + free_irq(brdp->irq, brdp); + + stl_cleanup_panels(brdp); + + release_region(brdp->ioaddr1, brdp->iosize1); + if (brdp->iosize2 > 0) + release_region(brdp->ioaddr2, brdp->iosize2); + + kfree(brdp); + stl_brds[i] = NULL; + } +} + +/* + * Loadable module initialization stuff. + */ +static int __init stallion_module_init(void) +{ + struct stlbrd *brdp; + struct stlconf conf; + unsigned int i, j; + int retval; + + printk(KERN_INFO "%s: version %s\n", stl_drvtitle, stl_drvversion); + + spin_lock_init(&stallion_lock); + spin_lock_init(&brd_lock); + +/* + * Find any dynamically supported boards. That is via module load + * line options. + */ + for (i = stl_nrbrds; i < stl_nargs; i++) { + memset(&conf, 0, sizeof(conf)); + if (stl_parsebrd(&conf, stl_brdsp[i]) == 0) + continue; + if ((brdp = stl_allocbrd()) == NULL) + continue; + brdp->brdnr = i; + brdp->brdtype = conf.brdtype; + brdp->ioaddr1 = conf.ioaddr1; + brdp->ioaddr2 = conf.ioaddr2; + brdp->irq = conf.irq; + brdp->irqtype = conf.irqtype; + if (stl_brdinit(brdp)) + kfree(brdp); + else { + for (j = 0; j < brdp->nrports; j++) + tty_register_device(stl_serial, + brdp->brdnr * STL_MAXPORTS + j, NULL); + stl_brds[brdp->brdnr] = brdp; + stl_nrbrds = i + 1; + } + } + + /* this has to be _after_ isa finding because of locking */ + retval = pci_register_driver(&stl_pcidriver); + if (retval && stl_nrbrds == 0) + goto err; + + stl_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS); + if (!stl_serial) { + retval = -ENOMEM; + goto err_pcidr; + } + +/* + * Set up a character driver for per board stuff. This is mainly used + * to do stats ioctls on the ports. + */ + if (register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stl_fsiomem)) + printk("STALLION: failed to register serial board device\n"); + + stallion_class = class_create(THIS_MODULE, "staliomem"); + if (IS_ERR(stallion_class)) { + retval = PTR_ERR(stallion_class); + goto err_reg; + } + for (i = 0; i < 4; i++) + class_device_create(stallion_class, NULL, + MKDEV(STL_SIOMEMMAJOR, i), NULL, + "staliomem%d", i); + + stl_serial->owner = THIS_MODULE; + stl_serial->driver_name = stl_drvname; + stl_serial->name = "ttyE"; + stl_serial->major = STL_SERIALMAJOR; + stl_serial->minor_start = 0; + stl_serial->type = TTY_DRIVER_TYPE_SERIAL; + stl_serial->subtype = SERIAL_TYPE_NORMAL; + stl_serial->init_termios = stl_deftermios; + stl_serial->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; + tty_set_operations(stl_serial, &stl_ops); + + retval = tty_register_driver(stl_serial); + if (retval) { + printk("STALLION: failed to register serial driver\n"); + goto err_clsdev; + } + + return 0; +err_clsdev: + for (i = 0; i < 4; i++) + class_device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i)); + class_destroy(stallion_class); +err_reg: + unregister_chrdev(STL_SIOMEMMAJOR, "staliomem"); + put_tty_driver(stl_serial); +err_pcidr: + pci_unregister_driver(&stl_pcidriver); + stl_free_isabrds(); +err: + return retval; +} + +static void __exit stallion_module_exit(void) +{ + struct stlbrd *brdp; + unsigned int i, j; + int retval; + + pr_debug("cleanup_module()\n"); + + printk(KERN_INFO "Unloading %s: version %s\n", stl_drvtitle, + stl_drvversion); + +/* + * Free up all allocated resources used by the ports. This includes + * memory and interrupts. As part of this process we will also do + * a hangup on every open port - to try to flush out any processes + * hanging onto ports. + */ + for (i = 0; i < stl_nrbrds; i++) { + if ((brdp = stl_brds[i]) == NULL || (brdp->state & STL_PROBED)) + continue; + for (j = 0; j < brdp->nrports; j++) + tty_unregister_device(stl_serial, + brdp->brdnr * STL_MAXPORTS + j); + } + tty_unregister_driver(stl_serial); + put_tty_driver(stl_serial); + + for (i = 0; i < 4; i++) + class_device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i)); + if ((retval = unregister_chrdev(STL_SIOMEMMAJOR, "staliomem"))) + printk("STALLION: failed to un-register serial memory device, " + "errno=%d\n", -retval); + class_destroy(stallion_class); + + pci_unregister_driver(&stl_pcidriver); + + stl_free_isabrds(); +} + +module_init(stallion_module_init); +module_exit(stallion_module_exit); + +MODULE_AUTHOR("Greg Ungerer"); +MODULE_DESCRIPTION("Stallion Multiport Serial Driver"); +MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/char/sx.c b/trunk/drivers/char/sx.c index cc10af08cb05..a3008ce13015 100644 --- a/trunk/drivers/char/sx.c +++ b/trunk/drivers/char/sx.c @@ -32,7 +32,6 @@ * USA. * * Revision history: - * $Log: sx.c,v $ * Revision 1.33 2000/03/09 10:00:00 pvdl,wolff * - Fixed module and port counting * - Fixed signal handling @@ -199,9 +198,7 @@ * * */ - -#define RCS_ID "$Id: sx.c,v 1.33 2000/03/08 10:01:02 wolff, pvdl Exp $" -#define RCS_REV "$Revision: 1.33 $" +#define SX_VERSION 1.33 #include #include @@ -217,6 +214,7 @@ #include #include #include +#include #include #include #include @@ -240,7 +238,6 @@ #include #include "sx.h" - /* I don't think that this driver can handle more than 256 ports on one machine. You'll have to increase the number of boards in sx.h if you want more than 4 boards. */ @@ -249,21 +246,12 @@ #define PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8 0x2000 #endif -#ifdef CONFIG_PCI -static struct pci_device_id sx_pci_tbl[] = { - { PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8, PCI_ANY_ID, PCI_ANY_ID }, - { 0 } -}; -MODULE_DEVICE_TABLE(pci, sx_pci_tbl); -#endif /* CONFIG_PCI */ - /* Configurable options: (Don't be too sure that it'll work if you toggle them) */ /* Am I paranoid or not ? ;-) */ #undef SX_PARANOIA_CHECK - /* 20 -> 2000 per second. The card should rate-limit interrupts at 100 Hz, but it is user configurable. I don't recommend going above 1000 Hz. The interrupt ratelimit might trigger if the interrupt is @@ -277,7 +265,6 @@ MODULE_DEVICE_TABLE(pci, sx_pci_tbl); interrupt. Use polling. */ #undef IRQ_RATE_LIMIT - #if 0 /* Not implemented */ /* @@ -286,35 +273,33 @@ MODULE_DEVICE_TABLE(pci, sx_pci_tbl); */ #define SX_REPORT_FIFO #define SX_REPORT_OVERRUN -#endif - +#endif /* Function prototypes */ -static void sx_disable_tx_interrupts (void * ptr); -static void sx_enable_tx_interrupts (void * ptr); -static void sx_disable_rx_interrupts (void * ptr); -static void sx_enable_rx_interrupts (void * ptr); -static int sx_get_CD (void * ptr); -static void sx_shutdown_port (void * ptr); -static int sx_set_real_termios (void *ptr); -static void sx_close (void *ptr); -static int sx_chars_in_buffer (void * ptr); -static int sx_init_board (struct sx_board *board); -static int sx_init_portstructs (int nboards, int nports); -static int sx_fw_ioctl (struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); +static void sx_disable_tx_interrupts(void *ptr); +static void sx_enable_tx_interrupts(void *ptr); +static void sx_disable_rx_interrupts(void *ptr); +static void sx_enable_rx_interrupts(void *ptr); +static int sx_get_CD(void *ptr); +static void sx_shutdown_port(void *ptr); +static int sx_set_real_termios(void *ptr); +static void sx_close(void *ptr); +static int sx_chars_in_buffer(void *ptr); +static int sx_init_board(struct sx_board *board); +static int sx_init_portstructs(int nboards, int nports); +static int sx_fw_ioctl(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); static int sx_init_drivers(void); - static struct tty_driver *sx_driver; +static DEFINE_MUTEX(sx_boards_lock); static struct sx_board boards[SX_NBOARDS]; static struct sx_port *sx_ports; static int sx_initialized; static int sx_nports; static int sx_debug; - /* You can have the driver poll your card. - Set sx_poll to 1 to poll every timer tick (10ms on Intel). This is used when the card cannot use an interrupt for some reason. @@ -333,27 +318,36 @@ static int sx_slowpoll; static int sx_maxints = 100; +#ifdef CONFIG_ISA + /* These are the only open spaces in my computer. Yours may have more or less.... -- REW duh: Card at 0xa0000 is possible on HP Netserver?? -- pvdl */ -static int sx_probe_addrs[]= {0xc0000, 0xd0000, 0xe0000, - 0xc8000, 0xd8000, 0xe8000}; -static int si_probe_addrs[]= {0xc0000, 0xd0000, 0xe0000, - 0xc8000, 0xd8000, 0xe8000, 0xa0000}; -static int si1_probe_addrs[]= { 0xd0000}; +static int sx_probe_addrs[] = { + 0xc0000, 0xd0000, 0xe0000, + 0xc8000, 0xd8000, 0xe8000 +}; +static int si_probe_addrs[] = { + 0xc0000, 0xd0000, 0xe0000, + 0xc8000, 0xd8000, 0xe8000, 0xa0000 +}; +static int si1_probe_addrs[] = { + 0xd0000 +}; #define NR_SX_ADDRS ARRAY_SIZE(sx_probe_addrs) #define NR_SI_ADDRS ARRAY_SIZE(si_probe_addrs) #define NR_SI1_ADDRS ARRAY_SIZE(si1_probe_addrs) +module_param_array(sx_probe_addrs, int, NULL, 0); +module_param_array(si_probe_addrs, int, NULL, 0); +#endif /* Set the mask to all-ones. This alas, only supports 32 interrupts. Some architectures may need more. */ static int sx_irqmask = -1; -module_param_array(sx_probe_addrs, int, NULL, 0); -module_param_array(si_probe_addrs, int, NULL, 0); module_param(sx_poll, int, 0); module_param(sx_slowpoll, int, 0); module_param(sx_maxints, int, 0); @@ -368,13 +362,12 @@ static struct real_driver sx_real_driver = { sx_disable_rx_interrupts, sx_enable_rx_interrupts, sx_get_CD, - sx_shutdown_port, - sx_set_real_termios, + sx_shutdown_port, + sx_set_real_termios, sx_chars_in_buffer, sx_close, }; - /* This driver can spew a whole lot of debugging output at you. If you need maximum performance, you should disable the DEBUG define. To @@ -385,23 +378,17 @@ static struct real_driver sx_real_driver = { */ #define DEBUG - #ifdef DEBUG -#define sx_dprintk(f, str...) if (sx_debug & f) printk (str) +#define sx_dprintk(f, str...) if (sx_debug & f) printk (str) #else -#define sx_dprintk(f, str...) /* nothing */ +#define sx_dprintk(f, str...) /* nothing */ #endif +#define func_enter() sx_dprintk(SX_DEBUG_FLOW, "sx: enter %s\n",__FUNCTION__) +#define func_exit() sx_dprintk(SX_DEBUG_FLOW, "sx: exit %s\n",__FUNCTION__) - -#define func_enter() sx_dprintk (SX_DEBUG_FLOW, "sx: enter %s\n",__FUNCTION__) -#define func_exit() sx_dprintk (SX_DEBUG_FLOW, "sx: exit %s\n", __FUNCTION__) - -#define func_enter2() sx_dprintk (SX_DEBUG_FLOW, "sx: enter %s (port %d)\n", \ - __FUNCTION__, port->line) - - - +#define func_enter2() sx_dprintk(SX_DEBUG_FLOW, "sx: enter %s (port %d)\n", \ + __FUNCTION__, port->line) /* * Firmware loader driver specific routines @@ -409,31 +396,26 @@ static struct real_driver sx_real_driver = { */ static const struct file_operations sx_fw_fops = { - .owner = THIS_MODULE, - .ioctl = sx_fw_ioctl, + .owner = THIS_MODULE, + .ioctl = sx_fw_ioctl, }; static struct miscdevice sx_fw_device = { SXCTL_MISC_MINOR, "sxctl", &sx_fw_fops }; - - - - #ifdef SX_PARANOIA_CHECK /* This doesn't work. Who's paranoid around here? Not me! */ -static inline int sx_paranoia_check(struct sx_port const * port, +static inline int sx_paranoia_check(struct sx_port const *port, char *name, const char *routine) { + static const char *badmagic = KERN_ERR "sx: Warning: bad sx port magic " + "number for device %s in %s\n"; + static const char *badinfo = KERN_ERR "sx: Warning: null sx port for " + "device %s in %s\n"; - static const char *badmagic = - KERN_ERR "sx: Warning: bad sx port magic number for device %s in %s\n"; - static const char *badinfo = - KERN_ERR "sx: Warning: null sx port for device %s in %s\n"; - if (!port) { printk(badinfo, name, routine); return 1; @@ -456,23 +438,24 @@ static inline int sx_paranoia_check(struct sx_port const * port, #define TIMEOUT_1 30 #define TIMEOUT_2 1000000 - #ifdef DEBUG static void my_hd_io(void __iomem *p, int len) { int i, j, ch; unsigned char __iomem *addr = p; - for (i=0;i 0x7f)?'.':ch)); + for (j = 0; j < 16; j++) { + ch = readb(addr + j + i); + printk("%c", (ch < 0x20) ? '.' : + ((ch > 0x7f) ? '.' : ch)); } - printk ("\n"); + printk("\n"); } } static void my_hd(void *p, int len) @@ -480,419 +463,468 @@ static void my_hd(void *p, int len) int i, j, ch; unsigned char *addr = p; - for (i=0;i 0x7f)?'.':ch)); + for (j = 0; j < 16; j++) { + ch = addr[j + i]; + printk("%c", (ch < 0x20) ? '.' : + ((ch > 0x7f) ? '.' : ch)); } - printk ("\n"); + printk("\n"); } } #endif - - /* This needs redoing for Alpha -- REW -- Done. */ -static inline void write_sx_byte (struct sx_board *board, int offset, u8 byte) +static inline void write_sx_byte(struct sx_board *board, int offset, u8 byte) { - writeb (byte, board->base+offset); + writeb(byte, board->base + offset); } -static inline u8 read_sx_byte (struct sx_board *board, int offset) +static inline u8 read_sx_byte(struct sx_board *board, int offset) { - return readb (board->base+offset); + return readb(board->base + offset); } - -static inline void write_sx_word (struct sx_board *board, int offset, u16 word) +static inline void write_sx_word(struct sx_board *board, int offset, u16 word) { - writew (word, board->base+offset); + writew(word, board->base + offset); } -static inline u16 read_sx_word (struct sx_board *board, int offset) +static inline u16 read_sx_word(struct sx_board *board, int offset) { - return readw (board->base + offset); + return readw(board->base + offset); } - -static int sx_busy_wait_eq (struct sx_board *board, - int offset, int mask, int correctval) +static int sx_busy_wait_eq(struct sx_board *board, + int offset, int mask, int correctval) { int i; - func_enter (); + func_enter(); - for (i=0; i < TIMEOUT_1 ;i++) - if ((read_sx_byte (board, offset) & mask) == correctval) { - func_exit (); + for (i = 0; i < TIMEOUT_1; i++) + if ((read_sx_byte(board, offset) & mask) == correctval) { + func_exit(); return 1; } - for (i=0; i < TIMEOUT_2 ;i++) { - if ((read_sx_byte (board, offset) & mask) == correctval) { - func_exit (); + for (i = 0; i < TIMEOUT_2; i++) { + if ((read_sx_byte(board, offset) & mask) == correctval) { + func_exit(); return 1; } - udelay (1); + udelay(1); } - func_exit (); + func_exit(); return 0; } - -static int sx_busy_wait_neq (struct sx_board *board, - int offset, int mask, int badval) +static int sx_busy_wait_neq(struct sx_board *board, + int offset, int mask, int badval) { int i; - func_enter (); + func_enter(); - for (i=0; i < TIMEOUT_1 ;i++) - if ((read_sx_byte (board, offset) & mask) != badval) { - func_exit (); + for (i = 0; i < TIMEOUT_1; i++) + if ((read_sx_byte(board, offset) & mask) != badval) { + func_exit(); return 1; } - for (i=0; i < TIMEOUT_2 ;i++) { - if ((read_sx_byte (board, offset) & mask) != badval) { - func_exit (); + for (i = 0; i < TIMEOUT_2; i++) { + if ((read_sx_byte(board, offset) & mask) != badval) { + func_exit(); return 1; } - udelay (1); + udelay(1); } - func_exit (); + func_exit(); return 0; } - - /* 5.6.4 of 6210028 r2.3 */ -static int sx_reset (struct sx_board *board) +static int sx_reset(struct sx_board *board) { - func_enter (); + func_enter(); - if (IS_SX_BOARD (board)) { + if (IS_SX_BOARD(board)) { - write_sx_byte (board, SX_CONFIG, 0); - write_sx_byte (board, SX_RESET, 1); /* Value doesn't matter */ + write_sx_byte(board, SX_CONFIG, 0); + write_sx_byte(board, SX_RESET, 1); /* Value doesn't matter */ - if (!sx_busy_wait_eq (board, SX_RESET_STATUS, 1, 0)) { - printk (KERN_INFO "sx: Card doesn't respond to reset....\n"); + if (!sx_busy_wait_eq(board, SX_RESET_STATUS, 1, 0)) { + printk(KERN_INFO "sx: Card doesn't respond to " + "reset...\n"); return 0; } } else if (IS_EISA_BOARD(board)) { - outb(board->irq<<4, board->eisa_base+0xc02); + outb(board->irq << 4, board->eisa_base + 0xc02); } else if (IS_SI1_BOARD(board)) { - write_sx_byte (board, SI1_ISA_RESET, 0); // value does not matter + write_sx_byte(board, SI1_ISA_RESET, 0); /*value doesn't matter*/ } else { /* Gory details of the SI/ISA board */ - write_sx_byte (board, SI2_ISA_RESET, SI2_ISA_RESET_SET); - write_sx_byte (board, SI2_ISA_IRQ11, SI2_ISA_IRQ11_CLEAR); - write_sx_byte (board, SI2_ISA_IRQ12, SI2_ISA_IRQ12_CLEAR); - write_sx_byte (board, SI2_ISA_IRQ15, SI2_ISA_IRQ15_CLEAR); - write_sx_byte (board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_CLEAR); - write_sx_byte (board, SI2_ISA_IRQSET, SI2_ISA_IRQSET_CLEAR); + write_sx_byte(board, SI2_ISA_RESET, SI2_ISA_RESET_SET); + write_sx_byte(board, SI2_ISA_IRQ11, SI2_ISA_IRQ11_CLEAR); + write_sx_byte(board, SI2_ISA_IRQ12, SI2_ISA_IRQ12_CLEAR); + write_sx_byte(board, SI2_ISA_IRQ15, SI2_ISA_IRQ15_CLEAR); + write_sx_byte(board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_CLEAR); + write_sx_byte(board, SI2_ISA_IRQSET, SI2_ISA_IRQSET_CLEAR); } - func_exit (); + func_exit(); return 1; } - /* This doesn't work on machines where "NULL" isn't 0 */ /* If you have one of those, someone will need to write the equivalent of this, which will amount to about 3 lines. I don't want to complicate this right now. -- REW (See, I do write comments every now and then :-) */ -#define OFFSETOF(strct, elem) ((long)&(((struct strct *)NULL)->elem)) - - -#define CHAN_OFFSET(port,elem) (port->ch_base + OFFSETOF (_SXCHANNEL, elem)) -#define MODU_OFFSET(board,addr,elem) (addr + OFFSETOF (_SXMODULE, elem)) -#define BRD_OFFSET(board,elem) (OFFSETOF (_SXCARD, elem)) +#define OFFSETOF(strct, elem) ((long)&(((struct strct *)NULL)->elem)) +#define CHAN_OFFSET(port,elem) (port->ch_base + OFFSETOF (_SXCHANNEL, elem)) +#define MODU_OFFSET(board,addr,elem) (addr + OFFSETOF (_SXMODULE, elem)) +#define BRD_OFFSET(board,elem) (OFFSETOF (_SXCARD, elem)) #define sx_write_channel_byte(port, elem, val) \ - write_sx_byte (port->board, CHAN_OFFSET (port, elem), val) + write_sx_byte (port->board, CHAN_OFFSET (port, elem), val) #define sx_read_channel_byte(port, elem) \ - read_sx_byte (port->board, CHAN_OFFSET (port, elem)) + read_sx_byte (port->board, CHAN_OFFSET (port, elem)) #define sx_write_channel_word(port, elem, val) \ - write_sx_word (port->board, CHAN_OFFSET (port, elem), val) + write_sx_word (port->board, CHAN_OFFSET (port, elem), val) #define sx_read_channel_word(port, elem) \ - read_sx_word (port->board, CHAN_OFFSET (port, elem)) - + read_sx_word (port->board, CHAN_OFFSET (port, elem)) #define sx_write_module_byte(board, addr, elem, val) \ - write_sx_byte (board, MODU_OFFSET (board, addr, elem), val) + write_sx_byte (board, MODU_OFFSET (board, addr, elem), val) #define sx_read_module_byte(board, addr, elem) \ - read_sx_byte (board, MODU_OFFSET (board, addr, elem)) + read_sx_byte (board, MODU_OFFSET (board, addr, elem)) #define sx_write_module_word(board, addr, elem, val) \ - write_sx_word (board, MODU_OFFSET (board, addr, elem), val) + write_sx_word (board, MODU_OFFSET (board, addr, elem), val) #define sx_read_module_word(board, addr, elem) \ - read_sx_word (board, MODU_OFFSET (board, addr, elem)) - + read_sx_word (board, MODU_OFFSET (board, addr, elem)) #define sx_write_board_byte(board, elem, val) \ - write_sx_byte (board, BRD_OFFSET (board, elem), val) + write_sx_byte (board, BRD_OFFSET (board, elem), val) #define sx_read_board_byte(board, elem) \ - read_sx_byte (board, BRD_OFFSET (board, elem)) + read_sx_byte (board, BRD_OFFSET (board, elem)) #define sx_write_board_word(board, elem, val) \ - write_sx_word (board, BRD_OFFSET (board, elem), val) + write_sx_word (board, BRD_OFFSET (board, elem), val) #define sx_read_board_word(board, elem) \ - read_sx_word (board, BRD_OFFSET (board, elem)) - + read_sx_word (board, BRD_OFFSET (board, elem)) -static int sx_start_board (struct sx_board *board) +static int sx_start_board(struct sx_board *board) { - if (IS_SX_BOARD (board)) { - write_sx_byte (board, SX_CONFIG, SX_CONF_BUSEN); + if (IS_SX_BOARD(board)) { + write_sx_byte(board, SX_CONFIG, SX_CONF_BUSEN); } else if (IS_EISA_BOARD(board)) { write_sx_byte(board, SI2_EISA_OFF, SI2_EISA_VAL); - outb((board->irq<<4)|4, board->eisa_base+0xc02); + outb((board->irq << 4) | 4, board->eisa_base + 0xc02); } else if (IS_SI1_BOARD(board)) { - write_sx_byte (board, SI1_ISA_RESET_CLEAR, 0); - write_sx_byte (board, SI1_ISA_INTCL, 0); + write_sx_byte(board, SI1_ISA_RESET_CLEAR, 0); + write_sx_byte(board, SI1_ISA_INTCL, 0); } else { /* Don't bug me about the clear_set. I haven't the foggiest idea what it's about -- REW */ - write_sx_byte (board, SI2_ISA_RESET, SI2_ISA_RESET_CLEAR); - write_sx_byte (board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_SET); + write_sx_byte(board, SI2_ISA_RESET, SI2_ISA_RESET_CLEAR); + write_sx_byte(board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_SET); } return 1; } #define SX_IRQ_REG_VAL(board) \ - ((board->flags & SX_ISA_BOARD)?(board->irq << 4):0) + ((board->flags & SX_ISA_BOARD) ? (board->irq << 4) : 0) /* Note. The SX register is write-only. Therefore, we have to enable the bus too. This is a no-op, if you don't mess with this driver... */ -static int sx_start_interrupts (struct sx_board *board) +static int sx_start_interrupts(struct sx_board *board) { /* Don't call this with board->irq == 0 */ if (IS_SX_BOARD(board)) { - write_sx_byte (board, SX_CONFIG, SX_IRQ_REG_VAL (board) | - SX_CONF_BUSEN | - SX_CONF_HOSTIRQ); + write_sx_byte(board, SX_CONFIG, SX_IRQ_REG_VAL(board) | + SX_CONF_BUSEN | SX_CONF_HOSTIRQ); } else if (IS_EISA_BOARD(board)) { - inb(board->eisa_base+0xc03); + inb(board->eisa_base + 0xc03); } else if (IS_SI1_BOARD(board)) { - write_sx_byte (board, SI1_ISA_INTCL,0); - write_sx_byte (board, SI1_ISA_INTCL_CLEAR,0); + write_sx_byte(board, SI1_ISA_INTCL, 0); + write_sx_byte(board, SI1_ISA_INTCL_CLEAR, 0); } else { switch (board->irq) { - case 11:write_sx_byte (board, SI2_ISA_IRQ11, SI2_ISA_IRQ11_SET);break; - case 12:write_sx_byte (board, SI2_ISA_IRQ12, SI2_ISA_IRQ12_SET);break; - case 15:write_sx_byte (board, SI2_ISA_IRQ15, SI2_ISA_IRQ15_SET);break; - default:printk (KERN_INFO "sx: SI/XIO card doesn't support interrupt %d.\n", - board->irq); - return 0; + case 11: + write_sx_byte(board, SI2_ISA_IRQ11, SI2_ISA_IRQ11_SET); + break; + case 12: + write_sx_byte(board, SI2_ISA_IRQ12, SI2_ISA_IRQ12_SET); + break; + case 15: + write_sx_byte(board, SI2_ISA_IRQ15, SI2_ISA_IRQ15_SET); + break; + default: + printk(KERN_INFO "sx: SI/XIO card doesn't support " + "interrupt %d.\n", board->irq); + return 0; } - write_sx_byte (board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_SET); + write_sx_byte(board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_SET); } return 1; } - -static int sx_send_command (struct sx_port *port, - int command, int mask, int newstat) +static int sx_send_command(struct sx_port *port, + int command, int mask, int newstat) { - func_enter2 (); - write_sx_byte (port->board, CHAN_OFFSET (port, hi_hstat), command); - func_exit (); - return sx_busy_wait_eq (port->board, CHAN_OFFSET (port, hi_hstat), mask, newstat); + func_enter2(); + write_sx_byte(port->board, CHAN_OFFSET(port, hi_hstat), command); + func_exit(); + return sx_busy_wait_eq(port->board, CHAN_OFFSET(port, hi_hstat), mask, + newstat); } - -static char *mod_type_s (int module_type) +static char *mod_type_s(int module_type) { switch (module_type) { - case TA4: return "TA4"; - case TA8: return "TA8"; - case TA4_ASIC: return "TA4_ASIC"; - case TA8_ASIC: return "TA8_ASIC"; - case MTA_CD1400:return "MTA_CD1400"; - case SXDC: return "SXDC"; - default:return "Unknown/invalid"; + case TA4: + return "TA4"; + case TA8: + return "TA8"; + case TA4_ASIC: + return "TA4_ASIC"; + case TA8_ASIC: + return "TA8_ASIC"; + case MTA_CD1400: + return "MTA_CD1400"; + case SXDC: + return "SXDC"; + default: + return "Unknown/invalid"; } } - -static char *pan_type_s (int pan_type) +static char *pan_type_s(int pan_type) { switch (pan_type) { - case MOD_RS232DB25: return "MOD_RS232DB25"; - case MOD_RS232RJ45: return "MOD_RS232RJ45"; - case MOD_RS422DB25: return "MOD_RS422DB25"; - case MOD_PARALLEL: return "MOD_PARALLEL"; - case MOD_2_RS232DB25: return "MOD_2_RS232DB25"; - case MOD_2_RS232RJ45: return "MOD_2_RS232RJ45"; - case MOD_2_RS422DB25: return "MOD_2_RS422DB25"; - case MOD_RS232DB25MALE: return "MOD_RS232DB25MALE"; - case MOD_2_PARALLEL: return "MOD_2_PARALLEL"; - case MOD_BLANK: return "empty"; - default:return "invalid"; + case MOD_RS232DB25: + return "MOD_RS232DB25"; + case MOD_RS232RJ45: + return "MOD_RS232RJ45"; + case MOD_RS422DB25: + return "MOD_RS422DB25"; + case MOD_PARALLEL: + return "MOD_PARALLEL"; + case MOD_2_RS232DB25: + return "MOD_2_RS232DB25"; + case MOD_2_RS232RJ45: + return "MOD_2_RS232RJ45"; + case MOD_2_RS422DB25: + return "MOD_2_RS422DB25"; + case MOD_RS232DB25MALE: + return "MOD_RS232DB25MALE"; + case MOD_2_PARALLEL: + return "MOD_2_PARALLEL"; + case MOD_BLANK: + return "empty"; + default: + return "invalid"; } } - -static int mod_compat_type (int module_type) +static int mod_compat_type(int module_type) { return module_type >> 4; } static void sx_reconfigure_port(struct sx_port *port) { - if (sx_read_channel_byte (port, hi_hstat) == HS_IDLE_OPEN) { - if (sx_send_command (port, HS_CONFIG, -1, HS_IDLE_OPEN) != 1) { - printk (KERN_WARNING "sx: Sent reconfigure command, but card didn't react.\n"); + if (sx_read_channel_byte(port, hi_hstat) == HS_IDLE_OPEN) { + if (sx_send_command(port, HS_CONFIG, -1, HS_IDLE_OPEN) != 1) { + printk(KERN_WARNING "sx: Sent reconfigure command, but " + "card didn't react.\n"); } } else { - sx_dprintk (SX_DEBUG_TERMIOS, - "sx: Not sending reconfigure: port isn't open (%02x).\n", - sx_read_channel_byte (port, hi_hstat)); - } + sx_dprintk(SX_DEBUG_TERMIOS, "sx: Not sending reconfigure: " + "port isn't open (%02x).\n", + sx_read_channel_byte(port, hi_hstat)); + } } -static void sx_setsignals (struct sx_port *port, int dtr, int rts) +static void sx_setsignals(struct sx_port *port, int dtr, int rts) { int t; - func_enter2 (); + func_enter2(); - t = sx_read_channel_byte (port, hi_op); - if (dtr >= 0) t = dtr? (t | OP_DTR): (t & ~OP_DTR); - if (rts >= 0) t = rts? (t | OP_RTS): (t & ~OP_RTS); - sx_write_channel_byte (port, hi_op, t); - sx_dprintk (SX_DEBUG_MODEMSIGNALS, "setsignals: %d/%d\n", dtr, rts); + t = sx_read_channel_byte(port, hi_op); + if (dtr >= 0) + t = dtr ? (t | OP_DTR) : (t & ~OP_DTR); + if (rts >= 0) + t = rts ? (t | OP_RTS) : (t & ~OP_RTS); + sx_write_channel_byte(port, hi_op, t); + sx_dprintk(SX_DEBUG_MODEMSIGNALS, "setsignals: %d/%d\n", dtr, rts); - func_exit (); + func_exit(); } - - -static int sx_getsignals (struct sx_port *port) +static int sx_getsignals(struct sx_port *port) { - int i_stat,o_stat; - - o_stat = sx_read_channel_byte (port, hi_op); - i_stat = sx_read_channel_byte (port, hi_ip); - - sx_dprintk (SX_DEBUG_MODEMSIGNALS, "getsignals: %d/%d (%d/%d) %02x/%02x\n", - (o_stat & OP_DTR) != 0, (o_stat & OP_RTS) != 0, - port->c_dcd, sx_get_CD (port), - sx_read_channel_byte (port, hi_ip), - sx_read_channel_byte (port, hi_state)); - - return (((o_stat & OP_DTR)?TIOCM_DTR:0) | - ((o_stat & OP_RTS)?TIOCM_RTS:0) | - ((i_stat & IP_CTS)?TIOCM_CTS:0) | - ((i_stat & IP_DCD)?TIOCM_CAR:0) | - ((i_stat & IP_DSR)?TIOCM_DSR:0) | - ((i_stat & IP_RI)?TIOCM_RNG:0) - ); + int i_stat, o_stat; + + o_stat = sx_read_channel_byte(port, hi_op); + i_stat = sx_read_channel_byte(port, hi_ip); + + sx_dprintk(SX_DEBUG_MODEMSIGNALS, "getsignals: %d/%d (%d/%d) " + "%02x/%02x\n", + (o_stat & OP_DTR) != 0, (o_stat & OP_RTS) != 0, + port->c_dcd, sx_get_CD(port), + sx_read_channel_byte(port, hi_ip), + sx_read_channel_byte(port, hi_state)); + + return (((o_stat & OP_DTR) ? TIOCM_DTR : 0) | + ((o_stat & OP_RTS) ? TIOCM_RTS : 0) | + ((i_stat & IP_CTS) ? TIOCM_CTS : 0) | + ((i_stat & IP_DCD) ? TIOCM_CAR : 0) | + ((i_stat & IP_DSR) ? TIOCM_DSR : 0) | + ((i_stat & IP_RI) ? TIOCM_RNG : 0)); } - -static void sx_set_baud (struct sx_port *port) +static void sx_set_baud(struct sx_port *port) { int t; if (port->board->ta_type == MOD_SXDC) { switch (port->gs.baud) { - /* Save some typing work... */ -#define e(x) case x:t= BAUD_ ## x ; break - e(50);e(75);e(110);e(150);e(200);e(300);e(600); - e(1200);e(1800);e(2000);e(2400);e(4800);e(7200); - e(9600);e(14400);e(19200);e(28800);e(38400); - e(56000);e(57600);e(64000);e(76800);e(115200); - e(128000);e(150000);e(230400);e(256000);e(460800); - e(921600); - case 134 :t = BAUD_134_5; break; - case 0 :t = -1; - break; + /* Save some typing work... */ +#define e(x) case x: t = BAUD_ ## x; break + e(50); + e(75); + e(110); + e(150); + e(200); + e(300); + e(600); + e(1200); + e(1800); + e(2000); + e(2400); + e(4800); + e(7200); + e(9600); + e(14400); + e(19200); + e(28800); + e(38400); + e(56000); + e(57600); + e(64000); + e(76800); + e(115200); + e(128000); + e(150000); + e(230400); + e(256000); + e(460800); + e(921600); + case 134: + t = BAUD_134_5; + break; + case 0: + t = -1; + break; default: /* Can I return "invalid"? */ t = BAUD_9600; - printk (KERN_INFO "sx: unsupported baud rate: %d.\n", port->gs.baud); + printk(KERN_INFO "sx: unsupported baud rate: %d.\n", + port->gs.baud); break; } #undef e if (t > 0) { - /* The baud rate is not set to 0, so we're enabeling DTR... -- REW */ - sx_setsignals (port, 1, -1); +/* The baud rate is not set to 0, so we're enabeling DTR... -- REW */ + sx_setsignals(port, 1, -1); /* XXX This is not TA & MTA compatible */ - sx_write_channel_byte (port, hi_csr, 0xff); + sx_write_channel_byte(port, hi_csr, 0xff); - sx_write_channel_byte (port, hi_txbaud, t); - sx_write_channel_byte (port, hi_rxbaud, t); + sx_write_channel_byte(port, hi_txbaud, t); + sx_write_channel_byte(port, hi_rxbaud, t); } else { - sx_setsignals (port, 0, -1); + sx_setsignals(port, 0, -1); } } else { switch (port->gs.baud) { -#define e(x) case x:t= CSR_ ## x ; break - e(75);e(150);e(300);e(600);e(1200);e(2400);e(4800); - e(1800);e(9600); - e(19200);e(57600);e(38400); - /* TA supports 110, but not 115200, MTA supports 115200, but not 110 */ - case 110: +#define e(x) case x: t = CSR_ ## x; break + e(75); + e(150); + e(300); + e(600); + e(1200); + e(2400); + e(4800); + e(1800); + e(9600); + e(19200); + e(57600); + e(38400); +/* TA supports 110, but not 115200, MTA supports 115200, but not 110 */ + case 110: if (port->board->ta_type == MOD_TA) { t = CSR_110; break; } else { t = CSR_9600; - printk (KERN_INFO "sx: Unsupported baud rate: %d.\n", port->gs.baud); + printk(KERN_INFO "sx: Unsupported baud rate: " + "%d.\n", port->gs.baud); break; } - case 115200: + case 115200: if (port->board->ta_type == MOD_TA) { t = CSR_9600; - printk (KERN_INFO "sx: Unsupported baud rate: %d.\n", port->gs.baud); + printk(KERN_INFO "sx: Unsupported baud rate: " + "%d.\n", port->gs.baud); break; } else { t = CSR_110; break; } - case 0 :t = -1; - break; + case 0: + t = -1; + break; default: t = CSR_9600; - printk (KERN_INFO "sx: Unsupported baud rate: %d.\n", port->gs.baud); + printk(KERN_INFO "sx: Unsupported baud rate: %d.\n", + port->gs.baud); break; } #undef e if (t >= 0) { - sx_setsignals (port, 1, -1); - sx_write_channel_byte (port, hi_csr, t * 0x11); + sx_setsignals(port, 1, -1); + sx_write_channel_byte(port, hi_csr, t * 0x11); } else { - sx_setsignals (port, 0, -1); + sx_setsignals(port, 0, -1); } } } - /* Simon Allen's version of this routine was 225 lines long. 85 is a lot better. -- REW */ -static int sx_set_real_termios (void *ptr) +static int sx_set_real_termios(void *ptr) { struct sx_port *port = ptr; @@ -907,80 +939,83 @@ static int sx_set_real_termios (void *ptr) belongs (next to the drop dtr if baud == 0) -- REW */ /* sx_setsignals (port, 1, -1); */ - sx_set_baud (port); + sx_set_baud(port); #define CFLAG port->gs.tty->termios->c_cflag - sx_write_channel_byte (port, hi_mr1, - (C_PARENB (port->gs.tty)? MR1_WITH:MR1_NONE) | - (C_PARODD (port->gs.tty)? MR1_ODD:MR1_EVEN) | - (C_CRTSCTS(port->gs.tty)? MR1_RTS_RXFLOW:0) | - (((CFLAG & CSIZE)==CS8) ? MR1_8_BITS:0) | - (((CFLAG & CSIZE)==CS7) ? MR1_7_BITS:0) | - (((CFLAG & CSIZE)==CS6) ? MR1_6_BITS:0) | - (((CFLAG & CSIZE)==CS5) ? MR1_5_BITS:0) ); - - sx_write_channel_byte (port, hi_mr2, - (C_CRTSCTS(port->gs.tty)?MR2_CTS_TXFLOW:0) | - (C_CSTOPB (port->gs.tty)?MR2_2_STOP:MR2_1_STOP)); + sx_write_channel_byte(port, hi_mr1, + (C_PARENB(port->gs.tty) ? MR1_WITH : MR1_NONE) | + (C_PARODD(port->gs.tty) ? MR1_ODD : MR1_EVEN) | + (C_CRTSCTS(port->gs.tty) ? MR1_RTS_RXFLOW : 0) | + (((CFLAG & CSIZE) == CS8) ? MR1_8_BITS : 0) | + (((CFLAG & CSIZE) == CS7) ? MR1_7_BITS : 0) | + (((CFLAG & CSIZE) == CS6) ? MR1_6_BITS : 0) | + (((CFLAG & CSIZE) == CS5) ? MR1_5_BITS : 0)); + + sx_write_channel_byte(port, hi_mr2, + (C_CRTSCTS(port->gs.tty) ? MR2_CTS_TXFLOW : 0) | + (C_CSTOPB(port->gs.tty) ? MR2_2_STOP : + MR2_1_STOP)); switch (CFLAG & CSIZE) { - case CS8:sx_write_channel_byte (port, hi_mask, 0xff);break; - case CS7:sx_write_channel_byte (port, hi_mask, 0x7f);break; - case CS6:sx_write_channel_byte (port, hi_mask, 0x3f);break; - case CS5:sx_write_channel_byte (port, hi_mask, 0x1f);break; + case CS8: + sx_write_channel_byte(port, hi_mask, 0xff); + break; + case CS7: + sx_write_channel_byte(port, hi_mask, 0x7f); + break; + case CS6: + sx_write_channel_byte(port, hi_mask, 0x3f); + break; + case CS5: + sx_write_channel_byte(port, hi_mask, 0x1f); + break; default: - printk (KERN_INFO "sx: Invalid wordsize: %u\n", CFLAG & CSIZE); + printk(KERN_INFO "sx: Invalid wordsize: %u\n", CFLAG & CSIZE); break; } - sx_write_channel_byte (port, hi_prtcl, - (I_IXON (port->gs.tty)?SP_TXEN:0) | - (I_IXOFF (port->gs.tty)?SP_RXEN:0) | - (I_IXANY (port->gs.tty)?SP_TANY:0) | - SP_DCEN); + sx_write_channel_byte(port, hi_prtcl, + (I_IXON(port->gs.tty) ? SP_TXEN : 0) | + (I_IXOFF(port->gs.tty) ? SP_RXEN : 0) | + (I_IXANY(port->gs.tty) ? SP_TANY : 0) | SP_DCEN); - sx_write_channel_byte (port, hi_break, - (I_IGNBRK(port->gs.tty)?BR_IGN:0 | - I_BRKINT(port->gs.tty)?BR_INT:0)); + sx_write_channel_byte(port, hi_break, + (I_IGNBRK(port->gs.tty) ? BR_IGN : 0 | + I_BRKINT(port->gs.tty) ? BR_INT : 0)); - sx_write_channel_byte (port, hi_txon, START_CHAR (port->gs.tty)); - sx_write_channel_byte (port, hi_rxon, START_CHAR (port->gs.tty)); - sx_write_channel_byte (port, hi_txoff, STOP_CHAR (port->gs.tty)); - sx_write_channel_byte (port, hi_rxoff, STOP_CHAR (port->gs.tty)); + sx_write_channel_byte(port, hi_txon, START_CHAR(port->gs.tty)); + sx_write_channel_byte(port, hi_rxon, START_CHAR(port->gs.tty)); + sx_write_channel_byte(port, hi_txoff, STOP_CHAR(port->gs.tty)); + sx_write_channel_byte(port, hi_rxoff, STOP_CHAR(port->gs.tty)); sx_reconfigure_port(port); /* Tell line discipline whether we will do input cooking */ - if(I_OTHER(port->gs.tty)) { + if (I_OTHER(port->gs.tty)) { clear_bit(TTY_HW_COOK_IN, &port->gs.tty->flags); } else { set_bit(TTY_HW_COOK_IN, &port->gs.tty->flags); } - sx_dprintk (SX_DEBUG_TERMIOS, "iflags: %x(%d) ", - port->gs.tty->termios->c_iflag, - I_OTHER(port->gs.tty)); - + sx_dprintk(SX_DEBUG_TERMIOS, "iflags: %x(%d) ", + port->gs.tty->termios->c_iflag, I_OTHER(port->gs.tty)); /* Tell line discipline whether we will do output cooking. * If OPOST is set and no other output flags are set then we can do output * processing. Even if only *one* other flag in the O_OTHER group is set * we do cooking in software. */ - if(O_OPOST(port->gs.tty) && !O_OTHER(port->gs.tty)) { + if (O_OPOST(port->gs.tty) && !O_OTHER(port->gs.tty)) { set_bit(TTY_HW_COOK_OUT, &port->gs.tty->flags); } else { clear_bit(TTY_HW_COOK_OUT, &port->gs.tty->flags); } - sx_dprintk (SX_DEBUG_TERMIOS, "oflags: %x(%d)\n", - port->gs.tty->termios->c_oflag, - O_OTHER(port->gs.tty)); + sx_dprintk(SX_DEBUG_TERMIOS, "oflags: %x(%d)\n", + port->gs.tty->termios->c_oflag, O_OTHER(port->gs.tty)); /* port->c_dcd = sx_get_CD (port); */ - func_exit (); + func_exit(); return 0; } - - /* ********************************************************************** * * the interrupt related routines * * ********************************************************************** */ @@ -996,245 +1031,260 @@ static int sx_set_real_termios (void *ptr) know I'm dead against that, but I think it is required in this case. */ - -static void sx_transmit_chars (struct sx_port *port) +static void sx_transmit_chars(struct sx_port *port) { int c; int tx_ip; int txroom; - func_enter2 (); - sx_dprintk (SX_DEBUG_TRANSMIT, "Port %p: transmit %d chars\n", - port, port->gs.xmit_cnt); + func_enter2(); + sx_dprintk(SX_DEBUG_TRANSMIT, "Port %p: transmit %d chars\n", + port, port->gs.xmit_cnt); - if (test_and_set_bit (SX_PORT_TRANSMIT_LOCK, &port->locks)) { + if (test_and_set_bit(SX_PORT_TRANSMIT_LOCK, &port->locks)) { return; } while (1) { c = port->gs.xmit_cnt; - sx_dprintk (SX_DEBUG_TRANSMIT, "Copying %d ", c); - tx_ip = sx_read_channel_byte (port, hi_txipos); + sx_dprintk(SX_DEBUG_TRANSMIT, "Copying %d ", c); + tx_ip = sx_read_channel_byte(port, hi_txipos); /* Took me 5 minutes to deduce this formula. Luckily it is literally in the manual in section 6.5.4.3.5 */ - txroom = (sx_read_channel_byte (port, hi_txopos) - tx_ip - 1) & 0xff; + txroom = (sx_read_channel_byte(port, hi_txopos) - tx_ip - 1) & + 0xff; /* Don't copy more bytes than there is room for in the buffer */ if (c > txroom) c = txroom; - sx_dprintk (SX_DEBUG_TRANSMIT, " %d(%d) ", c, txroom ); + sx_dprintk(SX_DEBUG_TRANSMIT, " %d(%d) ", c, txroom); /* Don't copy past the end of the hardware transmit buffer */ - if (c > 0x100 - tx_ip) + if (c > 0x100 - tx_ip) c = 0x100 - tx_ip; - sx_dprintk (SX_DEBUG_TRANSMIT, " %d(%d) ", c, 0x100-tx_ip ); + sx_dprintk(SX_DEBUG_TRANSMIT, " %d(%d) ", c, 0x100 - tx_ip); /* Don't copy pas the end of the source buffer */ - if (c > SERIAL_XMIT_SIZE - port->gs.xmit_tail) + if (c > SERIAL_XMIT_SIZE - port->gs.xmit_tail) c = SERIAL_XMIT_SIZE - port->gs.xmit_tail; - sx_dprintk (SX_DEBUG_TRANSMIT, " %d(%ld) \n", - c, SERIAL_XMIT_SIZE- port->gs.xmit_tail); - - /* If for one reason or another, we can't copy more data, we're done! */ - if (c == 0) break; + sx_dprintk(SX_DEBUG_TRANSMIT, " %d(%ld) \n", + c, SERIAL_XMIT_SIZE - port->gs.xmit_tail); + /* If for one reason or another, we can't copy more data, we're + done! */ + if (c == 0) + break; - memcpy_toio (port->board->base + CHAN_OFFSET(port,hi_txbuf) + tx_ip, - port->gs.xmit_buf + port->gs.xmit_tail, c); + memcpy_toio(port->board->base + CHAN_OFFSET(port, hi_txbuf) + + tx_ip, port->gs.xmit_buf + port->gs.xmit_tail, c); /* Update the pointer in the card */ - sx_write_channel_byte (port, hi_txipos, (tx_ip+c) & 0xff); + sx_write_channel_byte(port, hi_txipos, (tx_ip + c) & 0xff); /* Update the kernel buffer end */ - port->gs.xmit_tail = (port->gs.xmit_tail + c) & (SERIAL_XMIT_SIZE-1); + port->gs.xmit_tail = (port->gs.xmit_tail + c) & + (SERIAL_XMIT_SIZE - 1); /* This one last. (this is essential) - It would allow others to start putting more data into the buffer! */ + It would allow others to start putting more data into the + buffer! */ port->gs.xmit_cnt -= c; } if (port->gs.xmit_cnt == 0) { - sx_disable_tx_interrupts (port); + sx_disable_tx_interrupts(port); } if ((port->gs.xmit_cnt <= port->gs.wakeup_chars) && port->gs.tty) { tty_wakeup(port->gs.tty); - sx_dprintk (SX_DEBUG_TRANSMIT, "Waking up.... ldisc (%d)....\n", - port->gs.wakeup_chars); + sx_dprintk(SX_DEBUG_TRANSMIT, "Waking up.... ldisc (%d)....\n", + port->gs.wakeup_chars); } - clear_bit (SX_PORT_TRANSMIT_LOCK, &port->locks); - func_exit (); + clear_bit(SX_PORT_TRANSMIT_LOCK, &port->locks); + func_exit(); } - /* Note the symmetry between receiving chars and transmitting them! Note: The kernel should have implemented both a receive buffer and a transmit buffer. */ /* Inlined: Called only once. Remove the inline when you add another call */ -static inline void sx_receive_chars (struct sx_port *port) +static inline void sx_receive_chars(struct sx_port *port) { int c; int rx_op; struct tty_struct *tty; - int copied=0; + int copied = 0; unsigned char *rp; - func_enter2 (); + func_enter2(); tty = port->gs.tty; while (1) { - rx_op = sx_read_channel_byte (port, hi_rxopos); - c = (sx_read_channel_byte (port, hi_rxipos) - rx_op) & 0xff; + rx_op = sx_read_channel_byte(port, hi_rxopos); + c = (sx_read_channel_byte(port, hi_rxipos) - rx_op) & 0xff; - sx_dprintk (SX_DEBUG_RECEIVE, "rxop=%d, c = %d.\n", rx_op, c); + sx_dprintk(SX_DEBUG_RECEIVE, "rxop=%d, c = %d.\n", rx_op, c); /* Don't copy past the end of the hardware receive buffer */ - if (rx_op + c > 0x100) c = 0x100 - rx_op; + if (rx_op + c > 0x100) + c = 0x100 - rx_op; - sx_dprintk (SX_DEBUG_RECEIVE, "c = %d.\n", c); + sx_dprintk(SX_DEBUG_RECEIVE, "c = %d.\n", c); /* Don't copy more bytes than there is room for in the buffer */ c = tty_prepare_flip_string(tty, &rp, c); - sx_dprintk (SX_DEBUG_RECEIVE, "c = %d.\n", c); + sx_dprintk(SX_DEBUG_RECEIVE, "c = %d.\n", c); /* If for one reason or another, we can't copy more data, we're done! */ - if (c == 0) break; + if (c == 0) + break; - sx_dprintk (SX_DEBUG_RECEIVE , "Copying over %d chars. First is %d at %lx\n", c, - read_sx_byte (port->board, CHAN_OFFSET(port,hi_rxbuf) + rx_op), - CHAN_OFFSET(port, hi_rxbuf)); - memcpy_fromio (rp, - port->board->base + CHAN_OFFSET(port,hi_rxbuf) + rx_op, c); + sx_dprintk(SX_DEBUG_RECEIVE, "Copying over %d chars. First is " + "%d at %lx\n", c, read_sx_byte(port->board, + CHAN_OFFSET(port, hi_rxbuf) + rx_op), + CHAN_OFFSET(port, hi_rxbuf)); + memcpy_fromio(rp, port->board->base + + CHAN_OFFSET(port, hi_rxbuf) + rx_op, c); /* This one last. ( Not essential.) - It allows the card to start putting more data into the buffer! + It allows the card to start putting more data into the + buffer! Update the pointer in the card */ - sx_write_channel_byte (port, hi_rxopos, (rx_op + c) & 0xff); + sx_write_channel_byte(port, hi_rxopos, (rx_op + c) & 0xff); copied += c; } if (copied) { struct timeval tv; - do_gettimeofday (&tv); - sx_dprintk (SX_DEBUG_RECEIVE, - "pushing flipq port %d (%3d chars): %d.%06d (%d/%d)\n", - port->line, copied, - (int) (tv.tv_sec % 60), (int)tv.tv_usec, tty->raw, tty->real_raw); + do_gettimeofday(&tv); + sx_dprintk(SX_DEBUG_RECEIVE, "pushing flipq port %d (%3d " + "chars): %d.%06d (%d/%d)\n", port->line, + copied, (int)(tv.tv_sec % 60), (int)tv.tv_usec, + tty->raw, tty->real_raw); - /* Tell the rest of the system the news. Great news. New characters! */ - tty_flip_buffer_push (tty); + /* Tell the rest of the system the news. Great news. New + characters! */ + tty_flip_buffer_push(tty); /* tty_schedule_flip (tty); */ } - func_exit (); + func_exit(); } /* Inlined: it is called only once. Remove the inline if you add another call */ -static inline void sx_check_modem_signals (struct sx_port *port) +static inline void sx_check_modem_signals(struct sx_port *port) { int hi_state; int c_dcd; - hi_state = sx_read_channel_byte (port, hi_state); - sx_dprintk (SX_DEBUG_MODEMSIGNALS, "Checking modem signals (%d/%d)\n", - port->c_dcd, sx_get_CD (port)); + hi_state = sx_read_channel_byte(port, hi_state); + sx_dprintk(SX_DEBUG_MODEMSIGNALS, "Checking modem signals (%d/%d)\n", + port->c_dcd, sx_get_CD(port)); if (hi_state & ST_BREAK) { hi_state &= ~ST_BREAK; - sx_dprintk (SX_DEBUG_MODEMSIGNALS, "got a break.\n"); - sx_write_channel_byte (port, hi_state, hi_state); - gs_got_break (&port->gs); + sx_dprintk(SX_DEBUG_MODEMSIGNALS, "got a break.\n"); + sx_write_channel_byte(port, hi_state, hi_state); + gs_got_break(&port->gs); } if (hi_state & ST_DCD) { hi_state &= ~ST_DCD; - sx_dprintk (SX_DEBUG_MODEMSIGNALS, "got a DCD change.\n"); - sx_write_channel_byte (port, hi_state, hi_state); - c_dcd = sx_get_CD (port); - sx_dprintk (SX_DEBUG_MODEMSIGNALS, "DCD is now %d\n", c_dcd); + sx_dprintk(SX_DEBUG_MODEMSIGNALS, "got a DCD change.\n"); + sx_write_channel_byte(port, hi_state, hi_state); + c_dcd = sx_get_CD(port); + sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD is now %d\n", c_dcd); if (c_dcd != port->c_dcd) { port->c_dcd = c_dcd; - if (sx_get_CD (port)) { + if (sx_get_CD(port)) { /* DCD went UP */ - if ((sx_read_channel_byte(port, hi_hstat) != HS_IDLE_CLOSED) && - !(port->gs.tty->termios->c_cflag & CLOCAL) ) { - /* Are we blocking in open?*/ - sx_dprintk (SX_DEBUG_MODEMSIGNALS, "DCD active, unblocking open\n"); - wake_up_interruptible(&port->gs.open_wait); + if ((sx_read_channel_byte(port, hi_hstat) != + HS_IDLE_CLOSED) && + !(port->gs.tty->termios-> + c_cflag & CLOCAL)) { + /* Are we blocking in open? */ + sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD " + "active, unblocking open\n"); + wake_up_interruptible(&port->gs. + open_wait); } else { - sx_dprintk (SX_DEBUG_MODEMSIGNALS, "DCD raised. Ignoring.\n"); + sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD " + "raised. Ignoring.\n"); } } else { /* DCD went down! */ - if (!(port->gs.tty->termios->c_cflag & CLOCAL) ) { - sx_dprintk (SX_DEBUG_MODEMSIGNALS, "DCD dropped. hanging up....\n"); - tty_hangup (port->gs.tty); + if (!(port->gs.tty->termios->c_cflag & CLOCAL)){ + sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD " + "dropped. hanging up....\n"); + tty_hangup(port->gs.tty); } else { - sx_dprintk (SX_DEBUG_MODEMSIGNALS, "DCD dropped. ignoring.\n"); + sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD " + "dropped. ignoring.\n"); } } } else { - sx_dprintk (SX_DEBUG_MODEMSIGNALS, "Hmmm. card told us DCD changed, but it didn't.\n"); + sx_dprintk(SX_DEBUG_MODEMSIGNALS, "Hmmm. card told us " + "DCD changed, but it didn't.\n"); } } } - /* This is what an interrupt routine should look like. * Small, elegant, clear. */ -static irqreturn_t sx_interrupt (int irq, void *ptr) +static irqreturn_t sx_interrupt(int irq, void *ptr) { struct sx_board *board = ptr; struct sx_port *port; int i; - func_enter (); - sx_dprintk (SX_DEBUG_FLOW, "sx: enter sx_interrupt (%d/%d)\n", irq, board->irq); + func_enter(); + sx_dprintk(SX_DEBUG_FLOW, "sx: enter sx_interrupt (%d/%d)\n", irq, + board->irq); /* AAargh! The order in which to do these things is essential and not trivial. - Rate limit goes before "recursive". Otherwise a series of - recursive calls will hang the machine in the interrupt routine. + recursive calls will hang the machine in the interrupt routine. - hardware twiddling goes before "recursive". Otherwise when we - poll the card, and a recursive interrupt happens, we won't - ack the card, so it might keep on interrupting us. (especially - level sensitive interrupt systems like PCI). + poll the card, and a recursive interrupt happens, we won't + ack the card, so it might keep on interrupting us. (especially + level sensitive interrupt systems like PCI). - Rate limit goes before hardware twiddling. Otherwise we won't - catch a card that has gone bonkers. + catch a card that has gone bonkers. - The "initialized" test goes after the hardware twiddling. Otherwise - the card will stick us in the interrupt routine again. + the card will stick us in the interrupt routine again. - The initialized test goes before recursive. - */ - - + */ #ifdef IRQ_RATE_LIMIT /* Aaargh! I'm ashamed. This costs more lines-of-code than the - actual interrupt routine!. (Well, used to when I wrote that comment) */ + actual interrupt routine!. (Well, used to when I wrote that + comment) */ { static int lastjif; - static int nintr=0; + static int nintr = 0; if (lastjif == jiffies) { if (++nintr > IRQ_RATE_LIMIT) { - free_irq (board->irq, board); - printk (KERN_ERR "sx: Too many interrupts. Turning off interrupt %d.\n", - board->irq); + free_irq(board->irq, board); + printk(KERN_ERR "sx: Too many interrupts. " + "Turning off interrupt %d.\n", + board->irq); } } else { lastjif = jiffies; @@ -1243,19 +1293,20 @@ static irqreturn_t sx_interrupt (int irq, void *ptr) } #endif - if (board->irq == irq) { /* Tell the card we've noticed the interrupt. */ - sx_write_board_word (board, cc_int_pending, 0); - if (IS_SX_BOARD (board)) { - write_sx_byte (board, SX_RESET_IRQ, 1); + sx_write_board_word(board, cc_int_pending, 0); + if (IS_SX_BOARD(board)) { + write_sx_byte(board, SX_RESET_IRQ, 1); } else if (IS_EISA_BOARD(board)) { - inb(board->eisa_base+0xc03); - write_sx_word(board, 8, 0); + inb(board->eisa_base + 0xc03); + write_sx_word(board, 8, 0); } else { - write_sx_byte (board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_CLEAR); - write_sx_byte (board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_SET); + write_sx_byte(board, SI2_ISA_INTCLEAR, + SI2_ISA_INTCLEAR_CLEAR); + write_sx_byte(board, SI2_ISA_INTCLEAR, + SI2_ISA_INTCLEAR_SET); } } @@ -1264,53 +1315,48 @@ static irqreturn_t sx_interrupt (int irq, void *ptr) if (!(board->flags & SX_BOARD_INITIALIZED)) return IRQ_HANDLED; - if (test_and_set_bit (SX_BOARD_INTR_LOCK, &board->locks)) { - printk (KERN_ERR "Recursive interrupt! (%d)\n", board->irq); + if (test_and_set_bit(SX_BOARD_INTR_LOCK, &board->locks)) { + printk(KERN_ERR "Recursive interrupt! (%d)\n", board->irq); return IRQ_HANDLED; } - for (i=0;inports;i++) { + for (i = 0; i < board->nports; i++) { port = &board->ports[i]; if (port->gs.flags & GS_ACTIVE) { - if (sx_read_channel_byte (port, hi_state)) { - sx_dprintk (SX_DEBUG_INTERRUPTS, - "Port %d: modem signal change?... \n", i); - sx_check_modem_signals (port); + if (sx_read_channel_byte(port, hi_state)) { + sx_dprintk(SX_DEBUG_INTERRUPTS, "Port %d: " + "modem signal change?... \n",i); + sx_check_modem_signals(port); } if (port->gs.xmit_cnt) { - sx_transmit_chars (port); + sx_transmit_chars(port); } if (!(port->gs.flags & SX_RX_THROTTLE)) { - sx_receive_chars (port); + sx_receive_chars(port); } } } - clear_bit (SX_BOARD_INTR_LOCK, &board->locks); + clear_bit(SX_BOARD_INTR_LOCK, &board->locks); - sx_dprintk (SX_DEBUG_FLOW, "sx: exit sx_interrupt (%d/%d)\n", irq, board->irq); - func_exit (); + sx_dprintk(SX_DEBUG_FLOW, "sx: exit sx_interrupt (%d/%d)\n", irq, + board->irq); + func_exit(); return IRQ_HANDLED; } - -static void sx_pollfunc (unsigned long data) +static void sx_pollfunc(unsigned long data) { - struct sx_board *board = (struct sx_board *) data; - - func_enter (); + struct sx_board *board = (struct sx_board *)data; - sx_interrupt (0, board); + func_enter(); - init_timer(&board->timer); + sx_interrupt(0, board); - board->timer.expires = jiffies + sx_poll; - add_timer (&board->timer); - func_exit (); + mod_timer(&board->timer, jiffies + sx_poll); + func_exit(); } - - /* ********************************************************************** * * Here are the routines that actually * * interface with the generic_serial driver * @@ -1319,9 +1365,9 @@ static void sx_pollfunc (unsigned long data) /* Ehhm. I don't know how to fiddle with interrupts on the SX card. --REW */ /* Hmm. Ok I figured it out. You don't. */ -static void sx_disable_tx_interrupts (void * ptr) +static void sx_disable_tx_interrupts(void *ptr) { - struct sx_port *port = ptr; + struct sx_port *port = ptr; func_enter2(); port->gs.flags &= ~GS_TX_INTEN; @@ -1329,30 +1375,28 @@ static void sx_disable_tx_interrupts (void * ptr) func_exit(); } - -static void sx_enable_tx_interrupts (void * ptr) +static void sx_enable_tx_interrupts(void *ptr) { - struct sx_port *port = ptr; + struct sx_port *port = ptr; int data_in_buffer; func_enter2(); /* First transmit the characters that we're supposed to */ - sx_transmit_chars (port); + sx_transmit_chars(port); /* The sx card will never interrupt us if we don't fill the buffer past 25%. So we keep considering interrupts off if that's the case. */ - data_in_buffer = (sx_read_channel_byte (port, hi_txipos) - - sx_read_channel_byte (port, hi_txopos)) & 0xff; + data_in_buffer = (sx_read_channel_byte(port, hi_txipos) - + sx_read_channel_byte(port, hi_txopos)) & 0xff; /* XXX Must be "HIGH_WATER" for SI card according to doc. */ - if (data_in_buffer < LOW_WATER) + if (data_in_buffer < LOW_WATER) port->gs.flags &= ~GS_TX_INTEN; func_exit(); } - -static void sx_disable_rx_interrupts (void * ptr) +static void sx_disable_rx_interrupts(void *ptr) { /* struct sx_port *port = ptr; */ func_enter(); @@ -1360,7 +1404,7 @@ static void sx_disable_rx_interrupts (void * ptr) func_exit(); } -static void sx_enable_rx_interrupts (void * ptr) +static void sx_enable_rx_interrupts(void *ptr) { /* struct sx_port *port = ptr; */ func_enter(); @@ -1368,55 +1412,48 @@ static void sx_enable_rx_interrupts (void * ptr) func_exit(); } - /* Jeez. Isn't this simple? */ -static int sx_get_CD (void * ptr) +static int sx_get_CD(void *ptr) { struct sx_port *port = ptr; func_enter2(); func_exit(); - return ((sx_read_channel_byte (port, hi_ip) & IP_DCD) != 0); + return ((sx_read_channel_byte(port, hi_ip) & IP_DCD) != 0); } - /* Jeez. Isn't this simple? */ -static int sx_chars_in_buffer (void * ptr) +static int sx_chars_in_buffer(void *ptr) { struct sx_port *port = ptr; func_enter2(); func_exit(); - return ((sx_read_channel_byte (port, hi_txipos) - - sx_read_channel_byte (port, hi_txopos)) & 0xff); + return ((sx_read_channel_byte(port, hi_txipos) - + sx_read_channel_byte(port, hi_txopos)) & 0xff); } - -static void sx_shutdown_port (void * ptr) +static void sx_shutdown_port(void *ptr) { - struct sx_port *port = ptr; + struct sx_port *port = ptr; func_enter(); - port->gs.flags &= ~ GS_ACTIVE; + port->gs.flags &= ~GS_ACTIVE; if (port->gs.tty && (port->gs.tty->termios->c_cflag & HUPCL)) { - sx_setsignals (port, 0, 0); + sx_setsignals(port, 0, 0); sx_reconfigure_port(port); } func_exit(); } - - - - /* ********************************************************************** * * Here are the routines that actually * * interface with the rest of the system * * ********************************************************************** */ -static int sx_open (struct tty_struct * tty, struct file * filp) +static int sx_open(struct tty_struct *tty, struct file *filp) { struct sx_port *port; int retval, line; @@ -1429,18 +1466,18 @@ static int sx_open (struct tty_struct * tty, struct file * filp) } line = tty->index; - sx_dprintk (SX_DEBUG_OPEN, "%d: opening line %d. tty=%p ctty=%p, np=%d)\n", - current->pid, line, tty, current->signal->tty, sx_nports); + sx_dprintk(SX_DEBUG_OPEN, "%d: opening line %d. tty=%p ctty=%p, " + "np=%d)\n", current->pid, line, tty, + current->signal->tty, sx_nports); if ((line < 0) || (line >= SX_NPORTS) || (line >= sx_nports)) return -ENODEV; - port = & sx_ports[line]; + port = &sx_ports[line]; port->c_dcd = 0; /* Make sure that the first interrupt doesn't detect a - 1 -> 0 transition. */ + 1 -> 0 transition. */ - - sx_dprintk (SX_DEBUG_OPEN, "port = %p c_dcd = %d\n", port, port->c_dcd); + sx_dprintk(SX_DEBUG_OPEN, "port = %p c_dcd = %d\n", port, port->c_dcd); spin_lock_irqsave(&port->gs.driver_lock, flags); @@ -1449,13 +1486,13 @@ static int sx_open (struct tty_struct * tty, struct file * filp) port->gs.count++; spin_unlock_irqrestore(&port->gs.driver_lock, flags); - sx_dprintk (SX_DEBUG_OPEN, "starting port\n"); + sx_dprintk(SX_DEBUG_OPEN, "starting port\n"); /* * Start up serial port */ retval = gs_init_port(&port->gs); - sx_dprintk (SX_DEBUG_OPEN, "done gs_init\n"); + sx_dprintk(SX_DEBUG_OPEN, "done gs_init\n"); if (retval) { port->gs.count--; return retval; @@ -1463,19 +1500,20 @@ static int sx_open (struct tty_struct * tty, struct file * filp) port->gs.flags |= GS_ACTIVE; if (port->gs.count <= 1) - sx_setsignals (port, 1,1); + sx_setsignals(port, 1, 1); #if 0 if (sx_debug & SX_DEBUG_OPEN) - my_hd (port, sizeof (*port)); + my_hd(port, sizeof(*port)); #else if (sx_debug & SX_DEBUG_OPEN) - my_hd_io (port->board->base + port->ch_base, sizeof (*port)); + my_hd_io(port->board->base + port->ch_base, sizeof(*port)); #endif if (port->gs.count <= 1) { - if (sx_send_command (port, HS_LOPEN, -1, HS_IDLE_OPEN) != 1) { - printk (KERN_ERR "sx: Card didn't respond to LOPEN command.\n"); + if (sx_send_command(port, HS_LOPEN, -1, HS_IDLE_OPEN) != 1) { + printk(KERN_ERR "sx: Card didn't respond to LOPEN " + "command.\n"); spin_lock_irqsave(&port->gs.driver_lock, flags); port->gs.count--; spin_unlock_irqrestore(&port->gs.driver_lock, flags); @@ -1484,75 +1522,76 @@ static int sx_open (struct tty_struct * tty, struct file * filp) } retval = gs_block_til_ready(port, filp); - sx_dprintk (SX_DEBUG_OPEN, "Block til ready returned %d. Count=%d\n", - retval, port->gs.count); + sx_dprintk(SX_DEBUG_OPEN, "Block til ready returned %d. Count=%d\n", + retval, port->gs.count); if (retval) { - /* - * Don't lower gs.count here because sx_close() will be called later - */ +/* + * Don't lower gs.count here because sx_close() will be called later + */ return retval; } /* tty->low_latency = 1; */ - port->c_dcd = sx_get_CD (port); - sx_dprintk (SX_DEBUG_OPEN, "at open: cd=%d\n", port->c_dcd); + port->c_dcd = sx_get_CD(port); + sx_dprintk(SX_DEBUG_OPEN, "at open: cd=%d\n", port->c_dcd); func_exit(); return 0; } - -static void sx_close (void *ptr) +static void sx_close(void *ptr) { - struct sx_port *port = ptr; + struct sx_port *port = ptr; /* Give the port 5 seconds to close down. */ - int to = 5 * HZ; + int to = 5 * HZ; - func_enter (); + func_enter(); - sx_setsignals (port, 0, 0); - sx_reconfigure_port(port); - sx_send_command (port, HS_CLOSE, 0, 0); + sx_setsignals(port, 0, 0); + sx_reconfigure_port(port); + sx_send_command(port, HS_CLOSE, 0, 0); - while (to-- && (sx_read_channel_byte (port, hi_hstat) != HS_IDLE_CLOSED)) + while (to-- && (sx_read_channel_byte(port, hi_hstat) != HS_IDLE_CLOSED)) if (msleep_interruptible(10)) break; - if (sx_read_channel_byte (port, hi_hstat) != HS_IDLE_CLOSED) { - if (sx_send_command (port, HS_FORCE_CLOSED, -1, HS_IDLE_CLOSED) != 1) { - printk (KERN_ERR - "sx: sent the force_close command, but card didn't react\n"); + if (sx_read_channel_byte(port, hi_hstat) != HS_IDLE_CLOSED) { + if (sx_send_command(port, HS_FORCE_CLOSED, -1, HS_IDLE_CLOSED) + != 1) { + printk(KERN_ERR "sx: sent the force_close command, but " + "card didn't react\n"); } else - sx_dprintk (SX_DEBUG_CLOSE, "sent the force_close command.\n"); + sx_dprintk(SX_DEBUG_CLOSE, "sent the force_close " + "command.\n"); } - sx_dprintk (SX_DEBUG_CLOSE, "waited %d jiffies for close. count=%d\n", - 5 * HZ - to - 1, port->gs.count); + sx_dprintk(SX_DEBUG_CLOSE, "waited %d jiffies for close. count=%d\n", + 5 * HZ - to - 1, port->gs.count); - if(port->gs.count) { - sx_dprintk(SX_DEBUG_CLOSE, "WARNING port count:%d\n", port->gs.count); - //printk ("%s SETTING port count to zero: %p count: %d\n", __FUNCTION__, port, port->gs.count); - //port->gs.count = 0; + if (port->gs.count) { + sx_dprintk(SX_DEBUG_CLOSE, "WARNING port count:%d\n", + port->gs.count); + /*printk("%s SETTING port count to zero: %p count: %d\n", + __FUNCTION__, port, port->gs.count); + port->gs.count = 0;*/ } - func_exit (); + func_exit(); } - - /* This is relatively thorough. But then again it is only 20 lines. */ -#define MARCHUP for (i=min;i=min;i--) -#define W0 write_sx_byte (board, i, 0x55) -#define W1 write_sx_byte (board, i, 0xaa) -#define R0 if (read_sx_byte (board, i) != 0x55) return 1 -#define R1 if (read_sx_byte (board, i) != 0xaa) return 1 +#define MARCHUP for (i = min; i < max; i++) +#define MARCHDOWN for (i = max - 1; i >= min; i--) +#define W0 write_sx_byte(board, i, 0x55) +#define W1 write_sx_byte(board, i, 0xaa) +#define R0 if (read_sx_byte(board, i) != 0x55) return 1 +#define R1 if (read_sx_byte(board, i) != 0xaa) return 1 /* This memtest takes a human-noticable time. You normally only do it once a boot, so I guess that it is worth it. */ -static int do_memtest (struct sx_board *board, int min, int max) +static int do_memtest(struct sx_board *board, int min, int max) { int i; @@ -1561,16 +1600,37 @@ static int do_memtest (struct sx_board *board, int min, int max) intermittent errors. -- REW (For the theory behind memory testing see: Testing Semiconductor Memories by A.J. van de Goor.) */ - MARCHUP {W0;} - MARCHUP {R0;W1;R1;W0;R0;W1;} - MARCHUP {R1;W0;W1;} - MARCHDOWN {R1;W0;W1;W0;} - MARCHDOWN {R0;W1;W0;} + MARCHUP { + W0; + } + MARCHUP { + R0; + W1; + R1; + W0; + R0; + W1; + } + MARCHUP { + R1; + W0; + W1; + } + MARCHDOWN { + R1; + W0; + W1; + W0; + } + MARCHDOWN { + R0; + W1; + W0; + } return 0; } - #undef MARCHUP #undef MARCHDOWN #undef W0 @@ -1578,33 +1638,54 @@ static int do_memtest (struct sx_board *board, int min, int max) #undef R0 #undef R1 -#define MARCHUP for (i=min;i=min;i-=2) -#define W0 write_sx_word (board, i, 0x55aa) -#define W1 write_sx_word (board, i, 0xaa55) -#define R0 if (read_sx_word (board, i) != 0x55aa) return 1 -#define R1 if (read_sx_word (board, i) != 0xaa55) return 1 +#define MARCHUP for (i = min; i < max; i += 2) +#define MARCHDOWN for (i = max - 1; i >= min; i -= 2) +#define W0 write_sx_word(board, i, 0x55aa) +#define W1 write_sx_word(board, i, 0xaa55) +#define R0 if (read_sx_word(board, i) != 0x55aa) return 1 +#define R1 if (read_sx_word(board, i) != 0xaa55) return 1 #if 0 /* This memtest takes a human-noticable time. You normally only do it once a boot, so I guess that it is worth it. */ -static int do_memtest_w (struct sx_board *board, int min, int max) +static int do_memtest_w(struct sx_board *board, int min, int max) { int i; - MARCHUP {W0;} - MARCHUP {R0;W1;R1;W0;R0;W1;} - MARCHUP {R1;W0;W1;} - MARCHDOWN {R1;W0;W1;W0;} - MARCHDOWN {R0;W1;W0;} + MARCHUP { + W0; + } + MARCHUP { + R0; + W1; + R1; + W0; + R0; + W1; + } + MARCHUP { + R1; + W0; + W1; + } + MARCHDOWN { + R1; + W0; + W1; + W0; + } + MARCHDOWN { + R0; + W1; + W0; + } return 0; } #endif - -static int sx_fw_ioctl (struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) +static int sx_fw_ioctl(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) { int rc = 0; int __user *descr = (int __user *)arg; @@ -1616,7 +1697,7 @@ static int sx_fw_ioctl (struct inode *inode, struct file *filp, func_enter(); -#if 0 +#if 0 /* Removed superuser check: Sysops can use the permissions on the device file to restrict access. Recommendation: Root only. (root.root 600) */ if (!capable(CAP_SYS_ADMIN)) { @@ -1624,103 +1705,115 @@ static int sx_fw_ioctl (struct inode *inode, struct file *filp, } #endif - sx_dprintk (SX_DEBUG_FIRMWARE, "IOCTL %x: %lx\n", cmd, arg); + sx_dprintk(SX_DEBUG_FIRMWARE, "IOCTL %x: %lx\n", cmd, arg); - if (!board) board = &boards[0]; + if (!board) + board = &boards[0]; if (board->flags & SX_BOARD_PRESENT) { - sx_dprintk (SX_DEBUG_FIRMWARE, "Board present! (%x)\n", - board->flags); + sx_dprintk(SX_DEBUG_FIRMWARE, "Board present! (%x)\n", + board->flags); } else { - sx_dprintk (SX_DEBUG_FIRMWARE, "Board not present! (%x) all:", - board->flags); - for (i=0;i< SX_NBOARDS;i++) - sx_dprintk (SX_DEBUG_FIRMWARE, "<%x> ", boards[i].flags); - sx_dprintk (SX_DEBUG_FIRMWARE, "\n"); + sx_dprintk(SX_DEBUG_FIRMWARE, "Board not present! (%x) all:", + board->flags); + for (i = 0; i < SX_NBOARDS; i++) + sx_dprintk(SX_DEBUG_FIRMWARE, "<%x> ", boards[i].flags); + sx_dprintk(SX_DEBUG_FIRMWARE, "\n"); return -EIO; } switch (cmd) { case SXIO_SET_BOARD: - sx_dprintk (SX_DEBUG_FIRMWARE, "set board to %ld\n", arg); - if (arg >= SX_NBOARDS) return -EIO; - sx_dprintk (SX_DEBUG_FIRMWARE, "not out of range\n"); - if (!(boards[arg].flags & SX_BOARD_PRESENT)) return -EIO; - sx_dprintk (SX_DEBUG_FIRMWARE, ".. and present!\n"); + sx_dprintk(SX_DEBUG_FIRMWARE, "set board to %ld\n", arg); + if (arg >= SX_NBOARDS) + return -EIO; + sx_dprintk(SX_DEBUG_FIRMWARE, "not out of range\n"); + if (!(boards[arg].flags & SX_BOARD_PRESENT)) + return -EIO; + sx_dprintk(SX_DEBUG_FIRMWARE, ".. and present!\n"); board = &boards[arg]; break; case SXIO_GET_TYPE: - rc = -ENOENT; /* If we manage to miss one, return error. */ - if (IS_SX_BOARD (board)) rc = SX_TYPE_SX; - if (IS_CF_BOARD (board)) rc = SX_TYPE_CF; - if (IS_SI_BOARD (board)) rc = SX_TYPE_SI; - if (IS_SI1_BOARD (board)) rc = SX_TYPE_SI; - if (IS_EISA_BOARD (board)) rc = SX_TYPE_SI; - sx_dprintk (SX_DEBUG_FIRMWARE, "returning type= %d\n", rc); + rc = -ENOENT; /* If we manage to miss one, return error. */ + if (IS_SX_BOARD(board)) + rc = SX_TYPE_SX; + if (IS_CF_BOARD(board)) + rc = SX_TYPE_CF; + if (IS_SI_BOARD(board)) + rc = SX_TYPE_SI; + if (IS_SI1_BOARD(board)) + rc = SX_TYPE_SI; + if (IS_EISA_BOARD(board)) + rc = SX_TYPE_SI; + sx_dprintk(SX_DEBUG_FIRMWARE, "returning type= %d\n", rc); break; case SXIO_DO_RAMTEST: - if (sx_initialized) /* Already initialized: better not ramtest the board. */ + if (sx_initialized) /* Already initialized: better not ramtest the board. */ return -EPERM; - if (IS_SX_BOARD (board)) { - rc = do_memtest (board, 0, 0x7000); - if (!rc) rc = do_memtest (board, 0, 0x7000); - /*if (!rc) rc = do_memtest_w (board, 0, 0x7000);*/ + if (IS_SX_BOARD(board)) { + rc = do_memtest(board, 0, 0x7000); + if (!rc) + rc = do_memtest(board, 0, 0x7000); + /*if (!rc) rc = do_memtest_w (board, 0, 0x7000); */ } else { - rc = do_memtest (board, 0, 0x7ff8); + rc = do_memtest(board, 0, 0x7ff8); /* if (!rc) rc = do_memtest_w (board, 0, 0x7ff8); */ } - sx_dprintk (SX_DEBUG_FIRMWARE, "returning memtest result= %d\n", rc); + sx_dprintk(SX_DEBUG_FIRMWARE, "returning memtest result= %d\n", + rc); break; case SXIO_DOWNLOAD: - if (sx_initialized) /* Already initialized */ + if (sx_initialized) /* Already initialized */ return -EEXIST; - if (!sx_reset (board)) + if (!sx_reset(board)) return -EIO; - sx_dprintk (SX_DEBUG_INIT, "reset the board...\n"); - - tmp = kmalloc (SX_CHUNK_SIZE, GFP_USER); - if (!tmp) return -ENOMEM; - get_user (nbytes, descr++); - get_user (offset, descr++); - get_user (data, descr++); + sx_dprintk(SX_DEBUG_INIT, "reset the board...\n"); + + tmp = kmalloc(SX_CHUNK_SIZE, GFP_USER); + if (!tmp) + return -ENOMEM; + get_user(nbytes, descr++); + get_user(offset, descr++); + get_user(data, descr++); while (nbytes && data) { - for (i=0;i - nbytes) ? nbytes - i : - SX_CHUNK_SIZE)) { - kfree (tmp); + for (i = 0; i < nbytes; i += SX_CHUNK_SIZE) { + if (copy_from_user(tmp, (char __user *)data + i, + (i + SX_CHUNK_SIZE > nbytes) ? + nbytes - i : SX_CHUNK_SIZE)) { + kfree(tmp); return -EFAULT; } - memcpy_toio(board->base2 + offset + i, tmp, - (i+SX_CHUNK_SIZE>nbytes)?nbytes-i:SX_CHUNK_SIZE); + memcpy_toio(board->base2 + offset + i, tmp, + (i + SX_CHUNK_SIZE > nbytes) ? + nbytes - i : SX_CHUNK_SIZE); } - get_user (nbytes, descr++); - get_user (offset, descr++); - get_user (data, descr++); + get_user(nbytes, descr++); + get_user(offset, descr++); + get_user(data, descr++); } - kfree (tmp); - sx_nports += sx_init_board (board); + kfree(tmp); + sx_nports += sx_init_board(board); rc = sx_nports; break; case SXIO_INIT: - if (sx_initialized) /* Already initialized */ + if (sx_initialized) /* Already initialized */ return -EEXIST; /* This is not allowed until all boards are initialized... */ - for (i=0;i= 0) + for (i = 0; i < SX_NBOARDS; i++) + if (!(boards[i].flags & SX_BOARD_PRESENT)) + break; + + sx_dprintk(SX_DEBUG_FIRMWARE, "initing portstructs, %d boards, " + "%d channels, first board: %d ports\n", + i, sx_nports, boards[0].nports); + rc = sx_init_portstructs(i, sx_nports); + sx_init_drivers(); + if (rc >= 0) sx_initialized++; break; case SXIO_SETDEBUG: @@ -1737,32 +1830,32 @@ static int sx_fw_ioctl (struct inode *inode, struct file *filp, rc = sx_nports; break; default: - printk (KERN_WARNING "Unknown ioctl on firmware device (%x).\n", cmd); + printk(KERN_WARNING "Unknown ioctl on firmware device (%x).\n", + cmd); break; } - func_exit (); + func_exit(); return rc; } - -static void sx_break (struct tty_struct * tty, int flag) +static void sx_break(struct tty_struct *tty, int flag) { struct sx_port *port = tty->driver_data; int rv; - func_enter (); + func_enter(); - if (flag) - rv = sx_send_command (port, HS_START, -1, HS_IDLE_BREAK); - else - rv = sx_send_command (port, HS_STOP, -1, HS_IDLE_OPEN); - if (rv != 1) printk (KERN_ERR "sx: couldn't send break (%x).\n", - read_sx_byte (port->board, CHAN_OFFSET (port, hi_hstat))); + if (flag) + rv = sx_send_command(port, HS_START, -1, HS_IDLE_BREAK); + else + rv = sx_send_command(port, HS_STOP, -1, HS_IDLE_OPEN); + if (rv != 1) + printk(KERN_ERR "sx: couldn't send break (%x).\n", + read_sx_byte(port->board, CHAN_OFFSET(port, hi_hstat))); - func_exit (); + func_exit(); } - static int sx_tiocmget(struct tty_struct *tty, struct file *file) { struct sx_port *port = tty->driver_data; @@ -1770,7 +1863,7 @@ static int sx_tiocmget(struct tty_struct *tty, struct file *file) } static int sx_tiocmset(struct tty_struct *tty, struct file *file, - unsigned int set, unsigned int clear) + unsigned int set, unsigned int clear) { struct sx_port *port = tty->driver_data; int rts = -1, dtr = -1; @@ -1789,8 +1882,8 @@ static int sx_tiocmset(struct tty_struct *tty, struct file *file, return 0; } -static int sx_ioctl (struct tty_struct * tty, struct file * filp, - unsigned int cmd, unsigned long arg) +static int sx_ioctl(struct tty_struct *tty, struct file *filp, + unsigned int cmd, unsigned long arg) { int rc; struct sx_port *port = tty->driver_data; @@ -1803,10 +1896,10 @@ static int sx_ioctl (struct tty_struct * tty, struct file * filp, switch (cmd) { case TIOCGSOFTCAR: rc = put_user(((tty->termios->c_cflag & CLOCAL) ? 1 : 0), - (unsigned __user *) argp); + (unsigned __user *)argp); break; case TIOCSSOFTCAR: - if ((rc = get_user(ival, (unsigned __user *) argp)) == 0) { + if ((rc = get_user(ival, (unsigned __user *)argp)) == 0) { tty->termios->c_cflag = (tty->termios->c_cflag & ~CLOCAL) | (ival ? CLOCAL : 0); @@ -1827,7 +1920,6 @@ static int sx_ioctl (struct tty_struct * tty, struct file * filp, return rc; } - /* The throttle/unthrottle scheme for the Specialix card is different * from other drivers and deserves some explanation. * The Specialix hardware takes care of XON/XOFF @@ -1844,7 +1936,7 @@ static int sx_ioctl (struct tty_struct * tty, struct file * filp, * flow control scheme is in use for that port. -- Simon Allen */ -static void sx_throttle (struct tty_struct * tty) +static void sx_throttle(struct tty_struct *tty) { struct sx_port *port = (struct sx_port *)tty->driver_data; @@ -1852,14 +1944,13 @@ static void sx_throttle (struct tty_struct * tty) /* If the port is using any type of input flow * control then throttle the port. */ - if((tty->termios->c_cflag & CRTSCTS) || (I_IXOFF(tty)) ) { + if ((tty->termios->c_cflag & CRTSCTS) || (I_IXOFF(tty))) { port->gs.flags |= SX_RX_THROTTLE; } func_exit(); } - -static void sx_unthrottle (struct tty_struct * tty) +static void sx_unthrottle(struct tty_struct *tty) { struct sx_port *port = (struct sx_port *)tty->driver_data; @@ -1873,15 +1964,11 @@ static void sx_unthrottle (struct tty_struct * tty) return; } - /* ********************************************************************** * * Here are the initialization routines. * * ********************************************************************** */ - - - -static int sx_init_board (struct sx_board *board) +static int sx_init_board(struct sx_board *board) { int addr; int chans; @@ -1893,36 +1980,38 @@ static int sx_init_board (struct sx_board *board) board->flags |= SX_BOARD_INITIALIZED; - if (read_sx_byte (board, 0)) + if (read_sx_byte(board, 0)) /* CF boards may need this. */ - write_sx_byte(board,0, 0); + write_sx_byte(board, 0, 0); /* This resets the processor again, to make sure it didn't do any foolish things while we were downloading the image */ - if (!sx_reset (board)) + if (!sx_reset(board)) return 0; - sx_start_board (board); - udelay (10); - if (!sx_busy_wait_neq (board, 0, 0xff, 0)) { - printk (KERN_ERR "sx: Ooops. Board won't initialize.\n"); + sx_start_board(board); + udelay(10); + if (!sx_busy_wait_neq(board, 0, 0xff, 0)) { + printk(KERN_ERR "sx: Ooops. Board won't initialize.\n"); return 0; } /* Ok. So now the processor on the card is running. It gathered some info for us... */ - sx_dprintk (SX_DEBUG_INIT, "The sxcard structure:\n"); - if (sx_debug & SX_DEBUG_INIT) my_hd_io (board->base, 0x10); - sx_dprintk (SX_DEBUG_INIT, "the first sx_module structure:\n"); - if (sx_debug & SX_DEBUG_INIT) my_hd_io (board->base + 0x80, 0x30); - - sx_dprintk (SX_DEBUG_INIT, - "init_status: %x, %dk memory, firmware V%x.%02x,\n", - read_sx_byte (board, 0), read_sx_byte(board, 1), - read_sx_byte (board, 5), read_sx_byte(board, 4)); - - if (read_sx_byte (board, 0) == 0xff) { - printk (KERN_INFO "sx: No modules found. Sorry.\n"); + sx_dprintk(SX_DEBUG_INIT, "The sxcard structure:\n"); + if (sx_debug & SX_DEBUG_INIT) + my_hd_io(board->base, 0x10); + sx_dprintk(SX_DEBUG_INIT, "the first sx_module structure:\n"); + if (sx_debug & SX_DEBUG_INIT) + my_hd_io(board->base + 0x80, 0x30); + + sx_dprintk(SX_DEBUG_INIT, "init_status: %x, %dk memory, firmware " + "V%x.%02x,\n", + read_sx_byte(board, 0), read_sx_byte(board, 1), + read_sx_byte(board, 5), read_sx_byte(board, 4)); + + if (read_sx_byte(board, 0) == 0xff) { + printk(KERN_INFO "sx: No modules found. Sorry.\n"); board->nports = 0; return 0; } @@ -1930,82 +2019,97 @@ static int sx_init_board (struct sx_board *board) chans = 0; if (IS_SX_BOARD(board)) { - sx_write_board_word (board, cc_int_count, sx_maxints); + sx_write_board_word(board, cc_int_count, sx_maxints); } else { if (sx_maxints) - sx_write_board_word (board, cc_int_count, SI_PROCESSOR_CLOCK/8/sx_maxints); + sx_write_board_word(board, cc_int_count, + SI_PROCESSOR_CLOCK / 8 / sx_maxints); } /* grab the first module type... */ - /* board->ta_type = mod_compat_type (read_sx_byte (board, 0x80 + 0x08)); */ - board->ta_type = mod_compat_type (sx_read_module_byte (board, 0x80, mc_chip)); + /* board->ta_type = mod_compat_type (read_sx_byte (board, 0x80 + 0x08)); */ + board->ta_type = mod_compat_type(sx_read_module_byte(board, 0x80, + mc_chip)); /* XXX byteorder */ - for (addr = 0x80;addr != 0;addr = read_sx_word (board, addr) & 0x7fff) { - type = sx_read_module_byte (board, addr, mc_chip); - sx_dprintk (SX_DEBUG_INIT, "Module at %x: %d channels\n", - addr, read_sx_byte (board, addr + 2)); - - chans += sx_read_module_byte (board, addr, mc_type); - - sx_dprintk (SX_DEBUG_INIT, "module is an %s, which has %s/%s panels\n", - mod_type_s (type), - pan_type_s (sx_read_module_byte (board, addr, mc_mods) & 0xf), - pan_type_s (sx_read_module_byte (board, addr, mc_mods) >> 4)); - - sx_dprintk (SX_DEBUG_INIT, "CD1400 versions: %x/%x, ASIC version: %x\n", - sx_read_module_byte (board, addr, mc_rev1), - sx_read_module_byte (board, addr, mc_rev2), - sx_read_module_byte (board, addr, mc_mtaasic_rev)); + for (addr = 0x80; addr != 0; addr = read_sx_word(board, addr) & 0x7fff){ + type = sx_read_module_byte(board, addr, mc_chip); + sx_dprintk(SX_DEBUG_INIT, "Module at %x: %d channels\n", + addr, read_sx_byte(board, addr + 2)); + + chans += sx_read_module_byte(board, addr, mc_type); + + sx_dprintk(SX_DEBUG_INIT, "module is an %s, which has %s/%s " + "panels\n", + mod_type_s(type), + pan_type_s(sx_read_module_byte(board, addr, + mc_mods) & 0xf), + pan_type_s(sx_read_module_byte(board, addr, + mc_mods) >> 4)); + + sx_dprintk(SX_DEBUG_INIT, "CD1400 versions: %x/%x, ASIC " + "version: %x\n", + sx_read_module_byte(board, addr, mc_rev1), + sx_read_module_byte(board, addr, mc_rev2), + sx_read_module_byte(board, addr, mc_mtaasic_rev)); /* The following combinations are illegal: It should theoretically work, but timing problems make the bus HANG. */ - if (mod_compat_type (type) != board->ta_type) { - printk (KERN_ERR "sx: This is an invalid configuration.\n" - "Don't mix TA/MTA/SXDC on the same hostadapter.\n"); - chans=0; + if (mod_compat_type(type) != board->ta_type) { + printk(KERN_ERR "sx: This is an invalid " + "configuration.\nDon't mix TA/MTA/SXDC on the " + "same hostadapter.\n"); + chans = 0; break; } - if ((IS_EISA_BOARD(board) || - IS_SI_BOARD(board)) && (mod_compat_type(type) == 4)) { - printk (KERN_ERR "sx: This is an invalid configuration.\n" - "Don't use SXDCs on an SI/XIO adapter.\n"); - chans=0; + if ((IS_EISA_BOARD(board) || + IS_SI_BOARD(board)) && + (mod_compat_type(type) == 4)) { + printk(KERN_ERR "sx: This is an invalid " + "configuration.\nDon't use SXDCs on an SI/XIO " + "adapter.\n"); + chans = 0; break; } -#if 0 /* Problem fixed: firmware 3.05 */ +#if 0 /* Problem fixed: firmware 3.05 */ if (IS_SX_BOARD(board) && (type == TA8)) { /* There are some issues with the firmware and the DCD/RTS lines. It might work if you tie them together or something. - It might also work if you get a newer sx_firmware. Therefore + It might also work if you get a newer sx_firmware. Therefore this is just a warning. */ - printk (KERN_WARNING "sx: The SX host doesn't work too well " - "with the TA8 adapters.\nSpecialix is working on it.\n"); + printk(KERN_WARNING + "sx: The SX host doesn't work too well " + "with the TA8 adapters.\nSpecialix is working on it.\n"); } #endif } if (chans) { - /* board->flags |= SX_BOARD_PRESENT; */ - if(board->irq > 0) { + if (board->irq > 0) { /* fixed irq, probably PCI */ - if(sx_irqmask & (1 << board->irq)) { /* may we use this irq? */ - if(request_irq(board->irq, sx_interrupt, IRQF_SHARED | IRQF_DISABLED, "sx", board)) { - printk(KERN_ERR "sx: Cannot allocate irq %d.\n", board->irq); + if (sx_irqmask & (1 << board->irq)) { /* may we use this irq? */ + if (request_irq(board->irq, sx_interrupt, + IRQF_SHARED | IRQF_DISABLED, + "sx", board)) { + printk(KERN_ERR "sx: Cannot allocate " + "irq %d.\n", board->irq); board->irq = 0; } } else board->irq = 0; - } else if(board->irq < 0 && sx_irqmask) { + } else if (board->irq < 0 && sx_irqmask) { /* auto-allocate irq */ int irqnr; - int irqmask = sx_irqmask & (IS_SX_BOARD(board) ? SX_ISA_IRQ_MASK : SI2_ISA_IRQ_MASK); - for(irqnr = 15; irqnr > 0; irqnr--) - if(irqmask & (1 << irqnr)) - if(! request_irq(irqnr, sx_interrupt, IRQF_SHARED | IRQF_DISABLED, "sx", board)) + int irqmask = sx_irqmask & (IS_SX_BOARD(board) ? + SX_ISA_IRQ_MASK : SI2_ISA_IRQ_MASK); + for (irqnr = 15; irqnr > 0; irqnr--) + if (irqmask & (1 << irqnr)) + if (!request_irq(irqnr, sx_interrupt, + IRQF_SHARED | IRQF_DISABLED, + "sx", board)) break; - if(! irqnr) + if (!irqnr) printk(KERN_ERR "sx: Cannot allocate IRQ.\n"); board->irq = irqnr; } else @@ -2013,52 +2117,48 @@ static int sx_init_board (struct sx_board *board) if (board->irq) { /* Found a valid interrupt, start up interrupts! */ - sx_dprintk (SX_DEBUG_INIT, "Using irq %d.\n", board->irq); - sx_start_interrupts (board); + sx_dprintk(SX_DEBUG_INIT, "Using irq %d.\n", + board->irq); + sx_start_interrupts(board); board->poll = sx_slowpoll; board->flags |= SX_IRQ_ALLOCATED; } else { /* no irq: setup board for polled operation */ board->poll = sx_poll; - sx_dprintk (SX_DEBUG_INIT, "Using poll-interval %d.\n", board->poll); + sx_dprintk(SX_DEBUG_INIT, "Using poll-interval %d.\n", + board->poll); } - /* The timer should be initialized anyway: That way we can safely - del_timer it when the module is unloaded. */ - init_timer (&board->timer); + /* The timer should be initialized anyway: That way we can + safely del_timer it when the module is unloaded. */ + setup_timer(&board->timer, sx_pollfunc, (unsigned long)board); - if (board->poll) { - board->timer.data = (unsigned long) board; - board->timer.function = sx_pollfunc; - board->timer.expires = jiffies + board->poll; - add_timer (&board->timer); - } + if (board->poll) + mod_timer(&board->timer, jiffies + board->poll); } else { board->irq = 0; } board->nports = chans; - sx_dprintk (SX_DEBUG_INIT, "returning %d ports.", board->nports); + sx_dprintk(SX_DEBUG_INIT, "returning %d ports.", board->nports); func_exit(); return chans; } - -static void printheader(void) +static void __devinit printheader(void) { static int header_printed; if (!header_printed) { - printk (KERN_INFO "Specialix SX driver " - "(C) 1998/1999 R.E.Wolff@BitWizard.nl \n"); - printk (KERN_INFO "sx: version %s\n", RCS_ID); + printk(KERN_INFO "Specialix SX driver " + "(C) 1998/1999 R.E.Wolff@BitWizard.nl\n"); + printk(KERN_INFO "sx: version " __stringify(SX_VERSION) "\n"); header_printed = 1; } } - -static int probe_sx (struct sx_board *board) +static int __devinit probe_sx(struct sx_board *board) { struct vpd_prom vpdp; char *p; @@ -2066,51 +2166,57 @@ static int probe_sx (struct sx_board *board) func_enter(); - if (!IS_CF_BOARD (board)) { - sx_dprintk (SX_DEBUG_PROBE, "Going to verify vpd prom at %p.\n", - board->base + SX_VPD_ROM); + if (!IS_CF_BOARD(board)) { + sx_dprintk(SX_DEBUG_PROBE, "Going to verify vpd prom at %p.\n", + board->base + SX_VPD_ROM); if (sx_debug & SX_DEBUG_PROBE) my_hd_io(board->base + SX_VPD_ROM, 0x40); - p = (char *) &vpdp; - for (i=0;i< sizeof (struct vpd_prom);i++) - *p++ = read_sx_byte (board, SX_VPD_ROM + i*2); + p = (char *)&vpdp; + for (i = 0; i < sizeof(struct vpd_prom); i++) + *p++ = read_sx_byte(board, SX_VPD_ROM + i * 2); if (sx_debug & SX_DEBUG_PROBE) - my_hd (&vpdp, 0x20); + my_hd(&vpdp, 0x20); - sx_dprintk (SX_DEBUG_PROBE, "checking identifier...\n"); + sx_dprintk(SX_DEBUG_PROBE, "checking identifier...\n"); - if (strncmp (vpdp.identifier, SX_VPD_IDENT_STRING, 16) != 0) { - sx_dprintk (SX_DEBUG_PROBE, "Got non-SX identifier: '%s'\n", - vpdp.identifier); + if (strncmp(vpdp.identifier, SX_VPD_IDENT_STRING, 16) != 0) { + sx_dprintk(SX_DEBUG_PROBE, "Got non-SX identifier: " + "'%s'\n", vpdp.identifier); return 0; } } - printheader (); - - if (!IS_CF_BOARD (board)) { - printk (KERN_DEBUG "sx: Found an SX board at %lx\n", board->hw_base); - printk (KERN_DEBUG "sx: hw_rev: %d, assembly level: %d, uniq ID:%08x, ", - vpdp.hwrev, vpdp.hwass, vpdp.uniqid); - printk ( "Manufactured: %d/%d\n", - 1970 + vpdp.myear, vpdp.mweek); + printheader(); + if (!IS_CF_BOARD(board)) { + printk(KERN_DEBUG "sx: Found an SX board at %lx\n", + board->hw_base); + printk(KERN_DEBUG "sx: hw_rev: %d, assembly level: %d, " + "uniq ID:%08x, ", + vpdp.hwrev, vpdp.hwass, vpdp.uniqid); + printk("Manufactured: %d/%d\n", 1970 + vpdp.myear, vpdp.mweek); - if ((((vpdp.uniqid >> 24) & SX_UNIQUEID_MASK) != SX_PCI_UNIQUEID1) && - (((vpdp.uniqid >> 24) & SX_UNIQUEID_MASK) != SX_ISA_UNIQUEID1)) { - /* This might be a bit harsh. This was the primary reason the - SX/ISA card didn't work at first... */ - printk (KERN_ERR "sx: Hmm. Not an SX/PCI or SX/ISA card. Sorry: giving up.\n"); + if ((((vpdp.uniqid >> 24) & SX_UNIQUEID_MASK) != + SX_PCI_UNIQUEID1) && (((vpdp.uniqid >> 24) & + SX_UNIQUEID_MASK) != SX_ISA_UNIQUEID1)) { + /* This might be a bit harsh. This was the primary + reason the SX/ISA card didn't work at first... */ + printk(KERN_ERR "sx: Hmm. Not an SX/PCI or SX/ISA " + "card. Sorry: giving up.\n"); return (0); } - if (((vpdp.uniqid >> 24) & SX_UNIQUEID_MASK) == SX_ISA_UNIQUEID1) { + if (((vpdp.uniqid >> 24) & SX_UNIQUEID_MASK) == + SX_ISA_UNIQUEID1) { if (((unsigned long)board->hw_base) & 0x8000) { - printk (KERN_WARNING "sx: Warning: There may be hardware problems with the card at %lx.\n", board->hw_base); - printk (KERN_WARNING "sx: Read sx.txt for more info.\n"); + printk(KERN_WARNING "sx: Warning: There may be " + "hardware problems with the card at " + "%lx.\n", board->hw_base); + printk(KERN_WARNING "sx: Read sx.txt for more " + "info.\n"); } } } @@ -2118,17 +2224,15 @@ static int probe_sx (struct sx_board *board) board->nports = -1; /* This resets the processor, and keeps it off the bus. */ - if (!sx_reset (board)) + if (!sx_reset(board)) return 0; - sx_dprintk (SX_DEBUG_INIT, "reset the board...\n"); - - board->flags |= SX_BOARD_PRESENT; + sx_dprintk(SX_DEBUG_INIT, "reset the board...\n"); func_exit(); return 1; } - +#if defined(CONFIG_ISA) || defined(CONFIG_EISA) /* Specialix probes for this card at 32k increments from 640k to 16M. I consider machines with less than 16M unlikely nowadays, so I'm @@ -2136,28 +2240,27 @@ static int probe_sx (struct sx_board *board) card. 0xe0000 and 0xf0000 are taken by the BIOS. That only leaves 0xc0000, 0xc8000, 0xd0000 and 0xd8000 . */ -static int probe_si (struct sx_board *board) +static int __devinit probe_si(struct sx_board *board) { int i; func_enter(); - sx_dprintk (SX_DEBUG_PROBE, "Going to verify SI signature hw %lx at %p.\n", board->hw_base, - board->base + SI2_ISA_ID_BASE); + sx_dprintk(SX_DEBUG_PROBE, "Going to verify SI signature hw %lx at " + "%p.\n", board->hw_base, board->base + SI2_ISA_ID_BASE); if (sx_debug & SX_DEBUG_PROBE) my_hd_io(board->base + SI2_ISA_ID_BASE, 0x8); if (!IS_EISA_BOARD(board)) { - if( IS_SI1_BOARD(board) ) - { - for (i=0;i<8;i++) { - write_sx_byte (board, SI2_ISA_ID_BASE+7-i,i); - + if (IS_SI1_BOARD(board)) { + for (i = 0; i < 8; i++) { + write_sx_byte(board, SI2_ISA_ID_BASE + 7 - i,i); + } } - } - for (i=0;i<8;i++) { - if ((read_sx_byte (board, SI2_ISA_ID_BASE+7-i) & 7) != i) { - func_exit (); + for (i = 0; i < 8; i++) { + if ((read_sx_byte(board, SI2_ISA_ID_BASE + 7 - i) & 7) + != i) { + func_exit(); return 0; } } @@ -2167,20 +2270,20 @@ static int probe_si (struct sx_board *board) but to prevent trouble, we'd better double check that we don't have an SI1 board when we're probing for an SI2 board.... */ - write_sx_byte (board, SI2_ISA_ID_BASE,0x10); - if ( IS_SI1_BOARD(board)) { + write_sx_byte(board, SI2_ISA_ID_BASE, 0x10); + if (IS_SI1_BOARD(board)) { /* This should be an SI1 board, which has this location writable... */ - if (read_sx_byte (board, SI2_ISA_ID_BASE) != 0x10) { - func_exit (); - return 0; + if (read_sx_byte(board, SI2_ISA_ID_BASE) != 0x10) { + func_exit(); + return 0; } } else { /* This should be an SI2 board, which has the bottom 3 bits non-writable... */ - if (read_sx_byte (board, SI2_ISA_ID_BASE) == 0x10) { - func_exit (); - return 0; + if (read_sx_byte(board, SI2_ISA_ID_BASE) == 0x10) { + func_exit(); + return 0; } } @@ -2188,45 +2291,44 @@ static int probe_si (struct sx_board *board) but to prevent trouble, we'd better double check that we don't have an SI1 board when we're probing for an SI2 board.... */ - write_sx_byte (board, SI2_ISA_ID_BASE,0x10); - if ( IS_SI1_BOARD(board)) { + write_sx_byte(board, SI2_ISA_ID_BASE, 0x10); + if (IS_SI1_BOARD(board)) { /* This should be an SI1 board, which has this location writable... */ - if (read_sx_byte (board, SI2_ISA_ID_BASE) != 0x10) { + if (read_sx_byte(board, SI2_ISA_ID_BASE) != 0x10) { func_exit(); - return 0; + return 0; } } else { /* This should be an SI2 board, which has the bottom 3 bits non-writable... */ - if (read_sx_byte (board, SI2_ISA_ID_BASE) == 0x10) { - func_exit (); - return 0; + if (read_sx_byte(board, SI2_ISA_ID_BASE) == 0x10) { + func_exit(); + return 0; } } - printheader (); + printheader(); - printk (KERN_DEBUG "sx: Found an SI board at %lx\n", board->hw_base); + printk(KERN_DEBUG "sx: Found an SI board at %lx\n", board->hw_base); /* Compared to the SX boards, it is a complete guess as to what - this card is up to... */ + this card is up to... */ board->nports = -1; /* This resets the processor, and keeps it off the bus. */ - if (!sx_reset (board)) + if (!sx_reset(board)) return 0; - sx_dprintk (SX_DEBUG_INIT, "reset the board...\n"); - - board->flags |= SX_BOARD_PRESENT; + sx_dprintk(SX_DEBUG_INIT, "reset the board...\n"); func_exit(); return 1; } +#endif static const struct tty_operations sx_ops = { .break_ctl = sx_break, - .open = sx_open, + .open = sx_open, .close = gs_close, .write = gs_write, .put_char = gs_put_char, @@ -2261,34 +2363,23 @@ static int sx_init_drivers(void) sx_driver->type = TTY_DRIVER_TYPE_SERIAL; sx_driver->subtype = SERIAL_TYPE_NORMAL; sx_driver->init_termios = tty_std_termios; - sx_driver->init_termios.c_cflag = - B9600 | CS8 | CREAD | HUPCL | CLOCAL; + sx_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; + sx_driver->init_termios.c_ispeed = 9600; + sx_driver->init_termios.c_ospeed = 9600; sx_driver->flags = TTY_DRIVER_REAL_RAW; tty_set_operations(sx_driver, &sx_ops); if ((error = tty_register_driver(sx_driver))) { put_tty_driver(sx_driver); printk(KERN_ERR "sx: Couldn't register sx driver, error = %d\n", - error); + error); return 1; } func_exit(); return 0; } - -static void * ckmalloc (int size) -{ - void *p; - - p = kmalloc(size, GFP_KERNEL); - if (p) - memset(p, 0, size); - return p; -} - - -static int sx_init_portstructs (int nboards, int nports) +static int sx_init_portstructs(int nboards, int nports) { struct sx_board *board; struct sx_port *port; @@ -2299,8 +2390,9 @@ static int sx_init_portstructs (int nboards, int nports) func_enter(); /* Many drivers statically allocate the maximum number of ports - There is no reason not to allocate them dynamically. Is there? -- REW */ - sx_ports = ckmalloc(nports * sizeof (struct sx_port)); + There is no reason not to allocate them dynamically. + Is there? -- REW */ + sx_ports = kcalloc(nports, sizeof(struct sx_port), GFP_KERNEL); if (!sx_ports) return -ENOMEM; @@ -2308,10 +2400,10 @@ static int sx_init_portstructs (int nboards, int nports) for (i = 0; i < nboards; i++) { board = &boards[i]; board->ports = port; - for (j=0; j < boards[i].nports;j++) { - sx_dprintk (SX_DEBUG_INIT, "initing port %d\n", j); + for (j = 0; j < boards[i].nports; j++) { + sx_dprintk(SX_DEBUG_INIT, "initing port %d\n", j); port->gs.magic = SX_MAGIC; - port->gs.close_delay = HZ/2; + port->gs.close_delay = HZ / 2; port->gs.closing_wait = 30 * HZ; port->board = board; port->gs.rd = &sx_real_driver; @@ -2323,8 +2415,8 @@ static int sx_init_portstructs (int nboards, int nports) * Initializing wait queue */ init_waitqueue_head(&port->gs.open_wait); - init_waitqueue_head(&port->gs.close_wait); - + init_waitqueue_head(&port->gs.close_wait); + port++; } } @@ -2335,28 +2427,36 @@ static int sx_init_portstructs (int nboards, int nports) board = &boards[i]; board->port_base = portno; /* Possibly the configuration was rejected. */ - sx_dprintk (SX_DEBUG_PROBE, "Board has %d channels\n", board->nports); - if (board->nports <= 0) continue; + sx_dprintk(SX_DEBUG_PROBE, "Board has %d channels\n", + board->nports); + if (board->nports <= 0) + continue; /* XXX byteorder ?? */ - for (addr = 0x80;addr != 0;addr = read_sx_word (board, addr) & 0x7fff) { - chans = sx_read_module_byte (board, addr, mc_type); - sx_dprintk (SX_DEBUG_PROBE, "Module at %x: %d channels\n", addr, chans); - sx_dprintk (SX_DEBUG_PROBE, "Port at"); - for (j=0;jch_base = sx_read_module_word (board, addr+j*2, mc_chan_pointer); + port->ch_base = sx_read_module_word( + board, addr + j * 2, + mc_chan_pointer); else - port->ch_base = addr + 0x100 + 0x300*j; + port->ch_base = addr + 0x100 + 0x300 *j; - sx_dprintk (SX_DEBUG_PROBE, " %x", port->ch_base); + sx_dprintk(SX_DEBUG_PROBE, " %x", + port->ch_base); port->line = portno++; port++; } - sx_dprintk (SX_DEBUG_PROBE, "\n"); + sx_dprintk(SX_DEBUG_PROBE, "\n"); } /* This has to be done earlier. */ /* board->flags |= SX_BOARD_INITIALIZED; */ @@ -2366,6 +2466,17 @@ static int sx_init_portstructs (int nboards, int nports) return 0; } +static unsigned int sx_find_free_board(void) +{ + unsigned int i; + + for (i = 0; i < SX_NBOARDS; i++) + if (!(boards[i].flags & SX_BOARD_PRESENT)) + break; + + return i; +} + static void __exit sx_release_drivers(void) { func_enter(); @@ -2374,7 +2485,122 @@ static void __exit sx_release_drivers(void) func_exit(); } -#ifdef CONFIG_PCI +static void __devexit sx_remove_card(struct sx_board *board, + struct pci_dev *pdev) +{ + if (board->flags & SX_BOARD_INITIALIZED) { + /* The board should stop messing with us. (actually I mean the + interrupt) */ + sx_reset(board); + if ((board->irq) && (board->flags & SX_IRQ_ALLOCATED)) + free_irq(board->irq, board); + + /* It is safe/allowed to del_timer a non-active timer */ + del_timer(&board->timer); + if (pdev) { + pci_iounmap(pdev, board->base); + pci_release_region(pdev, IS_CF_BOARD(board) ? 3 : 2); + } else { + iounmap(board->base); + release_region(board->hw_base, board->hw_len); + } + + board->flags &= ~(SX_BOARD_INITIALIZED | SX_BOARD_PRESENT); + } +} + +#ifdef CONFIG_EISA + +static int __devinit sx_eisa_probe(struct device *dev) +{ + struct eisa_device *edev = to_eisa_device(dev); + struct sx_board *board; + unsigned long eisa_slot = edev->base_addr; + unsigned int i; + int retval = -EIO; + + mutex_lock(&sx_boards_lock); + i = sx_find_free_board(); + if (i == SX_NBOARDS) { + mutex_unlock(&sx_boards_lock); + goto err; + } + board = &boards[i]; + board->flags |= SX_BOARD_PRESENT; + mutex_unlock(&sx_boards_lock); + + dev_info(dev, "XIO : Signature found in EISA slot %lu, " + "Product %d Rev %d (REPORT THIS TO LKLM)\n", + eisa_slot >> 12, + inb(eisa_slot + EISA_VENDOR_ID_OFFSET + 2), + inb(eisa_slot + EISA_VENDOR_ID_OFFSET + 3)); + + board->eisa_base = eisa_slot; + board->flags &= ~SX_BOARD_TYPE; + board->flags |= SI_EISA_BOARD; + + board->hw_base = ((inb(eisa_slot + 0xc01) << 8) + + inb(eisa_slot + 0xc00)) << 16; + board->hw_len = SI2_EISA_WINDOW_LEN; + if (!request_region(board->hw_base, board->hw_len, "sx")) { + dev_err(dev, "can't request region\n"); + goto err_flag; + } + board->base2 = + board->base = ioremap(board->hw_base, SI2_EISA_WINDOW_LEN); + if (!board->base) { + dev_err(dev, "can't remap memory\n"); + goto err_reg; + } + + sx_dprintk(SX_DEBUG_PROBE, "IO hw_base address: %lx\n", board->hw_base); + sx_dprintk(SX_DEBUG_PROBE, "base: %p\n", board->base); + board->irq = inb(eisa_slot + 0xc02) >> 4; + sx_dprintk(SX_DEBUG_PROBE, "IRQ: %d\n", board->irq); + + if (!probe_si(board)) + goto err_unmap; + + dev_set_drvdata(dev, board); + + return 0; +err_unmap: + iounmap(board->base); +err_reg: + release_region(board->hw_base, board->hw_len); +err_flag: + board->flags &= ~SX_BOARD_PRESENT; +err: + return retval; +} + +static int __devexit sx_eisa_remove(struct device *dev) +{ + struct sx_board *board = dev_get_drvdata(dev); + + sx_remove_card(board, NULL); + + return 0; +} + +static struct eisa_device_id sx_eisa_tbl[] = { + { "SLX" }, + { "" } +}; + +MODULE_DEVICE_TABLE(eisa, sx_eisa_tbl); + +static struct eisa_driver sx_eisadriver = { + .id_table = sx_eisa_tbl, + .driver = { + .name = "sx", + .probe = sx_eisa_probe, + .remove = __devexit_p(sx_eisa_remove), + } +}; + +#endif + /******************************************************** * Setting bit 17 in the CNTRL register of the PLX 9050 * * chip forces a retry on writes while a read is pending.* @@ -2386,233 +2612,265 @@ static void __exit sx_release_drivers(void) EEprom. As the bit is read/write for the CPU, we can fix it here, if we detect that it isn't set correctly. -- REW */ -static void fix_sx_pci (struct pci_dev *pdev, struct sx_board *board) +static void __devinit fix_sx_pci(struct pci_dev *pdev, struct sx_board *board) { unsigned int hwbase; void __iomem *rebase; unsigned int t; -#define CNTRL_REG_OFFSET 0x50 -#define CNTRL_REG_GOODVALUE 0x18260000 +#define CNTRL_REG_OFFSET 0x50 +#define CNTRL_REG_GOODVALUE 0x18260000 pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &hwbase); hwbase &= PCI_BASE_ADDRESS_MEM_MASK; rebase = ioremap(hwbase, 0x80); - t = readl (rebase + CNTRL_REG_OFFSET); + t = readl(rebase + CNTRL_REG_OFFSET); if (t != CNTRL_REG_GOODVALUE) { - printk (KERN_DEBUG "sx: performing cntrl reg fix: %08x -> %08x\n", t, CNTRL_REG_GOODVALUE); - writel (CNTRL_REG_GOODVALUE, rebase + CNTRL_REG_OFFSET); + printk(KERN_DEBUG "sx: performing cntrl reg fix: %08x -> " + "%08x\n", t, CNTRL_REG_GOODVALUE); + writel(CNTRL_REG_GOODVALUE, rebase + CNTRL_REG_OFFSET); } iounmap(rebase); } -#endif - -static int __init sx_init(void) +static int __devinit sx_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) { - int i; - int found = 0; - int eisa_slot; struct sx_board *board; + unsigned int i, reg; + int retval = -EIO; -#ifdef CONFIG_PCI - struct pci_dev *pdev = NULL; - unsigned int tint; - unsigned short tshort; -#endif + mutex_lock(&sx_boards_lock); + i = sx_find_free_board(); + if (i == SX_NBOARDS) { + mutex_unlock(&sx_boards_lock); + goto err; + } + board = &boards[i]; + board->flags |= SX_BOARD_PRESENT; + mutex_unlock(&sx_boards_lock); - func_enter(); - sx_dprintk (SX_DEBUG_INIT, "Initing sx module... (sx_debug=%d)\n", sx_debug); - if (abs ((long) (&sx_debug) - sx_debug) < 0x10000) { - printk (KERN_WARNING "sx: sx_debug is an address, instead of a value. " - "Assuming -1.\n"); - printk ("(%p)\n", &sx_debug); - sx_debug=-1; + retval = pci_enable_device(pdev); + if (retval) + goto err_flag; + + board->flags &= ~SX_BOARD_TYPE; + board->flags |= (pdev->subsystem_vendor == 0x200) ? SX_PCI_BOARD : + SX_CFPCI_BOARD; + + /* CF boards use base address 3.... */ + reg = IS_CF_BOARD(board) ? 3 : 2; + retval = pci_request_region(pdev, reg, "sx"); + if (retval) { + dev_err(&pdev->dev, "can't request region\n"); + goto err_flag; + } + board->hw_base = pci_resource_start(pdev, reg); + board->base2 = + board->base = pci_iomap(pdev, reg, WINDOW_LEN(board)); + if (!board->base) { + dev_err(&pdev->dev, "ioremap failed\n"); + goto err_reg; } - if (misc_register(&sx_fw_device) < 0) { - printk(KERN_ERR "SX: Unable to register firmware loader driver.\n"); - return -EIO; + /* Most of the stuff on the CF board is offset by 0x18000 .... */ + if (IS_CF_BOARD(board)) + board->base += 0x18000; + + board->irq = pdev->irq; + + dev_info(&pdev->dev, "Got a specialix card: %p(%d) %x.\n", board->base, + board->irq, board->flags); + + if (!probe_sx(board)) { + retval = -EIO; + goto err_unmap; } -#ifdef CONFIG_PCI - while ((pdev = pci_find_device (PCI_VENDOR_ID_SPECIALIX, - PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8, - pdev))) { - if (pci_enable_device(pdev)) - continue; + fix_sx_pci(pdev, board); - /* Specialix has a whole bunch of cards with - 0x2000 as the device ID. They say its because - the standard requires it. Stupid standard. */ - /* It seems that reading a word doesn't work reliably on 2.0. - Also, reading a non-aligned dword doesn't work. So we read the - whole dword at 0x2c and extract the word at 0x2e (SUBSYSTEM_ID) - ourselves */ - /* I don't know why the define doesn't work, constant 0x2c does --REW */ - pci_read_config_dword (pdev, 0x2c, &tint); - tshort = (tint >> 16) & 0xffff; - sx_dprintk (SX_DEBUG_PROBE, "Got a specialix card: %x.\n", tint); - /* sx_dprintk (SX_DEBUG_PROBE, "pdev = %d/%d (%x)\n", pdev, tint); */ - if ((tshort != 0x0200) && (tshort != 0x0300)) { - sx_dprintk (SX_DEBUG_PROBE, "But it's not an SX card (%d)...\n", - tshort); - continue; - } - board = &boards[found]; + pci_set_drvdata(pdev, board); - board->flags &= ~SX_BOARD_TYPE; - board->flags |= (tshort == 0x200)?SX_PCI_BOARD: - SX_CFPCI_BOARD; - - /* CF boards use base address 3.... */ - if (IS_CF_BOARD (board)) - board->hw_base = pci_resource_start (pdev, 3); - else - board->hw_base = pci_resource_start (pdev, 2); - board->base2 = - board->base = ioremap(board->hw_base, WINDOW_LEN (board)); - if (!board->base) { - printk(KERN_ERR "ioremap failed\n"); - /* XXX handle error */ - } + return 0; +err_unmap: + pci_iounmap(pdev, board->base); +err_reg: + pci_release_region(pdev, reg); +err_flag: + board->flags &= ~SX_BOARD_PRESENT; +err: + return retval; +} - /* Most of the stuff on the CF board is offset by - 0x18000 .... */ - if (IS_CF_BOARD (board)) board->base += 0x18000; +static void __devexit sx_pci_remove(struct pci_dev *pdev) +{ + struct sx_board *board = pci_get_drvdata(pdev); - board->irq = pdev->irq; + sx_remove_card(board, pdev); +} - sx_dprintk (SX_DEBUG_PROBE, "Got a specialix card: %x/%p(%d) %x.\n", - tint, boards[found].base, board->irq, board->flags); +/* Specialix has a whole bunch of cards with 0x2000 as the device ID. They say + its because the standard requires it. So check for SUBVENDOR_ID. */ +static struct pci_device_id sx_pci_tbl[] = { + { PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8, + .subvendor = 0x0200,.subdevice = PCI_ANY_ID }, + { PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8, + .subvendor = 0x0300,.subdevice = PCI_ANY_ID }, + { 0 } +}; - if (probe_sx (board)) { - found++; - fix_sx_pci (pdev, board); - } else - iounmap(board->base2); - } +MODULE_DEVICE_TABLE(pci, sx_pci_tbl); + +static struct pci_driver sx_pcidriver = { + .name = "sx", + .id_table = sx_pci_tbl, + .probe = sx_pci_probe, + .remove = __devexit_p(sx_pci_remove) +}; + +static int __init sx_init(void) +{ +#ifdef CONFIG_EISA + int retval1; #endif +#ifdef CONFIG_ISA + struct sx_board *board; + unsigned int i; +#endif + unsigned int found = 0; + int retval; + + func_enter(); + sx_dprintk(SX_DEBUG_INIT, "Initing sx module... (sx_debug=%d)\n", + sx_debug); + if (abs((long)(&sx_debug) - sx_debug) < 0x10000) { + printk(KERN_WARNING "sx: sx_debug is an address, instead of a " + "value. Assuming -1.\n(%p)\n", &sx_debug); + sx_debug = -1; + } - for (i=0;ihw_base = sx_probe_addrs[i]; + board->hw_len = SX_WINDOW_LEN; + if (!request_region(board->hw_base, board->hw_len, "sx")) + continue; board->base2 = - board->base = ioremap(board->hw_base, SX_WINDOW_LEN); + board->base = ioremap(board->hw_base, board->hw_len); + if (!board->base) + goto err_sx_reg; board->flags &= ~SX_BOARD_TYPE; - board->flags |= SX_ISA_BOARD; - board->irq = sx_irqmask?-1:0; + board->flags |= SX_ISA_BOARD; + board->irq = sx_irqmask ? -1 : 0; - if (probe_sx (board)) { + if (probe_sx(board)) { + board->flags |= SX_BOARD_PRESENT; found++; } else { iounmap(board->base); +err_sx_reg: + release_region(board->hw_base, board->hw_len); } } - for (i=0;ihw_base = si_probe_addrs[i]; + board->hw_len = SI2_ISA_WINDOW_LEN; + if (!request_region(board->hw_base, board->hw_len, "sx")) + continue; board->base2 = - board->base = ioremap(board->hw_base, SI2_ISA_WINDOW_LEN); + board->base = ioremap(board->hw_base, board->hw_len); + if (!board->base) + goto err_si_reg; board->flags &= ~SX_BOARD_TYPE; - board->flags |= SI_ISA_BOARD; - board->irq = sx_irqmask ?-1:0; + board->flags |= SI_ISA_BOARD; + board->irq = sx_irqmask ? -1 : 0; - if (probe_si (board)) { + if (probe_si(board)) { + board->flags |= SX_BOARD_PRESENT; found++; } else { - iounmap (board->base); + iounmap(board->base); +err_si_reg: + release_region(board->hw_base, board->hw_len); } } - for (i=0;ihw_base = si1_probe_addrs[i]; + board->hw_len = SI1_ISA_WINDOW_LEN; + if (!request_region(board->hw_base, board->hw_len, "sx")) + continue; board->base2 = - board->base = ioremap(board->hw_base, SI1_ISA_WINDOW_LEN); + board->base = ioremap(board->hw_base, board->hw_len); + if (!board->base) + goto err_si1_reg; board->flags &= ~SX_BOARD_TYPE; - board->flags |= SI1_ISA_BOARD; - board->irq = sx_irqmask ?-1:0; + board->flags |= SI1_ISA_BOARD; + board->irq = sx_irqmask ? -1 : 0; - if (probe_si (board)) { + if (probe_si(board)) { + board->flags |= SX_BOARD_PRESENT; found++; } else { - iounmap (board->base); + iounmap(board->base); +err_si1_reg: + release_region(board->hw_base, board->hw_len); } } +#endif +#ifdef CONFIG_EISA + retval1 = eisa_driver_register(&sx_eisadriver); +#endif + retval = pci_register_driver(&sx_pcidriver); - sx_dprintk(SX_DEBUG_PROBE, "Probing for EISA cards\n"); - for(eisa_slot=0x1000; eisa_slot<0x10000; eisa_slot+=0x1000) - { - if((inb(eisa_slot+0xc80)==0x4d) && - (inb(eisa_slot+0xc81)==0x98)) - { - sx_dprintk(SX_DEBUG_PROBE, "%s : Signature found in EISA slot %d, Product %d Rev %d\n", - "XIO", (eisa_slot>>12), inb(eisa_slot+0xc82), inb(eisa_slot+0xc83)); - - board = &boards[found]; - board->eisa_base = eisa_slot; - board->flags &= ~SX_BOARD_TYPE; - board->flags |= SI_EISA_BOARD; - - board->hw_base = (((inb(0xc01+eisa_slot) << 8) + inb(0xc00+eisa_slot)) << 16); - board->base2 = - board->base = ioremap(board->hw_base, SI2_EISA_WINDOW_LEN); - - sx_dprintk(SX_DEBUG_PROBE, "IO hw_base address: %lx\n", board->hw_base); - sx_dprintk(SX_DEBUG_PROBE, "base: %p\n", board->base); - board->irq = inb(board->eisa_base+0xc02)>>4; - sx_dprintk(SX_DEBUG_PROBE, "IRQ: %d\n", board->irq); - - probe_si(board); - - found++; - } - } if (found) { - printk (KERN_INFO "sx: total of %d boards detected.\n", found); - } else { - misc_deregister(&sx_fw_device); + printk(KERN_INFO "sx: total of %d boards detected.\n", found); + retval = 0; + } else if (retval) { +#ifdef CONFIG_EISA + retval = retval1; + if (retval1) +#endif + misc_deregister(&sx_fw_device); } func_exit(); - return found?0:-EIO; + return retval; } - -static void __exit sx_exit (void) +static void __exit sx_exit(void) { - int i; - struct sx_board *board; + int i; func_enter(); - for (i = 0; i < SX_NBOARDS; i++) { - board = &boards[i]; - if (board->flags & SX_BOARD_INITIALIZED) { - sx_dprintk (SX_DEBUG_CLEANUP, "Cleaning up board at %p\n", board->base); - /* The board should stop messing with us. - (actually I mean the interrupt) */ - sx_reset (board); - if ((board->irq) && (board->flags & SX_IRQ_ALLOCATED)) - free_irq (board->irq, board); - - /* It is safe/allowed to del_timer a non-active timer */ - del_timer (& board->timer); - iounmap(board->base); - } - } +#ifdef CONFIG_EISA + eisa_driver_unregister(&sx_eisadriver); +#endif + pci_unregister_driver(&sx_pcidriver); + + for (i = 0; i < SX_NBOARDS; i++) + sx_remove_card(&boards[i], NULL); + if (misc_deregister(&sx_fw_device) < 0) { - printk (KERN_INFO "sx: couldn't deregister firmware loader device\n"); + printk(KERN_INFO "sx: couldn't deregister firmware loader " + "device\n"); } - sx_dprintk (SX_DEBUG_CLEANUP, "Cleaning up drivers (%d)\n", sx_initialized); + sx_dprintk(SX_DEBUG_CLEANUP, "Cleaning up drivers (%d)\n", + sx_initialized); if (sx_initialized) - sx_release_drivers (); + sx_release_drivers(); - kfree (sx_ports); + kfree(sx_ports); func_exit(); } module_init(sx_init); module_exit(sx_exit); - - diff --git a/trunk/drivers/char/sx.h b/trunk/drivers/char/sx.h index e01f83cbe299..432aad0a2ddd 100644 --- a/trunk/drivers/char/sx.h +++ b/trunk/drivers/char/sx.h @@ -35,6 +35,7 @@ struct sx_board { void __iomem *base; void __iomem *base2; unsigned long hw_base; + resource_size_t hw_len; int eisa_base; int port_base; /* Number of the first port */ struct sx_port *ports; diff --git a/trunk/drivers/char/synclink.c b/trunk/drivers/char/synclink.c index 06784adcc35c..acc6fab601cc 100644 --- a/trunk/drivers/char/synclink.c +++ b/trunk/drivers/char/synclink.c @@ -101,8 +101,10 @@ #include #include -#ifdef CONFIG_HDLC_MODULE -#define CONFIG_HDLC 1 +#if defined(CONFIG_HDLC) || (defined(CONFIG_HDLC_MODULE) && defined(CONFIG_SYNCLINK_MODULE)) +#define SYNCLINK_GENERIC_HDLC 1 +#else +#define SYNCLINK_GENERIC_HDLC 0 #endif #define GET_USER(error,value,addr) error = get_user(value,addr) @@ -320,7 +322,7 @@ struct mgsl_struct { int dosyncppp; spinlock_t netlock; -#ifdef CONFIG_HDLC +#if SYNCLINK_GENERIC_HDLC struct net_device *netdev; #endif }; @@ -728,7 +730,7 @@ static void usc_loopmode_send_done( struct mgsl_struct * info ); static int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigned long arg); -#ifdef CONFIG_HDLC +#if SYNCLINK_GENERIC_HDLC #define dev_to_port(D) (dev_to_hdlc(D)->priv) static void hdlcdev_tx_done(struct mgsl_struct *info); static void hdlcdev_rx(struct mgsl_struct *info, char *buf, int size); @@ -802,7 +804,7 @@ static int save_tx_buffer_request(struct mgsl_struct *info,const char *Buffer, u /* * Bottom half interrupt handlers */ -static void mgsl_bh_handler(void* Context); +static void mgsl_bh_handler(struct work_struct *work); static void mgsl_bh_receive(struct mgsl_struct *info); static void mgsl_bh_transmit(struct mgsl_struct *info); static void mgsl_bh_status(struct mgsl_struct *info); @@ -1071,9 +1073,10 @@ static int mgsl_bh_action(struct mgsl_struct *info) /* * Perform bottom half processing of work items queued by ISR. */ -static void mgsl_bh_handler(void* Context) +static void mgsl_bh_handler(struct work_struct *work) { - struct mgsl_struct *info = (struct mgsl_struct*)Context; + struct mgsl_struct *info = + container_of(work, struct mgsl_struct, task); int action; if (!info) @@ -1276,7 +1279,7 @@ static void mgsl_isr_transmit_status( struct mgsl_struct *info ) info->drop_rts_on_tx_done = 0; } -#ifdef CONFIG_HDLC +#if SYNCLINK_GENERIC_HDLC if (info->netcount) hdlcdev_tx_done(info); else @@ -1341,7 +1344,7 @@ static void mgsl_isr_io_pin( struct mgsl_struct *info ) info->input_signal_events.dcd_up++; } else info->input_signal_events.dcd_down++; -#ifdef CONFIG_HDLC +#if SYNCLINK_GENERIC_HDLC if (info->netcount) { if (status & MISCSTATUS_DCD) netif_carrier_on(info->netdev); @@ -3057,7 +3060,7 @@ static int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigne * * Return Value: None */ -static void mgsl_set_termios(struct tty_struct *tty, struct termios *old_termios) +static void mgsl_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { struct mgsl_struct *info = (struct mgsl_struct *)tty->driver_data; unsigned long flags; @@ -4312,7 +4315,7 @@ static void mgsl_add_device( struct mgsl_struct *info ) info->max_frame_size ); } -#ifdef CONFIG_HDLC +#if SYNCLINK_GENERIC_HDLC hdlcdev_init(info); #endif @@ -4337,7 +4340,7 @@ static struct mgsl_struct* mgsl_allocate_device(void) } else { memset(info, 0, sizeof(struct mgsl_struct)); info->magic = MGSL_MAGIC; - INIT_WORK(&info->task, mgsl_bh_handler, info); + INIT_WORK(&info->task, mgsl_bh_handler); info->max_frame_size = 4096; info->close_delay = 5*HZ/10; info->closing_wait = 30*HZ; @@ -4402,6 +4405,8 @@ static int mgsl_init_tty(void) serial_driver->init_termios = tty_std_termios; serial_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; + serial_driver->init_termios.c_ispeed = 9600; + serial_driver->init_termios.c_ospeed = 9600; serial_driver->flags = TTY_DRIVER_REAL_RAW; tty_set_operations(serial_driver, &mgsl_ops); if ((rc = tty_register_driver(serial_driver)) < 0) { @@ -4470,7 +4475,7 @@ static void synclink_cleanup(void) info = mgsl_device_list; while(info) { -#ifdef CONFIG_HDLC +#if SYNCLINK_GENERIC_HDLC hdlcdev_exit(info); #endif mgsl_release_resources(info); @@ -6644,7 +6649,7 @@ static int mgsl_get_rx_frame(struct mgsl_struct *info) return_frame = 1; } framesize = 0; -#ifdef CONFIG_HDLC +#if SYNCLINK_GENERIC_HDLC { struct net_device_stats *stats = hdlc_stats(info->netdev); stats->rx_errors++; @@ -6720,7 +6725,7 @@ static int mgsl_get_rx_frame(struct mgsl_struct *info) *ptmp); } -#ifdef CONFIG_HDLC +#if SYNCLINK_GENERIC_HDLC if (info->netcount) hdlcdev_rx(info,info->intermediate_rxbuffer,framesize); else @@ -7624,7 +7629,7 @@ static void mgsl_tx_timeout(unsigned long context) spin_unlock_irqrestore(&info->irq_spinlock,flags); -#ifdef CONFIG_HDLC +#if SYNCLINK_GENERIC_HDLC if (info->netcount) hdlcdev_tx_done(info); else @@ -7700,7 +7705,7 @@ static int usc_loopmode_active( struct mgsl_struct * info) return usc_InReg( info, CCSR ) & BIT7 ? 1 : 0 ; } -#ifdef CONFIG_HDLC +#if SYNCLINK_GENERIC_HDLC /** * called by generic HDLC layer when protocol selected (PPP, frame relay, etc.) diff --git a/trunk/drivers/char/synclink_gt.c b/trunk/drivers/char/synclink_gt.c index d4334c79f8d4..792c79c315e0 100644 --- a/trunk/drivers/char/synclink_gt.c +++ b/trunk/drivers/char/synclink_gt.c @@ -83,8 +83,10 @@ #include "linux/synclink.h" -#ifdef CONFIG_HDLC_MODULE -#define CONFIG_HDLC 1 +#if defined(CONFIG_HDLC) || (defined(CONFIG_HDLC_MODULE) && defined(CONFIG_SYNCLINK_GT_MODULE)) +#define SYNCLINK_GENERIC_HDLC 1 +#else +#define SYNCLINK_GENERIC_HDLC 0 #endif /* @@ -149,7 +151,7 @@ static struct tty_driver *serial_driver; static int open(struct tty_struct *tty, struct file * filp); static void close(struct tty_struct *tty, struct file * filp); static void hangup(struct tty_struct *tty); -static void set_termios(struct tty_struct *tty, struct termios *old_termios); +static void set_termios(struct tty_struct *tty, struct ktermios *old_termios); static int write(struct tty_struct *tty, const unsigned char *buf, int count); static void put_char(struct tty_struct *tty, unsigned char ch); @@ -171,7 +173,7 @@ static void set_break(struct tty_struct *tty, int break_state); /* * generic HDLC support and callbacks */ -#ifdef CONFIG_HDLC +#if SYNCLINK_GENERIC_HDLC #define dev_to_port(D) (dev_to_hdlc(D)->priv) static void hdlcdev_tx_done(struct slgt_info *info); static void hdlcdev_rx(struct slgt_info *info, char *buf, int size); @@ -359,7 +361,7 @@ struct slgt_info { int netcount; int dosyncppp; spinlock_t netlock; -#ifdef CONFIG_HDLC +#if SYNCLINK_GENERIC_HDLC struct net_device *netdev; #endif @@ -485,7 +487,7 @@ static void enable_loopback(struct slgt_info *info); static void set_rate(struct slgt_info *info, u32 data_rate); static int bh_action(struct slgt_info *info); -static void bh_handler(void* context); +static void bh_handler(struct work_struct *work); static void bh_transmit(struct slgt_info *info); static void isr_serial(struct slgt_info *info); static void isr_rdma(struct slgt_info *info); @@ -814,7 +816,7 @@ static void hangup(struct tty_struct *tty) wake_up_interruptible(&info->open_wait); } -static void set_termios(struct tty_struct *tty, struct termios *old_termios) +static void set_termios(struct tty_struct *tty, struct ktermios *old_termios) { struct slgt_info *info = tty->driver_data; unsigned long flags; @@ -1354,7 +1356,7 @@ static void set_break(struct tty_struct *tty, int break_state) spin_unlock_irqrestore(&info->lock,flags); } -#ifdef CONFIG_HDLC +#if SYNCLINK_GENERIC_HDLC /** * called by generic HDLC layer when protocol selected (PPP, frame relay, etc.) @@ -1878,9 +1880,9 @@ static int bh_action(struct slgt_info *info) /* * perform bottom half processing */ -static void bh_handler(void* context) +static void bh_handler(struct work_struct *work) { - struct slgt_info *info = context; + struct slgt_info *info = container_of(work, struct slgt_info, task); int action; if (!info) @@ -2002,7 +2004,7 @@ static void dcd_change(struct slgt_info *info) } else { info->input_signal_events.dcd_down++; } -#ifdef CONFIG_HDLC +#if SYNCLINK_GENERIC_HDLC if (info->netcount) { if (info->signals & SerialSignal_DCD) netif_carrier_on(info->netdev); @@ -2180,7 +2182,7 @@ static void isr_txeom(struct slgt_info *info, unsigned short status) set_signals(info); } -#ifdef CONFIG_HDLC +#if SYNCLINK_GENERIC_HDLC if (info->netcount) hdlcdev_tx_done(info); else @@ -3306,7 +3308,7 @@ static void add_device(struct slgt_info *info) devstr, info->device_name, info->phys_reg_addr, info->irq_level, info->max_frame_size); -#ifdef CONFIG_HDLC +#if SYNCLINK_GENERIC_HDLC hdlcdev_init(info); #endif } @@ -3326,7 +3328,7 @@ static struct slgt_info *alloc_dev(int adapter_num, int port_num, struct pci_dev } else { memset(info, 0, sizeof(struct slgt_info)); info->magic = MGSL_MAGIC; - INIT_WORK(&info->task, bh_handler, info); + INIT_WORK(&info->task, bh_handler); info->max_frame_size = 4096; info->raw_rx_size = DMABUFSIZE; info->close_delay = 5*HZ/10; @@ -3488,7 +3490,7 @@ static void slgt_cleanup(void) /* release devices */ info = slgt_device_list; while(info) { -#ifdef CONFIG_HDLC +#if SYNCLINK_GENERIC_HDLC hdlcdev_exit(info); #endif free_dma_bufs(info); @@ -3522,6 +3524,7 @@ static int __init slgt_init(void) if (!slgt_device_list) { printk("%s no devices found\n",driver_name); + pci_unregister_driver(&pci_driver); return -ENODEV; } @@ -3543,6 +3546,8 @@ static int __init slgt_init(void) serial_driver->init_termios = tty_std_termios; serial_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; + serial_driver->init_termios.c_ispeed = 9600; + serial_driver->init_termios.c_ospeed = 9600; serial_driver->flags = TTY_DRIVER_REAL_RAW; tty_set_operations(serial_driver, &ops); if ((rc = tty_register_driver(serial_driver)) < 0) { @@ -4433,7 +4438,7 @@ static int rx_get_frame(struct slgt_info *info) framesize = 0; } -#ifdef CONFIG_HDLC +#if SYNCLINK_GENERIC_HDLC if (framesize == 0) { struct net_device_stats *stats = hdlc_stats(info->netdev); stats->rx_errors++; @@ -4476,7 +4481,7 @@ static int rx_get_frame(struct slgt_info *info) framesize++; } -#ifdef CONFIG_HDLC +#if SYNCLINK_GENERIC_HDLC if (info->netcount) hdlcdev_rx(info,info->tmp_rbuf, framesize); else @@ -4779,7 +4784,7 @@ static void tx_timeout(unsigned long context) info->tx_count = 0; spin_unlock_irqrestore(&info->lock,flags); -#ifdef CONFIG_HDLC +#if SYNCLINK_GENERIC_HDLC if (info->netcount) hdlcdev_tx_done(info); else @@ -4799,6 +4804,6 @@ static void rx_timeout(unsigned long context) spin_lock_irqsave(&info->lock, flags); info->pending_bh |= BH_RECEIVE; spin_unlock_irqrestore(&info->lock, flags); - bh_handler(info); + bh_handler(&info->task); } diff --git a/trunk/drivers/char/synclinkmp.c b/trunk/drivers/char/synclinkmp.c index 3e932b681371..53e8ccf94fe3 100644 --- a/trunk/drivers/char/synclinkmp.c +++ b/trunk/drivers/char/synclinkmp.c @@ -67,8 +67,10 @@ #include #include -#ifdef CONFIG_HDLC_MODULE -#define CONFIG_HDLC 1 +#if defined(CONFIG_HDLC) || (defined(CONFIG_HDLC_MODULE) && defined(CONFIG_SYNCLINKMP_MODULE)) +#define SYNCLINK_GENERIC_HDLC 1 +#else +#define SYNCLINK_GENERIC_HDLC 0 #endif #define GET_USER(error,value,addr) error = get_user(value,addr) @@ -280,7 +282,7 @@ typedef struct _synclinkmp_info { int dosyncppp; spinlock_t netlock; -#ifdef CONFIG_HDLC +#if SYNCLINK_GENERIC_HDLC struct net_device *netdev; #endif @@ -517,7 +519,7 @@ static struct tty_driver *serial_driver; static int open(struct tty_struct *tty, struct file * filp); static void close(struct tty_struct *tty, struct file * filp); static void hangup(struct tty_struct *tty); -static void set_termios(struct tty_struct *tty, struct termios *old_termios); +static void set_termios(struct tty_struct *tty, struct ktermios *old_termios); static int write(struct tty_struct *tty, const unsigned char *buf, int count); static void put_char(struct tty_struct *tty, unsigned char ch); @@ -536,7 +538,7 @@ static void throttle(struct tty_struct * tty); static void unthrottle(struct tty_struct * tty); static void set_break(struct tty_struct *tty, int break_state); -#ifdef CONFIG_HDLC +#if SYNCLINK_GENERIC_HDLC #define dev_to_port(D) (dev_to_hdlc(D)->priv) static void hdlcdev_tx_done(SLMP_INFO *info); static void hdlcdev_rx(SLMP_INFO *info, char *buf, int size); @@ -602,7 +604,7 @@ static void enable_loopback(SLMP_INFO *info, int enable); static void set_rate(SLMP_INFO *info, u32 data_rate); static int bh_action(SLMP_INFO *info); -static void bh_handler(void* Context); +static void bh_handler(struct work_struct *work); static void bh_receive(SLMP_INFO *info); static void bh_transmit(SLMP_INFO *info); static void bh_status(SLMP_INFO *info); @@ -916,7 +918,7 @@ static void hangup(struct tty_struct *tty) /* Set new termios settings */ -static void set_termios(struct tty_struct *tty, struct termios *old_termios) +static void set_termios(struct tty_struct *tty, struct ktermios *old_termios) { SLMP_INFO *info = (SLMP_INFO *)tty->driver_data; unsigned long flags; @@ -1607,7 +1609,7 @@ static void set_break(struct tty_struct *tty, int break_state) spin_unlock_irqrestore(&info->lock,flags); } -#ifdef CONFIG_HDLC +#if SYNCLINK_GENERIC_HDLC /** * called by generic HDLC layer when protocol selected (PPP, frame relay, etc.) @@ -2063,9 +2065,9 @@ int bh_action(SLMP_INFO *info) /* Perform bottom half processing of work items queued by ISR. */ -void bh_handler(void* Context) +void bh_handler(struct work_struct *work) { - SLMP_INFO *info = (SLMP_INFO*)Context; + SLMP_INFO *info = container_of(work, SLMP_INFO, task); int action; if (!info) @@ -2339,7 +2341,7 @@ static void isr_txeom(SLMP_INFO * info, unsigned char status) set_signals(info); } -#ifdef CONFIG_HDLC +#if SYNCLINK_GENERIC_HDLC if (info->netcount) hdlcdev_tx_done(info); else @@ -2523,7 +2525,7 @@ void isr_io_pin( SLMP_INFO *info, u16 status ) info->input_signal_events.dcd_up++; } else info->input_signal_events.dcd_down++; -#ifdef CONFIG_HDLC +#if SYNCLINK_GENERIC_HDLC if (info->netcount) { if (status & SerialSignal_DCD) netif_carrier_on(info->netdev); @@ -3783,7 +3785,7 @@ void add_device(SLMP_INFO *info) info->irq_level, info->max_frame_size ); -#ifdef CONFIG_HDLC +#if SYNCLINK_GENERIC_HDLC hdlcdev_init(info); #endif } @@ -3805,7 +3807,7 @@ static SLMP_INFO *alloc_dev(int adapter_num, int port_num, struct pci_dev *pdev) } else { memset(info, 0, sizeof(SLMP_INFO)); info->magic = MGSL_MAGIC; - INIT_WORK(&info->task, bh_handler, info); + INIT_WORK(&info->task, bh_handler); info->max_frame_size = 4096; info->close_delay = 5*HZ/10; info->closing_wait = 30*HZ; @@ -3977,7 +3979,7 @@ static void synclinkmp_cleanup(void) /* release devices */ info = synclinkmp_device_list; while(info) { -#ifdef CONFIG_HDLC +#if SYNCLINK_GENERIC_HDLC hdlcdev_exit(info); #endif free_dma_bufs(info); @@ -4032,6 +4034,8 @@ static int __init synclinkmp_init(void) serial_driver->init_termios = tty_std_termios; serial_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; + serial_driver->init_termios.c_ispeed = 9600; + serial_driver->init_termios.c_ospeed = 9600; serial_driver->flags = TTY_DRIVER_REAL_RAW; tty_set_operations(serial_driver, &ops); if ((rc = tty_register_driver(serial_driver)) < 0) { @@ -4979,7 +4983,7 @@ int rx_get_frame(SLMP_INFO *info) info->icount.rxcrc++; framesize = 0; -#ifdef CONFIG_HDLC +#if SYNCLINK_GENERIC_HDLC { struct net_device_stats *stats = hdlc_stats(info->netdev); stats->rx_errors++; @@ -5020,7 +5024,7 @@ int rx_get_frame(SLMP_INFO *info) index = 0; } -#ifdef CONFIG_HDLC +#if SYNCLINK_GENERIC_HDLC if (info->netcount) hdlcdev_rx(info,info->tmp_rx_buf,framesize); else @@ -5531,7 +5535,7 @@ void tx_timeout(unsigned long context) spin_unlock_irqrestore(&info->lock,flags); -#ifdef CONFIG_HDLC +#if SYNCLINK_GENERIC_HDLC if (info->netcount) hdlcdev_tx_done(info); else diff --git a/trunk/drivers/char/sysrq.c b/trunk/drivers/char/sysrq.c index 5f49280779fb..05810c8d20bc 100644 --- a/trunk/drivers/char/sysrq.c +++ b/trunk/drivers/char/sysrq.c @@ -182,6 +182,18 @@ static struct sysrq_key_op sysrq_showstate_op = { .enable_mask = SYSRQ_ENABLE_DUMP, }; +static void sysrq_handle_showstate_blocked(int key, struct tty_struct *tty) +{ + show_state_filter(TASK_UNINTERRUPTIBLE); +} +static struct sysrq_key_op sysrq_showstate_blocked_op = { + .handler = sysrq_handle_showstate_blocked, + .help_msg = "showBlockedTasks", + .action_msg = "Show Blocked State", + .enable_mask = SYSRQ_ENABLE_DUMP, +}; + + static void sysrq_handle_showmem(int key, struct tty_struct *tty) { show_mem(); @@ -219,13 +231,13 @@ static struct sysrq_key_op sysrq_term_op = { .enable_mask = SYSRQ_ENABLE_SIGNAL, }; -static void moom_callback(void *ignored) +static void moom_callback(struct work_struct *ignored) { out_of_memory(&NODE_DATA(0)->node_zonelists[ZONE_NORMAL], GFP_KERNEL, 0); } -static DECLARE_WORK(moom_work, moom_callback, NULL); +static DECLARE_WORK(moom_work, moom_callback); static void sysrq_handle_moom(int key, struct tty_struct *tty) { @@ -304,7 +316,7 @@ static struct sysrq_key_op *sysrq_key_table[36] = { /* May be assigned at init time by SMP VOYAGER */ NULL, /* v */ NULL, /* w */ - NULL, /* x */ + &sysrq_showstate_blocked_op, /* x */ NULL, /* y */ NULL /* z */ }; diff --git a/trunk/drivers/char/tb0219.c b/trunk/drivers/char/tb0219.c index bb1bad4c18f9..4c431cb7cf1b 100644 --- a/trunk/drivers/char/tb0219.c +++ b/trunk/drivers/char/tb0219.c @@ -164,7 +164,7 @@ static ssize_t tanbac_tb0219_read(struct file *file, char __user *buf, size_t le unsigned int minor; char value; - minor = iminor(file->f_dentry->d_inode); + minor = iminor(file->f_path.dentry->d_inode); switch (minor) { case 0: value = get_led(); @@ -200,7 +200,7 @@ static ssize_t tanbac_tb0219_write(struct file *file, const char __user *data, int retval = 0; char c; - minor = iminor(file->f_dentry->d_inode); + minor = iminor(file->f_path.dentry->d_inode); switch (minor) { case 0: type = TYPE_LED; diff --git a/trunk/drivers/char/tipar.c b/trunk/drivers/char/tipar.c index 9df0ca1be0e3..47fb20f69695 100644 --- a/trunk/drivers/char/tipar.c +++ b/trunk/drivers/char/tipar.c @@ -285,7 +285,7 @@ static ssize_t tipar_write (struct file *file, const char __user *buf, size_t count, loff_t * ppos) { - unsigned int minor = iminor(file->f_dentry->d_inode) - TIPAR_MINOR; + unsigned int minor = iminor(file->f_path.dentry->d_inode) - TIPAR_MINOR; ssize_t n; parport_claim_or_block(table[minor].dev); @@ -313,7 +313,7 @@ static ssize_t tipar_read(struct file *file, char __user *buf, size_t count, loff_t * ppos) { int b = 0; - unsigned int minor = iminor(file->f_dentry->d_inode) - TIPAR_MINOR; + unsigned int minor = iminor(file->f_path.dentry->d_inode) - TIPAR_MINOR; ssize_t retval = 0; ssize_t n = 0; diff --git a/trunk/drivers/char/toshiba.c b/trunk/drivers/char/toshiba.c index dd36fd04a842..07067c31c4ec 100644 --- a/trunk/drivers/char/toshiba.c +++ b/trunk/drivers/char/toshiba.c @@ -249,6 +249,7 @@ int tosh_smm(SMMRegisters *regs) return eax; } +EXPORT_SYMBOL(tosh_smm); static int tosh_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, diff --git a/trunk/drivers/char/tpm/tpm.c b/trunk/drivers/char/tpm/tpm.c index 6e1329d404d2..33e1f66e39cb 100644 --- a/trunk/drivers/char/tpm/tpm.c +++ b/trunk/drivers/char/tpm/tpm.c @@ -325,9 +325,9 @@ static void user_reader_timeout(unsigned long ptr) schedule_work(&chip->work); } -static void timeout_work(void *ptr) +static void timeout_work(struct work_struct *work) { - struct tpm_chip *chip = ptr; + struct tpm_chip *chip = container_of(work, struct tpm_chip, work); down(&chip->buffer_mutex); atomic_set(&chip->data_pending, 0); @@ -1105,7 +1105,7 @@ struct tpm_chip *tpm_register_hardware(struct device *dev, const struct tpm_vend init_MUTEX(&chip->tpm_mutex); INIT_LIST_HEAD(&chip->list); - INIT_WORK(&chip->work, timeout_work, chip); + INIT_WORK(&chip->work, timeout_work); init_timer(&chip->user_read_timer); chip->user_read_timer.function = user_reader_timeout; @@ -1155,6 +1155,7 @@ struct tpm_chip *tpm_register_hardware(struct device *dev, const struct tpm_vend if (sysfs_create_group(&dev->kobj, chip->vendor.attr_group)) { list_del(&chip->list); + misc_deregister(&chip->vendor.miscdev); put_device(dev); clear_bit(chip->dev_num, dev_mask); kfree(chip); diff --git a/trunk/drivers/char/tty_io.c b/trunk/drivers/char/tty_io.c index 50dc49205a23..4044c864fdd4 100644 --- a/trunk/drivers/char/tty_io.c +++ b/trunk/drivers/char/tty_io.c @@ -109,13 +109,15 @@ #define TTY_PARANOIA_CHECK 1 #define CHECK_TTY_COUNT 1 -struct termios tty_std_termios = { /* for the benefit of tty drivers */ +struct ktermios tty_std_termios = { /* for the benefit of tty drivers */ .c_iflag = ICRNL | IXON, .c_oflag = OPOST | ONLCR, .c_cflag = B38400 | CS8 | CREAD | HUPCL, .c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHOCTL | ECHOKE | IEXTEN, - .c_cc = INIT_C_CC + .c_cc = INIT_C_CC, + .c_ispeed = 38400, + .c_ospeed = 38400 }; EXPORT_SYMBOL(tty_std_termios); @@ -126,7 +128,7 @@ EXPORT_SYMBOL(tty_std_termios); LIST_HEAD(tty_drivers); /* linked list of tty drivers */ -/* Semaphore to protect creating and releasing a tty. This is shared with +/* Mutex to protect creating and releasing a tty. This is shared with vt.c for deeply disgusting hack reasons */ DEFINE_MUTEX(tty_mutex); EXPORT_SYMBOL(tty_mutex); @@ -250,7 +252,7 @@ static int check_tty_count(struct tty_struct *tty, const char *routine) "!= #fd's(%d) in %s\n", tty->name, tty->count, count, routine); return count; - } + } #endif return 0; } @@ -259,18 +261,6 @@ static int check_tty_count(struct tty_struct *tty, const char *routine) * Tty buffer allocation management */ - -/** - * tty_buffer_free_all - free buffers used by a tty - * @tty: tty to free from - * - * Remove all the buffers pending on a tty whether queued with data - * or in the free ring. Must be called when the tty is no longer in use - * - * Locking: none - */ - - /** * tty_buffer_free_all - free buffers used by a tty * @tty: tty to free from @@ -614,7 +604,7 @@ EXPORT_SYMBOL_GPL(tty_prepare_flip_string_flags); * they are not on hot paths so a little discipline won't do * any harm. * - * Locking: takes termios_sem + * Locking: takes termios_mutex */ static void tty_set_termios_ldisc(struct tty_struct *tty, int num) @@ -915,7 +905,7 @@ static void tty_ldisc_enable(struct tty_struct *tty) * context. * * Locking: takes tty_ldisc_lock. - * called functions take termios_sem + * called functions take termios_mutex */ static int tty_set_ldisc(struct tty_struct *tty, int ldisc) @@ -1251,10 +1241,26 @@ void tty_ldisc_flush(struct tty_struct *tty) } EXPORT_SYMBOL_GPL(tty_ldisc_flush); + +/** + * tty_reset_termios - reset terminal state + * @tty: tty to reset + * + * Restore a terminal to the driver default state + */ + +static void tty_reset_termios(struct tty_struct *tty) +{ + mutex_lock(&tty->termios_mutex); + *tty->termios = tty->driver->init_termios; + tty->termios->c_ispeed = tty_termios_input_baud_rate(tty->termios); + tty->termios->c_ospeed = tty_termios_baud_rate(tty->termios); + mutex_unlock(&tty->termios_mutex); +} /** * do_tty_hangup - actual handler for hangup events - * @data: tty device + * @work: tty device * * This can be called by the "eventd" kernel thread. That is process * synchronous but doesn't hold any locks, so we need to make sure we @@ -1267,16 +1273,17 @@ EXPORT_SYMBOL_GPL(tty_ldisc_flush); * * Locking: * BKL - * redirect lock for undoing redirection - * file list lock for manipulating list of ttys - * tty_ldisc_lock from called functions - * termios_sem resetting termios data - * tasklist_lock to walk task list for hangup event - * + * redirect lock for undoing redirection + * file list lock for manipulating list of ttys + * tty_ldisc_lock from called functions + * termios_mutex resetting termios data + * tasklist_lock to walk task list for hangup event + * ->siglock to protect ->signal/->sighand */ -static void do_tty_hangup(void *data) +static void do_tty_hangup(struct work_struct *work) { - struct tty_struct *tty = (struct tty_struct *) data; + struct tty_struct *tty = + container_of(work, struct tty_struct, hangup_work); struct file * cons_filp = NULL; struct file *filp, *f = NULL; struct task_struct *p; @@ -1338,11 +1345,7 @@ static void do_tty_hangup(void *data) * N_TTY. */ if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) - { - mutex_lock(&tty->termios_mutex); - *tty->termios = tty->driver->init_termios; - mutex_unlock(&tty->termios_mutex); - } + tty_reset_termios(tty); /* Defer ldisc switch */ /* tty_deferred_ldisc_switch(N_TTY); @@ -1353,14 +1356,18 @@ static void do_tty_hangup(void *data) read_lock(&tasklist_lock); if (tty->session > 0) { do_each_task_pid(tty->session, PIDTYPE_SID, p) { + spin_lock_irq(&p->sighand->siglock); if (p->signal->tty == tty) p->signal->tty = NULL; - if (!p->signal->leader) + if (!p->signal->leader) { + spin_unlock_irq(&p->sighand->siglock); continue; - group_send_sig_info(SIGHUP, SEND_SIG_PRIV, p); - group_send_sig_info(SIGCONT, SEND_SIG_PRIV, p); + } + __group_send_sig_info(SIGHUP, SEND_SIG_PRIV, p); + __group_send_sig_info(SIGCONT, SEND_SIG_PRIV, p); if (tty->pgrp > 0) p->signal->tty_old_pgrp = tty->pgrp; + spin_unlock_irq(&p->sighand->siglock); } while_each_task_pid(tty->session, PIDTYPE_SID, p); } read_unlock(&tasklist_lock); @@ -1433,7 +1440,7 @@ void tty_vhangup(struct tty_struct * tty) printk(KERN_DEBUG "%s vhangup...\n", tty_name(tty, buf)); #endif - do_tty_hangup((void *) tty); + do_tty_hangup(&tty->hangup_work); } EXPORT_SYMBOL(tty_vhangup); @@ -1452,6 +1459,14 @@ int tty_hung_up_p(struct file * filp) EXPORT_SYMBOL(tty_hung_up_p); +static void session_clear_tty(pid_t session) +{ + struct task_struct *p; + do_each_task_pid(session, PIDTYPE_SID, p) { + proc_clear_tty(p); + } while_each_task_pid(session, PIDTYPE_SID, p); +} + /** * disassociate_ctty - disconnect controlling tty * @on_exit: true if exiting so need to "hang up" the session @@ -1468,31 +1483,35 @@ EXPORT_SYMBOL(tty_hung_up_p); * The argument on_exit is set to 1 if called when a process is * exiting; it is 0 if called by the ioctl TIOCNOTTY. * - * Locking: tty_mutex is taken to protect current->signal->tty + * Locking: * BKL is taken for hysterical raisins - * Tasklist lock is taken (under tty_mutex) to walk process - * lists for the session. + * tty_mutex is taken to protect tty + * ->siglock is taken to protect ->signal/->sighand + * tasklist_lock is taken to walk process list for sessions + * ->siglock is taken to protect ->signal/->sighand */ void disassociate_ctty(int on_exit) { struct tty_struct *tty; - struct task_struct *p; int tty_pgrp = -1; + int session; lock_kernel(); mutex_lock(&tty_mutex); - tty = current->signal->tty; + tty = get_current_tty(); if (tty) { tty_pgrp = tty->pgrp; mutex_unlock(&tty_mutex); + /* XXX: here we race, there is nothing protecting tty */ if (on_exit && tty->driver->type != TTY_DRIVER_TYPE_PTY) tty_vhangup(tty); } else { - if (current->signal->tty_old_pgrp) { - kill_pg(current->signal->tty_old_pgrp, SIGHUP, on_exit); - kill_pg(current->signal->tty_old_pgrp, SIGCONT, on_exit); + pid_t old_pgrp = current->signal->tty_old_pgrp; + if (old_pgrp) { + kill_pg(old_pgrp, SIGHUP, on_exit); + kill_pg(old_pgrp, SIGCONT, on_exit); } mutex_unlock(&tty_mutex); unlock_kernel(); @@ -1504,19 +1523,29 @@ void disassociate_ctty(int on_exit) kill_pg(tty_pgrp, SIGCONT, on_exit); } - /* Must lock changes to tty_old_pgrp */ - mutex_lock(&tty_mutex); + spin_lock_irq(¤t->sighand->siglock); current->signal->tty_old_pgrp = 0; - tty->session = 0; - tty->pgrp = -1; + session = process_session(current); + spin_unlock_irq(¤t->sighand->siglock); + + mutex_lock(&tty_mutex); + /* It is possible that do_tty_hangup has free'd this tty */ + tty = get_current_tty(); + if (tty) { + tty->session = 0; + tty->pgrp = 0; + } else { +#ifdef TTY_DEBUG_HANGUP + printk(KERN_DEBUG "error attempted to write to tty [0x%p]" + " = NULL", tty); +#endif + } + mutex_unlock(&tty_mutex); /* Now clear signal->tty under the lock */ read_lock(&tasklist_lock); - do_each_task_pid(current->signal->session, PIDTYPE_SID, p) { - p->signal->tty = NULL; - } while_each_task_pid(current->signal->session, PIDTYPE_SID, p); + session_clear_tty(session); read_unlock(&tasklist_lock); - mutex_unlock(&tty_mutex); unlock_kernel(); } @@ -1614,7 +1643,7 @@ static ssize_t tty_read(struct file * file, char __user * buf, size_t count, struct tty_ldisc *ld; tty = (struct tty_struct *)file->private_data; - inode = file->f_dentry->d_inode; + inode = file->f_path.dentry->d_inode; if (tty_paranoia_check(tty, inode, "tty_read")) return -EIO; if (!tty || (test_bit(TTY_IO_ERROR, &tty->flags))) @@ -1717,7 +1746,7 @@ static inline ssize_t do_tty_write( cond_resched(); } if (written) { - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; inode->i_mtime = current_fs_time(inode->i_sb); ret = written; } @@ -1748,7 +1777,7 @@ static ssize_t tty_write(struct file * file, const char __user * buf, size_t cou loff_t *ppos) { struct tty_struct * tty; - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; ssize_t ret; struct tty_ldisc *ld; @@ -1855,8 +1884,8 @@ static int init_dev(struct tty_driver *driver, int idx, struct tty_struct **ret_tty) { struct tty_struct *tty, *o_tty; - struct termios *tp, **tp_loc, *o_tp, **o_tp_loc; - struct termios *ltp, **ltp_loc, *o_ltp, **o_ltp_loc; + struct ktermios *tp, **tp_loc, *o_tp, **o_tp_loc; + struct ktermios *ltp, **ltp_loc, *o_ltp, **o_ltp_loc; int retval = 0; /* check whether we're reopening an existing tty */ @@ -1903,7 +1932,7 @@ static int init_dev(struct tty_driver *driver, int idx, } if (!*tp_loc) { - tp = (struct termios *) kmalloc(sizeof(struct termios), + tp = (struct ktermios *) kmalloc(sizeof(struct ktermios), GFP_KERNEL); if (!tp) goto free_mem_out; @@ -1911,11 +1940,11 @@ static int init_dev(struct tty_driver *driver, int idx, } if (!*ltp_loc) { - ltp = (struct termios *) kmalloc(sizeof(struct termios), + ltp = (struct ktermios *) kmalloc(sizeof(struct ktermios), GFP_KERNEL); if (!ltp) goto free_mem_out; - memset(ltp, 0, sizeof(struct termios)); + memset(ltp, 0, sizeof(struct ktermios)); } if (driver->type == TTY_DRIVER_TYPE_PTY) { @@ -1936,19 +1965,19 @@ static int init_dev(struct tty_driver *driver, int idx, } if (!*o_tp_loc) { - o_tp = (struct termios *) - kmalloc(sizeof(struct termios), GFP_KERNEL); + o_tp = (struct ktermios *) + kmalloc(sizeof(struct ktermios), GFP_KERNEL); if (!o_tp) goto free_mem_out; *o_tp = driver->other->init_termios; } if (!*o_ltp_loc) { - o_ltp = (struct termios *) - kmalloc(sizeof(struct termios), GFP_KERNEL); + o_ltp = (struct ktermios *) + kmalloc(sizeof(struct ktermios), GFP_KERNEL); if (!o_ltp) goto free_mem_out; - memset(o_ltp, 0, sizeof(struct termios)); + memset(o_ltp, 0, sizeof(struct ktermios)); } /* @@ -1987,6 +2016,9 @@ static int init_dev(struct tty_driver *driver, int idx, *ltp_loc = ltp; tty->termios = *tp_loc; tty->termios_locked = *ltp_loc; + /* Compatibility until drivers always set this */ + tty->termios->c_ispeed = tty_termios_input_baud_rate(tty->termios); + tty->termios->c_ospeed = tty_termios_baud_rate(tty->termios); driver->refcount++; tty->count++; @@ -2089,7 +2121,7 @@ static int init_dev(struct tty_driver *driver, int idx, static void release_mem(struct tty_struct *tty, int idx) { struct tty_struct *o_tty; - struct termios *tp; + struct ktermios *tp; int devpts = tty->driver->flags & TTY_DRIVER_DEVPTS_MEM; if ((o_tty = tty->link) != NULL) { @@ -2155,7 +2187,7 @@ static void release_dev(struct file * filp) unsigned long flags; tty = (struct tty_struct *)filp->private_data; - if (tty_paranoia_check(tty, filp->f_dentry->d_inode, "release_dev")) + if (tty_paranoia_check(tty, filp->f_path.dentry->d_inode, "release_dev")) return; check_tty_count(tty, "release_dev"); @@ -2336,16 +2368,10 @@ static void release_dev(struct file * filp) * tty. */ if (tty_closing || o_tty_closing) { - struct task_struct *p; - read_lock(&tasklist_lock); - do_each_task_pid(tty->session, PIDTYPE_SID, p) { - p->signal->tty = NULL; - } while_each_task_pid(tty->session, PIDTYPE_SID, p); + session_clear_tty(tty->session); if (o_tty) - do_each_task_pid(o_tty->session, PIDTYPE_SID, p) { - p->signal->tty = NULL; - } while_each_task_pid(o_tty->session, PIDTYPE_SID, p); + session_clear_tty(o_tty->session); read_unlock(&tasklist_lock); } @@ -2442,9 +2468,9 @@ static void release_dev(struct file * filp) * The termios state of a pty is reset on first open so that * settings don't persist across reuse. * - * Locking: tty_mutex protects current->signal->tty, get_tty_driver and - * init_dev work. tty->count should protect the rest. - * task_lock is held to update task details for sessions + * Locking: tty_mutex protects tty, get_tty_driver and init_dev work. + * tty->count should protect the rest. + * ->siglock protects ->signal/->sighand */ static int tty_open(struct inode * inode, struct file * filp) @@ -2466,12 +2492,13 @@ static int tty_open(struct inode * inode, struct file * filp) mutex_lock(&tty_mutex); if (device == MKDEV(TTYAUX_MAJOR,0)) { - if (!current->signal->tty) { + tty = get_current_tty(); + if (!tty) { mutex_unlock(&tty_mutex); return -ENXIO; } - driver = current->signal->tty->driver; - index = current->signal->tty->index; + driver = tty->driver; + index = tty->index; filp->f_flags |= O_NONBLOCK; /* Don't let /dev/tty block */ /* noctty = 1; */ goto got_driver; @@ -2546,17 +2573,16 @@ static int tty_open(struct inode * inode, struct file * filp) filp->f_op = &tty_fops; goto retry_open; } + + mutex_lock(&tty_mutex); + spin_lock_irq(¤t->sighand->siglock); if (!noctty && current->signal->leader && !current->signal->tty && - tty->session == 0) { - task_lock(current); - current->signal->tty = tty; - task_unlock(current); - current->signal->tty_old_pgrp = 0; - tty->session = current->signal->session; - tty->pgrp = process_group(current); - } + tty->session == 0) + __proc_set_tty(current, tty); + spin_unlock_irq(¤t->sighand->siglock); + mutex_unlock(&tty_mutex); return 0; } @@ -2671,7 +2697,7 @@ static unsigned int tty_poll(struct file * filp, poll_table * wait) int ret = 0; tty = (struct tty_struct *)filp->private_data; - if (tty_paranoia_check(tty, filp->f_dentry->d_inode, "tty_poll")) + if (tty_paranoia_check(tty, filp->f_path.dentry->d_inode, "tty_poll")) return 0; ld = tty_ldisc_ref_wait(tty); @@ -2687,7 +2713,7 @@ static int tty_fasync(int fd, struct file * filp, int on) int retval; tty = (struct tty_struct *)filp->private_data; - if (tty_paranoia_check(tty, filp->f_dentry->d_inode, "tty_fasync")) + if (tty_paranoia_check(tty, filp->f_path.dentry->d_inode, "tty_fasync")) return 0; retval = fasync_helper(fd, filp, on, &tty->fasync); @@ -2746,7 +2772,7 @@ static int tiocsti(struct tty_struct *tty, char __user *p) * * Copies the kernel idea of the window size into the user buffer. * - * Locking: tty->termios_sem is taken to ensure the winsize data + * Locking: tty->termios_mutex is taken to ensure the winsize data * is consistent. */ @@ -2773,8 +2799,8 @@ static int tiocgwinsz(struct tty_struct *tty, struct winsize __user * arg) * Locking: * Called function use the console_sem is used to ensure we do * not try and resize the console twice at once. - * The tty->termios_sem is used to ensure we don't double - * resize and get confused. Lock order - tty->termios.sem before + * The tty->termios_mutex is used to ensure we don't double + * resize and get confused. Lock order - tty->termios_mutex before * console sem */ @@ -2879,25 +2905,28 @@ static int fionbio(struct file *file, int __user *p) * leader to set this tty as the controlling tty for the session. * * Locking: - * Takes tasklist lock internally to walk sessions - * Takes task_lock() when updating signal->tty * Takes tty_mutex() to protect tty instance - * + * Takes tasklist_lock internally to walk sessions + * Takes ->siglock() when updating signal->tty */ static int tiocsctty(struct tty_struct *tty, int arg) { - struct task_struct *p; - + int ret = 0; if (current->signal->leader && - (current->signal->session == tty->session)) - return 0; + (process_session(current) == tty->session)) + return ret; + + mutex_lock(&tty_mutex); /* * The process must be a session leader and * not have a controlling tty already. */ - if (!current->signal->leader || current->signal->tty) - return -EPERM; + if (!current->signal->leader || current->signal->tty) { + ret = -EPERM; + goto unlock; + } + if (tty->session > 0) { /* * This tty is already the controlling @@ -2907,24 +2936,18 @@ static int tiocsctty(struct tty_struct *tty, int arg) /* * Steal it away */ - read_lock(&tasklist_lock); - do_each_task_pid(tty->session, PIDTYPE_SID, p) { - p->signal->tty = NULL; - } while_each_task_pid(tty->session, PIDTYPE_SID, p); + session_clear_tty(tty->session); read_unlock(&tasklist_lock); - } else - return -EPERM; + } else { + ret = -EPERM; + goto unlock; + } } - mutex_lock(&tty_mutex); - task_lock(current); - current->signal->tty = tty; - task_unlock(current); + proc_set_tty(current, tty); +unlock: mutex_unlock(&tty_mutex); - current->signal->tty_old_pgrp = 0; - tty->session = current->signal->session; - tty->pgrp = process_group(current); - return 0; + return ret; } /** @@ -2936,7 +2959,7 @@ static int tiocsctty(struct tty_struct *tty, int arg) * Obtain the process group of the tty. If there is no process group * return an error. * - * Locking: none. Reference to ->signal->tty is safe. + * Locking: none. Reference to current->signal->tty is safe. */ static int tiocgpgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p) @@ -2973,13 +2996,13 @@ static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t return retval; if (!current->signal->tty || (current->signal->tty != real_tty) || - (real_tty->session != current->signal->session)) + (real_tty->session != process_session(current))) return -ENOTTY; if (get_user(pgrp, p)) return -EFAULT; if (pgrp < 0) return -EINVAL; - if (session_of_pgrp(pgrp) != current->signal->session) + if (session_of_pgrp(pgrp) != process_session(current)) return -EPERM; real_tty->pgrp = pgrp; return 0; @@ -2994,7 +3017,7 @@ static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t * Obtain the session id of the tty. If there is no session * return an error. * - * Locking: none. Reference to ->signal->tty is safe. + * Locking: none. Reference to current->signal->tty is safe. */ static int tiocgsid(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p) @@ -3213,14 +3236,11 @@ int tty_ioctl(struct inode * inode, struct file * file, clear_bit(TTY_EXCLUSIVE, &tty->flags); return 0; case TIOCNOTTY: - /* FIXME: taks lock or tty_mutex ? */ if (current->signal->tty != tty) return -ENOTTY; if (current->signal->leader) disassociate_ctty(0); - task_lock(current); - current->signal->tty = NULL; - task_unlock(current); + proc_clear_tty(current); return 0; case TIOCSCTTY: return tiocsctty(tty, arg); @@ -3304,12 +3324,13 @@ int tty_ioctl(struct inode * inode, struct file * file, * Nasty bug: do_SAK is being called in interrupt context. This can * deadlock. We punt it up to process context. AKPM - 16Mar2001 */ -static void __do_SAK(void *arg) +static void __do_SAK(struct work_struct *work) { + struct tty_struct *tty = + container_of(work, struct tty_struct, SAK_work); #ifdef TTY_SOFT_SAK tty_hangup(tty); #else - struct tty_struct *tty = arg; struct task_struct *g, *p; int session; int i; @@ -3319,7 +3340,7 @@ static void __do_SAK(void *arg) if (!tty) return; - session = tty->session; + session = tty->session; /* We don't want an ldisc switch during this */ disc = tty_ldisc_ref(tty); @@ -3334,7 +3355,7 @@ static void __do_SAK(void *arg) /* Kill the entire session */ do_each_task_pid(session, PIDTYPE_SID, p) { printk(KERN_NOTICE "SAK: killed process %d" - " (%s): p->signal->session==tty->session\n", + " (%s): process_session(p)==tty->session\n", p->pid, p->comm); send_sig(SIGKILL, p, 1); } while_each_task_pid(session, PIDTYPE_SID, p); @@ -3344,7 +3365,7 @@ static void __do_SAK(void *arg) do_each_thread(g, p) { if (p->signal->tty == tty) { printk(KERN_NOTICE "SAK: killed process %d" - " (%s): p->signal->session==tty->session\n", + " (%s): process_session(p)==tty->session\n", p->pid, p->comm); send_sig(SIGKILL, p, 1); continue; @@ -3388,7 +3409,7 @@ void do_SAK(struct tty_struct *tty) { if (!tty) return; - PREPARE_WORK(&tty->SAK_work, __do_SAK, tty); + PREPARE_WORK(&tty->SAK_work, __do_SAK); schedule_work(&tty->SAK_work); } @@ -3396,7 +3417,7 @@ EXPORT_SYMBOL(do_SAK); /** * flush_to_ldisc - * @private_: tty structure passed from work queue. + * @work: tty structure passed from work queue. * * This routine is called out of the software interrupt to flush data * from the buffer chain to the line discipline. @@ -3406,9 +3427,10 @@ EXPORT_SYMBOL(do_SAK); * receive_buf method is single threaded for each tty instance. */ -static void flush_to_ldisc(void *private_) +static void flush_to_ldisc(struct work_struct *work) { - struct tty_struct *tty = (struct tty_struct *) private_; + struct tty_struct *tty = + container_of(work, struct tty_struct, buf.work.work); unsigned long flags; struct tty_ldisc *disc; struct tty_buffer *tbuf, *head; @@ -3453,84 +3475,6 @@ static void flush_to_ldisc(void *private_) tty_ldisc_deref(disc); } -/* - * Routine which returns the baud rate of the tty - * - * Note that the baud_table needs to be kept in sync with the - * include/asm/termbits.h file. - */ -static int baud_table[] = { - 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, - 9600, 19200, 38400, 57600, 115200, 230400, 460800, -#ifdef __sparc__ - 76800, 153600, 307200, 614400, 921600 -#else - 500000, 576000, 921600, 1000000, 1152000, 1500000, 2000000, - 2500000, 3000000, 3500000, 4000000 -#endif -}; - -static int n_baud_table = ARRAY_SIZE(baud_table); - -/** - * tty_termios_baud_rate - * @termios: termios structure - * - * Convert termios baud rate data into a speed. This should be called - * with the termios lock held if this termios is a terminal termios - * structure. May change the termios data. - * - * Locking: none - */ - -int tty_termios_baud_rate(struct termios *termios) -{ - unsigned int cbaud; - - cbaud = termios->c_cflag & CBAUD; - - if (cbaud & CBAUDEX) { - cbaud &= ~CBAUDEX; - - if (cbaud < 1 || cbaud + 15 > n_baud_table) - termios->c_cflag &= ~CBAUDEX; - else - cbaud += 15; - } - return baud_table[cbaud]; -} - -EXPORT_SYMBOL(tty_termios_baud_rate); - -/** - * tty_get_baud_rate - get tty bit rates - * @tty: tty to query - * - * Returns the baud rate as an integer for this terminal. The - * termios lock must be held by the caller and the terminal bit - * flags may be updated. - * - * Locking: none - */ - -int tty_get_baud_rate(struct tty_struct *tty) -{ - int baud = tty_termios_baud_rate(tty->termios); - - if (baud == 38400 && tty->alt_speed) { - if (!tty->warned) { - printk(KERN_WARNING "Use of setserial/setrocket to " - "set SPD_* flags is deprecated\n"); - tty->warned = 1; - } - baud = tty->alt_speed; - } - - return baud; -} - -EXPORT_SYMBOL(tty_get_baud_rate); - /** * tty_flip_buffer_push - terminal * @tty: tty to push @@ -3553,7 +3497,7 @@ void tty_flip_buffer_push(struct tty_struct *tty) spin_unlock_irqrestore(&tty->buf.lock, flags); if (tty->low_latency) - flush_to_ldisc((void *) tty); + flush_to_ldisc(&tty->buf.work.work); else schedule_delayed_work(&tty->buf.work, 1); } @@ -3580,17 +3524,17 @@ static void initialize_tty_struct(struct tty_struct *tty) tty->overrun_time = jiffies; tty->buf.head = tty->buf.tail = NULL; tty_buffer_init(tty); - INIT_WORK(&tty->buf.work, flush_to_ldisc, tty); + INIT_DELAYED_WORK(&tty->buf.work, flush_to_ldisc); init_MUTEX(&tty->buf.pty_sem); mutex_init(&tty->termios_mutex); init_waitqueue_head(&tty->write_wait); init_waitqueue_head(&tty->read_wait); - INIT_WORK(&tty->hangup_work, do_tty_hangup, tty); + INIT_WORK(&tty->hangup_work, do_tty_hangup); mutex_init(&tty->atomic_read_lock); mutex_init(&tty->atomic_write_lock); spin_lock_init(&tty->read_lock); INIT_LIST_HEAD(&tty->tty_files); - INIT_WORK(&tty->SAK_work, NULL, NULL); + INIT_WORK(&tty->SAK_work, NULL); } /* @@ -3753,8 +3697,8 @@ int tty_register_driver(struct tty_driver *driver) if (p) { driver->ttys = (struct tty_struct **)p; - driver->termios = (struct termios **)(p + driver->num); - driver->termios_locked = (struct termios **)(p + driver->num * 2); + driver->termios = (struct ktermios **)(p + driver->num); + driver->termios_locked = (struct ktermios **)(p + driver->num * 2); } else { driver->ttys = NULL; driver->termios = NULL; @@ -3793,7 +3737,7 @@ EXPORT_SYMBOL(tty_register_driver); int tty_unregister_driver(struct tty_driver *driver) { int i; - struct termios *tp; + struct ktermios *tp; void *p; if (driver->refcount) @@ -3831,9 +3775,52 @@ int tty_unregister_driver(struct tty_driver *driver) cdev_del(&driver->cdev); return 0; } - EXPORT_SYMBOL(tty_unregister_driver); +dev_t tty_devnum(struct tty_struct *tty) +{ + return MKDEV(tty->driver->major, tty->driver->minor_start) + tty->index; +} +EXPORT_SYMBOL(tty_devnum); + +void proc_clear_tty(struct task_struct *p) +{ + spin_lock_irq(&p->sighand->siglock); + p->signal->tty = NULL; + spin_unlock_irq(&p->sighand->siglock); +} +EXPORT_SYMBOL(proc_clear_tty); + +void __proc_set_tty(struct task_struct *tsk, struct tty_struct *tty) +{ + if (tty) { + tty->session = process_session(tsk); + tty->pgrp = process_group(tsk); + } + tsk->signal->tty = tty; + tsk->signal->tty_old_pgrp = 0; +} + +void proc_set_tty(struct task_struct *tsk, struct tty_struct *tty) +{ + spin_lock_irq(&tsk->sighand->siglock); + __proc_set_tty(tsk, tty); + spin_unlock_irq(&tsk->sighand->siglock); +} + +struct tty_struct *get_current_tty(void) +{ + struct tty_struct *tty; + WARN_ON_ONCE(!mutex_is_locked(&tty_mutex)); + tty = current->signal->tty; + /* + * session->tty can be changed/cleared from under us, make sure we + * issue the load. The obtained pointer, when not NULL, is valid as + * long as we hold tty_mutex. + */ + barrier(); + return tty; +} /* * Initialize the console device. This is called *early*, so diff --git a/trunk/drivers/char/tty_ioctl.c b/trunk/drivers/char/tty_ioctl.c index 3b6fa7b0be8b..dee47f40c6a3 100644 --- a/trunk/drivers/char/tty_ioctl.c +++ b/trunk/drivers/char/tty_ioctl.c @@ -36,6 +36,7 @@ #define TERMIOS_FLUSH 1 #define TERMIOS_WAIT 2 #define TERMIOS_TERMIO 4 +#define TERMIOS_OLD 8 /** @@ -84,9 +85,9 @@ void tty_wait_until_sent(struct tty_struct * tty, long timeout) EXPORT_SYMBOL(tty_wait_until_sent); -static void unset_locked_termios(struct termios *termios, - struct termios *old, - struct termios *locked) +static void unset_locked_termios(struct ktermios *termios, + struct ktermios *old, + struct ktermios *locked) { int i; @@ -105,8 +106,204 @@ static void unset_locked_termios(struct termios *termios, for (i=0; i < NCCS; i++) termios->c_cc[i] = locked->c_cc[i] ? old->c_cc[i] : termios->c_cc[i]; + /* FIXME: What should we do for i/ospeed */ } +/* + * Routine which returns the baud rate of the tty + * + * Note that the baud_table needs to be kept in sync with the + * include/asm/termbits.h file. + */ +static const speed_t baud_table[] = { + 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, + 9600, 19200, 38400, 57600, 115200, 230400, 460800, +#ifdef __sparc__ + 76800, 153600, 307200, 614400, 921600 +#else + 500000, 576000, 921600, 1000000, 1152000, 1500000, 2000000, + 2500000, 3000000, 3500000, 4000000 +#endif +}; + +#ifndef __sparc__ +static const tcflag_t baud_bits[] = { + B0, B50, B75, B110, B134, B150, B200, B300, B600, + B1200, B1800, B2400, B4800, B9600, B19200, B38400, + B57600, B115200, B230400, B460800, B500000, B576000, + B921600, B1000000, B1152000, B1500000, B2000000, B2500000, + B3000000, B3500000, B4000000 +}; +#else +static const tcflag_t baud_bits[] = { + B0, B50, B75, B110, B134, B150, B200, B300, B600, + B1200, B1800, B2400, B4800, B9600, B19200, B38400, + B57600, B115200, B230400, B460800, B76800, B153600, + B307200, B614400, B921600 +}; +#endif + +static int n_baud_table = ARRAY_SIZE(baud_table); + +/** + * tty_termios_baud_rate + * @termios: termios structure + * + * Convert termios baud rate data into a speed. This should be called + * with the termios lock held if this termios is a terminal termios + * structure. May change the termios data. Device drivers can call this + * function but should use ->c_[io]speed directly as they are updated. + * + * Locking: none + */ + +speed_t tty_termios_baud_rate(struct ktermios *termios) +{ + unsigned int cbaud; + + cbaud = termios->c_cflag & CBAUD; + +#ifdef BOTHER + /* Magic token for arbitary speed via c_ispeed/c_ospeed */ + if (cbaud == BOTHER) + return termios->c_ospeed; +#endif + if (cbaud & CBAUDEX) { + cbaud &= ~CBAUDEX; + + if (cbaud < 1 || cbaud + 15 > n_baud_table) + termios->c_cflag &= ~CBAUDEX; + else + cbaud += 15; + } + return baud_table[cbaud]; +} + +EXPORT_SYMBOL(tty_termios_baud_rate); + +/** + * tty_termios_input_baud_rate + * @termios: termios structure + * + * Convert termios baud rate data into a speed. This should be called + * with the termios lock held if this termios is a terminal termios + * structure. May change the termios data. Device drivers can call this + * function but should use ->c_[io]speed directly as they are updated. + * + * Locking: none + */ + +speed_t tty_termios_input_baud_rate(struct ktermios *termios) +{ +#ifdef IBSHIFT + unsigned int cbaud = (termios->c_cflag >> IBSHIFT) & CBAUD; + + if (cbaud == B0) + return tty_termios_baud_rate(termios); + + /* Magic token for arbitary speed via c_ispeed*/ + if (cbaud == BOTHER) + return termios->c_ispeed; + + if (cbaud & CBAUDEX) { + cbaud &= ~CBAUDEX; + + if (cbaud < 1 || cbaud + 15 > n_baud_table) + termios->c_cflag &= ~(CBAUDEX << IBSHIFT); + else + cbaud += 15; + } + return baud_table[cbaud]; +#else + return tty_termios_baud_rate(termios); +#endif +} + +EXPORT_SYMBOL(tty_termios_input_baud_rate); + +#ifdef BOTHER + +/** + * tty_termios_encode_baud_rate + * @termios: termios structure + * @ispeed: input speed + * @ospeed: output speed + * + * Encode the speeds set into the passed termios structure. This is + * used as a library helper for drivers os that they can report back + * the actual speed selected when it differs from the speed requested + * + * For now input and output speed must agree. + * + * Locking: Caller should hold termios lock. This is already held + * when calling this function from the driver termios handler. + */ + +void tty_termios_encode_baud_rate(struct ktermios *termios, speed_t ibaud, speed_t obaud) +{ + int i = 0; + int ifound = 0, ofound = 0; + + termios->c_ispeed = ibaud; + termios->c_ospeed = obaud; + + termios->c_cflag &= ~CBAUD; + /* Identical speed means no input encoding (ie B0 << IBSHIFT)*/ + if (termios->c_ispeed == termios->c_ospeed) + ifound = 1; + + do { + if (obaud == baud_table[i]) { + termios->c_cflag |= baud_bits[i]; + ofound = 1; + /* So that if ibaud == obaud we don't set it */ + continue; + } + if (ibaud == baud_table[i]) { + termios->c_cflag |= (baud_bits[i] << IBSHIFT); + ifound = 1; + } + } + while(++i < n_baud_table); + if (!ofound) + termios->c_cflag |= BOTHER; + if (!ifound) + termios->c_cflag |= (BOTHER << IBSHIFT); +} + +EXPORT_SYMBOL_GPL(tty_termios_encode_baud_rate); + +#endif + +/** + * tty_get_baud_rate - get tty bit rates + * @tty: tty to query + * + * Returns the baud rate as an integer for this terminal. The + * termios lock must be held by the caller and the terminal bit + * flags may be updated. + * + * Locking: none + */ + +speed_t tty_get_baud_rate(struct tty_struct *tty) +{ + speed_t baud = tty_termios_baud_rate(tty->termios); + + if (baud == 38400 && tty->alt_speed) { + if (!tty->warned) { + printk(KERN_WARNING "Use of setserial/setrocket to " + "set SPD_* flags is deprecated\n"); + tty->warned = 1; + } + baud = tty->alt_speed; + } + + return baud; +} + +EXPORT_SYMBOL(tty_get_baud_rate); + /** * change_termios - update termios values * @tty: tty to update @@ -119,10 +316,10 @@ static void unset_locked_termios(struct termios *termios, * Locking: termios_sem */ -static void change_termios(struct tty_struct * tty, struct termios * new_termios) +static void change_termios(struct tty_struct * tty, struct ktermios * new_termios) { int canon_change; - struct termios old_termios = *tty->termios; + struct ktermios old_termios = *tty->termios; struct tty_ldisc *ld; /* @@ -195,23 +392,39 @@ static void change_termios(struct tty_struct * tty, struct termios * new_termios static int set_termios(struct tty_struct * tty, void __user *arg, int opt) { - struct termios tmp_termios; + struct ktermios tmp_termios; struct tty_ldisc *ld; int retval = tty_check_change(tty); if (retval) return retval; + memcpy(&tmp_termios, tty->termios, sizeof(struct ktermios)); + if (opt & TERMIOS_TERMIO) { - memcpy(&tmp_termios, tty->termios, sizeof(struct termios)); if (user_termio_to_kernel_termios(&tmp_termios, (struct termio __user *)arg)) return -EFAULT; +#ifdef TCGETS2 + } else if (opt & TERMIOS_OLD) { + if (user_termios_to_kernel_termios_1(&tmp_termios, + (struct termios __user *)arg)) + return -EFAULT; } else { if (user_termios_to_kernel_termios(&tmp_termios, - (struct termios __user *)arg)) + (struct termios2 __user *)arg)) return -EFAULT; } +#else + } else if (user_termios_to_kernel_termios(&tmp_termios, + (struct termios __user *)arg)) + return -EFAULT; +#endif + + /* If old style Bfoo values are used then load c_ispeed/c_ospeed with the real speed + so its unconditionally usable */ + tmp_termios.c_ispeed = tty_termios_input_baud_rate(&tmp_termios); + tmp_termios.c_ospeed = tty_termios_baud_rate(&tmp_termios); ld = tty_ldisc_ref(tty); @@ -286,8 +499,8 @@ static int get_sgttyb(struct tty_struct * tty, struct sgttyb __user * sgttyb) struct sgttyb tmp; mutex_lock(&tty->termios_mutex); - tmp.sg_ispeed = 0; - tmp.sg_ospeed = 0; + tmp.sg_ispeed = tty->termios->c_ispeed; + tmp.sg_ospeed = tty->termios->c_ospeed; tmp.sg_erase = tty->termios->c_cc[VERASE]; tmp.sg_kill = tty->termios->c_cc[VKILL]; tmp.sg_flags = get_sgflags(tty); @@ -296,7 +509,7 @@ static int get_sgttyb(struct tty_struct * tty, struct sgttyb __user * sgttyb) return copy_to_user(sgttyb, &tmp, sizeof(tmp)) ? -EFAULT : 0; } -static void set_sgflags(struct termios * termios, int flags) +static void set_sgflags(struct ktermios * termios, int flags) { termios->c_iflag = ICRNL | IXON; termios->c_oflag = 0; @@ -337,7 +550,7 @@ static int set_sgttyb(struct tty_struct * tty, struct sgttyb __user * sgttyb) { int retval; struct sgttyb tmp; - struct termios termios; + struct ktermios termios; retval = tty_check_change(tty); if (retval) @@ -351,6 +564,10 @@ static int set_sgttyb(struct tty_struct * tty, struct sgttyb __user * sgttyb) termios.c_cc[VERASE] = tmp.sg_erase; termios.c_cc[VKILL] = tmp.sg_kill; set_sgflags(&termios, tmp.sg_flags); + /* Try and encode into Bfoo format */ +#ifdef BOTHER + tty_termios_encode_baud_rate(&termios, termios.c_ispeed, termios.c_ospeed); +#endif mutex_unlock(&tty->termios_mutex); change_termios(tty, &termios); return 0; @@ -481,16 +698,33 @@ int n_tty_ioctl(struct tty_struct * tty, struct file * file, case TIOCSLTC: return set_ltchars(real_tty, p); #endif + case TCSETSF: + return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT | TERMIOS_OLD); + case TCSETSW: + return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_OLD); + case TCSETS: + return set_termios(real_tty, p, TERMIOS_OLD); +#ifndef TCGETS2 case TCGETS: if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios)) return -EFAULT; return 0; - case TCSETSF: +#else + case TCGETS: + if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios)) + return -EFAULT; + return 0; + case TCGETS2: + if (kernel_termios_to_user_termios((struct termios2 __user *)arg, real_tty->termios)) + return -EFAULT; + return 0; + case TCSETSF2: return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT); - case TCSETSW: + case TCSETSW2: return set_termios(real_tty, p, TERMIOS_WAIT); - case TCSETS: + case TCSETS2: return set_termios(real_tty, p, 0); +#endif case TCGETA: return get_termio(real_tty, p); case TCSETAF: diff --git a/trunk/drivers/char/vc_screen.c b/trunk/drivers/char/vc_screen.c index f442b574b44a..26776517f04c 100644 --- a/trunk/drivers/char/vc_screen.c +++ b/trunk/drivers/char/vc_screen.c @@ -72,7 +72,7 @@ static loff_t vcs_lseek(struct file *file, loff_t offset, int orig) int size; down(&con_buf_sem); - size = vcs_size(file->f_dentry->d_inode); + size = vcs_size(file->f_path.dentry->d_inode); switch (orig) { default: up(&con_buf_sem); @@ -98,7 +98,7 @@ static loff_t vcs_lseek(struct file *file, loff_t offset, int orig) static ssize_t vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; unsigned int currcons = iminor(inode); struct vc_data *vc; long pos; @@ -271,7 +271,7 @@ vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) static ssize_t vcs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; unsigned int currcons = iminor(inode); struct vc_data *vc; long pos; diff --git a/trunk/drivers/char/viotape.c b/trunk/drivers/char/viotape.c index 73c78bf75d7f..94d79cb8ce8d 100644 --- a/trunk/drivers/char/viotape.c +++ b/trunk/drivers/char/viotape.c @@ -442,7 +442,7 @@ static ssize_t viotap_write(struct file *file, const char *buf, if (op == NULL) return -ENOMEM; - get_dev_info(file->f_dentry->d_inode, &devi); + get_dev_info(file->f_path.dentry->d_inode, &devi); /* * We need to make sure we can send a request. We use @@ -532,7 +532,7 @@ static ssize_t viotap_read(struct file *file, char *buf, size_t count, if (op == NULL) return -ENOMEM; - get_dev_info(file->f_dentry->d_inode, &devi); + get_dev_info(file->f_path.dentry->d_inode, &devi); /* * We need to make sure we can send a request. We use @@ -612,7 +612,7 @@ static int viotap_ioctl(struct inode *inode, struct file *file, if (op == NULL) return -ENOMEM; - get_dev_info(file->f_dentry->d_inode, &devi); + get_dev_info(file->f_path.dentry->d_inode, &devi); down(&reqSem); @@ -777,7 +777,7 @@ static int viotap_open(struct inode *inode, struct file *file) if (op == NULL) return -ENOMEM; - get_dev_info(file->f_dentry->d_inode, &devi); + get_dev_info(file->f_path.dentry->d_inode, &devi); /* Note: We currently only support one mode! */ if ((devi.devno >= viotape_numdev) || (devi.mode)) { @@ -822,7 +822,7 @@ static int viotap_release(struct inode *inode, struct file *file) return -ENOMEM; init_completion(&op->com); - get_dev_info(file->f_dentry->d_inode, &devi); + get_dev_info(file->f_path.dentry->d_inode, &devi); if (devi.devno >= viotape_numdev) { ret = -ENODEV; diff --git a/trunk/drivers/char/vme_scc.c b/trunk/drivers/char/vme_scc.c index d0b94dd1af6d..e01317cb1a0e 100644 --- a/trunk/drivers/char/vme_scc.c +++ b/trunk/drivers/char/vme_scc.c @@ -153,6 +153,8 @@ static int scc_init_drivers(void) scc_driver->init_termios = tty_std_termios; scc_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; + scc_driver->init_termios.c_ispeed = 9600; + scc_driver->init_termios.c_ospeed = 9600; scc_driver->flags = TTY_DRIVER_REAL_RAW; tty_set_operations(scc_driver, &scc_ops); diff --git a/trunk/drivers/char/vr41xx_giu.c b/trunk/drivers/char/vr41xx_giu.c index 8e7949305171..a744dad9cf45 100644 --- a/trunk/drivers/char/vr41xx_giu.c +++ b/trunk/drivers/char/vr41xx_giu.c @@ -506,7 +506,7 @@ static ssize_t gpio_read(struct file *file, char __user *buf, size_t len, unsigned int pin; char value = '0'; - pin = iminor(file->f_dentry->d_inode); + pin = iminor(file->f_path.dentry->d_inode); if (pin >= giu_nr_pins) return -EBADF; @@ -530,7 +530,7 @@ static ssize_t gpio_write(struct file *file, const char __user *data, char c; int retval = 0; - pin = iminor(file->f_dentry->d_inode); + pin = iminor(file->f_path.dentry->d_inode); if (pin >= giu_nr_pins) return -EBADF; diff --git a/trunk/drivers/char/vt.c b/trunk/drivers/char/vt.c index 87587b4385ab..a8239dac994f 100644 --- a/trunk/drivers/char/vt.c +++ b/trunk/drivers/char/vt.c @@ -152,10 +152,10 @@ static void gotoxy(struct vc_data *vc, int new_x, int new_y); static void save_cur(struct vc_data *vc); static void reset_terminal(struct vc_data *vc, int do_clear); static void con_flush_chars(struct tty_struct *tty); -static void set_vesa_blanking(char __user *p); +static int set_vesa_blanking(char __user *p); static void set_cursor(struct vc_data *vc); static void hide_cursor(struct vc_data *vc); -static void console_callback(void *ignored); +static void console_callback(struct work_struct *ignored); static void blank_screen_t(unsigned long dummy); static void set_palette(struct vc_data *vc); @@ -174,7 +174,7 @@ static int vesa_blank_mode; /* 0:none 1:suspendV 2:suspendH 3:powerdown */ static int blankinterval = 10*60*HZ; static int vesa_off_interval; -static DECLARE_WORK(console_work, console_callback, NULL); +static DECLARE_WORK(console_work, console_callback); /* * fg_console is the current virtual console, @@ -2154,7 +2154,7 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co * with other console code and prevention of re-entrancy is * ensured with console_sem. */ -static void console_callback(void *ignored) +static void console_callback(struct work_struct *ignored) { acquire_console_sem(); @@ -2369,7 +2369,7 @@ int tioclinux(struct tty_struct *tty, unsigned long arg) ret = __put_user(data, p); break; case TIOCL_SETVESABLANK: - set_vesa_blanking(p); + ret = set_vesa_blanking(p); break; case TIOCL_GETKMSGREDIRECT: data = kmsg_redirect; @@ -3313,11 +3313,15 @@ postcore_initcall(vtconsole_class_init); * Screen blanking */ -static void set_vesa_blanking(char __user *p) +static int set_vesa_blanking(char __user *p) { - unsigned int mode; - get_user(mode, p + 1); - vesa_blank_mode = (mode < 4) ? mode : 0; + unsigned int mode; + + if (get_user(mode, p + 1)) + return -EFAULT; + + vesa_blank_mode = (mode < 4) ? mode : 0; + return 0; } void do_blank_screen(int entering_gfx) diff --git a/trunk/drivers/char/watchdog/at91rm9200_wdt.c b/trunk/drivers/char/watchdog/at91rm9200_wdt.c index 4e7a1145e78f..cb86967e2c5f 100644 --- a/trunk/drivers/char/watchdog/at91rm9200_wdt.c +++ b/trunk/drivers/char/watchdog/at91rm9200_wdt.c @@ -21,6 +21,7 @@ #include #include #include +#include #define WDT_DEFAULT_TIME 5 /* seconds */ diff --git a/trunk/drivers/char/watchdog/pcwd_usb.c b/trunk/drivers/char/watchdog/pcwd_usb.c index e275dd4a705d..61138726b501 100644 --- a/trunk/drivers/char/watchdog/pcwd_usb.c +++ b/trunk/drivers/char/watchdog/pcwd_usb.c @@ -634,7 +634,7 @@ static int usb_pcwd_probe(struct usb_interface *interface, const struct usb_devi usb_pcwd->intr_size = (le16_to_cpu(endpoint->wMaxPacketSize) > 8 ? le16_to_cpu(endpoint->wMaxPacketSize) : 8); /* set up the memory buffer's */ - if (!(usb_pcwd->intr_buffer = usb_buffer_alloc(udev, usb_pcwd->intr_size, SLAB_ATOMIC, &usb_pcwd->intr_dma))) { + if (!(usb_pcwd->intr_buffer = usb_buffer_alloc(udev, usb_pcwd->intr_size, GFP_ATOMIC, &usb_pcwd->intr_dma))) { printk(KERN_ERR PFX "Out of memory\n"); goto error; } diff --git a/trunk/drivers/clocksource/acpi_pm.c b/trunk/drivers/clocksource/acpi_pm.c index 7fcb77a9d011..8ab61ef97b4c 100644 --- a/trunk/drivers/clocksource/acpi_pm.c +++ b/trunk/drivers/clocksource/acpi_pm.c @@ -142,6 +142,39 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_LE, acpi_pm_check_graylist); #endif +#ifndef CONFIG_X86_64 +#include "mach_timer.h" +#define PMTMR_EXPECTED_RATE \ + ((CALIBRATE_LATCH * (PMTMR_TICKS_PER_SEC >> 10)) / (CLOCK_TICK_RATE>>10)) +/* + * Some boards have the PMTMR running way too fast. We check + * the PMTMR rate against PIT channel 2 to catch these cases. + */ +static int verify_pmtmr_rate(void) +{ + u32 value1, value2; + unsigned long count, delta; + + mach_prepare_counter(); + value1 = read_pmtmr(); + mach_countup(&count); + value2 = read_pmtmr(); + delta = (value2 - value1) & ACPI_PM_MASK; + + /* Check that the PMTMR delta is within 5% of what we expect */ + if (delta < (PMTMR_EXPECTED_RATE * 19) / 20 || + delta > (PMTMR_EXPECTED_RATE * 21) / 20) { + printk(KERN_INFO "PM-Timer running at invalid rate: %lu%% " + "of normal - aborting.\n", + 100UL * delta / PMTMR_EXPECTED_RATE); + return -1; + } + + return 0; +} +#else +#define verify_pmtmr_rate() (0) +#endif static int __init init_acpi_pm_clocksource(void) { @@ -173,6 +206,9 @@ static int __init init_acpi_pm_clocksource(void) return -ENODEV; pm_good: + if (verify_pmtmr_rate() != 0) + return -ENODEV; + return clocksource_register(&clocksource_acpi_pm); } diff --git a/trunk/drivers/connector/cn_queue.c b/trunk/drivers/connector/cn_queue.c index 05f8ce2cfb4a..b418b16e910e 100644 --- a/trunk/drivers/connector/cn_queue.c +++ b/trunk/drivers/connector/cn_queue.c @@ -31,9 +31,11 @@ #include #include -void cn_queue_wrapper(void *data) +void cn_queue_wrapper(struct work_struct *work) { - struct cn_callback_data *d = data; + struct cn_callback_entry *cbq = + container_of(work, struct cn_callback_entry, work.work); + struct cn_callback_data *d = &cbq->data; d->callback(d->callback_priv); @@ -57,7 +59,7 @@ static struct cn_callback_entry *cn_queue_alloc_callback_entry(char *name, struc memcpy(&cbq->id.id, id, sizeof(struct cb_id)); cbq->data.callback = callback; - INIT_WORK(&cbq->work, &cn_queue_wrapper, &cbq->data); + INIT_DELAYED_WORK(&cbq->work, &cn_queue_wrapper); return cbq; } diff --git a/trunk/drivers/connector/connector.c b/trunk/drivers/connector/connector.c index b49bacfd8de8..5e7cd45d10ee 100644 --- a/trunk/drivers/connector/connector.c +++ b/trunk/drivers/connector/connector.c @@ -135,40 +135,39 @@ static int cn_call_callback(struct cn_msg *msg, void (*destruct_data)(void *), v spin_lock_bh(&dev->cbdev->queue_lock); list_for_each_entry(__cbq, &dev->cbdev->queue_list, callback_entry) { if (cn_cb_equal(&__cbq->id.id, &msg->id)) { - if (likely(!test_bit(0, &__cbq->work.pending) && + if (likely(!test_bit(WORK_STRUCT_PENDING, + &__cbq->work.work.management) && __cbq->data.ddata == NULL)) { __cbq->data.callback_priv = msg; __cbq->data.ddata = data; __cbq->data.destruct_data = destruct_data; - if (queue_work(dev->cbdev->cn_queue, - &__cbq->work)) + if (queue_delayed_work( + dev->cbdev->cn_queue, + &__cbq->work, 0)) err = 0; } else { - struct work_struct *w; struct cn_callback_data *d; - w = kzalloc(sizeof(*w) + sizeof(*d), GFP_ATOMIC); - if (w) { - d = (struct cn_callback_data *)(w+1); - + __cbq = kzalloc(sizeof(*__cbq), GFP_ATOMIC); + if (__cbq) { + d = &__cbq->data; d->callback_priv = msg; d->callback = __cbq->data.callback; d->ddata = data; d->destruct_data = destruct_data; - d->free = w; + d->free = __cbq; - INIT_LIST_HEAD(&w->entry); - w->pending = 0; - w->func = &cn_queue_wrapper; - w->data = d; - init_timer(&w->timer); + INIT_DELAYED_WORK(&__cbq->work, + &cn_queue_wrapper); - if (queue_work(dev->cbdev->cn_queue, w)) + if (queue_delayed_work( + dev->cbdev->cn_queue, + &__cbq->work, 0)) err = 0; else { - kfree(w); + kfree(__cbq); err = -EINVAL; } } else diff --git a/trunk/drivers/cpufreq/cpufreq.c b/trunk/drivers/cpufreq/cpufreq.c index dd0c2623e27b..47ab42db122a 100644 --- a/trunk/drivers/cpufreq/cpufreq.c +++ b/trunk/drivers/cpufreq/cpufreq.c @@ -42,7 +42,7 @@ static DEFINE_SPINLOCK(cpufreq_driver_lock); /* internal prototypes */ static int __cpufreq_governor(struct cpufreq_policy *policy, unsigned int event); -static void handle_update(void *data); +static void handle_update(struct work_struct *work); /** * Two notifier lists: the "policy" list is involved in the @@ -665,7 +665,7 @@ static int cpufreq_add_dev (struct sys_device * sys_dev) mutex_init(&policy->lock); mutex_lock(&policy->lock); init_completion(&policy->kobj_unregister); - INIT_WORK(&policy->update, handle_update, (void *)(long)cpu); + INIT_WORK(&policy->update, handle_update); /* call driver. From then on the cpufreq must be able * to accept all calls to ->verify and ->setpolicy for this CPU @@ -895,9 +895,11 @@ static int cpufreq_remove_dev (struct sys_device * sys_dev) } -static void handle_update(void *data) +static void handle_update(struct work_struct *work) { - unsigned int cpu = (unsigned int)(long)data; + struct cpufreq_policy *policy = + container_of(work, struct cpufreq_policy, update); + unsigned int cpu = policy->cpu; dprintk("handle_update for cpu %u called\n", cpu); cpufreq_update_policy(cpu); } @@ -1535,7 +1537,6 @@ int cpufreq_update_policy(unsigned int cpu) } EXPORT_SYMBOL(cpufreq_update_policy); -#ifdef CONFIG_HOTPLUG_CPU static int cpufreq_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { @@ -1575,7 +1576,6 @@ static struct notifier_block __cpuinitdata cpufreq_cpu_notifier = { .notifier_call = cpufreq_cpu_callback, }; -#endif /* CONFIG_HOTPLUG_CPU */ /********************************************************************* * REGISTER / UNREGISTER CPUFREQ DRIVER * diff --git a/trunk/drivers/cpufreq/cpufreq_conservative.c b/trunk/drivers/cpufreq/cpufreq_conservative.c index c4c578defabf..5ef5ede5b884 100644 --- a/trunk/drivers/cpufreq/cpufreq_conservative.c +++ b/trunk/drivers/cpufreq/cpufreq_conservative.c @@ -59,7 +59,7 @@ static unsigned int def_sampling_rate; #define MAX_SAMPLING_DOWN_FACTOR (10) #define TRANSITION_LATENCY_LIMIT (10 * 1000) -static void do_dbs_timer(void *data); +static void do_dbs_timer(struct work_struct *work); struct cpu_dbs_info_s { struct cpufreq_policy *cur_policy; @@ -82,7 +82,7 @@ static unsigned int dbs_enable; /* number of CPUs using this policy */ * is recursive for the same process. -Venki */ static DEFINE_MUTEX (dbs_mutex); -static DECLARE_WORK (dbs_work, do_dbs_timer, NULL); +static DECLARE_DELAYED_WORK(dbs_work, do_dbs_timer); struct dbs_tuners { unsigned int sampling_rate; @@ -420,7 +420,7 @@ static void dbs_check_cpu(int cpu) } } -static void do_dbs_timer(void *data) +static void do_dbs_timer(struct work_struct *work) { int i; lock_cpu_hotplug(); @@ -435,7 +435,6 @@ static void do_dbs_timer(void *data) static inline void dbs_timer_init(void) { - INIT_WORK(&dbs_work, do_dbs_timer, NULL); schedule_delayed_work(&dbs_work, usecs_to_jiffies(dbs_tuners_ins.sampling_rate)); return; diff --git a/trunk/drivers/cpufreq/cpufreq_ondemand.c b/trunk/drivers/cpufreq/cpufreq_ondemand.c index bf8aa45d4f01..e1cc5113c2ae 100644 --- a/trunk/drivers/cpufreq/cpufreq_ondemand.c +++ b/trunk/drivers/cpufreq/cpufreq_ondemand.c @@ -47,13 +47,17 @@ static unsigned int def_sampling_rate; #define DEF_SAMPLING_RATE_LATENCY_MULTIPLIER (1000) #define TRANSITION_LATENCY_LIMIT (10 * 1000) -static void do_dbs_timer(void *data); +static void do_dbs_timer(struct work_struct *work); + +/* Sampling types */ +enum dbs_sample {DBS_NORMAL_SAMPLE, DBS_SUB_SAMPLE}; struct cpu_dbs_info_s { cputime64_t prev_cpu_idle; cputime64_t prev_cpu_wall; struct cpufreq_policy *cur_policy; - struct work_struct work; + struct delayed_work work; + enum dbs_sample sample_type; unsigned int enable; struct cpufreq_frequency_table *freq_table; unsigned int freq_lo; @@ -407,30 +411,31 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info) } } -/* Sampling types */ -enum {DBS_NORMAL_SAMPLE, DBS_SUB_SAMPLE}; - -static void do_dbs_timer(void *data) +static void do_dbs_timer(struct work_struct *work) { unsigned int cpu = smp_processor_id(); struct cpu_dbs_info_s *dbs_info = &per_cpu(cpu_dbs_info, cpu); + enum dbs_sample sample_type = dbs_info->sample_type; /* We want all CPUs to do sampling nearly on same jiffy */ int delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate); + + /* Permit rescheduling of this work item */ + work_release(work); + delay -= jiffies % delay; if (!dbs_info->enable) return; /* Common NORMAL_SAMPLE setup */ - INIT_WORK(&dbs_info->work, do_dbs_timer, (void *)DBS_NORMAL_SAMPLE); + dbs_info->sample_type = DBS_NORMAL_SAMPLE; if (!dbs_tuners_ins.powersave_bias || - (unsigned long) data == DBS_NORMAL_SAMPLE) { + sample_type == DBS_NORMAL_SAMPLE) { lock_cpu_hotplug(); dbs_check_cpu(dbs_info); unlock_cpu_hotplug(); if (dbs_info->freq_lo) { /* Setup timer for SUB_SAMPLE */ - INIT_WORK(&dbs_info->work, do_dbs_timer, - (void *)DBS_SUB_SAMPLE); + dbs_info->sample_type = DBS_SUB_SAMPLE; delay = dbs_info->freq_hi_jiffies; } } else { @@ -449,7 +454,8 @@ static inline void dbs_timer_init(unsigned int cpu) delay -= jiffies % delay; ondemand_powersave_bias_init(); - INIT_WORK(&dbs_info->work, do_dbs_timer, NULL); + INIT_DELAYED_WORK_NAR(&dbs_info->work, do_dbs_timer); + dbs_info->sample_type = DBS_NORMAL_SAMPLE; queue_delayed_work_on(cpu, kondemand_wq, &dbs_info->work, delay); } diff --git a/trunk/drivers/crypto/Kconfig b/trunk/drivers/crypto/Kconfig index adb554153f67..e816535ab305 100644 --- a/trunk/drivers/crypto/Kconfig +++ b/trunk/drivers/crypto/Kconfig @@ -51,4 +51,17 @@ config CRYPTO_DEV_PADLOCK_SHA If unsure say M. The compiled module will be called padlock-sha.ko +config CRYPTO_DEV_GEODE + tristate "Support for the Geode LX AES engine" + depends on CRYPTO && X86_32 + select CRYPTO_ALGAPI + select CRYPTO_BLKCIPHER + default m + help + Say 'Y' here to use the AMD Geode LX processor on-board AES + engine for the CryptoAPI AES alogrithm. + + To compile this driver as a module, choose M here: the module + will be called geode-aes. + endmenu diff --git a/trunk/drivers/crypto/Makefile b/trunk/drivers/crypto/Makefile index 4c3d0ec1cf80..6059cf869414 100644 --- a/trunk/drivers/crypto/Makefile +++ b/trunk/drivers/crypto/Makefile @@ -1,3 +1,4 @@ obj-$(CONFIG_CRYPTO_DEV_PADLOCK) += padlock.o obj-$(CONFIG_CRYPTO_DEV_PADLOCK_AES) += padlock-aes.o obj-$(CONFIG_CRYPTO_DEV_PADLOCK_SHA) += padlock-sha.o +obj-$(CONFIG_CRYPTO_DEV_GEODE) += geode-aes.o diff --git a/trunk/drivers/crypto/geode-aes.c b/trunk/drivers/crypto/geode-aes.c new file mode 100644 index 000000000000..43a68398656f --- /dev/null +++ b/trunk/drivers/crypto/geode-aes.c @@ -0,0 +1,474 @@ + /* Copyright (C) 2004-2006, Advanced Micro Devices, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "geode-aes.h" + +/* Register definitions */ + +#define AES_CTRLA_REG 0x0000 + +#define AES_CTRL_START 0x01 +#define AES_CTRL_DECRYPT 0x00 +#define AES_CTRL_ENCRYPT 0x02 +#define AES_CTRL_WRKEY 0x04 +#define AES_CTRL_DCA 0x08 +#define AES_CTRL_SCA 0x10 +#define AES_CTRL_CBC 0x20 + +#define AES_INTR_REG 0x0008 + +#define AES_INTRA_PENDING (1 << 16) +#define AES_INTRB_PENDING (1 << 17) + +#define AES_INTR_PENDING (AES_INTRA_PENDING | AES_INTRB_PENDING) +#define AES_INTR_MASK 0x07 + +#define AES_SOURCEA_REG 0x0010 +#define AES_DSTA_REG 0x0014 +#define AES_LENA_REG 0x0018 +#define AES_WRITEKEY0_REG 0x0030 +#define AES_WRITEIV0_REG 0x0040 + +/* A very large counter that is used to gracefully bail out of an + * operation in case of trouble + */ + +#define AES_OP_TIMEOUT 0x50000 + +/* Static structures */ + +static void __iomem * _iobase; +static spinlock_t lock; + +/* Write a 128 bit field (either a writable key or IV) */ +static inline void +_writefield(u32 offset, void *value) +{ + int i; + for(i = 0; i < 4; i++) + iowrite32(((u32 *) value)[i], _iobase + offset + (i * 4)); +} + +/* Read a 128 bit field (either a writable key or IV) */ +static inline void +_readfield(u32 offset, void *value) +{ + int i; + for(i = 0; i < 4; i++) + ((u32 *) value)[i] = ioread32(_iobase + offset + (i * 4)); +} + +static int +do_crypt(void *src, void *dst, int len, u32 flags) +{ + u32 status; + u32 counter = AES_OP_TIMEOUT; + + iowrite32(virt_to_phys(src), _iobase + AES_SOURCEA_REG); + iowrite32(virt_to_phys(dst), _iobase + AES_DSTA_REG); + iowrite32(len, _iobase + AES_LENA_REG); + + /* Start the operation */ + iowrite32(AES_CTRL_START | flags, _iobase + AES_CTRLA_REG); + + do + status = ioread32(_iobase + AES_INTR_REG); + while(!(status & AES_INTRA_PENDING) && --counter); + + /* Clear the event */ + iowrite32((status & 0xFF) | AES_INTRA_PENDING, _iobase + AES_INTR_REG); + return counter ? 0 : 1; +} + +static unsigned int +geode_aes_crypt(struct geode_aes_op *op) +{ + + u32 flags = 0; + int iflags; + + if (op->len == 0 || op->src == op->dst) + return 0; + + if (op->flags & AES_FLAGS_COHERENT) + flags |= (AES_CTRL_DCA | AES_CTRL_SCA); + + if (op->dir == AES_DIR_ENCRYPT) + flags |= AES_CTRL_ENCRYPT; + + /* Start the critical section */ + + spin_lock_irqsave(&lock, iflags); + + if (op->mode == AES_MODE_CBC) { + flags |= AES_CTRL_CBC; + _writefield(AES_WRITEIV0_REG, op->iv); + } + + if (op->flags & AES_FLAGS_USRKEY) { + flags |= AES_CTRL_WRKEY; + _writefield(AES_WRITEKEY0_REG, op->key); + } + + do_crypt(op->src, op->dst, op->len, flags); + + if (op->mode == AES_MODE_CBC) + _readfield(AES_WRITEIV0_REG, op->iv); + + spin_unlock_irqrestore(&lock, iflags); + + return op->len; +} + +/* CRYPTO-API Functions */ + +static int +geode_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int len) +{ + struct geode_aes_op *op = crypto_tfm_ctx(tfm); + + if (len != AES_KEY_LENGTH) { + tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; + return -EINVAL; + } + + memcpy(op->key, key, len); + return 0; +} + +static void +geode_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) +{ + struct geode_aes_op *op = crypto_tfm_ctx(tfm); + + if ((out == NULL) || (in == NULL)) + return; + + op->src = (void *) in; + op->dst = (void *) out; + op->mode = AES_MODE_ECB; + op->flags = 0; + op->len = AES_MIN_BLOCK_SIZE; + op->dir = AES_DIR_ENCRYPT; + + geode_aes_crypt(op); +} + + +static void +geode_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) +{ + struct geode_aes_op *op = crypto_tfm_ctx(tfm); + + if ((out == NULL) || (in == NULL)) + return; + + op->src = (void *) in; + op->dst = (void *) out; + op->mode = AES_MODE_ECB; + op->flags = 0; + op->len = AES_MIN_BLOCK_SIZE; + op->dir = AES_DIR_DECRYPT; + + geode_aes_crypt(op); +} + + +static struct crypto_alg geode_alg = { + .cra_name = "aes", + .cra_driver_name = "geode-aes-128", + .cra_priority = 300, + .cra_alignmask = 15, + .cra_flags = CRYPTO_ALG_TYPE_CIPHER, + .cra_blocksize = AES_MIN_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct geode_aes_op), + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(geode_alg.cra_list), + .cra_u = { + .cipher = { + .cia_min_keysize = AES_KEY_LENGTH, + .cia_max_keysize = AES_KEY_LENGTH, + .cia_setkey = geode_setkey, + .cia_encrypt = geode_encrypt, + .cia_decrypt = geode_decrypt + } + } +}; + +static int +geode_cbc_decrypt(struct blkcipher_desc *desc, + struct scatterlist *dst, struct scatterlist *src, + unsigned int nbytes) +{ + struct geode_aes_op *op = crypto_blkcipher_ctx(desc->tfm); + struct blkcipher_walk walk; + int err, ret; + + blkcipher_walk_init(&walk, dst, src, nbytes); + err = blkcipher_walk_virt(desc, &walk); + + while((nbytes = walk.nbytes)) { + op->src = walk.src.virt.addr, + op->dst = walk.dst.virt.addr; + op->mode = AES_MODE_CBC; + op->len = nbytes - (nbytes % AES_MIN_BLOCK_SIZE); + op->dir = AES_DIR_DECRYPT; + + memcpy(op->iv, walk.iv, AES_IV_LENGTH); + + ret = geode_aes_crypt(op); + + memcpy(walk.iv, op->iv, AES_IV_LENGTH); + nbytes -= ret; + + err = blkcipher_walk_done(desc, &walk, nbytes); + } + + return err; +} + +static int +geode_cbc_encrypt(struct blkcipher_desc *desc, + struct scatterlist *dst, struct scatterlist *src, + unsigned int nbytes) +{ + struct geode_aes_op *op = crypto_blkcipher_ctx(desc->tfm); + struct blkcipher_walk walk; + int err, ret; + + blkcipher_walk_init(&walk, dst, src, nbytes); + err = blkcipher_walk_virt(desc, &walk); + + while((nbytes = walk.nbytes)) { + op->src = walk.src.virt.addr, + op->dst = walk.dst.virt.addr; + op->mode = AES_MODE_CBC; + op->len = nbytes - (nbytes % AES_MIN_BLOCK_SIZE); + op->dir = AES_DIR_ENCRYPT; + + memcpy(op->iv, walk.iv, AES_IV_LENGTH); + + ret = geode_aes_crypt(op); + nbytes -= ret; + err = blkcipher_walk_done(desc, &walk, nbytes); + } + + return err; +} + +static struct crypto_alg geode_cbc_alg = { + .cra_name = "cbc(aes)", + .cra_driver_name = "cbc-aes-geode-128", + .cra_priority = 400, + .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, + .cra_blocksize = AES_MIN_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct geode_aes_op), + .cra_alignmask = 15, + .cra_type = &crypto_blkcipher_type, + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(geode_cbc_alg.cra_list), + .cra_u = { + .blkcipher = { + .min_keysize = AES_KEY_LENGTH, + .max_keysize = AES_KEY_LENGTH, + .setkey = geode_setkey, + .encrypt = geode_cbc_encrypt, + .decrypt = geode_cbc_decrypt, + } + } +}; + +static int +geode_ecb_decrypt(struct blkcipher_desc *desc, + struct scatterlist *dst, struct scatterlist *src, + unsigned int nbytes) +{ + struct geode_aes_op *op = crypto_blkcipher_ctx(desc->tfm); + struct blkcipher_walk walk; + int err, ret; + + blkcipher_walk_init(&walk, dst, src, nbytes); + err = blkcipher_walk_virt(desc, &walk); + + while((nbytes = walk.nbytes)) { + op->src = walk.src.virt.addr, + op->dst = walk.dst.virt.addr; + op->mode = AES_MODE_ECB; + op->len = nbytes - (nbytes % AES_MIN_BLOCK_SIZE); + op->dir = AES_DIR_DECRYPT; + + ret = geode_aes_crypt(op); + nbytes -= ret; + err = blkcipher_walk_done(desc, &walk, nbytes); + } + + return err; +} + +static int +geode_ecb_encrypt(struct blkcipher_desc *desc, + struct scatterlist *dst, struct scatterlist *src, + unsigned int nbytes) +{ + struct geode_aes_op *op = crypto_blkcipher_ctx(desc->tfm); + struct blkcipher_walk walk; + int err, ret; + + blkcipher_walk_init(&walk, dst, src, nbytes); + err = blkcipher_walk_virt(desc, &walk); + + while((nbytes = walk.nbytes)) { + op->src = walk.src.virt.addr, + op->dst = walk.dst.virt.addr; + op->mode = AES_MODE_ECB; + op->len = nbytes - (nbytes % AES_MIN_BLOCK_SIZE); + op->dir = AES_DIR_ENCRYPT; + + ret = geode_aes_crypt(op); + nbytes -= ret; + ret = blkcipher_walk_done(desc, &walk, nbytes); + } + + return err; +} + +static struct crypto_alg geode_ecb_alg = { + .cra_name = "ecb(aes)", + .cra_driver_name = "ecb-aes-geode-128", + .cra_priority = 400, + .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, + .cra_blocksize = AES_MIN_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct geode_aes_op), + .cra_alignmask = 15, + .cra_type = &crypto_blkcipher_type, + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(geode_ecb_alg.cra_list), + .cra_u = { + .blkcipher = { + .min_keysize = AES_KEY_LENGTH, + .max_keysize = AES_KEY_LENGTH, + .setkey = geode_setkey, + .encrypt = geode_ecb_encrypt, + .decrypt = geode_ecb_decrypt, + } + } +}; + +static void +geode_aes_remove(struct pci_dev *dev) +{ + crypto_unregister_alg(&geode_alg); + crypto_unregister_alg(&geode_ecb_alg); + crypto_unregister_alg(&geode_cbc_alg); + + pci_iounmap(dev, _iobase); + _iobase = NULL; + + pci_release_regions(dev); + pci_disable_device(dev); +} + + +static int +geode_aes_probe(struct pci_dev *dev, const struct pci_device_id *id) +{ + int ret; + + if ((ret = pci_enable_device(dev))) + return ret; + + if ((ret = pci_request_regions(dev, "geode-aes-128"))) + goto eenable; + + _iobase = pci_iomap(dev, 0, 0); + + if (_iobase == NULL) { + ret = -ENOMEM; + goto erequest; + } + + spin_lock_init(&lock); + + /* Clear any pending activity */ + iowrite32(AES_INTR_PENDING | AES_INTR_MASK, _iobase + AES_INTR_REG); + + if ((ret = crypto_register_alg(&geode_alg))) + goto eiomap; + + if ((ret = crypto_register_alg(&geode_ecb_alg))) + goto ealg; + + if ((ret = crypto_register_alg(&geode_cbc_alg))) + goto eecb; + + printk(KERN_NOTICE "geode-aes: GEODE AES engine enabled.\n"); + return 0; + + eecb: + crypto_unregister_alg(&geode_ecb_alg); + + ealg: + crypto_unregister_alg(&geode_alg); + + eiomap: + pci_iounmap(dev, _iobase); + + erequest: + pci_release_regions(dev); + + eenable: + pci_disable_device(dev); + + printk(KERN_ERR "geode-aes: GEODE AES initialization failed.\n"); + return ret; +} + +static struct pci_device_id geode_aes_tbl[] = { + { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LX_AES, PCI_ANY_ID, PCI_ANY_ID} , + { 0, } +}; + +MODULE_DEVICE_TABLE(pci, geode_aes_tbl); + +static struct pci_driver geode_aes_driver = { + .name = "Geode LX AES", + .id_table = geode_aes_tbl, + .probe = geode_aes_probe, + .remove = __devexit_p(geode_aes_remove) +}; + +static int __init +geode_aes_init(void) +{ + return pci_module_init(&geode_aes_driver); +} + +static void __exit +geode_aes_exit(void) +{ + pci_unregister_driver(&geode_aes_driver); +} + +MODULE_AUTHOR("Advanced Micro Devices, Inc."); +MODULE_DESCRIPTION("Geode LX Hardware AES driver"); +MODULE_LICENSE("GPL"); + +module_init(geode_aes_init); +module_exit(geode_aes_exit); diff --git a/trunk/drivers/crypto/geode-aes.h b/trunk/drivers/crypto/geode-aes.h new file mode 100644 index 000000000000..8003a36f3a83 --- /dev/null +++ b/trunk/drivers/crypto/geode-aes.h @@ -0,0 +1,40 @@ +/* Copyright (C) 2003-2006, Advanced Micro Devices, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#ifndef _GEODE_AES_H_ +#define _GEODE_AES_H_ + +#define AES_KEY_LENGTH 16 +#define AES_IV_LENGTH 16 + +#define AES_MIN_BLOCK_SIZE 16 + +#define AES_MODE_ECB 0 +#define AES_MODE_CBC 1 + +#define AES_DIR_DECRYPT 0 +#define AES_DIR_ENCRYPT 1 + +#define AES_FLAGS_USRKEY (1 << 0) +#define AES_FLAGS_COHERENT (1 << 1) + +struct geode_aes_op { + + void *src; + void *dst; + + u32 mode; + u32 dir; + u32 flags; + int len; + + u8 key[AES_KEY_LENGTH]; + u8 iv[AES_IV_LENGTH]; +}; + +#endif diff --git a/trunk/drivers/dma/ioatdma.c b/trunk/drivers/dma/ioatdma.c index 0358419a0e48..8e8726104619 100644 --- a/trunk/drivers/dma/ioatdma.c +++ b/trunk/drivers/dma/ioatdma.c @@ -636,10 +636,10 @@ static int ioat_self_test(struct ioat_device *device) dma_cookie_t cookie; int err = 0; - src = kzalloc(sizeof(u8) * IOAT_TEST_SIZE, SLAB_KERNEL); + src = kzalloc(sizeof(u8) * IOAT_TEST_SIZE, GFP_KERNEL); if (!src) return -ENOMEM; - dest = kzalloc(sizeof(u8) * IOAT_TEST_SIZE, SLAB_KERNEL); + dest = kzalloc(sizeof(u8) * IOAT_TEST_SIZE, GFP_KERNEL); if (!dest) { kfree(src); return -ENOMEM; diff --git a/trunk/drivers/edac/edac_mc.c b/trunk/drivers/edac/edac_mc.c index 75e9e38330ff..1b4fc9221803 100644 --- a/trunk/drivers/edac/edac_mc.c +++ b/trunk/drivers/edac/edac_mc.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include diff --git a/trunk/drivers/i2c/busses/Kconfig b/trunk/drivers/i2c/busses/Kconfig index 04bee524e31a..90f91d039ee2 100644 --- a/trunk/drivers/i2c/busses/Kconfig +++ b/trunk/drivers/i2c/busses/Kconfig @@ -196,11 +196,11 @@ config I2C_IBM_IIC will be called i2c-ibm_iic. config I2C_IOP3XX - tristate "Intel IOP3xx and IXP4xx on-chip I2C interface" - depends on (ARCH_IOP32X || ARCH_IOP33X || ARCH_IXP4XX) && I2C + tristate "Intel IOPx3xx and IXP4xx on-chip I2C interface" + depends on (ARCH_IOP32X || ARCH_IOP33X || ARCH_IXP4XX || ARCH_IOP13XX) && I2C help Say Y here if you want to use the IIC bus controller on - the Intel IOP3xx I/O Processors or IXP4xx Network Processors. + the Intel IOPx3xx I/O Processors or IXP4xx Network Processors. This driver can also be built as a module. If so, the module will be called i2c-iop3xx. diff --git a/trunk/drivers/i2c/busses/i2c-pxa.c b/trunk/drivers/i2c/busses/i2c-pxa.c index c95a6c154165..c3b1567c852a 100644 --- a/trunk/drivers/i2c/busses/i2c-pxa.c +++ b/trunk/drivers/i2c/busses/i2c-pxa.c @@ -357,133 +357,6 @@ static void i2c_pxa_reset(struct pxa_i2c *i2c) #ifdef CONFIG_I2C_PXA_SLAVE -/* - * I2C EEPROM emulation. - */ -static struct i2c_eeprom_emu eeprom = { - .size = I2C_EEPROM_EMU_SIZE, - .watch = LIST_HEAD_INIT(eeprom.watch), -}; - -struct i2c_eeprom_emu *i2c_pxa_get_eeprom(void) -{ - return &eeprom; -} - -int i2c_eeprom_emu_addwatcher(struct i2c_eeprom_emu *emu, void *data, - unsigned int addr, unsigned int size, - struct i2c_eeprom_emu_watcher *watcher) -{ - struct i2c_eeprom_emu_watch *watch; - unsigned long flags; - - if (addr + size > emu->size) - return -EINVAL; - - watch = kmalloc(sizeof(struct i2c_eeprom_emu_watch), GFP_KERNEL); - if (watch) { - watch->start = addr; - watch->end = addr + size - 1; - watch->ops = watcher; - watch->data = data; - - local_irq_save(flags); - list_add(&watch->node, &emu->watch); - local_irq_restore(flags); - } - - return watch ? 0 : -ENOMEM; -} - -void i2c_eeprom_emu_delwatcher(struct i2c_eeprom_emu *emu, void *data, - struct i2c_eeprom_emu_watcher *watcher) -{ - struct i2c_eeprom_emu_watch *watch, *n; - unsigned long flags; - - list_for_each_entry_safe(watch, n, &emu->watch, node) { - if (watch->ops == watcher && watch->data == data) { - local_irq_save(flags); - list_del(&watch->node); - local_irq_restore(flags); - kfree(watch); - } - } -} - -static void i2c_eeprom_emu_event(void *ptr, i2c_slave_event_t event) -{ - struct i2c_eeprom_emu *emu = ptr; - - eedbg(3, "i2c_eeprom_emu_event: %d\n", event); - - switch (event) { - case I2C_SLAVE_EVENT_START_WRITE: - emu->seen_start = 1; - eedbg(2, "i2c_eeprom: write initiated\n"); - break; - - case I2C_SLAVE_EVENT_START_READ: - emu->seen_start = 0; - eedbg(2, "i2c_eeprom: read initiated\n"); - break; - - case I2C_SLAVE_EVENT_STOP: - emu->seen_start = 0; - eedbg(2, "i2c_eeprom: received stop\n"); - break; - - default: - eedbg(0, "i2c_eeprom: unhandled event\n"); - break; - } -} - -static int i2c_eeprom_emu_read(void *ptr) -{ - struct i2c_eeprom_emu *emu = ptr; - int ret; - - ret = emu->bytes[emu->ptr]; - emu->ptr = (emu->ptr + 1) % emu->size; - - return ret; -} - -static void i2c_eeprom_emu_write(void *ptr, unsigned int val) -{ - struct i2c_eeprom_emu *emu = ptr; - struct i2c_eeprom_emu_watch *watch; - - if (emu->seen_start != 0) { - eedbg(2, "i2c_eeprom_emu_write: setting ptr %02x\n", val); - emu->ptr = val; - emu->seen_start = 0; - return; - } - - emu->bytes[emu->ptr] = val; - - eedbg(1, "i2c_eeprom_emu_write: ptr=0x%02x, val=0x%02x\n", - emu->ptr, val); - - list_for_each_entry(watch, &emu->watch, node) { - if (!watch->ops || !watch->ops->write) - continue; - if (watch->start <= emu->ptr && watch->end >= emu->ptr) - watch->ops->write(watch->data, emu->ptr, val); - } - - emu->ptr = (emu->ptr + 1) % emu->size; -} - -struct i2c_slave_client eeprom_client = { - .data = &eeprom, - .event = i2c_eeprom_emu_event, - .read = i2c_eeprom_emu_read, - .write = i2c_eeprom_emu_write -}; - /* * PXA I2C Slave mode */ @@ -963,11 +836,9 @@ static int i2c_pxa_probe(struct platform_device *dev) i2c->slave_addr = I2C_PXA_SLAVE_ADDR; #ifdef CONFIG_I2C_PXA_SLAVE - i2c->slave = &eeprom_client; if (plat) { i2c->slave_addr = plat->slave_addr; - if (plat->slave) - i2c->slave = plat->slave; + i2c->slave = plat->slave; } #endif diff --git a/trunk/drivers/i2c/chips/ds1374.c b/trunk/drivers/i2c/chips/ds1374.c index 4630f1969a09..15edf40828b4 100644 --- a/trunk/drivers/i2c/chips/ds1374.c +++ b/trunk/drivers/i2c/chips/ds1374.c @@ -140,12 +140,14 @@ ulong ds1374_get_rtc_time(void) return t1; } -static void ds1374_set_work(void *arg) +static ulong new_time; + +static void ds1374_set_work(struct work_struct *work) { ulong t1, t2; int limit = 10; /* arbitrary retry limit */ - t1 = *(ulong *) arg; + t1 = new_time; mutex_lock(&ds1374_mutex); @@ -167,11 +169,9 @@ static void ds1374_set_work(void *arg) "can't confirm time set from rtc chip\n"); } -static ulong new_time; - static struct workqueue_struct *ds1374_workqueue; -static DECLARE_WORK(ds1374_work, ds1374_set_work, &new_time); +static DECLARE_WORK(ds1374_work, ds1374_set_work); int ds1374_set_rtc_time(ulong nowtime) { @@ -180,7 +180,7 @@ int ds1374_set_rtc_time(ulong nowtime) if (in_interrupt()) queue_work(ds1374_workqueue, &ds1374_work); else - ds1374_set_work(&new_time); + ds1374_set_work(NULL); return 0; } diff --git a/trunk/drivers/i2c/chips/m41t00.c b/trunk/drivers/i2c/chips/m41t00.c index 2dd0a34d9472..420377c86422 100644 --- a/trunk/drivers/i2c/chips/m41t00.c +++ b/trunk/drivers/i2c/chips/m41t00.c @@ -215,8 +215,15 @@ m41t00_set(void *arg) } static ulong new_time; +/* well, isn't this API just _lovely_? */ +static void +m41t00_barf(struct work_struct *unusable) +{ + m41t00_set(&new_time); +} + static struct workqueue_struct *m41t00_wq; -static DECLARE_WORK(m41t00_work, m41t00_set, &new_time); +static DECLARE_WORK(m41t00_work, m41t00_barf); int m41t00_set_rtc_time(ulong nowtime) diff --git a/trunk/drivers/i2c/i2c-dev.c b/trunk/drivers/i2c/i2c-dev.c index 94a4e9a3013c..2e22a2ffa606 100644 --- a/trunk/drivers/i2c/i2c-dev.c +++ b/trunk/drivers/i2c/i2c-dev.c @@ -119,7 +119,7 @@ static ssize_t i2cdev_read (struct file *file, char __user *buf, size_t count, return -ENOMEM; pr_debug("i2c-dev: i2c-%d reading %zd bytes.\n", - iminor(file->f_dentry->d_inode), count); + iminor(file->f_path.dentry->d_inode), count); ret = i2c_master_recv(client,tmp,count); if (ret >= 0) @@ -147,7 +147,7 @@ static ssize_t i2cdev_write (struct file *file, const char __user *buf, size_t c } pr_debug("i2c-dev: i2c-%d writing %zd bytes.\n", - iminor(file->f_dentry->d_inode), count); + iminor(file->f_path.dentry->d_inode), count); ret = i2c_master_send(client,tmp,count); kfree(tmp); diff --git a/trunk/drivers/ide/Kconfig b/trunk/drivers/ide/Kconfig index 0c68d0f0d8e5..e23bc0d62159 100644 --- a/trunk/drivers/ide/Kconfig +++ b/trunk/drivers/ide/Kconfig @@ -389,14 +389,6 @@ config BLK_DEV_RZ1000 Linux. This may slow disk throughput by a few percent, but at least things will operate 100% reliably. -config BLK_DEV_SL82C105 - tristate "Winbond SL82c105 support" - depends on PCI && (PPC || ARM) && BLK_DEV_IDEPCI - help - If you have a Winbond SL82c105 IDE controller, say Y here to enable - special configuration for this chip. This is common on various CHRP - motherboards, but could be used elsewhere. If in doubt, say Y. - config BLK_DEV_IDEDMA_PCI bool "Generic PCI bus-master DMA support" depends on PCI && BLK_DEV_IDEPCI @@ -712,6 +704,14 @@ config BLK_DEV_SIS5513 Please read the comments at the top of . +config BLK_DEV_SL82C105 + tristate "Winbond SL82c105 support" + depends on (PPC || ARM) + help + If you have a Winbond SL82c105 IDE controller, say Y here to enable + special configuration for this chip. This is common on various CHRP + motherboards, but could be used elsewhere. If in doubt, say Y. + config BLK_DEV_SLC90E66 tristate "SLC90E66 chipset support" help diff --git a/trunk/drivers/ide/ide.c b/trunk/drivers/ide/ide.c index 287a66201150..16890769dca6 100644 --- a/trunk/drivers/ide/ide.c +++ b/trunk/drivers/ide/ide.c @@ -973,8 +973,8 @@ ide_settings_t *ide_find_setting_by_name (ide_drive_t *drive, char *name) * @drive: drive * * Automatically remove all the driver specific settings for this - * drive. This function may sleep and must not be called from IRQ - * context. The caller must hold ide_setting_sem. + * drive. This function may not be called from IRQ context. The + * caller must hold ide_setting_sem. */ static void auto_remove_settings (ide_drive_t *drive) @@ -1874,11 +1874,22 @@ void ide_unregister_subdriver(ide_drive_t *drive, ide_driver_t *driver) { unsigned long flags; - down(&ide_setting_sem); - spin_lock_irqsave(&ide_lock, flags); #ifdef CONFIG_PROC_FS ide_remove_proc_entries(drive->proc, driver->proc); #endif + down(&ide_setting_sem); + spin_lock_irqsave(&ide_lock, flags); + /* + * ide_setting_sem protects the settings list + * ide_lock protects the use of settings + * + * so we need to hold both, ide_settings_sem because we want to + * modify the settings list, and ide_lock because we cannot take + * a setting out that is being used. + * + * OTOH both ide_{read,write}_setting are only ever used under + * ide_setting_sem. + */ auto_remove_settings(drive); spin_unlock_irqrestore(&ide_lock, flags); up(&ide_setting_sem); diff --git a/trunk/drivers/ide/legacy/ide-cs.c b/trunk/drivers/ide/legacy/ide-cs.c index bef4759f70e5..7efd28ac21ed 100644 --- a/trunk/drivers/ide/legacy/ide-cs.c +++ b/trunk/drivers/ide/legacy/ide-cs.c @@ -192,20 +192,10 @@ static int ide_config(struct pcmcia_device *link) tuple.TupleOffset = 0; tuple.TupleDataMax = 255; tuple.Attributes = 0; - tuple.DesiredTuple = CISTPL_CONFIG; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &stk->parse)); - link->conf.ConfigBase = stk->parse.config.base; - link->conf.Present = stk->parse.config.rmask[0]; - - tuple.DesiredTuple = CISTPL_MANFID; - if (!pcmcia_get_first_tuple(link, &tuple) && - !pcmcia_get_tuple_data(link, &tuple) && - !pcmcia_parse_tuple(link, &tuple, &stk->parse)) - is_kme = ((stk->parse.manfid.manf == MANFID_KME) && - ((stk->parse.manfid.card == PRODID_KME_KXLC005_A) || - (stk->parse.manfid.card == PRODID_KME_KXLC005_B))); + + is_kme = ((link->manf_id == MANFID_KME) && + ((link->card_id == PRODID_KME_KXLC005_A) || + (link->card_id == PRODID_KME_KXLC005_B))); /* Not sure if this is right... look up the current Vcc */ CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &stk->conf)); @@ -408,8 +398,10 @@ static struct pcmcia_device_id ide_ids[] = { PCMCIA_DEVICE_PROD_ID12("SMI VENDOR", "SMI PRODUCT", 0x30896c92, 0x703cc5f6), PCMCIA_DEVICE_PROD_ID12("TOSHIBA", "MK2001MPL", 0xb4585a1a, 0x3489e003), PCMCIA_DEVICE_PROD_ID1("TRANSCEND 512M ", 0xd0909443), + PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS1GCF80", 0x709b1bf1, 0x2a54d4b1), PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS4GCF120", 0x709b1bf1, 0xf54a91c8), PCMCIA_DEVICE_PROD_ID12("WIT", "IDE16", 0x244e5994, 0x3e232852), + PCMCIA_DEVICE_PROD_ID12("WEIDA", "TWTTI", 0xcc7cf69c, 0x212bb918), PCMCIA_DEVICE_PROD_ID1("STI Flash", 0xe4a13209), PCMCIA_DEVICE_PROD_ID12("STI", "Flash 5.0", 0xbf2df18d, 0x8cb57a0e), PCMCIA_MFC_DEVICE_PROD_ID12(1, "SanDisk", "ConnectPlus", 0x7a954bd9, 0x74be00c6), diff --git a/trunk/drivers/ide/pci/alim15x3.c b/trunk/drivers/ide/pci/alim15x3.c index d419e4bb54f4..89109be5162c 100644 --- a/trunk/drivers/ide/pci/alim15x3.c +++ b/trunk/drivers/ide/pci/alim15x3.c @@ -586,11 +586,11 @@ static unsigned int __devinit init_chipset_ali15x3 (struct pci_dev *dev, const c { unsigned long flags; u8 tmpbyte; - struct pci_dev *north = pci_find_slot(0, PCI_DEVFN(0,0)); + struct pci_dev *north = pci_get_slot(dev->bus, PCI_DEVFN(0,0)); pci_read_config_byte(dev, PCI_REVISION_ID, &m5229_revision); - isa_dev = pci_find_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL); + isa_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL); #if defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS) if (!ali_proc) { @@ -613,8 +613,7 @@ static unsigned int __devinit init_chipset_ali15x3 (struct pci_dev *dev, const c * clear bit 7 */ pci_write_config_byte(dev, 0x4b, tmpbyte & 0x7F); - local_irq_restore(flags); - return 0; + goto out; } /* @@ -637,10 +636,8 @@ static unsigned int __devinit init_chipset_ali15x3 (struct pci_dev *dev, const c * box without a device at 0:0.0. The ALi bridge will be at * 0:0.0 so if we didn't find one we know what is cooking. */ - if (north && north->vendor != PCI_VENDOR_ID_AL) { - local_irq_restore(flags); - return 0; - } + if (north && north->vendor != PCI_VENDOR_ID_AL) + goto out; if (m5229_revision < 0xC5 && isa_dev) { @@ -661,6 +658,9 @@ static unsigned int __devinit init_chipset_ali15x3 (struct pci_dev *dev, const c pci_write_config_byte(isa_dev, 0x79, tmpbyte | 0x02); } } +out: + pci_dev_put(north); + pci_dev_put(isa_dev); local_irq_restore(flags); return 0; } diff --git a/trunk/drivers/ide/pci/pdc202xx_new.c b/trunk/drivers/ide/pci/pdc202xx_new.c index 6c097e80b4df..3ca581063f72 100644 --- a/trunk/drivers/ide/pci/pdc202xx_new.c +++ b/trunk/drivers/ide/pci/pdc202xx_new.c @@ -9,6 +9,7 @@ * Split from: * linux/drivers/ide/pdc202xx.c Version 0.35 Mar. 30, 2002 * Copyright (C) 1998-2002 Andre Hedrick + * Copyright (C) 2005-2006 MontaVista Software, Inc. * Portions Copyright (C) 1999 Promise Technology, Inc. * Author: Frank Tiernan (frankt@promise.com) * Released under terms of General Public License @@ -168,12 +169,8 @@ static int pdcnew_new_tune_chipset (ide_drive_t *drive, u8 xferspeed) */ static void pdcnew_tune_drive(ide_drive_t *drive, u8 pio) { - u8 speed; - - if (pio == 5) pio = 4; - speed = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, pio, NULL); - - (void)pdcnew_new_tune_chipset(drive, speed); + pio = ide_get_best_pio_mode(drive, pio, 4, NULL); + (void)pdcnew_new_tune_chipset(drive, XFER_PIO_0 + pio); } static u8 pdcnew_new_cable_detect (ide_hwif_t *hwif) @@ -207,10 +204,8 @@ static int config_chipset_for_dma (ide_drive_t *drive) speed = ide_dma_speed(drive, pdcnew_ratemask(drive)); - if (!(speed)) { - hwif->tuneproc(drive, 5); + if (!speed) return 0; - } (void) hwif->speedproc(drive, speed); return ide_dma_enable(drive); @@ -234,7 +229,7 @@ static int pdcnew_config_drive_xfer_rate (ide_drive_t *drive) } else if ((id->capability & 8) || (id->field_valid & 2)) { fast_ata_pio: - hwif->tuneproc(drive, 5); + hwif->tuneproc(drive, 255); return hwif->ide_dma_off_quietly(drive); } /* IORDY not supported */ @@ -362,6 +357,7 @@ static int __devinit init_setup_pdc20270(struct pci_dev *dev, ide_pci_device_t *d) { struct pci_dev *findev = NULL; + int ret; if ((dev->bus->self && dev->bus->self->vendor == PCI_VENDOR_ID_DEC) && @@ -369,14 +365,16 @@ static int __devinit init_setup_pdc20270(struct pci_dev *dev, if (PCI_SLOT(dev->devfn) & 2) return -ENODEV; d->extra = 0; - while ((findev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, findev)) != NULL) { + while ((findev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, findev)) != NULL) { if ((findev->vendor == dev->vendor) && (findev->device == dev->device) && (PCI_SLOT(findev->devfn) & 2)) { if (findev->irq != dev->irq) { findev->irq = dev->irq; } - return ide_setup_pci_devices(dev, findev, d); + ret = ide_setup_pci_devices(dev, findev, d); + pci_dev_put(findev); + return ret; } } } diff --git a/trunk/drivers/ide/pci/sis5513.c b/trunk/drivers/ide/pci/sis5513.c index 92edf76bd7ad..6b313139b5e4 100644 --- a/trunk/drivers/ide/pci/sis5513.c +++ b/trunk/drivers/ide/pci/sis5513.c @@ -800,9 +800,10 @@ static unsigned int __devinit init_chipset_sis5513 (struct pci_dev *dev, const c if (trueid == 0x5517) { /* SiS 961/961B */ - lpc_bridge = pci_find_slot(0x00, 0x10); /* Bus 0, Dev 2, Fn 0 */ + lpc_bridge = pci_get_slot(dev->bus, 0x10); /* Bus 0, Dev 2, Fn 0 */ pci_read_config_byte(lpc_bridge, PCI_REVISION_ID, &sbrev); pci_read_config_byte(dev, 0x49, &prefctl); + pci_dev_put(lpc_bridge); if (sbrev == 0x10 && (prefctl & 0x80)) { printk(KERN_INFO "SIS5513: SiS 961B MuTIOL IDE UDMA133 controller\n"); diff --git a/trunk/drivers/ide/pci/sl82c105.c b/trunk/drivers/ide/pci/sl82c105.c index 0b4b60498515..5afefe8692fe 100644 --- a/trunk/drivers/ide/pci/sl82c105.c +++ b/trunk/drivers/ide/pci/sl82c105.c @@ -299,14 +299,14 @@ static void sl82c105_selectproc(ide_drive_t *drive) //DBG(("sl82c105_selectproc(drive:%s)\n", drive->name)); mask = hwif->channel ? CTRL_P1F16 : CTRL_P0F16; - old = val = *((u32 *)&hwif->hwif_data); + old = val = (u32)pci_get_drvdata(dev); if (drive->using_dma) val &= ~mask; else val |= mask; if (old != val) { pci_write_config_dword(dev, 0x40, val); - *((u32 *)&hwif->hwif_data) = val; + pci_set_drvdata(dev, (void *)val); } } @@ -316,14 +316,13 @@ static void sl82c105_selectproc(ide_drive_t *drive) */ static void sl82c105_resetproc(ide_drive_t *drive) { - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; + struct pci_dev *dev = HWIF(drive)->pci_dev; u32 val; DBG(("sl82c105_resetproc(drive:%s)\n", drive->name)); pci_read_config_dword(dev, 0x40, &val); - *((u32 *)&hwif->hwif_data) = val; + pci_set_drvdata(dev, (void *)val); } /* @@ -394,6 +393,7 @@ static unsigned int __devinit init_chipset_sl82c105(struct pci_dev *dev, const c pci_read_config_dword(dev, 0x40, &val); val |= CTRL_P0EN | CTRL_P0F16 | CTRL_P1F16; pci_write_config_dword(dev, 0x40, val); + pci_set_drvdata(dev, (void *)val); return dev->irq; } @@ -404,30 +404,25 @@ static unsigned int __devinit init_chipset_sl82c105(struct pci_dev *dev, const c static void __devinit init_hwif_sl82c105(ide_hwif_t *hwif) { - struct pci_dev *dev = hwif->pci_dev; unsigned int rev; u8 dma_state; - u32 val; - + DBG(("init_hwif_sl82c105(hwif: ide%d)\n", hwif->index)); hwif->tuneproc = tune_sl82c105; hwif->selectproc = sl82c105_selectproc; hwif->resetproc = sl82c105_resetproc; - - /* Default to PIO 0 for fallback unless tuned otherwise, - * we always autotune PIO, this is done before DMA is - * checked, so there is no risk of accidentally disabling - * DMA - */ + + /* + * Default to PIO 0 for fallback unless tuned otherwise. + * We always autotune PIO, this is done before DMA is checked, + * so there's no risk of accidentally disabling DMA + */ hwif->drives[0].pio_speed = XFER_PIO_0; hwif->drives[0].autotune = 1; - hwif->drives[1].pio_speed = XFER_PIO_1; + hwif->drives[1].pio_speed = XFER_PIO_0; hwif->drives[1].autotune = 1; - pci_read_config_dword(dev, 0x40, &val); - *((u32 *)&hwif->hwif_data) = val; - hwif->atapi_dma = 0; hwif->mwdma_mask = 0; hwif->swdma_mask = 0; diff --git a/trunk/drivers/ide/pci/via82cxxx.c b/trunk/drivers/ide/pci/via82cxxx.c index eb7ab112c050..61f1a9665a7f 100644 --- a/trunk/drivers/ide/pci/via82cxxx.c +++ b/trunk/drivers/ide/pci/via82cxxx.c @@ -282,11 +282,11 @@ static unsigned int __devinit init_chipset_via82cxxx(struct pci_dev *dev, const * Find the ISA bridge to see how good the IDE is. */ via_config = via_config_find(&isa); - if (!via_config->id) { - printk(KERN_WARNING "VP_IDE: Unknown VIA SouthBridge, disabling DMA.\n"); - pci_dev_put(isa); - return -ENODEV; - } + + /* We checked this earlier so if it fails here deeep badness + is involved */ + + BUG_ON(!via_config->id); /* * Setup or disable Clk66 if appropriate @@ -494,6 +494,17 @@ static ide_pci_device_t via82cxxx_chipsets[] __devinitdata = { static int __devinit via_init_one(struct pci_dev *dev, const struct pci_device_id *id) { + struct pci_dev *isa = NULL; + struct via_isa_bridge *via_config; + /* + * Find the ISA bridge and check we know what it is. + */ + via_config = via_config_find(&isa); + pci_dev_put(isa); + if (!via_config->id) { + printk(KERN_WARNING "VP_IDE: Unknown VIA SouthBridge, disabling DMA.\n"); + return -ENODEV; + } return ide_setup_pci_device(dev, &via82cxxx_chipsets[id->driver_data]); } diff --git a/trunk/drivers/ieee1394/Kconfig b/trunk/drivers/ieee1394/Kconfig index 672b92ef9f21..e7d56573fe56 100644 --- a/trunk/drivers/ieee1394/Kconfig +++ b/trunk/drivers/ieee1394/Kconfig @@ -36,7 +36,7 @@ config IEEE1394_VERBOSEDEBUG else says N. config IEEE1394_OUI_DB - bool "OUI Database built-in" + bool "OUI Database built-in (deprecated)" depends on IEEE1394 help If you say Y here, then an OUI list (vendor unique ID's) will be @@ -67,16 +67,11 @@ config IEEE1394_CONFIG_ROM_IP1394 eth1394 option below. config IEEE1394_EXPORT_FULL_API - bool "Export all symbols of ieee1394's API" + bool "Export all symbols of ieee1394's API (deprecated)" depends on IEEE1394 default n help - Export all symbols of ieee1394's driver programming interface, even - those that are not currently used by the standard IEEE 1394 drivers. - - This option does not affect the interface to userspace applications. - Say Y here if you want to compile externally developed drivers that - make extended use of ieee1394's API. It is otherwise safe to say N. + This option will be removed soon. Don't worry, say N. comment "Device Drivers" depends on IEEE1394 @@ -125,7 +120,7 @@ comment "SBP-2 support (for storage devices) requires SCSI" config IEEE1394_SBP2 tristate "SBP-2 support (Harddisks etc.)" - depends on IEEE1394 && SCSI && (PCI || BROKEN) + depends on IEEE1394 && SCSI help This option enables you to use SBP-2 devices connected to an IEEE 1394 bus. SBP-2 devices include storage devices like harddisks and @@ -161,17 +156,12 @@ config IEEE1394_ETH1394 MCAP, therefore multicast support is significantly limited. config IEEE1394_DV1394 - tristate "OHCI-DV I/O support" + tristate "OHCI-DV I/O support (deprecated)" depends on IEEE1394 && IEEE1394_OHCI1394 help - This driver allows you to transmit and receive DV (digital video) - streams on an OHCI-1394 card using a simple frame-oriented - interface. - - The user-space API for dv1394 is documented in dv1394.h. - - To compile this driver as a module, say M here: the - module will be called dv1394. + The dv1394 driver will be removed from Linux in a future release. + Its functionality is now provided by raw1394 together with libraries + such as libiec61883. config IEEE1394_RAWIO tristate "Raw IEEE1394 I/O support" diff --git a/trunk/drivers/ieee1394/Makefile b/trunk/drivers/ieee1394/Makefile index 6f53611fe255..d9650d3d77a0 100644 --- a/trunk/drivers/ieee1394/Makefile +++ b/trunk/drivers/ieee1394/Makefile @@ -3,8 +3,11 @@ # ieee1394-objs := ieee1394_core.o ieee1394_transactions.o hosts.o \ - highlevel.o csr.o nodemgr.o oui.o dma.o iso.o \ + highlevel.o csr.o nodemgr.o dma.o iso.o \ csr1212.o config_roms.o +ifdef CONFIG_IEEE1394_OUI_DB +ieee1394-objs += oui.o +endif obj-$(CONFIG_IEEE1394) += ieee1394.o obj-$(CONFIG_IEEE1394_PCILYNX) += pcilynx.o diff --git a/trunk/drivers/ieee1394/csr.c b/trunk/drivers/ieee1394/csr.c index ab0c80f61b9d..52ac83e0ebee 100644 --- a/trunk/drivers/ieee1394/csr.c +++ b/trunk/drivers/ieee1394/csr.c @@ -158,12 +158,10 @@ static void host_reset(struct hpsb_host *host) */ static inline void calculate_expire(struct csr_control *csr) { - unsigned long usecs = - (csr->split_timeout_hi & 0x07) * USEC_PER_SEC + - (csr->split_timeout_lo >> 19) * 125L; - - csr->expire = usecs_to_jiffies(usecs > 100000L ? usecs : 100000L); + unsigned int usecs = (csr->split_timeout_hi & 7) * 1000000 + + (csr->split_timeout_lo >> 19) * 125; + csr->expire = usecs_to_jiffies(usecs > 100000 ? usecs : 100000); HPSB_VERBOSE("CSR: setting expire to %lu, HZ=%u", csr->expire, HZ); } diff --git a/trunk/drivers/ieee1394/dv1394.c b/trunk/drivers/ieee1394/dv1394.c index 6c72f04b2b5d..1084da4d88a9 100644 --- a/trunk/drivers/ieee1394/dv1394.c +++ b/trunk/drivers/ieee1394/dv1394.c @@ -1536,27 +1536,20 @@ static ssize_t dv1394_read(struct file *file, char __user *buffer, size_t count static long dv1394_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - struct video_card *video; + struct video_card *video = file_to_video_card(file); unsigned long flags; int ret = -EINVAL; void __user *argp = (void __user *)arg; DECLARE_WAITQUEUE(wait, current); - lock_kernel(); - video = file_to_video_card(file); - /* serialize this to prevent multi-threaded mayhem */ if (file->f_flags & O_NONBLOCK) { - if (!mutex_trylock(&video->mtx)) { - unlock_kernel(); + if (!mutex_trylock(&video->mtx)) return -EAGAIN; - } } else { - if (mutex_lock_interruptible(&video->mtx)) { - unlock_kernel(); + if (mutex_lock_interruptible(&video->mtx)) return -ERESTARTSYS; - } } switch(cmd) @@ -1780,7 +1773,6 @@ static long dv1394_ioctl(struct file *file, unsigned int cmd, unsigned long arg) out: mutex_unlock(&video->mtx); - unlock_kernel(); return ret; } @@ -2188,12 +2180,8 @@ static struct ieee1394_device_id dv1394_id_table[] = { MODULE_DEVICE_TABLE(ieee1394, dv1394_id_table); static struct hpsb_protocol_driver dv1394_driver = { - .name = "DV/1394 Driver", + .name = "dv1394", .id_table = dv1394_id_table, - .driver = { - .name = "dv1394", - .bus = &ieee1394_bus_type, - }, }; @@ -2587,6 +2575,10 @@ static int __init dv1394_init_module(void) { int ret; + printk(KERN_WARNING + "WARNING: The dv1394 driver is unsupported and will be removed " + "from Linux soon. Use raw1394 instead.\n"); + cdev_init(&dv1394_cdev, &dv1394_fops); dv1394_cdev.owner = THIS_MODULE; kobject_set_name(&dv1394_cdev.kobj, "dv1394"); diff --git a/trunk/drivers/ieee1394/eth1394.c b/trunk/drivers/ieee1394/eth1394.c index 31e5cc49d61a..97e5c3dd044d 100644 --- a/trunk/drivers/ieee1394/eth1394.c +++ b/trunk/drivers/ieee1394/eth1394.c @@ -133,7 +133,7 @@ struct eth1394_node_info { #define ETH1394_DRIVER_NAME "eth1394" static const char driver_name[] = ETH1394_DRIVER_NAME; -static kmem_cache_t *packet_task_cache; +static struct kmem_cache *packet_task_cache; static struct hpsb_highlevel eth1394_highlevel; @@ -474,12 +474,10 @@ static struct ieee1394_device_id eth1394_id_table[] = { MODULE_DEVICE_TABLE(ieee1394, eth1394_id_table); static struct hpsb_protocol_driver eth1394_proto_driver = { - .name = "IPv4 over 1394 Driver", + .name = ETH1394_DRIVER_NAME, .id_table = eth1394_id_table, .update = eth1394_update, .driver = { - .name = ETH1394_DRIVER_NAME, - .bus = &ieee1394_bus_type, .probe = eth1394_probe, .remove = eth1394_remove, }, diff --git a/trunk/drivers/ieee1394/highlevel.h b/trunk/drivers/ieee1394/highlevel.h index 50f2dd2c7e20..4b330117067a 100644 --- a/trunk/drivers/ieee1394/highlevel.h +++ b/trunk/drivers/ieee1394/highlevel.h @@ -24,7 +24,6 @@ struct hpsb_address_serve { /* Only the following structures are of interest to actual highlevel drivers. */ struct hpsb_highlevel { - struct module *owner; const char *name; /* Any of the following pointers can legally be NULL, except for diff --git a/trunk/drivers/ieee1394/hosts.c b/trunk/drivers/ieee1394/hosts.c index d90a3a1898c0..ee82a5320bf7 100644 --- a/trunk/drivers/ieee1394/hosts.c +++ b/trunk/drivers/ieee1394/hosts.c @@ -31,9 +31,10 @@ #include "config_roms.h" -static void delayed_reset_bus(void * __reset_info) +static void delayed_reset_bus(struct work_struct *work) { - struct hpsb_host *host = (struct hpsb_host*)__reset_info; + struct hpsb_host *host = + container_of(work, struct hpsb_host, delayed_reset.work); int generation = host->csr.generation + 1; /* The generation field rolls over to 2 rather than 0 per IEEE @@ -43,9 +44,10 @@ static void delayed_reset_bus(void * __reset_info) CSR_SET_BUS_INFO_GENERATION(host->csr.rom, generation); if (csr1212_generate_csr_image(host->csr.rom) != CSR1212_SUCCESS) { - /* CSR image creation failed, reset generation field and do not - * issue a bus reset. */ - CSR_SET_BUS_INFO_GENERATION(host->csr.rom, host->csr.generation); + /* CSR image creation failed. + * Reset generation field and do not issue a bus reset. */ + CSR_SET_BUS_INFO_GENERATION(host->csr.rom, + host->csr.generation); return; } @@ -53,7 +55,8 @@ static void delayed_reset_bus(void * __reset_info) host->update_config_rom = 0; if (host->driver->set_hw_config_rom) - host->driver->set_hw_config_rom(host, host->csr.rom->bus_info_data); + host->driver->set_hw_config_rom(host, + host->csr.rom->bus_info_data); host->csr.gen_timestamp[host->csr.generation] = jiffies; hpsb_reset_bus(host, SHORT_RESET); @@ -69,7 +72,8 @@ static int dummy_devctl(struct hpsb_host *h, enum devctl_cmd c, int arg) return -1; } -static int dummy_isoctl(struct hpsb_iso *iso, enum isoctl_cmd command, unsigned long arg) +static int dummy_isoctl(struct hpsb_iso *iso, enum isoctl_cmd command, + unsigned long arg) { return -1; } @@ -122,15 +126,13 @@ struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra, int i; int hostnum = 0; - h = kzalloc(sizeof(*h) + extra, SLAB_KERNEL); + h = kzalloc(sizeof(*h) + extra, GFP_KERNEL); if (!h) return NULL; h->csr.rom = csr1212_create_csr(&csr_bus_ops, CSR_BUS_INFO_SIZE, h); - if (!h->csr.rom) { - kfree(h); - return NULL; - } + if (!h->csr.rom) + goto fail; h->hostdata = h + 1; h->driver = drv; @@ -145,21 +147,20 @@ struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra, atomic_set(&h->generation, 0); - INIT_WORK(&h->delayed_reset, delayed_reset_bus, h); + INIT_DELAYED_WORK(&h->delayed_reset, delayed_reset_bus); init_timer(&h->timeout); h->timeout.data = (unsigned long) h; h->timeout.function = abort_timedouts; - h->timeout_interval = HZ / 20; // 50ms by default + h->timeout_interval = HZ / 20; /* 50ms, half of minimum SPLIT_TIMEOUT */ h->topology_map = h->csr.topology_map + 3; h->speed_map = (u8 *)(h->csr.speed_map + 2); mutex_lock(&host_num_alloc); - while (nodemgr_for_each_host(&hostnum, alloc_hostnum_cb)) hostnum++; - + mutex_unlock(&host_num_alloc); h->id = hostnum; memcpy(&h->device, &nodemgr_dev_template_host, sizeof(h->device)); @@ -170,13 +171,19 @@ struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra, h->class_dev.class = &hpsb_host_class; snprintf(h->class_dev.class_id, BUS_ID_SIZE, "fw-host%d", h->id); - device_register(&h->device); - class_device_register(&h->class_dev); + if (device_register(&h->device)) + goto fail; + if (class_device_register(&h->class_dev)) { + device_unregister(&h->device); + goto fail; + } get_device(&h->device); - mutex_unlock(&host_num_alloc); - return h; + +fail: + kfree(h); + return NULL; } int hpsb_add_host(struct hpsb_host *host) @@ -228,13 +235,14 @@ int hpsb_update_config_rom_image(struct hpsb_host *host) if (time_before(jiffies, host->csr.gen_timestamp[next_gen] + 60 * HZ)) /* Wait 60 seconds from the last time this generation number was * used. */ - reset_delay = (60 * HZ) + host->csr.gen_timestamp[next_gen] - jiffies; + reset_delay = + (60 * HZ) + host->csr.gen_timestamp[next_gen] - jiffies; else /* Wait 1 second in case some other code wants to change the * Config ROM in the near future. */ reset_delay = HZ; - PREPARE_WORK(&host->delayed_reset, delayed_reset_bus, host); + PREPARE_DELAYED_WORK(&host->delayed_reset, delayed_reset_bus); schedule_delayed_work(&host->delayed_reset, reset_delay); return 0; diff --git a/trunk/drivers/ieee1394/hosts.h b/trunk/drivers/ieee1394/hosts.h index bc6dbfadb891..d553e38c9543 100644 --- a/trunk/drivers/ieee1394/hosts.h +++ b/trunk/drivers/ieee1394/hosts.h @@ -62,7 +62,7 @@ struct hpsb_host { struct class_device class_dev; int update_config_rom; - struct work_struct delayed_reset; + struct delayed_work delayed_reset; unsigned int config_roms; struct list_head addr_space; diff --git a/trunk/drivers/ieee1394/ieee1394_core.c b/trunk/drivers/ieee1394/ieee1394_core.c index 5fccf9f7a1d2..9a48ca20d1fd 100644 --- a/trunk/drivers/ieee1394/ieee1394_core.c +++ b/trunk/drivers/ieee1394/ieee1394_core.c @@ -1237,10 +1237,10 @@ EXPORT_SYMBOL(highlevel_remove_host); /** nodemgr.c **/ EXPORT_SYMBOL(hpsb_node_fill_packet); EXPORT_SYMBOL(hpsb_node_write); -EXPORT_SYMBOL(hpsb_register_protocol); +EXPORT_SYMBOL(__hpsb_register_protocol); EXPORT_SYMBOL(hpsb_unregister_protocol); -EXPORT_SYMBOL(ieee1394_bus_type); #ifdef CONFIG_IEEE1394_EXPORT_FULL_API +EXPORT_SYMBOL(ieee1394_bus_type); EXPORT_SYMBOL(nodemgr_for_each_host); #endif diff --git a/trunk/drivers/ieee1394/ieee1394_core.h b/trunk/drivers/ieee1394/ieee1394_core.h index af4a78a8ef3b..536ba3f580fd 100644 --- a/trunk/drivers/ieee1394/ieee1394_core.h +++ b/trunk/drivers/ieee1394/ieee1394_core.h @@ -217,7 +217,7 @@ void hpsb_packet_received(struct hpsb_host *host, quadlet_t *data, size_t size, /* return the index (within a minor number block) of a file */ static inline unsigned char ieee1394_file_to_instance(struct file *file) { - return file->f_dentry->d_inode->i_cindex; + return file->f_path.dentry->d_inode->i_cindex; } extern int hpsb_disable_irm; diff --git a/trunk/drivers/ieee1394/nodemgr.c b/trunk/drivers/ieee1394/nodemgr.c index 8e7b83f84485..61307ca296ae 100644 --- a/trunk/drivers/ieee1394/nodemgr.c +++ b/trunk/drivers/ieee1394/nodemgr.c @@ -14,7 +14,9 @@ #include #include #include +#include #include +#include #include #include "csr.h" @@ -66,7 +68,7 @@ static int nodemgr_check_speed(struct nodemgr_csr_info *ci, u64 addr, { quadlet_t q; u8 i, *speed, old_speed, good_speed; - int ret; + int error; speed = &(ci->host->speed[NODEID_TO_NODE(ci->nodeid)]); old_speed = *speed; @@ -78,9 +80,9 @@ static int nodemgr_check_speed(struct nodemgr_csr_info *ci, u64 addr, * just finished its initialization. */ for (i = IEEE1394_SPEED_100; i <= old_speed; i++) { *speed = i; - ret = hpsb_read(ci->host, ci->nodeid, ci->generation, addr, - &q, sizeof(quadlet_t)); - if (ret) + error = hpsb_read(ci->host, ci->nodeid, ci->generation, addr, + &q, sizeof(quadlet_t)); + if (error) break; *buffer = q; good_speed = i; @@ -94,19 +96,19 @@ static int nodemgr_check_speed(struct nodemgr_csr_info *ci, u64 addr, return 0; } *speed = old_speed; - return ret; + return error; } static int nodemgr_bus_read(struct csr1212_csr *csr, u64 addr, u16 length, - void *buffer, void *__ci) + void *buffer, void *__ci) { struct nodemgr_csr_info *ci = (struct nodemgr_csr_info*)__ci; - int i, ret; + int i, error; for (i = 1; ; i++) { - ret = hpsb_read(ci->host, ci->nodeid, ci->generation, addr, - buffer, length); - if (!ret) { + error = hpsb_read(ci->host, ci->nodeid, ci->generation, addr, + buffer, length); + if (!error) { ci->speed_unverified = 0; break; } @@ -117,14 +119,14 @@ static int nodemgr_bus_read(struct csr1212_csr *csr, u64 addr, u16 length, /* The ieee1394_core guessed the node's speed capability from * the self ID. Check whether a lower speed works. */ if (ci->speed_unverified && length == sizeof(quadlet_t)) { - ret = nodemgr_check_speed(ci, addr, buffer); - if (!ret) + error = nodemgr_check_speed(ci, addr, buffer); + if (!error) break; } if (msleep_interruptible(334)) return -EINTR; } - return ret; + return error; } static int nodemgr_get_max_rom(quadlet_t *bus_info_data, void *__ci) @@ -259,9 +261,20 @@ static struct device nodemgr_dev_template_ne = { .release = nodemgr_release_ne, }; +/* This dummy driver prevents the host devices from being scanned. We have no + * useful drivers for them yet, and there would be a deadlock possible if the + * driver core scans the host device while the host's low-level driver (i.e. + * the host's parent device) is being removed. */ +static struct device_driver nodemgr_mid_layer_driver = { + .bus = &ieee1394_bus_type, + .name = "nodemgr", + .owner = THIS_MODULE, +}; + struct device nodemgr_dev_template_host = { .bus = &ieee1394_bus_type, .release = nodemgr_release_host, + .driver = &nodemgr_mid_layer_driver, }; @@ -306,8 +319,8 @@ static ssize_t fw_drv_show_##field (struct device_driver *drv, char *buf) \ return sprintf(buf, format_string, (type)driver->field);\ } \ static struct driver_attribute driver_attr_drv_##field = { \ - .attr = {.name = __stringify(field), .mode = S_IRUGO }, \ - .show = fw_drv_show_##field, \ + .attr = {.name = __stringify(field), .mode = S_IRUGO }, \ + .show = fw_drv_show_##field, \ }; @@ -361,7 +374,7 @@ static ssize_t fw_show_ne_tlabels_mask(struct device *dev, #endif spin_unlock_irqrestore(&hpsb_tlabel_lock, flags); - return sprintf(buf, "0x%016llx\n", tm); + return sprintf(buf, "0x%016llx\n", (unsigned long long)tm); } static DEVICE_ATTR(tlabels_mask, S_IRUGO, fw_show_ne_tlabels_mask, NULL); #endif /* HPSB_DEBUG_TLABELS */ @@ -373,11 +386,11 @@ static ssize_t fw_set_ignore_driver(struct device *dev, struct device_attribute int state = simple_strtoul(buf, NULL, 10); if (state == 1) { - down_write(&dev->bus->subsys.rwsem); - device_release_driver(dev); ud->ignore_driver = 1; - up_write(&dev->bus->subsys.rwsem); - } else if (!state) + down_write(&ieee1394_bus_type.subsys.rwsem); + device_release_driver(dev); + up_write(&ieee1394_bus_type.subsys.rwsem); + } else if (state == 0) ud->ignore_driver = 0; return count; @@ -412,11 +425,14 @@ static ssize_t fw_get_destroy_node(struct bus_type *bus, char *buf) static BUS_ATTR(destroy_node, S_IWUSR | S_IRUGO, fw_get_destroy_node, fw_set_destroy_node); -static ssize_t fw_set_rescan(struct bus_type *bus, const char *buf, size_t count) +static ssize_t fw_set_rescan(struct bus_type *bus, const char *buf, + size_t count) { + int error = 0; + if (simple_strtoul(buf, NULL, 10) == 1) - bus_rescan_devices(&ieee1394_bus_type); - return count; + error = bus_rescan_devices(&ieee1394_bus_type); + return error ? error : count; } static ssize_t fw_get_rescan(struct bus_type *bus, char *buf) { @@ -432,7 +448,7 @@ static ssize_t fw_set_ignore_drivers(struct bus_type *bus, const char *buf, size if (state == 1) ignore_drivers = 1; - else if (!state) + else if (state == 0) ignore_drivers = 0; return count; @@ -525,7 +541,7 @@ static ssize_t fw_show_drv_device_ids(struct device_driver *drv, char *buf) int length = 0; char *scratch = buf; - driver = container_of(drv, struct hpsb_protocol_driver, driver); + driver = container_of(drv, struct hpsb_protocol_driver, driver); for (id = driver->id_table; id->match_flags != 0; id++) { int need_coma = 0; @@ -582,7 +598,11 @@ static void nodemgr_create_drv_files(struct hpsb_protocol_driver *driver) int i; for (i = 0; i < ARRAY_SIZE(fw_drv_attrs); i++) - driver_create_file(drv, fw_drv_attrs[i]); + if (driver_create_file(drv, fw_drv_attrs[i])) + goto fail; + return; +fail: + HPSB_ERR("Failed to add sysfs attribute for driver %s", driver->name); } @@ -602,7 +622,12 @@ static void nodemgr_create_ne_dev_files(struct node_entry *ne) int i; for (i = 0; i < ARRAY_SIZE(fw_ne_attrs); i++) - device_create_file(dev, fw_ne_attrs[i]); + if (device_create_file(dev, fw_ne_attrs[i])) + goto fail; + return; +fail: + HPSB_ERR("Failed to add sysfs attribute for node %016Lx", + (unsigned long long)ne->guid); } @@ -612,11 +637,16 @@ static void nodemgr_create_host_dev_files(struct hpsb_host *host) int i; for (i = 0; i < ARRAY_SIZE(fw_host_attrs); i++) - device_create_file(dev, fw_host_attrs[i]); + if (device_create_file(dev, fw_host_attrs[i])) + goto fail; + return; +fail: + HPSB_ERR("Failed to add sysfs attribute for host %d", host->id); } -static struct node_entry *find_entry_by_nodeid(struct hpsb_host *host, nodeid_t nodeid); +static struct node_entry *find_entry_by_nodeid(struct hpsb_host *host, + nodeid_t nodeid); static void nodemgr_update_host_dev_links(struct hpsb_host *host) { @@ -627,12 +657,18 @@ static void nodemgr_update_host_dev_links(struct hpsb_host *host) sysfs_remove_link(&dev->kobj, "busmgr_id"); sysfs_remove_link(&dev->kobj, "host_id"); - if ((ne = find_entry_by_nodeid(host, host->irm_id))) - sysfs_create_link(&dev->kobj, &ne->device.kobj, "irm_id"); - if ((ne = find_entry_by_nodeid(host, host->busmgr_id))) - sysfs_create_link(&dev->kobj, &ne->device.kobj, "busmgr_id"); - if ((ne = find_entry_by_nodeid(host, host->node_id))) - sysfs_create_link(&dev->kobj, &ne->device.kobj, "host_id"); + if ((ne = find_entry_by_nodeid(host, host->irm_id)) && + sysfs_create_link(&dev->kobj, &ne->device.kobj, "irm_id")) + goto fail; + if ((ne = find_entry_by_nodeid(host, host->busmgr_id)) && + sysfs_create_link(&dev->kobj, &ne->device.kobj, "busmgr_id")) + goto fail; + if ((ne = find_entry_by_nodeid(host, host->node_id)) && + sysfs_create_link(&dev->kobj, &ne->device.kobj, "host_id")) + goto fail; + return; +fail: + HPSB_ERR("Failed to update sysfs attributes for host %d", host->id); } static void nodemgr_create_ud_dev_files(struct unit_directory *ud) @@ -641,32 +677,39 @@ static void nodemgr_create_ud_dev_files(struct unit_directory *ud) int i; for (i = 0; i < ARRAY_SIZE(fw_ud_attrs); i++) - device_create_file(dev, fw_ud_attrs[i]); - + if (device_create_file(dev, fw_ud_attrs[i])) + goto fail; if (ud->flags & UNIT_DIRECTORY_SPECIFIER_ID) - device_create_file(dev, &dev_attr_ud_specifier_id); - + if (device_create_file(dev, &dev_attr_ud_specifier_id)) + goto fail; if (ud->flags & UNIT_DIRECTORY_VERSION) - device_create_file(dev, &dev_attr_ud_version); - + if (device_create_file(dev, &dev_attr_ud_version)) + goto fail; if (ud->flags & UNIT_DIRECTORY_VENDOR_ID) { - device_create_file(dev, &dev_attr_ud_vendor_id); - if (ud->vendor_name_kv) - device_create_file(dev, &dev_attr_ud_vendor_name_kv); + if (device_create_file(dev, &dev_attr_ud_vendor_id)) + goto fail; + if (ud->vendor_name_kv && + device_create_file(dev, &dev_attr_ud_vendor_name_kv)) + goto fail; } - if (ud->flags & UNIT_DIRECTORY_MODEL_ID) { - device_create_file(dev, &dev_attr_ud_model_id); - if (ud->model_name_kv) - device_create_file(dev, &dev_attr_ud_model_name_kv); + if (device_create_file(dev, &dev_attr_ud_model_id)) + goto fail; + if (ud->model_name_kv && + device_create_file(dev, &dev_attr_ud_model_name_kv)) + goto fail; } + return; +fail: + HPSB_ERR("Failed to add sysfs attributes for unit %s", + ud->device.bus_id); } static int nodemgr_bus_match(struct device * dev, struct device_driver * drv) { - struct hpsb_protocol_driver *driver; - struct unit_directory *ud; + struct hpsb_protocol_driver *driver; + struct unit_directory *ud; struct ieee1394_device_id *id; /* We only match unit directories */ @@ -674,55 +717,77 @@ static int nodemgr_bus_match(struct device * dev, struct device_driver * drv) return 0; ud = container_of(dev, struct unit_directory, device); - driver = container_of(drv, struct hpsb_protocol_driver, driver); - if (ud->ne->in_limbo || ud->ignore_driver) return 0; - for (id = driver->id_table; id->match_flags != 0; id++) { - if ((id->match_flags & IEEE1394_MATCH_VENDOR_ID) && - id->vendor_id != ud->vendor_id) - continue; + /* We only match drivers of type hpsb_protocol_driver */ + if (drv == &nodemgr_mid_layer_driver) + return 0; - if ((id->match_flags & IEEE1394_MATCH_MODEL_ID) && - id->model_id != ud->model_id) - continue; + driver = container_of(drv, struct hpsb_protocol_driver, driver); + for (id = driver->id_table; id->match_flags != 0; id++) { + if ((id->match_flags & IEEE1394_MATCH_VENDOR_ID) && + id->vendor_id != ud->vendor_id) + continue; - if ((id->match_flags & IEEE1394_MATCH_SPECIFIER_ID) && - id->specifier_id != ud->specifier_id) - continue; + if ((id->match_flags & IEEE1394_MATCH_MODEL_ID) && + id->model_id != ud->model_id) + continue; - if ((id->match_flags & IEEE1394_MATCH_VERSION) && - id->version != ud->version) - continue; + if ((id->match_flags & IEEE1394_MATCH_SPECIFIER_ID) && + id->specifier_id != ud->specifier_id) + continue; + + if ((id->match_flags & IEEE1394_MATCH_VERSION) && + id->version != ud->version) + continue; return 1; - } + } return 0; } +static DEFINE_MUTEX(nodemgr_serialize_remove_uds); + static void nodemgr_remove_uds(struct node_entry *ne) { - struct class_device *cdev, *next; - struct unit_directory *ud; - - list_for_each_entry_safe(cdev, next, &nodemgr_ud_class.children, node) { - ud = container_of(cdev, struct unit_directory, class_dev); - - if (ud->ne != ne) - continue; - + struct class_device *cdev; + struct unit_directory *tmp, *ud; + + /* Iteration over nodemgr_ud_class.children has to be protected by + * nodemgr_ud_class.sem, but class_device_unregister() will eventually + * take nodemgr_ud_class.sem too. Therefore pick out one ud at a time, + * release the semaphore, and then unregister the ud. Since this code + * may be called from other contexts besides the knodemgrds, protect the + * gap after release of the semaphore by nodemgr_serialize_remove_uds. + */ + mutex_lock(&nodemgr_serialize_remove_uds); + for (;;) { + ud = NULL; + down(&nodemgr_ud_class.sem); + list_for_each_entry(cdev, &nodemgr_ud_class.children, node) { + tmp = container_of(cdev, struct unit_directory, + class_dev); + if (tmp->ne == ne) { + ud = tmp; + break; + } + } + up(&nodemgr_ud_class.sem); + if (ud == NULL) + break; class_device_unregister(&ud->class_dev); device_unregister(&ud->device); } + mutex_unlock(&nodemgr_serialize_remove_uds); } static void nodemgr_remove_ne(struct node_entry *ne) { - struct device *dev = &ne->device; + struct device *dev; dev = get_device(&ne->device); if (!dev) @@ -747,7 +812,7 @@ static int __nodemgr_remove_host_dev(struct device *dev, void *data) static void nodemgr_remove_host_dev(struct device *dev) { - device_for_each_child(dev, NULL, __nodemgr_remove_host_dev); + WARN_ON(device_for_each_child(dev, NULL, __nodemgr_remove_host_dev)); sysfs_remove_link(&dev->kobj, "irm_id"); sysfs_remove_link(&dev->kobj, "busmgr_id"); sysfs_remove_link(&dev->kobj, "host_id"); @@ -761,16 +826,16 @@ static void nodemgr_update_bus_options(struct node_entry *ne) #endif quadlet_t busoptions = be32_to_cpu(ne->csr->bus_info_data[2]); - ne->busopt.irmc = (busoptions >> 31) & 1; - ne->busopt.cmc = (busoptions >> 30) & 1; - ne->busopt.isc = (busoptions >> 29) & 1; - ne->busopt.bmc = (busoptions >> 28) & 1; - ne->busopt.pmc = (busoptions >> 27) & 1; - ne->busopt.cyc_clk_acc = (busoptions >> 16) & 0xff; - ne->busopt.max_rec = 1 << (((busoptions >> 12) & 0xf) + 1); + ne->busopt.irmc = (busoptions >> 31) & 1; + ne->busopt.cmc = (busoptions >> 30) & 1; + ne->busopt.isc = (busoptions >> 29) & 1; + ne->busopt.bmc = (busoptions >> 28) & 1; + ne->busopt.pmc = (busoptions >> 27) & 1; + ne->busopt.cyc_clk_acc = (busoptions >> 16) & 0xff; + ne->busopt.max_rec = 1 << (((busoptions >> 12) & 0xf) + 1); ne->busopt.max_rom = (busoptions >> 8) & 0x3; - ne->busopt.generation = (busoptions >> 4) & 0xf; - ne->busopt.lnkspd = busoptions & 0x7; + ne->busopt.generation = (busoptions >> 4) & 0xf; + ne->busopt.lnkspd = busoptions & 0x7; HPSB_VERBOSE("NodeMgr: raw=0x%08x irmc=%d cmc=%d isc=%d bmc=%d pmc=%d " "cyc_clk_acc=%d max_rec=%d max_rom=%d gen=%d lspd=%d", @@ -791,7 +856,7 @@ static struct node_entry *nodemgr_create_node(octlet_t guid, struct csr1212_csr ne = kzalloc(sizeof(*ne), GFP_KERNEL); if (!ne) - return NULL; + goto fail_alloc; ne->host = host; ne->nodeid = nodeid; @@ -814,12 +879,15 @@ static struct node_entry *nodemgr_create_node(octlet_t guid, struct csr1212_csr snprintf(ne->class_dev.class_id, BUS_ID_SIZE, "%016Lx", (unsigned long long)(ne->guid)); - device_register(&ne->device); - class_device_register(&ne->class_dev); + if (device_register(&ne->device)) + goto fail_devreg; + if (class_device_register(&ne->class_dev)) + goto fail_classdevreg; get_device(&ne->device); - if (ne->guid_vendor_oui) - device_create_file(&ne->device, &dev_attr_ne_guid_vendor_oui); + if (ne->guid_vendor_oui && + device_create_file(&ne->device, &dev_attr_ne_guid_vendor_oui)) + goto fail_addoiu; nodemgr_create_ne_dev_files(ne); nodemgr_update_bus_options(ne); @@ -829,17 +897,28 @@ static struct node_entry *nodemgr_create_node(octlet_t guid, struct csr1212_csr NODE_BUS_ARGS(host, nodeid), (unsigned long long)guid); return ne; + +fail_addoiu: + put_device(&ne->device); +fail_classdevreg: + device_unregister(&ne->device); +fail_devreg: + kfree(ne); +fail_alloc: + HPSB_ERR("Failed to create node ID:BUS[" NODE_BUS_FMT "] GUID[%016Lx]", + NODE_BUS_ARGS(host, nodeid), (unsigned long long)guid); + + return NULL; } static struct node_entry *find_entry_by_guid(u64 guid) { - struct class *class = &nodemgr_ne_class; struct class_device *cdev; struct node_entry *ne, *ret_ne = NULL; - down_read(&class->subsys.rwsem); - list_for_each_entry(cdev, &class->children, node) { + down(&nodemgr_ne_class.sem); + list_for_each_entry(cdev, &nodemgr_ne_class.children, node) { ne = container_of(cdev, struct node_entry, class_dev); if (ne->guid == guid) { @@ -847,20 +926,20 @@ static struct node_entry *find_entry_by_guid(u64 guid) break; } } - up_read(&class->subsys.rwsem); + up(&nodemgr_ne_class.sem); - return ret_ne; + return ret_ne; } -static struct node_entry *find_entry_by_nodeid(struct hpsb_host *host, nodeid_t nodeid) +static struct node_entry *find_entry_by_nodeid(struct hpsb_host *host, + nodeid_t nodeid) { - struct class *class = &nodemgr_ne_class; struct class_device *cdev; struct node_entry *ne, *ret_ne = NULL; - down_read(&class->subsys.rwsem); - list_for_each_entry(cdev, &class->children, node) { + down(&nodemgr_ne_class.sem); + list_for_each_entry(cdev, &nodemgr_ne_class.children, node) { ne = container_of(cdev, struct node_entry, class_dev); if (ne->host == host && ne->nodeid == nodeid) { @@ -868,7 +947,7 @@ static struct node_entry *find_entry_by_nodeid(struct hpsb_host *host, nodeid_t break; } } - up_read(&class->subsys.rwsem); + up(&nodemgr_ne_class.sem); return ret_ne; } @@ -890,13 +969,25 @@ static void nodemgr_register_device(struct node_entry *ne, snprintf(ud->class_dev.class_id, BUS_ID_SIZE, "%s-%u", ne->device.bus_id, ud->id); - device_register(&ud->device); - class_device_register(&ud->class_dev); + if (device_register(&ud->device)) + goto fail_devreg; + if (class_device_register(&ud->class_dev)) + goto fail_classdevreg; get_device(&ud->device); - if (ud->vendor_oui) - device_create_file(&ud->device, &dev_attr_ud_vendor_oui); + if (ud->vendor_oui && + device_create_file(&ud->device, &dev_attr_ud_vendor_oui)) + goto fail_addoui; nodemgr_create_ud_dev_files(ud); + + return; + +fail_addoui: + put_device(&ud->device); +fail_classdevreg: + device_unregister(&ud->device); +fail_devreg: + HPSB_ERR("Failed to create unit %s", ud->device.bus_id); } @@ -976,10 +1067,9 @@ static struct unit_directory *nodemgr_process_unit_directory /* Logical Unit Number */ if (kv->key.type == CSR1212_KV_TYPE_IMMEDIATE) { if (ud->flags & UNIT_DIRECTORY_HAS_LUN) { - ud_child = kmalloc(sizeof(*ud_child), GFP_KERNEL); + ud_child = kmemdup(ud, sizeof(*ud_child), GFP_KERNEL); if (!ud_child) goto unit_directory_error; - memcpy(ud_child, ud, sizeof(*ud_child)); nodemgr_register_device(ne, ud_child, &ne->device); ud_child = NULL; @@ -1093,10 +1183,16 @@ static void nodemgr_process_root_directory(struct host_info *hi, struct node_ent last_key_id = kv->key.id; } - if (ne->vendor_oui) - device_create_file(&ne->device, &dev_attr_ne_vendor_oui); - if (ne->vendor_name_kv) - device_create_file(&ne->device, &dev_attr_ne_vendor_name_kv); + if (ne->vendor_oui && + device_create_file(&ne->device, &dev_attr_ne_vendor_oui)) + goto fail; + if (ne->vendor_name_kv && + device_create_file(&ne->device, &dev_attr_ne_vendor_name_kv)) + goto fail; + return; +fail: + HPSB_ERR("Failed to add sysfs attribute for node %016Lx", + (unsigned long long)ne->guid); } #ifdef CONFIG_HOTPLUG @@ -1160,16 +1256,20 @@ static int nodemgr_uevent(struct class_device *cdev, char **envp, int num_envp, #endif /* CONFIG_HOTPLUG */ -int hpsb_register_protocol(struct hpsb_protocol_driver *driver) +int __hpsb_register_protocol(struct hpsb_protocol_driver *drv, + struct module *owner) { - int ret; + int error; - /* This will cause a probe for devices */ - ret = driver_register(&driver->driver); - if (!ret) - nodemgr_create_drv_files(driver); + drv->driver.bus = &ieee1394_bus_type; + drv->driver.owner = owner; + drv->driver.name = drv->name; - return ret; + /* This will cause a probe for devices */ + error = driver_register(&drv->driver); + if (!error) + nodemgr_create_drv_files(drv); + return error; } void hpsb_unregister_protocol(struct hpsb_protocol_driver *driver) @@ -1297,26 +1397,25 @@ static void nodemgr_node_scan_one(struct host_info *hi, static void nodemgr_node_scan(struct host_info *hi, int generation) { - int count; - struct hpsb_host *host = hi->host; - struct selfid *sid = (struct selfid *)host->topology_map; - nodeid_t nodeid = LOCAL_BUS; + int count; + struct hpsb_host *host = hi->host; + struct selfid *sid = (struct selfid *)host->topology_map; + nodeid_t nodeid = LOCAL_BUS; - /* Scan each node on the bus */ - for (count = host->selfid_count; count; count--, sid++) { - if (sid->extended) - continue; + /* Scan each node on the bus */ + for (count = host->selfid_count; count; count--, sid++) { + if (sid->extended) + continue; - if (!sid->link_active) { - nodeid++; - continue; - } - nodemgr_node_scan_one(hi, nodeid++, generation); - } + if (!sid->link_active) { + nodeid++; + continue; + } + nodemgr_node_scan_one(hi, nodeid++, generation); + } } -/* Caller needs to hold nodemgr_ud_class.subsys.rwsem as reader. */ static void nodemgr_suspend_ne(struct node_entry *ne) { struct class_device *cdev; @@ -1326,21 +1425,22 @@ static void nodemgr_suspend_ne(struct node_entry *ne) NODE_BUS_ARGS(ne->host, ne->nodeid), (unsigned long long)ne->guid); ne->in_limbo = 1; - device_create_file(&ne->device, &dev_attr_ne_in_limbo); + WARN_ON(device_create_file(&ne->device, &dev_attr_ne_in_limbo)); - down_write(&ne->device.bus->subsys.rwsem); + down(&nodemgr_ud_class.sem); list_for_each_entry(cdev, &nodemgr_ud_class.children, node) { ud = container_of(cdev, struct unit_directory, class_dev); - if (ud->ne != ne) continue; + down_write(&ieee1394_bus_type.subsys.rwsem); if (ud->device.driver && (!ud->device.driver->suspend || ud->device.driver->suspend(&ud->device, PMSG_SUSPEND))) device_release_driver(&ud->device); + up_write(&ieee1394_bus_type.subsys.rwsem); } - up_write(&ne->device.bus->subsys.rwsem); + up(&nodemgr_ud_class.sem); } @@ -1352,45 +1452,47 @@ static void nodemgr_resume_ne(struct node_entry *ne) ne->in_limbo = 0; device_remove_file(&ne->device, &dev_attr_ne_in_limbo); - down_read(&nodemgr_ud_class.subsys.rwsem); - down_read(&ne->device.bus->subsys.rwsem); + down(&nodemgr_ud_class.sem); list_for_each_entry(cdev, &nodemgr_ud_class.children, node) { ud = container_of(cdev, struct unit_directory, class_dev); - if (ud->ne != ne) continue; + down_read(&ieee1394_bus_type.subsys.rwsem); if (ud->device.driver && ud->device.driver->resume) ud->device.driver->resume(&ud->device); + up_read(&ieee1394_bus_type.subsys.rwsem); } - up_read(&ne->device.bus->subsys.rwsem); - up_read(&nodemgr_ud_class.subsys.rwsem); + up(&nodemgr_ud_class.sem); HPSB_DEBUG("Node resumed: ID:BUS[" NODE_BUS_FMT "] GUID[%016Lx]", NODE_BUS_ARGS(ne->host, ne->nodeid), (unsigned long long)ne->guid); } -/* Caller needs to hold nodemgr_ud_class.subsys.rwsem as reader. */ static void nodemgr_update_pdrv(struct node_entry *ne) { struct unit_directory *ud; struct hpsb_protocol_driver *pdrv; struct class_device *cdev; + down(&nodemgr_ud_class.sem); list_for_each_entry(cdev, &nodemgr_ud_class.children, node) { ud = container_of(cdev, struct unit_directory, class_dev); - if (ud->ne != ne || !ud->device.driver) + if (ud->ne != ne) continue; - pdrv = container_of(ud->device.driver, struct hpsb_protocol_driver, driver); - - if (pdrv->update && pdrv->update(ud)) { - down_write(&ud->device.bus->subsys.rwsem); - device_release_driver(&ud->device); - up_write(&ud->device.bus->subsys.rwsem); + down_write(&ieee1394_bus_type.subsys.rwsem); + if (ud->device.driver) { + pdrv = container_of(ud->device.driver, + struct hpsb_protocol_driver, + driver); + if (pdrv->update && pdrv->update(ud)) + device_release_driver(&ud->device); } + up_write(&ieee1394_bus_type.subsys.rwsem); } + up(&nodemgr_ud_class.sem); } @@ -1404,7 +1506,7 @@ static void nodemgr_irm_write_bc(struct node_entry *ne, int generation) { const u64 bc_addr = (CSR_REGISTER_BASE | CSR_BROADCAST_CHANNEL); quadlet_t bc_remote, bc_local; - int ret; + int error; if (!ne->host->is_irm || ne->generation != generation || ne->nodeid == ne->host->node_id) @@ -1413,16 +1515,14 @@ static void nodemgr_irm_write_bc(struct node_entry *ne, int generation) bc_local = cpu_to_be32(ne->host->csr.broadcast_channel); /* Check if the register is implemented and 1394a compliant. */ - ret = hpsb_read(ne->host, ne->nodeid, generation, bc_addr, &bc_remote, - sizeof(bc_remote)); - if (!ret && bc_remote & cpu_to_be32(0x80000000) && + error = hpsb_read(ne->host, ne->nodeid, generation, bc_addr, &bc_remote, + sizeof(bc_remote)); + if (!error && bc_remote & cpu_to_be32(0x80000000) && bc_remote != bc_local) hpsb_node_write(ne, bc_addr, &bc_local, sizeof(bc_local)); } -/* Caller needs to hold nodemgr_ud_class.subsys.rwsem as reader because the - * calls to nodemgr_update_pdrv() and nodemgr_suspend_ne() here require it. */ static void nodemgr_probe_ne(struct host_info *hi, struct node_entry *ne, int generation) { struct device *dev; @@ -1455,7 +1555,6 @@ static void nodemgr_probe_ne(struct host_info *hi, struct node_entry *ne, int ge static void nodemgr_node_probe(struct host_info *hi, int generation) { struct hpsb_host *host = hi->host; - struct class *class = &nodemgr_ne_class; struct class_device *cdev; struct node_entry *ne; @@ -1468,18 +1567,18 @@ static void nodemgr_node_probe(struct host_info *hi, int generation) * while probes are time-consuming. (Well, those probes need some * improvement...) */ - down_read(&class->subsys.rwsem); - list_for_each_entry(cdev, &class->children, node) { + down(&nodemgr_ne_class.sem); + list_for_each_entry(cdev, &nodemgr_ne_class.children, node) { ne = container_of(cdev, struct node_entry, class_dev); if (!ne->needs_probe) nodemgr_probe_ne(hi, ne, generation); } - list_for_each_entry(cdev, &class->children, node) { + list_for_each_entry(cdev, &nodemgr_ne_class.children, node) { ne = container_of(cdev, struct node_entry, class_dev); if (ne->needs_probe) nodemgr_probe_ne(hi, ne, generation); } - up_read(&class->subsys.rwsem); + up(&nodemgr_ne_class.sem); /* If we had a bus reset while we were scanning the bus, it is @@ -1497,15 +1596,14 @@ static void nodemgr_node_probe(struct host_info *hi, int generation) * just removed. */ if (generation == get_hpsb_generation(host)) - bus_rescan_devices(&ieee1394_bus_type); - - return; + if (bus_rescan_devices(&ieee1394_bus_type)) + HPSB_DEBUG("bus_rescan_devices had an error"); } static int nodemgr_send_resume_packet(struct hpsb_host *host) { struct hpsb_packet *packet; - int ret = 1; + int error = -ENOMEM; packet = hpsb_make_phypacket(host, EXTPHYPACKET_TYPE_RESUME | @@ -1513,12 +1611,12 @@ static int nodemgr_send_resume_packet(struct hpsb_host *host) if (packet) { packet->no_waiter = 1; packet->generation = get_hpsb_generation(host); - ret = hpsb_send_packet(packet); + error = hpsb_send_packet(packet); } - if (ret) + if (error) HPSB_WARN("fw-host%d: Failed to broadcast resume packet", host->id); - return ret; + return error; } /* Perform a few high-level IRM responsibilities. */ @@ -1691,19 +1789,18 @@ static int nodemgr_host_thread(void *__hi) int nodemgr_for_each_host(void *__data, int (*cb)(struct hpsb_host *, void *)) { - struct class *class = &hpsb_host_class; struct class_device *cdev; struct hpsb_host *host; int error = 0; - down_read(&class->subsys.rwsem); - list_for_each_entry(cdev, &class->children, node) { + down(&hpsb_host_class.sem); + list_for_each_entry(cdev, &hpsb_host_class.children, node) { host = container_of(cdev, struct hpsb_host, class_dev); if ((error = cb(host, __data))) break; } - up_read(&class->subsys.rwsem); + up(&hpsb_host_class.sem); return error; } @@ -1725,10 +1822,10 @@ int nodemgr_for_each_host(void *__data, int (*cb)(struct hpsb_host *, void *)) void hpsb_node_fill_packet(struct node_entry *ne, struct hpsb_packet *pkt) { - pkt->host = ne->host; - pkt->generation = ne->generation; + pkt->host = ne->host; + pkt->generation = ne->generation; barrier(); - pkt->node_id = ne->nodeid; + pkt->node_id = ne->nodeid; } int hpsb_node_write(struct node_entry *ne, u64 addr, @@ -1788,26 +1885,25 @@ static struct hpsb_highlevel nodemgr_highlevel = { int init_ieee1394_nodemgr(void) { - int ret; + int error; - ret = class_register(&nodemgr_ne_class); - if (ret < 0) - return ret; + error = class_register(&nodemgr_ne_class); + if (error) + return error; - ret = class_register(&nodemgr_ud_class); - if (ret < 0) { + error = class_register(&nodemgr_ud_class); + if (error) { class_unregister(&nodemgr_ne_class); - return ret; + return error; } - + error = driver_register(&nodemgr_mid_layer_driver); hpsb_register_highlevel(&nodemgr_highlevel); - return 0; } void cleanup_ieee1394_nodemgr(void) { - hpsb_unregister_highlevel(&nodemgr_highlevel); + hpsb_unregister_highlevel(&nodemgr_highlevel); class_unregister(&nodemgr_ud_class); class_unregister(&nodemgr_ne_class); diff --git a/trunk/drivers/ieee1394/nodemgr.h b/trunk/drivers/ieee1394/nodemgr.h index 0e1e7d930783..e25cbadb8be0 100644 --- a/trunk/drivers/ieee1394/nodemgr.h +++ b/trunk/drivers/ieee1394/nodemgr.h @@ -144,7 +144,12 @@ struct hpsb_protocol_driver { struct device_driver driver; }; -int hpsb_register_protocol(struct hpsb_protocol_driver *driver); +int __hpsb_register_protocol(struct hpsb_protocol_driver *, struct module *); +static inline int hpsb_register_protocol(struct hpsb_protocol_driver *driver) +{ + return __hpsb_register_protocol(driver, THIS_MODULE); +} + void hpsb_unregister_protocol(struct hpsb_protocol_driver *driver); static inline int hpsb_node_entry_valid(struct node_entry *ne) diff --git a/trunk/drivers/ieee1394/ohci1394.c b/trunk/drivers/ieee1394/ohci1394.c index 6e8ea9110c46..628130a58af3 100644 --- a/trunk/drivers/ieee1394/ohci1394.c +++ b/trunk/drivers/ieee1394/ohci1394.c @@ -468,7 +468,6 @@ static int get_nb_iso_ctx(struct ti_ohci *ohci, int reg) /* Global initialization */ static void ohci_initialize(struct ti_ohci *ohci) { - char irq_buf[16]; quadlet_t buf; int num_ports, i; @@ -586,11 +585,10 @@ static void ohci_initialize(struct ti_ohci *ohci) reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_linkEnable); buf = reg_read(ohci, OHCI1394_Version); - sprintf (irq_buf, "%d", ohci->dev->irq); - PRINT(KERN_INFO, "OHCI-1394 %d.%d (PCI): IRQ=[%s] " + PRINT(KERN_INFO, "OHCI-1394 %d.%d (PCI): IRQ=[%d] " "MMIO=[%llx-%llx] Max Packet=[%d] IR/IT contexts=[%d/%d]", ((((buf) >> 16) & 0xf) + (((buf) >> 20) & 0xf) * 10), - ((((buf) >> 4) & 0xf) + ((buf) & 0xf) * 10), irq_buf, + ((((buf) >> 4) & 0xf) + ((buf) & 0xf) * 10), ohci->dev->irq, (unsigned long long)pci_resource_start(ohci->dev, 0), (unsigned long long)pci_resource_start(ohci->dev, 0) + OHCI1394_REGISTER_SIZE - 1, ohci->max_packet_size, @@ -1225,7 +1223,7 @@ static int ohci_iso_recv_init(struct hpsb_iso *iso) int ctx; int ret = -ENOMEM; - recv = kmalloc(sizeof(*recv), SLAB_KERNEL); + recv = kmalloc(sizeof(*recv), GFP_KERNEL); if (!recv) return -ENOMEM; @@ -1918,7 +1916,7 @@ static int ohci_iso_xmit_init(struct hpsb_iso *iso) int ctx; int ret = -ENOMEM; - xmit = kmalloc(sizeof(*xmit), SLAB_KERNEL); + xmit = kmalloc(sizeof(*xmit), GFP_KERNEL); if (!xmit) return -ENOMEM; @@ -3021,7 +3019,7 @@ alloc_dma_rcv_ctx(struct ti_ohci *ohci, struct dma_rcv_ctx *d, return -ENOMEM; } - d->prg_cpu[i] = pci_pool_alloc(d->prg_pool, SLAB_KERNEL, d->prg_bus+i); + d->prg_cpu[i] = pci_pool_alloc(d->prg_pool, GFP_KERNEL, d->prg_bus+i); OHCI_DMA_ALLOC("pool dma_rcv prg[%d]", i); if (d->prg_cpu[i] != NULL) { @@ -3117,7 +3115,7 @@ alloc_dma_trm_ctx(struct ti_ohci *ohci, struct dma_trm_ctx *d, OHCI_DMA_ALLOC("dma_rcv prg pool"); for (i = 0; i < d->num_desc; i++) { - d->prg_cpu[i] = pci_pool_alloc(d->prg_pool, SLAB_KERNEL, d->prg_bus+i); + d->prg_cpu[i] = pci_pool_alloc(d->prg_pool, GFP_KERNEL, d->prg_bus+i); OHCI_DMA_ALLOC("pool dma_trm prg[%d]", i); if (d->prg_cpu[i] != NULL) { @@ -3217,6 +3215,18 @@ static int __devinit ohci1394_pci_probe(struct pci_dev *dev, struct ti_ohci *ohci; /* shortcut to currently handled device */ resource_size_t ohci_base; +#ifdef CONFIG_PPC_PMAC + /* Necessary on some machines if ohci1394 was loaded/ unloaded before */ + if (machine_is(powermac)) { + struct device_node *ofn = pci_device_to_OF_node(dev); + + if (ofn) { + pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, ofn, 0, 1); + pmac_call_feature(PMAC_FTR_1394_ENABLE, ofn, 0, 1); + } + } +#endif /* CONFIG_PPC_PMAC */ + if (pci_enable_device(dev)) FAIL(-ENXIO, "Failed to enable OHCI hardware"); pci_set_master(dev); @@ -3505,17 +3515,14 @@ static void ohci1394_pci_remove(struct pci_dev *pdev) #endif #ifdef CONFIG_PPC_PMAC - /* On UniNorth, power down the cable and turn off the chip - * clock when the module is removed to save power on - * laptops. Turning it back ON is done by the arch code when - * pci_enable_device() is called */ - { - struct device_node* of_node; + /* On UniNorth, power down the cable and turn off the chip clock + * to save power on laptops */ + if (machine_is(powermac)) { + struct device_node* ofn = pci_device_to_OF_node(ohci->dev); - of_node = pci_device_to_OF_node(ohci->dev); - if (of_node) { - pmac_call_feature(PMAC_FTR_1394_ENABLE, of_node, 0, 0); - pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, of_node, 0, 0); + if (ofn) { + pmac_call_feature(PMAC_FTR_1394_ENABLE, ofn, 0, 0); + pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, ofn, 0, 0); } } #endif /* CONFIG_PPC_PMAC */ @@ -3529,59 +3536,102 @@ static void ohci1394_pci_remove(struct pci_dev *pdev) } #ifdef CONFIG_PM -static int ohci1394_pci_resume (struct pci_dev *pdev) -{ -/* PowerMac resume code comes first */ -#ifdef CONFIG_PPC_PMAC - if (machine_is(powermac)) { - struct device_node *of_node; - - /* Re-enable 1394 */ - of_node = pci_device_to_OF_node (pdev); - if (of_node) - pmac_call_feature (PMAC_FTR_1394_ENABLE, of_node, 0, 1); - } -#endif /* CONFIG_PPC_PMAC */ - - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - return pci_enable_device(pdev); -} - -static int ohci1394_pci_suspend (struct pci_dev *pdev, pm_message_t state) +static int ohci1394_pci_suspend(struct pci_dev *pdev, pm_message_t state) { int err; + struct ti_ohci *ohci = pci_get_drvdata(pdev); printk(KERN_INFO "%s does not fully support suspend and resume yet\n", OHCI1394_DRIVER_NAME); + if (!ohci) { + printk(KERN_ERR "%s: tried to suspend nonexisting host\n", + OHCI1394_DRIVER_NAME); + return -ENXIO; + } + DBGMSG("suspend called"); + + /* Clear the async DMA contexts and stop using the controller */ + hpsb_bus_reset(ohci->host); + + /* See ohci1394_pci_remove() for comments on this sequence */ + reg_write(ohci, OHCI1394_ConfigROMhdr, 0); + reg_write(ohci, OHCI1394_BusOptions, + (reg_read(ohci, OHCI1394_BusOptions) & 0x0000f007) | + 0x00ff0000); + reg_write(ohci, OHCI1394_IntMaskClear, 0xffffffff); + reg_write(ohci, OHCI1394_IntEventClear, 0xffffffff); + reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, 0xffffffff); + reg_write(ohci, OHCI1394_IsoXmitIntEventClear, 0xffffffff); + reg_write(ohci, OHCI1394_IsoRecvIntMaskClear, 0xffffffff); + reg_write(ohci, OHCI1394_IsoRecvIntEventClear, 0xffffffff); + set_phy_reg(ohci, 4, ~0xc0 & get_phy_reg(ohci, 4)); + reg_write(ohci, OHCI1394_LinkControlClear, 0xffffffff); + ohci_devctl(ohci->host, RESET_BUS, LONG_RESET_NO_FORCE_ROOT); + ohci_soft_reset(ohci); + err = pci_save_state(pdev); if (err) { - printk(KERN_ERR "%s: pci_save_state failed with %d\n", - OHCI1394_DRIVER_NAME, err); + PRINT(KERN_ERR, "pci_save_state failed with %d", err); return err; } err = pci_set_power_state(pdev, pci_choose_state(pdev, state)); -#ifdef OHCI1394_DEBUG if (err) - printk(KERN_DEBUG "%s: pci_set_power_state failed with %d\n", - OHCI1394_DRIVER_NAME, err); -#endif /* OHCI1394_DEBUG */ + DBGMSG("pci_set_power_state failed with %d", err); /* PowerMac suspend code comes last */ #ifdef CONFIG_PPC_PMAC if (machine_is(powermac)) { - struct device_node *of_node; + struct device_node *ofn = pci_device_to_OF_node(pdev); - /* Disable 1394 */ - of_node = pci_device_to_OF_node (pdev); - if (of_node) - pmac_call_feature(PMAC_FTR_1394_ENABLE, of_node, 0, 0); + if (ofn) + pmac_call_feature(PMAC_FTR_1394_ENABLE, ofn, 0, 0); } #endif /* CONFIG_PPC_PMAC */ return 0; } + +static int ohci1394_pci_resume(struct pci_dev *pdev) +{ + int err; + struct ti_ohci *ohci = pci_get_drvdata(pdev); + + if (!ohci) { + printk(KERN_ERR "%s: tried to resume nonexisting host\n", + OHCI1394_DRIVER_NAME); + return -ENXIO; + } + DBGMSG("resume called"); + +/* PowerMac resume code comes first */ +#ifdef CONFIG_PPC_PMAC + if (machine_is(powermac)) { + struct device_node *ofn = pci_device_to_OF_node(pdev); + + if (ofn) + pmac_call_feature(PMAC_FTR_1394_ENABLE, ofn, 0, 1); + } +#endif /* CONFIG_PPC_PMAC */ + + pci_set_power_state(pdev, PCI_D0); + pci_restore_state(pdev); + err = pci_enable_device(pdev); + if (err) { + PRINT(KERN_ERR, "pci_enable_device failed with %d", err); + return err; + } + + /* See ohci1394_pci_probe() for comments on this sequence */ + ohci_soft_reset(ohci); + reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_LPS); + reg_write(ohci, OHCI1394_IntEventClear, 0xffffffff); + reg_write(ohci, OHCI1394_IntMaskClear, 0xffffffff); + mdelay(50); + ohci_initialize(ohci); + + return 0; +} #endif /* CONFIG_PM */ #define PCI_CLASS_FIREWIRE_OHCI ((PCI_CLASS_SERIAL_FIREWIRE << 8) | 0x10) diff --git a/trunk/drivers/ieee1394/pcilynx.c b/trunk/drivers/ieee1394/pcilynx.c index 0a7412e27eb4..13a617917bf2 100644 --- a/trunk/drivers/ieee1394/pcilynx.c +++ b/trunk/drivers/ieee1394/pcilynx.c @@ -1428,10 +1428,9 @@ static int __devinit add_card(struct pci_dev *dev, struct i2c_algo_bit_data i2c_adapter_data; error = -ENOMEM; - i2c_ad = kmalloc(sizeof(*i2c_ad), SLAB_KERNEL); + i2c_ad = kmemdup(&bit_ops, sizeof(*i2c_ad), GFP_KERNEL); if (!i2c_ad) FAIL("failed to allocate I2C adapter memory"); - memcpy(i2c_ad, &bit_ops, sizeof(struct i2c_adapter)); i2c_adapter_data = bit_data; i2c_ad->algo_data = &i2c_adapter_data; i2c_adapter_data.data = lynx; diff --git a/trunk/drivers/ieee1394/raw1394-private.h b/trunk/drivers/ieee1394/raw1394-private.h index c7731d1bcd89..50daabf6e5fa 100644 --- a/trunk/drivers/ieee1394/raw1394-private.h +++ b/trunk/drivers/ieee1394/raw1394-private.h @@ -27,12 +27,12 @@ struct file_info { struct hpsb_host *host; - struct list_head req_pending; - struct list_head req_complete; + struct list_head req_pending; /* protected by reqlists_lock */ + struct list_head req_complete; /* protected by reqlists_lock */ spinlock_t reqlists_lock; wait_queue_head_t wait_complete; - struct list_head addr_list; + struct list_head addr_list; /* protected by host_info_lock */ u8 __user *fcp_buffer; @@ -63,7 +63,7 @@ struct arm_addr { u8 client_transactions; u64 recvb; u16 rec_length; - u8 *addr_space_buffer; /* accessed by read/write/lock */ + u8 *addr_space_buffer; /* accessed by read/write/lock requests */ }; struct pending_request { @@ -79,7 +79,7 @@ struct pending_request { struct host_info { struct list_head list; struct hpsb_host *host; - struct list_head file_info_list; + struct list_head file_info_list; /* protected by host_info_lock */ }; #endif /* IEEE1394_RAW1394_PRIVATE_H */ diff --git a/trunk/drivers/ieee1394/raw1394.c b/trunk/drivers/ieee1394/raw1394.c index 5ec4f5eb6b19..ad2108f27a04 100644 --- a/trunk/drivers/ieee1394/raw1394.c +++ b/trunk/drivers/ieee1394/raw1394.c @@ -99,6 +99,21 @@ static struct hpsb_address_ops arm_ops = { static void queue_complete_cb(struct pending_request *req); +#include +static void print_old_iso_deprecation(void) +{ + static pid_t p; + + if (p == current->pid) + return; + p = current->pid; + printk(KERN_WARNING "raw1394: WARNING - Program \"%s\" uses unsupported" + " isochronous request types which will be removed in a next" + " kernel release\n", current->comm); + printk(KERN_WARNING "raw1394: Update your software to use libraw1394's" + " newer interface\n"); +} + static struct pending_request *__alloc_pending_request(gfp_t flags) { struct pending_request *req; @@ -112,7 +127,7 @@ static struct pending_request *__alloc_pending_request(gfp_t flags) static inline struct pending_request *alloc_pending_request(void) { - return __alloc_pending_request(SLAB_KERNEL); + return __alloc_pending_request(GFP_KERNEL); } static void free_pending_request(struct pending_request *req) @@ -259,7 +274,7 @@ static void host_reset(struct hpsb_host *host) if (hi != NULL) { list_for_each_entry(fi, &hi->file_info_list, list) { if (fi->notification == RAW1394_NOTIFY_ON) { - req = __alloc_pending_request(SLAB_ATOMIC); + req = __alloc_pending_request(GFP_ATOMIC); if (req != NULL) { req->file_info = fi; @@ -306,13 +321,13 @@ static void iso_receive(struct hpsb_host *host, int channel, quadlet_t * data, if (!(fi->listen_channels & (1ULL << channel))) continue; - req = __alloc_pending_request(SLAB_ATOMIC); + req = __alloc_pending_request(GFP_ATOMIC); if (!req) break; if (!ibs) { ibs = kmalloc(sizeof(*ibs) + length, - SLAB_ATOMIC); + GFP_ATOMIC); if (!ibs) { kfree(req); break; @@ -367,13 +382,13 @@ static void fcp_request(struct hpsb_host *host, int nodeid, int direction, if (!fi->fcp_buffer) continue; - req = __alloc_pending_request(SLAB_ATOMIC); + req = __alloc_pending_request(GFP_ATOMIC); if (!req) break; if (!ibs) { ibs = kmalloc(sizeof(*ibs) + length, - SLAB_ATOMIC); + GFP_ATOMIC); if (!ibs) { kfree(req); break; @@ -593,7 +608,7 @@ static int state_initialized(struct file_info *fi, struct pending_request *req) switch (req->req.type) { case RAW1394_REQ_LIST_CARDS: spin_lock_irqsave(&host_info_lock, flags); - khl = kmalloc(sizeof(*khl) * host_count, SLAB_ATOMIC); + khl = kmalloc(sizeof(*khl) * host_count, GFP_ATOMIC); if (khl) { req->req.misc = host_count; @@ -1045,7 +1060,7 @@ static int arm_read(struct hpsb_host *host, int nodeid, quadlet_t * buffer, } if (arm_addr->notification_options & ARM_READ) { DBGMSG("arm_read -> entering notification-section"); - req = __alloc_pending_request(SLAB_ATOMIC); + req = __alloc_pending_request(GFP_ATOMIC); if (!req) { DBGMSG("arm_read -> rcode_conflict_error"); spin_unlock_irqrestore(&host_info_lock, irqflags); @@ -1064,7 +1079,7 @@ static int arm_read(struct hpsb_host *host, int nodeid, quadlet_t * buffer, sizeof(struct arm_response) + sizeof(struct arm_request_response); } - req->data = kmalloc(size, SLAB_ATOMIC); + req->data = kmalloc(size, GFP_ATOMIC); if (!(req->data)) { free_pending_request(req); DBGMSG("arm_read -> rcode_conflict_error"); @@ -1198,7 +1213,7 @@ static int arm_write(struct hpsb_host *host, int nodeid, int destid, } if (arm_addr->notification_options & ARM_WRITE) { DBGMSG("arm_write -> entering notification-section"); - req = __alloc_pending_request(SLAB_ATOMIC); + req = __alloc_pending_request(GFP_ATOMIC); if (!req) { DBGMSG("arm_write -> rcode_conflict_error"); spin_unlock_irqrestore(&host_info_lock, irqflags); @@ -1209,7 +1224,7 @@ static int arm_write(struct hpsb_host *host, int nodeid, int destid, sizeof(struct arm_request) + sizeof(struct arm_response) + (length) * sizeof(byte_t) + sizeof(struct arm_request_response); - req->data = kmalloc(size, SLAB_ATOMIC); + req->data = kmalloc(size, GFP_ATOMIC); if (!(req->data)) { free_pending_request(req); DBGMSG("arm_write -> rcode_conflict_error"); @@ -1400,7 +1415,7 @@ static int arm_lock(struct hpsb_host *host, int nodeid, quadlet_t * store, if (arm_addr->notification_options & ARM_LOCK) { byte_t *buf1, *buf2; DBGMSG("arm_lock -> entering notification-section"); - req = __alloc_pending_request(SLAB_ATOMIC); + req = __alloc_pending_request(GFP_ATOMIC); if (!req) { DBGMSG("arm_lock -> rcode_conflict_error"); spin_unlock_irqrestore(&host_info_lock, irqflags); @@ -1408,7 +1423,7 @@ static int arm_lock(struct hpsb_host *host, int nodeid, quadlet_t * store, The request may be retried */ } size = sizeof(struct arm_request) + sizeof(struct arm_response) + 3 * sizeof(*store) + sizeof(struct arm_request_response); /* maximum */ - req->data = kmalloc(size, SLAB_ATOMIC); + req->data = kmalloc(size, GFP_ATOMIC); if (!(req->data)) { free_pending_request(req); DBGMSG("arm_lock -> rcode_conflict_error"); @@ -1628,7 +1643,7 @@ static int arm_lock64(struct hpsb_host *host, int nodeid, octlet_t * store, if (arm_addr->notification_options & ARM_LOCK) { byte_t *buf1, *buf2; DBGMSG("arm_lock64 -> entering notification-section"); - req = __alloc_pending_request(SLAB_ATOMIC); + req = __alloc_pending_request(GFP_ATOMIC); if (!req) { spin_unlock_irqrestore(&host_info_lock, irqflags); DBGMSG("arm_lock64 -> rcode_conflict_error"); @@ -1636,7 +1651,7 @@ static int arm_lock64(struct hpsb_host *host, int nodeid, octlet_t * store, The request may be retried */ } size = sizeof(struct arm_request) + sizeof(struct arm_response) + 3 * sizeof(*store) + sizeof(struct arm_request_response); /* maximum */ - req->data = kmalloc(size, SLAB_ATOMIC); + req->data = kmalloc(size, GFP_ATOMIC); if (!(req->data)) { free_pending_request(req); spin_unlock_irqrestore(&host_info_lock, irqflags); @@ -1737,7 +1752,7 @@ static int arm_register(struct file_info *fi, struct pending_request *req) return (-EINVAL); } /* addr-list-entry for fileinfo */ - addr = kmalloc(sizeof(*addr), SLAB_KERNEL); + addr = kmalloc(sizeof(*addr), GFP_KERNEL); if (!addr) { req->req.length = 0; return (-ENOMEM); @@ -2103,7 +2118,7 @@ static int write_phypacket(struct file_info *fi, struct pending_request *req) static int get_config_rom(struct file_info *fi, struct pending_request *req) { int ret = sizeof(struct raw1394_request); - quadlet_t *data = kmalloc(req->req.length, SLAB_KERNEL); + quadlet_t *data = kmalloc(req->req.length, GFP_KERNEL); int status; if (!data) @@ -2133,7 +2148,7 @@ static int get_config_rom(struct file_info *fi, struct pending_request *req) static int update_config_rom(struct file_info *fi, struct pending_request *req) { int ret = sizeof(struct raw1394_request); - quadlet_t *data = kmalloc(req->req.length, SLAB_KERNEL); + quadlet_t *data = kmalloc(req->req.length, GFP_KERNEL); if (!data) return -ENOMEM; if (copy_from_user(data, int2ptr(req->req.sendb), req->req.length)) { @@ -2292,6 +2307,7 @@ static int state_connected(struct file_info *fi, struct pending_request *req) return sizeof(struct raw1394_request); case RAW1394_REQ_ISO_SEND: + print_old_iso_deprecation(); return handle_iso_send(fi, req, node); case RAW1394_REQ_ARM_REGISTER: @@ -2310,6 +2326,7 @@ static int state_connected(struct file_info *fi, struct pending_request *req) return reset_notification(fi, req); case RAW1394_REQ_ISO_LISTEN: + print_old_iso_deprecation(); handle_iso_listen(fi, req); return sizeof(struct raw1394_request); @@ -2443,7 +2460,7 @@ static void queue_rawiso_event(struct file_info *fi) /* only one ISO activity event may be in the queue */ if (!__rawiso_event_in_queue(fi)) { struct pending_request *req = - __alloc_pending_request(SLAB_ATOMIC); + __alloc_pending_request(GFP_ATOMIC); if (req) { req->file_info = fi; @@ -2779,7 +2796,7 @@ static int raw1394_open(struct inode *inode, struct file *file) { struct file_info *fi; - fi = kzalloc(sizeof(*fi), SLAB_KERNEL); + fi = kzalloc(sizeof(*fi), GFP_KERNEL); if (!fi) return -ENOMEM; @@ -2970,12 +2987,8 @@ static struct ieee1394_device_id raw1394_id_table[] = { MODULE_DEVICE_TABLE(ieee1394, raw1394_id_table); static struct hpsb_protocol_driver raw1394_driver = { - .name = "raw1394 Driver", + .name = "raw1394", .id_table = raw1394_id_table, - .driver = { - .name = "raw1394", - .bus = &ieee1394_bus_type, - }, }; /******************************************************************************/ diff --git a/trunk/drivers/ieee1394/sbp2.c b/trunk/drivers/ieee1394/sbp2.c index 6986ac188281..e68b80b7340d 100644 --- a/trunk/drivers/ieee1394/sbp2.c +++ b/trunk/drivers/ieee1394/sbp2.c @@ -29,13 +29,26 @@ * driver. It also registers as a SCSI lower-level driver in order to accept * SCSI commands for transport using SBP-2. * - * You may access any attached SBP-2 storage devices as if they were SCSI - * devices (e.g. mount /dev/sda1, fdisk, mkfs, etc.). + * You may access any attached SBP-2 (usually storage devices) as regular + * SCSI devices. E.g. mount /dev/sda1, fdisk, mkfs, etc.. * - * Current Issues: + * See http://www.t10.org/drafts.htm#sbp2 for the final draft of the SBP-2 + * specification and for where to purchase the official standard. * - * - Error Handling: SCSI aborts and bus reset requests are handled somewhat - * but the code needs additional debugging. + * TODO: + * - look into possible improvements of the SCSI error handlers + * - handle Unit_Characteristics.mgt_ORB_timeout and .ORB_size + * - handle Logical_Unit_Number.ordered + * - handle src == 1 in status blocks + * - reimplement the DMA mapping in absence of physical DMA so that + * bus_to_virt is no longer required + * - debug the handling of absent physical DMA + * - replace CONFIG_IEEE1394_SBP2_PHYS_DMA by automatic detection + * (this is easy but depends on the previous two TODO items) + * - make the parameter serialize_io configurable per device + * - move all requests to fetch agent registers into non-atomic context, + * replace all usages of sbp2util_node_write_no_wait by true transactions + * Grep for inline FIXME comments below. */ #include @@ -49,7 +62,6 @@ #include #include #include -#include #include #include #include @@ -98,20 +110,20 @@ * (probably due to PCI latency/throughput issues with the part). You can * bump down the speed if you are running into problems. */ -static int max_speed = IEEE1394_SPEED_MAX; -module_param(max_speed, int, 0644); -MODULE_PARM_DESC(max_speed, "Force max speed (3 = 800mb, 2 = 400mb, 1 = 200mb, 0 = 100mb)"); +static int sbp2_max_speed = IEEE1394_SPEED_MAX; +module_param_named(max_speed, sbp2_max_speed, int, 0644); +MODULE_PARM_DESC(max_speed, "Force max speed " + "(3 = 800Mb/s, 2 = 400Mb/s, 1 = 200Mb/s, 0 = 100Mb/s)"); /* * Set serialize_io to 1 if you'd like only one scsi command sent * down to us at a time (debugging). This might be necessary for very * badly behaved sbp2 devices. - * - * TODO: Make this configurable per device. */ -static int serialize_io = 1; -module_param(serialize_io, int, 0444); -MODULE_PARM_DESC(serialize_io, "Serialize I/O coming from scsi drivers (default = 1, faster = 0)"); +static int sbp2_serialize_io = 1; +module_param_named(serialize_io, sbp2_serialize_io, int, 0444); +MODULE_PARM_DESC(serialize_io, "Serialize I/O coming from scsi drivers " + "(default = 1, faster = 0)"); /* * Bump up max_sectors if you'd like to support very large sized @@ -121,10 +133,10 @@ MODULE_PARM_DESC(serialize_io, "Serialize I/O coming from scsi drivers (default * the Oxsemi sbp2 chipsets have no problems supporting very large * transfer sizes. */ -static int max_sectors = SBP2_MAX_SECTORS; -module_param(max_sectors, int, 0444); -MODULE_PARM_DESC(max_sectors, "Change max sectors per I/O supported (default = " - __stringify(SBP2_MAX_SECTORS) ")"); +static int sbp2_max_sectors = SBP2_MAX_SECTORS; +module_param_named(max_sectors, sbp2_max_sectors, int, 0444); +MODULE_PARM_DESC(max_sectors, "Change max sectors per I/O supported " + "(default = " __stringify(SBP2_MAX_SECTORS) ")"); /* * Exclusive login to sbp2 device? In most cases, the sbp2 driver should @@ -139,9 +151,10 @@ MODULE_PARM_DESC(max_sectors, "Change max sectors per I/O supported (default = " * concurrent logins. Depending on firmware, four or two concurrent logins * are possible on OXFW911 and newer Oxsemi bridges. */ -static int exclusive_login = 1; -module_param(exclusive_login, int, 0644); -MODULE_PARM_DESC(exclusive_login, "Exclusive login to sbp2 device (default = 1)"); +static int sbp2_exclusive_login = 1; +module_param_named(exclusive_login, sbp2_exclusive_login, int, 0644); +MODULE_PARM_DESC(exclusive_login, "Exclusive login to sbp2 device " + "(default = 1)"); /* * If any of the following workarounds is required for your device to work, @@ -179,123 +192,123 @@ MODULE_PARM_DESC(workarounds, "Work around device bugs (default = 0" ", override internal blacklist = " __stringify(SBP2_WORKAROUND_OVERRIDE) ", or a combination)"); -/* - * Export information about protocols/devices supported by this driver. - */ -static struct ieee1394_device_id sbp2_id_table[] = { - { - .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION, - .specifier_id = SBP2_UNIT_SPEC_ID_ENTRY & 0xffffff, - .version = SBP2_SW_VERSION_ENTRY & 0xffffff}, - {} -}; - -MODULE_DEVICE_TABLE(ieee1394, sbp2_id_table); - -/* - * Debug levels, configured via kernel config, or enable here. - */ - -#define CONFIG_IEEE1394_SBP2_DEBUG 0 -/* #define CONFIG_IEEE1394_SBP2_DEBUG_ORBS */ -/* #define CONFIG_IEEE1394_SBP2_DEBUG_DMA */ -/* #define CONFIG_IEEE1394_SBP2_DEBUG 1 */ -/* #define CONFIG_IEEE1394_SBP2_DEBUG 2 */ -/* #define CONFIG_IEEE1394_SBP2_PACKET_DUMP */ - -#ifdef CONFIG_IEEE1394_SBP2_DEBUG_ORBS -#define SBP2_ORB_DEBUG(fmt, args...) HPSB_ERR("sbp2(%s): "fmt, __FUNCTION__, ## args) -static u32 global_outstanding_command_orbs = 0; -#define outstanding_orb_incr global_outstanding_command_orbs++ -#define outstanding_orb_decr global_outstanding_command_orbs-- -#else -#define SBP2_ORB_DEBUG(fmt, args...) do {} while (0) -#define outstanding_orb_incr do {} while (0) -#define outstanding_orb_decr do {} while (0) -#endif - -#ifdef CONFIG_IEEE1394_SBP2_DEBUG_DMA -#define SBP2_DMA_ALLOC(fmt, args...) \ - HPSB_ERR("sbp2(%s)alloc(%d): "fmt, __FUNCTION__, \ - ++global_outstanding_dmas, ## args) -#define SBP2_DMA_FREE(fmt, args...) \ - HPSB_ERR("sbp2(%s)free(%d): "fmt, __FUNCTION__, \ - --global_outstanding_dmas, ## args) -static u32 global_outstanding_dmas = 0; -#else -#define SBP2_DMA_ALLOC(fmt, args...) do {} while (0) -#define SBP2_DMA_FREE(fmt, args...) do {} while (0) -#endif -#if CONFIG_IEEE1394_SBP2_DEBUG >= 2 -#define SBP2_DEBUG(fmt, args...) HPSB_ERR("sbp2: "fmt, ## args) -#define SBP2_INFO(fmt, args...) HPSB_ERR("sbp2: "fmt, ## args) -#define SBP2_NOTICE(fmt, args...) HPSB_ERR("sbp2: "fmt, ## args) -#define SBP2_WARN(fmt, args...) HPSB_ERR("sbp2: "fmt, ## args) -#elif CONFIG_IEEE1394_SBP2_DEBUG == 1 -#define SBP2_DEBUG(fmt, args...) HPSB_DEBUG("sbp2: "fmt, ## args) -#define SBP2_INFO(fmt, args...) HPSB_INFO("sbp2: "fmt, ## args) -#define SBP2_NOTICE(fmt, args...) HPSB_NOTICE("sbp2: "fmt, ## args) -#define SBP2_WARN(fmt, args...) HPSB_WARN("sbp2: "fmt, ## args) -#else -#define SBP2_DEBUG(fmt, args...) do {} while (0) -#define SBP2_INFO(fmt, args...) HPSB_INFO("sbp2: "fmt, ## args) -#define SBP2_NOTICE(fmt, args...) HPSB_NOTICE("sbp2: "fmt, ## args) -#define SBP2_WARN(fmt, args...) HPSB_WARN("sbp2: "fmt, ## args) -#endif - -#define SBP2_ERR(fmt, args...) HPSB_ERR("sbp2: "fmt, ## args) -#define SBP2_DEBUG_ENTER() SBP2_DEBUG("%s", __FUNCTION__) +#define SBP2_INFO(fmt, args...) HPSB_INFO("sbp2: "fmt, ## args) +#define SBP2_ERR(fmt, args...) HPSB_ERR("sbp2: "fmt, ## args) /* * Globals */ +static void sbp2scsi_complete_all_commands(struct sbp2_lu *, u32); +static void sbp2scsi_complete_command(struct sbp2_lu *, u32, struct scsi_cmnd *, + void (*)(struct scsi_cmnd *)); +static struct sbp2_lu *sbp2_alloc_device(struct unit_directory *); +static int sbp2_start_device(struct sbp2_lu *); +static void sbp2_remove_device(struct sbp2_lu *); +static int sbp2_login_device(struct sbp2_lu *); +static int sbp2_reconnect_device(struct sbp2_lu *); +static int sbp2_logout_device(struct sbp2_lu *); +static void sbp2_host_reset(struct hpsb_host *); +static int sbp2_handle_status_write(struct hpsb_host *, int, int, quadlet_t *, + u64, size_t, u16); +static int sbp2_agent_reset(struct sbp2_lu *, int); +static void sbp2_parse_unit_directory(struct sbp2_lu *, + struct unit_directory *); +static int sbp2_set_busy_timeout(struct sbp2_lu *); +static int sbp2_max_speed_and_size(struct sbp2_lu *); -static void sbp2scsi_complete_all_commands(struct scsi_id_instance_data *scsi_id, - u32 status); - -static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id, - u32 scsi_status, struct scsi_cmnd *SCpnt, - void (*done)(struct scsi_cmnd *)); - -static struct scsi_host_template scsi_driver_template; static const u8 sbp2_speedto_max_payload[] = { 0x7, 0x8, 0x9, 0xA, 0xB, 0xC }; -static void sbp2_host_reset(struct hpsb_host *host); - -static int sbp2_probe(struct device *dev); -static int sbp2_remove(struct device *dev); -static int sbp2_update(struct unit_directory *ud); - static struct hpsb_highlevel sbp2_highlevel = { - .name = SBP2_DEVICE_NAME, - .host_reset = sbp2_host_reset, + .name = SBP2_DEVICE_NAME, + .host_reset = sbp2_host_reset, }; static struct hpsb_address_ops sbp2_ops = { - .write = sbp2_handle_status_write + .write = sbp2_handle_status_write }; #ifdef CONFIG_IEEE1394_SBP2_PHYS_DMA +static int sbp2_handle_physdma_write(struct hpsb_host *, int, int, quadlet_t *, + u64, size_t, u16); +static int sbp2_handle_physdma_read(struct hpsb_host *, int, quadlet_t *, u64, + size_t, u16); + static struct hpsb_address_ops sbp2_physdma_ops = { - .read = sbp2_handle_physdma_read, - .write = sbp2_handle_physdma_write, + .read = sbp2_handle_physdma_read, + .write = sbp2_handle_physdma_write, }; #endif + +/* + * Interface to driver core and IEEE 1394 core + */ +static struct ieee1394_device_id sbp2_id_table[] = { + { + .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION, + .specifier_id = SBP2_UNIT_SPEC_ID_ENTRY & 0xffffff, + .version = SBP2_SW_VERSION_ENTRY & 0xffffff}, + {} +}; +MODULE_DEVICE_TABLE(ieee1394, sbp2_id_table); + +static int sbp2_probe(struct device *); +static int sbp2_remove(struct device *); +static int sbp2_update(struct unit_directory *); + static struct hpsb_protocol_driver sbp2_driver = { - .name = "SBP2 Driver", + .name = SBP2_DEVICE_NAME, .id_table = sbp2_id_table, .update = sbp2_update, .driver = { - .name = SBP2_DEVICE_NAME, - .bus = &ieee1394_bus_type, .probe = sbp2_probe, .remove = sbp2_remove, }, }; + +/* + * Interface to SCSI core + */ +static int sbp2scsi_queuecommand(struct scsi_cmnd *, + void (*)(struct scsi_cmnd *)); +static int sbp2scsi_abort(struct scsi_cmnd *); +static int sbp2scsi_reset(struct scsi_cmnd *); +static int sbp2scsi_slave_alloc(struct scsi_device *); +static int sbp2scsi_slave_configure(struct scsi_device *); +static void sbp2scsi_slave_destroy(struct scsi_device *); +static ssize_t sbp2_sysfs_ieee1394_id_show(struct device *, + struct device_attribute *, char *); + +static DEVICE_ATTR(ieee1394_id, S_IRUGO, sbp2_sysfs_ieee1394_id_show, NULL); + +static struct device_attribute *sbp2_sysfs_sdev_attrs[] = { + &dev_attr_ieee1394_id, + NULL +}; + +static struct scsi_host_template sbp2_shost_template = { + .module = THIS_MODULE, + .name = "SBP-2 IEEE-1394", + .proc_name = SBP2_DEVICE_NAME, + .queuecommand = sbp2scsi_queuecommand, + .eh_abort_handler = sbp2scsi_abort, + .eh_device_reset_handler = sbp2scsi_reset, + .slave_alloc = sbp2scsi_slave_alloc, + .slave_configure = sbp2scsi_slave_configure, + .slave_destroy = sbp2scsi_slave_destroy, + .this_id = -1, + .sg_tablesize = SG_ALL, + .use_clustering = ENABLE_CLUSTERING, + .cmd_per_lun = SBP2_MAX_CMDS, + .can_queue = SBP2_MAX_CMDS, + .emulated = 1, + .sdev_attrs = sbp2_sysfs_sdev_attrs, +}; + + /* * List of devices with known bugs. * @@ -363,8 +376,6 @@ static inline void sbp2util_be32_to_cpu_buffer(void *buffer, int length) for (length = (length >> 2); length--; ) temp[length] = be32_to_cpu(temp[length]); - - return; } /* @@ -376,8 +387,6 @@ static inline void sbp2util_cpu_to_be32_buffer(void *buffer, int length) for (length = (length >> 2); length--; ) temp[length] = cpu_to_be32(temp[length]); - - return; } #else /* BIG_ENDIAN */ /* Why waste the cpu cycles? */ @@ -385,339 +394,246 @@ static inline void sbp2util_cpu_to_be32_buffer(void *buffer, int length) #define sbp2util_cpu_to_be32_buffer(x,y) do {} while (0) #endif -#ifdef CONFIG_IEEE1394_SBP2_PACKET_DUMP -/* - * Debug packet dump routine. Length is in bytes. - */ -static void sbp2util_packet_dump(void *buffer, int length, char *dump_name, - u32 dump_phys_addr) -{ - int i; - unsigned char *dump = buffer; - - if (!dump || !length || !dump_name) - return; - - if (dump_phys_addr) - printk("[%s, 0x%x]", dump_name, dump_phys_addr); - else - printk("[%s]", dump_name); - for (i = 0; i < length; i++) { - if (i > 0x3f) { - printk("\n ..."); - break; - } - if ((i & 0x3) == 0) - printk(" "); - if ((i & 0xf) == 0) - printk("\n "); - printk("%02x ", (int)dump[i]); - } - printk("\n"); - - return; -} -#else -#define sbp2util_packet_dump(w,x,y,z) do {} while (0) -#endif - -static DECLARE_WAIT_QUEUE_HEAD(access_wq); +static DECLARE_WAIT_QUEUE_HEAD(sbp2_access_wq); /* * Waits for completion of an SBP-2 access request. * Returns nonzero if timed out or prematurely interrupted. */ -static int sbp2util_access_timeout(struct scsi_id_instance_data *scsi_id, - int timeout) +static int sbp2util_access_timeout(struct sbp2_lu *lu, int timeout) { - long leftover = wait_event_interruptible_timeout( - access_wq, scsi_id->access_complete, timeout); + long leftover; - scsi_id->access_complete = 0; + leftover = wait_event_interruptible_timeout( + sbp2_access_wq, lu->access_complete, timeout); + lu->access_complete = 0; return leftover <= 0; } -/* Frees an allocated packet */ -static void sbp2_free_packet(struct hpsb_packet *packet) +static void sbp2_free_packet(void *packet) { hpsb_free_tlabel(packet); hpsb_free_packet(packet); } -/* This is much like hpsb_node_write(), except it ignores the response - * subaction and returns immediately. Can be used from interrupts. +/* + * This is much like hpsb_node_write(), except it ignores the response + * subaction and returns immediately. Can be used from atomic context. */ static int sbp2util_node_write_no_wait(struct node_entry *ne, u64 addr, - quadlet_t *buffer, size_t length) + quadlet_t *buf, size_t len) { struct hpsb_packet *packet; - packet = hpsb_make_writepacket(ne->host, ne->nodeid, - addr, buffer, length); + packet = hpsb_make_writepacket(ne->host, ne->nodeid, addr, buf, len); if (!packet) return -ENOMEM; - hpsb_set_packet_complete_task(packet, - (void (*)(void *))sbp2_free_packet, - packet); - + hpsb_set_packet_complete_task(packet, sbp2_free_packet, packet); hpsb_node_fill_packet(ne, packet); - if (hpsb_send_packet(packet) < 0) { sbp2_free_packet(packet); return -EIO; } - return 0; } -static void sbp2util_notify_fetch_agent(struct scsi_id_instance_data *scsi_id, - u64 offset, quadlet_t *data, size_t len) +static void sbp2util_notify_fetch_agent(struct sbp2_lu *lu, u64 offset, + quadlet_t *data, size_t len) { - /* - * There is a small window after a bus reset within which the node - * entry's generation is current but the reconnect wasn't completed. - */ - if (unlikely(atomic_read(&scsi_id->state) == SBP2LU_STATE_IN_RESET)) + /* There is a small window after a bus reset within which the node + * entry's generation is current but the reconnect wasn't completed. */ + if (unlikely(atomic_read(&lu->state) == SBP2LU_STATE_IN_RESET)) return; - if (hpsb_node_write(scsi_id->ne, - scsi_id->sbp2_command_block_agent_addr + offset, + if (hpsb_node_write(lu->ne, lu->command_block_agent_addr + offset, data, len)) SBP2_ERR("sbp2util_notify_fetch_agent failed."); - /* - * Now accept new SCSI commands, unless a bus reset happended during - * hpsb_node_write. - */ - if (likely(atomic_read(&scsi_id->state) != SBP2LU_STATE_IN_RESET)) - scsi_unblock_requests(scsi_id->scsi_host); + + /* Now accept new SCSI commands, unless a bus reset happended during + * hpsb_node_write. */ + if (likely(atomic_read(&lu->state) != SBP2LU_STATE_IN_RESET)) + scsi_unblock_requests(lu->shost); } -static void sbp2util_write_orb_pointer(void *p) +static void sbp2util_write_orb_pointer(struct work_struct *work) { + struct sbp2_lu *lu = container_of(work, struct sbp2_lu, protocol_work); quadlet_t data[2]; - data[0] = ORB_SET_NODE_ID( - ((struct scsi_id_instance_data *)p)->hi->host->node_id); - data[1] = ((struct scsi_id_instance_data *)p)->last_orb_dma; + data[0] = ORB_SET_NODE_ID(lu->hi->host->node_id); + data[1] = lu->last_orb_dma; sbp2util_cpu_to_be32_buffer(data, 8); - sbp2util_notify_fetch_agent(p, SBP2_ORB_POINTER_OFFSET, data, 8); + sbp2util_notify_fetch_agent(lu, SBP2_ORB_POINTER_OFFSET, data, 8); } -static void sbp2util_write_doorbell(void *p) +static void sbp2util_write_doorbell(struct work_struct *work) { - sbp2util_notify_fetch_agent(p, SBP2_DOORBELL_OFFSET, NULL, 4); + struct sbp2_lu *lu = container_of(work, struct sbp2_lu, protocol_work); + + sbp2util_notify_fetch_agent(lu, SBP2_DOORBELL_OFFSET, NULL, 4); } -/* - * This function is called to create a pool of command orbs used for - * command processing. It is called when a new sbp2 device is detected. - */ -static int sbp2util_create_command_orb_pool(struct scsi_id_instance_data *scsi_id) +static int sbp2util_create_command_orb_pool(struct sbp2_lu *lu) { - struct sbp2scsi_host_info *hi = scsi_id->hi; + struct sbp2_fwhost_info *hi = lu->hi; int i; unsigned long flags, orbs; - struct sbp2_command_info *command; + struct sbp2_command_info *cmd; - orbs = serialize_io ? 2 : SBP2_MAX_CMDS; + orbs = sbp2_serialize_io ? 2 : SBP2_MAX_CMDS; - spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags); + spin_lock_irqsave(&lu->cmd_orb_lock, flags); for (i = 0; i < orbs; i++) { - command = kzalloc(sizeof(*command), GFP_ATOMIC); - if (!command) { - spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, - flags); + cmd = kzalloc(sizeof(*cmd), GFP_ATOMIC); + if (!cmd) { + spin_unlock_irqrestore(&lu->cmd_orb_lock, flags); return -ENOMEM; } - command->command_orb_dma = - pci_map_single(hi->host->pdev, &command->command_orb, - sizeof(struct sbp2_command_orb), - PCI_DMA_TODEVICE); - SBP2_DMA_ALLOC("single command orb DMA"); - command->sge_dma = - pci_map_single(hi->host->pdev, - &command->scatter_gather_element, - sizeof(command->scatter_gather_element), - PCI_DMA_BIDIRECTIONAL); - SBP2_DMA_ALLOC("scatter_gather_element"); - INIT_LIST_HEAD(&command->list); - list_add_tail(&command->list, &scsi_id->sbp2_command_orb_completed); - } - spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags); + cmd->command_orb_dma = dma_map_single(&hi->host->device, + &cmd->command_orb, + sizeof(struct sbp2_command_orb), + DMA_TO_DEVICE); + cmd->sge_dma = dma_map_single(&hi->host->device, + &cmd->scatter_gather_element, + sizeof(cmd->scatter_gather_element), + DMA_BIDIRECTIONAL); + INIT_LIST_HEAD(&cmd->list); + list_add_tail(&cmd->list, &lu->cmd_orb_completed); + } + spin_unlock_irqrestore(&lu->cmd_orb_lock, flags); return 0; } -/* - * This function is called to delete a pool of command orbs. - */ -static void sbp2util_remove_command_orb_pool(struct scsi_id_instance_data *scsi_id) +static void sbp2util_remove_command_orb_pool(struct sbp2_lu *lu) { - struct hpsb_host *host = scsi_id->hi->host; + struct hpsb_host *host = lu->hi->host; struct list_head *lh, *next; - struct sbp2_command_info *command; + struct sbp2_command_info *cmd; unsigned long flags; - spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags); - if (!list_empty(&scsi_id->sbp2_command_orb_completed)) { - list_for_each_safe(lh, next, &scsi_id->sbp2_command_orb_completed) { - command = list_entry(lh, struct sbp2_command_info, list); - - /* Release our generic DMA's */ - pci_unmap_single(host->pdev, command->command_orb_dma, + spin_lock_irqsave(&lu->cmd_orb_lock, flags); + if (!list_empty(&lu->cmd_orb_completed)) + list_for_each_safe(lh, next, &lu->cmd_orb_completed) { + cmd = list_entry(lh, struct sbp2_command_info, list); + dma_unmap_single(&host->device, cmd->command_orb_dma, sizeof(struct sbp2_command_orb), - PCI_DMA_TODEVICE); - SBP2_DMA_FREE("single command orb DMA"); - pci_unmap_single(host->pdev, command->sge_dma, - sizeof(command->scatter_gather_element), - PCI_DMA_BIDIRECTIONAL); - SBP2_DMA_FREE("scatter_gather_element"); - - kfree(command); + DMA_TO_DEVICE); + dma_unmap_single(&host->device, cmd->sge_dma, + sizeof(cmd->scatter_gather_element), + DMA_BIDIRECTIONAL); + kfree(cmd); } - } - spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags); + spin_unlock_irqrestore(&lu->cmd_orb_lock, flags); return; } /* - * This function finds the sbp2_command for a given outstanding command - * orb.Only looks at the inuse list. + * Finds the sbp2_command for a given outstanding command ORB. + * Only looks at the in-use list. */ static struct sbp2_command_info *sbp2util_find_command_for_orb( - struct scsi_id_instance_data *scsi_id, dma_addr_t orb) + struct sbp2_lu *lu, dma_addr_t orb) { - struct sbp2_command_info *command; + struct sbp2_command_info *cmd; unsigned long flags; - spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags); - if (!list_empty(&scsi_id->sbp2_command_orb_inuse)) { - list_for_each_entry(command, &scsi_id->sbp2_command_orb_inuse, list) { - if (command->command_orb_dma == orb) { - spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags); - return command; + spin_lock_irqsave(&lu->cmd_orb_lock, flags); + if (!list_empty(&lu->cmd_orb_inuse)) + list_for_each_entry(cmd, &lu->cmd_orb_inuse, list) + if (cmd->command_orb_dma == orb) { + spin_unlock_irqrestore( + &lu->cmd_orb_lock, flags); + return cmd; } - } - } - spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags); - - SBP2_ORB_DEBUG("could not match command orb %x", (unsigned int)orb); - + spin_unlock_irqrestore(&lu->cmd_orb_lock, flags); return NULL; } /* - * This function finds the sbp2_command for a given outstanding SCpnt. - * Only looks at the inuse list. - * Must be called with scsi_id->sbp2_command_orb_lock held. + * Finds the sbp2_command for a given outstanding SCpnt. + * Only looks at the in-use list. + * Must be called with lu->cmd_orb_lock held. */ static struct sbp2_command_info *sbp2util_find_command_for_SCpnt( - struct scsi_id_instance_data *scsi_id, void *SCpnt) + struct sbp2_lu *lu, void *SCpnt) { - struct sbp2_command_info *command; + struct sbp2_command_info *cmd; - if (!list_empty(&scsi_id->sbp2_command_orb_inuse)) - list_for_each_entry(command, &scsi_id->sbp2_command_orb_inuse, list) - if (command->Current_SCpnt == SCpnt) - return command; + if (!list_empty(&lu->cmd_orb_inuse)) + list_for_each_entry(cmd, &lu->cmd_orb_inuse, list) + if (cmd->Current_SCpnt == SCpnt) + return cmd; return NULL; } -/* - * This function allocates a command orb used to send a scsi command. - */ static struct sbp2_command_info *sbp2util_allocate_command_orb( - struct scsi_id_instance_data *scsi_id, - struct scsi_cmnd *Current_SCpnt, - void (*Current_done)(struct scsi_cmnd *)) + struct sbp2_lu *lu, + struct scsi_cmnd *Current_SCpnt, + void (*Current_done)(struct scsi_cmnd *)) { struct list_head *lh; - struct sbp2_command_info *command = NULL; + struct sbp2_command_info *cmd = NULL; unsigned long flags; - spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags); - if (!list_empty(&scsi_id->sbp2_command_orb_completed)) { - lh = scsi_id->sbp2_command_orb_completed.next; + spin_lock_irqsave(&lu->cmd_orb_lock, flags); + if (!list_empty(&lu->cmd_orb_completed)) { + lh = lu->cmd_orb_completed.next; list_del(lh); - command = list_entry(lh, struct sbp2_command_info, list); - command->Current_done = Current_done; - command->Current_SCpnt = Current_SCpnt; - list_add_tail(&command->list, &scsi_id->sbp2_command_orb_inuse); - } else { + cmd = list_entry(lh, struct sbp2_command_info, list); + cmd->Current_done = Current_done; + cmd->Current_SCpnt = Current_SCpnt; + list_add_tail(&cmd->list, &lu->cmd_orb_inuse); + } else SBP2_ERR("%s: no orbs available", __FUNCTION__); - } - spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags); - return command; -} - -/* Free our DMA's */ -static void sbp2util_free_command_dma(struct sbp2_command_info *command) -{ - struct scsi_id_instance_data *scsi_id = - (struct scsi_id_instance_data *)command->Current_SCpnt->device->host->hostdata[0]; - struct hpsb_host *host; - - if (!scsi_id) { - SBP2_ERR("%s: scsi_id == NULL", __FUNCTION__); - return; - } - - host = scsi_id->ud->ne->host; - - if (command->cmd_dma) { - if (command->dma_type == CMD_DMA_SINGLE) { - pci_unmap_single(host->pdev, command->cmd_dma, - command->dma_size, command->dma_dir); - SBP2_DMA_FREE("single bulk"); - } else if (command->dma_type == CMD_DMA_PAGE) { - pci_unmap_page(host->pdev, command->cmd_dma, - command->dma_size, command->dma_dir); - SBP2_DMA_FREE("single page"); - } /* XXX: Check for CMD_DMA_NONE bug */ - command->dma_type = CMD_DMA_NONE; - command->cmd_dma = 0; - } - - if (command->sge_buffer) { - pci_unmap_sg(host->pdev, command->sge_buffer, - command->dma_size, command->dma_dir); - SBP2_DMA_FREE("scatter list"); - command->sge_buffer = NULL; - } + spin_unlock_irqrestore(&lu->cmd_orb_lock, flags); + return cmd; } /* - * This function moves a command to the completed orb list. - * Must be called with scsi_id->sbp2_command_orb_lock held. + * Unmaps the DMAs of a command and moves the command to the completed ORB list. + * Must be called with lu->cmd_orb_lock held. */ -static void sbp2util_mark_command_completed( - struct scsi_id_instance_data *scsi_id, - struct sbp2_command_info *command) +static void sbp2util_mark_command_completed(struct sbp2_lu *lu, + struct sbp2_command_info *cmd) { - list_del(&command->list); - sbp2util_free_command_dma(command); - list_add_tail(&command->list, &scsi_id->sbp2_command_orb_completed); + struct hpsb_host *host = lu->ud->ne->host; + + if (cmd->cmd_dma) { + if (cmd->dma_type == CMD_DMA_SINGLE) + dma_unmap_single(&host->device, cmd->cmd_dma, + cmd->dma_size, cmd->dma_dir); + else if (cmd->dma_type == CMD_DMA_PAGE) + dma_unmap_page(&host->device, cmd->cmd_dma, + cmd->dma_size, cmd->dma_dir); + /* XXX: Check for CMD_DMA_NONE bug */ + cmd->dma_type = CMD_DMA_NONE; + cmd->cmd_dma = 0; + } + if (cmd->sge_buffer) { + dma_unmap_sg(&host->device, cmd->sge_buffer, + cmd->dma_size, cmd->dma_dir); + cmd->sge_buffer = NULL; + } + list_move_tail(&cmd->list, &lu->cmd_orb_completed); } /* - * Is scsi_id valid? Is the 1394 node still present? + * Is lu valid? Is the 1394 node still present? */ -static inline int sbp2util_node_is_available(struct scsi_id_instance_data *scsi_id) +static inline int sbp2util_node_is_available(struct sbp2_lu *lu) { - return scsi_id && scsi_id->ne && !scsi_id->ne->in_limbo; + return lu && lu->ne && !lu->ne->in_limbo; } /********************************************* * IEEE-1394 core driver stack related section *********************************************/ -static struct scsi_id_instance_data *sbp2_alloc_device(struct unit_directory *ud); static int sbp2_probe(struct device *dev) { struct unit_directory *ud; - struct scsi_id_instance_data *scsi_id; - - SBP2_DEBUG_ENTER(); + struct sbp2_lu *lu; ud = container_of(dev, struct unit_directory, device); @@ -726,67 +642,58 @@ static int sbp2_probe(struct device *dev) if (ud->flags & UNIT_DIRECTORY_HAS_LUN_DIRECTORY) return -ENODEV; - scsi_id = sbp2_alloc_device(ud); - - if (!scsi_id) + lu = sbp2_alloc_device(ud); + if (!lu) return -ENOMEM; - sbp2_parse_unit_directory(scsi_id, ud); - - return sbp2_start_device(scsi_id); + sbp2_parse_unit_directory(lu, ud); + return sbp2_start_device(lu); } static int sbp2_remove(struct device *dev) { struct unit_directory *ud; - struct scsi_id_instance_data *scsi_id; + struct sbp2_lu *lu; struct scsi_device *sdev; - SBP2_DEBUG_ENTER(); - ud = container_of(dev, struct unit_directory, device); - scsi_id = ud->device.driver_data; - if (!scsi_id) + lu = ud->device.driver_data; + if (!lu) return 0; - if (scsi_id->scsi_host) { + if (lu->shost) { /* Get rid of enqueued commands if there is no chance to * send them. */ - if (!sbp2util_node_is_available(scsi_id)) - sbp2scsi_complete_all_commands(scsi_id, DID_NO_CONNECT); - /* scsi_remove_device() will trigger shutdown functions of SCSI + if (!sbp2util_node_is_available(lu)) + sbp2scsi_complete_all_commands(lu, DID_NO_CONNECT); + /* scsi_remove_device() may trigger shutdown functions of SCSI * highlevel drivers which would deadlock if blocked. */ - atomic_set(&scsi_id->state, SBP2LU_STATE_IN_SHUTDOWN); - scsi_unblock_requests(scsi_id->scsi_host); + atomic_set(&lu->state, SBP2LU_STATE_IN_SHUTDOWN); + scsi_unblock_requests(lu->shost); } - sdev = scsi_id->sdev; + sdev = lu->sdev; if (sdev) { - scsi_id->sdev = NULL; + lu->sdev = NULL; scsi_remove_device(sdev); } - sbp2_logout_device(scsi_id); - sbp2_remove_device(scsi_id); + sbp2_logout_device(lu); + sbp2_remove_device(lu); return 0; } static int sbp2_update(struct unit_directory *ud) { - struct scsi_id_instance_data *scsi_id = ud->device.driver_data; - - SBP2_DEBUG_ENTER(); + struct sbp2_lu *lu = ud->device.driver_data; - if (sbp2_reconnect_device(scsi_id)) { + if (sbp2_reconnect_device(lu)) { + /* Reconnect has failed. Perhaps we didn't reconnect fast + * enough. Try a regular login, but first log out just in + * case of any weirdness. */ + sbp2_logout_device(lu); - /* - * Ok, reconnect has failed. Perhaps we didn't - * reconnect fast enough. Try doing a regular login, but - * first do a logout just in case of any weirdness. - */ - sbp2_logout_device(scsi_id); - - if (sbp2_login_device(scsi_id)) { + if (sbp2_login_device(lu)) { /* Login failed too, just fail, and the backend * will call our sbp2_remove for us */ SBP2_ERR("Failed to reconnect to sbp2 device!"); @@ -794,69 +701,59 @@ static int sbp2_update(struct unit_directory *ud) } } - /* Set max retries to something large on the device. */ - sbp2_set_busy_timeout(scsi_id); + sbp2_set_busy_timeout(lu); + sbp2_agent_reset(lu, 1); + sbp2_max_speed_and_size(lu); - /* Do a SBP-2 fetch agent reset. */ - sbp2_agent_reset(scsi_id, 1); - - /* Get the max speed and packet size that we can use. */ - sbp2_max_speed_and_size(scsi_id); - - /* Complete any pending commands with busy (so they get - * retried) and remove them from our queue - */ - sbp2scsi_complete_all_commands(scsi_id, DID_BUS_BUSY); + /* Complete any pending commands with busy (so they get retried) + * and remove them from our queue. */ + sbp2scsi_complete_all_commands(lu, DID_BUS_BUSY); /* Accept new commands unless there was another bus reset in the * meantime. */ - if (hpsb_node_entry_valid(scsi_id->ne)) { - atomic_set(&scsi_id->state, SBP2LU_STATE_RUNNING); - scsi_unblock_requests(scsi_id->scsi_host); + if (hpsb_node_entry_valid(lu->ne)) { + atomic_set(&lu->state, SBP2LU_STATE_RUNNING); + scsi_unblock_requests(lu->shost); } return 0; } -/* This functions is called by the sbp2_probe, for each new device. We now - * allocate one scsi host for each scsi_id (unit directory). */ -static struct scsi_id_instance_data *sbp2_alloc_device(struct unit_directory *ud) +static struct sbp2_lu *sbp2_alloc_device(struct unit_directory *ud) { - struct sbp2scsi_host_info *hi; - struct Scsi_Host *scsi_host = NULL; - struct scsi_id_instance_data *scsi_id = NULL; + struct sbp2_fwhost_info *hi; + struct Scsi_Host *shost = NULL; + struct sbp2_lu *lu = NULL; - SBP2_DEBUG_ENTER(); - - scsi_id = kzalloc(sizeof(*scsi_id), GFP_KERNEL); - if (!scsi_id) { - SBP2_ERR("failed to create scsi_id"); + lu = kzalloc(sizeof(*lu), GFP_KERNEL); + if (!lu) { + SBP2_ERR("failed to create lu"); goto failed_alloc; } - scsi_id->ne = ud->ne; - scsi_id->ud = ud; - scsi_id->speed_code = IEEE1394_SPEED_100; - scsi_id->max_payload_size = sbp2_speedto_max_payload[IEEE1394_SPEED_100]; - scsi_id->status_fifo_addr = CSR1212_INVALID_ADDR_SPACE; - INIT_LIST_HEAD(&scsi_id->sbp2_command_orb_inuse); - INIT_LIST_HEAD(&scsi_id->sbp2_command_orb_completed); - INIT_LIST_HEAD(&scsi_id->scsi_list); - spin_lock_init(&scsi_id->sbp2_command_orb_lock); - atomic_set(&scsi_id->state, SBP2LU_STATE_RUNNING); - INIT_WORK(&scsi_id->protocol_work, NULL, NULL); + lu->ne = ud->ne; + lu->ud = ud; + lu->speed_code = IEEE1394_SPEED_100; + lu->max_payload_size = sbp2_speedto_max_payload[IEEE1394_SPEED_100]; + lu->status_fifo_addr = CSR1212_INVALID_ADDR_SPACE; + INIT_LIST_HEAD(&lu->cmd_orb_inuse); + INIT_LIST_HEAD(&lu->cmd_orb_completed); + INIT_LIST_HEAD(&lu->lu_list); + spin_lock_init(&lu->cmd_orb_lock); + atomic_set(&lu->state, SBP2LU_STATE_RUNNING); + INIT_WORK(&lu->protocol_work, NULL); - ud->device.driver_data = scsi_id; + ud->device.driver_data = lu; hi = hpsb_get_hostinfo(&sbp2_highlevel, ud->ne->host); if (!hi) { - hi = hpsb_create_hostinfo(&sbp2_highlevel, ud->ne->host, sizeof(*hi)); + hi = hpsb_create_hostinfo(&sbp2_highlevel, ud->ne->host, + sizeof(*hi)); if (!hi) { SBP2_ERR("failed to allocate hostinfo"); goto failed_alloc; } - SBP2_DEBUG("sbp2_alloc_device: allocated hostinfo"); hi->host = ud->ne->host; - INIT_LIST_HEAD(&hi->scsi_ids); + INIT_LIST_HEAD(&hi->logical_units); #ifdef CONFIG_IEEE1394_SBP2_PHYS_DMA /* Handle data movement if physical dma is not @@ -876,9 +773,9 @@ static struct scsi_id_instance_data *sbp2_alloc_device(struct unit_directory *ud goto failed_alloc; } - scsi_id->hi = hi; + lu->hi = hi; - list_add_tail(&scsi_id->scsi_list, &hi->scsi_ids); + list_add_tail(&lu->lu_list, &hi->logical_units); /* Register the status FIFO address range. We could use the same FIFO * for targets at different nodes. However we need different FIFOs per @@ -888,302 +785,214 @@ static struct scsi_id_instance_data *sbp2_alloc_device(struct unit_directory *ud * then be performed as unified transactions. This slightly reduces * bandwidth usage, and some Prolific based devices seem to require it. */ - scsi_id->status_fifo_addr = hpsb_allocate_and_register_addrspace( + lu->status_fifo_addr = hpsb_allocate_and_register_addrspace( &sbp2_highlevel, ud->ne->host, &sbp2_ops, sizeof(struct sbp2_status_block), sizeof(quadlet_t), ud->ne->host->low_addr_space, CSR1212_ALL_SPACE_END); - if (scsi_id->status_fifo_addr == CSR1212_INVALID_ADDR_SPACE) { + if (lu->status_fifo_addr == CSR1212_INVALID_ADDR_SPACE) { SBP2_ERR("failed to allocate status FIFO address range"); goto failed_alloc; } - /* Register our host with the SCSI stack. */ - scsi_host = scsi_host_alloc(&scsi_driver_template, - sizeof(unsigned long)); - if (!scsi_host) { + shost = scsi_host_alloc(&sbp2_shost_template, sizeof(unsigned long)); + if (!shost) { SBP2_ERR("failed to register scsi host"); goto failed_alloc; } - scsi_host->hostdata[0] = (unsigned long)scsi_id; + shost->hostdata[0] = (unsigned long)lu; - if (!scsi_add_host(scsi_host, &ud->device)) { - scsi_id->scsi_host = scsi_host; - return scsi_id; + if (!scsi_add_host(shost, &ud->device)) { + lu->shost = shost; + return lu; } SBP2_ERR("failed to add scsi host"); - scsi_host_put(scsi_host); + scsi_host_put(shost); failed_alloc: - sbp2_remove_device(scsi_id); + sbp2_remove_device(lu); return NULL; } static void sbp2_host_reset(struct hpsb_host *host) { - struct sbp2scsi_host_info *hi; - struct scsi_id_instance_data *scsi_id; + struct sbp2_fwhost_info *hi; + struct sbp2_lu *lu; hi = hpsb_get_hostinfo(&sbp2_highlevel, host); if (!hi) return; - list_for_each_entry(scsi_id, &hi->scsi_ids, scsi_list) - if (likely(atomic_read(&scsi_id->state) != + list_for_each_entry(lu, &hi->logical_units, lu_list) + if (likely(atomic_read(&lu->state) != SBP2LU_STATE_IN_SHUTDOWN)) { - atomic_set(&scsi_id->state, SBP2LU_STATE_IN_RESET); - scsi_block_requests(scsi_id->scsi_host); + atomic_set(&lu->state, SBP2LU_STATE_IN_RESET); + scsi_block_requests(lu->shost); } } -/* - * This function is where we first pull the node unique ids, and then - * allocate memory and register a SBP-2 device. - */ -static int sbp2_start_device(struct scsi_id_instance_data *scsi_id) +static int sbp2_start_device(struct sbp2_lu *lu) { - struct sbp2scsi_host_info *hi = scsi_id->hi; + struct sbp2_fwhost_info *hi = lu->hi; int error; - SBP2_DEBUG_ENTER(); - - /* Login FIFO DMA */ - scsi_id->login_response = - pci_alloc_consistent(hi->host->pdev, + lu->login_response = dma_alloc_coherent(&hi->host->device, sizeof(struct sbp2_login_response), - &scsi_id->login_response_dma); - if (!scsi_id->login_response) + &lu->login_response_dma, GFP_KERNEL); + if (!lu->login_response) goto alloc_fail; - SBP2_DMA_ALLOC("consistent DMA region for login FIFO"); - /* Query logins ORB DMA */ - scsi_id->query_logins_orb = - pci_alloc_consistent(hi->host->pdev, + lu->query_logins_orb = dma_alloc_coherent(&hi->host->device, sizeof(struct sbp2_query_logins_orb), - &scsi_id->query_logins_orb_dma); - if (!scsi_id->query_logins_orb) + &lu->query_logins_orb_dma, GFP_KERNEL); + if (!lu->query_logins_orb) goto alloc_fail; - SBP2_DMA_ALLOC("consistent DMA region for query logins ORB"); - /* Query logins response DMA */ - scsi_id->query_logins_response = - pci_alloc_consistent(hi->host->pdev, + lu->query_logins_response = dma_alloc_coherent(&hi->host->device, sizeof(struct sbp2_query_logins_response), - &scsi_id->query_logins_response_dma); - if (!scsi_id->query_logins_response) + &lu->query_logins_response_dma, GFP_KERNEL); + if (!lu->query_logins_response) goto alloc_fail; - SBP2_DMA_ALLOC("consistent DMA region for query logins response"); - /* Reconnect ORB DMA */ - scsi_id->reconnect_orb = - pci_alloc_consistent(hi->host->pdev, + lu->reconnect_orb = dma_alloc_coherent(&hi->host->device, sizeof(struct sbp2_reconnect_orb), - &scsi_id->reconnect_orb_dma); - if (!scsi_id->reconnect_orb) + &lu->reconnect_orb_dma, GFP_KERNEL); + if (!lu->reconnect_orb) goto alloc_fail; - SBP2_DMA_ALLOC("consistent DMA region for reconnect ORB"); - /* Logout ORB DMA */ - scsi_id->logout_orb = - pci_alloc_consistent(hi->host->pdev, + lu->logout_orb = dma_alloc_coherent(&hi->host->device, sizeof(struct sbp2_logout_orb), - &scsi_id->logout_orb_dma); - if (!scsi_id->logout_orb) + &lu->logout_orb_dma, GFP_KERNEL); + if (!lu->logout_orb) goto alloc_fail; - SBP2_DMA_ALLOC("consistent DMA region for logout ORB"); - /* Login ORB DMA */ - scsi_id->login_orb = - pci_alloc_consistent(hi->host->pdev, + lu->login_orb = dma_alloc_coherent(&hi->host->device, sizeof(struct sbp2_login_orb), - &scsi_id->login_orb_dma); - if (!scsi_id->login_orb) + &lu->login_orb_dma, GFP_KERNEL); + if (!lu->login_orb) goto alloc_fail; - SBP2_DMA_ALLOC("consistent DMA region for login ORB"); - - SBP2_DEBUG("New SBP-2 device inserted, SCSI ID = %x", scsi_id->ud->id); - /* - * Create our command orb pool - */ - if (sbp2util_create_command_orb_pool(scsi_id)) { + if (sbp2util_create_command_orb_pool(lu)) { SBP2_ERR("sbp2util_create_command_orb_pool failed!"); - sbp2_remove_device(scsi_id); + sbp2_remove_device(lu); return -ENOMEM; } - /* Schedule a timeout here. The reason is that we may be so close - * to a bus reset, that the device is not available for logins. - * This can happen when the bus reset is caused by the host - * connected to the sbp2 device being removed. That host would - * have a certain amount of time to relogin before the sbp2 device - * allows someone else to login instead. One second makes sense. */ + /* Wait a second before trying to log in. Previously logged in + * initiators need a chance to reconnect. */ if (msleep_interruptible(1000)) { - sbp2_remove_device(scsi_id); + sbp2_remove_device(lu); return -EINTR; } - /* - * Login to the sbp-2 device - */ - if (sbp2_login_device(scsi_id)) { - /* Login failed, just remove the device. */ - sbp2_remove_device(scsi_id); + if (sbp2_login_device(lu)) { + sbp2_remove_device(lu); return -EBUSY; } - /* - * Set max retries to something large on the device - */ - sbp2_set_busy_timeout(scsi_id); - - /* - * Do a SBP-2 fetch agent reset - */ - sbp2_agent_reset(scsi_id, 1); + sbp2_set_busy_timeout(lu); + sbp2_agent_reset(lu, 1); + sbp2_max_speed_and_size(lu); - /* - * Get the max speed and packet size that we can use - */ - sbp2_max_speed_and_size(scsi_id); - - /* Add this device to the scsi layer now */ - error = scsi_add_device(scsi_id->scsi_host, 0, scsi_id->ud->id, 0); + error = scsi_add_device(lu->shost, 0, lu->ud->id, 0); if (error) { SBP2_ERR("scsi_add_device failed"); - sbp2_logout_device(scsi_id); - sbp2_remove_device(scsi_id); + sbp2_logout_device(lu); + sbp2_remove_device(lu); return error; } return 0; alloc_fail: - SBP2_ERR("Could not allocate memory for scsi_id"); - sbp2_remove_device(scsi_id); + SBP2_ERR("Could not allocate memory for lu"); + sbp2_remove_device(lu); return -ENOMEM; } -/* - * This function removes an sbp2 device from the sbp2scsi_host_info struct. - */ -static void sbp2_remove_device(struct scsi_id_instance_data *scsi_id) +static void sbp2_remove_device(struct sbp2_lu *lu) { - struct sbp2scsi_host_info *hi; - - SBP2_DEBUG_ENTER(); + struct sbp2_fwhost_info *hi; - if (!scsi_id) + if (!lu) return; - hi = scsi_id->hi; + hi = lu->hi; - /* This will remove our scsi device aswell */ - if (scsi_id->scsi_host) { - scsi_remove_host(scsi_id->scsi_host); - scsi_host_put(scsi_id->scsi_host); + if (lu->shost) { + scsi_remove_host(lu->shost); + scsi_host_put(lu->shost); } flush_scheduled_work(); - sbp2util_remove_command_orb_pool(scsi_id); + sbp2util_remove_command_orb_pool(lu); - list_del(&scsi_id->scsi_list); + list_del(&lu->lu_list); - if (scsi_id->login_response) { - pci_free_consistent(hi->host->pdev, + if (lu->login_response) + dma_free_coherent(&hi->host->device, sizeof(struct sbp2_login_response), - scsi_id->login_response, - scsi_id->login_response_dma); - SBP2_DMA_FREE("single login FIFO"); - } - - if (scsi_id->login_orb) { - pci_free_consistent(hi->host->pdev, + lu->login_response, + lu->login_response_dma); + if (lu->login_orb) + dma_free_coherent(&hi->host->device, sizeof(struct sbp2_login_orb), - scsi_id->login_orb, - scsi_id->login_orb_dma); - SBP2_DMA_FREE("single login ORB"); - } - - if (scsi_id->reconnect_orb) { - pci_free_consistent(hi->host->pdev, + lu->login_orb, + lu->login_orb_dma); + if (lu->reconnect_orb) + dma_free_coherent(&hi->host->device, sizeof(struct sbp2_reconnect_orb), - scsi_id->reconnect_orb, - scsi_id->reconnect_orb_dma); - SBP2_DMA_FREE("single reconnect orb"); - } - - if (scsi_id->logout_orb) { - pci_free_consistent(hi->host->pdev, + lu->reconnect_orb, + lu->reconnect_orb_dma); + if (lu->logout_orb) + dma_free_coherent(&hi->host->device, sizeof(struct sbp2_logout_orb), - scsi_id->logout_orb, - scsi_id->logout_orb_dma); - SBP2_DMA_FREE("single logout orb"); - } - - if (scsi_id->query_logins_orb) { - pci_free_consistent(hi->host->pdev, + lu->logout_orb, + lu->logout_orb_dma); + if (lu->query_logins_orb) + dma_free_coherent(&hi->host->device, sizeof(struct sbp2_query_logins_orb), - scsi_id->query_logins_orb, - scsi_id->query_logins_orb_dma); - SBP2_DMA_FREE("single query logins orb"); - } - - if (scsi_id->query_logins_response) { - pci_free_consistent(hi->host->pdev, + lu->query_logins_orb, + lu->query_logins_orb_dma); + if (lu->query_logins_response) + dma_free_coherent(&hi->host->device, sizeof(struct sbp2_query_logins_response), - scsi_id->query_logins_response, - scsi_id->query_logins_response_dma); - SBP2_DMA_FREE("single query logins data"); - } + lu->query_logins_response, + lu->query_logins_response_dma); - if (scsi_id->status_fifo_addr != CSR1212_INVALID_ADDR_SPACE) + if (lu->status_fifo_addr != CSR1212_INVALID_ADDR_SPACE) hpsb_unregister_addrspace(&sbp2_highlevel, hi->host, - scsi_id->status_fifo_addr); + lu->status_fifo_addr); - scsi_id->ud->device.driver_data = NULL; + lu->ud->device.driver_data = NULL; if (hi) module_put(hi->host->driver->owner); - SBP2_DEBUG("SBP-2 device removed, SCSI ID = %d", scsi_id->ud->id); - - kfree(scsi_id); + kfree(lu); } #ifdef CONFIG_IEEE1394_SBP2_PHYS_DMA /* - * This function deals with physical dma write requests (for adapters that do not support - * physical dma in hardware). Mostly just here for debugging... + * Deal with write requests on adapters which do not support physical DMA or + * have it switched off. */ static int sbp2_handle_physdma_write(struct hpsb_host *host, int nodeid, int destid, quadlet_t *data, u64 addr, size_t length, u16 flags) { - - /* - * Manually put the data in the right place. - */ memcpy(bus_to_virt((u32) addr), data, length); - sbp2util_packet_dump(data, length, "sbp2 phys dma write by device", - (u32) addr); return RCODE_COMPLETE; } /* - * This function deals with physical dma read requests (for adapters that do not support - * physical dma in hardware). Mostly just here for debugging... + * Deal with read requests on adapters which do not support physical DMA or + * have it switched off. */ static int sbp2_handle_physdma_read(struct hpsb_host *host, int nodeid, quadlet_t *data, u64 addr, size_t length, u16 flags) { - - /* - * Grab data from memory and send a read response. - */ memcpy(data, bus_to_virt((u32) addr), length); - sbp2util_packet_dump(data, length, "sbp2 phys dma read by device", - (u32) addr); return RCODE_COMPLETE; } #endif @@ -1192,74 +1001,69 @@ static int sbp2_handle_physdma_read(struct hpsb_host *host, int nodeid, * SBP-2 protocol related section **************************************/ -/* - * This function queries the device for the maximum concurrent logins it - * supports. - */ -static int sbp2_query_logins(struct scsi_id_instance_data *scsi_id) +static int sbp2_query_logins(struct sbp2_lu *lu) { - struct sbp2scsi_host_info *hi = scsi_id->hi; + struct sbp2_fwhost_info *hi = lu->hi; quadlet_t data[2]; int max_logins; int active_logins; - SBP2_DEBUG_ENTER(); - - scsi_id->query_logins_orb->reserved1 = 0x0; - scsi_id->query_logins_orb->reserved2 = 0x0; - - scsi_id->query_logins_orb->query_response_lo = scsi_id->query_logins_response_dma; - scsi_id->query_logins_orb->query_response_hi = ORB_SET_NODE_ID(hi->host->node_id); + lu->query_logins_orb->reserved1 = 0x0; + lu->query_logins_orb->reserved2 = 0x0; - scsi_id->query_logins_orb->lun_misc = ORB_SET_FUNCTION(SBP2_QUERY_LOGINS_REQUEST); - scsi_id->query_logins_orb->lun_misc |= ORB_SET_NOTIFY(1); - scsi_id->query_logins_orb->lun_misc |= ORB_SET_LUN(scsi_id->sbp2_lun); + lu->query_logins_orb->query_response_lo = lu->query_logins_response_dma; + lu->query_logins_orb->query_response_hi = + ORB_SET_NODE_ID(hi->host->node_id); + lu->query_logins_orb->lun_misc = + ORB_SET_FUNCTION(SBP2_QUERY_LOGINS_REQUEST); + lu->query_logins_orb->lun_misc |= ORB_SET_NOTIFY(1); + lu->query_logins_orb->lun_misc |= ORB_SET_LUN(lu->lun); - scsi_id->query_logins_orb->reserved_resp_length = - ORB_SET_QUERY_LOGINS_RESP_LENGTH(sizeof(struct sbp2_query_logins_response)); + lu->query_logins_orb->reserved_resp_length = + ORB_SET_QUERY_LOGINS_RESP_LENGTH( + sizeof(struct sbp2_query_logins_response)); - scsi_id->query_logins_orb->status_fifo_hi = - ORB_SET_STATUS_FIFO_HI(scsi_id->status_fifo_addr, hi->host->node_id); - scsi_id->query_logins_orb->status_fifo_lo = - ORB_SET_STATUS_FIFO_LO(scsi_id->status_fifo_addr); + lu->query_logins_orb->status_fifo_hi = + ORB_SET_STATUS_FIFO_HI(lu->status_fifo_addr, hi->host->node_id); + lu->query_logins_orb->status_fifo_lo = + ORB_SET_STATUS_FIFO_LO(lu->status_fifo_addr); - sbp2util_cpu_to_be32_buffer(scsi_id->query_logins_orb, sizeof(struct sbp2_query_logins_orb)); + sbp2util_cpu_to_be32_buffer(lu->query_logins_orb, + sizeof(struct sbp2_query_logins_orb)); - sbp2util_packet_dump(scsi_id->query_logins_orb, sizeof(struct sbp2_query_logins_orb), - "sbp2 query logins orb", scsi_id->query_logins_orb_dma); - - memset(scsi_id->query_logins_response, 0, sizeof(struct sbp2_query_logins_response)); + memset(lu->query_logins_response, 0, + sizeof(struct sbp2_query_logins_response)); data[0] = ORB_SET_NODE_ID(hi->host->node_id); - data[1] = scsi_id->query_logins_orb_dma; + data[1] = lu->query_logins_orb_dma; sbp2util_cpu_to_be32_buffer(data, 8); - hpsb_node_write(scsi_id->ne, scsi_id->sbp2_management_agent_addr, data, 8); + hpsb_node_write(lu->ne, lu->management_agent_addr, data, 8); - if (sbp2util_access_timeout(scsi_id, 2*HZ)) { + if (sbp2util_access_timeout(lu, 2*HZ)) { SBP2_INFO("Error querying logins to SBP-2 device - timed out"); return -EIO; } - if (scsi_id->status_block.ORB_offset_lo != scsi_id->query_logins_orb_dma) { + if (lu->status_block.ORB_offset_lo != lu->query_logins_orb_dma) { SBP2_INFO("Error querying logins to SBP-2 device - timed out"); return -EIO; } - if (STATUS_TEST_RDS(scsi_id->status_block.ORB_offset_hi_misc)) { + if (STATUS_TEST_RDS(lu->status_block.ORB_offset_hi_misc)) { SBP2_INFO("Error querying logins to SBP-2 device - failed"); return -EIO; } - sbp2util_cpu_to_be32_buffer(scsi_id->query_logins_response, sizeof(struct sbp2_query_logins_response)); - - SBP2_DEBUG("length_max_logins = %x", - (unsigned int)scsi_id->query_logins_response->length_max_logins); + sbp2util_cpu_to_be32_buffer(lu->query_logins_response, + sizeof(struct sbp2_query_logins_response)); - max_logins = RESPONSE_GET_MAX_LOGINS(scsi_id->query_logins_response->length_max_logins); + max_logins = RESPONSE_GET_MAX_LOGINS( + lu->query_logins_response->length_max_logins); SBP2_INFO("Maximum concurrent logins supported: %d", max_logins); - active_logins = RESPONSE_GET_ACTIVE_LOGINS(scsi_id->query_logins_response->length_max_logins); + active_logins = RESPONSE_GET_ACTIVE_LOGINS( + lu->query_logins_response->length_max_logins); SBP2_INFO("Number of active logins: %d", active_logins); if (active_logins >= max_logins) { @@ -1269,332 +1073,231 @@ static int sbp2_query_logins(struct scsi_id_instance_data *scsi_id) return 0; } -/* - * This function is called in order to login to a particular SBP-2 device, - * after a bus reset. - */ -static int sbp2_login_device(struct scsi_id_instance_data *scsi_id) +static int sbp2_login_device(struct sbp2_lu *lu) { - struct sbp2scsi_host_info *hi = scsi_id->hi; + struct sbp2_fwhost_info *hi = lu->hi; quadlet_t data[2]; - SBP2_DEBUG_ENTER(); - - if (!scsi_id->login_orb) { - SBP2_DEBUG("%s: login_orb not alloc'd!", __FUNCTION__); + if (!lu->login_orb) return -EIO; - } - if (!exclusive_login) { - if (sbp2_query_logins(scsi_id)) { - SBP2_INFO("Device does not support any more concurrent logins"); - return -EIO; - } + if (!sbp2_exclusive_login && sbp2_query_logins(lu)) { + SBP2_INFO("Device does not support any more concurrent logins"); + return -EIO; } - /* Set-up login ORB, assume no password */ - scsi_id->login_orb->password_hi = 0; - scsi_id->login_orb->password_lo = 0; + /* assume no password */ + lu->login_orb->password_hi = 0; + lu->login_orb->password_lo = 0; - scsi_id->login_orb->login_response_lo = scsi_id->login_response_dma; - scsi_id->login_orb->login_response_hi = ORB_SET_NODE_ID(hi->host->node_id); + lu->login_orb->login_response_lo = lu->login_response_dma; + lu->login_orb->login_response_hi = ORB_SET_NODE_ID(hi->host->node_id); + lu->login_orb->lun_misc = ORB_SET_FUNCTION(SBP2_LOGIN_REQUEST); - scsi_id->login_orb->lun_misc = ORB_SET_FUNCTION(SBP2_LOGIN_REQUEST); - scsi_id->login_orb->lun_misc |= ORB_SET_RECONNECT(0); /* One second reconnect time */ - scsi_id->login_orb->lun_misc |= ORB_SET_EXCLUSIVE(exclusive_login); /* Exclusive access to device */ - scsi_id->login_orb->lun_misc |= ORB_SET_NOTIFY(1); /* Notify us of login complete */ - scsi_id->login_orb->lun_misc |= ORB_SET_LUN(scsi_id->sbp2_lun); + /* one second reconnect time */ + lu->login_orb->lun_misc |= ORB_SET_RECONNECT(0); + lu->login_orb->lun_misc |= ORB_SET_EXCLUSIVE(sbp2_exclusive_login); + lu->login_orb->lun_misc |= ORB_SET_NOTIFY(1); + lu->login_orb->lun_misc |= ORB_SET_LUN(lu->lun); - scsi_id->login_orb->passwd_resp_lengths = + lu->login_orb->passwd_resp_lengths = ORB_SET_LOGIN_RESP_LENGTH(sizeof(struct sbp2_login_response)); - scsi_id->login_orb->status_fifo_hi = - ORB_SET_STATUS_FIFO_HI(scsi_id->status_fifo_addr, hi->host->node_id); - scsi_id->login_orb->status_fifo_lo = - ORB_SET_STATUS_FIFO_LO(scsi_id->status_fifo_addr); + lu->login_orb->status_fifo_hi = + ORB_SET_STATUS_FIFO_HI(lu->status_fifo_addr, hi->host->node_id); + lu->login_orb->status_fifo_lo = + ORB_SET_STATUS_FIFO_LO(lu->status_fifo_addr); - sbp2util_cpu_to_be32_buffer(scsi_id->login_orb, sizeof(struct sbp2_login_orb)); + sbp2util_cpu_to_be32_buffer(lu->login_orb, + sizeof(struct sbp2_login_orb)); - sbp2util_packet_dump(scsi_id->login_orb, sizeof(struct sbp2_login_orb), - "sbp2 login orb", scsi_id->login_orb_dma); - - memset(scsi_id->login_response, 0, sizeof(struct sbp2_login_response)); + memset(lu->login_response, 0, sizeof(struct sbp2_login_response)); data[0] = ORB_SET_NODE_ID(hi->host->node_id); - data[1] = scsi_id->login_orb_dma; + data[1] = lu->login_orb_dma; sbp2util_cpu_to_be32_buffer(data, 8); - hpsb_node_write(scsi_id->ne, scsi_id->sbp2_management_agent_addr, data, 8); + hpsb_node_write(lu->ne, lu->management_agent_addr, data, 8); - /* - * Wait for login status (up to 20 seconds)... - */ - if (sbp2util_access_timeout(scsi_id, 20*HZ)) { + /* wait up to 20 seconds for login status */ + if (sbp2util_access_timeout(lu, 20*HZ)) { SBP2_ERR("Error logging into SBP-2 device - timed out"); return -EIO; } - /* - * Sanity. Make sure status returned matches login orb. - */ - if (scsi_id->status_block.ORB_offset_lo != scsi_id->login_orb_dma) { + /* make sure that the returned status matches the login ORB */ + if (lu->status_block.ORB_offset_lo != lu->login_orb_dma) { SBP2_ERR("Error logging into SBP-2 device - timed out"); return -EIO; } - if (STATUS_TEST_RDS(scsi_id->status_block.ORB_offset_hi_misc)) { + if (STATUS_TEST_RDS(lu->status_block.ORB_offset_hi_misc)) { SBP2_ERR("Error logging into SBP-2 device - failed"); return -EIO; } - /* - * Byte swap the login response, for use when reconnecting or - * logging out. - */ - sbp2util_cpu_to_be32_buffer(scsi_id->login_response, sizeof(struct sbp2_login_response)); - - /* - * Grab our command block agent address from the login response. - */ - SBP2_DEBUG("command_block_agent_hi = %x", - (unsigned int)scsi_id->login_response->command_block_agent_hi); - SBP2_DEBUG("command_block_agent_lo = %x", - (unsigned int)scsi_id->login_response->command_block_agent_lo); - - scsi_id->sbp2_command_block_agent_addr = - ((u64)scsi_id->login_response->command_block_agent_hi) << 32; - scsi_id->sbp2_command_block_agent_addr |= ((u64)scsi_id->login_response->command_block_agent_lo); - scsi_id->sbp2_command_block_agent_addr &= 0x0000ffffffffffffULL; + sbp2util_cpu_to_be32_buffer(lu->login_response, + sizeof(struct sbp2_login_response)); + lu->command_block_agent_addr = + ((u64)lu->login_response->command_block_agent_hi) << 32; + lu->command_block_agent_addr |= + ((u64)lu->login_response->command_block_agent_lo); + lu->command_block_agent_addr &= 0x0000ffffffffffffULL; SBP2_INFO("Logged into SBP-2 device"); return 0; } -/* - * This function is called in order to logout from a particular SBP-2 - * device, usually called during driver unload. - */ -static int sbp2_logout_device(struct scsi_id_instance_data *scsi_id) +static int sbp2_logout_device(struct sbp2_lu *lu) { - struct sbp2scsi_host_info *hi = scsi_id->hi; + struct sbp2_fwhost_info *hi = lu->hi; quadlet_t data[2]; int error; - SBP2_DEBUG_ENTER(); - - /* - * Set-up logout ORB - */ - scsi_id->logout_orb->reserved1 = 0x0; - scsi_id->logout_orb->reserved2 = 0x0; - scsi_id->logout_orb->reserved3 = 0x0; - scsi_id->logout_orb->reserved4 = 0x0; - - scsi_id->logout_orb->login_ID_misc = ORB_SET_FUNCTION(SBP2_LOGOUT_REQUEST); - scsi_id->logout_orb->login_ID_misc |= ORB_SET_LOGIN_ID(scsi_id->login_response->length_login_ID); - - /* Notify us when complete */ - scsi_id->logout_orb->login_ID_misc |= ORB_SET_NOTIFY(1); + lu->logout_orb->reserved1 = 0x0; + lu->logout_orb->reserved2 = 0x0; + lu->logout_orb->reserved3 = 0x0; + lu->logout_orb->reserved4 = 0x0; - scsi_id->logout_orb->reserved5 = 0x0; - scsi_id->logout_orb->status_fifo_hi = - ORB_SET_STATUS_FIFO_HI(scsi_id->status_fifo_addr, hi->host->node_id); - scsi_id->logout_orb->status_fifo_lo = - ORB_SET_STATUS_FIFO_LO(scsi_id->status_fifo_addr); + lu->logout_orb->login_ID_misc = ORB_SET_FUNCTION(SBP2_LOGOUT_REQUEST); + lu->logout_orb->login_ID_misc |= + ORB_SET_LOGIN_ID(lu->login_response->length_login_ID); + lu->logout_orb->login_ID_misc |= ORB_SET_NOTIFY(1); - /* - * Byte swap ORB if necessary - */ - sbp2util_cpu_to_be32_buffer(scsi_id->logout_orb, sizeof(struct sbp2_logout_orb)); + lu->logout_orb->reserved5 = 0x0; + lu->logout_orb->status_fifo_hi = + ORB_SET_STATUS_FIFO_HI(lu->status_fifo_addr, hi->host->node_id); + lu->logout_orb->status_fifo_lo = + ORB_SET_STATUS_FIFO_LO(lu->status_fifo_addr); - sbp2util_packet_dump(scsi_id->logout_orb, sizeof(struct sbp2_logout_orb), - "sbp2 logout orb", scsi_id->logout_orb_dma); + sbp2util_cpu_to_be32_buffer(lu->logout_orb, + sizeof(struct sbp2_logout_orb)); - /* - * Ok, let's write to the target's management agent register - */ data[0] = ORB_SET_NODE_ID(hi->host->node_id); - data[1] = scsi_id->logout_orb_dma; + data[1] = lu->logout_orb_dma; sbp2util_cpu_to_be32_buffer(data, 8); - error = hpsb_node_write(scsi_id->ne, - scsi_id->sbp2_management_agent_addr, data, 8); + error = hpsb_node_write(lu->ne, lu->management_agent_addr, data, 8); if (error) return error; - /* Wait for device to logout...1 second. */ - if (sbp2util_access_timeout(scsi_id, HZ)) + /* wait up to 1 second for the device to complete logout */ + if (sbp2util_access_timeout(lu, HZ)) return -EIO; SBP2_INFO("Logged out of SBP-2 device"); return 0; } -/* - * This function is called in order to reconnect to a particular SBP-2 - * device, after a bus reset. - */ -static int sbp2_reconnect_device(struct scsi_id_instance_data *scsi_id) +static int sbp2_reconnect_device(struct sbp2_lu *lu) { - struct sbp2scsi_host_info *hi = scsi_id->hi; + struct sbp2_fwhost_info *hi = lu->hi; quadlet_t data[2]; int error; - SBP2_DEBUG_ENTER(); + lu->reconnect_orb->reserved1 = 0x0; + lu->reconnect_orb->reserved2 = 0x0; + lu->reconnect_orb->reserved3 = 0x0; + lu->reconnect_orb->reserved4 = 0x0; - /* - * Set-up reconnect ORB - */ - scsi_id->reconnect_orb->reserved1 = 0x0; - scsi_id->reconnect_orb->reserved2 = 0x0; - scsi_id->reconnect_orb->reserved3 = 0x0; - scsi_id->reconnect_orb->reserved4 = 0x0; - - scsi_id->reconnect_orb->login_ID_misc = ORB_SET_FUNCTION(SBP2_RECONNECT_REQUEST); - scsi_id->reconnect_orb->login_ID_misc |= - ORB_SET_LOGIN_ID(scsi_id->login_response->length_login_ID); + lu->reconnect_orb->login_ID_misc = + ORB_SET_FUNCTION(SBP2_RECONNECT_REQUEST); + lu->reconnect_orb->login_ID_misc |= + ORB_SET_LOGIN_ID(lu->login_response->length_login_ID); + lu->reconnect_orb->login_ID_misc |= ORB_SET_NOTIFY(1); - /* Notify us when complete */ - scsi_id->reconnect_orb->login_ID_misc |= ORB_SET_NOTIFY(1); + lu->reconnect_orb->reserved5 = 0x0; + lu->reconnect_orb->status_fifo_hi = + ORB_SET_STATUS_FIFO_HI(lu->status_fifo_addr, hi->host->node_id); + lu->reconnect_orb->status_fifo_lo = + ORB_SET_STATUS_FIFO_LO(lu->status_fifo_addr); - scsi_id->reconnect_orb->reserved5 = 0x0; - scsi_id->reconnect_orb->status_fifo_hi = - ORB_SET_STATUS_FIFO_HI(scsi_id->status_fifo_addr, hi->host->node_id); - scsi_id->reconnect_orb->status_fifo_lo = - ORB_SET_STATUS_FIFO_LO(scsi_id->status_fifo_addr); - - /* - * Byte swap ORB if necessary - */ - sbp2util_cpu_to_be32_buffer(scsi_id->reconnect_orb, sizeof(struct sbp2_reconnect_orb)); - - sbp2util_packet_dump(scsi_id->reconnect_orb, sizeof(struct sbp2_reconnect_orb), - "sbp2 reconnect orb", scsi_id->reconnect_orb_dma); + sbp2util_cpu_to_be32_buffer(lu->reconnect_orb, + sizeof(struct sbp2_reconnect_orb)); data[0] = ORB_SET_NODE_ID(hi->host->node_id); - data[1] = scsi_id->reconnect_orb_dma; + data[1] = lu->reconnect_orb_dma; sbp2util_cpu_to_be32_buffer(data, 8); - error = hpsb_node_write(scsi_id->ne, - scsi_id->sbp2_management_agent_addr, data, 8); + error = hpsb_node_write(lu->ne, lu->management_agent_addr, data, 8); if (error) return error; - /* - * Wait for reconnect status (up to 1 second)... - */ - if (sbp2util_access_timeout(scsi_id, HZ)) { + /* wait up to 1 second for reconnect status */ + if (sbp2util_access_timeout(lu, HZ)) { SBP2_ERR("Error reconnecting to SBP-2 device - timed out"); return -EIO; } - /* - * Sanity. Make sure status returned matches reconnect orb. - */ - if (scsi_id->status_block.ORB_offset_lo != scsi_id->reconnect_orb_dma) { + /* make sure that the returned status matches the reconnect ORB */ + if (lu->status_block.ORB_offset_lo != lu->reconnect_orb_dma) { SBP2_ERR("Error reconnecting to SBP-2 device - timed out"); return -EIO; } - if (STATUS_TEST_RDS(scsi_id->status_block.ORB_offset_hi_misc)) { + if (STATUS_TEST_RDS(lu->status_block.ORB_offset_hi_misc)) { SBP2_ERR("Error reconnecting to SBP-2 device - failed"); return -EIO; } - HPSB_DEBUG("Reconnected to SBP-2 device"); + SBP2_INFO("Reconnected to SBP-2 device"); return 0; } /* - * This function is called in order to set the busy timeout (number of - * retries to attempt) on the sbp2 device. + * Set the target node's Single Phase Retry limit. Affects the target's retry + * behaviour if our node is too busy to accept requests. */ -static int sbp2_set_busy_timeout(struct scsi_id_instance_data *scsi_id) +static int sbp2_set_busy_timeout(struct sbp2_lu *lu) { quadlet_t data; - SBP2_DEBUG_ENTER(); - data = cpu_to_be32(SBP2_BUSY_TIMEOUT_VALUE); - if (hpsb_node_write(scsi_id->ne, SBP2_BUSY_TIMEOUT_ADDRESS, &data, 4)) + if (hpsb_node_write(lu->ne, SBP2_BUSY_TIMEOUT_ADDRESS, &data, 4)) SBP2_ERR("%s error", __FUNCTION__); return 0; } -/* - * This function is called to parse sbp2 device's config rom unit - * directory. Used to determine things like sbp2 management agent offset, - * and command set used (SCSI or RBC). - */ -static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id, +static void sbp2_parse_unit_directory(struct sbp2_lu *lu, struct unit_directory *ud) { struct csr1212_keyval *kv; struct csr1212_dentry *dentry; u64 management_agent_addr; - u32 command_set_spec_id, command_set, unit_characteristics, - firmware_revision; + u32 unit_characteristics, firmware_revision; unsigned workarounds; int i; - SBP2_DEBUG_ENTER(); + management_agent_addr = 0; + unit_characteristics = 0; + firmware_revision = 0; - management_agent_addr = 0x0; - command_set_spec_id = 0x0; - command_set = 0x0; - unit_characteristics = 0x0; - firmware_revision = 0x0; - - /* Handle different fields in the unit directory, based on keys */ csr1212_for_each_dir_entry(ud->ne->csr, kv, ud->ud_kv, dentry) { switch (kv->key.id) { case CSR1212_KV_ID_DEPENDENT_INFO: - if (kv->key.type == CSR1212_KV_TYPE_CSR_OFFSET) { - /* Save off the management agent address */ + if (kv->key.type == CSR1212_KV_TYPE_CSR_OFFSET) management_agent_addr = CSR1212_REGISTER_SPACE_BASE + (kv->value.csr_offset << 2); - SBP2_DEBUG("sbp2_management_agent_addr = %x", - (unsigned int)management_agent_addr); - } else if (kv->key.type == CSR1212_KV_TYPE_IMMEDIATE) { - scsi_id->sbp2_lun = - ORB_SET_LUN(kv->value.immediate); - } - break; - - case SBP2_COMMAND_SET_SPEC_ID_KEY: - /* Command spec organization */ - command_set_spec_id = kv->value.immediate; - SBP2_DEBUG("sbp2_command_set_spec_id = %x", - (unsigned int)command_set_spec_id); - break; - - case SBP2_COMMAND_SET_KEY: - /* Command set used by sbp2 device */ - command_set = kv->value.immediate; - SBP2_DEBUG("sbp2_command_set = %x", - (unsigned int)command_set); + else if (kv->key.type == CSR1212_KV_TYPE_IMMEDIATE) + lu->lun = ORB_SET_LUN(kv->value.immediate); break; case SBP2_UNIT_CHARACTERISTICS_KEY: - /* - * Unit characterisitcs (orb related stuff - * that I'm not yet paying attention to) - */ + /* FIXME: This is ignored so far. + * See SBP-2 clause 7.4.8. */ unit_characteristics = kv->value.immediate; - SBP2_DEBUG("sbp2_unit_characteristics = %x", - (unsigned int)unit_characteristics); break; case SBP2_FIRMWARE_REVISION_KEY: - /* Firmware revision */ firmware_revision = kv->value.immediate; - SBP2_DEBUG("sbp2_firmware_revision = %x", - (unsigned int)firmware_revision); break; default: + /* FIXME: Check for SBP2_DEVICE_TYPE_AND_LUN_KEY. + * Its "ordered" bit has consequences for command ORB + * list handling. See SBP-2 clauses 4.6, 7.4.11, 10.2 */ break; } } @@ -1626,28 +1329,24 @@ static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id, /* We would need one SCSI host template for each target to adjust * max_sectors on the fly, therefore warn only. */ if (workarounds & SBP2_WORKAROUND_128K_MAX_TRANS && - (max_sectors * 512) > (128 * 1024)) - SBP2_WARN("Node " NODE_BUS_FMT ": Bridge only supports 128KB " + (sbp2_max_sectors * 512) > (128 * 1024)) + SBP2_INFO("Node " NODE_BUS_FMT ": Bridge only supports 128KB " "max transfer size. WARNING: Current max_sectors " "setting is larger than 128KB (%d sectors)", NODE_BUS_ARGS(ud->ne->host, ud->ne->nodeid), - max_sectors); + sbp2_max_sectors); /* If this is a logical unit directory entry, process the parent * to get the values. */ if (ud->flags & UNIT_DIRECTORY_LUN_DIRECTORY) { - struct unit_directory *parent_ud = - container_of(ud->device.parent, struct unit_directory, device); - sbp2_parse_unit_directory(scsi_id, parent_ud); + struct unit_directory *parent_ud = container_of( + ud->device.parent, struct unit_directory, device); + sbp2_parse_unit_directory(lu, parent_ud); } else { - scsi_id->sbp2_management_agent_addr = management_agent_addr; - scsi_id->sbp2_command_set_spec_id = command_set_spec_id; - scsi_id->sbp2_command_set = command_set; - scsi_id->sbp2_unit_characteristics = unit_characteristics; - scsi_id->sbp2_firmware_revision = firmware_revision; - scsi_id->workarounds = workarounds; + lu->management_agent_addr = management_agent_addr; + lu->workarounds = workarounds; if (ud->flags & UNIT_DIRECTORY_HAS_LUN) - scsi_id->sbp2_lun = ORB_SET_LUN(ud->lun); + lu->lun = ORB_SET_LUN(ud->lun); } } @@ -1662,133 +1361,114 @@ static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id, * the speed that it needs to use, and the max_rec the host supports, and * it takes care of the rest. */ -static int sbp2_max_speed_and_size(struct scsi_id_instance_data *scsi_id) +static int sbp2_max_speed_and_size(struct sbp2_lu *lu) { - struct sbp2scsi_host_info *hi = scsi_id->hi; + struct sbp2_fwhost_info *hi = lu->hi; u8 payload; - SBP2_DEBUG_ENTER(); - - scsi_id->speed_code = - hi->host->speed[NODEID_TO_NODE(scsi_id->ne->nodeid)]; + lu->speed_code = hi->host->speed[NODEID_TO_NODE(lu->ne->nodeid)]; - /* Bump down our speed if the user requested it */ - if (scsi_id->speed_code > max_speed) { - scsi_id->speed_code = max_speed; - SBP2_ERR("Forcing SBP-2 max speed down to %s", - hpsb_speedto_str[scsi_id->speed_code]); + if (lu->speed_code > sbp2_max_speed) { + lu->speed_code = sbp2_max_speed; + SBP2_INFO("Reducing speed to %s", + hpsb_speedto_str[sbp2_max_speed]); } /* Payload size is the lesser of what our speed supports and what * our host supports. */ - payload = min(sbp2_speedto_max_payload[scsi_id->speed_code], + payload = min(sbp2_speedto_max_payload[lu->speed_code], (u8) (hi->host->csr.max_rec - 1)); /* If physical DMA is off, work around limitation in ohci1394: * packet size must not exceed PAGE_SIZE */ - if (scsi_id->ne->host->low_addr_space < (1ULL << 32)) + if (lu->ne->host->low_addr_space < (1ULL << 32)) while (SBP2_PAYLOAD_TO_BYTES(payload) + 24 > PAGE_SIZE && payload) payload--; - HPSB_DEBUG("Node " NODE_BUS_FMT ": Max speed [%s] - Max payload [%u]", - NODE_BUS_ARGS(hi->host, scsi_id->ne->nodeid), - hpsb_speedto_str[scsi_id->speed_code], - SBP2_PAYLOAD_TO_BYTES(payload)); + SBP2_INFO("Node " NODE_BUS_FMT ": Max speed [%s] - Max payload [%u]", + NODE_BUS_ARGS(hi->host, lu->ne->nodeid), + hpsb_speedto_str[lu->speed_code], + SBP2_PAYLOAD_TO_BYTES(payload)); - scsi_id->max_payload_size = payload; + lu->max_payload_size = payload; return 0; } -/* - * This function is called in order to perform a SBP-2 agent reset. - */ -static int sbp2_agent_reset(struct scsi_id_instance_data *scsi_id, int wait) +static int sbp2_agent_reset(struct sbp2_lu *lu, int wait) { quadlet_t data; u64 addr; int retval; unsigned long flags; - SBP2_DEBUG_ENTER(); - - cancel_delayed_work(&scsi_id->protocol_work); + /* flush lu->protocol_work */ if (wait) flush_scheduled_work(); data = ntohl(SBP2_AGENT_RESET_DATA); - addr = scsi_id->sbp2_command_block_agent_addr + SBP2_AGENT_RESET_OFFSET; + addr = lu->command_block_agent_addr + SBP2_AGENT_RESET_OFFSET; if (wait) - retval = hpsb_node_write(scsi_id->ne, addr, &data, 4); + retval = hpsb_node_write(lu->ne, addr, &data, 4); else - retval = sbp2util_node_write_no_wait(scsi_id->ne, addr, &data, 4); + retval = sbp2util_node_write_no_wait(lu->ne, addr, &data, 4); if (retval < 0) { SBP2_ERR("hpsb_node_write failed.\n"); return -EIO; } - /* - * Need to make sure orb pointer is written on next command - */ - spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags); - scsi_id->last_orb = NULL; - spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags); + /* make sure that the ORB_POINTER is written on next command */ + spin_lock_irqsave(&lu->cmd_orb_lock, flags); + lu->last_orb = NULL; + spin_unlock_irqrestore(&lu->cmd_orb_lock, flags); return 0; } static void sbp2_prep_command_orb_sg(struct sbp2_command_orb *orb, - struct sbp2scsi_host_info *hi, - struct sbp2_command_info *command, + struct sbp2_fwhost_info *hi, + struct sbp2_command_info *cmd, unsigned int scsi_use_sg, struct scatterlist *sgpnt, u32 orb_direction, enum dma_data_direction dma_dir) { - command->dma_dir = dma_dir; + cmd->dma_dir = dma_dir; orb->data_descriptor_hi = ORB_SET_NODE_ID(hi->host->node_id); orb->misc |= ORB_SET_DIRECTION(orb_direction); - /* Special case if only one element (and less than 64KB in size) */ + /* special case if only one element (and less than 64KB in size) */ if ((scsi_use_sg == 1) && (sgpnt[0].length <= SBP2_MAX_SG_ELEMENT_LENGTH)) { - SBP2_DEBUG("Only one s/g element"); - command->dma_size = sgpnt[0].length; - command->dma_type = CMD_DMA_PAGE; - command->cmd_dma = pci_map_page(hi->host->pdev, - sgpnt[0].page, - sgpnt[0].offset, - command->dma_size, - command->dma_dir); - SBP2_DMA_ALLOC("single page scatter element"); + cmd->dma_size = sgpnt[0].length; + cmd->dma_type = CMD_DMA_PAGE; + cmd->cmd_dma = dma_map_page(&hi->host->device, + sgpnt[0].page, sgpnt[0].offset, + cmd->dma_size, cmd->dma_dir); - orb->data_descriptor_lo = command->cmd_dma; - orb->misc |= ORB_SET_DATA_SIZE(command->dma_size); + orb->data_descriptor_lo = cmd->cmd_dma; + orb->misc |= ORB_SET_DATA_SIZE(cmd->dma_size); } else { struct sbp2_unrestricted_page_table *sg_element = - &command->scatter_gather_element[0]; + &cmd->scatter_gather_element[0]; u32 sg_count, sg_len; dma_addr_t sg_addr; - int i, count = pci_map_sg(hi->host->pdev, sgpnt, scsi_use_sg, + int i, count = dma_map_sg(&hi->host->device, sgpnt, scsi_use_sg, dma_dir); - SBP2_DMA_ALLOC("scatter list"); - - command->dma_size = scsi_use_sg; - command->sge_buffer = sgpnt; + cmd->dma_size = scsi_use_sg; + cmd->sge_buffer = sgpnt; /* use page tables (s/g) */ orb->misc |= ORB_SET_PAGE_TABLE_PRESENT(0x1); - orb->data_descriptor_lo = command->sge_dma; + orb->data_descriptor_lo = cmd->sge_dma; - /* - * Loop through and fill out our sbp-2 page tables - * (and split up anything too large) - */ + /* loop through and fill out our SBP-2 page tables + * (and split up anything too large) */ for (i = 0, sg_count = 0 ; i < count; i++, sgpnt++) { sg_len = sg_dma_len(sgpnt); sg_addr = sg_dma_address(sgpnt); @@ -1808,70 +1488,53 @@ static void sbp2_prep_command_orb_sg(struct sbp2_command_orb *orb, } } - /* Number of page table (s/g) elements */ orb->misc |= ORB_SET_DATA_SIZE(sg_count); - sbp2util_packet_dump(sg_element, - (sizeof(struct sbp2_unrestricted_page_table)) * sg_count, - "sbp2 s/g list", command->sge_dma); - - /* Byte swap page tables if necessary */ sbp2util_cpu_to_be32_buffer(sg_element, - (sizeof(struct sbp2_unrestricted_page_table)) * - sg_count); + (sizeof(struct sbp2_unrestricted_page_table)) * + sg_count); } } static void sbp2_prep_command_orb_no_sg(struct sbp2_command_orb *orb, - struct sbp2scsi_host_info *hi, - struct sbp2_command_info *command, + struct sbp2_fwhost_info *hi, + struct sbp2_command_info *cmd, struct scatterlist *sgpnt, u32 orb_direction, unsigned int scsi_request_bufflen, void *scsi_request_buffer, enum dma_data_direction dma_dir) { - command->dma_dir = dma_dir; - command->dma_size = scsi_request_bufflen; - command->dma_type = CMD_DMA_SINGLE; - command->cmd_dma = pci_map_single(hi->host->pdev, scsi_request_buffer, - command->dma_size, command->dma_dir); + cmd->dma_dir = dma_dir; + cmd->dma_size = scsi_request_bufflen; + cmd->dma_type = CMD_DMA_SINGLE; + cmd->cmd_dma = dma_map_single(&hi->host->device, scsi_request_buffer, + cmd->dma_size, cmd->dma_dir); orb->data_descriptor_hi = ORB_SET_NODE_ID(hi->host->node_id); orb->misc |= ORB_SET_DIRECTION(orb_direction); - SBP2_DMA_ALLOC("single bulk"); - - /* - * Handle case where we get a command w/o s/g enabled (but - * check for transfers larger than 64K) - */ + /* handle case where we get a command w/o s/g enabled + * (but check for transfers larger than 64K) */ if (scsi_request_bufflen <= SBP2_MAX_SG_ELEMENT_LENGTH) { - orb->data_descriptor_lo = command->cmd_dma; + orb->data_descriptor_lo = cmd->cmd_dma; orb->misc |= ORB_SET_DATA_SIZE(scsi_request_bufflen); } else { + /* The buffer is too large. Turn this into page tables. */ + struct sbp2_unrestricted_page_table *sg_element = - &command->scatter_gather_element[0]; + &cmd->scatter_gather_element[0]; u32 sg_count, sg_len; dma_addr_t sg_addr; - /* - * Need to turn this into page tables, since the - * buffer is too large. - */ - orb->data_descriptor_lo = command->sge_dma; - - /* Use page tables (s/g) */ + orb->data_descriptor_lo = cmd->sge_dma; orb->misc |= ORB_SET_PAGE_TABLE_PRESENT(0x1); - /* - * fill out our sbp-2 page tables (and split up - * the large buffer) - */ + /* fill out our SBP-2 page tables; split up the large buffer */ sg_count = 0; sg_len = scsi_request_bufflen; - sg_addr = command->cmd_dma; + sg_addr = cmd->cmd_dma; while (sg_len) { sg_element[sg_count].segment_base_lo = sg_addr; if (sg_len > SBP2_MAX_SG_ELEMENT_LENGTH) { @@ -1887,50 +1550,40 @@ static void sbp2_prep_command_orb_no_sg(struct sbp2_command_orb *orb, sg_count++; } - /* Number of page table (s/g) elements */ orb->misc |= ORB_SET_DATA_SIZE(sg_count); - sbp2util_packet_dump(sg_element, - (sizeof(struct sbp2_unrestricted_page_table)) * sg_count, - "sbp2 s/g list", command->sge_dma); - - /* Byte swap page tables if necessary */ sbp2util_cpu_to_be32_buffer(sg_element, - (sizeof(struct sbp2_unrestricted_page_table)) * - sg_count); + (sizeof(struct sbp2_unrestricted_page_table)) * + sg_count); } } -/* - * This function is called to create the actual command orb and s/g list - * out of the scsi command itself. - */ -static void sbp2_create_command_orb(struct scsi_id_instance_data *scsi_id, - struct sbp2_command_info *command, +static void sbp2_create_command_orb(struct sbp2_lu *lu, + struct sbp2_command_info *cmd, unchar *scsi_cmd, unsigned int scsi_use_sg, unsigned int scsi_request_bufflen, void *scsi_request_buffer, enum dma_data_direction dma_dir) { - struct sbp2scsi_host_info *hi = scsi_id->hi; + struct sbp2_fwhost_info *hi = lu->hi; struct scatterlist *sgpnt = (struct scatterlist *)scsi_request_buffer; - struct sbp2_command_orb *command_orb = &command->command_orb; + struct sbp2_command_orb *orb = &cmd->command_orb; u32 orb_direction; /* - * Set-up our command ORB.. + * Set-up our command ORB. * * NOTE: We're doing unrestricted page tables (s/g), as this is * best performance (at least with the devices I have). This means * that data_size becomes the number of s/g elements, and * page_size should be zero (for unrestricted). */ - command_orb->next_ORB_hi = ORB_SET_NULL_PTR(1); - command_orb->next_ORB_lo = 0x0; - command_orb->misc = ORB_SET_MAX_PAYLOAD(scsi_id->max_payload_size); - command_orb->misc |= ORB_SET_SPEED(scsi_id->speed_code); - command_orb->misc |= ORB_SET_NOTIFY(1); /* Notify us when complete */ + orb->next_ORB_hi = ORB_SET_NULL_PTR(1); + orb->next_ORB_lo = 0x0; + orb->misc = ORB_SET_MAX_PAYLOAD(lu->max_payload_size); + orb->misc |= ORB_SET_SPEED(lu->speed_code); + orb->misc |= ORB_SET_NOTIFY(1); if (dma_dir == DMA_NONE) orb_direction = ORB_DIRECTION_NO_DATA_TRANSFER; @@ -1939,66 +1592,51 @@ static void sbp2_create_command_orb(struct scsi_id_instance_data *scsi_id, else if (dma_dir == DMA_FROM_DEVICE && scsi_request_bufflen) orb_direction = ORB_DIRECTION_READ_FROM_MEDIA; else { - SBP2_WARN("Falling back to DMA_NONE"); + SBP2_INFO("Falling back to DMA_NONE"); orb_direction = ORB_DIRECTION_NO_DATA_TRANSFER; } - /* Set-up our pagetable stuff */ + /* set up our page table stuff */ if (orb_direction == ORB_DIRECTION_NO_DATA_TRANSFER) { - SBP2_DEBUG("No data transfer"); - command_orb->data_descriptor_hi = 0x0; - command_orb->data_descriptor_lo = 0x0; - command_orb->misc |= ORB_SET_DIRECTION(1); - } else if (scsi_use_sg) { - SBP2_DEBUG("Use scatter/gather"); - sbp2_prep_command_orb_sg(command_orb, hi, command, scsi_use_sg, - sgpnt, orb_direction, dma_dir); - } else { - SBP2_DEBUG("No scatter/gather"); - sbp2_prep_command_orb_no_sg(command_orb, hi, command, sgpnt, - orb_direction, scsi_request_bufflen, + orb->data_descriptor_hi = 0x0; + orb->data_descriptor_lo = 0x0; + orb->misc |= ORB_SET_DIRECTION(1); + } else if (scsi_use_sg) + sbp2_prep_command_orb_sg(orb, hi, cmd, scsi_use_sg, sgpnt, + orb_direction, dma_dir); + else + sbp2_prep_command_orb_no_sg(orb, hi, cmd, sgpnt, orb_direction, + scsi_request_bufflen, scsi_request_buffer, dma_dir); - } - /* Byte swap command ORB if necessary */ - sbp2util_cpu_to_be32_buffer(command_orb, sizeof(struct sbp2_command_orb)); + sbp2util_cpu_to_be32_buffer(orb, sizeof(*orb)); - /* Put our scsi command in the command ORB */ - memset(command_orb->cdb, 0, 12); - memcpy(command_orb->cdb, scsi_cmd, COMMAND_SIZE(*scsi_cmd)); + memset(orb->cdb, 0, 12); + memcpy(orb->cdb, scsi_cmd, COMMAND_SIZE(*scsi_cmd)); } -/* - * This function is called in order to begin a regular SBP-2 command. - */ -static void sbp2_link_orb_command(struct scsi_id_instance_data *scsi_id, - struct sbp2_command_info *command) +static void sbp2_link_orb_command(struct sbp2_lu *lu, + struct sbp2_command_info *cmd) { - struct sbp2scsi_host_info *hi = scsi_id->hi; - struct sbp2_command_orb *command_orb = &command->command_orb; + struct sbp2_fwhost_info *hi = lu->hi; struct sbp2_command_orb *last_orb; dma_addr_t last_orb_dma; - u64 addr = scsi_id->sbp2_command_block_agent_addr; + u64 addr = lu->command_block_agent_addr; quadlet_t data[2]; size_t length; unsigned long flags; - outstanding_orb_incr; - SBP2_ORB_DEBUG("sending command orb %p, total orbs = %x", - command_orb, global_outstanding_command_orbs); - - pci_dma_sync_single_for_device(hi->host->pdev, command->command_orb_dma, - sizeof(struct sbp2_command_orb), - PCI_DMA_TODEVICE); - pci_dma_sync_single_for_device(hi->host->pdev, command->sge_dma, - sizeof(command->scatter_gather_element), - PCI_DMA_BIDIRECTIONAL); - /* - * Check to see if there are any previous orbs to use - */ - spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags); - last_orb = scsi_id->last_orb; - last_orb_dma = scsi_id->last_orb_dma; + dma_sync_single_for_device(&hi->host->device, cmd->command_orb_dma, + sizeof(struct sbp2_command_orb), + DMA_TO_DEVICE); + dma_sync_single_for_device(&hi->host->device, cmd->sge_dma, + sizeof(cmd->scatter_gather_element), + DMA_BIDIRECTIONAL); + + /* check to see if there are any previous orbs to use */ + spin_lock_irqsave(&lu->cmd_orb_lock, flags); + last_orb = lu->last_orb; + last_orb_dma = lu->last_orb_dma; if (!last_orb) { /* * last_orb == NULL means: We know that the target's fetch agent @@ -2006,7 +1644,7 @@ static void sbp2_link_orb_command(struct scsi_id_instance_data *scsi_id, */ addr += SBP2_ORB_POINTER_OFFSET; data[0] = ORB_SET_NODE_ID(hi->host->node_id); - data[1] = command->command_orb_dma; + data[1] = cmd->command_orb_dma; sbp2util_cpu_to_be32_buffer(data, 8); length = 8; } else { @@ -2017,27 +1655,25 @@ static void sbp2_link_orb_command(struct scsi_id_instance_data *scsi_id, * The target's fetch agent may or may not have read this * previous ORB yet. */ - pci_dma_sync_single_for_cpu(hi->host->pdev, last_orb_dma, - sizeof(struct sbp2_command_orb), - PCI_DMA_TODEVICE); - last_orb->next_ORB_lo = cpu_to_be32(command->command_orb_dma); + dma_sync_single_for_cpu(&hi->host->device, last_orb_dma, + sizeof(struct sbp2_command_orb), + DMA_TO_DEVICE); + last_orb->next_ORB_lo = cpu_to_be32(cmd->command_orb_dma); wmb(); /* Tells hardware that this pointer is valid */ last_orb->next_ORB_hi = 0; - pci_dma_sync_single_for_device(hi->host->pdev, last_orb_dma, - sizeof(struct sbp2_command_orb), - PCI_DMA_TODEVICE); + dma_sync_single_for_device(&hi->host->device, last_orb_dma, + sizeof(struct sbp2_command_orb), + DMA_TO_DEVICE); addr += SBP2_DOORBELL_OFFSET; data[0] = 0; length = 4; } - scsi_id->last_orb = command_orb; - scsi_id->last_orb_dma = command->command_orb_dma; - spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags); + lu->last_orb = &cmd->command_orb; + lu->last_orb_dma = cmd->command_orb_dma; + spin_unlock_irqrestore(&lu->cmd_orb_lock, flags); - SBP2_ORB_DEBUG("write to %s register, command orb %p", - last_orb ? "DOORBELL" : "ORB_POINTER", command_orb); - if (sbp2util_node_write_no_wait(scsi_id->ne, addr, data, length)) { + if (sbp2util_node_write_no_wait(lu->ne, addr, data, length)) { /* * sbp2util_node_write_no_wait failed. We certainly ran out * of transaction labels, perhaps just because there were no @@ -2046,52 +1682,29 @@ static void sbp2_link_orb_command(struct scsi_id_instance_data *scsi_id, * the workqueue job will sleep to guaranteedly get a tlabel. * We do not accept new commands until the job is over. */ - scsi_block_requests(scsi_id->scsi_host); - PREPARE_WORK(&scsi_id->protocol_work, + scsi_block_requests(lu->shost); + PREPARE_WORK(&lu->protocol_work, last_orb ? sbp2util_write_doorbell: - sbp2util_write_orb_pointer, - scsi_id); - schedule_work(&scsi_id->protocol_work); + sbp2util_write_orb_pointer); + schedule_work(&lu->protocol_work); } } -/* - * This function is called in order to begin a regular SBP-2 command. - */ -static int sbp2_send_command(struct scsi_id_instance_data *scsi_id, - struct scsi_cmnd *SCpnt, +static int sbp2_send_command(struct sbp2_lu *lu, struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) { - unchar *cmd = (unchar *) SCpnt->cmnd; + unchar *scsi_cmd = (unchar *)SCpnt->cmnd; unsigned int request_bufflen = SCpnt->request_bufflen; - struct sbp2_command_info *command; + struct sbp2_command_info *cmd; - SBP2_DEBUG_ENTER(); - SBP2_DEBUG("SCSI transfer size = %x", request_bufflen); - SBP2_DEBUG("SCSI s/g elements = %x", (unsigned int)SCpnt->use_sg); - - /* - * Allocate a command orb and s/g structure - */ - command = sbp2util_allocate_command_orb(scsi_id, SCpnt, done); - if (!command) { + cmd = sbp2util_allocate_command_orb(lu, SCpnt, done); + if (!cmd) return -EIO; - } - /* - * Now actually fill in the comamnd orb and sbp2 s/g list - */ - sbp2_create_command_orb(scsi_id, command, cmd, SCpnt->use_sg, + sbp2_create_command_orb(lu, cmd, scsi_cmd, SCpnt->use_sg, request_bufflen, SCpnt->request_buffer, SCpnt->sc_data_direction); - - sbp2util_packet_dump(&command->command_orb, sizeof(struct sbp2_command_orb), - "sbp2 command orb", command->command_orb_dma); - - /* - * Link up the orb, and ring the doorbell if needed - */ - sbp2_link_orb_command(scsi_id, command); + sbp2_link_orb_command(lu, cmd); return 0; } @@ -2099,13 +1712,10 @@ static int sbp2_send_command(struct scsi_id_instance_data *scsi_id, /* * Translates SBP-2 status into SCSI sense data for check conditions */ -static unsigned int sbp2_status_to_sense_data(unchar *sbp2_status, unchar *sense_data) +static unsigned int sbp2_status_to_sense_data(unchar *sbp2_status, + unchar *sense_data) { - SBP2_DEBUG_ENTER(); - - /* - * Ok, it's pretty ugly... ;-) - */ + /* OK, it's pretty ugly... ;-) */ sense_data[0] = 0x70; sense_data[1] = 0x0; sense_data[2] = sbp2_status[9]; @@ -2123,28 +1733,21 @@ static unsigned int sbp2_status_to_sense_data(unchar *sbp2_status, unchar *sense sense_data[14] = sbp2_status[20]; sense_data[15] = sbp2_status[21]; - return sbp2_status[8] & 0x3f; /* return scsi status */ + return sbp2_status[8] & 0x3f; } -/* - * This function deals with status writes from the SBP-2 device - */ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int destid, quadlet_t *data, u64 addr, size_t length, u16 fl) { - struct sbp2scsi_host_info *hi; - struct scsi_id_instance_data *scsi_id = NULL, *scsi_id_tmp; + struct sbp2_fwhost_info *hi; + struct sbp2_lu *lu = NULL, *lu_tmp; struct scsi_cmnd *SCpnt = NULL; struct sbp2_status_block *sb; u32 scsi_status = SBP2_SCSI_STATUS_GOOD; - struct sbp2_command_info *command; + struct sbp2_command_info *cmd; unsigned long flags; - SBP2_DEBUG_ENTER(); - - sbp2util_packet_dump(data, length, "sbp2 status write by device", (u32)addr); - if (unlikely(length < 8 || length > sizeof(struct sbp2_status_block))) { SBP2_ERR("Wrong size of status block"); return RCODE_ADDRESS_ERROR; @@ -2158,131 +1761,97 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, SBP2_ERR("host info is NULL - this is bad!"); return RCODE_ADDRESS_ERROR; } - /* - * Find our scsi_id structure by looking at the status fifo address - * written to by the sbp2 device. - */ - list_for_each_entry(scsi_id_tmp, &hi->scsi_ids, scsi_list) { - if (scsi_id_tmp->ne->nodeid == nodeid && - scsi_id_tmp->status_fifo_addr == addr) { - scsi_id = scsi_id_tmp; + + /* Find the unit which wrote the status. */ + list_for_each_entry(lu_tmp, &hi->logical_units, lu_list) { + if (lu_tmp->ne->nodeid == nodeid && + lu_tmp->status_fifo_addr == addr) { + lu = lu_tmp; break; } } - if (unlikely(!scsi_id)) { - SBP2_ERR("scsi_id is NULL - device is gone?"); + if (unlikely(!lu)) { + SBP2_ERR("lu is NULL - device is gone?"); return RCODE_ADDRESS_ERROR; } - /* - * Put response into scsi_id status fifo buffer. The first two bytes + /* Put response into lu status fifo buffer. The first two bytes * come in big endian bit order. Often the target writes only a * truncated status block, minimally the first two quadlets. The rest - * is implied to be zeros. - */ - sb = &scsi_id->status_block; + * is implied to be zeros. */ + sb = &lu->status_block; memset(sb->command_set_dependent, 0, sizeof(sb->command_set_dependent)); memcpy(sb, data, length); sbp2util_be32_to_cpu_buffer(sb, 8); - /* - * Ignore unsolicited status. Handle command ORB status. - */ + /* Ignore unsolicited status. Handle command ORB status. */ if (unlikely(STATUS_GET_SRC(sb->ORB_offset_hi_misc) == 2)) - command = NULL; + cmd = NULL; else - command = sbp2util_find_command_for_orb(scsi_id, - sb->ORB_offset_lo); - if (command) { - SBP2_DEBUG("Found status for command ORB"); - pci_dma_sync_single_for_cpu(hi->host->pdev, command->command_orb_dma, - sizeof(struct sbp2_command_orb), - PCI_DMA_TODEVICE); - pci_dma_sync_single_for_cpu(hi->host->pdev, command->sge_dma, - sizeof(command->scatter_gather_element), - PCI_DMA_BIDIRECTIONAL); - - SBP2_ORB_DEBUG("matched command orb %p", &command->command_orb); - outstanding_orb_decr; - - /* - * Matched status with command, now grab scsi command pointers - * and check status. - */ + cmd = sbp2util_find_command_for_orb(lu, sb->ORB_offset_lo); + if (cmd) { + dma_sync_single_for_cpu(&hi->host->device, cmd->command_orb_dma, + sizeof(struct sbp2_command_orb), + DMA_TO_DEVICE); + dma_sync_single_for_cpu(&hi->host->device, cmd->sge_dma, + sizeof(cmd->scatter_gather_element), + DMA_BIDIRECTIONAL); + /* Grab SCSI command pointers and check status. */ /* * FIXME: If the src field in the status is 1, the ORB DMA must * not be reused until status for a subsequent ORB is received. */ - SCpnt = command->Current_SCpnt; - spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags); - sbp2util_mark_command_completed(scsi_id, command); - spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags); + SCpnt = cmd->Current_SCpnt; + spin_lock_irqsave(&lu->cmd_orb_lock, flags); + sbp2util_mark_command_completed(lu, cmd); + spin_unlock_irqrestore(&lu->cmd_orb_lock, flags); if (SCpnt) { u32 h = sb->ORB_offset_hi_misc; u32 r = STATUS_GET_RESP(h); if (r != RESP_STATUS_REQUEST_COMPLETE) { - SBP2_WARN("resp 0x%x, sbp_status 0x%x", + SBP2_INFO("resp 0x%x, sbp_status 0x%x", r, STATUS_GET_SBP_STATUS(h)); scsi_status = r == RESP_STATUS_TRANSPORT_FAILURE ? SBP2_SCSI_STATUS_BUSY : SBP2_SCSI_STATUS_COMMAND_TERMINATED; } - /* - * See if the target stored any scsi status information. - */ - if (STATUS_GET_LEN(h) > 1) { - SBP2_DEBUG("CHECK CONDITION"); + + if (STATUS_GET_LEN(h) > 1) scsi_status = sbp2_status_to_sense_data( (unchar *)sb, SCpnt->sense_buffer); - } - /* - * Check to see if the dead bit is set. If so, we'll - * have to initiate a fetch agent reset. - */ - if (STATUS_TEST_DEAD(h)) { - SBP2_DEBUG("Dead bit set - " - "initiating fetch agent reset"); - sbp2_agent_reset(scsi_id, 0); - } - SBP2_ORB_DEBUG("completing command orb %p", &command->command_orb); + + if (STATUS_TEST_DEAD(h)) + sbp2_agent_reset(lu, 0); } - /* - * Check here to see if there are no commands in-use. If there + /* Check here to see if there are no commands in-use. If there * are none, we know that the fetch agent left the active state * _and_ that we did not reactivate it yet. Therefore clear * last_orb so that next time we write directly to the * ORB_POINTER register. That way the fetch agent does not need - * to refetch the next_ORB. - */ - spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags); - if (list_empty(&scsi_id->sbp2_command_orb_inuse)) - scsi_id->last_orb = NULL; - spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags); + * to refetch the next_ORB. */ + spin_lock_irqsave(&lu->cmd_orb_lock, flags); + if (list_empty(&lu->cmd_orb_inuse)) + lu->last_orb = NULL; + spin_unlock_irqrestore(&lu->cmd_orb_lock, flags); } else { - /* - * It's probably a login/logout/reconnect status. - */ - if ((sb->ORB_offset_lo == scsi_id->reconnect_orb_dma) || - (sb->ORB_offset_lo == scsi_id->login_orb_dma) || - (sb->ORB_offset_lo == scsi_id->query_logins_orb_dma) || - (sb->ORB_offset_lo == scsi_id->logout_orb_dma)) { - scsi_id->access_complete = 1; - wake_up_interruptible(&access_wq); + /* It's probably status after a management request. */ + if ((sb->ORB_offset_lo == lu->reconnect_orb_dma) || + (sb->ORB_offset_lo == lu->login_orb_dma) || + (sb->ORB_offset_lo == lu->query_logins_orb_dma) || + (sb->ORB_offset_lo == lu->logout_orb_dma)) { + lu->access_complete = 1; + wake_up_interruptible(&sbp2_access_wq); } } - if (SCpnt) { - SBP2_DEBUG("Completing SCSI command"); - sbp2scsi_complete_command(scsi_id, scsi_status, SCpnt, - command->Current_done); - SBP2_ORB_DEBUG("command orb completed"); - } - + if (SCpnt) + sbp2scsi_complete_command(lu, scsi_status, SCpnt, + cmd->Current_done); return RCODE_COMPLETE; } @@ -2290,77 +1859,57 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, * SCSI interface related section **************************************/ -/* - * This routine is the main request entry routine for doing I/O. It is - * called from the scsi stack directly. - */ static int sbp2scsi_queuecommand(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) { - struct scsi_id_instance_data *scsi_id = - (struct scsi_id_instance_data *)SCpnt->device->host->hostdata[0]; - struct sbp2scsi_host_info *hi; + struct sbp2_lu *lu = (struct sbp2_lu *)SCpnt->device->host->hostdata[0]; + struct sbp2_fwhost_info *hi; int result = DID_NO_CONNECT << 16; - SBP2_DEBUG_ENTER(); -#if (CONFIG_IEEE1394_SBP2_DEBUG >= 2) || defined(CONFIG_IEEE1394_SBP2_PACKET_DUMP) - scsi_print_command(SCpnt); -#endif - - if (!sbp2util_node_is_available(scsi_id)) + if (unlikely(!sbp2util_node_is_available(lu))) goto done; - hi = scsi_id->hi; + hi = lu->hi; - if (!hi) { - SBP2_ERR("sbp2scsi_host_info is NULL - this is bad!"); + if (unlikely(!hi)) { + SBP2_ERR("sbp2_fwhost_info is NULL - this is bad!"); goto done; } - /* - * Until we handle multiple luns, just return selection time-out - * to any IO directed at non-zero LUNs - */ - if (SCpnt->device->lun) + /* Multiple units are currently represented to the SCSI core as separate + * targets, not as one target with multiple LUs. Therefore return + * selection time-out to any IO directed at non-zero LUNs. */ + if (unlikely(SCpnt->device->lun)) goto done; - /* - * Check for request sense command, and handle it here - * (autorequest sense) - */ + /* handle the request sense command here (auto-request sense) */ if (SCpnt->cmnd[0] == REQUEST_SENSE) { - SBP2_DEBUG("REQUEST_SENSE"); - memcpy(SCpnt->request_buffer, SCpnt->sense_buffer, SCpnt->request_bufflen); + memcpy(SCpnt->request_buffer, SCpnt->sense_buffer, + SCpnt->request_bufflen); memset(SCpnt->sense_buffer, 0, sizeof(SCpnt->sense_buffer)); - sbp2scsi_complete_command(scsi_id, SBP2_SCSI_STATUS_GOOD, SCpnt, done); + sbp2scsi_complete_command(lu, SBP2_SCSI_STATUS_GOOD, SCpnt, + done); return 0; } - /* - * Check to see if we are in the middle of a bus reset. - */ - if (!hpsb_node_entry_valid(scsi_id->ne)) { + if (unlikely(!hpsb_node_entry_valid(lu->ne))) { SBP2_ERR("Bus reset in progress - rejecting command"); result = DID_BUS_BUSY << 16; goto done; } - /* - * Bidirectional commands are not yet implemented, - * and unknown transfer direction not handled. - */ - if (SCpnt->sc_data_direction == DMA_BIDIRECTIONAL) { + /* Bidirectional commands are not yet implemented, + * and unknown transfer direction not handled. */ + if (unlikely(SCpnt->sc_data_direction == DMA_BIDIRECTIONAL)) { SBP2_ERR("Cannot handle DMA_BIDIRECTIONAL - rejecting command"); result = DID_ERROR << 16; goto done; } - /* - * Try and send our SCSI command - */ - if (sbp2_send_command(scsi_id, SCpnt, done)) { + if (sbp2_send_command(lu, SCpnt, done)) { SBP2_ERR("Error sending SCSI command"); - sbp2scsi_complete_command(scsi_id, SBP2_SCSI_STATUS_SELECTION_TIMEOUT, + sbp2scsi_complete_command(lu, + SBP2_SCSI_STATUS_SELECTION_TIMEOUT, SCpnt, done); } return 0; @@ -2371,75 +1920,46 @@ static int sbp2scsi_queuecommand(struct scsi_cmnd *SCpnt, return 0; } -/* - * This function is called in order to complete all outstanding SBP-2 - * commands (in case of resets, etc.). - */ -static void sbp2scsi_complete_all_commands(struct scsi_id_instance_data *scsi_id, - u32 status) +static void sbp2scsi_complete_all_commands(struct sbp2_lu *lu, u32 status) { - struct sbp2scsi_host_info *hi = scsi_id->hi; + struct sbp2_fwhost_info *hi = lu->hi; struct list_head *lh; - struct sbp2_command_info *command; + struct sbp2_command_info *cmd; unsigned long flags; - SBP2_DEBUG_ENTER(); - - spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags); - while (!list_empty(&scsi_id->sbp2_command_orb_inuse)) { - SBP2_DEBUG("Found pending command to complete"); - lh = scsi_id->sbp2_command_orb_inuse.next; - command = list_entry(lh, struct sbp2_command_info, list); - pci_dma_sync_single_for_cpu(hi->host->pdev, command->command_orb_dma, - sizeof(struct sbp2_command_orb), - PCI_DMA_TODEVICE); - pci_dma_sync_single_for_cpu(hi->host->pdev, command->sge_dma, - sizeof(command->scatter_gather_element), - PCI_DMA_BIDIRECTIONAL); - sbp2util_mark_command_completed(scsi_id, command); - if (command->Current_SCpnt) { - command->Current_SCpnt->result = status << 16; - command->Current_done(command->Current_SCpnt); + spin_lock_irqsave(&lu->cmd_orb_lock, flags); + while (!list_empty(&lu->cmd_orb_inuse)) { + lh = lu->cmd_orb_inuse.next; + cmd = list_entry(lh, struct sbp2_command_info, list); + dma_sync_single_for_cpu(&hi->host->device, cmd->command_orb_dma, + sizeof(struct sbp2_command_orb), + DMA_TO_DEVICE); + dma_sync_single_for_cpu(&hi->host->device, cmd->sge_dma, + sizeof(cmd->scatter_gather_element), + DMA_BIDIRECTIONAL); + sbp2util_mark_command_completed(lu, cmd); + if (cmd->Current_SCpnt) { + cmd->Current_SCpnt->result = status << 16; + cmd->Current_done(cmd->Current_SCpnt); } } - spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags); + spin_unlock_irqrestore(&lu->cmd_orb_lock, flags); return; } /* - * This function is called in order to complete a regular SBP-2 command. - * - * This can be called in interrupt context. + * Complete a regular SCSI command. Can be called in atomic context. */ -static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id, - u32 scsi_status, struct scsi_cmnd *SCpnt, +static void sbp2scsi_complete_command(struct sbp2_lu *lu, u32 scsi_status, + struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) { - SBP2_DEBUG_ENTER(); - - /* - * Sanity - */ if (!SCpnt) { SBP2_ERR("SCpnt is NULL"); return; } - /* - * If a bus reset is in progress and there was an error, don't - * complete the command, just let it get retried at the end of the - * bus reset. - */ - if (!hpsb_node_entry_valid(scsi_id->ne) - && (scsi_status != SBP2_SCSI_STATUS_GOOD)) { - SBP2_ERR("Bus reset in progress - retry command later"); - return; - } - - /* - * Switch on scsi status - */ switch (scsi_status) { case SBP2_SCSI_STATUS_GOOD: SCpnt->result = DID_OK << 16; @@ -2451,12 +1971,7 @@ static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id, break; case SBP2_SCSI_STATUS_CHECK_CONDITION: - SBP2_DEBUG("SBP2_SCSI_STATUS_CHECK_CONDITION"); SCpnt->result = CHECK_CONDITION << 1 | DID_OK << 16; -#if CONFIG_IEEE1394_SBP2_DEBUG >= 1 - scsi_print_command(SCpnt); - scsi_print_sense(SBP2_DEVICE_NAME, SCpnt); -#endif break; case SBP2_SCSI_STATUS_SELECTION_TIMEOUT: @@ -2478,118 +1993,88 @@ static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id, SCpnt->result = DID_ERROR << 16; } - /* - * If a bus reset is in progress and there was an error, complete - * the command as busy so that it will get retried. - */ - if (!hpsb_node_entry_valid(scsi_id->ne) + /* If a bus reset is in progress and there was an error, complete + * the command as busy so that it will get retried. */ + if (!hpsb_node_entry_valid(lu->ne) && (scsi_status != SBP2_SCSI_STATUS_GOOD)) { SBP2_ERR("Completing command with busy (bus reset)"); SCpnt->result = DID_BUS_BUSY << 16; } - /* - * If a unit attention occurs, return busy status so it gets - * retried... it could have happened because of a 1394 bus reset - * or hot-plug... - * XXX DID_BUS_BUSY is actually a bad idea because it will defy - * the scsi layer's retry logic. - */ -#if 0 - if ((scsi_status == SBP2_SCSI_STATUS_CHECK_CONDITION) && - (SCpnt->sense_buffer[2] == UNIT_ATTENTION)) { - SBP2_DEBUG("UNIT ATTENTION - return busy"); - SCpnt->result = DID_BUS_BUSY << 16; - } -#endif - - /* - * Tell scsi stack that we're done with this command - */ + /* Tell the SCSI stack that we're done with this command. */ done(SCpnt); } static int sbp2scsi_slave_alloc(struct scsi_device *sdev) { - struct scsi_id_instance_data *scsi_id = - (struct scsi_id_instance_data *)sdev->host->hostdata[0]; + struct sbp2_lu *lu = (struct sbp2_lu *)sdev->host->hostdata[0]; - scsi_id->sdev = sdev; + lu->sdev = sdev; sdev->allow_restart = 1; - if (scsi_id->workarounds & SBP2_WORKAROUND_INQUIRY_36) + if (lu->workarounds & SBP2_WORKAROUND_INQUIRY_36) sdev->inquiry_len = 36; return 0; } static int sbp2scsi_slave_configure(struct scsi_device *sdev) { - struct scsi_id_instance_data *scsi_id = - (struct scsi_id_instance_data *)sdev->host->hostdata[0]; + struct sbp2_lu *lu = (struct sbp2_lu *)sdev->host->hostdata[0]; blk_queue_dma_alignment(sdev->request_queue, (512 - 1)); sdev->use_10_for_rw = 1; if (sdev->type == TYPE_DISK && - scsi_id->workarounds & SBP2_WORKAROUND_MODE_SENSE_8) + lu->workarounds & SBP2_WORKAROUND_MODE_SENSE_8) sdev->skip_ms_page_8 = 1; - if (scsi_id->workarounds & SBP2_WORKAROUND_FIX_CAPACITY) + if (lu->workarounds & SBP2_WORKAROUND_FIX_CAPACITY) sdev->fix_capacity = 1; return 0; } static void sbp2scsi_slave_destroy(struct scsi_device *sdev) { - ((struct scsi_id_instance_data *)sdev->host->hostdata[0])->sdev = NULL; + ((struct sbp2_lu *)sdev->host->hostdata[0])->sdev = NULL; return; } /* - * Called by scsi stack when something has really gone wrong. Usually - * called when a command has timed-out for some reason. + * Called by scsi stack when something has really gone wrong. + * Usually called when a command has timed-out for some reason. */ static int sbp2scsi_abort(struct scsi_cmnd *SCpnt) { - struct scsi_id_instance_data *scsi_id = - (struct scsi_id_instance_data *)SCpnt->device->host->hostdata[0]; - struct sbp2scsi_host_info *hi = scsi_id->hi; - struct sbp2_command_info *command; + struct sbp2_lu *lu = (struct sbp2_lu *)SCpnt->device->host->hostdata[0]; + struct sbp2_fwhost_info *hi = lu->hi; + struct sbp2_command_info *cmd; unsigned long flags; - SBP2_ERR("aborting sbp2 command"); + SBP2_INFO("aborting sbp2 command"); scsi_print_command(SCpnt); - if (sbp2util_node_is_available(scsi_id)) { - - /* - * Right now, just return any matching command structures - * to the free pool. - */ - spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags); - command = sbp2util_find_command_for_SCpnt(scsi_id, SCpnt); - if (command) { - SBP2_DEBUG("Found command to abort"); - pci_dma_sync_single_for_cpu(hi->host->pdev, - command->command_orb_dma, - sizeof(struct sbp2_command_orb), - PCI_DMA_TODEVICE); - pci_dma_sync_single_for_cpu(hi->host->pdev, - command->sge_dma, - sizeof(command->scatter_gather_element), - PCI_DMA_BIDIRECTIONAL); - sbp2util_mark_command_completed(scsi_id, command); - if (command->Current_SCpnt) { - command->Current_SCpnt->result = DID_ABORT << 16; - command->Current_done(command->Current_SCpnt); + if (sbp2util_node_is_available(lu)) { + sbp2_agent_reset(lu, 1); + + /* Return a matching command structure to the free pool. */ + spin_lock_irqsave(&lu->cmd_orb_lock, flags); + cmd = sbp2util_find_command_for_SCpnt(lu, SCpnt); + if (cmd) { + dma_sync_single_for_cpu(&hi->host->device, + cmd->command_orb_dma, + sizeof(struct sbp2_command_orb), + DMA_TO_DEVICE); + dma_sync_single_for_cpu(&hi->host->device, cmd->sge_dma, + sizeof(cmd->scatter_gather_element), + DMA_BIDIRECTIONAL); + sbp2util_mark_command_completed(lu, cmd); + if (cmd->Current_SCpnt) { + cmd->Current_SCpnt->result = DID_ABORT << 16; + cmd->Current_done(cmd->Current_SCpnt); } } - spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags); + spin_unlock_irqrestore(&lu->cmd_orb_lock, flags); - /* - * Initiate a fetch agent reset. - */ - sbp2_agent_reset(scsi_id, 1); - sbp2scsi_complete_all_commands(scsi_id, DID_BUS_BUSY); + sbp2scsi_complete_all_commands(lu, DID_BUS_BUSY); } return SUCCESS; @@ -2600,14 +2085,13 @@ static int sbp2scsi_abort(struct scsi_cmnd *SCpnt) */ static int sbp2scsi_reset(struct scsi_cmnd *SCpnt) { - struct scsi_id_instance_data *scsi_id = - (struct scsi_id_instance_data *)SCpnt->device->host->hostdata[0]; + struct sbp2_lu *lu = (struct sbp2_lu *)SCpnt->device->host->hostdata[0]; - SBP2_ERR("reset requested"); + SBP2_INFO("reset requested"); - if (sbp2util_node_is_available(scsi_id)) { - SBP2_ERR("Generating sbp2 fetch agent reset"); - sbp2_agent_reset(scsi_id, 1); + if (sbp2util_node_is_available(lu)) { + SBP2_INFO("generating sbp2 fetch agent reset"); + sbp2_agent_reset(lu, 1); } return SUCCESS; @@ -2618,90 +2102,50 @@ static ssize_t sbp2_sysfs_ieee1394_id_show(struct device *dev, char *buf) { struct scsi_device *sdev; - struct scsi_id_instance_data *scsi_id; - int lun; + struct sbp2_lu *lu; if (!(sdev = to_scsi_device(dev))) return 0; - if (!(scsi_id = (struct scsi_id_instance_data *)sdev->host->hostdata[0])) + if (!(lu = (struct sbp2_lu *)sdev->host->hostdata[0])) return 0; - lun = ORB_SET_LUN(scsi_id->sbp2_lun); - - return sprintf(buf, "%016Lx:%d:%d\n", (unsigned long long)scsi_id->ne->guid, - scsi_id->ud->id, lun); + return sprintf(buf, "%016Lx:%d:%d\n", (unsigned long long)lu->ne->guid, + lu->ud->id, ORB_SET_LUN(lu->lun)); } -static DEVICE_ATTR(ieee1394_id, S_IRUGO, sbp2_sysfs_ieee1394_id_show, NULL); - -static struct device_attribute *sbp2_sysfs_sdev_attrs[] = { - &dev_attr_ieee1394_id, - NULL -}; MODULE_AUTHOR("Ben Collins "); MODULE_DESCRIPTION("IEEE-1394 SBP-2 protocol driver"); MODULE_SUPPORTED_DEVICE(SBP2_DEVICE_NAME); MODULE_LICENSE("GPL"); -/* SCSI host template */ -static struct scsi_host_template scsi_driver_template = { - .module = THIS_MODULE, - .name = "SBP-2 IEEE-1394", - .proc_name = SBP2_DEVICE_NAME, - .queuecommand = sbp2scsi_queuecommand, - .eh_abort_handler = sbp2scsi_abort, - .eh_device_reset_handler = sbp2scsi_reset, - .slave_alloc = sbp2scsi_slave_alloc, - .slave_configure = sbp2scsi_slave_configure, - .slave_destroy = sbp2scsi_slave_destroy, - .this_id = -1, - .sg_tablesize = SG_ALL, - .use_clustering = ENABLE_CLUSTERING, - .cmd_per_lun = SBP2_MAX_CMDS, - .can_queue = SBP2_MAX_CMDS, - .emulated = 1, - .sdev_attrs = sbp2_sysfs_sdev_attrs, -}; - static int sbp2_module_init(void) { int ret; - SBP2_DEBUG_ENTER(); - - /* Module load debug option to force one command at a time (serializing I/O) */ - if (serialize_io) { - SBP2_INFO("Driver forced to serialize I/O (serialize_io=1)"); - SBP2_INFO("Try serialize_io=0 for better performance"); - scsi_driver_template.can_queue = 1; - scsi_driver_template.cmd_per_lun = 1; + if (sbp2_serialize_io) { + sbp2_shost_template.can_queue = 1; + sbp2_shost_template.cmd_per_lun = 1; } if (sbp2_default_workarounds & SBP2_WORKAROUND_128K_MAX_TRANS && - (max_sectors * 512) > (128 * 1024)) - max_sectors = 128 * 1024 / 512; - scsi_driver_template.max_sectors = max_sectors; + (sbp2_max_sectors * 512) > (128 * 1024)) + sbp2_max_sectors = 128 * 1024 / 512; + sbp2_shost_template.max_sectors = sbp2_max_sectors; - /* Register our high level driver with 1394 stack */ hpsb_register_highlevel(&sbp2_highlevel); - ret = hpsb_register_protocol(&sbp2_driver); if (ret) { SBP2_ERR("Failed to register protocol"); hpsb_unregister_highlevel(&sbp2_highlevel); return ret; } - return 0; } static void __exit sbp2_module_exit(void) { - SBP2_DEBUG_ENTER(); - hpsb_unregister_protocol(&sbp2_driver); - hpsb_unregister_highlevel(&sbp2_highlevel); } diff --git a/trunk/drivers/ieee1394/sbp2.h b/trunk/drivers/ieee1394/sbp2.h index abbe48e646c3..9ae842329bf3 100644 --- a/trunk/drivers/ieee1394/sbp2.h +++ b/trunk/drivers/ieee1394/sbp2.h @@ -25,25 +25,25 @@ #define SBP2_DEVICE_NAME "sbp2" /* - * SBP2 specific structures and defines + * SBP-2 specific definitions */ -#define ORB_DIRECTION_WRITE_TO_MEDIA 0x0 -#define ORB_DIRECTION_READ_FROM_MEDIA 0x1 -#define ORB_DIRECTION_NO_DATA_TRANSFER 0x2 - -#define ORB_SET_NULL_PTR(value) ((value & 0x1) << 31) -#define ORB_SET_NOTIFY(value) ((value & 0x1) << 31) -#define ORB_SET_RQ_FMT(value) ((value & 0x3) << 29) /* unused ? */ -#define ORB_SET_NODE_ID(value) ((value & 0xffff) << 16) -#define ORB_SET_STATUS_FIFO_HI(value, id) (value >> 32 | ORB_SET_NODE_ID(id)) -#define ORB_SET_STATUS_FIFO_LO(value) (value & 0xffffffff) -#define ORB_SET_DATA_SIZE(value) (value & 0xffff) -#define ORB_SET_PAGE_SIZE(value) ((value & 0x7) << 16) -#define ORB_SET_PAGE_TABLE_PRESENT(value) ((value & 0x1) << 19) -#define ORB_SET_MAX_PAYLOAD(value) ((value & 0xf) << 20) -#define ORB_SET_SPEED(value) ((value & 0x7) << 24) -#define ORB_SET_DIRECTION(value) ((value & 0x1) << 27) +#define ORB_DIRECTION_WRITE_TO_MEDIA 0x0 +#define ORB_DIRECTION_READ_FROM_MEDIA 0x1 +#define ORB_DIRECTION_NO_DATA_TRANSFER 0x2 + +#define ORB_SET_NULL_PTR(v) (((v) & 0x1) << 31) +#define ORB_SET_NOTIFY(v) (((v) & 0x1) << 31) +#define ORB_SET_RQ_FMT(v) (((v) & 0x3) << 29) +#define ORB_SET_NODE_ID(v) (((v) & 0xffff) << 16) +#define ORB_SET_STATUS_FIFO_HI(v, id) ((v) >> 32 | ORB_SET_NODE_ID(id)) +#define ORB_SET_STATUS_FIFO_LO(v) ((v) & 0xffffffff) +#define ORB_SET_DATA_SIZE(v) ((v) & 0xffff) +#define ORB_SET_PAGE_SIZE(v) (((v) & 0x7) << 16) +#define ORB_SET_PAGE_TABLE_PRESENT(v) (((v) & 0x1) << 19) +#define ORB_SET_MAX_PAYLOAD(v) (((v) & 0xf) << 20) +#define ORB_SET_SPEED(v) (((v) & 0x7) << 24) +#define ORB_SET_DIRECTION(v) (((v) & 0x1) << 27) struct sbp2_command_orb { u32 next_ORB_hi; @@ -64,12 +64,12 @@ struct sbp2_command_orb { #define SBP2_LOGICAL_UNIT_RESET 0xe #define SBP2_TARGET_RESET_REQUEST 0xf -#define ORB_SET_LUN(value) (value & 0xffff) -#define ORB_SET_FUNCTION(value) ((value & 0xf) << 16) -#define ORB_SET_RECONNECT(value) ((value & 0xf) << 20) -#define ORB_SET_EXCLUSIVE(value) ((value & 0x1) << 28) -#define ORB_SET_LOGIN_RESP_LENGTH(value) (value & 0xffff) -#define ORB_SET_PASSWD_LENGTH(value) ((value & 0xffff) << 16) +#define ORB_SET_LUN(v) ((v) & 0xffff) +#define ORB_SET_FUNCTION(v) (((v) & 0xf) << 16) +#define ORB_SET_RECONNECT(v) (((v) & 0xf) << 20) +#define ORB_SET_EXCLUSIVE(v) (((v) & 0x1) << 28) +#define ORB_SET_LOGIN_RESP_LENGTH(v) ((v) & 0xffff) +#define ORB_SET_PASSWD_LENGTH(v) (((v) & 0xffff) << 16) struct sbp2_login_orb { u32 password_hi; @@ -82,9 +82,9 @@ struct sbp2_login_orb { u32 status_fifo_lo; } __attribute__((packed)); -#define RESPONSE_GET_LOGIN_ID(value) (value & 0xffff) -#define RESPONSE_GET_LENGTH(value) ((value >> 16) & 0xffff) -#define RESPONSE_GET_RECONNECT_HOLD(value) (value & 0xffff) +#define RESPONSE_GET_LOGIN_ID(v) ((v) & 0xffff) +#define RESPONSE_GET_LENGTH(v) (((v) >> 16) & 0xffff) +#define RESPONSE_GET_RECONNECT_HOLD(v) ((v) & 0xffff) struct sbp2_login_response { u32 length_login_ID; @@ -93,9 +93,8 @@ struct sbp2_login_response { u32 reconnect_hold; } __attribute__((packed)); -#define ORB_SET_LOGIN_ID(value) (value & 0xffff) - -#define ORB_SET_QUERY_LOGINS_RESP_LENGTH(value) (value & 0xffff) +#define ORB_SET_LOGIN_ID(v) ((v) & 0xffff) +#define ORB_SET_QUERY_LOGINS_RESP_LENGTH(v) ((v) & 0xffff) struct sbp2_query_logins_orb { u32 reserved1; @@ -108,8 +107,8 @@ struct sbp2_query_logins_orb { u32 status_fifo_lo; } __attribute__((packed)); -#define RESPONSE_GET_MAX_LOGINS(value) (value & 0xffff) -#define RESPONSE_GET_ACTIVE_LOGINS(value) ((RESPONSE_GET_LENGTH(value) - 4) / 12) +#define RESPONSE_GET_MAX_LOGINS(v) ((v) & 0xffff) +#define RESPONSE_GET_ACTIVE_LOGINS(v) ((RESPONSE_GET_LENGTH((v)) - 4) / 12) struct sbp2_query_logins_response { u32 length_max_logins; @@ -140,8 +139,8 @@ struct sbp2_logout_orb { u32 status_fifo_lo; } __attribute__((packed)); -#define PAGE_TABLE_SET_SEGMENT_BASE_HI(value) (value & 0xffff) -#define PAGE_TABLE_SET_SEGMENT_LENGTH(value) ((value & 0xffff) << 16) +#define PAGE_TABLE_SET_SEGMENT_BASE_HI(v) ((v) & 0xffff) +#define PAGE_TABLE_SET_SEGMENT_LENGTH(v) (((v) & 0xffff) << 16) struct sbp2_unrestricted_page_table { u32 length_segment_base_hi; @@ -171,23 +170,14 @@ struct sbp2_unrestricted_page_table { #define SFMT_DEFERRED_ERROR 0x1 #define SFMT_VENDOR_DEPENDENT_STATUS 0x3 -#define SBP2_SCSI_STATUS_GOOD 0x0 -#define SBP2_SCSI_STATUS_CHECK_CONDITION 0x2 -#define SBP2_SCSI_STATUS_CONDITION_MET 0x4 -#define SBP2_SCSI_STATUS_BUSY 0x8 -#define SBP2_SCSI_STATUS_RESERVATION_CONFLICT 0x18 -#define SBP2_SCSI_STATUS_COMMAND_TERMINATED 0x22 - -#define SBP2_SCSI_STATUS_SELECTION_TIMEOUT 0xff - -#define STATUS_GET_SRC(value) (((value) >> 30) & 0x3) -#define STATUS_GET_RESP(value) (((value) >> 28) & 0x3) -#define STATUS_GET_LEN(value) (((value) >> 24) & 0x7) -#define STATUS_GET_SBP_STATUS(value) (((value) >> 16) & 0xff) -#define STATUS_GET_ORB_OFFSET_HI(value) ((value) & 0x0000ffff) -#define STATUS_TEST_DEAD(value) ((value) & 0x08000000) +#define STATUS_GET_SRC(v) (((v) >> 30) & 0x3) +#define STATUS_GET_RESP(v) (((v) >> 28) & 0x3) +#define STATUS_GET_LEN(v) (((v) >> 24) & 0x7) +#define STATUS_GET_SBP_STATUS(v) (((v) >> 16) & 0xff) +#define STATUS_GET_ORB_OFFSET_HI(v) ((v) & 0x0000ffff) +#define STATUS_TEST_DEAD(v) ((v) & 0x08000000) /* test 'resp' | 'dead' | 'sbp2_status' */ -#define STATUS_TEST_RDS(value) ((value) & 0x38ff0000) +#define STATUS_TEST_RDS(v) ((v) & 0x38ff0000) struct sbp2_status_block { u32 ORB_offset_hi_misc; @@ -195,66 +185,70 @@ struct sbp2_status_block { u8 command_set_dependent[24]; } __attribute__((packed)); + /* - * Miscellaneous SBP2 related config rom defines + * SBP2 related configuration ROM definitions */ -#define SBP2_UNIT_DIRECTORY_OFFSET_KEY 0xd1 -#define SBP2_CSR_OFFSET_KEY 0x54 -#define SBP2_UNIT_SPEC_ID_KEY 0x12 -#define SBP2_UNIT_SW_VERSION_KEY 0x13 -#define SBP2_COMMAND_SET_SPEC_ID_KEY 0x38 -#define SBP2_COMMAND_SET_KEY 0x39 -#define SBP2_UNIT_CHARACTERISTICS_KEY 0x3a -#define SBP2_DEVICE_TYPE_AND_LUN_KEY 0x14 -#define SBP2_FIRMWARE_REVISION_KEY 0x3c +#define SBP2_UNIT_DIRECTORY_OFFSET_KEY 0xd1 +#define SBP2_CSR_OFFSET_KEY 0x54 +#define SBP2_UNIT_SPEC_ID_KEY 0x12 +#define SBP2_UNIT_SW_VERSION_KEY 0x13 +#define SBP2_COMMAND_SET_SPEC_ID_KEY 0x38 +#define SBP2_COMMAND_SET_KEY 0x39 +#define SBP2_UNIT_CHARACTERISTICS_KEY 0x3a +#define SBP2_DEVICE_TYPE_AND_LUN_KEY 0x14 +#define SBP2_FIRMWARE_REVISION_KEY 0x3c -#define SBP2_AGENT_STATE_OFFSET 0x00ULL -#define SBP2_AGENT_RESET_OFFSET 0x04ULL -#define SBP2_ORB_POINTER_OFFSET 0x08ULL -#define SBP2_DOORBELL_OFFSET 0x10ULL -#define SBP2_UNSOLICITED_STATUS_ENABLE_OFFSET 0x14ULL -#define SBP2_UNSOLICITED_STATUS_VALUE 0xf +#define SBP2_AGENT_STATE_OFFSET 0x00ULL +#define SBP2_AGENT_RESET_OFFSET 0x04ULL +#define SBP2_ORB_POINTER_OFFSET 0x08ULL +#define SBP2_DOORBELL_OFFSET 0x10ULL +#define SBP2_UNSOLICITED_STATUS_ENABLE_OFFSET 0x14ULL +#define SBP2_UNSOLICITED_STATUS_VALUE 0xf -#define SBP2_BUSY_TIMEOUT_ADDRESS 0xfffff0000210ULL -#define SBP2_BUSY_TIMEOUT_VALUE 0xf +#define SBP2_BUSY_TIMEOUT_ADDRESS 0xfffff0000210ULL +/* biggest possible value for Single Phase Retry count is 0xf */ +#define SBP2_BUSY_TIMEOUT_VALUE 0xf -#define SBP2_AGENT_RESET_DATA 0xf +#define SBP2_AGENT_RESET_DATA 0xf -/* - * Unit spec id and sw version entry for SBP-2 devices - */ +#define SBP2_UNIT_SPEC_ID_ENTRY 0x0000609e +#define SBP2_SW_VERSION_ENTRY 0x00010483 -#define SBP2_UNIT_SPEC_ID_ENTRY 0x0000609e -#define SBP2_SW_VERSION_ENTRY 0x00010483 /* - * SCSI specific stuff + * SCSI specific definitions */ -#define SBP2_MAX_SG_ELEMENT_LENGTH 0xf000 -#define SBP2_MAX_SECTORS 255 /* Max sectors supported */ -#define SBP2_MAX_CMDS 8 /* This should be safe */ +#define SBP2_MAX_SG_ELEMENT_LENGTH 0xf000 +#define SBP2_MAX_SECTORS 255 +/* There is no real limitation of the queue depth (i.e. length of the linked + * list of command ORBs) at the target. The chosen depth is merely an + * implementation detail of the sbp2 driver. */ +#define SBP2_MAX_CMDS 8 + +#define SBP2_SCSI_STATUS_GOOD 0x0 +#define SBP2_SCSI_STATUS_CHECK_CONDITION 0x2 +#define SBP2_SCSI_STATUS_CONDITION_MET 0x4 +#define SBP2_SCSI_STATUS_BUSY 0x8 +#define SBP2_SCSI_STATUS_RESERVATION_CONFLICT 0x18 +#define SBP2_SCSI_STATUS_COMMAND_TERMINATED 0x22 +#define SBP2_SCSI_STATUS_SELECTION_TIMEOUT 0xff -/* Flags for detected oddities and brokeness */ -#define SBP2_WORKAROUND_128K_MAX_TRANS 0x1 -#define SBP2_WORKAROUND_INQUIRY_36 0x2 -#define SBP2_WORKAROUND_MODE_SENSE_8 0x4 -#define SBP2_WORKAROUND_FIX_CAPACITY 0x8 -#define SBP2_WORKAROUND_OVERRIDE 0x100 -/* This is the two dma types we use for cmd_dma below */ -enum cmd_dma_types { +/* + * Representations of commands and devices + */ + +enum sbp2_dma_types { CMD_DMA_NONE, CMD_DMA_PAGE, CMD_DMA_SINGLE }; -/* - * Encapsulates all the info necessary for an outstanding command. - */ +/* Per SCSI command */ struct sbp2_command_info { - struct list_head list; struct sbp2_command_orb command_orb ____cacheline_aligned; dma_addr_t command_orb_dma ____cacheline_aligned; @@ -262,25 +256,25 @@ struct sbp2_command_info { void (*Current_done)(struct scsi_cmnd *); /* Also need s/g structure for each sbp2 command */ - struct sbp2_unrestricted_page_table scatter_gather_element[SG_ALL] ____cacheline_aligned; + struct sbp2_unrestricted_page_table + scatter_gather_element[SG_ALL] ____cacheline_aligned; dma_addr_t sge_dma ____cacheline_aligned; void *sge_buffer; dma_addr_t cmd_dma; - enum cmd_dma_types dma_type; + enum sbp2_dma_types dma_type; unsigned long dma_size; - int dma_dir; - + enum dma_data_direction dma_dir; }; -struct sbp2scsi_host_info; +/* Per FireWire host */ +struct sbp2_fwhost_info { + struct hpsb_host *host; + struct list_head logical_units; +}; -/* - * Information needed on a per scsi id basis (one for each sbp2 device) - */ -struct scsi_id_instance_data { - /* - * Various sbp2 specific structures - */ +/* Per logical unit */ +struct sbp2_lu { + /* Operation request blocks */ struct sbp2_command_orb *last_orb; dma_addr_t last_orb_dma; struct sbp2_login_orb *login_orb; @@ -297,116 +291,59 @@ struct scsi_id_instance_data { dma_addr_t logout_orb_dma; struct sbp2_status_block status_block; - /* - * Stuff we need to know about the sbp2 device itself - */ - u64 sbp2_management_agent_addr; - u64 sbp2_command_block_agent_addr; + /* How to talk to the unit */ + u64 management_agent_addr; + u64 command_block_agent_addr; u32 speed_code; u32 max_payload_size; + u16 lun; - /* - * Values pulled from the device's unit directory - */ - u32 sbp2_command_set_spec_id; - u32 sbp2_command_set; - u32 sbp2_unit_characteristics; - u32 sbp2_lun; - u32 sbp2_firmware_revision; - - /* - * Address for the device to write status blocks to - */ + /* Address for the unit to write status blocks to */ u64 status_fifo_addr; - /* - * Waitqueue flag for logins, reconnects, logouts, query logins - */ - int access_complete:1; + /* Waitqueue flag for logins, reconnects, logouts, query logins */ + unsigned int access_complete:1; - /* - * Pool of command orbs, so we can have more than overlapped command per id - */ - spinlock_t sbp2_command_orb_lock; - struct list_head sbp2_command_orb_inuse; - struct list_head sbp2_command_orb_completed; + /* Pool of command ORBs for this logical unit */ + spinlock_t cmd_orb_lock; + struct list_head cmd_orb_inuse; + struct list_head cmd_orb_completed; - struct list_head scsi_list; + /* Backlink to FireWire host; list of units attached to the host */ + struct sbp2_fwhost_info *hi; + struct list_head lu_list; - /* Node entry, as retrieved from NodeMgr entries */ + /* IEEE 1394 core's device representations */ struct node_entry *ne; struct unit_directory *ud; - /* A backlink to our host_info */ - struct sbp2scsi_host_info *hi; - - /* SCSI related pointers */ + /* SCSI core's device representations */ struct scsi_device *sdev; - struct Scsi_Host *scsi_host; + struct Scsi_Host *shost; /* Device specific workarounds/brokeness */ unsigned workarounds; + /* Connection state */ atomic_t state; + + /* For deferred requests to the fetch agent */ struct work_struct protocol_work; }; -/* For use in scsi_id_instance_data.state */ +/* For use in sbp2_lu.state */ enum sbp2lu_state_types { SBP2LU_STATE_RUNNING, /* all normal */ SBP2LU_STATE_IN_RESET, /* between bus reset and reconnect */ SBP2LU_STATE_IN_SHUTDOWN /* when sbp2_remove was called */ }; -/* Sbp2 host data structure (one per IEEE1394 host) */ -struct sbp2scsi_host_info { - struct hpsb_host *host; /* IEEE1394 host */ - struct list_head scsi_ids; /* List of scsi ids on this host */ -}; - -/* - * Function prototypes - */ - -/* - * Various utility prototypes - */ -static int sbp2util_create_command_orb_pool(struct scsi_id_instance_data *scsi_id); -static void sbp2util_remove_command_orb_pool(struct scsi_id_instance_data *scsi_id); -static struct sbp2_command_info *sbp2util_find_command_for_orb(struct scsi_id_instance_data *scsi_id, dma_addr_t orb); -static struct sbp2_command_info *sbp2util_find_command_for_SCpnt(struct scsi_id_instance_data *scsi_id, void *SCpnt); -static struct sbp2_command_info *sbp2util_allocate_command_orb(struct scsi_id_instance_data *scsi_id, - struct scsi_cmnd *Current_SCpnt, - void (*Current_done)(struct scsi_cmnd *)); -static void sbp2util_mark_command_completed(struct scsi_id_instance_data *scsi_id, - struct sbp2_command_info *command); - - -static int sbp2_start_device(struct scsi_id_instance_data *scsi_id); -static void sbp2_remove_device(struct scsi_id_instance_data *scsi_id); - -#ifdef CONFIG_IEEE1394_SBP2_PHYS_DMA -static int sbp2_handle_physdma_write(struct hpsb_host *host, int nodeid, int destid, quadlet_t *data, - u64 addr, size_t length, u16 flags); -static int sbp2_handle_physdma_read(struct hpsb_host *host, int nodeid, quadlet_t *data, - u64 addr, size_t length, u16 flags); -#endif - -/* - * SBP-2 protocol related prototypes - */ -static int sbp2_query_logins(struct scsi_id_instance_data *scsi_id); -static int sbp2_login_device(struct scsi_id_instance_data *scsi_id); -static int sbp2_reconnect_device(struct scsi_id_instance_data *scsi_id); -static int sbp2_logout_device(struct scsi_id_instance_data *scsi_id); -static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int destid, - quadlet_t *data, u64 addr, size_t length, u16 flags); -static int sbp2_agent_reset(struct scsi_id_instance_data *scsi_id, int wait); -static unsigned int sbp2_status_to_sense_data(unchar *sbp2_status, - unchar *sense_data); -static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id, - struct unit_directory *ud); -static int sbp2_set_busy_timeout(struct scsi_id_instance_data *scsi_id); -static int sbp2_max_speed_and_size(struct scsi_id_instance_data *scsi_id); +/* For use in sbp2_lu.workarounds and in the corresponding + * module load parameter */ +#define SBP2_WORKAROUND_128K_MAX_TRANS 0x1 +#define SBP2_WORKAROUND_INQUIRY_36 0x2 +#define SBP2_WORKAROUND_MODE_SENSE_8 0x4 +#define SBP2_WORKAROUND_FIX_CAPACITY 0x8 +#define SBP2_WORKAROUND_OVERRIDE 0x100 #endif /* SBP2_H */ diff --git a/trunk/drivers/ieee1394/video1394.c b/trunk/drivers/ieee1394/video1394.c index 9bc65059cc69..598b19fc5989 100644 --- a/trunk/drivers/ieee1394/video1394.c +++ b/trunk/drivers/ieee1394/video1394.c @@ -714,8 +714,8 @@ static inline unsigned video1394_buffer_state(struct dma_iso_ctx *d, return ret; } -static int __video1394_ioctl(struct file *file, - unsigned int cmd, unsigned long arg) +static long video1394_ioctl(struct file *file, + unsigned int cmd, unsigned long arg) { struct file_ctx *ctx = (struct file_ctx *)file->private_data; struct ti_ohci *ohci = ctx->ohci; @@ -884,13 +884,14 @@ static int __video1394_ioctl(struct file *file, struct dma_iso_ctx *d; int next_prg; - if (copy_from_user(&v, argp, sizeof(v))) + if (unlikely(copy_from_user(&v, argp, sizeof(v)))) return -EFAULT; d = find_ctx(&ctx->context_list, OHCI_ISO_RECEIVE, v.channel); - if (d == NULL) return -EFAULT; + if (unlikely(d == NULL)) + return -EFAULT; - if ((v.buffer<0) || (v.buffer>=d->num_desc - 1)) { + if (unlikely((v.buffer<0) || (v.buffer>=d->num_desc - 1))) { PRINT(KERN_ERR, ohci->host->id, "Buffer %d out of range",v.buffer); return -EINVAL; @@ -898,7 +899,7 @@ static int __video1394_ioctl(struct file *file, spin_lock_irqsave(&d->lock,flags); - if (d->buffer_status[v.buffer]==VIDEO1394_BUFFER_QUEUED) { + if (unlikely(d->buffer_status[v.buffer]==VIDEO1394_BUFFER_QUEUED)) { PRINT(KERN_ERR, ohci->host->id, "Buffer %d is already used",v.buffer); spin_unlock_irqrestore(&d->lock,flags); @@ -949,13 +950,14 @@ static int __video1394_ioctl(struct file *file, struct dma_iso_ctx *d; int i = 0; - if (copy_from_user(&v, argp, sizeof(v))) + if (unlikely(copy_from_user(&v, argp, sizeof(v)))) return -EFAULT; d = find_ctx(&ctx->context_list, OHCI_ISO_RECEIVE, v.channel); - if (d == NULL) return -EFAULT; + if (unlikely(d == NULL)) + return -EFAULT; - if ((v.buffer<0) || (v.buffer>d->num_desc - 1)) { + if (unlikely((v.buffer<0) || (v.buffer>d->num_desc - 1))) { PRINT(KERN_ERR, ohci->host->id, "Buffer %d out of range",v.buffer); return -EINVAL; @@ -1008,7 +1010,7 @@ static int __video1394_ioctl(struct file *file, spin_unlock_irqrestore(&d->lock, flags); v.buffer=i; - if (copy_to_user(argp, &v, sizeof(v))) + if (unlikely(copy_to_user(argp, &v, sizeof(v)))) return -EFAULT; return 0; @@ -1156,15 +1158,6 @@ static int __video1394_ioctl(struct file *file, } } -static long video1394_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - int err; - lock_kernel(); - err = __video1394_ioctl(file, cmd, arg); - unlock_kernel(); - return err; -} - /* * This maps the vmalloced and reserved buffer to user space. * @@ -1177,17 +1170,14 @@ static long video1394_ioctl(struct file *file, unsigned int cmd, unsigned long a static int video1394_mmap(struct file *file, struct vm_area_struct *vma) { struct file_ctx *ctx = (struct file_ctx *)file->private_data; - int res = -EINVAL; - lock_kernel(); if (ctx->current_ctx == NULL) { PRINT(KERN_ERR, ctx->ohci->host->id, "Current iso context not set"); - } else - res = dma_region_mmap(&ctx->current_ctx->dma, file, vma); - unlock_kernel(); + return -EINVAL; + } - return res; + return dma_region_mmap(&ctx->current_ctx->dma, file, vma); } static unsigned int video1394_poll(struct file *file, poll_table *pt) @@ -1198,14 +1188,12 @@ static unsigned int video1394_poll(struct file *file, poll_table *pt) struct dma_iso_ctx *d; int i; - lock_kernel(); ctx = file->private_data; d = ctx->current_ctx; if (d == NULL) { PRINT(KERN_ERR, ctx->ohci->host->id, "Current iso context not set"); - mask = POLLERR; - goto done; + return POLLERR; } poll_wait(file, &d->waitq, pt); @@ -1218,8 +1206,6 @@ static unsigned int video1394_poll(struct file *file, poll_table *pt) } } spin_unlock_irqrestore(&d->lock, flags); -done: - unlock_kernel(); return mask; } @@ -1255,7 +1241,6 @@ static int video1394_release(struct inode *inode, struct file *file) struct list_head *lh, *next; u64 mask; - lock_kernel(); list_for_each_safe(lh, next, &ctx->context_list) { struct dma_iso_ctx *d; d = list_entry(lh, struct dma_iso_ctx, link); @@ -1276,7 +1261,6 @@ static int video1394_release(struct inode *inode, struct file *file) kfree(ctx); file->private_data = NULL; - unlock_kernel(); return 0; } @@ -1324,12 +1308,8 @@ static struct ieee1394_device_id video1394_id_table[] = { MODULE_DEVICE_TABLE(ieee1394, video1394_id_table); static struct hpsb_protocol_driver video1394_driver = { - .name = "1394 Digital Camera Driver", + .name = VIDEO1394_DRIVER_NAME, .id_table = video1394_id_table, - .driver = { - .name = VIDEO1394_DRIVER_NAME, - .bus = &ieee1394_bus_type, - }, }; diff --git a/trunk/drivers/infiniband/core/addr.c b/trunk/drivers/infiniband/core/addr.c index 7767a11b6890..af939796750d 100644 --- a/trunk/drivers/infiniband/core/addr.c +++ b/trunk/drivers/infiniband/core/addr.c @@ -55,11 +55,11 @@ struct addr_req { int status; }; -static void process_req(void *data); +static void process_req(struct work_struct *work); static DEFINE_MUTEX(lock); static LIST_HEAD(req_list); -static DECLARE_WORK(work, process_req, NULL); +static DECLARE_DELAYED_WORK(work, process_req); static struct workqueue_struct *addr_wq; void rdma_addr_register_client(struct rdma_addr_client *client) @@ -215,7 +215,7 @@ static int addr_resolve_remote(struct sockaddr_in *src_in, return ret; } -static void process_req(void *data) +static void process_req(struct work_struct *work) { struct addr_req *req, *temp_req; struct sockaddr_in *src_in, *dst_in; diff --git a/trunk/drivers/infiniband/core/cache.c b/trunk/drivers/infiniband/core/cache.c index 20e9f64e67a6..98272fbbfb31 100644 --- a/trunk/drivers/infiniband/core/cache.c +++ b/trunk/drivers/infiniband/core/cache.c @@ -285,9 +285,10 @@ static void ib_cache_update(struct ib_device *device, kfree(tprops); } -static void ib_cache_task(void *work_ptr) +static void ib_cache_task(struct work_struct *_work) { - struct ib_update_work *work = work_ptr; + struct ib_update_work *work = + container_of(_work, struct ib_update_work, work); ib_cache_update(work->device, work->port_num); kfree(work); @@ -306,7 +307,7 @@ static void ib_cache_event(struct ib_event_handler *handler, event->event == IB_EVENT_CLIENT_REREGISTER) { work = kmalloc(sizeof *work, GFP_ATOMIC); if (work) { - INIT_WORK(&work->work, ib_cache_task, work); + INIT_WORK(&work->work, ib_cache_task); work->device = event->device; work->port_num = event->element.port_num; schedule_work(&work->work); diff --git a/trunk/drivers/infiniband/core/cm.c b/trunk/drivers/infiniband/core/cm.c index e5dc4530808a..79c937bf6962 100644 --- a/trunk/drivers/infiniband/core/cm.c +++ b/trunk/drivers/infiniband/core/cm.c @@ -101,7 +101,7 @@ struct cm_av { }; struct cm_work { - struct work_struct work; + struct delayed_work work; struct list_head list; struct cm_port *port; struct ib_mad_recv_wc *mad_recv_wc; /* Received MADs */ @@ -161,7 +161,7 @@ struct cm_id_private { atomic_t work_count; }; -static void cm_work_handler(void *data); +static void cm_work_handler(struct work_struct *work); static inline void cm_deref_id(struct cm_id_private *cm_id_priv) { @@ -668,8 +668,7 @@ static struct cm_timewait_info * cm_create_timewait_info(__be32 local_id) return ERR_PTR(-ENOMEM); timewait_info->work.local_id = local_id; - INIT_WORK(&timewait_info->work.work, cm_work_handler, - &timewait_info->work); + INIT_DELAYED_WORK(&timewait_info->work.work, cm_work_handler); timewait_info->work.cm_event.event = IB_CM_TIMEWAIT_EXIT; return timewait_info; } @@ -2995,9 +2994,9 @@ static void cm_send_handler(struct ib_mad_agent *mad_agent, } } -static void cm_work_handler(void *data) +static void cm_work_handler(struct work_struct *_work) { - struct cm_work *work = data; + struct cm_work *work = container_of(_work, struct cm_work, work.work); int ret; switch (work->cm_event.event) { @@ -3087,12 +3086,12 @@ static int cm_establish(struct ib_cm_id *cm_id) * we need to find the cm_id once we're in the context of the * worker thread, rather than holding a reference on it. */ - INIT_WORK(&work->work, cm_work_handler, work); + INIT_DELAYED_WORK(&work->work, cm_work_handler); work->local_id = cm_id->local_id; work->remote_id = cm_id->remote_id; work->mad_recv_wc = NULL; work->cm_event.event = IB_CM_USER_ESTABLISHED; - queue_work(cm.wq, &work->work); + queue_delayed_work(cm.wq, &work->work, 0); out: return ret; } @@ -3191,11 +3190,11 @@ static void cm_recv_handler(struct ib_mad_agent *mad_agent, return; } - INIT_WORK(&work->work, cm_work_handler, work); + INIT_DELAYED_WORK(&work->work, cm_work_handler); work->cm_event.event = event; work->mad_recv_wc = mad_recv_wc; work->port = (struct cm_port *)mad_agent->context; - queue_work(cm.wq, &work->work); + queue_delayed_work(cm.wq, &work->work, 0); } static int cm_init_qp_init_attr(struct cm_id_private *cm_id_priv, diff --git a/trunk/drivers/infiniband/core/cma.c b/trunk/drivers/infiniband/core/cma.c index cf48f2697434..985a6b564d8f 100644 --- a/trunk/drivers/infiniband/core/cma.c +++ b/trunk/drivers/infiniband/core/cma.c @@ -1340,9 +1340,9 @@ static int cma_query_ib_route(struct rdma_id_private *id_priv, int timeout_ms, return (id_priv->query_id < 0) ? id_priv->query_id : 0; } -static void cma_work_handler(void *data) +static void cma_work_handler(struct work_struct *_work) { - struct cma_work *work = data; + struct cma_work *work = container_of(_work, struct cma_work, work); struct rdma_id_private *id_priv = work->id; int destroy = 0; @@ -1373,7 +1373,7 @@ static int cma_resolve_ib_route(struct rdma_id_private *id_priv, int timeout_ms) return -ENOMEM; work->id = id_priv; - INIT_WORK(&work->work, cma_work_handler, work); + INIT_WORK(&work->work, cma_work_handler); work->old_state = CMA_ROUTE_QUERY; work->new_state = CMA_ROUTE_RESOLVED; work->event.event = RDMA_CM_EVENT_ROUTE_RESOLVED; @@ -1430,7 +1430,7 @@ static int cma_resolve_iw_route(struct rdma_id_private *id_priv, int timeout_ms) return -ENOMEM; work->id = id_priv; - INIT_WORK(&work->work, cma_work_handler, work); + INIT_WORK(&work->work, cma_work_handler); work->old_state = CMA_ROUTE_QUERY; work->new_state = CMA_ROUTE_RESOLVED; work->event.event = RDMA_CM_EVENT_ROUTE_RESOLVED; @@ -1583,7 +1583,7 @@ static int cma_resolve_loopback(struct rdma_id_private *id_priv) } work->id = id_priv; - INIT_WORK(&work->work, cma_work_handler, work); + INIT_WORK(&work->work, cma_work_handler); work->old_state = CMA_ADDR_QUERY; work->new_state = CMA_ADDR_RESOLVED; work->event.event = RDMA_CM_EVENT_ADDR_RESOLVED; diff --git a/trunk/drivers/infiniband/core/iwcm.c b/trunk/drivers/infiniband/core/iwcm.c index cf797d7aea09..1039ad57d53b 100644 --- a/trunk/drivers/infiniband/core/iwcm.c +++ b/trunk/drivers/infiniband/core/iwcm.c @@ -828,9 +828,9 @@ static int process_event(struct iwcm_id_private *cm_id_priv, * thread asleep on the destroy_comp list vs. an object destroyed * here synchronously when the last reference is removed. */ -static void cm_work_handler(void *arg) +static void cm_work_handler(struct work_struct *_work) { - struct iwcm_work *work = arg; + struct iwcm_work *work = container_of(_work, struct iwcm_work, work); struct iw_cm_event levent; struct iwcm_id_private *cm_id_priv = work->cm_id; unsigned long flags; @@ -900,7 +900,7 @@ static int cm_event_handler(struct iw_cm_id *cm_id, goto out; } - INIT_WORK(&work->work, cm_work_handler, work); + INIT_WORK(&work->work, cm_work_handler); work->cm_id = cm_id_priv; work->event = *iw_event; diff --git a/trunk/drivers/infiniband/core/mad.c b/trunk/drivers/infiniband/core/mad.c index 3f9c16232c4d..15f38d94b3a8 100644 --- a/trunk/drivers/infiniband/core/mad.c +++ b/trunk/drivers/infiniband/core/mad.c @@ -65,8 +65,8 @@ static struct ib_mad_agent_private *find_mad_agent( static int ib_mad_post_receive_mads(struct ib_mad_qp_info *qp_info, struct ib_mad_private *mad); static void cancel_mads(struct ib_mad_agent_private *mad_agent_priv); -static void timeout_sends(void *data); -static void local_completions(void *data); +static void timeout_sends(struct work_struct *work); +static void local_completions(struct work_struct *work); static int add_nonoui_reg_req(struct ib_mad_reg_req *mad_reg_req, struct ib_mad_agent_private *agent_priv, u8 mgmt_class); @@ -356,10 +356,9 @@ struct ib_mad_agent *ib_register_mad_agent(struct ib_device *device, INIT_LIST_HEAD(&mad_agent_priv->wait_list); INIT_LIST_HEAD(&mad_agent_priv->done_list); INIT_LIST_HEAD(&mad_agent_priv->rmpp_list); - INIT_WORK(&mad_agent_priv->timed_work, timeout_sends, mad_agent_priv); + INIT_DELAYED_WORK(&mad_agent_priv->timed_work, timeout_sends); INIT_LIST_HEAD(&mad_agent_priv->local_list); - INIT_WORK(&mad_agent_priv->local_work, local_completions, - mad_agent_priv); + INIT_WORK(&mad_agent_priv->local_work, local_completions); atomic_set(&mad_agent_priv->refcount, 1); init_completion(&mad_agent_priv->comp); @@ -2198,12 +2197,12 @@ static void mad_error_handler(struct ib_mad_port_private *port_priv, /* * IB MAD completion callback */ -static void ib_mad_completion_handler(void *data) +static void ib_mad_completion_handler(struct work_struct *work) { struct ib_mad_port_private *port_priv; struct ib_wc wc; - port_priv = (struct ib_mad_port_private *)data; + port_priv = container_of(work, struct ib_mad_port_private, work); ib_req_notify_cq(port_priv->cq, IB_CQ_NEXT_COMP); while (ib_poll_cq(port_priv->cq, 1, &wc) == 1) { @@ -2324,7 +2323,7 @@ void ib_cancel_mad(struct ib_mad_agent *mad_agent, } EXPORT_SYMBOL(ib_cancel_mad); -static void local_completions(void *data) +static void local_completions(struct work_struct *work) { struct ib_mad_agent_private *mad_agent_priv; struct ib_mad_local_private *local; @@ -2334,7 +2333,8 @@ static void local_completions(void *data) struct ib_wc wc; struct ib_mad_send_wc mad_send_wc; - mad_agent_priv = (struct ib_mad_agent_private *)data; + mad_agent_priv = + container_of(work, struct ib_mad_agent_private, local_work); spin_lock_irqsave(&mad_agent_priv->lock, flags); while (!list_empty(&mad_agent_priv->local_list)) { @@ -2434,14 +2434,15 @@ static int retry_send(struct ib_mad_send_wr_private *mad_send_wr) return ret; } -static void timeout_sends(void *data) +static void timeout_sends(struct work_struct *work) { struct ib_mad_agent_private *mad_agent_priv; struct ib_mad_send_wr_private *mad_send_wr; struct ib_mad_send_wc mad_send_wc; unsigned long flags, delay; - mad_agent_priv = (struct ib_mad_agent_private *)data; + mad_agent_priv = container_of(work, struct ib_mad_agent_private, + timed_work.work); mad_send_wc.vendor_err = 0; spin_lock_irqsave(&mad_agent_priv->lock, flags); @@ -2799,7 +2800,7 @@ static int ib_mad_port_open(struct ib_device *device, ret = -ENOMEM; goto error8; } - INIT_WORK(&port_priv->work, ib_mad_completion_handler, port_priv); + INIT_WORK(&port_priv->work, ib_mad_completion_handler); spin_lock_irqsave(&ib_mad_port_list_lock, flags); list_add_tail(&port_priv->port_list, &ib_mad_port_list); diff --git a/trunk/drivers/infiniband/core/mad_priv.h b/trunk/drivers/infiniband/core/mad_priv.h index d06b59083f6e..d5548e73e068 100644 --- a/trunk/drivers/infiniband/core/mad_priv.h +++ b/trunk/drivers/infiniband/core/mad_priv.h @@ -102,7 +102,7 @@ struct ib_mad_agent_private { struct list_head send_list; struct list_head wait_list; struct list_head done_list; - struct work_struct timed_work; + struct delayed_work timed_work; unsigned long timeout; struct list_head local_list; struct work_struct local_work; diff --git a/trunk/drivers/infiniband/core/mad_rmpp.c b/trunk/drivers/infiniband/core/mad_rmpp.c index 1ef79d015a1e..3663fd7022be 100644 --- a/trunk/drivers/infiniband/core/mad_rmpp.c +++ b/trunk/drivers/infiniband/core/mad_rmpp.c @@ -45,8 +45,8 @@ enum rmpp_state { struct mad_rmpp_recv { struct ib_mad_agent_private *agent; struct list_head list; - struct work_struct timeout_work; - struct work_struct cleanup_work; + struct delayed_work timeout_work; + struct delayed_work cleanup_work; struct completion comp; enum rmpp_state state; spinlock_t lock; @@ -233,9 +233,10 @@ static void nack_recv(struct ib_mad_agent_private *agent, } } -static void recv_timeout_handler(void *data) +static void recv_timeout_handler(struct work_struct *work) { - struct mad_rmpp_recv *rmpp_recv = data; + struct mad_rmpp_recv *rmpp_recv = + container_of(work, struct mad_rmpp_recv, timeout_work.work); struct ib_mad_recv_wc *rmpp_wc; unsigned long flags; @@ -254,9 +255,10 @@ static void recv_timeout_handler(void *data) ib_free_recv_mad(rmpp_wc); } -static void recv_cleanup_handler(void *data) +static void recv_cleanup_handler(struct work_struct *work) { - struct mad_rmpp_recv *rmpp_recv = data; + struct mad_rmpp_recv *rmpp_recv = + container_of(work, struct mad_rmpp_recv, cleanup_work.work); unsigned long flags; spin_lock_irqsave(&rmpp_recv->agent->lock, flags); @@ -285,8 +287,8 @@ create_rmpp_recv(struct ib_mad_agent_private *agent, rmpp_recv->agent = agent; init_completion(&rmpp_recv->comp); - INIT_WORK(&rmpp_recv->timeout_work, recv_timeout_handler, rmpp_recv); - INIT_WORK(&rmpp_recv->cleanup_work, recv_cleanup_handler, rmpp_recv); + INIT_DELAYED_WORK(&rmpp_recv->timeout_work, recv_timeout_handler); + INIT_DELAYED_WORK(&rmpp_recv->cleanup_work, recv_cleanup_handler); spin_lock_init(&rmpp_recv->lock); rmpp_recv->state = RMPP_STATE_ACTIVE; atomic_set(&rmpp_recv->refcount, 1); diff --git a/trunk/drivers/infiniband/core/sa_query.c b/trunk/drivers/infiniband/core/sa_query.c index 1706d3c7e95e..e45afba75341 100644 --- a/trunk/drivers/infiniband/core/sa_query.c +++ b/trunk/drivers/infiniband/core/sa_query.c @@ -360,9 +360,10 @@ static void free_sm_ah(struct kref *kref) kfree(sm_ah); } -static void update_sm_ah(void *port_ptr) +static void update_sm_ah(struct work_struct *work) { - struct ib_sa_port *port = port_ptr; + struct ib_sa_port *port = + container_of(work, struct ib_sa_port, update_task); struct ib_sa_sm_ah *new_ah, *old_ah; struct ib_port_attr port_attr; struct ib_ah_attr ah_attr; @@ -992,8 +993,7 @@ static void ib_sa_add_one(struct ib_device *device) if (IS_ERR(sa_dev->port[i].agent)) goto err; - INIT_WORK(&sa_dev->port[i].update_task, - update_sm_ah, &sa_dev->port[i]); + INIT_WORK(&sa_dev->port[i].update_task, update_sm_ah); } ib_set_client_data(device, &sa_client, sa_dev); @@ -1010,7 +1010,7 @@ static void ib_sa_add_one(struct ib_device *device) goto err; for (i = 0; i <= e - s; ++i) - update_sm_ah(&sa_dev->port[i]); + update_sm_ah(&sa_dev->port[i].update_task); return; diff --git a/trunk/drivers/infiniband/core/uverbs_main.c b/trunk/drivers/infiniband/core/uverbs_main.c index 4e16314e8e6d..a617ca7b6923 100644 --- a/trunk/drivers/infiniband/core/uverbs_main.c +++ b/trunk/drivers/infiniband/core/uverbs_main.c @@ -534,9 +534,9 @@ struct file *ib_uverbs_alloc_event_file(struct ib_uverbs_file *uverbs_file, * module reference. */ filp->f_op = fops_get(&uverbs_event_fops); - filp->f_vfsmnt = mntget(uverbs_event_mnt); - filp->f_dentry = dget(uverbs_event_mnt->mnt_root); - filp->f_mapping = filp->f_dentry->d_inode->i_mapping; + filp->f_path.mnt = mntget(uverbs_event_mnt); + filp->f_path.dentry = dget(uverbs_event_mnt->mnt_root); + filp->f_mapping = filp->f_path.dentry->d_inode->i_mapping; filp->f_flags = O_RDONLY; filp->f_mode = FMODE_READ; filp->private_data = ev_file; diff --git a/trunk/drivers/infiniband/core/uverbs_mem.c b/trunk/drivers/infiniband/core/uverbs_mem.c index efe147dbeb42..db12cc0841df 100644 --- a/trunk/drivers/infiniband/core/uverbs_mem.c +++ b/trunk/drivers/infiniband/core/uverbs_mem.c @@ -179,9 +179,10 @@ void ib_umem_release(struct ib_device *dev, struct ib_umem *umem) up_write(¤t->mm->mmap_sem); } -static void ib_umem_account(void *work_ptr) +static void ib_umem_account(struct work_struct *_work) { - struct ib_umem_account_work *work = work_ptr; + struct ib_umem_account_work *work = + container_of(_work, struct ib_umem_account_work, work); down_write(&work->mm->mmap_sem); work->mm->locked_vm -= work->diff; @@ -216,7 +217,7 @@ void ib_umem_release_on_close(struct ib_device *dev, struct ib_umem *umem) return; } - INIT_WORK(&work->work, ib_umem_account, work); + INIT_WORK(&work->work, ib_umem_account); work->mm = mm; work->diff = PAGE_ALIGN(umem->length + umem->offset) >> PAGE_SHIFT; diff --git a/trunk/drivers/infiniband/hw/amso1100/c2_vq.c b/trunk/drivers/infiniband/hw/amso1100/c2_vq.c index 40caeb5f41b4..36620a22413c 100644 --- a/trunk/drivers/infiniband/hw/amso1100/c2_vq.c +++ b/trunk/drivers/infiniband/hw/amso1100/c2_vq.c @@ -164,7 +164,7 @@ void vq_req_put(struct c2_dev *c2dev, struct c2_vq_req *r) */ void *vq_repbuf_alloc(struct c2_dev *c2dev) { - return kmem_cache_alloc(c2dev->host_msg_cache, SLAB_ATOMIC); + return kmem_cache_alloc(c2dev->host_msg_cache, GFP_ATOMIC); } /* diff --git a/trunk/drivers/infiniband/hw/ehca/ehca_av.c b/trunk/drivers/infiniband/hw/ehca/ehca_av.c index 214e2fdddeef..0d6e2c4bb245 100644 --- a/trunk/drivers/infiniband/hw/ehca/ehca_av.c +++ b/trunk/drivers/infiniband/hw/ehca/ehca_av.c @@ -57,7 +57,7 @@ struct ib_ah *ehca_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr) struct ehca_shca *shca = container_of(pd->device, struct ehca_shca, ib_device); - av = kmem_cache_alloc(av_cache, SLAB_KERNEL); + av = kmem_cache_alloc(av_cache, GFP_KERNEL); if (!av) { ehca_err(pd->device, "Out of memory pd=%p ah_attr=%p", pd, ah_attr); diff --git a/trunk/drivers/infiniband/hw/ehca/ehca_cq.c b/trunk/drivers/infiniband/hw/ehca/ehca_cq.c index 458fe19648a1..93995b658d94 100644 --- a/trunk/drivers/infiniband/hw/ehca/ehca_cq.c +++ b/trunk/drivers/infiniband/hw/ehca/ehca_cq.c @@ -134,7 +134,7 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, if (cqe >= 0xFFFFFFFF - 64 - additional_cqe) return ERR_PTR(-EINVAL); - my_cq = kmem_cache_alloc(cq_cache, SLAB_KERNEL); + my_cq = kmem_cache_alloc(cq_cache, GFP_KERNEL); if (!my_cq) { ehca_err(device, "Out of memory for ehca_cq struct device=%p", device); diff --git a/trunk/drivers/infiniband/hw/ehca/ehca_main.c b/trunk/drivers/infiniband/hw/ehca/ehca_main.c index 3d1c1c535038..cc47e4c13a18 100644 --- a/trunk/drivers/infiniband/hw/ehca/ehca_main.c +++ b/trunk/drivers/infiniband/hw/ehca/ehca_main.c @@ -108,7 +108,7 @@ static struct kmem_cache *ctblk_cache = NULL; void *ehca_alloc_fw_ctrlblock(void) { - void *ret = kmem_cache_zalloc(ctblk_cache, SLAB_KERNEL); + void *ret = kmem_cache_zalloc(ctblk_cache, GFP_KERNEL); if (!ret) ehca_gen_err("Out of memory for ctblk"); return ret; diff --git a/trunk/drivers/infiniband/hw/ehca/ehca_mrmw.c b/trunk/drivers/infiniband/hw/ehca/ehca_mrmw.c index abce676c0ae0..0a5e2214cc5f 100644 --- a/trunk/drivers/infiniband/hw/ehca/ehca_mrmw.c +++ b/trunk/drivers/infiniband/hw/ehca/ehca_mrmw.c @@ -53,7 +53,7 @@ static struct ehca_mr *ehca_mr_new(void) { struct ehca_mr *me; - me = kmem_cache_alloc(mr_cache, SLAB_KERNEL); + me = kmem_cache_alloc(mr_cache, GFP_KERNEL); if (me) { memset(me, 0, sizeof(struct ehca_mr)); spin_lock_init(&me->mrlock); @@ -72,7 +72,7 @@ static struct ehca_mw *ehca_mw_new(void) { struct ehca_mw *me; - me = kmem_cache_alloc(mw_cache, SLAB_KERNEL); + me = kmem_cache_alloc(mw_cache, GFP_KERNEL); if (me) { memset(me, 0, sizeof(struct ehca_mw)); spin_lock_init(&me->mwlock); diff --git a/trunk/drivers/infiniband/hw/ehca/ehca_pd.c b/trunk/drivers/infiniband/hw/ehca/ehca_pd.c index 2c3cdc6f7b39..d5345e5b3cd6 100644 --- a/trunk/drivers/infiniband/hw/ehca/ehca_pd.c +++ b/trunk/drivers/infiniband/hw/ehca/ehca_pd.c @@ -50,7 +50,7 @@ struct ib_pd *ehca_alloc_pd(struct ib_device *device, { struct ehca_pd *pd; - pd = kmem_cache_alloc(pd_cache, SLAB_KERNEL); + pd = kmem_cache_alloc(pd_cache, GFP_KERNEL); if (!pd) { ehca_err(device, "device=%p context=%p out of memory", device, context); diff --git a/trunk/drivers/infiniband/hw/ehca/ehca_qp.c b/trunk/drivers/infiniband/hw/ehca/ehca_qp.c index 8682aa50c707..c6c9cef203e3 100644 --- a/trunk/drivers/infiniband/hw/ehca/ehca_qp.c +++ b/trunk/drivers/infiniband/hw/ehca/ehca_qp.c @@ -450,7 +450,7 @@ struct ib_qp *ehca_create_qp(struct ib_pd *pd, if (pd->uobject && udata) context = pd->uobject->context; - my_qp = kmem_cache_alloc(qp_cache, SLAB_KERNEL); + my_qp = kmem_cache_alloc(qp_cache, GFP_KERNEL); if (!my_qp) { ehca_err(pd->device, "pd=%p not enough memory to alloc qp", pd); return ERR_PTR(-ENOMEM); diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_file_ops.c b/trunk/drivers/infiniband/hw/ipath/ipath_file_ops.c index a9ddc6911f66..340f27e3ebff 100644 --- a/trunk/drivers/infiniband/hw/ipath/ipath_file_ops.c +++ b/trunk/drivers/infiniband/hw/ipath/ipath_file_ops.c @@ -1745,9 +1745,9 @@ static int ipath_assign_port(struct file *fp, goto done; } - i_minor = iminor(fp->f_dentry->d_inode) - IPATH_USER_MINOR_BASE; + i_minor = iminor(fp->f_path.dentry->d_inode) - IPATH_USER_MINOR_BASE; ipath_cdbg(VERBOSE, "open on dev %lx (minor %d)\n", - (long)fp->f_dentry->d_inode->i_rdev, i_minor); + (long)fp->f_path.dentry->d_inode->i_rdev, i_minor); if (i_minor) ret = find_free_port(i_minor - 1, fp, uinfo); diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_fs.c b/trunk/drivers/infiniband/hw/ipath/ipath_fs.c index d9ff283f725e..79a60f020a21 100644 --- a/trunk/drivers/infiniband/hw/ipath/ipath_fs.c +++ b/trunk/drivers/infiniband/hw/ipath/ipath_fs.c @@ -118,7 +118,7 @@ static ssize_t atomic_counters_read(struct file *file, char __user *buf, u16 i; struct ipath_devdata *dd; - dd = file->f_dentry->d_inode->i_private; + dd = file->f_path.dentry->d_inode->i_private; for (i = 0; i < NUM_COUNTERS; i++) counters[i] = ipath_snap_cntr(dd, i); @@ -138,7 +138,7 @@ static ssize_t atomic_node_info_read(struct file *file, char __user *buf, struct ipath_devdata *dd; u64 guid; - dd = file->f_dentry->d_inode->i_private; + dd = file->f_path.dentry->d_inode->i_private; guid = be64_to_cpu(dd->ipath_guid); @@ -177,7 +177,7 @@ static ssize_t atomic_port_info_read(struct file *file, char __user *buf, u32 tmp, tmp2; struct ipath_devdata *dd; - dd = file->f_dentry->d_inode->i_private; + dd = file->f_path.dentry->d_inode->i_private; /* so we only initialize non-zero fields. */ memset(portinfo, 0, sizeof portinfo); @@ -324,7 +324,7 @@ static ssize_t flash_read(struct file *file, char __user *buf, goto bail; } - dd = file->f_dentry->d_inode->i_private; + dd = file->f_path.dentry->d_inode->i_private; if (ipath_eeprom_read(dd, pos, tmp, count)) { ipath_dev_err(dd, "failed to read from flash\n"); ret = -ENXIO; @@ -377,7 +377,7 @@ static ssize_t flash_write(struct file *file, const char __user *buf, goto bail_tmp; } - dd = file->f_dentry->d_inode->i_private; + dd = file->f_path.dentry->d_inode->i_private; if (ipath_eeprom_write(dd, pos, tmp, count)) { ret = -ENXIO; ipath_dev_err(dd, "failed to write to flash\n"); diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_user_pages.c b/trunk/drivers/infiniband/hw/ipath/ipath_user_pages.c index 413754b1d8a2..8536aeb96af8 100644 --- a/trunk/drivers/infiniband/hw/ipath/ipath_user_pages.c +++ b/trunk/drivers/infiniband/hw/ipath/ipath_user_pages.c @@ -214,9 +214,10 @@ struct ipath_user_pages_work { unsigned long num_pages; }; -static void user_pages_account(void *ptr) +static void user_pages_account(struct work_struct *_work) { - struct ipath_user_pages_work *work = ptr; + struct ipath_user_pages_work *work = + container_of(_work, struct ipath_user_pages_work, work); down_write(&work->mm->mmap_sem); work->mm->locked_vm -= work->num_pages; @@ -242,7 +243,7 @@ void ipath_release_user_pages_on_close(struct page **p, size_t num_pages) goto bail; - INIT_WORK(&work->work, user_pages_account, work); + INIT_WORK(&work->work, user_pages_account); work->mm = mm; work->num_pages = num_pages; diff --git a/trunk/drivers/infiniband/hw/mthca/mthca_av.c b/trunk/drivers/infiniband/hw/mthca/mthca_av.c index 57cdc1bc5f50..27caf3b0648a 100644 --- a/trunk/drivers/infiniband/hw/mthca/mthca_av.c +++ b/trunk/drivers/infiniband/hw/mthca/mthca_av.c @@ -189,7 +189,7 @@ int mthca_create_ah(struct mthca_dev *dev, on_hca_fail: if (ah->type == MTHCA_AH_PCI_POOL) { ah->av = pci_pool_alloc(dev->av_table.pool, - SLAB_ATOMIC, &ah->avdma); + GFP_ATOMIC, &ah->avdma); if (!ah->av) return -ENOMEM; diff --git a/trunk/drivers/infiniband/hw/mthca/mthca_catas.c b/trunk/drivers/infiniband/hw/mthca/mthca_catas.c index cd044ea2dfa4..e948158a28d9 100644 --- a/trunk/drivers/infiniband/hw/mthca/mthca_catas.c +++ b/trunk/drivers/infiniband/hw/mthca/mthca_catas.c @@ -57,7 +57,7 @@ static int catas_reset_disable; module_param_named(catas_reset_disable, catas_reset_disable, int, 0644); MODULE_PARM_DESC(catas_reset_disable, "disable reset on catastrophic event if nonzero"); -static void catas_reset(void *work_ptr) +static void catas_reset(struct work_struct *work) { struct mthca_dev *dev, *tmpdev; LIST_HEAD(tlist); @@ -203,7 +203,7 @@ void mthca_stop_catas_poll(struct mthca_dev *dev) int __init mthca_catas_init(void) { - INIT_WORK(&catas_work, catas_reset, NULL); + INIT_WORK(&catas_work, catas_reset); catas_wq = create_singlethread_workqueue("mthca_catas"); if (!catas_wq) diff --git a/trunk/drivers/infiniband/hw/mthca/mthca_provider.c b/trunk/drivers/infiniband/hw/mthca/mthca_provider.c index 21422a3336ad..7ec7c4b937f9 100644 --- a/trunk/drivers/infiniband/hw/mthca/mthca_provider.c +++ b/trunk/drivers/infiniband/hw/mthca/mthca_provider.c @@ -124,7 +124,7 @@ static int mthca_query_device(struct ib_device *ibdev, props->max_map_per_fmr = 255; else props->max_map_per_fmr = - (1 << (32 - long_log2(mdev->limits.num_mpts))) - 1; + (1 << (32 - ilog2(mdev->limits.num_mpts))) - 1; err = 0; out: @@ -816,7 +816,7 @@ static int mthca_resize_cq(struct ib_cq *ibcq, int entries, struct ib_udata *uda lkey = ucmd.lkey; } - ret = mthca_RESIZE_CQ(dev, cq->cqn, lkey, long_log2(entries), &status); + ret = mthca_RESIZE_CQ(dev, cq->cqn, lkey, ilog2(entries), &status); if (status) ret = -EINVAL; diff --git a/trunk/drivers/infiniband/hw/mthca/mthca_qp.c b/trunk/drivers/infiniband/hw/mthca/mthca_qp.c index 33e3ba7937f1..d844a2569b47 100644 --- a/trunk/drivers/infiniband/hw/mthca/mthca_qp.c +++ b/trunk/drivers/infiniband/hw/mthca/mthca_qp.c @@ -636,11 +636,11 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask, if (mthca_is_memfree(dev)) { if (qp->rq.max) - qp_context->rq_size_stride = long_log2(qp->rq.max) << 3; + qp_context->rq_size_stride = ilog2(qp->rq.max) << 3; qp_context->rq_size_stride |= qp->rq.wqe_shift - 4; if (qp->sq.max) - qp_context->sq_size_stride = long_log2(qp->sq.max) << 3; + qp_context->sq_size_stride = ilog2(qp->sq.max) << 3; qp_context->sq_size_stride |= qp->sq.wqe_shift - 4; } diff --git a/trunk/drivers/infiniband/hw/mthca/mthca_srq.c b/trunk/drivers/infiniband/hw/mthca/mthca_srq.c index 34d2c4768962..10684da33d58 100644 --- a/trunk/drivers/infiniband/hw/mthca/mthca_srq.c +++ b/trunk/drivers/infiniband/hw/mthca/mthca_srq.c @@ -120,7 +120,7 @@ static void mthca_arbel_init_srq_context(struct mthca_dev *dev, memset(context, 0, sizeof *context); - logsize = long_log2(srq->max); + logsize = ilog2(srq->max); context->state_logsize_srqn = cpu_to_be32(logsize << 24 | srq->srqn); context->lkey = cpu_to_be32(srq->mr.ibmr.lkey); context->db_index = cpu_to_be32(srq->db_index); @@ -213,7 +213,7 @@ int mthca_alloc_srq(struct mthca_dev *dev, struct mthca_pd *pd, if (!mthca_is_memfree(dev) && (ds > dev->limits.max_desc_sz)) return -EINVAL; - srq->wqe_shift = long_log2(ds); + srq->wqe_shift = ilog2(ds); srq->srqn = mthca_alloc(&dev->srq_table.alloc); if (srq->srqn == -1) diff --git a/trunk/drivers/infiniband/ulp/ipoib/ipoib.h b/trunk/drivers/infiniband/ulp/ipoib/ipoib.h index f2b61851a49c..99547996aba2 100644 --- a/trunk/drivers/infiniband/ulp/ipoib/ipoib.h +++ b/trunk/drivers/infiniband/ulp/ipoib/ipoib.h @@ -136,11 +136,11 @@ struct ipoib_dev_priv { struct list_head multicast_list; struct rb_root multicast_tree; - struct work_struct pkey_task; - struct work_struct mcast_task; + struct delayed_work pkey_task; + struct delayed_work mcast_task; struct work_struct flush_task; struct work_struct restart_task; - struct work_struct ah_reap_task; + struct delayed_work ah_reap_task; struct ib_device *ca; u8 port; @@ -254,13 +254,13 @@ int ipoib_add_pkey_attr(struct net_device *dev); void ipoib_send(struct net_device *dev, struct sk_buff *skb, struct ipoib_ah *address, u32 qpn); -void ipoib_reap_ah(void *dev_ptr); +void ipoib_reap_ah(struct work_struct *work); void ipoib_flush_paths(struct net_device *dev); struct ipoib_dev_priv *ipoib_intf_alloc(const char *format); int ipoib_ib_dev_init(struct net_device *dev, struct ib_device *ca, int port); -void ipoib_ib_dev_flush(void *dev); +void ipoib_ib_dev_flush(struct work_struct *work); void ipoib_ib_dev_cleanup(struct net_device *dev); int ipoib_ib_dev_open(struct net_device *dev); @@ -271,10 +271,10 @@ int ipoib_ib_dev_stop(struct net_device *dev); int ipoib_dev_init(struct net_device *dev, struct ib_device *ca, int port); void ipoib_dev_cleanup(struct net_device *dev); -void ipoib_mcast_join_task(void *dev_ptr); +void ipoib_mcast_join_task(struct work_struct *work); void ipoib_mcast_send(struct net_device *dev, void *mgid, struct sk_buff *skb); -void ipoib_mcast_restart_task(void *dev_ptr); +void ipoib_mcast_restart_task(struct work_struct *work); int ipoib_mcast_start_thread(struct net_device *dev); int ipoib_mcast_stop_thread(struct net_device *dev, int flush); @@ -312,7 +312,7 @@ void ipoib_event(struct ib_event_handler *handler, int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey); int ipoib_vlan_delete(struct net_device *pdev, unsigned short pkey); -void ipoib_pkey_poll(void *dev); +void ipoib_pkey_poll(struct work_struct *work); int ipoib_pkey_dev_delay_open(struct net_device *dev); #ifdef CONFIG_INFINIBAND_IPOIB_DEBUG diff --git a/trunk/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/trunk/drivers/infiniband/ulp/ipoib/ipoib_ib.c index 8bf5e9ec7c95..f10fba5d3265 100644 --- a/trunk/drivers/infiniband/ulp/ipoib/ipoib_ib.c +++ b/trunk/drivers/infiniband/ulp/ipoib/ipoib_ib.c @@ -400,10 +400,11 @@ static void __ipoib_reap_ah(struct net_device *dev) spin_unlock_irq(&priv->tx_lock); } -void ipoib_reap_ah(void *dev_ptr) +void ipoib_reap_ah(struct work_struct *work) { - struct net_device *dev = dev_ptr; - struct ipoib_dev_priv *priv = netdev_priv(dev); + struct ipoib_dev_priv *priv = + container_of(work, struct ipoib_dev_priv, ah_reap_task.work); + struct net_device *dev = priv->dev; __ipoib_reap_ah(dev); @@ -613,10 +614,11 @@ int ipoib_ib_dev_init(struct net_device *dev, struct ib_device *ca, int port) return 0; } -void ipoib_ib_dev_flush(void *_dev) +void ipoib_ib_dev_flush(struct work_struct *work) { - struct net_device *dev = (struct net_device *)_dev; - struct ipoib_dev_priv *priv = netdev_priv(dev), *cpriv; + struct ipoib_dev_priv *cpriv, *priv = + container_of(work, struct ipoib_dev_priv, flush_task); + struct net_device *dev = priv->dev; if (!test_bit(IPOIB_FLAG_INITIALIZED, &priv->flags) ) { ipoib_dbg(priv, "Not flushing - IPOIB_FLAG_INITIALIZED not set.\n"); @@ -638,14 +640,14 @@ void ipoib_ib_dev_flush(void *_dev) */ if (test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags)) { ipoib_ib_dev_up(dev); - ipoib_mcast_restart_task(dev); + ipoib_mcast_restart_task(&priv->restart_task); } mutex_lock(&priv->vlan_mutex); /* Flush any child interfaces too */ list_for_each_entry(cpriv, &priv->child_intfs, list) - ipoib_ib_dev_flush(cpriv->dev); + ipoib_ib_dev_flush(&cpriv->flush_task); mutex_unlock(&priv->vlan_mutex); } @@ -672,10 +674,11 @@ void ipoib_ib_dev_cleanup(struct net_device *dev) * change async notification is available. */ -void ipoib_pkey_poll(void *dev_ptr) +void ipoib_pkey_poll(struct work_struct *work) { - struct net_device *dev = dev_ptr; - struct ipoib_dev_priv *priv = netdev_priv(dev); + struct ipoib_dev_priv *priv = + container_of(work, struct ipoib_dev_priv, pkey_task.work); + struct net_device *dev = priv->dev; ipoib_pkey_dev_check_presence(dev); diff --git a/trunk/drivers/infiniband/ulp/ipoib/ipoib_main.c b/trunk/drivers/infiniband/ulp/ipoib/ipoib_main.c index 5ba3154320b4..c09280243726 100644 --- a/trunk/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/trunk/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -940,11 +940,11 @@ static void ipoib_setup(struct net_device *dev) INIT_LIST_HEAD(&priv->dead_ahs); INIT_LIST_HEAD(&priv->multicast_list); - INIT_WORK(&priv->pkey_task, ipoib_pkey_poll, priv->dev); - INIT_WORK(&priv->mcast_task, ipoib_mcast_join_task, priv->dev); - INIT_WORK(&priv->flush_task, ipoib_ib_dev_flush, priv->dev); - INIT_WORK(&priv->restart_task, ipoib_mcast_restart_task, priv->dev); - INIT_WORK(&priv->ah_reap_task, ipoib_reap_ah, priv->dev); + INIT_DELAYED_WORK(&priv->pkey_task, ipoib_pkey_poll); + INIT_DELAYED_WORK(&priv->mcast_task, ipoib_mcast_join_task); + INIT_WORK(&priv->flush_task, ipoib_ib_dev_flush); + INIT_WORK(&priv->restart_task, ipoib_mcast_restart_task); + INIT_DELAYED_WORK(&priv->ah_reap_task, ipoib_reap_ah); } struct ipoib_dev_priv *ipoib_intf_alloc(const char *name) diff --git a/trunk/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/trunk/drivers/infiniband/ulp/ipoib/ipoib_multicast.c index d282d65e3ee0..b04b72ca32ed 100644 --- a/trunk/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +++ b/trunk/drivers/infiniband/ulp/ipoib/ipoib_multicast.c @@ -399,7 +399,8 @@ static void ipoib_mcast_join_complete(int status, mcast->backoff = 1; mutex_lock(&mcast_mutex); if (test_bit(IPOIB_MCAST_RUN, &priv->flags)) - queue_work(ipoib_workqueue, &priv->mcast_task); + queue_delayed_work(ipoib_workqueue, + &priv->mcast_task, 0); mutex_unlock(&mcast_mutex); complete(&mcast->done); return; @@ -435,7 +436,8 @@ static void ipoib_mcast_join_complete(int status, if (test_bit(IPOIB_MCAST_RUN, &priv->flags)) { if (status == -ETIMEDOUT) - queue_work(ipoib_workqueue, &priv->mcast_task); + queue_delayed_work(ipoib_workqueue, &priv->mcast_task, + 0); else queue_delayed_work(ipoib_workqueue, &priv->mcast_task, mcast->backoff * HZ); @@ -517,10 +519,11 @@ static void ipoib_mcast_join(struct net_device *dev, struct ipoib_mcast *mcast, mcast->query_id = ret; } -void ipoib_mcast_join_task(void *dev_ptr) +void ipoib_mcast_join_task(struct work_struct *work) { - struct net_device *dev = dev_ptr; - struct ipoib_dev_priv *priv = netdev_priv(dev); + struct ipoib_dev_priv *priv = + container_of(work, struct ipoib_dev_priv, mcast_task.work); + struct net_device *dev = priv->dev; if (!test_bit(IPOIB_MCAST_RUN, &priv->flags)) return; @@ -610,7 +613,7 @@ int ipoib_mcast_start_thread(struct net_device *dev) mutex_lock(&mcast_mutex); if (!test_and_set_bit(IPOIB_MCAST_RUN, &priv->flags)) - queue_work(ipoib_workqueue, &priv->mcast_task); + queue_delayed_work(ipoib_workqueue, &priv->mcast_task, 0); mutex_unlock(&mcast_mutex); spin_lock_irq(&priv->lock); @@ -818,10 +821,11 @@ void ipoib_mcast_dev_flush(struct net_device *dev) } } -void ipoib_mcast_restart_task(void *dev_ptr) +void ipoib_mcast_restart_task(struct work_struct *work) { - struct net_device *dev = dev_ptr; - struct ipoib_dev_priv *priv = netdev_priv(dev); + struct ipoib_dev_priv *priv = + container_of(work, struct ipoib_dev_priv, restart_task); + struct net_device *dev = priv->dev; struct dev_mc_list *mclist; struct ipoib_mcast *mcast, *tmcast; LIST_HEAD(remove_list); diff --git a/trunk/drivers/infiniband/ulp/iser/iser_memory.c b/trunk/drivers/infiniband/ulp/iser/iser_memory.c index 5e122501fd80..3aedd59b8a84 100644 --- a/trunk/drivers/infiniband/ulp/iser/iser_memory.c +++ b/trunk/drivers/infiniband/ulp/iser/iser_memory.c @@ -114,7 +114,7 @@ int iser_start_rdma_unaligned_sg(struct iscsi_iser_cmd_task *iser_ctask, if (cmd_data_len > ISER_KMALLOC_THRESHOLD) mem = (void *)__get_free_pages(GFP_NOIO, - long_log2(roundup_pow_of_two(cmd_data_len)) - PAGE_SHIFT); + ilog2(roundup_pow_of_two(cmd_data_len)) - PAGE_SHIFT); else mem = kmalloc(cmd_data_len, GFP_NOIO); @@ -211,7 +211,7 @@ void iser_finalize_rdma_unaligned_sg(struct iscsi_iser_cmd_task *iser_ctask, if (cmd_data_len > ISER_KMALLOC_THRESHOLD) free_pages((unsigned long)mem_copy->copy_buf, - long_log2(roundup_pow_of_two(cmd_data_len)) - PAGE_SHIFT); + ilog2(roundup_pow_of_two(cmd_data_len)) - PAGE_SHIFT); else kfree(mem_copy->copy_buf); diff --git a/trunk/drivers/infiniband/ulp/iser/iser_verbs.c b/trunk/drivers/infiniband/ulp/iser/iser_verbs.c index 18a000034996..693b77002897 100644 --- a/trunk/drivers/infiniband/ulp/iser/iser_verbs.c +++ b/trunk/drivers/infiniband/ulp/iser/iser_verbs.c @@ -48,7 +48,7 @@ static void iser_cq_tasklet_fn(unsigned long data); static void iser_cq_callback(struct ib_cq *cq, void *cq_context); -static void iser_comp_error_worker(void *data); +static void iser_comp_error_worker(struct work_struct *work); static void iser_cq_event_callback(struct ib_event *cause, void *context) { @@ -480,8 +480,7 @@ int iser_conn_init(struct iser_conn **ibconn) init_waitqueue_head(&ib_conn->wait); atomic_set(&ib_conn->post_recv_buf_count, 0); atomic_set(&ib_conn->post_send_buf_count, 0); - INIT_WORK(&ib_conn->comperror_work, iser_comp_error_worker, - ib_conn); + INIT_WORK(&ib_conn->comperror_work, iser_comp_error_worker); INIT_LIST_HEAD(&ib_conn->conn_list); spin_lock_init(&ib_conn->lock); @@ -754,9 +753,10 @@ int iser_post_send(struct iser_desc *tx_desc) return ret_val; } -static void iser_comp_error_worker(void *data) +static void iser_comp_error_worker(struct work_struct *work) { - struct iser_conn *ib_conn = data; + struct iser_conn *ib_conn = + container_of(work, struct iser_conn, comperror_work); /* getting here when the state is UP means that the conn is being * * terminated asynchronously from the iSCSI layer's perspective. */ diff --git a/trunk/drivers/infiniband/ulp/srp/ib_srp.c b/trunk/drivers/infiniband/ulp/srp/ib_srp.c index 64ab5fc7cca3..a6289595557b 100644 --- a/trunk/drivers/infiniband/ulp/srp/ib_srp.c +++ b/trunk/drivers/infiniband/ulp/srp/ib_srp.c @@ -390,9 +390,10 @@ static void srp_disconnect_target(struct srp_target_port *target) wait_for_completion(&target->done); } -static void srp_remove_work(void *target_ptr) +static void srp_remove_work(struct work_struct *work) { - struct srp_target_port *target = target_ptr; + struct srp_target_port *target = + container_of(work, struct srp_target_port, work); spin_lock_irq(target->scsi_host->host_lock); if (target->state != SRP_TARGET_DEAD) { @@ -575,7 +576,7 @@ static int srp_reconnect_target(struct srp_target_port *target) spin_lock_irq(target->scsi_host->host_lock); if (target->state == SRP_TARGET_CONNECTING) { target->state = SRP_TARGET_DEAD; - INIT_WORK(&target->work, srp_remove_work, target); + INIT_WORK(&target->work, srp_remove_work); schedule_work(&target->work); } spin_unlock_irq(target->scsi_host->host_lock); diff --git a/trunk/drivers/input/ff-core.c b/trunk/drivers/input/ff-core.c index 35656cadc914..783b3412cead 100644 --- a/trunk/drivers/input/ff-core.c +++ b/trunk/drivers/input/ff-core.c @@ -203,7 +203,7 @@ static int erase_effect(struct input_dev *dev, int effect_id, } /** - * input_ff_erase - erase an effect from device + * input_ff_erase - erase a force-feedback effect from device * @dev: input device to erase effect from * @effect_id: id of the ffect to be erased * @file: purported owner of the request @@ -347,7 +347,7 @@ EXPORT_SYMBOL_GPL(input_ff_create); /** * input_ff_free() - frees force feedback portion of input device - * @dev: input device supporintg force feedback + * @dev: input device supporting force feedback * * This function is only needed in error path as input core will * automatically free force feedback structures when device is diff --git a/trunk/drivers/input/ff-memless.c b/trunk/drivers/input/ff-memless.c index cd8b7297e6df..eba18b6ac5e4 100644 --- a/trunk/drivers/input/ff-memless.c +++ b/trunk/drivers/input/ff-memless.c @@ -460,7 +460,7 @@ static void ml_ff_destroy(struct ff_device *ff) } /** - * input_ff_create_memless() - create memoryless FF device + * input_ff_create_memless() - create memoryless force-feedback device * @dev: input device supporting force-feedback * @data: driver-specific data to be passed into @play_effect * @play_effect: driver-specific method for playing FF effect diff --git a/trunk/drivers/input/gameport/gameport.c b/trunk/drivers/input/gameport/gameport.c index a0af97efe6ac..a00fe470a829 100644 --- a/trunk/drivers/input/gameport/gameport.c +++ b/trunk/drivers/input/gameport/gameport.c @@ -23,6 +23,7 @@ #include #include /* HZ */ #include +#include /*#include */ @@ -730,12 +731,6 @@ static int gameport_driver_remove(struct device *dev) return 0; } -static struct bus_type gameport_bus = { - .name = "gameport", - .probe = gameport_driver_probe, - .remove = gameport_driver_remove, -}; - static void gameport_add_driver(struct gameport_driver *drv) { int error; @@ -781,6 +776,15 @@ static int gameport_bus_match(struct device *dev, struct device_driver *drv) return !gameport_drv->ignore; } +static struct bus_type gameport_bus = { + .name = "gameport", + .dev_attrs = gameport_device_attrs, + .drv_attrs = gameport_driver_attrs, + .match = gameport_bus_match, + .probe = gameport_driver_probe, + .remove = gameport_driver_remove, +}; + static void gameport_set_drv(struct gameport *gameport, struct gameport_driver *drv) { mutex_lock(&gameport->drv_mutex); @@ -790,7 +794,6 @@ static void gameport_set_drv(struct gameport *gameport, struct gameport_driver * int gameport_open(struct gameport *gameport, struct gameport_driver *drv, int mode) { - if (gameport->open) { if (gameport->open(gameport, mode)) { return -1; @@ -818,9 +821,6 @@ static int __init gameport_init(void) { int error; - gameport_bus.dev_attrs = gameport_device_attrs; - gameport_bus.drv_attrs = gameport_driver_attrs; - gameport_bus.match = gameport_bus_match; error = bus_register(&gameport_bus); if (error) { printk(KERN_ERR "gameport: failed to register gameport bus, error: %d\n", error); diff --git a/trunk/drivers/input/gameport/lightning.c b/trunk/drivers/input/gameport/lightning.c index d65d81080257..6b4d4561d465 100644 --- a/trunk/drivers/input/gameport/lightning.c +++ b/trunk/drivers/input/gameport/lightning.c @@ -309,7 +309,7 @@ static int __init l4_init(void) int i, cards = 0; if (!request_region(L4_PORT, 1, "lightning")) - return -1; + return -EBUSY; for (i = 0; i < 2; i++) if (l4_add_card(i) == 0) @@ -319,7 +319,7 @@ static int __init l4_init(void) if (!cards) { release_region(L4_PORT, 1); - return -1; + return -ENODEV; } return 0; diff --git a/trunk/drivers/input/input.c b/trunk/drivers/input/input.c index 1c8c8a5bc4a9..7cf2b4f603a3 100644 --- a/trunk/drivers/input/input.c +++ b/trunk/drivers/input/input.c @@ -37,7 +37,7 @@ static struct input_handler *input_table[8]; /** * input_event() - report new input event - * @handle: device that generated the event + * @dev: device that generated the event * @type: type of the event * @code: event code * @value: value of the event @@ -900,6 +900,15 @@ struct class input_class = { }; EXPORT_SYMBOL_GPL(input_class); +/** + * input_allocate_device - allocate memory for new input device + * + * Returns prepared struct input_dev or NULL. + * + * NOTE: Use input_free_device() to free devices that have not been + * registered; input_unregister_device() should be used for already + * registered devices. + */ struct input_dev *input_allocate_device(void) { struct input_dev *dev; @@ -919,6 +928,20 @@ struct input_dev *input_allocate_device(void) } EXPORT_SYMBOL(input_allocate_device); +/** + * input_free_device - free memory occupied by input_dev structure + * @dev: input device to free + * + * This function should only be used if input_register_device() + * was not called yet or if it failed. Once device was registered + * use input_unregister_device() and memory will be freed once last + * refrence to the device is dropped. + * + * Device should be allocated by input_allocate_device(). + * + * NOTE: If there are references to the input device then memory + * will not be freed until last reference is dropped. + */ void input_free_device(struct input_dev *dev) { if (dev) { diff --git a/trunk/drivers/input/joystick/adi.c b/trunk/drivers/input/joystick/adi.c index 704bf70f1db7..6279ced8a35b 100644 --- a/trunk/drivers/input/joystick/adi.c +++ b/trunk/drivers/input/joystick/adi.c @@ -521,11 +521,19 @@ static int adi_connect(struct gameport *gameport, struct gameport_driver *drv) for (i = 0; i < 2; i++) if (port->adi[i].length > 0) { adi_init_center(port->adi + i); - input_register_device(port->adi[i].dev); + err = input_register_device(port->adi[i].dev); + if (err) + goto fail3; } return 0; + fail3: while (--i >= 0) { + if (port->adi[i].length > 0) { + input_unregister_device(port->adi[i].dev); + port->adi[i].dev = NULL; + } + } fail2: for (i = 0; i < 2; i++) if (port->adi[i].dev) input_free_device(port->adi[i].dev); diff --git a/trunk/drivers/input/joystick/amijoy.c b/trunk/drivers/input/joystick/amijoy.c index 650acf3a30b7..e608691b5a61 100644 --- a/trunk/drivers/input/joystick/amijoy.c +++ b/trunk/drivers/input/joystick/amijoy.c @@ -147,7 +147,11 @@ static int __init amijoy_init(void) amijoy_dev[i]->absmax[ABS_X + j] = 1; } - input_register_device(amijoy_dev[i]); + err = input_register_device(amijoy_dev[i]); + if (err) { + input_free_device(amijoy_dev[i]); + goto fail; + } } return 0; diff --git a/trunk/drivers/input/joystick/analog.c b/trunk/drivers/input/joystick/analog.c index e9a02db36ecc..7ef68456d7d6 100644 --- a/trunk/drivers/input/joystick/analog.c +++ b/trunk/drivers/input/joystick/analog.c @@ -434,6 +434,7 @@ static int analog_init_device(struct analog_port *port, struct analog *analog, i { struct input_dev *input_dev; int i, j, t, v, w, x, y, z; + int error; analog_name(analog); snprintf(analog->phys, sizeof(analog->phys), @@ -505,7 +506,11 @@ static int analog_init_device(struct analog_port *port, struct analog *analog, i analog_decode(analog, port->axes, port->initial, port->buttons); - input_register_device(analog->dev); + error = input_register_device(analog->dev); + if (error) { + input_free_device(analog->dev); + return error; + } return 0; } @@ -668,7 +673,8 @@ static int analog_connect(struct gameport *gameport, struct gameport_driver *drv return 0; fail3: while (--i >= 0) - input_unregister_device(port->analog[i].dev); + if (port->analog[i].mask) + input_unregister_device(port->analog[i].dev); fail2: gameport_close(gameport); fail1: gameport_set_drvdata(gameport, NULL); kfree(port); diff --git a/trunk/drivers/input/joystick/cobra.c b/trunk/drivers/input/joystick/cobra.c index d5e42eb88a20..034ec39c251d 100644 --- a/trunk/drivers/input/joystick/cobra.c +++ b/trunk/drivers/input/joystick/cobra.c @@ -223,12 +223,15 @@ static int cobra_connect(struct gameport *gameport, struct gameport_driver *drv) for (j = 0; cobra_btn[j]; j++) set_bit(cobra_btn[j], input_dev->keybit); - input_register_device(cobra->dev[i]); + err = input_register_device(cobra->dev[i]); + if (err) + goto fail4; } return 0; - fail3: for (i = 0; i < 2; i++) + fail4: input_free_device(cobra->dev[i]); + fail3: while (--i >= 0) if (cobra->dev[i]) input_unregister_device(cobra->dev[i]); fail2: gameport_close(gameport); diff --git a/trunk/drivers/input/joystick/gf2k.c b/trunk/drivers/input/joystick/gf2k.c index e4a699f6ec87..bacbab5d1b6f 100644 --- a/trunk/drivers/input/joystick/gf2k.c +++ b/trunk/drivers/input/joystick/gf2k.c @@ -341,7 +341,9 @@ static int gf2k_connect(struct gameport *gameport, struct gameport_driver *drv) input_dev->absflat[gf2k_abs[i]] = (i < 2) ? 24 : 0; } - input_register_device(gf2k->dev); + err = input_register_device(gf2k->dev); + if (err) + goto fail2; return 0; diff --git a/trunk/drivers/input/joystick/grip_mp.c b/trunk/drivers/input/joystick/grip_mp.c index 62438944a69a..8120a9c40773 100644 --- a/trunk/drivers/input/joystick/grip_mp.c +++ b/trunk/drivers/input/joystick/grip_mp.c @@ -423,7 +423,10 @@ static int get_and_decode_packet(struct grip_mp *grip, int flags) if (!port->registered) { dbg("New Grip pad in multiport slot %d.\n", slot); - register_slot(slot, grip); + if (register_slot(slot, grip)) { + port->mode = GRIP_MODE_RESET; + port->dirty = 0; + } } return flags; } @@ -585,6 +588,7 @@ static int register_slot(int slot, struct grip_mp *grip) struct grip_port *port = grip->port[slot]; struct input_dev *input_dev; int j, t; + int err; port->dev = input_dev = input_allocate_device(); if (!input_dev) @@ -610,7 +614,12 @@ static int register_slot(int slot, struct grip_mp *grip) if (t > 0) set_bit(t, input_dev->keybit); - input_register_device(port->dev); + err = input_register_device(port->dev); + if (err) { + input_free_device(port->dev); + return err; + } + port->registered = 1; if (port->dirty) /* report initial state, if any */ diff --git a/trunk/drivers/input/joystick/guillemot.c b/trunk/drivers/input/joystick/guillemot.c index 840ed9b512b2..dbc5d92858b8 100644 --- a/trunk/drivers/input/joystick/guillemot.c +++ b/trunk/drivers/input/joystick/guillemot.c @@ -250,7 +250,9 @@ static int guillemot_connect(struct gameport *gameport, struct gameport_driver * for (i = 0; (t = guillemot->type->btn[i]) >= 0; i++) set_bit(t, input_dev->keybit); - input_register_device(guillemot->dev); + err = input_register_device(guillemot->dev); + if (err) + goto fail2; return 0; diff --git a/trunk/drivers/input/joystick/iforce/iforce-main.c b/trunk/drivers/input/joystick/iforce/iforce-main.c index 24c684bc6337..3393a37fec39 100644 --- a/trunk/drivers/input/joystick/iforce/iforce-main.c +++ b/trunk/drivers/input/joystick/iforce/iforce-main.c @@ -325,8 +325,8 @@ int iforce_init_device(struct iforce *iforce) if (i == 20) { /* 5 seconds */ printk(KERN_ERR "iforce-main.c: Timeout waiting for response from device.\n"); - input_free_device(input_dev); - return -ENODEV; + error = -ENODEV; + goto fail; } /* @@ -439,10 +439,8 @@ int iforce_init_device(struct iforce *iforce) set_bit(iforce->type->ff[i], input_dev->ffbit); error = input_ff_create(input_dev, ff_effects); - if (error) { - input_free_device(input_dev); - return error; - } + if (error) + goto fail; ff = input_dev->ff; ff->upload = iforce_upload_effect; @@ -455,22 +453,35 @@ int iforce_init_device(struct iforce *iforce) * Register input device. */ - input_register_device(iforce->dev); + error = input_register_device(iforce->dev); + if (error) + goto fail; printk(KERN_DEBUG "iforce->dev->open = %p\n", iforce->dev->open); return 0; + + fail: input_free_device(input_dev); + return error; } static int __init iforce_init(void) { + int err = 0; + #ifdef CONFIG_JOYSTICK_IFORCE_USB - usb_register(&iforce_usb_driver); + err = usb_register(&iforce_usb_driver); + if (err) + return err; #endif #ifdef CONFIG_JOYSTICK_IFORCE_232 - serio_register_driver(&iforce_serio_drv); + err = serio_register_driver(&iforce_serio_drv); +#ifdef CONFIG_JOYSTICK_IFORCE_USB + if (err) + usb_deregister(&iforce_usb_driver); #endif - return 0; +#endif + return err; } static void __exit iforce_exit(void) diff --git a/trunk/drivers/input/joystick/iforce/iforce-serio.c b/trunk/drivers/input/joystick/iforce/iforce-serio.c index ca08f45c2040..ec4be535f483 100644 --- a/trunk/drivers/input/joystick/iforce/iforce-serio.c +++ b/trunk/drivers/input/joystick/iforce/iforce-serio.c @@ -141,21 +141,19 @@ static int iforce_serio_connect(struct serio *serio, struct serio_driver *drv) serio_set_drvdata(serio, iforce); err = serio_open(serio, drv); - if (err) { - serio_set_drvdata(serio, NULL); - kfree(iforce); - return err; - } + if (err) + goto fail1; err = iforce_init_device(iforce); - if (err) { - serio_close(serio); - serio_set_drvdata(serio, NULL); - kfree(iforce); - return -ENODEV; - } + if (err) + goto fail2; return 0; + + fail2: serio_close(serio); + fail1: serio_set_drvdata(serio, NULL); + kfree(iforce); + return err; } static void iforce_serio_disconnect(struct serio *serio) diff --git a/trunk/drivers/input/joystick/interact.c b/trunk/drivers/input/joystick/interact.c index bbfeb9c59b87..fec8b3d0967d 100644 --- a/trunk/drivers/input/joystick/interact.c +++ b/trunk/drivers/input/joystick/interact.c @@ -283,7 +283,9 @@ static int interact_connect(struct gameport *gameport, struct gameport_driver *d for (i = 0; (t = interact_type[interact->type].btn[i]) >= 0; i++) set_bit(t, input_dev->keybit); - input_register_device(interact->dev); + err = input_register_device(interact->dev); + if (err) + goto fail2; return 0; diff --git a/trunk/drivers/input/joystick/magellan.c b/trunk/drivers/input/joystick/magellan.c index e3d19444ba2e..4112789f1196 100644 --- a/trunk/drivers/input/joystick/magellan.c +++ b/trunk/drivers/input/joystick/magellan.c @@ -157,7 +157,7 @@ static int magellan_connect(struct serio *serio, struct serio_driver *drv) magellan = kzalloc(sizeof(struct magellan), GFP_KERNEL); input_dev = input_allocate_device(); if (!magellan || !input_dev) - goto fail; + goto fail1; magellan->dev = input_dev; snprintf(magellan->phys, sizeof(magellan->phys), "%s/input0", serio->phys); @@ -183,13 +183,17 @@ static int magellan_connect(struct serio *serio, struct serio_driver *drv) err = serio_open(serio, drv); if (err) - goto fail; + goto fail2; + + err = input_register_device(magellan->dev); + if (err) + goto fail3; - input_register_device(magellan->dev); return 0; - fail: serio_set_drvdata(serio, NULL); - input_free_device(input_dev); + fail3: serio_close(serio); + fail2: serio_set_drvdata(serio, NULL); + fail1: input_free_device(input_dev); kfree(magellan); return err; } @@ -227,8 +231,7 @@ static struct serio_driver magellan_drv = { static int __init magellan_init(void) { - serio_register_driver(&magellan_drv); - return 0; + return serio_register_driver(&magellan_drv); } static void __exit magellan_exit(void) diff --git a/trunk/drivers/input/joystick/spaceball.c b/trunk/drivers/input/joystick/spaceball.c index 2a9808cf826f..08bf113e62eb 100644 --- a/trunk/drivers/input/joystick/spaceball.c +++ b/trunk/drivers/input/joystick/spaceball.c @@ -215,7 +215,7 @@ static int spaceball_connect(struct serio *serio, struct serio_driver *drv) spaceball = kmalloc(sizeof(struct spaceball), GFP_KERNEL); input_dev = input_allocate_device(); if (!spaceball || !input_dev) - goto fail; + goto fail1; spaceball->dev = input_dev; snprintf(spaceball->phys, sizeof(spaceball->phys), "%s/input0", serio->phys); @@ -252,13 +252,17 @@ static int spaceball_connect(struct serio *serio, struct serio_driver *drv) err = serio_open(serio, drv); if (err) - goto fail; + goto fail2; + + err = input_register_device(spaceball->dev); + if (err) + goto fail3; - input_register_device(spaceball->dev); return 0; - fail: serio_set_drvdata(serio, NULL); - input_free_device(input_dev); + fail3: serio_close(serio); + fail2: serio_set_drvdata(serio, NULL); + fail1: input_free_device(input_dev); kfree(spaceball); return err; } @@ -296,8 +300,7 @@ static struct serio_driver spaceball_drv = { static int __init spaceball_init(void) { - serio_register_driver(&spaceball_drv); - return 0; + return serio_register_driver(&spaceball_drv); } static void __exit spaceball_exit(void) diff --git a/trunk/drivers/input/joystick/spaceorb.c b/trunk/drivers/input/joystick/spaceorb.c index c4db0247c5fb..c9c79211af71 100644 --- a/trunk/drivers/input/joystick/spaceorb.c +++ b/trunk/drivers/input/joystick/spaceorb.c @@ -172,7 +172,7 @@ static int spaceorb_connect(struct serio *serio, struct serio_driver *drv) spaceorb = kzalloc(sizeof(struct spaceorb), GFP_KERNEL); input_dev = input_allocate_device(); if (!spaceorb || !input_dev) - goto fail; + goto fail1; spaceorb->dev = input_dev; snprintf(spaceorb->phys, sizeof(spaceorb->phys), "%s/input0", serio->phys); @@ -198,13 +198,17 @@ static int spaceorb_connect(struct serio *serio, struct serio_driver *drv) err = serio_open(serio, drv); if (err) - goto fail; + goto fail2; + + err = input_register_device(spaceorb->dev); + if (err) + goto fail3; - input_register_device(spaceorb->dev); return 0; - fail: serio_set_drvdata(serio, NULL); - input_free_device(input_dev); + fail3: serio_close(serio); + fail2: serio_set_drvdata(serio, NULL); + fail1: input_free_device(input_dev); kfree(spaceorb); return err; } @@ -242,8 +246,7 @@ static struct serio_driver spaceorb_drv = { static int __init spaceorb_init(void) { - serio_register_driver(&spaceorb_drv); - return 0; + return serio_register_driver(&spaceorb_drv); } static void __exit spaceorb_exit(void) diff --git a/trunk/drivers/input/joystick/stinger.c b/trunk/drivers/input/joystick/stinger.c index 1ffb03223311..ecb0916215fa 100644 --- a/trunk/drivers/input/joystick/stinger.c +++ b/trunk/drivers/input/joystick/stinger.c @@ -143,7 +143,7 @@ static int stinger_connect(struct serio *serio, struct serio_driver *drv) stinger = kmalloc(sizeof(struct stinger), GFP_KERNEL); input_dev = input_allocate_device(); if (!stinger || !input_dev) - goto fail; + goto fail1; stinger->dev = input_dev; snprintf(stinger->phys, sizeof(stinger->phys), "%s/serio0", serio->phys); @@ -168,13 +168,17 @@ static int stinger_connect(struct serio *serio, struct serio_driver *drv) err = serio_open(serio, drv); if (err) - goto fail; + goto fail2; + + err = input_register_device(stinger->dev); + if (err) + goto fail3; - input_register_device(stinger->dev); return 0; - fail: serio_set_drvdata(serio, NULL); - input_free_device(input_dev); + fail3: serio_close(serio); + fail2: serio_set_drvdata(serio, NULL); + fail1: input_free_device(input_dev); kfree(stinger); return err; } @@ -212,8 +216,7 @@ static struct serio_driver stinger_drv = { static int __init stinger_init(void) { - serio_register_driver(&stinger_drv); - return 0; + return serio_register_driver(&stinger_drv); } static void __exit stinger_exit(void) diff --git a/trunk/drivers/input/joystick/twidjoy.c b/trunk/drivers/input/joystick/twidjoy.c index 49085df2d631..9cf17d6ced82 100644 --- a/trunk/drivers/input/joystick/twidjoy.c +++ b/trunk/drivers/input/joystick/twidjoy.c @@ -194,7 +194,7 @@ static int twidjoy_connect(struct serio *serio, struct serio_driver *drv) twidjoy = kzalloc(sizeof(struct twidjoy), GFP_KERNEL); input_dev = input_allocate_device(); if (!twidjoy || !input_dev) - goto fail; + goto fail1; twidjoy->dev = input_dev; snprintf(twidjoy->phys, sizeof(twidjoy->phys), "%s/input0", serio->phys); @@ -221,13 +221,17 @@ static int twidjoy_connect(struct serio *serio, struct serio_driver *drv) err = serio_open(serio, drv); if (err) - goto fail; + goto fail2; + + err = input_register_device(twidjoy->dev); + if (err) + goto fail3; - input_register_device(twidjoy->dev); return 0; - fail: serio_set_drvdata(serio, NULL); - input_free_device(input_dev); + fail3: serio_close(serio); + fail2: serio_set_drvdata(serio, NULL); + fail1: input_free_device(input_dev); kfree(twidjoy); return err; } @@ -265,8 +269,7 @@ static struct serio_driver twidjoy_drv = { static int __init twidjoy_init(void) { - serio_register_driver(&twidjoy_drv); - return 0; + return serio_register_driver(&twidjoy_drv); } static void __exit twidjoy_exit(void) diff --git a/trunk/drivers/input/joystick/warrior.c b/trunk/drivers/input/joystick/warrior.c index 35edea1ab955..29d339acf430 100644 --- a/trunk/drivers/input/joystick/warrior.c +++ b/trunk/drivers/input/joystick/warrior.c @@ -149,7 +149,7 @@ static int warrior_connect(struct serio *serio, struct serio_driver *drv) warrior = kzalloc(sizeof(struct warrior), GFP_KERNEL); input_dev = input_allocate_device(); if (!warrior || !input_dev) - goto fail; + goto fail1; warrior->dev = input_dev; snprintf(warrior->phys, sizeof(warrior->phys), "%s/input0", serio->phys); @@ -176,13 +176,17 @@ static int warrior_connect(struct serio *serio, struct serio_driver *drv) err = serio_open(serio, drv); if (err) - goto fail; + goto fail2; + + err = input_register_device(warrior->dev); + if (err) + goto fail3; - input_register_device(warrior->dev); return 0; - fail: serio_set_drvdata(serio, NULL); - input_free_device(input_dev); + fail3: serio_close(serio); + fail2: serio_set_drvdata(serio, NULL); + fail1: input_free_device(input_dev); kfree(warrior); return err; } @@ -220,8 +224,7 @@ static struct serio_driver warrior_drv = { static int __init warrior_init(void) { - serio_register_driver(&warrior_drv); - return 0; + return serio_register_driver(&warrior_drv); } static void __exit warrior_exit(void) diff --git a/trunk/drivers/input/keyboard/Kconfig b/trunk/drivers/input/keyboard/Kconfig index 81a333f73010..049f2f544e75 100644 --- a/trunk/drivers/input/keyboard/Kconfig +++ b/trunk/drivers/input/keyboard/Kconfig @@ -203,4 +203,15 @@ config KEYBOARD_OMAP To compile this driver as a module, choose M here: the module will be called omap-keypad. +config KEYBOARD_AAED2000 + tristate "AAED-2000 keyboard" + depends on MACH_AAED2000 + default y + help + Say Y here to enable the keyboard on the Agilent AAED-2000 + development board. + + To compile this driver as a module, choose M here: the + module will be called aaed2000_kbd. + endif diff --git a/trunk/drivers/input/keyboard/Makefile b/trunk/drivers/input/keyboard/Makefile index 4c79e7bc9d06..568797907347 100644 --- a/trunk/drivers/input/keyboard/Makefile +++ b/trunk/drivers/input/keyboard/Makefile @@ -17,4 +17,5 @@ obj-$(CONFIG_KEYBOARD_SPITZ) += spitzkbd.o obj-$(CONFIG_KEYBOARD_HIL) += hil_kbd.o obj-$(CONFIG_KEYBOARD_HIL_OLD) += hilkbd.o obj-$(CONFIG_KEYBOARD_OMAP) += omap-keypad.o +obj-$(CONFIG_KEYBOARD_AAED2000) += aaed2000_kbd.o diff --git a/trunk/drivers/input/keyboard/aaed2000_kbd.c b/trunk/drivers/input/keyboard/aaed2000_kbd.c new file mode 100644 index 000000000000..65fcb6af63a8 --- /dev/null +++ b/trunk/drivers/input/keyboard/aaed2000_kbd.c @@ -0,0 +1,203 @@ +/* + * Keyboard driver for the AAED-2000 dev board + * + * Copyright (c) 2006 Nicolas Bellido Y Ortega + * + * Based on corgikbd.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define KB_ROWS 12 +#define KB_COLS 8 +#define KB_ROWMASK(r) (1 << (r)) +#define SCANCODE(r,c) (((c) * KB_ROWS) + (r)) +#define NR_SCANCODES (KB_COLS * KB_ROWS) + +#define SCAN_INTERVAL (50) /* ms */ +#define KB_ACTIVATE_DELAY (20) /* us */ + +static unsigned char aaedkbd_keycode[NR_SCANCODES] = { + KEY_9, KEY_0, KEY_MINUS, KEY_EQUAL, KEY_BACKSPACE, 0, KEY_SPACE, KEY_KP6, 0, KEY_KPDOT, 0, 0, + KEY_K, KEY_M, KEY_O, KEY_DOT, KEY_SLASH, 0, KEY_F, 0, 0, 0, KEY_LEFTSHIFT, 0, + KEY_I, KEY_P, KEY_LEFTBRACE, KEY_RIGHTBRACE, KEY_BACKSLASH, 0, 0, 0, 0, 0, KEY_RIGHTSHIFT, 0, + KEY_8, KEY_L, KEY_SEMICOLON, KEY_APOSTROPHE, KEY_ENTER, 0, 0, 0, 0, 0, 0, 0, + KEY_J, KEY_H, KEY_B, KEY_KP8, KEY_KP4, 0, KEY_C, KEY_D, KEY_S, KEY_A, 0, KEY_CAPSLOCK, + KEY_Y, KEY_U, KEY_N, KEY_T, 0, 0, KEY_R, KEY_E, KEY_W, KEY_Q, 0, KEY_TAB, + KEY_7, KEY_6, KEY_G, 0, KEY_5, 0, KEY_4, KEY_3, KEY_2, KEY_1, 0, KEY_GRAVE, + 0, 0, KEY_COMMA, 0, KEY_KP2, 0, KEY_V, KEY_LEFTALT, KEY_X, KEY_Z, 0, KEY_LEFTCTRL +}; + +struct aaedkbd { + unsigned char keycode[ARRAY_SIZE(aaedkbd_keycode)]; + struct input_dev *input; + struct work_struct workq; + int kbdscan_state[KB_COLS]; + int kbdscan_count[KB_COLS]; +}; + +#define KBDSCAN_STABLE_COUNT 2 + +static void aaedkbd_report_col(struct aaedkbd *aaedkbd, + unsigned int col, unsigned int rowd) +{ + unsigned int scancode, pressed; + unsigned int row; + + for (row = 0; row < KB_ROWS; row++) { + scancode = SCANCODE(row, col); + pressed = rowd & KB_ROWMASK(row); + + input_report_key(aaedkbd->input, aaedkbd->keycode[scancode], pressed); + } +} + +/* Scan the hardware keyboard and push any changes up through the input layer */ +static void aaedkbd_work(void *data) +{ + struct aaedkbd *aaedkbd = data; + unsigned int col, rowd; + + col = 0; + do { + AAEC_GPIO_KSCAN = col + 8; + udelay(KB_ACTIVATE_DELAY); + rowd = AAED_EXT_GPIO & AAED_EGPIO_KBD_SCAN; + + if (rowd != aaedkbd->kbdscan_state[col]) { + aaedkbd->kbdscan_count[col] = 0; + aaedkbd->kbdscan_state[col] = rowd; + } else if (++aaedkbd->kbdscan_count[col] >= KBDSCAN_STABLE_COUNT) { + aaedkbd_report_col(aaedkbd, col, rowd); + col++; + } + } while (col < KB_COLS); + + AAEC_GPIO_KSCAN = 0x07; + input_sync(aaedkbd->input); + + schedule_delayed_work(&aaedkbd->workq, msecs_to_jiffies(SCAN_INTERVAL)); +} + +static int aaedkbd_open(struct input_dev *indev) +{ + struct aaedkbd *aaedkbd = indev->private; + + schedule_delayed_work(&aaedkbd->workq, msecs_to_jiffies(SCAN_INTERVAL)); + + return 0; +} + +static void aaedkbd_close(struct input_dev *indev) +{ + struct aaedkbd *aaedkbd = indev->private; + + cancel_delayed_work(&aaedkbd->workq); + flush_scheduled_work(); +} + +static int __devinit aaedkbd_probe(struct platform_device *pdev) +{ + struct aaedkbd *aaedkbd; + struct input_dev *input_dev; + int i; + int error; + + aaedkbd = kzalloc(sizeof(struct aaedkbd), GFP_KERNEL); + input_dev = input_allocate_device(); + if (!aaedkbd || !input_dev) { + error = -ENOMEM; + goto fail; + } + + platform_set_drvdata(pdev, aaedkbd); + + aaedkbd->input = input_dev; + + /* Init keyboard rescan workqueue */ + INIT_WORK(&aaedkbd->workq, aaedkbd_work, aaedkbd); + + memcpy(aaedkbd->keycode, aaedkbd_keycode, sizeof(aaedkbd->keycode)); + + input_dev->name = "AAED-2000 Keyboard"; + input_dev->phys = "aaedkbd/input0"; + input_dev->id.bustype = BUS_HOST; + input_dev->id.vendor = 0x0001; + input_dev->id.product = 0x0001; + input_dev->id.version = 0x0100; + input_dev->cdev.dev = &pdev->dev; + input_dev->private = aaedkbd; + + input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP); + input_dev->keycode = aaedkbd->keycode; + input_dev->keycodesize = sizeof(unsigned char); + input_dev->keycodemax = ARRAY_SIZE(aaedkbd_keycode); + + for (i = 0; i < ARRAY_SIZE(aaedkbd_keycode); i++) + set_bit(aaedkbd->keycode[i], input_dev->keybit); + clear_bit(0, input_dev->keybit); + + input_dev->open = aaedkbd_open; + input_dev->close = aaedkbd_close; + + error = input_register_device(aaedkbd->input); + if (error) + goto fail; + + return 0; + + fail: kfree(aaedkbd); + input_free_device(input_dev); + return error; +} + +static int __devexit aaedkbd_remove(struct platform_device *pdev) +{ + struct aaedkbd *aaedkbd = platform_get_drvdata(pdev); + + input_unregister_device(aaedkbd->input); + kfree(aaedkbd); + + return 0; +} + +static struct platform_driver aaedkbd_driver = { + .probe = aaedkbd_probe, + .remove = __devexit_p(aaedkbd_remove), + .driver = { + .name = "aaed2000-keyboard", + }, +}; + +static int __init aaedkbd_init(void) +{ + return platform_driver_register(&aaedkbd_driver); +} + +static void __exit aaedkbd_exit(void) +{ + platform_driver_unregister(&aaedkbd_driver); +} + +module_init(aaedkbd_init); +module_exit(aaedkbd_exit); + +MODULE_AUTHOR("Nicolas Bellido Y Ortega"); +MODULE_DESCRIPTION("AAED-2000 Keyboard Driver"); +MODULE_LICENSE("GPLv2"); diff --git a/trunk/drivers/input/keyboard/amikbd.c b/trunk/drivers/input/keyboard/amikbd.c index 8abdbd0ee8f9..16583d71753b 100644 --- a/trunk/drivers/input/keyboard/amikbd.c +++ b/trunk/drivers/input/keyboard/amikbd.c @@ -190,7 +190,7 @@ static int __init amikbd_init(void) int i, j; if (!AMIGAHW_PRESENT(AMI_KEYBOARD)) - return -EIO; + return -ENODEV; if (!request_mem_region(CIAA_PHYSADDR-1+0xb00, 0x100, "amikeyb")) return -EBUSY; @@ -198,8 +198,8 @@ static int __init amikbd_init(void) amikbd_dev = input_allocate_device(); if (!amikbd_dev) { printk(KERN_ERR "amikbd: not enough memory for input device\n"); - release_mem_region(CIAA_PHYSADDR - 1 + 0xb00, 0x100); - return -ENOMEM; + err = -ENOMEM; + goto fail1; } amikbd_dev->name = "Amiga Keyboard"; @@ -231,10 +231,22 @@ static int __init amikbd_init(void) memcpy(key_maps[i], temp_map, sizeof(temp_map)); } ciaa.cra &= ~0x41; /* serial data in, turn off TA */ - request_irq(IRQ_AMIGA_CIAA_SP, amikbd_interrupt, 0, "amikbd", amikbd_interrupt); + if (request_irq(IRQ_AMIGA_CIAA_SP, amikbd_interrupt, 0, "amikbd", + amikbd_interrupt)) { + err = -EBUSY; + goto fail2; + } + + err = input_register_device(amikbd_dev); + if (err) + goto fail3; - input_register_device(amikbd_dev); return 0; + + fail3: free_irq(IRQ_AMIGA_CIAA_SP, amikbd_interrupt); + fail2: input_free_device(amikbd_dev); + fail1: release_mem_region(CIAA_PHYSADDR - 1 + 0xb00, 0x100); + return err; } static void __exit amikbd_exit(void) diff --git a/trunk/drivers/input/keyboard/atkbd.c b/trunk/drivers/input/keyboard/atkbd.c index cbb93669d1ce..c621a9177a56 100644 --- a/trunk/drivers/input/keyboard/atkbd.c +++ b/trunk/drivers/input/keyboard/atkbd.c @@ -567,9 +567,9 @@ static int atkbd_set_leds(struct atkbd *atkbd) * interrupt context. */ -static void atkbd_event_work(void *data) +static void atkbd_event_work(struct work_struct *work) { - struct atkbd *atkbd = data; + struct atkbd *atkbd = container_of(work, struct atkbd, event_work); mutex_lock(&atkbd->event_mutex); @@ -939,11 +939,11 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv) atkbd = kzalloc(sizeof(struct atkbd), GFP_KERNEL); dev = input_allocate_device(); if (!atkbd || !dev) - goto fail; + goto fail1; atkbd->dev = dev; ps2_init(&atkbd->ps2dev, serio); - INIT_WORK(&atkbd->event_work, atkbd_event_work, atkbd); + INIT_WORK(&atkbd->event_work, atkbd_event_work); mutex_init(&atkbd->event_mutex); switch (serio->id.type) { @@ -967,14 +967,13 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv) err = serio_open(serio, drv); if (err) - goto fail; + goto fail2; if (atkbd->write) { if (atkbd_probe(atkbd)) { - serio_close(serio); err = -ENODEV; - goto fail; + goto fail3; } atkbd->set = atkbd_select_set(atkbd, atkbd_set, atkbd_extra); @@ -988,16 +987,22 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv) atkbd_set_keycode_table(atkbd); atkbd_set_device_attrs(atkbd); - sysfs_create_group(&serio->dev.kobj, &atkbd_attribute_group); + err = sysfs_create_group(&serio->dev.kobj, &atkbd_attribute_group); + if (err) + goto fail3; atkbd_enable(atkbd); - input_register_device(atkbd->dev); + err = input_register_device(atkbd->dev); + if (err) + goto fail4; return 0; - fail: serio_set_drvdata(serio, NULL); - input_free_device(dev); + fail4: sysfs_remove_group(&serio->dev.kobj, &atkbd_attribute_group); + fail3: serio_close(serio); + fail2: serio_set_drvdata(serio, NULL); + fail1: input_free_device(dev); kfree(atkbd); return err; } @@ -1133,9 +1138,11 @@ static ssize_t atkbd_show_extra(struct atkbd *atkbd, char *buf) static ssize_t atkbd_set_extra(struct atkbd *atkbd, const char *buf, size_t count) { - struct input_dev *new_dev; + struct input_dev *old_dev, *new_dev; unsigned long value; char *rest; + int err; + unsigned char old_extra, old_set; if (!atkbd->write) return -EIO; @@ -1147,17 +1154,36 @@ static ssize_t atkbd_set_extra(struct atkbd *atkbd, const char *buf, size_t coun if (atkbd->extra != value) { /* * Since device's properties will change we need to - * unregister old device. But allocate new one first - * to make sure we have it. + * unregister old device. But allocate and register + * new one first to make sure we have it. */ - if (!(new_dev = input_allocate_device())) + old_dev = atkbd->dev; + old_extra = atkbd->extra; + old_set = atkbd->set; + + new_dev = input_allocate_device(); + if (!new_dev) return -ENOMEM; - input_unregister_device(atkbd->dev); + atkbd->dev = new_dev; atkbd->set = atkbd_select_set(atkbd, atkbd->set, value); atkbd_activate(atkbd); + atkbd_set_keycode_table(atkbd); atkbd_set_device_attrs(atkbd); - input_register_device(atkbd->dev); + + err = input_register_device(atkbd->dev); + if (err) { + input_free_device(new_dev); + + atkbd->dev = old_dev; + atkbd->set = atkbd_select_set(atkbd, old_set, old_extra); + atkbd_set_keycode_table(atkbd); + atkbd_set_device_attrs(atkbd); + + return err; + } + input_unregister_device(old_dev); + } return count; } @@ -1169,23 +1195,41 @@ static ssize_t atkbd_show_scroll(struct atkbd *atkbd, char *buf) static ssize_t atkbd_set_scroll(struct atkbd *atkbd, const char *buf, size_t count) { - struct input_dev *new_dev; + struct input_dev *old_dev, *new_dev; unsigned long value; char *rest; + int err; + unsigned char old_scroll; value = simple_strtoul(buf, &rest, 10); if (*rest || value > 1) return -EINVAL; if (atkbd->scroll != value) { - if (!(new_dev = input_allocate_device())) + old_dev = atkbd->dev; + old_scroll = atkbd->scroll; + + new_dev = input_allocate_device(); + if (!new_dev) return -ENOMEM; - input_unregister_device(atkbd->dev); + atkbd->dev = new_dev; atkbd->scroll = value; atkbd_set_keycode_table(atkbd); atkbd_set_device_attrs(atkbd); - input_register_device(atkbd->dev); + + err = input_register_device(atkbd->dev); + if (err) { + input_free_device(new_dev); + + atkbd->scroll = old_scroll; + atkbd->dev = old_dev; + atkbd_set_keycode_table(atkbd); + atkbd_set_device_attrs(atkbd); + + return err; + } + input_unregister_device(old_dev); } return count; } @@ -1197,9 +1241,11 @@ static ssize_t atkbd_show_set(struct atkbd *atkbd, char *buf) static ssize_t atkbd_set_set(struct atkbd *atkbd, const char *buf, size_t count) { - struct input_dev *new_dev; + struct input_dev *old_dev, *new_dev; unsigned long value; char *rest; + int err; + unsigned char old_set, old_extra; if (!atkbd->write) return -EIO; @@ -1209,15 +1255,32 @@ static ssize_t atkbd_set_set(struct atkbd *atkbd, const char *buf, size_t count) return -EINVAL; if (atkbd->set != value) { - if (!(new_dev = input_allocate_device())) + old_dev = atkbd->dev; + old_extra = atkbd->extra; + old_set = atkbd->set; + + new_dev = input_allocate_device(); + if (!new_dev) return -ENOMEM; - input_unregister_device(atkbd->dev); + atkbd->dev = new_dev; atkbd->set = atkbd_select_set(atkbd, value, atkbd->extra); atkbd_activate(atkbd); atkbd_set_keycode_table(atkbd); atkbd_set_device_attrs(atkbd); - input_register_device(atkbd->dev); + + err = input_register_device(atkbd->dev); + if (err) { + input_free_device(new_dev); + + atkbd->dev = old_dev; + atkbd->set = atkbd_select_set(atkbd, old_set, old_extra); + atkbd_set_keycode_table(atkbd); + atkbd_set_device_attrs(atkbd); + + return err; + } + input_unregister_device(old_dev); } return count; } @@ -1229,9 +1292,11 @@ static ssize_t atkbd_show_softrepeat(struct atkbd *atkbd, char *buf) static ssize_t atkbd_set_softrepeat(struct atkbd *atkbd, const char *buf, size_t count) { - struct input_dev *new_dev; + struct input_dev *old_dev, *new_dev; unsigned long value; char *rest; + int err; + unsigned char old_softrepeat, old_softraw; if (!atkbd->write) return -EIO; @@ -1241,15 +1306,32 @@ static ssize_t atkbd_set_softrepeat(struct atkbd *atkbd, const char *buf, size_t return -EINVAL; if (atkbd->softrepeat != value) { - if (!(new_dev = input_allocate_device())) + old_dev = atkbd->dev; + old_softrepeat = atkbd->softrepeat; + old_softraw = atkbd->softraw; + + new_dev = input_allocate_device(); + if (!new_dev) return -ENOMEM; - input_unregister_device(atkbd->dev); + atkbd->dev = new_dev; atkbd->softrepeat = value; if (atkbd->softrepeat) atkbd->softraw = 1; atkbd_set_device_attrs(atkbd); - input_register_device(atkbd->dev); + + err = input_register_device(atkbd->dev); + if (err) { + input_free_device(new_dev); + + atkbd->dev = old_dev; + atkbd->softrepeat = old_softrepeat; + atkbd->softraw = old_softraw; + atkbd_set_device_attrs(atkbd); + + return err; + } + input_unregister_device(old_dev); } return count; } @@ -1262,22 +1344,39 @@ static ssize_t atkbd_show_softraw(struct atkbd *atkbd, char *buf) static ssize_t atkbd_set_softraw(struct atkbd *atkbd, const char *buf, size_t count) { - struct input_dev *new_dev; + struct input_dev *old_dev, *new_dev; unsigned long value; char *rest; + int err; + unsigned char old_softraw; value = simple_strtoul(buf, &rest, 10); if (*rest || value > 1) return -EINVAL; if (atkbd->softraw != value) { - if (!(new_dev = input_allocate_device())) + old_dev = atkbd->dev; + old_softraw = atkbd->softraw; + + new_dev = input_allocate_device(); + if (!new_dev) return -ENOMEM; - input_unregister_device(atkbd->dev); + atkbd->dev = new_dev; atkbd->softraw = value; atkbd_set_device_attrs(atkbd); - input_register_device(atkbd->dev); + + err = input_register_device(atkbd->dev); + if (err) { + input_free_device(new_dev); + + atkbd->dev = old_dev; + atkbd->softraw = old_softraw; + atkbd_set_device_attrs(atkbd); + + return err; + } + input_unregister_device(old_dev); } return count; } @@ -1290,8 +1389,7 @@ static ssize_t atkbd_show_err_count(struct atkbd *atkbd, char *buf) static int __init atkbd_init(void) { - serio_register_driver(&atkbd_drv); - return 0; + return serio_register_driver(&atkbd_drv); } static void __exit atkbd_exit(void) diff --git a/trunk/drivers/input/keyboard/corgikbd.c b/trunk/drivers/input/keyboard/corgikbd.c index befdd6006b50..1016c94e65db 100644 --- a/trunk/drivers/input/keyboard/corgikbd.c +++ b/trunk/drivers/input/keyboard/corgikbd.c @@ -291,15 +291,12 @@ static int __init corgikbd_probe(struct platform_device *pdev) { struct corgikbd *corgikbd; struct input_dev *input_dev; - int i; + int i, err = -ENOMEM; corgikbd = kzalloc(sizeof(struct corgikbd), GFP_KERNEL); input_dev = input_allocate_device(); - if (!corgikbd || !input_dev) { - kfree(corgikbd); - input_free_device(input_dev); - return -ENOMEM; - } + if (!corgikbd || !input_dev) + goto fail; platform_set_drvdata(pdev, corgikbd); @@ -341,7 +338,9 @@ static int __init corgikbd_probe(struct platform_device *pdev) set_bit(SW_TABLET_MODE, input_dev->swbit); set_bit(SW_HEADPHONE_INSERT, input_dev->swbit); - input_register_device(corgikbd->input); + err = input_register_device(corgikbd->input); + if (err) + goto fail; mod_timer(&corgikbd->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL)); @@ -362,6 +361,10 @@ static int __init corgikbd_probe(struct platform_device *pdev) pxa_gpio_mode(CORGI_GPIO_AK_INT | GPIO_IN); return 0; + + fail: input_free_device(input_dev); + kfree(corgikbd); + return err; } static int corgikbd_remove(struct platform_device *pdev) diff --git a/trunk/drivers/input/keyboard/hil_kbd.c b/trunk/drivers/input/keyboard/hil_kbd.c index e774dd31e99b..7cc9728b04df 100644 --- a/trunk/drivers/input/keyboard/hil_kbd.c +++ b/trunk/drivers/input/keyboard/hil_kbd.c @@ -381,8 +381,7 @@ struct serio_driver hil_kbd_serio_drv = { static int __init hil_kbd_init(void) { - serio_register_driver(&hil_kbd_serio_drv); - return 0; + return serio_register_driver(&hil_kbd_serio_drv); } static void __exit hil_kbd_exit(void) diff --git a/trunk/drivers/input/keyboard/lkkbd.c b/trunk/drivers/input/keyboard/lkkbd.c index 979b93e33da7..3d4d0a0ede28 100644 --- a/trunk/drivers/input/keyboard/lkkbd.c +++ b/trunk/drivers/input/keyboard/lkkbd.c @@ -572,9 +572,9 @@ lkkbd_event (struct input_dev *dev, unsigned int type, unsigned int code, * were in. */ static void -lkkbd_reinit (void *data) +lkkbd_reinit (struct work_struct *work) { - struct lkkbd *lk = data; + struct lkkbd *lk = container_of(work, struct lkkbd, tq); int division; unsigned char leds_on = 0; unsigned char leds_off = 0; @@ -646,12 +646,12 @@ lkkbd_connect (struct serio *serio, struct serio_driver *drv) input_dev = input_allocate_device (); if (!lk || !input_dev) { err = -ENOMEM; - goto fail; + goto fail1; } lk->serio = serio; lk->dev = input_dev; - INIT_WORK (&lk->tq, lkkbd_reinit, lk); + INIT_WORK (&lk->tq, lkkbd_reinit); lk->bell_volume = bell_volume; lk->keyclick_volume = keyclick_volume; lk->ctrlclick_volume = ctrlclick_volume; @@ -691,15 +691,19 @@ lkkbd_connect (struct serio *serio, struct serio_driver *drv) err = serio_open (serio, drv); if (err) - goto fail; + goto fail2; + + err = input_register_device (lk->dev); + if (err) + goto fail3; - input_register_device (lk->dev); lk->serio->write (lk->serio, LK_CMD_POWERCYCLE_RESET); return 0; - fail: serio_set_drvdata (serio, NULL); - input_free_device (input_dev); + fail3: serio_close (serio); + fail2: serio_set_drvdata (serio, NULL); + fail1: input_free_device (input_dev); kfree (lk); return err; } @@ -749,8 +753,7 @@ static struct serio_driver lkkbd_drv = { static int __init lkkbd_init (void) { - serio_register_driver(&lkkbd_drv); - return 0; + return serio_register_driver(&lkkbd_drv); } static void __exit diff --git a/trunk/drivers/input/keyboard/locomokbd.c b/trunk/drivers/input/keyboard/locomokbd.c index 5788dbc317bb..2ade5186cc41 100644 --- a/trunk/drivers/input/keyboard/locomokbd.c +++ b/trunk/drivers/input/keyboard/locomokbd.c @@ -193,22 +193,22 @@ static int locomokbd_probe(struct locomo_dev *dev) { struct locomokbd *locomokbd; struct input_dev *input_dev; - int i, ret; + int i, err; locomokbd = kzalloc(sizeof(struct locomokbd), GFP_KERNEL); input_dev = input_allocate_device(); if (!locomokbd || !input_dev) { - ret = -ENOMEM; - goto free; + err = -ENOMEM; + goto err_free_mem; } /* try and claim memory region */ if (!request_mem_region((unsigned long) dev->mapbase, dev->length, LOCOMO_DRIVER_NAME(dev))) { - ret = -EBUSY; + err = -EBUSY; printk(KERN_ERR "locomokbd: Can't acquire access to io memory for keyboard\n"); - goto free; + goto err_free_mem; } locomokbd->ldev = dev; @@ -244,24 +244,28 @@ static int locomokbd_probe(struct locomo_dev *dev) clear_bit(0, input_dev->keybit); /* attempt to get the interrupt */ - ret = request_irq(dev->irq[0], locomokbd_interrupt, 0, "locomokbd", locomokbd); - if (ret) { + err = request_irq(dev->irq[0], locomokbd_interrupt, 0, "locomokbd", locomokbd); + if (err) { printk(KERN_ERR "locomokbd: Can't get irq for keyboard\n"); - goto out; + goto err_release_region; } - input_register_device(locomokbd->input); + err = input_register_device(locomokbd->input); + if (err) + goto err_free_irq; return 0; -out: + err_free_irq: + free_irq(dev->irq[0], locomokbd); + err_release_region: release_mem_region((unsigned long) dev->mapbase, dev->length); locomo_set_drvdata(dev, NULL); -free: + err_free_mem: input_free_device(input_dev); kfree(locomokbd); - return ret; + return err; } static int locomokbd_remove(struct locomo_dev *dev) diff --git a/trunk/drivers/input/keyboard/maple_keyb.c b/trunk/drivers/input/keyboard/maple_keyb.c deleted file mode 100644 index cc6aaf9e85be..000000000000 --- a/trunk/drivers/input/keyboard/maple_keyb.c +++ /dev/null @@ -1,160 +0,0 @@ -/* - * $Id: maple_keyb.c,v 1.4 2004/03/22 01:18:15 lethal Exp $ - * SEGA Dreamcast keyboard driver - * Based on drivers/usb/usbkbd.c - */ - -#include -#include -#include -#include -#include -#include -#include - -MODULE_AUTHOR("YAEGASHI Takeshi "); -MODULE_DESCRIPTION("SEGA Dreamcast keyboard driver"); -MODULE_LICENSE("GPL"); - -static unsigned char dc_kbd_keycode[256] = { - 0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38, - 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44, 2, 3, - 4, 5, 6, 7, 8, 9, 10, 11, 28, 1, 14, 15, 57, 12, 13, 26, - 27, 43, 43, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64, - 65, 66, 67, 68, 87, 88, 99, 70,119,110,102,104,111,107,109,106, - 105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71, - 72, 73, 82, 83, 86,127,116,117,183,184,185,186,187,188,189,190, - 191,192,193,194,134,138,130,132,128,129,131,137,133,135,136,113, - 115,114, 0, 0, 0,121, 0, 89, 93,124, 92, 94, 95, 0, 0, 0, - 122,123, 90, 91, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113, - 150,158,159,128,136,177,178,176,142,152,173,140 -}; - - -struct dc_kbd { - struct input_dev *dev; - unsigned char new[8]; - unsigned char old[8]; -}; - - -static void dc_scan_kbd(struct dc_kbd *kbd) -{ - int i; - struct input_dev *dev = kbd->dev; - - for (i = 0; i < 8; i++) - input_report_key(dev, dc_kbd_keycode[i + 224], (kbd->new[0] >> i) & 1); - - for (i = 2; i < 8; i++) { - - if (kbd->old[i] > 3 && memscan(kbd->new + 2, kbd->old[i], 6) == NULL) { - if (dc_kbd_keycode[kbd->old[i]]) - input_report_key(dev, dc_kbd_keycode[kbd->old[i]], 0); - else - printk("Unknown key (scancode %#x) released.", - kbd->old[i]); - } - - if (kbd->new[i] > 3 && memscan(kbd->old + 2, kbd->new[i], 6) != NULL) { - if(dc_kbd_keycode[kbd->new[i]]) - input_report_key(dev, dc_kbd_keycode[kbd->new[i]], 1); - else - printk("Unknown key (scancode %#x) pressed.", - kbd->new[i]); - } - } - - input_sync(dev); - - memcpy(kbd->old, kbd->new, 8); -} - - -static void dc_kbd_callback(struct mapleq *mq) -{ - struct maple_device *mapledev = mq->dev; - struct dc_kbd *kbd = mapledev->private_data; - unsigned long *buf = mq->recvbuf; - - if (buf[1] == mapledev->function) { - memcpy(kbd->new, buf + 2, 8); - dc_scan_kbd(kbd); - } -} - -static int dc_kbd_connect(struct maple_device *dev) -{ - struct dc_kbd *kbd; - struct input_dev *input_dev; - unsigned long data = be32_to_cpu(dev->devinfo.function_data[0]); - int i; - - dev->private_data = kbd = kzalloc(sizeof(struct dc_kbd), GFP_KERNEL); - input_dev = input_allocate_device(); - if (!kbd || !input_dev) { - kfree(kbd); - input_free_device(input_dev); - return -ENOMEM; - } - - kbd->dev = input_dev; - - input_dev->name = dev->product_name; - input_dev->id.bustype = BUS_MAPLE; - input_dev->private = kbd; - input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP); - for (i = 0; i < 255; i++) - set_bit(dc_kbd_keycode[i], input_dev->keybit); - clear_bit(0, input_dev->keybit); - - input_register_device(kbd->dev); - - maple_getcond_callback(dev, dc_kbd_callback, 1, MAPLE_FUNC_KEYBOARD); - return 0; -} - - -static void dc_kbd_disconnect(struct maple_device *dev) -{ - struct dc_kbd *kbd = dev->private_data; - - input_unregister_device(kbd->dev); - kfree(kbd); -} - - -static struct maple_driver dc_kbd_driver = { - .function = MAPLE_FUNC_KEYBOARD, - .name = "Dreamcast keyboard", - .connect = dc_kbd_connect, - .disconnect = dc_kbd_disconnect, -}; - - -static int __init dc_kbd_init(void) -{ - maple_register_driver(&dc_kbd_driver); - return 0; -} - - -static void __exit dc_kbd_exit(void) -{ - maple_unregister_driver(&dc_kbd_driver); -} - - -module_init(dc_kbd_init); -module_exit(dc_kbd_exit); - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/trunk/drivers/input/keyboard/newtonkbd.c b/trunk/drivers/input/keyboard/newtonkbd.c index 9282e4e082bd..aa29b50765c9 100644 --- a/trunk/drivers/input/keyboard/newtonkbd.c +++ b/trunk/drivers/input/keyboard/newtonkbd.c @@ -91,7 +91,7 @@ static int nkbd_connect(struct serio *serio, struct serio_driver *drv) nkbd = kzalloc(sizeof(struct nkbd), GFP_KERNEL); input_dev = input_allocate_device(); if (!nkbd || !input_dev) - goto fail; + goto fail1; nkbd->serio = serio; nkbd->dev = input_dev; @@ -119,13 +119,17 @@ static int nkbd_connect(struct serio *serio, struct serio_driver *drv) err = serio_open(serio, drv); if (err) - goto fail; + goto fail2; + + err = input_register_device(nkbd->dev); + if (err) + goto fail3; - input_register_device(nkbd->dev); return 0; - fail: serio_set_drvdata(serio, NULL); - input_free_device(input_dev); + fail3: serio_close(serio); + fail2: serio_set_drvdata(serio, NULL); + fail1: input_free_device(input_dev); kfree(nkbd); return err; } @@ -165,8 +169,7 @@ static struct serio_driver nkbd_drv = { static int __init nkbd_init(void) { - serio_register_driver(&nkbd_drv); - return 0; + return serio_register_driver(&nkbd_drv); } static void __exit nkbd_exit(void) diff --git a/trunk/drivers/input/keyboard/spitzkbd.c b/trunk/drivers/input/keyboard/spitzkbd.c index 28b2748e82d0..8a2166c77ff4 100644 --- a/trunk/drivers/input/keyboard/spitzkbd.c +++ b/trunk/drivers/input/keyboard/spitzkbd.c @@ -346,17 +346,12 @@ static int __init spitzkbd_probe(struct platform_device *dev) { struct spitzkbd *spitzkbd; struct input_dev *input_dev; - int i; + int i, err = -ENOMEM; spitzkbd = kzalloc(sizeof(struct spitzkbd), GFP_KERNEL); - if (!spitzkbd) - return -ENOMEM; - input_dev = input_allocate_device(); - if (!input_dev) { - kfree(spitzkbd); - return -ENOMEM; - } + if (!spitzkbd || !input_dev) + goto fail; platform_set_drvdata(dev, spitzkbd); strcpy(spitzkbd->phys, "spitzkbd/input0"); @@ -400,7 +395,9 @@ static int __init spitzkbd_probe(struct platform_device *dev) set_bit(SW_TABLET_MODE, input_dev->swbit); set_bit(SW_HEADPHONE_INSERT, input_dev->swbit); - input_register_device(input_dev); + err = input_register_device(input_dev); + if (err) + goto fail; mod_timer(&spitzkbd->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL)); @@ -434,13 +431,15 @@ static int __init spitzkbd_probe(struct platform_device *dev) request_irq(SPITZ_IRQ_GPIO_SWB, spitzkbd_hinge_isr, IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "Spitzkbd SWB", spitzkbd); - request_irq(SPITZ_IRQ_GPIO_AK_INT, spitzkbd_hinge_isr, + request_irq(SPITZ_IRQ_GPIO_AK_INT, spitzkbd_hinge_isr, IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "Spitzkbd HP", spitzkbd); - printk(KERN_INFO "input: Spitz Keyboard Registered\n"); - return 0; + + fail: input_free_device(input_dev); + kfree(spitzkbd); + return err; } static int spitzkbd_remove(struct platform_device *dev) @@ -474,6 +473,7 @@ static struct platform_driver spitzkbd_driver = { .resume = spitzkbd_resume, .driver = { .name = "spitz-keyboard", + .owner = THIS_MODULE, }, }; diff --git a/trunk/drivers/input/keyboard/stowaway.c b/trunk/drivers/input/keyboard/stowaway.c index e60937d17b1c..f7b5c5b81451 100644 --- a/trunk/drivers/input/keyboard/stowaway.c +++ b/trunk/drivers/input/keyboard/stowaway.c @@ -173,8 +173,7 @@ static struct serio_driver skbd_drv = { static int __init skbd_init(void) { - serio_register_driver(&skbd_drv); - return 0; + return serio_register_driver(&skbd_drv); } static void __exit skbd_exit(void) diff --git a/trunk/drivers/input/keyboard/sunkbd.c b/trunk/drivers/input/keyboard/sunkbd.c index cac4781103c3..3826db9403e6 100644 --- a/trunk/drivers/input/keyboard/sunkbd.c +++ b/trunk/drivers/input/keyboard/sunkbd.c @@ -208,9 +208,9 @@ static int sunkbd_initialize(struct sunkbd *sunkbd) * were in. */ -static void sunkbd_reinit(void *data) +static void sunkbd_reinit(struct work_struct *work) { - struct sunkbd *sunkbd = data; + struct sunkbd *sunkbd = container_of(work, struct sunkbd, tq); wait_event_interruptible_timeout(sunkbd->wait, sunkbd->reset >= 0, HZ); @@ -243,23 +243,23 @@ static int sunkbd_connect(struct serio *serio, struct serio_driver *drv) sunkbd = kzalloc(sizeof(struct sunkbd), GFP_KERNEL); input_dev = input_allocate_device(); if (!sunkbd || !input_dev) - goto fail; + goto fail1; sunkbd->serio = serio; sunkbd->dev = input_dev; init_waitqueue_head(&sunkbd->wait); - INIT_WORK(&sunkbd->tq, sunkbd_reinit, sunkbd); + INIT_WORK(&sunkbd->tq, sunkbd_reinit); snprintf(sunkbd->phys, sizeof(sunkbd->phys), "%s/input0", serio->phys); serio_set_drvdata(serio, sunkbd); err = serio_open(serio, drv); if (err) - goto fail; + goto fail2; if (sunkbd_initialize(sunkbd) < 0) { - serio_close(serio); - goto fail; + err = -ENODEV; + goto fail3; } snprintf(sunkbd->name, sizeof(sunkbd->name), "Sun Type %d keyboard", sunkbd->type); @@ -287,11 +287,17 @@ static int sunkbd_connect(struct serio *serio, struct serio_driver *drv) clear_bit(0, input_dev->keybit); sunkbd_enable(sunkbd, 1); - input_register_device(sunkbd->dev); + + err = input_register_device(sunkbd->dev); + if (err) + goto fail4; + return 0; - fail: serio_set_drvdata(serio, NULL); - input_free_device(input_dev); + fail4: sunkbd_enable(sunkbd, 0); + fail3: serio_close(serio); + fail2: serio_set_drvdata(serio, NULL); + fail1: input_free_device(input_dev); kfree(sunkbd); return err; } @@ -346,8 +352,7 @@ static struct serio_driver sunkbd_drv = { static int __init sunkbd_init(void) { - serio_register_driver(&sunkbd_drv); - return 0; + return serio_register_driver(&sunkbd_drv); } static void __exit sunkbd_exit(void) diff --git a/trunk/drivers/input/keyboard/xtkbd.c b/trunk/drivers/input/keyboard/xtkbd.c index 8c11dc935454..a82093432138 100644 --- a/trunk/drivers/input/keyboard/xtkbd.c +++ b/trunk/drivers/input/keyboard/xtkbd.c @@ -95,7 +95,7 @@ static int xtkbd_connect(struct serio *serio, struct serio_driver *drv) xtkbd = kmalloc(sizeof(struct xtkbd), GFP_KERNEL); input_dev = input_allocate_device(); if (!xtkbd || !input_dev) - goto fail; + goto fail1; xtkbd->serio = serio; xtkbd->dev = input_dev; @@ -124,13 +124,17 @@ static int xtkbd_connect(struct serio *serio, struct serio_driver *drv) err = serio_open(serio, drv); if (err) - goto fail; + goto fail2; + + err = input_register_device(xtkbd->dev); + if (err) + goto fail3; - input_register_device(xtkbd->dev); return 0; - fail: serio_set_drvdata(serio, NULL); - input_free_device(input_dev); + fail3: serio_close(serio); + fail2: serio_set_drvdata(serio, NULL); + fail1: input_free_device(input_dev); kfree(xtkbd); return err; } @@ -170,8 +174,7 @@ static struct serio_driver xtkbd_drv = { static int __init xtkbd_init(void) { - serio_register_driver(&xtkbd_drv); - return 0; + return serio_register_driver(&xtkbd_drv); } static void __exit xtkbd_exit(void) diff --git a/trunk/drivers/input/misc/hp_sdc_rtc.c b/trunk/drivers/input/misc/hp_sdc_rtc.c index ab4da79ee560..31d5a13bfd6b 100644 --- a/trunk/drivers/input/misc/hp_sdc_rtc.c +++ b/trunk/drivers/input/misc/hp_sdc_rtc.c @@ -695,7 +695,9 @@ static int __init hp_sdc_rtc_init(void) if ((ret = hp_sdc_request_timer_irq(&hp_sdc_rtc_isr))) return ret; - misc_register(&hp_sdc_rtc_dev); + if (misc_register(&hp_sdc_rtc_dev) != 0) + printk(KERN_INFO "Could not register misc. dev for i8042 rtc\n"); + create_proc_read_entry ("driver/rtc", 0, NULL, hp_sdc_rtc_read_proc, NULL); diff --git a/trunk/drivers/input/mouse/amimouse.c b/trunk/drivers/input/mouse/amimouse.c index 599a7b2dc519..239a0e16d91a 100644 --- a/trunk/drivers/input/mouse/amimouse.c +++ b/trunk/drivers/input/mouse/amimouse.c @@ -95,10 +95,13 @@ static void amimouse_close(struct input_dev *dev) static int __init amimouse_init(void) { + int err; + if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(AMI_MOUSE)) return -ENODEV; - if (!(amimouse_dev = input_allocate_device())) + amimouse_dev = input_allocate_device(); + if (!amimouse_dev) return -ENOMEM; amimouse_dev->name = "Amiga mouse"; @@ -114,7 +117,11 @@ static int __init amimouse_init(void) amimouse_dev->open = amimouse_open; amimouse_dev->close = amimouse_close; - input_register_device(amimouse_dev); + err = input_register_device(amimouse_dev); + if (err) { + input_free_device(amimouse_dev); + return err; + } return 0; } diff --git a/trunk/drivers/input/mouse/hil_ptr.c b/trunk/drivers/input/mouse/hil_ptr.c index 4f2b503c1ac7..bfb174fe3230 100644 --- a/trunk/drivers/input/mouse/hil_ptr.c +++ b/trunk/drivers/input/mouse/hil_ptr.c @@ -417,8 +417,7 @@ static struct serio_driver hil_ptr_serio_driver = { static int __init hil_ptr_init(void) { - serio_register_driver(&hil_ptr_serio_driver); - return 0; + return serio_register_driver(&hil_ptr_serio_driver); } static void __exit hil_ptr_exit(void) diff --git a/trunk/drivers/input/mouse/inport.c b/trunk/drivers/input/mouse/inport.c index e1252fa9a107..13dd96785e39 100644 --- a/trunk/drivers/input/mouse/inport.c +++ b/trunk/drivers/input/mouse/inport.c @@ -135,6 +135,7 @@ static void inport_close(struct input_dev *dev) static int __init inport_init(void) { unsigned char a, b, c; + int err; if (!request_region(INPORT_BASE, INPORT_EXTENT, "inport")) { printk(KERN_ERR "inport.c: Can't allocate ports at %#x\n", INPORT_BASE); @@ -145,15 +146,16 @@ static int __init inport_init(void) b = inb(INPORT_SIGNATURE_PORT); c = inb(INPORT_SIGNATURE_PORT); if (a == b || a != c) { - release_region(INPORT_BASE, INPORT_EXTENT); printk(KERN_ERR "inport.c: Didn't find InPort mouse at %#x\n", INPORT_BASE); - return -ENODEV; + err = -ENODEV; + goto err_release_region; } - if (!(inport_dev = input_allocate_device())) { + inport_dev = input_allocate_device(); + if (!inport_dev) { printk(KERN_ERR "inport.c: Not enough memory for input device\n"); - release_region(INPORT_BASE, INPORT_EXTENT); - return -ENOMEM; + err = -ENOMEM; + goto err_release_region; } inport_dev->name = INPORT_NAME; @@ -174,9 +176,18 @@ static int __init inport_init(void) outb(INPORT_REG_MODE, INPORT_CONTROL_PORT); outb(INPORT_MODE_BASE, INPORT_DATA_PORT); - input_register_device(inport_dev); + err = input_register_device(inport_dev); + if (err) + goto err_free_dev; return 0; + + err_free_dev: + input_free_device(inport_dev); + err_release_region: + release_region(INPORT_BASE, INPORT_EXTENT); + + return err; } static void __exit inport_exit(void) diff --git a/trunk/drivers/input/mouse/lifebook.c b/trunk/drivers/input/mouse/lifebook.c index c57e8853b949..29542f0631cb 100644 --- a/trunk/drivers/input/mouse/lifebook.c +++ b/trunk/drivers/input/mouse/lifebook.c @@ -21,47 +21,51 @@ #include "lifebook.h" static struct dmi_system_id lifebook_dmi_table[] = { - { - .ident = "LifeBook B", - .matches = { - DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook B Series"), - }, - }, - { - .ident = "Lifebook B", - .matches = { - DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK B Series"), - }, - }, - { - .ident = "Lifebook B213x/B2150", - .matches = { - DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook B2131/B2133/B2150"), - }, - }, - { - .ident = "Zephyr", - .matches = { - DMI_MATCH(DMI_PRODUCT_NAME, "ZEPHYR"), - }, - }, - { - .ident = "CF-18", - .matches = { - DMI_MATCH(DMI_PRODUCT_NAME, "CF-18"), - }, - }, - { - .ident = "Lifebook B142", - .matches = { - DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook B142"), - }, - - }, - { } + { + .ident = "FLORA-ie 55mi", + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "FLORA-ie 55mi"), + }, + }, + { + .ident = "LifeBook B", + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook B Series"), + }, + }, + { + .ident = "Lifebook B", + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK B Series"), + }, + }, + { + .ident = "Lifebook B213x/B2150", + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook B2131/B2133/B2150"), + }, + }, + { + .ident = "Zephyr", + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "ZEPHYR"), + }, + }, + { + .ident = "CF-18", + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "CF-18"), + }, + }, + { + .ident = "Lifebook B142", + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook B142"), + }, + }, + { } }; - static psmouse_ret_t lifebook_process_byte(struct psmouse *psmouse) { unsigned char *packet = psmouse->packet; diff --git a/trunk/drivers/input/mouse/logibm.c b/trunk/drivers/input/mouse/logibm.c index 8e9c2f3d69a8..db205995bffd 100644 --- a/trunk/drivers/input/mouse/logibm.c +++ b/trunk/drivers/input/mouse/logibm.c @@ -124,6 +124,8 @@ static void logibm_close(struct input_dev *dev) static int __init logibm_init(void) { + int err; + if (!request_region(LOGIBM_BASE, LOGIBM_EXTENT, "logibm")) { printk(KERN_ERR "logibm.c: Can't allocate ports at %#x\n", LOGIBM_BASE); return -EBUSY; @@ -134,18 +136,19 @@ static int __init logibm_init(void) udelay(100); if (inb(LOGIBM_SIGNATURE_PORT) != LOGIBM_SIGNATURE_BYTE) { - release_region(LOGIBM_BASE, LOGIBM_EXTENT); printk(KERN_ERR "logibm.c: Didn't find Logitech busmouse at %#x\n", LOGIBM_BASE); - return -ENODEV; + err = -ENODEV; + goto err_release_region; } outb(LOGIBM_DEFAULT_MODE, LOGIBM_CONFIG_PORT); outb(LOGIBM_DISABLE_IRQ, LOGIBM_CONTROL_PORT); - if (!(logibm_dev = input_allocate_device())) { + logibm_dev = input_allocate_device(); + if (!logibm_dev) { printk(KERN_ERR "logibm.c: Not enough memory for input device\n"); - release_region(LOGIBM_BASE, LOGIBM_EXTENT); - return -ENOMEM; + err = -ENOMEM; + goto err_release_region; } logibm_dev->name = "Logitech bus mouse"; @@ -162,9 +165,18 @@ static int __init logibm_init(void) logibm_dev->open = logibm_open; logibm_dev->close = logibm_close; - input_register_device(logibm_dev); + err = input_register_device(logibm_dev); + if (err) + goto err_free_dev; return 0; + + err_free_dev: + input_free_device(logibm_dev); + err_release_region: + release_region(LOGIBM_BASE, LOGIBM_EXTENT); + + return err; } static void __exit logibm_exit(void) diff --git a/trunk/drivers/input/mouse/logips2pp.c b/trunk/drivers/input/mouse/logips2pp.c index 8a4f862709e7..d3ddea26b8ca 100644 --- a/trunk/drivers/input/mouse/logips2pp.c +++ b/trunk/drivers/input/mouse/logips2pp.c @@ -328,6 +328,7 @@ int ps2pp_init(struct psmouse *psmouse, int set_properties) unsigned char model, buttons; const struct ps2pp_info *model_info; int use_ps2pp = 0; + int error; param[0] = 0; ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES); @@ -393,8 +394,14 @@ int ps2pp_init(struct psmouse *psmouse, int set_properties) psmouse->set_resolution = ps2pp_set_resolution; psmouse->disconnect = ps2pp_disconnect; - device_create_file(&psmouse->ps2dev.serio->dev, - &psmouse_attr_smartscroll.dattr); + error = device_create_file(&psmouse->ps2dev.serio->dev, + &psmouse_attr_smartscroll.dattr); + if (error) { + printk(KERN_ERR + "logips2pp.c: failed to create smartscroll " + "sysfs attribute, error: %d\n", error); + return -1; + } } } diff --git a/trunk/drivers/input/mouse/pc110pad.c b/trunk/drivers/input/mouse/pc110pad.c index 8c075aa7223b..f155c1fea04e 100644 --- a/trunk/drivers/input/mouse/pc110pad.c +++ b/trunk/drivers/input/mouse/pc110pad.c @@ -108,6 +108,7 @@ static int pc110pad_open(struct input_dev *dev) static int __init pc110pad_init(void) { struct pci_dev *dev; + int err; dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL); if (dev) { @@ -124,16 +125,16 @@ static int __init pc110pad_init(void) outb(PC110PAD_OFF, pc110pad_io + 2); if (request_irq(pc110pad_irq, pc110pad_interrupt, 0, "pc110pad", NULL)) { - release_region(pc110pad_io, 4); printk(KERN_ERR "pc110pad: Unable to get irq %d.\n", pc110pad_irq); - return -EBUSY; + err = -EBUSY; + goto err_release_region; } - if (!(pc110pad_dev = input_allocate_device())) { - free_irq(pc110pad_irq, NULL); - release_region(pc110pad_io, 4); + pc110pad_dev = input_allocate_device(); + if (!pc110pad_dev) { printk(KERN_ERR "pc110pad: Not enough memory.\n"); - return -ENOMEM; + err = -ENOMEM; + goto err_free_irq; } pc110pad_dev->name = "IBM PC110 TouchPad"; @@ -153,9 +154,20 @@ static int __init pc110pad_init(void) pc110pad_dev->open = pc110pad_open; pc110pad_dev->close = pc110pad_close; - input_register_device(pc110pad_dev); + err = input_register_device(pc110pad_dev); + if (err) + goto err_free_dev; return 0; + + err_free_dev: + input_free_device(pc110pad_dev); + err_free_irq: + free_irq(pc110pad_irq, NULL); + err_release_region: + release_region(pc110pad_io, 4); + + return err; } static void __exit pc110pad_exit(void) diff --git a/trunk/drivers/input/mouse/psmouse-base.c b/trunk/drivers/input/mouse/psmouse-base.c index 6f9b2c7cc9c2..a0e4a033e2db 100644 --- a/trunk/drivers/input/mouse/psmouse-base.c +++ b/trunk/drivers/input/mouse/psmouse-base.c @@ -888,9 +888,10 @@ static int psmouse_poll(struct psmouse *psmouse) * psmouse_resync() attempts to re-validate current protocol. */ -static void psmouse_resync(void *p) +static void psmouse_resync(struct work_struct *work) { - struct psmouse *psmouse = p, *parent = NULL; + struct psmouse *parent = NULL, *psmouse = + container_of(work, struct psmouse, resync_work); struct serio *serio = psmouse->ps2dev.serio; psmouse_ret_t rc = PSMOUSE_GOOD_DATA; int failed = 0, enabled = 0; @@ -1102,7 +1103,7 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv) { struct psmouse *psmouse, *parent = NULL; struct input_dev *input_dev; - int retval = -ENOMEM; + int retval = 0, error = -ENOMEM; mutex_lock(&psmouse_mutex); @@ -1118,10 +1119,10 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv) psmouse = kzalloc(sizeof(struct psmouse), GFP_KERNEL); input_dev = input_allocate_device(); if (!psmouse || !input_dev) - goto out; + goto err_free; ps2_init(&psmouse->ps2dev, serio); - INIT_WORK(&psmouse->resync_work, psmouse_resync, psmouse); + INIT_WORK(&psmouse->resync_work, psmouse_resync); psmouse->dev = input_dev; snprintf(psmouse->phys, sizeof(psmouse->phys), "%s/input0", serio->phys); @@ -1129,14 +1130,13 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv) serio_set_drvdata(serio, psmouse); - retval = serio_open(serio, drv); - if (retval) - goto out; + error = serio_open(serio, drv); + if (error) + goto err_clear_drvdata; if (psmouse_probe(psmouse) < 0) { - serio_close(serio); - retval = -ENODEV; - goto out; + error = -ENODEV; + goto err_close_serio; } psmouse->rate = psmouse_rate; @@ -1150,30 +1150,44 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv) psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); psmouse_initialize(psmouse); - input_register_device(psmouse->dev); + error = input_register_device(psmouse->dev); + if (error) + goto err_protocol_disconnect; if (parent && parent->pt_activate) parent->pt_activate(parent); - sysfs_create_group(&serio->dev.kobj, &psmouse_attribute_group); + error = sysfs_create_group(&serio->dev.kobj, &psmouse_attribute_group); + if (error) + goto err_pt_deactivate; psmouse_activate(psmouse); - retval = 0; - -out: - if (retval) { - serio_set_drvdata(serio, NULL); - input_free_device(input_dev); - kfree(psmouse); - } - + out: /* If this is a pass-through port the parent needs to be re-activated */ if (parent) psmouse_activate(parent); mutex_unlock(&psmouse_mutex); return retval; + + err_pt_deactivate: + if (parent && parent->pt_deactivate) + parent->pt_deactivate(parent); + err_protocol_disconnect: + if (psmouse->disconnect) + psmouse->disconnect(psmouse); + psmouse_set_state(psmouse, PSMOUSE_IGNORE); + err_close_serio: + serio_close(serio); + err_clear_drvdata: + serio_set_drvdata(serio, NULL); + err_free: + input_free_device(input_dev); + kfree(psmouse); + + retval = error; + goto out; } @@ -1336,14 +1350,14 @@ ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *dev static ssize_t psmouse_show_int_attr(struct psmouse *psmouse, void *offset, char *buf) { - unsigned long *field = (unsigned long *)((char *)psmouse + (size_t)offset); + unsigned int *field = (unsigned int *)((char *)psmouse + (size_t)offset); - return sprintf(buf, "%lu\n", *field); + return sprintf(buf, "%u\n", *field); } static ssize_t psmouse_set_int_attr(struct psmouse *psmouse, void *offset, const char *buf, size_t count) { - unsigned long *field = (unsigned long *)((char *)psmouse + (size_t)offset); + unsigned int *field = (unsigned int *)((char *)psmouse + (size_t)offset); unsigned long value; char *rest; @@ -1351,6 +1365,9 @@ static ssize_t psmouse_set_int_attr(struct psmouse *psmouse, void *offset, const if (*rest) return -EINVAL; + if ((unsigned int)value != value) + return -EINVAL; + *field = value; return count; @@ -1365,17 +1382,20 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, co { struct serio *serio = psmouse->ps2dev.serio; struct psmouse *parent = NULL; - struct input_dev *new_dev; - const struct psmouse_protocol *proto; + struct input_dev *old_dev, *new_dev; + const struct psmouse_protocol *proto, *old_proto; + int error; int retry = 0; - if (!(proto = psmouse_protocol_by_name(buf, count))) + proto = psmouse_protocol_by_name(buf, count); + if (!proto) return -EINVAL; if (psmouse->type == proto->type) return count; - if (!(new_dev = input_allocate_device())) + new_dev = input_allocate_device(); + if (!new_dev) return -ENOMEM; while (serio->child) { @@ -1408,11 +1428,13 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, co parent->pt_deactivate(parent); } + old_dev = psmouse->dev; + old_proto = psmouse_protocol_by_type(psmouse->type); + if (psmouse->disconnect) psmouse->disconnect(psmouse); psmouse_set_state(psmouse, PSMOUSE_IGNORE); - input_unregister_device(psmouse->dev); psmouse->dev = new_dev; psmouse_set_state(psmouse, PSMOUSE_INITIALIZING); @@ -1426,7 +1448,23 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, co psmouse_initialize(psmouse); psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); - input_register_device(psmouse->dev); + error = input_register_device(psmouse->dev); + if (error) { + if (psmouse->disconnect) + psmouse->disconnect(psmouse); + + psmouse_set_state(psmouse, PSMOUSE_IGNORE); + input_free_device(new_dev); + psmouse->dev = old_dev; + psmouse_set_state(psmouse, PSMOUSE_INITIALIZING); + psmouse_switch_protocol(psmouse, old_proto); + psmouse_initialize(psmouse); + psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); + + return error; + } + + input_unregister_device(old_dev); if (parent && parent->pt_activate) parent->pt_activate(parent); @@ -1487,15 +1525,19 @@ static int psmouse_get_maxproto(char *buffer, struct kernel_param *kp) static int __init psmouse_init(void) { + int err; + kpsmoused_wq = create_singlethread_workqueue("kpsmoused"); if (!kpsmoused_wq) { printk(KERN_ERR "psmouse: failed to create kpsmoused workqueue\n"); return -ENOMEM; } - serio_register_driver(&psmouse_drv); + err = serio_register_driver(&psmouse_drv); + if (err) + destroy_workqueue(kpsmoused_wq); - return 0; + return err; } static void __exit psmouse_exit(void) diff --git a/trunk/drivers/input/mouse/rpcmouse.c b/trunk/drivers/input/mouse/rpcmouse.c index ea0468569610..fbdcfd8eb4e9 100644 --- a/trunk/drivers/input/mouse/rpcmouse.c +++ b/trunk/drivers/input/mouse/rpcmouse.c @@ -66,7 +66,10 @@ static irqreturn_t rpcmouse_irq(int irq, void *dev_id) static int __init rpcmouse_init(void) { - if (!(rpcmouse_dev = input_allocate_device())) + int err; + + rpcmouse_dev = input_allocate_device(); + if (!rpcmouse_dev) return -ENOMEM; rpcmouse_dev->name = "Acorn RiscPC Mouse"; @@ -85,13 +88,22 @@ static int __init rpcmouse_init(void) if (request_irq(IRQ_VSYNCPULSE, rpcmouse_irq, IRQF_SHARED, "rpcmouse", rpcmouse_dev)) { printk(KERN_ERR "rpcmouse: unable to allocate VSYNC interrupt\n"); - input_free_device(rpcmouse_dev); - return -EBUSY; + err = -EBUSY; + goto err_free_dev; } - input_register_device(rpcmouse_dev); + err = input_register_device(rpcmouse_dev); + if (err) + goto err_free_irq; return 0; + + err_free_irq: + free_irq(IRQ_VSYNCPULSE, rpcmouse_dev); + err_free_dev: + input_free_device(rpcmouse_dev); + + return err; } static void __exit rpcmouse_exit(void) diff --git a/trunk/drivers/input/mouse/sermouse.c b/trunk/drivers/input/mouse/sermouse.c index 2a272c5daf08..a85d74710b44 100644 --- a/trunk/drivers/input/mouse/sermouse.c +++ b/trunk/drivers/input/mouse/sermouse.c @@ -246,7 +246,7 @@ static int sermouse_connect(struct serio *serio, struct serio_driver *drv) sermouse = kzalloc(sizeof(struct sermouse), GFP_KERNEL); input_dev = input_allocate_device(); if (!sermouse || !input_dev) - goto fail; + goto fail1; sermouse->dev = input_dev; snprintf(sermouse->phys, sizeof(sermouse->phys), "%s/input0", serio->phys); @@ -275,14 +275,17 @@ static int sermouse_connect(struct serio *serio, struct serio_driver *drv) err = serio_open(serio, drv); if (err) - goto fail; + goto fail2; - input_register_device(sermouse->dev); + err = input_register_device(sermouse->dev); + if (err) + goto fail3; return 0; - fail: serio_set_drvdata(serio, NULL); - input_free_device(input_dev); + fail3: serio_close(serio); + fail2: serio_set_drvdata(serio, NULL); + fail1: input_free_device(input_dev); kfree(sermouse); return err; } @@ -348,8 +351,7 @@ static struct serio_driver sermouse_drv = { static int __init sermouse_init(void) { - serio_register_driver(&sermouse_drv); - return 0; + return serio_register_driver(&sermouse_drv); } static void __exit sermouse_exit(void) diff --git a/trunk/drivers/input/mouse/trackpoint.c b/trunk/drivers/input/mouse/trackpoint.c index ae5871a0e060..9ab5b5ea809d 100644 --- a/trunk/drivers/input/mouse/trackpoint.c +++ b/trunk/drivers/input/mouse/trackpoint.c @@ -293,6 +293,7 @@ int trackpoint_detect(struct psmouse *psmouse, int set_properties) struct ps2dev *ps2dev = &psmouse->ps2dev; unsigned char firmware_id; unsigned char button_info; + int error; if (trackpoint_start_protocol(psmouse, &firmware_id)) return -1; @@ -305,7 +306,7 @@ int trackpoint_detect(struct psmouse *psmouse, int set_properties) button_info = 0; } - psmouse->private = priv = kcalloc(1, sizeof(struct trackpoint_data), GFP_KERNEL); + psmouse->private = priv = kzalloc(sizeof(struct trackpoint_data), GFP_KERNEL); if (!priv) return -1; @@ -318,7 +319,14 @@ int trackpoint_detect(struct psmouse *psmouse, int set_properties) trackpoint_defaults(priv); trackpoint_sync(psmouse); - sysfs_create_group(&ps2dev->serio->dev.kobj, &trackpoint_attr_group); + error = sysfs_create_group(&ps2dev->serio->dev.kobj, &trackpoint_attr_group); + if (error) { + printk(KERN_ERR + "trackpoint.c: failed to create sysfs attributes, error: %d\n", + error); + kfree(priv); + return -1; + } printk(KERN_INFO "IBM TrackPoint firmware: 0x%02x, buttons: %d/%d\n", firmware_id, (button_info & 0xf0) >> 4, button_info & 0x0f); diff --git a/trunk/drivers/input/mouse/vsxxxaa.c b/trunk/drivers/input/mouse/vsxxxaa.c index ffdb50eee93d..c3d64fcc858d 100644 --- a/trunk/drivers/input/mouse/vsxxxaa.c +++ b/trunk/drivers/input/mouse/vsxxxaa.c @@ -497,7 +497,7 @@ vsxxxaa_connect (struct serio *serio, struct serio_driver *drv) mouse = kzalloc (sizeof (struct vsxxxaa), GFP_KERNEL); input_dev = input_allocate_device (); if (!mouse || !input_dev) - goto fail; + goto fail1; mouse->dev = input_dev; mouse->serio = serio; @@ -527,7 +527,7 @@ vsxxxaa_connect (struct serio *serio, struct serio_driver *drv) err = serio_open (serio, drv); if (err) - goto fail; + goto fail2; /* * Request selftest. Standard packet format and differential @@ -535,12 +535,15 @@ vsxxxaa_connect (struct serio *serio, struct serio_driver *drv) */ serio->write (serio, 'T'); /* Test */ - input_register_device (input_dev); + err = input_register_device (input_dev); + if (err) + goto fail3; return 0; - fail: serio_set_drvdata (serio, NULL); - input_free_device (input_dev); + fail3: serio_close (serio); + fail2: serio_set_drvdata (serio, NULL); + fail1: input_free_device (input_dev); kfree (mouse); return err; } @@ -571,8 +574,7 @@ static struct serio_driver vsxxxaa_drv = { static int __init vsxxxaa_init (void) { - serio_register_driver(&vsxxxaa_drv); - return 0; + return serio_register_driver(&vsxxxaa_drv); } static void __exit diff --git a/trunk/drivers/input/mousedev.c b/trunk/drivers/input/mousedev.c index a22a74a2a3dc..664bcc8116fc 100644 --- a/trunk/drivers/input/mousedev.c +++ b/trunk/drivers/input/mousedev.c @@ -196,12 +196,12 @@ static void mousedev_key_event(struct mousedev *mousedev, unsigned int code, int switch (code) { case BTN_TOUCH: case BTN_0: - case BTN_FORWARD: case BTN_LEFT: index = 0; break; case BTN_STYLUS: case BTN_1: case BTN_RIGHT: index = 1; break; case BTN_2: + case BTN_FORWARD: case BTN_STYLUS2: case BTN_MIDDLE: index = 2; break; case BTN_3: diff --git a/trunk/drivers/input/serio/i8042-x86ia64io.h b/trunk/drivers/input/serio/i8042-x86ia64io.h index 8738edda6610..d36bd5475b6d 100644 --- a/trunk/drivers/input/serio/i8042-x86ia64io.h +++ b/trunk/drivers/input/serio/i8042-x86ia64io.h @@ -110,6 +110,13 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "P7010"), }, }, + { + .ident = "Fujitsu Lifebook P7010", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), + DMI_MATCH(DMI_PRODUCT_NAME, "0000000000"), + }, + }, { .ident = "Fujitsu Lifebook P5020D", .matches = { diff --git a/trunk/drivers/input/serio/i8042.c b/trunk/drivers/input/serio/i8042.c index 7e3141f37e32..debe9445488c 100644 --- a/trunk/drivers/input/serio/i8042.c +++ b/trunk/drivers/input/serio/i8042.c @@ -255,25 +255,10 @@ static int i8042_kbd_write(struct serio *port, unsigned char c) static int i8042_aux_write(struct serio *serio, unsigned char c) { struct i8042_port *port = serio->port_data; - int retval; - -/* - * Send the byte out. - */ - - if (port->mux == -1) - retval = i8042_command(&c, I8042_CMD_AUX_SEND); - else - retval = i8042_command(&c, I8042_CMD_MUX_SEND + port->mux); - -/* - * Make sure the interrupt happens and the character is received even - * in the case the IRQ isn't wired, so that we can receive further - * characters later. - */ - i8042_interrupt(0, NULL); - return retval; + return i8042_command(&c, port->mux == -1 ? + I8042_CMD_AUX_SEND : + I8042_CMD_MUX_SEND + port->mux); } /* @@ -337,23 +322,27 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id) dfl = 0; if (str & I8042_STR_MUXERR) { dbg("MUX error, status is %02x, data is %02x", str, data); - switch (data) { - default: /* * When MUXERR condition is signalled the data register can only contain * 0xfd, 0xfe or 0xff if implementation follows the spec. Unfortunately - * it is not always the case. Some KBC just get confused which port the - * data came from and signal error leaving the data intact. They _do not_ - * revert to legacy mode (actually I've never seen KBC reverting to legacy - * mode yet, when we see one we'll add proper handling). - * Anyway, we will assume that the data came from the same serio last byte + * it is not always the case. Some KBCs also report 0xfc when there is + * nothing connected to the port while others sometimes get confused which + * port the data came from and signal error leaving the data intact. They + * _do not_ revert to legacy mode (actually I've never seen KBC reverting + * to legacy mode yet, when we see one we'll add proper handling). + * Anyway, we process 0xfc, 0xfd, 0xfe and 0xff as timeouts, and for the + * rest assume that the data came from the same serio last byte * was transmitted (if transmission happened not too long ago). */ + + switch (data) { + default: if (time_before(jiffies, last_transmit + HZ/10)) { str = last_str; break; } /* fall through - report timeout */ + case 0xfc: case 0xfd: case 0xfe: dfl = SERIO_TIMEOUT; data = 0xfe; break; case 0xff: dfl = SERIO_PARITY; data = 0xfe; break; diff --git a/trunk/drivers/input/serio/libps2.c b/trunk/drivers/input/serio/libps2.c index e5b1b60757bb..b3e84d3bb7f7 100644 --- a/trunk/drivers/input/serio/libps2.c +++ b/trunk/drivers/input/serio/libps2.c @@ -251,9 +251,9 @@ EXPORT_SYMBOL(ps2_command); * ps2_schedule_command(), to a PS/2 device (keyboard, mouse, etc.) */ -static void ps2_execute_scheduled_command(void *data) +static void ps2_execute_scheduled_command(struct work_struct *work) { - struct ps2work *ps2work = data; + struct ps2work *ps2work = container_of(work, struct ps2work, work); ps2_command(ps2work->ps2dev, ps2work->param, ps2work->command); kfree(ps2work); @@ -278,7 +278,7 @@ int ps2_schedule_command(struct ps2dev *ps2dev, unsigned char *param, int comman ps2work->ps2dev = ps2dev; ps2work->command = command; memcpy(ps2work->param, param, send); - INIT_WORK(&ps2work->work, ps2_execute_scheduled_command, ps2work); + INIT_WORK(&ps2work->work, ps2_execute_scheduled_command); if (!schedule_work(&ps2work->work)) { kfree(ps2work); diff --git a/trunk/drivers/input/serio/serio.c b/trunk/drivers/input/serio/serio.c index 211943f85cb6..f0ce822c1028 100644 --- a/trunk/drivers/input/serio/serio.c +++ b/trunk/drivers/input/serio/serio.c @@ -35,6 +35,7 @@ #include #include #include +#include MODULE_AUTHOR("Vojtech Pavlik "); MODULE_DESCRIPTION("Serio abstraction core"); @@ -44,8 +45,7 @@ EXPORT_SYMBOL(serio_interrupt); EXPORT_SYMBOL(__serio_register_port); EXPORT_SYMBOL(serio_unregister_port); EXPORT_SYMBOL(serio_unregister_child_port); -EXPORT_SYMBOL(__serio_unregister_port_delayed); -EXPORT_SYMBOL(__serio_register_driver); +EXPORT_SYMBOL(serio_register_driver); EXPORT_SYMBOL(serio_unregister_driver); EXPORT_SYMBOL(serio_open); EXPORT_SYMBOL(serio_close); @@ -62,11 +62,10 @@ static LIST_HEAD(serio_list); static struct bus_type serio_bus; -static void serio_add_driver(struct serio_driver *drv); static void serio_add_port(struct serio *serio); -static void serio_destroy_port(struct serio *serio); static void serio_reconnect_port(struct serio *serio); static void serio_disconnect_port(struct serio *serio); +static void serio_attach_driver(struct serio_driver *drv); static int serio_connect_driver(struct serio *serio, struct serio_driver *drv) { @@ -170,11 +169,10 @@ static void serio_find_driver(struct serio *serio) */ enum serio_event_type { - SERIO_RESCAN, - SERIO_RECONNECT, + SERIO_RESCAN_PORT, + SERIO_RECONNECT_PORT, SERIO_REGISTER_PORT, - SERIO_UNREGISTER_PORT, - SERIO_REGISTER_DRIVER, + SERIO_ATTACH_DRIVER, }; struct serio_event { @@ -189,11 +187,12 @@ static LIST_HEAD(serio_event_list); static DECLARE_WAIT_QUEUE_HEAD(serio_wait); static struct task_struct *serio_task; -static void serio_queue_event(void *object, struct module *owner, - enum serio_event_type event_type) +static int serio_queue_event(void *object, struct module *owner, + enum serio_event_type event_type) { unsigned long flags; struct serio_event *event; + int retval = 0; spin_lock_irqsave(&serio_event_lock, flags); @@ -212,24 +211,34 @@ static void serio_queue_event(void *object, struct module *owner, } } - if ((event = kmalloc(sizeof(struct serio_event), GFP_ATOMIC))) { - if (!try_module_get(owner)) { - printk(KERN_WARNING "serio: Can't get module reference, dropping event %d\n", event_type); - kfree(event); - goto out; - } - - event->type = event_type; - event->object = object; - event->owner = owner; + event = kmalloc(sizeof(struct serio_event), GFP_ATOMIC); + if (!event) { + printk(KERN_ERR + "serio: Not enough memory to queue event %d\n", + event_type); + retval = -ENOMEM; + goto out; + } - list_add_tail(&event->node, &serio_event_list); - wake_up(&serio_wait); - } else { - printk(KERN_ERR "serio: Not enough memory to queue event %d\n", event_type); + if (!try_module_get(owner)) { + printk(KERN_WARNING + "serio: Can't get module reference, dropping event %d\n", + event_type); + kfree(event); + retval = -EINVAL; + goto out; } + + event->type = event_type; + event->object = object; + event->owner = owner; + + list_add_tail(&event->node, &serio_event_list); + wake_up(&serio_wait); + out: spin_unlock_irqrestore(&serio_event_lock, flags); + return retval; } static void serio_free_event(struct serio_event *event) @@ -307,22 +316,17 @@ static void serio_handle_event(void) serio_add_port(event->object); break; - case SERIO_UNREGISTER_PORT: - serio_disconnect_port(event->object); - serio_destroy_port(event->object); - break; - - case SERIO_RECONNECT: + case SERIO_RECONNECT_PORT: serio_reconnect_port(event->object); break; - case SERIO_RESCAN: + case SERIO_RESCAN_PORT: serio_disconnect_port(event->object); serio_find_driver(event->object); break; - case SERIO_REGISTER_DRIVER: - serio_add_driver(event->object); + case SERIO_ATTACH_DRIVER: + serio_attach_driver(event->object); break; default: @@ -674,12 +678,12 @@ static void serio_disconnect_port(struct serio *serio) void serio_rescan(struct serio *serio) { - serio_queue_event(serio, NULL, SERIO_RESCAN); + serio_queue_event(serio, NULL, SERIO_RESCAN_PORT); } void serio_reconnect(struct serio *serio) { - serio_queue_event(serio, NULL, SERIO_RECONNECT); + serio_queue_event(serio, NULL, SERIO_RECONNECT_PORT); } /* @@ -716,16 +720,6 @@ void serio_unregister_child_port(struct serio *serio) mutex_unlock(&serio_mutex); } -/* - * Submits register request to kseriod for subsequent execution. - * Can be used when it is not obvious whether the serio_mutex is - * taken or not and when delayed execution is feasible. - */ -void __serio_unregister_port_delayed(struct serio *serio, struct module *owner) -{ - serio_queue_event(serio, owner, SERIO_UNREGISTER_PORT); -} - /* * Serio driver operations @@ -784,28 +778,52 @@ static int serio_driver_remove(struct device *dev) return 0; } -static struct bus_type serio_bus = { - .name = "serio", - .probe = serio_driver_probe, - .remove = serio_driver_remove, -}; - -static void serio_add_driver(struct serio_driver *drv) +static void serio_attach_driver(struct serio_driver *drv) { int error; - error = driver_register(&drv->driver); + error = driver_attach(&drv->driver); if (error) - printk(KERN_ERR - "serio: driver_register() failed for %s, error: %d\n", + printk(KERN_WARNING + "serio: driver_attach() failed for %s with error %d\n", drv->driver.name, error); } -void __serio_register_driver(struct serio_driver *drv, struct module *owner) +int serio_register_driver(struct serio_driver *drv) { + int manual_bind = drv->manual_bind; + int error; + drv->driver.bus = &serio_bus; - serio_queue_event(drv, owner, SERIO_REGISTER_DRIVER); + /* + * Temporarily disable automatic binding because probing + * takes long time and we are better off doing it in kseriod + */ + drv->manual_bind = 1; + + error = driver_register(&drv->driver); + if (error) { + printk(KERN_ERR + "serio: driver_register() failed for %s, error: %d\n", + drv->driver.name, error); + return error; + } + + /* + * Restore original bind mode and let kseriod bind the + * driver to free ports + */ + if (!manual_bind) { + drv->manual_bind = 0; + error = serio_queue_event(drv, NULL, SERIO_ATTACH_DRIVER); + if (error) { + driver_unregister(&drv->driver); + return error; + } + } + + return 0; } void serio_unregister_driver(struct serio_driver *drv) @@ -946,15 +964,21 @@ irqreturn_t serio_interrupt(struct serio *serio, return ret; } +static struct bus_type serio_bus = { + .name = "serio", + .dev_attrs = serio_device_attrs, + .drv_attrs = serio_driver_attrs, + .match = serio_bus_match, + .uevent = serio_uevent, + .probe = serio_driver_probe, + .remove = serio_driver_remove, + .resume = serio_resume, +}; + static int __init serio_init(void) { int error; - serio_bus.dev_attrs = serio_device_attrs; - serio_bus.drv_attrs = serio_driver_attrs; - serio_bus.match = serio_bus_match; - serio_bus.uevent = serio_uevent; - serio_bus.resume = serio_resume; error = bus_register(&serio_bus); if (error) { printk(KERN_ERR "serio: failed to register serio bus, error: %d\n", error); diff --git a/trunk/drivers/input/serio/serio_raw.c b/trunk/drivers/input/serio/serio_raw.c index 7c8d0399ae82..088ebc348ba3 100644 --- a/trunk/drivers/input/serio/serio_raw.c +++ b/trunk/drivers/input/serio/serio_raw.c @@ -389,8 +389,7 @@ static struct serio_driver serio_raw_drv = { static int __init serio_raw_init(void) { - serio_register_driver(&serio_raw_drv); - return 0; + return serio_register_driver(&serio_raw_drv); } static void __exit serio_raw_exit(void) diff --git a/trunk/drivers/input/touchscreen/Kconfig b/trunk/drivers/input/touchscreen/Kconfig index 9418bbe47072..29ca0ab0acb8 100644 --- a/trunk/drivers/input/touchscreen/Kconfig +++ b/trunk/drivers/input/touchscreen/Kconfig @@ -144,4 +144,19 @@ config TOUCHSCREEN_TOUCHWIN To compile this driver as a module, choose M here: the module will be called touchwin. +config TOUCHSCREEN_UCB1400 + tristate "Philips UCB1400 touchscreen" + select SND_AC97_BUS + help + This enables support for the Philips UCB1400 touchscreen interface. + The UCB1400 is an AC97 audio codec. The touchscreen interface + will be initialized only after the ALSA subsystem has been + brought up and the UCB1400 detected. You therefore have to + configure ALSA support as well (either built-in or modular, + independently of whether this driver is itself built-in or + modular) for this driver to work. + + To compile this driver as a module, choose M here: the + module will be called ucb1400_ts. + endif diff --git a/trunk/drivers/input/touchscreen/Makefile b/trunk/drivers/input/touchscreen/Makefile index 1abb8f10d608..30e6e2217a15 100644 --- a/trunk/drivers/input/touchscreen/Makefile +++ b/trunk/drivers/input/touchscreen/Makefile @@ -15,3 +15,4 @@ obj-$(CONFIG_TOUCHSCREEN_HP600) += hp680_ts_input.o obj-$(CONFIG_TOUCHSCREEN_PENMOUNT) += penmount.o obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN) += touchwin.o +obj-$(CONFIG_TOUCHSCREEN_UCB1400) += ucb1400_ts.o diff --git a/trunk/drivers/input/touchscreen/ads7846.c b/trunk/drivers/input/touchscreen/ads7846.c index f56d6a0f0624..c6164b6f476a 100644 --- a/trunk/drivers/input/touchscreen/ads7846.c +++ b/trunk/drivers/input/touchscreen/ads7846.c @@ -76,6 +76,7 @@ struct ads7846 { char phys[32]; struct spi_device *spi; + struct attribute_group *attr_group; u16 model; u16 vref_delay_usecs; u16 x_plate_ohms; @@ -189,7 +190,7 @@ static int ads7846_read12_ser(struct device *dev, unsigned command) { struct spi_device *spi = to_spi_device(dev); struct ads7846 *ts = dev_get_drvdata(dev); - struct ser_req *req = kzalloc(sizeof *req, SLAB_KERNEL); + struct ser_req *req = kzalloc(sizeof *req, GFP_KERNEL); int status; int sample; int i; @@ -317,6 +318,48 @@ static ssize_t ads7846_disable_store(struct device *dev, static DEVICE_ATTR(disable, 0664, ads7846_disable_show, ads7846_disable_store); +static struct attribute *ads7846_attributes[] = { + &dev_attr_temp0.attr, + &dev_attr_temp1.attr, + &dev_attr_vbatt.attr, + &dev_attr_vaux.attr, + &dev_attr_pen_down.attr, + &dev_attr_disable.attr, + NULL, +}; + +static struct attribute_group ads7846_attr_group = { + .attrs = ads7846_attributes, +}; + +/* + * ads7843/7845 don't have temperature sensors, and + * use the other sensors a bit differently too + */ + +static struct attribute *ads7843_attributes[] = { + &dev_attr_vbatt.attr, + &dev_attr_vaux.attr, + &dev_attr_pen_down.attr, + &dev_attr_disable.attr, + NULL, +}; + +static struct attribute_group ads7843_attr_group = { + .attrs = ads7843_attributes, +}; + +static struct attribute *ads7845_attributes[] = { + &dev_attr_vaux.attr, + &dev_attr_pen_down.attr, + &dev_attr_disable.attr, + NULL, +}; + +static struct attribute_group ads7845_attr_group = { + .attrs = ads7845_attributes, +}; + /*--------------------------------------------------------------------------*/ /* @@ -788,38 +831,30 @@ static int __devinit ads7846_probe(struct spi_device *spi) (void) ads7846_read12_ser(&spi->dev, READ_12BIT_SER(vaux) | ADS_PD10_ALL_ON); - /* ads7843/7845 don't have temperature sensors, and - * use the other sensors a bit differently too - */ - if (ts->model == 7846) { - device_create_file(&spi->dev, &dev_attr_temp0); - device_create_file(&spi->dev, &dev_attr_temp1); + switch (ts->model) { + case 7846: + ts->attr_group = &ads7846_attr_group; + break; + case 7845: + ts->attr_group = &ads7845_attr_group; + break; + default: + ts->attr_group = &ads7843_attr_group; + break; } - if (ts->model != 7845) - device_create_file(&spi->dev, &dev_attr_vbatt); - device_create_file(&spi->dev, &dev_attr_vaux); - - device_create_file(&spi->dev, &dev_attr_pen_down); - - device_create_file(&spi->dev, &dev_attr_disable); + err = sysfs_create_group(&spi->dev.kobj, ts->attr_group); + if (err) + goto err_free_irq; err = input_register_device(input_dev); if (err) - goto err_remove_attr; + goto err_remove_attr_group; return 0; - err_remove_attr: - device_remove_file(&spi->dev, &dev_attr_disable); - device_remove_file(&spi->dev, &dev_attr_pen_down); - if (ts->model == 7846) { - device_remove_file(&spi->dev, &dev_attr_temp1); - device_remove_file(&spi->dev, &dev_attr_temp0); - } - if (ts->model != 7845) - device_remove_file(&spi->dev, &dev_attr_vbatt); - device_remove_file(&spi->dev, &dev_attr_vaux); - + err_remove_attr_group: + sysfs_remove_group(&spi->dev.kobj, ts->attr_group); + err_free_irq: free_irq(spi->irq, ts); err_free_mem: input_free_device(input_dev); @@ -835,15 +870,7 @@ static int __devexit ads7846_remove(struct spi_device *spi) ads7846_suspend(spi, PMSG_SUSPEND); - device_remove_file(&spi->dev, &dev_attr_disable); - device_remove_file(&spi->dev, &dev_attr_pen_down); - if (ts->model == 7846) { - device_remove_file(&spi->dev, &dev_attr_temp1); - device_remove_file(&spi->dev, &dev_attr_temp0); - } - if (ts->model != 7845) - device_remove_file(&spi->dev, &dev_attr_vbatt); - device_remove_file(&spi->dev, &dev_attr_vaux); + sysfs_remove_group(&spi->dev.kobj, ts->attr_group); free_irq(ts->spi->irq, ts); /* suspend left the IRQ disabled */ diff --git a/trunk/drivers/input/touchscreen/corgi_ts.c b/trunk/drivers/input/touchscreen/corgi_ts.c index 66121f6a89ad..e2945582828e 100644 --- a/trunk/drivers/input/touchscreen/corgi_ts.c +++ b/trunk/drivers/input/touchscreen/corgi_ts.c @@ -175,17 +175,19 @@ static int read_xydata(struct corgi_ts *corgi_ts) static void new_data(struct corgi_ts *corgi_ts) { + struct input_dev *dev = corgi_ts->input; + if (corgi_ts->power_mode != PWR_MODE_ACTIVE) return; if (!corgi_ts->tc.pressure && corgi_ts->pendown == 0) return; - input_report_abs(corgi_ts->input, ABS_X, corgi_ts->tc.x); - input_report_abs(corgi_ts->input, ABS_Y, corgi_ts->tc.y); - input_report_abs(corgi_ts->input, ABS_PRESSURE, corgi_ts->tc.pressure); - input_report_key(corgi_ts->input, BTN_TOUCH, (corgi_ts->pendown != 0)); - input_sync(corgi_ts->input); + input_report_abs(dev, ABS_X, corgi_ts->tc.x); + input_report_abs(dev, ABS_Y, corgi_ts->tc.y); + input_report_abs(dev, ABS_PRESSURE, corgi_ts->tc.pressure); + input_report_key(dev, BTN_TOUCH, corgi_ts->pendown); + input_sync(dev); } static void ts_interrupt_main(struct corgi_ts *corgi_ts, int isTimer) @@ -219,12 +221,14 @@ static void ts_interrupt_main(struct corgi_ts *corgi_ts, int isTimer) static void corgi_ts_timer(unsigned long data) { struct corgi_ts *corgits_data = (struct corgi_ts *) data; + ts_interrupt_main(corgits_data, 1); } static irqreturn_t ts_interrupt(int irq, void *dev_id) { struct corgi_ts *corgits_data = dev_id; + ts_interrupt_main(corgits_data, 0); return IRQ_HANDLED; } @@ -272,7 +276,7 @@ static int __init corgits_probe(struct platform_device *pdev) corgi_ts = kzalloc(sizeof(struct corgi_ts), GFP_KERNEL); input_dev = input_allocate_device(); if (!corgi_ts || !input_dev) - goto fail; + goto fail1; platform_set_drvdata(pdev, corgi_ts); @@ -281,7 +285,7 @@ static int __init corgits_probe(struct platform_device *pdev) if (corgi_ts->irq_gpio < 0) { err = -ENODEV; - goto fail; + goto fail1; } corgi_ts->input = input_dev; @@ -319,10 +323,12 @@ static int __init corgits_probe(struct platform_device *pdev) if (request_irq(corgi_ts->irq_gpio, ts_interrupt, IRQF_DISABLED, "ts", corgi_ts)) { err = -EBUSY; - goto fail; + goto fail1; } - input_register_device(corgi_ts->input); + err = input_register_device(corgi_ts->input); + if (err) + goto fail2; corgi_ts->power_mode = PWR_MODE_ACTIVE; @@ -331,17 +337,17 @@ static int __init corgits_probe(struct platform_device *pdev) return 0; - fail: input_free_device(input_dev); + fail2: free_irq(corgi_ts->irq_gpio, corgi_ts); + fail1: input_free_device(input_dev); kfree(corgi_ts); return err; - } static int corgits_remove(struct platform_device *pdev) { struct corgi_ts *corgi_ts = platform_get_drvdata(pdev); - free_irq(corgi_ts->irq_gpio, NULL); + free_irq(corgi_ts->irq_gpio, corgi_ts); del_timer_sync(&corgi_ts->timer); corgi_ts->machinfo->put_hsync(); input_unregister_device(corgi_ts->input); diff --git a/trunk/drivers/input/touchscreen/elo.c b/trunk/drivers/input/touchscreen/elo.c index 913e1b73bb0e..9d61cd133d01 100644 --- a/trunk/drivers/input/touchscreen/elo.c +++ b/trunk/drivers/input/touchscreen/elo.c @@ -397,8 +397,7 @@ static struct serio_driver elo_drv = { static int __init elo_init(void) { - serio_register_driver(&elo_drv); - return 0; + return serio_register_driver(&elo_drv); } static void __exit elo_exit(void) diff --git a/trunk/drivers/input/touchscreen/gunze.c b/trunk/drivers/input/touchscreen/gunze.c index 817c2198933d..9157eb148e84 100644 --- a/trunk/drivers/input/touchscreen/gunze.c +++ b/trunk/drivers/input/touchscreen/gunze.c @@ -123,7 +123,7 @@ static int gunze_connect(struct serio *serio, struct serio_driver *drv) input_dev = input_allocate_device(); if (!gunze || !input_dev) { err = -ENOMEM; - goto fail; + goto fail1; } gunze->serio = serio; @@ -146,13 +146,17 @@ static int gunze_connect(struct serio *serio, struct serio_driver *drv) err = serio_open(serio, drv); if (err) - goto fail; + goto fail2; + + err = input_register_device(gunze->dev); + if (err) + goto fail3; - input_register_device(gunze->dev); return 0; - fail: serio_set_drvdata(serio, NULL); - input_free_device(input_dev); + fail3: serio_close(serio); + fail2: serio_set_drvdata(serio, NULL); + fail1: input_free_device(input_dev); kfree(gunze); return err; } @@ -190,8 +194,7 @@ static struct serio_driver gunze_drv = { static int __init gunze_init(void) { - serio_register_driver(&gunze_drv); - return 0; + return serio_register_driver(&gunze_drv); } static void __exit gunze_exit(void) diff --git a/trunk/drivers/input/touchscreen/h3600_ts_input.c b/trunk/drivers/input/touchscreen/h3600_ts_input.c index d9e61ee05ea9..c4116d4f64e7 100644 --- a/trunk/drivers/input/touchscreen/h3600_ts_input.c +++ b/trunk/drivers/input/touchscreen/h3600_ts_input.c @@ -478,8 +478,7 @@ static struct serio_driver h3600ts_drv = { static int __init h3600ts_init(void) { - serio_register_driver(&h3600ts_drv); - return 0; + return serio_register_driver(&h3600ts_drv); } static void __exit h3600ts_exit(void) diff --git a/trunk/drivers/input/touchscreen/hp680_ts_input.c b/trunk/drivers/input/touchscreen/hp680_ts_input.c index 58fca316786c..249087472740 100644 --- a/trunk/drivers/input/touchscreen/hp680_ts_input.c +++ b/trunk/drivers/input/touchscreen/hp680_ts_input.c @@ -76,38 +76,47 @@ static irqreturn_t hp680_ts_interrupt(int irq, void *dev) static int __init hp680_ts_init(void) { + int err; + hp680_ts_dev = input_allocate_device(); if (!hp680_ts_dev) return -ENOMEM; hp680_ts_dev->evbit[0] = BIT(EV_ABS) | BIT(EV_KEY); - hp680_ts_dev->absbit[0] = BIT(ABS_X) | BIT(ABS_Y); hp680_ts_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); - hp680_ts_dev->absmin[ABS_X] = HP680_TS_ABS_X_MIN; - hp680_ts_dev->absmin[ABS_Y] = HP680_TS_ABS_Y_MIN; - hp680_ts_dev->absmax[ABS_X] = HP680_TS_ABS_X_MAX; - hp680_ts_dev->absmax[ABS_Y] = HP680_TS_ABS_Y_MAX; + input_set_abs_params(hp680_ts_dev, ABS_X, + HP680_TS_ABS_X_MIN, HP680_TS_ABS_X_MAX, 0, 0); + input_set_abs_params(hp680_ts_dev, ABS_Y, + HP680_TS_ABS_Y_MIN, HP680_TS_ABS_Y_MAX, 0, 0); hp680_ts_dev->name = "HP Jornada touchscreen"; hp680_ts_dev->phys = "hp680_ts/input0"; - input_register_device(hp680_ts_dev); - if (request_irq(HP680_TS_IRQ, hp680_ts_interrupt, IRQF_DISABLED, MODNAME, 0) < 0) { printk(KERN_ERR "hp680_touchscreen.c: Can't allocate irq %d\n", HP680_TS_IRQ); - input_unregister_device(hp680_ts_dev); - return -EBUSY; + err = -EBUSY; + goto fail1; } + err = input_register_device(hp680_ts_dev); + if (err) + goto fail2; + return 0; + + fail2: free_irq(HP680_TS_IRQ, NULL); + cancel_delayed_work(&work); + flush_scheduled_work(); + fail1: input_free_device(hp680_ts_dev); + return err; } static void __exit hp680_ts_exit(void) { - free_irq(HP680_TS_IRQ, 0); + free_irq(HP680_TS_IRQ, NULL); cancel_delayed_work(&work); flush_scheduled_work(); input_unregister_device(hp680_ts_dev); diff --git a/trunk/drivers/input/touchscreen/mk712.c b/trunk/drivers/input/touchscreen/mk712.c index 4cbcaa6a71e5..44140feeffc5 100644 --- a/trunk/drivers/input/touchscreen/mk712.c +++ b/trunk/drivers/input/touchscreen/mk712.c @@ -96,15 +96,13 @@ static irqreturn_t mk712_interrupt(int irq, void *dev_id) goto end; } - if (~status & MK712_STATUS_TOUCH) - { + if (~status & MK712_STATUS_TOUCH) { debounce = 1; input_report_key(mk712_dev, BTN_TOUCH, 0); goto end; } - if (debounce) - { + if (debounce) { debounce = 0; goto end; } @@ -113,8 +111,7 @@ static irqreturn_t mk712_interrupt(int irq, void *dev_id) input_report_abs(mk712_dev, ABS_X, last_x); input_report_abs(mk712_dev, ABS_Y, last_y); -end: - + end: last_x = inw(mk712_io + MK712_X) & 0x0fff; last_y = inw(mk712_io + MK712_Y) & 0x0fff; input_sync(mk712_dev); @@ -169,13 +166,14 @@ static int __init mk712_init(void) (inw(mk712_io + MK712_STATUS) & 0xf333)) { printk(KERN_WARNING "mk712: device not present\n"); err = -ENODEV; - goto fail; + goto fail1; } - if (!(mk712_dev = input_allocate_device())) { + mk712_dev = input_allocate_device(); + if (!mk712_dev) { printk(KERN_ERR "mk712: not enough memory\n"); err = -ENOMEM; - goto fail; + goto fail1; } mk712_dev->name = "ICS MicroClock MK712 TouchScreen"; @@ -196,13 +194,17 @@ static int __init mk712_init(void) if (request_irq(mk712_irq, mk712_interrupt, 0, "mk712", mk712_dev)) { printk(KERN_WARNING "mk712: unable to get IRQ\n"); err = -EBUSY; - goto fail; + goto fail1; } - input_register_device(mk712_dev); + err = input_register_device(mk712_dev); + if (err) + goto fail2; + return 0; - fail: input_free_device(mk712_dev); + fail2: free_irq(mk712_irq, mk712_dev); + fail1: input_free_device(mk712_dev); release_region(mk712_io, 8); return err; } diff --git a/trunk/drivers/input/touchscreen/mtouch.c b/trunk/drivers/input/touchscreen/mtouch.c index 3b4c61664b63..c3c2d735d0ec 100644 --- a/trunk/drivers/input/touchscreen/mtouch.c +++ b/trunk/drivers/input/touchscreen/mtouch.c @@ -137,7 +137,7 @@ static int mtouch_connect(struct serio *serio, struct serio_driver *drv) input_dev = input_allocate_device(); if (!mtouch || !input_dev) { err = -ENOMEM; - goto fail; + goto fail1; } mtouch->serio = serio; @@ -160,14 +160,17 @@ static int mtouch_connect(struct serio *serio, struct serio_driver *drv) err = serio_open(serio, drv); if (err) - goto fail; + goto fail2; - input_register_device(mtouch->dev); + err = input_register_device(mtouch->dev); + if (err) + goto fail3; return 0; - fail: serio_set_drvdata(serio, NULL); - input_free_device(input_dev); + fail3: serio_close(serio); + fail2: serio_set_drvdata(serio, NULL); + fail1: input_free_device(input_dev); kfree(mtouch); return err; } @@ -205,8 +208,7 @@ static struct serio_driver mtouch_drv = { static int __init mtouch_init(void) { - serio_register_driver(&mtouch_drv); - return 0; + return serio_register_driver(&mtouch_drv); } static void __exit mtouch_exit(void) diff --git a/trunk/drivers/input/touchscreen/penmount.c b/trunk/drivers/input/touchscreen/penmount.c index 6c7d0c2c76cc..bd2767991ae9 100644 --- a/trunk/drivers/input/touchscreen/penmount.c +++ b/trunk/drivers/input/touchscreen/penmount.c @@ -171,8 +171,7 @@ static struct serio_driver pm_drv = { static int __init pm_init(void) { - serio_register_driver(&pm_drv); - return 0; + return serio_register_driver(&pm_drv); } static void __exit pm_exit(void) diff --git a/trunk/drivers/input/touchscreen/touchright.c b/trunk/drivers/input/touchscreen/touchright.c index c74f74e57af0..35ba46c6ad2d 100644 --- a/trunk/drivers/input/touchscreen/touchright.c +++ b/trunk/drivers/input/touchscreen/touchright.c @@ -182,8 +182,7 @@ static struct serio_driver tr_drv = { static int __init tr_init(void) { - serio_register_driver(&tr_drv); - return 0; + return serio_register_driver(&tr_drv); } static void __exit tr_exit(void) diff --git a/trunk/drivers/input/touchscreen/touchwin.c b/trunk/drivers/input/touchscreen/touchwin.c index 9911820fa2fe..4dc073dacabb 100644 --- a/trunk/drivers/input/touchscreen/touchwin.c +++ b/trunk/drivers/input/touchscreen/touchwin.c @@ -189,8 +189,7 @@ static struct serio_driver tw_drv = { static int __init tw_init(void) { - serio_register_driver(&tw_drv); - return 0; + return serio_register_driver(&tw_drv); } static void __exit tw_exit(void) diff --git a/trunk/drivers/input/touchscreen/ucb1400_ts.c b/trunk/drivers/input/touchscreen/ucb1400_ts.c new file mode 100644 index 000000000000..4358a0a78eaa --- /dev/null +++ b/trunk/drivers/input/touchscreen/ucb1400_ts.c @@ -0,0 +1,579 @@ +/* + * Philips UCB1400 touchscreen driver + * + * Author: Nicolas Pitre + * Created: September 25, 2006 + * Copyright: MontaVista Software, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This code is heavily based on ucb1x00-*.c copyrighted by Russell King + * covering the UCB1100, UCB1200 and UCB1300.. Support for the UCB1400 has + * been made separate from ucb1x00-core/ucb1x00-ts on Russell's request. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + + +/* + * Interesting UCB1400 AC-link registers + */ + +#define UCB_IE_RIS 0x5e +#define UCB_IE_FAL 0x60 +#define UCB_IE_STATUS 0x62 +#define UCB_IE_CLEAR 0x62 +#define UCB_IE_ADC (1 << 11) +#define UCB_IE_TSPX (1 << 12) + +#define UCB_TS_CR 0x64 +#define UCB_TS_CR_TSMX_POW (1 << 0) +#define UCB_TS_CR_TSPX_POW (1 << 1) +#define UCB_TS_CR_TSMY_POW (1 << 2) +#define UCB_TS_CR_TSPY_POW (1 << 3) +#define UCB_TS_CR_TSMX_GND (1 << 4) +#define UCB_TS_CR_TSPX_GND (1 << 5) +#define UCB_TS_CR_TSMY_GND (1 << 6) +#define UCB_TS_CR_TSPY_GND (1 << 7) +#define UCB_TS_CR_MODE_INT (0 << 8) +#define UCB_TS_CR_MODE_PRES (1 << 8) +#define UCB_TS_CR_MODE_POS (2 << 8) +#define UCB_TS_CR_BIAS_ENA (1 << 11) +#define UCB_TS_CR_TSPX_LOW (1 << 12) +#define UCB_TS_CR_TSMX_LOW (1 << 13) + +#define UCB_ADC_CR 0x66 +#define UCB_ADC_SYNC_ENA (1 << 0) +#define UCB_ADC_VREFBYP_CON (1 << 1) +#define UCB_ADC_INP_TSPX (0 << 2) +#define UCB_ADC_INP_TSMX (1 << 2) +#define UCB_ADC_INP_TSPY (2 << 2) +#define UCB_ADC_INP_TSMY (3 << 2) +#define UCB_ADC_INP_AD0 (4 << 2) +#define UCB_ADC_INP_AD1 (5 << 2) +#define UCB_ADC_INP_AD2 (6 << 2) +#define UCB_ADC_INP_AD3 (7 << 2) +#define UCB_ADC_EXT_REF (1 << 5) +#define UCB_ADC_START (1 << 7) +#define UCB_ADC_ENA (1 << 15) + +#define UCB_ADC_DATA 0x68 +#define UCB_ADC_DAT_VALID (1 << 15) +#define UCB_ADC_DAT_VALUE(x) ((x) & 0x3ff) + +#define UCB_ID 0x7e +#define UCB_ID_1400 0x4304 + + +struct ucb1400 { + ac97_t *ac97; + struct input_dev *ts_idev; + + int irq; + + wait_queue_head_t ts_wait; + struct task_struct *ts_task; + + unsigned int irq_pending; /* not bit field shared */ + unsigned int ts_restart:1; + unsigned int adcsync:1; +}; + +static int adcsync; + +static inline u16 ucb1400_reg_read(struct ucb1400 *ucb, u16 reg) +{ + return ucb->ac97->bus->ops->read(ucb->ac97, reg); +} + +static inline void ucb1400_reg_write(struct ucb1400 *ucb, u16 reg, u16 val) +{ + ucb->ac97->bus->ops->write(ucb->ac97, reg, val); +} + +static inline void ucb1400_adc_enable(struct ucb1400 *ucb) +{ + ucb1400_reg_write(ucb, UCB_ADC_CR, UCB_ADC_ENA); +} + +static unsigned int ucb1400_adc_read(struct ucb1400 *ucb, u16 adc_channel) +{ + unsigned int val; + + if (ucb->adcsync) + adc_channel |= UCB_ADC_SYNC_ENA; + + ucb1400_reg_write(ucb, UCB_ADC_CR, UCB_ADC_ENA | adc_channel); + ucb1400_reg_write(ucb, UCB_ADC_CR, UCB_ADC_ENA | adc_channel | UCB_ADC_START); + + for (;;) { + val = ucb1400_reg_read(ucb, UCB_ADC_DATA); + if (val & UCB_ADC_DAT_VALID) + break; + /* yield to other processes */ + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(1); + } + + return UCB_ADC_DAT_VALUE(val); +} + +static inline void ucb1400_adc_disable(struct ucb1400 *ucb) +{ + ucb1400_reg_write(ucb, UCB_ADC_CR, 0); +} + +/* Switch to interrupt mode. */ +static inline void ucb1400_ts_mode_int(struct ucb1400 *ucb) +{ + ucb1400_reg_write(ucb, UCB_TS_CR, + UCB_TS_CR_TSMX_POW | UCB_TS_CR_TSPX_POW | + UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND | + UCB_TS_CR_MODE_INT); +} + +/* + * Switch to pressure mode, and read pressure. We don't need to wait + * here, since both plates are being driven. + */ +static inline unsigned int ucb1400_ts_read_pressure(struct ucb1400 *ucb) +{ + ucb1400_reg_write(ucb, UCB_TS_CR, + UCB_TS_CR_TSMX_POW | UCB_TS_CR_TSPX_POW | + UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_GND | + UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA); + return ucb1400_adc_read(ucb, UCB_ADC_INP_TSPY); +} + +/* + * Switch to X position mode and measure Y plate. We switch the plate + * configuration in pressure mode, then switch to position mode. This + * gives a faster response time. Even so, we need to wait about 55us + * for things to stabilise. + */ +static inline unsigned int ucb1400_ts_read_xpos(struct ucb1400 *ucb) +{ + ucb1400_reg_write(ucb, UCB_TS_CR, + UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW | + UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA); + ucb1400_reg_write(ucb, UCB_TS_CR, + UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW | + UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA); + ucb1400_reg_write(ucb, UCB_TS_CR, + UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW | + UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA); + + udelay(55); + + return ucb1400_adc_read(ucb, UCB_ADC_INP_TSPY); +} + +/* + * Switch to Y position mode and measure X plate. We switch the plate + * configuration in pressure mode, then switch to position mode. This + * gives a faster response time. Even so, we need to wait about 55us + * for things to stabilise. + */ +static inline unsigned int ucb1400_ts_read_ypos(struct ucb1400 *ucb) +{ + ucb1400_reg_write(ucb, UCB_TS_CR, + UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW | + UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA); + ucb1400_reg_write(ucb, UCB_TS_CR, + UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW | + UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA); + ucb1400_reg_write(ucb, UCB_TS_CR, + UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW | + UCB_TS_CR_MODE_POS | UCB_TS_CR_BIAS_ENA); + + udelay(55); + + return ucb1400_adc_read(ucb, UCB_ADC_INP_TSPX); +} + +/* + * Switch to X plate resistance mode. Set MX to ground, PX to + * supply. Measure current. + */ +static inline unsigned int ucb1400_ts_read_xres(struct ucb1400 *ucb) +{ + ucb1400_reg_write(ucb, UCB_TS_CR, + UCB_TS_CR_TSMX_GND | UCB_TS_CR_TSPX_POW | + UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA); + return ucb1400_adc_read(ucb, 0); +} + +/* + * Switch to Y plate resistance mode. Set MY to ground, PY to + * supply. Measure current. + */ +static inline unsigned int ucb1400_ts_read_yres(struct ucb1400 *ucb) +{ + ucb1400_reg_write(ucb, UCB_TS_CR, + UCB_TS_CR_TSMY_GND | UCB_TS_CR_TSPY_POW | + UCB_TS_CR_MODE_PRES | UCB_TS_CR_BIAS_ENA); + return ucb1400_adc_read(ucb, 0); +} + +static inline int ucb1400_ts_pen_down(struct ucb1400 *ucb) +{ + unsigned short val = ucb1400_reg_read(ucb, UCB_TS_CR); + return (val & (UCB_TS_CR_TSPX_LOW | UCB_TS_CR_TSMX_LOW)); +} + +static inline void ucb1400_ts_irq_enable(struct ucb1400 *ucb) +{ + ucb1400_reg_write(ucb, UCB_IE_CLEAR, UCB_IE_TSPX); + ucb1400_reg_write(ucb, UCB_IE_CLEAR, 0); + ucb1400_reg_write(ucb, UCB_IE_FAL, UCB_IE_TSPX); +} + +static inline void ucb1400_ts_irq_disable(struct ucb1400 *ucb) +{ + ucb1400_reg_write(ucb, UCB_IE_FAL, 0); +} + +static void ucb1400_ts_evt_add(struct input_dev *idev, u16 pressure, u16 x, u16 y) +{ + input_report_abs(idev, ABS_X, x); + input_report_abs(idev, ABS_Y, y); + input_report_abs(idev, ABS_PRESSURE, pressure); + input_sync(idev); +} + +static void ucb1400_ts_event_release(struct input_dev *idev) +{ + input_report_abs(idev, ABS_PRESSURE, 0); + input_sync(idev); +} + +static void ucb1400_handle_pending_irq(struct ucb1400 *ucb) +{ + unsigned int isr; + + isr = ucb1400_reg_read(ucb, UCB_IE_STATUS); + ucb1400_reg_write(ucb, UCB_IE_CLEAR, isr); + ucb1400_reg_write(ucb, UCB_IE_CLEAR, 0); + + if (isr & UCB_IE_TSPX) + ucb1400_ts_irq_disable(ucb); + else + printk(KERN_ERR "ucb1400: unexpected IE_STATUS = %#x\n", isr); + + enable_irq(ucb->irq); +} + +static int ucb1400_ts_thread(void *_ucb) +{ + struct ucb1400 *ucb = _ucb; + struct task_struct *tsk = current; + int valid = 0; + + tsk->policy = SCHED_FIFO; + tsk->rt_priority = 1; + + while (!kthread_should_stop()) { + unsigned int x, y, p; + long timeout; + + ucb->ts_restart = 0; + + if (ucb->irq_pending) { + ucb->irq_pending = 0; + ucb1400_handle_pending_irq(ucb); + } + + ucb1400_adc_enable(ucb); + x = ucb1400_ts_read_xpos(ucb); + y = ucb1400_ts_read_ypos(ucb); + p = ucb1400_ts_read_pressure(ucb); + ucb1400_adc_disable(ucb); + + /* Switch back to interrupt mode. */ + ucb1400_ts_mode_int(ucb); + + msleep(10); + + if (ucb1400_ts_pen_down(ucb)) { + ucb1400_ts_irq_enable(ucb); + + /* + * If we spat out a valid sample set last time, + * spit out a "pen off" sample here. + */ + if (valid) { + ucb1400_ts_event_release(ucb->ts_idev); + valid = 0; + } + + timeout = MAX_SCHEDULE_TIMEOUT; + } else { + valid = 1; + ucb1400_ts_evt_add(ucb->ts_idev, p, x, y); + timeout = msecs_to_jiffies(10); + } + + wait_event_interruptible_timeout(ucb->ts_wait, + ucb->irq_pending || ucb->ts_restart || kthread_should_stop(), + timeout); + try_to_freeze(); + } + + /* Send the "pen off" if we are stopping with the pen still active */ + if (valid) + ucb1400_ts_event_release(ucb->ts_idev); + + ucb->ts_task = NULL; + return 0; +} + +/* + * A restriction with interrupts exists when using the ucb1400, as + * the codec read/write routines may sleep while waiting for codec + * access completion and uses semaphores for access control to the + * AC97 bus. A complete codec read cycle could take anywhere from + * 60 to 100uSec so we *definitely* don't want to spin inside the + * interrupt handler waiting for codec access. So, we handle the + * interrupt by scheduling a RT kernel thread to run in process + * context instead of interrupt context. + */ +static irqreturn_t ucb1400_hard_irq(int irqnr, void *devid) +{ + struct ucb1400 *ucb = devid; + + if (irqnr == ucb->irq) { + disable_irq(ucb->irq); + ucb->irq_pending = 1; + wake_up(&ucb->ts_wait); + return IRQ_HANDLED; + } + return IRQ_NONE; +} + +static int ucb1400_ts_open(struct input_dev *idev) +{ + struct ucb1400 *ucb = idev->private; + int ret = 0; + + BUG_ON(ucb->ts_task); + + ucb->ts_task = kthread_run(ucb1400_ts_thread, ucb, "UCB1400_ts"); + if (IS_ERR(ucb->ts_task)) { + ret = PTR_ERR(ucb->ts_task); + ucb->ts_task = NULL; + } + + return ret; +} + +static void ucb1400_ts_close(struct input_dev *idev) +{ + struct ucb1400 *ucb = idev->private; + + if (ucb->ts_task) + kthread_stop(ucb->ts_task); + + ucb1400_ts_irq_disable(ucb); + ucb1400_reg_write(ucb, UCB_TS_CR, 0); +} + +#ifdef CONFIG_PM +static int ucb1400_ts_resume(struct device *dev) +{ + struct ucb1400 *ucb = dev_get_drvdata(dev); + + if (ucb->ts_task) { + /* + * Restart the TS thread to ensure the + * TS interrupt mode is set up again + * after sleep. + */ + ucb->ts_restart = 1; + wake_up(&ucb->ts_wait); + } + return 0; +} +#else +#define ucb1400_ts_resume NULL +#endif + +#ifndef NO_IRQ +#define NO_IRQ 0 +#endif + +/* + * Try to probe our interrupt, rather than relying on lots of + * hard-coded machine dependencies. + */ +static int ucb1400_detect_irq(struct ucb1400 *ucb) +{ + unsigned long mask, timeout; + + mask = probe_irq_on(); + if (!mask) { + probe_irq_off(mask); + return -EBUSY; + } + + /* Enable the ADC interrupt. */ + ucb1400_reg_write(ucb, UCB_IE_RIS, UCB_IE_ADC); + ucb1400_reg_write(ucb, UCB_IE_FAL, UCB_IE_ADC); + ucb1400_reg_write(ucb, UCB_IE_CLEAR, 0xffff); + ucb1400_reg_write(ucb, UCB_IE_CLEAR, 0); + + /* Cause an ADC interrupt. */ + ucb1400_reg_write(ucb, UCB_ADC_CR, UCB_ADC_ENA); + ucb1400_reg_write(ucb, UCB_ADC_CR, UCB_ADC_ENA | UCB_ADC_START); + + /* Wait for the conversion to complete. */ + timeout = jiffies + HZ/2; + while (!(ucb1400_reg_read(ucb, UCB_ADC_DATA) & UCB_ADC_DAT_VALID)) { + cpu_relax(); + if (time_after(jiffies, timeout)) { + printk(KERN_ERR "ucb1400: timed out in IRQ probe\n"); + probe_irq_off(mask); + return -ENODEV; + } + } + ucb1400_reg_write(ucb, UCB_ADC_CR, 0); + + /* Disable and clear interrupt. */ + ucb1400_reg_write(ucb, UCB_IE_RIS, 0); + ucb1400_reg_write(ucb, UCB_IE_FAL, 0); + ucb1400_reg_write(ucb, UCB_IE_CLEAR, 0xffff); + ucb1400_reg_write(ucb, UCB_IE_CLEAR, 0); + + /* Read triggered interrupt. */ + ucb->irq = probe_irq_off(mask); + if (ucb->irq < 0 || ucb->irq == NO_IRQ) + return -ENODEV; + + return 0; +} + +static int ucb1400_ts_probe(struct device *dev) +{ + struct ucb1400 *ucb; + struct input_dev *idev; + int error, id, x_res, y_res; + + ucb = kzalloc(sizeof(struct ucb1400), GFP_KERNEL); + idev = input_allocate_device(); + if (!ucb || !idev) { + error = -ENOMEM; + goto err_free_devs; + } + + ucb->ts_idev = idev; + ucb->adcsync = adcsync; + ucb->ac97 = to_ac97_t(dev); + init_waitqueue_head(&ucb->ts_wait); + + id = ucb1400_reg_read(ucb, UCB_ID); + if (id != UCB_ID_1400) { + error = -ENODEV; + goto err_free_devs; + } + + error = ucb1400_detect_irq(ucb); + if (error) { + printk(KERN_ERR "UCB1400: IRQ probe failed\n"); + goto err_free_devs; + } + + error = request_irq(ucb->irq, ucb1400_hard_irq, IRQF_TRIGGER_RISING, + "UCB1400", ucb); + if (error) { + printk(KERN_ERR "ucb1400: unable to grab irq%d: %d\n", + ucb->irq, error); + goto err_free_devs; + } + printk(KERN_DEBUG "UCB1400: found IRQ %d\n", ucb->irq); + + idev->private = ucb; + idev->cdev.dev = dev; + idev->name = "UCB1400 touchscreen interface"; + idev->id.vendor = ucb1400_reg_read(ucb, AC97_VENDOR_ID1); + idev->id.product = id; + idev->open = ucb1400_ts_open; + idev->close = ucb1400_ts_close; + idev->evbit[0] = BIT(EV_ABS); + + ucb1400_adc_enable(ucb); + x_res = ucb1400_ts_read_xres(ucb); + y_res = ucb1400_ts_read_yres(ucb); + ucb1400_adc_disable(ucb); + printk(KERN_DEBUG "UCB1400: x/y = %d/%d\n", x_res, y_res); + + input_set_abs_params(idev, ABS_X, 0, x_res, 0, 0); + input_set_abs_params(idev, ABS_Y, 0, y_res, 0, 0); + input_set_abs_params(idev, ABS_PRESSURE, 0, 0, 0, 0); + + error = input_register_device(idev); + if (error) + goto err_free_irq; + + dev_set_drvdata(dev, ucb); + return 0; + + err_free_irq: + free_irq(ucb->irq, ucb); + err_free_devs: + input_free_device(idev); + kfree(ucb); + return error; +} + +static int ucb1400_ts_remove(struct device *dev) +{ + struct ucb1400 *ucb = dev_get_drvdata(dev); + + free_irq(ucb->irq, ucb); + input_unregister_device(ucb->ts_idev); + dev_set_drvdata(dev, NULL); + kfree(ucb); + return 0; +} + +static struct device_driver ucb1400_ts_driver = { + .owner = THIS_MODULE, + .bus = &ac97_bus_type, + .probe = ucb1400_ts_probe, + .remove = ucb1400_ts_remove, + .resume = ucb1400_ts_resume, +}; + +static int __init ucb1400_ts_init(void) +{ + return driver_register(&ucb1400_ts_driver); +} + +static void __exit ucb1400_ts_exit(void) +{ + driver_unregister(&ucb1400_ts_driver); +} + +module_param(adcsync, int, 0444); + +module_init(ucb1400_ts_init); +module_exit(ucb1400_ts_exit); + +MODULE_DESCRIPTION("Philips UCB1400 touchscreen driver"); +MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/isdn/act2000/capi.c b/trunk/drivers/isdn/act2000/capi.c index 6ae6eb322111..946c38cf6f8a 100644 --- a/trunk/drivers/isdn/act2000/capi.c +++ b/trunk/drivers/isdn/act2000/capi.c @@ -627,8 +627,10 @@ handle_ack(act2000_card *card, act2000_chan *chan, __u8 blocknr) { } void -actcapi_dispatch(act2000_card *card) +actcapi_dispatch(struct work_struct *work) { + struct act2000_card *card = + container_of(work, struct act2000_card, rcv_tq); struct sk_buff *skb; actcapi_msg *msg; __u16 ccmd; diff --git a/trunk/drivers/isdn/act2000/capi.h b/trunk/drivers/isdn/act2000/capi.h index 49f453c53c64..e55f6a931f66 100644 --- a/trunk/drivers/isdn/act2000/capi.h +++ b/trunk/drivers/isdn/act2000/capi.h @@ -356,7 +356,7 @@ extern int actcapi_connect_req(act2000_card *, act2000_chan *, char *, char, int extern void actcapi_select_b2_protocol_req(act2000_card *, act2000_chan *); extern void actcapi_disconnect_b3_req(act2000_card *, act2000_chan *); extern void actcapi_connect_resp(act2000_card *, act2000_chan *, __u8); -extern void actcapi_dispatch(act2000_card *); +extern void actcapi_dispatch(struct work_struct *); #ifdef DEBUG_MSG extern void actcapi_debug_msg(struct sk_buff *skb, int); #else diff --git a/trunk/drivers/isdn/act2000/module.c b/trunk/drivers/isdn/act2000/module.c index d89dcde4eade..e3e5c1399076 100644 --- a/trunk/drivers/isdn/act2000/module.c +++ b/trunk/drivers/isdn/act2000/module.c @@ -192,8 +192,11 @@ act2000_set_msn(act2000_card *card, char *eazmsn) } static void -act2000_transmit(struct act2000_card *card) +act2000_transmit(struct work_struct *work) { + struct act2000_card *card = + container_of(work, struct act2000_card, snd_tq); + switch (card->bus) { case ACT2000_BUS_ISA: act2000_isa_send(card); @@ -207,8 +210,11 @@ act2000_transmit(struct act2000_card *card) } static void -act2000_receive(struct act2000_card *card) +act2000_receive(struct work_struct *work) { + struct act2000_card *card = + container_of(work, struct act2000_card, poll_tq); + switch (card->bus) { case ACT2000_BUS_ISA: act2000_isa_receive(card); @@ -227,7 +233,7 @@ act2000_poll(unsigned long data) act2000_card * card = (act2000_card *)data; unsigned long flags; - act2000_receive(card); + act2000_receive(&card->poll_tq); spin_lock_irqsave(&card->lock, flags); mod_timer(&card->ptimer, jiffies+3); spin_unlock_irqrestore(&card->lock, flags); @@ -567,20 +573,19 @@ act2000_alloccard(int bus, int port, int irq, char *id) { int i; act2000_card *card; - if (!(card = (act2000_card *) kmalloc(sizeof(act2000_card), GFP_KERNEL))) { + if (!(card = kzalloc(sizeof(act2000_card), GFP_KERNEL))) { printk(KERN_WARNING "act2000: (%s) Could not allocate card-struct.\n", id); return; } - memset((char *) card, 0, sizeof(act2000_card)); spin_lock_init(&card->lock); spin_lock_init(&card->mnlock); skb_queue_head_init(&card->sndq); skb_queue_head_init(&card->rcvq); skb_queue_head_init(&card->ackq); - INIT_WORK(&card->snd_tq, (void *) (void *) act2000_transmit, card); - INIT_WORK(&card->rcv_tq, (void *) (void *) actcapi_dispatch, card); - INIT_WORK(&card->poll_tq, (void *) (void *) act2000_receive, card); + INIT_WORK(&card->snd_tq, act2000_transmit); + INIT_WORK(&card->rcv_tq, actcapi_dispatch); + INIT_WORK(&card->poll_tq, act2000_receive); init_timer(&card->ptimer); card->interface.owner = THIS_MODULE; card->interface.channels = ACT2000_BCH; diff --git a/trunk/drivers/isdn/capi/capi.c b/trunk/drivers/isdn/capi/capi.c index 11844bbfe933..d22c0224fde6 100644 --- a/trunk/drivers/isdn/capi/capi.c +++ b/trunk/drivers/isdn/capi/capi.c @@ -215,13 +215,12 @@ static struct capiminor *capiminor_alloc(struct capi20_appl *ap, u32 ncci) unsigned int minor = 0; unsigned long flags; - mp = kmalloc(sizeof(*mp), GFP_ATOMIC); + mp = kzalloc(sizeof(*mp), GFP_ATOMIC); if (!mp) { printk(KERN_ERR "capi: can't alloc capiminor\n"); return NULL; } - memset(mp, 0, sizeof(struct capiminor)); mp->ap = ap; mp->ncci = ncci; mp->msgid = 0; @@ -304,10 +303,9 @@ static struct capincci *capincci_alloc(struct capidev *cdev, u32 ncci) struct capiminor *mp = NULL; #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ - np = kmalloc(sizeof(*np), GFP_ATOMIC); + np = kzalloc(sizeof(*np), GFP_ATOMIC); if (!np) return NULL; - memset(np, 0, sizeof(struct capincci)); np->ncci = ncci; np->cdev = cdev; #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE @@ -384,10 +382,9 @@ static struct capidev *capidev_alloc(void) struct capidev *cdev; unsigned long flags; - cdev = kmalloc(sizeof(*cdev), GFP_KERNEL); + cdev = kzalloc(sizeof(*cdev), GFP_KERNEL); if (!cdev) return NULL; - memset(cdev, 0, sizeof(struct capidev)); init_MUTEX(&cdev->ncci_list_sem); skb_queue_head_init(&cdev->recvqueue); @@ -1010,7 +1007,7 @@ static int capinc_tty_open(struct tty_struct * tty, struct file * file) { struct capiminor *mp; - if ((mp = capiminor_find(iminor(file->f_dentry->d_inode))) == 0) + if ((mp = capiminor_find(iminor(file->f_path.dentry->d_inode))) == 0) return -ENXIO; if (mp->nccip == 0) return -ENXIO; @@ -1203,7 +1200,7 @@ static int capinc_tty_ioctl(struct tty_struct *tty, struct file * file, return error; } -static void capinc_tty_set_termios(struct tty_struct *tty, struct termios * old) +static void capinc_tty_set_termios(struct tty_struct *tty, struct ktermios * old) { #ifdef _DEBUG_TTYFUNCS printk(KERN_DEBUG "capinc_tty_set_termios\n"); diff --git a/trunk/drivers/isdn/capi/capidrv.c b/trunk/drivers/isdn/capi/capidrv.c index b6f9476c0501..097bfa7bc323 100644 --- a/trunk/drivers/isdn/capi/capidrv.c +++ b/trunk/drivers/isdn/capi/capidrv.c @@ -334,12 +334,11 @@ static capidrv_plci *new_plci(capidrv_contr * card, int chan) { capidrv_plci *plcip; - plcip = (capidrv_plci *) kmalloc(sizeof(capidrv_plci), GFP_ATOMIC); + plcip = kzalloc(sizeof(capidrv_plci), GFP_ATOMIC); if (plcip == 0) return NULL; - memset(plcip, 0, sizeof(capidrv_plci)); plcip->state = ST_PLCI_NONE; plcip->plci = 0; plcip->msgid = 0; @@ -404,12 +403,11 @@ static inline capidrv_ncci *new_ncci(capidrv_contr * card, { capidrv_ncci *nccip; - nccip = (capidrv_ncci *) kmalloc(sizeof(capidrv_ncci), GFP_ATOMIC); + nccip = kzalloc(sizeof(capidrv_ncci), GFP_ATOMIC); if (nccip == 0) return NULL; - memset(nccip, 0, sizeof(capidrv_ncci)); nccip->ncci = ncci; nccip->state = ST_NCCI_NONE; nccip->plcip = plcip; @@ -2005,12 +2003,11 @@ static int capidrv_addcontr(u16 contr, struct capi_profile *profp) printk(KERN_WARNING "capidrv: (%s) Could not reserve module\n", id); return -1; } - if (!(card = (capidrv_contr *) kmalloc(sizeof(capidrv_contr), GFP_ATOMIC))) { + if (!(card = kzalloc(sizeof(capidrv_contr), GFP_ATOMIC))) { printk(KERN_WARNING "capidrv: (%s) Could not allocate contr-struct.\n", id); return -1; } - memset(card, 0, sizeof(capidrv_contr)); card->owner = THIS_MODULE; init_timer(&card->listentimer); strcpy(card->name, id); diff --git a/trunk/drivers/isdn/capi/kcapi.c b/trunk/drivers/isdn/capi/kcapi.c index 8c4fcb9027b3..783a25526315 100644 --- a/trunk/drivers/isdn/capi/kcapi.c +++ b/trunk/drivers/isdn/capi/kcapi.c @@ -208,9 +208,10 @@ static void notify_down(u32 contr) } } -static void notify_handler(void *data) +static void notify_handler(struct work_struct *work) { - struct capi_notifier *np = data; + struct capi_notifier *np = + container_of(work, struct capi_notifier, work); switch (np->cmd) { case KCI_CONTRUP: @@ -235,7 +236,7 @@ static int notify_push(unsigned int cmd, u32 controller, u16 applid, u32 ncci) if (!np) return -ENOMEM; - INIT_WORK(&np->work, notify_handler, np); + INIT_WORK(&np->work, notify_handler); np->cmd = cmd; np->controller = controller; np->applid = applid; @@ -248,10 +249,11 @@ static int notify_push(unsigned int cmd, u32 controller, u16 applid, u32 ncci) /* -------- Receiver ------------------------------------------ */ -static void recv_handler(void *_ap) +static void recv_handler(struct work_struct *work) { struct sk_buff *skb; - struct capi20_appl *ap = (struct capi20_appl *) _ap; + struct capi20_appl *ap = + container_of(work, struct capi20_appl, recv_work); if ((!ap) || (ap->release_in_progress)) return; @@ -527,7 +529,7 @@ u16 capi20_register(struct capi20_appl *ap) ap->callback = NULL; init_MUTEX(&ap->recv_sem); skb_queue_head_init(&ap->recv_queue); - INIT_WORK(&ap->recv_work, recv_handler, (void *)ap); + INIT_WORK(&ap->recv_work, recv_handler); ap->release_in_progress = 0; write_unlock_irqrestore(&application_lock, flags); diff --git a/trunk/drivers/isdn/gigaset/Kconfig b/trunk/drivers/isdn/gigaset/Kconfig index 5b203fe21dcd..708d47a6484b 100644 --- a/trunk/drivers/isdn/gigaset/Kconfig +++ b/trunk/drivers/isdn/gigaset/Kconfig @@ -5,6 +5,7 @@ config ISDN_DRV_GIGASET tristate "Siemens Gigaset support (isdn)" depends on ISDN_I4L select CRC_CCITT + select BITREVERSE help Say m here if you have a Gigaset or Sinus isdn device. diff --git a/trunk/drivers/isdn/gigaset/asyncdata.c b/trunk/drivers/isdn/gigaset/asyncdata.c index ce3cd77094b3..88e958f176d2 100644 --- a/trunk/drivers/isdn/gigaset/asyncdata.c +++ b/trunk/drivers/isdn/gigaset/asyncdata.c @@ -15,6 +15,7 @@ #include "gigaset.h" #include +#include //#define GIG_M10x_STUFF_VOICE_DATA @@ -302,7 +303,7 @@ static inline int iraw_loop(unsigned char c, unsigned char *src, int numbytes, inputstate |= INS_skip_frame; break; } - *__skb_put(skb, 1) = gigaset_invtab[c]; + *__skb_put(skb, 1) = bitrev8(c); } if (unlikely(!numbytes)) @@ -543,7 +544,7 @@ static struct sk_buff *iraw_encode(struct sk_buff *skb, int head, int tail) cp = skb->data; len = skb->len; while (len--) { - c = gigaset_invtab[*cp++]; + c = bitrev8(*cp++); if (c == DLE_FLAG) *(skb_put(iraw_skb, 1)) = c; *(skb_put(iraw_skb, 1)) = c; diff --git a/trunk/drivers/isdn/gigaset/bas-gigaset.c b/trunk/drivers/isdn/gigaset/bas-gigaset.c index 0c937325a1b3..63b629b1cdb2 100644 --- a/trunk/drivers/isdn/gigaset/bas-gigaset.c +++ b/trunk/drivers/isdn/gigaset/bas-gigaset.c @@ -572,7 +572,7 @@ static int atread_submit(struct cardstate *cs, int timeout) ucs->rcvbuf, ucs->rcvbuf_size, read_ctrl_callback, cs->inbuf); - if ((ret = usb_submit_urb(ucs->urb_cmd_in, SLAB_ATOMIC)) != 0) { + if ((ret = usb_submit_urb(ucs->urb_cmd_in, GFP_ATOMIC)) != 0) { update_basstate(ucs, 0, BS_ATRDPEND); dev_err(cs->dev, "could not submit HD_READ_ATMESSAGE: %s\n", get_usb_rcmsg(ret)); @@ -747,7 +747,7 @@ static void read_int_callback(struct urb *urb) check_pending(ucs); resubmit: - rc = usb_submit_urb(urb, SLAB_ATOMIC); + rc = usb_submit_urb(urb, GFP_ATOMIC); if (unlikely(rc != 0 && rc != -ENODEV)) { dev_err(cs->dev, "could not resubmit interrupt URB: %s\n", get_usb_rcmsg(rc)); @@ -807,7 +807,7 @@ static void read_iso_callback(struct urb *urb) urb->number_of_packets = BAS_NUMFRAMES; gig_dbg(DEBUG_ISO, "%s: isoc read overrun/resubmit", __func__); - rc = usb_submit_urb(urb, SLAB_ATOMIC); + rc = usb_submit_urb(urb, GFP_ATOMIC); if (unlikely(rc != 0 && rc != -ENODEV)) { dev_err(bcs->cs->dev, "could not resubmit isochronous read " @@ -900,7 +900,7 @@ static int starturbs(struct bc_state *bcs) } dump_urb(DEBUG_ISO, "Initial isoc read", urb); - if ((rc = usb_submit_urb(urb, SLAB_ATOMIC)) != 0) + if ((rc = usb_submit_urb(urb, GFP_ATOMIC)) != 0) goto error; } @@ -935,7 +935,7 @@ static int starturbs(struct bc_state *bcs) /* submit two URBs, keep third one */ for (k = 0; k < 2; ++k) { dump_urb(DEBUG_ISO, "Initial isoc write", urb); - rc = usb_submit_urb(ubc->isoouturbs[k].urb, SLAB_ATOMIC); + rc = usb_submit_urb(ubc->isoouturbs[k].urb, GFP_ATOMIC); if (rc != 0) goto error; } @@ -1042,7 +1042,7 @@ static int submit_iso_write_urb(struct isow_urbctx_t *ucx) return 0; /* no data to send */ urb->number_of_packets = nframe; - rc = usb_submit_urb(urb, SLAB_ATOMIC); + rc = usb_submit_urb(urb, GFP_ATOMIC); if (unlikely(rc)) { if (rc == -ENODEV) /* device removed - give up silently */ @@ -1341,7 +1341,7 @@ static void read_iso_tasklet(unsigned long data) urb->dev = bcs->cs->hw.bas->udev; urb->transfer_flags = URB_ISO_ASAP; urb->number_of_packets = BAS_NUMFRAMES; - rc = usb_submit_urb(urb, SLAB_ATOMIC); + rc = usb_submit_urb(urb, GFP_ATOMIC); if (unlikely(rc != 0 && rc != -ENODEV)) { dev_err(cs->dev, "could not resubmit isochronous read URB: %s\n", @@ -1458,7 +1458,7 @@ static void write_ctrl_callback(struct urb *urb) ucs->retry_ctrl); /* urb->dev is clobbered by USB subsystem */ urb->dev = ucs->udev; - rc = usb_submit_urb(urb, SLAB_ATOMIC); + rc = usb_submit_urb(urb, GFP_ATOMIC); if (unlikely(rc)) { dev_err(&ucs->interface->dev, "could not resubmit request 0x%02x: %s\n", @@ -1517,7 +1517,7 @@ static int req_submit(struct bc_state *bcs, int req, int val, int timeout) (unsigned char*) &ucs->dr_ctrl, NULL, 0, write_ctrl_callback, ucs); ucs->retry_ctrl = 0; - ret = usb_submit_urb(ucs->urb_ctrl, SLAB_ATOMIC); + ret = usb_submit_urb(ucs->urb_ctrl, GFP_ATOMIC); if (unlikely(ret)) { dev_err(bcs->cs->dev, "could not submit request 0x%02x: %s\n", req, get_usb_rcmsg(ret)); @@ -1763,7 +1763,7 @@ static int atwrite_submit(struct cardstate *cs, unsigned char *buf, int len) usb_sndctrlpipe(ucs->udev, 0), (unsigned char*) &ucs->dr_cmd_out, buf, len, write_command_callback, cs); - rc = usb_submit_urb(ucs->urb_cmd_out, SLAB_ATOMIC); + rc = usb_submit_urb(ucs->urb_cmd_out, GFP_ATOMIC); if (unlikely(rc)) { update_basstate(ucs, 0, BS_ATWRPEND); dev_err(cs->dev, "could not submit HD_WRITE_ATMESSAGE: %s\n", @@ -2218,21 +2218,21 @@ static int gigaset_probe(struct usb_interface *interface, * - three for the different uses of the default control pipe * - three for each isochronous pipe */ - if (!(ucs->urb_int_in = usb_alloc_urb(0, SLAB_KERNEL)) || - !(ucs->urb_cmd_in = usb_alloc_urb(0, SLAB_KERNEL)) || - !(ucs->urb_cmd_out = usb_alloc_urb(0, SLAB_KERNEL)) || - !(ucs->urb_ctrl = usb_alloc_urb(0, SLAB_KERNEL))) + if (!(ucs->urb_int_in = usb_alloc_urb(0, GFP_KERNEL)) || + !(ucs->urb_cmd_in = usb_alloc_urb(0, GFP_KERNEL)) || + !(ucs->urb_cmd_out = usb_alloc_urb(0, GFP_KERNEL)) || + !(ucs->urb_ctrl = usb_alloc_urb(0, GFP_KERNEL))) goto allocerr; for (j = 0; j < 2; ++j) { ubc = cs->bcs[j].hw.bas; for (i = 0; i < BAS_OUTURBS; ++i) if (!(ubc->isoouturbs[i].urb = - usb_alloc_urb(BAS_NUMFRAMES, SLAB_KERNEL))) + usb_alloc_urb(BAS_NUMFRAMES, GFP_KERNEL))) goto allocerr; for (i = 0; i < BAS_INURBS; ++i) if (!(ubc->isoinurbs[i] = - usb_alloc_urb(BAS_NUMFRAMES, SLAB_KERNEL))) + usb_alloc_urb(BAS_NUMFRAMES, GFP_KERNEL))) goto allocerr; } @@ -2246,7 +2246,7 @@ static int gigaset_probe(struct usb_interface *interface, (endpoint->bEndpointAddress) & 0x0f), ucs->int_in_buf, 3, read_int_callback, cs, endpoint->bInterval); - if ((rc = usb_submit_urb(ucs->urb_int_in, SLAB_KERNEL)) != 0) { + if ((rc = usb_submit_urb(ucs->urb_int_in, GFP_KERNEL)) != 0) { dev_err(cs->dev, "could not submit interrupt URB: %s\n", get_usb_rcmsg(rc)); goto error; diff --git a/trunk/drivers/isdn/gigaset/common.c b/trunk/drivers/isdn/gigaset/common.c index defd5743dba6..95eff3b2917a 100644 --- a/trunk/drivers/isdn/gigaset/common.c +++ b/trunk/drivers/isdn/gigaset/common.c @@ -33,43 +33,6 @@ MODULE_PARM_DESC(debug, "debug level"); #define VALID_ID 0x02 #define ASSIGNED 0x04 -/* bitwise byte inversion table */ -__u8 gigaset_invtab[256] = { - 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, - 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, - 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, - 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, - 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, - 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, - 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, - 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, - 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, - 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, - 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, - 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, - 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, - 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, - 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, - 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, - 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, - 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, - 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, - 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, - 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, - 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, - 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, - 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, - 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, - 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, - 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, - 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, - 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, - 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, - 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, - 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff -}; -EXPORT_SYMBOL_GPL(gigaset_invtab); - void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg, size_t len, const unsigned char *buf) { diff --git a/trunk/drivers/isdn/gigaset/gigaset.h b/trunk/drivers/isdn/gigaset/gigaset.h index 06298cc52bf5..a0317abaeb11 100644 --- a/trunk/drivers/isdn/gigaset/gigaset.h +++ b/trunk/drivers/isdn/gigaset/gigaset.h @@ -876,10 +876,6 @@ static inline void gigaset_rcv_error(struct sk_buff *procskb, } } - -/* bitwise byte inversion table */ -extern __u8 gigaset_invtab[]; /* in common.c */ - /* append received bytes to inbuf */ int gigaset_fill_inbuf(struct inbuf_t *inbuf, const unsigned char *src, unsigned numbytes); diff --git a/trunk/drivers/isdn/gigaset/interface.c b/trunk/drivers/isdn/gigaset/interface.c index 7edea015867e..458b6462f937 100644 --- a/trunk/drivers/isdn/gigaset/interface.c +++ b/trunk/drivers/isdn/gigaset/interface.c @@ -127,7 +127,7 @@ static int if_write_room(struct tty_struct *tty); static int if_chars_in_buffer(struct tty_struct *tty); static void if_throttle(struct tty_struct *tty); static void if_unthrottle(struct tty_struct *tty); -static void if_set_termios(struct tty_struct *tty, struct termios *old); +static void if_set_termios(struct tty_struct *tty, struct ktermios *old); static int if_tiocmget(struct tty_struct *tty, struct file *file); static int if_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear); @@ -490,7 +490,7 @@ static void if_unthrottle(struct tty_struct *tty) mutex_unlock(&cs->mutex); } -static void if_set_termios(struct tty_struct *tty, struct termios *old) +static void if_set_termios(struct tty_struct *tty, struct ktermios *old) { struct cardstate *cs; unsigned int iflag; diff --git a/trunk/drivers/isdn/gigaset/isocdata.c b/trunk/drivers/isdn/gigaset/isocdata.c index 8667daaa1a82..df988eb0e36f 100644 --- a/trunk/drivers/isdn/gigaset/isocdata.c +++ b/trunk/drivers/isdn/gigaset/isocdata.c @@ -14,6 +14,7 @@ #include "gigaset.h" #include +#include /* access methods for isowbuf_t */ /* ============================ */ @@ -487,7 +488,7 @@ static inline int trans_buildframe(struct isowbuf_t *iwb, gig_dbg(DEBUG_STREAM, "put %d bytes", count); write = atomic_read(&iwb->write); do { - c = gigaset_invtab[*in++]; + c = bitrev8(*in++); iwb->data[write++] = c; write %= BAS_OUTBUFSIZE; } while (--count > 0); @@ -876,7 +877,7 @@ static inline void trans_receive(unsigned char *src, unsigned count, while (count > 0) { dst = skb_put(skb, count < dobytes ? count : dobytes); while (count > 0 && dobytes > 0) { - *dst++ = gigaset_invtab[*src++]; + *dst++ = bitrev8(*src++); count--; dobytes--; } diff --git a/trunk/drivers/isdn/gigaset/usb-gigaset.c b/trunk/drivers/isdn/gigaset/usb-gigaset.c index 5ebf49ac9b23..04f2ad7ba8b0 100644 --- a/trunk/drivers/isdn/gigaset/usb-gigaset.c +++ b/trunk/drivers/isdn/gigaset/usb-gigaset.c @@ -410,7 +410,7 @@ static void gigaset_read_int_callback(struct urb *urb) if (resubmit) { spin_lock_irqsave(&cs->lock, flags); - r = cs->connected ? usb_submit_urb(urb, SLAB_ATOMIC) : -ENODEV; + r = cs->connected ? usb_submit_urb(urb, GFP_ATOMIC) : -ENODEV; spin_unlock_irqrestore(&cs->lock, flags); if (r) dev_err(cs->dev, "error %d when resubmitting urb.\n", @@ -486,7 +486,7 @@ static int send_cb(struct cardstate *cs, struct cmdbuf_t *cb) atomic_set(&ucs->busy, 1); spin_lock_irqsave(&cs->lock, flags); - status = cs->connected ? usb_submit_urb(ucs->bulk_out_urb, SLAB_ATOMIC) : -ENODEV; + status = cs->connected ? usb_submit_urb(ucs->bulk_out_urb, GFP_ATOMIC) : -ENODEV; spin_unlock_irqrestore(&cs->lock, flags); if (status) { @@ -664,7 +664,7 @@ static int write_modem(struct cardstate *cs) ucs->bulk_out_endpointAddr & 0x0f), ucs->bulk_out_buffer, count, gigaset_write_bulk_callback, cs); - ret = usb_submit_urb(ucs->bulk_out_urb, SLAB_ATOMIC); + ret = usb_submit_urb(ucs->bulk_out_urb, GFP_ATOMIC); } else { ret = -ENODEV; } @@ -763,7 +763,7 @@ static int gigaset_probe(struct usb_interface *interface, goto error; } - ucs->bulk_out_urb = usb_alloc_urb(0, SLAB_KERNEL); + ucs->bulk_out_urb = usb_alloc_urb(0, GFP_KERNEL); if (!ucs->bulk_out_urb) { dev_err(cs->dev, "Couldn't allocate bulk_out_urb\n"); retval = -ENOMEM; @@ -774,7 +774,7 @@ static int gigaset_probe(struct usb_interface *interface, atomic_set(&ucs->busy, 0); - ucs->read_urb = usb_alloc_urb(0, SLAB_KERNEL); + ucs->read_urb = usb_alloc_urb(0, GFP_KERNEL); if (!ucs->read_urb) { dev_err(cs->dev, "No free urbs available\n"); retval = -ENOMEM; @@ -797,7 +797,7 @@ static int gigaset_probe(struct usb_interface *interface, gigaset_read_int_callback, cs->inbuf + 0, endpoint->bInterval); - retval = usb_submit_urb(ucs->read_urb, SLAB_KERNEL); + retval = usb_submit_urb(ucs->read_urb, GFP_KERNEL); if (retval) { dev_err(cs->dev, "Could not submit URB (error %d)\n", -retval); goto error; diff --git a/trunk/drivers/isdn/hardware/avm/avm_cs.c b/trunk/drivers/isdn/hardware/avm/avm_cs.c index 7bbfd85ab793..eba10466ccc6 100644 --- a/trunk/drivers/isdn/hardware/avm/avm_cs.c +++ b/trunk/drivers/isdn/hardware/avm/avm_cs.c @@ -121,10 +121,9 @@ static int avmcs_probe(struct pcmcia_device *p_dev) p_dev->conf.Present = PRESENT_OPTION; /* Allocate space for private device-specific data */ - local = kmalloc(sizeof(local_info_t), GFP_KERNEL); + local = kzalloc(sizeof(local_info_t), GFP_KERNEL); if (!local) goto err; - memset(local, 0, sizeof(local_info_t)); p_dev->priv = local; return avmcs_config(p_dev); @@ -194,41 +193,11 @@ static int avmcs_config(struct pcmcia_device *link) dev = link->priv; - /* - This reads the card's CONFIG tuple to find its configuration - registers. - */ do { - tuple.DesiredTuple = CISTPL_CONFIG; - i = pcmcia_get_first_tuple(link, &tuple); - if (i != CS_SUCCESS) break; - tuple.TupleData = buf; - tuple.TupleDataMax = 64; - tuple.TupleOffset = 0; - i = pcmcia_get_tuple_data(link, &tuple); - if (i != CS_SUCCESS) break; - i = pcmcia_parse_tuple(link, &tuple, &parse); - if (i != CS_SUCCESS) break; - link->conf.ConfigBase = parse.config.base; - } while (0); - if (i != CS_SUCCESS) { - cs_error(link, ParseTuple, i); - return -ENODEV; - } - - do { - - tuple.Attributes = 0; - tuple.TupleData = buf; - tuple.TupleDataMax = 254; - tuple.TupleOffset = 0; - tuple.DesiredTuple = CISTPL_VERS_1; - devname[0] = 0; - if( !first_tuple(link, &tuple, &parse) && parse.version_1.ns > 1 ) { - strlcpy(devname,parse.version_1.str + parse.version_1.ofs[1], - sizeof(devname)); - } + if (link->prod_id[1]) + strlcpy(devname, link->prod_id[1], sizeof(devname)); + /* * find IO port */ diff --git a/trunk/drivers/isdn/hardware/avm/b1.c b/trunk/drivers/isdn/hardware/avm/b1.c index da2729247713..7a69a18d07e2 100644 --- a/trunk/drivers/isdn/hardware/avm/b1.c +++ b/trunk/drivers/isdn/hardware/avm/b1.c @@ -65,18 +65,15 @@ avmcard *b1_alloc_card(int nr_controllers) avmctrl_info *cinfo; int i; - card = kmalloc(sizeof(*card), GFP_KERNEL); + card = kzalloc(sizeof(*card), GFP_KERNEL); if (!card) return NULL; - memset(card, 0, sizeof(*card)); - - cinfo = kmalloc(sizeof(*cinfo) * nr_controllers, GFP_KERNEL); + cinfo = kzalloc(sizeof(*cinfo) * nr_controllers, GFP_KERNEL); if (!cinfo) { kfree(card); return NULL; } - memset(cinfo, 0, sizeof(*cinfo) * nr_controllers); card->ctrlinfo = cinfo; for (i = 0; i < nr_controllers; i++) { @@ -718,12 +715,11 @@ avmcard_dma_alloc(char *name, struct pci_dev *pdev, long rsize, long ssize) avmcard_dmainfo *p; void *buf; - p = kmalloc(sizeof(avmcard_dmainfo), GFP_KERNEL); + p = kzalloc(sizeof(avmcard_dmainfo), GFP_KERNEL); if (!p) { printk(KERN_WARNING "%s: no memory.\n", name); goto err; } - memset(p, 0, sizeof(avmcard_dmainfo)); p->recvbuf.size = rsize; buf = pci_alloc_consistent(pdev, rsize, &p->recvbuf.dmaaddr); diff --git a/trunk/drivers/isdn/hardware/avm/t1isa.c b/trunk/drivers/isdn/hardware/avm/t1isa.c index e47c60b0a8ec..c925020fe9b7 100644 --- a/trunk/drivers/isdn/hardware/avm/t1isa.c +++ b/trunk/drivers/isdn/hardware/avm/t1isa.c @@ -584,6 +584,7 @@ static void __exit t1isa_exit(void) { int i; + unregister_capi_driver(&capi_driver_t1isa); for (i = 0; i < MAX_CARDS; i++) { if (!io[i]) break; diff --git a/trunk/drivers/isdn/hardware/eicon/debug.c b/trunk/drivers/isdn/hardware/eicon/debug.c index 6851c6270ce8..d835e74ecf18 100644 --- a/trunk/drivers/isdn/hardware/eicon/debug.c +++ b/trunk/drivers/isdn/hardware/eicon/debug.c @@ -756,14 +756,14 @@ int diva_get_driver_info (dword id, byte* data, int data_length) { data_length -= 9; - if ((to_copy = MIN(strlen(clients[id].drvName), data_length-1))) { + if ((to_copy = min(strlen(clients[id].drvName), (size_t)(data_length-1)))) { memcpy (p, clients[id].drvName, to_copy); p += to_copy; data_length -= to_copy; if ((data_length >= 4) && clients[id].hDbg->drvTag[0]) { *p++ = '('; data_length -= 1; - if ((to_copy = MIN(strlen(clients[id].hDbg->drvTag), data_length-2))) { + if ((to_copy = min(strlen(clients[id].hDbg->drvTag), (size_t)(data_length-2)))) { memcpy (p, clients[id].hDbg->drvTag, to_copy); p += to_copy; data_length -= to_copy; diff --git a/trunk/drivers/isdn/hardware/eicon/di.c b/trunk/drivers/isdn/hardware/eicon/di.c index 0617d7cabf06..e1df8d98c311 100644 --- a/trunk/drivers/isdn/hardware/eicon/di.c +++ b/trunk/drivers/isdn/hardware/eicon/di.c @@ -133,7 +133,7 @@ void pr_out(ADAPTER * a) i = this->XCurrent; X = PTR_X(a,this); while(iXNum && length<270) { - clength = MIN((word)(270-length),X[i].PLength-this->XOffset); + clength = min((word)(270-length),(word)(X[i].PLength-this->XOffset)); a->ram_out_buffer(a, &ReqOut->XBuffer.P[length], PTR_P(a,this,&X[i].P[this->XOffset]), @@ -622,7 +622,7 @@ byte isdn_ind(ADAPTER * a, sizeof(a->stream_buffer), &final, NULL, NULL); } - IoAdapter->RBuffer.length = MIN(MLength, 270); + IoAdapter->RBuffer.length = min(MLength, (word)270); if (IoAdapter->RBuffer.length != MLength) { this->complete = 0; } else { @@ -676,9 +676,9 @@ byte isdn_ind(ADAPTER * a, this->RCurrent++; } if (cma) { - clength = MIN(MLength, R[this->RCurrent].PLength-this->ROffset); + clength = min(MLength, (word)(R[this->RCurrent].PLength-this->ROffset)); } else { - clength = MIN(a->ram_inw(a, &RBuffer->length)-offset, + clength = min(a->ram_inw(a, &RBuffer->length)-offset, R[this->RCurrent].PLength-this->ROffset); } if(R[this->RCurrent].P) { diff --git a/trunk/drivers/isdn/hardware/eicon/divasmain.c b/trunk/drivers/isdn/hardware/eicon/divasmain.c index dae2e83dd5e8..91fc92c01afe 100644 --- a/trunk/drivers/isdn/hardware/eicon/divasmain.c +++ b/trunk/drivers/isdn/hardware/eicon/divasmain.c @@ -185,7 +185,7 @@ void diva_log_info(unsigned char *format, ...) unsigned char line[160]; va_start(args, format); - vsprintf(line, format, args); + vsnprintf(line, sizeof(line), format, args); va_end(args); printk(KERN_INFO "%s: %s\n", DRIVERLNAME, line); diff --git a/trunk/drivers/isdn/hardware/eicon/io.c b/trunk/drivers/isdn/hardware/eicon/io.c index 4a27e230b0a5..6fd9b007417d 100644 --- a/trunk/drivers/isdn/hardware/eicon/io.c +++ b/trunk/drivers/isdn/hardware/eicon/io.c @@ -262,7 +262,7 @@ void request(PISDN_ADAPTER IoAdapter, ENTITY * e) case IDI_SYNC_REQ_XDI_GET_CAPI_PARAMS: { diva_xdi_get_capi_parameters_t prms, *pI = &syncReq->xdi_capi_prms.info; memset (&prms, 0x00, sizeof(prms)); - prms.structure_length = MIN(sizeof(prms), pI->structure_length); + prms.structure_length = min_t(size_t, sizeof(prms), pI->structure_length); memset (pI, 0x00, pI->structure_length); prms.flag_dynamic_l1_down = (IoAdapter->capi_cfg.cfg_1 & \ DIVA_XDI_CAPI_CFG_1_DYNAMIC_L1_ON) ? 1 : 0; diff --git a/trunk/drivers/isdn/hardware/eicon/istream.c b/trunk/drivers/isdn/hardware/eicon/istream.c index 23139668d9b1..18f8798442fa 100644 --- a/trunk/drivers/isdn/hardware/eicon/istream.c +++ b/trunk/drivers/isdn/hardware/eicon/istream.c @@ -92,7 +92,7 @@ int diva_istream_write (void* context, return (-1); /* was not able to write */ break; /* only part of message was written */ } - to_write = MIN(length, DIVA_DFIFO_DATA_SZ); + to_write = min(length, DIVA_DFIFO_DATA_SZ); if (to_write) { a->ram_out_buffer (a, #ifdef PLATFORM_GT_32BIT @@ -176,7 +176,7 @@ int diva_istream_read (void* context, return (-1); /* was not able to read */ break; } - to_read = MIN(max_length, tmp[1]); + to_read = min(max_length, (int)tmp[1]); if (to_read) { a->ram_in_buffer(a, #ifdef PLATFORM_GT_32BIT diff --git a/trunk/drivers/isdn/hardware/eicon/platform.h b/trunk/drivers/isdn/hardware/eicon/platform.h index a66836cf756c..2444811e0b38 100644 --- a/trunk/drivers/isdn/hardware/eicon/platform.h +++ b/trunk/drivers/isdn/hardware/eicon/platform.h @@ -83,14 +83,6 @@ #define NULL ((void *) 0) #endif -#ifndef MIN -#define MIN(a,b) ((a)>(b) ? (b) : (a)) -#endif - -#ifndef MAX -#define MAX(a,b) ((a)>(b) ? (a) : (b)) -#endif - #ifndef far #define far #endif diff --git a/trunk/drivers/isdn/hisax/Kconfig b/trunk/drivers/isdn/hisax/Kconfig index cfd2718a490d..6fa12cc8e4ff 100644 --- a/trunk/drivers/isdn/hisax/Kconfig +++ b/trunk/drivers/isdn/hisax/Kconfig @@ -349,13 +349,6 @@ config HISAX_ENTERNOW_PCI This enables HiSax support for the Formula-n enter:now PCI ISDN card. -config HISAX_AMD7930 - bool "Am7930 (EXPERIMENTAL)" - depends on EXPERIMENTAL && SPARC && BROKEN - help - This enables HiSax support for the AMD7930 chips on some SPARCs. - This code is not finished yet. - endif if ISDN_DRV_HISAX @@ -402,6 +395,7 @@ config HISAX_ST5481 tristate "ST5481 USB ISDN modem (EXPERIMENTAL)" depends on USB && EXPERIMENTAL select CRC_CCITT + select BITREVERSE help This enables the driver for ST5481 based USB ISDN adapters, e.g. the BeWan Gazel 128 USB diff --git a/trunk/drivers/isdn/hisax/amd7930_fn.c b/trunk/drivers/isdn/hisax/amd7930_fn.c index bec59010bc66..3b19caeba258 100644 --- a/trunk/drivers/isdn/hisax/amd7930_fn.c +++ b/trunk/drivers/isdn/hisax/amd7930_fn.c @@ -232,9 +232,10 @@ Amd7930_new_ph(struct IsdnCardState *cs) static void -Amd7930_bh(struct IsdnCardState *cs) +Amd7930_bh(struct work_struct *work) { - + struct IsdnCardState *cs = + container_of(work, struct IsdnCardState, tqueue); struct PStack *stptr; if (!cs) @@ -789,7 +790,7 @@ Amd7930_init(struct IsdnCardState *cs) void __devinit setup_Amd7930(struct IsdnCardState *cs) { - INIT_WORK(&cs->tqueue, (void *)(void *) Amd7930_bh, cs); + INIT_WORK(&cs->tqueue, Amd7930_bh); cs->dbusytimer.function = (void *) dbusy_timer_handler; cs->dbusytimer.data = (long) cs; init_timer(&cs->dbusytimer); diff --git a/trunk/drivers/isdn/hisax/avma1_cs.c b/trunk/drivers/isdn/hisax/avma1_cs.c index ac28e3278ad9..9e70c206779e 100644 --- a/trunk/drivers/isdn/hisax/avma1_cs.c +++ b/trunk/drivers/isdn/hisax/avma1_cs.c @@ -123,11 +123,10 @@ static int avma1cs_probe(struct pcmcia_device *p_dev) DEBUG(0, "avma1cs_attach()\n"); /* Allocate space for private device-specific data */ - local = kmalloc(sizeof(local_info_t), GFP_KERNEL); + local = kzalloc(sizeof(local_info_t), GFP_KERNEL); if (!local) return -ENOMEM; - memset(local, 0, sizeof(local_info_t)); p_dev->priv = local; /* The io structure describes IO port mapping */ @@ -216,41 +215,11 @@ static int avma1cs_config(struct pcmcia_device *link) DEBUG(0, "avma1cs_config(0x%p)\n", link); - /* - This reads the card's CONFIG tuple to find its configuration - registers. - */ do { - tuple.DesiredTuple = CISTPL_CONFIG; - i = pcmcia_get_first_tuple(link, &tuple); - if (i != CS_SUCCESS) break; - tuple.TupleData = buf; - tuple.TupleDataMax = 64; - tuple.TupleOffset = 0; - i = pcmcia_get_tuple_data(link, &tuple); - if (i != CS_SUCCESS) break; - i = pcmcia_parse_tuple(link, &tuple, &parse); - if (i != CS_SUCCESS) break; - link->conf.ConfigBase = parse.config.base; - } while (0); - if (i != CS_SUCCESS) { - cs_error(link, ParseTuple, i); - return -ENODEV; - } - - do { - - tuple.Attributes = 0; - tuple.TupleData = buf; - tuple.TupleDataMax = 254; - tuple.TupleOffset = 0; - tuple.DesiredTuple = CISTPL_VERS_1; - devname[0] = 0; - if( !first_tuple(link, &tuple, &parse) && parse.version_1.ns > 1 ) { - strlcpy(devname,parse.version_1.str + parse.version_1.ofs[1], - sizeof(devname)); - } + if (link->prod_id[1]) + strlcpy(devname, link->prod_id[1], sizeof(devname)); + /* * find IO port */ diff --git a/trunk/drivers/isdn/hisax/config.c b/trunk/drivers/isdn/hisax/config.c index 785b08554fca..17ec0b70ba1d 100644 --- a/trunk/drivers/isdn/hisax/config.c +++ b/trunk/drivers/isdn/hisax/config.c @@ -227,14 +227,6 @@ const char *CardType[] = { #define DEFAULT_CFG {5,0x2E0,0,0} #endif - -#ifdef CONFIG_HISAX_AMD7930 -#undef DEFAULT_CARD -#undef DEFAULT_CFG -#define DEFAULT_CARD ISDN_CTYPE_AMD7930 -#define DEFAULT_CFG {12,0x3e0,0,0} -#endif - #ifdef CONFIG_HISAX_NICCY #undef DEFAULT_CARD #undef DEFAULT_CFG @@ -545,10 +537,6 @@ extern int setup_hfcpci(struct IsdnCard *card); extern int setup_hfcsx(struct IsdnCard *card); #endif -#if CARD_AMD7930 -extern int setup_amd7930(struct IsdnCard *card); -#endif - #if CARD_NICCY extern int setup_niccy(struct IsdnCard *card); #endif @@ -869,14 +857,13 @@ static int checkcard(int cardnr, char *id, int *busy_flag, struct module *lockow struct IsdnCard *card = cards + cardnr; struct IsdnCardState *cs; - cs = kmalloc(sizeof(struct IsdnCardState), GFP_ATOMIC); + cs = kzalloc(sizeof(struct IsdnCardState), GFP_ATOMIC); if (!cs) { printk(KERN_WARNING "HiSax: No memory for IsdnCardState(card %d)\n", cardnr + 1); goto out; } - memset(cs, 0, sizeof(struct IsdnCardState)); card->cs = cs; spin_lock_init(&cs->statlock); spin_lock_init(&cs->lock); @@ -1064,11 +1051,6 @@ static int checkcard(int cardnr, char *id, int *busy_flag, struct module *lockow ret = setup_niccy(card); break; #endif -#if CARD_AMD7930 - case ISDN_CTYPE_AMD7930: - ret = setup_amd7930(card); - break; -#endif #if CARD_ISURF case ISDN_CTYPE_ISURF: ret = setup_isurf(card); @@ -1137,7 +1119,6 @@ static int checkcard(int cardnr, char *id, int *busy_flag, struct module *lockow cs->tx_skb = NULL; cs->tx_cnt = 0; cs->event = 0; - cs->tqueue.data = cs; skb_queue_head_init(&cs->rq); skb_queue_head_init(&cs->sq); @@ -1438,7 +1419,6 @@ static int __init HiSax_init(void) break; case ISDN_CTYPE_ELSA_PCI: case ISDN_CTYPE_NETJET_S: - case ISDN_CTYPE_AMD7930: case ISDN_CTYPE_TELESPCI: case ISDN_CTYPE_W6692: case ISDN_CTYPE_NETJET_U: @@ -1554,7 +1534,7 @@ static void hisax_b_l2l1(struct PStack *st, int pr, void *arg); static int hisax_cardmsg(struct IsdnCardState *cs, int mt, void *arg); static int hisax_bc_setstack(struct PStack *st, struct BCState *bcs); static void hisax_bc_close(struct BCState *bcs); -static void hisax_bh(struct IsdnCardState *cs); +static void hisax_bh(struct work_struct *work); static void EChannel_proc_rcv(struct hisax_d_if *d_if); int hisax_register(struct hisax_d_if *hisax_d_if, struct hisax_b_if *b_if[], @@ -1586,7 +1566,7 @@ int hisax_register(struct hisax_d_if *hisax_d_if, struct hisax_b_if *b_if[], hisax_d_if->cs = cs; cs->hw.hisax_d_if = hisax_d_if; cs->cardmsg = hisax_cardmsg; - INIT_WORK(&cs->tqueue, (void *)(void *)hisax_bh, cs); + INIT_WORK(&cs->tqueue, hisax_bh); cs->channel[0].d_st->l2.l2l1 = hisax_d_l2l1; for (i = 0; i < 2; i++) { cs->bcs[i].BC_SetStack = hisax_bc_setstack; @@ -1618,8 +1598,10 @@ static void hisax_sched_event(struct IsdnCardState *cs, int event) schedule_work(&cs->tqueue); } -static void hisax_bh(struct IsdnCardState *cs) +static void hisax_bh(struct work_struct *work) { + struct IsdnCardState *cs = + container_of(work, struct IsdnCardState, tqueue); struct PStack *st; int pr; diff --git a/trunk/drivers/isdn/hisax/diva.c b/trunk/drivers/isdn/hisax/diva.c index 3dacfff93f5f..6eebeb441bfd 100644 --- a/trunk/drivers/isdn/hisax/diva.c +++ b/trunk/drivers/isdn/hisax/diva.c @@ -1121,7 +1121,11 @@ setup_diva(struct IsdnCard *card) bytecnt = 32; } } + +#ifdef __ISAPNP__ ready: +#endif + printk(KERN_INFO "Diva: %s card configured at %#lx IRQ %d\n", (cs->subtyp == DIVA_PCI) ? "PCI" : diff --git a/trunk/drivers/isdn/hisax/elsa_cs.c b/trunk/drivers/isdn/hisax/elsa_cs.c index e18e75be8ed3..79ab9dda7d08 100644 --- a/trunk/drivers/isdn/hisax/elsa_cs.c +++ b/trunk/drivers/isdn/hisax/elsa_cs.c @@ -146,9 +146,8 @@ static int elsa_cs_probe(struct pcmcia_device *link) DEBUG(0, "elsa_cs_attach()\n"); /* Allocate space for private device-specific data */ - local = kmalloc(sizeof(local_info_t), GFP_KERNEL); + local = kzalloc(sizeof(local_info_t), GFP_KERNEL); if (!local) return -ENOMEM; - memset(local, 0, sizeof(local_info_t)); local->p_dev = link; link->priv = local; @@ -242,23 +241,6 @@ static int elsa_cs_config(struct pcmcia_device *link) DEBUG(0, "elsa_config(0x%p)\n", link); dev = link->priv; - /* - This reads the card's CONFIG tuple to find its configuration - registers. - */ - tuple.DesiredTuple = CISTPL_CONFIG; - tuple.TupleData = (cisdata_t *)buf; - tuple.TupleDataMax = 255; - tuple.TupleOffset = 0; - tuple.Attributes = 0; - i = first_tuple(link, &tuple, &parse); - if (i != CS_SUCCESS) { - last_fn = ParseTuple; - goto cs_failed; - } - link->conf.ConfigBase = parse.config.base; - link->conf.Present = parse.config.rmask[0]; - tuple.TupleData = (cisdata_t *)buf; tuple.TupleOffset = 0; tuple.TupleDataMax = 255; tuple.Attributes = 0; diff --git a/trunk/drivers/isdn/hisax/fsm.c b/trunk/drivers/isdn/hisax/fsm.c index 0d44a3f480ac..34fade96a581 100644 --- a/trunk/drivers/isdn/hisax/fsm.c +++ b/trunk/drivers/isdn/hisax/fsm.c @@ -26,12 +26,10 @@ FsmNew(struct Fsm *fsm, struct FsmNode *fnlist, int fncount) int i; fsm->jumpmatrix = (FSMFNPTR *) - kmalloc(sizeof (FSMFNPTR) * fsm->state_count * fsm->event_count, GFP_KERNEL); + kzalloc(sizeof (FSMFNPTR) * fsm->state_count * fsm->event_count, GFP_KERNEL); if (!fsm->jumpmatrix) return -ENOMEM; - memset(fsm->jumpmatrix, 0, sizeof (FSMFNPTR) * fsm->state_count * fsm->event_count); - for (i = 0; i < fncount; i++) if ((fnlist[i].state>=fsm->state_count) || (fnlist[i].event>=fsm->event_count)) { printk(KERN_ERR "FsmNew Error line %d st(%ld/%ld) ev(%ld/%ld)\n", diff --git a/trunk/drivers/isdn/hisax/hfc4s8s_l1.c b/trunk/drivers/isdn/hisax/hfc4s8s_l1.c index d852c9d998b2..a2fa4ecb8c88 100644 --- a/trunk/drivers/isdn/hisax/hfc4s8s_l1.c +++ b/trunk/drivers/isdn/hisax/hfc4s8s_l1.c @@ -1083,8 +1083,9 @@ tx_b_frame(struct hfc4s8s_btype *bch) /* bottom half handler for interrupt */ /*************************************/ static void -hfc4s8s_bh(hfc4s8s_hw * hw) +hfc4s8s_bh(struct work_struct *work) { + hfc4s8s_hw *hw = container_of(work, hfc4s8s_hw, tqueue); u_char b; struct hfc4s8s_l1 *l1p; volatile u_char *fifo_stat; @@ -1550,7 +1551,7 @@ setup_instance(hfc4s8s_hw * hw) goto out; } - INIT_WORK(&hw->tqueue, (void *) (void *) hfc4s8s_bh, hw); + INIT_WORK(&hw->tqueue, hfc4s8s_bh); if (request_irq (hw->irq, hfc4s8s_interrupt, IRQF_SHARED, hw->card_name, hw)) { @@ -1590,11 +1591,10 @@ hfc4s8s_probe(struct pci_dev *pdev, const struct pci_device_id *ent) hfc4s8s_param *driver_data = (hfc4s8s_param *) ent->driver_data; hfc4s8s_hw *hw; - if (!(hw = kmalloc(sizeof(hfc4s8s_hw), GFP_ATOMIC))) { + if (!(hw = kzalloc(sizeof(hfc4s8s_hw), GFP_ATOMIC))) { printk(KERN_ERR "No kmem for HFC-4S/8S card\n"); return (err); } - memset(hw, 0, sizeof(hfc4s8s_hw)); hw->pdev = pdev; err = pci_enable_device(pdev); diff --git a/trunk/drivers/isdn/hisax/hfc_2bds0.c b/trunk/drivers/isdn/hisax/hfc_2bds0.c index 6360e8214720..8d9864453a23 100644 --- a/trunk/drivers/isdn/hisax/hfc_2bds0.c +++ b/trunk/drivers/isdn/hisax/hfc_2bds0.c @@ -549,10 +549,11 @@ setstack_2b(struct PStack *st, struct BCState *bcs) } static void -hfcd_bh(struct IsdnCardState *cs) +hfcd_bh(struct work_struct *work) { - if (!cs) - return; + struct IsdnCardState *cs = + container_of(work, struct IsdnCardState, tqueue); + if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) { switch (cs->dc.hfcd.ph_state) { case (0): @@ -1072,5 +1073,5 @@ set_cs_func(struct IsdnCardState *cs) cs->dbusytimer.function = (void *) hfc_dbusy_timer; cs->dbusytimer.data = (long) cs; init_timer(&cs->dbusytimer); - INIT_WORK(&cs->tqueue, (void *)(void *) hfcd_bh, cs); + INIT_WORK(&cs->tqueue, hfcd_bh); } diff --git a/trunk/drivers/isdn/hisax/hfc_pci.c b/trunk/drivers/isdn/hisax/hfc_pci.c index 93f60b563515..8a48a3ce0a55 100644 --- a/trunk/drivers/isdn/hisax/hfc_pci.c +++ b/trunk/drivers/isdn/hisax/hfc_pci.c @@ -1211,7 +1211,7 @@ HFCPCI_l1hw(struct PStack *st, int pr, void *arg) break; case (HW_TESTLOOP | REQUEST): spin_lock_irqsave(&cs->lock, flags); - switch ((int) arg) { + switch ((long) arg) { case (1): Write_hfc(cs, HFCPCI_B1_SSL, 0x80); /* tx slot */ Write_hfc(cs, HFCPCI_B1_RSL, 0x80); /* rx slot */ @@ -1229,7 +1229,7 @@ HFCPCI_l1hw(struct PStack *st, int pr, void *arg) default: spin_unlock_irqrestore(&cs->lock, flags); if (cs->debug & L1_DEB_WARN) - debugl1(cs, "hfcpci_l1hw loop invalid %4x", (int) arg); + debugl1(cs, "hfcpci_l1hw loop invalid %4lx", (long) arg); return; } cs->hw.hfcpci.trm |= 0x80; /* enable IOM-loop */ @@ -1506,8 +1506,10 @@ setstack_2b(struct PStack *st, struct BCState *bcs) /* handle L1 state changes */ /***************************/ static void -hfcpci_bh(struct IsdnCardState *cs) +hfcpci_bh(struct work_struct *work) { + struct IsdnCardState *cs = + container_of(work, struct IsdnCardState, tqueue); u_long flags; // struct PStack *stptr; @@ -1709,9 +1711,9 @@ setup_hfcpci(struct IsdnCard *card) pci_write_config_dword(cs->hw.hfcpci.dev, 0x80, (u_int) virt_to_bus(cs->hw.hfcpci.fifos)); cs->hw.hfcpci.pci_io = ioremap((ulong) cs->hw.hfcpci.pci_io, 256); printk(KERN_INFO - "HFC-PCI: defined at mem %#x fifo %#x(%#x) IRQ %d HZ %d\n", - (u_int) cs->hw.hfcpci.pci_io, - (u_int) cs->hw.hfcpci.fifos, + "HFC-PCI: defined at mem %p fifo %p(%#x) IRQ %d HZ %d\n", + cs->hw.hfcpci.pci_io, + cs->hw.hfcpci.fifos, (u_int) virt_to_bus(cs->hw.hfcpci.fifos), cs->irq, HZ); spin_lock_irqsave(&cs->lock, flags); @@ -1722,7 +1724,7 @@ setup_hfcpci(struct IsdnCard *card) Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2); /* At this point the needed PCI config is done */ /* fifos are still not enabled */ - INIT_WORK(&cs->tqueue, (void *)(void *) hfcpci_bh, cs); + INIT_WORK(&cs->tqueue, hfcpci_bh); cs->setstack_d = setstack_hfcpci; cs->BC_Send_Data = &hfcpci_send_data; cs->readisac = NULL; diff --git a/trunk/drivers/isdn/hisax/hfc_sx.c b/trunk/drivers/isdn/hisax/hfc_sx.c index 954d1536db1f..4fd09d21a27f 100644 --- a/trunk/drivers/isdn/hisax/hfc_sx.c +++ b/trunk/drivers/isdn/hisax/hfc_sx.c @@ -1251,8 +1251,10 @@ setstack_2b(struct PStack *st, struct BCState *bcs) /* handle L1 state changes */ /***************************/ static void -hfcsx_bh(struct IsdnCardState *cs) +hfcsx_bh(struct work_struct *work) { + struct IsdnCardState *cs = + container_of(work, struct IsdnCardState, tqueue); u_long flags; if (!cs) @@ -1499,7 +1501,7 @@ setup_hfcsx(struct IsdnCard *card) cs->dbusytimer.function = (void *) hfcsx_dbusy_timer; cs->dbusytimer.data = (long) cs; init_timer(&cs->dbusytimer); - INIT_WORK(&cs->tqueue, (void *)(void *) hfcsx_bh, cs); + INIT_WORK(&cs->tqueue, hfcsx_bh); cs->readisac = NULL; cs->writeisac = NULL; cs->readisacfifo = NULL; diff --git a/trunk/drivers/isdn/hisax/hfc_usb.c b/trunk/drivers/isdn/hisax/hfc_usb.c index 7105b043add8..5a6989f23fcf 100644 --- a/trunk/drivers/isdn/hisax/hfc_usb.c +++ b/trunk/drivers/isdn/hisax/hfc_usb.c @@ -1481,9 +1481,8 @@ hfc_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) iface = iface_used; if (! (context = - kmalloc(sizeof(hfcusb_data), GFP_KERNEL))) + kzalloc(sizeof(hfcusb_data), GFP_KERNEL))) return (-ENOMEM); /* got no mem */ - memset(context, 0, sizeof(hfcusb_data)); ep = iface->endpoint; vcf = validconf[small_match]; diff --git a/trunk/drivers/isdn/hisax/hisax.h b/trunk/drivers/isdn/hisax/hisax.h index 159c5896061e..3f1137e34678 100644 --- a/trunk/drivers/isdn/hisax/hisax.h +++ b/trunk/drivers/isdn/hisax/hisax.h @@ -1139,12 +1139,6 @@ struct IsdnCardState { #define CARD_HFC_SX 0 #endif -#ifdef CONFIG_HISAX_AMD7930 -#define CARD_AMD7930 1 -#else -#define CARD_AMD7930 0 -#endif - #ifdef CONFIG_HISAX_NICCY #define CARD_NICCY 1 #ifndef ISDN_CHIP_ISAC diff --git a/trunk/drivers/isdn/hisax/hisax_fcpcipnp.c b/trunk/drivers/isdn/hisax/hisax_fcpcipnp.c index f6db55a752c4..9e088fce8c3a 100644 --- a/trunk/drivers/isdn/hisax/hisax_fcpcipnp.c +++ b/trunk/drivers/isdn/hisax/hisax_fcpcipnp.c @@ -841,12 +841,10 @@ new_adapter(void) struct hisax_b_if *b_if[2]; int i; - adapter = kmalloc(sizeof(struct fritz_adapter), GFP_KERNEL); + adapter = kzalloc(sizeof(struct fritz_adapter), GFP_KERNEL); if (!adapter) return NULL; - memset(adapter, 0, sizeof(struct fritz_adapter)); - adapter->isac.hisax_d_if.owner = THIS_MODULE; adapter->isac.hisax_d_if.ifc.priv = &adapter->isac; adapter->isac.hisax_d_if.ifc.l2l1 = isac_d_l2l1; diff --git a/trunk/drivers/isdn/hisax/hisax_isac.c b/trunk/drivers/isdn/hisax/hisax_isac.c index 81eac344bb03..d0fefcf999cb 100644 --- a/trunk/drivers/isdn/hisax/hisax_isac.c +++ b/trunk/drivers/isdn/hisax/hisax_isac.c @@ -433,7 +433,7 @@ static void l1m_debug(struct FsmInst *fi, char *fmt, ...) char buf[256]; va_start(args, fmt); - vsprintf(buf, fmt, args); + vsnprintf(buf, sizeof(buf), fmt, args); DBG(DBG_L1M, "%s", buf); va_end(args); } diff --git a/trunk/drivers/isdn/hisax/icc.c b/trunk/drivers/isdn/hisax/icc.c index da706925d54d..682cac32f259 100644 --- a/trunk/drivers/isdn/hisax/icc.c +++ b/trunk/drivers/isdn/hisax/icc.c @@ -77,8 +77,10 @@ icc_new_ph(struct IsdnCardState *cs) } static void -icc_bh(struct IsdnCardState *cs) +icc_bh(struct work_struct *work) { + struct IsdnCardState *cs = + container_of(work, struct IsdnCardState, tqueue); struct PStack *stptr; if (!cs) @@ -674,7 +676,7 @@ clear_pending_icc_ints(struct IsdnCardState *cs) void __devinit setup_icc(struct IsdnCardState *cs) { - INIT_WORK(&cs->tqueue, (void *)(void *) icc_bh, cs); + INIT_WORK(&cs->tqueue, icc_bh); cs->dbusytimer.function = (void *) dbusy_timer_handler; cs->dbusytimer.data = (long) cs; init_timer(&cs->dbusytimer); diff --git a/trunk/drivers/isdn/hisax/isac.c b/trunk/drivers/isdn/hisax/isac.c index 282f349408bc..4e9f23803dae 100644 --- a/trunk/drivers/isdn/hisax/isac.c +++ b/trunk/drivers/isdn/hisax/isac.c @@ -81,8 +81,10 @@ isac_new_ph(struct IsdnCardState *cs) } static void -isac_bh(struct IsdnCardState *cs) +isac_bh(struct work_struct *work) { + struct IsdnCardState *cs = + container_of(work, struct IsdnCardState, tqueue); struct PStack *stptr; if (!cs) @@ -674,7 +676,7 @@ clear_pending_isac_ints(struct IsdnCardState *cs) void __devinit setup_isac(struct IsdnCardState *cs) { - INIT_WORK(&cs->tqueue, (void *)(void *) isac_bh, cs); + INIT_WORK(&cs->tqueue, isac_bh); cs->dbusytimer.function = (void *) dbusy_timer_handler; cs->dbusytimer.data = (long) cs; init_timer(&cs->dbusytimer); diff --git a/trunk/drivers/isdn/hisax/isar.c b/trunk/drivers/isdn/hisax/isar.c index 674af673ff96..6f1a6583b17d 100644 --- a/trunk/drivers/isdn/hisax/isar.c +++ b/trunk/drivers/isdn/hisax/isar.c @@ -437,8 +437,10 @@ extern void BChannel_bh(struct BCState *); #define B_LL_OK 10 static void -isar_bh(struct BCState *bcs) +isar_bh(struct work_struct *work) { + struct BCState *bcs = container_of(work, struct BCState, tqueue); + BChannel_bh(bcs); if (test_and_clear_bit(B_LL_NOCARRIER, &bcs->event)) ll_deliver_faxstat(bcs, ISDN_FAX_CLASS1_NOCARR); @@ -1580,7 +1582,7 @@ isar_setup(struct IsdnCardState *cs) cs->bcs[i].mode = 0; cs->bcs[i].hw.isar.dpath = i + 1; modeisar(&cs->bcs[i], 0, 0); - INIT_WORK(&cs->bcs[i].tqueue, (void *)(void *) isar_bh, &cs->bcs[i]); + INIT_WORK(&cs->bcs[i].tqueue, isar_bh); } } diff --git a/trunk/drivers/isdn/hisax/isdnhdlc.c b/trunk/drivers/isdn/hisax/isdnhdlc.c index cbdf54c5af84..268dced6c34a 100644 --- a/trunk/drivers/isdn/hisax/isdnhdlc.c +++ b/trunk/drivers/isdn/hisax/isdnhdlc.c @@ -35,30 +35,6 @@ MODULE_LICENSE("GPL"); /*-------------------------------------------------------------------*/ -/* bit swap table. - * Very handy for devices with different bit order, - * and neccessary for each transparent B-channel access for all - * devices which works with this HDLC decoder without bit reversal. - */ -const unsigned char isdnhdlc_bit_rev_tab[256] = { - 0x00,0x80,0x40,0xC0,0x20,0xA0,0x60,0xE0,0x10,0x90,0x50,0xD0,0x30,0xB0,0x70,0xF0, - 0x08,0x88,0x48,0xC8,0x28,0xA8,0x68,0xE8,0x18,0x98,0x58,0xD8,0x38,0xB8,0x78,0xF8, - 0x04,0x84,0x44,0xC4,0x24,0xA4,0x64,0xE4,0x14,0x94,0x54,0xD4,0x34,0xB4,0x74,0xF4, - 0x0C,0x8C,0x4C,0xCC,0x2C,0xAC,0x6C,0xEC,0x1C,0x9C,0x5C,0xDC,0x3C,0xBC,0x7C,0xFC, - 0x02,0x82,0x42,0xC2,0x22,0xA2,0x62,0xE2,0x12,0x92,0x52,0xD2,0x32,0xB2,0x72,0xF2, - 0x0A,0x8A,0x4A,0xCA,0x2A,0xAA,0x6A,0xEA,0x1A,0x9A,0x5A,0xDA,0x3A,0xBA,0x7A,0xFA, - 0x06,0x86,0x46,0xC6,0x26,0xA6,0x66,0xE6,0x16,0x96,0x56,0xD6,0x36,0xB6,0x76,0xF6, - 0x0E,0x8E,0x4E,0xCE,0x2E,0xAE,0x6E,0xEE,0x1E,0x9E,0x5E,0xDE,0x3E,0xBE,0x7E,0xFE, - 0x01,0x81,0x41,0xC1,0x21,0xA1,0x61,0xE1,0x11,0x91,0x51,0xD1,0x31,0xB1,0x71,0xF1, - 0x09,0x89,0x49,0xC9,0x29,0xA9,0x69,0xE9,0x19,0x99,0x59,0xD9,0x39,0xB9,0x79,0xF9, - 0x05,0x85,0x45,0xC5,0x25,0xA5,0x65,0xE5,0x15,0x95,0x55,0xD5,0x35,0xB5,0x75,0xF5, - 0x0D,0x8D,0x4D,0xCD,0x2D,0xAD,0x6D,0xED,0x1D,0x9D,0x5D,0xDD,0x3D,0xBD,0x7D,0xFD, - 0x03,0x83,0x43,0xC3,0x23,0xA3,0x63,0xE3,0x13,0x93,0x53,0xD3,0x33,0xB3,0x73,0xF3, - 0x0B,0x8B,0x4B,0xCB,0x2B,0xAB,0x6B,0xEB,0x1B,0x9B,0x5B,0xDB,0x3B,0xBB,0x7B,0xFB, - 0x07,0x87,0x47,0xC7,0x27,0xA7,0x67,0xE7,0x17,0x97,0x57,0xD7,0x37,0xB7,0x77,0xF7, - 0x0F,0x8F,0x4F,0xCF,0x2F,0xAF,0x6F,0xEF,0x1F,0x9F,0x5F,0xDF,0x3F,0xBF,0x7F,0xFF -}; - enum { HDLC_FAST_IDLE,HDLC_GET_FLAG_B0,HDLC_GETFLAG_B1A6,HDLC_GETFLAG_B7, HDLC_GET_DATA,HDLC_FAST_FLAG @@ -621,7 +597,6 @@ int isdnhdlc_encode(struct isdnhdlc_vars *hdlc, const unsigned char *src, return len; } -EXPORT_SYMBOL(isdnhdlc_bit_rev_tab); EXPORT_SYMBOL(isdnhdlc_rcv_init); EXPORT_SYMBOL(isdnhdlc_decode); EXPORT_SYMBOL(isdnhdlc_out_init); diff --git a/trunk/drivers/isdn/hisax/isdnhdlc.h b/trunk/drivers/isdn/hisax/isdnhdlc.h index 269315988dc8..45167d2f8fb0 100644 --- a/trunk/drivers/isdn/hisax/isdnhdlc.h +++ b/trunk/drivers/isdn/hisax/isdnhdlc.h @@ -41,10 +41,10 @@ struct isdnhdlc_vars { unsigned char shift_reg; unsigned char ffvalue; - int data_received:1; // set if transferring data - int dchannel:1; // set if D channel (send idle instead of flags) - int do_adapt56:1; // set if 56K adaptation - int do_closing:1; // set if in closing phase (need to send CRC + flag + unsigned int data_received:1; // set if transferring data + unsigned int dchannel:1; // set if D channel (send idle instead of flags) + unsigned int do_adapt56:1; // set if 56K adaptation + unsigned int do_closing:1; // set if in closing phase (need to send CRC + flag }; @@ -57,8 +57,6 @@ struct isdnhdlc_vars { #define HDLC_CRC_ERROR 2 #define HDLC_LENGTH_ERROR 3 -extern const unsigned char isdnhdlc_bit_rev_tab[256]; - extern void isdnhdlc_rcv_init (struct isdnhdlc_vars *hdlc, int do_adapt56); extern int isdnhdlc_decode (struct isdnhdlc_vars *hdlc, const unsigned char *src, int slen,int *count, diff --git a/trunk/drivers/isdn/hisax/isdnl1.c b/trunk/drivers/isdn/hisax/isdnl1.c index bab356886483..a14204ec88ee 100644 --- a/trunk/drivers/isdn/hisax/isdnl1.c +++ b/trunk/drivers/isdn/hisax/isdnl1.c @@ -315,8 +315,10 @@ BChannel_proc_ack(struct BCState *bcs) } void -BChannel_bh(struct BCState *bcs) +BChannel_bh(struct work_struct *work) { + struct BCState *bcs = container_of(work, struct BCState, tqueue); + if (!bcs) return; if (test_and_clear_bit(B_RCVBUFREADY, &bcs->event)) @@ -362,7 +364,7 @@ init_bcstate(struct IsdnCardState *cs, int bc) bcs->cs = cs; bcs->channel = bc; - INIT_WORK(&bcs->tqueue, (void *)(void *) BChannel_bh, bcs); + INIT_WORK(&bcs->tqueue, BChannel_bh); spin_lock_init(&bcs->aclock); bcs->BC_SetStack = NULL; bcs->BC_Close = NULL; diff --git a/trunk/drivers/isdn/hisax/sedlbauer.c b/trunk/drivers/isdn/hisax/sedlbauer.c index 9522141f4351..030d1625c5c6 100644 --- a/trunk/drivers/isdn/hisax/sedlbauer.c +++ b/trunk/drivers/isdn/hisax/sedlbauer.c @@ -677,7 +677,11 @@ setup_sedlbauer(struct IsdnCard *card) return (0); #endif /* CONFIG_PCI */ } + +#ifdef __ISAPNP__ ready: +#endif + /* In case of the sedlbauer pcmcia card, this region is in use, * reserved for us by the card manager. So we do not check it * here, it would fail. diff --git a/trunk/drivers/isdn/hisax/sedlbauer_cs.c b/trunk/drivers/isdn/hisax/sedlbauer_cs.c index f9c14a2970bc..45debde05fbd 100644 --- a/trunk/drivers/isdn/hisax/sedlbauer_cs.c +++ b/trunk/drivers/isdn/hisax/sedlbauer_cs.c @@ -155,9 +155,8 @@ static int sedlbauer_probe(struct pcmcia_device *link) DEBUG(0, "sedlbauer_attach()\n"); /* Allocate space for private device-specific data */ - local = kmalloc(sizeof(local_info_t), GFP_KERNEL); + local = kzalloc(sizeof(local_info_t), GFP_KERNEL); if (!local) return -ENOMEM; - memset(local, 0, sizeof(local_info_t)); local->cardnr = -1; local->p_dev = link; @@ -233,20 +232,10 @@ static int sedlbauer_config(struct pcmcia_device *link) DEBUG(0, "sedlbauer_config(0x%p)\n", link); - /* - This reads the card's CONFIG tuple to find its configuration - registers. - */ - tuple.DesiredTuple = CISTPL_CONFIG; tuple.Attributes = 0; tuple.TupleData = buf; tuple.TupleDataMax = sizeof(buf); tuple.TupleOffset = 0; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); - link->conf.ConfigBase = parse.config.base; - link->conf.Present = parse.config.rmask[0]; CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &conf)); diff --git a/trunk/drivers/isdn/hisax/st5481_b.c b/trunk/drivers/isdn/hisax/st5481_b.c index 75d0f248e4ee..fa64115cd7c7 100644 --- a/trunk/drivers/isdn/hisax/st5481_b.c +++ b/trunk/drivers/isdn/hisax/st5481_b.c @@ -14,6 +14,7 @@ #include #include #include +#include #include "st5481.h" static inline void B_L1L2(struct st5481_bcs *bcs, int pr, void *arg) @@ -72,7 +73,7 @@ static void usb_b_out(struct st5481_bcs *bcs,int buf_nr) register unsigned char *dest = urb->transfer_buffer+len; register unsigned int count; for (count = 0; count < bytes_sent; count++) - *dest++ = isdnhdlc_bit_rev_tab[*src++]; + *dest++ = bitrev8(*src++); } len += bytes_sent; } else { diff --git a/trunk/drivers/isdn/hisax/st5481_d.c b/trunk/drivers/isdn/hisax/st5481_d.c index 1d8c2618366c..b8c4855cc889 100644 --- a/trunk/drivers/isdn/hisax/st5481_d.c +++ b/trunk/drivers/isdn/hisax/st5481_d.c @@ -173,7 +173,7 @@ static void l1m_debug(struct FsmInst *fi, char *fmt, ...) char buf[256]; va_start(args, fmt); - vsprintf(buf, fmt, args); + vsnprintf(buf, sizeof(buf), fmt, args); DBG(8, "%s", buf); va_end(args); } @@ -275,7 +275,7 @@ static void dout_debug(struct FsmInst *fi, char *fmt, ...) char buf[256]; va_start(args, fmt); - vsprintf(buf, fmt, args); + vsnprintf(buf, sizeof(buf), fmt, args); DBG(0x2, "%s", buf); va_end(args); } diff --git a/trunk/drivers/isdn/hisax/st5481_init.c b/trunk/drivers/isdn/hisax/st5481_init.c index 2716aa5c60f7..bb3a28a53ff4 100644 --- a/trunk/drivers/isdn/hisax/st5481_init.c +++ b/trunk/drivers/isdn/hisax/st5481_init.c @@ -69,12 +69,10 @@ static int probe_st5481(struct usb_interface *intf, le16_to_cpu(dev->descriptor.idProduct), number_of_leds); - adapter = kmalloc(sizeof(struct st5481_adapter), GFP_KERNEL); + adapter = kzalloc(sizeof(struct st5481_adapter), GFP_KERNEL); if (!adapter) return -ENOMEM; - memset(adapter, 0, sizeof(struct st5481_adapter)); - adapter->number_of_leds = number_of_leds; adapter->usb_dev = dev; diff --git a/trunk/drivers/isdn/hisax/teles_cs.c b/trunk/drivers/isdn/hisax/teles_cs.c index afcc2aeadb34..3e3e18239ec7 100644 --- a/trunk/drivers/isdn/hisax/teles_cs.c +++ b/trunk/drivers/isdn/hisax/teles_cs.c @@ -137,9 +137,8 @@ static int teles_probe(struct pcmcia_device *link) DEBUG(0, "teles_attach()\n"); /* Allocate space for private device-specific data */ - local = kmalloc(sizeof(local_info_t), GFP_KERNEL); + local = kzalloc(sizeof(local_info_t), GFP_KERNEL); if (!local) return -ENOMEM; - memset(local, 0, sizeof(local_info_t)); local->cardnr = -1; local->p_dev = link; @@ -232,23 +231,6 @@ static int teles_cs_config(struct pcmcia_device *link) DEBUG(0, "teles_config(0x%p)\n", link); dev = link->priv; - /* - This reads the card's CONFIG tuple to find its configuration - registers. - */ - tuple.DesiredTuple = CISTPL_CONFIG; - tuple.TupleData = (cisdata_t *)buf; - tuple.TupleDataMax = 255; - tuple.TupleOffset = 0; - tuple.Attributes = 0; - i = first_tuple(link, &tuple, &parse); - if (i != CS_SUCCESS) { - last_fn = ParseTuple; - goto cs_failed; - } - link->conf.ConfigBase = parse.config.base; - link->conf.Present = parse.config.rmask[0]; - tuple.TupleData = (cisdata_t *)buf; tuple.TupleOffset = 0; tuple.TupleDataMax = 255; tuple.Attributes = 0; diff --git a/trunk/drivers/isdn/hisax/w6692.c b/trunk/drivers/isdn/hisax/w6692.c index 1655341797a9..3aeceaf9769e 100644 --- a/trunk/drivers/isdn/hisax/w6692.c +++ b/trunk/drivers/isdn/hisax/w6692.c @@ -101,8 +101,10 @@ W6692_new_ph(struct IsdnCardState *cs) } static void -W6692_bh(struct IsdnCardState *cs) +W6692_bh(struct work_struct *work) { + struct IsdnCardState *cs = + container_of(work, struct IsdnCardState, tqueue); struct PStack *stptr; if (!cs) @@ -1070,7 +1072,7 @@ setup_w6692(struct IsdnCard *card) id_list[cs->subtyp].card_name, cs->irq, cs->hw.w6692.iobase); - INIT_WORK(&cs->tqueue, (void *)(void *) W6692_bh, cs); + INIT_WORK(&cs->tqueue, W6692_bh); cs->readW6692 = &ReadW6692; cs->writeW6692 = &WriteW6692; cs->readisacfifo = &ReadISACfifo; diff --git a/trunk/drivers/isdn/hysdn/boardergo.c b/trunk/drivers/isdn/hysdn/boardergo.c index 82e42a80dc4b..a1206498a1cf 100644 --- a/trunk/drivers/isdn/hysdn/boardergo.c +++ b/trunk/drivers/isdn/hysdn/boardergo.c @@ -71,8 +71,9 @@ ergo_interrupt(int intno, void *dev_id) /* may be queued from everywhere (interrupts included). */ /******************************************************************************/ static void -ergo_irq_bh(hysdn_card * card) +ergo_irq_bh(struct work_struct *ugli_api) { + hysdn_card * card = container_of(ugli_api, hysdn_card, irq_queue); tErgDpram *dpr; int again; unsigned long flags; @@ -442,7 +443,7 @@ ergo_inithardware(hysdn_card * card) card->writebootseq = ergo_writebootseq; card->waitpofready = ergo_waitpofready; card->set_errlog_state = ergo_set_errlog_state; - INIT_WORK(&card->irq_queue, (void *) (void *) ergo_irq_bh, card); + INIT_WORK(&card->irq_queue, ergo_irq_bh); card->hysdn_lock = SPIN_LOCK_UNLOCKED; return (0); diff --git a/trunk/drivers/isdn/hysdn/hycapi.c b/trunk/drivers/isdn/hysdn/hycapi.c index 6bac43cc91bd..b2ae4ec1e49e 100644 --- a/trunk/drivers/isdn/hysdn/hycapi.c +++ b/trunk/drivers/isdn/hysdn/hycapi.c @@ -745,12 +745,11 @@ hycapi_capi_create(hysdn_card *card) return 1; } if (!card->hyctrlinfo) { - cinfo = (hycapictrl_info *) kmalloc(sizeof(hycapictrl_info), GFP_ATOMIC); + cinfo = kzalloc(sizeof(hycapictrl_info), GFP_ATOMIC); if (!cinfo) { printk(KERN_WARNING "HYSDN: no memory for capi-ctrl.\n"); return -ENOMEM; } - memset(cinfo, 0, sizeof(hycapictrl_info)); card->hyctrlinfo = cinfo; cinfo->card = card; spin_lock_init(&cinfo->lock); diff --git a/trunk/drivers/isdn/hysdn/hysdn_boot.c b/trunk/drivers/isdn/hysdn/hysdn_boot.c index 6d0eb0f42fca..be787e16bb79 100644 --- a/trunk/drivers/isdn/hysdn/hysdn_boot.c +++ b/trunk/drivers/isdn/hysdn/hysdn_boot.c @@ -278,14 +278,13 @@ pof_write_open(hysdn_card * card, unsigned char **bufp) return (-ERR_ALREADY_BOOT); /* boot already active */ } /* error no mem available */ - if (!(boot = kmalloc(sizeof(struct boot_data), GFP_KERNEL))) { + if (!(boot = kzalloc(sizeof(struct boot_data), GFP_KERNEL))) { if (card->debug_flags & LOG_MEM_ERR) hysdn_addlog(card, "POF open: unable to allocate mem"); return (-EFAULT); } card->boot = boot; card->state = CARD_STATE_BOOTING; - memset(boot, 0, sizeof(struct boot_data)); card->stopcard(card); /* first stop the card */ if (card->testram(card)) { diff --git a/trunk/drivers/isdn/hysdn/hysdn_init.c b/trunk/drivers/isdn/hysdn/hysdn_init.c index b702ed27252b..9e01748a176e 100644 --- a/trunk/drivers/isdn/hysdn/hysdn_init.c +++ b/trunk/drivers/isdn/hysdn/hysdn_init.c @@ -81,11 +81,10 @@ search_cards(void) if (pci_enable_device(akt_pcidev)) continue; - if (!(card = kmalloc(sizeof(hysdn_card), GFP_KERNEL))) { + if (!(card = kzalloc(sizeof(hysdn_card), GFP_KERNEL))) { printk(KERN_ERR "HYSDN: unable to alloc device mem \n"); return; } - memset(card, 0, sizeof(hysdn_card)); card->myid = cardmax; /* set own id */ card->bus = akt_pcidev->bus->number; card->devfn = akt_pcidev->devfn; /* slot + function */ diff --git a/trunk/drivers/isdn/hysdn/hysdn_net.c b/trunk/drivers/isdn/hysdn/hysdn_net.c index d205249a1242..557d96c78a62 100644 --- a/trunk/drivers/isdn/hysdn/hysdn_net.c +++ b/trunk/drivers/isdn/hysdn/hysdn_net.c @@ -278,11 +278,10 @@ hysdn_net_create(hysdn_card * card) return (-ENOMEM); } hysdn_net_release(card); /* release an existing net device */ - if ((dev = kmalloc(sizeof(struct net_local), GFP_KERNEL)) == NULL) { + if ((dev = kzalloc(sizeof(struct net_local), GFP_KERNEL)) == NULL) { printk(KERN_WARNING "HYSDN: unable to allocate mem\n"); return (-ENOMEM); } - memset(dev, 0, sizeof(struct net_local)); /* clean the structure */ spin_lock_init(&((struct net_local *) dev)->lock); diff --git a/trunk/drivers/isdn/hysdn/hysdn_proclog.c b/trunk/drivers/isdn/hysdn/hysdn_proclog.c index fcd49920b220..f241f5e551cb 100644 --- a/trunk/drivers/isdn/hysdn/hysdn_proclog.c +++ b/trunk/drivers/isdn/hysdn/hysdn_proclog.c @@ -204,7 +204,7 @@ hysdn_log_read(struct file *file, char __user *buf, size_t count, loff_t * off) { struct log_data *inf; int len; - struct proc_dir_entry *pde = PDE(file->f_dentry->d_inode); + struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode); struct procdata *pd = NULL; hysdn_card *card; @@ -354,7 +354,7 @@ static unsigned int hysdn_log_poll(struct file *file, poll_table * wait) { unsigned int mask = 0; - struct proc_dir_entry *pde = PDE(file->f_dentry->d_inode); + struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode); hysdn_card *card; struct procdata *pd = NULL; @@ -405,8 +405,7 @@ hysdn_proclog_init(hysdn_card * card) /* create a cardlog proc entry */ - if ((pd = (struct procdata *) kmalloc(sizeof(struct procdata), GFP_KERNEL)) != NULL) { - memset(pd, 0, sizeof(struct procdata)); + if ((pd = kzalloc(sizeof(struct procdata), GFP_KERNEL)) != NULL) { sprintf(pd->log_name, "%s%d", PROC_LOG_BASENAME, card->myid); if ((pd->log = create_proc_entry(pd->log_name, S_IFREG | S_IRUGO | S_IWUSR, hysdn_proc_entry)) != NULL) { pd->log->proc_fops = &log_fops; diff --git a/trunk/drivers/isdn/i4l/isdn_bsdcomp.c b/trunk/drivers/isdn/i4l/isdn_bsdcomp.c index 0afe442db3b0..a20f33b4a220 100644 --- a/trunk/drivers/isdn/i4l/isdn_bsdcomp.c +++ b/trunk/drivers/isdn/i4l/isdn_bsdcomp.c @@ -331,12 +331,10 @@ static void *bsd_alloc (struct isdn_ppp_comp_data *data) * Allocate the main control structure for this instance. */ maxmaxcode = MAXCODE(bits); - db = (struct bsd_db *) kmalloc (sizeof (struct bsd_db),GFP_KERNEL); + db = kzalloc (sizeof (struct bsd_db),GFP_KERNEL); if (!db) return NULL; - memset (db, 0, sizeof(struct bsd_db)); - db->xmit = data->flags & IPPP_COMP_FLAG_XMIT; decomp = db->xmit ? 0 : 1; diff --git a/trunk/drivers/isdn/i4l/isdn_common.c b/trunk/drivers/isdn/i4l/isdn_common.c index 69aee2602aa6..6a2ef0a87ed9 100644 --- a/trunk/drivers/isdn/i4l/isdn_common.c +++ b/trunk/drivers/isdn/i4l/isdn_common.c @@ -1059,7 +1059,7 @@ isdn_info_update(void) static ssize_t isdn_read(struct file *file, char __user *buf, size_t count, loff_t * off) { - uint minor = iminor(file->f_dentry->d_inode); + uint minor = iminor(file->f_path.dentry->d_inode); int len = 0; int drvidx; int chidx; @@ -1166,7 +1166,7 @@ isdn_read(struct file *file, char __user *buf, size_t count, loff_t * off) static ssize_t isdn_write(struct file *file, const char __user *buf, size_t count, loff_t * off) { - uint minor = iminor(file->f_dentry->d_inode); + uint minor = iminor(file->f_path.dentry->d_inode); int drvidx; int chidx; int retval; @@ -1228,7 +1228,7 @@ static unsigned int isdn_poll(struct file *file, poll_table * wait) { unsigned int mask = 0; - unsigned int minor = iminor(file->f_dentry->d_inode); + unsigned int minor = iminor(file->f_path.dentry->d_inode); int drvidx = isdn_minor2drv(minor - ISDN_MINOR_CTRL); lock_kernel(); @@ -2072,21 +2072,19 @@ isdn_add_channels(isdn_driver_t *d, int drvidx, int n, int adding) if ((adding) && (d->rcverr)) kfree(d->rcverr); - if (!(d->rcverr = kmalloc(sizeof(int) * m, GFP_ATOMIC))) { + if (!(d->rcverr = kzalloc(sizeof(int) * m, GFP_ATOMIC))) { printk(KERN_WARNING "register_isdn: Could not alloc rcverr\n"); return -1; } - memset((char *) d->rcverr, 0, sizeof(int) * m); if ((adding) && (d->rcvcount)) kfree(d->rcvcount); - if (!(d->rcvcount = kmalloc(sizeof(int) * m, GFP_ATOMIC))) { + if (!(d->rcvcount = kzalloc(sizeof(int) * m, GFP_ATOMIC))) { printk(KERN_WARNING "register_isdn: Could not alloc rcvcount\n"); if (!adding) kfree(d->rcverr); return -1; } - memset((char *) d->rcvcount, 0, sizeof(int) * m); if ((adding) && (d->rpqueue)) { for (j = 0; j < d->channels; j++) @@ -2226,11 +2224,10 @@ register_isdn(isdn_if * i) printk(KERN_WARNING "register_isdn: No write routine given.\n"); return 0; } - if (!(d = kmalloc(sizeof(isdn_driver_t), GFP_KERNEL))) { + if (!(d = kzalloc(sizeof(isdn_driver_t), GFP_KERNEL))) { printk(KERN_WARNING "register_isdn: Could not alloc driver-struct\n"); return 0; } - memset((char *) d, 0, sizeof(isdn_driver_t)); d->maxbufsize = i->maxbufsize; d->pktcount = 0; diff --git a/trunk/drivers/isdn/i4l/isdn_net.c b/trunk/drivers/isdn/i4l/isdn_net.c index 1f8d6ae66b41..c36c817578cb 100644 --- a/trunk/drivers/isdn/i4l/isdn_net.c +++ b/trunk/drivers/isdn/i4l/isdn_net.c @@ -984,9 +984,9 @@ void isdn_net_write_super(isdn_net_local *lp, struct sk_buff *skb) /* * called from tq_immediate */ -static void isdn_net_softint(void *private) +static void isdn_net_softint(struct work_struct *work) { - isdn_net_local *lp = private; + isdn_net_local *lp = container_of(work, isdn_net_local, tqueue); struct sk_buff *skb; spin_lock_bh(&lp->xmit_lock); @@ -2542,17 +2542,15 @@ isdn_net_new(char *name, struct net_device *master) printk(KERN_WARNING "isdn_net: interface %s already exists\n", name); return NULL; } - if (!(netdev = (isdn_net_dev *) kmalloc(sizeof(isdn_net_dev), GFP_KERNEL))) { + if (!(netdev = kzalloc(sizeof(isdn_net_dev), GFP_KERNEL))) { printk(KERN_WARNING "isdn_net: Could not allocate net-device\n"); return NULL; } - memset(netdev, 0, sizeof(isdn_net_dev)); - if (!(netdev->local = (isdn_net_local *) kmalloc(sizeof(isdn_net_local), GFP_KERNEL))) { + if (!(netdev->local = kzalloc(sizeof(isdn_net_local), GFP_KERNEL))) { printk(KERN_WARNING "isdn_net: Could not allocate device locals\n"); kfree(netdev); return NULL; } - memset(netdev->local, 0, sizeof(isdn_net_local)); if (name == NULL) strcpy(netdev->local->name, " "); else @@ -2596,7 +2594,7 @@ isdn_net_new(char *name, struct net_device *master) netdev->local->netdev = netdev; netdev->local->next = netdev->local; - INIT_WORK(&netdev->local->tqueue, (void *)(void *) isdn_net_softint, netdev->local); + INIT_WORK(&netdev->local->tqueue, isdn_net_softint); spin_lock_init(&netdev->local->xmit_lock); netdev->local->isdn_device = -1; diff --git a/trunk/drivers/isdn/i4l/isdn_ppp.c b/trunk/drivers/isdn/i4l/isdn_ppp.c index 119412d6bd15..43811795b46b 100644 --- a/trunk/drivers/isdn/i4l/isdn_ppp.c +++ b/trunk/drivers/isdn/i4l/isdn_ppp.c @@ -667,7 +667,7 @@ isdn_ppp_poll(struct file *file, poll_table * wait) if (is->debug & 0x2) printk(KERN_DEBUG "isdn_ppp_poll: minor: %d\n", - iminor(file->f_dentry->d_inode)); + iminor(file->f_path.dentry->d_inode)); /* just registers wait_queue hook. This doesn't really wait. */ poll_wait(file, &is->wq, wait); @@ -876,14 +876,12 @@ isdn_ppp_init(void) #endif /* CONFIG_ISDN_MPP */ for (i = 0; i < ISDN_MAX_CHANNELS; i++) { - if (!(ippp_table[i] = (struct ippp_struct *) - kmalloc(sizeof(struct ippp_struct), GFP_KERNEL))) { + if (!(ippp_table[i] = kzalloc(sizeof(struct ippp_struct), GFP_KERNEL))) { printk(KERN_WARNING "isdn_ppp_init: Could not alloc ippp_table\n"); for (j = 0; j < i; j++) kfree(ippp_table[j]); return -1; } - memset((char *) ippp_table[i], 0, sizeof(struct ippp_struct)); spin_lock_init(&ippp_table[i]->buflock); ippp_table[i]->state = 0; ippp_table[i]->first = ippp_table[i]->rq + NUM_RCV_BUFFS - 1; @@ -1529,10 +1527,8 @@ static int isdn_ppp_mp_bundle_array_init(void) { int i; int sz = ISDN_MAX_CHANNELS*sizeof(ippp_bundle); - if( (isdn_ppp_bundle_arr = (ippp_bundle*)kmalloc(sz, - GFP_KERNEL)) == NULL ) + if( (isdn_ppp_bundle_arr = kzalloc(sz, GFP_KERNEL)) == NULL ) return -ENOMEM; - memset(isdn_ppp_bundle_arr, 0, sz); for( i = 0; i < ISDN_MAX_CHANNELS; i++ ) spin_lock_init(&isdn_ppp_bundle_arr[i].lock); return 0; @@ -2246,13 +2242,12 @@ static void isdn_ppp_ccp_xmit_reset(struct ippp_struct *is, int proto, static struct ippp_ccp_reset *isdn_ppp_ccp_reset_alloc(struct ippp_struct *is) { struct ippp_ccp_reset *r; - r = kmalloc(sizeof(struct ippp_ccp_reset), GFP_KERNEL); + r = kzalloc(sizeof(struct ippp_ccp_reset), GFP_KERNEL); if(!r) { printk(KERN_ERR "ippp_ccp: failed to allocate reset data" " structure - no mem\n"); return NULL; } - memset(r, 0, sizeof(struct ippp_ccp_reset)); printk(KERN_DEBUG "ippp_ccp: allocated reset data structure %p\n", r); is->reset = r; return r; @@ -2338,10 +2333,9 @@ static struct ippp_ccp_reset_state *isdn_ppp_ccp_reset_alloc_state(struct ippp_s id); return NULL; } else { - rs = kmalloc(sizeof(struct ippp_ccp_reset_state), GFP_KERNEL); + rs = kzalloc(sizeof(struct ippp_ccp_reset_state), GFP_KERNEL); if(!rs) return NULL; - memset(rs, 0, sizeof(struct ippp_ccp_reset_state)); rs->state = CCPResetIdle; rs->is = is; rs->id = id; @@ -2536,6 +2530,11 @@ static struct sk_buff *isdn_ppp_decompress(struct sk_buff *skb,struct ippp_struc rsparm.maxdlen = IPPP_RESET_MAXDATABYTES; skb_out = dev_alloc_skb(is->mru + PPP_HDRLEN); + if (!skb_out) { + kfree_skb(skb); + printk(KERN_ERR "ippp: decomp memory allocation failure\n"); + return NULL; + } len = ipc->decompress(stat, skb, skb_out, &rsparm); kfree_skb(skb); if (len <= 0) { diff --git a/trunk/drivers/isdn/i4l/isdn_tty.c b/trunk/drivers/isdn/i4l/isdn_tty.c index 2b91bb07fc7f..fc80afe555b9 100644 --- a/trunk/drivers/isdn/i4l/isdn_tty.c +++ b/trunk/drivers/isdn/i4l/isdn_tty.c @@ -1464,7 +1464,7 @@ isdn_tty_ioctl(struct tty_struct *tty, struct file *file, } static void -isdn_tty_set_termios(struct tty_struct *tty, struct termios *old_termios) +isdn_tty_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { modem_info *info = (modem_info *) tty->driver_data; diff --git a/trunk/drivers/isdn/i4l/isdn_v110.c b/trunk/drivers/isdn/i4l/isdn_v110.c index 38619e8cd823..5484d3c38a57 100644 --- a/trunk/drivers/isdn/i4l/isdn_v110.c +++ b/trunk/drivers/isdn/i4l/isdn_v110.c @@ -92,9 +92,8 @@ isdn_v110_open(unsigned char key, int hdrlen, int maxsize) int i; isdn_v110_stream *v; - if ((v = kmalloc(sizeof(isdn_v110_stream), GFP_ATOMIC)) == NULL) + if ((v = kzalloc(sizeof(isdn_v110_stream), GFP_ATOMIC)) == NULL) return NULL; - memset(v, 0, sizeof(isdn_v110_stream)); v->key = key; v->nbits = 0; for (i = 0; key & (1 << i); i++) diff --git a/trunk/drivers/isdn/icn/icn.c b/trunk/drivers/isdn/icn/icn.c index 730bbd07ebc7..1e699bcaba0f 100644 --- a/trunk/drivers/isdn/icn/icn.c +++ b/trunk/drivers/isdn/icn/icn.c @@ -1519,12 +1519,11 @@ icn_initcard(int port, char *id) icn_card *card; int i; - if (!(card = (icn_card *) kmalloc(sizeof(icn_card), GFP_KERNEL))) { + if (!(card = kzalloc(sizeof(icn_card), GFP_KERNEL))) { printk(KERN_WARNING "icn: (%s) Could not allocate card-struct.\n", id); return (icn_card *) 0; } - memset((char *) card, 0, sizeof(icn_card)); spin_lock_init(&card->lock); card->port = port; card->interface.owner = THIS_MODULE; diff --git a/trunk/drivers/isdn/isdnloop/isdnloop.c b/trunk/drivers/isdn/isdnloop/isdnloop.c index c3ae2edaf6fa..e3add27dd0e1 100644 --- a/trunk/drivers/isdn/isdnloop/isdnloop.c +++ b/trunk/drivers/isdn/isdnloop/isdnloop.c @@ -1430,12 +1430,11 @@ isdnloop_initcard(char *id) isdnloop_card *card; int i; - if (!(card = (isdnloop_card *) kmalloc(sizeof(isdnloop_card), GFP_KERNEL))) { + if (!(card = kzalloc(sizeof(isdnloop_card), GFP_KERNEL))) { printk(KERN_WARNING "isdnloop: (%s) Could not allocate card-struct.\n", id); return (isdnloop_card *) 0; } - memset((char *) card, 0, sizeof(isdnloop_card)); card->interface.owner = THIS_MODULE; card->interface.channels = ISDNLOOP_BCH; card->interface.hl_hdrlen = 1; /* scratch area for storing ack flag*/ diff --git a/trunk/drivers/isdn/pcbit/drv.c b/trunk/drivers/isdn/pcbit/drv.c index 6ead5e1508b7..11c1b0b6e390 100644 --- a/trunk/drivers/isdn/pcbit/drv.c +++ b/trunk/drivers/isdn/pcbit/drv.c @@ -68,21 +68,18 @@ static void pcbit_set_msn(struct pcbit_dev *dev, char *list); static int pcbit_check_msn(struct pcbit_dev *dev, char *msn); -extern void pcbit_deliver(void * data); - int pcbit_init_dev(int board, int mem_base, int irq) { struct pcbit_dev *dev; isdn_if *dev_if; - if ((dev=kmalloc(sizeof(struct pcbit_dev), GFP_KERNEL)) == NULL) + if ((dev=kzalloc(sizeof(struct pcbit_dev), GFP_KERNEL)) == NULL) { printk("pcbit_init: couldn't malloc pcbit_dev struct\n"); return -ENOMEM; } dev_pcbit[board] = dev; - memset(dev, 0, sizeof(struct pcbit_dev)); init_waitqueue_head(&dev->set_running_wq); spin_lock_init(&dev->lock); @@ -106,7 +103,7 @@ int pcbit_init_dev(int board, int mem_base, int irq) return -EACCES; } - dev->b1 = kmalloc(sizeof(struct pcbit_chan), GFP_KERNEL); + dev->b1 = kzalloc(sizeof(struct pcbit_chan), GFP_KERNEL); if (!dev->b1) { printk("pcbit_init: couldn't malloc pcbit_chan struct\n"); iounmap(dev->sh_mem); @@ -115,7 +112,7 @@ int pcbit_init_dev(int board, int mem_base, int irq) return -ENOMEM; } - dev->b2 = kmalloc(sizeof(struct pcbit_chan), GFP_KERNEL); + dev->b2 = kzalloc(sizeof(struct pcbit_chan), GFP_KERNEL); if (!dev->b2) { printk("pcbit_init: couldn't malloc pcbit_chan struct\n"); kfree(dev->b1); @@ -125,11 +122,9 @@ int pcbit_init_dev(int board, int mem_base, int irq) return -ENOMEM; } - memset(dev->b1, 0, sizeof(struct pcbit_chan)); - memset(dev->b2, 0, sizeof(struct pcbit_chan)); dev->b2->id = 1; - INIT_WORK(&dev->qdelivery, pcbit_deliver, dev); + INIT_WORK(&dev->qdelivery, pcbit_deliver); /* * interrupts diff --git a/trunk/drivers/isdn/pcbit/layer2.c b/trunk/drivers/isdn/pcbit/layer2.c index 937fd2120381..6ff85574e941 100644 --- a/trunk/drivers/isdn/pcbit/layer2.c +++ b/trunk/drivers/isdn/pcbit/layer2.c @@ -67,7 +67,6 @@ extern void pcbit_l3_receive(struct pcbit_dev *dev, ulong msg, * Prototypes */ -void pcbit_deliver(void *data); static void pcbit_transmit(struct pcbit_dev *dev); static void pcbit_recv_ack(struct pcbit_dev *dev, unsigned char ack); @@ -299,11 +298,12 @@ pcbit_transmit(struct pcbit_dev *dev) */ void -pcbit_deliver(void *data) +pcbit_deliver(struct work_struct *work) { struct frame_buf *frame; unsigned long flags, msg; - struct pcbit_dev *dev = (struct pcbit_dev *) data; + struct pcbit_dev *dev = + container_of(work, struct pcbit_dev, qdelivery); spin_lock_irqsave(&dev->lock, flags); @@ -369,13 +369,12 @@ pcbit_receive(struct pcbit_dev *dev) kfree(dev->read_frame); dev->read_frame = NULL; } - frame = kmalloc(sizeof(struct frame_buf), GFP_ATOMIC); + frame = kzalloc(sizeof(struct frame_buf), GFP_ATOMIC); if (frame == NULL) { printk(KERN_WARNING "kmalloc failed\n"); return; } - memset(frame, 0, sizeof(struct frame_buf)); cpu = pcbit_readb(dev); proc = pcbit_readb(dev); diff --git a/trunk/drivers/isdn/pcbit/pcbit.h b/trunk/drivers/isdn/pcbit/pcbit.h index 388bacefd23a..19c18e88ff16 100644 --- a/trunk/drivers/isdn/pcbit/pcbit.h +++ b/trunk/drivers/isdn/pcbit/pcbit.h @@ -166,4 +166,6 @@ struct pcbit_ioctl { #define L2_RUNNING 5 #define L2_ERROR 6 +extern void pcbit_deliver(struct work_struct *work); + #endif diff --git a/trunk/drivers/isdn/sc/init.c b/trunk/drivers/isdn/sc/init.c index 06c9872e8c6a..150759a5cddf 100644 --- a/trunk/drivers/isdn/sc/init.c +++ b/trunk/drivers/isdn/sc/init.c @@ -271,14 +271,13 @@ static int __init sc_init(void) * Horray! We found a board, Make sure we can register * it with ISDN4Linux */ - interface = kmalloc(sizeof(isdn_if), GFP_KERNEL); + interface = kzalloc(sizeof(isdn_if), GFP_KERNEL); if (interface == NULL) { /* * Oops, can't malloc isdn_if */ continue; } - memset(interface, 0, sizeof(isdn_if)); interface->owner = THIS_MODULE; interface->hl_hdrlen = 0; @@ -294,7 +293,7 @@ static int __init sc_init(void) /* * Allocate the board structure */ - sc_adapter[cinst] = kmalloc(sizeof(board), GFP_KERNEL); + sc_adapter[cinst] = kzalloc(sizeof(board), GFP_KERNEL); if (sc_adapter[cinst] == NULL) { /* * Oops, can't alloc memory for the board @@ -302,7 +301,6 @@ static int __init sc_init(void) kfree(interface); continue; } - memset(sc_adapter[cinst], 0, sizeof(board)); spin_lock_init(&sc_adapter[cinst]->lock); if(!register_isdn(interface)) { @@ -326,7 +324,7 @@ static int __init sc_init(void) /* * Allocate channels status structures */ - sc_adapter[cinst]->channel = kmalloc(sizeof(bchan) * channels, GFP_KERNEL); + sc_adapter[cinst]->channel = kzalloc(sizeof(bchan) * channels, GFP_KERNEL); if (sc_adapter[cinst]->channel == NULL) { /* * Oops, can't alloc memory for the channels @@ -336,7 +334,6 @@ static int __init sc_init(void) kfree(sc_adapter[cinst]); continue; } - memset(sc_adapter[cinst]->channel, 0, sizeof(bchan) * channels); /* * Lock down the hardware resources diff --git a/trunk/drivers/leds/Kconfig b/trunk/drivers/leds/Kconfig index 9c39b98d5a5b..176142c61492 100644 --- a/trunk/drivers/leds/Kconfig +++ b/trunk/drivers/leds/Kconfig @@ -76,6 +76,12 @@ config LEDS_NET48XX This option enables support for the Soekris net4801 and net4826 error LED. +config LEDS_WRAP + tristate "LED Support for the WRAP series LEDs" + depends on LEDS_CLASS && SCx200_GPIO + help + This option enables support for the PCEngines WRAP programmable LEDs. + comment "LED Triggers" config LEDS_TRIGGERS diff --git a/trunk/drivers/leds/Makefile b/trunk/drivers/leds/Makefile index 6aa2aed7539d..500de3dc962a 100644 --- a/trunk/drivers/leds/Makefile +++ b/trunk/drivers/leds/Makefile @@ -13,6 +13,7 @@ obj-$(CONFIG_LEDS_TOSA) += leds-tosa.o obj-$(CONFIG_LEDS_S3C24XX) += leds-s3c24xx.o obj-$(CONFIG_LEDS_AMS_DELTA) += leds-ams-delta.o obj-$(CONFIG_LEDS_NET48XX) += leds-net48xx.o +obj-$(CONFIG_LEDS_WRAP) += leds-wrap.o # LED Triggers obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o diff --git a/trunk/drivers/leds/leds-wrap.c b/trunk/drivers/leds/leds-wrap.c new file mode 100644 index 000000000000..27fb2d8e991f --- /dev/null +++ b/trunk/drivers/leds/leds-wrap.c @@ -0,0 +1,142 @@ +/* + * LEDs driver for PCEngines WRAP + * + * Copyright (C) 2006 Kristian Kielhofner + * + * Based on leds-net48xx.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define DRVNAME "wrap-led" +#define WRAP_ERROR_LED_GPIO 3 +#define WRAP_EXTRA_LED_GPIO 18 + +static struct platform_device *pdev; + +static void wrap_error_led_set(struct led_classdev *led_cdev, + enum led_brightness value) +{ + if (value) + scx200_gpio_set_low(WRAP_ERROR_LED_GPIO); + else + scx200_gpio_set_high(WRAP_ERROR_LED_GPIO); +} + +static void wrap_extra_led_set(struct led_classdev *led_cdev, + enum led_brightness value) +{ + if (value) + scx200_gpio_set_low(WRAP_EXTRA_LED_GPIO); + else + scx200_gpio_set_high(WRAP_EXTRA_LED_GPIO); +} + +static struct led_classdev wrap_error_led = { + .name = "wrap:error", + .brightness_set = wrap_error_led_set, +}; + +static struct led_classdev wrap_extra_led = { + .name = "wrap:extra", + .brightness_set = wrap_extra_led_set, +}; + +#ifdef CONFIG_PM +static int wrap_led_suspend(struct platform_device *dev, + pm_message_t state) +{ + led_classdev_suspend(&wrap_error_led); + led_classdev_suspend(&wrap_extra_led); + return 0; +} + +static int wrap_led_resume(struct platform_device *dev) +{ + led_classdev_resume(&wrap_error_led); + led_classdev_resume(&wrap_extra_led); + return 0; +} +#else +#define wrap_led_suspend NULL +#define wrap_led_resume NULL +#endif + +static int wrap_led_probe(struct platform_device *pdev) +{ + int ret; + + ret = led_classdev_register(&pdev->dev, &wrap_error_led); + if (ret == 0) { + ret = led_classdev_register(&pdev->dev, &wrap_extra_led); + if (ret < 0) + led_classdev_unregister(&wrap_error_led); + } + return ret; +} + +static int wrap_led_remove(struct platform_device *pdev) +{ + led_classdev_unregister(&wrap_error_led); + led_classdev_unregister(&wrap_extra_led); + return 0; +} + +static struct platform_driver wrap_led_driver = { + .probe = wrap_led_probe, + .remove = wrap_led_remove, + .suspend = wrap_led_suspend, + .resume = wrap_led_resume, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +static int __init wrap_led_init(void) +{ + int ret; + + if (!scx200_gpio_present()) { + ret = -ENODEV; + goto out; + } + + ret = platform_driver_register(&wrap_led_driver); + if (ret < 0) + goto out; + + pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(pdev)) { + ret = PTR_ERR(pdev); + platform_driver_unregister(&wrap_led_driver); + goto out; + } + +out: + return ret; +} + +static void __exit wrap_led_exit(void) +{ + platform_device_unregister(pdev); + platform_driver_unregister(&wrap_led_driver); +} + +module_init(wrap_led_init); +module_exit(wrap_led_exit); + +MODULE_AUTHOR("Kristian Kielhofner "); +MODULE_DESCRIPTION("PCEngines WRAP LED driver"); +MODULE_LICENSE("GPL"); + diff --git a/trunk/drivers/macintosh/Kconfig b/trunk/drivers/macintosh/Kconfig index 92ccee85e2a2..a9e747c39791 100644 --- a/trunk/drivers/macintosh/Kconfig +++ b/trunk/drivers/macintosh/Kconfig @@ -162,7 +162,6 @@ config INPUT_ADBHID config MAC_EMUMOUSEBTN bool "Support for mouse button 2+3 emulation" - depends on INPUT_ADBHID help This provides generic support for emulating the 2nd and 3rd mouse button with keypresses. If you say Y here, the emulation is still diff --git a/trunk/drivers/macintosh/adb.c b/trunk/drivers/macintosh/adb.c index be0bd34ff6f9..d43ea81d6df9 100644 --- a/trunk/drivers/macintosh/adb.c +++ b/trunk/drivers/macintosh/adb.c @@ -267,12 +267,12 @@ adb_probe_task(void *x) } static void -__adb_probe_task(void *data) +__adb_probe_task(struct work_struct *bullshit) { adb_probe_task_pid = kernel_thread(adb_probe_task, NULL, SIGCHLD | CLONE_KERNEL); } -static DECLARE_WORK(adb_reset_work, __adb_probe_task, NULL); +static DECLARE_WORK(adb_reset_work, __adb_probe_task); int adb_reset_bus(void) diff --git a/trunk/drivers/macintosh/adbhid.c b/trunk/drivers/macintosh/adbhid.c index 5066e7a8ea9c..1c7d6f221b55 100644 --- a/trunk/drivers/macintosh/adbhid.c +++ b/trunk/drivers/macintosh/adbhid.c @@ -689,7 +689,6 @@ adbhid_input_register(int id, int default_id, int original_handler_id, if (!hid || !input_dev) { err = -ENOMEM; goto fail; - } sprintf(hid->phys, "adb%d:%d.%02x/input", id, default_id, original_handler_id); @@ -807,7 +806,9 @@ adbhid_input_register(int id, int default_id, int original_handler_id, input_dev->keycode = hid->keycode; - input_register_device(input_dev); + err = input_register_device(input_dev); + if (err) + goto fail; if (default_id == ADB_KEYBOARD) { /* HACK WARNING!! This should go away as soon there is an utility @@ -820,7 +821,10 @@ adbhid_input_register(int id, int default_id, int original_handler_id, return 0; fail: input_free_device(input_dev); - kfree(hid); + if (hid) { + kfree(hid->keycode); + kfree(hid); + } adbhid[id] = NULL; return err; } diff --git a/trunk/drivers/macintosh/apm_emu.c b/trunk/drivers/macintosh/apm_emu.c index 1293876a2ebd..8862a83b8d84 100644 --- a/trunk/drivers/macintosh/apm_emu.c +++ b/trunk/drivers/macintosh/apm_emu.c @@ -529,7 +529,8 @@ static int __init apm_emu_init(void) if (apm_proc) apm_proc->owner = THIS_MODULE; - misc_register(&apm_device); + if (misc_register(&apm_device) != 0) + printk(KERN_INFO "Could not create misc. device for apm\n"); pmu_register_sleep_notifier(&apm_sleep_notifier); diff --git a/trunk/drivers/macintosh/mac_hid.c b/trunk/drivers/macintosh/mac_hid.c index 6b129eef7987..ee6b4ca69130 100644 --- a/trunk/drivers/macintosh/mac_hid.c +++ b/trunk/drivers/macintosh/mac_hid.c @@ -106,6 +106,8 @@ EXPORT_SYMBOL(mac_hid_mouse_emulate_buttons); static int emumousebtn_input_register(void) { + int ret; + emumousebtn = input_allocate_device(); if (!emumousebtn) return -ENOMEM; @@ -120,9 +122,11 @@ static int emumousebtn_input_register(void) emumousebtn->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT); emumousebtn->relbit[0] = BIT(REL_X) | BIT(REL_Y); - input_register_device(emumousebtn); + ret = input_register_device(emumousebtn); + if (ret) + input_free_device(emumousebtn); - return 0; + return ret; } int __init mac_hid_init(void) diff --git a/trunk/drivers/macintosh/rack-meter.c b/trunk/drivers/macintosh/rack-meter.c index f1b6f563673a..5ed41fe84e57 100644 --- a/trunk/drivers/macintosh/rack-meter.c +++ b/trunk/drivers/macintosh/rack-meter.c @@ -48,7 +48,8 @@ struct rackmeter_dma { } ____cacheline_aligned; struct rackmeter_cpu { - struct work_struct sniffer; + struct delayed_work sniffer; + struct rackmeter *rm; cputime64_t prev_wall; cputime64_t prev_idle; int zero; @@ -208,11 +209,12 @@ static void rackmeter_setup_dbdma(struct rackmeter *rm) rackmeter_do_pause(rm, 0); } -static void rackmeter_do_timer(void *data) +static void rackmeter_do_timer(struct work_struct *work) { - struct rackmeter *rm = data; + struct rackmeter_cpu *rcpu = + container_of(work, struct rackmeter_cpu, sniffer.work); + struct rackmeter *rm = rcpu->rm; unsigned int cpu = smp_processor_id(); - struct rackmeter_cpu *rcpu = &rm->cpu[cpu]; cputime64_t cur_jiffies, total_idle_ticks; unsigned int total_ticks, idle_ticks; int i, offset, load, cumm, pause; @@ -263,8 +265,10 @@ static void __devinit rackmeter_init_cpu_sniffer(struct rackmeter *rm) * on those machines yet */ - INIT_WORK(&rm->cpu[0].sniffer, rackmeter_do_timer, rm); - INIT_WORK(&rm->cpu[1].sniffer, rackmeter_do_timer, rm); + rm->cpu[0].rm = rm; + INIT_DELAYED_WORK(&rm->cpu[0].sniffer, rackmeter_do_timer); + rm->cpu[1].rm = rm; + INIT_DELAYED_WORK(&rm->cpu[1].sniffer, rackmeter_do_timer); for_each_online_cpu(cpu) { struct rackmeter_cpu *rcpu; diff --git a/trunk/drivers/macintosh/smu.c b/trunk/drivers/macintosh/smu.c index 4f724cdd2efa..6dde27ab79a8 100644 --- a/trunk/drivers/macintosh/smu.c +++ b/trunk/drivers/macintosh/smu.c @@ -601,7 +601,7 @@ core_initcall(smu_late_init); * sysfs visibility */ -static void smu_expose_childs(void *unused) +static void smu_expose_childs(struct work_struct *unused) { struct device_node *np; @@ -611,7 +611,7 @@ static void smu_expose_childs(void *unused) &smu->of_dev->dev); } -static DECLARE_WORK(smu_expose_childs_work, smu_expose_childs, NULL); +static DECLARE_WORK(smu_expose_childs_work, smu_expose_childs); static int smu_platform_probe(struct of_device* dev, const struct of_device_id *match) diff --git a/trunk/drivers/macintosh/therm_adt746x.c b/trunk/drivers/macintosh/therm_adt746x.c index 13b953ae8ebc..3d3bf1643e73 100644 --- a/trunk/drivers/macintosh/therm_adt746x.c +++ b/trunk/drivers/macintosh/therm_adt746x.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include diff --git a/trunk/drivers/macintosh/via-pmu.c b/trunk/drivers/macintosh/via-pmu.c index e63ea1c1f3c1..c8558d4ed506 100644 --- a/trunk/drivers/macintosh/via-pmu.c +++ b/trunk/drivers/macintosh/via-pmu.c @@ -42,7 +42,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/trunk/drivers/macintosh/windfarm_core.c b/trunk/drivers/macintosh/windfarm_core.c index ab3faa702d58..e947af982f93 100644 --- a/trunk/drivers/macintosh/windfarm_core.c +++ b/trunk/drivers/macintosh/windfarm_core.c @@ -34,6 +34,7 @@ #include #include #include +#include #include diff --git a/trunk/drivers/md/bitmap.c b/trunk/drivers/md/bitmap.c index d6f614738bbd..5432d07c074d 100644 --- a/trunk/drivers/md/bitmap.c +++ b/trunk/drivers/md/bitmap.c @@ -212,8 +212,8 @@ char *file_path(struct file *file, char *buf, int count) if (!buf) return NULL; - d = file->f_dentry; - v = file->f_vfsmnt; + d = file->f_path.dentry; + v = file->f_path.mnt; buf = d_path(d, v, buf, count); @@ -349,7 +349,7 @@ static struct page *read_page(struct file *file, unsigned long index, unsigned long count) { struct page *page = NULL; - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; struct buffer_head *bh; sector_t block; @@ -662,7 +662,7 @@ static void bitmap_file_put(struct bitmap *bitmap) bitmap_file_unmap(bitmap); if (file) { - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; invalidate_inode_pages(inode->i_mapping); fput(file); } diff --git a/trunk/drivers/md/dm-bio-list.h b/trunk/drivers/md/dm-bio-list.h index bbf4615f0e30..da4349649f7f 100644 --- a/trunk/drivers/md/dm-bio-list.h +++ b/trunk/drivers/md/dm-bio-list.h @@ -44,6 +44,20 @@ static inline void bio_list_merge(struct bio_list *bl, struct bio_list *bl2) bl->tail = bl2->tail; } +static inline void bio_list_merge_head(struct bio_list *bl, + struct bio_list *bl2) +{ + if (!bl2->head) + return; + + if (bl->head) + bl2->tail->bi_next = bl->head; + else + bl->tail = bl2->tail; + + bl->head = bl2->head; +} + static inline struct bio *bio_list_pop(struct bio_list *bl) { struct bio *bio = bl->head; diff --git a/trunk/drivers/md/dm-crypt.c b/trunk/drivers/md/dm-crypt.c index 08a40f4e4f60..4c2471ee054a 100644 --- a/trunk/drivers/md/dm-crypt.c +++ b/trunk/drivers/md/dm-crypt.c @@ -20,6 +20,7 @@ #include #include #include +#include #include "dm.h" @@ -85,7 +86,10 @@ struct crypt_config { */ struct crypt_iv_operations *iv_gen_ops; char *iv_mode; - struct crypto_cipher *iv_gen_private; + union { + struct crypto_cipher *essiv_tfm; + int benbi_shift; + } iv_gen_private; sector_t iv_offset; unsigned int iv_size; @@ -101,7 +105,7 @@ struct crypt_config { #define MIN_POOL_PAGES 32 #define MIN_BIO_PAGES 8 -static kmem_cache_t *_crypt_io_pool; +static struct kmem_cache *_crypt_io_pool; /* * Different IV generation algorithms: @@ -113,6 +117,9 @@ static kmem_cache_t *_crypt_io_pool; * encrypted with the bulk cipher using a salt as key. The salt * should be derived from the bulk cipher's key via hashing. * + * benbi: the 64-bit "big-endian 'narrow block'-count", starting at 1 + * (needed for LRW-32-AES and possible other narrow block modes) + * * plumb: unimplemented, see: * http://article.gmane.org/gmane.linux.kernel.device-mapper.dm-crypt/454 */ @@ -191,21 +198,61 @@ static int crypt_iv_essiv_ctr(struct crypt_config *cc, struct dm_target *ti, } kfree(salt); - cc->iv_gen_private = essiv_tfm; + cc->iv_gen_private.essiv_tfm = essiv_tfm; return 0; } static void crypt_iv_essiv_dtr(struct crypt_config *cc) { - crypto_free_cipher(cc->iv_gen_private); - cc->iv_gen_private = NULL; + crypto_free_cipher(cc->iv_gen_private.essiv_tfm); + cc->iv_gen_private.essiv_tfm = NULL; } static int crypt_iv_essiv_gen(struct crypt_config *cc, u8 *iv, sector_t sector) { memset(iv, 0, cc->iv_size); *(u64 *)iv = cpu_to_le64(sector); - crypto_cipher_encrypt_one(cc->iv_gen_private, iv, iv); + crypto_cipher_encrypt_one(cc->iv_gen_private.essiv_tfm, iv, iv); + return 0; +} + +static int crypt_iv_benbi_ctr(struct crypt_config *cc, struct dm_target *ti, + const char *opts) +{ + unsigned int bs = crypto_blkcipher_blocksize(cc->tfm); + int log = ilog2(bs); + + /* we need to calculate how far we must shift the sector count + * to get the cipher block count, we use this shift in _gen */ + + if (1 << log != bs) { + ti->error = "cypher blocksize is not a power of 2"; + return -EINVAL; + } + + if (log > 9) { + ti->error = "cypher blocksize is > 512"; + return -EINVAL; + } + + cc->iv_gen_private.benbi_shift = 9 - log; + + return 0; +} + +static void crypt_iv_benbi_dtr(struct crypt_config *cc) +{ +} + +static int crypt_iv_benbi_gen(struct crypt_config *cc, u8 *iv, sector_t sector) +{ + __be64 val; + + memset(iv, 0, cc->iv_size - sizeof(u64)); /* rest is cleared below */ + + val = cpu_to_be64(((u64)sector << cc->iv_gen_private.benbi_shift) + 1); + put_unaligned(val, (__be64 *)(iv + cc->iv_size - sizeof(u64))); + return 0; } @@ -219,13 +266,18 @@ static struct crypt_iv_operations crypt_iv_essiv_ops = { .generator = crypt_iv_essiv_gen }; +static struct crypt_iv_operations crypt_iv_benbi_ops = { + .ctr = crypt_iv_benbi_ctr, + .dtr = crypt_iv_benbi_dtr, + .generator = crypt_iv_benbi_gen +}; static int crypt_convert_scatterlist(struct crypt_config *cc, struct scatterlist *out, struct scatterlist *in, unsigned int length, int write, sector_t sector) { - u8 iv[cc->iv_size]; + u8 iv[cc->iv_size] __attribute__ ((aligned(__alignof__(u64)))); struct blkcipher_desc desc = { .tfm = cc->tfm, .info = iv, @@ -458,11 +510,11 @@ static void dec_pending(struct crypt_io *io, int error) * interrupt context. */ static struct workqueue_struct *_kcryptd_workqueue; -static void kcryptd_do_work(void *data); +static void kcryptd_do_work(struct work_struct *work); static void kcryptd_queue_io(struct crypt_io *io) { - INIT_WORK(&io->work, kcryptd_do_work, io); + INIT_WORK(&io->work, kcryptd_do_work); queue_work(_kcryptd_workqueue, &io->work); } @@ -618,9 +670,9 @@ static void process_read_endio(struct crypt_io *io) dec_pending(io, crypt_convert(cc, &ctx)); } -static void kcryptd_do_work(void *data) +static void kcryptd_do_work(struct work_struct *work) { - struct crypt_io *io = data; + struct crypt_io *io = container_of(work, struct crypt_io, work); if (io->post_process) process_read_endio(io); @@ -768,7 +820,7 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) cc->tfm = tfm; /* - * Choose ivmode. Valid modes: "plain", "essiv:". + * Choose ivmode. Valid modes: "plain", "essiv:", "benbi". * See comments at iv code */ @@ -778,6 +830,8 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) cc->iv_gen_ops = &crypt_iv_plain_ops; else if (strcmp(ivmode, "essiv") == 0) cc->iv_gen_ops = &crypt_iv_essiv_ops; + else if (strcmp(ivmode, "benbi") == 0) + cc->iv_gen_ops = &crypt_iv_benbi_ops; else { ti->error = "Invalid IV mode"; goto bad2; @@ -908,7 +962,7 @@ static int crypt_map(struct dm_target *ti, struct bio *bio, atomic_set(&io->pending, 0); kcryptd_queue_io(io); - return 0; + return DM_MAPIO_SUBMITTED; } static int crypt_status(struct dm_target *ti, status_type_t type, diff --git a/trunk/drivers/md/dm-emc.c b/trunk/drivers/md/dm-emc.c index 2b2d45d7baaa..265c467854da 100644 --- a/trunk/drivers/md/dm-emc.c +++ b/trunk/drivers/md/dm-emc.c @@ -40,7 +40,7 @@ static inline void free_bio(struct bio *bio) static int emc_endio(struct bio *bio, unsigned int bytes_done, int error) { - struct path *path = bio->bi_private; + struct dm_path *path = bio->bi_private; if (bio->bi_size) return 1; @@ -61,7 +61,7 @@ static int emc_endio(struct bio *bio, unsigned int bytes_done, int error) return 0; } -static struct bio *get_failover_bio(struct path *path, unsigned data_size) +static struct bio *get_failover_bio(struct dm_path *path, unsigned data_size) { struct bio *bio; struct page *page; @@ -96,7 +96,7 @@ static struct bio *get_failover_bio(struct path *path, unsigned data_size) } static struct request *get_failover_req(struct emc_handler *h, - struct bio *bio, struct path *path) + struct bio *bio, struct dm_path *path) { struct request *rq; struct block_device *bdev = bio->bi_bdev; @@ -133,7 +133,7 @@ static struct request *get_failover_req(struct emc_handler *h, } static struct request *emc_trespass_get(struct emc_handler *h, - struct path *path) + struct dm_path *path) { struct bio *bio; struct request *rq; @@ -191,7 +191,7 @@ static struct request *emc_trespass_get(struct emc_handler *h, } static void emc_pg_init(struct hw_handler *hwh, unsigned bypassed, - struct path *path) + struct dm_path *path) { struct request *rq; struct request_queue *q = bdev_get_queue(path->dev->bdev); diff --git a/trunk/drivers/md/dm-hw-handler.h b/trunk/drivers/md/dm-hw-handler.h index 15f5629e231a..32eff28e4adc 100644 --- a/trunk/drivers/md/dm-hw-handler.h +++ b/trunk/drivers/md/dm-hw-handler.h @@ -32,7 +32,7 @@ struct hw_handler_type { void (*destroy) (struct hw_handler *hwh); void (*pg_init) (struct hw_handler *hwh, unsigned bypassed, - struct path *path); + struct dm_path *path); unsigned (*error) (struct hw_handler *hwh, struct bio *bio); int (*status) (struct hw_handler *hwh, status_type_t type, char *result, unsigned int maxlen); diff --git a/trunk/drivers/md/dm-io.c b/trunk/drivers/md/dm-io.c index da663d2ff552..4eb73d395213 100644 --- a/trunk/drivers/md/dm-io.c +++ b/trunk/drivers/md/dm-io.c @@ -92,12 +92,12 @@ void dm_io_put(unsigned int num_pages) *---------------------------------------------------------------*/ static inline void bio_set_region(struct bio *bio, unsigned region) { - bio->bi_io_vec[bio->bi_max_vecs - 1].bv_len = region; + bio->bi_io_vec[bio->bi_max_vecs].bv_len = region; } static inline unsigned bio_get_region(struct bio *bio) { - return bio->bi_io_vec[bio->bi_max_vecs - 1].bv_len; + return bio->bi_io_vec[bio->bi_max_vecs].bv_len; } /*----------------------------------------------------------------- @@ -136,6 +136,7 @@ static int endio(struct bio *bio, unsigned int done, int error) zero_fill_bio(bio); dec_count(io, bio_get_region(bio), error); + bio->bi_max_vecs++; bio_put(bio); return 0; @@ -250,16 +251,18 @@ static void do_region(int rw, unsigned int region, struct io_region *where, while (remaining) { /* - * Allocate a suitably sized bio, we add an extra - * bvec for bio_get/set_region(). + * Allocate a suitably sized-bio: we add an extra + * bvec for bio_get/set_region() and decrement bi_max_vecs + * to hide it from bio_add_page(). */ - num_bvecs = (remaining / (PAGE_SIZE >> 9)) + 2; + num_bvecs = (remaining / (PAGE_SIZE >> SECTOR_SHIFT)) + 2; bio = bio_alloc_bioset(GFP_NOIO, num_bvecs, _bios); bio->bi_sector = where->sector + (where->count - remaining); bio->bi_bdev = where->bdev; bio->bi_end_io = endio; bio->bi_private = io; bio->bi_destructor = dm_bio_destructor; + bio->bi_max_vecs--; bio_set_region(bio, region); /* @@ -302,7 +305,7 @@ static void dispatch_io(int rw, unsigned int num_regions, } /* - * Drop the extra refence that we were holding to avoid + * Drop the extra reference that we were holding to avoid * the io being completed too early. */ dec_count(io, 0, 0); diff --git a/trunk/drivers/md/dm-ioctl.c b/trunk/drivers/md/dm-ioctl.c index 4510ad8f971c..cd6a184536a1 100644 --- a/trunk/drivers/md/dm-ioctl.c +++ b/trunk/drivers/md/dm-ioctl.c @@ -765,7 +765,7 @@ static int dev_set_geometry(struct dm_ioctl *param, size_t param_size) static int do_suspend(struct dm_ioctl *param) { int r = 0; - int do_lockfs = 1; + unsigned suspend_flags = DM_SUSPEND_LOCKFS_FLAG; struct mapped_device *md; md = find_device(param); @@ -773,10 +773,12 @@ static int do_suspend(struct dm_ioctl *param) return -ENXIO; if (param->flags & DM_SKIP_LOCKFS_FLAG) - do_lockfs = 0; + suspend_flags &= ~DM_SUSPEND_LOCKFS_FLAG; + if (param->flags & DM_NOFLUSH_FLAG) + suspend_flags |= DM_SUSPEND_NOFLUSH_FLAG; if (!dm_suspended(md)) - r = dm_suspend(md, do_lockfs); + r = dm_suspend(md, suspend_flags); if (!r) r = __dev_status(md, param); @@ -788,7 +790,7 @@ static int do_suspend(struct dm_ioctl *param) static int do_resume(struct dm_ioctl *param) { int r = 0; - int do_lockfs = 1; + unsigned suspend_flags = DM_SUSPEND_LOCKFS_FLAG; struct hash_cell *hc; struct mapped_device *md; struct dm_table *new_map; @@ -814,9 +816,11 @@ static int do_resume(struct dm_ioctl *param) if (new_map) { /* Suspend if it isn't already suspended */ if (param->flags & DM_SKIP_LOCKFS_FLAG) - do_lockfs = 0; + suspend_flags &= ~DM_SUSPEND_LOCKFS_FLAG; + if (param->flags & DM_NOFLUSH_FLAG) + suspend_flags |= DM_SUSPEND_NOFLUSH_FLAG; if (!dm_suspended(md)) - dm_suspend(md, do_lockfs); + dm_suspend(md, suspend_flags); r = dm_swap_table(md, new_map); if (r) { diff --git a/trunk/drivers/md/dm-linear.c b/trunk/drivers/md/dm-linear.c index 00234909b3db..17753d80ad22 100644 --- a/trunk/drivers/md/dm-linear.c +++ b/trunk/drivers/md/dm-linear.c @@ -77,7 +77,7 @@ static int linear_map(struct dm_target *ti, struct bio *bio, bio->bi_bdev = lc->dev->bdev; bio->bi_sector = lc->start + (bio->bi_sector - ti->begin); - return 1; + return DM_MAPIO_REMAPPED; } static int linear_status(struct dm_target *ti, status_type_t type, @@ -108,7 +108,7 @@ static int linear_ioctl(struct dm_target *ti, struct inode *inode, struct dentry fake_dentry = {}; fake_file.f_mode = lc->dev->mode; - fake_file.f_dentry = &fake_dentry; + fake_file.f_path.dentry = &fake_dentry; fake_dentry.d_inode = bdev->bd_inode; return blkdev_driver_ioctl(bdev->bd_inode, &fake_file, bdev->bd_disk, cmd, arg); diff --git a/trunk/drivers/md/dm-log.c b/trunk/drivers/md/dm-log.c index 64b764bd02cc..6a9261351848 100644 --- a/trunk/drivers/md/dm-log.c +++ b/trunk/drivers/md/dm-log.c @@ -466,6 +466,7 @@ static int disk_resume(struct dirty_log *log) /* copy clean across to sync */ memcpy(lc->sync_bits, lc->clean_bits, size); lc->sync_count = count_bits32(lc->clean_bits, lc->bitset_uint32_count); + lc->sync_search = 0; /* set the correct number of regions in the header */ lc->header.nr_regions = lc->region_count; @@ -480,6 +481,13 @@ static uint32_t core_get_region_size(struct dirty_log *log) return lc->region_size; } +static int core_resume(struct dirty_log *log) +{ + struct log_c *lc = (struct log_c *) log->context; + lc->sync_search = 0; + return 0; +} + static int core_is_clean(struct dirty_log *log, region_t region) { struct log_c *lc = (struct log_c *) log->context; @@ -549,16 +557,19 @@ static int core_get_resync_work(struct dirty_log *log, region_t *region) return 1; } -static void core_complete_resync_work(struct dirty_log *log, region_t region, - int success) +static void core_set_region_sync(struct dirty_log *log, region_t region, + int in_sync) { struct log_c *lc = (struct log_c *) log->context; log_clear_bit(lc, lc->recovering_bits, region); - if (success) { + if (in_sync) { log_set_bit(lc, lc->sync_bits, region); lc->sync_count++; - } + } else if (log_test_bit(lc->sync_bits, region)) { + lc->sync_count--; + log_clear_bit(lc, lc->sync_bits, region); + } } static region_t core_get_sync_count(struct dirty_log *log) @@ -618,6 +629,7 @@ static struct dirty_log_type _core_type = { .module = THIS_MODULE, .ctr = core_ctr, .dtr = core_dtr, + .resume = core_resume, .get_region_size = core_get_region_size, .is_clean = core_is_clean, .in_sync = core_in_sync, @@ -625,7 +637,7 @@ static struct dirty_log_type _core_type = { .mark_region = core_mark_region, .clear_region = core_clear_region, .get_resync_work = core_get_resync_work, - .complete_resync_work = core_complete_resync_work, + .set_region_sync = core_set_region_sync, .get_sync_count = core_get_sync_count, .status = core_status, }; @@ -644,7 +656,7 @@ static struct dirty_log_type _disk_type = { .mark_region = core_mark_region, .clear_region = core_clear_region, .get_resync_work = core_get_resync_work, - .complete_resync_work = core_complete_resync_work, + .set_region_sync = core_set_region_sync, .get_sync_count = core_get_sync_count, .status = disk_status, }; diff --git a/trunk/drivers/md/dm-log.h b/trunk/drivers/md/dm-log.h index 5ae5309ebf28..86a301c8daf1 100644 --- a/trunk/drivers/md/dm-log.h +++ b/trunk/drivers/md/dm-log.h @@ -90,12 +90,12 @@ struct dirty_log_type { int (*get_resync_work)(struct dirty_log *log, region_t *region); /* - * This notifies the log that the resync of an area has - * been completed. The log should then mark this region - * as CLEAN. + * This notifies the log that the resync status of a region + * has changed. It also clears the region from the recovering + * list (if present). */ - void (*complete_resync_work)(struct dirty_log *log, - region_t region, int success); + void (*set_region_sync)(struct dirty_log *log, + region_t region, int in_sync); /* * Returns the number of regions that are in sync. diff --git a/trunk/drivers/md/dm-mpath.c b/trunk/drivers/md/dm-mpath.c index d754e0bc6e90..3aa013506967 100644 --- a/trunk/drivers/md/dm-mpath.c +++ b/trunk/drivers/md/dm-mpath.c @@ -31,7 +31,7 @@ struct pgpath { struct priority_group *pg; /* Owning PG */ unsigned fail_count; /* Cumulative failure count */ - struct path path; + struct dm_path path; }; #define path_to_pgpath(__pgp) container_of((__pgp), struct pgpath, path) @@ -101,11 +101,11 @@ typedef int (*action_fn) (struct pgpath *pgpath); #define MIN_IOS 256 /* Mempool size */ -static kmem_cache_t *_mpio_cache; +static struct kmem_cache *_mpio_cache; struct workqueue_struct *kmultipathd; -static void process_queued_ios(void *data); -static void trigger_event(void *data); +static void process_queued_ios(struct work_struct *work); +static void trigger_event(struct work_struct *work); /*----------------------------------------------- @@ -173,8 +173,8 @@ static struct multipath *alloc_multipath(struct dm_target *ti) INIT_LIST_HEAD(&m->priority_groups); spin_lock_init(&m->lock); m->queue_io = 1; - INIT_WORK(&m->process_queued_ios, process_queued_ios, m); - INIT_WORK(&m->trigger_event, trigger_event, m); + INIT_WORK(&m->process_queued_ios, process_queued_ios); + INIT_WORK(&m->trigger_event, trigger_event); m->mpio_pool = mempool_create_slab_pool(MIN_IOS, _mpio_cache); if (!m->mpio_pool) { kfree(m); @@ -229,7 +229,7 @@ static void __switch_pg(struct multipath *m, struct pgpath *pgpath) static int __choose_path_in_pg(struct multipath *m, struct priority_group *pg) { - struct path *path; + struct dm_path *path; path = pg->ps.type->select_path(&pg->ps, &m->repeat_count); if (!path) @@ -282,10 +282,27 @@ static void __choose_pgpath(struct multipath *m) m->current_pg = NULL; } +/* + * Check whether bios must be queued in the device-mapper core rather + * than here in the target. + * + * m->lock must be held on entry. + * + * If m->queue_if_no_path and m->saved_queue_if_no_path hold the + * same value then we are not between multipath_presuspend() + * and multipath_resume() calls and we have no need to check + * for the DMF_NOFLUSH_SUSPENDING flag. + */ +static int __must_push_back(struct multipath *m) +{ + return (m->queue_if_no_path != m->saved_queue_if_no_path && + dm_noflush_suspending(m->ti)); +} + static int map_io(struct multipath *m, struct bio *bio, struct mpath_io *mpio, unsigned was_queued) { - int r = 1; + int r = DM_MAPIO_REMAPPED; unsigned long flags; struct pgpath *pgpath; @@ -310,11 +327,13 @@ static int map_io(struct multipath *m, struct bio *bio, struct mpath_io *mpio, !m->queue_io) queue_work(kmultipathd, &m->process_queued_ios); pgpath = NULL; - r = 0; - } else if (!pgpath) - r = -EIO; /* Failed */ - else + r = DM_MAPIO_SUBMITTED; + } else if (pgpath) bio->bi_bdev = pgpath->path.dev->bdev; + else if (__must_push_back(m)) + r = DM_MAPIO_REQUEUE; + else + r = -EIO; /* Failed */ mpio->pgpath = pgpath; @@ -372,16 +391,19 @@ static void dispatch_queued_ios(struct multipath *m) r = map_io(m, bio, mpio, 1); if (r < 0) bio_endio(bio, bio->bi_size, r); - else if (r == 1) + else if (r == DM_MAPIO_REMAPPED) generic_make_request(bio); + else if (r == DM_MAPIO_REQUEUE) + bio_endio(bio, bio->bi_size, -EIO); bio = next; } } -static void process_queued_ios(void *data) +static void process_queued_ios(struct work_struct *work) { - struct multipath *m = (struct multipath *) data; + struct multipath *m = + container_of(work, struct multipath, process_queued_ios); struct hw_handler *hwh = &m->hw_handler; struct pgpath *pgpath = NULL; unsigned init_required = 0, must_queue = 1; @@ -421,9 +443,10 @@ static void process_queued_ios(void *data) * An event is triggered whenever a path is taken out of use. * Includes path failure and PG bypass. */ -static void trigger_event(void *data) +static void trigger_event(struct work_struct *work) { - struct multipath *m = (struct multipath *) data; + struct multipath *m = + container_of(work, struct multipath, trigger_event); dm_table_event(m->ti->table); } @@ -781,7 +804,7 @@ static int multipath_map(struct dm_target *ti, struct bio *bio, map_context->ptr = mpio; bio->bi_rw |= (1 << BIO_RW_FAILFAST); r = map_io(m, bio, mpio, 0); - if (r < 0) + if (r < 0 || r == DM_MAPIO_REQUEUE) mempool_free(mpio, m->mpio_pool); return r; @@ -955,7 +978,7 @@ static int bypass_pg_num(struct multipath *m, const char *pgstr, int bypassed) /* * pg_init must call this when it has completed its initialisation */ -void dm_pg_init_complete(struct path *path, unsigned err_flags) +void dm_pg_init_complete(struct dm_path *path, unsigned err_flags) { struct pgpath *pgpath = path_to_pgpath(path); struct priority_group *pg = pgpath->pg; @@ -1005,7 +1028,10 @@ static int do_end_io(struct multipath *m, struct bio *bio, spin_lock_irqsave(&m->lock, flags); if (!m->nr_valid_paths) { - if (!m->queue_if_no_path) { + if (__must_push_back(m)) { + spin_unlock_irqrestore(&m->lock, flags); + return DM_ENDIO_REQUEUE; + } else if (!m->queue_if_no_path) { spin_unlock_irqrestore(&m->lock, flags); return -EIO; } else { @@ -1040,7 +1066,7 @@ static int do_end_io(struct multipath *m, struct bio *bio, queue_work(kmultipathd, &m->process_queued_ios); spin_unlock_irqrestore(&m->lock, flags); - return 1; /* io not complete */ + return DM_ENDIO_INCOMPLETE; /* io not complete */ } static int multipath_end_io(struct dm_target *ti, struct bio *bio, @@ -1058,7 +1084,7 @@ static int multipath_end_io(struct dm_target *ti, struct bio *bio, if (ps->type->end_io) ps->type->end_io(ps, &pgpath->path); } - if (r <= 0) + if (r != DM_ENDIO_INCOMPLETE) mempool_free(mpio, m->mpio_pool); return r; @@ -1270,7 +1296,7 @@ static int multipath_ioctl(struct dm_target *ti, struct inode *inode, struct dentry fake_dentry = {}; int r = 0; - fake_file.f_dentry = &fake_dentry; + fake_file.f_path.dentry = &fake_dentry; spin_lock_irqsave(&m->lock, flags); diff --git a/trunk/drivers/md/dm-mpath.h b/trunk/drivers/md/dm-mpath.h index 8a4bf2b6d52e..b9cdcbb3ed59 100644 --- a/trunk/drivers/md/dm-mpath.h +++ b/trunk/drivers/md/dm-mpath.h @@ -11,7 +11,7 @@ struct dm_dev; -struct path { +struct dm_path { struct dm_dev *dev; /* Read-only */ unsigned is_active; /* Read-only */ @@ -20,6 +20,6 @@ struct path { }; /* Callback for hwh_pg_init_fn to use when complete */ -void dm_pg_init_complete(struct path *path, unsigned err_flags); +void dm_pg_init_complete(struct dm_path *path, unsigned err_flags); #endif diff --git a/trunk/drivers/md/dm-path-selector.h b/trunk/drivers/md/dm-path-selector.h index 732d06a84f85..27357b85d73d 100644 --- a/trunk/drivers/md/dm-path-selector.h +++ b/trunk/drivers/md/dm-path-selector.h @@ -44,7 +44,7 @@ struct path_selector_type { * Add an opaque path object, along with some selector specific * path args (eg, path priority). */ - int (*add_path) (struct path_selector *ps, struct path *path, + int (*add_path) (struct path_selector *ps, struct dm_path *path, int argc, char **argv, char **error); /* @@ -55,27 +55,27 @@ struct path_selector_type { * calling the function again. 0 means don't call it again unless * the path fails. */ - struct path *(*select_path) (struct path_selector *ps, + struct dm_path *(*select_path) (struct path_selector *ps, unsigned *repeat_count); /* * Notify the selector that a path has failed. */ - void (*fail_path) (struct path_selector *ps, struct path *p); + void (*fail_path) (struct path_selector *ps, struct dm_path *p); /* * Ask selector to reinstate a path. */ - int (*reinstate_path) (struct path_selector *ps, struct path *p); + int (*reinstate_path) (struct path_selector *ps, struct dm_path *p); /* * Table content based on parameters added in ps_add_path_fn * or path selector status */ - int (*status) (struct path_selector *ps, struct path *path, + int (*status) (struct path_selector *ps, struct dm_path *path, status_type_t type, char *result, unsigned int maxlen); - int (*end_io) (struct path_selector *ps, struct path *path); + int (*end_io) (struct path_selector *ps, struct dm_path *path); }; /* Register a path selector */ diff --git a/trunk/drivers/md/dm-raid1.c b/trunk/drivers/md/dm-raid1.c index 48a653b3f518..23a642619bed 100644 --- a/trunk/drivers/md/dm-raid1.c +++ b/trunk/drivers/md/dm-raid1.c @@ -344,6 +344,17 @@ static void dispatch_bios(struct mirror_set *ms, struct bio_list *bio_list) } } +static void complete_resync_work(struct region *reg, int success) +{ + struct region_hash *rh = reg->rh; + + rh->log->type->set_region_sync(rh->log, reg->key, success); + dispatch_bios(rh->ms, ®->delayed_bios); + if (atomic_dec_and_test(&rh->recovery_in_flight)) + wake_up_all(&_kmirrord_recovery_stopped); + up(&rh->recovery_count); +} + static void rh_update_states(struct region_hash *rh) { struct region *reg, *next; @@ -383,11 +394,7 @@ static void rh_update_states(struct region_hash *rh) */ list_for_each_entry_safe (reg, next, &recovered, list) { rh->log->type->clear_region(rh->log, reg->key); - rh->log->type->complete_resync_work(rh->log, reg->key, 1); - dispatch_bios(rh->ms, ®->delayed_bios); - if (atomic_dec_and_test(&rh->recovery_in_flight)) - wake_up_all(&_kmirrord_recovery_stopped); - up(&rh->recovery_count); + complete_resync_work(reg, 1); mempool_free(reg, rh->region_pool); } @@ -883,7 +890,7 @@ static void do_mirror(struct mirror_set *ms) do_writes(ms, &writes); } -static void do_work(void *ignored) +static void do_work(struct work_struct *ignored) { struct mirror_set *ms; @@ -1137,7 +1144,7 @@ static int mirror_map(struct dm_target *ti, struct bio *bio, if (rw == WRITE) { queue_bio(ms, bio, rw); - return 0; + return DM_MAPIO_SUBMITTED; } r = ms->rh.log->type->in_sync(ms->rh.log, @@ -1146,7 +1153,7 @@ static int mirror_map(struct dm_target *ti, struct bio *bio, return r; if (r == -EWOULDBLOCK) /* FIXME: ugly */ - r = 0; + r = DM_MAPIO_SUBMITTED; /* * We don't want to fast track a recovery just for a read @@ -1159,7 +1166,7 @@ static int mirror_map(struct dm_target *ti, struct bio *bio, if (!r) { /* Pass this io over to the daemon */ queue_bio(ms, bio, rw); - return 0; + return DM_MAPIO_SUBMITTED; } m = choose_mirror(ms, bio->bi_sector); @@ -1167,7 +1174,7 @@ static int mirror_map(struct dm_target *ti, struct bio *bio, return -EIO; map_bio(ms, m, bio); - return 1; + return DM_MAPIO_REMAPPED; } static int mirror_end_io(struct dm_target *ti, struct bio *bio, @@ -1269,7 +1276,7 @@ static int __init dm_mirror_init(void) dm_dirty_log_exit(); return r; } - INIT_WORK(&_kmirrord_work, do_work, NULL); + INIT_WORK(&_kmirrord_work, do_work); r = dm_register_target(&mirror_target); if (r < 0) { diff --git a/trunk/drivers/md/dm-round-robin.c b/trunk/drivers/md/dm-round-robin.c index 6f9fcd4db9b5..a348a97b65af 100644 --- a/trunk/drivers/md/dm-round-robin.c +++ b/trunk/drivers/md/dm-round-robin.c @@ -21,7 +21,7 @@ *---------------------------------------------------------------*/ struct path_info { struct list_head list; - struct path *path; + struct dm_path *path; unsigned repeat_count; }; @@ -80,7 +80,7 @@ static void rr_destroy(struct path_selector *ps) ps->context = NULL; } -static int rr_status(struct path_selector *ps, struct path *path, +static int rr_status(struct path_selector *ps, struct dm_path *path, status_type_t type, char *result, unsigned int maxlen) { struct path_info *pi; @@ -106,7 +106,7 @@ static int rr_status(struct path_selector *ps, struct path *path, * Called during initialisation to register each path with an * optional repeat_count. */ -static int rr_add_path(struct path_selector *ps, struct path *path, +static int rr_add_path(struct path_selector *ps, struct dm_path *path, int argc, char **argv, char **error) { struct selector *s = (struct selector *) ps->context; @@ -141,7 +141,7 @@ static int rr_add_path(struct path_selector *ps, struct path *path, return 0; } -static void rr_fail_path(struct path_selector *ps, struct path *p) +static void rr_fail_path(struct path_selector *ps, struct dm_path *p) { struct selector *s = (struct selector *) ps->context; struct path_info *pi = p->pscontext; @@ -149,7 +149,7 @@ static void rr_fail_path(struct path_selector *ps, struct path *p) list_move(&pi->list, &s->invalid_paths); } -static int rr_reinstate_path(struct path_selector *ps, struct path *p) +static int rr_reinstate_path(struct path_selector *ps, struct dm_path *p) { struct selector *s = (struct selector *) ps->context; struct path_info *pi = p->pscontext; @@ -159,7 +159,7 @@ static int rr_reinstate_path(struct path_selector *ps, struct path *p) return 0; } -static struct path *rr_select_path(struct path_selector *ps, +static struct dm_path *rr_select_path(struct path_selector *ps, unsigned *repeat_count) { struct selector *s = (struct selector *) ps->context; diff --git a/trunk/drivers/md/dm-snap.c b/trunk/drivers/md/dm-snap.c index 5281e0094072..0821a2b68a73 100644 --- a/trunk/drivers/md/dm-snap.c +++ b/trunk/drivers/md/dm-snap.c @@ -39,8 +39,8 @@ */ #define SNAPSHOT_PAGES 256 -struct workqueue_struct *ksnapd; -static void flush_queued_bios(void *data); +static struct workqueue_struct *ksnapd; +static void flush_queued_bios(struct work_struct *work); struct pending_exception { struct exception e; @@ -88,8 +88,8 @@ struct pending_exception { * Hash table mapping origin volumes to lists of snapshots and * a lock to protect it */ -static kmem_cache_t *exception_cache; -static kmem_cache_t *pending_cache; +static struct kmem_cache *exception_cache; +static struct kmem_cache *pending_cache; static mempool_t *pending_pool; /* @@ -228,7 +228,7 @@ static int init_exception_table(struct exception_table *et, uint32_t size) return 0; } -static void exit_exception_table(struct exception_table *et, kmem_cache_t *mem) +static void exit_exception_table(struct exception_table *et, struct kmem_cache *mem) { struct list_head *slot; struct exception *ex, *next; @@ -528,7 +528,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv) } bio_list_init(&s->queued_bios); - INIT_WORK(&s->queued_bios_work, flush_queued_bios, s); + INIT_WORK(&s->queued_bios_work, flush_queued_bios); /* Add snapshot to the list of snapshots for this origin */ /* Exceptions aren't triggered till snapshot_resume() is called */ @@ -564,6 +564,17 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv) return r; } +static void __free_exceptions(struct dm_snapshot *s) +{ + kcopyd_client_destroy(s->kcopyd_client); + s->kcopyd_client = NULL; + + exit_exception_table(&s->pending, pending_cache); + exit_exception_table(&s->complete, exception_cache); + + s->store.destroy(&s->store); +} + static void snapshot_dtr(struct dm_target *ti) { struct dm_snapshot *s = (struct dm_snapshot *) ti->private; @@ -574,13 +585,7 @@ static void snapshot_dtr(struct dm_target *ti) /* After this returns there can be no new kcopyd jobs. */ unregister_snapshot(s); - kcopyd_client_destroy(s->kcopyd_client); - - exit_exception_table(&s->pending, pending_cache); - exit_exception_table(&s->complete, exception_cache); - - /* Deallocate memory used */ - s->store.destroy(&s->store); + __free_exceptions(s); dm_put_device(ti, s->origin); dm_put_device(ti, s->cow); @@ -603,9 +608,10 @@ static void flush_bios(struct bio *bio) } } -static void flush_queued_bios(void *data) +static void flush_queued_bios(struct work_struct *work) { - struct dm_snapshot *s = (struct dm_snapshot *) data; + struct dm_snapshot *s = + container_of(work, struct dm_snapshot, queued_bios_work); struct bio *queued_bios; unsigned long flags; @@ -867,7 +873,7 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio, { struct exception *e; struct dm_snapshot *s = (struct dm_snapshot *) ti->private; - int r = 1; + int r = DM_MAPIO_REMAPPED; chunk_t chunk; struct pending_exception *pe = NULL; @@ -913,7 +919,7 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio, remap_exception(s, &pe->e, bio); bio_list_add(&pe->snapshot_bios, bio); - r = 0; + r = DM_MAPIO_SUBMITTED; if (!pe->started) { /* this is protected by snap->lock */ @@ -991,7 +997,7 @@ static int snapshot_status(struct dm_target *ti, status_type_t type, *---------------------------------------------------------------*/ static int __origin_write(struct list_head *snapshots, struct bio *bio) { - int r = 1, first = 0; + int r = DM_MAPIO_REMAPPED, first = 0; struct dm_snapshot *snap; struct exception *e; struct pending_exception *pe, *next_pe, *primary_pe = NULL; @@ -1049,7 +1055,7 @@ static int __origin_write(struct list_head *snapshots, struct bio *bio) bio_list_add(&primary_pe->origin_bios, bio); - r = 0; + r = DM_MAPIO_SUBMITTED; } if (!pe->primary_pe) { @@ -1098,7 +1104,7 @@ static int __origin_write(struct list_head *snapshots, struct bio *bio) static int do_origin(struct dm_dev *origin, struct bio *bio) { struct origin *o; - int r = 1; + int r = DM_MAPIO_REMAPPED; down_read(&_origins_lock); o = __lookup_origin(origin->bdev); @@ -1155,7 +1161,7 @@ static int origin_map(struct dm_target *ti, struct bio *bio, return -EOPNOTSUPP; /* Only tell snapshots if this is a write */ - return (bio_rw(bio) == WRITE) ? do_origin(dev, bio) : 1; + return (bio_rw(bio) == WRITE) ? do_origin(dev, bio) : DM_MAPIO_REMAPPED; } #define min_not_zero(l, r) (l == 0) ? r : ((r == 0) ? l : min(l, r)) diff --git a/trunk/drivers/md/dm-stripe.c b/trunk/drivers/md/dm-stripe.c index 6c29fcecd892..51f5e0760012 100644 --- a/trunk/drivers/md/dm-stripe.c +++ b/trunk/drivers/md/dm-stripe.c @@ -186,7 +186,7 @@ static int stripe_map(struct dm_target *ti, struct bio *bio, bio->bi_bdev = sc->stripe[stripe].dev->bdev; bio->bi_sector = sc->stripe[stripe].physical_start + (chunk << sc->chunk_shift) + (offset & sc->chunk_mask); - return 1; + return DM_MAPIO_REMAPPED; } static int stripe_status(struct dm_target *ti, diff --git a/trunk/drivers/md/dm-zero.c b/trunk/drivers/md/dm-zero.c index ea569f7348d2..f314d7dc9c26 100644 --- a/trunk/drivers/md/dm-zero.c +++ b/trunk/drivers/md/dm-zero.c @@ -46,7 +46,7 @@ static int zero_map(struct dm_target *ti, struct bio *bio, bio_endio(bio, bio->bi_size, 0); /* accepted bio, don't make new request */ - return 0; + return DM_MAPIO_SUBMITTED; } static struct target_type zero_target = { diff --git a/trunk/drivers/md/dm.c b/trunk/drivers/md/dm.c index fc4f743f3b53..fe7c56e10435 100644 --- a/trunk/drivers/md/dm.c +++ b/trunk/drivers/md/dm.c @@ -68,10 +68,12 @@ union map_info *dm_get_mapinfo(struct bio *bio) #define DMF_FROZEN 2 #define DMF_FREEING 3 #define DMF_DELETING 4 +#define DMF_NOFLUSH_SUSPENDING 5 struct mapped_device { struct rw_semaphore io_lock; struct semaphore suspend_lock; + spinlock_t pushback_lock; rwlock_t map_lock; atomic_t holders; atomic_t open_count; @@ -89,7 +91,8 @@ struct mapped_device { */ atomic_t pending; wait_queue_head_t wait; - struct bio_list deferred; + struct bio_list deferred; + struct bio_list pushback; /* * The current mapping. @@ -121,8 +124,8 @@ struct mapped_device { }; #define MIN_IOS 256 -static kmem_cache_t *_io_cache; -static kmem_cache_t *_tio_cache; +static struct kmem_cache *_io_cache; +static struct kmem_cache *_tio_cache; static int __init local_init(void) { @@ -444,23 +447,50 @@ int dm_set_geometry(struct mapped_device *md, struct hd_geometry *geo) * you this clearly demarcated crap. *---------------------------------------------------------------*/ +static int __noflush_suspending(struct mapped_device *md) +{ + return test_bit(DMF_NOFLUSH_SUSPENDING, &md->flags); +} + /* * Decrements the number of outstanding ios that a bio has been * cloned into, completing the original io if necc. */ static void dec_pending(struct dm_io *io, int error) { - if (error) + unsigned long flags; + + /* Push-back supersedes any I/O errors */ + if (error && !(io->error > 0 && __noflush_suspending(io->md))) io->error = error; if (atomic_dec_and_test(&io->io_count)) { + if (io->error == DM_ENDIO_REQUEUE) { + /* + * Target requested pushing back the I/O. + * This must be handled before the sleeper on + * suspend queue merges the pushback list. + */ + spin_lock_irqsave(&io->md->pushback_lock, flags); + if (__noflush_suspending(io->md)) + bio_list_add(&io->md->pushback, io->bio); + else + /* noflush suspend was interrupted. */ + io->error = -EIO; + spin_unlock_irqrestore(&io->md->pushback_lock, flags); + } + if (end_io_acct(io)) /* nudge anyone waiting on suspend queue */ wake_up(&io->md->wait); - blk_add_trace_bio(io->md->queue, io->bio, BLK_TA_COMPLETE); + if (io->error != DM_ENDIO_REQUEUE) { + blk_add_trace_bio(io->md->queue, io->bio, + BLK_TA_COMPLETE); + + bio_endio(io->bio, io->bio->bi_size, io->error); + } - bio_endio(io->bio, io->bio->bi_size, io->error); free_io(io->md, io); } } @@ -480,12 +510,19 @@ static int clone_endio(struct bio *bio, unsigned int done, int error) if (endio) { r = endio(tio->ti, bio, error, &tio->info); - if (r < 0) + if (r < 0 || r == DM_ENDIO_REQUEUE) + /* + * error and requeue request are handled + * in dec_pending(). + */ error = r; - - else if (r > 0) - /* the target wants another shot at the io */ + else if (r == DM_ENDIO_INCOMPLETE) + /* The target will handle the io */ return 1; + else if (r) { + DMWARN("unimplemented target endio return value: %d", r); + BUG(); + } } dec_pending(tio->io, error); @@ -543,7 +580,7 @@ static void __map_bio(struct dm_target *ti, struct bio *clone, atomic_inc(&tio->io->io_count); sector = clone->bi_sector; r = ti->type->map(ti, clone, &tio->info); - if (r > 0) { + if (r == DM_MAPIO_REMAPPED) { /* the bio has been remapped so dispatch it */ blk_add_trace_remap(bdev_get_queue(clone->bi_bdev), clone, @@ -551,10 +588,8 @@ static void __map_bio(struct dm_target *ti, struct bio *clone, clone->bi_sector); generic_make_request(clone); - } - - else if (r < 0) { - /* error the io and bail out */ + } else if (r < 0 || r == DM_MAPIO_REQUEUE) { + /* error the io and bail out, or requeue it if needed */ md = tio->io->md; dec_pending(tio->io, r); /* @@ -563,6 +598,9 @@ static void __map_bio(struct dm_target *ti, struct bio *clone, clone->bi_private = md->bs; bio_put(clone); free_tio(md, tio); + } else if (r) { + DMWARN("unimplemented target map return value: %d", r); + BUG(); } } @@ -948,6 +986,7 @@ static struct mapped_device *alloc_dev(int minor) memset(md, 0, sizeof(*md)); init_rwsem(&md->io_lock); init_MUTEX(&md->suspend_lock); + spin_lock_init(&md->pushback_lock); rwlock_init(&md->map_lock); atomic_set(&md->holders, 1); atomic_set(&md->open_count, 0); @@ -966,8 +1005,8 @@ static struct mapped_device *alloc_dev(int minor) md->queue->issue_flush_fn = dm_flush_all; md->io_pool = mempool_create_slab_pool(MIN_IOS, _io_cache); - if (!md->io_pool) - goto bad2; + if (!md->io_pool) + goto bad2; md->tio_pool = mempool_create_slab_pool(MIN_IOS, _tio_cache); if (!md->tio_pool) @@ -1275,12 +1314,15 @@ static void unlock_fs(struct mapped_device *md) * dm_bind_table, dm_suspend must be called to flush any in * flight bios and ensure that any further io gets deferred. */ -int dm_suspend(struct mapped_device *md, int do_lockfs) +int dm_suspend(struct mapped_device *md, unsigned suspend_flags) { struct dm_table *map = NULL; + unsigned long flags; DECLARE_WAITQUEUE(wait, current); struct bio *def; int r = -EINVAL; + int do_lockfs = suspend_flags & DM_SUSPEND_LOCKFS_FLAG ? 1 : 0; + int noflush = suspend_flags & DM_SUSPEND_NOFLUSH_FLAG ? 1 : 0; down(&md->suspend_lock); @@ -1289,6 +1331,13 @@ int dm_suspend(struct mapped_device *md, int do_lockfs) map = dm_get_table(md); + /* + * DMF_NOFLUSH_SUSPENDING must be set before presuspend. + * This flag is cleared before dm_suspend returns. + */ + if (noflush) + set_bit(DMF_NOFLUSH_SUSPENDING, &md->flags); + /* This does not get reverted if there's an error later. */ dm_table_presuspend_targets(map); @@ -1296,11 +1345,14 @@ int dm_suspend(struct mapped_device *md, int do_lockfs) if (!md->suspended_bdev) { DMWARN("bdget failed in dm_suspend"); r = -ENOMEM; - goto out; + goto flush_and_out; } - /* Flush I/O to the device. */ - if (do_lockfs) { + /* + * Flush I/O to the device. + * noflush supersedes do_lockfs, because lock_fs() needs to flush I/Os. + */ + if (do_lockfs && !noflush) { r = lock_fs(md); if (r) goto out; @@ -1336,6 +1388,14 @@ int dm_suspend(struct mapped_device *md, int do_lockfs) down_write(&md->io_lock); remove_wait_queue(&md->wait, &wait); + if (noflush) { + spin_lock_irqsave(&md->pushback_lock, flags); + clear_bit(DMF_NOFLUSH_SUSPENDING, &md->flags); + bio_list_merge_head(&md->deferred, &md->pushback); + bio_list_init(&md->pushback); + spin_unlock_irqrestore(&md->pushback_lock, flags); + } + /* were we interrupted ? */ r = -EINTR; if (atomic_read(&md->pending)) { @@ -1344,7 +1404,7 @@ int dm_suspend(struct mapped_device *md, int do_lockfs) __flush_deferred_io(md, def); up_write(&md->io_lock); unlock_fs(md); - goto out; + goto out; /* pushback list is already flushed, so skip flush */ } up_write(&md->io_lock); @@ -1354,6 +1414,25 @@ int dm_suspend(struct mapped_device *md, int do_lockfs) r = 0; +flush_and_out: + if (r && noflush) { + /* + * Because there may be already I/Os in the pushback list, + * flush them before return. + */ + down_write(&md->io_lock); + + spin_lock_irqsave(&md->pushback_lock, flags); + clear_bit(DMF_NOFLUSH_SUSPENDING, &md->flags); + bio_list_merge_head(&md->deferred, &md->pushback); + bio_list_init(&md->pushback); + spin_unlock_irqrestore(&md->pushback_lock, flags); + + def = bio_list_get(&md->deferred); + __flush_deferred_io(md, def); + up_write(&md->io_lock); + } + out: if (r && md->suspended_bdev) { bdput(md->suspended_bdev); @@ -1440,6 +1519,17 @@ int dm_suspended(struct mapped_device *md) return test_bit(DMF_SUSPENDED, &md->flags); } +int dm_noflush_suspending(struct dm_target *ti) +{ + struct mapped_device *md = dm_table_get_md(ti->table); + int r = __noflush_suspending(md); + + dm_put(md); + + return r; +} +EXPORT_SYMBOL_GPL(dm_noflush_suspending); + static struct block_device_operations dm_blk_dops = { .open = dm_blk_open, .release = dm_blk_close, diff --git a/trunk/drivers/md/dm.h b/trunk/drivers/md/dm.h index a48ec5e3c1f4..2f796b1436b2 100644 --- a/trunk/drivers/md/dm.h +++ b/trunk/drivers/md/dm.h @@ -32,6 +32,25 @@ #define SECTOR_SHIFT 9 +/* + * Definitions of return values from target end_io function. + */ +#define DM_ENDIO_INCOMPLETE 1 +#define DM_ENDIO_REQUEUE 2 + +/* + * Definitions of return values from target map function. + */ +#define DM_MAPIO_SUBMITTED 0 +#define DM_MAPIO_REMAPPED 1 +#define DM_MAPIO_REQUEUE DM_ENDIO_REQUEUE + +/* + * Suspend feature flags + */ +#define DM_SUSPEND_LOCKFS_FLAG (1 << 0) +#define DM_SUSPEND_NOFLUSH_FLAG (1 << 1) + /* * List of devices that a metadevice uses and should open/close. */ diff --git a/trunk/drivers/md/kcopyd.c b/trunk/drivers/md/kcopyd.c index f1db6eff4857..b46f6c575f7e 100644 --- a/trunk/drivers/md/kcopyd.c +++ b/trunk/drivers/md/kcopyd.c @@ -203,7 +203,7 @@ struct kcopyd_job { /* FIXME: this should scale with the number of pages */ #define MIN_JOBS 512 -static kmem_cache_t *_job_cache; +static struct kmem_cache *_job_cache; static mempool_t *_job_pool; /* @@ -417,7 +417,7 @@ static int process_jobs(struct list_head *jobs, int (*fn) (struct kcopyd_job *)) /* * kcopyd does this every time it's woken up. */ -static void do_work(void *ignored) +static void do_work(struct work_struct *ignored) { /* * The order that these are called is *very* important. @@ -628,7 +628,7 @@ static int kcopyd_init(void) } kcopyd_clients++; - INIT_WORK(&_kcopyd_work, do_work, NULL); + INIT_WORK(&_kcopyd_work, do_work); mutex_unlock(&kcopyd_init_lock); return 0; } diff --git a/trunk/drivers/md/md.c b/trunk/drivers/md/md.c index 8cbf9c9df1c3..53bd46dba0cb 100644 --- a/trunk/drivers/md/md.c +++ b/trunk/drivers/md/md.c @@ -39,10 +39,10 @@ #include #include #include /* for invalidate_bdev */ -#include #include #include #include +#include #include @@ -1413,7 +1413,7 @@ static int lock_rdev(mdk_rdev_t *rdev, dev_t dev) struct block_device *bdev; char b[BDEVNAME_SIZE]; - bdev = open_partition_by_devnum(dev, FMODE_READ|FMODE_WRITE); + bdev = open_by_devnum(dev, FMODE_READ|FMODE_WRITE); if (IS_ERR(bdev)) { printk(KERN_ERR "md: could not open %s.\n", __bdevname(dev, b)); @@ -1423,7 +1423,7 @@ static int lock_rdev(mdk_rdev_t *rdev, dev_t dev) if (err) { printk(KERN_ERR "md: could not bd_claim %s.\n", bdevname(bdev, b)); - blkdev_put_partition(bdev); + blkdev_put(bdev); return err; } rdev->bdev = bdev; @@ -1437,7 +1437,7 @@ static void unlock_rdev(mdk_rdev_t *rdev) if (!bdev) MD_BUG(); bd_release(bdev); - blkdev_put_partition(bdev); + blkdev_put(bdev); } void md_autodetect_dev(dev_t dev); @@ -4423,7 +4423,7 @@ static int md_open(struct inode *inode, struct file *file) mddev_t *mddev = inode->i_bdev->bd_disk->private_data; int err; - if ((err = mddev_lock(mddev))) + if ((err = mutex_lock_interruptible_nested(&mddev->reconfig_mutex, 1))) goto out; err = 0; @@ -4846,8 +4846,8 @@ static int md_seq_show(struct seq_file *seq, void *v) chunk_kb ? "KB" : "B"); if (bitmap->file) { seq_printf(seq, ", file: "); - seq_path(seq, bitmap->file->f_vfsmnt, - bitmap->file->f_dentry," \t\n"); + seq_path(seq, bitmap->file->f_path.mnt, + bitmap->file->f_path.dentry," \t\n"); } seq_printf(seq, "\n"); diff --git a/trunk/drivers/md/raid5.c b/trunk/drivers/md/raid5.c index 69c3e201fa3b..52914d5cec76 100644 --- a/trunk/drivers/md/raid5.c +++ b/trunk/drivers/md/raid5.c @@ -348,7 +348,7 @@ static int grow_one_stripe(raid5_conf_t *conf) static int grow_stripes(raid5_conf_t *conf, int num) { - kmem_cache_t *sc; + struct kmem_cache *sc; int devs = conf->raid_disks; sprintf(conf->cache_name[0], "raid5/%s", mdname(conf->mddev)); @@ -397,7 +397,7 @@ static int resize_stripes(raid5_conf_t *conf, int newsize) LIST_HEAD(newstripes); struct disk_info *ndisks; int err = 0; - kmem_cache_t *sc; + struct kmem_cache *sc; int i; if (newsize <= conf->pool_size) diff --git a/trunk/drivers/media/dvb/b2c2/flexcop-pci.c b/trunk/drivers/media/dvb/b2c2/flexcop-pci.c index 06893243f3d4..6e166801505d 100644 --- a/trunk/drivers/media/dvb/b2c2/flexcop-pci.c +++ b/trunk/drivers/media/dvb/b2c2/flexcop-pci.c @@ -63,7 +63,7 @@ struct flexcop_pci { unsigned long last_irq; - struct work_struct irq_check_work; + struct delayed_work irq_check_work; struct flexcop_device *fc_dev; }; @@ -97,9 +97,10 @@ static int flexcop_pci_write_ibi_reg(struct flexcop_device *fc, flexcop_ibi_regi return 0; } -static void flexcop_pci_irq_check_work(void *data) +static void flexcop_pci_irq_check_work(struct work_struct *work) { - struct flexcop_pci *fc_pci = data; + struct flexcop_pci *fc_pci = + container_of(work, struct flexcop_pci, irq_check_work.work); struct flexcop_device *fc = fc_pci->fc_dev; flexcop_ibi_value v = fc->read_ibi_reg(fc,sram_dest_reg_714); @@ -371,7 +372,7 @@ static int flexcop_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e if ((ret = flexcop_pci_dma_init(fc_pci)) != 0) goto err_fc_exit; - INIT_WORK(&fc_pci->irq_check_work, flexcop_pci_irq_check_work, fc_pci); + INIT_DELAYED_WORK(&fc_pci->irq_check_work, flexcop_pci_irq_check_work); return ret; diff --git a/trunk/drivers/media/dvb/cinergyT2/cinergyT2.c b/trunk/drivers/media/dvb/cinergyT2/cinergyT2.c index 8a7dd507cf6e..9123147e376f 100644 --- a/trunk/drivers/media/dvb/cinergyT2/cinergyT2.c +++ b/trunk/drivers/media/dvb/cinergyT2/cinergyT2.c @@ -128,7 +128,7 @@ struct cinergyt2 { struct dvbt_set_parameters_msg param; struct dvbt_get_status_msg status; - struct work_struct query_work; + struct delayed_work query_work; wait_queue_head_t poll_wq; int pending_fe_events; @@ -142,7 +142,7 @@ struct cinergyt2 { #ifdef ENABLE_RC struct input_dev *rc_input_dev; char phys[64]; - struct work_struct rc_query_work; + struct delayed_work rc_query_work; int rc_input_event; u32 rc_last_code; unsigned long last_event_jiffies; @@ -287,7 +287,7 @@ static int cinergyt2_alloc_stream_urbs (struct cinergyt2 *cinergyt2) int i; cinergyt2->streambuf = usb_buffer_alloc(cinergyt2->udev, STREAM_URB_COUNT*STREAM_BUF_SIZE, - SLAB_KERNEL, &cinergyt2->streambuf_dmahandle); + GFP_KERNEL, &cinergyt2->streambuf_dmahandle); if (!cinergyt2->streambuf) { dprintk(1, "failed to alloc consistent stream memory area, bailing out!\n"); return -ENOMEM; @@ -723,9 +723,10 @@ static struct dvb_device cinergyt2_fe_template = { #ifdef ENABLE_RC -static void cinergyt2_query_rc (void *data) +static void cinergyt2_query_rc (struct work_struct *work) { - struct cinergyt2 *cinergyt2 = data; + struct cinergyt2 *cinergyt2 = + container_of(work, struct cinergyt2, rc_query_work.work); char buf[1] = { CINERGYT2_EP1_GET_RC_EVENTS }; struct cinergyt2_rc_event rc_events[12]; int n, len, i; @@ -806,7 +807,7 @@ static int cinergyt2_register_rc(struct cinergyt2 *cinergyt2) strlcat(cinergyt2->phys, "/input0", sizeof(cinergyt2->phys)); cinergyt2->rc_input_event = KEY_MAX; cinergyt2->rc_last_code = ~0; - INIT_WORK(&cinergyt2->rc_query_work, cinergyt2_query_rc, cinergyt2); + INIT_DELAYED_WORK(&cinergyt2->rc_query_work, cinergyt2_query_rc); input_dev->name = DRIVER_NAME " remote control"; input_dev->phys = cinergyt2->phys; @@ -847,9 +848,10 @@ static inline void cinergyt2_resume_rc(struct cinergyt2 *cinergyt2) { } #endif /* ENABLE_RC */ -static void cinergyt2_query (void *data) +static void cinergyt2_query (struct work_struct *work) { - struct cinergyt2 *cinergyt2 = (struct cinergyt2 *) data; + struct cinergyt2 *cinergyt2 = + container_of(work, struct cinergyt2, query_work.work); char cmd [] = { CINERGYT2_EP1_GET_TUNER_STATUS }; struct dvbt_get_status_msg *s = &cinergyt2->status; uint8_t lock_bits; @@ -893,7 +895,7 @@ static int cinergyt2_probe (struct usb_interface *intf, mutex_init(&cinergyt2->sem); init_waitqueue_head (&cinergyt2->poll_wq); - INIT_WORK(&cinergyt2->query_work, cinergyt2_query, cinergyt2); + INIT_DELAYED_WORK(&cinergyt2->query_work, cinergyt2_query); cinergyt2->udev = interface_to_usbdev(intf); cinergyt2->param.cmd = CINERGYT2_EP1_SET_TUNER_PARAMETERS; diff --git a/trunk/drivers/media/dvb/dvb-core/dvb_frontend.c b/trunk/drivers/media/dvb/dvb-core/dvb_frontend.c index a2ab2eebfc68..e85972222ab4 100644 --- a/trunk/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/trunk/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -34,7 +34,7 @@ #include #include #include -#include +#include #include #include diff --git a/trunk/drivers/media/dvb/dvb-core/dvb_net.c b/trunk/drivers/media/dvb/dvb-core/dvb_net.c index 8859ab74f0fe..ebf4dc5190f6 100644 --- a/trunk/drivers/media/dvb/dvb-core/dvb_net.c +++ b/trunk/drivers/media/dvb/dvb-core/dvb_net.c @@ -127,6 +127,7 @@ struct dvb_net_priv { int in_use; struct net_device_stats stats; u16 pid; + struct net_device *net; struct dvb_net *host; struct dmx_demux *demux; struct dmx_section_feed *secfeed; @@ -1123,10 +1124,11 @@ static int dvb_set_mc_filter (struct net_device *dev, struct dev_mc_list *mc) } -static void wq_set_multicast_list (void *data) +static void wq_set_multicast_list (struct work_struct *work) { - struct net_device *dev = data; - struct dvb_net_priv *priv = dev->priv; + struct dvb_net_priv *priv = + container_of(work, struct dvb_net_priv, set_multicast_list_wq); + struct net_device *dev = priv->net; dvb_net_feed_stop(dev); priv->rx_mode = RX_MODE_UNI; @@ -1167,9 +1169,11 @@ static void dvb_net_set_multicast_list (struct net_device *dev) } -static void wq_restart_net_feed (void *data) +static void wq_restart_net_feed (struct work_struct *work) { - struct net_device *dev = data; + struct dvb_net_priv *priv = + container_of(work, struct dvb_net_priv, restart_net_feed_wq); + struct net_device *dev = priv->net; if (netif_running(dev)) { dvb_net_feed_stop(dev); @@ -1276,6 +1280,7 @@ static int dvb_net_add_if(struct dvb_net *dvbnet, u16 pid, u8 feedtype) dvbnet->device[if_num] = net; priv = net->priv; + priv->net = net; priv->demux = dvbnet->demux; priv->pid = pid; priv->rx_mode = RX_MODE_UNI; @@ -1284,8 +1289,8 @@ static int dvb_net_add_if(struct dvb_net *dvbnet, u16 pid, u8 feedtype) priv->feedtype = feedtype; reset_ule(priv); - INIT_WORK(&priv->set_multicast_list_wq, wq_set_multicast_list, net); - INIT_WORK(&priv->restart_net_feed_wq, wq_restart_net_feed, net); + INIT_WORK(&priv->set_multicast_list_wq, wq_set_multicast_list); + INIT_WORK(&priv->restart_net_feed_wq, wq_restart_net_feed); mutex_init(&priv->mutex); net->base_addr = pid; diff --git a/trunk/drivers/media/dvb/dvb-usb/dvb-usb-remote.c b/trunk/drivers/media/dvb/dvb-usb/dvb-usb-remote.c index 0a3a0b6c2350..794e4471561c 100644 --- a/trunk/drivers/media/dvb/dvb-usb/dvb-usb-remote.c +++ b/trunk/drivers/media/dvb/dvb-usb/dvb-usb-remote.c @@ -13,9 +13,10 @@ * * TODO: Fix the repeat rate of the input device. */ -static void dvb_usb_read_remote_control(void *data) +static void dvb_usb_read_remote_control(struct work_struct *work) { - struct dvb_usb_device *d = data; + struct dvb_usb_device *d = + container_of(work, struct dvb_usb_device, rc_query_work.work); u32 event; int state; @@ -128,7 +129,7 @@ int dvb_usb_remote_init(struct dvb_usb_device *d) input_register_device(d->rc_input_dev); - INIT_WORK(&d->rc_query_work, dvb_usb_read_remote_control, d); + INIT_DELAYED_WORK(&d->rc_query_work, dvb_usb_read_remote_control); info("schedule remote query interval to %d msecs.", d->props.rc_interval); schedule_delayed_work(&d->rc_query_work,msecs_to_jiffies(d->props.rc_interval)); diff --git a/trunk/drivers/media/dvb/dvb-usb/dvb-usb.h b/trunk/drivers/media/dvb/dvb-usb/dvb-usb.h index 376c45a8e779..0d721731a524 100644 --- a/trunk/drivers/media/dvb/dvb-usb/dvb-usb.h +++ b/trunk/drivers/media/dvb/dvb-usb/dvb-usb.h @@ -369,7 +369,7 @@ struct dvb_usb_device { /* remote control */ struct input_dev *rc_input_dev; char rc_phys[64]; - struct work_struct rc_query_work; + struct delayed_work rc_query_work; u32 last_event; int last_state; diff --git a/trunk/drivers/media/dvb/dvb-usb/usb-urb.c b/trunk/drivers/media/dvb/dvb-usb/usb-urb.c index 78035ee824ca..397f51a7b2ad 100644 --- a/trunk/drivers/media/dvb/dvb-usb/usb-urb.c +++ b/trunk/drivers/media/dvb/dvb-usb/usb-urb.c @@ -116,7 +116,7 @@ static int usb_allocate_stream_buffers(struct usb_data_stream *stream, int num, for (stream->buf_num = 0; stream->buf_num < num; stream->buf_num++) { deb_mem("allocating buffer %d\n",stream->buf_num); if (( stream->buf_list[stream->buf_num] = - usb_buffer_alloc(stream->udev, size, SLAB_ATOMIC, + usb_buffer_alloc(stream->udev, size, GFP_ATOMIC, &stream->dma_addr[stream->buf_num]) ) == NULL) { deb_mem("not enough memory for urb-buffer allocation.\n"); usb_free_stream_buffers(stream); diff --git a/trunk/drivers/media/dvb/frontends/l64781.c b/trunk/drivers/media/dvb/frontends/l64781.c index f3bc82e44a28..1aeacb1c4af7 100644 --- a/trunk/drivers/media/dvb/frontends/l64781.c +++ b/trunk/drivers/media/dvb/frontends/l64781.c @@ -36,7 +36,7 @@ struct l64781_state { struct dvb_frontend frontend; /* private demodulator data */ - int first:1; + unsigned int first:1; }; #define dprintk(args...) \ diff --git a/trunk/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/trunk/drivers/media/dvb/ttusb-dec/ttusb_dec.c index 8135f3e76aeb..10b121ada833 100644 --- a/trunk/drivers/media/dvb/ttusb-dec/ttusb_dec.c +++ b/trunk/drivers/media/dvb/ttusb-dec/ttusb_dec.c @@ -1244,7 +1244,7 @@ static int ttusb_dec_init_usb(struct ttusb_dec *dec) return -ENOMEM; } dec->irq_buffer = usb_buffer_alloc(dec->udev,IRQ_PACKET_SIZE, - SLAB_ATOMIC, &dec->irq_dma_handle); + GFP_ATOMIC, &dec->irq_dma_handle); if(!dec->irq_buffer) { return -ENOMEM; } diff --git a/trunk/drivers/media/radio/Kconfig b/trunk/drivers/media/radio/Kconfig index 6d96b17a7f81..920b63f8cf05 100644 --- a/trunk/drivers/media/radio/Kconfig +++ b/trunk/drivers/media/radio/Kconfig @@ -173,38 +173,6 @@ config RADIO_MAESTRO To compile this driver as a module, choose M here: the module will be called radio-maestro. -config RADIO_MIROPCM20 - tristate "miroSOUND PCM20 radio" - depends on ISA && VIDEO_V4L1 && SOUND_ACI_MIXER - ---help--- - Choose Y here if you have this FM radio card. You also need to say Y - to "ACI mixer (miroSOUND PCM1-pro/PCM12/PCM20 radio)" (in "Sound") - for this to work. - - In order to control your radio card, you will need to use programs - that are compatible with the Video For Linux API. Information on - this API and pointers to "v4l" programs may be found at - . - - To compile this driver as a module, choose M here: the - module will be called miropcm20. - -config RADIO_MIROPCM20_RDS - tristate "miroSOUND PCM20 radio RDS user interface (EXPERIMENTAL)" - depends on RADIO_MIROPCM20 && EXPERIMENTAL - ---help--- - Choose Y here if you want to see RDS/RBDS information like - RadioText, Programme Service name, Clock Time and date, Programme - Type and Traffic Announcement/Programme identification. - - It's not possible to read the raw RDS packets from the device, so - the driver cant provide an V4L interface for this. But the - availability of RDS is reported over V4L by the basic driver - already. Here RDS can be read from files in /dev/v4l/rds. - - To compile this driver as a module, choose M here: the - module will be called miropcm20-rds. - config RADIO_SF16FMI tristate "SF16FMI Radio" depends on ISA && VIDEO_V4L2 diff --git a/trunk/drivers/media/video/compat_ioctl32.c b/trunk/drivers/media/video/compat_ioctl32.c index d82a488f12a6..f065ad12cc61 100644 --- a/trunk/drivers/media/video/compat_ioctl32.c +++ b/trunk/drivers/media/video/compat_ioctl32.c @@ -118,7 +118,7 @@ static int native_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ret = file->f_op->unlocked_ioctl(file, cmd, arg); else if (file->f_op->ioctl) { lock_kernel(); - ret = file->f_op->ioctl(file->f_dentry->d_inode, file, cmd, arg); + ret = file->f_op->ioctl(file->f_path.dentry->d_inode, file, cmd, arg); unlock_kernel(); } diff --git a/trunk/drivers/media/video/cpia_pp.c b/trunk/drivers/media/video/cpia_pp.c index 41f4b8d17559..b12cec94f4cc 100644 --- a/trunk/drivers/media/video/cpia_pp.c +++ b/trunk/drivers/media/video/cpia_pp.c @@ -82,6 +82,8 @@ struct pp_cam_entry { struct pardevice *pdev; struct parport *port; struct work_struct cb_task; + void (*cb_func)(void *cbdata); + void *cb_data; int open_count; wait_queue_head_t wq_stream; /* image state flags */ @@ -130,6 +132,20 @@ static void cpia_parport_disable_irq( struct parport *port ) { #define PARPORT_CHUNK_SIZE PAGE_SIZE +static void cpia_pp_run_callback(struct work_struct *work) +{ + void (*cb_func)(void *cbdata); + void *cb_data; + struct pp_cam_entry *cam; + + cam = container_of(work, struct pp_cam_entry, cb_task); + cb_func = cam->cb_func; + cb_data = cam->cb_data; + work_release(work); + + cb_func(cb_data); +} + /**************************************************************************** * * CPiA-specific low-level parport functions for nibble uploads @@ -664,7 +680,9 @@ static int cpia_pp_registerCallback(void *privdata, void (*cb)(void *cbdata), vo int retval = 0; if(cam->port->irq != PARPORT_IRQ_NONE) { - INIT_WORK(&cam->cb_task, cb, cbdata); + cam->cb_func = cb; + cam->cb_data = cbdata; + INIT_WORK_NAR(&cam->cb_task, cpia_pp_run_callback); } else { retval = -1; } diff --git a/trunk/drivers/media/video/cx88/cx88-input.c b/trunk/drivers/media/video/cx88/cx88-input.c index 57e1c024a547..e60a0a52e4b2 100644 --- a/trunk/drivers/media/video/cx88/cx88-input.c +++ b/trunk/drivers/media/video/cx88/cx88-input.c @@ -145,9 +145,9 @@ static void ir_timer(unsigned long data) schedule_work(&ir->work); } -static void cx88_ir_work(void *data) +static void cx88_ir_work(struct work_struct *work) { - struct cx88_IR *ir = data; + struct cx88_IR *ir = container_of(work, struct cx88_IR, work); unsigned long timeout; cx88_ir_handle_key(ir); @@ -308,7 +308,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) core->ir = ir; if (ir->polling) { - INIT_WORK(&ir->work, cx88_ir_work, ir); + INIT_WORK(&ir->work, cx88_ir_work); init_timer(&ir->timer); ir->timer.function = ir_timer; ir->timer.data = (unsigned long)ir; diff --git a/trunk/drivers/media/video/ir-kbd-i2c.c b/trunk/drivers/media/video/ir-kbd-i2c.c index 1457b1602221..ab87e7bfe84f 100644 --- a/trunk/drivers/media/video/ir-kbd-i2c.c +++ b/trunk/drivers/media/video/ir-kbd-i2c.c @@ -268,9 +268,9 @@ static void ir_timer(unsigned long data) schedule_work(&ir->work); } -static void ir_work(void *data) +static void ir_work(struct work_struct *work) { - struct IR_i2c *ir = data; + struct IR_i2c *ir = container_of(work, struct IR_i2c, work); ir_key_poll(ir); mod_timer(&ir->timer, jiffies+HZ/10); } @@ -400,7 +400,7 @@ static int ir_attach(struct i2c_adapter *adap, int addr, ir->input->name,ir->input->phys,adap->name); /* start polling via eventd */ - INIT_WORK(&ir->work, ir_work, ir); + INIT_WORK(&ir->work, ir_work); init_timer(&ir->timer); ir->timer.function = ir_timer; ir->timer.data = (unsigned long)ir; diff --git a/trunk/drivers/media/video/msp3400-driver.c b/trunk/drivers/media/video/msp3400-driver.c index cf43df3fe708..e1b56dc13c3f 100644 --- a/trunk/drivers/media/video/msp3400-driver.c +++ b/trunk/drivers/media/video/msp3400-driver.c @@ -56,7 +56,7 @@ #include #include #include -#include +#include #include "msp3400-driver.h" /* ---------------------------------------------------------------------- */ diff --git a/trunk/drivers/media/video/pvrusb2/pvrusb2-context.c b/trunk/drivers/media/video/pvrusb2/pvrusb2-context.c index f129f316d20e..cf129746205d 100644 --- a/trunk/drivers/media/video/pvrusb2/pvrusb2-context.c +++ b/trunk/drivers/media/video/pvrusb2/pvrusb2-context.c @@ -45,16 +45,21 @@ static void pvr2_context_trigger_poll(struct pvr2_context *mp) } -static void pvr2_context_poll(struct pvr2_context *mp) +static void pvr2_context_poll(struct work_struct *work) { + struct pvr2_context *mp = + container_of(work, struct pvr2_context, workpoll); pvr2_context_enter(mp); do { pvr2_hdw_poll(mp->hdw); } while (0); pvr2_context_exit(mp); } -static void pvr2_context_setup(struct pvr2_context *mp) +static void pvr2_context_setup(struct work_struct *work) { + struct pvr2_context *mp = + container_of(work, struct pvr2_context, workinit); + pvr2_context_enter(mp); do { if (!pvr2_hdw_dev_ok(mp->hdw)) break; pvr2_hdw_setup(mp->hdw); @@ -92,8 +97,8 @@ struct pvr2_context *pvr2_context_create( } mp->workqueue = create_singlethread_workqueue("pvrusb2"); - INIT_WORK(&mp->workinit,(void (*)(void*))pvr2_context_setup,mp); - INIT_WORK(&mp->workpoll,(void (*)(void*))pvr2_context_poll,mp); + INIT_WORK(&mp->workinit, pvr2_context_setup); + INIT_WORK(&mp->workpoll, pvr2_context_poll); queue_work(mp->workqueue,&mp->workinit); done: return mp; diff --git a/trunk/drivers/media/video/saa6588.c b/trunk/drivers/media/video/saa6588.c index 7b9859c33018..92eabf88a09b 100644 --- a/trunk/drivers/media/video/saa6588.c +++ b/trunk/drivers/media/video/saa6588.c @@ -324,9 +324,9 @@ static void saa6588_timer(unsigned long data) schedule_work(&s->work); } -static void saa6588_work(void *data) +static void saa6588_work(struct work_struct *work) { - struct saa6588 *s = (struct saa6588 *)data; + struct saa6588 *s = container_of(work, struct saa6588, work); saa6588_i2c_poll(s); mod_timer(&s->timer, jiffies + msecs_to_jiffies(20)); @@ -419,7 +419,7 @@ static int saa6588_attach(struct i2c_adapter *adap, int addr, int kind) saa6588_configure(s); /* start polling via eventd */ - INIT_WORK(&s->work, saa6588_work, s); + INIT_WORK(&s->work, saa6588_work); init_timer(&s->timer); s->timer.function = saa6588_timer; s->timer.data = (unsigned long)s; diff --git a/trunk/drivers/media/video/saa7134/saa7134-empress.c b/trunk/drivers/media/video/saa7134/saa7134-empress.c index 65d044086ce9..daaae870a2c4 100644 --- a/trunk/drivers/media/video/saa7134/saa7134-empress.c +++ b/trunk/drivers/media/video/saa7134/saa7134-empress.c @@ -343,9 +343,10 @@ static struct video_device saa7134_empress_template = .minor = -1, }; -static void empress_signal_update(void* data) +static void empress_signal_update(struct work_struct *work) { - struct saa7134_dev* dev = (struct saa7134_dev*) data; + struct saa7134_dev* dev = + container_of(work, struct saa7134_dev, empress_workqueue); if (dev->nosignal) { dprintk("no video signal\n"); @@ -378,7 +379,7 @@ static int empress_init(struct saa7134_dev *dev) "%s empress (%s)", dev->name, saa7134_boards[dev->board].name); - INIT_WORK(&dev->empress_workqueue, empress_signal_update, (void*) dev); + INIT_WORK(&dev->empress_workqueue, empress_signal_update); err = video_register_device(dev->empress_dev,VFL_TYPE_GRABBER, empress_nr[dev->nr]); @@ -399,7 +400,7 @@ static int empress_init(struct saa7134_dev *dev) sizeof(struct saa7134_buf), dev); - empress_signal_update(dev); + empress_signal_update(&dev->empress_workqueue); return 0; } diff --git a/trunk/drivers/media/video/tvaudio.c b/trunk/drivers/media/video/tvaudio.c index fcaef4bf8289..d506dfaa45a9 100644 --- a/trunk/drivers/media/video/tvaudio.c +++ b/trunk/drivers/media/video/tvaudio.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include diff --git a/trunk/drivers/media/video/video-buf-dvb.c b/trunk/drivers/media/video/video-buf-dvb.c index f53edf1923b7..fcc5467e7636 100644 --- a/trunk/drivers/media/video/video-buf-dvb.c +++ b/trunk/drivers/media/video/video-buf-dvb.c @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #include diff --git a/trunk/drivers/media/video/videodev.c b/trunk/drivers/media/video/videodev.c index d424a4129d69..41ec0c4b35a2 100644 --- a/trunk/drivers/media/video/videodev.c +++ b/trunk/drivers/media/video/videodev.c @@ -105,7 +105,7 @@ static DEFINE_MUTEX(videodev_lock); struct video_device* video_devdata(struct file *file) { - return video_device[iminor(file->f_dentry->d_inode)]; + return video_device[iminor(file->f_path.dentry->d_inode)]; } /* diff --git a/trunk/drivers/media/video/vivi.c b/trunk/drivers/media/video/vivi.c index 3c8dc72dc8e9..9986de5cb3d6 100644 --- a/trunk/drivers/media/video/vivi.c +++ b/trunk/drivers/media/video/vivi.c @@ -36,6 +36,7 @@ #include #include #include +#include /* Wake up at about 30 fps */ #define WAKE_NUMERATOR 30 diff --git a/trunk/drivers/media/video/zoran_procfs.c b/trunk/drivers/media/video/zoran_procfs.c index c7f6f6488360..c374c76b3753 100644 --- a/trunk/drivers/media/video/zoran_procfs.c +++ b/trunk/drivers/media/video/zoran_procfs.c @@ -144,7 +144,7 @@ static int zoran_open(struct inode *inode, struct file *file) static ssize_t zoran_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) { - struct zoran *zr = PDE(file->f_dentry->d_inode)->data; + struct zoran *zr = PDE(file->f_path.dentry->d_inode)->data; char *string, *sp; char *line, *ldelim, *varname, *svar, *tdelim; @@ -165,7 +165,7 @@ static ssize_t zoran_write(struct file *file, const char __user *buffer, } string[count] = 0; dprintk(4, KERN_INFO "%s: write_proc: name=%s count=%zu zr=%p\n", - ZR_DEVNAME(zr), file->f_dentry->d_name.name, count, zr); + ZR_DEVNAME(zr), file->f_path.dentry->d_name.name, count, zr); ldelim = " \t\n"; tdelim = "="; line = strpbrk(sp, ldelim); diff --git a/trunk/drivers/message/fusion/mptbase.c b/trunk/drivers/message/fusion/mptbase.c index 051b7c5b8f03..6e068cf1049b 100644 --- a/trunk/drivers/message/fusion/mptbase.c +++ b/trunk/drivers/message/fusion/mptbase.c @@ -347,7 +347,7 @@ mpt_reply(MPT_ADAPTER *ioc, u32 pa) } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* +/** * mpt_interrupt - MPT adapter (IOC) specific interrupt handler. * @irq: irq number (not used) * @bus_id: bus identifier cookie == pointer to MPT_ADAPTER structure @@ -387,14 +387,16 @@ mpt_interrupt(int irq, void *bus_id) } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * mpt_base_reply - MPT base driver's callback routine; all base driver - * "internal" request/reply processing is routed here. - * Currently used for EventNotification and EventAck handling. +/** + * mpt_base_reply - MPT base driver's callback routine * @ioc: Pointer to MPT_ADAPTER structure * @mf: Pointer to original MPT request frame * @reply: Pointer to MPT reply frame (NULL if TurboReply) * + * MPT base driver's callback routine; all base driver + * "internal" request/reply processing is routed here. + * Currently used for EventNotification and EventAck handling. + * * Returns 1 indicating original alloc'd request frame ptr * should be freed, or 0 if it shouldn't. */ @@ -530,7 +532,7 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply) * @dclass: Protocol driver's class (%MPT_DRIVER_CLASS enum value) * * This routine is called by a protocol-specific driver (SCSI host, - * LAN, SCSI target) to register it's reply callback routine. Each + * LAN, SCSI target) to register its reply callback routine. Each * protocol-specific driver must do this before it will be able to * use any IOC resources, such as obtaining request frames. * @@ -572,7 +574,7 @@ mpt_register(MPT_CALLBACK cbfunc, MPT_DRIVER_CLASS dclass) * mpt_deregister - Deregister a protocol drivers resources. * @cb_idx: previously registered callback handle * - * Each protocol-specific driver should call this routine when it's + * Each protocol-specific driver should call this routine when its * module is unloaded. */ void @@ -617,7 +619,7 @@ mpt_event_register(int cb_idx, MPT_EVHANDLER ev_cbfunc) * * Each protocol-specific driver should call this routine * when it does not (or can no longer) handle events, - * or when it's module is unloaded. + * or when its module is unloaded. */ void mpt_event_deregister(int cb_idx) @@ -656,7 +658,7 @@ mpt_reset_register(int cb_idx, MPT_RESETHANDLER reset_func) * * Each protocol-specific driver should call this routine * when it does not (or can no longer) handle IOC reset handling, - * or when it's module is unloaded. + * or when its module is unloaded. */ void mpt_reset_deregister(int cb_idx) @@ -670,6 +672,8 @@ mpt_reset_deregister(int cb_idx) /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mpt_device_driver_register - Register device driver hooks + * @dd_cbfunc: driver callbacks struct + * @cb_idx: MPT protocol driver index */ int mpt_device_driver_register(struct mpt_pci_driver * dd_cbfunc, int cb_idx) @@ -696,6 +700,7 @@ mpt_device_driver_register(struct mpt_pci_driver * dd_cbfunc, int cb_idx) /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mpt_device_driver_deregister - DeRegister device driver hooks + * @cb_idx: MPT protocol driver index */ void mpt_device_driver_deregister(int cb_idx) @@ -887,8 +892,7 @@ mpt_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr) /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** - * mpt_send_handshake_request - Send MPT request via doorbell - * handshake method. + * mpt_send_handshake_request - Send MPT request via doorbell handshake method. * @handle: Handle of registered MPT protocol driver * @ioc: Pointer to MPT adapter structure * @reqBytes: Size of the request in bytes @@ -981,10 +985,13 @@ mpt_send_handshake_request(int handle, MPT_ADAPTER *ioc, int reqBytes, u32 *req, /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** - * mpt_host_page_access_control - provides mechanism for the host - * driver to control the IOC's Host Page Buffer access. + * mpt_host_page_access_control - control the IOC's Host Page Buffer access * @ioc: Pointer to MPT adapter structure * @access_control_value: define bits below + * @sleepFlag: Specifies whether the process can sleep + * + * Provides mechanism for the host driver to control the IOC's + * Host Page Buffer access. * * Access Control Value - bits[15:12] * 0h Reserved @@ -1022,10 +1029,10 @@ mpt_host_page_access_control(MPT_ADAPTER *ioc, u8 access_control_value, int slee /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mpt_host_page_alloc - allocate system memory for the fw - * If we already allocated memory in past, then resend the same pointer. - * ioc@: Pointer to pointer to IOC adapter - * ioc_init@: Pointer to ioc init config page + * @ioc: Pointer to pointer to IOC adapter + * @ioc_init: Pointer to ioc init config page * + * If we already allocated memory in past, then resend the same pointer. * Returns 0 for success, non-zero for failure. */ static int @@ -1091,12 +1098,15 @@ return 0; /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** - * mpt_verify_adapter - Given a unique IOC identifier, set pointer to - * the associated MPT adapter structure. + * mpt_verify_adapter - Given IOC identifier, set pointer to its adapter structure. * @iocid: IOC unique identifier (integer) * @iocpp: Pointer to pointer to IOC adapter * - * Returns iocid and sets iocpp. + * Given a unique IOC identifier, set pointer to the associated MPT + * adapter structure. + * + * Returns iocid and sets iocpp if iocid is found. + * Returns -1 if iocid is not found. */ int mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp) @@ -1115,9 +1125,10 @@ mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp) } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* +/** * mpt_attach - Install a PCI intelligent MPT adapter. * @pdev: Pointer to pci_dev structure + * @id: PCI device ID information * * This routine performs all the steps necessary to bring the IOC of * a MPT adapter to a OPERATIONAL state. This includes registering @@ -1417,10 +1428,9 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* +/** * mpt_detach - Remove a PCI intelligent MPT adapter. * @pdev: Pointer to pci_dev structure - * */ void @@ -1466,10 +1476,10 @@ mpt_detach(struct pci_dev *pdev) */ #ifdef CONFIG_PM /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* +/** * mpt_suspend - Fusion MPT base driver suspend routine. - * - * + * @pdev: Pointer to pci_dev structure + * @state: new state to enter */ int mpt_suspend(struct pci_dev *pdev, pm_message_t state) @@ -1505,10 +1515,9 @@ mpt_suspend(struct pci_dev *pdev, pm_message_t state) } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* +/** * mpt_resume - Fusion MPT base driver resume routine. - * - * + * @pdev: Pointer to pci_dev structure */ int mpt_resume(struct pci_dev *pdev) @@ -1566,7 +1575,7 @@ mpt_signal_reset(int index, MPT_ADAPTER *ioc, int reset_phase) } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* +/** * mpt_do_ioc_recovery - Initialize or recover MPT adapter. * @ioc: Pointer to MPT adapter structure * @reason: Event word / reason @@ -1892,13 +1901,15 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * mpt_detect_bound_ports - Search for PCI bus/dev_function - * which matches PCI bus/dev_function (+/-1) for newly discovered 929, - * 929X, 1030 or 1035. +/** + * mpt_detect_bound_ports - Search for matching PCI bus/dev_function * @ioc: Pointer to MPT adapter structure * @pdev: Pointer to (struct pci_dev) structure * + * Search for PCI bus/dev_function which matches + * PCI bus/dev_function (+/-1) for newly discovered 929, + * 929X, 1030 or 1035. + * * If match on PCI dev_function +/-1 is found, bind the two MPT adapters * using alt_ioc pointer fields in their %MPT_ADAPTER structures. */ @@ -1945,9 +1956,9 @@ mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev) } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* +/** * mpt_adapter_disable - Disable misbehaving MPT adapter. - * @this: Pointer to MPT adapter structure + * @ioc: Pointer to MPT adapter structure */ static void mpt_adapter_disable(MPT_ADAPTER *ioc) @@ -2046,9 +2057,8 @@ mpt_adapter_disable(MPT_ADAPTER *ioc) } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * mpt_adapter_dispose - Free all resources associated with a MPT - * adapter. +/** + * mpt_adapter_dispose - Free all resources associated with an MPT adapter * @ioc: Pointer to MPT adapter structure * * This routine unregisters h/w resources and frees all alloc'd memory @@ -2099,8 +2109,8 @@ mpt_adapter_dispose(MPT_ADAPTER *ioc) } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * MptDisplayIocCapabilities - Disply IOC's capacilities. +/** + * MptDisplayIocCapabilities - Disply IOC's capabilities. * @ioc: Pointer to MPT adapter structure */ static void @@ -2142,7 +2152,7 @@ MptDisplayIocCapabilities(MPT_ADAPTER *ioc) } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* +/** * MakeIocReady - Get IOC to a READY state, using KickStart if needed. * @ioc: Pointer to MPT_ADAPTER structure * @force: Force hard KickStart of IOC @@ -2279,7 +2289,7 @@ MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag) } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* +/** * mpt_GetIocState - Get the current state of a MPT adapter. * @ioc: Pointer to MPT_ADAPTER structure * @cooked: Request raw or cooked IOC state @@ -2304,7 +2314,7 @@ mpt_GetIocState(MPT_ADAPTER *ioc, int cooked) } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* +/** * GetIocFacts - Send IOCFacts request to MPT adapter. * @ioc: Pointer to MPT_ADAPTER structure * @sleepFlag: Specifies whether the process can sleep @@ -2478,7 +2488,7 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason) } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* +/** * GetPortFacts - Send PortFacts request to MPT adapter. * @ioc: Pointer to MPT_ADAPTER structure * @portnum: Port number @@ -2545,7 +2555,7 @@ GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag) } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* +/** * SendIocInit - Send IOCInit request to MPT adapter. * @ioc: Pointer to MPT_ADAPTER structure * @sleepFlag: Specifies whether the process can sleep @@ -2630,7 +2640,7 @@ SendIocInit(MPT_ADAPTER *ioc, int sleepFlag) } /* No need to byte swap the multibyte fields in the reply - * since we don't even look at it's contents. + * since we don't even look at its contents. */ dhsprintk((MYIOC_s_INFO_FMT "Sending PortEnable (req @ %p)\n", @@ -2672,7 +2682,7 @@ SendIocInit(MPT_ADAPTER *ioc, int sleepFlag) } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* +/** * SendPortEnable - Send PortEnable request to MPT adapter port. * @ioc: Pointer to MPT_ADAPTER structure * @portnum: Port number to enable @@ -2723,9 +2733,13 @@ SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag) return rc; } -/* - * ioc: Pointer to MPT_ADAPTER structure - * size - total FW bytes +/** + * mpt_alloc_fw_memory - allocate firmware memory + * @ioc: Pointer to MPT_ADAPTER structure + * @size: total FW bytes + * + * If memory has already been allocated, the same (cached) value + * is returned. */ void mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size) @@ -2742,9 +2756,12 @@ mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size) ioc->alloc_total += size; } } -/* - * If alt_img is NULL, delete from ioc structure. - * Else, delete a secondary image in same format. +/** + * mpt_free_fw_memory - free firmware memory + * @ioc: Pointer to MPT_ADAPTER structure + * + * If alt_img is NULL, delete from ioc structure. + * Else, delete a secondary image in same format. */ void mpt_free_fw_memory(MPT_ADAPTER *ioc) @@ -2763,7 +2780,7 @@ mpt_free_fw_memory(MPT_ADAPTER *ioc) /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* +/** * mpt_do_upload - Construct and Send FWUpload request to MPT adapter port. * @ioc: Pointer to MPT_ADAPTER structure * @sleepFlag: Specifies whether the process can sleep @@ -2865,10 +2882,10 @@ mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag) } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* +/** * mpt_downloadboot - DownloadBoot code * @ioc: Pointer to MPT_ADAPTER structure - * @flag: Specify which part of IOC memory is to be uploaded. + * @pFwHeader: Pointer to firmware header info * @sleepFlag: Specifies whether the process can sleep * * FwDownloadBoot requires Programmed IO access. @@ -3071,7 +3088,7 @@ mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag) } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* +/** * KickStart - Perform hard reset of MPT adapter. * @ioc: Pointer to MPT_ADAPTER structure * @force: Force hard reset @@ -3145,12 +3162,12 @@ KickStart(MPT_ADAPTER *ioc, int force, int sleepFlag) } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* +/** * mpt_diag_reset - Perform hard reset of the adapter. * @ioc: Pointer to MPT_ADAPTER structure * @ignore: Set if to honor and clear to ignore * the reset history bit - * @sleepflag: CAN_SLEEP if called in a non-interrupt thread, + * @sleepFlag: CAN_SLEEP if called in a non-interrupt thread, * else set to NO_SLEEP (use mdelay instead) * * This routine places the adapter in diagnostic mode via the @@ -3436,11 +3453,12 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag) } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* +/** * SendIocReset - Send IOCReset request to MPT adapter. * @ioc: Pointer to MPT_ADAPTER structure * @reset_type: reset type, expected values are * %MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET or %MPI_FUNCTION_IO_UNIT_RESET + * @sleepFlag: Specifies whether the process can sleep * * Send IOCReset request to the MPT adapter. * @@ -3494,11 +3512,12 @@ SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag) } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * initChainBuffers - Allocate memory for and initialize - * chain buffers, chain buffer control arrays and spinlock. - * @hd: Pointer to MPT_SCSI_HOST structure - * @init: If set, initialize the spin lock. +/** + * initChainBuffers - Allocate memory for and initialize chain buffers + * @ioc: Pointer to MPT_ADAPTER structure + * + * Allocates memory for and initializes chain buffers, + * chain buffer control arrays and spinlock. */ static int initChainBuffers(MPT_ADAPTER *ioc) @@ -3594,7 +3613,7 @@ initChainBuffers(MPT_ADAPTER *ioc) } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* +/** * PrimeIocFifos - Initialize IOC request and reply FIFOs. * @ioc: Pointer to MPT_ADAPTER structure * @@ -3891,15 +3910,15 @@ mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, u32 *req, } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * WaitForDoorbellAck - Wait for IOC to clear the IOP_DOORBELL_STATUS bit - * in it's IntStatus register. +/** + * WaitForDoorbellAck - Wait for IOC doorbell handshake acknowledge * @ioc: Pointer to MPT_ADAPTER structure * @howlong: How long to wait (in seconds) * @sleepFlag: Specifies whether the process can sleep * * This routine waits (up to ~2 seconds max) for IOC doorbell - * handshake ACKnowledge. + * handshake ACKnowledge, indicated by the IOP_DOORBELL_STATUS + * bit in its IntStatus register being clear. * * Returns a negative value on failure, else wait loop count. */ @@ -3942,14 +3961,14 @@ WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag) } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * WaitForDoorbellInt - Wait for IOC to set the HIS_DOORBELL_INTERRUPT bit - * in it's IntStatus register. +/** + * WaitForDoorbellInt - Wait for IOC to set its doorbell interrupt bit * @ioc: Pointer to MPT_ADAPTER structure * @howlong: How long to wait (in seconds) * @sleepFlag: Specifies whether the process can sleep * - * This routine waits (up to ~2 seconds max) for IOC doorbell interrupt. + * This routine waits (up to ~2 seconds max) for IOC doorbell interrupt + * (MPI_HIS_DOORBELL_INTERRUPT) to be set in the IntStatus register. * * Returns a negative value on failure, else wait loop count. */ @@ -3991,8 +4010,8 @@ WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag) } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * WaitForDoorbellReply - Wait for and capture a IOC handshake reply. +/** + * WaitForDoorbellReply - Wait for and capture an IOC handshake reply. * @ioc: Pointer to MPT_ADAPTER structure * @howlong: How long to wait (in seconds) * @sleepFlag: Specifies whether the process can sleep @@ -4077,7 +4096,7 @@ WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag) } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* +/** * GetLanConfigPages - Fetch LANConfig pages. * @ioc: Pointer to MPT_ADAPTER structure * @@ -4188,12 +4207,9 @@ GetLanConfigPages(MPT_ADAPTER *ioc) } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * mptbase_sas_persist_operation - Perform operation on SAS Persitent Table +/** + * mptbase_sas_persist_operation - Perform operation on SAS Persistent Table * @ioc: Pointer to MPT_ADAPTER structure - * @sas_address: 64bit SAS Address for operation. - * @target_id: specified target for operation - * @bus: specified bus for operation * @persist_opcode: see below * * MPI_SAS_OP_CLEAR_NOT_PRESENT - Free all persist TargetID mappings for @@ -4202,7 +4218,7 @@ GetLanConfigPages(MPT_ADAPTER *ioc) * * NOTE: Don't use not this function during interrupt time. * - * Returns: 0 for success, non-zero error + * Returns 0 for success, non-zero error */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -4399,7 +4415,7 @@ mptbase_raid_process_event_data(MPT_ADAPTER *ioc, } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* +/** * GetIoUnitPage2 - Retrieve BIOS version and boot order information. * @ioc: Pointer to MPT_ADAPTER structure * @@ -4457,7 +4473,8 @@ GetIoUnitPage2(MPT_ADAPTER *ioc) } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* mpt_GetScsiPortSettings - read SCSI Port Page 0 and 2 +/** + * mpt_GetScsiPortSettings - read SCSI Port Page 0 and 2 * @ioc: Pointer to a Adapter Strucutre * @portnum: IOC port number * @@ -4644,7 +4661,8 @@ mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum) } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* mpt_readScsiDevicePageHeaders - save version and length of SDP1 +/** + * mpt_readScsiDevicePageHeaders - save version and length of SDP1 * @ioc: Pointer to a Adapter Strucutre * @portnum: IOC port number * @@ -4996,9 +5014,8 @@ mpt_read_ioc_pg_1(MPT_ADAPTER *ioc) } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * SendEventNotification - Send EventNotification (on or off) request - * to MPT adapter. +/** + * SendEventNotification - Send EventNotification (on or off) request to adapter * @ioc: Pointer to MPT_ADAPTER structure * @EvSwitch: Event switch flags */ @@ -5062,8 +5079,8 @@ SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp) /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mpt_config - Generic function to issue config message - * @ioc - Pointer to an adapter structure - * @cfg - Pointer to a configuration structure. Struct contains + * @ioc: Pointer to an adapter structure + * @pCfg: Pointer to a configuration structure. Struct contains * action, page address, direction, physical address * and pointer to a configuration page header * Page header is updated. @@ -5188,8 +5205,8 @@ mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg) } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * mpt_timer_expired - Call back for timer process. +/** + * mpt_timer_expired - Callback for timer process. * Used only internal config functionality. * @data: Pointer to MPT_SCSI_HOST recast as an unsigned long */ @@ -5214,12 +5231,12 @@ mpt_timer_expired(unsigned long data) } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* +/** * mpt_ioc_reset - Base cleanup for hard reset * @ioc: Pointer to the adapter structure * @reset_phase: Indicates pre- or post-reset functionality * - * Remark: Free's resources with internally generated commands. + * Remark: Frees resources with internally generated commands. */ static int mpt_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) @@ -5271,7 +5288,7 @@ mpt_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) * procfs (%MPT_PROCFS_MPTBASEDIR/...) support stuff... */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* +/** * procmpt_create - Create %MPT_PROCFS_MPTBASEDIR entries. * * Returns 0 for success, non-zero for failure. @@ -5297,7 +5314,7 @@ procmpt_create(void) } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* +/** * procmpt_destroy - Tear down %MPT_PROCFS_MPTBASEDIR entries. * * Returns 0 for success, non-zero for failure. @@ -5311,16 +5328,16 @@ procmpt_destroy(void) } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * procmpt_summary_read - Handle read request from /proc/mpt/summary - * or from /proc/mpt/iocN/summary. +/** + * procmpt_summary_read - Handle read request of a summary file * @buf: Pointer to area to write information * @start: Pointer to start pointer * @offset: Offset to start writing - * @request: + * @request: Amount of read data requested * @eof: Pointer to EOF integer * @data: Pointer * + * Handles read request from /proc/mpt/summary or /proc/mpt/iocN/summary. * Returns number of characters written to process performing the read. */ static int @@ -5355,12 +5372,12 @@ procmpt_summary_read(char *buf, char **start, off_t offset, int request, int *eo } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* +/** * procmpt_version_read - Handle read request from /proc/mpt/version. * @buf: Pointer to area to write information * @start: Pointer to start pointer * @offset: Offset to start writing - * @request: + * @request: Amount of read data requested * @eof: Pointer to EOF integer * @data: Pointer * @@ -5411,12 +5428,12 @@ procmpt_version_read(char *buf, char **start, off_t offset, int request, int *eo } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* +/** * procmpt_iocinfo_read - Handle read request from /proc/mpt/iocN/info. * @buf: Pointer to area to write information * @start: Pointer to start pointer * @offset: Offset to start writing - * @request: + * @request: Amount of read data requested * @eof: Pointer to EOF integer * @data: Pointer * @@ -5577,16 +5594,17 @@ mpt_print_ioc_summary(MPT_ADAPTER *ioc, char *buffer, int *size, int len, int sh */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** - * mpt_HardResetHandler - Generic reset handler, issue SCSI Task - * Management call based on input arg values. If TaskMgmt fails, - * return associated SCSI request. + * mpt_HardResetHandler - Generic reset handler * @ioc: Pointer to MPT_ADAPTER structure * @sleepFlag: Indicates if sleep or schedule must be called. * + * Issues SCSI Task Management call based on input arg values. + * If TaskMgmt fails, returns associated SCSI request. + * * Remark: _HardResetHandler can be invoked from an interrupt thread (timer) * or a non-interrupt thread. In the former, must not call schedule(). * - * Remark: A return of -1 is a FATAL error case, as it means a + * Note: A return of -1 is a FATAL error case, as it means a * FW reload/initialization failed. * * Returns 0 for SUCCESS or -1 if FAILED. @@ -5935,13 +5953,14 @@ EventDescriptionStr(u8 event, u32 evData0, char *evStr) } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * ProcessEventNotification - Route a received EventNotificationReply to - * all currently regeistered event handlers. +/** + * ProcessEventNotification - Route EventNotificationReply to all event handlers * @ioc: Pointer to MPT_ADAPTER structure * @pEventReply: Pointer to EventNotification reply frame * @evHandlers: Pointer to integer, number of event handlers * + * Routes a received EventNotificationReply to all currently registered + * event handlers. * Returns sum of event handlers return values. */ static int @@ -6056,7 +6075,7 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* +/** * mpt_fc_log_info - Log information returned from Fibre Channel IOC. * @ioc: Pointer to MPT_ADAPTER structure * @log_info: U32 LogInfo reply word from the IOC @@ -6077,7 +6096,7 @@ mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info) } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* +/** * mpt_spi_log_info - Log information returned from SCSI Parallel IOC. * @ioc: Pointer to MPT_ADAPTER structure * @mr: Pointer to MPT reply frame @@ -6200,7 +6219,7 @@ mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info) }; /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* +/** * mpt_sas_log_info - Log information returned from SAS IOC. * @ioc: Pointer to MPT_ADAPTER structure * @log_info: U32 LogInfo reply word from the IOC @@ -6255,7 +6274,7 @@ union loginfo_type { } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* +/** * mpt_sp_ioc_info - IOC information returned from SCSI Parallel IOC. * @ioc: Pointer to MPT_ADAPTER structure * @ioc_status: U32 IOCStatus word from IOC @@ -6416,7 +6435,7 @@ EXPORT_SYMBOL(mpt_free_fw_memory); EXPORT_SYMBOL(mptbase_sas_persist_operation); /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* +/** * fusion_init - Fusion MPT base driver initialization routine. * * Returns 0 for success, non-zero for failure. @@ -6456,7 +6475,7 @@ fusion_init(void) } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* +/** * fusion_exit - Perform driver unload cleanup. * * This routine frees all resources associated with each MPT adapter diff --git a/trunk/drivers/message/fusion/mptfc.c b/trunk/drivers/message/fusion/mptfc.c index 1dd491773150..ca2f9107f145 100644 --- a/trunk/drivers/message/fusion/mptfc.c +++ b/trunk/drivers/message/fusion/mptfc.c @@ -1018,9 +1018,10 @@ mptfc_init_host_attr(MPT_ADAPTER *ioc,int portnum) } static void -mptfc_setup_reset(void *arg) +mptfc_setup_reset(struct work_struct *work) { - MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg; + MPT_ADAPTER *ioc = + container_of(work, MPT_ADAPTER, fc_setup_reset_work); u64 pn; struct mptfc_rport_info *ri; @@ -1043,9 +1044,10 @@ mptfc_setup_reset(void *arg) } static void -mptfc_rescan_devices(void *arg) +mptfc_rescan_devices(struct work_struct *work) { - MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg; + MPT_ADAPTER *ioc = + container_of(work, MPT_ADAPTER, fc_rescan_work); int ii; u64 pn; struct mptfc_rport_info *ri; @@ -1154,8 +1156,8 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id) } spin_lock_init(&ioc->fc_rescan_work_lock); - INIT_WORK(&ioc->fc_rescan_work, mptfc_rescan_devices,(void *)ioc); - INIT_WORK(&ioc->fc_setup_reset_work, mptfc_setup_reset, (void *)ioc); + INIT_WORK(&ioc->fc_rescan_work, mptfc_rescan_devices); + INIT_WORK(&ioc->fc_setup_reset_work, mptfc_setup_reset); spin_lock_irqsave(&ioc->FreeQlock, flags); @@ -1393,8 +1395,7 @@ mptfc_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** - * mptfc_init - Register MPT adapter(s) as SCSI host(s) with - * linux scsi mid-layer. + * mptfc_init - Register MPT adapter(s) as SCSI host(s) with SCSI mid-layer. * * Returns 0 for success, non-zero for failure. */ @@ -1438,7 +1439,7 @@ mptfc_init(void) /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** - * mptfc_remove - Removed fc infrastructure for devices + * mptfc_remove - Remove fc infrastructure for devices * @pdev: Pointer to pci_dev structure * */ diff --git a/trunk/drivers/message/fusion/mptlan.c b/trunk/drivers/message/fusion/mptlan.c index 314c3a27585d..b7c4407c5e3f 100644 --- a/trunk/drivers/message/fusion/mptlan.c +++ b/trunk/drivers/message/fusion/mptlan.c @@ -111,7 +111,8 @@ struct mpt_lan_priv { u32 total_received; struct net_device_stats stats; /* Per device statistics */ - struct work_struct post_buckets_task; + struct delayed_work post_buckets_task; + struct net_device *dev; unsigned long post_buckets_active; }; @@ -132,7 +133,7 @@ static int lan_reply (MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, static int mpt_lan_open(struct net_device *dev); static int mpt_lan_reset(struct net_device *dev); static int mpt_lan_close(struct net_device *dev); -static void mpt_lan_post_receive_buckets(void *dev_id); +static void mpt_lan_post_receive_buckets(struct mpt_lan_priv *priv); static void mpt_lan_wake_post_buckets_task(struct net_device *dev, int priority); static int mpt_lan_receive_post_turbo(struct net_device *dev, u32 tmsg); @@ -345,7 +346,7 @@ mpt_lan_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) priv->mpt_rxfidx[++priv->mpt_rxfidx_tail] = i; spin_unlock_irqrestore(&priv->rxfidx_lock, flags); } else { - mpt_lan_post_receive_buckets(dev); + mpt_lan_post_receive_buckets(priv); netif_wake_queue(dev); } @@ -441,7 +442,7 @@ mpt_lan_open(struct net_device *dev) dlprintk((KERN_INFO MYNAM "/lo: Finished initializing RcvCtl\n")); - mpt_lan_post_receive_buckets(dev); + mpt_lan_post_receive_buckets(priv); printk(KERN_INFO MYNAM ": %s/%s: interface up & active\n", IOC_AND_NETDEV_NAMES_s_s(dev)); @@ -854,7 +855,7 @@ mpt_lan_wake_post_buckets_task(struct net_device *dev, int priority) if (test_and_set_bit(0, &priv->post_buckets_active) == 0) { if (priority) { - schedule_work(&priv->post_buckets_task); + schedule_delayed_work(&priv->post_buckets_task, 0); } else { schedule_delayed_work(&priv->post_buckets_task, 1); dioprintk((KERN_INFO MYNAM ": post_buckets queued on " @@ -1188,10 +1189,9 @@ mpt_lan_receive_post_reply(struct net_device *dev, /* Simple SGE's only at the moment */ static void -mpt_lan_post_receive_buckets(void *dev_id) +mpt_lan_post_receive_buckets(struct mpt_lan_priv *priv) { - struct net_device *dev = dev_id; - struct mpt_lan_priv *priv = dev->priv; + struct net_device *dev = priv->dev; MPT_ADAPTER *mpt_dev = priv->mpt_dev; MPT_FRAME_HDR *mf; LANReceivePostRequest_t *pRecvReq; @@ -1335,6 +1335,13 @@ mpt_lan_post_receive_buckets(void *dev_id) clear_bit(0, &priv->post_buckets_active); } +static void +mpt_lan_post_receive_buckets_work(struct work_struct *work) +{ + mpt_lan_post_receive_buckets(container_of(work, struct mpt_lan_priv, + post_buckets_task.work)); +} + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ static struct net_device * mpt_register_lan_device (MPT_ADAPTER *mpt_dev, int pnum) @@ -1350,11 +1357,13 @@ mpt_register_lan_device (MPT_ADAPTER *mpt_dev, int pnum) priv = netdev_priv(dev); + priv->dev = dev; priv->mpt_dev = mpt_dev; priv->pnum = pnum; - memset(&priv->post_buckets_task, 0, sizeof(struct work_struct)); - INIT_WORK(&priv->post_buckets_task, mpt_lan_post_receive_buckets, dev); + memset(&priv->post_buckets_task, 0, sizeof(priv->post_buckets_task)); + INIT_DELAYED_WORK(&priv->post_buckets_task, + mpt_lan_post_receive_buckets_work); priv->post_buckets_active = 0; dlprintk((KERN_INFO MYNAM "@%d: bucketlen = %d\n", diff --git a/trunk/drivers/message/fusion/mptsas.c b/trunk/drivers/message/fusion/mptsas.c index b752a479f6db..4f0c530e47b0 100644 --- a/trunk/drivers/message/fusion/mptsas.c +++ b/trunk/drivers/message/fusion/mptsas.c @@ -2006,9 +2006,10 @@ __mptsas_discovery_work(MPT_ADAPTER *ioc) *(Mutex LOCKED) */ static void -mptsas_discovery_work(void * arg) +mptsas_discovery_work(struct work_struct *work) { - struct mptsas_discovery_event *ev = arg; + struct mptsas_discovery_event *ev = + container_of(work, struct mptsas_discovery_event, work); MPT_ADAPTER *ioc = ev->ioc; mutex_lock(&ioc->sas_discovery_mutex); @@ -2068,9 +2069,9 @@ mptsas_find_phyinfo_by_target(MPT_ADAPTER *ioc, u32 id) * Work queue thread to clear the persitency table */ static void -mptsas_persist_clear_table(void * arg) +mptsas_persist_clear_table(struct work_struct *work) { - MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg; + MPT_ADAPTER *ioc = container_of(work, MPT_ADAPTER, sas_persist_task); mptbase_sas_persist_operation(ioc, MPI_SAS_OP_CLEAR_NOT_PRESENT); } @@ -2093,9 +2094,10 @@ mptsas_reprobe_target(struct scsi_target *starget, int uld_attach) * Work queue thread to handle SAS hotplug events */ static void -mptsas_hotplug_work(void *arg) +mptsas_hotplug_work(struct work_struct *work) { - struct mptsas_hotplug_event *ev = arg; + struct mptsas_hotplug_event *ev = + container_of(work, struct mptsas_hotplug_event, work); MPT_ADAPTER *ioc = ev->ioc; struct mptsas_phyinfo *phy_info; struct sas_rphy *rphy; @@ -2341,7 +2343,7 @@ mptsas_send_sas_event(MPT_ADAPTER *ioc, break; } - INIT_WORK(&ev->work, mptsas_hotplug_work, ev); + INIT_WORK(&ev->work, mptsas_hotplug_work); ev->ioc = ioc; ev->handle = le16_to_cpu(sas_event_data->DevHandle); ev->parent_handle = @@ -2366,7 +2368,7 @@ mptsas_send_sas_event(MPT_ADAPTER *ioc, * Persistent table is full. */ INIT_WORK(&ioc->sas_persist_task, - mptsas_persist_clear_table, (void *)ioc); + mptsas_persist_clear_table); schedule_work(&ioc->sas_persist_task); break; case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA: @@ -2395,7 +2397,7 @@ mptsas_send_raid_event(MPT_ADAPTER *ioc, return; } - INIT_WORK(&ev->work, mptsas_hotplug_work, ev); + INIT_WORK(&ev->work, mptsas_hotplug_work); ev->ioc = ioc; ev->id = raid_event_data->VolumeID; ev->event_type = MPTSAS_IGNORE_EVENT; @@ -2474,7 +2476,7 @@ mptsas_send_discovery_event(MPT_ADAPTER *ioc, ev = kzalloc(sizeof(*ev), GFP_ATOMIC); if (!ev) return; - INIT_WORK(&ev->work, mptsas_discovery_work, ev); + INIT_WORK(&ev->work, mptsas_discovery_work); ev->ioc = ioc; schedule_work(&ev->work); }; @@ -2511,8 +2513,7 @@ mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply) break; case MPI_EVENT_PERSISTENT_TABLE_FULL: INIT_WORK(&ioc->sas_persist_task, - mptsas_persist_clear_table, - (void *)ioc); + mptsas_persist_clear_table); schedule_work(&ioc->sas_persist_task); break; case MPI_EVENT_SAS_DISCOVERY: diff --git a/trunk/drivers/message/fusion/mptscsih.c b/trunk/drivers/message/fusion/mptscsih.c index 30524dc54b16..2c72c36b8171 100644 --- a/trunk/drivers/message/fusion/mptscsih.c +++ b/trunk/drivers/message/fusion/mptscsih.c @@ -1230,15 +1230,15 @@ mptscsih_host_info(MPT_ADAPTER *ioc, char *pbuf, off_t offset, int len) /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mptscsih_proc_info - Return information about MPT adapter + * @host: scsi host struct + * @buffer: if write, user data; if read, buffer for user + * @start: returns the buffer address + * @offset: if write, 0; if read, the current offset into the buffer from + * the previous read. + * @length: if write, return length; + * @func: write = 1; read = 0 * * (linux scsi_host_template.info routine) - * - * buffer: if write, user data; if read, buffer for user - * length: if write, return length; - * offset: if write, 0; if read, the current offset into the buffer from - * the previous read. - * hostno: scsi host number - * func: if write = 1; if read = 0 */ int mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset, @@ -1902,8 +1902,7 @@ mptscsih_bus_reset(struct scsi_cmnd * SCpnt) /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** - * mptscsih_host_reset - Perform a SCSI host adapter RESET! - * new_eh variant + * mptscsih_host_reset - Perform a SCSI host adapter RESET (new_eh variant) * @SCpnt: Pointer to scsi_cmnd structure, IO which reset is due to * * (linux scsi_host_template.eh_host_reset_handler routine) @@ -1949,8 +1948,7 @@ mptscsih_host_reset(struct scsi_cmnd *SCpnt) /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** - * mptscsih_tm_pending_wait - wait for pending task management request to - * complete. + * mptscsih_tm_pending_wait - wait for pending task management request to complete * @hd: Pointer to MPT host structure. * * Returns {SUCCESS,FAILED}. @@ -1982,6 +1980,7 @@ mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd) /** * mptscsih_tm_wait_for_completion - wait for completion of TM task * @hd: Pointer to MPT host structure. + * @timeout: timeout in seconds * * Returns {SUCCESS,FAILED}. */ @@ -3429,8 +3428,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) /** * mptscsih_synchronize_cache - Send SYNCHRONIZE_CACHE to all disks. * @hd: Pointer to a SCSI HOST structure - * @vtarget: per device private data - * @lun: lun + * @vdevice: virtual target device * * Uses the ISR, but with special processing. * MUST be single-threaded. diff --git a/trunk/drivers/message/fusion/mptspi.c b/trunk/drivers/message/fusion/mptspi.c index e4cc3dd5fc9f..36641da59289 100644 --- a/trunk/drivers/message/fusion/mptspi.c +++ b/trunk/drivers/message/fusion/mptspi.c @@ -646,9 +646,10 @@ struct work_queue_wrapper { int disk; }; -static void mpt_work_wrapper(void *data) +static void mpt_work_wrapper(struct work_struct *work) { - struct work_queue_wrapper *wqw = (struct work_queue_wrapper *)data; + struct work_queue_wrapper *wqw = + container_of(work, struct work_queue_wrapper, work); struct _MPT_SCSI_HOST *hd = wqw->hd; struct Scsi_Host *shost = hd->ioc->sh; struct scsi_device *sdev; @@ -695,7 +696,7 @@ static void mpt_dv_raid(struct _MPT_SCSI_HOST *hd, int disk) disk); return; } - INIT_WORK(&wqw->work, mpt_work_wrapper, wqw); + INIT_WORK(&wqw->work, mpt_work_wrapper); wqw->hd = hd; wqw->disk = disk; @@ -784,9 +785,10 @@ MODULE_DEVICE_TABLE(pci, mptspi_pci_table); * renegotiate for a given target */ static void -mptspi_dv_renegotiate_work(void *data) +mptspi_dv_renegotiate_work(struct work_struct *work) { - struct work_queue_wrapper *wqw = (struct work_queue_wrapper *)data; + struct work_queue_wrapper *wqw = + container_of(work, struct work_queue_wrapper, work); struct _MPT_SCSI_HOST *hd = wqw->hd; struct scsi_device *sdev; @@ -804,7 +806,7 @@ mptspi_dv_renegotiate(struct _MPT_SCSI_HOST *hd) if (!wqw) return; - INIT_WORK(&wqw->work, mptspi_dv_renegotiate_work, wqw); + INIT_WORK(&wqw->work, mptspi_dv_renegotiate_work); wqw->hd = hd; schedule_work(&wqw->work); @@ -1098,8 +1100,7 @@ static struct pci_driver mptspi_driver = { /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** - * mptspi_init - Register MPT adapter(s) as SCSI host(s) with - * linux scsi mid-layer. + * mptspi_init - Register MPT adapter(s) as SCSI host(s) with SCSI mid-layer. * * Returns 0 for success, non-zero for failure. */ @@ -1133,7 +1134,6 @@ mptspi_init(void) /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mptspi_exit - Unregisters MPT adapter(s) - * */ static void __exit mptspi_exit(void) diff --git a/trunk/drivers/message/i2o/bus-osm.c b/trunk/drivers/message/i2o/bus-osm.c index d96c687aee93..c463dc2efc09 100644 --- a/trunk/drivers/message/i2o/bus-osm.c +++ b/trunk/drivers/message/i2o/bus-osm.c @@ -56,6 +56,9 @@ static int i2o_bus_scan(struct i2o_device *dev) /** * i2o_bus_store_scan - Scan the I2O Bus Adapter * @d: device which should be scanned + * @attr: device_attribute + * @buf: output buffer + * @count: buffer size * * Returns count. */ diff --git a/trunk/drivers/message/i2o/device.c b/trunk/drivers/message/i2o/device.c index ee183053fa23..b9df143e4ff1 100644 --- a/trunk/drivers/message/i2o/device.c +++ b/trunk/drivers/message/i2o/device.c @@ -54,8 +54,8 @@ static inline int i2o_device_issue_claim(struct i2o_device *dev, u32 cmd, * @dev: I2O device to claim * @drv: I2O driver which wants to claim the device * - * Do the leg work to assign a device to a given OSM. If the claim succeed - * the owner of the rimary. If the attempt fails a negative errno code + * Do the leg work to assign a device to a given OSM. If the claim succeeds, + * the owner is the primary. If the attempt fails a negative errno code * is returned. On success zero is returned. */ int i2o_device_claim(struct i2o_device *dev) @@ -208,24 +208,23 @@ static struct i2o_device *i2o_device_alloc(void) /** * i2o_device_add - allocate a new I2O device and add it to the IOP - * @iop: I2O controller where the device is on + * @c: I2O controller that the device is on * @entry: LCT entry of the I2O device * * Allocate a new I2O device and initialize it with the LCT entry. The * device is appended to the device list of the controller. * - * Returns a pointer to the I2O device on success or negative error code - * on failure. + * Returns zero on success, or a -ve errno. */ -static struct i2o_device *i2o_device_add(struct i2o_controller *c, - i2o_lct_entry * entry) +static int i2o_device_add(struct i2o_controller *c, i2o_lct_entry *entry) { struct i2o_device *i2o_dev, *tmp; + int rc; i2o_dev = i2o_device_alloc(); if (IS_ERR(i2o_dev)) { printk(KERN_ERR "i2o: unable to allocate i2o device\n"); - return i2o_dev; + return PTR_ERR(i2o_dev); } i2o_dev->lct_data = *entry; @@ -236,7 +235,9 @@ static struct i2o_device *i2o_device_add(struct i2o_controller *c, i2o_dev->iop = c; i2o_dev->device.parent = &c->device; - device_register(&i2o_dev->device); + rc = device_register(&i2o_dev->device); + if (rc) + goto err; list_add_tail(&i2o_dev->list, &c->devices); @@ -270,12 +271,16 @@ static struct i2o_device *i2o_device_add(struct i2o_controller *c, pr_debug("i2o: device %s added\n", i2o_dev->device.bus_id); - return i2o_dev; + return 0; + +err: + kfree(i2o_dev); + return rc; } /** * i2o_device_remove - remove an I2O device from the I2O core - * @dev: I2O device which should be released + * @i2o_dev: I2O device which should be released * * Is used on I2O controller removal or LCT modification, when the device * is removed from the system. Note that the device could still hang diff --git a/trunk/drivers/message/i2o/driver.c b/trunk/drivers/message/i2o/driver.c index 64130227574f..9104b65ff70f 100644 --- a/trunk/drivers/message/i2o/driver.c +++ b/trunk/drivers/message/i2o/driver.c @@ -34,9 +34,7 @@ static spinlock_t i2o_drivers_lock; static struct i2o_driver **i2o_drivers; /** - * i2o_bus_match - Tell if a I2O device class id match the class ids of - * the I2O driver (OSM) - * + * i2o_bus_match - Tell if I2O device class id matches the class ids of the I2O driver (OSM) * @dev: device which should be verified * @drv: the driver to match against * @@ -232,7 +230,7 @@ int i2o_driver_dispatch(struct i2o_controller *c, u32 m) break; } - INIT_WORK(&evt->work, (void (*)(void *))drv->event, evt); + INIT_WORK(&evt->work, drv->event); queue_work(drv->event_queue, &evt->work); return 1; } @@ -248,7 +246,7 @@ int i2o_driver_dispatch(struct i2o_controller *c, u32 m) /** * i2o_driver_notify_controller_add_all - Send notify of added controller - * to all I2O drivers + * @c: newly added controller * * Send notifications to all registered drivers that a new controller was * added. @@ -267,8 +265,8 @@ void i2o_driver_notify_controller_add_all(struct i2o_controller *c) } /** - * i2o_driver_notify_controller_remove_all - Send notify of removed - * controller to all I2O drivers + * i2o_driver_notify_controller_remove_all - Send notify of removed controller + * @c: controller that is being removed * * Send notifications to all registered drivers that a controller was * removed. @@ -287,8 +285,8 @@ void i2o_driver_notify_controller_remove_all(struct i2o_controller *c) } /** - * i2o_driver_notify_device_add_all - Send notify of added device to all - * I2O drivers + * i2o_driver_notify_device_add_all - Send notify of added device + * @i2o_dev: newly added I2O device * * Send notifications to all registered drivers that a device was added. */ @@ -306,8 +304,8 @@ void i2o_driver_notify_device_add_all(struct i2o_device *i2o_dev) } /** - * i2o_driver_notify_device_remove_all - Send notify of removed device to - * all I2O drivers + * i2o_driver_notify_device_remove_all - Send notify of removed device + * @i2o_dev: device that is being removed * * Send notifications to all registered drivers that a device was removed. */ @@ -362,7 +360,7 @@ int __init i2o_driver_init(void) /** * i2o_driver_exit - clean up I2O drivers (OSMs) * - * Unregisters the I2O bus and free driver array. + * Unregisters the I2O bus and frees driver array. */ void __exit i2o_driver_exit(void) { diff --git a/trunk/drivers/message/i2o/exec-osm.c b/trunk/drivers/message/i2o/exec-osm.c index a2350640384b..902753b2c661 100644 --- a/trunk/drivers/message/i2o/exec-osm.c +++ b/trunk/drivers/message/i2o/exec-osm.c @@ -94,8 +94,8 @@ static struct i2o_exec_wait *i2o_exec_wait_alloc(void) }; /** - * i2o_exec_wait_free - Free a i2o_exec_wait struct - * @i2o_exec_wait: I2O wait data which should be cleaned up + * i2o_exec_wait_free - Free an i2o_exec_wait struct + * @wait: I2O wait data which should be cleaned up */ static void i2o_exec_wait_free(struct i2o_exec_wait *wait) { @@ -105,7 +105,7 @@ static void i2o_exec_wait_free(struct i2o_exec_wait *wait) /** * i2o_msg_post_wait_mem - Post and wait a message with DMA buffers * @c: controller - * @m: message to post + * @msg: message to post * @timeout: time in seconds to wait * @dma: i2o_dma struct of the DMA buffer to free on failure * @@ -269,6 +269,7 @@ static int i2o_msg_post_wait_complete(struct i2o_controller *c, u32 m, /** * i2o_exec_show_vendor_id - Displays Vendor ID of controller * @d: device of which the Vendor ID should be displayed + * @attr: device_attribute to display * @buf: buffer into which the Vendor ID should be printed * * Returns number of bytes printed into buffer. @@ -290,6 +291,7 @@ static ssize_t i2o_exec_show_vendor_id(struct device *d, /** * i2o_exec_show_product_id - Displays Product ID of controller * @d: device of which the Product ID should be displayed + * @attr: device_attribute to display * @buf: buffer into which the Product ID should be printed * * Returns number of bytes printed into buffer. @@ -365,14 +367,16 @@ static int i2o_exec_remove(struct device *dev) /** * i2o_exec_lct_modified - Called on LCT NOTIFY reply - * @c: I2O controller on which the LCT has modified + * @work: work struct for a specific controller * * This function handles asynchronus LCT NOTIFY replies. It parses the * new LCT and if the buffer for the LCT was to small sends a LCT NOTIFY * again, otherwise send LCT NOTIFY to get informed on next LCT change. */ -static void i2o_exec_lct_modified(struct i2o_exec_lct_notify_work *work) +static void i2o_exec_lct_modified(struct work_struct *_work) { + struct i2o_exec_lct_notify_work *work = + container_of(_work, struct i2o_exec_lct_notify_work, work); u32 change_ind = 0; struct i2o_controller *c = work->c; @@ -439,8 +443,7 @@ static int i2o_exec_reply(struct i2o_controller *c, u32 m, work->c = c; - INIT_WORK(&work->work, (void (*)(void *))i2o_exec_lct_modified, - work); + INIT_WORK(&work->work, i2o_exec_lct_modified); queue_work(i2o_exec_driver.event_queue, &work->work); return 1; } @@ -460,13 +463,15 @@ static int i2o_exec_reply(struct i2o_controller *c, u32 m, /** * i2o_exec_event - Event handling function - * @evt: Event which occurs + * @work: Work item in occurring event * * Handles events send by the Executive device. At the moment does not do * anything useful. */ -static void i2o_exec_event(struct i2o_event *evt) +static void i2o_exec_event(struct work_struct *work) { + struct i2o_event *evt = container_of(work, struct i2o_event, work); + if (likely(evt->i2o_dev)) osm_debug("Event received from device: %d\n", evt->i2o_dev->lct_data.tid); diff --git a/trunk/drivers/message/i2o/i2o_block.c b/trunk/drivers/message/i2o/i2o_block.c index eaba81bf2eca..da9859f2caf2 100644 --- a/trunk/drivers/message/i2o/i2o_block.c +++ b/trunk/drivers/message/i2o/i2o_block.c @@ -259,7 +259,7 @@ static int i2o_block_device_unlock(struct i2o_device *dev, u32 media_id) /** * i2o_block_device_power - Power management for device dev * @dev: I2O device which should receive the power management request - * @operation: Operation which should be send + * @op: Operation to send * * Send a power management request to the device dev. * @@ -315,7 +315,7 @@ static inline struct i2o_block_request *i2o_block_request_alloc(void) * i2o_block_request_free - Frees a I2O block request * @ireq: I2O block request which should be freed * - * Fres the allocated memory (give it back to the request mempool). + * Frees the allocated memory (give it back to the request mempool). */ static inline void i2o_block_request_free(struct i2o_block_request *ireq) { @@ -326,6 +326,7 @@ static inline void i2o_block_request_free(struct i2o_block_request *ireq) * i2o_block_sglist_alloc - Allocate the SG list and map it * @c: I2O controller to which the request belongs * @ireq: I2O block request + * @mptr: message body pointer * * Builds the SG list and map it to be accessable by the controller. * @@ -419,16 +420,18 @@ static int i2o_block_prep_req_fn(struct request_queue *q, struct request *req) /** * i2o_block_delayed_request_fn - delayed request queue function - * delayed_request: the delayed request with the queue to start + * @work: the delayed request with the queue to start * * If the request queue is stopped for a disk, and there is no open * request, a new event is created, which calls this function to start * the queue after I2O_BLOCK_REQUEST_TIME. Otherwise the queue will never * be started again. */ -static void i2o_block_delayed_request_fn(void *delayed_request) +static void i2o_block_delayed_request_fn(struct work_struct *work) { - struct i2o_block_delayed_request *dreq = delayed_request; + struct i2o_block_delayed_request *dreq = + container_of(work, struct i2o_block_delayed_request, + work.work); struct request_queue *q = dreq->queue; unsigned long flags; @@ -488,7 +491,7 @@ static void i2o_block_end_request(struct request *req, int uptodate, * i2o_block_reply - Block OSM reply handler. * @c: I2O controller from which the message arrives * @m: message id of reply - * qmsg: the actuall I2O message reply + * @msg: the actual I2O message reply * * This function gets all the message replies. * @@ -538,8 +541,9 @@ static int i2o_block_reply(struct i2o_controller *c, u32 m, return 1; }; -static void i2o_block_event(struct i2o_event *evt) +static void i2o_block_event(struct work_struct *work) { + struct i2o_event *evt = container_of(work, struct i2o_event, work); osm_debug("event received\n"); kfree(evt); }; @@ -599,6 +603,8 @@ static void i2o_block_biosparam(unsigned long capacity, unsigned short *cyls, /** * i2o_block_open - Open the block device + * @inode: inode for block device being opened + * @file: file to open * * Power up the device, mount and lock the media. This function is called, * if the block device is opened for access. @@ -626,6 +632,8 @@ static int i2o_block_open(struct inode *inode, struct file *file) /** * i2o_block_release - Release the I2O block device + * @inode: inode for block device being released + * @file: file to close * * Unlock and unmount the media, and power down the device. Gets called if * the block device is closed. @@ -672,6 +680,8 @@ static int i2o_block_getgeo(struct block_device *bdev, struct hd_geometry *geo) /** * i2o_block_ioctl - Issue device specific ioctl calls. + * @inode: inode for block device ioctl + * @file: file for ioctl * @cmd: ioctl command * @arg: arg * @@ -899,7 +909,7 @@ static int i2o_block_transfer(struct request *req) /** * i2o_block_request_fn - request queue handling function - * q: request queue from which the request could be fetched + * @q: request queue from which the request could be fetched * * Takes the next request from the queue, transfers it and if no error * occurs dequeue it from the queue. On arrival of the reply the message @@ -938,8 +948,8 @@ static void i2o_block_request_fn(struct request_queue *q) continue; dreq->queue = q; - INIT_WORK(&dreq->work, i2o_block_delayed_request_fn, - dreq); + INIT_DELAYED_WORK(&dreq->work, + i2o_block_delayed_request_fn); if (!queue_delayed_work(i2o_block_driver.event_queue, &dreq->work, diff --git a/trunk/drivers/message/i2o/i2o_block.h b/trunk/drivers/message/i2o/i2o_block.h index 4fdaa5bda412..67f921b4419b 100644 --- a/trunk/drivers/message/i2o/i2o_block.h +++ b/trunk/drivers/message/i2o/i2o_block.h @@ -64,7 +64,7 @@ /* I2O Block OSM mempool struct */ struct i2o_block_mempool { - kmem_cache_t *slab; + struct kmem_cache *slab; mempool_t *pool; }; @@ -96,7 +96,7 @@ struct i2o_block_request { /* I2O Block device delayed request */ struct i2o_block_delayed_request { - struct work_struct work; + struct delayed_work work; struct request_queue *queue; }; diff --git a/trunk/drivers/message/i2o/i2o_config.c b/trunk/drivers/message/i2o/i2o_config.c index 7d23e082bf26..1de30d711671 100644 --- a/trunk/drivers/message/i2o/i2o_config.c +++ b/trunk/drivers/message/i2o/i2o_config.c @@ -265,7 +265,11 @@ static int i2o_cfg_swdl(unsigned long arg) return -ENOMEM; } - __copy_from_user(buffer.virt, kxfer.buf, fragsize); + if (__copy_from_user(buffer.virt, kxfer.buf, fragsize)) { + i2o_msg_nop(c, msg); + i2o_dma_free(&c->pdev->dev, &buffer); + return -EFAULT; + } msg->u.head[0] = cpu_to_le32(NINE_WORD_MSG_SIZE | SGL_OFFSET_7); msg->u.head[1] = @@ -516,7 +520,6 @@ static int i2o_cfg_evt_get(unsigned long arg, struct file *fp) return 0; } -#ifdef CONFIG_I2O_EXT_ADAPTEC #ifdef CONFIG_COMPAT static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long arg) @@ -759,6 +762,7 @@ static long i2o_cfg_compat_ioctl(struct file *file, unsigned cmd, #endif +#ifdef CONFIG_I2O_EXT_ADAPTEC static int i2o_cfg_passthru(unsigned long arg) { struct i2o_cmd_passthru __user *cmd = diff --git a/trunk/drivers/message/i2o/i2o_proc.c b/trunk/drivers/message/i2o/i2o_proc.c index 3d2e76eea93e..a61cb17c5c12 100644 --- a/trunk/drivers/message/i2o/i2o_proc.c +++ b/trunk/drivers/message/i2o/i2o_proc.c @@ -163,7 +163,7 @@ static int print_serial_number(struct seq_file *seq, u8 * serialno, int max_len) * i2o_get_class_name - do i2o class name lookup * @class: class number * - * Return a descriptive string for an i2o class + * Return a descriptive string for an i2o class. */ static const char *i2o_get_class_name(int class) { diff --git a/trunk/drivers/message/i2o/i2o_scsi.c b/trunk/drivers/message/i2o/i2o_scsi.c index 6ebf38213f9f..1045c8a518bb 100644 --- a/trunk/drivers/message/i2o/i2o_scsi.c +++ b/trunk/drivers/message/i2o/i2o_scsi.c @@ -220,7 +220,7 @@ static int i2o_scsi_probe(struct device *dev) u32 id = -1; u64 lun = -1; int channel = -1; - int i; + int i, rc; i2o_shost = i2o_scsi_get_host(c); if (!i2o_shost) @@ -304,14 +304,20 @@ static int i2o_scsi_probe(struct device *dev) return PTR_ERR(scsi_dev); } - sysfs_create_link(&i2o_dev->device.kobj, &scsi_dev->sdev_gendev.kobj, - "scsi"); + rc = sysfs_create_link(&i2o_dev->device.kobj, + &scsi_dev->sdev_gendev.kobj, "scsi"); + if (rc) + goto err; osm_info("device added (TID: %03x) channel: %d, id: %d, lun: %ld\n", i2o_dev->lct_data.tid, channel, le32_to_cpu(id), (long unsigned int)le64_to_cpu(lun)); return 0; + +err: + scsi_remove_device(scsi_dev); + return rc; }; static const char *i2o_scsi_info(struct Scsi_Host *SChost) @@ -405,8 +411,7 @@ static void i2o_scsi_notify_device_add(struct i2o_device *i2o_dev) }; /** - * i2o_scsi_notify_device_remove - Retrieve notifications of removed - * devices + * i2o_scsi_notify_device_remove - Retrieve notifications of removed devices * @i2o_dev: the I2O device which was removed * * If a I2O device is removed, we catch the notification to remove the @@ -426,8 +431,7 @@ static void i2o_scsi_notify_device_remove(struct i2o_device *i2o_dev) }; /** - * i2o_scsi_notify_controller_add - Retrieve notifications of added - * controllers + * i2o_scsi_notify_controller_add - Retrieve notifications of added controllers * @c: the controller which was added * * If a I2O controller is added, we catch the notification to add a @@ -457,8 +461,7 @@ static void i2o_scsi_notify_controller_add(struct i2o_controller *c) }; /** - * i2o_scsi_notify_controller_remove - Retrieve notifications of removed - * controllers + * i2o_scsi_notify_controller_remove - Retrieve notifications of removed controllers * @c: the controller which was removed * * If a I2O controller is removed, we catch the notification to remove the @@ -745,7 +748,7 @@ static int i2o_scsi_abort(struct scsi_cmnd *SCpnt) * @capacity: size in sectors * @ip: geometry array * - * This is anyones guess quite frankly. We use the same rules everyone + * This is anyone's guess quite frankly. We use the same rules everyone * else appears to and hope. It seems to work. */ diff --git a/trunk/drivers/message/i2o/pci.c b/trunk/drivers/message/i2o/pci.c index 8287f95c8c42..3661e6e065d2 100644 --- a/trunk/drivers/message/i2o/pci.c +++ b/trunk/drivers/message/i2o/pci.c @@ -259,6 +259,7 @@ static irqreturn_t i2o_pci_interrupt(int irq, void *dev_id) /** * i2o_pci_irq_enable - Allocate interrupt for I2O controller + * @c: i2o_controller that the request is for * * Allocate an interrupt for the I2O controller, and activate interrupts * on the I2O controller. @@ -305,7 +306,7 @@ static void i2o_pci_irq_disable(struct i2o_controller *c) /** * i2o_pci_probe - Probe the PCI device for an I2O controller - * @dev: PCI device to test + * @pdev: PCI device to test * @id: id which matched with the PCI device id table * * Probe the PCI device for any device which is a memory of the @@ -447,7 +448,7 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev, /** * i2o_pci_remove - Removes a I2O controller from the system - * pdev: I2O controller which should be removed + * @pdev: I2O controller which should be removed * * Reset the I2O controller, disable interrupts and remove all allocated * resources. diff --git a/trunk/drivers/mfd/ucb1x00-ts.c b/trunk/drivers/mfd/ucb1x00-ts.c index 82938ad6ddbd..ce1a48108210 100644 --- a/trunk/drivers/mfd/ucb1x00-ts.c +++ b/trunk/drivers/mfd/ucb1x00-ts.c @@ -28,7 +28,7 @@ #include #include #include -#include +#include #include #include diff --git a/trunk/drivers/misc/tifm_7xx1.c b/trunk/drivers/misc/tifm_7xx1.c index 1ba8754e9383..2ab7add78f94 100644 --- a/trunk/drivers/misc/tifm_7xx1.c +++ b/trunk/drivers/misc/tifm_7xx1.c @@ -33,9 +33,10 @@ static void tifm_7xx1_eject(struct tifm_adapter *fm, struct tifm_dev *sock) spin_unlock_irqrestore(&fm->lock, flags); } -static void tifm_7xx1_remove_media(void *adapter) +static void tifm_7xx1_remove_media(struct work_struct *work) { - struct tifm_adapter *fm = adapter; + struct tifm_adapter *fm = + container_of(work, struct tifm_adapter, media_remover); unsigned long flags; int cnt; struct tifm_dev *sock; @@ -169,9 +170,10 @@ tifm_7xx1_sock_addr(char __iomem *base_addr, unsigned int sock_num) return base_addr + ((sock_num + 1) << 10); } -static void tifm_7xx1_insert_media(void *adapter) +static void tifm_7xx1_insert_media(struct work_struct *work) { - struct tifm_adapter *fm = adapter; + struct tifm_adapter *fm = + container_of(work, struct tifm_adapter, media_inserter); unsigned long flags; tifm_media_id media_id; char *card_name = "xx"; @@ -261,7 +263,7 @@ static int tifm_7xx1_suspend(struct pci_dev *dev, pm_message_t state) spin_unlock_irqrestore(&fm->lock, flags); flush_workqueue(fm->wq); - tifm_7xx1_remove_media(fm); + tifm_7xx1_remove_media(&fm->media_remover); pci_set_power_state(dev, PCI_D3hot); pci_disable_device(dev); @@ -328,8 +330,8 @@ static int tifm_7xx1_probe(struct pci_dev *dev, if (!fm->sockets) goto err_out_free; - INIT_WORK(&fm->media_inserter, tifm_7xx1_insert_media, fm); - INIT_WORK(&fm->media_remover, tifm_7xx1_remove_media, fm); + INIT_WORK(&fm->media_inserter, tifm_7xx1_insert_media); + INIT_WORK(&fm->media_remover, tifm_7xx1_remove_media); fm->eject = tifm_7xx1_eject; pci_set_drvdata(dev, fm); @@ -384,7 +386,7 @@ static void tifm_7xx1_remove(struct pci_dev *dev) flush_workqueue(fm->wq); - tifm_7xx1_remove_media(fm); + tifm_7xx1_remove_media(&fm->media_remover); writel(TIFM_IRQ_SETALL, fm->addr + FM_CLEAR_INTERRUPT_ENABLE); free_irq(dev->irq, fm); diff --git a/trunk/drivers/misc/tifm_core.c b/trunk/drivers/misc/tifm_core.c index ee326136d03b..d61df5c3ac36 100644 --- a/trunk/drivers/misc/tifm_core.c +++ b/trunk/drivers/misc/tifm_core.c @@ -219,8 +219,9 @@ static int tifm_device_remove(struct device *dev) struct tifm_driver *drv = fm_dev->drv; if (drv) { - if (drv->remove) drv->remove(fm_dev); - fm_dev->drv = 0; + if (drv->remove) + drv->remove(fm_dev); + fm_dev->drv = NULL; } put_device(dev); diff --git a/trunk/drivers/mmc/Kconfig b/trunk/drivers/mmc/Kconfig index f4f8ccaf5455..4224686fdf2a 100644 --- a/trunk/drivers/mmc/Kconfig +++ b/trunk/drivers/mmc/Kconfig @@ -91,11 +91,11 @@ config MMC_AU1X If unsure, say N. -config MMC_AT91RM9200 - tristate "AT91RM9200 SD/MMC Card Interface support" - depends on ARCH_AT91RM9200 && MMC +config MMC_AT91 + tristate "AT91 SD/MMC Card Interface support" + depends on ARCH_AT91 && MMC help - This selects the AT91RM9200 MCI controller. + This selects the AT91 MCI controller. If unsure, say N. diff --git a/trunk/drivers/mmc/Makefile b/trunk/drivers/mmc/Makefile index acfd4de0aba5..83ffb9326a54 100644 --- a/trunk/drivers/mmc/Makefile +++ b/trunk/drivers/mmc/Makefile @@ -22,7 +22,7 @@ obj-$(CONFIG_MMC_SDHCI) += sdhci.o obj-$(CONFIG_MMC_WBSD) += wbsd.o obj-$(CONFIG_MMC_AU1X) += au1xmmc.o obj-$(CONFIG_MMC_OMAP) += omap.o -obj-$(CONFIG_MMC_AT91RM9200) += at91_mci.o +obj-$(CONFIG_MMC_AT91) += at91_mci.o obj-$(CONFIG_MMC_TIFM_SD) += tifm_sd.o mmc_core-y := mmc.o mmc_sysfs.o diff --git a/trunk/drivers/mmc/at91_mci.c b/trunk/drivers/mmc/at91_mci.c index 6495cd8a9306..4633dbc9a90f 100644 --- a/trunk/drivers/mmc/at91_mci.c +++ b/trunk/drivers/mmc/at91_mci.c @@ -73,8 +73,8 @@ #include #include #include -#include -#include +#include +#include #define DRIVER_NAME "at91_mci" diff --git a/trunk/drivers/mmc/mmc.c b/trunk/drivers/mmc/mmc.c index 9d190022a490..6f2a282e2b97 100644 --- a/trunk/drivers/mmc/mmc.c +++ b/trunk/drivers/mmc/mmc.c @@ -1419,18 +1419,16 @@ static void mmc_setup(struct mmc_host *host) */ void mmc_detect_change(struct mmc_host *host, unsigned long delay) { - if (delay) - mmc_schedule_delayed_work(&host->detect, delay); - else - mmc_schedule_work(&host->detect); + mmc_schedule_delayed_work(&host->detect, delay); } EXPORT_SYMBOL(mmc_detect_change); -static void mmc_rescan(void *data) +static void mmc_rescan(struct work_struct *work) { - struct mmc_host *host = data; + struct mmc_host *host = + container_of(work, struct mmc_host, detect.work); struct list_head *l, *n; unsigned char power_mode; @@ -1513,7 +1511,7 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev) spin_lock_init(&host->lock); init_waitqueue_head(&host->wq); INIT_LIST_HEAD(&host->cards); - INIT_WORK(&host->detect, mmc_rescan, host); + INIT_DELAYED_WORK(&host->detect, mmc_rescan); /* * By default, hosts do not support SGIO or large requests. @@ -1611,7 +1609,7 @@ EXPORT_SYMBOL(mmc_suspend_host); */ int mmc_resume_host(struct mmc_host *host) { - mmc_rescan(host); + mmc_rescan(&host->detect.work); return 0; } diff --git a/trunk/drivers/mmc/mmc.h b/trunk/drivers/mmc/mmc.h index cd5e0ab3d84b..149affe0b686 100644 --- a/trunk/drivers/mmc/mmc.h +++ b/trunk/drivers/mmc/mmc.h @@ -20,6 +20,6 @@ void mmc_remove_host_sysfs(struct mmc_host *host); void mmc_free_host_sysfs(struct mmc_host *host); int mmc_schedule_work(struct work_struct *work); -int mmc_schedule_delayed_work(struct work_struct *work, unsigned long delay); +int mmc_schedule_delayed_work(struct delayed_work *work, unsigned long delay); void mmc_flush_scheduled_work(void); #endif diff --git a/trunk/drivers/mmc/mmc_sysfs.c b/trunk/drivers/mmc/mmc_sysfs.c index ac5329636045..e334acd045bc 100644 --- a/trunk/drivers/mmc/mmc_sysfs.c +++ b/trunk/drivers/mmc/mmc_sysfs.c @@ -320,18 +320,10 @@ void mmc_free_host_sysfs(struct mmc_host *host) static struct workqueue_struct *workqueue; -/* - * Internal function. Schedule work in the MMC work queue. - */ -int mmc_schedule_work(struct work_struct *work) -{ - return queue_work(workqueue, work); -} - /* * Internal function. Schedule delayed work in the MMC work queue. */ -int mmc_schedule_delayed_work(struct work_struct *work, unsigned long delay) +int mmc_schedule_delayed_work(struct delayed_work *work, unsigned long delay) { return queue_delayed_work(workqueue, work, delay); } diff --git a/trunk/drivers/mmc/tifm_sd.c b/trunk/drivers/mmc/tifm_sd.c index 0fdc55b08a6d..f18ad998b3cb 100644 --- a/trunk/drivers/mmc/tifm_sd.c +++ b/trunk/drivers/mmc/tifm_sd.c @@ -99,7 +99,7 @@ struct tifm_sd { struct mmc_request *req; struct work_struct cmd_handler; - struct work_struct abort_handler; + struct delayed_work abort_handler; wait_queue_head_t can_eject; size_t written_blocks; @@ -387,7 +387,7 @@ static void tifm_sd_prepare_data(struct tifm_sd *card, struct mmc_command *cmd) writel(TIFM_FIFO_INT_SETALL, sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR); - writel(long_log2(cmd->data->blksz) - 2, + writel(ilog2(cmd->data->blksz) - 2, sock->addr + SOCK_FIFO_PAGE_SIZE); writel(TIFM_FIFO_ENABLE, sock->addr + SOCK_FIFO_CONTROL); writel(TIFM_FIFO_INTMASK, sock->addr + SOCK_DMA_FIFO_INT_ENABLE_SET); @@ -496,9 +496,9 @@ static void tifm_sd_request(struct mmc_host *mmc, struct mmc_request *mrq) mmc_request_done(mmc, mrq); } -static void tifm_sd_end_cmd(void *data) +static void tifm_sd_end_cmd(struct work_struct *work) { - struct tifm_sd *host = data; + struct tifm_sd *host = container_of(work, struct tifm_sd, cmd_handler); struct tifm_dev *sock = host->dev; struct mmc_host *mmc = tifm_get_drvdata(sock); struct mmc_request *mrq; @@ -608,9 +608,9 @@ static void tifm_sd_request_nodma(struct mmc_host *mmc, struct mmc_request *mrq) mmc_request_done(mmc, mrq); } -static void tifm_sd_end_cmd_nodma(void *data) +static void tifm_sd_end_cmd_nodma(struct work_struct *work) { - struct tifm_sd *host = (struct tifm_sd*)data; + struct tifm_sd *host = container_of(work, struct tifm_sd, cmd_handler); struct tifm_dev *sock = host->dev; struct mmc_host *mmc = tifm_get_drvdata(sock); struct mmc_request *mrq; @@ -661,11 +661,14 @@ static void tifm_sd_end_cmd_nodma(void *data) mmc_request_done(mmc, mrq); } -static void tifm_sd_abort(void *data) +static void tifm_sd_abort(struct work_struct *work) { + struct tifm_sd *host = + container_of(work, struct tifm_sd, abort_handler.work); + printk(KERN_ERR DRIVER_NAME ": card failed to respond for a long period of time"); - tifm_eject(((struct tifm_sd*)data)->dev); + tifm_eject(host->dev); } static void tifm_sd_ios(struct mmc_host *mmc, struct mmc_ios *ios) @@ -762,9 +765,9 @@ static struct mmc_host_ops tifm_sd_ops = { .get_ro = tifm_sd_ro }; -static void tifm_sd_register_host(void *data) +static void tifm_sd_register_host(struct work_struct *work) { - struct tifm_sd *host = (struct tifm_sd*)data; + struct tifm_sd *host = container_of(work, struct tifm_sd, cmd_handler); struct tifm_dev *sock = host->dev; struct mmc_host *mmc = tifm_get_drvdata(sock); unsigned long flags; @@ -772,8 +775,7 @@ static void tifm_sd_register_host(void *data) spin_lock_irqsave(&sock->lock, flags); host->flags |= HOST_REG; PREPARE_WORK(&host->cmd_handler, - no_dma ? tifm_sd_end_cmd_nodma : tifm_sd_end_cmd, - data); + no_dma ? tifm_sd_end_cmd_nodma : tifm_sd_end_cmd); spin_unlock_irqrestore(&sock->lock, flags); dev_dbg(&sock->dev, "adding host\n"); mmc_add_host(mmc); @@ -799,8 +801,8 @@ static int tifm_sd_probe(struct tifm_dev *sock) host->dev = sock; host->clk_div = 61; init_waitqueue_head(&host->can_eject); - INIT_WORK(&host->cmd_handler, tifm_sd_register_host, host); - INIT_WORK(&host->abort_handler, tifm_sd_abort, host); + INIT_WORK(&host->cmd_handler, tifm_sd_register_host); + INIT_DELAYED_WORK(&host->abort_handler, tifm_sd_abort); tifm_set_drvdata(sock, mmc); sock->signal_irq = tifm_sd_signal_irq; diff --git a/trunk/drivers/mtd/devices/m25p80.c b/trunk/drivers/mtd/devices/m25p80.c index ef4a731ca5c2..334e078ffaff 100644 --- a/trunk/drivers/mtd/devices/m25p80.c +++ b/trunk/drivers/mtd/devices/m25p80.c @@ -451,7 +451,7 @@ static int __devinit m25p_probe(struct spi_device *spi) return -ENODEV; } - flash = kzalloc(sizeof *flash, SLAB_KERNEL); + flash = kzalloc(sizeof *flash, GFP_KERNEL); if (!flash) return -ENOMEM; diff --git a/trunk/drivers/net/3c501.c b/trunk/drivers/net/3c501.c index 11d170afa9c3..06e33786078d 100644 --- a/trunk/drivers/net/3c501.c +++ b/trunk/drivers/net/3c501.c @@ -922,7 +922,7 @@ int __init init_module(void) * and then free up the resources we took when the card was found. */ -void cleanup_module(void) +void __exit cleanup_module(void) { struct net_device *dev = dev_3c501; unregister_netdev(dev); diff --git a/trunk/drivers/net/3c503.c b/trunk/drivers/net/3c503.c index a34b2206132d..7e34c4f07b70 100644 --- a/trunk/drivers/net/3c503.c +++ b/trunk/drivers/net/3c503.c @@ -726,7 +726,7 @@ static void cleanup_card(struct net_device *dev) iounmap(ei_status.mem); } -void +void __exit cleanup_module(void) { int this_dev; diff --git a/trunk/drivers/net/3c505.c b/trunk/drivers/net/3c505.c index 458cb9cbe915..702bfb2a5e99 100644 --- a/trunk/drivers/net/3c505.c +++ b/trunk/drivers/net/3c505.c @@ -1670,7 +1670,7 @@ int __init init_module(void) return 0; } -void cleanup_module(void) +void __exit cleanup_module(void) { int this_dev; diff --git a/trunk/drivers/net/3c507.c b/trunk/drivers/net/3c507.c index aa43563610ae..54e1d5aebed3 100644 --- a/trunk/drivers/net/3c507.c +++ b/trunk/drivers/net/3c507.c @@ -940,7 +940,7 @@ int __init init_module(void) return IS_ERR(dev_3c507) ? PTR_ERR(dev_3c507) : 0; } -void +void __exit cleanup_module(void) { struct net_device *dev = dev_3c507; diff --git a/trunk/drivers/net/3c523.c b/trunk/drivers/net/3c523.c index 91849469b4f4..17d61eb0a7e5 100644 --- a/trunk/drivers/net/3c523.c +++ b/trunk/drivers/net/3c523.c @@ -1302,7 +1302,7 @@ int __init init_module(void) } else return 0; } -void cleanup_module(void) +void __exit cleanup_module(void) { int this_dev; for (this_dev=0; this_devlock); spin_lock_init (&tp->rx_lock); - INIT_WORK(&tp->thread, rtl8139_thread, dev); + INIT_DELAYED_WORK(&tp->thread, rtl8139_thread); tp->mii.dev = dev; tp->mii.mdio_read = mdio_read; tp->mii.mdio_write = mdio_write; @@ -1596,15 +1596,16 @@ static inline void rtl8139_thread_iter (struct net_device *dev, RTL_R8 (Config1)); } -static void rtl8139_thread (void *_data) +static void rtl8139_thread (struct work_struct *work) { - struct net_device *dev = _data; - struct rtl8139_private *tp = netdev_priv(dev); + struct rtl8139_private *tp = + container_of(work, struct rtl8139_private, thread.work); + struct net_device *dev = tp->mii.dev; unsigned long thr_delay = next_tick; if (tp->watchdog_fired) { tp->watchdog_fired = 0; - rtl8139_tx_timeout_task(_data); + rtl8139_tx_timeout_task(work); } else if (rtnl_trylock()) { rtl8139_thread_iter (dev, tp, tp->mmio_addr); rtnl_unlock (); @@ -1646,10 +1647,11 @@ static inline void rtl8139_tx_clear (struct rtl8139_private *tp) /* XXX account for unsent Tx packets in tp->stats.tx_dropped */ } -static void rtl8139_tx_timeout_task (void *_data) +static void rtl8139_tx_timeout_task (struct work_struct *work) { - struct net_device *dev = _data; - struct rtl8139_private *tp = netdev_priv(dev); + struct rtl8139_private *tp = + container_of(work, struct rtl8139_private, thread.work); + struct net_device *dev = tp->mii.dev; void __iomem *ioaddr = tp->mmio_addr; int i; u8 tmp8; @@ -1695,7 +1697,7 @@ static void rtl8139_tx_timeout (struct net_device *dev) struct rtl8139_private *tp = netdev_priv(dev); if (!tp->have_thread) { - INIT_WORK(&tp->thread, rtl8139_tx_timeout_task, dev); + INIT_DELAYED_WORK(&tp->thread, rtl8139_tx_timeout_task); schedule_delayed_work(&tp->thread, next_tick); } else tp->watchdog_fired = 1; diff --git a/trunk/drivers/net/ac3200.c b/trunk/drivers/net/ac3200.c index 0dca8bb9d2c7..c01f87f5bed7 100644 --- a/trunk/drivers/net/ac3200.c +++ b/trunk/drivers/net/ac3200.c @@ -405,7 +405,7 @@ static void cleanup_card(struct net_device *dev) iounmap(ei_status.mem); } -void +void __exit cleanup_module(void) { int this_dev; diff --git a/trunk/drivers/net/apne.c b/trunk/drivers/net/apne.c index 9164d8cd670e..d4e408169073 100644 --- a/trunk/drivers/net/apne.c +++ b/trunk/drivers/net/apne.c @@ -568,7 +568,7 @@ static irqreturn_t apne_interrupt(int irq, void *dev_id) #ifdef MODULE static struct net_device *apne_dev; -int init_module(void) +int __init init_module(void) { apne_dev = apne_probe(-1); if (IS_ERR(apne_dev)) @@ -576,7 +576,7 @@ int init_module(void) return 0; } -void cleanup_module(void) +void __exit cleanup_module(void) { unregister_netdev(apne_dev); diff --git a/trunk/drivers/net/appletalk/cops.c b/trunk/drivers/net/appletalk/cops.c index cc1a27ed197f..dba5e5165452 100644 --- a/trunk/drivers/net/appletalk/cops.c +++ b/trunk/drivers/net/appletalk/cops.c @@ -1041,7 +1041,7 @@ int __init init_module(void) return 0; } -void cleanup_module(void) +void __exit cleanup_module(void) { unregister_netdev(cops_dev); cleanup_card(cops_dev); diff --git a/trunk/drivers/net/arm/at91_ether.c b/trunk/drivers/net/arm/at91_ether.c index b54b857e357e..fada15d959de 100644 --- a/trunk/drivers/net/arm/at91_ether.c +++ b/trunk/drivers/net/arm/at91_ether.c @@ -41,9 +41,6 @@ #define DRV_NAME "at91_ether" #define DRV_VERSION "1.0" -static struct net_device *at91_dev; - -static struct timer_list check_timer; #define LINK_POLL_INTERVAL (HZ) /* ..................................................................... */ @@ -146,7 +143,7 @@ static void read_phy(unsigned char phy_addr, unsigned char address, unsigned int */ static void update_linkspeed(struct net_device *dev, int silent) { - struct at91_private *lp = (struct at91_private *) dev->priv; + struct at91_private *lp = netdev_priv(dev); unsigned int bmsr, bmcr, lpa, mac_cfg; unsigned int speed, duplex; @@ -199,7 +196,7 @@ static void update_linkspeed(struct net_device *dev, int silent) static irqreturn_t at91ether_phy_interrupt(int irq, void *dev_id) { struct net_device *dev = (struct net_device *) dev_id; - struct at91_private *lp = (struct at91_private *) dev->priv; + struct at91_private *lp = netdev_priv(dev); unsigned int phy; /* @@ -242,7 +239,7 @@ static irqreturn_t at91ether_phy_interrupt(int irq, void *dev_id) */ static void enable_phyirq(struct net_device *dev) { - struct at91_private *lp = (struct at91_private *) dev->priv; + struct at91_private *lp = netdev_priv(dev); unsigned int dsintr, irq_number; int status; @@ -252,8 +249,7 @@ static void enable_phyirq(struct net_device *dev) * PHY doesn't have an IRQ pin (RTL8201, DP83847, AC101L), * or board does not have it connected. */ - check_timer.expires = jiffies + LINK_POLL_INTERVAL; - add_timer(&check_timer); + mod_timer(&lp->check_timer, jiffies + LINK_POLL_INTERVAL); return; } @@ -294,13 +290,13 @@ static void enable_phyirq(struct net_device *dev) */ static void disable_phyirq(struct net_device *dev) { - struct at91_private *lp = (struct at91_private *) dev->priv; + struct at91_private *lp = netdev_priv(dev); unsigned int dsintr; unsigned int irq_number; irq_number = lp->board_data.phy_irq_pin; if (!irq_number) { - del_timer_sync(&check_timer); + del_timer_sync(&lp->check_timer); return; } @@ -340,7 +336,7 @@ static void disable_phyirq(struct net_device *dev) #if 0 static void reset_phy(struct net_device *dev) { - struct at91_private *lp = (struct at91_private *) dev->priv; + struct at91_private *lp = netdev_priv(dev); unsigned int bmcr; spin_lock_irq(&lp->lock); @@ -362,13 +358,13 @@ static void reset_phy(struct net_device *dev) static void at91ether_check_link(unsigned long dev_id) { struct net_device *dev = (struct net_device *) dev_id; + struct at91_private *lp = netdev_priv(dev); enable_mdi(); update_linkspeed(dev, 1); disable_mdi(); - check_timer.expires = jiffies + LINK_POLL_INTERVAL; - add_timer(&check_timer); + mod_timer(&lp->check_timer, jiffies + LINK_POLL_INTERVAL); } /* ......................... ADDRESS MANAGEMENT ........................ */ @@ -590,7 +586,7 @@ static void mdio_write(struct net_device *dev, int phy_id, int location, int val static int at91ether_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) { - struct at91_private *lp = (struct at91_private *) dev->priv; + struct at91_private *lp = netdev_priv(dev); int ret; spin_lock_irq(&lp->lock); @@ -611,7 +607,7 @@ static int at91ether_get_settings(struct net_device *dev, struct ethtool_cmd *cm static int at91ether_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) { - struct at91_private *lp = (struct at91_private *) dev->priv; + struct at91_private *lp = netdev_priv(dev); int ret; spin_lock_irq(&lp->lock); @@ -627,7 +623,7 @@ static int at91ether_set_settings(struct net_device *dev, struct ethtool_cmd *cm static int at91ether_nwayreset(struct net_device *dev) { - struct at91_private *lp = (struct at91_private *) dev->priv; + struct at91_private *lp = netdev_priv(dev); int ret; spin_lock_irq(&lp->lock); @@ -658,7 +654,7 @@ static const struct ethtool_ops at91ether_ethtool_ops = { static int at91ether_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { - struct at91_private *lp = (struct at91_private *) dev->priv; + struct at91_private *lp = netdev_priv(dev); int res; if (!netif_running(dev)) @@ -680,7 +676,7 @@ static int at91ether_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) */ static void at91ether_start(struct net_device *dev) { - struct at91_private *lp = (struct at91_private *) dev->priv; + struct at91_private *lp = netdev_priv(dev); struct recv_desc_bufs *dlist, *dlist_phys; int i; unsigned long ctl; @@ -712,7 +708,7 @@ static void at91ether_start(struct net_device *dev) */ static int at91ether_open(struct net_device *dev) { - struct at91_private *lp = (struct at91_private *) dev->priv; + struct at91_private *lp = netdev_priv(dev); unsigned long ctl; if (!is_valid_ether_addr(dev->dev_addr)) @@ -752,7 +748,7 @@ static int at91ether_open(struct net_device *dev) */ static int at91ether_close(struct net_device *dev) { - struct at91_private *lp = (struct at91_private *) dev->priv; + struct at91_private *lp = netdev_priv(dev); unsigned long ctl; /* Disable Receiver and Transmitter */ @@ -779,7 +775,7 @@ static int at91ether_close(struct net_device *dev) */ static int at91ether_tx(struct sk_buff *skb, struct net_device *dev) { - struct at91_private *lp = (struct at91_private *) dev->priv; + struct at91_private *lp = netdev_priv(dev); if (at91_emac_read(AT91_EMAC_TSR) & AT91_EMAC_TSR_BNQ) { netif_stop_queue(dev); @@ -811,7 +807,7 @@ static int at91ether_tx(struct sk_buff *skb, struct net_device *dev) */ static struct net_device_stats *at91ether_stats(struct net_device *dev) { - struct at91_private *lp = (struct at91_private *) dev->priv; + struct at91_private *lp = netdev_priv(dev); int ale, lenerr, seqe, lcol, ecol; if (netif_running(dev)) { @@ -847,7 +843,7 @@ static struct net_device_stats *at91ether_stats(struct net_device *dev) */ static void at91ether_rx(struct net_device *dev) { - struct at91_private *lp = (struct at91_private *) dev->priv; + struct at91_private *lp = netdev_priv(dev); struct recv_desc_bufs *dlist; unsigned char *p_recv; struct sk_buff *skb; @@ -857,14 +853,13 @@ static void at91ether_rx(struct net_device *dev) while (dlist->descriptors[lp->rxBuffIndex].addr & EMAC_DESC_DONE) { p_recv = dlist->recv_buf[lp->rxBuffIndex]; pktlen = dlist->descriptors[lp->rxBuffIndex].size & 0x7ff; /* Length of frame including FCS */ - skb = alloc_skb(pktlen + 2, GFP_ATOMIC); + skb = dev_alloc_skb(pktlen + 2); if (skb != NULL) { skb_reserve(skb, 2); memcpy(skb_put(skb, pktlen), p_recv, pktlen); skb->dev = dev; skb->protocol = eth_type_trans(skb, dev); - skb->len = pktlen; dev->last_rx = jiffies; lp->stats.rx_bytes += pktlen; netif_rx(skb); @@ -891,7 +886,7 @@ static void at91ether_rx(struct net_device *dev) static irqreturn_t at91ether_interrupt(int irq, void *dev_id) { struct net_device *dev = (struct net_device *) dev_id; - struct at91_private *lp = (struct at91_private *) dev->priv; + struct at91_private *lp = netdev_priv(dev); unsigned long intstatus, ctl; /* MAC Interrupt Status register indicates what interrupts are pending. @@ -927,6 +922,17 @@ static irqreturn_t at91ether_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } +#ifdef CONFIG_NET_POLL_CONTROLLER +static void at91ether_poll_controller(struct net_device *dev) +{ + unsigned long flags; + + local_irq_save(flags); + at91ether_interrupt(dev->irq, dev); + local_irq_restore(flags); +} +#endif + /* * Initialize the ethernet interface */ @@ -939,9 +945,6 @@ static int __init at91ether_setup(unsigned long phy_type, unsigned short phy_add unsigned int val; int res; - if (at91_dev) /* already initialized */ - return 0; - dev = alloc_etherdev(sizeof(struct at91_private)); if (!dev) return -ENOMEM; @@ -957,7 +960,7 @@ static int __init at91ether_setup(unsigned long phy_type, unsigned short phy_add } /* Allocate memory for DMA Receive descriptors */ - lp = (struct at91_private *)dev->priv; + lp = netdev_priv(dev); lp->dlist = (struct recv_desc_bufs *) dma_alloc_coherent(NULL, sizeof(struct recv_desc_bufs), (dma_addr_t *) &lp->dlist_phys, GFP_KERNEL); if (lp->dlist == NULL) { free_irq(dev->irq, dev); @@ -979,6 +982,9 @@ static int __init at91ether_setup(unsigned long phy_type, unsigned short phy_add dev->set_mac_address = set_mac_address; dev->ethtool_ops = &at91ether_ethtool_ops; dev->do_ioctl = at91ether_ioctl; +#ifdef CONFIG_NET_POLL_CONTROLLER + dev->poll_controller = at91ether_poll_controller; +#endif SET_NETDEV_DEV(dev, &pdev->dev); @@ -1024,7 +1030,6 @@ static int __init at91ether_setup(unsigned long phy_type, unsigned short phy_add dma_free_coherent(NULL, sizeof(struct recv_desc_bufs), lp->dlist, (dma_addr_t)lp->dlist_phys); return res; } - at91_dev = dev; /* Determine current link speed */ spin_lock_irq(&lp->lock); @@ -1036,9 +1041,9 @@ static int __init at91ether_setup(unsigned long phy_type, unsigned short phy_add /* If board has no PHY IRQ, use a timer to poll the PHY */ if (!lp->board_data.phy_irq_pin) { - init_timer(&check_timer); - check_timer.data = (unsigned long)dev; - check_timer.function = at91ether_check_link; + init_timer(&lp->check_timer); + lp->check_timer.data = (unsigned long)dev; + lp->check_timer.function = at91ether_check_link; } /* Display ethernet banner */ @@ -1115,15 +1120,16 @@ static int __init at91ether_probe(struct platform_device *pdev) static int __devexit at91ether_remove(struct platform_device *pdev) { - struct at91_private *lp = (struct at91_private *) at91_dev->priv; + struct net_device *dev = platform_get_drvdata(pdev); + struct at91_private *lp = netdev_priv(dev); - unregister_netdev(at91_dev); - free_irq(at91_dev->irq, at91_dev); + unregister_netdev(dev); + free_irq(dev->irq, dev); dma_free_coherent(NULL, sizeof(struct recv_desc_bufs), lp->dlist, (dma_addr_t)lp->dlist_phys); clk_put(lp->ether_clk); - free_netdev(at91_dev); - at91_dev = NULL; + platform_set_drvdata(pdev, NULL); + free_netdev(dev); return 0; } @@ -1131,8 +1137,8 @@ static int __devexit at91ether_remove(struct platform_device *pdev) static int at91ether_suspend(struct platform_device *pdev, pm_message_t mesg) { - struct at91_private *lp = (struct at91_private *) at91_dev->priv; struct net_device *net_dev = platform_get_drvdata(pdev); + struct at91_private *lp = netdev_priv(net_dev); int phy_irq = lp->board_data.phy_irq_pin; if (netif_running(net_dev)) { @@ -1149,8 +1155,8 @@ static int at91ether_suspend(struct platform_device *pdev, pm_message_t mesg) static int at91ether_resume(struct platform_device *pdev) { - struct at91_private *lp = (struct at91_private *) at91_dev->priv; struct net_device *net_dev = platform_get_drvdata(pdev); + struct at91_private *lp = netdev_priv(net_dev); int phy_irq = lp->board_data.phy_irq_pin; if (netif_running(net_dev)) { diff --git a/trunk/drivers/net/arm/at91_ether.h b/trunk/drivers/net/arm/at91_ether.h index d1e72e02be3a..b6b665de2ea0 100644 --- a/trunk/drivers/net/arm/at91_ether.h +++ b/trunk/drivers/net/arm/at91_ether.h @@ -87,6 +87,7 @@ struct at91_private spinlock_t lock; /* lock for MDI interface */ short phy_media; /* media interface type */ unsigned short phy_address; /* 5-bit MDI address of PHY (0..31) */ + struct timer_list check_timer; /* Poll link status */ /* Transmit */ struct sk_buff *skb; /* holds skb until xmit interrupt completes */ diff --git a/trunk/drivers/net/arm/ether1.c b/trunk/drivers/net/arm/ether1.c index f3478a30e778..d6da3ce9ad79 100644 --- a/trunk/drivers/net/arm/ether1.c +++ b/trunk/drivers/net/arm/ether1.c @@ -254,7 +254,7 @@ ether1_readbuffer (struct net_device *dev, void *data, unsigned int start, unsig } while (thislen); } -static int __init +static int __devinit ether1_ramtest(struct net_device *dev, unsigned char byte) { unsigned char *buffer = kmalloc (BUFFER_SIZE, GFP_KERNEL); @@ -308,7 +308,7 @@ ether1_reset (struct net_device *dev) return BUS_16; } -static int __init +static int __devinit ether1_init_2(struct net_device *dev) { int i; @@ -986,7 +986,7 @@ ether1_setmulticastlist (struct net_device *dev) /* ------------------------------------------------------------------------- */ -static void __init ether1_banner(void) +static void __devinit ether1_banner(void) { static unsigned int version_printed = 0; diff --git a/trunk/drivers/net/arm/ether3.c b/trunk/drivers/net/arm/ether3.c index 84686c8a5bc2..4fc234785d56 100644 --- a/trunk/drivers/net/arm/ether3.c +++ b/trunk/drivers/net/arm/ether3.c @@ -198,7 +198,7 @@ static inline void ether3_ledon(struct net_device *dev) * Read the ethernet address string from the on board rom. * This is an ascii string!!! */ -static int __init +static int __devinit ether3_addr(char *addr, struct expansion_card *ec) { struct in_chunk_dir cd; @@ -223,7 +223,7 @@ ether3_addr(char *addr, struct expansion_card *ec) /* --------------------------------------------------------------------------- */ -static int __init +static int __devinit ether3_ramtest(struct net_device *dev, unsigned char byte) { unsigned char *buffer = kmalloc(RX_END, GFP_KERNEL); @@ -272,7 +272,7 @@ ether3_ramtest(struct net_device *dev, unsigned char byte) /* ------------------------------------------------------------------------------- */ -static int __init ether3_init_2(struct net_device *dev) +static int __devinit ether3_init_2(struct net_device *dev) { int i; @@ -765,7 +765,7 @@ static void ether3_tx(struct net_device *dev) } } -static void __init ether3_banner(void) +static void __devinit ether3_banner(void) { static unsigned version_printed = 0; diff --git a/trunk/drivers/net/at1700.c b/trunk/drivers/net/at1700.c index 8620a5b470f5..56ae8babd919 100644 --- a/trunk/drivers/net/at1700.c +++ b/trunk/drivers/net/at1700.c @@ -908,7 +908,7 @@ int __init init_module(void) return 0; } -void +void __exit cleanup_module(void) { unregister_netdev(dev_at1700); diff --git a/trunk/drivers/net/atarilance.c b/trunk/drivers/net/atarilance.c index d79489e46249..7e37ac86a69a 100644 --- a/trunk/drivers/net/atarilance.c +++ b/trunk/drivers/net/atarilance.c @@ -1179,7 +1179,7 @@ static int lance_set_mac_address( struct net_device *dev, void *addr ) #ifdef MODULE static struct net_device *atarilance_dev; -int init_module(void) +int __init init_module(void) { atarilance_dev = atarilance_probe(-1); if (IS_ERR(atarilance_dev)) @@ -1187,7 +1187,7 @@ int init_module(void) return 0; } -void cleanup_module(void) +void __exit cleanup_module(void) { unregister_netdev(atarilance_dev); free_irq(atarilance_dev->irq, atarilance_dev); diff --git a/trunk/drivers/net/bnx2.c b/trunk/drivers/net/bnx2.c index fc2f1d1c7ead..5bacb7587df4 100644 --- a/trunk/drivers/net/bnx2.c +++ b/trunk/drivers/net/bnx2.c @@ -4411,9 +4411,9 @@ bnx2_open(struct net_device *dev) } static void -bnx2_reset_task(void *data) +bnx2_reset_task(struct work_struct *work) { - struct bnx2 *bp = data; + struct bnx2 *bp = container_of(work, struct bnx2, reset_task); if (!netif_running(bp->dev)) return; @@ -5702,7 +5702,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) bp->pdev = pdev; spin_lock_init(&bp->phy_lock); - INIT_WORK(&bp->reset_task, bnx2_reset_task, bp); + INIT_WORK(&bp->reset_task, bnx2_reset_task); dev->base_addr = dev->mem_start = pci_resource_start(pdev, 0); mem_len = MB_GET_CID_ADDR(TX_TSS_CID + 1); diff --git a/trunk/drivers/net/bonding/bond_main.c b/trunk/drivers/net/bonding/bond_main.c index 488d8ed9e740..6482aed4bb7c 100644 --- a/trunk/drivers/net/bonding/bond_main.c +++ b/trunk/drivers/net/bonding/bond_main.c @@ -3684,7 +3684,7 @@ static int bond_do_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cmd mii->val_out = 0; read_lock_bh(&bond->lock); read_lock(&bond->curr_slave_lock); - if (bond->curr_active_slave) { + if (netif_carrier_ok(bond->dev)) { mii->val_out = BMSR_LSTATUS; } read_unlock(&bond->curr_slave_lock); diff --git a/trunk/drivers/net/cassini.c b/trunk/drivers/net/cassini.c index fd2cc13f7d97..c8126484c2be 100644 --- a/trunk/drivers/net/cassini.c +++ b/trunk/drivers/net/cassini.c @@ -4066,9 +4066,9 @@ static int cas_alloc_rxds(struct cas *cp) return 0; } -static void cas_reset_task(void *data) +static void cas_reset_task(struct work_struct *work) { - struct cas *cp = (struct cas *) data; + struct cas *cp = container_of(work, struct cas, reset_task); #if 0 int pending = atomic_read(&cp->reset_task_pending); #else @@ -5006,7 +5006,7 @@ static int __devinit cas_init_one(struct pci_dev *pdev, atomic_set(&cp->reset_task_pending_spare, 0); atomic_set(&cp->reset_task_pending_mtu, 0); #endif - INIT_WORK(&cp->reset_task, cas_reset_task, cp); + INIT_WORK(&cp->reset_task, cas_reset_task); /* Default link parameters */ if (link_mode >= 0 && link_mode <= 6) diff --git a/trunk/drivers/net/chelsio/common.h b/trunk/drivers/net/chelsio/common.h index b265941e1372..74758d2c7af8 100644 --- a/trunk/drivers/net/chelsio/common.h +++ b/trunk/drivers/net/chelsio/common.h @@ -279,7 +279,7 @@ struct adapter { struct petp *tp; struct port_info port[MAX_NPORTS]; - struct work_struct stats_update_task; + struct delayed_work stats_update_task; struct timer_list stats_update_timer; spinlock_t tpi_lock; diff --git a/trunk/drivers/net/chelsio/cphy.h b/trunk/drivers/net/chelsio/cphy.h index 60901f25014e..cf9143499882 100644 --- a/trunk/drivers/net/chelsio/cphy.h +++ b/trunk/drivers/net/chelsio/cphy.h @@ -91,7 +91,7 @@ struct cphy { int state; /* Link status state machine */ adapter_t *adapter; /* associated adapter */ - struct work_struct phy_update; + struct delayed_work phy_update; u16 bmsr; int count; diff --git a/trunk/drivers/net/chelsio/cxgb2.c b/trunk/drivers/net/chelsio/cxgb2.c index 53bec6739812..de48eadddbc4 100644 --- a/trunk/drivers/net/chelsio/cxgb2.c +++ b/trunk/drivers/net/chelsio/cxgb2.c @@ -953,10 +953,11 @@ static void t1_netpoll(struct net_device *dev) * Periodic accumulation of MAC statistics. This is used only if the MAC * does not have any other way to prevent stats counter overflow. */ -static void mac_stats_task(void *data) +static void mac_stats_task(struct work_struct *work) { int i; - struct adapter *adapter = data; + struct adapter *adapter = + container_of(work, struct adapter, stats_update_task.work); for_each_port(adapter, i) { struct port_info *p = &adapter->port[i]; @@ -977,9 +978,10 @@ static void mac_stats_task(void *data) /* * Processes elmer0 external interrupts in process context. */ -static void ext_intr_task(void *data) +static void ext_intr_task(struct work_struct *work) { - struct adapter *adapter = data; + struct adapter *adapter = + container_of(work, struct adapter, ext_intr_handler_task); t1_elmer0_ext_intr_handler(adapter); @@ -1113,9 +1115,9 @@ static int __devinit init_one(struct pci_dev *pdev, spin_lock_init(&adapter->mac_lock); INIT_WORK(&adapter->ext_intr_handler_task, - ext_intr_task, adapter); - INIT_WORK(&adapter->stats_update_task, mac_stats_task, - adapter); + ext_intr_task); + INIT_DELAYED_WORK(&adapter->stats_update_task, + mac_stats_task); pci_set_drvdata(pdev, netdev); } diff --git a/trunk/drivers/net/chelsio/my3126.c b/trunk/drivers/net/chelsio/my3126.c index 0b90014d5b3e..c7731b6f9de3 100644 --- a/trunk/drivers/net/chelsio/my3126.c +++ b/trunk/drivers/net/chelsio/my3126.c @@ -93,9 +93,11 @@ static int my3126_interrupt_handler(struct cphy *cphy) return cphy_cause_link_change; } -static void my3216_poll(void *arg) +static void my3216_poll(struct work_struct *work) { - my3126_interrupt_handler(arg); + struct cphy *cphy = container_of(work, struct cphy, phy_update.work); + + my3126_interrupt_handler(cphy); } static int my3126_set_loopback(struct cphy *cphy, int on) @@ -171,7 +173,7 @@ static struct cphy *my3126_phy_create(adapter_t *adapter, if (cphy) cphy_init(cphy, adapter, phy_addr, &my3126_ops, mdio_ops); - INIT_WORK(&cphy->phy_update, my3216_poll, cphy); + INIT_DELAYED_WORK(&cphy->phy_update, my3216_poll); cphy->bmsr = 0; return (cphy); diff --git a/trunk/drivers/net/cs89x0.c b/trunk/drivers/net/cs89x0.c index dec70c2b374a..4612f71a7106 100644 --- a/trunk/drivers/net/cs89x0.c +++ b/trunk/drivers/net/cs89x0.c @@ -1974,7 +1974,7 @@ int __init init_module(void) return ret; } -void +void __exit cleanup_module(void) { unregister_netdev(dev_cs89x0); diff --git a/trunk/drivers/net/de600.c b/trunk/drivers/net/de600.c index 690bb40b353d..8396e411f1ce 100644 --- a/trunk/drivers/net/de600.c +++ b/trunk/drivers/net/de600.c @@ -43,7 +43,6 @@ static const char version[] = "de600.c: $Revision: 1.41-2.5 $, Bjorn Ekwall (bj * modify the following "#define": (see for more info) #define REALLY_SLOW_IO */ -#define SLOW_IO_BY_JUMPING /* Looks "better" than dummy write to port 0x80 :-) */ /* use 0 for production, 1 for verification, >2 for debug */ #ifdef DE600_DEBUG diff --git a/trunk/drivers/net/declance.c b/trunk/drivers/net/declance.c index 00e2a8a134d7..4ae0fed7122e 100644 --- a/trunk/drivers/net/declance.c +++ b/trunk/drivers/net/declance.c @@ -40,6 +40,10 @@ * * v0.009: Module support fixes, multiple interfaces support, various * bits. macro + * + * v0.010: Fixes for the PMAD mapping of the LANCE buffer and for the + * PMAX requirement to only use halfword accesses to the + * buffer. macro */ #include @@ -54,6 +58,7 @@ #include #include #include +#include #include #include @@ -67,7 +72,7 @@ #include static char version[] __devinitdata = -"declance.c: v0.009 by Linux MIPS DECstation task force\n"; +"declance.c: v0.010 by Linux MIPS DECstation task force\n"; MODULE_AUTHOR("Linux MIPS DECstation task force"); MODULE_DESCRIPTION("DEC LANCE (DECstation onboard, PMAD-xx) driver"); @@ -110,24 +115,25 @@ MODULE_LICENSE("GPL"); #define LE_C3_BCON 0x1 /* Byte control */ /* Receive message descriptor 1 */ -#define LE_R1_OWN 0x80 /* Who owns the entry */ -#define LE_R1_ERR 0x40 /* Error: if FRA, OFL, CRC or BUF is set */ -#define LE_R1_FRA 0x20 /* FRA: Frame error */ -#define LE_R1_OFL 0x10 /* OFL: Frame overflow */ -#define LE_R1_CRC 0x08 /* CRC error */ -#define LE_R1_BUF 0x04 /* BUF: Buffer error */ -#define LE_R1_SOP 0x02 /* Start of packet */ -#define LE_R1_EOP 0x01 /* End of packet */ -#define LE_R1_POK 0x03 /* Packet is complete: SOP + EOP */ - -#define LE_T1_OWN 0x80 /* Lance owns the packet */ -#define LE_T1_ERR 0x40 /* Error summary */ -#define LE_T1_EMORE 0x10 /* Error: more than one retry needed */ -#define LE_T1_EONE 0x08 /* Error: one retry needed */ -#define LE_T1_EDEF 0x04 /* Error: deferred */ -#define LE_T1_SOP 0x02 /* Start of packet */ -#define LE_T1_EOP 0x01 /* End of packet */ -#define LE_T1_POK 0x03 /* Packet is complete: SOP + EOP */ +#define LE_R1_OWN 0x8000 /* Who owns the entry */ +#define LE_R1_ERR 0x4000 /* Error: if FRA, OFL, CRC or BUF is set */ +#define LE_R1_FRA 0x2000 /* FRA: Frame error */ +#define LE_R1_OFL 0x1000 /* OFL: Frame overflow */ +#define LE_R1_CRC 0x0800 /* CRC error */ +#define LE_R1_BUF 0x0400 /* BUF: Buffer error */ +#define LE_R1_SOP 0x0200 /* Start of packet */ +#define LE_R1_EOP 0x0100 /* End of packet */ +#define LE_R1_POK 0x0300 /* Packet is complete: SOP + EOP */ + +/* Transmit message descriptor 1 */ +#define LE_T1_OWN 0x8000 /* Lance owns the packet */ +#define LE_T1_ERR 0x4000 /* Error summary */ +#define LE_T1_EMORE 0x1000 /* Error: more than one retry needed */ +#define LE_T1_EONE 0x0800 /* Error: one retry needed */ +#define LE_T1_EDEF 0x0400 /* Error: deferred */ +#define LE_T1_SOP 0x0200 /* Start of packet */ +#define LE_T1_EOP 0x0100 /* End of packet */ +#define LE_T1_POK 0x0300 /* Packet is complete: SOP + EOP */ #define LE_T3_BUF 0x8000 /* Buffer error */ #define LE_T3_UFL 0x4000 /* Error underflow */ @@ -156,69 +162,57 @@ MODULE_LICENSE("GPL"); #undef TEST_HITS #define ZERO 0 -/* The DS2000/3000 have a linear 64 KB buffer. - - * The PMAD-AA has 128 kb buffer on-board. +/* + * The DS2100/3100 have a linear 64 kB buffer which supports halfword + * accesses only. Each halfword of the buffer is word-aligned in the + * CPU address space. * - * The IOASIC LANCE devices use a shared memory region. This region as seen - * from the CPU is (max) 128 KB long and has to be on an 128 KB boundary. - * The LANCE sees this as a 64 KB long continuous memory region. + * The PMAD-AA has a 128 kB buffer on-board. * - * The LANCE's DMA address is used as an index in this buffer and DMA takes - * place in bursts of eight 16-Bit words which are packed into four 32-Bit words - * by the IOASIC. This leads to a strange padding: 16 bytes of valid data followed - * by a 16 byte gap :-(. + * The IOASIC LANCE devices use a shared memory region. This region + * as seen from the CPU is (max) 128 kB long and has to be on an 128 kB + * boundary. The LANCE sees this as a 64 kB long continuous memory + * region. + * + * The LANCE's DMA address is used as an index in this buffer and DMA + * takes place in bursts of eight 16-bit words which are packed into + * four 32-bit words by the IOASIC. This leads to a strange padding: + * 16 bytes of valid data followed by a 16 byte gap :-(. */ struct lance_rx_desc { unsigned short rmd0; /* low address of packet */ - short gap0; - unsigned char rmd1_hadr; /* high address of packet */ - unsigned char rmd1_bits; /* descriptor bits */ - short gap1; + unsigned short rmd1; /* high address of packet + and descriptor bits */ short length; /* 2s complement (negative!) of buffer length */ - short gap2; unsigned short mblength; /* actual number of bytes received */ - short gap3; }; struct lance_tx_desc { unsigned short tmd0; /* low address of packet */ - short gap0; - unsigned char tmd1_hadr; /* high address of packet */ - unsigned char tmd1_bits; /* descriptor bits */ - short gap1; + unsigned short tmd1; /* high address of packet + and descriptor bits */ short length; /* 2s complement (negative!) of buffer length */ - short gap2; unsigned short misc; - short gap3; }; /* First part of the LANCE initialization block, described in databook. */ struct lance_init_block { unsigned short mode; /* pre-set mode (reg. 15) */ - short gap0; - unsigned char phys_addr[12]; /* physical ethernet address - only 0, 1, 4, 5, 8, 9 are valid - 2, 3, 6, 7, 10, 11 are gaps */ - unsigned short filter[8]; /* multicast filter - only 0, 2, 4, 6 are valid - 1, 3, 5, 7 are gaps */ + unsigned short phys_addr[3]; /* physical ethernet address */ + unsigned short filter[4]; /* multicast filter */ /* Receive and transmit ring base, along with extra bits. */ unsigned short rx_ptr; /* receive descriptor addr */ - short gap1; unsigned short rx_len; /* receive len and high addr */ - short gap2; unsigned short tx_ptr; /* transmit descriptor addr */ - short gap3; unsigned short tx_len; /* transmit len and high addr */ - short gap4; - short gap5[8]; + + short gap[4]; /* The buffer descriptors */ struct lance_rx_desc brx_ring[RX_RING_SIZE]; @@ -226,15 +220,28 @@ struct lance_init_block { }; #define BUF_OFFSET_CPU sizeof(struct lance_init_block) -#define BUF_OFFSET_LNC (sizeof(struct lance_init_block)>>1) +#define BUF_OFFSET_LNC sizeof(struct lance_init_block) -#define libdesc_offset(rt, elem) \ -((__u32)(((unsigned long)(&(((struct lance_init_block *)0)->rt[elem]))))) +#define shift_off(off, type) \ + (type == ASIC_LANCE || type == PMAX_LANCE ? off << 1 : off) -/* - * This works *only* for the ring descriptors - */ -#define LANCE_ADDR(x) (CPHYSADDR(x) >> 1) +#define lib_off(rt, type) \ + shift_off(offsetof(struct lance_init_block, rt), type) + +#define lib_ptr(ib, rt, type) \ + ((volatile u16 *)((u8 *)(ib) + lib_off(rt, type))) + +#define rds_off(rt, type) \ + shift_off(offsetof(struct lance_rx_desc, rt), type) + +#define rds_ptr(rd, rt, type) \ + ((volatile u16 *)((u8 *)(rd) + rds_off(rt, type))) + +#define tds_off(rt, type) \ + shift_off(offsetof(struct lance_tx_desc, rt), type) + +#define tds_ptr(td, rt, type) \ + ((volatile u16 *)((u8 *)(td) + tds_off(rt, type))) struct lance_private { struct net_device *next; @@ -242,7 +249,6 @@ struct lance_private { int slot; int dma_irq; volatile struct lance_regs *ll; - volatile struct lance_init_block *init_block; spinlock_t lock; @@ -260,8 +266,8 @@ struct lance_private { char *tx_buf_ptr_cpu[TX_RING_SIZE]; /* Pointers to the ring buffers as seen from the LANCE */ - char *rx_buf_ptr_lnc[RX_RING_SIZE]; - char *tx_buf_ptr_lnc[TX_RING_SIZE]; + uint rx_buf_ptr_lnc[RX_RING_SIZE]; + uint tx_buf_ptr_lnc[TX_RING_SIZE]; }; #define TX_BUFFS_AVAIL ((lp->tx_old<=lp->tx_new)?\ @@ -294,7 +300,7 @@ static inline void writereg(volatile unsigned short *regptr, short value) static void load_csrs(struct lance_private *lp) { volatile struct lance_regs *ll = lp->ll; - int leptr; + uint leptr; /* The address space as seen from the LANCE * begins at address 0. HK @@ -316,12 +322,14 @@ static void load_csrs(struct lance_private *lp) * Our specialized copy routines * */ -void cp_to_buf(const int type, void *to, const void *from, int len) +static void cp_to_buf(const int type, void *to, const void *from, int len) { unsigned short *tp, *fp, clen; unsigned char *rtp, *rfp; - if (type == PMAX_LANCE) { + if (type == PMAD_LANCE) { + memcpy(to, from, len); + } else if (type == PMAX_LANCE) { clen = len >> 1; tp = (unsigned short *) to; fp = (unsigned short *) from; @@ -370,12 +378,14 @@ void cp_to_buf(const int type, void *to, const void *from, int len) iob(); } -void cp_from_buf(const int type, void *to, const void *from, int len) +static void cp_from_buf(const int type, void *to, const void *from, int len) { unsigned short *tp, *fp, clen; unsigned char *rtp, *rfp; - if (type == PMAX_LANCE) { + if (type == PMAD_LANCE) { + memcpy(to, from, len); + } else if (type == PMAX_LANCE) { clen = len >> 1; tp = (unsigned short *) to; fp = (unsigned short *) from; @@ -431,12 +441,10 @@ void cp_from_buf(const int type, void *to, const void *from, int len) static void lance_init_ring(struct net_device *dev) { struct lance_private *lp = netdev_priv(dev); - volatile struct lance_init_block *ib; - int leptr; + volatile u16 *ib = (volatile u16 *)dev->mem_start; + uint leptr; int i; - ib = (struct lance_init_block *) (dev->mem_start); - /* Lock out other processes while setting up hardware */ netif_stop_queue(dev); lp->rx_new = lp->tx_new = 0; @@ -445,55 +453,64 @@ static void lance_init_ring(struct net_device *dev) /* Copy the ethernet address to the lance init block. * XXX bit 0 of the physical address registers has to be zero */ - ib->phys_addr[0] = dev->dev_addr[0]; - ib->phys_addr[1] = dev->dev_addr[1]; - ib->phys_addr[4] = dev->dev_addr[2]; - ib->phys_addr[5] = dev->dev_addr[3]; - ib->phys_addr[8] = dev->dev_addr[4]; - ib->phys_addr[9] = dev->dev_addr[5]; + *lib_ptr(ib, phys_addr[0], lp->type) = (dev->dev_addr[1] << 8) | + dev->dev_addr[0]; + *lib_ptr(ib, phys_addr[1], lp->type) = (dev->dev_addr[3] << 8) | + dev->dev_addr[2]; + *lib_ptr(ib, phys_addr[2], lp->type) = (dev->dev_addr[5] << 8) | + dev->dev_addr[4]; /* Setup the initialization block */ /* Setup rx descriptor pointer */ - leptr = LANCE_ADDR(libdesc_offset(brx_ring, 0)); - ib->rx_len = (LANCE_LOG_RX_BUFFERS << 13) | (leptr >> 16); - ib->rx_ptr = leptr; + leptr = offsetof(struct lance_init_block, brx_ring); + *lib_ptr(ib, rx_len, lp->type) = (LANCE_LOG_RX_BUFFERS << 13) | + (leptr >> 16); + *lib_ptr(ib, rx_ptr, lp->type) = leptr; if (ZERO) - printk("RX ptr: %8.8x(%8.8x)\n", leptr, libdesc_offset(brx_ring, 0)); + printk("RX ptr: %8.8x(%8.8x)\n", + leptr, lib_off(brx_ring, lp->type)); /* Setup tx descriptor pointer */ - leptr = LANCE_ADDR(libdesc_offset(btx_ring, 0)); - ib->tx_len = (LANCE_LOG_TX_BUFFERS << 13) | (leptr >> 16); - ib->tx_ptr = leptr; + leptr = offsetof(struct lance_init_block, btx_ring); + *lib_ptr(ib, tx_len, lp->type) = (LANCE_LOG_TX_BUFFERS << 13) | + (leptr >> 16); + *lib_ptr(ib, tx_ptr, lp->type) = leptr; if (ZERO) - printk("TX ptr: %8.8x(%8.8x)\n", leptr, libdesc_offset(btx_ring, 0)); + printk("TX ptr: %8.8x(%8.8x)\n", + leptr, lib_off(btx_ring, lp->type)); if (ZERO) printk("TX rings:\n"); /* Setup the Tx ring entries */ for (i = 0; i < TX_RING_SIZE; i++) { - leptr = (int) lp->tx_buf_ptr_lnc[i]; - ib->btx_ring[i].tmd0 = leptr; - ib->btx_ring[i].tmd1_hadr = leptr >> 16; - ib->btx_ring[i].tmd1_bits = 0; - ib->btx_ring[i].length = 0xf000; /* The ones required by tmd2 */ - ib->btx_ring[i].misc = 0; + leptr = lp->tx_buf_ptr_lnc[i]; + *lib_ptr(ib, btx_ring[i].tmd0, lp->type) = leptr; + *lib_ptr(ib, btx_ring[i].tmd1, lp->type) = (leptr >> 16) & + 0xff; + *lib_ptr(ib, btx_ring[i].length, lp->type) = 0xf000; + /* The ones required by tmd2 */ + *lib_ptr(ib, btx_ring[i].misc, lp->type) = 0; if (i < 3 && ZERO) - printk("%d: 0x%8.8x(0x%8.8x)\n", i, leptr, (int) lp->tx_buf_ptr_cpu[i]); + printk("%d: 0x%8.8x(0x%8.8x)\n", + i, leptr, (uint)lp->tx_buf_ptr_cpu[i]); } /* Setup the Rx ring entries */ if (ZERO) printk("RX rings:\n"); for (i = 0; i < RX_RING_SIZE; i++) { - leptr = (int) lp->rx_buf_ptr_lnc[i]; - ib->brx_ring[i].rmd0 = leptr; - ib->brx_ring[i].rmd1_hadr = leptr >> 16; - ib->brx_ring[i].rmd1_bits = LE_R1_OWN; - ib->brx_ring[i].length = -RX_BUFF_SIZE | 0xf000; - ib->brx_ring[i].mblength = 0; + leptr = lp->rx_buf_ptr_lnc[i]; + *lib_ptr(ib, brx_ring[i].rmd0, lp->type) = leptr; + *lib_ptr(ib, brx_ring[i].rmd1, lp->type) = ((leptr >> 16) & + 0xff) | + LE_R1_OWN; + *lib_ptr(ib, brx_ring[i].length, lp->type) = -RX_BUFF_SIZE | + 0xf000; + *lib_ptr(ib, brx_ring[i].mblength, lp->type) = 0; if (i < 3 && ZERO) - printk("%d: 0x%8.8x(0x%8.8x)\n", i, leptr, (int) lp->rx_buf_ptr_cpu[i]); + printk("%d: 0x%8.8x(0x%8.8x)\n", + i, leptr, (uint)lp->rx_buf_ptr_cpu[i]); } iob(); } @@ -511,11 +528,13 @@ static int init_restart_lance(struct lance_private *lp) udelay(10); } if ((i == 100) || (ll->rdp & LE_C0_ERR)) { - printk("LANCE unopened after %d ticks, csr0=%4.4x.\n", i, ll->rdp); + printk("LANCE unopened after %d ticks, csr0=%4.4x.\n", + i, ll->rdp); return -1; } if ((ll->rdp & LE_C0_ERR)) { - printk("LANCE unopened after %d ticks, csr0=%4.4x.\n", i, ll->rdp); + printk("LANCE unopened after %d ticks, csr0=%4.4x.\n", + i, ll->rdp); return -1; } writereg(&ll->rdp, LE_C0_IDON); @@ -528,12 +547,11 @@ static int init_restart_lance(struct lance_private *lp) static int lance_rx(struct net_device *dev) { struct lance_private *lp = netdev_priv(dev); - volatile struct lance_init_block *ib; - volatile struct lance_rx_desc *rd = 0; - unsigned char bits; - int len = 0; - struct sk_buff *skb = 0; - ib = (struct lance_init_block *) (dev->mem_start); + volatile u16 *ib = (volatile u16 *)dev->mem_start; + volatile u16 *rd; + unsigned short bits; + int entry, len; + struct sk_buff *skb; #ifdef TEST_HITS { @@ -542,19 +560,22 @@ static int lance_rx(struct net_device *dev) printk("["); for (i = 0; i < RX_RING_SIZE; i++) { if (i == lp->rx_new) - printk("%s", ib->brx_ring[i].rmd1_bits & + printk("%s", *lib_ptr(ib, brx_ring[i].rmd1, + lp->type) & LE_R1_OWN ? "_" : "X"); else - printk("%s", ib->brx_ring[i].rmd1_bits & + printk("%s", *lib_ptr(ib, brx_ring[i].rmd1, + lp->type) & LE_R1_OWN ? "." : "1"); } printk("]"); } #endif - for (rd = &ib->brx_ring[lp->rx_new]; - !((bits = rd->rmd1_bits) & LE_R1_OWN); - rd = &ib->brx_ring[lp->rx_new]) { + for (rd = lib_ptr(ib, brx_ring[lp->rx_new], lp->type); + !((bits = *rds_ptr(rd, rmd1, lp->type)) & LE_R1_OWN); + rd = lib_ptr(ib, brx_ring[lp->rx_new], lp->type)) { + entry = lp->rx_new; /* We got an incomplete frame? */ if ((bits & LE_R1_POK) != LE_R1_POK) { @@ -575,16 +596,18 @@ static int lance_rx(struct net_device *dev) if (bits & LE_R1_EOP) lp->stats.rx_errors++; } else { - len = (rd->mblength & 0xfff) - 4; + len = (*rds_ptr(rd, mblength, lp->type) & 0xfff) - 4; skb = dev_alloc_skb(len + 2); if (skb == 0) { printk("%s: Memory squeeze, deferring packet.\n", dev->name); lp->stats.rx_dropped++; - rd->mblength = 0; - rd->rmd1_bits = LE_R1_OWN; - lp->rx_new = (lp->rx_new + 1) & RX_RING_MOD_MASK; + *rds_ptr(rd, mblength, lp->type) = 0; + *rds_ptr(rd, rmd1, lp->type) = + ((lp->rx_buf_ptr_lnc[entry] >> 16) & + 0xff) | LE_R1_OWN; + lp->rx_new = (entry + 1) & RX_RING_MOD_MASK; return 0; } lp->stats.rx_bytes += len; @@ -594,8 +617,7 @@ static int lance_rx(struct net_device *dev) skb_put(skb, len); /* make room */ cp_from_buf(lp->type, skb->data, - (char *)lp->rx_buf_ptr_cpu[lp->rx_new], - len); + (char *)lp->rx_buf_ptr_cpu[entry], len); skb->protocol = eth_type_trans(skb, dev); netif_rx(skb); @@ -604,10 +626,11 @@ static int lance_rx(struct net_device *dev) } /* Return the packet to the pool */ - rd->mblength = 0; - rd->length = -RX_BUFF_SIZE | 0xf000; - rd->rmd1_bits = LE_R1_OWN; - lp->rx_new = (lp->rx_new + 1) & RX_RING_MOD_MASK; + *rds_ptr(rd, mblength, lp->type) = 0; + *rds_ptr(rd, length, lp->type) = -RX_BUFF_SIZE | 0xf000; + *rds_ptr(rd, rmd1, lp->type) = + ((lp->rx_buf_ptr_lnc[entry] >> 16) & 0xff) | LE_R1_OWN; + lp->rx_new = (entry + 1) & RX_RING_MOD_MASK; } return 0; } @@ -615,24 +638,24 @@ static int lance_rx(struct net_device *dev) static void lance_tx(struct net_device *dev) { struct lance_private *lp = netdev_priv(dev); - volatile struct lance_init_block *ib; + volatile u16 *ib = (volatile u16 *)dev->mem_start; volatile struct lance_regs *ll = lp->ll; - volatile struct lance_tx_desc *td; + volatile u16 *td; int i, j; int status; - ib = (struct lance_init_block *) (dev->mem_start); + j = lp->tx_old; spin_lock(&lp->lock); for (i = j; i != lp->tx_new; i = j) { - td = &ib->btx_ring[i]; + td = lib_ptr(ib, btx_ring[i], lp->type); /* If we hit a packet not owned by us, stop */ - if (td->tmd1_bits & LE_T1_OWN) + if (*tds_ptr(td, tmd1, lp->type) & LE_T1_OWN) break; - if (td->tmd1_bits & LE_T1_ERR) { - status = td->misc; + if (*tds_ptr(td, tmd1, lp->type) & LE_T1_ERR) { + status = *tds_ptr(td, misc, lp->type); lp->stats.tx_errors++; if (status & LE_T3_RTY) @@ -667,18 +690,19 @@ static void lance_tx(struct net_device *dev) init_restart_lance(lp); goto out; } - } else if ((td->tmd1_bits & LE_T1_POK) == LE_T1_POK) { + } else if ((*tds_ptr(td, tmd1, lp->type) & LE_T1_POK) == + LE_T1_POK) { /* * So we don't count the packet more than once. */ - td->tmd1_bits &= ~(LE_T1_POK); + *tds_ptr(td, tmd1, lp->type) &= ~(LE_T1_POK); /* One collision before packet was sent. */ - if (td->tmd1_bits & LE_T1_EONE) + if (*tds_ptr(td, tmd1, lp->type) & LE_T1_EONE) lp->stats.collisions++; /* More than one collision, be optimistic. */ - if (td->tmd1_bits & LE_T1_EMORE) + if (*tds_ptr(td, tmd1, lp->type) & LE_T1_EMORE) lp->stats.collisions += 2; lp->stats.tx_packets++; @@ -752,7 +776,7 @@ struct net_device *last_dev = 0; static int lance_open(struct net_device *dev) { - volatile struct lance_init_block *ib = (struct lance_init_block *) (dev->mem_start); + volatile u16 *ib = (volatile u16 *)dev->mem_start; struct lance_private *lp = netdev_priv(dev); volatile struct lance_regs *ll = lp->ll; int status = 0; @@ -769,11 +793,11 @@ static int lance_open(struct net_device *dev) * * BTW it is common bug in all lance drivers! --ANK */ - ib->mode = 0; - ib->filter [0] = 0; - ib->filter [2] = 0; - ib->filter [4] = 0; - ib->filter [6] = 0; + *lib_ptr(ib, mode, lp->type) = 0; + *lib_ptr(ib, filter[0], lp->type) = 0; + *lib_ptr(ib, filter[1], lp->type) = 0; + *lib_ptr(ib, filter[2], lp->type) = 0; + *lib_ptr(ib, filter[3], lp->type) = 0; lance_init_ring(dev); load_csrs(lp); @@ -874,12 +898,10 @@ static int lance_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct lance_private *lp = netdev_priv(dev); volatile struct lance_regs *ll = lp->ll; - volatile struct lance_init_block *ib = (struct lance_init_block *) (dev->mem_start); - int entry, skblen, len; + volatile u16 *ib = (volatile u16 *)dev->mem_start; + int entry, len; - skblen = skb->len; - - len = skblen; + len = skb->len; if (len < ETH_ZLEN) { if (skb_padto(skb, ETH_ZLEN)) @@ -889,23 +911,17 @@ static int lance_start_xmit(struct sk_buff *skb, struct net_device *dev) lp->stats.tx_bytes += len; - entry = lp->tx_new & TX_RING_MOD_MASK; - ib->btx_ring[entry].length = (-len); - ib->btx_ring[entry].misc = 0; - - cp_to_buf(lp->type, (char *)lp->tx_buf_ptr_cpu[entry], skb->data, - skblen); + entry = lp->tx_new; + *lib_ptr(ib, btx_ring[entry].length, lp->type) = (-len); + *lib_ptr(ib, btx_ring[entry].misc, lp->type) = 0; - /* Clear the slack of the packet, do I need this? */ - /* For a firewall it's a good idea - AC */ -/* - if (len != skblen) - memset ((char *) &ib->tx_buf [entry][skblen], 0, (len - skblen) << 1); - */ + cp_to_buf(lp->type, (char *)lp->tx_buf_ptr_cpu[entry], skb->data, len); /* Now, give the packet to the lance */ - ib->btx_ring[entry].tmd1_bits = (LE_T1_POK | LE_T1_OWN); - lp->tx_new = (lp->tx_new + 1) & TX_RING_MOD_MASK; + *lib_ptr(ib, btx_ring[entry].tmd1, lp->type) = + ((lp->tx_buf_ptr_lnc[entry] >> 16) & 0xff) | + (LE_T1_POK | LE_T1_OWN); + lp->tx_new = (entry + 1) & TX_RING_MOD_MASK; if (TX_BUFFS_AVAIL <= 0) netif_stop_queue(dev); @@ -930,8 +946,8 @@ static struct net_device_stats *lance_get_stats(struct net_device *dev) static void lance_load_multicast(struct net_device *dev) { - volatile struct lance_init_block *ib = (struct lance_init_block *) (dev->mem_start); - volatile u16 *mcast_table = (u16 *) & ib->filter; + struct lance_private *lp = netdev_priv(dev); + volatile u16 *ib = (volatile u16 *)dev->mem_start; struct dev_mc_list *dmi = dev->mc_list; char *addrs; int i; @@ -939,17 +955,17 @@ static void lance_load_multicast(struct net_device *dev) /* set all multicast bits */ if (dev->flags & IFF_ALLMULTI) { - ib->filter[0] = 0xffff; - ib->filter[2] = 0xffff; - ib->filter[4] = 0xffff; - ib->filter[6] = 0xffff; + *lib_ptr(ib, filter[0], lp->type) = 0xffff; + *lib_ptr(ib, filter[1], lp->type) = 0xffff; + *lib_ptr(ib, filter[2], lp->type) = 0xffff; + *lib_ptr(ib, filter[3], lp->type) = 0xffff; return; } /* clear the multicast filter */ - ib->filter[0] = 0; - ib->filter[2] = 0; - ib->filter[4] = 0; - ib->filter[6] = 0; + *lib_ptr(ib, filter[0], lp->type) = 0; + *lib_ptr(ib, filter[1], lp->type) = 0; + *lib_ptr(ib, filter[2], lp->type) = 0; + *lib_ptr(ib, filter[3], lp->type) = 0; /* Add addresses */ for (i = 0; i < dev->mc_count; i++) { @@ -962,7 +978,7 @@ static void lance_load_multicast(struct net_device *dev) crc = ether_crc_le(ETH_ALEN, addrs); crc = crc >> 26; - mcast_table[2 * (crc >> 4)] |= 1 << (crc & 0xf); + *lib_ptr(ib, filter[crc >> 4], lp->type) |= 1 << (crc & 0xf); } return; } @@ -970,11 +986,9 @@ static void lance_load_multicast(struct net_device *dev) static void lance_set_multicast(struct net_device *dev) { struct lance_private *lp = netdev_priv(dev); - volatile struct lance_init_block *ib; + volatile u16 *ib = (volatile u16 *)dev->mem_start; volatile struct lance_regs *ll = lp->ll; - ib = (struct lance_init_block *) (dev->mem_start); - if (!netif_running(dev)) return; @@ -992,9 +1006,9 @@ static void lance_set_multicast(struct net_device *dev) lance_init_ring(dev); if (dev->flags & IFF_PROMISC) { - ib->mode |= LE_MO_PROM; + *lib_ptr(ib, mode, lp->type) |= LE_MO_PROM; } else { - ib->mode &= ~LE_MO_PROM; + *lib_ptr(ib, mode, lp->type) &= ~LE_MO_PROM; lance_load_multicast(dev); } load_csrs(lp); @@ -1051,7 +1065,6 @@ static int __init dec_lance_init(const int type, const int slot) lp->type = type; lp->slot = slot; switch (type) { -#ifdef CONFIG_TC case ASIC_LANCE: dev->base_addr = CKSEG1ADDR(dec_kn_slot_base + IOASIC_LANCE); @@ -1073,20 +1086,20 @@ static int __init dec_lance_init(const int type, const int slot) */ for (i = 0; i < RX_RING_SIZE; i++) { lp->rx_buf_ptr_cpu[i] = - (char *)(dev->mem_start + BUF_OFFSET_CPU + + (char *)(dev->mem_start + 2 * BUF_OFFSET_CPU + 2 * i * RX_BUFF_SIZE); lp->rx_buf_ptr_lnc[i] = - (char *)(BUF_OFFSET_LNC + i * RX_BUFF_SIZE); + (BUF_OFFSET_LNC + i * RX_BUFF_SIZE); } for (i = 0; i < TX_RING_SIZE; i++) { lp->tx_buf_ptr_cpu[i] = - (char *)(dev->mem_start + BUF_OFFSET_CPU + + (char *)(dev->mem_start + 2 * BUF_OFFSET_CPU + 2 * RX_RING_SIZE * RX_BUFF_SIZE + 2 * i * TX_BUFF_SIZE); lp->tx_buf_ptr_lnc[i] = - (char *)(BUF_OFFSET_LNC + - RX_RING_SIZE * RX_BUFF_SIZE + - i * TX_BUFF_SIZE); + (BUF_OFFSET_LNC + + RX_RING_SIZE * RX_BUFF_SIZE + + i * TX_BUFF_SIZE); } /* Setup I/O ASIC LANCE DMA. */ @@ -1095,11 +1108,12 @@ static int __init dec_lance_init(const int type, const int slot) CPHYSADDR(dev->mem_start) << 3); break; - +#ifdef CONFIG_TC case PMAD_LANCE: claim_tc_card(slot); dev->mem_start = CKSEG1ADDR(get_tc_base_addr(slot)); + dev->mem_end = dev->mem_start + 0x100000; dev->base_addr = dev->mem_start + 0x100000; dev->irq = get_tc_irq_nr(slot); esar_base = dev->mem_start + 0x1c0002; @@ -1110,7 +1124,7 @@ static int __init dec_lance_init(const int type, const int slot) (char *)(dev->mem_start + BUF_OFFSET_CPU + i * RX_BUFF_SIZE); lp->rx_buf_ptr_lnc[i] = - (char *)(BUF_OFFSET_LNC + i * RX_BUFF_SIZE); + (BUF_OFFSET_LNC + i * RX_BUFF_SIZE); } for (i = 0; i < TX_RING_SIZE; i++) { lp->tx_buf_ptr_cpu[i] = @@ -1118,18 +1132,18 @@ static int __init dec_lance_init(const int type, const int slot) RX_RING_SIZE * RX_BUFF_SIZE + i * TX_BUFF_SIZE); lp->tx_buf_ptr_lnc[i] = - (char *)(BUF_OFFSET_LNC + - RX_RING_SIZE * RX_BUFF_SIZE + - i * TX_BUFF_SIZE); + (BUF_OFFSET_LNC + + RX_RING_SIZE * RX_BUFF_SIZE + + i * TX_BUFF_SIZE); } break; #endif - case PMAX_LANCE: dev->irq = dec_interrupt[DEC_IRQ_LANCE]; dev->base_addr = CKSEG1ADDR(KN01_SLOT_BASE + KN01_LANCE); dev->mem_start = CKSEG1ADDR(KN01_SLOT_BASE + KN01_LANCE_MEM); + dev->mem_end = dev->mem_start + KN01_SLOT_SIZE; esar_base = CKSEG1ADDR(KN01_SLOT_BASE + KN01_ESAR + 1); lp->dma_irq = -1; @@ -1138,20 +1152,20 @@ static int __init dec_lance_init(const int type, const int slot) */ for (i = 0; i < RX_RING_SIZE; i++) { lp->rx_buf_ptr_cpu[i] = - (char *)(dev->mem_start + BUF_OFFSET_CPU + + (char *)(dev->mem_start + 2 * BUF_OFFSET_CPU + 2 * i * RX_BUFF_SIZE); lp->rx_buf_ptr_lnc[i] = - (char *)(BUF_OFFSET_LNC + i * RX_BUFF_SIZE); + (BUF_OFFSET_LNC + i * RX_BUFF_SIZE); } for (i = 0; i < TX_RING_SIZE; i++) { lp->tx_buf_ptr_cpu[i] = - (char *)(dev->mem_start + BUF_OFFSET_CPU + + (char *)(dev->mem_start + 2 * BUF_OFFSET_CPU + 2 * RX_RING_SIZE * RX_BUFF_SIZE + 2 * i * TX_BUFF_SIZE); lp->tx_buf_ptr_lnc[i] = - (char *)(BUF_OFFSET_LNC + - RX_RING_SIZE * RX_BUFF_SIZE + - i * TX_BUFF_SIZE); + (BUF_OFFSET_LNC + + RX_RING_SIZE * RX_BUFF_SIZE + + i * TX_BUFF_SIZE); } break; @@ -1279,10 +1293,8 @@ static int __init dec_lance_probe(void) /* Then handle onboard devices. */ if (dec_interrupt[DEC_IRQ_LANCE] >= 0) { if (dec_interrupt[DEC_IRQ_LANCE_MERR] >= 0) { -#ifdef CONFIG_TC if (dec_lance_init(ASIC_LANCE, -1) >= 0) count++; -#endif } else if (!TURBOCHANNEL) { if (dec_lance_init(PMAX_LANCE, -1) >= 0) count++; diff --git a/trunk/drivers/net/e100.c b/trunk/drivers/net/e100.c index 3a8df479cbda..03bf164f9e8d 100644 --- a/trunk/drivers/net/e100.c +++ b/trunk/drivers/net/e100.c @@ -2102,9 +2102,10 @@ static void e100_tx_timeout(struct net_device *netdev) schedule_work(&nic->tx_timeout_task); } -static void e100_tx_timeout_task(struct net_device *netdev) +static void e100_tx_timeout_task(struct work_struct *work) { - struct nic *nic = netdev_priv(netdev); + struct nic *nic = container_of(work, struct nic, tx_timeout_task); + struct net_device *netdev = nic->netdev; DPRINTK(TX_ERR, DEBUG, "scb.status=0x%02X\n", readb(&nic->csr->scb.status)); @@ -2637,8 +2638,7 @@ static int __devinit e100_probe(struct pci_dev *pdev, nic->blink_timer.function = e100_blink_led; nic->blink_timer.data = (unsigned long)nic; - INIT_WORK(&nic->tx_timeout_task, - (void (*)(void *))e100_tx_timeout_task, netdev); + INIT_WORK(&nic->tx_timeout_task, e100_tx_timeout_task); if((err = e100_alloc(nic))) { DPRINTK(PROBE, ERR, "Cannot alloc driver memory, aborting.\n"); diff --git a/trunk/drivers/net/e1000/e1000_main.c b/trunk/drivers/net/e1000/e1000_main.c index 32dde0adb683..73f3a85fd238 100644 --- a/trunk/drivers/net/e1000/e1000_main.c +++ b/trunk/drivers/net/e1000/e1000_main.c @@ -190,7 +190,7 @@ void e1000_set_ethtool_ops(struct net_device *netdev); static void e1000_enter_82542_rst(struct e1000_adapter *adapter); static void e1000_leave_82542_rst(struct e1000_adapter *adapter); static void e1000_tx_timeout(struct net_device *dev); -static void e1000_reset_task(struct net_device *dev); +static void e1000_reset_task(struct work_struct *work); static void e1000_smartspeed(struct e1000_adapter *adapter); static int e1000_82547_fifo_workaround(struct e1000_adapter *adapter, struct sk_buff *skb); @@ -914,8 +914,7 @@ e1000_probe(struct pci_dev *pdev, adapter->phy_info_timer.function = &e1000_update_phy_info; adapter->phy_info_timer.data = (unsigned long) adapter; - INIT_WORK(&adapter->reset_task, - (void (*)(void *))e1000_reset_task, netdev); + INIT_WORK(&adapter->reset_task, e1000_reset_task); e1000_check_options(adapter); @@ -3306,9 +3305,10 @@ e1000_tx_timeout(struct net_device *netdev) } static void -e1000_reset_task(struct net_device *netdev) +e1000_reset_task(struct work_struct *work) { - struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_adapter *adapter = + container_of(work, struct e1000_adapter, reset_task); e1000_reinit_locked(adapter); } diff --git a/trunk/drivers/net/e2100.c b/trunk/drivers/net/e2100.c index d39e8480ca56..c62d9c6363c6 100644 --- a/trunk/drivers/net/e2100.c +++ b/trunk/drivers/net/e2100.c @@ -463,7 +463,7 @@ static void cleanup_card(struct net_device *dev) release_region(dev->base_addr, E21_IO_EXTENT); } -void +void __exit cleanup_module(void) { int this_dev; diff --git a/trunk/drivers/net/eepro.c b/trunk/drivers/net/eepro.c index a4eb0dc99ecf..b4463094c93a 100644 --- a/trunk/drivers/net/eepro.c +++ b/trunk/drivers/net/eepro.c @@ -1827,7 +1827,7 @@ int __init init_module(void) return n_eepro ? 0 : -ENODEV; } -void +void __exit cleanup_module(void) { int i; diff --git a/trunk/drivers/net/eexpress.c b/trunk/drivers/net/eexpress.c index e14be020e562..4a50fcb5ad6b 100644 --- a/trunk/drivers/net/eexpress.c +++ b/trunk/drivers/net/eexpress.c @@ -1719,7 +1719,7 @@ int __init init_module(void) return -ENXIO; } -void cleanup_module(void) +void __exit cleanup_module(void) { int this_dev; diff --git a/trunk/drivers/net/ehea/ehea_main.c b/trunk/drivers/net/ehea/ehea_main.c index 6ad696101418..83fa32f72398 100644 --- a/trunk/drivers/net/ehea/ehea_main.c +++ b/trunk/drivers/net/ehea/ehea_main.c @@ -2224,11 +2224,12 @@ static int ehea_stop(struct net_device *dev) return ret; } -static void ehea_reset_port(void *data) +static void ehea_reset_port(struct work_struct *work) { int ret; - struct net_device *dev = data; - struct ehea_port *port = netdev_priv(dev); + struct ehea_port *port = + container_of(work, struct ehea_port, reset_task); + struct net_device *dev = port->netdev; port->resets++; down(&port->port_lock); @@ -2379,7 +2380,7 @@ static int ehea_setup_single_port(struct ehea_port *port, dev->tx_timeout = &ehea_tx_watchdog; dev->watchdog_timeo = EHEA_WATCH_DOG_TIMEOUT; - INIT_WORK(&port->reset_task, ehea_reset_port, dev); + INIT_WORK(&port->reset_task, ehea_reset_port); ehea_set_ethtool_ops(dev); diff --git a/trunk/drivers/net/es3210.c b/trunk/drivers/net/es3210.c index fd7b32a24ea4..2d2ea94a00bb 100644 --- a/trunk/drivers/net/es3210.c +++ b/trunk/drivers/net/es3210.c @@ -455,7 +455,7 @@ static void cleanup_card(struct net_device *dev) iounmap(ei_status.mem); } -void +void __exit cleanup_module(void) { int this_dev; diff --git a/trunk/drivers/net/eth16i.c b/trunk/drivers/net/eth16i.c index b7b8bc2a6307..93283e386f3a 100644 --- a/trunk/drivers/net/eth16i.c +++ b/trunk/drivers/net/eth16i.c @@ -1475,7 +1475,7 @@ int __init init_module(void) return -ENXIO; } -void cleanup_module(void) +void __exit cleanup_module(void) { int this_dev; diff --git a/trunk/drivers/net/hamradio/baycom_epp.c b/trunk/drivers/net/hamradio/baycom_epp.c index 1ed9cccd3c11..3c33d6f6a6a6 100644 --- a/trunk/drivers/net/hamradio/baycom_epp.c +++ b/trunk/drivers/net/hamradio/baycom_epp.c @@ -168,8 +168,9 @@ struct baycom_state { int magic; struct pardevice *pdev; + struct net_device *dev; unsigned int work_running; - struct work_struct run_work; + struct delayed_work run_work; unsigned int modem; unsigned int bitrate; unsigned char stat; @@ -659,16 +660,18 @@ static int receive(struct net_device *dev, int cnt) #define GETTICK(x) #endif /* __i386__ */ -static void epp_bh(struct net_device *dev) +static void epp_bh(struct work_struct *work) { + struct net_device *dev; struct baycom_state *bc; struct parport *pp; unsigned char stat; unsigned char tmp[2]; unsigned int time1 = 0, time2 = 0, time3 = 0; int cnt, cnt2; - - bc = netdev_priv(dev); + + bc = container_of(work, struct baycom_state, run_work.work); + dev = bc->dev; if (!bc->work_running) return; baycom_int_freq(bc); @@ -889,7 +892,7 @@ static int epp_open(struct net_device *dev) return -EBUSY; } dev->irq = /*pp->irq*/ 0; - INIT_WORK(&bc->run_work, (void *)(void *)epp_bh, dev); + INIT_DELAYED_WORK(&bc->run_work, epp_bh); bc->work_running = 1; bc->modem = EPP_CONVENTIONAL; if (eppconfig(bc)) @@ -1213,6 +1216,7 @@ static void __init baycom_epp_dev_setup(struct net_device *dev) /* * initialize part of the baycom_state struct */ + bc->dev = dev; bc->magic = BAYCOM_MAGIC; bc->cfg.fclk = 19666600; bc->cfg.bps = 9600; diff --git a/trunk/drivers/net/hamradio/dmascc.c b/trunk/drivers/net/hamradio/dmascc.c index 0f8b9afd55b4..e6e721aff6f6 100644 --- a/trunk/drivers/net/hamradio/dmascc.c +++ b/trunk/drivers/net/hamradio/dmascc.c @@ -252,7 +252,7 @@ static inline void z8530_isr(struct scc_info *info); static irqreturn_t scc_isr(int irq, void *dev_id); static void rx_isr(struct scc_priv *priv); static void special_condition(struct scc_priv *priv, int rc); -static void rx_bh(void *arg); +static void rx_bh(struct work_struct *); static void tx_isr(struct scc_priv *priv); static void es_isr(struct scc_priv *priv); static void tm_isr(struct scc_priv *priv); @@ -579,7 +579,7 @@ static int __init setup_adapter(int card_base, int type, int n) priv->param.clocks = TCTRxCP | RCRTxCP; priv->param.persist = 256; priv->param.dma = -1; - INIT_WORK(&priv->rx_work, rx_bh, priv); + INIT_WORK(&priv->rx_work, rx_bh); dev->priv = priv; sprintf(dev->name, "dmascc%i", 2 * n + i); dev->base_addr = card_base; @@ -1272,9 +1272,9 @@ static void special_condition(struct scc_priv *priv, int rc) } -static void rx_bh(void *arg) +static void rx_bh(struct work_struct *ugli_api) { - struct scc_priv *priv = arg; + struct scc_priv *priv = container_of(ugli_api, struct scc_priv, rx_work); int i = priv->rx_tail; int cb; unsigned long flags; diff --git a/trunk/drivers/net/hp-plus.c b/trunk/drivers/net/hp-plus.c index 6abcfd2a4b28..99a36cc3f8df 100644 --- a/trunk/drivers/net/hp-plus.c +++ b/trunk/drivers/net/hp-plus.c @@ -482,7 +482,7 @@ static void cleanup_card(struct net_device *dev) release_region(dev->base_addr - NIC_OFFSET, HP_IO_EXTENT); } -void +void __exit cleanup_module(void) { int this_dev; diff --git a/trunk/drivers/net/hp.c b/trunk/drivers/net/hp.c index 29470970aa27..635b13c2e2aa 100644 --- a/trunk/drivers/net/hp.c +++ b/trunk/drivers/net/hp.c @@ -444,7 +444,7 @@ static void cleanup_card(struct net_device *dev) release_region(dev->base_addr - NIC_OFFSET, HP_IO_EXTENT); } -void +void __exit cleanup_module(void) { int this_dev; diff --git a/trunk/drivers/net/irda/irtty-sir.c b/trunk/drivers/net/irda/irtty-sir.c index 6a98b7ae4975..ad1857364d51 100644 --- a/trunk/drivers/net/irda/irtty-sir.c +++ b/trunk/drivers/net/irda/irtty-sir.c @@ -117,7 +117,7 @@ static int irtty_change_speed(struct sir_dev *dev, unsigned speed) { struct sirtty_cb *priv = dev->priv; struct tty_struct *tty; - struct termios old_termios; + struct ktermios old_termios; int cflag; IRDA_ASSERT(priv != NULL, return -1;); @@ -318,7 +318,7 @@ static void irtty_write_wakeup(struct tty_struct *tty) static inline void irtty_stop_receiver(struct tty_struct *tty, int stop) { - struct termios old_termios; + struct ktermios old_termios; int cflag; lock_kernel(); diff --git a/trunk/drivers/net/irda/mcs7780.c b/trunk/drivers/net/irda/mcs7780.c index b32c52ed19d7..f0c61f3b2a82 100644 --- a/trunk/drivers/net/irda/mcs7780.c +++ b/trunk/drivers/net/irda/mcs7780.c @@ -560,9 +560,9 @@ static inline int mcs_find_endpoints(struct mcs_cb *mcs, return ret; } -static void mcs_speed_work(void *arg) +static void mcs_speed_work(struct work_struct *work) { - struct mcs_cb *mcs = arg; + struct mcs_cb *mcs = container_of(work, struct mcs_cb, work); struct net_device *netdev = mcs->netdev; mcs_speed_change(mcs); @@ -927,7 +927,7 @@ static int mcs_probe(struct usb_interface *intf, irda_qos_bits_to_value(&mcs->qos); /* Speed change work initialisation*/ - INIT_WORK(&mcs->work, mcs_speed_work, mcs); + INIT_WORK(&mcs->work, mcs_speed_work); /* Override the network functions we need to use */ ndev->hard_start_xmit = mcs_hard_xmit; diff --git a/trunk/drivers/net/irda/pxaficp_ir.c b/trunk/drivers/net/irda/pxaficp_ir.c index f9a1c88a4283..9137e239fac2 100644 --- a/trunk/drivers/net/irda/pxaficp_ir.c +++ b/trunk/drivers/net/irda/pxaficp_ir.c @@ -704,9 +704,9 @@ static int pxa_irda_stop(struct net_device *dev) return 0; } -static int pxa_irda_suspend(struct device *_dev, pm_message_t state) +static int pxa_irda_suspend(struct platform_device *_dev, pm_message_t state) { - struct net_device *dev = dev_get_drvdata(_dev); + struct net_device *dev = platform_get_drvdata(_dev); struct pxa_irda *si; if (dev && netif_running(dev)) { @@ -718,9 +718,9 @@ static int pxa_irda_suspend(struct device *_dev, pm_message_t state) return 0; } -static int pxa_irda_resume(struct device *_dev) +static int pxa_irda_resume(struct platform_device *_dev) { - struct net_device *dev = dev_get_drvdata(_dev); + struct net_device *dev = platform_get_drvdata(_dev); struct pxa_irda *si; if (dev && netif_running(dev)) { @@ -746,9 +746,8 @@ static int pxa_irda_init_iobuf(iobuff_t *io, int size) return io->head ? 0 : -ENOMEM; } -static int pxa_irda_probe(struct device *_dev) +static int pxa_irda_probe(struct platform_device *pdev) { - struct platform_device *pdev = to_platform_device(_dev); struct net_device *dev; struct pxa_irda *si; unsigned int baudrate_mask; @@ -822,9 +821,9 @@ static int pxa_irda_probe(struct device *_dev) return err; } -static int pxa_irda_remove(struct device *_dev) +static int pxa_irda_remove(struct platform_device *_dev) { - struct net_device *dev = dev_get_drvdata(_dev); + struct net_device *dev = platform_get_drvdata(_dev); if (dev) { struct pxa_irda *si = netdev_priv(dev); @@ -840,9 +839,10 @@ static int pxa_irda_remove(struct device *_dev) return 0; } -static struct device_driver pxa_ir_driver = { - .name = "pxa2xx-ir", - .bus = &platform_bus_type, +static struct platform_driver pxa_ir_driver = { + .driver = { + .name = "pxa2xx-ir", + }, .probe = pxa_irda_probe, .remove = pxa_irda_remove, .suspend = pxa_irda_suspend, @@ -851,12 +851,12 @@ static struct device_driver pxa_ir_driver = { static int __init pxa_irda_init(void) { - return driver_register(&pxa_ir_driver); + return platform_driver_register(&pxa_ir_driver); } static void __exit pxa_irda_exit(void) { - driver_unregister(&pxa_ir_driver); + platform_driver_unregister(&pxa_ir_driver); } module_init(pxa_irda_init); diff --git a/trunk/drivers/net/irda/sir-dev.h b/trunk/drivers/net/irda/sir-dev.h index 9fa294a546d6..2a57bc67ce35 100644 --- a/trunk/drivers/net/irda/sir-dev.h +++ b/trunk/drivers/net/irda/sir-dev.h @@ -22,7 +22,7 @@ struct sir_fsm { struct semaphore sem; - struct work_struct work; + struct delayed_work work; unsigned state, substate; int param; int result; diff --git a/trunk/drivers/net/irda/sir_dev.c b/trunk/drivers/net/irda/sir_dev.c index 3b5854d10c17..17b0c3ab6201 100644 --- a/trunk/drivers/net/irda/sir_dev.c +++ b/trunk/drivers/net/irda/sir_dev.c @@ -100,9 +100,9 @@ static int sirdev_tx_complete_fsm(struct sir_dev *dev) * Both must be unlocked/restarted on completion - but only on final exit. */ -static void sirdev_config_fsm(void *data) +static void sirdev_config_fsm(struct work_struct *work) { - struct sir_dev *dev = data; + struct sir_dev *dev = container_of(work, struct sir_dev, fsm.work.work); struct sir_fsm *fsm = &dev->fsm; int next_state; int ret = -1; @@ -309,8 +309,8 @@ int sirdev_schedule_request(struct sir_dev *dev, int initial_state, unsigned par fsm->param = param; fsm->result = 0; - INIT_WORK(&fsm->work, sirdev_config_fsm, dev); - queue_work(irda_sir_wq, &fsm->work); + INIT_DELAYED_WORK(&fsm->work, sirdev_config_fsm); + queue_delayed_work(irda_sir_wq, &fsm->work, 0); return 0; } diff --git a/trunk/drivers/net/irda/stir4200.c b/trunk/drivers/net/irda/stir4200.c index 3b4c47875935..c14a74634fd5 100644 --- a/trunk/drivers/net/irda/stir4200.c +++ b/trunk/drivers/net/irda/stir4200.c @@ -50,6 +50,7 @@ #include #include #include +#include #include #include #include diff --git a/trunk/drivers/net/iseries_veth.c b/trunk/drivers/net/iseries_veth.c index 2284e2ce1692..d6f4f185bf37 100644 --- a/trunk/drivers/net/iseries_veth.c +++ b/trunk/drivers/net/iseries_veth.c @@ -166,7 +166,7 @@ struct veth_msg { struct veth_lpar_connection { HvLpIndex remote_lp; - struct work_struct statemachine_wq; + struct delayed_work statemachine_wq; struct veth_msg *msgs; int num_events; struct veth_cap_data local_caps; @@ -456,7 +456,7 @@ static struct kobj_type veth_port_ktype = { static inline void veth_kick_statemachine(struct veth_lpar_connection *cnx) { - schedule_work(&cnx->statemachine_wq); + schedule_delayed_work(&cnx->statemachine_wq, 0); } static void veth_take_cap(struct veth_lpar_connection *cnx, @@ -638,9 +638,11 @@ static int veth_process_caps(struct veth_lpar_connection *cnx) } /* FIXME: The gotos here are a bit dubious */ -static void veth_statemachine(void *p) +static void veth_statemachine(struct work_struct *work) { - struct veth_lpar_connection *cnx = (struct veth_lpar_connection *)p; + struct veth_lpar_connection *cnx = + container_of(work, struct veth_lpar_connection, + statemachine_wq.work); int rlp = cnx->remote_lp; int rc; @@ -827,7 +829,7 @@ static int veth_init_connection(u8 rlp) cnx->remote_lp = rlp; spin_lock_init(&cnx->lock); - INIT_WORK(&cnx->statemachine_wq, veth_statemachine, cnx); + INIT_DELAYED_WORK(&cnx->statemachine_wq, veth_statemachine); init_timer(&cnx->ack_timer); cnx->ack_timer.function = veth_timed_ack; diff --git a/trunk/drivers/net/ixgb/ixgb_main.c b/trunk/drivers/net/ixgb/ixgb_main.c index 7b127212e62b..e628126c9c49 100644 --- a/trunk/drivers/net/ixgb/ixgb_main.c +++ b/trunk/drivers/net/ixgb/ixgb_main.c @@ -106,7 +106,7 @@ static boolean_t ixgb_clean_rx_irq(struct ixgb_adapter *adapter); static void ixgb_alloc_rx_buffers(struct ixgb_adapter *adapter); void ixgb_set_ethtool_ops(struct net_device *netdev); static void ixgb_tx_timeout(struct net_device *dev); -static void ixgb_tx_timeout_task(struct net_device *dev); +static void ixgb_tx_timeout_task(struct work_struct *work); static void ixgb_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp); static void ixgb_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid); @@ -489,8 +489,7 @@ ixgb_probe(struct pci_dev *pdev, adapter->watchdog_timer.function = &ixgb_watchdog; adapter->watchdog_timer.data = (unsigned long)adapter; - INIT_WORK(&adapter->tx_timeout_task, - (void (*)(void *))ixgb_tx_timeout_task, netdev); + INIT_WORK(&adapter->tx_timeout_task, ixgb_tx_timeout_task); strcpy(netdev->name, "eth%d"); if((err = register_netdev(netdev))) @@ -1493,9 +1492,10 @@ ixgb_tx_timeout(struct net_device *netdev) } static void -ixgb_tx_timeout_task(struct net_device *netdev) +ixgb_tx_timeout_task(struct work_struct *work) { - struct ixgb_adapter *adapter = netdev_priv(netdev); + struct ixgb_adapter *adapter = + container_of(work, struct ixgb_adapter, tx_timeout_task); adapter->tx_timeout_count++; ixgb_down(adapter, TRUE); diff --git a/trunk/drivers/net/lance.c b/trunk/drivers/net/lance.c index 4256c13c73c2..a3843320dbe1 100644 --- a/trunk/drivers/net/lance.c +++ b/trunk/drivers/net/lance.c @@ -368,7 +368,7 @@ static void cleanup_card(struct net_device *dev) kfree(lp); } -void cleanup_module(void) +void __exit cleanup_module(void) { int this_dev; diff --git a/trunk/drivers/net/lasi_82596.c b/trunk/drivers/net/lasi_82596.c index f4d815bca643..ea392f2a5aa2 100644 --- a/trunk/drivers/net/lasi_82596.c +++ b/trunk/drivers/net/lasi_82596.c @@ -119,14 +119,14 @@ #define DEB(x,y) if (i596_debug & (x)) { y; } -#define CHECK_WBACK(addr,len) \ - do { dma_cache_sync((void *)addr, len, DMA_TO_DEVICE); } while (0) +#define CHECK_WBACK(priv, addr,len) \ + do { dma_cache_sync((priv)->dev, (void *)addr, len, DMA_TO_DEVICE); } while (0) -#define CHECK_INV(addr,len) \ - do { dma_cache_sync((void *)addr, len, DMA_FROM_DEVICE); } while(0) +#define CHECK_INV(priv, addr,len) \ + do { dma_cache_sync((priv)->dev, (void *)addr, len, DMA_FROM_DEVICE); } while(0) -#define CHECK_WBACK_INV(addr,len) \ - do { dma_cache_sync((void *)addr, len, DMA_BIDIRECTIONAL); } while (0) +#define CHECK_WBACK_INV(priv, addr,len) \ + do { dma_cache_sync((priv)->dev, (void *)addr, len, DMA_BIDIRECTIONAL); } while (0) #define PA_I82596_RESET 0 /* Offsets relative to LASI-LAN-Addr.*/ @@ -449,10 +449,10 @@ static inline void MPU_PORT(struct net_device *dev, int c, dma_addr_t x) static inline int wait_istat(struct net_device *dev, struct i596_private *lp, int delcnt, char *str) { - CHECK_INV(&(lp->iscp), sizeof(struct i596_iscp)); + CHECK_INV(lp, &(lp->iscp), sizeof(struct i596_iscp)); while (--delcnt && lp->iscp.stat) { udelay(10); - CHECK_INV(&(lp->iscp), sizeof(struct i596_iscp)); + CHECK_INV(lp, &(lp->iscp), sizeof(struct i596_iscp)); } if (!delcnt) { printk("%s: %s, iscp.stat %04x, didn't clear\n", @@ -466,10 +466,10 @@ static inline int wait_istat(struct net_device *dev, struct i596_private *lp, in static inline int wait_cmd(struct net_device *dev, struct i596_private *lp, int delcnt, char *str) { - CHECK_INV(&(lp->scb), sizeof(struct i596_scb)); + CHECK_INV(lp, &(lp->scb), sizeof(struct i596_scb)); while (--delcnt && lp->scb.command) { udelay(10); - CHECK_INV(&(lp->scb), sizeof(struct i596_scb)); + CHECK_INV(lp, &(lp->scb), sizeof(struct i596_scb)); } if (!delcnt) { printk("%s: %s, status %4.4x, cmd %4.4x.\n", @@ -522,7 +522,7 @@ static void i596_display_data(struct net_device *dev) rbd, rbd->count, rbd->b_next, rbd->b_data, rbd->size); rbd = rbd->v_next; } while (rbd != lp->rbd_head); - CHECK_INV(lp, sizeof(struct i596_private)); + CHECK_INV(lp, lp, sizeof(struct i596_private)); } @@ -592,7 +592,7 @@ static inline void init_rx_bufs(struct net_device *dev) rfd->b_next = WSWAPrfd(virt_to_dma(lp,lp->rfds)); rfd->cmd = CMD_EOL|CMD_FLEX; - CHECK_WBACK_INV(lp, sizeof(struct i596_private)); + CHECK_WBACK_INV(lp, lp, sizeof(struct i596_private)); } static inline void remove_rx_bufs(struct net_device *dev) @@ -629,7 +629,7 @@ static void rebuild_rx_bufs(struct net_device *dev) lp->rbd_head = lp->rbds; lp->rfds[0].rbd = WSWAPrbd(virt_to_dma(lp,lp->rbds)); - CHECK_WBACK_INV(lp, sizeof(struct i596_private)); + CHECK_WBACK_INV(lp, lp, sizeof(struct i596_private)); } @@ -663,8 +663,8 @@ static int init_i596_mem(struct net_device *dev) DEB(DEB_INIT, printk("%s: starting i82596.\n", dev->name)); - CHECK_WBACK(&(lp->scp), sizeof(struct i596_scp)); - CHECK_WBACK(&(lp->iscp), sizeof(struct i596_iscp)); + CHECK_WBACK(lp, &(lp->scp), sizeof(struct i596_scp)); + CHECK_WBACK(lp, &(lp->iscp), sizeof(struct i596_iscp)); MPU_PORT(dev, PORT_ALTSCP, virt_to_dma(lp,&lp->scp)); @@ -678,25 +678,25 @@ static int init_i596_mem(struct net_device *dev) rebuild_rx_bufs(dev); lp->scb.command = 0; - CHECK_WBACK(&(lp->scb), sizeof(struct i596_scb)); + CHECK_WBACK(lp, &(lp->scb), sizeof(struct i596_scb)); enable_irq(dev->irq); /* enable IRQs from LAN */ DEB(DEB_INIT, printk("%s: queuing CmdConfigure\n", dev->name)); memcpy(lp->cf_cmd.i596_config, init_setup, 14); lp->cf_cmd.cmd.command = CmdConfigure; - CHECK_WBACK(&(lp->cf_cmd), sizeof(struct cf_cmd)); + CHECK_WBACK(lp, &(lp->cf_cmd), sizeof(struct cf_cmd)); i596_add_cmd(dev, &lp->cf_cmd.cmd); DEB(DEB_INIT, printk("%s: queuing CmdSASetup\n", dev->name)); memcpy(lp->sa_cmd.eth_addr, dev->dev_addr, 6); lp->sa_cmd.cmd.command = CmdSASetup; - CHECK_WBACK(&(lp->sa_cmd), sizeof(struct sa_cmd)); + CHECK_WBACK(lp, &(lp->sa_cmd), sizeof(struct sa_cmd)); i596_add_cmd(dev, &lp->sa_cmd.cmd); DEB(DEB_INIT, printk("%s: queuing CmdTDR\n", dev->name)); lp->tdr_cmd.cmd.command = CmdTDR; - CHECK_WBACK(&(lp->tdr_cmd), sizeof(struct tdr_cmd)); + CHECK_WBACK(lp, &(lp->tdr_cmd), sizeof(struct tdr_cmd)); i596_add_cmd(dev, &lp->tdr_cmd.cmd); spin_lock_irqsave (&lp->lock, flags); @@ -708,7 +708,7 @@ static int init_i596_mem(struct net_device *dev) DEB(DEB_INIT, printk("%s: Issuing RX_START\n", dev->name)); lp->scb.command = RX_START; lp->scb.rfd = WSWAPrfd(virt_to_dma(lp,lp->rfds)); - CHECK_WBACK(&(lp->scb), sizeof(struct i596_scb)); + CHECK_WBACK(lp, &(lp->scb), sizeof(struct i596_scb)); CA(dev); @@ -740,13 +740,13 @@ static inline int i596_rx(struct net_device *dev) rfd = lp->rfd_head; /* Ref next frame to check */ - CHECK_INV(rfd, sizeof(struct i596_rfd)); + CHECK_INV(lp, rfd, sizeof(struct i596_rfd)); while ((rfd->stat) & STAT_C) { /* Loop while complete frames */ if (rfd->rbd == I596_NULL) rbd = NULL; else if (rfd->rbd == lp->rbd_head->b_addr) { rbd = lp->rbd_head; - CHECK_INV(rbd, sizeof(struct i596_rbd)); + CHECK_INV(lp, rbd, sizeof(struct i596_rbd)); } else { printk("%s: rbd chain broken!\n", dev->name); @@ -790,7 +790,7 @@ static inline int i596_rx(struct net_device *dev) dma_addr = dma_map_single(lp->dev, newskb->data, PKT_BUF_SZ, DMA_FROM_DEVICE); rbd->v_data = newskb->data; rbd->b_data = WSWAPchar(dma_addr); - CHECK_WBACK_INV(rbd, sizeof(struct i596_rbd)); + CHECK_WBACK_INV(lp, rbd, sizeof(struct i596_rbd)); } else skb = dev_alloc_skb(pkt_len + 2); @@ -842,7 +842,7 @@ static inline int i596_rx(struct net_device *dev) if (rbd != NULL && (rbd->count & 0x4000)) { rbd->count = 0; lp->rbd_head = rbd->v_next; - CHECK_WBACK_INV(rbd, sizeof(struct i596_rbd)); + CHECK_WBACK_INV(lp, rbd, sizeof(struct i596_rbd)); } /* Tidy the frame descriptor, marking it as end of list */ @@ -860,10 +860,10 @@ static inline int i596_rx(struct net_device *dev) lp->scb.rfd = rfd->b_next; lp->rfd_head = rfd->v_next; - CHECK_WBACK_INV(rfd->v_prev, sizeof(struct i596_rfd)); - CHECK_WBACK_INV(rfd, sizeof(struct i596_rfd)); + CHECK_WBACK_INV(lp, rfd->v_prev, sizeof(struct i596_rfd)); + CHECK_WBACK_INV(lp, rfd, sizeof(struct i596_rfd)); rfd = lp->rfd_head; - CHECK_INV(rfd, sizeof(struct i596_rfd)); + CHECK_INV(lp, rfd, sizeof(struct i596_rfd)); } DEB(DEB_RXFRAME, printk("frames %d\n", frames)); @@ -902,12 +902,12 @@ static inline void i596_cleanup_cmd(struct net_device *dev, struct i596_private ptr->v_next = NULL; ptr->b_next = I596_NULL; } - CHECK_WBACK_INV(ptr, sizeof(struct i596_cmd)); + CHECK_WBACK_INV(lp, ptr, sizeof(struct i596_cmd)); } wait_cmd(dev, lp, 100, "i596_cleanup_cmd timed out"); lp->scb.cmd = I596_NULL; - CHECK_WBACK(&(lp->scb), sizeof(struct i596_scb)); + CHECK_WBACK(lp, &(lp->scb), sizeof(struct i596_scb)); } @@ -925,7 +925,7 @@ static inline void i596_reset(struct net_device *dev, struct i596_private *lp) /* FIXME: this command might cause an lpmc */ lp->scb.command = CUC_ABORT | RX_ABORT; - CHECK_WBACK(&(lp->scb), sizeof(struct i596_scb)); + CHECK_WBACK(lp, &(lp->scb), sizeof(struct i596_scb)); CA(dev); /* wait for shutdown */ @@ -951,20 +951,20 @@ static void i596_add_cmd(struct net_device *dev, struct i596_cmd *cmd) cmd->command |= (CMD_EOL | CMD_INTR); cmd->v_next = NULL; cmd->b_next = I596_NULL; - CHECK_WBACK(cmd, sizeof(struct i596_cmd)); + CHECK_WBACK(lp, cmd, sizeof(struct i596_cmd)); spin_lock_irqsave (&lp->lock, flags); if (lp->cmd_head != NULL) { lp->cmd_tail->v_next = cmd; lp->cmd_tail->b_next = WSWAPcmd(virt_to_dma(lp,&cmd->status)); - CHECK_WBACK(lp->cmd_tail, sizeof(struct i596_cmd)); + CHECK_WBACK(lp, lp->cmd_tail, sizeof(struct i596_cmd)); } else { lp->cmd_head = cmd; wait_cmd(dev, lp, 100, "i596_add_cmd timed out"); lp->scb.cmd = WSWAPcmd(virt_to_dma(lp,&cmd->status)); lp->scb.command = CUC_START; - CHECK_WBACK(&(lp->scb), sizeof(struct i596_scb)); + CHECK_WBACK(lp, &(lp->scb), sizeof(struct i596_scb)); CA(dev); } lp->cmd_tail = cmd; @@ -998,12 +998,12 @@ static int i596_test(struct net_device *dev) data = virt_to_dma(lp,tint); tint[1] = -1; - CHECK_WBACK(tint,PAGE_SIZE); + CHECK_WBACK(lp, tint, PAGE_SIZE); MPU_PORT(dev, 1, data); for(data = 1000000; data; data--) { - CHECK_INV(tint,PAGE_SIZE); + CHECK_INV(lp, tint, PAGE_SIZE); if(tint[1] != -1) break; @@ -1061,7 +1061,7 @@ static void i596_tx_timeout (struct net_device *dev) /* Issue a channel attention signal */ DEB(DEB_ERRORS, printk("Kicking board.\n")); lp->scb.command = CUC_START | RX_START; - CHECK_WBACK_INV(&(lp->scb), sizeof(struct i596_scb)); + CHECK_WBACK_INV(lp, &(lp->scb), sizeof(struct i596_scb)); CA (dev); lp->last_restart = lp->stats.tx_packets; } @@ -1118,8 +1118,8 @@ static int i596_start_xmit(struct sk_buff *skb, struct net_device *dev) tbd->data = WSWAPchar(tx_cmd->dma_addr); DEB(DEB_TXADDR,print_eth(skb->data, "tx-queued")); - CHECK_WBACK_INV(tx_cmd, sizeof(struct tx_cmd)); - CHECK_WBACK_INV(tbd, sizeof(struct i596_tbd)); + CHECK_WBACK_INV(lp, tx_cmd, sizeof(struct tx_cmd)); + CHECK_WBACK_INV(lp, tbd, sizeof(struct i596_tbd)); i596_add_cmd(dev, &tx_cmd->cmd); lp->stats.tx_packets++; @@ -1228,7 +1228,7 @@ static int __devinit i82596_probe(struct net_device *dev, lp->dma_addr = dma_addr; lp->dev = gen_dev; - CHECK_WBACK_INV(dev->mem_start, sizeof(struct i596_private)); + CHECK_WBACK_INV(lp, dev->mem_start, sizeof(struct i596_private)); i = register_netdev(dev); if (i) { @@ -1295,7 +1295,7 @@ static irqreturn_t i596_interrupt(int irq, void *dev_id) DEB(DEB_INTS, printk("%s: i596 interrupt command unit inactive %x.\n", dev->name, status & 0x0700)); while (lp->cmd_head != NULL) { - CHECK_INV(lp->cmd_head, sizeof(struct i596_cmd)); + CHECK_INV(lp, lp->cmd_head, sizeof(struct i596_cmd)); if (!(lp->cmd_head->status & STAT_C)) break; @@ -1358,7 +1358,7 @@ static irqreturn_t i596_interrupt(int irq, void *dev_id) } ptr->v_next = NULL; ptr->b_next = I596_NULL; - CHECK_WBACK(ptr, sizeof(struct i596_cmd)); + CHECK_WBACK(lp, ptr, sizeof(struct i596_cmd)); lp->last_cmd = jiffies; } @@ -1372,13 +1372,13 @@ static irqreturn_t i596_interrupt(int irq, void *dev_id) ptr->command &= 0x1fff; ptr = ptr->v_next; - CHECK_WBACK_INV(prev, sizeof(struct i596_cmd)); + CHECK_WBACK_INV(lp, prev, sizeof(struct i596_cmd)); } if ((lp->cmd_head != NULL)) ack_cmd |= CUC_START; lp->scb.cmd = WSWAPcmd(virt_to_dma(lp,&lp->cmd_head->status)); - CHECK_WBACK_INV(&lp->scb, sizeof(struct i596_scb)); + CHECK_WBACK_INV(lp, &lp->scb, sizeof(struct i596_scb)); } if ((status & 0x1000) || (status & 0x4000)) { if ((status & 0x4000)) @@ -1397,7 +1397,7 @@ static irqreturn_t i596_interrupt(int irq, void *dev_id) } wait_cmd(dev, lp, 100, "i596 interrupt, timeout"); lp->scb.command = ack_cmd; - CHECK_WBACK(&lp->scb, sizeof(struct i596_scb)); + CHECK_WBACK(lp, &lp->scb, sizeof(struct i596_scb)); /* DANGER: I suspect that some kind of interrupt acknowledgement aside from acking the 82596 might be needed @@ -1426,7 +1426,7 @@ static int i596_close(struct net_device *dev) wait_cmd(dev, lp, 100, "close1 timed out"); lp->scb.command = CUC_ABORT | RX_ABORT; - CHECK_WBACK(&lp->scb, sizeof(struct i596_scb)); + CHECK_WBACK(lp, &lp->scb, sizeof(struct i596_scb)); CA(dev); @@ -1486,7 +1486,7 @@ static void set_multicast_list(struct net_device *dev) dev->name); else { lp->cf_cmd.cmd.command = CmdConfigure; - CHECK_WBACK_INV(&lp->cf_cmd, sizeof(struct cf_cmd)); + CHECK_WBACK_INV(lp, &lp->cf_cmd, sizeof(struct cf_cmd)); i596_add_cmd(dev, &lp->cf_cmd.cmd); } } @@ -1514,7 +1514,7 @@ static void set_multicast_list(struct net_device *dev) DEB(DEB_MULTI, printk("%s: Adding address %02x:%02x:%02x:%02x:%02x:%02x\n", dev->name, cp[0],cp[1],cp[2],cp[3],cp[4],cp[5])); } - CHECK_WBACK_INV(&lp->mc_cmd, sizeof(struct mc_cmd)); + CHECK_WBACK_INV(lp, &lp->mc_cmd, sizeof(struct mc_cmd)); i596_add_cmd(dev, &cmd->cmd); } } diff --git a/trunk/drivers/net/lne390.c b/trunk/drivers/net/lne390.c index 5795ee116205..0a08d0c4e7b4 100644 --- a/trunk/drivers/net/lne390.c +++ b/trunk/drivers/net/lne390.c @@ -440,7 +440,7 @@ static void cleanup_card(struct net_device *dev) iounmap(ei_status.mem); } -void cleanup_module(void) +void __exit cleanup_module(void) { int this_dev; diff --git a/trunk/drivers/net/mv643xx_eth.c b/trunk/drivers/net/mv643xx_eth.c index 9997081c6dae..c41ae4286eea 100644 --- a/trunk/drivers/net/mv643xx_eth.c +++ b/trunk/drivers/net/mv643xx_eth.c @@ -277,9 +277,11 @@ static void mv643xx_eth_tx_timeout(struct net_device *dev) * * Actual routine to reset the adapter when a timeout on Tx has occurred */ -static void mv643xx_eth_tx_timeout_task(struct net_device *dev) +static void mv643xx_eth_tx_timeout_task(struct work_struct *ugly) { - struct mv643xx_private *mp = netdev_priv(dev); + struct mv643xx_private *mp = container_of(ugly, struct mv643xx_private, + tx_timeout_task); + struct net_device *dev = mp->mii.dev; /* yuck */ if (!netif_running(dev)) return; @@ -1098,7 +1100,7 @@ static void eth_tx_fill_frag_descs(struct mv643xx_private *mp, ETH_TX_ENABLE_INTERRUPT; mp->tx_skb[tx_index] = skb; } else - mp->tx_skb[tx_index] = 0; + mp->tx_skb[tx_index] = NULL; desc = &mp->p_tx_desc_area[tx_index]; desc->l4i_chk = 0; @@ -1134,7 +1136,7 @@ static void eth_tx_submit_descs_for_skb(struct mv643xx_private *mp, eth_tx_fill_frag_descs(mp, skb); length = skb_headlen(skb); - mp->tx_skb[tx_index] = 0; + mp->tx_skb[tx_index] = NULL; } else { cmd_sts |= ETH_ZERO_PADDING | ETH_TX_LAST_DESC | @@ -1360,8 +1362,7 @@ static int mv643xx_eth_probe(struct platform_device *pdev) #endif /* Configure the timeout task */ - INIT_WORK(&mp->tx_timeout_task, - (void (*)(void *))mv643xx_eth_tx_timeout_task, dev); + INIT_WORK(&mp->tx_timeout_task, mv643xx_eth_tx_timeout_task); spin_lock_init(&mp->lock); diff --git a/trunk/drivers/net/mvme147.c b/trunk/drivers/net/mvme147.c index 56a82d8ee8f5..e246d00bba6d 100644 --- a/trunk/drivers/net/mvme147.c +++ b/trunk/drivers/net/mvme147.c @@ -184,7 +184,7 @@ static int m147lance_close(struct net_device *dev) MODULE_LICENSE("GPL"); static struct net_device *dev_mvme147_lance; -int init_module(void) +int __init init_module(void) { dev_mvme147_lance = mvme147lance_probe(-1); if (IS_ERR(dev_mvme147_lance)) @@ -192,7 +192,7 @@ int init_module(void) return 0; } -void cleanup_module(void) +void __exit cleanup_module(void) { struct m147lance_private *lp = dev_mvme147_lance->priv; unregister_netdev(dev_mvme147_lance); diff --git a/trunk/drivers/net/myri10ge/myri10ge.c b/trunk/drivers/net/myri10ge/myri10ge.c index 36350e6db1c1..81f127a78afa 100644 --- a/trunk/drivers/net/myri10ge/myri10ge.c +++ b/trunk/drivers/net/myri10ge/myri10ge.c @@ -89,7 +89,7 @@ MODULE_LICENSE("Dual BSD/GPL"); #define MYRI10GE_EEPROM_STRINGS_SIZE 256 #define MYRI10GE_MAX_SEND_DESC_TSO ((65536 / 2048) * 2) -#define MYRI10GE_NO_CONFIRM_DATA 0xffffffff +#define MYRI10GE_NO_CONFIRM_DATA htonl(0xffffffff) #define MYRI10GE_NO_RESPONSE_RESULT 0xffffffff struct myri10ge_rx_buffer_state { @@ -156,8 +156,8 @@ struct myri10ge_priv { int sram_size; unsigned long board_span; unsigned long iomem_base; - u32 __iomem *irq_claim; - u32 __iomem *irq_deassert; + __be32 __iomem *irq_claim; + __be32 __iomem *irq_deassert; char *mac_addr_string; struct mcp_cmd_response *cmd; dma_addr_t cmd_bus; @@ -165,10 +165,10 @@ struct myri10ge_priv { dma_addr_t fw_stats_bus; struct pci_dev *pdev; int msi_enabled; - unsigned int link_state; + __be32 link_state; unsigned int rdma_tags_available; int intr_coal_delay; - u32 __iomem *intr_coal_delay_ptr; + __be32 __iomem *intr_coal_delay_ptr; int mtrr; int wake_queue; int stop_queue; @@ -273,6 +273,11 @@ MODULE_PARM_DESC(myri10ge_debug, "Debug level (0=none,...,16=all)"); #define myri10ge_pio_copy(to,from,size) __iowrite64_copy(to,from,size/8) +static inline void put_be32(__be32 val, __be32 __iomem *p) +{ + __raw_writel((__force __u32)val, (__force void __iomem *)p); +} + static int myri10ge_send_cmd(struct myri10ge_priv *mgp, u32 cmd, struct myri10ge_cmd *data, int atomic) @@ -296,7 +301,7 @@ myri10ge_send_cmd(struct myri10ge_priv *mgp, u32 cmd, buf->response_addr.low = htonl(dma_low); buf->response_addr.high = htonl(dma_high); - response->result = MYRI10GE_NO_RESPONSE_RESULT; + response->result = htonl(MYRI10GE_NO_RESPONSE_RESULT); mb(); myri10ge_pio_copy(cmd_addr, buf, sizeof(*buf)); @@ -311,14 +316,14 @@ myri10ge_send_cmd(struct myri10ge_priv *mgp, u32 cmd, * (1ms will be enough for those commands) */ for (sleep_total = 0; sleep_total < 1000 - && response->result == MYRI10GE_NO_RESPONSE_RESULT; + && response->result == htonl(MYRI10GE_NO_RESPONSE_RESULT); sleep_total += 10) udelay(10); } else { /* use msleep for most command */ for (sleep_total = 0; sleep_total < 15 - && response->result == MYRI10GE_NO_RESPONSE_RESULT; + && response->result == htonl(MYRI10GE_NO_RESPONSE_RESULT); sleep_total++) msleep(1); } @@ -393,7 +398,7 @@ static int myri10ge_read_mac_addr(struct myri10ge_priv *mgp) static void myri10ge_dummy_rdma(struct myri10ge_priv *mgp, int enable) { char __iomem *submit; - u32 buf[16]; + __be32 buf[16]; u32 dma_low, dma_high; int i; @@ -410,7 +415,7 @@ static void myri10ge_dummy_rdma(struct myri10ge_priv *mgp, int enable) buf[0] = htonl(dma_high); /* confirm addr MSW */ buf[1] = htonl(dma_low); /* confirm addr LSW */ - buf[2] = htonl(MYRI10GE_NO_CONFIRM_DATA); /* confirm data */ + buf[2] = MYRI10GE_NO_CONFIRM_DATA; /* confirm data */ buf[3] = htonl(dma_high); /* dummy addr MSW */ buf[4] = htonl(dma_low); /* dummy addr LSW */ buf[5] = htonl(enable); /* enable? */ @@ -479,7 +484,7 @@ static int myri10ge_load_hotplug_firmware(struct myri10ge_priv *mgp, u32 * size) } /* check id */ - hdr_offset = ntohl(*(u32 *) (fw->data + MCP_HEADER_PTR_OFFSET)); + hdr_offset = ntohl(*(__be32 *) (fw->data + MCP_HEADER_PTR_OFFSET)); if ((hdr_offset & 3) || hdr_offset + sizeof(*hdr) > fw->size) { dev_err(dev, "Bad firmware file\n"); status = -EINVAL; @@ -550,7 +555,7 @@ static int myri10ge_adopt_running_firmware(struct myri10ge_priv *mgp) static int myri10ge_load_firmware(struct myri10ge_priv *mgp) { char __iomem *submit; - u32 buf[16]; + __be32 buf[16]; u32 dma_low, dma_high, size; int status, i; @@ -600,7 +605,7 @@ static int myri10ge_load_firmware(struct myri10ge_priv *mgp) buf[0] = htonl(dma_high); /* confirm addr MSW */ buf[1] = htonl(dma_low); /* confirm addr LSW */ - buf[2] = htonl(MYRI10GE_NO_CONFIRM_DATA); /* confirm data */ + buf[2] = MYRI10GE_NO_CONFIRM_DATA; /* confirm data */ /* FIX: All newest firmware should un-protect the bottom of * the sram before handoff. However, the very first interfaces @@ -705,21 +710,21 @@ static int myri10ge_reset(struct myri10ge_priv *mgp) status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_IRQ_ACK_OFFSET, &cmd, 0); - mgp->irq_claim = (__iomem u32 *) (mgp->sram + cmd.data0); + mgp->irq_claim = (__iomem __be32 *) (mgp->sram + cmd.data0); if (!mgp->msi_enabled) { status |= myri10ge_send_cmd (mgp, MXGEFW_CMD_GET_IRQ_DEASSERT_OFFSET, &cmd, 0); - mgp->irq_deassert = (__iomem u32 *) (mgp->sram + cmd.data0); + mgp->irq_deassert = (__iomem __be32 *) (mgp->sram + cmd.data0); } status |= myri10ge_send_cmd (mgp, MXGEFW_CMD_GET_INTR_COAL_DELAY_OFFSET, &cmd, 0); - mgp->intr_coal_delay_ptr = (__iomem u32 *) (mgp->sram + cmd.data0); + mgp->intr_coal_delay_ptr = (__iomem __be32 *) (mgp->sram + cmd.data0); if (status != 0) { dev_err(&mgp->pdev->dev, "failed set interrupt parameters\n"); return status; } - __raw_writel(htonl(mgp->intr_coal_delay), mgp->intr_coal_delay_ptr); + put_be32(htonl(mgp->intr_coal_delay), mgp->intr_coal_delay_ptr); /* Run a small DMA test. * The magic multipliers to the length tell the firmware @@ -786,14 +791,16 @@ static inline void myri10ge_submit_8rx(struct mcp_kreq_ether_recv __iomem * dst, struct mcp_kreq_ether_recv *src) { - u32 low; + __be32 low; low = src->addr_low; - src->addr_low = DMA_32BIT_MASK; - myri10ge_pio_copy(dst, src, 8 * sizeof(*src)); + src->addr_low = htonl(DMA_32BIT_MASK); + myri10ge_pio_copy(dst, src, 4 * sizeof(*src)); + mb(); + myri10ge_pio_copy(dst + 4, src + 4, 4 * sizeof(*src)); mb(); src->addr_low = low; - __raw_writel(low, &dst->addr_low); + put_be32(low, &dst->addr_low); mb(); } @@ -939,11 +946,11 @@ myri10ge_getbuf(struct myri10ge_rx_buf *rx, struct myri10ge_priv *mgp, return retval; } -static inline void myri10ge_vlan_ip_csum(struct sk_buff *skb, u16 hw_csum) +static inline void myri10ge_vlan_ip_csum(struct sk_buff *skb, __wsum hw_csum) { struct vlan_hdr *vh = (struct vlan_hdr *)(skb->data); - if ((skb->protocol == ntohs(ETH_P_8021Q)) && + if ((skb->protocol == htons(ETH_P_8021Q)) && (vh->h_vlan_encapsulated_proto == htons(ETH_P_IP) || vh->h_vlan_encapsulated_proto == htons(ETH_P_IPV6))) { skb->csum = hw_csum; @@ -953,7 +960,7 @@ static inline void myri10ge_vlan_ip_csum(struct sk_buff *skb, u16 hw_csum) static inline unsigned long myri10ge_rx_done(struct myri10ge_priv *mgp, struct myri10ge_rx_buf *rx, - int bytes, int len, int csum) + int bytes, int len, __wsum csum) { dma_addr_t bus; struct sk_buff *skb; @@ -986,12 +993,12 @@ myri10ge_rx_done(struct myri10ge_priv *mgp, struct myri10ge_rx_buf *rx, skb->protocol = eth_type_trans(skb, mgp->dev); if (mgp->csum_flag) { - if ((skb->protocol == ntohs(ETH_P_IP)) || - (skb->protocol == ntohs(ETH_P_IPV6))) { - skb->csum = ntohs((u16) csum); + if ((skb->protocol == htons(ETH_P_IP)) || + (skb->protocol == htons(ETH_P_IPV6))) { + skb->csum = csum; skb->ip_summed = CHECKSUM_COMPLETE; } else - myri10ge_vlan_ip_csum(skb, ntohs((u16) csum)); + myri10ge_vlan_ip_csum(skb, csum); } netif_receive_skb(skb); @@ -1060,12 +1067,12 @@ static inline void myri10ge_clean_rx_done(struct myri10ge_priv *mgp, int *limit) int idx = rx_done->idx; int cnt = rx_done->cnt; u16 length; - u16 checksum; + __wsum checksum; while (rx_done->entry[idx].length != 0 && *limit != 0) { length = ntohs(rx_done->entry[idx].length); rx_done->entry[idx].length = 0; - checksum = ntohs(rx_done->entry[idx].checksum); + checksum = csum_unfold(rx_done->entry[idx].checksum); if (length <= mgp->small_bytes) rx_ok = myri10ge_rx_done(mgp, &mgp->rx_small, mgp->small_bytes, @@ -1142,7 +1149,7 @@ static int myri10ge_poll(struct net_device *netdev, int *budget) if (rx_done->entry[rx_done->idx].length == 0 || !netif_running(netdev)) { netif_rx_complete(netdev); - __raw_writel(htonl(3), mgp->irq_claim); + put_be32(htonl(3), mgp->irq_claim); return 0; } return 1; @@ -1166,7 +1173,7 @@ static irqreturn_t myri10ge_intr(int irq, void *arg) netif_rx_schedule(mgp->dev); if (!mgp->msi_enabled) { - __raw_writel(0, mgp->irq_deassert); + put_be32(0, mgp->irq_deassert); if (!myri10ge_deassert_wait) stats->valid = 0; mb(); @@ -1195,7 +1202,7 @@ static irqreturn_t myri10ge_intr(int irq, void *arg) myri10ge_check_statblock(mgp); - __raw_writel(htonl(3), mgp->irq_claim + 1); + put_be32(htonl(3), mgp->irq_claim + 1); return (IRQ_HANDLED); } @@ -1233,7 +1240,7 @@ myri10ge_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *coal) struct myri10ge_priv *mgp = netdev_priv(netdev); mgp->intr_coal_delay = coal->rx_coalesce_usecs; - __raw_writel(htonl(mgp->intr_coal_delay), mgp->intr_coal_delay_ptr); + put_be32(htonl(mgp->intr_coal_delay), mgp->intr_coal_delay_ptr); return 0; } @@ -1748,7 +1755,7 @@ static int myri10ge_open(struct net_device *dev) goto abort_with_rings; } - mgp->link_state = -1; + mgp->link_state = htonl(~0U); mgp->rdma_tags_available = 15; netif_poll_enable(mgp->dev); /* must happen prior to any irq */ @@ -1876,7 +1883,7 @@ myri10ge_submit_req(struct myri10ge_tx_buf *tx, struct mcp_kreq_ether_send *src, /* re-write the last 32-bits with the valid flags */ src->flags = last_flags; - __raw_writel(*((u32 *) src + 3), (u32 __iomem *) dst + 3); + put_be32(*((__be32 *) src + 3), (__be32 __iomem *) dst + 3); tx->req += cnt; mb(); } @@ -1919,7 +1926,8 @@ static int myri10ge_xmit(struct sk_buff *skb, struct net_device *dev) struct myri10ge_tx_buf *tx = &mgp->tx; struct skb_frag_struct *frag; dma_addr_t bus; - u32 low, high_swapped; + u32 low; + __be32 high_swapped; unsigned int len; int idx, last_idx, avail, frag_cnt, frag_idx, count, mss, max_segments; u16 pseudo_hdr_offset, cksum_offset; @@ -1964,7 +1972,6 @@ static int myri10ge_xmit(struct sk_buff *skb, struct net_device *dev) cksum_offset = 0; pseudo_hdr_offset = 0; } else { - pseudo_hdr_offset = htons(pseudo_hdr_offset); odd_flag = MXGEFW_FLAGS_ALIGN_ODD; flags |= MXGEFW_FLAGS_CKSUM; } @@ -1986,7 +1993,7 @@ static int myri10ge_xmit(struct sk_buff *skb, struct net_device *dev) /* for TSO, pseudo_hdr_offset holds mss. * The firmware figures out where to put * the checksum by parsing the header. */ - pseudo_hdr_offset = htons(mss); + pseudo_hdr_offset = mss; } else #endif /*NETIF_F_TSO */ /* Mark small packets, and pad out tiny packets */ @@ -2086,7 +2093,7 @@ static int myri10ge_xmit(struct sk_buff *skb, struct net_device *dev) #endif /* NETIF_F_TSO */ req->addr_high = high_swapped; req->addr_low = htonl(low); - req->pseudo_hdr_offset = pseudo_hdr_offset; + req->pseudo_hdr_offset = htons(pseudo_hdr_offset); req->pad = 0; /* complete solid 16-byte block; does this matter? */ req->rdma_count = 1; req->length = htons(seglen); @@ -2199,6 +2206,7 @@ static void myri10ge_set_multicast_list(struct net_device *dev) struct myri10ge_cmd cmd; struct myri10ge_priv *mgp; struct dev_mc_list *mc_list; + __be32 data[2] = {0, 0}; int err; mgp = netdev_priv(dev); @@ -2237,10 +2245,9 @@ static void myri10ge_set_multicast_list(struct net_device *dev) /* Walk the multicast list, and add each address */ for (mc_list = dev->mc_list; mc_list != NULL; mc_list = mc_list->next) { - memcpy(&cmd.data0, &mc_list->dmi_addr, 4); - memcpy(&cmd.data1, ((char *)&mc_list->dmi_addr) + 4, 2); - cmd.data0 = htonl(cmd.data0); - cmd.data1 = htonl(cmd.data1); + memcpy(data, &mc_list->dmi_addr, 6); + cmd.data0 = ntohl(data[0]); + cmd.data1 = ntohl(data[1]); err = myri10ge_send_cmd(mgp, MXGEFW_JOIN_MULTICAST_GROUP, &cmd, 1); @@ -2615,9 +2622,10 @@ static u32 myri10ge_read_reboot(struct myri10ge_priv *mgp) * This watchdog is used to check whether the board has suffered * from a parity error and needs to be recovered. */ -static void myri10ge_watchdog(void *arg) +static void myri10ge_watchdog(struct work_struct *work) { - struct myri10ge_priv *mgp = arg; + struct myri10ge_priv *mgp = + container_of(work, struct myri10ge_priv, watchdog_work); u32 reboot; int status; u16 cmd, vendor; @@ -2887,7 +2895,7 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent) (unsigned long)mgp); SET_ETHTOOL_OPS(netdev, &myri10ge_ethtool_ops); - INIT_WORK(&mgp->watchdog_work, myri10ge_watchdog, mgp); + INIT_WORK(&mgp->watchdog_work, myri10ge_watchdog); status = register_netdev(netdev); if (status != 0) { dev_err(&pdev->dev, "register_netdev failed: %d\n", status); diff --git a/trunk/drivers/net/myri10ge/myri10ge_mcp.h b/trunk/drivers/net/myri10ge/myri10ge_mcp.h index 9519ae7cd5ec..29463b301a84 100644 --- a/trunk/drivers/net/myri10ge/myri10ge_mcp.h +++ b/trunk/drivers/net/myri10ge/myri10ge_mcp.h @@ -6,23 +6,23 @@ /* 8 Bytes */ struct mcp_dma_addr { - u32 high; - u32 low; + __be32 high; + __be32 low; }; /* 4 Bytes */ struct mcp_slot { - u16 checksum; - u16 length; + __sum16 checksum; + __be16 length; }; /* 64 Bytes */ struct mcp_cmd { - u32 cmd; - u32 data0; /* will be low portion if data > 32 bits */ + __be32 cmd; + __be32 data0; /* will be low portion if data > 32 bits */ /* 8 */ - u32 data1; /* will be high portion if data > 32 bits */ - u32 data2; /* currently unused.. */ + __be32 data1; /* will be high portion if data > 32 bits */ + __be32 data2; /* currently unused.. */ /* 16 */ struct mcp_dma_addr response_addr; /* 24 */ @@ -31,8 +31,8 @@ struct mcp_cmd { /* 8 Bytes */ struct mcp_cmd_response { - u32 data; - u32 result; + __be32 data; + __be32 result; }; /* @@ -73,10 +73,10 @@ union mcp_pso_or_cumlen { /* 16 Bytes */ struct mcp_kreq_ether_send { - u32 addr_high; - u32 addr_low; - u16 pseudo_hdr_offset; - u16 length; + __be32 addr_high; + __be32 addr_low; + __be16 pseudo_hdr_offset; + __be16 length; u8 pad; u8 rdma_count; u8 cksum_offset; /* where to start computing cksum */ @@ -85,8 +85,8 @@ struct mcp_kreq_ether_send { /* 8 Bytes */ struct mcp_kreq_ether_recv { - u32 addr_high; - u32 addr_low; + __be32 addr_high; + __be32 addr_low; }; /* Commands */ @@ -219,19 +219,19 @@ enum myri10ge_mcp_cmd_status { struct mcp_irq_data { /* add new counters at the beginning */ - u32 future_use[5]; - u32 dropped_multicast_filtered; + __be32 future_use[5]; + __be32 dropped_multicast_filtered; /* 40 Bytes */ - u32 send_done_count; - - u32 link_up; - u32 dropped_link_overflow; - u32 dropped_link_error_or_filtered; - u32 dropped_runt; - u32 dropped_overrun; - u32 dropped_no_small_buffer; - u32 dropped_no_big_buffer; - u32 rdma_tags_available; + __be32 send_done_count; + + __be32 link_up; + __be32 dropped_link_overflow; + __be32 dropped_link_error_or_filtered; + __be32 dropped_runt; + __be32 dropped_overrun; + __be32 dropped_no_small_buffer; + __be32 dropped_no_big_buffer; + __be32 rdma_tags_available; u8 tx_stopped; u8 link_down; diff --git a/trunk/drivers/net/myri10ge/myri10ge_mcp_gen_header.h b/trunk/drivers/net/myri10ge/myri10ge_mcp_gen_header.h index 487f7792fd46..16a810dd6d51 100644 --- a/trunk/drivers/net/myri10ge/myri10ge_mcp_gen_header.h +++ b/trunk/drivers/net/myri10ge/myri10ge_mcp_gen_header.h @@ -36,7 +36,7 @@ struct mcp_gen_header { /* the first 4 fields are filled at compile time */ unsigned header_length; - unsigned mcp_type; + __be32 mcp_type; char version[128]; unsigned mcp_globals; /* pointer to mcp-type specific structure */ diff --git a/trunk/drivers/net/ne.c b/trunk/drivers/net/ne.c index 787aa4221528..a5c4199e2754 100644 --- a/trunk/drivers/net/ne.c +++ b/trunk/drivers/net/ne.c @@ -867,7 +867,7 @@ static void cleanup_card(struct net_device *dev) release_region(dev->base_addr, NE_IO_EXTENT); } -void cleanup_module(void) +void __exit cleanup_module(void) { int this_dev; diff --git a/trunk/drivers/net/ne2.c b/trunk/drivers/net/ne2.c index 5fccfea66d87..089b5bb702fc 100644 --- a/trunk/drivers/net/ne2.c +++ b/trunk/drivers/net/ne2.c @@ -813,7 +813,7 @@ static void cleanup_card(struct net_device *dev) release_region(dev->base_addr, NE_IO_EXTENT); } -void cleanup_module(void) +void __exit cleanup_module(void) { int this_dev; diff --git a/trunk/drivers/net/netxen/netxen_nic.h b/trunk/drivers/net/netxen/netxen_nic.h index d925053fe597..b5410bee5f21 100644 --- a/trunk/drivers/net/netxen/netxen_nic.h +++ b/trunk/drivers/net/netxen/netxen_nic.h @@ -1,25 +1,25 @@ /* * Copyright (C) 2003 - 2006 NetXen, Inc. * All rights reserved. - * + * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. - * + * * The full GNU General Public License is included in this distribution * in the file called LICENSE. - * + * * Contact Information: * info@netxen.com * NetXen, @@ -63,40 +63,68 @@ #include "netxen_nic_hw.h" -#define NETXEN_NIC_BUILD_NO "5" -#define _NETXEN_NIC_LINUX_MAJOR 2 +#define NETXEN_NIC_BUILD_NO "1" +#define _NETXEN_NIC_LINUX_MAJOR 3 #define _NETXEN_NIC_LINUX_MINOR 3 -#define _NETXEN_NIC_LINUX_SUBVERSION 59 -#define NETXEN_NIC_LINUX_VERSIONID "2.3.59" "-" NETXEN_NIC_BUILD_NO -#define NETXEN_NIC_FW_VERSIONID "2.3.59" +#define _NETXEN_NIC_LINUX_SUBVERSION 2 +#define NETXEN_NIC_LINUX_VERSIONID "3.3.2" "-" NETXEN_NIC_BUILD_NO +#define NETXEN_NIC_FW_VERSIONID "3.3.2" #define RCV_DESC_RINGSIZE \ (sizeof(struct rcv_desc) * adapter->max_rx_desc_count) #define STATUS_DESC_RINGSIZE \ (sizeof(struct status_desc)* adapter->max_rx_desc_count) +#define LRO_DESC_RINGSIZE \ + (sizeof(rcvDesc_t) * adapter->max_lro_rx_desc_count) #define TX_RINGSIZE \ (sizeof(struct netxen_cmd_buffer) * adapter->max_tx_desc_count) #define RCV_BUFFSIZE \ (sizeof(struct netxen_rx_buffer) * rcv_desc->max_rx_desc_count) #define find_diff_among(a,b,range) ((a)<(b)?((b)-(a)):((b)+(range)-(a))) -#define NETXEN_NETDEV_STATUS 0x1 +#define NETXEN_NETDEV_STATUS 0x1 +#define NETXEN_RCV_PRODUCER_OFFSET 0 +#define NETXEN_RCV_PEG_DB_ID 2 +#define NETXEN_HOST_DUMMY_DMA_SIZE 1024 #define ADDR_IN_WINDOW1(off) \ ((off > NETXEN_CRB_PCIX_HOST2) && (off < NETXEN_CRB_MAX)) ? 1 : 0 +/* + * In netxen_nic_down(), we must wait for any pending callback requests into + * netxen_watchdog_task() to complete; eg otherwise the watchdog_timer could be + * reenabled right after it is deleted in netxen_nic_down(). FLUSH_SCHEDULED_WORK() + * does this synchronization. + * + * Normally, schedule_work()/flush_scheduled_work() could have worked, but + * netxen_nic_close() is invoked with kernel rtnl lock held. netif_carrier_off() + * call in netxen_nic_close() triggers a schedule_work(&linkwatch_work), and a + * subsequent call to flush_scheduled_work() in netxen_nic_down() would cause + * linkwatch_event() to be executed which also attempts to acquire the rtnl + * lock thus causing a deadlock. + */ + +#define SCHEDULE_WORK(tp) queue_work(netxen_workq, tp) +#define FLUSH_SCHEDULED_WORK() flush_workqueue(netxen_workq) +extern struct workqueue_struct *netxen_workq; /* * normalize a 64MB crb address to 32MB PCI window * To use NETXEN_CRB_NORMALIZE, window _must_ be set to 1 */ -#define NETXEN_CRB_NORMAL(reg) \ - (reg) - NETXEN_CRB_PCIX_HOST2 + NETXEN_CRB_PCIX_HOST +#define NETXEN_CRB_NORMAL(reg) \ + ((reg) - NETXEN_CRB_PCIX_HOST2 + NETXEN_CRB_PCIX_HOST) #define NETXEN_CRB_NORMALIZE(adapter, reg) \ pci_base_offset(adapter, NETXEN_CRB_NORMAL(reg)) +#define DB_NORMALIZE(adapter, off) \ + (adapter->ahw.db_base + (off)) + +#define NX_P2_C0 0x24 +#define NX_P2_C1 0x25 + #define FIRST_PAGE_GROUP_START 0 -#define FIRST_PAGE_GROUP_END 0x400000 +#define FIRST_PAGE_GROUP_END 0x100000 #define SECOND_PAGE_GROUP_START 0x4000000 #define SECOND_PAGE_GROUP_END 0x66BC000 @@ -108,11 +136,13 @@ #define SECOND_PAGE_GROUP_SIZE SECOND_PAGE_GROUP_END - SECOND_PAGE_GROUP_START #define THIRD_PAGE_GROUP_SIZE THIRD_PAGE_GROUP_END - THIRD_PAGE_GROUP_START -#define MAX_RX_BUFFER_LENGTH 2000 +#define MAX_RX_BUFFER_LENGTH 1760 #define MAX_RX_JUMBO_BUFFER_LENGTH 9046 -#define RX_DMA_MAP_LEN (MAX_RX_BUFFER_LENGTH - NET_IP_ALIGN) +#define MAX_RX_LRO_BUFFER_LENGTH ((48*1024)-512) +#define RX_DMA_MAP_LEN (MAX_RX_BUFFER_LENGTH - 2) #define RX_JUMBO_DMA_MAP_LEN \ - (MAX_RX_JUMBO_BUFFER_LENGTH - NET_IP_ALIGN) + (MAX_RX_JUMBO_BUFFER_LENGTH - 2) +#define RX_LRO_DMA_MAP_LEN (MAX_RX_LRO_BUFFER_LENGTH - 2) #define NETXEN_ROM_ROUNDUP 0x80000000ULL /* @@ -151,30 +181,38 @@ enum { /* Host writes the following to notify that it has done the init-handshake */ #define PHAN_INITIALIZE_ACK 0xf00f -#define NUM_RCV_DESC_RINGS 2 /* No of Rcv Descriptor contexts */ +#define NUM_RCV_DESC_RINGS 3 /* No of Rcv Descriptor contexts */ /* descriptor types */ #define RCV_DESC_NORMAL 0x01 #define RCV_DESC_JUMBO 0x02 +#define RCV_DESC_LRO 0x04 #define RCV_DESC_NORMAL_CTXID 0 #define RCV_DESC_JUMBO_CTXID 1 +#define RCV_DESC_LRO_CTXID 2 #define RCV_DESC_TYPE(ID) \ - ((ID == RCV_DESC_JUMBO_CTXID) ? RCV_DESC_JUMBO : RCV_DESC_NORMAL) + ((ID == RCV_DESC_JUMBO_CTXID) \ + ? RCV_DESC_JUMBO \ + : ((ID == RCV_DESC_LRO_CTXID) \ + ? RCV_DESC_LRO : \ + (RCV_DESC_NORMAL))) #define MAX_CMD_DESCRIPTORS 1024 #define MAX_RCV_DESCRIPTORS 32768 -#define MAX_JUMBO_RCV_DESCRIPTORS 1024 +#define MAX_JUMBO_RCV_DESCRIPTORS 4096 +#define MAX_LRO_RCV_DESCRIPTORS 2048 #define MAX_RCVSTATUS_DESCRIPTORS MAX_RCV_DESCRIPTORS #define MAX_JUMBO_RCV_DESC MAX_JUMBO_RCV_DESCRIPTORS #define MAX_RCV_DESC MAX_RCV_DESCRIPTORS #define MAX_RCVSTATUS_DESC MAX_RCV_DESCRIPTORS -#define NUM_RCV_DESC (MAX_RCV_DESC + MAX_JUMBO_RCV_DESCRIPTORS) #define MAX_EPG_DESCRIPTORS (MAX_CMD_DESCRIPTORS * 8) - +#define NUM_RCV_DESC (MAX_RCV_DESC + MAX_JUMBO_RCV_DESCRIPTORS + \ + MAX_LRO_RCV_DESCRIPTORS) #define MIN_TX_COUNT 4096 #define MIN_RX_COUNT 4096 - +#define NETXEN_CTX_SIGNATURE 0xdee0 +#define NETXEN_RCV_PRODUCER(ringid) (ringid) #define MAX_FRAME_SIZE 0x10000 /* 64K MAX size for LSO */ #define PHAN_PEG_RCV_INITIALIZED 0xff01 @@ -186,6 +224,67 @@ enum { #define get_index_range(index,length,count) \ (((index) + (count)) & ((length) - 1)) +#define MPORT_SINGLE_FUNCTION_MODE 0x1111 + +extern unsigned long long netxen_dma_mask; + +/* + * NetXen host-peg signal message structure + * + * Bit 0-1 : peg_id => 0x2 for tx and 01 for rx + * Bit 2 : priv_id => must be 1 + * Bit 3-17 : count => for doorbell + * Bit 18-27 : ctx_id => Context id + * Bit 28-31 : opcode + */ + +typedef u32 netxen_ctx_msg; + +#define _netxen_set_bits(config_word, start, bits, val) {\ + unsigned long long mask = (((1ULL << (bits)) - 1) << (start)); \ + unsigned long long value = (val); \ + (config_word) &= ~mask; \ + (config_word) |= (((value) << (start)) & mask); \ +} + +#define netxen_set_msg_peg_id(config_word, val) \ + _netxen_set_bits(config_word, 0, 2, val) +#define netxen_set_msg_privid(config_word) \ + set_bit(2, (unsigned long*)&config_word) +#define netxen_set_msg_count(config_word, val) \ + _netxen_set_bits(config_word, 3, 15, val) +#define netxen_set_msg_ctxid(config_word, val) \ + _netxen_set_bits(config_word, 18, 10, val) +#define netxen_set_msg_opcode(config_word, val) \ + _netxen_set_bits(config_word, 28, 4, val) + +struct netxen_rcv_context { + u32 rcv_ring_addr_lo; + u32 rcv_ring_addr_hi; + u32 rcv_ring_size; + u32 rsrvd; +}; + +struct netxen_ring_ctx { + + /* one command ring */ + u64 cmd_consumer_offset; + u32 cmd_ring_addr_lo; + u32 cmd_ring_addr_hi; + u32 cmd_ring_size; + u32 rsrvd; + + /* three receive rings */ + struct netxen_rcv_context rcv_ctx[3]; + + /* one status ring */ + u32 sts_ring_addr_lo; + u32 sts_ring_addr_hi; + u32 sts_ring_size; + + u32 ctx_id; +} __attribute__ ((aligned(64))); + /* * Following data structures describe the descriptors that will be used. * Added fileds of tcpHdrSize and ipHdrSize, The driver needs to do it only when @@ -203,22 +302,32 @@ enum { #define FLAGS_IPSEC_SA_DELETE 0x08 #define FLAGS_VLAN_TAGGED 0x10 -#define CMD_DESC_TOTAL_LENGTH(cmd_desc) \ - ((cmd_desc)->length_tcp_hdr & 0x00FFFFFF) -#define CMD_DESC_TCP_HDR_OFFSET(cmd_desc) \ - (((cmd_desc)->length_tcp_hdr >> 24) & 0x0FF) -#define CMD_DESC_PORT(cmd_desc) ((cmd_desc)->port_ctxid & 0x0F) -#define CMD_DESC_CTX_ID(cmd_desc) (((cmd_desc)->port_ctxid >> 4) & 0x0F) +#define netxen_set_cmd_desc_port(cmd_desc, var) \ + ((cmd_desc)->port_ctxid |= ((var) & 0x0F)) -#define CMD_DESC_TOTAL_LENGTH_WRT(cmd_desc, var) \ - ((cmd_desc)->length_tcp_hdr |= ((var) & 0x00FFFFFF)) -#define CMD_DESC_TCP_HDR_OFFSET_WRT(cmd_desc, var) \ - ((cmd_desc)->length_tcp_hdr |= (((var) << 24) & 0xFF000000)) -#define CMD_DESC_PORT_WRT(cmd_desc, var) \ - ((cmd_desc)->port_ctxid |= ((var) & 0x0F)) +#define netxen_set_cmd_desc_flags(cmd_desc, val) \ + _netxen_set_bits((cmd_desc)->flags_opcode, 0, 7, val) +#define netxen_set_cmd_desc_opcode(cmd_desc, val) \ + _netxen_set_bits((cmd_desc)->flags_opcode, 7, 6, val) + +#define netxen_set_cmd_desc_num_of_buff(cmd_desc, val) \ + _netxen_set_bits((cmd_desc)->num_of_buffers_total_length, 0, 8, val); +#define netxen_set_cmd_desc_totallength(cmd_desc, val) \ + _netxen_set_bits((cmd_desc)->num_of_buffers_total_length, 8, 24, val); + +#define netxen_get_cmd_desc_opcode(cmd_desc) \ + (((cmd_desc)->flags_opcode >> 7) & 0x003F) +#define netxen_get_cmd_desc_totallength(cmd_desc) \ + (((cmd_desc)->num_of_buffers_total_length >> 8) & 0x0FFFFFF) struct cmd_desc_type0 { - u64 netxen_next; /* for fragments handled by Phantom */ + u8 tcp_hdr_offset; /* For LSO only */ + u8 ip_hdr_offset; /* For LSO only */ + /* Bit pattern: 0-6 flags, 7-12 opcode, 13-15 unused */ + u16 flags_opcode; + /* Bit pattern: 0-7 total number of segments, + 8-31 Total size of the packet */ + u32 num_of_buffers_total_length; union { struct { u32 addr_low_part2; @@ -227,13 +336,6 @@ struct cmd_desc_type0 { u64 addr_buffer2; }; - /* Bit pattern: 0-23 total length, 24-32 tcp header offset */ - u32 length_tcp_hdr; - u8 ip_hdr_offset; /* For LSO only */ - u8 num_of_buffers; /* total number of segments */ - u8 flags; /* as defined above */ - u8 opcode; - u16 reference_handle; /* changed to u16 to add mss */ u16 mss; /* passed by NDIS_PACKET for LSO */ /* Bit pattern 0-3 port, 0-3 ctx id */ @@ -248,7 +350,6 @@ struct cmd_desc_type0 { }; u64 addr_buffer3; }; - union { struct { u32 addr_low_part1; @@ -270,6 +371,8 @@ struct cmd_desc_type0 { u64 addr_buffer4; }; + u64 unused; + } __attribute__ ((aligned(64))); /* Note: sizeof(rcv_desc) should always be a mutliple of 2 */ @@ -296,22 +399,49 @@ struct rcv_desc { #define NETXEN_PROT_UNKNOWN (0) /* Note: sizeof(status_desc) should always be a mutliple of 2 */ -#define STATUS_DESC_PORT(status_desc) \ - ((status_desc)->port_status_type_op & 0x0F) -#define STATUS_DESC_STATUS(status_desc) \ - (((status_desc)->port_status_type_op >> 4) & 0x0F) -#define STATUS_DESC_TYPE(status_desc) \ - (((status_desc)->port_status_type_op >> 8) & 0x0F) -#define STATUS_DESC_OPCODE(status_desc) \ - (((status_desc)->port_status_type_op >> 12) & 0x0F) + +#define netxen_get_sts_desc_lro_cnt(status_desc) \ + ((status_desc)->lro & 0x7F) +#define netxen_get_sts_desc_lro_last_frag(status_desc) \ + (((status_desc)->lro & 0x80) >> 7) + +#define netxen_get_sts_port(status_desc) \ + ((status_desc)->status_desc_data & 0x0F) +#define netxen_get_sts_status(status_desc) \ + (((status_desc)->status_desc_data >> 4) & 0x0F) +#define netxen_get_sts_type(status_desc) \ + (((status_desc)->status_desc_data >> 8) & 0x0F) +#define netxen_get_sts_totallength(status_desc) \ + (((status_desc)->status_desc_data >> 12) & 0xFFFF) +#define netxen_get_sts_refhandle(status_desc) \ + (((status_desc)->status_desc_data >> 28) & 0xFFFF) +#define netxen_get_sts_prot(status_desc) \ + (((status_desc)->status_desc_data >> 44) & 0x0F) +#define netxen_get_sts_owner(status_desc) \ + (((status_desc)->status_desc_data >> 56) & 0x03) +#define netxen_get_sts_opcode(status_desc) \ + (((status_desc)->status_desc_data >> 58) & 0x03F) + +#define netxen_clear_sts_owner(status_desc) \ + ((status_desc)->status_desc_data &= \ + ~(((unsigned long long)3) << 56 )) +#define netxen_set_sts_owner(status_desc, val) \ + ((status_desc)->status_desc_data |= \ + (((unsigned long long)((val) & 0x3)) << 56 )) struct status_desc { - /* Bit pattern: 0-3 port, 4-7 status, 8-11 type, 12-15 opcode */ - u16 port_status_type_op; - u16 total_length; /* NIC mode */ - u16 reference_handle; /* handle for the associated packet */ - /* Bit pattern: 0-1 owner, 2-5 protocol */ - u16 owner; /* Owner of the descriptor */ + /* Bit pattern: 0-3 port, 4-7 status, 8-11 type, 12-27 total_length + 28-43 reference_handle, 44-47 protocol, 48-52 unused + 53-55 desc_cnt, 56-57 owner, 58-63 opcode + */ + u64 status_desc_data; + u32 hash_value; + u8 hash_type; + u8 msg_type; + u8 unused; + /* Bit pattern: 0-6 lro_count indicates frag sequence, + 7 last_frag indicates last frag */ + u8 lro; } __attribute__ ((aligned(8))); enum { @@ -559,11 +689,12 @@ typedef enum { #define PRIMARY_START (BOOTLD_START) #define FLASH_CRBINIT_SIZE (0x4000) #define FLASH_BRDCFG_SIZE (sizeof(struct netxen_board_info)) -#define FLASH_USER_SIZE (sizeof(netxen_user_info)/sizeof(u32)) +#define FLASH_USER_SIZE (sizeof(struct netxen_user_info)/sizeof(u32)) #define FLASH_SECONDARY_SIZE (USER_START-SECONDARY_START) #define NUM_PRIMARY_SECTORS (0x20) #define NUM_CONFIG_SECTORS (1) -#define PFX "netxen: " +#define PFX "NetXen: " +extern char netxen_nic_driver_name[]; /* Note: Make sure to not call this before adapter->port is valid */ #if !defined(NETXEN_DEBUG) @@ -572,7 +703,7 @@ typedef enum { #else #define DPRINTK(klevel, fmt, args...) do { \ printk(KERN_##klevel PFX "%s: %s: " fmt, __FUNCTION__,\ - (adapter != NULL && adapter->port != NULL && \ + (adapter != NULL && \ adapter->port[0] != NULL && \ adapter->port[0]->netdev != NULL) ? \ adapter->port[0]->netdev->name : NULL, \ @@ -609,7 +740,6 @@ struct netxen_cmd_buffer { u8 frag_count; unsigned long time_stamp; u32 state; - u32 no_of_descriptors; }; /* In rx_buffer, we do not need multiple fragments as is a single buffer */ @@ -618,6 +748,9 @@ struct netxen_rx_buffer { u64 dma; u16 ref_handle; u16 state; + u32 lro_expected_frags; + u32 lro_current_frags; + u32 lro_length; }; /* Board types */ @@ -633,6 +766,8 @@ struct netxen_hardware_context { void __iomem *pci_base0; void __iomem *pci_base1; void __iomem *pci_base2; + void __iomem *db_base; + unsigned long db_len; u8 revision_id; u16 board_type; @@ -642,14 +777,13 @@ struct netxen_hardware_context { u32 qg_linksup; /* Address of cmd ring in Phantom */ struct cmd_desc_type0 *cmd_desc_head; - char *pauseaddr; struct pci_dev *cmd_desc_pdev; dma_addr_t cmd_desc_phys_addr; - dma_addr_t pause_physaddr; - struct pci_dev *pause_pdev; struct netxen_adapter *adapter; }; +#define RCV_RING_LRO RCV_DESC_LRO + #define MINIMUM_ETHERNET_FRAME_SIZE 64 /* With FCS */ #define ETHERNET_FCS_SIZE 4 @@ -702,8 +836,13 @@ struct netxen_recv_context { }; #define NETXEN_NIC_MSI_ENABLED 0x02 +#define NETXEN_DMA_MASK 0xfffffffe +#define NETXEN_DB_MAPSIZE_BYTES 0x1000 -struct netxen_drvops; +struct netxen_dummy_dma { + void *addr; + dma_addr_t phys_addr; +}; struct netxen_adapter { struct netxen_hardware_context ahw; @@ -714,17 +853,19 @@ struct netxen_adapter { spinlock_t lock; struct work_struct watchdog_task; struct work_struct tx_timeout_task; + struct net_device *netdev; struct timer_list watchdog_timer; u32 curr_window; u32 cmd_producer; - u32 cmd_consumer; + u32 *cmd_consumer; u32 last_cmd_consumer; u32 max_tx_desc_count; u32 max_rx_desc_count; u32 max_jumbo_rx_desc_count; + u32 max_lro_rx_desc_count; /* Num of instances active on cmd buffer ring */ u32 proc_cmd_buf_counter; @@ -746,8 +887,27 @@ struct netxen_adapter { struct netxen_recv_context recv_ctx[MAX_RCV_CTX]; int is_up; - int work_done; - struct netxen_drvops *ops; + int number; + struct netxen_dummy_dma dummy_dma; + + /* Context interface shared between card and host */ + struct netxen_ring_ctx *ctx_desc; + struct pci_dev *ctx_desc_pdev; + dma_addr_t ctx_desc_phys_addr; + int (*enable_phy_interrupts) (struct netxen_adapter *, int); + int (*disable_phy_interrupts) (struct netxen_adapter *, int); + void (*handle_phy_intr) (struct netxen_adapter *); + int (*macaddr_set) (struct netxen_port *, netxen_ethernet_macaddr_t); + int (*set_mtu) (struct netxen_port *, int); + int (*set_promisc) (struct netxen_adapter *, int, + netxen_niu_prom_mode_t); + int (*unset_promisc) (struct netxen_adapter *, int, + netxen_niu_prom_mode_t); + int (*phy_read) (struct netxen_adapter *, long phy, long reg, u32 *); + int (*phy_write) (struct netxen_adapter *, long phy, long reg, u32 val); + int (*init_port) (struct netxen_adapter *, int); + void (*init_niu) (struct netxen_adapter *); + int (*stop_port) (struct netxen_adapter *, int); }; /* netxen_adapter structure */ /* Max number of xmit producer threads that can run simultaneously */ @@ -829,25 +989,6 @@ static inline void __iomem *pci_base(struct netxen_adapter *adapter, return NULL; } -struct netxen_drvops { - int (*enable_phy_interrupts) (struct netxen_adapter *, int); - int (*disable_phy_interrupts) (struct netxen_adapter *, int); - void (*handle_phy_intr) (struct netxen_adapter *); - int (*macaddr_set) (struct netxen_port *, netxen_ethernet_macaddr_t); - int (*set_mtu) (struct netxen_port *, int); - int (*set_promisc) (struct netxen_adapter *, int, - netxen_niu_prom_mode_t); - int (*unset_promisc) (struct netxen_adapter *, int, - netxen_niu_prom_mode_t); - int (*phy_read) (struct netxen_adapter *, long phy, long reg, u32 *); - int (*phy_write) (struct netxen_adapter *, long phy, long reg, u32 val); - int (*init_port) (struct netxen_adapter *, int); - void (*init_niu) (struct netxen_adapter *); - int (*stop_port) (struct netxen_adapter *, int); -}; - -extern char netxen_nic_driver_name[]; - int netxen_niu_xgbe_enable_phy_interrupts(struct netxen_adapter *adapter, int port); int netxen_niu_gbe_enable_phy_interrupts(struct netxen_adapter *adapter, @@ -886,10 +1027,20 @@ int netxen_nic_hw_read_wx(struct netxen_adapter *adapter, u64 off, void *data, int len); int netxen_nic_hw_write_wx(struct netxen_adapter *adapter, u64 off, void *data, int len); +int netxen_nic_hw_read_ioctl(struct netxen_adapter *adapter, u64 off, + void *data, int len); +int netxen_nic_hw_write_ioctl(struct netxen_adapter *adapter, u64 off, + void *data, int len); +int netxen_nic_pci_mem_write_ioctl(struct netxen_adapter *adapter, + u64 off, void *data, int size); +int netxen_nic_pci_mem_read_ioctl(struct netxen_adapter *adapter, + u64 off, void *data, int size); void netxen_crb_writelit_adapter(struct netxen_adapter *adapter, unsigned long off, int data); /* Functions from netxen_nic_init.c */ +void netxen_free_adapter_offload(struct netxen_adapter *adapter); +int netxen_initialize_adapter_offload(struct netxen_adapter *adapter); void netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val); void netxen_load_firmware(struct netxen_adapter *adapter); int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose); @@ -921,10 +1072,12 @@ netxen_nic_do_ioctl(struct netxen_adapter *adapter, void *u_data, struct netxen_port *port); int netxen_nic_rx_has_work(struct netxen_adapter *adapter); int netxen_nic_tx_has_work(struct netxen_adapter *adapter); -void netxen_watchdog_task(unsigned long v); +void netxen_watchdog_task(struct work_struct *work); void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, u32 ringid); -void netxen_process_cmd_ring(unsigned long data); +void netxen_post_rx_buffers_nodb(struct netxen_adapter *adapter, u32 ctx, + u32 ringid); +int netxen_process_cmd_ring(unsigned long data); u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctx, int max); void netxen_nic_set_multi(struct net_device *netdev); int netxen_nic_change_mtu(struct net_device *netdev, int new_mtu); @@ -1018,7 +1171,6 @@ static inline void get_brd_name_by_type(u32 type, char *name) int netxen_is_flash_supported(struct netxen_adapter *adapter); int netxen_get_flash_mac_addr(struct netxen_adapter *adapter, u64 mac[]); - extern void netxen_change_ringparam(struct netxen_adapter *adapter); extern int netxen_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp); diff --git a/trunk/drivers/net/netxen/netxen_nic_ethtool.c b/trunk/drivers/net/netxen/netxen_nic_ethtool.c index 9a914aeba5bc..2ab4885cc950 100644 --- a/trunk/drivers/net/netxen/netxen_nic_ethtool.c +++ b/trunk/drivers/net/netxen/netxen_nic_ethtool.c @@ -1,25 +1,25 @@ /* * Copyright (C) 2003 - 2006 NetXen, Inc. * All rights reserved. - * + * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. - * + * * The full GNU General Public License is included in this distribution * in the file called LICENSE. - * + * * Contact Information: * info@netxen.com * NetXen, @@ -118,7 +118,7 @@ netxen_nic_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo) u32 fw_minor = 0; u32 fw_build = 0; - strncpy(drvinfo->driver, "netxen_nic", 32); + strncpy(drvinfo->driver, netxen_nic_driver_name, 32); strncpy(drvinfo->version, NETXEN_NIC_LINUX_VERSIONID, 32); fw_major = readl(NETXEN_CRB_NORMALIZE(adapter, NETXEN_FW_VERSION_MAJOR)); @@ -210,7 +210,6 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) printk(KERN_ERR "netxen-nic: Unsupported board model %d\n", (netxen_brdtype_t) boardinfo->board_type); return -EIO; - } return 0; @@ -226,18 +225,18 @@ netxen_nic_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) /* read which mode */ if (adapter->ahw.board_type == NETXEN_NIC_GBE) { /* autonegotiation */ - if (adapter->ops->phy_write - && adapter->ops->phy_write(adapter, port->portnum, - NETXEN_NIU_GB_MII_MGMT_ADDR_AUTONEG, - (__le32) ecmd->autoneg) != 0) + if (adapter->phy_write + && adapter->phy_write(adapter, port->portnum, + NETXEN_NIU_GB_MII_MGMT_ADDR_AUTONEG, + (__le32) ecmd->autoneg) != 0) return -EIO; else port->link_autoneg = ecmd->autoneg; - if (adapter->ops->phy_read - && adapter->ops->phy_read(adapter, port->portnum, - NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS, - &status) != 0) + if (adapter->phy_read + && adapter->phy_read(adapter, port->portnum, + NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS, + &status) != 0) return -EIO; /* speed */ @@ -257,10 +256,10 @@ netxen_nic_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) netxen_clear_phy_duplex(status); if (ecmd->duplex == DUPLEX_FULL) netxen_set_phy_duplex(status); - if (adapter->ops->phy_write - && adapter->ops->phy_write(adapter, port->portnum, - NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS, - *((int *)&status)) != 0) + if (adapter->phy_write + && adapter->phy_write(adapter, port->portnum, + NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS, + *((int *)&status)) != 0) return -EIO; else { port->link_speed = ecmd->speed; @@ -422,10 +421,10 @@ static u32 netxen_nic_get_link(struct net_device *dev) /* read which mode */ if (adapter->ahw.board_type == NETXEN_NIC_GBE) { - if (adapter->ops->phy_read - && adapter->ops->phy_read(adapter, port->portnum, - NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS, - &status) != 0) + if (adapter->phy_read + && adapter->phy_read(adapter, port->portnum, + NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS, + &status) != 0) return -EIO; else return (netxen_get_phy_link(status)); @@ -460,20 +459,22 @@ netxen_nic_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ring) { struct netxen_port *port = netdev_priv(dev); struct netxen_adapter *adapter = port->adapter; - int i, j; + int i; ring->rx_pending = 0; + ring->rx_jumbo_pending = 0; for (i = 0; i < MAX_RCV_CTX; ++i) { - for (j = 0; j < NUM_RCV_DESC_RINGS; j++) - ring->rx_pending += - adapter->recv_ctx[i].rcv_desc[j].rcv_pending; + ring->rx_pending += adapter->recv_ctx[i]. + rcv_desc[RCV_DESC_NORMAL_CTXID].rcv_pending; + ring->rx_jumbo_pending += adapter->recv_ctx[i]. + rcv_desc[RCV_DESC_JUMBO_CTXID].rcv_pending; } ring->rx_max_pending = adapter->max_rx_desc_count; ring->tx_max_pending = adapter->max_tx_desc_count; + ring->rx_jumbo_max_pending = adapter->max_jumbo_rx_desc_count; ring->rx_mini_max_pending = 0; ring->rx_mini_pending = 0; - ring->rx_jumbo_max_pending = 0; ring->rx_jumbo_pending = 0; } @@ -526,10 +527,10 @@ netxen_nic_set_pauseparam(struct net_device *dev, *(u32 *) (&val)); /* set autoneg */ autoneg = pause->autoneg; - if (adapter->ops->phy_write - && adapter->ops->phy_write(adapter, port->portnum, - NETXEN_NIU_GB_MII_MGMT_ADDR_AUTONEG, - (__le32) autoneg) != 0) + if (adapter->phy_write + && adapter->phy_write(adapter, port->portnum, + NETXEN_NIU_GB_MII_MGMT_ADDR_AUTONEG, + (__le32) autoneg) != 0) return -EIO; else { port->link_autoneg = pause->autoneg; diff --git a/trunk/drivers/net/netxen/netxen_nic_hdr.h b/trunk/drivers/net/netxen/netxen_nic_hdr.h index 72c6ec4ee2a0..fe8b675f9e72 100644 --- a/trunk/drivers/net/netxen/netxen_nic_hdr.h +++ b/trunk/drivers/net/netxen/netxen_nic_hdr.h @@ -1,7 +1,7 @@ /* * Copyright (C) 2003 - 2006 NetXen, Inc. * All rights reserved. - * + * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 @@ -16,10 +16,10 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. - * + * * The full GNU General Public License is included in this distribution * in the file called LICENSE. - * + * * Contact Information: * info@netxen.com * NetXen, diff --git a/trunk/drivers/net/netxen/netxen_nic_hw.c b/trunk/drivers/net/netxen/netxen_nic_hw.c index 105c24f0ad4c..9147b6048dfb 100644 --- a/trunk/drivers/net/netxen/netxen_nic_hw.c +++ b/trunk/drivers/net/netxen/netxen_nic_hw.c @@ -1,7 +1,7 @@ /* * Copyright (C) 2003 - 2006 NetXen, Inc. * All rights reserved. - * + * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 @@ -16,10 +16,10 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. - * + * * The full GNU General Public License is included in this distribution * in the file called LICENSE. - * + * * Contact Information: * info@netxen.com * NetXen, @@ -42,7 +42,7 @@ #define NETXEN_FLASH_BASE (BOOTLD_START) #define NETXEN_PHANTOM_MEM_BASE (NETXEN_FLASH_BASE) -#define NETXEN_MAX_MTU 8000 +#define NETXEN_MAX_MTU 8000 + NETXEN_ENET_HEADER_SIZE + NETXEN_ETH_FCS_SIZE #define NETXEN_MIN_MTU 64 #define NETXEN_ETH_FCS_SIZE 4 #define NETXEN_ENET_HEADER_SIZE 14 @@ -81,8 +81,8 @@ int netxen_nic_set_mac(struct net_device *netdev, void *p) DPRINTK(INFO, "valid ether addr\n"); memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); - if (adapter->ops->macaddr_set) - adapter->ops->macaddr_set(port, addr->sa_data); + if (adapter->macaddr_set) + adapter->macaddr_set(port, addr->sa_data); return 0; } @@ -99,17 +99,17 @@ void netxen_nic_set_multi(struct net_device *netdev) mc_ptr = netdev->mc_list; if (netdev->flags & IFF_PROMISC) { - if (adapter->ops->set_promisc) - adapter->ops->set_promisc(adapter, - port->portnum, - NETXEN_NIU_PROMISC_MODE); + if (adapter->set_promisc) + adapter->set_promisc(adapter, + port->portnum, + NETXEN_NIU_PROMISC_MODE); } else { - if (adapter->ops->unset_promisc && + if (adapter->unset_promisc && adapter->ahw.boardcfg.board_type != NETXEN_BRDTYPE_P2_SB31_10G_IMEZ) - adapter->ops->unset_promisc(adapter, - port->portnum, - NETXEN_NIU_NON_PROMISC_MODE); + adapter->unset_promisc(adapter, + port->portnum, + NETXEN_NIU_NON_PROMISC_MODE); } if (adapter->ahw.board_type == NETXEN_NIC_XGBE) { netxen_nic_mcr_set_mode_select(netxen_mac_addr_cntl_data, 0x03); @@ -160,8 +160,8 @@ int netxen_nic_change_mtu(struct net_device *netdev, int mtu) return -EINVAL; } - if (adapter->ops->set_mtu) - adapter->ops->set_mtu(port, mtu); + if (adapter->set_mtu) + adapter->set_mtu(port, mtu); netdev->mtu = mtu; return 0; @@ -176,22 +176,18 @@ int netxen_nic_hw_resources(struct netxen_adapter *adapter) struct netxen_hardware_context *hw = &adapter->ahw; u32 state = 0; void *addr; - void *pause_addr; int loops = 0, err = 0; int ctx, ring; u32 card_cmdring = 0; - struct netxen_rcv_desc_crb *rcv_desc_crb = NULL; struct netxen_recv_context *recv_ctx; struct netxen_rcv_desc_ctx *rcv_desc; - DPRINTK(INFO, "crb_base: %lx %lx", NETXEN_PCI_CRBSPACE, + DPRINTK(INFO, "crb_base: %lx %x", NETXEN_PCI_CRBSPACE, PCI_OFFSET_SECOND_RANGE(adapter, NETXEN_PCI_CRBSPACE)); - DPRINTK(INFO, "cam base: %lx %lx", NETXEN_CRB_CAM, + DPRINTK(INFO, "cam base: %lx %x", NETXEN_CRB_CAM, pci_base_offset(adapter, NETXEN_CRB_CAM)); - DPRINTK(INFO, "cam RAM: %lx %lx", NETXEN_CAM_RAM_BASE, + DPRINTK(INFO, "cam RAM: %lx %x", NETXEN_CAM_RAM_BASE, pci_base_offset(adapter, NETXEN_CAM_RAM_BASE)); - DPRINTK(INFO, "NIC base:%lx %lx\n", NIC_CRB_BASE_PORT1, - pci_base_offset(adapter, NIC_CRB_BASE_PORT1)); /* Window 1 call */ card_cmdring = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_CMDRING)); @@ -226,33 +222,42 @@ int netxen_nic_hw_resources(struct netxen_adapter *adapter) DPRINTK(INFO, "Recieve Peg ready too. starting stuff\n"); addr = netxen_alloc(adapter->ahw.pdev, - sizeof(struct cmd_desc_type0) * - adapter->max_tx_desc_count, - &hw->cmd_desc_phys_addr, &hw->cmd_desc_pdev); + sizeof(struct netxen_ring_ctx) + + sizeof(uint32_t), + (dma_addr_t *) & adapter->ctx_desc_phys_addr, + &adapter->ctx_desc_pdev); + printk("ctx_desc_phys_addr: 0x%llx\n", + (u64) adapter->ctx_desc_phys_addr); if (addr == NULL) { DPRINTK(ERR, "bad return from pci_alloc_consistent\n"); - return -ENOMEM; + err = -ENOMEM; + return err; } + memset(addr, 0, sizeof(struct netxen_ring_ctx)); + adapter->ctx_desc = (struct netxen_ring_ctx *)addr; + adapter->ctx_desc->cmd_consumer_offset = adapter->ctx_desc_phys_addr + + sizeof(struct netxen_ring_ctx); + adapter->cmd_consumer = (uint32_t *) (((char *)addr) + + sizeof(struct netxen_ring_ctx)); + + addr = pci_alloc_consistent(adapter->ahw.pdev, + sizeof(struct cmd_desc_type0) * + adapter->max_tx_desc_count, + (dma_addr_t *) & hw->cmd_desc_phys_addr); + printk("cmd_desc_phys_addr: 0x%llx\n", (u64) hw->cmd_desc_phys_addr); - pause_addr = netxen_alloc(adapter->ahw.pdev, 512, - (dma_addr_t *) & hw->pause_physaddr, - &hw->pause_pdev); - if (pause_addr == NULL) { - DPRINTK(1, ERR, "bad return from pci_alloc_consistent\n"); + if (addr == NULL) { + DPRINTK(ERR, "bad return from pci_alloc_consistent\n"); + netxen_free_hw_resources(adapter); return -ENOMEM; } - hw->pauseaddr = (char *)pause_addr; - { - u64 *ptr = (u64 *) pause_addr; - *ptr++ = NETXEN_NIC_ZERO_PAUSE_ADDR; - *ptr++ = NETXEN_NIC_ZERO_PAUSE_ADDR; - *ptr++ = NETXEN_NIC_UNIT_PAUSE_ADDR; - *ptr++ = NETXEN_NIC_ZERO_PAUSE_ADDR; - *ptr++ = NETXEN_NIC_EPG_PAUSE_ADDR1; - *ptr++ = NETXEN_NIC_EPG_PAUSE_ADDR2; - } + adapter->ctx_desc->cmd_ring_addr_lo = + hw->cmd_desc_phys_addr & 0xffffffffUL; + adapter->ctx_desc->cmd_ring_addr_hi = + ((u64) hw->cmd_desc_phys_addr >> 32); + adapter->ctx_desc->cmd_ring_size = adapter->max_tx_desc_count; hw->cmd_desc_head = (struct cmd_desc_type0 *)addr; @@ -273,6 +278,12 @@ int netxen_nic_hw_resources(struct netxen_adapter *adapter) return err; } rcv_desc->desc_head = (struct rcv_desc *)addr; + adapter->ctx_desc->rcv_ctx[ring].rcv_ring_addr_lo = + rcv_desc->phys_addr & 0xffffffffUL; + adapter->ctx_desc->rcv_ctx[ring].rcv_ring_addr_hi = + ((u64) rcv_desc->phys_addr >> 32); + adapter->ctx_desc->rcv_ctx[ring].rcv_ring_size = + rcv_desc->max_rx_desc_count; } addr = netxen_alloc(adapter->ahw.pdev, STATUS_DESC_RINGSIZE, @@ -286,47 +297,21 @@ int netxen_nic_hw_resources(struct netxen_adapter *adapter) return err; } recv_ctx->rcv_status_desc_head = (struct status_desc *)addr; - for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) { - rcv_desc = &recv_ctx->rcv_desc[ring]; - rcv_desc_crb = - &recv_crb_registers[ctx].rcv_desc_crb[ring]; - DPRINTK(INFO, "ring #%d crb global ring reg 0x%x\n", - ring, rcv_desc_crb->crb_globalrcv_ring); - /* Window = 1 */ - writel(lower32(rcv_desc->phys_addr), - NETXEN_CRB_NORMALIZE(adapter, - rcv_desc_crb-> - crb_globalrcv_ring)); - DPRINTK(INFO, "GLOBAL_RCV_RING ctx %d, addr 0x%x" - " val 0x%llx," - " virt %p\n", ctx, - rcv_desc_crb->crb_globalrcv_ring, - (unsigned long long)rcv_desc->phys_addr, - +rcv_desc->desc_head); - } + adapter->ctx_desc->sts_ring_addr_lo = + recv_ctx->rcv_status_desc_phys_addr & 0xffffffffUL; + adapter->ctx_desc->sts_ring_addr_hi = + ((u64) recv_ctx->rcv_status_desc_phys_addr >> 32); + adapter->ctx_desc->sts_ring_size = adapter->max_rx_desc_count; - /* Window = 1 */ - writel(lower32(recv_ctx->rcv_status_desc_phys_addr), - NETXEN_CRB_NORMALIZE(adapter, - recv_crb_registers[ctx]. - crb_rcvstatus_ring)); - DPRINTK(INFO, "RCVSTATUS_RING, ctx %d, addr 0x%x," - " val 0x%x,virt%p\n", - ctx, - recv_crb_registers[ctx].crb_rcvstatus_ring, - (unsigned long long)recv_ctx->rcv_status_desc_phys_addr, - recv_ctx->rcv_status_desc_head); } /* Window = 1 */ - writel(lower32(hw->pause_physaddr), - NETXEN_CRB_NORMALIZE(adapter, CRB_PAUSE_ADDR_LO)); - writel(upper32(hw->pause_physaddr), - NETXEN_CRB_NORMALIZE(adapter, CRB_PAUSE_ADDR_HI)); - - writel(lower32(hw->cmd_desc_phys_addr), - NETXEN_CRB_NORMALIZE(adapter, CRB_HOST_CMD_ADDR_LO)); - writel(upper32(hw->cmd_desc_phys_addr), - NETXEN_CRB_NORMALIZE(adapter, CRB_HOST_CMD_ADDR_HI)); + + writel(lower32(adapter->ctx_desc_phys_addr), + NETXEN_CRB_NORMALIZE(adapter, CRB_CTX_ADDR_REG_LO)); + writel(upper32(adapter->ctx_desc_phys_addr), + NETXEN_CRB_NORMALIZE(adapter, CRB_CTX_ADDR_REG_HI)); + writel(NETXEN_CTX_SIGNATURE, + NETXEN_CRB_NORMALIZE(adapter, CRB_CTX_SIGNATURE_REG)); return err; } @@ -336,6 +321,15 @@ void netxen_free_hw_resources(struct netxen_adapter *adapter) struct netxen_rcv_desc_ctx *rcv_desc; int ctx, ring; + if (adapter->ctx_desc != NULL) { + pci_free_consistent(adapter->ctx_desc_pdev, + sizeof(struct netxen_ring_ctx) + + sizeof(uint32_t), + adapter->ctx_desc, + adapter->ctx_desc_phys_addr); + adapter->ctx_desc = NULL; + } + if (adapter->ahw.cmd_desc_head != NULL) { pci_free_consistent(adapter->ahw.cmd_desc_pdev, sizeof(struct cmd_desc_type0) * @@ -344,11 +338,9 @@ void netxen_free_hw_resources(struct netxen_adapter *adapter) adapter->ahw.cmd_desc_phys_addr); adapter->ahw.cmd_desc_head = NULL; } - if (adapter->ahw.pauseaddr != NULL) { - pci_free_consistent(adapter->ahw.pause_pdev, 512, - adapter->ahw.pauseaddr, - adapter->ahw.pause_physaddr); - adapter->ahw.pauseaddr = NULL; + /* Special handling: there are 2 ports on this board */ + if (adapter->ahw.boardcfg.board_type == NETXEN_BRDTYPE_P2_SB31_10G_IMEZ) { + adapter->ahw.max_ports = 2; } for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) { @@ -383,19 +375,22 @@ void netxen_tso_check(struct netxen_adapter *adapter, desc->total_hdr_length = sizeof(struct ethhdr) + ((skb->nh.iph)->ihl * sizeof(u32)) + ((skb->h.th)->doff * sizeof(u32)); - desc->opcode = TX_TCP_LSO; + netxen_set_cmd_desc_opcode(desc, TX_TCP_LSO); } else if (skb->ip_summed == CHECKSUM_COMPLETE) { if (skb->nh.iph->protocol == IPPROTO_TCP) { - desc->opcode = TX_TCP_PKT; + netxen_set_cmd_desc_opcode(desc, TX_TCP_PKT); } else if (skb->nh.iph->protocol == IPPROTO_UDP) { - desc->opcode = TX_UDP_PKT; + netxen_set_cmd_desc_opcode(desc, TX_UDP_PKT); } else { return; } } adapter->stats.xmitcsummed++; - CMD_DESC_TCP_HDR_OFFSET_WRT(desc, skb->h.raw - skb->data); - desc->length_tcp_hdr = cpu_to_le32(desc->length_tcp_hdr); + desc->tcp_hdr_offset = skb->h.raw - skb->data; + netxen_set_cmd_desc_totallength(desc, + cpu_to_le32 + (netxen_get_cmd_desc_totallength + (desc))); desc->ip_hdr_offset = skb->nh.raw - skb->data; } @@ -648,7 +643,7 @@ void netxen_nic_reg_write(struct netxen_adapter *adapter, u64 off, u32 val) addr = NETXEN_CRB_NORMALIZE(adapter, off); DPRINTK(INFO, "writing to base %lx offset %llx addr %p data %x\n", - pci_base(adapter, off), off, addr); + pci_base(adapter, off), off, addr, val); writel(val, addr); } @@ -660,7 +655,7 @@ int netxen_nic_reg_read(struct netxen_adapter *adapter, u64 off) addr = NETXEN_CRB_NORMALIZE(adapter, off); DPRINTK(INFO, "reading from base %lx offset %llx addr %p\n", - adapter->ahw.pci_base, off, addr); + pci_base(adapter, off), off, addr); val = readl(addr); writel(val, addr); @@ -848,8 +843,8 @@ void netxen_nic_stop_all_ports(struct netxen_adapter *adapter) for (port_nr = 0; port_nr < adapter->ahw.max_ports; port_nr++) { port = adapter->port[port_nr]; - if (adapter->ops->stop_port) - adapter->ops->stop_port(adapter, port->portnum); + if (adapter->stop_port) + adapter->stop_port(adapter, port->portnum); } } @@ -873,13 +868,13 @@ void netxen_nic_set_link_parameters(struct netxen_port *port) { struct netxen_adapter *adapter = port->adapter; __le32 status; - u16 autoneg; + __le32 autoneg; __le32 mode; netxen_nic_read_w0(adapter, NETXEN_NIU_MODE, &mode); if (netxen_get_niu_enable_ge(mode)) { /* Gb 10/100/1000 Mbps mode */ - if (adapter->ops->phy_read - && adapter->ops-> + if (adapter->phy_read + && adapter-> phy_read(adapter, port->portnum, NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS, &status) == 0) { @@ -909,11 +904,11 @@ void netxen_nic_set_link_parameters(struct netxen_port *port) port->link_duplex = -1; break; } - if (adapter->ops->phy_read - && adapter->ops-> + if (adapter->phy_read + && adapter-> phy_read(adapter, port->portnum, NETXEN_NIU_GB_MII_MGMT_ADDR_AUTONEG, - (__le32 *) & autoneg) != 0) + &autoneg) != 0) port->link_autoneg = autoneg; } else goto link_down; @@ -1008,3 +1003,291 @@ int netxen_crb_read_val(struct netxen_adapter *adapter, unsigned long off) netxen_nic_hw_read_wx(adapter, off, &data, 4); return data; } + +int netxen_nic_hw_write_ioctl(struct netxen_adapter *adapter, u64 off, + void *data, int len) +{ + void *addr; + u64 offset = off; + u8 *mem_ptr = NULL; + unsigned long mem_base; + unsigned long mem_page; + + if (ADDR_IN_WINDOW1(off)) { + addr = NETXEN_CRB_NORMALIZE(adapter, off); + if (!addr) { + mem_base = pci_resource_start(adapter->ahw.pdev, 0); + offset = NETXEN_CRB_NORMAL(off); + mem_page = offset & PAGE_MASK; + if (mem_page != ((offset + len - 1) & PAGE_MASK)) + mem_ptr = + ioremap(mem_base + mem_page, PAGE_SIZE * 2); + else + mem_ptr = + ioremap(mem_base + mem_page, PAGE_SIZE); + if (mem_ptr == 0UL) { + return 1; + } + addr = mem_ptr; + addr += offset & (PAGE_SIZE - 1); + } + } else { + addr = pci_base_offset(adapter, off); + if (!addr) { + mem_base = pci_resource_start(adapter->ahw.pdev, 0); + mem_page = off & PAGE_MASK; + if (mem_page != ((off + len - 1) & PAGE_MASK)) + mem_ptr = + ioremap(mem_base + mem_page, PAGE_SIZE * 2); + else + mem_ptr = + ioremap(mem_base + mem_page, PAGE_SIZE); + if (mem_ptr == 0UL) { + return 1; + } + addr = mem_ptr; + addr += off & (PAGE_SIZE - 1); + } + netxen_nic_pci_change_crbwindow(adapter, 0); + } + switch (len) { + case 1: + writeb(*(u8 *) data, addr); + break; + case 2: + writew(*(u16 *) data, addr); + break; + case 4: + writel(*(u32 *) data, addr); + break; + case 8: + writeq(*(u64 *) data, addr); + break; + default: + DPRINTK(INFO, + "writing data %lx to offset %llx, num words=%d\n", + *(unsigned long *)data, off, (len >> 3)); + + netxen_nic_hw_block_write64((u64 __iomem *) data, addr, + (len >> 3)); + break; + } + + if (!ADDR_IN_WINDOW1(off)) + netxen_nic_pci_change_crbwindow(adapter, 1); + if (mem_ptr) + iounmap(mem_ptr); + return 0; +} + +int netxen_nic_hw_read_ioctl(struct netxen_adapter *adapter, u64 off, + void *data, int len) +{ + void *addr; + u64 offset; + u8 *mem_ptr = NULL; + unsigned long mem_base; + unsigned long mem_page; + + if (ADDR_IN_WINDOW1(off)) { + addr = NETXEN_CRB_NORMALIZE(adapter, off); + if (!addr) { + mem_base = pci_resource_start(adapter->ahw.pdev, 0); + offset = NETXEN_CRB_NORMAL(off); + mem_page = offset & PAGE_MASK; + if (mem_page != ((offset + len - 1) & PAGE_MASK)) + mem_ptr = + ioremap(mem_base + mem_page, PAGE_SIZE * 2); + else + mem_ptr = + ioremap(mem_base + mem_page, PAGE_SIZE); + if (mem_ptr == 0UL) { + *(u8 *) data = 0; + return 1; + } + addr = mem_ptr; + addr += offset & (PAGE_SIZE - 1); + } + } else { + addr = pci_base_offset(adapter, off); + if (!addr) { + mem_base = pci_resource_start(adapter->ahw.pdev, 0); + mem_page = off & PAGE_MASK; + if (mem_page != ((off + len - 1) & PAGE_MASK)) + mem_ptr = + ioremap(mem_base + mem_page, PAGE_SIZE * 2); + else + mem_ptr = + ioremap(mem_base + mem_page, PAGE_SIZE); + if (mem_ptr == 0UL) + return 1; + addr = mem_ptr; + addr += off & (PAGE_SIZE - 1); + } + netxen_nic_pci_change_crbwindow(adapter, 0); + } + switch (len) { + case 1: + *(u8 *) data = readb(addr); + break; + case 2: + *(u16 *) data = readw(addr); + break; + case 4: + *(u32 *) data = readl(addr); + break; + case 8: + *(u64 *) data = readq(addr); + break; + default: + netxen_nic_hw_block_read64((u64 __iomem *) data, addr, + (len >> 3)); + break; + } + if (!ADDR_IN_WINDOW1(off)) + netxen_nic_pci_change_crbwindow(adapter, 1); + if (mem_ptr) + iounmap(mem_ptr); + return 0; +} + +int netxen_nic_pci_mem_write_ioctl(struct netxen_adapter *adapter, u64 off, + void *data, int size) +{ + void *addr; + int ret = 0; + u8 *mem_ptr = NULL; + unsigned long mem_base; + unsigned long mem_page; + + if (data == NULL || off > (128 * 1024 * 1024)) { + printk(KERN_ERR "%s: data: %p off:%llx\n", + netxen_nic_driver_name, data, off); + return 1; + } + off = netxen_nic_pci_set_window(adapter, off); + /* Corner case : Malicious user tried to break the driver by reading + last few bytes in ranges and tries to read further addresses. + */ + if (!pci_base(adapter, off + size - 1) && pci_base(adapter, off)) { + printk(KERN_ERR "%s: Invalid access to memory address range" + " 0x%llx - 0x%llx\n", netxen_nic_driver_name, off, + off + size); + return 1; + } + addr = pci_base_offset(adapter, off); + DPRINTK(INFO, "writing data %llx to offset %llx\n", + *(unsigned long long *)data, off); + if (!addr) { + mem_base = pci_resource_start(adapter->ahw.pdev, 0); + mem_page = off & PAGE_MASK; + /* Map two pages whenever user tries to access addresses in two + consecutive pages. + */ + if (mem_page != ((off + size - 1) & PAGE_MASK)) + mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE * 2); + else + mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE); + if (mem_ptr == 0UL) { + return 1; + } + addr = mem_ptr; + addr += off & (PAGE_SIZE - 1); + } + switch (size) { + case 1: + writeb(*(u8 *) data, addr); + break; + case 2: + writew(*(u16 *) data, addr); + break; + case 4: + writel(*(u32 *) data, addr); + break; + case 8: + writeq(*(u64 *) data, addr); + break; + default: + DPRINTK(INFO, + "writing data %lx to offset %llx, num words=%d\n", + *(unsigned long *)data, off, (size >> 3)); + + netxen_nic_hw_block_write64((u64 __iomem *) data, addr, + (size >> 3)); + break; + } + + if (mem_ptr) + iounmap(mem_ptr); + DPRINTK(INFO, "wrote %llx\n", *(unsigned long long *)data); + + return ret; +} + +int netxen_nic_pci_mem_read_ioctl(struct netxen_adapter *adapter, + u64 off, void *data, int size) +{ + void *addr; + int ret = 0; + u8 *mem_ptr = NULL; + unsigned long mem_base; + unsigned long mem_page; + + if (data == NULL || off > (128 * 1024 * 1024)) { + printk(KERN_ERR "%s: data: %p off:%llx\n", + netxen_nic_driver_name, data, off); + return 1; + } + off = netxen_nic_pci_set_window(adapter, off); + /* Corner case : Malicious user tried to break the driver by reading + last few bytes in ranges and tries to read further addresses. + */ + if (!pci_base(adapter, off + size - 1) && pci_base(adapter, off)) { + printk(KERN_ERR "%s: Invalid access to memory address range" + " 0x%llx - 0x%llx\n", netxen_nic_driver_name, off, + off + size); + return 1; + } + addr = pci_base_offset(adapter, off); + if (!addr) { + mem_base = pci_resource_start(adapter->ahw.pdev, 0); + mem_page = off & PAGE_MASK; + /* Map two pages whenever user tries to access addresses in two + consecutive pages. + */ + if (mem_page != ((off + size - 1) & PAGE_MASK)) + mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE * 2); + else + mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE); + if (mem_ptr == 0UL) { + *(u8 *) data = 0; + return 1; + } + addr = mem_ptr; + addr += off & (PAGE_SIZE - 1); + } + switch (size) { + case 1: + *(u8 *) data = readb(addr); + break; + case 2: + *(u16 *) data = readw(addr); + break; + case 4: + *(u32 *) data = readl(addr); + break; + case 8: + *(u64 *) data = readq(addr); + break; + default: + netxen_nic_hw_block_read64((u64 __iomem *) data, addr, + (size >> 3)); + break; + } + + if (mem_ptr) + iounmap(mem_ptr); + DPRINTK(INFO, "read %llx\n", *(unsigned long long *)data); + + return ret; +} diff --git a/trunk/drivers/net/netxen/netxen_nic_hw.h b/trunk/drivers/net/netxen/netxen_nic_hw.h index 201a636b7ab8..0685633a9c1e 100644 --- a/trunk/drivers/net/netxen/netxen_nic_hw.h +++ b/trunk/drivers/net/netxen/netxen_nic_hw.h @@ -1,7 +1,7 @@ /* * Copyright (C) 2003 - 2006 NetXen, Inc. * All rights reserved. - * + * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 @@ -16,10 +16,10 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. - * + * * The full GNU General Public License is included in this distribution * in the file called LICENSE. - * + * * Contact Information: * info@netxen.com * NetXen, @@ -83,8 +83,8 @@ struct netxen_adapter; #define NETXEN_PCI_MAPSIZE_BYTES (NETXEN_PCI_MAPSIZE << 20) #define NETXEN_NIC_LOCKED_READ_REG(X, Y) \ - addr = pci_base_offset(adapter, (X)); \ - *(u32 *)Y = readl(addr); + addr = pci_base_offset(adapter, X); \ + *(u32 *)Y = readl((void __iomem*) addr); struct netxen_port; void netxen_nic_set_link_parameters(struct netxen_port *port); diff --git a/trunk/drivers/net/netxen/netxen_nic_init.c b/trunk/drivers/net/netxen/netxen_nic_init.c index 0dca029bc3e5..869725f0bb18 100644 --- a/trunk/drivers/net/netxen/netxen_nic_init.c +++ b/trunk/drivers/net/netxen/netxen_nic_init.c @@ -1,25 +1,25 @@ /* * Copyright (C) 2003 - 2006 NetXen, Inc. * All rights reserved. - * + * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. - * + * * The full GNU General Public License is included in this distribution * in the file called LICENSE. - * + * * Contact Information: * info@netxen.com * NetXen, @@ -137,6 +137,8 @@ int netxen_init_firmware(struct netxen_adapter *adapter) return err; } /* Window 1 call */ + writel(MPORT_SINGLE_FUNCTION_MODE, + NETXEN_CRB_NORMALIZE(adapter, CRB_MPORT_MODE)); writel(PHAN_INITIALIZE_ACK, NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE)); @@ -184,15 +186,12 @@ void netxen_initialize_adapter_sw(struct netxen_adapter *adapter) for (i = 0; i < num_rx_bufs; i++) { rx_buf->ref_handle = i; rx_buf->state = NETXEN_BUFFER_FREE; - DPRINTK(INFO, "Rx buf:ctx%d i(%d) rx_buf:" "%p\n", ctxid, i, rx_buf); rx_buf++; } } } - DPRINTK(INFO, "initialized buffers for %s and %s\n", - "adapter->free_cmd_buf_list", "adapter->free_rxbuf"); } void netxen_initialize_adapter_hw(struct netxen_adapter *adapter) @@ -212,37 +211,36 @@ void netxen_initialize_adapter_hw(struct netxen_adapter *adapter) void netxen_initialize_adapter_ops(struct netxen_adapter *adapter) { - struct netxen_drvops *ops = adapter->ops; switch (adapter->ahw.board_type) { case NETXEN_NIC_GBE: - ops->enable_phy_interrupts = + adapter->enable_phy_interrupts = netxen_niu_gbe_enable_phy_interrupts; - ops->disable_phy_interrupts = + adapter->disable_phy_interrupts = netxen_niu_gbe_disable_phy_interrupts; - ops->handle_phy_intr = netxen_nic_gbe_handle_phy_intr; - ops->macaddr_set = netxen_niu_macaddr_set; - ops->set_mtu = netxen_nic_set_mtu_gb; - ops->set_promisc = netxen_niu_set_promiscuous_mode; - ops->unset_promisc = netxen_niu_set_promiscuous_mode; - ops->phy_read = netxen_niu_gbe_phy_read; - ops->phy_write = netxen_niu_gbe_phy_write; - ops->init_port = netxen_niu_gbe_init_port; - ops->init_niu = netxen_nic_init_niu_gb; - ops->stop_port = netxen_niu_disable_gbe_port; + adapter->handle_phy_intr = netxen_nic_gbe_handle_phy_intr; + adapter->macaddr_set = netxen_niu_macaddr_set; + adapter->set_mtu = netxen_nic_set_mtu_gb; + adapter->set_promisc = netxen_niu_set_promiscuous_mode; + adapter->unset_promisc = netxen_niu_set_promiscuous_mode; + adapter->phy_read = netxen_niu_gbe_phy_read; + adapter->phy_write = netxen_niu_gbe_phy_write; + adapter->init_port = netxen_niu_gbe_init_port; + adapter->init_niu = netxen_nic_init_niu_gb; + adapter->stop_port = netxen_niu_disable_gbe_port; break; case NETXEN_NIC_XGBE: - ops->enable_phy_interrupts = + adapter->enable_phy_interrupts = netxen_niu_xgbe_enable_phy_interrupts; - ops->disable_phy_interrupts = + adapter->disable_phy_interrupts = netxen_niu_xgbe_disable_phy_interrupts; - ops->handle_phy_intr = netxen_nic_xgbe_handle_phy_intr; - ops->macaddr_set = netxen_niu_xg_macaddr_set; - ops->set_mtu = netxen_nic_set_mtu_xgb; - ops->init_port = netxen_niu_xg_init_port; - ops->set_promisc = netxen_niu_xg_set_promiscuous_mode; - ops->unset_promisc = netxen_niu_xg_set_promiscuous_mode; - ops->stop_port = netxen_niu_disable_xg_port; + adapter->handle_phy_intr = netxen_nic_xgbe_handle_phy_intr; + adapter->macaddr_set = netxen_niu_xg_macaddr_set; + adapter->set_mtu = netxen_nic_set_mtu_xgb; + adapter->init_port = netxen_niu_xg_init_port; + adapter->set_promisc = netxen_niu_xg_set_promiscuous_mode; + adapter->unset_promisc = netxen_niu_xg_set_promiscuous_mode; + adapter->stop_port = netxen_niu_disable_xg_port; break; default: @@ -383,8 +381,8 @@ int netxen_rom_wip_poll(struct netxen_adapter *adapter) return 0; } -static inline int do_rom_fast_write(struct netxen_adapter *adapter, - int addr, int data) +static inline int do_rom_fast_write(struct netxen_adapter *adapter, int addr, + int data) { if (netxen_rom_wren(adapter)) { return -1; @@ -622,6 +620,43 @@ int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose) return 0; } +int netxen_initialize_adapter_offload(struct netxen_adapter *adapter) +{ + uint64_t addr; + uint32_t hi; + uint32_t lo; + + adapter->dummy_dma.addr = + pci_alloc_consistent(adapter->ahw.pdev, + NETXEN_HOST_DUMMY_DMA_SIZE, + &adapter->dummy_dma.phys_addr); + if (adapter->dummy_dma.addr == NULL) { + printk("%s: ERROR: Could not allocate dummy DMA memory\n", + __FUNCTION__); + return -ENOMEM; + } + + addr = (uint64_t) adapter->dummy_dma.phys_addr; + hi = (addr >> 32) & 0xffffffff; + lo = addr & 0xffffffff; + + writel(hi, NETXEN_CRB_NORMALIZE(adapter, CRB_HOST_DUMMY_BUF_ADDR_HI)); + writel(lo, NETXEN_CRB_NORMALIZE(adapter, CRB_HOST_DUMMY_BUF_ADDR_LO)); + + return 0; +} + +void netxen_free_adapter_offload(struct netxen_adapter *adapter) +{ + if (adapter->dummy_dma.addr) { + pci_free_consistent(adapter->ahw.pdev, + NETXEN_HOST_DUMMY_DMA_SIZE, + adapter->dummy_dma.addr, + adapter->dummy_dma.phys_addr); + adapter->dummy_dma.addr = NULL; + } +} + void netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val) { u32 val = 0; @@ -656,7 +691,8 @@ int netxen_nic_rx_has_work(struct netxen_adapter *adapter) desc_head = recv_ctx->rcv_status_desc_head; desc = &desc_head[consumer]; - if (((le16_to_cpu(desc->owner)) & STATUS_OWNER_HOST)) + if (((le16_to_cpu(netxen_get_sts_owner(desc))) + & STATUS_OWNER_HOST)) return 1; } @@ -710,12 +746,13 @@ static inline int netxen_nic_check_temp(struct netxen_adapter *adapter) return rv; } -void netxen_watchdog_task(unsigned long v) +void netxen_watchdog_task(struct work_struct *work) { int port_num; struct netxen_port *port; struct net_device *netdev; - struct netxen_adapter *adapter = (struct netxen_adapter *)v; + struct netxen_adapter *adapter = + container_of(work, struct netxen_adapter, watchdog_task); if (netxen_nic_check_temp(adapter)) return; @@ -734,8 +771,8 @@ void netxen_watchdog_task(unsigned long v) netif_wake_queue(netdev); } - if (adapter->ops->handle_phy_intr) - adapter->ops->handle_phy_intr(adapter); + if (adapter->handle_phy_intr) + adapter->handle_phy_intr(adapter); mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ); } @@ -748,19 +785,19 @@ void netxen_process_rcv(struct netxen_adapter *adapter, int ctxid, struct status_desc *desc) { - struct netxen_port *port = adapter->port[STATUS_DESC_PORT(desc)]; + struct netxen_port *port = adapter->port[netxen_get_sts_port(desc)]; struct pci_dev *pdev = port->pdev; struct net_device *netdev = port->netdev; - int index = le16_to_cpu(desc->reference_handle); + int index = le16_to_cpu(netxen_get_sts_refhandle(desc)); struct netxen_recv_context *recv_ctx = &(adapter->recv_ctx[ctxid]); struct netxen_rx_buffer *buffer; struct sk_buff *skb; - u32 length = le16_to_cpu(desc->total_length); + u32 length = le16_to_cpu(netxen_get_sts_totallength(desc)); u32 desc_ctx; struct netxen_rcv_desc_ctx *rcv_desc; int ret; - desc_ctx = STATUS_DESC_TYPE(desc); + desc_ctx = netxen_get_sts_type(desc); if (unlikely(desc_ctx >= NUM_RCV_DESC_RINGS)) { printk("%s: %s Bad Rcv descriptor ring\n", netxen_nic_driver_name, netdev->name); @@ -768,20 +805,49 @@ netxen_process_rcv(struct netxen_adapter *adapter, int ctxid, } rcv_desc = &recv_ctx->rcv_desc[desc_ctx]; + if (unlikely(index > rcv_desc->max_rx_desc_count)) { + DPRINTK(ERR, "Got a buffer index:%x Max is %x\n", + index, rcv_desc->max_rx_desc_count); + return; + } buffer = &rcv_desc->rx_buf_arr[index]; + if (desc_ctx == RCV_DESC_LRO_CTXID) { + buffer->lro_current_frags++; + if (netxen_get_sts_desc_lro_last_frag(desc)) { + buffer->lro_expected_frags = + netxen_get_sts_desc_lro_cnt(desc); + buffer->lro_length = length; + } + if (buffer->lro_current_frags != buffer->lro_expected_frags) { + if (buffer->lro_expected_frags != 0) { + printk("LRO: (refhandle:%x) recv frag." + "wait for last. flags: %x expected:%d" + "have:%d\n", index, + netxen_get_sts_desc_lro_last_frag(desc), + buffer->lro_expected_frags, + buffer->lro_current_frags); + } + return; + } + } pci_unmap_single(pdev, buffer->dma, rcv_desc->dma_size, PCI_DMA_FROMDEVICE); skb = (struct sk_buff *)buffer->skb; - if (likely(STATUS_DESC_STATUS(desc) == STATUS_CKSUM_OK)) { + if (likely(netxen_get_sts_status(desc) == STATUS_CKSUM_OK)) { port->stats.csummed++; skb->ip_summed = CHECKSUM_UNNECESSARY; - } else - skb->ip_summed = CHECKSUM_NONE; + } skb->dev = netdev; - skb_put(skb, length); + if (desc_ctx == RCV_DESC_LRO_CTXID) { + /* True length was only available on the last pkt */ + skb_put(skb, buffer->lro_length); + } else { + skb_put(skb, length); + } + skb->protocol = eth_type_trans(skb, netdev); ret = netif_receive_skb(skb); @@ -827,6 +893,8 @@ netxen_process_rcv(struct netxen_adapter *adapter, int ctxid, adapter->stats.post_called++; buffer->skb = NULL; buffer->state = NETXEN_BUFFER_FREE; + buffer->lro_current_frags = 0; + buffer->lro_expected_frags = 0; port->stats.no_rcv++; port->stats.rxbytes += length; @@ -839,6 +907,7 @@ u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctxid, int max) struct status_desc *desc_head = recv_ctx->rcv_status_desc_head; struct status_desc *desc; /* used to read status desc here */ u32 consumer = recv_ctx->status_rx_consumer; + u32 producer = 0; int count = 0, ring; DPRINTK(INFO, "procesing receive\n"); @@ -850,18 +919,22 @@ u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctxid, int max) */ while (count < max) { desc = &desc_head[consumer]; - if (!((le16_to_cpu(desc->owner)) & STATUS_OWNER_HOST)) { - DPRINTK(ERR, "desc %p ownedby %x\n", desc, desc->owner); + if (! + (le16_to_cpu(netxen_get_sts_owner(desc)) & + STATUS_OWNER_HOST)) { + DPRINTK(ERR, "desc %p ownedby %x\n", desc, + netxen_get_sts_owner(desc)); break; } netxen_process_rcv(adapter, ctxid, desc); - desc->owner = STATUS_OWNER_PHANTOM; + netxen_clear_sts_owner(desc); + netxen_set_sts_owner(desc, STATUS_OWNER_PHANTOM); consumer = (consumer + 1) & (adapter->max_rx_desc_count - 1); count++; } if (count) { for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) { - netxen_post_rx_buffers(adapter, ctxid, ring); + netxen_post_rx_buffers_nodb(adapter, ctxid, ring); } } @@ -869,6 +942,7 @@ u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctxid, int max) if (count) { adapter->stats.process_rcv++; recv_ctx->status_rx_consumer = consumer; + recv_ctx->status_rx_producer = producer; /* Window = 1 */ writel(consumer, @@ -881,12 +955,13 @@ u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctxid, int max) } /* Process Command status ring */ -void netxen_process_cmd_ring(unsigned long data) +int netxen_process_cmd_ring(unsigned long data) { u32 last_consumer; u32 consumer; struct netxen_adapter *adapter = (struct netxen_adapter *)data; - int count = 0; + int count1 = 0; + int count2 = 0; struct netxen_cmd_buffer *buffer; struct netxen_port *port; /* port #1 */ struct netxen_port *nport; @@ -895,6 +970,7 @@ void netxen_process_cmd_ring(unsigned long data) u32 i; struct sk_buff *skb = NULL; int p; + int done; spin_lock(&adapter->tx_lock); last_consumer = adapter->last_cmd_consumer; @@ -904,14 +980,13 @@ void netxen_process_cmd_ring(unsigned long data) * number as part of the descriptor. This way we will be able to get * the netdev which is associated with that device. */ - consumer = - readl(NETXEN_CRB_NORMALIZE(adapter, CRB_CMD_CONSUMER_OFFSET)); + consumer = *(adapter->cmd_consumer); if (last_consumer == consumer) { /* Ring is empty */ DPRINTK(INFO, "last_consumer %d == consumer %d\n", last_consumer, consumer); spin_unlock(&adapter->tx_lock); - return; + return 1; } adapter->proc_cmd_buf_counter++; @@ -922,7 +997,7 @@ void netxen_process_cmd_ring(unsigned long data) */ spin_unlock(&adapter->tx_lock); - while ((last_consumer != consumer) && (count < MAX_STATUS_HANDLE)) { + while ((last_consumer != consumer) && (count1 < MAX_STATUS_HANDLE)) { buffer = &adapter->cmd_buf_arr[last_consumer]; port = adapter->port[buffer->port]; pdev = port->pdev; @@ -948,24 +1023,24 @@ void netxen_process_cmd_ring(unsigned long data) && netif_carrier_ok(port->netdev)) && ((jiffies - port->netdev->trans_start) > port->netdev->watchdog_timeo)) { - schedule_work(&port->adapter->tx_timeout_task); + SCHEDULE_WORK(&port->adapter->tx_timeout_task); } last_consumer = get_next_index(last_consumer, adapter->max_tx_desc_count); - count++; + count1++; } - adapter->stats.noxmitdone += count; + adapter->stats.noxmitdone += count1; - count = 0; + count2 = 0; spin_lock(&adapter->tx_lock); if ((--adapter->proc_cmd_buf_counter) == 0) { adapter->last_cmd_consumer = last_consumer; while ((adapter->last_cmd_consumer != consumer) - && (count < MAX_STATUS_HANDLE)) { + && (count2 < MAX_STATUS_HANDLE)) { buffer = &adapter->cmd_buf_arr[adapter->last_cmd_consumer]; - count++; + count2++; if (buffer->skb) break; else @@ -974,7 +1049,7 @@ void netxen_process_cmd_ring(unsigned long data) adapter->max_tx_desc_count); } } - if (count) { + if (count1 || count2) { for (p = 0; p < adapter->ahw.max_ports; p++) { nport = adapter->port[p]; if (netif_queue_stopped(nport->netdev) @@ -984,10 +1059,30 @@ void netxen_process_cmd_ring(unsigned long data) } } } + /* + * If everything is freed up to consumer then check if the ring is full + * If the ring is full then check if more needs to be freed and + * schedule the call back again. + * + * This happens when there are 2 CPUs. One could be freeing and the + * other filling it. If the ring is full when we get out of here and + * the card has already interrupted the host then the host can miss the + * interrupt. + * + * There is still a possible race condition and the host could miss an + * interrupt. The card has to take care of this. + */ + if (adapter->last_cmd_consumer == consumer && + (((adapter->cmd_producer + 1) % + adapter->max_tx_desc_count) == adapter->last_cmd_consumer)) { + consumer = *(adapter->cmd_consumer); + } + done = (adapter->last_cmd_consumer == consumer); spin_unlock(&adapter->tx_lock); DPRINTK(INFO, "last consumer is %d in %s\n", last_consumer, __FUNCTION__); + return (done); } /* @@ -999,17 +1094,16 @@ void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, u32 ringid) struct sk_buff *skb; struct netxen_recv_context *recv_ctx = &(adapter->recv_ctx[ctx]); struct netxen_rcv_desc_ctx *rcv_desc = NULL; - struct netxen_recv_crb *crbarea = &recv_crb_registers[ctx]; - struct netxen_rcv_desc_crb *rcv_desc_crb = NULL; - u32 producer; + uint producer; struct rcv_desc *pdesc; struct netxen_rx_buffer *buffer; int count = 0; int index = 0; + netxen_ctx_msg msg = 0; + dma_addr_t dma; adapter->stats.post_called++; rcv_desc = &recv_ctx->rcv_desc[ringid]; - rcv_desc_crb = &crbarea->rcv_desc_crb[ringid]; producer = rcv_desc->producer; index = rcv_desc->begin_alloc; @@ -1019,6 +1113,7 @@ void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, u32 ringid) skb = dev_alloc_skb(rcv_desc->skb_size); if (unlikely(!skb)) { /* + * TODO * We need to schedule the posting of buffers to the pegs. */ rcv_desc->begin_alloc = index; @@ -1026,9 +1121,105 @@ void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, u32 ringid) " allocated only %d buffers\n", count); break; } + count++; /* now there should be no failure */ pdesc = &rcv_desc->desc_head[producer]; - skb_reserve(skb, NET_IP_ALIGN); + +#if defined(XGB_DEBUG) + *(unsigned long *)(skb->head) = 0xc0debabe; + if (skb_is_nonlinear(skb)) { + printk("Allocated SKB @%p is nonlinear\n"); + } +#endif + skb_reserve(skb, 2); + /* This will be setup when we receive the + * buffer after it has been filled FSL TBD TBD + * skb->dev = netdev; + */ + dma = pci_map_single(pdev, skb->data, rcv_desc->dma_size, + PCI_DMA_FROMDEVICE); + pdesc->addr_buffer = dma; + buffer->skb = skb; + buffer->state = NETXEN_BUFFER_BUSY; + buffer->dma = dma; + /* make a rcv descriptor */ + pdesc->reference_handle = buffer->ref_handle; + pdesc->buffer_length = rcv_desc->dma_size; + DPRINTK(INFO, "done writing descripter\n"); + producer = + get_next_index(producer, rcv_desc->max_rx_desc_count); + index = get_next_index(index, rcv_desc->max_rx_desc_count); + buffer = &rcv_desc->rx_buf_arr[index]; + } + /* if we did allocate buffers, then write the count to Phantom */ + if (count) { + rcv_desc->begin_alloc = index; + rcv_desc->rcv_pending += count; + adapter->stats.lastposted = count; + adapter->stats.posted += count; + rcv_desc->producer = producer; + if (rcv_desc->rcv_free >= 32) { + rcv_desc->rcv_free = 0; + /* Window = 1 */ + writel((producer - 1) & + (rcv_desc->max_rx_desc_count - 1), + NETXEN_CRB_NORMALIZE(adapter, + recv_crb_registers[0]. + rcv_desc_crb[ringid]. + crb_rcv_producer_offset)); + /* + * Write a doorbell msg to tell phanmon of change in + * receive ring producer + */ + netxen_set_msg_peg_id(msg, NETXEN_RCV_PEG_DB_ID); + netxen_set_msg_privid(msg); + netxen_set_msg_count(msg, + ((producer - + 1) & (rcv_desc-> + max_rx_desc_count - 1))); + netxen_set_msg_ctxid(msg, 0); + netxen_set_msg_opcode(msg, NETXEN_RCV_PRODUCER(ringid)); + writel(msg, + DB_NORMALIZE(adapter, + NETXEN_RCV_PRODUCER_OFFSET)); + } + } +} + +void netxen_post_rx_buffers_nodb(struct netxen_adapter *adapter, uint32_t ctx, + uint32_t ringid) +{ + struct pci_dev *pdev = adapter->ahw.pdev; + struct sk_buff *skb; + struct netxen_recv_context *recv_ctx = &(adapter->recv_ctx[ctx]); + struct netxen_rcv_desc_ctx *rcv_desc = NULL; + u32 producer; + struct rcv_desc *pdesc; + struct netxen_rx_buffer *buffer; + int count = 0; + int index = 0; + + adapter->stats.post_called++; + rcv_desc = &recv_ctx->rcv_desc[ringid]; + + producer = rcv_desc->producer; + index = rcv_desc->begin_alloc; + buffer = &rcv_desc->rx_buf_arr[index]; + /* We can start writing rx descriptors into the phantom memory. */ + while (buffer->state == NETXEN_BUFFER_FREE) { + skb = dev_alloc_skb(rcv_desc->skb_size); + if (unlikely(!skb)) { + /* + * We need to schedule the posting of buffers to the pegs. + */ + rcv_desc->begin_alloc = index; + DPRINTK(ERR, "netxen_post_rx_buffers_nodb: " + " allocated only %d buffers\n", count); + break; + } + count++; /* now there should be no failure */ + pdesc = &rcv_desc->desc_head[producer]; + skb_reserve(skb, 2); /* * This will be setup when we receive the * buffer after it has been filled @@ -1039,6 +1230,7 @@ void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, u32 ringid) buffer->dma = pci_map_single(pdev, skb->data, rcv_desc->dma_size, PCI_DMA_FROMDEVICE); + /* make a rcv descriptor */ pdesc->reference_handle = le16_to_cpu(buffer->ref_handle); pdesc->buffer_length = le16_to_cpu(rcv_desc->dma_size); @@ -1063,7 +1255,8 @@ void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, u32 ringid) writel((producer - 1) & (rcv_desc->max_rx_desc_count - 1), NETXEN_CRB_NORMALIZE(adapter, - rcv_desc_crb-> + recv_crb_registers[0]. + rcv_desc_crb[ringid]. crb_rcv_producer_offset)); wmb(); } @@ -1196,8 +1389,8 @@ netxen_nic_do_ioctl(struct netxen_adapter *adapter, void *u_data, switch (data.cmd) { case netxen_nic_cmd_pci_read: - if ((retval = netxen_nic_hw_read_wx(adapter, data.off, - &(data.u), data.size))) + if ((retval = netxen_nic_hw_read_ioctl(adapter, data.off, + &(data.u), data.size))) goto error_out; if (copy_to_user ((void __user *)&(up_data->u), &(data.u), data.size)) { @@ -1210,8 +1403,35 @@ netxen_nic_do_ioctl(struct netxen_adapter *adapter, void *u_data, break; case netxen_nic_cmd_pci_write: - data.rv = netxen_nic_hw_write_wx(adapter, data.off, &(data.u), - data.size); + if ((retval = netxen_nic_hw_write_ioctl(adapter, data.off, + &(data.u), data.size))) + goto error_out; + data.rv = 0; + break; + + case netxen_nic_cmd_pci_mem_read: + if (netxen_nic_pci_mem_read_ioctl(adapter, data.off, &(data.u), + data.size)) { + DPRINTK(ERR, "Failed to read the data.\n"); + retval = -EFAULT; + goto error_out; + } + if (copy_to_user + ((void __user *)&(up_data->u), &(data.u), data.size)) { + DPRINTK(ERR, "bad copy to userland: %d\n", + (int)sizeof(data)); + retval = -EFAULT; + goto error_out; + } + data.rv = 0; + break; + + case netxen_nic_cmd_pci_mem_write: + if ((retval = netxen_nic_pci_mem_write_ioctl(adapter, data.off, + &(data.u), + data.size))) + goto error_out; + data.rv = 0; break; case netxen_nic_cmd_pci_config_read: @@ -1296,7 +1516,7 @@ netxen_nic_do_ioctl(struct netxen_adapter *adapter, void *u_data, retval = -EOPNOTSUPP; goto error_out; } - put_user(data.rv, (u16 __user *) (&(up_data->rv))); + put_user(data.rv, (&(up_data->rv))); DPRINTK(INFO, "done ioctl for %p well.\n", adapter); error_out: diff --git a/trunk/drivers/net/netxen/netxen_nic_ioctl.h b/trunk/drivers/net/netxen/netxen_nic_ioctl.h index 23e53adbf123..1221fa527552 100644 --- a/trunk/drivers/net/netxen/netxen_nic_ioctl.h +++ b/trunk/drivers/net/netxen/netxen_nic_ioctl.h @@ -1,7 +1,7 @@ /* * Copyright (C) 2003 - 2006 NetXen, Inc. * All rights reserved. - * + * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 @@ -16,10 +16,10 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. - * + * * The full GNU General Public License is included in this distribution * in the file called LICENSE. - * + * * Contact Information: * info@netxen.com * NetXen, @@ -36,7 +36,7 @@ #define NETXEN_NIC_CMD (NETXEN_CMD_START + 1) #define NETXEN_NIC_NAME (NETXEN_CMD_START + 2) #define NETXEN_NIC_NAME_LEN 16 -#define NETXEN_NIC_NAME_RSP "NETXEN" +#define NETXEN_NIC_NAME_RSP "NETXEN-UNM" typedef enum { netxen_nic_cmd_none = 0, diff --git a/trunk/drivers/net/netxen/netxen_nic_isr.c b/trunk/drivers/net/netxen/netxen_nic_isr.c index ae180fee8008..1b45f50fa6aa 100644 --- a/trunk/drivers/net/netxen/netxen_nic_isr.c +++ b/trunk/drivers/net/netxen/netxen_nic_isr.c @@ -1,7 +1,7 @@ /* * Copyright (C) 2003 - 2006 NetXen, Inc. * All rights reserved. - * + * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 @@ -16,10 +16,10 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. - * + * * The full GNU General Public License is included in this distribution * in the file called LICENSE. - * + * * Contact Information: * info@netxen.com * NetXen, @@ -68,8 +68,7 @@ struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev) void netxen_indicate_link_status(struct netxen_adapter *adapter, u32 portno, u32 link) { - struct netxen_port *pport = adapter->port[portno]; - struct net_device *netdev = pport->netdev; + struct net_device *netdev = (adapter->port[portno])->netdev; if (link) netif_carrier_on(netdev); @@ -84,46 +83,41 @@ void netxen_handle_port_int(struct netxen_adapter *adapter, u32 portno, struct netxen_port *port; /* This should clear the interrupt source */ - if (adapter->ops->phy_read) - adapter->ops->phy_read(adapter, portno, - NETXEN_NIU_GB_MII_MGMT_ADDR_INT_STATUS, - &int_src); + if (adapter->phy_read) + adapter->phy_read(adapter, portno, + NETXEN_NIU_GB_MII_MGMT_ADDR_INT_STATUS, + &int_src); if (int_src == 0) { DPRINTK(INFO, "No phy interrupts for port #%d\n", portno); return; } - if (adapter->ops->disable_phy_interrupts) - adapter->ops->disable_phy_interrupts(adapter, portno); + if (adapter->disable_phy_interrupts) + adapter->disable_phy_interrupts(adapter, portno); port = adapter->port[portno]; if (netxen_get_phy_int_jabber(int_src)) - DPRINTK(INFO, "NetXen: %s Jabber interrupt \n", - port->netdev->name); + DPRINTK(INFO, "Jabber interrupt \n"); if (netxen_get_phy_int_polarity_changed(int_src)) - DPRINTK(INFO, "NetXen: %s POLARITY CHANGED int \n", - port->netdev->name); + DPRINTK(INFO, "POLARITY CHANGED int \n"); if (netxen_get_phy_int_energy_detect(int_src)) - DPRINTK(INFO, "NetXen: %s ENERGY DETECT INT \n", - port->netdev->name); + DPRINTK(INFO, "ENERGY DETECT INT \n"); if (netxen_get_phy_int_downshift(int_src)) - DPRINTK(INFO, "NetXen: %s DOWNSHIFT INT \n", - port->netdev->name); + DPRINTK(INFO, "DOWNSHIFT INT \n"); /* write it down later.. */ if ((netxen_get_phy_int_speed_changed(int_src)) || (netxen_get_phy_int_link_status_changed(int_src))) { __le32 status; - DPRINTK(INFO, "NetXen: %s SPEED CHANGED OR" - " LINK STATUS CHANGED \n", port->netdev->name); + DPRINTK(INFO, "SPEED CHANGED OR LINK STATUS CHANGED \n"); - if (adapter->ops->phy_read - && adapter->ops->phy_read(adapter, portno, - NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS, - &status) == 0) { + if (adapter->phy_read + && adapter->phy_read(adapter, portno, + NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS, + &status) == 0) { if (netxen_get_phy_int_link_status_changed(int_src)) { if (netxen_get_phy_link(status)) { netxen_niu_gbe_init_port(adapter, @@ -143,8 +137,8 @@ void netxen_handle_port_int(struct netxen_adapter *adapter, u32 portno, } } } - if (adapter->ops->enable_phy_interrupts) - adapter->ops->enable_phy_interrupts(adapter, portno); + if (adapter->enable_phy_interrupts) + adapter->enable_phy_interrupts(adapter, portno); } void netxen_nic_isr_other(struct netxen_adapter *adapter) @@ -159,8 +153,7 @@ void netxen_nic_isr_other(struct netxen_adapter *adapter) qg_linksup = adapter->ahw.qg_linksup; adapter->ahw.qg_linksup = val; - DPRINTK(1, INFO, "%s: link update 0x%08x\n", netxen_nic_driver_name, - val); + DPRINTK(INFO, "link update 0x%08x\n", val); for (portno = 0; portno < NETXEN_NIU_MAX_GBE_PORTS; portno++) { linkup = val & 1; if (linkup != (qg_linksup & 1)) { diff --git a/trunk/drivers/net/netxen/netxen_nic_main.c b/trunk/drivers/net/netxen/netxen_nic_main.c index 1cb662d5bd76..575b71b67202 100644 --- a/trunk/drivers/net/netxen/netxen_nic_main.c +++ b/trunk/drivers/net/netxen/netxen_nic_main.c @@ -1,25 +1,25 @@ /* * Copyright (C) 2003 - 2006 NetXen, Inc. * All rights reserved. - * + * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. - * + * * The full GNU General Public License is included in this distribution * in the file called LICENSE. - * + * * Contact Information: * info@netxen.com * NetXen, @@ -32,6 +32,7 @@ */ #include +#include #include "netxen_nic_hw.h" #include "netxen_nic.h" @@ -48,14 +49,21 @@ MODULE_DESCRIPTION("NetXen Multi port (1/10) Gigabit Network Driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(NETXEN_NIC_LINUX_VERSIONID); -char netxen_nic_driver_name[] = "netxen"; +char netxen_nic_driver_name[] = "netxen-nic"; static char netxen_nic_driver_string[] = "NetXen Network Driver version " NETXEN_NIC_LINUX_VERSIONID; +struct netxen_adapter *g_adapter = NULL; + #define NETXEN_NETDEV_WEIGHT 120 #define NETXEN_ADAPTER_UP_MAGIC 777 #define NETXEN_NIC_PEG_TUNE 0 +u8 nx_p2_id = NX_P2_C0; + +#define DMA_32BIT_MASK 0x00000000ffffffffULL +#define DMA_35BIT_MASK 0x00000007ffffffffULL + /* Local functions to NetXen NIC driver */ static int __devinit netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent); @@ -64,7 +72,7 @@ static int netxen_nic_open(struct net_device *netdev); static int netxen_nic_close(struct net_device *netdev); static int netxen_nic_xmit_frame(struct sk_buff *, struct net_device *); static void netxen_tx_timeout(struct net_device *netdev); -static void netxen_tx_timeout_task(struct net_device *netdev); +static void netxen_tx_timeout_task(struct work_struct *work); static void netxen_watchdog(unsigned long); static int netxen_handle_int(struct netxen_adapter *, struct net_device *); static int netxen_nic_ioctl(struct net_device *netdev, @@ -87,6 +95,9 @@ static struct pci_device_id netxen_pci_tbl[] __devinitdata = { MODULE_DEVICE_TABLE(pci, netxen_pci_tbl); +struct workqueue_struct *netxen_workq; +static void netxen_watchdog(unsigned long); + /* * netxen_nic_probe() * @@ -105,20 +116,28 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) struct net_device *netdev = NULL; struct netxen_adapter *adapter = NULL; struct netxen_port *port = NULL; - u8 *mem_ptr0 = NULL; - u8 *mem_ptr1 = NULL; - u8 *mem_ptr2 = NULL; + void __iomem *mem_ptr0 = NULL; + void __iomem *mem_ptr1 = NULL; + void __iomem *mem_ptr2 = NULL; - unsigned long mem_base, mem_len; + u8 *db_ptr = NULL; + unsigned long mem_base, mem_len, db_base, db_len; int pci_using_dac, i, err; int ring; struct netxen_recv_context *recv_ctx = NULL; struct netxen_rcv_desc_ctx *rcv_desc = NULL; struct netxen_cmd_buffer *cmd_buf_arr = NULL; u64 mac_addr[FLASH_NUM_PORTS + 1]; - int valid_mac; + int valid_mac = 0; + static int netxen_cards_found = 0; printk(KERN_INFO "%s \n", netxen_nic_driver_string); + /* In current scheme, we use only PCI function 0 */ + if (PCI_FUNC(pdev->devfn) != 0) { + DPRINTK(ERR, "NetXen function %d will not be enabled.\n", + PCI_FUNC(pdev->devfn)); + return -ENODEV; + } if ((err = pci_enable_device(pdev))) return err; if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { @@ -130,10 +149,12 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto err_out_disable_pdev; pci_set_master(pdev); - if ((pci_set_dma_mask(pdev, DMA_64BIT_MASK) == 0) && - (pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK) == 0)) + pci_read_config_byte(pdev, PCI_REVISION_ID, &nx_p2_id); + if (nx_p2_id == NX_P2_C1 && + (pci_set_dma_mask(pdev, DMA_35BIT_MASK) == 0) && + (pci_set_consistent_dma_mask(pdev, DMA_35BIT_MASK) == 0)) { pci_using_dac = 1; - else { + } else { if ((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK)) || (err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK))) goto err_out_free_res; @@ -153,21 +174,34 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ioremap(mem_base + THIRD_PAGE_GROUP_START, THIRD_PAGE_GROUP_SIZE); if ((mem_ptr0 == 0UL) || (mem_ptr1 == 0UL) || (mem_ptr2 == 0UL)) { - DPRINTK(1, ERR, + DPRINTK(ERR, "Cannot remap adapter memory aborting.:" "0 -> %p, 1 -> %p, 2 -> %p\n", mem_ptr0, mem_ptr1, mem_ptr2); err = -EIO; - if (mem_ptr0) - iounmap(mem_ptr0); - if (mem_ptr1) - iounmap(mem_ptr1); - if (mem_ptr2) - iounmap(mem_ptr2); - - goto err_out_free_res; + goto err_out_iounmap; + } + db_base = pci_resource_start(pdev, 4); /* doorbell is on bar 4 */ + db_len = pci_resource_len(pdev, 4); + + if (db_len == 0) { + printk(KERN_ERR "%s: doorbell is disabled\n", + netxen_nic_driver_name); + err = -EIO; + goto err_out_iounmap; + } + DPRINTK(INFO, "doorbell ioremap from %lx a size of %lx\n", db_base, + db_len); + + db_ptr = ioremap(db_base, NETXEN_DB_MAPSIZE_BYTES); + if (db_ptr == 0UL) { + printk(KERN_ERR "%s: Failed to allocate doorbell map.", + netxen_nic_driver_name); + err = -EIO; + goto err_out_iounmap; } + DPRINTK(INFO, "doorbell ioremaped at %p\n", db_ptr); /* * Allocate a adapter structure which will manage all the initialization @@ -183,17 +217,24 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) netxen_nic_driver_name, (int)sizeof(struct netxen_adapter)); err = -ENOMEM; - goto err_out_iounmap; + goto err_out_dbunmap; } + if (netxen_cards_found == 0) { + g_adapter = adapter; + } adapter->max_tx_desc_count = MAX_CMD_DESCRIPTORS; adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS; adapter->max_jumbo_rx_desc_count = MAX_JUMBO_RCV_DESCRIPTORS; + adapter->max_lro_rx_desc_count = MAX_LRO_RCV_DESCRIPTORS; pci_set_drvdata(pdev, adapter); cmd_buf_arr = (struct netxen_cmd_buffer *)vmalloc(TX_RINGSIZE); if (cmd_buf_arr == NULL) { + printk(KERN_ERR + "%s: Could not allocate cmd_buf_arr memory:%d\n", + netxen_nic_driver_name, (int)TX_RINGSIZE); err = -ENOMEM; goto err_out_free_adapter; } @@ -220,11 +261,23 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) rcv_desc->skb_size = MAX_RX_JUMBO_BUFFER_LENGTH; break; + case RCV_RING_LRO: + rcv_desc->max_rx_desc_count = + adapter->max_lro_rx_desc_count; + rcv_desc->flags = RCV_DESC_LRO; + rcv_desc->dma_size = RX_LRO_DMA_MAP_LEN; + rcv_desc->skb_size = MAX_RX_LRO_BUFFER_LENGTH; + break; + } rcv_desc->rx_buf_arr = (struct netxen_rx_buffer *) vmalloc(RCV_BUFFSIZE); if (rcv_desc->rx_buf_arr == NULL) { + printk(KERN_ERR "%s: Could not allocate" + "rcv_desc->rx_buf_arr memory:%d\n", + netxen_nic_driver_name, + (int)RCV_BUFFSIZE); err = -ENOMEM; goto err_out_free_rx_buffer; } @@ -233,30 +286,21 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) } - adapter->ops = kzalloc(sizeof(struct netxen_drvops), GFP_KERNEL); - if (adapter->ops == NULL) { - printk(KERN_ERR - "%s: Could not allocate memory for adapter->ops:%d\n", - netxen_nic_driver_name, - (int)sizeof(struct netxen_adapter)); - err = -ENOMEM; - goto err_out_free_rx_buffer; - } - adapter->cmd_buf_arr = cmd_buf_arr; adapter->ahw.pci_base0 = mem_ptr0; adapter->ahw.pci_base1 = mem_ptr1; adapter->ahw.pci_base2 = mem_ptr2; + adapter->ahw.db_base = db_ptr; + adapter->ahw.db_len = db_len; spin_lock_init(&adapter->tx_lock); spin_lock_init(&adapter->lock); + netxen_initialize_adapter_sw(adapter); /* initialize the buffers in adapter */ #ifdef CONFIG_IA64 netxen_pinit_from_rom(adapter, 0); udelay(500); netxen_load_firmware(adapter); #endif - /* initialize the buffers in adapter */ - netxen_initialize_adapter_sw(adapter); /* * Set the CRB window to invalid. If any register in window 0 is * accessed it should set the window to 0 and then reset it to 1. @@ -274,11 +318,10 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) adapter->ahw.xg_linkup = 0; adapter->watchdog_timer.function = &netxen_watchdog; adapter->watchdog_timer.data = (unsigned long)adapter; - INIT_WORK(&adapter->watchdog_task, - (void (*)(void *))netxen_watchdog_task, adapter); + INIT_WORK(&adapter->watchdog_task, netxen_watchdog_task); adapter->ahw.pdev = pdev; adapter->proc_cmd_buf_counter = 0; - pci_read_config_byte(pdev, PCI_REVISION_ID, &adapter->ahw.revision_id); + adapter->ahw.revision_id = nx_p2_id; if (pci_enable_msi(pdev)) { adapter->flags &= ~NETXEN_NIC_MSI_ENABLED; @@ -300,6 +343,12 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) writel(0, NETXEN_CRB_NORMALIZE(adapter, CRB_CMD_CONSUMER_OFFSET)); writel(0, NETXEN_CRB_NORMALIZE(adapter, CRB_HOST_CMD_ADDR_LO)); + /* do this before waking up pegs so that we have valid dummy dma addr */ + err = netxen_initialize_adapter_offload(adapter); + if (err) { + goto err_out_free_dev; + } + /* Unlock the HW, prompting the boot sequence */ writel(1, NETXEN_CRB_NORMALIZE(adapter, NETXEN_ROMUSB_GLB_PEGTUNE_DONE)); @@ -308,6 +357,7 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE); /* initialize the all the ports */ + adapter->active_ports = 0; for (i = 0; i < adapter->ahw.max_ports; i++) { netdev = alloc_etherdev(sizeof(struct netxen_port)); @@ -373,14 +423,13 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) netdev->dev_addr[4], netdev->dev_addr[5]); } else { - if (adapter->ops->macaddr_set) - adapter->ops->macaddr_set(port, - netdev-> - dev_addr); + if (adapter->macaddr_set) + adapter->macaddr_set(port, + netdev->dev_addr); } } - INIT_WORK(&adapter->tx_timeout_task, - (void (*)(void *))netxen_tx_timeout_task, netdev); + adapter->netdev = netdev; + INIT_WORK(&adapter->tx_timeout_task, netxen_tx_timeout_task); netif_carrier_off(netdev); netif_stop_queue(netdev); @@ -392,7 +441,6 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto err_out_free_dev; } adapter->port_count++; - adapter->active_ports = 0; adapter->port[i] = port; } @@ -413,6 +461,7 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) break; } + adapter->number = netxen_cards_found; adapter->driver_mismatch = 0; return 0; @@ -427,7 +476,8 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) free_netdev(port->netdev); } } - kfree(adapter->ops); + + netxen_free_adapter_offload(adapter); err_out_free_rx_buffer: for (i = 0; i < MAX_RCV_CTX; ++i) { @@ -440,19 +490,23 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) } } } - vfree(cmd_buf_arr); - kfree(adapter->port); - err_out_free_adapter: pci_set_drvdata(pdev, NULL); kfree(adapter); + err_out_dbunmap: + if (db_ptr) + iounmap(db_ptr); + err_out_iounmap: - iounmap(mem_ptr0); - iounmap(mem_ptr1); - iounmap(mem_ptr2); + if (mem_ptr0) + iounmap(mem_ptr0); + if (mem_ptr1) + iounmap(mem_ptr1); + if (mem_ptr2) + iounmap(mem_ptr2); err_out_free_res: pci_release_regions(pdev); @@ -477,12 +531,8 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev) netxen_nic_stop_all_ports(adapter); /* leave the hw in the same state as reboot */ - netxen_pinit_from_rom(adapter, 0); - udelay(500); netxen_load_firmware(adapter); - - if ((adapter->flags & NETXEN_NIC_MSI_ENABLED)) - netxen_nic_disable_int(adapter); + netxen_free_adapter_offload(adapter); udelay(500); /* Delay for a while to drain the DMA engines */ for (i = 0; i < adapter->port_count; i++) { @@ -499,6 +549,7 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev) if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) netxen_free_hw_resources(adapter); + iounmap(adapter->ahw.db_base); iounmap(adapter->ahw.pci_base0); iounmap(adapter->ahw.pci_base1); iounmap(adapter->ahw.pci_base2); @@ -525,7 +576,6 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev) } vfree(adapter->cmd_buf_arr); - kfree(adapter->ops); kfree(adapter); } @@ -547,6 +597,8 @@ static int netxen_nic_open(struct net_device *netdev) return -EIO; } netxen_nic_flash_print(adapter); + if (adapter->init_niu) + adapter->init_niu(adapter); /* setup all the resources for the Phantom... */ /* this include the descriptors for rcv, tx, and status */ @@ -557,32 +609,31 @@ static int netxen_nic_open(struct net_device *netdev) err); return err; } - if (adapter->ops->init_port - && adapter->ops->init_port(adapter, port->portnum) != 0) { + if (adapter->init_port + && adapter->init_port(adapter, port->portnum) != 0) { printk(KERN_ERR "%s: Failed to initialize port %d\n", netxen_nic_driver_name, port->portnum); netxen_free_hw_resources(adapter); return -EIO; } - if (adapter->ops->init_niu) - adapter->ops->init_niu(adapter); for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) { for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) netxen_post_rx_buffers(adapter, ctx, ring); } - adapter->is_up = NETXEN_ADAPTER_UP_MAGIC; - } - adapter->active_ports++; - if (adapter->active_ports == 1) { + adapter->irq = adapter->ahw.pdev->irq; err = request_irq(adapter->ahw.pdev->irq, &netxen_intr, SA_SHIRQ | SA_SAMPLE_RANDOM, netdev->name, adapter); if (err) { printk(KERN_ERR "request_irq failed with: %d\n", err); - adapter->active_ports--; + netxen_free_hw_resources(adapter); return err; } - adapter->irq = adapter->ahw.pdev->irq; + + adapter->is_up = NETXEN_ADAPTER_UP_MAGIC; + } + adapter->active_ports++; + if (adapter->active_ports == 1) { if (!adapter->driver_mismatch) mod_timer(&adapter->watchdog_timer, jiffies); @@ -591,11 +642,14 @@ static int netxen_nic_open(struct net_device *netdev) /* Done here again so that even if phantom sw overwrote it, * we set it */ - if (adapter->ops->macaddr_set) - adapter->ops->macaddr_set(port, netdev->dev_addr); + if (adapter->macaddr_set) + adapter->macaddr_set(port, netdev->dev_addr); netxen_nic_set_link_parameters(port); netxen_nic_set_multi(netdev); + if (adapter->set_mtu) + adapter->set_mtu(port, netdev->mtu); + if (!adapter->driver_mismatch) netif_start_queue(netdev); @@ -648,6 +702,7 @@ static int netxen_nic_close(struct net_device *netdev) } cmd_buff++; } + FLUSH_SCHEDULED_WORK(); del_timer_sync(&adapter->watchdog_timer); } @@ -668,7 +723,6 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) struct cmd_desc_type0 *hwdesc; int k; struct netxen_cmd_buffer *pbuf = NULL; - unsigned int tries = 0; static int dropped_packet = 0; int frag_count; u32 local_producer = 0; @@ -730,7 +784,7 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) if (((skb->nh.iph)->ihl * sizeof(u32)) + ((skb->h.th)->doff * sizeof(u32)) + sizeof(struct ethhdr) > - (sizeof(struct cmd_desc_type0) - NET_IP_ALIGN)) { + (sizeof(struct cmd_desc_type0) - 2)) { no_of_desc++; } } @@ -741,27 +795,17 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) if ((k + no_of_desc) >= ((last_cmd_consumer <= k) ? last_cmd_consumer + max_tx_desc_count : last_cmd_consumer)) { + port->stats.nocmddescriptor++; + DPRINTK(ERR, "No command descriptors available," + " producer = %d, consumer = %d count=%llu," + " dropping packet\n", producer, + adapter->last_cmd_consumer, + port->stats.nocmddescriptor); + + netif_stop_queue(netdev); + port->flags |= NETXEN_NETDEV_STATUS; spin_unlock_bh(&adapter->tx_lock); - if (tries == 0) { - local_bh_disable(); - netxen_process_cmd_ring((unsigned long)adapter); - local_bh_enable(); - ++tries; - goto retry_getting_window; - } else { - port->stats.nocmddescriptor++; - DPRINTK(ERR, "No command descriptors available," - " producer = %d, consumer = %d count=%llu," - " dropping packet\n", producer, - adapter->last_cmd_consumer, - port->stats.nocmddescriptor); - - spin_lock_bh(&adapter->tx_lock); - netif_stop_queue(netdev); - port->flags |= NETXEN_NETDEV_STATUS; - spin_unlock_bh(&adapter->tx_lock); - return NETDEV_TX_BUSY; - } + return NETDEV_TX_BUSY; } k = get_index_range(k, max_tx_desc_count, no_of_desc); adapter->cmd_producer = k; @@ -783,7 +827,6 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) pbuf->mss = 0; hwdesc->mss = 0; } - pbuf->no_of_descriptors = no_of_desc; pbuf->total_length = skb->len; pbuf->skb = skb; pbuf->cmd = TX_ETHER_PKT; @@ -793,11 +836,11 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) buffrag->dma = pci_map_single(port->pdev, skb->data, first_seg_len, PCI_DMA_TODEVICE); buffrag->length = first_seg_len; - CMD_DESC_TOTAL_LENGTH_WRT(hwdesc, skb->len); - hwdesc->num_of_buffers = frag_count; - hwdesc->opcode = TX_ETHER_PKT; + netxen_set_cmd_desc_totallength(hwdesc, skb->len); + netxen_set_cmd_desc_num_of_buff(hwdesc, frag_count); + netxen_set_cmd_desc_opcode(hwdesc, TX_ETHER_PKT); - CMD_DESC_PORT_WRT(hwdesc, port->portnum); + netxen_set_cmd_desc_port(hwdesc, port->portnum); hwdesc->buffer1_length = cpu_to_le16(first_seg_len); hwdesc->addr_buffer1 = cpu_to_le64(buffrag->dma); @@ -856,12 +899,12 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) /* For LSO, we need to copy the MAC/IP/TCP headers into * the descriptor ring */ - if (hw->cmd_desc_head[saved_producer].opcode == TX_TCP_LSO) { + if (netxen_get_cmd_desc_opcode(&hw->cmd_desc_head[saved_producer]) + == TX_TCP_LSO) { int hdr_len, first_hdr_len, more_hdr; hdr_len = hw->cmd_desc_head[saved_producer].total_hdr_length; - if (hdr_len > (sizeof(struct cmd_desc_type0) - NET_IP_ALIGN)) { - first_hdr_len = - sizeof(struct cmd_desc_type0) - NET_IP_ALIGN; + if (hdr_len > (sizeof(struct cmd_desc_type0) - 2)) { + first_hdr_len = sizeof(struct cmd_desc_type0) - 2; more_hdr = 1; } else { first_hdr_len = hdr_len; @@ -871,7 +914,7 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) hwdesc = &hw->cmd_desc_head[producer]; /* copy the first 64 bytes */ - memcpy(((void *)hwdesc) + NET_IP_ALIGN, + memcpy(((void *)hwdesc) + 2, (void *)(skb->data), first_hdr_len); producer = get_next_index(producer, max_tx_desc_count); @@ -887,7 +930,7 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) } spin_lock_bh(&adapter->tx_lock); port->stats.txbytes += - CMD_DESC_TOTAL_LENGTH(&hw->cmd_desc_head[saved_producer]); + netxen_get_cmd_desc_totallength(&hw->cmd_desc_head[saved_producer]); /* Code to update the adapter considering how many producer threads are currently working */ if ((--adapter->num_threads) == 0) { @@ -897,20 +940,6 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) NETXEN_CRB_NORMALIZE(adapter, CRB_CMD_PRODUCER_OFFSET)); wmb(); adapter->total_threads = 0; - } else { - u32 crb_producer = 0; - crb_producer = - readl(NETXEN_CRB_NORMALIZE - (adapter, CRB_CMD_PRODUCER_OFFSET)); - if (crb_producer == local_producer) { - crb_producer = get_index_range(crb_producer, - max_tx_desc_count, - no_of_desc); - writel(crb_producer, - NETXEN_CRB_NORMALIZE(adapter, - CRB_CMD_PRODUCER_OFFSET)); - wmb(); - } } port->stats.xmitfinished++; @@ -927,29 +956,36 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) static void netxen_watchdog(unsigned long v) { struct netxen_adapter *adapter = (struct netxen_adapter *)v; - schedule_work(&adapter->watchdog_task); + if (adapter != g_adapter) { + printk("%s: ***BUG*** adapter[%p] != g_adapter[%p]\n", + __FUNCTION__, adapter, g_adapter); + return; + } + + SCHEDULE_WORK(&adapter->watchdog_task); } static void netxen_tx_timeout(struct net_device *netdev) { struct netxen_port *port = (struct netxen_port *)netdev_priv(netdev); - struct netxen_adapter *adapter = port->adapter; - schedule_work(&adapter->tx_timeout_task); + SCHEDULE_WORK(&port->adapter->tx_timeout_task); } -static void netxen_tx_timeout_task(struct net_device *netdev) +static void netxen_tx_timeout_task(struct work_struct *work) { - struct netxen_port *port = (struct netxen_port *)netdev_priv(netdev); + struct netxen_adapter *adapter = + container_of(work, struct netxen_adapter, tx_timeout_task); + struct net_device *netdev = adapter->netdev; unsigned long flags; printk(KERN_ERR "%s %s: transmit timeout, resetting.\n", netxen_nic_driver_name, netdev->name); - spin_lock_irqsave(&port->adapter->lock, flags); + spin_lock_irqsave(&adapter->lock, flags); netxen_nic_close(netdev); netxen_nic_open(netdev); - spin_unlock_irqrestore(&port->adapter->lock, flags); + spin_unlock_irqrestore(&adapter->lock, flags); netdev->trans_start = jiffies; netif_wake_queue(netdev); } @@ -966,6 +1002,11 @@ netxen_handle_int(struct netxen_adapter *adapter, struct net_device *netdev) if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) { int count = 0; u32 mask; + mask = readl(pci_base_offset(adapter, ISR_INT_VECTOR)); + if ((mask & 0x80) == 0) { + /* not our interrupt */ + return ret; + } netxen_nic_disable_int(adapter); /* Window = 0 or 1 */ do { @@ -1025,7 +1066,10 @@ irqreturn_t netxen_intr(int irq, void *data) netdev = port->netdev; /* process our status queue (for all 4 ports) */ - netxen_handle_int(adapter, netdev); + if (netif_running(netdev)) { + netxen_handle_int(adapter, netdev); + break; + } } return IRQ_HANDLED; @@ -1039,11 +1083,12 @@ static int netxen_nic_poll(struct net_device *netdev, int *budget) int done = 1; int ctx; int this_work_done; + int work_done = 0; DPRINTK(INFO, "polling for %d descriptors\n", *budget); port->stats.polled++; - adapter->work_done = 0; + work_done = 0; for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) { /* * Fairness issue. This will give undue weight to the @@ -1060,20 +1105,20 @@ static int netxen_nic_poll(struct net_device *netdev, int *budget) this_work_done = netxen_process_rcv_ring(adapter, ctx, work_to_do / MAX_RCV_CTX); - adapter->work_done += this_work_done; + work_done += this_work_done; } - netdev->quota -= adapter->work_done; - *budget -= adapter->work_done; + netdev->quota -= work_done; + *budget -= work_done; - if (adapter->work_done >= work_to_do - && netxen_nic_rx_has_work(adapter) != 0) + if (work_done >= work_to_do && netxen_nic_rx_has_work(adapter) != 0) done = 0; - netxen_process_cmd_ring((unsigned long)adapter); + if (netxen_process_cmd_ring((unsigned long)adapter) == 0) + done = 0; DPRINTK(INFO, "new work_done: %d work_to_do: %d\n", - adapter->work_done, work_to_do); + work_done, work_to_do); if (done) { netif_rx_complete(netdev); netxen_nic_enable_int(adapter); @@ -1116,8 +1161,9 @@ netxen_nic_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) if (ifr->ifr_data) { sprintf(dev_name, "%s-%d", NETXEN_NIC_NAME_RSP, port->portnum); - nr_bytes = copy_to_user((char *)ifr->ifr_data, dev_name, - NETXEN_NIC_NAME_LEN); + nr_bytes = + copy_to_user((char __user *)ifr->ifr_data, dev_name, + NETXEN_NIC_NAME_LEN); if (nr_bytes) err = -EIO; @@ -1144,6 +1190,9 @@ static struct pci_driver netxen_driver = { static int __init netxen_init_module(void) { + if ((netxen_workq = create_singlethread_workqueue("netxen")) == 0) + return -ENOMEM; + return pci_module_init(&netxen_driver); } @@ -1154,7 +1203,7 @@ static void __exit netxen_exit_module(void) /* * Wait for some time to allow the dma to drain, if any. */ - mdelay(5); + destroy_workqueue(netxen_workq); pci_unregister_driver(&netxen_driver); } diff --git a/trunk/drivers/net/netxen/netxen_nic_niu.c b/trunk/drivers/net/netxen/netxen_nic_niu.c index 7950a04532e6..4987dc765d99 100644 --- a/trunk/drivers/net/netxen/netxen_nic_niu.c +++ b/trunk/drivers/net/netxen/netxen_nic_niu.c @@ -1,7 +1,7 @@ /* * Copyright (C) 2003 - 2006 NetXen, Inc. * All rights reserved. - * + * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 @@ -16,10 +16,10 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. - * + * * The full GNU General Public License is included in this distribution * in the file called LICENSE. - * + * * Contact Information: * info@netxen.com * NetXen, @@ -40,13 +40,15 @@ static long phy_lock_timeout = 100000000; -static inline int phy_lock(void) +static inline int phy_lock(struct netxen_adapter *adapter) { int i; int done = 0, timeout = 0; while (!done) { - done = readl((void __iomem *)NETXEN_PCIE_REG(PCIE_SEM3_LOCK)); + done = + readl(pci_base_offset + (adapter, NETXEN_PCIE_REG(PCIE_SEM3_LOCK))); if (done == 1) break; if (timeout >= phy_lock_timeout) { @@ -61,13 +63,15 @@ static inline int phy_lock(void) } } - writel(NETXEN_PHY_LOCK_ID, (void __iomem *)PHY_LOCK_DRIVER); + writel(PHY_LOCK_DRIVER, + NETXEN_CRB_NORMALIZE(adapter, NETXEN_PHY_LOCK_ID)); return 0; } -static inline int phy_unlock(void) +static inline int phy_unlock(struct netxen_adapter *adapter) { - readl((void __iomem *)NETXEN_PCIE_REG(PCIE_SEM3_UNLOCK)); + readl(pci_base_offset(adapter, NETXEN_PCIE_REG(PCIE_SEM3_UNLOCK))); + return 0; } @@ -95,7 +99,7 @@ int netxen_niu_gbe_phy_read(struct netxen_adapter *adapter, long phy, __le32 status; __le32 mac_cfg0; - if (phy_lock() != 0) { + if (phy_lock(adapter) != 0) { return -1; } @@ -162,7 +166,7 @@ int netxen_niu_gbe_phy_read(struct netxen_adapter *adapter, long phy, NETXEN_NIU_GB_MAC_CONFIG_0(0), &mac_cfg0, 4)) return -EIO; - phy_unlock(); + phy_unlock(adapter); return result; } @@ -399,8 +403,8 @@ int netxen_niu_gbe_init_port(struct netxen_adapter *adapter, int port) { int result = 0; __le32 status; - if (adapter->ops->disable_phy_interrupts) - adapter->ops->disable_phy_interrupts(adapter, port); + if (adapter->disable_phy_interrupts) + adapter->disable_phy_interrupts(adapter, port); mdelay(2); if (0 == @@ -612,7 +616,7 @@ int netxen_niu_macaddr_set(struct netxen_port *port, __le32 temp = 0; struct netxen_adapter *adapter = port->adapter; int phy = port->portnum; - unsigned char mac_addr[MAX_ADDR_LEN]; + unsigned char mac_addr[6]; int i; for (i = 0; i < 10; i++) { @@ -631,7 +635,7 @@ int netxen_niu_macaddr_set(struct netxen_port *port, netxen_niu_macaddr_get(adapter, phy, (netxen_ethernet_macaddr_t *) mac_addr); - if (memcmp(mac_addr, addr, MAX_ADDR_LEN == 0)) + if (memcmp(mac_addr, addr, 6) == 0) break; } diff --git a/trunk/drivers/net/netxen/netxen_nic_phan_reg.h b/trunk/drivers/net/netxen/netxen_nic_phan_reg.h index 8181d436783f..7879f855af0b 100644 --- a/trunk/drivers/net/netxen/netxen_nic_phan_reg.h +++ b/trunk/drivers/net/netxen/netxen_nic_phan_reg.h @@ -33,15 +33,74 @@ /* * CRB Registers or queue message done only at initialization time. */ +#define NIC_CRB_BASE NETXEN_CAM_RAM(0x200) +#define NETXEN_NIC_REG(X) (NIC_CRB_BASE+(X)) -/* - * The following 2 are the base adresses for the CRB registers and their - * offsets will be added to get addresses for the index addresses. - */ -#define NIC_CRB_BASE_PORT1 NETXEN_CAM_RAM(0x200) -#define NIC_CRB_BASE_PORT2 NETXEN_CAM_RAM(0x250) +#define CRB_PHAN_CNTRL_LO_OFFSET NETXEN_NIC_REG(0x00) +#define CRB_PHAN_CNTRL_HI_OFFSET NETXEN_NIC_REG(0x04) +#define CRB_CMD_PRODUCER_OFFSET NETXEN_NIC_REG(0x08) +#define CRB_CMD_CONSUMER_OFFSET NETXEN_NIC_REG(0x0c) +#define CRB_PAUSE_ADDR_LO NETXEN_NIC_REG(0x10) /* C0 EPG BUG */ +#define CRB_PAUSE_ADDR_HI NETXEN_NIC_REG(0x14) +#define CRB_HOST_CMD_ADDR_HI NETXEN_NIC_REG(0x18) /* host add:cmd ring */ +#define CRB_HOST_CMD_ADDR_LO NETXEN_NIC_REG(0x1c) +#define CRB_CMD_INTR_LOOP NETXEN_NIC_REG(0x20) /* 4 regs for perf */ +#define CRB_CMD_DMA_LOOP NETXEN_NIC_REG(0x24) +#define CRB_RCV_INTR_LOOP NETXEN_NIC_REG(0x28) +#define CRB_RCV_DMA_LOOP NETXEN_NIC_REG(0x2c) +#define CRB_ENABLE_TX_INTR NETXEN_NIC_REG(0x30) /* phantom init status */ +#define CRB_MMAP_ADDR_3 NETXEN_NIC_REG(0x34) +#define CRB_CMDPEG_CMDRING NETXEN_NIC_REG(0x38) +#define CRB_HOST_DUMMY_BUF_ADDR_HI NETXEN_NIC_REG(0x3c) +#define CRB_HOST_DUMMY_BUF_ADDR_LO NETXEN_NIC_REG(0x40) +#define CRB_MMAP_ADDR_0 NETXEN_NIC_REG(0x44) +#define CRB_MMAP_ADDR_1 NETXEN_NIC_REG(0x48) +#define CRB_MMAP_ADDR_2 NETXEN_NIC_REG(0x4c) +#define CRB_CMDPEG_STATE NETXEN_NIC_REG(0x50) +#define CRB_MMAP_SIZE_0 NETXEN_NIC_REG(0x54) +#define CRB_MMAP_SIZE_1 NETXEN_NIC_REG(0x58) +#define CRB_MMAP_SIZE_2 NETXEN_NIC_REG(0x5c) +#define CRB_MMAP_SIZE_3 NETXEN_NIC_REG(0x60) +#define CRB_GLOBAL_INT_COAL NETXEN_NIC_REG(0x64) /* interrupt coalescing */ +#define CRB_INT_COAL_MODE NETXEN_NIC_REG(0x68) +#define CRB_MAX_RCV_BUFS NETXEN_NIC_REG(0x6c) +#define CRB_TX_INT_THRESHOLD NETXEN_NIC_REG(0x70) +#define CRB_RX_PKT_TIMER NETXEN_NIC_REG(0x74) +#define CRB_TX_PKT_TIMER NETXEN_NIC_REG(0x78) +#define CRB_RX_PKT_CNT NETXEN_NIC_REG(0x7c) +#define CRB_RX_TMR_CNT NETXEN_NIC_REG(0x80) +#define CRB_RX_LRO_TIMER NETXEN_NIC_REG(0x84) +#define CRB_RX_LRO_MID_TIMER NETXEN_NIC_REG(0x88) +#define CRB_DMA_MAX_RCV_BUFS NETXEN_NIC_REG(0x8c) +#define CRB_MAX_DMA_ENTRIES NETXEN_NIC_REG(0x90) +#define CRB_XG_STATE NETXEN_NIC_REG(0x94) /* XG Link status */ +#define CRB_AGENT_GO NETXEN_NIC_REG(0x98) /* NIC pkt gen agent */ +#define CRB_AGENT_TX_SIZE NETXEN_NIC_REG(0x9c) +#define CRB_AGENT_TX_TYPE NETXEN_NIC_REG(0xa0) +#define CRB_AGENT_TX_ADDR NETXEN_NIC_REG(0xa4) +#define CRB_AGENT_TX_MSS NETXEN_NIC_REG(0xa8) +#define CRB_TX_STATE NETXEN_NIC_REG(0xac) /* Debug -performance */ +#define CRB_TX_COUNT NETXEN_NIC_REG(0xb0) +#define CRB_RX_STATE NETXEN_NIC_REG(0xb4) +#define CRB_RX_PERF_DEBUG_1 NETXEN_NIC_REG(0xb8) +#define CRB_RX_LRO_CONTROL NETXEN_NIC_REG(0xbc) /* LRO On/OFF */ +#define CRB_RX_LRO_START_NUM NETXEN_NIC_REG(0xc0) +#define CRB_MPORT_MODE NETXEN_NIC_REG(0xc4) /* Multiport Mode */ +#define CRB_CMD_RING_SIZE NETXEN_NIC_REG(0xc8) +#define CRB_INT_VECTOR NETXEN_NIC_REG(0xd4) +#define CRB_CTX_RESET NETXEN_NIC_REG(0xd8) +#define CRB_HOST_STS_PROD NETXEN_NIC_REG(0xdc) +#define CRB_HOST_STS_CONS NETXEN_NIC_REG(0xe0) +#define CRB_PEG_CMD_PROD NETXEN_NIC_REG(0xe4) +#define CRB_PEG_CMD_CONS NETXEN_NIC_REG(0xe8) +#define CRB_HOST_BUFFER_PROD NETXEN_NIC_REG(0xec) +#define CRB_HOST_BUFFER_CONS NETXEN_NIC_REG(0xf0) +#define CRB_JUMBO_BUFFER_PROD NETXEN_NIC_REG(0xf4) +#define CRB_JUMBO_BUFFER_CONS NETXEN_NIC_REG(0xf8) -#define NETXEN_NIC_REG(X) (NIC_CRB_BASE_PORT1+(X)) +#define CRB_CMD_PRODUCER_OFFSET_1 NETXEN_NIC_REG(0x1ac) +#define CRB_CMD_CONSUMER_OFFSET_1 NETXEN_NIC_REG(0x1b0) +#define CRB_TEMP_STATE NETXEN_NIC_REG(0x1b4) /* * CrbPortPhanCntrHi/Lo is used to pass the address of HostPhantomIndex address @@ -51,74 +110,20 @@ * on the Phantom. */ -#define CRB_PHAN_CNTRL_LO_OFFSET NETXEN_NIC_REG(0x00) -#define CRB_PHAN_CNTRL_HI_OFFSET NETXEN_NIC_REG(0x04) - -/* point to the indexes */ -#define CRB_CMD_PRODUCER_OFFSET NETXEN_NIC_REG(0x08) -#define CRB_CMD_CONSUMER_OFFSET NETXEN_NIC_REG(0x0c) - -#define CRB_PAUSE_ADDR_LO NETXEN_NIC_REG(0x10) -#define CRB_PAUSE_ADDR_HI NETXEN_NIC_REG(0x14) - -/* address of command descriptors in the host memory */ -#define CRB_HOST_CMD_ADDR_HI NETXEN_NIC_REG(0x30) -#define CRB_HOST_CMD_ADDR_LO NETXEN_NIC_REG(0x34) - -/* The following 4 CRB registers are for doing performance coal */ -#define CRB_CMD_INTR_LOOP NETXEN_NIC_REG(0x38) -#define CRB_CMD_DMA_LOOP NETXEN_NIC_REG(0x3c) -#define CRB_RCV_INTR_LOOP NETXEN_NIC_REG(0x40) -#define CRB_RCV_DMA_LOOP NETXEN_NIC_REG(0x44) - -/* Needed by the host to find out the state of Phantom's initialization */ -#define CRB_ENABLE_TX_INTR NETXEN_NIC_REG(0x4c) -#define CRB_CMDPEG_STATE NETXEN_NIC_REG(0x50) -#define CRB_CMDPEG_CMDRING NETXEN_NIC_REG(0x54) - -/* Interrupt coalescing parameters */ -#define CRB_GLOBAL_INT_COAL NETXEN_NIC_REG(0x80) -#define CRB_INT_COAL_MODE NETXEN_NIC_REG(0x84) -#define CRB_MAX_RCV_BUFS NETXEN_NIC_REG(0x88) -#define CRB_TX_INT_THRESHOLD NETXEN_NIC_REG(0x8c) -#define CRB_RX_PKT_TIMER NETXEN_NIC_REG(0x90) -#define CRB_TX_PKT_TIMER NETXEN_NIC_REG(0x94) -#define CRB_RX_PKT_CNT NETXEN_NIC_REG(0x98) -#define CRB_RX_TMR_CNT NETXEN_NIC_REG(0x9c) -#define CRB_INT_THRESH NETXEN_NIC_REG(0xa4) - -/* Register for communicating XG link status */ -#define CRB_XG_STATE NETXEN_NIC_REG(0xa0) - -/* Register for communicating card temperature */ -/* Upper 16 bits are temperature value. Lower 16 bits are the state */ -#define CRB_TEMP_STATE NETXEN_NIC_REG(0xa8) -#define nx_get_temp_val(x) ((x) >> 16) -#define nx_get_temp_state(x) ((x) & 0xffff) -#define nx_encode_temp(val, state) (((val) << 16) | (state)) - -/* Debug registers for controlling NIC pkt gen agent */ -#define CRB_AGENT_GO NETXEN_NIC_REG(0xb0) -#define CRB_AGENT_TX_SIZE NETXEN_NIC_REG(0xb4) -#define CRB_AGENT_TX_TYPE NETXEN_NIC_REG(0xb8) -#define CRB_AGENT_TX_ADDR NETXEN_NIC_REG(0xbc) -#define CRB_AGENT_TX_MSS NETXEN_NIC_REG(0xc0) - -/* Debug registers for observing NIC performance */ -#define CRB_TX_STATE NETXEN_NIC_REG(0xd0) -#define CRB_TX_COUNT NETXEN_NIC_REG(0xd4) -#define CRB_RX_STATE NETXEN_NIC_REG(0xd8) +#define nx_get_temp_val(x) ((x) >> 16) +#define nx_get_temp_state(x) ((x) & 0xffff) +#define nx_encode_temp(val, state) (((val) << 16) | (state)) /* CRB registers per Rcv Descriptor ring */ struct netxen_rcv_desc_crb { u32 crb_rcv_producer_offset __attribute__ ((aligned(512))); u32 crb_rcv_consumer_offset; u32 crb_globalrcv_ring; + u32 crb_rcv_ring_size; }; /* - * CRB registers used by the receive peg logic. One instance of these - * needs to be instantiated per instance of the receive peg. + * CRB registers used by the receive peg logic. */ struct netxen_recv_crb { @@ -127,6 +132,7 @@ struct netxen_recv_crb { u32 crb_rcv_status_producer; u32 crb_rcv_status_consumer; u32 crb_rcvpeg_state; + u32 crb_status_ring_size; }; #if defined(DEFINE_GLOBAL_RECV_CRB) @@ -139,30 +145,48 @@ struct netxen_recv_crb recv_crb_registers[] = { { { /* crb_rcv_producer_offset: */ - NETXEN_NIC_REG(0x18), + NETXEN_NIC_REG(0x100), /* crb_rcv_consumer_offset: */ - NETXEN_NIC_REG(0x1c), + NETXEN_NIC_REG(0x104), /* crb_gloablrcv_ring: */ - NETXEN_NIC_REG(0x20), + NETXEN_NIC_REG(0x108), + /* crb_rcv_ring_size */ + NETXEN_NIC_REG(0x10c), + }, /* Jumbo frames */ { /* crb_rcv_producer_offset: */ - NETXEN_NIC_REG(0x100), + NETXEN_NIC_REG(0x110), /* crb_rcv_consumer_offset: */ - NETXEN_NIC_REG(0x104), + NETXEN_NIC_REG(0x114), /* crb_gloablrcv_ring: */ - NETXEN_NIC_REG(0x108), + NETXEN_NIC_REG(0x118), + /* crb_rcv_ring_size */ + NETXEN_NIC_REG(0x11c), + }, + /* LRO */ + { + /* crb_rcv_producer_offset: */ + NETXEN_NIC_REG(0x120), + /* crb_rcv_consumer_offset: */ + NETXEN_NIC_REG(0x124), + /* crb_gloablrcv_ring: */ + NETXEN_NIC_REG(0x128), + /* crb_rcv_ring_size */ + NETXEN_NIC_REG(0x12c), } }, /* crb_rcvstatus_ring: */ - NETXEN_NIC_REG(0x24), + NETXEN_NIC_REG(0x130), /* crb_rcv_status_producer: */ - NETXEN_NIC_REG(0x28), + NETXEN_NIC_REG(0x134), /* crb_rcv_status_consumer: */ - NETXEN_NIC_REG(0x2c), + NETXEN_NIC_REG(0x138), /* crb_rcvpeg_state: */ - NETXEN_NIC_REG(0x48), + NETXEN_NIC_REG(0x13c), + /* crb_status_ring_size */ + NETXEN_NIC_REG(0x140), }, /* @@ -173,34 +197,66 @@ struct netxen_recv_crb recv_crb_registers[] = { { { /* crb_rcv_producer_offset: */ - NETXEN_NIC_REG(0x80), + NETXEN_NIC_REG(0x144), /* crb_rcv_consumer_offset: */ - NETXEN_NIC_REG(0x84), + NETXEN_NIC_REG(0x148), /* crb_globalrcv_ring: */ - NETXEN_NIC_REG(0x88), + NETXEN_NIC_REG(0x14c), + /* crb_rcv_ring_size */ + NETXEN_NIC_REG(0x150), + }, /* Jumbo frames */ { /* crb_rcv_producer_offset: */ - NETXEN_NIC_REG(0x10C), + NETXEN_NIC_REG(0x154), /* crb_rcv_consumer_offset: */ - NETXEN_NIC_REG(0x110), + NETXEN_NIC_REG(0x158), /* crb_globalrcv_ring: */ - NETXEN_NIC_REG(0x114), + NETXEN_NIC_REG(0x15c), + /* crb_rcv_ring_size */ + NETXEN_NIC_REG(0x160), + }, + /* LRO */ + { + /* crb_rcv_producer_offset: */ + NETXEN_NIC_REG(0x164), + /* crb_rcv_consumer_offset: */ + NETXEN_NIC_REG(0x168), + /* crb_globalrcv_ring: */ + NETXEN_NIC_REG(0x16c), + /* crb_rcv_ring_size */ + NETXEN_NIC_REG(0x170), } + }, /* crb_rcvstatus_ring: */ - NETXEN_NIC_REG(0x8c), + NETXEN_NIC_REG(0x174), /* crb_rcv_status_producer: */ - NETXEN_NIC_REG(0x90), + NETXEN_NIC_REG(0x178), /* crb_rcv_status_consumer: */ - NETXEN_NIC_REG(0x94), + NETXEN_NIC_REG(0x17c), /* crb_rcvpeg_state: */ - NETXEN_NIC_REG(0x98), + NETXEN_NIC_REG(0x180), + /* crb_status_ring_size */ + NETXEN_NIC_REG(0x184), + }, }; + +u64 ctx_addr_sig_regs[][3] = { + {NETXEN_NIC_REG(0x188), NETXEN_NIC_REG(0x18c), NETXEN_NIC_REG(0x1c0)}, + {NETXEN_NIC_REG(0x190), NETXEN_NIC_REG(0x194), NETXEN_NIC_REG(0x1c4)}, + {NETXEN_NIC_REG(0x198), NETXEN_NIC_REG(0x19c), NETXEN_NIC_REG(0x1c8)}, + {NETXEN_NIC_REG(0x1a0), NETXEN_NIC_REG(0x1a4), NETXEN_NIC_REG(0x1cc)} +}; + #else extern struct netxen_recv_crb recv_crb_registers[]; +extern u64 ctx_addr_sig_regs[][3]; +#define CRB_CTX_ADDR_REG_LO (ctx_addr_sig_regs[0][0]) +#define CRB_CTX_ADDR_REG_HI (ctx_addr_sig_regs[0][2]) +#define CRB_CTX_SIGNATURE_REG (ctx_addr_sig_regs[0][1]) #endif /* DEFINE_GLOBAL_RECEIVE_CRB */ /* diff --git a/trunk/drivers/net/ni52.c b/trunk/drivers/net/ni52.c index 26e42f6e9fb1..196993a29b09 100644 --- a/trunk/drivers/net/ni52.c +++ b/trunk/drivers/net/ni52.c @@ -1335,7 +1335,7 @@ int __init init_module(void) return 0; } -void cleanup_module(void) +void __exit cleanup_module(void) { unregister_netdev(dev_ni52); release_region(dev_ni52->base_addr, NI52_TOTAL_SIZE); diff --git a/trunk/drivers/net/ni65.c b/trunk/drivers/net/ni65.c index 340ad0d5388a..1578f4d98498 100644 --- a/trunk/drivers/net/ni65.c +++ b/trunk/drivers/net/ni65.c @@ -1259,7 +1259,7 @@ int __init init_module(void) return IS_ERR(dev_ni65) ? PTR_ERR(dev_ni65) : 0; } -void cleanup_module(void) +void __exit cleanup_module(void) { unregister_netdev(dev_ni65); cleanup_card(dev_ni65); diff --git a/trunk/drivers/net/ns83820.c b/trunk/drivers/net/ns83820.c index b0127c71a5b6..568daeb3e9d8 100644 --- a/trunk/drivers/net/ns83820.c +++ b/trunk/drivers/net/ns83820.c @@ -414,10 +414,10 @@ struct rx_info { struct sk_buff *skbs[NR_RX_DESC]; - u32 *next_rx_desc; + __le32 *next_rx_desc; u16 next_rx, next_empty; - u32 *descs; + __le32 *descs; dma_addr_t phy_descs; }; @@ -427,6 +427,7 @@ struct ns83820 { u8 __iomem *base; struct pci_dev *pci_dev; + struct net_device *ndev; #ifdef NS83820_VLAN_ACCEL_SUPPORT struct vlan_group *vlgrp; @@ -459,7 +460,7 @@ struct ns83820 { struct sk_buff *tx_skbs[NR_TX_DESC]; char pad[16] __attribute__((aligned(16))); - u32 *tx_descs; + __le32 *tx_descs; dma_addr_t tx_phy_descs; struct timer_list tx_watchdog; @@ -533,7 +534,7 @@ static void ns83820_vlan_rx_kill_vid(struct net_device *ndev, unsigned short vid * conditions, still route realtime traffic with as low jitter as * possible. */ -static inline void build_rx_desc(struct ns83820 *dev, u32 *desc, dma_addr_t link, dma_addr_t buf, u32 cmdsts, u32 extsts) +static inline void build_rx_desc(struct ns83820 *dev, __le32 *desc, dma_addr_t link, dma_addr_t buf, u32 cmdsts, u32 extsts) { desc_addr_set(desc + DESC_LINK, link); desc_addr_set(desc + DESC_BUFPTR, buf); @@ -547,7 +548,7 @@ static inline int ns83820_add_rx_skb(struct ns83820 *dev, struct sk_buff *skb) { unsigned next_empty; u32 cmdsts; - u32 *sg; + __le32 *sg; dma_addr_t buf; next_empty = dev->rx_info.next_empty; @@ -631,10 +632,10 @@ static void fastcall rx_refill_atomic(struct net_device *ndev) } /* REFILL */ -static inline void queue_refill(void *_dev) +static inline void queue_refill(struct work_struct *work) { - struct net_device *ndev = _dev; - struct ns83820 *dev = PRIV(ndev); + struct ns83820 *dev = container_of(work, struct ns83820, tq_refill); + struct net_device *ndev = dev->ndev; rx_refill(ndev, GFP_KERNEL); if (dev->rx_info.up) @@ -874,7 +875,8 @@ static void fastcall rx_irq(struct net_device *ndev) struct rx_info *info = &dev->rx_info; unsigned next_rx; int rx_rc, len; - u32 cmdsts, *desc; + u32 cmdsts; + __le32 *desc; unsigned long flags; int nr = 0; @@ -1010,7 +1012,8 @@ static inline void kick_tx(struct ns83820 *dev) static void do_tx_done(struct net_device *ndev) { struct ns83820 *dev = PRIV(ndev); - u32 cmdsts, tx_done_idx, *desc; + u32 cmdsts, tx_done_idx; + __le32 *desc; dprintk("do_tx_done(%p)\n", ndev); tx_done_idx = dev->tx_done_idx; @@ -1077,7 +1080,7 @@ static void ns83820_cleanup_tx(struct ns83820 *dev) struct sk_buff *skb = dev->tx_skbs[i]; dev->tx_skbs[i] = NULL; if (skb) { - u32 *desc = dev->tx_descs + (i * DESC_SIZE); + __le32 *desc = dev->tx_descs + (i * DESC_SIZE); pci_unmap_single(dev->pci_dev, desc_addr_get(desc + DESC_BUFPTR), le32_to_cpu(desc[DESC_CMDSTS]) & CMDSTS_LEN_MASK, @@ -1107,7 +1110,7 @@ static int ns83820_hard_start_xmit(struct sk_buff *skb, struct net_device *ndev) skb_frag_t *frag; int stopped = 0; int do_intr = 0; - volatile u32 *first_desc; + volatile __le32 *first_desc; dprintk("ns83820_hard_start_xmit\n"); @@ -1180,7 +1183,7 @@ static int ns83820_hard_start_xmit(struct sk_buff *skb, struct net_device *ndev) first_desc = dev->tx_descs + (free_idx * DESC_SIZE); for (;;) { - volatile u32 *desc = dev->tx_descs + (free_idx * DESC_SIZE); + volatile __le32 *desc = dev->tx_descs + (free_idx * DESC_SIZE); dprintk("frag[%3u]: %4u @ 0x%08Lx\n", free_idx, len, (unsigned long long)buf); @@ -1455,7 +1458,8 @@ static int ns83820_stop(struct net_device *ndev) static void ns83820_tx_timeout(struct net_device *ndev) { struct ns83820 *dev = PRIV(ndev); - u32 tx_done_idx, *desc; + u32 tx_done_idx; + __le32 *desc; unsigned long flags; spin_lock_irqsave(&dev->tx_lock, flags); @@ -1841,6 +1845,7 @@ static int __devinit ns83820_init_one(struct pci_dev *pci_dev, const struct pci_ ndev = alloc_etherdev(sizeof(struct ns83820)); dev = PRIV(ndev); + dev->ndev = ndev; err = -ENOMEM; if (!dev) goto out; @@ -1853,7 +1858,7 @@ static int __devinit ns83820_init_one(struct pci_dev *pci_dev, const struct pci_ SET_MODULE_OWNER(ndev); SET_NETDEV_DEV(ndev, &pci_dev->dev); - INIT_WORK(&dev->tq_refill, queue_refill, ndev); + INIT_WORK(&dev->tq_refill, queue_refill); tasklet_init(&dev->rx_tasklet, rx_action, (unsigned long)ndev); err = pci_enable_device(pci_dev); diff --git a/trunk/drivers/net/pcmcia/3c574_cs.c b/trunk/drivers/net/pcmcia/3c574_cs.c index 046009928526..794cc61819dd 100644 --- a/trunk/drivers/net/pcmcia/3c574_cs.c +++ b/trunk/drivers/net/pcmcia/3c574_cs.c @@ -338,7 +338,6 @@ static int tc574_config(struct pcmcia_device *link) struct net_device *dev = link->priv; struct el3_private *lp = netdev_priv(dev); tuple_t tuple; - cisparse_t parse; unsigned short buf[32]; int last_fn, last_ret, i, j; kio_addr_t ioaddr; @@ -350,17 +349,6 @@ static int tc574_config(struct pcmcia_device *link) DEBUG(0, "3c574_config(0x%p)\n", link); - tuple.Attributes = 0; - tuple.DesiredTuple = CISTPL_CONFIG; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); - tuple.TupleData = (cisdata_t *)buf; - tuple.TupleDataMax = 64; - tuple.TupleOffset = 0; - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); - link->conf.ConfigBase = parse.config.base; - link->conf.Present = parse.config.rmask[0]; - link->io.IOAddrLines = 16; for (i = j = 0; j < 0x400; j += 0x20) { link->io.BasePort1 = j ^ 0x300; @@ -382,6 +370,10 @@ static int tc574_config(struct pcmcia_device *link) /* The 3c574 normally uses an EEPROM for configuration info, including the hardware address. The future products may include a modem chip and put the address in the CIS. */ + tuple.Attributes = 0; + tuple.TupleData = (cisdata_t *)buf; + tuple.TupleDataMax = 64; + tuple.TupleOffset = 0; tuple.DesiredTuple = 0x88; if (pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) { pcmcia_get_tuple_data(link, &tuple); @@ -397,12 +389,9 @@ static int tc574_config(struct pcmcia_device *link) goto failed; } } - tuple.DesiredTuple = CISTPL_VERS_1; - if (pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS && - pcmcia_get_tuple_data(link, &tuple) == CS_SUCCESS && - pcmcia_parse_tuple(link, &tuple, &parse) == CS_SUCCESS) { - cardname = parse.version_1.str + parse.version_1.ofs[1]; - } else + if (link->prod_id[1]) + cardname = link->prod_id[1]; + else cardname = "3Com 3c574"; { diff --git a/trunk/drivers/net/pcmcia/3c589_cs.c b/trunk/drivers/net/pcmcia/3c589_cs.c index 231fa2c9ec6c..1e73ff7d5d8e 100644 --- a/trunk/drivers/net/pcmcia/3c589_cs.c +++ b/trunk/drivers/net/pcmcia/3c589_cs.c @@ -253,7 +253,6 @@ static int tc589_config(struct pcmcia_device *link) struct net_device *dev = link->priv; struct el3_private *lp = netdev_priv(dev); tuple_t tuple; - cisparse_t parse; u16 buf[32], *phys_addr; int last_fn, last_ret, i, j, multi = 0, fifo; kio_addr_t ioaddr; @@ -263,26 +262,16 @@ static int tc589_config(struct pcmcia_device *link) phys_addr = (u16 *)dev->dev_addr; tuple.Attributes = 0; - tuple.DesiredTuple = CISTPL_CONFIG; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); tuple.TupleData = (cisdata_t *)buf; tuple.TupleDataMax = sizeof(buf); tuple.TupleOffset = 0; - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); - link->conf.ConfigBase = parse.config.base; - link->conf.Present = parse.config.rmask[0]; - - /* Is this a 3c562? */ - tuple.DesiredTuple = CISTPL_MANFID; tuple.Attributes = TUPLE_RETURN_COMMON; - if ((pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) && - (pcmcia_get_tuple_data(link, &tuple) == CS_SUCCESS)) { - if (le16_to_cpu(buf[0]) != MANFID_3COM) + + /* Is this a 3c562? */ + if (link->manf_id != MANFID_3COM) printk(KERN_INFO "3c589_cs: hmmm, is this really a " "3Com card??\n"); - multi = (le16_to_cpu(buf[1]) == PRODID_3COM_3C562); - } + multi = (link->card_id == PRODID_3COM_3C562); /* For the 3c562, the base address must be xx00-xx7f */ link->io.IOAddrLines = 16; diff --git a/trunk/drivers/net/pcmcia/axnet_cs.c b/trunk/drivers/net/pcmcia/axnet_cs.c index 5ddd5742f779..6139048f8117 100644 --- a/trunk/drivers/net/pcmcia/axnet_cs.c +++ b/trunk/drivers/net/pcmcia/axnet_cs.c @@ -299,11 +299,7 @@ static int axnet_config(struct pcmcia_device *link) tuple.TupleData = (cisdata_t *)buf; tuple.TupleDataMax = sizeof(buf); tuple.TupleOffset = 0; - tuple.DesiredTuple = CISTPL_CONFIG; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); - link->conf.ConfigBase = parse.config.base; + /* don't trust the CIS on this; Linksys got it wrong */ link->conf.Present = 0x63; diff --git a/trunk/drivers/net/pcmcia/com20020_cs.c b/trunk/drivers/net/pcmcia/com20020_cs.c index 48434d7924eb..91f65e91cd5f 100644 --- a/trunk/drivers/net/pcmcia/com20020_cs.c +++ b/trunk/drivers/net/pcmcia/com20020_cs.c @@ -249,12 +249,9 @@ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) static int com20020_config(struct pcmcia_device *link) { struct arcnet_local *lp; - tuple_t tuple; - cisparse_t parse; com20020_dev_t *info; struct net_device *dev; int i, last_ret, last_fn; - u_char buf[64]; int ioaddr; info = link->priv; @@ -264,16 +261,6 @@ static int com20020_config(struct pcmcia_device *link) DEBUG(0, "com20020_config(0x%p)\n", link); - tuple.Attributes = 0; - tuple.TupleData = buf; - tuple.TupleDataMax = 64; - tuple.TupleOffset = 0; - tuple.DesiredTuple = CISTPL_CONFIG; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); - link->conf.ConfigBase = parse.config.base; - DEBUG(1,"arcnet: baseport1 is %Xh\n", link->io.BasePort1); i = !CS_SUCCESS; if (!link->io.BasePort1) diff --git a/trunk/drivers/net/pcmcia/fmvj18x_cs.c b/trunk/drivers/net/pcmcia/fmvj18x_cs.c index 65f6fdf43725..0d7de617e535 100644 --- a/trunk/drivers/net/pcmcia/fmvj18x_cs.c +++ b/trunk/drivers/net/pcmcia/fmvj18x_cs.c @@ -342,7 +342,7 @@ static int fmvj18x_config(struct pcmcia_device *link) tuple_t tuple; cisparse_t parse; u_short buf[32]; - int i, last_fn, last_ret, ret; + int i, last_fn = 0, last_ret = 0, ret; kio_addr_t ioaddr; cardtype_t cardtype; char *card_name = "unknown"; @@ -350,21 +350,9 @@ static int fmvj18x_config(struct pcmcia_device *link) DEBUG(0, "fmvj18x_config(0x%p)\n", link); - /* - This reads the card's CONFIG tuple to find its configuration - registers. - */ - tuple.DesiredTuple = CISTPL_CONFIG; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); tuple.TupleData = (u_char *)buf; tuple.TupleDataMax = 64; tuple.TupleOffset = 0; - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); - - link->conf.ConfigBase = parse.config.base; - link->conf.Present = parse.config.rmask[0]; - tuple.DesiredTuple = CISTPL_FUNCE; tuple.TupleOffset = 0; if (pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) { @@ -374,17 +362,12 @@ static int fmvj18x_config(struct pcmcia_device *link) CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); link->conf.ConfigIndex = parse.cftable_entry.index; - tuple.DesiredTuple = CISTPL_MANFID; - if (pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); - else - buf[0] = 0xffff; - switch (le16_to_cpu(buf[0])) { + switch (link->manf_id) { case MANFID_TDK: cardtype = TDK; - if (le16_to_cpu(buf[1]) == PRODID_TDK_GN3410 - || le16_to_cpu(buf[1]) == PRODID_TDK_NP9610 - || le16_to_cpu(buf[1]) == PRODID_TDK_MN3200) { + if (link->card_id == PRODID_TDK_GN3410 + || link->card_id == PRODID_TDK_NP9610 + || link->card_id == PRODID_TDK_MN3200) { /* MultiFunction Card */ link->conf.ConfigBase = 0x800; link->conf.ConfigIndex = 0x47; @@ -395,11 +378,11 @@ static int fmvj18x_config(struct pcmcia_device *link) cardtype = CONTEC; break; case MANFID_FUJITSU: - if (le16_to_cpu(buf[1]) == PRODID_FUJITSU_MBH10302) + if (link->card_id == PRODID_FUJITSU_MBH10302) /* RATOC REX-5588/9822/4886's PRODID are 0004(=MBH10302), but these are MBH10304 based card. */ cardtype = MBH10304; - else if (le16_to_cpu(buf[1]) == PRODID_FUJITSU_MBH10304) + else if (link->card_id == PRODID_FUJITSU_MBH10304) cardtype = MBH10304; else cardtype = LA501; @@ -409,14 +392,9 @@ static int fmvj18x_config(struct pcmcia_device *link) } } else { /* old type card */ - tuple.DesiredTuple = CISTPL_MANFID; - if (pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); - else - buf[0] = 0xffff; - switch (le16_to_cpu(buf[0])) { + switch (link->manf_id) { case MANFID_FUJITSU: - if (le16_to_cpu(buf[1]) == PRODID_FUJITSU_MBH10304) { + if (link->card_id == PRODID_FUJITSU_MBH10304) { cardtype = XXX10304; /* MBH10304 with buggy CIS */ link->conf.ConfigIndex = 0x20; } else { diff --git a/trunk/drivers/net/pcmcia/ibmtr_cs.c b/trunk/drivers/net/pcmcia/ibmtr_cs.c index bc0ca41a0542..a956a51d284f 100644 --- a/trunk/drivers/net/pcmcia/ibmtr_cs.c +++ b/trunk/drivers/net/pcmcia/ibmtr_cs.c @@ -222,24 +222,12 @@ static int ibmtr_config(struct pcmcia_device *link) ibmtr_dev_t *info = link->priv; struct net_device *dev = info->dev; struct tok_info *ti = netdev_priv(dev); - tuple_t tuple; - cisparse_t parse; win_req_t req; memreq_t mem; int i, last_ret, last_fn; - u_char buf[64]; DEBUG(0, "ibmtr_config(0x%p)\n", link); - tuple.Attributes = 0; - tuple.TupleData = buf; - tuple.TupleDataMax = 64; - tuple.TupleOffset = 0; - tuple.DesiredTuple = CISTPL_CONFIG; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); - link->conf.ConfigBase = parse.config.base; link->conf.ConfigIndex = 0x61; /* Determine if this is PRIMARY or ALTERNATE. */ diff --git a/trunk/drivers/net/pcmcia/nmclan_cs.c b/trunk/drivers/net/pcmcia/nmclan_cs.c index e77110e4c288..3b707747a811 100644 --- a/trunk/drivers/net/pcmcia/nmclan_cs.c +++ b/trunk/drivers/net/pcmcia/nmclan_cs.c @@ -656,23 +656,12 @@ static int nmclan_config(struct pcmcia_device *link) struct net_device *dev = link->priv; mace_private *lp = netdev_priv(dev); tuple_t tuple; - cisparse_t parse; u_char buf[64]; int i, last_ret, last_fn; kio_addr_t ioaddr; DEBUG(0, "nmclan_config(0x%p)\n", link); - tuple.Attributes = 0; - tuple.TupleData = buf; - tuple.TupleDataMax = 64; - tuple.TupleOffset = 0; - tuple.DesiredTuple = CISTPL_CONFIG; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); - link->conf.ConfigBase = parse.config.base; - CS_CHECK(RequestIO, pcmcia_request_io(link, &link->io)); CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); @@ -686,6 +675,7 @@ static int nmclan_config(struct pcmcia_device *link) tuple.TupleData = buf; tuple.TupleDataMax = 64; tuple.TupleOffset = 0; + tuple.Attributes = 0; CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); memcpy(dev->dev_addr, tuple.TupleData, ETHER_ADDR_LEN); diff --git a/trunk/drivers/net/pcmcia/pcnet_cs.c b/trunk/drivers/net/pcmcia/pcnet_cs.c index c51cc5d8789a..2b1238e2dbdb 100644 --- a/trunk/drivers/net/pcmcia/pcnet_cs.c +++ b/trunk/drivers/net/pcmcia/pcnet_cs.c @@ -519,31 +519,15 @@ static int pcnet_config(struct pcmcia_device *link) tuple_t tuple; cisparse_t parse; int i, last_ret, last_fn, start_pg, stop_pg, cm_offset; - int manfid = 0, prodid = 0, has_shmem = 0; + int has_shmem = 0; u_short buf[64]; hw_info_t *hw_info; DEBUG(0, "pcnet_config(0x%p)\n", link); - tuple.Attributes = 0; tuple.TupleData = (cisdata_t *)buf; tuple.TupleDataMax = sizeof(buf); tuple.TupleOffset = 0; - tuple.DesiredTuple = CISTPL_CONFIG; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); - link->conf.ConfigBase = parse.config.base; - link->conf.Present = parse.config.rmask[0]; - - tuple.DesiredTuple = CISTPL_MANFID; - tuple.Attributes = TUPLE_RETURN_COMMON; - if ((pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) && - (pcmcia_get_tuple_data(link, &tuple) == CS_SUCCESS)) { - manfid = le16_to_cpu(buf[0]); - prodid = le16_to_cpu(buf[1]); - } - tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; tuple.Attributes = 0; CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); @@ -589,8 +573,8 @@ static int pcnet_config(struct pcmcia_device *link) link->conf.Attributes |= CONF_ENABLE_SPKR; link->conf.Status = CCSR_AUDIO_ENA; } - if ((manfid == MANFID_IBM) && - (prodid == PRODID_IBM_HOME_AND_AWAY)) + if ((link->manf_id == MANFID_IBM) && + (link->card_id == PRODID_IBM_HOME_AND_AWAY)) link->conf.ConfigIndex |= 0x10; CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); @@ -624,10 +608,10 @@ static int pcnet_config(struct pcmcia_device *link) info->flags = hw_info->flags; /* Check for user overrides */ info->flags |= (delay_output) ? DELAY_OUTPUT : 0; - if ((manfid == MANFID_SOCKET) && - ((prodid == PRODID_SOCKET_LPE) || - (prodid == PRODID_SOCKET_LPE_CF) || - (prodid == PRODID_SOCKET_EIO))) + if ((link->manf_id == MANFID_SOCKET) && + ((link->card_id == PRODID_SOCKET_LPE) || + (link->card_id == PRODID_SOCKET_LPE_CF) || + (link->card_id == PRODID_SOCKET_EIO))) info->flags &= ~USE_BIG_BUF; if (!use_big_buf) info->flags &= ~USE_BIG_BUF; diff --git a/trunk/drivers/net/pcmcia/smc91c92_cs.c b/trunk/drivers/net/pcmcia/smc91c92_cs.c index 20fcc3576202..530df8883fe5 100644 --- a/trunk/drivers/net/pcmcia/smc91c92_cs.c +++ b/trunk/drivers/net/pcmcia/smc91c92_cs.c @@ -560,16 +560,8 @@ static int mhz_setup(struct pcmcia_device *link) /* Read the station address from the CIS. It is stored as the last (fourth) string in the Version 1 Version/ID tuple. */ - tuple->DesiredTuple = CISTPL_VERS_1; - if (first_tuple(link, tuple, parse) != CS_SUCCESS) { - rc = -1; - goto free_cfg_mem; - } - /* Ugh -- the EM1144 card has two VERS_1 tuples!?! */ - if (next_tuple(link, tuple, parse) != CS_SUCCESS) - first_tuple(link, tuple, parse); - if (parse->version_1.ns > 3) { - station_addr = parse->version_1.str + parse->version_1.ofs[3]; + if (link->prod_id[3]) { + station_addr = link->prod_id[3]; if (cvt_ascii_address(dev, station_addr) == 0) { rc = 0; goto free_cfg_mem; @@ -744,15 +736,12 @@ static int smc_setup(struct pcmcia_device *link) } } /* Try the third string in the Version 1 Version/ID tuple. */ - tuple->DesiredTuple = CISTPL_VERS_1; - if (first_tuple(link, tuple, parse) != CS_SUCCESS) { - rc = -1; - goto free_cfg_mem; - } - station_addr = parse->version_1.str + parse->version_1.ofs[2]; - if (cvt_ascii_address(dev, station_addr) == 0) { - rc = 0; - goto free_cfg_mem; + if (link->prod_id[2]) { + station_addr = link->prod_id[2]; + if (cvt_ascii_address(dev, station_addr) == 0) { + rc = 0; + goto free_cfg_mem; + } } rc = -1; @@ -970,10 +959,6 @@ static int smc91c92_config(struct pcmcia_device *link) { struct net_device *dev = link->priv; struct smc_private *smc = netdev_priv(dev); - struct smc_cfg_mem *cfg_mem; - tuple_t *tuple; - cisparse_t *parse; - u_char *buf; char *name; int i, j, rev; kio_addr_t ioaddr; @@ -981,30 +966,8 @@ static int smc91c92_config(struct pcmcia_device *link) DEBUG(0, "smc91c92_config(0x%p)\n", link); - cfg_mem = kmalloc(sizeof(struct smc_cfg_mem), GFP_KERNEL); - if (!cfg_mem) - goto config_failed; - - tuple = &cfg_mem->tuple; - parse = &cfg_mem->parse; - buf = cfg_mem->buf; - - tuple->Attributes = tuple->TupleOffset = 0; - tuple->TupleData = (cisdata_t *)buf; - tuple->TupleDataMax = 64; - - tuple->DesiredTuple = CISTPL_CONFIG; - i = first_tuple(link, tuple, parse); - CS_EXIT_TEST(i, ParseTuple, config_failed); - link->conf.ConfigBase = parse->config.base; - link->conf.Present = parse->config.rmask[0]; - - tuple->DesiredTuple = CISTPL_MANFID; - tuple->Attributes = TUPLE_RETURN_COMMON; - if (first_tuple(link, tuple, parse) == CS_SUCCESS) { - smc->manfid = parse->manfid.manf; - smc->cardid = parse->manfid.card; - } + smc->manfid = link->manf_id; + smc->cardid = link->card_id; if ((smc->manfid == MANFID_OSITECH) && (smc->cardid != PRODID_OSITECH_SEVEN)) { @@ -1134,14 +1097,12 @@ static int smc91c92_config(struct pcmcia_device *link) printk(KERN_NOTICE " No MII transceivers found!\n"); } } - kfree(cfg_mem); return 0; config_undo: unregister_netdev(dev); config_failed: /* CS_EXIT_TEST() calls jump to here... */ smc91c92_release(link); - kfree(cfg_mem); return -ENODEV; } /* smc91c92_config */ diff --git a/trunk/drivers/net/pcmcia/xirc2ps_cs.c b/trunk/drivers/net/pcmcia/xirc2ps_cs.c index f3914f58d67f..8478dca3d8d1 100644 --- a/trunk/drivers/net/pcmcia/xirc2ps_cs.c +++ b/trunk/drivers/net/pcmcia/xirc2ps_cs.c @@ -332,6 +332,7 @@ static irqreturn_t xirc2ps_interrupt(int irq, void *dev_id); */ typedef struct local_info_t { + struct net_device *dev; struct pcmcia_device *p_dev; dev_node_t node; struct net_device_stats stats; @@ -353,7 +354,7 @@ typedef struct local_info_t { */ static int do_start_xmit(struct sk_buff *skb, struct net_device *dev); static void do_tx_timeout(struct net_device *dev); -static void xirc2ps_tx_timeout_task(void *data); +static void xirc2ps_tx_timeout_task(struct work_struct *work); static struct net_device_stats *do_get_stats(struct net_device *dev); static void set_addresses(struct net_device *dev); static void set_multicast_list(struct net_device *dev); @@ -567,6 +568,7 @@ xirc2ps_probe(struct pcmcia_device *link) if (!dev) return -ENOMEM; local = netdev_priv(dev); + local->dev = dev; local->p_dev = link; link->priv = dev; @@ -591,7 +593,7 @@ xirc2ps_probe(struct pcmcia_device *link) #ifdef HAVE_TX_TIMEOUT dev->tx_timeout = do_tx_timeout; dev->watchdog_timeo = TX_TIMEOUT; - INIT_WORK(&local->tx_timeout_task, xirc2ps_tx_timeout_task, dev); + INIT_WORK(&local->tx_timeout_task, xirc2ps_tx_timeout_task); #endif return xirc2ps_config(link); @@ -707,22 +709,11 @@ set_card_type(struct pcmcia_device *link, const void *s) * Returns: true if this is a CE2 */ static int -has_ce2_string(struct pcmcia_device * link) +has_ce2_string(struct pcmcia_device * p_dev) { - tuple_t tuple; - cisparse_t parse; - u_char buf[256]; - - tuple.Attributes = 0; - tuple.TupleData = buf; - tuple.TupleDataMax = 254; - tuple.TupleOffset = 0; - tuple.DesiredTuple = CISTPL_VERS_1; - if (!first_tuple(link, &tuple, &parse) && parse.version_1.ns > 2) { - if (strstr(parse.version_1.str + parse.version_1.ofs[2], "CE2")) - return 1; - } - return 0; + if (p_dev->prod_id[2] && strstr(p_dev->prod_id[2], "CE2")) + return 1; + return 0; } /**************** @@ -792,13 +783,6 @@ xirc2ps_config(struct pcmcia_device * link) goto failure; } - /* get configuration stuff */ - tuple.DesiredTuple = CISTPL_CONFIG; - if ((err=first_tuple(link, &tuple, &parse))) - goto cis_error; - link->conf.ConfigBase = parse.config.base; - link->conf.Present = parse.config.rmask[0]; - /* get the ethernet address from the CIS */ tuple.DesiredTuple = CISTPL_FUNCE; for (err = first_tuple(link, &tuple, &parse); !err; @@ -1062,8 +1046,6 @@ xirc2ps_config(struct pcmcia_device * link) xirc2ps_release(link); return -ENODEV; - cis_error: - printk(KNOT_XIRC "unable to parse CIS\n"); failure: return -ENODEV; } /* xirc2ps_config */ @@ -1344,9 +1326,11 @@ xirc2ps_interrupt(int irq, void *dev_id) /*====================================================================*/ static void -xirc2ps_tx_timeout_task(void *data) +xirc2ps_tx_timeout_task(struct work_struct *work) { - struct net_device *dev = data; + local_info_t *local = + container_of(work, local_info_t, tx_timeout_task); + struct net_device *dev = local->dev; /* reset the card */ do_reset(dev,1); dev->trans_start = jiffies; diff --git a/trunk/drivers/net/phy/phy.c b/trunk/drivers/net/phy/phy.c index 88237bdb5255..e175f3910b18 100644 --- a/trunk/drivers/net/phy/phy.c +++ b/trunk/drivers/net/phy/phy.c @@ -397,7 +397,7 @@ int phy_start_aneg(struct phy_device *phydev) EXPORT_SYMBOL(phy_start_aneg); -static void phy_change(void *data); +static void phy_change(struct work_struct *work); static void phy_timer(unsigned long data); /* phy_start_machine: @@ -555,7 +555,7 @@ int phy_start_interrupts(struct phy_device *phydev) { int err = 0; - INIT_WORK(&phydev->phy_queue, phy_change, phydev); + INIT_WORK(&phydev->phy_queue, phy_change); if (request_irq(phydev->irq, phy_interrupt, IRQF_SHARED, @@ -587,8 +587,7 @@ int phy_stop_interrupts(struct phy_device *phydev) * Finish any pending work; we might have been scheduled * to be called from keventd ourselves, though. */ - if (!current_is_keventd()) - flush_scheduled_work(); + run_scheduled_work(&phydev->phy_queue); free_irq(phydev->irq, phydev); @@ -598,10 +597,11 @@ EXPORT_SYMBOL(phy_stop_interrupts); /* Scheduled by the phy_interrupt/timer to handle PHY changes */ -static void phy_change(void *data) +static void phy_change(struct work_struct *work) { int err; - struct phy_device *phydev = data; + struct phy_device *phydev = + container_of(work, struct phy_device, phy_queue); err = phy_disable_interrupts(phydev); diff --git a/trunk/drivers/net/plip.c b/trunk/drivers/net/plip.c index 71afb274498f..6bb085f54437 100644 --- a/trunk/drivers/net/plip.c +++ b/trunk/drivers/net/plip.c @@ -138,9 +138,9 @@ static const unsigned int net_debug = NET_DEBUG; #define PLIP_NIBBLE_WAIT 3000 /* Bottom halves */ -static void plip_kick_bh(struct net_device *dev); -static void plip_bh(struct net_device *dev); -static void plip_timer_bh(struct net_device *dev); +static void plip_kick_bh(struct work_struct *work); +static void plip_bh(struct work_struct *work); +static void plip_timer_bh(struct work_struct *work); /* Interrupt handler */ static void plip_interrupt(int irq, void *dev_id); @@ -207,9 +207,10 @@ struct plip_local { struct net_local { struct net_device_stats enet_stats; + struct net_device *dev; struct work_struct immediate; - struct work_struct deferred; - struct work_struct timer; + struct delayed_work deferred; + struct delayed_work timer; struct plip_local snd_data; struct plip_local rcv_data; struct pardevice *pardev; @@ -306,11 +307,11 @@ plip_init_netdev(struct net_device *dev) nl->nibble = PLIP_NIBBLE_WAIT; /* Initialize task queue structures */ - INIT_WORK(&nl->immediate, (void (*)(void *))plip_bh, dev); - INIT_WORK(&nl->deferred, (void (*)(void *))plip_kick_bh, dev); + INIT_WORK(&nl->immediate, plip_bh); + INIT_DELAYED_WORK(&nl->deferred, plip_kick_bh); if (dev->irq == -1) - INIT_WORK(&nl->timer, (void (*)(void *))plip_timer_bh, dev); + INIT_DELAYED_WORK(&nl->timer, plip_timer_bh); spin_lock_init(&nl->lock); } @@ -319,9 +320,10 @@ plip_init_netdev(struct net_device *dev) This routine is kicked by do_timer(). Request `plip_bh' to be invoked. */ static void -plip_kick_bh(struct net_device *dev) +plip_kick_bh(struct work_struct *work) { - struct net_local *nl = netdev_priv(dev); + struct net_local *nl = + container_of(work, struct net_local, deferred.work); if (nl->is_deferred) schedule_work(&nl->immediate); @@ -362,9 +364,9 @@ static const plip_func connection_state_table[] = /* Bottom half handler of PLIP. */ static void -plip_bh(struct net_device *dev) +plip_bh(struct work_struct *work) { - struct net_local *nl = netdev_priv(dev); + struct net_local *nl = container_of(work, struct net_local, immediate); struct plip_local *snd = &nl->snd_data; struct plip_local *rcv = &nl->rcv_data; plip_func f; @@ -372,20 +374,21 @@ plip_bh(struct net_device *dev) nl->is_deferred = 0; f = connection_state_table[nl->connection]; - if ((r = (*f)(dev, nl, snd, rcv)) != OK - && (r = plip_bh_timeout_error(dev, nl, snd, rcv, r)) != OK) { + if ((r = (*f)(nl->dev, nl, snd, rcv)) != OK + && (r = plip_bh_timeout_error(nl->dev, nl, snd, rcv, r)) != OK) { nl->is_deferred = 1; schedule_delayed_work(&nl->deferred, 1); } } static void -plip_timer_bh(struct net_device *dev) +plip_timer_bh(struct work_struct *work) { - struct net_local *nl = netdev_priv(dev); + struct net_local *nl = + container_of(work, struct net_local, timer.work); if (!(atomic_read (&nl->kill_timer))) { - plip_interrupt (-1, dev); + plip_interrupt (-1, nl->dev); schedule_delayed_work(&nl->timer, 1); } @@ -1284,6 +1287,7 @@ static void plip_attach (struct parport *port) } nl = netdev_priv(dev); + nl->dev = dev; nl->pardev = parport_register_device(port, name, plip_preempt, plip_wakeup, plip_interrupt, 0, dev); diff --git a/trunk/drivers/net/qla3xxx.c b/trunk/drivers/net/qla3xxx.c index ec640f6229ae..d79d141a601d 100644 --- a/trunk/drivers/net/qla3xxx.c +++ b/trunk/drivers/net/qla3xxx.c @@ -2008,7 +2008,7 @@ static irqreturn_t ql3xxx_isr(int irq, void *dev_id) "%s: Another function issued a reset to the " "chip. ISR value = %x.\n", ndev->name, value); } - queue_work(qdev->workqueue, &qdev->reset_work); + queue_delayed_work(qdev->workqueue, &qdev->reset_work, 0); spin_unlock(&qdev->adapter_lock); } else if (value & ISP_IMR_DISABLE_CMPL_INT) { ql_disable_interrupts(qdev); @@ -3182,11 +3182,13 @@ static void ql3xxx_tx_timeout(struct net_device *ndev) /* * Wake up the worker to process this event. */ - queue_work(qdev->workqueue, &qdev->tx_timeout_work); + queue_delayed_work(qdev->workqueue, &qdev->tx_timeout_work, 0); } -static void ql_reset_work(struct ql3_adapter *qdev) +static void ql_reset_work(struct work_struct *work) { + struct ql3_adapter *qdev = + container_of(work, struct ql3_adapter, reset_work.work); struct net_device *ndev = qdev->ndev; u32 value; struct ql_tx_buf_cb *tx_cb; @@ -3278,9 +3280,12 @@ static void ql_reset_work(struct ql3_adapter *qdev) } } -static void ql_tx_timeout_work(struct ql3_adapter *qdev) +static void ql_tx_timeout_work(struct work_struct *work) { - ql_cycle_adapter(qdev,QL_DO_RESET); + struct ql3_adapter *qdev = + container_of(work, struct ql3_adapter, tx_timeout_work.work); + + ql_cycle_adapter(qdev, QL_DO_RESET); } static void ql_get_board_info(struct ql3_adapter *qdev) @@ -3459,9 +3464,8 @@ static int __devinit ql3xxx_probe(struct pci_dev *pdev, netif_stop_queue(ndev); qdev->workqueue = create_singlethread_workqueue(ndev->name); - INIT_WORK(&qdev->reset_work, (void (*)(void *))ql_reset_work, qdev); - INIT_WORK(&qdev->tx_timeout_work, - (void (*)(void *))ql_tx_timeout_work, qdev); + INIT_DELAYED_WORK(&qdev->reset_work, ql_reset_work); + INIT_DELAYED_WORK(&qdev->tx_timeout_work, ql_tx_timeout_work); init_timer(&qdev->adapter_timer); qdev->adapter_timer.function = ql3xxx_timer; diff --git a/trunk/drivers/net/qla3xxx.h b/trunk/drivers/net/qla3xxx.h index 65da2c0bfda6..ea94de7fd071 100644 --- a/trunk/drivers/net/qla3xxx.h +++ b/trunk/drivers/net/qla3xxx.h @@ -1186,8 +1186,8 @@ struct ql3_adapter { u32 numPorts; struct net_device_stats stats; struct workqueue_struct *workqueue; - struct work_struct reset_work; - struct work_struct tx_timeout_work; + struct delayed_work reset_work; + struct delayed_work tx_timeout_work; u32 max_frame_size; }; diff --git a/trunk/drivers/net/r8169.c b/trunk/drivers/net/r8169.c index 45d3ca431957..f83b41d4cb0e 100644 --- a/trunk/drivers/net/r8169.c +++ b/trunk/drivers/net/r8169.c @@ -225,6 +225,7 @@ MODULE_DEVICE_TABLE(pci, rtl8169_pci_tbl); static int rx_copybreak = 200; static int use_dac; +static int ignore_parity_err; static struct { u32 msg_enable; } debug = { -1 }; @@ -424,6 +425,7 @@ struct ring_info { struct rtl8169_private { void __iomem *mmio_addr; /* memory map physical address */ struct pci_dev *pci_dev; /* Index of PCI device */ + struct net_device *dev; struct net_device_stats stats; /* statistics of net device */ spinlock_t lock; /* spin lock flag */ u32 msg_enable; @@ -455,7 +457,7 @@ struct rtl8169_private { void (*phy_reset_enable)(void __iomem *); unsigned int (*phy_reset_pending)(void __iomem *); unsigned int (*link_ok)(void __iomem *); - struct work_struct task; + struct delayed_work task; unsigned wol_enabled : 1; }; @@ -469,6 +471,8 @@ module_param(use_dac, int, 0); MODULE_PARM_DESC(use_dac, "Enable PCI DAC. Unsafe on 32 bit PCI slot."); module_param_named(debug, debug.msg_enable, int, 0); MODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., 16=all)"); +module_param_named(ignore_parity_err, ignore_parity_err, bool, 0); +MODULE_PARM_DESC(ignore_parity_err, "Ignore PCI parity error as target. Default: false"); MODULE_LICENSE("GPL"); MODULE_VERSION(RTL8169_VERSION); @@ -1283,11 +1287,6 @@ static void rtl8169_hw_phy_config(struct net_device *dev) /* Shazam ! */ if (tp->mac_version == RTL_GIGA_MAC_VER_04) { - mdio_write(ioaddr, 31, 0x0001); - mdio_write(ioaddr, 9, 0x273a); - mdio_write(ioaddr, 14, 0x7bfb); - mdio_write(ioaddr, 27, 0x841e); - mdio_write(ioaddr, 31, 0x0002); mdio_write(ioaddr, 1, 0x90d0); mdio_write(ioaddr, 31, 0x0000); @@ -1510,6 +1509,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) SET_MODULE_OWNER(dev); SET_NETDEV_DEV(dev, &pdev->dev); tp = netdev_priv(dev); + tp->dev = dev; tp->msg_enable = netif_msg_init(debug.msg_enable, R8169_MSG_DEFAULT); /* enable device (incl. PCI PM wakeup and hotplug setup) */ @@ -1782,7 +1782,7 @@ static int rtl8169_open(struct net_device *dev) if (retval < 0) goto err_free_rx; - INIT_WORK(&tp->task, NULL, dev); + INIT_DELAYED_WORK(&tp->task, NULL); rtl8169_hw_start(dev); @@ -1815,12 +1815,25 @@ static void rtl8169_hw_reset(void __iomem *ioaddr) RTL_R8(ChipCmd); } -static void -rtl8169_hw_start(struct net_device *dev) +static void rtl8169_set_rx_tx_config_registers(struct rtl8169_private *tp) +{ + void __iomem *ioaddr = tp->mmio_addr; + u32 cfg = rtl8169_rx_config; + + cfg |= (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask); + RTL_W32(RxConfig, cfg); + + /* Set DMA burst size and Interframe Gap Time */ + RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) | + (InterFrameGap << TxInterFrameGapShift)); +} + +static void rtl8169_hw_start(struct net_device *dev) { struct rtl8169_private *tp = netdev_priv(dev); void __iomem *ioaddr = tp->mmio_addr; struct pci_dev *pdev = tp->pci_dev; + u16 cmd; u32 i; /* Soft reset the chip. */ @@ -1833,6 +1846,11 @@ rtl8169_hw_start(struct net_device *dev) msleep_interruptible(1); } + if (tp->mac_version == RTL_GIGA_MAC_VER_05) { + RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) | PCIMulRW); + pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x08); + } + if (tp->mac_version == RTL_GIGA_MAC_VER_13) { pci_write_config_word(pdev, 0x68, 0x00); pci_write_config_word(pdev, 0x69, 0x08); @@ -1840,8 +1858,6 @@ rtl8169_hw_start(struct net_device *dev) /* Undocumented stuff. */ if (tp->mac_version == RTL_GIGA_MAC_VER_05) { - u16 cmd; - /* Realtek's r1000_n.c driver uses '&& 0x01' here. Well... */ if ((RTL_R8(Config2) & 0x07) & 0x01) RTL_W32(0x7c, 0x0007ffff); @@ -1853,23 +1869,29 @@ rtl8169_hw_start(struct net_device *dev) pci_write_config_word(pdev, PCI_COMMAND, cmd); } - RTL_W8(Cfg9346, Cfg9346_Unlock); + if ((tp->mac_version == RTL_GIGA_MAC_VER_01) || + (tp->mac_version == RTL_GIGA_MAC_VER_02) || + (tp->mac_version == RTL_GIGA_MAC_VER_03) || + (tp->mac_version == RTL_GIGA_MAC_VER_04)) + RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); + RTL_W8(EarlyTxThres, EarlyTxThld); /* Low hurts. Let's disable the filtering. */ RTL_W16(RxMaxSize, 16383); - /* Set Rx Config register */ - i = rtl8169_rx_config | - (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask); - RTL_W32(RxConfig, i); + if ((tp->mac_version == RTL_GIGA_MAC_VER_01) || + (tp->mac_version == RTL_GIGA_MAC_VER_02) || + (tp->mac_version == RTL_GIGA_MAC_VER_03) || + (tp->mac_version == RTL_GIGA_MAC_VER_04)) + RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); + rtl8169_set_rx_tx_config_registers(tp); - /* Set DMA burst size and Interframe Gap Time */ - RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) | - (InterFrameGap << TxInterFrameGapShift)); + cmd = RTL_R16(CPlusCmd); + RTL_W16(CPlusCmd, cmd); - tp->cp_cmd |= RTL_R16(CPlusCmd) | PCIMulRW; + tp->cp_cmd |= cmd | PCIMulRW; if ((tp->mac_version == RTL_GIGA_MAC_VER_02) || (tp->mac_version == RTL_GIGA_MAC_VER_03)) { @@ -1895,7 +1917,15 @@ rtl8169_hw_start(struct net_device *dev) RTL_W32(TxDescStartAddrLow, ((u64) tp->TxPhyAddr & DMA_32BIT_MASK)); RTL_W32(RxDescAddrHigh, ((u64) tp->RxPhyAddr >> 32)); RTL_W32(RxDescAddrLow, ((u64) tp->RxPhyAddr & DMA_32BIT_MASK)); - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); + + if ((tp->mac_version != RTL_GIGA_MAC_VER_01) && + (tp->mac_version != RTL_GIGA_MAC_VER_02) && + (tp->mac_version != RTL_GIGA_MAC_VER_03) && + (tp->mac_version != RTL_GIGA_MAC_VER_04)) { + RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); + rtl8169_set_rx_tx_config_registers(tp); + } + RTL_W8(Cfg9346, Cfg9346_Lock); /* Initially a 10 us delay. Turned it into a PCI commit. - FR */ @@ -1990,7 +2020,7 @@ static int rtl8169_alloc_rx_skb(struct pci_dev *pdev, struct sk_buff **sk_buff, if (!skb) goto err_out; - skb_reserve(skb, align); + skb_reserve(skb, (align - 1) & (u32)skb->data); *sk_buff = skb; mapping = pci_map_single(pdev, skb->data, rx_buf_sz, @@ -2105,11 +2135,11 @@ static void rtl8169_tx_clear(struct rtl8169_private *tp) tp->cur_tx = tp->dirty_tx = 0; } -static void rtl8169_schedule_work(struct net_device *dev, void (*task)(void *)) +static void rtl8169_schedule_work(struct net_device *dev, work_func_t task) { struct rtl8169_private *tp = netdev_priv(dev); - PREPARE_WORK(&tp->task, task, dev); + PREPARE_DELAYED_WORK(&tp->task, task); schedule_delayed_work(&tp->task, 4); } @@ -2128,9 +2158,11 @@ static void rtl8169_wait_for_quiescence(struct net_device *dev) netif_poll_enable(dev); } -static void rtl8169_reinit_task(void *_data) +static void rtl8169_reinit_task(struct work_struct *work) { - struct net_device *dev = _data; + struct rtl8169_private *tp = + container_of(work, struct rtl8169_private, task.work); + struct net_device *dev = tp->dev; int ret; if (netif_running(dev)) { @@ -2153,10 +2185,11 @@ static void rtl8169_reinit_task(void *_data) } } -static void rtl8169_reset_task(void *_data) +static void rtl8169_reset_task(struct work_struct *work) { - struct net_device *dev = _data; - struct rtl8169_private *tp = netdev_priv(dev); + struct rtl8169_private *tp = + container_of(work, struct rtl8169_private, task.work); + struct net_device *dev = tp->dev; if (!netif_running(dev)) return; @@ -2350,12 +2383,17 @@ static void rtl8169_pcierr_interrupt(struct net_device *dev) /* * The recovery sequence below admits a very elaborated explanation: * - it seems to work; - * - I did not see what else could be done. + * - I did not see what else could be done; + * - it makes iop3xx happy. * * Feel free to adjust to your needs. */ - pci_write_config_word(pdev, PCI_COMMAND, - pci_cmd | PCI_COMMAND_SERR | PCI_COMMAND_PARITY); + if (ignore_parity_err) + pci_cmd &= ~PCI_COMMAND_PARITY; + else + pci_cmd |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY; + + pci_write_config_word(pdev, PCI_COMMAND, pci_cmd); pci_write_config_word(pdev, PCI_STATUS, pci_status & (PCI_STATUS_DETECTED_PARITY | @@ -2369,10 +2407,11 @@ static void rtl8169_pcierr_interrupt(struct net_device *dev) tp->cp_cmd &= ~PCIDAC; RTL_W16(CPlusCmd, tp->cp_cmd); dev->features &= ~NETIF_F_HIGHDMA; - rtl8169_schedule_work(dev, rtl8169_reinit_task); } rtl8169_hw_reset(ioaddr); + + rtl8169_schedule_work(dev, rtl8169_reinit_task); } static void @@ -2452,7 +2491,7 @@ static inline int rtl8169_try_rx_copy(struct sk_buff **sk_buff, int pkt_size, skb = dev_alloc_skb(pkt_size + align); if (skb) { - skb_reserve(skb, align); + skb_reserve(skb, (align - 1) & (u32)skb->data); eth_copy_and_sum(skb, sk_buff[0]->data, pkt_size, 0); *sk_buff = skb; rtl8169_mark_to_asic(desc, rx_buf_sz); diff --git a/trunk/drivers/net/s2io.c b/trunk/drivers/net/s2io.c index 33569ec9dbfc..250cdbeefdfd 100644 --- a/trunk/drivers/net/s2io.c +++ b/trunk/drivers/net/s2io.c @@ -5872,9 +5872,9 @@ static void s2io_tasklet(unsigned long dev_addr) * Description: Sets the link status for the adapter */ -static void s2io_set_link(unsigned long data) +static void s2io_set_link(struct work_struct *work) { - nic_t *nic = (nic_t *) data; + nic_t *nic = container_of(work, nic_t, set_link_task); struct net_device *dev = nic->dev; XENA_dev_config_t __iomem *bar0 = nic->bar0; register u64 val64; @@ -6379,10 +6379,10 @@ static int s2io_card_up(nic_t * sp) * spin lock. */ -static void s2io_restart_nic(unsigned long data) +static void s2io_restart_nic(struct work_struct *work) { - struct net_device *dev = (struct net_device *) data; - nic_t *sp = dev->priv; + nic_t *sp = container_of(work, nic_t, rst_timer_task); + struct net_device *dev = sp->dev; s2io_card_down(sp); if (s2io_card_up(sp)) { @@ -6992,10 +6992,8 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) dev->tx_timeout = &s2io_tx_watchdog; dev->watchdog_timeo = WATCH_DOG_TIMEOUT; - INIT_WORK(&sp->rst_timer_task, - (void (*)(void *)) s2io_restart_nic, dev); - INIT_WORK(&sp->set_link_task, - (void (*)(void *)) s2io_set_link, sp); + INIT_WORK(&sp->rst_timer_task, s2io_restart_nic); + INIT_WORK(&sp->set_link_task, s2io_set_link); pci_save_state(sp->pdev); diff --git a/trunk/drivers/net/s2io.h b/trunk/drivers/net/s2io.h index 12b719f4d00f..3b0bafd273c8 100644 --- a/trunk/drivers/net/s2io.h +++ b/trunk/drivers/net/s2io.h @@ -1000,7 +1000,7 @@ s2io_msix_fifo_handle(int irq, void *dev_id); static irqreturn_t s2io_isr(int irq, void *dev_id); static int verify_xena_quiescence(nic_t *sp, u64 val64, int flag); static const struct ethtool_ops netdev_ethtool_ops; -static void s2io_set_link(unsigned long data); +static void s2io_set_link(struct work_struct *work); static int s2io_set_swapper(nic_t * sp); static void s2io_card_down(nic_t *nic); static int s2io_card_up(nic_t *nic); diff --git a/trunk/drivers/net/seeq8005.c b/trunk/drivers/net/seeq8005.c index d9d0a3a3c558..0d6c95c7aedf 100644 --- a/trunk/drivers/net/seeq8005.c +++ b/trunk/drivers/net/seeq8005.c @@ -750,7 +750,7 @@ int __init init_module(void) return 0; } -void cleanup_module(void) +void __exit cleanup_module(void) { unregister_netdev(dev_seeq); release_region(dev_seeq->base_addr, SEEQ8005_IO_EXTENT); diff --git a/trunk/drivers/net/sis190.c b/trunk/drivers/net/sis190.c index aaba458584fb..b70ed79d4121 100644 --- a/trunk/drivers/net/sis190.c +++ b/trunk/drivers/net/sis190.c @@ -280,6 +280,7 @@ enum sis190_feature { struct sis190_private { void __iomem *mmio_addr; struct pci_dev *pci_dev; + struct net_device *dev; struct net_device_stats stats; spinlock_t lock; u32 rx_buf_sz; @@ -897,10 +898,11 @@ static void sis190_hw_start(struct net_device *dev) netif_start_queue(dev); } -static void sis190_phy_task(void * data) +static void sis190_phy_task(struct work_struct *work) { - struct net_device *dev = data; - struct sis190_private *tp = netdev_priv(dev); + struct sis190_private *tp = + container_of(work, struct sis190_private, phy_task); + struct net_device *dev = tp->dev; void __iomem *ioaddr = tp->mmio_addr; int phy_id = tp->mii_if.phy_id; u16 val; @@ -1047,7 +1049,7 @@ static int sis190_open(struct net_device *dev) if (rc < 0) goto err_free_rx_1; - INIT_WORK(&tp->phy_task, sis190_phy_task, dev); + INIT_WORK(&tp->phy_task, sis190_phy_task); sis190_request_timer(dev); @@ -1436,6 +1438,7 @@ static struct net_device * __devinit sis190_init_board(struct pci_dev *pdev) SET_NETDEV_DEV(dev, &pdev->dev); tp = netdev_priv(dev); + tp->dev = dev; tp->msg_enable = netif_msg_init(debug.msg_enable, SIS190_MSG_DEFAULT); rc = pci_enable_device(pdev); @@ -1798,7 +1801,7 @@ static int __devinit sis190_init_one(struct pci_dev *pdev, sis190_init_rxfilter(dev); - INIT_WORK(&tp->phy_task, sis190_phy_task, dev); + INIT_WORK(&tp->phy_task, sis190_phy_task); dev->open = sis190_open; dev->stop = sis190_close; diff --git a/trunk/drivers/net/sk98lin/skgesirq.c b/trunk/drivers/net/sk98lin/skgesirq.c index ab66d80a4455..3e7aa49afd00 100644 --- a/trunk/drivers/net/sk98lin/skgesirq.c +++ b/trunk/drivers/net/sk98lin/skgesirq.c @@ -1319,7 +1319,7 @@ SK_BOOL AutoNeg) /* Is Auto-negotiation used ? */ SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_STAT, &Isrc); #ifdef xDEBUG - if ((Isrc & ~(PHY_B_IS_HCT | PHY_B_IS_LCT) == + if ((Isrc & ~(PHY_B_IS_HCT | PHY_B_IS_LCT)) == (PHY_B_IS_SCR_S_ER | PHY_B_IS_RRS_CHANGE | PHY_B_IS_LRS_CHANGE)) { SK_U32 Stat1, Stat2, Stat3; diff --git a/trunk/drivers/net/skge.c b/trunk/drivers/net/skge.c index 5513907e8393..b60f0451f6cd 100644 --- a/trunk/drivers/net/skge.c +++ b/trunk/drivers/net/skge.c @@ -1327,10 +1327,11 @@ static void xm_check_link(struct net_device *dev) * Since internal PHY is wired to a level triggered pin, can't * get an interrupt when carrier is detected. */ -static void xm_link_timer(void *arg) +static void xm_link_timer(struct work_struct *work) { - struct net_device *dev = arg; - struct skge_port *skge = netdev_priv(arg); + struct skge_port *skge = + container_of(work, struct skge_port, link_thread.work); + struct net_device *dev = skge->netdev; struct skge_hw *hw = skge->hw; int port = skge->port; @@ -3072,9 +3073,9 @@ static void skge_error_irq(struct skge_hw *hw) * because accessing phy registers requires spin wait which might * cause excess interrupt latency. */ -static void skge_extirq(void *arg) +static void skge_extirq(struct work_struct *work) { - struct skge_hw *hw = arg; + struct skge_hw *hw = container_of(work, struct skge_hw, phy_work); int port; mutex_lock(&hw->phy_mutex); @@ -3456,7 +3457,7 @@ static struct net_device *skge_devinit(struct skge_hw *hw, int port, skge->port = port; /* Only used for Genesis XMAC */ - INIT_WORK(&skge->link_thread, xm_link_timer, dev); + INIT_DELAYED_WORK(&skge->link_thread, xm_link_timer); if (hw->chip_id != CHIP_ID_GENESIS) { dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG; @@ -3543,7 +3544,7 @@ static int __devinit skge_probe(struct pci_dev *pdev, hw->pdev = pdev; mutex_init(&hw->phy_mutex); - INIT_WORK(&hw->phy_work, skge_extirq, hw); + INIT_WORK(&hw->phy_work, skge_extirq); spin_lock_init(&hw->hw_lock); hw->regs = ioremap_nocache(pci_resource_start(pdev, 0), 0x4000); diff --git a/trunk/drivers/net/skge.h b/trunk/drivers/net/skge.h index 537c0aaa1db8..f6223c533c01 100644 --- a/trunk/drivers/net/skge.h +++ b/trunk/drivers/net/skge.h @@ -389,10 +389,10 @@ enum { /* Packet Arbiter Registers */ /* B3_PA_CTRL 16 bit Packet Arbiter Ctrl Register */ enum { - PA_CLR_TO_TX2 = 1<<13, /* Clear IRQ Packet Timeout TX2 */ - PA_CLR_TO_TX1 = 1<<12, /* Clear IRQ Packet Timeout TX1 */ - PA_CLR_TO_RX2 = 1<<11, /* Clear IRQ Packet Timeout RX2 */ - PA_CLR_TO_RX1 = 1<<10, /* Clear IRQ Packet Timeout RX1 */ + PA_CLR_TO_TX2 = 1<<13,/* Clear IRQ Packet Timeout TX2 */ + PA_CLR_TO_TX1 = 1<<12,/* Clear IRQ Packet Timeout TX1 */ + PA_CLR_TO_RX2 = 1<<11,/* Clear IRQ Packet Timeout RX2 */ + PA_CLR_TO_RX1 = 1<<10,/* Clear IRQ Packet Timeout RX1 */ PA_ENA_TO_TX2 = 1<<9, /* Enable Timeout Timer TX2 */ PA_DIS_TO_TX2 = 1<<8, /* Disable Timeout Timer TX2 */ PA_ENA_TO_TX1 = 1<<7, /* Enable Timeout Timer TX1 */ @@ -481,14 +481,14 @@ enum { /* RAM Buffer Register Offsets */ enum { - RB_START = 0x00,/* 32 bit RAM Buffer Start Address */ + RB_START= 0x00,/* 32 bit RAM Buffer Start Address */ RB_END = 0x04,/* 32 bit RAM Buffer End Address */ RB_WP = 0x08,/* 32 bit RAM Buffer Write Pointer */ RB_RP = 0x0c,/* 32 bit RAM Buffer Read Pointer */ - RB_RX_UTPP = 0x10,/* 32 bit Rx Upper Threshold, Pause Packet */ - RB_RX_LTPP = 0x14,/* 32 bit Rx Lower Threshold, Pause Packet */ - RB_RX_UTHP = 0x18,/* 32 bit Rx Upper Threshold, High Prio */ - RB_RX_LTHP = 0x1c,/* 32 bit Rx Lower Threshold, High Prio */ + RB_RX_UTPP= 0x10,/* 32 bit Rx Upper Threshold, Pause Packet */ + RB_RX_LTPP= 0x14,/* 32 bit Rx Lower Threshold, Pause Packet */ + RB_RX_UTHP= 0x18,/* 32 bit Rx Upper Threshold, High Prio */ + RB_RX_LTHP= 0x1c,/* 32 bit Rx Lower Threshold, High Prio */ /* 0x10 - 0x1f: reserved at Tx RAM Buffer Registers */ RB_PC = 0x20,/* 32 bit RAM Buffer Packet Counter */ RB_LEV = 0x24,/* 32 bit RAM Buffer Level Register */ @@ -532,7 +532,7 @@ enum { PHY_ADDR_MARV = 0, }; -#define RB_ADDR(offs, queue) (B16_RAM_REGS + (queue) + (offs)) +#define RB_ADDR(offs, queue) ((u16)B16_RAM_REGS + (u16)(queue) + (offs)) /* Receive MAC FIFO, Receive LED, and Link_Sync regs (GENESIS only) */ enum { @@ -578,15 +578,15 @@ enum { MFF_DIS_TIST = 1<<2, /* Disable Time Stamp Gener */ MFF_CLR_INTIST = 1<<1, /* Clear IRQ No Time Stamp */ MFF_CLR_INSTAT = 1<<0, /* Clear IRQ No Status */ -#define MFF_RX_CTRL_DEF MFF_ENA_TIM_PAT + MFF_RX_CTRL_DEF = MFF_ENA_TIM_PAT, }; /* TX_MFF_CTRL1 16 bit Transmit MAC FIFO Control Reg 1 */ enum { - MFF_CLR_PERR = 1<<15, /* Clear Parity Error IRQ */ - /* Bit 14: reserved */ - MFF_ENA_PKT_REC = 1<<13, /* Enable Packet Recovery */ - MFF_DIS_PKT_REC = 1<<12, /* Disable Packet Recovery */ + MFF_CLR_PERR = 1<<15, /* Clear Parity Error IRQ */ + + MFF_ENA_PKT_REC = 1<<13, /* Enable Packet Recovery */ + MFF_DIS_PKT_REC = 1<<12, /* Disable Packet Recovery */ MFF_ENA_W4E = 1<<7, /* Enable Wait for Empty */ MFF_DIS_W4E = 1<<6, /* Disable Wait for Empty */ @@ -595,9 +595,10 @@ enum { MFF_DIS_LOOPB = 1<<2, /* Disable Loopback */ MFF_CLR_MAC_RST = 1<<1, /* Clear XMAC Reset */ MFF_SET_MAC_RST = 1<<0, /* Set XMAC Reset */ + + MFF_TX_CTRL_DEF = MFF_ENA_PKT_REC | (u16) MFF_ENA_TIM_PAT | MFF_ENA_FLUSH, }; -#define MFF_TX_CTRL_DEF (MFF_ENA_PKT_REC | MFF_ENA_TIM_PAT | MFF_ENA_FLUSH) /* RX_MFF_TST2 8 bit Receive MAC FIFO Test Register 2 */ /* TX_MFF_TST2 8 bit Transmit MAC FIFO Test Register 2 */ @@ -1304,8 +1305,8 @@ enum { /* special defines for FIBER (88E1011S only) */ enum { - PHY_M_AN_ASP_X = 1<<8, /* Asymmetric Pause */ - PHY_M_AN_PC_X = 1<<7, /* MAC Pause implemented */ + PHY_M_AN_ASP_X = 1<<8, /* Asymmetric Pause */ + PHY_M_AN_PC_X = 1<<7, /* MAC Pause implemented */ PHY_M_AN_1000X_AHD = 1<<6, /* Advertise 10000Base-X Half Duplex */ PHY_M_AN_1000X_AFD = 1<<5, /* Advertise 10000Base-X Full Duplex */ }; @@ -1320,7 +1321,7 @@ enum { /***** PHY_MARV_1000T_CTRL 16 bit r/w 1000Base-T Control Reg *****/ enum { - PHY_M_1000C_TEST = 7<<13,/* Bit 15..13: Test Modes */ + PHY_M_1000C_TEST= 7<<13,/* Bit 15..13: Test Modes */ PHY_M_1000C_MSE = 1<<12, /* Manual Master/Slave Enable */ PHY_M_1000C_MSC = 1<<11, /* M/S Configuration (1=Master) */ PHY_M_1000C_MPD = 1<<10, /* Multi-Port Device */ @@ -1349,7 +1350,7 @@ enum { PHY_M_PC_EN_DET_PLUS = 3<<8, /* Energy Detect Plus (Mode 2) */ }; -#define PHY_M_PC_MDI_XMODE(x) (((x)<<5) & PHY_M_PC_MDIX_MSK) +#define PHY_M_PC_MDI_XMODE(x) ((((u16)(x)<<5) & PHY_M_PC_MDIX_MSK) enum { PHY_M_PC_MAN_MDI = 0, /* 00 = Manual MDI configuration */ @@ -1432,24 +1433,24 @@ enum { PHY_M_EC_DIS_LINK_P = 1<<12, /* Disable Link Pulses (88E1111 only) */ PHY_M_EC_M_DSC_MSK = 3<<10, /* Bit 11..10: Master Downshift Counter */ /* (88E1011 only) */ - PHY_M_EC_S_DSC_MSK = 3<<8,/* Bit 9.. 8: Slave Downshift Counter */ + PHY_M_EC_S_DSC_MSK = 3<<8, /* Bit 9.. 8: Slave Downshift Counter */ /* (88E1011 only) */ - PHY_M_EC_M_DSC_MSK2 = 7<<9,/* Bit 11.. 9: Master Downshift Counter */ + PHY_M_EC_M_DSC_MSK2 = 7<<9, /* Bit 11.. 9: Master Downshift Counter */ /* (88E1111 only) */ - PHY_M_EC_DOWN_S_ENA = 1<<8, /* Downshift Enable (88E1111 only) */ + PHY_M_EC_DOWN_S_ENA = 1<<8, /* Downshift Enable (88E1111 only) */ /* !!! Errata in spec. (1 = disable) */ - PHY_M_EC_RX_TIM_CT = 1<<7, /* RGMII Rx Timing Control*/ - PHY_M_EC_MAC_S_MSK = 7<<4,/* Bit 6.. 4: Def. MAC interface speed */ - PHY_M_EC_FIB_AN_ENA = 1<<3, /* Fiber Auto-Neg. Enable (88E1011S only) */ - PHY_M_EC_DTE_D_ENA = 1<<2, /* DTE Detect Enable (88E1111 only) */ - PHY_M_EC_TX_TIM_CT = 1<<1, /* RGMII Tx Timing Control */ - PHY_M_EC_TRANS_DIS = 1<<0, /* Transmitter Disable (88E1111 only) */}; - -#define PHY_M_EC_M_DSC(x) ((x)<<10) /* 00=1x; 01=2x; 10=3x; 11=4x */ -#define PHY_M_EC_S_DSC(x) ((x)<<8) /* 00=dis; 01=1x; 10=2x; 11=3x */ -#define PHY_M_EC_MAC_S(x) ((x)<<4) /* 01X=0; 110=2.5; 111=25 (MHz) */ - -#define PHY_M_EC_M_DSC_2(x) ((x)<<9) /* 000=1x; 001=2x; 010=3x; 011=4x */ + PHY_M_EC_RX_TIM_CT = 1<<7, /* RGMII Rx Timing Control*/ + PHY_M_EC_MAC_S_MSK = 7<<4, /* Bit 6.. 4: Def. MAC interface speed */ + PHY_M_EC_FIB_AN_ENA = 1<<3, /* Fiber Auto-Neg. Enable (88E1011S only) */ + PHY_M_EC_DTE_D_ENA = 1<<2, /* DTE Detect Enable (88E1111 only) */ + PHY_M_EC_TX_TIM_CT = 1<<1, /* RGMII Tx Timing Control */ + PHY_M_EC_TRANS_DIS = 1<<0, /* Transmitter Disable (88E1111 only) */}; + +#define PHY_M_EC_M_DSC(x) ((u16)(x)<<10) /* 00=1x; 01=2x; 10=3x; 11=4x */ +#define PHY_M_EC_S_DSC(x) ((u16)(x)<<8) /* 00=dis; 01=1x; 10=2x; 11=3x */ +#define PHY_M_EC_MAC_S(x) ((u16)(x)<<4) /* 01X=0; 110=2.5; 111=25 (MHz) */ + +#define PHY_M_EC_M_DSC_2(x) ((u16)(x)<<9) /* 000=1x; 001=2x; 010=3x; 011=4x */ /* 100=5x; 101=6x; 110=7x; 111=8x */ enum { MAC_TX_CLK_0_MHZ = 2, @@ -1468,10 +1469,12 @@ enum { PHY_M_LEDC_LK_C_MSK = 7<<3,/* Bit 5.. 3: Link Control Mask */ /* (88E1111 only) */ }; +#define PHY_M_LED_PULS_DUR(x) (((u16)(x)<<12) & PHY_M_LEDC_PULS_MSK) +#define PHY_M_LED_BLINK_RT(x) (((u16)(x)<<8) & PHY_M_LEDC_BL_R_MSK) enum { - PHY_M_LEDC_LINK_MSK = 3<<3,/* Bit 4.. 3: Link Control Mask */ - /* (88E1011 only) */ + PHY_M_LEDC_LINK_MSK = 3<<3, /* Bit 4.. 3: Link Control Mask */ + /* (88E1011 only) */ PHY_M_LEDC_DP_CTRL = 1<<2, /* Duplex Control */ PHY_M_LEDC_DP_C_MSB = 1<<2, /* Duplex Control (MSB, 88E1111 only) */ PHY_M_LEDC_RX_CTRL = 1<<1, /* Rx Activity / Link */ @@ -1479,27 +1482,24 @@ enum { PHY_M_LEDC_TX_C_MSB = 1<<0, /* Tx Control (MSB, 88E1111 only) */ }; -#define PHY_M_LED_PULS_DUR(x) (((x)<<12) & PHY_M_LEDC_PULS_MSK) - enum { - PULS_NO_STR = 0,/* no pulse stretching */ - PULS_21MS = 1,/* 21 ms to 42 ms */ - PULS_42MS = 2,/* 42 ms to 84 ms */ - PULS_84MS = 3,/* 84 ms to 170 ms */ - PULS_170MS = 4,/* 170 ms to 340 ms */ - PULS_340MS = 5,/* 340 ms to 670 ms */ - PULS_670MS = 6,/* 670 ms to 1.3 s */ - PULS_1300MS = 7,/* 1.3 s to 2.7 s */ + PULS_NO_STR = 0, /* no pulse stretching */ + PULS_21MS = 1, /* 21 ms to 42 ms */ + PULS_42MS = 2, /* 42 ms to 84 ms */ + PULS_84MS = 3, /* 84 ms to 170 ms */ + PULS_170MS = 4, /* 170 ms to 340 ms */ + PULS_340MS = 5, /* 340 ms to 670 ms */ + PULS_670MS = 6, /* 670 ms to 1.3 s */ + PULS_1300MS = 7, /* 1.3 s to 2.7 s */ }; -#define PHY_M_LED_BLINK_RT(x) (((x)<<8) & PHY_M_LEDC_BL_R_MSK) enum { - BLINK_42MS = 0,/* 42 ms */ - BLINK_84MS = 1,/* 84 ms */ - BLINK_170MS = 2,/* 170 ms */ - BLINK_340MS = 3,/* 340 ms */ - BLINK_670MS = 4,/* 670 ms */ + BLINK_42MS = 0, /* 42 ms */ + BLINK_84MS = 1, /* 84 ms */ + BLINK_170MS = 2, /* 170 ms */ + BLINK_340MS = 3, /* 340 ms */ + BLINK_670MS = 4, /* 670 ms */ }; /***** PHY_MARV_LED_OVER 16 bit r/w Manual LED Override Reg *****/ @@ -1525,7 +1525,7 @@ enum { PHY_M_EC2_FO_IMPED = 1<<5, /* Fiber Output Impedance */ PHY_M_EC2_FO_M_CLK = 1<<4, /* Fiber Mode Clock Enable */ PHY_M_EC2_FO_BOOST = 1<<3, /* Fiber Output Boost */ - PHY_M_EC2_FO_AM_MSK = 7,/* Bit 2.. 0: Fiber Output Amplitude */ + PHY_M_EC2_FO_AM_MSK = 7, /* Bit 2.. 0: Fiber Output Amplitude */ }; /***** PHY_MARV_EXT_P_STAT 16 bit r/w Ext. PHY Specific Status *****/ @@ -1550,7 +1550,7 @@ enum { PHY_M_CABD_DIS_WAIT = 1<<15, /* Disable Waiting Period (Page 1) */ /* (88E1111 only) */ PHY_M_CABD_STAT_MSK = 3<<13, /* Bit 14..13: Status Mask */ - PHY_M_CABD_AMPL_MSK = 0x1f<<8,/* Bit 12.. 8: Amplitude Mask */ + PHY_M_CABD_AMPL_MSK = 0x1f<<8, /* Bit 12.. 8: Amplitude Mask */ /* (88E1111 only) */ PHY_M_CABD_DIST_MSK = 0xff, /* Bit 7.. 0: Distance Mask */ }; @@ -1605,9 +1605,9 @@ enum { /***** PHY_MARV_PHY_CTRL (page 3) 16 bit r/w LED Control Reg. *****/ enum { - PHY_M_LEDC_LOS_MSK = 0xf<<12,/* Bit 15..12: LOS LED Ctrl. Mask */ + PHY_M_LEDC_LOS_MSK = 0xf<<12, /* Bit 15..12: LOS LED Ctrl. Mask */ PHY_M_LEDC_INIT_MSK = 0xf<<8, /* Bit 11.. 8: INIT LED Ctrl. Mask */ - PHY_M_LEDC_STA1_MSK = 0xf<<4,/* Bit 7.. 4: STAT1 LED Ctrl. Mask */ + PHY_M_LEDC_STA1_MSK = 0xf<<4, /* Bit 7.. 4: STAT1 LED Ctrl. Mask */ PHY_M_LEDC_STA0_MSK = 0xf, /* Bit 3.. 0: STAT0 LED Ctrl. Mask */ }; @@ -1804,8 +1804,8 @@ enum { /* GM_SMI_CTRL 16 bit r/w SMI Control Register */ enum { - GM_SMI_CT_PHY_A_MSK = 0x1f<<11,/* Bit 15..11: PHY Device Address */ - GM_SMI_CT_REG_A_MSK = 0x1f<<6,/* Bit 10.. 6: PHY Register Address */ + GM_SMI_CT_PHY_A_MSK = 0x1f<<11, /* Bit 15..11: PHY Device Address */ + GM_SMI_CT_REG_A_MSK = 0x1f<<6, /* Bit 10.. 6: PHY Register Address */ GM_SMI_CT_OP_RD = 1<<5, /* Bit 5: OpCode Read (0=Write)*/ GM_SMI_CT_RD_VAL = 1<<4, /* Bit 4: Read Valid (Read completed) */ GM_SMI_CT_BUSY = 1<<3, /* Bit 3: Busy (Operation in progress) */ @@ -1875,9 +1875,9 @@ enum { /* TX_GMF_CTRL_T 32 bit Tx GMAC FIFO Control/Test */ enum { - GMF_WSP_TST_ON = 1<<18,/* Write Shadow Pointer Test On */ - GMF_WSP_TST_OFF = 1<<17,/* Write Shadow Pointer Test Off */ - GMF_WSP_STEP = 1<<16,/* Write Shadow Pointer Step/Increment */ + GMF_WSP_TST_ON = 1<<18, /* Write Shadow Pointer Test On */ + GMF_WSP_TST_OFF = 1<<17, /* Write Shadow Pointer Test Off */ + GMF_WSP_STEP = 1<<16, /* Write Shadow Pointer Step/Increment */ GMF_CLI_TX_FU = 1<<6, /* Clear IRQ Tx FIFO Underrun */ GMF_CLI_TX_FC = 1<<5, /* Clear IRQ Tx Frame Complete */ @@ -2111,18 +2111,18 @@ enum { /* XM_MMU_CMD 16 bit r/w MMU Command Register */ enum { - XM_MMU_PHY_RDY = 1<<12,/* Bit 12: PHY Read Ready */ - XM_MMU_PHY_BUSY = 1<<11,/* Bit 11: PHY Busy */ - XM_MMU_IGN_PF = 1<<10,/* Bit 10: Ignore Pause Frame */ - XM_MMU_MAC_LB = 1<<9, /* Bit 9: Enable MAC Loopback */ - XM_MMU_FRC_COL = 1<<7, /* Bit 7: Force Collision */ - XM_MMU_SIM_COL = 1<<6, /* Bit 6: Simulate Collision */ - XM_MMU_NO_PRE = 1<<5, /* Bit 5: No MDIO Preamble */ - XM_MMU_GMII_FD = 1<<4, /* Bit 4: GMII uses Full Duplex */ - XM_MMU_RAT_CTRL = 1<<3, /* Bit 3: Enable Rate Control */ - XM_MMU_GMII_LOOP= 1<<2, /* Bit 2: PHY is in Loopback Mode */ - XM_MMU_ENA_RX = 1<<1, /* Bit 1: Enable Receiver */ - XM_MMU_ENA_TX = 1<<0, /* Bit 0: Enable Transmitter */ + XM_MMU_PHY_RDY = 1<<12, /* Bit 12: PHY Read Ready */ + XM_MMU_PHY_BUSY = 1<<11, /* Bit 11: PHY Busy */ + XM_MMU_IGN_PF = 1<<10, /* Bit 10: Ignore Pause Frame */ + XM_MMU_MAC_LB = 1<<9, /* Bit 9: Enable MAC Loopback */ + XM_MMU_FRC_COL = 1<<7, /* Bit 7: Force Collision */ + XM_MMU_SIM_COL = 1<<6, /* Bit 6: Simulate Collision */ + XM_MMU_NO_PRE = 1<<5, /* Bit 5: No MDIO Preamble */ + XM_MMU_GMII_FD = 1<<4, /* Bit 4: GMII uses Full Duplex */ + XM_MMU_RAT_CTRL = 1<<3, /* Bit 3: Enable Rate Control */ + XM_MMU_GMII_LOOP= 1<<2, /* Bit 2: PHY is in Loopback Mode */ + XM_MMU_ENA_RX = 1<<1, /* Bit 1: Enable Receiver */ + XM_MMU_ENA_TX = 1<<0, /* Bit 0: Enable Transmitter */ }; @@ -2456,7 +2456,7 @@ struct skge_port { struct net_device_stats net_stats; - struct work_struct link_thread; + struct delayed_work link_thread; enum pause_control flow_control; enum pause_status flow_status; u8 rx_csum; @@ -2506,7 +2506,7 @@ static inline void skge_write8(const struct skge_hw *hw, int reg, u8 val) } /* MAC Related Registers inside the device. */ -#define SK_REG(port,reg) (((port)<<7)+(reg)) +#define SK_REG(port,reg) (((port)<<7)+(u16)(reg)) #define SK_XMAC_REG(port, reg) \ ((BASE_XMAC_1 + (port) * (BASE_XMAC_2 - BASE_XMAC_1)) | (reg) << 1) diff --git a/trunk/drivers/net/sky2.c b/trunk/drivers/net/sky2.c index 842abd9396c6..fb1d2c30c1bb 100644 --- a/trunk/drivers/net/sky2.c +++ b/trunk/drivers/net/sky2.c @@ -100,33 +100,32 @@ module_param(idle_timeout, int, 0); MODULE_PARM_DESC(idle_timeout, "Watchdog timer for lost interrupts (ms)"); static const struct pci_device_id sky2_id_table[] = { - { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9000) }, - { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9E00) }, + { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9000) }, /* SK-9Sxx */ + { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9E00) }, /* SK-9Exx */ { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4b00) }, /* DGE-560T */ { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4001) }, /* DGE-550SX */ { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4B02) }, /* DGE-560SX */ - { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4340) }, - { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4341) }, - { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4342) }, - { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4343) }, - { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4344) }, - { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4345) }, - { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4346) }, - { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4347) }, - { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4350) }, - { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4351) }, - { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4352) }, - { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4353) }, - { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4360) }, - { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4361) }, - { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4362) }, - { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4363) }, - { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4364) }, - { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4365) }, - { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4366) }, - { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4367) }, - { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4368) }, - { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4369) }, + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4340) }, /* 88E8021 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4341) }, /* 88E8022 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4342) }, /* 88E8061 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4343) }, /* 88E8062 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4344) }, /* 88E8021 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4345) }, /* 88E8022 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4346) }, /* 88E8061 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4347) }, /* 88E8062 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4350) }, /* 88E8035 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4351) }, /* 88E8036 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4352) }, /* 88E8038 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4353) }, /* 88E8039 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4356) }, /* 88EC033 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4360) }, /* 88E8052 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4361) }, /* 88E8050 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4362) }, /* 88E8053 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4363) }, /* 88E8055 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4364) }, /* 88E8056 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4366) }, /* 88EC036 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4367) }, /* 88EC032 */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4368) }, /* 88EC034 */ { 0 } }; @@ -522,7 +521,7 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) /* set Tx LED (LED_TX) to blink mode on Rx OR Tx activity */ ledctrl |= PHY_M_LED_BLINK_RT(BLINK_84MS) | PHY_M_LEDC_TX_CTRL; /* turn off the Rx LED (LED_RX) */ - ledover |= PHY_M_LED_MO_RX(MO_LED_OFF); + ledover &= ~PHY_M_LED_MO_RX; } if (hw->chip_id == CHIP_ID_YUKON_EC_U && hw->chip_rev == CHIP_REV_YU_EC_A1) { @@ -545,7 +544,7 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) if (sky2->autoneg == AUTONEG_DISABLE || sky2->speed == SPEED_100) { /* turn on 100 Mbps LED (LED_LINK100) */ - ledover |= PHY_M_LED_MO_100(MO_LED_ON); + ledover |= PHY_M_LED_MO_100; } if (ledover) @@ -697,10 +696,15 @@ static void sky2_mac_init(struct sky2_hw *hw, unsigned port) } -/* Assign Ram Buffer allocation in units of 64bit (8 bytes) */ -static void sky2_ramset(struct sky2_hw *hw, u16 q, u32 start, u32 end) +/* Assign Ram Buffer allocation to queue */ +static void sky2_ramset(struct sky2_hw *hw, u16 q, u32 start, u32 space) { - pr_debug(PFX "q %d %#x %#x\n", q, start, end); + u32 end; + + /* convert from K bytes to qwords used for hw register */ + start *= 1024/8; + space *= 1024/8; + end = start + space - 1; sky2_write8(hw, RB_ADDR(q, RB_CTRL), RB_RST_CLR); sky2_write32(hw, RB_ADDR(q, RB_START), start); @@ -709,7 +713,6 @@ static void sky2_ramset(struct sky2_hw *hw, u16 q, u32 start, u32 end) sky2_write32(hw, RB_ADDR(q, RB_RP), start); if (q == Q_R1 || q == Q_R2) { - u32 space = end - start + 1; u32 tp = space - space/4; /* On receive queue's set the thresholds @@ -1059,11 +1062,16 @@ static int sky2_rx_start(struct sky2_port *sky2) sky2->rx_put = sky2->rx_next = 0; sky2_qset(hw, rxq); + /* On PCI express lowering the watermark gives better performance */ + if (pci_find_capability(hw->pdev, PCI_CAP_ID_EXP)) + sky2_write32(hw, Q_ADDR(rxq, Q_WM), BMU_WM_PEX); + + /* These chips have no ram buffer? + * MAC Rx RAM Read is controlled by hardware */ if (hw->chip_id == CHIP_ID_YUKON_EC_U && - (hw->chip_rev == CHIP_REV_YU_EC_U_A1 || hw->chip_rev == CHIP_REV_YU_EC_U_B0)) { - /* MAC Rx RAM Read is controlled by hardware */ + (hw->chip_rev == CHIP_REV_YU_EC_U_A1 + || hw->chip_rev == CHIP_REV_YU_EC_U_B0)) sky2_write32(hw, Q_ADDR(rxq, Q_F), F_M_RX_RAM_DIS); - } sky2_prefetch_init(hw, rxq, sky2->rx_le_map, RX_LE_SIZE - 1); @@ -1139,7 +1147,7 @@ static int sky2_up(struct net_device *dev) struct sky2_port *sky2 = netdev_priv(dev); struct sky2_hw *hw = sky2->hw; unsigned port = sky2->port; - u32 ramsize, rxspace, imask; + u32 ramsize, imask; int cap, err = -ENOMEM; struct net_device *otherdev = hw->dev[sky2->port^1]; @@ -1192,20 +1200,25 @@ static int sky2_up(struct net_device *dev) sky2_mac_init(hw, port); - /* Determine available ram buffer space in qwords. */ - ramsize = sky2_read8(hw, B2_E_0) * 4096/8; + /* Register is number of 4K blocks on internal RAM buffer. */ + ramsize = sky2_read8(hw, B2_E_0) * 4; + printk(KERN_INFO PFX "%s: ram buffer %dK\n", dev->name, ramsize); - if (ramsize > 6*1024/8) - rxspace = ramsize - (ramsize + 2) / 3; - else - rxspace = ramsize / 2; + if (ramsize > 0) { + u32 rxspace; - sky2_ramset(hw, rxqaddr[port], 0, rxspace-1); - sky2_ramset(hw, txqaddr[port], rxspace, ramsize-1); + if (ramsize < 16) + rxspace = ramsize / 2; + else + rxspace = 8 + (2*(ramsize - 16))/3; + + sky2_ramset(hw, rxqaddr[port], 0, rxspace); + sky2_ramset(hw, txqaddr[port], rxspace, ramsize - rxspace); - /* Make sure SyncQ is disabled */ - sky2_write8(hw, RB_ADDR(port == 0 ? Q_XS1 : Q_XS2, RB_CTRL), - RB_RST_SET); + /* Make sure SyncQ is disabled */ + sky2_write8(hw, RB_ADDR(port == 0 ? Q_XS1 : Q_XS2, RB_CTRL), + RB_RST_SET); + } sky2_qset(hw, txqaddr[port]); @@ -2917,18 +2930,8 @@ static void sky2_led(struct sky2_hw *hw, unsigned port, int on) default: gm_phy_write(hw, port, PHY_MARV_LED_CTRL, 0); - gm_phy_write(hw, port, PHY_MARV_LED_OVER, - on ? PHY_M_LED_MO_DUP(MO_LED_ON) | - PHY_M_LED_MO_10(MO_LED_ON) | - PHY_M_LED_MO_100(MO_LED_ON) | - PHY_M_LED_MO_1000(MO_LED_ON) | - PHY_M_LED_MO_RX(MO_LED_ON) - : PHY_M_LED_MO_DUP(MO_LED_OFF) | - PHY_M_LED_MO_10(MO_LED_OFF) | - PHY_M_LED_MO_100(MO_LED_OFF) | - PHY_M_LED_MO_1000(MO_LED_OFF) | - PHY_M_LED_MO_RX(MO_LED_OFF)); - + gm_phy_write(hw, port, PHY_MARV_LED_OVER, + on ? PHY_M_LED_ALL : 0); } } diff --git a/trunk/drivers/net/sky2.h b/trunk/drivers/net/sky2.h index 7760545edbf2..6ed1d47dbbd3 100644 --- a/trunk/drivers/net/sky2.h +++ b/trunk/drivers/net/sky2.h @@ -608,7 +608,7 @@ enum { PHY_ADDR_MARV = 0, }; -#define RB_ADDR(offs, queue) (B16_RAM_REGS + (queue) + (offs)) +#define RB_ADDR(offs, queue) ((u16) B16_RAM_REGS + (queue) + (offs)) enum { @@ -680,6 +680,7 @@ enum { BMU_FIFO_ENA | BMU_OP_ON, BMU_WM_DEFAULT = 0x600, + BMU_WM_PEX = 0x80, }; /* Tx BMU Control / Status Registers (Yukon-2) */ @@ -1060,7 +1061,7 @@ enum { PHY_M_PC_EN_DET_PLUS = 3<<8, /* Energy Detect Plus (Mode 2) */ }; -#define PHY_M_PC_MDI_XMODE(x) (((x)<<5) & PHY_M_PC_MDIX_MSK) +#define PHY_M_PC_MDI_XMODE(x) (((u16)(x)<<5) & PHY_M_PC_MDIX_MSK) enum { PHY_M_PC_MAN_MDI = 0, /* 00 = Manual MDI configuration */ @@ -1156,13 +1157,13 @@ enum { PHY_M_EC_TX_TIM_CT = 1<<1, /* RGMII Tx Timing Control */ PHY_M_EC_TRANS_DIS = 1<<0, /* Transmitter Disable (88E1111 only) */}; -#define PHY_M_EC_M_DSC(x) ((x)<<10 & PHY_M_EC_M_DSC_MSK) +#define PHY_M_EC_M_DSC(x) ((u16)(x)<<10 & PHY_M_EC_M_DSC_MSK) /* 00=1x; 01=2x; 10=3x; 11=4x */ -#define PHY_M_EC_S_DSC(x) ((x)<<8 & PHY_M_EC_S_DSC_MSK) +#define PHY_M_EC_S_DSC(x) ((u16)(x)<<8 & PHY_M_EC_S_DSC_MSK) /* 00=dis; 01=1x; 10=2x; 11=3x */ -#define PHY_M_EC_DSC_2(x) ((x)<<9 & PHY_M_EC_M_DSC_MSK2) +#define PHY_M_EC_DSC_2(x) ((u16)(x)<<9 & PHY_M_EC_M_DSC_MSK2) /* 000=1x; 001=2x; 010=3x; 011=4x */ -#define PHY_M_EC_MAC_S(x) ((x)<<4 & PHY_M_EC_MAC_S_MSK) +#define PHY_M_EC_MAC_S(x) ((u16)(x)<<4 & PHY_M_EC_MAC_S_MSK) /* 01X=0; 110=2.5; 111=25 (MHz) */ /* for Yukon-2 Gigabit Ethernet PHY (88E1112 only) */ @@ -1173,7 +1174,7 @@ enum { }; /* !!! Errata in spec. (1 = disable) */ -#define PHY_M_PC_DSC(x) (((x)<<12) & PHY_M_PC_DSC_MSK) +#define PHY_M_PC_DSC(x) (((u16)(x)<<12) & PHY_M_PC_DSC_MSK) /* 100=5x; 101=6x; 110=7x; 111=8x */ enum { MAC_TX_CLK_0_MHZ = 2, @@ -1203,7 +1204,7 @@ enum { PHY_M_LEDC_TX_C_MSB = 1<<0, /* Tx Control (MSB, 88E1111 only) */ }; -#define PHY_M_LED_PULS_DUR(x) (((x)<<12) & PHY_M_LEDC_PULS_MSK) +#define PHY_M_LED_PULS_DUR(x) (((u16)(x)<<12) & PHY_M_LEDC_PULS_MSK) /***** PHY_MARV_PHY_STAT (page 3)16 bit r/w Polarity Control Reg. *****/ enum { @@ -1233,7 +1234,7 @@ enum { PULS_1300MS = 7,/* 1.3 s to 2.7 s */ }; -#define PHY_M_LED_BLINK_RT(x) (((x)<<8) & PHY_M_LEDC_BL_R_MSK) +#define PHY_M_LED_BLINK_RT(x) (((u16)(x)<<8) & PHY_M_LEDC_BL_R_MSK) enum { BLINK_42MS = 0,/* 42 ms */ @@ -1243,21 +1244,18 @@ enum { BLINK_670MS = 4,/* 670 ms */ }; -/***** PHY_MARV_LED_OVER 16 bit r/w Manual LED Override Reg *****/ -#define PHY_M_LED_MO_SGMII(x) ((x)<<14) /* Bit 15..14: SGMII AN Timer */ - /* Bit 13..12: reserved */ -#define PHY_M_LED_MO_DUP(x) ((x)<<10) /* Bit 11..10: Duplex */ -#define PHY_M_LED_MO_10(x) ((x)<<8) /* Bit 9.. 8: Link 10 */ -#define PHY_M_LED_MO_100(x) ((x)<<6) /* Bit 7.. 6: Link 100 */ -#define PHY_M_LED_MO_1000(x) ((x)<<4) /* Bit 5.. 4: Link 1000 */ -#define PHY_M_LED_MO_RX(x) ((x)<<2) /* Bit 3.. 2: Rx */ -#define PHY_M_LED_MO_TX(x) ((x)<<0) /* Bit 1.. 0: Tx */ - +/**** PHY_MARV_LED_OVER 16 bit r/w LED control */ enum { - MO_LED_NORM = 0, - MO_LED_BLINK = 1, - MO_LED_OFF = 2, - MO_LED_ON = 3, + PHY_M_LED_MO_DUP = 3<<10,/* Bit 11..10: Duplex */ + PHY_M_LED_MO_10 = 3<<8, /* Bit 9.. 8: Link 10 */ + PHY_M_LED_MO_100 = 3<<6, /* Bit 7.. 6: Link 100 */ + PHY_M_LED_MO_1000 = 3<<4, /* Bit 5.. 4: Link 1000 */ + PHY_M_LED_MO_RX = 3<<2, /* Bit 3.. 2: Rx */ + PHY_M_LED_MO_TX = 3<<0, /* Bit 1.. 0: Tx */ + + PHY_M_LED_ALL = PHY_M_LED_MO_DUP | PHY_M_LED_MO_10 + | PHY_M_LED_MO_100 | PHY_M_LED_MO_1000 + | PHY_M_LED_MO_RX, }; /***** PHY_MARV_EXT_CTRL_2 16 bit r/w Ext. PHY Specific Ctrl 2 *****/ @@ -1294,9 +1292,9 @@ enum { PHY_M_FELP_LED0_MSK = 0xf, /* Bit 3.. 0: LED0 Mask (SPEED) */ }; -#define PHY_M_FELP_LED2_CTRL(x) (((x)<<8) & PHY_M_FELP_LED2_MSK) -#define PHY_M_FELP_LED1_CTRL(x) (((x)<<4) & PHY_M_FELP_LED1_MSK) -#define PHY_M_FELP_LED0_CTRL(x) (((x)<<0) & PHY_M_FELP_LED0_MSK) +#define PHY_M_FELP_LED2_CTRL(x) (((u16)(x)<<8) & PHY_M_FELP_LED2_MSK) +#define PHY_M_FELP_LED1_CTRL(x) (((u16)(x)<<4) & PHY_M_FELP_LED1_MSK) +#define PHY_M_FELP_LED0_CTRL(x) (((u16)(x)<<0) & PHY_M_FELP_LED0_MSK) enum { LED_PAR_CTRL_COLX = 0x00, @@ -1552,8 +1550,8 @@ enum { GM_SMI_CT_BUSY = 1<<3, /* Bit 3: Busy (Operation in progress) */ }; -#define GM_SMI_CT_PHY_AD(x) (((x)<<11) & GM_SMI_CT_PHY_A_MSK) -#define GM_SMI_CT_REG_AD(x) (((x)<<6) & GM_SMI_CT_REG_A_MSK) +#define GM_SMI_CT_PHY_AD(x) (((u16)(x)<<11) & GM_SMI_CT_PHY_A_MSK) +#define GM_SMI_CT_REG_AD(x) (((u16)(x)<<6) & GM_SMI_CT_REG_A_MSK) /* GM_PHY_ADDR 16 bit r/w GPHY Address Register */ enum { diff --git a/trunk/drivers/net/smc-ultra.c b/trunk/drivers/net/smc-ultra.c index 889ef0d7c374..d70bc9795346 100644 --- a/trunk/drivers/net/smc-ultra.c +++ b/trunk/drivers/net/smc-ultra.c @@ -593,7 +593,7 @@ static void cleanup_card(struct net_device *dev) iounmap(ei_status.mem); } -void +void __exit cleanup_module(void) { int this_dev; diff --git a/trunk/drivers/net/smc-ultra32.c b/trunk/drivers/net/smc-ultra32.c index e10755ec5def..2c5319c62fa5 100644 --- a/trunk/drivers/net/smc-ultra32.c +++ b/trunk/drivers/net/smc-ultra32.c @@ -437,7 +437,7 @@ int __init init_module(void) return -ENXIO; } -void cleanup_module(void) +void __exit cleanup_module(void) { int this_dev; diff --git a/trunk/drivers/net/smc9194.c b/trunk/drivers/net/smc9194.c index c0d13d650913..bd6e84506c29 100644 --- a/trunk/drivers/net/smc9194.c +++ b/trunk/drivers/net/smc9194.c @@ -1616,7 +1616,7 @@ int __init init_module(void) return 0; } -void cleanup_module(void) +void __exit cleanup_module(void) { unregister_netdev(devSMC9194); free_irq(devSMC9194->irq, devSMC9194); diff --git a/trunk/drivers/net/smc91x.c b/trunk/drivers/net/smc91x.c index 95b6478f55c6..e62a9586fb95 100644 --- a/trunk/drivers/net/smc91x.c +++ b/trunk/drivers/net/smc91x.c @@ -210,6 +210,7 @@ struct smc_local { /* work queue */ struct work_struct phy_configure; + struct net_device *dev; int work_pending; spinlock_t lock; @@ -1114,10 +1115,11 @@ static void smc_phy_check_media(struct net_device *dev, int init) * of autonegotiation.) If the RPC ANEG bit is cleared, the selection * is controlled by the RPC SPEED and RPC DPLX bits. */ -static void smc_phy_configure(void *data) +static void smc_phy_configure(struct work_struct *work) { - struct net_device *dev = data; - struct smc_local *lp = netdev_priv(dev); + struct smc_local *lp = + container_of(work, struct smc_local, phy_configure); + struct net_device *dev = lp->dev; void __iomem *ioaddr = lp->base; int phyaddr = lp->mii.phy_id; int my_phy_caps; /* My PHY capabilities */ @@ -1592,7 +1594,7 @@ smc_open(struct net_device *dev) /* Configure the PHY, initialize the link state */ if (lp->phy_type != 0) - smc_phy_configure(dev); + smc_phy_configure(&lp->phy_configure); else { spin_lock_irq(&lp->lock); smc_10bt_check_media(dev, 1); @@ -1972,7 +1974,8 @@ static int __init smc_probe(struct net_device *dev, void __iomem *ioaddr) #endif tasklet_init(&lp->tx_task, smc_hardware_send_pkt, (unsigned long)dev); - INIT_WORK(&lp->phy_configure, smc_phy_configure, dev); + INIT_WORK(&lp->phy_configure, smc_phy_configure); + lp->dev = dev; lp->mii.phy_id_mask = 0x1f; lp->mii.reg_num_mask = 0x1f; lp->mii.force_media = 0; @@ -2322,7 +2325,7 @@ static int smc_drv_resume(struct platform_device *dev) smc_reset(ndev); smc_enable(ndev); if (lp->phy_type != 0) - smc_phy_configure(ndev); + smc_phy_configure(&lp->phy_configure); netif_device_attach(ndev); } } diff --git a/trunk/drivers/net/smc91x.h b/trunk/drivers/net/smc91x.h index a8640169fc77..9367c574477a 100644 --- a/trunk/drivers/net/smc91x.h +++ b/trunk/drivers/net/smc91x.h @@ -238,7 +238,7 @@ SMC_outw(u16 val, void __iomem *ioaddr, int reg) #define SMC_CAN_USE_16BIT 1 #define SMC_CAN_USE_32BIT 0 -#define SMC_inb(a, r) inb((u32)a) + (r)) +#define SMC_inb(a, r) inb(((u32)a) + (r)) #define SMC_inw(a, r) inw(((u32)a) + (r)) #define SMC_outb(v, a, r) outb(v, ((u32)a) + (r)) #define SMC_outw(v, a, r) outw(v, ((u32)a) + (r)) @@ -434,6 +434,24 @@ static inline void LPD7_SMC_outsw (unsigned char* a, int r, #define SMC_IRQ_FLAGS (0) +#elif defined(CONFIG_ARCH_VERSATILE) + +#define SMC_CAN_USE_8BIT 1 +#define SMC_CAN_USE_16BIT 1 +#define SMC_CAN_USE_32BIT 1 +#define SMC_NOWAIT 1 + +#define SMC_inb(a, r) readb((a) + (r)) +#define SMC_inw(a, r) readw((a) + (r)) +#define SMC_inl(a, r) readl((a) + (r)) +#define SMC_outb(v, a, r) writeb(v, (a) + (r)) +#define SMC_outw(v, a, r) writew(v, (a) + (r)) +#define SMC_outl(v, a, r) writel(v, (a) + (r)) +#define SMC_insl(a, r, p, l) readsl((a) + (r), p, l) +#define SMC_outsl(a, r, p, l) writesl((a) + (r), p, l) + +#define SMC_IRQ_FLAGS (0) + #else #define SMC_CAN_USE_8BIT 1 @@ -1216,7 +1234,7 @@ static const char * chip_ids[ 16 ] = { if (SMC_CAN_USE_32BIT) { \ void *__ptr = (p); \ int __len = (l); \ - void *__ioaddr = ioaddr; \ + void __iomem *__ioaddr = ioaddr; \ if (__len >= 2 && (unsigned long)__ptr & 2) { \ __len -= 2; \ SMC_outw(*(u16 *)__ptr, ioaddr, DATA_REG); \ @@ -1240,7 +1258,7 @@ static const char * chip_ids[ 16 ] = { if (SMC_CAN_USE_32BIT) { \ void *__ptr = (p); \ int __len = (l); \ - void *__ioaddr = ioaddr; \ + void __iomem *__ioaddr = ioaddr; \ if ((unsigned long)__ptr & 2) { \ /* \ * We want 32bit alignment here. \ diff --git a/trunk/drivers/net/spider_net.c b/trunk/drivers/net/spider_net.c index 13e0a43e423b..ebb6aa39f9c7 100644 --- a/trunk/drivers/net/spider_net.c +++ b/trunk/drivers/net/spider_net.c @@ -1939,10 +1939,11 @@ spider_net_stop(struct net_device *netdev) * called as task when tx hangs, resets interface (if interface is up) */ static void -spider_net_tx_timeout_task(void *data) +spider_net_tx_timeout_task(struct work_struct *work) { - struct net_device *netdev = data; - struct spider_net_card *card = netdev_priv(netdev); + struct spider_net_card *card = + container_of(work, struct spider_net_card, tx_timeout_task); + struct net_device *netdev = card->netdev; if (!(netdev->flags & IFF_UP)) goto out; @@ -2116,7 +2117,7 @@ spider_net_alloc_card(void) card = netdev_priv(netdev); card->netdev = netdev; card->msg_enable = SPIDER_NET_DEFAULT_MSG; - INIT_WORK(&card->tx_timeout_task, spider_net_tx_timeout_task, netdev); + INIT_WORK(&card->tx_timeout_task, spider_net_tx_timeout_task); init_waitqueue_head(&card->waitq); atomic_set(&card->tx_timeout_task_counter, 0); diff --git a/trunk/drivers/net/sun3lance.c b/trunk/drivers/net/sun3lance.c index 47a1c09d19ac..c62e85d89f41 100644 --- a/trunk/drivers/net/sun3lance.c +++ b/trunk/drivers/net/sun3lance.c @@ -945,7 +945,7 @@ static void set_multicast_list( struct net_device *dev ) static struct net_device *sun3lance_dev; -int init_module(void) +int __init init_module(void) { sun3lance_dev = sun3lance_probe(-1); if (IS_ERR(sun3lance_dev)) @@ -953,7 +953,7 @@ int init_module(void) return 0; } -void cleanup_module(void) +void __exit cleanup_module(void) { unregister_netdev(sun3lance_dev); #ifdef CONFIG_SUN3 diff --git a/trunk/drivers/net/sungem.c b/trunk/drivers/net/sungem.c index cf44e72399b9..785e4a535f9e 100644 --- a/trunk/drivers/net/sungem.c +++ b/trunk/drivers/net/sungem.c @@ -2282,9 +2282,9 @@ static void gem_do_stop(struct net_device *dev, int wol) } } -static void gem_reset_task(void *data) +static void gem_reset_task(struct work_struct *work) { - struct gem *gp = (struct gem *) data; + struct gem *gp = container_of(work, struct gem, reset_task); mutex_lock(&gp->pm_mutex); @@ -3044,7 +3044,7 @@ static int __devinit gem_init_one(struct pci_dev *pdev, gp->link_timer.function = gem_link_timer; gp->link_timer.data = (unsigned long) gp; - INIT_WORK(&gp->reset_task, gem_reset_task, gp); + INIT_WORK(&gp->reset_task, gem_reset_task); gp->lstate = link_down; gp->timer_ticks = 0; diff --git a/trunk/drivers/net/tg3.c b/trunk/drivers/net/tg3.c index c20bb998e0e5..571320ae87ab 100644 --- a/trunk/drivers/net/tg3.c +++ b/trunk/drivers/net/tg3.c @@ -68,8 +68,8 @@ #define DRV_MODULE_NAME "tg3" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "3.69" -#define DRV_MODULE_RELDATE "November 15, 2006" +#define DRV_MODULE_VERSION "3.70" +#define DRV_MODULE_RELDATE "December 1, 2006" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 @@ -192,6 +192,7 @@ static struct pci_device_id tg3_pci_tbl[] = { {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5786)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787M)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787F)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5714)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5714S)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5715)}, @@ -1061,7 +1062,7 @@ static void tg3_frob_aux_power(struct tg3 *tp) { struct tg3 *tp_peer = tp; - if ((tp->tg3_flags & TG3_FLAG_EEPROM_WRITE_PROT) != 0) + if ((tp->tg3_flags2 & TG3_FLG2_IS_NIC) == 0) return; if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) || @@ -1212,8 +1213,8 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state) power_control); udelay(100); /* Delay after power state change */ - /* Switch out of Vaux if it is not a LOM */ - if (!(tp->tg3_flags & TG3_FLAG_EEPROM_WRITE_PROT)) + /* Switch out of Vaux if it is a NIC */ + if (tp->tg3_flags2 & TG3_FLG2_IS_NIC) tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl, 100); return 0; @@ -1401,8 +1402,10 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state) static void tg3_link_report(struct tg3 *tp) { if (!netif_carrier_ok(tp->dev)) { - printk(KERN_INFO PFX "%s: Link is down.\n", tp->dev->name); - } else { + if (netif_msg_link(tp)) + printk(KERN_INFO PFX "%s: Link is down.\n", + tp->dev->name); + } else if (netif_msg_link(tp)) { printk(KERN_INFO PFX "%s: Link is up at %d Mbps, %s duplex.\n", tp->dev->name, (tp->link_config.active_speed == SPEED_1000 ? @@ -1557,12 +1560,6 @@ static void tg3_phy_copper_begin(struct tg3 *tp) tg3_writephy(tp, MII_ADVERTISE, new_adv); } else if (tp->link_config.speed == SPEED_INVALID) { - tp->link_config.advertising = - (ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | - ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full | - ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full | - ADVERTISED_Autoneg | ADVERTISED_MII); - if (tp->tg3_flags & TG3_FLAG_10_100_ONLY) tp->link_config.advertising &= ~(ADVERTISED_1000baseT_Half | @@ -1706,25 +1703,36 @@ static int tg3_init_5401phy_dsp(struct tg3 *tp) return err; } -static int tg3_copper_is_advertising_all(struct tg3 *tp) +static int tg3_copper_is_advertising_all(struct tg3 *tp, u32 mask) { - u32 adv_reg, all_mask; + u32 adv_reg, all_mask = 0; + + if (mask & ADVERTISED_10baseT_Half) + all_mask |= ADVERTISE_10HALF; + if (mask & ADVERTISED_10baseT_Full) + all_mask |= ADVERTISE_10FULL; + if (mask & ADVERTISED_100baseT_Half) + all_mask |= ADVERTISE_100HALF; + if (mask & ADVERTISED_100baseT_Full) + all_mask |= ADVERTISE_100FULL; if (tg3_readphy(tp, MII_ADVERTISE, &adv_reg)) return 0; - all_mask = (ADVERTISE_10HALF | ADVERTISE_10FULL | - ADVERTISE_100HALF | ADVERTISE_100FULL); if ((adv_reg & all_mask) != all_mask) return 0; if (!(tp->tg3_flags & TG3_FLAG_10_100_ONLY)) { u32 tg3_ctrl; + all_mask = 0; + if (mask & ADVERTISED_1000baseT_Half) + all_mask |= ADVERTISE_1000HALF; + if (mask & ADVERTISED_1000baseT_Full) + all_mask |= ADVERTISE_1000FULL; + if (tg3_readphy(tp, MII_TG3_CTRL, &tg3_ctrl)) return 0; - all_mask = (MII_TG3_CTRL_ADV_1000_HALF | - MII_TG3_CTRL_ADV_1000_FULL); if ((tg3_ctrl & all_mask) != all_mask) return 0; } @@ -1884,7 +1892,8 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset) /* Force autoneg restart if we are exiting * low power mode. */ - if (!tg3_copper_is_advertising_all(tp)) + if (!tg3_copper_is_advertising_all(tp, + tp->link_config.advertising)) current_link_up = 0; } else { current_link_up = 0; @@ -3654,9 +3663,9 @@ static void tg3_poll_controller(struct net_device *dev) } #endif -static void tg3_reset_task(void *_data) +static void tg3_reset_task(struct work_struct *work) { - struct tg3 *tp = _data; + struct tg3 *tp = container_of(work, struct tg3, reset_task); unsigned int restart_timer; tg3_full_lock(tp, 0); @@ -3703,8 +3712,9 @@ static void tg3_tx_timeout(struct net_device *dev) { struct tg3 *tp = netdev_priv(dev); - printk(KERN_ERR PFX "%s: transmit timed out, resetting\n", - dev->name); + if (netif_msg_tx_err(tp)) + printk(KERN_ERR PFX "%s: transmit timed out, resetting\n", + dev->name); schedule_work(&tp->reset_task); } @@ -6396,16 +6406,17 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) udelay(40); /* tp->grc_local_ctrl is partially set up during tg3_get_invariants(). - * If TG3_FLAG_EEPROM_WRITE_PROT is set, we should read the + * If TG3_FLG2_IS_NIC is zero, we should read the * register to preserve the GPIO settings for LOMs. The GPIOs, * whether used as inputs or outputs, are set by boot code after * reset. */ - if (tp->tg3_flags & TG3_FLAG_EEPROM_WRITE_PROT) { + if (!(tp->tg3_flags2 & TG3_FLG2_IS_NIC)) { u32 gpio_mask; - gpio_mask = GRC_LCLCTRL_GPIO_OE0 | GRC_LCLCTRL_GPIO_OE2 | - GRC_LCLCTRL_GPIO_OUTPUT0 | GRC_LCLCTRL_GPIO_OUTPUT2; + gpio_mask = GRC_LCLCTRL_GPIO_OE0 | GRC_LCLCTRL_GPIO_OE1 | + GRC_LCLCTRL_GPIO_OE2 | GRC_LCLCTRL_GPIO_OUTPUT0 | + GRC_LCLCTRL_GPIO_OUTPUT1 | GRC_LCLCTRL_GPIO_OUTPUT2; if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752) gpio_mask |= GRC_LCLCTRL_GPIO_OE3 | @@ -6417,8 +6428,9 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tp->grc_local_ctrl |= tr32(GRC_LOCAL_CTRL) & gpio_mask; /* GPIO1 must be driven high for eeprom write protect */ - tp->grc_local_ctrl |= (GRC_LCLCTRL_GPIO_OE1 | - GRC_LCLCTRL_GPIO_OUTPUT1); + if (tp->tg3_flags & TG3_FLAG_EEPROM_WRITE_PROT) + tp->grc_local_ctrl |= (GRC_LCLCTRL_GPIO_OE1 | + GRC_LCLCTRL_GPIO_OUTPUT1); } tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl); udelay(100); @@ -8656,7 +8668,9 @@ static int tg3_test_registers(struct tg3 *tp) return 0; out: - printk(KERN_ERR PFX "Register test failed at offset %x\n", offset); + if (netif_msg_hw(tp)) + printk(KERN_ERR PFX "Register test failed at offset %x\n", + offset); tw32(offset, save_val); return -EIO; } @@ -8781,17 +8795,20 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode) tg3_writephy(tp, 0x10, phy & ~0x4000); tg3_writephy(tp, MII_TG3_EPHY_TEST, phytest); } - } - val = BMCR_LOOPBACK | BMCR_FULLDPLX; - if (tp->tg3_flags & TG3_FLAG_10_100_ONLY) - val |= BMCR_SPEED100; - else - val |= BMCR_SPEED1000; + val = BMCR_LOOPBACK | BMCR_FULLDPLX | BMCR_SPEED100; + } else + val = BMCR_LOOPBACK | BMCR_FULLDPLX | BMCR_SPEED1000; tg3_writephy(tp, MII_BMCR, val); udelay(40); - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) + + mac_mode = (tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK) | + MAC_MODE_LINK_POLARITY; + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { tg3_writephy(tp, MII_TG3_EPHY_PTEST, 0x1800); + mac_mode |= MAC_MODE_PORT_MODE_MII; + } else + mac_mode |= MAC_MODE_PORT_MODE_GMII; /* reset to prevent losing 1st rx packet intermittently */ if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES) { @@ -8799,12 +8816,6 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode) udelay(10); tw32_f(MAC_RX_MODE, tp->rx_mode); } - mac_mode = (tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK) | - MAC_MODE_LINK_POLARITY; - if (tp->tg3_flags & TG3_FLAG_10_100_ONLY) - mac_mode |= MAC_MODE_PORT_MODE_MII; - else - mac_mode |= MAC_MODE_PORT_MODE_GMII; if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401) { mac_mode &= ~MAC_MODE_LINK_POLARITY; tg3_writephy(tp, MII_TG3_EXT_CTRL, @@ -9456,16 +9467,12 @@ static void __devinit tg3_get_5906_nvram_info(struct tg3 *tp) /* Chips other than 5700/5701 use the NVRAM for fetching info. */ static void __devinit tg3_nvram_init(struct tg3 *tp) { - int j; - tw32_f(GRC_EEPROM_ADDR, (EEPROM_ADDR_FSM_RESET | (EEPROM_DEFAULT_CLOCK_PERIOD << EEPROM_ADDR_CLKPERD_SHIFT))); - /* XXX schedule_timeout() ... */ - for (j = 0; j < 100; j++) - udelay(10); + msleep(1); /* Enable seeprom accesses. */ tw32_f(GRC_LOCAL_CTRL, @@ -9526,12 +9533,12 @@ static int tg3_nvram_read_using_eeprom(struct tg3 *tp, EEPROM_ADDR_ADDR_MASK) | EEPROM_ADDR_READ | EEPROM_ADDR_START); - for (i = 0; i < 10000; i++) { + for (i = 0; i < 1000; i++) { tmp = tr32(GRC_EEPROM_ADDR); if (tmp & EEPROM_ADDR_COMPLETE) break; - udelay(100); + msleep(1); } if (!(tmp & EEPROM_ADDR_COMPLETE)) return -EBUSY; @@ -9656,12 +9663,12 @@ static int tg3_nvram_write_block_using_eeprom(struct tg3 *tp, EEPROM_ADDR_START | EEPROM_ADDR_WRITE); - for (j = 0; j < 10000; j++) { + for (j = 0; j < 1000; j++) { val = tr32(GRC_EEPROM_ADDR); if (val & EEPROM_ADDR_COMPLETE) break; - udelay(100); + msleep(1); } if (!(val & EEPROM_ADDR_COMPLETE)) { rc = -EBUSY; @@ -9965,8 +9972,10 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp) tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT; if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { - if (!(tr32(PCIE_TRANSACTION_CFG) & PCIE_TRANS_CFG_LOM)) + if (!(tr32(PCIE_TRANSACTION_CFG) & PCIE_TRANS_CFG_LOM)) { tp->tg3_flags &= ~TG3_FLAG_EEPROM_WRITE_PROT; + tp->tg3_flags2 |= TG3_FLG2_IS_NIC; + } return; } @@ -10066,10 +10075,17 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp) tp->pdev->subsystem_vendor == PCI_VENDOR_ID_DELL) tp->led_ctrl = LED_CTRL_MODE_PHY_2; - if (nic_cfg & NIC_SRAM_DATA_CFG_EEPROM_WP) + if (nic_cfg & NIC_SRAM_DATA_CFG_EEPROM_WP) { tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT; - else + if ((tp->pdev->subsystem_vendor == + PCI_VENDOR_ID_ARIMA) && + (tp->pdev->subsystem_device == 0x205a || + tp->pdev->subsystem_device == 0x2063)) + tp->tg3_flags &= ~TG3_FLAG_EEPROM_WRITE_PROT; + } else { tp->tg3_flags &= ~TG3_FLAG_EEPROM_WRITE_PROT; + tp->tg3_flags2 |= TG3_FLG2_IS_NIC; + } if (nic_cfg & NIC_SRAM_DATA_CFG_ASF_ENABLE) { tp->tg3_flags |= TG3_FLAG_ENABLE_ASF; @@ -10147,7 +10163,7 @@ static int __devinit tg3_phy_probe(struct tg3 *tp) if (!(tp->tg3_flags2 & TG3_FLG2_ANY_SERDES) && !(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) { - u32 bmsr, adv_reg, tg3_ctrl; + u32 bmsr, adv_reg, tg3_ctrl, mask; tg3_readphy(tp, MII_BMSR, &bmsr); if (!tg3_readphy(tp, MII_BMSR, &bmsr) && @@ -10171,7 +10187,10 @@ static int __devinit tg3_phy_probe(struct tg3 *tp) MII_TG3_CTRL_ENABLE_AS_MASTER); } - if (!tg3_copper_is_advertising_all(tp)) { + mask = (ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | + ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full | + ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full); + if (!tg3_copper_is_advertising_all(tp, mask)) { tg3_writephy(tp, MII_ADVERTISE, adv_reg); if (!(tp->tg3_flags & TG3_FLAG_10_100_ONLY)) @@ -10695,7 +10714,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tp->tg3_flags |= TG3_FLAG_SRAM_USE_CONFIG; /* Get eeprom hw config before calling tg3_set_power_state(). - * In particular, the TG3_FLAG_EEPROM_WRITE_PROT flag must be + * In particular, the TG3_FLG2_IS_NIC flag must be * determined before calling tg3_set_power_state() so that * we know whether or not to switch out of Vaux power. * When the flag is set, it means that GPIO1 is used for eeprom @@ -10862,7 +10881,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tp->pdev->device == PCI_DEVICE_ID_TIGON3_5705F)) || (tp->pdev->vendor == PCI_VENDOR_ID_BROADCOM && (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5751F || - tp->pdev->device == PCI_DEVICE_ID_TIGON3_5753F)) || + tp->pdev->device == PCI_DEVICE_ID_TIGON3_5753F || + tp->pdev->device == PCI_DEVICE_ID_TIGON3_5787F)) || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) tp->tg3_flags |= TG3_FLAG_10_100_ONLY; @@ -11734,7 +11754,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, #endif spin_lock_init(&tp->lock); spin_lock_init(&tp->indirect_lock); - INIT_WORK(&tp->reset_task, tg3_reset_task, tp); + INIT_WORK(&tp->reset_task, tg3_reset_task); tp->regs = ioremap_nocache(tg3reg_base, tg3reg_len); if (tp->regs == 0UL) { @@ -11912,13 +11932,15 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, pci_set_drvdata(pdev, dev); - printk(KERN_INFO "%s: Tigon3 [partno(%s) rev %04x PHY(%s)] (%s) %sBaseT Ethernet ", + printk(KERN_INFO "%s: Tigon3 [partno(%s) rev %04x PHY(%s)] (%s) %s Ethernet ", dev->name, tp->board_part_number, tp->pci_chip_rev_id, tg3_phy_string(tp), tg3_bus_string(tp, str), - (tp->tg3_flags & TG3_FLAG_10_100_ONLY) ? "10/100" : "10/100/1000"); + ((tp->tg3_flags & TG3_FLAG_10_100_ONLY) ? "10/100Base-TX" : + ((tp->tg3_flags2 & TG3_FLG2_ANY_SERDES) ? "1000Base-SX" : + "10/100/1000Base-T"))); for (i = 0; i < 6; i++) printk("%2.2x%c", dev->dev_addr[i], diff --git a/trunk/drivers/net/tg3.h b/trunk/drivers/net/tg3.h index 92f53000bce6..dfaf4ed127bd 100644 --- a/trunk/drivers/net/tg3.h +++ b/trunk/drivers/net/tg3.h @@ -2233,6 +2233,7 @@ struct tg3 { #define TG3_FLG2_PCI_EXPRESS 0x00000200 #define TG3_FLG2_ASF_NEW_HANDSHAKE 0x00000400 #define TG3_FLG2_HW_AUTONEG 0x00000800 +#define TG3_FLG2_IS_NIC 0x00001000 #define TG3_FLG2_PHY_SERDES 0x00002000 #define TG3_FLG2_CAPACITIVE_COUPLING 0x00004000 #define TG3_FLG2_FLASH 0x00008000 diff --git a/trunk/drivers/net/tlan.c b/trunk/drivers/net/tlan.c index e14f5a00f65a..f85f00251123 100644 --- a/trunk/drivers/net/tlan.c +++ b/trunk/drivers/net/tlan.c @@ -296,6 +296,7 @@ static void TLan_SetMulticastList( struct net_device *); static int TLan_ioctl( struct net_device *dev, struct ifreq *rq, int cmd); static int TLan_probe1( struct pci_dev *pdev, long ioaddr, int irq, int rev, const struct pci_device_id *ent); static void TLan_tx_timeout( struct net_device *dev); +static void TLan_tx_timeout_work(struct work_struct *work); static int tlan_init_one( struct pci_dev *pdev, const struct pci_device_id *ent); static u32 TLan_HandleInvalid( struct net_device *, u16 ); @@ -562,6 +563,7 @@ static int __devinit TLan_probe1(struct pci_dev *pdev, priv = netdev_priv(dev); priv->pciDev = pdev; + priv->dev = dev; /* Is this a PCI device? */ if (pdev) { @@ -634,7 +636,7 @@ static int __devinit TLan_probe1(struct pci_dev *pdev, /* This will be used when we get an adapter error from * within our irq handler */ - INIT_WORK(&priv->tlan_tqueue, (void *)(void*)TLan_tx_timeout, dev); + INIT_WORK(&priv->tlan_tqueue, TLan_tx_timeout_work); spin_lock_init(&priv->lock); @@ -1040,6 +1042,25 @@ static void TLan_tx_timeout(struct net_device *dev) } + /*************************************************************** + * TLan_tx_timeout_work + * + * Returns: nothing + * + * Params: + * work work item of device which timed out + * + **************************************************************/ + +static void TLan_tx_timeout_work(struct work_struct *work) +{ + TLanPrivateInfo *priv = + container_of(work, TLanPrivateInfo, tlan_tqueue); + + TLan_tx_timeout(priv->dev); +} + + /*************************************************************** * TLan_StartTx diff --git a/trunk/drivers/net/tlan.h b/trunk/drivers/net/tlan.h index a44e2f2ef62a..41ce0b665937 100644 --- a/trunk/drivers/net/tlan.h +++ b/trunk/drivers/net/tlan.h @@ -170,6 +170,7 @@ typedef u8 TLanBuffer[TLAN_MAX_FRAME_SIZE]; typedef struct tlan_private_tag { struct net_device *nextDevice; struct pci_dev *pciDev; + struct net_device *dev; void *dmaStorage; dma_addr_t dmaStorageDMA; unsigned int dmaSize; diff --git a/trunk/drivers/net/tokenring/smctr.c b/trunk/drivers/net/tokenring/smctr.c index 46dabdb12071..cec282a6f62d 100644 --- a/trunk/drivers/net/tokenring/smctr.c +++ b/trunk/drivers/net/tokenring/smctr.c @@ -5706,7 +5706,7 @@ int __init init_module(void) return found ? 0 : -ENODEV; } -void cleanup_module(void) +void __exit cleanup_module(void) { int i; diff --git a/trunk/drivers/net/tulip/21142.c b/trunk/drivers/net/tulip/21142.c index fa3a2bb105ad..942b839ccc5b 100644 --- a/trunk/drivers/net/tulip/21142.c +++ b/trunk/drivers/net/tulip/21142.c @@ -26,10 +26,11 @@ static u16 t21142_csr15[] = { 0x0008, 0x0006, 0x000E, 0x0008, 0x0008, }; /* Handle the 21143 uniquely: do autoselect with NWay, not the EEPROM list of available transceivers. */ -void t21142_media_task(void *data) +void t21142_media_task(struct work_struct *work) { - struct net_device *dev = data; - struct tulip_private *tp = netdev_priv(dev); + struct tulip_private *tp = + container_of(work, struct tulip_private, media_work); + struct net_device *dev = tp->dev; void __iomem *ioaddr = tp->base_addr; int csr12 = ioread32(ioaddr + CSR12); int next_tick = 60*HZ; diff --git a/trunk/drivers/net/tulip/timer.c b/trunk/drivers/net/tulip/timer.c index 066e5d6bcbd8..df326fe1cc8f 100644 --- a/trunk/drivers/net/tulip/timer.c +++ b/trunk/drivers/net/tulip/timer.c @@ -18,10 +18,11 @@ #include "tulip.h" -void tulip_media_task(void *data) +void tulip_media_task(struct work_struct *work) { - struct net_device *dev = data; - struct tulip_private *tp = netdev_priv(dev); + struct tulip_private *tp = + container_of(work, struct tulip_private, media_work); + struct net_device *dev = tp->dev; void __iomem *ioaddr = tp->base_addr; u32 csr12 = ioread32(ioaddr + CSR12); int next_tick = 2*HZ; diff --git a/trunk/drivers/net/tulip/tulip.h b/trunk/drivers/net/tulip/tulip.h index ad107f45c7b1..25f25da76917 100644 --- a/trunk/drivers/net/tulip/tulip.h +++ b/trunk/drivers/net/tulip/tulip.h @@ -44,7 +44,7 @@ struct tulip_chip_table { int valid_intrs; /* CSR7 interrupt enable settings */ int flags; void (*media_timer) (unsigned long); - void (*media_task) (void *); + work_func_t media_task; }; @@ -392,6 +392,7 @@ struct tulip_private { int csr12_shadow; int pad0; /* Used for 8-byte alignment */ struct work_struct media_work; + struct net_device *dev; }; @@ -406,7 +407,7 @@ struct eeprom_fixup { /* 21142.c */ extern u16 t21142_csr14[]; -void t21142_media_task(void *data); +void t21142_media_task(struct work_struct *work); void t21142_start_nway(struct net_device *dev); void t21142_lnk_change(struct net_device *dev, int csr5); @@ -444,7 +445,7 @@ void pnic_lnk_change(struct net_device *dev, int csr5); void pnic_timer(unsigned long data); /* timer.c */ -void tulip_media_task(void *data); +void tulip_media_task(struct work_struct *work); void mxic_timer(unsigned long data); void comet_timer(unsigned long data); diff --git a/trunk/drivers/net/tulip/tulip_core.c b/trunk/drivers/net/tulip/tulip_core.c index 0aee618f883c..5a35354aa523 100644 --- a/trunk/drivers/net/tulip/tulip_core.c +++ b/trunk/drivers/net/tulip/tulip_core.c @@ -1367,6 +1367,7 @@ static int __devinit tulip_init_one (struct pci_dev *pdev, * it is zeroed and aligned in alloc_etherdev */ tp = netdev_priv(dev); + tp->dev = dev; tp->rx_ring = pci_alloc_consistent(pdev, sizeof(struct tulip_rx_desc) * RX_RING_SIZE + @@ -1389,7 +1390,7 @@ static int __devinit tulip_init_one (struct pci_dev *pdev, tp->timer.data = (unsigned long)dev; tp->timer.function = tulip_tbl[tp->chip_id].media_timer; - INIT_WORK(&tp->media_work, tulip_tbl[tp->chip_id].media_task, dev); + INIT_WORK(&tp->media_work, tulip_tbl[tp->chip_id].media_task); dev->base_addr = (unsigned long)ioaddr; diff --git a/trunk/drivers/net/via-velocity.c b/trunk/drivers/net/via-velocity.c index 74f894795a1b..4587f23f4e4b 100644 --- a/trunk/drivers/net/via-velocity.c +++ b/trunk/drivers/net/via-velocity.c @@ -3132,7 +3132,7 @@ static u16 wol_calc_crc(int size, u8 * pattern, u8 *mask_pattern) } /* Finally, invert the result once to get the correct data */ crc = ~crc; - return bitreverse(crc) >> 16; + return bitrev32(crc) >> 16; } /** diff --git a/trunk/drivers/net/wan/cosa.c b/trunk/drivers/net/wan/cosa.c index e1bf8b93f958..6c7dfb50143f 100644 --- a/trunk/drivers/net/wan/cosa.c +++ b/trunk/drivers/net/wan/cosa.c @@ -974,12 +974,12 @@ static int cosa_open(struct inode *inode, struct file *file) unsigned long flags; int n; - if ((n=iminor(file->f_dentry->d_inode)>>CARD_MINOR_BITS) + if ((n=iminor(file->f_path.dentry->d_inode)>>CARD_MINOR_BITS) >= nr_cards) return -ENODEV; cosa = cosa_cards+n; - if ((n=iminor(file->f_dentry->d_inode) + if ((n=iminor(file->f_path.dentry->d_inode) & ((1<= cosa->nchannels) return -ENODEV; chan = cosa->chan + n; diff --git a/trunk/drivers/net/wan/pc300_tty.c b/trunk/drivers/net/wan/pc300_tty.c index 931cbdf6d791..b2a23aed4428 100644 --- a/trunk/drivers/net/wan/pc300_tty.c +++ b/trunk/drivers/net/wan/pc300_tty.c @@ -125,8 +125,8 @@ static int cpc_tty_write_room(struct tty_struct *tty); static int cpc_tty_chars_in_buffer(struct tty_struct *tty); static void cpc_tty_flush_buffer(struct tty_struct *tty); static void cpc_tty_hangup(struct tty_struct *tty); -static void cpc_tty_rx_work(void *data); -static void cpc_tty_tx_work(void *data); +static void cpc_tty_rx_work(struct work_struct *work); +static void cpc_tty_tx_work(struct work_struct *work); static int cpc_tty_send_to_card(pc300dev_t *dev,void *buf, int len); static void cpc_tty_trace(pc300dev_t *dev, char* buf, int len, char rxtx); static void cpc_tty_signal_off(pc300dev_t *pc300dev, unsigned char); @@ -261,8 +261,8 @@ void cpc_tty_init(pc300dev_t *pc300dev) cpc_tty->tty_minor = port + CPC_TTY_MINOR_START; cpc_tty->pc300dev = pc300dev; - INIT_WORK(&cpc_tty->tty_tx_work, cpc_tty_tx_work, (void *)cpc_tty); - INIT_WORK(&cpc_tty->tty_rx_work, cpc_tty_rx_work, (void *)port); + INIT_WORK(&cpc_tty->tty_tx_work, cpc_tty_tx_work); + INIT_WORK(&cpc_tty->tty_rx_work, cpc_tty_rx_work); cpc_tty->buf_rx.first = cpc_tty->buf_rx.last = NULL; @@ -659,21 +659,23 @@ static void cpc_tty_hangup(struct tty_struct *tty) * o call the line disc. read * o free memory */ -static void cpc_tty_rx_work(void * data) +static void cpc_tty_rx_work(struct work_struct *work) { + st_cpc_tty_area *cpc_tty; unsigned long port; int i, j; - st_cpc_tty_area *cpc_tty; volatile st_cpc_rx_buf *buf; char flags=0,flg_rx=1; struct tty_ldisc *ld; if (cpc_tty_cnt == 0) return; - for (i=0; (i < 4) && flg_rx ; i++) { flg_rx = 0; - port = (unsigned long)data; + + cpc_tty = container_of(work, st_cpc_tty_area, tty_rx_work); + port = cpc_tty - cpc_tty_area; + for (j=0; j < CPC_TTY_NPORTS; j++) { cpc_tty = &cpc_tty_area[port]; @@ -882,9 +884,10 @@ void cpc_tty_receive(pc300dev_t *pc300dev) * o if need call line discipline wakeup * o call wake_up_interruptible */ -static void cpc_tty_tx_work(void *data) +static void cpc_tty_tx_work(struct work_struct *work) { - st_cpc_tty_area *cpc_tty = (st_cpc_tty_area *) data; + st_cpc_tty_area *cpc_tty = + container_of(work, st_cpc_tty_area, tty_tx_work); struct tty_struct *tty; CPC_TTY_DBG("%s: cpc_tty_tx_work init\n",cpc_tty->name); diff --git a/trunk/drivers/net/wd.c b/trunk/drivers/net/wd.c index 41f1d6778849..7f38012b9c92 100644 --- a/trunk/drivers/net/wd.c +++ b/trunk/drivers/net/wd.c @@ -538,7 +538,7 @@ static void cleanup_card(struct net_device *dev) iounmap(ei_status.mem); } -void +void __exit cleanup_module(void) { int this_dev; diff --git a/trunk/drivers/net/wireless/airo.c b/trunk/drivers/net/wireless/airo.c index efcdaf1c5f73..44a22701da97 100644 --- a/trunk/drivers/net/wireless/airo.c +++ b/trunk/drivers/net/wireless/airo.c @@ -49,6 +49,7 @@ #include #include #include +#include #include "airo.h" diff --git a/trunk/drivers/net/wireless/airo_cs.c b/trunk/drivers/net/wireless/airo_cs.c index ac9437d497f0..f12355398fe7 100644 --- a/trunk/drivers/net/wireless/airo_cs.c +++ b/trunk/drivers/net/wireless/airo_cs.c @@ -219,21 +219,6 @@ static int airo_config(struct pcmcia_device *link) dev = link->priv; DEBUG(0, "airo_config(0x%p)\n", link); - - /* - This reads the card's CONFIG tuple to find its configuration - registers. - */ - tuple.DesiredTuple = CISTPL_CONFIG; - tuple.Attributes = 0; - tuple.TupleData = buf; - tuple.TupleDataMax = sizeof(buf); - tuple.TupleOffset = 0; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); - link->conf.ConfigBase = parse.config.base; - link->conf.Present = parse.config.rmask[0]; /* In this loop, we scan the CIS for configuration table entries, @@ -247,6 +232,10 @@ static int airo_config(struct pcmcia_device *link) these things without consulting the CIS, and most client drivers will only use the CIS to fill in implementation-defined details. */ + tuple.Attributes = 0; + tuple.TupleData = buf; + tuple.TupleDataMax = sizeof(buf); + tuple.TupleOffset = 0; tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); while (1) { diff --git a/trunk/drivers/net/wireless/atmel_cs.c b/trunk/drivers/net/wireless/atmel_cs.c index 5c410989c4d7..12617cd0b78e 100644 --- a/trunk/drivers/net/wireless/atmel_cs.c +++ b/trunk/drivers/net/wireless/atmel_cs.c @@ -243,17 +243,6 @@ static int atmel_config(struct pcmcia_device *link) tuple.TupleDataMax = sizeof(buf); tuple.TupleOffset = 0; - /* - This reads the card's CONFIG tuple to find its configuration - registers. - */ - tuple.DesiredTuple = CISTPL_CONFIG; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); - link->conf.ConfigBase = parse.config.base; - link->conf.Present = parse.config.rmask[0]; - /* In this loop, we scan the CIS for configuration table entries, each of which describes a valid card configuration, including diff --git a/trunk/drivers/net/wireless/bcm43xx/bcm43xx.h b/trunk/drivers/net/wireless/bcm43xx/bcm43xx.h index 94dfb92fab5c..8286678513b9 100644 --- a/trunk/drivers/net/wireless/bcm43xx/bcm43xx.h +++ b/trunk/drivers/net/wireless/bcm43xx/bcm43xx.h @@ -819,7 +819,7 @@ struct bcm43xx_private { struct tasklet_struct isr_tasklet; /* Periodic tasks */ - struct work_struct periodic_work; + struct delayed_work periodic_work; unsigned int periodic_state; struct work_struct restart_work; diff --git a/trunk/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/trunk/drivers/net/wireless/bcm43xx/bcm43xx_main.c index 5b3c27359a18..2ec2e5afce67 100644 --- a/trunk/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/trunk/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -3215,9 +3215,10 @@ static void do_periodic_work(struct bcm43xx_private *bcm) schedule_delayed_work(&bcm->periodic_work, HZ * 15); } -static void bcm43xx_periodic_work_handler(void *d) +static void bcm43xx_periodic_work_handler(struct work_struct *work) { - struct bcm43xx_private *bcm = d; + struct bcm43xx_private *bcm = + container_of(work, struct bcm43xx_private, periodic_work.work); struct net_device *net_dev = bcm->net_dev; unsigned long flags; u32 savedirqs = 0; @@ -3279,11 +3280,11 @@ void bcm43xx_periodic_tasks_delete(struct bcm43xx_private *bcm) void bcm43xx_periodic_tasks_setup(struct bcm43xx_private *bcm) { - struct work_struct *work = &(bcm->periodic_work); + struct delayed_work *work = &bcm->periodic_work; assert(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED); - INIT_WORK(work, bcm43xx_periodic_work_handler, bcm); - schedule_work(work); + INIT_DELAYED_WORK(work, bcm43xx_periodic_work_handler); + schedule_delayed_work(work, 0); } static void bcm43xx_security_init(struct bcm43xx_private *bcm) @@ -3635,7 +3636,7 @@ static int bcm43xx_init_board(struct bcm43xx_private *bcm) bcm43xx_periodic_tasks_setup(bcm); /*FIXME: This should be handled by softmac instead. */ - schedule_work(&bcm->softmac->associnfo.work); + schedule_delayed_work(&bcm->softmac->associnfo.work, 0); out: mutex_unlock(&(bcm)->mutex); @@ -4182,9 +4183,10 @@ static void __devexit bcm43xx_remove_one(struct pci_dev *pdev) /* Hard-reset the chip. Do not call this directly. * Use bcm43xx_controller_restart() */ -static void bcm43xx_chip_reset(void *_bcm) +static void bcm43xx_chip_reset(struct work_struct *work) { - struct bcm43xx_private *bcm = _bcm; + struct bcm43xx_private *bcm = + container_of(work, struct bcm43xx_private, restart_work); struct bcm43xx_phyinfo *phy; int err = -ENODEV; @@ -4211,7 +4213,7 @@ void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason) if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) return; printk(KERN_ERR PFX "Controller RESET (%s) ...\n", reason); - INIT_WORK(&bcm->restart_work, bcm43xx_chip_reset, bcm); + INIT_WORK(&bcm->restart_work, bcm43xx_chip_reset); schedule_work(&bcm->restart_work); } diff --git a/trunk/drivers/net/wireless/hostap/hostap.h b/trunk/drivers/net/wireless/hostap/hostap.h index e663518bd570..e89c890d16fd 100644 --- a/trunk/drivers/net/wireless/hostap/hostap.h +++ b/trunk/drivers/net/wireless/hostap/hostap.h @@ -35,7 +35,7 @@ int hostap_80211_get_hdrlen(u16 fc); struct net_device_stats *hostap_get_stats(struct net_device *dev); void hostap_setup_dev(struct net_device *dev, local_info_t *local, int main_dev); -void hostap_set_multicast_list_queue(void *data); +void hostap_set_multicast_list_queue(struct work_struct *work); int hostap_set_hostapd(local_info_t *local, int val, int rtnl_locked); int hostap_set_hostapd_sta(local_info_t *local, int val, int rtnl_locked); void hostap_cleanup(local_info_t *local); diff --git a/trunk/drivers/net/wireless/hostap/hostap_ap.c b/trunk/drivers/net/wireless/hostap/hostap_ap.c index ba13125024cb..974a8e5bec8b 100644 --- a/trunk/drivers/net/wireless/hostap/hostap_ap.c +++ b/trunk/drivers/net/wireless/hostap/hostap_ap.c @@ -49,10 +49,10 @@ MODULE_PARM_DESC(autom_ap_wds, "Add WDS connections to other APs " static struct sta_info* ap_get_sta(struct ap_data *ap, u8 *sta); static void hostap_event_expired_sta(struct net_device *dev, struct sta_info *sta); -static void handle_add_proc_queue(void *data); +static void handle_add_proc_queue(struct work_struct *work); #ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT -static void handle_wds_oper_queue(void *data); +static void handle_wds_oper_queue(struct work_struct *work); static void prism2_send_mgmt(struct net_device *dev, u16 type_subtype, char *body, int body_len, u8 *addr, u16 tx_cb_idx); @@ -807,7 +807,7 @@ void hostap_init_data(local_info_t *local) INIT_LIST_HEAD(&ap->sta_list); /* Initialize task queue structure for AP management */ - INIT_WORK(&local->ap->add_sta_proc_queue, handle_add_proc_queue, ap); + INIT_WORK(&local->ap->add_sta_proc_queue, handle_add_proc_queue); ap->tx_callback_idx = hostap_tx_callback_register(local, hostap_ap_tx_cb, ap); @@ -815,7 +815,7 @@ void hostap_init_data(local_info_t *local) printk(KERN_WARNING "%s: failed to register TX callback for " "AP\n", local->dev->name); #ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT - INIT_WORK(&local->ap->wds_oper_queue, handle_wds_oper_queue, local); + INIT_WORK(&local->ap->wds_oper_queue, handle_wds_oper_queue); ap->tx_callback_auth = hostap_tx_callback_register(local, hostap_ap_tx_cb_auth, ap); @@ -1062,9 +1062,10 @@ static int prism2_sta_proc_read(char *page, char **start, off_t off, } -static void handle_add_proc_queue(void *data) +static void handle_add_proc_queue(struct work_struct *work) { - struct ap_data *ap = (struct ap_data *) data; + struct ap_data *ap = container_of(work, struct ap_data, + add_sta_proc_queue); struct sta_info *sta; char name[20]; struct add_sta_proc_data *entry, *prev; @@ -1099,15 +1100,13 @@ static struct sta_info * ap_add_sta(struct ap_data *ap, u8 *addr) { struct sta_info *sta; - sta = (struct sta_info *) - kmalloc(sizeof(struct sta_info), GFP_ATOMIC); + sta = kzalloc(sizeof(struct sta_info), GFP_ATOMIC); if (sta == NULL) { PDEBUG(DEBUG_AP, "AP: kmalloc failed\n"); return NULL; } /* initialize STA info data */ - memset(sta, 0, sizeof(struct sta_info)); sta->local = ap->local; skb_queue_head_init(&sta->tx_buf); memcpy(sta->addr, addr, ETH_ALEN); @@ -1952,9 +1951,11 @@ static void handle_pspoll(local_info_t *local, #ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT -static void handle_wds_oper_queue(void *data) +static void handle_wds_oper_queue(struct work_struct *work) { - local_info_t *local = data; + struct ap_data *ap = container_of(work, struct ap_data, + wds_oper_queue); + local_info_t *local = ap->local; struct wds_oper_data *entry, *prev; spin_lock_bh(&local->lock); diff --git a/trunk/drivers/net/wireless/hostap/hostap_cs.c b/trunk/drivers/net/wireless/hostap/hostap_cs.c index f63909e4bc32..8d8f4b9b8b07 100644 --- a/trunk/drivers/net/wireless/hostap/hostap_cs.c +++ b/trunk/drivers/net/wireless/hostap/hostap_cs.c @@ -293,15 +293,12 @@ static int sandisk_enable_wireless(struct net_device *dev) goto done; } - tuple.DesiredTuple = CISTPL_MANFID; tuple.Attributes = TUPLE_RETURN_COMMON; tuple.TupleData = buf; tuple.TupleDataMax = sizeof(buf); tuple.TupleOffset = 0; - if (pcmcia_get_first_tuple(hw_priv->link, &tuple) || - pcmcia_get_tuple_data(hw_priv->link, &tuple) || - pcmcia_parse_tuple(hw_priv->link, &tuple, parse) || - parse->manfid.manf != 0xd601 || parse->manfid.card != 0x0101) { + + if (hw_priv->link->manf_id != 0xd601 || hw_priv->link->card_id != 0x0101) { /* No SanDisk manfid found */ ret = -ENODEV; goto done; @@ -566,23 +563,16 @@ static int prism2_config(struct pcmcia_device *link) PDEBUG(DEBUG_FLOW, "prism2_config()\n"); parse = kmalloc(sizeof(cisparse_t), GFP_KERNEL); - hw_priv = kmalloc(sizeof(*hw_priv), GFP_KERNEL); + hw_priv = kzalloc(sizeof(*hw_priv), GFP_KERNEL); if (parse == NULL || hw_priv == NULL) { ret = -ENOMEM; goto failed; } - memset(hw_priv, 0, sizeof(*hw_priv)); - tuple.DesiredTuple = CISTPL_CONFIG; tuple.Attributes = 0; tuple.TupleData = buf; tuple.TupleDataMax = sizeof(buf); tuple.TupleOffset = 0; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, parse)); - link->conf.ConfigBase = parse->config.base; - link->conf.Present = parse->config.rmask[0]; CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &conf)); diff --git a/trunk/drivers/net/wireless/hostap/hostap_download.c b/trunk/drivers/net/wireless/hostap/hostap_download.c index ab26b52b3e76..24fc387bba67 100644 --- a/trunk/drivers/net/wireless/hostap/hostap_download.c +++ b/trunk/drivers/net/wireless/hostap/hostap_download.c @@ -685,14 +685,12 @@ static int prism2_download(local_info_t *local, goto out; } - dl = kmalloc(sizeof(*dl) + param->num_areas * + dl = kzalloc(sizeof(*dl) + param->num_areas * sizeof(struct prism2_download_data_area), GFP_KERNEL); if (dl == NULL) { ret = -ENOMEM; goto out; } - memset(dl, 0, sizeof(*dl) + param->num_areas * - sizeof(struct prism2_download_data_area)); dl->dl_cmd = param->dl_cmd; dl->start_addr = param->start_addr; dl->num_areas = param->num_areas; diff --git a/trunk/drivers/net/wireless/hostap/hostap_hw.c b/trunk/drivers/net/wireless/hostap/hostap_hw.c index ed00ebb6e7f4..a394a23b9a20 100644 --- a/trunk/drivers/net/wireless/hostap/hostap_hw.c +++ b/trunk/drivers/net/wireless/hostap/hostap_hw.c @@ -347,14 +347,12 @@ static int hfa384x_cmd(struct net_device *dev, u16 cmd, u16 param0, if (signal_pending(current)) return -EINTR; - entry = (struct hostap_cmd_queue *) - kmalloc(sizeof(*entry), GFP_ATOMIC); + entry = kzalloc(sizeof(*entry), GFP_ATOMIC); if (entry == NULL) { printk(KERN_DEBUG "%s: hfa384x_cmd - kmalloc failed\n", dev->name); return -ENOMEM; } - memset(entry, 0, sizeof(*entry)); atomic_set(&entry->usecnt, 1); entry->type = CMD_SLEEP; entry->cmd = cmd; @@ -517,14 +515,12 @@ static int hfa384x_cmd_callback(struct net_device *dev, u16 cmd, u16 param0, return -1; } - entry = (struct hostap_cmd_queue *) - kmalloc(sizeof(*entry), GFP_ATOMIC); + entry = kzalloc(sizeof(*entry), GFP_ATOMIC); if (entry == NULL) { printk(KERN_DEBUG "%s: hfa384x_cmd_callback - kmalloc " "failed\n", dev->name); return -ENOMEM; } - memset(entry, 0, sizeof(*entry)); atomic_set(&entry->usecnt, 1); entry->type = CMD_CALLBACK; entry->cmd = cmd; @@ -1645,9 +1641,9 @@ static void prism2_schedule_reset(local_info_t *local) /* Called only as scheduled task after noticing card timeout in interrupt * context */ -static void handle_reset_queue(void *data) +static void handle_reset_queue(struct work_struct *work) { - local_info_t *local = (local_info_t *) data; + local_info_t *local = container_of(work, local_info_t, reset_queue); printk(KERN_DEBUG "%s: scheduled card reset\n", local->dev->name); prism2_hw_reset(local->dev); @@ -2896,9 +2892,10 @@ static void hostap_passive_scan(unsigned long data) /* Called only as a scheduled task when communications quality values should * be updated. */ -static void handle_comms_qual_update(void *data) +static void handle_comms_qual_update(struct work_struct *work) { - local_info_t *local = data; + local_info_t *local = + container_of(work, local_info_t, comms_qual_update); prism2_update_comms_qual(local->dev); } @@ -3015,14 +3012,12 @@ static int prism2_set_tim(struct net_device *dev, int aid, int set) iface = netdev_priv(dev); local = iface->local; - new_entry = (struct set_tim_data *) - kmalloc(sizeof(*new_entry), GFP_ATOMIC); + new_entry = kzalloc(sizeof(*new_entry), GFP_ATOMIC); if (new_entry == NULL) { printk(KERN_DEBUG "%s: prism2_set_tim: kmalloc failed\n", local->dev->name); return -ENOMEM; } - memset(new_entry, 0, sizeof(*new_entry)); new_entry->aid = aid; new_entry->set = set; @@ -3050,9 +3045,9 @@ static int prism2_set_tim(struct net_device *dev, int aid, int set) } -static void handle_set_tim_queue(void *data) +static void handle_set_tim_queue(struct work_struct *work) { - local_info_t *local = (local_info_t *) data; + local_info_t *local = container_of(work, local_info_t, set_tim_queue); struct set_tim_data *entry; u16 val; @@ -3209,15 +3204,15 @@ prism2_init_local_data(struct prism2_helper_functions *funcs, int card_idx, local->scan_channel_mask = 0xffff; /* Initialize task queue structures */ - INIT_WORK(&local->reset_queue, handle_reset_queue, local); + INIT_WORK(&local->reset_queue, handle_reset_queue); INIT_WORK(&local->set_multicast_list_queue, - hostap_set_multicast_list_queue, local->dev); + hostap_set_multicast_list_queue); - INIT_WORK(&local->set_tim_queue, handle_set_tim_queue, local); + INIT_WORK(&local->set_tim_queue, handle_set_tim_queue); INIT_LIST_HEAD(&local->set_tim_list); spin_lock_init(&local->set_tim_lock); - INIT_WORK(&local->comms_qual_update, handle_comms_qual_update, local); + INIT_WORK(&local->comms_qual_update, handle_comms_qual_update); /* Initialize tasklets for handling hardware IRQ related operations * outside hw IRQ handler */ diff --git a/trunk/drivers/net/wireless/hostap/hostap_info.c b/trunk/drivers/net/wireless/hostap/hostap_info.c index 50f72d831cf4..b6a02a02da74 100644 --- a/trunk/drivers/net/wireless/hostap/hostap_info.c +++ b/trunk/drivers/net/wireless/hostap/hostap_info.c @@ -327,11 +327,10 @@ static void prism2_info_hostscanresults(local_info_t *local, ptr = (u8 *) pos; new_count = left / result_size; - results = kmalloc(new_count * sizeof(struct hfa384x_hostscan_result), + results = kcalloc(new_count, sizeof(struct hfa384x_hostscan_result), GFP_ATOMIC); if (results == NULL) return; - memset(results, 0, new_count * sizeof(struct hfa384x_hostscan_result)); for (i = 0; i < new_count; i++) { memcpy(&results[i], ptr, copy_len); @@ -474,9 +473,9 @@ static void handle_info_queue_scanresults(local_info_t *local) /* Called only as scheduled task after receiving info frames (used to avoid * pending too much time in HW IRQ handler). */ -static void handle_info_queue(void *data) +static void handle_info_queue(struct work_struct *work) { - local_info_t *local = (local_info_t *) data; + local_info_t *local = container_of(work, local_info_t, info_queue); if (test_and_clear_bit(PRISM2_INFO_PENDING_LINKSTATUS, &local->pending_info)) @@ -493,7 +492,7 @@ void hostap_info_init(local_info_t *local) { skb_queue_head_init(&local->info_list); #ifndef PRISM2_NO_STATION_MODES - INIT_WORK(&local->info_queue, handle_info_queue, local); + INIT_WORK(&local->info_queue, handle_info_queue); #endif /* PRISM2_NO_STATION_MODES */ } diff --git a/trunk/drivers/net/wireless/hostap/hostap_ioctl.c b/trunk/drivers/net/wireless/hostap/hostap_ioctl.c index d061fb3443ff..3b7b8063ff1c 100644 --- a/trunk/drivers/net/wireless/hostap/hostap_ioctl.c +++ b/trunk/drivers/net/wireless/hostap/hostap_ioctl.c @@ -181,12 +181,10 @@ static int prism2_ioctl_siwencode(struct net_device *dev, struct ieee80211_crypt_data *new_crypt; /* take WEP into use */ - new_crypt = (struct ieee80211_crypt_data *) - kmalloc(sizeof(struct ieee80211_crypt_data), + new_crypt = kzalloc(sizeof(struct ieee80211_crypt_data), GFP_KERNEL); if (new_crypt == NULL) return -ENOMEM; - memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data)); new_crypt->ops = ieee80211_get_crypto_ops("WEP"); if (!new_crypt->ops) { request_module("ieee80211_crypt_wep"); @@ -3320,14 +3318,12 @@ static int prism2_ioctl_siwencodeext(struct net_device *dev, prism2_crypt_delayed_deinit(local, crypt); - new_crypt = (struct ieee80211_crypt_data *) - kmalloc(sizeof(struct ieee80211_crypt_data), + new_crypt = kzalloc(sizeof(struct ieee80211_crypt_data), GFP_KERNEL); if (new_crypt == NULL) { ret = -ENOMEM; goto done; } - memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data)); new_crypt->ops = ops; new_crypt->priv = new_crypt->ops->init(i); if (new_crypt->priv == NULL) { @@ -3538,14 +3534,12 @@ static int prism2_ioctl_set_encryption(local_info_t *local, prism2_crypt_delayed_deinit(local, crypt); - new_crypt = (struct ieee80211_crypt_data *) - kmalloc(sizeof(struct ieee80211_crypt_data), + new_crypt = kzalloc(sizeof(struct ieee80211_crypt_data), GFP_KERNEL); if (new_crypt == NULL) { ret = -ENOMEM; goto done; } - memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data)); new_crypt->ops = ops; new_crypt->priv = new_crypt->ops->init(param->u.crypt.idx); if (new_crypt->priv == NULL) { diff --git a/trunk/drivers/net/wireless/hostap/hostap_main.c b/trunk/drivers/net/wireless/hostap/hostap_main.c index 53374fcba77e..0796be9d9e77 100644 --- a/trunk/drivers/net/wireless/hostap/hostap_main.c +++ b/trunk/drivers/net/wireless/hostap/hostap_main.c @@ -767,14 +767,14 @@ static int prism2_set_mac_address(struct net_device *dev, void *p) /* TODO: to be further implemented as soon as Prism2 fully supports * GroupAddresses and correct documentation is available */ -void hostap_set_multicast_list_queue(void *data) +void hostap_set_multicast_list_queue(struct work_struct *work) { - struct net_device *dev = (struct net_device *) data; + local_info_t *local = + container_of(work, local_info_t, set_multicast_list_queue); + struct net_device *dev = local->dev; struct hostap_interface *iface; - local_info_t *local; iface = netdev_priv(dev); - local = iface->local; if (hostap_set_word(dev, HFA384X_RID_PROMISCUOUSMODE, local->is_promisc)) { printk(KERN_INFO "%s: %sabling promiscuous mode failed\n", diff --git a/trunk/drivers/net/wireless/hostap/hostap_pci.c b/trunk/drivers/net/wireless/hostap/hostap_pci.c index d1de9766c831..c4f6020baa9e 100644 --- a/trunk/drivers/net/wireless/hostap/hostap_pci.c +++ b/trunk/drivers/net/wireless/hostap/hostap_pci.c @@ -300,10 +300,9 @@ static int prism2_pci_probe(struct pci_dev *pdev, struct hostap_interface *iface; struct hostap_pci_priv *hw_priv; - hw_priv = kmalloc(sizeof(*hw_priv), GFP_KERNEL); + hw_priv = kzalloc(sizeof(*hw_priv), GFP_KERNEL); if (hw_priv == NULL) return -ENOMEM; - memset(hw_priv, 0, sizeof(*hw_priv)); if (pci_enable_device(pdev)) goto err_out_free; diff --git a/trunk/drivers/net/wireless/hostap/hostap_plx.c b/trunk/drivers/net/wireless/hostap/hostap_plx.c index bc81b13a5a2a..e235e0647897 100644 --- a/trunk/drivers/net/wireless/hostap/hostap_plx.c +++ b/trunk/drivers/net/wireless/hostap/hostap_plx.c @@ -447,10 +447,9 @@ static int prism2_plx_probe(struct pci_dev *pdev, int tmd7160; struct hostap_plx_priv *hw_priv; - hw_priv = kmalloc(sizeof(*hw_priv), GFP_KERNEL); + hw_priv = kzalloc(sizeof(*hw_priv), GFP_KERNEL); if (hw_priv == NULL) return -ENOMEM; - memset(hw_priv, 0, sizeof(*hw_priv)); if (pci_enable_device(pdev)) goto err_out_free; diff --git a/trunk/drivers/net/wireless/ipw2100.c b/trunk/drivers/net/wireless/ipw2100.c index 79607b8b877c..dd9ba4aad7bb 100644 --- a/trunk/drivers/net/wireless/ipw2100.c +++ b/trunk/drivers/net/wireless/ipw2100.c @@ -316,7 +316,7 @@ static void ipw2100_release_firmware(struct ipw2100_priv *priv, struct ipw2100_fw *fw); static int ipw2100_ucode_download(struct ipw2100_priv *priv, struct ipw2100_fw *fw); -static void ipw2100_wx_event_work(struct ipw2100_priv *priv); +static void ipw2100_wx_event_work(struct work_struct *work); static struct iw_statistics *ipw2100_wx_wireless_stats(struct net_device *dev); static struct iw_handler_def ipw2100_wx_handler_def; @@ -679,7 +679,8 @@ static void schedule_reset(struct ipw2100_priv *priv) queue_delayed_work(priv->workqueue, &priv->reset_work, priv->reset_backoff * HZ); else - queue_work(priv->workqueue, &priv->reset_work); + queue_delayed_work(priv->workqueue, &priv->reset_work, + 0); if (priv->reset_backoff < MAX_RESET_BACKOFF) priv->reset_backoff++; @@ -1873,8 +1874,10 @@ static void ipw2100_down(struct ipw2100_priv *priv) netif_stop_queue(priv->net_dev); } -static void ipw2100_reset_adapter(struct ipw2100_priv *priv) +static void ipw2100_reset_adapter(struct work_struct *work) { + struct ipw2100_priv *priv = + container_of(work, struct ipw2100_priv, reset_work.work); unsigned long flags; union iwreq_data wrqu = { .ap_addr = { @@ -2071,9 +2074,9 @@ static void isr_indicate_association_lost(struct ipw2100_priv *priv, u32 status) return; if (priv->status & STATUS_SECURITY_UPDATED) - queue_work(priv->workqueue, &priv->security_work); + queue_delayed_work(priv->workqueue, &priv->security_work, 0); - queue_work(priv->workqueue, &priv->wx_event_work); + queue_delayed_work(priv->workqueue, &priv->wx_event_work, 0); } static void isr_indicate_rf_kill(struct ipw2100_priv *priv, u32 status) @@ -5524,8 +5527,11 @@ static int ipw2100_configure_security(struct ipw2100_priv *priv, int batch_mode) return err; } -static void ipw2100_security_work(struct ipw2100_priv *priv) +static void ipw2100_security_work(struct work_struct *work) { + struct ipw2100_priv *priv = + container_of(work, struct ipw2100_priv, security_work.work); + /* If we happen to have reconnected before we get a chance to * process this, then update the security settings--which causes * a disassociation to occur */ @@ -5748,7 +5754,7 @@ static int ipw2100_set_address(struct net_device *dev, void *p) priv->reset_backoff = 0; mutex_unlock(&priv->action_mutex); - ipw2100_reset_adapter(priv); + ipw2100_reset_adapter(&priv->reset_work.work); return 0; done: @@ -5910,9 +5916,10 @@ static const struct ethtool_ops ipw2100_ethtool_ops = { .get_drvinfo = ipw_ethtool_get_drvinfo, }; -static void ipw2100_hang_check(void *adapter) +static void ipw2100_hang_check(struct work_struct *work) { - struct ipw2100_priv *priv = adapter; + struct ipw2100_priv *priv = + container_of(work, struct ipw2100_priv, hang_check.work); unsigned long flags; u32 rtc = 0xa5a5a5a5; u32 len = sizeof(rtc); @@ -5952,9 +5959,10 @@ static void ipw2100_hang_check(void *adapter) spin_unlock_irqrestore(&priv->low_lock, flags); } -static void ipw2100_rf_kill(void *adapter) +static void ipw2100_rf_kill(struct work_struct *work) { - struct ipw2100_priv *priv = adapter; + struct ipw2100_priv *priv = + container_of(work, struct ipw2100_priv, rf_kill.work); unsigned long flags; spin_lock_irqsave(&priv->low_lock, flags); @@ -6103,14 +6111,11 @@ static struct net_device *ipw2100_alloc_device(struct pci_dev *pci_dev, priv->workqueue = create_workqueue(DRV_NAME); - INIT_WORK(&priv->reset_work, - (void (*)(void *))ipw2100_reset_adapter, priv); - INIT_WORK(&priv->security_work, - (void (*)(void *))ipw2100_security_work, priv); - INIT_WORK(&priv->wx_event_work, - (void (*)(void *))ipw2100_wx_event_work, priv); - INIT_WORK(&priv->hang_check, ipw2100_hang_check, priv); - INIT_WORK(&priv->rf_kill, ipw2100_rf_kill, priv); + INIT_DELAYED_WORK(&priv->reset_work, ipw2100_reset_adapter); + INIT_DELAYED_WORK(&priv->security_work, ipw2100_security_work); + INIT_DELAYED_WORK(&priv->wx_event_work, ipw2100_wx_event_work); + INIT_DELAYED_WORK(&priv->hang_check, ipw2100_hang_check); + INIT_DELAYED_WORK(&priv->rf_kill, ipw2100_rf_kill); tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) ipw2100_irq_tasklet, (unsigned long)priv); @@ -6215,7 +6220,7 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev, /* Allocate and initialize the Tx/Rx queues and lists */ if (ipw2100_queues_allocate(priv)) { printk(KERN_WARNING DRV_NAME - "Error calilng ipw2100_queues_allocate.\n"); + "Error calling ipw2100_queues_allocate.\n"); err = -ENOMEM; goto fail; } @@ -8281,8 +8286,10 @@ static struct iw_handler_def ipw2100_wx_handler_def = { .get_wireless_stats = ipw2100_wx_wireless_stats, }; -static void ipw2100_wx_event_work(struct ipw2100_priv *priv) +static void ipw2100_wx_event_work(struct work_struct *work) { + struct ipw2100_priv *priv = + container_of(work, struct ipw2100_priv, wx_event_work.work); union iwreq_data wrqu; int len = ETH_ALEN; diff --git a/trunk/drivers/net/wireless/ipw2100.h b/trunk/drivers/net/wireless/ipw2100.h index 55b7227198df..de7d384d38af 100644 --- a/trunk/drivers/net/wireless/ipw2100.h +++ b/trunk/drivers/net/wireless/ipw2100.h @@ -583,11 +583,11 @@ struct ipw2100_priv { struct tasklet_struct irq_tasklet; struct workqueue_struct *workqueue; - struct work_struct reset_work; - struct work_struct security_work; - struct work_struct wx_event_work; - struct work_struct hang_check; - struct work_struct rf_kill; + struct delayed_work reset_work; + struct delayed_work security_work; + struct delayed_work wx_event_work; + struct delayed_work hang_check; + struct delayed_work rf_kill; u32 interrupts; int tx_interrupts; diff --git a/trunk/drivers/net/wireless/ipw2200.c b/trunk/drivers/net/wireless/ipw2200.c index c692d01a76ca..22cb3fb7502e 100644 --- a/trunk/drivers/net/wireless/ipw2200.c +++ b/trunk/drivers/net/wireless/ipw2200.c @@ -70,7 +70,7 @@ #define VQ #endif -#define IPW2200_VERSION "1.1.4" VK VD VM VP VR VQ +#define IPW2200_VERSION "1.2.0" VK VD VM VP VR VQ #define DRV_DESCRIPTION "Intel(R) PRO/Wireless 2200/2915 Network Driver" #define DRV_COPYRIGHT "Copyright(c) 2003-2006 Intel Corporation" #define DRV_VERSION IPW2200_VERSION @@ -187,9 +187,9 @@ static struct ipw_rx_queue *ipw_rx_queue_alloc(struct ipw_priv *); static void ipw_rx_queue_free(struct ipw_priv *, struct ipw_rx_queue *); static void ipw_rx_queue_replenish(void *); static int ipw_up(struct ipw_priv *); -static void ipw_bg_up(void *); +static void ipw_bg_up(struct work_struct *work); static void ipw_down(struct ipw_priv *); -static void ipw_bg_down(void *); +static void ipw_bg_down(struct work_struct *work); static int ipw_config(struct ipw_priv *); static int init_supported_rates(struct ipw_priv *priv, struct ipw_supported_rates *prates); @@ -862,11 +862,12 @@ static void ipw_led_link_on(struct ipw_priv *priv) spin_unlock_irqrestore(&priv->lock, flags); } -static void ipw_bg_led_link_on(void *data) +static void ipw_bg_led_link_on(struct work_struct *work) { - struct ipw_priv *priv = data; + struct ipw_priv *priv = + container_of(work, struct ipw_priv, led_link_on.work); mutex_lock(&priv->mutex); - ipw_led_link_on(data); + ipw_led_link_on(priv); mutex_unlock(&priv->mutex); } @@ -906,11 +907,12 @@ static void ipw_led_link_off(struct ipw_priv *priv) spin_unlock_irqrestore(&priv->lock, flags); } -static void ipw_bg_led_link_off(void *data) +static void ipw_bg_led_link_off(struct work_struct *work) { - struct ipw_priv *priv = data; + struct ipw_priv *priv = + container_of(work, struct ipw_priv, led_link_off.work); mutex_lock(&priv->mutex); - ipw_led_link_off(data); + ipw_led_link_off(priv); mutex_unlock(&priv->mutex); } @@ -985,11 +987,12 @@ static void ipw_led_activity_off(struct ipw_priv *priv) spin_unlock_irqrestore(&priv->lock, flags); } -static void ipw_bg_led_activity_off(void *data) +static void ipw_bg_led_activity_off(struct work_struct *work) { - struct ipw_priv *priv = data; + struct ipw_priv *priv = + container_of(work, struct ipw_priv, led_act_off.work); mutex_lock(&priv->mutex); - ipw_led_activity_off(data); + ipw_led_activity_off(priv); mutex_unlock(&priv->mutex); } @@ -2228,11 +2231,12 @@ static void ipw_adapter_restart(void *adapter) } } -static void ipw_bg_adapter_restart(void *data) +static void ipw_bg_adapter_restart(struct work_struct *work) { - struct ipw_priv *priv = data; + struct ipw_priv *priv = + container_of(work, struct ipw_priv, adapter_restart); mutex_lock(&priv->mutex); - ipw_adapter_restart(data); + ipw_adapter_restart(priv); mutex_unlock(&priv->mutex); } @@ -2249,11 +2253,12 @@ static void ipw_scan_check(void *data) } } -static void ipw_bg_scan_check(void *data) +static void ipw_bg_scan_check(struct work_struct *work) { - struct ipw_priv *priv = data; + struct ipw_priv *priv = + container_of(work, struct ipw_priv, scan_check.work); mutex_lock(&priv->mutex); - ipw_scan_check(data); + ipw_scan_check(priv); mutex_unlock(&priv->mutex); } @@ -3831,17 +3836,19 @@ static int ipw_disassociate(void *data) return 1; } -static void ipw_bg_disassociate(void *data) +static void ipw_bg_disassociate(struct work_struct *work) { - struct ipw_priv *priv = data; + struct ipw_priv *priv = + container_of(work, struct ipw_priv, disassociate); mutex_lock(&priv->mutex); - ipw_disassociate(data); + ipw_disassociate(priv); mutex_unlock(&priv->mutex); } -static void ipw_system_config(void *data) +static void ipw_system_config(struct work_struct *work) { - struct ipw_priv *priv = data; + struct ipw_priv *priv = + container_of(work, struct ipw_priv, system_config); #ifdef CONFIG_IPW2200_PROMISCUOUS if (priv->prom_net_dev && netif_running(priv->prom_net_dev)) { @@ -4208,11 +4215,12 @@ static void ipw_gather_stats(struct ipw_priv *priv) IPW_STATS_INTERVAL); } -static void ipw_bg_gather_stats(void *data) +static void ipw_bg_gather_stats(struct work_struct *work) { - struct ipw_priv *priv = data; + struct ipw_priv *priv = + container_of(work, struct ipw_priv, gather_stats.work); mutex_lock(&priv->mutex); - ipw_gather_stats(data); + ipw_gather_stats(priv); mutex_unlock(&priv->mutex); } @@ -4268,8 +4276,8 @@ static void ipw_handle_missed_beacon(struct ipw_priv *priv, if (!(priv->status & STATUS_ROAMING)) { priv->status |= STATUS_ROAMING; if (!(priv->status & STATUS_SCANNING)) - queue_work(priv->workqueue, - &priv->request_scan); + queue_delayed_work(priv->workqueue, + &priv->request_scan, 0); } return; } @@ -4607,8 +4615,8 @@ static void ipw_rx_notification(struct ipw_priv *priv, #ifdef CONFIG_IPW2200_MONITOR if (priv->ieee->iw_mode == IW_MODE_MONITOR) { priv->status |= STATUS_SCAN_FORCED; - queue_work(priv->workqueue, - &priv->request_scan); + queue_delayed_work(priv->workqueue, + &priv->request_scan, 0); break; } priv->status &= ~STATUS_SCAN_FORCED; @@ -4631,8 +4639,8 @@ static void ipw_rx_notification(struct ipw_priv *priv, /* Don't schedule if we aborted the scan */ priv->status &= ~STATUS_ROAMING; } else if (priv->status & STATUS_SCAN_PENDING) - queue_work(priv->workqueue, - &priv->request_scan); + queue_delayed_work(priv->workqueue, + &priv->request_scan, 0); else if (priv->config & CFG_BACKGROUND_SCAN && priv->status & STATUS_ASSOCIATED) queue_delayed_work(priv->workqueue, @@ -5055,11 +5063,12 @@ static void ipw_rx_queue_replenish(void *data) ipw_rx_queue_restock(priv); } -static void ipw_bg_rx_queue_replenish(void *data) +static void ipw_bg_rx_queue_replenish(struct work_struct *work) { - struct ipw_priv *priv = data; + struct ipw_priv *priv = + container_of(work, struct ipw_priv, rx_replenish); mutex_lock(&priv->mutex); - ipw_rx_queue_replenish(data); + ipw_rx_queue_replenish(priv); mutex_unlock(&priv->mutex); } @@ -5489,9 +5498,10 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv, return 1; } -static void ipw_merge_adhoc_network(void *data) +static void ipw_merge_adhoc_network(struct work_struct *work) { - struct ipw_priv *priv = data; + struct ipw_priv *priv = + container_of(work, struct ipw_priv, merge_networks); struct ieee80211_network *network = NULL; struct ipw_network_match match = { .network = priv->assoc_network @@ -5948,11 +5958,12 @@ static void ipw_adhoc_check(void *data) priv->assoc_request.beacon_interval); } -static void ipw_bg_adhoc_check(void *data) +static void ipw_bg_adhoc_check(struct work_struct *work) { - struct ipw_priv *priv = data; + struct ipw_priv *priv = + container_of(work, struct ipw_priv, adhoc_check.work); mutex_lock(&priv->mutex); - ipw_adhoc_check(data); + ipw_adhoc_check(priv); mutex_unlock(&priv->mutex); } @@ -6299,19 +6310,26 @@ static int ipw_request_scan_helper(struct ipw_priv *priv, int type) return err; } -static int ipw_request_passive_scan(struct ipw_priv *priv) { - return ipw_request_scan_helper(priv, IW_SCAN_TYPE_PASSIVE); +static void ipw_request_passive_scan(struct work_struct *work) +{ + struct ipw_priv *priv = + container_of(work, struct ipw_priv, request_passive_scan); + ipw_request_scan_helper(priv, IW_SCAN_TYPE_PASSIVE); } -static int ipw_request_scan(struct ipw_priv *priv) { - return ipw_request_scan_helper(priv, IW_SCAN_TYPE_ACTIVE); +static void ipw_request_scan(struct work_struct *work) +{ + struct ipw_priv *priv = + container_of(work, struct ipw_priv, request_scan.work); + ipw_request_scan_helper(priv, IW_SCAN_TYPE_ACTIVE); } -static void ipw_bg_abort_scan(void *data) +static void ipw_bg_abort_scan(struct work_struct *work) { - struct ipw_priv *priv = data; + struct ipw_priv *priv = + container_of(work, struct ipw_priv, abort_scan); mutex_lock(&priv->mutex); - ipw_abort_scan(data); + ipw_abort_scan(priv); mutex_unlock(&priv->mutex); } @@ -7084,9 +7102,10 @@ static int ipw_qos_set_tx_queue_command(struct ipw_priv *priv, /* * background support to run QoS activate functionality */ -static void ipw_bg_qos_activate(void *data) +static void ipw_bg_qos_activate(struct work_struct *work) { - struct ipw_priv *priv = data; + struct ipw_priv *priv = + container_of(work, struct ipw_priv, qos_activate); if (priv == NULL) return; @@ -7394,11 +7413,12 @@ static void ipw_roam(void *data) priv->status &= ~STATUS_ROAMING; } -static void ipw_bg_roam(void *data) +static void ipw_bg_roam(struct work_struct *work) { - struct ipw_priv *priv = data; + struct ipw_priv *priv = + container_of(work, struct ipw_priv, roam); mutex_lock(&priv->mutex); - ipw_roam(data); + ipw_roam(priv); mutex_unlock(&priv->mutex); } @@ -7479,8 +7499,8 @@ static int ipw_associate(void *data) &priv->request_scan, SCAN_INTERVAL); else - queue_work(priv->workqueue, - &priv->request_scan); + queue_delayed_work(priv->workqueue, + &priv->request_scan, 0); } return 0; @@ -7491,11 +7511,12 @@ static int ipw_associate(void *data) return 1; } -static void ipw_bg_associate(void *data) +static void ipw_bg_associate(struct work_struct *work) { - struct ipw_priv *priv = data; + struct ipw_priv *priv = + container_of(work, struct ipw_priv, associate); mutex_lock(&priv->mutex); - ipw_associate(data); + ipw_associate(priv); mutex_unlock(&priv->mutex); } @@ -7656,7 +7677,8 @@ static void ipw_handle_data_packet_monitor(struct ipw_priv *priv, /* Big bitfield of all the fields we provide in radiotap */ ipw_rt->rt_hdr.it_present = - ((1 << IEEE80211_RADIOTAP_FLAGS) | + ((1 << IEEE80211_RADIOTAP_TSFT) | + (1 << IEEE80211_RADIOTAP_FLAGS) | (1 << IEEE80211_RADIOTAP_RATE) | (1 << IEEE80211_RADIOTAP_CHANNEL) | (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) | @@ -7665,10 +7687,14 @@ static void ipw_handle_data_packet_monitor(struct ipw_priv *priv, /* Zero the flags, we'll add to them as we go */ ipw_rt->rt_flags = 0; - ipw_rt->rt_tsf = 0ULL; + ipw_rt->rt_tsf = (u64)(frame->parent_tsf[3] << 24 | + frame->parent_tsf[2] << 16 | + frame->parent_tsf[1] << 8 | + frame->parent_tsf[0]); /* Convert signal to DBM */ ipw_rt->rt_dbmsignal = antsignal; + ipw_rt->rt_dbmnoise = frame->noise; /* Convert the channel data and set the flags */ ipw_rt->rt_channel = cpu_to_le16(ieee80211chan2mhz(received_channel)); @@ -7868,7 +7894,8 @@ static void ipw_handle_promiscuous_rx(struct ipw_priv *priv, /* Big bitfield of all the fields we provide in radiotap */ ipw_rt->rt_hdr.it_present = - ((1 << IEEE80211_RADIOTAP_FLAGS) | + ((1 << IEEE80211_RADIOTAP_TSFT) | + (1 << IEEE80211_RADIOTAP_FLAGS) | (1 << IEEE80211_RADIOTAP_RATE) | (1 << IEEE80211_RADIOTAP_CHANNEL) | (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) | @@ -7877,7 +7904,10 @@ static void ipw_handle_promiscuous_rx(struct ipw_priv *priv, /* Zero the flags, we'll add to them as we go */ ipw_rt->rt_flags = 0; - ipw_rt->rt_tsf = 0ULL; + ipw_rt->rt_tsf = (u64)(frame->parent_tsf[3] << 24 | + frame->parent_tsf[2] << 16 | + frame->parent_tsf[1] << 8 | + frame->parent_tsf[0]); /* Convert to DBM */ ipw_rt->rt_dbmsignal = signal; @@ -8276,7 +8306,7 @@ static void ipw_rx(struct ipw_priv *priv) ("Notification: subtype=%02X flags=%02X size=%d\n", pkt->u.notification.subtype, pkt->u.notification.flags, - pkt->u.notification.size); + le16_to_cpu(pkt->u.notification.size)); ipw_rx_notification(priv, &pkt->u.notification); break; } @@ -9410,7 +9440,7 @@ static int ipw_wx_set_scan(struct net_device *dev, IPW_DEBUG_WX("Start scan\n"); - queue_work(priv->workqueue, &priv->request_scan); + queue_delayed_work(priv->workqueue, &priv->request_scan, 0); return 0; } @@ -10547,11 +10577,12 @@ static void ipw_rf_kill(void *adapter) spin_unlock_irqrestore(&priv->lock, flags); } -static void ipw_bg_rf_kill(void *data) +static void ipw_bg_rf_kill(struct work_struct *work) { - struct ipw_priv *priv = data; + struct ipw_priv *priv = + container_of(work, struct ipw_priv, rf_kill.work); mutex_lock(&priv->mutex); - ipw_rf_kill(data); + ipw_rf_kill(priv); mutex_unlock(&priv->mutex); } @@ -10582,11 +10613,12 @@ static void ipw_link_up(struct ipw_priv *priv) queue_delayed_work(priv->workqueue, &priv->request_scan, HZ); } -static void ipw_bg_link_up(void *data) +static void ipw_bg_link_up(struct work_struct *work) { - struct ipw_priv *priv = data; + struct ipw_priv *priv = + container_of(work, struct ipw_priv, link_up); mutex_lock(&priv->mutex); - ipw_link_up(data); + ipw_link_up(priv); mutex_unlock(&priv->mutex); } @@ -10606,15 +10638,16 @@ static void ipw_link_down(struct ipw_priv *priv) if (!(priv->status & STATUS_EXIT_PENDING)) { /* Queue up another scan... */ - queue_work(priv->workqueue, &priv->request_scan); + queue_delayed_work(priv->workqueue, &priv->request_scan, 0); } } -static void ipw_bg_link_down(void *data) +static void ipw_bg_link_down(struct work_struct *work) { - struct ipw_priv *priv = data; + struct ipw_priv *priv = + container_of(work, struct ipw_priv, link_down); mutex_lock(&priv->mutex); - ipw_link_down(data); + ipw_link_down(priv); mutex_unlock(&priv->mutex); } @@ -10626,38 +10659,30 @@ static int ipw_setup_deferred_work(struct ipw_priv *priv) init_waitqueue_head(&priv->wait_command_queue); init_waitqueue_head(&priv->wait_state); - INIT_WORK(&priv->adhoc_check, ipw_bg_adhoc_check, priv); - INIT_WORK(&priv->associate, ipw_bg_associate, priv); - INIT_WORK(&priv->disassociate, ipw_bg_disassociate, priv); - INIT_WORK(&priv->system_config, ipw_system_config, priv); - INIT_WORK(&priv->rx_replenish, ipw_bg_rx_queue_replenish, priv); - INIT_WORK(&priv->adapter_restart, ipw_bg_adapter_restart, priv); - INIT_WORK(&priv->rf_kill, ipw_bg_rf_kill, priv); - INIT_WORK(&priv->up, (void (*)(void *))ipw_bg_up, priv); - INIT_WORK(&priv->down, (void (*)(void *))ipw_bg_down, priv); - INIT_WORK(&priv->request_scan, - (void (*)(void *))ipw_request_scan, priv); - INIT_WORK(&priv->request_passive_scan, - (void (*)(void *))ipw_request_passive_scan, priv); - INIT_WORK(&priv->gather_stats, - (void (*)(void *))ipw_bg_gather_stats, priv); - INIT_WORK(&priv->abort_scan, (void (*)(void *))ipw_bg_abort_scan, priv); - INIT_WORK(&priv->roam, ipw_bg_roam, priv); - INIT_WORK(&priv->scan_check, ipw_bg_scan_check, priv); - INIT_WORK(&priv->link_up, (void (*)(void *))ipw_bg_link_up, priv); - INIT_WORK(&priv->link_down, (void (*)(void *))ipw_bg_link_down, priv); - INIT_WORK(&priv->led_link_on, (void (*)(void *))ipw_bg_led_link_on, - priv); - INIT_WORK(&priv->led_link_off, (void (*)(void *))ipw_bg_led_link_off, - priv); - INIT_WORK(&priv->led_act_off, (void (*)(void *))ipw_bg_led_activity_off, - priv); - INIT_WORK(&priv->merge_networks, - (void (*)(void *))ipw_merge_adhoc_network, priv); + INIT_DELAYED_WORK(&priv->adhoc_check, ipw_bg_adhoc_check); + INIT_WORK(&priv->associate, ipw_bg_associate); + INIT_WORK(&priv->disassociate, ipw_bg_disassociate); + INIT_WORK(&priv->system_config, ipw_system_config); + INIT_WORK(&priv->rx_replenish, ipw_bg_rx_queue_replenish); + INIT_WORK(&priv->adapter_restart, ipw_bg_adapter_restart); + INIT_DELAYED_WORK(&priv->rf_kill, ipw_bg_rf_kill); + INIT_WORK(&priv->up, ipw_bg_up); + INIT_WORK(&priv->down, ipw_bg_down); + INIT_DELAYED_WORK(&priv->request_scan, ipw_request_scan); + INIT_WORK(&priv->request_passive_scan, ipw_request_passive_scan); + INIT_DELAYED_WORK(&priv->gather_stats, ipw_bg_gather_stats); + INIT_WORK(&priv->abort_scan, ipw_bg_abort_scan); + INIT_WORK(&priv->roam, ipw_bg_roam); + INIT_DELAYED_WORK(&priv->scan_check, ipw_bg_scan_check); + INIT_WORK(&priv->link_up, ipw_bg_link_up); + INIT_WORK(&priv->link_down, ipw_bg_link_down); + INIT_DELAYED_WORK(&priv->led_link_on, ipw_bg_led_link_on); + INIT_DELAYED_WORK(&priv->led_link_off, ipw_bg_led_link_off); + INIT_DELAYED_WORK(&priv->led_act_off, ipw_bg_led_activity_off); + INIT_WORK(&priv->merge_networks, ipw_merge_adhoc_network); #ifdef CONFIG_IPW2200_QOS - INIT_WORK(&priv->qos_activate, (void (*)(void *))ipw_bg_qos_activate, - priv); + INIT_WORK(&priv->qos_activate, ipw_bg_qos_activate); #endif /* CONFIG_IPW2200_QOS */ tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) @@ -11129,14 +11154,13 @@ static int ipw_up(struct ipw_priv *priv) return -EIO; if (cmdlog && !priv->cmdlog) { - priv->cmdlog = kmalloc(sizeof(*priv->cmdlog) * cmdlog, + priv->cmdlog = kcalloc(cmdlog, sizeof(*priv->cmdlog), GFP_KERNEL); if (priv->cmdlog == NULL) { IPW_ERROR("Error allocating %d command log entries.\n", cmdlog); return -ENOMEM; } else { - memset(priv->cmdlog, 0, sizeof(*priv->cmdlog) * cmdlog); priv->cmdlog_len = cmdlog; } } @@ -11190,7 +11214,8 @@ static int ipw_up(struct ipw_priv *priv) /* If configure to try and auto-associate, kick * off a scan. */ - queue_work(priv->workqueue, &priv->request_scan); + queue_delayed_work(priv->workqueue, + &priv->request_scan, 0); return 0; } @@ -11211,11 +11236,12 @@ static int ipw_up(struct ipw_priv *priv) return -EIO; } -static void ipw_bg_up(void *data) +static void ipw_bg_up(struct work_struct *work) { - struct ipw_priv *priv = data; + struct ipw_priv *priv = + container_of(work, struct ipw_priv, up); mutex_lock(&priv->mutex); - ipw_up(data); + ipw_up(priv); mutex_unlock(&priv->mutex); } @@ -11282,11 +11308,12 @@ static void ipw_down(struct ipw_priv *priv) ipw_led_radio_off(priv); } -static void ipw_bg_down(void *data) +static void ipw_bg_down(struct work_struct *work) { - struct ipw_priv *priv = data; + struct ipw_priv *priv = + container_of(work, struct ipw_priv, down); mutex_lock(&priv->mutex); - ipw_down(data); + ipw_down(priv); mutex_unlock(&priv->mutex); } diff --git a/trunk/drivers/net/wireless/ipw2200.h b/trunk/drivers/net/wireless/ipw2200.h index dad5eedefbf1..626a240a87d8 100644 --- a/trunk/drivers/net/wireless/ipw2200.h +++ b/trunk/drivers/net/wireless/ipw2200.h @@ -1290,21 +1290,21 @@ struct ipw_priv { struct workqueue_struct *workqueue; - struct work_struct adhoc_check; + struct delayed_work adhoc_check; struct work_struct associate; struct work_struct disassociate; struct work_struct system_config; struct work_struct rx_replenish; - struct work_struct request_scan; + struct delayed_work request_scan; struct work_struct request_passive_scan; struct work_struct adapter_restart; - struct work_struct rf_kill; + struct delayed_work rf_kill; struct work_struct up; struct work_struct down; - struct work_struct gather_stats; + struct delayed_work gather_stats; struct work_struct abort_scan; struct work_struct roam; - struct work_struct scan_check; + struct delayed_work scan_check; struct work_struct link_up; struct work_struct link_down; @@ -1319,9 +1319,9 @@ struct ipw_priv { u32 led_ofdm_on; u32 led_ofdm_off; - struct work_struct led_link_on; - struct work_struct led_link_off; - struct work_struct led_act_off; + struct delayed_work led_link_on; + struct delayed_work led_link_off; + struct delayed_work led_act_off; struct work_struct merge_networks; struct ipw_cmd_log *cmdlog; diff --git a/trunk/drivers/net/wireless/netwave_cs.c b/trunk/drivers/net/wireless/netwave_cs.c index 6714e0dfa8d6..644b4741ef74 100644 --- a/trunk/drivers/net/wireless/netwave_cs.c +++ b/trunk/drivers/net/wireless/netwave_cs.c @@ -735,31 +735,13 @@ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) static int netwave_pcmcia_config(struct pcmcia_device *link) { struct net_device *dev = link->priv; netwave_private *priv = netdev_priv(dev); - tuple_t tuple; - cisparse_t parse; int i, j, last_ret, last_fn; - u_char buf[64]; win_req_t req; memreq_t mem; u_char __iomem *ramBase = NULL; DEBUG(0, "netwave_pcmcia_config(0x%p)\n", link); - /* - This reads the card's CONFIG tuple to find its configuration - registers. - */ - tuple.Attributes = 0; - tuple.TupleData = (cisdata_t *) buf; - tuple.TupleDataMax = 64; - tuple.TupleOffset = 0; - tuple.DesiredTuple = CISTPL_CONFIG; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); - link->conf.ConfigBase = parse.config.base; - link->conf.Present = parse.config.rmask[0]; - /* * Try allocating IO ports. This tries a few fixed addresses. * If you want, you can also read the card's config table to diff --git a/trunk/drivers/net/wireless/orinoco.c b/trunk/drivers/net/wireless/orinoco.c index 336cabac13b3..936c888e03e1 100644 --- a/trunk/drivers/net/wireless/orinoco.c +++ b/trunk/drivers/net/wireless/orinoco.c @@ -980,9 +980,11 @@ static void print_linkstatus(struct net_device *dev, u16 status) } /* Search scan results for requested BSSID, join it if found */ -static void orinoco_join_ap(struct net_device *dev) +static void orinoco_join_ap(struct work_struct *work) { - struct orinoco_private *priv = netdev_priv(dev); + struct orinoco_private *priv = + container_of(work, struct orinoco_private, join_work); + struct net_device *dev = priv->ndev; struct hermes *hw = &priv->hw; int err; unsigned long flags; @@ -1055,9 +1057,11 @@ static void orinoco_join_ap(struct net_device *dev) } /* Send new BSSID to userspace */ -static void orinoco_send_wevents(struct net_device *dev) +static void orinoco_send_wevents(struct work_struct *work) { - struct orinoco_private *priv = netdev_priv(dev); + struct orinoco_private *priv = + container_of(work, struct orinoco_private, wevent_work); + struct net_device *dev = priv->ndev; struct hermes *hw = &priv->hw; union iwreq_data wrqu; int err; @@ -1864,9 +1868,11 @@ __orinoco_set_multicast_list(struct net_device *dev) /* This must be called from user context, without locks held - use * schedule_work() */ -static void orinoco_reset(struct net_device *dev) +static void orinoco_reset(struct work_struct *work) { - struct orinoco_private *priv = netdev_priv(dev); + struct orinoco_private *priv = + container_of(work, struct orinoco_private, reset_work); + struct net_device *dev = priv->ndev; struct hermes *hw = &priv->hw; int err; unsigned long flags; @@ -2434,9 +2440,9 @@ struct net_device *alloc_orinocodev(int sizeof_card, priv->hw_unavailable = 1; /* orinoco_init() must clear this * before anything else touches the * hardware */ - INIT_WORK(&priv->reset_work, (void (*)(void *))orinoco_reset, dev); - INIT_WORK(&priv->join_work, (void (*)(void *))orinoco_join_ap, dev); - INIT_WORK(&priv->wevent_work, (void (*)(void *))orinoco_send_wevents, dev); + INIT_WORK(&priv->reset_work, orinoco_reset); + INIT_WORK(&priv->join_work, orinoco_join_ap); + INIT_WORK(&priv->wevent_work, orinoco_send_wevents); netif_carrier_off(dev); priv->last_linkstatus = 0xffff; @@ -3608,7 +3614,7 @@ static int orinoco_ioctl_reset(struct net_device *dev, printk(KERN_DEBUG "%s: Forcing reset!\n", dev->name); /* Firmware reset */ - orinoco_reset(dev); + orinoco_reset(&priv->reset_work); } else { printk(KERN_DEBUG "%s: Force scheduling reset!\n", dev->name); @@ -4154,7 +4160,7 @@ static int orinoco_ioctl_commit(struct net_device *dev, return 0; if (priv->broken_disableport) { - orinoco_reset(dev); + orinoco_reset(&priv->reset_work); return 0; } diff --git a/trunk/drivers/net/wireless/orinoco_cs.c b/trunk/drivers/net/wireless/orinoco_cs.c index bc14689cbf24..d08ae8d2726c 100644 --- a/trunk/drivers/net/wireless/orinoco_cs.c +++ b/trunk/drivers/net/wireless/orinoco_cs.c @@ -178,21 +178,6 @@ orinoco_cs_config(struct pcmcia_device *link) cisparse_t parse; void __iomem *mem; - /* - * This reads the card's CONFIG tuple to find its - * configuration registers. - */ - tuple.DesiredTuple = CISTPL_CONFIG; - tuple.Attributes = 0; - tuple.TupleData = buf; - tuple.TupleDataMax = sizeof(buf); - tuple.TupleOffset = 0; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); - link->conf.ConfigBase = parse.config.base; - link->conf.Present = parse.config.rmask[0]; - /* Look up the current Vcc */ CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &conf)); @@ -211,6 +196,10 @@ orinoco_cs_config(struct pcmcia_device *link) * and most client drivers will only use the CIS to fill in * implementation-defined details. */ + tuple.Attributes = 0; + tuple.TupleData = buf; + tuple.TupleDataMax = sizeof(buf); + tuple.TupleOffset = 0; tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); while (1) { diff --git a/trunk/drivers/net/wireless/prism54/isl_ioctl.c b/trunk/drivers/net/wireless/prism54/isl_ioctl.c index 4a20e45de3ca..96606ed10076 100644 --- a/trunk/drivers/net/wireless/prism54/isl_ioctl.c +++ b/trunk/drivers/net/wireless/prism54/isl_ioctl.c @@ -157,8 +157,9 @@ prism54_mib_init(islpci_private *priv) * schedule_work(), thus we can as well use sleeping semaphore * locking */ void -prism54_update_stats(islpci_private *priv) +prism54_update_stats(struct work_struct *work) { + islpci_private *priv = container_of(work, islpci_private, stats_work); char *data; int j; struct obj_bss bss, *bss2; @@ -2140,11 +2141,9 @@ prism54_wpa_bss_ie_add(islpci_private *priv, u8 *bssid, struct islpci_bss_wpa_ie, list); list_del(&bss->list); } else { - bss = kmalloc(sizeof (*bss), GFP_ATOMIC); - if (bss != NULL) { + bss = kzalloc(sizeof (*bss), GFP_ATOMIC); + if (bss != NULL) priv->num_bss_wpa++; - memset(bss, 0, sizeof (*bss)); - } } if (bss != NULL) { memcpy(bss->bssid, bssid, ETH_ALEN); @@ -2493,9 +2492,10 @@ prism54_process_trap_helper(islpci_private *priv, enum oid_num_t oid, * interrupt context, no locks held. */ void -prism54_process_trap(void *data) +prism54_process_trap(struct work_struct *work) { - struct islpci_mgmtframe *frame = data; + struct islpci_mgmtframe *frame = + container_of(work, struct islpci_mgmtframe, ws); struct net_device *ndev = frame->ndev; enum oid_num_t n = mgt_oidtonum(frame->header->oid); @@ -2684,11 +2684,10 @@ prism2_ioctl_set_generic_element(struct net_device *ndev, return -EINVAL; alen = sizeof(*attach) + len; - attach = kmalloc(alen, GFP_KERNEL); + attach = kzalloc(alen, GFP_KERNEL); if (attach == NULL) return -ENOMEM; - memset(attach, 0, alen); #define WLAN_FC_TYPE_MGMT 0 #define WLAN_FC_STYPE_ASSOC_REQ 0 #define WLAN_FC_STYPE_REASSOC_REQ 2 diff --git a/trunk/drivers/net/wireless/prism54/isl_ioctl.h b/trunk/drivers/net/wireless/prism54/isl_ioctl.h index e8183d30c52e..bcfbfb9281d2 100644 --- a/trunk/drivers/net/wireless/prism54/isl_ioctl.h +++ b/trunk/drivers/net/wireless/prism54/isl_ioctl.h @@ -31,12 +31,12 @@ void prism54_mib_init(islpci_private *); struct iw_statistics *prism54_get_wireless_stats(struct net_device *); -void prism54_update_stats(islpci_private *); +void prism54_update_stats(struct work_struct *); void prism54_acl_init(struct islpci_acl *); void prism54_acl_clean(struct islpci_acl *); -void prism54_process_trap(void *); +void prism54_process_trap(struct work_struct *); void prism54_wpa_bss_ie_init(islpci_private *priv); void prism54_wpa_bss_ie_clean(islpci_private *priv); diff --git a/trunk/drivers/net/wireless/prism54/islpci_dev.c b/trunk/drivers/net/wireless/prism54/islpci_dev.c index 1e0603ca436c..f057fd9fcd79 100644 --- a/trunk/drivers/net/wireless/prism54/islpci_dev.c +++ b/trunk/drivers/net/wireless/prism54/islpci_dev.c @@ -860,11 +860,10 @@ islpci_setup(struct pci_dev *pdev) priv->state_off = 1; /* initialize workqueue's */ - INIT_WORK(&priv->stats_work, - (void (*)(void *)) prism54_update_stats, priv); + INIT_WORK(&priv->stats_work, prism54_update_stats); priv->stats_timestamp = 0; - INIT_WORK(&priv->reset_task, islpci_do_reset_and_wake, priv); + INIT_WORK(&priv->reset_task, islpci_do_reset_and_wake); priv->reset_task_pending = 0; /* allocate various memory areas */ diff --git a/trunk/drivers/net/wireless/prism54/islpci_eth.c b/trunk/drivers/net/wireless/prism54/islpci_eth.c index 676d83813dc8..b1122912ee2d 100644 --- a/trunk/drivers/net/wireless/prism54/islpci_eth.c +++ b/trunk/drivers/net/wireless/prism54/islpci_eth.c @@ -480,9 +480,9 @@ islpci_eth_receive(islpci_private *priv) } void -islpci_do_reset_and_wake(void *data) +islpci_do_reset_and_wake(struct work_struct *work) { - islpci_private *priv = data; + islpci_private *priv = container_of(work, islpci_private, reset_task); islpci_reset(priv, 1); priv->reset_task_pending = 0; diff --git a/trunk/drivers/net/wireless/prism54/islpci_eth.h b/trunk/drivers/net/wireless/prism54/islpci_eth.h index 26789454067c..5bf820defbd0 100644 --- a/trunk/drivers/net/wireless/prism54/islpci_eth.h +++ b/trunk/drivers/net/wireless/prism54/islpci_eth.h @@ -67,6 +67,6 @@ void islpci_eth_cleanup_transmit(islpci_private *, isl38xx_control_block *); int islpci_eth_transmit(struct sk_buff *, struct net_device *); int islpci_eth_receive(islpci_private *); void islpci_eth_tx_timeout(struct net_device *); -void islpci_do_reset_and_wake(void *data); +void islpci_do_reset_and_wake(struct work_struct *); #endif /* _ISL_GEN_H */ diff --git a/trunk/drivers/net/wireless/prism54/islpci_mgt.c b/trunk/drivers/net/wireless/prism54/islpci_mgt.c index 036a875054c9..2246f7930b4e 100644 --- a/trunk/drivers/net/wireless/prism54/islpci_mgt.c +++ b/trunk/drivers/net/wireless/prism54/islpci_mgt.c @@ -386,7 +386,7 @@ islpci_mgt_receive(struct net_device *ndev) /* Create work to handle trap out of interrupt * context. */ - INIT_WORK(&frame->ws, prism54_process_trap, frame); + INIT_WORK(&frame->ws, prism54_process_trap); schedule_work(&frame->ws); } else { diff --git a/trunk/drivers/net/wireless/prism54/oid_mgt.c b/trunk/drivers/net/wireless/prism54/oid_mgt.c index fbc52b6a3024..e6cf9df2c206 100644 --- a/trunk/drivers/net/wireless/prism54/oid_mgt.c +++ b/trunk/drivers/net/wireless/prism54/oid_mgt.c @@ -235,12 +235,10 @@ mgt_init(islpci_private *priv) { int i; - priv->mib = kmalloc(OID_NUM_LAST * sizeof (void *), GFP_KERNEL); + priv->mib = kcalloc(OID_NUM_LAST, sizeof (void *), GFP_KERNEL); if (!priv->mib) return -ENOMEM; - memset(priv->mib, 0, OID_NUM_LAST * sizeof (void *)); - /* Alloc the cache */ for (i = 0; i < OID_NUM_LAST; i++) { if (isl_oid[i].flags & OID_FLAG_CACHED) { diff --git a/trunk/drivers/net/wireless/ray_cs.c b/trunk/drivers/net/wireless/ray_cs.c index 7fbfc9e41d07..88e10c9bc4ac 100644 --- a/trunk/drivers/net/wireless/ray_cs.c +++ b/trunk/drivers/net/wireless/ray_cs.c @@ -408,11 +408,8 @@ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) #define MAX_TUPLE_SIZE 128 static int ray_config(struct pcmcia_device *link) { - tuple_t tuple; - cisparse_t parse; int last_fn = 0, last_ret = 0; int i; - u_char buf[MAX_TUPLE_SIZE]; win_req_t req; memreq_t mem; struct net_device *dev = (struct net_device *)link->priv; @@ -420,29 +417,12 @@ static int ray_config(struct pcmcia_device *link) DEBUG(1, "ray_config(0x%p)\n", link); - /* This reads the card's CONFIG tuple to find its configuration regs */ - tuple.DesiredTuple = CISTPL_CONFIG; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); - tuple.TupleData = buf; - tuple.TupleDataMax = MAX_TUPLE_SIZE; - tuple.TupleOffset = 0; - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); - link->conf.ConfigBase = parse.config.base; - link->conf.Present = parse.config.rmask[0]; - /* Determine card type and firmware version */ - buf[0] = buf[MAX_TUPLE_SIZE - 1] = 0; - tuple.DesiredTuple = CISTPL_VERS_1; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); - tuple.TupleData = buf; - tuple.TupleDataMax = MAX_TUPLE_SIZE; - tuple.TupleOffset = 2; - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); - - for (i=0; iprod_id[0] ? link->prod_id[0] : " ", + link->prod_id[1] ? link->prod_id[1] : " ", + link->prod_id[2] ? link->prod_id[2] : " ", + link->prod_id[3] ? link->prod_id[3] : " "); /* Now allocate an interrupt line. Note that this does not actually assign a handler to the interrupt. diff --git a/trunk/drivers/net/wireless/spectrum_cs.c b/trunk/drivers/net/wireless/spectrum_cs.c index bcc7038130f6..cf2d1486b01d 100644 --- a/trunk/drivers/net/wireless/spectrum_cs.c +++ b/trunk/drivers/net/wireless/spectrum_cs.c @@ -647,21 +647,6 @@ spectrum_cs_config(struct pcmcia_device *link) cisparse_t parse; void __iomem *mem; - /* - * This reads the card's CONFIG tuple to find its - * configuration registers. - */ - tuple.DesiredTuple = CISTPL_CONFIG; - tuple.Attributes = 0; - tuple.TupleData = buf; - tuple.TupleDataMax = sizeof(buf); - tuple.TupleOffset = 0; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); - link->conf.ConfigBase = parse.config.base; - link->conf.Present = parse.config.rmask[0]; - /* Look up the current Vcc */ CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &conf)); @@ -681,6 +666,10 @@ spectrum_cs_config(struct pcmcia_device *link) * implementation-defined details. */ tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; + tuple.Attributes = 0; + tuple.TupleData = buf; + tuple.TupleDataMax = sizeof(buf); + tuple.TupleOffset = 0; CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); while (1) { cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); diff --git a/trunk/drivers/net/wireless/strip.c b/trunk/drivers/net/wireless/strip.c index 337c692f6fd6..ce3a8bac66ff 100644 --- a/trunk/drivers/net/wireless/strip.c +++ b/trunk/drivers/net/wireless/strip.c @@ -798,7 +798,7 @@ static unsigned int get_baud(struct tty_struct *tty) */ static void set_baud(struct tty_struct *tty, unsigned int baudcode) { - struct termios old_termios = *(tty->termios); + struct ktermios old_termios = *(tty->termios); tty->termios->c_cflag &= ~CBAUD; /* Clear the old baud setting */ tty->termios->c_cflag |= baudcode; /* Set the new baud setting */ tty->driver->set_termios(tty, &old_termios); diff --git a/trunk/drivers/net/wireless/wavelan_cs.c b/trunk/drivers/net/wireless/wavelan_cs.c index aafb301041b1..233d906c08f0 100644 --- a/trunk/drivers/net/wireless/wavelan_cs.c +++ b/trunk/drivers/net/wireless/wavelan_cs.c @@ -3939,11 +3939,8 @@ wv_hw_reset(struct net_device * dev) static inline int wv_pcmcia_config(struct pcmcia_device * link) { - tuple_t tuple; - cisparse_t parse; struct net_device * dev = (struct net_device *) link->priv; int i; - u_char buf[64]; win_req_t req; memreq_t mem; net_local * lp = netdev_priv(dev); @@ -3953,36 +3950,6 @@ wv_pcmcia_config(struct pcmcia_device * link) printk(KERN_DEBUG "->wv_pcmcia_config(0x%p)\n", link); #endif - /* - * This reads the card's CONFIG tuple to find its configuration - * registers. - */ - do - { - tuple.Attributes = 0; - tuple.DesiredTuple = CISTPL_CONFIG; - i = pcmcia_get_first_tuple(link, &tuple); - if(i != CS_SUCCESS) - break; - tuple.TupleData = (cisdata_t *)buf; - tuple.TupleDataMax = 64; - tuple.TupleOffset = 0; - i = pcmcia_get_tuple_data(link, &tuple); - if(i != CS_SUCCESS) - break; - i = pcmcia_parse_tuple(link, &tuple, &parse); - if(i != CS_SUCCESS) - break; - link->conf.ConfigBase = parse.config.base; - link->conf.Present = parse.config.rmask[0]; - } - while(0); - if(i != CS_SUCCESS) - { - cs_error(link, ParseTuple, i); - return FALSE; - } - do { i = pcmcia_request_io(link, &link->io); diff --git a/trunk/drivers/net/wireless/wl3501_cs.c b/trunk/drivers/net/wireless/wl3501_cs.c index 5b98a7876982..583e0d655a98 100644 --- a/trunk/drivers/net/wireless/wl3501_cs.c +++ b/trunk/drivers/net/wireless/wl3501_cs.c @@ -1966,25 +1966,10 @@ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) */ static int wl3501_config(struct pcmcia_device *link) { - tuple_t tuple; - cisparse_t parse; struct net_device *dev = link->priv; int i = 0, j, last_fn, last_ret; - unsigned char bf[64]; struct wl3501_card *this; - /* This reads the card's CONFIG tuple to find its config registers. */ - tuple.Attributes = 0; - tuple.DesiredTuple = CISTPL_CONFIG; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); - tuple.TupleData = bf; - tuple.TupleDataMax = sizeof(bf); - tuple.TupleOffset = 0; - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); - link->conf.ConfigBase = parse.config.base; - link->conf.Present = parse.config.rmask[0]; - /* Try allocating IO ports. This tries a few fixed addresses. If you * want, you can also read the card's config table to pick addresses -- * see the serial driver for an example. */ diff --git a/trunk/drivers/net/wireless/zd1211rw/zd_chip.c b/trunk/drivers/net/wireless/zd1211rw/zd_chip.c index 8be99ebbe1cd..77e11ddad836 100644 --- a/trunk/drivers/net/wireless/zd1211rw/zd_chip.c +++ b/trunk/drivers/net/wireless/zd1211rw/zd_chip.c @@ -1673,3 +1673,16 @@ int zd_rfwritev_cr_locked(struct zd_chip *chip, return 0; } + +int zd_chip_set_multicast_hash(struct zd_chip *chip, + struct zd_mc_hash *hash) +{ + struct zd_ioreq32 ioreqs[] = { + { CR_GROUP_HASH_P1, hash->low }, + { CR_GROUP_HASH_P2, hash->high }, + }; + + dev_dbg_f(zd_chip_dev(chip), "hash l 0x%08x h 0x%08x\n", + ioreqs[0].value, ioreqs[1].value); + return zd_iowrite32a(chip, ioreqs, ARRAY_SIZE(ioreqs)); +} diff --git a/trunk/drivers/net/wireless/zd1211rw/zd_chip.h b/trunk/drivers/net/wireless/zd1211rw/zd_chip.h index ca892b9a6448..a4e3cee9b59d 100644 --- a/trunk/drivers/net/wireless/zd1211rw/zd_chip.h +++ b/trunk/drivers/net/wireless/zd1211rw/zd_chip.h @@ -390,10 +390,19 @@ #define CR_BSSID_P1 CTL_REG(0x0618) #define CR_BSSID_P2 CTL_REG(0x061C) #define CR_BCN_PLCP_CFG CTL_REG(0x0620) + +/* Group hash table for filtering incoming packets. + * + * The group hash table is 64 bit large and split over two parts. The first + * part is the lower part. The upper 6 bits of the last byte of the target + * address are used as index. Packets are received if the hash table bit is + * set. This is used for multicast handling, but for broadcasts (address + * ff:ff:ff:ff:ff:ff) the highest bit in the second table must also be set. + */ #define CR_GROUP_HASH_P1 CTL_REG(0x0624) #define CR_GROUP_HASH_P2 CTL_REG(0x0628) -#define CR_RX_TIMEOUT CTL_REG(0x062C) +#define CR_RX_TIMEOUT CTL_REG(0x062C) /* Basic rates supported by the BSS. When producing ACK or CTS messages, the * device will use a rate in this table that is less than or equal to the rate * of the incoming frame which prompted the response */ @@ -864,4 +873,36 @@ u8 zd_rx_strength_percent(u8 rssi); u16 zd_rx_rate(const void *rx_frame, const struct rx_status *status); +struct zd_mc_hash { + u32 low; + u32 high; +}; + +static inline void zd_mc_clear(struct zd_mc_hash *hash) +{ + hash->low = 0; + /* The interfaces must always received broadcasts. + * The hash of the broadcast address ff:ff:ff:ff:ff:ff is 63. + */ + hash->high = 0x80000000; +} + +static inline void zd_mc_add_all(struct zd_mc_hash *hash) +{ + hash->low = hash->high = 0xffffffff; +} + +static inline void zd_mc_add_addr(struct zd_mc_hash *hash, u8 *addr) +{ + unsigned int i = addr[5] >> 2; + if (i < 32) { + hash->low |= 1 << i; + } else { + hash->high |= 1 << (i-32); + } +} + +int zd_chip_set_multicast_hash(struct zd_chip *chip, + struct zd_mc_hash *hash); + #endif /* _ZD_CHIP_H */ diff --git a/trunk/drivers/net/wireless/zd1211rw/zd_mac.c b/trunk/drivers/net/wireless/zd1211rw/zd_mac.c index 2696f95b9278..00ca704ece35 100644 --- a/trunk/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/trunk/drivers/net/wireless/zd1211rw/zd_mac.c @@ -32,13 +32,15 @@ static void ieee_init(struct ieee80211_device *ieee); static void softmac_init(struct ieee80211softmac_device *sm); -static void set_rts_cts_work(void *d); -static void set_basic_rates_work(void *d); +static void set_rts_cts_work(struct work_struct *work); +static void set_basic_rates_work(struct work_struct *work); static void housekeeping_init(struct zd_mac *mac); static void housekeeping_enable(struct zd_mac *mac); static void housekeeping_disable(struct zd_mac *mac); +static void set_multicast_hash_handler(struct work_struct *work); + int zd_mac_init(struct zd_mac *mac, struct net_device *netdev, struct usb_interface *intf) @@ -48,13 +50,14 @@ int zd_mac_init(struct zd_mac *mac, memset(mac, 0, sizeof(*mac)); spin_lock_init(&mac->lock); mac->netdev = netdev; - INIT_WORK(&mac->set_rts_cts_work, set_rts_cts_work, mac); - INIT_WORK(&mac->set_basic_rates_work, set_basic_rates_work, mac); + INIT_DELAYED_WORK(&mac->set_rts_cts_work, set_rts_cts_work); + INIT_DELAYED_WORK(&mac->set_basic_rates_work, set_basic_rates_work); ieee_init(ieee); softmac_init(ieee80211_priv(netdev)); zd_chip_init(&mac->chip, netdev, intf); housekeeping_init(mac); + INIT_WORK(&mac->set_multicast_hash_work, set_multicast_hash_handler); return 0; } @@ -136,6 +139,7 @@ int zd_mac_init_hw(struct zd_mac *mac, u8 device_type) void zd_mac_clear(struct zd_mac *mac) { + flush_workqueue(zd_workqueue); zd_chip_clear(&mac->chip); ZD_ASSERT(!spin_is_locked(&mac->lock)); ZD_MEMCLEAR(mac, sizeof(struct zd_mac)); @@ -256,6 +260,43 @@ int zd_mac_set_mac_address(struct net_device *netdev, void *p) return 0; } +static void set_multicast_hash_handler(struct work_struct *work) +{ + struct zd_mac *mac = container_of(work, struct zd_mac, + set_multicast_hash_work); + struct zd_mc_hash hash; + + spin_lock_irq(&mac->lock); + hash = mac->multicast_hash; + spin_unlock_irq(&mac->lock); + + zd_chip_set_multicast_hash(&mac->chip, &hash); +} + +void zd_mac_set_multicast_list(struct net_device *dev) +{ + struct zd_mc_hash hash; + struct zd_mac *mac = zd_netdev_mac(dev); + struct dev_mc_list *mc; + unsigned long flags; + + if (dev->flags & (IFF_PROMISC|IFF_ALLMULTI)) { + zd_mc_add_all(&hash); + } else { + zd_mc_clear(&hash); + for (mc = dev->mc_list; mc; mc = mc->next) { + dev_dbg_f(zd_mac_dev(mac), "mc addr " MAC_FMT "\n", + MAC_ARG(mc->dmi_addr)); + zd_mc_add_addr(&hash, mc->dmi_addr); + } + } + + spin_lock_irqsave(&mac->lock, flags); + mac->multicast_hash = hash; + spin_unlock_irqrestore(&mac->lock, flags); + queue_work(zd_workqueue, &mac->set_multicast_hash_work); +} + int zd_mac_set_regdomain(struct zd_mac *mac, u8 regdomain) { int r; @@ -366,9 +407,10 @@ static void try_enable_tx(struct zd_mac *mac) spin_unlock_irqrestore(&mac->lock, flags); } -static void set_rts_cts_work(void *d) +static void set_rts_cts_work(struct work_struct *work) { - struct zd_mac *mac = d; + struct zd_mac *mac = + container_of(work, struct zd_mac, set_rts_cts_work.work); unsigned long flags; u8 rts_rate; unsigned int short_preamble; @@ -387,9 +429,10 @@ static void set_rts_cts_work(void *d) try_enable_tx(mac); } -static void set_basic_rates_work(void *d) +static void set_basic_rates_work(struct work_struct *work) { - struct zd_mac *mac = d; + struct zd_mac *mac = + container_of(work, struct zd_mac, set_basic_rates_work.work); unsigned long flags; u16 basic_rates; @@ -467,12 +510,13 @@ static void bssinfo_change(struct net_device *netdev, u32 changes) if (need_set_rts_cts && !mac->updating_rts_rate) { mac->updating_rts_rate = 1; netif_stop_queue(mac->netdev); - queue_work(zd_workqueue, &mac->set_rts_cts_work); + queue_delayed_work(zd_workqueue, &mac->set_rts_cts_work, 0); } if (need_set_rates && !mac->updating_basic_rates) { mac->updating_basic_rates = 1; netif_stop_queue(mac->netdev); - queue_work(zd_workqueue, &mac->set_basic_rates_work); + queue_delayed_work(zd_workqueue, &mac->set_basic_rates_work, + 0); } spin_unlock_irqrestore(&mac->lock, flags); } @@ -615,6 +659,9 @@ int zd_mac_get_range(struct zd_mac *mac, struct iw_range *range) range->we_version_compiled = WIRELESS_EXT; range->we_version_source = 20; + range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 | + IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP; + ZD_ASSERT(!irqs_disabled()); spin_lock_irq(&mac->lock); regdomain = mac->regdomain; @@ -927,7 +974,8 @@ static int is_data_packet_for_us(struct ieee80211_device *ieee, } return memcmp(hdr->addr1, netdev->dev_addr, ETH_ALEN) == 0 || - is_multicast_ether_addr(hdr->addr1) || + (is_multicast_ether_addr(hdr->addr1) && + memcmp(hdr->addr3, netdev->dev_addr, ETH_ALEN) != 0) || (netdev->flags & IFF_PROMISC); } @@ -1059,10 +1107,8 @@ int zd_mac_rx(struct zd_mac *mac, const u8 *buffer, unsigned int length) memcpy(skb_put(skb, length), buffer, length); r = ieee80211_rx(ieee, skb, &stats); - if (!r) { - ZD_ASSERT(in_irq()); - dev_kfree_skb_irq(skb); - } + if (!r) + dev_kfree_skb_any(skb); return 0; } @@ -1182,9 +1228,10 @@ struct iw_statistics *zd_mac_get_wireless_stats(struct net_device *ndev) #define LINK_LED_WORK_DELAY HZ -static void link_led_handler(void *p) +static void link_led_handler(struct work_struct *work) { - struct zd_mac *mac = p; + struct zd_mac *mac = + container_of(work, struct zd_mac, housekeeping.link_led_work.work); struct zd_chip *chip = &mac->chip; struct ieee80211softmac_device *sm = ieee80211_priv(mac->netdev); int is_associated; @@ -1205,7 +1252,7 @@ static void link_led_handler(void *p) static void housekeeping_init(struct zd_mac *mac) { - INIT_WORK(&mac->housekeeping.link_led_work, link_led_handler, mac); + INIT_DELAYED_WORK(&mac->housekeeping.link_led_work, link_led_handler); } static void housekeeping_enable(struct zd_mac *mac) diff --git a/trunk/drivers/net/wireless/zd1211rw/zd_mac.h b/trunk/drivers/net/wireless/zd1211rw/zd_mac.h index 5dcfb251f02e..f0cf05dc7d3e 100644 --- a/trunk/drivers/net/wireless/zd1211rw/zd_mac.h +++ b/trunk/drivers/net/wireless/zd1211rw/zd_mac.h @@ -119,7 +119,7 @@ struct rx_status { #define ZD_RX_ERROR 0x80 struct housekeeping { - struct work_struct link_led_work; + struct delayed_work link_led_work; }; #define ZD_MAC_STATS_BUFFER_SIZE 16 @@ -133,8 +133,10 @@ struct zd_mac { struct iw_statistics iw_stats; struct housekeeping housekeeping; - struct work_struct set_rts_cts_work; - struct work_struct set_basic_rates_work; + struct work_struct set_multicast_hash_work; + struct zd_mc_hash multicast_hash; + struct delayed_work set_rts_cts_work; + struct delayed_work set_basic_rates_work; unsigned int stats_count; u8 qual_buffer[ZD_MAC_STATS_BUFFER_SIZE]; @@ -189,6 +191,7 @@ int zd_mac_init_hw(struct zd_mac *mac, u8 device_type); int zd_mac_open(struct net_device *netdev); int zd_mac_stop(struct net_device *netdev); int zd_mac_set_mac_address(struct net_device *dev, void *p); +void zd_mac_set_multicast_list(struct net_device *netdev); int zd_mac_rx(struct zd_mac *mac, const u8 *buffer, unsigned int length); diff --git a/trunk/drivers/net/wireless/zd1211rw/zd_netdev.c b/trunk/drivers/net/wireless/zd1211rw/zd_netdev.c index 60f1b0f6d45b..8bda48de31ef 100644 --- a/trunk/drivers/net/wireless/zd1211rw/zd_netdev.c +++ b/trunk/drivers/net/wireless/zd1211rw/zd_netdev.c @@ -242,7 +242,7 @@ struct net_device *zd_netdev_alloc(struct usb_interface *intf) netdev->open = zd_mac_open; netdev->stop = zd_mac_stop; /* netdev->get_stats = */ - /* netdev->set_multicast_list = */ + netdev->set_multicast_list = zd_mac_set_multicast_list; netdev->set_mac_address = zd_mac_set_mac_address; netdev->wireless_handlers = &iw_handler_def; /* netdev->ethtool_ops = */ diff --git a/trunk/drivers/oprofile/buffer_sync.c b/trunk/drivers/oprofile/buffer_sync.c index 43e521e99126..78c2e6e4b42e 100644 --- a/trunk/drivers/oprofile/buffer_sync.c +++ b/trunk/drivers/oprofile/buffer_sync.c @@ -220,8 +220,8 @@ static unsigned long get_exec_dcookie(struct mm_struct * mm) continue; if (!(vma->vm_flags & VM_EXECUTABLE)) continue; - cookie = fast_get_dcookie(vma->vm_file->f_dentry, - vma->vm_file->f_vfsmnt); + cookie = fast_get_dcookie(vma->vm_file->f_path.dentry, + vma->vm_file->f_path.mnt); break; } @@ -246,8 +246,8 @@ static unsigned long lookup_dcookie(struct mm_struct * mm, unsigned long addr, o continue; if (vma->vm_file) { - cookie = fast_get_dcookie(vma->vm_file->f_dentry, - vma->vm_file->f_vfsmnt); + cookie = fast_get_dcookie(vma->vm_file->f_path.dentry, + vma->vm_file->f_path.mnt); *offset = (vma->vm_pgoff << PAGE_SHIFT) + addr - vma->vm_start; } else { diff --git a/trunk/drivers/oprofile/cpu_buffer.c b/trunk/drivers/oprofile/cpu_buffer.c index fc4bc9b94c74..a83c3db7d18f 100644 --- a/trunk/drivers/oprofile/cpu_buffer.c +++ b/trunk/drivers/oprofile/cpu_buffer.c @@ -29,7 +29,7 @@ struct oprofile_cpu_buffer cpu_buffer[NR_CPUS] __cacheline_aligned; -static void wq_sync_buffer(void *); +static void wq_sync_buffer(struct work_struct *work); #define DEFAULT_TIMER_EXPIRE (HZ / 10) static int work_enabled; @@ -65,7 +65,7 @@ int alloc_cpu_buffers(void) b->sample_received = 0; b->sample_lost_overflow = 0; b->cpu = i; - INIT_WORK(&b->work, wq_sync_buffer, b); + INIT_DELAYED_WORK(&b->work, wq_sync_buffer); } return 0; @@ -282,9 +282,10 @@ void oprofile_add_trace(unsigned long pc) * By using schedule_delayed_work_on and then schedule_delayed_work * we guarantee this will stay on the correct cpu */ -static void wq_sync_buffer(void * data) +static void wq_sync_buffer(struct work_struct *work) { - struct oprofile_cpu_buffer * b = data; + struct oprofile_cpu_buffer * b = + container_of(work, struct oprofile_cpu_buffer, work.work); if (b->cpu != smp_processor_id()) { printk("WQ on CPU%d, prefer CPU%d\n", smp_processor_id(), b->cpu); diff --git a/trunk/drivers/oprofile/cpu_buffer.h b/trunk/drivers/oprofile/cpu_buffer.h index 09abb80e0570..49900d9e3235 100644 --- a/trunk/drivers/oprofile/cpu_buffer.h +++ b/trunk/drivers/oprofile/cpu_buffer.h @@ -43,7 +43,7 @@ struct oprofile_cpu_buffer { unsigned long sample_lost_overflow; unsigned long backtrace_aborted; int cpu; - struct work_struct work; + struct delayed_work work; } ____cacheline_aligned; extern struct oprofile_cpu_buffer cpu_buffer[]; diff --git a/trunk/drivers/parport/parport_cs.c b/trunk/drivers/parport/parport_cs.c index b953d5907c05..e60b4bf6bae8 100644 --- a/trunk/drivers/parport/parport_cs.c +++ b/trunk/drivers/parport/parport_cs.c @@ -166,14 +166,6 @@ static int parport_config(struct pcmcia_device *link) tuple.TupleData = (cisdata_t *)buf; tuple.TupleOffset = 0; tuple.TupleDataMax = 255; - tuple.Attributes = 0; - tuple.DesiredTuple = CISTPL_CONFIG; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); - link->conf.ConfigBase = parse.config.base; - link->conf.Present = parse.config.rmask[0]; - tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; tuple.Attributes = 0; CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); @@ -263,6 +255,7 @@ void parport_cs_release(struct pcmcia_device *link) static struct pcmcia_device_id parport_ids[] = { PCMCIA_DEVICE_FUNC_ID(3), + PCMCIA_MFC_DEVICE_PROD_ID12(1,"Elan","Serial+Parallel Port: SP230",0x3beb8cf2,0xdb9e58bc), PCMCIA_DEVICE_MANF_CARD(0x0137, 0x0003), PCMCIA_DEVICE_NULL }; diff --git a/trunk/drivers/parport/parport_pc.c b/trunk/drivers/parport/parport_pc.c index 39c96641bc72..b61c17b3e298 100644 --- a/trunk/drivers/parport/parport_pc.c +++ b/trunk/drivers/parport/parport_pc.c @@ -1975,7 +1975,7 @@ static int __devinit parport_ECPPS2_supported(struct parport *pb){return 0;} /* --- IRQ detection -------------------------------------- */ /* Only if supports ECP mode */ -static int __devinit programmable_irq_support(struct parport *pb) +static int programmable_irq_support(struct parport *pb) { int irq, intrLine; unsigned char oecr = inb (ECONTROL (pb)); @@ -1992,7 +1992,7 @@ static int __devinit programmable_irq_support(struct parport *pb) return irq; } -static int __devinit irq_probe_ECP(struct parport *pb) +static int irq_probe_ECP(struct parport *pb) { int i; unsigned long irqs; @@ -2020,7 +2020,7 @@ static int __devinit irq_probe_ECP(struct parport *pb) * This detection seems that only works in National Semiconductors * This doesn't work in SMC, LGS, and Winbond */ -static int __devinit irq_probe_EPP(struct parport *pb) +static int irq_probe_EPP(struct parport *pb) { #ifndef ADVANCED_DETECT return PARPORT_IRQ_NONE; @@ -2059,7 +2059,7 @@ static int __devinit irq_probe_EPP(struct parport *pb) #endif /* Advanced detection */ } -static int __devinit irq_probe_SPP(struct parport *pb) +static int irq_probe_SPP(struct parport *pb) { /* Don't even try to do this. */ return PARPORT_IRQ_NONE; @@ -2747,6 +2747,7 @@ enum parport_pc_pci_cards { titan_1284p2, avlab_1p, avlab_2p, + oxsemi_952, oxsemi_954, oxsemi_840, aks_0100, @@ -2822,6 +2823,7 @@ static struct parport_pc_pci { /* avlab_2p */ { 2, { { 0, 1}, { 2, 3 },} }, /* The Oxford Semi cards are unusual: 954 doesn't support ECP, * and 840 locks up if you write 1 to bit 2! */ + /* oxsemi_952 */ { 1, { { 0, 1 }, } }, /* oxsemi_954 */ { 1, { { 0, -1 }, } }, /* oxsemi_840 */ { 1, { { 0, -1 }, } }, /* aks_0100 */ { 1, { { 0, -1 }, } }, @@ -2895,6 +2897,8 @@ static const struct pci_device_id parport_pc_pci_tbl[] = { /* PCI_VENDOR_ID_AVLAB/Intek21 has another bunch of cards ...*/ { 0x14db, 0x2120, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1p}, /* AFAVLAB_TK9902 */ { 0x14db, 0x2121, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_2p}, + { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI952PP, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, oxsemi_952 }, { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI954PP, PCI_ANY_ID, PCI_ANY_ID, 0, 0, oxsemi_954 }, { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_12PCI840, diff --git a/trunk/drivers/pci/hotplug/shpchp.h b/trunk/drivers/pci/hotplug/shpchp.h index ea2087c34149..50757695844f 100644 --- a/trunk/drivers/pci/hotplug/shpchp.h +++ b/trunk/drivers/pci/hotplug/shpchp.h @@ -70,7 +70,7 @@ struct slot { struct hotplug_slot *hotplug_slot; struct list_head slot_list; char name[SLOT_NAME_SIZE]; - struct work_struct work; /* work for button event */ + struct delayed_work work; /* work for button event */ struct mutex lock; }; @@ -187,7 +187,7 @@ extern int shpchp_configure_device(struct slot *p_slot); extern int shpchp_unconfigure_device(struct slot *p_slot); extern void shpchp_remove_ctrl_files(struct controller *ctrl); extern void cleanup_slots(struct controller *ctrl); -extern void queue_pushbutton_work(void *data); +extern void queue_pushbutton_work(struct work_struct *work); #ifdef CONFIG_ACPI diff --git a/trunk/drivers/pci/hotplug/shpchp_core.c b/trunk/drivers/pci/hotplug/shpchp_core.c index 235c18a22393..4eac85b3d90e 100644 --- a/trunk/drivers/pci/hotplug/shpchp_core.c +++ b/trunk/drivers/pci/hotplug/shpchp_core.c @@ -159,7 +159,7 @@ static int init_slots(struct controller *ctrl) goto error_info; slot->number = sun; - INIT_WORK(&slot->work, queue_pushbutton_work, slot); + INIT_DELAYED_WORK(&slot->work, queue_pushbutton_work); /* register this slot with the hotplug pci core */ hotplug_slot->private = slot; diff --git a/trunk/drivers/pci/hotplug/shpchp_ctrl.c b/trunk/drivers/pci/hotplug/shpchp_ctrl.c index c39901dbff20..158ac7836096 100644 --- a/trunk/drivers/pci/hotplug/shpchp_ctrl.c +++ b/trunk/drivers/pci/hotplug/shpchp_ctrl.c @@ -36,7 +36,7 @@ #include "../pci.h" #include "shpchp.h" -static void interrupt_event_handler(void *data); +static void interrupt_event_handler(struct work_struct *work); static int shpchp_enable_slot(struct slot *p_slot); static int shpchp_disable_slot(struct slot *p_slot); @@ -50,7 +50,7 @@ static int queue_interrupt_event(struct slot *p_slot, u32 event_type) info->event_type = event_type; info->p_slot = p_slot; - INIT_WORK(&info->work, interrupt_event_handler, info); + INIT_WORK(&info->work, interrupt_event_handler); schedule_work(&info->work); @@ -408,9 +408,10 @@ struct pushbutton_work_info { * Handles all pending events and exits. * */ -static void shpchp_pushbutton_thread(void *data) +static void shpchp_pushbutton_thread(struct work_struct *work) { - struct pushbutton_work_info *info = data; + struct pushbutton_work_info *info = + container_of(work, struct pushbutton_work_info, work); struct slot *p_slot = info->p_slot; mutex_lock(&p_slot->lock); @@ -436,9 +437,9 @@ static void shpchp_pushbutton_thread(void *data) kfree(info); } -void queue_pushbutton_work(void *data) +void queue_pushbutton_work(struct work_struct *work) { - struct slot *p_slot = data; + struct slot *p_slot = container_of(work, struct slot, work.work); struct pushbutton_work_info *info; info = kmalloc(sizeof(*info), GFP_KERNEL); @@ -447,7 +448,7 @@ void queue_pushbutton_work(void *data) return; } info->p_slot = p_slot; - INIT_WORK(&info->work, shpchp_pushbutton_thread, info); + INIT_WORK(&info->work, shpchp_pushbutton_thread); mutex_lock(&p_slot->lock); switch (p_slot->state) { @@ -541,9 +542,9 @@ static void handle_button_press_event(struct slot *p_slot) } } -static void interrupt_event_handler(void *data) +static void interrupt_event_handler(struct work_struct *work) { - struct event_info *info = data; + struct event_info *info = container_of(work, struct event_info, work); struct slot *p_slot = info->p_slot; mutex_lock(&p_slot->lock); diff --git a/trunk/drivers/pci/msi.c b/trunk/drivers/pci/msi.c index 9fc9a34ef24a..ed3f7e1a563c 100644 --- a/trunk/drivers/pci/msi.c +++ b/trunk/drivers/pci/msi.c @@ -26,7 +26,7 @@ static DEFINE_SPINLOCK(msi_lock); static struct msi_desc* msi_desc[NR_IRQS] = { [0 ... NR_IRQS-1] = NULL }; -static kmem_cache_t* msi_cachep; +static struct kmem_cache* msi_cachep; static int pci_msi_enable = 1; @@ -255,10 +255,8 @@ static void enable_msi_mode(struct pci_dev *dev, int pos, int type) pci_write_config_word(dev, msi_control_reg(pos), control); dev->msix_enabled = 1; } - if (pci_find_capability(dev, PCI_CAP_ID_EXP)) { - /* PCI Express Endpoint device detected */ - pci_intx(dev, 0); /* disable intx */ - } + + pci_intx(dev, 0); /* disable intx */ } void disable_msi_mode(struct pci_dev *dev, int pos, int type) @@ -276,10 +274,8 @@ void disable_msi_mode(struct pci_dev *dev, int pos, int type) pci_write_config_word(dev, msi_control_reg(pos), control); dev->msix_enabled = 0; } - if (pci_find_capability(dev, PCI_CAP_ID_EXP)) { - /* PCI Express Endpoint device detected */ - pci_intx(dev, 1); /* enable intx */ - } + + pci_intx(dev, 1); /* enable intx */ } static int msi_lookup_irq(struct pci_dev *dev, int type) diff --git a/trunk/drivers/pci/pcie/aer/aerdrv.c b/trunk/drivers/pci/pcie/aer/aerdrv.c index 04c43ef529ac..55866b6b26fa 100644 --- a/trunk/drivers/pci/pcie/aer/aerdrv.c +++ b/trunk/drivers/pci/pcie/aer/aerdrv.c @@ -160,7 +160,7 @@ static struct aer_rpc* aer_alloc_rpc(struct pcie_device *dev) rpc->e_lock = SPIN_LOCK_UNLOCKED; rpc->rpd = dev; - INIT_WORK(&rpc->dpc_handler, aer_isr, (void *)dev); + INIT_WORK(&rpc->dpc_handler, aer_isr); rpc->prod_idx = rpc->cons_idx = 0; mutex_init(&rpc->rpc_mutex); init_waitqueue_head(&rpc->wait_release); diff --git a/trunk/drivers/pci/pcie/aer/aerdrv.h b/trunk/drivers/pci/pcie/aer/aerdrv.h index daf0cad88fc8..3c0a58f64dd8 100644 --- a/trunk/drivers/pci/pcie/aer/aerdrv.h +++ b/trunk/drivers/pci/pcie/aer/aerdrv.h @@ -118,7 +118,7 @@ extern struct bus_type pcie_port_bus_type; extern void aer_enable_rootport(struct aer_rpc *rpc); extern void aer_delete_rootport(struct aer_rpc *rpc); extern int aer_init(struct pcie_device *dev); -extern void aer_isr(void *context); +extern void aer_isr(struct work_struct *work); extern void aer_print_error(struct pci_dev *dev, struct aer_err_info *info); extern int aer_osc_setup(struct pci_dev *dev); diff --git a/trunk/drivers/pci/pcie/aer/aerdrv_core.c b/trunk/drivers/pci/pcie/aer/aerdrv_core.c index 1c7e660d6535..08e13033ced8 100644 --- a/trunk/drivers/pci/pcie/aer/aerdrv_core.c +++ b/trunk/drivers/pci/pcie/aer/aerdrv_core.c @@ -690,14 +690,14 @@ static void aer_isr_one_error(struct pcie_device *p_device, /** * aer_isr - consume errors detected by root port - * @context: pointer to a private data of pcie device + * @work: definition of this work item * * Invoked, as DPC, when root port records new detected error **/ -void aer_isr(void *context) +void aer_isr(struct work_struct *work) { - struct pcie_device *p_device = (struct pcie_device *) context; - struct aer_rpc *rpc = get_service_data(p_device); + struct aer_rpc *rpc = container_of(work, struct aer_rpc, dpc_handler); + struct pcie_device *p_device = rpc->rpd; struct aer_err_source *e_src; mutex_lock(&rpc->rpc_mutex); diff --git a/trunk/drivers/pci/probe.c b/trunk/drivers/pci/probe.c index 0eeac60042b3..6a3c1e728900 100644 --- a/trunk/drivers/pci/probe.c +++ b/trunk/drivers/pci/probe.c @@ -873,6 +873,7 @@ void __devinit pci_device_add(struct pci_dev *dev, struct pci_bus *bus) dev->dev.release = pci_release_dev; pci_dev_get(dev); + set_dev_node(&dev->dev, pcibus_to_node(bus)); dev->dev.dma_mask = &dev->dma_mask; dev->dev.coherent_dma_mask = 0xffffffffull; diff --git a/trunk/drivers/pci/proc.c b/trunk/drivers/pci/proc.c index 99cf33379769..4a6760a3b31f 100644 --- a/trunk/drivers/pci/proc.c +++ b/trunk/drivers/pci/proc.c @@ -23,7 +23,7 @@ static loff_t proc_bus_pci_lseek(struct file *file, loff_t off, int whence) { loff_t new = -1; - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; mutex_lock(&inode->i_mutex); switch (whence) { @@ -48,7 +48,7 @@ proc_bus_pci_lseek(struct file *file, loff_t off, int whence) static ssize_t proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos) { - const struct inode *ino = file->f_dentry->d_inode; + const struct inode *ino = file->f_path.dentry->d_inode; const struct proc_dir_entry *dp = PDE(ino); struct pci_dev *dev = dp->data; unsigned int pos = *ppos; @@ -130,7 +130,7 @@ proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *pp static ssize_t proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, loff_t *ppos) { - const struct inode *ino = file->f_dentry->d_inode; + const struct inode *ino = file->f_path.dentry->d_inode; const struct proc_dir_entry *dp = PDE(ino); struct pci_dev *dev = dp->data; int pos = *ppos; @@ -245,7 +245,7 @@ static int proc_bus_pci_ioctl(struct inode *inode, struct file *file, unsigned i #ifdef HAVE_PCI_MMAP static int proc_bus_pci_mmap(struct file *file, struct vm_area_struct *vma) { - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; const struct proc_dir_entry *dp = PDE(inode); struct pci_dev *dev = dp->data; struct pci_filp_private *fpriv = file->private_data; diff --git a/trunk/drivers/pcmcia/at91_cf.c b/trunk/drivers/pcmcia/at91_cf.c index 3bcb7dc32995..52d4a38b3667 100644 --- a/trunk/drivers/pcmcia/at91_cf.c +++ b/trunk/drivers/pcmcia/at91_cf.c @@ -23,19 +23,20 @@ #include #include -#include #include #include +#include /* * A0..A10 work in each range; A23 indicates I/O space; A25 is CFRNW; * some other bit in {A24,A22..A11} is nREG to flag memory access * (vs attributes). So more than 2KB/region would just be waste. + * Note: These are offsets from the physical base address. */ -#define CF_ATTR_PHYS (AT91_CF_BASE) -#define CF_IO_PHYS (AT91_CF_BASE + (1 << 23)) -#define CF_MEM_PHYS (AT91_CF_BASE + 0x017ff800) +#define CF_ATTR_PHYS (0) +#define CF_IO_PHYS (1 << 23) +#define CF_MEM_PHYS (0x017ff800) /*--------------------------------------------------------------------------*/ @@ -48,6 +49,8 @@ struct at91_cf_socket { struct platform_device *pdev; struct at91_cf_data *board; + + unsigned long phys_baseaddr; }; #define SZ_2K (2 * SZ_1K) @@ -154,9 +157,8 @@ static int at91_cf_set_io_map(struct pcmcia_socket *s, struct pccard_io_map *io) /* * Use 16 bit accesses unless/until we need 8-bit i/o space. - * Always set CSR4 ... PCMCIA won't always unmap things. */ - csr = at91_sys_read(AT91_SMC_CSR(4)) & ~AT91_SMC_DBW; + csr = at91_sys_read(AT91_SMC_CSR(cf->board->chipselect)) & ~AT91_SMC_DBW; /* * NOTE: this CF controller ignores IOIS16, so we can't really do @@ -168,14 +170,14 @@ static int at91_cf_set_io_map(struct pcmcia_socket *s, struct pccard_io_map *io) * some cards only like that way to get at the odd byte, despite * CF 3.0 spec table 35 also giving the D8-D15 option. */ - if (!(io->flags & (MAP_16BIT|MAP_AUTOSZ))) { + if (!(io->flags & (MAP_16BIT | MAP_AUTOSZ))) { csr |= AT91_SMC_DBW_8; pr_debug("%s: 8bit i/o bus\n", driver_name); } else { csr |= AT91_SMC_DBW_16; pr_debug("%s: 16bit i/o bus\n", driver_name); } - at91_sys_write(AT91_SMC_CSR(4), csr); + at91_sys_write(AT91_SMC_CSR(cf->board->chipselect), csr); io->start = cf->socket.io_offset; io->stop = io->start + SZ_2K - 1; @@ -194,11 +196,11 @@ at91_cf_set_mem_map(struct pcmcia_socket *s, struct pccard_mem_map *map) cf = container_of(s, struct at91_cf_socket, socket); - map->flags &= MAP_ACTIVE|MAP_ATTRIB|MAP_16BIT; + map->flags &= (MAP_ACTIVE | MAP_ATTRIB | MAP_16BIT); if (map->flags & MAP_ATTRIB) - map->static_start = CF_ATTR_PHYS; + map->static_start = cf->phys_baseaddr + CF_ATTR_PHYS; else - map->static_start = CF_MEM_PHYS; + map->static_start = cf->phys_baseaddr + CF_MEM_PHYS; return 0; } @@ -219,7 +221,6 @@ static int __init at91_cf_probe(struct platform_device *pdev) struct at91_cf_socket *cf; struct at91_cf_data *board = pdev->dev.platform_data; struct resource *io; - unsigned int csa; int status; if (!board || !board->det_pin || !board->rst_pin) @@ -235,33 +236,11 @@ static int __init at91_cf_probe(struct platform_device *pdev) cf->board = board; cf->pdev = pdev; + cf->phys_baseaddr = io->start; platform_set_drvdata(pdev, cf); - /* CF takes over CS4, CS5, CS6 */ - csa = at91_sys_read(AT91_EBI_CSA); - at91_sys_write(AT91_EBI_CSA, csa | AT91_EBI_CS4A_SMC_COMPACTFLASH); - - /* nWAIT is _not_ a default setting */ - (void) at91_set_A_periph(AT91_PIN_PC6, 1); /* nWAIT */ - - /* - * Static memory controller timing adjustments. - * REVISIT: these timings are in terms of MCK cycles, so - * when MCK changes (cpufreq etc) so must these values... - */ - at91_sys_write(AT91_SMC_CSR(4), - AT91_SMC_ACSS_STD - | AT91_SMC_DBW_16 - | AT91_SMC_BAT - | AT91_SMC_WSEN - | AT91_SMC_NWS_(32) /* wait states */ - | AT91_SMC_RWSETUP_(6) /* setup time */ - | AT91_SMC_RWHOLD_(4) /* hold time */ - ); - /* must be a GPIO; ergo must trigger on both edges */ - status = request_irq(board->det_pin, at91_cf_irq, - IRQF_SAMPLE_RANDOM, driver_name, cf); + status = request_irq(board->det_pin, at91_cf_irq, 0, driver_name, cf); if (status < 0) goto fail0; device_init_wakeup(&pdev->dev, 1); @@ -282,14 +261,18 @@ static int __init at91_cf_probe(struct platform_device *pdev) cf->socket.pci_irq = NR_IRQS + 1; /* pcmcia layer only remaps "real" memory not iospace */ - cf->socket.io_offset = (unsigned long) ioremap(CF_IO_PHYS, SZ_2K); - if (!cf->socket.io_offset) + cf->socket.io_offset = (unsigned long) ioremap(cf->phys_baseaddr + CF_IO_PHYS, SZ_2K); + if (!cf->socket.io_offset) { + status = -ENXIO; goto fail1; + } - /* reserve CS4, CS5, and CS6 regions; but use just CS4 */ + /* reserve chip-select regions */ if (!request_mem_region(io->start, io->end + 1 - io->start, - driver_name)) + driver_name)) { + status = -ENXIO; goto fail1; + } pr_info("%s: irqs det #%d, io #%d\n", driver_name, board->det_pin, board->irq_pin); @@ -319,9 +302,7 @@ static int __init at91_cf_probe(struct platform_device *pdev) fail0a: device_init_wakeup(&pdev->dev, 0); free_irq(board->det_pin, cf); - device_init_wakeup(&pdev->dev, 0); fail0: - at91_sys_write(AT91_EBI_CSA, csa); kfree(cf); return status; } @@ -331,19 +312,15 @@ static int __exit at91_cf_remove(struct platform_device *pdev) struct at91_cf_socket *cf = platform_get_drvdata(pdev); struct at91_cf_data *board = cf->board; struct resource *io = cf->socket.io[0].res; - unsigned int csa; pcmcia_unregister_socket(&cf->socket); if (board->irq_pin) free_irq(board->irq_pin, cf); - free_irq(board->det_pin, cf); device_init_wakeup(&pdev->dev, 0); + free_irq(board->det_pin, cf); iounmap((void __iomem *) cf->socket.io_offset); release_mem_region(io->start, io->end + 1 - io->start); - csa = at91_sys_read(AT91_EBI_CSA); - at91_sys_write(AT91_EBI_CSA, csa & ~AT91_EBI_CS4A); - kfree(cf); return 0; } diff --git a/trunk/drivers/pcmcia/cs.c b/trunk/drivers/pcmcia/cs.c index f9cd831a3f31..606a46740338 100644 --- a/trunk/drivers/pcmcia/cs.c +++ b/trunk/drivers/pcmcia/cs.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include diff --git a/trunk/drivers/pcmcia/cs_internal.h b/trunk/drivers/pcmcia/cs_internal.h index d6164cd583fd..f573ea04db6f 100644 --- a/trunk/drivers/pcmcia/cs_internal.h +++ b/trunk/drivers/pcmcia/cs_internal.h @@ -135,7 +135,7 @@ int pccard_get_status(struct pcmcia_socket *s, struct pcmcia_device *p_dev, cs_s struct pcmcia_callback{ struct module *owner; int (*event) (struct pcmcia_socket *s, event_t event, int priority); - void (*requery) (struct pcmcia_socket *s); + void (*requery) (struct pcmcia_socket *s, int new_cis); int (*suspend) (struct pcmcia_socket *s); int (*resume) (struct pcmcia_socket *s); }; diff --git a/trunk/drivers/pcmcia/ds.c b/trunk/drivers/pcmcia/ds.c index 21d83a895b21..7355eb455a88 100644 --- a/trunk/drivers/pcmcia/ds.c +++ b/trunk/drivers/pcmcia/ds.c @@ -231,65 +231,6 @@ static void pcmcia_check_driver(struct pcmcia_driver *p_drv) } -#ifdef CONFIG_PCMCIA_LOAD_CIS - -/** - * pcmcia_load_firmware - load CIS from userspace if device-provided is broken - * @dev - the pcmcia device which needs a CIS override - * @filename - requested filename in /lib/firmware/ - * - * This uses the in-kernel firmware loading mechanism to use a "fake CIS" if - * the one provided by the card is broken. The firmware files reside in - * /lib/firmware/ in userspace. - */ -static int pcmcia_load_firmware(struct pcmcia_device *dev, char * filename) -{ - struct pcmcia_socket *s = dev->socket; - const struct firmware *fw; - char path[20]; - int ret=-ENOMEM; - cisdump_t *cis; - - if (!filename) - return -EINVAL; - - ds_dbg(1, "trying to load firmware %s\n", filename); - - if (strlen(filename) > 14) - return -EINVAL; - - snprintf(path, 20, "%s", filename); - - if (request_firmware(&fw, path, &dev->dev) == 0) { - if (fw->size >= CISTPL_MAX_CIS_SIZE) - goto release; - - cis = kzalloc(sizeof(cisdump_t), GFP_KERNEL); - if (!cis) - goto release; - - cis->Length = fw->size + 1; - memcpy(cis->Data, fw->data, fw->size); - - if (!pcmcia_replace_cis(s, cis)) - ret = 0; - } - release: - release_firmware(fw); - - return (ret); -} - -#else /* !CONFIG_PCMCIA_LOAD_CIS */ - -static inline int pcmcia_load_firmware(struct pcmcia_device *dev, char * filename) -{ - return -ENODEV; -} - -#endif - - /*======================================================================*/ @@ -309,6 +250,8 @@ int pcmcia_register_driver(struct pcmcia_driver *driver) driver->drv.bus = &pcmcia_bus_type; driver->drv.owner = driver->owner; + ds_dbg(3, "registering driver %s\n", driver->drv.name); + return driver_register(&driver->drv); } EXPORT_SYMBOL(pcmcia_register_driver); @@ -318,6 +261,7 @@ EXPORT_SYMBOL(pcmcia_register_driver); */ void pcmcia_unregister_driver(struct pcmcia_driver *driver) { + ds_dbg(3, "unregistering driver %s\n", driver->drv.name); driver_unregister(&driver->drv); } EXPORT_SYMBOL(pcmcia_unregister_driver); @@ -343,23 +287,27 @@ void pcmcia_put_dev(struct pcmcia_device *p_dev) static void pcmcia_release_function(struct kref *ref) { struct config_t *c = container_of(ref, struct config_t, ref); + ds_dbg(1, "releasing config_t\n"); kfree(c); } static void pcmcia_release_dev(struct device *dev) { struct pcmcia_device *p_dev = to_pcmcia_dev(dev); - ds_dbg(1, "releasing dev %p\n", p_dev); + ds_dbg(1, "releasing device %s\n", p_dev->dev.bus_id); pcmcia_put_socket(p_dev->socket); kfree(p_dev->devname); kref_put(&p_dev->function_config->ref, pcmcia_release_function); kfree(p_dev); } -static void pcmcia_add_pseudo_device(struct pcmcia_socket *s) +static void pcmcia_add_device_later(struct pcmcia_socket *s, int mfc) { if (!s->pcmcia_state.device_add_pending) { + ds_dbg(1, "scheduling to add %s secondary" + " device to %d\n", mfc ? "mfc" : "pfc", s->sock); s->pcmcia_state.device_add_pending = 1; + s->pcmcia_state.mfc_pfc = mfc; schedule_work(&s->device_add); } return; @@ -371,6 +319,7 @@ static int pcmcia_device_probe(struct device * dev) struct pcmcia_driver *p_drv; struct pcmcia_device_id *did; struct pcmcia_socket *s; + cistpl_config_t cis_config; int ret = 0; dev = get_device(dev); @@ -381,15 +330,33 @@ static int pcmcia_device_probe(struct device * dev) p_drv = to_pcmcia_drv(dev->driver); s = p_dev->socket; + ds_dbg(1, "trying to bind %s to %s\n", p_dev->dev.bus_id, + p_drv->drv.name); + if ((!p_drv->probe) || (!p_dev->function_config) || (!try_module_get(p_drv->owner))) { ret = -EINVAL; goto put_dev; } + /* set up some more device information */ + ret = pccard_read_tuple(p_dev->socket, p_dev->func, CISTPL_CONFIG, + &cis_config); + if (!ret) { + p_dev->conf.ConfigBase = cis_config.base; + p_dev->conf.Present = cis_config.rmask[0]; + } else { + printk(KERN_INFO "pcmcia: could not parse base and rmask0 of CIS\n"); + p_dev->conf.ConfigBase = 0; + p_dev->conf.Present = 0; + } + ret = p_drv->probe(p_dev); - if (ret) + if (ret) { + ds_dbg(1, "binding %s to %s failed with %d\n", + p_dev->dev.bus_id, p_drv->drv.name, ret); goto put_module; + } /* handle pseudo multifunction devices: * there are at most two pseudo multifunction devices. @@ -400,7 +367,7 @@ static int pcmcia_device_probe(struct device * dev) did = p_dev->dev.driver_data; if (did && (did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) && (p_dev->socket->device_count == 1) && (p_dev->device_no == 0)) - pcmcia_add_pseudo_device(p_dev->socket); + pcmcia_add_device_later(p_dev->socket, 0); put_module: if (ret) @@ -421,8 +388,8 @@ static void pcmcia_card_remove(struct pcmcia_socket *s, struct pcmcia_device *le struct pcmcia_device *tmp; unsigned long flags; - ds_dbg(2, "unbind_request(%d)\n", s->sock); - + ds_dbg(2, "pcmcia_card_remove(%d) %s\n", s->sock, + leftover ? leftover->devname : ""); if (!leftover) s->device_count = 0; @@ -439,6 +406,7 @@ static void pcmcia_card_remove(struct pcmcia_socket *s, struct pcmcia_device *le p_dev->_removed=1; spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); + ds_dbg(2, "unregistering device %s\n", p_dev->dev.bus_id); device_unregister(&p_dev->dev); } @@ -455,6 +423,8 @@ static int pcmcia_device_remove(struct device * dev) p_dev = to_pcmcia_dev(dev); p_drv = to_pcmcia_drv(dev->driver); + ds_dbg(1, "removing device %s\n", p_dev->dev.bus_id); + /* If we're removing the primary module driving a * pseudo multi-function card, we need to unbind * all devices @@ -587,8 +557,10 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f mutex_lock(&device_add_lock); - /* max of 2 devices per card */ - if (s->device_count == 2) + ds_dbg(3, "adding device to %d, function %d\n", s->sock, function); + + /* max of 4 devices per card */ + if (s->device_count == 4) goto err_put; p_dev = kzalloc(sizeof(struct pcmcia_device), GFP_KERNEL); @@ -598,8 +570,6 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f p_dev->socket = s; p_dev->device_no = (s->device_count++); p_dev->func = function; - if (s->functions <= function) - s->functions = function + 1; p_dev->dev.bus = &pcmcia_bus_type; p_dev->dev.parent = s->dev.dev; @@ -610,8 +580,8 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f if (!p_dev->devname) goto err_free; sprintf (p_dev->devname, "pcmcia%s", p_dev->dev.bus_id); + ds_dbg(3, "devname is %s\n", p_dev->devname); - /* compat */ spin_lock_irqsave(&pcmcia_dev_list_lock, flags); /* @@ -631,6 +601,7 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); if (!p_dev->function_config) { + ds_dbg(3, "creating config_t for %s\n", p_dev->dev.bus_id); p_dev->function_config = kzalloc(sizeof(struct config_t), GFP_KERNEL); if (!p_dev->function_config) @@ -674,11 +645,16 @@ static int pcmcia_card_add(struct pcmcia_socket *s) unsigned int no_funcs, i; int ret = 0; - if (!(s->resource_setup_done)) + if (!(s->resource_setup_done)) { + ds_dbg(3, "no resources available, delaying card_add\n"); return -EAGAIN; /* try again, but later... */ + } - if (pcmcia_validate_mem(s)) + if (pcmcia_validate_mem(s)) { + ds_dbg(3, "validating mem resources failed, " + "delaying card_add\n"); return -EAGAIN; /* try again, but later... */ + } ret = pccard_validate_cis(s, BIND_FN_ALL, &cisinfo); if (ret || !cisinfo.Chains) { @@ -690,6 +666,7 @@ static int pcmcia_card_add(struct pcmcia_socket *s) no_funcs = mfc.nfn; else no_funcs = 1; + s->functions = no_funcs; for (i=0; i < no_funcs; i++) pcmcia_device_add(s, i); @@ -698,38 +675,50 @@ static int pcmcia_card_add(struct pcmcia_socket *s) } -static void pcmcia_delayed_add_pseudo_device(void *data) +static void pcmcia_delayed_add_device(struct work_struct *work) { - struct pcmcia_socket *s = data; - pcmcia_device_add(s, 0); + struct pcmcia_socket *s = + container_of(work, struct pcmcia_socket, device_add); + ds_dbg(1, "adding additional device to %d\n", s->sock); + pcmcia_device_add(s, s->pcmcia_state.mfc_pfc); s->pcmcia_state.device_add_pending = 0; + s->pcmcia_state.mfc_pfc = 0; } static int pcmcia_requery(struct device *dev, void * _data) { struct pcmcia_device *p_dev = to_pcmcia_dev(dev); - if (!p_dev->dev.driver) + if (!p_dev->dev.driver) { + ds_dbg(1, "update device information for %s\n", + p_dev->dev.bus_id); pcmcia_device_query(p_dev); + } return 0; } -static void pcmcia_bus_rescan(struct pcmcia_socket *skt) +static void pcmcia_bus_rescan(struct pcmcia_socket *skt, int new_cis) { - int no_devices=0; + int no_devices = 0; int ret = 0; unsigned long flags; /* must be called with skt_mutex held */ + ds_dbg(0, "re-scanning socket %d\n", skt->sock); + spin_lock_irqsave(&pcmcia_dev_list_lock, flags); if (list_empty(&skt->devices_list)) - no_devices=1; + no_devices = 1; spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); + /* If this is because of a CIS override, start over */ + if (new_cis && !no_devices) + pcmcia_card_remove(skt, NULL); + /* if no devices were added for this socket yet because of * missing resource information or other trouble, we need to * do this now. */ - if (no_devices) { + if (no_devices || new_cis) { ret = pcmcia_card_add(skt); if (ret) return; @@ -747,6 +736,97 @@ static void pcmcia_bus_rescan(struct pcmcia_socket *skt) printk(KERN_INFO "pcmcia: bus_rescan_devices failed\n"); } +#ifdef CONFIG_PCMCIA_LOAD_CIS + +/** + * pcmcia_load_firmware - load CIS from userspace if device-provided is broken + * @dev - the pcmcia device which needs a CIS override + * @filename - requested filename in /lib/firmware/ + * + * This uses the in-kernel firmware loading mechanism to use a "fake CIS" if + * the one provided by the card is broken. The firmware files reside in + * /lib/firmware/ in userspace. + */ +static int pcmcia_load_firmware(struct pcmcia_device *dev, char * filename) +{ + struct pcmcia_socket *s = dev->socket; + const struct firmware *fw; + char path[20]; + int ret = -ENOMEM; + int no_funcs; + int old_funcs; + cisdump_t *cis; + cistpl_longlink_mfc_t mfc; + + if (!filename) + return -EINVAL; + + ds_dbg(1, "trying to load CIS file %s\n", filename); + + if (strlen(filename) > 14) { + printk(KERN_WARNING "pcmcia: CIS filename is too long\n"); + return -EINVAL; + } + + snprintf(path, 20, "%s", filename); + + if (request_firmware(&fw, path, &dev->dev) == 0) { + if (fw->size >= CISTPL_MAX_CIS_SIZE) { + ret = -EINVAL; + printk(KERN_ERR "pcmcia: CIS override is too big\n"); + goto release; + } + + cis = kzalloc(sizeof(cisdump_t), GFP_KERNEL); + if (!cis) { + ret = -ENOMEM; + goto release; + } + + cis->Length = fw->size + 1; + memcpy(cis->Data, fw->data, fw->size); + + if (!pcmcia_replace_cis(s, cis)) + ret = 0; + else { + printk(KERN_ERR "pcmcia: CIS override failed\n"); + goto release; + } + + + /* update information */ + pcmcia_device_query(dev); + + /* does this cis override add or remove functions? */ + old_funcs = s->functions; + + if (!pccard_read_tuple(s, BIND_FN_ALL, CISTPL_LONGLINK_MFC, &mfc)) + no_funcs = mfc.nfn; + else + no_funcs = 1; + s->functions = no_funcs; + + if (old_funcs > no_funcs) + pcmcia_card_remove(s, dev); + else if (no_funcs > old_funcs) + pcmcia_add_device_later(s, 1); + } + release: + release_firmware(fw); + + return (ret); +} + +#else /* !CONFIG_PCMCIA_LOAD_CIS */ + +static inline int pcmcia_load_firmware(struct pcmcia_device *dev, char * filename) +{ + return -ENODEV; +} + +#endif + + static inline int pcmcia_devmatch(struct pcmcia_device *dev, struct pcmcia_device_id *did) { @@ -813,11 +893,14 @@ static inline int pcmcia_devmatch(struct pcmcia_device *dev, * after it has re-checked that there is no possible module * with a prod_id/manf_id/card_id match. */ + ds_dbg(0, "skipping FUNC_ID match for %s until userspace " + "interaction\n", dev->dev.bus_id); if (!dev->allow_func_id_match) return 0; } if (did->match_flags & PCMCIA_DEV_ID_MATCH_FAKE_CIS) { + ds_dbg(0, "device %s needs a fake CIS\n", dev->dev.bus_id); if (!dev->socket->fake_cis) pcmcia_load_firmware(dev, did->cisfile); @@ -847,13 +930,21 @@ static int pcmcia_bus_match(struct device * dev, struct device_driver * drv) { #ifdef CONFIG_PCMCIA_IOCTL /* matching by cardmgr */ - if (p_dev->cardmgr == p_drv) + if (p_dev->cardmgr == p_drv) { + ds_dbg(0, "cardmgr matched %s to %s\n", dev->bus_id, + drv->name); return 1; + } #endif while (did && did->match_flags) { - if (pcmcia_devmatch(p_dev, did)) + ds_dbg(3, "trying to match %s to %s\n", dev->bus_id, + drv->name); + if (pcmcia_devmatch(p_dev, did)) { + ds_dbg(0, "matched %s to %s\n", dev->bus_id, + drv->name); return 1; + } did++; } @@ -1044,6 +1135,8 @@ static int pcmcia_dev_suspend(struct device * dev, pm_message_t state) struct pcmcia_driver *p_drv = NULL; int ret = 0; + ds_dbg(2, "suspending %s\n", dev->bus_id); + if (dev->driver) p_drv = to_pcmcia_drv(dev->driver); @@ -1052,12 +1145,18 @@ static int pcmcia_dev_suspend(struct device * dev, pm_message_t state) if (p_drv->suspend) { ret = p_drv->suspend(p_dev); - if (ret) + if (ret) { + printk(KERN_ERR "pcmcia: device %s (driver %s) did " + "not want to go to sleep (%d)\n", + p_dev->devname, p_drv->drv.name, ret); goto out; + } } - if (p_dev->device_no == p_dev->func) + if (p_dev->device_no == p_dev->func) { + ds_dbg(2, "releasing configuration for %s\n", dev->bus_id); pcmcia_release_configuration(p_dev); + } out: if (!ret) @@ -1072,6 +1171,8 @@ static int pcmcia_dev_resume(struct device * dev) struct pcmcia_driver *p_drv = NULL; int ret = 0; + ds_dbg(2, "resuming %s\n", dev->bus_id); + if (dev->driver) p_drv = to_pcmcia_drv(dev->driver); @@ -1079,6 +1180,7 @@ static int pcmcia_dev_resume(struct device * dev) goto out; if (p_dev->device_no == p_dev->func) { + ds_dbg(2, "requesting configuration for %s\n", dev->bus_id); ret = pcmcia_request_configuration(p_dev, &p_dev->conf); if (ret) goto out; @@ -1120,12 +1222,14 @@ static int pcmcia_bus_resume_callback(struct device *dev, void * _data) static int pcmcia_bus_resume(struct pcmcia_socket *skt) { + ds_dbg(2, "resuming socket %d\n", skt->sock); bus_for_each_dev(&pcmcia_bus_type, NULL, skt, pcmcia_bus_resume_callback); return 0; } static int pcmcia_bus_suspend(struct pcmcia_socket *skt) { + ds_dbg(2, "suspending socket %d\n", skt->sock); if (bus_for_each_dev(&pcmcia_bus_type, NULL, skt, pcmcia_bus_suspend_callback)) { pcmcia_bus_resume(skt); @@ -1246,7 +1350,7 @@ static int __devinit pcmcia_bus_add_socket(struct class_device *class_dev, init_waitqueue_head(&socket->queue); #endif INIT_LIST_HEAD(&socket->devices_list); - INIT_WORK(&socket->device_add, pcmcia_delayed_add_pseudo_device, socket); + INIT_WORK(&socket->device_add, pcmcia_delayed_add_device); memset(&socket->pcmcia_state, 0, sizeof(u8)); socket->device_count = 0; diff --git a/trunk/drivers/pcmcia/m32r_cfc.c b/trunk/drivers/pcmcia/m32r_cfc.c index 36fdaa58458c..3c22ac4625c2 100644 --- a/trunk/drivers/pcmcia/m32r_cfc.c +++ b/trunk/drivers/pcmcia/m32r_cfc.c @@ -398,7 +398,7 @@ static irqreturn_t pcc_interrupt(int irq, void *dev) static void pcc_interrupt_wrapper(u_long data) { debug(3, "m32r_cfc: pcc_interrupt_wrapper:\n"); - pcc_interrupt(0, NULL, NULL); + pcc_interrupt(0, NULL); init_timer(&poll_timer); poll_timer.expires = jiffies + poll_interval; add_timer(&poll_timer); diff --git a/trunk/drivers/pcmcia/pcmcia_ioctl.c b/trunk/drivers/pcmcia/pcmcia_ioctl.c index 310ede575caa..327372b7a54e 100644 --- a/trunk/drivers/pcmcia/pcmcia_ioctl.c +++ b/trunk/drivers/pcmcia/pcmcia_ioctl.c @@ -486,7 +486,7 @@ static ssize_t ds_read(struct file *file, char __user *buf, user_info_t *user; int ret; - ds_dbg(2, "ds_read(socket %d)\n", iminor(file->f_dentry->d_inode)); + ds_dbg(2, "ds_read(socket %d)\n", iminor(file->f_path.dentry->d_inode)); if (count < 4) return -EINVAL; @@ -511,7 +511,7 @@ static ssize_t ds_read(struct file *file, char __user *buf, static ssize_t ds_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { - ds_dbg(2, "ds_write(socket %d)\n", iminor(file->f_dentry->d_inode)); + ds_dbg(2, "ds_write(socket %d)\n", iminor(file->f_path.dentry->d_inode)); if (count != 4) return -EINVAL; @@ -529,7 +529,7 @@ static u_int ds_poll(struct file *file, poll_table *wait) struct pcmcia_socket *s; user_info_t *user; - ds_dbg(2, "ds_poll(socket %d)\n", iminor(file->f_dentry->d_inode)); + ds_dbg(2, "ds_poll(socket %d)\n", iminor(file->f_path.dentry->d_inode)); user = file->private_data; if (CHECK_USER(user)) @@ -594,7 +594,12 @@ static int ds_ioctl(struct inode * inode, struct file * file, err = ret = 0; - if (cmd & IOC_IN) __copy_from_user((char *)buf, uarg, size); + if (cmd & IOC_IN) { + if (__copy_from_user((char *)buf, uarg, size)) { + err = -EFAULT; + goto free_out; + } + } switch (cmd) { case DS_ADJUST_RESOURCE_INFO: diff --git a/trunk/drivers/pcmcia/pd6729.c b/trunk/drivers/pcmcia/pd6729.c index a70f97fdbbdd..360c24896548 100644 --- a/trunk/drivers/pcmcia/pd6729.c +++ b/trunk/drivers/pcmcia/pd6729.c @@ -581,10 +581,10 @@ static irqreturn_t pd6729_test(int irq, void *dev) return IRQ_HANDLED; } -static int pd6729_check_irq(int irq, int flags) +static int pd6729_check_irq(int irq) { - if (request_irq(irq, pd6729_test, flags, "x", pd6729_test) != 0) - return -1; + if (request_irq(irq, pd6729_test, IRQF_PROBE_SHARED, "x", pd6729_test) + != 0) return -1; free_irq(irq, pd6729_test); return 0; } @@ -610,7 +610,7 @@ static u_int __devinit pd6729_isa_scan(void) /* just find interrupts that aren't in use */ for (i = 0; i < 16; i++) - if ((mask0 & (1 << i)) && (pd6729_check_irq(i, 0) == 0)) + if ((mask0 & (1 << i)) && (pd6729_check_irq(i) == 0)) mask |= (1 << i); printk(KERN_INFO "pd6729: ISA irqs = "); diff --git a/trunk/drivers/pcmcia/socket_sysfs.c b/trunk/drivers/pcmcia/socket_sysfs.c index 933cd864a5c9..b005602d6b53 100644 --- a/trunk/drivers/pcmcia/socket_sysfs.c +++ b/trunk/drivers/pcmcia/socket_sysfs.c @@ -188,7 +188,7 @@ static ssize_t pccard_store_resource(struct class_device *dev, const char *buf, (s->state & SOCKET_PRESENT) && !(s->state & SOCKET_CARDBUS)) { if (try_module_get(s->callback->owner)) { - s->callback->requery(s); + s->callback->requery(s, 0); module_put(s->callback->owner); } } @@ -325,7 +325,7 @@ static ssize_t pccard_store_cis(struct kobject *kobj, char *buf, loff_t off, siz if ((s->callback) && (s->state & SOCKET_PRESENT) && !(s->state & SOCKET_CARDBUS)) { if (try_module_get(s->callback->owner)) { - s->callback->requery(s); + s->callback->requery(s, 1); module_put(s->callback->owner); } } diff --git a/trunk/drivers/pnp/card.c b/trunk/drivers/pnp/card.c index 227600cd6360..91c047a7e635 100644 --- a/trunk/drivers/pnp/card.c +++ b/trunk/drivers/pnp/card.c @@ -164,9 +164,17 @@ static DEVICE_ATTR(card_id,S_IRUGO,pnp_show_card_ids,NULL); static int pnp_interface_attach_card(struct pnp_card *card) { - device_create_file(&card->dev,&dev_attr_name); - device_create_file(&card->dev,&dev_attr_card_id); + int rc = device_create_file(&card->dev,&dev_attr_name); + if (rc) return rc; + + rc = device_create_file(&card->dev,&dev_attr_card_id); + if (rc) goto err_name; + return 0; + +err_name: + device_remove_file(&card->dev,&dev_attr_name); + return rc; } /** @@ -306,16 +314,20 @@ struct pnp_dev * pnp_request_card_device(struct pnp_card_link *clink, const char down_write(&dev->dev.bus->subsys.rwsem); dev->card_link = clink; dev->dev.driver = &drv->link.driver; - if (pnp_bus_type.probe(&dev->dev)) { - dev->dev.driver = NULL; - dev->card_link = NULL; - up_write(&dev->dev.bus->subsys.rwsem); - return NULL; - } - device_bind_driver(&dev->dev); + if (pnp_bus_type.probe(&dev->dev)) + goto err_out; + if (device_bind_driver(&dev->dev)) + goto err_out; + up_write(&dev->dev.bus->subsys.rwsem); return dev; + +err_out: + dev->dev.driver = NULL; + dev->card_link = NULL; + up_write(&dev->dev.bus->subsys.rwsem); + return NULL; } /** diff --git a/trunk/drivers/pnp/interface.c b/trunk/drivers/pnp/interface.c index 9d8b415eca79..ac9fcd499f3f 100644 --- a/trunk/drivers/pnp/interface.c +++ b/trunk/drivers/pnp/interface.c @@ -461,8 +461,19 @@ static DEVICE_ATTR(id,S_IRUGO,pnp_show_current_ids,NULL); int pnp_interface_attach_device(struct pnp_dev *dev) { - device_create_file(&dev->dev,&dev_attr_options); - device_create_file(&dev->dev,&dev_attr_resources); - device_create_file(&dev->dev,&dev_attr_id); + int rc = device_create_file(&dev->dev,&dev_attr_options); + if (rc) goto err; + rc = device_create_file(&dev->dev,&dev_attr_resources); + if (rc) goto err_opt; + rc = device_create_file(&dev->dev,&dev_attr_id); + if (rc) goto err_res; + return 0; + +err_res: + device_remove_file(&dev->dev,&dev_attr_resources); +err_opt: + device_remove_file(&dev->dev,&dev_attr_options); +err: + return rc; } diff --git a/trunk/drivers/pnp/isapnp/proc.c b/trunk/drivers/pnp/isapnp/proc.c index 958c11bedd0d..d21f3c1e72fc 100644 --- a/trunk/drivers/pnp/isapnp/proc.c +++ b/trunk/drivers/pnp/isapnp/proc.c @@ -56,7 +56,7 @@ static loff_t isapnp_proc_bus_lseek(struct file *file, loff_t off, int whence) static ssize_t isapnp_proc_bus_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos) { - struct inode *ino = file->f_dentry->d_inode; + struct inode *ino = file->f_path.dentry->d_inode; struct proc_dir_entry *dp = PDE(ino); struct pnp_dev *dev = dp->data; int pos = *ppos; diff --git a/trunk/drivers/pnp/pnpbios/core.c b/trunk/drivers/pnp/pnpbios/core.c index 81a6c83d89a6..33adeba1a31f 100644 --- a/trunk/drivers/pnp/pnpbios/core.c +++ b/trunk/drivers/pnp/pnpbios/core.c @@ -61,6 +61,7 @@ #include #include #include +#include #include #include @@ -530,7 +531,8 @@ static int __init pnpbios_init(void) if (check_legacy_ioport(PNPBIOS_BASE)) return -ENODEV; #endif - if (pnpbios_disabled || dmi_check_system(pnpbios_dmi_table)) { + if (pnpbios_disabled || dmi_check_system(pnpbios_dmi_table) || + paravirt_enabled()) { printk(KERN_INFO "PnPBIOS: Disabled\n"); return -ENODEV; } diff --git a/trunk/drivers/rtc/Kconfig b/trunk/drivers/rtc/Kconfig index fc766a7a611e..2a63ab2b47f4 100644 --- a/trunk/drivers/rtc/Kconfig +++ b/trunk/drivers/rtc/Kconfig @@ -154,15 +154,23 @@ config RTC_DRV_DS1672 will be called rtc-ds1672. config RTC_DRV_DS1742 - tristate "Dallas DS1742" + tristate "Dallas DS1742/1743" depends on RTC_CLASS help If you say yes here you get support for the - Dallas DS1742 timekeeping chip. + Dallas DS1742/1743 timekeeping chip. This driver can also be built as a module. If so, the module will be called rtc-ds1742. +config RTC_DRV_OMAP + tristate "TI OMAP1" + depends on RTC_CLASS && ( \ + ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730 ) + help + Say "yes" here to support the real time clock on TI OMAP1 chips. + This driver can also be built as a module called rtc-omap. + config RTC_DRV_PCF8563 tristate "Philips PCF8563/Epson RTC8564" depends on RTC_CLASS && I2C diff --git a/trunk/drivers/rtc/Makefile b/trunk/drivers/rtc/Makefile index 3ba5ff6e6800..bd4c45d333f0 100644 --- a/trunk/drivers/rtc/Makefile +++ b/trunk/drivers/rtc/Makefile @@ -21,6 +21,7 @@ obj-$(CONFIG_RTC_DRV_TEST) += rtc-test.o obj-$(CONFIG_RTC_DRV_DS1307) += rtc-ds1307.o obj-$(CONFIG_RTC_DRV_DS1672) += rtc-ds1672.o obj-$(CONFIG_RTC_DRV_DS1742) += rtc-ds1742.o +obj-$(CONFIG_RTC_DRV_OMAP) += rtc-omap.o obj-$(CONFIG_RTC_DRV_PCF8563) += rtc-pcf8563.o obj-$(CONFIG_RTC_DRV_PCF8583) += rtc-pcf8583.o obj-$(CONFIG_RTC_DRV_RS5C372) += rtc-rs5c372.o diff --git a/trunk/drivers/rtc/rtc-dev.c b/trunk/drivers/rtc/rtc-dev.c index 814b9e1873f5..828b329e08e0 100644 --- a/trunk/drivers/rtc/rtc-dev.c +++ b/trunk/drivers/rtc/rtc-dev.c @@ -53,9 +53,10 @@ static int rtc_dev_open(struct inode *inode, struct file *file) * Routine to poll RTC seconds field for change as often as possible, * after first RTC_UIE use timer to reduce polling */ -static void rtc_uie_task(void *data) +static void rtc_uie_task(struct work_struct *work) { - struct rtc_device *rtc = data; + struct rtc_device *rtc = + container_of(work, struct rtc_device, uie_task); struct rtc_time tm; int num = 0; int err; @@ -411,7 +412,7 @@ static int rtc_dev_add_device(struct class_device *class_dev, spin_lock_init(&rtc->irq_lock); init_waitqueue_head(&rtc->irq_queue); #ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL - INIT_WORK(&rtc->uie_task, rtc_uie_task, rtc); + INIT_WORK(&rtc->uie_task, rtc_uie_task); setup_timer(&rtc->uie_timer, rtc_uie_timer, (unsigned long)rtc); #endif diff --git a/trunk/drivers/rtc/rtc-ds1672.c b/trunk/drivers/rtc/rtc-ds1672.c index 67e816a9a39f..dfef1637bfb8 100644 --- a/trunk/drivers/rtc/rtc-ds1672.c +++ b/trunk/drivers/rtc/rtc-ds1672.c @@ -237,17 +237,22 @@ static int ds1672_probe(struct i2c_adapter *adapter, int address, int kind) /* read control register */ err = ds1672_get_control(client, &control); if (err) - goto exit_detach; + goto exit_devreg; if (control & DS1672_REG_CONTROL_EOSC) dev_warn(&client->dev, "Oscillator not enabled. " "Set time to enable.\n"); /* Register sysfs hooks */ - device_create_file(&client->dev, &dev_attr_control); + err = device_create_file(&client->dev, &dev_attr_control); + if (err) + goto exit_devreg; return 0; +exit_devreg: + rtc_device_unregister(rtc); + exit_detach: i2c_detach_client(client); diff --git a/trunk/drivers/rtc/rtc-ds1742.c b/trunk/drivers/rtc/rtc-ds1742.c index 6273a3d240a2..17633bfa8480 100644 --- a/trunk/drivers/rtc/rtc-ds1742.c +++ b/trunk/drivers/rtc/rtc-ds1742.c @@ -6,6 +6,10 @@ * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. + * + * Copyright (C) 2006 Torsten Ertbjerg Rasmussen + * - nvram size determined from resource + * - this ds1742 driver now supports ds1743. */ #include @@ -17,20 +21,19 @@ #include #include -#define DRV_VERSION "0.2" +#define DRV_VERSION "0.3" -#define RTC_REG_SIZE 0x800 -#define RTC_OFFSET 0x7f8 +#define RTC_SIZE 8 -#define RTC_CONTROL (RTC_OFFSET + 0) -#define RTC_CENTURY (RTC_OFFSET + 0) -#define RTC_SECONDS (RTC_OFFSET + 1) -#define RTC_MINUTES (RTC_OFFSET + 2) -#define RTC_HOURS (RTC_OFFSET + 3) -#define RTC_DAY (RTC_OFFSET + 4) -#define RTC_DATE (RTC_OFFSET + 5) -#define RTC_MONTH (RTC_OFFSET + 6) -#define RTC_YEAR (RTC_OFFSET + 7) +#define RTC_CONTROL 0 +#define RTC_CENTURY 0 +#define RTC_SECONDS 1 +#define RTC_MINUTES 2 +#define RTC_HOURS 3 +#define RTC_DAY 4 +#define RTC_DATE 5 +#define RTC_MONTH 6 +#define RTC_YEAR 7 #define RTC_CENTURY_MASK 0x3f #define RTC_SECONDS_MASK 0x7f @@ -48,7 +51,10 @@ struct rtc_plat_data { struct rtc_device *rtc; - void __iomem *ioaddr; + void __iomem *ioaddr_nvram; + void __iomem *ioaddr_rtc; + size_t size_nvram; + size_t size; unsigned long baseaddr; unsigned long last_jiffies; }; @@ -57,7 +63,7 @@ static int ds1742_rtc_set_time(struct device *dev, struct rtc_time *tm) { struct platform_device *pdev = to_platform_device(dev); struct rtc_plat_data *pdata = platform_get_drvdata(pdev); - void __iomem *ioaddr = pdata->ioaddr; + void __iomem *ioaddr = pdata->ioaddr_rtc; u8 century; century = BIN2BCD((tm->tm_year + 1900) / 100); @@ -82,7 +88,7 @@ static int ds1742_rtc_read_time(struct device *dev, struct rtc_time *tm) { struct platform_device *pdev = to_platform_device(dev); struct rtc_plat_data *pdata = platform_get_drvdata(pdev); - void __iomem *ioaddr = pdata->ioaddr; + void __iomem *ioaddr = pdata->ioaddr_rtc; unsigned int year, month, day, hour, minute, second, week; unsigned int century; @@ -127,10 +133,10 @@ static ssize_t ds1742_nvram_read(struct kobject *kobj, char *buf, struct platform_device *pdev = to_platform_device(container_of(kobj, struct device, kobj)); struct rtc_plat_data *pdata = platform_get_drvdata(pdev); - void __iomem *ioaddr = pdata->ioaddr; + void __iomem *ioaddr = pdata->ioaddr_nvram; ssize_t count; - for (count = 0; size > 0 && pos < RTC_OFFSET; count++, size--) + for (count = 0; size > 0 && pos < pdata->size_nvram; count++, size--) *buf++ = readb(ioaddr + pos++); return count; } @@ -141,10 +147,10 @@ static ssize_t ds1742_nvram_write(struct kobject *kobj, char *buf, struct platform_device *pdev = to_platform_device(container_of(kobj, struct device, kobj)); struct rtc_plat_data *pdata = platform_get_drvdata(pdev); - void __iomem *ioaddr = pdata->ioaddr; + void __iomem *ioaddr = pdata->ioaddr_nvram; ssize_t count; - for (count = 0; size > 0 && pos < RTC_OFFSET; count++, size--) + for (count = 0; size > 0 && pos < pdata->size_nvram; count++, size--) writeb(*buf++, ioaddr + pos++); return count; } @@ -155,7 +161,6 @@ static struct bin_attribute ds1742_nvram_attr = { .mode = S_IRUGO | S_IWUGO, .owner = THIS_MODULE, }, - .size = RTC_OFFSET, .read = ds1742_nvram_read, .write = ds1742_nvram_write, }; @@ -175,19 +180,23 @@ static int __init ds1742_rtc_probe(struct platform_device *pdev) pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); if (!pdata) return -ENOMEM; - if (!request_mem_region(res->start, RTC_REG_SIZE, pdev->name)) { + pdata->size = res->end - res->start + 1; + if (!request_mem_region(res->start, pdata->size, pdev->name)) { ret = -EBUSY; goto out; } pdata->baseaddr = res->start; - ioaddr = ioremap(pdata->baseaddr, RTC_REG_SIZE); + ioaddr = ioremap(pdata->baseaddr, pdata->size); if (!ioaddr) { ret = -ENOMEM; goto out; } - pdata->ioaddr = ioaddr; + pdata->ioaddr_nvram = ioaddr; + pdata->size_nvram = pdata->size - RTC_SIZE; + pdata->ioaddr_rtc = ioaddr + pdata->size_nvram; /* turn RTC on if it was not on */ + ioaddr = pdata->ioaddr_rtc; sec = readb(ioaddr + RTC_SECONDS); if (sec & RTC_STOP) { sec &= RTC_SECONDS_MASK; @@ -208,6 +217,8 @@ static int __init ds1742_rtc_probe(struct platform_device *pdev) pdata->rtc = rtc; pdata->last_jiffies = jiffies; platform_set_drvdata(pdev, pdata); + ds1742_nvram_attr.size = max(ds1742_nvram_attr.size, + pdata->size_nvram); ret = sysfs_create_bin_file(&pdev->dev.kobj, &ds1742_nvram_attr); if (ret) goto out; @@ -215,10 +226,10 @@ static int __init ds1742_rtc_probe(struct platform_device *pdev) out: if (pdata->rtc) rtc_device_unregister(pdata->rtc); - if (ioaddr) - iounmap(ioaddr); + if (pdata->ioaddr_nvram) + iounmap(pdata->ioaddr_nvram); if (pdata->baseaddr) - release_mem_region(pdata->baseaddr, RTC_REG_SIZE); + release_mem_region(pdata->baseaddr, pdata->size); kfree(pdata); return ret; } @@ -229,8 +240,8 @@ static int __devexit ds1742_rtc_remove(struct platform_device *pdev) sysfs_remove_bin_file(&pdev->dev.kobj, &ds1742_nvram_attr); rtc_device_unregister(pdata->rtc); - iounmap(pdata->ioaddr); - release_mem_region(pdata->baseaddr, RTC_REG_SIZE); + iounmap(pdata->ioaddr_nvram); + release_mem_region(pdata->baseaddr, pdata->size); kfree(pdata); return 0; } diff --git a/trunk/drivers/rtc/rtc-omap.c b/trunk/drivers/rtc/rtc-omap.c new file mode 100644 index 000000000000..eac5fb1fc02f --- /dev/null +++ b/trunk/drivers/rtc/rtc-omap.c @@ -0,0 +1,572 @@ +/* + * TI OMAP1 Real Time Clock interface for Linux + * + * Copyright (C) 2003 MontaVista Software, Inc. + * Author: George G. Davis or + * + * Copyright (C) 2006 David Brownell (new RTC framework) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + + +/* The OMAP1 RTC is a year/month/day/hours/minutes/seconds BCD clock + * with century-range alarm matching, driven by the 32kHz clock. + * + * The main user-visible ways it differs from PC RTCs are by omitting + * "don't care" alarm fields and sub-second periodic IRQs, and having + * an autoadjust mechanism to calibrate to the true oscillator rate. + * + * Board-specific wiring options include using split power mode with + * RTC_OFF_NOFF used as the reset signal (so the RTC won't be reset), + * and wiring RTC_WAKE_INT (so the RTC alarm can wake the system from + * low power modes). See the BOARD-SPECIFIC CUSTOMIZATION comment. + */ + +#define OMAP_RTC_BASE 0xfffb4800 + +/* RTC registers */ +#define OMAP_RTC_SECONDS_REG 0x00 +#define OMAP_RTC_MINUTES_REG 0x04 +#define OMAP_RTC_HOURS_REG 0x08 +#define OMAP_RTC_DAYS_REG 0x0C +#define OMAP_RTC_MONTHS_REG 0x10 +#define OMAP_RTC_YEARS_REG 0x14 +#define OMAP_RTC_WEEKS_REG 0x18 + +#define OMAP_RTC_ALARM_SECONDS_REG 0x20 +#define OMAP_RTC_ALARM_MINUTES_REG 0x24 +#define OMAP_RTC_ALARM_HOURS_REG 0x28 +#define OMAP_RTC_ALARM_DAYS_REG 0x2c +#define OMAP_RTC_ALARM_MONTHS_REG 0x30 +#define OMAP_RTC_ALARM_YEARS_REG 0x34 + +#define OMAP_RTC_CTRL_REG 0x40 +#define OMAP_RTC_STATUS_REG 0x44 +#define OMAP_RTC_INTERRUPTS_REG 0x48 + +#define OMAP_RTC_COMP_LSB_REG 0x4c +#define OMAP_RTC_COMP_MSB_REG 0x50 +#define OMAP_RTC_OSC_REG 0x54 + +/* OMAP_RTC_CTRL_REG bit fields: */ +#define OMAP_RTC_CTRL_SPLIT (1<<7) +#define OMAP_RTC_CTRL_DISABLE (1<<6) +#define OMAP_RTC_CTRL_SET_32_COUNTER (1<<5) +#define OMAP_RTC_CTRL_TEST (1<<4) +#define OMAP_RTC_CTRL_MODE_12_24 (1<<3) +#define OMAP_RTC_CTRL_AUTO_COMP (1<<2) +#define OMAP_RTC_CTRL_ROUND_30S (1<<1) +#define OMAP_RTC_CTRL_STOP (1<<0) + +/* OMAP_RTC_STATUS_REG bit fields: */ +#define OMAP_RTC_STATUS_POWER_UP (1<<7) +#define OMAP_RTC_STATUS_ALARM (1<<6) +#define OMAP_RTC_STATUS_1D_EVENT (1<<5) +#define OMAP_RTC_STATUS_1H_EVENT (1<<4) +#define OMAP_RTC_STATUS_1M_EVENT (1<<3) +#define OMAP_RTC_STATUS_1S_EVENT (1<<2) +#define OMAP_RTC_STATUS_RUN (1<<1) +#define OMAP_RTC_STATUS_BUSY (1<<0) + +/* OMAP_RTC_INTERRUPTS_REG bit fields: */ +#define OMAP_RTC_INTERRUPTS_IT_ALARM (1<<3) +#define OMAP_RTC_INTERRUPTS_IT_TIMER (1<<2) + + +#define rtc_read(addr) omap_readb(OMAP_RTC_BASE + (addr)) +#define rtc_write(val, addr) omap_writeb(val, OMAP_RTC_BASE + (addr)) + + +/* platform_bus isn't hotpluggable, so for static linkage it'd be safe + * to get rid of probe() and remove() code ... too bad the driver struct + * remembers probe(), that's about 25% of the runtime footprint!! + */ +#ifndef MODULE +#undef __devexit +#undef __devexit_p +#define __devexit __exit +#define __devexit_p __exit_p +#endif + + +/* we rely on the rtc framework to handle locking (rtc->ops_lock), + * so the only other requirement is that register accesses which + * require BUSY to be clear are made with IRQs locally disabled + */ +static void rtc_wait_not_busy(void) +{ + int count = 0; + u8 status; + + /* BUSY may stay active for 1/32768 second (~30 usec) */ + for (count = 0; count < 50; count++) { + status = rtc_read(OMAP_RTC_STATUS_REG); + if ((status & (u8)OMAP_RTC_STATUS_BUSY) == 0) + break; + udelay(1); + } + /* now we have ~15 usec to read/write various registers */ +} + +static irqreturn_t rtc_irq(int irq, void *class_dev) +{ + unsigned long events = 0; + u8 irq_data; + + irq_data = rtc_read(OMAP_RTC_STATUS_REG); + + /* alarm irq? */ + if (irq_data & OMAP_RTC_STATUS_ALARM) { + rtc_write(OMAP_RTC_STATUS_ALARM, OMAP_RTC_STATUS_REG); + events |= RTC_IRQF | RTC_AF; + } + + /* 1/sec periodic/update irq? */ + if (irq_data & OMAP_RTC_STATUS_1S_EVENT) + events |= RTC_IRQF | RTC_UF; + + rtc_update_irq(class_dev, 1, events); + + return IRQ_HANDLED; +} + +#ifdef CONFIG_RTC_INTF_DEV + +static int +omap_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) +{ + u8 reg; + + switch (cmd) { + case RTC_AIE_OFF: + case RTC_AIE_ON: + case RTC_UIE_OFF: + case RTC_UIE_ON: + break; + default: + return -ENOIOCTLCMD; + } + + local_irq_disable(); + rtc_wait_not_busy(); + reg = rtc_read(OMAP_RTC_INTERRUPTS_REG); + switch (cmd) { + /* AIE = Alarm Interrupt Enable */ + case RTC_AIE_OFF: + reg &= ~OMAP_RTC_INTERRUPTS_IT_ALARM; + break; + case RTC_AIE_ON: + reg |= OMAP_RTC_INTERRUPTS_IT_ALARM; + break; + /* UIE = Update Interrupt Enable (1/second) */ + case RTC_UIE_OFF: + reg &= ~OMAP_RTC_INTERRUPTS_IT_TIMER; + break; + case RTC_UIE_ON: + reg |= OMAP_RTC_INTERRUPTS_IT_TIMER; + break; + } + rtc_wait_not_busy(); + rtc_write(reg, OMAP_RTC_INTERRUPTS_REG); + local_irq_enable(); + + return 0; +} + +#else +#define omap_rtc_ioctl NULL +#endif + +/* this hardware doesn't support "don't care" alarm fields */ +static int tm2bcd(struct rtc_time *tm) +{ + if (rtc_valid_tm(tm) != 0) + return -EINVAL; + + tm->tm_sec = BIN2BCD(tm->tm_sec); + tm->tm_min = BIN2BCD(tm->tm_min); + tm->tm_hour = BIN2BCD(tm->tm_hour); + tm->tm_mday = BIN2BCD(tm->tm_mday); + + tm->tm_mon = BIN2BCD(tm->tm_mon + 1); + + /* epoch == 1900 */ + if (tm->tm_year < 100 || tm->tm_year > 199) + return -EINVAL; + tm->tm_year = BIN2BCD(tm->tm_year - 100); + + return 0; +} + +static void bcd2tm(struct rtc_time *tm) +{ + tm->tm_sec = BCD2BIN(tm->tm_sec); + tm->tm_min = BCD2BIN(tm->tm_min); + tm->tm_hour = BCD2BIN(tm->tm_hour); + tm->tm_mday = BCD2BIN(tm->tm_mday); + tm->tm_mon = BCD2BIN(tm->tm_mon) - 1; + /* epoch == 1900 */ + tm->tm_year = BCD2BIN(tm->tm_year) + 100; +} + + +static int omap_rtc_read_time(struct device *dev, struct rtc_time *tm) +{ + /* we don't report wday/yday/isdst ... */ + local_irq_disable(); + rtc_wait_not_busy(); + + tm->tm_sec = rtc_read(OMAP_RTC_SECONDS_REG); + tm->tm_min = rtc_read(OMAP_RTC_MINUTES_REG); + tm->tm_hour = rtc_read(OMAP_RTC_HOURS_REG); + tm->tm_mday = rtc_read(OMAP_RTC_DAYS_REG); + tm->tm_mon = rtc_read(OMAP_RTC_MONTHS_REG); + tm->tm_year = rtc_read(OMAP_RTC_YEARS_REG); + + local_irq_enable(); + + bcd2tm(tm); + return 0; +} + +static int omap_rtc_set_time(struct device *dev, struct rtc_time *tm) +{ + if (tm2bcd(tm) < 0) + return -EINVAL; + local_irq_disable(); + rtc_wait_not_busy(); + + rtc_write(tm->tm_year, OMAP_RTC_YEARS_REG); + rtc_write(tm->tm_mon, OMAP_RTC_MONTHS_REG); + rtc_write(tm->tm_mday, OMAP_RTC_DAYS_REG); + rtc_write(tm->tm_hour, OMAP_RTC_HOURS_REG); + rtc_write(tm->tm_min, OMAP_RTC_MINUTES_REG); + rtc_write(tm->tm_sec, OMAP_RTC_SECONDS_REG); + + local_irq_enable(); + + return 0; +} + +static int omap_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) +{ + local_irq_disable(); + rtc_wait_not_busy(); + + alm->time.tm_sec = rtc_read(OMAP_RTC_ALARM_SECONDS_REG); + alm->time.tm_min = rtc_read(OMAP_RTC_ALARM_MINUTES_REG); + alm->time.tm_hour = rtc_read(OMAP_RTC_ALARM_HOURS_REG); + alm->time.tm_mday = rtc_read(OMAP_RTC_ALARM_DAYS_REG); + alm->time.tm_mon = rtc_read(OMAP_RTC_ALARM_MONTHS_REG); + alm->time.tm_year = rtc_read(OMAP_RTC_ALARM_YEARS_REG); + + local_irq_enable(); + + bcd2tm(&alm->time); + alm->pending = !!(rtc_read(OMAP_RTC_INTERRUPTS_REG) + & OMAP_RTC_INTERRUPTS_IT_ALARM); + alm->enabled = alm->pending && device_may_wakeup(dev); + + return 0; +} + +static int omap_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) +{ + u8 reg; + + /* Much userspace code uses RTC_ALM_SET, thus "don't care" for + * day/month/year specifies alarms up to 24 hours in the future. + * So we need to handle that ... but let's ignore the "don't care" + * values for hours/minutes/seconds. + */ + if (alm->time.tm_mday <= 0 + && alm->time.tm_mon < 0 + && alm->time.tm_year < 0) { + struct rtc_time tm; + unsigned long now, then; + + omap_rtc_read_time(dev, &tm); + rtc_tm_to_time(&tm, &now); + + alm->time.tm_mday = tm.tm_mday; + alm->time.tm_mon = tm.tm_mon; + alm->time.tm_year = tm.tm_year; + rtc_tm_to_time(&alm->time, &then); + + /* sometimes the alarm wraps into tomorrow */ + if (then < now) { + rtc_time_to_tm(now + 24 * 60 * 60, &tm); + alm->time.tm_mday = tm.tm_mday; + alm->time.tm_mon = tm.tm_mon; + alm->time.tm_year = tm.tm_year; + } + } + + if (tm2bcd(&alm->time) < 0) + return -EINVAL; + + local_irq_disable(); + rtc_wait_not_busy(); + + rtc_write(alm->time.tm_year, OMAP_RTC_ALARM_YEARS_REG); + rtc_write(alm->time.tm_mon, OMAP_RTC_ALARM_MONTHS_REG); + rtc_write(alm->time.tm_mday, OMAP_RTC_ALARM_DAYS_REG); + rtc_write(alm->time.tm_hour, OMAP_RTC_ALARM_HOURS_REG); + rtc_write(alm->time.tm_min, OMAP_RTC_ALARM_MINUTES_REG); + rtc_write(alm->time.tm_sec, OMAP_RTC_ALARM_SECONDS_REG); + + reg = rtc_read(OMAP_RTC_INTERRUPTS_REG); + if (alm->enabled) + reg |= OMAP_RTC_INTERRUPTS_IT_ALARM; + else + reg &= ~OMAP_RTC_INTERRUPTS_IT_ALARM; + rtc_write(reg, OMAP_RTC_INTERRUPTS_REG); + + local_irq_enable(); + + return 0; +} + +static struct rtc_class_ops omap_rtc_ops = { + .ioctl = omap_rtc_ioctl, + .read_time = omap_rtc_read_time, + .set_time = omap_rtc_set_time, + .read_alarm = omap_rtc_read_alarm, + .set_alarm = omap_rtc_set_alarm, +}; + +static int omap_rtc_alarm; +static int omap_rtc_timer; + +static int __devinit omap_rtc_probe(struct platform_device *pdev) +{ + struct resource *res, *mem; + struct rtc_device *rtc; + u8 reg, new_ctrl; + + omap_rtc_timer = platform_get_irq(pdev, 0); + if (omap_rtc_timer <= 0) { + pr_debug("%s: no update irq?\n", pdev->name); + return -ENOENT; + } + + omap_rtc_alarm = platform_get_irq(pdev, 1); + if (omap_rtc_alarm <= 0) { + pr_debug("%s: no alarm irq?\n", pdev->name); + return -ENOENT; + } + + /* NOTE: using static mapping for RTC registers */ + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res && res->start != OMAP_RTC_BASE) { + pr_debug("%s: RTC registers at %08x, expected %08x\n", + pdev->name, (unsigned) res->start, OMAP_RTC_BASE); + return -ENOENT; + } + + if (res) + mem = request_mem_region(res->start, + res->end - res->start + 1, + pdev->name); + else + mem = NULL; + if (!mem) { + pr_debug("%s: RTC registers at %08x are not free\n", + pdev->name, OMAP_RTC_BASE); + return -EBUSY; + } + + rtc = rtc_device_register(pdev->name, &pdev->dev, + &omap_rtc_ops, THIS_MODULE); + if (IS_ERR(rtc)) { + pr_debug("%s: can't register RTC device, err %ld\n", + pdev->name, PTR_ERR(rtc)); + goto fail; + } + platform_set_drvdata(pdev, rtc); + class_set_devdata(&rtc->class_dev, mem); + + /* clear pending irqs, and set 1/second periodic, + * which we'll use instead of update irqs + */ + rtc_write(0, OMAP_RTC_INTERRUPTS_REG); + + /* clear old status */ + reg = rtc_read(OMAP_RTC_STATUS_REG); + if (reg & (u8) OMAP_RTC_STATUS_POWER_UP) { + pr_info("%s: RTC power up reset detected\n", + pdev->name); + rtc_write(OMAP_RTC_STATUS_POWER_UP, OMAP_RTC_STATUS_REG); + } + if (reg & (u8) OMAP_RTC_STATUS_ALARM) + rtc_write(OMAP_RTC_STATUS_ALARM, OMAP_RTC_STATUS_REG); + + /* handle periodic and alarm irqs */ + if (request_irq(omap_rtc_timer, rtc_irq, SA_INTERRUPT, + rtc->class_dev.class_id, &rtc->class_dev)) { + pr_debug("%s: RTC timer interrupt IRQ%d already claimed\n", + pdev->name, omap_rtc_timer); + goto fail0; + } + if (request_irq(omap_rtc_alarm, rtc_irq, SA_INTERRUPT, + rtc->class_dev.class_id, &rtc->class_dev)) { + pr_debug("%s: RTC alarm interrupt IRQ%d already claimed\n", + pdev->name, omap_rtc_alarm); + goto fail1; + } + + /* On boards with split power, RTC_ON_NOFF won't reset the RTC */ + reg = rtc_read(OMAP_RTC_CTRL_REG); + if (reg & (u8) OMAP_RTC_CTRL_STOP) + pr_info("%s: already running\n", pdev->name); + + /* force to 24 hour mode */ + new_ctrl = reg & ~(OMAP_RTC_CTRL_SPLIT|OMAP_RTC_CTRL_AUTO_COMP); + new_ctrl |= OMAP_RTC_CTRL_STOP; + + /* BOARD-SPECIFIC CUSTOMIZATION CAN GO HERE: + * + * - Boards wired so that RTC_WAKE_INT does something, and muxed + * right (W13_1610_RTC_WAKE_INT is the default after chip reset), + * should initialize the device wakeup flag appropriately. + * + * - Boards wired so RTC_ON_nOFF is used as the reset signal, + * rather than nPWRON_RESET, should forcibly enable split + * power mode. (Some chip errata report that RTC_CTRL_SPLIT + * is write-only, and always reads as zero...) + */ + device_init_wakeup(&pdev->dev, 0); + + if (new_ctrl & (u8) OMAP_RTC_CTRL_SPLIT) + pr_info("%s: split power mode\n", pdev->name); + + if (reg != new_ctrl) + rtc_write(new_ctrl, OMAP_RTC_CTRL_REG); + + return 0; + +fail1: + free_irq(omap_rtc_timer, NULL); +fail0: + rtc_device_unregister(rtc); +fail: + release_resource(mem); + return -EIO; +} + +static int __devexit omap_rtc_remove(struct platform_device *pdev) +{ + struct rtc_device *rtc = platform_get_drvdata(pdev);; + + device_init_wakeup(&pdev->dev, 0); + + /* leave rtc running, but disable irqs */ + rtc_write(0, OMAP_RTC_INTERRUPTS_REG); + + free_irq(omap_rtc_timer, rtc); + free_irq(omap_rtc_alarm, rtc); + + release_resource(class_get_devdata(&rtc->class_dev)); + rtc_device_unregister(rtc); + return 0; +} + +#ifdef CONFIG_PM + +static struct timespec rtc_delta; +static u8 irqstat; + +static int omap_rtc_suspend(struct platform_device *pdev, pm_message_t state) +{ + struct rtc_time rtc_tm; + struct timespec time; + + time.tv_nsec = 0; + omap_rtc_read_time(NULL, &rtc_tm); + rtc_tm_to_time(&rtc_tm, &time.tv_sec); + + save_time_delta(&rtc_delta, &time); + irqstat = rtc_read(OMAP_RTC_INTERRUPTS_REG); + + /* FIXME the RTC alarm is not currently acting as a wakeup event + * source, and in fact this enable() call is just saving a flag + * that's never used... + */ + if (device_may_wakeup(&pdev->dev)) + enable_irq_wake(omap_rtc_alarm); + else + rtc_write(0, OMAP_RTC_INTERRUPTS_REG); + + return 0; +} + +static int omap_rtc_resume(struct platform_device *pdev) +{ + struct rtc_time rtc_tm; + struct timespec time; + + time.tv_nsec = 0; + omap_rtc_read_time(NULL, &rtc_tm); + rtc_tm_to_time(&rtc_tm, &time.tv_sec); + + restore_time_delta(&rtc_delta, &time); + if (device_may_wakeup(&pdev->dev)) + disable_irq_wake(omap_rtc_alarm); + else + rtc_write(irqstat, OMAP_RTC_INTERRUPTS_REG); + return 0; +} + +#else +#define omap_rtc_suspend NULL +#define omap_rtc_resume NULL +#endif + +static void omap_rtc_shutdown(struct platform_device *pdev) +{ + rtc_write(0, OMAP_RTC_INTERRUPTS_REG); +} + +MODULE_ALIAS("omap_rtc"); +static struct platform_driver omap_rtc_driver = { + .probe = omap_rtc_probe, + .remove = __devexit_p(omap_rtc_remove), + .suspend = omap_rtc_suspend, + .resume = omap_rtc_resume, + .shutdown = omap_rtc_shutdown, + .driver = { + .name = "omap_rtc", + .owner = THIS_MODULE, + }, +}; + +static int __init rtc_init(void) +{ + return platform_driver_register(&omap_rtc_driver); +} +module_init(rtc_init); + +static void __exit rtc_exit(void) +{ + platform_driver_unregister(&omap_rtc_driver); +} +module_exit(rtc_exit); + +MODULE_AUTHOR("George G. Davis (and others)"); +MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/rtc/rtc-rs5c372.c b/trunk/drivers/rtc/rtc-rs5c372.c index a44fe4efa216..e2c7698fdba3 100644 --- a/trunk/drivers/rtc/rtc-rs5c372.c +++ b/trunk/drivers/rtc/rtc-rs5c372.c @@ -13,7 +13,7 @@ #include #include -#define DRV_VERSION "0.2" +#define DRV_VERSION "0.3" /* Addresses to scan */ static unsigned short normal_i2c[] = { /* 0x32,*/ I2C_CLIENT_END }; @@ -39,6 +39,14 @@ static int rs5c372_attach(struct i2c_adapter *adapter); static int rs5c372_detach(struct i2c_client *client); static int rs5c372_probe(struct i2c_adapter *adapter, int address, int kind); +struct rs5c372 { + u8 reg_addr; + u8 regs[17]; + struct i2c_msg msg[1]; + struct i2c_client client; + struct rtc_device *rtc; +}; + static struct i2c_driver rs5c372_driver = { .driver = { .name = "rs5c372", @@ -49,18 +57,16 @@ static struct i2c_driver rs5c372_driver = { static int rs5c372_get_datetime(struct i2c_client *client, struct rtc_time *tm) { - unsigned char buf[7] = { RS5C372_REG_BASE }; - /* this implements the 1st reading method, according - * to the datasheet. buf[0] is initialized with - * address ptr and transmission format register. + struct rs5c372 *rs5c372 = i2c_get_clientdata(client); + u8 *buf = &(rs5c372->regs[1]); + + /* this implements the 3rd reading method, according + * to the datasheet. rs5c372 defaults to internal + * address 0xF, so 0x0 is in regs[1] */ - struct i2c_msg msgs[] = { - { client->addr, 0, 1, buf }, - { client->addr, I2C_M_RD, 7, buf }, - }; - if ((i2c_transfer(client->adapter, msgs, 2)) != 2) { + if ((i2c_transfer(client->adapter, rs5c372->msg, 1)) != 1) { dev_err(&client->dev, "%s: read error\n", __FUNCTION__); return -EIO; } @@ -114,23 +120,14 @@ static int rs5c372_set_datetime(struct i2c_client *client, struct rtc_time *tm) static int rs5c372_get_trim(struct i2c_client *client, int *osc, int *trim) { - unsigned char buf = RS5C372_REG_TRIM; - - struct i2c_msg msgs[] = { - { client->addr, 0, 1, &buf }, - { client->addr, I2C_M_RD, 1, &buf }, - }; - - if ((i2c_transfer(client->adapter, msgs, 2)) != 2) { - dev_err(&client->dev, "%s: read error\n", __FUNCTION__); - return -EIO; - } + struct rs5c372 *rs5c372 = i2c_get_clientdata(client); + u8 tmp = rs5c372->regs[RS5C372_REG_TRIM + 1]; if (osc) - *osc = (buf & RS5C372_TRIM_XSL) ? 32000 : 32768; + *osc = (tmp & RS5C372_TRIM_XSL) ? 32000 : 32768; if (trim) { - *trim = buf & RS5C372_TRIM_MASK; + *trim = tmp & RS5C372_TRIM_MASK; dev_dbg(&client->dev, "%s: raw trim=%x\n", __FUNCTION__, *trim); } @@ -201,7 +198,7 @@ static int rs5c372_probe(struct i2c_adapter *adapter, int address, int kind) { int err = 0; struct i2c_client *client; - struct rtc_device *rtc; + struct rs5c372 *rs5c372; dev_dbg(&adapter->dev, "%s\n", __FUNCTION__); @@ -210,10 +207,11 @@ static int rs5c372_probe(struct i2c_adapter *adapter, int address, int kind) goto exit; } - if (!(client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL))) { + if (!(rs5c372 = kzalloc(sizeof(struct rs5c372), GFP_KERNEL))) { err = -ENOMEM; goto exit; } + client = &rs5c372->client; /* I2C client */ client->addr = address; @@ -222,32 +220,47 @@ static int rs5c372_probe(struct i2c_adapter *adapter, int address, int kind) strlcpy(client->name, rs5c372_driver.driver.name, I2C_NAME_SIZE); + i2c_set_clientdata(client, rs5c372); + + rs5c372->msg[0].addr = address; + rs5c372->msg[0].flags = I2C_M_RD; + rs5c372->msg[0].len = sizeof(rs5c372->regs); + rs5c372->msg[0].buf = rs5c372->regs; + /* Inform the i2c layer */ if ((err = i2c_attach_client(client))) goto exit_kfree; dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n"); - rtc = rtc_device_register(rs5c372_driver.driver.name, &client->dev, - &rs5c372_rtc_ops, THIS_MODULE); + rs5c372->rtc = rtc_device_register(rs5c372_driver.driver.name, + &client->dev, &rs5c372_rtc_ops, THIS_MODULE); - if (IS_ERR(rtc)) { - err = PTR_ERR(rtc); + if (IS_ERR(rs5c372->rtc)) { + err = PTR_ERR(rs5c372->rtc); goto exit_detach; } - i2c_set_clientdata(client, rtc); - - device_create_file(&client->dev, &dev_attr_trim); - device_create_file(&client->dev, &dev_attr_osc); + err = device_create_file(&client->dev, &dev_attr_trim); + if (err) + goto exit_devreg; + err = device_create_file(&client->dev, &dev_attr_osc); + if (err) + goto exit_trim; return 0; +exit_trim: + device_remove_file(&client->dev, &dev_attr_trim); + +exit_devreg: + rtc_device_unregister(rs5c372->rtc); + exit_detach: i2c_detach_client(client); exit_kfree: - kfree(client); + kfree(rs5c372); exit: return err; @@ -256,16 +269,15 @@ static int rs5c372_probe(struct i2c_adapter *adapter, int address, int kind) static int rs5c372_detach(struct i2c_client *client) { int err; - struct rtc_device *rtc = i2c_get_clientdata(client); + struct rs5c372 *rs5c372 = i2c_get_clientdata(client); - if (rtc) - rtc_device_unregister(rtc); + if (rs5c372->rtc) + rtc_device_unregister(rs5c372->rtc); if ((err = i2c_detach_client(client))) return err; - kfree(client); - + kfree(rs5c372); return 0; } diff --git a/trunk/drivers/rtc/rtc-test.c b/trunk/drivers/rtc/rtc-test.c index 6ef9c62d5032..f50a1b8e1607 100644 --- a/trunk/drivers/rtc/rtc-test.c +++ b/trunk/drivers/rtc/rtc-test.c @@ -123,11 +123,18 @@ static int test_probe(struct platform_device *plat_dev) err = PTR_ERR(rtc); return err; } - device_create_file(&plat_dev->dev, &dev_attr_irq); + + err = device_create_file(&plat_dev->dev, &dev_attr_irq); + if (err) + goto err; platform_set_drvdata(plat_dev, rtc); return 0; + +err: + rtc_device_unregister(rtc); + return err; } static int __devexit test_remove(struct platform_device *plat_dev) diff --git a/trunk/drivers/rtc/rtc-x1205.c b/trunk/drivers/rtc/rtc-x1205.c index 522c69753bbf..9a67487d086b 100644 --- a/trunk/drivers/rtc/rtc-x1205.c +++ b/trunk/drivers/rtc/rtc-x1205.c @@ -562,11 +562,19 @@ static int x1205_probe(struct i2c_adapter *adapter, int address, int kind) else dev_err(&client->dev, "couldn't read status\n"); - device_create_file(&client->dev, &dev_attr_atrim); - device_create_file(&client->dev, &dev_attr_dtrim); + err = device_create_file(&client->dev, &dev_attr_atrim); + if (err) goto exit_devreg; + err = device_create_file(&client->dev, &dev_attr_dtrim); + if (err) goto exit_atrim; return 0; +exit_atrim: + device_remove_file(&client->dev, &dev_attr_atrim); + +exit_devreg: + rtc_device_unregister(rtc); + exit_detach: i2c_detach_client(client); diff --git a/trunk/drivers/s390/block/dasd.c b/trunk/drivers/s390/block/dasd.c index a2cef57d7bcb..2af2d9b53d18 100644 --- a/trunk/drivers/s390/block/dasd.c +++ b/trunk/drivers/s390/block/dasd.c @@ -54,7 +54,7 @@ static void dasd_flush_request_queue(struct dasd_device *); static void dasd_int_handler(struct ccw_device *, unsigned long, struct irb *); static int dasd_flush_ccw_queue(struct dasd_device *, int); static void dasd_tasklet(struct dasd_device *); -static void do_kick_device(void *data); +static void do_kick_device(struct work_struct *); /* * SECTION: Operations on the device structure. @@ -100,7 +100,7 @@ dasd_alloc_device(void) (unsigned long) device); INIT_LIST_HEAD(&device->ccw_queue); init_timer(&device->timer); - INIT_WORK(&device->kick_work, do_kick_device, device); + INIT_WORK(&device->kick_work, do_kick_device); device->state = DASD_STATE_NEW; device->target = DASD_STATE_NEW; @@ -407,11 +407,9 @@ dasd_change_state(struct dasd_device *device) * event daemon. */ static void -do_kick_device(void *data) +do_kick_device(struct work_struct *work) { - struct dasd_device *device; - - device = (struct dasd_device *) data; + struct dasd_device *device = container_of(work, struct dasd_device, kick_work); dasd_change_state(device); dasd_schedule_bh(device); dasd_put_device(device); diff --git a/trunk/drivers/s390/block/dasd_devmap.c b/trunk/drivers/s390/block/dasd_devmap.c index 17fdd8c9f740..cf28ccc57948 100644 --- a/trunk/drivers/s390/block/dasd_devmap.c +++ b/trunk/drivers/s390/block/dasd_devmap.c @@ -25,7 +25,7 @@ #include "dasd_int.h" -kmem_cache_t *dasd_page_cache; +struct kmem_cache *dasd_page_cache; EXPORT_SYMBOL_GPL(dasd_page_cache); /* diff --git a/trunk/drivers/s390/block/dasd_eckd.c b/trunk/drivers/s390/block/dasd_eckd.c index 5ecea3e4fdef..fdaa471e845f 100644 --- a/trunk/drivers/s390/block/dasd_eckd.c +++ b/trunk/drivers/s390/block/dasd_eckd.c @@ -1215,7 +1215,7 @@ dasd_eckd_build_cp(struct dasd_device * device, struct request *req) dst = page_address(bv->bv_page) + bv->bv_offset; if (dasd_page_cache) { char *copy = kmem_cache_alloc(dasd_page_cache, - SLAB_DMA | __GFP_NOWARN); + GFP_DMA | __GFP_NOWARN); if (copy && rq_data_dir(req) == WRITE) memcpy(copy + bv->bv_offset, dst, bv->bv_len); if (copy) diff --git a/trunk/drivers/s390/block/dasd_fba.c b/trunk/drivers/s390/block/dasd_fba.c index 80926c548228..b857fd5893fd 100644 --- a/trunk/drivers/s390/block/dasd_fba.c +++ b/trunk/drivers/s390/block/dasd_fba.c @@ -308,7 +308,7 @@ dasd_fba_build_cp(struct dasd_device * device, struct request *req) dst = page_address(bv->bv_page) + bv->bv_offset; if (dasd_page_cache) { char *copy = kmem_cache_alloc(dasd_page_cache, - SLAB_DMA | __GFP_NOWARN); + GFP_DMA | __GFP_NOWARN); if (copy && rq_data_dir(req) == WRITE) memcpy(copy + bv->bv_offset, dst, bv->bv_len); if (copy) diff --git a/trunk/drivers/s390/block/dasd_int.h b/trunk/drivers/s390/block/dasd_int.h index 9f52004f6fc2..dc5dd509434d 100644 --- a/trunk/drivers/s390/block/dasd_int.h +++ b/trunk/drivers/s390/block/dasd_int.h @@ -474,7 +474,7 @@ extern struct dasd_profile_info_t dasd_global_profile; extern unsigned int dasd_profile_level; extern struct block_device_operations dasd_device_operations; -extern kmem_cache_t *dasd_page_cache; +extern struct kmem_cache *dasd_page_cache; struct dasd_ccw_req * dasd_kmalloc_request(char *, int, int, struct dasd_device *); diff --git a/trunk/drivers/s390/block/dasd_ioctl.c b/trunk/drivers/s390/block/dasd_ioctl.c index 8fed3603e9ea..758cfb542865 100644 --- a/trunk/drivers/s390/block/dasd_ioctl.c +++ b/trunk/drivers/s390/block/dasd_ioctl.c @@ -430,7 +430,7 @@ dasd_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) int rval; lock_kernel(); - rval = dasd_ioctl(filp->f_dentry->d_inode, filp, cmd, arg); + rval = dasd_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg); unlock_kernel(); return (rval == -EINVAL) ? -ENOIOCTLCMD : rval; diff --git a/trunk/drivers/s390/char/fs3270.c b/trunk/drivers/s390/char/fs3270.c index 78f8bda81dae..0893d306ae80 100644 --- a/trunk/drivers/s390/char/fs3270.c +++ b/trunk/drivers/s390/char/fs3270.c @@ -419,16 +419,20 @@ fs3270_open(struct inode *inode, struct file *filp) struct idal_buffer *ib; int minor, rc; - if (imajor(filp->f_dentry->d_inode) != IBM_FS3270_MAJOR) + if (imajor(filp->f_path.dentry->d_inode) != IBM_FS3270_MAJOR) return -ENODEV; - minor = iminor(filp->f_dentry->d_inode); + minor = iminor(filp->f_path.dentry->d_inode); /* Check for minor 0 multiplexer. */ if (minor == 0) { - if (!current->signal->tty) + struct tty_struct *tty; + mutex_lock(&tty_mutex); + tty = get_current_tty(); + if (!tty || tty->driver->major != IBM_TTY3270_MAJOR) { + mutex_unlock(&tty_mutex); return -ENODEV; - if (current->signal->tty->driver->major != IBM_TTY3270_MAJOR) - return -ENODEV; - minor = current->signal->tty->index + RAW3270_FIRSTMINOR; + } + minor = tty->index + RAW3270_FIRSTMINOR; + mutex_unlock(&tty_mutex); } /* Check if some other program is already using fullscreen mode. */ fp = (struct fs3270 *) raw3270_find_view(&fs3270_fn, minor); diff --git a/trunk/drivers/s390/char/sclp_tty.c b/trunk/drivers/s390/char/sclp_tty.c index 6f43e04dbefd..2d173e5c8a09 100644 --- a/trunk/drivers/s390/char/sclp_tty.c +++ b/trunk/drivers/s390/char/sclp_tty.c @@ -60,8 +60,6 @@ static unsigned short int sclp_tty_chars_count; struct tty_driver *sclp_tty_driver; -extern struct termios tty_std_termios; - static struct sclp_ioctls sclp_ioctls; static struct sclp_ioctls sclp_ioctls_init = { diff --git a/trunk/drivers/s390/char/tape_char.c b/trunk/drivers/s390/char/tape_char.c index 97f75237bed6..31198c8f2718 100644 --- a/trunk/drivers/s390/char/tape_char.c +++ b/trunk/drivers/s390/char/tape_char.c @@ -298,13 +298,13 @@ tapechar_open (struct inode *inode, struct file *filp) int minor, rc; DBF_EVENT(6, "TCHAR:open: %i:%i\n", - imajor(filp->f_dentry->d_inode), - iminor(filp->f_dentry->d_inode)); + imajor(filp->f_path.dentry->d_inode), + iminor(filp->f_path.dentry->d_inode)); - if (imajor(filp->f_dentry->d_inode) != tapechar_major) + if (imajor(filp->f_path.dentry->d_inode) != tapechar_major) return -ENODEV; - minor = iminor(filp->f_dentry->d_inode); + minor = iminor(filp->f_path.dentry->d_inode); device = tape_get_device(minor / TAPE_MINORS_PER_DEV); if (IS_ERR(device)) { DBF_EVENT(3, "TCHAR:open: tape_get_device() failed\n"); diff --git a/trunk/drivers/s390/char/tty3270.c b/trunk/drivers/s390/char/tty3270.c index 4717c3611601..09844621edc0 100644 --- a/trunk/drivers/s390/char/tty3270.c +++ b/trunk/drivers/s390/char/tty3270.c @@ -1659,7 +1659,7 @@ tty3270_flush_buffer(struct tty_struct *tty) * Check for visible/invisible input switches */ static void -tty3270_set_termios(struct tty_struct *tty, struct termios *old) +tty3270_set_termios(struct tty_struct *tty, struct ktermios *old) { struct tty3270 *tp; int new; diff --git a/trunk/drivers/s390/cio/css.c b/trunk/drivers/s390/cio/css.c index ad7f7e1c0163..26cf2f5ae2e7 100644 --- a/trunk/drivers/s390/cio/css.c +++ b/trunk/drivers/s390/cio/css.c @@ -334,7 +334,7 @@ static LIST_HEAD(slow_subchannels_head); static DEFINE_SPINLOCK(slow_subchannel_lock); static void -css_trigger_slow_path(void) +css_trigger_slow_path(struct work_struct *unused) { CIO_TRACE_EVENT(4, "slowpath"); @@ -359,8 +359,7 @@ css_trigger_slow_path(void) spin_unlock_irq(&slow_subchannel_lock); } -typedef void (*workfunc)(void *); -DECLARE_WORK(slow_path_work, (workfunc)css_trigger_slow_path, NULL); +DECLARE_WORK(slow_path_work, css_trigger_slow_path); struct workqueue_struct *slow_path_wq; /* Reprobe subchannel if unregistered. */ @@ -397,7 +396,7 @@ static int reprobe_subchannel(struct subchannel_id schid, void *data) } /* Work function used to reprobe all unregistered subchannels. */ -static void reprobe_all(void *data) +static void reprobe_all(struct work_struct *unused) { int ret; @@ -413,7 +412,7 @@ static void reprobe_all(void *data) need_reprobe); } -DECLARE_WORK(css_reprobe_work, reprobe_all, NULL); +DECLARE_WORK(css_reprobe_work, reprobe_all); /* Schedule reprobing of all unregistered subchannels. */ void css_schedule_reprobe(void) diff --git a/trunk/drivers/s390/crypto/ap_bus.c b/trunk/drivers/s390/crypto/ap_bus.c index 6a54334ffe09..e4dc947e74e9 100644 --- a/trunk/drivers/s390/crypto/ap_bus.c +++ b/trunk/drivers/s390/crypto/ap_bus.c @@ -37,7 +37,7 @@ #include "ap_bus.h" /* Some prototypes. */ -static void ap_scan_bus(void *); +static void ap_scan_bus(struct work_struct *); static void ap_poll_all(unsigned long); static void ap_poll_timeout(unsigned long); static int ap_poll_thread_start(void); @@ -71,7 +71,7 @@ static struct device *ap_root_device = NULL; static struct workqueue_struct *ap_work_queue; static struct timer_list ap_config_timer; static int ap_config_time = AP_CONFIG_TIME; -static DECLARE_WORK(ap_config_work, ap_scan_bus, NULL); +static DECLARE_WORK(ap_config_work, ap_scan_bus); /** * Tasklet & timer for AP request polling. @@ -732,7 +732,7 @@ static void ap_device_release(struct device *dev) kfree(ap_dev); } -static void ap_scan_bus(void *data) +static void ap_scan_bus(struct work_struct *unused) { struct ap_device *ap_dev; struct device *dev; diff --git a/trunk/drivers/s390/net/lcs.c b/trunk/drivers/s390/net/lcs.c index 08d4e47070bd..e5665b6743a1 100644 --- a/trunk/drivers/s390/net/lcs.c +++ b/trunk/drivers/s390/net/lcs.c @@ -67,7 +67,7 @@ static char debug_buffer[255]; * Some prototypes. */ static void lcs_tasklet(unsigned long); -static void lcs_start_kernel_thread(struct lcs_card *card); +static void lcs_start_kernel_thread(struct work_struct *); static void lcs_get_frames_cb(struct lcs_channel *, struct lcs_buffer *); static int lcs_send_delipm(struct lcs_card *, struct lcs_ipm_list *); static int lcs_recovery(void *ptr); @@ -1724,8 +1724,9 @@ lcs_stopcard(struct lcs_card *card) * Kernel Thread helper functions for LGW initiated commands */ static void -lcs_start_kernel_thread(struct lcs_card *card) +lcs_start_kernel_thread(struct work_struct *work) { + struct lcs_card *card = container_of(work, struct lcs_card, kernel_thread_starter); LCS_DBF_TEXT(5, trace, "krnthrd"); if (lcs_do_start_thread(card, LCS_RECOVERY_THREAD)) kernel_thread(lcs_recovery, (void *) card, SIGCHLD); @@ -2053,8 +2054,7 @@ lcs_probe_device(struct ccwgroup_device *ccwgdev) ccwgdev->cdev[0]->handler = lcs_irq; ccwgdev->cdev[1]->handler = lcs_irq; card->gdev = ccwgdev; - INIT_WORK(&card->kernel_thread_starter, - (void *) lcs_start_kernel_thread, card); + INIT_WORK(&card->kernel_thread_starter, lcs_start_kernel_thread); card->thread_start_mask = 0; card->thread_allowed_mask = 0; card->thread_running_mask = 0; diff --git a/trunk/drivers/s390/net/qeth_main.c b/trunk/drivers/s390/net/qeth_main.c index 7fdc5272c446..2bde4f1fb9c2 100644 --- a/trunk/drivers/s390/net/qeth_main.c +++ b/trunk/drivers/s390/net/qeth_main.c @@ -1039,8 +1039,9 @@ qeth_do_start_thread(struct qeth_card *card, unsigned long thread) } static void -qeth_start_kernel_thread(struct qeth_card *card) +qeth_start_kernel_thread(struct work_struct *work) { + struct qeth_card *card = container_of(work, struct qeth_card, kernel_thread_starter); QETH_DBF_TEXT(trace , 2, "strthrd"); if (card->read.state != CH_STATE_UP && @@ -1103,8 +1104,7 @@ qeth_setup_card(struct qeth_card *card) card->thread_start_mask = 0; card->thread_allowed_mask = 0; card->thread_running_mask = 0; - INIT_WORK(&card->kernel_thread_starter, - (void *)qeth_start_kernel_thread,card); + INIT_WORK(&card->kernel_thread_starter, qeth_start_kernel_thread); INIT_LIST_HEAD(&card->ip_list); card->ip_tbd_list = kmalloc(sizeof(struct list_head), GFP_KERNEL); if (!card->ip_tbd_list) { diff --git a/trunk/drivers/s390/scsi/zfcp_def.h b/trunk/drivers/s390/scsi/zfcp_def.h index 74c0eac083e4..32933ed54b8a 100644 --- a/trunk/drivers/s390/scsi/zfcp_def.h +++ b/trunk/drivers/s390/scsi/zfcp_def.h @@ -1032,9 +1032,9 @@ struct zfcp_data { wwn_t init_wwpn; fcp_lun_t init_fcp_lun; char *driver_version; - kmem_cache_t *fsf_req_qtcb_cache; - kmem_cache_t *sr_buffer_cache; - kmem_cache_t *gid_pn_cache; + struct kmem_cache *fsf_req_qtcb_cache; + struct kmem_cache *sr_buffer_cache; + struct kmem_cache *gid_pn_cache; }; /** diff --git a/trunk/drivers/s390/scsi/zfcp_fsf.c b/trunk/drivers/s390/scsi/zfcp_fsf.c index 277826cdd0c8..067f1519eb04 100644 --- a/trunk/drivers/s390/scsi/zfcp_fsf.c +++ b/trunk/drivers/s390/scsi/zfcp_fsf.c @@ -109,7 +109,7 @@ zfcp_fsf_req_alloc(mempool_t *pool, int req_flags) ptr = kmalloc(size, GFP_ATOMIC); else ptr = kmem_cache_alloc(zfcp_data.fsf_req_qtcb_cache, - SLAB_ATOMIC); + GFP_ATOMIC); } if (unlikely(!ptr)) diff --git a/trunk/drivers/sbus/char/bpp.c b/trunk/drivers/sbus/char/bpp.c index 385f4f768311..ac7d1258efee 100644 --- a/trunk/drivers/sbus/char/bpp.c +++ b/trunk/drivers/sbus/char/bpp.c @@ -621,7 +621,7 @@ static long read_ecp(unsigned minor, char __user *c, unsigned long cnt) static ssize_t bpp_read(struct file *f, char __user *c, size_t cnt, loff_t * ppos) { long rc; - unsigned minor = iminor(f->f_dentry->d_inode); + unsigned minor = iminor(f->f_path.dentry->d_inode); if (minor >= BPP_NO) return -ENODEV; if (!instances[minor].present) return -ENODEV; @@ -774,7 +774,7 @@ static long write_ecp(unsigned minor, const char __user *c, unsigned long cnt) static ssize_t bpp_write(struct file *f, const char __user *c, size_t cnt, loff_t * ppos) { long errno = 0; - unsigned minor = iminor(f->f_dentry->d_inode); + unsigned minor = iminor(f->f_path.dentry->d_inode); if (minor >= BPP_NO) return -ENODEV; if (!instances[minor].present) return -ENODEV; diff --git a/trunk/drivers/sbus/char/cpwatchdog.c b/trunk/drivers/sbus/char/cpwatchdog.c index f5803ecb1999..ad1c7db96cb4 100644 --- a/trunk/drivers/sbus/char/cpwatchdog.c +++ b/trunk/drivers/sbus/char/cpwatchdog.c @@ -404,7 +404,7 @@ static long wd_compat_ioctl(struct file *file, unsigned int cmd, case WIOCSTOP: case WIOCGSTAT: lock_kernel(); - rval = wd_ioctl(file->f_dentry->d_inode, file, cmd, arg); + rval = wd_ioctl(file->f_path.dentry->d_inode, file, cmd, arg); unlock_kernel(); break; /* everything else is handled by the generic compat layer */ diff --git a/trunk/drivers/sbus/char/display7seg.c b/trunk/drivers/sbus/char/display7seg.c index d92bc8827a9e..a4909e0c7f83 100644 --- a/trunk/drivers/sbus/char/display7seg.c +++ b/trunk/drivers/sbus/char/display7seg.c @@ -121,7 +121,7 @@ static long d7s_ioctl(struct file *file, unsigned int cmd, unsigned long arg) __u8 ireg = 0; int error = 0; - if (D7S_MINOR != iminor(file->f_dentry->d_inode)) + if (D7S_MINOR != iminor(file->f_path.dentry->d_inode)) return -ENODEV; lock_kernel(); diff --git a/trunk/drivers/sbus/char/openprom.c b/trunk/drivers/sbus/char/openprom.c index 81ba2d71cee2..4e2a0e2dcc2e 100644 --- a/trunk/drivers/sbus/char/openprom.c +++ b/trunk/drivers/sbus/char/openprom.c @@ -676,7 +676,7 @@ static long openprom_compat_ioctl(struct file *file, unsigned int cmd, case OPROMSETCUR: case OPROMPCI2NODE: case OPROMPATH2NODE: - rval = openprom_ioctl(file->f_dentry->d_inode, file, cmd, arg); + rval = openprom_ioctl(file->f_path.dentry->d_inode, file, cmd, arg); break; } diff --git a/trunk/drivers/sbus/char/vfc_dev.c b/trunk/drivers/sbus/char/vfc_dev.c index 55b2b31bd7ab..2722af5d3404 100644 --- a/trunk/drivers/sbus/char/vfc_dev.c +++ b/trunk/drivers/sbus/char/vfc_dev.c @@ -610,7 +610,7 @@ static int vfc_mmap(struct file *file, struct vm_area_struct *vma) unsigned int map_size, ret, map_offset; struct vfc_dev *dev; - dev = vfc_get_dev_ptr(iminor(file->f_dentry->d_inode)); + dev = vfc_get_dev_ptr(iminor(file->f_path.dentry->d_inode)); if(dev == NULL) return -ENODEV; diff --git a/trunk/drivers/scsi/53c700.c b/trunk/drivers/scsi/53c700.c index 562432d017b0..68103e508db7 100644 --- a/trunk/drivers/scsi/53c700.c +++ b/trunk/drivers/scsi/53c700.c @@ -313,7 +313,7 @@ NCR_700_detect(struct scsi_host_template *tpnt, hostdata->status = memory + STATUS_OFFSET; /* all of these offsets are L1_CACHE_BYTES separated. It is fatal * if this isn't sufficient separation to avoid dma flushing issues */ - BUG_ON(!dma_is_consistent(pScript) && L1_CACHE_BYTES < dma_get_cache_alignment()); + BUG_ON(!dma_is_consistent(hostdata->dev, pScript) && L1_CACHE_BYTES < dma_get_cache_alignment()); hostdata->slots = (struct NCR_700_command_slot *)(memory + SLOTS_OFFSET); hostdata->dev = dev; @@ -362,11 +362,11 @@ NCR_700_detect(struct scsi_host_template *tpnt, for (j = 0; j < PATCHES; j++) script[LABELPATCHES[j]] = bS_to_host(pScript + SCRIPT[LABELPATCHES[j]]); /* now patch up fixed addresses. */ - script_patch_32(script, MessageLocation, + script_patch_32(hostdata->dev, script, MessageLocation, pScript + MSGOUT_OFFSET); - script_patch_32(script, StatusAddress, + script_patch_32(hostdata->dev, script, StatusAddress, pScript + STATUS_OFFSET); - script_patch_32(script, ReceiveMsgAddress, + script_patch_32(hostdata->dev, script, ReceiveMsgAddress, pScript + MSGIN_OFFSET); hostdata->script = script; @@ -622,8 +622,10 @@ NCR_700_scsi_done(struct NCR_700_Host_Parameters *hostdata, dma_unmap_single(hostdata->dev, slot->dma_handle, sizeof(SCp->sense_buffer), DMA_FROM_DEVICE); /* restore the old result if the request sense was * successful */ - if(result == 0) + if (result == 0) result = cmnd[7]; + /* restore the original length */ + SCp->cmd_len = cmnd[8]; } else NCR_700_unmap(hostdata, SCp, slot); @@ -819,8 +821,9 @@ process_extended_message(struct Scsi_Host *host, shost_printk(KERN_WARNING, host, "Unexpected SDTR msg\n"); hostdata->msgout[0] = A_REJECT_MSG; - dma_cache_sync(hostdata->msgout, 1, DMA_TO_DEVICE); - script_patch_16(hostdata->script, MessageCount, 1); + dma_cache_sync(hostdata->dev, hostdata->msgout, 1, DMA_TO_DEVICE); + script_patch_16(hostdata->dev, hostdata->script, + MessageCount, 1); /* SendMsgOut returns, so set up the return * address */ resume_offset = hostdata->pScript + Ent_SendMessageWithATN; @@ -831,8 +834,9 @@ process_extended_message(struct Scsi_Host *host, printk(KERN_INFO "scsi%d: (%d:%d), Unsolicited WDTR after CMD, Rejecting\n", host->host_no, pun, lun); hostdata->msgout[0] = A_REJECT_MSG; - dma_cache_sync(hostdata->msgout, 1, DMA_TO_DEVICE); - script_patch_16(hostdata->script, MessageCount, 1); + dma_cache_sync(hostdata->dev, hostdata->msgout, 1, DMA_TO_DEVICE); + script_patch_16(hostdata->dev, hostdata->script, MessageCount, + 1); resume_offset = hostdata->pScript + Ent_SendMessageWithATN; break; @@ -845,8 +849,9 @@ process_extended_message(struct Scsi_Host *host, printk("\n"); /* just reject it */ hostdata->msgout[0] = A_REJECT_MSG; - dma_cache_sync(hostdata->msgout, 1, DMA_TO_DEVICE); - script_patch_16(hostdata->script, MessageCount, 1); + dma_cache_sync(hostdata->dev, hostdata->msgout, 1, DMA_TO_DEVICE); + script_patch_16(hostdata->dev, hostdata->script, MessageCount, + 1); /* SendMsgOut returns, so set up the return * address */ resume_offset = hostdata->pScript + Ent_SendMessageWithATN; @@ -927,8 +932,9 @@ process_message(struct Scsi_Host *host, struct NCR_700_Host_Parameters *hostdata printk("\n"); /* just reject it */ hostdata->msgout[0] = A_REJECT_MSG; - dma_cache_sync(hostdata->msgout, 1, DMA_TO_DEVICE); - script_patch_16(hostdata->script, MessageCount, 1); + dma_cache_sync(hostdata->dev, hostdata->msgout, 1, DMA_TO_DEVICE); + script_patch_16(hostdata->dev, hostdata->script, MessageCount, + 1); /* SendMsgOut returns, so set up the return * address */ resume_offset = hostdata->pScript + Ent_SendMessageWithATN; @@ -937,7 +943,7 @@ process_message(struct Scsi_Host *host, struct NCR_700_Host_Parameters *hostdata } NCR_700_writel(temp, host, TEMP_REG); /* set us up to receive another message */ - dma_cache_sync(hostdata->msgin, MSG_ARRAY_SIZE, DMA_FROM_DEVICE); + dma_cache_sync(hostdata->dev, hostdata->msgin, MSG_ARRAY_SIZE, DMA_FROM_DEVICE); return resume_offset; } @@ -1007,6 +1013,9 @@ process_script_interrupt(__u32 dsps, __u32 dsp, struct scsi_cmnd *SCp, * of the command */ cmnd[6] = NCR_700_INTERNAL_SENSE_MAGIC; cmnd[7] = hostdata->status[0]; + cmnd[8] = SCp->cmd_len; + SCp->cmd_len = 6; /* command length for + * REQUEST_SENSE */ slot->pCmd = dma_map_single(hostdata->dev, cmnd, MAX_COMMAND_SIZE, DMA_TO_DEVICE); slot->dma_handle = dma_map_single(hostdata->dev, SCp->sense_buffer, sizeof(SCp->sense_buffer), DMA_FROM_DEVICE); slot->SG[0].ins = bS_to_host(SCRIPT_MOVE_DATA_IN | sizeof(SCp->sense_buffer)); @@ -1014,9 +1023,9 @@ process_script_interrupt(__u32 dsps, __u32 dsp, struct scsi_cmnd *SCp, slot->SG[1].ins = bS_to_host(SCRIPT_RETURN); slot->SG[1].pAddr = 0; slot->resume_offset = hostdata->pScript; - dma_cache_sync(slot->SG, sizeof(slot->SG[0])*2, DMA_TO_DEVICE); - dma_cache_sync(SCp->sense_buffer, sizeof(SCp->sense_buffer), DMA_FROM_DEVICE); - + dma_cache_sync(hostdata->dev, slot->SG, sizeof(slot->SG[0])*2, DMA_TO_DEVICE); + dma_cache_sync(hostdata->dev, SCp->sense_buffer, sizeof(SCp->sense_buffer), DMA_FROM_DEVICE); + /* queue the command for reissue */ slot->state = NCR_700_SLOT_QUEUED; slot->flags = NCR_700_FLAG_AUTOSENSE; @@ -1131,11 +1140,12 @@ process_script_interrupt(__u32 dsps, __u32 dsp, struct scsi_cmnd *SCp, hostdata->cmd = slot->cmnd; /* re-patch for this command */ - script_patch_32_abs(hostdata->script, CommandAddress, - slot->pCmd); - script_patch_16(hostdata->script, + script_patch_32_abs(hostdata->dev, hostdata->script, + CommandAddress, slot->pCmd); + script_patch_16(hostdata->dev, hostdata->script, CommandCount, slot->cmnd->cmd_len); - script_patch_32_abs(hostdata->script, SGScriptStartAddress, + script_patch_32_abs(hostdata->dev, hostdata->script, + SGScriptStartAddress, to32bit(&slot->pSG[0].ins)); /* Note: setting SXFER only works if we're @@ -1145,13 +1155,13 @@ process_script_interrupt(__u32 dsps, __u32 dsp, struct scsi_cmnd *SCp, * should therefore always clear ACK */ NCR_700_writeb(NCR_700_get_SXFER(hostdata->cmd->device), host, SXFER_REG); - dma_cache_sync(hostdata->msgin, + dma_cache_sync(hostdata->dev, hostdata->msgin, MSG_ARRAY_SIZE, DMA_FROM_DEVICE); - dma_cache_sync(hostdata->msgout, + dma_cache_sync(hostdata->dev, hostdata->msgout, MSG_ARRAY_SIZE, DMA_TO_DEVICE); /* I'm just being paranoid here, the command should * already have been flushed from the cache */ - dma_cache_sync(slot->cmnd->cmnd, + dma_cache_sync(hostdata->dev, slot->cmnd->cmnd, slot->cmnd->cmd_len, DMA_TO_DEVICE); @@ -1215,7 +1225,7 @@ process_script_interrupt(__u32 dsps, __u32 dsp, struct scsi_cmnd *SCp, hostdata->reselection_id = reselection_id; /* just in case we have a stale simple tag message, clear it */ hostdata->msgin[1] = 0; - dma_cache_sync(hostdata->msgin, + dma_cache_sync(hostdata->dev, hostdata->msgin, MSG_ARRAY_SIZE, DMA_BIDIRECTIONAL); if(hostdata->tag_negotiated & (1<pScript + Ent_GetReselectionWithTag; @@ -1331,7 +1341,7 @@ process_selection(struct Scsi_Host *host, __u32 dsp) hostdata->cmd = NULL; /* clear any stale simple tag message */ hostdata->msgin[1] = 0; - dma_cache_sync(hostdata->msgin, MSG_ARRAY_SIZE, + dma_cache_sync(hostdata->dev, hostdata->msgin, MSG_ARRAY_SIZE, DMA_BIDIRECTIONAL); if(id == 0xff) { @@ -1428,29 +1438,30 @@ NCR_700_start_command(struct scsi_cmnd *SCp) NCR_700_set_flag(SCp->device, NCR_700_DEV_BEGIN_SYNC_NEGOTIATION); } - script_patch_16(hostdata->script, MessageCount, count); + script_patch_16(hostdata->dev, hostdata->script, MessageCount, count); - script_patch_ID(hostdata->script, + script_patch_ID(hostdata->dev, hostdata->script, Device_ID, 1<script, CommandAddress, + script_patch_32_abs(hostdata->dev, hostdata->script, CommandAddress, slot->pCmd); - script_patch_16(hostdata->script, CommandCount, SCp->cmd_len); + script_patch_16(hostdata->dev, hostdata->script, CommandCount, + SCp->cmd_len); /* finally plumb the beginning of the SG list into the script * */ - script_patch_32_abs(hostdata->script, SGScriptStartAddress, - to32bit(&slot->pSG[0].ins)); + script_patch_32_abs(hostdata->dev, hostdata->script, + SGScriptStartAddress, to32bit(&slot->pSG[0].ins)); NCR_700_clear_fifo(SCp->device->host); if(slot->resume_offset == 0) slot->resume_offset = hostdata->pScript; /* now perform all the writebacks and invalidates */ - dma_cache_sync(hostdata->msgout, count, DMA_TO_DEVICE); - dma_cache_sync(hostdata->msgin, MSG_ARRAY_SIZE, + dma_cache_sync(hostdata->dev, hostdata->msgout, count, DMA_TO_DEVICE); + dma_cache_sync(hostdata->dev, hostdata->msgin, MSG_ARRAY_SIZE, DMA_FROM_DEVICE); - dma_cache_sync(SCp->cmnd, SCp->cmd_len, DMA_TO_DEVICE); - dma_cache_sync(hostdata->status, 1, DMA_FROM_DEVICE); + dma_cache_sync(hostdata->dev, SCp->cmnd, SCp->cmd_len, DMA_TO_DEVICE); + dma_cache_sync(hostdata->dev, hostdata->status, 1, DMA_FROM_DEVICE); /* set the synchronous period/offset */ NCR_700_writeb(NCR_700_get_SXFER(SCp->device), @@ -1626,7 +1637,7 @@ NCR_700_intr(int irq, void *dev_id) slot->SG[i].ins = bS_to_host(SCRIPT_NOP); slot->SG[i].pAddr = 0; } - dma_cache_sync(slot->SG, sizeof(slot->SG), DMA_TO_DEVICE); + dma_cache_sync(hostdata->dev, slot->SG, sizeof(slot->SG), DMA_TO_DEVICE); /* and pretend we disconnected after * the command phase */ resume_offset = hostdata->pScript + Ent_MsgInDuringData; @@ -1892,9 +1903,9 @@ NCR_700_queuecommand(struct scsi_cmnd *SCp, void (*done)(struct scsi_cmnd *)) } slot->SG[i].ins = bS_to_host(SCRIPT_RETURN); slot->SG[i].pAddr = 0; - dma_cache_sync(slot->SG, sizeof(slot->SG), DMA_TO_DEVICE); + dma_cache_sync(hostdata->dev, slot->SG, sizeof(slot->SG), DMA_TO_DEVICE); DEBUG((" SETTING %08lx to %x\n", - (&slot->pSG[i].ins), + (&slot->pSG[i].ins), slot->SG[i].ins)); } slot->resume_offset = 0; diff --git a/trunk/drivers/scsi/53c700.h b/trunk/drivers/scsi/53c700.h index f5c3caf344a7..f38822db4210 100644 --- a/trunk/drivers/scsi/53c700.h +++ b/trunk/drivers/scsi/53c700.h @@ -415,31 +415,31 @@ struct NCR_700_Host_Parameters { #define NCR_710_MIN_XFERP 0 #define NCR_700_MIN_PERIOD 25 /* for SDTR message, 100ns */ -#define script_patch_32(script, symbol, value) \ +#define script_patch_32(dev, script, symbol, value) \ { \ int i; \ for(i=0; i< (sizeof(A_##symbol##_used) / sizeof(__u32)); i++) { \ __u32 val = bS_to_cpu((script)[A_##symbol##_used[i]]) + value; \ (script)[A_##symbol##_used[i]] = bS_to_host(val); \ - dma_cache_sync(&(script)[A_##symbol##_used[i]], 4, DMA_TO_DEVICE); \ + dma_cache_sync((dev), &(script)[A_##symbol##_used[i]], 4, DMA_TO_DEVICE); \ DEBUG((" script, patching %s at %d to 0x%lx\n", \ #symbol, A_##symbol##_used[i], (value))); \ } \ } -#define script_patch_32_abs(script, symbol, value) \ +#define script_patch_32_abs(dev, script, symbol, value) \ { \ int i; \ for(i=0; i< (sizeof(A_##symbol##_used) / sizeof(__u32)); i++) { \ (script)[A_##symbol##_used[i]] = bS_to_host(value); \ - dma_cache_sync(&(script)[A_##symbol##_used[i]], 4, DMA_TO_DEVICE); \ + dma_cache_sync((dev), &(script)[A_##symbol##_used[i]], 4, DMA_TO_DEVICE); \ DEBUG((" script, patching %s at %d to 0x%lx\n", \ #symbol, A_##symbol##_used[i], (value))); \ } \ } /* Used for patching the SCSI ID in the SELECT instruction */ -#define script_patch_ID(script, symbol, value) \ +#define script_patch_ID(dev, script, symbol, value) \ { \ int i; \ for(i=0; i< (sizeof(A_##symbol##_used) / sizeof(__u32)); i++) { \ @@ -447,13 +447,13 @@ struct NCR_700_Host_Parameters { val &= 0xff00ffff; \ val |= ((value) & 0xff) << 16; \ (script)[A_##symbol##_used[i]] = bS_to_host(val); \ - dma_cache_sync(&(script)[A_##symbol##_used[i]], 4, DMA_TO_DEVICE); \ + dma_cache_sync((dev), &(script)[A_##symbol##_used[i]], 4, DMA_TO_DEVICE); \ DEBUG((" script, patching ID field %s at %d to 0x%x\n", \ #symbol, A_##symbol##_used[i], val)); \ } \ } -#define script_patch_16(script, symbol, value) \ +#define script_patch_16(dev, script, symbol, value) \ { \ int i; \ for(i=0; i< (sizeof(A_##symbol##_used) / sizeof(__u32)); i++) { \ @@ -461,7 +461,7 @@ struct NCR_700_Host_Parameters { val &= 0xffff0000; \ val |= ((value) & 0xffff); \ (script)[A_##symbol##_used[i]] = bS_to_host(val); \ - dma_cache_sync(&(script)[A_##symbol##_used[i]], 4, DMA_TO_DEVICE); \ + dma_cache_sync((dev), &(script)[A_##symbol##_used[i]], 4, DMA_TO_DEVICE); \ DEBUG((" script, patching short field %s at %d to 0x%x\n", \ #symbol, A_##symbol##_used[i], val)); \ } \ diff --git a/trunk/drivers/scsi/BusLogic.c b/trunk/drivers/scsi/BusLogic.c index cdd033724786..3075204915c8 100644 --- a/trunk/drivers/scsi/BusLogic.c +++ b/trunk/drivers/scsi/BusLogic.c @@ -2186,21 +2186,21 @@ static int __init BusLogic_init(void) if (BusLogic_ProbeOptions.NoProbe) return -ENODEV; - BusLogic_ProbeInfoList = (struct BusLogic_ProbeInfo *) - kmalloc(BusLogic_MaxHostAdapters * sizeof(struct BusLogic_ProbeInfo), GFP_ATOMIC); + BusLogic_ProbeInfoList = + kzalloc(BusLogic_MaxHostAdapters * sizeof(struct BusLogic_ProbeInfo), GFP_KERNEL); if (BusLogic_ProbeInfoList == NULL) { BusLogic_Error("BusLogic: Unable to allocate Probe Info List\n", NULL); return -ENOMEM; } - memset(BusLogic_ProbeInfoList, 0, BusLogic_MaxHostAdapters * sizeof(struct BusLogic_ProbeInfo)); - PrototypeHostAdapter = (struct BusLogic_HostAdapter *) - kmalloc(sizeof(struct BusLogic_HostAdapter), GFP_ATOMIC); + + PrototypeHostAdapter = + kzalloc(sizeof(struct BusLogic_HostAdapter), GFP_KERNEL); if (PrototypeHostAdapter == NULL) { kfree(BusLogic_ProbeInfoList); BusLogic_Error("BusLogic: Unable to allocate Prototype " "Host Adapter\n", NULL); return -ENOMEM; } - memset(PrototypeHostAdapter, 0, sizeof(struct BusLogic_HostAdapter)); + #ifdef MODULE if (BusLogic != NULL) BusLogic_Setup(BusLogic); diff --git a/trunk/drivers/scsi/Kconfig b/trunk/drivers/scsi/Kconfig index 9540eb8efdcb..69569096dae5 100644 --- a/trunk/drivers/scsi/Kconfig +++ b/trunk/drivers/scsi/Kconfig @@ -29,6 +29,13 @@ config SCSI However, do not compile this as a module if your root file system (the one containing the directory /) is located on a SCSI device. +config SCSI_TGT + tristate "SCSI target support" + depends on SCSI && EXPERIMENTAL + ---help--- + If you want to use SCSI target mode drivers enable this option. + If you choose M, the module will be called scsi_tgt. + config SCSI_NETLINK bool default n @@ -216,6 +223,23 @@ config SCSI_LOGGING there should be no noticeable performance impact as long as you have logging turned off. +config SCSI_SCAN_ASYNC + bool "Asynchronous SCSI scanning" + depends on SCSI + help + The SCSI subsystem can probe for devices while the rest of the + system continues booting, and even probe devices on different + busses in parallel, leading to a significant speed-up. + If you have built SCSI as modules, enabling this option can + be a problem as the devices may not have been found by the + time your system expects them to have been. You can load the + scsi_wait_scan module to ensure that all scans have completed. + If you build your SCSI drivers into the kernel, then everything + will work fine if you say Y here. + + You can override this choice by specifying scsi_mod.scan="sync" + or "async" on the kernel's command line. + menu "SCSI Transports" depends on SCSI @@ -797,6 +821,20 @@ config SCSI_IBMVSCSI To compile this driver as a module, choose M here: the module will be called ibmvscsic. +config SCSI_IBMVSCSIS + tristate "IBM Virtual SCSI Server support" + depends on PPC_PSERIES && SCSI_TGT && SCSI_SRP + help + This is the SRP target driver for IBM pSeries virtual environments. + + The userspace component needed to initialize the driver and + documentation can be found: + + http://stgt.berlios.de/ + + To compile this driver as a module, choose M here: the + module will be called ibmvstgt. + config SCSI_INITIO tristate "Initio 9100U(W) support" depends on PCI && SCSI @@ -944,8 +982,13 @@ config SCSI_STEX tristate "Promise SuperTrak EX Series support" depends on PCI && SCSI ---help--- - This driver supports Promise SuperTrak EX8350/8300/16350/16300 - Storage controllers. + This driver supports Promise SuperTrak EX series storage controllers. + + Promise provides Linux RAID configuration utility for these + controllers. Please visit to download. + + To compile this driver as a module, choose M here: the + module will be called stex. config SCSI_SYM53C8XX_2 tristate "SYM53C8XX Version 2 SCSI support" @@ -1026,6 +1069,7 @@ config SCSI_IPR config SCSI_IPR_TRACE bool "enable driver internal trace" depends on SCSI_IPR + default y help If you say Y here, the driver will trace all commands issued to the adapter. Performance impact is minimal. Trace can be @@ -1034,6 +1078,7 @@ config SCSI_IPR_TRACE config SCSI_IPR_DUMP bool "enable adapter dump support" depends on SCSI_IPR + default y help If you say Y here, the driver will support adapter crash dump. If you enable this support, the iprdump daemon can be used @@ -1734,6 +1779,16 @@ config ZFCP called zfcp. If you want to compile it as a module, say M here and read . +config SCSI_SRP + tristate "SCSI RDMA Protocol helper library" + depends on SCSI && PCI + select SCSI_TGT + help + If you wish to use SRP target drivers, say Y. + + To compile this driver as a module, choose M here: the + module will be called libsrp. + endmenu source "drivers/scsi/pcmcia/Kconfig" diff --git a/trunk/drivers/scsi/Makefile b/trunk/drivers/scsi/Makefile index bcca39c3bcbf..bd7c9888f7f4 100644 --- a/trunk/drivers/scsi/Makefile +++ b/trunk/drivers/scsi/Makefile @@ -21,6 +21,7 @@ CFLAGS_seagate.o = -DARBITRATE -DPARITY -DSEAGATE_USE_ASM subdir-$(CONFIG_PCMCIA) += pcmcia obj-$(CONFIG_SCSI) += scsi_mod.o +obj-$(CONFIG_SCSI_TGT) += scsi_tgt.o obj-$(CONFIG_RAID_ATTRS) += raid_class.o @@ -125,7 +126,9 @@ obj-$(CONFIG_SCSI_FCAL) += fcal.o obj-$(CONFIG_SCSI_LASI700) += 53c700.o lasi700.o obj-$(CONFIG_SCSI_NSP32) += nsp32.o obj-$(CONFIG_SCSI_IPR) += ipr.o +obj-$(CONFIG_SCSI_SRP) += libsrp.o obj-$(CONFIG_SCSI_IBMVSCSI) += ibmvscsi/ +obj-$(CONFIG_SCSI_IBMVSCSIS) += ibmvscsi/ obj-$(CONFIG_SCSI_HPTIOP) += hptiop.o obj-$(CONFIG_SCSI_STEX) += stex.o @@ -141,6 +144,8 @@ obj-$(CONFIG_CHR_DEV_SCH) += ch.o # This goes last, so that "real" scsi devices probe earlier obj-$(CONFIG_SCSI_DEBUG) += scsi_debug.o +obj-$(CONFIG_SCSI) += scsi_wait_scan.o + scsi_mod-y += scsi.o hosts.o scsi_ioctl.o constants.o \ scsicam.o scsi_error.o scsi_lib.o \ scsi_scan.o scsi_sysfs.o \ @@ -149,6 +154,8 @@ scsi_mod-$(CONFIG_SCSI_NETLINK) += scsi_netlink.o scsi_mod-$(CONFIG_SYSCTL) += scsi_sysctl.o scsi_mod-$(CONFIG_SCSI_PROC_FS) += scsi_proc.o +scsi_tgt-y += scsi_tgt_lib.o scsi_tgt_if.o + sd_mod-objs := sd.o sr_mod-objs := sr.o sr_ioctl.o sr_vendor.o ncr53c8xx-flags-$(CONFIG_SCSI_ZALON) \ diff --git a/trunk/drivers/scsi/NCR5380.c b/trunk/drivers/scsi/NCR5380.c index a6aa91072880..bb3cb3360541 100644 --- a/trunk/drivers/scsi/NCR5380.c +++ b/trunk/drivers/scsi/NCR5380.c @@ -849,7 +849,7 @@ static int __devinit NCR5380_init(struct Scsi_Host *instance, int flags) hostdata->issue_queue = NULL; hostdata->disconnected_queue = NULL; - INIT_WORK(&hostdata->coroutine, NCR5380_main, hostdata); + INIT_DELAYED_WORK(&hostdata->coroutine, NCR5380_main); #ifdef NCR5380_STATS for (i = 0; i < 8; ++i) { @@ -1016,7 +1016,7 @@ static int NCR5380_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) /* Run the coroutine if it isn't already running. */ /* Kick off command processing */ - schedule_work(&hostdata->coroutine); + schedule_delayed_work(&hostdata->coroutine, 0); return 0; } @@ -1033,9 +1033,10 @@ static int NCR5380_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) * host lock and called routines may take the isa dma lock. */ -static void NCR5380_main(void *p) +static void NCR5380_main(struct work_struct *work) { - struct NCR5380_hostdata *hostdata = p; + struct NCR5380_hostdata *hostdata = + container_of(work, struct NCR5380_hostdata, coroutine.work); struct Scsi_Host *instance = hostdata->host; Scsi_Cmnd *tmp, *prev; int done; @@ -1221,7 +1222,7 @@ static irqreturn_t NCR5380_intr(int irq, void *dev_id) } /* if BASR_IRQ */ spin_unlock_irqrestore(instance->host_lock, flags); if(!done) - schedule_work(&hostdata->coroutine); + schedule_delayed_work(&hostdata->coroutine, 0); } while (!done); return IRQ_HANDLED; } diff --git a/trunk/drivers/scsi/NCR5380.h b/trunk/drivers/scsi/NCR5380.h index 1bc73de496b0..713a108c02ef 100644 --- a/trunk/drivers/scsi/NCR5380.h +++ b/trunk/drivers/scsi/NCR5380.h @@ -271,7 +271,7 @@ struct NCR5380_hostdata { unsigned long time_expires; /* in jiffies, set prior to sleeping */ int select_time; /* timer in select for target response */ volatile Scsi_Cmnd *selecting; - struct work_struct coroutine; /* our co-routine */ + struct delayed_work coroutine; /* our co-routine */ #ifdef NCR5380_STATS unsigned timebase; /* Base for time calcs */ long time_read[8]; /* time to do reads */ @@ -298,7 +298,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance); #ifndef DONT_USE_INTR static irqreturn_t NCR5380_intr(int irq, void *dev_id); #endif -static void NCR5380_main(void *ptr); +static void NCR5380_main(struct work_struct *work); static void NCR5380_print_options(struct Scsi_Host *instance); #ifdef NDEBUG static void NCR5380_print_phase(struct Scsi_Host *instance); diff --git a/trunk/drivers/scsi/NCR53c406a.c b/trunk/drivers/scsi/NCR53c406a.c index d4613815f685..8578555d58fd 100644 --- a/trunk/drivers/scsi/NCR53c406a.c +++ b/trunk/drivers/scsi/NCR53c406a.c @@ -220,9 +220,11 @@ static void *addresses[] = { static unsigned short ports[] = { 0x230, 0x330, 0x280, 0x290, 0x330, 0x340, 0x300, 0x310, 0x348, 0x350 }; #define PORT_COUNT ARRAY_SIZE(ports) +#ifndef MODULE /* possible interrupt channels */ static unsigned short intrs[] = { 10, 11, 12, 15 }; #define INTR_COUNT ARRAY_SIZE(intrs) +#endif /* !MODULE */ /* signatures for NCR 53c406a based controllers */ #if USE_BIOS @@ -605,6 +607,7 @@ static int NCR53c406a_release(struct Scsi_Host *shost) return 0; } +#ifndef MODULE /* called from init/main.c */ static int __init NCR53c406a_setup(char *str) { @@ -661,6 +664,8 @@ static int __init NCR53c406a_setup(char *str) __setup("ncr53c406a=", NCR53c406a_setup); +#endif /* !MODULE */ + static const char *NCR53c406a_info(struct Scsi_Host *SChost) { DEB(printk("NCR53c406a_info called\n")); diff --git a/trunk/drivers/scsi/aacraid/aacraid.h b/trunk/drivers/scsi/aacraid/aacraid.h index eb3ed91bac79..4f8b4c53d435 100644 --- a/trunk/drivers/scsi/aacraid/aacraid.h +++ b/trunk/drivers/scsi/aacraid/aacraid.h @@ -11,8 +11,8 @@ *----------------------------------------------------------------------------*/ #ifndef AAC_DRIVER_BUILD -# define AAC_DRIVER_BUILD 2409 -# define AAC_DRIVER_BRANCH "-mh2" +# define AAC_DRIVER_BUILD 2423 +# define AAC_DRIVER_BRANCH "-mh3" #endif #define MAXIMUM_NUM_CONTAINERS 32 diff --git a/trunk/drivers/scsi/aacraid/commsup.c b/trunk/drivers/scsi/aacraid/commsup.c index 19e42ac07cb2..4893a6d06a33 100644 --- a/trunk/drivers/scsi/aacraid/commsup.c +++ b/trunk/drivers/scsi/aacraid/commsup.c @@ -518,6 +518,7 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size, */ unsigned long count = 36000000L; /* 3 minutes */ while (down_trylock(&fibptr->event_wait)) { + int blink; if (--count == 0) { spin_lock_irqsave(q->lock, qflags); q->numpending--; @@ -530,6 +531,14 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size, } return -ETIMEDOUT; } + if ((blink = aac_adapter_check_health(dev)) > 0) { + if (wait == -1) { + printk(KERN_ERR "aacraid: aac_fib_send: adapter blinkLED 0x%x.\n" + "Usually a result of a serious unrecoverable hardware problem\n", + blink); + } + return -EFAULT; + } udelay(5); } } else if (down_interruptible(&fibptr->event_wait)) { @@ -1093,6 +1102,20 @@ static int _aac_reset_adapter(struct aac_dev *aac) goto out; } + /* + * Loop through the fibs, close the synchronous FIBS + */ + for (index = 0; index < (aac->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB); index++) { + struct fib *fib = &aac->fibs[index]; + if (!(fib->hw_fib->header.XferState & cpu_to_le32(NoResponseExpected | Async)) && + (fib->hw_fib->header.XferState & cpu_to_le32(ResponseExpected))) { + unsigned long flagv; + spin_lock_irqsave(&fib->event_lock, flagv); + up(&fib->event_wait); + spin_unlock_irqrestore(&fib->event_lock, flagv); + schedule(); + } + } index = aac->cardtype; /* diff --git a/trunk/drivers/scsi/aha152x.c b/trunk/drivers/scsi/aha152x.c index 306f46b85a55..0cec742d12e9 100644 --- a/trunk/drivers/scsi/aha152x.c +++ b/trunk/drivers/scsi/aha152x.c @@ -1443,7 +1443,7 @@ static struct work_struct aha152x_tq; * Run service completions on the card with interrupts enabled. * */ -static void run(void) +static void run(struct work_struct *work) { struct aha152x_hostdata *hd; @@ -1499,7 +1499,7 @@ static irqreturn_t intr(int irqno, void *dev_id) HOSTDATA(shpnt)->service=1; /* Poke the BH handler */ - INIT_WORK(&aha152x_tq, (void *) run, NULL); + INIT_WORK(&aha152x_tq, run); schedule_work(&aha152x_tq); } DO_UNLOCK(flags); diff --git a/trunk/drivers/scsi/aha1740.c b/trunk/drivers/scsi/aha1740.c index c3c38a7e8d32..d7af9c63a04d 100644 --- a/trunk/drivers/scsi/aha1740.c +++ b/trunk/drivers/scsi/aha1740.c @@ -586,7 +586,7 @@ static struct scsi_host_template aha1740_template = { static int aha1740_probe (struct device *dev) { - int slotbase; + int slotbase, rc; unsigned int irq_level, irq_type, translation; struct Scsi_Host *shpnt; struct aha1740_hostdata *host; @@ -641,10 +641,16 @@ static int aha1740_probe (struct device *dev) } eisa_set_drvdata (edev, shpnt); - scsi_add_host (shpnt, dev); /* XXX handle failure */ + + rc = scsi_add_host (shpnt, dev); + if (rc) + goto err_irq; + scsi_scan_host (shpnt); return 0; + err_irq: + free_irq(irq_level, shpnt); err_unmap: dma_unmap_single (&edev->dev, host->ecb_dma_addr, sizeof (host->ecb), DMA_BIDIRECTIONAL); diff --git a/trunk/drivers/scsi/aic7xxx/aic79xx_osm_pci.c b/trunk/drivers/scsi/aic7xxx/aic79xx_osm_pci.c index 2001fe890e71..1a3ab6aa856b 100644 --- a/trunk/drivers/scsi/aic7xxx/aic79xx_osm_pci.c +++ b/trunk/drivers/scsi/aic7xxx/aic79xx_osm_pci.c @@ -62,6 +62,7 @@ static struct pci_device_id ahd_linux_pci_id_table[] = { /* aic7901 based controllers */ ID(ID_AHA_29320A), ID(ID_AHA_29320ALP), + ID(ID_AHA_29320LPE), /* aic7902 based controllers */ ID(ID_AHA_29320), ID(ID_AHA_29320B), diff --git a/trunk/drivers/scsi/aic7xxx/aic79xx_pci.c b/trunk/drivers/scsi/aic7xxx/aic79xx_pci.c index c07735819cd1..2cf7bb3123f0 100644 --- a/trunk/drivers/scsi/aic7xxx/aic79xx_pci.c +++ b/trunk/drivers/scsi/aic7xxx/aic79xx_pci.c @@ -109,7 +109,13 @@ static struct ahd_pci_identity ahd_pci_ident_table [] = { ID_AHA_29320ALP, ID_ALL_MASK, - "Adaptec 29320ALP Ultra320 SCSI adapter", + "Adaptec 29320ALP PCIx Ultra320 SCSI adapter", + ahd_aic7901_setup + }, + { + ID_AHA_29320LPE, + ID_ALL_MASK, + "Adaptec 29320LPE PCIe Ultra320 SCSI adapter", ahd_aic7901_setup }, /* aic7901A based controllers */ diff --git a/trunk/drivers/scsi/aic7xxx/aic79xx_pci.h b/trunk/drivers/scsi/aic7xxx/aic79xx_pci.h index da45153668c7..16b7c70a673c 100644 --- a/trunk/drivers/scsi/aic7xxx/aic79xx_pci.h +++ b/trunk/drivers/scsi/aic7xxx/aic79xx_pci.h @@ -51,6 +51,7 @@ #define ID_AIC7901 0x800F9005FFFF9005ull #define ID_AHA_29320A 0x8000900500609005ull #define ID_AHA_29320ALP 0x8017900500449005ull +#define ID_AHA_29320LPE 0x8017900500459005ull #define ID_AIC7901A 0x801E9005FFFF9005ull #define ID_AHA_29320LP 0x8014900500449005ull diff --git a/trunk/drivers/scsi/aic94xx/aic94xx.h b/trunk/drivers/scsi/aic94xx/aic94xx.h index 71a031df7a34..32f513b1b78a 100644 --- a/trunk/drivers/scsi/aic94xx/aic94xx.h +++ b/trunk/drivers/scsi/aic94xx/aic94xx.h @@ -56,8 +56,8 @@ /* 2*ITNL timeout + 1 second */ #define AIC94XX_SCB_TIMEOUT (5*HZ) -extern kmem_cache_t *asd_dma_token_cache; -extern kmem_cache_t *asd_ascb_cache; +extern struct kmem_cache *asd_dma_token_cache; +extern struct kmem_cache *asd_ascb_cache; extern char sas_addr_str[2*SAS_ADDR_SIZE + 1]; static inline void asd_stringify_sas_addr(char *p, const u8 *sas_addr) diff --git a/trunk/drivers/scsi/aic94xx/aic94xx_hwi.c b/trunk/drivers/scsi/aic94xx/aic94xx_hwi.c index af7e01134364..da94e126ca83 100644 --- a/trunk/drivers/scsi/aic94xx/aic94xx_hwi.c +++ b/trunk/drivers/scsi/aic94xx/aic94xx_hwi.c @@ -1047,7 +1047,7 @@ irqreturn_t asd_hw_isr(int irq, void *dev_id) static inline struct asd_ascb *asd_ascb_alloc(struct asd_ha_struct *asd_ha, gfp_t gfp_flags) { - extern kmem_cache_t *asd_ascb_cache; + extern struct kmem_cache *asd_ascb_cache; struct asd_seq_data *seq = &asd_ha->seq; struct asd_ascb *ascb; unsigned long flags; diff --git a/trunk/drivers/scsi/aic94xx/aic94xx_init.c b/trunk/drivers/scsi/aic94xx/aic94xx_init.c index 57c5ba4043f2..fbc82b00a418 100644 --- a/trunk/drivers/scsi/aic94xx/aic94xx_init.c +++ b/trunk/drivers/scsi/aic94xx/aic94xx_init.c @@ -450,8 +450,8 @@ static inline void asd_destroy_ha_caches(struct asd_ha_struct *asd_ha) asd_ha->scb_pool = NULL; } -kmem_cache_t *asd_dma_token_cache; -kmem_cache_t *asd_ascb_cache; +struct kmem_cache *asd_dma_token_cache; +struct kmem_cache *asd_ascb_cache; static int asd_create_global_caches(void) { @@ -724,6 +724,15 @@ static void asd_free_queues(struct asd_ha_struct *asd_ha) list_for_each_safe(pos, n, &pending) { struct asd_ascb *ascb = list_entry(pos, struct asd_ascb, list); + /* + * Delete unexpired ascb timers. This may happen if we issue + * a CONTROL PHY scb to an adapter and rmmod before the scb + * times out. Apparently we don't wait for the CONTROL PHY + * to complete, so it doesn't matter if we kill the timer. + */ + del_timer_sync(&ascb->timer); + WARN_ON(ascb->scb->header.opcode != CONTROL_PHY); + list_del_init(pos); ASD_DPRINTK("freeing from pending\n"); asd_ascb_free(ascb); diff --git a/trunk/drivers/scsi/aic94xx/aic94xx_scb.c b/trunk/drivers/scsi/aic94xx/aic94xx_scb.c index b15caf1c8fa2..75ed6b0569d1 100644 --- a/trunk/drivers/scsi/aic94xx/aic94xx_scb.c +++ b/trunk/drivers/scsi/aic94xx/aic94xx_scb.c @@ -25,6 +25,7 @@ */ #include +#include #include "aic94xx.h" #include "aic94xx_reg.h" @@ -412,6 +413,40 @@ void asd_invalidate_edb(struct asd_ascb *ascb, int edb_id) } } +/* hard reset a phy later */ +static void do_phy_reset_later(struct work_struct *work) +{ + struct sas_phy *sas_phy = + container_of(work, struct sas_phy, reset_work); + int error; + + ASD_DPRINTK("%s: About to hard reset phy %d\n", __FUNCTION__, + sas_phy->identify.phy_identifier); + /* Reset device port */ + error = sas_phy_reset(sas_phy, 1); + if (error) + ASD_DPRINTK("%s: Hard reset of phy %d failed (%d).\n", + __FUNCTION__, sas_phy->identify.phy_identifier, error); +} + +static void phy_reset_later(struct sas_phy *sas_phy, struct Scsi_Host *shost) +{ + INIT_WORK(&sas_phy->reset_work, do_phy_reset_later); + queue_work(shost->work_q, &sas_phy->reset_work); +} + +/* start up the ABORT TASK tmf... */ +static void task_kill_later(struct asd_ascb *ascb) +{ + struct asd_ha_struct *asd_ha = ascb->ha; + struct sas_ha_struct *sas_ha = &asd_ha->sas_ha; + struct Scsi_Host *shost = sas_ha->core.shost; + struct sas_task *task = ascb->uldd_task; + + INIT_WORK(&task->abort_work, sas_task_abort); + queue_work(shost->work_q, &task->abort_work); +} + static void escb_tasklet_complete(struct asd_ascb *ascb, struct done_list_struct *dl) { @@ -439,6 +474,74 @@ static void escb_tasklet_complete(struct asd_ascb *ascb, ascb->scb->header.opcode); } + /* Catch these before we mask off the sb_opcode bits */ + switch (sb_opcode) { + case REQ_TASK_ABORT: { + struct asd_ascb *a, *b; + u16 tc_abort; + + tc_abort = *((u16*)(&dl->status_block[1])); + tc_abort = le16_to_cpu(tc_abort); + + ASD_DPRINTK("%s: REQ_TASK_ABORT, reason=0x%X\n", + __FUNCTION__, dl->status_block[3]); + + /* Find the pending task and abort it. */ + list_for_each_entry_safe(a, b, &asd_ha->seq.pend_q, list) + if (a->tc_index == tc_abort) { + task_kill_later(a); + break; + } + goto out; + } + case REQ_DEVICE_RESET: { + struct Scsi_Host *shost = sas_ha->core.shost; + struct sas_phy *dev_phy; + struct asd_ascb *a; + u16 conn_handle; + + conn_handle = *((u16*)(&dl->status_block[1])); + conn_handle = le16_to_cpu(conn_handle); + + ASD_DPRINTK("%s: REQ_DEVICE_RESET, reason=0x%X\n", __FUNCTION__, + dl->status_block[3]); + + /* Kill all pending tasks and reset the device */ + dev_phy = NULL; + list_for_each_entry(a, &asd_ha->seq.pend_q, list) { + struct sas_task *task; + struct domain_device *dev; + u16 x; + + task = a->uldd_task; + if (!task) + continue; + dev = task->dev; + + x = (unsigned long)dev->lldd_dev; + if (x == conn_handle) { + dev_phy = dev->port->phy; + task_kill_later(a); + } + } + + /* Reset device port */ + if (!dev_phy) { + ASD_DPRINTK("%s: No pending commands; can't reset.\n", + __FUNCTION__); + goto out; + } + phy_reset_later(dev_phy, shost); + goto out; + } + case SIGNAL_NCQ_ERROR: + ASD_DPRINTK("%s: SIGNAL_NCQ_ERROR\n", __FUNCTION__); + goto out; + case CLEAR_NCQ_ERROR: + ASD_DPRINTK("%s: CLEAR_NCQ_ERROR\n", __FUNCTION__); + goto out; + } + sb_opcode &= ~DL_PHY_MASK; switch (sb_opcode) { @@ -469,22 +572,6 @@ static void escb_tasklet_complete(struct asd_ascb *ascb, asd_deform_port(asd_ha, phy); sas_ha->notify_port_event(sas_phy, PORTE_TIMER_EVENT); break; - case REQ_TASK_ABORT: - ASD_DPRINTK("%s: phy%d: REQ_TASK_ABORT\n", __FUNCTION__, - phy_id); - break; - case REQ_DEVICE_RESET: - ASD_DPRINTK("%s: phy%d: REQ_DEVICE_RESET\n", __FUNCTION__, - phy_id); - break; - case SIGNAL_NCQ_ERROR: - ASD_DPRINTK("%s: phy%d: SIGNAL_NCQ_ERROR\n", __FUNCTION__, - phy_id); - break; - case CLEAR_NCQ_ERROR: - ASD_DPRINTK("%s: phy%d: CLEAR_NCQ_ERROR\n", __FUNCTION__, - phy_id); - break; default: ASD_DPRINTK("%s: phy%d: unknown event:0x%x\n", __FUNCTION__, phy_id, sb_opcode); @@ -504,7 +591,7 @@ static void escb_tasklet_complete(struct asd_ascb *ascb, break; } - +out: asd_invalidate_edb(ascb, edb); } diff --git a/trunk/drivers/scsi/fd_mcs.c b/trunk/drivers/scsi/fd_mcs.c index ef8285c326e4..668569e8856b 100644 --- a/trunk/drivers/scsi/fd_mcs.c +++ b/trunk/drivers/scsi/fd_mcs.c @@ -294,6 +294,7 @@ static struct Scsi_Host *hosts[FD_MAX_HOSTS + 1] = { NULL }; static int user_fifo_count = 0; static int user_fifo_size = 0; +#ifndef MODULE static int __init fd_mcs_setup(char *str) { static int done_setup = 0; @@ -311,6 +312,7 @@ static int __init fd_mcs_setup(char *str) } __setup("fd_mcs=", fd_mcs_setup); +#endif /* !MODULE */ static void print_banner(struct Scsi_Host *shpnt) { diff --git a/trunk/drivers/scsi/hosts.c b/trunk/drivers/scsi/hosts.c index 68ef1636678d..38c3a291efac 100644 --- a/trunk/drivers/scsi/hosts.c +++ b/trunk/drivers/scsi/hosts.c @@ -263,6 +263,10 @@ static void scsi_host_dev_release(struct device *dev) kthread_stop(shost->ehandler); if (shost->work_q) destroy_workqueue(shost->work_q); + if (shost->uspace_req_q) { + kfree(shost->uspace_req_q->queuedata); + scsi_free_queue(shost->uspace_req_q); + } scsi_destroy_command_freelist(shost); if (shost->bqt) @@ -301,8 +305,8 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize) if (!shost) return NULL; - spin_lock_init(&shost->default_lock); - scsi_assign_lock(shost, &shost->default_lock); + shost->host_lock = &shost->default_lock; + spin_lock_init(shost->host_lock); shost->shost_state = SHOST_CREATED; INIT_LIST_HEAD(&shost->__devices); INIT_LIST_HEAD(&shost->__targets); diff --git a/trunk/drivers/scsi/ibmvscsi/Makefile b/trunk/drivers/scsi/ibmvscsi/Makefile index 4e247b6b8700..6ac0633d5452 100644 --- a/trunk/drivers/scsi/ibmvscsi/Makefile +++ b/trunk/drivers/scsi/ibmvscsi/Makefile @@ -3,3 +3,5 @@ obj-$(CONFIG_SCSI_IBMVSCSI) += ibmvscsic.o ibmvscsic-y += ibmvscsi.o ibmvscsic-$(CONFIG_PPC_ISERIES) += iseries_vscsi.o ibmvscsic-$(CONFIG_PPC_PSERIES) += rpa_vscsi.o + +obj-$(CONFIG_SCSI_IBMVSCSIS) += ibmvstgt.o diff --git a/trunk/drivers/scsi/ibmvscsi/ibmvstgt.c b/trunk/drivers/scsi/ibmvscsi/ibmvstgt.c new file mode 100644 index 000000000000..e28260f05d6b --- /dev/null +++ b/trunk/drivers/scsi/ibmvscsi/ibmvstgt.c @@ -0,0 +1,960 @@ +/* + * IBM eServer i/pSeries Virtual SCSI Target Driver + * Copyright (C) 2003-2005 Dave Boutcher (boutcher@us.ibm.com) IBM Corp. + * Santiago Leon (santil@us.ibm.com) IBM Corp. + * Linda Xie (lxie@us.ibm.com) IBM Corp. + * + * Copyright (C) 2005-2006 FUJITA Tomonori + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ibmvscsi.h" + +#define INITIAL_SRP_LIMIT 16 +#define DEFAULT_MAX_SECTORS 512 + +#define TGT_NAME "ibmvstgt" + +/* + * Hypervisor calls. + */ +#define h_copy_rdma(l, sa, sb, da, db) \ + plpar_hcall_norets(H_COPY_RDMA, l, sa, sb, da, db) +#define h_send_crq(ua, l, h) \ + plpar_hcall_norets(H_SEND_CRQ, ua, l, h) +#define h_reg_crq(ua, tok, sz)\ + plpar_hcall_norets(H_REG_CRQ, ua, tok, sz); +#define h_free_crq(ua) \ + plpar_hcall_norets(H_FREE_CRQ, ua); + +/* tmp - will replace with SCSI logging stuff */ +#define eprintk(fmt, args...) \ +do { \ + printk("%s(%d) " fmt, __FUNCTION__, __LINE__, ##args); \ +} while (0) +/* #define dprintk eprintk */ +#define dprintk(fmt, args...) + +struct vio_port { + struct vio_dev *dma_dev; + + struct crq_queue crq_queue; + struct work_struct crq_work; + + unsigned long liobn; + unsigned long riobn; + struct srp_target *target; +}; + +static struct workqueue_struct *vtgtd; + +/* + * These are fixed for the system and come from the Open Firmware device tree. + * We just store them here to save getting them every time. + */ +static char system_id[64] = ""; +static char partition_name[97] = "UNKNOWN"; +static unsigned int partition_number = -1; + +static struct vio_port *target_to_port(struct srp_target *target) +{ + return (struct vio_port *) target->ldata; +} + +static inline union viosrp_iu *vio_iu(struct iu_entry *iue) +{ + return (union viosrp_iu *) (iue->sbuf->buf); +} + +static int send_iu(struct iu_entry *iue, uint64_t length, uint8_t format) +{ + struct srp_target *target = iue->target; + struct vio_port *vport = target_to_port(target); + long rc, rc1; + union { + struct viosrp_crq cooked; + uint64_t raw[2]; + } crq; + + /* First copy the SRP */ + rc = h_copy_rdma(length, vport->liobn, iue->sbuf->dma, + vport->riobn, iue->remote_token); + + if (rc) + eprintk("Error %ld transferring data\n", rc); + + crq.cooked.valid = 0x80; + crq.cooked.format = format; + crq.cooked.reserved = 0x00; + crq.cooked.timeout = 0x00; + crq.cooked.IU_length = length; + crq.cooked.IU_data_ptr = vio_iu(iue)->srp.rsp.tag; + + if (rc == 0) + crq.cooked.status = 0x99; /* Just needs to be non-zero */ + else + crq.cooked.status = 0x00; + + rc1 = h_send_crq(vport->dma_dev->unit_address, crq.raw[0], crq.raw[1]); + + if (rc1) { + eprintk("%ld sending response\n", rc1); + return rc1; + } + + return rc; +} + +#define SRP_RSP_SENSE_DATA_LEN 18 + +static int send_rsp(struct iu_entry *iue, struct scsi_cmnd *sc, + unsigned char status, unsigned char asc) +{ + union viosrp_iu *iu = vio_iu(iue); + uint64_t tag = iu->srp.rsp.tag; + + /* If the linked bit is on and status is good */ + if (test_bit(V_LINKED, &iue->flags) && (status == NO_SENSE)) + status = 0x10; + + memset(iu, 0, sizeof(struct srp_rsp)); + iu->srp.rsp.opcode = SRP_RSP; + iu->srp.rsp.req_lim_delta = 1; + iu->srp.rsp.tag = tag; + + if (test_bit(V_DIOVER, &iue->flags)) + iu->srp.rsp.flags |= SRP_RSP_FLAG_DIOVER; + + iu->srp.rsp.data_in_res_cnt = 0; + iu->srp.rsp.data_out_res_cnt = 0; + + iu->srp.rsp.flags &= ~SRP_RSP_FLAG_RSPVALID; + + iu->srp.rsp.resp_data_len = 0; + iu->srp.rsp.status = status; + if (status) { + uint8_t *sense = iu->srp.rsp.data; + + if (sc) { + iu->srp.rsp.flags |= SRP_RSP_FLAG_SNSVALID; + iu->srp.rsp.sense_data_len = SCSI_SENSE_BUFFERSIZE; + memcpy(sense, sc->sense_buffer, SCSI_SENSE_BUFFERSIZE); + } else { + iu->srp.rsp.status = SAM_STAT_CHECK_CONDITION; + iu->srp.rsp.flags |= SRP_RSP_FLAG_SNSVALID; + iu->srp.rsp.sense_data_len = SRP_RSP_SENSE_DATA_LEN; + + /* Valid bit and 'current errors' */ + sense[0] = (0x1 << 7 | 0x70); + /* Sense key */ + sense[2] = status; + /* Additional sense length */ + sense[7] = 0xa; /* 10 bytes */ + /* Additional sense code */ + sense[12] = asc; + } + } + + send_iu(iue, sizeof(iu->srp.rsp) + SRP_RSP_SENSE_DATA_LEN, + VIOSRP_SRP_FORMAT); + + return 0; +} + +static void handle_cmd_queue(struct srp_target *target) +{ + struct Scsi_Host *shost = target->shost; + struct iu_entry *iue; + struct srp_cmd *cmd; + unsigned long flags; + int err; + +retry: + spin_lock_irqsave(&target->lock, flags); + + list_for_each_entry(iue, &target->cmd_queue, ilist) { + if (!test_and_set_bit(V_FLYING, &iue->flags)) { + spin_unlock_irqrestore(&target->lock, flags); + cmd = iue->sbuf->buf; + err = srp_cmd_queue(shost, cmd, iue, 0); + if (err) { + eprintk("cannot queue cmd %p %d\n", cmd, err); + srp_iu_put(iue); + } + goto retry; + } + } + + spin_unlock_irqrestore(&target->lock, flags); +} + +static int ibmvstgt_rdma(struct scsi_cmnd *sc, struct scatterlist *sg, int nsg, + struct srp_direct_buf *md, int nmd, + enum dma_data_direction dir, unsigned int rest) +{ + struct iu_entry *iue = (struct iu_entry *) sc->SCp.ptr; + struct srp_target *target = iue->target; + struct vio_port *vport = target_to_port(target); + dma_addr_t token; + long err; + unsigned int done = 0; + int i, sidx, soff; + + sidx = soff = 0; + token = sg_dma_address(sg + sidx); + + for (i = 0; i < nmd && rest; i++) { + unsigned int mdone, mlen; + + mlen = min(rest, md[i].len); + for (mdone = 0; mlen;) { + int slen = min(sg_dma_len(sg + sidx) - soff, mlen); + + if (dir == DMA_TO_DEVICE) + err = h_copy_rdma(slen, + vport->riobn, + md[i].va + mdone, + vport->liobn, + token + soff); + else + err = h_copy_rdma(slen, + vport->liobn, + token + soff, + vport->riobn, + md[i].va + mdone); + + if (err != H_SUCCESS) { + eprintk("rdma error %d %d\n", dir, slen); + goto out; + } + + mlen -= slen; + mdone += slen; + soff += slen; + done += slen; + + if (soff == sg_dma_len(sg + sidx)) { + sidx++; + soff = 0; + token = sg_dma_address(sg + sidx); + + if (sidx > nsg) { + eprintk("out of sg %p %d %d\n", + iue, sidx, nsg); + goto out; + } + } + }; + + rest -= mlen; + } +out: + + return 0; +} + +static int ibmvstgt_transfer_data(struct scsi_cmnd *sc, + void (*done)(struct scsi_cmnd *)) +{ + struct iu_entry *iue = (struct iu_entry *) sc->SCp.ptr; + int err; + + err = srp_transfer_data(sc, &vio_iu(iue)->srp.cmd, ibmvstgt_rdma, 1, 1); + + done(sc); + + return err; +} + +static int ibmvstgt_cmd_done(struct scsi_cmnd *sc, + void (*done)(struct scsi_cmnd *)) +{ + unsigned long flags; + struct iu_entry *iue = (struct iu_entry *) sc->SCp.ptr; + struct srp_target *target = iue->target; + + dprintk("%p %p %x\n", iue, target, vio_iu(iue)->srp.cmd.cdb[0]); + + spin_lock_irqsave(&target->lock, flags); + list_del(&iue->ilist); + spin_unlock_irqrestore(&target->lock, flags); + + if (sc->result != SAM_STAT_GOOD) { + eprintk("operation failed %p %d %x\n", + iue, sc->result, vio_iu(iue)->srp.cmd.cdb[0]); + send_rsp(iue, sc, HARDWARE_ERROR, 0x00); + } else + send_rsp(iue, sc, NO_SENSE, 0x00); + + done(sc); + srp_iu_put(iue); + return 0; +} + +int send_adapter_info(struct iu_entry *iue, + dma_addr_t remote_buffer, uint16_t length) +{ + struct srp_target *target = iue->target; + struct vio_port *vport = target_to_port(target); + struct Scsi_Host *shost = target->shost; + dma_addr_t data_token; + struct mad_adapter_info_data *info; + int err; + + info = dma_alloc_coherent(target->dev, sizeof(*info), &data_token, + GFP_KERNEL); + if (!info) { + eprintk("bad dma_alloc_coherent %p\n", target); + return 1; + } + + /* Get remote info */ + err = h_copy_rdma(sizeof(*info), vport->riobn, remote_buffer, + vport->liobn, data_token); + if (err == H_SUCCESS) { + dprintk("Client connect: %s (%d)\n", + info->partition_name, info->partition_number); + } + + memset(info, 0, sizeof(*info)); + + strcpy(info->srp_version, "16.a"); + strncpy(info->partition_name, partition_name, + sizeof(info->partition_name)); + info->partition_number = partition_number; + info->mad_version = 1; + info->os_type = 2; + info->port_max_txu[0] = shost->hostt->max_sectors << 9; + + /* Send our info to remote */ + err = h_copy_rdma(sizeof(*info), vport->liobn, data_token, + vport->riobn, remote_buffer); + + dma_free_coherent(target->dev, sizeof(*info), info, data_token); + + if (err != H_SUCCESS) { + eprintk("Error sending adapter info %d\n", err); + return 1; + } + + return 0; +} + +static void process_login(struct iu_entry *iue) +{ + union viosrp_iu *iu = vio_iu(iue); + struct srp_login_rsp *rsp = &iu->srp.login_rsp; + uint64_t tag = iu->srp.rsp.tag; + + /* TODO handle case that requested size is wrong and + * buffer format is wrong + */ + memset(iu, 0, sizeof(struct srp_login_rsp)); + rsp->opcode = SRP_LOGIN_RSP; + rsp->req_lim_delta = INITIAL_SRP_LIMIT; + rsp->tag = tag; + rsp->max_it_iu_len = sizeof(union srp_iu); + rsp->max_ti_iu_len = sizeof(union srp_iu); + /* direct and indirect */ + rsp->buf_fmt = SRP_BUF_FORMAT_DIRECT | SRP_BUF_FORMAT_INDIRECT; + + send_iu(iue, sizeof(*rsp), VIOSRP_SRP_FORMAT); +} + +static inline void queue_cmd(struct iu_entry *iue) +{ + struct srp_target *target = iue->target; + unsigned long flags; + + spin_lock_irqsave(&target->lock, flags); + list_add_tail(&iue->ilist, &target->cmd_queue); + spin_unlock_irqrestore(&target->lock, flags); +} + +static int process_tsk_mgmt(struct iu_entry *iue) +{ + union viosrp_iu *iu = vio_iu(iue); + int fn; + + dprintk("%p %u\n", iue, iu->srp.tsk_mgmt.tsk_mgmt_func); + + switch (iu->srp.tsk_mgmt.tsk_mgmt_func) { + case SRP_TSK_ABORT_TASK: + fn = ABORT_TASK; + break; + case SRP_TSK_ABORT_TASK_SET: + fn = ABORT_TASK_SET; + break; + case SRP_TSK_CLEAR_TASK_SET: + fn = CLEAR_TASK_SET; + break; + case SRP_TSK_LUN_RESET: + fn = LOGICAL_UNIT_RESET; + break; + case SRP_TSK_CLEAR_ACA: + fn = CLEAR_ACA; + break; + default: + fn = 0; + } + if (fn) + scsi_tgt_tsk_mgmt_request(iue->target->shost, fn, + iu->srp.tsk_mgmt.task_tag, + (struct scsi_lun *) &iu->srp.tsk_mgmt.lun, + iue); + else + send_rsp(iue, NULL, ILLEGAL_REQUEST, 0x20); + + return !fn; +} + +static int process_mad_iu(struct iu_entry *iue) +{ + union viosrp_iu *iu = vio_iu(iue); + struct viosrp_adapter_info *info; + struct viosrp_host_config *conf; + + switch (iu->mad.empty_iu.common.type) { + case VIOSRP_EMPTY_IU_TYPE: + eprintk("%s\n", "Unsupported EMPTY MAD IU"); + break; + case VIOSRP_ERROR_LOG_TYPE: + eprintk("%s\n", "Unsupported ERROR LOG MAD IU"); + iu->mad.error_log.common.status = 1; + send_iu(iue, sizeof(iu->mad.error_log), VIOSRP_MAD_FORMAT); + break; + case VIOSRP_ADAPTER_INFO_TYPE: + info = &iu->mad.adapter_info; + info->common.status = send_adapter_info(iue, info->buffer, + info->common.length); + send_iu(iue, sizeof(*info), VIOSRP_MAD_FORMAT); + break; + case VIOSRP_HOST_CONFIG_TYPE: + conf = &iu->mad.host_config; + conf->common.status = 1; + send_iu(iue, sizeof(*conf), VIOSRP_MAD_FORMAT); + break; + default: + eprintk("Unknown type %u\n", iu->srp.rsp.opcode); + } + + return 1; +} + +static int process_srp_iu(struct iu_entry *iue) +{ + union viosrp_iu *iu = vio_iu(iue); + int done = 1; + u8 opcode = iu->srp.rsp.opcode; + + switch (opcode) { + case SRP_LOGIN_REQ: + process_login(iue); + break; + case SRP_TSK_MGMT: + done = process_tsk_mgmt(iue); + break; + case SRP_CMD: + queue_cmd(iue); + done = 0; + break; + case SRP_LOGIN_RSP: + case SRP_I_LOGOUT: + case SRP_T_LOGOUT: + case SRP_RSP: + case SRP_CRED_REQ: + case SRP_CRED_RSP: + case SRP_AER_REQ: + case SRP_AER_RSP: + eprintk("Unsupported type %u\n", opcode); + break; + default: + eprintk("Unknown type %u\n", opcode); + } + + return done; +} + +static void process_iu(struct viosrp_crq *crq, struct srp_target *target) +{ + struct vio_port *vport = target_to_port(target); + struct iu_entry *iue; + long err, done; + + iue = srp_iu_get(target); + if (!iue) { + eprintk("Error getting IU from pool, %p\n", target); + return; + } + + iue->remote_token = crq->IU_data_ptr; + + err = h_copy_rdma(crq->IU_length, vport->riobn, + iue->remote_token, vport->liobn, iue->sbuf->dma); + + if (err != H_SUCCESS) { + eprintk("%ld transferring data error %p\n", err, iue); + done = 1; + goto out; + } + + if (crq->format == VIOSRP_MAD_FORMAT) + done = process_mad_iu(iue); + else + done = process_srp_iu(iue); +out: + if (done) + srp_iu_put(iue); +} + +static irqreturn_t ibmvstgt_interrupt(int irq, void *data) +{ + struct srp_target *target = (struct srp_target *) data; + struct vio_port *vport = target_to_port(target); + + vio_disable_interrupts(vport->dma_dev); + queue_work(vtgtd, &vport->crq_work); + + return IRQ_HANDLED; +} + +static int crq_queue_create(struct crq_queue *queue, struct srp_target *target) +{ + int err; + struct vio_port *vport = target_to_port(target); + + queue->msgs = (struct viosrp_crq *) get_zeroed_page(GFP_KERNEL); + if (!queue->msgs) + goto malloc_failed; + queue->size = PAGE_SIZE / sizeof(*queue->msgs); + + queue->msg_token = dma_map_single(target->dev, queue->msgs, + queue->size * sizeof(*queue->msgs), + DMA_BIDIRECTIONAL); + + if (dma_mapping_error(queue->msg_token)) + goto map_failed; + + err = h_reg_crq(vport->dma_dev->unit_address, queue->msg_token, + PAGE_SIZE); + + /* If the adapter was left active for some reason (like kexec) + * try freeing and re-registering + */ + if (err == H_RESOURCE) { + do { + err = h_free_crq(vport->dma_dev->unit_address); + } while (err == H_BUSY || H_IS_LONG_BUSY(err)); + + err = h_reg_crq(vport->dma_dev->unit_address, queue->msg_token, + PAGE_SIZE); + } + + if (err != H_SUCCESS && err != 2) { + eprintk("Error 0x%x opening virtual adapter\n", err); + goto reg_crq_failed; + } + + err = request_irq(vport->dma_dev->irq, &ibmvstgt_interrupt, + SA_INTERRUPT, "ibmvstgt", target); + if (err) + goto req_irq_failed; + + vio_enable_interrupts(vport->dma_dev); + + h_send_crq(vport->dma_dev->unit_address, 0xC001000000000000, 0); + + queue->cur = 0; + spin_lock_init(&queue->lock); + + return 0; + +req_irq_failed: + do { + err = h_free_crq(vport->dma_dev->unit_address); + } while (err == H_BUSY || H_IS_LONG_BUSY(err)); + +reg_crq_failed: + dma_unmap_single(target->dev, queue->msg_token, + queue->size * sizeof(*queue->msgs), DMA_BIDIRECTIONAL); +map_failed: + free_page((unsigned long) queue->msgs); + +malloc_failed: + return -ENOMEM; +} + +static void crq_queue_destroy(struct srp_target *target) +{ + struct vio_port *vport = target_to_port(target); + struct crq_queue *queue = &vport->crq_queue; + int err; + + free_irq(vport->dma_dev->irq, target); + do { + err = h_free_crq(vport->dma_dev->unit_address); + } while (err == H_BUSY || H_IS_LONG_BUSY(err)); + + dma_unmap_single(target->dev, queue->msg_token, + queue->size * sizeof(*queue->msgs), DMA_BIDIRECTIONAL); + + free_page((unsigned long) queue->msgs); +} + +static void process_crq(struct viosrp_crq *crq, struct srp_target *target) +{ + struct vio_port *vport = target_to_port(target); + dprintk("%x %x\n", crq->valid, crq->format); + + switch (crq->valid) { + case 0xC0: + /* initialization */ + switch (crq->format) { + case 0x01: + h_send_crq(vport->dma_dev->unit_address, + 0xC002000000000000, 0); + break; + case 0x02: + break; + default: + eprintk("Unknown format %u\n", crq->format); + } + break; + case 0xFF: + /* transport event */ + break; + case 0x80: + /* real payload */ + switch (crq->format) { + case VIOSRP_SRP_FORMAT: + case VIOSRP_MAD_FORMAT: + process_iu(crq, target); + break; + case VIOSRP_OS400_FORMAT: + case VIOSRP_AIX_FORMAT: + case VIOSRP_LINUX_FORMAT: + case VIOSRP_INLINE_FORMAT: + eprintk("Unsupported format %u\n", crq->format); + break; + default: + eprintk("Unknown format %u\n", crq->format); + } + break; + default: + eprintk("unknown message type 0x%02x!?\n", crq->valid); + } +} + +static inline struct viosrp_crq *next_crq(struct crq_queue *queue) +{ + struct viosrp_crq *crq; + unsigned long flags; + + spin_lock_irqsave(&queue->lock, flags); + crq = &queue->msgs[queue->cur]; + if (crq->valid & 0x80) { + if (++queue->cur == queue->size) + queue->cur = 0; + } else + crq = NULL; + spin_unlock_irqrestore(&queue->lock, flags); + + return crq; +} + +static void handle_crq(struct work_struct *work) +{ + struct vio_port *vport = container_of(work, struct vio_port, crq_work); + struct srp_target *target = vport->target; + struct viosrp_crq *crq; + int done = 0; + + while (!done) { + while ((crq = next_crq(&vport->crq_queue)) != NULL) { + process_crq(crq, target); + crq->valid = 0x00; + } + + vio_enable_interrupts(vport->dma_dev); + + crq = next_crq(&vport->crq_queue); + if (crq) { + vio_disable_interrupts(vport->dma_dev); + process_crq(crq, target); + crq->valid = 0x00; + } else + done = 1; + } + + handle_cmd_queue(target); +} + + +static int ibmvstgt_eh_abort_handler(struct scsi_cmnd *sc) +{ + unsigned long flags; + struct iu_entry *iue = (struct iu_entry *) sc->SCp.ptr; + struct srp_target *target = iue->target; + + dprintk("%p %p %x\n", iue, target, vio_iu(iue)->srp.cmd.cdb[0]); + + spin_lock_irqsave(&target->lock, flags); + list_del(&iue->ilist); + spin_unlock_irqrestore(&target->lock, flags); + + srp_iu_put(iue); + + return 0; +} + +static int ibmvstgt_tsk_mgmt_response(u64 mid, int result) +{ + struct iu_entry *iue = (struct iu_entry *) ((void *) mid); + union viosrp_iu *iu = vio_iu(iue); + unsigned char status, asc; + + eprintk("%p %d\n", iue, result); + status = NO_SENSE; + asc = 0; + + switch (iu->srp.tsk_mgmt.tsk_mgmt_func) { + case SRP_TSK_ABORT_TASK: + asc = 0x14; + if (result) + status = ABORTED_COMMAND; + break; + default: + break; + } + + send_rsp(iue, NULL, status, asc); + srp_iu_put(iue); + + return 0; +} + +static ssize_t system_id_show(struct class_device *cdev, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%s\n", system_id); +} + +static ssize_t partition_number_show(struct class_device *cdev, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%x\n", partition_number); +} + +static ssize_t unit_address_show(struct class_device *cdev, char *buf) +{ + struct Scsi_Host *shost = class_to_shost(cdev); + struct srp_target *target = host_to_srp_target(shost); + struct vio_port *vport = target_to_port(target); + return snprintf(buf, PAGE_SIZE, "%x\n", vport->dma_dev->unit_address); +} + +static CLASS_DEVICE_ATTR(system_id, S_IRUGO, system_id_show, NULL); +static CLASS_DEVICE_ATTR(partition_number, S_IRUGO, partition_number_show, NULL); +static CLASS_DEVICE_ATTR(unit_address, S_IRUGO, unit_address_show, NULL); + +static struct class_device_attribute *ibmvstgt_attrs[] = { + &class_device_attr_system_id, + &class_device_attr_partition_number, + &class_device_attr_unit_address, + NULL, +}; + +static struct scsi_host_template ibmvstgt_sht = { + .name = TGT_NAME, + .module = THIS_MODULE, + .can_queue = INITIAL_SRP_LIMIT, + .sg_tablesize = SG_ALL, + .use_clustering = DISABLE_CLUSTERING, + .max_sectors = DEFAULT_MAX_SECTORS, + .transfer_response = ibmvstgt_cmd_done, + .transfer_data = ibmvstgt_transfer_data, + .eh_abort_handler = ibmvstgt_eh_abort_handler, + .tsk_mgmt_response = ibmvstgt_tsk_mgmt_response, + .shost_attrs = ibmvstgt_attrs, + .proc_name = TGT_NAME, +}; + +static int ibmvstgt_probe(struct vio_dev *dev, const struct vio_device_id *id) +{ + struct Scsi_Host *shost; + struct srp_target *target; + struct vio_port *vport; + unsigned int *dma, dma_size; + int err = -ENOMEM; + + vport = kzalloc(sizeof(struct vio_port), GFP_KERNEL); + if (!vport) + return err; + shost = scsi_host_alloc(&ibmvstgt_sht, sizeof(struct srp_target)); + if (!shost) + goto free_vport; + err = scsi_tgt_alloc_queue(shost); + if (err) + goto put_host; + + target = host_to_srp_target(shost); + target->shost = shost; + vport->dma_dev = dev; + target->ldata = vport; + vport->target = target; + err = srp_target_alloc(target, &dev->dev, INITIAL_SRP_LIMIT, + SRP_MAX_IU_LEN); + if (err) + goto put_host; + + dma = (unsigned int *) vio_get_attribute(dev, "ibm,my-dma-window", + &dma_size); + if (!dma || dma_size != 40) { + eprintk("Couldn't get window property %d\n", dma_size); + err = -EIO; + goto free_srp_target; + } + vport->liobn = dma[0]; + vport->riobn = dma[5]; + + INIT_WORK(&vport->crq_work, handle_crq); + + err = crq_queue_create(&vport->crq_queue, target); + if (err) + goto free_srp_target; + + err = scsi_add_host(shost, target->dev); + if (err) + goto destroy_queue; + return 0; + +destroy_queue: + crq_queue_destroy(target); +free_srp_target: + srp_target_free(target); +put_host: + scsi_host_put(shost); +free_vport: + kfree(vport); + return err; +} + +static int ibmvstgt_remove(struct vio_dev *dev) +{ + struct srp_target *target = (struct srp_target *) dev->dev.driver_data; + struct Scsi_Host *shost = target->shost; + struct vio_port *vport = target->ldata; + + crq_queue_destroy(target); + scsi_remove_host(shost); + scsi_tgt_free_queue(shost); + srp_target_free(target); + kfree(vport); + scsi_host_put(shost); + return 0; +} + +static struct vio_device_id ibmvstgt_device_table[] __devinitdata = { + {"v-scsi-host", "IBM,v-scsi-host"}, + {"",""} +}; + +MODULE_DEVICE_TABLE(vio, ibmvstgt_device_table); + +static struct vio_driver ibmvstgt_driver = { + .id_table = ibmvstgt_device_table, + .probe = ibmvstgt_probe, + .remove = ibmvstgt_remove, + .driver = { + .name = "ibmvscsis", + .owner = THIS_MODULE, + } +}; + +static int get_system_info(void) +{ + struct device_node *rootdn; + const char *id, *model, *name; + unsigned int *num; + + rootdn = find_path_device("/"); + if (!rootdn) + return -ENOENT; + + model = get_property(rootdn, "model", NULL); + id = get_property(rootdn, "system-id", NULL); + if (model && id) + snprintf(system_id, sizeof(system_id), "%s-%s", model, id); + + name = get_property(rootdn, "ibm,partition-name", NULL); + if (name) + strncpy(partition_name, name, sizeof(partition_name)); + + num = (unsigned int *) get_property(rootdn, "ibm,partition-no", NULL); + if (num) + partition_number = *num; + + return 0; +} + +static int ibmvstgt_init(void) +{ + int err = -ENOMEM; + + printk("IBM eServer i/pSeries Virtual SCSI Target Driver\n"); + + vtgtd = create_workqueue("ibmvtgtd"); + if (!vtgtd) + return err; + + err = get_system_info(); + if (err) + goto destroy_wq; + + err = vio_register_driver(&ibmvstgt_driver); + if (err) + goto destroy_wq; + + return 0; + +destroy_wq: + destroy_workqueue(vtgtd); + return err; +} + +static void ibmvstgt_exit(void) +{ + printk("Unregister IBM virtual SCSI driver\n"); + + destroy_workqueue(vtgtd); + vio_unregister_driver(&ibmvstgt_driver); +} + +MODULE_DESCRIPTION("IBM Virtual SCSI Target"); +MODULE_AUTHOR("Santiago Leon"); +MODULE_LICENSE("GPL"); + +module_init(ibmvstgt_init); +module_exit(ibmvstgt_exit); diff --git a/trunk/drivers/scsi/ide-scsi.c b/trunk/drivers/scsi/ide-scsi.c index 1427a41e8441..8f6b5bf580f6 100644 --- a/trunk/drivers/scsi/ide-scsi.c +++ b/trunk/drivers/scsi/ide-scsi.c @@ -110,6 +110,7 @@ typedef struct ide_scsi_obj { } idescsi_scsi_t; static DEFINE_MUTEX(idescsi_ref_mutex); +static int idescsi_nocd; /* Set by module param to skip cd */ #define ide_scsi_g(disk) \ container_of((disk)->private_data, struct ide_scsi_obj, driver) @@ -1127,6 +1128,9 @@ static int ide_scsi_probe(ide_drive_t *drive) warned = 1; } + if (idescsi_nocd && drive->media == ide_cdrom) + return -ENODEV; + if (!strstr("ide-scsi", drive->driver_req) || !drive->present || drive->media == ide_disk || @@ -1187,6 +1191,8 @@ static void __exit exit_idescsi_module(void) driver_unregister(&idescsi_driver.gen_driver); } +module_param(idescsi_nocd, int, 0600); +MODULE_PARM_DESC(idescsi_nocd, "Disable handling of CD-ROMs so they may be driven by ide-cd"); module_init(init_idescsi_module); module_exit(exit_idescsi_module); MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/scsi/imm.c b/trunk/drivers/scsi/imm.c index e31f6122106f..0464c182c577 100644 --- a/trunk/drivers/scsi/imm.c +++ b/trunk/drivers/scsi/imm.c @@ -36,7 +36,7 @@ typedef struct { int base_hi; /* Hi Base address for ECP-ISA chipset */ int mode; /* Transfer mode */ struct scsi_cmnd *cur_cmd; /* Current queued command */ - struct work_struct imm_tq; /* Polling interrupt stuff */ + struct delayed_work imm_tq; /* Polling interrupt stuff */ unsigned long jstart; /* Jiffies at start */ unsigned failed:1; /* Failure flag */ unsigned dp:1; /* Data phase present */ @@ -733,9 +733,9 @@ static int imm_completion(struct scsi_cmnd *cmd) * the scheduler's task queue to generate a stream of call-backs and * complete the request when the drive is ready. */ -static void imm_interrupt(void *data) +static void imm_interrupt(struct work_struct *work) { - imm_struct *dev = (imm_struct *) data; + imm_struct *dev = container_of(work, imm_struct, imm_tq.work); struct scsi_cmnd *cmd = dev->cur_cmd; struct Scsi_Host *host = cmd->device->host; unsigned long flags; @@ -745,7 +745,6 @@ static void imm_interrupt(void *data) return; } if (imm_engine(dev, cmd)) { - INIT_WORK(&dev->imm_tq, imm_interrupt, (void *) dev); schedule_delayed_work(&dev->imm_tq, 1); return; } @@ -953,8 +952,7 @@ static int imm_queuecommand(struct scsi_cmnd *cmd, cmd->result = DID_ERROR << 16; /* default return code */ cmd->SCp.phase = 0; /* bus free */ - INIT_WORK(&dev->imm_tq, imm_interrupt, dev); - schedule_work(&dev->imm_tq); + schedule_delayed_work(&dev->imm_tq, 0); imm_pb_claim(dev); @@ -1225,7 +1223,7 @@ static int __imm_attach(struct parport *pb) else ports = 8; - INIT_WORK(&dev->imm_tq, imm_interrupt, dev); + INIT_DELAYED_WORK(&dev->imm_tq, imm_interrupt); err = -ENOMEM; host = scsi_host_alloc(&imm_template, sizeof(imm_struct *)); diff --git a/trunk/drivers/scsi/initio.c b/trunk/drivers/scsi/initio.c index afed293dd7b9..f160357e37a6 100644 --- a/trunk/drivers/scsi/initio.c +++ b/trunk/drivers/scsi/initio.c @@ -170,7 +170,7 @@ static int setup_debug = 0; static void i91uSCBPost(BYTE * pHcb, BYTE * pScb); /* PCI Devices supported by this driver */ -static struct pci_device_id i91u_pci_devices[] __devinitdata = { +static struct pci_device_id i91u_pci_devices[] = { { PCI_VENDOR_ID_INIT, I950_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { PCI_VENDOR_ID_INIT, I940_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { PCI_VENDOR_ID_INIT, I935_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, diff --git a/trunk/drivers/scsi/ipr.c b/trunk/drivers/scsi/ipr.c index 2dde821025f3..b318500785e5 100644 --- a/trunk/drivers/scsi/ipr.c +++ b/trunk/drivers/scsi/ipr.c @@ -79,7 +79,6 @@ #include #include #include -#include #include "ipr.h" /* @@ -98,7 +97,7 @@ static DEFINE_SPINLOCK(ipr_driver_lock); /* This table describes the differences between DMA controller chips */ static const struct ipr_chip_cfg_t ipr_chip_cfg[] = { - { /* Gemstone, Citrine, and Obsidian */ + { /* Gemstone, Citrine, Obsidian, and Obsidian-E */ .mailbox = 0x0042C, .cache_line_size = 0x20, { @@ -135,6 +134,7 @@ static const struct ipr_chip_t ipr_chip[] = { { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CITRINE, &ipr_chip_cfg[0] }, { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN, &ipr_chip_cfg[0] }, { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN, &ipr_chip_cfg[0] }, + { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN_E, &ipr_chip_cfg[0] }, { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_SNIPE, &ipr_chip_cfg[1] }, { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_SCAMP, &ipr_chip_cfg[1] } }; @@ -1249,19 +1249,23 @@ static void ipr_log_array_error(struct ipr_ioa_cfg *ioa_cfg, /** * ipr_log_hex_data - Log additional hex IOA error data. + * @ioa_cfg: ioa config struct * @data: IOA error data * @len: data length * * Return value: * none **/ -static void ipr_log_hex_data(u32 *data, int len) +static void ipr_log_hex_data(struct ipr_ioa_cfg *ioa_cfg, u32 *data, int len) { int i; if (len == 0) return; + if (ioa_cfg->log_level <= IPR_DEFAULT_LOG_LEVEL) + len = min_t(int, len, IPR_DEFAULT_MAX_ERROR_DUMP); + for (i = 0; i < len / 4; i += 4) { ipr_err("%08X: %08X %08X %08X %08X\n", i*4, be32_to_cpu(data[i]), @@ -1290,7 +1294,7 @@ static void ipr_log_enhanced_dual_ioa_error(struct ipr_ioa_cfg *ioa_cfg, ipr_err("%s\n", error->failure_reason); ipr_err("Remote Adapter VPD:\n"); ipr_log_ext_vpd(&error->vpd); - ipr_log_hex_data(error->data, + ipr_log_hex_data(ioa_cfg, error->data, be32_to_cpu(hostrcb->hcam.length) - (offsetof(struct ipr_hostrcb_error, u) + offsetof(struct ipr_hostrcb_type_17_error, data))); @@ -1315,12 +1319,225 @@ static void ipr_log_dual_ioa_error(struct ipr_ioa_cfg *ioa_cfg, ipr_err("%s\n", error->failure_reason); ipr_err("Remote Adapter VPD:\n"); ipr_log_vpd(&error->vpd); - ipr_log_hex_data(error->data, + ipr_log_hex_data(ioa_cfg, error->data, be32_to_cpu(hostrcb->hcam.length) - (offsetof(struct ipr_hostrcb_error, u) + offsetof(struct ipr_hostrcb_type_07_error, data))); } +static const struct { + u8 active; + char *desc; +} path_active_desc[] = { + { IPR_PATH_NO_INFO, "Path" }, + { IPR_PATH_ACTIVE, "Active path" }, + { IPR_PATH_NOT_ACTIVE, "Inactive path" } +}; + +static const struct { + u8 state; + char *desc; +} path_state_desc[] = { + { IPR_PATH_STATE_NO_INFO, "has no path state information available" }, + { IPR_PATH_HEALTHY, "is healthy" }, + { IPR_PATH_DEGRADED, "is degraded" }, + { IPR_PATH_FAILED, "is failed" } +}; + +/** + * ipr_log_fabric_path - Log a fabric path error + * @hostrcb: hostrcb struct + * @fabric: fabric descriptor + * + * Return value: + * none + **/ +static void ipr_log_fabric_path(struct ipr_hostrcb *hostrcb, + struct ipr_hostrcb_fabric_desc *fabric) +{ + int i, j; + u8 path_state = fabric->path_state; + u8 active = path_state & IPR_PATH_ACTIVE_MASK; + u8 state = path_state & IPR_PATH_STATE_MASK; + + for (i = 0; i < ARRAY_SIZE(path_active_desc); i++) { + if (path_active_desc[i].active != active) + continue; + + for (j = 0; j < ARRAY_SIZE(path_state_desc); j++) { + if (path_state_desc[j].state != state) + continue; + + if (fabric->cascaded_expander == 0xff && fabric->phy == 0xff) { + ipr_hcam_err(hostrcb, "%s %s: IOA Port=%d\n", + path_active_desc[i].desc, path_state_desc[j].desc, + fabric->ioa_port); + } else if (fabric->cascaded_expander == 0xff) { + ipr_hcam_err(hostrcb, "%s %s: IOA Port=%d, Phy=%d\n", + path_active_desc[i].desc, path_state_desc[j].desc, + fabric->ioa_port, fabric->phy); + } else if (fabric->phy == 0xff) { + ipr_hcam_err(hostrcb, "%s %s: IOA Port=%d, Cascade=%d\n", + path_active_desc[i].desc, path_state_desc[j].desc, + fabric->ioa_port, fabric->cascaded_expander); + } else { + ipr_hcam_err(hostrcb, "%s %s: IOA Port=%d, Cascade=%d, Phy=%d\n", + path_active_desc[i].desc, path_state_desc[j].desc, + fabric->ioa_port, fabric->cascaded_expander, fabric->phy); + } + return; + } + } + + ipr_err("Path state=%02X IOA Port=%d Cascade=%d Phy=%d\n", path_state, + fabric->ioa_port, fabric->cascaded_expander, fabric->phy); +} + +static const struct { + u8 type; + char *desc; +} path_type_desc[] = { + { IPR_PATH_CFG_IOA_PORT, "IOA port" }, + { IPR_PATH_CFG_EXP_PORT, "Expander port" }, + { IPR_PATH_CFG_DEVICE_PORT, "Device port" }, + { IPR_PATH_CFG_DEVICE_LUN, "Device LUN" } +}; + +static const struct { + u8 status; + char *desc; +} path_status_desc[] = { + { IPR_PATH_CFG_NO_PROB, "Functional" }, + { IPR_PATH_CFG_DEGRADED, "Degraded" }, + { IPR_PATH_CFG_FAILED, "Failed" }, + { IPR_PATH_CFG_SUSPECT, "Suspect" }, + { IPR_PATH_NOT_DETECTED, "Missing" }, + { IPR_PATH_INCORRECT_CONN, "Incorrectly connected" } +}; + +static const char *link_rate[] = { + "unknown", + "disabled", + "phy reset problem", + "spinup hold", + "port selector", + "unknown", + "unknown", + "unknown", + "1.5Gbps", + "3.0Gbps", + "unknown", + "unknown", + "unknown", + "unknown", + "unknown", + "unknown" +}; + +/** + * ipr_log_path_elem - Log a fabric path element. + * @hostrcb: hostrcb struct + * @cfg: fabric path element struct + * + * Return value: + * none + **/ +static void ipr_log_path_elem(struct ipr_hostrcb *hostrcb, + struct ipr_hostrcb_config_element *cfg) +{ + int i, j; + u8 type = cfg->type_status & IPR_PATH_CFG_TYPE_MASK; + u8 status = cfg->type_status & IPR_PATH_CFG_STATUS_MASK; + + if (type == IPR_PATH_CFG_NOT_EXIST) + return; + + for (i = 0; i < ARRAY_SIZE(path_type_desc); i++) { + if (path_type_desc[i].type != type) + continue; + + for (j = 0; j < ARRAY_SIZE(path_status_desc); j++) { + if (path_status_desc[j].status != status) + continue; + + if (type == IPR_PATH_CFG_IOA_PORT) { + ipr_hcam_err(hostrcb, "%s %s: Phy=%d, Link rate=%s, WWN=%08X%08X\n", + path_status_desc[j].desc, path_type_desc[i].desc, + cfg->phy, link_rate[cfg->link_rate & IPR_PHY_LINK_RATE_MASK], + be32_to_cpu(cfg->wwid[0]), be32_to_cpu(cfg->wwid[1])); + } else { + if (cfg->cascaded_expander == 0xff && cfg->phy == 0xff) { + ipr_hcam_err(hostrcb, "%s %s: Link rate=%s, WWN=%08X%08X\n", + path_status_desc[j].desc, path_type_desc[i].desc, + link_rate[cfg->link_rate & IPR_PHY_LINK_RATE_MASK], + be32_to_cpu(cfg->wwid[0]), be32_to_cpu(cfg->wwid[1])); + } else if (cfg->cascaded_expander == 0xff) { + ipr_hcam_err(hostrcb, "%s %s: Phy=%d, Link rate=%s, " + "WWN=%08X%08X\n", path_status_desc[j].desc, + path_type_desc[i].desc, cfg->phy, + link_rate[cfg->link_rate & IPR_PHY_LINK_RATE_MASK], + be32_to_cpu(cfg->wwid[0]), be32_to_cpu(cfg->wwid[1])); + } else if (cfg->phy == 0xff) { + ipr_hcam_err(hostrcb, "%s %s: Cascade=%d, Link rate=%s, " + "WWN=%08X%08X\n", path_status_desc[j].desc, + path_type_desc[i].desc, cfg->cascaded_expander, + link_rate[cfg->link_rate & IPR_PHY_LINK_RATE_MASK], + be32_to_cpu(cfg->wwid[0]), be32_to_cpu(cfg->wwid[1])); + } else { + ipr_hcam_err(hostrcb, "%s %s: Cascade=%d, Phy=%d, Link rate=%s " + "WWN=%08X%08X\n", path_status_desc[j].desc, + path_type_desc[i].desc, cfg->cascaded_expander, cfg->phy, + link_rate[cfg->link_rate & IPR_PHY_LINK_RATE_MASK], + be32_to_cpu(cfg->wwid[0]), be32_to_cpu(cfg->wwid[1])); + } + } + return; + } + } + + ipr_hcam_err(hostrcb, "Path element=%02X: Cascade=%d Phy=%d Link rate=%s " + "WWN=%08X%08X\n", cfg->type_status, cfg->cascaded_expander, cfg->phy, + link_rate[cfg->link_rate & IPR_PHY_LINK_RATE_MASK], + be32_to_cpu(cfg->wwid[0]), be32_to_cpu(cfg->wwid[1])); +} + +/** + * ipr_log_fabric_error - Log a fabric error. + * @ioa_cfg: ioa config struct + * @hostrcb: hostrcb struct + * + * Return value: + * none + **/ +static void ipr_log_fabric_error(struct ipr_ioa_cfg *ioa_cfg, + struct ipr_hostrcb *hostrcb) +{ + struct ipr_hostrcb_type_20_error *error; + struct ipr_hostrcb_fabric_desc *fabric; + struct ipr_hostrcb_config_element *cfg; + int i, add_len; + + error = &hostrcb->hcam.u.error.u.type_20_error; + error->failure_reason[sizeof(error->failure_reason) - 1] = '\0'; + ipr_hcam_err(hostrcb, "%s\n", error->failure_reason); + + add_len = be32_to_cpu(hostrcb->hcam.length) - + (offsetof(struct ipr_hostrcb_error, u) + + offsetof(struct ipr_hostrcb_type_20_error, desc)); + + for (i = 0, fabric = error->desc; i < error->num_entries; i++) { + ipr_log_fabric_path(hostrcb, fabric); + for_each_fabric_cfg(fabric, cfg) + ipr_log_path_elem(hostrcb, cfg); + + add_len -= be16_to_cpu(fabric->length); + fabric = (struct ipr_hostrcb_fabric_desc *) + ((unsigned long)fabric + be16_to_cpu(fabric->length)); + } + + ipr_log_hex_data(ioa_cfg, (u32 *)fabric, add_len); +} + /** * ipr_log_generic_error - Log an adapter error. * @ioa_cfg: ioa config struct @@ -1332,7 +1549,7 @@ static void ipr_log_dual_ioa_error(struct ipr_ioa_cfg *ioa_cfg, static void ipr_log_generic_error(struct ipr_ioa_cfg *ioa_cfg, struct ipr_hostrcb *hostrcb) { - ipr_log_hex_data(hostrcb->hcam.u.raw.data, + ipr_log_hex_data(ioa_cfg, hostrcb->hcam.u.raw.data, be32_to_cpu(hostrcb->hcam.length)); } @@ -1394,13 +1611,7 @@ static void ipr_handle_log_data(struct ipr_ioa_cfg *ioa_cfg, if (!ipr_error_table[error_index].log_hcam) return; - if (ipr_is_device(&hostrcb->hcam.u.error.failing_dev_res_addr)) { - ipr_ra_err(ioa_cfg, hostrcb->hcam.u.error.failing_dev_res_addr, - "%s\n", ipr_error_table[error_index].error); - } else { - dev_err(&ioa_cfg->pdev->dev, "%s\n", - ipr_error_table[error_index].error); - } + ipr_hcam_err(hostrcb, "%s\n", ipr_error_table[error_index].error); /* Set indication we have logged an error */ ioa_cfg->errors_logged++; @@ -1437,6 +1648,9 @@ static void ipr_handle_log_data(struct ipr_ioa_cfg *ioa_cfg, case IPR_HOST_RCB_OVERLAY_ID_17: ipr_log_enhanced_dual_ioa_error(ioa_cfg, hostrcb); break; + case IPR_HOST_RCB_OVERLAY_ID_20: + ipr_log_fabric_error(ioa_cfg, hostrcb); + break; case IPR_HOST_RCB_OVERLAY_ID_1: case IPR_HOST_RCB_OVERLAY_ID_DEFAULT: default: @@ -2093,7 +2307,7 @@ static void ipr_release_dump(struct kref *kref) /** * ipr_worker_thread - Worker thread - * @data: ioa config struct + * @work: ioa config struct * * Called at task level from a work thread. This function takes care * of adding and removing device from the mid-layer as configuration @@ -2102,13 +2316,14 @@ static void ipr_release_dump(struct kref *kref) * Return value: * nothing **/ -static void ipr_worker_thread(void *data) +static void ipr_worker_thread(struct work_struct *work) { unsigned long lock_flags; struct ipr_resource_entry *res; struct scsi_device *sdev; struct ipr_dump *dump; - struct ipr_ioa_cfg *ioa_cfg = data; + struct ipr_ioa_cfg *ioa_cfg = + container_of(work, struct ipr_ioa_cfg, work_q); u8 bus, target, lun; int did_work; @@ -2969,7 +3184,6 @@ static int ipr_alloc_dump(struct ipr_ioa_cfg *ioa_cfg) struct ipr_dump *dump; unsigned long lock_flags = 0; - ENTER; dump = kzalloc(sizeof(struct ipr_dump), GFP_KERNEL); if (!dump) { @@ -2996,7 +3210,6 @@ static int ipr_alloc_dump(struct ipr_ioa_cfg *ioa_cfg) } spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); - LEAVE; return 0; } @@ -3573,6 +3786,12 @@ static int ipr_sata_reset(struct ata_port *ap, unsigned int *classes) ENTER; spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); + while(ioa_cfg->in_reset_reload) { + spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); + wait_event(ioa_cfg->reset_wait_q, !ioa_cfg->in_reset_reload); + spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); + } + res = sata_port->res; if (res) { rc = ipr_device_reset(ioa_cfg, res); @@ -3636,6 +3855,10 @@ static int __ipr_eh_dev_reset(struct scsi_cmnd * scsi_cmd) if (ipr_cmd->ioarcb.res_handle == res->cfgte.res_handle) { if (ipr_cmd->scsi_cmd) ipr_cmd->done = ipr_scsi_eh_done; + if (ipr_cmd->qc && !(ipr_cmd->qc->flags & ATA_QCFLAG_FAILED)) { + ipr_cmd->qc->err_mask |= AC_ERR_TIMEOUT; + ipr_cmd->qc->flags |= ATA_QCFLAG_FAILED; + } } } @@ -3770,7 +3993,7 @@ static int ipr_cancel_op(struct scsi_cmnd * scsi_cmd) */ if (ioa_cfg->in_reset_reload || ioa_cfg->ioa_is_dead) return FAILED; - if (!res || (!ipr_is_gscsi(res) && !ipr_is_vset_device(res))) + if (!res || !ipr_is_gscsi(res)) return FAILED; list_for_each_entry(ipr_cmd, &ioa_cfg->pending_q, queue) { @@ -4615,7 +4838,7 @@ static int ipr_queuecommand(struct scsi_cmnd *scsi_cmd, * Return value: * 0 on success / other on failure **/ -int ipr_ioctl(struct scsi_device *sdev, int cmd, void __user *arg) +static int ipr_ioctl(struct scsi_device *sdev, int cmd, void __user *arg) { struct ipr_resource_entry *res; @@ -4648,40 +4871,6 @@ static const char * ipr_ioa_info(struct Scsi_Host *host) return buffer; } -/** - * ipr_scsi_timed_out - Handle scsi command timeout - * @scsi_cmd: scsi command struct - * - * Return value: - * EH_NOT_HANDLED - **/ -enum scsi_eh_timer_return ipr_scsi_timed_out(struct scsi_cmnd *scsi_cmd) -{ - struct ipr_ioa_cfg *ioa_cfg; - struct ipr_cmnd *ipr_cmd; - unsigned long flags; - - ENTER; - spin_lock_irqsave(scsi_cmd->device->host->host_lock, flags); - ioa_cfg = (struct ipr_ioa_cfg *)scsi_cmd->device->host->hostdata; - - list_for_each_entry(ipr_cmd, &ioa_cfg->pending_q, queue) { - if (ipr_cmd->qc && ipr_cmd->qc->scsicmd == scsi_cmd) { - ipr_cmd->qc->err_mask |= AC_ERR_TIMEOUT; - ipr_cmd->qc->flags |= ATA_QCFLAG_FAILED; - break; - } - } - - spin_unlock_irqrestore(scsi_cmd->device->host->host_lock, flags); - LEAVE; - return EH_NOT_HANDLED; -} - -static struct scsi_transport_template ipr_transport_template = { - .eh_timed_out = ipr_scsi_timed_out -}; - static struct scsi_host_template driver_template = { .module = THIS_MODULE, .name = "IPR", @@ -4776,6 +4965,12 @@ static void ipr_ata_post_internal(struct ata_queued_cmd *qc) unsigned long flags; spin_lock_irqsave(ioa_cfg->host->host_lock, flags); + while(ioa_cfg->in_reset_reload) { + spin_unlock_irqrestore(ioa_cfg->host->host_lock, flags); + wait_event(ioa_cfg->reset_wait_q, !ioa_cfg->in_reset_reload); + spin_lock_irqsave(ioa_cfg->host->host_lock, flags); + } + list_for_each_entry(ipr_cmd, &ioa_cfg->pending_q, queue) { if (ipr_cmd->qc == qc) { ipr_device_reset(ioa_cfg, sata_port->res); @@ -6745,7 +6940,7 @@ static int __devinit ipr_alloc_cmd_blks(struct ipr_ioa_cfg *ioa_cfg) return -ENOMEM; for (i = 0; i < IPR_NUM_CMD_BLKS; i++) { - ipr_cmd = pci_pool_alloc (ioa_cfg->ipr_cmd_pool, SLAB_KERNEL, &dma_addr); + ipr_cmd = pci_pool_alloc (ioa_cfg->ipr_cmd_pool, GFP_KERNEL, &dma_addr); if (!ipr_cmd) { ipr_free_cmd_blks(ioa_cfg); @@ -6832,6 +7027,7 @@ static int __devinit ipr_alloc_mem(struct ipr_ioa_cfg *ioa_cfg) ioa_cfg->hostrcb[i]->hostrcb_dma = ioa_cfg->hostrcb_dma[i] + offsetof(struct ipr_hostrcb, hcam); + ioa_cfg->hostrcb[i]->ioa_cfg = ioa_cfg; list_add_tail(&ioa_cfg->hostrcb[i]->queue, &ioa_cfg->hostrcb_free_q); } @@ -6926,7 +7122,7 @@ static void __devinit ipr_init_ioa_cfg(struct ipr_ioa_cfg *ioa_cfg, INIT_LIST_HEAD(&ioa_cfg->hostrcb_pending_q); INIT_LIST_HEAD(&ioa_cfg->free_res_q); INIT_LIST_HEAD(&ioa_cfg->used_res_q); - INIT_WORK(&ioa_cfg->work_q, ipr_worker_thread, ioa_cfg); + INIT_WORK(&ioa_cfg->work_q, ipr_worker_thread); init_waitqueue_head(&ioa_cfg->reset_wait_q); ioa_cfg->sdt_state = INACTIVE; if (ipr_enable_cache) @@ -7017,7 +7213,6 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev, ioa_cfg = (struct ipr_ioa_cfg *)host->hostdata; memset(ioa_cfg, 0, sizeof(struct ipr_ioa_cfg)); - host->transportt = &ipr_transport_template; ata_host_init(&ioa_cfg->ata_host, &pdev->dev, sata_port_info.flags, &ipr_sata_ops); @@ -7351,12 +7546,24 @@ static struct pci_device_id ipr_pci_table[] __devinitdata = { { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN, PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572B, 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, + { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN, + PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575C, + 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN, PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572A, 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN, PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572B, 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, + { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN, + PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575C, + 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, + { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN, + PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57B8, + 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, + { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN_E, + PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57B7, + 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_SNIPE, PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_2780, 0, 0, (kernel_ulong_t)&ipr_chip_cfg[1] }, @@ -7366,6 +7573,9 @@ static struct pci_device_id ipr_pci_table[] __devinitdata = { { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_SCAMP, PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_571F, 0, 0, (kernel_ulong_t)&ipr_chip_cfg[1] }, + { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_SCAMP, + PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572F, + 0, 0, (kernel_ulong_t)&ipr_chip_cfg[1] }, { } }; MODULE_DEVICE_TABLE(pci, ipr_pci_table); diff --git a/trunk/drivers/scsi/ipr.h b/trunk/drivers/scsi/ipr.h index 6d035283af08..9f62a1d4d511 100644 --- a/trunk/drivers/scsi/ipr.h +++ b/trunk/drivers/scsi/ipr.h @@ -37,8 +37,8 @@ /* * Literals */ -#define IPR_DRIVER_VERSION "2.2.0" -#define IPR_DRIVER_DATE "(September 25, 2006)" +#define IPR_DRIVER_VERSION "2.3.0" +#define IPR_DRIVER_DATE "(November 8, 2006)" /* * IPR_MAX_CMD_PER_LUN: This defines the maximum number of outstanding @@ -54,6 +54,8 @@ */ #define IPR_NUM_BASE_CMD_BLKS 100 +#define PCI_DEVICE_ID_IBM_OBSIDIAN_E 0x0339 + #define IPR_SUBS_DEV_ID_2780 0x0264 #define IPR_SUBS_DEV_ID_5702 0x0266 #define IPR_SUBS_DEV_ID_5703 0x0278 @@ -66,7 +68,11 @@ #define IPR_SUBS_DEV_ID_571F 0x02D5 #define IPR_SUBS_DEV_ID_572A 0x02C1 #define IPR_SUBS_DEV_ID_572B 0x02C2 +#define IPR_SUBS_DEV_ID_572F 0x02C3 #define IPR_SUBS_DEV_ID_575B 0x030D +#define IPR_SUBS_DEV_ID_575C 0x0338 +#define IPR_SUBS_DEV_ID_57B7 0x0360 +#define IPR_SUBS_DEV_ID_57B8 0x02C2 #define IPR_NAME "ipr" @@ -98,6 +104,7 @@ #define IPR_IOASC_IOA_WAS_RESET 0x10000001 #define IPR_IOASC_PCI_ACCESS_ERROR 0x10000002 +#define IPR_DEFAULT_MAX_ERROR_DUMP 984 #define IPR_NUM_LOG_HCAMS 2 #define IPR_NUM_CFG_CHG_HCAMS 2 #define IPR_NUM_HCAMS (IPR_NUM_LOG_HCAMS + IPR_NUM_CFG_CHG_HCAMS) @@ -731,6 +738,64 @@ struct ipr_hostrcb_type_17_error { u32 data[476]; }__attribute__((packed, aligned (4))); +struct ipr_hostrcb_config_element { + u8 type_status; +#define IPR_PATH_CFG_TYPE_MASK 0xF0 +#define IPR_PATH_CFG_NOT_EXIST 0x00 +#define IPR_PATH_CFG_IOA_PORT 0x10 +#define IPR_PATH_CFG_EXP_PORT 0x20 +#define IPR_PATH_CFG_DEVICE_PORT 0x30 +#define IPR_PATH_CFG_DEVICE_LUN 0x40 + +#define IPR_PATH_CFG_STATUS_MASK 0x0F +#define IPR_PATH_CFG_NO_PROB 0x00 +#define IPR_PATH_CFG_DEGRADED 0x01 +#define IPR_PATH_CFG_FAILED 0x02 +#define IPR_PATH_CFG_SUSPECT 0x03 +#define IPR_PATH_NOT_DETECTED 0x04 +#define IPR_PATH_INCORRECT_CONN 0x05 + + u8 cascaded_expander; + u8 phy; + u8 link_rate; +#define IPR_PHY_LINK_RATE_MASK 0x0F + + __be32 wwid[2]; +}__attribute__((packed, aligned (4))); + +struct ipr_hostrcb_fabric_desc { + __be16 length; + u8 ioa_port; + u8 cascaded_expander; + u8 phy; + u8 path_state; +#define IPR_PATH_ACTIVE_MASK 0xC0 +#define IPR_PATH_NO_INFO 0x00 +#define IPR_PATH_ACTIVE 0x40 +#define IPR_PATH_NOT_ACTIVE 0x80 + +#define IPR_PATH_STATE_MASK 0x0F +#define IPR_PATH_STATE_NO_INFO 0x00 +#define IPR_PATH_HEALTHY 0x01 +#define IPR_PATH_DEGRADED 0x02 +#define IPR_PATH_FAILED 0x03 + + __be16 num_entries; + struct ipr_hostrcb_config_element elem[1]; +}__attribute__((packed, aligned (4))); + +#define for_each_fabric_cfg(fabric, cfg) \ + for (cfg = (fabric)->elem; \ + cfg < ((fabric)->elem + be16_to_cpu((fabric)->num_entries)); \ + cfg++) + +struct ipr_hostrcb_type_20_error { + u8 failure_reason[64]; + u8 reserved[3]; + u8 num_entries; + struct ipr_hostrcb_fabric_desc desc[1]; +}__attribute__((packed, aligned (4))); + struct ipr_hostrcb_error { __be32 failing_dev_ioasc; struct ipr_res_addr failing_dev_res_addr; @@ -747,6 +812,7 @@ struct ipr_hostrcb_error { struct ipr_hostrcb_type_13_error type_13_error; struct ipr_hostrcb_type_14_error type_14_error; struct ipr_hostrcb_type_17_error type_17_error; + struct ipr_hostrcb_type_20_error type_20_error; } u; }__attribute__((packed, aligned (4))); @@ -786,6 +852,7 @@ struct ipr_hcam { #define IPR_HOST_RCB_OVERLAY_ID_14 0x14 #define IPR_HOST_RCB_OVERLAY_ID_16 0x16 #define IPR_HOST_RCB_OVERLAY_ID_17 0x17 +#define IPR_HOST_RCB_OVERLAY_ID_20 0x20 #define IPR_HOST_RCB_OVERLAY_ID_DEFAULT 0xFF u8 reserved1[3]; @@ -805,6 +872,7 @@ struct ipr_hostrcb { struct ipr_hcam hcam; dma_addr_t hostrcb_dma; struct list_head queue; + struct ipr_ioa_cfg *ioa_cfg; }; /* IPR smart dump table structures */ @@ -1283,6 +1351,17 @@ struct ipr_ucode_image_header { } \ } +#define ipr_hcam_err(hostrcb, fmt, ...) \ +{ \ + if (ipr_is_device(&(hostrcb)->hcam.u.error.failing_dev_res_addr)) { \ + ipr_ra_err((hostrcb)->ioa_cfg, \ + (hostrcb)->hcam.u.error.failing_dev_res_addr, \ + fmt, ##__VA_ARGS__); \ + } else { \ + dev_err(&(hostrcb)->ioa_cfg->pdev->dev, fmt, ##__VA_ARGS__); \ + } \ +} + #define ipr_trace ipr_dbg("%s: %s: Line: %d\n",\ __FILE__, __FUNCTION__, __LINE__) diff --git a/trunk/drivers/scsi/ips.c b/trunk/drivers/scsi/ips.c index f06a06ae6092..8b704f73055a 100644 --- a/trunk/drivers/scsi/ips.c +++ b/trunk/drivers/scsi/ips.c @@ -5001,7 +5001,7 @@ ips_init_copperhead(ips_ha_t * ha) break; /* Delay for 1 Second */ - msleep(IPS_ONE_SEC); + MDELAY(IPS_ONE_SEC); } if (j >= 45) @@ -5027,7 +5027,7 @@ ips_init_copperhead(ips_ha_t * ha) break; /* Delay for 1 Second */ - msleep(IPS_ONE_SEC); + MDELAY(IPS_ONE_SEC); } if (j >= 240) @@ -5045,7 +5045,7 @@ ips_init_copperhead(ips_ha_t * ha) break; /* Delay for 1 Second */ - msleep(IPS_ONE_SEC); + MDELAY(IPS_ONE_SEC); } if (i >= 240) @@ -5095,7 +5095,7 @@ ips_init_copperhead_memio(ips_ha_t * ha) break; /* Delay for 1 Second */ - msleep(IPS_ONE_SEC); + MDELAY(IPS_ONE_SEC); } if (j >= 45) @@ -5121,7 +5121,7 @@ ips_init_copperhead_memio(ips_ha_t * ha) break; /* Delay for 1 Second */ - msleep(IPS_ONE_SEC); + MDELAY(IPS_ONE_SEC); } if (j >= 240) @@ -5139,7 +5139,7 @@ ips_init_copperhead_memio(ips_ha_t * ha) break; /* Delay for 1 Second */ - msleep(IPS_ONE_SEC); + MDELAY(IPS_ONE_SEC); } if (i >= 240) @@ -5191,7 +5191,7 @@ ips_init_morpheus(ips_ha_t * ha) break; /* Delay for 1 Second */ - msleep(IPS_ONE_SEC); + MDELAY(IPS_ONE_SEC); } if (i >= 45) { @@ -5217,7 +5217,7 @@ ips_init_morpheus(ips_ha_t * ha) if (Post != 0x4F00) break; /* Delay for 1 Second */ - msleep(IPS_ONE_SEC); + MDELAY(IPS_ONE_SEC); } if (i >= 120) { @@ -5247,7 +5247,7 @@ ips_init_morpheus(ips_ha_t * ha) break; /* Delay for 1 Second */ - msleep(IPS_ONE_SEC); + MDELAY(IPS_ONE_SEC); } if (i >= 240) { @@ -5307,12 +5307,12 @@ ips_reset_copperhead(ips_ha_t * ha) outb(IPS_BIT_RST, ha->io_addr + IPS_REG_SCPR); /* Delay for 1 Second */ - msleep(IPS_ONE_SEC); + MDELAY(IPS_ONE_SEC); outb(0, ha->io_addr + IPS_REG_SCPR); /* Delay for 1 Second */ - msleep(IPS_ONE_SEC); + MDELAY(IPS_ONE_SEC); if ((*ha->func.init) (ha)) break; @@ -5352,12 +5352,12 @@ ips_reset_copperhead_memio(ips_ha_t * ha) writeb(IPS_BIT_RST, ha->mem_ptr + IPS_REG_SCPR); /* Delay for 1 Second */ - msleep(IPS_ONE_SEC); + MDELAY(IPS_ONE_SEC); writeb(0, ha->mem_ptr + IPS_REG_SCPR); /* Delay for 1 Second */ - msleep(IPS_ONE_SEC); + MDELAY(IPS_ONE_SEC); if ((*ha->func.init) (ha)) break; @@ -5398,7 +5398,7 @@ ips_reset_morpheus(ips_ha_t * ha) writel(0x80000000, ha->mem_ptr + IPS_REG_I960_IDR); /* Delay for 5 Seconds */ - msleep(5 * IPS_ONE_SEC); + MDELAY(5 * IPS_ONE_SEC); /* Do a PCI config read to wait for adapter */ pci_read_config_byte(ha->pcidev, 4, &junk); diff --git a/trunk/drivers/scsi/ips.h b/trunk/drivers/scsi/ips.h index 34680f3dd452..b726dcc424b1 100644 --- a/trunk/drivers/scsi/ips.h +++ b/trunk/drivers/scsi/ips.h @@ -51,6 +51,7 @@ #define _IPS_H_ #include +#include #include #include @@ -116,9 +117,11 @@ dev_printk(level , &((pcidev)->dev) , format , ## arg) #endif - #ifndef MDELAY - #define MDELAY mdelay - #endif + #define MDELAY(n) \ + do { \ + mdelay(n); \ + touch_nmi_watchdog(); \ + } while (0) #ifndef min #define min(x,y) ((x) < (y) ? x : y) diff --git a/trunk/drivers/scsi/libiscsi.c b/trunk/drivers/scsi/libiscsi.c index 5d8862189485..e11b23c641e2 100644 --- a/trunk/drivers/scsi/libiscsi.c +++ b/trunk/drivers/scsi/libiscsi.c @@ -719,9 +719,10 @@ static int iscsi_data_xmit(struct iscsi_conn *conn) return rc; } -static void iscsi_xmitworker(void *data) +static void iscsi_xmitworker(struct work_struct *work) { - struct iscsi_conn *conn = data; + struct iscsi_conn *conn = + container_of(work, struct iscsi_conn, xmitwork); int rc; /* * serialize Xmit worker on a per-connection basis. @@ -1512,7 +1513,7 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, uint32_t conn_idx) if (conn->mgmtqueue == ERR_PTR(-ENOMEM)) goto mgmtqueue_alloc_fail; - INIT_WORK(&conn->xmitwork, iscsi_xmitworker, conn); + INIT_WORK(&conn->xmitwork, iscsi_xmitworker); /* allocate login_mtask used for the login/text sequences */ spin_lock_bh(&session->lock); diff --git a/trunk/drivers/scsi/libsas/sas_discover.c b/trunk/drivers/scsi/libsas/sas_discover.c index d977bd492d8d..fb7df7b75811 100644 --- a/trunk/drivers/scsi/libsas/sas_discover.c +++ b/trunk/drivers/scsi/libsas/sas_discover.c @@ -647,10 +647,12 @@ void sas_unregister_domain_devices(struct asd_sas_port *port) * Discover process only interrogates devices in order to discover the * domain. */ -static void sas_discover_domain(void *data) +static void sas_discover_domain(struct work_struct *work) { int error = 0; - struct asd_sas_port *port = data; + struct sas_discovery_event *ev = + container_of(work, struct sas_discovery_event, work); + struct asd_sas_port *port = ev->port; sas_begin_event(DISCE_DISCOVER_DOMAIN, &port->disc.disc_event_lock, &port->disc.pending); @@ -692,10 +694,12 @@ static void sas_discover_domain(void *data) current->pid, error); } -static void sas_revalidate_domain(void *data) +static void sas_revalidate_domain(struct work_struct *work) { int res = 0; - struct asd_sas_port *port = data; + struct sas_discovery_event *ev = + container_of(work, struct sas_discovery_event, work); + struct asd_sas_port *port = ev->port; sas_begin_event(DISCE_REVALIDATE_DOMAIN, &port->disc.disc_event_lock, &port->disc.pending); @@ -722,7 +726,7 @@ int sas_discover_event(struct asd_sas_port *port, enum discover_event ev) BUG_ON(ev >= DISC_NUM_EVENTS); sas_queue_event(ev, &disc->disc_event_lock, &disc->pending, - &disc->disc_work[ev], port->ha->core.shost); + &disc->disc_work[ev].work, port->ha->core.shost); return 0; } @@ -737,13 +741,15 @@ void sas_init_disc(struct sas_discovery *disc, struct asd_sas_port *port) { int i; - static void (*sas_event_fns[DISC_NUM_EVENTS])(void *) = { + static const work_func_t sas_event_fns[DISC_NUM_EVENTS] = { [DISCE_DISCOVER_DOMAIN] = sas_discover_domain, [DISCE_REVALIDATE_DOMAIN] = sas_revalidate_domain, }; spin_lock_init(&disc->disc_event_lock); disc->pending = 0; - for (i = 0; i < DISC_NUM_EVENTS; i++) - INIT_WORK(&disc->disc_work[i], sas_event_fns[i], port); + for (i = 0; i < DISC_NUM_EVENTS; i++) { + INIT_WORK(&disc->disc_work[i].work, sas_event_fns[i]); + disc->disc_work[i].port = port; + } } diff --git a/trunk/drivers/scsi/libsas/sas_event.c b/trunk/drivers/scsi/libsas/sas_event.c index 19110ed1c89c..d83392ee6823 100644 --- a/trunk/drivers/scsi/libsas/sas_event.c +++ b/trunk/drivers/scsi/libsas/sas_event.c @@ -31,7 +31,7 @@ static void notify_ha_event(struct sas_ha_struct *sas_ha, enum ha_event event) BUG_ON(event >= HA_NUM_EVENTS); sas_queue_event(event, &sas_ha->event_lock, &sas_ha->pending, - &sas_ha->ha_events[event], sas_ha->core.shost); + &sas_ha->ha_events[event].work, sas_ha->core.shost); } static void notify_port_event(struct asd_sas_phy *phy, enum port_event event) @@ -41,7 +41,7 @@ static void notify_port_event(struct asd_sas_phy *phy, enum port_event event) BUG_ON(event >= PORT_NUM_EVENTS); sas_queue_event(event, &ha->event_lock, &phy->port_events_pending, - &phy->port_events[event], ha->core.shost); + &phy->port_events[event].work, ha->core.shost); } static void notify_phy_event(struct asd_sas_phy *phy, enum phy_event event) @@ -51,12 +51,12 @@ static void notify_phy_event(struct asd_sas_phy *phy, enum phy_event event) BUG_ON(event >= PHY_NUM_EVENTS); sas_queue_event(event, &ha->event_lock, &phy->phy_events_pending, - &phy->phy_events[event], ha->core.shost); + &phy->phy_events[event].work, ha->core.shost); } int sas_init_events(struct sas_ha_struct *sas_ha) { - static void (*sas_ha_event_fns[HA_NUM_EVENTS])(void *) = { + static const work_func_t sas_ha_event_fns[HA_NUM_EVENTS] = { [HAE_RESET] = sas_hae_reset, }; @@ -64,8 +64,10 @@ int sas_init_events(struct sas_ha_struct *sas_ha) spin_lock_init(&sas_ha->event_lock); - for (i = 0; i < HA_NUM_EVENTS; i++) - INIT_WORK(&sas_ha->ha_events[i], sas_ha_event_fns[i], sas_ha); + for (i = 0; i < HA_NUM_EVENTS; i++) { + INIT_WORK(&sas_ha->ha_events[i].work, sas_ha_event_fns[i]); + sas_ha->ha_events[i].ha = sas_ha; + } sas_ha->notify_ha_event = notify_ha_event; sas_ha->notify_port_event = notify_port_event; diff --git a/trunk/drivers/scsi/libsas/sas_expander.c b/trunk/drivers/scsi/libsas/sas_expander.c index e34a93435497..d31e6fa466f7 100644 --- a/trunk/drivers/scsi/libsas/sas_expander.c +++ b/trunk/drivers/scsi/libsas/sas_expander.c @@ -597,10 +597,15 @@ static struct domain_device *sas_ex_discover_end_dev( child->iproto = phy->attached_iproto; memcpy(child->sas_addr, phy->attached_sas_addr, SAS_ADDR_SIZE); sas_hash_addr(child->hashed_sas_addr, child->sas_addr); - phy->port = sas_port_alloc(&parent->rphy->dev, phy_id); - BUG_ON(!phy->port); - /* FIXME: better error handling*/ - BUG_ON(sas_port_add(phy->port) != 0); + if (!phy->port) { + phy->port = sas_port_alloc(&parent->rphy->dev, phy_id); + if (unlikely(!phy->port)) + goto out_err; + if (unlikely(sas_port_add(phy->port) != 0)) { + sas_port_free(phy->port); + goto out_err; + } + } sas_ex_get_linkrate(parent, child, phy); if ((phy->attached_tproto & SAS_PROTO_STP) || phy->attached_sata_dev) { @@ -615,8 +620,7 @@ static struct domain_device *sas_ex_discover_end_dev( SAS_DPRINTK("report phy sata to %016llx:0x%x returned " "0x%x\n", SAS_ADDR(parent->sas_addr), phy_id, res); - kfree(child); - return NULL; + goto out_free; } memcpy(child->frame_rcvd, &child->sata_dev.rps_resp.rps.fis, sizeof(struct dev_to_host_fis)); @@ -627,14 +631,14 @@ static struct domain_device *sas_ex_discover_end_dev( "%016llx:0x%x returned 0x%x\n", SAS_ADDR(child->sas_addr), SAS_ADDR(parent->sas_addr), phy_id, res); - kfree(child); - return NULL; + goto out_free; } } else if (phy->attached_tproto & SAS_PROTO_SSP) { child->dev_type = SAS_END_DEV; rphy = sas_end_device_alloc(phy->port); /* FIXME: error handling */ - BUG_ON(!rphy); + if (unlikely(!rphy)) + goto out_free; child->tproto = phy->attached_tproto; sas_init_dev(child); @@ -651,9 +655,7 @@ static struct domain_device *sas_ex_discover_end_dev( "at %016llx:0x%x returned 0x%x\n", SAS_ADDR(child->sas_addr), SAS_ADDR(parent->sas_addr), phy_id, res); - /* FIXME: this kfrees list elements without removing them */ - //kfree(child); - return NULL; + goto out_list_del; } } else { SAS_DPRINTK("target proto 0x%x at %016llx:0x%x not handled\n", @@ -663,6 +665,16 @@ static struct domain_device *sas_ex_discover_end_dev( list_add_tail(&child->siblings, &parent_ex->children); return child; + + out_list_del: + list_del(&child->dev_list_node); + sas_rphy_free(rphy); + out_free: + sas_port_delete(phy->port); + out_err: + phy->port = NULL; + kfree(child); + return NULL; } static struct domain_device *sas_ex_discover_expander( diff --git a/trunk/drivers/scsi/libsas/sas_init.c b/trunk/drivers/scsi/libsas/sas_init.c index c836a237fb79..2f0c07fc3f48 100644 --- a/trunk/drivers/scsi/libsas/sas_init.c +++ b/trunk/drivers/scsi/libsas/sas_init.c @@ -36,7 +36,7 @@ #include "../scsi_sas_internal.h" -kmem_cache_t *sas_task_cache; +struct kmem_cache *sas_task_cache; /*------------ SAS addr hash -----------*/ void sas_hash_addr(u8 *hashed, const u8 *sas_addr) @@ -65,9 +65,11 @@ void sas_hash_addr(u8 *hashed, const u8 *sas_addr) /* ---------- HA events ---------- */ -void sas_hae_reset(void *data) +void sas_hae_reset(struct work_struct *work) { - struct sas_ha_struct *ha = data; + struct sas_ha_event *ev = + container_of(work, struct sas_ha_event, work); + struct sas_ha_struct *ha = ev->ha; sas_begin_event(HAE_RESET, &ha->event_lock, &ha->pending); @@ -112,6 +114,8 @@ int sas_register_ha(struct sas_ha_struct *sas_ha) } } + INIT_LIST_HEAD(&sas_ha->eh_done_q); + return 0; Undo_ports: @@ -142,7 +146,7 @@ static int sas_get_linkerrors(struct sas_phy *phy) return sas_smp_get_phy_events(phy); } -static int sas_phy_reset(struct sas_phy *phy, int hard_reset) +int sas_phy_reset(struct sas_phy *phy, int hard_reset) { int ret; enum phy_func reset_type; diff --git a/trunk/drivers/scsi/libsas/sas_internal.h b/trunk/drivers/scsi/libsas/sas_internal.h index bffcee474921..137d7e496b6d 100644 --- a/trunk/drivers/scsi/libsas/sas_internal.h +++ b/trunk/drivers/scsi/libsas/sas_internal.h @@ -60,11 +60,11 @@ void sas_shutdown_queue(struct sas_ha_struct *sas_ha); void sas_deform_port(struct asd_sas_phy *phy); -void sas_porte_bytes_dmaed(void *); -void sas_porte_broadcast_rcvd(void *); -void sas_porte_link_reset_err(void *); -void sas_porte_timer_event(void *); -void sas_porte_hard_reset(void *); +void sas_porte_bytes_dmaed(struct work_struct *work); +void sas_porte_broadcast_rcvd(struct work_struct *work); +void sas_porte_link_reset_err(struct work_struct *work); +void sas_porte_timer_event(struct work_struct *work); +void sas_porte_hard_reset(struct work_struct *work); int sas_notify_lldd_dev_found(struct domain_device *); void sas_notify_lldd_dev_gone(struct domain_device *); @@ -75,7 +75,7 @@ int sas_smp_get_phy_events(struct sas_phy *phy); struct domain_device *sas_find_dev_by_rphy(struct sas_rphy *rphy); -void sas_hae_reset(void *); +void sas_hae_reset(struct work_struct *work); static inline void sas_queue_event(int event, spinlock_t *lock, unsigned long *pending, diff --git a/trunk/drivers/scsi/libsas/sas_phy.c b/trunk/drivers/scsi/libsas/sas_phy.c index 9340cdbae4a3..b459c4b635b1 100644 --- a/trunk/drivers/scsi/libsas/sas_phy.c +++ b/trunk/drivers/scsi/libsas/sas_phy.c @@ -30,9 +30,11 @@ /* ---------- Phy events ---------- */ -static void sas_phye_loss_of_signal(void *data) +static void sas_phye_loss_of_signal(struct work_struct *work) { - struct asd_sas_phy *phy = data; + struct asd_sas_event *ev = + container_of(work, struct asd_sas_event, work); + struct asd_sas_phy *phy = ev->phy; sas_begin_event(PHYE_LOSS_OF_SIGNAL, &phy->ha->event_lock, &phy->phy_events_pending); @@ -40,18 +42,22 @@ static void sas_phye_loss_of_signal(void *data) sas_deform_port(phy); } -static void sas_phye_oob_done(void *data) +static void sas_phye_oob_done(struct work_struct *work) { - struct asd_sas_phy *phy = data; + struct asd_sas_event *ev = + container_of(work, struct asd_sas_event, work); + struct asd_sas_phy *phy = ev->phy; sas_begin_event(PHYE_OOB_DONE, &phy->ha->event_lock, &phy->phy_events_pending); phy->error = 0; } -static void sas_phye_oob_error(void *data) +static void sas_phye_oob_error(struct work_struct *work) { - struct asd_sas_phy *phy = data; + struct asd_sas_event *ev = + container_of(work, struct asd_sas_event, work); + struct asd_sas_phy *phy = ev->phy; struct sas_ha_struct *sas_ha = phy->ha; struct asd_sas_port *port = phy->port; struct sas_internal *i = @@ -80,9 +86,11 @@ static void sas_phye_oob_error(void *data) } } -static void sas_phye_spinup_hold(void *data) +static void sas_phye_spinup_hold(struct work_struct *work) { - struct asd_sas_phy *phy = data; + struct asd_sas_event *ev = + container_of(work, struct asd_sas_event, work); + struct asd_sas_phy *phy = ev->phy; struct sas_ha_struct *sas_ha = phy->ha; struct sas_internal *i = to_sas_internal(sas_ha->core.shost->transportt); @@ -100,14 +108,14 @@ int sas_register_phys(struct sas_ha_struct *sas_ha) { int i; - static void (*sas_phy_event_fns[PHY_NUM_EVENTS])(void *) = { + static const work_func_t sas_phy_event_fns[PHY_NUM_EVENTS] = { [PHYE_LOSS_OF_SIGNAL] = sas_phye_loss_of_signal, [PHYE_OOB_DONE] = sas_phye_oob_done, [PHYE_OOB_ERROR] = sas_phye_oob_error, [PHYE_SPINUP_HOLD] = sas_phye_spinup_hold, }; - static void (*sas_port_event_fns[PORT_NUM_EVENTS])(void *) = { + static const work_func_t sas_port_event_fns[PORT_NUM_EVENTS] = { [PORTE_BYTES_DMAED] = sas_porte_bytes_dmaed, [PORTE_BROADCAST_RCVD] = sas_porte_broadcast_rcvd, [PORTE_LINK_RESET_ERR] = sas_porte_link_reset_err, @@ -122,13 +130,18 @@ int sas_register_phys(struct sas_ha_struct *sas_ha) phy->error = 0; INIT_LIST_HEAD(&phy->port_phy_el); - for (k = 0; k < PORT_NUM_EVENTS; k++) - INIT_WORK(&phy->port_events[k], sas_port_event_fns[k], - phy); + for (k = 0; k < PORT_NUM_EVENTS; k++) { + INIT_WORK(&phy->port_events[k].work, + sas_port_event_fns[k]); + phy->port_events[k].phy = phy; + } + + for (k = 0; k < PHY_NUM_EVENTS; k++) { + INIT_WORK(&phy->phy_events[k].work, + sas_phy_event_fns[k]); + phy->phy_events[k].phy = phy; + } - for (k = 0; k < PHY_NUM_EVENTS; k++) - INIT_WORK(&phy->phy_events[k], sas_phy_event_fns[k], - phy); phy->port = NULL; phy->ha = sas_ha; spin_lock_init(&phy->frame_rcvd_lock); diff --git a/trunk/drivers/scsi/libsas/sas_port.c b/trunk/drivers/scsi/libsas/sas_port.c index 253cdcf306a2..971c37ceecb4 100644 --- a/trunk/drivers/scsi/libsas/sas_port.c +++ b/trunk/drivers/scsi/libsas/sas_port.c @@ -181,9 +181,11 @@ void sas_deform_port(struct asd_sas_phy *phy) /* ---------- SAS port events ---------- */ -void sas_porte_bytes_dmaed(void *data) +void sas_porte_bytes_dmaed(struct work_struct *work) { - struct asd_sas_phy *phy = data; + struct asd_sas_event *ev = + container_of(work, struct asd_sas_event, work); + struct asd_sas_phy *phy = ev->phy; sas_begin_event(PORTE_BYTES_DMAED, &phy->ha->event_lock, &phy->port_events_pending); @@ -191,11 +193,13 @@ void sas_porte_bytes_dmaed(void *data) sas_form_port(phy); } -void sas_porte_broadcast_rcvd(void *data) +void sas_porte_broadcast_rcvd(struct work_struct *work) { + struct asd_sas_event *ev = + container_of(work, struct asd_sas_event, work); + struct asd_sas_phy *phy = ev->phy; unsigned long flags; u32 prim; - struct asd_sas_phy *phy = data; sas_begin_event(PORTE_BROADCAST_RCVD, &phy->ha->event_lock, &phy->port_events_pending); @@ -208,9 +212,11 @@ void sas_porte_broadcast_rcvd(void *data) sas_discover_event(phy->port, DISCE_REVALIDATE_DOMAIN); } -void sas_porte_link_reset_err(void *data) +void sas_porte_link_reset_err(struct work_struct *work) { - struct asd_sas_phy *phy = data; + struct asd_sas_event *ev = + container_of(work, struct asd_sas_event, work); + struct asd_sas_phy *phy = ev->phy; sas_begin_event(PORTE_LINK_RESET_ERR, &phy->ha->event_lock, &phy->port_events_pending); @@ -218,9 +224,11 @@ void sas_porte_link_reset_err(void *data) sas_deform_port(phy); } -void sas_porte_timer_event(void *data) +void sas_porte_timer_event(struct work_struct *work) { - struct asd_sas_phy *phy = data; + struct asd_sas_event *ev = + container_of(work, struct asd_sas_event, work); + struct asd_sas_phy *phy = ev->phy; sas_begin_event(PORTE_TIMER_EVENT, &phy->ha->event_lock, &phy->port_events_pending); @@ -228,9 +236,11 @@ void sas_porte_timer_event(void *data) sas_deform_port(phy); } -void sas_porte_hard_reset(void *data) +void sas_porte_hard_reset(struct work_struct *work) { - struct asd_sas_phy *phy = data; + struct asd_sas_event *ev = + container_of(work, struct asd_sas_event, work); + struct asd_sas_phy *phy = ev->phy; sas_begin_event(PORTE_HARD_RESET, &phy->ha->event_lock, &phy->port_events_pending); diff --git a/trunk/drivers/scsi/libsas/sas_scsi_host.c b/trunk/drivers/scsi/libsas/sas_scsi_host.c index e46e79355b77..22672d54aa27 100644 --- a/trunk/drivers/scsi/libsas/sas_scsi_host.c +++ b/trunk/drivers/scsi/libsas/sas_scsi_host.c @@ -29,9 +29,11 @@ #include #include #include +#include #include #include #include "../scsi_sas_internal.h" +#include "../scsi_transport_api.h" #include #include @@ -46,6 +48,7 @@ static void sas_scsi_task_done(struct sas_task *task) { struct task_status_struct *ts = &task->task_status; struct scsi_cmnd *sc = task->uldd_task; + struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(sc->device->host); unsigned ts_flags = task->task_state_flags; int hs = 0, stat = 0; @@ -116,7 +119,7 @@ static void sas_scsi_task_done(struct sas_task *task) sas_free_task(task); /* This is very ugly but this is how SCSI Core works. */ if (ts_flags & SAS_TASK_STATE_ABORTED) - scsi_finish_command(sc); + scsi_eh_finish_cmd(sc, &sas_ha->eh_done_q); else sc->scsi_done(sc); } @@ -307,6 +310,15 @@ static enum task_disposition sas_scsi_find_task(struct sas_task *task) spin_unlock_irqrestore(&core->task_queue_lock, flags); } + spin_lock_irqsave(&task->task_state_lock, flags); + if (task->task_state_flags & SAS_TASK_INITIATOR_ABORTED) { + spin_unlock_irqrestore(&task->task_state_lock, flags); + SAS_DPRINTK("%s: task 0x%p already aborted\n", + __FUNCTION__, task); + return TASK_IS_ABORTED; + } + spin_unlock_irqrestore(&task->task_state_lock, flags); + for (i = 0; i < 5; i++) { SAS_DPRINTK("%s: aborting task 0x%p\n", __FUNCTION__, task); res = si->dft->lldd_abort_task(task); @@ -409,13 +421,16 @@ void sas_scsi_recover_host(struct Scsi_Host *shost) SAS_DPRINTK("going over list...\n"); list_for_each_entry_safe(cmd, n, &error_q, eh_entry) { struct sas_task *task = TO_SAS_TASK(cmd); + list_del_init(&cmd->eh_entry); + if (!task) { + SAS_DPRINTK("%s: taskless cmd?!\n", __FUNCTION__); + continue; + } SAS_DPRINTK("trying to find task 0x%p\n", task); - list_del_init(&cmd->eh_entry); res = sas_scsi_find_task(task); cmd->eh_eflags = 0; - shost->host_failed--; switch (res) { case TASK_IS_DONE: @@ -491,6 +506,7 @@ void sas_scsi_recover_host(struct Scsi_Host *shost) } } out: + scsi_eh_flush_done_q(&ha->eh_done_q); SAS_DPRINTK("--- Exit %s\n", __FUNCTION__); return; clear_q: @@ -508,12 +524,18 @@ enum scsi_eh_timer_return sas_scsi_timed_out(struct scsi_cmnd *cmd) unsigned long flags; if (!task) { - SAS_DPRINTK("command 0x%p, task 0x%p, timed out: EH_HANDLED\n", + SAS_DPRINTK("command 0x%p, task 0x%p, gone: EH_HANDLED\n", cmd, task); return EH_HANDLED; } spin_lock_irqsave(&task->task_state_lock, flags); + if (task->task_state_flags & SAS_TASK_INITIATOR_ABORTED) { + spin_unlock_irqrestore(&task->task_state_lock, flags); + SAS_DPRINTK("command 0x%p, task 0x%p, aborted by initiator: " + "EH_NOT_HANDLED\n", cmd, task); + return EH_NOT_HANDLED; + } if (task->task_state_flags & SAS_TASK_STATE_DONE) { spin_unlock_irqrestore(&task->task_state_lock, flags); SAS_DPRINTK("command 0x%p, task 0x%p, timed out: EH_HANDLED\n", @@ -777,6 +799,66 @@ void sas_shutdown_queue(struct sas_ha_struct *sas_ha) spin_unlock_irqrestore(&core->task_queue_lock, flags); } +static int do_sas_task_abort(struct sas_task *task) +{ + struct scsi_cmnd *sc = task->uldd_task; + struct sas_internal *si = + to_sas_internal(task->dev->port->ha->core.shost->transportt); + unsigned long flags; + int res; + + spin_lock_irqsave(&task->task_state_lock, flags); + if (task->task_state_flags & SAS_TASK_STATE_ABORTED) { + spin_unlock_irqrestore(&task->task_state_lock, flags); + SAS_DPRINTK("%s: Task %p already aborted.\n", __FUNCTION__, + task); + return 0; + } + + task->task_state_flags |= SAS_TASK_INITIATOR_ABORTED; + if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) + task->task_state_flags |= SAS_TASK_STATE_ABORTED; + spin_unlock_irqrestore(&task->task_state_lock, flags); + + if (!si->dft->lldd_abort_task) + return -ENODEV; + + res = si->dft->lldd_abort_task(task); + if ((task->task_state_flags & SAS_TASK_STATE_DONE) || + (res == TMF_RESP_FUNC_COMPLETE)) + { + /* SMP commands don't have scsi_cmds(?) */ + if (!sc) { + task->task_done(task); + return 0; + } + scsi_req_abort_cmd(sc); + scsi_schedule_eh(sc->device->host); + return 0; + } + + spin_lock_irqsave(&task->task_state_lock, flags); + task->task_state_flags &= ~SAS_TASK_INITIATOR_ABORTED; + if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) + task->task_state_flags &= ~SAS_TASK_STATE_ABORTED; + spin_unlock_irqrestore(&task->task_state_lock, flags); + + return -EAGAIN; +} + +void sas_task_abort(struct work_struct *work) +{ + struct sas_task *task = + container_of(work, struct sas_task, abort_work); + int i; + + for (i = 0; i < 5; i++) + if (!do_sas_task_abort(task)) + return; + + SAS_DPRINTK("%s: Could not kill task!\n", __FUNCTION__); +} + EXPORT_SYMBOL_GPL(sas_queuecommand); EXPORT_SYMBOL_GPL(sas_target_alloc); EXPORT_SYMBOL_GPL(sas_slave_configure); @@ -784,3 +866,5 @@ EXPORT_SYMBOL_GPL(sas_slave_destroy); EXPORT_SYMBOL_GPL(sas_change_queue_depth); EXPORT_SYMBOL_GPL(sas_change_queue_type); EXPORT_SYMBOL_GPL(sas_bios_param); +EXPORT_SYMBOL_GPL(sas_task_abort); +EXPORT_SYMBOL_GPL(sas_phy_reset); diff --git a/trunk/drivers/scsi/libsrp.c b/trunk/drivers/scsi/libsrp.c new file mode 100644 index 000000000000..89403b00e042 --- /dev/null +++ b/trunk/drivers/scsi/libsrp.c @@ -0,0 +1,441 @@ +/* + * SCSI RDAM Protocol lib functions + * + * Copyright (C) 2006 FUJITA Tomonori + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +enum srp_task_attributes { + SRP_SIMPLE_TASK = 0, + SRP_HEAD_TASK = 1, + SRP_ORDERED_TASK = 2, + SRP_ACA_TASK = 4 +}; + +/* tmp - will replace with SCSI logging stuff */ +#define eprintk(fmt, args...) \ +do { \ + printk("%s(%d) " fmt, __FUNCTION__, __LINE__, ##args); \ +} while (0) +/* #define dprintk eprintk */ +#define dprintk(fmt, args...) + +static int srp_iu_pool_alloc(struct srp_queue *q, size_t max, + struct srp_buf **ring) +{ + int i; + struct iu_entry *iue; + + q->pool = kcalloc(max, sizeof(struct iu_entry *), GFP_KERNEL); + if (!q->pool) + return -ENOMEM; + q->items = kcalloc(max, sizeof(struct iu_entry), GFP_KERNEL); + if (!q->items) + goto free_pool; + + spin_lock_init(&q->lock); + q->queue = kfifo_init((void *) q->pool, max * sizeof(void *), + GFP_KERNEL, &q->lock); + if (IS_ERR(q->queue)) + goto free_item; + + for (i = 0, iue = q->items; i < max; i++) { + __kfifo_put(q->queue, (void *) &iue, sizeof(void *)); + iue->sbuf = ring[i]; + iue++; + } + return 0; + +free_item: + kfree(q->items); +free_pool: + kfree(q->pool); + return -ENOMEM; +} + +static void srp_iu_pool_free(struct srp_queue *q) +{ + kfree(q->items); + kfree(q->pool); +} + +static struct srp_buf **srp_ring_alloc(struct device *dev, + size_t max, size_t size) +{ + int i; + struct srp_buf **ring; + + ring = kcalloc(max, sizeof(struct srp_buf *), GFP_KERNEL); + if (!ring) + return NULL; + + for (i = 0; i < max; i++) { + ring[i] = kzalloc(sizeof(struct srp_buf), GFP_KERNEL); + if (!ring[i]) + goto out; + ring[i]->buf = dma_alloc_coherent(dev, size, &ring[i]->dma, + GFP_KERNEL); + if (!ring[i]->buf) + goto out; + } + return ring; + +out: + for (i = 0; i < max && ring[i]; i++) { + if (ring[i]->buf) + dma_free_coherent(dev, size, ring[i]->buf, ring[i]->dma); + kfree(ring[i]); + } + kfree(ring); + + return NULL; +} + +static void srp_ring_free(struct device *dev, struct srp_buf **ring, size_t max, + size_t size) +{ + int i; + + for (i = 0; i < max; i++) { + dma_free_coherent(dev, size, ring[i]->buf, ring[i]->dma); + kfree(ring[i]); + } +} + +int srp_target_alloc(struct srp_target *target, struct device *dev, + size_t nr, size_t iu_size) +{ + int err; + + spin_lock_init(&target->lock); + INIT_LIST_HEAD(&target->cmd_queue); + + target->dev = dev; + target->dev->driver_data = target; + + target->srp_iu_size = iu_size; + target->rx_ring_size = nr; + target->rx_ring = srp_ring_alloc(target->dev, nr, iu_size); + if (!target->rx_ring) + return -ENOMEM; + err = srp_iu_pool_alloc(&target->iu_queue, nr, target->rx_ring); + if (err) + goto free_ring; + + return 0; + +free_ring: + srp_ring_free(target->dev, target->rx_ring, nr, iu_size); + return -ENOMEM; +} +EXPORT_SYMBOL_GPL(srp_target_alloc); + +void srp_target_free(struct srp_target *target) +{ + srp_ring_free(target->dev, target->rx_ring, target->rx_ring_size, + target->srp_iu_size); + srp_iu_pool_free(&target->iu_queue); +} +EXPORT_SYMBOL_GPL(srp_target_free); + +struct iu_entry *srp_iu_get(struct srp_target *target) +{ + struct iu_entry *iue = NULL; + + kfifo_get(target->iu_queue.queue, (void *) &iue, sizeof(void *)); + if (!iue) + return iue; + iue->target = target; + INIT_LIST_HEAD(&iue->ilist); + iue->flags = 0; + return iue; +} +EXPORT_SYMBOL_GPL(srp_iu_get); + +void srp_iu_put(struct iu_entry *iue) +{ + kfifo_put(iue->target->iu_queue.queue, (void *) &iue, sizeof(void *)); +} +EXPORT_SYMBOL_GPL(srp_iu_put); + +static int srp_direct_data(struct scsi_cmnd *sc, struct srp_direct_buf *md, + enum dma_data_direction dir, srp_rdma_t rdma_io, + int dma_map, int ext_desc) +{ + struct iu_entry *iue = NULL; + struct scatterlist *sg = NULL; + int err, nsg = 0, len; + + if (dma_map) { + iue = (struct iu_entry *) sc->SCp.ptr; + sg = sc->request_buffer; + + dprintk("%p %u %u %d\n", iue, sc->request_bufflen, + md->len, sc->use_sg); + + nsg = dma_map_sg(iue->target->dev, sg, sc->use_sg, + DMA_BIDIRECTIONAL); + if (!nsg) { + printk("fail to map %p %d\n", iue, sc->use_sg); + return 0; + } + len = min(sc->request_bufflen, md->len); + } else + len = md->len; + + err = rdma_io(sc, sg, nsg, md, 1, dir, len); + + if (dma_map) + dma_unmap_sg(iue->target->dev, sg, nsg, DMA_BIDIRECTIONAL); + + return err; +} + +static int srp_indirect_data(struct scsi_cmnd *sc, struct srp_cmd *cmd, + struct srp_indirect_buf *id, + enum dma_data_direction dir, srp_rdma_t rdma_io, + int dma_map, int ext_desc) +{ + struct iu_entry *iue = NULL; + struct srp_direct_buf *md = NULL; + struct scatterlist dummy, *sg = NULL; + dma_addr_t token = 0; + long err; + unsigned int done = 0; + int nmd, nsg = 0, len; + + if (dma_map || ext_desc) { + iue = (struct iu_entry *) sc->SCp.ptr; + sg = sc->request_buffer; + + dprintk("%p %u %u %d %d\n", + iue, sc->request_bufflen, id->len, + cmd->data_in_desc_cnt, cmd->data_out_desc_cnt); + } + + nmd = id->table_desc.len / sizeof(struct srp_direct_buf); + + if ((dir == DMA_FROM_DEVICE && nmd == cmd->data_in_desc_cnt) || + (dir == DMA_TO_DEVICE && nmd == cmd->data_out_desc_cnt)) { + md = &id->desc_list[0]; + goto rdma; + } + + if (ext_desc && dma_map) { + md = dma_alloc_coherent(iue->target->dev, id->table_desc.len, + &token, GFP_KERNEL); + if (!md) { + eprintk("Can't get dma memory %u\n", id->table_desc.len); + return -ENOMEM; + } + + sg_init_one(&dummy, md, id->table_desc.len); + sg_dma_address(&dummy) = token; + err = rdma_io(sc, &dummy, 1, &id->table_desc, 1, DMA_TO_DEVICE, + id->table_desc.len); + if (err < 0) { + eprintk("Error copying indirect table %ld\n", err); + goto free_mem; + } + } else { + eprintk("This command uses external indirect buffer\n"); + return -EINVAL; + } + +rdma: + if (dma_map) { + nsg = dma_map_sg(iue->target->dev, sg, sc->use_sg, DMA_BIDIRECTIONAL); + if (!nsg) { + eprintk("fail to map %p %d\n", iue, sc->use_sg); + goto free_mem; + } + len = min(sc->request_bufflen, id->len); + } else + len = id->len; + + err = rdma_io(sc, sg, nsg, md, nmd, dir, len); + + if (dma_map) + dma_unmap_sg(iue->target->dev, sg, nsg, DMA_BIDIRECTIONAL); + +free_mem: + if (token && dma_map) + dma_free_coherent(iue->target->dev, id->table_desc.len, md, token); + + return done; +} + +static int data_out_desc_size(struct srp_cmd *cmd) +{ + int size = 0; + u8 fmt = cmd->buf_fmt >> 4; + + switch (fmt) { + case SRP_NO_DATA_DESC: + break; + case SRP_DATA_DESC_DIRECT: + size = sizeof(struct srp_direct_buf); + break; + case SRP_DATA_DESC_INDIRECT: + size = sizeof(struct srp_indirect_buf) + + sizeof(struct srp_direct_buf) * cmd->data_out_desc_cnt; + break; + default: + eprintk("client error. Invalid data_out_format %x\n", fmt); + break; + } + return size; +} + +/* + * TODO: this can be called multiple times for a single command if it + * has very long data. + */ +int srp_transfer_data(struct scsi_cmnd *sc, struct srp_cmd *cmd, + srp_rdma_t rdma_io, int dma_map, int ext_desc) +{ + struct srp_direct_buf *md; + struct srp_indirect_buf *id; + enum dma_data_direction dir; + int offset, err = 0; + u8 format; + + offset = cmd->add_cdb_len * 4; + + dir = srp_cmd_direction(cmd); + if (dir == DMA_FROM_DEVICE) + offset += data_out_desc_size(cmd); + + if (dir == DMA_TO_DEVICE) + format = cmd->buf_fmt >> 4; + else + format = cmd->buf_fmt & ((1U << 4) - 1); + + switch (format) { + case SRP_NO_DATA_DESC: + break; + case SRP_DATA_DESC_DIRECT: + md = (struct srp_direct_buf *) + (cmd->add_data + offset); + err = srp_direct_data(sc, md, dir, rdma_io, dma_map, ext_desc); + break; + case SRP_DATA_DESC_INDIRECT: + id = (struct srp_indirect_buf *) + (cmd->add_data + offset); + err = srp_indirect_data(sc, cmd, id, dir, rdma_io, dma_map, + ext_desc); + break; + default: + eprintk("Unknown format %d %x\n", dir, format); + break; + } + + return err; +} +EXPORT_SYMBOL_GPL(srp_transfer_data); + +static int vscsis_data_length(struct srp_cmd *cmd, enum dma_data_direction dir) +{ + struct srp_direct_buf *md; + struct srp_indirect_buf *id; + int len = 0, offset = cmd->add_cdb_len * 4; + u8 fmt; + + if (dir == DMA_TO_DEVICE) + fmt = cmd->buf_fmt >> 4; + else { + fmt = cmd->buf_fmt & ((1U << 4) - 1); + offset += data_out_desc_size(cmd); + } + + switch (fmt) { + case SRP_NO_DATA_DESC: + break; + case SRP_DATA_DESC_DIRECT: + md = (struct srp_direct_buf *) (cmd->add_data + offset); + len = md->len; + break; + case SRP_DATA_DESC_INDIRECT: + id = (struct srp_indirect_buf *) (cmd->add_data + offset); + len = id->len; + break; + default: + eprintk("invalid data format %x\n", fmt); + break; + } + return len; +} + +int srp_cmd_queue(struct Scsi_Host *shost, struct srp_cmd *cmd, void *info, + u64 addr) +{ + enum dma_data_direction dir; + struct scsi_cmnd *sc; + int tag, len, err; + + switch (cmd->task_attr) { + case SRP_SIMPLE_TASK: + tag = MSG_SIMPLE_TAG; + break; + case SRP_ORDERED_TASK: + tag = MSG_ORDERED_TAG; + break; + case SRP_HEAD_TASK: + tag = MSG_HEAD_TAG; + break; + default: + eprintk("Task attribute %d not supported\n", cmd->task_attr); + tag = MSG_ORDERED_TAG; + } + + dir = srp_cmd_direction(cmd); + len = vscsis_data_length(cmd, dir); + + dprintk("%p %x %lx %d %d %d %llx\n", info, cmd->cdb[0], + cmd->lun, dir, len, tag, (unsigned long long) cmd->tag); + + sc = scsi_host_get_command(shost, dir, GFP_KERNEL); + if (!sc) + return -ENOMEM; + + sc->SCp.ptr = info; + memcpy(sc->cmnd, cmd->cdb, MAX_COMMAND_SIZE); + sc->request_bufflen = len; + sc->request_buffer = (void *) (unsigned long) addr; + sc->tag = tag; + err = scsi_tgt_queue_command(sc, (struct scsi_lun *) &cmd->lun, cmd->tag); + if (err) + scsi_host_put_command(shost, sc); + + return err; +} +EXPORT_SYMBOL_GPL(srp_cmd_queue); + +MODULE_DESCRIPTION("SCSI RDAM Protocol lib functions"); +MODULE_AUTHOR("FUJITA Tomonori"); +MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/scsi/lpfc/lpfc.h b/trunk/drivers/scsi/lpfc/lpfc.h index 3f7f5f8abd75..a7de0bca5bdd 100644 --- a/trunk/drivers/scsi/lpfc/lpfc.h +++ b/trunk/drivers/scsi/lpfc/lpfc.h @@ -296,13 +296,17 @@ struct lpfc_hba { uint32_t cfg_cr_delay; uint32_t cfg_cr_count; uint32_t cfg_multi_ring_support; + uint32_t cfg_multi_ring_rctl; + uint32_t cfg_multi_ring_type; uint32_t cfg_fdmi_on; uint32_t cfg_discovery_threads; uint32_t cfg_max_luns; uint32_t cfg_poll; uint32_t cfg_poll_tmo; + uint32_t cfg_use_msi; uint32_t cfg_sg_seg_cnt; uint32_t cfg_sg_dma_buf_size; + uint64_t cfg_soft_wwnn; uint64_t cfg_soft_wwpn; uint32_t dev_loss_tmo_changed; @@ -355,7 +359,7 @@ struct lpfc_hba { #define VPD_PORT 0x8 /* valid vpd port data */ #define VPD_MASK 0xf /* mask for any vpd data */ - uint8_t soft_wwpn_enable; + uint8_t soft_wwn_enable; struct timer_list fcp_poll_timer; struct timer_list els_tmofunc; diff --git a/trunk/drivers/scsi/lpfc/lpfc_attr.c b/trunk/drivers/scsi/lpfc/lpfc_attr.c index 2a4e02e7a392..f247e786af99 100644 --- a/trunk/drivers/scsi/lpfc/lpfc_attr.c +++ b/trunk/drivers/scsi/lpfc/lpfc_attr.c @@ -552,10 +552,10 @@ static CLASS_DEVICE_ATTR(board_mode, S_IRUGO | S_IWUSR, static CLASS_DEVICE_ATTR(issue_reset, S_IWUSR, NULL, lpfc_issue_reset); -static char *lpfc_soft_wwpn_key = "C99G71SL8032A"; +static char *lpfc_soft_wwn_key = "C99G71SL8032A"; static ssize_t -lpfc_soft_wwpn_enable_store(struct class_device *cdev, const char *buf, +lpfc_soft_wwn_enable_store(struct class_device *cdev, const char *buf, size_t count) { struct Scsi_Host *host = class_to_shost(cdev); @@ -579,15 +579,15 @@ lpfc_soft_wwpn_enable_store(struct class_device *cdev, const char *buf, if (buf[cnt-1] == '\n') cnt--; - if ((cnt != strlen(lpfc_soft_wwpn_key)) || - (strncmp(buf, lpfc_soft_wwpn_key, strlen(lpfc_soft_wwpn_key)) != 0)) + if ((cnt != strlen(lpfc_soft_wwn_key)) || + (strncmp(buf, lpfc_soft_wwn_key, strlen(lpfc_soft_wwn_key)) != 0)) return -EINVAL; - phba->soft_wwpn_enable = 1; + phba->soft_wwn_enable = 1; return count; } -static CLASS_DEVICE_ATTR(lpfc_soft_wwpn_enable, S_IWUSR, NULL, - lpfc_soft_wwpn_enable_store); +static CLASS_DEVICE_ATTR(lpfc_soft_wwn_enable, S_IWUSR, NULL, + lpfc_soft_wwn_enable_store); static ssize_t lpfc_soft_wwpn_show(struct class_device *cdev, char *buf) @@ -613,12 +613,12 @@ lpfc_soft_wwpn_store(struct class_device *cdev, const char *buf, size_t count) if (buf[cnt-1] == '\n') cnt--; - if (!phba->soft_wwpn_enable || (cnt < 16) || (cnt > 18) || + if (!phba->soft_wwn_enable || (cnt < 16) || (cnt > 18) || ((cnt == 17) && (*buf++ != 'x')) || ((cnt == 18) && ((*buf++ != '0') || (*buf++ != 'x')))) return -EINVAL; - phba->soft_wwpn_enable = 0; + phba->soft_wwn_enable = 0; memset(wwpn, 0, sizeof(wwpn)); @@ -639,6 +639,8 @@ lpfc_soft_wwpn_store(struct class_device *cdev, const char *buf, size_t count) } phba->cfg_soft_wwpn = wwn_to_u64(wwpn); fc_host_port_name(host) = phba->cfg_soft_wwpn; + if (phba->cfg_soft_wwnn) + fc_host_node_name(host) = phba->cfg_soft_wwnn; dev_printk(KERN_NOTICE, &phba->pcidev->dev, "lpfc%d: Reinitializing to use soft_wwpn\n", phba->brd_no); @@ -664,6 +666,66 @@ lpfc_soft_wwpn_store(struct class_device *cdev, const char *buf, size_t count) static CLASS_DEVICE_ATTR(lpfc_soft_wwpn, S_IRUGO | S_IWUSR,\ lpfc_soft_wwpn_show, lpfc_soft_wwpn_store); +static ssize_t +lpfc_soft_wwnn_show(struct class_device *cdev, char *buf) +{ + struct Scsi_Host *host = class_to_shost(cdev); + struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata; + return snprintf(buf, PAGE_SIZE, "0x%llx\n", + (unsigned long long)phba->cfg_soft_wwnn); +} + + +static ssize_t +lpfc_soft_wwnn_store(struct class_device *cdev, const char *buf, size_t count) +{ + struct Scsi_Host *host = class_to_shost(cdev); + struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata; + unsigned int i, j, cnt=count; + u8 wwnn[8]; + + /* count may include a LF at end of string */ + if (buf[cnt-1] == '\n') + cnt--; + + if (!phba->soft_wwn_enable || (cnt < 16) || (cnt > 18) || + ((cnt == 17) && (*buf++ != 'x')) || + ((cnt == 18) && ((*buf++ != '0') || (*buf++ != 'x')))) + return -EINVAL; + + /* + * Allow wwnn to be set many times, as long as the enable is set. + * However, once the wwpn is set, everything locks. + */ + + memset(wwnn, 0, sizeof(wwnn)); + + /* Validate and store the new name */ + for (i=0, j=0; i < 16; i++) { + if ((*buf >= 'a') && (*buf <= 'f')) + j = ((j << 4) | ((*buf++ -'a') + 10)); + else if ((*buf >= 'A') && (*buf <= 'F')) + j = ((j << 4) | ((*buf++ -'A') + 10)); + else if ((*buf >= '0') && (*buf <= '9')) + j = ((j << 4) | (*buf++ -'0')); + else + return -EINVAL; + if (i % 2) { + wwnn[i/2] = j & 0xff; + j = 0; + } + } + phba->cfg_soft_wwnn = wwn_to_u64(wwnn); + + dev_printk(KERN_NOTICE, &phba->pcidev->dev, + "lpfc%d: soft_wwnn set. Value will take effect upon " + "setting of the soft_wwpn\n", phba->brd_no); + + return count; +} +static CLASS_DEVICE_ATTR(lpfc_soft_wwnn, S_IRUGO | S_IWUSR,\ + lpfc_soft_wwnn_show, lpfc_soft_wwnn_store); + static int lpfc_poll = 0; module_param(lpfc_poll, int, 0); @@ -802,12 +864,11 @@ static CLASS_DEVICE_ATTR(lpfc_devloss_tmo, S_IRUGO | S_IWUSR, # LOG_MBOX 0x4 Mailbox events # LOG_INIT 0x8 Initialization events # LOG_LINK_EVENT 0x10 Link events -# LOG_IP 0x20 IP traffic history # LOG_FCP 0x40 FCP traffic history # LOG_NODE 0x80 Node table events # LOG_MISC 0x400 Miscellaneous events # LOG_SLI 0x800 SLI events -# LOG_CHK_COND 0x1000 FCP Check condition flag +# LOG_FCP_ERROR 0x1000 Only log FCP errors # LOG_LIBDFC 0x2000 LIBDFC events # LOG_ALL_MSG 0xffff LOG all messages */ @@ -915,6 +976,22 @@ LPFC_ATTR_RW(cr_count, 1, 1, 255, "A count of I/O completions after which an " LPFC_ATTR_R(multi_ring_support, 1, 1, 2, "Determines number of primary " "SLI rings to spread IOCB entries across"); +/* +# lpfc_multi_ring_rctl: If lpfc_multi_ring_support is enabled, this +# identifies what rctl value to configure the additional ring for. +# Value range is [1,0xff]. Default value is 4 (Unsolicated Data). +*/ +LPFC_ATTR_R(multi_ring_rctl, FC_UNSOL_DATA, 1, + 255, "Identifies RCTL for additional ring configuration"); + +/* +# lpfc_multi_ring_type: If lpfc_multi_ring_support is enabled, this +# identifies what type value to configure the additional ring for. +# Value range is [1,0xff]. Default value is 5 (LLC/SNAP). +*/ +LPFC_ATTR_R(multi_ring_type, FC_LLC_SNAP, 1, + 255, "Identifies TYPE for additional ring configuration"); + /* # lpfc_fdmi_on: controls FDMI support. # 0 = no FDMI support @@ -946,6 +1023,15 @@ LPFC_ATTR_R(max_luns, 255, 0, 65535, LPFC_ATTR_RW(poll_tmo, 10, 1, 255, "Milliseconds driver will wait between polling FCP ring"); +/* +# lpfc_use_msi: Use MSI (Message Signaled Interrupts) in systems that +# support this feature +# 0 = MSI disabled (default) +# 1 = MSI enabled +# Value range is [0,1]. Default value is 0. +*/ +LPFC_ATTR_R(use_msi, 0, 0, 1, "Use Message Signaled Interrupts, if possible"); + struct class_device_attribute *lpfc_host_attrs[] = { &class_device_attr_info, @@ -974,6 +1060,8 @@ struct class_device_attribute *lpfc_host_attrs[] = { &class_device_attr_lpfc_cr_delay, &class_device_attr_lpfc_cr_count, &class_device_attr_lpfc_multi_ring_support, + &class_device_attr_lpfc_multi_ring_rctl, + &class_device_attr_lpfc_multi_ring_type, &class_device_attr_lpfc_fdmi_on, &class_device_attr_lpfc_max_luns, &class_device_attr_nport_evt_cnt, @@ -982,8 +1070,10 @@ struct class_device_attribute *lpfc_host_attrs[] = { &class_device_attr_issue_reset, &class_device_attr_lpfc_poll, &class_device_attr_lpfc_poll_tmo, + &class_device_attr_lpfc_use_msi, + &class_device_attr_lpfc_soft_wwnn, &class_device_attr_lpfc_soft_wwpn, - &class_device_attr_lpfc_soft_wwpn_enable, + &class_device_attr_lpfc_soft_wwn_enable, NULL, }; @@ -1771,6 +1861,8 @@ lpfc_get_cfgparam(struct lpfc_hba *phba) lpfc_cr_delay_init(phba, lpfc_cr_delay); lpfc_cr_count_init(phba, lpfc_cr_count); lpfc_multi_ring_support_init(phba, lpfc_multi_ring_support); + lpfc_multi_ring_rctl_init(phba, lpfc_multi_ring_rctl); + lpfc_multi_ring_type_init(phba, lpfc_multi_ring_type); lpfc_lun_queue_depth_init(phba, lpfc_lun_queue_depth); lpfc_fcp_class_init(phba, lpfc_fcp_class); lpfc_use_adisc_init(phba, lpfc_use_adisc); @@ -1782,9 +1874,11 @@ lpfc_get_cfgparam(struct lpfc_hba *phba) lpfc_discovery_threads_init(phba, lpfc_discovery_threads); lpfc_max_luns_init(phba, lpfc_max_luns); lpfc_poll_tmo_init(phba, lpfc_poll_tmo); + lpfc_use_msi_init(phba, lpfc_use_msi); lpfc_devloss_tmo_init(phba, lpfc_devloss_tmo); lpfc_nodev_tmo_init(phba, lpfc_nodev_tmo); phba->cfg_poll = lpfc_poll; + phba->cfg_soft_wwnn = 0L; phba->cfg_soft_wwpn = 0L; /* diff --git a/trunk/drivers/scsi/lpfc/lpfc_ct.c b/trunk/drivers/scsi/lpfc/lpfc_ct.c index 3add7c237859..a51a41b7f15d 100644 --- a/trunk/drivers/scsi/lpfc/lpfc_ct.c +++ b/trunk/drivers/scsi/lpfc/lpfc_ct.c @@ -558,6 +558,14 @@ lpfc_cmpl_ct_cmd_rsnn_nn(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, return; } +static void +lpfc_cmpl_ct_cmd_rff_id(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, + struct lpfc_iocbq * rspiocb) +{ + lpfc_cmpl_ct_cmd_rft_id(phba, cmdiocb, rspiocb); + return; +} + void lpfc_get_hba_sym_node_name(struct lpfc_hba * phba, uint8_t * symbp) { @@ -629,6 +637,8 @@ lpfc_ns_cmd(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, int cmdcode) bpl->tus.f.bdeSize = RNN_REQUEST_SZ; else if (cmdcode == SLI_CTNS_RSNN_NN) bpl->tus.f.bdeSize = RSNN_REQUEST_SZ; + else if (cmdcode == SLI_CTNS_RFF_ID) + bpl->tus.f.bdeSize = RFF_REQUEST_SZ; else bpl->tus.f.bdeSize = 0; bpl->tus.w = le32_to_cpu(bpl->tus.w); @@ -660,6 +670,17 @@ lpfc_ns_cmd(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, int cmdcode) cmpl = lpfc_cmpl_ct_cmd_rft_id; break; + case SLI_CTNS_RFF_ID: + CtReq->CommandResponse.bits.CmdRsp = + be16_to_cpu(SLI_CTNS_RFF_ID); + CtReq->un.rff.PortId = be32_to_cpu(phba->fc_myDID); + CtReq->un.rff.feature_res = 0; + CtReq->un.rff.feature_tgt = 0; + CtReq->un.rff.type_code = FC_FCP_DATA; + CtReq->un.rff.feature_init = 1; + cmpl = lpfc_cmpl_ct_cmd_rff_id; + break; + case SLI_CTNS_RNN_ID: CtReq->CommandResponse.bits.CmdRsp = be16_to_cpu(SLI_CTNS_RNN_ID); @@ -934,7 +955,8 @@ lpfc_fdmi_cmd(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, int cmdcode) ae = (ATTRIBUTE_ENTRY *) ((uint8_t *) rh + size); ae->ad.bits.AttrType = be16_to_cpu(OS_NAME_VERSION); sprintf(ae->un.OsNameVersion, "%s %s %s", - init_utsname()->sysname, init_utsname()->release, + init_utsname()->sysname, + init_utsname()->release, init_utsname()->version); len = strlen(ae->un.OsNameVersion); len += (len & 3) ? (4 - (len & 3)) : 4; diff --git a/trunk/drivers/scsi/lpfc/lpfc_els.c b/trunk/drivers/scsi/lpfc/lpfc_els.c index 71864cdc6c71..a5f33a0dd4e7 100644 --- a/trunk/drivers/scsi/lpfc/lpfc_els.c +++ b/trunk/drivers/scsi/lpfc/lpfc_els.c @@ -243,6 +243,7 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, struct serv_parm *sp, IOCB_t *irsp) { LPFC_MBOXQ_t *mbox; + struct lpfc_dmabuf *mp; int rc; spin_lock_irq(phba->host->host_lock); @@ -307,10 +308,14 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT | MBX_STOP_IOCB); if (rc == MBX_NOT_FINISHED) - goto fail_free_mbox; + goto fail_issue_reg_login; return 0; + fail_issue_reg_login: + mp = (struct lpfc_dmabuf *) mbox->context1; + lpfc_mbuf_free(phba, mp->virt, mp->phys); + kfree(mp); fail_free_mbox: mempool_free(mbox, phba->mbox_mem_pool); fail: @@ -657,6 +662,12 @@ lpfc_plogi_confirm_nport(struct lpfc_hba * phba, struct lpfc_dmabuf *prsp, uint8_t name[sizeof (struct lpfc_name)]; uint32_t rc; + /* Fabric nodes can have the same WWPN so we don't bother searching + * by WWPN. Just return the ndlp that was given to us. + */ + if (ndlp->nlp_type & NLP_FABRIC) + return ndlp; + lp = (uint32_t *) prsp->virt; sp = (struct serv_parm *) ((uint8_t *) lp + sizeof (uint32_t)); memset(name, 0, sizeof (struct lpfc_name)); @@ -1122,7 +1133,7 @@ lpfc_cmpl_els_adisc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, mempool_free(mbox, phba->mbox_mem_pool); lpfc_disc_flush_list(phba); - psli->ring[(psli->ip_ring)]. + psli->ring[(psli->extra_ring)]. flag &= ~LPFC_STOP_IOCB_EVENT; psli->ring[(psli->fcp_ring)]. @@ -1851,6 +1862,7 @@ lpfc_cmpl_els_acc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, IOCB_t *irsp; struct lpfc_nodelist *ndlp; LPFC_MBOXQ_t *mbox = NULL; + struct lpfc_dmabuf *mp; irsp = &rspiocb->iocb; @@ -1862,6 +1874,11 @@ lpfc_cmpl_els_acc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, /* Check to see if link went down during discovery */ if ((lpfc_els_chk_latt(phba)) || !ndlp) { if (mbox) { + mp = (struct lpfc_dmabuf *) mbox->context1; + if (mp) { + lpfc_mbuf_free(phba, mp->virt, mp->phys); + kfree(mp); + } mempool_free( mbox, phba->mbox_mem_pool); } goto out; @@ -1893,9 +1910,7 @@ lpfc_cmpl_els_acc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, } /* NOTE: we should have messages for unsuccessful reglogin */ - mempool_free( mbox, phba->mbox_mem_pool); } else { - mempool_free( mbox, phba->mbox_mem_pool); /* Do not call NO_LIST for lpfc_els_abort'ed ELS cmds */ if (!((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) && ((irsp->un.ulpWord[4] == IOERR_SLI_ABORTED) || @@ -1907,6 +1922,12 @@ lpfc_cmpl_els_acc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, } } } + mp = (struct lpfc_dmabuf *) mbox->context1; + if (mp) { + lpfc_mbuf_free(phba, mp->virt, mp->phys); + kfree(mp); + } + mempool_free(mbox, phba->mbox_mem_pool); } out: if (ndlp) { @@ -2644,6 +2665,7 @@ lpfc_els_handle_rscn(struct lpfc_hba * phba) ndlp->nlp_type |= NLP_FABRIC; ndlp->nlp_prev_state = ndlp->nlp_state; ndlp->nlp_state = NLP_STE_PLOGI_ISSUE; + lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST); lpfc_issue_els_plogi(phba, NameServer_DID, 0); /* Wait for NameServer login cmpl before we can continue */ @@ -3039,7 +3061,7 @@ lpfc_els_rcv_farp(struct lpfc_hba * phba, /* FARP-REQ received from DID */ lpfc_printf_log(phba, KERN_INFO, - LOG_IP, + LOG_ELS, "%d:0601 FARP-REQ received from DID x%x\n", phba->brd_no, did); @@ -3101,7 +3123,7 @@ lpfc_els_rcv_farpr(struct lpfc_hba * phba, /* FARP-RSP received from DID */ lpfc_printf_log(phba, KERN_INFO, - LOG_IP, + LOG_ELS, "%d:0600 FARP-RSP received from DID x%x\n", phba->brd_no, did); diff --git a/trunk/drivers/scsi/lpfc/lpfc_hbadisc.c b/trunk/drivers/scsi/lpfc/lpfc_hbadisc.c index 19c79a0549a7..c39564e85e94 100644 --- a/trunk/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/trunk/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -525,7 +525,7 @@ lpfc_mbx_cmpl_clear_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) psli = &phba->sli; mb = &pmb->mb; /* Since we don't do discovery right now, turn these off here */ - psli->ring[psli->ip_ring].flag &= ~LPFC_STOP_IOCB_EVENT; + psli->ring[psli->extra_ring].flag &= ~LPFC_STOP_IOCB_EVENT; psli->ring[psli->fcp_ring].flag &= ~LPFC_STOP_IOCB_EVENT; psli->ring[psli->next_ring].flag &= ~LPFC_STOP_IOCB_EVENT; @@ -641,7 +641,7 @@ lpfc_mbx_cmpl_local_config_link(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) if (rc == MBX_NOT_FINISHED) { mempool_free(pmb, phba->mbox_mem_pool); lpfc_disc_flush_list(phba); - psli->ring[(psli->ip_ring)].flag &= ~LPFC_STOP_IOCB_EVENT; + psli->ring[(psli->extra_ring)].flag &= ~LPFC_STOP_IOCB_EVENT; psli->ring[(psli->fcp_ring)].flag &= ~LPFC_STOP_IOCB_EVENT; psli->ring[(psli->next_ring)].flag &= ~LPFC_STOP_IOCB_EVENT; phba->hba_state = LPFC_HBA_READY; @@ -672,6 +672,8 @@ lpfc_mbx_cmpl_read_sparam(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) memcpy((uint8_t *) & phba->fc_sparam, (uint8_t *) mp->virt, sizeof (struct serv_parm)); + if (phba->cfg_soft_wwnn) + u64_to_wwn(phba->cfg_soft_wwnn, phba->fc_sparam.nodeName.u.wwn); if (phba->cfg_soft_wwpn) u64_to_wwn(phba->cfg_soft_wwpn, phba->fc_sparam.portName.u.wwn); memcpy((uint8_t *) & phba->fc_nodename, @@ -696,7 +698,7 @@ lpfc_mbx_cmpl_read_sparam(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) == MBX_NOT_FINISHED) { mempool_free( pmb, phba->mbox_mem_pool); lpfc_disc_flush_list(phba); - psli->ring[(psli->ip_ring)].flag &= + psli->ring[(psli->extra_ring)].flag &= ~LPFC_STOP_IOCB_EVENT; psli->ring[(psli->fcp_ring)].flag &= ~LPFC_STOP_IOCB_EVENT; @@ -715,6 +717,9 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, READ_LA_VAR *la) { int i; LPFC_MBOXQ_t *sparam_mbox, *cfglink_mbox; + struct lpfc_dmabuf *mp; + int rc; + sparam_mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); cfglink_mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); @@ -793,16 +798,27 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, READ_LA_VAR *la) if (sparam_mbox) { lpfc_read_sparam(phba, sparam_mbox); sparam_mbox->mbox_cmpl = lpfc_mbx_cmpl_read_sparam; - lpfc_sli_issue_mbox(phba, sparam_mbox, + rc = lpfc_sli_issue_mbox(phba, sparam_mbox, (MBX_NOWAIT | MBX_STOP_IOCB)); + if (rc == MBX_NOT_FINISHED) { + mp = (struct lpfc_dmabuf *) sparam_mbox->context1; + lpfc_mbuf_free(phba, mp->virt, mp->phys); + kfree(mp); + mempool_free(sparam_mbox, phba->mbox_mem_pool); + if (cfglink_mbox) + mempool_free(cfglink_mbox, phba->mbox_mem_pool); + return; + } } if (cfglink_mbox) { phba->hba_state = LPFC_LOCAL_CFG_LINK; lpfc_config_link(phba, cfglink_mbox); cfglink_mbox->mbox_cmpl = lpfc_mbx_cmpl_local_config_link; - lpfc_sli_issue_mbox(phba, cfglink_mbox, + rc = lpfc_sli_issue_mbox(phba, cfglink_mbox, (MBX_NOWAIT | MBX_STOP_IOCB)); + if (rc == MBX_NOT_FINISHED) + mempool_free(cfglink_mbox, phba->mbox_mem_pool); } } @@ -1067,6 +1083,7 @@ lpfc_mbx_cmpl_ns_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) lpfc_ns_cmd(phba, ndlp, SLI_CTNS_RNN_ID); lpfc_ns_cmd(phba, ndlp, SLI_CTNS_RSNN_NN); lpfc_ns_cmd(phba, ndlp, SLI_CTNS_RFT_ID); + lpfc_ns_cmd(phba, ndlp, SLI_CTNS_RFF_ID); } phba->fc_ns_retry = 0; @@ -1423,7 +1440,7 @@ lpfc_check_sli_ndlp(struct lpfc_hba * phba, if (iocb->context1 == (uint8_t *) ndlp) return 1; } - } else if (pring->ringno == psli->ip_ring) { + } else if (pring->ringno == psli->extra_ring) { } else if (pring->ringno == psli->fcp_ring) { /* Skip match check if waiting to relogin to FCP target */ @@ -1680,112 +1697,38 @@ lpfc_matchdid(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, uint32_t did) struct lpfc_nodelist * lpfc_findnode_did(struct lpfc_hba * phba, uint32_t order, uint32_t did) { - struct lpfc_nodelist *ndlp, *next_ndlp; + struct lpfc_nodelist *ndlp; + struct list_head *lists[]={&phba->fc_nlpunmap_list, + &phba->fc_nlpmap_list, + &phba->fc_plogi_list, + &phba->fc_adisc_list, + &phba->fc_reglogin_list, + &phba->fc_prli_list, + &phba->fc_npr_list, + &phba->fc_unused_list}; + uint32_t search[]={NLP_SEARCH_UNMAPPED, + NLP_SEARCH_MAPPED, + NLP_SEARCH_PLOGI, + NLP_SEARCH_ADISC, + NLP_SEARCH_REGLOGIN, + NLP_SEARCH_PRLI, + NLP_SEARCH_NPR, + NLP_SEARCH_UNUSED}; + int i; uint32_t data1; spin_lock_irq(phba->host->host_lock); - if (order & NLP_SEARCH_UNMAPPED) { - list_for_each_entry_safe(ndlp, next_ndlp, - &phba->fc_nlpunmap_list, nlp_listp) { - if (lpfc_matchdid(phba, ndlp, did)) { - data1 = (((uint32_t) ndlp->nlp_state << 24) | - ((uint32_t) ndlp->nlp_xri << 16) | - ((uint32_t) ndlp->nlp_type << 8) | - ((uint32_t) ndlp->nlp_rpi & 0xff)); - /* FIND node DID unmapped */ - lpfc_printf_log(phba, KERN_INFO, LOG_NODE, - "%d:0929 FIND node DID unmapped" - " Data: x%p x%x x%x x%x\n", - phba->brd_no, - ndlp, ndlp->nlp_DID, - ndlp->nlp_flag, data1); - spin_unlock_irq(phba->host->host_lock); - return ndlp; - } - } - } - - if (order & NLP_SEARCH_MAPPED) { - list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nlpmap_list, - nlp_listp) { - if (lpfc_matchdid(phba, ndlp, did)) { - - data1 = (((uint32_t) ndlp->nlp_state << 24) | - ((uint32_t) ndlp->nlp_xri << 16) | - ((uint32_t) ndlp->nlp_type << 8) | - ((uint32_t) ndlp->nlp_rpi & 0xff)); - /* FIND node DID mapped */ - lpfc_printf_log(phba, KERN_INFO, LOG_NODE, - "%d:0930 FIND node DID mapped " - "Data: x%p x%x x%x x%x\n", - phba->brd_no, - ndlp, ndlp->nlp_DID, - ndlp->nlp_flag, data1); - spin_unlock_irq(phba->host->host_lock); - return ndlp; - } - } - } - - if (order & NLP_SEARCH_PLOGI) { - list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_plogi_list, - nlp_listp) { - if (lpfc_matchdid(phba, ndlp, did)) { - - data1 = (((uint32_t) ndlp->nlp_state << 24) | - ((uint32_t) ndlp->nlp_xri << 16) | - ((uint32_t) ndlp->nlp_type << 8) | - ((uint32_t) ndlp->nlp_rpi & 0xff)); - /* LOG change to PLOGI */ - /* FIND node DID plogi */ - lpfc_printf_log(phba, KERN_INFO, LOG_NODE, - "%d:0908 FIND node DID plogi " - "Data: x%p x%x x%x x%x\n", - phba->brd_no, - ndlp, ndlp->nlp_DID, - ndlp->nlp_flag, data1); - spin_unlock_irq(phba->host->host_lock); - return ndlp; - } - } - } - - if (order & NLP_SEARCH_ADISC) { - list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_adisc_list, - nlp_listp) { - if (lpfc_matchdid(phba, ndlp, did)) { - - data1 = (((uint32_t) ndlp->nlp_state << 24) | - ((uint32_t) ndlp->nlp_xri << 16) | - ((uint32_t) ndlp->nlp_type << 8) | - ((uint32_t) ndlp->nlp_rpi & 0xff)); - /* LOG change to ADISC */ - /* FIND node DID adisc */ - lpfc_printf_log(phba, KERN_INFO, LOG_NODE, - "%d:0931 FIND node DID adisc " - "Data: x%p x%x x%x x%x\n", - phba->brd_no, - ndlp, ndlp->nlp_DID, - ndlp->nlp_flag, data1); - spin_unlock_irq(phba->host->host_lock); - return ndlp; - } - } - } - - if (order & NLP_SEARCH_REGLOGIN) { - list_for_each_entry_safe(ndlp, next_ndlp, - &phba->fc_reglogin_list, nlp_listp) { + for (i = 0; i < ARRAY_SIZE(lists); i++ ) { + if (!(order & search[i])) + continue; + list_for_each_entry(ndlp, lists[i], nlp_listp) { if (lpfc_matchdid(phba, ndlp, did)) { - data1 = (((uint32_t) ndlp->nlp_state << 24) | ((uint32_t) ndlp->nlp_xri << 16) | ((uint32_t) ndlp->nlp_type << 8) | ((uint32_t) ndlp->nlp_rpi & 0xff)); - /* LOG change to REGLOGIN */ - /* FIND node DID reglogin */ lpfc_printf_log(phba, KERN_INFO, LOG_NODE, - "%d:0901 FIND node DID reglogin" + "%d:0929 FIND node DID " " Data: x%p x%x x%x x%x\n", phba->brd_no, ndlp, ndlp->nlp_DID, @@ -1795,86 +1738,12 @@ lpfc_findnode_did(struct lpfc_hba * phba, uint32_t order, uint32_t did) } } } - - if (order & NLP_SEARCH_PRLI) { - list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_prli_list, - nlp_listp) { - if (lpfc_matchdid(phba, ndlp, did)) { - - data1 = (((uint32_t) ndlp->nlp_state << 24) | - ((uint32_t) ndlp->nlp_xri << 16) | - ((uint32_t) ndlp->nlp_type << 8) | - ((uint32_t) ndlp->nlp_rpi & 0xff)); - /* LOG change to PRLI */ - /* FIND node DID prli */ - lpfc_printf_log(phba, KERN_INFO, LOG_NODE, - "%d:0902 FIND node DID prli " - "Data: x%p x%x x%x x%x\n", - phba->brd_no, - ndlp, ndlp->nlp_DID, - ndlp->nlp_flag, data1); - spin_unlock_irq(phba->host->host_lock); - return ndlp; - } - } - } - - if (order & NLP_SEARCH_NPR) { - list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_npr_list, - nlp_listp) { - if (lpfc_matchdid(phba, ndlp, did)) { - - data1 = (((uint32_t) ndlp->nlp_state << 24) | - ((uint32_t) ndlp->nlp_xri << 16) | - ((uint32_t) ndlp->nlp_type << 8) | - ((uint32_t) ndlp->nlp_rpi & 0xff)); - /* LOG change to NPR */ - /* FIND node DID npr */ - lpfc_printf_log(phba, KERN_INFO, LOG_NODE, - "%d:0903 FIND node DID npr " - "Data: x%p x%x x%x x%x\n", - phba->brd_no, - ndlp, ndlp->nlp_DID, - ndlp->nlp_flag, data1); - spin_unlock_irq(phba->host->host_lock); - return ndlp; - } - } - } - - if (order & NLP_SEARCH_UNUSED) { - list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_adisc_list, - nlp_listp) { - if (lpfc_matchdid(phba, ndlp, did)) { - - data1 = (((uint32_t) ndlp->nlp_state << 24) | - ((uint32_t) ndlp->nlp_xri << 16) | - ((uint32_t) ndlp->nlp_type << 8) | - ((uint32_t) ndlp->nlp_rpi & 0xff)); - /* LOG change to UNUSED */ - /* FIND node DID unused */ - lpfc_printf_log(phba, KERN_INFO, LOG_NODE, - "%d:0905 FIND node DID unused " - "Data: x%p x%x x%x x%x\n", - phba->brd_no, - ndlp, ndlp->nlp_DID, - ndlp->nlp_flag, data1); - spin_unlock_irq(phba->host->host_lock); - return ndlp; - } - } - } - spin_unlock_irq(phba->host->host_lock); /* FIND node did NOT FOUND */ - lpfc_printf_log(phba, - KERN_INFO, - LOG_NODE, + lpfc_printf_log(phba, KERN_INFO, LOG_NODE, "%d:0932 FIND node did x%x NOT FOUND Data: x%x\n", phba->brd_no, did, order); - - /* no match found */ return NULL; } @@ -2036,7 +1905,7 @@ lpfc_disc_start(struct lpfc_hba * phba) if (rc == MBX_NOT_FINISHED) { mempool_free( mbox, phba->mbox_mem_pool); lpfc_disc_flush_list(phba); - psli->ring[(psli->ip_ring)].flag &= + psli->ring[(psli->extra_ring)].flag &= ~LPFC_STOP_IOCB_EVENT; psli->ring[(psli->fcp_ring)].flag &= ~LPFC_STOP_IOCB_EVENT; @@ -2415,7 +2284,7 @@ lpfc_disc_timeout_handler(struct lpfc_hba *phba) if (clrlaerr) { lpfc_disc_flush_list(phba); - psli->ring[(psli->ip_ring)].flag &= ~LPFC_STOP_IOCB_EVENT; + psli->ring[(psli->extra_ring)].flag &= ~LPFC_STOP_IOCB_EVENT; psli->ring[(psli->fcp_ring)].flag &= ~LPFC_STOP_IOCB_EVENT; psli->ring[(psli->next_ring)].flag &= ~LPFC_STOP_IOCB_EVENT; phba->hba_state = LPFC_HBA_READY; diff --git a/trunk/drivers/scsi/lpfc/lpfc_hw.h b/trunk/drivers/scsi/lpfc/lpfc_hw.h index eedf98801366..f79cb6136906 100644 --- a/trunk/drivers/scsi/lpfc/lpfc_hw.h +++ b/trunk/drivers/scsi/lpfc/lpfc_hw.h @@ -42,14 +42,14 @@ #define FCELSSIZE 1024 /* maximum ELS transfer size */ #define LPFC_FCP_RING 0 /* ring 0 for FCP initiator commands */ -#define LPFC_IP_RING 1 /* ring 1 for IP commands */ +#define LPFC_EXTRA_RING 1 /* ring 1 for other protocols */ #define LPFC_ELS_RING 2 /* ring 2 for ELS commands */ #define LPFC_FCP_NEXT_RING 3 #define SLI2_IOCB_CMD_R0_ENTRIES 172 /* SLI-2 FCP command ring entries */ #define SLI2_IOCB_RSP_R0_ENTRIES 134 /* SLI-2 FCP response ring entries */ -#define SLI2_IOCB_CMD_R1_ENTRIES 4 /* SLI-2 IP command ring entries */ -#define SLI2_IOCB_RSP_R1_ENTRIES 4 /* SLI-2 IP response ring entries */ +#define SLI2_IOCB_CMD_R1_ENTRIES 4 /* SLI-2 extra command ring entries */ +#define SLI2_IOCB_RSP_R1_ENTRIES 4 /* SLI-2 extra response ring entries */ #define SLI2_IOCB_CMD_R1XTRA_ENTRIES 36 /* SLI-2 extra FCP cmd ring entries */ #define SLI2_IOCB_RSP_R1XTRA_ENTRIES 52 /* SLI-2 extra FCP rsp ring entries */ #define SLI2_IOCB_CMD_R2_ENTRIES 20 /* SLI-2 ELS command ring entries */ @@ -121,6 +121,20 @@ struct lpfc_sli_ct_request { uint32_t rsvd[7]; } rft; + struct rff { + uint32_t PortId; + uint8_t reserved[2]; +#ifdef __BIG_ENDIAN_BITFIELD + uint8_t feature_res:6; + uint8_t feature_init:1; + uint8_t feature_tgt:1; +#else /* __LITTLE_ENDIAN_BITFIELD */ + uint8_t feature_tgt:1; + uint8_t feature_init:1; + uint8_t feature_res:6; +#endif + uint8_t type_code; /* type=8 for FCP */ + } rff; struct rnn { uint32_t PortId; /* For RNN_ID requests */ uint8_t wwnn[8]; @@ -136,6 +150,7 @@ struct lpfc_sli_ct_request { #define SLI_CT_REVISION 1 #define GID_REQUEST_SZ (sizeof(struct lpfc_sli_ct_request) - 260) #define RFT_REQUEST_SZ (sizeof(struct lpfc_sli_ct_request) - 228) +#define RFF_REQUEST_SZ (sizeof(struct lpfc_sli_ct_request) - 235) #define RNN_REQUEST_SZ (sizeof(struct lpfc_sli_ct_request) - 252) #define RSNN_REQUEST_SZ (sizeof(struct lpfc_sli_ct_request)) @@ -225,6 +240,7 @@ struct lpfc_sli_ct_request { #define SLI_CTNS_RNN_ID 0x0213 #define SLI_CTNS_RCS_ID 0x0214 #define SLI_CTNS_RFT_ID 0x0217 +#define SLI_CTNS_RFF_ID 0x021F #define SLI_CTNS_RSPN_ID 0x0218 #define SLI_CTNS_RPT_ID 0x021A #define SLI_CTNS_RIP_NN 0x0235 @@ -1089,12 +1105,6 @@ typedef struct { #define PCI_DEVICE_ID_ZEPHYR_SCSP 0xfe11 #define PCI_DEVICE_ID_ZEPHYR_DCSP 0xfe12 -#define PCI_SUBSYSTEM_ID_LP11000S 0xfc11 -#define PCI_SUBSYSTEM_ID_LP11002S 0xfc12 -#define PCI_SUBSYSTEM_ID_LPE11000S 0xfc21 -#define PCI_SUBSYSTEM_ID_LPE11002S 0xfc22 -#define PCI_SUBSYSTEM_ID_LPE11010S 0xfc2A - #define JEDEC_ID_ADDRESS 0x0080001c #define FIREFLY_JEDEC_ID 0x1ACC #define SUPERFLY_JEDEC_ID 0x0020 @@ -1284,6 +1294,10 @@ typedef struct { /* FireFly BIU registers */ #define CMD_FCP_IREAD_CX 0x1B #define CMD_FCP_ICMND_CR 0x1C #define CMD_FCP_ICMND_CX 0x1D +#define CMD_FCP_TSEND_CX 0x1F +#define CMD_FCP_TRECEIVE_CX 0x21 +#define CMD_FCP_TRSP_CX 0x23 +#define CMD_FCP_AUTO_TRSP_CX 0x29 #define CMD_ADAPTER_MSG 0x20 #define CMD_ADAPTER_DUMP 0x22 @@ -1310,6 +1324,9 @@ typedef struct { /* FireFly BIU registers */ #define CMD_FCP_IREAD64_CX 0x9B #define CMD_FCP_ICMND64_CR 0x9C #define CMD_FCP_ICMND64_CX 0x9D +#define CMD_FCP_TSEND64_CX 0x9F +#define CMD_FCP_TRECEIVE64_CX 0xA1 +#define CMD_FCP_TRSP64_CX 0xA3 #define CMD_GEN_REQUEST64_CR 0xC2 #define CMD_GEN_REQUEST64_CX 0xC3 diff --git a/trunk/drivers/scsi/lpfc/lpfc_init.c b/trunk/drivers/scsi/lpfc/lpfc_init.c index a5723ad0a099..afca45cdbcef 100644 --- a/trunk/drivers/scsi/lpfc/lpfc_init.c +++ b/trunk/drivers/scsi/lpfc/lpfc_init.c @@ -268,6 +268,8 @@ lpfc_config_port_post(struct lpfc_hba * phba) kfree(mp); pmb->context1 = NULL; + if (phba->cfg_soft_wwnn) + u64_to_wwn(phba->cfg_soft_wwnn, phba->fc_sparam.nodeName.u.wwn); if (phba->cfg_soft_wwpn) u64_to_wwn(phba->cfg_soft_wwpn, phba->fc_sparam.portName.u.wwn); memcpy(&phba->fc_nodename, &phba->fc_sparam.nodeName, @@ -349,8 +351,8 @@ lpfc_config_port_post(struct lpfc_hba * phba) phba->hba_state = LPFC_LINK_DOWN; /* Only process IOCBs on ring 0 till hba_state is READY */ - if (psli->ring[psli->ip_ring].cmdringaddr) - psli->ring[psli->ip_ring].flag |= LPFC_STOP_IOCB_EVENT; + if (psli->ring[psli->extra_ring].cmdringaddr) + psli->ring[psli->extra_ring].flag |= LPFC_STOP_IOCB_EVENT; if (psli->ring[psli->fcp_ring].cmdringaddr) psli->ring[psli->fcp_ring].flag |= LPFC_STOP_IOCB_EVENT; if (psli->ring[psli->next_ring].cmdringaddr) @@ -517,7 +519,8 @@ lpfc_handle_eratt(struct lpfc_hba * phba) struct lpfc_sli_ring *pring; uint32_t event_data; - if (phba->work_hs & HS_FFER6) { + if (phba->work_hs & HS_FFER6 || + phba->work_hs & HS_FFER5) { /* Re-establishing Link */ lpfc_printf_log(phba, KERN_INFO, LOG_LINK_EVENT, "%d:1301 Re-establishing Link " @@ -611,7 +614,7 @@ lpfc_handle_latt(struct lpfc_hba * phba) pmb->mbox_cmpl = lpfc_mbx_cmpl_read_la; rc = lpfc_sli_issue_mbox (phba, pmb, (MBX_NOWAIT | MBX_STOP_IOCB)); if (rc == MBX_NOT_FINISHED) - goto lpfc_handle_latt_free_mp; + goto lpfc_handle_latt_free_mbuf; /* Clear Link Attention in HA REG */ spin_lock_irq(phba->host->host_lock); @@ -621,6 +624,8 @@ lpfc_handle_latt(struct lpfc_hba * phba) return; +lpfc_handle_latt_free_mbuf: + lpfc_mbuf_free(phba, mp->virt, mp->phys); lpfc_handle_latt_free_mp: kfree(mp); lpfc_handle_latt_free_pmb: @@ -802,19 +807,13 @@ lpfc_get_hba_model_desc(struct lpfc_hba * phba, uint8_t * mdp, uint8_t * descp) { lpfc_vpd_t *vp; uint16_t dev_id = phba->pcidev->device; - uint16_t dev_subid = phba->pcidev->subsystem_device; - uint8_t hdrtype; int max_speed; - char * ports; struct { char * name; int max_speed; - char * ports; char * bus; - } m = {"", 0, "", ""}; + } m = {"", 0, ""}; - pci_read_config_byte(phba->pcidev, PCI_HEADER_TYPE, &hdrtype); - ports = (hdrtype == 0x80) ? "2-port " : ""; if (mdp && mdp[0] != '\0' && descp && descp[0] != '\0') return; @@ -834,130 +833,93 @@ lpfc_get_hba_model_desc(struct lpfc_hba * phba, uint8_t * mdp, uint8_t * descp) switch (dev_id) { case PCI_DEVICE_ID_FIREFLY: - m = (typeof(m)){"LP6000", max_speed, "", "PCI"}; + m = (typeof(m)){"LP6000", max_speed, "PCI"}; break; case PCI_DEVICE_ID_SUPERFLY: if (vp->rev.biuRev >= 1 && vp->rev.biuRev <= 3) - m = (typeof(m)){"LP7000", max_speed, "", "PCI"}; + m = (typeof(m)){"LP7000", max_speed, "PCI"}; else - m = (typeof(m)){"LP7000E", max_speed, "", "PCI"}; + m = (typeof(m)){"LP7000E", max_speed, "PCI"}; break; case PCI_DEVICE_ID_DRAGONFLY: - m = (typeof(m)){"LP8000", max_speed, "", "PCI"}; + m = (typeof(m)){"LP8000", max_speed, "PCI"}; break; case PCI_DEVICE_ID_CENTAUR: if (FC_JEDEC_ID(vp->rev.biuRev) == CENTAUR_2G_JEDEC_ID) - m = (typeof(m)){"LP9002", max_speed, "", "PCI"}; + m = (typeof(m)){"LP9002", max_speed, "PCI"}; else - m = (typeof(m)){"LP9000", max_speed, "", "PCI"}; + m = (typeof(m)){"LP9000", max_speed, "PCI"}; break; case PCI_DEVICE_ID_RFLY: - m = (typeof(m)){"LP952", max_speed, "", "PCI"}; + m = (typeof(m)){"LP952", max_speed, "PCI"}; break; case PCI_DEVICE_ID_PEGASUS: - m = (typeof(m)){"LP9802", max_speed, "", "PCI-X"}; + m = (typeof(m)){"LP9802", max_speed, "PCI-X"}; break; case PCI_DEVICE_ID_THOR: - if (hdrtype == 0x80) - m = (typeof(m)){"LP10000DC", - max_speed, ports, "PCI-X"}; - else - m = (typeof(m)){"LP10000", - max_speed, ports, "PCI-X"}; + m = (typeof(m)){"LP10000", max_speed, "PCI-X"}; break; case PCI_DEVICE_ID_VIPER: - m = (typeof(m)){"LPX1000", max_speed, "", "PCI-X"}; + m = (typeof(m)){"LPX1000", max_speed, "PCI-X"}; break; case PCI_DEVICE_ID_PFLY: - m = (typeof(m)){"LP982", max_speed, "", "PCI-X"}; + m = (typeof(m)){"LP982", max_speed, "PCI-X"}; break; case PCI_DEVICE_ID_TFLY: - if (hdrtype == 0x80) - m = (typeof(m)){"LP1050DC", max_speed, ports, "PCI-X"}; - else - m = (typeof(m)){"LP1050", max_speed, ports, "PCI-X"}; + m = (typeof(m)){"LP1050", max_speed, "PCI-X"}; break; case PCI_DEVICE_ID_HELIOS: - if (hdrtype == 0x80) - m = (typeof(m)){"LP11002", max_speed, ports, "PCI-X2"}; - else - m = (typeof(m)){"LP11000", max_speed, ports, "PCI-X2"}; + m = (typeof(m)){"LP11000", max_speed, "PCI-X2"}; break; case PCI_DEVICE_ID_HELIOS_SCSP: - m = (typeof(m)){"LP11000-SP", max_speed, ports, "PCI-X2"}; + m = (typeof(m)){"LP11000-SP", max_speed, "PCI-X2"}; break; case PCI_DEVICE_ID_HELIOS_DCSP: - m = (typeof(m)){"LP11002-SP", max_speed, ports, "PCI-X2"}; + m = (typeof(m)){"LP11002-SP", max_speed, "PCI-X2"}; break; case PCI_DEVICE_ID_NEPTUNE: - if (hdrtype == 0x80) - m = (typeof(m)){"LPe1002", max_speed, ports, "PCIe"}; - else - m = (typeof(m)){"LPe1000", max_speed, ports, "PCIe"}; + m = (typeof(m)){"LPe1000", max_speed, "PCIe"}; break; case PCI_DEVICE_ID_NEPTUNE_SCSP: - m = (typeof(m)){"LPe1000-SP", max_speed, ports, "PCIe"}; + m = (typeof(m)){"LPe1000-SP", max_speed, "PCIe"}; break; case PCI_DEVICE_ID_NEPTUNE_DCSP: - m = (typeof(m)){"LPe1002-SP", max_speed, ports, "PCIe"}; + m = (typeof(m)){"LPe1002-SP", max_speed, "PCIe"}; break; case PCI_DEVICE_ID_BMID: - m = (typeof(m)){"LP1150", max_speed, ports, "PCI-X2"}; + m = (typeof(m)){"LP1150", max_speed, "PCI-X2"}; break; case PCI_DEVICE_ID_BSMB: - m = (typeof(m)){"LP111", max_speed, ports, "PCI-X2"}; + m = (typeof(m)){"LP111", max_speed, "PCI-X2"}; break; case PCI_DEVICE_ID_ZEPHYR: - if (hdrtype == 0x80) - m = (typeof(m)){"LPe11002", max_speed, ports, "PCIe"}; - else - m = (typeof(m)){"LPe11000", max_speed, ports, "PCIe"}; + m = (typeof(m)){"LPe11000", max_speed, "PCIe"}; break; case PCI_DEVICE_ID_ZEPHYR_SCSP: - m = (typeof(m)){"LPe11000", max_speed, ports, "PCIe"}; + m = (typeof(m)){"LPe11000", max_speed, "PCIe"}; break; case PCI_DEVICE_ID_ZEPHYR_DCSP: - m = (typeof(m)){"LPe11002-SP", max_speed, ports, "PCIe"}; + m = (typeof(m)){"LPe11002-SP", max_speed, "PCIe"}; break; case PCI_DEVICE_ID_ZMID: - m = (typeof(m)){"LPe1150", max_speed, ports, "PCIe"}; + m = (typeof(m)){"LPe1150", max_speed, "PCIe"}; break; case PCI_DEVICE_ID_ZSMB: - m = (typeof(m)){"LPe111", max_speed, ports, "PCIe"}; + m = (typeof(m)){"LPe111", max_speed, "PCIe"}; break; case PCI_DEVICE_ID_LP101: - m = (typeof(m)){"LP101", max_speed, ports, "PCI-X"}; + m = (typeof(m)){"LP101", max_speed, "PCI-X"}; break; case PCI_DEVICE_ID_LP10000S: - m = (typeof(m)){"LP10000-S", max_speed, ports, "PCI"}; + m = (typeof(m)){"LP10000-S", max_speed, "PCI"}; break; case PCI_DEVICE_ID_LP11000S: + m = (typeof(m)){"LP11000-S", max_speed, + "PCI-X2"}; + break; case PCI_DEVICE_ID_LPE11000S: - switch (dev_subid) { - case PCI_SUBSYSTEM_ID_LP11000S: - m = (typeof(m)){"LP11000-S", max_speed, - ports, "PCI-X2"}; - break; - case PCI_SUBSYSTEM_ID_LP11002S: - m = (typeof(m)){"LP11002-S", max_speed, - ports, "PCI-X2"}; - break; - case PCI_SUBSYSTEM_ID_LPE11000S: - m = (typeof(m)){"LPe11000-S", max_speed, - ports, "PCIe"}; - break; - case PCI_SUBSYSTEM_ID_LPE11002S: - m = (typeof(m)){"LPe11002-S", max_speed, - ports, "PCIe"}; - break; - case PCI_SUBSYSTEM_ID_LPE11010S: - m = (typeof(m)){"LPe11010-S", max_speed, - "10-port ", "PCIe"}; - break; - default: - m = (typeof(m)){ NULL }; - break; - } + m = (typeof(m)){"LPe11000-S", max_speed, + "PCIe"}; break; default: m = (typeof(m)){ NULL }; @@ -968,8 +930,8 @@ lpfc_get_hba_model_desc(struct lpfc_hba * phba, uint8_t * mdp, uint8_t * descp) snprintf(mdp, 79,"%s", m.name); if (descp && descp[0] == '\0') snprintf(descp, 255, - "Emulex %s %dGb %s%s Fibre Channel Adapter", - m.name, m.max_speed, m.ports, m.bus); + "Emulex %s %dGb %s Fibre Channel Adapter", + m.name, m.max_speed, m.bus); } /**************************************************/ @@ -1651,6 +1613,14 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) if (error) goto out_remove_host; + if (phba->cfg_use_msi) { + error = pci_enable_msi(phba->pcidev); + if (error) + lpfc_printf_log(phba, KERN_INFO, LOG_INIT, "%d:0452 " + "Enable MSI failed, continuing with " + "IRQ\n", phba->brd_no); + } + error = request_irq(phba->pcidev->irq, lpfc_intr_handler, IRQF_SHARED, LPFC_DRIVER_NAME, phba); if (error) { @@ -1730,6 +1700,7 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) lpfc_stop_timer(phba); phba->work_hba_events = 0; free_irq(phba->pcidev->irq, phba); + pci_disable_msi(phba->pcidev); out_free_sysfs_attr: lpfc_free_sysfs_attr(phba); out_remove_host: @@ -1796,6 +1767,7 @@ lpfc_pci_remove_one(struct pci_dev *pdev) /* Release the irq reservation */ free_irq(phba->pcidev->irq, phba); + pci_disable_msi(phba->pcidev); lpfc_cleanup(phba, 0); lpfc_stop_timer(phba); diff --git a/trunk/drivers/scsi/lpfc/lpfc_logmsg.h b/trunk/drivers/scsi/lpfc/lpfc_logmsg.h index 62c8ca862e9e..438cbcd9eb13 100644 --- a/trunk/drivers/scsi/lpfc/lpfc_logmsg.h +++ b/trunk/drivers/scsi/lpfc/lpfc_logmsg.h @@ -28,7 +28,7 @@ #define LOG_NODE 0x80 /* Node table events */ #define LOG_MISC 0x400 /* Miscellaneous events */ #define LOG_SLI 0x800 /* SLI events */ -#define LOG_CHK_COND 0x1000 /* FCP Check condition flag */ +#define LOG_FCP_ERROR 0x1000 /* log errors, not underruns */ #define LOG_LIBDFC 0x2000 /* Libdfc events */ #define LOG_ALL_MSG 0xffff /* LOG all messages */ diff --git a/trunk/drivers/scsi/lpfc/lpfc_nportdisc.c b/trunk/drivers/scsi/lpfc/lpfc_nportdisc.c index d5f415007db2..0c7e731dc45a 100644 --- a/trunk/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/trunk/drivers/scsi/lpfc/lpfc_nportdisc.c @@ -739,7 +739,7 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_hba * phba, uint32_t evt) { struct lpfc_iocbq *cmdiocb, *rspiocb; - struct lpfc_dmabuf *pcmd, *prsp; + struct lpfc_dmabuf *pcmd, *prsp, *mp; uint32_t *lp; IOCB_t *irsp; struct serv_parm *sp; @@ -829,6 +829,9 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_hba * phba, NLP_REGLOGIN_LIST); return ndlp->nlp_state; } + mp = (struct lpfc_dmabuf *)mbox->context1; + lpfc_mbuf_free(phba, mp->virt, mp->phys); + kfree(mp); mempool_free(mbox, phba->mbox_mem_pool); } else { mempool_free(mbox, phba->mbox_mem_pool); @@ -1620,8 +1623,8 @@ lpfc_rcv_padisc_npr_node(struct lpfc_hba * phba, * or discovery in progress for this node. Starting discovery * here will affect the counting of discovery threads. */ - if ((!(ndlp->nlp_flag & NLP_DELAY_TMO)) && - (ndlp->nlp_flag & NLP_NPR_2B_DISC)){ + if (!(ndlp->nlp_flag & NLP_DELAY_TMO) && + !(ndlp->nlp_flag & NLP_NPR_2B_DISC)){ if (ndlp->nlp_flag & NLP_NPR_ADISC) { ndlp->nlp_prev_state = NLP_STE_NPR_NODE; ndlp->nlp_state = NLP_STE_ADISC_ISSUE; diff --git a/trunk/drivers/scsi/lpfc/lpfc_scsi.c b/trunk/drivers/scsi/lpfc/lpfc_scsi.c index 97ae98dc95d0..c3e68e0d8f74 100644 --- a/trunk/drivers/scsi/lpfc/lpfc_scsi.c +++ b/trunk/drivers/scsi/lpfc/lpfc_scsi.c @@ -297,8 +297,10 @@ lpfc_handle_fcp_err(struct lpfc_scsi_buf *lpfc_cmd) uint32_t fcpi_parm = lpfc_cmd->cur_iocbq.iocb.un.fcpi.fcpi_parm; uint32_t resp_info = fcprsp->rspStatus2; uint32_t scsi_status = fcprsp->rspStatus3; + uint32_t *lp; uint32_t host_status = DID_OK; uint32_t rsplen = 0; + uint32_t logit = LOG_FCP | LOG_FCP_ERROR; /* * If this is a task management command, there is no @@ -310,10 +312,25 @@ lpfc_handle_fcp_err(struct lpfc_scsi_buf *lpfc_cmd) goto out; } - lpfc_printf_log(phba, KERN_WARNING, LOG_FCP, - "%d:0730 FCP command failed: RSP " - "Data: x%x x%x x%x x%x x%x x%x\n", - phba->brd_no, resp_info, scsi_status, + if ((resp_info & SNS_LEN_VALID) && fcprsp->rspSnsLen) { + uint32_t snslen = be32_to_cpu(fcprsp->rspSnsLen); + if (snslen > SCSI_SENSE_BUFFERSIZE) + snslen = SCSI_SENSE_BUFFERSIZE; + + if (resp_info & RSP_LEN_VALID) + rsplen = be32_to_cpu(fcprsp->rspRspLen); + memcpy(cmnd->sense_buffer, &fcprsp->rspInfo0 + rsplen, snslen); + } + lp = (uint32_t *)cmnd->sense_buffer; + + if (!scsi_status && (resp_info & RESID_UNDER)) + logit = LOG_FCP; + + lpfc_printf_log(phba, KERN_WARNING, logit, + "%d:0730 FCP command x%x failed: x%x SNS x%x x%x " + "Data: x%x x%x x%x x%x x%x\n", + phba->brd_no, cmnd->cmnd[0], scsi_status, + be32_to_cpu(*lp), be32_to_cpu(*(lp + 3)), resp_info, be32_to_cpu(fcprsp->rspResId), be32_to_cpu(fcprsp->rspSnsLen), be32_to_cpu(fcprsp->rspRspLen), @@ -328,14 +345,6 @@ lpfc_handle_fcp_err(struct lpfc_scsi_buf *lpfc_cmd) } } - if ((resp_info & SNS_LEN_VALID) && fcprsp->rspSnsLen) { - uint32_t snslen = be32_to_cpu(fcprsp->rspSnsLen); - if (snslen > SCSI_SENSE_BUFFERSIZE) - snslen = SCSI_SENSE_BUFFERSIZE; - - memcpy(cmnd->sense_buffer, &fcprsp->rspInfo0 + rsplen, snslen); - } - cmnd->resid = 0; if (resp_info & RESID_UNDER) { cmnd->resid = be32_to_cpu(fcprsp->rspResId); @@ -378,7 +387,7 @@ lpfc_handle_fcp_err(struct lpfc_scsi_buf *lpfc_cmd) */ } else if ((scsi_status == SAM_STAT_GOOD) && fcpi_parm && (cmnd->sc_data_direction == DMA_FROM_DEVICE)) { - lpfc_printf_log(phba, KERN_WARNING, LOG_FCP, + lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_FCP_ERROR, "%d:0734 FCP Read Check Error Data: " "x%x x%x x%x x%x\n", phba->brd_no, be32_to_cpu(fcpcmd->fcpDl), @@ -670,6 +679,9 @@ lpfc_scsi_tgt_reset(struct lpfc_scsi_buf * lpfc_cmd, struct lpfc_hba * phba, struct lpfc_iocbq *iocbqrsp; int ret; + if (!rdata->pnode) + return FAILED; + lpfc_cmd->rdata = rdata; ret = lpfc_scsi_prep_task_mgmt_cmd(phba, lpfc_cmd, lun, FCP_TARGET_RESET); @@ -976,20 +988,34 @@ lpfc_reset_lun_handler(struct scsi_cmnd *cmnd) lpfc_block_error_handler(cmnd); spin_lock_irq(shost->host_lock); + loopcnt = 0; /* * If target is not in a MAPPED state, delay the reset until * target is rediscovered or devloss timeout expires. */ while ( 1 ) { if (!pnode) - break; + return FAILED; if (pnode->nlp_state != NLP_STE_MAPPED_NODE) { spin_unlock_irq(phba->host->host_lock); schedule_timeout_uninterruptible(msecs_to_jiffies(500)); spin_lock_irq(phba->host->host_lock); + loopcnt++; + rdata = cmnd->device->hostdata; + if (!rdata || + (loopcnt > ((phba->cfg_devloss_tmo * 2) + 1))) { + lpfc_printf_log(phba, KERN_ERR, LOG_FCP, + "%d:0721 LUN Reset rport failure:" + " cnt x%x rdata x%p\n", + phba->brd_no, loopcnt, rdata); + goto out; + } + pnode = rdata->pnode; + if (!pnode) + return FAILED; } - if ((pnode) && (pnode->nlp_state == NLP_STE_MAPPED_NODE)) + if (pnode->nlp_state == NLP_STE_MAPPED_NODE) break; } diff --git a/trunk/drivers/scsi/lpfc/lpfc_sli.c b/trunk/drivers/scsi/lpfc/lpfc_sli.c index 582f5ea4e84e..a4128e19338a 100644 --- a/trunk/drivers/scsi/lpfc/lpfc_sli.c +++ b/trunk/drivers/scsi/lpfc/lpfc_sli.c @@ -117,6 +117,10 @@ lpfc_sli_iocb_cmd_type(uint8_t iocb_cmnd) case CMD_FCP_IREAD_CX: case CMD_FCP_ICMND_CR: case CMD_FCP_ICMND_CX: + case CMD_FCP_TSEND_CX: + case CMD_FCP_TRSP_CX: + case CMD_FCP_TRECEIVE_CX: + case CMD_FCP_AUTO_TRSP_CX: case CMD_ADAPTER_MSG: case CMD_ADAPTER_DUMP: case CMD_XMIT_SEQUENCE64_CR: @@ -131,6 +135,9 @@ lpfc_sli_iocb_cmd_type(uint8_t iocb_cmnd) case CMD_FCP_IREAD64_CX: case CMD_FCP_ICMND64_CR: case CMD_FCP_ICMND64_CX: + case CMD_FCP_TSEND64_CX: + case CMD_FCP_TRSP64_CX: + case CMD_FCP_TRECEIVE64_CX: case CMD_GEN_REQUEST64_CR: case CMD_GEN_REQUEST64_CX: case CMD_XMIT_ELS_RSP64_CX: @@ -1098,6 +1105,7 @@ lpfc_sli_handle_fast_ring_event(struct lpfc_hba * phba, lpfc_sli_pcimem_bcopy((uint32_t *) entry, (uint32_t *) &rspiocbq.iocb, sizeof (IOCB_t)); + INIT_LIST_HEAD(&(rspiocbq.list)); irsp = &rspiocbq.iocb; type = lpfc_sli_iocb_cmd_type(irsp->ulpCommand & CMD_IOCB_MASK); @@ -1149,6 +1157,11 @@ lpfc_sli_handle_fast_ring_event(struct lpfc_hba * phba, } } break; + case LPFC_UNSOL_IOCB: + spin_unlock_irqrestore(phba->host->host_lock, iflag); + lpfc_sli_process_unsol_iocb(phba, pring, &rspiocbq); + spin_lock_irqsave(phba->host->host_lock, iflag); + break; default: if (irsp->ulpCommand == CMD_ADAPTER_MSG) { char adaptermsg[LPFC_MAX_ADPTMSG]; @@ -2472,13 +2485,17 @@ lpfc_extra_ring_setup( struct lpfc_hba *phba) psli = &phba->sli; /* Adjust cmd/rsp ring iocb entries more evenly */ + + /* Take some away from the FCP ring */ pring = &psli->ring[psli->fcp_ring]; pring->numCiocb -= SLI2_IOCB_CMD_R1XTRA_ENTRIES; pring->numRiocb -= SLI2_IOCB_RSP_R1XTRA_ENTRIES; pring->numCiocb -= SLI2_IOCB_CMD_R3XTRA_ENTRIES; pring->numRiocb -= SLI2_IOCB_RSP_R3XTRA_ENTRIES; - pring = &psli->ring[1]; + /* and give them to the extra ring */ + pring = &psli->ring[psli->extra_ring]; + pring->numCiocb += SLI2_IOCB_CMD_R1XTRA_ENTRIES; pring->numRiocb += SLI2_IOCB_RSP_R1XTRA_ENTRIES; pring->numCiocb += SLI2_IOCB_CMD_R3XTRA_ENTRIES; @@ -2488,8 +2505,8 @@ lpfc_extra_ring_setup( struct lpfc_hba *phba) pring->iotag_max = 4096; pring->num_mask = 1; pring->prt[0].profile = 0; /* Mask 0 */ - pring->prt[0].rctl = FC_UNSOL_DATA; - pring->prt[0].type = 5; + pring->prt[0].rctl = phba->cfg_multi_ring_rctl; + pring->prt[0].type = phba->cfg_multi_ring_type; pring->prt[0].lpfc_sli_rcv_unsol_event = NULL; return 0; } @@ -2505,7 +2522,7 @@ lpfc_sli_setup(struct lpfc_hba *phba) psli->sli_flag = 0; psli->fcp_ring = LPFC_FCP_RING; psli->next_ring = LPFC_FCP_NEXT_RING; - psli->ip_ring = LPFC_IP_RING; + psli->extra_ring = LPFC_EXTRA_RING; psli->iocbq_lookup = NULL; psli->iocbq_lookup_len = 0; @@ -2528,7 +2545,7 @@ lpfc_sli_setup(struct lpfc_hba *phba) pring->fast_iotag = pring->iotag_max; pring->num_mask = 0; break; - case LPFC_IP_RING: /* ring 1 - IP */ + case LPFC_EXTRA_RING: /* ring 1 - EXTRA */ /* numCiocb and numRiocb are used in config_port */ pring->numCiocb = SLI2_IOCB_CMD_R1_ENTRIES; pring->numRiocb = SLI2_IOCB_RSP_R1_ENTRIES; @@ -3238,6 +3255,21 @@ lpfc_intr_handler(int irq, void *dev_id) lpfc_sli_handle_fast_ring_event(phba, &phba->sli.ring[LPFC_FCP_RING], status); + + if (phba->cfg_multi_ring_support == 2) { + /* + * Process all events on extra ring. Take the optimized path + * for extra ring IO. Any other IO is slow path and is handled + * by the worker thread. + */ + status = (ha_copy & (HA_RXMASK << (4*LPFC_EXTRA_RING))); + status >>= (4*LPFC_EXTRA_RING); + if (status & HA_RXATT) { + lpfc_sli_handle_fast_ring_event(phba, + &phba->sli.ring[LPFC_EXTRA_RING], + status); + } + } return IRQ_HANDLED; } /* lpfc_intr_handler */ diff --git a/trunk/drivers/scsi/lpfc/lpfc_sli.h b/trunk/drivers/scsi/lpfc/lpfc_sli.h index e26de6809358..a43549959dc7 100644 --- a/trunk/drivers/scsi/lpfc/lpfc_sli.h +++ b/trunk/drivers/scsi/lpfc/lpfc_sli.h @@ -198,7 +198,7 @@ struct lpfc_sli { int fcp_ring; /* ring used for FCP initiator commands */ int next_ring; - int ip_ring; /* ring used for IP network drv cmds */ + int extra_ring; /* extra ring used for other protocols */ struct lpfc_sli_stat slistat; /* SLI statistical info */ struct list_head mboxq; diff --git a/trunk/drivers/scsi/lpfc/lpfc_version.h b/trunk/drivers/scsi/lpfc/lpfc_version.h index ac417908b407..a61ef3d1e7f1 100644 --- a/trunk/drivers/scsi/lpfc/lpfc_version.h +++ b/trunk/drivers/scsi/lpfc/lpfc_version.h @@ -18,7 +18,7 @@ * included with this package. * *******************************************************************/ -#define LPFC_DRIVER_VERSION "8.1.10" +#define LPFC_DRIVER_VERSION "8.1.11" #define LPFC_DRIVER_NAME "lpfc" diff --git a/trunk/drivers/scsi/megaraid.c b/trunk/drivers/scsi/megaraid.c index 86099fde1b2a..77d9d3804ccf 100644 --- a/trunk/drivers/scsi/megaraid.c +++ b/trunk/drivers/scsi/megaraid.c @@ -73,10 +73,10 @@ static unsigned short int max_mbox_busy_wait = MBOX_BUSY_WAIT; module_param(max_mbox_busy_wait, ushort, 0); MODULE_PARM_DESC(max_mbox_busy_wait, "Maximum wait for mailbox in microseconds if busy (default=MBOX_BUSY_WAIT=10)"); -#define RDINDOOR(adapter) readl((adapter)->base + 0x20) -#define RDOUTDOOR(adapter) readl((adapter)->base + 0x2C) -#define WRINDOOR(adapter,value) writel(value, (adapter)->base + 0x20) -#define WROUTDOOR(adapter,value) writel(value, (adapter)->base + 0x2C) +#define RDINDOOR(adapter) readl((adapter)->mmio_base + 0x20) +#define RDOUTDOOR(adapter) readl((adapter)->mmio_base + 0x2C) +#define WRINDOOR(adapter,value) writel(value, (adapter)->mmio_base + 0x20) +#define WROUTDOOR(adapter,value) writel(value, (adapter)->mmio_base + 0x2C) /* * Global variables @@ -1386,7 +1386,8 @@ megaraid_isr_memmapped(int irq, void *devp) handled = 1; - while( RDINDOOR(adapter) & 0x02 ) cpu_relax(); + while( RDINDOOR(adapter) & 0x02 ) + cpu_relax(); mega_cmd_done(adapter, completed, nstatus, status); @@ -4668,6 +4669,8 @@ megaraid_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) host->host_no, mega_baseport, irq); adapter->base = mega_baseport; + if (flag & BOARD_MEMMAP) + adapter->mmio_base = (void __iomem *) mega_baseport; INIT_LIST_HEAD(&adapter->free_list); INIT_LIST_HEAD(&adapter->pending_list); diff --git a/trunk/drivers/scsi/megaraid.h b/trunk/drivers/scsi/megaraid.h index 66529f11d23c..c6e74643abe2 100644 --- a/trunk/drivers/scsi/megaraid.h +++ b/trunk/drivers/scsi/megaraid.h @@ -801,7 +801,8 @@ typedef struct { clustering is available */ u32 flag; - unsigned long base; + unsigned long base; + void __iomem *mmio_base; /* mbox64 with mbox not aligned on 16-byte boundry */ mbox64_t *una_mbox64; diff --git a/trunk/drivers/scsi/megaraid/megaraid_sas.c b/trunk/drivers/scsi/megaraid/megaraid_sas.c index 7e4262f2af96..046223b4ae57 100644 --- a/trunk/drivers/scsi/megaraid/megaraid_sas.c +++ b/trunk/drivers/scsi/megaraid/megaraid_sas.c @@ -517,7 +517,7 @@ megasas_make_sgl64(struct megasas_instance *instance, struct scsi_cmnd *scp, * Returns the number of frames required for numnber of sge's (sge_count) */ -u32 megasas_get_frame_count(u8 sge_count) +static u32 megasas_get_frame_count(u8 sge_count) { int num_cnt; int sge_bytes; @@ -1733,7 +1733,7 @@ megasas_get_ctrl_info(struct megasas_instance *instance, * * Tasklet to complete cmds */ -void megasas_complete_cmd_dpc(unsigned long instance_addr) +static void megasas_complete_cmd_dpc(unsigned long instance_addr) { u32 producer; u32 consumer; diff --git a/trunk/drivers/scsi/ncr53c8xx.c b/trunk/drivers/scsi/ncr53c8xx.c index adb8eb4f5fd1..bbf521cbc55d 100644 --- a/trunk/drivers/scsi/ncr53c8xx.c +++ b/trunk/drivers/scsi/ncr53c8xx.c @@ -589,10 +589,12 @@ static int __map_scsi_sg_data(struct device *dev, struct scsi_cmnd *cmd) static struct ncr_driver_setup driver_setup = SCSI_NCR_DRIVER_SETUP; +#ifndef MODULE #ifdef SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT static struct ncr_driver_setup driver_safe_setup __initdata = SCSI_NCR_DRIVER_SAFE_SETUP; #endif +#endif /* !MODULE */ #define initverbose (driver_setup.verbose) #define bootverbose (np->verbose) @@ -641,6 +643,13 @@ static struct ncr_driver_setup #define OPT_IARB 26 #endif +#ifdef MODULE +#define ARG_SEP ' ' +#else +#define ARG_SEP ',' +#endif + +#ifndef MODULE static char setup_token[] __initdata = "tags:" "mpar:" "spar:" "disc:" @@ -660,12 +669,6 @@ static char setup_token[] __initdata = #endif ; /* DONNOT REMOVE THIS ';' */ -#ifdef MODULE -#define ARG_SEP ' ' -#else -#define ARG_SEP ',' -#endif - static int __init get_setup_token(char *p) { char *cur = setup_token; @@ -682,7 +685,6 @@ static int __init get_setup_token(char *p) return 0; } - static int __init sym53c8xx__setup(char *str) { #ifdef SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT @@ -804,6 +806,7 @@ static int __init sym53c8xx__setup(char *str) #endif /* SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT */ return 1; } +#endif /* !MODULE */ /*=================================================================== ** @@ -8321,12 +8324,12 @@ char *ncr53c8xx; /* command line passed by insmod */ module_param(ncr53c8xx, charp, 0); #endif +#ifndef MODULE static int __init ncr53c8xx_setup(char *str) { return sym53c8xx__setup(str); } -#ifndef MODULE __setup("ncr53c8xx=", ncr53c8xx_setup); #endif diff --git a/trunk/drivers/scsi/oktagon_esp.c b/trunk/drivers/scsi/oktagon_esp.c index dd67a68c5c23..c116a6ae3c54 100644 --- a/trunk/drivers/scsi/oktagon_esp.c +++ b/trunk/drivers/scsi/oktagon_esp.c @@ -72,12 +72,12 @@ static void dma_advance_sg(Scsi_Cmnd *); static int oktagon_notify_reboot(struct notifier_block *this, unsigned long code, void *x); #ifdef USE_BOTTOM_HALF -static void dma_commit(void *opaque); +static void dma_commit(struct work_struct *unused); long oktag_to_io(long *paddr, long *addr, long len); long oktag_from_io(long *addr, long *paddr, long len); -static DECLARE_WORK(tq_fake_dma, dma_commit, NULL); +static DECLARE_WORK(tq_fake_dma, dma_commit); #define DMA_MAXTRANSFER 0x8000 @@ -266,7 +266,7 @@ oktagon_notify_reboot(struct notifier_block *this, unsigned long code, void *x) */ -static void dma_commit(void *opaque) +static void dma_commit(struct work_struct *unused) { long wait,len2,pos; struct NCR_ESP *esp; diff --git a/trunk/drivers/scsi/pcmcia/aha152x_stub.c b/trunk/drivers/scsi/pcmcia/aha152x_stub.c index ee449b29fc82..aad362ba02e0 100644 --- a/trunk/drivers/scsi/pcmcia/aha152x_stub.c +++ b/trunk/drivers/scsi/pcmcia/aha152x_stub.c @@ -154,16 +154,11 @@ static int aha152x_config_cs(struct pcmcia_device *link) DEBUG(0, "aha152x_config(0x%p)\n", link); - tuple.DesiredTuple = CISTPL_CONFIG; tuple.TupleData = tuple_data; tuple.TupleDataMax = 64; tuple.TupleOffset = 0; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); - link->conf.ConfigBase = parse.config.base; - tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; + tuple.Attributes = 0; CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); while (1) { if (pcmcia_get_tuple_data(link, &tuple) != 0 || diff --git a/trunk/drivers/scsi/pcmcia/fdomain_stub.c b/trunk/drivers/scsi/pcmcia/fdomain_stub.c index 85f7ffac19a0..a1c5f265069f 100644 --- a/trunk/drivers/scsi/pcmcia/fdomain_stub.c +++ b/trunk/drivers/scsi/pcmcia/fdomain_stub.c @@ -136,14 +136,9 @@ static int fdomain_config(struct pcmcia_device *link) DEBUG(0, "fdomain_config(0x%p)\n", link); - tuple.DesiredTuple = CISTPL_CONFIG; tuple.TupleData = tuple_data; tuple.TupleDataMax = 64; tuple.TupleOffset = 0; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); - link->conf.ConfigBase = parse.config.base; tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); diff --git a/trunk/drivers/scsi/pcmcia/nsp_cs.c b/trunk/drivers/scsi/pcmcia/nsp_cs.c index f2d79c3f0b8e..d72df5dae4ee 100644 --- a/trunk/drivers/scsi/pcmcia/nsp_cs.c +++ b/trunk/drivers/scsi/pcmcia/nsp_cs.c @@ -1685,16 +1685,10 @@ static int nsp_cs_config(struct pcmcia_device *link) nsp_dbg(NSP_DEBUG_INIT, "in"); - tuple.DesiredTuple = CISTPL_CONFIG; tuple.Attributes = 0; tuple.TupleData = tuple_data; tuple.TupleDataMax = sizeof(tuple_data); tuple.TupleOffset = 0; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); - link->conf.ConfigBase = parse.config.base; - link->conf.Present = parse.config.rmask[0]; /* Look up the current Vcc */ CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &conf)); diff --git a/trunk/drivers/scsi/pcmcia/qlogic_stub.c b/trunk/drivers/scsi/pcmcia/qlogic_stub.c index 86c2ac6ae623..9d431fe7f47f 100644 --- a/trunk/drivers/scsi/pcmcia/qlogic_stub.c +++ b/trunk/drivers/scsi/pcmcia/qlogic_stub.c @@ -208,18 +208,11 @@ static int qlogic_config(struct pcmcia_device * link) DEBUG(0, "qlogic_config(0x%p)\n", link); + info->manf_id = link->manf_id; + tuple.TupleData = (cisdata_t *) tuple_data; tuple.TupleDataMax = 64; tuple.TupleOffset = 0; - tuple.DesiredTuple = CISTPL_CONFIG; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); - link->conf.ConfigBase = parse.config.base; - - tuple.DesiredTuple = CISTPL_MANFID; - if ((pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) && (pcmcia_get_tuple_data(link, &tuple) == CS_SUCCESS)) - info->manf_id = le16_to_cpu(tuple.TupleData[0]); tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); diff --git a/trunk/drivers/scsi/pcmcia/sym53c500_cs.c b/trunk/drivers/scsi/pcmcia/sym53c500_cs.c index 72fe5d055de1..fb7acea60286 100644 --- a/trunk/drivers/scsi/pcmcia/sym53c500_cs.c +++ b/trunk/drivers/scsi/pcmcia/sym53c500_cs.c @@ -722,19 +722,11 @@ SYM53C500_config(struct pcmcia_device *link) DEBUG(0, "SYM53C500_config(0x%p)\n", link); + info->manf_id = link->manf_id; + tuple.TupleData = (cisdata_t *)tuple_data; tuple.TupleDataMax = 64; tuple.TupleOffset = 0; - tuple.DesiredTuple = CISTPL_CONFIG; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); - link->conf.ConfigBase = parse.config.base; - - tuple.DesiredTuple = CISTPL_MANFID; - if ((pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) && - (pcmcia_get_tuple_data(link, &tuple) == CS_SUCCESS)) - info->manf_id = le16_to_cpu(tuple.TupleData[0]); tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); diff --git a/trunk/drivers/scsi/ppa.c b/trunk/drivers/scsi/ppa.c index 89a2a9f11e41..584ba4d6e038 100644 --- a/trunk/drivers/scsi/ppa.c +++ b/trunk/drivers/scsi/ppa.c @@ -31,7 +31,7 @@ typedef struct { int base; /* Actual port address */ int mode; /* Transfer mode */ struct scsi_cmnd *cur_cmd; /* Current queued command */ - struct work_struct ppa_tq; /* Polling interrupt stuff */ + struct delayed_work ppa_tq; /* Polling interrupt stuff */ unsigned long jstart; /* Jiffies at start */ unsigned long recon_tmo; /* How many usecs to wait for reconnection (6th bit) */ unsigned int failed:1; /* Failure flag */ @@ -627,9 +627,9 @@ static int ppa_completion(struct scsi_cmnd *cmd) * the scheduler's task queue to generate a stream of call-backs and * complete the request when the drive is ready. */ -static void ppa_interrupt(void *data) +static void ppa_interrupt(struct work_struct *work) { - ppa_struct *dev = (ppa_struct *) data; + ppa_struct *dev = container_of(work, ppa_struct, ppa_tq.work); struct scsi_cmnd *cmd = dev->cur_cmd; if (!cmd) { @@ -637,7 +637,6 @@ static void ppa_interrupt(void *data) return; } if (ppa_engine(dev, cmd)) { - dev->ppa_tq.data = (void *) dev; schedule_delayed_work(&dev->ppa_tq, 1); return; } @@ -822,8 +821,7 @@ static int ppa_queuecommand(struct scsi_cmnd *cmd, cmd->result = DID_ERROR << 16; /* default return code */ cmd->SCp.phase = 0; /* bus free */ - dev->ppa_tq.data = dev; - schedule_work(&dev->ppa_tq); + schedule_delayed_work(&dev->ppa_tq, 0); ppa_pb_claim(dev); @@ -1086,7 +1084,7 @@ static int __ppa_attach(struct parport *pb) else ports = 8; - INIT_WORK(&dev->ppa_tq, ppa_interrupt, dev); + INIT_DELAYED_WORK(&dev->ppa_tq, ppa_interrupt); err = -ENOMEM; host = scsi_host_alloc(&ppa_template, sizeof(ppa_struct *)); diff --git a/trunk/drivers/scsi/qla2xxx/qla_attr.c b/trunk/drivers/scsi/qla2xxx/qla_attr.c index 285c8e8ff1a0..7b18a6c7b7eb 100644 --- a/trunk/drivers/scsi/qla2xxx/qla_attr.c +++ b/trunk/drivers/scsi/qla2xxx/qla_attr.c @@ -390,7 +390,7 @@ static struct sysfs_entry { { "optrom_ctl", &sysfs_optrom_ctl_attr, }, { "vpd", &sysfs_vpd_attr, 1 }, { "sfp", &sysfs_sfp_attr, 1 }, - { 0 }, + { NULL }, }; void diff --git a/trunk/drivers/scsi/qla2xxx/qla_init.c b/trunk/drivers/scsi/qla2xxx/qla_init.c index 08cb5e3fb553..a823f0bc519d 100644 --- a/trunk/drivers/scsi/qla2xxx/qla_init.c +++ b/trunk/drivers/scsi/qla2xxx/qla_init.c @@ -59,9 +59,6 @@ int qla2x00_initialize_adapter(scsi_qla_host_t *ha) { int rval; - uint8_t restart_risc = 0; - uint8_t retry; - uint32_t wait_time; /* Clear adapter flags. */ ha->flags.online = 0; @@ -104,87 +101,15 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha) qla_printk(KERN_INFO, ha, "Verifying loaded RISC code...\n"); - retry = 10; - /* - * Try to configure the loop. - */ - do { - restart_risc = 0; - - /* If firmware needs to be loaded */ - if (qla2x00_isp_firmware(ha) != QLA_SUCCESS) { - if ((rval = ha->isp_ops.chip_diag(ha)) == QLA_SUCCESS) { - rval = qla2x00_setup_chip(ha); - } - } - - if (rval == QLA_SUCCESS && - (rval = qla2x00_init_rings(ha)) == QLA_SUCCESS) { -check_fw_ready_again: - /* - * Wait for a successful LIP up to a maximum - * of (in seconds): RISC login timeout value, - * RISC retry count value, and port down retry - * value OR a minimum of 4 seconds OR If no - * cable, only 5 seconds. - */ - rval = qla2x00_fw_ready(ha); - if (rval == QLA_SUCCESS) { - clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags); - - /* Issue a marker after FW becomes ready. */ - qla2x00_marker(ha, 0, 0, MK_SYNC_ALL); - - /* - * Wait at most MAX_TARGET RSCNs for a stable - * link. - */ - wait_time = 256; - do { - clear_bit(LOOP_RESYNC_NEEDED, - &ha->dpc_flags); - rval = qla2x00_configure_loop(ha); - - if (test_and_clear_bit(ISP_ABORT_NEEDED, - &ha->dpc_flags)) { - restart_risc = 1; - break; - } - - /* - * If loop state change while we were - * discoverying devices then wait for - * LIP to complete - */ - - if (atomic_read(&ha->loop_state) != - LOOP_READY && retry--) { - goto check_fw_ready_again; - } - wait_time--; - } while (!atomic_read(&ha->loop_down_timer) && - retry && - wait_time && - (test_bit(LOOP_RESYNC_NEEDED, - &ha->dpc_flags))); - - if (wait_time == 0) - rval = QLA_FUNCTION_FAILED; - } else if (ha->device_flags & DFLG_NO_CABLE) - /* If no cable, then all is good. */ - rval = QLA_SUCCESS; - } - } while (restart_risc && retry--); - - if (rval == QLA_SUCCESS) { - clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags); - qla2x00_marker(ha, 0, 0, MK_SYNC_ALL); - ha->marker_needed = 0; - - ha->flags.online = 1; - } else { - DEBUG2_3(printk("%s(): **** FAILED ****\n", __func__)); + if (qla2x00_isp_firmware(ha) != QLA_SUCCESS) { + rval = ha->isp_ops.chip_diag(ha); + if (rval) + return (rval); + rval = qla2x00_setup_chip(ha); + if (rval) + return (rval); } + rval = qla2x00_init_rings(ha); return (rval); } @@ -2208,8 +2133,7 @@ qla2x00_update_fcport(scsi_qla_host_t *ha, fc_port_t *fcport) atomic_set(&fcport->state, FCS_ONLINE); - if (ha->flags.init_done) - qla2x00_reg_remote_port(ha, fcport); + qla2x00_reg_remote_port(ha, fcport); } void diff --git a/trunk/drivers/scsi/qla2xxx/qla_os.c b/trunk/drivers/scsi/qla2xxx/qla_os.c index 208607be78c7..d03523d3bf38 100644 --- a/trunk/drivers/scsi/qla2xxx/qla_os.c +++ b/trunk/drivers/scsi/qla2xxx/qla_os.c @@ -24,7 +24,7 @@ char qla2x00_version_str[40]; /* * SRB allocation cache */ -static kmem_cache_t *srb_cachep; +static struct kmem_cache *srb_cachep; /* * Ioctl related information. @@ -95,6 +95,8 @@ MODULE_PARM_DESC(ql2xqfullrampup, */ static int qla2xxx_slave_configure(struct scsi_device * device); static int qla2xxx_slave_alloc(struct scsi_device *); +static int qla2xxx_scan_finished(struct Scsi_Host *, unsigned long time); +static void qla2xxx_scan_start(struct Scsi_Host *); static void qla2xxx_slave_destroy(struct scsi_device *); static int qla2x00_queuecommand(struct scsi_cmnd *cmd, void (*fn)(struct scsi_cmnd *)); @@ -124,6 +126,8 @@ static struct scsi_host_template qla2x00_driver_template = { .slave_alloc = qla2xxx_slave_alloc, .slave_destroy = qla2xxx_slave_destroy, + .scan_finished = qla2xxx_scan_finished, + .scan_start = qla2xxx_scan_start, .change_queue_depth = qla2x00_change_queue_depth, .change_queue_type = qla2x00_change_queue_type, .this_id = -1, @@ -287,7 +291,7 @@ qla24xx_pci_info_str(struct scsi_qla_host *ha, char *str) return str; } -char * +static char * qla2x00_fw_version_str(struct scsi_qla_host *ha, char *str) { char un_str[10]; @@ -325,7 +329,7 @@ qla2x00_fw_version_str(struct scsi_qla_host *ha, char *str) return (str); } -char * +static char * qla24xx_fw_version_str(struct scsi_qla_host *ha, char *str) { sprintf(str, "%d.%02d.%02d ", ha->fw_major_version, @@ -634,7 +638,7 @@ qla2x00_block_error_handler(struct scsi_cmnd *cmnd) * Note: * Only return FAILED if command not returned by firmware. **************************************************************************/ -int +static int qla2xxx_eh_abort(struct scsi_cmnd *cmd) { scsi_qla_host_t *ha = to_qla_host(cmd->device->host); @@ -771,7 +775,7 @@ qla2x00_eh_wait_for_pending_target_commands(scsi_qla_host_t *ha, unsigned int t) * SUCCESS/FAILURE (defined as macro in scsi.h). * **************************************************************************/ -int +static int qla2xxx_eh_device_reset(struct scsi_cmnd *cmd) { scsi_qla_host_t *ha = to_qla_host(cmd->device->host); @@ -902,7 +906,7 @@ qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *ha) * SUCCESS/FAILURE (defined as macro in scsi.h). * **************************************************************************/ -int +static int qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd) { scsi_qla_host_t *ha = to_qla_host(cmd->device->host); @@ -963,7 +967,7 @@ qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd) * * Note: **************************************************************************/ -int +static int qla2xxx_eh_host_reset(struct scsi_cmnd *cmd) { scsi_qla_host_t *ha = to_qla_host(cmd->device->host); @@ -1366,6 +1370,29 @@ qla24xx_disable_intrs(scsi_qla_host_t *ha) spin_unlock_irqrestore(&ha->hardware_lock, flags); } +static void +qla2xxx_scan_start(struct Scsi_Host *shost) +{ + scsi_qla_host_t *ha = (scsi_qla_host_t *)shost->hostdata; + + set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags); + set_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags); + set_bit(RSCN_UPDATE, &ha->dpc_flags); +} + +static int +qla2xxx_scan_finished(struct Scsi_Host *shost, unsigned long time) +{ + scsi_qla_host_t *ha = (scsi_qla_host_t *)shost->hostdata; + + if (!ha->host) + return 1; + if (time > ha->loop_reset_delay * HZ) + return 1; + + return atomic_read(&ha->loop_state) == LOOP_READY; +} + /* * PCI driver interface */ @@ -1377,10 +1404,8 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) struct Scsi_Host *host; scsi_qla_host_t *ha; unsigned long flags = 0; - unsigned long wait_switch = 0; char pci_info[20]; char fw_str[30]; - fc_port_t *fcport; struct scsi_host_template *sht; if (pci_enable_device(pdev)) @@ -1631,30 +1656,19 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) ha->isp_ops.enable_intrs(ha); - /* v2.19.5b6 */ - /* - * Wait around max loop_reset_delay secs for the devices to come - * on-line. We don't want Linux scanning before we are ready. - * - */ - for (wait_switch = jiffies + (ha->loop_reset_delay * HZ); - time_before(jiffies,wait_switch) && - !(ha->device_flags & (DFLG_NO_CABLE | DFLG_FABRIC_DEVICES)) - && (ha->device_flags & SWITCH_FOUND) ;) { - - qla2x00_check_fabric_devices(ha); - - msleep(10); - } - pci_set_drvdata(pdev, ha); + ha->flags.init_done = 1; + ha->flags.online = 1; + num_hosts++; ret = scsi_add_host(host, &pdev->dev); if (ret) goto probe_failed; + scsi_scan_host(host); + qla2x00_alloc_sysfs_attr(ha); qla2x00_init_host_attr(ha); @@ -1669,10 +1683,6 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) ha->flags.enable_64bit_addressing ? '+': '-', ha->host_no, ha->isp_ops.fw_version_str(ha, fw_str)); - /* Go with fc_rport registration. */ - list_for_each_entry(fcport, &ha->fcports, list) - qla2x00_reg_remote_port(ha, fcport); - return 0; probe_failed: diff --git a/trunk/drivers/scsi/qla2xxx/qla_sup.c b/trunk/drivers/scsi/qla2xxx/qla_sup.c index c71dbd5bd543..15390ad87456 100644 --- a/trunk/drivers/scsi/qla2xxx/qla_sup.c +++ b/trunk/drivers/scsi/qla2xxx/qla_sup.c @@ -449,7 +449,7 @@ nvram_data_to_access_addr(uint32_t naddr) return FARX_ACCESS_NVRAM_DATA | naddr; } -uint32_t +static uint32_t qla24xx_read_flash_dword(scsi_qla_host_t *ha, uint32_t addr) { int rval; @@ -490,7 +490,7 @@ qla24xx_read_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr, return dwptr; } -int +static int qla24xx_write_flash_dword(scsi_qla_host_t *ha, uint32_t addr, uint32_t data) { int rval; @@ -512,7 +512,7 @@ qla24xx_write_flash_dword(scsi_qla_host_t *ha, uint32_t addr, uint32_t data) return rval; } -void +static void qla24xx_get_flash_manufacturer(scsi_qla_host_t *ha, uint8_t *man_id, uint8_t *flash_id) { @@ -537,7 +537,7 @@ qla24xx_get_flash_manufacturer(scsi_qla_host_t *ha, uint8_t *man_id, } } -int +static int qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr, uint32_t dwords) { diff --git a/trunk/drivers/scsi/qla4xxx/ql4_dbg.c b/trunk/drivers/scsi/qla4xxx/ql4_dbg.c index 752031fadfef..7b4e077a39c1 100644 --- a/trunk/drivers/scsi/qla4xxx/ql4_dbg.c +++ b/trunk/drivers/scsi/qla4xxx/ql4_dbg.c @@ -71,7 +71,7 @@ void __dump_registers(struct scsi_qla_host *ha) readw(&ha->reg->u1.isp4010.nvram)); } - else if (is_qla4022(ha)) { + else if (is_qla4022(ha) | is_qla4032(ha)) { printk(KERN_INFO "0x%02X intr_mask = 0x%08X\n", (uint8_t) offsetof(struct isp_reg, u1.isp4022.intr_mask), @@ -119,7 +119,7 @@ void __dump_registers(struct scsi_qla_host *ha) readw(&ha->reg->u2.isp4010.port_err_status)); } - else if (is_qla4022(ha)) { + else if (is_qla4022(ha) | is_qla4032(ha)) { printk(KERN_INFO "Page 0 Registers:\n"); printk(KERN_INFO "0x%02X ext_hw_conf = 0x%08X\n", (uint8_t) offsetof(struct isp_reg, diff --git a/trunk/drivers/scsi/qla4xxx/ql4_def.h b/trunk/drivers/scsi/qla4xxx/ql4_def.h index a7f6c7b1c590..4249e52a5592 100644 --- a/trunk/drivers/scsi/qla4xxx/ql4_def.h +++ b/trunk/drivers/scsi/qla4xxx/ql4_def.h @@ -40,7 +40,11 @@ #ifndef PCI_DEVICE_ID_QLOGIC_ISP4022 #define PCI_DEVICE_ID_QLOGIC_ISP4022 0x4022 -#endif /* */ +#endif + +#ifndef PCI_DEVICE_ID_QLOGIC_ISP4032 +#define PCI_DEVICE_ID_QLOGIC_ISP4032 0x4032 +#endif #define QLA_SUCCESS 0 #define QLA_ERROR 1 @@ -277,7 +281,6 @@ struct scsi_qla_host { #define AF_INTERRUPTS_ON 6 /* 0x00000040 Not Used */ #define AF_GET_CRASH_RECORD 7 /* 0x00000080 */ #define AF_LINK_UP 8 /* 0x00000100 */ -#define AF_TOPCAT_CHIP_PRESENT 9 /* 0x00000200 */ #define AF_IRQ_ATTACHED 10 /* 0x00000400 */ #define AF_ISNS_CMD_IN_PROCESS 12 /* 0x00001000 */ #define AF_ISNS_CMD_DONE 13 /* 0x00002000 */ @@ -317,16 +320,17 @@ struct scsi_qla_host { /* NVRAM registers */ struct eeprom_data *nvram; spinlock_t hardware_lock ____cacheline_aligned; - spinlock_t list_lock; uint32_t eeprom_cmd_data; /* Counters for general statistics */ + uint64_t isr_count; uint64_t adapter_error_count; uint64_t device_error_count; uint64_t total_io_count; uint64_t total_mbytes_xferred; uint64_t link_failure_count; uint64_t invalid_crc_count; + uint32_t bytes_xfered; uint32_t spurious_int_count; uint32_t aborted_io_count; uint32_t io_timeout_count; @@ -438,6 +442,11 @@ static inline int is_qla4022(struct scsi_qla_host *ha) return ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP4022; } +static inline int is_qla4032(struct scsi_qla_host *ha) +{ + return ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP4032; +} + static inline int adapter_up(struct scsi_qla_host *ha) { return (test_bit(AF_ONLINE, &ha->flags) != 0) && @@ -451,58 +460,58 @@ static inline struct scsi_qla_host* to_qla_host(struct Scsi_Host *shost) static inline void __iomem* isp_semaphore(struct scsi_qla_host *ha) { - return (is_qla4022(ha) ? - &ha->reg->u1.isp4022.semaphore : - &ha->reg->u1.isp4010.nvram); + return (is_qla4010(ha) ? + &ha->reg->u1.isp4010.nvram : + &ha->reg->u1.isp4022.semaphore); } static inline void __iomem* isp_nvram(struct scsi_qla_host *ha) { - return (is_qla4022(ha) ? - &ha->reg->u1.isp4022.nvram : - &ha->reg->u1.isp4010.nvram); + return (is_qla4010(ha) ? + &ha->reg->u1.isp4010.nvram : + &ha->reg->u1.isp4022.nvram); } static inline void __iomem* isp_ext_hw_conf(struct scsi_qla_host *ha) { - return (is_qla4022(ha) ? - &ha->reg->u2.isp4022.p0.ext_hw_conf : - &ha->reg->u2.isp4010.ext_hw_conf); + return (is_qla4010(ha) ? + &ha->reg->u2.isp4010.ext_hw_conf : + &ha->reg->u2.isp4022.p0.ext_hw_conf); } static inline void __iomem* isp_port_status(struct scsi_qla_host *ha) { - return (is_qla4022(ha) ? - &ha->reg->u2.isp4022.p0.port_status : - &ha->reg->u2.isp4010.port_status); + return (is_qla4010(ha) ? + &ha->reg->u2.isp4010.port_status : + &ha->reg->u2.isp4022.p0.port_status); } static inline void __iomem* isp_port_ctrl(struct scsi_qla_host *ha) { - return (is_qla4022(ha) ? - &ha->reg->u2.isp4022.p0.port_ctrl : - &ha->reg->u2.isp4010.port_ctrl); + return (is_qla4010(ha) ? + &ha->reg->u2.isp4010.port_ctrl : + &ha->reg->u2.isp4022.p0.port_ctrl); } static inline void __iomem* isp_port_error_status(struct scsi_qla_host *ha) { - return (is_qla4022(ha) ? - &ha->reg->u2.isp4022.p0.port_err_status : - &ha->reg->u2.isp4010.port_err_status); + return (is_qla4010(ha) ? + &ha->reg->u2.isp4010.port_err_status : + &ha->reg->u2.isp4022.p0.port_err_status); } static inline void __iomem * isp_gp_out(struct scsi_qla_host *ha) { - return (is_qla4022(ha) ? - &ha->reg->u2.isp4022.p0.gp_out : - &ha->reg->u2.isp4010.gp_out); + return (is_qla4010(ha) ? + &ha->reg->u2.isp4010.gp_out : + &ha->reg->u2.isp4022.p0.gp_out); } static inline int eeprom_ext_hw_conf_offset(struct scsi_qla_host *ha) { - return (is_qla4022(ha) ? - offsetof(struct eeprom_data, isp4022.ext_hw_conf) / 2 : - offsetof(struct eeprom_data, isp4010.ext_hw_conf) / 2); + return (is_qla4010(ha) ? + offsetof(struct eeprom_data, isp4010.ext_hw_conf) / 2 : + offsetof(struct eeprom_data, isp4022.ext_hw_conf) / 2); } int ql4xxx_sem_spinlock(struct scsi_qla_host * ha, u32 sem_mask, u32 sem_bits); @@ -511,59 +520,59 @@ int ql4xxx_sem_lock(struct scsi_qla_host * ha, u32 sem_mask, u32 sem_bits); static inline int ql4xxx_lock_flash(struct scsi_qla_host *a) { - if (is_qla4022(a)) + if (is_qla4010(a)) + return ql4xxx_sem_spinlock(a, QL4010_FLASH_SEM_MASK, + QL4010_FLASH_SEM_BITS); + else return ql4xxx_sem_spinlock(a, QL4022_FLASH_SEM_MASK, (QL4022_RESOURCE_BITS_BASE_CODE | (a->mac_index)) << 13); - else - return ql4xxx_sem_spinlock(a, QL4010_FLASH_SEM_MASK, - QL4010_FLASH_SEM_BITS); } static inline void ql4xxx_unlock_flash(struct scsi_qla_host *a) { - if (is_qla4022(a)) - ql4xxx_sem_unlock(a, QL4022_FLASH_SEM_MASK); - else + if (is_qla4010(a)) ql4xxx_sem_unlock(a, QL4010_FLASH_SEM_MASK); + else + ql4xxx_sem_unlock(a, QL4022_FLASH_SEM_MASK); } static inline int ql4xxx_lock_nvram(struct scsi_qla_host *a) { - if (is_qla4022(a)) + if (is_qla4010(a)) + return ql4xxx_sem_spinlock(a, QL4010_NVRAM_SEM_MASK, + QL4010_NVRAM_SEM_BITS); + else return ql4xxx_sem_spinlock(a, QL4022_NVRAM_SEM_MASK, (QL4022_RESOURCE_BITS_BASE_CODE | (a->mac_index)) << 10); - else - return ql4xxx_sem_spinlock(a, QL4010_NVRAM_SEM_MASK, - QL4010_NVRAM_SEM_BITS); } static inline void ql4xxx_unlock_nvram(struct scsi_qla_host *a) { - if (is_qla4022(a)) - ql4xxx_sem_unlock(a, QL4022_NVRAM_SEM_MASK); - else + if (is_qla4010(a)) ql4xxx_sem_unlock(a, QL4010_NVRAM_SEM_MASK); + else + ql4xxx_sem_unlock(a, QL4022_NVRAM_SEM_MASK); } static inline int ql4xxx_lock_drvr(struct scsi_qla_host *a) { - if (is_qla4022(a)) + if (is_qla4010(a)) + return ql4xxx_sem_lock(a, QL4010_DRVR_SEM_MASK, + QL4010_DRVR_SEM_BITS); + else return ql4xxx_sem_lock(a, QL4022_DRVR_SEM_MASK, (QL4022_RESOURCE_BITS_BASE_CODE | (a->mac_index)) << 1); - else - return ql4xxx_sem_lock(a, QL4010_DRVR_SEM_MASK, - QL4010_DRVR_SEM_BITS); } static inline void ql4xxx_unlock_drvr(struct scsi_qla_host *a) { - if (is_qla4022(a)) - ql4xxx_sem_unlock(a, QL4022_DRVR_SEM_MASK); - else + if (is_qla4010(a)) ql4xxx_sem_unlock(a, QL4010_DRVR_SEM_MASK); + else + ql4xxx_sem_unlock(a, QL4022_DRVR_SEM_MASK); } /*---------------------------------------------------------------------------*/ diff --git a/trunk/drivers/scsi/qla4xxx/ql4_fw.h b/trunk/drivers/scsi/qla4xxx/ql4_fw.h index 427489de64bc..4eea8c571916 100644 --- a/trunk/drivers/scsi/qla4xxx/ql4_fw.h +++ b/trunk/drivers/scsi/qla4xxx/ql4_fw.h @@ -296,7 +296,6 @@ static inline uint32_t clr_rmask(uint32_t val) /* ISP Semaphore definitions */ /* ISP General Purpose Output definitions */ -#define GPOR_TOPCAT_RESET 0x00000004 /* shadow registers (DMA'd from HA to system memory. read only) */ struct shadow_regs { @@ -339,10 +338,13 @@ union external_hw_config_reg { /* Mailbox command definitions */ #define MBOX_CMD_ABOUT_FW 0x0009 #define MBOX_CMD_LUN_RESET 0x0016 +#define MBOX_CMD_GET_MANAGEMENT_DATA 0x001E #define MBOX_CMD_GET_FW_STATUS 0x001F #define MBOX_CMD_SET_ISNS_SERVICE 0x0021 #define ISNS_DISABLE 0 #define ISNS_ENABLE 1 +#define MBOX_CMD_COPY_FLASH 0x0024 +#define MBOX_CMD_WRITE_FLASH 0x0025 #define MBOX_CMD_READ_FLASH 0x0026 #define MBOX_CMD_CLEAR_DATABASE_ENTRY 0x0031 #define MBOX_CMD_CONN_CLOSE_SESS_LOGOUT 0x0056 @@ -360,10 +362,13 @@ union external_hw_config_reg { #define DDB_DS_SESSION_FAILED 0x06 #define DDB_DS_LOGIN_IN_PROCESS 0x07 #define MBOX_CMD_GET_FW_STATE 0x0069 +#define MBOX_CMD_GET_INIT_FW_CTRL_BLOCK_DEFAULTS 0x006A +#define MBOX_CMD_RESTORE_FACTORY_DEFAULTS 0x0087 /* Mailbox 1 */ #define FW_STATE_READY 0x0000 #define FW_STATE_CONFIG_WAIT 0x0001 +#define FW_STATE_WAIT_LOGIN 0x0002 #define FW_STATE_ERROR 0x0004 #define FW_STATE_DHCP_IN_PROGRESS 0x0008 diff --git a/trunk/drivers/scsi/qla4xxx/ql4_glbl.h b/trunk/drivers/scsi/qla4xxx/ql4_glbl.h index 1b221ff0f6f7..2122967bbf0b 100644 --- a/trunk/drivers/scsi/qla4xxx/ql4_glbl.h +++ b/trunk/drivers/scsi/qla4xxx/ql4_glbl.h @@ -8,6 +8,7 @@ #ifndef __QLA4x_GBL_H #define __QLA4x_GBL_H +int ql4xxx_lock_drvr_wait(struct scsi_qla_host *a); int qla4xxx_send_tgts(struct scsi_qla_host *ha, char *ip, uint16_t port); int qla4xxx_send_command_to_isp(struct scsi_qla_host *ha, struct srb * srb); int qla4xxx_initialize_adapter(struct scsi_qla_host * ha, @@ -75,4 +76,4 @@ int qla4xxx_process_ddb_changed(struct scsi_qla_host * ha, extern int ql4xextended_error_logging; extern int ql4xdiscoverywait; extern int ql4xdontresethba; -#endif /* _QLA4x_GBL_H */ +#endif /* _QLA4x_GBL_H */ diff --git a/trunk/drivers/scsi/qla4xxx/ql4_init.c b/trunk/drivers/scsi/qla4xxx/ql4_init.c index bb3a1c11f44c..cc210f297a78 100644 --- a/trunk/drivers/scsi/qla4xxx/ql4_init.c +++ b/trunk/drivers/scsi/qla4xxx/ql4_init.c @@ -259,10 +259,16 @@ static int qla4xxx_fw_ready(struct scsi_qla_host *ha) "seconds expired= %d\n", ha->host_no, __func__, ha->firmware_state, ha->addl_fw_state, timeout_count)); + if (is_qla4032(ha) && + !(ha->addl_fw_state & FW_ADDSTATE_LINK_UP) && + (timeout_count < ADAPTER_INIT_TOV - 5)) { + break; + } + msleep(1000); } /* end of for */ - if (timeout_count <= 0) + if (timeout_count == 0) DEBUG2(printk("scsi%ld: %s: FW Initialization timed out!\n", ha->host_no, __func__)); @@ -806,32 +812,6 @@ int qla4xxx_relogin_device(struct scsi_qla_host *ha, return QLA_SUCCESS; } -/** - * qla4010_get_topcat_presence - check if it is QLA4040 TopCat Chip - * @ha: Pointer to host adapter structure. - * - **/ -static int qla4010_get_topcat_presence(struct scsi_qla_host *ha) -{ - unsigned long flags; - uint16_t topcat; - - if (ql4xxx_lock_nvram(ha) != QLA_SUCCESS) - return QLA_ERROR; - spin_lock_irqsave(&ha->hardware_lock, flags); - topcat = rd_nvram_word(ha, offsetof(struct eeprom_data, - isp4010.topcat)); - spin_unlock_irqrestore(&ha->hardware_lock, flags); - - if ((topcat & TOPCAT_MASK) == TOPCAT_PRESENT) - set_bit(AF_TOPCAT_CHIP_PRESENT, &ha->flags); - else - clear_bit(AF_TOPCAT_CHIP_PRESENT, &ha->flags); - ql4xxx_unlock_nvram(ha); - return QLA_SUCCESS; -} - - static int qla4xxx_config_nvram(struct scsi_qla_host *ha) { unsigned long flags; @@ -866,7 +846,7 @@ static int qla4xxx_config_nvram(struct scsi_qla_host *ha) /* set defaults */ if (is_qla4010(ha)) extHwConfig.Asuint32_t = 0x1912; - else if (is_qla4022(ha)) + else if (is_qla4022(ha) | is_qla4032(ha)) extHwConfig.Asuint32_t = 0x0023; } DEBUG(printk("scsi%ld: %s: Setting extHwConfig to 0xFFFF%04x\n", @@ -927,7 +907,7 @@ static int qla4xxx_start_firmware_from_flash(struct scsi_qla_host *ha) spin_lock_irqsave(&ha->hardware_lock, flags); writel(jiffies, &ha->reg->mailbox[7]); - if (is_qla4022(ha)) + if (is_qla4022(ha) | is_qla4032(ha)) writel(set_rmask(NVR_WRITE_ENABLE), &ha->reg->u1.isp4022.nvram); @@ -978,7 +958,7 @@ static int qla4xxx_start_firmware_from_flash(struct scsi_qla_host *ha) return status; } -static int ql4xxx_lock_drvr_wait(struct scsi_qla_host *a) +int ql4xxx_lock_drvr_wait(struct scsi_qla_host *a) { #define QL4_LOCK_DRVR_WAIT 300 #define QL4_LOCK_DRVR_SLEEP 100 @@ -1018,12 +998,7 @@ static int qla4xxx_start_firmware(struct scsi_qla_host *ha) int soft_reset = 1; int config_chip = 0; - if (is_qla4010(ha)){ - if (qla4010_get_topcat_presence(ha) != QLA_SUCCESS) - return QLA_ERROR; - } - - if (is_qla4022(ha)) + if (is_qla4022(ha) | is_qla4032(ha)) ql4xxx_set_mac_number(ha); if (ql4xxx_lock_drvr_wait(ha) != QLA_SUCCESS) diff --git a/trunk/drivers/scsi/qla4xxx/ql4_inline.h b/trunk/drivers/scsi/qla4xxx/ql4_inline.h index 0d61797af7da..6375eb017dd3 100644 --- a/trunk/drivers/scsi/qla4xxx/ql4_inline.h +++ b/trunk/drivers/scsi/qla4xxx/ql4_inline.h @@ -38,7 +38,7 @@ qla4xxx_lookup_ddb_by_fw_index(struct scsi_qla_host *ha, uint32_t fw_ddb_index) static inline void __qla4xxx_enable_intrs(struct scsi_qla_host *ha) { - if (is_qla4022(ha)) { + if (is_qla4022(ha) | is_qla4032(ha)) { writel(set_rmask(IMR_SCSI_INTR_ENABLE), &ha->reg->u1.isp4022.intr_mask); readl(&ha->reg->u1.isp4022.intr_mask); @@ -52,7 +52,7 @@ __qla4xxx_enable_intrs(struct scsi_qla_host *ha) static inline void __qla4xxx_disable_intrs(struct scsi_qla_host *ha) { - if (is_qla4022(ha)) { + if (is_qla4022(ha) | is_qla4032(ha)) { writel(clr_rmask(IMR_SCSI_INTR_ENABLE), &ha->reg->u1.isp4022.intr_mask); readl(&ha->reg->u1.isp4022.intr_mask); diff --git a/trunk/drivers/scsi/qla4xxx/ql4_iocb.c b/trunk/drivers/scsi/qla4xxx/ql4_iocb.c index c0a254b89a30..d41ce380eedc 100644 --- a/trunk/drivers/scsi/qla4xxx/ql4_iocb.c +++ b/trunk/drivers/scsi/qla4xxx/ql4_iocb.c @@ -294,6 +294,12 @@ int qla4xxx_send_command_to_isp(struct scsi_qla_host *ha, struct srb * srb) cmd_entry->control_flags = CF_WRITE; else if (cmd->sc_data_direction == DMA_FROM_DEVICE) cmd_entry->control_flags = CF_READ; + + ha->bytes_xfered += cmd->request_bufflen; + if (ha->bytes_xfered & ~0xFFFFF){ + ha->total_mbytes_xferred += ha->bytes_xfered >> 20; + ha->bytes_xfered &= 0xFFFFF; + } } /* Set tagged queueing control flags */ diff --git a/trunk/drivers/scsi/qla4xxx/ql4_isr.c b/trunk/drivers/scsi/qla4xxx/ql4_isr.c index 1e283321a59d..ef975e0dc87f 100644 --- a/trunk/drivers/scsi/qla4xxx/ql4_isr.c +++ b/trunk/drivers/scsi/qla4xxx/ql4_isr.c @@ -627,6 +627,7 @@ irqreturn_t qla4xxx_intr_handler(int irq, void *dev_id) spin_lock_irqsave(&ha->hardware_lock, flags); + ha->isr_count++; /* * Repeatedly service interrupts up to a maximum of * MAX_REQS_SERVICED_PER_INTR diff --git a/trunk/drivers/scsi/qla4xxx/ql4_nvram.c b/trunk/drivers/scsi/qla4xxx/ql4_nvram.c index e3957ca5b645..58afd135aa1d 100644 --- a/trunk/drivers/scsi/qla4xxx/ql4_nvram.c +++ b/trunk/drivers/scsi/qla4xxx/ql4_nvram.c @@ -7,15 +7,22 @@ #include "ql4_def.h" +static inline void eeprom_cmd(uint32_t cmd, struct scsi_qla_host *ha) +{ + writel(cmd, isp_nvram(ha)); + readl(isp_nvram(ha)); + udelay(1); +} + static inline int eeprom_size(struct scsi_qla_host *ha) { - return is_qla4022(ha) ? FM93C86A_SIZE_16 : FM93C66A_SIZE_16; + return is_qla4010(ha) ? FM93C66A_SIZE_16 : FM93C86A_SIZE_16; } static inline int eeprom_no_addr_bits(struct scsi_qla_host *ha) { - return is_qla4022(ha) ? FM93C86A_NO_ADDR_BITS_16 : - FM93C56A_NO_ADDR_BITS_16; + return is_qla4010(ha) ? FM93C56A_NO_ADDR_BITS_16 : + FM93C86A_NO_ADDR_BITS_16 ; } static inline int eeprom_no_data_bits(struct scsi_qla_host *ha) @@ -28,8 +35,7 @@ static int fm93c56a_select(struct scsi_qla_host * ha) DEBUG5(printk(KERN_ERR "fm93c56a_select:\n")); ha->eeprom_cmd_data = AUBURN_EEPROM_CS_1 | 0x000f0000; - writel(ha->eeprom_cmd_data, isp_nvram(ha)); - readl(isp_nvram(ha)); + eeprom_cmd(ha->eeprom_cmd_data, ha); return 1; } @@ -41,12 +47,13 @@ static int fm93c56a_cmd(struct scsi_qla_host * ha, int cmd, int addr) int previousBit; /* Clock in a zero, then do the start bit. */ - writel(ha->eeprom_cmd_data | AUBURN_EEPROM_DO_1, isp_nvram(ha)); - writel(ha->eeprom_cmd_data | AUBURN_EEPROM_DO_1 | - AUBURN_EEPROM_CLK_RISE, isp_nvram(ha)); - writel(ha->eeprom_cmd_data | AUBURN_EEPROM_DO_1 | - AUBURN_EEPROM_CLK_FALL, isp_nvram(ha)); - readl(isp_nvram(ha)); + eeprom_cmd(ha->eeprom_cmd_data | AUBURN_EEPROM_DO_1, ha); + + eeprom_cmd(ha->eeprom_cmd_data | AUBURN_EEPROM_DO_1 | + AUBURN_EEPROM_CLK_RISE, ha); + eeprom_cmd(ha->eeprom_cmd_data | AUBURN_EEPROM_DO_1 | + AUBURN_EEPROM_CLK_FALL, ha); + mask = 1 << (FM93C56A_CMD_BITS - 1); /* Force the previous data bit to be different. */ @@ -60,14 +67,14 @@ static int fm93c56a_cmd(struct scsi_qla_host * ha, int cmd, int addr) * If the bit changed, then change the DO state to * match. */ - writel(ha->eeprom_cmd_data | dataBit, isp_nvram(ha)); + eeprom_cmd(ha->eeprom_cmd_data | dataBit, ha); previousBit = dataBit; } - writel(ha->eeprom_cmd_data | dataBit | - AUBURN_EEPROM_CLK_RISE, isp_nvram(ha)); - writel(ha->eeprom_cmd_data | dataBit | - AUBURN_EEPROM_CLK_FALL, isp_nvram(ha)); - readl(isp_nvram(ha)); + eeprom_cmd(ha->eeprom_cmd_data | dataBit | + AUBURN_EEPROM_CLK_RISE, ha); + eeprom_cmd(ha->eeprom_cmd_data | dataBit | + AUBURN_EEPROM_CLK_FALL, ha); + cmd = cmd << 1; } mask = 1 << (eeprom_no_addr_bits(ha) - 1); @@ -82,14 +89,15 @@ static int fm93c56a_cmd(struct scsi_qla_host * ha, int cmd, int addr) * If the bit changed, then change the DO state to * match. */ - writel(ha->eeprom_cmd_data | dataBit, isp_nvram(ha)); + eeprom_cmd(ha->eeprom_cmd_data | dataBit, ha); + previousBit = dataBit; } - writel(ha->eeprom_cmd_data | dataBit | - AUBURN_EEPROM_CLK_RISE, isp_nvram(ha)); - writel(ha->eeprom_cmd_data | dataBit | - AUBURN_EEPROM_CLK_FALL, isp_nvram(ha)); - readl(isp_nvram(ha)); + eeprom_cmd(ha->eeprom_cmd_data | dataBit | + AUBURN_EEPROM_CLK_RISE, ha); + eeprom_cmd(ha->eeprom_cmd_data | dataBit | + AUBURN_EEPROM_CLK_FALL, ha); + addr = addr << 1; } return 1; @@ -98,8 +106,7 @@ static int fm93c56a_cmd(struct scsi_qla_host * ha, int cmd, int addr) static int fm93c56a_deselect(struct scsi_qla_host * ha) { ha->eeprom_cmd_data = AUBURN_EEPROM_CS_0 | 0x000f0000; - writel(ha->eeprom_cmd_data, isp_nvram(ha)); - readl(isp_nvram(ha)); + eeprom_cmd(ha->eeprom_cmd_data, ha); return 1; } @@ -112,12 +119,13 @@ static int fm93c56a_datain(struct scsi_qla_host * ha, unsigned short *value) /* Read the data bits * The first bit is a dummy. Clock right over it. */ for (i = 0; i < eeprom_no_data_bits(ha); i++) { - writel(ha->eeprom_cmd_data | - AUBURN_EEPROM_CLK_RISE, isp_nvram(ha)); - writel(ha->eeprom_cmd_data | - AUBURN_EEPROM_CLK_FALL, isp_nvram(ha)); - dataBit = - (readw(isp_nvram(ha)) & AUBURN_EEPROM_DI_1) ? 1 : 0; + eeprom_cmd(ha->eeprom_cmd_data | + AUBURN_EEPROM_CLK_RISE, ha); + eeprom_cmd(ha->eeprom_cmd_data | + AUBURN_EEPROM_CLK_FALL, ha); + + dataBit = (readw(isp_nvram(ha)) & AUBURN_EEPROM_DI_1) ? 1 : 0; + data = (data << 1) | dataBit; } diff --git a/trunk/drivers/scsi/qla4xxx/ql4_nvram.h b/trunk/drivers/scsi/qla4xxx/ql4_nvram.h index 08e2aed8c6cc..b47b4fc59d83 100644 --- a/trunk/drivers/scsi/qla4xxx/ql4_nvram.h +++ b/trunk/drivers/scsi/qla4xxx/ql4_nvram.h @@ -134,9 +134,7 @@ struct eeprom_data { u16 phyConfig; /* x36 */ #define PHY_CONFIG_PHY_ADDR_MASK 0x1f #define PHY_CONFIG_ENABLE_FW_MANAGEMENT_MASK 0x20 - u16 topcat; /* x38 */ -#define TOPCAT_PRESENT 0x0100 -#define TOPCAT_MASK 0xFF00 + u16 reserved_56; /* x38 */ #define EEPROM_UNUSED_1_SIZE 2 u8 unused_1[EEPROM_UNUSED_1_SIZE]; /* x3A */ diff --git a/trunk/drivers/scsi/qla4xxx/ql4_os.c b/trunk/drivers/scsi/qla4xxx/ql4_os.c index 5b8db6109536..9ef693c8809a 100644 --- a/trunk/drivers/scsi/qla4xxx/ql4_os.c +++ b/trunk/drivers/scsi/qla4xxx/ql4_os.c @@ -19,7 +19,7 @@ char qla4xxx_version_str[40]; /* * SRB allocation cache */ -static kmem_cache_t *srb_cachep; +static struct kmem_cache *srb_cachep; /* * Module parameter information and variables @@ -708,10 +708,10 @@ static int qla4xxx_cmd_wait(struct scsi_qla_host *ha) } /** - * qla4010_soft_reset - performs soft reset. + * qla4xxx_soft_reset - performs soft reset. * @ha: Pointer to host adapter structure. **/ -static int qla4010_soft_reset(struct scsi_qla_host *ha) +int qla4xxx_soft_reset(struct scsi_qla_host *ha) { uint32_t max_wait_time; unsigned long flags = 0; @@ -816,29 +816,6 @@ static int qla4010_soft_reset(struct scsi_qla_host *ha) return status; } -/** - * qla4xxx_topcat_reset - performs hard reset of TopCat Chip. - * @ha: Pointer to host adapter structure. - **/ -static int qla4xxx_topcat_reset(struct scsi_qla_host *ha) -{ - unsigned long flags; - - ql4xxx_lock_nvram(ha); - spin_lock_irqsave(&ha->hardware_lock, flags); - writel(set_rmask(GPOR_TOPCAT_RESET), isp_gp_out(ha)); - readl(isp_gp_out(ha)); - mdelay(1); - - writel(clr_rmask(GPOR_TOPCAT_RESET), isp_gp_out(ha)); - readl(isp_gp_out(ha)); - spin_unlock_irqrestore(&ha->hardware_lock, flags); - mdelay(2523); - - ql4xxx_unlock_nvram(ha); - return QLA_SUCCESS; -} - /** * qla4xxx_flush_active_srbs - returns all outstanding i/o requests to O.S. * @ha: Pointer to host adapter structure. @@ -866,26 +843,6 @@ static void qla4xxx_flush_active_srbs(struct scsi_qla_host *ha) } -/** - * qla4xxx_hard_reset - performs HBA Hard Reset - * @ha: Pointer to host adapter structure. - **/ -static int qla4xxx_hard_reset(struct scsi_qla_host *ha) -{ - /* The QLA4010 really doesn't have an equivalent to a hard reset */ - qla4xxx_flush_active_srbs(ha); - if (test_bit(AF_TOPCAT_CHIP_PRESENT, &ha->flags)) { - int status = QLA_ERROR; - - if ((qla4010_soft_reset(ha) == QLA_SUCCESS) && - (qla4xxx_topcat_reset(ha) == QLA_SUCCESS) && - (qla4010_soft_reset(ha) == QLA_SUCCESS)) - status = QLA_SUCCESS; - return status; - } else - return qla4010_soft_reset(ha); -} - /** * qla4xxx_recover_adapter - recovers adapter after a fatal error * @ha: Pointer to host adapter structure. @@ -919,18 +876,11 @@ static int qla4xxx_recover_adapter(struct scsi_qla_host *ha, if (status == QLA_SUCCESS) { DEBUG2(printk("scsi%ld: %s - Performing soft reset..\n", ha->host_no, __func__)); - status = qla4xxx_soft_reset(ha); - } - /* FIXMEkaren: Do we want to keep interrupts enabled and process - AENs after soft reset */ - - /* If firmware (SOFT) reset failed, or if all outstanding - * commands have not returned, then do a HARD reset. - */ - if (status == QLA_ERROR) { - DEBUG2(printk("scsi%ld: %s - Performing hard reset..\n", - ha->host_no, __func__)); - status = qla4xxx_hard_reset(ha); + qla4xxx_flush_active_srbs(ha); + if (ql4xxx_lock_drvr_wait(ha) == QLA_SUCCESS) + status = qla4xxx_soft_reset(ha); + else + status = QLA_ERROR; } /* Flush any pending ddb changed AENs */ @@ -1011,18 +961,15 @@ static int qla4xxx_recover_adapter(struct scsi_qla_host *ha, * the mid-level tries to sleep when it reaches the driver threshold * "host->can_queue". This can cause a panic if we were in our interrupt code. **/ -static void qla4xxx_do_dpc(void *data) +static void qla4xxx_do_dpc(struct work_struct *work) { - struct scsi_qla_host *ha = (struct scsi_qla_host *) data; + struct scsi_qla_host *ha = + container_of(work, struct scsi_qla_host, dpc_work); struct ddb_entry *ddb_entry, *dtemp; - DEBUG2(printk("scsi%ld: %s: DPC handler waking up.\n", - ha->host_no, __func__)); - - DEBUG2(printk("scsi%ld: %s: ha->flags = 0x%08lx\n", - ha->host_no, __func__, ha->flags)); - DEBUG2(printk("scsi%ld: %s: ha->dpc_flags = 0x%08lx\n", - ha->host_no, __func__, ha->dpc_flags)); + DEBUG2(printk("scsi%ld: %s: DPC handler waking up." + "flags = 0x%08lx, dpc_flags = 0x%08lx\n", + ha->host_no, __func__, ha->flags, ha->dpc_flags)); /* Initialization not yet finished. Don't do anything yet. */ if (!test_bit(AF_INIT_DONE, &ha->flags)) @@ -1032,16 +979,8 @@ static void qla4xxx_do_dpc(void *data) test_bit(DPC_RESET_HA, &ha->dpc_flags) || test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags) || test_bit(DPC_RESET_HA_DESTROY_DDB_LIST, &ha->dpc_flags)) { - if (test_bit(DPC_RESET_HA_DESTROY_DDB_LIST, &ha->dpc_flags)) - /* - * dg 09/23 Never initialize ddb list - * once we up and running - * qla4xxx_recover_adapter(ha, - * REBUILD_DDB_LIST); - */ - qla4xxx_recover_adapter(ha, PRESERVE_DDB_LIST); - - if (test_bit(DPC_RESET_HA, &ha->dpc_flags)) + if (test_bit(DPC_RESET_HA_DESTROY_DDB_LIST, &ha->dpc_flags) || + test_bit(DPC_RESET_HA, &ha->dpc_flags)) qla4xxx_recover_adapter(ha, PRESERVE_DDB_LIST); if (test_and_clear_bit(DPC_RESET_HA_INTR, &ha->dpc_flags)) { @@ -1122,7 +1061,8 @@ static void qla4xxx_free_adapter(struct scsi_qla_host *ha) destroy_workqueue(ha->dpc_thread); /* Issue Soft Reset to put firmware in unknown state */ - qla4xxx_soft_reset(ha); + if (ql4xxx_lock_drvr_wait(ha) == QLA_SUCCESS) + qla4xxx_soft_reset(ha); /* Remove timer thread, if present */ if (ha->timer_active) @@ -1261,7 +1201,6 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev, init_waitqueue_head(&ha->mailbox_wait_queue); spin_lock_init(&ha->hardware_lock); - spin_lock_init(&ha->list_lock); /* Allocate dma buffers */ if (qla4xxx_mem_alloc(ha)) { @@ -1315,7 +1254,7 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev, ret = -ENODEV; goto probe_failed; } - INIT_WORK(&ha->dpc_work, qla4xxx_do_dpc, ha); + INIT_WORK(&ha->dpc_work, qla4xxx_do_dpc); ret = request_irq(pdev->irq, qla4xxx_intr_handler, SA_INTERRUPT|SA_SHIRQ, "qla4xxx", ha); @@ -1467,27 +1406,6 @@ struct srb * qla4xxx_del_from_active_array(struct scsi_qla_host *ha, uint32_t in return srb; } -/** - * qla4xxx_soft_reset - performs a SOFT RESET of hba. - * @ha: Pointer to host adapter structure. - **/ -int qla4xxx_soft_reset(struct scsi_qla_host *ha) -{ - - DEBUG2(printk(KERN_WARNING "scsi%ld: %s: chip reset!\n", ha->host_no, - __func__)); - if (test_bit(AF_TOPCAT_CHIP_PRESENT, &ha->flags)) { - int status = QLA_ERROR; - - if ((qla4010_soft_reset(ha) == QLA_SUCCESS) && - (qla4xxx_topcat_reset(ha) == QLA_SUCCESS) && - (qla4010_soft_reset(ha) == QLA_SUCCESS) ) - status = QLA_SUCCESS; - return status; - } else - return qla4010_soft_reset(ha); -} - /** * qla4xxx_eh_wait_on_command - waits for command to be returned by firmware * @ha: actual ha whose done queue will contain the comd returned by firmware. @@ -1686,6 +1604,12 @@ static struct pci_device_id qla4xxx_pci_tbl[] = { .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, }, + { + .vendor = PCI_VENDOR_ID_QLOGIC, + .device = PCI_DEVICE_ID_QLOGIC_ISP4032, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + }, {0, 0}, }; MODULE_DEVICE_TABLE(pci, qla4xxx_pci_tbl); diff --git a/trunk/drivers/scsi/qla4xxx/ql4_version.h b/trunk/drivers/scsi/qla4xxx/ql4_version.h index b3fe7e68988e..454e19c8ad68 100644 --- a/trunk/drivers/scsi/qla4xxx/ql4_version.h +++ b/trunk/drivers/scsi/qla4xxx/ql4_version.h @@ -5,9 +5,4 @@ * See LICENSE.qla4xxx for copyright and licensing details. */ -#define QLA4XXX_DRIVER_VERSION "5.00.05b9-k" - -#define QL4_DRIVER_MAJOR_VER 5 -#define QL4_DRIVER_MINOR_VER 0 -#define QL4_DRIVER_PATCH_VER 5 -#define QL4_DRIVER_BETA_VER 9 +#define QLA4XXX_DRIVER_VERSION "5.00.07-k" diff --git a/trunk/drivers/scsi/scsi.c b/trunk/drivers/scsi/scsi.c index c59f31533ab4..24cffd98ee63 100644 --- a/trunk/drivers/scsi/scsi.c +++ b/trunk/drivers/scsi/scsi.c @@ -136,7 +136,7 @@ const char * scsi_device_type(unsigned type) EXPORT_SYMBOL(scsi_device_type); struct scsi_host_cmd_pool { - kmem_cache_t *slab; + struct kmem_cache *slab; unsigned int users; char *name; unsigned int slab_flags; @@ -156,8 +156,7 @@ static struct scsi_host_cmd_pool scsi_cmd_dma_pool = { static DEFINE_MUTEX(host_cmd_pool_mutex); -static struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *shost, - gfp_t gfp_mask) +struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *shost, gfp_t gfp_mask) { struct scsi_cmnd *cmd; @@ -178,6 +177,7 @@ static struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *shost, return cmd; } +EXPORT_SYMBOL_GPL(__scsi_get_command); /* * Function: scsi_get_command() @@ -214,9 +214,29 @@ struct scsi_cmnd *scsi_get_command(struct scsi_device *dev, gfp_t gfp_mask) put_device(&dev->sdev_gendev); return cmd; -} +} EXPORT_SYMBOL(scsi_get_command); +void __scsi_put_command(struct Scsi_Host *shost, struct scsi_cmnd *cmd, + struct device *dev) +{ + unsigned long flags; + + /* changing locks here, don't need to restore the irq state */ + spin_lock_irqsave(&shost->free_list_lock, flags); + if (unlikely(list_empty(&shost->free_list))) { + list_add(&cmd->list, &shost->free_list); + cmd = NULL; + } + spin_unlock_irqrestore(&shost->free_list_lock, flags); + + if (likely(cmd != NULL)) + kmem_cache_free(shost->cmd_pool->slab, cmd); + + put_device(dev); +} +EXPORT_SYMBOL(__scsi_put_command); + /* * Function: scsi_put_command() * @@ -231,26 +251,15 @@ EXPORT_SYMBOL(scsi_get_command); void scsi_put_command(struct scsi_cmnd *cmd) { struct scsi_device *sdev = cmd->device; - struct Scsi_Host *shost = sdev->host; unsigned long flags; - + /* serious error if the command hasn't come from a device list */ spin_lock_irqsave(&cmd->device->list_lock, flags); BUG_ON(list_empty(&cmd->list)); list_del_init(&cmd->list); - spin_unlock(&cmd->device->list_lock); - /* changing locks here, don't need to restore the irq state */ - spin_lock(&shost->free_list_lock); - if (unlikely(list_empty(&shost->free_list))) { - list_add(&cmd->list, &shost->free_list); - cmd = NULL; - } - spin_unlock_irqrestore(&shost->free_list_lock, flags); - - if (likely(cmd != NULL)) - kmem_cache_free(shost->cmd_pool->slab, cmd); + spin_unlock_irqrestore(&cmd->device->list_lock, flags); - put_device(&sdev->sdev_gendev); + __scsi_put_command(cmd->device->host, cmd, &sdev->sdev_gendev); } EXPORT_SYMBOL(scsi_put_command); @@ -871,9 +880,9 @@ EXPORT_SYMBOL(scsi_device_get); */ void scsi_device_put(struct scsi_device *sdev) { +#ifdef CONFIG_MODULE_UNLOAD struct module *module = sdev->host->hostt->module; -#ifdef CONFIG_MODULE_UNLOAD /* The module refcount will be zero if scsi_device_get() * was called from a module removal routine */ if (module && module_refcount(module) != 0) diff --git a/trunk/drivers/scsi/scsi_error.c b/trunk/drivers/scsi/scsi_error.c index aff1b0cfd4b2..2ecb6ff42444 100644 --- a/trunk/drivers/scsi/scsi_error.c +++ b/trunk/drivers/scsi/scsi_error.c @@ -453,9 +453,18 @@ static void scsi_eh_done(struct scsi_cmnd *scmd) } /** - * scsi_send_eh_cmnd - send a cmd to a device as part of error recovery. - * @scmd: SCSI Cmd to send. - * @timeout: Timeout for cmd. + * scsi_send_eh_cmnd - submit a scsi command as part of error recory + * @scmd: SCSI command structure to hijack + * @cmnd: CDB to send + * @cmnd_size: size in bytes of @cmnd + * @timeout: timeout for this request + * @copy_sense: request sense data if set to 1 + * + * This function is used to send a scsi command down to a target device + * as part of the error recovery process. If @copy_sense is 0 the command + * sent must be one that does not transfer any data. If @copy_sense is 1 + * the command must be REQUEST_SENSE and this functions copies out the + * sense buffer it got into @scmd->sense_buffer. * * Return value: * SUCCESS or FAILED or NEEDS_RETRY @@ -469,6 +478,7 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd, DECLARE_COMPLETION_ONSTACK(done); unsigned long timeleft; unsigned long flags; + struct scatterlist sgl; unsigned char old_cmnd[MAX_COMMAND_SIZE]; enum dma_data_direction old_data_direction; unsigned short old_use_sg; @@ -500,19 +510,24 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd, if (shost->hostt->unchecked_isa_dma) gfp_mask |= __GFP_DMA; - scmd->sc_data_direction = DMA_FROM_DEVICE; - scmd->request_bufflen = 252; - scmd->request_buffer = kzalloc(scmd->request_bufflen, gfp_mask); - if (!scmd->request_buffer) + sgl.page = alloc_page(gfp_mask); + if (!sgl.page) return FAILED; + sgl.offset = 0; + sgl.length = 252; + + scmd->sc_data_direction = DMA_FROM_DEVICE; + scmd->request_bufflen = sgl.length; + scmd->request_buffer = &sgl; + scmd->use_sg = 1; } else { scmd->request_buffer = NULL; scmd->request_bufflen = 0; scmd->sc_data_direction = DMA_NONE; + scmd->use_sg = 0; } scmd->underflow = 0; - scmd->use_sg = 0; scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]); if (sdev->scsi_level <= SCSI_2) @@ -583,7 +598,7 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd, memcpy(scmd->sense_buffer, scmd->request_buffer, sizeof(scmd->sense_buffer)); } - kfree(scmd->request_buffer); + __free_page(sgl.page); } diff --git a/trunk/drivers/scsi/scsi_lib.c b/trunk/drivers/scsi/scsi_lib.c index 3ac4890ce086..1748e27501cd 100644 --- a/trunk/drivers/scsi/scsi_lib.c +++ b/trunk/drivers/scsi/scsi_lib.c @@ -36,7 +36,7 @@ struct scsi_host_sg_pool { size_t size; char *name; - kmem_cache_t *slab; + struct kmem_cache *slab; mempool_t *pool; }; @@ -241,7 +241,7 @@ struct scsi_io_context { char sense[SCSI_SENSE_BUFFERSIZE]; }; -static kmem_cache_t *scsi_io_context_cache; +static struct kmem_cache *scsi_io_context_cache; static void scsi_end_async(struct request *req, int uptodate) { @@ -704,7 +704,7 @@ static struct scsi_cmnd *scsi_end_request(struct scsi_cmnd *cmd, int uptodate, return NULL; } -static struct scatterlist *scsi_alloc_sgtable(struct scsi_cmnd *cmd, gfp_t gfp_mask) +struct scatterlist *scsi_alloc_sgtable(struct scsi_cmnd *cmd, gfp_t gfp_mask) { struct scsi_host_sg_pool *sgp; struct scatterlist *sgl; @@ -745,7 +745,9 @@ static struct scatterlist *scsi_alloc_sgtable(struct scsi_cmnd *cmd, gfp_t gfp_m return sgl; } -static void scsi_free_sgtable(struct scatterlist *sgl, int index) +EXPORT_SYMBOL(scsi_alloc_sgtable); + +void scsi_free_sgtable(struct scatterlist *sgl, int index) { struct scsi_host_sg_pool *sgp; @@ -755,6 +757,8 @@ static void scsi_free_sgtable(struct scatterlist *sgl, int index) mempool_free(sgl, sgp->pool); } +EXPORT_SYMBOL(scsi_free_sgtable); + /* * Function: scsi_release_buffers() * @@ -996,25 +1000,14 @@ static int scsi_init_io(struct scsi_cmnd *cmd) int count; /* - * if this is a rq->data based REQ_BLOCK_PC, setup for a non-sg xfer - */ - if (blk_pc_request(req) && !req->bio) { - cmd->request_bufflen = req->data_len; - cmd->request_buffer = req->data; - req->buffer = req->data; - cmd->use_sg = 0; - return 0; - } - - /* - * we used to not use scatter-gather for single segment request, + * We used to not use scatter-gather for single segment request, * but now we do (it makes highmem I/O easier to support without * kmapping pages) */ cmd->use_sg = req->nr_phys_segments; /* - * if sg table allocation fails, requeue request later. + * If sg table allocation fails, requeue request later. */ sgpnt = scsi_alloc_sgtable(cmd, GFP_ATOMIC); if (unlikely(!sgpnt)) { @@ -1022,24 +1015,21 @@ static int scsi_init_io(struct scsi_cmnd *cmd) return BLKPREP_DEFER; } + req->buffer = NULL; cmd->request_buffer = (char *) sgpnt; - cmd->request_bufflen = req->nr_sectors << 9; if (blk_pc_request(req)) cmd->request_bufflen = req->data_len; - req->buffer = NULL; + else + cmd->request_bufflen = req->nr_sectors << 9; /* * Next, walk the list, and fill in the addresses and sizes of * each segment. */ count = blk_rq_map_sg(req->q, req, cmd->request_buffer); - - /* - * mapped well, send it off - */ if (likely(count <= cmd->use_sg)) { cmd->use_sg = count; - return 0; + return BLKPREP_OK; } printk(KERN_ERR "Incorrect number of segments after building list\n"); @@ -1069,6 +1059,27 @@ static int scsi_issue_flush_fn(request_queue_t *q, struct gendisk *disk, return -EOPNOTSUPP; } +static struct scsi_cmnd *scsi_get_cmd_from_req(struct scsi_device *sdev, + struct request *req) +{ + struct scsi_cmnd *cmd; + + if (!req->special) { + cmd = scsi_get_command(sdev, GFP_ATOMIC); + if (unlikely(!cmd)) + return NULL; + req->special = cmd; + } else { + cmd = req->special; + } + + /* pull a tag out of the request if we have one */ + cmd->tag = req->tag; + cmd->request = req; + + return cmd; +} + static void scsi_blk_pc_done(struct scsi_cmnd *cmd) { BUG_ON(!blk_pc_request(cmd->request)); @@ -1081,9 +1092,37 @@ static void scsi_blk_pc_done(struct scsi_cmnd *cmd) scsi_io_completion(cmd, cmd->request_bufflen); } -static void scsi_setup_blk_pc_cmnd(struct scsi_cmnd *cmd) +static int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req) { - struct request *req = cmd->request; + struct scsi_cmnd *cmd; + + cmd = scsi_get_cmd_from_req(sdev, req); + if (unlikely(!cmd)) + return BLKPREP_DEFER; + + /* + * BLOCK_PC requests may transfer data, in which case they must + * a bio attached to them. Or they might contain a SCSI command + * that does not transfer data, in which case they may optionally + * submit a request without an attached bio. + */ + if (req->bio) { + int ret; + + BUG_ON(!req->nr_phys_segments); + + ret = scsi_init_io(cmd); + if (unlikely(ret)) + return ret; + } else { + BUG_ON(req->data_len); + BUG_ON(req->data); + + cmd->request_bufflen = 0; + cmd->request_buffer = NULL; + cmd->use_sg = 0; + req->buffer = NULL; + } BUILD_BUG_ON(sizeof(req->cmd) > sizeof(cmd->cmnd)); memcpy(cmd->cmnd, req->cmd, sizeof(cmd->cmnd)); @@ -1099,154 +1138,138 @@ static void scsi_setup_blk_pc_cmnd(struct scsi_cmnd *cmd) cmd->allowed = req->retries; cmd->timeout_per_command = req->timeout; cmd->done = scsi_blk_pc_done; + return BLKPREP_OK; } -static int scsi_prep_fn(struct request_queue *q, struct request *req) +/* + * Setup a REQ_TYPE_FS command. These are simple read/write request + * from filesystems that still need to be translated to SCSI CDBs from + * the ULD. + */ +static int scsi_setup_fs_cmnd(struct scsi_device *sdev, struct request *req) { - struct scsi_device *sdev = q->queuedata; struct scsi_cmnd *cmd; - int specials_only = 0; + struct scsi_driver *drv; + int ret; /* - * Just check to see if the device is online. If it isn't, we - * refuse to process any commands. The device must be brought - * online before trying any recovery commands + * Filesystem requests must transfer data. */ - if (unlikely(!scsi_device_online(sdev))) { - sdev_printk(KERN_ERR, sdev, - "rejecting I/O to offline device\n"); - goto kill; - } - if (unlikely(sdev->sdev_state != SDEV_RUNNING)) { - /* OK, we're not in a running state don't prep - * user commands */ - if (sdev->sdev_state == SDEV_DEL) { - /* Device is fully deleted, no commands - * at all allowed down */ - sdev_printk(KERN_ERR, sdev, - "rejecting I/O to dead device\n"); - goto kill; - } - /* OK, we only allow special commands (i.e. not - * user initiated ones */ - specials_only = sdev->sdev_state; + BUG_ON(!req->nr_phys_segments); + + cmd = scsi_get_cmd_from_req(sdev, req); + if (unlikely(!cmd)) + return BLKPREP_DEFER; + + ret = scsi_init_io(cmd); + if (unlikely(ret)) + return ret; + + /* + * Initialize the actual SCSI command for this request. + */ + drv = *(struct scsi_driver **)req->rq_disk->private_data; + if (unlikely(!drv->init_command(cmd))) { + scsi_release_buffers(cmd); + scsi_put_command(cmd); + return BLKPREP_KILL; } + return BLKPREP_OK; +} + +static int scsi_prep_fn(struct request_queue *q, struct request *req) +{ + struct scsi_device *sdev = q->queuedata; + int ret = BLKPREP_OK; + /* - * Find the actual device driver associated with this command. - * The SPECIAL requests are things like character device or - * ioctls, which did not originate from ll_rw_blk. Note that - * the special field is also used to indicate the cmd for - * the remainder of a partially fulfilled request that can - * come up when there is a medium error. We have to treat - * these two cases differently. We differentiate by looking - * at request->cmd, as this tells us the real story. + * If the device is not in running state we will reject some + * or all commands. */ - if (blk_special_request(req) && req->special) - cmd = req->special; - else if (blk_pc_request(req) || blk_fs_request(req)) { - if (unlikely(specials_only) && !(req->cmd_flags & REQ_PREEMPT)){ - if (specials_only == SDEV_QUIESCE || - specials_only == SDEV_BLOCK) - goto defer; - + if (unlikely(sdev->sdev_state != SDEV_RUNNING)) { + switch (sdev->sdev_state) { + case SDEV_OFFLINE: + /* + * If the device is offline we refuse to process any + * commands. The device must be brought online + * before trying any recovery commands. + */ sdev_printk(KERN_ERR, sdev, - "rejecting I/O to device being removed\n"); - goto kill; + "rejecting I/O to offline device\n"); + ret = BLKPREP_KILL; + break; + case SDEV_DEL: + /* + * If the device is fully deleted, we refuse to + * process any commands as well. + */ + sdev_printk(KERN_ERR, sdev, + "rejecting I/O to dead device\n"); + ret = BLKPREP_KILL; + break; + case SDEV_QUIESCE: + case SDEV_BLOCK: + /* + * If the devices is blocked we defer normal commands. + */ + if (!(req->cmd_flags & REQ_PREEMPT)) + ret = BLKPREP_DEFER; + break; + default: + /* + * For any other not fully online state we only allow + * special commands. In particular any user initiated + * command is not allowed. + */ + if (!(req->cmd_flags & REQ_PREEMPT)) + ret = BLKPREP_KILL; + break; } - - /* - * Now try and find a command block that we can use. - */ - if (!req->special) { - cmd = scsi_get_command(sdev, GFP_ATOMIC); - if (unlikely(!cmd)) - goto defer; - } else - cmd = req->special; - - /* pull a tag out of the request if we have one */ - cmd->tag = req->tag; - } else { - blk_dump_rq_flags(req, "SCSI bad req"); - goto kill; + + if (ret != BLKPREP_OK) + goto out; } - - /* note the overloading of req->special. When the tag - * is active it always means cmd. If the tag goes - * back for re-queueing, it may be reset */ - req->special = cmd; - cmd->request = req; - - /* - * FIXME: drop the lock here because the functions below - * expect to be called without the queue lock held. Also, - * previously, we dequeued the request before dropping the - * lock. We hope REQ_STARTED prevents anything untoward from - * happening now. - */ - if (blk_fs_request(req) || blk_pc_request(req)) { - int ret; + switch (req->cmd_type) { + case REQ_TYPE_BLOCK_PC: + ret = scsi_setup_blk_pc_cmnd(sdev, req); + break; + case REQ_TYPE_FS: + ret = scsi_setup_fs_cmnd(sdev, req); + break; + default: /* - * This will do a couple of things: - * 1) Fill in the actual SCSI command. - * 2) Fill in any other upper-level specific fields - * (timeout). + * All other command types are not supported. * - * If this returns 0, it means that the request failed - * (reading past end of disk, reading offline device, - * etc). This won't actually talk to the device, but - * some kinds of consistency checking may cause the - * request to be rejected immediately. + * Note that these days the SCSI subsystem does not use + * REQ_TYPE_SPECIAL requests anymore. These are only used + * (directly or via blk_insert_request) by non-SCSI drivers. */ + blk_dump_rq_flags(req, "SCSI bad req"); + ret = BLKPREP_KILL; + break; + } - /* - * This sets up the scatter-gather table (allocating if - * required). - */ - ret = scsi_init_io(cmd); - switch(ret) { - /* For BLKPREP_KILL/DEFER the cmd was released */ - case BLKPREP_KILL: - goto kill; - case BLKPREP_DEFER: - goto defer; - } - + out: + switch (ret) { + case BLKPREP_KILL: + req->errors = DID_NO_CONNECT << 16; + break; + case BLKPREP_DEFER: /* - * Initialize the actual SCSI command for this request. + * If we defer, the elv_next_request() returns NULL, but the + * queue must be restarted, so we plug here if no returning + * command will automatically do that. */ - if (blk_pc_request(req)) { - scsi_setup_blk_pc_cmnd(cmd); - } else if (req->rq_disk) { - struct scsi_driver *drv; - - drv = *(struct scsi_driver **)req->rq_disk->private_data; - if (unlikely(!drv->init_command(cmd))) { - scsi_release_buffers(cmd); - scsi_put_command(cmd); - goto kill; - } - } + if (sdev->device_busy == 0) + blk_plug_device(q); + break; + default: + req->cmd_flags |= REQ_DONTPREP; } - /* - * The request is now prepped, no need to come back here - */ - req->cmd_flags |= REQ_DONTPREP; - return BLKPREP_OK; - - defer: - /* If we defer, the elv_next_request() returns NULL, but the - * queue must be restarted, so we plug here if no returning - * command will automatically do that. */ - if (sdev->device_busy == 0) - blk_plug_device(q); - return BLKPREP_DEFER; - kill: - req->errors = DID_NO_CONNECT << 16; - return BLKPREP_KILL; + return ret; } /* @@ -1548,29 +1571,40 @@ u64 scsi_calculate_bounce_limit(struct Scsi_Host *shost) } EXPORT_SYMBOL(scsi_calculate_bounce_limit); -struct request_queue *scsi_alloc_queue(struct scsi_device *sdev) +struct request_queue *__scsi_alloc_queue(struct Scsi_Host *shost, + request_fn_proc *request_fn) { - struct Scsi_Host *shost = sdev->host; struct request_queue *q; - q = blk_init_queue(scsi_request_fn, NULL); + q = blk_init_queue(request_fn, NULL); if (!q) return NULL; - blk_queue_prep_rq(q, scsi_prep_fn); - blk_queue_max_hw_segments(q, shost->sg_tablesize); blk_queue_max_phys_segments(q, SCSI_MAX_PHYS_SEGMENTS); blk_queue_max_sectors(q, shost->max_sectors); blk_queue_bounce_limit(q, scsi_calculate_bounce_limit(shost)); blk_queue_segment_boundary(q, shost->dma_boundary); - blk_queue_issue_flush_fn(q, scsi_issue_flush_fn); - blk_queue_softirq_done(q, scsi_softirq_done); if (!shost->use_clustering) clear_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags); return q; } +EXPORT_SYMBOL(__scsi_alloc_queue); + +struct request_queue *scsi_alloc_queue(struct scsi_device *sdev) +{ + struct request_queue *q; + + q = __scsi_alloc_queue(sdev->host, scsi_request_fn); + if (!q) + return NULL; + + blk_queue_prep_rq(q, scsi_prep_fn); + blk_queue_issue_flush_fn(q, scsi_issue_flush_fn); + blk_queue_softirq_done(q, scsi_softirq_done); + return q; +} void scsi_free_queue(struct request_queue *q) { diff --git a/trunk/drivers/scsi/scsi_priv.h b/trunk/drivers/scsi/scsi_priv.h index 5d023d44e5e7..f458c2f686d2 100644 --- a/trunk/drivers/scsi/scsi_priv.h +++ b/trunk/drivers/scsi/scsi_priv.h @@ -39,6 +39,9 @@ static inline void scsi_log_completion(struct scsi_cmnd *cmd, int disposition) { }; #endif +/* scsi_scan.c */ +int scsi_complete_async_scans(void); + /* scsi_devinfo.c */ extern int scsi_get_device_flags(struct scsi_device *sdev, const unsigned char *vendor, diff --git a/trunk/drivers/scsi/scsi_scan.c b/trunk/drivers/scsi/scsi_scan.c index 94a274645f6f..14e635aa44ce 100644 --- a/trunk/drivers/scsi/scsi_scan.c +++ b/trunk/drivers/scsi/scsi_scan.c @@ -29,7 +29,9 @@ #include #include #include -#include +#include +#include +#include #include #include @@ -87,6 +89,17 @@ module_param_named(max_luns, max_scsi_luns, int, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(max_luns, "last scsi LUN (should be between 1 and 2^32-1)"); +#ifdef CONFIG_SCSI_SCAN_ASYNC +#define SCSI_SCAN_TYPE_DEFAULT "async" +#else +#define SCSI_SCAN_TYPE_DEFAULT "sync" +#endif + +static char scsi_scan_type[6] = SCSI_SCAN_TYPE_DEFAULT; + +module_param_string(scan, scsi_scan_type, sizeof(scsi_scan_type), S_IRUGO); +MODULE_PARM_DESC(scan, "sync, async or none"); + /* * max_scsi_report_luns: the maximum number of LUNS that will be * returned from the REPORT LUNS command. 8 times this value must @@ -108,6 +121,68 @@ MODULE_PARM_DESC(inq_timeout, "Timeout (in seconds) waiting for devices to answer INQUIRY." " Default is 5. Some non-compliant devices need more."); +static DEFINE_SPINLOCK(async_scan_lock); +static LIST_HEAD(scanning_hosts); + +struct async_scan_data { + struct list_head list; + struct Scsi_Host *shost; + struct completion prev_finished; +}; + +/** + * scsi_complete_async_scans - Wait for asynchronous scans to complete + * + * Asynchronous scans add themselves to the scanning_hosts list. Once + * that list is empty, we know that the scans are complete. Rather than + * waking up periodically to check the state of the list, we pretend to be + * a scanning task by adding ourselves at the end of the list and going to + * sleep. When the task before us wakes us up, we take ourselves off the + * list and return. + */ +int scsi_complete_async_scans(void) +{ + struct async_scan_data *data; + + do { + if (list_empty(&scanning_hosts)) + return 0; + /* If we can't get memory immediately, that's OK. Just + * sleep a little. Even if we never get memory, the async + * scans will finish eventually. + */ + data = kmalloc(sizeof(*data), GFP_KERNEL); + if (!data) + msleep(1); + } while (!data); + + data->shost = NULL; + init_completion(&data->prev_finished); + + spin_lock(&async_scan_lock); + /* Check that there's still somebody else on the list */ + if (list_empty(&scanning_hosts)) + goto done; + list_add_tail(&data->list, &scanning_hosts); + spin_unlock(&async_scan_lock); + + printk(KERN_INFO "scsi: waiting for bus probes to complete ...\n"); + wait_for_completion(&data->prev_finished); + + spin_lock(&async_scan_lock); + list_del(&data->list); + done: + spin_unlock(&async_scan_lock); + + kfree(data); + return 0; +} + +#ifdef MODULE +/* Only exported for the benefit of scsi_wait_scan */ +EXPORT_SYMBOL_GPL(scsi_complete_async_scans); +#endif + /** * scsi_unlock_floptical - unlock device via a special MODE SENSE command * @sdev: scsi device to send command to @@ -362,9 +437,10 @@ static struct scsi_target *scsi_alloc_target(struct device *parent, goto retry; } -static void scsi_target_reap_usercontext(void *data) +static void scsi_target_reap_usercontext(struct work_struct *work) { - struct scsi_target *starget = data; + struct scsi_target *starget = + container_of(work, struct scsi_target, ew.work); struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); unsigned long flags; @@ -400,7 +476,7 @@ void scsi_target_reap(struct scsi_target *starget) starget->state = STARGET_DEL; spin_unlock_irqrestore(shost->host_lock, flags); execute_in_process_context(scsi_target_reap_usercontext, - starget, &starget->ew); + &starget->ew); return; } @@ -619,7 +695,7 @@ static int scsi_probe_lun(struct scsi_device *sdev, unsigned char *inq_result, * SCSI_SCAN_LUN_PRESENT: a new scsi_device was allocated and initialized **/ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result, - int *bflags) + int *bflags, int async) { /* * XXX do not save the inquiry, since it can change underneath us, @@ -805,7 +881,7 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result, * register it and tell the rest of the kernel * about it. */ - if (scsi_sysfs_add_sdev(sdev) != 0) + if (!async && scsi_sysfs_add_sdev(sdev) != 0) return SCSI_SCAN_NO_RESPONSE; return SCSI_SCAN_LUN_PRESENT; @@ -974,7 +1050,7 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget, goto out_free_result; } - res = scsi_add_lun(sdev, result, &bflags); + res = scsi_add_lun(sdev, result, &bflags, shost->async_scan); if (res == SCSI_SCAN_LUN_PRESENT) { if (bflags & BLIST_KEY) { sdev->lockable = 0; @@ -1474,6 +1550,12 @@ void scsi_scan_target(struct device *parent, unsigned int channel, { struct Scsi_Host *shost = dev_to_shost(parent); + if (strncmp(scsi_scan_type, "none", 4) == 0) + return; + + if (!shost->async_scan) + scsi_complete_async_scans(); + mutex_lock(&shost->scan_mutex); if (scsi_host_scan_allowed(shost)) __scsi_scan_target(parent, channel, id, lun, rescan); @@ -1519,6 +1601,9 @@ int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel, "%s: <%u:%u:%u>\n", __FUNCTION__, channel, id, lun)); + if (!shost->async_scan) + scsi_complete_async_scans(); + if (((channel != SCAN_WILD_CARD) && (channel > shost->max_channel)) || ((id != SCAN_WILD_CARD) && (id >= shost->max_id)) || ((lun != SCAN_WILD_CARD) && (lun > shost->max_lun))) @@ -1539,14 +1624,143 @@ int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel, return 0; } +static void scsi_sysfs_add_devices(struct Scsi_Host *shost) +{ + struct scsi_device *sdev; + shost_for_each_device(sdev, shost) { + if (scsi_sysfs_add_sdev(sdev) != 0) + scsi_destroy_sdev(sdev); + } +} + +/** + * scsi_prep_async_scan - prepare for an async scan + * @shost: the host which will be scanned + * Returns: a cookie to be passed to scsi_finish_async_scan() + * + * Tells the midlayer this host is going to do an asynchronous scan. + * It reserves the host's position in the scanning list and ensures + * that other asynchronous scans started after this one won't affect the + * ordering of the discovered devices. + */ +static struct async_scan_data *scsi_prep_async_scan(struct Scsi_Host *shost) +{ + struct async_scan_data *data; + + if (strncmp(scsi_scan_type, "sync", 4) == 0) + return NULL; + + if (shost->async_scan) { + printk("%s called twice for host %d", __FUNCTION__, + shost->host_no); + dump_stack(); + return NULL; + } + + data = kmalloc(sizeof(*data), GFP_KERNEL); + if (!data) + goto err; + data->shost = scsi_host_get(shost); + if (!data->shost) + goto err; + init_completion(&data->prev_finished); + + spin_lock(&async_scan_lock); + shost->async_scan = 1; + if (list_empty(&scanning_hosts)) + complete(&data->prev_finished); + list_add_tail(&data->list, &scanning_hosts); + spin_unlock(&async_scan_lock); + + return data; + + err: + kfree(data); + return NULL; +} + +/** + * scsi_finish_async_scan - asynchronous scan has finished + * @data: cookie returned from earlier call to scsi_prep_async_scan() + * + * All the devices currently attached to this host have been found. + * This function announces all the devices it has found to the rest + * of the system. + */ +static void scsi_finish_async_scan(struct async_scan_data *data) +{ + struct Scsi_Host *shost; + + if (!data) + return; + + shost = data->shost; + if (!shost->async_scan) { + printk("%s called twice for host %d", __FUNCTION__, + shost->host_no); + dump_stack(); + return; + } + + wait_for_completion(&data->prev_finished); + + scsi_sysfs_add_devices(shost); + + spin_lock(&async_scan_lock); + shost->async_scan = 0; + list_del(&data->list); + if (!list_empty(&scanning_hosts)) { + struct async_scan_data *next = list_entry(scanning_hosts.next, + struct async_scan_data, list); + complete(&next->prev_finished); + } + spin_unlock(&async_scan_lock); + + scsi_host_put(shost); + kfree(data); +} + +static void do_scsi_scan_host(struct Scsi_Host *shost) +{ + if (shost->hostt->scan_finished) { + unsigned long start = jiffies; + if (shost->hostt->scan_start) + shost->hostt->scan_start(shost); + + while (!shost->hostt->scan_finished(shost, jiffies - start)) + msleep(10); + } else { + scsi_scan_host_selected(shost, SCAN_WILD_CARD, SCAN_WILD_CARD, + SCAN_WILD_CARD, 0); + } +} + +static int do_scan_async(void *_data) +{ + struct async_scan_data *data = _data; + do_scsi_scan_host(data->shost); + scsi_finish_async_scan(data); + return 0; +} + /** * scsi_scan_host - scan the given adapter * @shost: adapter to scan **/ void scsi_scan_host(struct Scsi_Host *shost) { - scsi_scan_host_selected(shost, SCAN_WILD_CARD, SCAN_WILD_CARD, - SCAN_WILD_CARD, 0); + struct async_scan_data *data; + + if (strncmp(scsi_scan_type, "none", 4) == 0) + return; + + data = scsi_prep_async_scan(shost); + if (!data) { + do_scsi_scan_host(shost); + return; + } + + kthread_run(do_scan_async, data, "scsi_scan_%d", shost->host_no); } EXPORT_SYMBOL(scsi_scan_host); diff --git a/trunk/drivers/scsi/scsi_sysfs.c b/trunk/drivers/scsi/scsi_sysfs.c index e1a91665d1c2..259c90cfa367 100644 --- a/trunk/drivers/scsi/scsi_sysfs.c +++ b/trunk/drivers/scsi/scsi_sysfs.c @@ -218,16 +218,16 @@ static void scsi_device_cls_release(struct class_device *class_dev) put_device(&sdev->sdev_gendev); } -static void scsi_device_dev_release_usercontext(void *data) +static void scsi_device_dev_release_usercontext(struct work_struct *work) { - struct device *dev = data; struct scsi_device *sdev; struct device *parent; struct scsi_target *starget; unsigned long flags; - parent = dev->parent; - sdev = to_scsi_device(dev); + sdev = container_of(work, struct scsi_device, ew.work); + + parent = sdev->sdev_gendev.parent; starget = to_scsi_target(parent); spin_lock_irqsave(sdev->host->host_lock, flags); @@ -258,7 +258,7 @@ static void scsi_device_dev_release_usercontext(void *data) static void scsi_device_dev_release(struct device *dev) { struct scsi_device *sdp = to_scsi_device(dev); - execute_in_process_context(scsi_device_dev_release_usercontext, dev, + execute_in_process_context(scsi_device_dev_release_usercontext, &sdp->ew); } diff --git a/trunk/drivers/scsi/scsi_tgt_if.c b/trunk/drivers/scsi/scsi_tgt_if.c new file mode 100644 index 000000000000..37bbfbdb870f --- /dev/null +++ b/trunk/drivers/scsi/scsi_tgt_if.c @@ -0,0 +1,352 @@ +/* + * SCSI target kernel/user interface functions + * + * Copyright (C) 2005 FUJITA Tomonori + * Copyright (C) 2005 Mike Christie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "scsi_tgt_priv.h" + +struct tgt_ring { + u32 tr_idx; + unsigned long tr_pages[TGT_RING_PAGES]; + spinlock_t tr_lock; +}; + +/* tx_ring : kernel->user, rx_ring : user->kernel */ +static struct tgt_ring tx_ring, rx_ring; +static DECLARE_WAIT_QUEUE_HEAD(tgt_poll_wait); + +static inline void tgt_ring_idx_inc(struct tgt_ring *ring) +{ + if (ring->tr_idx == TGT_MAX_EVENTS - 1) + ring->tr_idx = 0; + else + ring->tr_idx++; +} + +static struct tgt_event *tgt_head_event(struct tgt_ring *ring, u32 idx) +{ + u32 pidx, off; + + pidx = idx / TGT_EVENT_PER_PAGE; + off = idx % TGT_EVENT_PER_PAGE; + + return (struct tgt_event *) + (ring->tr_pages[pidx] + sizeof(struct tgt_event) * off); +} + +static int tgt_uspace_send_event(u32 type, struct tgt_event *p) +{ + struct tgt_event *ev; + struct tgt_ring *ring = &tx_ring; + unsigned long flags; + int err = 0; + + spin_lock_irqsave(&ring->tr_lock, flags); + + ev = tgt_head_event(ring, ring->tr_idx); + if (!ev->hdr.status) + tgt_ring_idx_inc(ring); + else + err = -BUSY; + + spin_unlock_irqrestore(&ring->tr_lock, flags); + + if (err) + return err; + + memcpy(ev, p, sizeof(*ev)); + ev->hdr.type = type; + mb(); + ev->hdr.status = 1; + + flush_dcache_page(virt_to_page(ev)); + + wake_up_interruptible(&tgt_poll_wait); + + return 0; +} + +int scsi_tgt_uspace_send_cmd(struct scsi_cmnd *cmd, struct scsi_lun *lun, u64 tag) +{ + struct Scsi_Host *shost = scsi_tgt_cmd_to_host(cmd); + struct tgt_event ev; + int err; + + memset(&ev, 0, sizeof(ev)); + ev.p.cmd_req.host_no = shost->host_no; + ev.p.cmd_req.data_len = cmd->request_bufflen; + memcpy(ev.p.cmd_req.scb, cmd->cmnd, sizeof(ev.p.cmd_req.scb)); + memcpy(ev.p.cmd_req.lun, lun, sizeof(ev.p.cmd_req.lun)); + ev.p.cmd_req.attribute = cmd->tag; + ev.p.cmd_req.tag = tag; + + dprintk("%p %d %u %x %llx\n", cmd, shost->host_no, + ev.p.cmd_req.data_len, cmd->tag, + (unsigned long long) ev.p.cmd_req.tag); + + err = tgt_uspace_send_event(TGT_KEVENT_CMD_REQ, &ev); + if (err) + eprintk("tx buf is full, could not send\n"); + + return err; +} + +int scsi_tgt_uspace_send_status(struct scsi_cmnd *cmd, u64 tag) +{ + struct Scsi_Host *shost = scsi_tgt_cmd_to_host(cmd); + struct tgt_event ev; + int err; + + memset(&ev, 0, sizeof(ev)); + ev.p.cmd_done.host_no = shost->host_no; + ev.p.cmd_done.tag = tag; + ev.p.cmd_done.result = cmd->result; + + dprintk("%p %d %llu %u %x\n", cmd, shost->host_no, + (unsigned long long) ev.p.cmd_req.tag, + ev.p.cmd_req.data_len, cmd->tag); + + err = tgt_uspace_send_event(TGT_KEVENT_CMD_DONE, &ev); + if (err) + eprintk("tx buf is full, could not send\n"); + + return err; +} + +int scsi_tgt_uspace_send_tsk_mgmt(int host_no, int function, u64 tag, + struct scsi_lun *scsilun, void *data) +{ + struct tgt_event ev; + int err; + + memset(&ev, 0, sizeof(ev)); + ev.p.tsk_mgmt_req.host_no = host_no; + ev.p.tsk_mgmt_req.function = function; + ev.p.tsk_mgmt_req.tag = tag; + memcpy(ev.p.tsk_mgmt_req.lun, scsilun, sizeof(ev.p.tsk_mgmt_req.lun)); + ev.p.tsk_mgmt_req.mid = (u64) (unsigned long) data; + + dprintk("%d %x %llx %llx\n", host_no, function, (unsigned long long) tag, + (unsigned long long) ev.p.tsk_mgmt_req.mid); + + err = tgt_uspace_send_event(TGT_KEVENT_TSK_MGMT_REQ, &ev); + if (err) + eprintk("tx buf is full, could not send\n"); + + return err; +} + +static int event_recv_msg(struct tgt_event *ev) +{ + int err = 0; + + switch (ev->hdr.type) { + case TGT_UEVENT_CMD_RSP: + err = scsi_tgt_kspace_exec(ev->p.cmd_rsp.host_no, + ev->p.cmd_rsp.tag, + ev->p.cmd_rsp.result, + ev->p.cmd_rsp.len, + ev->p.cmd_rsp.uaddr, + ev->p.cmd_rsp.rw); + break; + case TGT_UEVENT_TSK_MGMT_RSP: + err = scsi_tgt_kspace_tsk_mgmt(ev->p.tsk_mgmt_rsp.host_no, + ev->p.tsk_mgmt_rsp.mid, + ev->p.tsk_mgmt_rsp.result); + break; + default: + eprintk("unknown type %d\n", ev->hdr.type); + err = -EINVAL; + } + + return err; +} + +static ssize_t tgt_write(struct file *file, const char __user * buffer, + size_t count, loff_t * ppos) +{ + struct tgt_event *ev; + struct tgt_ring *ring = &rx_ring; + + while (1) { + ev = tgt_head_event(ring, ring->tr_idx); + /* do we need this? */ + flush_dcache_page(virt_to_page(ev)); + + if (!ev->hdr.status) + break; + + tgt_ring_idx_inc(ring); + event_recv_msg(ev); + ev->hdr.status = 0; + }; + + return count; +} + +static unsigned int tgt_poll(struct file * file, struct poll_table_struct *wait) +{ + struct tgt_event *ev; + struct tgt_ring *ring = &tx_ring; + unsigned long flags; + unsigned int mask = 0; + u32 idx; + + poll_wait(file, &tgt_poll_wait, wait); + + spin_lock_irqsave(&ring->tr_lock, flags); + + idx = ring->tr_idx ? ring->tr_idx - 1 : TGT_MAX_EVENTS - 1; + ev = tgt_head_event(ring, idx); + if (ev->hdr.status) + mask |= POLLIN | POLLRDNORM; + + spin_unlock_irqrestore(&ring->tr_lock, flags); + + return mask; +} + +static int uspace_ring_map(struct vm_area_struct *vma, unsigned long addr, + struct tgt_ring *ring) +{ + int i, err; + + for (i = 0; i < TGT_RING_PAGES; i++) { + struct page *page = virt_to_page(ring->tr_pages[i]); + err = vm_insert_page(vma, addr, page); + if (err) + return err; + addr += PAGE_SIZE; + } + + return 0; +} + +static int tgt_mmap(struct file *filp, struct vm_area_struct *vma) +{ + unsigned long addr; + int err; + + if (vma->vm_pgoff) + return -EINVAL; + + if (vma->vm_end - vma->vm_start != TGT_RING_SIZE * 2) { + eprintk("mmap size must be %lu, not %lu \n", + TGT_RING_SIZE * 2, vma->vm_end - vma->vm_start); + return -EINVAL; + } + + addr = vma->vm_start; + err = uspace_ring_map(vma, addr, &tx_ring); + if (err) + return err; + err = uspace_ring_map(vma, addr + TGT_RING_SIZE, &rx_ring); + + return err; +} + +static int tgt_open(struct inode *inode, struct file *file) +{ + tx_ring.tr_idx = rx_ring.tr_idx = 0; + + return 0; +} + +static struct file_operations tgt_fops = { + .owner = THIS_MODULE, + .open = tgt_open, + .poll = tgt_poll, + .write = tgt_write, + .mmap = tgt_mmap, +}; + +static struct miscdevice tgt_miscdev = { + .minor = MISC_DYNAMIC_MINOR, + .name = "tgt", + .fops = &tgt_fops, +}; + +static void tgt_ring_exit(struct tgt_ring *ring) +{ + int i; + + for (i = 0; i < TGT_RING_PAGES; i++) + free_page(ring->tr_pages[i]); +} + +static int tgt_ring_init(struct tgt_ring *ring) +{ + int i; + + spin_lock_init(&ring->tr_lock); + + for (i = 0; i < TGT_RING_PAGES; i++) { + ring->tr_pages[i] = get_zeroed_page(GFP_KERNEL); + if (!ring->tr_pages[i]) { + eprintk("out of memory\n"); + return -ENOMEM; + } + } + + return 0; +} + +void scsi_tgt_if_exit(void) +{ + tgt_ring_exit(&tx_ring); + tgt_ring_exit(&rx_ring); + misc_deregister(&tgt_miscdev); +} + +int scsi_tgt_if_init(void) +{ + int err; + + err = tgt_ring_init(&tx_ring); + if (err) + return err; + + err = tgt_ring_init(&rx_ring); + if (err) + goto free_tx_ring; + + err = misc_register(&tgt_miscdev); + if (err) + goto free_rx_ring; + + return 0; +free_rx_ring: + tgt_ring_exit(&rx_ring); +free_tx_ring: + tgt_ring_exit(&tx_ring); + + return err; +} diff --git a/trunk/drivers/scsi/scsi_tgt_lib.c b/trunk/drivers/scsi/scsi_tgt_lib.c new file mode 100644 index 000000000000..d402aff5f314 --- /dev/null +++ b/trunk/drivers/scsi/scsi_tgt_lib.c @@ -0,0 +1,745 @@ +/* + * SCSI target lib functions + * + * Copyright (C) 2005 Mike Christie + * Copyright (C) 2005 FUJITA Tomonori + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include <../drivers/md/dm-bio-list.h> + +#include "scsi_tgt_priv.h" + +static struct workqueue_struct *scsi_tgtd; +static struct kmem_cache *scsi_tgt_cmd_cache; + +/* + * TODO: this struct will be killed when the block layer supports large bios + * and James's work struct code is in + */ +struct scsi_tgt_cmd { + /* TODO replace work with James b's code */ + struct work_struct work; + /* TODO replace the lists with a large bio */ + struct bio_list xfer_done_list; + struct bio_list xfer_list; + + struct list_head hash_list; + struct request *rq; + u64 tag; + + void *buffer; + unsigned bufflen; +}; + +#define TGT_HASH_ORDER 4 +#define cmd_hashfn(tag) hash_long((unsigned long) (tag), TGT_HASH_ORDER) + +struct scsi_tgt_queuedata { + struct Scsi_Host *shost; + struct list_head cmd_hash[1 << TGT_HASH_ORDER]; + spinlock_t cmd_hash_lock; +}; + +/* + * Function: scsi_host_get_command() + * + * Purpose: Allocate and setup a scsi command block and blk request + * + * Arguments: shost - scsi host + * data_dir - dma data dir + * gfp_mask- allocator flags + * + * Returns: The allocated scsi command structure. + * + * This should be called by target LLDs to get a command. + */ +struct scsi_cmnd *scsi_host_get_command(struct Scsi_Host *shost, + enum dma_data_direction data_dir, + gfp_t gfp_mask) +{ + int write = (data_dir == DMA_TO_DEVICE); + struct request *rq; + struct scsi_cmnd *cmd; + struct scsi_tgt_cmd *tcmd; + + /* Bail if we can't get a reference to the device */ + if (!get_device(&shost->shost_gendev)) + return NULL; + + tcmd = kmem_cache_alloc(scsi_tgt_cmd_cache, GFP_ATOMIC); + if (!tcmd) + goto put_dev; + + rq = blk_get_request(shost->uspace_req_q, write, gfp_mask); + if (!rq) + goto free_tcmd; + + cmd = __scsi_get_command(shost, gfp_mask); + if (!cmd) + goto release_rq; + + memset(cmd, 0, sizeof(*cmd)); + cmd->sc_data_direction = data_dir; + cmd->jiffies_at_alloc = jiffies; + cmd->request = rq; + + rq->special = cmd; + rq->cmd_type = REQ_TYPE_SPECIAL; + rq->cmd_flags |= REQ_TYPE_BLOCK_PC; + rq->end_io_data = tcmd; + + bio_list_init(&tcmd->xfer_list); + bio_list_init(&tcmd->xfer_done_list); + tcmd->rq = rq; + + return cmd; + +release_rq: + blk_put_request(rq); +free_tcmd: + kmem_cache_free(scsi_tgt_cmd_cache, tcmd); +put_dev: + put_device(&shost->shost_gendev); + return NULL; + +} +EXPORT_SYMBOL_GPL(scsi_host_get_command); + +/* + * Function: scsi_host_put_command() + * + * Purpose: Free a scsi command block + * + * Arguments: shost - scsi host + * cmd - command block to free + * + * Returns: Nothing. + * + * Notes: The command must not belong to any lists. + */ +void scsi_host_put_command(struct Scsi_Host *shost, struct scsi_cmnd *cmd) +{ + struct request_queue *q = shost->uspace_req_q; + struct request *rq = cmd->request; + struct scsi_tgt_cmd *tcmd = rq->end_io_data; + unsigned long flags; + + kmem_cache_free(scsi_tgt_cmd_cache, tcmd); + + spin_lock_irqsave(q->queue_lock, flags); + __blk_put_request(q, rq); + spin_unlock_irqrestore(q->queue_lock, flags); + + __scsi_put_command(shost, cmd, &shost->shost_gendev); +} +EXPORT_SYMBOL_GPL(scsi_host_put_command); + +static void scsi_unmap_user_pages(struct scsi_tgt_cmd *tcmd) +{ + struct bio *bio; + + /* must call bio_endio in case bio was bounced */ + while ((bio = bio_list_pop(&tcmd->xfer_done_list))) { + bio_endio(bio, bio->bi_size, 0); + bio_unmap_user(bio); + } + + while ((bio = bio_list_pop(&tcmd->xfer_list))) { + bio_endio(bio, bio->bi_size, 0); + bio_unmap_user(bio); + } +} + +static void cmd_hashlist_del(struct scsi_cmnd *cmd) +{ + struct request_queue *q = cmd->request->q; + struct scsi_tgt_queuedata *qdata = q->queuedata; + unsigned long flags; + struct scsi_tgt_cmd *tcmd = cmd->request->end_io_data; + + spin_lock_irqsave(&qdata->cmd_hash_lock, flags); + list_del(&tcmd->hash_list); + spin_unlock_irqrestore(&qdata->cmd_hash_lock, flags); +} + +static void scsi_tgt_cmd_destroy(struct work_struct *work) +{ + struct scsi_tgt_cmd *tcmd = + container_of(work, struct scsi_tgt_cmd, work); + struct scsi_cmnd *cmd = tcmd->rq->special; + + dprintk("cmd %p %d %lu\n", cmd, cmd->sc_data_direction, + rq_data_dir(cmd->request)); + /* + * We fix rq->cmd_flags here since when we told bio_map_user + * to write vm for WRITE commands, blk_rq_bio_prep set + * rq_data_dir the flags to READ. + */ + if (cmd->sc_data_direction == DMA_TO_DEVICE) + cmd->request->cmd_flags |= REQ_RW; + else + cmd->request->cmd_flags &= ~REQ_RW; + + scsi_unmap_user_pages(tcmd); + scsi_host_put_command(scsi_tgt_cmd_to_host(cmd), cmd); +} + +static void init_scsi_tgt_cmd(struct request *rq, struct scsi_tgt_cmd *tcmd, + u64 tag) +{ + struct scsi_tgt_queuedata *qdata = rq->q->queuedata; + unsigned long flags; + struct list_head *head; + + tcmd->tag = tag; + INIT_WORK(&tcmd->work, scsi_tgt_cmd_destroy); + spin_lock_irqsave(&qdata->cmd_hash_lock, flags); + head = &qdata->cmd_hash[cmd_hashfn(tag)]; + list_add(&tcmd->hash_list, head); + spin_unlock_irqrestore(&qdata->cmd_hash_lock, flags); +} + +/* + * scsi_tgt_alloc_queue - setup queue used for message passing + * shost: scsi host + * + * This should be called by the LLD after host allocation. + * And will be released when the host is released. + */ +int scsi_tgt_alloc_queue(struct Scsi_Host *shost) +{ + struct scsi_tgt_queuedata *queuedata; + struct request_queue *q; + int err, i; + + /* + * Do we need to send a netlink event or should uspace + * just respond to the hotplug event? + */ + q = __scsi_alloc_queue(shost, NULL); + if (!q) + return -ENOMEM; + + queuedata = kzalloc(sizeof(*queuedata), GFP_KERNEL); + if (!queuedata) { + err = -ENOMEM; + goto cleanup_queue; + } + queuedata->shost = shost; + q->queuedata = queuedata; + + /* + * this is a silly hack. We should probably just queue as many + * command as is recvd to userspace. uspace can then make + * sure we do not overload the HBA + */ + q->nr_requests = shost->hostt->can_queue; + /* + * We currently only support software LLDs so this does + * not matter for now. Do we need this for the cards we support? + * If so we should make it a host template value. + */ + blk_queue_dma_alignment(q, 0); + shost->uspace_req_q = q; + + for (i = 0; i < ARRAY_SIZE(queuedata->cmd_hash); i++) + INIT_LIST_HEAD(&queuedata->cmd_hash[i]); + spin_lock_init(&queuedata->cmd_hash_lock); + + return 0; + +cleanup_queue: + blk_cleanup_queue(q); + return err; +} +EXPORT_SYMBOL_GPL(scsi_tgt_alloc_queue); + +void scsi_tgt_free_queue(struct Scsi_Host *shost) +{ + int i; + unsigned long flags; + struct request_queue *q = shost->uspace_req_q; + struct scsi_cmnd *cmd; + struct scsi_tgt_queuedata *qdata = q->queuedata; + struct scsi_tgt_cmd *tcmd, *n; + LIST_HEAD(cmds); + + spin_lock_irqsave(&qdata->cmd_hash_lock, flags); + + for (i = 0; i < ARRAY_SIZE(qdata->cmd_hash); i++) { + list_for_each_entry_safe(tcmd, n, &qdata->cmd_hash[i], + hash_list) { + list_del(&tcmd->hash_list); + list_add(&tcmd->hash_list, &cmds); + } + } + + spin_unlock_irqrestore(&qdata->cmd_hash_lock, flags); + + while (!list_empty(&cmds)) { + tcmd = list_entry(cmds.next, struct scsi_tgt_cmd, hash_list); + list_del(&tcmd->hash_list); + cmd = tcmd->rq->special; + + shost->hostt->eh_abort_handler(cmd); + scsi_tgt_cmd_destroy(&tcmd->work); + } +} +EXPORT_SYMBOL_GPL(scsi_tgt_free_queue); + +struct Scsi_Host *scsi_tgt_cmd_to_host(struct scsi_cmnd *cmd) +{ + struct scsi_tgt_queuedata *queue = cmd->request->q->queuedata; + return queue->shost; +} +EXPORT_SYMBOL_GPL(scsi_tgt_cmd_to_host); + +/* + * scsi_tgt_queue_command - queue command for userspace processing + * @cmd: scsi command + * @scsilun: scsi lun + * @tag: unique value to identify this command for tmf + */ +int scsi_tgt_queue_command(struct scsi_cmnd *cmd, struct scsi_lun *scsilun, + u64 tag) +{ + struct scsi_tgt_cmd *tcmd = cmd->request->end_io_data; + int err; + + init_scsi_tgt_cmd(cmd->request, tcmd, tag); + err = scsi_tgt_uspace_send_cmd(cmd, scsilun, tag); + if (err) + cmd_hashlist_del(cmd); + + return err; +} +EXPORT_SYMBOL_GPL(scsi_tgt_queue_command); + +/* + * This is run from a interrpt handler normally and the unmap + * needs process context so we must queue + */ +static void scsi_tgt_cmd_done(struct scsi_cmnd *cmd) +{ + struct scsi_tgt_cmd *tcmd = cmd->request->end_io_data; + + dprintk("cmd %p %lu\n", cmd, rq_data_dir(cmd->request)); + + scsi_tgt_uspace_send_status(cmd, tcmd->tag); + queue_work(scsi_tgtd, &tcmd->work); +} + +static int __scsi_tgt_transfer_response(struct scsi_cmnd *cmd) +{ + struct Scsi_Host *shost = scsi_tgt_cmd_to_host(cmd); + int err; + + dprintk("cmd %p %lu\n", cmd, rq_data_dir(cmd->request)); + + err = shost->hostt->transfer_response(cmd, scsi_tgt_cmd_done); + switch (err) { + case SCSI_MLQUEUE_HOST_BUSY: + case SCSI_MLQUEUE_DEVICE_BUSY: + return -EAGAIN; + } + + return 0; +} + +static void scsi_tgt_transfer_response(struct scsi_cmnd *cmd) +{ + struct scsi_tgt_cmd *tcmd = cmd->request->end_io_data; + int err; + + err = __scsi_tgt_transfer_response(cmd); + if (!err) + return; + + cmd->result = DID_BUS_BUSY << 16; + err = scsi_tgt_uspace_send_status(cmd, tcmd->tag); + if (err <= 0) + /* the eh will have to pick this up */ + printk(KERN_ERR "Could not send cmd %p status\n", cmd); +} + +static int scsi_tgt_init_cmd(struct scsi_cmnd *cmd, gfp_t gfp_mask) +{ + struct request *rq = cmd->request; + struct scsi_tgt_cmd *tcmd = rq->end_io_data; + int count; + + cmd->use_sg = rq->nr_phys_segments; + cmd->request_buffer = scsi_alloc_sgtable(cmd, gfp_mask); + if (!cmd->request_buffer) + return -ENOMEM; + + cmd->request_bufflen = rq->data_len; + + dprintk("cmd %p addr %p cnt %d %lu\n", cmd, tcmd->buffer, cmd->use_sg, + rq_data_dir(rq)); + count = blk_rq_map_sg(rq->q, rq, cmd->request_buffer); + if (likely(count <= cmd->use_sg)) { + cmd->use_sg = count; + return 0; + } + + eprintk("cmd %p addr %p cnt %d\n", cmd, tcmd->buffer, cmd->use_sg); + scsi_free_sgtable(cmd->request_buffer, cmd->sglist_len); + return -EINVAL; +} + +/* TODO: test this crap and replace bio_map_user with new interface maybe */ +static int scsi_map_user_pages(struct scsi_tgt_cmd *tcmd, struct scsi_cmnd *cmd, + int rw) +{ + struct request_queue *q = cmd->request->q; + struct request *rq = cmd->request; + void *uaddr = tcmd->buffer; + unsigned int len = tcmd->bufflen; + struct bio *bio; + int err; + + while (len > 0) { + dprintk("%lx %u\n", (unsigned long) uaddr, len); + bio = bio_map_user(q, NULL, (unsigned long) uaddr, len, rw); + if (IS_ERR(bio)) { + err = PTR_ERR(bio); + dprintk("fail to map %lx %u %d %x\n", + (unsigned long) uaddr, len, err, cmd->cmnd[0]); + goto unmap_bios; + } + + uaddr += bio->bi_size; + len -= bio->bi_size; + + /* + * The first bio is added and merged. We could probably + * try to add others using scsi_merge_bio() but for now + * we keep it simple. The first bio should be pretty large + * (either hitting the 1 MB bio pages limit or a queue limit) + * already but for really large IO we may want to try and + * merge these. + */ + if (!rq->bio) { + blk_rq_bio_prep(q, rq, bio); + rq->data_len = bio->bi_size; + } else + /* put list of bios to transfer in next go around */ + bio_list_add(&tcmd->xfer_list, bio); + } + + cmd->offset = 0; + err = scsi_tgt_init_cmd(cmd, GFP_KERNEL); + if (err) + goto unmap_bios; + + return 0; + +unmap_bios: + if (rq->bio) { + bio_unmap_user(rq->bio); + while ((bio = bio_list_pop(&tcmd->xfer_list))) + bio_unmap_user(bio); + } + + return err; +} + +static int scsi_tgt_transfer_data(struct scsi_cmnd *); + +static void scsi_tgt_data_transfer_done(struct scsi_cmnd *cmd) +{ + struct scsi_tgt_cmd *tcmd = cmd->request->end_io_data; + struct bio *bio; + int err; + + /* should we free resources here on error ? */ + if (cmd->result) { +send_uspace_err: + err = scsi_tgt_uspace_send_status(cmd, tcmd->tag); + if (err <= 0) + /* the tgt uspace eh will have to pick this up */ + printk(KERN_ERR "Could not send cmd %p status\n", cmd); + return; + } + + dprintk("cmd %p request_bufflen %u bufflen %u\n", + cmd, cmd->request_bufflen, tcmd->bufflen); + + scsi_free_sgtable(cmd->request_buffer, cmd->sglist_len); + bio_list_add(&tcmd->xfer_done_list, cmd->request->bio); + + tcmd->buffer += cmd->request_bufflen; + cmd->offset += cmd->request_bufflen; + + if (!tcmd->xfer_list.head) { + scsi_tgt_transfer_response(cmd); + return; + } + + dprintk("cmd2 %p request_bufflen %u bufflen %u\n", + cmd, cmd->request_bufflen, tcmd->bufflen); + + bio = bio_list_pop(&tcmd->xfer_list); + BUG_ON(!bio); + + blk_rq_bio_prep(cmd->request->q, cmd->request, bio); + cmd->request->data_len = bio->bi_size; + err = scsi_tgt_init_cmd(cmd, GFP_ATOMIC); + if (err) { + cmd->result = DID_ERROR << 16; + goto send_uspace_err; + } + + if (scsi_tgt_transfer_data(cmd)) { + cmd->result = DID_NO_CONNECT << 16; + goto send_uspace_err; + } +} + +static int scsi_tgt_transfer_data(struct scsi_cmnd *cmd) +{ + int err; + struct Scsi_Host *host = scsi_tgt_cmd_to_host(cmd); + + err = host->hostt->transfer_data(cmd, scsi_tgt_data_transfer_done); + switch (err) { + case SCSI_MLQUEUE_HOST_BUSY: + case SCSI_MLQUEUE_DEVICE_BUSY: + return -EAGAIN; + default: + return 0; + } +} + +static int scsi_tgt_copy_sense(struct scsi_cmnd *cmd, unsigned long uaddr, + unsigned len) +{ + char __user *p = (char __user *) uaddr; + + if (copy_from_user(cmd->sense_buffer, p, + min_t(unsigned, SCSI_SENSE_BUFFERSIZE, len))) { + printk(KERN_ERR "Could not copy the sense buffer\n"); + return -EIO; + } + return 0; +} + +static int scsi_tgt_abort_cmd(struct Scsi_Host *shost, struct scsi_cmnd *cmd) +{ + struct scsi_tgt_cmd *tcmd; + int err; + + err = shost->hostt->eh_abort_handler(cmd); + if (err) + eprintk("fail to abort %p\n", cmd); + + tcmd = cmd->request->end_io_data; + scsi_tgt_cmd_destroy(&tcmd->work); + return err; +} + +static struct request *tgt_cmd_hash_lookup(struct request_queue *q, u64 tag) +{ + struct scsi_tgt_queuedata *qdata = q->queuedata; + struct request *rq = NULL; + struct list_head *head; + struct scsi_tgt_cmd *tcmd; + unsigned long flags; + + head = &qdata->cmd_hash[cmd_hashfn(tag)]; + spin_lock_irqsave(&qdata->cmd_hash_lock, flags); + list_for_each_entry(tcmd, head, hash_list) { + if (tcmd->tag == tag) { + rq = tcmd->rq; + list_del(&tcmd->hash_list); + break; + } + } + spin_unlock_irqrestore(&qdata->cmd_hash_lock, flags); + + return rq; +} + +int scsi_tgt_kspace_exec(int host_no, u64 tag, int result, u32 len, + unsigned long uaddr, u8 rw) +{ + struct Scsi_Host *shost; + struct scsi_cmnd *cmd; + struct request *rq; + struct scsi_tgt_cmd *tcmd; + int err = 0; + + dprintk("%d %llu %d %u %lx %u\n", host_no, (unsigned long long) tag, + result, len, uaddr, rw); + + /* TODO: replace with a O(1) alg */ + shost = scsi_host_lookup(host_no); + if (IS_ERR(shost)) { + printk(KERN_ERR "Could not find host no %d\n", host_no); + return -EINVAL; + } + + if (!shost->uspace_req_q) { + printk(KERN_ERR "Not target scsi host %d\n", host_no); + goto done; + } + + rq = tgt_cmd_hash_lookup(shost->uspace_req_q, tag); + if (!rq) { + printk(KERN_ERR "Could not find tag %llu\n", + (unsigned long long) tag); + err = -EINVAL; + goto done; + } + cmd = rq->special; + + dprintk("cmd %p result %d len %d bufflen %u %lu %x\n", cmd, + result, len, cmd->request_bufflen, rq_data_dir(rq), cmd->cmnd[0]); + + if (result == TASK_ABORTED) { + scsi_tgt_abort_cmd(shost, cmd); + goto done; + } + /* + * store the userspace values here, the working values are + * in the request_* values + */ + tcmd = cmd->request->end_io_data; + tcmd->buffer = (void *)uaddr; + tcmd->bufflen = len; + cmd->result = result; + + if (!tcmd->bufflen || cmd->request_buffer) { + err = __scsi_tgt_transfer_response(cmd); + goto done; + } + + /* + * TODO: Do we need to handle case where request does not + * align with LLD. + */ + err = scsi_map_user_pages(rq->end_io_data, cmd, rw); + if (err) { + eprintk("%p %d\n", cmd, err); + err = -EAGAIN; + goto done; + } + + /* userspace failure */ + if (cmd->result) { + if (status_byte(cmd->result) == CHECK_CONDITION) + scsi_tgt_copy_sense(cmd, uaddr, len); + err = __scsi_tgt_transfer_response(cmd); + goto done; + } + /* ask the target LLD to transfer the data to the buffer */ + err = scsi_tgt_transfer_data(cmd); + +done: + scsi_host_put(shost); + return err; +} + +int scsi_tgt_tsk_mgmt_request(struct Scsi_Host *shost, int function, u64 tag, + struct scsi_lun *scsilun, void *data) +{ + int err; + + /* TODO: need to retry if this fails. */ + err = scsi_tgt_uspace_send_tsk_mgmt(shost->host_no, function, + tag, scsilun, data); + if (err < 0) + eprintk("The task management request lost!\n"); + return err; +} +EXPORT_SYMBOL_GPL(scsi_tgt_tsk_mgmt_request); + +int scsi_tgt_kspace_tsk_mgmt(int host_no, u64 mid, int result) +{ + struct Scsi_Host *shost; + int err = -EINVAL; + + dprintk("%d %d %llx\n", host_no, result, (unsigned long long) mid); + + shost = scsi_host_lookup(host_no); + if (IS_ERR(shost)) { + printk(KERN_ERR "Could not find host no %d\n", host_no); + return err; + } + + if (!shost->uspace_req_q) { + printk(KERN_ERR "Not target scsi host %d\n", host_no); + goto done; + } + + err = shost->hostt->tsk_mgmt_response(mid, result); +done: + scsi_host_put(shost); + return err; +} + +static int __init scsi_tgt_init(void) +{ + int err; + + scsi_tgt_cmd_cache = kmem_cache_create("scsi_tgt_cmd", + sizeof(struct scsi_tgt_cmd), + 0, 0, NULL, NULL); + if (!scsi_tgt_cmd_cache) + return -ENOMEM; + + scsi_tgtd = create_workqueue("scsi_tgtd"); + if (!scsi_tgtd) { + err = -ENOMEM; + goto free_kmemcache; + } + + err = scsi_tgt_if_init(); + if (err) + goto destroy_wq; + + return 0; + +destroy_wq: + destroy_workqueue(scsi_tgtd); +free_kmemcache: + kmem_cache_destroy(scsi_tgt_cmd_cache); + return err; +} + +static void __exit scsi_tgt_exit(void) +{ + destroy_workqueue(scsi_tgtd); + scsi_tgt_if_exit(); + kmem_cache_destroy(scsi_tgt_cmd_cache); +} + +module_init(scsi_tgt_init); +module_exit(scsi_tgt_exit); + +MODULE_DESCRIPTION("SCSI target core"); +MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/scsi/scsi_tgt_priv.h b/trunk/drivers/scsi/scsi_tgt_priv.h new file mode 100644 index 000000000000..84488c51ff62 --- /dev/null +++ b/trunk/drivers/scsi/scsi_tgt_priv.h @@ -0,0 +1,25 @@ +struct scsi_cmnd; +struct scsi_lun; +struct Scsi_Host; +struct task_struct; + +/* tmp - will replace with SCSI logging stuff */ +#define eprintk(fmt, args...) \ +do { \ + printk("%s(%d) " fmt, __FUNCTION__, __LINE__, ##args); \ +} while (0) + +#define dprintk(fmt, args...) +/* #define dprintk eprintk */ + +extern void scsi_tgt_if_exit(void); +extern int scsi_tgt_if_init(void); + +extern int scsi_tgt_uspace_send_cmd(struct scsi_cmnd *cmd, struct scsi_lun *lun, + u64 tag); +extern int scsi_tgt_uspace_send_status(struct scsi_cmnd *cmd, u64 tag); +extern int scsi_tgt_kspace_exec(int host_no, u64 tag, int result, u32 len, + unsigned long uaddr, u8 rw); +extern int scsi_tgt_uspace_send_tsk_mgmt(int host_no, int function, u64 tag, + struct scsi_lun *scsilun, void *data); +extern int scsi_tgt_kspace_tsk_mgmt(int host_no, u64 mid, int result); diff --git a/trunk/drivers/scsi/scsi_transport_fc.c b/trunk/drivers/scsi/scsi_transport_fc.c index 38c215a78f69..3571ce8934e7 100644 --- a/trunk/drivers/scsi/scsi_transport_fc.c +++ b/trunk/drivers/scsi/scsi_transport_fc.c @@ -241,9 +241,9 @@ fc_bitfield_name_search(remote_port_roles, fc_remote_port_role_names) #define FC_MGMTSRVR_PORTID 0x00000a -static void fc_timeout_deleted_rport(void *data); -static void fc_timeout_fail_rport_io(void *data); -static void fc_scsi_scan_rport(void *data); +static void fc_timeout_deleted_rport(struct work_struct *work); +static void fc_timeout_fail_rport_io(struct work_struct *work); +static void fc_scsi_scan_rport(struct work_struct *work); /* * Attribute counts pre object type... @@ -1613,7 +1613,7 @@ fc_flush_work(struct Scsi_Host *shost) * 1 on success / 0 already queued / < 0 for error **/ static int -fc_queue_devloss_work(struct Scsi_Host *shost, struct work_struct *work, +fc_queue_devloss_work(struct Scsi_Host *shost, struct delayed_work *work, unsigned long delay) { if (unlikely(!fc_host_devloss_work_q(shost))) { @@ -1625,9 +1625,6 @@ fc_queue_devloss_work(struct Scsi_Host *shost, struct work_struct *work, return -EINVAL; } - if (delay == 0) - return queue_work(fc_host_devloss_work_q(shost), work); - return queue_delayed_work(fc_host_devloss_work_q(shost), work, delay); } @@ -1712,12 +1709,13 @@ EXPORT_SYMBOL(fc_remove_host); * fc_starget_delete - called to delete the scsi decendents of an rport * (target and all sdevs) * - * @data: remote port to be operated on. + * @work: remote port to be operated on. **/ static void -fc_starget_delete(void *data) +fc_starget_delete(struct work_struct *work) { - struct fc_rport *rport = (struct fc_rport *)data; + struct fc_rport *rport = + container_of(work, struct fc_rport, stgt_delete_work); struct Scsi_Host *shost = rport_to_shost(rport); unsigned long flags; struct fc_internal *i = to_fc_internal(shost->transportt); @@ -1751,12 +1749,13 @@ fc_starget_delete(void *data) /** * fc_rport_final_delete - finish rport termination and delete it. * - * @data: remote port to be deleted. + * @work: remote port to be deleted. **/ static void -fc_rport_final_delete(void *data) +fc_rport_final_delete(struct work_struct *work) { - struct fc_rport *rport = (struct fc_rport *)data; + struct fc_rport *rport = + container_of(work, struct fc_rport, rport_delete_work); struct device *dev = &rport->dev; struct Scsi_Host *shost = rport_to_shost(rport); struct fc_internal *i = to_fc_internal(shost->transportt); @@ -1770,7 +1769,7 @@ fc_rport_final_delete(void *data) /* Delete SCSI target and sdevs */ if (rport->scsi_target_id != -1) - fc_starget_delete(data); + fc_starget_delete(&rport->stgt_delete_work); else if (i->f->dev_loss_tmo_callbk) i->f->dev_loss_tmo_callbk(rport); else if (i->f->terminate_rport_io) @@ -1829,11 +1828,11 @@ fc_rport_create(struct Scsi_Host *shost, int channel, rport->channel = channel; rport->fast_io_fail_tmo = -1; - INIT_WORK(&rport->dev_loss_work, fc_timeout_deleted_rport, rport); - INIT_WORK(&rport->fail_io_work, fc_timeout_fail_rport_io, rport); - INIT_WORK(&rport->scan_work, fc_scsi_scan_rport, rport); - INIT_WORK(&rport->stgt_delete_work, fc_starget_delete, rport); - INIT_WORK(&rport->rport_delete_work, fc_rport_final_delete, rport); + INIT_DELAYED_WORK(&rport->dev_loss_work, fc_timeout_deleted_rport); + INIT_DELAYED_WORK(&rport->fail_io_work, fc_timeout_fail_rport_io); + INIT_WORK(&rport->scan_work, fc_scsi_scan_rport); + INIT_WORK(&rport->stgt_delete_work, fc_starget_delete); + INIT_WORK(&rport->rport_delete_work, fc_rport_final_delete); spin_lock_irqsave(shost->host_lock, flags); @@ -1963,7 +1962,7 @@ fc_remote_port_add(struct Scsi_Host *shost, int channel, } if (match) { - struct work_struct *work = + struct delayed_work *work = &rport->dev_loss_work; memcpy(&rport->node_name, &ids->node_name, @@ -2267,12 +2266,13 @@ EXPORT_SYMBOL(fc_remote_port_rolechg); * was a SCSI target (thus was blocked), and failed * to return in the alloted time. * - * @data: rport target that failed to reappear in the alloted time. + * @work: rport target that failed to reappear in the alloted time. **/ static void -fc_timeout_deleted_rport(void *data) +fc_timeout_deleted_rport(struct work_struct *work) { - struct fc_rport *rport = (struct fc_rport *)data; + struct fc_rport *rport = + container_of(work, struct fc_rport, dev_loss_work.work); struct Scsi_Host *shost = rport_to_shost(rport); struct fc_host_attrs *fc_host = shost_to_fc_host(shost); unsigned long flags; @@ -2366,15 +2366,16 @@ fc_timeout_deleted_rport(void *data) * fc_timeout_fail_rport_io - Timeout handler for a fast io failing on a * disconnected SCSI target. * - * @data: rport to terminate io on. + * @work: rport to terminate io on. * * Notes: Only requests the failure of the io, not that all are flushed * prior to returning. **/ static void -fc_timeout_fail_rport_io(void *data) +fc_timeout_fail_rport_io(struct work_struct *work) { - struct fc_rport *rport = (struct fc_rport *)data; + struct fc_rport *rport = + container_of(work, struct fc_rport, fail_io_work.work); struct Scsi_Host *shost = rport_to_shost(rport); struct fc_internal *i = to_fc_internal(shost->transportt); @@ -2387,12 +2388,13 @@ fc_timeout_fail_rport_io(void *data) /** * fc_scsi_scan_rport - called to perform a scsi scan on a remote port. * - * @data: remote port to be scanned. + * @work: remote port to be scanned. **/ static void -fc_scsi_scan_rport(void *data) +fc_scsi_scan_rport(struct work_struct *work) { - struct fc_rport *rport = (struct fc_rport *)data; + struct fc_rport *rport = + container_of(work, struct fc_rport, scan_work); struct Scsi_Host *shost = rport_to_shost(rport); unsigned long flags; diff --git a/trunk/drivers/scsi/scsi_transport_iscsi.c b/trunk/drivers/scsi/scsi_transport_iscsi.c index 9b25124a989e..9c22f1342715 100644 --- a/trunk/drivers/scsi/scsi_transport_iscsi.c +++ b/trunk/drivers/scsi/scsi_transport_iscsi.c @@ -234,9 +234,11 @@ static int iscsi_user_scan(struct Scsi_Host *shost, uint channel, return 0; } -static void session_recovery_timedout(void *data) +static void session_recovery_timedout(struct work_struct *work) { - struct iscsi_cls_session *session = data; + struct iscsi_cls_session *session = + container_of(work, struct iscsi_cls_session, + recovery_work.work); dev_printk(KERN_INFO, &session->dev, "iscsi: session recovery timed " "out after %d secs\n", session->recovery_tmo); @@ -276,7 +278,7 @@ iscsi_alloc_session(struct Scsi_Host *shost, session->transport = transport; session->recovery_tmo = 120; - INIT_WORK(&session->recovery_work, session_recovery_timedout, session); + INIT_DELAYED_WORK(&session->recovery_work, session_recovery_timedout); INIT_LIST_HEAD(&session->host_list); INIT_LIST_HEAD(&session->sess_list); diff --git a/trunk/drivers/scsi/scsi_transport_spi.c b/trunk/drivers/scsi/scsi_transport_spi.c index 9f070f0d0f2b..3fded4831460 100644 --- a/trunk/drivers/scsi/scsi_transport_spi.c +++ b/trunk/drivers/scsi/scsi_transport_spi.c @@ -964,9 +964,10 @@ struct work_queue_wrapper { }; static void -spi_dv_device_work_wrapper(void *data) +spi_dv_device_work_wrapper(struct work_struct *work) { - struct work_queue_wrapper *wqw = (struct work_queue_wrapper *)data; + struct work_queue_wrapper *wqw = + container_of(work, struct work_queue_wrapper, work); struct scsi_device *sdev = wqw->sdev; kfree(wqw); @@ -1006,7 +1007,7 @@ spi_schedule_dv_device(struct scsi_device *sdev) return; } - INIT_WORK(&wqw->work, spi_dv_device_work_wrapper, wqw); + INIT_WORK(&wqw->work, spi_dv_device_work_wrapper); wqw->sdev = sdev; schedule_work(&wqw->work); diff --git a/trunk/drivers/scsi/scsi_wait_scan.c b/trunk/drivers/scsi/scsi_wait_scan.c new file mode 100644 index 000000000000..8a636103083d --- /dev/null +++ b/trunk/drivers/scsi/scsi_wait_scan.c @@ -0,0 +1,31 @@ +/* + * scsi_wait_scan.c + * + * Copyright (C) 2006 James Bottomley + * + * This is a simple module to wait until all the async scans are + * complete. The idea is to use it in initrd/initramfs scripts. You + * modprobe it after all the modprobes of the root SCSI drivers and it + * will wait until they have all finished scanning their busses before + * allowing the boot to proceed + */ + +#include +#include "scsi_priv.h" + +static int __init wait_scan_init(void) +{ + scsi_complete_async_scans(); + return 0; +} + +static void __exit wait_scan_exit(void) +{ +} + +MODULE_DESCRIPTION("SCSI wait for scans"); +MODULE_AUTHOR("James Bottomley"); +MODULE_LICENSE("GPL"); + +late_initcall(wait_scan_init); +module_exit(wait_scan_exit); diff --git a/trunk/drivers/scsi/sd.c b/trunk/drivers/scsi/sd.c index 84ff203ffedd..978bfc1e0c6a 100644 --- a/trunk/drivers/scsi/sd.c +++ b/trunk/drivers/scsi/sd.c @@ -863,7 +863,7 @@ static void sd_rescan(struct device *dev) */ static long sd_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - struct block_device *bdev = file->f_dentry->d_inode->i_bdev; + struct block_device *bdev = file->f_path.dentry->d_inode->i_bdev; struct gendisk *disk = bdev->bd_disk; struct scsi_device *sdev = scsi_disk(disk)->device; @@ -1051,6 +1051,14 @@ sd_spinup_disk(struct scsi_disk *sdkp, char *diskname) &sshdr, SD_TIMEOUT, SD_MAX_RETRIES); + /* + * If the drive has indicated to us that it + * doesn't have any media in it, don't bother + * with any more polling. + */ + if (media_not_present(sdkp, &sshdr)) + return; + if (the_result) sense_valid = scsi_sense_valid(&sshdr); retries++; @@ -1059,14 +1067,6 @@ sd_spinup_disk(struct scsi_disk *sdkp, char *diskname) ((driver_byte(the_result) & DRIVER_SENSE) && sense_valid && sshdr.sense_key == UNIT_ATTENTION))); - /* - * If the drive has indicated to us that it doesn't have - * any media in it, don't bother with any of the rest of - * this crap. - */ - if (media_not_present(sdkp, &sshdr)) - return; - if ((driver_byte(the_result) & DRIVER_SENSE) == 0) { /* no sense, TUR either succeeded or failed * with a status error */ @@ -1467,7 +1467,6 @@ sd_read_cache_type(struct scsi_disk *sdkp, char *diskname, res = sd_do_mode_sense(sdp, dbd, modepage, buffer, len, &data, &sshdr); if (scsi_status_is_good(res)) { - int ct = 0; int offset = data.header_length + data.block_descriptor_length; if (offset >= SD_BUF_SIZE - 2) { @@ -1496,11 +1495,13 @@ sd_read_cache_type(struct scsi_disk *sdkp, char *diskname, sdkp->DPOFUA = 0; } - ct = sdkp->RCD + 2*sdkp->WCE; - - printk(KERN_NOTICE "SCSI device %s: drive cache: %s%s\n", - diskname, sd_cache_types[ct], - sdkp->DPOFUA ? " w/ FUA" : ""); + printk(KERN_NOTICE "SCSI device %s: " + "write cache: %s, read cache: %s, %s\n", + diskname, + sdkp->WCE ? "enabled" : "disabled", + sdkp->RCD ? "disabled" : "enabled", + sdkp->DPOFUA ? "supports DPO and FUA" + : "doesn't support DPO or FUA"); return; } diff --git a/trunk/drivers/scsi/st.c b/trunk/drivers/scsi/st.c index e1a52c525ed4..e016e0906e1a 100644 --- a/trunk/drivers/scsi/st.c +++ b/trunk/drivers/scsi/st.c @@ -9,7 +9,7 @@ Steve Hirsch, Andreas Koppenh"ofer, Michael Leodolter, Eyal Lebedinsky, Michael Schaefer, J"org Weule, and Eric Youngdale. - Copyright 1992 - 2005 Kai Makisara + Copyright 1992 - 2006 Kai Makisara email Kai.Makisara@kolumbus.fi Some small formal changes - aeb, 950809 @@ -17,7 +17,7 @@ Last modified: 18-JAN-1998 Richard Gooch Devfs support */ -static const char *verstr = "20050830"; +static const char *verstr = "20061107"; #include @@ -922,7 +922,7 @@ static int check_tape(struct scsi_tape *STp, struct file *filp) struct st_modedef *STm; struct st_partstat *STps; char *name = tape_name(STp); - struct inode *inode = filp->f_dentry->d_inode; + struct inode *inode = filp->f_path.dentry->d_inode; int mode = TAPE_MODE(inode); STp->ready = ST_READY; @@ -999,7 +999,7 @@ static int check_tape(struct scsi_tape *STp, struct file *filp) STp->min_block = ((STp->buffer)->b_data[4] << 8) | (STp->buffer)->b_data[5]; if ( DEB( debugging || ) !STp->inited) - printk(KERN_WARNING + printk(KERN_INFO "%s: Block limits %d - %d bytes.\n", name, STp->min_block, STp->max_block); } else { @@ -1224,7 +1224,7 @@ static int st_flush(struct file *filp, fl_owner_t id) } DEBC( if (STp->nbr_requests) - printk(KERN_WARNING "%s: Number of r/w requests %d, dio used in %d, pages %d (%d).\n", + printk(KERN_DEBUG "%s: Number of r/w requests %d, dio used in %d, pages %d (%d).\n", name, STp->nbr_requests, STp->nbr_dio, STp->nbr_pages, STp->nbr_combinable)); if (STps->rw == ST_WRITING && !STp->pos_unknown) { @@ -4056,11 +4056,11 @@ static int st_probe(struct device *dev) goto out_free_tape; } - sdev_printk(KERN_WARNING, SDp, + sdev_printk(KERN_NOTICE, SDp, "Attached scsi tape %s\n", tape_name(tpnt)); - printk(KERN_WARNING "%s: try direct i/o: %s (alignment %d B)\n", - tape_name(tpnt), tpnt->try_dio ? "yes" : "no", - queue_dma_alignment(SDp->request_queue) + 1); + sdev_printk(KERN_INFO, SDp, "%s: try direct i/o: %s (alignment %d B)\n", + tape_name(tpnt), tpnt->try_dio ? "yes" : "no", + queue_dma_alignment(SDp->request_queue) + 1); return 0; diff --git a/trunk/drivers/scsi/stex.c b/trunk/drivers/scsi/stex.c index 185c270bb043..ba6bcdaf2a6a 100644 --- a/trunk/drivers/scsi/stex.c +++ b/trunk/drivers/scsi/stex.c @@ -11,8 +11,6 @@ * Written By: * Ed Lin * - * Version: 3.0.0.1 - * */ #include @@ -37,9 +35,9 @@ #include #define DRV_NAME "stex" -#define ST_DRIVER_VERSION "3.0.0.1" +#define ST_DRIVER_VERSION "3.1.0.1" #define ST_VER_MAJOR 3 -#define ST_VER_MINOR 0 +#define ST_VER_MINOR 1 #define ST_OEM 0 #define ST_BUILD_VER 1 @@ -76,8 +74,10 @@ enum { MU_STATE_STARTED = 4, MU_STATE_RESETTING = 5, - MU_MAX_DELAY_TIME = 240000, + MU_MAX_DELAY = 120, MU_HANDSHAKE_SIGNATURE = 0x55aaaa55, + MU_HANDSHAKE_SIGNATURE_HALF = 0x5a5a0000, + MU_HARD_RESET_WAIT = 30000, HMU_PARTNER_TYPE = 2, /* firmware returned values */ @@ -120,7 +120,8 @@ enum { st_shasta = 0, st_vsc = 1, - st_yosemite = 2, + st_vsc1 = 2, + st_yosemite = 3, PASSTHRU_REQ_TYPE = 0x00000001, PASSTHRU_REQ_NO_WAKEUP = 0x00000100, @@ -150,6 +151,8 @@ enum { MGT_CMD_SIGNATURE = 0xba, INQUIRY_EVPD = 0x01, + + ST_ADDITIONAL_MEM = 0x200000, }; /* SCSI inquiry data */ @@ -211,7 +214,9 @@ struct handshake_frame { __le32 partner_ver_minor; __le32 partner_ver_oem; __le32 partner_ver_build; - u32 reserved1[4]; + __le32 extra_offset; /* NEW */ + __le32 extra_size; /* NEW */ + u32 reserved1[2]; }; struct req_msg { @@ -302,6 +307,7 @@ struct st_hba { void __iomem *mmio_base; /* iomapped PCI memory space */ void *dma_mem; dma_addr_t dma_handle; + size_t dma_size; struct Scsi_Host *host; struct pci_dev *pdev; @@ -507,6 +513,7 @@ static void stex_controller_info(struct st_hba *hba, struct st_ccb *ccb) size_t count = sizeof(struct st_frame); p = hba->copy_buffer; + stex_internal_copy(ccb->cmd, p, &count, ccb->sg_count, ST_FROM_CMD); memset(p->base, 0, sizeof(u32)*6); *(unsigned long *)(p->base) = pci_resource_start(hba->pdev, 0); p->rom_addr = 0; @@ -901,27 +908,34 @@ static int stex_handshake(struct st_hba *hba) void __iomem *base = hba->mmio_base; struct handshake_frame *h; dma_addr_t status_phys; - int i; + u32 data; + unsigned long before; if (readl(base + OMR0) != MU_HANDSHAKE_SIGNATURE) { writel(MU_INBOUND_DOORBELL_HANDSHAKE, base + IDBL); readl(base + IDBL); - for (i = 0; readl(base + OMR0) != MU_HANDSHAKE_SIGNATURE - && i < MU_MAX_DELAY_TIME; i++) { + before = jiffies; + while (readl(base + OMR0) != MU_HANDSHAKE_SIGNATURE) { + if (time_after(jiffies, before + MU_MAX_DELAY * HZ)) { + printk(KERN_ERR DRV_NAME + "(%s): no handshake signature\n", + pci_name(hba->pdev)); + return -1; + } rmb(); msleep(1); } - - if (i == MU_MAX_DELAY_TIME) { - printk(KERN_ERR DRV_NAME - "(%s): no handshake signature\n", - pci_name(hba->pdev)); - return -1; - } } udelay(10); + data = readl(base + OMR1); + if ((data & 0xffff0000) == MU_HANDSHAKE_SIGNATURE_HALF) { + data &= 0x0000ffff; + if (hba->host->can_queue > data) + hba->host->can_queue = data; + } + h = (struct handshake_frame *)(hba->dma_mem + MU_REQ_BUFFER_SIZE); h->rb_phy = cpu_to_le32(hba->dma_handle); h->rb_phy_hi = cpu_to_le32((hba->dma_handle >> 16) >> 16); @@ -931,6 +945,11 @@ static int stex_handshake(struct st_hba *hba) h->status_cnt = cpu_to_le16(MU_STATUS_COUNT); stex_gettime(&h->hosttime); h->partner_type = HMU_PARTNER_TYPE; + if (hba->dma_size > STEX_BUFFER_SIZE) { + h->extra_offset = cpu_to_le32(STEX_BUFFER_SIZE); + h->extra_size = cpu_to_le32(ST_ADDITIONAL_MEM); + } else + h->extra_offset = h->extra_size = 0; status_phys = hba->dma_handle + MU_REQ_BUFFER_SIZE; writel(status_phys, base + IMR0); @@ -944,19 +963,18 @@ static int stex_handshake(struct st_hba *hba) readl(base + IDBL); /* flush */ udelay(10); - for (i = 0; readl(base + OMR0) != MU_HANDSHAKE_SIGNATURE - && i < MU_MAX_DELAY_TIME; i++) { + before = jiffies; + while (readl(base + OMR0) != MU_HANDSHAKE_SIGNATURE) { + if (time_after(jiffies, before + MU_MAX_DELAY * HZ)) { + printk(KERN_ERR DRV_NAME + "(%s): no signature after handshake frame\n", + pci_name(hba->pdev)); + return -1; + } rmb(); msleep(1); } - if (i == MU_MAX_DELAY_TIME) { - printk(KERN_ERR DRV_NAME - "(%s): no signature after handshake frame\n", - pci_name(hba->pdev)); - return -1; - } - writel(0, base + IMR0); readl(base + IMR0); writel(0, base + OMR0); @@ -1038,9 +1056,9 @@ static void stex_hard_reset(struct st_hba *hba) pci_bctl &= ~PCI_BRIDGE_CTL_BUS_RESET; pci_write_config_byte(bus->self, PCI_BRIDGE_CONTROL, pci_bctl); - for (i = 0; i < MU_MAX_DELAY_TIME; i++) { + for (i = 0; i < MU_HARD_RESET_WAIT; i++) { pci_read_config_word(hba->pdev, PCI_COMMAND, &pci_cmd); - if (pci_cmd & PCI_COMMAND_MASTER) + if (pci_cmd != 0xffff && (pci_cmd & PCI_COMMAND_MASTER)) break; msleep(1); } @@ -1100,18 +1118,18 @@ static int stex_reset(struct scsi_cmnd *cmd) static int stex_biosparam(struct scsi_device *sdev, struct block_device *bdev, sector_t capacity, int geom[]) { - int heads = 255, sectors = 63, cylinders; + int heads = 255, sectors = 63; if (capacity < 0x200000) { heads = 64; sectors = 32; } - cylinders = sector_div(capacity, heads * sectors); + sector_div(capacity, heads * sectors); geom[0] = heads; geom[1] = sectors; - geom[2] = cylinders; + geom[2] = capacity; return 0; } @@ -1193,8 +1211,13 @@ stex_probe(struct pci_dev *pdev, const struct pci_device_id *id) goto out_iounmap; } + hba->cardtype = (unsigned int) id->driver_data; + if (hba->cardtype == st_vsc && (pdev->subsystem_device & 0xf) == 0x1) + hba->cardtype = st_vsc1; + hba->dma_size = (hba->cardtype == st_vsc1) ? + (STEX_BUFFER_SIZE + ST_ADDITIONAL_MEM) : (STEX_BUFFER_SIZE); hba->dma_mem = dma_alloc_coherent(&pdev->dev, - STEX_BUFFER_SIZE, &hba->dma_handle, GFP_KERNEL); + hba->dma_size, &hba->dma_handle, GFP_KERNEL); if (!hba->dma_mem) { err = -ENOMEM; printk(KERN_ERR DRV_NAME "(%s): dma mem alloc failed\n", @@ -1207,8 +1230,6 @@ stex_probe(struct pci_dev *pdev, const struct pci_device_id *id) hba->copy_buffer = hba->dma_mem + MU_BUFFER_SIZE; hba->mu_status = MU_STATE_STARTING; - hba->cardtype = (unsigned int) id->driver_data; - /* firmware uses id/lun pair for a logical drive, but lun would be always 0 if CONFIG_SCSI_MULTI_LUN not configured, so we use channel to map lun here */ @@ -1233,7 +1254,7 @@ stex_probe(struct pci_dev *pdev, const struct pci_device_id *id) if (err) goto out_free_irq; - err = scsi_init_shared_tag_map(host, ST_CAN_QUEUE); + err = scsi_init_shared_tag_map(host, host->can_queue); if (err) { printk(KERN_ERR DRV_NAME "(%s): init shared queue failed\n", pci_name(pdev)); @@ -1256,7 +1277,7 @@ stex_probe(struct pci_dev *pdev, const struct pci_device_id *id) out_free_irq: free_irq(pdev->irq, hba); out_pci_free: - dma_free_coherent(&pdev->dev, STEX_BUFFER_SIZE, + dma_free_coherent(&pdev->dev, hba->dma_size, hba->dma_mem, hba->dma_handle); out_iounmap: iounmap(hba->mmio_base); @@ -1317,7 +1338,7 @@ static void stex_hba_free(struct st_hba *hba) pci_release_regions(hba->pdev); - dma_free_coherent(&hba->pdev->dev, STEX_BUFFER_SIZE, + dma_free_coherent(&hba->pdev->dev, hba->dma_size, hba->dma_mem, hba->dma_handle); } @@ -1346,15 +1367,32 @@ static void stex_shutdown(struct pci_dev *pdev) } static struct pci_device_id stex_pci_tbl[] = { - { 0x105a, 0x8350, PCI_ANY_ID, PCI_ANY_ID, 0, 0, st_shasta }, - { 0x105a, 0xc350, PCI_ANY_ID, PCI_ANY_ID, 0, 0, st_shasta }, - { 0x105a, 0xf350, PCI_ANY_ID, PCI_ANY_ID, 0, 0, st_shasta }, - { 0x105a, 0x4301, PCI_ANY_ID, PCI_ANY_ID, 0, 0, st_shasta }, - { 0x105a, 0x4302, PCI_ANY_ID, PCI_ANY_ID, 0, 0, st_shasta }, - { 0x105a, 0x8301, PCI_ANY_ID, PCI_ANY_ID, 0, 0, st_shasta }, - { 0x105a, 0x8302, PCI_ANY_ID, PCI_ANY_ID, 0, 0, st_shasta }, - { 0x1725, 0x7250, PCI_ANY_ID, PCI_ANY_ID, 0, 0, st_vsc }, - { 0x105a, 0x8650, PCI_ANY_ID, PCI_ANY_ID, 0, 0, st_yosemite }, + /* st_shasta */ + { 0x105a, 0x8350, PCI_ANY_ID, PCI_ANY_ID, 0, 0, + st_shasta }, /* SuperTrak EX8350/8300/16350/16300 */ + { 0x105a, 0xc350, PCI_ANY_ID, PCI_ANY_ID, 0, 0, + st_shasta }, /* SuperTrak EX12350 */ + { 0x105a, 0x4302, PCI_ANY_ID, PCI_ANY_ID, 0, 0, + st_shasta }, /* SuperTrak EX4350 */ + { 0x105a, 0xe350, PCI_ANY_ID, PCI_ANY_ID, 0, 0, + st_shasta }, /* SuperTrak EX24350 */ + + /* st_vsc */ + { 0x105a, 0x7250, PCI_ANY_ID, PCI_ANY_ID, 0, 0, st_vsc }, + + /* st_yosemite */ + { 0x105a, 0x8650, PCI_ANY_ID, 0x4600, 0, 0, + st_yosemite }, /* SuperTrak EX4650 */ + { 0x105a, 0x8650, PCI_ANY_ID, 0x4610, 0, 0, + st_yosemite }, /* SuperTrak EX4650o */ + { 0x105a, 0x8650, PCI_ANY_ID, 0x8600, 0, 0, + st_yosemite }, /* SuperTrak EX8650EL */ + { 0x105a, 0x8650, PCI_ANY_ID, 0x8601, 0, 0, + st_yosemite }, /* SuperTrak EX8650 */ + { 0x105a, 0x8650, PCI_ANY_ID, 0x8602, 0, 0, + st_yosemite }, /* SuperTrak EX8654 */ + { 0x105a, 0x8650, PCI_ANY_ID, PCI_ANY_ID, 0, 0, + st_yosemite }, /* generic st_yosemite */ { } /* terminate list */ }; MODULE_DEVICE_TABLE(pci, stex_pci_tbl); diff --git a/trunk/drivers/scsi/t128.h b/trunk/drivers/scsi/t128.h index 646e840266e2..76a069b7ac0b 100644 --- a/trunk/drivers/scsi/t128.h +++ b/trunk/drivers/scsi/t128.h @@ -8,20 +8,20 @@ * drew@colorado.edu * +1 (303) 440-4894 * - * DISTRIBUTION RELEASE 3. + * DISTRIBUTION RELEASE 3. * - * For more information, please consult + * For more information, please consult * * Trantor Systems, Ltd. * T128/T128F/T228 SCSI Host Adapter * Hardware Specifications - * - * Trantor Systems, Ltd. + * + * Trantor Systems, Ltd. * 5415 Randall Place * Fremont, CA 94538 * 1+ (415) 770-1400, FAX 1+ (415) 770-9910 - * - * and + * + * and * * NCR 5380 Family * SCSI Protocol Controller @@ -48,15 +48,15 @@ #define TDEBUG_TRANSFER 0x2 /* - * The trantor boards are memory mapped. They use an NCR5380 or + * The trantor boards are memory mapped. They use an NCR5380 or * equivalent (my sample board had part second sourced from ZILOG). - * NCR's recommended "Pseudo-DMA" architecture is used, where + * NCR's recommended "Pseudo-DMA" architecture is used, where * a PAL drives the DMA signals on the 5380 allowing fast, blind - * transfers with proper handshaking. + * transfers with proper handshaking. */ /* - * Note : a boot switch is provided for the purpose of informing the + * Note : a boot switch is provided for the purpose of informing the * firmware to boot or not boot from attached SCSI devices. So, I imagine * there are fewer people who've yanked the ROM like they do on the Seagate * to make bootup faster, and I'll probably use this for autodetection. @@ -92,19 +92,20 @@ #define T_DATA_REG_OFFSET 0x1e00 /* rw 512 bytes long */ #ifndef ASM -static int t128_abort(Scsi_Cmnd *); +static int t128_abort(struct scsi_cmnd *); static int t128_biosparam(struct scsi_device *, struct block_device *, sector_t, int*); static int t128_detect(struct scsi_host_template *); -static int t128_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); -static int t128_bus_reset(Scsi_Cmnd *); +static int t128_queue_command(struct scsi_cmnd *, + void (*done)(struct scsi_cmnd *)); +static int t128_bus_reset(struct scsi_cmnd *); #ifndef CMD_PER_LUN #define CMD_PER_LUN 2 #endif #ifndef CAN_QUEUE -#define CAN_QUEUE 32 +#define CAN_QUEUE 32 #endif #ifndef HOSTS_C @@ -120,7 +121,7 @@ static int t128_bus_reset(Scsi_Cmnd *); #define T128_address(reg) (base + T_5380_OFFSET + ((reg) * 0x20)) -#if !(TDEBUG & TDEBUG_TRANSFER) +#if !(TDEBUG & TDEBUG_TRANSFER) #define NCR5380_read(reg) readb(T128_address(reg)) #define NCR5380_write(reg, value) writeb((value),(T128_address(reg))) #else @@ -129,7 +130,7 @@ static int t128_bus_reset(Scsi_Cmnd *); , instance->hostno, (reg), T128_address(reg))), readb(T128_address(reg))) #define NCR5380_write(reg, value) { \ - printk("scsi%d : write %02x to register %d at address %08x\n", \ + printk("scsi%d : write %02x to register %d at address %08x\n", \ instance->hostno, (value), (reg), T128_address(reg)); \ writeb((value), (T128_address(reg))); \ } @@ -142,10 +143,10 @@ static int t128_bus_reset(Scsi_Cmnd *); #define NCR5380_bus_reset t128_bus_reset #define NCR5380_proc_info t128_proc_info -/* 15 14 12 10 7 5 3 +/* 15 14 12 10 7 5 3 1101 0100 1010 1000 */ - -#define T128_IRQS 0xc4a8 + +#define T128_IRQS 0xc4a8 #endif /* else def HOSTS_C */ #endif /* ndef ASM */ diff --git a/trunk/drivers/serial/21285.c b/trunk/drivers/serial/21285.c index 6a1a568ca649..facb67855619 100644 --- a/trunk/drivers/serial/21285.c +++ b/trunk/drivers/serial/21285.c @@ -214,8 +214,8 @@ static void serial21285_shutdown(struct uart_port *port) } static void -serial21285_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +serial21285_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { unsigned long flags; unsigned int baud, quot, h_lcr; diff --git a/trunk/drivers/serial/68328serial.c b/trunk/drivers/serial/68328serial.c index 9b8b585513ec..cad426c9711e 100644 --- a/trunk/drivers/serial/68328serial.c +++ b/trunk/drivers/serial/68328serial.c @@ -1061,7 +1061,7 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file, return 0; } -static void rs_set_termios(struct tty_struct *tty, struct termios *old_termios) +static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { struct m68k_serial *info = (struct m68k_serial *)tty->driver_data; diff --git a/trunk/drivers/serial/68360serial.c b/trunk/drivers/serial/68360serial.c index 634ecca36a77..68817a7d8c0d 100644 --- a/trunk/drivers/serial/68360serial.c +++ b/trunk/drivers/serial/68360serial.c @@ -1523,7 +1523,7 @@ static int rs_360_ioctl(struct tty_struct *tty, struct file * file, /* FIX UP modem control here someday...... */ -static void rs_360_set_termios(struct tty_struct *tty, struct termios *old_termios) +static void rs_360_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { ser_info_t *info = (ser_info_t *)tty->driver_data; diff --git a/trunk/drivers/serial/8250.c b/trunk/drivers/serial/8250.c index e34bd03cfce7..51f3c739f7e1 100644 --- a/trunk/drivers/serial/8250.c +++ b/trunk/drivers/serial/8250.c @@ -1763,8 +1763,8 @@ static unsigned int serial8250_get_divisor(struct uart_port *port, unsigned int } static void -serial8250_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +serial8250_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { struct uart_8250_port *up = (struct uart_8250_port *)port; unsigned char cval, fcr = 0; diff --git a/trunk/drivers/serial/8250_exar_st16c554.c b/trunk/drivers/serial/8250_exar_st16c554.c new file mode 100644 index 000000000000..567143ace159 --- /dev/null +++ b/trunk/drivers/serial/8250_exar_st16c554.c @@ -0,0 +1,52 @@ +/* + * linux/drivers/serial/8250_exar.c + * + * Written by Paul B Schroeder < pschroeder "at" uplogix "dot" com > + * Based on 8250_boca. + * + * Copyright (C) 2005 Russell King. + * Data taken from include/asm-i386/serial.h + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include + +#define PORT(_base,_irq) \ + { \ + .iobase = _base, \ + .irq = _irq, \ + .uartclk = 1843200, \ + .iotype = UPIO_PORT, \ + .flags = UPF_BOOT_AUTOCONF, \ + } + +static struct plat_serial8250_port exar_data[] = { + PORT(0x100, 5), + PORT(0x108, 5), + PORT(0x110, 5), + PORT(0x118, 5), + { }, +}; + +static struct platform_device exar_device = { + .name = "serial8250", + .id = PLAT8250_DEV_EXAR_ST16C554, + .dev = { + .platform_data = exar_data, + }, +}; + +static int __init exar_init(void) +{ + return platform_device_register(&exar_device); +} + +module_init(exar_init); + +MODULE_AUTHOR("Paul B Schroeder"); +MODULE_DESCRIPTION("8250 serial probe module for Exar cards"); +MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/serial/8250_pnp.c b/trunk/drivers/serial/8250_pnp.c index 71d907c8288b..d3d6b82706b5 100644 --- a/trunk/drivers/serial/8250_pnp.c +++ b/trunk/drivers/serial/8250_pnp.c @@ -464,11 +464,38 @@ static void __devexit serial_pnp_remove(struct pnp_dev *dev) serial8250_unregister_port(line - 1); } +#ifdef CONFIG_PM +static int serial_pnp_suspend(struct pnp_dev *dev, pm_message_t state) +{ + long line = (long)pnp_get_drvdata(dev); + + if (!line) + return -ENODEV; + serial8250_suspend_port(line - 1); + return 0; +} + +static int serial_pnp_resume(struct pnp_dev *dev) +{ + long line = (long)pnp_get_drvdata(dev); + + if (!line) + return -ENODEV; + serial8250_resume_port(line - 1); + return 0; +} +#else +#define serial_pnp_suspend NULL +#define serial_pnp_resume NULL +#endif /* CONFIG_PM */ + static struct pnp_driver serial_pnp_driver = { .name = "serial", - .id_table = pnp_dev_table, .probe = serial_pnp_probe, .remove = __devexit_p(serial_pnp_remove), + .suspend = serial_pnp_suspend, + .resume = serial_pnp_resume, + .id_table = pnp_dev_table, }; static int __init serial8250_pnp_init(void) diff --git a/trunk/drivers/serial/Kconfig b/trunk/drivers/serial/Kconfig index 0b71e7d18903..fc12d5df10e2 100644 --- a/trunk/drivers/serial/Kconfig +++ b/trunk/drivers/serial/Kconfig @@ -210,6 +210,17 @@ config SERIAL_8250_BOCA To compile this driver as a module, choose M here: the module will be called 8250_boca. +config SERIAL_8250_EXAR_ST16C554 + tristate "Support Exar ST16C554/554D Quad UART" + depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS + help + The Uplogix Envoy TU301 uses this Exar Quad UART. If you are + tinkering with your Envoy TU301, or have a machine with this UART, + say Y here. + + To compile this driver as a module, choose M here: the module + will be called 8250_exar_st16c554. + config SERIAL_8250_HUB6 tristate "Support Hub6 cards" depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS @@ -511,6 +522,25 @@ config SERIAL_IMX_CONSOLE your boot loader (lilo or loadlin) about how to pass options to the kernel at boot time.) +config SERIAL_UARTLITE + tristate "Xilinx uartlite serial port support" + depends on PPC32 + select SERIAL_CORE + help + Say Y here if you want to use the Xilinx uartlite serial controller. + + To compile this driver as a module, choose M here: the + module will be called uartlite.ko. + +config SERIAL_UARTLITE_CONSOLE + bool "Support for console on Xilinx uartlite serial port" + depends on SERIAL_UARTLITE=y + select SERIAL_CORE_CONSOLE + help + Say Y here if you wish to use a Xilinx uartlite as the system + console (the system console is the device which receives all kernel + messages and warnings and which allows logins in single user mode). + config SERIAL_SUNCORE bool depends on SPARC diff --git a/trunk/drivers/serial/Makefile b/trunk/drivers/serial/Makefile index b4d8a7c182e3..df3632cd7df9 100644 --- a/trunk/drivers/serial/Makefile +++ b/trunk/drivers/serial/Makefile @@ -17,6 +17,7 @@ obj-$(CONFIG_SERIAL_8250_CONSOLE) += 8250_early.o obj-$(CONFIG_SERIAL_8250_FOURPORT) += 8250_fourport.o obj-$(CONFIG_SERIAL_8250_ACCENT) += 8250_accent.o obj-$(CONFIG_SERIAL_8250_BOCA) += 8250_boca.o +obj-$(CONFIG_SERIAL_8250_EXAR_ST16C554) += 8250_exar_st16c554.o obj-$(CONFIG_SERIAL_8250_HUB6) += 8250_hub6.o obj-$(CONFIG_SERIAL_8250_MCA) += 8250_mca.o obj-$(CONFIG_SERIAL_8250_AU1X00) += 8250_au1x00.o @@ -55,4 +56,5 @@ obj-$(CONFIG_SERIAL_VR41XX) += vr41xx_siu.o obj-$(CONFIG_SERIAL_SGI_IOC4) += ioc4_serial.o obj-$(CONFIG_SERIAL_SGI_IOC3) += ioc3_serial.o obj-$(CONFIG_SERIAL_ATMEL) += atmel_serial.o +obj-$(CONFIG_SERIAL_UARTLITE) += uartlite.o obj-$(CONFIG_SERIAL_NETX) += netx-serial.o diff --git a/trunk/drivers/serial/amba-pl010.c b/trunk/drivers/serial/amba-pl010.c index 4213fabc62bf..61db6973755a 100644 --- a/trunk/drivers/serial/amba-pl010.c +++ b/trunk/drivers/serial/amba-pl010.c @@ -129,6 +129,8 @@ static void pl010_rx_chars(struct uart_port *port) */ rsr = readb(port->membase + UART01x_RSR) | UART_DUMMY_RSR_RX; if (unlikely(rsr & UART01x_RSR_ANY)) { + writel(0, port->membase + UART01x_ECR); + if (rsr & UART01x_RSR_BE) { rsr &= ~(UART01x_RSR_FE | UART01x_RSR_PE); port->icount.brk++; @@ -343,8 +345,8 @@ static void pl010_shutdown(struct uart_port *port) } static void -pl010_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +pl010_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { unsigned int lcr_h, old_cr; unsigned long flags; diff --git a/trunk/drivers/serial/amba-pl011.c b/trunk/drivers/serial/amba-pl011.c index d503625730df..9a3b374b2a08 100644 --- a/trunk/drivers/serial/amba-pl011.c +++ b/trunk/drivers/serial/amba-pl011.c @@ -412,8 +412,8 @@ static void pl011_shutdown(struct uart_port *port) } static void -pl011_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +pl011_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { unsigned int lcr_h, old_cr; unsigned long flags; diff --git a/trunk/drivers/serial/atmel_serial.c b/trunk/drivers/serial/atmel_serial.c index 391a1f4167a4..ed7f7209ea59 100644 --- a/trunk/drivers/serial/atmel_serial.c +++ b/trunk/drivers/serial/atmel_serial.c @@ -1,5 +1,5 @@ /* - * linux/drivers/char/at91_serial.c + * linux/drivers/char/atmel_serial.c * * Driver for Atmel AT91 / AT32 Serial ports * Copyright (C) 2003 Rick Bronson @@ -36,11 +36,11 @@ #include -#include #include #include +#include #ifdef CONFIG_ARM -#include +#include #include #endif @@ -137,8 +137,8 @@ static void atmel_set_mctrl(struct uart_port *port, u_int mctrl) unsigned int control = 0; unsigned int mode; -#ifdef CONFIG_ARM - if (arch_identify() == ARCH_ID_AT91RM9200) { +#ifdef CONFIG_ARCH_AT91RM9200 + if (cpu_is_at91rm9200()) { /* * AT91RM9200 Errata #39: RTS0 is not internally connected to PA21. * We need to drive the pin manually. @@ -478,7 +478,7 @@ static void atmel_serial_pm(struct uart_port *port, unsigned int state, unsigned /* * Change the port parameters */ -static void atmel_set_termios(struct uart_port *port, struct termios * termios, struct termios * old) +static void atmel_set_termios(struct uart_port *port, struct ktermios * termios, struct ktermios * old) { unsigned long flags; unsigned int mode, imr, quot, baud; diff --git a/trunk/drivers/serial/atmel_serial.h b/trunk/drivers/serial/atmel_serial.h index eced2ad1a8d9..fe1763b2a6d5 100644 --- a/trunk/drivers/serial/atmel_serial.h +++ b/trunk/drivers/serial/atmel_serial.h @@ -31,8 +31,8 @@ #define ATMEL_US_RSTIT (1 << 13) /* Reset Iterations */ #define ATMEL_US_RSTNACK (1 << 14) /* Reset Non Acknowledge */ #define ATMEL_US_RETTO (1 << 15) /* Rearm Time-out */ -#define ATMEL_US_DTREN (1 << 16) /* Data Terminal Ready Enable */ -#define ATMEL_US_DTRDIS (1 << 17) /* Data Terminal Ready Disable */ +#define ATMEL_US_DTREN (1 << 16) /* Data Terminal Ready Enable [AT91RM9200 only] */ +#define ATMEL_US_DTRDIS (1 << 17) /* Data Terminal Ready Disable [AT91RM9200 only] */ #define ATMEL_US_RTSEN (1 << 18) /* Request To Send Enable */ #define ATMEL_US_RTSDIS (1 << 19) /* Request To Send Disable */ @@ -92,9 +92,9 @@ #define ATMEL_US_TXBUFE (1 << 11) /* Transmission Buffer Empty */ #define ATMEL_US_RXBUFF (1 << 12) /* Reception Buffer Full */ #define ATMEL_US_NACK (1 << 13) /* Non Acknowledge */ -#define ATMEL_US_RIIC (1 << 16) /* Ring Indicator Input Change */ -#define ATMEL_US_DSRIC (1 << 17) /* Data Set Ready Input Change */ -#define ATMEL_US_DCDIC (1 << 18) /* Data Carrier Detect Input Change */ +#define ATMEL_US_RIIC (1 << 16) /* Ring Indicator Input Change [AT91RM9200 only] */ +#define ATMEL_US_DSRIC (1 << 17) /* Data Set Ready Input Change [AT91RM9200 only] */ +#define ATMEL_US_DCDIC (1 << 18) /* Data Carrier Detect Input Change [AT91RM9200 only] */ #define ATMEL_US_CTSIC (1 << 19) /* Clear to Send Input Change */ #define ATMEL_US_RI (1 << 20) /* RI */ #define ATMEL_US_DSR (1 << 21) /* DSR */ @@ -106,6 +106,7 @@ #define ATMEL_US_CSR 0x14 /* Channel Status Register */ #define ATMEL_US_RHR 0x18 /* Receiver Holding Register */ #define ATMEL_US_THR 0x1c /* Transmitter Holding Register */ +#define ATMEL_US_SYNH (1 << 15) /* Transmit/Receive Sync [SAM9 only] */ #define ATMEL_US_BRGR 0x20 /* Baud Rate Generator Register */ #define ATMEL_US_CD (0xffff << 0) /* Clock Divider */ diff --git a/trunk/drivers/serial/clps711x.c b/trunk/drivers/serial/clps711x.c index 598012714882..23827189ec0e 100644 --- a/trunk/drivers/serial/clps711x.c +++ b/trunk/drivers/serial/clps711x.c @@ -286,8 +286,8 @@ static void clps711xuart_shutdown(struct uart_port *port) } static void -clps711xuart_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +clps711xuart_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { unsigned int ubrlcr, baud, quot; unsigned long flags; diff --git a/trunk/drivers/serial/crisv10.c b/trunk/drivers/serial/crisv10.c index 7a24e53546c7..42b050c46abe 100644 --- a/trunk/drivers/serial/crisv10.c +++ b/trunk/drivers/serial/crisv10.c @@ -804,8 +804,8 @@ static struct e100_serial rs_table[] = { #define NR_PORTS (sizeof(rs_table)/sizeof(struct e100_serial)) -static struct termios *serial_termios[NR_PORTS]; -static struct termios *serial_termios_locked[NR_PORTS]; +static struct ktermios *serial_termios[NR_PORTS]; +static struct ktermios *serial_termios_locked[NR_PORTS]; #ifdef CONFIG_ETRAX_SERIAL_FAST_TIMER static struct fast_timer fast_timers[NR_PORTS]; #endif @@ -4223,7 +4223,7 @@ rs_ioctl(struct tty_struct *tty, struct file * file, } static void -rs_set_termios(struct tty_struct *tty, struct termios *old_termios) +rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { struct e100_serial *info = (struct e100_serial *)tty->driver_data; @@ -4877,6 +4877,8 @@ rs_init(void) driver->init_termios = tty_std_termios; driver->init_termios.c_cflag = B115200 | CS8 | CREAD | HUPCL | CLOCAL; /* is normally B9600 default... */ + driver->init_termios.c_ispeed = 115200; + driver->init_termios.c_ospeed = 115200; driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; driver->termios = serial_termios; driver->termios_locked = serial_termios_locked; diff --git a/trunk/drivers/serial/crisv10.h b/trunk/drivers/serial/crisv10.h index f30b93d6ef79..4a23340663aa 100644 --- a/trunk/drivers/serial/crisv10.h +++ b/trunk/drivers/serial/crisv10.h @@ -93,8 +93,8 @@ struct e100_serial { struct work_struct work; struct async_icount icount; /* error-statistics etc.*/ - struct termios normal_termios; - struct termios callout_termios; + struct ktermios normal_termios; + struct ktermios callout_termios; #ifdef DECLARE_WAITQUEUE wait_queue_head_t open_wait; wait_queue_head_t close_wait; diff --git a/trunk/drivers/serial/dz.c b/trunk/drivers/serial/dz.c index 53662b33b841..587d87b9eb3c 100644 --- a/trunk/drivers/serial/dz.c +++ b/trunk/drivers/serial/dz.c @@ -1,11 +1,13 @@ /* - * dz.c: Serial port driver for DECStations equiped + * dz.c: Serial port driver for DECstations equipped * with the DZ chipset. * * Copyright (C) 1998 Olivier A. D. Lebaillif * * Email: olivier.lebaillif@ifrsys.com * + * Copyright (C) 2004, 2006 Maciej W. Rozycki + * * [31-AUG-98] triemer * Changed IRQ to use Harald's dec internals interrupts.h * removed base_addr code - moving address assignment to setup.c @@ -26,10 +28,16 @@ #undef DEBUG_DZ +#if defined(CONFIG_SERIAL_DZ_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) +#define SUPPORT_SYSRQ +#endif + +#include #include #include #include #include +#include #include #include #include @@ -45,14 +53,10 @@ #include #include -#define CONSOLE_LINE (3) /* for definition of struct console */ - #include "dz.h" -#define DZ_INTR_DEBUG 1 - static char *dz_name = "DECstation DZ serial driver version "; -static char *dz_version = "1.02"; +static char *dz_version = "1.03"; struct dz_port { struct uart_port port; @@ -61,22 +65,6 @@ struct dz_port { static struct dz_port dz_ports[DZ_NB_PORT]; -#ifdef DEBUG_DZ -/* - * debugging code to send out chars via prom - */ -static void debug_console(const char *s, int count) -{ - unsigned i; - - for (i = 0; i < count; i++) { - if (*s == 10) - prom_printf("%c", 13); - prom_printf("%c", *s++); - } -} -#endif - /* * ------------------------------------------------------------ * dz_in () and dz_out () @@ -90,6 +78,7 @@ static inline unsigned short dz_in(struct dz_port *dport, unsigned offset) { volatile unsigned short *addr = (volatile unsigned short *) (dport->port.membase + offset); + return *addr; } @@ -98,6 +87,7 @@ static inline void dz_out(struct dz_port *dport, unsigned offset, { volatile unsigned short *addr = (volatile unsigned short *) (dport->port.membase + offset); + *addr = value; } @@ -144,7 +134,7 @@ static void dz_stop_rx(struct uart_port *uport) spin_lock_irqsave(&dport->port.lock, flags); dport->cflag &= ~DZ_CREAD; - dz_out(dport, DZ_LPR, dport->cflag); + dz_out(dport, DZ_LPR, dport->cflag | dport->port.line); spin_unlock_irqrestore(&dport->port.lock, flags); } @@ -155,14 +145,14 @@ static void dz_enable_ms(struct uart_port *port) /* * ------------------------------------------------------------ - * Here starts the interrupt handling routines. All of the - * following subroutines are declared as inline and are folded - * into dz_interrupt. They were separated out for readability's - * sake. * - * Note: rs_interrupt() is a "fast" interrupt, which means that it + * Here start the interrupt handling routines. All of the following + * subroutines are declared as inline and are folded into + * dz_interrupt. They were separated out for readability's sake. + * + * Note: dz_interrupt() is a "fast" interrupt, which means that it * runs with interrupts turned off. People who may want to modify - * rs_interrupt() should try to keep the interrupt handler as fast as + * dz_interrupt() should try to keep the interrupt handler as fast as * possible. After you are done making modifications, it is not a bad * idea to do: * @@ -180,92 +170,74 @@ static void dz_enable_ms(struct uart_port *port) * This routine deals with inputs from any lines. * ------------------------------------------------------------ */ -static inline void dz_receive_chars(struct dz_port *dport) +static inline void dz_receive_chars(struct dz_port *dport_in, + struct pt_regs *regs) { + struct dz_port *dport; struct tty_struct *tty = NULL; struct uart_icount *icount; - int ignore = 0; - unsigned short status, tmp; + int lines_rx[DZ_NB_PORT] = { [0 ... DZ_NB_PORT - 1] = 0 }; + unsigned short status; unsigned char ch, flag; + int i; - /* this code is going to be a problem... - the call to tty_flip_buffer is going to need - to be rethought... - */ - do { - status = dz_in(dport, DZ_RBUF); - - /* punt so we don't get duplicate characters */ - if (!(status & DZ_DVAL)) - goto ignore_char; - - - ch = UCHAR(status); /* grab the char */ - flag = TTY_NORMAL; + while ((status = dz_in(dport_in, DZ_RBUF)) & DZ_DVAL) { + dport = &dz_ports[LINE(status)]; + tty = dport->port.info->tty; /* point to the proper dev */ -#if 0 - if (info->is_console) { - if (ch == 0) - return; /* it's a break ... */ - } -#endif + ch = UCHAR(status); /* grab the char */ - tty = dport->port.info->tty;/* now tty points to the proper dev */ icount = &dport->port.icount; - - if (!tty) - break; - icount->rx++; - /* keep track of the statistics */ - if (status & (DZ_OERR | DZ_FERR | DZ_PERR)) { - if (status & DZ_PERR) /* parity error */ - icount->parity++; - else if (status & DZ_FERR) /* frame error */ - icount->frame++; - if (status & DZ_OERR) /* overrun error */ - icount->overrun++; - - /* check to see if we should ignore the character - and mask off conditions that should be ignored + flag = TTY_NORMAL; + if (status & DZ_FERR) { /* frame error */ + /* + * There is no separate BREAK status bit, so + * treat framing errors as BREAKs for Magic SysRq + * and SAK; normally, otherwise. */ - - if (status & dport->port.ignore_status_mask) { - if (++ignore > 100) - break; - goto ignore_char; - } - /* mask off the error conditions we want to ignore */ - tmp = status & dport->port.read_status_mask; - - if (tmp & DZ_PERR) { - flag = TTY_PARITY; -#ifdef DEBUG_DZ - debug_console("PERR\n", 5); -#endif - } else if (tmp & DZ_FERR) { + if (uart_handle_break(&dport->port)) + continue; + if (dport->port.flags & UPF_SAK) + flag = TTY_BREAK; + else flag = TTY_FRAME; -#ifdef DEBUG_DZ - debug_console("FERR\n", 5); -#endif - } - if (tmp & DZ_OERR) { -#ifdef DEBUG_DZ - debug_console("OERR\n", 5); -#endif - tty_insert_flip_char(tty, ch, flag); - ch = 0; - flag = TTY_OVERRUN; - } + } else if (status & DZ_OERR) /* overrun error */ + flag = TTY_OVERRUN; + else if (status & DZ_PERR) /* parity error */ + flag = TTY_PARITY; + + /* keep track of the statistics */ + switch (flag) { + case TTY_FRAME: + icount->frame++; + break; + case TTY_PARITY: + icount->parity++; + break; + case TTY_OVERRUN: + icount->overrun++; + break; + case TTY_BREAK: + icount->brk++; + break; + default: + break; } - tty_insert_flip_char(tty, ch, flag); - ignore_char: - ; - } while (status & DZ_DVAL); - if (tty) - tty_flip_buffer_push(tty); + if (uart_handle_sysrq_char(&dport->port, ch, regs)) + continue; + + if ((status & dport->port.ignore_status_mask) == 0) { + uart_insert_char(&dport->port, + status, DZ_OERR, ch, flag); + lines_rx[LINE(status)] = 1; + } + } + for (i = 0; i < DZ_NB_PORT; i++) + if (lines_rx[i]) + tty_flip_buffer_push(dz_ports[i].port.info->tty); } /* @@ -275,26 +247,32 @@ static inline void dz_receive_chars(struct dz_port *dport) * This routine deals with outputs to any lines. * ------------------------------------------------------------ */ -static inline void dz_transmit_chars(struct dz_port *dport) +static inline void dz_transmit_chars(struct dz_port *dport_in) { - struct circ_buf *xmit = &dport->port.info->xmit; + struct dz_port *dport; + struct circ_buf *xmit; + unsigned short status; unsigned char tmp; - if (dport->port.x_char) { /* XON/XOFF chars */ + status = dz_in(dport_in, DZ_CSR); + dport = &dz_ports[LINE(status)]; + xmit = &dport->port.info->xmit; + + if (dport->port.x_char) { /* XON/XOFF chars */ dz_out(dport, DZ_TDR, dport->port.x_char); dport->port.icount.tx++; dport->port.x_char = 0; return; } - /* if nothing to do or stopped or hardware stopped */ + /* If nothing to do or stopped or hardware stopped. */ if (uart_circ_empty(xmit) || uart_tx_stopped(&dport->port)) { dz_stop_tx(&dport->port); return; } /* - * if something to do ... (rember the dz has no output fifo so we go - * one char at a time :-< + * If something to do... (remember the dz has no output fifo, + * so we go one char at a time) :-< */ tmp = xmit->buf[xmit->tail]; xmit->tail = (xmit->tail + 1) & (DZ_XMIT_SIZE - 1); @@ -304,23 +282,29 @@ static inline void dz_transmit_chars(struct dz_port *dport) if (uart_circ_chars_pending(xmit) < DZ_WAKEUP_CHARS) uart_write_wakeup(&dport->port); - /* Are we done */ + /* Are we are done. */ if (uart_circ_empty(xmit)) dz_stop_tx(&dport->port); } /* * ------------------------------------------------------------ - * check_modem_status () + * check_modem_status() * - * Only valid for the MODEM line duh ! + * DS 3100 & 5100: Only valid for the MODEM line, duh! + * DS 5000/200: Valid for the MODEM and PRINTER line. * ------------------------------------------------------------ */ static inline void check_modem_status(struct dz_port *dport) { + /* + * FIXME: + * 1. No status change interrupt; use a timer. + * 2. Handle the 3100/5000 as appropriate. --macro + */ unsigned short status; - /* if not ne modem line just return */ + /* If not the modem line just return. */ if (dport->port.line != DZ_MODEM) return; @@ -341,21 +325,18 @@ static inline void check_modem_status(struct dz_port *dport) */ static irqreturn_t dz_interrupt(int irq, void *dev) { - struct dz_port *dport; + struct dz_port *dport = (struct dz_port *)dev; unsigned short status; /* get the reason why we just got an irq */ - status = dz_in((struct dz_port *)dev, DZ_CSR); - dport = &dz_ports[LINE(status)]; + status = dz_in(dport, DZ_CSR); - if (status & DZ_RDONE) - dz_receive_chars(dport); + if ((status & (DZ_RDONE | DZ_RIE)) == (DZ_RDONE | DZ_RIE)) + dz_receive_chars(dport, regs); - if (status & DZ_TRDY) + if ((status & (DZ_TRDY | DZ_TIE)) == (DZ_TRDY | DZ_TIE)) dz_transmit_chars(dport); - /* FIXME: what about check modem status??? --rmk */ - return IRQ_HANDLED; } @@ -367,13 +348,13 @@ static irqreturn_t dz_interrupt(int irq, void *dev) static unsigned int dz_get_mctrl(struct uart_port *uport) { + /* + * FIXME: Handle the 3100/5000 as appropriate. --macro + */ struct dz_port *dport = (struct dz_port *)uport; unsigned int mctrl = TIOCM_CAR | TIOCM_DSR | TIOCM_CTS; if (dport->port.line == DZ_MODEM) { - /* - * CHECKME: This is a guess from the other code... --rmk - */ if (dz_in(dport, DZ_MSR) & DZ_MODEM_DSR) mctrl &= ~TIOCM_DSR; } @@ -383,6 +364,9 @@ static unsigned int dz_get_mctrl(struct uart_port *uport) static void dz_set_mctrl(struct uart_port *uport, unsigned int mctrl) { + /* + * FIXME: Handle the 3100/5000 as appropriate. --macro + */ struct dz_port *dport = (struct dz_port *)uport; unsigned short tmp; @@ -409,13 +393,6 @@ static int dz_startup(struct uart_port *uport) unsigned long flags; unsigned short tmp; - /* The dz lines for the mouse/keyboard must be - * opened using their respective drivers. - */ - if ((dport->port.line == DZ_KEYBOARD) || - (dport->port.line == DZ_MOUSE)) - return -ENODEV; - spin_lock_irqsave(&dport->port.lock, flags); /* enable the interrupt and the scanning */ @@ -442,7 +419,8 @@ static void dz_shutdown(struct uart_port *uport) } /* - * get_lsr_info - get line status register info + * ------------------------------------------------------------------- + * dz_tx_empty() -- get the transmitter empty status * * Purpose: Let user call ioctl() to get info when the UART physically * is emptied. On bus types like RS485, the transmitter must @@ -450,21 +428,28 @@ static void dz_shutdown(struct uart_port *uport) * the transmit shift register is empty, not be done when the * transmit holding register is empty. This functionality * allows an RS485 driver to be written in user space. + * ------------------------------------------------------------------- */ static unsigned int dz_tx_empty(struct uart_port *uport) { struct dz_port *dport = (struct dz_port *)uport; - unsigned short status = dz_in(dport, DZ_LPR); + unsigned short tmp, mask = 1 << dport->port.line; - /* FIXME: this appears to be obviously broken --rmk. */ - return status ? TIOCSER_TEMT : 0; + tmp = dz_in(dport, DZ_TCR); + tmp &= mask; + + return tmp ? 0 : TIOCSER_TEMT; } static void dz_break_ctl(struct uart_port *uport, int break_state) { + /* + * FIXME: Can't access BREAK bits in TDR easily; + * reuse the code for polled TX. --macro + */ struct dz_port *dport = (struct dz_port *)uport; unsigned long flags; - unsigned short tmp, mask = 1 << uport->line; + unsigned short tmp, mask = 1 << dport->port.line; spin_lock_irqsave(&uport->lock, flags); tmp = dz_in(dport, DZ_TCR); @@ -476,8 +461,8 @@ static void dz_break_ctl(struct uart_port *uport, int break_state) spin_unlock_irqrestore(&uport->lock, flags); } -static void dz_set_termios(struct uart_port *uport, struct termios *termios, - struct termios *old_termios) +static void dz_set_termios(struct uart_port *uport, struct ktermios *termios, + struct ktermios *old_termios) { struct dz_port *dport = (struct dz_port *)uport; unsigned long flags; @@ -561,7 +546,7 @@ static void dz_set_termios(struct uart_port *uport, struct termios *termios, spin_lock_irqsave(&dport->port.lock, flags); - dz_out(dport, DZ_LPR, cflag); + dz_out(dport, DZ_LPR, cflag | dport->port.line); dport->cflag = cflag; /* setup accept flag */ @@ -650,7 +635,7 @@ static void __init dz_init_ports(void) for (i = 0, dport = dz_ports; i < DZ_NB_PORT; i++, dport++) { spin_lock_init(&dport->port.lock); dport->port.membase = (char *) base; - dport->port.iotype = UPIO_PORT; + dport->port.iotype = UPIO_MEM; dport->port.irq = dec_interrupt[DEC_IRQ_DZ11]; dport->port.line = i; dport->port.fifosize = 1; @@ -662,10 +647,7 @@ static void __init dz_init_ports(void) static void dz_reset(struct dz_port *dport) { dz_out(dport, DZ_CSR, DZ_CLR); - while (dz_in(dport, DZ_CSR) & DZ_CLR); - /* FIXME: cpu_relax? */ - iob(); /* enable scanning */ @@ -673,26 +655,55 @@ static void dz_reset(struct dz_port *dport) } #ifdef CONFIG_SERIAL_DZ_CONSOLE +/* + * ------------------------------------------------------------------- + * dz_console_putchar() -- transmit a character + * + * Polled transmission. This is tricky. We need to mask transmit + * interrupts so that they do not interfere, enable the transmitter + * for the line requested and then wait till the transmit scanner + * requests data for this line. But it may request data for another + * line first, in which case we have to disable its transmitter and + * repeat waiting till our line pops up. Only then the character may + * be transmitted. Finally, the state of the transmitter mask is + * restored. Welcome to the world of PDP-11! + * ------------------------------------------------------------------- + */ static void dz_console_putchar(struct uart_port *uport, int ch) { struct dz_port *dport = (struct dz_port *)uport; unsigned long flags; - int loops = 2500; - unsigned short tmp = (unsigned char)ch; - /* this code sends stuff out to serial device - spinning its - wheels and waiting. */ + unsigned short csr, tcr, trdy, mask; + int loops = 10000; spin_lock_irqsave(&dport->port.lock, flags); + csr = dz_in(dport, DZ_CSR); + dz_out(dport, DZ_CSR, csr & ~DZ_TIE); + tcr = dz_in(dport, DZ_TCR); + tcr |= 1 << dport->port.line; + mask = tcr; + dz_out(dport, DZ_TCR, mask); + iob(); + spin_unlock_irqrestore(&dport->port.lock, flags); - /* spin our wheels */ - while (((dz_in(dport, DZ_CSR) & DZ_TRDY) != DZ_TRDY) && loops--) - /* FIXME: cpu_relax, udelay? --rmk */ - ; + while (loops--) { + trdy = dz_in(dport, DZ_CSR); + if (!(trdy & DZ_TRDY)) + continue; + trdy = (trdy & DZ_TLINE) >> 8; + if (trdy == dport->port.line) + break; + mask &= ~(1 << trdy); + dz_out(dport, DZ_TCR, mask); + iob(); + udelay(2); + } - /* Actually transmit the character. */ - dz_out(dport, DZ_TDR, tmp); + if (loops) /* Cannot send otherwise. */ + dz_out(dport, DZ_TDR, ch); - spin_unlock_irqrestore(&dport->port.lock, flags); + dz_out(dport, DZ_TCR, tcr); + dz_out(dport, DZ_CSR, csr); } /* @@ -703,11 +714,11 @@ static void dz_console_putchar(struct uart_port *uport, int ch) * The console must be locked when we get here. * ------------------------------------------------------------------- */ -static void dz_console_print(struct console *cons, +static void dz_console_print(struct console *co, const char *str, unsigned int count) { - struct dz_port *dport = &dz_ports[CONSOLE_LINE]; + struct dz_port *dport = &dz_ports[co->index]; #ifdef DEBUG_DZ prom_printf((char *) str); #endif @@ -716,49 +727,43 @@ static void dz_console_print(struct console *cons, static int __init dz_console_setup(struct console *co, char *options) { - struct dz_port *dport = &dz_ports[CONSOLE_LINE]; + struct dz_port *dport = &dz_ports[co->index]; int baud = 9600; int bits = 8; int parity = 'n'; int flow = 'n'; - int ret; - unsigned short mask, tmp; if (options) uart_parse_options(options, &baud, &parity, &bits, &flow); dz_reset(dport); - ret = uart_set_options(&dport->port, co, baud, parity, bits, flow); - if (ret == 0) { - mask = 1 << dport->port.line; - tmp = dz_in(dport, DZ_TCR); /* read the TX flag */ - if (!(tmp & mask)) { - tmp |= mask; /* set the TX flag */ - dz_out(dport, DZ_TCR, tmp); - } - } - - return ret; + return uart_set_options(&dport->port, co, baud, parity, bits, flow); } -static struct console dz_sercons = -{ +static struct uart_driver dz_reg; +static struct console dz_sercons = { .name = "ttyS", .write = dz_console_print, .device = uart_console_device, .setup = dz_console_setup, - .flags = CON_CONSDEV | CON_PRINTBUFFER, - .index = CONSOLE_LINE, + .flags = CON_PRINTBUFFER, + .index = -1, + .data = &dz_reg, }; -void __init dz_serial_console_init(void) +static int __init dz_serial_console_init(void) { - dz_init_ports(); - - register_console(&dz_sercons); + if (!IOASIC) { + dz_init_ports(); + register_console(&dz_sercons); + return 0; + } else + return -ENXIO; } +console_initcall(dz_serial_console_init); + #define SERIAL_DZ_CONSOLE &dz_sercons #else #define SERIAL_DZ_CONSOLE NULL @@ -767,35 +772,29 @@ void __init dz_serial_console_init(void) static struct uart_driver dz_reg = { .owner = THIS_MODULE, .driver_name = "serial", - .dev_name = "ttyS%d", + .dev_name = "ttyS", .major = TTY_MAJOR, .minor = 64, .nr = DZ_NB_PORT, .cons = SERIAL_DZ_CONSOLE, }; -int __init dz_init(void) +static int __init dz_init(void) { - unsigned long flags; int ret, i; + if (IOASIC) + return -ENXIO; + printk("%s%s\n", dz_name, dz_version); dz_init_ports(); - save_flags(flags); - cli(); - #ifndef CONFIG_SERIAL_DZ_CONSOLE /* reset the chip */ dz_reset(&dz_ports[0]); #endif - /* order matters here... the trick is that flags - is updated... in request_irq - to immediatedly obliterate - it is unwise. */ - restore_flags(flags); - if (request_irq(dz_ports[0].port.irq, dz_interrupt, IRQF_DISABLED, "DZ", &dz_ports[0])) panic("Unable to register DZ interrupt"); @@ -810,5 +809,7 @@ int __init dz_init(void) return ret; } +module_init(dz_init); + MODULE_DESCRIPTION("DECstation DZ serial driver"); MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/serial/dz.h b/trunk/drivers/serial/dz.h index 86ef417382bb..9674d4e49872 100644 --- a/trunk/drivers/serial/dz.h +++ b/trunk/drivers/serial/dz.h @@ -1,20 +1,22 @@ /* - * dz.h: Serial port driver for DECStations equiped + * dz.h: Serial port driver for DECstations equipped * with the DZ chipset. * * Copyright (C) 1998 Olivier A. D. Lebaillif * * Email: olivier.lebaillif@ifrsys.com * + * Copyright (C) 2004, 2006 Maciej W. Rozycki */ #ifndef DZ_SERIAL_H #define DZ_SERIAL_H /* - * Definitions for the Control and Status Received. + * Definitions for the Control and Status Register. */ #define DZ_TRDY 0x8000 /* Transmitter empty */ -#define DZ_TIE 0x4000 /* Transmitter Interrupt Enable */ +#define DZ_TIE 0x4000 /* Transmitter Interrupt Enbl */ +#define DZ_TLINE 0x0300 /* Transmitter Line Number */ #define DZ_RDONE 0x0080 /* Receiver data ready */ #define DZ_RIE 0x0040 /* Receive Interrupt Enable */ #define DZ_MSE 0x0020 /* Master Scan Enable */ @@ -22,32 +24,44 @@ #define DZ_MAINT 0x0008 /* Loop Back Mode */ /* - * Definitions for the Received buffer. + * Definitions for the Receiver Buffer Register. */ -#define DZ_RBUF_MASK 0x00FF /* Data Mask in the Receive Buffer */ -#define DZ_LINE_MASK 0x0300 /* Line Mask in the Receive Buffer */ +#define DZ_RBUF_MASK 0x00FF /* Data Mask */ +#define DZ_LINE_MASK 0x0300 /* Line Mask */ #define DZ_DVAL 0x8000 /* Valid Data indicator */ #define DZ_OERR 0x4000 /* Overrun error indicator */ #define DZ_FERR 0x2000 /* Frame error indicator */ #define DZ_PERR 0x1000 /* Parity error indicator */ -#define LINE(x) (x & DZ_LINE_MASK) >> 8 /* Get the line number from the input buffer */ -#define UCHAR(x) (unsigned char)(x & DZ_RBUF_MASK) +#define LINE(x) ((x & DZ_LINE_MASK) >> 8) /* Get the line number + from the input buffer */ +#define UCHAR(x) ((unsigned char)(x & DZ_RBUF_MASK)) /* - * Definitions for the Transmit Register. + * Definitions for the Transmit Control Register. */ #define DZ_LINE_KEYBOARD 0x0001 #define DZ_LINE_MOUSE 0x0002 #define DZ_LINE_MODEM 0x0004 #define DZ_LINE_PRINTER 0x0008 +#define DZ_MODEM_RTS 0x0800 /* RTS for the modem line (2) */ #define DZ_MODEM_DTR 0x0400 /* DTR for the modem line (2) */ +#define DZ_PRINT_RTS 0x0200 /* RTS for the prntr line (3) */ +#define DZ_PRINT_DTR 0x0100 /* DTR for the prntr line (3) */ +#define DZ_LNENB 0x000f /* Transmitter Line Enable */ /* * Definitions for the Modem Status Register. */ +#define DZ_MODEM_RI 0x0800 /* RI for the modem line (2) */ +#define DZ_MODEM_CD 0x0400 /* CD for the modem line (2) */ #define DZ_MODEM_DSR 0x0200 /* DSR for the modem line (2) */ +#define DZ_MODEM_CTS 0x0100 /* CTS for the modem line (2) */ +#define DZ_PRINT_RI 0x0008 /* RI for the printer line (3) */ +#define DZ_PRINT_CD 0x0004 /* CD for the printer line (3) */ +#define DZ_PRINT_DSR 0x0002 /* DSR for the prntr line (3) */ +#define DZ_PRINT_CTS 0x0001 /* CTS for the prntr line (3) */ /* * Definitions for the Transmit Data Register. diff --git a/trunk/drivers/serial/icom.c b/trunk/drivers/serial/icom.c index 8aa0f641866b..7d623003e65e 100644 --- a/trunk/drivers/serial/icom.c +++ b/trunk/drivers/serial/icom.c @@ -1087,8 +1087,8 @@ static void icom_close(struct uart_port *port) } static void icom_set_termios(struct uart_port *port, - struct termios *termios, - struct termios *old_termios) + struct ktermios *termios, + struct ktermios *old_termios) { int baud; unsigned cflag, iflag; diff --git a/trunk/drivers/serial/imx.c b/trunk/drivers/serial/imx.c index ee5c782597dd..e216dcf29376 100644 --- a/trunk/drivers/serial/imx.c +++ b/trunk/drivers/serial/imx.c @@ -459,8 +459,8 @@ static void imx_shutdown(struct uart_port *port) } static void -imx_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +imx_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { struct imx_port *sport = (struct imx_port *)port; unsigned long flags; diff --git a/trunk/drivers/serial/ioc3_serial.c b/trunk/drivers/serial/ioc3_serial.c index 2308d26c8629..9cc0be932316 100644 --- a/trunk/drivers/serial/ioc3_serial.c +++ b/trunk/drivers/serial/ioc3_serial.c @@ -950,7 +950,7 @@ static void transmit_chars(struct uart_port *the_port) */ static void ioc3_change_speed(struct uart_port *the_port, - struct termios *new_termios, struct termios *old_termios) + struct ktermios *new_termios, struct ktermios *old_termios) { struct ioc3_port *port = get_ioc3_port(the_port); unsigned int cflag; @@ -1853,7 +1853,7 @@ static int ic3_startup(struct uart_port *the_port) */ static void ic3_set_termios(struct uart_port *the_port, - struct termios *termios, struct termios *old_termios) + struct ktermios *termios, struct ktermios *old_termios) { unsigned long port_flags; diff --git a/trunk/drivers/serial/ioc4_serial.c b/trunk/drivers/serial/ioc4_serial.c index 711bd1511439..c862f67c985a 100644 --- a/trunk/drivers/serial/ioc4_serial.c +++ b/trunk/drivers/serial/ioc4_serial.c @@ -1681,7 +1681,7 @@ static void transmit_chars(struct uart_port *the_port) */ static void ioc4_change_speed(struct uart_port *the_port, - struct termios *new_termios, struct termios *old_termios) + struct ktermios *new_termios, struct ktermios *old_termios) { struct ioc4_port *port = get_ioc4_port(the_port, 0); int baud, bits; @@ -1802,7 +1802,7 @@ static inline int ic4_startup_local(struct uart_port *the_port) ioc4_set_proto(port, the_port->mapbase); /* set the speed of the serial port */ - ioc4_change_speed(the_port, info->tty->termios, (struct termios *)0); + ioc4_change_speed(the_port, info->tty->termios, (struct ktermios *)0); return 0; } @@ -2570,7 +2570,7 @@ static int ic4_startup(struct uart_port *the_port) */ static void ic4_set_termios(struct uart_port *the_port, - struct termios *termios, struct termios *old_termios) + struct ktermios *termios, struct ktermios *old_termios) { unsigned long port_flags; diff --git a/trunk/drivers/serial/ip22zilog.c b/trunk/drivers/serial/ip22zilog.c index dca6c1bde8f9..0746c9446ae0 100644 --- a/trunk/drivers/serial/ip22zilog.c +++ b/trunk/drivers/serial/ip22zilog.c @@ -840,8 +840,8 @@ ip22zilog_convert_to_zs(struct uart_ip22zilog_port *up, unsigned int cflag, /* The port lock is not held. */ static void -ip22zilog_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +ip22zilog_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { struct uart_ip22zilog_port *up = (struct uart_ip22zilog_port *) port; unsigned long flags; diff --git a/trunk/drivers/serial/jsm/jsm_tty.c b/trunk/drivers/serial/jsm/jsm_tty.c index f8262e6ad8d3..7cf1c60027f8 100644 --- a/trunk/drivers/serial/jsm/jsm_tty.c +++ b/trunk/drivers/serial/jsm/jsm_tty.c @@ -142,7 +142,7 @@ static void jsm_tty_send_xchar(struct uart_port *port, char ch) { unsigned long lock_flags; struct jsm_channel *channel = (struct jsm_channel *)port; - struct termios *termios; + struct ktermios *termios; spin_lock_irqsave(&port->lock, lock_flags); termios = port->info->tty->termios; @@ -180,7 +180,7 @@ static int jsm_tty_open(struct uart_port *port) struct jsm_board *brd; int rc = 0; struct jsm_channel *channel = (struct jsm_channel *)port; - struct termios *termios; + struct ktermios *termios; /* Get board pointer from our array of majors we have allocated */ brd = channel->ch_bd; @@ -269,7 +269,7 @@ static int jsm_tty_open(struct uart_port *port) static void jsm_tty_close(struct uart_port *port) { struct jsm_board *bd; - struct termios *ts; + struct ktermios *ts; struct jsm_channel *channel = (struct jsm_channel *)port; jsm_printk(CLOSE, INFO, &channel->ch_bd->pci_dev, "start\n"); @@ -302,8 +302,8 @@ static void jsm_tty_close(struct uart_port *port) } static void jsm_tty_set_termios(struct uart_port *port, - struct termios *termios, - struct termios *old_termios) + struct ktermios *termios, + struct ktermios *old_termios) { unsigned long lock_flags; struct jsm_channel *channel = (struct jsm_channel *)port; diff --git a/trunk/drivers/serial/m32r_sio.c b/trunk/drivers/serial/m32r_sio.c index 7656a35f5e2f..6e09c8b395e8 100644 --- a/trunk/drivers/serial/m32r_sio.c +++ b/trunk/drivers/serial/m32r_sio.c @@ -699,7 +699,7 @@ static unsigned int m32r_sio_get_divisor(struct uart_port *port, } static void m32r_sio_set_termios(struct uart_port *port, - struct termios *termios, struct termios *old) + struct ktermios *termios, struct ktermios *old) { struct uart_sio_port *up = (struct uart_sio_port *)port; unsigned char cval = 0; diff --git a/trunk/drivers/serial/mcfserial.c b/trunk/drivers/serial/mcfserial.c index aee1b31f1a1c..08430961a895 100644 --- a/trunk/drivers/serial/mcfserial.c +++ b/trunk/drivers/serial/mcfserial.c @@ -60,7 +60,8 @@ struct timer_list mcfrs_timer_struct; #if defined(CONFIG_HW_FEITH) #define CONSOLE_BAUD_RATE 38400 #define DEFAULT_CBAUD B38400 -#elif defined(CONFIG_MOD5272) || defined(CONFIG_M5208EVB) || defined(CONFIG_M5329EVB) +#elif defined(CONFIG_MOD5272) || defined(CONFIG_M5208EVB) || \ + defined(CONFIG_M5329EVB) || defined(CONFIG_GILBARCO) #define CONSOLE_BAUD_RATE 115200 #define DEFAULT_CBAUD B115200 #elif defined(CONFIG_ARNEWSH) || defined(CONFIG_FREESCALE) || \ @@ -109,12 +110,30 @@ static struct mcf_serial mcfrs_table[] = { .irq = IRQBASE, .flags = ASYNC_BOOT_AUTOCONF, }, +#ifdef MCFUART_BASE2 { /* ttyS1 */ .magic = 0, .addr = (volatile unsigned char *) (MCF_MBAR+MCFUART_BASE2), .irq = IRQBASE+1, .flags = ASYNC_BOOT_AUTOCONF, }, +#endif +#ifdef MCFUART_BASE3 + { /* ttyS2 */ + .magic = 0, + .addr = (volatile unsigned char *) (MCF_MBAR+MCFUART_BASE3), + .irq = IRQBASE+2, + .flags = ASYNC_BOOT_AUTOCONF, + }, +#endif +#ifdef MCFUART_BASE4 + { /* ttyS3 */ + .magic = 0, + .addr = (volatile unsigned char *) (MCF_MBAR+MCFUART_BASE4), + .irq = IRQBASE+3, + .flags = ASYNC_BOOT_AUTOCONF, + }, +#endif }; @@ -1113,7 +1132,7 @@ static int mcfrs_ioctl(struct tty_struct *tty, struct file * file, return 0; } -static void mcfrs_set_termios(struct tty_struct *tty, struct termios *old_termios) +static void mcfrs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { struct mcf_serial *info = (struct mcf_serial *)tty->driver_data; @@ -1516,6 +1535,22 @@ static void mcfrs_irqinit(struct mcf_serial *info) imrp = (volatile unsigned long *) (MCF_MBAR + MCFICM_INTC0 + MCFINTC_IMRL); *imrp &= ~((1 << (info->irq - MCFINT_VECBASE)) | 1); +#if defined(CONFIG_M527x) + { + /* + * External Pin Mask Setting & Enable External Pin for Interface + * mrcbis@aliceposta.it + */ + unsigned short *serpin_enable_mask; + serpin_enable_mask = (MCF_IPSBAR + MCF_GPIO_PAR_UART); + if (info->line == 0) + *serpin_enable_mask |= UART0_ENABLE_MASK; + else if (info->line == 1) + *serpin_enable_mask |= UART1_ENABLE_MASK; + else if (info->line == 2) + *serpin_enable_mask |= UART2_ENABLE_MASK; + } +#endif #elif defined(CONFIG_M520x) volatile unsigned char *icrp, *uartp; volatile unsigned long *imrp; @@ -1713,7 +1748,7 @@ mcfrs_init(void) /* Initialize the tty_driver structure */ mcfrs_serial_driver->owner = THIS_MODULE; mcfrs_serial_driver->name = "ttyS"; - mcfrs_serial_driver->driver_name = "serial"; + mcfrs_serial_driver->driver_name = "mcfserial"; mcfrs_serial_driver->major = TTY_MAJOR; mcfrs_serial_driver->minor_start = 64; mcfrs_serial_driver->type = TTY_DRIVER_TYPE_SERIAL; @@ -1797,10 +1832,23 @@ void mcfrs_init_console(void) uartp[MCFUART_UMR] = MCFUART_MR1_PARITYNONE | MCFUART_MR1_CS8; uartp[MCFUART_UMR] = MCFUART_MR2_STOP1; +#ifdef CONFIG_M5272 +{ + /* + * For the MCF5272, also compute the baudrate fraction. + */ + int fraction = MCF_BUSCLK - (clk * 32 * mcfrs_console_baud); + fraction *= 16; + fraction /= (32 * mcfrs_console_baud); + uartp[MCFUART_UFPD] = (fraction & 0xf); /* set fraction */ + clk = (MCF_BUSCLK / mcfrs_console_baud) / 32; +} +#else clk = ((MCF_BUSCLK / mcfrs_console_baud) + 16) / 32; /* set baud */ +#endif + uartp[MCFUART_UBG1] = (clk & 0xff00) >> 8; /* set msb baud */ uartp[MCFUART_UBG2] = (clk & 0xff); /* set lsb baud */ - uartp[MCFUART_UCSR] = MCFUART_UCSR_RXCLKTIMER | MCFUART_UCSR_TXCLKTIMER; uartp[MCFUART_UCR] = MCFUART_UCR_RXENABLE | MCFUART_UCR_TXENABLE; diff --git a/trunk/drivers/serial/mpc52xx_uart.c b/trunk/drivers/serial/mpc52xx_uart.c index 6dd579ed9777..9d11a75663e6 100644 --- a/trunk/drivers/serial/mpc52xx_uart.c +++ b/trunk/drivers/serial/mpc52xx_uart.c @@ -270,8 +270,8 @@ mpc52xx_uart_shutdown(struct uart_port *port) } static void -mpc52xx_uart_set_termios(struct uart_port *port, struct termios *new, - struct termios *old) +mpc52xx_uart_set_termios(struct uart_port *port, struct ktermios *new, + struct ktermios *old) { struct mpc52xx_psc __iomem *psc = PSC(port); unsigned long flags; diff --git a/trunk/drivers/serial/mpsc.c b/trunk/drivers/serial/mpsc.c index 8eea69f29989..3d2fcc57b1ce 100644 --- a/trunk/drivers/serial/mpsc.c +++ b/trunk/drivers/serial/mpsc.c @@ -555,7 +555,7 @@ mpsc_sdma_start_tx(struct mpsc_port_info *pi) if (!mpsc_sdma_tx_active(pi)) { txre = (struct mpsc_tx_desc *)(pi->txr + (pi->txr_tail * MPSC_TXRE_SIZE)); - dma_cache_sync((void *) txre, MPSC_TXRE_SIZE, DMA_FROM_DEVICE); + dma_cache_sync(pi->port.dev, (void *) txre, MPSC_TXRE_SIZE, DMA_FROM_DEVICE); #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */ invalidate_dcache_range((ulong)txre, @@ -931,7 +931,7 @@ mpsc_init_rings(struct mpsc_port_info *pi) } txre->link = cpu_to_be32(pi->txr_p); /* Wrap last back to first */ - dma_cache_sync((void *) pi->dma_region, MPSC_DMA_ALLOC_SIZE, + dma_cache_sync(pi->port.dev, (void *) pi->dma_region, MPSC_DMA_ALLOC_SIZE, DMA_BIDIRECTIONAL); #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */ @@ -1005,7 +1005,7 @@ mpsc_rx_intr(struct mpsc_port_info *pi) rxre = (struct mpsc_rx_desc *)(pi->rxr + (pi->rxr_posn*MPSC_RXRE_SIZE)); - dma_cache_sync((void *)rxre, MPSC_RXRE_SIZE, DMA_FROM_DEVICE); + dma_cache_sync(pi->port.dev, (void *)rxre, MPSC_RXRE_SIZE, DMA_FROM_DEVICE); #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */ invalidate_dcache_range((ulong)rxre, @@ -1029,7 +1029,7 @@ mpsc_rx_intr(struct mpsc_port_info *pi) } bp = pi->rxb + (pi->rxr_posn * MPSC_RXBE_SIZE); - dma_cache_sync((void *) bp, MPSC_RXBE_SIZE, DMA_FROM_DEVICE); + dma_cache_sync(pi->port.dev, (void *) bp, MPSC_RXBE_SIZE, DMA_FROM_DEVICE); #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */ invalidate_dcache_range((ulong)bp, @@ -1098,7 +1098,7 @@ mpsc_rx_intr(struct mpsc_port_info *pi) SDMA_DESC_CMDSTAT_F | SDMA_DESC_CMDSTAT_L); wmb(); - dma_cache_sync((void *)rxre, MPSC_RXRE_SIZE, DMA_BIDIRECTIONAL); + dma_cache_sync(pi->port.dev, (void *)rxre, MPSC_RXRE_SIZE, DMA_BIDIRECTIONAL); #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */ flush_dcache_range((ulong)rxre, @@ -1109,7 +1109,7 @@ mpsc_rx_intr(struct mpsc_port_info *pi) pi->rxr_posn = (pi->rxr_posn + 1) & (MPSC_RXR_ENTRIES - 1); rxre = (struct mpsc_rx_desc *)(pi->rxr + (pi->rxr_posn * MPSC_RXRE_SIZE)); - dma_cache_sync((void *)rxre, MPSC_RXRE_SIZE, DMA_FROM_DEVICE); + dma_cache_sync(pi->port.dev, (void *)rxre, MPSC_RXRE_SIZE, DMA_FROM_DEVICE); #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */ invalidate_dcache_range((ulong)rxre, @@ -1143,7 +1143,7 @@ mpsc_setup_tx_desc(struct mpsc_port_info *pi, u32 count, u32 intr) SDMA_DESC_CMDSTAT_EI : 0)); wmb(); - dma_cache_sync((void *) txre, MPSC_TXRE_SIZE, DMA_BIDIRECTIONAL); + dma_cache_sync(pi->port.dev, (void *) txre, MPSC_TXRE_SIZE, DMA_BIDIRECTIONAL); #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */ flush_dcache_range((ulong)txre, @@ -1192,7 +1192,7 @@ mpsc_copy_tx_data(struct mpsc_port_info *pi) else /* All tx data copied into ring bufs */ return; - dma_cache_sync((void *) bp, MPSC_TXBE_SIZE, DMA_BIDIRECTIONAL); + dma_cache_sync(pi->port.dev, (void *) bp, MPSC_TXBE_SIZE, DMA_BIDIRECTIONAL); #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */ flush_dcache_range((ulong)bp, @@ -1217,7 +1217,7 @@ mpsc_tx_intr(struct mpsc_port_info *pi) txre = (struct mpsc_tx_desc *)(pi->txr + (pi->txr_tail * MPSC_TXRE_SIZE)); - dma_cache_sync((void *) txre, MPSC_TXRE_SIZE, DMA_FROM_DEVICE); + dma_cache_sync(pi->port.dev, (void *) txre, MPSC_TXRE_SIZE, DMA_FROM_DEVICE); #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */ invalidate_dcache_range((ulong)txre, @@ -1235,7 +1235,7 @@ mpsc_tx_intr(struct mpsc_port_info *pi) txre = (struct mpsc_tx_desc *)(pi->txr + (pi->txr_tail * MPSC_TXRE_SIZE)); - dma_cache_sync((void *) txre, MPSC_TXRE_SIZE, + dma_cache_sync(pi->port.dev, (void *) txre, MPSC_TXRE_SIZE, DMA_FROM_DEVICE); #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */ @@ -1440,8 +1440,8 @@ mpsc_shutdown(struct uart_port *port) } static void -mpsc_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +mpsc_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { struct mpsc_port_info *pi = (struct mpsc_port_info *)port; u32 baud; @@ -1652,7 +1652,7 @@ mpsc_console_write(struct console *co, const char *s, uint count) count--; } - dma_cache_sync((void *) bp, MPSC_TXBE_SIZE, DMA_BIDIRECTIONAL); + dma_cache_sync(pi->port.dev, (void *) bp, MPSC_TXBE_SIZE, DMA_BIDIRECTIONAL); #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) if (pi->cache_mgmt) /* GT642[46]0 Res #COMM-2 */ flush_dcache_range((ulong)bp, diff --git a/trunk/drivers/serial/mux.c b/trunk/drivers/serial/mux.c index 8ad1b8c5ec5d..ccb8fa1800a5 100644 --- a/trunk/drivers/serial/mux.c +++ b/trunk/drivers/serial/mux.c @@ -273,8 +273,8 @@ static void mux_shutdown(struct uart_port *port) * The Serial Mux does not support this function. */ static void -mux_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +mux_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { } diff --git a/trunk/drivers/serial/netx-serial.c b/trunk/drivers/serial/netx-serial.c index 062bad457b1a..b56f7db45031 100644 --- a/trunk/drivers/serial/netx-serial.c +++ b/trunk/drivers/serial/netx-serial.c @@ -337,8 +337,8 @@ static void netx_shutdown(struct uart_port *port) } static void -netx_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +netx_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { unsigned int baud, quot; unsigned char old_cr; diff --git a/trunk/drivers/serial/pmac_zilog.c b/trunk/drivers/serial/pmac_zilog.c index bf9809ed9c0b..752ef07516b9 100644 --- a/trunk/drivers/serial/pmac_zilog.c +++ b/trunk/drivers/serial/pmac_zilog.c @@ -1262,8 +1262,8 @@ static void pmz_irda_setup(struct uart_pmac_port *uap, unsigned long *baud) } -static void __pmz_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +static void __pmz_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { struct uart_pmac_port *uap = to_pmz(port); unsigned long baud; @@ -1273,7 +1273,7 @@ static void __pmz_set_termios(struct uart_port *port, struct termios *termios, if (ZS_IS_ASLEEP(uap)) return; - memcpy(&uap->termios_cache, termios, sizeof(struct termios)); + memcpy(&uap->termios_cache, termios, sizeof(struct ktermios)); /* XXX Check which revs of machines actually allow 1 and 4Mb speeds * on the IR dongle. Note that the IRTTY driver currently doesn't know @@ -1313,8 +1313,8 @@ static void __pmz_set_termios(struct uart_port *port, struct termios *termios, } /* The port lock is not held. */ -static void pmz_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +static void pmz_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { struct uart_pmac_port *uap = to_pmz(port); unsigned long flags; diff --git a/trunk/drivers/serial/pmac_zilog.h b/trunk/drivers/serial/pmac_zilog.h index c03f9bfacdd8..570b0d925e83 100644 --- a/trunk/drivers/serial/pmac_zilog.h +++ b/trunk/drivers/serial/pmac_zilog.h @@ -60,7 +60,7 @@ struct uart_pmac_port { volatile struct dbdma_regs __iomem *tx_dma_regs; volatile struct dbdma_regs __iomem *rx_dma_regs; - struct termios termios_cache; + struct ktermios termios_cache; }; #define to_pmz(p) ((struct uart_pmac_port *)(p)) diff --git a/trunk/drivers/serial/pxa.c b/trunk/drivers/serial/pxa.c index 415fe9633a9b..d403aaa55092 100644 --- a/trunk/drivers/serial/pxa.c +++ b/trunk/drivers/serial/pxa.c @@ -433,8 +433,8 @@ static void serial_pxa_shutdown(struct uart_port *port) } static void -serial_pxa_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +serial_pxa_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { struct uart_pxa_port *up = (struct uart_pxa_port *)port; unsigned char cval, fcr = 0; diff --git a/trunk/drivers/serial/s3c2410.c b/trunk/drivers/serial/s3c2410.c index 8dfc2dd058ca..3ba9208ebd0c 100644 --- a/trunk/drivers/serial/s3c2410.c +++ b/trunk/drivers/serial/s3c2410.c @@ -738,8 +738,8 @@ static unsigned int s3c24xx_serial_getclk(struct uart_port *port, } static void s3c24xx_serial_set_termios(struct uart_port *port, - struct termios *termios, - struct termios *old) + struct ktermios *termios, + struct ktermios *old) { struct s3c2410_uartcfg *cfg = s3c24xx_port_to_cfg(port); struct s3c24xx_uart_port *ourport = to_ourport(port); diff --git a/trunk/drivers/serial/sa1100.c b/trunk/drivers/serial/sa1100.c index d4065266b6fc..58a83c27e14b 100644 --- a/trunk/drivers/serial/sa1100.c +++ b/trunk/drivers/serial/sa1100.c @@ -408,8 +408,8 @@ static void sa1100_shutdown(struct uart_port *port) } static void -sa1100_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +sa1100_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { struct sa1100_port *sport = (struct sa1100_port *)port; unsigned long flags; diff --git a/trunk/drivers/serial/serial_core.c b/trunk/drivers/serial/serial_core.c index c67b05e9a451..f84982e508c7 100644 --- a/trunk/drivers/serial/serial_core.c +++ b/trunk/drivers/serial/serial_core.c @@ -65,7 +65,7 @@ static struct lock_class_key port_lock_key; #define uart_console(port) (0) #endif -static void uart_change_speed(struct uart_state *state, struct termios *old_termios); +static void uart_change_speed(struct uart_state *state, struct ktermios *old_termios); static void uart_wait_until_sent(struct tty_struct *tty, int timeout); static void uart_change_pm(struct uart_state *state, int pm_state); @@ -338,8 +338,8 @@ EXPORT_SYMBOL(uart_update_timeout); * we're actually going to be using. */ unsigned int -uart_get_baud_rate(struct uart_port *port, struct termios *termios, - struct termios *old, unsigned int min, unsigned int max) +uart_get_baud_rate(struct uart_port *port, struct ktermios *termios, + struct ktermios *old, unsigned int min, unsigned int max) { unsigned int try, baud, altbaud = 38400; upf_t flags = port->flags & UPF_SPD_MASK; @@ -421,11 +421,11 @@ uart_get_divisor(struct uart_port *port, unsigned int baud) EXPORT_SYMBOL(uart_get_divisor); static void -uart_change_speed(struct uart_state *state, struct termios *old_termios) +uart_change_speed(struct uart_state *state, struct ktermios *old_termios) { struct tty_struct *tty = state->info->tty; struct uart_port *port = state->port; - struct termios *termios; + struct ktermios *termios; /* * If we have no tty, termios, or the port does not exist, @@ -1139,7 +1139,7 @@ uart_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd, return ret; } -static void uart_set_termios(struct tty_struct *tty, struct termios *old_termios) +static void uart_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { struct uart_state *state = tty->driver_data; unsigned long flags; @@ -1866,7 +1866,7 @@ int __init uart_set_options(struct uart_port *port, struct console *co, int baud, int parity, int bits, int flow) { - struct termios termios; + struct ktermios termios; int i; /* @@ -1876,7 +1876,7 @@ uart_set_options(struct uart_port *port, struct console *co, spin_lock_init(&port->lock); lockdep_set_class(&port->lock, &port_lock_key); - memset(&termios, 0, sizeof(struct termios)); + memset(&termios, 0, sizeof(struct ktermios)); termios.c_cflag = CREAD | HUPCL | CLOCAL; @@ -1991,12 +1991,12 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *port) * Re-enable the console device after suspending. */ if (uart_console(port)) { - struct termios termios; + struct ktermios termios; /* * First try to use the console cflag setting. */ - memset(&termios, 0, sizeof(struct termios)); + memset(&termios, 0, sizeof(struct ktermios)); termios.c_cflag = port->cons->cflag; /* @@ -2189,6 +2189,7 @@ int uart_register_driver(struct uart_driver *drv) normal->subtype = SERIAL_TYPE_NORMAL; normal->init_termios = tty_std_termios; normal->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; + normal->init_termios.c_ispeed = normal->init_termios.c_ospeed = 9600; normal->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; normal->driver_state = drv; tty_set_operations(normal, &uart_ops); diff --git a/trunk/drivers/serial/serial_cs.c b/trunk/drivers/serial/serial_cs.c index 00f9ffd69489..431433f4dd6d 100644 --- a/trunk/drivers/serial/serial_cs.c +++ b/trunk/drivers/serial/serial_cs.c @@ -723,7 +723,7 @@ static int serial_config(struct pcmcia_device * link) u_char *buf; cisparse_t *parse; cistpl_cftable_entry_t *cf; - int i, last_ret, last_fn; + int i; DEBUG(0, "serial_config(0x%p)\n", link); @@ -740,15 +740,6 @@ static int serial_config(struct pcmcia_device * link) tuple->TupleOffset = 0; tuple->TupleDataMax = 255; tuple->Attributes = 0; - /* Get configuration register information */ - tuple->DesiredTuple = CISTPL_CONFIG; - last_ret = first_tuple(link, tuple, parse); - if (last_ret != CS_SUCCESS) { - last_fn = ParseTuple; - goto cs_failed; - } - link->conf.ConfigBase = parse->config.base; - link->conf.Present = parse->config.rmask[0]; /* Is this a compliant multifunction card? */ tuple->DesiredTuple = CISTPL_LONGLINK_MFC; @@ -757,27 +748,25 @@ static int serial_config(struct pcmcia_device * link) /* Is this a multiport card? */ tuple->DesiredTuple = CISTPL_MANFID; - if (first_tuple(link, tuple, parse) == CS_SUCCESS) { - info->manfid = parse->manfid.manf; - info->prodid = parse->manfid.card; - - for (i = 0; i < ARRAY_SIZE(quirks); i++) - if ((quirks[i].manfid == ~0 || - quirks[i].manfid == info->manfid) && - (quirks[i].prodid == ~0 || - quirks[i].prodid == info->prodid)) { - info->quirk = &quirks[i]; - break; - } - } + info->manfid = link->manf_id; + info->prodid = link->card_id; + + for (i = 0; i < ARRAY_SIZE(quirks); i++) + if ((quirks[i].manfid == ~0 || + quirks[i].manfid == info->manfid) && + (quirks[i].prodid == ~0 || + quirks[i].prodid == info->prodid)) { + info->quirk = &quirks[i]; + break; + } /* Another check for dual-serial cards: look for either serial or multifunction cards that ask for appropriate IO port ranges */ tuple->DesiredTuple = CISTPL_FUNCID; if ((info->multi == 0) && - ((first_tuple(link, tuple, parse) != CS_SUCCESS) || - (parse->funcid.func == CISTPL_FUNCID_MULTI) || - (parse->funcid.func == CISTPL_FUNCID_SERIAL))) { + (link->has_func_id) && + ((link->func_id == CISTPL_FUNCID_MULTI) || + (link->func_id == CISTPL_FUNCID_SERIAL))) { tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY; if (first_tuple(link, tuple, parse) == CS_SUCCESS) { if ((cf->io.nwin == 1) && (cf->io.win[0].len % 8 == 0)) @@ -814,8 +803,6 @@ static int serial_config(struct pcmcia_device * link) kfree(cfg_mem); return 0; - cs_failed: - cs_error(link, last_fn, last_ret); failed: serial_remove(link); kfree(cfg_mem); @@ -925,6 +912,30 @@ static struct pcmcia_device_id serial_ids[] = { PCMCIA_DEVICE_CIS_PROD_ID123("ADVANTECH", "COMpad-32/85", "1.0", 0x96913a85, 0x8fbe92ae, 0x0877b627, "COMpad2.cis"), PCMCIA_DEVICE_CIS_PROD_ID2("RS-COM 2P", 0xad20b156, "RS-COM-2P.cis"), PCMCIA_DEVICE_CIS_MANF_CARD(0x0013, 0x0000, "GLOBETROTTER.cis"), + PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.","SERIAL CARD: SL100 1.00.",0x19ca78af,0xf964f42b), + PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.","SERIAL CARD: SL100",0x19ca78af,0x71d98e83), + PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.","SERIAL CARD: SL232 1.00.",0x19ca78af,0x69fb7490), + PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.","SERIAL CARD: SL232",0x19ca78af,0xb6bc0235), + PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c2000.","SERIAL CARD: CF232",0x63f2e0bd,0xb9e175d3), + PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c2000.","SERIAL CARD: CF232-5",0x63f2e0bd,0xfce33442), + PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: CF232",0x3beb8cf2,0x171e7190), + PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: CF232-5",0x3beb8cf2,0x20da4262), + PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: CF428",0x3beb8cf2,0xea5dd57d), + PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: CF500",0x3beb8cf2,0xd77255fa), + PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: IC232",0x3beb8cf2,0x6a709903), + PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: SL232",0x3beb8cf2,0x18430676), + PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: XL232",0x3beb8cf2,0x6f933767), + PCMCIA_MFC_DEVICE_PROD_ID12(0,"Elan","Serial Port: CF332",0x3beb8cf2,0x16dc1ba7), + PCMCIA_MFC_DEVICE_PROD_ID12(0,"Elan","Serial Port: SL332",0x3beb8cf2,0x19816c41), + PCMCIA_MFC_DEVICE_PROD_ID12(0,"Elan","Serial Port: SL385",0x3beb8cf2,0x64112029), + PCMCIA_MFC_DEVICE_PROD_ID12(0,"Elan","Serial Port: SL432",0x3beb8cf2,0x1cce7ac4), + PCMCIA_MFC_DEVICE_PROD_ID12(0,"Elan","Serial+Parallel Port: SP230",0x3beb8cf2,0xdb9e58bc), + PCMCIA_MFC_DEVICE_PROD_ID12(1,"Elan","Serial Port: CF332",0x3beb8cf2,0x16dc1ba7), + PCMCIA_MFC_DEVICE_PROD_ID12(1,"Elan","Serial Port: SL332",0x3beb8cf2,0x19816c41), + PCMCIA_MFC_DEVICE_PROD_ID12(1,"Elan","Serial Port: SL385",0x3beb8cf2,0x64112029), + PCMCIA_MFC_DEVICE_PROD_ID12(1,"Elan","Serial Port: SL432",0x3beb8cf2,0x1cce7ac4), + PCMCIA_MFC_DEVICE_PROD_ID12(2,"Elan","Serial Port: SL432",0x3beb8cf2,0x1cce7ac4), + PCMCIA_MFC_DEVICE_PROD_ID12(3,"Elan","Serial Port: SL432",0x3beb8cf2,0x1cce7ac4), /* too generic */ /* PCMCIA_MFC_DEVICE_MANF_CARD(0, 0x0160, 0x0002), */ /* PCMCIA_MFC_DEVICE_MANF_CARD(1, 0x0160, 0x0002), */ diff --git a/trunk/drivers/serial/serial_lh7a40x.c b/trunk/drivers/serial/serial_lh7a40x.c index 5e1ac356bbb0..eb18d429752d 100644 --- a/trunk/drivers/serial/serial_lh7a40x.c +++ b/trunk/drivers/serial/serial_lh7a40x.c @@ -348,8 +348,8 @@ static void lh7a40xuart_shutdown (struct uart_port* port) } static void lh7a40xuart_set_termios (struct uart_port* port, - struct termios* termios, - struct termios* old) + struct ktermios* termios, + struct ktermios* old) { unsigned int con; unsigned int inten; diff --git a/trunk/drivers/serial/serial_txx9.c b/trunk/drivers/serial/serial_txx9.c index 2a48289ac722..7186a82c4759 100644 --- a/trunk/drivers/serial/serial_txx9.c +++ b/trunk/drivers/serial/serial_txx9.c @@ -556,8 +556,8 @@ static void serial_txx9_shutdown(struct uart_port *port) } static void -serial_txx9_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +serial_txx9_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { struct uart_txx9_port *up = (struct uart_txx9_port *)port; unsigned int cval, fcr = 0; diff --git a/trunk/drivers/serial/sh-sci.c b/trunk/drivers/serial/sh-sci.c index cfcc3caf49d8..9031b57f12dd 100644 --- a/trunk/drivers/serial/sh-sci.c +++ b/trunk/drivers/serial/sh-sci.c @@ -775,7 +775,7 @@ static int sci_notifier(struct notifier_block *self, * * Clean this up later.. */ - clk = clk_get("module_clk"); + clk = clk_get(NULL, "module_clk"); port->uartclk = clk_get_rate(clk) * 16; clk_put(clk); } @@ -943,8 +943,8 @@ static void sci_shutdown(struct uart_port *port) s->disable(port); } -static void sci_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +static void sci_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { struct sci_port *s = &sci_ports[port->line]; unsigned int status, baud, smr_val; @@ -960,7 +960,7 @@ static void sci_set_termios(struct uart_port *port, struct termios *termios, default: { #if defined(CONFIG_SUPERH) && !defined(CONFIG_SUPERH64) - struct clk *clk = clk_get("module_clk"); + struct clk *clk = clk_get(NULL, "module_clk"); t = SCBRR_VALUE(baud, clk_get_rate(clk)); clk_put(clk); #else @@ -1128,7 +1128,7 @@ static void __init sci_init_ports(void) * XXX: We should use a proper SCI/SCIF clock */ { - struct clk *clk = clk_get("module_clk"); + struct clk *clk = clk_get(NULL, "module_clk"); sci_ports[i].port.uartclk = clk_get_rate(clk) * 16; clk_put(clk); } diff --git a/trunk/drivers/serial/sh-sci.h b/trunk/drivers/serial/sh-sci.h index 7ee992146ae9..e4557cc4f74b 100644 --- a/trunk/drivers/serial/sh-sci.h +++ b/trunk/drivers/serial/sh-sci.h @@ -133,6 +133,20 @@ # define SCIF_ORER 0x0001 /* Overrun error bit */ # define SCSCR_INIT(port) 0x3a /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ # define SCIF_ONLY +#elif defined(CONFIG_CPU_SUBTYPE_SH7206) +# define SCSPTR0 0xfffe8020 /* 16 bit SCIF */ +# define SCSPTR1 0xfffe8820 /* 16 bit SCIF */ +# define SCSPTR2 0xfffe9020 /* 16 bit SCIF */ +# define SCSPTR3 0xfffe9820 /* 16 bit SCIF */ +# define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ +# define SCIF_ONLY +#elif defined(CONFIG_CPU_SUBTYPE_SH7619) +# define SCSPTR0 0xf8400020 /* 16 bit SCIF */ +# define SCSPTR1 0xf8410020 /* 16 bit SCIF */ +# define SCSPTR2 0xf8420020 /* 16 bit SCIF */ +# define SCIF_ORER 0x0001 /* overrun error bit */ +# define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ +# define SCIF_ONLY #else # error CPU subtype not defined #endif @@ -365,6 +379,7 @@ SCIx_FNS(SCxSR, 0x08, 8, 0x10, 8, 0x08, 16, 0x10, 16, 0x04, 8) SCIx_FNS(SCxRDR, 0x0a, 8, 0x14, 8, 0x0A, 8, 0x14, 8, 0x05, 8) SCIF_FNS(SCFCR, 0x0c, 8, 0x18, 16) #if defined(CONFIG_CPU_SUBTYPE_SH7760) || defined(CONFIG_CPU_SUBTYPE_SH7780) +SCIF_FNS(SCFDR, 0x0e, 16, 0x1C, 16) SCIF_FNS(SCTFDR, 0x0e, 16, 0x1C, 16) SCIF_FNS(SCRFDR, 0x0e, 16, 0x20, 16) SCIF_FNS(SCSPTR, 0, 0, 0x24, 16) @@ -544,6 +559,28 @@ static inline int sci_rxd_in(struct uart_port *port) if (port->mapbase == 0xffe10000) return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */ } +#elif defined(CONFIG_CPU_SUBTYPE_SH7206) +static inline int sci_rxd_in(struct uart_port *port) +{ + if (port->mapbase == 0xfffe8000) + return ctrl_inw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */ + if (port->mapbase == 0xfffe8800) + return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */ + if (port->mapbase == 0xfffe9000) + return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */ + if (port->mapbase == 0xfffe9800) + return ctrl_inw(SCSPTR3) & 0x0001 ? 1 : 0; /* SCIF */ +} +#elif defined(CONFIG_CPU_SUBTYPE_SH7619) +static inline int sci_rxd_in(struct uart_port *port) +{ + if (port->mapbase == 0xf8400000) + return ctrl_inw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */ + if (port->mapbase == 0xf8410000) + return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */ + if (port->mapbase == 0xf8420000) + return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */ +} #endif /* diff --git a/trunk/drivers/serial/sn_console.c b/trunk/drivers/serial/sn_console.c index 956b2cf08e1e..253ceb895ca7 100644 --- a/trunk/drivers/serial/sn_console.c +++ b/trunk/drivers/serial/sn_console.c @@ -361,8 +361,8 @@ static int snp_startup(struct uart_port *port) * */ static void -snp_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +snp_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { } diff --git a/trunk/drivers/serial/sunhv.c b/trunk/drivers/serial/sunhv.c index 03941d27d15d..40d48566215c 100644 --- a/trunk/drivers/serial/sunhv.c +++ b/trunk/drivers/serial/sunhv.c @@ -281,8 +281,8 @@ static void sunhv_shutdown(struct uart_port *port) } /* port->lock is not held. */ -static void sunhv_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +static void sunhv_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { unsigned int baud = uart_get_baud_rate(port, termios, old, 0, 4000000); unsigned int quot = uart_get_divisor(port, baud); diff --git a/trunk/drivers/serial/sunsab.c b/trunk/drivers/serial/sunsab.c index 08a7cd6a3a0c..493d5bbb661b 100644 --- a/trunk/drivers/serial/sunsab.c +++ b/trunk/drivers/serial/sunsab.c @@ -786,8 +786,8 @@ static void sunsab_convert_to_sab(struct uart_sunsab_port *up, unsigned int cfla } /* port->lock is not held. */ -static void sunsab_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +static void sunsab_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { struct uart_sunsab_port *up = (struct uart_sunsab_port *) port; unsigned long flags; diff --git a/trunk/drivers/serial/sunsu.c b/trunk/drivers/serial/sunsu.c index c577faea60e8..564592b2b2ba 100644 --- a/trunk/drivers/serial/sunsu.c +++ b/trunk/drivers/serial/sunsu.c @@ -893,8 +893,8 @@ sunsu_change_speed(struct uart_port *port, unsigned int cflag, } static void -sunsu_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +sunsu_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { unsigned int baud, quot; diff --git a/trunk/drivers/serial/sunzilog.c b/trunk/drivers/serial/sunzilog.c index b2cc703b2b9e..75de919a9471 100644 --- a/trunk/drivers/serial/sunzilog.c +++ b/trunk/drivers/serial/sunzilog.c @@ -922,8 +922,8 @@ sunzilog_convert_to_zs(struct uart_sunzilog_port *up, unsigned int cflag, /* The port lock is not held. */ static void -sunzilog_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) +sunzilog_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { struct uart_sunzilog_port *up = (struct uart_sunzilog_port *) port; unsigned long flags; diff --git a/trunk/drivers/serial/uartlite.c b/trunk/drivers/serial/uartlite.c new file mode 100644 index 000000000000..92eba893559d --- /dev/null +++ b/trunk/drivers/serial/uartlite.c @@ -0,0 +1,505 @@ +/* + * uartlite.c: Serial driver for Xilinx uartlite serial controller + * + * Peter Korsgaard + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define ULITE_MAJOR 204 +#define ULITE_MINOR 187 +#define ULITE_NR_UARTS 4 + +/* For register details see datasheet: + http://www.xilinx.com/bvdocs/ipcenter/data_sheet/opb_uartlite.pdf +*/ +#define ULITE_RX 0x00 +#define ULITE_TX 0x04 +#define ULITE_STATUS 0x08 +#define ULITE_CONTROL 0x0c + +#define ULITE_REGION 16 + +#define ULITE_STATUS_RXVALID 0x01 +#define ULITE_STATUS_RXFULL 0x02 +#define ULITE_STATUS_TXEMPTY 0x04 +#define ULITE_STATUS_TXFULL 0x08 +#define ULITE_STATUS_IE 0x10 +#define ULITE_STATUS_OVERRUN 0x20 +#define ULITE_STATUS_FRAME 0x40 +#define ULITE_STATUS_PARITY 0x80 + +#define ULITE_CONTROL_RST_TX 0x01 +#define ULITE_CONTROL_RST_RX 0x02 +#define ULITE_CONTROL_IE 0x10 + + +static struct uart_port ports[ULITE_NR_UARTS]; + +static int ulite_receive(struct uart_port *port, int stat) +{ + struct tty_struct *tty = port->info->tty; + unsigned char ch = 0; + char flag = TTY_NORMAL; + + if ((stat & (ULITE_STATUS_RXVALID | ULITE_STATUS_OVERRUN + | ULITE_STATUS_FRAME)) == 0) + return 0; + + /* stats */ + if (stat & ULITE_STATUS_RXVALID) { + port->icount.rx++; + ch = readb(port->membase + ULITE_RX); + + if (stat & ULITE_STATUS_PARITY) + port->icount.parity++; + } + + if (stat & ULITE_STATUS_OVERRUN) + port->icount.overrun++; + + if (stat & ULITE_STATUS_FRAME) + port->icount.frame++; + + + /* drop byte with parity error if IGNPAR specificed */ + if (stat & port->ignore_status_mask & ULITE_STATUS_PARITY) + stat &= ~ULITE_STATUS_RXVALID; + + stat &= port->read_status_mask; + + if (stat & ULITE_STATUS_PARITY) + flag = TTY_PARITY; + + + stat &= ~port->ignore_status_mask; + + if (stat & ULITE_STATUS_RXVALID) + tty_insert_flip_char(tty, ch, flag); + + if (stat & ULITE_STATUS_FRAME) + tty_insert_flip_char(tty, 0, TTY_FRAME); + + if (stat & ULITE_STATUS_OVERRUN) + tty_insert_flip_char(tty, 0, TTY_OVERRUN); + + return 1; +} + +static int ulite_transmit(struct uart_port *port, int stat) +{ + struct circ_buf *xmit = &port->info->xmit; + + if (stat & ULITE_STATUS_TXFULL) + return 0; + + if (port->x_char) { + writeb(port->x_char, port->membase + ULITE_TX); + port->x_char = 0; + port->icount.tx++; + return 1; + } + + if (uart_circ_empty(xmit) || uart_tx_stopped(port)) + return 0; + + writeb(xmit->buf[xmit->tail], port->membase + ULITE_TX); + xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE-1); + port->icount.tx++; + + /* wake up */ + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + uart_write_wakeup(port); + + return 1; +} + +static irqreturn_t ulite_isr(int irq, void *dev_id) +{ + struct uart_port *port = (struct uart_port *)dev_id; + int busy; + + do { + int stat = readb(port->membase + ULITE_STATUS); + busy = ulite_receive(port, stat); + busy |= ulite_transmit(port, stat); + } while (busy); + + tty_flip_buffer_push(port->info->tty); + + return IRQ_HANDLED; +} + +static unsigned int ulite_tx_empty(struct uart_port *port) +{ + unsigned long flags; + unsigned int ret; + + spin_lock_irqsave(&port->lock, flags); + ret = readb(port->membase + ULITE_STATUS); + spin_unlock_irqrestore(&port->lock, flags); + + return ret & ULITE_STATUS_TXEMPTY ? TIOCSER_TEMT : 0; +} + +static unsigned int ulite_get_mctrl(struct uart_port *port) +{ + return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR; +} + +static void ulite_set_mctrl(struct uart_port *port, unsigned int mctrl) +{ + /* N/A */ +} + +static void ulite_stop_tx(struct uart_port *port) +{ + /* N/A */ +} + +static void ulite_start_tx(struct uart_port *port) +{ + ulite_transmit(port, readb(port->membase + ULITE_STATUS)); +} + +static void ulite_stop_rx(struct uart_port *port) +{ + /* don't forward any more data (like !CREAD) */ + port->ignore_status_mask = ULITE_STATUS_RXVALID | ULITE_STATUS_PARITY + | ULITE_STATUS_FRAME | ULITE_STATUS_OVERRUN; +} + +static void ulite_enable_ms(struct uart_port *port) +{ + /* N/A */ +} + +static void ulite_break_ctl(struct uart_port *port, int ctl) +{ + /* N/A */ +} + +static int ulite_startup(struct uart_port *port) +{ + int ret; + + ret = request_irq(port->irq, ulite_isr, + IRQF_DISABLED | IRQF_SAMPLE_RANDOM, "uartlite", port); + if (ret) + return ret; + + writeb(ULITE_CONTROL_RST_RX | ULITE_CONTROL_RST_TX, + port->membase + ULITE_CONTROL); + writeb(ULITE_CONTROL_IE, port->membase + ULITE_CONTROL); + + return 0; +} + +static void ulite_shutdown(struct uart_port *port) +{ + writeb(0, port->membase + ULITE_CONTROL); + readb(port->membase + ULITE_CONTROL); /* dummy */ + free_irq(port->irq, port); +} + +static void ulite_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) +{ + unsigned long flags; + unsigned int baud; + + spin_lock_irqsave(&port->lock, flags); + + port->read_status_mask = ULITE_STATUS_RXVALID | ULITE_STATUS_OVERRUN + | ULITE_STATUS_TXFULL; + + if (termios->c_iflag & INPCK) + port->read_status_mask |= + ULITE_STATUS_PARITY | ULITE_STATUS_FRAME; + + port->ignore_status_mask = 0; + if (termios->c_iflag & IGNPAR) + port->ignore_status_mask |= ULITE_STATUS_PARITY + | ULITE_STATUS_FRAME | ULITE_STATUS_OVERRUN; + + /* ignore all characters if CREAD is not set */ + if ((termios->c_cflag & CREAD) == 0) + port->ignore_status_mask |= + ULITE_STATUS_RXVALID | ULITE_STATUS_PARITY + | ULITE_STATUS_FRAME | ULITE_STATUS_OVERRUN; + + /* update timeout */ + baud = uart_get_baud_rate(port, termios, old, 0, 460800); + uart_update_timeout(port, termios->c_cflag, baud); + + spin_unlock_irqrestore(&port->lock, flags); +} + +static const char *ulite_type(struct uart_port *port) +{ + return port->type == PORT_UARTLITE ? "uartlite" : NULL; +} + +static void ulite_release_port(struct uart_port *port) +{ + release_mem_region(port->mapbase, ULITE_REGION); + iounmap(port->membase); + port->membase = 0; +} + +static int ulite_request_port(struct uart_port *port) +{ + if (!request_mem_region(port->mapbase, ULITE_REGION, "uartlite")) { + dev_err(port->dev, "Memory region busy\n"); + return -EBUSY; + } + + port->membase = ioremap(port->mapbase, ULITE_REGION); + if (!port->membase) { + dev_err(port->dev, "Unable to map registers\n"); + release_mem_region(port->mapbase, ULITE_REGION); + return -EBUSY; + } + + return 0; +} + +static void ulite_config_port(struct uart_port *port, int flags) +{ + ulite_request_port(port); + port->type = PORT_UARTLITE; +} + +static int ulite_verify_port(struct uart_port *port, struct serial_struct *ser) +{ + /* we don't want the core code to modify any port params */ + return -EINVAL; +} + +static struct uart_ops ulite_ops = { + .tx_empty = ulite_tx_empty, + .set_mctrl = ulite_set_mctrl, + .get_mctrl = ulite_get_mctrl, + .stop_tx = ulite_stop_tx, + .start_tx = ulite_start_tx, + .stop_rx = ulite_stop_rx, + .enable_ms = ulite_enable_ms, + .break_ctl = ulite_break_ctl, + .startup = ulite_startup, + .shutdown = ulite_shutdown, + .set_termios = ulite_set_termios, + .type = ulite_type, + .release_port = ulite_release_port, + .request_port = ulite_request_port, + .config_port = ulite_config_port, + .verify_port = ulite_verify_port +}; + +#ifdef CONFIG_SERIAL_UARTLITE_CONSOLE +static void ulite_console_wait_tx(struct uart_port *port) +{ + int i; + + /* wait up to 10ms for the character(s) to be sent */ + for (i = 0; i < 10000; i++) { + if (readb(port->membase + ULITE_STATUS) & ULITE_STATUS_TXEMPTY) + break; + udelay(1); + } +} + +static void ulite_console_putchar(struct uart_port *port, int ch) +{ + ulite_console_wait_tx(port); + writeb(ch, port->membase + ULITE_TX); +} + +static void ulite_console_write(struct console *co, const char *s, + unsigned int count) +{ + struct uart_port *port = &ports[co->index]; + unsigned long flags; + unsigned int ier; + int locked = 1; + + if (oops_in_progress) { + locked = spin_trylock_irqsave(&port->lock, flags); + } else + spin_lock_irqsave(&port->lock, flags); + + /* save and disable interrupt */ + ier = readb(port->membase + ULITE_STATUS) & ULITE_STATUS_IE; + writeb(0, port->membase + ULITE_CONTROL); + + uart_console_write(port, s, count, ulite_console_putchar); + + ulite_console_wait_tx(port); + + /* restore interrupt state */ + if (ier) + writeb(ULITE_CONTROL_IE, port->membase + ULITE_CONTROL); + + if (locked) + spin_unlock_irqrestore(&port->lock, flags); +} + +static int __init ulite_console_setup(struct console *co, char *options) +{ + struct uart_port *port; + int baud = 9600; + int bits = 8; + int parity = 'n'; + int flow = 'n'; + + if (co->index < 0 || co->index >= ULITE_NR_UARTS) + return -EINVAL; + + port = &ports[co->index]; + + /* not initialized yet? */ + if (!port->membase) + return -ENODEV; + + if (options) + uart_parse_options(options, &baud, &parity, &bits, &flow); + + return uart_set_options(port, co, baud, parity, bits, flow); +} + +static struct uart_driver ulite_uart_driver; + +static struct console ulite_console = { + .name = "ttyUL", + .write = ulite_console_write, + .device = uart_console_device, + .setup = ulite_console_setup, + .flags = CON_PRINTBUFFER, + .index = -1, /* Specified on the cmdline (e.g. console=ttyUL0 ) */ + .data = &ulite_uart_driver, +}; + +static int __init ulite_console_init(void) +{ + register_console(&ulite_console); + return 0; +} + +console_initcall(ulite_console_init); + +#endif /* CONFIG_SERIAL_UARTLITE_CONSOLE */ + +static struct uart_driver ulite_uart_driver = { + .owner = THIS_MODULE, + .driver_name = "uartlite", + .dev_name = "ttyUL", + .major = ULITE_MAJOR, + .minor = ULITE_MINOR, + .nr = ULITE_NR_UARTS, +#ifdef CONFIG_SERIAL_UARTLITE_CONSOLE + .cons = &ulite_console, +#endif +}; + +static int __devinit ulite_probe(struct platform_device *pdev) +{ + struct resource *res, *res2; + struct uart_port *port; + + if (pdev->id < 0 || pdev->id >= ULITE_NR_UARTS) + return -EINVAL; + + if (ports[pdev->id].membase) + return -EBUSY; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -ENODEV; + + res2 = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (!res2) + return -ENODEV; + + port = &ports[pdev->id]; + + port->fifosize = 16; + port->regshift = 2; + port->iotype = UPIO_MEM; + port->iobase = 1; /* mark port in use */ + port->mapbase = res->start; + port->membase = 0; + port->ops = &ulite_ops; + port->irq = res2->start; + port->flags = UPF_BOOT_AUTOCONF; + port->dev = &pdev->dev; + port->type = PORT_UNKNOWN; + port->line = pdev->id; + + uart_add_one_port(&ulite_uart_driver, port); + platform_set_drvdata(pdev, port); + + return 0; +} + +static int ulite_remove(struct platform_device *pdev) +{ + struct uart_port *port = platform_get_drvdata(pdev); + + platform_set_drvdata(pdev, NULL); + + if (port) + uart_remove_one_port(&ulite_uart_driver, port); + + /* mark port as free */ + port->membase = 0; + + return 0; +} + +static struct platform_driver ulite_platform_driver = { + .probe = ulite_probe, + .remove = ulite_remove, + .driver = { + .owner = THIS_MODULE, + .name = "uartlite", + }, +}; + +int __init ulite_init(void) +{ + int ret; + + ret = uart_register_driver(&ulite_uart_driver); + if (ret) + return ret; + + ret = platform_driver_register(&ulite_platform_driver); + if (ret) + uart_unregister_driver(&ulite_uart_driver); + + return ret; +} + +void __exit ulite_exit(void) +{ + platform_driver_unregister(&ulite_platform_driver); + uart_unregister_driver(&ulite_uart_driver); +} + +module_init(ulite_init); +module_exit(ulite_exit); + +MODULE_AUTHOR("Peter Korsgaard "); +MODULE_DESCRIPTION("Xilinx uartlite serial driver"); +MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/serial/v850e_uart.c b/trunk/drivers/serial/v850e_uart.c index 28f3bbff87bf..dd98aca6ed08 100644 --- a/trunk/drivers/serial/v850e_uart.c +++ b/trunk/drivers/serial/v850e_uart.c @@ -404,8 +404,8 @@ static void v850e_uart_shutdown (struct uart_port *port) } static void -v850e_uart_set_termios (struct uart_port *port, struct termios *termios, - struct termios *old) +v850e_uart_set_termios (struct uart_port *port, struct ktermios *termios, + struct ktermios *old) { unsigned cflags = termios->c_cflag; diff --git a/trunk/drivers/serial/vr41xx_siu.c b/trunk/drivers/serial/vr41xx_siu.c index fd51f8182dec..cf0e663b42ed 100644 --- a/trunk/drivers/serial/vr41xx_siu.c +++ b/trunk/drivers/serial/vr41xx_siu.c @@ -562,8 +562,8 @@ static void siu_shutdown(struct uart_port *port) free_irq(port->irq, port); } -static void siu_set_termios(struct uart_port *port, struct termios *new, - struct termios *old) +static void siu_set_termios(struct uart_port *port, struct ktermios *new, + struct ktermios *old) { tcflag_t c_cflag, c_iflag; uint8_t lcr, fcr, ier; diff --git a/trunk/drivers/spi/pxa2xx_spi.c b/trunk/drivers/spi/pxa2xx_spi.c index 72025df5561d..494d9b856488 100644 --- a/trunk/drivers/spi/pxa2xx_spi.c +++ b/trunk/drivers/spi/pxa2xx_spi.c @@ -148,7 +148,7 @@ struct chip_data { void (*cs_control)(u32 command); }; -static void pump_messages(void *data); +static void pump_messages(struct work_struct *work); static int flush(struct driver_data *drv_data) { @@ -884,9 +884,10 @@ static void pump_transfers(unsigned long data) } } -static void pump_messages(void *data) +static void pump_messages(struct work_struct *work) { - struct driver_data *drv_data = data; + struct driver_data *drv_data = + container_of(work, struct driver_data, pump_messages); unsigned long flags; /* Lock queue and check for queue work */ @@ -1098,7 +1099,7 @@ static int init_queue(struct driver_data *drv_data) tasklet_init(&drv_data->pump_transfers, pump_transfers, (unsigned long)drv_data); - INIT_WORK(&drv_data->pump_messages, pump_messages, drv_data); + INIT_WORK(&drv_data->pump_messages, pump_messages); drv_data->workqueue = create_singlethread_workqueue( drv_data->master->cdev.dev->bus_id); if (drv_data->workqueue == NULL) diff --git a/trunk/drivers/spi/spi.c b/trunk/drivers/spi/spi.c index c3c0626f550b..270e6211c2e3 100644 --- a/trunk/drivers/spi/spi.c +++ b/trunk/drivers/spi/spi.c @@ -360,12 +360,13 @@ spi_alloc_master(struct device *dev, unsigned size) if (!dev) return NULL; - master = kzalloc(size + sizeof *master, SLAB_KERNEL); + master = kzalloc(size + sizeof *master, GFP_KERNEL); if (!master) return NULL; class_device_initialize(&master->cdev); master->cdev.class = &spi_master_class; + kobj_set_kset_s(&master->cdev, spi_master_class.subsys); master->cdev.dev = get_device(dev); spi_master_set_devdata(master, &master[1]); @@ -447,7 +448,9 @@ static int __unregister(struct device *dev, void *unused) */ void spi_unregister_master(struct spi_master *master) { - (void) device_for_each_child(master->cdev.dev, NULL, __unregister); + int dummy; + + dummy = device_for_each_child(master->cdev.dev, NULL, __unregister); class_device_unregister(&master->cdev); } EXPORT_SYMBOL_GPL(spi_unregister_master); @@ -463,15 +466,13 @@ EXPORT_SYMBOL_GPL(spi_unregister_master); */ struct spi_master *spi_busnum_to_master(u16 bus_num) { - if (bus_num) { - char name[8]; - struct kobject *bus; - - snprintf(name, sizeof name, "spi%u", bus_num); - bus = kset_find_obj(&spi_master_class.subsys.kset, name); - if (bus) - return container_of(bus, struct spi_master, cdev.kobj); - } + char name[9]; + struct kobject *bus; + + snprintf(name, sizeof name, "spi%u", bus_num); + bus = kset_find_obj(&spi_master_class.subsys.kset, name); + if (bus) + return container_of(bus, struct spi_master, cdev.kobj); return NULL; } EXPORT_SYMBOL_GPL(spi_busnum_to_master); @@ -607,7 +608,7 @@ static int __init spi_init(void) { int status; - buf = kmalloc(SPI_BUFSIZ, SLAB_KERNEL); + buf = kmalloc(SPI_BUFSIZ, GFP_KERNEL); if (!buf) { status = -ENOMEM; goto err0; diff --git a/trunk/drivers/spi/spi_bitbang.c b/trunk/drivers/spi/spi_bitbang.c index a23862ef72b2..57289b61d0be 100644 --- a/trunk/drivers/spi/spi_bitbang.c +++ b/trunk/drivers/spi/spi_bitbang.c @@ -196,7 +196,7 @@ int spi_bitbang_setup(struct spi_device *spi) return -EINVAL; if (!cs) { - cs = kzalloc(sizeof *cs, SLAB_KERNEL); + cs = kzalloc(sizeof *cs, GFP_KERNEL); if (!cs) return -ENOMEM; spi->controller_state = cs; @@ -265,9 +265,10 @@ static int spi_bitbang_bufs(struct spi_device *spi, struct spi_transfer *t) * Drivers can provide word-at-a-time i/o primitives, or provide * transfer-at-a-time ones to leverage dma or fifo hardware. */ -static void bitbang_work(void *_bitbang) +static void bitbang_work(struct work_struct *work) { - struct spi_bitbang *bitbang = _bitbang; + struct spi_bitbang *bitbang = + container_of(work, struct spi_bitbang, work); unsigned long flags; spin_lock_irqsave(&bitbang->lock, flags); @@ -456,7 +457,7 @@ int spi_bitbang_start(struct spi_bitbang *bitbang) if (!bitbang->master || !bitbang->chipselect) return -EINVAL; - INIT_WORK(&bitbang->work, bitbang_work, bitbang); + INIT_WORK(&bitbang->work, bitbang_work); spin_lock_init(&bitbang->lock); INIT_LIST_HEAD(&bitbang->queue); diff --git a/trunk/drivers/spi/spi_butterfly.c b/trunk/drivers/spi/spi_butterfly.c index c2f601f8e4f2..312987a03210 100644 --- a/trunk/drivers/spi/spi_butterfly.c +++ b/trunk/drivers/spi/spi_butterfly.c @@ -251,6 +251,8 @@ static void butterfly_attach(struct parport *p) * setting up a platform device like this is an ugly kluge... */ pdev = platform_device_register_simple("butterfly", -1, NULL, 0); + if (IS_ERR(pdev)) + return; master = spi_alloc_master(&pdev->dev, sizeof *pp); if (!master) { diff --git a/trunk/drivers/tc/zs.c b/trunk/drivers/tc/zs.c index 792becdfe6f8..fc3197273663 100644 --- a/trunk/drivers/tc/zs.c +++ b/trunk/drivers/tc/zs.c @@ -1238,7 +1238,7 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file, return 0; } -static void rs_set_termios(struct tty_struct *tty, struct termios *old_termios) +static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { struct dec_serial *info = (struct dec_serial *)tty->driver_data; int was_stopped; diff --git a/trunk/drivers/telephony/ixj.c b/trunk/drivers/telephony/ixj.c index 1b601b6cf2a2..df4cc1fb5f68 100644 --- a/trunk/drivers/telephony/ixj.c +++ b/trunk/drivers/telephony/ixj.c @@ -2747,7 +2747,7 @@ static void alaw2ulaw(unsigned char *buff, unsigned long len) static ssize_t ixj_read(struct file * file_p, char __user *buf, size_t length, loff_t * ppos) { unsigned long i = *ppos; - IXJ * j = get_ixj(NUM(file_p->f_dentry->d_inode)); + IXJ * j = get_ixj(NUM(file_p->f_path.dentry->d_inode)); DECLARE_WAITQUEUE(wait, current); @@ -2804,7 +2804,7 @@ static ssize_t ixj_enhanced_read(struct file * file_p, char __user *buf, size_t { int pre_retval; ssize_t read_retval = 0; - IXJ *j = get_ixj(NUM(file_p->f_dentry->d_inode)); + IXJ *j = get_ixj(NUM(file_p->f_path.dentry->d_inode)); pre_retval = ixj_PreRead(j, 0L); switch (pre_retval) { @@ -2883,7 +2883,7 @@ static ssize_t ixj_enhanced_write(struct file * file_p, const char __user *buf, int pre_retval; ssize_t write_retval = 0; - IXJ *j = get_ixj(NUM(file_p->f_dentry->d_inode)); + IXJ *j = get_ixj(NUM(file_p->f_path.dentry->d_inode)); pre_retval = ixj_PreWrite(j, 0L); switch (pre_retval) { @@ -4582,7 +4582,7 @@ static unsigned int ixj_poll(struct file *file_p, poll_table * wait) { unsigned int mask = 0; - IXJ *j = get_ixj(NUM(file_p->f_dentry->d_inode)); + IXJ *j = get_ixj(NUM(file_p->f_path.dentry->d_inode)); poll_wait(file_p, &(j->poll_q), wait); if (j->read_buffer_ready > 0) @@ -6657,7 +6657,7 @@ static int ixj_ioctl(struct inode *inode, struct file *file_p, unsigned int cmd, static int ixj_fasync(int fd, struct file *file_p, int mode) { - IXJ *j = get_ixj(NUM(file_p->f_dentry->d_inode)); + IXJ *j = get_ixj(NUM(file_p->f_path.dentry->d_inode)); return fasync_helper(fd, file_p, mode, &j->async_queue); } diff --git a/trunk/drivers/telephony/ixj_pcmcia.c b/trunk/drivers/telephony/ixj_pcmcia.c index dda0ca45d904..164a5dcf1f1e 100644 --- a/trunk/drivers/telephony/ixj_pcmcia.c +++ b/trunk/drivers/telephony/ixj_pcmcia.c @@ -69,25 +69,21 @@ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) static void ixj_get_serial(struct pcmcia_device * link, IXJ * j) { - tuple_t tuple; - u_short buf[128]; char *str; - int last_ret, last_fn, i, place; + int i, place; DEBUG(0, "ixj_get_serial(0x%p)\n", link); - tuple.TupleData = (cisdata_t *) buf; - tuple.TupleOffset = 0; - tuple.TupleDataMax = 80; - tuple.Attributes = 0; - tuple.DesiredTuple = CISTPL_VERS_1; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); - str = (char *) buf; - printk("PCMCIA Version %d.%d\n", str[0], str[1]); - str += 2; + + str = link->prod_id[0]; + if (!str) + goto cs_failed; printk("%s", str); - str = str + strlen(str) + 1; + str = link->prod_id[1]; + if (!str) + goto cs_failed; printk(" %s", str); - str = str + strlen(str) + 1; + str = link->prod_id[2]; + if (!str) + goto cs_failed; place = 1; for (i = strlen(str) - 1; i >= 0; i--) { switch (str[i]) { @@ -122,7 +118,9 @@ static void ixj_get_serial(struct pcmcia_device * link, IXJ * j) } place = place * 0x10; } - str = str + strlen(str) + 1; + str = link->prod_id[3]; + if (!str) + goto cs_failed; printk(" version %s\n", str); cs_failed: return; @@ -146,13 +144,6 @@ static int ixj_config(struct pcmcia_device * link) tuple.TupleData = (cisdata_t *) buf; tuple.TupleOffset = 0; tuple.TupleDataMax = 255; - tuple.Attributes = 0; - tuple.DesiredTuple = CISTPL_CONFIG; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); - link->conf.ConfigBase = parse.config.base; - link->conf.Present = parse.config.rmask[0]; tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; tuple.Attributes = 0; CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); diff --git a/trunk/drivers/usb/Kconfig b/trunk/drivers/usb/Kconfig index f9b1719b9a37..9980a4ddfed9 100644 --- a/trunk/drivers/usb/Kconfig +++ b/trunk/drivers/usb/Kconfig @@ -24,7 +24,7 @@ config USB_ARCH_HAS_OHCI default y if ARCH_S3C2410 default y if PXA27x default y if ARCH_EP93XX - default y if (ARCH_AT91RM9200 || ARCH_AT91SAM9261) + default y if ARCH_AT91 default y if ARCH_PNX4008 # PPC: default y if STB03xxx diff --git a/trunk/drivers/usb/atm/cxacru.c b/trunk/drivers/usb/atm/cxacru.c index e6565633ba0f..3dfa3e40e148 100644 --- a/trunk/drivers/usb/atm/cxacru.c +++ b/trunk/drivers/usb/atm/cxacru.c @@ -158,7 +158,7 @@ struct cxacru_data { const struct cxacru_modem_type *modem_type; int line_status; - struct work_struct poll_work; + struct delayed_work poll_work; /* contol handles */ struct mutex cm_serialize; @@ -347,7 +347,7 @@ static int cxacru_card_status(struct cxacru_data *instance) return 0; } -static void cxacru_poll_status(struct cxacru_data *instance); +static void cxacru_poll_status(struct work_struct *work); static int cxacru_atm_start(struct usbatm_data *usbatm_instance, struct atm_dev *atm_dev) @@ -376,12 +376,14 @@ static int cxacru_atm_start(struct usbatm_data *usbatm_instance, } /* Start status polling */ - cxacru_poll_status(instance); + cxacru_poll_status(&instance->poll_work.work); return 0; } -static void cxacru_poll_status(struct cxacru_data *instance) +static void cxacru_poll_status(struct work_struct *work) { + struct cxacru_data *instance = + container_of(work, struct cxacru_data, poll_work.work); u32 buf[CXINF_MAX] = {}; struct usbatm_data *usbatm = instance->usbatm; struct atm_dev *atm_dev = usbatm->atm_dev; @@ -720,7 +722,7 @@ static int cxacru_bind(struct usbatm_data *usbatm_instance, mutex_init(&instance->cm_serialize); - INIT_WORK(&instance->poll_work, (void *)cxacru_poll_status, instance); + INIT_DELAYED_WORK(&instance->poll_work, cxacru_poll_status); usbatm_instance->driver_data = instance; diff --git a/trunk/drivers/usb/atm/speedtch.c b/trunk/drivers/usb/atm/speedtch.c index a823486495c3..8ed6c75adf0f 100644 --- a/trunk/drivers/usb/atm/speedtch.c +++ b/trunk/drivers/usb/atm/speedtch.c @@ -142,7 +142,7 @@ struct speedtch_instance_data { struct speedtch_params params; /* set in probe, constant afterwards */ - struct work_struct status_checker; + struct delayed_work status_checker; unsigned char last_status; @@ -498,8 +498,11 @@ static int speedtch_start_synchro(struct speedtch_instance_data *instance) return ret; } -static void speedtch_check_status(struct speedtch_instance_data *instance) +static void speedtch_check_status(struct work_struct *work) { + struct speedtch_instance_data *instance = + container_of(work, struct speedtch_instance_data, + status_checker.work); struct usbatm_data *usbatm = instance->usbatm; struct atm_dev *atm_dev = usbatm->atm_dev; unsigned char *buf = instance->scratch_buffer; @@ -576,7 +579,7 @@ static void speedtch_status_poll(unsigned long data) { struct speedtch_instance_data *instance = (void *)data; - schedule_work(&instance->status_checker); + schedule_delayed_work(&instance->status_checker, 0); /* The following check is racy, but the race is harmless */ if (instance->poll_delay < MAX_POLL_DELAY) @@ -596,7 +599,7 @@ static void speedtch_resubmit_int(unsigned long data) if (int_urb) { ret = usb_submit_urb(int_urb, GFP_ATOMIC); if (!ret) - schedule_work(&instance->status_checker); + schedule_delayed_work(&instance->status_checker, 0); else { atm_dbg(instance->usbatm, "%s: usb_submit_urb failed with result %d\n", __func__, ret); mod_timer(&instance->resubmit_timer, jiffies + msecs_to_jiffies(RESUBMIT_DELAY)); @@ -640,7 +643,7 @@ static void speedtch_handle_int(struct urb *int_urb) if ((int_urb = instance->int_urb)) { ret = usb_submit_urb(int_urb, GFP_ATOMIC); - schedule_work(&instance->status_checker); + schedule_delayed_work(&instance->status_checker, 0); if (ret < 0) { atm_dbg(usbatm, "%s: usb_submit_urb failed with result %d\n", __func__, ret); goto fail; @@ -855,7 +858,7 @@ static int speedtch_bind(struct usbatm_data *usbatm, usbatm->flags |= (use_isoc ? UDSL_USE_ISOC : 0); - INIT_WORK(&instance->status_checker, (void *)speedtch_check_status, instance); + INIT_DELAYED_WORK(&instance->status_checker, speedtch_check_status); instance->status_checker.timer.function = speedtch_status_poll; instance->status_checker.timer.data = (unsigned long)instance; diff --git a/trunk/drivers/usb/atm/ueagle-atm.c b/trunk/drivers/usb/atm/ueagle-atm.c index c137c041f7a4..dae4ef1e8fe5 100644 --- a/trunk/drivers/usb/atm/ueagle-atm.c +++ b/trunk/drivers/usb/atm/ueagle-atm.c @@ -64,6 +64,8 @@ #include #include #include +#include + #include #include "usbatm.h" @@ -655,9 +657,9 @@ static int request_dsp(struct uea_softc *sc) /* * The uea_load_page() function must be called within a process context */ -static void uea_load_page(void *xsc) +static void uea_load_page(struct work_struct *work) { - struct uea_softc *sc = xsc; + struct uea_softc *sc = container_of(work, struct uea_softc, task); u16 pageno = sc->pageno; u16 ovl = sc->ovl; struct block_info bi; @@ -1348,7 +1350,7 @@ static int uea_boot(struct uea_softc *sc) uea_enters(INS_TO_USBDEV(sc)); - INIT_WORK(&sc->task, uea_load_page, sc); + INIT_WORK(&sc->task, uea_load_page); init_waitqueue_head(&sc->sync_q); init_waitqueue_head(&sc->cmv_ack_wait); diff --git a/trunk/drivers/usb/class/cdc-acm.c b/trunk/drivers/usb/class/cdc-acm.c index ec3438dc8ee5..98199628e394 100644 --- a/trunk/drivers/usb/class/cdc-acm.c +++ b/trunk/drivers/usb/class/cdc-acm.c @@ -421,9 +421,9 @@ static void acm_write_bulk(struct urb *urb) schedule_work(&acm->work); } -static void acm_softint(void *private) +static void acm_softint(struct work_struct *work) { - struct acm *acm = private; + struct acm *acm = container_of(work, struct acm, work); dbg("Entering acm_softint."); if (!ACM_READY(acm)) @@ -677,10 +677,10 @@ static const __u8 acm_tty_size[] = { 5, 6, 7, 8 }; -static void acm_tty_set_termios(struct tty_struct *tty, struct termios *termios_old) +static void acm_tty_set_termios(struct tty_struct *tty, struct ktermios *termios_old) { struct acm *acm = tty->driver_data; - struct termios *termios = tty->termios; + struct ktermios *termios = tty->termios; struct usb_cdc_line_coding newline; int newctrl = acm->ctrlout; @@ -927,7 +927,7 @@ static int acm_probe (struct usb_interface *intf, acm->rx_buflimit = num_rx_buf; acm->urb_task.func = acm_rx_tasklet; acm->urb_task.data = (unsigned long) acm; - INIT_WORK(&acm->work, acm_softint, acm); + INIT_WORK(&acm->work, acm_softint); spin_lock_init(&acm->throttle_lock); spin_lock_init(&acm->write_lock); spin_lock_init(&acm->read_lock); diff --git a/trunk/drivers/usb/core/buffer.c b/trunk/drivers/usb/core/buffer.c index 840442a25b61..c3915dc28608 100644 --- a/trunk/drivers/usb/core/buffer.c +++ b/trunk/drivers/usb/core/buffer.c @@ -93,7 +93,7 @@ void hcd_buffer_destroy (struct usb_hcd *hcd) } -/* sometimes alloc/free could use kmalloc with SLAB_DMA, for +/* sometimes alloc/free could use kmalloc with GFP_DMA, for * better sharing and to leverage mm/slab.c intelligence. */ diff --git a/trunk/drivers/usb/core/hub.c b/trunk/drivers/usb/core/hub.c index 0ce393eb3c4b..2651c2e2a89f 100644 --- a/trunk/drivers/usb/core/hub.c +++ b/trunk/drivers/usb/core/hub.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -68,7 +69,7 @@ struct usb_hub { unsigned has_indicators:1; u8 indicator[USB_MAXCHILDREN]; - struct work_struct leds; + struct delayed_work leds; }; @@ -218,9 +219,10 @@ static void set_port_led( #define LED_CYCLE_PERIOD ((2*HZ)/3) -static void led_work (void *__hub) +static void led_work (struct work_struct *work) { - struct usb_hub *hub = __hub; + struct usb_hub *hub = + container_of(work, struct usb_hub, leds.work); struct usb_device *hdev = hub->hdev; unsigned i; unsigned changed = 0; @@ -405,9 +407,10 @@ hub_clear_tt_buffer (struct usb_device *hdev, u16 devinfo, u16 tt) * talking to TTs must queue control transfers (not just bulk and iso), so * both can talk to the same hub concurrently. */ -static void hub_tt_kevent (void *arg) +static void hub_tt_kevent (struct work_struct *work) { - struct usb_hub *hub = arg; + struct usb_hub *hub = + container_of(work, struct usb_hub, tt.kevent); unsigned long flags; spin_lock_irqsave (&hub->tt.lock, flags); @@ -458,7 +461,7 @@ void usb_hub_tt_clear_buffer (struct usb_device *udev, int pipe) * since each TT has "at least two" buffers that can need it (and * there can be many TTs per hub). even if they're uncommon. */ - if ((clear = kmalloc (sizeof *clear, SLAB_ATOMIC)) == NULL) { + if ((clear = kmalloc (sizeof *clear, GFP_ATOMIC)) == NULL) { dev_err (&udev->dev, "can't save CLEAR_TT_BUFFER state\n"); /* FIXME recover somehow ... RESET_TT? */ return; @@ -694,7 +697,7 @@ static int hub_configure(struct usb_hub *hub, spin_lock_init (&hub->tt.lock); INIT_LIST_HEAD (&hub->tt.clear_list); - INIT_WORK (&hub->tt.kevent, hub_tt_kevent, hub); + INIT_WORK (&hub->tt.kevent, hub_tt_kevent); switch (hdev->descriptor.bDeviceProtocol) { case 0: break; @@ -938,7 +941,7 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id) INIT_LIST_HEAD(&hub->event_list); hub->intfdev = &intf->dev; hub->hdev = hdev; - INIT_WORK(&hub->leds, led_work, hub); + INIT_DELAYED_WORK(&hub->leds, led_work); usb_set_intfdata (intf, hub); intf->needs_remote_wakeup = 1; @@ -2369,7 +2372,7 @@ check_highspeed (struct usb_hub *hub, struct usb_device *udev, int port1) struct usb_qualifier_descriptor *qual; int status; - qual = kmalloc (sizeof *qual, SLAB_KERNEL); + qual = kmalloc (sizeof *qual, GFP_KERNEL); if (qual == NULL) return; @@ -2381,7 +2384,7 @@ check_highspeed (struct usb_hub *hub, struct usb_device *udev, int port1) /* hub LEDs are probably harder to miss than syslog */ if (hub->has_indicators) { hub->indicator[port1-1] = INDICATOR_GREEN_BLINK; - schedule_work (&hub->leds); + schedule_delayed_work (&hub->leds, 0); } } kfree(qual); @@ -2555,7 +2558,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, if (hub->has_indicators) { hub->indicator[port1-1] = INDICATOR_AMBER_BLINK; - schedule_work (&hub->leds); + schedule_delayed_work (&hub->leds, 0); } status = -ENOTCONN; /* Don't retry */ goto loop_disable; @@ -2920,7 +2923,7 @@ static int config_descriptors_changed(struct usb_device *udev) if (len < le16_to_cpu(udev->config[index].desc.wTotalLength)) len = le16_to_cpu(udev->config[index].desc.wTotalLength); } - buf = kmalloc (len, SLAB_KERNEL); + buf = kmalloc (len, GFP_KERNEL); if (buf == NULL) { dev_err(&udev->dev, "no mem to re-read configs after reset\n"); /* assume the worst */ diff --git a/trunk/drivers/usb/core/inode.c b/trunk/drivers/usb/core/inode.c index b5d6a79af0be..11dad22da41c 100644 --- a/trunk/drivers/usb/core/inode.c +++ b/trunk/drivers/usb/core/inode.c @@ -379,7 +379,7 @@ static loff_t default_file_lseek (struct file *file, loff_t offset, int orig) { loff_t retval = -EINVAL; - mutex_lock(&file->f_dentry->d_inode->i_mutex); + mutex_lock(&file->f_path.dentry->d_inode->i_mutex); switch(orig) { case 0: if (offset > 0) { @@ -396,7 +396,7 @@ static loff_t default_file_lseek (struct file *file, loff_t offset, int orig) default: break; } - mutex_unlock(&file->f_dentry->d_inode->i_mutex); + mutex_unlock(&file->f_path.dentry->d_inode->i_mutex); return retval; } diff --git a/trunk/drivers/usb/core/message.c b/trunk/drivers/usb/core/message.c index 29b0fa9ff9d0..149aa8bfb1fe 100644 --- a/trunk/drivers/usb/core/message.c +++ b/trunk/drivers/usb/core/message.c @@ -488,7 +488,7 @@ void usb_sg_wait (struct usb_sg_request *io) int retval; io->urbs [i]->dev = io->dev; - retval = usb_submit_urb (io->urbs [i], SLAB_ATOMIC); + retval = usb_submit_urb (io->urbs [i], GFP_ATOMIC); /* after we submit, let completions or cancelations fire; * we handshake using io->status. @@ -1501,9 +1501,10 @@ struct set_config_request { }; /* Worker routine for usb_driver_set_configuration() */ -static void driver_set_config_work(void *_req) +static void driver_set_config_work(struct work_struct *work) { - struct set_config_request *req = _req; + struct set_config_request *req = + container_of(work, struct set_config_request, work); usb_lock_device(req->udev); usb_set_configuration(req->udev, req->config); @@ -1541,7 +1542,7 @@ int usb_driver_set_configuration(struct usb_device *udev, int config) return -ENOMEM; req->udev = udev; req->config = config; - INIT_WORK(&req->work, driver_set_config_work, req); + INIT_WORK(&req->work, driver_set_config_work); usb_get_dev(udev); if (!schedule_work(&req->work)) { diff --git a/trunk/drivers/usb/core/usb.c b/trunk/drivers/usb/core/usb.c index 81cb52564e68..02426d0b9a34 100644 --- a/trunk/drivers/usb/core/usb.c +++ b/trunk/drivers/usb/core/usb.c @@ -203,9 +203,10 @@ static void ksuspend_usb_cleanup(void) #ifdef CONFIG_USB_SUSPEND /* usb_autosuspend_work - callback routine to autosuspend a USB device */ -static void usb_autosuspend_work(void *_udev) +static void usb_autosuspend_work(struct work_struct *work) { - struct usb_device *udev = _udev; + struct usb_device *udev = + container_of(work, struct usb_device, autosuspend.work); usb_pm_lock(udev); udev->auto_pm = 1; @@ -215,7 +216,7 @@ static void usb_autosuspend_work(void *_udev) #else -static void usb_autosuspend_work(void *_udev) +static void usb_autosuspend_work(struct work_struct *work) {} #endif /* CONFIG_USB_SUSPEND */ @@ -304,7 +305,7 @@ usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1) #ifdef CONFIG_PM mutex_init(&dev->pm_mutex); - INIT_WORK(&dev->autosuspend, usb_autosuspend_work, dev); + INIT_DELAYED_WORK(&dev->autosuspend, usb_autosuspend_work); #endif return dev; } diff --git a/trunk/drivers/usb/gadget/Kconfig b/trunk/drivers/usb/gadget/Kconfig index bbbc82a8336a..4097a86c4b5e 100644 --- a/trunk/drivers/usb/gadget/Kconfig +++ b/trunk/drivers/usb/gadget/Kconfig @@ -189,7 +189,7 @@ config USB_OTG config USB_GADGET_AT91 boolean "AT91 USB Device Port" - depends on ARCH_AT91RM9200 + depends on ARCH_AT91 select USB_GADGET_SELECTED help Many Atmel AT91 processors (such as the AT91RM2000) have a diff --git a/trunk/drivers/usb/gadget/ether.c b/trunk/drivers/usb/gadget/ether.c index 3bd1dfe565c1..d15bf22b9a03 100644 --- a/trunk/drivers/usb/gadget/ether.c +++ b/trunk/drivers/usb/gadget/ether.c @@ -1833,9 +1833,9 @@ static void rx_fill (struct eth_dev *dev, gfp_t gfp_flags) spin_unlock_irqrestore(&dev->req_lock, flags); } -static void eth_work (void *_dev) +static void eth_work (struct work_struct *work) { - struct eth_dev *dev = _dev; + struct eth_dev *dev = container_of(work, struct eth_dev, work); if (test_and_clear_bit (WORK_RX_MEMORY, &dev->todo)) { if (netif_running (dev->net)) @@ -2398,7 +2398,7 @@ eth_bind (struct usb_gadget *gadget) dev = netdev_priv(net); spin_lock_init (&dev->lock); spin_lock_init (&dev->req_lock); - INIT_WORK (&dev->work, eth_work, dev); + INIT_WORK (&dev->work, eth_work); INIT_LIST_HEAD (&dev->tx_reqs); INIT_LIST_HEAD (&dev->rx_reqs); diff --git a/trunk/drivers/usb/gadget/file_storage.c b/trunk/drivers/usb/gadget/file_storage.c index 8b975d15538d..a265e262a2ee 100644 --- a/trunk/drivers/usb/gadget/file_storage.c +++ b/trunk/drivers/usb/gadget/file_storage.c @@ -250,7 +250,7 @@ #include #include #include -#include +#include #include #include @@ -1909,10 +1909,10 @@ static int fsync_sub(struct lun *curlun) if (!filp->f_op->fsync) return -EINVAL; - inode = filp->f_dentry->d_inode; + inode = filp->f_path.dentry->d_inode; mutex_lock(&inode->i_mutex); rc = filemap_fdatawrite(inode->i_mapping); - err = filp->f_op->fsync(filp, filp->f_dentry, 1); + err = filp->f_op->fsync(filp, filp->f_path.dentry, 1); if (!rc) rc = err; err = filemap_fdatawait(inode->i_mapping); @@ -1950,7 +1950,7 @@ static int do_synchronize_cache(struct fsg_dev *fsg) static void invalidate_sub(struct lun *curlun) { struct file *filp = curlun->filp; - struct inode *inode = filp->f_dentry->d_inode; + struct inode *inode = filp->f_path.dentry->d_inode; unsigned long rc; rc = invalidate_inode_pages(inode->i_mapping); @@ -3526,8 +3526,8 @@ static int open_backing_file(struct lun *curlun, const char *filename) if (!(filp->f_mode & FMODE_WRITE)) ro = 1; - if (filp->f_dentry) - inode = filp->f_dentry->d_inode; + if (filp->f_path.dentry) + inode = filp->f_path.dentry->d_inode; if (inode && S_ISBLK(inode->i_mode)) { if (bdev_read_only(inode->i_bdev)) ro = 1; @@ -3606,7 +3606,7 @@ static ssize_t show_file(struct device *dev, struct device_attribute *attr, char down_read(&fsg->filesem); if (backing_file_is_open(curlun)) { // Get the complete pathname - p = d_path(curlun->filp->f_dentry, curlun->filp->f_vfsmnt, + p = d_path(curlun->filp->f_path.dentry, curlun->filp->f_path.mnt, buf, PAGE_SIZE - 1); if (IS_ERR(p)) rc = PTR_ERR(p); @@ -4030,8 +4030,8 @@ static int __init fsg_bind(struct usb_gadget *gadget) if (backing_file_is_open(curlun)) { p = NULL; if (pathbuf) { - p = d_path(curlun->filp->f_dentry, - curlun->filp->f_vfsmnt, + p = d_path(curlun->filp->f_path.dentry, + curlun->filp->f_path.mnt, pathbuf, PATH_MAX); if (IS_ERR(p)) p = NULL; diff --git a/trunk/drivers/usb/gadget/gmidi.c b/trunk/drivers/usb/gadget/gmidi.c index 64554acad63f..31351826f2ba 100644 --- a/trunk/drivers/usb/gadget/gmidi.c +++ b/trunk/drivers/usb/gadget/gmidi.c @@ -1236,7 +1236,7 @@ static int __devinit gmidi_bind(struct usb_gadget *gadget) /* ok, we made sense of the hardware ... */ - dev = kzalloc(sizeof(*dev), SLAB_KERNEL); + dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (!dev) { return -ENOMEM; } diff --git a/trunk/drivers/usb/gadget/goku_udc.c b/trunk/drivers/usb/gadget/goku_udc.c index a3076da3f4eb..805a9826842d 100644 --- a/trunk/drivers/usb/gadget/goku_udc.c +++ b/trunk/drivers/usb/gadget/goku_udc.c @@ -1864,7 +1864,7 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id) } /* alloc, and start init */ - dev = kmalloc (sizeof *dev, SLAB_KERNEL); + dev = kmalloc (sizeof *dev, GFP_KERNEL); if (dev == NULL){ pr_debug("enomem %s\n", pci_name(pdev)); retval = -ENOMEM; diff --git a/trunk/drivers/usb/gadget/inode.c b/trunk/drivers/usb/gadget/inode.c index 86924f9cdd7e..3fb1044a4db0 100644 --- a/trunk/drivers/usb/gadget/inode.c +++ b/trunk/drivers/usb/gadget/inode.c @@ -412,7 +412,7 @@ ep_read (struct file *fd, char __user *buf, size_t len, loff_t *ptr) /* FIXME readahead for O_NONBLOCK and poll(); careful with ZLPs */ value = -ENOMEM; - kbuf = kmalloc (len, SLAB_KERNEL); + kbuf = kmalloc (len, GFP_KERNEL); if (unlikely (!kbuf)) goto free1; @@ -456,7 +456,7 @@ ep_write (struct file *fd, const char __user *buf, size_t len, loff_t *ptr) /* FIXME writebehind for O_NONBLOCK and poll(), qlen = 1 */ value = -ENOMEM; - kbuf = kmalloc (len, SLAB_KERNEL); + kbuf = kmalloc (len, GFP_KERNEL); if (!kbuf) goto free1; if (copy_from_user (kbuf, buf, len)) { @@ -1898,7 +1898,7 @@ dev_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr) buf += 4; length -= 4; - kbuf = kmalloc (length, SLAB_KERNEL); + kbuf = kmalloc (length, GFP_KERNEL); if (!kbuf) return -ENOMEM; if (copy_from_user (kbuf, buf, length)) { diff --git a/trunk/drivers/usb/gadget/net2280.c b/trunk/drivers/usb/gadget/net2280.c index 0b590831582c..3024c679e38e 100644 --- a/trunk/drivers/usb/gadget/net2280.c +++ b/trunk/drivers/usb/gadget/net2280.c @@ -2861,7 +2861,7 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id) } /* alloc, and start init */ - dev = kzalloc (sizeof *dev, SLAB_KERNEL); + dev = kzalloc (sizeof *dev, GFP_KERNEL); if (dev == NULL){ retval = -ENOMEM; goto done; diff --git a/trunk/drivers/usb/gadget/omap_udc.c b/trunk/drivers/usb/gadget/omap_udc.c index 48a09fd89d18..030d87c28c2f 100644 --- a/trunk/drivers/usb/gadget/omap_udc.c +++ b/trunk/drivers/usb/gadget/omap_udc.c @@ -2581,7 +2581,7 @@ omap_udc_setup(struct platform_device *odev, struct otg_transceiver *xceiv) /* UDC_PULLUP_EN gates the chip clock */ // OTG_SYSCON_1_REG |= DEV_IDLE_EN; - udc = kzalloc(sizeof(*udc), SLAB_KERNEL); + udc = kzalloc(sizeof(*udc), GFP_KERNEL); if (!udc) return -ENOMEM; diff --git a/trunk/drivers/usb/gadget/serial.c b/trunk/drivers/usb/gadget/serial.c index 208e55a667ac..5516c59ed5ec 100644 --- a/trunk/drivers/usb/gadget/serial.c +++ b/trunk/drivers/usb/gadget/serial.c @@ -200,7 +200,7 @@ static void gs_unthrottle(struct tty_struct * tty); static void gs_break(struct tty_struct *tty, int break_state); static int gs_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg); -static void gs_set_termios(struct tty_struct *tty, struct termios *old); +static void gs_set_termios(struct tty_struct *tty, struct ktermios *old); static int gs_send(struct gs_dev *dev); static int gs_send_packet(struct gs_dev *dev, char *packet, @@ -1077,7 +1077,7 @@ static int gs_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, /* * gs_set_termios */ -static void gs_set_termios(struct tty_struct *tty, struct termios *old) +static void gs_set_termios(struct tty_struct *tty, struct ktermios *old) { } diff --git a/trunk/drivers/usb/gadget/zero.c b/trunk/drivers/usb/gadget/zero.c index 0f809dd68492..40710ea1b490 100644 --- a/trunk/drivers/usb/gadget/zero.c +++ b/trunk/drivers/usb/gadget/zero.c @@ -1190,7 +1190,7 @@ zero_bind (struct usb_gadget *gadget) /* ok, we made sense of the hardware ... */ - dev = kzalloc(sizeof(*dev), SLAB_KERNEL); + dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (!dev) return -ENOMEM; spin_lock_init (&dev->lock); diff --git a/trunk/drivers/usb/host/ehci-dbg.c b/trunk/drivers/usb/host/ehci-dbg.c index 34b7a31cd85b..56349d21e6ea 100644 --- a/trunk/drivers/usb/host/ehci-dbg.c +++ b/trunk/drivers/usb/host/ehci-dbg.c @@ -492,7 +492,7 @@ show_periodic (struct class_device *class_dev, char *buf) unsigned i; __le32 tag; - if (!(seen = kmalloc (DBG_SCHED_LIMIT * sizeof *seen, SLAB_ATOMIC))) + if (!(seen = kmalloc (DBG_SCHED_LIMIT * sizeof *seen, GFP_ATOMIC))) return 0; seen_count = 0; diff --git a/trunk/drivers/usb/host/hc_crisv10.c b/trunk/drivers/usb/host/hc_crisv10.c index 87eca6aeacf2..9325e46a68c0 100644 --- a/trunk/drivers/usb/host/hc_crisv10.c +++ b/trunk/drivers/usb/host/hc_crisv10.c @@ -188,7 +188,7 @@ static DEFINE_TIMER(bulk_eot_timer, NULL, 0, 0); #define CHECK_ALIGN(x) if (((__u32)(x)) & 0x00000003) \ {panic("Alignment check (DWORD) failed at %s:%s:%d\n", __FILE__, __FUNCTION__, __LINE__);} -#define SLAB_FLAG (in_interrupt() ? SLAB_ATOMIC : SLAB_KERNEL) +#define SLAB_FLAG (in_interrupt() ? GFP_ATOMIC : GFP_KERNEL) #define KMALLOC_FLAG (in_interrupt() ? GFP_ATOMIC : GFP_KERNEL) /* Most helpful debugging aid */ @@ -275,13 +275,13 @@ static volatile USB_SB_Desc_t TxIntrSB_zout __attribute__ ((aligned (4))); static int zout_buffer[4] __attribute__ ((aligned (4))); /* Cache for allocating new EP and SB descriptors. */ -static kmem_cache_t *usb_desc_cache; +static struct kmem_cache *usb_desc_cache; /* Cache for the registers allocated in the top half. */ -static kmem_cache_t *top_half_reg_cache; +static struct kmem_cache *top_half_reg_cache; /* Cache for the data allocated in the isoc descr top half. */ -static kmem_cache_t *isoc_compl_cache; +static struct kmem_cache *isoc_compl_cache; static struct usb_bus *etrax_usb_bus; @@ -1743,7 +1743,7 @@ static irqreturn_t etrax_usb_tx_interrupt(int irq, void *vhc) *R_DMA_CH8_SUB3_CLR_INTR = IO_STATE(R_DMA_CH8_SUB3_CLR_INTR, clr_descr, do); - comp_data = (usb_isoc_complete_data_t*)kmem_cache_alloc(isoc_compl_cache, SLAB_ATOMIC); + comp_data = (usb_isoc_complete_data_t*)kmem_cache_alloc(isoc_compl_cache, GFP_ATOMIC); assert(comp_data != NULL); INIT_WORK(&comp_data->usb_bh, etrax_usb_isoc_descr_interrupt_bottom_half, comp_data); @@ -3010,7 +3010,7 @@ static void etrax_usb_add_to_isoc_sb_list(struct urb *urb, int epid) if (!urb->iso_frame_desc[i].length) continue; - next_sb_desc = (USB_SB_Desc_t*)kmem_cache_alloc(usb_desc_cache, SLAB_ATOMIC); + next_sb_desc = (USB_SB_Desc_t*)kmem_cache_alloc(usb_desc_cache, GFP_ATOMIC); assert(next_sb_desc != NULL); if (urb->iso_frame_desc[i].length > 0) { @@ -3063,7 +3063,7 @@ static void etrax_usb_add_to_isoc_sb_list(struct urb *urb, int epid) if (TxIsocEPList[epid].sub == 0) { dbg_isoc("Isoc traffic not already running, allocating SB"); - next_sb_desc = (USB_SB_Desc_t*)kmem_cache_alloc(usb_desc_cache, SLAB_ATOMIC); + next_sb_desc = (USB_SB_Desc_t*)kmem_cache_alloc(usb_desc_cache, GFP_ATOMIC); assert(next_sb_desc != NULL); next_sb_desc->command = (IO_STATE(USB_SB_command, tt, in) | @@ -3317,7 +3317,7 @@ static irqreturn_t etrax_usb_hc_interrupt_top_half(int irq, void *vhc) restore_flags(flags); - reg = (usb_interrupt_registers_t *)kmem_cache_alloc(top_half_reg_cache, SLAB_ATOMIC); + reg = (usb_interrupt_registers_t *)kmem_cache_alloc(top_half_reg_cache, GFP_ATOMIC); assert(reg != NULL); diff --git a/trunk/drivers/usb/host/ohci-dbg.c b/trunk/drivers/usb/host/ohci-dbg.c index 8293c1d4be3f..0f47a57dac28 100644 --- a/trunk/drivers/usb/host/ohci-dbg.c +++ b/trunk/drivers/usb/host/ohci-dbg.c @@ -505,7 +505,7 @@ show_periodic (struct class_device *class_dev, char *buf) char *next; unsigned i; - if (!(seen = kmalloc (DBG_SCHED_LIMIT * sizeof *seen, SLAB_ATOMIC))) + if (!(seen = kmalloc (DBG_SCHED_LIMIT * sizeof *seen, GFP_ATOMIC))) return 0; seen_count = 0; diff --git a/trunk/drivers/usb/host/ohci-hcd.c b/trunk/drivers/usb/host/ohci-hcd.c index a95275a401b1..b28a9b602066 100644 --- a/trunk/drivers/usb/host/ohci-hcd.c +++ b/trunk/drivers/usb/host/ohci-hcd.c @@ -945,7 +945,7 @@ MODULE_LICENSE ("GPL"); #include "ohci-ppc-soc.c" #endif -#if defined(CONFIG_ARCH_AT91RM9200) || defined(CONFIG_ARCH_AT91SAM9261) +#ifdef CONFIG_ARCH_AT91 #include "ohci-at91.c" #endif @@ -962,8 +962,7 @@ MODULE_LICENSE ("GPL"); || defined (CONFIG_ARCH_EP93XX) \ || defined (CONFIG_SOC_AU1X00) \ || defined (CONFIG_USB_OHCI_HCD_PPC_SOC) \ - || defined (CONFIG_ARCH_AT91RM9200) \ - || defined (CONFIG_ARCH_AT91SAM9261) \ + || defined (CONFIG_ARCH_AT91) \ || defined (CONFIG_ARCH_PNX4008) \ ) #error "missing bus glue for ohci-hcd" diff --git a/trunk/drivers/usb/host/ohci-pnx4008.c b/trunk/drivers/usb/host/ohci-pnx4008.c index 2dbb77414905..7f26f9bdbaf1 100644 --- a/trunk/drivers/usb/host/ohci-pnx4008.c +++ b/trunk/drivers/usb/host/ohci-pnx4008.c @@ -134,7 +134,7 @@ static int isp1301_attach(struct i2c_adapter *adap, int addr, int kind) { struct i2c_client *c; - c = (struct i2c_client *)kzalloc(sizeof(*c), SLAB_KERNEL); + c = (struct i2c_client *)kzalloc(sizeof(*c), GFP_KERNEL); if (!c) return -ENOMEM; diff --git a/trunk/drivers/usb/host/sl811_cs.c b/trunk/drivers/usb/host/sl811_cs.c index 54f554e0f0ad..ac9f11d19817 100644 --- a/trunk/drivers/usb/host/sl811_cs.c +++ b/trunk/drivers/usb/host/sl811_cs.c @@ -169,21 +169,14 @@ static int sl811_cs_config(struct pcmcia_device *link) DBG(0, "sl811_cs_config(0x%p)\n", link); - tuple.DesiredTuple = CISTPL_CONFIG; - tuple.Attributes = 0; - tuple.TupleData = buf; - tuple.TupleDataMax = sizeof(buf); - tuple.TupleOffset = 0; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); - link->conf.ConfigBase = parse.config.base; - link->conf.Present = parse.config.rmask[0]; - /* Look up the current Vcc */ CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &conf)); + tuple.Attributes = 0; + tuple.TupleData = buf; + tuple.TupleDataMax = sizeof(buf); + tuple.TupleOffset = 0; tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); while (1) { diff --git a/trunk/drivers/usb/host/u132-hcd.c b/trunk/drivers/usb/host/u132-hcd.c index ef54e310bfc4..a9d7119e3176 100644 --- a/trunk/drivers/usb/host/u132-hcd.c +++ b/trunk/drivers/usb/host/u132-hcd.c @@ -163,7 +163,7 @@ struct u132_endp { u16 queue_next; struct urb *urb_list[ENDP_QUEUE_SIZE]; struct list_head urb_more; - struct work_struct scheduler; + struct delayed_work scheduler; }; struct u132_ring { unsigned in_use:1; @@ -171,7 +171,7 @@ struct u132_ring { u8 number; struct u132 *u132; struct u132_endp *curr_endp; - struct work_struct scheduler; + struct delayed_work scheduler; }; #define OHCI_QUIRK_AMD756 0x01 #define OHCI_QUIRK_SUPERIO 0x02 @@ -198,7 +198,7 @@ struct u132 { u32 hc_roothub_portstatus[MAX_ROOT_PORTS]; int flags; unsigned long next_statechange; - struct work_struct monitor; + struct delayed_work monitor; int num_endpoints; struct u132_addr addr[MAX_U132_ADDRS]; struct u132_udev udev[MAX_U132_UDEVS]; @@ -310,7 +310,7 @@ static void u132_ring_requeue_work(struct u132 *u132, struct u132_ring *ring, if (delta > 0) { if (queue_delayed_work(workqueue, &ring->scheduler, delta)) return; - } else if (queue_work(workqueue, &ring->scheduler)) + } else if (queue_delayed_work(workqueue, &ring->scheduler, 0)) return; kref_put(&u132->kref, u132_hcd_delete); return; @@ -389,12 +389,8 @@ static inline void u132_endp_init_kref(struct u132 *u132, static void u132_endp_queue_work(struct u132 *u132, struct u132_endp *endp, unsigned int delta) { - if (delta > 0) { - if (queue_delayed_work(workqueue, &endp->scheduler, delta)) - kref_get(&endp->kref); - } else if (queue_work(workqueue, &endp->scheduler)) - kref_get(&endp->kref); - return; + if (queue_delayed_work(workqueue, &endp->scheduler, delta)) + kref_get(&endp->kref); } static void u132_endp_cancel_work(struct u132 *u132, struct u132_endp *endp) @@ -410,24 +406,14 @@ static inline void u132_monitor_put_kref(struct u132 *u132) static void u132_monitor_queue_work(struct u132 *u132, unsigned int delta) { - if (delta > 0) { - if (queue_delayed_work(workqueue, &u132->monitor, delta)) { - kref_get(&u132->kref); - } - } else if (queue_work(workqueue, &u132->monitor)) - kref_get(&u132->kref); - return; + if (queue_delayed_work(workqueue, &u132->monitor, delta)) + kref_get(&u132->kref); } static void u132_monitor_requeue_work(struct u132 *u132, unsigned int delta) { - if (delta > 0) { - if (queue_delayed_work(workqueue, &u132->monitor, delta)) - return; - } else if (queue_work(workqueue, &u132->monitor)) - return; - kref_put(&u132->kref, u132_hcd_delete); - return; + if (!queue_delayed_work(workqueue, &u132->monitor, delta)) + kref_put(&u132->kref, u132_hcd_delete); } static void u132_monitor_cancel_work(struct u132 *u132) @@ -489,9 +475,9 @@ static int read_roothub_info(struct u132 *u132) return 0; } -static void u132_hcd_monitor_work(void *data) +static void u132_hcd_monitor_work(struct work_struct *work) { - struct u132 *u132 = data; + struct u132 *u132 = container_of(work, struct u132, monitor.work); if (u132->going > 1) { dev_err(&u132->platform_dev->dev, "device has been removed %d\n" , u132->going); @@ -1315,15 +1301,14 @@ static void u132_hcd_initial_setup_sent(void *data, struct urb *urb, u8 *buf, } } -static void u132_hcd_ring_work_scheduler(void *data); -static void u132_hcd_endp_work_scheduler(void *data); /* * this work function is only executed from the work queue * */ -static void u132_hcd_ring_work_scheduler(void *data) +static void u132_hcd_ring_work_scheduler(struct work_struct *work) { - struct u132_ring *ring = data; + struct u132_ring *ring = + container_of(work, struct u132_ring, scheduler.work); struct u132 *u132 = ring->u132; down(&u132->scheduler_lock); if (ring->in_use) { @@ -1382,10 +1367,11 @@ static void u132_hcd_ring_work_scheduler(void *data) } } -static void u132_hcd_endp_work_scheduler(void *data) +static void u132_hcd_endp_work_scheduler(struct work_struct *work) { struct u132_ring *ring; - struct u132_endp *endp = data; + struct u132_endp *endp = + container_of(work, struct u132_endp, scheduler.work); struct u132 *u132 = endp->u132; down(&u132->scheduler_lock); ring = endp->ring; @@ -1943,7 +1929,7 @@ static int create_endpoint_and_queue_int(struct u132 *u132, if (!endp) { return -ENOMEM; } - INIT_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler, (void *)endp); + INIT_DELAYED_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler); spin_lock_init(&endp->queue_lock.slock); INIT_LIST_HEAD(&endp->urb_more); ring = endp->ring = &u132->ring[0]; @@ -2032,7 +2018,7 @@ static int create_endpoint_and_queue_bulk(struct u132 *u132, if (!endp) { return -ENOMEM; } - INIT_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler, (void *)endp); + INIT_DELAYED_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler); spin_lock_init(&endp->queue_lock.slock); INIT_LIST_HEAD(&endp->urb_more); endp->dequeueing = 0; @@ -2117,7 +2103,7 @@ static int create_endpoint_and_queue_control(struct u132 *u132, if (!endp) { return -ENOMEM; } - INIT_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler, (void *)endp); + INIT_DELAYED_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler); spin_lock_init(&endp->queue_lock.slock); INIT_LIST_HEAD(&endp->urb_more); ring = endp->ring = &u132->ring[0]; @@ -3096,10 +3082,10 @@ static void u132_initialise(struct u132 *u132, struct platform_device *pdev) ring->number = rings + 1; ring->length = 0; ring->curr_endp = NULL; - INIT_WORK(&ring->scheduler, u132_hcd_ring_work_scheduler, - (void *)ring); + INIT_DELAYED_WORK(&ring->scheduler, + u132_hcd_ring_work_scheduler); } down(&u132->sw_lock); - INIT_WORK(&u132->monitor, u132_hcd_monitor_work, (void *)u132); + INIT_DELAYED_WORK(&u132->monitor, u132_hcd_monitor_work); while (ports-- > 0) { struct u132_port *port = &u132->port[ports]; port->u132 = u132; diff --git a/trunk/drivers/usb/host/uhci-hcd.c b/trunk/drivers/usb/host/uhci-hcd.c index 226bf3de8edd..e87692c31be4 100644 --- a/trunk/drivers/usb/host/uhci-hcd.c +++ b/trunk/drivers/usb/host/uhci-hcd.c @@ -81,7 +81,7 @@ MODULE_PARM_DESC(debug, "Debug level"); static char *errbuf; #define ERRBUF_LEN (32 * 1024) -static kmem_cache_t *uhci_up_cachep; /* urb_priv */ +static struct kmem_cache *uhci_up_cachep; /* urb_priv */ static void suspend_rh(struct uhci_hcd *uhci, enum uhci_rh_state new_state); static void wakeup_rh(struct uhci_hcd *uhci); diff --git a/trunk/drivers/usb/host/uhci-q.c b/trunk/drivers/usb/host/uhci-q.c index 06115f22a4fa..30b88459ac7d 100644 --- a/trunk/drivers/usb/host/uhci-q.c +++ b/trunk/drivers/usb/host/uhci-q.c @@ -498,7 +498,7 @@ static inline struct urb_priv *uhci_alloc_urb_priv(struct uhci_hcd *uhci, { struct urb_priv *urbp; - urbp = kmem_cache_alloc(uhci_up_cachep, SLAB_ATOMIC); + urbp = kmem_cache_alloc(uhci_up_cachep, GFP_ATOMIC); if (!urbp) return NULL; diff --git a/trunk/drivers/usb/input/acecad.c b/trunk/drivers/usb/input/acecad.c index 0096373b5f98..909138e5aa04 100644 --- a/trunk/drivers/usb/input/acecad.c +++ b/trunk/drivers/usb/input/acecad.c @@ -152,7 +152,7 @@ static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_ if (!acecad || !input_dev) goto fail1; - acecad->data = usb_buffer_alloc(dev, 8, SLAB_KERNEL, &acecad->data_dma); + acecad->data = usb_buffer_alloc(dev, 8, GFP_KERNEL, &acecad->data_dma); if (!acecad->data) goto fail1; diff --git a/trunk/drivers/usb/input/aiptek.c b/trunk/drivers/usb/input/aiptek.c index bf428184608f..9f52429ce654 100644 --- a/trunk/drivers/usb/input/aiptek.c +++ b/trunk/drivers/usb/input/aiptek.c @@ -1988,7 +1988,7 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id) goto fail1; aiptek->data = usb_buffer_alloc(usbdev, AIPTEK_PACKET_LENGTH, - SLAB_ATOMIC, &aiptek->data_dma); + GFP_ATOMIC, &aiptek->data_dma); if (!aiptek->data) goto fail1; diff --git a/trunk/drivers/usb/input/appletouch.c b/trunk/drivers/usb/input/appletouch.c index 4c213513484d..c77291d3d063 100644 --- a/trunk/drivers/usb/input/appletouch.c +++ b/trunk/drivers/usb/input/appletouch.c @@ -38,14 +38,29 @@ #define APPLE_VENDOR_ID 0x05AC /* These names come from Info.plist in AppleUSBTrackpad.kext */ -#define GEYSER_ANSI_PRODUCT_ID 0x0214 -#define GEYSER_ISO_PRODUCT_ID 0x0215 -#define GEYSER_JIS_PRODUCT_ID 0x0216 +#define FOUNTAIN_ANSI_PRODUCT_ID 0x020E +#define FOUNTAIN_ISO_PRODUCT_ID 0x020F + +#define FOUNTAIN_TP_ONLY_PRODUCT_ID 0x030A + +#define GEYSER1_TP_ONLY_PRODUCT_ID 0x030B + +#define GEYSER_ANSI_PRODUCT_ID 0x0214 +#define GEYSER_ISO_PRODUCT_ID 0x0215 +#define GEYSER_JIS_PRODUCT_ID 0x0216 /* MacBook devices */ -#define GEYSER3_ANSI_PRODUCT_ID 0x0217 -#define GEYSER3_ISO_PRODUCT_ID 0x0218 -#define GEYSER3_JIS_PRODUCT_ID 0x0219 +#define GEYSER3_ANSI_PRODUCT_ID 0x0217 +#define GEYSER3_ISO_PRODUCT_ID 0x0218 +#define GEYSER3_JIS_PRODUCT_ID 0x0219 + +/* + * Geyser IV: same as Geyser III according to Info.plist in AppleUSBTrackpad.kext + * -> same IOClass (AppleUSBGrIIITrackpad), same acceleration tables + */ +#define GEYSER4_ANSI_PRODUCT_ID 0x021A +#define GEYSER4_ISO_PRODUCT_ID 0x021B +#define GEYSER4_JIS_PRODUCT_ID 0x021C #define ATP_DEVICE(prod) \ .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \ @@ -58,20 +73,26 @@ /* table of devices that work with this driver */ static struct usb_device_id atp_table [] = { - { ATP_DEVICE(0x020E) }, - { ATP_DEVICE(0x020F) }, - { ATP_DEVICE(0x030A) }, - { ATP_DEVICE(0x030B) }, + { ATP_DEVICE(FOUNTAIN_ANSI_PRODUCT_ID) }, + { ATP_DEVICE(FOUNTAIN_ISO_PRODUCT_ID) }, + { ATP_DEVICE(FOUNTAIN_TP_ONLY_PRODUCT_ID) }, + { ATP_DEVICE(GEYSER1_TP_ONLY_PRODUCT_ID) }, /* PowerBooks Oct 2005 */ { ATP_DEVICE(GEYSER_ANSI_PRODUCT_ID) }, { ATP_DEVICE(GEYSER_ISO_PRODUCT_ID) }, { ATP_DEVICE(GEYSER_JIS_PRODUCT_ID) }, + /* Core Duo MacBook & MacBook Pro */ { ATP_DEVICE(GEYSER3_ANSI_PRODUCT_ID) }, { ATP_DEVICE(GEYSER3_ISO_PRODUCT_ID) }, { ATP_DEVICE(GEYSER3_JIS_PRODUCT_ID) }, + /* Core2 Duo MacBook & MacBook Pro */ + { ATP_DEVICE(GEYSER4_ANSI_PRODUCT_ID) }, + { ATP_DEVICE(GEYSER4_ISO_PRODUCT_ID) }, + { ATP_DEVICE(GEYSER4_JIS_PRODUCT_ID) }, + /* Terminating entry */ { } }; @@ -108,7 +129,7 @@ MODULE_DEVICE_TABLE (usb, atp_table); */ #define ATP_THRESHOLD 5 -/* MacBook Pro (Geyser 3) initialization constants */ +/* MacBook Pro (Geyser 3 & 4) initialization constants */ #define ATP_GEYSER3_MODE_READ_REQUEST_ID 1 #define ATP_GEYSER3_MODE_WRITE_REQUEST_ID 9 #define ATP_GEYSER3_MODE_REQUEST_VALUE 0x300 @@ -154,6 +175,13 @@ MODULE_AUTHOR("Johannes Berg, Stelian Pop, Frank Arnold, Michael Hanselmann"); MODULE_DESCRIPTION("Apple PowerBooks USB touchpad driver"); MODULE_LICENSE("GPL"); +/* + * Make the threshold a module parameter + */ +static int threshold = ATP_THRESHOLD; +module_param(threshold, int, 0644); +MODULE_PARM_DESC(threshold, "Discards any change in data from a sensor (trackpad has hundreds of these sensors) less than this value"); + static int debug = 1; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Activate debugging output"); @@ -174,7 +202,10 @@ static inline int atp_is_geyser_3(struct atp *dev) return (productId == GEYSER3_ANSI_PRODUCT_ID) || (productId == GEYSER3_ISO_PRODUCT_ID) || - (productId == GEYSER3_JIS_PRODUCT_ID); + (productId == GEYSER3_JIS_PRODUCT_ID) || + (productId == GEYSER4_ANSI_PRODUCT_ID) || + (productId == GEYSER4_ISO_PRODUCT_ID) || + (productId == GEYSER4_JIS_PRODUCT_ID); } static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact, @@ -183,16 +214,48 @@ static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact, int i; /* values to calculate mean */ int pcum = 0, psum = 0; + int is_increasing = 0; *fingers = 0; for (i = 0; i < nb_sensors; i++) { - if (xy_sensors[i] < ATP_THRESHOLD) + if (xy_sensors[i] < threshold) { + if (is_increasing) + is_increasing = 0; + continue; - if ((i - 1 < 0) || (xy_sensors[i - 1] < ATP_THRESHOLD)) + } + + /* + * Makes the finger detection more versatile. For example, + * two fingers with no gap will be detected. Also, my + * tests show it less likely to have intermittent loss + * of multiple finger readings while moving around (scrolling). + * + * Changes the multiple finger detection to counting humps on + * sensors (transitions from nonincreasing to increasing) + * instead of counting transitions from low sensors (no + * finger reading) to high sensors (finger above + * sensor) + * + * - Jason Parekh + */ + if (i < 1 || (!is_increasing && xy_sensors[i - 1] < xy_sensors[i])) { (*fingers)++; - pcum += xy_sensors[i] * i; - psum += xy_sensors[i]; + is_increasing = 1; + } else if (i > 0 && xy_sensors[i - 1] >= xy_sensors[i]) { + is_increasing = 0; + } + + /* + * Subtracts threshold so a high sensor that just passes the threshold + * won't skew the calculated absolute coordinate. Fixes an issue + * where slowly moving the mouse would occassionaly jump a number of + * pixels (let me restate--slowly moving the mouse makes this issue + * most apparent). + */ + pcum += (xy_sensors[i] - threshold) * i; + psum += (xy_sensors[i] - threshold); } if (psum > 0) { diff --git a/trunk/drivers/usb/input/ati_remote.c b/trunk/drivers/usb/input/ati_remote.c index ff23318dc301..b724e36f7b92 100644 --- a/trunk/drivers/usb/input/ati_remote.c +++ b/trunk/drivers/usb/input/ati_remote.c @@ -592,7 +592,7 @@ static void ati_remote_irq_in(struct urb *urb) __FUNCTION__, urb->status); } - retval = usb_submit_urb(urb, SLAB_ATOMIC); + retval = usb_submit_urb(urb, GFP_ATOMIC); if (retval) dev_err(&ati_remote->interface->dev, "%s: usb_submit_urb()=%d\n", __FUNCTION__, retval); @@ -604,12 +604,12 @@ static void ati_remote_irq_in(struct urb *urb) static int ati_remote_alloc_buffers(struct usb_device *udev, struct ati_remote *ati_remote) { - ati_remote->inbuf = usb_buffer_alloc(udev, DATA_BUFSIZE, SLAB_ATOMIC, + ati_remote->inbuf = usb_buffer_alloc(udev, DATA_BUFSIZE, GFP_ATOMIC, &ati_remote->inbuf_dma); if (!ati_remote->inbuf) return -1; - ati_remote->outbuf = usb_buffer_alloc(udev, DATA_BUFSIZE, SLAB_ATOMIC, + ati_remote->outbuf = usb_buffer_alloc(udev, DATA_BUFSIZE, GFP_ATOMIC, &ati_remote->outbuf_dma); if (!ati_remote->outbuf) return -1; diff --git a/trunk/drivers/usb/input/hid-core.c b/trunk/drivers/usb/input/hid-core.c index a49644b7c58e..0811c39bd14f 100644 --- a/trunk/drivers/usb/input/hid-core.c +++ b/trunk/drivers/usb/input/hid-core.c @@ -969,9 +969,10 @@ static void hid_retry_timeout(unsigned long _hid) } /* Workqueue routine to reset the device or clear a halt */ -static void hid_reset(void *_hid) +static void hid_reset(struct work_struct *work) { - struct hid_device *hid = (struct hid_device *) _hid; + struct hid_device *hid = + container_of(work, struct hid_device, reset_work); int rc_lock, rc = 0; if (test_bit(HID_CLEAR_HALT, &hid->iofl)) { @@ -1078,7 +1079,7 @@ static void hid_irq_in(struct urb *urb) warn("input irq status %d received", urb->status); } - status = usb_submit_urb(urb, SLAB_ATOMIC); + status = usb_submit_urb(urb, GFP_ATOMIC); if (status) { clear_bit(HID_IN_RUNNING, &hid->iofl); if (status != -EPERM) { @@ -1669,6 +1670,9 @@ void hid_init_reports(struct hid_device *hid) #define USB_VENDOR_ID_AIRCABLE 0x16CA #define USB_DEVICE_ID_AIRCABLE1 0x1502 +#define USB_VENDOR_ID_LOGITECH 0x046d +#define USB_DEVICE_ID_LOGITECH_USB_RECEIVER 0xc101 + /* * Alphabetically sorted blacklist by quirk type. */ @@ -1840,7 +1844,9 @@ static const struct hid_blacklist { { USB_VENDOR_ID_PANJIT, 0x0004, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET }, - + + { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_USB_RECEIVER, HID_QUIRK_BAD_RELATIVE_KEYS }, + { 0, 0 } }; @@ -1863,13 +1869,13 @@ static void hid_find_max_report(struct hid_device *hid, unsigned int type, int * static int hid_alloc_buffers(struct usb_device *dev, struct hid_device *hid) { - if (!(hid->inbuf = usb_buffer_alloc(dev, hid->bufsize, SLAB_ATOMIC, &hid->inbuf_dma))) + if (!(hid->inbuf = usb_buffer_alloc(dev, hid->bufsize, GFP_ATOMIC, &hid->inbuf_dma))) return -1; - if (!(hid->outbuf = usb_buffer_alloc(dev, hid->bufsize, SLAB_ATOMIC, &hid->outbuf_dma))) + if (!(hid->outbuf = usb_buffer_alloc(dev, hid->bufsize, GFP_ATOMIC, &hid->outbuf_dma))) return -1; - if (!(hid->cr = usb_buffer_alloc(dev, sizeof(*(hid->cr)), SLAB_ATOMIC, &hid->cr_dma))) + if (!(hid->cr = usb_buffer_alloc(dev, sizeof(*(hid->cr)), GFP_ATOMIC, &hid->cr_dma))) return -1; - if (!(hid->ctrlbuf = usb_buffer_alloc(dev, hid->bufsize, SLAB_ATOMIC, &hid->ctrlbuf_dma))) + if (!(hid->ctrlbuf = usb_buffer_alloc(dev, hid->bufsize, GFP_ATOMIC, &hid->ctrlbuf_dma))) return -1; return 0; @@ -2043,7 +2049,7 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf) init_waitqueue_head(&hid->wait); - INIT_WORK(&hid->reset_work, hid_reset, hid); + INIT_WORK(&hid->reset_work, hid_reset); setup_timer(&hid->io_retry, hid_retry_timeout, (unsigned long) hid); spin_lock_init(&hid->inlock); diff --git a/trunk/drivers/usb/input/hid-input.c b/trunk/drivers/usb/input/hid-input.c index 68e7ebb978a9..3a7e5fbff025 100644 --- a/trunk/drivers/usb/input/hid-input.c +++ b/trunk/drivers/usb/input/hid-input.c @@ -581,6 +581,10 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel || ((device->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_7) && (usage->hid == 0x00090007))) goto ignore; + if ((device->quirks & HID_QUIRK_BAD_RELATIVE_KEYS) && + usage->type == EV_KEY && (field->flags & HID_MAIN_ITEM_RELATIVE)) + field->flags &= ~HID_MAIN_ITEM_RELATIVE; + set_bit(usage->type, input->evbit); while (usage->code <= max && test_and_set_bit(usage->code, bit)) diff --git a/trunk/drivers/usb/input/hid.h b/trunk/drivers/usb/input/hid.h index 2a9bf07944c0..76ad68d9edfd 100644 --- a/trunk/drivers/usb/input/hid.h +++ b/trunk/drivers/usb/input/hid.h @@ -261,6 +261,7 @@ struct hid_item { #define HID_QUIRK_POWERBOOK_FN_ON 0x00002000 #define HID_QUIRK_INVERT_HWHEEL 0x00004000 #define HID_QUIRK_POWERBOOK_ISO_KEYBOARD 0x00008000 +#define HID_QUIRK_BAD_RELATIVE_KEYS 0x00010000 /* * This is the global environment of the parser. This information is diff --git a/trunk/drivers/usb/input/keyspan_remote.c b/trunk/drivers/usb/input/keyspan_remote.c index 50aa8108a50b..98bd323369c7 100644 --- a/trunk/drivers/usb/input/keyspan_remote.c +++ b/trunk/drivers/usb/input/keyspan_remote.c @@ -456,7 +456,7 @@ static int keyspan_probe(struct usb_interface *interface, const struct usb_devic remote->in_endpoint = endpoint; remote->toggle = -1; /* Set to -1 so we will always not match the toggle from the first remote message. */ - remote->in_buffer = usb_buffer_alloc(udev, RECV_SIZE, SLAB_ATOMIC, &remote->in_dma); + remote->in_buffer = usb_buffer_alloc(udev, RECV_SIZE, GFP_ATOMIC, &remote->in_dma); if (!remote->in_buffer) { retval = -ENOMEM; goto fail1; diff --git a/trunk/drivers/usb/input/mtouchusb.c b/trunk/drivers/usb/input/mtouchusb.c index 79a85d46cb13..92c4e07da4c8 100644 --- a/trunk/drivers/usb/input/mtouchusb.c +++ b/trunk/drivers/usb/input/mtouchusb.c @@ -164,7 +164,7 @@ static int mtouchusb_alloc_buffers(struct usb_device *udev, struct mtouch_usb *m dbg("%s - called", __FUNCTION__); mtouch->data = usb_buffer_alloc(udev, MTOUCHUSB_REPORT_DATA_SIZE, - SLAB_ATOMIC, &mtouch->data_dma); + GFP_ATOMIC, &mtouch->data_dma); if (!mtouch->data) return -1; diff --git a/trunk/drivers/usb/input/powermate.c b/trunk/drivers/usb/input/powermate.c index 0bf91778c40d..fea97e5437f8 100644 --- a/trunk/drivers/usb/input/powermate.c +++ b/trunk/drivers/usb/input/powermate.c @@ -277,12 +277,12 @@ static int powermate_input_event(struct input_dev *dev, unsigned int type, unsig static int powermate_alloc_buffers(struct usb_device *udev, struct powermate_device *pm) { pm->data = usb_buffer_alloc(udev, POWERMATE_PAYLOAD_SIZE_MAX, - SLAB_ATOMIC, &pm->data_dma); + GFP_ATOMIC, &pm->data_dma); if (!pm->data) return -1; pm->configcr = usb_buffer_alloc(udev, sizeof(*(pm->configcr)), - SLAB_ATOMIC, &pm->configcr_dma); + GFP_ATOMIC, &pm->configcr_dma); if (!pm->configcr) return -1; diff --git a/trunk/drivers/usb/input/touchkitusb.c b/trunk/drivers/usb/input/touchkitusb.c index 05c0d1ca39ab..2a314b065922 100644 --- a/trunk/drivers/usb/input/touchkitusb.c +++ b/trunk/drivers/usb/input/touchkitusb.c @@ -248,7 +248,7 @@ static int touchkit_alloc_buffers(struct usb_device *udev, struct touchkit_usb *touchkit) { touchkit->data = usb_buffer_alloc(udev, TOUCHKIT_REPORT_DATA_SIZE, - SLAB_ATOMIC, &touchkit->data_dma); + GFP_ATOMIC, &touchkit->data_dma); if (!touchkit->data) return -1; diff --git a/trunk/drivers/usb/input/usbkbd.c b/trunk/drivers/usb/input/usbkbd.c index dac88640eab6..8505824848f6 100644 --- a/trunk/drivers/usb/input/usbkbd.c +++ b/trunk/drivers/usb/input/usbkbd.c @@ -122,7 +122,7 @@ static void usb_kbd_irq(struct urb *urb) memcpy(kbd->old, kbd->new, 8); resubmit: - i = usb_submit_urb (urb, SLAB_ATOMIC); + i = usb_submit_urb (urb, GFP_ATOMIC); if (i) err ("can't resubmit intr, %s-%s/input0, status %d", kbd->usbdev->bus->bus_name, @@ -196,11 +196,11 @@ static int usb_kbd_alloc_mem(struct usb_device *dev, struct usb_kbd *kbd) return -1; if (!(kbd->led = usb_alloc_urb(0, GFP_KERNEL))) return -1; - if (!(kbd->new = usb_buffer_alloc(dev, 8, SLAB_ATOMIC, &kbd->new_dma))) + if (!(kbd->new = usb_buffer_alloc(dev, 8, GFP_ATOMIC, &kbd->new_dma))) return -1; - if (!(kbd->cr = usb_buffer_alloc(dev, sizeof(struct usb_ctrlrequest), SLAB_ATOMIC, &kbd->cr_dma))) + if (!(kbd->cr = usb_buffer_alloc(dev, sizeof(struct usb_ctrlrequest), GFP_ATOMIC, &kbd->cr_dma))) return -1; - if (!(kbd->leds = usb_buffer_alloc(dev, 1, SLAB_ATOMIC, &kbd->leds_dma))) + if (!(kbd->leds = usb_buffer_alloc(dev, 1, GFP_ATOMIC, &kbd->leds_dma))) return -1; return 0; diff --git a/trunk/drivers/usb/input/usbmouse.c b/trunk/drivers/usb/input/usbmouse.c index 68a55642c082..64a33e420cfb 100644 --- a/trunk/drivers/usb/input/usbmouse.c +++ b/trunk/drivers/usb/input/usbmouse.c @@ -86,7 +86,7 @@ static void usb_mouse_irq(struct urb *urb) input_sync(dev); resubmit: - status = usb_submit_urb (urb, SLAB_ATOMIC); + status = usb_submit_urb (urb, GFP_ATOMIC); if (status) err ("can't resubmit intr, %s-%s/input0, status %d", mouse->usbdev->bus->bus_name, @@ -137,7 +137,7 @@ static int usb_mouse_probe(struct usb_interface *intf, const struct usb_device_i if (!mouse || !input_dev) goto fail1; - mouse->data = usb_buffer_alloc(dev, 8, SLAB_ATOMIC, &mouse->data_dma); + mouse->data = usb_buffer_alloc(dev, 8, GFP_ATOMIC, &mouse->data_dma); if (!mouse->data) goto fail1; diff --git a/trunk/drivers/usb/input/usbtouchscreen.c b/trunk/drivers/usb/input/usbtouchscreen.c index 49704d4ed0e2..7f3c57da9bc0 100644 --- a/trunk/drivers/usb/input/usbtouchscreen.c +++ b/trunk/drivers/usb/input/usbtouchscreen.c @@ -680,7 +680,7 @@ static int usbtouch_probe(struct usb_interface *intf, type->process_pkt = usbtouch_process_pkt; usbtouch->data = usb_buffer_alloc(udev, type->rept_size, - SLAB_KERNEL, &usbtouch->data_dma); + GFP_KERNEL, &usbtouch->data_dma); if (!usbtouch->data) goto out_free; diff --git a/trunk/drivers/usb/input/xpad.c b/trunk/drivers/usb/input/xpad.c index df97e5c803f9..e4bc76ebc835 100644 --- a/trunk/drivers/usb/input/xpad.c +++ b/trunk/drivers/usb/input/xpad.c @@ -325,7 +325,7 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id goto fail1; xpad->idata = usb_buffer_alloc(udev, XPAD_PKT_LEN, - SLAB_ATOMIC, &xpad->idata_dma); + GFP_ATOMIC, &xpad->idata_dma); if (!xpad->idata) goto fail1; diff --git a/trunk/drivers/usb/input/yealink.c b/trunk/drivers/usb/input/yealink.c index 2268ca311ade..caff8e6d7448 100644 --- a/trunk/drivers/usb/input/yealink.c +++ b/trunk/drivers/usb/input/yealink.c @@ -874,17 +874,17 @@ static int usb_probe(struct usb_interface *intf, const struct usb_device_id *id) /* allocate usb buffers */ yld->irq_data = usb_buffer_alloc(udev, USB_PKT_LEN, - SLAB_ATOMIC, &yld->irq_dma); + GFP_ATOMIC, &yld->irq_dma); if (yld->irq_data == NULL) return usb_cleanup(yld, -ENOMEM); yld->ctl_data = usb_buffer_alloc(udev, USB_PKT_LEN, - SLAB_ATOMIC, &yld->ctl_dma); + GFP_ATOMIC, &yld->ctl_dma); if (!yld->ctl_data) return usb_cleanup(yld, -ENOMEM); yld->ctl_req = usb_buffer_alloc(udev, sizeof(*(yld->ctl_req)), - SLAB_ATOMIC, &yld->ctl_req_dma); + GFP_ATOMIC, &yld->ctl_req_dma); if (yld->ctl_req == NULL) return usb_cleanup(yld, -ENOMEM); diff --git a/trunk/drivers/usb/misc/appledisplay.c b/trunk/drivers/usb/misc/appledisplay.c index ba30ca6a14aa..02cbb7fff24f 100644 --- a/trunk/drivers/usb/misc/appledisplay.c +++ b/trunk/drivers/usb/misc/appledisplay.c @@ -76,7 +76,7 @@ struct appledisplay { char *urbdata; /* interrupt URB data buffer */ char *msgdata; /* control message data buffer */ - struct work_struct work; + struct delayed_work work; int button_pressed; spinlock_t lock; }; @@ -117,7 +117,7 @@ static void appledisplay_complete(struct urb *urb) case ACD_BTN_BRIGHT_UP: case ACD_BTN_BRIGHT_DOWN: pdata->button_pressed = 1; - queue_work(wq, &pdata->work); + queue_delayed_work(wq, &pdata->work, 0); break; case ACD_BTN_NONE: default: @@ -184,9 +184,10 @@ static struct backlight_properties appledisplay_bl_data = { .max_brightness = 0xFF }; -static void appledisplay_work(void *private) +static void appledisplay_work(struct work_struct *work) { - struct appledisplay *pdata = private; + struct appledisplay *pdata = + container_of(work, struct appledisplay, work.work); int retval; up(&pdata->bd->sem); @@ -238,7 +239,7 @@ static int appledisplay_probe(struct usb_interface *iface, pdata->udev = udev; spin_lock_init(&pdata->lock); - INIT_WORK(&pdata->work, appledisplay_work, pdata); + INIT_DELAYED_WORK(&pdata->work, appledisplay_work); /* Allocate buffer for control messages */ pdata->msgdata = kmalloc(ACD_MSG_BUFFER_LEN, GFP_KERNEL); diff --git a/trunk/drivers/usb/misc/ftdi-elan.c b/trunk/drivers/usb/misc/ftdi-elan.c index cb0ba3107d7f..18b1925032a8 100644 --- a/trunk/drivers/usb/misc/ftdi-elan.c +++ b/trunk/drivers/usb/misc/ftdi-elan.c @@ -156,9 +156,9 @@ struct usb_ftdi { struct usb_device *udev; struct usb_interface *interface; struct usb_class_driver *class; - struct work_struct status_work; - struct work_struct command_work; - struct work_struct respond_work; + struct delayed_work status_work; + struct delayed_work command_work; + struct delayed_work respond_work; struct u132_platform_data platform_data; struct resource resources[0]; struct platform_device platform_dev; @@ -210,23 +210,14 @@ static void ftdi_elan_init_kref(struct usb_ftdi *ftdi) static void ftdi_status_requeue_work(struct usb_ftdi *ftdi, unsigned int delta) { - if (delta > 0) { - if (queue_delayed_work(status_queue, &ftdi->status_work, delta)) - return; - } else if (queue_work(status_queue, &ftdi->status_work)) - return; - kref_put(&ftdi->kref, ftdi_elan_delete); - return; + if (!queue_delayed_work(status_queue, &ftdi->status_work, delta)) + kref_put(&ftdi->kref, ftdi_elan_delete); } static void ftdi_status_queue_work(struct usb_ftdi *ftdi, unsigned int delta) { - if (delta > 0) { - if (queue_delayed_work(status_queue, &ftdi->status_work, delta)) - kref_get(&ftdi->kref); - } else if (queue_work(status_queue, &ftdi->status_work)) - kref_get(&ftdi->kref); - return; + if (queue_delayed_work(status_queue, &ftdi->status_work, delta)) + kref_get(&ftdi->kref); } static void ftdi_status_cancel_work(struct usb_ftdi *ftdi) @@ -237,25 +228,14 @@ static void ftdi_status_cancel_work(struct usb_ftdi *ftdi) static void ftdi_command_requeue_work(struct usb_ftdi *ftdi, unsigned int delta) { - if (delta > 0) { - if (queue_delayed_work(command_queue, &ftdi->command_work, - delta)) - return; - } else if (queue_work(command_queue, &ftdi->command_work)) - return; - kref_put(&ftdi->kref, ftdi_elan_delete); - return; + if (!queue_delayed_work(command_queue, &ftdi->command_work, delta)) + kref_put(&ftdi->kref, ftdi_elan_delete); } static void ftdi_command_queue_work(struct usb_ftdi *ftdi, unsigned int delta) { - if (delta > 0) { - if (queue_delayed_work(command_queue, &ftdi->command_work, - delta)) - kref_get(&ftdi->kref); - } else if (queue_work(command_queue, &ftdi->command_work)) - kref_get(&ftdi->kref); - return; + if (queue_delayed_work(command_queue, &ftdi->command_work, delta)) + kref_get(&ftdi->kref); } static void ftdi_command_cancel_work(struct usb_ftdi *ftdi) @@ -267,25 +247,14 @@ static void ftdi_command_cancel_work(struct usb_ftdi *ftdi) static void ftdi_response_requeue_work(struct usb_ftdi *ftdi, unsigned int delta) { - if (delta > 0) { - if (queue_delayed_work(respond_queue, &ftdi->respond_work, - delta)) - return; - } else if (queue_work(respond_queue, &ftdi->respond_work)) - return; - kref_put(&ftdi->kref, ftdi_elan_delete); - return; + if (!queue_delayed_work(respond_queue, &ftdi->respond_work, delta)) + kref_put(&ftdi->kref, ftdi_elan_delete); } static void ftdi_respond_queue_work(struct usb_ftdi *ftdi, unsigned int delta) { - if (delta > 0) { - if (queue_delayed_work(respond_queue, &ftdi->respond_work, - delta)) - kref_get(&ftdi->kref); - } else if (queue_work(respond_queue, &ftdi->respond_work)) - kref_get(&ftdi->kref); - return; + if (queue_delayed_work(respond_queue, &ftdi->respond_work, delta)) + kref_get(&ftdi->kref); } static void ftdi_response_cancel_work(struct usb_ftdi *ftdi) @@ -475,9 +444,11 @@ static void ftdi_elan_kick_command_queue(struct usb_ftdi *ftdi) return; } -static void ftdi_elan_command_work(void *data) +static void ftdi_elan_command_work(struct work_struct *work) { - struct usb_ftdi *ftdi = data; + struct usb_ftdi *ftdi = + container_of(work, struct usb_ftdi, command_work.work); + if (ftdi->disconnected > 0) { ftdi_elan_put_kref(ftdi); return; @@ -500,9 +471,10 @@ static void ftdi_elan_kick_respond_queue(struct usb_ftdi *ftdi) return; } -static void ftdi_elan_respond_work(void *data) +static void ftdi_elan_respond_work(struct work_struct *work) { - struct usb_ftdi *ftdi = data; + struct usb_ftdi *ftdi = + container_of(work, struct usb_ftdi, respond_work.work); if (ftdi->disconnected > 0) { ftdi_elan_put_kref(ftdi); return; @@ -534,9 +506,10 @@ static void ftdi_elan_respond_work(void *data) * after the FTDI has been synchronized * */ -static void ftdi_elan_status_work(void *data) +static void ftdi_elan_status_work(struct work_struct *work) { - struct usb_ftdi *ftdi = data; + struct usb_ftdi *ftdi = + container_of(work, struct usb_ftdi, status_work.work); int work_delay_in_msec = 0; if (ftdi->disconnected > 0) { ftdi_elan_put_kref(ftdi); @@ -2677,12 +2650,9 @@ static int ftdi_elan_probe(struct usb_interface *interface, ftdi->class = NULL; dev_info(&ftdi->udev->dev, "USB FDTI=%p ELAN interface %d now a" "ctivated\n", ftdi, iface_desc->desc.bInterfaceNumber); - INIT_WORK(&ftdi->status_work, ftdi_elan_status_work, - (void *)ftdi); - INIT_WORK(&ftdi->command_work, ftdi_elan_command_work, - (void *)ftdi); - INIT_WORK(&ftdi->respond_work, ftdi_elan_respond_work, - (void *)ftdi); + INIT_DELAYED_WORK(&ftdi->status_work, ftdi_elan_status_work); + INIT_DELAYED_WORK(&ftdi->command_work, ftdi_elan_command_work); + INIT_DELAYED_WORK(&ftdi->respond_work, ftdi_elan_respond_work); ftdi_status_queue_work(ftdi, msecs_to_jiffies(3 *1000)); return 0; } else { diff --git a/trunk/drivers/usb/misc/phidgetkit.c b/trunk/drivers/usb/misc/phidgetkit.c index 9110793f81d3..371bf2b1197d 100644 --- a/trunk/drivers/usb/misc/phidgetkit.c +++ b/trunk/drivers/usb/misc/phidgetkit.c @@ -81,8 +81,8 @@ struct interfacekit { unsigned char *data; dma_addr_t data_dma; - struct work_struct do_notify; - struct work_struct do_resubmit; + struct delayed_work do_notify; + struct delayed_work do_resubmit; unsigned long input_events; unsigned long sensor_events; }; @@ -374,19 +374,20 @@ static void interfacekit_irq(struct urb *urb) } if (kit->input_events || kit->sensor_events) - schedule_work(&kit->do_notify); + schedule_delayed_work(&kit->do_notify, 0); resubmit: - status = usb_submit_urb(urb, SLAB_ATOMIC); + status = usb_submit_urb(urb, GFP_ATOMIC); if (status) err("can't resubmit intr, %s-%s/interfacekit0, status %d", kit->udev->bus->bus_name, kit->udev->devpath, status); } -static void do_notify(void *data) +static void do_notify(struct work_struct *work) { - struct interfacekit *kit = data; + struct interfacekit *kit = + container_of(work, struct interfacekit, do_notify.work); int i; char sysfs_file[8]; @@ -405,9 +406,11 @@ static void do_notify(void *data) } } -static void do_resubmit(void *data) +static void do_resubmit(struct work_struct *work) { - set_outputs(data); + struct interfacekit *kit = + container_of(work, struct interfacekit, do_resubmit.work); + set_outputs(kit); } #define show_set_output(value) \ @@ -565,7 +568,7 @@ static int interfacekit_probe(struct usb_interface *intf, const struct usb_devic kit->dev_no = -1; kit->ifkit = ifkit; - kit->data = usb_buffer_alloc(dev, URB_INT_SIZE, SLAB_ATOMIC, &kit->data_dma); + kit->data = usb_buffer_alloc(dev, URB_INT_SIZE, GFP_ATOMIC, &kit->data_dma); if (!kit->data) goto out; @@ -575,8 +578,8 @@ static int interfacekit_probe(struct usb_interface *intf, const struct usb_devic kit->udev = usb_get_dev(dev); kit->intf = intf; - INIT_WORK(&kit->do_notify, do_notify, kit); - INIT_WORK(&kit->do_resubmit, do_resubmit, kit); + INIT_DELAYED_WORK(&kit->do_notify, do_notify); + INIT_DELAYED_WORK(&kit->do_resubmit, do_resubmit); usb_fill_int_urb(kit->irq, kit->udev, pipe, kit->data, maxp > URB_INT_SIZE ? URB_INT_SIZE : maxp, interfacekit_irq, kit, endpoint->bInterval); diff --git a/trunk/drivers/usb/misc/phidgetmotorcontrol.c b/trunk/drivers/usb/misc/phidgetmotorcontrol.c index c3469b0a67c2..5727e1ea2f91 100644 --- a/trunk/drivers/usb/misc/phidgetmotorcontrol.c +++ b/trunk/drivers/usb/misc/phidgetmotorcontrol.c @@ -41,7 +41,7 @@ struct motorcontrol { unsigned char *data; dma_addr_t data_dma; - struct work_struct do_notify; + struct delayed_work do_notify; unsigned long input_events; unsigned long speed_events; unsigned long exceed_events; @@ -148,10 +148,10 @@ static void motorcontrol_irq(struct urb *urb) set_bit(1, &mc->exceed_events); if (mc->input_events || mc->exceed_events || mc->speed_events) - schedule_work(&mc->do_notify); + schedule_delayed_work(&mc->do_notify, 0); resubmit: - status = usb_submit_urb(urb, SLAB_ATOMIC); + status = usb_submit_urb(urb, GFP_ATOMIC); if (status) dev_err(&mc->intf->dev, "can't resubmit intr, %s-%s/motorcontrol0, status %d", @@ -159,9 +159,10 @@ static void motorcontrol_irq(struct urb *urb) mc->udev->devpath, status); } -static void do_notify(void *data) +static void do_notify(struct work_struct *work) { - struct motorcontrol *mc = data; + struct motorcontrol *mc = + container_of(work, struct motorcontrol, do_notify.work); int i; char sysfs_file[8]; @@ -337,7 +338,7 @@ static int motorcontrol_probe(struct usb_interface *intf, const struct usb_devic goto out; mc->dev_no = -1; - mc->data = usb_buffer_alloc(dev, URB_INT_SIZE, SLAB_ATOMIC, &mc->data_dma); + mc->data = usb_buffer_alloc(dev, URB_INT_SIZE, GFP_ATOMIC, &mc->data_dma); if (!mc->data) goto out; @@ -348,7 +349,7 @@ static int motorcontrol_probe(struct usb_interface *intf, const struct usb_devic mc->udev = usb_get_dev(dev); mc->intf = intf; mc->acceleration[0] = mc->acceleration[1] = 10; - INIT_WORK(&mc->do_notify, do_notify, mc); + INIT_DELAYED_WORK(&mc->do_notify, do_notify); usb_fill_int_urb(mc->irq, mc->udev, pipe, mc->data, maxp > URB_INT_SIZE ? URB_INT_SIZE : maxp, motorcontrol_irq, mc, endpoint->bInterval); diff --git a/trunk/drivers/usb/misc/sisusbvga/sisusb.c b/trunk/drivers/usb/misc/sisusbvga/sisusb.c index b99ca9c79821..0398908b15d4 100644 --- a/trunk/drivers/usb/misc/sisusbvga/sisusb.c +++ b/trunk/drivers/usb/misc/sisusbvga/sisusb.c @@ -3168,7 +3168,7 @@ sisusb_compat_ioctl(struct file *f, unsigned int cmd, unsigned long arg) case SISUSB_GET_CONFIG: case SISUSB_COMMAND: lock_kernel(); - retval = sisusb_ioctl(f->f_dentry->d_inode, f, cmd, arg); + retval = sisusb_ioctl(f->f_path.dentry->d_inode, f, cmd, arg); unlock_kernel(); return retval; diff --git a/trunk/drivers/usb/misc/usbtest.c b/trunk/drivers/usb/misc/usbtest.c index 194065dbb51f..fb321864a92d 100644 --- a/trunk/drivers/usb/misc/usbtest.c +++ b/trunk/drivers/usb/misc/usbtest.c @@ -213,7 +213,7 @@ static struct urb *simple_alloc_urb ( if (bytes < 0) return NULL; - urb = usb_alloc_urb (0, SLAB_KERNEL); + urb = usb_alloc_urb (0, GFP_KERNEL); if (!urb) return urb; usb_fill_bulk_urb (urb, udev, pipe, NULL, bytes, simple_callback, NULL); @@ -223,7 +223,7 @@ static struct urb *simple_alloc_urb ( urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP; if (usb_pipein (pipe)) urb->transfer_flags |= URB_SHORT_NOT_OK; - urb->transfer_buffer = usb_buffer_alloc (udev, bytes, SLAB_KERNEL, + urb->transfer_buffer = usb_buffer_alloc (udev, bytes, GFP_KERNEL, &urb->transfer_dma); if (!urb->transfer_buffer) { usb_free_urb (urb); @@ -315,7 +315,7 @@ static int simple_io ( init_completion (&completion); if (usb_pipeout (urb->pipe)) simple_fill_buf (urb); - if ((retval = usb_submit_urb (urb, SLAB_KERNEL)) != 0) + if ((retval = usb_submit_urb (urb, GFP_KERNEL)) != 0) break; /* NOTE: no timeouts; can't be broken out of by interrupt */ @@ -374,7 +374,7 @@ alloc_sglist (int nents, int max, int vary) unsigned i; unsigned size = max; - sg = kmalloc (nents * sizeof *sg, SLAB_KERNEL); + sg = kmalloc (nents * sizeof *sg, GFP_KERNEL); if (!sg) return NULL; @@ -382,7 +382,7 @@ alloc_sglist (int nents, int max, int vary) char *buf; unsigned j; - buf = kzalloc (size, SLAB_KERNEL); + buf = kzalloc (size, GFP_KERNEL); if (!buf) { free_sglist (sg, i); return NULL; @@ -428,7 +428,7 @@ static int perform_sglist ( (udev->speed == USB_SPEED_HIGH) ? (INTERRUPT_RATE << 3) : INTERRUPT_RATE, - sg, nents, 0, SLAB_KERNEL); + sg, nents, 0, GFP_KERNEL); if (retval) break; @@ -819,7 +819,7 @@ static void ctrl_complete (struct urb *urb) /* resubmit if we need to, else mark this as done */ if ((status == 0) && (ctx->pending < ctx->count)) { - if ((status = usb_submit_urb (urb, SLAB_ATOMIC)) != 0) { + if ((status = usb_submit_urb (urb, GFP_ATOMIC)) != 0) { dbg ("can't resubmit ctrl %02x.%02x, err %d", reqp->bRequestType, reqp->bRequest, status); urb->dev = NULL; @@ -855,7 +855,7 @@ test_ctrl_queue (struct usbtest_dev *dev, struct usbtest_param *param) * as with bulk/intr sglists, sglen is the queue depth; it also * controls which subtests run (more tests than sglen) or rerun. */ - urb = kcalloc(param->sglen, sizeof(struct urb *), SLAB_KERNEL); + urb = kcalloc(param->sglen, sizeof(struct urb *), GFP_KERNEL); if (!urb) return -ENOMEM; for (i = 0; i < param->sglen; i++) { @@ -981,7 +981,7 @@ test_ctrl_queue (struct usbtest_dev *dev, struct usbtest_param *param) if (!u) goto cleanup; - reqp = usb_buffer_alloc (udev, sizeof *reqp, SLAB_KERNEL, + reqp = usb_buffer_alloc (udev, sizeof *reqp, GFP_KERNEL, &u->setup_dma); if (!reqp) goto cleanup; @@ -999,7 +999,7 @@ test_ctrl_queue (struct usbtest_dev *dev, struct usbtest_param *param) context.urb = urb; spin_lock_irq (&context.lock); for (i = 0; i < param->sglen; i++) { - context.status = usb_submit_urb (urb [i], SLAB_ATOMIC); + context.status = usb_submit_urb (urb [i], GFP_ATOMIC); if (context.status != 0) { dbg ("can't submit urb[%d], status %d", i, context.status); @@ -1041,7 +1041,7 @@ static void unlink1_callback (struct urb *urb) // we "know" -EPIPE (stall) never happens if (!status) - status = usb_submit_urb (urb, SLAB_ATOMIC); + status = usb_submit_urb (urb, GFP_ATOMIC); if (status) { urb->status = status; complete ((struct completion *) urb->context); @@ -1067,7 +1067,7 @@ static int unlink1 (struct usbtest_dev *dev, int pipe, int size, int async) * FIXME want additional tests for when endpoint is STALLing * due to errors, or is just NAKing requests. */ - if ((retval = usb_submit_urb (urb, SLAB_KERNEL)) != 0) { + if ((retval = usb_submit_urb (urb, GFP_KERNEL)) != 0) { dev_dbg (&dev->intf->dev, "submit fail %d\n", retval); return retval; } @@ -1251,7 +1251,7 @@ static int ctrl_out (struct usbtest_dev *dev, if (length < 1 || length > 0xffff || vary >= length) return -EINVAL; - buf = kmalloc(length, SLAB_KERNEL); + buf = kmalloc(length, GFP_KERNEL); if (!buf) return -ENOMEM; @@ -1403,7 +1403,7 @@ static struct urb *iso_alloc_urb ( maxp *= 1 + (0x3 & (le16_to_cpu(desc->wMaxPacketSize) >> 11)); packets = (bytes + maxp - 1) / maxp; - urb = usb_alloc_urb (packets, SLAB_KERNEL); + urb = usb_alloc_urb (packets, GFP_KERNEL); if (!urb) return urb; urb->dev = udev; @@ -1411,7 +1411,7 @@ static struct urb *iso_alloc_urb ( urb->number_of_packets = packets; urb->transfer_buffer_length = bytes; - urb->transfer_buffer = usb_buffer_alloc (udev, bytes, SLAB_KERNEL, + urb->transfer_buffer = usb_buffer_alloc (udev, bytes, GFP_KERNEL, &urb->transfer_dma); if (!urb->transfer_buffer) { usb_free_urb (urb); @@ -1481,7 +1481,7 @@ test_iso_queue (struct usbtest_dev *dev, struct usbtest_param *param, spin_lock_irq (&context.lock); for (i = 0; i < param->sglen; i++) { ++context.pending; - status = usb_submit_urb (urbs [i], SLAB_ATOMIC); + status = usb_submit_urb (urbs [i], GFP_ATOMIC); if (status < 0) { ERROR (dev, "submit iso[%d], error %d\n", i, status); if (i == 0) { @@ -1900,7 +1900,7 @@ usbtest_probe (struct usb_interface *intf, const struct usb_device_id *id) } #endif - dev = kzalloc(sizeof(*dev), SLAB_KERNEL); + dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (!dev) return -ENOMEM; info = (struct usbtest_info *) id->driver_info; @@ -1910,7 +1910,7 @@ usbtest_probe (struct usb_interface *intf, const struct usb_device_id *id) dev->intf = intf; /* cacheline-aligned scratch for i/o */ - if ((dev->buf = kmalloc (TBUF_SIZE, SLAB_KERNEL)) == NULL) { + if ((dev->buf = kmalloc (TBUF_SIZE, GFP_KERNEL)) == NULL) { kfree (dev); return -ENOMEM; } diff --git a/trunk/drivers/usb/mon/mon_text.c b/trunk/drivers/usb/mon/mon_text.c index 7a2346c53284..05cf2c9a8f84 100644 --- a/trunk/drivers/usb/mon/mon_text.c +++ b/trunk/drivers/usb/mon/mon_text.c @@ -50,7 +50,7 @@ struct mon_event_text { #define SLAB_NAME_SZ 30 struct mon_reader_text { - kmem_cache_t *e_slab; + struct kmem_cache *e_slab; int nevents; struct list_head e_list; struct mon_reader r; /* In C, parent class can be placed anywhere */ @@ -63,7 +63,7 @@ struct mon_reader_text { char slab_name[SLAB_NAME_SZ]; }; -static void mon_text_ctor(void *, kmem_cache_t *, unsigned long); +static void mon_text_ctor(void *, struct kmem_cache *, unsigned long); /* * mon_text_submit @@ -147,7 +147,7 @@ static void mon_text_event(struct mon_reader_text *rp, struct urb *urb, stamp = mon_get_timestamp(); if (rp->nevents >= EVENT_MAX || - (ep = kmem_cache_alloc(rp->e_slab, SLAB_ATOMIC)) == NULL) { + (ep = kmem_cache_alloc(rp->e_slab, GFP_ATOMIC)) == NULL) { rp->r.m_bus->cnt_text_lost++; return; } @@ -188,7 +188,7 @@ static void mon_text_error(void *data, struct urb *urb, int error) struct mon_event_text *ep; if (rp->nevents >= EVENT_MAX || - (ep = kmem_cache_alloc(rp->e_slab, SLAB_ATOMIC)) == NULL) { + (ep = kmem_cache_alloc(rp->e_slab, GFP_ATOMIC)) == NULL) { rp->r.m_bus->cnt_text_lost++; return; } @@ -450,7 +450,7 @@ const struct file_operations mon_fops_text = { /* * Slab interface: constructor. */ -static void mon_text_ctor(void *mem, kmem_cache_t *slab, unsigned long sflags) +static void mon_text_ctor(void *mem, struct kmem_cache *slab, unsigned long sflags) { /* * Nothing to initialize. No, really! diff --git a/trunk/drivers/usb/net/catc.c b/trunk/drivers/usb/net/catc.c index 907b820a5faf..4852012735f6 100644 --- a/trunk/drivers/usb/net/catc.c +++ b/trunk/drivers/usb/net/catc.c @@ -345,7 +345,7 @@ static void catc_irq_done(struct urb *urb) } } resubmit: - status = usb_submit_urb (urb, SLAB_ATOMIC); + status = usb_submit_urb (urb, GFP_ATOMIC); if (status) err ("can't resubmit intr, %s-%s, status %d", catc->usbdev->bus->bus_name, diff --git a/trunk/drivers/usb/net/kaweth.c b/trunk/drivers/usb/net/kaweth.c index 7c906a43e497..fa78326d0bf0 100644 --- a/trunk/drivers/usb/net/kaweth.c +++ b/trunk/drivers/usb/net/kaweth.c @@ -222,7 +222,7 @@ struct kaweth_device int suspend_lowmem_ctrl; int linkstate; int opened; - struct work_struct lowmem_work; + struct delayed_work lowmem_work; struct usb_device *dev; struct net_device *net; @@ -530,9 +530,10 @@ static void int_callback(struct urb *u) kaweth_resubmit_int_urb(kaweth, GFP_ATOMIC); } -static void kaweth_resubmit_tl(void *d) +static void kaweth_resubmit_tl(struct work_struct *work) { - struct kaweth_device *kaweth = (struct kaweth_device *)d; + struct kaweth_device *kaweth = + container_of(work, struct kaweth_device, lowmem_work.work); if (IS_BLOCKED(kaweth->status)) return; @@ -1126,7 +1127,7 @@ static int kaweth_probe( /* kaweth is zeroed as part of alloc_netdev */ - INIT_WORK(&kaweth->lowmem_work, kaweth_resubmit_tl, (void *)kaweth); + INIT_DELAYED_WORK(&kaweth->lowmem_work, kaweth_resubmit_tl); SET_MODULE_OWNER(netdev); diff --git a/trunk/drivers/usb/net/net1080.c b/trunk/drivers/usb/net/net1080.c index a77410562e12..493635954513 100644 --- a/trunk/drivers/usb/net/net1080.c +++ b/trunk/drivers/usb/net/net1080.c @@ -383,7 +383,7 @@ static void nc_ensure_sync(struct usbnet *dev) int status; /* Send a flush */ - urb = usb_alloc_urb(0, SLAB_ATOMIC); + urb = usb_alloc_urb(0, GFP_ATOMIC); if (!urb) return; diff --git a/trunk/drivers/usb/net/pegasus.c b/trunk/drivers/usb/net/pegasus.c index 69eb0db399df..d48c024cff59 100644 --- a/trunk/drivers/usb/net/pegasus.c +++ b/trunk/drivers/usb/net/pegasus.c @@ -856,7 +856,7 @@ static void intr_callback(struct urb *urb) pegasus->stats.rx_missed_errors += ((d[3] & 0x7f) << 8) | d[4]; } - status = usb_submit_urb(urb, SLAB_ATOMIC); + status = usb_submit_urb(urb, GFP_ATOMIC); if (status == -ENODEV) netif_device_detach(pegasus->net); if (status && netif_msg_timer(pegasus)) @@ -1281,9 +1281,9 @@ static inline void setup_pegasus_II(pegasus_t * pegasus) static struct workqueue_struct *pegasus_workqueue = NULL; #define CARRIER_CHECK_DELAY (2 * HZ) -static void check_carrier(void *data) +static void check_carrier(struct work_struct *work) { - pegasus_t *pegasus = data; + pegasus_t *pegasus = container_of(work, pegasus_t, carrier_check.work); set_carrier(pegasus->net); if (!(pegasus->flags & PEGASUS_UNPLUG)) { queue_delayed_work(pegasus_workqueue, &pegasus->carrier_check, @@ -1319,7 +1319,7 @@ static int pegasus_probe(struct usb_interface *intf, tasklet_init(&pegasus->rx_tl, rx_fixup, (unsigned long) pegasus); - INIT_WORK(&pegasus->carrier_check, check_carrier, pegasus); + INIT_DELAYED_WORK(&pegasus->carrier_check, check_carrier); pegasus->intf = intf; pegasus->usb = dev; diff --git a/trunk/drivers/usb/net/pegasus.h b/trunk/drivers/usb/net/pegasus.h index 006438069b66..98f6898cae1f 100644 --- a/trunk/drivers/usb/net/pegasus.h +++ b/trunk/drivers/usb/net/pegasus.h @@ -95,7 +95,7 @@ typedef struct pegasus { int dev_index; int intr_interval; struct tasklet_struct rx_tl; - struct work_struct carrier_check; + struct delayed_work carrier_check; struct urb *ctrl_urb, *rx_urb, *tx_urb, *intr_urb; struct sk_buff *rx_pool[RX_SKBS]; struct sk_buff *rx_skb; diff --git a/trunk/drivers/usb/net/rndis_host.c b/trunk/drivers/usb/net/rndis_host.c index c2a28d88ef3c..99f26b3e502f 100644 --- a/trunk/drivers/usb/net/rndis_host.c +++ b/trunk/drivers/usb/net/rndis_host.c @@ -469,7 +469,7 @@ static void rndis_unbind(struct usbnet *dev, struct usb_interface *intf) struct rndis_halt *halt; /* try to clear any rndis state/activity (no i/o from stack!) */ - halt = kcalloc(1, sizeof *halt, SLAB_KERNEL); + halt = kcalloc(1, sizeof *halt, GFP_KERNEL); if (halt) { halt->msg_type = RNDIS_MSG_HALT; halt->msg_len = ccpu2(sizeof *halt); diff --git a/trunk/drivers/usb/net/rtl8150.c b/trunk/drivers/usb/net/rtl8150.c index 72171f94ded4..c54235f73cb6 100644 --- a/trunk/drivers/usb/net/rtl8150.c +++ b/trunk/drivers/usb/net/rtl8150.c @@ -587,7 +587,7 @@ static void intr_callback(struct urb *urb) } resubmit: - status = usb_submit_urb (urb, SLAB_ATOMIC); + status = usb_submit_urb (urb, GFP_ATOMIC); if (status == -ENODEV) netif_device_detach(dev->netdev); else if (status) diff --git a/trunk/drivers/usb/net/usbnet.c b/trunk/drivers/usb/net/usbnet.c index 7672e11c94c4..6e39e9988259 100644 --- a/trunk/drivers/usb/net/usbnet.c +++ b/trunk/drivers/usb/net/usbnet.c @@ -179,9 +179,9 @@ static int init_status (struct usbnet *dev, struct usb_interface *intf) period = max ((int) dev->status->desc.bInterval, (dev->udev->speed == USB_SPEED_HIGH) ? 7 : 3); - buf = kmalloc (maxp, SLAB_KERNEL); + buf = kmalloc (maxp, GFP_KERNEL); if (buf) { - dev->interrupt = usb_alloc_urb (0, SLAB_KERNEL); + dev->interrupt = usb_alloc_urb (0, GFP_KERNEL); if (!dev->interrupt) { kfree (buf); return -ENOMEM; @@ -782,9 +782,10 @@ static struct ethtool_ops usbnet_ethtool_ops = { * especially now that control transfers can be queued. */ static void -kevent (void *data) +kevent (struct work_struct *work) { - struct usbnet *dev = data; + struct usbnet *dev = + container_of(work, struct usbnet, kevent); int status; /* usb_clear_halt() needs a thread context */ @@ -1146,7 +1147,7 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod) skb_queue_head_init (&dev->done); dev->bh.func = usbnet_bh; dev->bh.data = (unsigned long) dev; - INIT_WORK (&dev->kevent, kevent, dev); + INIT_WORK (&dev->kevent, kevent); dev->delay.function = usbnet_bh; dev->delay.data = (unsigned long) dev; init_timer (&dev->delay); diff --git a/trunk/drivers/usb/serial/aircable.c b/trunk/drivers/usb/serial/aircable.c index b1b5707bc99a..86bcf63b6ba5 100644 --- a/trunk/drivers/usb/serial/aircable.c +++ b/trunk/drivers/usb/serial/aircable.c @@ -92,6 +92,7 @@ struct aircable_private { struct circ_buf *rx_buf; /* read buffer */ int rx_flags; /* for throttilng */ struct work_struct rx_work; /* work cue for the receiving line */ + struct usb_serial_port *port; /* USB port with which associated */ }; /* Private methods */ @@ -251,10 +252,11 @@ static void aircable_send(struct usb_serial_port *port) schedule_work(&port->work); } -static void aircable_read(void *params) +static void aircable_read(struct work_struct *work) { - struct usb_serial_port *port = params; - struct aircable_private *priv = usb_get_serial_port_data(port); + struct aircable_private *priv = + container_of(work, struct aircable_private, rx_work); + struct usb_serial_port *port = priv->port; struct tty_struct *tty; unsigned char *data; int count; @@ -349,7 +351,8 @@ static int aircable_attach (struct usb_serial *serial) } priv->rx_flags &= ~(THROTTLED | ACTUALLY_THROTTLED); - INIT_WORK(&priv->rx_work, aircable_read, port); + priv->port = port; + INIT_WORK(&priv->rx_work, aircable_read); usb_set_serial_port_data(serial->port[0], priv); @@ -516,7 +519,7 @@ static void aircable_read_bulk_callback(struct urb *urb) package_length - shift); } } - aircable_read(port); + aircable_read(&priv->rx_work); } /* Schedule the next read _if_ we are still open */ diff --git a/trunk/drivers/usb/serial/ark3116.c b/trunk/drivers/usb/serial/ark3116.c index 863966c1c5ac..5261cd22ee6b 100644 --- a/trunk/drivers/usb/serial/ark3116.c +++ b/trunk/drivers/usb/serial/ark3116.c @@ -156,7 +156,7 @@ static int ark3116_attach(struct usb_serial *serial) } static void ark3116_set_termios(struct usb_serial_port *port, - struct termios *old_termios) + struct ktermios *old_termios) { struct usb_serial *serial = port->serial; struct ark3116_private *priv = usb_get_serial_port_data(port); @@ -326,7 +326,7 @@ static void ark3116_set_termios(struct usb_serial_port *port, static int ark3116_open(struct usb_serial_port *port, struct file *filp) { - struct termios tmp_termios; + struct ktermios tmp_termios; struct usb_serial *serial = port->serial; char *buf; int result = 0; diff --git a/trunk/drivers/usb/serial/belkin_sa.c b/trunk/drivers/usb/serial/belkin_sa.c index 8835bb58ca9b..38b4dae319ee 100644 --- a/trunk/drivers/usb/serial/belkin_sa.c +++ b/trunk/drivers/usb/serial/belkin_sa.c @@ -92,7 +92,7 @@ static void belkin_sa_shutdown (struct usb_serial *serial); static int belkin_sa_open (struct usb_serial_port *port, struct file *filp); static void belkin_sa_close (struct usb_serial_port *port, struct file *filp); static void belkin_sa_read_int_callback (struct urb *urb); -static void belkin_sa_set_termios (struct usb_serial_port *port, struct termios * old); +static void belkin_sa_set_termios (struct usb_serial_port *port, struct ktermios * old); static int belkin_sa_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg); static void belkin_sa_break_ctl (struct usb_serial_port *port, int break_state ); static int belkin_sa_tiocmget (struct usb_serial_port *port, struct file *file); @@ -333,7 +333,7 @@ static void belkin_sa_read_int_callback (struct urb *urb) __FUNCTION__, retval); } -static void belkin_sa_set_termios (struct usb_serial_port *port, struct termios *old_termios) +static void belkin_sa_set_termios (struct usb_serial_port *port, struct ktermios *old_termios) { struct usb_serial *serial = port->serial; struct belkin_sa_private *priv = usb_get_serial_port_data(port); diff --git a/trunk/drivers/usb/serial/console.c b/trunk/drivers/usb/serial/console.c index 7167728d764c..9386e216d681 100644 --- a/trunk/drivers/usb/serial/console.c +++ b/trunk/drivers/usb/serial/console.c @@ -65,7 +65,7 @@ static int usb_console_setup(struct console *co, char *options) struct usb_serial_port *port; int retval = 0; struct tty_struct *tty; - struct termios *termios; + struct ktermios *termios; dbg ("%s", __FUNCTION__); diff --git a/trunk/drivers/usb/serial/cp2101.c b/trunk/drivers/usb/serial/cp2101.c index f95d42c0d16a..2f9b7ac32663 100644 --- a/trunk/drivers/usb/serial/cp2101.c +++ b/trunk/drivers/usb/serial/cp2101.c @@ -41,7 +41,7 @@ static int cp2101_open(struct usb_serial_port*, struct file*); static void cp2101_cleanup(struct usb_serial_port*); static void cp2101_close(struct usb_serial_port*, struct file*); static void cp2101_get_termios(struct usb_serial_port*); -static void cp2101_set_termios(struct usb_serial_port*, struct termios*); +static void cp2101_set_termios(struct usb_serial_port*, struct ktermios*); static int cp2101_tiocmget (struct usb_serial_port *, struct file *); static int cp2101_tiocmset (struct usb_serial_port *, struct file *, unsigned int, unsigned int); @@ -506,7 +506,7 @@ static void cp2101_get_termios (struct usb_serial_port *port) } static void cp2101_set_termios (struct usb_serial_port *port, - struct termios *old_termios) + struct ktermios *old_termios) { unsigned int cflag, old_cflag=0; int baud=0, bits; diff --git a/trunk/drivers/usb/serial/cypress_m8.c b/trunk/drivers/usb/serial/cypress_m8.c index 093f303b3189..a1fdb85b8c0a 100644 --- a/trunk/drivers/usb/serial/cypress_m8.c +++ b/trunk/drivers/usb/serial/cypress_m8.c @@ -143,7 +143,7 @@ struct cypress_private { wait_queue_head_t delta_msr_wait; /* used for TIOCMIWAIT */ char prev_status, diff_status; /* used for TIOCMIWAIT */ /* we pass a pointer to this as the arguement sent to cypress_set_termios old_termios */ - struct termios tmp_termios; /* stores the old termios settings */ + struct ktermios tmp_termios; /* stores the old termios settings */ }; /* write buffer structure */ @@ -165,7 +165,7 @@ static int cypress_write (struct usb_serial_port *port, const unsigned char *b static void cypress_send (struct usb_serial_port *port); static int cypress_write_room (struct usb_serial_port *port); static int cypress_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg); -static void cypress_set_termios (struct usb_serial_port *port, struct termios * old); +static void cypress_set_termios (struct usb_serial_port *port, struct ktermios * old); static int cypress_tiocmget (struct usb_serial_port *port, struct file *file); static int cypress_tiocmset (struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear); static int cypress_chars_in_buffer (struct usb_serial_port *port); @@ -949,13 +949,13 @@ static int cypress_ioctl (struct usb_serial_port *port, struct file * file, unsi switch (cmd) { case TIOCGSERIAL: - if (copy_to_user((void __user *)arg, port->tty->termios, sizeof(struct termios))) { + if (copy_to_user((void __user *)arg, port->tty->termios, sizeof(struct ktermios))) { return -EFAULT; } return (0); break; case TIOCSSERIAL: - if (copy_from_user(port->tty->termios, (void __user *)arg, sizeof(struct termios))) { + if (copy_from_user(port->tty->termios, (void __user *)arg, sizeof(struct ktermios))) { return -EFAULT; } /* here we need to call cypress_set_termios to invoke the new settings */ @@ -1019,7 +1019,7 @@ static int cypress_ioctl (struct usb_serial_port *port, struct file * file, unsi static void cypress_set_termios (struct usb_serial_port *port, - struct termios *old_termios) + struct ktermios *old_termios) { struct cypress_private *priv = usb_get_serial_port_data(port); struct tty_struct *tty; diff --git a/trunk/drivers/usb/serial/digi_acceleport.c b/trunk/drivers/usb/serial/digi_acceleport.c index 5e3ac281a2f8..9d9ea874639c 100644 --- a/trunk/drivers/usb/serial/digi_acceleport.c +++ b/trunk/drivers/usb/serial/digi_acceleport.c @@ -430,13 +430,14 @@ struct digi_port { int dp_in_close; /* close in progress */ wait_queue_head_t dp_close_wait; /* wait queue for close */ struct work_struct dp_wakeup_work; + struct usb_serial_port *dp_port; }; /* Local Function Declarations */ static void digi_wakeup_write( struct usb_serial_port *port ); -static void digi_wakeup_write_lock(void *); +static void digi_wakeup_write_lock(struct work_struct *work); static int digi_write_oob_command( struct usb_serial_port *port, unsigned char *buf, int count, int interruptible ); static int digi_write_inb_command( struct usb_serial_port *port, @@ -448,7 +449,7 @@ static int digi_transmit_idle( struct usb_serial_port *port, static void digi_rx_throttle (struct usb_serial_port *port); static void digi_rx_unthrottle (struct usb_serial_port *port); static void digi_set_termios( struct usb_serial_port *port, - struct termios *old_termios ); + struct ktermios *old_termios ); static void digi_break_ctl( struct usb_serial_port *port, int break_state ); static int digi_ioctl( struct usb_serial_port *port, struct file *file, unsigned int cmd, unsigned long arg ); @@ -598,11 +599,12 @@ static inline long cond_wait_interruptible_timeout_irqrestore( * on writes. */ -static void digi_wakeup_write_lock(void *arg) +static void digi_wakeup_write_lock(struct work_struct *work) { - struct usb_serial_port *port = arg; + struct digi_port *priv = + container_of(work, struct digi_port, dp_wakeup_work); + struct usb_serial_port *port = priv->dp_port; unsigned long flags; - struct digi_port *priv = usb_get_serial_port_data(port); spin_lock_irqsave( &priv->dp_port_lock, flags ); @@ -974,7 +976,7 @@ dbg( "digi_rx_unthrottle: TOP: port=%d", priv->dp_port_num ); static void digi_set_termios( struct usb_serial_port *port, - struct termios *old_termios ) + struct ktermios *old_termios ) { struct digi_port *priv = usb_get_serial_port_data(port); @@ -1461,7 +1463,7 @@ static int digi_open( struct usb_serial_port *port, struct file *filp ) int ret; unsigned char buf[32]; struct digi_port *priv = usb_get_serial_port_data(port); - struct termios not_termios; + struct ktermios not_termios; unsigned long flags = 0; @@ -1702,8 +1704,8 @@ dbg( "digi_startup: TOP" ); init_waitqueue_head( &priv->dp_flush_wait ); priv->dp_in_close = 0; init_waitqueue_head( &priv->dp_close_wait ); - INIT_WORK(&priv->dp_wakeup_work, - digi_wakeup_write_lock, serial->port[i]); + INIT_WORK(&priv->dp_wakeup_work, digi_wakeup_write_lock); + priv->dp_port = serial->port[i]; /* initialize write wait queue for this port */ init_waitqueue_head( &serial->port[i]->write_wait ); diff --git a/trunk/drivers/usb/serial/empeg.c b/trunk/drivers/usb/serial/empeg.c index 4ce10a831953..92beeb19795f 100644 --- a/trunk/drivers/usb/serial/empeg.c +++ b/trunk/drivers/usb/serial/empeg.c @@ -92,7 +92,7 @@ static int empeg_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg); -static void empeg_set_termios (struct usb_serial_port *port, struct termios *old_termios); +static void empeg_set_termios (struct usb_serial_port *port, struct ktermios *old_termios); static void empeg_write_bulk_callback (struct urb *urb); static void empeg_read_bulk_callback (struct urb *urb); @@ -442,7 +442,7 @@ static int empeg_ioctl (struct usb_serial_port *port, struct file * file, unsign } -static void empeg_set_termios (struct usb_serial_port *port, struct termios *old_termios) +static void empeg_set_termios (struct usb_serial_port *port, struct ktermios *old_termios) { dbg("%s - port %d", __FUNCTION__, port->number); diff --git a/trunk/drivers/usb/serial/ftdi_sio.c b/trunk/drivers/usb/serial/ftdi_sio.c index 89ce2775be15..41b0ad2d56ac 100644 --- a/trunk/drivers/usb/serial/ftdi_sio.c +++ b/trunk/drivers/usb/serial/ftdi_sio.c @@ -559,7 +559,8 @@ struct ftdi_private { char prev_status, diff_status; /* Used for TIOCMIWAIT */ __u8 rx_flags; /* receive state flags (throttling) */ spinlock_t rx_lock; /* spinlock for receive state */ - struct work_struct rx_work; + struct delayed_work rx_work; + struct usb_serial_port *port; int rx_processed; unsigned long rx_bytes; @@ -593,8 +594,8 @@ static int ftdi_write_room (struct usb_serial_port *port); static int ftdi_chars_in_buffer (struct usb_serial_port *port); static void ftdi_write_bulk_callback (struct urb *urb); static void ftdi_read_bulk_callback (struct urb *urb); -static void ftdi_process_read (void *param); -static void ftdi_set_termios (struct usb_serial_port *port, struct termios * old); +static void ftdi_process_read (struct work_struct *work); +static void ftdi_set_termios (struct usb_serial_port *port, struct ktermios * old); static int ftdi_tiocmget (struct usb_serial_port *port, struct file *file); static int ftdi_tiocmset (struct usb_serial_port *port, struct file * file, unsigned int set, unsigned int clear); static int ftdi_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg); @@ -1201,7 +1202,8 @@ static int ftdi_sio_attach (struct usb_serial *serial) port->read_urb->transfer_buffer_length = BUFSZ; } - INIT_WORK(&priv->rx_work, ftdi_process_read, port); + INIT_DELAYED_WORK(&priv->rx_work, ftdi_process_read); + priv->port = port; /* Free port's existing write urb and transfer buffer. */ if (port->write_urb) { @@ -1640,17 +1642,18 @@ static void ftdi_read_bulk_callback (struct urb *urb) priv->rx_bytes += countread; spin_unlock_irqrestore(&priv->rx_lock, flags); - ftdi_process_read(port); + ftdi_process_read(&priv->rx_work.work); } /* ftdi_read_bulk_callback */ -static void ftdi_process_read (void *param) +static void ftdi_process_read (struct work_struct *work) { /* ftdi_process_read */ - struct usb_serial_port *port = (struct usb_serial_port*)param; + struct ftdi_private *priv = + container_of(work, struct ftdi_private, rx_work.work); + struct usb_serial_port *port = priv->port; struct urb *urb; struct tty_struct *tty; - struct ftdi_private *priv; char error_flag; unsigned char *data; @@ -1877,7 +1880,7 @@ static void ftdi_break_ctl( struct usb_serial_port *port, int break_state ) * WARNING: set_termios calls this with old_termios in kernel space */ -static void ftdi_set_termios (struct usb_serial_port *port, struct termios *old_termios) +static void ftdi_set_termios (struct usb_serial_port *port, struct ktermios *old_termios) { /* ftdi_termios */ struct usb_device *dev = port->serial->dev; unsigned int cflag = port->tty->termios->c_cflag; @@ -2179,7 +2182,7 @@ static void ftdi_unthrottle (struct usb_serial_port *port) spin_unlock_irqrestore(&priv->rx_lock, flags); if (actually_throttled) - schedule_work(&priv->rx_work); + schedule_delayed_work(&priv->rx_work, 0); } static int __init ftdi_init (void) diff --git a/trunk/drivers/usb/serial/io_edgeport.c b/trunk/drivers/usb/serial/io_edgeport.c index d06547a13f28..f623d58370a4 100644 --- a/trunk/drivers/usb/serial/io_edgeport.c +++ b/trunk/drivers/usb/serial/io_edgeport.c @@ -229,7 +229,7 @@ static int edge_write_room (struct usb_serial_port *port); static int edge_chars_in_buffer (struct usb_serial_port *port); static void edge_throttle (struct usb_serial_port *port); static void edge_unthrottle (struct usb_serial_port *port); -static void edge_set_termios (struct usb_serial_port *port, struct termios *old_termios); +static void edge_set_termios (struct usb_serial_port *port, struct ktermios *old_termios); static int edge_ioctl (struct usb_serial_port *port, struct file *file, unsigned int cmd, unsigned long arg); static void edge_break (struct usb_serial_port *port, int break_state); static int edge_tiocmget (struct usb_serial_port *port, struct file *file); @@ -257,7 +257,7 @@ static void handle_new_lsr (struct edgeport_port *edge_port, __u8 lsrData, __u8 static int send_iosp_ext_cmd (struct edgeport_port *edge_port, __u8 command, __u8 param); static int calc_baud_rate_divisor (int baud_rate, int *divisor); static int send_cmd_write_baud_rate (struct edgeport_port *edge_port, int baudRate); -static void change_port_settings (struct edgeport_port *edge_port, struct termios *old_termios); +static void change_port_settings (struct edgeport_port *edge_port, struct ktermios *old_termios); static int send_cmd_write_uart_register (struct edgeport_port *edge_port, __u8 regNum, __u8 regValue); static int write_cmd_usb (struct edgeport_port *edge_port, unsigned char *buffer, int writeLength); static void send_more_port_data (struct edgeport_serial *edge_serial, struct edgeport_port *edge_port); @@ -1431,7 +1431,7 @@ static void edge_unthrottle (struct usb_serial_port *port) * SerialSetTermios * this function is called by the tty driver when it wants to change the termios structure *****************************************************************************/ -static void edge_set_termios (struct usb_serial_port *port, struct termios *old_termios) +static void edge_set_termios (struct usb_serial_port *port, struct ktermios *old_termios) { struct edgeport_port *edge_port = usb_get_serial_port_data(port); struct tty_struct *tty = port->tty; @@ -2412,7 +2412,7 @@ static int send_cmd_write_uart_register (struct edgeport_port *edge_port, __u8 r #ifndef CMSPAR #define CMSPAR 0 #endif -static void change_port_settings (struct edgeport_port *edge_port, struct termios *old_termios) +static void change_port_settings (struct edgeport_port *edge_port, struct ktermios *old_termios) { struct tty_struct *tty; int baud; diff --git a/trunk/drivers/usb/serial/io_ti.c b/trunk/drivers/usb/serial/io_ti.c index ee0c921e1520..2da2684e0809 100644 --- a/trunk/drivers/usb/serial/io_ti.c +++ b/trunk/drivers/usb/serial/io_ti.c @@ -238,7 +238,7 @@ static void edge_tty_recv(struct device *dev, struct tty_struct *tty, unsigned c static void stop_read(struct edgeport_port *edge_port); static int restart_read(struct edgeport_port *edge_port); -static void edge_set_termios (struct usb_serial_port *port, struct termios *old_termios); +static void edge_set_termios (struct usb_serial_port *port, struct ktermios *old_termios); static void edge_send(struct usb_serial_port *port); /* circular buffer */ @@ -2361,7 +2361,7 @@ static int restart_read(struct edgeport_port *edge_port) return status; } -static void change_port_settings (struct edgeport_port *edge_port, struct termios *old_termios) +static void change_port_settings (struct edgeport_port *edge_port, struct ktermios *old_termios) { struct ump_uart_config *config; struct tty_struct *tty; @@ -2512,7 +2512,7 @@ static void change_port_settings (struct edgeport_port *edge_port, struct termio return; } -static void edge_set_termios (struct usb_serial_port *port, struct termios *old_termios) +static void edge_set_termios (struct usb_serial_port *port, struct ktermios *old_termios) { struct edgeport_port *edge_port = usb_get_serial_port_data(port); struct tty_struct *tty = port->tty; diff --git a/trunk/drivers/usb/serial/ir-usb.c b/trunk/drivers/usb/serial/ir-usb.c index 331bf81556fc..8fdf486e3465 100644 --- a/trunk/drivers/usb/serial/ir-usb.c +++ b/trunk/drivers/usb/serial/ir-usb.c @@ -107,7 +107,7 @@ static void ir_close (struct usb_serial_port *port, struct file *filep); static int ir_write (struct usb_serial_port *port, const unsigned char *buf, int count); static void ir_write_bulk_callback (struct urb *urb); static void ir_read_bulk_callback (struct urb *urb); -static void ir_set_termios (struct usb_serial_port *port, struct termios *old_termios); +static void ir_set_termios (struct usb_serial_port *port, struct ktermios *old_termios); static u8 ir_baud = 0; static u8 ir_xbof = 0; @@ -497,7 +497,7 @@ static void ir_read_bulk_callback (struct urb *urb) return; } -static void ir_set_termios (struct usb_serial_port *port, struct termios *old_termios) +static void ir_set_termios (struct usb_serial_port *port, struct ktermios *old_termios) { unsigned char *transfer_buffer; unsigned int cflag; diff --git a/trunk/drivers/usb/serial/keyspan.c b/trunk/drivers/usb/serial/keyspan.c index 7639652cec42..9d2fdfd6865f 100644 --- a/trunk/drivers/usb/serial/keyspan.c +++ b/trunk/drivers/usb/serial/keyspan.c @@ -264,7 +264,7 @@ static void keyspan_break_ctl (struct usb_serial_port *port, int break_state) static void keyspan_set_termios (struct usb_serial_port *port, - struct termios *old_termios) + struct ktermios *old_termios) { int baud_rate, device_port; struct keyspan_port_private *p_priv; diff --git a/trunk/drivers/usb/serial/keyspan.h b/trunk/drivers/usb/serial/keyspan.h index 7472ed6bf626..6413d73c139c 100644 --- a/trunk/drivers/usb/serial/keyspan.h +++ b/trunk/drivers/usb/serial/keyspan.h @@ -59,7 +59,7 @@ static int keyspan_ioctl (struct usb_serial_port *port, unsigned int cmd, unsigned long arg); static void keyspan_set_termios (struct usb_serial_port *port, - struct termios *old); + struct ktermios *old); static void keyspan_break_ctl (struct usb_serial_port *port, int break_state); static int keyspan_tiocmget (struct usb_serial_port *port, diff --git a/trunk/drivers/usb/serial/keyspan_pda.c b/trunk/drivers/usb/serial/keyspan_pda.c index 909005107ea2..126b9703bbaf 100644 --- a/trunk/drivers/usb/serial/keyspan_pda.c +++ b/trunk/drivers/usb/serial/keyspan_pda.c @@ -120,6 +120,8 @@ struct keyspan_pda_private { int tx_throttled; struct work_struct wakeup_work; struct work_struct unthrottle_work; + struct usb_serial *serial; + struct usb_serial_port *port; }; @@ -175,9 +177,11 @@ static struct usb_device_id id_table_fake_xircom [] = { }; #endif -static void keyspan_pda_wakeup_write( struct usb_serial_port *port ) +static void keyspan_pda_wakeup_write(struct work_struct *work) { - + struct keyspan_pda_private *priv = + container_of(work, struct keyspan_pda_private, wakeup_work); + struct usb_serial_port *port = priv->port; struct tty_struct *tty = port->tty; /* wake up port processes */ @@ -187,8 +191,11 @@ static void keyspan_pda_wakeup_write( struct usb_serial_port *port ) tty_wakeup(tty); } -static void keyspan_pda_request_unthrottle( struct usb_serial *serial ) +static void keyspan_pda_request_unthrottle(struct work_struct *work) { + struct keyspan_pda_private *priv = + container_of(work, struct keyspan_pda_private, unthrottle_work); + struct usb_serial *serial = priv->serial; int result; dbg(" request_unthrottle"); @@ -358,7 +365,7 @@ static void keyspan_pda_break_ctl (struct usb_serial_port *port, int break_state static void keyspan_pda_set_termios (struct usb_serial_port *port, - struct termios *old_termios) + struct ktermios *old_termios) { struct usb_serial *serial = port->serial; unsigned int cflag = port->tty->termios->c_cflag; @@ -765,11 +772,10 @@ static int keyspan_pda_startup (struct usb_serial *serial) return (1); /* error */ usb_set_serial_port_data(serial->port[0], priv); init_waitqueue_head(&serial->port[0]->write_wait); - INIT_WORK(&priv->wakeup_work, (void *)keyspan_pda_wakeup_write, - (void *)(serial->port[0])); - INIT_WORK(&priv->unthrottle_work, - (void *)keyspan_pda_request_unthrottle, - (void *)(serial)); + INIT_WORK(&priv->wakeup_work, keyspan_pda_wakeup_write); + INIT_WORK(&priv->unthrottle_work, keyspan_pda_request_unthrottle); + priv->serial = serial; + priv->port = serial->port[0]; return (0); } diff --git a/trunk/drivers/usb/serial/kl5kusb105.c b/trunk/drivers/usb/serial/kl5kusb105.c index 17e205699c2b..73d755df4840 100644 --- a/trunk/drivers/usb/serial/kl5kusb105.c +++ b/trunk/drivers/usb/serial/kl5kusb105.c @@ -86,7 +86,7 @@ static int klsi_105_write_room (struct usb_serial_port *port); static void klsi_105_read_bulk_callback (struct urb *urb); static void klsi_105_set_termios (struct usb_serial_port *port, - struct termios * old); + struct ktermios *old); static int klsi_105_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, @@ -164,7 +164,7 @@ struct klsi_105_port_settings { #define URB_TRANSFER_BUFFER_SIZE 64 struct klsi_105_private { struct klsi_105_port_settings cfg; - struct termios termios; + struct ktermios termios; unsigned long line_state; /* modem line settings */ /* write pool */ struct urb * write_urb_pool[NUM_URBS]; @@ -688,7 +688,7 @@ static void klsi_105_read_bulk_callback (struct urb *urb) static void klsi_105_set_termios (struct usb_serial_port *port, - struct termios *old_termios) + struct ktermios *old_termios) { struct klsi_105_private *priv = usb_get_serial_port_data(port); unsigned int iflag = port->tty->termios->c_iflag; diff --git a/trunk/drivers/usb/serial/kobil_sct.c b/trunk/drivers/usb/serial/kobil_sct.c index 237289920f03..e284d6c0fd35 100644 --- a/trunk/drivers/usb/serial/kobil_sct.c +++ b/trunk/drivers/usb/serial/kobil_sct.c @@ -136,7 +136,7 @@ struct kobil_private { int cur_pos; // index of the next char to send in buf __u16 device_type; int line_state; - struct termios internal_termios; + struct ktermios internal_termios; }; @@ -624,11 +624,11 @@ static int kobil_ioctl(struct usb_serial_port *port, struct file *file, switch (cmd) { case TCGETS: // 0x5401 - if (!access_ok(VERIFY_WRITE, user_arg, sizeof(struct termios))) { + if (!access_ok(VERIFY_WRITE, user_arg, sizeof(struct ktermios))) { dbg("%s - port %d Error in access_ok", __FUNCTION__, port->number); return -EFAULT; } - if (kernel_termios_to_user_termios((struct termios __user *)arg, + if (kernel_termios_to_user_termios((struct ktermios __user *)arg, &priv->internal_termios)) return -EFAULT; return 0; @@ -638,12 +638,12 @@ static int kobil_ioctl(struct usb_serial_port *port, struct file *file, dbg("%s - port %d Error: port->tty->termios is NULL", __FUNCTION__, port->number); return -ENOTTY; } - if (!access_ok(VERIFY_READ, user_arg, sizeof(struct termios))) { + if (!access_ok(VERIFY_READ, user_arg, sizeof(struct ktermios))) { dbg("%s - port %d Error in access_ok", __FUNCTION__, port->number); return -EFAULT; } if (user_termios_to_kernel_termios(&priv->internal_termios, - (struct termios __user *)arg)) + (struct ktermios __user *)arg)) return -EFAULT; settings = kzalloc(50, GFP_KERNEL); diff --git a/trunk/drivers/usb/serial/mct_u232.c b/trunk/drivers/usb/serial/mct_u232.c index a906e500a02b..38b1d17e06ef 100644 --- a/trunk/drivers/usb/serial/mct_u232.c +++ b/trunk/drivers/usb/serial/mct_u232.c @@ -98,7 +98,7 @@ static void mct_u232_close (struct usb_serial_port *port, struct file *filp); static void mct_u232_read_int_callback (struct urb *urb); static void mct_u232_set_termios (struct usb_serial_port *port, - struct termios * old); + struct ktermios * old); static int mct_u232_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, @@ -556,7 +556,7 @@ static void mct_u232_read_int_callback (struct urb *urb) } /* mct_u232_read_int_callback */ static void mct_u232_set_termios (struct usb_serial_port *port, - struct termios *old_termios) + struct ktermios *old_termios) { struct usb_serial *serial = port->serial; struct mct_u232_private *priv = usb_get_serial_port_data(port); diff --git a/trunk/drivers/usb/serial/mos7720.c b/trunk/drivers/usb/serial/mos7720.c index 82cd15b894b0..e55f4ed81d7b 100644 --- a/trunk/drivers/usb/serial/mos7720.c +++ b/trunk/drivers/usb/serial/mos7720.c @@ -363,7 +363,7 @@ static int mos7720_open(struct usb_serial_port *port, struct file * filp) /* Initialising the write urb pool */ for (j = 0; j < NUM_URBS; ++j) { - urb = usb_alloc_urb(0,SLAB_ATOMIC); + urb = usb_alloc_urb(0,GFP_ATOMIC); mos7720_port->write_urb_pool[j] = urb; if (urb == NULL) { @@ -1014,7 +1014,7 @@ static int send_cmd_write_baud_rate(struct moschip_port *mos7720_port, * the specified new settings. */ static void change_port_settings(struct moschip_port *mos7720_port, - struct termios *old_termios) + struct ktermios *old_termios) { struct usb_serial_port *port; struct usb_serial *serial; @@ -1203,7 +1203,7 @@ static void change_port_settings(struct moschip_port *mos7720_port, * termios structure. */ static void mos7720_set_termios(struct usb_serial_port *port, - struct termios *old_termios) + struct ktermios *old_termios) { int status; unsigned int cflag; diff --git a/trunk/drivers/usb/serial/mos7840.c b/trunk/drivers/usb/serial/mos7840.c index 02c89e10b2cf..8cc728a49e41 100644 --- a/trunk/drivers/usb/serial/mos7840.c +++ b/trunk/drivers/usb/serial/mos7840.c @@ -826,7 +826,7 @@ static int mos7840_open(struct usb_serial_port *port, struct file *filp) /* Initialising the write urb pool */ for (j = 0; j < NUM_URBS; ++j) { - urb = usb_alloc_urb(0, SLAB_ATOMIC); + urb = usb_alloc_urb(0, GFP_ATOMIC); mos7840_port->write_urb_pool[j] = urb; if (urb == NULL) { @@ -1931,7 +1931,7 @@ static int mos7840_send_cmd_write_baud_rate(struct moschip_port *mos7840_port, *****************************************************************************/ static void mos7840_change_port_settings(struct moschip_port *mos7840_port, - struct termios *old_termios) + struct ktermios *old_termios) { struct tty_struct *tty; int baud; @@ -2118,7 +2118,7 @@ static void mos7840_change_port_settings(struct moschip_port *mos7840_port, *****************************************************************************/ static void mos7840_set_termios(struct usb_serial_port *port, - struct termios *old_termios) + struct ktermios *old_termios) { int status; unsigned int cflag; @@ -2786,7 +2786,7 @@ static int mos7840_startup(struct usb_serial *serial) i + 1, status); } - mos7840_port->control_urb = usb_alloc_urb(0, SLAB_ATOMIC); + mos7840_port->control_urb = usb_alloc_urb(0, GFP_ATOMIC); mos7840_port->ctrl_buf = kmalloc(16, GFP_KERNEL); } diff --git a/trunk/drivers/usb/serial/option.c b/trunk/drivers/usb/serial/option.c index 130afbbd3fca..0ae4098718c3 100644 --- a/trunk/drivers/usb/serial/option.c +++ b/trunk/drivers/usb/serial/option.c @@ -59,7 +59,7 @@ static int option_chars_in_buffer(struct usb_serial_port *port); static int option_ioctl(struct usb_serial_port *port, struct file *file, unsigned int cmd, unsigned long arg); static void option_set_termios(struct usb_serial_port *port, - struct termios *old); + struct ktermios *old); static void option_break_ctl(struct usb_serial_port *port, int break_state); static int option_tiocmget(struct usb_serial_port *port, struct file *file); static int option_tiocmset(struct usb_serial_port *port, struct file *file, @@ -230,7 +230,7 @@ static void option_break_ctl(struct usb_serial_port *port, int break_state) } static void option_set_termios(struct usb_serial_port *port, - struct termios *old_termios) + struct ktermios *old_termios) { dbg("%s", __FUNCTION__); diff --git a/trunk/drivers/usb/serial/pl2303.c b/trunk/drivers/usb/serial/pl2303.c index bc800c8787a8..d124d780e42e 100644 --- a/trunk/drivers/usb/serial/pl2303.c +++ b/trunk/drivers/usb/serial/pl2303.c @@ -455,7 +455,7 @@ static int pl2303_chars_in_buffer(struct usb_serial_port *port) } static void pl2303_set_termios(struct usb_serial_port *port, - struct termios *old_termios) + struct ktermios *old_termios) { struct usb_serial *serial = port->serial; struct pl2303_private *priv = usb_get_serial_port_data(port); @@ -687,7 +687,7 @@ static void pl2303_close(struct usb_serial_port *port, struct file *filp) static int pl2303_open(struct usb_serial_port *port, struct file *filp) { - struct termios tmp_termios; + struct ktermios tmp_termios; struct usb_serial *serial = port->serial; struct pl2303_private *priv = usb_get_serial_port_data(port); unsigned char *buf; diff --git a/trunk/drivers/usb/serial/sierra.c b/trunk/drivers/usb/serial/sierra.c index 4b5097fa48d7..6d8e91e00ecf 100644 --- a/trunk/drivers/usb/serial/sierra.c +++ b/trunk/drivers/usb/serial/sierra.c @@ -145,7 +145,7 @@ static void sierra_break_ctl(struct usb_serial_port *port, int break_state) } static void sierra_set_termios(struct usb_serial_port *port, - struct termios *old_termios) + struct ktermios *old_termios) { dbg("%s", __FUNCTION__); diff --git a/trunk/drivers/usb/serial/ti_usb_3410_5052.c b/trunk/drivers/usb/serial/ti_usb_3410_5052.c index ae98d8cbdbb8..f42eb9ea6405 100644 --- a/trunk/drivers/usb/serial/ti_usb_3410_5052.c +++ b/trunk/drivers/usb/serial/ti_usb_3410_5052.c @@ -161,7 +161,7 @@ static void ti_throttle(struct usb_serial_port *port); static void ti_unthrottle(struct usb_serial_port *port); static int ti_ioctl(struct usb_serial_port *port, struct file *file, unsigned int cmd, unsigned long arg); static void ti_set_termios(struct usb_serial_port *port, - struct termios *old_termios); + struct ktermios *old_termios); static int ti_tiocmget(struct usb_serial_port *port, struct file *file); static int ti_tiocmset(struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear); @@ -881,7 +881,7 @@ static int ti_ioctl(struct usb_serial_port *port, struct file *file, static void ti_set_termios(struct usb_serial_port *port, - struct termios *old_termios) + struct ktermios *old_termios) { struct ti_port *tport = usb_get_serial_port_data(port); struct tty_struct *tty = port->tty; diff --git a/trunk/drivers/usb/serial/usb-serial.c b/trunk/drivers/usb/serial/usb-serial.c index c1257d5292f5..716f6806cc89 100644 --- a/trunk/drivers/usb/serial/usb-serial.c +++ b/trunk/drivers/usb/serial/usb-serial.c @@ -397,7 +397,7 @@ static int serial_ioctl (struct tty_struct *tty, struct file * file, unsigned in return retval; } -static void serial_set_termios (struct tty_struct *tty, struct termios * old) +static void serial_set_termios (struct tty_struct *tty, struct ktermios * old) { struct usb_serial_port *port = tty->driver_data; @@ -533,9 +533,10 @@ void usb_serial_port_softint(struct usb_serial_port *port) schedule_work(&port->work); } -static void usb_serial_port_work(void *private) +static void usb_serial_port_work(struct work_struct *work) { - struct usb_serial_port *port = private; + struct usb_serial_port *port = + container_of(work, struct usb_serial_port, work); struct tty_struct *tty; dbg("%s - port %d", __FUNCTION__, port->number); @@ -799,7 +800,7 @@ int usb_serial_probe(struct usb_interface *interface, port->serial = serial; spin_lock_init(&port->lock); mutex_init(&port->mutex); - INIT_WORK(&port->work, usb_serial_port_work, port); + INIT_WORK(&port->work, usb_serial_port_work); serial->port[i] = port; } diff --git a/trunk/drivers/usb/serial/visor.c b/trunk/drivers/usb/serial/visor.c index eef5eaa5fa0b..b09f06096056 100644 --- a/trunk/drivers/usb/serial/visor.c +++ b/trunk/drivers/usb/serial/visor.c @@ -46,7 +46,7 @@ static int visor_probe (struct usb_serial *serial, const struct usb_device_id static int visor_calc_num_ports(struct usb_serial *serial); static void visor_shutdown (struct usb_serial *serial); static int visor_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg); -static void visor_set_termios (struct usb_serial_port *port, struct termios *old_termios); +static void visor_set_termios (struct usb_serial_port *port, struct ktermios *old_termios); static void visor_write_bulk_callback (struct urb *urb); static void visor_read_bulk_callback (struct urb *urb); static void visor_read_int_callback (struct urb *urb); @@ -916,7 +916,7 @@ static int visor_ioctl (struct usb_serial_port *port, struct file * file, unsign /* This function is all nice and good, but we don't change anything based on it :) */ -static void visor_set_termios (struct usb_serial_port *port, struct termios *old_termios) +static void visor_set_termios (struct usb_serial_port *port, struct ktermios *old_termios) { unsigned int cflag; diff --git a/trunk/drivers/usb/serial/whiteheat.c b/trunk/drivers/usb/serial/whiteheat.c index 4d1cd7aeccd3..dc45e58e2b8c 100644 --- a/trunk/drivers/usb/serial/whiteheat.c +++ b/trunk/drivers/usb/serial/whiteheat.c @@ -145,7 +145,7 @@ static void whiteheat_close (struct usb_serial_port *port, struct file *filp); static int whiteheat_write (struct usb_serial_port *port, const unsigned char *buf, int count); static int whiteheat_write_room (struct usb_serial_port *port); static int whiteheat_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg); -static void whiteheat_set_termios (struct usb_serial_port *port, struct termios * old); +static void whiteheat_set_termios (struct usb_serial_port *port, struct ktermios * old); static int whiteheat_tiocmget (struct usb_serial_port *port, struct file *file); static int whiteheat_tiocmset (struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear); static void whiteheat_break_ctl (struct usb_serial_port *port, int break_state); @@ -227,6 +227,7 @@ struct whiteheat_private { struct list_head rx_urbs_submitted; struct list_head rx_urb_q; struct work_struct rx_work; + struct usb_serial_port *port; struct list_head tx_urbs_free; struct list_head tx_urbs_submitted; }; @@ -241,7 +242,7 @@ static void command_port_read_callback(struct urb *urb); static int start_port_read(struct usb_serial_port *port); static struct whiteheat_urb_wrap *urb_to_wrap(struct urb *urb, struct list_head *head); static struct list_head *list_first(struct list_head *head); -static void rx_data_softint(void *private); +static void rx_data_softint(struct work_struct *work); static int firm_send_command(struct usb_serial_port *port, __u8 command, __u8 *data, __u8 datasize); static int firm_open(struct usb_serial_port *port); @@ -424,7 +425,8 @@ static int whiteheat_attach (struct usb_serial *serial) spin_lock_init(&info->lock); info->flags = 0; info->mcr = 0; - INIT_WORK(&info->rx_work, rx_data_softint, port); + INIT_WORK(&info->rx_work, rx_data_softint); + info->port = port; INIT_LIST_HEAD(&info->rx_urbs_free); INIT_LIST_HEAD(&info->rx_urbs_submitted); @@ -595,7 +597,7 @@ static void whiteheat_shutdown (struct usb_serial *serial) static int whiteheat_open (struct usb_serial_port *port, struct file *filp) { int retval = 0; - struct termios old_term; + struct ktermios old_term; dbg("%s - port %d", __FUNCTION__, port->number); @@ -868,7 +870,7 @@ static int whiteheat_ioctl (struct usb_serial_port *port, struct file * file, un } -static void whiteheat_set_termios (struct usb_serial_port *port, struct termios *old_termios) +static void whiteheat_set_termios (struct usb_serial_port *port, struct ktermios *old_termios) { dbg("%s -port %d", __FUNCTION__, port->number); @@ -949,7 +951,7 @@ static void whiteheat_unthrottle (struct usb_serial_port *port) spin_unlock_irqrestore(&info->lock, flags); if (actually_throttled) - rx_data_softint(port); + rx_data_softint(&info->rx_work); return; } @@ -1400,10 +1402,11 @@ static struct list_head *list_first(struct list_head *head) } -static void rx_data_softint(void *private) +static void rx_data_softint(struct work_struct *work) { - struct usb_serial_port *port = (struct usb_serial_port *)private; - struct whiteheat_private *info = usb_get_serial_port_data(port); + struct whiteheat_private *info = + container_of(work, struct whiteheat_private, rx_work); + struct usb_serial_port *port = info->port; struct tty_struct *tty = port->tty; struct whiteheat_urb_wrap *wrap; struct urb *urb; diff --git a/trunk/drivers/usb/storage/onetouch.c b/trunk/drivers/usb/storage/onetouch.c index 3a158d58441f..e565d3d2ab29 100644 --- a/trunk/drivers/usb/storage/onetouch.c +++ b/trunk/drivers/usb/storage/onetouch.c @@ -76,7 +76,7 @@ static void usb_onetouch_irq(struct urb *urb) input_sync(dev); resubmit: - status = usb_submit_urb (urb, SLAB_ATOMIC); + status = usb_submit_urb (urb, GFP_ATOMIC); if (status) err ("can't resubmit intr, %s-%s/input0, status %d", onetouch->udev->bus->bus_name, @@ -154,7 +154,7 @@ int onetouch_connect_input(struct us_data *ss) goto fail1; onetouch->data = usb_buffer_alloc(udev, ONETOUCH_PKT_LEN, - SLAB_ATOMIC, &onetouch->data_dma); + GFP_ATOMIC, &onetouch->data_dma); if (!onetouch->data) goto fail1; diff --git a/trunk/drivers/usb/storage/transport.c b/trunk/drivers/usb/storage/transport.c index 47644b5b6155..323293a3e61f 100644 --- a/trunk/drivers/usb/storage/transport.c +++ b/trunk/drivers/usb/storage/transport.c @@ -427,7 +427,7 @@ static int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe, US_DEBUGP("%s: xfer %u bytes, %d entries\n", __FUNCTION__, length, num_sg); result = usb_sg_init(&us->current_sg, us->pusb_dev, pipe, 0, - sg, num_sg, length, SLAB_NOIO); + sg, num_sg, length, GFP_NOIO); if (result) { US_DEBUGP("usb_sg_init returned %d\n", result); return USB_STOR_XFER_ERROR; diff --git a/trunk/drivers/usb/storage/usb.c b/trunk/drivers/usb/storage/usb.c index b401084b3d22..70644506651f 100644 --- a/trunk/drivers/usb/storage/usb.c +++ b/trunk/drivers/usb/storage/usb.c @@ -49,7 +49,7 @@ #include #include -#include +#include #include #include #include diff --git a/trunk/drivers/video/Kconfig b/trunk/drivers/video/Kconfig index 7a43020fa583..ab1daecfeac6 100644 --- a/trunk/drivers/video/Kconfig +++ b/trunk/drivers/video/Kconfig @@ -541,6 +541,7 @@ config FB_TGA select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT + select BITREVERSE help This is the frame buffer device driver for generic TGA graphic cards. Say Y if you have one of those. @@ -551,6 +552,7 @@ config FB_VESA select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT + select VIDEO_SELECT help This is the frame buffer device driver for generic VESA 2.0 compliant graphic cards. The older VESA 1.2 cards are not supported. @@ -705,6 +707,7 @@ config FB_NVIDIA select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT + select BITREVERSE help This driver supports graphics boards with the nVidia chips, TNT and newer. For very old chipsets, such as the RIVA128, then use @@ -744,6 +747,7 @@ config FB_RIVA select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT + select BITREVERSE help This driver supports graphics boards with the nVidia Riva/Geforce chips. diff --git a/trunk/drivers/video/S3triofb.c b/trunk/drivers/video/S3triofb.c index 397005eb392d..b3717c8f1bc2 100644 --- a/trunk/drivers/video/S3triofb.c +++ b/trunk/drivers/video/S3triofb.c @@ -535,8 +535,11 @@ static void __init s3triofb_of_init(struct device_node *dp) #endif fb_info.flags = FBINFO_FLAG_DEFAULT; - if (register_framebuffer(&fb_info) < 0) - return; + if (register_framebuffer(&fb_info) < 0) { + iounmap(fb_info.screen_base); + fb_info.screen_base = NULL; + return; + } printk("fb%d: S3 Trio frame buffer device on %s\n", fb_info.node, dp->full_name); diff --git a/trunk/drivers/video/amifb.c b/trunk/drivers/video/amifb.c index a4e3fca05891..88a47845c4f7 100644 --- a/trunk/drivers/video/amifb.c +++ b/trunk/drivers/video/amifb.c @@ -2407,10 +2407,10 @@ int __init amifb_init(void) fb_info.fix.smem_len); if (!videomemory) { printk("amifb: WARNING! unable to map videomem cached writethrough\n"); - videomemory = ZTWO_VADDR(fb_info.fix.smem_start); - } + fb_info.screen_base = (char *)ZTWO_VADDR(fb_info.fix.smem_start); + } else + fb_info.screen_base = (char *)videomemory; - fb_info.screen_base = (char *)videomemory; memset(dummysprite, 0, DUMMYSPRITEMEMSIZE); /* @@ -2453,6 +2453,8 @@ static void amifb_deinit(void) { fb_dealloc_cmap(&fb_info.cmap); chipfree(); + if (videomemory) + iounmap((void*)videomemory); release_mem_region(CUSTOM_PHYSADDR+0xe0, 0x120); custom.dmacon = DMAF_ALL | DMAF_MASTER; } diff --git a/trunk/drivers/video/arcfb.c b/trunk/drivers/video/arcfb.c index ab34b96acc31..30a8369757e7 100644 --- a/trunk/drivers/video/arcfb.c +++ b/trunk/drivers/video/arcfb.c @@ -454,7 +454,7 @@ static ssize_t arcfb_write(struct file *file, const char __user *buf, size_t cou unsigned int xres; p = *ppos; - inode = file->f_dentry->d_inode; + inode = file->f_path.dentry->d_inode; fbidx = iminor(inode); info = registered_fb[fbidx]; diff --git a/trunk/drivers/video/atafb.c b/trunk/drivers/video/atafb.c index 02c41a626fa2..602db660bc73 100644 --- a/trunk/drivers/video/atafb.c +++ b/trunk/drivers/video/atafb.c @@ -2804,8 +2804,19 @@ int __init atafb_init(void) atafb_set_disp(-1, &fb_info); do_install_cmap(0, &fb_info); - if (register_framebuffer(&fb_info) < 0) + if (register_framebuffer(&fb_info) < 0) { +#ifdef ATAFB_EXT + if (external_addr) { + iounmap(external_addr); + external_addr = NULL; + } + if (external_vgaiobase) { + iounmap((void*)external_vgaiobase); + external_vgaiobase = 0; + } +#endif return -EINVAL; + } printk("Determined %dx%d, depth %d\n", disp.var.xres, disp.var.yres, disp.var.bits_per_pixel); diff --git a/trunk/drivers/video/aty/aty128fb.c b/trunk/drivers/video/aty/aty128fb.c index 276a21530b95..3feddf89d100 100644 --- a/trunk/drivers/video/aty/aty128fb.c +++ b/trunk/drivers/video/aty/aty128fb.c @@ -1333,6 +1333,8 @@ static int aty128_var_to_pll(u32 period_in_ps, struct aty128_pll *pll, if (vclk * 12 < c.ppll_min) vclk = c.ppll_min/12; + pll->post_divider = -1; + /* now, find an acceptable divider */ for (i = 0; i < sizeof(post_dividers); i++) { output_freq = post_dividers[i] * vclk; @@ -1342,6 +1344,9 @@ static int aty128_var_to_pll(u32 period_in_ps, struct aty128_pll *pll, } } + if (pll->post_divider < 0) + return -EINVAL; + /* calculate feedback divider */ n = c.ref_divider * output_freq; d = c.ref_clk; diff --git a/trunk/drivers/video/aty/atyfb.h b/trunk/drivers/video/aty/atyfb.h index b04f49fb976a..f72faff33c0c 100644 --- a/trunk/drivers/video/aty/atyfb.h +++ b/trunk/drivers/video/aty/atyfb.h @@ -126,7 +126,6 @@ union aty_pll { */ struct atyfb_par { - struct aty_cmap_regs __iomem *aty_cmap_regs; struct { u8 red, green, blue; } palette[256]; const struct aty_dac_ops *dac_ops; const struct aty_pll_ops *pll_ops; @@ -186,6 +185,7 @@ struct atyfb_par { int mtrr_aper; int mtrr_reg; #endif + u32 mem_cntl; }; /* @@ -227,7 +227,7 @@ static inline u32 aty_ld_le32(int regindex, const struct atyfb_par *par) regindex -= 0x800; #ifdef CONFIG_ATARI - return in_le32((volatile u32 *)(par->ati_regbase + regindex)); + return in_le32(par->ati_regbase + regindex); #else return readl(par->ati_regbase + regindex); #endif @@ -240,7 +240,7 @@ static inline void aty_st_le32(int regindex, u32 val, const struct atyfb_par *pa regindex -= 0x800; #ifdef CONFIG_ATARI - out_le32((volatile u32 *)(par->ati_regbase + regindex), val); + out_le32(par->ati_regbase + regindex, val); #else writel(val, par->ati_regbase + regindex); #endif @@ -253,7 +253,7 @@ static inline void aty_st_le16(int regindex, u16 val, if (regindex >= 0x400) regindex -= 0x800; #ifdef CONFIG_ATARI - out_le16((volatile u16 *)(par->ati_regbase + regindex), val); + out_le16(par->ati_regbase + regindex, val); #else writel(val, par->ati_regbase + regindex); #endif @@ -315,6 +315,7 @@ struct aty_pll_ops { void (*set_pll) (const struct fb_info * info, const union aty_pll * pll); void (*get_pll) (const struct fb_info *info, union aty_pll * pll); int (*init_pll) (const struct fb_info * info, union aty_pll * pll); + void (*resume_pll)(const struct fb_info *info, union aty_pll *pll); }; extern const struct aty_pll_ops aty_pll_ati18818_1; /* ATI 18818 */ diff --git a/trunk/drivers/video/aty/atyfb_base.c b/trunk/drivers/video/aty/atyfb_base.c index e815b354c09d..176f9b85cdbe 100644 --- a/trunk/drivers/video/aty/atyfb_base.c +++ b/trunk/drivers/video/aty/atyfb_base.c @@ -203,14 +203,6 @@ static void ATIReduceRatio(int *Numerator, int *Denominator) * The Hardware parameters for each card */ -struct aty_cmap_regs { - u8 windex; - u8 lut; - u8 mask; - u8 rindex; - u8 cntl; -}; - struct pci_mmap_map { unsigned long voff; unsigned long poff; @@ -249,7 +241,8 @@ static int atyfb_sync(struct fb_info *info); * Internal routines */ -static int aty_init(struct fb_info *info, const char *name); +static int aty_init(struct fb_info *info); +static void aty_resume_chip(struct fb_info *info); #ifdef CONFIG_ATARI static int store_video_par(char *videopar, unsigned char m64_num); #endif @@ -1937,17 +1930,14 @@ static void atyfb_save_palette(struct atyfb_par *par, int enter) aty_st_8(DAC_CNTL, tmp, par); aty_st_8(DAC_MASK, 0xff, par); - writeb(i, &par->aty_cmap_regs->rindex); - atyfb_save.r[enter][i] = readb(&par->aty_cmap_regs->lut); - atyfb_save.g[enter][i] = readb(&par->aty_cmap_regs->lut); - atyfb_save.b[enter][i] = readb(&par->aty_cmap_regs->lut); - writeb(i, &par->aty_cmap_regs->windex); - writeb(atyfb_save.r[1 - enter][i], - &par->aty_cmap_regs->lut); - writeb(atyfb_save.g[1 - enter][i], - &par->aty_cmap_regs->lut); - writeb(atyfb_save.b[1 - enter][i], - &par->aty_cmap_regs->lut); + aty_st_8(DAC_R_INDEX, i, par); + atyfb_save.r[enter][i] = aty_ld_8(DAC_DATA, par); + atyfb_save.g[enter][i] = aty_ld_8(DAC_DATA, par); + atyfb_save.b[enter][i] = aty_ld_8(DAC_DATA, par); + aty_st_8(DAC_W_INDEX, i, par); + aty_st_8(DAC_DATA, atyfb_save.r[1 - enter][i], par); + aty_st_8(DAC_DATA, atyfb_save.g[1 - enter][i], par); + aty_st_8(DAC_DATA, atyfb_save.b[1 - enter][i], par); } } @@ -1982,6 +1972,7 @@ static void atyfb_palette(int enter) #if defined(CONFIG_PM) && defined(CONFIG_PCI) +#ifdef CONFIG_PPC_PMAC /* Power management routines. Those are used for PowerBook sleep. */ static int aty_power_mgmt(int sleep, struct atyfb_par *par) @@ -2038,21 +2029,13 @@ static int aty_power_mgmt(int sleep, struct atyfb_par *par) return timeout ? 0 : -EIO; } +#endif static int atyfb_pci_suspend(struct pci_dev *pdev, pm_message_t state) { struct fb_info *info = pci_get_drvdata(pdev); struct atyfb_par *par = (struct atyfb_par *) info->par; -#ifndef CONFIG_PPC_PMAC - /* HACK ALERT ! Once I find a proper way to say to each driver - * individually what will happen with it's PCI slot, I'll change - * that. On laptops, the AGP slot is just unclocked, so D2 is - * expected, while on desktops, the card is powered off - */ - return 0; -#endif /* CONFIG_PPC_PMAC */ - if (state.event == pdev->dev.power.power_state.event) return 0; @@ -2070,6 +2053,7 @@ static int atyfb_pci_suspend(struct pci_dev *pdev, pm_message_t state) par->asleep = 1; par->lock_blank = 1; +#ifdef CONFIG_PPC_PMAC /* Set chip to "suspend" mode */ if (aty_power_mgmt(1, par)) { par->asleep = 0; @@ -2079,6 +2063,9 @@ static int atyfb_pci_suspend(struct pci_dev *pdev, pm_message_t state) release_console_sem(); return -EIO; } +#else + pci_set_power_state(pdev, pci_choose_state(pdev, state)); +#endif release_console_sem(); @@ -2097,8 +2084,15 @@ static int atyfb_pci_resume(struct pci_dev *pdev) acquire_console_sem(); +#ifdef CONFIG_PPC_PMAC if (pdev->dev.power.power_state.event == 2) aty_power_mgmt(0, par); +#else + pci_set_power_state(pdev, PCI_D0); +#endif + + aty_resume_chip(info); + par->asleep = 0; /* Restore display */ @@ -2344,24 +2338,16 @@ static int __devinit atyfb_get_timings_from_lcd(struct atyfb_par *par, } #endif /* defined(__i386__) && defined(CONFIG_FB_ATY_GENERIC_LCD) */ -static int __devinit aty_init(struct fb_info *info, const char *name) +static int __devinit aty_init(struct fb_info *info) { struct atyfb_par *par = (struct atyfb_par *) info->par; const char *ramname = NULL, *xtal; int gtb_memsize, has_var = 0; struct fb_var_screeninfo var; - u8 pll_ref_div; - u32 i; -#if defined(CONFIG_PPC) - int sense; -#endif init_waitqueue_head(&par->vblank.wait); spin_lock_init(&par->int_lock); - par->aty_cmap_regs = - (struct aty_cmap_regs __iomem *) (par->ati_regbase + 0xc0); - #ifdef CONFIG_PPC_PMAC /* The Apple iBook1 uses non-standard memory frequencies. We detect it * and set the frequency manually. */ @@ -2464,18 +2450,21 @@ static int __devinit aty_init(struct fb_info *info, const char *name) par->pll_limits.mclk = 63; } - if (M64_HAS(GTB_DSP) - && (pll_ref_div = aty_ld_pll_ct(PLL_REF_DIV, par))) { - int diff1, diff2; - diff1 = 510 * 14 / pll_ref_div - par->pll_limits.pll_max; - diff2 = 510 * 29 / pll_ref_div - par->pll_limits.pll_max; - if (diff1 < 0) - diff1 = -diff1; - if (diff2 < 0) - diff2 = -diff2; - if (diff2 < diff1) { - par->ref_clk_per = 1000000000000ULL / 29498928; - xtal = "29.498928"; + if (M64_HAS(GTB_DSP)) { + u8 pll_ref_div = aty_ld_pll_ct(PLL_REF_DIV, par); + + if (pll_ref_div) { + int diff1, diff2; + diff1 = 510 * 14 / pll_ref_div - par->pll_limits.pll_max; + diff2 = 510 * 29 / pll_ref_div - par->pll_limits.pll_max; + if (diff1 < 0) + diff1 = -diff1; + if (diff2 < 0) + diff2 = -diff2; + if (diff2 < diff1) { + par->ref_clk_per = 1000000000000ULL / 29498928; + xtal = "29.498928"; + } } } #endif /* CONFIG_FB_ATY_CT */ @@ -2485,10 +2474,10 @@ static int __devinit aty_init(struct fb_info *info, const char *name) if(par->pll_ops->get_pll) par->pll_ops->get_pll(info, &saved_pll); - i = aty_ld_le32(MEM_CNTL, par); + par->mem_cntl = aty_ld_le32(MEM_CNTL, par); gtb_memsize = M64_HAS(GTB_DSP); if (gtb_memsize) - switch (i & 0xF) { /* 0xF used instead of MEM_SIZE_ALIAS */ + switch (par->mem_cntl & 0xF) { /* 0xF used instead of MEM_SIZE_ALIAS */ case MEM_SIZE_512K: info->fix.smem_len = 0x80000; break; @@ -2510,7 +2499,7 @@ static int __devinit aty_init(struct fb_info *info, const char *name) default: info->fix.smem_len = 0x80000; } else - switch (i & MEM_SIZE_ALIAS) { + switch (par->mem_cntl & MEM_SIZE_ALIAS) { case MEM_SIZE_512K: info->fix.smem_len = 0x80000; break; @@ -2540,20 +2529,20 @@ static int __devinit aty_init(struct fb_info *info, const char *name) if (vram) { info->fix.smem_len = vram * 1024; - i = i & ~(gtb_memsize ? 0xF : MEM_SIZE_ALIAS); + par->mem_cntl &= ~(gtb_memsize ? 0xF : MEM_SIZE_ALIAS); if (info->fix.smem_len <= 0x80000) - i |= MEM_SIZE_512K; + par->mem_cntl |= MEM_SIZE_512K; else if (info->fix.smem_len <= 0x100000) - i |= MEM_SIZE_1M; + par->mem_cntl |= MEM_SIZE_1M; else if (info->fix.smem_len <= 0x200000) - i |= gtb_memsize ? MEM_SIZE_2M_GTB : MEM_SIZE_2M; + par->mem_cntl |= gtb_memsize ? MEM_SIZE_2M_GTB : MEM_SIZE_2M; else if (info->fix.smem_len <= 0x400000) - i |= gtb_memsize ? MEM_SIZE_4M_GTB : MEM_SIZE_4M; + par->mem_cntl |= gtb_memsize ? MEM_SIZE_4M_GTB : MEM_SIZE_4M; else if (info->fix.smem_len <= 0x600000) - i |= gtb_memsize ? MEM_SIZE_6M_GTB : MEM_SIZE_6M; + par->mem_cntl |= gtb_memsize ? MEM_SIZE_6M_GTB : MEM_SIZE_6M; else - i |= gtb_memsize ? MEM_SIZE_8M_GTB : MEM_SIZE_8M; - aty_st_le32(MEM_CNTL, i, par); + par->mem_cntl |= gtb_memsize ? MEM_SIZE_8M_GTB : MEM_SIZE_8M; + aty_st_le32(MEM_CNTL, par->mem_cntl, par); } /* @@ -2599,11 +2588,12 @@ static int __devinit aty_init(struct fb_info *info, const char *name) #endif if(par->pll_ops->init_pll) par->pll_ops->init_pll(info, &par->pll); + if (par->pll_ops->resume_pll) + par->pll_ops->resume_pll(info, &par->pll); /* - * Last page of 8 MB (4 MB on ISA) aperture is MMIO - * FIXME: we should use the auxiliary aperture instead so we can access - * the full 8 MB of video RAM on 8 MB boards + * Last page of 8 MB (4 MB on ISA) aperture is MMIO, + * unless the auxiliary register aperture is used. */ if (!par->aux_start && @@ -2669,6 +2659,7 @@ static int __devinit aty_init(struct fb_info *info, const char *name) has_var = 1; } else { if (default_vmode == VMODE_CHOOSE) { + int sense; if (M64_HAS(G3_PB_1024x768)) /* G3 PowerBook with 1024x768 LCD */ default_vmode = VMODE_1024_768_60; @@ -2749,7 +2740,7 @@ static int __devinit aty_init(struct fb_info *info, const char *name) fb_list = info; PRINTKI("fb%d: %s frame buffer device on %s\n", - info->node, info->fix.id, name); + info->node, info->fix.id, par->bus_type == ISA ? "ISA" : "PCI"); return 0; aty_init_exit: @@ -2770,6 +2761,19 @@ static int __devinit aty_init(struct fb_info *info, const char *name) return -1; } +static void aty_resume_chip(struct fb_info *info) +{ + struct atyfb_par *par = info->par; + + aty_st_le32(MEM_CNTL, par->mem_cntl, par); + + if (par->pll_ops->resume_pll) + par->pll_ops->resume_pll(info, &par->pll); + + if (par->aux_start) + aty_st_le32(BUS_CNTL, aty_ld_le32(BUS_CNTL, par) | BUS_APER_REG_DIS, par); +} + #ifdef CONFIG_ATARI static int __devinit store_video_par(char *video_str, unsigned char m64_num) { @@ -2826,9 +2830,9 @@ static int atyfb_blank(int blank, struct fb_info *info) #endif gen_cntl = aty_ld_le32(CRTC_GEN_CNTL, par); + gen_cntl &= ~0x400004c; switch (blank) { - case FB_BLANK_UNBLANK: - gen_cntl &= ~0x400004c; + case FB_BLANK_UNBLANK: break; case FB_BLANK_NORMAL: gen_cntl |= 0x4000040; @@ -2863,17 +2867,10 @@ static int atyfb_blank(int blank, struct fb_info *info) static void aty_st_pal(u_int regno, u_int red, u_int green, u_int blue, const struct atyfb_par *par) { -#ifdef CONFIG_ATARI - out_8(&par->aty_cmap_regs->windex, regno); - out_8(&par->aty_cmap_regs->lut, red); - out_8(&par->aty_cmap_regs->lut, green); - out_8(&par->aty_cmap_regs->lut, blue); -#else - writeb(regno, &par->aty_cmap_regs->windex); - writeb(red, &par->aty_cmap_regs->lut); - writeb(green, &par->aty_cmap_regs->lut); - writeb(blue, &par->aty_cmap_regs->lut); -#endif + aty_st_8(DAC_W_INDEX, regno, par); + aty_st_8(DAC_DATA, red, par); + aty_st_8(DAC_DATA, green, par); + aty_st_8(DAC_DATA, blue, par); } /* @@ -3182,7 +3179,7 @@ static int __devinit atyfb_setup_sparc(struct pci_dev *pdev, #ifdef __i386__ #ifdef CONFIG_FB_ATY_GENERIC_LCD -static void aty_init_lcd(struct atyfb_par *par, u32 bios_base) +static void __devinit aty_init_lcd(struct atyfb_par *par, u32 bios_base) { u32 driv_inf_tab, sig; u16 lcd_ofs; @@ -3527,6 +3524,10 @@ static int __devinit atyfb_setup_generic(struct pci_dev *pdev, struct fb_info *i atyfb_setup_generic_fail: iounmap(par->ati_regbase); par->ati_regbase = NULL; + if (info->screen_base) { + iounmap(info->screen_base); + info->screen_base = NULL; + } return ret; } @@ -3594,7 +3595,7 @@ static int __devinit atyfb_pci_probe(struct pci_dev *pdev, const struct pci_devi pci_set_drvdata(pdev, info); /* Init chip & register framebuffer */ - if (aty_init(info, "PCI")) + if (aty_init(info)) goto err_release_io; #ifdef __sparc__ @@ -3641,12 +3642,13 @@ static int __devinit atyfb_pci_probe(struct pci_dev *pdev, const struct pci_devi #ifdef CONFIG_ATARI -static int __devinit atyfb_atari_probe(void) +static int __init atyfb_atari_probe(void) { struct atyfb_par *par; struct fb_info *info; int m64_num; u32 clock_r; + int num_found = 0; for (m64_num = 0; m64_num < mach64_count; m64_num++) { if (!phys_vmembase[m64_num] || !phys_size[m64_num] || @@ -3694,16 +3696,34 @@ static int __devinit atyfb_atari_probe(void) break; } - if (aty_init(info, "ISA bus")) { + /* Fake pci_id for correct_chipset() */ + switch (aty_ld_le32(CONFIG_CHIP_ID, par) & CFG_CHIP_TYPE) { + case 0x00d7: + par->pci_id = PCI_CHIP_MACH64GX; + break; + case 0x0057: + par->pci_id = PCI_CHIP_MACH64CX; + break; + default: + break; + } + + if (correct_chipset(par) || aty_init(info)) { + iounmap(info->screen_base); + iounmap(par->ati_regbase); framebuffer_release(info); - /* This is insufficient! kernel_map has added two large chunks!! */ - return -ENXIO; + } else { + num_found++; } } + + return num_found ? 0 : -ENXIO; } #endif /* CONFIG_ATARI */ +#ifdef CONFIG_PCI + static void __devexit atyfb_remove(struct fb_info *info) { struct atyfb_par *par = (struct atyfb_par *) info->par; @@ -3751,7 +3771,6 @@ static void __devexit atyfb_remove(struct fb_info *info) framebuffer_release(info); } -#ifdef CONFIG_PCI static void __devexit atyfb_pci_remove(struct pci_dev *pdev) { @@ -3786,7 +3805,7 @@ static struct pci_driver atyfb_driver = { #endif /* CONFIG_PCI */ #ifndef MODULE -static int __devinit atyfb_setup(char *options) +static int __init atyfb_setup(char *options) { char *this_opt; @@ -3858,7 +3877,7 @@ static int __devinit atyfb_setup(char *options) } #endif /* MODULE */ -static int __devinit atyfb_init(void) +static int __init atyfb_init(void) { int err1 = 1, err2 = 1; #ifndef MODULE diff --git a/trunk/drivers/video/aty/mach64_ct.c b/trunk/drivers/video/aty/mach64_ct.c index 5080816be653..f3b487b8710b 100644 --- a/trunk/drivers/video/aty/mach64_ct.c +++ b/trunk/drivers/video/aty/mach64_ct.c @@ -370,8 +370,8 @@ void aty_set_pll_ct(const struct fb_info *info, const union aty_pll *pll) #endif } -static void __init aty_get_pll_ct(const struct fb_info *info, - union aty_pll *pll) +static void __devinit aty_get_pll_ct(const struct fb_info *info, + union aty_pll *pll) { struct atyfb_par *par = (struct atyfb_par *) info->par; u8 tmp, clock; @@ -394,12 +394,12 @@ static void __init aty_get_pll_ct(const struct fb_info *info, } } -static int __init aty_init_pll_ct(const struct fb_info *info, - union aty_pll *pll) +static int __devinit aty_init_pll_ct(const struct fb_info *info, + union aty_pll *pll) { struct atyfb_par *par = (struct atyfb_par *) info->par; - u8 mpost_div, xpost_div, sclk_post_div_real, sclk_fb_div, spll_cntl2; - u32 q, i, memcntl, trp; + u8 mpost_div, xpost_div, sclk_post_div_real; + u32 q, memcntl, trp; u32 dsp_config, dsp_on_off, vga_dsp_config, vga_dsp_on_off; #ifdef DEBUG int pllmclk, pllsclk; @@ -575,14 +575,30 @@ static int __init aty_init_pll_ct(const struct fb_info *info, mpost_div += (q < 32*8); } sclk_post_div_real = postdividers[mpost_div]; - sclk_fb_div = q * sclk_post_div_real / 8; - spll_cntl2 = mpost_div << 4; + pll->ct.sclk_fb_div = q * sclk_post_div_real / 8; + pll->ct.spll_cntl2 = mpost_div << 4; #ifdef DEBUG - pllsclk = (1000000 * 2 * sclk_fb_div) / + pllsclk = (1000000 * 2 * pll->ct.sclk_fb_div) / (par->ref_clk_per * pll->ct.pll_ref_div); printk("atyfb(%s): use sclk, pllsclk=%d MHz, sclk=mclk=%d MHz\n", __FUNCTION__, pllsclk, pllsclk / sclk_post_div_real); #endif + } + + /* Disable the extra precision pixel clock controls since we do not use them. */ + pll->ct.ext_vpll_cntl = aty_ld_pll_ct(EXT_VPLL_CNTL, par); + pll->ct.ext_vpll_cntl &= ~(EXT_VPLL_EN | EXT_VPLL_VGA_EN | EXT_VPLL_INSYNC); + + return 0; +} + +static void aty_resume_pll_ct(const struct fb_info *info, + union aty_pll *pll) +{ + struct atyfb_par *par = info->par; + + if (par->mclk_per != par->xclk_per) { + int i; /* * This disables the sclk, crashes the computer as reported: * aty_st_pll_ct(SPLL_CNTL2, 3, info); @@ -590,8 +606,8 @@ static int __init aty_init_pll_ct(const struct fb_info *info, * So it seems the sclk must be enabled before it is used; * so PLL_GEN_CNTL must be programmed *after* the sclk. */ - aty_st_pll_ct(SCLK_FB_DIV, sclk_fb_div, par); - aty_st_pll_ct(SPLL_CNTL2, spll_cntl2, par); + aty_st_pll_ct(SCLK_FB_DIV, pll->ct.sclk_fb_div, par); + aty_st_pll_ct(SPLL_CNTL2, pll->ct.spll_cntl2, par); /* * The sclk has been started. However, I believe the first clock * ticks it generates are not very stable. Hope this primitive loop @@ -605,11 +621,7 @@ static int __init aty_init_pll_ct(const struct fb_info *info, aty_st_pll_ct(PLL_GEN_CNTL, pll->ct.pll_gen_cntl, par); aty_st_pll_ct(MCLK_FB_DIV, pll->ct.mclk_fb_div, par); aty_st_pll_ct(PLL_EXT_CNTL, pll->ct.pll_ext_cntl, par); - /* Disable the extra precision pixel clock controls since we do not use them. */ - aty_st_pll_ct(EXT_VPLL_CNTL, aty_ld_pll_ct(EXT_VPLL_CNTL, par) & - ~(EXT_VPLL_EN | EXT_VPLL_VGA_EN | EXT_VPLL_INSYNC), par); - - return 0; + aty_st_pll_ct(EXT_VPLL_CNTL, pll->ct.ext_vpll_cntl, par); } static int dummy(void) @@ -626,5 +638,6 @@ const struct aty_pll_ops aty_pll_ct = { .pll_to_var = aty_pll_to_var_ct, .set_pll = aty_set_pll_ct, .get_pll = aty_get_pll_ct, - .init_pll = aty_init_pll_ct + .init_pll = aty_init_pll_ct, + .resume_pll = aty_resume_pll_ct, }; diff --git a/trunk/drivers/video/aty/radeon_monitor.c b/trunk/drivers/video/aty/radeon_monitor.c index ea531a6f45d1..38c7dbf8c151 100644 --- a/trunk/drivers/video/aty/radeon_monitor.c +++ b/trunk/drivers/video/aty/radeon_monitor.c @@ -104,10 +104,9 @@ static int __devinit radeon_parse_montype_prop(struct device_node *dp, u8 **out_ if (pedid == NULL) return mt; - tmp = (u8 *)kmalloc(EDID_LENGTH, GFP_KERNEL); + tmp = kmemdup(pedid, EDID_LENGTH, GFP_KERNEL); if (!tmp) return mt; - memcpy(tmp, pedid, EDID_LENGTH); *out_EDID = tmp; return mt; } diff --git a/trunk/drivers/video/au1100fb.h b/trunk/drivers/video/au1100fb.h index 2855534dc235..164fe2f231ec 100644 --- a/trunk/drivers/video/au1100fb.h +++ b/trunk/drivers/video/au1100fb.h @@ -274,7 +274,7 @@ static struct au1100fb_panel known_lcd_panels[] = .bpp = 16, .control_base = 0x0004886A | LCD_CONTROL_DEFAULT_PO | LCD_CONTROL_DEFAULT_SBPPF | - LCD_CONTROL_BPP_16, + LCD_CONTROL_BPP_16 | LCD_CONTROL_SBB_4, .clkcontrol_base = 0x00020000, .horztiming = 0x005aff1f, .verttiming = 0x16000e57, diff --git a/trunk/drivers/video/backlight/backlight.c b/trunk/drivers/video/backlight/backlight.c index 27597c576eff..db8c191b1201 100644 --- a/trunk/drivers/video/backlight/backlight.c +++ b/trunk/drivers/video/backlight/backlight.c @@ -14,6 +14,59 @@ #include #include + +#if defined(CONFIG_FB) || (defined(CONFIG_FB_MODULE) && \ + defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE)) +/* This callback gets called when something important happens inside a + * framebuffer driver. We're looking if that important event is blanking, + * and if it is, we're switching backlight power as well ... + */ +static int fb_notifier_callback(struct notifier_block *self, + unsigned long event, void *data) +{ + struct backlight_device *bd; + struct fb_event *evdata = data; + + /* If we aren't interested in this event, skip it immediately ... */ + if (event != FB_EVENT_BLANK) + return 0; + + bd = container_of(self, struct backlight_device, fb_notif); + down(&bd->sem); + if (bd->props) + if (!bd->props->check_fb || + bd->props->check_fb(evdata->info)) { + bd->props->fb_blank = *(int *)evdata->data; + if (likely(bd->props && bd->props->update_status)) + bd->props->update_status(bd); + } + up(&bd->sem); + return 0; +} + +static int backlight_register_fb(struct backlight_device *bd) +{ + memset(&bd->fb_notif, 0, sizeof(bd->fb_notif)); + bd->fb_notif.notifier_call = fb_notifier_callback; + + return fb_register_client(&bd->fb_notif); +} + +static void backlight_unregister_fb(struct backlight_device *bd) +{ + fb_unregister_client(&bd->fb_notif); +} +#else +static inline int backlight_register_fb(struct backlight_device *bd) +{ + return 0; +} + +static inline void backlight_unregister_fb(struct backlight_device *bd) +{ +} +#endif /* CONFIG_FB */ + static ssize_t backlight_show_power(struct class_device *cdev, char *buf) { int rc = -ENXIO; @@ -142,7 +195,7 @@ static struct class backlight_class = { .store = _store, \ } -static struct class_device_attribute bl_class_device_attributes[] = { +static const struct class_device_attribute bl_class_device_attributes[] = { DECLARE_ATTR(power, 0644, backlight_show_power, backlight_store_power), DECLARE_ATTR(brightness, 0644, backlight_show_brightness, backlight_store_brightness), @@ -151,33 +204,6 @@ static struct class_device_attribute bl_class_device_attributes[] = { DECLARE_ATTR(max_brightness, 0444, backlight_show_max_brightness, NULL), }; -/* This callback gets called when something important happens inside a - * framebuffer driver. We're looking if that important event is blanking, - * and if it is, we're switching backlight power as well ... - */ -static int fb_notifier_callback(struct notifier_block *self, - unsigned long event, void *data) -{ - struct backlight_device *bd; - struct fb_event *evdata =(struct fb_event *)data; - - /* If we aren't interested in this event, skip it immediately ... */ - if (event != FB_EVENT_BLANK) - return 0; - - bd = container_of(self, struct backlight_device, fb_notif); - down(&bd->sem); - if (bd->props) - if (!bd->props->check_fb || - bd->props->check_fb(evdata->info)) { - bd->props->fb_blank = *(int *)evdata->data; - if (likely(bd->props && bd->props->update_status)) - bd->props->update_status(bd); - } - up(&bd->sem); - return 0; -} - /** * backlight_device_register - create and register a new object of * backlight_device class. @@ -215,10 +241,7 @@ error: kfree(new_bd); return ERR_PTR(rc); } - memset(&new_bd->fb_notif, 0, sizeof(new_bd->fb_notif)); - new_bd->fb_notif.notifier_call = fb_notifier_callback; - - rc = fb_register_client(&new_bd->fb_notif); + rc = backlight_register_fb(new_bd); if (unlikely(rc)) goto error; @@ -259,16 +282,10 @@ void backlight_device_unregister(struct backlight_device *bd) &bl_class_device_attributes[i]); down(&bd->sem); - if (likely(bd->props && bd->props->update_status)) { - bd->props->brightness = 0; - bd->props->power = 0; - bd->props->update_status(bd); - } - bd->props = NULL; up(&bd->sem); - fb_unregister_client(&bd->fb_notif); + backlight_unregister_fb(bd); class_device_unregister(&bd->class_dev); } diff --git a/trunk/drivers/video/backlight/corgi_bl.c b/trunk/drivers/video/backlight/corgi_bl.c index d07ecb53c68b..61587ca2cdbb 100644 --- a/trunk/drivers/video/backlight/corgi_bl.c +++ b/trunk/drivers/video/backlight/corgi_bl.c @@ -135,6 +135,10 @@ static int corgibl_probe(struct platform_device *pdev) static int corgibl_remove(struct platform_device *dev) { + corgibl_data.power = 0; + corgibl_data.brightness = 0; + corgibl_send_intensity(corgi_backlight_device); + backlight_device_unregister(corgi_backlight_device); printk("Corgi Backlight Driver Unloaded\n"); diff --git a/trunk/drivers/video/backlight/hp680_bl.c b/trunk/drivers/video/backlight/hp680_bl.c index e3993213d10e..1c569fb543ae 100644 --- a/trunk/drivers/video/backlight/hp680_bl.c +++ b/trunk/drivers/video/backlight/hp680_bl.c @@ -117,6 +117,10 @@ static int __init hp680bl_probe(struct platform_device *dev) static int hp680bl_remove(struct platform_device *dev) { + hp680bl_data.brightness = 0; + hp680bl_data.power = 0; + hp680bl_send_intensity(hp680_backlight_device); + backlight_device_unregister(hp680_backlight_device); return 0; diff --git a/trunk/drivers/video/backlight/lcd.c b/trunk/drivers/video/backlight/lcd.c index bc8ab005a3fb..f6e041627edb 100644 --- a/trunk/drivers/video/backlight/lcd.c +++ b/trunk/drivers/video/backlight/lcd.c @@ -14,6 +14,53 @@ #include #include +#if defined(CONFIG_FB) || (defined(CONFIG_FB_MODULE) && \ + defined(CONFIG_LCD_CLASS_DEVICE_MODULE)) +/* This callback gets called when something important happens inside a + * framebuffer driver. We're looking if that important event is blanking, + * and if it is, we're switching lcd power as well ... + */ +static int fb_notifier_callback(struct notifier_block *self, + unsigned long event, void *data) +{ + struct lcd_device *ld; + struct fb_event *evdata = data; + + /* If we aren't interested in this event, skip it immediately ... */ + if (event != FB_EVENT_BLANK) + return 0; + + ld = container_of(self, struct lcd_device, fb_notif); + down(&ld->sem); + if (ld->props) + if (!ld->props->check_fb || ld->props->check_fb(evdata->info)) + ld->props->set_power(ld, *(int *)evdata->data); + up(&ld->sem); + return 0; +} + +static int lcd_register_fb(struct lcd_device *ld) +{ + memset(&ld->fb_notif, 0, sizeof(&ld->fb_notif)); + ld->fb_notif.notifier_call = fb_notifier_callback; + return fb_register_client(&ld->fb_notif); +} + +static void lcd_unregister_fb(struct lcd_device *ld) +{ + fb_unregister_client(&ld->fb_notif); +} +#else +static int lcd_register_fb(struct lcd_device *ld) +{ + return 0; +} + +static inline void lcd_unregister_fb(struct lcd_device *ld) +{ +} +#endif /* CONFIG_FB */ + static ssize_t lcd_show_power(struct class_device *cdev, char *buf) { int rc; @@ -121,35 +168,12 @@ static struct class lcd_class = { .store = _store, \ } -static struct class_device_attribute lcd_class_device_attributes[] = { +static const struct class_device_attribute lcd_class_device_attributes[] = { DECLARE_ATTR(power, 0644, lcd_show_power, lcd_store_power), DECLARE_ATTR(contrast, 0644, lcd_show_contrast, lcd_store_contrast), DECLARE_ATTR(max_contrast, 0444, lcd_show_max_contrast, NULL), }; -/* This callback gets called when something important happens inside a - * framebuffer driver. We're looking if that important event is blanking, - * and if it is, we're switching lcd power as well ... - */ -static int fb_notifier_callback(struct notifier_block *self, - unsigned long event, void *data) -{ - struct lcd_device *ld; - struct fb_event *evdata =(struct fb_event *)data; - - /* If we aren't interested in this event, skip it immediately ... */ - if (event != FB_EVENT_BLANK) - return 0; - - ld = container_of(self, struct lcd_device, fb_notif); - down(&ld->sem); - if (ld->props) - if (!ld->props->check_fb || ld->props->check_fb(evdata->info)) - ld->props->set_power(ld, *(int *)evdata->data); - up(&ld->sem); - return 0; -} - /** * lcd_device_register - register a new object of lcd_device class. * @name: the name of the new object(must be the same as the name of the @@ -186,10 +210,8 @@ error: kfree(new_ld); return ERR_PTR(rc); } - memset(&new_ld->fb_notif, 0, sizeof(new_ld->fb_notif)); - new_ld->fb_notif.notifier_call = fb_notifier_callback; + rc = lcd_register_fb(new_ld); - rc = fb_register_client(&new_ld->fb_notif); if (unlikely(rc)) goto error; @@ -232,9 +254,7 @@ void lcd_device_unregister(struct lcd_device *ld) down(&ld->sem); ld->props = NULL; up(&ld->sem); - - fb_unregister_client(&ld->fb_notif); - + lcd_unregister_fb(ld); class_device_unregister(&ld->class_dev); } EXPORT_SYMBOL(lcd_device_unregister); diff --git a/trunk/drivers/video/backlight/locomolcd.c b/trunk/drivers/video/backlight/locomolcd.c index 628571c63bac..2d7905410b2a 100644 --- a/trunk/drivers/video/backlight/locomolcd.c +++ b/trunk/drivers/video/backlight/locomolcd.c @@ -200,6 +200,10 @@ static int locomolcd_remove(struct locomo_dev *dev) { unsigned long flags; + locomobl_data.brightness = 0; + locomobl_data.power = 0; + locomolcd_set_intensity(locomolcd_bl_device); + backlight_device_unregister(locomolcd_bl_device); local_irq_save(flags); locomolcd_dev = NULL; diff --git a/trunk/drivers/video/cfbimgblt.c b/trunk/drivers/video/cfbimgblt.c index 51d35386a945..261004473c8e 100644 --- a/trunk/drivers/video/cfbimgblt.c +++ b/trunk/drivers/video/cfbimgblt.c @@ -42,7 +42,7 @@ #define DPRINTK(fmt, args...) #endif -static u32 cfb_tab8[] = { +static const u32 cfb_tab8[] = { #if defined(__BIG_ENDIAN) 0x00000000,0x000000ff,0x0000ff00,0x0000ffff, 0x00ff0000,0x00ff00ff,0x00ffff00,0x00ffffff, @@ -58,7 +58,7 @@ static u32 cfb_tab8[] = { #endif }; -static u32 cfb_tab16[] = { +static const u32 cfb_tab16[] = { #if defined(__BIG_ENDIAN) 0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff #elif defined(__LITTLE_ENDIAN) @@ -68,7 +68,7 @@ static u32 cfb_tab16[] = { #endif }; -static u32 cfb_tab32[] = { +static const u32 cfb_tab32[] = { 0x00000000, 0xffffffff }; @@ -218,7 +218,7 @@ static inline void fast_imageblit(const struct fb_image *image, struct fb_info * u32 bit_mask, end_mask, eorx, shift; const char *s = image->data, *src; u32 __iomem *dst; - u32 *tab = NULL; + const u32 *tab = NULL; int i, j, k; switch (bpp) { diff --git a/trunk/drivers/video/cirrusfb.c b/trunk/drivers/video/cirrusfb.c index daf43f535a0b..2c4bc6205738 100644 --- a/trunk/drivers/video/cirrusfb.c +++ b/trunk/drivers/video/cirrusfb.c @@ -2442,7 +2442,10 @@ static int cirrusfb_pci_register (struct pci_dev *pdev, printk ("Cirrus Logic chipset on PCI bus\n"); pci_set_drvdata(pdev, info); - return cirrusfb_register(cinfo); + ret = cirrusfb_register(cinfo); + if (ret) + iounmap(cinfo->fbmem); + return ret; err_release_legacy: if (release_io_ports) @@ -2574,7 +2577,15 @@ static int cirrusfb_zorro_register(struct zorro_dev *z, printk (KERN_INFO "Cirrus Logic chipset on Zorro bus\n"); zorro_set_drvdata(z, info); - return cirrusfb_register(cinfo); + ret = cirrusfb_register(cinfo); + if (ret) { + if (btype == BT_PICASSO4) { + iounmap(cinfo->fbmem); + iounmap(cinfo->regbase - 0x600000); + } else if (board_addr > 0x01000000) + iounmap(cinfo->fbmem); + } + return ret; err_unmap_regbase: /* Parental advisory: explicit hack */ diff --git a/trunk/drivers/video/console/fbcon.c b/trunk/drivers/video/console/fbcon.c index 302174b8e477..31f476a64790 100644 --- a/trunk/drivers/video/console/fbcon.c +++ b/trunk/drivers/video/console/fbcon.c @@ -383,9 +383,9 @@ static void fbcon_update_softback(struct vc_data *vc) softback_top = 0; } -static void fb_flashcursor(void *private) +static void fb_flashcursor(struct work_struct *work) { - struct fb_info *info = private; + struct fb_info *info = container_of(work, struct fb_info, queue); struct fbcon_ops *ops = info->fbcon_par; struct display *p; struct vc_data *vc = NULL; @@ -442,7 +442,7 @@ static void fbcon_add_cursor_timer(struct fb_info *info) if ((!info->queue.func || info->queue.func == fb_flashcursor) && !(ops->flags & FBCON_FLAGS_CURSOR_TIMER)) { if (!info->queue.func) - INIT_WORK(&info->queue, fb_flashcursor, info); + INIT_WORK(&info->queue, fb_flashcursor); init_timer(&ops->cursor_timer); ops->cursor_timer.function = cursor_timer_handler; diff --git a/trunk/drivers/video/console/softcursor.c b/trunk/drivers/video/console/softcursor.c index 7d07d8383569..f577bd80e020 100644 --- a/trunk/drivers/video/console/softcursor.c +++ b/trunk/drivers/video/console/softcursor.c @@ -1,11 +1,13 @@ /* - * linux/drivers/video/softcursor.c -- Generic software cursor for frame buffer devices + * linux/drivers/video/softcursor.c + * + * Generic software cursor for frame buffer devices * * Created 14 Nov 2002 by James Simmons * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive - * for more details. + * This file is subject to the terms and conditions of the GNU General + * Public License. See the file COPYING in the main directory of this + * archive for more details. */ #include @@ -25,7 +27,7 @@ int soft_cursor(struct fb_info *info, struct fb_cursor *cursor) unsigned int buf_align = info->pixmap.buf_align - 1; unsigned int i, size, dsize, s_pitch, d_pitch; struct fb_image *image; - u8 *dst; + u8 *src, *dst; if (info->state != FBINFO_STATE_RUNNING) return 0; @@ -45,7 +47,8 @@ int soft_cursor(struct fb_info *info, struct fb_cursor *cursor) } } - image = (struct fb_image *) (ops->cursor_src + dsize); + src = ops->cursor_src + sizeof(struct fb_image); + image = (struct fb_image *)ops->cursor_src; *image = cursor->image; d_pitch = (s_pitch + scan_align) & ~scan_align; @@ -57,21 +60,18 @@ int soft_cursor(struct fb_info *info, struct fb_cursor *cursor) switch (cursor->rop) { case ROP_XOR: for (i = 0; i < dsize; i++) - ops->cursor_src[i] = image->data[i] ^ - cursor->mask[i]; + src[i] = image->data[i] ^ cursor->mask[i]; break; case ROP_COPY: default: for (i = 0; i < dsize; i++) - ops->cursor_src[i] = image->data[i] & - cursor->mask[i]; + src[i] = image->data[i] & cursor->mask[i]; break; } } else - memcpy(ops->cursor_src, image->data, dsize); + memcpy(src, image->data, dsize); - fb_pad_aligned_buffer(dst, d_pitch, ops->cursor_src, s_pitch, - image->height); + fb_pad_aligned_buffer(dst, d_pitch, src, s_pitch, image->height); image->data = dst; info->fbops->fb_imageblit(info, image); return 0; diff --git a/trunk/drivers/video/console/sticon.c b/trunk/drivers/video/console/sticon.c index 45586aaabd1e..57b21e533036 100644 --- a/trunk/drivers/video/console/sticon.c +++ b/trunk/drivers/video/console/sticon.c @@ -345,7 +345,7 @@ static void sticon_save_screen(struct vc_data *conp) { } -static struct consw sti_con = { +static const struct consw sti_con = { .owner = THIS_MODULE, .con_startup = sticon_startup, .con_init = sticon_init, diff --git a/trunk/drivers/video/console/vgacon.c b/trunk/drivers/video/console/vgacon.c index 0a2c10a1abf8..4a9bde2c839b 100644 --- a/trunk/drivers/video/console/vgacon.c +++ b/trunk/drivers/video/console/vgacon.c @@ -93,27 +93,27 @@ static void vgacon_invert_region(struct vc_data *c, u16 * p, int count); static unsigned long vgacon_uni_pagedir[2]; /* Description of the hardware situation */ -static unsigned long vga_vram_base; /* Base of video memory */ -static unsigned long vga_vram_end; /* End of video memory */ -static int vga_vram_size; /* Size of video memory */ -static u16 vga_video_port_reg; /* Video register select port */ -static u16 vga_video_port_val; /* Video register value port */ -static unsigned int vga_video_num_columns; /* Number of text columns */ -static unsigned int vga_video_num_lines; /* Number of text lines */ -static int vga_can_do_color = 0; /* Do we support colors? */ -static unsigned int vga_default_font_height;/* Height of default screen font */ -static unsigned char vga_video_type; /* Card type */ -static unsigned char vga_hardscroll_enabled; -static unsigned char vga_hardscroll_user_enable = 1; +static int vga_init_done __read_mostly; +static unsigned long vga_vram_base __read_mostly; /* Base of video memory */ +static unsigned long vga_vram_end __read_mostly; /* End of video memory */ +static unsigned int vga_vram_size __read_mostly; /* Size of video memory */ +static u16 vga_video_port_reg __read_mostly; /* Video register select port */ +static u16 vga_video_port_val __read_mostly; /* Video register value port */ +static unsigned int vga_video_num_columns; /* Number of text columns */ +static unsigned int vga_video_num_lines; /* Number of text lines */ +static int vga_can_do_color __read_mostly; /* Do we support colors? */ +static unsigned int vga_default_font_height __read_mostly; /* Height of default screen font */ +static unsigned char vga_video_type __read_mostly; /* Card type */ +static unsigned char vga_hardscroll_enabled __read_mostly; +static unsigned char vga_hardscroll_user_enable __read_mostly = 1; static unsigned char vga_font_is_default = 1; static int vga_vesa_blanked; static int vga_palette_blanked; static int vga_is_gfx; static int vga_512_chars; static int vga_video_font_height; -static int vga_scan_lines; -static unsigned int vga_rolled_over = 0; -static int vga_init_done; +static int vga_scan_lines __read_mostly; +static unsigned int vga_rolled_over; static int __init no_scroll(char *str) { diff --git a/trunk/drivers/video/cyberfb.c b/trunk/drivers/video/cyberfb.c index c40e72dafb0e..0b8d5b121152 100644 --- a/trunk/drivers/video/cyberfb.c +++ b/trunk/drivers/video/cyberfb.c @@ -109,8 +109,6 @@ static void cv64_dump(void); #define wb_64(regs,reg,dat) (*(((volatile unsigned char *)regs) + reg) = dat) #define rb_64(regs, reg) (*(((volatile unsigned char *)regs) + reg)) -#define ww_64(regs,reg,dat) (*((volatile unsigned short *)(regs + reg) = dat) - struct cyberfb_par { struct fb_var_screeninfo var; __u32 type; @@ -1055,6 +1053,8 @@ int __init cyberfb_init(void) if (register_framebuffer(&fb_info) < 0) { DPRINTK("EXIT - register_framebuffer failed\n"); + if (CyberBase) + iounmap(CyberBase); release_mem_region(CyberMem_phys, 0x400000); release_mem_region(CyberRegs_phys, 0x10000); return -EINVAL; diff --git a/trunk/drivers/video/epson1355fb.c b/trunk/drivers/video/epson1355fb.c index 737257d278f0..29e07c109887 100644 --- a/trunk/drivers/video/epson1355fb.c +++ b/trunk/drivers/video/epson1355fb.c @@ -405,7 +405,7 @@ static inline unsigned long copy_to_user16(void *to, const void *from, static ssize_t epson1355fb_read(struct file *file, char *buf, size_t count, loff_t * ppos) { - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; int fbidx = iminor(inode); struct fb_info *info = registered_fb[fbidx]; unsigned long p = *ppos; @@ -437,7 +437,7 @@ static ssize_t epson1355fb_write(struct file *file, const char *buf, size_t count, loff_t * ppos) { - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; int fbidx = iminor(inode); struct fb_info *info = registered_fb[fbidx]; unsigned long p = *ppos; diff --git a/trunk/drivers/video/fbcmap.c b/trunk/drivers/video/fbcmap.c index e8b135f3d80d..148108afdd51 100644 --- a/trunk/drivers/video/fbcmap.c +++ b/trunk/drivers/video/fbcmap.c @@ -18,63 +18,64 @@ #include -static u16 red2[] = { +static u16 red2[] __read_mostly = { 0x0000, 0xaaaa }; -static u16 green2[] = { +static u16 green2[] __read_mostly = { 0x0000, 0xaaaa }; -static u16 blue2[] = { +static u16 blue2[] __read_mostly = { 0x0000, 0xaaaa }; -static u16 red4[] = { +static u16 red4[] __read_mostly = { 0x0000, 0xaaaa, 0x5555, 0xffff }; -static u16 green4[] = { +static u16 green4[] __read_mostly = { 0x0000, 0xaaaa, 0x5555, 0xffff }; -static u16 blue4[] = { +static u16 blue4[] __read_mostly = { 0x0000, 0xaaaa, 0x5555, 0xffff }; -static u16 red8[] = { +static u16 red8[] __read_mostly = { 0x0000, 0x0000, 0x0000, 0x0000, 0xaaaa, 0xaaaa, 0xaaaa, 0xaaaa }; -static u16 green8[] = { +static u16 green8[] __read_mostly = { 0x0000, 0x0000, 0xaaaa, 0xaaaa, 0x0000, 0x0000, 0x5555, 0xaaaa }; -static u16 blue8[] = { +static u16 blue8[] __read_mostly = { 0x0000, 0xaaaa, 0x0000, 0xaaaa, 0x0000, 0xaaaa, 0x0000, 0xaaaa }; -static u16 red16[] = { +static u16 red16[] __read_mostly = { 0x0000, 0x0000, 0x0000, 0x0000, 0xaaaa, 0xaaaa, 0xaaaa, 0xaaaa, 0x5555, 0x5555, 0x5555, 0x5555, 0xffff, 0xffff, 0xffff, 0xffff }; -static u16 green16[] = { +static u16 green16[] __read_mostly = { 0x0000, 0x0000, 0xaaaa, 0xaaaa, 0x0000, 0x0000, 0x5555, 0xaaaa, 0x5555, 0x5555, 0xffff, 0xffff, 0x5555, 0x5555, 0xffff, 0xffff }; -static u16 blue16[] = { +static u16 blue16[] __read_mostly = { 0x0000, 0xaaaa, 0x0000, 0xaaaa, 0x0000, 0xaaaa, 0x0000, 0xaaaa, 0x5555, 0xffff, 0x5555, 0xffff, 0x5555, 0xffff, 0x5555, 0xffff }; -static struct fb_cmap default_2_colors = { - 0, 2, red2, green2, blue2, NULL +static const struct fb_cmap default_2_colors = { + .len=2, .red=red2, .green=green2, .blue=blue2 }; -static struct fb_cmap default_8_colors = { - 0, 8, red8, green8, blue8, NULL +static const struct fb_cmap default_8_colors = { + .len=8, .red=red8, .green=green8, .blue=blue8 }; -static struct fb_cmap default_4_colors = { - 0, 4, red4, green4, blue4, NULL +static const struct fb_cmap default_4_colors = { + .len=4, .red=red4, .green=green4, .blue=blue4 }; -static struct fb_cmap default_16_colors = { - 0, 16, red16, green16, blue16, NULL +static const struct fb_cmap default_16_colors = { + .len=16, .red=red16, .green=green16, .blue=blue16 }; + /** * fb_alloc_cmap - allocate a colormap * @cmap: frame buffer colormap structure @@ -146,7 +147,7 @@ void fb_dealloc_cmap(struct fb_cmap *cmap) * Copy contents of colormap from @from to @to. */ -int fb_copy_cmap(struct fb_cmap *from, struct fb_cmap *to) +int fb_copy_cmap(const struct fb_cmap *from, struct fb_cmap *to) { int tooff = 0, fromoff = 0; int size; @@ -170,7 +171,7 @@ int fb_copy_cmap(struct fb_cmap *from, struct fb_cmap *to) return 0; } -int fb_cmap_to_user(struct fb_cmap *from, struct fb_cmap_user *to) +int fb_cmap_to_user(const struct fb_cmap *from, struct fb_cmap_user *to) { int tooff = 0, fromoff = 0; int size; @@ -282,7 +283,7 @@ int fb_set_user_cmap(struct fb_cmap_user *cmap, struct fb_info *info) * */ -struct fb_cmap *fb_default_cmap(int len) +const struct fb_cmap *fb_default_cmap(int len) { if (len <= 2) return &default_2_colors; @@ -305,22 +306,22 @@ void fb_invert_cmaps(void) { u_int i; - for (i = 0; i < 2; i++) { + for (i = 0; i < ARRAY_SIZE(red2); i++) { red2[i] = ~red2[i]; green2[i] = ~green2[i]; blue2[i] = ~blue2[i]; } - for (i = 0; i < 4; i++) { + for (i = 0; i < ARRAY_SIZE(red4); i++) { red4[i] = ~red4[i]; green4[i] = ~green4[i]; blue4[i] = ~blue4[i]; } - for (i = 0; i < 8; i++) { + for (i = 0; i < ARRAY_SIZE(red8); i++) { red8[i] = ~red8[i]; green8[i] = ~green8[i]; blue8[i] = ~blue8[i]; } - for (i = 0; i < 16; i++) { + for (i = 0; i < ARRAY_SIZE(red16); i++) { red16[i] = ~red16[i]; green16[i] = ~green16[i]; blue16[i] = ~blue16[i]; diff --git a/trunk/drivers/video/fbcvt.c b/trunk/drivers/video/fbcvt.c index b5498999c4ec..0847c5e72cbd 100644 --- a/trunk/drivers/video/fbcvt.c +++ b/trunk/drivers/video/fbcvt.c @@ -57,7 +57,7 @@ struct fb_cvt_data { u32 status; }; -static int fb_cvt_vbi_tab[] = { +static const unsigned char fb_cvt_vbi_tab[] = { 4, /* 4:3 */ 5, /* 16:9 */ 6, /* 16:10 */ diff --git a/trunk/drivers/video/fbmem.c b/trunk/drivers/video/fbmem.c index e973a87fbb01..3cfea315a48f 100644 --- a/trunk/drivers/video/fbmem.c +++ b/trunk/drivers/video/fbmem.c @@ -52,8 +52,8 @@ #define FBPIXMAPSIZE (1024 * 8) -struct fb_info *registered_fb[FB_MAX]; -int num_registered_fb; +struct fb_info *registered_fb[FB_MAX] __read_mostly; +int num_registered_fb __read_mostly; /* * Helpers @@ -202,7 +202,7 @@ static void fb_set_logo_truepalette(struct fb_info *info, const struct linux_logo *logo, u32 *palette) { - unsigned char mask[9] = { 0,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff }; + static const unsigned char mask[] = { 0,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff }; unsigned char redmask, greenmask, bluemask; int redshift, greenshift, blueshift; int i; @@ -317,7 +317,7 @@ static struct logo_data { int needs_truepalette; int needs_cmapreset; const struct linux_logo *logo; -} fb_logo; +} fb_logo __read_mostly; static void fb_rotate_logo_ud(const u8 *in, u8 *out, u32 width, u32 height) { @@ -572,7 +572,7 @@ static ssize_t fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { unsigned long p = *ppos; - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; int fbidx = iminor(inode); struct fb_info *info = registered_fb[fbidx]; u32 *buffer, *dst; @@ -647,7 +647,7 @@ static ssize_t fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { unsigned long p = *ppos; - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; int fbidx = iminor(inode); struct fb_info *info = registered_fb[fbidx]; u32 *buffer, *src; @@ -1081,7 +1081,7 @@ static int fb_get_fscreeninfo(struct inode *inode, struct file *file, static long fb_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; int fbidx = iminor(inode); struct fb_info *info = registered_fb[fbidx]; struct fb_ops *fb = info->fbops; @@ -1121,7 +1121,7 @@ fb_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) static int fb_mmap(struct file *file, struct vm_area_struct * vma) { - int fbidx = iminor(file->f_dentry->d_inode); + int fbidx = iminor(file->f_path.dentry->d_inode); struct fb_info *info = registered_fb[fbidx]; struct fb_ops *fb = info->fbops; unsigned long off; @@ -1253,7 +1253,7 @@ fb_release(struct inode *inode, struct file *file) return 0; } -static struct file_operations fb_fops = { +static const struct file_operations fb_fops = { .owner = THIS_MODULE, .read = fb_read, .write = fb_write, @@ -1459,8 +1459,8 @@ int fb_new_modelist(struct fb_info *info) return err; } -static char *video_options[FB_MAX]; -static int ofonly; +static char *video_options[FB_MAX] __read_mostly; +static int ofonly __read_mostly; extern const char *global_mode_option; diff --git a/trunk/drivers/video/fbmon.c b/trunk/drivers/video/fbmon.c index de93139ccbb5..6b385c39b8b5 100644 --- a/trunk/drivers/video/fbmon.c +++ b/trunk/drivers/video/fbmon.c @@ -58,7 +58,7 @@ struct broken_edid { u32 fix; }; -static struct broken_edid brokendb[] = { +static const struct broken_edid brokendb[] = { /* DEC FR-PCXAV-YZ */ { .manufacturer = "DEC", diff --git a/trunk/drivers/video/ffb.c b/trunk/drivers/video/ffb.c index 2a0e8210d398..949141bd44d4 100644 --- a/trunk/drivers/video/ffb.c +++ b/trunk/drivers/video/ffb.c @@ -968,6 +968,8 @@ static int ffb_init_one(struct of_device *op) if (fb_alloc_cmap(&all->info.cmap, 256, 0)) { printk(KERN_ERR "ffb: Could not allocate color map.\n"); + of_iounmap(all->par.fbc, sizeof(struct ffb_fbc)); + of_iounmap(all->par.dac, sizeof(struct ffb_dac)); kfree(all); return -ENOMEM; } @@ -978,6 +980,8 @@ static int ffb_init_one(struct of_device *op) if (err < 0) { printk(KERN_ERR "ffb: Could not register framebuffer.\n"); fb_dealloc_cmap(&all->info.cmap); + of_iounmap(all->par.fbc, sizeof(struct ffb_fbc)); + of_iounmap(all->par.dac, sizeof(struct ffb_dac)); kfree(all); return err; } diff --git a/trunk/drivers/video/fm2fb.c b/trunk/drivers/video/fm2fb.c index 998374cfae6d..70ff55b14596 100644 --- a/trunk/drivers/video/fm2fb.c +++ b/trunk/drivers/video/fm2fb.c @@ -283,6 +283,7 @@ static int __devinit fm2fb_probe(struct zorro_dev *z, if (register_framebuffer(info) < 0) { fb_dealloc_cmap(&info->cmap); + iounmap(info->screen_base); framebuffer_release(info); zorro_release_device(z); return -EINVAL; diff --git a/trunk/drivers/video/geode/Kconfig b/trunk/drivers/video/geode/Kconfig index 4e173ef20a7d..a814b6c2605c 100644 --- a/trunk/drivers/video/geode/Kconfig +++ b/trunk/drivers/video/geode/Kconfig @@ -23,6 +23,26 @@ config FB_GEODE_GX If unsure, say N. +config FB_GEODE_GX_SET_FBSIZE + bool "Manually specify the Geode GX framebuffer size" + depends on FB_GEODE_GX + default n + ---help--- + If you want to manually specify the size of your GX framebuffer, + say Y here, otherwise say N to dynamically probe it. + + Say N unless you know what you are doing. + +config FB_GEODE_GX_FBSIZE + hex "Size of the GX framebuffer, in bytes" + depends on FB_GEODE_GX_SET_FBSIZE + default "0x1600000" + ---help--- + Specify the size of the GX framebuffer. Normally, you will + want this to be MB aligned. Common values are 0x80000 (8MB) + and 0x1600000 (16MB). Don't change this unless you know what + you are doing + config FB_GEODE_GX1 tristate "AMD Geode GX1 framebuffer support (EXPERIMENTAL)" depends on FB && FB_GEODE && EXPERIMENTAL diff --git a/trunk/drivers/video/geode/display_gx.c b/trunk/drivers/video/geode/display_gx.c index 825c3405f5c2..0f16e4bffc6c 100644 --- a/trunk/drivers/video/geode/display_gx.c +++ b/trunk/drivers/video/geode/display_gx.c @@ -21,11 +21,27 @@ #include "geodefb.h" #include "display_gx.h" -int gx_frame_buffer_size(void) +#ifdef CONFIG_FB_GEODE_GX_SET_FBSIZE +unsigned int gx_frame_buffer_size(void) { - /* Assuming 16 MiB. */ - return 16*1024*1024; + return CONFIG_FB_GEODE_GX_FBSIZE; } +#else +unsigned int gx_frame_buffer_size(void) +{ + unsigned int val; + + /* FB size is reported by a virtual register */ + /* Virtual register class = 0x02 */ + /* VG_MEM_SIZE(512Kb units) = 0x00 */ + + outw(0xFC53, 0xAC1C); + outw(0x0200, 0xAC1C); + + val = (unsigned int)(inw(0xAC1E)) & 0xFFl; + return (val << 19); +} +#endif int gx_line_delta(int xres, int bpp) { @@ -81,6 +97,7 @@ static void gx_set_mode(struct fb_info *info) writel(((info->var.xres * info->var.bits_per_pixel/8) >> 3) + 2, par->dc_regs + DC_LINE_SIZE); + /* Enable graphics and video data and unmask address lines. */ dcfg |= DC_DCFG_GDEN | DC_DCFG_VDEN | DC_DCFG_A20M | DC_DCFG_A18M; diff --git a/trunk/drivers/video/geode/display_gx.h b/trunk/drivers/video/geode/display_gx.h index 86c623361305..0af33f329e88 100644 --- a/trunk/drivers/video/geode/display_gx.h +++ b/trunk/drivers/video/geode/display_gx.h @@ -11,11 +11,15 @@ #ifndef __DISPLAY_GX_H__ #define __DISPLAY_GX_H__ -int gx_frame_buffer_size(void); +unsigned int gx_frame_buffer_size(void); int gx_line_delta(int xres, int bpp); extern struct geode_dc_ops gx_dc_ops; +/* MSR that tells us if a TFT or CRT is attached */ +#define GLD_MSR_CONFIG 0xC0002001 +#define GLD_MSR_CONFIG_DM_FP 0x40 + /* Display controller registers */ #define DC_UNLOCK 0x00 @@ -93,4 +97,5 @@ extern struct geode_dc_ops gx_dc_ops; #define DC_PAL_ADDRESS 0x70 #define DC_PAL_DATA 0x74 +#define DC_GLIU0_MEM_OFFSET 0x84 #endif /* !__DISPLAY_GX1_H__ */ diff --git a/trunk/drivers/video/geode/gxfb_core.c b/trunk/drivers/video/geode/gxfb_core.c index 0d3643fc6293..cf841efa229a 100644 --- a/trunk/drivers/video/geode/gxfb_core.c +++ b/trunk/drivers/video/geode/gxfb_core.c @@ -35,10 +35,10 @@ #include "display_gx.h" #include "video_gx.h" -static char mode_option[32] = "640x480-16@60"; +static char *mode_option; /* Modes relevant to the GX (taken from modedb.c) */ -static const struct fb_videomode __initdata gx_modedb[] = { +static const struct fb_videomode gx_modedb[] __initdata = { /* 640x480-60 VESA */ { NULL, 60, 640, 480, 39682, 48, 16, 33, 10, 96, 2, 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, @@ -240,6 +240,12 @@ static int __init gxfb_map_video_memory(struct fb_info *info, struct pci_dev *de if (!info->screen_base) return -ENOMEM; + /* Set the 16MB aligned base address of the graphics memory region + * in the display controller */ + + writel(info->fix.smem_start & 0xFF000000, + par->dc_regs + DC_GLIU0_MEM_OFFSET); + dev_info(&dev->dev, "%d Kibyte of video memory at 0x%lx\n", info->fix.smem_len / 1024, info->fix.smem_start); @@ -302,6 +308,7 @@ static int __init gxfb_probe(struct pci_dev *pdev, const struct pci_device_id *i struct geodefb_par *par; struct fb_info *info; int ret; + unsigned long val; info = gxfb_init_fbinfo(&pdev->dev); if (!info) @@ -317,6 +324,15 @@ static int __init gxfb_probe(struct pci_dev *pdev, const struct pci_device_id *i goto err; } + /* Figure out if this is a TFT or CRT part */ + + rdmsrl(GLD_MSR_CONFIG, val); + + if ((val & GLD_MSR_CONFIG_DM_FP) == GLD_MSR_CONFIG_DM_FP) + par->enable_crt = 0; + else + par->enable_crt = 1; + ret = fb_find_mode(&info->var, info, mode_option, gx_modedb, ARRAY_SIZE(gx_modedb), NULL, 16); if (ret == 0 || ret == 4) { @@ -325,7 +341,8 @@ static int __init gxfb_probe(struct pci_dev *pdev, const struct pci_device_id *i goto err; } - /* Clear the frame buffer of garbage. */ + + /* Clear the frame buffer of garbage. */ memset_io(info->screen_base, 0, info->fix.smem_len); gxfb_check_var(&info->var, info); @@ -380,7 +397,7 @@ static void gxfb_remove(struct pci_dev *pdev) } static struct pci_device_id gxfb_id_table[] = { - { PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_CS5535_VIDEO, + { PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_GX_VIDEO, PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16, 0xff0000, 0 }, { 0, } @@ -395,11 +412,35 @@ static struct pci_driver gxfb_driver = { .remove = gxfb_remove, }; +#ifndef MODULE +static int __init gxfb_setup(char *options) +{ + + char *opt; + + if (!options || !*options) + return 0; + + while ((opt = strsep(&options, ",")) != NULL) { + if (!*opt) + continue; + + mode_option = opt; + } + + return 0; +} +#endif + static int __init gxfb_init(void) { #ifndef MODULE - if (fb_get_options("gxfb", NULL)) + char *option = NULL; + + if (fb_get_options("gxfb", &option)) return -ENODEV; + + gxfb_setup(option); #endif return pci_register_driver(&gxfb_driver); } @@ -412,8 +453,8 @@ static void __exit gxfb_cleanup(void) module_init(gxfb_init); module_exit(gxfb_cleanup); -module_param_string(mode, mode_option, sizeof(mode_option), 0444); -MODULE_PARM_DESC(mode, "video mode (x[-][@])"); +module_param(mode_option, charp, 0); +MODULE_PARM_DESC(mode_option, "video mode (x[-][@])"); MODULE_DESCRIPTION("Framebuffer driver for the AMD Geode GX"); MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/video/geode/video_gx.c b/trunk/drivers/video/geode/video_gx.c index 2b2a7880ea75..7f3f18d06718 100644 --- a/trunk/drivers/video/geode/video_gx.c +++ b/trunk/drivers/video/geode/video_gx.c @@ -175,13 +175,88 @@ static void gx_set_dclk_frequency(struct fb_info *info) } while (timeout-- && !(dotpll & MSR_GLCP_DOTPLL_LOCK)); } +static void +gx_configure_tft(struct fb_info *info) +{ + struct geodefb_par *par = info->par; + unsigned long val; + unsigned long fp; + + /* Set up the DF pad select MSR */ + + rdmsrl(GX_VP_MSR_PAD_SELECT, val); + val &= ~GX_VP_PAD_SELECT_MASK; + val |= GX_VP_PAD_SELECT_TFT; + wrmsrl(GX_VP_MSR_PAD_SELECT, val); + + /* Turn off the panel */ + + fp = readl(par->vid_regs + GX_FP_PM); + fp &= ~GX_FP_PM_P; + writel(fp, par->vid_regs + GX_FP_PM); + + /* Set timing 1 */ + + fp = readl(par->vid_regs + GX_FP_PT1); + fp &= GX_FP_PT1_VSIZE_MASK; + fp |= info->var.yres << GX_FP_PT1_VSIZE_SHIFT; + writel(fp, par->vid_regs + GX_FP_PT1); + + /* Timing 2 */ + /* Set bits that are always on for TFT */ + + fp = 0x0F100000; + + /* Add sync polarity */ + + if (!(info->var.sync & FB_SYNC_VERT_HIGH_ACT)) + fp |= GX_FP_PT2_VSP; + + if (!(info->var.sync & FB_SYNC_HOR_HIGH_ACT)) + fp |= GX_FP_PT2_HSP; + + writel(fp, par->vid_regs + GX_FP_PT2); + + /* Set the dither control */ + writel(0x70, par->vid_regs + GX_FP_DFC); + + /* Enable the FP data and power (in case the BIOS didn't) */ + + fp = readl(par->vid_regs + GX_DCFG); + fp |= GX_DCFG_FP_PWR_EN | GX_DCFG_FP_DATA_EN; + writel(fp, par->vid_regs + GX_DCFG); + + /* Unblank the panel */ + + fp = readl(par->vid_regs + GX_FP_PM); + fp |= GX_FP_PM_P; + writel(fp, par->vid_regs + GX_FP_PM); +} + static void gx_configure_display(struct fb_info *info) { struct geodefb_par *par = info->par; - u32 dcfg, fp_pm; + u32 dcfg, misc; + + /* Set up the MISC register */ + + misc = readl(par->vid_regs + GX_MISC); + + /* Power up the DAC */ + misc &= ~(GX_MISC_A_PWRDN | GX_MISC_DAC_PWRDN); + + /* Disable gamma correction */ + misc |= GX_MISC_GAM_EN; + + writel(misc, par->vid_regs + GX_MISC); + /* Write the display configuration */ dcfg = readl(par->vid_regs + GX_DCFG); + /* Disable hsync and vsync */ + dcfg &= ~(GX_DCFG_VSYNC_EN | GX_DCFG_HSYNC_EN); + writel(dcfg, par->vid_regs + GX_DCFG); + /* Clear bits from existing mode. */ dcfg &= ~(GX_DCFG_CRT_SYNC_SKW_MASK | GX_DCFG_CRT_HSYNC_POL | GX_DCFG_CRT_VSYNC_POL @@ -199,12 +274,19 @@ static void gx_configure_display(struct fb_info *info) if (info->var.sync & FB_SYNC_VERT_HIGH_ACT) dcfg |= GX_DCFG_CRT_VSYNC_POL; + /* Enable the display logic */ + /* Set up the DACS to blank normally */ + + dcfg |= GX_DCFG_CRT_EN | GX_DCFG_DAC_BL_EN; + + /* Enable the external DAC VREF? */ + writel(dcfg, par->vid_regs + GX_DCFG); - /* Power on flat panel. */ - fp_pm = readl(par->vid_regs + GX_FP_PM); - fp_pm |= GX_FP_PM_P; - writel(fp_pm, par->vid_regs + GX_FP_PM); + /* Set up the flat panel (if it is enabled) */ + + if (par->enable_crt == 0) + gx_configure_tft(info); } static int gx_blank_display(struct fb_info *info, int blank_mode) @@ -245,12 +327,15 @@ static int gx_blank_display(struct fb_info *info, int blank_mode) writel(dcfg, par->vid_regs + GX_DCFG); /* Power on/off flat panel. */ - fp_pm = readl(par->vid_regs + GX_FP_PM); - if (blank_mode == FB_BLANK_POWERDOWN) - fp_pm &= ~GX_FP_PM_P; - else - fp_pm |= GX_FP_PM_P; - writel(fp_pm, par->vid_regs + GX_FP_PM); + + if (par->enable_crt == 0) { + fp_pm = readl(par->vid_regs + GX_FP_PM); + if (blank_mode == FB_BLANK_POWERDOWN) + fp_pm &= ~GX_FP_PM_P; + else + fp_pm |= GX_FP_PM_P; + writel(fp_pm, par->vid_regs + GX_FP_PM); + } return 0; } diff --git a/trunk/drivers/video/geode/video_gx.h b/trunk/drivers/video/geode/video_gx.h index 2d9211f3ed84..ce28d8f382dc 100644 --- a/trunk/drivers/video/geode/video_gx.h +++ b/trunk/drivers/video/geode/video_gx.h @@ -13,6 +13,11 @@ extern struct geode_vid_ops gx_vid_ops; +/* GX Flatpanel control MSR */ +#define GX_VP_MSR_PAD_SELECT 0xC0002011 +#define GX_VP_PAD_SELECT_MASK 0x3FFFFFFF +#define GX_VP_PAD_SELECT_TFT 0x1FFFFFFF + /* Geode GX video processor registers */ #define GX_DCFG 0x0008 @@ -20,6 +25,8 @@ extern struct geode_vid_ops gx_vid_ops; # define GX_DCFG_HSYNC_EN 0x00000002 # define GX_DCFG_VSYNC_EN 0x00000004 # define GX_DCFG_DAC_BL_EN 0x00000008 +# define GX_DCFG_FP_PWR_EN 0x00000040 +# define GX_DCFG_FP_DATA_EN 0x00000080 # define GX_DCFG_CRT_HSYNC_POL 0x00000100 # define GX_DCFG_CRT_VSYNC_POL 0x00000200 # define GX_DCFG_CRT_SYNC_SKW_MASK 0x0001C000 @@ -28,10 +35,28 @@ extern struct geode_vid_ops gx_vid_ops; # define GX_DCFG_GV_GAM 0x00200000 # define GX_DCFG_DAC_VREF 0x04000000 +/* Geode GX MISC video configuration */ + +#define GX_MISC 0x50 +#define GX_MISC_GAM_EN 0x00000001 +#define GX_MISC_DAC_PWRDN 0x00000400 +#define GX_MISC_A_PWRDN 0x00000800 + /* Geode GX flat panel display control registers */ + +#define GX_FP_PT1 0x0400 +#define GX_FP_PT1_VSIZE_MASK 0x7FF0000 +#define GX_FP_PT1_VSIZE_SHIFT 16 + +#define GX_FP_PT2 0x408 +#define GX_FP_PT2_VSP (1 << 23) +#define GX_FP_PT2_HSP (1 << 22) + #define GX_FP_PM 0x410 # define GX_FP_PM_P 0x01000000 +#define GX_FP_DFC 0x418 + /* Geode GX clock control MSRs */ #define MSR_GLCP_SYS_RSTPLL 0x4c000014 diff --git a/trunk/drivers/video/hpfb.c b/trunk/drivers/video/hpfb.c index 91cf3b577d15..9ab9b839a0f5 100644 --- a/trunk/drivers/video/hpfb.c +++ b/trunk/drivers/video/hpfb.c @@ -295,6 +295,8 @@ static int __init hpfb_init_one(unsigned long phys_base, unsigned long virt_base if (register_framebuffer(&fb_info) < 0) { fb_dealloc_cmap(&fb_info.cmap); + iounmap(fb_info.screen_base); + fb_info.screen_base = NULL; return 1; } diff --git a/trunk/drivers/video/i810/i810-i2c.c b/trunk/drivers/video/i810/i810-i2c.c index b38d805db313..b952e4504abe 100644 --- a/trunk/drivers/video/i810/i810-i2c.c +++ b/trunk/drivers/video/i810/i810-i2c.c @@ -162,9 +162,7 @@ int i810_probe_i2c_connector(struct fb_info *info, u8 **out_edid, int conn) if (e != NULL) { DPRINTK("i810-i2c: Getting EDID from BIOS\n"); - edid = kmalloc(EDID_LENGTH, GFP_KERNEL); - if (edid) - memcpy(edid, e, EDID_LENGTH); + edid = kmemdup(e, EDID_LENGTH, GFP_KERNEL); } } diff --git a/trunk/drivers/video/igafb.c b/trunk/drivers/video/igafb.c index e6df492c22a5..655ae0fa99ca 100644 --- a/trunk/drivers/video/igafb.c +++ b/trunk/drivers/video/igafb.c @@ -384,19 +384,21 @@ int __init igafb_init(void) if (!con_is_present()) return -ENXIO; - pdev = pci_find_device(PCI_VENDOR_ID_INTERG, + pdev = pci_get_device(PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_1682, 0); if (pdev == NULL) { /* * XXX We tried to use cyber2000fb.c for IGS 2000. * But it does not initialize the chip in JavaStation-E, alas. */ - pdev = pci_find_device(PCI_VENDOR_ID_INTERG, 0x2000, 0); + pdev = pci_get_device(PCI_VENDOR_ID_INTERG, 0x2000, 0); if(pdev == NULL) { return -ENXIO; } iga2000 = 1; } + /* We leak a reference here but as it cannot be unloaded this is + fine. If you write unload code remember to free it in unload */ size = sizeof(struct fb_info) + sizeof(struct iga_par) + sizeof(u32)*16; diff --git a/trunk/drivers/video/intelfb/intelfbdrv.c b/trunk/drivers/video/intelfb/intelfbdrv.c index 6f9de04193d2..664fc5cf962a 100644 --- a/trunk/drivers/video/intelfb/intelfbdrv.c +++ b/trunk/drivers/video/intelfb/intelfbdrv.c @@ -1058,10 +1058,9 @@ intelfb_init_var(struct intelfb_info *dinfo) u8 *edid_d = NULL; if (edid_s) { - edid_d = kmalloc(EDID_LENGTH, GFP_KERNEL); + edid_d = kmemdup(edid_s, EDID_LENGTH, GFP_KERNEL); if (edid_d) { - memcpy(edid_d, edid_s, EDID_LENGTH); fb_edid_to_monspecs(edid_d, &dinfo->info->monspecs); kfree(edid_d); diff --git a/trunk/drivers/video/macfb.c b/trunk/drivers/video/macfb.c index 80a043807161..180d94c2b4d2 100644 --- a/trunk/drivers/video/macfb.c +++ b/trunk/drivers/video/macfb.c @@ -608,6 +608,22 @@ void __init macfb_setup(char *options) } } +static void __init iounmap_macfb(void) +{ + if (valkyrie_cmap_regs) + iounmap(valkyrie_cmap_regs); + if (dafb_cmap_regs) + iounmap(dafb_cmap_regs); + if (v8_brazil_cmap_regs) + iounmap(v8_brazil_cmap_regs); + if (rbv_cmap_regs) + iounmap(rbv_cmap_regs); + if (civic_cmap_regs) + iounmap(civic_cmap_regs); + if (csc_cmap_regs) + iounmap(csc_cmap_regs); +} + static int __init macfb_init(void) { int video_cmap_len, video_is_nubus = 0; @@ -962,6 +978,10 @@ static int __init macfb_init(void) if (!err) printk("fb%d: %s frame buffer device\n", fb_info.node, fb_info.fix.id); + else { + iounmap(fb_info.screen_base); + iounmap_macfb(); + } return err; } diff --git a/trunk/drivers/video/mbx/mbxdebugfs.c b/trunk/drivers/video/mbx/mbxdebugfs.c index 84aab3ad024e..472a3ca3d92d 100644 --- a/trunk/drivers/video/mbx/mbxdebugfs.c +++ b/trunk/drivers/video/mbx/mbxdebugfs.c @@ -10,6 +10,8 @@ struct mbxfb_debugfs_data { struct dentry *clock; struct dentry *display; struct dentry *gsctl; + struct dentry *sdram; + struct dentry *misc; }; static int open_file_generic(struct inode *inode, struct file *file) @@ -29,11 +31,11 @@ static ssize_t sysconf_read_file(struct file *file, char __user *userbuf, { char * s = big_buffer; - s += sprintf(s, "SYSCFG = %08lx\n", SYSCFG); - s += sprintf(s, "PFBASE = %08lx\n", PFBASE); - s += sprintf(s, "PFCEIL = %08lx\n", PFCEIL); - s += sprintf(s, "POLLFLAG = %08lx\n", POLLFLAG); - s += sprintf(s, "SYSRST = %08lx\n", SYSRST); + s += sprintf(s, "SYSCFG = %08x\n", readl(SYSCFG)); + s += sprintf(s, "PFBASE = %08x\n", readl(PFBASE)); + s += sprintf(s, "PFCEIL = %08x\n", readl(PFCEIL)); + s += sprintf(s, "POLLFLAG = %08x\n", readl(POLLFLAG)); + s += sprintf(s, "SYSRST = %08x\n", readl(SYSRST)); return simple_read_from_buffer(userbuf, count, ppos, big_buffer, s-big_buffer); @@ -45,24 +47,24 @@ static ssize_t gsctl_read_file(struct file *file, char __user *userbuf, { char * s = big_buffer; - s += sprintf(s, "GSCTRL = %08lx\n", GSCTRL); - s += sprintf(s, "VSCTRL = %08lx\n", VSCTRL); - s += sprintf(s, "GBBASE = %08lx\n", GBBASE); - s += sprintf(s, "VBBASE = %08lx\n", VBBASE); - s += sprintf(s, "GDRCTRL = %08lx\n", GDRCTRL); - s += sprintf(s, "VCMSK = %08lx\n", VCMSK); - s += sprintf(s, "GSCADR = %08lx\n", GSCADR); - s += sprintf(s, "VSCADR = %08lx\n", VSCADR); - s += sprintf(s, "VUBASE = %08lx\n", VUBASE); - s += sprintf(s, "VVBASE = %08lx\n", VVBASE); - s += sprintf(s, "GSADR = %08lx\n", GSADR); - s += sprintf(s, "VSADR = %08lx\n", VSADR); - s += sprintf(s, "HCCTRL = %08lx\n", HCCTRL); - s += sprintf(s, "HCSIZE = %08lx\n", HCSIZE); - s += sprintf(s, "HCPOS = %08lx\n", HCPOS); - s += sprintf(s, "HCBADR = %08lx\n", HCBADR); - s += sprintf(s, "HCCKMSK = %08lx\n", HCCKMSK); - s += sprintf(s, "GPLUT = %08lx\n", GPLUT); + s += sprintf(s, "GSCTRL = %08x\n", readl(GSCTRL)); + s += sprintf(s, "VSCTRL = %08x\n", readl(VSCTRL)); + s += sprintf(s, "GBBASE = %08x\n", readl(GBBASE)); + s += sprintf(s, "VBBASE = %08x\n", readl(VBBASE)); + s += sprintf(s, "GDRCTRL = %08x\n", readl(GDRCTRL)); + s += sprintf(s, "VCMSK = %08x\n", readl(VCMSK)); + s += sprintf(s, "GSCADR = %08x\n", readl(GSCADR)); + s += sprintf(s, "VSCADR = %08x\n", readl(VSCADR)); + s += sprintf(s, "VUBASE = %08x\n", readl(VUBASE)); + s += sprintf(s, "VVBASE = %08x\n", readl(VVBASE)); + s += sprintf(s, "GSADR = %08x\n", readl(GSADR)); + s += sprintf(s, "VSADR = %08x\n", readl(VSADR)); + s += sprintf(s, "HCCTRL = %08x\n", readl(HCCTRL)); + s += sprintf(s, "HCSIZE = %08x\n", readl(HCSIZE)); + s += sprintf(s, "HCPOS = %08x\n", readl(HCPOS)); + s += sprintf(s, "HCBADR = %08x\n", readl(HCBADR)); + s += sprintf(s, "HCCKMSK = %08x\n", readl(HCCKMSK)); + s += sprintf(s, "GPLUT = %08x\n", readl(GPLUT)); return simple_read_from_buffer(userbuf, count, ppos, big_buffer, s-big_buffer); @@ -73,36 +75,36 @@ static ssize_t display_read_file(struct file *file, char __user *userbuf, { char * s = big_buffer; - s += sprintf(s, "DSCTRL = %08lx\n", DSCTRL); - s += sprintf(s, "DHT01 = %08lx\n", DHT01); - s += sprintf(s, "DHT02 = %08lx\n", DHT02); - s += sprintf(s, "DHT03 = %08lx\n", DHT03); - s += sprintf(s, "DVT01 = %08lx\n", DVT01); - s += sprintf(s, "DVT02 = %08lx\n", DVT02); - s += sprintf(s, "DVT03 = %08lx\n", DVT03); - s += sprintf(s, "DBCOL = %08lx\n", DBCOL); - s += sprintf(s, "BGCOLOR = %08lx\n", BGCOLOR); - s += sprintf(s, "DINTRS = %08lx\n", DINTRS); - s += sprintf(s, "DINTRE = %08lx\n", DINTRE); - s += sprintf(s, "DINTRCNT = %08lx\n", DINTRCNT); - s += sprintf(s, "DSIG = %08lx\n", DSIG); - s += sprintf(s, "DMCTRL = %08lx\n", DMCTRL); - s += sprintf(s, "CLIPCTRL = %08lx\n", CLIPCTRL); - s += sprintf(s, "SPOCTRL = %08lx\n", SPOCTRL); - s += sprintf(s, "SVCTRL = %08lx\n", SVCTRL); - s += sprintf(s, "DLSTS = %08lx\n", DLSTS); - s += sprintf(s, "DLLCTRL = %08lx\n", DLLCTRL); - s += sprintf(s, "DVLNUM = %08lx\n", DVLNUM); - s += sprintf(s, "DUCTRL = %08lx\n", DUCTRL); - s += sprintf(s, "DVECTRL = %08lx\n", DVECTRL); - s += sprintf(s, "DHDET = %08lx\n", DHDET); - s += sprintf(s, "DVDET = %08lx\n", DVDET); - s += sprintf(s, "DODMSK = %08lx\n", DODMSK); - s += sprintf(s, "CSC01 = %08lx\n", CSC01); - s += sprintf(s, "CSC02 = %08lx\n", CSC02); - s += sprintf(s, "CSC03 = %08lx\n", CSC03); - s += sprintf(s, "CSC04 = %08lx\n", CSC04); - s += sprintf(s, "CSC05 = %08lx\n", CSC05); + s += sprintf(s, "DSCTRL = %08x\n", readl(DSCTRL)); + s += sprintf(s, "DHT01 = %08x\n", readl(DHT01)); + s += sprintf(s, "DHT02 = %08x\n", readl(DHT02)); + s += sprintf(s, "DHT03 = %08x\n", readl(DHT03)); + s += sprintf(s, "DVT01 = %08x\n", readl(DVT01)); + s += sprintf(s, "DVT02 = %08x\n", readl(DVT02)); + s += sprintf(s, "DVT03 = %08x\n", readl(DVT03)); + s += sprintf(s, "DBCOL = %08x\n", readl(DBCOL)); + s += sprintf(s, "BGCOLOR = %08x\n", readl(BGCOLOR)); + s += sprintf(s, "DINTRS = %08x\n", readl(DINTRS)); + s += sprintf(s, "DINTRE = %08x\n", readl(DINTRE)); + s += sprintf(s, "DINTRCNT = %08x\n", readl(DINTRCNT)); + s += sprintf(s, "DSIG = %08x\n", readl(DSIG)); + s += sprintf(s, "DMCTRL = %08x\n", readl(DMCTRL)); + s += sprintf(s, "CLIPCTRL = %08x\n", readl(CLIPCTRL)); + s += sprintf(s, "SPOCTRL = %08x\n", readl(SPOCTRL)); + s += sprintf(s, "SVCTRL = %08x\n", readl(SVCTRL)); + s += sprintf(s, "DLSTS = %08x\n", readl(DLSTS)); + s += sprintf(s, "DLLCTRL = %08x\n", readl(DLLCTRL)); + s += sprintf(s, "DVLNUM = %08x\n", readl(DVLNUM)); + s += sprintf(s, "DUCTRL = %08x\n", readl(DUCTRL)); + s += sprintf(s, "DVECTRL = %08x\n", readl(DVECTRL)); + s += sprintf(s, "DHDET = %08x\n", readl(DHDET)); + s += sprintf(s, "DVDET = %08x\n", readl(DVDET)); + s += sprintf(s, "DODMSK = %08x\n", readl(DODMSK)); + s += sprintf(s, "CSC01 = %08x\n", readl(CSC01)); + s += sprintf(s, "CSC02 = %08x\n", readl(CSC02)); + s += sprintf(s, "CSC03 = %08x\n", readl(CSC03)); + s += sprintf(s, "CSC04 = %08x\n", readl(CSC04)); + s += sprintf(s, "CSC05 = %08x\n", readl(CSC05)); return simple_read_from_buffer(userbuf, count, ppos, big_buffer, s-big_buffer); @@ -113,24 +115,61 @@ static ssize_t clock_read_file(struct file *file, char __user *userbuf, { char * s = big_buffer; - s += sprintf(s, "SYSCLKSRC = %08lx\n", SYSCLKSRC); - s += sprintf(s, "PIXCLKSRC = %08lx\n", PIXCLKSRC); - s += sprintf(s, "CLKSLEEP = %08lx\n", CLKSLEEP); - s += sprintf(s, "COREPLL = %08lx\n", COREPLL); - s += sprintf(s, "DISPPLL = %08lx\n", DISPPLL); - s += sprintf(s, "PLLSTAT = %08lx\n", PLLSTAT); - s += sprintf(s, "VOVRCLK = %08lx\n", VOVRCLK); - s += sprintf(s, "PIXCLK = %08lx\n", PIXCLK); - s += sprintf(s, "MEMCLK = %08lx\n", MEMCLK); - s += sprintf(s, "M24CLK = %08lx\n", M24CLK); - s += sprintf(s, "MBXCLK = %08lx\n", MBXCLK); - s += sprintf(s, "SDCLK = %08lx\n", SDCLK); - s += sprintf(s, "PIXCLKDIV = %08lx\n", PIXCLKDIV); + s += sprintf(s, "SYSCLKSRC = %08x\n", readl(SYSCLKSRC)); + s += sprintf(s, "PIXCLKSRC = %08x\n", readl(PIXCLKSRC)); + s += sprintf(s, "CLKSLEEP = %08x\n", readl(CLKSLEEP)); + s += sprintf(s, "COREPLL = %08x\n", readl(COREPLL)); + s += sprintf(s, "DISPPLL = %08x\n", readl(DISPPLL)); + s += sprintf(s, "PLLSTAT = %08x\n", readl(PLLSTAT)); + s += sprintf(s, "VOVRCLK = %08x\n", readl(VOVRCLK)); + s += sprintf(s, "PIXCLK = %08x\n", readl(PIXCLK)); + s += sprintf(s, "MEMCLK = %08x\n", readl(MEMCLK)); + s += sprintf(s, "M24CLK = %08x\n", readl(M24CLK)); + s += sprintf(s, "MBXCLK = %08x\n", readl(MBXCLK)); + s += sprintf(s, "SDCLK = %08x\n", readl(SDCLK)); + s += sprintf(s, "PIXCLKDIV = %08x\n", readl(PIXCLKDIV)); return simple_read_from_buffer(userbuf, count, ppos, big_buffer, s-big_buffer); } +static ssize_t sdram_read_file(struct file *file, char __user *userbuf, + size_t count, loff_t *ppos) +{ + char * s = big_buffer; + + s += sprintf(s, "LMRST = %08x\n", readl(LMRST)); + s += sprintf(s, "LMCFG = %08x\n", readl(LMCFG)); + s += sprintf(s, "LMPWR = %08x\n", readl(LMPWR)); + s += sprintf(s, "LMPWRSTAT = %08x\n", readl(LMPWRSTAT)); + s += sprintf(s, "LMCEMR = %08x\n", readl(LMCEMR)); + s += sprintf(s, "LMTYPE = %08x\n", readl(LMTYPE)); + s += sprintf(s, "LMTIM = %08x\n", readl(LMTIM)); + s += sprintf(s, "LMREFRESH = %08x\n", readl(LMREFRESH)); + s += sprintf(s, "LMPROTMIN = %08x\n", readl(LMPROTMIN)); + s += sprintf(s, "LMPROTMAX = %08x\n", readl(LMPROTMAX)); + s += sprintf(s, "LMPROTCFG = %08x\n", readl(LMPROTCFG)); + s += sprintf(s, "LMPROTERR = %08x\n", readl(LMPROTERR)); + + return simple_read_from_buffer(userbuf, count, ppos, + big_buffer, s-big_buffer); +} + +static ssize_t misc_read_file(struct file *file, char __user *userbuf, + size_t count, loff_t *ppos) +{ + char * s = big_buffer; + + s += sprintf(s, "LCD_CONFIG = %08x\n", readl(LCD_CONFIG)); + s += sprintf(s, "ODFBPWR = %08x\n", readl(ODFBPWR)); + s += sprintf(s, "ODFBSTAT = %08x\n", readl(ODFBSTAT)); + s += sprintf(s, "ID = %08x\n", readl(ID)); + + return simple_read_from_buffer(userbuf, count, ppos, + big_buffer, s-big_buffer); +} + + static struct file_operations sysconf_fops = { .read = sysconf_read_file, .write = write_file_dummy, @@ -155,6 +194,17 @@ static struct file_operations gsctl_fops = { .open = open_file_generic, }; +static struct file_operations sdram_fops = { + .read = sdram_read_file, + .write = write_file_dummy, + .open = open_file_generic, +}; + +static struct file_operations misc_fops = { + .read = misc_read_file, + .write = write_file_dummy, + .open = open_file_generic, +}; static void __devinit mbxfb_debugfs_init(struct fb_info *fbi) { @@ -173,6 +223,10 @@ static void __devinit mbxfb_debugfs_init(struct fb_info *fbi) fbi, &display_fops); dbg->gsctl = debugfs_create_file("gsctl", 0444, dbg->dir, fbi, &gsctl_fops); + dbg->sdram = debugfs_create_file("sdram", 0444, dbg->dir, + fbi, &sdram_fops); + dbg->misc = debugfs_create_file("misc", 0444, dbg->dir, + fbi, &misc_fops); } static void __devexit mbxfb_debugfs_remove(struct fb_info *fbi) @@ -180,6 +234,8 @@ static void __devexit mbxfb_debugfs_remove(struct fb_info *fbi) struct mbxfb_info *mfbi = fbi->par; struct mbxfb_debugfs_data *dbg = mfbi->debugfs_data; + debugfs_remove(dbg->misc); + debugfs_remove(dbg->sdram); debugfs_remove(dbg->gsctl); debugfs_remove(dbg->display); debugfs_remove(dbg->clock); diff --git a/trunk/drivers/video/mbx/mbxfb.c b/trunk/drivers/video/mbx/mbxfb.c index a32d1af79e07..980d5f623902 100644 --- a/trunk/drivers/video/mbx/mbxfb.c +++ b/trunk/drivers/video/mbx/mbxfb.c @@ -1,8 +1,14 @@ /* * linux/drivers/video/mbx/mbxfb.c * + * Copyright (C) 2006 8D Technologies inc + * Raphael Assenat + * - Added video overlay support + * - Various improvements + * * Copyright (C) 2006 Compulab, Ltd. * Mike Rapoport + * - Creation of driver * * Based on pxafb.c * @@ -19,6 +25,7 @@ #include #include #include +#include #include @@ -29,6 +36,14 @@ static unsigned long virt_base_2700; +#define write_reg(val, reg) do { writel((val), (reg)); } while(0) + +/* Without this delay, the graphics appears somehow scaled and + * there is a lot of jitter in scanlines. This delay is probably + * needed only after setting some specific register(s) somewhere, + * not all over the place... */ +#define write_reg_dly(val, reg) do { writel((val), reg); udelay(1000); } while(0) + #define MIN_XRES 16 #define MIN_YRES 16 #define MAX_XRES 2048 @@ -257,19 +272,17 @@ static int mbxfb_set_par(struct fb_info *info) gsctrl &= ~(FMsk(GSCTRL_GSWIDTH) | FMsk(GSCTRL_GSHEIGHT)); gsctrl |= Gsctrl_Width(info->var.xres) | Gsctrl_Height(info->var.yres); - writel(gsctrl, GSCTRL); - udelay(1000); + write_reg_dly(gsctrl, GSCTRL); gsadr &= ~(FMsk(GSADR_SRCSTRIDE)); gsadr |= Gsadr_Srcstride(info->var.xres * info->var.bits_per_pixel / (8 * 16) - 1); - writel(gsadr, GSADR); - udelay(1000); + write_reg_dly(gsadr, GSADR); /* setup timings */ var->pixclock = mbxfb_get_pixclock(info->var.pixclock, &div); - writel((Disp_Pll_M(div.m) | Disp_Pll_N(div.n) | + write_reg_dly((Disp_Pll_M(div.m) | Disp_Pll_N(div.n) | Disp_Pll_P(div.p) | DISP_PLL_EN), DISPPLL); hbps = var->hsync_len; @@ -282,18 +295,20 @@ static int mbxfb_set_par(struct fb_info *info) vfps = vas + var->yres; vt = vfps + var->lower_margin; - writel((Dht01_Hbps(hbps) | Dht01_Ht(ht)), DHT01); - writel((Dht02_Hlbs(has) | Dht02_Has(has)), DHT02); - writel((Dht03_Hfps(hfps) | Dht03_Hrbs(hfps)), DHT03); - writel((Dhdet_Hdes(has) | Dhdet_Hdef(hfps)), DHDET); + write_reg_dly((Dht01_Hbps(hbps) | Dht01_Ht(ht)), DHT01); + write_reg_dly((Dht02_Hlbs(has) | Dht02_Has(has)), DHT02); + write_reg_dly((Dht03_Hfps(hfps) | Dht03_Hrbs(hfps)), DHT03); + write_reg_dly((Dhdet_Hdes(has) | Dhdet_Hdef(hfps)), DHDET); - writel((Dvt01_Vbps(vbps) | Dvt01_Vt(vt)), DVT01); - writel((Dvt02_Vtbs(vas) | Dvt02_Vas(vas)), DVT02); - writel((Dvt03_Vfps(vfps) | Dvt03_Vbbs(vfps)), DVT03); - writel((Dvdet_Vdes(vas) | Dvdet_Vdef(vfps)), DVDET); - writel((Dvectrl_Vevent(vfps) | Dvectrl_Vfetch(vbps)), DVECTRL); + write_reg_dly((Dvt01_Vbps(vbps) | Dvt01_Vt(vt)), DVT01); + write_reg_dly((Dvt02_Vtbs(vas) | Dvt02_Vas(vas)), DVT02); + write_reg_dly((Dvt03_Vfps(vfps) | Dvt03_Vbbs(vfps)), DVT03); + write_reg_dly((Dvdet_Vdes(vas) | Dvdet_Vdef(vfps)), DVDET); + write_reg_dly((Dvectrl_Vevent(vfps) | Dvectrl_Vfetch(vbps)), DVECTRL); - writel((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL); + write_reg_dly((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL); + + write_reg_dly(DINTRE_VEVENT0_EN, DINTRE); return 0; } @@ -305,23 +320,203 @@ static int mbxfb_blank(int blank, struct fb_info *info) case FB_BLANK_VSYNC_SUSPEND: case FB_BLANK_HSYNC_SUSPEND: case FB_BLANK_NORMAL: - writel((readl(DSCTRL) & ~DSCTRL_SYNCGEN_EN), DSCTRL); - udelay(1000); - writel((readl(PIXCLK) & ~PIXCLK_EN), PIXCLK); - udelay(1000); - writel((readl(VOVRCLK) & ~VOVRCLK_EN), VOVRCLK); - udelay(1000); + write_reg_dly((readl(DSCTRL) & ~DSCTRL_SYNCGEN_EN), DSCTRL); + write_reg_dly((readl(PIXCLK) & ~PIXCLK_EN), PIXCLK); + write_reg_dly((readl(VOVRCLK) & ~VOVRCLK_EN), VOVRCLK); break; case FB_BLANK_UNBLANK: - writel((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL); - udelay(1000); - writel((readl(PIXCLK) | PIXCLK_EN), PIXCLK); - udelay(1000); + write_reg_dly((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL); + write_reg_dly((readl(PIXCLK) | PIXCLK_EN), PIXCLK); break; } return 0; } +static int mbxfb_setupOverlay(struct mbxfb_overlaySetup *set) +{ + u32 vsctrl, vbbase, vscadr, vsadr; + u32 sssize, spoctrl, svctrl, shctrl; + u32 vubase, vvbase; + u32 vovrclk; + + if (set->scaled_width==0 || set->scaled_height==0) + return -EINVAL; + + /* read registers which have reserved bits + * so we can write them back as-is. */ + vovrclk = readl(VOVRCLK); + vsctrl = readl(VSCTRL); + vscadr = readl(VSCADR); + vubase = readl(VUBASE); + vvbase = readl(VVBASE); + + spoctrl = readl(SPOCTRL); + sssize = readl(SSSIZE); + + + vbbase = Vbbase_Glalpha(set->alpha); + + vsctrl &= ~( FMsk(VSCTRL_VSWIDTH) | + FMsk(VSCTRL_VSHEIGHT) | + FMsk(VSCTRL_VPIXFMT) | + VSCTRL_GAMMA_EN | VSCTRL_CSC_EN | + VSCTRL_COSITED ); + vsctrl |= Vsctrl_Width(set->width) | Vsctrl_Height(set->height) | + VSCTRL_CSC_EN; + + vscadr &= ~(VSCADR_STR_EN | VSCADR_COLKEY_EN | VSCADR_COLKEYSRC | + FMsk(VSCADR_BLEND_M) | FMsk(VSCADR_BLEND_POS) | + FMsk(VSCADR_VBASE_ADR) ); + vubase &= ~(VUBASE_UVHALFSTR | FMsk(VUBASE_UBASE_ADR)); + vvbase &= ~(FMsk(VVBASE_VBASE_ADR)); + + switch (set->fmt) + { + case MBXFB_FMT_YUV12: + vsctrl |= VSCTRL_VPIXFMT_YUV12; + + set->Y_stride = ((set->width) + 0xf ) & ~0xf; + + break; + case MBXFB_FMT_UY0VY1: + vsctrl |= VSCTRL_VPIXFMT_UY0VY1; + set->Y_stride = (set->width*2 + 0xf ) & ~0xf; + break; + case MBXFB_FMT_VY0UY1: + vsctrl |= VSCTRL_VPIXFMT_VY0UY1; + set->Y_stride = (set->width*2 + 0xf ) & ~0xf; + break; + case MBXFB_FMT_Y0UY1V: + vsctrl |= VSCTRL_VPIXFMT_Y0UY1V; + set->Y_stride = (set->width*2 + 0xf ) & ~0xf; + break; + case MBXFB_FMT_Y0VY1U: + vsctrl |= VSCTRL_VPIXFMT_Y0VY1U; + set->Y_stride = (set->width*2 + 0xf ) & ~0xf; + break; + default: + return -EINVAL; + } + + /* VSCTRL has the bits which sets the Video Pixel Format. + * When passing from a packed to planar format, + * if we write VSCTRL first, VVBASE and VUBASE would + * be zero if we would not set them here. (And then, + * the chips hangs and only a reset seems to fix it). + * + * If course, the values calculated here have no meaning + * for packed formats. + */ + set->UV_stride = ((set->width/2) + 0x7 ) & ~0x7; + set->U_offset = set->height * set->Y_stride; + set->V_offset = set->U_offset + + set->height * set->UV_stride; + vubase |= Vubase_Ubase_Adr( + (0x60000 + set->mem_offset + set->U_offset)>>3); + vvbase |= Vvbase_Vbase_Adr( + (0x60000 + set->mem_offset + set->V_offset)>>3); + + + vscadr |= VSCADR_BLEND_VID | VSCADR_BLEND_GLOB | + Vscadr_Vbase_Adr((0x60000 + set->mem_offset)>>4); + + if (set->enable) + vscadr |= VSCADR_STR_EN; + + + vsadr = Vsadr_Srcstride((set->Y_stride)/16-1) | + Vsadr_Xstart(set->x) | Vsadr_Ystart(set->y); + + sssize &= ~(FMsk(SSSIZE_SC_WIDTH) | FMsk(SSSIZE_SC_HEIGHT)); + sssize = Sssize_Sc_Width(set->scaled_width-1) | + Sssize_Sc_Height(set->scaled_height-1); + + spoctrl &= ~(SPOCTRL_H_SC_BP | SPOCTRL_V_SC_BP | + SPOCTRL_HV_SC_OR | SPOCTRL_VS_UR_C | + FMsk(SPOCTRL_VORDER) | FMsk(SPOCTRL_VPITCH)); + spoctrl = Spoctrl_Vpitch((set->height<<11)/set->scaled_height) + | SPOCTRL_VORDER_2TAP; + + /* Bypass horiz/vert scaler when same size */ + if (set->scaled_width == set->width) + spoctrl |= SPOCTRL_H_SC_BP; + if (set->scaled_height == set->height) + spoctrl |= SPOCTRL_V_SC_BP; + + svctrl = Svctrl_Initial1(1<<10) | Svctrl_Initial2(1<<10); + + shctrl = Shctrl_Hinitial(4<<11) + | Shctrl_Hpitch((set->width<<11)/set->scaled_width); + + /* Video plane registers */ + write_reg(vsctrl, VSCTRL); + write_reg(vbbase, VBBASE); + write_reg(vscadr, VSCADR); + write_reg(vubase, VUBASE); + write_reg(vvbase, VVBASE); + write_reg(vsadr, VSADR); + + /* Video scaler registers */ + write_reg(sssize, SSSIZE); + write_reg(spoctrl, SPOCTRL); + write_reg(svctrl, SVCTRL); + write_reg(shctrl, SHCTRL); + + /* RAPH: Using those coefficients, the scaled + * image is quite blurry. I dont know how + * to improve them ; The chip documentation + * was not helpful.. */ + write_reg(0x21212121, VSCOEFF0); + write_reg(0x21212121, VSCOEFF1); + write_reg(0x21212121, VSCOEFF2); + write_reg(0x21212121, VSCOEFF3); + write_reg(0x21212121, VSCOEFF4); + write_reg(0x00000000, HSCOEFF0); + write_reg(0x00000000, HSCOEFF1); + write_reg(0x00000000, HSCOEFF2); + write_reg(0x03020201, HSCOEFF3); + write_reg(0x09070604, HSCOEFF4); + write_reg(0x0f0e0c0a, HSCOEFF5); + write_reg(0x15141211, HSCOEFF6); + write_reg(0x19181716, HSCOEFF7); + write_reg(0x00000019, HSCOEFF8); + + /* Clock */ + if (set->enable) + vovrclk |= 1; + else + vovrclk &= ~1; + + write_reg(vovrclk, VOVRCLK); + + return 0; +} + +static int mbxfb_ioctl(struct fb_info *info, unsigned int cmd, + unsigned long arg) +{ + struct mbxfb_overlaySetup setup; + int res; + + if (cmd == MBXFB_IOCX_OVERLAY) + { + if (copy_from_user(&setup, (void __user*)arg, + sizeof(struct mbxfb_overlaySetup))) + return -EFAULT; + + res = mbxfb_setupOverlay(&setup); + if (res) + return res; + + if (copy_to_user((void __user*)arg, &setup, + sizeof(struct mbxfb_overlaySetup))) + return -EFAULT; + + return 0; + } + return -EINVAL; +} + static struct fb_ops mbxfb_ops = { .owner = THIS_MODULE, .fb_check_var = mbxfb_check_var, @@ -331,6 +526,7 @@ static struct fb_ops mbxfb_ops = { .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, .fb_blank = mbxfb_blank, + .fb_ioctl = mbxfb_ioctl, }; /* @@ -339,36 +535,29 @@ static struct fb_ops mbxfb_ops = { */ static void __devinit setup_memc(struct fb_info *fbi) { - struct mbxfb_info *mfbi = fbi->par; unsigned long tmp; int i; /* FIXME: use platfrom specific parameters */ /* setup SDRAM controller */ - writel((LMCFG_LMC_DS | LMCFG_LMC_TS | LMCFG_LMD_TS | + write_reg_dly((LMCFG_LMC_DS | LMCFG_LMC_TS | LMCFG_LMD_TS | LMCFG_LMA_TS), LMCFG); - udelay(1000); - writel(LMPWR_MC_PWR_ACT, LMPWR); - udelay(1000); + write_reg_dly(LMPWR_MC_PWR_ACT, LMPWR); /* setup SDRAM timings */ - writel((Lmtim_Tras(7) | Lmtim_Trp(3) | Lmtim_Trcd(3) | + write_reg_dly((Lmtim_Tras(7) | Lmtim_Trp(3) | Lmtim_Trcd(3) | Lmtim_Trc(9) | Lmtim_Tdpl(2)), LMTIM); - udelay(1000); /* setup SDRAM refresh rate */ - writel(0xc2b, LMREFRESH); - udelay(1000); + write_reg_dly(0xc2b, LMREFRESH); /* setup SDRAM type parameters */ - writel((LMTYPE_CASLAT_3 | LMTYPE_BKSZ_2 | LMTYPE_ROWSZ_11 | + write_reg_dly((LMTYPE_CASLAT_3 | LMTYPE_BKSZ_2 | LMTYPE_ROWSZ_11 | LMTYPE_COLSZ_8), LMTYPE); - udelay(1000); /* enable memory controller */ - writel(LMPWR_MC_PWR_ACT, LMPWR); - udelay(1000); + write_reg_dly(LMPWR_MC_PWR_ACT, LMPWR); /* perform dummy reads */ for ( i = 0; i < 16; i++ ) { @@ -379,34 +568,30 @@ static void __devinit setup_memc(struct fb_info *fbi) static void enable_clocks(struct fb_info *fbi) { /* enable clocks */ - writel(SYSCLKSRC_PLL_2, SYSCLKSRC); - udelay(1000); - writel(PIXCLKSRC_PLL_1, PIXCLKSRC); - udelay(1000); - writel(0x00000000, CLKSLEEP); - udelay(1000); - writel((Core_Pll_M(0x17) | Core_Pll_N(0x3) | Core_Pll_P(0x0) | + write_reg_dly(SYSCLKSRC_PLL_2, SYSCLKSRC); + write_reg_dly(PIXCLKSRC_PLL_1, PIXCLKSRC); + write_reg_dly(0x00000000, CLKSLEEP); + + /* PLL output = (Frefclk * M) / (N * 2^P ) + * + * M: 0x17, N: 0x3, P: 0x0 == 100 Mhz! + * M: 0xb, N: 0x1, P: 0x1 == 71 Mhz + * */ + write_reg_dly((Core_Pll_M(0xb) | Core_Pll_N(0x1) | Core_Pll_P(0x1) | CORE_PLL_EN), COREPLL); - udelay(1000); - writel((Disp_Pll_M(0x1b) | Disp_Pll_N(0x7) | Disp_Pll_P(0x1) | + + write_reg_dly((Disp_Pll_M(0x1b) | Disp_Pll_N(0x7) | Disp_Pll_P(0x1) | DISP_PLL_EN), DISPPLL); - writel(0x00000000, VOVRCLK); - udelay(1000); - writel(PIXCLK_EN, PIXCLK); - udelay(1000); - writel(MEMCLK_EN, MEMCLK); - udelay(1000); - writel(0x00000006, M24CLK); - udelay(1000); - writel(0x00000006, MBXCLK); - udelay(1000); - writel(SDCLK_EN, SDCLK); - udelay(1000); - writel(0x00000001, PIXCLKDIV); - udelay(1000); + write_reg_dly(0x00000000, VOVRCLK); + write_reg_dly(PIXCLK_EN, PIXCLK); + write_reg_dly(MEMCLK_EN, MEMCLK); + write_reg_dly(0x00000006, M24CLK); + write_reg_dly(0x00000006, MBXCLK); + write_reg_dly(SDCLK_EN, SDCLK); + write_reg_dly(0x00000001, PIXCLKDIV); } static void __devinit setup_graphics(struct fb_info *fbi) @@ -430,16 +615,11 @@ static void __devinit setup_graphics(struct fb_info *fbi) break; } - writel(gsctrl, GSCTRL); - udelay(1000); - writel(0x00000000, GBBASE); - udelay(1000); - writel(0x00ffffff, GDRCTRL); - udelay(1000); - writel((GSCADR_STR_EN | Gscadr_Gbase_Adr(0x6000)), GSCADR); - udelay(1000); - writel(0x00000000, GPLUT); - udelay(1000); + write_reg_dly(gsctrl, GSCTRL); + write_reg_dly(0x00000000, GBBASE); + write_reg_dly(0x00ffffff, GDRCTRL); + write_reg_dly((GSCADR_STR_EN | Gscadr_Gbase_Adr(0x6000)), GSCADR); + write_reg_dly(0x00000000, GPLUT); } static void __devinit setup_display(struct fb_info *fbi) @@ -451,17 +631,14 @@ static void __devinit setup_display(struct fb_info *fbi) dsctrl |= DSCTRL_HS_POL; if (fbi->var.sync & FB_SYNC_VERT_HIGH_ACT) dsctrl |= DSCTRL_VS_POL; - writel(dsctrl, DSCTRL); - udelay(1000); - writel(0xd0303010, DMCTRL); - udelay(1000); - writel((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL); + write_reg_dly(dsctrl, DSCTRL); + write_reg_dly(0xd0303010, DMCTRL); + write_reg_dly((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL); } static void __devinit enable_controller(struct fb_info *fbi) { - writel(SYSRST_RST, SYSRST); - udelay(1000); + write_reg_dly(SYSRST_RST, SYSRST); enable_clocks(fbi); @@ -478,12 +655,12 @@ static void __devinit enable_controller(struct fb_info *fbi) static int mbxfb_suspend(struct platform_device *dev, pm_message_t state) { /* make frame buffer memory enter self-refresh mode */ - writel(LMPWR_MC_PWR_SRM, LMPWR); + write_reg_dly(LMPWR_MC_PWR_SRM, LMPWR); while (LMPWRSTAT != LMPWRSTAT_MC_PWR_SRM) ; /* empty statement */ /* reset the device, since it's initial state is 'mostly sleeping' */ - writel(SYSRST_RST, SYSRST); + write_reg_dly(SYSRST_RST, SYSRST); return 0; } @@ -495,7 +672,7 @@ static int mbxfb_resume(struct platform_device *dev) /* setup_graphics(fbi); */ /* setup_display(fbi); */ - writel((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL); + write_reg_dly((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL); return 0; } #else @@ -520,6 +697,12 @@ static int __devinit mbxfb_probe(struct platform_device *dev) dev_dbg(dev, "mbxfb_probe\n"); + pdata = dev->dev.platform_data; + if (!pdata) { + dev_err(&dev->dev, "platform data is required\n"); + return -EINVAL; + } + fbi = framebuffer_alloc(sizeof(struct mbxfb_info), &dev->dev); if (fbi == NULL) { dev_err(&dev->dev, "framebuffer_alloc failed\n"); @@ -528,7 +711,8 @@ static int __devinit mbxfb_probe(struct platform_device *dev) mfbi = fbi->par; fbi->pseudo_palette = mfbi->pseudo_palette; - pdata = dev->dev.platform_data; + + if (pdata->probe) mfbi->platform_probe = pdata->probe; if (pdata->remove) @@ -578,16 +762,16 @@ static int __devinit mbxfb_probe(struct platform_device *dev) goto err4; } - /* FIXME: get from platform */ fbi->screen_base = (char __iomem *)(mfbi->fb_virt_addr + 0x60000); - fbi->screen_size = 8 * 1024 * 1024; /* 8 Megs */ + fbi->screen_size = pdata->memsize; fbi->fbops = &mbxfb_ops; fbi->var = mbxfb_default; fbi->fix = mbxfb_fix; fbi->fix.smem_start = mfbi->fb_phys_addr + 0x60000; - fbi->fix.smem_len = 8 * 1024 * 1024; - fbi->fix.line_length = 640 * 2; + fbi->fix.smem_len = pdata->memsize; + fbi->fix.line_length = mbxfb_default.xres_virtual * + mbxfb_default.bits_per_pixel / 8; ret = fb_alloc_cmap(&fbi->cmap, 256, 0); if (ret < 0) { @@ -636,8 +820,7 @@ static int __devexit mbxfb_remove(struct platform_device *dev) { struct fb_info *fbi = platform_get_drvdata(dev); - writel(SYSRST_RST, SYSRST); - udelay(1000); + write_reg_dly(SYSRST_RST, SYSRST); mbxfb_debugfs_remove(fbi); diff --git a/trunk/drivers/video/mbx/reg_bits.h b/trunk/drivers/video/mbx/reg_bits.h index c226a8e45312..9a24fb0c7d48 100644 --- a/trunk/drivers/video/mbx/reg_bits.h +++ b/trunk/drivers/video/mbx/reg_bits.h @@ -242,6 +242,67 @@ #define GPLUT_LUTDATA Fld(24,0) #define Gplut_Lutdata(x) ((x) << FShft(GPLUT_LUTDATA)) +/* VSCTRL - Video Surface Control Register */ +#define VSCTRL_VPIXFMT Fld(4,27) +#define VSCTRL_VPIXFMT_YUV12 ((0x9) << FShft(VSCTRL_VPIXFMT)) +#define VSCTRL_VPIXFMT_UY0VY1 ((0xc) << FShft(VSCTRL_VPIXFMT)) +#define VSCTRL_VPIXFMT_VY0UY1 ((0xd) << FShft(VSCTRL_VPIXFMT)) +#define VSCTRL_VPIXFMT_Y0UY1V ((0xe) << FShft(VSCTRL_VPIXFMT)) +#define VSCTRL_VPIXFMT_Y0VY1U ((0xf) << FShft(VSCTRL_VPIXFMT)) +#define VSCTRL_GAMMA_EN (1 << 26) +#define VSCTRL_CSC_EN (1 << 25) +#define VSCTRL_COSITED (1 << 22) +#define VSCTRL_VSWIDTH Fld(11,11) +#define Vsctrl_Width(Pixels) /* Video Width [1-2048] */ \ + (((Pixels) - 1) << FShft(VSCTRL_VSWIDTH)) +#define VSCTRL_VSHEIGHT Fld(11,0) +#define Vsctrl_Height(Pixels) /* Video Height [1-2048] */ \ + (((Pixels) - 1) << FShft(VSCTRL_VSHEIGHT)) + +/* VBBASE - Video Blending Base Register */ +#define VBBASE_GLALPHA Fld(8,24) +#define Vbbase_Glalpha(x) ((x) << FShft(VBBASE_GLALPHA)) + +#define VBBASE_COLKEY Fld(24,0) +#define Vbbase_Colkey(x) ((x) << FShft(VBBASE_COLKEY)) + +/* VCMSK - Video Color Key Mask Register */ +#define VCMSK_COLKEY_M Fld(24,0) +#define Vcmsk_colkey_m(x) ((x) << FShft(VCMSK_COLKEY_M)) + +/* VSCADR - Video Stream Control Rddress Register */ +#define VSCADR_STR_EN (1 << 31) +#define VSCADR_COLKEY_EN (1 << 30) +#define VSCADR_COLKEYSRC (1 << 29) +#define VSCADR_BLEND_M Fld(2,27) +#define VSCADR_BLEND_NONE ((0x0) << FShft(VSCADR_BLEND_M)) +#define VSCADR_BLEND_INV ((0x1) << FShft(VSCADR_BLEND_M)) +#define VSCADR_BLEND_GLOB ((0x2) << FShft(VSCADR_BLEND_M)) +#define VSCADR_BLEND_PIX ((0x3) << FShft(VSCADR_BLEND_M)) +#define VSCADR_BLEND_POS Fld(2,24) +#define VSCADR_BLEND_GFX ((0x0) << FShft(VSCADR_BLEND_POS)) +#define VSCADR_BLEND_VID ((0x1) << FShft(VSCADR_BLEND_POS)) +#define VSCADR_BLEND_CUR ((0x2) << FShft(VSCADR_BLEND_POS)) +#define VSCADR_VBASE_ADR Fld(23,0) +#define Vscadr_Vbase_Adr(x) ((x) << FShft(VSCADR_VBASE_ADR)) + +/* VUBASE - Video U Base Register */ +#define VUBASE_UVHALFSTR (1 << 31) +#define VUBASE_UBASE_ADR Fld(24,0) +#define Vubase_Ubase_Adr(x) ((x) << FShft(VUBASE_UBASE_ADR)) + +/* VVBASE - Video V Base Register */ +#define VVBASE_VBASE_ADR Fld(24,0) +#define Vvbase_Vbase_Adr(x) ((x) << FShft(VVBASE_VBASE_ADR)) + +/* VSADR - Video Stride Address Register */ +#define VSADR_SRCSTRIDE Fld(10,22) +#define Vsadr_Srcstride(x) ((x) << FShft(VSADR_SRCSTRIDE)) +#define VSADR_XSTART Fld(11,11) +#define Vsadr_Xstart(x) ((x) << FShft(VSADR_XSTART)) +#define VSADR_YSTART Fld(11,0) +#define Vsadr_Ystart(x) ((x) << FShft(VSADR_YSTART)) + /* HCCTRL - Hardware Cursor Register fields */ #define HCCTRL_CUR_EN (1 << 31) #define HCCTRL_COLKEY_EN (1 << 29) @@ -394,6 +455,30 @@ #define DMCTRL_BURSTLEN Fld(6,0) #define Dmctrl_Burstlen(x) ((x) << FShft(DMCTRL_BURSTLEN)) +/* DINTRS - Display Interrupt Status Register */ +#define DINTRS_CUR_OR_S (1 << 18) +#define DINTRS_STR2_OR_S (1 << 17) +#define DINTRS_STR1_OR_S (1 << 16) +#define DINTRS_CUR_UR_S (1 << 6) +#define DINTRS_STR2_UR_S (1 << 5) +#define DINTRS_STR1_UR_S (1 << 4) +#define DINTRS_VEVENT1_S (1 << 3) +#define DINTRS_VEVENT0_S (1 << 2) +#define DINTRS_HBLNK1_S (1 << 1) +#define DINTRS_HBLNK0_S (1 << 0) + +/* DINTRE - Display Interrupt Enable Register */ +#define DINTRE_CUR_OR_EN (1 << 18) +#define DINTRE_STR2_OR_EN (1 << 17) +#define DINTRE_STR1_OR_EN (1 << 16) +#define DINTRE_CUR_UR_EN (1 << 6) +#define DINTRE_STR2_UR_EN (1 << 5) +#define DINTRE_STR1_UR_EN (1 << 4) +#define DINTRE_VEVENT1_EN (1 << 3) +#define DINTRE_VEVENT0_EN (1 << 2) +#define DINTRE_HBLNK1_EN (1 << 1) +#define DINTRE_HBLNK0_EN (1 << 0) + /* DLSTS - display load status register */ #define DLSTS_RLD_ADONE (1 << 23) @@ -403,16 +488,41 @@ #define DLLCTRL_RLD_ADRLN Fld(8,24) #define Dllctrl_Rld_Adrln(x) ((x) << FShft(DLLCTRL_RLD_ADRLN)) +/* CLIPCTRL - Clipping Control Register */ +#define CLIPCTRL_HSKIP Fld(11,16) +#define Clipctrl_Hskip ((x) << FShft(CLIPCTRL_HSKIP)) +#define CLIPCTRL_VSKIP Fld(11,0) +#define Clipctrl_Vskip ((x) << FShft(CLIPCTRL_VSKIP)) + /* SPOCTRL - Scale Pitch/Order Control Register */ #define SPOCTRL_H_SC_BP (1 << 31) #define SPOCTRL_V_SC_BP (1 << 30) #define SPOCTRL_HV_SC_OR (1 << 29) #define SPOCTRL_VS_UR_C (1 << 27) -#define SPOCTRL_VORDER Fld(2,16) +#define SPOCTRL_VORDER Fld(2,16) #define SPOCTRL_VORDER_1TAP ((0x0) << FShft(SPOCTRL_VORDER)) #define SPOCTRL_VORDER_2TAP ((0x1) << FShft(SPOCTRL_VORDER)) #define SPOCTRL_VORDER_4TAP ((0x3) << FShft(SPOCTRL_VORDER)) -#define SPOCTRL_VPITCH Fld(16,0) +#define SPOCTRL_VPITCH Fld(16,0) #define Spoctrl_Vpitch(x) ((x) << FShft(SPOCTRL_VPITCH)) +/* SVCTRL - Scale Vertical Control Register */ +#define SVCTRL_INITIAL1 Fld(16,16) +#define Svctrl_Initial1(x) ((x) << FShft(SVCTRL_INITIAL1)) +#define SVCTRL_INITIAL2 Fld(16,0) +#define Svctrl_Initial2(x) ((x) << FShft(SVCTRL_INITIAL2)) + +/* SHCTRL - Scale Horizontal Control Register */ +#define SHCTRL_HINITIAL Fld(16,16) +#define Shctrl_Hinitial(x) ((x) << FShft(SHCTRL_HINITIAL)) +#define SHCTRL_HDECIM (1 << 15) +#define SHCTRL_HPITCH Fld(15,0) +#define Shctrl_Hpitch(x) ((x) << FShft(SHCTRL_HPITCH)) + +/* SSSIZE - Scale Surface Size Register */ +#define SSSIZE_SC_WIDTH Fld(11,16) +#define Sssize_Sc_Width(x) ((x) << FShft(SSSIZE_SC_WIDTH)) +#define SSSIZE_SC_HEIGHT Fld(11,0) +#define Sssize_Sc_Height(x) ((x) << FShft(SSSIZE_SC_HEIGHT)) + #endif /* __REG_BITS_2700G_ */ diff --git a/trunk/drivers/video/mbx/regs.h b/trunk/drivers/video/mbx/regs.h index ad20be07666b..a7c63d865aad 100644 --- a/trunk/drivers/video/mbx/regs.h +++ b/trunk/drivers/video/mbx/regs.h @@ -127,7 +127,7 @@ #define HSCOEFF0 __REG_2700G(0x000021b4) #define HSCOEFF1 __REG_2700G(0x000021b8) #define HSCOEFF2 __REG_2700G(0x000021bc) -#define HSCOEFF3 __REG_2700G(0x000021b0) +#define HSCOEFF3 __REG_2700G(0x000021c0) #define HSCOEFF4 __REG_2700G(0x000021c4) #define HSCOEFF5 __REG_2700G(0x000021c8) #define HSCOEFF6 __REG_2700G(0x000021cc) diff --git a/trunk/drivers/video/modedb.c b/trunk/drivers/video/modedb.c index d1267904c280..5df41f6f2b86 100644 --- a/trunk/drivers/video/modedb.c +++ b/trunk/drivers/video/modedb.c @@ -34,8 +34,6 @@ const char *global_mode_option; * Standard video mode definitions (taken from XFree86) */ -#define DEFAULT_MODEDB_INDEX 0 - static const struct fb_videomode modedb[] = { { /* 640x400 @ 70 Hz, 31.5 kHz hsync */ @@ -505,8 +503,10 @@ int fb_find_mode(struct fb_var_screeninfo *var, db = modedb; dbsize = ARRAY_SIZE(modedb); } + if (!default_mode) - default_mode = &modedb[DEFAULT_MODEDB_INDEX]; + default_mode = &db[0]; + if (!default_bpp) default_bpp = 8; diff --git a/trunk/drivers/video/neofb.c b/trunk/drivers/video/neofb.c index 59a6f5fa5ae6..deaf820cb38f 100644 --- a/trunk/drivers/video/neofb.c +++ b/trunk/drivers/video/neofb.c @@ -1932,7 +1932,7 @@ static int __devinit neo_init_hw(struct fb_info *info) printk(KERN_DEBUG "--- Neo extended register dump ---\n"); for (int w = 0; w < 0x85; w++) printk(KERN_DEBUG "CR %p: %p\n", (void *) w, - (void *) vga_rcrt(NULL, w); + (void *) vga_rcrt(NULL, w)); for (int w = 0; w < 0xC7; w++) printk(KERN_DEBUG "GR %p: %p\n", (void *) w, (void *) vga_rgfx(NULL, w)); diff --git a/trunk/drivers/video/nvidia/nv_accel.c b/trunk/drivers/video/nvidia/nv_accel.c index 4aefb8f41637..9efb8a3854e2 100644 --- a/trunk/drivers/video/nvidia/nv_accel.c +++ b/trunk/drivers/video/nvidia/nv_accel.c @@ -261,41 +261,6 @@ void NVResetGraphics(struct fb_info *info) NVDmaKickoff(par); } -u8 byte_rev[256] = { - 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, - 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, - 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, - 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, - 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, - 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, - 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, - 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, - 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, - 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, - 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, - 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, - 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, - 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, - 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, - 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, - 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, - 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, - 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, - 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, - 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, - 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, - 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, - 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, - 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, - 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, - 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, - 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, - 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, - 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, - 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, - 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff, -}; - int nvidiafb_sync(struct fb_info *info) { struct nvidia_par *par = info->par; diff --git a/trunk/drivers/video/nvidia/nv_i2c.c b/trunk/drivers/video/nvidia/nv_i2c.c index 19eef3a09023..442e85328341 100644 --- a/trunk/drivers/video/nvidia/nv_i2c.c +++ b/trunk/drivers/video/nvidia/nv_i2c.c @@ -210,11 +210,8 @@ int nvidia_probe_i2c_connector(struct fb_info *info, int conn, u8 **out_edid) /* try to get from firmware */ const u8 *e = fb_firmware_edid(info->device); - if (e != NULL) { - edid = kmalloc(EDID_LENGTH, GFP_KERNEL); - if (edid) - memcpy(edid, e, EDID_LENGTH); - } + if (e != NULL) + edid = kmemdup(e, EDID_LENGTH, GFP_KERNEL); } *out_edid = edid; diff --git a/trunk/drivers/video/nvidia/nv_local.h b/trunk/drivers/video/nvidia/nv_local.h index 4243d7fae972..e009d242ea10 100644 --- a/trunk/drivers/video/nvidia/nv_local.h +++ b/trunk/drivers/video/nvidia/nv_local.h @@ -96,13 +96,16 @@ #define READ_GET(par) (NV_RD32(&(par)->FIFO[0x0011], 0) >> 2) #ifdef __LITTLE_ENDIAN + +#include + #define reverse_order(l) \ do { \ u8 *a = (u8 *)(l); \ - *a = byte_rev[*a], a++; \ - *a = byte_rev[*a], a++; \ - *a = byte_rev[*a], a++; \ - *a = byte_rev[*a]; \ + a[0] = bitrev8(a[0]); \ + a[1] = bitrev8(a[1]); \ + a[2] = bitrev8(a[2]); \ + a[3] = bitrev8(a[3]); \ } while(0) #else #define reverse_order(l) do { } while(0) diff --git a/trunk/drivers/video/nvidia/nv_of.c b/trunk/drivers/video/nvidia/nv_of.c index d9af88c2b580..181875fe35c6 100644 --- a/trunk/drivers/video/nvidia/nv_of.c +++ b/trunk/drivers/video/nvidia/nv_of.c @@ -72,10 +72,9 @@ int nvidia_probe_of_connector(struct fb_info *info, int conn, u8 **out_edid) } } if (pedid) { - *out_edid = kmalloc(EDID_LENGTH, GFP_KERNEL); + *out_edid = kmemdup(pedid, EDID_LENGTH, GFP_KERNEL); if (*out_edid == NULL) return -1; - memcpy(*out_edid, pedid, EDID_LENGTH); printk(KERN_DEBUG "nvidiafb: Found OF EDID for head %d\n", conn); return 0; } diff --git a/trunk/drivers/video/nvidia/nv_proto.h b/trunk/drivers/video/nvidia/nv_proto.h index 861271017655..43058d0cf5b7 100644 --- a/trunk/drivers/video/nvidia/nv_proto.h +++ b/trunk/drivers/video/nvidia/nv_proto.h @@ -62,7 +62,6 @@ extern void nvidiafb_fillrect(struct fb_info *info, extern void nvidiafb_imageblit(struct fb_info *info, const struct fb_image *image); extern int nvidiafb_sync(struct fb_info *info); -extern u8 byte_rev[256]; /* in nv_backlight.h */ #ifdef CONFIG_FB_NVIDIA_BACKLIGHT diff --git a/trunk/drivers/video/offb.c b/trunk/drivers/video/offb.c index 9a40bbecf76b..9576a55eaf16 100644 --- a/trunk/drivers/video/offb.c +++ b/trunk/drivers/video/offb.c @@ -402,6 +402,9 @@ static void __init offb_init_fb(const char *name, const char *full_name, fb_alloc_cmap(&info->cmap, 256, 0); if (register_framebuffer(info) < 0) { + iounmap(par->cmap_adr); + par->cmap_adr = NULL; + iounmap(info->screen_base); kfree(info); release_mem_region(res_start, res_size); return; diff --git a/trunk/drivers/video/platinumfb.c b/trunk/drivers/video/platinumfb.c index cb26c6df0583..233871655824 100644 --- a/trunk/drivers/video/platinumfb.c +++ b/trunk/drivers/video/platinumfb.c @@ -627,6 +627,9 @@ static int __devinit platinumfb_probe(struct of_device* odev, rc = platinum_init_fb(info); if (rc != 0) { + iounmap(pinfo->frame_buffer); + iounmap(pinfo->platinum_regs); + iounmap(pinfo->cmap_regs); dev_set_drvdata(&odev->dev, NULL); framebuffer_release(info); } diff --git a/trunk/drivers/video/pmagb-b-fb.c b/trunk/drivers/video/pmagb-b-fb.c index 73e2d7d16608..a06a064ad757 100644 --- a/trunk/drivers/video/pmagb-b-fb.c +++ b/trunk/drivers/video/pmagb-b-fb.c @@ -186,7 +186,7 @@ static void __init pmagbbfb_screen_setup(struct fb_info *info) static void __init pmagbbfb_osc_setup(struct fb_info *info) { static unsigned int pmagbbfb_freqs[] __initdata = { - 130808, 119843, 104000, 92980, 74367, 72800, + 130808, 119843, 104000, 92980, 74370, 72800, 69197, 66000, 65000, 50350, 36000, 32000, 25175 }; struct pmagbbfb_par *par = info->par; diff --git a/trunk/drivers/video/pvr2fb.c b/trunk/drivers/video/pvr2fb.c index c7bc80921f16..a93618bc9d27 100644 --- a/trunk/drivers/video/pvr2fb.c +++ b/trunk/drivers/video/pvr2fb.c @@ -905,6 +905,15 @@ static int __init pvr2fb_dc_init(void) static void pvr2fb_dc_exit(void) { + if (fb_info->screen_base) { + iounmap(fb_info->screen_base); + fb_info->screen_base = NULL; + } + if (currentpar->mmio_base) { + iounmap((void *)currentpar->mmio_base); + currentpar->mmio_base = 0; + } + free_irq(HW_EVENT_VSYNC, 0); #ifdef CONFIG_SH_DMA free_dma(pvr2dma); @@ -946,6 +955,15 @@ static int __devinit pvr2fb_pci_probe(struct pci_dev *pdev, static void __devexit pvr2fb_pci_remove(struct pci_dev *pdev) { + if (fb_info->screen_base) { + iounmap(fb_info->screen_base); + fb_info->screen_base = NULL; + } + if (currentpar->mmio_base) { + iounmap((void *)currentpar->mmio_base); + currentpar->mmio_base = 0; + } + pci_release_regions(pdev); } diff --git a/trunk/drivers/video/pxafb.c b/trunk/drivers/video/pxafb.c index 8a8ae55a7403..38eb0b69c2d7 100644 --- a/trunk/drivers/video/pxafb.c +++ b/trunk/drivers/video/pxafb.c @@ -964,9 +964,10 @@ static void set_ctrlr_state(struct pxafb_info *fbi, u_int state) * Our LCD controller task (which is called when we blank or unblank) * via keventd. */ -static void pxafb_task(void *dummy) +static void pxafb_task(struct work_struct *work) { - struct pxafb_info *fbi = dummy; + struct pxafb_info *fbi = + container_of(work, struct pxafb_info, task); u_int state = xchg(&fbi->task_state, -1); set_ctrlr_state(fbi, state); @@ -1159,7 +1160,7 @@ static struct pxafb_info * __init pxafb_init_fbinfo(struct device *dev) } init_waitqueue_head(&fbi->ctrlr_wait); - INIT_WORK(&fbi->task, pxafb_task, fbi); + INIT_WORK(&fbi->task, pxafb_task); init_MUTEX(&fbi->ctrlr_sem); return fbi; diff --git a/trunk/drivers/video/retz3fb.c b/trunk/drivers/video/retz3fb.c index cf41ff177644..bc7ffc84e185 100644 --- a/trunk/drivers/video/retz3fb.c +++ b/trunk/drivers/video/retz3fb.c @@ -1423,8 +1423,10 @@ int __init retz3fb_init(void) do_install_cmap(0, fb_info); - if (register_framebuffer(fb_info) < 0) + if (register_framebuffer(fb_info) < 0) { + iounmap(zinfo->base); return -EINVAL; + } printk(KERN_INFO "fb%d: %s frame buffer device, using %ldK of " "video memory\n", fb_info->node, diff --git a/trunk/drivers/video/riva/fbdev.c b/trunk/drivers/video/riva/fbdev.c index a433cc78ef90..345e8b1c1af8 100644 --- a/trunk/drivers/video/riva/fbdev.c +++ b/trunk/drivers/video/riva/fbdev.c @@ -40,6 +40,7 @@ #include #include #include +#include #ifdef CONFIG_MTRR #include #endif @@ -521,48 +522,13 @@ static inline unsigned char MISCin(struct riva_par *par) return (VGA_RD08(par->riva.PVIO, 0x3cc)); } -static u8 byte_rev[256] = { - 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, - 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, - 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, - 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, - 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, - 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, - 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, - 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, - 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, - 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, - 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, - 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, - 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, - 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, - 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, - 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, - 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, - 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, - 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, - 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, - 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, - 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, - 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, - 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, - 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, - 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, - 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, - 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, - 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, - 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, - 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, - 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff, -}; - static inline void reverse_order(u32 *l) { u8 *a = (u8 *)l; - *a = byte_rev[*a], a++; - *a = byte_rev[*a], a++; - *a = byte_rev[*a], a++; - *a = byte_rev[*a]; + a[0] = bitrev8(a[0]); + a[1] = bitrev8(a[1]); + a[2] = bitrev8(a[2]); + a[3] = bitrev8(a[3]); } /* ------------------------------------------------------------------------- * @@ -774,11 +740,12 @@ static void riva_load_state(struct riva_par *par, struct riva_regs *regs) * CALLED FROM: * rivafb_set_par() */ -static void riva_load_video_mode(struct fb_info *info) +static int riva_load_video_mode(struct fb_info *info) { int bpp, width, hDisplaySize, hDisplay, hStart, hEnd, hTotal, height, vDisplay, vStart, vEnd, vTotal, dotClock; int hBlankStart, hBlankEnd, vBlankStart, vBlankEnd; + int rc; struct riva_par *par = info->par; struct riva_regs newmode; @@ -884,8 +851,10 @@ static void riva_load_video_mode(struct fb_info *info) else newmode.misc_output |= 0x80; - par->riva.CalcStateExt(&par->riva, &newmode.ext, bpp, width, - hDisplaySize, height, dotClock); + rc = CalcStateExt(&par->riva, &newmode.ext, bpp, width, + hDisplaySize, height, dotClock); + if (rc) + goto out; newmode.ext.scale = NV_RD32(par->riva.PRAMDAC, 0x00000848) & 0xfff000ff; @@ -917,8 +886,12 @@ static void riva_load_video_mode(struct fb_info *info) par->current_state = newmode; riva_load_state(par, &par->current_state); par->riva.LockUnlock(&par->riva, 0); /* important for HW cursor */ + +out: rivafb_blank(FB_BLANK_UNBLANK, info); NVTRACE_LEAVE(); + + return rc; } static void riva_update_var(struct fb_var_screeninfo *var, struct fb_videomode *modedb) @@ -1286,12 +1259,15 @@ static int rivafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) static int rivafb_set_par(struct fb_info *info) { struct riva_par *par = info->par; + int rc = 0; NVTRACE_ENTER(); /* vgaHWunlock() + riva unlock (0x7F) */ CRTCout(par, 0x11, 0xFF); par->riva.LockUnlock(&par->riva, 0); - riva_load_video_mode(info); + rc = riva_load_video_mode(info); + if (rc) + goto out; if(!(info->flags & FBINFO_HWACCEL_DISABLED)) riva_setup_accel(info); @@ -1304,8 +1280,10 @@ static int rivafb_set_par(struct fb_info *info) info->pixmap.scan_align = 1; else info->pixmap.scan_align = 4; + +out: NVTRACE_LEAVE(); - return 0; + return rc; } /** diff --git a/trunk/drivers/video/riva/riva_hw.c b/trunk/drivers/video/riva/riva_hw.c index b6f8690b96c9..e0b8c521cc9c 100644 --- a/trunk/drivers/video/riva/riva_hw.c +++ b/trunk/drivers/video/riva/riva_hw.c @@ -1227,7 +1227,7 @@ static int CalcVClock * Calculate extended mode parameters (SVGA) and save in a * mode state structure. */ -static void CalcStateExt +int CalcStateExt ( RIVA_HW_INST *chip, RIVA_HW_STATE *state, @@ -1249,7 +1249,8 @@ static void CalcStateExt * Extended RIVA registers. */ pixelDepth = (bpp + 1)/8; - CalcVClock(dotClock, &VClk, &m, &n, &p, chip); + if (!CalcVClock(dotClock, &VClk, &m, &n, &p, chip)) + return -EINVAL; switch (chip->Architecture) { @@ -1327,6 +1328,8 @@ static void CalcStateExt state->pitch1 = state->pitch2 = state->pitch3 = pixelDepth * width; + + return 0; } /* * Load fixed function state and pre-calculated/stored state. @@ -2026,7 +2029,6 @@ static void nv3GetConfig */ chip->Busy = nv3Busy; chip->ShowHideCursor = ShowHideCursor; - chip->CalcStateExt = CalcStateExt; chip->LoadStateExt = LoadStateExt; chip->UnloadStateExt = UnloadStateExt; chip->SetStartAddress = SetStartAddress3; @@ -2084,7 +2086,6 @@ static void nv4GetConfig */ chip->Busy = nv4Busy; chip->ShowHideCursor = ShowHideCursor; - chip->CalcStateExt = CalcStateExt; chip->LoadStateExt = LoadStateExt; chip->UnloadStateExt = UnloadStateExt; chip->SetStartAddress = SetStartAddress; @@ -2186,7 +2187,6 @@ static void nv10GetConfig */ chip->Busy = nv10Busy; chip->ShowHideCursor = ShowHideCursor; - chip->CalcStateExt = CalcStateExt; chip->LoadStateExt = LoadStateExt; chip->UnloadStateExt = UnloadStateExt; chip->SetStartAddress = SetStartAddress; diff --git a/trunk/drivers/video/riva/riva_hw.h b/trunk/drivers/video/riva/riva_hw.h index a1e71a626df2..c2769f73e0b2 100644 --- a/trunk/drivers/video/riva/riva_hw.h +++ b/trunk/drivers/video/riva/riva_hw.h @@ -463,7 +463,6 @@ typedef struct _riva_hw_inst * Common chip functions. */ int (*Busy)(struct _riva_hw_inst *); - void (*CalcStateExt)(struct _riva_hw_inst *,struct _riva_hw_state *,int,int,int,int,int); void (*LoadStateExt)(struct _riva_hw_inst *,struct _riva_hw_state *); void (*UnloadStateExt)(struct _riva_hw_inst *,struct _riva_hw_state *); void (*SetStartAddress)(struct _riva_hw_inst *,U032); @@ -528,6 +527,22 @@ typedef struct _riva_hw_state U032 pitch2; U032 pitch3; } RIVA_HW_STATE; + +/* + * function prototypes + */ + +extern int CalcStateExt +( + RIVA_HW_INST *chip, + RIVA_HW_STATE *state, + int bpp, + int width, + int hDisplaySize, + int height, + int dotClock +); + /* * External routines. */ diff --git a/trunk/drivers/video/s3c2410fb.c b/trunk/drivers/video/s3c2410fb.c index 59407343cc73..ccef56d0c157 100644 --- a/trunk/drivers/video/s3c2410fb.c +++ b/trunk/drivers/video/s3c2410fb.c @@ -131,7 +131,7 @@ static void s3c2410fb_set_lcdaddr(struct s3c2410fb_info *fbi) saddr2 += (var->xres * var->yres * var->bits_per_pixel)/8; saddr2>>= 1; - saddr3 = S3C2410_OFFSIZE(0) | S3C2410_PAGEWIDTH(var->xres); + saddr3 = S3C2410_OFFSIZE(0) | S3C2410_PAGEWIDTH((var->xres * var->bits_per_pixel / 16) & 0x3ff); dprintk("LCDSADDR1 = 0x%08lx\n", saddr1); dprintk("LCDSADDR2 = 0x%08lx\n", saddr2); @@ -199,28 +199,86 @@ static int s3c2410fb_check_var(struct fb_var_screeninfo *var, var->bits_per_pixel = fbi->mach_info->bpp.min; /* set r/g/b positions */ + switch (var->bits_per_pixel) { + case 1: + case 2: + case 4: + var->red.offset = 0; + var->red.length = var->bits_per_pixel; + var->green = var->red; + var->blue = var->red; + var->transp.offset = 0; + var->transp.length = 0; + break; + case 8: + if ( fbi->mach_info->type != S3C2410_LCDCON1_TFT ) { + /* 8 bpp 332 */ + var->red.length = 3; + var->red.offset = 5; + var->green.length = 3; + var->green.offset = 2; + var->blue.length = 2; + var->blue.offset = 0; + var->transp.length = 0; + } else { + var->red.offset = 0; + var->red.length = var->bits_per_pixel; + var->green = var->red; + var->blue = var->red; + var->transp.offset = 0; + var->transp.length = 0; + } + break; + case 12: + /* 12 bpp 444 */ + var->red.length = 4; + var->red.offset = 8; + var->green.length = 4; + var->green.offset = 4; + var->blue.length = 4; + var->blue.offset = 0; + var->transp.length = 0; + break; + + default: + case 16: + if (fbi->regs.lcdcon5 & S3C2410_LCDCON5_FRM565 ) { + /* 16 bpp, 565 format */ + var->red.offset = 11; + var->green.offset = 5; + var->blue.offset = 0; + var->red.length = 5; + var->green.length = 6; + var->blue.length = 5; + var->transp.length = 0; + } else { + /* 16 bpp, 5551 format */ + var->red.offset = 11; + var->green.offset = 6; + var->blue.offset = 1; + var->red.length = 5; + var->green.length = 5; + var->blue.length = 5; + var->transp.length = 0; + } + break; + case 24: + /* 24 bpp 888 */ + var->red.length = 8; + var->red.offset = 16; + var->green.length = 8; + var->green.offset = 8; + var->blue.length = 8; + var->blue.offset = 0; + var->transp.length = 0; + break; - if (var->bits_per_pixel == 16) { - var->red.offset = 11; - var->green.offset = 5; - var->blue.offset = 0; - var->red.length = 5; - var->green.length = 6; - var->blue.length = 5; - var->transp.length = 0; - } else { - var->red.length = var->bits_per_pixel; - var->red.offset = 0; - var->green.length = var->bits_per_pixel; - var->green.offset = 0; - var->blue.length = var->bits_per_pixel; - var->blue.offset = 0; - var->transp.length = 0; - } + } return 0; } + /* s3c2410fb_activate_var * * activate (set) the controller from the given framebuffer @@ -230,29 +288,61 @@ static int s3c2410fb_check_var(struct fb_var_screeninfo *var, static void s3c2410fb_activate_var(struct s3c2410fb_info *fbi, struct fb_var_screeninfo *var) { + int hs; + fbi->regs.lcdcon1 &= ~S3C2410_LCDCON1_MODEMASK; + fbi->regs.lcdcon1 &= ~S3C2410_LCDCON1_TFT; dprintk("%s: var->xres = %d\n", __FUNCTION__, var->xres); dprintk("%s: var->yres = %d\n", __FUNCTION__, var->yres); dprintk("%s: var->bpp = %d\n", __FUNCTION__, var->bits_per_pixel); - switch (var->bits_per_pixel) { - case 1: - fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT1BPP; - break; - case 2: - fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT2BPP; - break; - case 4: - fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT4BPP; - break; - case 8: - fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT8BPP; - break; - case 16: - fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT16BPP; - break; - } + fbi->regs.lcdcon1 |= fbi->mach_info->type; + + if (fbi->mach_info->type == S3C2410_LCDCON1_TFT) + switch (var->bits_per_pixel) { + case 1: + fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT1BPP; + break; + case 2: + fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT2BPP; + break; + case 4: + fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT4BPP; + break; + case 8: + fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT8BPP; + break; + case 16: + fbi->regs.lcdcon1 |= S3C2410_LCDCON1_TFT16BPP; + break; + + default: + /* invalid pixel depth */ + dev_err(fbi->dev, "invalid bpp %d\n", var->bits_per_pixel); + } + else + switch (var->bits_per_pixel) { + case 1: + fbi->regs.lcdcon1 |= S3C2410_LCDCON1_STN1BPP; + break; + case 2: + fbi->regs.lcdcon1 |= S3C2410_LCDCON1_STN2GREY; + break; + case 4: + fbi->regs.lcdcon1 |= S3C2410_LCDCON1_STN4GREY; + break; + case 8: + fbi->regs.lcdcon1 |= S3C2410_LCDCON1_STN8BPP; + break; + case 12: + fbi->regs.lcdcon1 |= S3C2410_LCDCON1_STN12BPP; + break; + + default: + /* invalid pixel depth */ + dev_err(fbi->dev, "invalid bpp %d\n", var->bits_per_pixel); + } /* check to see if we need to update sync/borders */ @@ -283,15 +373,44 @@ static void s3c2410fb_activate_var(struct s3c2410fb_info *fbi, fbi->regs.lcdcon2 &= ~S3C2410_LCDCON2_LINEVAL(0x3ff); fbi->regs.lcdcon2 |= S3C2410_LCDCON2_LINEVAL(var->yres - 1); + switch(fbi->mach_info->type) { + case S3C2410_LCDCON1_DSCAN4: + case S3C2410_LCDCON1_STN8: + hs = var->xres / 8; + break; + case S3C2410_LCDCON1_STN4: + hs = var->xres / 4; + break; + default: + case S3C2410_LCDCON1_TFT: + hs = var->xres; + break; + + } + + /* Special cases : STN color displays */ + if ( ((fbi->regs.lcdcon1 & S3C2410_LCDCON1_MODEMASK) == S3C2410_LCDCON1_STN8BPP) \ + || ((fbi->regs.lcdcon1 & S3C2410_LCDCON1_MODEMASK) == S3C2410_LCDCON1_STN12BPP) ) { + hs = hs * 3; + } + + fbi->regs.lcdcon3 &= ~S3C2410_LCDCON3_HOZVAL(0x7ff); - fbi->regs.lcdcon3 |= S3C2410_LCDCON3_HOZVAL(var->xres - 1); + fbi->regs.lcdcon3 |= S3C2410_LCDCON3_HOZVAL(hs - 1); if (var->pixclock > 0) { int clkdiv = s3c2410fb_calc_pixclk(fbi, var->pixclock); - clkdiv = (clkdiv / 2) -1; - if (clkdiv < 0) - clkdiv = 0; + if (fbi->mach_info->type == S3C2410_LCDCON1_TFT) { + clkdiv = (clkdiv / 2) -1; + if (clkdiv < 0) + clkdiv = 0; + } + else { + clkdiv = (clkdiv / 2); + if (clkdiv < 2) + clkdiv = 2; + } fbi->regs.lcdcon1 &= ~S3C2410_LCDCON1_CLKVAL(0x3ff); fbi->regs.lcdcon1 |= S3C2410_LCDCON1_CLKVAL(clkdiv); @@ -329,10 +448,18 @@ static int s3c2410fb_set_par(struct fb_info *info) struct s3c2410fb_info *fbi = info->par; struct fb_var_screeninfo *var = &info->var; - if (var->bits_per_pixel == 16) - fbi->fb->fix.visual = FB_VISUAL_TRUECOLOR; - else - fbi->fb->fix.visual = FB_VISUAL_PSEUDOCOLOR; + switch (var->bits_per_pixel) + { + case 16: + fbi->fb->fix.visual = FB_VISUAL_TRUECOLOR; + break; + case 1: + fbi->fb->fix.visual = FB_VISUAL_MONO01; + break; + default: + fbi->fb->fix.visual = FB_VISUAL_PSEUDOCOLOR; + break; + } fbi->fb->fix.line_length = (var->width*var->bits_per_pixel)/8; diff --git a/trunk/drivers/video/savage/savagefb-i2c.c b/trunk/drivers/video/savage/savagefb-i2c.c index 3f94223b7f0c..cef5bf591cdf 100644 --- a/trunk/drivers/video/savage/savagefb-i2c.c +++ b/trunk/drivers/video/savage/savagefb-i2c.c @@ -227,11 +227,8 @@ int savagefb_probe_i2c_connector(struct fb_info *info, u8 **out_edid) /* try to get from firmware */ const u8 *e = fb_firmware_edid(info->device); - if (e) { - edid = kmalloc(EDID_LENGTH, GFP_KERNEL); - if (edid) - memcpy(edid, e, EDID_LENGTH); - } + if (e) + edid = kmemdup(e, EDID_LENGTH, GFP_KERNEL); } *out_edid = edid; diff --git a/trunk/drivers/video/sis/init301.c b/trunk/drivers/video/sis/init301.c index f13faddc6181..47e1896cffeb 100644 --- a/trunk/drivers/video/sis/init301.c +++ b/trunk/drivers/video/sis/init301.c @@ -445,11 +445,8 @@ SiS_CR36BIOSWord23d(struct SiS_Private *SiS_Pr) void SiS_DDC2Delay(struct SiS_Private *SiS_Pr, unsigned int delaytime) { - unsigned int i, j; - - for(i = 0; i < delaytime; i++) { - j += SiS_GetReg(SiS_Pr->SiS_P3c4,0x05); - } + while (delaytime-- > 0) + SiS_GetReg(SiS_Pr->SiS_P3c4, 0x05); } #if defined(SIS300) || defined(SIS315H) diff --git a/trunk/drivers/video/stifb.c b/trunk/drivers/video/stifb.c index 3e16e2d9d55d..69f3b264a22e 100644 --- a/trunk/drivers/video/stifb.c +++ b/trunk/drivers/video/stifb.c @@ -1291,6 +1291,7 @@ stifb_init_fb(struct sti_struct *sti, int bpp_pref) out_err2: release_mem_region(fix->smem_start, fix->smem_len); out_err1: + iounmap(info->screen_base); fb_dealloc_cmap(&info->cmap); out_err0: kfree(fb); @@ -1364,6 +1365,8 @@ stifb_cleanup(void) unregister_framebuffer(sti->info); release_mem_region(info->fix.mmio_start, info->fix.mmio_len); release_mem_region(info->fix.smem_start, info->fix.smem_len); + if (info->screen_base) + iounmap(info->screen_base); fb_dealloc_cmap(&info->cmap); kfree(info); } diff --git a/trunk/drivers/video/tgafb.c b/trunk/drivers/video/tgafb.c index 94fde625a6c0..4b88fab83b74 100644 --- a/trunk/drivers/video/tgafb.c +++ b/trunk/drivers/video/tgafb.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include