diff --git a/Documentation/00-INDEX b/Documentation/00-INDEX index 8d556707bb68..30b327a116ea 100644 --- a/Documentation/00-INDEX +++ b/Documentation/00-INDEX @@ -109,6 +109,8 @@ cpu-hotplug.txt - document describing CPU hotplug support in the Linux kernel. cpu-load.txt - document describing how CPU load statistics are collected. +cpuidle/ + - info on CPU_IDLE, CPU idle state management subsystem. cpusets.txt - documents the cpusets feature; assign CPUs and Mem to a set of tasks. cputopology.txt diff --git a/Documentation/cpuidle/core.txt b/Documentation/cpuidle/core.txt new file mode 100644 index 000000000000..63ecc5dc9d8a --- /dev/null +++ b/Documentation/cpuidle/core.txt @@ -0,0 +1,23 @@ + + Supporting multiple CPU idle levels in kernel + + cpuidle + +General Information: + +Various CPUs today support multiple idle levels that are differentiated +by varying exit latencies and power consumption during idle. +cpuidle is a generic in-kernel infrastructure that separates +idle policy (governor) from idle mechanism (driver) and provides a +standardized infrastructure to support independent development of +governors and drivers. + +cpuidle resides under drivers/cpuidle. + +Boot options: +"cpuidle_sysfs_switch" +enables current_governor interface in /sys/devices/system/cpu/cpuidle/, +which can be used to switch governors at run time. This boot option +is meant for developer testing only. In normal usage, kernel picks the +best governor based on governor ratings. +SEE ALSO: sysfs.txt in this directory. diff --git a/Documentation/cpuidle/driver.txt b/Documentation/cpuidle/driver.txt new file mode 100644 index 000000000000..7a9e09ece931 --- /dev/null +++ b/Documentation/cpuidle/driver.txt @@ -0,0 +1,31 @@ + + + Supporting multiple CPU idle levels in kernel + + cpuidle drivers + + + + +cpuidle driver hooks into the cpuidle infrastructure and handles the +architecture/platform dependent part of CPU idle states. Driver +provides the platform idle state detection capability and also +has mechanisms in place to support actual entry-exit into CPU idle states. + +cpuidle driver initializes the cpuidle_device structure for each CPU device +and registers with cpuidle using cpuidle_register_device. + +It can also support the dynamic changes (like battery <-> AC), by using +cpuidle_pause_and_lock, cpuidle_disable_device and cpuidle_enable_device, +cpuidle_resume_and_unlock. + +Interfaces: +extern int cpuidle_register_driver(struct cpuidle_driver *drv); +extern void cpuidle_unregister_driver(struct cpuidle_driver *drv); +extern int cpuidle_register_device(struct cpuidle_device *dev); +extern void cpuidle_unregister_device(struct cpuidle_device *dev); + +extern void cpuidle_pause_and_lock(void); +extern void cpuidle_resume_and_unlock(void); +extern int cpuidle_enable_device(struct cpuidle_device *dev); +extern void cpuidle_disable_device(struct cpuidle_device *dev); diff --git a/Documentation/cpuidle/governor.txt b/Documentation/cpuidle/governor.txt new file mode 100644 index 000000000000..12c6bd50c9f6 --- /dev/null +++ b/Documentation/cpuidle/governor.txt @@ -0,0 +1,29 @@ + + + + Supporting multiple CPU idle levels in kernel + + cpuidle governors + + + + +cpuidle governor is policy routine that decides what idle state to enter at +any given time. cpuidle core uses different callbacks to the governor. + +* enable() to enable governor for a particular device +* disable() to disable governor for a particular device +* select() to select an idle state to enter +* reflect() called after returning from the idle state, which can be used + by the governor for some record keeping. + +More than one governor can be registered at the same time and +users can switch between drivers using /sysfs interface (when enabled). +More than one governor part is supported for developers to easily experiment +with different governors. By default, most optimal governor based on your +kernel configuration and platform will be selected by cpuidle. + +Interfaces: +extern int cpuidle_register_governor(struct cpuidle_governor *gov); +extern void cpuidle_unregister_governor(struct cpuidle_governor *gov); +struct cpuidle_governor diff --git a/Documentation/cpuidle/sysfs.txt b/Documentation/cpuidle/sysfs.txt new file mode 100644 index 000000000000..50d7b1642759 --- /dev/null +++ b/Documentation/cpuidle/sysfs.txt @@ -0,0 +1,79 @@ + + + Supporting multiple CPU idle levels in kernel + + cpuidle sysfs + +System global cpuidle related information and tunables are under +/sys/devices/system/cpu/cpuidle + +The current interfaces in this directory has self-explanatory names: +* current_driver +* current_governor_ro + +With cpuidle_sysfs_switch boot option (meant for developer testing) +following objects are visible instead. +* current_driver +* available_governors +* current_governor +In this case users can switch the governor at run time by writing +to current_governor. + + +Per logical CPU specific cpuidle information are under +/sys/devices/system/cpu/cpuX/cpuidle +for each online cpu X + +-------------------------------------------------------------------------------- +# ls -lR /sys/devices/system/cpu/cpu0/cpuidle/ +/sys/devices/system/cpu/cpu0/cpuidle/: +total 0 +drwxr-xr-x 2 root root 0 Feb 8 10:42 state0 +drwxr-xr-x 2 root root 0 Feb 8 10:42 state1 +drwxr-xr-x 2 root root 0 Feb 8 10:42 state2 +drwxr-xr-x 2 root root 0 Feb 8 10:42 state3 + +/sys/devices/system/cpu/cpu0/cpuidle/state0: +total 0 +-r--r--r-- 1 root root 4096 Feb 8 10:42 desc +-r--r--r-- 1 root root 4096 Feb 8 10:42 latency +-r--r--r-- 1 root root 4096 Feb 8 10:42 name +-r--r--r-- 1 root root 4096 Feb 8 10:42 power +-r--r--r-- 1 root root 4096 Feb 8 10:42 time +-r--r--r-- 1 root root 4096 Feb 8 10:42 usage + +/sys/devices/system/cpu/cpu0/cpuidle/state1: +total 0 +-r--r--r-- 1 root root 4096 Feb 8 10:42 desc +-r--r--r-- 1 root root 4096 Feb 8 10:42 latency +-r--r--r-- 1 root root 4096 Feb 8 10:42 name +-r--r--r-- 1 root root 4096 Feb 8 10:42 power +-r--r--r-- 1 root root 4096 Feb 8 10:42 time +-r--r--r-- 1 root root 4096 Feb 8 10:42 usage + +/sys/devices/system/cpu/cpu0/cpuidle/state2: +total 0 +-r--r--r-- 1 root root 4096 Feb 8 10:42 desc +-r--r--r-- 1 root root 4096 Feb 8 10:42 latency +-r--r--r-- 1 root root 4096 Feb 8 10:42 name +-r--r--r-- 1 root root 4096 Feb 8 10:42 power +-r--r--r-- 1 root root 4096 Feb 8 10:42 time +-r--r--r-- 1 root root 4096 Feb 8 10:42 usage + +/sys/devices/system/cpu/cpu0/cpuidle/state3: +total 0 +-r--r--r-- 1 root root 4096 Feb 8 10:42 desc +-r--r--r-- 1 root root 4096 Feb 8 10:42 latency +-r--r--r-- 1 root root 4096 Feb 8 10:42 name +-r--r--r-- 1 root root 4096 Feb 8 10:42 power +-r--r--r-- 1 root root 4096 Feb 8 10:42 time +-r--r--r-- 1 root root 4096 Feb 8 10:42 usage +-------------------------------------------------------------------------------- + + +* desc : Small description about the idle state (string) +* latency : Latency to exit out of this idle state (in microseconds) +* name : Name of the idle state (string) +* power : Power consumed while in this idle state (in milliwatts) +* time : Total time spent in this idle state (in microseconds) +* usage : Number of times this state was entered (count) diff --git a/Documentation/i386/IO-APIC.txt b/Documentation/i386/IO-APIC.txt index 435e69e6e9aa..f95166645d29 100644 --- a/Documentation/i386/IO-APIC.txt +++ b/Documentation/i386/IO-APIC.txt @@ -1,12 +1,14 @@ Most (all) Intel-MP compliant SMP boards have the so-called 'IO-APIC', -which is an enhanced interrupt controller, it enables us to route -hardware interrupts to multiple CPUs, or to CPU groups. +which is an enhanced interrupt controller. It enables us to route +hardware interrupts to multiple CPUs, or to CPU groups. Without an +IO-APIC, interrupts from hardware will be delivered only to the +CPU which boots the operating system (usually CPU#0). Linux supports all variants of compliant SMP boards, including ones with -multiple IO-APICs. (multiple IO-APICs are used in high-end servers to -distribute IRQ load further). +multiple IO-APICs. Multiple IO-APICs are used in high-end servers to +distribute IRQ load further. -There are (a few) known breakages in certain older boards, which bugs are +There are (a few) known breakages in certain older boards, such bugs are usually worked around by the kernel. If your MP-compliant SMP board does not boot Linux, then consult the linux-smp mailing list archives first. @@ -28,18 +30,18 @@ If your box boots fine with enabled IO-APIC IRQs, then your hell:~> <---------------------------- -some interrupts are still listed as 'XT PIC', but this is not a problem, +Some interrupts are still listed as 'XT PIC', but this is not a problem; none of those IRQ sources is performance-critical. -in the unlikely case that your board does not create a working mp-table, +In the unlikely case that your board does not create a working mp-table, you can use the pirq= boot parameter to 'hand-construct' IRQ entries. This -is nontrivial though and cannot be automated. One sample /etc/lilo.conf +is non-trivial though and cannot be automated. One sample /etc/lilo.conf entry: append="pirq=15,11,10" -the actual numbers depend on your system, on your PCI cards and on their +The actual numbers depend on your system, on your PCI cards and on their PCI slot position. Usually PCI slots are 'daisy chained' before they are connected to the PCI chipset IRQ routing facility (the incoming PIRQ1-4 lines): @@ -54,7 +56,7 @@ lines): PIRQ1 ----| |- `----| |- `----| |- `----| |--------| | `-' `-' `-' `-' `-' -every PCI card emits a PCI IRQ, which can be INTA,INTB,INTC,INTD: +Every PCI card emits a PCI IRQ, which can be INTA, INTB, INTC or INTD: ,-. INTD--| | @@ -95,21 +97,21 @@ card (IRQ11) in Slot3, and have Slot1 empty: [value '0' is a generic 'placeholder', reserved for empty (or non-IRQ emitting) slots.] -generally, it's always possible to find out the correct pirq= settings, just +Generally, it's always possible to find out the correct pirq= settings, just permute all IRQ numbers properly ... it will take some time though. An 'incorrect' pirq line will cause the booting process to hang, or a device -won't function properly (if it's inserted as eg. a module). +won't function properly (e.g. if it's inserted as a module). -If you have 2 PCI buses, then you can use up to 8 pirq values. Although such +If you have 2 PCI buses, then you can use up to 8 pirq values, although such boards tend to have a good configuration. Be prepared that it might happen that you need some strange pirq line: append="pirq=0,0,0,0,0,0,9,11" -use smart try-and-err techniques to find out the correct pirq line ... +Use smart trial-and-error techniques to find out the correct pirq line ... -good luck and mail to linux-smp@vger.kernel.org or +Good luck and mail to linux-smp@vger.kernel.org or linux-kernel@vger.kernel.org if you have any problems that are not covered by this document. diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index a4fc7fc21439..9a5b6658c65e 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -950,6 +950,41 @@ and is between 256 and 4096 characters. It is defined in the file when set. Format: + libata.force= [LIBATA] Force configurations. The format is comma + separated list of "[ID:]VAL" where ID is + PORT[:DEVICE]. PORT and DEVICE are decimal numbers + matching port, link or device. Basically, it matches + the ATA ID string printed on console by libata. If + the whole ID part is omitted, the last PORT and DEVICE + values are used. If ID hasn't been specified yet, the + configuration applies to all ports, links and devices. + + If only DEVICE is omitted, the parameter applies to + the port and all links and devices behind it. DEVICE + number of 0 either selects the first device or the + first fan-out link behind PMP device. It does not + select the host link. DEVICE number of 15 selects the + host link and device attached to it. + + The VAL specifies the configuration to force. As long + as there's no ambiguity shortcut notation is allowed. + For example, both 1.5 and 1.5G would work for 1.5Gbps. + The following configurations can be forced. + + * Cable type: 40c, 80c, short40c, unk, ign or sata. + Any ID with matching PORT is used. + + * SATA link speed limit: 1.5Gbps or 3.0Gbps. + + * Transfer mode: pio[0-7], mwdma[0-4] and udma[0-7]. + udma[/][16,25,33,44,66,100,133] notation is also + allowed. + + * [no]ncq: Turn on or off NCQ. + + If there are multiple matching configurations changing + the same attribute, the last one is used. + load_ramdisk= [RAM] List of ramdisks to load from floppy See Documentation/ramdisk.txt. @@ -1056,8 +1091,6 @@ and is between 256 and 4096 characters. It is defined in the file [SCSI] Maximum number of LUNs received. Should be between 1 and 16384. - mca-pentium [BUGS=X86-32] - mcatest= [IA-64] mce [X86-32] Machine Check Exception diff --git a/Documentation/laptops/thinkpad-acpi.txt b/Documentation/laptops/thinkpad-acpi.txt index 6c2477754a2a..76cb428435da 100644 --- a/Documentation/laptops/thinkpad-acpi.txt +++ b/Documentation/laptops/thinkpad-acpi.txt @@ -160,7 +160,7 @@ Hot keys procfs: /proc/acpi/ibm/hotkey sysfs device attribute: hotkey_* -In a ThinkPad, the ACPI HKEY handler is responsible for comunicating +In a ThinkPad, the ACPI HKEY handler is responsible for communicating some important events and also keyboard hot key presses to the operating system. Enabling the hotkey functionality of thinkpad-acpi signals the firmware that such a driver is present, and modifies how the ThinkPad @@ -193,7 +193,7 @@ Not all bits in the mask can be modified. Not all bits that can be modified do anything. Not all hot keys can be individually controlled by the mask. Some models do not support the mask at all, and in those models, hot keys cannot be controlled individually. The behaviour of -the mask is, therefore, higly dependent on the ThinkPad model. +the mask is, therefore, highly dependent on the ThinkPad model. Note that unmasking some keys prevents their default behavior. For example, if Fn+F5 is unmasked, that key will no longer enable/disable @@ -288,7 +288,7 @@ sysfs notes: in ACPI event mode, volume up/down/mute are reported as separate events, but this behaviour may be corrected in future releases of this driver, in which case the - ThinkPad volume mixer user interface semanthics will be + ThinkPad volume mixer user interface semantics will be enforced. hotkey_poll_freq: @@ -306,13 +306,20 @@ sysfs notes: The recommended polling frequency is 10Hz. hotkey_radio_sw: - if the ThinkPad has a hardware radio switch, this + If the ThinkPad has a hardware radio switch, this attribute will read 0 if the switch is in the "radios - disabled" postition, and 1 if the switch is in the + disabled" position, and 1 if the switch is in the "radios enabled" position. This attribute has poll()/select() support. + hotkey_tablet_mode: + If the ThinkPad has tablet capabilities, this attribute + will read 0 if the ThinkPad is in normal mode, and + 1 if the ThinkPad is in tablet mode. + + This attribute has poll()/select() support. + hotkey_report_mode: Returns the state of the procfs ACPI event report mode filter for hot keys. If it is set to 1 (the default), @@ -339,7 +346,7 @@ sysfs notes: wakeup_hotunplug_complete: Set to 1 if the system was waken up because of an undock or bay ejection request, and that request - was sucessfully completed. At this point, it might + was successfully completed. At this point, it might be useful to send the system back to sleep, at the user's choice. Refer to HKEY events 0x4003 and 0x3003, below. @@ -392,7 +399,7 @@ event code Key Notes Lenovo: battery 0x1004 0x03 FN+F4 Sleep button (ACPI sleep button - semanthics, i.e. sleep-to-RAM). + semantics, i.e. sleep-to-RAM). It is always generate some kind of event, either the hot key event or a ACPI sleep button @@ -403,12 +410,12 @@ event code Key Notes time passes. 0x1005 0x04 FN+F5 Radio. Enables/disables - the internal BlueTooth hardware + the internal Bluetooth hardware and W-WAN card if left in control of the firmware. Does not affect the WLAN card. Should be used to turn on/off all - radios (bluetooth+W-WAN+WLAN), + radios (Bluetooth+W-WAN+WLAN), really. 0x1006 0x05 FN+F6 - @@ -417,7 +424,7 @@ event code Key Notes Do you feel lucky today? 0x1008 0x07 FN+F8 IBM: toggle screen expand - Lenovo: configure ultranav + Lenovo: configure UltraNav 0x1009 0x08 FN+F9 - .. .. .. @@ -447,7 +454,7 @@ event code Key Notes 0x1011 0x10 FN+END Brightness down. See brightness up for details. -0x1012 0x11 FN+PGUP Thinklight toggle. This key is +0x1012 0x11 FN+PGUP ThinkLight toggle. This key is always handled by the firmware, even when unmasked. @@ -469,7 +476,7 @@ event code Key Notes key is always handled by the firmware, even when unmasked. -0x1018 0x17 THINKPAD Thinkpad/Access IBM/Lenovo key +0x1018 0x17 THINKPAD ThinkPad/Access IBM/Lenovo key 0x1019 0x18 unknown .. .. .. @@ -488,9 +495,17 @@ If a key is mapped to KEY_UNKNOWN, it generates an input event that includes an scan code. If a key is mapped to anything else, it will generate input device EV_KEY events. +In addition to the EV_KEY events, thinkpad-acpi may also issue EV_SW +events for switches: + +SW_RADIO T60 and later hardare rfkill rocker switch +SW_TABLET_MODE Tablet ThinkPads HKEY events 0x5009 and 0x500A + Non hot-key ACPI HKEY event map: 0x5001 Lid closed 0x5002 Lid opened +0x5009 Tablet swivel: switched to tablet mode +0x500A Tablet swivel: switched to normal mode 0x7000 Radio Switch may have changed state The above events are not propagated by the driver, except for legacy @@ -505,9 +520,7 @@ The above events are never propagated by the driver. 0x3003 Bay ejection (see 0x2x05) complete, can sleep again 0x4003 Undocked (see 0x2x04), can sleep again -0x5009 Tablet swivel: switched to tablet mode -0x500A Tablet swivel: switched to normal mode -0x500B Tablet pen insterted into its storage bay +0x500B Tablet pen inserted into its storage bay 0x500C Tablet pen removed from its storage bay 0x5010 Brightness level changed (newer Lenovo BIOSes) @@ -539,7 +552,7 @@ sysfs (it is read-only). If the hotkey_report_mode module parameter is set to 1 or 2, it cannot be changed later through sysfs (any writes will return -EPERM to signal that hotkey_report_mode was locked. On 2.6.23 and later, where -hotkey_report_mode cannot be changed at all, writes will return -EACES). +hotkey_report_mode cannot be changed at all, writes will return -EACCES). hotkey_report_mode set to 1 makes the driver export through the procfs ACPI event interface all hot key presses (which are *also* sent to the @@ -584,7 +597,7 @@ Sysfs notes: 0: disables Bluetooth / Bluetooth is disabled 1: enables Bluetooth / Bluetooth is enabled. - Note: this interface will be probably be superseeded by the + Note: this interface will be probably be superseded by the generic rfkill class, so it is NOT to be considered stable yet. Video output control -- /proc/acpi/ibm/video @@ -791,12 +804,12 @@ on the X40 (tpb is the ThinkPad Buttons utility): 1 - Related to "Volume up" key press 2 - Related to "Mute on" key press 3 - Related to "Access IBM" key press - 4 - Related to "LCD brightness up" key pess + 4 - Related to "LCD brightness up" key press 5 - Related to "LCD brightness down" key press 11 - Related to "toggle screen expansion" key press/function 12 - Related to "ThinkLight on" 13 - Related to "ThinkLight off" - 14 - Related to "ThinkLight" key press (toggle thinklight) + 14 - Related to "ThinkLight" key press (toggle ThinkLight) The cmos command interface is prone to firmware split-brain problems, as in newer ThinkPads it is just a compatibility layer. Do not use it, it is @@ -1024,7 +1037,7 @@ There are two interfaces to the firmware for direct brightness control, EC and CMOS. To select which one should be used, use the brightness_mode module parameter: brightness_mode=1 selects EC mode, brightness_mode=2 selects CMOS mode, brightness_mode=3 selects both EC -and CMOS. The driver tries to autodetect which interface to use. +and CMOS. The driver tries to auto-detect which interface to use. When display backlight brightness controls are available through the standard ACPI interface, it is best to use it instead of this direct @@ -1266,8 +1279,8 @@ experimental=1 parameter when loading the module. This feature shows the presence and current state of a W-WAN (Sierra Wireless EV-DO) device. -It was tested on a Lenovo Thinkpad X60. It should probably work on other -Thinkpad models which come with this module installed. +It was tested on a Lenovo ThinkPad X60. It should probably work on other +ThinkPad models which come with this module installed. Procfs notes: @@ -1286,7 +1299,7 @@ Sysfs notes: 0: disables WWAN card / WWAN card is disabled 1: enables WWAN card / WWAN card is enabled. - Note: this interface will be probably be superseeded by the + Note: this interface will be probably be superseded by the generic rfkill class, so it is NOT to be considered stable yet. Multiple Commands, Module Parameters @@ -1309,7 +1322,7 @@ Enabling debugging output The module takes a debug parameter which can be used to selectively enable various classes of debugging output, for example: - modprobe ibm_acpi debug=0xffff + modprobe thinkpad_acpi debug=0xffff will enable all debugging output classes. It takes a bitmask, so to enable more than one output class, just add their values. @@ -1356,7 +1369,7 @@ Sysfs interface changelog: NVRAM is compiled out by the user because it is unneeded/undesired in the first place). 0x020101: Marker for thinkpad-acpi with hot key NVRAM polling - and proper hotkey_mask semanthics (version 8 of the + and proper hotkey_mask semantics (version 8 of the NVRAM polling patch). Some development snapshots of 0.18 had an earlier version that did strange things to hotkey_mask. diff --git a/Documentation/networking/tcp.txt b/Documentation/networking/tcp.txt index 0121edc3ba06..7d11bb5dc30a 100644 --- a/Documentation/networking/tcp.txt +++ b/Documentation/networking/tcp.txt @@ -1,7 +1,7 @@ TCP protocol ============ -Last updated: 21 June 2005 +Last updated: 9 February 2008 Contents ======== @@ -52,9 +52,9 @@ research and RFC's before developing new modules. The method that is used to determine which congestion control mechanism is determined by the setting of the sysctl net.ipv4.tcp_congestion_control. The default congestion control will be the last one registered (LIFO); -so if you built everything as modules. the default will be reno. If you -build with the default's from Kconfig, then BIC will be builtin (not a module) -and it will end up the default. +so if you built everything as modules, the default will be reno. If you +build with the defaults from Kconfig, then CUBIC will be builtin (not a +module) and it will end up the default. If you really want a particular default value then you will need to set it with the sysctl. If you use a sysctl, the module will be autoloaded diff --git a/Documentation/video4linux/CARDLIST.em28xx b/Documentation/video4linux/CARDLIST.em28xx index 6a8469f2bcae..f40e09296f30 100644 --- a/Documentation/video4linux/CARDLIST.em28xx +++ b/Documentation/video4linux/CARDLIST.em28xx @@ -8,7 +8,7 @@ 7 -> Leadtek Winfast USB II (em2800) 8 -> Kworld USB2800 (em2800) 9 -> Pinnacle Dazzle DVC 90/DVC 100 (em2820/em2840) [2304:0207,2304:021a] - 10 -> Hauppauge WinTV HVR 900 (em2880) [2040:6500] + 10 -> Hauppauge WinTV HVR 900 (em2880) [2040:6500,2040:6502] 11 -> Terratec Hybrid XS (em2880) [0ccd:0042] 12 -> Kworld PVR TV 2800 RF (em2820/em2840) 13 -> Terratec Prodigy XS (em2880) [0ccd:0047] diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index 5d3b6b4d2515..0424901ebc78 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 @@ -92,9 +92,9 @@ 91 -> AVerMedia A169 B [1461:7360] 92 -> AVerMedia A169 B1 [1461:6360] 93 -> Medion 7134 Bridge #2 [16be:0005] - 94 -> LifeView FlyDVB-T Hybrid Cardbus/MSI TV @nywhere A/D NB [5168:3306,5168:3502,4e42:3502] + 94 -> LifeView FlyDVB-T Hybrid Cardbus/MSI TV @nywhere A/D NB [5168:3306,5168:3502,5168:3307,4e42:3502] 95 -> LifeView FlyVIDEO3000 (NTSC) [5169:0138] - 96 -> Medion Md8800 Quadro [16be:0007,16be:0008] + 96 -> Medion Md8800 Quadro [16be:0007,16be:0008,16be:000d] 97 -> LifeView FlyDVB-S /Acorp TV134DS [5168:0300,4e42:0300] 98 -> Proteus Pro 2309 [0919:2003] 99 -> AVerMedia TV Hybrid A16AR [1461:2c00] @@ -129,3 +129,5 @@ 128 -> Beholder BeholdTV Columbus TVFM [0000:5201] 129 -> Beholder BeholdTV 607 / BeholdTV 609 [5ace:6070,5ace:6071,5ace:6072,5ace:6073,5ace:6090,5ace:6091,5ace:6092,5ace:6093] 130 -> Beholder BeholdTV M6 / BeholdTV M6 Extra [5ace:6190,5ace:6193] +131 -> Twinhan Hybrid DTV-DVB 3056 PCI [1822:0022] +132 -> Genius TVGO AM11MCE diff --git a/Documentation/video4linux/zr364xx.txt b/Documentation/video4linux/zr364xx.txt index 4d9a0c33f2fd..5c81e3ae6458 100644 --- a/Documentation/video4linux/zr364xx.txt +++ b/Documentation/video4linux/zr364xx.txt @@ -25,7 +25,7 @@ modprobe zr364xx debug=X mode=Y - debug : set to 1 to enable verbose debug messages - mode : 0 = 320x240, 1 = 160x120, 2 = 640x480 You can then use the camera with V4L2 compatible applications, for example Ekiga. -To capture a single image, try this: dd if=/dev/video0 of=test.jpg bs=1 count=1 +To capture a single image, try this: dd if=/dev/video0 of=test.jpg bs=1M count=1 links : http://mxhaard.free.fr/ (support for many others cams including some Aiptek PocketDV) @@ -63,3 +63,5 @@ Vendor Product Distributor Model 0x06d6 0x0034 Trust Powerc@m 750 0x0a17 0x0062 Pentax Optio 50L 0x06d6 0x003b Trust Powerc@m 970Z +0x0a17 0x004e Pentax Optio 50 +0x041e 0x405d Creative DiVi CAM 516 diff --git a/MAINTAINERS b/MAINTAINERS index 6680ec44779e..082d1ee154a9 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1255,8 +1255,8 @@ W: http://linux-net.osdl.org/index.php/DCCP S: Maintained DECnet NETWORK LAYER -P: Patrick Caulfield -M: patrick@tykepenguin.com +P: Christine Caulfield +M: christine.caulfield@googlemail.com W: http://linux-decnet.sourceforge.net L: linux-decnet-user@lists.sourceforge.net S: Maintained @@ -1318,8 +1318,8 @@ L: linux-kernel@vger.kernel.org S: Maintained DISTRIBUTED LOCK MANAGER -P: Patrick Caulfield -M: pcaulfie@redhat.com +P: Christine Caulfield +M: ccaulfie@redhat.com P: David Teigland M: teigland@redhat.com L: cluster-devel@redhat.com @@ -1616,6 +1616,7 @@ S: Maintained FILESYSTEMS (VFS and infrastructure) P: Alexander Viro M: viro@zeniv.linux.org.uk +L: linux-fsdevel@vger.kernel.org S: Maintained FIREWIRE SUBSYSTEM (drivers/firewire, ) @@ -1923,7 +1924,7 @@ S: Maintained IDE/ATAPI CDROM DRIVER P: Borislav Petkov -M: bbpetkov@yahoo.de +M: petkovbb@gmail.com L: linux-ide@vger.kernel.org S: Maintained diff --git a/Makefile b/Makefile index c162370c7367..99300dc680e9 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,8 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 25 -EXTRAVERSION = -rc1 -NAME = Arr Matey! A Hairy Bilge Rat! +EXTRAVERSION = -rc2 +NAME = Funky Weasel is Jiggy wit it # *DOCUMENTATION* # To see a list of typical targets execute "make help" @@ -507,6 +507,10 @@ else KBUILD_CFLAGS += -O2 endif +# Force gcc to behave correct even for buggy distributions +# Arch Makefiles may override this setting +KBUILD_CFLAGS += $(call cc-option, -fno-stack-protector) + include $(srctree)/arch/$(SRCARCH)/Makefile ifdef CONFIG_FRAME_POINTER @@ -525,9 +529,6 @@ ifdef CONFIG_DEBUG_SECTION_MISMATCH KBUILD_CFLAGS += $(call cc-option, -fno-inline-functions-called-once) endif -# Force gcc to behave correct even for buggy distributions -KBUILD_CFLAGS += $(call cc-option, -fno-stack-protector) - # arch Makefile may override CC so keep this after arch Makefile is included NOSTDINC_FLAGS += -nostdinc -isystem $(shell $(CC) -print-file-name=include) CHECKFLAGS += $(NOSTDINC_FLAGS) @@ -810,7 +811,9 @@ endif $(Q)rm -f .old_version # build vmlinux.o first to catch section mismatch errors early -$(kallsyms.o): vmlinux.o +ifdef CONFIG_KALLSYMS +.tmp_vmlinux1: vmlinux.o +endif vmlinux.o: $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) FORCE $(call if_changed_rule,vmlinux-modpost) diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c index 973c5c3705e3..8c71daf94a59 100644 --- a/arch/alpha/kernel/osf_sys.c +++ b/arch/alpha/kernel/osf_sys.c @@ -259,8 +259,8 @@ osf_statfs(char __user *path, struct osf_statfs __user *buffer, unsigned long bu retval = user_path_walk(path, &nd); if (!retval) { - retval = do_osf_statfs(nd.dentry, buffer, bufsiz); - path_release(&nd); + retval = do_osf_statfs(nd.path.dentry, buffer, bufsiz); + path_put(&nd.path); } return retval; } diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c index 58717cb19707..56a67ab698c7 100644 --- a/arch/blackfin/kernel/traps.c +++ b/arch/blackfin/kernel/traps.c @@ -126,15 +126,13 @@ static void decode_address(char *buf, unsigned long address) struct vm_area_struct *vma = vml->vma; if (address >= vma->vm_start && address < vma->vm_end) { + char _tmpbuf[256]; char *name = p->comm; struct file *file = vma->vm_file; - if (file) { - char _tmpbuf[256]; - name = d_path(file->f_dentry, - file->f_vfsmnt, - _tmpbuf, - sizeof(_tmpbuf)); - } + + if (file) + name = d_path(&file->f_path, _tmpbuf, + sizeof(_tmpbuf)); /* FLAT does not have its text aligned to the start of * the map while FDPIC ELF does ... diff --git a/arch/cris/arch-v10/lib/memset.c b/arch/cris/arch-v10/lib/memset.c index 42c1101043a3..c94ea9b3ec29 100644 --- a/arch/cris/arch-v10/lib/memset.c +++ b/arch/cris/arch-v10/lib/memset.c @@ -1,252 +1,259 @@ -/*#************************************************************************#*/ -/*#-------------------------------------------------------------------------*/ -/*# */ -/*# FUNCTION NAME: memset() */ -/*# */ -/*# PARAMETERS: void* dst; Destination address. */ -/*# int c; Value of byte to write. */ -/*# int len; Number of bytes to write. */ -/*# */ -/*# RETURNS: dst. */ -/*# */ -/*# DESCRIPTION: Sets the memory dst of length len bytes to c, as standard. */ -/*# Framework taken from memcpy. This routine is */ -/*# very sensitive to compiler changes in register allocation. */ -/*# Should really be rewritten to avoid this problem. */ -/*# */ -/*#-------------------------------------------------------------------------*/ -/*# */ -/*# HISTORY */ -/*# */ -/*# DATE NAME CHANGES */ -/*# ---- ---- ------- */ -/*# 990713 HP Tired of watching this function (or */ -/*# really, the nonoptimized generic */ -/*# implementation) take up 90% of simulator */ -/*# output. Measurements needed. */ -/*# */ -/*#-------------------------------------------------------------------------*/ +/* A memset for CRIS. + Copyright (C) 1999-2005 Axis Communications. + All rights reserved. -#include + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: -/* No, there's no macro saying 12*4, since it is "hard" to get it into - the asm in a good way. Thus better to expose the problem everywhere. - */ + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. -/* Assuming 1 cycle per dword written or read (ok, not really true), and - one per instruction, then 43+3*(n/48-1) <= 24+24*(n/48-1) - so n >= 45.7; n >= 0.9; we win on the first full 48-byte block to set. */ + 2. Neither the name of Axis Communications nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. -#define ZERO_BLOCK_SIZE (1*12*4) + THIS SOFTWARE IS PROVIDED BY AXIS COMMUNICATIONS AND ITS CONTRIBUTORS + ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL AXIS + COMMUNICATIONS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. */ -void *memset(void *pdst, - int c, - size_t plen) +/* FIXME: This file should really only be used for reference, as the + result is somewhat depending on gcc generating what we expect rather + than what we describe. An assembly file should be used instead. */ + +/* Note the multiple occurrence of the expression "12*4", including the + asm. It is hard to get it into the asm in a good way. Thus better to + expose the problem everywhere: no macro. */ + +/* Assuming one cycle per dword written or read (ok, not really true; the + world is not ideal), and one cycle per instruction, then 43+3*(n/48-1) + <= 24+24*(n/48-1) so n >= 45.7; n >= 0.9; we win on the first full + 48-byte block to set. */ + +#define MEMSET_BY_BLOCK_THRESHOLD (1 * 48) + +/* No name ambiguities in this file. */ +__asm__ (".syntax no_register_prefix"); + +void *memset(void *pdst, int c, unsigned int plen) { - /* Ok. Now we want the parameters put in special registers. - Make sure the compiler is able to make something useful of this. */ + /* Now we want the parameters in special registers. Make sure the + compiler does something usable with this. */ register char *return_dst __asm__ ("r10") = pdst; register int n __asm__ ("r12") = plen; register int lc __asm__ ("r11") = c; - /* Most apps use memset sanely. Only those memsetting about 3..4 - bytes or less get penalized compared to the generic implementation - - and that's not really sane use. */ + /* Most apps use memset sanely. Memsetting about 3..4 bytes or less get + penalized here compared to the generic implementation. */ - /* Ugh. This is fragile at best. Check with newer GCC releases, if - they compile cascaded "x |= x << 8" sanely! */ - __asm__("movu.b %0,$r13\n\t" - "lslq 8,$r13\n\t" - "move.b %0,$r13\n\t" - "move.d $r13,%0\n\t" - "lslq 16,$r13\n\t" - "or.d $r13,%0" - : "=r" (lc) : "0" (lc) : "r13"); + /* This is fragile performancewise at best. Check with newer GCC + releases, if they compile cascaded "x |= x << 8" to sane code. */ + __asm__("movu.b %0,r13 \n\ + lslq 8,r13 \n\ + move.b %0,r13 \n\ + move.d r13,%0 \n\ + lslq 16,r13 \n\ + or.d r13,%0" + : "=r" (lc) /* Inputs. */ + : "0" (lc) /* Outputs. */ + : "r13"); /* Trash. */ { register char *dst __asm__ ("r13") = pdst; - /* This is NONPORTABLE, but since this whole routine is */ - /* grossly nonportable that doesn't matter. */ + if (((unsigned long) pdst & 3) != 0 + /* Oops! n = 0 must be a valid call, regardless of alignment. */ + && n >= 3) + { + if ((unsigned long) dst & 1) + { + *dst = (char) lc; + n--; + dst++; + } - if (((unsigned long) pdst & 3) != 0 - /* Oops! n=0 must be a legal call, regardless of alignment. */ - && n >= 3) - { - if ((unsigned long)dst & 1) - { - *dst = (char) lc; - n--; - dst++; - } + if ((unsigned long) dst & 2) + { + *(short *) dst = lc; + n -= 2; + dst += 2; + } + } - if ((unsigned long)dst & 2) - { - *(short *)dst = lc; - n -= 2; - dst += 2; - } - } - - /* Now the fun part. For the threshold value of this, check the equation - above. */ - /* Decide which copying method to use. */ - if (n >= ZERO_BLOCK_SIZE) - { - /* For large copies we use 'movem' */ - - /* It is not optimal to tell the compiler about clobbering any - registers; that will move the saving/restoring of those registers - to the function prologue/epilogue, and make non-movem sizes - suboptimal. - - This method is not foolproof; it assumes that the "asm reg" - declarations at the beginning of the function really are used - here (beware: they may be moved to temporary registers). - This way, we do not have to save/move the registers around into - temporaries; we can safely use them straight away. - - If you want to check that the allocation was right; then - check the equalities in the first comment. It should say - "r13=r13, r12=r12, r11=r11" */ - __asm__ volatile ("\n\ - ;; Check that the following is true (same register names on \n\ - ;; both sides of equal sign, as in r8=r8): \n\ - ;; %0=r13, %1=r12, %4=r11 \n\ - ;; \n\ - ;; Save the registers we'll clobber in the movem process \n\ - ;; on the stack. Don't mention them to gcc, it will only be \n\ - ;; upset. \n\ - subq 11*4,$sp \n\ - movem $r10,[$sp] \n\ + /* Decide which setting method to use. */ + if (n >= MEMSET_BY_BLOCK_THRESHOLD) + { + /* It is not optimal to tell the compiler about clobbering any + registers; that will move the saving/restoring of those registers + to the function prologue/epilogue, and make non-block sizes + suboptimal. */ + __asm__ volatile + ("\ + ;; GCC does promise correct register allocations, but let's \n\ + ;; make sure it keeps its promises. \n\ + .ifnc %0-%1-%4,$r13-$r12-$r11 \n\ + .error \"GCC reg alloc bug: %0-%1-%4 != $r13-$r12-$r11\" \n\ + .endif \n\ \n\ - move.d $r11,$r0 \n\ - move.d $r11,$r1 \n\ - move.d $r11,$r2 \n\ - move.d $r11,$r3 \n\ - move.d $r11,$r4 \n\ - move.d $r11,$r5 \n\ - move.d $r11,$r6 \n\ - move.d $r11,$r7 \n\ - move.d $r11,$r8 \n\ - move.d $r11,$r9 \n\ - move.d $r11,$r10 \n\ + ;; Save the registers we'll clobber in the movem process \n\ + ;; on the stack. Don't mention them to gcc, it will only be \n\ + ;; upset. \n\ + subq 11*4,sp \n\ + movem r10,[sp] \n\ \n\ - ;; Now we've got this: \n\ - ;; r13 - dst \n\ - ;; r12 - n \n\ + move.d r11,r0 \n\ + move.d r11,r1 \n\ + move.d r11,r2 \n\ + move.d r11,r3 \n\ + move.d r11,r4 \n\ + move.d r11,r5 \n\ + move.d r11,r6 \n\ + move.d r11,r7 \n\ + move.d r11,r8 \n\ + move.d r11,r9 \n\ + move.d r11,r10 \n\ \n\ - ;; Update n for the first loop \n\ - subq 12*4,$r12 \n\ + ;; Now we've got this: \n\ + ;; r13 - dst \n\ + ;; r12 - n \n\ + \n\ + ;; Update n for the first loop \n\ + subq 12*4,r12 \n\ 0: \n\ - subq 12*4,$r12 \n\ - bge 0b \n\ - movem $r11,[$r13+] \n\ +" +#ifdef __arch_common_v10_v32 + /* Cater to branch offset difference between v32 and v10. We + assume the branch below has an 8-bit offset. */ +" setf\n" +#endif +" subq 12*4,r12 \n\ + bge 0b \n\ + movem r11,[r13+] \n\ \n\ - addq 12*4,$r12 ;; compensate for last loop underflowing n \n\ + ;; Compensate for last loop underflowing n. \n\ + addq 12*4,r12 \n\ \n\ - ;; Restore registers from stack \n\ - movem [$sp+],$r10" + ;; Restore registers from stack. \n\ + movem [sp+],r10" - /* Outputs */ : "=r" (dst), "=r" (n) - /* Inputs */ : "0" (dst), "1" (n), "r" (lc)); + /* Outputs. */ + : "=r" (dst), "=r" (n) - } + /* Inputs. */ + : "0" (dst), "1" (n), "r" (lc)); + } - /* Either we directly starts copying, using dword copying - in a loop, or we copy as much as possible with 'movem' - and then the last block (<44 bytes) is copied here. - This will work since 'movem' will have updated src,dst,n. */ + /* An ad-hoc unroll, used for 4*12-1..16 bytes. */ + while (n >= 16) + { + *(long *) dst = lc; dst += 4; + *(long *) dst = lc; dst += 4; + *(long *) dst = lc; dst += 4; + *(long *) dst = lc; dst += 4; + n -= 16; + } - while ( n >= 16 ) - { - *((long*)dst)++ = lc; - *((long*)dst)++ = lc; - *((long*)dst)++ = lc; - *((long*)dst)++ = lc; - n -= 16; - } - - /* A switch() is definitely the fastest although it takes a LOT of code. - * Particularly if you inline code this. - */ switch (n) - { + { case 0: break; + case 1: - *(char*)dst = (char) lc; + *dst = (char) lc; break; + case 2: - *(short*)dst = (short) lc; + *(short *) dst = (short) lc; break; + case 3: - *((short*)dst)++ = (short) lc; - *(char*)dst = (char) lc; + *(short *) dst = (short) lc; dst += 2; + *dst = (char) lc; break; + case 4: - *((long*)dst)++ = lc; + *(long *) dst = lc; break; + case 5: - *((long*)dst)++ = lc; - *(char*)dst = (char) lc; + *(long *) dst = lc; dst += 4; + *dst = (char) lc; break; + case 6: - *((long*)dst)++ = lc; - *(short*)dst = (short) lc; + *(long *) dst = lc; dst += 4; + *(short *) dst = (short) lc; break; + case 7: - *((long*)dst)++ = lc; - *((short*)dst)++ = (short) lc; - *(char*)dst = (char) lc; + *(long *) dst = lc; dst += 4; + *(short *) dst = (short) lc; dst += 2; + *dst = (char) lc; break; + case 8: - *((long*)dst)++ = lc; - *((long*)dst)++ = lc; + *(long *) dst = lc; dst += 4; + *(long *) dst = lc; break; + case 9: - *((long*)dst)++ = lc; - *((long*)dst)++ = lc; - *(char*)dst = (char) lc; + *(long *) dst = lc; dst += 4; + *(long *) dst = lc; dst += 4; + *dst = (char) lc; break; + case 10: - *((long*)dst)++ = lc; - *((long*)dst)++ = lc; - *(short*)dst = (short) lc; + *(long *) dst = lc; dst += 4; + *(long *) dst = lc; dst += 4; + *(short *) dst = (short) lc; break; + case 11: - *((long*)dst)++ = lc; - *((long*)dst)++ = lc; - *((short*)dst)++ = (short) lc; - *(char*)dst = (char) lc; + *(long *) dst = lc; dst += 4; + *(long *) dst = lc; dst += 4; + *(short *) dst = (short) lc; dst += 2; + *dst = (char) lc; break; + case 12: - *((long*)dst)++ = lc; - *((long*)dst)++ = lc; - *((long*)dst)++ = lc; + *(long *) dst = lc; dst += 4; + *(long *) dst = lc; dst += 4; + *(long *) dst = lc; break; + case 13: - *((long*)dst)++ = lc; - *((long*)dst)++ = lc; - *((long*)dst)++ = lc; - *(char*)dst = (char) lc; + *(long *) dst = lc; dst += 4; + *(long *) dst = lc; dst += 4; + *(long *) dst = lc; dst += 4; + *dst = (char) lc; break; + case 14: - *((long*)dst)++ = lc; - *((long*)dst)++ = lc; - *((long*)dst)++ = lc; - *(short*)dst = (short) lc; + *(long *) dst = lc; dst += 4; + *(long *) dst = lc; dst += 4; + *(long *) dst = lc; dst += 4; + *(short *) dst = (short) lc; break; + case 15: - *((long*)dst)++ = lc; - *((long*)dst)++ = lc; - *((long*)dst)++ = lc; - *((short*)dst)++ = (short) lc; - *(char*)dst = (char) lc; + *(long *) dst = lc; dst += 4; + *(long *) dst = lc; dst += 4; + *(long *) dst = lc; dst += 4; + *(short *) dst = (short) lc; dst += 2; + *dst = (char) lc; break; - } + } } - return return_dst; /* destination pointer. */ -} /* memset() */ + return return_dst; +} diff --git a/arch/cris/arch-v32/lib/memset.c b/arch/cris/arch-v32/lib/memset.c index ffca1214674e..c94ea9b3ec29 100644 --- a/arch/cris/arch-v32/lib/memset.c +++ b/arch/cris/arch-v32/lib/memset.c @@ -1,253 +1,259 @@ -/*#************************************************************************#*/ -/*#-------------------------------------------------------------------------*/ -/*# */ -/*# FUNCTION NAME: memset() */ -/*# */ -/*# PARAMETERS: void* dst; Destination address. */ -/*# int c; Value of byte to write. */ -/*# int len; Number of bytes to write. */ -/*# */ -/*# RETURNS: dst. */ -/*# */ -/*# DESCRIPTION: Sets the memory dst of length len bytes to c, as standard. */ -/*# Framework taken from memcpy. This routine is */ -/*# very sensitive to compiler changes in register allocation. */ -/*# Should really be rewritten to avoid this problem. */ -/*# */ -/*#-------------------------------------------------------------------------*/ -/*# */ -/*# HISTORY */ -/*# */ -/*# DATE NAME CHANGES */ -/*# ---- ---- ------- */ -/*# 990713 HP Tired of watching this function (or */ -/*# really, the nonoptimized generic */ -/*# implementation) take up 90% of simulator */ -/*# output. Measurements needed. */ -/*# */ -/*#-------------------------------------------------------------------------*/ +/* A memset for CRIS. + Copyright (C) 1999-2005 Axis Communications. + All rights reserved. -#include + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: -/* No, there's no macro saying 12*4, since it is "hard" to get it into - the asm in a good way. Thus better to expose the problem everywhere. - */ + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. -/* Assuming 1 cycle per dword written or read (ok, not really true), and - one per instruction, then 43+3*(n/48-1) <= 24+24*(n/48-1) - so n >= 45.7; n >= 0.9; we win on the first full 48-byte block to set. */ + 2. Neither the name of Axis Communications nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. -#define ZERO_BLOCK_SIZE (1*12*4) + THIS SOFTWARE IS PROVIDED BY AXIS COMMUNICATIONS AND ITS CONTRIBUTORS + ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL AXIS + COMMUNICATIONS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. */ -void *memset(void *pdst, - int c, - size_t plen) +/* FIXME: This file should really only be used for reference, as the + result is somewhat depending on gcc generating what we expect rather + than what we describe. An assembly file should be used instead. */ + +/* Note the multiple occurrence of the expression "12*4", including the + asm. It is hard to get it into the asm in a good way. Thus better to + expose the problem everywhere: no macro. */ + +/* Assuming one cycle per dword written or read (ok, not really true; the + world is not ideal), and one cycle per instruction, then 43+3*(n/48-1) + <= 24+24*(n/48-1) so n >= 45.7; n >= 0.9; we win on the first full + 48-byte block to set. */ + +#define MEMSET_BY_BLOCK_THRESHOLD (1 * 48) + +/* No name ambiguities in this file. */ +__asm__ (".syntax no_register_prefix"); + +void *memset(void *pdst, int c, unsigned int plen) { - /* Ok. Now we want the parameters put in special registers. - Make sure the compiler is able to make something useful of this. */ + /* Now we want the parameters in special registers. Make sure the + compiler does something usable with this. */ register char *return_dst __asm__ ("r10") = pdst; register int n __asm__ ("r12") = plen; register int lc __asm__ ("r11") = c; - /* Most apps use memset sanely. Only those memsetting about 3..4 - bytes or less get penalized compared to the generic implementation - - and that's not really sane use. */ + /* Most apps use memset sanely. Memsetting about 3..4 bytes or less get + penalized here compared to the generic implementation. */ - /* Ugh. This is fragile at best. Check with newer GCC releases, if - they compile cascaded "x |= x << 8" sanely! */ - __asm__("movu.b %0,$r13 \n\ - lslq 8,$r13 \n\ - move.b %0,$r13 \n\ - move.d $r13,%0 \n\ - lslq 16,$r13 \n\ - or.d $r13,%0" - : "=r" (lc) : "0" (lc) : "r13"); + /* This is fragile performancewise at best. Check with newer GCC + releases, if they compile cascaded "x |= x << 8" to sane code. */ + __asm__("movu.b %0,r13 \n\ + lslq 8,r13 \n\ + move.b %0,r13 \n\ + move.d r13,%0 \n\ + lslq 16,r13 \n\ + or.d r13,%0" + : "=r" (lc) /* Inputs. */ + : "0" (lc) /* Outputs. */ + : "r13"); /* Trash. */ { register char *dst __asm__ ("r13") = pdst; - /* This is NONPORTABLE, but since this whole routine is */ - /* grossly nonportable that doesn't matter. */ + if (((unsigned long) pdst & 3) != 0 + /* Oops! n = 0 must be a valid call, regardless of alignment. */ + && n >= 3) + { + if ((unsigned long) dst & 1) + { + *dst = (char) lc; + n--; + dst++; + } - if (((unsigned long) pdst & 3) != 0 - /* Oops! n=0 must be a legal call, regardless of alignment. */ - && n >= 3) - { - if ((unsigned long)dst & 1) - { - *dst = (char) lc; - n--; - dst++; - } + if ((unsigned long) dst & 2) + { + *(short *) dst = lc; + n -= 2; + dst += 2; + } + } - if ((unsigned long)dst & 2) - { - *(short *)dst = lc; - n -= 2; - dst += 2; - } - } - - /* Now the fun part. For the threshold value of this, check the equation - above. */ - /* Decide which copying method to use. */ - if (n >= ZERO_BLOCK_SIZE) - { - /* For large copies we use 'movem' */ - - /* It is not optimal to tell the compiler about clobbering any - registers; that will move the saving/restoring of those registers - to the function prologue/epilogue, and make non-movem sizes - suboptimal. - - This method is not foolproof; it assumes that the "asm reg" - declarations at the beginning of the function really are used - here (beware: they may be moved to temporary registers). - This way, we do not have to save/move the registers around into - temporaries; we can safely use them straight away. - - If you want to check that the allocation was right; then - check the equalities in the first comment. It should say - "r13=r13, r12=r12, r11=r11" */ - __asm__ volatile (" \n\ - ;; Check that the register asm declaration got right. \n\ - ;; The GCC manual says it will work, but there *has* been bugs. \n\ - .ifnc %0-%1-%4,$r13-$r12-$r11 \n\ - .err \n\ - .endif \n\ + /* Decide which setting method to use. */ + if (n >= MEMSET_BY_BLOCK_THRESHOLD) + { + /* It is not optimal to tell the compiler about clobbering any + registers; that will move the saving/restoring of those registers + to the function prologue/epilogue, and make non-block sizes + suboptimal. */ + __asm__ volatile + ("\ + ;; GCC does promise correct register allocations, but let's \n\ + ;; make sure it keeps its promises. \n\ + .ifnc %0-%1-%4,$r13-$r12-$r11 \n\ + .error \"GCC reg alloc bug: %0-%1-%4 != $r13-$r12-$r11\" \n\ + .endif \n\ \n\ - ;; Save the registers we'll clobber in the movem process \n\ - ;; on the stack. Don't mention them to gcc, it will only be \n\ - ;; upset. \n\ - subq 11*4,$sp \n\ - movem $r10,[$sp] \n\ + ;; Save the registers we'll clobber in the movem process \n\ + ;; on the stack. Don't mention them to gcc, it will only be \n\ + ;; upset. \n\ + subq 11*4,sp \n\ + movem r10,[sp] \n\ \n\ - move.d $r11,$r0 \n\ - move.d $r11,$r1 \n\ - move.d $r11,$r2 \n\ - move.d $r11,$r3 \n\ - move.d $r11,$r4 \n\ - move.d $r11,$r5 \n\ - move.d $r11,$r6 \n\ - move.d $r11,$r7 \n\ - move.d $r11,$r8 \n\ - move.d $r11,$r9 \n\ - move.d $r11,$r10 \n\ + move.d r11,r0 \n\ + move.d r11,r1 \n\ + move.d r11,r2 \n\ + move.d r11,r3 \n\ + move.d r11,r4 \n\ + move.d r11,r5 \n\ + move.d r11,r6 \n\ + move.d r11,r7 \n\ + move.d r11,r8 \n\ + move.d r11,r9 \n\ + move.d r11,r10 \n\ \n\ - ;; Now we've got this: \n\ - ;; r13 - dst \n\ - ;; r12 - n \n\ + ;; Now we've got this: \n\ + ;; r13 - dst \n\ + ;; r12 - n \n\ \n\ - ;; Update n for the first loop \n\ - subq 12*4,$r12 \n\ + ;; Update n for the first loop \n\ + subq 12*4,r12 \n\ 0: \n\ - subq 12*4,$r12 \n\ - bge 0b \n\ - movem $r11,[$r13+] \n\ +" +#ifdef __arch_common_v10_v32 + /* Cater to branch offset difference between v32 and v10. We + assume the branch below has an 8-bit offset. */ +" setf\n" +#endif +" subq 12*4,r12 \n\ + bge 0b \n\ + movem r11,[r13+] \n\ \n\ - addq 12*4,$r12 ;; compensate for last loop underflowing n \n\ + ;; Compensate for last loop underflowing n. \n\ + addq 12*4,r12 \n\ \n\ - ;; Restore registers from stack \n\ - movem [$sp+],$r10" + ;; Restore registers from stack. \n\ + movem [sp+],r10" - /* Outputs */ : "=r" (dst), "=r" (n) - /* Inputs */ : "0" (dst), "1" (n), "r" (lc)); - } + /* Outputs. */ + : "=r" (dst), "=r" (n) - /* Either we directly starts copying, using dword copying - in a loop, or we copy as much as possible with 'movem' - and then the last block (<44 bytes) is copied here. - This will work since 'movem' will have updated src,dst,n. */ + /* Inputs. */ + : "0" (dst), "1" (n), "r" (lc)); + } - while ( n >= 16 ) - { - *((long*)dst)++ = lc; - *((long*)dst)++ = lc; - *((long*)dst)++ = lc; - *((long*)dst)++ = lc; - n -= 16; - } + /* An ad-hoc unroll, used for 4*12-1..16 bytes. */ + while (n >= 16) + { + *(long *) dst = lc; dst += 4; + *(long *) dst = lc; dst += 4; + *(long *) dst = lc; dst += 4; + *(long *) dst = lc; dst += 4; + n -= 16; + } - /* A switch() is definitely the fastest although it takes a LOT of code. - * Particularly if you inline code this. - */ switch (n) - { + { case 0: break; + case 1: - *(char*)dst = (char) lc; + *dst = (char) lc; break; + case 2: - *(short*)dst = (short) lc; + *(short *) dst = (short) lc; break; + case 3: - *((short*)dst)++ = (short) lc; - *(char*)dst = (char) lc; + *(short *) dst = (short) lc; dst += 2; + *dst = (char) lc; break; + case 4: - *((long*)dst)++ = lc; + *(long *) dst = lc; break; + case 5: - *((long*)dst)++ = lc; - *(char*)dst = (char) lc; + *(long *) dst = lc; dst += 4; + *dst = (char) lc; break; + case 6: - *((long*)dst)++ = lc; - *(short*)dst = (short) lc; + *(long *) dst = lc; dst += 4; + *(short *) dst = (short) lc; break; + case 7: - *((long*)dst)++ = lc; - *((short*)dst)++ = (short) lc; - *(char*)dst = (char) lc; + *(long *) dst = lc; dst += 4; + *(short *) dst = (short) lc; dst += 2; + *dst = (char) lc; break; + case 8: - *((long*)dst)++ = lc; - *((long*)dst)++ = lc; + *(long *) dst = lc; dst += 4; + *(long *) dst = lc; break; + case 9: - *((long*)dst)++ = lc; - *((long*)dst)++ = lc; - *(char*)dst = (char) lc; + *(long *) dst = lc; dst += 4; + *(long *) dst = lc; dst += 4; + *dst = (char) lc; break; + case 10: - *((long*)dst)++ = lc; - *((long*)dst)++ = lc; - *(short*)dst = (short) lc; + *(long *) dst = lc; dst += 4; + *(long *) dst = lc; dst += 4; + *(short *) dst = (short) lc; break; + case 11: - *((long*)dst)++ = lc; - *((long*)dst)++ = lc; - *((short*)dst)++ = (short) lc; - *(char*)dst = (char) lc; + *(long *) dst = lc; dst += 4; + *(long *) dst = lc; dst += 4; + *(short *) dst = (short) lc; dst += 2; + *dst = (char) lc; break; + case 12: - *((long*)dst)++ = lc; - *((long*)dst)++ = lc; - *((long*)dst)++ = lc; + *(long *) dst = lc; dst += 4; + *(long *) dst = lc; dst += 4; + *(long *) dst = lc; break; + case 13: - *((long*)dst)++ = lc; - *((long*)dst)++ = lc; - *((long*)dst)++ = lc; - *(char*)dst = (char) lc; + *(long *) dst = lc; dst += 4; + *(long *) dst = lc; dst += 4; + *(long *) dst = lc; dst += 4; + *dst = (char) lc; break; + case 14: - *((long*)dst)++ = lc; - *((long*)dst)++ = lc; - *((long*)dst)++ = lc; - *(short*)dst = (short) lc; + *(long *) dst = lc; dst += 4; + *(long *) dst = lc; dst += 4; + *(long *) dst = lc; dst += 4; + *(short *) dst = (short) lc; break; + case 15: - *((long*)dst)++ = lc; - *((long*)dst)++ = lc; - *((long*)dst)++ = lc; - *((short*)dst)++ = (short) lc; - *(char*)dst = (char) lc; + *(long *) dst = lc; dst += 4; + *(long *) dst = lc; dst += 4; + *(long *) dst = lc; dst += 4; + *(short *) dst = (short) lc; dst += 2; + *dst = (char) lc; break; - } + } } - return return_dst; /* destination pointer. */ -} /* memset() */ + return return_dst; +} diff --git a/arch/frv/kernel/entry.S b/arch/frv/kernel/entry.S index ca6a345b87e4..f36d7f4a7c25 100644 --- a/arch/frv/kernel/entry.S +++ b/arch/frv/kernel/entry.S @@ -1494,9 +1494,11 @@ sys_call_table: .long sys_epoll_pwait .long sys_utimensat /* 320 */ .long sys_signalfd - .long sys_ni_syscall + .long sys_timerfd_create .long sys_eventfd .long sys_fallocate + .long sys_timerfd_settime /* 325 */ + .long sys_timerfd_gettime syscall_table_size = (. - sys_call_table) diff --git a/arch/frv/kernel/vmlinux.lds.S b/arch/frv/kernel/vmlinux.lds.S index 17725a55aed8..b95c4eace62f 100644 --- a/arch/frv/kernel/vmlinux.lds.S +++ b/arch/frv/kernel/vmlinux.lds.S @@ -76,9 +76,6 @@ SECTIONS *(.data.init_task) } - . = ALIGN(4096); - .data.page_aligned : { *(.data.idt) } - . = ALIGN(L1_CACHE_BYTES); .data.cacheline_aligned : { *(.data.cacheline_aligned) } diff --git a/arch/m68knommu/platform/5206/Makefile b/arch/m68knommu/platform/5206/Makefile index c7bb0cef31a0..a439d9ab3f27 100644 --- a/arch/m68knommu/platform/5206/Makefile +++ b/arch/m68knommu/platform/5206/Makefile @@ -12,9 +12,7 @@ # EXTRA_AFLAGS += -DTRAP_DBG_INTERRUPT # -ifdef CONFIG_FULLDEBUG -EXTRA_AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1 -endif +asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1 obj-y := config.o diff --git a/arch/m68knommu/platform/5206e/Makefile b/arch/m68knommu/platform/5206e/Makefile index c7bb0cef31a0..a439d9ab3f27 100644 --- a/arch/m68knommu/platform/5206e/Makefile +++ b/arch/m68knommu/platform/5206e/Makefile @@ -12,9 +12,7 @@ # EXTRA_AFLAGS += -DTRAP_DBG_INTERRUPT # -ifdef CONFIG_FULLDEBUG -EXTRA_AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1 -endif +asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1 obj-y := config.o diff --git a/arch/m68knommu/platform/520x/Makefile b/arch/m68knommu/platform/520x/Makefile index 31b4eb51739d..a50e76acc8fd 100644 --- a/arch/m68knommu/platform/520x/Makefile +++ b/arch/m68knommu/platform/520x/Makefile @@ -12,8 +12,6 @@ # EXTRA_AFLAGS += -DTRAP_DBG_INTERRUPT # -ifdef CONFIG_FULLDEBUG -EXTRA_AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1 -endif +asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1 obj-y := config.o diff --git a/arch/m68knommu/platform/523x/Makefile b/arch/m68knommu/platform/523x/Makefile index ac9fbece8a4f..5694d593f029 100644 --- a/arch/m68knommu/platform/523x/Makefile +++ b/arch/m68knommu/platform/523x/Makefile @@ -12,8 +12,6 @@ # EXTRA_AFLAGS += -DTRAP_DBG_INTERRUPT # -ifdef CONFIG_FULLDEBUG -EXTRA_AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1 -endif +asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1 obj-y := config.o diff --git a/arch/m68knommu/platform/5249/Makefile b/arch/m68knommu/platform/5249/Makefile index c7bb0cef31a0..a439d9ab3f27 100644 --- a/arch/m68knommu/platform/5249/Makefile +++ b/arch/m68knommu/platform/5249/Makefile @@ -12,9 +12,7 @@ # EXTRA_AFLAGS += -DTRAP_DBG_INTERRUPT # -ifdef CONFIG_FULLDEBUG -EXTRA_AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1 -endif +asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1 obj-y := config.o diff --git a/arch/m68knommu/platform/5272/Makefile b/arch/m68knommu/platform/5272/Makefile index 7475c38c3b4e..26135d92b34d 100644 --- a/arch/m68knommu/platform/5272/Makefile +++ b/arch/m68knommu/platform/5272/Makefile @@ -12,9 +12,7 @@ # EXTRA_AFLAGS += -DTRAP_DBG_INTERRUPT # -ifdef CONFIG_FULLDEBUG -EXTRA_AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1 -endif +asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1 obj-y := config.o diff --git a/arch/m68knommu/platform/527x/Makefile b/arch/m68knommu/platform/527x/Makefile index 7475c38c3b4e..26135d92b34d 100644 --- a/arch/m68knommu/platform/527x/Makefile +++ b/arch/m68knommu/platform/527x/Makefile @@ -12,9 +12,7 @@ # EXTRA_AFLAGS += -DTRAP_DBG_INTERRUPT # -ifdef CONFIG_FULLDEBUG -EXTRA_AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1 -endif +asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1 obj-y := config.o diff --git a/arch/m68knommu/platform/528x/Makefile b/arch/m68knommu/platform/528x/Makefile index 7475c38c3b4e..26135d92b34d 100644 --- a/arch/m68knommu/platform/528x/Makefile +++ b/arch/m68knommu/platform/528x/Makefile @@ -12,9 +12,7 @@ # EXTRA_AFLAGS += -DTRAP_DBG_INTERRUPT # -ifdef CONFIG_FULLDEBUG -EXTRA_AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1 -endif +asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1 obj-y := config.o diff --git a/arch/m68knommu/platform/5307/Makefile b/arch/m68knommu/platform/5307/Makefile index 580fd6658d7c..cfd586860fd8 100644 --- a/arch/m68knommu/platform/5307/Makefile +++ b/arch/m68knommu/platform/5307/Makefile @@ -12,9 +12,7 @@ # EXTRA_AFLAGS += -DTRAP_DBG_INTERRUPT # -ifdef CONFIG_FULLDEBUG -EXTRA_AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1 -endif +asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1 obj-y += config.o diff --git a/arch/m68knommu/platform/532x/Makefile b/arch/m68knommu/platform/532x/Makefile index 475b92866a9b..e431912f5628 100644 --- a/arch/m68knommu/platform/532x/Makefile +++ b/arch/m68knommu/platform/532x/Makefile @@ -12,9 +12,7 @@ # EXTRA_AFLAGS += -DTRAP_DBG_INTERRUPT # -ifdef CONFIG_FULLDEBUG -EXTRA_AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1 -endif +asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1 #obj-y := config.o usb-mcf532x.o spi-mcf532x.o obj-y := config.o diff --git a/arch/m68knommu/platform/5407/Makefile b/arch/m68knommu/platform/5407/Makefile index 68633b27df51..e6035e7a2d3f 100644 --- a/arch/m68knommu/platform/5407/Makefile +++ b/arch/m68knommu/platform/5407/Makefile @@ -12,9 +12,7 @@ # EXTRA_AFLAGS += -DTRAP_DBG_INTERRUPT # -ifdef CONFIG_FULLDEBUG -EXTRA_AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1 -endif +asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1 obj-y := config.o diff --git a/arch/m68knommu/platform/coldfire/Makefile b/arch/m68knommu/platform/coldfire/Makefile index e5fff297ae01..40cf20be1b90 100644 --- a/arch/m68knommu/platform/coldfire/Makefile +++ b/arch/m68knommu/platform/coldfire/Makefile @@ -12,9 +12,7 @@ # EXTRA_AFLAGS += -DTRAP_DBG_INTERRUPT # -ifdef CONFIG_FULLDEBUG -AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1 -endif +asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1 obj-$(CONFIG_COLDFIRE) += dma.o entry.o vectors.o obj-$(CONFIG_M5206) += timers.o diff --git a/arch/m68knommu/platform/coldfire/entry.S b/arch/m68knommu/platform/coldfire/entry.S index b333731b875a..111b66dc737b 100644 --- a/arch/m68knommu/platform/coldfire/entry.S +++ b/arch/m68knommu/platform/coldfire/entry.S @@ -197,14 +197,13 @@ ENTRY(fasthandler) RESTORE_LOCAL ENTRY(ret_from_interrupt) - jeq 2f -1: - RESTORE_ALL -2: moveb %sp@(PT_SR),%d0 andl #0x7,%d0 - jhi 1b + jeq 1f + RESTORE_ALL + +1: /* check if we need to do software interrupts */ movel irq_stat+CPUSTAT_SOFTIRQ_PENDING,%d0 jeq ret_from_exception diff --git a/arch/m68knommu/platform/coldfire/timers.c b/arch/m68knommu/platform/coldfire/timers.c index a60213e877ef..ba5a9f32ebd4 100644 --- a/arch/m68knommu/platform/coldfire/timers.c +++ b/arch/m68knommu/platform/coldfire/timers.c @@ -148,25 +148,32 @@ irqreturn_t coldfire_profile_tick(int irq, void *dummy) /* Reset ColdFire timer2 */ __raw_writeb(MCFTIMER_TER_CAP | MCFTIMER_TER_REF, PA(MCFTIMER_TER)); if (current->pid) - profile_tick(CPU_PROFILING, regs); + profile_tick(CPU_PROFILING); return IRQ_HANDLED; } /***************************************************************************/ +static struct irqaction coldfire_profile_irq = { + .name = "profile timer", + .flags = IRQF_DISABLED | IRQF_TIMER, + .handler = coldfire_profile_tick, +}; + void coldfire_profile_init(void) { - printk(KERN_INFO "PROFILE: lodging TIMER2 @ %dHz as profile timer\n", PROFILEHZ); + printk(KERN_INFO "PROFILE: lodging TIMER2 @ %dHz as profile timer\n", + PROFILEHZ); + + setup_irq(mcf_profilevector, &coldfire_profile_irq); /* Set up TIMER 2 as high speed profile clock */ __raw_writew(MCFTIMER_TMR_DISABLE, PA(MCFTIMER_TMR)); - __raw_writetrr(((MCF_CLK / 16) / PROFILEHZ), PA(MCFTIMER_TRR)); + __raw_writetrr(((MCF_BUSCLK / 16) / PROFILEHZ), PA(MCFTIMER_TRR)); __raw_writew(MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 | MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE, PA(MCFTIMER_TMR)); - request_irq(mcf_profilevector, coldfire_profile_tick, - (IRQF_DISABLED | IRQ_FLG_FAST), "profile timer", NULL); mcf_settimericr(2, 7); } diff --git a/arch/mips/bcm47xx/setup.c b/arch/mips/bcm47xx/setup.c index 1b6b0fa5028f..8d36f186890e 100644 --- a/arch/mips/bcm47xx/setup.c +++ b/arch/mips/bcm47xx/setup.c @@ -92,17 +92,17 @@ static int bcm47xx_get_invariants(struct ssb_bus *bus, iv->sprom.revision = 3; if (cfe_getenv("et0macaddr", buf, sizeof(buf)) >= 0) - str2eaddr(buf, iv->sprom.r1.et0mac); + str2eaddr(buf, iv->sprom.et0mac); if (cfe_getenv("et1macaddr", buf, sizeof(buf)) >= 0) - str2eaddr(buf, iv->sprom.r1.et1mac); + str2eaddr(buf, iv->sprom.et1mac); if (cfe_getenv("et0phyaddr", buf, sizeof(buf)) >= 0) - iv->sprom.r1.et0phyaddr = simple_strtoul(buf, NULL, 10); + iv->sprom.et0phyaddr = simple_strtoul(buf, NULL, 10); if (cfe_getenv("et1phyaddr", buf, sizeof(buf)) >= 0) - iv->sprom.r1.et1phyaddr = simple_strtoul(buf, NULL, 10); + iv->sprom.et1phyaddr = simple_strtoul(buf, NULL, 10); if (cfe_getenv("et0mdcport", buf, sizeof(buf)) >= 0) - iv->sprom.r1.et0mdcport = simple_strtoul(buf, NULL, 10); + iv->sprom.et0mdcport = simple_strtoul(buf, NULL, 10); if (cfe_getenv("et1mdcport", buf, sizeof(buf)) >= 0) - iv->sprom.r1.et1mdcport = simple_strtoul(buf, NULL, 10); + iv->sprom.et1mdcport = simple_strtoul(buf, NULL, 10); return 0; } diff --git a/arch/mips/bcm47xx/wgt634u.c b/arch/mips/bcm47xx/wgt634u.c index 5a017eaee712..d1d90c9ef2fa 100644 --- a/arch/mips/bcm47xx/wgt634u.c +++ b/arch/mips/bcm47xx/wgt634u.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -43,6 +44,61 @@ static struct platform_device wgt634u_gpio_leds = { } }; + +/* 8MiB flash. The struct mtd_partition matches original Netgear WGT634U + firmware. */ +static struct mtd_partition wgt634u_partitions[] = { + { + .name = "cfe", + .offset = 0, + .size = 0x60000, /* 384k */ + .mask_flags = MTD_WRITEABLE /* force read-only */ + }, + { + .name = "config", + .offset = 0x60000, + .size = 0x20000 /* 128k */ + }, + { + .name = "linux", + .offset = 0x80000, + .size = 0x140000 /* 1280k */ + }, + { + .name = "jffs", + .offset = 0x1c0000, + .size = 0x620000 /* 6272k */ + }, + { + .name = "nvram", + .offset = 0x7e0000, + .size = 0x20000 /* 128k */ + }, +}; + +static struct physmap_flash_data wgt634u_flash_data = { + .parts = wgt634u_partitions, + .nr_parts = ARRAY_SIZE(wgt634u_partitions) +}; + +static struct resource wgt634u_flash_resource = { + .flags = IORESOURCE_MEM, +}; + +static struct platform_device wgt634u_flash = { + .name = "physmap-flash", + .id = 0, + .dev = { .platform_data = &wgt634u_flash_data, }, + .resource = &wgt634u_flash_resource, + .num_resources = 1, +}; + +/* Platform devices */ +static struct platform_device *wgt634u_devices[] __initdata = { + &wgt634u_flash, + &wgt634u_gpio_leds, +}; + static int __init wgt634u_init(void) { /* There is no easy way to detect that we are running on a WGT634U @@ -50,13 +106,20 @@ static int __init wgt634u_init(void) * been allocated ranges 00:09:5b:xx:xx:xx and 00:0f:b5:xx:xx:xx. */ - u8 *et0mac = ssb_bcm47xx.sprom.r1.et0mac; + u8 *et0mac = ssb_bcm47xx.sprom.et0mac; if (et0mac[0] == 0x00 && ((et0mac[1] == 0x09 && et0mac[2] == 0x5b) || - (et0mac[1] == 0x0f && et0mac[2] == 0xb5))) - return platform_device_register(&wgt634u_gpio_leds); - else + (et0mac[1] == 0x0f && et0mac[2] == 0xb5))) { + struct ssb_mipscore *mcore = &ssb_bcm47xx.mipscore; + wgt634u_flash_data.width = mcore->flash_buswidth; + wgt634u_flash_resource.start = mcore->flash_window; + wgt634u_flash_resource.end = mcore->flash_window + + mcore->flash_window_size + - 1; + return platform_add_devices(wgt634u_devices, + ARRAY_SIZE(wgt634u_devices)); + } else return -ENODEV; } diff --git a/arch/mips/configs/bcm47xx_defconfig b/arch/mips/configs/bcm47xx_defconfig new file mode 100644 index 000000000000..c0e42e74dfbd --- /dev/null +++ b/arch/mips/configs/bcm47xx_defconfig @@ -0,0 +1,1939 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.25-rc2 +# Mon Feb 18 11:55:24 2008 +# +CONFIG_MIPS=y + +# +# Machine selection +# +# CONFIG_MACH_ALCHEMY is not set +# CONFIG_BASLER_EXCITE is not set +CONFIG_BCM47XX=y +# CONFIG_MIPS_COBALT is not set +# CONFIG_MACH_DECSTATION is not set +# CONFIG_MACH_JAZZ is not set +# CONFIG_LASAT is not set +# CONFIG_LEMOTE_FULONG is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set +# CONFIG_MIPS_SIM is not set +# CONFIG_MARKEINS is not set +# CONFIG_MACH_VR41XX is not set +# CONFIG_PNX8550_JBS is not set +# CONFIG_PNX8550_STB810 is not set +# CONFIG_PMC_MSP is not set +# CONFIG_PMC_YOSEMITE is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP27 is not set +# CONFIG_SGI_IP28 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SIBYTE_CRHINE is not set +# CONFIG_SIBYTE_CARMEL is not set +# CONFIG_SIBYTE_CRHONE is not set +# CONFIG_SIBYTE_RHONE is not set +# CONFIG_SIBYTE_SWARM is not set +# CONFIG_SIBYTE_LITTLESUR is not set +# CONFIG_SIBYTE_SENTOSA is not set +# CONFIG_SIBYTE_BIGSUR is not set +# CONFIG_SNI_RM is not set +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +# CONFIG_TOSHIBA_RBTX4938 is not set +# CONFIG_WR_PPMC is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_ARCH_HAS_ILOG2_U32 is not set +# CONFIG_ARCH_HAS_ILOG2_U64 is not set +CONFIG_ARCH_SUPPORTS_OPROFILE=y +CONFIG_GENERIC_FIND_NEXT_BIT=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_TIME=y +CONFIG_GENERIC_CMOS_UPDATE=y +CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y +# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set +CONFIG_CEVT_R4K=y +CONFIG_CSRC_R4K=y +CONFIG_CFE=y +CONFIG_DMA_NONCOHERENT=y +CONFIG_DMA_NEED_PCI_MAP_STATE=y +CONFIG_EARLY_PRINTK=y +CONFIG_SYS_HAS_EARLY_PRINTK=y +# CONFIG_HOTPLUG_CPU is not set +# CONFIG_NO_IOPORT is not set +CONFIG_GENERIC_GPIO=y +# CONFIG_CPU_BIG_ENDIAN is not set +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y +CONFIG_IRQ_CPU=y +CONFIG_MIPS_L1_CACHE_SHIFT=5 + +# +# CPU selection +# +# CONFIG_CPU_LOONGSON2 is not set +CONFIG_CPU_MIPS32_R1=y +# CONFIG_CPU_MIPS32_R2 is not set +# CONFIG_CPU_MIPS64_R1 is not set +# CONFIG_CPU_MIPS64_R2 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_VR41XX is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_RM9000 is not set +# CONFIG_CPU_SB1 is not set +CONFIG_SYS_HAS_CPU_MIPS32_R1=y +CONFIG_CPU_MIPS32=y +CONFIG_CPU_MIPSR1=y +CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y +CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y + +# +# Kernel type +# +CONFIG_32BIT=y +# CONFIG_64BIT is not set +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_8KB is not set +# CONFIG_PAGE_SIZE_16KB is not set +# CONFIG_PAGE_SIZE_64KB is not set +CONFIG_CPU_HAS_PREFETCH=y +CONFIG_MIPS_MT_DISABLED=y +# CONFIG_MIPS_MT_SMP is not set +# CONFIG_MIPS_MT_SMTC is not set +CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_HAS_SYNC=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_CPU_SUPPORTS_HIGHMEM=y +CONFIG_ARCH_FLATMEM_ENABLE=y +CONFIG_ARCH_POPULATES_NODE_MAP=y +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_SPARSEMEM_VMEMMAP_ENABLE is not set +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_RESOURCES_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_VIRT_TO_BUS=y +CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +# CONFIG_HZ_48 is not set +# CONFIG_HZ_100 is not set +# CONFIG_HZ_128 is not set +CONFIG_HZ_250=y +# CONFIG_HZ_256 is not set +# CONFIG_HZ_1000 is not set +# CONFIG_HZ_1024 is not set +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_HZ=250 +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PREEMPT is not set +CONFIG_RCU_TRACE=y +CONFIG_KEXEC=y +# CONFIG_SECCOMP is not set +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +CONFIG_POSIX_MQUEUE=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_BSD_PROCESS_ACCT_V3=y +CONFIG_TASKSTATS=y +CONFIG_TASK_DELAY_ACCT=y +CONFIG_TASK_XACCT=y +CONFIG_TASK_IO_ACCOUNTING=y +CONFIG_AUDIT=y +# CONFIG_IKCONFIG is not set +CONFIG_LOG_BUF_SHIFT=17 +CONFIG_CGROUPS=y +# CONFIG_CGROUP_DEBUG is not set +CONFIG_CGROUP_NS=y +CONFIG_GROUP_SCHED=y +CONFIG_FAIR_GROUP_SCHED=y +# CONFIG_RT_GROUP_SCHED is not set +CONFIG_USER_SCHED=y +# CONFIG_CGROUP_SCHED is not set +CONFIG_CGROUP_CPUACCT=y +# CONFIG_RESOURCE_COUNTERS is not set +CONFIG_SYSFS_DEPRECATED=y +CONFIG_RELAY=y +# CONFIG_NAMESPACES is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +CONFIG_EMBEDDED=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_COMPAT_BRK=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_ANON_INODES=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +# CONFIG_MARKERS is not set +CONFIG_HAVE_OPROFILE=y +# CONFIG_HAVE_KPROBES is not set +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +CONFIG_MODVERSIONS=y +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_KMOD=y +CONFIG_BLOCK=y +CONFIG_LBD=y +CONFIG_BLK_DEV_IO_TRACE=y +CONFIG_LSF=y +# CONFIG_BLK_DEV_BSG is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_AS is not set +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" +CONFIG_CLASSIC_RCU=y +# CONFIG_PREEMPT_RCU is not set + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +CONFIG_HW_HAS_PCI=y +CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y +# CONFIG_ARCH_SUPPORTS_MSI is not set +CONFIG_PCI_LEGACY=y +CONFIG_MMU=y +# CONFIG_PCCARD is not set +# CONFIG_HOTPLUG_PCI is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +CONFIG_BINFMT_MISC=m +CONFIG_TRAD_SIGNALS=y + +# +# Power management options +# +CONFIG_ARCH_SUSPEND_POSSIBLE=y +# CONFIG_PM is not set + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +CONFIG_XFRM=y +CONFIG_XFRM_USER=m +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set +# CONFIG_XFRM_STATISTICS is not set +CONFIG_NET_KEY=m +# CONFIG_NET_KEY_MIGRATE is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_ASK_IP_FIB_HASH=y +# CONFIG_IP_FIB_TRIE is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_MULTIPATH=y +CONFIG_IP_ROUTE_VERBOSE=y +# CONFIG_IP_PNP is not set +CONFIG_NET_IPIP=m +CONFIG_NET_IPGRE=m +CONFIG_NET_IPGRE_BROADCAST=y +CONFIG_IP_MROUTE=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +CONFIG_INET_AH=m +CONFIG_INET_ESP=m +CONFIG_INET_IPCOMP=m +CONFIG_INET_XFRM_TUNNEL=m +CONFIG_INET_TUNNEL=m +CONFIG_INET_XFRM_MODE_TRANSPORT=m +CONFIG_INET_XFRM_MODE_TUNNEL=m +CONFIG_INET_XFRM_MODE_BEET=m +CONFIG_INET_LRO=m +CONFIG_INET_DIAG=m +CONFIG_INET_TCP_DIAG=m +CONFIG_TCP_CONG_ADVANCED=y +CONFIG_TCP_CONG_BIC=y +CONFIG_TCP_CONG_CUBIC=m +CONFIG_TCP_CONG_WESTWOOD=m +CONFIG_TCP_CONG_HTCP=m +CONFIG_TCP_CONG_HSTCP=m +CONFIG_TCP_CONG_HYBLA=m +CONFIG_TCP_CONG_VEGAS=m +CONFIG_TCP_CONG_SCALABLE=m +CONFIG_TCP_CONG_LP=m +CONFIG_TCP_CONG_VENO=m +CONFIG_TCP_CONG_YEAH=m +CONFIG_TCP_CONG_ILLINOIS=m +CONFIG_DEFAULT_BIC=y +# CONFIG_DEFAULT_CUBIC is not set +# CONFIG_DEFAULT_HTCP is not set +# CONFIG_DEFAULT_VEGAS is not set +# CONFIG_DEFAULT_WESTWOOD is not set +# CONFIG_DEFAULT_RENO is not set +CONFIG_DEFAULT_TCP_CONG="bic" +# CONFIG_TCP_MD5SIG is not set +CONFIG_IP_VS=m +# CONFIG_IP_VS_DEBUG is not set +CONFIG_IP_VS_TAB_BITS=12 + +# +# IPVS transport protocol load balancing support +# +CONFIG_IP_VS_PROTO_TCP=y +CONFIG_IP_VS_PROTO_UDP=y +CONFIG_IP_VS_PROTO_ESP=y +CONFIG_IP_VS_PROTO_AH=y + +# +# IPVS scheduler +# +CONFIG_IP_VS_RR=m +CONFIG_IP_VS_WRR=m +CONFIG_IP_VS_LC=m +CONFIG_IP_VS_WLC=m +CONFIG_IP_VS_LBLC=m +CONFIG_IP_VS_LBLCR=m +CONFIG_IP_VS_DH=m +CONFIG_IP_VS_SH=m +CONFIG_IP_VS_SED=m +CONFIG_IP_VS_NQ=m + +# +# IPVS application helper +# +CONFIG_IP_VS_FTP=m +CONFIG_IPV6=m +CONFIG_IPV6_PRIVACY=y +# CONFIG_IPV6_ROUTER_PREF is not set +# CONFIG_IPV6_OPTIMISTIC_DAD is not set +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m +CONFIG_INET6_IPCOMP=m +# CONFIG_IPV6_MIP6 is not set +CONFIG_INET6_XFRM_TUNNEL=m +CONFIG_INET6_TUNNEL=m +CONFIG_INET6_XFRM_MODE_TRANSPORT=m +CONFIG_INET6_XFRM_MODE_TUNNEL=m +CONFIG_INET6_XFRM_MODE_BEET=m +CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m +CONFIG_IPV6_SIT=m +CONFIG_IPV6_TUNNEL=m +CONFIG_IPV6_MULTIPLE_TABLES=y +CONFIG_IPV6_SUBTREES=y +CONFIG_NETWORK_SECMARK=y +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +CONFIG_NETFILTER_ADVANCED=y +CONFIG_BRIDGE_NETFILTER=y + +# +# Core Netfilter Configuration +# +CONFIG_NETFILTER_NETLINK=m +CONFIG_NETFILTER_NETLINK_QUEUE=m +CONFIG_NETFILTER_NETLINK_LOG=m +CONFIG_NF_CONNTRACK=m +CONFIG_NF_CT_ACCT=y +CONFIG_NF_CONNTRACK_MARK=y +CONFIG_NF_CONNTRACK_SECMARK=y +CONFIG_NF_CONNTRACK_EVENTS=y +CONFIG_NF_CT_PROTO_GRE=m +CONFIG_NF_CT_PROTO_SCTP=m +CONFIG_NF_CT_PROTO_UDPLITE=m +CONFIG_NF_CONNTRACK_AMANDA=m +CONFIG_NF_CONNTRACK_FTP=m +CONFIG_NF_CONNTRACK_H323=m +CONFIG_NF_CONNTRACK_IRC=m +CONFIG_NF_CONNTRACK_NETBIOS_NS=m +CONFIG_NF_CONNTRACK_PPTP=m +CONFIG_NF_CONNTRACK_SANE=m +CONFIG_NF_CONNTRACK_SIP=m +CONFIG_NF_CONNTRACK_TFTP=m +CONFIG_NF_CT_NETLINK=m +CONFIG_NETFILTER_XTABLES=m +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m +CONFIG_NETFILTER_XT_TARGET_CONNMARK=m +CONFIG_NETFILTER_XT_TARGET_DSCP=m +CONFIG_NETFILTER_XT_TARGET_MARK=m +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m +CONFIG_NETFILTER_XT_TARGET_NFLOG=m +CONFIG_NETFILTER_XT_TARGET_NOTRACK=m +# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set +CONFIG_NETFILTER_XT_TARGET_TRACE=m +CONFIG_NETFILTER_XT_TARGET_SECMARK=m +CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m +CONFIG_NETFILTER_XT_TARGET_TCPMSS=m +# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set +CONFIG_NETFILTER_XT_MATCH_COMMENT=m +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m +CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m +CONFIG_NETFILTER_XT_MATCH_CONNMARK=m +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m +CONFIG_NETFILTER_XT_MATCH_DCCP=m +CONFIG_NETFILTER_XT_MATCH_DSCP=m +CONFIG_NETFILTER_XT_MATCH_ESP=m +CONFIG_NETFILTER_XT_MATCH_HELPER=m +# CONFIG_NETFILTER_XT_MATCH_IPRANGE is not set +CONFIG_NETFILTER_XT_MATCH_LENGTH=m +CONFIG_NETFILTER_XT_MATCH_LIMIT=m +CONFIG_NETFILTER_XT_MATCH_MAC=m +CONFIG_NETFILTER_XT_MATCH_MARK=m +# CONFIG_NETFILTER_XT_MATCH_OWNER is not set +CONFIG_NETFILTER_XT_MATCH_POLICY=m +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m +CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m +CONFIG_NETFILTER_XT_MATCH_QUOTA=m +# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set +CONFIG_NETFILTER_XT_MATCH_REALM=m +CONFIG_NETFILTER_XT_MATCH_SCTP=m +CONFIG_NETFILTER_XT_MATCH_STATE=m +CONFIG_NETFILTER_XT_MATCH_STATISTIC=m +CONFIG_NETFILTER_XT_MATCH_STRING=m +CONFIG_NETFILTER_XT_MATCH_TCPMSS=m +CONFIG_NETFILTER_XT_MATCH_TIME=m +CONFIG_NETFILTER_XT_MATCH_U32=m +CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m + +# +# IP: Netfilter Configuration +# +CONFIG_NF_CONNTRACK_IPV4=m +CONFIG_NF_CONNTRACK_PROC_COMPAT=y +CONFIG_IP_NF_QUEUE=m +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_MATCH_RECENT=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_AH=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_MATCH_ADDRTYPE=m +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_TARGET_LOG=m +CONFIG_IP_NF_TARGET_ULOG=m +CONFIG_NF_NAT=m +CONFIG_NF_NAT_NEEDED=y +CONFIG_IP_NF_TARGET_MASQUERADE=m +CONFIG_IP_NF_TARGET_REDIRECT=m +CONFIG_IP_NF_TARGET_NETMAP=m +CONFIG_NF_NAT_SNMP_BASIC=m +CONFIG_NF_NAT_PROTO_GRE=m +CONFIG_NF_NAT_FTP=m +CONFIG_NF_NAT_IRC=m +CONFIG_NF_NAT_TFTP=m +CONFIG_NF_NAT_AMANDA=m +CONFIG_NF_NAT_PPTP=m +CONFIG_NF_NAT_H323=m +CONFIG_NF_NAT_SIP=m +CONFIG_IP_NF_MANGLE=m +CONFIG_IP_NF_TARGET_ECN=m +CONFIG_IP_NF_TARGET_TTL=m +CONFIG_IP_NF_TARGET_CLUSTERIP=m +CONFIG_IP_NF_RAW=m +CONFIG_IP_NF_ARPTABLES=m +CONFIG_IP_NF_ARPFILTER=m +CONFIG_IP_NF_ARP_MANGLE=m + +# +# IPv6: Netfilter Configuration +# +CONFIG_NF_CONNTRACK_IPV6=m +CONFIG_IP6_NF_QUEUE=m +CONFIG_IP6_NF_IPTABLES=m +CONFIG_IP6_NF_MATCH_RT=m +CONFIG_IP6_NF_MATCH_OPTS=m +CONFIG_IP6_NF_MATCH_FRAG=m +CONFIG_IP6_NF_MATCH_HL=m +CONFIG_IP6_NF_MATCH_IPV6HEADER=m +CONFIG_IP6_NF_MATCH_AH=m +CONFIG_IP6_NF_MATCH_MH=m +CONFIG_IP6_NF_MATCH_EUI64=m +CONFIG_IP6_NF_FILTER=m +CONFIG_IP6_NF_TARGET_LOG=m +CONFIG_IP6_NF_TARGET_REJECT=m +CONFIG_IP6_NF_MANGLE=m +CONFIG_IP6_NF_TARGET_HL=m +CONFIG_IP6_NF_RAW=m + +# +# Bridge: Netfilter Configuration +# +CONFIG_BRIDGE_NF_EBTABLES=m +CONFIG_BRIDGE_EBT_BROUTE=m +CONFIG_BRIDGE_EBT_T_FILTER=m +CONFIG_BRIDGE_EBT_T_NAT=m +CONFIG_BRIDGE_EBT_802_3=m +CONFIG_BRIDGE_EBT_AMONG=m +CONFIG_BRIDGE_EBT_ARP=m +CONFIG_BRIDGE_EBT_IP=m +CONFIG_BRIDGE_EBT_LIMIT=m +CONFIG_BRIDGE_EBT_MARK=m +CONFIG_BRIDGE_EBT_PKTTYPE=m +CONFIG_BRIDGE_EBT_STP=m +CONFIG_BRIDGE_EBT_VLAN=m +CONFIG_BRIDGE_EBT_ARPREPLY=m +CONFIG_BRIDGE_EBT_DNAT=m +CONFIG_BRIDGE_EBT_MARK_T=m +CONFIG_BRIDGE_EBT_REDIRECT=m +CONFIG_BRIDGE_EBT_SNAT=m +CONFIG_BRIDGE_EBT_LOG=m +CONFIG_BRIDGE_EBT_ULOG=m +CONFIG_IP_DCCP=m +CONFIG_INET_DCCP_DIAG=m +CONFIG_IP_DCCP_ACKVEC=y + +# +# DCCP CCIDs Configuration (EXPERIMENTAL) +# +CONFIG_IP_DCCP_CCID2=m +# CONFIG_IP_DCCP_CCID2_DEBUG is not set +CONFIG_IP_DCCP_CCID3=m +# CONFIG_IP_DCCP_CCID3_DEBUG is not set +CONFIG_IP_DCCP_CCID3_RTO=100 +CONFIG_IP_DCCP_TFRC_LIB=m +CONFIG_IP_SCTP=m +# CONFIG_SCTP_DBG_MSG is not set +# CONFIG_SCTP_DBG_OBJCNT is not set +# CONFIG_SCTP_HMAC_NONE is not set +# CONFIG_SCTP_HMAC_SHA1 is not set +CONFIG_SCTP_HMAC_MD5=y +CONFIG_TIPC=m +CONFIG_TIPC_ADVANCED=y +CONFIG_TIPC_ZONES=3 +CONFIG_TIPC_CLUSTERS=1 +CONFIG_TIPC_NODES=255 +CONFIG_TIPC_SLAVE_NODES=0 +CONFIG_TIPC_PORTS=8191 +CONFIG_TIPC_LOG=0 +# CONFIG_TIPC_DEBUG is not set +CONFIG_ATM=m +CONFIG_ATM_CLIP=m +# CONFIG_ATM_CLIP_NO_ICMP is not set +CONFIG_ATM_LANE=m +CONFIG_ATM_MPOA=m +CONFIG_ATM_BR2684=m +# CONFIG_ATM_BR2684_IPFILTER is not set +CONFIG_BRIDGE=m +CONFIG_VLAN_8021Q=m +# CONFIG_DECNET is not set +CONFIG_LLC=m +# 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 +CONFIG_NET_SCHED=y + +# +# Queueing/Scheduling +# +CONFIG_NET_SCH_CBQ=m +CONFIG_NET_SCH_HTB=m +CONFIG_NET_SCH_HFSC=m +CONFIG_NET_SCH_ATM=m +CONFIG_NET_SCH_PRIO=m +CONFIG_NET_SCH_RR=m +CONFIG_NET_SCH_RED=m +CONFIG_NET_SCH_SFQ=m +CONFIG_NET_SCH_TEQL=m +CONFIG_NET_SCH_TBF=m +CONFIG_NET_SCH_GRED=m +CONFIG_NET_SCH_DSMARK=m +CONFIG_NET_SCH_NETEM=m +CONFIG_NET_SCH_INGRESS=m + +# +# Classification +# +CONFIG_NET_CLS=y +CONFIG_NET_CLS_BASIC=m +CONFIG_NET_CLS_TCINDEX=m +CONFIG_NET_CLS_ROUTE4=m +CONFIG_NET_CLS_ROUTE=y +CONFIG_NET_CLS_FW=m +CONFIG_NET_CLS_U32=m +CONFIG_CLS_U32_PERF=y +CONFIG_CLS_U32_MARK=y +CONFIG_NET_CLS_RSVP=m +CONFIG_NET_CLS_RSVP6=m +# CONFIG_NET_CLS_FLOW is not set +CONFIG_NET_EMATCH=y +CONFIG_NET_EMATCH_STACK=32 +CONFIG_NET_EMATCH_CMP=m +CONFIG_NET_EMATCH_NBYTE=m +CONFIG_NET_EMATCH_U32=m +CONFIG_NET_EMATCH_META=m +CONFIG_NET_EMATCH_TEXT=m +CONFIG_NET_CLS_ACT=y +CONFIG_NET_ACT_POLICE=m +CONFIG_NET_ACT_GACT=m +CONFIG_GACT_PROB=y +CONFIG_NET_ACT_MIRRED=m +CONFIG_NET_ACT_IPT=m +CONFIG_NET_ACT_NAT=m +CONFIG_NET_ACT_PEDIT=m +CONFIG_NET_ACT_SIMP=m +CONFIG_NET_CLS_IND=y +CONFIG_NET_SCH_FIFO=y + +# +# Network testing +# +CONFIG_NET_PKTGEN=m +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +CONFIG_IRDA=m + +# +# IrDA protocols +# +CONFIG_IRLAN=m +CONFIG_IRNET=m +CONFIG_IRCOMM=m +# CONFIG_IRDA_ULTRA is not set + +# +# IrDA options +# +CONFIG_IRDA_CACHE_LAST_LSAP=y +CONFIG_IRDA_FAST_RR=y +# CONFIG_IRDA_DEBUG is not set + +# +# Infrared-port device drivers +# + +# +# SIR device drivers +# +CONFIG_IRTTY_SIR=m + +# +# Dongle support +# +CONFIG_DONGLE=y +CONFIG_ESI_DONGLE=m +CONFIG_ACTISYS_DONGLE=m +CONFIG_TEKRAM_DONGLE=m +CONFIG_TOIM3232_DONGLE=m +CONFIG_LITELINK_DONGLE=m +CONFIG_MA600_DONGLE=m +CONFIG_GIRBIL_DONGLE=m +CONFIG_MCP2120_DONGLE=m +CONFIG_OLD_BELKIN_DONGLE=m +CONFIG_ACT200L_DONGLE=m +CONFIG_KINGSUN_DONGLE=m +CONFIG_KSDAZZLE_DONGLE=m +CONFIG_KS959_DONGLE=m + +# +# FIR device drivers +# +CONFIG_USB_IRDA=m +CONFIG_SIGMATEL_FIR=m +CONFIG_TOSHIBA_FIR=m +CONFIG_VLSI_FIR=m +CONFIG_MCS_FIR=m +CONFIG_BT=m +# CONFIG_BT_L2CAP is not set +# CONFIG_BT_SCO is not set + +# +# Bluetooth device drivers +# +CONFIG_BT_HCIUSB=m +CONFIG_BT_HCIUSB_SCO=y +CONFIG_BT_HCIUART=m +CONFIG_BT_HCIUART_H4=y +CONFIG_BT_HCIUART_BCSP=y +CONFIG_BT_HCIUART_LL=y +CONFIG_BT_HCIBCM203X=m +CONFIG_BT_HCIBPA10X=m +CONFIG_BT_HCIBFUSB=m +CONFIG_BT_HCIVHCI=m +# CONFIG_AF_RXRPC is not set +CONFIG_FIB_RULES=y + +# +# Wireless +# +CONFIG_CFG80211=m +CONFIG_NL80211=y +CONFIG_WIRELESS_EXT=y +CONFIG_MAC80211=m + +# +# Rate control algorithm selection +# +CONFIG_MAC80211_RC_DEFAULT_PID=y +# CONFIG_MAC80211_RC_DEFAULT_SIMPLE is not set +# CONFIG_MAC80211_RC_DEFAULT_NONE is not set + +# +# Selecting 'y' for an algorithm will +# + +# +# build the algorithm into mac80211. +# +CONFIG_MAC80211_RC_DEFAULT="pid" +CONFIG_MAC80211_RC_PID=y +# CONFIG_MAC80211_RC_SIMPLE is not set +CONFIG_MAC80211_LEDS=y +# CONFIG_MAC80211_DEBUGFS is not set +# CONFIG_MAC80211_DEBUG_PACKET_ALIGNMENT is not set +# CONFIG_MAC80211_DEBUG is not set +CONFIG_IEEE80211=m +# CONFIG_IEEE80211_DEBUG is not set +CONFIG_IEEE80211_CRYPT_WEP=m +CONFIG_IEEE80211_CRYPT_CCMP=m +CONFIG_IEEE80211_CRYPT_TKIP=m +CONFIG_IEEE80211_SOFTMAC=m +# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set +CONFIG_RFKILL=m +CONFIG_RFKILL_INPUT=m +CONFIG_RFKILL_LEDS=y +CONFIG_NET_9P=m +CONFIG_NET_9P_FD=m +# CONFIG_NET_9P_DEBUG is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=m +# CONFIG_SYS_HYPERVISOR is not set +CONFIG_CONNECTOR=m +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +CONFIG_MTD_CONCAT=y +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_REDBOOT_PARTS is not set +# CONFIG_MTD_CMDLINE_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLKDEVS=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 +# CONFIG_MTD_OOPS 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=y +CONFIG_MTD_CFI_AMDSTD=y +CONFIG_MTD_CFI_STAA=y +CONFIG_MTD_CFI_UTIL=y +CONFIG_MTD_RAM=y +CONFIG_MTD_ROM=y +CONFIG_MTD_ABSENT=y + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +CONFIG_MTD_PHYSMAP=y +CONFIG_MTD_PHYSMAP_START=0x8000000 +CONFIG_MTD_PHYSMAP_LEN=0x0 +CONFIG_MTD_PHYSMAP_BANKWIDTH=2 +# CONFIG_MTD_INTEL_VR_NOR 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 +# CONFIG_MTD_NAND is not set +# CONFIG_MTD_ONENAND is not set + +# +# UBI - Unsorted block images +# +# CONFIG_MTD_UBI is not set +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# 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=m +CONFIG_BLK_DEV_CRYPTOLOOP=m +CONFIG_BLK_DEV_NBD=m +# CONFIG_BLK_DEV_SX8 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=16384 +# CONFIG_BLK_DEV_XIP is not set +# CONFIG_CDROM_PKTCDVD is not set +CONFIG_ATA_OVER_ETH=m +CONFIG_MISC_DEVICES=y +# CONFIG_PHANTOM is not set +# CONFIG_EEPROM_93CX6 is not set +# CONFIG_SGI_IOC4 is not set +# CONFIG_TIFM_CORE is not set +# CONFIG_ENCLOSURE_SERVICES is not set +CONFIG_HAVE_IDE=y +# CONFIG_IDE is not set + +# +# SCSI device support +# +CONFIG_RAID_ATTRS=m +CONFIG_SCSI=y +CONFIG_SCSI_DMA=y +CONFIG_SCSI_TGT=m +# 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=m +CONFIG_CHR_DEV_OSST=m +CONFIG_BLK_DEV_SR=m +CONFIG_BLK_DEV_SR_VENDOR=y +CONFIG_CHR_DEV_SG=m +CONFIG_CHR_DEV_SCH=m + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +CONFIG_SCSI_MULTI_LUN=y +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y +CONFIG_SCSI_SCAN_ASYNC=y +CONFIG_SCSI_WAIT_SCAN=m + +# +# SCSI Transports +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +CONFIG_SCSI_ISCSI_ATTRS=m +# CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set +CONFIG_SCSI_LOWLEVEL=y +CONFIG_ISCSI_TCP=m +# 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_ADVANSYS 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 +# CONFIG_SCSI_SRP is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# +# CONFIG_FIREWIRE is not set +# CONFIG_IEEE1394 is not set +# CONFIG_I2O is not set +CONFIG_NETDEVICES=y +# CONFIG_NETDEVICES_MULTIQUEUE is not set +# CONFIG_IFB is not set +CONFIG_DUMMY=m +# CONFIG_BONDING is not set +# CONFIG_MACVLAN is not set +CONFIG_EQUALIZER=m +CONFIG_TUN=m +CONFIG_VETH=m +# CONFIG_ARCNET is not set +CONFIG_PHYLIB=m + +# +# MII PHY device drivers +# +CONFIG_MARVELL_PHY=m +CONFIG_DAVICOM_PHY=m +CONFIG_QSEMI_PHY=m +CONFIG_LXT_PHY=m +CONFIG_CICADA_PHY=m +CONFIG_VITESSE_PHY=m +CONFIG_SMSC_PHY=m +CONFIG_BROADCOM_PHY=m +CONFIG_ICPLUS_PHY=m +# CONFIG_REALTEK_PHY is not set +# CONFIG_FIXED_PHY is not set +CONFIG_MDIO_BITBANG=m +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_AX88796 is not set +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_CASSINI is not set +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_DM9000 is not set +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +# CONFIG_IBM_NEW_EMAC_ZMII is not set +# CONFIG_IBM_NEW_EMAC_RGMII is not set +# CONFIG_IBM_NEW_EMAC_TAH is not set +# CONFIG_IBM_NEW_EMAC_EMAC4 is not set +CONFIG_NET_PCI=y +# CONFIG_PCNET32 is not set +# CONFIG_AMD8111_ETH is not set +# CONFIG_ADAPTEC_STARFIRE is not set +CONFIG_B44=y +CONFIG_B44_PCI_AUTOSELECT=y +CONFIG_B44_PCICORE_AUTOSELECT=y +CONFIG_B44_PCI=y +# CONFIG_FORCEDETH is not set +# CONFIG_TC35815 is not set +# CONFIG_EEPRO100 is not set +# CONFIG_E100 is not set +# CONFIG_FEALNX is not set +# CONFIG_NATSEMI is not set +# CONFIG_NE2K_PCI is not set +# CONFIG_8139CP is not set +# CONFIG_8139TOO is not set +# CONFIG_R6040 is not set +# CONFIG_SIS900 is not set +# CONFIG_EPIC100 is not set +# CONFIG_SUNDANCE is not set +# CONFIG_TLAN is not set +# CONFIG_VIA_RHINE is not set +# CONFIG_SC92031 is not set +# CONFIG_NETDEV_1000 is not set +# CONFIG_NETDEV_10000 is not set +# CONFIG_TR is not set + +# +# Wireless LAN +# +# CONFIG_WLAN_PRE80211 is not set +CONFIG_WLAN_80211=y +# CONFIG_IPW2100 is not set +# CONFIG_IPW2200 is not set +# CONFIG_LIBERTAS is not set +# CONFIG_HERMES is not set +# CONFIG_ATMEL is not set +# CONFIG_PRISM54 is not set +# CONFIG_USB_ZD1201 is not set +# CONFIG_USB_NET_RNDIS_WLAN is not set +# CONFIG_RTL8180 is not set +# CONFIG_RTL8187 is not set +# CONFIG_ADM8211 is not set +# CONFIG_P54_COMMON is not set +CONFIG_ATH5K=m +# CONFIG_IWL4965 is not set +# CONFIG_IWL3945 is not set +# CONFIG_HOSTAP is not set +# CONFIG_BCM43XX is not set +# CONFIG_B43 is not set +# CONFIG_B43LEGACY is not set +CONFIG_ZD1211RW=m +# CONFIG_ZD1211RW_DEBUG is not set +# CONFIG_RT2X00 is not set + +# +# USB Network Adapters +# +CONFIG_USB_CATC=m +CONFIG_USB_KAWETH=m +CONFIG_USB_PEGASUS=m +CONFIG_USB_RTL8150=m +CONFIG_USB_USBNET=m +CONFIG_USB_NET_AX8817X=m +CONFIG_USB_NET_CDCETHER=m +CONFIG_USB_NET_DM9601=m +CONFIG_USB_NET_GL620A=m +CONFIG_USB_NET_NET1080=m +CONFIG_USB_NET_PLUSB=m +CONFIG_USB_NET_MCS7830=m +CONFIG_USB_NET_RNDIS_HOST=m +CONFIG_USB_NET_CDC_SUBSET=m +CONFIG_USB_ALI_M5632=y +CONFIG_USB_AN2720=y +CONFIG_USB_BELKIN=y +CONFIG_USB_ARMLINUX=y +CONFIG_USB_EPSON2888=y +CONFIG_USB_KC2190=y +CONFIG_USB_NET_ZAURUS=m +# CONFIG_WAN is not set +CONFIG_ATM_DRIVERS=y +CONFIG_ATM_DUMMY=m +CONFIG_ATM_TCP=m +# CONFIG_ATM_LANAI is not set +# CONFIG_ATM_ENI is not set +# CONFIG_ATM_FIRESTREAM is not set +# CONFIG_ATM_ZATM is not set +# CONFIG_ATM_NICSTAR is not set +# CONFIG_ATM_IDT77252 is not set +# CONFIG_ATM_AMBASSADOR is not set +# CONFIG_ATM_HORIZON is not set +# CONFIG_ATM_IA is not set +# CONFIG_ATM_FORE200E_MAYBE is not set +# CONFIG_ATM_HE is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +CONFIG_PPP=m +# CONFIG_PPP_MULTILINK is not set +# CONFIG_PPP_FILTER is not set +CONFIG_PPP_ASYNC=m +# CONFIG_PPP_SYNC_TTY is not set +CONFIG_PPP_DEFLATE=m +CONFIG_PPP_BSDCOMP=m +CONFIG_PPP_MPPE=m +CONFIG_PPPOE=m +CONFIG_PPPOATM=m +# CONFIG_PPPOL2TP is not set +CONFIG_SLIP=m +# CONFIG_SLIP_COMPRESSED is not set +CONFIG_SLHC=m +# CONFIG_SLIP_SMART is not set +# CONFIG_SLIP_MODE_SLIP6 is not set +# CONFIG_NET_FC is not set +CONFIG_NETCONSOLE=y +# CONFIG_NETCONSOLE_DYNAMIC is not set +CONFIG_NETPOLL=y +# CONFIG_NETPOLL_TRAP is not set +CONFIG_NET_POLL_CONTROLLER=y +# CONFIG_ISDN is not set +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +CONFIG_INPUT_EVDEV=m +# 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_TABLET 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 is not set +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_NOZOMI is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +# CONFIG_SERIAL_8250_PCI is not set +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 is not set +# CONFIG_IPMI_HANDLER is not set +# CONFIG_HW_RANDOM is not set +# CONFIG_RTC is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +CONFIG_DEVPORT=y +# CONFIG_I2C is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set +CONFIG_W1=m +CONFIG_W1_CON=y + +# +# 1-wire Bus Masters +# +CONFIG_W1_MASTER_MATROX=m +CONFIG_W1_MASTER_DS2490=m +# CONFIG_W1_MASTER_GPIO is not set + +# +# 1-wire Slaves +# +CONFIG_W1_SLAVE_THERM=m +CONFIG_W1_SLAVE_SMEM=m +CONFIG_W1_SLAVE_DS2433=m +# CONFIG_W1_SLAVE_DS2433_CRC is not set +CONFIG_W1_SLAVE_DS2760=m +# CONFIG_POWER_SUPPLY is not set +# CONFIG_HWMON is not set +CONFIG_THERMAL=y +# CONFIG_WATCHDOG is not set + +# +# Sonics Silicon Backplane +# +CONFIG_SSB_POSSIBLE=y +CONFIG_SSB=y +CONFIG_SSB_PCIHOST_POSSIBLE=y +CONFIG_SSB_PCIHOST=y +# CONFIG_SSB_SILENT is not set +# CONFIG_SSB_DEBUG is not set +CONFIG_SSB_SERIAL=y +CONFIG_SSB_DRIVER_PCICORE_POSSIBLE=y +CONFIG_SSB_DRIVER_PCICORE=y +CONFIG_SSB_PCICORE_HOSTMODE=y +CONFIG_SSB_DRIVER_MIPS=y +CONFIG_SSB_DRIVER_EXTIF=y + +# +# Multifunction device drivers +# +# CONFIG_MFD_SM501 is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set +# CONFIG_DVB_CORE is not set +CONFIG_DAB=y +CONFIG_USB_DABUSB=m + +# +# Graphics support +# +# CONFIG_DRM is not set +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +# CONFIG_FB is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +CONFIG_DISPLAY_SUPPORT=m + +# +# Display hardware drivers +# + +# +# Sound +# +CONFIG_SOUND=m + +# +# Advanced Linux Sound Architecture +# +CONFIG_SND=m +CONFIG_SND_TIMER=m +CONFIG_SND_PCM=m +CONFIG_SND_HWDEP=m +CONFIG_SND_RAWMIDI=m +CONFIG_SND_SEQUENCER=m +CONFIG_SND_SEQ_DUMMY=m +CONFIG_SND_OSSEMUL=y +CONFIG_SND_MIXER_OSS=m +CONFIG_SND_PCM_OSS=m +CONFIG_SND_PCM_OSS_PLUGINS=y +CONFIG_SND_SEQUENCER_OSS=y +# CONFIG_SND_DYNAMIC_MINORS is not set +CONFIG_SND_SUPPORT_OLD_API=y +CONFIG_SND_VERBOSE_PROCFS=y +# CONFIG_SND_VERBOSE_PRINTK is not set +# CONFIG_SND_DEBUG is not set + +# +# Generic devices +# +CONFIG_SND_DUMMY=m +CONFIG_SND_VIRMIDI=m +# CONFIG_SND_MTPAV is not set +# CONFIG_SND_SERIAL_U16550 is not set +# CONFIG_SND_MPU401 is not set + +# +# PCI devices +# +# CONFIG_SND_AD1889 is not set +# CONFIG_SND_ALS300 is not set +# CONFIG_SND_ALI5451 is not set +# CONFIG_SND_ATIIXP is not set +# CONFIG_SND_ATIIXP_MODEM is not set +# CONFIG_SND_AU8810 is not set +# CONFIG_SND_AU8820 is not set +# CONFIG_SND_AU8830 is not set +# CONFIG_SND_AZT3328 is not set +# CONFIG_SND_BT87X is not set +# CONFIG_SND_CA0106 is not set +# CONFIG_SND_CMIPCI is not set +# CONFIG_SND_OXYGEN is not set +# CONFIG_SND_CS4281 is not set +# CONFIG_SND_CS46XX is not set +# CONFIG_SND_DARLA20 is not set +# CONFIG_SND_GINA20 is not set +# CONFIG_SND_LAYLA20 is not set +# CONFIG_SND_DARLA24 is not set +# CONFIG_SND_GINA24 is not set +# CONFIG_SND_LAYLA24 is not set +# CONFIG_SND_MONA is not set +# CONFIG_SND_MIA is not set +# CONFIG_SND_ECHO3G is not set +# CONFIG_SND_INDIGO is not set +# CONFIG_SND_INDIGOIO is not set +# CONFIG_SND_INDIGODJ is not set +# CONFIG_SND_EMU10K1 is not set +# CONFIG_SND_EMU10K1X is not set +# CONFIG_SND_ENS1370 is not set +# CONFIG_SND_ENS1371 is not set +# CONFIG_SND_ES1938 is not set +# CONFIG_SND_ES1968 is not set +# CONFIG_SND_FM801 is not set +# CONFIG_SND_HDA_INTEL is not set +# CONFIG_SND_HDSP is not set +# CONFIG_SND_HDSPM is not set +# CONFIG_SND_HIFIER is not set +# CONFIG_SND_ICE1712 is not set +# CONFIG_SND_ICE1724 is not set +# CONFIG_SND_INTEL8X0 is not set +# CONFIG_SND_INTEL8X0M is not set +# CONFIG_SND_KORG1212 is not set +# CONFIG_SND_MAESTRO3 is not set +# CONFIG_SND_MIXART is not set +# CONFIG_SND_NM256 is not set +# CONFIG_SND_PCXHR is not set +# CONFIG_SND_RIPTIDE is not set +# CONFIG_SND_RME32 is not set +# CONFIG_SND_RME96 is not set +# CONFIG_SND_RME9652 is not set +# CONFIG_SND_SONICVIBES is not set +# CONFIG_SND_TRIDENT is not set +# CONFIG_SND_VIA82XX is not set +# CONFIG_SND_VIA82XX_MODEM is not set +# CONFIG_SND_VIRTUOSO is not set +# CONFIG_SND_VX222 is not set +# CONFIG_SND_YMFPCI is not set + +# +# ALSA MIPS devices +# + +# +# USB devices +# +CONFIG_SND_USB_AUDIO=m +# CONFIG_SND_USB_CAIAQ is not set + +# +# System on Chip audio support +# +# CONFIG_SND_SOC is not set + +# +# SoC Audio support for SuperH +# + +# +# ALSA SoC audio for Freescale SOCs +# + +# +# Open Sound System +# +# CONFIG_SOUND_PRIME is not set +CONFIG_HID_SUPPORT=y +CONFIG_HID=m +# CONFIG_HID_DEBUG is not set +# CONFIG_HIDRAW is not set + +# +# USB Input Devices +# +CONFIG_USB_HID=m +# CONFIG_USB_HIDINPUT_POWERBOOK is not set +# CONFIG_HID_FF is not set +CONFIG_USB_HIDDEV=y + +# +# USB HID Boot Protocol drivers +# +# CONFIG_USB_KBD is not set +# CONFIG_USB_MOUSE is not set +CONFIG_USB_SUPPORT=y +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set +# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +# CONFIG_USB_DEVICE_CLASS is not set +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_OTG is not set + +# +# USB Host Controller Drivers +# +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_ROOT_HUB_TT=y +CONFIG_USB_EHCI_TT_NEWSCHED=y +# CONFIG_USB_ISP116X_HCD is not set +CONFIG_USB_OHCI_HCD=y +# CONFIG_USB_OHCI_HCD_SSB is not set +# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set +# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +# CONFIG_USB_UHCI_HCD is not set +CONFIG_USB_U132_HCD=m +# CONFIG_USB_SL811_HCD is not set +CONFIG_USB_R8A66597_HCD=m + +# +# USB Device Class drivers +# +CONFIG_USB_ACM=m +CONFIG_USB_PRINTER=m + +# +# 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 is not set +CONFIG_USB_STORAGE_DATAFAB=y +CONFIG_USB_STORAGE_FREECOM=y +# CONFIG_USB_STORAGE_ISD200 is not set +CONFIG_USB_STORAGE_DPCM=y +CONFIG_USB_STORAGE_USBAT=y +CONFIG_USB_STORAGE_SDDR09=y +CONFIG_USB_STORAGE_SDDR55=y +CONFIG_USB_STORAGE_JUMPSHOT=y +CONFIG_USB_STORAGE_ALAUDA=y +CONFIG_USB_STORAGE_ONETOUCH=y +CONFIG_USB_STORAGE_KARMA=y +# CONFIG_USB_LIBUSUAL is not set + +# +# USB Imaging devices +# +CONFIG_USB_MDC800=m +CONFIG_USB_MICROTEK=m +# CONFIG_USB_MON is not set + +# +# USB port drivers +# +CONFIG_USB_SERIAL=m +CONFIG_USB_EZUSB=y +CONFIG_USB_SERIAL_GENERIC=y +CONFIG_USB_SERIAL_AIRCABLE=m +CONFIG_USB_SERIAL_AIRPRIME=m +CONFIG_USB_SERIAL_ARK3116=m +CONFIG_USB_SERIAL_BELKIN=m +CONFIG_USB_SERIAL_CH341=m +# CONFIG_USB_SERIAL_WHITEHEAT is not set +CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m +CONFIG_USB_SERIAL_CP2101=m +CONFIG_USB_SERIAL_CYPRESS_M8=m +CONFIG_USB_SERIAL_EMPEG=m +CONFIG_USB_SERIAL_FTDI_SIO=m +CONFIG_USB_SERIAL_FUNSOFT=m +CONFIG_USB_SERIAL_VISOR=m +CONFIG_USB_SERIAL_IPAQ=m +CONFIG_USB_SERIAL_IR=m +# CONFIG_USB_SERIAL_EDGEPORT is not set +# CONFIG_USB_SERIAL_EDGEPORT_TI is not set +CONFIG_USB_SERIAL_GARMIN=m +CONFIG_USB_SERIAL_IPW=m +# CONFIG_USB_SERIAL_IUU is not set +CONFIG_USB_SERIAL_KEYSPAN_PDA=m +# CONFIG_USB_SERIAL_KEYSPAN is not set +CONFIG_USB_SERIAL_KLSI=m +CONFIG_USB_SERIAL_KOBIL_SCT=m +CONFIG_USB_SERIAL_MCT_U232=m +CONFIG_USB_SERIAL_MOS7720=m +CONFIG_USB_SERIAL_MOS7840=m +CONFIG_USB_SERIAL_NAVMAN=m +CONFIG_USB_SERIAL_PL2303=m +CONFIG_USB_SERIAL_OTI6858=m +CONFIG_USB_SERIAL_HP4X=m +CONFIG_USB_SERIAL_SAFE=m +# CONFIG_USB_SERIAL_SAFE_PADDED is not set +CONFIG_USB_SERIAL_SIERRAWIRELESS=m +# CONFIG_USB_SERIAL_TI is not set +CONFIG_USB_SERIAL_CYBERJACK=m +CONFIG_USB_SERIAL_XIRCOM=m +CONFIG_USB_SERIAL_OPTION=m +CONFIG_USB_SERIAL_OMNINET=m +CONFIG_USB_SERIAL_DEBUG=m + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +CONFIG_USB_ADUTUX=m +CONFIG_USB_AUERSWALD=m +CONFIG_USB_RIO500=m +CONFIG_USB_LEGOTOWER=m +CONFIG_USB_LCD=m +CONFIG_USB_BERRY_CHARGE=m +CONFIG_USB_LED=m +CONFIG_USB_CYPRESS_CY7C63=m +CONFIG_USB_CYTHERM=m +CONFIG_USB_PHIDGET=m +CONFIG_USB_PHIDGETKIT=m +CONFIG_USB_PHIDGETMOTORCONTROL=m +CONFIG_USB_PHIDGETSERVO=m +CONFIG_USB_IDMOUSE=m +CONFIG_USB_FTDI_ELAN=m +# CONFIG_USB_APPLEDISPLAY is not set +CONFIG_USB_SISUSBVGA=m +CONFIG_USB_LD=m +CONFIG_USB_TRANCEVIBRATOR=m +CONFIG_USB_IOWARRIOR=m +CONFIG_USB_TEST=m +CONFIG_USB_ATM=m +CONFIG_USB_SPEEDTOUCH=m +CONFIG_USB_CXACRU=m +CONFIG_USB_UEAGLEATM=m +CONFIG_USB_XUSBATM=m +CONFIG_USB_GADGET=m +# CONFIG_USB_GADGET_DEBUG_FILES is not set +# CONFIG_USB_GADGET_DEBUG_FS is not set +CONFIG_USB_GADGET_SELECTED=y +# CONFIG_USB_GADGET_AMD5536UDC is not set +# CONFIG_USB_GADGET_ATMEL_USBA is not set +# CONFIG_USB_GADGET_FSL_USB2 is not set +CONFIG_USB_GADGET_NET2280=y +CONFIG_USB_NET2280=m +# CONFIG_USB_GADGET_PXA2XX is not set +# CONFIG_USB_GADGET_M66592 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_S3C2410 is not set +# CONFIG_USB_GADGET_AT91 is not set +# CONFIG_USB_GADGET_DUMMY_HCD is not set +CONFIG_USB_GADGET_DUALSPEED=y +CONFIG_USB_ZERO=m +CONFIG_USB_ETH=m +CONFIG_USB_ETH_RNDIS=y +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=m +# CONFIG_USB_G_PRINTER is not set +# CONFIG_MMC is not set +# CONFIG_MEMSTICK is not set +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y + +# +# LED drivers +# +CONFIG_LEDS_GPIO=y + +# +# LED Triggers +# +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=y +# CONFIG_INFINIBAND is not set +CONFIG_RTC_LIB=y +# CONFIG_RTC_CLASS is not set + +# +# Userspace I/O +# +# CONFIG_UIO is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +# CONFIG_EXT4DEV_FS is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +CONFIG_REISERFS_FS=m +# CONFIG_REISERFS_CHECK is not set +# CONFIG_REISERFS_PROC_INFO is not set +CONFIG_REISERFS_FS_XATTR=y +CONFIG_REISERFS_FS_POSIX_ACL=y +CONFIG_REISERFS_FS_SECURITY=y +CONFIG_JFS_FS=m +CONFIG_JFS_POSIX_ACL=y +CONFIG_JFS_SECURITY=y +# CONFIG_JFS_DEBUG is not set +# CONFIG_JFS_STATISTICS is not set +CONFIG_FS_POSIX_ACL=y +CONFIG_XFS_FS=m +CONFIG_XFS_QUOTA=y +CONFIG_XFS_SECURITY=y +CONFIG_XFS_POSIX_ACL=y +CONFIG_XFS_RT=y +CONFIG_GFS2_FS=m +CONFIG_GFS2_FS_LOCKING_NOLOCK=m +CONFIG_GFS2_FS_LOCKING_DLM=m +# CONFIG_OCFS2_FS is not set +CONFIG_DNOTIFY=y +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +CONFIG_QUOTA=y +CONFIG_QUOTA_NETLINK_INTERFACE=y +CONFIG_PRINT_QUOTA_WARNING=y +CONFIG_QFMT_V1=m +CONFIG_QFMT_V2=m +CONFIG_QUOTACTL=y +CONFIG_AUTOFS_FS=m +CONFIG_AUTOFS4_FS=m +CONFIG_FUSE_FS=m +CONFIG_GENERIC_ACL=y + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=m +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_UDF_FS=m +CONFIG_UDF_NLS=y + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=m +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +CONFIG_NTFS_FS=m +# CONFIG_NTFS_DEBUG is not set +CONFIG_NTFS_RW=y + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_PROC_SYSCTL=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_CONFIGFS_FS=m + +# +# Miscellaneous filesystems +# +CONFIG_ADFS_FS=m +# CONFIG_ADFS_FS_RW is not set +CONFIG_AFFS_FS=m +CONFIG_HFS_FS=m +CONFIG_HFSPLUS_FS=m +CONFIG_BEFS_FS=m +# CONFIG_BEFS_DEBUG is not set +CONFIG_BFS_FS=m +CONFIG_EFS_FS=m +CONFIG_JFFS2_FS=m +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_WBUF_VERIFY is not set +# CONFIG_JFFS2_SUMMARY is not set +CONFIG_JFFS2_FS_XATTR=y +CONFIG_JFFS2_FS_POSIX_ACL=y +CONFIG_JFFS2_FS_SECURITY=y +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +# CONFIG_JFFS2_LZO is not set +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +CONFIG_CRAMFS=m +CONFIG_VXFS_FS=m +CONFIG_MINIX_FS=m +CONFIG_HPFS_FS=m +CONFIG_QNX4FS_FS=m +CONFIG_ROMFS_FS=m +CONFIG_SYSV_FS=m +CONFIG_UFS_FS=m +# CONFIG_UFS_FS_WRITE is not set +# CONFIG_UFS_DEBUG is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=m +CONFIG_NFS_V3=y +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=y +# CONFIG_NFS_DIRECTIO is not set +CONFIG_NFSD=m +CONFIG_NFSD_V2_ACL=y +CONFIG_NFSD_V3=y +CONFIG_NFSD_V3_ACL=y +CONFIG_NFSD_V4=y +CONFIG_NFSD_TCP=y +CONFIG_LOCKD=m +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=m +CONFIG_NFS_ACL_SUPPORT=m +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=m +CONFIG_SUNRPC_GSS=m +CONFIG_SUNRPC_BIND34=y +CONFIG_RPCSEC_GSS_KRB5=m +CONFIG_RPCSEC_GSS_SPKM3=m +# CONFIG_SMB_FS is not set +CONFIG_CIFS=m +# CONFIG_CIFS_STATS is not set +# CONFIG_CIFS_WEAK_PW_HASH is not set +CONFIG_CIFS_XATTR=y +CONFIG_CIFS_POSIX=y +# CONFIG_CIFS_DEBUG2 is not set +# CONFIG_CIFS_EXPERIMENTAL is not set +CONFIG_NCP_FS=m +# CONFIG_NCPFS_PACKET_SIGNING is not set +# CONFIG_NCPFS_IOCTL_LOCKING is not set +# CONFIG_NCPFS_STRONG is not set +CONFIG_NCPFS_NFS_NS=y +CONFIG_NCPFS_OS2_NS=y +# CONFIG_NCPFS_SMALLDOS is not set +CONFIG_NCPFS_NLS=y +CONFIG_NCPFS_EXTRAS=y +CONFIG_CODA_FS=m +# CONFIG_CODA_FS_OLD_API is not set +# CONFIG_AFS_FS is not set +CONFIG_9P_FS=m + +# +# 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=y +# CONFIG_EFI_PARTITION is not set +# CONFIG_SYSV68_PARTITION is not set +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=m +CONFIG_NLS_CODEPAGE_737=m +CONFIG_NLS_CODEPAGE_775=m +CONFIG_NLS_CODEPAGE_850=m +CONFIG_NLS_CODEPAGE_852=m +CONFIG_NLS_CODEPAGE_855=m +CONFIG_NLS_CODEPAGE_857=m +CONFIG_NLS_CODEPAGE_860=m +CONFIG_NLS_CODEPAGE_861=m +CONFIG_NLS_CODEPAGE_862=m +CONFIG_NLS_CODEPAGE_863=m +CONFIG_NLS_CODEPAGE_864=m +CONFIG_NLS_CODEPAGE_865=m +CONFIG_NLS_CODEPAGE_866=m +CONFIG_NLS_CODEPAGE_869=m +CONFIG_NLS_CODEPAGE_936=m +CONFIG_NLS_CODEPAGE_950=m +CONFIG_NLS_CODEPAGE_932=m +CONFIG_NLS_CODEPAGE_949=m +CONFIG_NLS_CODEPAGE_874=m +CONFIG_NLS_ISO8859_8=m +CONFIG_NLS_CODEPAGE_1250=m +CONFIG_NLS_CODEPAGE_1251=m +CONFIG_NLS_ASCII=m +CONFIG_NLS_ISO8859_1=m +CONFIG_NLS_ISO8859_2=m +CONFIG_NLS_ISO8859_3=m +CONFIG_NLS_ISO8859_4=m +CONFIG_NLS_ISO8859_5=m +CONFIG_NLS_ISO8859_6=m +CONFIG_NLS_ISO8859_7=m +CONFIG_NLS_ISO8859_9=m +CONFIG_NLS_ISO8859_13=m +CONFIG_NLS_ISO8859_14=m +CONFIG_NLS_ISO8859_15=m +CONFIG_NLS_KOI8_R=m +CONFIG_NLS_KOI8_U=m +CONFIG_NLS_UTF8=m +CONFIG_DLM=m +CONFIG_DLM_DEBUG=y + +# +# Kernel hacking +# +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +# CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_FS=y +# CONFIG_HEADERS_CHECK is not set +# CONFIG_DEBUG_KERNEL is not set +# CONFIG_SAMPLES is not set +CONFIG_CMDLINE="" + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITY_FILE_CAPABILITIES is not set +CONFIG_CRYPTO=y +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_AEAD=m +CONFIG_CRYPTO_BLKCIPHER=m +# CONFIG_CRYPTO_SEQIV is not set +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_XCBC=m +CONFIG_CRYPTO_NULL=m +CONFIG_CRYPTO_MD4=m +CONFIG_CRYPTO_MD5=y +CONFIG_CRYPTO_SHA1=m +CONFIG_CRYPTO_SHA256=m +CONFIG_CRYPTO_SHA512=m +CONFIG_CRYPTO_WP512=m +CONFIG_CRYPTO_TGR192=m +CONFIG_CRYPTO_GF128MUL=m +CONFIG_CRYPTO_ECB=m +CONFIG_CRYPTO_CBC=m +CONFIG_CRYPTO_PCBC=m +CONFIG_CRYPTO_LRW=m +CONFIG_CRYPTO_XTS=m +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_CRYPTD is not set +CONFIG_CRYPTO_DES=m +CONFIG_CRYPTO_FCRYPT=m +CONFIG_CRYPTO_BLOWFISH=m +CONFIG_CRYPTO_TWOFISH=m +CONFIG_CRYPTO_TWOFISH_COMMON=m +CONFIG_CRYPTO_SERPENT=m +CONFIG_CRYPTO_AES=m +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_CAST6=m +CONFIG_CRYPTO_TEA=m +CONFIG_CRYPTO_ARC4=m +CONFIG_CRYPTO_KHAZAD=m +CONFIG_CRYPTO_ANUBIS=m +CONFIG_CRYPTO_SEED=m +# CONFIG_CRYPTO_SALSA20 is not set +CONFIG_CRYPTO_DEFLATE=m +CONFIG_CRYPTO_MICHAEL_MIC=m +CONFIG_CRYPTO_CRC32C=m +CONFIG_CRYPTO_CAMELLIA=m +CONFIG_CRYPTO_TEST=m +CONFIG_CRYPTO_AUTHENC=m +# CONFIG_CRYPTO_LZO is not set +CONFIG_CRYPTO_HW=y +# CONFIG_CRYPTO_DEV_HIFN_795X is not set + +# +# Library routines +# +CONFIG_BITREVERSE=y +CONFIG_CRC_CCITT=m +CONFIG_CRC16=m +CONFIG_CRC_ITU_T=m +CONFIG_CRC32=y +CONFIG_CRC7=m +CONFIG_LIBCRC32C=m +CONFIG_AUDIT_GENERIC=y +CONFIG_ZLIB_INFLATE=m +CONFIG_ZLIB_DEFLATE=m +CONFIG_TEXTSEARCH=y +CONFIG_TEXTSEARCH_KMP=m +CONFIG_TEXTSEARCH_BM=m +CONFIG_TEXTSEARCH_FSM=m +CONFIG_PLIST=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y diff --git a/arch/mips/configs/ip28_defconfig b/arch/mips/configs/ip28_defconfig new file mode 100644 index 000000000000..ec188be9a67a --- /dev/null +++ b/arch/mips/configs/ip28_defconfig @@ -0,0 +1,891 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.25-rc1 +# Mon Feb 11 15:58:54 2008 +# +CONFIG_MIPS=y + +# +# Machine selection +# +# CONFIG_MACH_ALCHEMY is not set +# CONFIG_BASLER_EXCITE is not set +# CONFIG_BCM47XX is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_MACH_DECSTATION is not set +# CONFIG_MACH_JAZZ is not set +# CONFIG_LASAT is not set +# CONFIG_LEMOTE_FULONG is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set +# CONFIG_MIPS_SIM is not set +# CONFIG_MARKEINS is not set +# CONFIG_MACH_VR41XX is not set +# CONFIG_PNX8550_JBS is not set +# CONFIG_PNX8550_STB810 is not set +# CONFIG_PMC_MSP is not set +# CONFIG_PMC_YOSEMITE is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP27 is not set +CONFIG_SGI_IP28=y +# CONFIG_SGI_IP32 is not set +# CONFIG_SIBYTE_CRHINE is not set +# CONFIG_SIBYTE_CARMEL is not set +# CONFIG_SIBYTE_CRHONE is not set +# CONFIG_SIBYTE_RHONE is not set +# CONFIG_SIBYTE_SWARM is not set +# CONFIG_SIBYTE_LITTLESUR is not set +# CONFIG_SIBYTE_SENTOSA is not set +# CONFIG_SIBYTE_BIGSUR is not set +# CONFIG_SNI_RM is not set +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +# CONFIG_TOSHIBA_RBTX4938 is not set +# CONFIG_WR_PPMC is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_ARCH_HAS_ILOG2_U32 is not set +# CONFIG_ARCH_HAS_ILOG2_U64 is not set +CONFIG_ARCH_SUPPORTS_OPROFILE=y +CONFIG_GENERIC_FIND_NEXT_BIT=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_TIME=y +CONFIG_GENERIC_CMOS_UPDATE=y +CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y +# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set +CONFIG_ARC=y +CONFIG_CEVT_R4K=y +CONFIG_CSRC_R4K=y +CONFIG_DMA_NONCOHERENT=y +CONFIG_DMA_NEED_PCI_MAP_STATE=y +CONFIG_EARLY_PRINTK=y +CONFIG_SYS_HAS_EARLY_PRINTK=y +# CONFIG_HOTPLUG_CPU is not set +CONFIG_I8259=y +# CONFIG_NO_IOPORT is not set +CONFIG_GENERIC_ISA_DMA=y +CONFIG_GENERIC_ISA_DMA_SUPPORT_BROKEN=y +CONFIG_CPU_BIG_ENDIAN=y +# CONFIG_CPU_LITTLE_ENDIAN is not set +CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y +CONFIG_IRQ_CPU=y +CONFIG_SWAP_IO_SPACE=y +CONFIG_SGI_HAS_DS1286=y +CONFIG_SGI_HAS_INDYDOG=y +CONFIG_SGI_HAS_SEEQ=y +CONFIG_SGI_HAS_WD93=y +CONFIG_SGI_HAS_ZILOG=y +CONFIG_SGI_HAS_I8042=y +CONFIG_DEFAULT_SGI_PARTITION=y +CONFIG_MIPS_L1_CACHE_SHIFT=7 +CONFIG_ARC_CONSOLE=y +CONFIG_ARC_PROMLIB=y +CONFIG_ARC64=y +CONFIG_BOOT_ELF64=y + +# +# CPU selection +# +# CONFIG_CPU_LOONGSON2 is not set +# CONFIG_CPU_MIPS32_R1 is not set +# CONFIG_CPU_MIPS32_R2 is not set +# CONFIG_CPU_MIPS64_R1 is not set +# CONFIG_CPU_MIPS64_R2 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_VR41XX is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +CONFIG_CPU_R10000=y +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_RM9000 is not set +# CONFIG_CPU_SB1 is not set +CONFIG_SYS_HAS_CPU_R10000=y +CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y +CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y +CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y + +# +# Kernel type +# +# CONFIG_32BIT is not set +CONFIG_64BIT=y +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_8KB is not set +# CONFIG_PAGE_SIZE_16KB is not set +# CONFIG_PAGE_SIZE_64KB is not set +CONFIG_CPU_HAS_PREFETCH=y +CONFIG_MIPS_MT_DISABLED=y +# CONFIG_MIPS_MT_SMP is not set +# CONFIG_MIPS_MT_SMTC is not set +CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_HAS_SYNC=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_CPU_SUPPORTS_HIGHMEM=y +CONFIG_ARCH_FLATMEM_ENABLE=y +CONFIG_ARCH_POPULATES_NODE_MAP=y +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_SPARSEMEM_VMEMMAP_ENABLE is not set +CONFIG_SPLIT_PTLOCK_CPUS=4 +CONFIG_RESOURCES_64BIT=y +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_VIRT_TO_BUS=y +# CONFIG_TICK_ONESHOT is not set +# CONFIG_NO_HZ is not set +# CONFIG_HIGH_RES_TIMERS is not set +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +# CONFIG_HZ_48 is not set +# CONFIG_HZ_100 is not set +# CONFIG_HZ_128 is not set +CONFIG_HZ_250=y +# CONFIG_HZ_256 is not set +# CONFIG_HZ_1000 is not set +# CONFIG_HZ_1024 is not set +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_HZ=250 +# CONFIG_PREEMPT_NONE is not set +CONFIG_PREEMPT_VOLUNTARY=y +# CONFIG_PREEMPT is not set +# CONFIG_RCU_TRACE is not set +# CONFIG_MIPS_INSANE_LARGE is not set +# CONFIG_KEXEC is not set +CONFIG_SECCOMP=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_TASKSTATS is not set +# CONFIG_AUDIT is not set +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_CGROUPS is not set +CONFIG_FAIR_GROUP_SCHED=y +CONFIG_FAIR_USER_SCHED=y +# CONFIG_FAIR_CGROUP_SCHED is not set +CONFIG_SYSFS_DEPRECATED=y +CONFIG_RELAY=y +# CONFIG_NAMESPACES is not set +# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SYSCTL=y +CONFIG_EMBEDDED=y +CONFIG_SYSCTL_SYSCALL=y +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_COMPAT_BRK=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_ANON_INODES=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +# CONFIG_MARKERS is not set +CONFIG_HAVE_OPROFILE=y +# CONFIG_HAVE_KPROBES is not set +# CONFIG_PROC_PAGE_MONITOR is not set +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +CONFIG_KMOD=y +CONFIG_BLOCK=y +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_BLK_DEV_BSG is not set +CONFIG_BLOCK_COMPAT=y + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +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" +CONFIG_CLASSIC_RCU=y +# CONFIG_PREEMPT_RCU is not set + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +CONFIG_HW_HAS_EISA=y +# CONFIG_ARCH_SUPPORTS_MSI is not set +CONFIG_ISA=y +CONFIG_EISA=y +CONFIG_EISA_NAMES=y +CONFIG_MMU=y +CONFIG_I8253=y + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_MIPS32_COMPAT=y +CONFIG_COMPAT=y +CONFIG_SYSVIPC_COMPAT=y +CONFIG_MIPS32_O32=y +CONFIG_MIPS32_N32=y +CONFIG_BINFMT_ELF32=y + +# +# Power management options +# +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_PM=y +# CONFIG_PM_LEGACY is not set +# CONFIG_PM_DEBUG is not set +# CONFIG_SUSPEND is not set + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +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_XFRM_MIGRATE=y +# CONFIG_XFRM_STATISTICS is not set +CONFIG_NET_KEY=y +CONFIG_NET_KEY_MIGRATE=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=y +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 is not set +# CONFIG_INET_XFRM_MODE_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_BEET is not set +# CONFIG_INET_LRO is not set +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_TCP_MD5SIG=y +# 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 +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# 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 +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set + +# +# Wireless +# +# CONFIG_CFG80211 is not set +# CONFIG_WIRELESS_EXT is not set +# CONFIG_MAC80211 is not set +# CONFIG_IEEE80211 is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_CONNECTOR is not set +# CONFIG_MTD is not set +# CONFIG_PARPORT is not set +# CONFIG_PNP is not set +CONFIG_BLK_DEV=y +# 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 is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +# CONFIG_MISC_DEVICES is not set +CONFIG_HAVE_IDE=y +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=y +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_TGT is not set +# 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=y +# CONFIG_BLK_DEV_SR_VENDOR 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 is not set +CONFIG_SCSI_CONSTANTS=y +# CONFIG_SCSI_LOGGING is not set +# CONFIG_SCSI_SCAN_ASYNC is not set +CONFIG_SCSI_WAIT_SCAN=m + +# +# 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_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set +CONFIG_SCSI_LOWLEVEL=y +# CONFIG_ISCSI_TCP is not set +CONFIG_SGIWD93_SCSI=y +# CONFIG_SCSI_AHA1740 is not set +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_ADVANSYS is not set +# CONFIG_SCSI_IN2000 is not set +# CONFIG_SCSI_DTC3280 is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +# CONFIG_SCSI_GENERIC_NCR5380 is not set +# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set +# CONFIG_SCSI_NCR53C406A is not set +# CONFIG_SCSI_PAS16 is not set +# CONFIG_SCSI_QLOGIC_FAS is not set +# CONFIG_SCSI_SIM710 is not set +# CONFIG_SCSI_SYM53C416 is not set +# CONFIG_SCSI_T128 is not set +# CONFIG_SCSI_DEBUG is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set +CONFIG_NETDEVICES=y +# CONFIG_NETDEVICES_MULTIQUEUE is not set +CONFIG_DUMMY=m +# CONFIG_BONDING is not set +# CONFIG_MACVLAN is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_VETH is not set +# CONFIG_ARCNET is not set +# CONFIG_PHYLIB is not set +CONFIG_NET_ETHERNET=y +# CONFIG_MII is not set +# CONFIG_AX88796 is not set +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_NET_VENDOR_SMC is not set +# CONFIG_DM9000 is not set +# CONFIG_NET_VENDOR_RACAL is not set +# CONFIG_NET_TULIP is not set +# CONFIG_AT1700 is not set +# CONFIG_DEPCA is not set +# CONFIG_HP100 is not set +# CONFIG_NET_ISA is not set +# CONFIG_IBM_NEW_EMAC_ZMII is not set +# CONFIG_IBM_NEW_EMAC_RGMII is not set +# CONFIG_IBM_NEW_EMAC_TAH is not set +# CONFIG_IBM_NEW_EMAC_EMAC4 is not set +# CONFIG_NET_PCI is not set +# CONFIG_B44 is not set +CONFIG_SGISEEQ=y +# CONFIG_NETDEV_1000 is not set +# CONFIG_NETDEV_10000 is not set +# CONFIG_TR is not set + +# +# Wireless LAN +# +# CONFIG_WLAN_PRE80211 is not set +# CONFIG_WLAN_80211 is not set +# CONFIG_WAN is not set +# CONFIG_FDDI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_ISDN is not set +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_STOWAWAY is not set +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=y +# CONFIG_MOUSE_PS2_ALPS is not set +CONFIG_MOUSE_PS2_LOGIPS2PP=y +# CONFIG_MOUSE_PS2_SYNAPTICS is not set +# CONFIG_MOUSE_PS2_LIFEBOOK is not set +CONFIG_MOUSE_PS2_TRACKPOINT=y +# CONFIG_MOUSE_PS2_TOUCHKIT is not set +# CONFIG_MOUSE_SERIAL is not set +# CONFIG_MOUSE_INPORT is not set +# CONFIG_MOUSE_LOGIBM is not set +# CONFIG_MOUSE_PC110PAD is not set +# CONFIG_MOUSE_VSXXXAA is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_I8042=y +CONFIG_SERIO_SERPORT=y +CONFIG_SERIO_LIBPS2=y +# CONFIG_SERIO_RAW 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=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_IP22_ZILOG=y +CONFIG_SERIAL_IP22_ZILOG_CONSOLE=y +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 +# CONFIG_IPMI_HANDLER is not set +# CONFIG_HW_RANDOM is not set +# CONFIG_RTC is not set +CONFIG_SGI_DS1286=y +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +CONFIG_DEVPORT=y +# CONFIG_I2C is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +# CONFIG_HWMON is not set +# CONFIG_THERMAL is not set +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set +CONFIG_INDYDOG=y + +# +# ISA-based Watchdog Cards +# +# CONFIG_PCWATCHDOG is not set +# CONFIG_MIXCOMWD is not set +# CONFIG_WDT is not set + +# +# Sonics Silicon Backplane +# +CONFIG_SSB_POSSIBLE=y +# CONFIG_SSB is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_SM501 is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set +# CONFIG_DVB_CORE is not set +# CONFIG_DAB is not set + +# +# Graphics support +# +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +# CONFIG_FB is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +# CONFIG_MDA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y + +# +# Sound +# +# CONFIG_SOUND is not set +CONFIG_HID_SUPPORT=y +CONFIG_HID=y +# CONFIG_HID_DEBUG is not set +# CONFIG_HIDRAW is not set +CONFIG_USB_SUPPORT=y +# 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' +# +# CONFIG_USB_GADGET is not set +# CONFIG_MMC is not set +# CONFIG_MEMSTICK is not set +# CONFIG_NEW_LEDS is not set +CONFIG_RTC_LIB=y +# CONFIG_RTC_CLASS is not set + +# +# Userspace I/O +# +# CONFIG_UIO 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=y +CONFIG_EXT3_FS_SECURITY=y +# CONFIG_EXT4DEV_FS is not set +CONFIG_JBD=y +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y +# CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set +# CONFIG_OCFS2_FS is not set +CONFIG_DNOTIFY=y +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +CONFIG_QUOTA=y +# CONFIG_QUOTA_NETLINK_INTERFACE is not set +CONFIG_PRINT_QUOTA_WARNING=y +# CONFIG_QFMT_V1 is not set +# CONFIG_QFMT_V2 is not set +CONFIG_QUOTACTL=y +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set +CONFIG_GENERIC_ACL=y + +# +# 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_KCORE=y +CONFIG_PROC_SYSCTL=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +# CONFIG_HUGETLB_PAGE is not set +# 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 is not set +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +CONFIG_NFS_V3_ACL=y +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +# CONFIG_NFSD is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_ACL_SUPPORT=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_BIND34 is not set +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 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 + +# +# 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=y +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +# CONFIG_EFI_PARTITION is not set +# CONFIG_SYSV68_PARTITION is not set +# CONFIG_NLS is not set +# CONFIG_DLM is not set + +# +# Kernel hacking +# +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +# CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_MAGIC_SYSRQ=y +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_HEADERS_CHECK is not set +# CONFIG_DEBUG_KERNEL is not set +# CONFIG_SAMPLES is not set +CONFIG_CMDLINE="" + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITY_FILE_CAPABILITIES is not set +CONFIG_CRYPTO=y +CONFIG_CRYPTO_ALGAPI=y +# CONFIG_CRYPTO_SEQIV is not set +CONFIG_CRYPTO_MANAGER=y +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_XCBC is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_MD4 is not set +CONFIG_CRYPTO_MD5=y +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_WP512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_ECB is not set +# CONFIG_CRYPTO_CBC is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_XTS is not set +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_CRYPTD is not set +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_TWOFISH is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_TEST is not set +# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_LZO is not set +# CONFIG_CRYPTO_HW is not set + +# +# Library routines +# +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +# CONFIG_CRC_ITU_T is not set +# CONFIG_CRC32 is not set +# CONFIG_CRC7 is not set +# CONFIG_LIBCRC32C is not set +CONFIG_PLIST=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y diff --git a/arch/mips/configs/qemu_defconfig b/arch/mips/configs/qemu_defconfig deleted file mode 100644 index 72ca147f9422..000000000000 --- a/arch/mips/configs/qemu_defconfig +++ /dev/null @@ -1,800 +0,0 @@ -# -# Automatically generated make config: don't edit -# Linux kernel version: 2.6.20 -# Tue Feb 20 21:47:39 2007 -# -CONFIG_MIPS=y - -# -# Machine selection -# -CONFIG_ZONE_DMA=y -# CONFIG_MIPS_MTX1 is not set -# CONFIG_MIPS_BOSPORUS is not set -# CONFIG_MIPS_PB1000 is not set -# CONFIG_MIPS_PB1100 is not set -# CONFIG_MIPS_PB1500 is not set -# CONFIG_MIPS_PB1550 is not set -# CONFIG_MIPS_PB1200 is not set -# CONFIG_MIPS_DB1000 is not set -# CONFIG_MIPS_DB1100 is not set -# CONFIG_MIPS_DB1500 is not set -# CONFIG_MIPS_DB1550 is not set -# CONFIG_MIPS_DB1200 is not set -# CONFIG_MIPS_MIRAGE is not set -# CONFIG_BASLER_EXCITE is not set -# CONFIG_MIPS_COBALT is not set -# CONFIG_MACH_DECSTATION is not set -# CONFIG_MACH_JAZZ is not set -# CONFIG_MIPS_ATLAS is not set -# CONFIG_MIPS_MALTA is not set -# CONFIG_MIPS_SEAD is not set -# CONFIG_WR_PPMC is not set -# CONFIG_MIPS_SIM is not set -# CONFIG_MOMENCO_JAGUAR_ATX is not set -# CONFIG_MIPS_XXS1500 is not set -# CONFIG_PNX8550_JBS is not set -# CONFIG_PNX8550_STB810 is not set -# CONFIG_MACH_VR41XX is not set -# CONFIG_PMC_YOSEMITE is not set -# CONFIG_MARKEINS is not set -# CONFIG_SGI_IP22 is not set -# CONFIG_SGI_IP27 is not set -# CONFIG_SGI_IP32 is not set -# CONFIG_SIBYTE_BIGSUR is not set -# CONFIG_SIBYTE_SWARM is not set -# CONFIG_SIBYTE_SENTOSA is not set -# CONFIG_SIBYTE_RHONE is not set -# CONFIG_SIBYTE_CARMEL is not set -# CONFIG_SIBYTE_LITTLESUR is not set -# CONFIG_SIBYTE_CRHINE is not set -# CONFIG_SIBYTE_CRHONE is not set -# CONFIG_SNI_RM is not set -# CONFIG_TOSHIBA_JMR3927 is not set -# CONFIG_TOSHIBA_RBTX4927 is not set -# CONFIG_TOSHIBA_RBTX4938 is not set -CONFIG_RWSEM_GENERIC_SPINLOCK=y -# CONFIG_ARCH_HAS_ILOG2_U32 is not set -# CONFIG_ARCH_HAS_ILOG2_U64 is not set -CONFIG_GENERIC_FIND_NEXT_BIT=y -CONFIG_GENERIC_HWEIGHT=y -CONFIG_GENERIC_CALIBRATE_DELAY=y -CONFIG_GENERIC_TIME=y -CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y -CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y -CONFIG_DMA_COHERENT=y -CONFIG_GENERIC_ISA_DMA=y -CONFIG_I8259=y -CONFIG_CPU_BIG_ENDIAN=y -# CONFIG_CPU_LITTLE_ENDIAN is not set -CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y -CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y -CONFIG_SWAP_IO_SPACE=y -CONFIG_MIPS_L1_CACHE_SHIFT=5 -CONFIG_HAVE_STD_PC_SERIAL_PORT=y - -# -# CPU selection -# -CONFIG_CPU_MIPS32_R1=y -# CONFIG_CPU_MIPS32_R2 is not set -# CONFIG_CPU_MIPS64_R1 is not set -# CONFIG_CPU_MIPS64_R2 is not set -# CONFIG_CPU_R3000 is not set -# CONFIG_CPU_TX39XX is not set -# CONFIG_CPU_VR41XX is not set -# CONFIG_CPU_R4300 is not set -# CONFIG_CPU_R4X00 is not set -# CONFIG_CPU_TX49XX is not set -# CONFIG_CPU_R5000 is not set -# CONFIG_CPU_R5432 is not set -# CONFIG_CPU_R6000 is not set -# CONFIG_CPU_NEVADA is not set -# CONFIG_CPU_R8000 is not set -# CONFIG_CPU_R10000 is not set -# CONFIG_CPU_RM7000 is not set -# CONFIG_CPU_RM9000 is not set -# CONFIG_CPU_SB1 is not set -CONFIG_SYS_HAS_CPU_MIPS32_R1=y -CONFIG_CPU_MIPS32=y -CONFIG_CPU_MIPSR1=y -CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y -CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y - -# -# Kernel type -# -CONFIG_32BIT=y -# CONFIG_64BIT is not set -CONFIG_PAGE_SIZE_4KB=y -# CONFIG_PAGE_SIZE_8KB is not set -# CONFIG_PAGE_SIZE_16KB is not set -# CONFIG_PAGE_SIZE_64KB is not set -CONFIG_CPU_HAS_PREFETCH=y -CONFIG_MIPS_MT_DISABLED=y -# CONFIG_MIPS_MT_SMP is not set -# CONFIG_MIPS_MT_SMTC is not set -# CONFIG_MIPS_VPE_LOADER is not set -# CONFIG_64BIT_PHYS_ADDR is not set -CONFIG_CPU_HAS_LLSC=y -CONFIG_CPU_HAS_SYNC=y -CONFIG_GENERIC_HARDIRQS=y -CONFIG_GENERIC_IRQ_PROBE=y -CONFIG_CPU_SUPPORTS_HIGHMEM=y -CONFIG_ARCH_FLATMEM_ENABLE=y -CONFIG_ARCH_SPARSEMEM_ENABLE=y -CONFIG_FLATMEM=y -CONFIG_FLAT_NODE_MEM_MAP=y -CONFIG_SPARSEMEM_STATIC=y -CONFIG_SPLIT_PTLOCK_CPUS=4 -# CONFIG_RESOURCES_64BIT is not set -CONFIG_ZONE_DMA_FLAG=1 -# CONFIG_HZ_48 is not set -CONFIG_HZ_100=y -# CONFIG_HZ_128 is not set -# CONFIG_HZ_250 is not set -# CONFIG_HZ_256 is not set -# CONFIG_HZ_1000 is not set -# CONFIG_HZ_1024 is not set -CONFIG_SYS_SUPPORTS_ARBIT_HZ=y -CONFIG_HZ=100 -CONFIG_PREEMPT_NONE=y -# CONFIG_PREEMPT_VOLUNTARY is not set -# CONFIG_PREEMPT is not set -CONFIG_LOCKDEP_SUPPORT=y -CONFIG_STACKTRACE_SUPPORT=y -CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" - -# -# Code maturity level options -# -# CONFIG_EXPERIMENTAL is not set -CONFIG_BROKEN_ON_SMP=y -CONFIG_INIT_ENV_ARG_LIMIT=32 - -# -# General setup -# -CONFIG_LOCALVERSION="" -CONFIG_LOCALVERSION_AUTO=y -# CONFIG_SWAP is not set -# CONFIG_SYSVIPC 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_SYSFS_DEPRECATED=y -CONFIG_RELAY=y -CONFIG_SYSCTL=y -CONFIG_EMBEDDED=y -CONFIG_SYSCTL_SYSCALL=y -CONFIG_KALLSYMS=y -# CONFIG_KALLSYMS_EXTRA_PASS is not set -# CONFIG_HOTPLUG is not set -CONFIG_PRINTK=y -# CONFIG_BUG is not set -CONFIG_ELF_CORE=y -# CONFIG_BASE_FULL is not set -# CONFIG_FUTEX is not set -# CONFIG_EPOLL is not set -# CONFIG_SHMEM is not set -CONFIG_SLAB=y -CONFIG_VM_EVENT_COUNTERS=y -CONFIG_TINY_SHMEM=y -CONFIG_BASE_SMALL=1 -# CONFIG_SLOB is not set - -# -# Loadable module support -# -# CONFIG_MODULES is not set - -# -# Block layer -# -CONFIG_BLOCK=y -# CONFIG_LBD is not set -# CONFIG_BLK_DEV_IO_TRACE 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" - -# -# Bus options (PCI, PCMCIA, EISA, ISA, TC) -# -CONFIG_ISA=y -CONFIG_MMU=y -CONFIG_PCSPEAKER=y - -# -# PCCARD (PCMCIA/CardBus) support -# - -# -# PCI Hotplug Support -# - -# -# Executable file formats -# -CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_MISC is not set -CONFIG_TRAD_SIGNALS=y - -# -# Power management options -# -CONFIG_PM=y -# CONFIG_PM_LEGACY is not set -# CONFIG_PM_DEBUG is not set -# CONFIG_PM_SYSFS_DEPRECATED 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_NET_KEY is not set -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=y -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_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=y -# CONFIG_NETFILTER 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 - -# -# 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 is not set -# CONFIG_SYS_HYPERVISOR is not set - -# -# Connector - unified userspace <-> kernelspace linker -# -CONFIG_CONNECTOR=y -CONFIG_PROC_EVENTS=y - -# -# Memory Technology Devices (MTD) -# -# CONFIG_MTD is not set - -# -# Parallel port support -# -# CONFIG_PARPORT is not set - -# -# Plug and Play support -# -# CONFIG_PNP is not set -# CONFIG_PNPACPI is not set - -# -# 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 is not set -# CONFIG_BLK_DEV_INITRD is not set -# CONFIG_CDROM_PKTCDVD is not set -# CONFIG_ATA_OVER_ETH is not set - -# -# Misc devices -# - -# -# 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 - -# -# Old CD-ROM drivers (not SCSI, not IDE) -# -# CONFIG_CD_NO_IDESCSI 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 - -# -# ARCnet devices -# -# CONFIG_ARCNET is not set - -# -# PHY device support -# -# CONFIG_PHYLIB is not set - -# -# Ethernet (10 or 100Mbit) -# -CONFIG_NET_ETHERNET=y -# CONFIG_MII is not set -# CONFIG_NET_VENDOR_3COM is not set -# CONFIG_NET_VENDOR_SMC is not set -# CONFIG_DM9000 is not set -# CONFIG_NET_VENDOR_RACAL is not set -# CONFIG_DEPCA is not set -# CONFIG_HP100 is not set -CONFIG_NET_ISA=y -# CONFIG_E2100 is not set -# CONFIG_EWRK3 is not set -# CONFIG_EEXPRESS is not set -# CONFIG_EEXPRESS_PRO is not set -# CONFIG_HPLAN_PLUS is not set -# CONFIG_HPLAN is not set -# CONFIG_LP486E is not set -# CONFIG_ETH16I is not set -CONFIG_NE2000=y -# CONFIG_NET_PCI is not set - -# -# Ethernet (1000 Mbit) -# - -# -# Ethernet (10000 Mbit) -# - -# -# 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_PPP is not set -# CONFIG_SLIP 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=y -# CONFIG_INPUT_FF_MEMLESS is not set - -# -# Userland interfaces -# -# CONFIG_INPUT_MOUSEDEV is not set -# 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=y -# CONFIG_SERIAL_NONSTANDARD is not set - -# -# Serial drivers -# -CONFIG_SERIAL_8250=y -CONFIG_SERIAL_8250_CONSOLE=y -CONFIG_SERIAL_8250_NR_UARTS=4 -CONFIG_SERIAL_8250_RUNTIME_UARTS=4 -# CONFIG_SERIAL_8250_EXTENDED is not set - -# -# Non-8250 serial port support -# -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 is not set -# CONFIG_HW_RANDOM is not set -# CONFIG_RTC is not set -# CONFIG_GEN_RTC is not set -# CONFIG_DTLK is not set -# CONFIG_R3964 is not set -# CONFIG_RAW_DRIVER is not set - -# -# TPM devices -# - -# -# 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 - -# -# Multimedia devices -# -# CONFIG_VIDEO_DEV is not set - -# -# Digital Video Broadcasting Devices -# -# CONFIG_DVB is not set - -# -# Graphics support -# -# CONFIG_FIRMWARE_EDID is not set -# CONFIG_FB is not set - -# -# Console display driver support -# -CONFIG_VGA_CONSOLE=y -# CONFIG_VGACON_SOFT_SCROLLBACK is not set -# CONFIG_MDA_CONSOLE is not set -CONFIG_DUMMY_CONSOLE=y -# CONFIG_BACKLIGHT_LCD_SUPPORT is not set - -# -# Sound -# -# CONFIG_SOUND is not set - -# -# HID Devices -# -CONFIG_HID=y -# CONFIG_HID_DEBUG 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 -# - -# -# DMA Engine support -# -# CONFIG_DMA_ENGINE is not set - -# -# DMA Clients -# - -# -# DMA Devices -# - -# -# Auxiliary Display support -# - -# -# Virtualization -# - -# -# File systems -# -# CONFIG_EXT2_FS is not set -# CONFIG_EXT3_FS is not set -# CONFIG_REISERFS_FS is not set -# CONFIG_JFS_FS is not set -CONFIG_FS_POSIX_ACL=y -# CONFIG_XFS_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 is not set -# CONFIG_AUTOFS_FS is not set -# CONFIG_AUTOFS4_FS is not set -CONFIG_FUSE_FS=y -CONFIG_GENERIC_ACL=y - -# -# 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_KCORE=y -CONFIG_PROC_SYSCTL=y -CONFIG_SYSFS=y -CONFIG_TMPFS=y -CONFIG_TMPFS_POSIX_ACL=y -# CONFIG_HUGETLB_PAGE is not set -CONFIG_RAMFS=y - -# -# Miscellaneous filesystems -# -# CONFIG_HFSPLUS_FS 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_DIRECTIO=y -# CONFIG_NFSD is not set -CONFIG_ROOT_NFS=y -CONFIG_LOCKD=y -CONFIG_LOCKD_V4=y -CONFIG_NFS_COMMON=y -CONFIG_SUNRPC=y -# CONFIG_SMB_FS is not set -# CONFIG_CIFS is not set -# CONFIG_NCP_FS is not set -# CONFIG_CODA_FS is not set - -# -# Partition Types -# -# CONFIG_PARTITION_ADVANCED is not set -CONFIG_MSDOS_PARTITION=y - -# -# Native Language Support -# -# CONFIG_NLS is not set - -# -# Kernel hacking -# -CONFIG_TRACE_IRQFLAGS_SUPPORT=y -# 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_FS is not set -# CONFIG_HEADERS_CHECK is not set -# CONFIG_DEBUG_KERNEL is not set -CONFIG_LOG_BUF_SHIFT=14 -CONFIG_CROSSCOMPILE=y -CONFIG_CMDLINE="" - -# -# Security options -# -# CONFIG_KEYS is not set -# CONFIG_SECURITY is not set - -# -# Cryptographic options -# -# CONFIG_CRYPTO is not set - -# -# Library routines -# -CONFIG_BITREVERSE=y -# CONFIG_CRC_CCITT is not set -# CONFIG_CRC16 is not set -CONFIG_CRC32=y -# CONFIG_LIBCRC32C is not set -CONFIG_HAS_IOMEM=y -CONFIG_HAS_IOPORT=y diff --git a/arch/mips/kernel/irq-rm7000.c b/arch/mips/kernel/irq-rm7000.c index 971adf6ef4f4..fb50cc78b28b 100644 --- a/arch/mips/kernel/irq-rm7000.c +++ b/arch/mips/kernel/irq-rm7000.c @@ -33,6 +33,7 @@ static struct irq_chip rm7k_irq_controller = { .mask = mask_rm7k_irq, .mask_ack = mask_rm7k_irq, .unmask = unmask_rm7k_irq, + .eoi = unmask_rm7k_irq }; void __init rm7k_cpu_irq_init(void) diff --git a/arch/mips/kernel/irq-rm9000.c b/arch/mips/kernel/irq-rm9000.c index 7b04583bd800..ed9febe63d72 100644 --- a/arch/mips/kernel/irq-rm9000.c +++ b/arch/mips/kernel/irq-rm9000.c @@ -75,6 +75,7 @@ static struct irq_chip rm9k_irq_controller = { .mask = mask_rm9k_irq, .mask_ack = mask_rm9k_irq, .unmask = unmask_rm9k_irq, + .eoi = unmask_rm9k_irq }; static struct irq_chip rm9k_perfcounter_irq = { diff --git a/arch/mips/kernel/mips-mt-fpaff.c b/arch/mips/kernel/mips-mt-fpaff.c index bb4f00c0cbe9..df4d3f2f740c 100644 --- a/arch/mips/kernel/mips-mt-fpaff.c +++ b/arch/mips/kernel/mips-mt-fpaff.c @@ -36,7 +36,7 @@ unsigned long mt_fpemul_threshold = 0; */ static inline struct task_struct *find_process_by_pid(pid_t pid) { - return pid ? find_task_by_pid(pid) : current; + return pid ? find_task_by_vpid(pid) : current; } diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S index f798139e888e..08a9c5070ea8 100644 --- a/arch/mips/kernel/scall32-o32.S +++ b/arch/mips/kernel/scall32-o32.S @@ -663,6 +663,9 @@ einval: li v0, -EINVAL sys sys_ni_syscall 0 sys sys_eventfd 1 sys sys_fallocate 6 /* 4320 */ + sys sys_timerfd_create 2 + sys sys_timerfd_gettime 2 + sys sys_timerfd_settime 4 .endm /* We pre-compute the number of _instruction_ bytes needed to diff --git a/arch/mips/kernel/scall64-64.S b/arch/mips/kernel/scall64-64.S index a626be6baea3..dc597b600c68 100644 --- a/arch/mips/kernel/scall64-64.S +++ b/arch/mips/kernel/scall64-64.S @@ -478,4 +478,7 @@ sys_call_table: PTR sys_ni_syscall PTR sys_eventfd PTR sys_fallocate + PTR sys_timerfd_create /* 5280 */ + PTR sys_timerfd_gettime + PTR sys_timerfd_settime .size sys_call_table,.-sys_call_table diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S index 9d5bcaf1b389..12940eca7893 100644 --- a/arch/mips/kernel/scall64-n32.S +++ b/arch/mips/kernel/scall64-n32.S @@ -404,4 +404,7 @@ EXPORT(sysn32_call_table) PTR sys_ni_syscall PTR sys_eventfd PTR sys_fallocate + PTR sys_timerfd_create + PTR sys_timerfd_gettime /* 5285 */ + PTR sys_timerfd_settime .size sysn32_call_table,.-sysn32_call_table diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S index fd2019c1ec2d..9a275efb4f04 100644 --- a/arch/mips/kernel/scall64-o32.S +++ b/arch/mips/kernel/scall64-o32.S @@ -526,4 +526,7 @@ sys_call_table: PTR sys_ni_syscall PTR sys_eventfd PTR sys32_fallocate /* 4320 */ + PTR sys_timerfd_create + PTR sys_timerfd_gettime + PTR sys_timerfd_settime .size sys_call_table,.-sys_call_table diff --git a/arch/mips/kernel/sysirix.c b/arch/mips/kernel/sysirix.c index d70c4e0e85fb..c357762b8012 100644 --- a/arch/mips/kernel/sysirix.c +++ b/arch/mips/kernel/sysirix.c @@ -111,7 +111,7 @@ asmlinkage int irix_prctl(unsigned option, ...) printk("irix_prctl[%s:%d]: Wants PR_ISBLOCKED\n", current->comm, current->pid); read_lock(&tasklist_lock); - task = find_task_by_pid(va_arg(args, pid_t)); + task = find_task_by_vpid(va_arg(args, pid_t)); error = -ESRCH; if (error) error = (task->run_list.next != NULL); @@ -694,7 +694,7 @@ asmlinkage int irix_statfs(const char __user *path, if (error) goto out; - error = vfs_statfs(nd.dentry, &kbuf); + error = vfs_statfs(nd.path.dentry, &kbuf); if (error) goto dput_and_out; @@ -711,7 +711,7 @@ asmlinkage int irix_statfs(const char __user *path, } dput_and_out: - path_release(&nd); + path_put(&nd.path); out: return error; } @@ -1360,7 +1360,7 @@ asmlinkage int irix_statvfs(char __user *fname, struct irix_statvfs __user *buf) error = user_path_walk(fname, &nd); if (error) goto out; - error = vfs_statfs(nd.dentry, &kbuf); + error = vfs_statfs(nd.path.dentry, &kbuf); if (error) goto dput_and_out; @@ -1385,7 +1385,7 @@ asmlinkage int irix_statvfs(char __user *fname, struct irix_statvfs __user *buf) error |= __put_user(0, &buf->f_fstr[i]); dput_and_out: - path_release(&nd); + path_put(&nd.path); out: return error; } @@ -1611,7 +1611,7 @@ asmlinkage int irix_statvfs64(char __user *fname, struct irix_statvfs64 __user * error = user_path_walk(fname, &nd); if (error) goto out; - error = vfs_statfs(nd.dentry, &kbuf); + error = vfs_statfs(nd.path.dentry, &kbuf); if (error) goto dput_and_out; @@ -1636,7 +1636,7 @@ asmlinkage int irix_statvfs64(char __user *fname, struct irix_statvfs64 __user * error |= __put_user(0, &buf->f_fstr[i]); dput_and_out: - path_release(&nd); + path_put(&nd.path); out: return error; } diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c index 53ec05267a98..2c4f7e11f0d5 100644 --- a/arch/mips/mm/c-r4k.c +++ b/arch/mips/mm/c-r4k.c @@ -364,20 +364,23 @@ static inline int has_valid_asid(const struct mm_struct *mm) static inline void local_r4k_flush_cache_range(void * args) { struct vm_area_struct *vma = args; + int exec = vma->vm_flags & VM_EXEC; if (!(has_valid_asid(vma->vm_mm))) return; r4k_blast_dcache(); + if (exec) + r4k_blast_icache(); } static void r4k_flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end) { - if (!cpu_has_dc_aliases) - return; + int exec = vma->vm_flags & VM_EXEC; - r4k_on_each_cpu(local_r4k_flush_cache_range, vma, 1, 1); + if (cpu_has_dc_aliases || (exec && !cpu_has_ic_fills_f_dc)) + r4k_on_each_cpu(local_r4k_flush_cache_range, vma, 1, 1); } static inline void local_r4k_flush_cache_mm(void * args) diff --git a/arch/mips/mm/cache.c b/arch/mips/mm/cache.c index 81f30ac2bff9..6a24651971df 100644 --- a/arch/mips/mm/cache.c +++ b/arch/mips/mm/cache.c @@ -92,12 +92,17 @@ EXPORT_SYMBOL(__flush_dcache_page); void __flush_anon_page(struct page *page, unsigned long vmaddr) { - if (pages_do_alias((unsigned long)page_address(page), vmaddr)) { - void *kaddr; + unsigned long addr = (unsigned long) page_address(page); - kaddr = kmap_coherent(page, vmaddr); - flush_data_cache_page((unsigned long)kaddr); - kunmap_coherent(); + if (pages_do_alias(addr, vmaddr)) { + if (page_mapped(page) && !Page_dcache_dirty(page)) { + void *kaddr; + + kaddr = kmap_coherent(page, vmaddr); + flush_data_cache_page((unsigned long)kaddr); + kunmap_coherent(); + } else + flush_data_cache_page(addr); } } diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c index 480dec04f552..c7aed133d11d 100644 --- a/arch/mips/mm/init.c +++ b/arch/mips/mm/init.c @@ -211,7 +211,8 @@ void copy_user_highpage(struct page *to, struct page *from, void *vfrom, *vto; vto = kmap_atomic(to, KM_USER1); - if (cpu_has_dc_aliases && page_mapped(from)) { + if (cpu_has_dc_aliases && + page_mapped(from) && !Page_dcache_dirty(from)) { vfrom = kmap_coherent(from, vaddr); copy_page(vto, vfrom); kunmap_coherent(); @@ -234,7 +235,8 @@ void copy_to_user_page(struct vm_area_struct *vma, struct page *page, unsigned long vaddr, void *dst, const void *src, unsigned long len) { - if (cpu_has_dc_aliases && page_mapped(page)) { + if (cpu_has_dc_aliases && + page_mapped(page) && !Page_dcache_dirty(page)) { void *vto = kmap_coherent(page, vaddr) + (vaddr & ~PAGE_MASK); memcpy(vto, src, len); kunmap_coherent(); @@ -253,7 +255,8 @@ void copy_from_user_page(struct vm_area_struct *vma, struct page *page, unsigned long vaddr, void *dst, const void *src, unsigned long len) { - if (cpu_has_dc_aliases && page_mapped(page)) { + if (cpu_has_dc_aliases && + page_mapped(page) && !Page_dcache_dirty(page)) { void *vfrom = kmap_coherent(page, vaddr) + (vaddr & ~PAGE_MASK); memcpy(dst, vfrom, len); kunmap_coherent(); diff --git a/arch/mips/mm/pg-sb1.c b/arch/mips/mm/pg-sb1.c index a3e98c243a89..89925ec57d6a 100644 --- a/arch/mips/mm/pg-sb1.c +++ b/arch/mips/mm/pg-sb1.c @@ -216,7 +216,7 @@ void sb1_dma_init(void) int i; for (i = 0; i < DM_NUM_CHANNELS; i++) { - const u64 base_val = CPHYSADDR(&page_descr[i]) | + const u64 base_val = CPHYSADDR((unsigned long)&page_descr[i]) | V_DM_DSCR_BASE_RINGSZ(1); void *base_reg = IOADDR(A_DM_REGISTER(i, R_DM_DSCR_BASE)); @@ -228,11 +228,11 @@ void sb1_dma_init(void) void clear_page(void *page) { - u64 to_phys = CPHYSADDR(page); + u64 to_phys = CPHYSADDR((unsigned long)page); unsigned int cpu = smp_processor_id(); /* if the page is not in KSEG0, use old way */ - if ((long)KSEGX(page) != (long)CKSEG0) + if ((long)KSEGX((unsigned long)page) != (long)CKSEG0) return clear_page_cpu(page); page_descr[cpu].dscr_a = to_phys | M_DM_DSCRA_ZERO_MEM | @@ -252,13 +252,13 @@ void clear_page(void *page) void copy_page(void *to, void *from) { - u64 from_phys = CPHYSADDR(from); - u64 to_phys = CPHYSADDR(to); + u64 from_phys = CPHYSADDR((unsigned long)from); + u64 to_phys = CPHYSADDR((unsigned long)to); unsigned int cpu = smp_processor_id(); /* if any page is not in KSEG0, use old way */ - if ((long)KSEGX(to) != (long)CKSEG0 - || (long)KSEGX(from) != (long)CKSEG0) + if ((long)KSEGX((unsigned long)to) != (long)CKSEG0 + || (long)KSEGX((unsigned long)from) != (long)CKSEG0) return copy_page_cpu(to, from); page_descr[cpu].dscr_a = to_phys | M_DM_DSCRA_L2C_DEST | diff --git a/arch/mips/pci/pci.c b/arch/mips/pci/pci.c index 6e6981fd7934..f9471d77c096 100644 --- a/arch/mips/pci/pci.c +++ b/arch/mips/pci/pci.c @@ -177,8 +177,15 @@ static int pcibios_enable_resources(struct pci_dev *dev, int mask) continue; r = &dev->resource[idx]; + if (!(r->flags & (IORESOURCE_IO | IORESOURCE_MEM))) + continue; + if ((idx == PCI_ROM_RESOURCE) && + (!(r->flags & IORESOURCE_ROM_ENABLE))) + continue; if (!r->start && r->end) { - printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", pci_name(dev)); + printk(KERN_ERR "PCI: Device %s not available " + "because of resource collisions\n", + pci_name(dev)); return -EINVAL; } if (r->flags & IORESOURCE_IO) @@ -186,10 +193,9 @@ static int pcibios_enable_resources(struct pci_dev *dev, int mask) if (r->flags & IORESOURCE_MEM) cmd |= PCI_COMMAND_MEMORY; } - if (dev->resource[PCI_ROM_RESOURCE].start) - cmd |= PCI_COMMAND_MEMORY; if (cmd != old_cmd) { - printk("PCI: Enabling device %s (%04x -> %04x)\n", pci_name(dev), old_cmd, cmd); + printk("PCI: Enabling device %s (%04x -> %04x)\n", + pci_name(dev), old_cmd, cmd); pci_write_config_word(dev, PCI_COMMAND, cmd); } return 0; diff --git a/arch/mips/sibyte/bcm1480/smp.c b/arch/mips/sibyte/bcm1480/smp.c index 183c460b9ca1..bd9eeb43ed0e 100644 --- a/arch/mips/sibyte/bcm1480/smp.c +++ b/arch/mips/sibyte/bcm1480/smp.c @@ -110,7 +110,6 @@ static void __cpuinit bcm1480_smp_finish(void) sb1480_clockevent_init(); local_irq_enable(); - bcm1480_smp_finish(); } /* diff --git a/arch/mn10300/configs/asb2303_defconfig b/arch/mn10300/configs/asb2303_defconfig index ca9876a111d3..3aa8906b3dea 100644 --- a/arch/mn10300/configs/asb2303_defconfig +++ b/arch/mn10300/configs/asb2303_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.24-rc2 -# Fri Nov 16 13:36:38 2007 +# Linux kernel version: 2.6.25-rc2 +# Tue Feb 19 18:52:24 2008 # CONFIG_MN10300=y CONFIG_AM33=y @@ -21,6 +21,7 @@ CONFIG_ARCH_HAS_ILOG2_U32=y # CONFIG_ARCH_SUPPORTS_AOUT is not set CONFIG_GENERIC_HARDIRQS=y # CONFIG_HOTPLUG_CPU is not set +CONFIG_HZ=1000 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" # @@ -38,15 +39,16 @@ CONFIG_SYSVIPC_SYSCTL=y CONFIG_BSD_PROCESS_ACCT=y # CONFIG_BSD_PROCESS_ACCT_V3 is not set # CONFIG_TASKSTATS is not set -# CONFIG_USER_NS is not set -# CONFIG_PID_NS is not set # CONFIG_AUDIT is not set # CONFIG_IKCONFIG is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_CGROUPS is not set -# CONFIG_FAIR_GROUP_SCHED is not set +# CONFIG_GROUP_SCHED is not set +# CONFIG_USER_SCHED is not set +# CONFIG_CGROUP_SCHED is not set # CONFIG_SYSFS_DEPRECATED is not set # CONFIG_RELAY is not set +# CONFIG_NAMESPACES is not set # CONFIG_BLK_DEV_INITRD is not set # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set CONFIG_SYSCTL=y @@ -57,22 +59,33 @@ CONFIG_SYSCTL_SYSCALL=y CONFIG_PRINTK=y CONFIG_BUG=y CONFIG_ELF_CORE=y +CONFIG_COMPAT_BRK=y CONFIG_BASE_FULL=y CONFIG_FUTEX=y CONFIG_ANON_INODES=y CONFIG_EPOLL=y CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y # CONFIG_VM_EVENT_COUNTERS is not set CONFIG_SLAB=y # CONFIG_SLUB is not set # CONFIG_SLOB is not set +CONFIG_PROFILING=y +# CONFIG_MARKERS is not set +CONFIG_OPROFILE=y +# CONFIG_HAVE_OPROFILE is not set +# CONFIG_HAVE_KPROBES is not set +# CONFIG_PROC_PAGE_MONITOR is not set +CONFIG_SLABINFO=y CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 # CONFIG_MODULES is not set # CONFIG_BLOCK is not set +CONFIG_CLASSIC_RCU=y +# CONFIG_PREEMPT_RCU is not set # # Matsushita MN10300 system setup @@ -206,6 +219,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic" # # CONFIG_NET_PKTGEN is not set # CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set # CONFIG_IRDA is not set # CONFIG_BT is not set # CONFIG_AF_RXRPC is not set @@ -311,6 +325,8 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=2 # CONFIG_PARPORT is not set CONFIG_MISC_DEVICES=y # CONFIG_EEPROM_93CX6 is not set +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_HAVE_IDE is not set # # SCSI device support @@ -345,7 +361,6 @@ CONFIG_SMC91X=y # 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 @@ -405,6 +420,7 @@ CONFIG_RTC=y # CONFIG_W1 is not set # CONFIG_POWER_SUPPLY is not set # CONFIG_HWMON is not set +# CONFIG_THERMAL is not set # CONFIG_WATCHDOG is not set # @@ -444,6 +460,7 @@ CONFIG_SSB_POSSIBLE=y # CONFIG_SOUND is not set # CONFIG_USB_SUPPORT is not set # CONFIG_MMC is not set +# CONFIG_MEMSTICK is not set # CONFIG_NEW_LEDS is not set # CONFIG_RTC_CLASS is not set @@ -455,10 +472,10 @@ CONFIG_SSB_POSSIBLE=y # # File systems # +CONFIG_DNOTIFY=y 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 @@ -554,5 +571,3 @@ CONFIG_HAS_DMA=y # # Profiling support # -CONFIG_PROFILING=y -CONFIG_OPROFILE=y diff --git a/arch/mn10300/kernel/gdb-io-ttysm.c b/arch/mn10300/kernel/gdb-io-ttysm.c index c5451592d403..e94c25e8ca05 100644 --- a/arch/mn10300/kernel/gdb-io-ttysm.c +++ b/arch/mn10300/kernel/gdb-io-ttysm.c @@ -196,6 +196,7 @@ int gdbstub_io_rx_char(unsigned char *_ch, int nonblock) try_again: /* pull chars out of the buffer */ ix = gdbstub_rx_outp; + barrier(); if (ix == gdbstub_rx_inp) { if (nonblock) return -EAGAIN; @@ -207,6 +208,7 @@ try_again: ch = gdbstub_rx_buffer[ix++]; st = gdbstub_rx_buffer[ix++]; + barrier(); gdbstub_rx_outp = ix & (PAGE_SIZE - 1); st &= SC01STR_RXF | SC01STR_RBF | SC01STR_FEF | SC01STR_PEF | diff --git a/arch/mn10300/kernel/time.c b/arch/mn10300/kernel/time.c index ff492e3b3457..babb7c2ac377 100644 --- a/arch/mn10300/kernel/time.c +++ b/arch/mn10300/kernel/time.c @@ -84,11 +84,13 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id) /* advance the kernel's time tracking system */ profile_tick(CPU_PROFILING); do_timer(1); - update_process_times(user_mode(get_irq_regs())); check_rtc_time(); } write_sequnlock(&xtime_lock); + + update_process_times(user_mode(get_irq_regs())); + return IRQ_HANDLED; } diff --git a/arch/mn10300/kernel/traps.c b/arch/mn10300/kernel/traps.c index 8b9dc6d9dcc6..fcb9a03d46a8 100644 --- a/arch/mn10300/kernel/traps.c +++ b/arch/mn10300/kernel/traps.c @@ -391,7 +391,7 @@ static asmlinkage void unsupported_syscall(struct pt_regs *regs, if (code == EXCEP_SYSCALL15 && !user_mode(regs)) { if (report_bug(regs->pc, regs) == BUG_TRAP_TYPE_BUG) { #ifdef CONFIG_GDBSTUB - __gdbstub_bug_trap(); + gdbstub_intercept(regs, code); #endif } } diff --git a/arch/parisc/hpux/sys_hpux.c b/arch/parisc/hpux/sys_hpux.c index 3e025df2dc86..0c5b9dabb475 100644 --- a/arch/parisc/hpux/sys_hpux.c +++ b/arch/parisc/hpux/sys_hpux.c @@ -219,10 +219,10 @@ asmlinkage long hpux_statfs(const char __user *path, error = user_path_walk(path, &nd); if (!error) { struct hpux_statfs tmp; - error = vfs_statfs_hpux(nd.dentry, &tmp); + error = vfs_statfs_hpux(nd.path.dentry, &tmp); if (!error && copy_to_user(buf, &tmp, sizeof(tmp))) error = -EFAULT; - path_release(&nd); + path_put(&nd.path); } return error; } diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 485513c9f1af..5b8d8382b762 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -442,10 +442,6 @@ config SECCOMP If unsure, say Y. Only embedded should say N here. -config WANT_DEVICE_TREE - bool - default n - endmenu config ISA_DMA_API diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile index 6845482f0093..1c6ce3536e4c 100644 --- a/arch/powerpc/Makefile +++ b/arch/powerpc/Makefile @@ -176,7 +176,7 @@ define archhelp @echo ' *_defconfig - Select default config from arch/$(ARCH)/configs' endef -install: vdso_install +install: $(Q)$(MAKE) $(build)=$(boot) install vdso_install: diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile index 49797a45416c..63d07ccbb9db 100644 --- a/arch/powerpc/boot/Makefile +++ b/arch/powerpc/boot/Makefile @@ -147,6 +147,8 @@ HOSTCFLAGS += -I$(src)/dtc-src/ -I$(src)/libfdt/ targets += dtc-src/dtc-parser.tab.c targets += dtc-src/dtc-lexer.lex.c +clean-files += dtc-src/dtc-parser.tab.h + ifdef DTC_GENPARSER BISON = bison FLEX = flex diff --git a/arch/powerpc/boot/ps3-hvcall.S b/arch/powerpc/boot/ps3-hvcall.S index 585965f7e6a8..d6068f1829ca 100644 --- a/arch/powerpc/boot/ps3-hvcall.S +++ b/arch/powerpc/boot/ps3-hvcall.S @@ -145,7 +145,7 @@ .macro STORE_REGS_5_2 lwz r11, 16(r1) std r4, 0(r11) - lwz r11, 24(r1) + lwz r11, 20(r1) std r5, 0(r11) .endm diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index 0662ae46f724..c1baf9d5903f 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile @@ -104,3 +104,5 @@ quiet_cmd_systbl_chk = CALL $< PHONY += systbl_chk systbl_chk: $(src)/systbl_chk.sh $(obj)/systbl_chk.i $(call cmd,systbl_chk) + +clean-files := vmlinux.lds diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index b9d88374f14f..4846bf543a8c 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -462,7 +462,7 @@ void show_regs(struct pt_regs * regs) current, task_pid_nr(current), current->comm, task_thread_info(current)); #ifdef CONFIG_SMP - printk(" CPU: %d", smp_processor_id()); + printk(" CPU: %d", raw_smp_processor_id()); #endif /* CONFIG_SMP */ for (i = 0; i < 32; i++) { diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c index 3702df7dc567..d3437c4c4a6f 100644 --- a/arch/powerpc/kernel/vdso.c +++ b/arch/powerpc/kernel/vdso.c @@ -336,9 +336,9 @@ static unsigned long __init find_function32(struct lib32_elfinfo *lib, return sym->st_value - VDSO32_LBASE; } -static int vdso_do_func_patch32(struct lib32_elfinfo *v32, - struct lib64_elfinfo *v64, - const char *orig, const char *fix) +static int __init vdso_do_func_patch32(struct lib32_elfinfo *v32, + struct lib64_elfinfo *v64, + const char *orig, const char *fix) { Elf32_Sym *sym32_gen, *sym32_fix; @@ -433,9 +433,9 @@ static unsigned long __init find_function64(struct lib64_elfinfo *lib, #endif } -static int vdso_do_func_patch64(struct lib32_elfinfo *v32, - struct lib64_elfinfo *v64, - const char *orig, const char *fix) +static int __init vdso_do_func_patch64(struct lib32_elfinfo *v32, + struct lib64_elfinfo *v64, + const char *orig, const char *fix) { Elf64_Sym *sym64_gen, *sym64_fix; diff --git a/arch/powerpc/oprofile/cell/spu_task_sync.c b/arch/powerpc/oprofile/cell/spu_task_sync.c index 4a890cb42b98..257b13cb18af 100644 --- a/arch/powerpc/oprofile/cell/spu_task_sync.c +++ b/arch/powerpc/oprofile/cell/spu_task_sync.c @@ -198,14 +198,13 @@ out: * dcookie user still being registered (namely, the reader * of the event buffer). */ -static inline unsigned long fast_get_dcookie(struct dentry *dentry, - struct vfsmount *vfsmnt) +static inline unsigned long fast_get_dcookie(struct path *path) { unsigned long cookie; - if (dentry->d_cookie) - return (unsigned long)dentry; - get_dcookie(dentry, vfsmnt, &cookie); + if (path->dentry->d_cookie) + return (unsigned long)path->dentry; + get_dcookie(path, &cookie); return cookie; } @@ -240,8 +239,7 @@ get_exec_dcookie_and_offset(struct spu *spu, unsigned int *offsetp, continue; if (!(vma->vm_flags & VM_EXECUTABLE)) continue; - app_cookie = fast_get_dcookie(vma->vm_file->f_dentry, - vma->vm_file->f_vfsmnt); + app_cookie = fast_get_dcookie(&vma->vm_file->f_path); pr_debug("got dcookie for %s\n", vma->vm_file->f_dentry->d_name.name); app = vma->vm_file; @@ -262,8 +260,7 @@ get_exec_dcookie_and_offset(struct spu *spu, unsigned int *offsetp, break; } - *spu_bin_dcookie = fast_get_dcookie(vma->vm_file->f_dentry, - vma->vm_file->f_vfsmnt); + *spu_bin_dcookie = fast_get_dcookie(&vma->vm_file->f_path); pr_debug("got dcookie for %s\n", vma->vm_file->f_dentry->d_name.name); up_read(&mm->mmap_sem); diff --git a/arch/powerpc/platforms/512x/Kconfig b/arch/powerpc/platforms/512x/Kconfig index c6fa49e23dc0..4c0da0c079e9 100644 --- a/arch/powerpc/platforms/512x/Kconfig +++ b/arch/powerpc/platforms/512x/Kconfig @@ -13,7 +13,6 @@ config MPC5121_ADS bool "Freescale MPC5121E ADS" depends on PPC_MULTIPLATFORM && PPC32 select DEFAULT_UIMAGE - select WANT_DEVICE_TREE select PPC_MPC5121 help This option enables support for the MPC5121E ADS board. diff --git a/arch/powerpc/platforms/52xx/Kconfig b/arch/powerpc/platforms/52xx/Kconfig index 515f244c90bb..cf945d55c276 100644 --- a/arch/powerpc/platforms/52xx/Kconfig +++ b/arch/powerpc/platforms/52xx/Kconfig @@ -8,7 +8,6 @@ config PPC_MPC5200_SIMPLE bool "Generic support for simple MPC5200 based boards" depends on PPC_MPC52xx select DEFAULT_UIMAGE - select WANT_DEVICE_TREE help This option enables support for a simple MPC52xx based boards which do not need a custom platform specific setup. Such boards are @@ -35,7 +34,6 @@ config PPC_LITE5200 bool "Freescale Lite5200 Eval Board" depends on PPC_MPC52xx select DEFAULT_UIMAGE - select WANT_DEVICE_TREE config PPC_MPC5200_BUGFIX bool "MPC5200 (L25R) bugfix support" diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig index fcedbec07f94..0afd22595546 100644 --- a/arch/powerpc/platforms/Kconfig +++ b/arch/powerpc/platforms/Kconfig @@ -15,7 +15,6 @@ config PPC_MULTIPLATFORM config PPC_82xx bool "Freescale 82xx" depends on 6xx - select WANT_DEVICE_TREE config PPC_83xx bool "Freescale 83xx" @@ -23,7 +22,6 @@ config PPC_83xx select FSL_SOC select MPC83xx select IPIC - select WANT_DEVICE_TREE select FSL_EMB_PERFMON config PPC_86xx diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype index 69941ba70975..73d81ce14b67 100644 --- a/arch/powerpc/platforms/Kconfig.cputype +++ b/arch/powerpc/platforms/Kconfig.cputype @@ -29,26 +29,22 @@ config PPC_85xx bool "Freescale 85xx" select E500 select FSL_SOC - select WANT_DEVICE_TREE select MPC85xx config PPC_8xx bool "Freescale 8xx" select FSL_SOC select 8xx - select WANT_DEVICE_TREE select PPC_LIB_RHEAP config 40x bool "AMCC 40x" select PPC_DCR_NATIVE - select WANT_DEVICE_TREE select PPC_UDBG_16550 config 44x bool "AMCC 44x" select PPC_DCR_NATIVE - select WANT_DEVICE_TREE select PPC_UDBG_16550 config E200 diff --git a/arch/powerpc/platforms/cell/ras.c b/arch/powerpc/platforms/cell/ras.c index b2494ebcdbe9..e43024c0392e 100644 --- a/arch/powerpc/platforms/cell/ras.c +++ b/arch/powerpc/platforms/cell/ras.c @@ -1,4 +1,13 @@ -#define DEBUG +/* + * Copyright 2006-2008, 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. + */ + +#undef DEBUG #include #include diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c index e6e6559c55ed..6d1228c66c5e 100644 --- a/arch/powerpc/platforms/cell/spufs/inode.c +++ b/arch/powerpc/platforms/cell/spufs/inode.c @@ -1,3 +1,4 @@ + /* * SPU file system * @@ -592,7 +593,7 @@ long spufs_create(struct nameidata *nd, unsigned int flags, mode_t mode, ret = -EINVAL; /* check if we are on spufs */ - if (nd->dentry->d_sb->s_type != &spufs_type) + if (nd->path.dentry->d_sb->s_type != &spufs_type) goto out; /* don't accept undefined flags */ @@ -600,9 +601,9 @@ long spufs_create(struct nameidata *nd, unsigned int flags, mode_t mode, goto out; /* only threads can be underneath a gang */ - if (nd->dentry != nd->dentry->d_sb->s_root) { + if (nd->path.dentry != nd->path.dentry->d_sb->s_root) { if ((flags & SPU_CREATE_GANG) || - !SPUFS_I(nd->dentry->d_inode)->i_gang) + !SPUFS_I(nd->path.dentry->d_inode)->i_gang) goto out; } @@ -618,16 +619,17 @@ long spufs_create(struct nameidata *nd, unsigned int flags, mode_t mode, mode &= ~current->fs->umask; if (flags & SPU_CREATE_GANG) - return spufs_create_gang(nd->dentry->d_inode, - dentry, nd->mnt, mode); + return spufs_create_gang(nd->path.dentry->d_inode, + dentry, nd->path.mnt, mode); else - return spufs_create_context(nd->dentry->d_inode, - dentry, nd->mnt, flags, mode, filp); + return spufs_create_context(nd->path.dentry->d_inode, + dentry, nd->path.mnt, flags, mode, + filp); out_dput: dput(dentry); out_dir: - mutex_unlock(&nd->dentry->d_inode->i_mutex); + mutex_unlock(&nd->path.dentry->d_inode->i_mutex); out: return ret; } diff --git a/arch/powerpc/platforms/cell/spufs/syscalls.c b/arch/powerpc/platforms/cell/spufs/syscalls.c index 430404413178..49c87769b1f8 100644 --- a/arch/powerpc/platforms/cell/spufs/syscalls.c +++ b/arch/powerpc/platforms/cell/spufs/syscalls.c @@ -73,7 +73,7 @@ static long do_spu_create(const char __user *pathname, unsigned int flags, LOOKUP_OPEN|LOOKUP_CREATE, &nd); if (!ret) { ret = spufs_create(&nd, flags, mode, neighbor); - path_release(&nd); + path_put(&nd.path); } putname(tmp); } diff --git a/arch/powerpc/platforms/embedded6xx/Kconfig b/arch/powerpc/platforms/embedded6xx/Kconfig index 6c8083757938..429088967813 100644 --- a/arch/powerpc/platforms/embedded6xx/Kconfig +++ b/arch/powerpc/platforms/embedded6xx/Kconfig @@ -24,7 +24,6 @@ config STORCENTER select MPIC select FSL_SOC select PPC_UDBG_16550 if SERIAL_8250 - select WANT_DEVICE_TREE select MPC10X_OPENPIC select MPC10X_BRIDGE help @@ -37,7 +36,6 @@ config MPC7448HPC2 select TSI108_BRIDGE select DEFAULT_UIMAGE select PPC_UDBG_16550 - select WANT_DEVICE_TREE select TSI108_BRIDGE help Select MPC7448HPC2 if configuring for Freescale MPC7448HPC2 (Taiga) @@ -48,7 +46,6 @@ config PPC_HOLLY depends on EMBEDDED6xx select TSI108_BRIDGE select PPC_UDBG_16550 - select WANT_DEVICE_TREE select TSI108_BRIDGE help Select PPC_HOLLY if configuring for an IBM 750GX/CL Eval @@ -59,7 +56,6 @@ config PPC_PRPMC2800 depends on EMBEDDED6xx select MV64X60 select NOT_COHERENT_CACHE - select WANT_DEVICE_TREE help This option enables support for the Motorola PrPMC2800 board diff --git a/arch/powerpc/platforms/iseries/vio.c b/arch/powerpc/platforms/iseries/vio.c index be06cfd9fa3d..657b72f68493 100644 --- a/arch/powerpc/platforms/iseries/vio.c +++ b/arch/powerpc/platforms/iseries/vio.c @@ -75,7 +75,7 @@ static struct property *new_property(const char *name, int length, return np; } -static void __init free_property(struct property *np) +static void free_property(struct property *np) { kfree(np); } diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 92a4f7b4323a..b21444b681b6 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -100,7 +100,8 @@ config NR_CPUS int "Maximum number of CPUs (2-64)" range 2 64 depends on SMP - default "32" + default "32" if !64BIT + default "64" if 64BIT help This allows you to specify the maximum number of CPUs which this kernel will support. The maximum supported value is 64 and the diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c index a6a4729e0e94..1c59ec161cf8 100644 --- a/arch/s390/kernel/process.c +++ b/arch/s390/kernel/process.c @@ -114,24 +114,27 @@ extern void s390_handle_mcck(void); static void default_idle(void) { int cpu, rc; + int nr_calls = 0; + void *hcpu; #ifdef CONFIG_SMP struct s390_idle_data *idle; #endif /* CPU is going idle. */ cpu = smp_processor_id(); - + hcpu = (void *)(long)cpu; local_irq_disable(); if (need_resched()) { local_irq_enable(); return; } - rc = atomic_notifier_call_chain(&idle_chain, - S390_CPU_IDLE, (void *)(long) cpu); - if (rc != NOTIFY_OK && rc != NOTIFY_DONE) - BUG(); - if (rc != NOTIFY_OK) { + rc = __atomic_notifier_call_chain(&idle_chain, S390_CPU_IDLE, hcpu, -1, + &nr_calls); + if (rc == NOTIFY_BAD) { + nr_calls--; + __atomic_notifier_call_chain(&idle_chain, S390_CPU_NOT_IDLE, + hcpu, nr_calls, NULL); local_irq_enable(); return; } diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 85060659fb12..818bd09c0260 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -626,13 +626,17 @@ static int __cpuinit smp_alloc_lowcore(int cpu) if (!lowcore) return -ENOMEM; async_stack = __get_free_pages(GFP_KERNEL, ASYNC_ORDER); - if (!async_stack) - goto out_async_stack; panic_stack = __get_free_page(GFP_KERNEL); - if (!panic_stack) - goto out_panic_stack; - - *lowcore = S390_lowcore; + if (!panic_stack || !async_stack) + goto out; + /* + * Only need to copy the first 512 bytes from address 0. But since + * the compiler emits a warning if src == NULL for memcpy use copy_page + * instead. Copies more than needed but this code is not performance + * critical. + */ + copy_page(lowcore, &S390_lowcore); + memset((void *)lowcore + 512, 0, sizeof(*lowcore) - 512); lowcore->async_stack = async_stack + ASYNC_SIZE; lowcore->panic_stack = panic_stack + PAGE_SIZE; @@ -653,9 +657,8 @@ static int __cpuinit smp_alloc_lowcore(int cpu) out_save_area: free_page(panic_stack); #endif -out_panic_stack: +out: free_pages(async_stack, ASYNC_ORDER); -out_async_stack: free_pages((unsigned long) lowcore, lc_order); return -ENOMEM; } @@ -719,8 +722,8 @@ int __cpuinit __cpu_up(unsigned int cpu) cpu_lowcore->percpu_offset = __per_cpu_offset[cpu]; cpu_lowcore->current_task = (unsigned long) idle; cpu_lowcore->cpu_data.cpu_nr = cpu; - cpu_lowcore->softirq_pending = 0; - cpu_lowcore->ext_call_fast = 0; + cpu_lowcore->kernel_asce = S390_lowcore.kernel_asce; + cpu_lowcore->ipl_device = S390_lowcore.ipl_device; eieio(); while (signal_processor(cpu, sigp_restart) == sigp_busy) @@ -797,23 +800,43 @@ void cpu_die(void) void __init smp_prepare_cpus(unsigned int max_cpus) { +#ifndef CONFIG_64BIT + unsigned long save_area = 0; +#endif + unsigned long async_stack, panic_stack; + struct _lowcore *lowcore; unsigned int cpu; + int lc_order; smp_detect_cpus(); /* request the 0x1201 emergency signal external interrupt */ if (register_external_interrupt(0x1201, do_ext_call_interrupt) != 0) panic("Couldn't request external interrupt 0x1201"); - memset(lowcore_ptr, 0, sizeof(lowcore_ptr)); print_cpu_info(&S390_lowcore.cpu_data); - smp_alloc_lowcore(smp_processor_id()); + /* Reallocate current lowcore, but keep its contents. */ + lc_order = sizeof(long) == 8 ? 1 : 0; + lowcore = (void *) __get_free_pages(GFP_KERNEL | GFP_DMA, lc_order); + panic_stack = __get_free_page(GFP_KERNEL); + async_stack = __get_free_pages(GFP_KERNEL, ASYNC_ORDER); #ifndef CONFIG_64BIT if (MACHINE_HAS_IEEE) - ctl_set_bit(14, 29); /* enable extended save area */ + save_area = get_zeroed_page(GFP_KERNEL); #endif - set_prefix((u32)(unsigned long) lowcore_ptr[smp_processor_id()]); - + local_irq_disable(); + local_mcck_disable(); + lowcore_ptr[smp_processor_id()] = lowcore; + *lowcore = S390_lowcore; + lowcore->panic_stack = panic_stack + PAGE_SIZE; + lowcore->async_stack = async_stack + ASYNC_SIZE; +#ifndef CONFIG_64BIT + if (MACHINE_HAS_IEEE) + lowcore->extended_save_area_addr = (u32) save_area; +#endif + set_prefix((u32)(unsigned long) lowcore); + local_mcck_enable(); + local_irq_enable(); for_each_possible_cpu(cpu) if (cpu != smp_processor_id()) smp_create_idle(cpu); diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index 3bbac1293be4..76a5dd1b4ce9 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c @@ -744,7 +744,6 @@ static void etr_adjust_time(unsigned long long clock, unsigned long long delay) } } -#ifdef CONFIG_SMP static void etr_sync_cpu_start(void *dummy) { int *in_sync = dummy; @@ -777,7 +776,6 @@ static void etr_sync_cpu_start(void *dummy) static void etr_sync_cpu_end(void *dummy) { } -#endif /* CONFIG_SMP */ /* * Sync the TOD clock using the port refered to by aibp. This port diff --git a/arch/s390/lib/uaccess_std.c b/arch/s390/lib/uaccess_std.c index 28c4500a58d0..d2ffbadb51a7 100644 --- a/arch/s390/lib/uaccess_std.c +++ b/arch/s390/lib/uaccess_std.c @@ -293,10 +293,10 @@ int futex_atomic_cmpxchg_std(int __user *uaddr, int oldval, int newval) asm volatile( " sacf 256\n" - " cs %1,%4,0(%5)\n" - "0: lr %0,%1\n" - "1: sacf 0\n" - EX_TABLE(0b,1b) + "0: cs %1,%4,0(%5)\n" + "1: lr %0,%1\n" + "2: sacf 0\n" + EX_TABLE(0b,2b) EX_TABLE(1b,2b) : "=d" (ret), "+d" (oldval), "=m" (*uaddr) : "0" (-EFAULT), "d" (newval), "a" (uaddr), "m" (*uaddr) : "cc", "memory" ); diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index d87d4bf88803..b3400b5ad5c6 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -93,6 +93,9 @@ config ARCH_NO_VIRT_TO_BUS config ARCH_SUPPORTS_AOUT def_bool y +config IO_TRAPPED + bool + source "init/Kconfig" menu "System type" @@ -312,6 +315,13 @@ config CPU_SUBTYPE_SH7722 select ARCH_SPARSEMEM_ENABLE select SYS_SUPPORTS_NUMA +config CPU_SUBTYPE_SH7366 + bool "Support SH7366 processor" + select CPU_SH4AL_DSP + select CPU_SHX2 + select ARCH_SPARSEMEM_ENABLE + select SYS_SUPPORTS_NUMA + # SH-5 Processor Support config CPU_SUBTYPE_SH5_101 @@ -456,6 +466,7 @@ config SH_RTS7751R2D bool "RTS7751R2D" depends on CPU_SUBTYPE_SH7751R select SYS_SUPPORTS_PCI + select IO_TRAPPED help Select RTS7751R2D if configuring for a Renesas Technology Sales SH-Graphics board. @@ -472,6 +483,14 @@ config SH_HIGHLANDER bool "Highlander" depends on CPU_SUBTYPE_SH7780 || CPU_SUBTYPE_SH7785 select SYS_SUPPORTS_PCI + select IO_TRAPPED + +config SH_MIGOR + bool "Migo-R" + depends on CPU_SUBTYPE_SH7722 + help + Select Migo-R if configuring for the SH7722 Migo-R platform + by Renesas System Solutions Asia Pte. Ltd. config SH_EDOSK7705 bool "EDOSK7705" diff --git a/arch/sh/Kconfig.cpu b/arch/sh/Kconfig.cpu index d850184d0694..0e27fe3b182b 100644 --- a/arch/sh/Kconfig.cpu +++ b/arch/sh/Kconfig.cpu @@ -12,6 +12,7 @@ config CPU_LITTLE_ENDIAN config CPU_BIG_ENDIAN bool "Big Endian" + depends on !CPU_SH5 endchoice @@ -87,9 +88,6 @@ config SH64_ID2815_WORKAROUND config CPU_HAS_INTEVT bool -config CPU_HAS_MASKREG_IRQ - bool - config CPU_HAS_IPR_IRQ bool diff --git a/arch/sh/Kconfig.debug b/arch/sh/Kconfig.debug index f7c716166ce8..5dcb74b947a9 100644 --- a/arch/sh/Kconfig.debug +++ b/arch/sh/Kconfig.debug @@ -29,7 +29,8 @@ config EARLY_SCIF_CONSOLE config EARLY_SCIF_CONSOLE_PORT hex depends on EARLY_SCIF_CONSOLE - default "0xffe00000" if CPU_SUBTYPE_SH7780 || CPU_SUBTYPE_SH7763 + default "0xffe00000" if CPU_SUBTYPE_SH7780 || CPU_SUBTYPE_SH7763 + default "0xffe00000" if CPU_SUBTYPE_SH7722 || CPU_SUBTYPE_SH7366 default "0xffea0000" if CPU_SUBTYPE_SH7785 default "0xfffe8000" if CPU_SUBTYPE_SH7203 default "0xfffe9800" if CPU_SUBTYPE_SH7206 || CPU_SUBTYPE_SH7263 diff --git a/arch/sh/Makefile b/arch/sh/Makefile index 17fc36186bf4..81381e5773c8 100644 --- a/arch/sh/Makefile +++ b/arch/sh/Makefile @@ -116,6 +116,7 @@ machdir-$(CONFIG_SH_RTS7751R2D) += renesas/rts7751r2d machdir-$(CONFIG_SH_7751_SYSTEMH) += renesas/systemh machdir-$(CONFIG_SH_EDOSK7705) += renesas/edosk7705 machdir-$(CONFIG_SH_HIGHLANDER) += renesas/r7780rp +machdir-$(CONFIG_SH_MIGOR) += renesas/migor machdir-$(CONFIG_SH_SDK7780) += renesas/sdk7780 machdir-$(CONFIG_SH_7710VOIPGW) += renesas/sh7710voipgw machdir-$(CONFIG_SH_X3PROTO) += renesas/x3proto diff --git a/arch/sh/boards/renesas/migor/Makefile b/arch/sh/boards/renesas/migor/Makefile new file mode 100644 index 000000000000..77037567633b --- /dev/null +++ b/arch/sh/boards/renesas/migor/Makefile @@ -0,0 +1 @@ +obj-y := setup.o diff --git a/arch/sh/boards/renesas/migor/setup.c b/arch/sh/boards/renesas/migor/setup.c new file mode 100644 index 000000000000..21ab8c8fb590 --- /dev/null +++ b/arch/sh/boards/renesas/migor/setup.c @@ -0,0 +1,61 @@ +/* + * Renesas System Solutions Asia Pte. Ltd - Migo-R + * + * Copyright (C) 2008 Magnus Damm + * + * 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 + +/* Address IRQ Size Bus Description + * 0x00000000 64MB 16 NOR Flash (SP29PL256N) + * 0x0c000000 64MB 64 SDRAM (2xK4M563233G) + * 0x10000000 IRQ0 16 Ethernet (SMC91C111) + * 0x14000000 IRQ4 16 USB 2.0 Host Controller (M66596) + * 0x18000000 8GB 8 NAND Flash (K9K8G08U0A) + */ + +static struct resource smc91x_eth_resources[] = { + [0] = { + .name = "smc91x-regs" , + .start = P2SEGADDR(0x10000300), + .end = P2SEGADDR(0x1000030f), + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = 32, /* IRQ0 */ + .flags = IORESOURCE_IRQ | IRQF_TRIGGER_HIGH, + }, +}; + +static struct platform_device smc91x_eth_device = { + .name = "smc91x", + .num_resources = ARRAY_SIZE(smc91x_eth_resources), + .resource = smc91x_eth_resources, +}; + +static struct platform_device *migor_devices[] __initdata = { + &smc91x_eth_device, +}; + +static int __init migor_devices_setup(void) +{ + return platform_add_devices(migor_devices, ARRAY_SIZE(migor_devices)); +} +__initcall(migor_devices_setup); + +static void __init migor_setup(char **cmdline_p) +{ + ctrl_outw(0x1000, 0xa4050110); /* Enable IRQ0 in PJCR */ +} + +static struct sh_machine_vector mv_migor __initmv = { + .mv_name = "Migo-R", + .mv_setup = migor_setup, +}; diff --git a/arch/sh/boards/renesas/r7780rp/setup.c b/arch/sh/boards/renesas/r7780rp/setup.c index f7a8d5c9d510..2f68bea7890c 100644 --- a/arch/sh/boards/renesas/r7780rp/setup.c +++ b/arch/sh/boards/renesas/r7780rp/setup.c @@ -23,6 +23,7 @@ #include #include #include +#include static struct resource r8a66597_usb_host_resources[] = { [0] = { @@ -181,13 +182,27 @@ static struct platform_device *r7780rp_devices[] __initdata = { &m66592_usb_peripheral_device, &heartbeat_device, #ifndef CONFIG_SH_R7780RP - &cf_ide_device, &ax88796_device, #endif }; +/* + * The CF is connected using a 16-bit bus where 8-bit operations are + * unsupported. The linux ata driver is however using 8-bit operations, so + * insert a trapped io filter to convert 8-bit operations into 16-bit. + */ +static struct trapped_io cf_trapped_io = { + .resource = cf_ide_resources, + .num_resources = 2, + .minimum_bus_width = 16, +}; + static int __init r7780rp_devices_setup(void) { +#ifndef CONFIG_SH_R7780RP + if (register_trapped_io(&cf_trapped_io) == 0) + platform_device_register(&cf_ide_device); +#endif return platform_add_devices(r7780rp_devices, ARRAY_SIZE(r7780rp_devices)); } @@ -226,34 +241,6 @@ static void r7780rp_power_off(void) ctrl_outw(0x0001, PA_POFF); } -static inline unsigned char is_ide_ioaddr(unsigned long addr) -{ - return ((cf_ide_resources[0].start <= addr && - addr <= cf_ide_resources[0].end) || - (cf_ide_resources[1].start <= addr && - addr <= cf_ide_resources[1].end)); -} - -void highlander_writeb(u8 b, void __iomem *addr) -{ - unsigned long tmp = (unsigned long __force)addr; - - if (is_ide_ioaddr(tmp)) - ctrl_outw((u16)b, tmp); - else - ctrl_outb(b, tmp); -} - -u8 highlander_readb(void __iomem *addr) -{ - unsigned long tmp = (unsigned long __force)addr; - - if (is_ide_ioaddr(tmp)) - return ctrl_inw(tmp) & 0xff; - else - return ctrl_inb(tmp); -} - /* * Initialize the board */ @@ -338,6 +325,4 @@ static struct sh_machine_vector mv_highlander __initmv = { .mv_setup = highlander_setup, .mv_init_irq = highlander_init_irq, .mv_irq_demux = highlander_irq_demux, - .mv_readb = highlander_readb, - .mv_writeb = highlander_writeb, }; diff --git a/arch/sh/boards/renesas/rts7751r2d/setup.c b/arch/sh/boards/renesas/rts7751r2d/setup.c index a0ef81b7de37..f21ee49ef3a5 100644 --- a/arch/sh/boards/renesas/rts7751r2d/setup.c +++ b/arch/sh/boards/renesas/rts7751r2d/setup.c @@ -21,6 +21,7 @@ #include #include #include +#include #include static struct resource cf_ide_resources[] = { @@ -214,13 +215,25 @@ static struct platform_device *rts7751r2d_devices[] __initdata = { &uart_device, &sm501_device, #endif - &cf_ide_device, &heartbeat_device, &spi_sh_sci_device, }; +/* + * The CF is connected with a 16-bit bus where 8-bit operations are + * unsupported. The linux ata driver is however using 8-bit operations, so + * insert a trapped io filter to convert 8-bit operations into 16-bit. + */ +static struct trapped_io cf_trapped_io = { + .resource = cf_ide_resources, + .num_resources = 2, + .minimum_bus_width = 16, +}; + static int __init rts7751r2d_devices_setup(void) { + if (register_trapped_io(&cf_trapped_io) == 0) + platform_device_register(&cf_ide_device); spi_register_board_info(spi_bus, ARRAY_SIZE(spi_bus)); return platform_add_devices(rts7751r2d_devices, ARRAY_SIZE(rts7751r2d_devices)); @@ -232,34 +245,6 @@ static void rts7751r2d_power_off(void) ctrl_outw(0x0001, PA_POWOFF); } -static inline unsigned char is_ide_ioaddr(unsigned long addr) -{ - return ((cf_ide_resources[0].start <= addr && - addr <= cf_ide_resources[0].end) || - (cf_ide_resources[1].start <= addr && - addr <= cf_ide_resources[1].end)); -} - -void rts7751r2d_writeb(u8 b, void __iomem *addr) -{ - unsigned long tmp = (unsigned long __force)addr; - - if (is_ide_ioaddr(tmp)) - ctrl_outw((u16)b, tmp); - else - ctrl_outb(b, tmp); -} - -u8 rts7751r2d_readb(void __iomem *addr) -{ - unsigned long tmp = (unsigned long __force)addr; - - if (is_ide_ioaddr(tmp)) - return ctrl_inw(tmp) & 0xff; - else - return ctrl_inb(tmp); -} - /* * Initialize the board */ @@ -310,6 +295,4 @@ static struct sh_machine_vector mv_rts7751r2d __initmv = { .mv_setup = rts7751r2d_setup, .mv_init_irq = init_rts7751r2d_IRQ, .mv_irq_demux = rts7751r2d_irq_demux, - .mv_writeb = rts7751r2d_writeb, - .mv_readb = rts7751r2d_readb, }; diff --git a/arch/sh/boards/renesas/sdk7780/Kconfig b/arch/sh/boards/renesas/sdk7780/Kconfig index e4f5b6985be1..065f1df09bf1 100644 --- a/arch/sh/boards/renesas/sdk7780/Kconfig +++ b/arch/sh/boards/renesas/sdk7780/Kconfig @@ -4,13 +4,6 @@ choice prompt "SDK7780 options" default SH_SDK7780_BASE -config SH_SDK7780_STANDALONE - bool "SDK7780 board support" - depends on CPU_SUBTYPE_SH7780 - help - Selecting this option will enable support for the - standalone version of the SDK7780. If in doubt, say Y. - config SH_SDK7780_BASE bool "SDK7780 with base-board support" depends on CPU_SUBTYPE_SH7780 diff --git a/arch/sh/cchips/hd6446x/hd64465/setup.c b/arch/sh/cchips/hd6446x/hd64465/setup.c index 5cef0db4018b..9b8820c36701 100644 --- a/arch/sh/cchips/hd6446x/hd64465/setup.c +++ b/arch/sh/cchips/hd6446x/hd64465/setup.c @@ -17,10 +17,8 @@ #include #include #include - #include #include - #include static void disable_hd64465_irq(unsigned int irq) @@ -28,51 +26,45 @@ static void disable_hd64465_irq(unsigned int irq) unsigned short nimr; unsigned short mask = 1 << (irq - HD64465_IRQ_BASE); - pr_debug("disable_hd64465_irq(%d): mask=%x\n", irq, mask); + pr_debug("disable_hd64465_irq(%d): mask=%x\n", irq, mask); nimr = inw(HD64465_REG_NIMR); nimr |= mask; outw(nimr, HD64465_REG_NIMR); } - static void enable_hd64465_irq(unsigned int irq) { unsigned short nimr; unsigned short mask = 1 << (irq - HD64465_IRQ_BASE); - pr_debug("enable_hd64465_irq(%d): mask=%x\n", irq, mask); + pr_debug("enable_hd64465_irq(%d): mask=%x\n", irq, mask); nimr = inw(HD64465_REG_NIMR); nimr &= ~mask; outw(nimr, HD64465_REG_NIMR); } - static void mask_and_ack_hd64465(unsigned int irq) { disable_hd64465_irq(irq); } - static void end_hd64465_irq(unsigned int irq) { if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) enable_hd64465_irq(irq); } - static unsigned int startup_hd64465_irq(unsigned int irq) -{ +{ enable_hd64465_irq(irq); return 0; } - static void shutdown_hd64465_irq(unsigned int irq) { disable_hd64465_irq(irq); } - static struct hw_interrupt_type hd64465_irq_type = { .typename = "HD64465-IRQ", .startup = startup_hd64465_irq, @@ -83,7 +75,6 @@ static struct hw_interrupt_type hd64465_irq_type = { .end = end_hd64465_irq, }; - static irqreturn_t hd64465_interrupt(int irq, void *dev_id) { printk(KERN_INFO @@ -93,9 +84,6 @@ static irqreturn_t hd64465_interrupt(int irq, void *dev_id) return IRQ_NONE; } - -/*====================================================*/ - /* * Support for a secondary IRQ demux step. This is necessary * because the HD64465 presents a very thin interface to the @@ -103,8 +91,7 @@ static irqreturn_t hd64465_interrupt(int irq, void *dev_id) * normally done in hardware by other PCMCIA host bridges is * instead done in software. */ -static struct -{ +static struct { int (*func)(int, void *); void *dev; } hd64465_demux[HD64465_IRQ_NUM]; @@ -112,19 +99,17 @@ static struct void hd64465_register_irq_demux(int irq, int (*demux)(int irq, void *dev), void *dev) { - hd64465_demux[irq - HD64465_IRQ_BASE].func = demux; - hd64465_demux[irq - HD64465_IRQ_BASE].dev = dev; + hd64465_demux[irq - HD64465_IRQ_BASE].func = demux; + hd64465_demux[irq - HD64465_IRQ_BASE].dev = dev; } EXPORT_SYMBOL(hd64465_register_irq_demux); void hd64465_unregister_irq_demux(int irq) { - hd64465_demux[irq - HD64465_IRQ_BASE].func = 0; + hd64465_demux[irq - HD64465_IRQ_BASE].func = 0; } EXPORT_SYMBOL(hd64465_unregister_irq_demux); - - int hd64465_irq_demux(int irq) { if (irq == CONFIG_HD64465_IRQ) { @@ -132,16 +117,16 @@ int hd64465_irq_demux(int irq) unsigned short nirr = inw(HD64465_REG_NIRR); unsigned short nimr = inw(HD64465_REG_NIMR); - pr_debug("hd64465_irq_demux, nirr=%04x, nimr=%04x\n", nirr, nimr); + pr_debug("hd64465_irq_demux, nirr=%04x, nimr=%04x\n", nirr, nimr); nirr &= ~nimr; for (bit = 1, i = 0 ; i < HD64465_IRQ_NUM ; bit <<= 1, i++) if (nirr & bit) - break; + break; - if (i < HD64465_IRQ_NUM) { + if (i < HD64465_IRQ_NUM) { irq = HD64465_IRQ_BASE + i; - if (hd64465_demux[i].func != 0) - irq = hd64465_demux[i].func(irq, hd64465_demux[i].dev); + if (hd64465_demux[i].func != 0) + irq = hd64465_demux[i].func(irq, hd64465_demux[i].dev); } } return irq; @@ -154,7 +139,6 @@ static struct irqaction irq0 = { .name = "HD64465", }; - static int __init setup_hd64465(void) { int i; @@ -176,8 +160,8 @@ static int __init setup_hd64465(void) rev = inw(HD64465_REG_SRR); printk(KERN_INFO "HD64465 hardware revision %d.%d\n", (rev >> 8) & 0xff, rev & 0xff); - - outw(0xffff, HD64465_REG_NIMR); /* mask all interrupts */ + + outw(0xffff, HD64465_REG_NIMR); /* mask all interrupts */ for (i = 0; i < HD64465_IRQ_NUM ; i++) { irq_desc[HD64465_IRQ_BASE + i].chip = &hd64465_irq_type; @@ -185,16 +169,13 @@ static int __init setup_hd64465(void) setup_irq(CONFIG_HD64465_IRQ, &irq0); -#ifdef CONFIG_SERIAL /* wake up the UART from STANDBY at this point */ smscr = inw(HD64465_REG_SMSCR); outw(smscr & (~HD64465_SMSCR_UARTST), HD64465_REG_SMSCR); /* remap IO ports for first ISA serial port to HD64465 UART */ hd64465_port_map(0x3f8, 8, CONFIG_HD64465_IOBASE + 0x8000, 1); -#endif return 0; } - module_init(setup_hd64465); diff --git a/arch/sh/configs/migor_defconfig b/arch/sh/configs/migor_defconfig new file mode 100644 index 000000000000..ee5900817f8f --- /dev/null +++ b/arch/sh/configs/migor_defconfig @@ -0,0 +1,824 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.24 +# Wed Feb 6 21:52:20 2008 +# +CONFIG_SUPERH=y +CONFIG_SUPERH32=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_BUG=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=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_SYS_SUPPORTS_NUMA=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +# CONFIG_ARCH_HAS_ILOG2_U32 is not set +# CONFIG_ARCH_HAS_ILOG2_U64 is not set +CONFIG_ARCH_NO_VIRT_TO_BUS=y +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_TASKSTATS is not set +# CONFIG_USER_NS is not set +# CONFIG_PID_NS is not set +# CONFIG_AUDIT is not set +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_CGROUPS is not set +CONFIG_FAIR_GROUP_SCHED=y +CONFIG_FAIR_USER_SCHED=y +# CONFIG_FAIR_CGROUP_SCHED is not set +CONFIG_SYSFS_DEPRECATED=y +# CONFIG_RELAY is not set +CONFIG_BLK_DEV_INITRD=y +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=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_ANON_INODES=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set +CONFIG_PROFILING=y +# CONFIG_MARKERS is not set +CONFIG_OPROFILE=y +CONFIG_HAVE_OPROFILE=y +# CONFIG_HAVE_KPROBES is not set +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_UNLOAD is not set +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +# CONFIG_KMOD is not set +CONFIG_BLOCK=y +# CONFIG_LBD is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_LSF is not set +# CONFIG_BLK_DEV_BSG is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +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" +CONFIG_CLASSIC_RCU=y +# CONFIG_PREEMPT_RCU is not set + +# +# System type +# +CONFIG_CPU_SH4=y +CONFIG_CPU_SH4A=y +CONFIG_CPU_SH4AL_DSP=y +CONFIG_CPU_SHX2=y +# CONFIG_CPU_SUBTYPE_SH7619 is not set +# CONFIG_CPU_SUBTYPE_SH7203 is not set +# CONFIG_CPU_SUBTYPE_SH7206 is not set +# CONFIG_CPU_SUBTYPE_SH7263 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 +# CONFIG_CPU_SUBTYPE_SH7712 is not set +# CONFIG_CPU_SUBTYPE_SH7720 is not set +# CONFIG_CPU_SUBTYPE_SH7721 is not set +# 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 +# CONFIG_CPU_SUBTYPE_SH7763 is not set +# CONFIG_CPU_SUBTYPE_SH7770 is not set +# CONFIG_CPU_SUBTYPE_SH7780 is not set +# CONFIG_CPU_SUBTYPE_SH7785 is not set +# CONFIG_CPU_SUBTYPE_SHX3 is not set +# CONFIG_CPU_SUBTYPE_SH7343 is not set +CONFIG_CPU_SUBTYPE_SH7722=y +# CONFIG_CPU_SUBTYPE_SH5_101 is not set +# CONFIG_CPU_SUBTYPE_SH5_103 is not set + +# +# Memory management options +# +CONFIG_QUICKLIST=y +CONFIG_MMU=y +CONFIG_PAGE_OFFSET=0x80000000 +CONFIG_MEMORY_START=0x0c000000 +CONFIG_MEMORY_SIZE=0x04000000 +CONFIG_29BIT=y +# CONFIG_X2TLB is not set +CONFIG_VSYSCALL=y +CONFIG_NUMA=y +CONFIG_NODES_SHIFT=1 +CONFIG_ARCH_SPARSEMEM_ENABLE=y +CONFIG_ARCH_SPARSEMEM_DEFAULT=y +CONFIG_MAX_ACTIVE_REGIONS=2 +CONFIG_ARCH_POPULATES_NODE_MAP=y +CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_8KB is not set +# CONFIG_PAGE_SIZE_64KB is not set +CONFIG_SELECT_MEMORY_MODEL=y +# CONFIG_FLATMEM_MANUAL is not set +# CONFIG_DISCONTIGMEM_MANUAL is not set +CONFIG_SPARSEMEM_MANUAL=y +CONFIG_SPARSEMEM=y +CONFIG_NEED_MULTIPLE_NODES=y +CONFIG_HAVE_MEMORY_PRESENT=y +CONFIG_SPARSEMEM_STATIC=y +# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set +# CONFIG_MEMORY_HOTPLUG is not set +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_MIGRATION is not set +# CONFIG_RESOURCES_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_NR_QUICK=2 + +# +# Cache configuration +# +# CONFIG_SH_DIRECT_MAPPED is not set +CONFIG_CACHE_WRITEBACK=y +# CONFIG_CACHE_WRITETHROUGH is not set +# CONFIG_CACHE_OFF is not set + +# +# Processor features +# +CONFIG_CPU_LITTLE_ENDIAN=y +# CONFIG_CPU_BIG_ENDIAN is not set +# CONFIG_SH_FPU_EMU is not set +CONFIG_SH_DSP=y +# CONFIG_SH_STORE_QUEUES is not set +CONFIG_CPU_HAS_INTEVT=y +CONFIG_CPU_HAS_SR_RB=y +CONFIG_CPU_HAS_PTEA=y +CONFIG_CPU_HAS_DSP=y + +# +# Board support +# +# CONFIG_SH_7722_SOLUTION_ENGINE is not set +CONFIG_SH_MIGOR=y + +# +# Timer and clock configuration +# +CONFIG_SH_TMU=y +CONFIG_SH_TIMER_IRQ=16 +CONFIG_SH_PCLK_FREQ=33333333 +# CONFIG_TICK_ONESHOT is not set +# CONFIG_NO_HZ is not set +# CONFIG_HIGH_RES_TIMERS is not set +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y + +# +# CPU Frequency scaling +# +# CONFIG_CPU_FREQ is not set + +# +# DMA support +# +# CONFIG_SH_DMA is not set + +# +# Companion Chips +# + +# +# Additional SuperH Device Drivers +# +# CONFIG_HEARTBEAT is not set +# CONFIG_PUSH_SWITCH is not set + +# +# Kernel features +# +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +# CONFIG_HZ_300 is not set +# CONFIG_HZ_1000 is not set +CONFIG_HZ=250 +# CONFIG_SCHED_HRTICK is not set +# CONFIG_KEXEC is not set +# CONFIG_CRASH_DUMP is not set +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PREEMPT is not set +CONFIG_RCU_TRACE=y +CONFIG_GUSA=y + +# +# Boot options +# +CONFIG_ZERO_PAGE_OFFSET=0x00001000 +CONFIG_BOOT_LINK_OFFSET=0x00800000 +CONFIG_CMDLINE_BOOL=y +CONFIG_CMDLINE="console=ttySC0,115200 earlyprintk=serial ip=on" + +# +# Bus options +# +# CONFIG_ARCH_SUPPORTS_MSI is not set +# CONFIG_PCCARD is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +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_XFRM_MIGRATE is not set +# CONFIG_XFRM_STATISTICS 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=y +# CONFIG_IP_PNP_BOOTP is not set +# 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_LRO is not set +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_TCP_MD5SIG is not set +# 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 +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# 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 +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set + +# +# Wireless +# +# CONFIG_CFG80211 is not set +CONFIG_WIRELESS_EXT=y +# CONFIG_MAC80211 is not set +# CONFIG_IEEE80211 is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=m +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_CONNECTOR is not set +# CONFIG_MTD is not set +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# 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_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +CONFIG_MISC_DEVICES=y +# CONFIG_EEPROM_93CX6 is not set +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=y +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_TGT is not set +# 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 is not set +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set +# CONFIG_SCSI_SCAN_ASYNC is not set +CONFIG_SCSI_WAIT_SCAN=m + +# +# 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_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set +CONFIG_SCSI_LOWLEVEL=y +# CONFIG_ISCSI_TCP is not set +# CONFIG_SCSI_DEBUG is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set +CONFIG_NETDEVICES=y +# CONFIG_NETDEVICES_MULTIQUEUE is not set +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_MACVLAN is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_VETH is not set +# CONFIG_PHYLIB is not set +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_AX88796 is not set +# CONFIG_STNIC is not set +CONFIG_SMC91X=y +# CONFIG_IBM_NEW_EMAC_ZMII is not set +# CONFIG_IBM_NEW_EMAC_RGMII is not set +# CONFIG_IBM_NEW_EMAC_TAH is not set +# CONFIG_IBM_NEW_EMAC_EMAC4 is not set +# CONFIG_B44 is not set +# CONFIG_NETDEV_1000 is not set +# CONFIG_NETDEV_10000 is not set + +# +# Wireless LAN +# +# CONFIG_WLAN_PRE80211 is not set +# CONFIG_WLAN_80211 is not set +# CONFIG_WAN is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_ISDN is not set +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV 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_TABLET 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=y +# 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=3 +CONFIG_SERIAL_SH_SCI_CONSOLE=y +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 +# CONFIG_IPMI_HANDLER is not set +CONFIG_HW_RANDOM=y +# CONFIG_R3964 is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +# CONFIG_I2C is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +# CONFIG_HWMON is not set +# CONFIG_WATCHDOG is not set + +# +# Sonics Silicon Backplane +# +CONFIG_SSB_POSSIBLE=y +# CONFIG_SSB is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_SM501 is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set +# CONFIG_DVB_CORE is not set +# CONFIG_DAB is not set + +# +# Graphics support +# +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +# CONFIG_FB is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set + +# +# Console display driver support +# +CONFIG_DUMMY_CONSOLE=y + +# +# Sound +# +# CONFIG_SOUND is not set +CONFIG_HID_SUPPORT=y +CONFIG_HID=y +# CONFIG_HID_DEBUG is not set +# CONFIG_HIDRAW is not set +CONFIG_USB_SUPPORT=y +CONFIG_USB_ARCH_HAS_HCD=y +# CONFIG_USB_ARCH_HAS_OHCI is not set +# CONFIG_USB_ARCH_HAS_EHCI is not set +# CONFIG_USB is not set + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# +CONFIG_USB_GADGET=y +# CONFIG_USB_GADGET_DEBUG_FILES is not set +# CONFIG_USB_GADGET_DEBUG_FS is not set +CONFIG_USB_GADGET_SELECTED=y +# CONFIG_USB_GADGET_AMD5536UDC is not set +# CONFIG_USB_GADGET_ATMEL_USBA is not set +# CONFIG_USB_GADGET_FSL_USB2 is not set +# CONFIG_USB_GADGET_NET2280 is not set +# CONFIG_USB_GADGET_PXA2XX is not set +CONFIG_USB_GADGET_M66592=y +CONFIG_USB_M66592=y +CONFIG_SUPERH_BUILT_IN_M66592=y +# CONFIG_USB_GADGET_GOKU is not set +# CONFIG_USB_GADGET_LH7A40X is not set +# CONFIG_USB_GADGET_OMAP is not set +# CONFIG_USB_GADGET_S3C2410 is not set +# CONFIG_USB_GADGET_AT91 is not set +# CONFIG_USB_GADGET_DUMMY_HCD is not set +CONFIG_USB_GADGET_DUALSPEED=y +# CONFIG_USB_ZERO is not set +# CONFIG_USB_ETH is not set +# CONFIG_USB_GADGETFS is not set +# CONFIG_USB_FILE_STORAGE is not set +CONFIG_USB_G_SERIAL=y +# CONFIG_USB_MIDI_GADGET is not set +# CONFIG_USB_G_PRINTER is not set +# CONFIG_MMC is not set +# CONFIG_NEW_LEDS is not set +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set + +# +# SPI RTC drivers +# + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_V3020 is not set + +# +# on-CPU RTC drivers +# +CONFIG_RTC_DRV_SH=y + +# +# Userspace I/O +# +# CONFIG_UIO is not set + +# +# File systems +# +# CONFIG_EXT2_FS 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 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_KCORE=y +CONFIG_PROC_SYSCTL=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_HUGETLBFS is not set +# CONFIG_HUGETLB_PAGE is not set +# 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 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 +# CONFIG_NETWORK_FILESYSTEMS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_NLS is not set +# CONFIG_DLM is not set + +# +# Kernel hacking +# +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +# CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_FS=y +# CONFIG_HEADERS_CHECK is not set +# CONFIG_DEBUG_KERNEL is not set +# CONFIG_DEBUG_BUGVERBOSE is not set +# CONFIG_SAMPLES is not set +# CONFIG_SH_STANDARD_BIOS is not set +CONFIG_EARLY_SCIF_CONSOLE=y +CONFIG_EARLY_SCIF_CONSOLE_PORT=0xffe00000 +CONFIG_EARLY_PRINTK=y +# CONFIG_SH_KGDB is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITY_FILE_CAPABILITIES is not set +CONFIG_CRYPTO=y +# CONFIG_CRYPTO_SEQIV is not set +# CONFIG_CRYPTO_MANAGER is not set +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_XCBC is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_WP512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_ECB is not set +# CONFIG_CRYPTO_CBC is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_XTS is not set +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_CRYPTD is not set +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_TWOFISH is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_TEST is not set +# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_LZO is not set +CONFIG_CRYPTO_HW=y + +# +# Library routines +# +CONFIG_BITREVERSE=y +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +# CONFIG_CRC_ITU_T is not set +CONFIG_CRC32=y +# CONFIG_CRC7 is not set +# CONFIG_LIBCRC32C is not set +CONFIG_PLIST=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y diff --git a/arch/sh/configs/rts7751r2d1_defconfig b/arch/sh/configs/rts7751r2d1_defconfig index 2dc754e5b733..3a915fd436d9 100644 --- a/arch/sh/configs/rts7751r2d1_defconfig +++ b/arch/sh/configs/rts7751r2d1_defconfig @@ -1,9 +1,10 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.23-rc2 -# Tue Aug 14 18:04:44 2007 +# Linux kernel version: 2.6.24 +# Thu Feb 7 16:25:55 2008 # CONFIG_SUPERH=y +CONFIG_SUPERH32=y CONFIG_RWSEM_GENERIC_SPINLOCK=y CONFIG_GENERIC_BUG=y CONFIG_GENERIC_FIND_NEXT_BIT=y @@ -36,9 +37,14 @@ CONFIG_SYSVIPC_SYSCTL=y # CONFIG_BSD_PROCESS_ACCT is not set # CONFIG_TASKSTATS is not set # CONFIG_USER_NS is not set +# CONFIG_PID_NS is not set # CONFIG_AUDIT is not set # CONFIG_IKCONFIG is not set CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_CGROUPS is not set +CONFIG_FAIR_GROUP_SCHED=y +CONFIG_FAIR_USER_SCHED=y +# CONFIG_FAIR_CGROUP_SCHED is not set CONFIG_SYSFS_DEPRECATED=y # CONFIG_RELAY is not set # CONFIG_BLK_DEV_INITRD is not set @@ -53,6 +59,7 @@ CONFIG_HOTPLUG=y CONFIG_PRINTK=y CONFIG_BUG=y CONFIG_ELF_CORE=y +CONFIG_COMPAT_BRK=y CONFIG_BASE_FULL=y CONFIG_FUTEX=y CONFIG_ANON_INODES=y @@ -65,6 +72,13 @@ CONFIG_VM_EVENT_COUNTERS=y CONFIG_SLAB=y # CONFIG_SLUB is not set # CONFIG_SLOB is not set +CONFIG_PROFILING=y +# CONFIG_MARKERS is not set +CONFIG_OPROFILE=y +CONFIG_HAVE_OPROFILE=y +# CONFIG_HAVE_KPROBES is not set +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_SLABINFO=y CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 @@ -91,13 +105,17 @@ CONFIG_DEFAULT_AS=y # CONFIG_DEFAULT_CFQ is not set # CONFIG_DEFAULT_NOOP is not set CONFIG_DEFAULT_IOSCHED="anticipatory" +CONFIG_CLASSIC_RCU=y +# CONFIG_PREEMPT_RCU is not set # # System type # CONFIG_CPU_SH4=y # CONFIG_CPU_SUBTYPE_SH7619 is not set +# CONFIG_CPU_SUBTYPE_SH7203 is not set # CONFIG_CPU_SUBTYPE_SH7206 is not set +# CONFIG_CPU_SUBTYPE_SH7263 is not set # CONFIG_CPU_SUBTYPE_SH7705 is not set # CONFIG_CPU_SUBTYPE_SH7706 is not set # CONFIG_CPU_SUBTYPE_SH7707 is not set @@ -105,6 +123,8 @@ CONFIG_CPU_SH4=y # CONFIG_CPU_SUBTYPE_SH7709 is not set # CONFIG_CPU_SUBTYPE_SH7710 is not set # CONFIG_CPU_SUBTYPE_SH7712 is not set +# CONFIG_CPU_SUBTYPE_SH7720 is not set +# CONFIG_CPU_SUBTYPE_SH7721 is not set # CONFIG_CPU_SUBTYPE_SH7750 is not set # CONFIG_CPU_SUBTYPE_SH7091 is not set # CONFIG_CPU_SUBTYPE_SH7750R is not set @@ -113,14 +133,15 @@ CONFIG_CPU_SH4=y CONFIG_CPU_SUBTYPE_SH7751R=y # CONFIG_CPU_SUBTYPE_SH7760 is not set # CONFIG_CPU_SUBTYPE_SH4_202 is not set -# CONFIG_CPU_SUBTYPE_ST40STB1 is not set -# CONFIG_CPU_SUBTYPE_ST40GX1 is not set +# CONFIG_CPU_SUBTYPE_SH7763 is not set # CONFIG_CPU_SUBTYPE_SH7770 is not set # CONFIG_CPU_SUBTYPE_SH7780 is not set # CONFIG_CPU_SUBTYPE_SH7785 is not set # CONFIG_CPU_SUBTYPE_SHX3 is not set # CONFIG_CPU_SUBTYPE_SH7343 is not set # CONFIG_CPU_SUBTYPE_SH7722 is not set +# CONFIG_CPU_SUBTYPE_SH5_101 is not set +# CONFIG_CPU_SUBTYPE_SH5_103 is not set # # Memory management options @@ -130,6 +151,7 @@ CONFIG_MMU=y CONFIG_PAGE_OFFSET=0x80000000 CONFIG_MEMORY_START=0x0c000000 CONFIG_MEMORY_SIZE=0x04000000 +CONFIG_29BIT=y CONFIG_VSYSCALL=y CONFIG_ARCH_FLATMEM_ENABLE=y CONFIG_ARCH_SPARSEMEM_ENABLE=y @@ -147,6 +169,7 @@ CONFIG_FLATMEM_MANUAL=y CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y CONFIG_SPARSEMEM_STATIC=y +# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_RESOURCES_64BIT is not set CONFIG_ZONE_DMA_FLAG=0 @@ -168,23 +191,22 @@ CONFIG_CPU_LITTLE_ENDIAN=y CONFIG_SH_FPU=y # CONFIG_SH_STORE_QUEUES is not set CONFIG_CPU_HAS_INTEVT=y -CONFIG_CPU_HAS_INTC_IRQ=y CONFIG_CPU_HAS_SR_RB=y CONFIG_CPU_HAS_PTEA=y +CONFIG_CPU_HAS_FPU=y # # Board support # # CONFIG_SH_7751_SYSTEMH is not set # CONFIG_SH_SECUREEDGE5410 is not set -# CONFIG_SH_HS7751RVOIP is not set CONFIG_SH_RTS7751R2D=y # CONFIG_SH_LANDISK is not set # CONFIG_SH_TITAN is not set # CONFIG_SH_LBOX_RE2 is not set # -# RTS7751R2D options +# RTS7751R2D Board Revision # # CONFIG_RTS7751R2D_PLUS is not set CONFIG_RTS7751R2D_1=y @@ -198,6 +220,7 @@ CONFIG_SH_PCLK_FREQ=60000000 # CONFIG_TICK_ONESHOT is not set # CONFIG_NO_HZ is not set # CONFIG_HIGH_RES_TIMERS is not set +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y # # CPU Frequency scaling @@ -227,11 +250,15 @@ CONFIG_HZ_250=y # CONFIG_HZ_300 is not set # CONFIG_HZ_1000 is not set CONFIG_HZ=250 +# CONFIG_SCHED_HRTICK is not set # CONFIG_KEXEC is not set # CONFIG_CRASH_DUMP is not set CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT_VOLUNTARY is not set # CONFIG_PREEMPT is not set +CONFIG_RCU_TRACE=y +CONFIG_GUSA=y +# CONFIG_GUSA_RB is not set # # Boot options @@ -250,10 +277,7 @@ CONFIG_SH_PCIDMA_NONCOHERENT=y CONFIG_PCI_AUTO=y CONFIG_PCI_AUTO_UPDATE_RESOURCES=y # CONFIG_ARCH_SUPPORTS_MSI is not set - -# -# PCCARD (PCMCIA/CardBus) support -# +CONFIG_PCI_LEGACY=y # CONFIG_PCCARD is not set CONFIG_HOTPLUG_PCI=y # CONFIG_HOTPLUG_PCI_FAKE is not set @@ -281,6 +305,7 @@ CONFIG_XFRM=y # CONFIG_XFRM_USER is not set # CONFIG_XFRM_SUB_POLICY is not set # CONFIG_XFRM_MIGRATE is not set +# CONFIG_XFRM_STATISTICS is not set # CONFIG_NET_KEY is not set CONFIG_INET=y # CONFIG_IP_MULTICAST is not set @@ -299,6 +324,7 @@ CONFIG_IP_FIB_HASH=y CONFIG_INET_XFRM_MODE_TRANSPORT=y CONFIG_INET_XFRM_MODE_TUNNEL=y CONFIG_INET_XFRM_MODE_BEET=y +# CONFIG_INET_LRO is not set CONFIG_INET_DIAG=y CONFIG_INET_TCP_DIAG=y # CONFIG_TCP_CONG_ADVANCED is not set @@ -324,10 +350,6 @@ CONFIG_DEFAULT_TCP_CONG="cubic" # 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 # @@ -335,6 +357,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic" # # CONFIG_NET_PKTGEN is not set # CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set # CONFIG_IRDA is not set # CONFIG_BT is not set # CONFIG_AF_RXRPC is not set @@ -356,6 +379,7 @@ CONFIG_WIRELESS_EXT=y # # Generic Driver Options # +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y CONFIG_FW_LOADER=m @@ -371,6 +395,7 @@ CONFIG_BLK_DEV=y # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_SX8 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=4096 @@ -420,6 +445,7 @@ CONFIG_SCSI_WAIT_SCAN=m # CONFIG_SCSI_FC_ATTRS is not set # CONFIG_SCSI_ISCSI_ATTRS is not set # CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set CONFIG_SCSI_LOWLEVEL=y # CONFIG_ISCSI_TCP is not set # CONFIG_BLK_DEV_3W_XXXX_RAID is not set @@ -493,7 +519,9 @@ CONFIG_ATA=y # CONFIG_PATA_MPIIX is not set # CONFIG_PATA_OLDPIIX is not set # CONFIG_PATA_NETCELL is not set +# CONFIG_PATA_NINJA32 is not set # CONFIG_PATA_NS87410 is not set +# CONFIG_PATA_NS87415 is not set # CONFIG_PATA_OPTI is not set # CONFIG_PATA_OPTIDMA is not set # CONFIG_PATA_PDC_OLD is not set @@ -508,14 +536,7 @@ CONFIG_ATA=y # CONFIG_PATA_WINBOND is not set CONFIG_PATA_PLATFORM=y # CONFIG_MD 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 @@ -530,25 +551,31 @@ CONFIG_NETDEVICES=y # CONFIG_MACVLAN is not set # CONFIG_EQUALIZER is not set # CONFIG_TUN is not set +# CONFIG_VETH is not set # CONFIG_ARCNET is not set # CONFIG_PHYLIB is not set CONFIG_NET_ETHERNET=y CONFIG_MII=y +# CONFIG_AX88796 is not set # CONFIG_STNIC is not set # CONFIG_HAPPYMEAL is not set # CONFIG_SUNGEM is not set # CONFIG_CASSINI is not set # CONFIG_NET_VENDOR_3COM is not set # CONFIG_SMC91X is not set +# CONFIG_ENC28J60 is not set # CONFIG_NET_TULIP is not set # CONFIG_HP100 is not set +# CONFIG_IBM_NEW_EMAC_ZMII is not set +# CONFIG_IBM_NEW_EMAC_RGMII is not set +# CONFIG_IBM_NEW_EMAC_TAH is not set +# CONFIG_IBM_NEW_EMAC_EMAC4 is not set CONFIG_NET_PCI=y # CONFIG_PCNET32 is not set # CONFIG_AMD8111_ETH is not set # CONFIG_ADAPTEC_STARFIRE is not set # CONFIG_B44 is not set # CONFIG_FORCEDETH is not set -# CONFIG_DGRS is not set # CONFIG_EEPRO100 is not set # CONFIG_E100 is not set # CONFIG_FEALNX is not set @@ -560,6 +587,7 @@ CONFIG_8139TOO=y # CONFIG_8139TOO_TUNE_TWISTER is not set # CONFIG_8139TOO_8129 is not set # CONFIG_8139_OLD_RX_RESET is not set +# CONFIG_R6040 is not set # CONFIG_SIS900 is not set # CONFIG_EPIC100 is not set # CONFIG_SUNDANCE is not set @@ -570,6 +598,10 @@ CONFIG_NETDEV_1000=y # CONFIG_ACENIC is not set # CONFIG_DL2K is not set # CONFIG_E1000 is not set +# CONFIG_E1000E is not set +# CONFIG_E1000E_ENABLED is not set +# CONFIG_IP1000 is not set +# CONFIG_IGB is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set @@ -577,6 +609,7 @@ CONFIG_NETDEV_1000=y # CONFIG_SIS190 is not set # CONFIG_SKGE is not set # CONFIG_SKY2 is not set +# CONFIG_SK98LIN is not set # CONFIG_VIA_VELOCITY is not set # CONFIG_TIGON3 is not set # CONFIG_BNX2 is not set @@ -585,11 +618,15 @@ CONFIG_NETDEV_1000=y CONFIG_NETDEV_10000=y # CONFIG_CHELSIO_T1 is not set # CONFIG_CHELSIO_T3 is not set +# CONFIG_IXGBE is not set # CONFIG_IXGB is not set # CONFIG_S2IO is not set # CONFIG_MYRI10GE is not set # CONFIG_NETXEN_NIC is not set +# CONFIG_NIU is not set # CONFIG_MLX4_CORE is not set +# CONFIG_TEHUTI is not set +# CONFIG_BNX2X is not set # CONFIG_TR is not set # @@ -597,13 +634,21 @@ CONFIG_NETDEV_10000=y # # CONFIG_WLAN_PRE80211 is not set # CONFIG_WLAN_80211 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 is not set # 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 @@ -622,7 +667,6 @@ CONFIG_INPUT=y # # CONFIG_INPUT_MOUSEDEV is not set # CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_TSDEV is not set # CONFIG_INPUT_EVDEV is not set # CONFIG_INPUT_EVBUG is not set @@ -650,6 +694,7 @@ CONFIG_VT_CONSOLE=y CONFIG_HW_CONSOLE=y CONFIG_VT_HW_CONSOLE_BINDING=y # CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_NOZOMI is not set # # Serial drivers @@ -674,11 +719,9 @@ CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 # CONFIG_IPMI_HANDLER is not set -# CONFIG_WATCHDOG is not set CONFIG_HW_RANDOM=y # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set -# CONFIG_DRM is not set # CONFIG_RAW_DRIVER is not set # CONFIG_TCG_TPM is not set CONFIG_DEVPORT=y @@ -687,16 +730,30 @@ CONFIG_DEVPORT=y # # SPI support # -# CONFIG_SPI is not set -# CONFIG_SPI_MASTER is not set +CONFIG_SPI=y +CONFIG_SPI_MASTER=y + +# +# SPI Master Controller Drivers +# +CONFIG_SPI_BITBANG=y +CONFIG_SPI_SH_SCI=y + +# +# SPI Protocol Masters +# +# CONFIG_SPI_AT25 is not set +# CONFIG_SPI_SPIDEV is not set +# CONFIG_SPI_TLE62X0 is not set # CONFIG_W1 is not set # CONFIG_POWER_SUPPLY is not set CONFIG_HWMON=y # CONFIG_HWMON_VID is not set -# CONFIG_SENSORS_ABITUGURU is not set -# CONFIG_SENSORS_ABITUGURU3 is not set +# CONFIG_SENSORS_I5K_AMB is not set # CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_F71882FG is not set # CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_LM70 is not set # CONFIG_SENSORS_PC87360 is not set # CONFIG_SENSORS_PC87427 is not set # CONFIG_SENSORS_SIS5595 is not set @@ -708,6 +765,13 @@ CONFIG_HWMON=y # CONFIG_SENSORS_W83627HF is not set # CONFIG_SENSORS_W83627EHF is not set # CONFIG_HWMON_DEBUG_CHIP is not set +# CONFIG_WATCHDOG is not set + +# +# Sonics Silicon Backplane +# +CONFIG_SSB_POSSIBLE=y +# CONFIG_SSB is not set # # Multifunction device drivers @@ -720,16 +784,12 @@ CONFIG_MFD_SM501=y # CONFIG_VIDEO_DEV is not set # CONFIG_DVB_CORE is not set CONFIG_DAB=y +# CONFIG_USB_DABUSB is not set # # Graphics support # -# CONFIG_BACKLIGHT_LCD_SUPPORT is not set - -# -# Display device support -# -# CONFIG_DISPLAY_SUPPORT is not set +# CONFIG_DRM is not set # CONFIG_VGASTATE is not set CONFIG_VIDEO_OUTPUT_CONTROL=m CONFIG_FB=y @@ -738,6 +798,7 @@ CONFIG_FB=y CONFIG_FB_CFB_FILLRECT=y CONFIG_FB_CFB_COPYAREA=y CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set # CONFIG_FB_SYS_FILLRECT is not set # CONFIG_FB_SYS_COPYAREA is not set # CONFIG_FB_SYS_IMAGEBLIT is not set @@ -777,6 +838,12 @@ CONFIG_FB_DEFERRED_IO=y # CONFIG_FB_PM3 is not set CONFIG_FB_SM501=y # CONFIG_FB_VIRTUAL is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set # # Console display driver support @@ -844,6 +911,7 @@ CONFIG_SND_AC97_CODEC=m # CONFIG_SND_BT87X is not set # CONFIG_SND_CA0106 is not set # CONFIG_SND_CMIPCI is not set +# CONFIG_SND_OXYGEN is not set # CONFIG_SND_CS4281 is not set # CONFIG_SND_CS46XX is not set # CONFIG_SND_DARLA20 is not set @@ -868,6 +936,7 @@ CONFIG_SND_AC97_CODEC=m # CONFIG_SND_HDA_INTEL is not set # CONFIG_SND_HDSP is not set # CONFIG_SND_HDSPM is not set +# CONFIG_SND_HIFIER is not set # CONFIG_SND_ICE1712 is not set # CONFIG_SND_ICE1724 is not set # CONFIG_SND_INTEL8X0 is not set @@ -885,15 +954,26 @@ CONFIG_SND_AC97_CODEC=m # CONFIG_SND_TRIDENT is not set # CONFIG_SND_VIA82XX is not set # CONFIG_SND_VIA82XX_MODEM is not set +# CONFIG_SND_VIRTUOSO is not set # CONFIG_SND_VX222 is not set CONFIG_SND_YMFPCI=m CONFIG_SND_YMFPCI_FIRMWARE_IN_KERNEL=y # CONFIG_SND_AC97_POWER_SAVE is not set +# +# SPI devices +# + # # SUPERH devices # +# +# USB devices +# +# CONFIG_SND_USB_AUDIO is not set +# CONFIG_SND_USB_CAIAQ is not set + # # System on Chip audio support # @@ -903,6 +983,10 @@ CONFIG_SND_YMFPCI_FIRMWARE_IN_KERNEL=y # SoC Audio support for SuperH # +# +# ALSA SoC audio for Freescale SOCs +# + # # Open Sound System # @@ -914,19 +998,104 @@ CONFIG_AC97_BUS=m CONFIG_HID_SUPPORT=y CONFIG_HID=y # CONFIG_HID_DEBUG is not set +# CONFIG_HIDRAW is not set + +# +# USB Input Devices +# +CONFIG_USB_HID=y +# CONFIG_USB_HIDINPUT_POWERBOOK is not set +# CONFIG_HID_FF is not set +# CONFIG_USB_HIDDEV is not set CONFIG_USB_SUPPORT=y CONFIG_USB_ARCH_HAS_HCD=y CONFIG_USB_ARCH_HAS_OHCI=y CONFIG_USB_ARCH_HAS_EHCI=y -# CONFIG_USB is not set +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y + +# +# Miscellaneous USB options +# +# CONFIG_USB_DEVICEFS is not set +CONFIG_USB_DEVICE_CLASS=y +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_OTG is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_EHCI_HCD is not set +# CONFIG_USB_ISP116X_HCD is not set +CONFIG_USB_OHCI_HCD=y +# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set +# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +# CONFIG_USB_UHCI_HCD is not set +# CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_R8A66597_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' # # -# USB Gadget Support +# may also be needed; see USB_STORAGE Help for more information # +CONFIG_USB_STORAGE=y +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 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=y + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set +# CONFIG_USB_MON is not set + +# +# USB port drivers +# +# 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_BERRY_CHARGE 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_IOWARRIOR is not set # CONFIG_USB_GADGET is not set # CONFIG_MMC is not set # CONFIG_NEW_LEDS is not set @@ -949,13 +1118,17 @@ CONFIG_RTC_INTF_DEV=y # # SPI RTC drivers # +# CONFIG_RTC_DRV_MAX6902 is not set +CONFIG_RTC_DRV_R9701=y +# CONFIG_RTC_DRV_RS5C348 is not set # # Platform RTC drivers # +# CONFIG_RTC_DRV_DS1511 is not set # CONFIG_RTC_DRV_DS1553 is not set -# CONFIG_RTC_DRV_STK17TA8 is not set # CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set # CONFIG_RTC_DRV_M48T86 is not set # CONFIG_RTC_DRV_M48T59 is not set # CONFIG_RTC_DRV_V3020 is not set @@ -963,20 +1136,7 @@ CONFIG_RTC_INTF_DEV=y # # on-CPU RTC drivers # -CONFIG_RTC_DRV_SH=y - -# -# DMA Engine support -# -# CONFIG_DMA_ENGINE is not set - -# -# DMA Clients -# - -# -# DMA Devices -# +# CONFIG_RTC_DRV_SH is not set # # Userspace I/O @@ -1034,7 +1194,6 @@ CONFIG_TMPFS=y # CONFIG_TMPFS_POSIX_ACL is not set # CONFIG_HUGETLBFS is not set # CONFIG_HUGETLB_PAGE is not set -CONFIG_RAMFS=y # CONFIG_CONFIGFS_FS is not set # @@ -1053,10 +1212,7 @@ CONFIG_RAMFS=y # CONFIG_QNX4FS_FS is not set # CONFIG_SYSV_FS is not set # CONFIG_UFS_FS is not set - -# -# Network File Systems -# +CONFIG_NETWORK_FILESYSTEMS=y # CONFIG_NFS_FS is not set # CONFIG_NFSD is not set # CONFIG_SMB_FS is not set @@ -1070,10 +1226,6 @@ CONFIG_RAMFS=y # # 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 is not set @@ -1114,30 +1266,22 @@ CONFIG_NLS_CODEPAGE_932=y # CONFIG_NLS_KOI8_R is not set # CONFIG_NLS_KOI8_U is not set # CONFIG_NLS_UTF8 is not set - -# -# Distributed Lock Manager -# # CONFIG_DLM is not set -# -# Profiling support -# -CONFIG_PROFILING=y -CONFIG_OPROFILE=y - # # Kernel hacking # CONFIG_TRACE_IRQFLAGS_SUPPORT=y # CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_WARN_DEPRECATED=y CONFIG_ENABLE_MUST_CHECK=y # CONFIG_MAGIC_SYSRQ is not set # CONFIG_UNUSED_SYMBOLS is not set -# CONFIG_DEBUG_FS is not set +CONFIG_DEBUG_FS=y # CONFIG_HEADERS_CHECK is not set # CONFIG_DEBUG_KERNEL is not set # CONFIG_DEBUG_BUGVERBOSE is not set +# CONFIG_SAMPLES is not set # CONFIG_SH_STANDARD_BIOS is not set CONFIG_EARLY_SCIF_CONSOLE=y CONFIG_EARLY_SCIF_CONSOLE_PORT=0xffe80000 @@ -1149,7 +1293,53 @@ CONFIG_EARLY_PRINTK=y # # CONFIG_KEYS is not set # CONFIG_SECURITY is not set -# CONFIG_CRYPTO is not set +# CONFIG_SECURITY_FILE_CAPABILITIES is not set +CONFIG_CRYPTO=y +# CONFIG_CRYPTO_SEQIV is not set +# CONFIG_CRYPTO_MANAGER is not set +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_XCBC is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_WP512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_ECB is not set +# CONFIG_CRYPTO_CBC is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_XTS is not set +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_CRYPTD is not set +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_TWOFISH is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_TEST is not set +# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_LZO is not set +CONFIG_CRYPTO_HW=y +# CONFIG_CRYPTO_DEV_HIFN_795X is not set # # Library routines diff --git a/arch/sh/configs/rts7751r2dplus_defconfig b/arch/sh/configs/rts7751r2dplus_defconfig index 4ff5a752dcd9..0a6d3b9e648b 100644 --- a/arch/sh/configs/rts7751r2dplus_defconfig +++ b/arch/sh/configs/rts7751r2dplus_defconfig @@ -1,9 +1,10 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.23-rc2 -# Tue Aug 14 16:33:08 2007 +# Linux kernel version: 2.6.24 +# Thu Feb 7 16:17:47 2008 # CONFIG_SUPERH=y +CONFIG_SUPERH32=y CONFIG_RWSEM_GENERIC_SPINLOCK=y CONFIG_GENERIC_BUG=y CONFIG_GENERIC_FIND_NEXT_BIT=y @@ -36,9 +37,14 @@ CONFIG_SYSVIPC_SYSCTL=y # CONFIG_BSD_PROCESS_ACCT is not set # CONFIG_TASKSTATS is not set # CONFIG_USER_NS is not set +# CONFIG_PID_NS is not set # CONFIG_AUDIT is not set # CONFIG_IKCONFIG is not set CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_CGROUPS is not set +CONFIG_FAIR_GROUP_SCHED=y +CONFIG_FAIR_USER_SCHED=y +# CONFIG_FAIR_CGROUP_SCHED is not set CONFIG_SYSFS_DEPRECATED=y # CONFIG_RELAY is not set # CONFIG_BLK_DEV_INITRD is not set @@ -53,6 +59,7 @@ CONFIG_HOTPLUG=y CONFIG_PRINTK=y CONFIG_BUG=y CONFIG_ELF_CORE=y +CONFIG_COMPAT_BRK=y CONFIG_BASE_FULL=y CONFIG_FUTEX=y CONFIG_ANON_INODES=y @@ -65,6 +72,13 @@ CONFIG_VM_EVENT_COUNTERS=y CONFIG_SLAB=y # CONFIG_SLUB is not set # CONFIG_SLOB is not set +CONFIG_PROFILING=y +# CONFIG_MARKERS is not set +CONFIG_OPROFILE=y +CONFIG_HAVE_OPROFILE=y +# CONFIG_HAVE_KPROBES is not set +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_SLABINFO=y CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 @@ -91,13 +105,17 @@ CONFIG_DEFAULT_AS=y # CONFIG_DEFAULT_CFQ is not set # CONFIG_DEFAULT_NOOP is not set CONFIG_DEFAULT_IOSCHED="anticipatory" +CONFIG_CLASSIC_RCU=y +# CONFIG_PREEMPT_RCU is not set # # System type # CONFIG_CPU_SH4=y # CONFIG_CPU_SUBTYPE_SH7619 is not set +# CONFIG_CPU_SUBTYPE_SH7203 is not set # CONFIG_CPU_SUBTYPE_SH7206 is not set +# CONFIG_CPU_SUBTYPE_SH7263 is not set # CONFIG_CPU_SUBTYPE_SH7705 is not set # CONFIG_CPU_SUBTYPE_SH7706 is not set # CONFIG_CPU_SUBTYPE_SH7707 is not set @@ -105,6 +123,8 @@ CONFIG_CPU_SH4=y # CONFIG_CPU_SUBTYPE_SH7709 is not set # CONFIG_CPU_SUBTYPE_SH7710 is not set # CONFIG_CPU_SUBTYPE_SH7712 is not set +# CONFIG_CPU_SUBTYPE_SH7720 is not set +# CONFIG_CPU_SUBTYPE_SH7721 is not set # CONFIG_CPU_SUBTYPE_SH7750 is not set # CONFIG_CPU_SUBTYPE_SH7091 is not set # CONFIG_CPU_SUBTYPE_SH7750R is not set @@ -113,14 +133,15 @@ CONFIG_CPU_SH4=y CONFIG_CPU_SUBTYPE_SH7751R=y # CONFIG_CPU_SUBTYPE_SH7760 is not set # CONFIG_CPU_SUBTYPE_SH4_202 is not set -# CONFIG_CPU_SUBTYPE_ST40STB1 is not set -# CONFIG_CPU_SUBTYPE_ST40GX1 is not set +# CONFIG_CPU_SUBTYPE_SH7763 is not set # CONFIG_CPU_SUBTYPE_SH7770 is not set # CONFIG_CPU_SUBTYPE_SH7780 is not set # CONFIG_CPU_SUBTYPE_SH7785 is not set # CONFIG_CPU_SUBTYPE_SHX3 is not set # CONFIG_CPU_SUBTYPE_SH7343 is not set # CONFIG_CPU_SUBTYPE_SH7722 is not set +# CONFIG_CPU_SUBTYPE_SH5_101 is not set +# CONFIG_CPU_SUBTYPE_SH5_103 is not set # # Memory management options @@ -130,6 +151,7 @@ CONFIG_MMU=y CONFIG_PAGE_OFFSET=0x80000000 CONFIG_MEMORY_START=0x0c000000 CONFIG_MEMORY_SIZE=0x04000000 +CONFIG_29BIT=y CONFIG_VSYSCALL=y CONFIG_ARCH_FLATMEM_ENABLE=y CONFIG_ARCH_SPARSEMEM_ENABLE=y @@ -147,6 +169,7 @@ CONFIG_FLATMEM_MANUAL=y CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y CONFIG_SPARSEMEM_STATIC=y +# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_RESOURCES_64BIT is not set CONFIG_ZONE_DMA_FLAG=0 @@ -168,23 +191,22 @@ CONFIG_CPU_LITTLE_ENDIAN=y CONFIG_SH_FPU=y # CONFIG_SH_STORE_QUEUES is not set CONFIG_CPU_HAS_INTEVT=y -CONFIG_CPU_HAS_INTC_IRQ=y CONFIG_CPU_HAS_SR_RB=y CONFIG_CPU_HAS_PTEA=y +CONFIG_CPU_HAS_FPU=y # # Board support # # CONFIG_SH_7751_SYSTEMH is not set # CONFIG_SH_SECUREEDGE5410 is not set -# CONFIG_SH_HS7751RVOIP is not set CONFIG_SH_RTS7751R2D=y # CONFIG_SH_LANDISK is not set # CONFIG_SH_TITAN is not set # CONFIG_SH_LBOX_RE2 is not set # -# RTS7751R2D options +# RTS7751R2D Board Revision # CONFIG_RTS7751R2D_PLUS=y # CONFIG_RTS7751R2D_1 is not set @@ -198,6 +220,7 @@ CONFIG_SH_PCLK_FREQ=60000000 # CONFIG_TICK_ONESHOT is not set # CONFIG_NO_HZ is not set # CONFIG_HIGH_RES_TIMERS is not set +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y # # CPU Frequency scaling @@ -227,11 +250,15 @@ CONFIG_HZ_250=y # CONFIG_HZ_300 is not set # CONFIG_HZ_1000 is not set CONFIG_HZ=250 +# CONFIG_SCHED_HRTICK is not set # CONFIG_KEXEC is not set # CONFIG_CRASH_DUMP is not set CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT_VOLUNTARY is not set # CONFIG_PREEMPT is not set +CONFIG_RCU_TRACE=y +CONFIG_GUSA=y +# CONFIG_GUSA_RB is not set # # Boot options @@ -250,10 +277,7 @@ CONFIG_SH_PCIDMA_NONCOHERENT=y CONFIG_PCI_AUTO=y CONFIG_PCI_AUTO_UPDATE_RESOURCES=y # CONFIG_ARCH_SUPPORTS_MSI is not set - -# -# PCCARD (PCMCIA/CardBus) support -# +CONFIG_PCI_LEGACY=y # CONFIG_PCCARD is not set CONFIG_HOTPLUG_PCI=y # CONFIG_HOTPLUG_PCI_FAKE is not set @@ -281,6 +305,7 @@ CONFIG_XFRM=y # CONFIG_XFRM_USER is not set # CONFIG_XFRM_SUB_POLICY is not set # CONFIG_XFRM_MIGRATE is not set +# CONFIG_XFRM_STATISTICS is not set # CONFIG_NET_KEY is not set CONFIG_INET=y # CONFIG_IP_MULTICAST is not set @@ -299,6 +324,7 @@ CONFIG_IP_FIB_HASH=y CONFIG_INET_XFRM_MODE_TRANSPORT=y CONFIG_INET_XFRM_MODE_TUNNEL=y CONFIG_INET_XFRM_MODE_BEET=y +# CONFIG_INET_LRO is not set CONFIG_INET_DIAG=y CONFIG_INET_TCP_DIAG=y # CONFIG_TCP_CONG_ADVANCED is not set @@ -324,10 +350,6 @@ CONFIG_DEFAULT_TCP_CONG="cubic" # 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 # @@ -335,6 +357,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic" # # CONFIG_NET_PKTGEN is not set # CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set # CONFIG_IRDA is not set # CONFIG_BT is not set # CONFIG_AF_RXRPC is not set @@ -356,6 +379,7 @@ CONFIG_WIRELESS_EXT=y # # Generic Driver Options # +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y CONFIG_FW_LOADER=m @@ -371,6 +395,7 @@ CONFIG_BLK_DEV=y # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_SX8 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=4096 @@ -420,6 +445,7 @@ CONFIG_SCSI_WAIT_SCAN=m # CONFIG_SCSI_FC_ATTRS is not set # CONFIG_SCSI_ISCSI_ATTRS is not set # CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set CONFIG_SCSI_LOWLEVEL=y # CONFIG_ISCSI_TCP is not set # CONFIG_BLK_DEV_3W_XXXX_RAID is not set @@ -493,7 +519,9 @@ CONFIG_ATA=y # CONFIG_PATA_MPIIX is not set # CONFIG_PATA_OLDPIIX is not set # CONFIG_PATA_NETCELL is not set +# CONFIG_PATA_NINJA32 is not set # CONFIG_PATA_NS87410 is not set +# CONFIG_PATA_NS87415 is not set # CONFIG_PATA_OPTI is not set # CONFIG_PATA_OPTIDMA is not set # CONFIG_PATA_PDC_OLD is not set @@ -508,14 +536,7 @@ CONFIG_ATA=y # CONFIG_PATA_WINBOND is not set CONFIG_PATA_PLATFORM=y # CONFIG_MD 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 @@ -530,25 +551,31 @@ CONFIG_NETDEVICES=y # CONFIG_MACVLAN is not set # CONFIG_EQUALIZER is not set # CONFIG_TUN is not set +# CONFIG_VETH is not set # CONFIG_ARCNET is not set # CONFIG_PHYLIB is not set CONFIG_NET_ETHERNET=y CONFIG_MII=y +# CONFIG_AX88796 is not set # CONFIG_STNIC is not set # CONFIG_HAPPYMEAL is not set # CONFIG_SUNGEM is not set # CONFIG_CASSINI is not set # CONFIG_NET_VENDOR_3COM is not set # CONFIG_SMC91X is not set +# CONFIG_ENC28J60 is not set # CONFIG_NET_TULIP is not set # CONFIG_HP100 is not set +# CONFIG_IBM_NEW_EMAC_ZMII is not set +# CONFIG_IBM_NEW_EMAC_RGMII is not set +# CONFIG_IBM_NEW_EMAC_TAH is not set +# CONFIG_IBM_NEW_EMAC_EMAC4 is not set CONFIG_NET_PCI=y # CONFIG_PCNET32 is not set # CONFIG_AMD8111_ETH is not set # CONFIG_ADAPTEC_STARFIRE is not set # CONFIG_B44 is not set # CONFIG_FORCEDETH is not set -# CONFIG_DGRS is not set # CONFIG_EEPRO100 is not set # CONFIG_E100 is not set # CONFIG_FEALNX is not set @@ -560,6 +587,7 @@ CONFIG_8139TOO=y # CONFIG_8139TOO_TUNE_TWISTER is not set # CONFIG_8139TOO_8129 is not set # CONFIG_8139_OLD_RX_RESET is not set +# CONFIG_R6040 is not set # CONFIG_SIS900 is not set # CONFIG_EPIC100 is not set # CONFIG_SUNDANCE is not set @@ -570,6 +598,10 @@ CONFIG_NETDEV_1000=y # CONFIG_ACENIC is not set # CONFIG_DL2K is not set # CONFIG_E1000 is not set +# CONFIG_E1000E is not set +# CONFIG_E1000E_ENABLED is not set +# CONFIG_IP1000 is not set +# CONFIG_IGB is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set @@ -577,6 +609,7 @@ CONFIG_NETDEV_1000=y # CONFIG_SIS190 is not set # CONFIG_SKGE is not set # CONFIG_SKY2 is not set +# CONFIG_SK98LIN is not set # CONFIG_VIA_VELOCITY is not set # CONFIG_TIGON3 is not set # CONFIG_BNX2 is not set @@ -585,11 +618,15 @@ CONFIG_NETDEV_1000=y CONFIG_NETDEV_10000=y # CONFIG_CHELSIO_T1 is not set # CONFIG_CHELSIO_T3 is not set +# CONFIG_IXGBE is not set # CONFIG_IXGB is not set # CONFIG_S2IO is not set # CONFIG_MYRI10GE is not set # CONFIG_NETXEN_NIC is not set +# CONFIG_NIU is not set # CONFIG_MLX4_CORE is not set +# CONFIG_TEHUTI is not set +# CONFIG_BNX2X is not set # CONFIG_TR is not set # @@ -597,13 +634,21 @@ CONFIG_NETDEV_10000=y # # CONFIG_WLAN_PRE80211 is not set # CONFIG_WLAN_80211 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 is not set # 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 @@ -622,7 +667,6 @@ CONFIG_INPUT=y # # CONFIG_INPUT_MOUSEDEV is not set # CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_TSDEV is not set # CONFIG_INPUT_EVDEV is not set # CONFIG_INPUT_EVBUG is not set @@ -650,6 +694,7 @@ CONFIG_VT_CONSOLE=y CONFIG_HW_CONSOLE=y CONFIG_VT_HW_CONSOLE_BINDING=y # CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_NOZOMI is not set # # Serial drivers @@ -674,11 +719,9 @@ CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 # CONFIG_IPMI_HANDLER is not set -# CONFIG_WATCHDOG is not set CONFIG_HW_RANDOM=y # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set -# CONFIG_DRM is not set # CONFIG_RAW_DRIVER is not set # CONFIG_TCG_TPM is not set CONFIG_DEVPORT=y @@ -687,16 +730,30 @@ CONFIG_DEVPORT=y # # SPI support # -# CONFIG_SPI is not set -# CONFIG_SPI_MASTER is not set +CONFIG_SPI=y +CONFIG_SPI_MASTER=y + +# +# SPI Master Controller Drivers +# +CONFIG_SPI_BITBANG=y +CONFIG_SPI_SH_SCI=y + +# +# SPI Protocol Masters +# +# CONFIG_SPI_AT25 is not set +# CONFIG_SPI_SPIDEV is not set +# CONFIG_SPI_TLE62X0 is not set # CONFIG_W1 is not set # CONFIG_POWER_SUPPLY is not set CONFIG_HWMON=y # CONFIG_HWMON_VID is not set -# CONFIG_SENSORS_ABITUGURU is not set -# CONFIG_SENSORS_ABITUGURU3 is not set +# CONFIG_SENSORS_I5K_AMB is not set # CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_F71882FG is not set # CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_LM70 is not set # CONFIG_SENSORS_PC87360 is not set # CONFIG_SENSORS_PC87427 is not set # CONFIG_SENSORS_SIS5595 is not set @@ -708,6 +765,13 @@ CONFIG_HWMON=y # CONFIG_SENSORS_W83627HF is not set # CONFIG_SENSORS_W83627EHF is not set # CONFIG_HWMON_DEBUG_CHIP is not set +# CONFIG_WATCHDOG is not set + +# +# Sonics Silicon Backplane +# +CONFIG_SSB_POSSIBLE=y +# CONFIG_SSB is not set # # Multifunction device drivers @@ -720,16 +784,12 @@ CONFIG_MFD_SM501=y # CONFIG_VIDEO_DEV is not set # CONFIG_DVB_CORE is not set CONFIG_DAB=y +# CONFIG_USB_DABUSB is not set # # Graphics support # -# CONFIG_BACKLIGHT_LCD_SUPPORT is not set - -# -# Display device support -# -# CONFIG_DISPLAY_SUPPORT is not set +# CONFIG_DRM is not set # CONFIG_VGASTATE is not set CONFIG_VIDEO_OUTPUT_CONTROL=m CONFIG_FB=y @@ -738,6 +798,7 @@ CONFIG_FB=y CONFIG_FB_CFB_FILLRECT=y CONFIG_FB_CFB_COPYAREA=y CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set # CONFIG_FB_SYS_FILLRECT is not set # CONFIG_FB_SYS_COPYAREA is not set # CONFIG_FB_SYS_IMAGEBLIT is not set @@ -777,6 +838,12 @@ CONFIG_FB_DEFERRED_IO=y # CONFIG_FB_PM3 is not set CONFIG_FB_SM501=y # CONFIG_FB_VIRTUAL is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set # # Console display driver support @@ -844,6 +911,7 @@ CONFIG_SND_AC97_CODEC=m # CONFIG_SND_BT87X is not set # CONFIG_SND_CA0106 is not set # CONFIG_SND_CMIPCI is not set +# CONFIG_SND_OXYGEN is not set # CONFIG_SND_CS4281 is not set # CONFIG_SND_CS46XX is not set # CONFIG_SND_DARLA20 is not set @@ -868,6 +936,7 @@ CONFIG_SND_AC97_CODEC=m # CONFIG_SND_HDA_INTEL is not set # CONFIG_SND_HDSP is not set # CONFIG_SND_HDSPM is not set +# CONFIG_SND_HIFIER is not set # CONFIG_SND_ICE1712 is not set # CONFIG_SND_ICE1724 is not set # CONFIG_SND_INTEL8X0 is not set @@ -885,15 +954,26 @@ CONFIG_SND_AC97_CODEC=m # CONFIG_SND_TRIDENT is not set # CONFIG_SND_VIA82XX is not set # CONFIG_SND_VIA82XX_MODEM is not set +# CONFIG_SND_VIRTUOSO is not set # CONFIG_SND_VX222 is not set CONFIG_SND_YMFPCI=m CONFIG_SND_YMFPCI_FIRMWARE_IN_KERNEL=y # CONFIG_SND_AC97_POWER_SAVE is not set +# +# SPI devices +# + # # SUPERH devices # +# +# USB devices +# +# CONFIG_SND_USB_AUDIO is not set +# CONFIG_SND_USB_CAIAQ is not set + # # System on Chip audio support # @@ -903,6 +983,10 @@ CONFIG_SND_YMFPCI_FIRMWARE_IN_KERNEL=y # SoC Audio support for SuperH # +# +# ALSA SoC audio for Freescale SOCs +# + # # Open Sound System # @@ -914,19 +998,104 @@ CONFIG_AC97_BUS=m CONFIG_HID_SUPPORT=y CONFIG_HID=y # CONFIG_HID_DEBUG is not set +# CONFIG_HIDRAW is not set + +# +# USB Input Devices +# +CONFIG_USB_HID=y +# CONFIG_USB_HIDINPUT_POWERBOOK is not set +# CONFIG_HID_FF is not set +# CONFIG_USB_HIDDEV is not set CONFIG_USB_SUPPORT=y CONFIG_USB_ARCH_HAS_HCD=y CONFIG_USB_ARCH_HAS_OHCI=y CONFIG_USB_ARCH_HAS_EHCI=y -# CONFIG_USB is not set +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y + +# +# Miscellaneous USB options +# +# CONFIG_USB_DEVICEFS is not set +CONFIG_USB_DEVICE_CLASS=y +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_OTG is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_EHCI_HCD is not set +# CONFIG_USB_ISP116X_HCD is not set +CONFIG_USB_OHCI_HCD=y +# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set +# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +# CONFIG_USB_UHCI_HCD is not set +# CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_R8A66597_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' # # -# USB Gadget Support +# may also be needed; see USB_STORAGE Help for more information # +CONFIG_USB_STORAGE=y +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 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=y + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set +# CONFIG_USB_MON is not set + +# +# USB port drivers +# +# 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_BERRY_CHARGE 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_IOWARRIOR is not set # CONFIG_USB_GADGET is not set # CONFIG_MMC is not set # CONFIG_NEW_LEDS is not set @@ -949,13 +1118,17 @@ CONFIG_RTC_INTF_DEV=y # # SPI RTC drivers # +# CONFIG_RTC_DRV_MAX6902 is not set +CONFIG_RTC_DRV_R9701=y +# CONFIG_RTC_DRV_RS5C348 is not set # # Platform RTC drivers # +# CONFIG_RTC_DRV_DS1511 is not set # CONFIG_RTC_DRV_DS1553 is not set -# CONFIG_RTC_DRV_STK17TA8 is not set # CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set # CONFIG_RTC_DRV_M48T86 is not set # CONFIG_RTC_DRV_M48T59 is not set # CONFIG_RTC_DRV_V3020 is not set @@ -963,20 +1136,7 @@ CONFIG_RTC_INTF_DEV=y # # on-CPU RTC drivers # -CONFIG_RTC_DRV_SH=y - -# -# DMA Engine support -# -# CONFIG_DMA_ENGINE is not set - -# -# DMA Clients -# - -# -# DMA Devices -# +# CONFIG_RTC_DRV_SH is not set # # Userspace I/O @@ -1034,7 +1194,6 @@ CONFIG_TMPFS=y # CONFIG_TMPFS_POSIX_ACL is not set # CONFIG_HUGETLBFS is not set # CONFIG_HUGETLB_PAGE is not set -CONFIG_RAMFS=y # CONFIG_CONFIGFS_FS is not set # @@ -1053,10 +1212,7 @@ CONFIG_RAMFS=y # CONFIG_QNX4FS_FS is not set # CONFIG_SYSV_FS is not set # CONFIG_UFS_FS is not set - -# -# Network File Systems -# +CONFIG_NETWORK_FILESYSTEMS=y # CONFIG_NFS_FS is not set # CONFIG_NFSD is not set # CONFIG_SMB_FS is not set @@ -1070,10 +1226,6 @@ CONFIG_RAMFS=y # # 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 is not set @@ -1114,30 +1266,22 @@ CONFIG_NLS_CODEPAGE_932=y # CONFIG_NLS_KOI8_R is not set # CONFIG_NLS_KOI8_U is not set # CONFIG_NLS_UTF8 is not set - -# -# Distributed Lock Manager -# # CONFIG_DLM is not set -# -# Profiling support -# -CONFIG_PROFILING=y -CONFIG_OPROFILE=y - # # Kernel hacking # CONFIG_TRACE_IRQFLAGS_SUPPORT=y # CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_WARN_DEPRECATED=y CONFIG_ENABLE_MUST_CHECK=y # CONFIG_MAGIC_SYSRQ is not set # CONFIG_UNUSED_SYMBOLS is not set -# CONFIG_DEBUG_FS is not set +CONFIG_DEBUG_FS=y # CONFIG_HEADERS_CHECK is not set # CONFIG_DEBUG_KERNEL is not set # CONFIG_DEBUG_BUGVERBOSE is not set +# CONFIG_SAMPLES is not set # CONFIG_SH_STANDARD_BIOS is not set CONFIG_EARLY_SCIF_CONSOLE=y CONFIG_EARLY_SCIF_CONSOLE_PORT=0xffe80000 @@ -1149,7 +1293,53 @@ CONFIG_EARLY_PRINTK=y # # CONFIG_KEYS is not set # CONFIG_SECURITY is not set -# CONFIG_CRYPTO is not set +# CONFIG_SECURITY_FILE_CAPABILITIES is not set +CONFIG_CRYPTO=y +# CONFIG_CRYPTO_SEQIV is not set +# CONFIG_CRYPTO_MANAGER is not set +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_XCBC is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_WP512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_ECB is not set +# CONFIG_CRYPTO_CBC is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_XTS is not set +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_CRYPTD is not set +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_TWOFISH is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_TEST is not set +# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_LZO is not set +CONFIG_CRYPTO_HW=y +# CONFIG_CRYPTO_DEV_HIFN_795X is not set # # Library routines diff --git a/arch/sh/configs/se7705_defconfig b/arch/sh/configs/se7705_defconfig index 87ae5c1f8629..84717d854867 100644 --- a/arch/sh/configs/se7705_defconfig +++ b/arch/sh/configs/se7705_defconfig @@ -231,7 +231,6 @@ CONFIG_CPU_LITTLE_ENDIAN=y # CONFIG_SH_DSP is not set # CONFIG_SH_ADC is not set CONFIG_CPU_HAS_INTEVT=y -CONFIG_CPU_HAS_PINT_IRQ=y CONFIG_CPU_HAS_IPR_IRQ=y CONFIG_CPU_HAS_SR_RB=y diff --git a/arch/sh/drivers/dma/dma-api.c b/arch/sh/drivers/dma/dma-api.c index 76ed816d9a24..727126e907e3 100644 --- a/arch/sh/drivers/dma/dma-api.c +++ b/arch/sh/drivers/dma/dma-api.c @@ -350,7 +350,7 @@ int register_dmac(struct dma_info *info) BUG_ON((info->flags & DMAC_CHANNELS_CONFIGURED) && !info->channels); - info->pdev = platform_device_register_simple((char *)info->name, -1, + info->pdev = platform_device_register_simple(info->name, -1, NULL, 0); if (IS_ERR(info->pdev)) return PTR_ERR(info->pdev); diff --git a/arch/sh/drivers/pci/fixups-lboxre2.c b/arch/sh/drivers/pci/fixups-lboxre2.c index 40b19bdfb891..1c1d41255ec0 100644 --- a/arch/sh/drivers/pci/fixups-lboxre2.c +++ b/arch/sh/drivers/pci/fixups-lboxre2.c @@ -18,7 +18,7 @@ int pci_fixup_pcic(void) { unsigned long bcr1, mcr; - bcr1 = inl(SH7751_BCR1); + bcr1 = ctrl_inl(SH7751_BCR1); bcr1 |= 0x40080000; /* Enable Bit 19 BREQEN, set PCIC to slave */ pci_write_reg(bcr1, SH4_PCIBCR1); @@ -28,7 +28,7 @@ int pci_fixup_pcic(void) pci_write_reg(0xfb900047, SH7751_PCICONF1); pci_write_reg(0xab000001, SH7751_PCICONF4); - mcr = inl(SH7751_MCR); + mcr = ctrl_inl(SH7751_MCR); mcr = (mcr & PCIMCR_MRSET_OFF) & PCIMCR_RFSH_OFF; pci_write_reg(mcr, SH4_PCIMCR); diff --git a/arch/sh/drivers/pci/fixups-rts7751r2d.c b/arch/sh/drivers/pci/fixups-rts7751r2d.c index e72ceb560d5b..904bce8768d3 100644 --- a/arch/sh/drivers/pci/fixups-rts7751r2d.c +++ b/arch/sh/drivers/pci/fixups-rts7751r2d.c @@ -19,7 +19,7 @@ int pci_fixup_pcic(void) { unsigned long bcr1, mcr; - bcr1 = inl(SH7751_BCR1); + bcr1 = ctrl_inl(SH7751_BCR1); bcr1 |= 0x40080000; /* Enable Bit 19 BREQEN, set PCIC to slave */ pci_write_reg(bcr1, SH4_PCIBCR1); @@ -30,7 +30,7 @@ int pci_fixup_pcic(void) pci_write_reg(0xfb900047, SH7751_PCICONF1); pci_write_reg(0xab000001, SH7751_PCICONF4); - mcr = inl(SH7751_MCR); + mcr = ctrl_inl(SH7751_MCR); mcr = (mcr & PCIMCR_MRSET_OFF) & PCIMCR_RFSH_OFF; pci_write_reg(mcr, SH4_PCIMCR); diff --git a/arch/sh/drivers/pci/ops-dreamcast.c b/arch/sh/drivers/pci/ops-dreamcast.c index e1284fc69361..0dac87b19624 100644 --- a/arch/sh/drivers/pci/ops-dreamcast.c +++ b/arch/sh/drivers/pci/ops-dreamcast.c @@ -83,9 +83,9 @@ static int gapspci_read(struct pci_bus *bus, unsigned int devfn, int where, int return PCIBIOS_DEVICE_NOT_FOUND; switch (size) { - case 1: *val = inb(GAPSPCI_BBA_CONFIG+where); break; - case 2: *val = inw(GAPSPCI_BBA_CONFIG+where); break; - case 4: *val = inl(GAPSPCI_BBA_CONFIG+where); break; + case 1: *val = ctrl_inb(GAPSPCI_BBA_CONFIG+where); break; + case 2: *val = ctrl_inw(GAPSPCI_BBA_CONFIG+where); break; + case 4: *val = ctrl_inl(GAPSPCI_BBA_CONFIG+where); break; } return PCIBIOS_SUCCESSFUL; @@ -97,9 +97,9 @@ static int gapspci_write(struct pci_bus *bus, unsigned int devfn, int where, int return PCIBIOS_DEVICE_NOT_FOUND; switch (size) { - case 1: outb(( u8)val, GAPSPCI_BBA_CONFIG+where); break; - case 2: outw((u16)val, GAPSPCI_BBA_CONFIG+where); break; - case 4: outl((u32)val, GAPSPCI_BBA_CONFIG+where); break; + case 1: ctrl_outb(( u8)val, GAPSPCI_BBA_CONFIG+where); break; + case 2: ctrl_outw((u16)val, GAPSPCI_BBA_CONFIG+where); break; + case 4: ctrl_outl((u32)val, GAPSPCI_BBA_CONFIG+where); break; } return PCIBIOS_SUCCESSFUL; @@ -127,36 +127,36 @@ int __init gapspci_init(void) */ for (i=0; i<16; i++) - idbuf[i] = inb(GAPSPCI_REGS+i); + idbuf[i] = ctrl_inb(GAPSPCI_REGS+i); if (strncmp(idbuf, "GAPSPCI_BRIDGE_2", 16)) return -ENODEV; - outl(0x5a14a501, GAPSPCI_REGS+0x18); + ctrl_outl(0x5a14a501, GAPSPCI_REGS+0x18); for (i=0; i<1000000; i++) ; - if (inl(GAPSPCI_REGS+0x18) != 1) + if (ctrl_inl(GAPSPCI_REGS+0x18) != 1) return -EINVAL; - outl(0x01000000, GAPSPCI_REGS+0x20); - outl(0x01000000, GAPSPCI_REGS+0x24); + ctrl_outl(0x01000000, GAPSPCI_REGS+0x20); + ctrl_outl(0x01000000, GAPSPCI_REGS+0x24); - outl(GAPSPCI_DMA_BASE, GAPSPCI_REGS+0x28); - outl(GAPSPCI_DMA_BASE+GAPSPCI_DMA_SIZE, GAPSPCI_REGS+0x2c); + ctrl_outl(GAPSPCI_DMA_BASE, GAPSPCI_REGS+0x28); + ctrl_outl(GAPSPCI_DMA_BASE+GAPSPCI_DMA_SIZE, GAPSPCI_REGS+0x2c); - outl(1, GAPSPCI_REGS+0x14); - outl(1, GAPSPCI_REGS+0x34); + ctrl_outl(1, GAPSPCI_REGS+0x14); + ctrl_outl(1, GAPSPCI_REGS+0x34); /* Setting Broadband Adapter */ - outw(0xf900, GAPSPCI_BBA_CONFIG+0x06); - outl(0x00000000, GAPSPCI_BBA_CONFIG+0x30); - outb(0x00, GAPSPCI_BBA_CONFIG+0x3c); - outb(0xf0, GAPSPCI_BBA_CONFIG+0x0d); - outw(0x0006, GAPSPCI_BBA_CONFIG+0x04); - outl(0x00002001, GAPSPCI_BBA_CONFIG+0x10); - outl(0x01000000, GAPSPCI_BBA_CONFIG+0x14); + ctrl_outw(0xf900, GAPSPCI_BBA_CONFIG+0x06); + ctrl_outl(0x00000000, GAPSPCI_BBA_CONFIG+0x30); + ctrl_outb(0x00, GAPSPCI_BBA_CONFIG+0x3c); + ctrl_outb(0xf0, GAPSPCI_BBA_CONFIG+0x0d); + ctrl_outw(0x0006, GAPSPCI_BBA_CONFIG+0x04); + ctrl_outl(0x00002001, GAPSPCI_BBA_CONFIG+0x10); + ctrl_outl(0x01000000, GAPSPCI_BBA_CONFIG+0x14); return 0; } diff --git a/arch/sh/drivers/pci/ops-rts7751r2d.c b/arch/sh/drivers/pci/ops-rts7751r2d.c index ec8430c8d2d1..b3fa3e2ef184 100644 --- a/arch/sh/drivers/pci/ops-rts7751r2d.c +++ b/arch/sh/drivers/pci/ops-rts7751r2d.c @@ -33,7 +33,7 @@ int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin) static struct resource sh7751_io_resource = { .name = "SH7751_IO", .start = 0x4000, - .end = 0x4000 + SH7751_PCI_IO_SIZE - 1, + .end = SH7751_PCI_IO_SIZE - 1, .flags = IORESOURCE_IO }; @@ -68,6 +68,7 @@ static struct sh4_pci_address_map sh7751_pci_map = { int __init pcibios_init_platform(void) { + __set_io_port_base(SH7751_PCI_IO_BASE); return sh7751_pcic_init(&sh7751_pci_map); } diff --git a/arch/sh/drivers/pci/pci-sh4.h b/arch/sh/drivers/pci/pci-sh4.h index 4925c79ea959..07e29506080f 100644 --- a/arch/sh/drivers/pci/pci-sh4.h +++ b/arch/sh/drivers/pci/pci-sh4.h @@ -172,11 +172,11 @@ struct sh4_pci_address_map { static inline void pci_write_reg(unsigned long val, unsigned long reg) { - outl(val, PCI_REG(reg)); + ctrl_outl(val, PCI_REG(reg)); } static inline unsigned long pci_read_reg(unsigned long reg) { - return inl(PCI_REG(reg)); + return ctrl_inl(PCI_REG(reg)); } #endif /* __PCI_SH4_H */ diff --git a/arch/sh/drivers/pci/pci-sh7751.c b/arch/sh/drivers/pci/pci-sh7751.c index 1aca7fe5783b..3065eb184f01 100644 --- a/arch/sh/drivers/pci/pci-sh7751.c +++ b/arch/sh/drivers/pci/pci-sh7751.c @@ -58,7 +58,7 @@ static int __init __area_sdram_check(unsigned int area) { u32 word; - word = inl(SH7751_BCR1); + word = ctrl_inl(SH7751_BCR1); /* check BCR for SDRAM in area */ if (((word >> area) & 1) == 0) { printk("PCI: Area %d is not configured for SDRAM. BCR1=0x%x\n", @@ -67,7 +67,7 @@ static int __init __area_sdram_check(unsigned int area) } pci_write_reg(word, SH4_PCIBCR1); - word = (u16)inw(SH7751_BCR2); + word = (u16)ctrl_inw(SH7751_BCR2); /* check BCR2 for 32bit SDRAM interface*/ if (((word >> (area << 1)) & 0x3) != 0x3) { printk("PCI: Area %d is not 32 bit SDRAM. BCR2=0x%x\n", @@ -85,9 +85,9 @@ int __init sh7751_pcic_init(struct sh4_pci_address_map *map) u32 word; /* Set the BCR's to enable PCI access */ - reg = inl(SH7751_BCR1); + reg = ctrl_inl(SH7751_BCR1); reg |= 0x80000; - outl(reg, SH7751_BCR1); + ctrl_outl(reg, SH7751_BCR1); /* Turn the clocks back on (not done in reset)*/ pci_write_reg(0, SH4_PCICLKR); @@ -179,13 +179,13 @@ int __init sh7751_pcic_init(struct sh4_pci_address_map *map) return 0; /* configure the wait control registers */ - word = inl(SH7751_WCR1); + word = ctrl_inl(SH7751_WCR1); pci_write_reg(word, SH4_PCIWCR1); - word = inl(SH7751_WCR2); + word = ctrl_inl(SH7751_WCR2); pci_write_reg(word, SH4_PCIWCR2); - word = inl(SH7751_WCR3); + word = ctrl_inl(SH7751_WCR3); pci_write_reg(word, SH4_PCIWCR3); - word = inl(SH7751_MCR); + word = ctrl_inl(SH7751_MCR); pci_write_reg(word, SH4_PCIMCR); /* NOTE: I'm ignoring the PCI error IRQs for now.. diff --git a/arch/sh/drivers/pci/pci-sh7780.c b/arch/sh/drivers/pci/pci-sh7780.c index 7d797f4de5e7..b2a2bfa3c1bd 100644 --- a/arch/sh/drivers/pci/pci-sh7780.c +++ b/arch/sh/drivers/pci/pci-sh7780.c @@ -52,7 +52,7 @@ static int __init sh7780_pci_init(void) pr_debug("PCI: Starting intialization.\n"); - outl(0x00000001, SH7780_PCI_VCR2); /* Enable PCIC */ + ctrl_outl(0x00000001, SH7780_PCI_VCR2); /* Enable PCIC */ /* check for SH7780/SH7780R hardware */ id = pci_read_reg(SH7780_PCIVID); diff --git a/arch/sh/kernel/Makefile_32 b/arch/sh/kernel/Makefile_32 index c89289831053..62bf373266f7 100644 --- a/arch/sh/kernel/Makefile_32 +++ b/arch/sh/kernel/Makefile_32 @@ -22,5 +22,6 @@ obj-$(CONFIG_CRASH_DUMP) += crash_dump.o obj-$(CONFIG_PM) += pm.o obj-$(CONFIG_STACKTRACE) += stacktrace.o obj-$(CONFIG_BINFMT_ELF) += dump_task.o +obj-$(CONFIG_IO_TRAPPED) += io_trapped.o EXTRA_CFLAGS += -Werror diff --git a/arch/sh/kernel/Makefile_64 b/arch/sh/kernel/Makefile_64 index 1ef21cc087f3..e01283d49cbf 100644 --- a/arch/sh/kernel/Makefile_64 +++ b/arch/sh/kernel/Makefile_64 @@ -18,5 +18,6 @@ obj-$(CONFIG_CRASH_DUMP) += crash_dump.o obj-$(CONFIG_PM) += pm.o obj-$(CONFIG_STACKTRACE) += stacktrace.o obj-$(CONFIG_BINFMT_ELF) += dump_task.o +obj-$(CONFIG_IO_TRAPPED) += io_trapped.o EXTRA_CFLAGS += -Werror diff --git a/arch/sh/kernel/cpu/irq/Makefile b/arch/sh/kernel/cpu/irq/Makefile index cc1836e47a5d..462a8f6dfee2 100644 --- a/arch/sh/kernel/cpu/irq/Makefile +++ b/arch/sh/kernel/cpu/irq/Makefile @@ -6,4 +6,3 @@ obj-y += intc.o obj-$(CONFIG_SUPERH32) += imask.o obj-$(CONFIG_CPU_SH5) += intc-sh5.o obj-$(CONFIG_CPU_HAS_IPR_IRQ) += ipr.o -obj-$(CONFIG_CPU_HAS_MASKREG_IRQ) += maskreg.o diff --git a/arch/sh/kernel/cpu/irq/intc-sh5.c b/arch/sh/kernel/cpu/irq/intc-sh5.c index 43ee7a9a4f0b..d6e0e2bdaad5 100644 --- a/arch/sh/kernel/cpu/irq/intc-sh5.c +++ b/arch/sh/kernel/cpu/irq/intc-sh5.c @@ -75,21 +75,6 @@ int intc_evt_to_irq[(0xE20/0x20)+1] = { -1, -1 /* 0xE00 - 0xE20 */ }; -/* - * Opposite mapper. - */ -static int IRQ_to_vectorN[NR_INTC_IRQS] = { - 0x12, 0x15, 0x18, 0x1B, 0x40, 0x41, 0x42, 0x43, /* 0- 7 */ - -1, -1, -1, -1, 0x50, 0x51, 0x52, 0x53, /* 8-15 */ - 0x54, 0x55, 0x32, 0x33, 0x34, 0x35, 0x36, -1, /* 16-23 */ - -1, -1, -1, -1, -1, -1, -1, -1, /* 24-31 */ - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x38, /* 32-39 */ - 0x39, 0x3A, 0x3B, -1, -1, -1, -1, -1, /* 40-47 */ - -1, -1, -1, -1, -1, -1, -1, -1, /* 48-55 */ - -1, -1, -1, -1, -1, -1, -1, 0x2B, /* 56-63 */ - -}; - static unsigned long intc_virt; static unsigned int startup_intc_irq(unsigned int irq); @@ -176,6 +161,18 @@ void make_intc_irq(unsigned int irq) } #if defined(CONFIG_PROC_FS) && defined(CONFIG_SYSCTL) +static int IRQ_to_vectorN[NR_INTC_IRQS] = { + 0x12, 0x15, 0x18, 0x1B, 0x40, 0x41, 0x42, 0x43, /* 0- 7 */ + -1, -1, -1, -1, 0x50, 0x51, 0x52, 0x53, /* 8-15 */ + 0x54, 0x55, 0x32, 0x33, 0x34, 0x35, 0x36, -1, /* 16-23 */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 24-31 */ + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x38, /* 32-39 */ + 0x39, 0x3A, 0x3B, -1, -1, -1, -1, -1, /* 40-47 */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 48-55 */ + -1, -1, -1, -1, -1, -1, -1, 0x2B, /* 56-63 */ + +}; + int intc_irq_describe(char* p, int irq) { if (irq < NR_INTC_IRQS) diff --git a/arch/sh/kernel/cpu/irq/maskreg.c b/arch/sh/kernel/cpu/irq/maskreg.c deleted file mode 100644 index 978992e367a5..000000000000 --- a/arch/sh/kernel/cpu/irq/maskreg.c +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Interrupt handling for Simple external interrupt mask register - * - * Copyright (C) 2001 A&D Co., Ltd. - * - * This is for the machine which have single 16 bit register - * for masking external IRQ individually. - * Each bit of the register is for masking each interrupt. - * - * This file may be copied or modified under the terms of the GNU - * General Public License. See linux/COPYING for more information. - */ -#include -#include -#include -#include -#include - -/* address of external interrupt mask register */ -unsigned long irq_mask_register; - -/* forward declaration */ -static unsigned int startup_maskreg_irq(unsigned int irq); -static void shutdown_maskreg_irq(unsigned int irq); -static void enable_maskreg_irq(unsigned int irq); -static void disable_maskreg_irq(unsigned int irq); -static void mask_and_ack_maskreg(unsigned int); -static void end_maskreg_irq(unsigned int irq); - -/* hw_interrupt_type */ -static struct hw_interrupt_type maskreg_irq_type = { - .typename = "Mask Register", - .startup = startup_maskreg_irq, - .shutdown = shutdown_maskreg_irq, - .enable = enable_maskreg_irq, - .disable = disable_maskreg_irq, - .ack = mask_and_ack_maskreg, - .end = end_maskreg_irq -}; - -/* actual implementation */ -static unsigned int startup_maskreg_irq(unsigned int irq) -{ - enable_maskreg_irq(irq); - return 0; /* never anything pending */ -} - -static void shutdown_maskreg_irq(unsigned int irq) -{ - disable_maskreg_irq(irq); -} - -static void disable_maskreg_irq(unsigned int irq) -{ - unsigned short val, mask = 0x01 << irq; - - BUG_ON(!irq_mask_register); - - /* Set "irq"th bit */ - val = ctrl_inw(irq_mask_register); - val |= mask; - ctrl_outw(val, irq_mask_register); -} - -static void enable_maskreg_irq(unsigned int irq) -{ - unsigned short val, mask = ~(0x01 << irq); - - BUG_ON(!irq_mask_register); - - /* Clear "irq"th bit */ - val = ctrl_inw(irq_mask_register); - val &= mask; - ctrl_outw(val, irq_mask_register); -} - -static void mask_and_ack_maskreg(unsigned int irq) -{ - disable_maskreg_irq(irq); -} - -static void end_maskreg_irq(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) - enable_maskreg_irq(irq); -} - -void make_maskreg_irq(unsigned int irq) -{ - disable_irq_nosync(irq); - irq_desc[irq].handler = &maskreg_irq_type; - disable_maskreg_irq(irq); -} diff --git a/arch/sh/kernel/cpu/sh4/probe.c b/arch/sh/kernel/cpu/sh4/probe.c index f2b9238cda04..9e89984c4f1d 100644 --- a/arch/sh/kernel/cpu/sh4/probe.c +++ b/arch/sh/kernel/cpu/sh4/probe.c @@ -126,12 +126,18 @@ int __init detect_cpu_and_cache_system(void) CPU_HAS_LLSC; break; case 0x3008: - if (prr == 0xa0) { + if (prr == 0xa0 || prr == 0xa1) { boot_cpu_data.type = CPU_SH7722; boot_cpu_data.icache.ways = 4; boot_cpu_data.dcache.ways = 4; boot_cpu_data.flags |= CPU_HAS_LLSC; } + else if (prr == 0x70) { + boot_cpu_data.type = CPU_SH7366; + boot_cpu_data.icache.ways = 4; + boot_cpu_data.dcache.ways = 4; + boot_cpu_data.flags |= CPU_HAS_LLSC; + } break; case 0x4000: /* 1st cut */ case 0x4001: /* 2nd cut */ diff --git a/arch/sh/kernel/cpu/sh4a/Makefile b/arch/sh/kernel/cpu/sh4a/Makefile index 08ac6387bf17..5d890ac8e793 100644 --- a/arch/sh/kernel/cpu/sh4a/Makefile +++ b/arch/sh/kernel/cpu/sh4a/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_CPU_SUBTYPE_SH7780) += setup-sh7780.o obj-$(CONFIG_CPU_SUBTYPE_SH7785) += setup-sh7785.o obj-$(CONFIG_CPU_SUBTYPE_SH7343) += setup-sh7343.o obj-$(CONFIG_CPU_SUBTYPE_SH7722) += setup-sh7722.o +obj-$(CONFIG_CPU_SUBTYPE_SH7366) += setup-sh7366.o obj-$(CONFIG_CPU_SUBTYPE_SHX3) += setup-shx3.o # SMP setup @@ -21,6 +22,7 @@ clock-$(CONFIG_CPU_SUBTYPE_SH7780) := clock-sh7780.o clock-$(CONFIG_CPU_SUBTYPE_SH7785) := clock-sh7785.o clock-$(CONFIG_CPU_SUBTYPE_SH7343) := clock-sh7343.o clock-$(CONFIG_CPU_SUBTYPE_SH7722) := clock-sh7722.o +clock-$(CONFIG_CPU_SUBTYPE_SH7366) := clock-sh7722.o clock-$(CONFIG_CPU_SUBTYPE_SHX3) := clock-shx3.o obj-y += $(clock-y) diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c index a0fd8bb21f7c..299138ebe160 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c @@ -1,7 +1,7 @@ /* * arch/sh/kernel/cpu/sh4a/clock-sh7722.c * - * SH7722 support for the clock framework + * SH7722 & SH7366 support for the clock framework * * Copyright (c) 2006-2007 Nomad Global Solutions Inc * Based on code for sh7343 by Paul Mundt @@ -417,15 +417,19 @@ static int sh7722_siu_which(struct clk *clk) return 0; if (!strcmp(clk->name, "siu_b_clk")) return 1; +#if defined(CONFIG_CPU_SUBTYPE_SH7722) if (!strcmp(clk->name, "irda_clk")) return 2; +#endif return -EINVAL; } static unsigned long sh7722_siu_regs[] = { [0] = SCLKACR, [1] = SCLKBCR, +#if defined(CONFIG_CPU_SUBTYPE_SH7722) [2] = IrDACLKCR, +#endif }; static int sh7722_siu_start_stop(struct clk *clk, int enable) @@ -571,10 +575,12 @@ static struct clk sh7722_siu_b_clock = { .ops = &sh7722_siu_clk_ops, }; +#if defined(CONFIG_CPU_SUBTYPE_SH7722) static struct clk sh7722_irda_clock = { .name = "irda_clk", .ops = &sh7722_siu_clk_ops, }; +#endif static struct clk sh7722_video_clock = { .name = "video_clk", @@ -588,7 +594,9 @@ static struct clk *sh7722_clocks[] = { &sh7722_sdram_clock, &sh7722_siu_a_clock, &sh7722_siu_b_clock, +#if defined(CONFIG_CPU_SUBTYPE_SH7722) &sh7722_irda_clock, +#endif &sh7722_video_clock, }; diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7366.c b/arch/sh/kernel/cpu/sh4a/setup-sh7366.c new file mode 100644 index 000000000000..967e8b69a2f8 --- /dev/null +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7366.c @@ -0,0 +1,177 @@ +/* + * SH7366 Setup + * + * Copyright (C) 2008 Renesas Solutions + * + * Based on linux/arch/sh/kernel/cpu/sh4a/setup-sh7722.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 + +static struct plat_sci_port sci_platform_data[] = { + { + .mapbase = 0xffe00000, + .flags = UPF_BOOT_AUTOCONF, + .type = PORT_SCIF, + .irqs = { 80, 80, 80, 80 }, + }, { + .flags = 0, + } +}; + +static struct platform_device sci_device = { + .name = "sh-sci", + .id = -1, + .dev = { + .platform_data = sci_platform_data, + }, +}; + +static struct platform_device *sh7366_devices[] __initdata = { + &sci_device, +}; + +static int __init sh7366_devices_setup(void) +{ + return platform_add_devices(sh7366_devices, + ARRAY_SIZE(sh7366_devices)); +} +__initcall(sh7366_devices_setup); + +enum { + UNUSED=0, + + /* interrupt sources */ + IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7, + ICB, + DMAC0, DMAC1, DMAC2, DMAC3, + VIO_CEUI, VIO_BEUI, VIO_VEUI, VOU, + MFI, VPU, USB, + MMC_MMC1I, MMC_MMC2I, MMC_MMC3I, + DMAC4, DMAC5, DMAC_DADERR, + SCIF, SCIFA1, SCIFA2, + DENC, MSIOF, + FLCTL_FLSTEI, FLCTL_FLENDI, FLCTL_FLTREQ0I, FLCTL_FLTREQ1I, + I2C_ALI, I2C_TACKI, I2C_WAITI, I2C_DTEI, + SDHI0, SDHI1, SDHI2, SDHI3, + CMT, TSIF, SIU, + TMU0, TMU1, TMU2, + VEU2, LCDC, + + /* interrupt groups */ + + DMAC0123, VIOVOU, MMC, DMAC45, FLCTL, I2C, SDHI, +}; + +static struct intc_vect vectors[] __initdata = { + INTC_VECT(IRQ0, 0x600), INTC_VECT(IRQ1, 0x620), + INTC_VECT(IRQ2, 0x640), INTC_VECT(IRQ3, 0x660), + INTC_VECT(IRQ4, 0x680), INTC_VECT(IRQ5, 0x6a0), + INTC_VECT(IRQ6, 0x6c0), INTC_VECT(IRQ7, 0x6e0), + INTC_VECT(ICB, 0x700), + INTC_VECT(DMAC0, 0x800), INTC_VECT(DMAC1, 0x820), + INTC_VECT(DMAC2, 0x840), INTC_VECT(DMAC3, 0x860), + INTC_VECT(VIO_CEUI, 0x880), INTC_VECT(VIO_BEUI, 0x8a0), + INTC_VECT(VIO_VEUI, 0x8c0), INTC_VECT(VOU, 0x8e0), + INTC_VECT(MFI, 0x900), INTC_VECT(VPU, 0x980), INTC_VECT(USB, 0xa20), + INTC_VECT(MMC_MMC1I, 0xb00), INTC_VECT(MMC_MMC2I, 0xb20), + INTC_VECT(MMC_MMC3I, 0xb40), + INTC_VECT(DMAC4, 0xb80), INTC_VECT(DMAC5, 0xba0), + INTC_VECT(DMAC_DADERR, 0xbc0), + INTC_VECT(SCIF, 0xc00), INTC_VECT(SCIFA1, 0xc20), + INTC_VECT(SCIFA2, 0xc40), + INTC_VECT(DENC, 0xc60), INTC_VECT(MSIOF, 0xc80), + INTC_VECT(FLCTL_FLSTEI, 0xd80), INTC_VECT(FLCTL_FLENDI, 0xda0), + INTC_VECT(FLCTL_FLTREQ0I, 0xdc0), INTC_VECT(FLCTL_FLTREQ1I, 0xde0), + INTC_VECT(I2C_ALI, 0xe00), INTC_VECT(I2C_TACKI, 0xe20), + INTC_VECT(I2C_WAITI, 0xe40), INTC_VECT(I2C_DTEI, 0xe60), + INTC_VECT(SDHI0, 0xe80), INTC_VECT(SDHI1, 0xea0), + INTC_VECT(SDHI2, 0xec0), INTC_VECT(SDHI3, 0xee0), + INTC_VECT(CMT, 0xf00), INTC_VECT(TSIF, 0xf20), + INTC_VECT(SIU, 0xf80), + INTC_VECT(TMU0, 0x400), INTC_VECT(TMU1, 0x420), + INTC_VECT(TMU2, 0x440), + INTC_VECT(VEU2, 0x580), INTC_VECT(LCDC, 0x580), +}; + +static struct intc_group groups[] __initdata = { + INTC_GROUP(DMAC0123, DMAC0, DMAC1, DMAC2, DMAC3), + INTC_GROUP(VIOVOU, VIO_CEUI, VIO_BEUI, VIO_VEUI, VOU), + INTC_GROUP(MMC, MMC_MMC1I, MMC_MMC2I, MMC_MMC3I), + INTC_GROUP(DMAC45, DMAC4, DMAC5, DMAC_DADERR), + INTC_GROUP(FLCTL, FLCTL_FLSTEI, FLCTL_FLENDI, + FLCTL_FLTREQ0I, FLCTL_FLTREQ1I), + INTC_GROUP(I2C, I2C_ALI, I2C_TACKI, I2C_WAITI, I2C_DTEI), + INTC_GROUP(SDHI, SDHI0, SDHI1, SDHI2, SDHI3), +}; + +static struct intc_mask_reg mask_registers[] __initdata = { + { 0xa4080080, 0xa40800c0, 8, /* IMR0 / IMCR0 */ + { } }, + { 0xa4080084, 0xa40800c4, 8, /* IMR1 / IMCR1 */ + { VOU, VIO_VEUI, VIO_BEUI, VIO_CEUI, DMAC3, DMAC2, DMAC1, DMAC0 } }, + { 0xa4080088, 0xa40800c8, 8, /* IMR2 / IMCR2 */ + { 0, 0, 0, VPU, 0, 0, 0, MFI } }, + { 0xa408008c, 0xa40800cc, 8, /* IMR3 / IMCR3 */ + { 0, 0, 0, ICB } }, + { 0xa4080090, 0xa40800d0, 8, /* IMR4 / IMCR4 */ + { 0, TMU2, TMU1, TMU0, VEU2, 0, 0, LCDC } }, + { 0xa4080094, 0xa40800d4, 8, /* IMR5 / IMCR5 */ + { 0, DMAC_DADERR, DMAC5, DMAC4, DENC, SCIFA2, SCIFA1, SCIF } }, + { 0xa4080098, 0xa40800d8, 8, /* IMR6 / IMCR6 */ + { 0, 0, 0, 0, 0, 0, 0, MSIOF } }, + { 0xa408009c, 0xa40800dc, 8, /* IMR7 / IMCR7 */ + { I2C_DTEI, I2C_WAITI, I2C_TACKI, I2C_ALI, + FLCTL_FLTREQ1I, FLCTL_FLTREQ0I, FLCTL_FLENDI, FLCTL_FLSTEI } }, + { 0xa40800a0, 0xa40800e0, 8, /* IMR8 / IMCR8 */ + { SDHI3, SDHI2, SDHI1, SDHI0, 0, 0, 0, SIU } }, + { 0xa40800a4, 0xa40800e4, 8, /* IMR9 / IMCR9 */ + { 0, 0, 0, CMT, 0, USB, } }, + { 0xa40800a8, 0xa40800e8, 8, /* IMR10 / IMCR10 */ + { 0, MMC_MMC3I, MMC_MMC2I, MMC_MMC1I } }, + { 0xa40800ac, 0xa40800ec, 8, /* IMR11 / IMCR11 */ + { 0, 0, 0, 0, 0, 0, 0, TSIF } }, + { 0xa4140044, 0xa4140064, 8, /* INTMSK00 / INTMSKCLR00 */ + { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } }, +}; + +static struct intc_prio_reg prio_registers[] __initdata = { + { 0xa4080000, 0, 16, 4, /* IPRA */ { TMU0, TMU1, TMU2 } }, + { 0xa4080004, 0, 16, 4, /* IPRB */ { VEU2, LCDC, ICB } }, + { 0xa4080008, 0, 16, 4, /* IPRC */ { } }, + { 0xa408000c, 0, 16, 4, /* IPRD */ { } }, + { 0xa4080010, 0, 16, 4, /* IPRE */ { DMAC0123, VIOVOU, MFI, VPU } }, + { 0xa4080014, 0, 16, 4, /* IPRF */ { 0, DMAC45, USB, CMT } }, + { 0xa4080018, 0, 16, 4, /* IPRG */ { SCIF, SCIFA1, SCIFA2, DENC } }, + { 0xa408001c, 0, 16, 4, /* IPRH */ { MSIOF, 0, FLCTL, I2C } }, + { 0xa4080020, 0, 16, 4, /* IPRI */ { 0, 0, TSIF, } }, + { 0xa4080024, 0, 16, 4, /* IPRJ */ { 0, 0, SIU } }, + { 0xa4080028, 0, 16, 4, /* IPRK */ { 0, MMC, 0, SDHI } }, + { 0xa408002c, 0, 16, 4, /* IPRL */ { } }, + { 0xa4140010, 0, 32, 4, /* INTPRI00 */ + { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } }, +}; + +static struct intc_sense_reg sense_registers[] __initdata = { + { 0xa414001c, 16, 2, /* ICR1 */ + { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } }, +}; + +static DECLARE_INTC_DESC(intc_desc, "sh7366", vectors, groups, + mask_registers, prio_registers, sense_registers); + +void __init plat_irq_setup(void) +{ + register_intc_controller(&intc_desc); +} + +void __init plat_mem_setup(void) +{ + /* TODO: Register Node 1 */ +} diff --git a/arch/sh/kernel/cpu/sh5/probe.c b/arch/sh/kernel/cpu/sh5/probe.c index 15d167fd0ae7..31f8cb0f6374 100644 --- a/arch/sh/kernel/cpu/sh5/probe.c +++ b/arch/sh/kernel/cpu/sh5/probe.c @@ -20,19 +20,18 @@ int __init detect_cpu_and_cache_system(void) { unsigned long long cir; - /* Do peeks in real mode to avoid having to set up a mapping for the - WPC registers. On SH5-101 cut2, such a mapping would be exposed to - an address translation erratum which would make it hard to set up - correctly. */ + /* + * Do peeks in real mode to avoid having to set up a mapping for + * the WPC registers. On SH5-101 cut2, such a mapping would be + * exposed to an address translation erratum which would make it + * hard to set up correctly. + */ cir = peek_real_address_q(0x0d000008); - if ((cir & 0xffff) == 0x5103) { + if ((cir & 0xffff) == 0x5103) boot_cpu_data.type = CPU_SH5_103; - } else if (((cir >> 32) & 0xffff) == 0x51e2) { + else if (((cir >> 32) & 0xffff) == 0x51e2) /* CPU.VCR aliased at CIR address on SH5-101 */ boot_cpu_data.type = CPU_SH5_101; - } else { - boot_cpu_data.type = CPU_SH_NONE; - } /* * First, setup some sane values for the I-cache. @@ -40,37 +39,33 @@ int __init detect_cpu_and_cache_system(void) boot_cpu_data.icache.ways = 4; boot_cpu_data.icache.sets = 256; boot_cpu_data.icache.linesz = L1_CACHE_BYTES; - -#if 0 - /* - * FIXME: This can probably be cleaned up a bit as well.. for example, - * do we really need the way shift _and_ the way_step_shift ?? Judging - * by the existing code, I would guess no.. is there any valid reason - * why we need to be tracking this around? - */ - boot_cpu_data.icache.way_shift = 13; + boot_cpu_data.icache.way_incr = (1 << 13); boot_cpu_data.icache.entry_shift = 5; - boot_cpu_data.icache.set_shift = 4; - boot_cpu_data.icache.way_step_shift = 16; - boot_cpu_data.icache.asid_shift = 2; - - /* - * way offset = cache size / associativity, so just don't factor in - * associativity in the first place.. - */ - boot_cpu_data.icache.way_ofs = boot_cpu_data.icache.sets * - boot_cpu_data.icache.linesz; - - boot_cpu_data.icache.asid_mask = 0x3fc; - boot_cpu_data.icache.idx_mask = 0x1fe0; - boot_cpu_data.icache.epn_mask = 0xffffe000; -#endif - + boot_cpu_data.icache.way_size = boot_cpu_data.icache.sets * + boot_cpu_data.icache.linesz; + boot_cpu_data.icache.entry_mask = 0x1fe0; boot_cpu_data.icache.flags = 0; - /* A trivial starting point.. */ - memcpy(&boot_cpu_data.dcache, - &boot_cpu_data.icache, sizeof(struct cache_info)); + /* + * Next, setup some sane values for the D-cache. + * + * On the SH5, these are pretty consistent with the I-cache settings, + * so we just copy over the existing definitions.. these can be fixed + * up later, especially if we add runtime CPU probing. + * + * Though in the meantime it saves us from having to duplicate all of + * the above definitions.. + */ + boot_cpu_data.dcache = boot_cpu_data.icache; + + /* + * Setup any cache-related flags here + */ +#if defined(CONFIG_CACHE_WRITETHROUGH) + set_bit(SH_CACHE_MODE_WT, &(boot_cpu_data.dcache.flags)); +#elif defined(CONFIG_CACHE_WRITEBACK) + set_bit(SH_CACHE_MODE_WB, &(boot_cpu_data.dcache.flags)); +#endif return 0; } diff --git a/arch/sh/kernel/io.c b/arch/sh/kernel/io.c index 71c9fde2fd90..2b8991229900 100644 --- a/arch/sh/kernel/io.c +++ b/arch/sh/kernel/io.c @@ -63,7 +63,13 @@ EXPORT_SYMBOL(memset_io); void __iomem *ioport_map(unsigned long port, unsigned int nr) { - return sh_mv.mv_ioport_map(port, nr); + void __iomem *ret; + + ret = __ioport_map_trapped(port, nr); + if (ret) + return ret; + + return __ioport_map(port, nr); } EXPORT_SYMBOL(ioport_map); diff --git a/arch/sh/kernel/io_generic.c b/arch/sh/kernel/io_generic.c index 771ea4230441..db769449f5a7 100644 --- a/arch/sh/kernel/io_generic.c +++ b/arch/sh/kernel/io_generic.c @@ -33,17 +33,17 @@ static inline void delay(void) u8 generic_inb(unsigned long port) { - return ctrl_inb((unsigned long __force)ioport_map(port, 1)); + return ctrl_inb((unsigned long __force)__ioport_map(port, 1)); } u16 generic_inw(unsigned long port) { - return ctrl_inw((unsigned long __force)ioport_map(port, 2)); + return ctrl_inw((unsigned long __force)__ioport_map(port, 2)); } u32 generic_inl(unsigned long port) { - return ctrl_inl((unsigned long __force)ioport_map(port, 4)); + return ctrl_inl((unsigned long __force)__ioport_map(port, 4)); } u8 generic_inb_p(unsigned long port) @@ -81,7 +81,7 @@ void generic_insb(unsigned long port, void *dst, unsigned long count) volatile u8 *port_addr; u8 *buf = dst; - port_addr = (volatile u8 *)ioport_map(port, 1); + port_addr = (volatile u8 *)__ioport_map(port, 1); while (count--) *buf++ = *port_addr; } @@ -91,7 +91,7 @@ void generic_insw(unsigned long port, void *dst, unsigned long count) volatile u16 *port_addr; u16 *buf = dst; - port_addr = (volatile u16 *)ioport_map(port, 2); + port_addr = (volatile u16 *)__ioport_map(port, 2); while (count--) *buf++ = *port_addr; @@ -103,7 +103,7 @@ void generic_insl(unsigned long port, void *dst, unsigned long count) volatile u32 *port_addr; u32 *buf = dst; - port_addr = (volatile u32 *)ioport_map(port, 4); + port_addr = (volatile u32 *)__ioport_map(port, 4); while (count--) *buf++ = *port_addr; @@ -112,17 +112,17 @@ void generic_insl(unsigned long port, void *dst, unsigned long count) void generic_outb(u8 b, unsigned long port) { - ctrl_outb(b, (unsigned long __force)ioport_map(port, 1)); + ctrl_outb(b, (unsigned long __force)__ioport_map(port, 1)); } void generic_outw(u16 b, unsigned long port) { - ctrl_outw(b, (unsigned long __force)ioport_map(port, 2)); + ctrl_outw(b, (unsigned long __force)__ioport_map(port, 2)); } void generic_outl(u32 b, unsigned long port) { - ctrl_outl(b, (unsigned long __force)ioport_map(port, 4)); + ctrl_outl(b, (unsigned long __force)__ioport_map(port, 4)); } void generic_outb_p(u8 b, unsigned long port) @@ -153,7 +153,7 @@ void generic_outsb(unsigned long port, const void *src, unsigned long count) volatile u8 *port_addr; const u8 *buf = src; - port_addr = (volatile u8 __force *)ioport_map(port, 1); + port_addr = (volatile u8 __force *)__ioport_map(port, 1); while (count--) *port_addr = *buf++; @@ -164,7 +164,7 @@ void generic_outsw(unsigned long port, const void *src, unsigned long count) volatile u16 *port_addr; const u16 *buf = src; - port_addr = (volatile u16 __force *)ioport_map(port, 2); + port_addr = (volatile u16 __force *)__ioport_map(port, 2); while (count--) *port_addr = *buf++; @@ -177,7 +177,7 @@ void generic_outsl(unsigned long port, const void *src, unsigned long count) volatile u32 *port_addr; const u32 *buf = src; - port_addr = (volatile u32 __force *)ioport_map(port, 4); + port_addr = (volatile u32 __force *)__ioport_map(port, 4); while (count--) *port_addr = *buf++; diff --git a/arch/sh/kernel/io_trapped.c b/arch/sh/kernel/io_trapped.c new file mode 100644 index 000000000000..86a665d92201 --- /dev/null +++ b/arch/sh/kernel/io_trapped.c @@ -0,0 +1,276 @@ +/* + * Trapped io support + * + * Copyright (C) 2008 Magnus Damm + * + * Intercept io operations by trapping. + * + * 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 + +#define TRAPPED_PAGES_MAX 16 + +#ifdef CONFIG_HAS_IOPORT +LIST_HEAD(trapped_io); +EXPORT_SYMBOL_GPL(trapped_io); +#endif +#ifdef CONFIG_HAS_IOMEM +LIST_HEAD(trapped_mem); +EXPORT_SYMBOL_GPL(trapped_mem); +#endif +static DEFINE_SPINLOCK(trapped_lock); + +int __init register_trapped_io(struct trapped_io *tiop) +{ + struct resource *res; + unsigned long len = 0, flags = 0; + struct page *pages[TRAPPED_PAGES_MAX]; + int k, n; + + /* structure must be page aligned */ + if ((unsigned long)tiop & (PAGE_SIZE - 1)) + goto bad; + + for (k = 0; k < tiop->num_resources; k++) { + res = tiop->resource + k; + len += roundup((res->end - res->start) + 1, PAGE_SIZE); + flags |= res->flags; + } + + /* support IORESOURCE_IO _or_ MEM, not both */ + if (hweight_long(flags) != 1) + goto bad; + + n = len >> PAGE_SHIFT; + + if (n >= TRAPPED_PAGES_MAX) + goto bad; + + for (k = 0; k < n; k++) + pages[k] = virt_to_page(tiop); + + tiop->virt_base = vmap(pages, n, VM_MAP, PAGE_NONE); + if (!tiop->virt_base) + goto bad; + + len = 0; + for (k = 0; k < tiop->num_resources; k++) { + res = tiop->resource + k; + pr_info("trapped io 0x%08lx overrides %s 0x%08lx\n", + (unsigned long)(tiop->virt_base + len), + res->flags & IORESOURCE_IO ? "io" : "mmio", + (unsigned long)res->start); + len += roundup((res->end - res->start) + 1, PAGE_SIZE); + } + + tiop->magic = IO_TRAPPED_MAGIC; + INIT_LIST_HEAD(&tiop->list); + spin_lock_irq(&trapped_lock); + if (flags & IORESOURCE_IO) + list_add(&tiop->list, &trapped_io); + if (flags & IORESOURCE_MEM) + list_add(&tiop->list, &trapped_mem); + spin_unlock_irq(&trapped_lock); + + return 0; + bad: + pr_warning("unable to install trapped io filter\n"); + return -1; +} +EXPORT_SYMBOL_GPL(register_trapped_io); + +void __iomem *match_trapped_io_handler(struct list_head *list, + unsigned long offset, + unsigned long size) +{ + unsigned long voffs; + struct trapped_io *tiop; + struct resource *res; + int k, len; + + spin_lock_irq(&trapped_lock); + list_for_each_entry(tiop, list, list) { + voffs = 0; + for (k = 0; k < tiop->num_resources; k++) { + res = tiop->resource + k; + if (res->start == offset) { + spin_unlock_irq(&trapped_lock); + return tiop->virt_base + voffs; + } + + len = (res->end - res->start) + 1; + voffs += roundup(len, PAGE_SIZE); + } + } + spin_unlock_irq(&trapped_lock); + return NULL; +} +EXPORT_SYMBOL_GPL(match_trapped_io_handler); + +static struct trapped_io *lookup_tiop(unsigned long address) +{ + pgd_t *pgd_k; + pud_t *pud_k; + pmd_t *pmd_k; + pte_t *pte_k; + pte_t entry; + + pgd_k = swapper_pg_dir + pgd_index(address); + if (!pgd_present(*pgd_k)) + return NULL; + + pud_k = pud_offset(pgd_k, address); + if (!pud_present(*pud_k)) + return NULL; + + pmd_k = pmd_offset(pud_k, address); + if (!pmd_present(*pmd_k)) + return NULL; + + pte_k = pte_offset_kernel(pmd_k, address); + entry = *pte_k; + + return pfn_to_kaddr(pte_pfn(entry)); +} + +static unsigned long lookup_address(struct trapped_io *tiop, + unsigned long address) +{ + struct resource *res; + unsigned long vaddr = (unsigned long)tiop->virt_base; + unsigned long len; + int k; + + for (k = 0; k < tiop->num_resources; k++) { + res = tiop->resource + k; + len = roundup((res->end - res->start) + 1, PAGE_SIZE); + if (address < (vaddr + len)) + return res->start + (address - vaddr); + vaddr += len; + } + return 0; +} + +static unsigned long long copy_word(unsigned long src_addr, int src_len, + unsigned long dst_addr, int dst_len) +{ + unsigned long long tmp = 0; + + switch (src_len) { + case 1: + tmp = ctrl_inb(src_addr); + break; + case 2: + tmp = ctrl_inw(src_addr); + break; + case 4: + tmp = ctrl_inl(src_addr); + break; + case 8: + tmp = ctrl_inq(src_addr); + break; + } + + switch (dst_len) { + case 1: + ctrl_outb(tmp, dst_addr); + break; + case 2: + ctrl_outw(tmp, dst_addr); + break; + case 4: + ctrl_outl(tmp, dst_addr); + break; + case 8: + ctrl_outq(tmp, dst_addr); + break; + } + + return tmp; +} + +static unsigned long from_device(void *dst, const void *src, unsigned long cnt) +{ + struct trapped_io *tiop; + unsigned long src_addr = (unsigned long)src; + unsigned long long tmp; + + pr_debug("trapped io read 0x%08lx (%ld)\n", src_addr, cnt); + tiop = lookup_tiop(src_addr); + WARN_ON(!tiop || (tiop->magic != IO_TRAPPED_MAGIC)); + + src_addr = lookup_address(tiop, src_addr); + if (!src_addr) + return cnt; + + tmp = copy_word(src_addr, + max_t(unsigned long, cnt, + (tiop->minimum_bus_width / 8)), + (unsigned long)dst, cnt); + + pr_debug("trapped io read 0x%08lx -> 0x%08llx\n", src_addr, tmp); + return 0; +} + +static unsigned long to_device(void *dst, const void *src, unsigned long cnt) +{ + struct trapped_io *tiop; + unsigned long dst_addr = (unsigned long)dst; + unsigned long long tmp; + + pr_debug("trapped io write 0x%08lx (%ld)\n", dst_addr, cnt); + tiop = lookup_tiop(dst_addr); + WARN_ON(!tiop || (tiop->magic != IO_TRAPPED_MAGIC)); + + dst_addr = lookup_address(tiop, dst_addr); + if (!dst_addr) + return cnt; + + tmp = copy_word((unsigned long)src, cnt, + dst_addr, max_t(unsigned long, cnt, + (tiop->minimum_bus_width / 8))); + + pr_debug("trapped io write 0x%08lx -> 0x%08llx\n", dst_addr, tmp); + return 0; +} + +static struct mem_access trapped_io_access = { + from_device, + to_device, +}; + +int handle_trapped_io(struct pt_regs *regs, unsigned long address) +{ + mm_segment_t oldfs; + opcode_t instruction; + int tmp; + + if (!lookup_tiop(address)) + return 0; + + WARN_ON(user_mode(regs)); + + oldfs = get_fs(); + set_fs(KERNEL_DS); + if (copy_from_user(&instruction, (void *)(regs->pc), + sizeof(instruction))) { + set_fs(oldfs); + return 0; + } + + tmp = handle_unaligned_access(instruction, regs, &trapped_io_access); + set_fs(oldfs); + return tmp == 0; +} diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c index 0586bc62ad96..9bf19b00696a 100644 --- a/arch/sh/kernel/irq.c +++ b/arch/sh/kernel/irq.c @@ -248,9 +248,6 @@ asmlinkage void do_softirq(void) void __init init_IRQ(void) { -#ifdef CONFIG_CPU_HAS_PINT_IRQ - init_IRQ_pint(); -#endif plat_irq_setup(); /* Perform the machine specific initialisation */ diff --git a/arch/sh/kernel/process_64.c b/arch/sh/kernel/process_64.c index cff3b7dc9c56..046999b1d1af 100644 --- a/arch/sh/kernel/process_64.c +++ b/arch/sh/kernel/process_64.c @@ -623,6 +623,7 @@ extern void interruptible_sleep_on(wait_queue_head_t *q); #define mid_sched ((unsigned long) interruptible_sleep_on) +#ifdef CONFIG_FRAME_POINTER static int in_sh64_switch_to(unsigned long pc) { extern char __sh64_switch_to_end; @@ -631,12 +632,10 @@ static int in_sh64_switch_to(unsigned long pc) return (pc >= (unsigned long) sh64_switch_to) && (pc < (unsigned long) &__sh64_switch_to_end); } +#endif unsigned long get_wchan(struct task_struct *p) { - unsigned long schedule_fp; - unsigned long sh64_switch_to_fp; - unsigned long schedule_caller_pc; unsigned long pc; if (!p || p == current || p->state == TASK_RUNNING) @@ -649,6 +648,10 @@ unsigned long get_wchan(struct task_struct *p) #ifdef CONFIG_FRAME_POINTER if (in_sh64_switch_to(pc)) { + unsigned long schedule_fp; + unsigned long sh64_switch_to_fp; + unsigned long schedule_caller_pc; + sh64_switch_to_fp = (long) p->thread.sp; /* r14 is saved at offset 4 in the sh64_switch_to frame */ schedule_fp = *(unsigned long *) (long)(sh64_switch_to_fp + 4); diff --git a/arch/sh/kernel/ptrace_32.c b/arch/sh/kernel/ptrace_32.c index ce0664a58b49..fddb547f3c2b 100644 --- a/arch/sh/kernel/ptrace_32.c +++ b/arch/sh/kernel/ptrace_32.c @@ -220,7 +220,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) dp = ((unsigned long) child) + THREAD_SIZE - sizeof(struct pt_dspregs); if (*((int *) (dp - 4)) == SR_FD) { - copy_to_user(addr, (void *) dp, + copy_to_user((void *)addr, (void *) dp, sizeof(struct pt_dspregs)); ret = 0; } @@ -234,7 +234,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) dp = ((unsigned long) child) + THREAD_SIZE - sizeof(struct pt_dspregs); if (*((int *) (dp - 4)) == SR_FD) { - copy_from_user((void *) dp, addr, + copy_from_user((void *) dp, (void *)addr, sizeof(struct pt_dspregs)); ret = 0; } diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c index 18a5baf2cbad..ff4f54a47c07 100644 --- a/arch/sh/kernel/setup.c +++ b/arch/sh/kernel/setup.c @@ -333,7 +333,7 @@ static const char *cpu_name[] = { [CPU_SH7343] = "SH7343", [CPU_SH7785] = "SH7785", [CPU_SH7722] = "SH7722", [CPU_SHX3] = "SH-X3", [CPU_SH5_101] = "SH5-101", [CPU_SH5_103] = "SH5-103", - [CPU_SH_NONE] = "Unknown" + [CPU_SH7366] = "SH7366", [CPU_SH_NONE] = "Unknown" }; const char *get_cpu_subtype(struct sh_cpuinfo *c) diff --git a/arch/sh/kernel/syscalls_32.S b/arch/sh/kernel/syscalls_32.S index 719e127a7c05..a46cc3a41148 100644 --- a/arch/sh/kernel/syscalls_32.S +++ b/arch/sh/kernel/syscalls_32.S @@ -338,6 +338,8 @@ ENTRY(sys_call_table) .long sys_epoll_pwait .long sys_utimensat /* 320 */ .long sys_signalfd - .long sys_ni_syscall + .long sys_timerfd_create .long sys_eventfd .long sys_fallocate + .long sys_timerfd_settime /* 325 */ + .long sys_timerfd_gettime diff --git a/arch/sh/kernel/syscalls_64.S b/arch/sh/kernel/syscalls_64.S index 12c7340356ae..d5d7843aad94 100644 --- a/arch/sh/kernel/syscalls_64.S +++ b/arch/sh/kernel/syscalls_64.S @@ -376,6 +376,8 @@ sys_call_table: .long sys_epoll_pwait .long sys_utimensat .long sys_signalfd - .long sys_ni_syscall /* 350 */ + .long sys_timerfd_create /* 350 */ .long sys_eventfd .long sys_fallocate + .long sys_timerfd_settime + .long sys_timerfd_gettime diff --git a/arch/sh/kernel/time_32.c b/arch/sh/kernel/time_32.c index 2bc04bfee738..7281342c044d 100644 --- a/arch/sh/kernel/time_32.c +++ b/arch/sh/kernel/time_32.c @@ -120,10 +120,6 @@ static long last_rtc_update; */ void handle_timer_tick(void) { - do_timer(1); -#ifndef CONFIG_SMP - update_process_times(user_mode(get_irq_regs())); -#endif if (current->pid) profile_tick(CPU_PROFILING); @@ -132,6 +128,16 @@ void handle_timer_tick(void) sh_mv.mv_heartbeat(); #endif + /* + * 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); + do_timer(1); + /* * If we have an externally synchronized Linux clock, then update * RTC clock accordingly every ~11 minutes. Set_rtc_mmss() has to be @@ -147,6 +153,11 @@ void handle_timer_tick(void) /* do it again in 60s */ last_rtc_update = xtime.tv_sec - 600; } + write_sequnlock(&xtime_lock); + +#ifndef CONFIG_SMP + update_process_times(user_mode(get_irq_regs())); +#endif } #endif /* !CONFIG_GENERIC_CLOCKEVENTS */ diff --git a/arch/sh/kernel/time_64.c b/arch/sh/kernel/time_64.c index f819ba38a6ce..898977ee2030 100644 --- a/arch/sh/kernel/time_64.c +++ b/arch/sh/kernel/time_64.c @@ -229,15 +229,22 @@ static long last_rtc_update; static inline void do_timer_interrupt(void) { unsigned long long current_ctc; + + if (current->pid) + profile_tick(CPU_PROFILING); + + /* + * 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_lock(&xtime_lock); asm ("getcon cr62, %0" : "=r" (current_ctc)); ctc_last_interrupt = (unsigned long) current_ctc; do_timer(1); -#ifndef CONFIG_SMP - update_process_times(user_mode(get_irq_regs())); -#endif - if (current->pid) - profile_tick(CPU_PROFILING); #ifdef CONFIG_HEARTBEAT if (sh_mv.mv_heartbeat != NULL) @@ -259,6 +266,11 @@ static inline void do_timer_interrupt(void) /* do it again in 60 s */ last_rtc_update = xtime.tv_sec - 600; } + write_unlock(&xtime_lock); + +#ifndef CONFIG_SMP + update_process_times(user_mode(get_irq_regs())); +#endif } /* @@ -275,16 +287,7 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id) timer_status &= ~0x100; ctrl_outw(timer_status, TMU0_TCR); - /* - * 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_lock(&xtime_lock); do_timer_interrupt(); - write_unlock(&xtime_lock); return IRQ_HANDLED; } diff --git a/arch/sh/kernel/timers/timer-mtu2.c b/arch/sh/kernel/timers/timer-mtu2.c index 463cd08f9517..ade9d6eb29f9 100644 --- a/arch/sh/kernel/timers/timer-mtu2.c +++ b/arch/sh/kernel/timers/timer-mtu2.c @@ -154,7 +154,6 @@ static int mtu2_timer_stop(void) static int mtu2_timer_init(void) { - u8 tmp; unsigned long interval; setup_irq(CONFIG_SH_TIMER_IRQ, &mtu2_irq); diff --git a/arch/sh/kernel/traps_32.c b/arch/sh/kernel/traps_32.c index 2e58f7a6b746..baa4fa368dce 100644 --- a/arch/sh/kernel/traps_32.c +++ b/arch/sh/kernel/traps_32.c @@ -147,6 +147,36 @@ static int die_if_no_fixup(const char * str, struct pt_regs * regs, long err) return -EFAULT; } +static inline void sign_extend(unsigned int count, unsigned char *dst) +{ +#ifdef __LITTLE_ENDIAN__ + if ((count == 1) && dst[0] & 0x80) { + dst[1] = 0xff; + dst[2] = 0xff; + dst[3] = 0xff; + } + if ((count == 2) && dst[1] & 0x80) { + dst[2] = 0xff; + dst[3] = 0xff; + } +#else + if ((count == 1) && dst[3] & 0x80) { + dst[2] = 0xff; + dst[1] = 0xff; + dst[0] = 0xff; + } + if ((count == 2) && dst[2] & 0x80) { + dst[1] = 0xff; + dst[0] = 0xff; + } +#endif +} + +static struct mem_access user_mem_access = { + copy_from_user, + copy_to_user, +}; + /* * handle an instruction that does an unaligned memory access by emulating the * desired behaviour @@ -154,7 +184,8 @@ static int die_if_no_fixup(const char * str, struct pt_regs * regs, long err) * (if that instruction is in a branch delay slot) * - return 0 if emulation okay, -EFAULT on existential error */ -static int handle_unaligned_ins(u16 instruction, struct pt_regs *regs) +static int handle_unaligned_ins(opcode_t instruction, struct pt_regs *regs, + struct mem_access *ma) { int ret, index, count; unsigned long *rm, *rn; @@ -178,25 +209,13 @@ static int handle_unaligned_ins(u16 instruction, struct pt_regs *regs) dst = (unsigned char*) rn; *(unsigned long*)dst = 0; -#ifdef __LITTLE_ENDIAN__ - if (copy_from_user(dst, src, count)) - goto fetch_fault; - - if ((count == 2) && dst[1] & 0x80) { - dst[2] = 0xff; - dst[3] = 0xff; - } -#else +#if !defined(__LITTLE_ENDIAN__) dst += 4-count; - - if (__copy_user(dst, src, count)) +#endif + if (ma->from(dst, src, count)) goto fetch_fault; - if ((count == 2) && dst[2] & 0x80) { - dst[0] = 0xff; - dst[1] = 0xff; - } -#endif + sign_extend(count, dst); } else { /* to memory */ src = (unsigned char*) rm; @@ -206,7 +225,7 @@ static int handle_unaligned_ins(u16 instruction, struct pt_regs *regs) dst = (unsigned char*) *rn; dst += regs->regs[0]; - if (copy_to_user(dst, src, count)) + if (ma->to(dst, src, count)) goto fetch_fault; } ret = 0; @@ -217,7 +236,7 @@ static int handle_unaligned_ins(u16 instruction, struct pt_regs *regs) dst = (unsigned char*) *rn; dst += (instruction&0x000F)<<2; - if (copy_to_user(dst,src,4)) + if (ma->to(dst, src, 4)) goto fetch_fault; ret = 0; break; @@ -230,7 +249,7 @@ static int handle_unaligned_ins(u16 instruction, struct pt_regs *regs) #if !defined(__LITTLE_ENDIAN__) src += 4-count; #endif - if (copy_to_user(dst, src, count)) + if (ma->to(dst, src, count)) goto fetch_fault; ret = 0; break; @@ -241,7 +260,7 @@ static int handle_unaligned_ins(u16 instruction, struct pt_regs *regs) dst = (unsigned char*) rn; *(unsigned long*)dst = 0; - if (copy_from_user(dst,src,4)) + if (ma->from(dst, src, 4)) goto fetch_fault; ret = 0; break; @@ -253,25 +272,12 @@ static int handle_unaligned_ins(u16 instruction, struct pt_regs *regs) dst = (unsigned char*) rn; *(unsigned long*)dst = 0; -#ifdef __LITTLE_ENDIAN__ - if (copy_from_user(dst, src, count)) - goto fetch_fault; - - if ((count == 2) && dst[1] & 0x80) { - dst[2] = 0xff; - dst[3] = 0xff; - } -#else +#if !defined(__LITTLE_ENDIAN__) dst += 4-count; - - if (copy_from_user(dst, src, count)) - goto fetch_fault; - - if ((count == 2) && dst[2] & 0x80) { - dst[0] = 0xff; - dst[1] = 0xff; - } #endif + if (ma->from(dst, src, count)) + goto fetch_fault; + sign_extend(count, dst); ret = 0; break; @@ -285,7 +291,7 @@ static int handle_unaligned_ins(u16 instruction, struct pt_regs *regs) dst = (unsigned char*) *rm; /* called Rn in the spec */ dst += (instruction&0x000F)<<1; - if (copy_to_user(dst, src, 2)) + if (ma->to(dst, src, 2)) goto fetch_fault; ret = 0; break; @@ -299,21 +305,9 @@ static int handle_unaligned_ins(u16 instruction, struct pt_regs *regs) #if !defined(__LITTLE_ENDIAN__) dst += 2; #endif - - if (copy_from_user(dst, src, 2)) + if (ma->from(dst, src, 2)) goto fetch_fault; - -#ifdef __LITTLE_ENDIAN__ - if (dst[1] & 0x80) { - dst[2] = 0xff; - dst[3] = 0xff; - } -#else - if (dst[2] & 0x80) { - dst[0] = 0xff; - dst[1] = 0xff; - } -#endif + sign_extend(2, dst); ret = 0; break; } @@ -332,11 +326,14 @@ static int handle_unaligned_ins(u16 instruction, struct pt_regs *regs) * emulate the instruction in the delay slot * - fetches the instruction from PC+2 */ -static inline int handle_unaligned_delayslot(struct pt_regs *regs) +static inline int handle_delayslot(struct pt_regs *regs, + opcode_t old_instruction, + struct mem_access *ma) { - u16 instruction; + opcode_t instruction; + void *addr = (void *)(regs->pc + instruction_size(old_instruction)); - if (copy_from_user(&instruction, (u16 *)(regs->pc+2), 2)) { + if (copy_from_user(&instruction, addr, sizeof(instruction))) { /* the instruction-fetch faulted */ if (user_mode(regs)) return -EFAULT; @@ -346,7 +343,7 @@ static inline int handle_unaligned_delayslot(struct pt_regs *regs) regs, 0); } - return handle_unaligned_ins(instruction,regs); + return handle_unaligned_ins(instruction, regs, ma); } /* @@ -369,10 +366,11 @@ static inline int handle_unaligned_delayslot(struct pt_regs *regs) * 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) +int handle_unaligned_access(opcode_t instruction, struct pt_regs *regs, + struct mem_access *ma) { u_int rm; int ret, index; @@ -387,7 +385,7 @@ static int handle_unaligned_access(u16 instruction, struct pt_regs *regs) printk(KERN_NOTICE "Fixing up unaligned userspace access " "in \"%s\" pid=%d pc=0x%p ins=0x%04hx\n", current->comm, task_pid_nr(current), - (u16 *)regs->pc, instruction); + (void *)regs->pc, instruction); } ret = -EFAULT; @@ -395,19 +393,19 @@ static int handle_unaligned_access(u16 instruction, struct pt_regs *regs) case 0x0000: if (instruction==0x000B) { /* rts */ - ret = handle_unaligned_delayslot(regs); + ret = handle_delayslot(regs, instruction, ma); if (ret==0) regs->pc = regs->pr; } else if ((instruction&0x00FF)==0x0023) { /* braf @Rm */ - ret = handle_unaligned_delayslot(regs); + ret = handle_delayslot(regs, instruction, ma); if (ret==0) regs->pc += rm + 4; } else if ((instruction&0x00FF)==0x0003) { /* bsrf @Rm */ - ret = handle_unaligned_delayslot(regs); + ret = handle_delayslot(regs, instruction, ma); if (ret==0) { regs->pr = regs->pc + 4; regs->pc += rm + 4; @@ -428,13 +426,13 @@ static int handle_unaligned_access(u16 instruction, struct pt_regs *regs) case 0x4000: if ((instruction&0x00FF)==0x002B) { /* jmp @Rm */ - ret = handle_unaligned_delayslot(regs); + ret = handle_delayslot(regs, instruction, ma); if (ret==0) regs->pc = rm; } else if ((instruction&0x00FF)==0x000B) { /* jsr @Rm */ - ret = handle_unaligned_delayslot(regs); + ret = handle_delayslot(regs, instruction, ma); if (ret==0) { regs->pr = regs->pc + 4; regs->pc = rm; @@ -461,7 +459,7 @@ static int handle_unaligned_access(u16 instruction, struct pt_regs *regs) case 0x0B00: /* bf lab - no delayslot*/ break; case 0x0F00: /* bf/s lab */ - ret = handle_unaligned_delayslot(regs); + ret = handle_delayslot(regs, instruction, ma); if (ret==0) { #if defined(CONFIG_CPU_SH4) || defined(CONFIG_SH7705_CACHE_32KB) if ((regs->sr & 0x00000001) != 0) @@ -474,7 +472,7 @@ static int handle_unaligned_access(u16 instruction, struct pt_regs *regs) case 0x0900: /* bt lab - no delayslot */ break; case 0x0D00: /* bt/s lab */ - ret = handle_unaligned_delayslot(regs); + ret = handle_delayslot(regs, instruction, ma); if (ret==0) { #if defined(CONFIG_CPU_SH4) || defined(CONFIG_SH7705_CACHE_32KB) if ((regs->sr & 0x00000001) == 0) @@ -488,13 +486,13 @@ static int handle_unaligned_access(u16 instruction, struct pt_regs *regs) break; case 0xA000: /* bra label */ - ret = handle_unaligned_delayslot(regs); + ret = handle_delayslot(regs, instruction, ma); if (ret==0) regs->pc += SH_PC_12BIT_OFFSET(instruction); break; case 0xB000: /* bsr label */ - ret = handle_unaligned_delayslot(regs); + ret = handle_delayslot(regs, instruction, ma); if (ret==0) { regs->pr = regs->pc + 4; regs->pc += SH_PC_12BIT_OFFSET(instruction); @@ -505,12 +503,11 @@ static int handle_unaligned_access(u16 instruction, struct pt_regs *regs) /* handle non-delay-slot instruction */ simple: - ret = handle_unaligned_ins(instruction,regs); + ret = handle_unaligned_ins(instruction, regs, ma); if (ret==0) regs->pc += instruction_size(instruction); return ret; } -#endif /* CONFIG_CPU_SH2A */ #ifdef CONFIG_CPU_HAS_SR_RB #define lookup_exception_vector(x) \ @@ -538,10 +535,8 @@ asmlinkage void do_address_error(struct pt_regs *regs, unsigned long error_code = 0; mm_segment_t oldfs; siginfo_t info; -#ifndef CONFIG_CPU_SH2A - u16 instruction; + opcode_t instruction; int tmp; -#endif /* Intentional ifdef */ #ifdef CONFIG_CPU_HAS_SR_RB @@ -561,9 +556,9 @@ asmlinkage void do_address_error(struct pt_regs *regs, goto uspace_segv; } -#ifndef CONFIG_CPU_SH2A set_fs(USER_DS); - if (copy_from_user(&instruction, (u16 *)(regs->pc), 2)) { + if (copy_from_user(&instruction, (void *)(regs->pc), + sizeof(instruction))) { /* Argh. Fault on the instruction itself. This should never happen non-SMP */ @@ -571,13 +566,12 @@ asmlinkage void do_address_error(struct pt_regs *regs, goto uspace_segv; } - tmp = handle_unaligned_access(instruction, regs); + tmp = handle_unaligned_access(instruction, regs, + &user_mem_access); set_fs(oldfs); if (tmp==0) return; /* sorted */ -#endif - uspace_segv: printk(KERN_NOTICE "Sending SIGBUS to \"%s\" due to unaligned " "access (PC %lx PR %lx)\n", current->comm, regs->pc, @@ -592,9 +586,9 @@ uspace_segv: 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)) { + if (copy_from_user(&instruction, (void *)(regs->pc), + sizeof(instruction))) { /* Argh. Fault on the instruction itself. This should never happen non-SMP */ @@ -602,14 +596,8 @@ uspace_segv: die("insn faulting in do_address_error", regs, 0); } - handle_unaligned_access(instruction, regs); + handle_unaligned_access(instruction, regs, &user_mem_access); set_fs(oldfs); -#else - printk(KERN_NOTICE "Killing process \"%s\" due to unaligned " - "access\n", current->comm); - - force_sig(SIGSEGV, current); -#endif } } diff --git a/arch/sh/kernel/traps_64.c b/arch/sh/kernel/traps_64.c index c0b3c6f6edb5..a55ac81d795b 100644 --- a/arch/sh/kernel/traps_64.c +++ b/arch/sh/kernel/traps_64.c @@ -630,7 +630,7 @@ static int misaligned_fpu_load(struct pt_regs *regs, current->thread.fpu.hard.fp_regs[destreg] = buflo; current->thread.fpu.hard.fp_regs[destreg+1] = bufhi; } else { -#if defined(CONFIG_LITTLE_ENDIAN) +#if defined(CONFIG_CPU_LITTLE_ENDIAN) current->thread.fpu.hard.fp_regs[destreg] = bufhi; current->thread.fpu.hard.fp_regs[destreg+1] = buflo; #else @@ -700,7 +700,7 @@ static int misaligned_fpu_store(struct pt_regs *regs, buflo = current->thread.fpu.hard.fp_regs[srcreg]; bufhi = current->thread.fpu.hard.fp_regs[srcreg+1]; } else { -#if defined(CONFIG_LITTLE_ENDIAN) +#if defined(CONFIG_CPU_LITTLE_ENDIAN) bufhi = current->thread.fpu.hard.fp_regs[srcreg]; buflo = current->thread.fpu.hard.fp_regs[srcreg+1]; #else diff --git a/arch/sh/kernel/vmlinux_64.lds.S b/arch/sh/kernel/vmlinux_64.lds.S index 3f1bd6392bb3..d1e177009a41 100644 --- a/arch/sh/kernel/vmlinux_64.lds.S +++ b/arch/sh/kernel/vmlinux_64.lds.S @@ -51,7 +51,7 @@ SECTIONS KPROBES_TEXT *(.fixup) *(.gnu.warning) -#ifdef CONFIG_LITTLE_ENDIAN +#ifdef CONFIG_CPU_LITTLE_ENDIAN } = 0x6ff0fff0 #else } = 0xf0fff06f diff --git a/arch/sh/mm/cache-sh5.c b/arch/sh/mm/cache-sh5.c index 4617e3aeee73..3877321fcede 100644 --- a/arch/sh/mm/cache-sh5.c +++ b/arch/sh/mm/cache-sh5.c @@ -1,10 +1,10 @@ /* * arch/sh/mm/cache-sh5.c * - * Original version Copyright (C) 2000, 2001 Paolo Alberelli - * Second version Copyright (C) benedict.gaster@superh.com 2002 - * Third version Copyright Richard.Curnow@superh.com 2003 - * Hacks to third version Copyright (C) 2003 Paul Mundt + * Copyright (C) 2000, 2001 Paolo Alberelli + * Copyright (C) 2002 Benedict Gaster + * Copyright (C) 2003 Richard Curnow + * Copyright (C) 2003 - 2008 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 @@ -13,101 +13,20 @@ #include #include #include -#include -#include -#include +#include #include #include -#include -#include +#include #include #include -#include /* for flush_itlb_range */ - -#include - -/* This function is in entry.S */ -extern unsigned long switch_and_save_asid(unsigned long new_asid); /* Wired TLB entry for the D-cache */ static unsigned long long dtlb_cache_slot; -/** - * sh64_cache_init() - * - * This is pretty much just a straightforward clone of the SH - * detect_cpu_and_cache_system(). - * - * This function is responsible for setting up all of the cache - * info dynamically as well as taking care of CPU probing and - * setting up the relevant subtype data. - * - * FIXME: For the time being, we only really support the SH5-101 - * out of the box, and don't support dynamic probing for things - * like the SH5-103 or even cut2 of the SH5-101. Implement this - * later! - */ -int __init sh64_cache_init(void) +void __init p3_cache_init(void) { - /* - * First, setup some sane values for the I-cache. - */ - cpu_data->icache.ways = 4; - cpu_data->icache.sets = 256; - cpu_data->icache.linesz = L1_CACHE_BYTES; - - /* - * FIXME: This can probably be cleaned up a bit as well.. for example, - * do we really need the way shift _and_ the way_step_shift ?? Judging - * by the existing code, I would guess no.. is there any valid reason - * why we need to be tracking this around? - */ - cpu_data->icache.way_shift = 13; - cpu_data->icache.entry_shift = 5; - cpu_data->icache.set_shift = 4; - cpu_data->icache.way_step_shift = 16; - cpu_data->icache.asid_shift = 2; - - /* - * way offset = cache size / associativity, so just don't factor in - * associativity in the first place.. - */ - cpu_data->icache.way_ofs = cpu_data->icache.sets * - cpu_data->icache.linesz; - - cpu_data->icache.asid_mask = 0x3fc; - cpu_data->icache.idx_mask = 0x1fe0; - cpu_data->icache.epn_mask = 0xffffe000; - cpu_data->icache.flags = 0; - - /* - * Next, setup some sane values for the D-cache. - * - * On the SH5, these are pretty consistent with the I-cache settings, - * so we just copy over the existing definitions.. these can be fixed - * up later, especially if we add runtime CPU probing. - * - * Though in the meantime it saves us from having to duplicate all of - * the above definitions.. - */ - cpu_data->dcache = cpu_data->icache; - - /* - * Setup any cache-related flags here - */ -#if defined(CONFIG_DCACHE_WRITE_THROUGH) - set_bit(SH_CACHE_MODE_WT, &(cpu_data->dcache.flags)); -#elif defined(CONFIG_DCACHE_WRITE_BACK) - set_bit(SH_CACHE_MODE_WB, &(cpu_data->dcache.flags)); -#endif - - /* - * We also need to reserve a slot for the D-cache in the DTLB, so we - * do this now .. - */ - dtlb_cache_slot = sh64_get_wired_dtlb_entry(); - - return 0; + /* Reserve a slot for dcache colouring in the DTLB */ + dtlb_cache_slot = sh64_get_wired_dtlb_entry(); } #ifdef CONFIG_DCACHE_DISABLED @@ -116,73 +35,48 @@ int __init sh64_cache_init(void) #define sh64_dcache_purge_user_range(mm, start, end) do { } while (0) #define sh64_dcache_purge_phy_page(paddr) do { } while (0) #define sh64_dcache_purge_virt_page(mm, eaddr) do { } while (0) -#define sh64_dcache_purge_kernel_range(start, end) do { } while (0) -#define sh64_dcache_wback_current_user_range(start, end) do { } while (0) #endif -/*##########################################################################*/ - -/* From here onwards, a rewrite of the implementation, - by Richard.Curnow@superh.com. - - The major changes in this compared to the old version are; - 1. use more selective purging through OCBP instead of using ALLOCO to purge - by natural replacement. This avoids purging out unrelated cache lines - that happen to be in the same set. - 2. exploit the APIs copy_user_page and clear_user_page better - 3. be more selective about I-cache purging, in particular use invalidate_all - more sparingly. - - */ - -/*########################################################################## - SUPPORT FUNCTIONS - ##########################################################################*/ - -/****************************************************************************/ -/* The following group of functions deal with mapping and unmapping a temporary - page into the DTLB slot that have been set aside for our exclusive use. */ -/* In order to accomplish this, we use the generic interface for adding and - removing a wired slot entry as defined in arch/sh/mm/tlb-sh5.c */ -/****************************************************************************/ - -static unsigned long slot_own_flags; - -static inline void sh64_setup_dtlb_cache_slot(unsigned long eaddr, unsigned long asid, unsigned long paddr) +/* + * The following group of functions deal with mapping and unmapping a + * temporary page into a DTLB slot that has been set aside for exclusive + * use. + */ +static inline void +sh64_setup_dtlb_cache_slot(unsigned long eaddr, unsigned long asid, + unsigned long paddr) { - local_irq_save(slot_own_flags); + local_irq_disable(); sh64_setup_tlb_slot(dtlb_cache_slot, eaddr, asid, paddr); } static inline void sh64_teardown_dtlb_cache_slot(void) { sh64_teardown_tlb_slot(dtlb_cache_slot); - local_irq_restore(slot_own_flags); + local_irq_enable(); } -/****************************************************************************/ - #ifndef CONFIG_ICACHE_DISABLED - -static void __inline__ sh64_icache_inv_all(void) +static inline void sh64_icache_inv_all(void) { unsigned long long addr, flag, data; unsigned int flags; - addr=ICCR0; - flag=ICCR0_ICI; - data=0; + addr = ICCR0; + flag = ICCR0_ICI; + data = 0; /* Make this a critical section for safety (probably not strictly necessary.) */ local_irq_save(flags); /* Without %1 it gets unexplicably wrong */ - asm volatile("getcfg %3, 0, %0\n\t" - "or %0, %2, %0\n\t" - "putcfg %3, 0, %0\n\t" - "synci" - : "=&r" (data) - : "0" (data), "r" (flag), "r" (addr)); + __asm__ __volatile__ ( + "getcfg %3, 0, %0\n\t" + "or %0, %2, %0\n\t" + "putcfg %3, 0, %0\n\t" + "synci" + : "=&r" (data) + : "0" (data), "r" (flag), "r" (addr)); local_irq_restore(flags); } @@ -193,20 +87,12 @@ static void sh64_icache_inv_kernel_range(unsigned long start, unsigned long end) * the addresses lie in the kernel superpage. */ unsigned long long ullend, addr, aligned_start; -#if (NEFF == 32) aligned_start = (unsigned long long)(signed long long)(signed long) start; -#else -#error "NEFF != 32" -#endif - aligned_start &= L1_CACHE_ALIGN_MASK; - addr = aligned_start; -#if (NEFF == 32) + addr = L1_CACHE_ALIGN(aligned_start); ullend = (unsigned long long) (signed long long) (signed long) end; -#else -#error "NEFF != 32" -#endif + while (addr <= ullend) { - asm __volatile__ ("icbi %0, 0" : : "r" (addr)); + __asm__ __volatile__ ("icbi %0, 0" : : "r" (addr)); addr += L1_CACHE_BYTES; } } @@ -215,7 +101,7 @@ static void sh64_icache_inv_user_page(struct vm_area_struct *vma, unsigned long { /* If we get called, we know that vma->vm_flags contains VM_EXEC. Also, eaddr is page-aligned. */ - + unsigned int cpu = smp_processor_id(); unsigned long long addr, end_addr; unsigned long flags = 0; unsigned long running_asid, vma_asid; @@ -237,17 +123,17 @@ static void sh64_icache_inv_user_page(struct vm_area_struct *vma, unsigned long */ running_asid = get_asid(); - vma_asid = (vma->vm_mm->context & MMU_CONTEXT_ASID_MASK); + vma_asid = cpu_asid(cpu, vma->vm_mm); if (running_asid != vma_asid) { local_irq_save(flags); switch_and_save_asid(vma_asid); } while (addr < end_addr) { /* Worth unrolling a little */ - asm __volatile__("icbi %0, 0" : : "r" (addr)); - asm __volatile__("icbi %0, 32" : : "r" (addr)); - asm __volatile__("icbi %0, 64" : : "r" (addr)); - asm __volatile__("icbi %0, 96" : : "r" (addr)); + __asm__ __volatile__("icbi %0, 0" : : "r" (addr)); + __asm__ __volatile__("icbi %0, 32" : : "r" (addr)); + __asm__ __volatile__("icbi %0, 64" : : "r" (addr)); + __asm__ __volatile__("icbi %0, 96" : : "r" (addr)); addr += 128; } if (running_asid != vma_asid) { @@ -256,8 +142,6 @@ static void sh64_icache_inv_user_page(struct vm_area_struct *vma, unsigned long } } -/****************************************************************************/ - static void sh64_icache_inv_user_page_range(struct mm_struct *mm, unsigned long start, unsigned long end) { @@ -275,10 +159,10 @@ static void sh64_icache_inv_user_page_range(struct mm_struct *mm, possible with the D-cache. Just assume 64 for now as a working figure. */ - int n_pages; - if (!mm) return; + if (!mm) + return; n_pages = ((end - start) >> PAGE_SHIFT); if (n_pages >= 64) { @@ -290,7 +174,7 @@ static void sh64_icache_inv_user_page_range(struct mm_struct *mm, unsigned long mm_asid, current_asid; unsigned long long flags = 0ULL; - mm_asid = mm->context & MMU_CONTEXT_ASID_MASK; + mm_asid = cpu_asid(smp_processor_id(), mm); current_asid = get_asid(); if (mm_asid != current_asid) { @@ -322,6 +206,7 @@ static void sh64_icache_inv_user_page_range(struct mm_struct *mm, } aligned_start = vma->vm_end; /* Skip to start of next region */ } + if (mm_asid != current_asid) { switch_and_save_asid(current_asid); local_irq_restore(flags); @@ -329,47 +214,46 @@ static void sh64_icache_inv_user_page_range(struct mm_struct *mm, } } +/* + * Invalidate a small range of user context I-cache, not necessarily page + * (or even cache-line) aligned. + * + * Since this is used inside ptrace, the ASID in the mm context typically + * won't match current_asid. We'll have to switch ASID to do this. For + * safety, and given that the range will be small, do all this under cli. + * + * Note, there is a hazard that the ASID in mm->context is no longer + * actually associated with mm, i.e. if the mm->context has started a new + * cycle since mm was last active. However, this is just a performance + * issue: all that happens is that we invalidate lines belonging to + * another mm, so the owning process has to refill them when that mm goes + * live again. mm itself can't have any cache entries because there will + * have been a flush_cache_all when the new mm->context cycle started. + */ static void sh64_icache_inv_user_small_range(struct mm_struct *mm, unsigned long start, int len) { - - /* Invalidate a small range of user context I-cache, not necessarily - page (or even cache-line) aligned. */ - unsigned long long eaddr = start; unsigned long long eaddr_end = start + len; unsigned long current_asid, mm_asid; unsigned long long flags; unsigned long long epage_start; - /* Since this is used inside ptrace, the ASID in the mm context - typically won't match current_asid. We'll have to switch ASID to do - this. For safety, and given that the range will be small, do all - this under cli. - - Note, there is a hazard that the ASID in mm->context is no longer - actually associated with mm, i.e. if the mm->context has started a - new cycle since mm was last active. However, this is just a - performance issue: all that happens is that we invalidate lines - belonging to another mm, so the owning process has to refill them - when that mm goes live again. mm itself can't have any cache - entries because there will have been a flush_cache_all when the new - mm->context cycle started. */ - - /* Align to start of cache line. Otherwise, suppose len==8 and start - was at 32N+28 : the last 4 bytes wouldn't get invalidated. */ - eaddr = start & L1_CACHE_ALIGN_MASK; + /* + * Align to start of cache line. Otherwise, suppose len==8 and + * start was at 32N+28 : the last 4 bytes wouldn't get invalidated. + */ + eaddr = L1_CACHE_ALIGN(start); eaddr_end = start + len; + mm_asid = cpu_asid(smp_processor_id(), mm); local_irq_save(flags); - mm_asid = mm->context & MMU_CONTEXT_ASID_MASK; current_asid = switch_and_save_asid(mm_asid); epage_start = eaddr & PAGE_MASK; - while (eaddr < eaddr_end) - { - asm __volatile__("icbi %0, 0" : : "r" (eaddr)); + while (eaddr < eaddr_end) { + __asm__ __volatile__("icbi %0, 0" : : "r" (eaddr)); eaddr += L1_CACHE_BYTES; } switch_and_save_asid(current_asid); @@ -394,30 +278,24 @@ static void sh64_icache_inv_current_user_range(unsigned long start, unsigned lon been recycled since we were last active in which case we might just invalidate another processes I-cache entries : no worries, just a performance drop for him. */ - aligned_start = start & L1_CACHE_ALIGN_MASK; + aligned_start = L1_CACHE_ALIGN(start); addr = aligned_start; while (addr < ull_end) { - asm __volatile__ ("icbi %0, 0" : : "r" (addr)); - asm __volatile__ ("nop"); - asm __volatile__ ("nop"); + __asm__ __volatile__ ("icbi %0, 0" : : "r" (addr)); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); addr += L1_CACHE_BYTES; } } - #endif /* !CONFIG_ICACHE_DISABLED */ -/****************************************************************************/ - #ifndef CONFIG_DCACHE_DISABLED - /* Buffer used as the target of alloco instructions to purge data from cache sets by natural eviction. -- RPC */ -#define DUMMY_ALLOCO_AREA_SIZE L1_CACHE_SIZE_BYTES + (1024 * 4) +#define DUMMY_ALLOCO_AREA_SIZE ((L1_CACHE_BYTES << 10) + (1024 * 4)) static unsigned char dummy_alloco_area[DUMMY_ALLOCO_AREA_SIZE] __cacheline_aligned = { 0, }; -/****************************************************************************/ - -static void __inline__ sh64_dcache_purge_sets(int sets_to_purge_base, int n_sets) +static void inline sh64_dcache_purge_sets(int sets_to_purge_base, int n_sets) { /* Purge all ways in a particular block of sets, specified by the base set number and number of sets. Can handle wrap-around, if that's @@ -428,102 +306,86 @@ static void __inline__ sh64_dcache_purge_sets(int sets_to_purge_base, int n_sets int j; int set_offset; - dummy_buffer_base_set = ((int)&dummy_alloco_area & cpu_data->dcache.idx_mask) >> cpu_data->dcache.entry_shift; + dummy_buffer_base_set = ((int)&dummy_alloco_area & + cpu_data->dcache.entry_mask) >> + cpu_data->dcache.entry_shift; set_offset = sets_to_purge_base - dummy_buffer_base_set; - for (j=0; jdcache.sets - 1); - eaddr0 = (unsigned long long)dummy_alloco_area + (set_offset << cpu_data->dcache.entry_shift); + eaddr0 = (unsigned long long)dummy_alloco_area + + (set_offset << cpu_data->dcache.entry_shift); - /* Do one alloco which hits the required set per cache way. For - write-back mode, this will purge the #ways resident lines. There's - little point unrolling this loop because the allocos stall more if - they're too close together. */ - eaddr1 = eaddr0 + cpu_data->dcache.way_ofs * cpu_data->dcache.ways; - for (eaddr=eaddr0; eaddrdcache.way_ofs) { - asm __volatile__ ("alloco %0, 0" : : "r" (eaddr)); - asm __volatile__ ("synco"); /* TAKum03020 */ + /* + * Do one alloco which hits the required set per cache + * way. For write-back mode, this will purge the #ways + * resident lines. There's little point unrolling this + * loop because the allocos stall more if they're too + * close together. + */ + eaddr1 = eaddr0 + cpu_data->dcache.way_size * + cpu_data->dcache.ways; + + for (eaddr = eaddr0; eaddr < eaddr1; + eaddr += cpu_data->dcache.way_size) { + __asm__ __volatile__ ("alloco %0, 0" : : "r" (eaddr)); + __asm__ __volatile__ ("synco"); /* TAKum03020 */ } - eaddr1 = eaddr0 + cpu_data->dcache.way_ofs * cpu_data->dcache.ways; - for (eaddr=eaddr0; eaddrdcache.way_ofs) { - /* Load from each address. Required because alloco is a NOP if - the cache is write-through. Write-through is a config option. */ + eaddr1 = eaddr0 + cpu_data->dcache.way_size * + cpu_data->dcache.ways; + + for (eaddr = eaddr0; eaddr < eaddr1; + eaddr += cpu_data->dcache.way_size) { + /* + * Load from each address. Required because + * alloco is a NOP if the cache is write-through. + */ if (test_bit(SH_CACHE_MODE_WT, &(cpu_data->dcache.flags))) - *(volatile unsigned char *)(int)eaddr; + ctrl_inb(eaddr); } } - /* Don't use OCBI to invalidate the lines. That costs cycles directly. - If the dummy block is just left resident, it will naturally get - evicted as required. */ - - return; + /* + * Don't use OCBI to invalidate the lines. That costs cycles + * directly. If the dummy block is just left resident, it will + * naturally get evicted as required. + */ } -/****************************************************************************/ - +/* + * Purge the entire contents of the dcache. The most efficient way to + * achieve this is to use alloco instructions on a region of unused + * memory equal in size to the cache, thereby causing the current + * contents to be discarded by natural eviction. The alternative, namely + * reading every tag, setting up a mapping for the corresponding page and + * doing an OCBP for the line, would be much more expensive. + */ static void sh64_dcache_purge_all(void) { - /* Purge the entire contents of the dcache. The most efficient way to - achieve this is to use alloco instructions on a region of unused - memory equal in size to the cache, thereby causing the current - contents to be discarded by natural eviction. The alternative, - namely reading every tag, setting up a mapping for the corresponding - page and doing an OCBP for the line, would be much more expensive. - */ sh64_dcache_purge_sets(0, cpu_data->dcache.sets); - - return; - } -/****************************************************************************/ - -static void sh64_dcache_purge_kernel_range(unsigned long start, unsigned long end) -{ - /* Purge the range of addresses [start,end] from the D-cache. The - addresses lie in the superpage mapping. There's no harm if we - overpurge at either end - just a small performance loss. */ - unsigned long long ullend, addr, aligned_start; -#if (NEFF == 32) - aligned_start = (unsigned long long)(signed long long)(signed long) start; -#else -#error "NEFF != 32" -#endif - aligned_start &= L1_CACHE_ALIGN_MASK; - addr = aligned_start; -#if (NEFF == 32) - ullend = (unsigned long long) (signed long long) (signed long) end; -#else -#error "NEFF != 32" -#endif - while (addr <= ullend) { - asm __volatile__ ("ocbp %0, 0" : : "r" (addr)); - addr += L1_CACHE_BYTES; - } - return; -} /* Assumes this address (+ (2**n_synbits) pages up from it) aren't used for anything else in the kernel */ #define MAGIC_PAGE0_START 0xffffffffec000000ULL -static void sh64_dcache_purge_coloured_phy_page(unsigned long paddr, unsigned long eaddr) +/* Purge the physical page 'paddr' from the cache. It's known that any + * cache lines requiring attention have the same page colour as the the + * address 'eaddr'. + * + * This relies on the fact that the D-cache matches on physical tags when + * no virtual tag matches. So we create an alias for the original page + * and purge through that. (Alternatively, we could have done this by + * switching ASID to match the original mapping and purged through that, + * but that involves ASID switching cost + probably a TLBMISS + refill + * anyway.) + */ +static void sh64_dcache_purge_coloured_phy_page(unsigned long paddr, + unsigned long eaddr) { - /* Purge the physical page 'paddr' from the cache. It's known that any - cache lines requiring attention have the same page colour as the the - address 'eaddr'. - - This relies on the fact that the D-cache matches on physical tags - when no virtual tag matches. So we create an alias for the original - page and purge through that. (Alternatively, we could have done - this by switching ASID to match the original mapping and purged - through that, but that involves ASID switching cost + probably a - TLBMISS + refill anyway.) - */ - unsigned long long magic_page_start; unsigned long long magic_eaddr, magic_eaddr_end; @@ -531,47 +393,45 @@ static void sh64_dcache_purge_coloured_phy_page(unsigned long paddr, unsigned lo /* As long as the kernel is not pre-emptible, this doesn't need to be under cli/sti. */ - sh64_setup_dtlb_cache_slot(magic_page_start, get_asid(), paddr); magic_eaddr = magic_page_start; magic_eaddr_end = magic_eaddr + PAGE_SIZE; + while (magic_eaddr < magic_eaddr_end) { /* Little point in unrolling this loop - the OCBPs are blocking and won't go any quicker (i.e. the loop overhead is parallel to part of the OCBP execution.) */ - asm __volatile__ ("ocbp %0, 0" : : "r" (magic_eaddr)); + __asm__ __volatile__ ("ocbp %0, 0" : : "r" (magic_eaddr)); magic_eaddr += L1_CACHE_BYTES; } sh64_teardown_dtlb_cache_slot(); } -/****************************************************************************/ - +/* + * Purge a page given its physical start address, by creating a temporary + * 1 page mapping and purging across that. Even if we know the virtual + * address (& vma or mm) of the page, the method here is more elegant + * because it avoids issues of coping with page faults on the purge + * instructions (i.e. no special-case code required in the critical path + * in the TLB miss handling). + */ static void sh64_dcache_purge_phy_page(unsigned long paddr) { - /* Pure a page given its physical start address, by creating a - temporary 1 page mapping and purging across that. Even if we know - the virtual address (& vma or mm) of the page, the method here is - more elegant because it avoids issues of coping with page faults on - the purge instructions (i.e. no special-case code required in the - critical path in the TLB miss handling). */ - unsigned long long eaddr_start, eaddr, eaddr_end; int i; /* As long as the kernel is not pre-emptible, this doesn't need to be under cli/sti. */ - eaddr_start = MAGIC_PAGE0_START; - for (i=0; i < (1 << CACHE_OC_N_SYNBITS); i++) { + for (i = 0; i < (1 << CACHE_OC_N_SYNBITS); i++) { sh64_setup_dtlb_cache_slot(eaddr_start, get_asid(), paddr); eaddr = eaddr_start; eaddr_end = eaddr + PAGE_SIZE; while (eaddr < eaddr_end) { - asm __volatile__ ("ocbp %0, 0" : : "r" (eaddr)); + __asm__ __volatile__ ("ocbp %0, 0" : : "r" (eaddr)); eaddr += L1_CACHE_BYTES; } @@ -584,6 +444,7 @@ static void sh64_dcache_purge_user_pages(struct mm_struct *mm, unsigned long addr, unsigned long end) { pgd_t *pgd; + pud_t *pud; pmd_t *pmd; pte_t *pte; pte_t entry; @@ -597,7 +458,11 @@ static void sh64_dcache_purge_user_pages(struct mm_struct *mm, if (pgd_bad(*pgd)) return; - pmd = pmd_offset(pgd, addr); + pud = pud_offset(pgd, addr); + if (pud_none(*pud) || pud_bad(*pud)) + return; + + pmd = pmd_offset(pud, addr); if (pmd_none(*pmd) || pmd_bad(*pmd)) return; @@ -611,151 +476,260 @@ static void sh64_dcache_purge_user_pages(struct mm_struct *mm, } while (pte++, addr += PAGE_SIZE, addr != end); pte_unmap_unlock(pte - 1, ptl); } -/****************************************************************************/ +/* + * There are at least 5 choices for the implementation of this, with + * pros (+), cons(-), comments(*): + * + * 1. ocbp each line in the range through the original user's ASID + * + no lines spuriously evicted + * - tlbmiss handling (must either handle faults on demand => extra + * special-case code in tlbmiss critical path), or map the page in + * advance (=> flush_tlb_range in advance to avoid multiple hits) + * - ASID switching + * - expensive for large ranges + * + * 2. temporarily map each page in the range to a special effective + * address and ocbp through the temporary mapping; relies on the + * fact that SH-5 OCB* always do TLB lookup and match on ptags (they + * never look at the etags) + * + no spurious evictions + * - expensive for large ranges + * * surely cheaper than (1) + * + * 3. walk all the lines in the cache, check the tags, if a match + * occurs create a page mapping to ocbp the line through + * + no spurious evictions + * - tag inspection overhead + * - (especially for small ranges) + * - potential cost of setting up/tearing down page mapping for + * every line that matches the range + * * cost partly independent of range size + * + * 4. walk all the lines in the cache, check the tags, if a match + * occurs use 4 * alloco to purge the line (+3 other probably + * innocent victims) by natural eviction + * + no tlb mapping overheads + * - spurious evictions + * - tag inspection overhead + * + * 5. implement like flush_cache_all + * + no tag inspection overhead + * - spurious evictions + * - bad for small ranges + * + * (1) can be ruled out as more expensive than (2). (2) appears best + * for small ranges. The choice between (3), (4) and (5) for large + * ranges and the range size for the large/small boundary need + * benchmarking to determine. + * + * For now use approach (2) for small ranges and (5) for large ones. + */ static void sh64_dcache_purge_user_range(struct mm_struct *mm, unsigned long start, unsigned long end) { - /* There are at least 5 choices for the implementation of this, with - pros (+), cons(-), comments(*): + int n_pages = ((end - start) >> PAGE_SHIFT); - 1. ocbp each line in the range through the original user's ASID - + no lines spuriously evicted - - tlbmiss handling (must either handle faults on demand => extra - special-case code in tlbmiss critical path), or map the page in - advance (=> flush_tlb_range in advance to avoid multiple hits) - - ASID switching - - expensive for large ranges - - 2. temporarily map each page in the range to a special effective - address and ocbp through the temporary mapping; relies on the - fact that SH-5 OCB* always do TLB lookup and match on ptags (they - never look at the etags) - + no spurious evictions - - expensive for large ranges - * surely cheaper than (1) - - 3. walk all the lines in the cache, check the tags, if a match - occurs create a page mapping to ocbp the line through - + no spurious evictions - - tag inspection overhead - - (especially for small ranges) - - potential cost of setting up/tearing down page mapping for - every line that matches the range - * cost partly independent of range size - - 4. walk all the lines in the cache, check the tags, if a match - occurs use 4 * alloco to purge the line (+3 other probably - innocent victims) by natural eviction - + no tlb mapping overheads - - spurious evictions - - tag inspection overhead - - 5. implement like flush_cache_all - + no tag inspection overhead - - spurious evictions - - bad for small ranges - - (1) can be ruled out as more expensive than (2). (2) appears best - for small ranges. The choice between (3), (4) and (5) for large - ranges and the range size for the large/small boundary need - benchmarking to determine. - - For now use approach (2) for small ranges and (5) for large ones. - - */ - - int n_pages; - - n_pages = ((end - start) >> PAGE_SHIFT); if (n_pages >= 64 || ((start ^ (end - 1)) & PMD_MASK)) { -#if 1 sh64_dcache_purge_all(); -#else - unsigned long long set, way; - unsigned long mm_asid = mm->context & MMU_CONTEXT_ASID_MASK; - for (set = 0; set < cpu_data->dcache.sets; set++) { - unsigned long long set_base_config_addr = CACHE_OC_ADDRESS_ARRAY + (set << cpu_data->dcache.set_shift); - for (way = 0; way < cpu_data->dcache.ways; way++) { - unsigned long long config_addr = set_base_config_addr + (way << cpu_data->dcache.way_step_shift); - unsigned long long tag0; - unsigned long line_valid; - - asm __volatile__("getcfg %1, 0, %0" : "=r" (tag0) : "r" (config_addr)); - line_valid = tag0 & SH_CACHE_VALID; - if (line_valid) { - unsigned long cache_asid; - unsigned long epn; - - cache_asid = (tag0 & cpu_data->dcache.asid_mask) >> cpu_data->dcache.asid_shift; - /* The next line needs some - explanation. The virtual tags - encode bits [31:13] of the virtual - address, bit [12] of the 'tag' being - implied by the cache set index. */ - epn = (tag0 & cpu_data->dcache.epn_mask) | ((set & 0x80) << cpu_data->dcache.entry_shift); - - if ((cache_asid == mm_asid) && (start <= epn) && (epn < end)) { - /* TODO : could optimise this - call by batching multiple - adjacent sets together. */ - sh64_dcache_purge_sets(set, 1); - break; /* Don't waste time inspecting other ways for this set */ - } - } - } - } -#endif } else { /* Small range, covered by a single page table page */ start &= PAGE_MASK; /* should already be so */ end = PAGE_ALIGN(end); /* should already be so */ sh64_dcache_purge_user_pages(mm, start, end); } - return; } -static void sh64_dcache_wback_current_user_range(unsigned long start, unsigned long end) +/* + * Purge the range of addresses from the D-cache. + * + * The addresses lie in the superpage mapping. There's no harm if we + * overpurge at either end - just a small performance loss. + */ +void __flush_purge_region(void *start, int size) { - unsigned long long aligned_start; - unsigned long long ull_end; - unsigned long long addr; + unsigned long long ullend, addr, aligned_start; - ull_end = end; + aligned_start = (unsigned long long)(signed long long)(signed long) start; + addr = L1_CACHE_ALIGN(aligned_start); + ullend = (unsigned long long) (signed long long) (signed long) start + size; - /* Just wback over the range using the natural addresses. TLB miss - handling will be OK (TBC) : the range has just been written to by - the signal frame setup code, so the PTEs must exist. - - Note, if we have CONFIG_PREEMPT and get preempted inside this loop, - it doesn't matter, even if the pid->ASID mapping changes whilst - we're away. In that case the cache will have been flushed when the - mapping was renewed. So the writebacks below will be nugatory (and - we'll doubtless have to fault the TLB entry/ies in again with the - new ASID), but it's a rare case. - */ - aligned_start = start & L1_CACHE_ALIGN_MASK; - addr = aligned_start; - while (addr < ull_end) { - asm __volatile__ ("ocbwb %0, 0" : : "r" (addr)); + while (addr <= ullend) { + __asm__ __volatile__ ("ocbp %0, 0" : : "r" (addr)); addr += L1_CACHE_BYTES; } } -/****************************************************************************/ +void __flush_wback_region(void *start, int size) +{ + unsigned long long ullend, addr, aligned_start; -/* These *MUST* lie in an area of virtual address space that's otherwise unused. */ + aligned_start = (unsigned long long)(signed long long)(signed long) start; + addr = L1_CACHE_ALIGN(aligned_start); + ullend = (unsigned long long) (signed long long) (signed long) start + size; + + while (addr < ullend) { + __asm__ __volatile__ ("ocbwb %0, 0" : : "r" (addr)); + addr += L1_CACHE_BYTES; + } +} + +void __flush_invalidate_region(void *start, int size) +{ + unsigned long long ullend, addr, aligned_start; + + aligned_start = (unsigned long long)(signed long long)(signed long) start; + addr = L1_CACHE_ALIGN(aligned_start); + ullend = (unsigned long long) (signed long long) (signed long) start + size; + + while (addr < ullend) { + __asm__ __volatile__ ("ocbi %0, 0" : : "r" (addr)); + addr += L1_CACHE_BYTES; + } +} +#endif /* !CONFIG_DCACHE_DISABLED */ + +/* + * Invalidate the entire contents of both caches, after writing back to + * memory any dirty data from the D-cache. + */ +void flush_cache_all(void) +{ + sh64_dcache_purge_all(); + sh64_icache_inv_all(); +} + +/* + * Invalidate an entire user-address space from both caches, after + * writing back dirty data (e.g. for shared mmap etc). + * + * This could be coded selectively by inspecting all the tags then + * doing 4*alloco on any set containing a match (as for + * flush_cache_range), but fork/exit/execve (where this is called from) + * are expensive anyway. + * + * Have to do a purge here, despite the comments re I-cache below. + * There could be odd-coloured dirty data associated with the mm still + * in the cache - if this gets written out through natural eviction + * after the kernel has reused the page there will be chaos. + * + * The mm being torn down won't ever be active again, so any Icache + * lines tagged with its ASID won't be visible for the rest of the + * lifetime of this ASID cycle. Before the ASID gets reused, there + * will be a flush_cache_all. Hence we don't need to touch the + * I-cache. This is similar to the lack of action needed in + * flush_tlb_mm - see fault.c. + */ +void flush_cache_mm(struct mm_struct *mm) +{ + sh64_dcache_purge_all(); +} + +/* + * Invalidate (from both caches) the range [start,end) of virtual + * addresses from the user address space specified by mm, after writing + * back any dirty data. + * + * Note, 'end' is 1 byte beyond the end of the range to flush. + */ +void flush_cache_range(struct vm_area_struct *vma, unsigned long start, + unsigned long end) +{ + struct mm_struct *mm = vma->vm_mm; + + sh64_dcache_purge_user_range(mm, start, end); + sh64_icache_inv_user_page_range(mm, start, end); +} + +/* + * Invalidate any entries in either cache for the vma within the user + * address space vma->vm_mm for the page starting at virtual address + * 'eaddr'. This seems to be used primarily in breaking COW. Note, + * the I-cache must be searched too in case the page in question is + * both writable and being executed from (e.g. stack trampolines.) + * + * Note, this is called with pte lock held. + */ +void flush_cache_page(struct vm_area_struct *vma, unsigned long eaddr, + unsigned long pfn) +{ + sh64_dcache_purge_phy_page(pfn << PAGE_SHIFT); + + if (vma->vm_flags & VM_EXEC) + sh64_icache_inv_user_page(vma, eaddr); +} + +void flush_dcache_page(struct page *page) +{ + sh64_dcache_purge_phy_page(page_to_phys(page)); + wmb(); +} + +/* + * Flush the range [start,end] of kernel virtual adddress space from + * the I-cache. The corresponding range must be purged from the + * D-cache also because the SH-5 doesn't have cache snooping between + * the caches. The addresses will be visible through the superpage + * mapping, therefore it's guaranteed that there no cache entries for + * the range in cache sets of the wrong colour. + */ +void flush_icache_range(unsigned long start, unsigned long end) +{ + __flush_purge_region((void *)start, end); + wmb(); + sh64_icache_inv_kernel_range(start, end); +} + +/* + * Flush the range of user (defined by vma->vm_mm) address space starting + * at 'addr' for 'len' bytes from the cache. The range does not straddle + * a page boundary, the unique physical page containing the range is + * 'page'. This seems to be used mainly for invalidating an address + * range following a poke into the program text through the ptrace() call + * from another process (e.g. for BRK instruction insertion). + */ +void flush_icache_user_range(struct vm_area_struct *vma, + struct page *page, unsigned long addr, int len) +{ + + sh64_dcache_purge_coloured_phy_page(page_to_phys(page), addr); + mb(); + + if (vma->vm_flags & VM_EXEC) + sh64_icache_inv_user_small_range(vma->vm_mm, addr, len); +} + +/* + * For the address range [start,end), write back the data from the + * D-cache and invalidate the corresponding region of the I-cache for the + * current process. Used to flush signal trampolines on the stack to + * make them executable. + */ +void flush_cache_sigtramp(unsigned long vaddr) +{ + unsigned long end = vaddr + L1_CACHE_BYTES; + + __flush_wback_region((void *)vaddr, L1_CACHE_BYTES); + wmb(); + sh64_icache_inv_current_user_range(vaddr, end); +} + +/* + * These *MUST* lie in an area of virtual address space that's otherwise + * unused. + */ #define UNIQUE_EADDR_START 0xe0000000UL #define UNIQUE_EADDR_END 0xe8000000UL -static unsigned long sh64_make_unique_eaddr(unsigned long user_eaddr, unsigned long paddr) +/* + * Given a physical address paddr, and a user virtual address user_eaddr + * which will eventually be mapped to it, create a one-off kernel-private + * eaddr mapped to the same paddr. This is used for creating special + * destination pages for copy_user_page and clear_user_page. + */ +static unsigned long sh64_make_unique_eaddr(unsigned long user_eaddr, + unsigned long paddr) { - /* Given a physical address paddr, and a user virtual address - user_eaddr which will eventually be mapped to it, create a one-off - kernel-private eaddr mapped to the same paddr. This is used for - creating special destination pages for copy_user_page and - clear_user_page */ - static unsigned long current_pointer = UNIQUE_EADDR_START; unsigned long coloured_pointer; @@ -764,7 +738,8 @@ static unsigned long sh64_make_unique_eaddr(unsigned long user_eaddr, unsigned l current_pointer = UNIQUE_EADDR_START; } - coloured_pointer = (current_pointer & ~CACHE_OC_SYN_MASK) | (user_eaddr & CACHE_OC_SYN_MASK); + coloured_pointer = (current_pointer & ~CACHE_OC_SYN_MASK) | + (user_eaddr & CACHE_OC_SYN_MASK); sh64_setup_dtlb_cache_slot(coloured_pointer, get_asid(), paddr); current_pointer += (PAGE_SIZE << CACHE_OC_N_SYNBITS); @@ -772,20 +747,20 @@ static unsigned long sh64_make_unique_eaddr(unsigned long user_eaddr, unsigned l return coloured_pointer; } -/****************************************************************************/ - -static void sh64_copy_user_page_coloured(void *to, void *from, unsigned long address) +static void sh64_copy_user_page_coloured(void *to, void *from, + unsigned long address) { void *coloured_to; - /* Discard any existing cache entries of the wrong colour. These are - present quite often, if the kernel has recently used the page - internally, then given it up, then it's been allocated to the user. - */ - sh64_dcache_purge_coloured_phy_page(__pa(to), (unsigned long) to); + /* + * Discard any existing cache entries of the wrong colour. These are + * present quite often, if the kernel has recently used the page + * internally, then given it up, then it's been allocated to the user. + */ + sh64_dcache_purge_coloured_phy_page(__pa(to), (unsigned long)to); - coloured_to = (void *) sh64_make_unique_eaddr(address, __pa(to)); - sh64_page_copy(from, coloured_to); + coloured_to = (void *)sh64_make_unique_eaddr(address, __pa(to)); + copy_page(from, coloured_to); sh64_teardown_dtlb_cache_slot(); } @@ -794,236 +769,64 @@ static void sh64_clear_user_page_coloured(void *to, unsigned long address) { void *coloured_to; - /* Discard any existing kernel-originated lines of the wrong colour (as - above) */ - sh64_dcache_purge_coloured_phy_page(__pa(to), (unsigned long) to); + /* + * Discard any existing kernel-originated lines of the wrong + * colour (as above) + */ + sh64_dcache_purge_coloured_phy_page(__pa(to), (unsigned long)to); - coloured_to = (void *) sh64_make_unique_eaddr(address, __pa(to)); - sh64_page_clear(coloured_to); + coloured_to = (void *)sh64_make_unique_eaddr(address, __pa(to)); + clear_page(coloured_to); sh64_teardown_dtlb_cache_slot(); } -#endif /* !CONFIG_DCACHE_DISABLED */ - -/****************************************************************************/ - -/*########################################################################## - EXTERNALLY CALLABLE API. - ##########################################################################*/ - -/* These functions are described in Documentation/cachetlb.txt. - Each one of these functions varies in behaviour depending on whether the - I-cache and/or D-cache are configured out. - - Note that the Linux term 'flush' corresponds to what is termed 'purge' in - the sh/sh64 jargon for the D-cache, i.e. write back dirty data then - invalidate the cache lines, and 'invalidate' for the I-cache. - */ - -#undef FLUSH_TRACE - -void flush_cache_all(void) +/* + * 'from' and 'to' are kernel virtual addresses (within the superpage + * mapping of the physical RAM). 'address' is the user virtual address + * where the copy 'to' will be mapped after. This allows a custom + * mapping to be used to ensure that the new copy is placed in the + * right cache sets for the user to see it without having to bounce it + * out via memory. Note however : the call to flush_page_to_ram in + * (generic)/mm/memory.c:(break_cow) undoes all this good work in that one + * very important case! + * + * TBD : can we guarantee that on every call, any cache entries for + * 'from' are in the same colour sets as 'address' also? i.e. is this + * always used just to deal with COW? (I suspect not). + * + * There are two possibilities here for when the page 'from' was last accessed: + * - by the kernel : this is OK, no purge required. + * - by the/a user (e.g. for break_COW) : need to purge. + * + * If the potential user mapping at 'address' is the same colour as + * 'from' there is no need to purge any cache lines from the 'from' + * page mapped into cache sets of colour 'address'. (The copy will be + * accessing the page through 'from'). + */ +void copy_user_page(void *to, void *from, unsigned long address, + struct page *page) { - /* Invalidate the entire contents of both caches, after writing back to - memory any dirty data from the D-cache. */ - sh64_dcache_purge_all(); - sh64_icache_inv_all(); -} - -/****************************************************************************/ - -void flush_cache_mm(struct mm_struct *mm) -{ - /* Invalidate an entire user-address space from both caches, after - writing back dirty data (e.g. for shared mmap etc). */ - - /* This could be coded selectively by inspecting all the tags then - doing 4*alloco on any set containing a match (as for - flush_cache_range), but fork/exit/execve (where this is called from) - are expensive anyway. */ - - /* Have to do a purge here, despite the comments re I-cache below. - There could be odd-coloured dirty data associated with the mm still - in the cache - if this gets written out through natural eviction - after the kernel has reused the page there will be chaos. - */ - - sh64_dcache_purge_all(); - - /* The mm being torn down won't ever be active again, so any Icache - lines tagged with its ASID won't be visible for the rest of the - lifetime of this ASID cycle. Before the ASID gets reused, there - will be a flush_cache_all. Hence we don't need to touch the - I-cache. This is similar to the lack of action needed in - flush_tlb_mm - see fault.c. */ -} - -/****************************************************************************/ - -void flush_cache_range(struct vm_area_struct *vma, unsigned long start, - unsigned long end) -{ - struct mm_struct *mm = vma->vm_mm; - - /* Invalidate (from both caches) the range [start,end) of virtual - addresses from the user address space specified by mm, after writing - back any dirty data. - - Note, 'end' is 1 byte beyond the end of the range to flush. */ - - sh64_dcache_purge_user_range(mm, start, end); - sh64_icache_inv_user_page_range(mm, start, end); -} - -/****************************************************************************/ - -void flush_cache_page(struct vm_area_struct *vma, unsigned long eaddr, unsigned long pfn) -{ - /* Invalidate any entries in either cache for the vma within the user - address space vma->vm_mm for the page starting at virtual address - 'eaddr'. This seems to be used primarily in breaking COW. Note, - the I-cache must be searched too in case the page in question is - both writable and being executed from (e.g. stack trampolines.) - - Note, this is called with pte lock held. - */ - - sh64_dcache_purge_phy_page(pfn << PAGE_SHIFT); - - if (vma->vm_flags & VM_EXEC) { - sh64_icache_inv_user_page(vma, eaddr); - } -} - -/****************************************************************************/ - -#ifndef CONFIG_DCACHE_DISABLED - -void copy_user_page(void *to, void *from, unsigned long address, struct page *page) -{ - /* 'from' and 'to' are kernel virtual addresses (within the superpage - mapping of the physical RAM). 'address' is the user virtual address - where the copy 'to' will be mapped after. This allows a custom - mapping to be used to ensure that the new copy is placed in the - right cache sets for the user to see it without having to bounce it - out via memory. Note however : the call to flush_page_to_ram in - (generic)/mm/memory.c:(break_cow) undoes all this good work in that one - very important case! - - TBD : can we guarantee that on every call, any cache entries for - 'from' are in the same colour sets as 'address' also? i.e. is this - always used just to deal with COW? (I suspect not). */ - - /* There are two possibilities here for when the page 'from' was last accessed: - * by the kernel : this is OK, no purge required. - * by the/a user (e.g. for break_COW) : need to purge. - - If the potential user mapping at 'address' is the same colour as - 'from' there is no need to purge any cache lines from the 'from' - page mapped into cache sets of colour 'address'. (The copy will be - accessing the page through 'from'). - */ - - if (((address ^ (unsigned long) from) & CACHE_OC_SYN_MASK) != 0) { + if (((address ^ (unsigned long) from) & CACHE_OC_SYN_MASK) != 0) sh64_dcache_purge_coloured_phy_page(__pa(from), address); - } - if (((address ^ (unsigned long) to) & CACHE_OC_SYN_MASK) == 0) { - /* No synonym problem on destination */ - sh64_page_copy(from, to); - } else { + if (((address ^ (unsigned long) to) & CACHE_OC_SYN_MASK) == 0) + copy_page(to, from); + else sh64_copy_user_page_coloured(to, from, address); - } - - /* Note, don't need to flush 'from' page from the cache again - it's - done anyway by the generic code */ } +/* + * 'to' is a kernel virtual address (within the superpage mapping of the + * physical RAM). 'address' is the user virtual address where the 'to' + * page will be mapped after. This allows a custom mapping to be used to + * ensure that the new copy is placed in the right cache sets for the + * user to see it without having to bounce it out via memory. + */ void clear_user_page(void *to, unsigned long address, struct page *page) { - /* 'to' is a kernel virtual address (within the superpage - mapping of the physical RAM). 'address' is the user virtual address - where the 'to' page will be mapped after. This allows a custom - mapping to be used to ensure that the new copy is placed in the - right cache sets for the user to see it without having to bounce it - out via memory. - */ - - if (((address ^ (unsigned long) to) & CACHE_OC_SYN_MASK) == 0) { - /* No synonym problem on destination */ - sh64_page_clear(to); - } else { + if (((address ^ (unsigned long) to) & CACHE_OC_SYN_MASK) == 0) + clear_page(to); + else sh64_clear_user_page_coloured(to, address); - } } - -#endif /* !CONFIG_DCACHE_DISABLED */ - -/****************************************************************************/ - -void flush_dcache_page(struct page *page) -{ - sh64_dcache_purge_phy_page(page_to_phys(page)); - wmb(); -} - -/****************************************************************************/ - -void flush_icache_range(unsigned long start, unsigned long end) -{ - /* Flush the range [start,end] of kernel virtual adddress space from - the I-cache. The corresponding range must be purged from the - D-cache also because the SH-5 doesn't have cache snooping between - the caches. The addresses will be visible through the superpage - mapping, therefore it's guaranteed that there no cache entries for - the range in cache sets of the wrong colour. - - Primarily used for cohering the I-cache after a module has - been loaded. */ - - /* We also make sure to purge the same range from the D-cache since - flush_page_to_ram() won't be doing this for us! */ - - sh64_dcache_purge_kernel_range(start, end); - wmb(); - sh64_icache_inv_kernel_range(start, end); -} - -/****************************************************************************/ - -void flush_icache_user_range(struct vm_area_struct *vma, - struct page *page, unsigned long addr, int len) -{ - /* Flush the range of user (defined by vma->vm_mm) address space - starting at 'addr' for 'len' bytes from the cache. The range does - not straddle a page boundary, the unique physical page containing - the range is 'page'. This seems to be used mainly for invalidating - an address range following a poke into the program text through the - ptrace() call from another process (e.g. for BRK instruction - insertion). */ - - sh64_dcache_purge_coloured_phy_page(page_to_phys(page), addr); - mb(); - - if (vma->vm_flags & VM_EXEC) { - sh64_icache_inv_user_small_range(vma->vm_mm, addr, len); - } -} - -/*########################################################################## - ARCH/SH64 PRIVATE CALLABLE API. - ##########################################################################*/ - -void flush_cache_sigtramp(unsigned long start, unsigned long end) -{ - /* For the address range [start,end), write back the data from the - D-cache and invalidate the corresponding region of the I-cache for - the current process. Used to flush signal trampolines on the stack - to make them executable. */ - - sh64_dcache_wback_current_user_range(start, end); - wmb(); - sh64_icache_inv_current_user_range(start, end); -} - diff --git a/arch/sh/mm/consistent.c b/arch/sh/mm/consistent.c index 7b2131c9eeda..d3c33fc5b1c2 100644 --- a/arch/sh/mm/consistent.c +++ b/arch/sh/mm/consistent.c @@ -26,7 +26,7 @@ struct dma_coherent_mem { void *dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t gfp) { - void *ret; + void *ret, *ret_nocache; struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL; int order = get_order(size); @@ -44,17 +44,24 @@ void *dma_alloc_coherent(struct device *dev, size_t size, } ret = (void *)__get_free_pages(gfp, order); + if (!ret) + return NULL; - if (ret != NULL) { - memset(ret, 0, size); - /* - * Pages from the page allocator may have data present in - * cache. So flush the cache before using uncached memory. - */ - dma_cache_sync(NULL, ret, size, DMA_BIDIRECTIONAL); - *dma_handle = virt_to_phys(ret); + memset(ret, 0, size); + /* + * Pages from the page allocator may have data present in + * cache. So flush the cache before using uncached memory. + */ + dma_cache_sync(dev, ret, size, DMA_BIDIRECTIONAL); + + ret_nocache = ioremap_nocache(virt_to_phys(ret), size); + if (!ret_nocache) { + free_pages((unsigned long)ret, order); + return NULL; } - return ret; + + *dma_handle = virt_to_phys(ret); + return ret_nocache; } EXPORT_SYMBOL(dma_alloc_coherent); @@ -71,7 +78,8 @@ void dma_free_coherent(struct device *dev, size_t size, } else { WARN_ON(irqs_disabled()); /* for portability */ BUG_ON(mem && mem->flags & DMA_MEMORY_EXCLUSIVE); - free_pages((unsigned long)vaddr, order); + free_pages((unsigned long)phys_to_virt(dma_handle), order); + iounmap(vaddr); } } EXPORT_SYMBOL(dma_free_coherent); diff --git a/arch/sh/mm/fault_32.c b/arch/sh/mm/fault_32.c index 33b43d20e9f6..d1fa27594c6e 100644 --- a/arch/sh/mm/fault_32.c +++ b/arch/sh/mm/fault_32.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -163,6 +164,8 @@ no_context: if (fixup_exception(regs)) return; + if (handle_trapped_io(regs, address)) + return; /* * Oops. The kernel tried to access some bad page. We'll have to * terminate things with extreme prejudice. @@ -296,6 +299,14 @@ asmlinkage int __kprobes __do_page_fault(struct pt_regs *regs, entry = pte_mkdirty(entry); entry = pte_mkyoung(entry); +#if defined(CONFIG_CPU_SH4) && !defined(CONFIG_SMP) + /* + * ITLB is not affected by "ldtlb" instruction. + * So, we need to flush the entry by ourselves. + */ + local_flush_tlb_one(get_asid(), address & PAGE_MASK); +#endif + set_pte(pte, entry); update_mmu_cache(NULL, address, entry); diff --git a/arch/sh/mm/init.c b/arch/sh/mm/init.c index 2918c6b14659..e2ed6dd252b9 100644 --- a/arch/sh/mm/init.c +++ b/arch/sh/mm/init.c @@ -203,6 +203,7 @@ void __init paging_init(void) free_area_init_nodes(max_zone_pfns); +#ifdef CONFIG_SUPERH32 /* Set up the uncached fixmap */ set_fixmap_nocache(FIX_UNCACHED, __pa(&__uncached_start)); @@ -214,6 +215,7 @@ void __init paging_init(void) */ cached_to_uncached = P2SEG - P1SEG; #endif +#endif } static struct kcore_list kcore_mem, kcore_vmalloc; diff --git a/arch/sh/tools/mach-types b/arch/sh/tools/mach-types index 25810670a0fa..67997af25c0c 100644 --- a/arch/sh/tools/mach-types +++ b/arch/sh/tools/mach-types @@ -45,3 +45,5 @@ MAGICPANELR2 SH_MAGIC_PANEL_R2 R2D_PLUS RTS7751R2D_PLUS R2D_1 RTS7751R2D_1 CAYMAN SH_CAYMAN +SDK7780 SH_SDK7780 +MIGOR SH_MIGOR diff --git a/arch/sparc/kernel/process.c b/arch/sparc/kernel/process.c index 19186ce8850d..0bd69d0b5cd7 100644 --- a/arch/sparc/kernel/process.c +++ b/arch/sparc/kernel/process.c @@ -141,16 +141,12 @@ void cpu_idle(void) extern char reboot_command []; -extern void (*prom_palette)(int); - /* XXX cli/sti -> local_irq_xxx here, check this works once SMP is fixed. */ void machine_halt(void) { local_irq_enable(); mdelay(8); local_irq_disable(); - if (prom_palette) - prom_palette (1); prom_halt(); panic("Halt failed!"); } @@ -165,8 +161,6 @@ void machine_restart(char * cmd) p = strchr (reboot_command, '\n'); if (p) *p = 0; - if (prom_palette) - prom_palette (1); if (cmd) prom_reboot(cmd); if (*reboot_command) diff --git a/arch/sparc/kernel/setup.c b/arch/sparc/kernel/setup.c index 3cf78f160846..3c13137685da 100644 --- a/arch/sparc/kernel/setup.c +++ b/arch/sparc/kernel/setup.c @@ -65,7 +65,6 @@ struct screen_info screen_info = { */ extern unsigned long trapbase; -void (*prom_palette)(int); /* Pretty sick eh? */ void prom_sync_me(void) @@ -80,8 +79,6 @@ void prom_sync_me(void) "nop\n\t" "nop\n\t" : : "r" (&trapbase)); - if (prom_palette) - prom_palette(1); prom_printf("PROM SYNC COMMAND...\n"); show_free_areas(); if(current->pid != 0) { @@ -191,7 +188,6 @@ extern int prom_probe_memory(void); extern void sun4c_probe_vac(void); extern char cputypval; extern unsigned long start, end; -extern void panic_setup(char *, int *); extern unsigned short root_flags; extern unsigned short root_dev; diff --git a/arch/sparc/mm/sun4c.c b/arch/sparc/mm/sun4c.c index c0442e8c4b15..2375fe9dc312 100644 --- a/arch/sparc/mm/sun4c.c +++ b/arch/sparc/mm/sun4c.c @@ -1941,9 +1941,7 @@ static pte_t *sun4c_pte_alloc_one_kernel(struct mm_struct *mm, unsigned long add if ((pte = sun4c_pte_alloc_one_fast(mm, address)) != NULL) return pte; - pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT); - if (pte) - memset(pte, 0, PAGE_SIZE); + pte = (pte_t *)get_zeroed_page(GFP_KERNEL|__GFP_REPEAT); return pte; } diff --git a/arch/sparc/prom/misc.c b/arch/sparc/prom/misc.c index 37cff5f54704..d9fb3af41c1f 100644 --- a/arch/sparc/prom/misc.c +++ b/arch/sparc/prom/misc.c @@ -45,9 +45,6 @@ prom_feval(char *fstring) spin_unlock_irqrestore(&prom_lock, flags); } -/* We want to do this more nicely some day. */ -extern void (*prom_palette)(int); - /* Drop into the prom, with the chance to continue with the 'go' * prom command. */ @@ -58,8 +55,6 @@ prom_cmdline(void) extern void install_linux_ticker(void); unsigned long flags; - if (prom_palette) - prom_palette (1); spin_lock_irqsave(&prom_lock, flags); install_obp_ticker(); (*(romvec->pv_abort))(); @@ -69,8 +64,6 @@ prom_cmdline(void) #ifdef CONFIG_SUN_AUXIO set_auxio(AUXIO_LED, 0); #endif - if (prom_palette) - prom_palette (0); } /* Drop into the prom, but completely terminate the program. diff --git a/arch/sparc64/Kconfig.debug b/arch/sparc64/Kconfig.debug index a5faa3683bd6..6a4d28a4076d 100644 --- a/arch/sparc64/Kconfig.debug +++ b/arch/sparc64/Kconfig.debug @@ -23,10 +23,6 @@ config STACK_DEBUG depends on DEBUG_KERNEL bool "Stack Overflow Detection Support" -config DEBUG_BOOTMEM - depends on DEBUG_KERNEL - bool "Debug BOOTMEM initialization" - config DEBUG_PAGEALLOC bool "Debug page memory allocations" depends on DEBUG_KERNEL && !HIBERNATION diff --git a/arch/sparc64/Makefile b/arch/sparc64/Makefile index 01159cb5f16d..f0c22f826982 100644 --- a/arch/sparc64/Makefile +++ b/arch/sparc64/Makefile @@ -12,39 +12,13 @@ CHECKFLAGS += -D__sparc__ -D__sparc_v9__ -m64 CPPFLAGS_vmlinux.lds += -Usparc -CC := $(shell if $(CC) -m64 -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo $(CC); else echo sparc64-linux-gcc; fi ) - -NEW_GCC := $(call cc-option-yn, -m64 -mcmodel=medlow) -NEW_GAS := $(shell if $(LD) -V 2>&1 | grep 'elf64_sparc' > /dev/null; then echo y; else echo n; fi) -UNDECLARED_REGS := $(shell if $(CC) -c -x assembler /dev/null -Wa,--help | grep undeclared-regs > /dev/null; then echo y; else echo n; fi; ) - -ifneq ($(NEW_GAS),y) -AS = sparc64-linux-as -LD = sparc64-linux-ld -NM = sparc64-linux-nm -AR = sparc64-linux-ar -RANLIB = sparc64-linux-ranlib -else -AS := $(AS) -64 LDFLAGS := -m elf64_sparc -endif -ifneq ($(UNDECLARED_REGS),y) -CC_UNDECL = -else -CC_UNDECL = -Wa,--undeclared-regs -AS := $(AS) --undeclared-regs -endif - -ifneq ($(NEW_GCC),y) - KBUILD_CFLAGS += -pipe -mno-fpu -mtune=ultrasparc -mmedlow \ - -ffixed-g4 -ffixed-g5 -fcall-used-g7 -Wno-sign-compare -else - KBUILD_CFLAGS += -m64 -pipe -mno-fpu -mcpu=ultrasparc -mcmodel=medlow \ - -ffixed-g4 -ffixed-g5 -fcall-used-g7 -Wno-sign-compare \ - $(CC_UNDECL) - KBUILD_AFLAGS += -m64 -mcpu=ultrasparc $(CC_UNDECL) -endif +KBUILD_CFLAGS += -m64 -pipe -mno-fpu -mcpu=ultrasparc -mcmodel=medlow \ + -ffixed-g4 -ffixed-g5 -fcall-used-g7 -Wno-sign-compare \ + -Wa,--undeclared-regs +KBUILD_CFLAGS += $(call cc-option,-mtune=ultrasparc3) +KBUILD_AFLAGS += -m64 -mcpu=ultrasparc -Wa,--undeclared-regs ifeq ($(CONFIG_MCOUNT),y) KBUILD_CFLAGS += -pg diff --git a/arch/sparc64/defconfig b/arch/sparc64/defconfig index 833d74b2b192..250958d1e3cb 100644 --- a/arch/sparc64/defconfig +++ b/arch/sparc64/defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.24 -# Tue Feb 5 17:28:19 2008 +# Linux kernel version: 2.6.25-rc1 +# Sun Feb 17 22:44:12 2008 # CONFIG_SPARC=y CONFIG_SPARC64=y @@ -10,6 +10,7 @@ CONFIG_GENERIC_CMOS_UPDATE=y CONFIG_GENERIC_CLOCKEVENTS=y CONFIG_64BIT=y CONFIG_MMU=y +CONFIG_IOMMU_HELPER=y CONFIG_QUICKLIST=y CONFIG_STACKTRACE_SUPPORT=y CONFIG_LOCKDEP_SUPPORT=y @@ -21,6 +22,7 @@ CONFIG_HAVE_SETUP_PER_CPU_AREA=y CONFIG_ARCH_NO_VIRT_TO_BUS=y CONFIG_OF=y CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y +CONFIG_ARCH_SUPPORTS_AOUT=y CONFIG_SPARC64_PAGE_SIZE_8KB=y # CONFIG_SPARC64_PAGE_SIZE_64KB is not set # CONFIG_SPARC64_PAGE_SIZE_512KB is not set @@ -49,8 +51,6 @@ CONFIG_SYSVIPC_SYSCTL=y CONFIG_POSIX_MQUEUE=y # CONFIG_BSD_PROCESS_ACCT is not set # CONFIG_TASKSTATS is not set -# CONFIG_USER_NS is not set -# CONFIG_PID_NS is not set # CONFIG_AUDIT is not set # CONFIG_IKCONFIG is not set CONFIG_LOG_BUF_SHIFT=18 @@ -60,6 +60,11 @@ CONFIG_FAIR_USER_SCHED=y # CONFIG_FAIR_CGROUP_SCHED is not set CONFIG_SYSFS_DEPRECATED=y CONFIG_RELAY=y +CONFIG_NAMESPACES=y +# CONFIG_UTS_NS is not set +# CONFIG_IPC_NS is not set +# CONFIG_USER_NS is not set +# CONFIG_PID_NS is not set CONFIG_BLK_DEV_INITRD=y CONFIG_INITRAMFS_SOURCE="" CONFIG_CC_OPTIMIZE_FOR_SIZE=y @@ -74,6 +79,7 @@ CONFIG_HOTPLUG=y CONFIG_PRINTK=y CONFIG_BUG=y CONFIG_ELF_CORE=y +# CONFIG_COMPAT_BRK is not set CONFIG_BASE_FULL=y CONFIG_FUTEX=y CONFIG_ANON_INODES=y @@ -176,13 +182,13 @@ CONFIG_PCI_MSI=y CONFIG_SUN_OPENPROMFS=m CONFIG_SPARC32_COMPAT=y CONFIG_COMPAT=y -CONFIG_BINFMT_ELF32=y # CONFIG_BINFMT_AOUT32 is not set # # Executable file formats # CONFIG_BINFMT_ELF=y +CONFIG_COMPAT_BINFMT_ELF=y CONFIG_BINFMT_MISC=m CONFIG_SOLARIS_EMUL=y CONFIG_SCHED_SMT=y @@ -354,6 +360,8 @@ CONFIG_MISC_DEVICES=y # CONFIG_EEPROM_93CX6 is not set # CONFIG_SGI_IOC4 is not set # CONFIG_TIFM_CORE is not set +# CONFIG_ENCLOSURE_SERVICES is not set +CONFIG_HAVE_IDE=y CONFIG_IDE=y CONFIG_BLK_DEV_IDE=y @@ -376,6 +384,7 @@ CONFIG_IDE_PROC_FS=y # CONFIG_IDE_GENERIC=y # CONFIG_BLK_DEV_PLATFORM is not set +CONFIG_BLK_DEV_IDEDMA_SFF=y # # PCI IDE chipsets support @@ -775,7 +784,6 @@ CONFIG_I2C_ALGOBIT=y # CONFIG_SENSORS_EEPROM is not set # CONFIG_SENSORS_PCF8574 is not set # CONFIG_PCF8575 is not set -# CONFIG_SENSORS_PCA9539 is not set # CONFIG_SENSORS_PCF8591 is not set # CONFIG_TPS65010 is not set # CONFIG_SENSORS_MAX6875 is not set @@ -831,6 +839,7 @@ CONFIG_HWMON=y # CONFIG_SENSORS_SMSC47M1 is not set # CONFIG_SENSORS_SMSC47M192 is not set # CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_ADS7828 is not set # CONFIG_SENSORS_THMC50 is not set # CONFIG_SENSORS_VIA686A is not set # CONFIG_SENSORS_VT1211 is not set @@ -840,9 +849,11 @@ CONFIG_HWMON=y # CONFIG_SENSORS_W83792D is not set # CONFIG_SENSORS_W83793 is not set # CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83L786NG is not set # CONFIG_SENSORS_W83627HF is not set # CONFIG_SENSORS_W83627EHF is not set # CONFIG_HWMON_DEBUG_CHIP is not set +# CONFIG_THERMAL is not set # CONFIG_WATCHDOG is not set # @@ -1201,6 +1212,7 @@ CONFIG_USB_STORAGE=m # CONFIG_USB_TEST is not set # CONFIG_USB_GADGET is not set # CONFIG_MMC is not set +# CONFIG_MEMSTICK is not set # CONFIG_NEW_LEDS is not set # CONFIG_INFINIBAND is not set # CONFIG_RTC_CLASS is not set @@ -1242,12 +1254,10 @@ CONFIG_FS_POSIX_ACL=y # 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_DNOTIFY=y 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 @@ -1291,8 +1301,10 @@ CONFIG_HUGETLB_PAGE=y # CONFIG_EFS_FS is not set # CONFIG_CRAMFS is not set # CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set # CONFIG_HPFS_FS is not set # CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set # CONFIG_SYSV_FS is not set # CONFIG_UFS_FS is not set CONFIG_NETWORK_FILESYSTEMS=y @@ -1370,6 +1382,7 @@ CONFIG_DETECT_SOFTLOCKUP=y CONFIG_SCHEDSTATS=y # CONFIG_TIMER_STATS is not set # CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_SLUB_STATS is not set # CONFIG_DEBUG_RT_MUTEXES is not set # CONFIG_RT_MUTEX_TESTER is not set # CONFIG_DEBUG_SPINLOCK is not set @@ -1385,7 +1398,6 @@ CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_VM is not set # CONFIG_DEBUG_LIST is not set # CONFIG_DEBUG_SG is not set -CONFIG_FORCED_INLINING=y # CONFIG_BOOT_PRINTK_DELAY is not set # CONFIG_RCU_TORTURE_TEST is not set # CONFIG_KPROBES_SANITY_TEST is not set @@ -1396,7 +1408,6 @@ CONFIG_FORCED_INLINING=y # CONFIG_DEBUG_STACK_USAGE is not set # CONFIG_DEBUG_DCFLUSH is not set # CONFIG_STACK_DEBUG is not set -# CONFIG_DEBUG_BOOTMEM is not set # CONFIG_DEBUG_PAGEALLOC is not set # diff --git a/arch/sparc64/kernel/iommu.c b/arch/sparc64/kernel/iommu.c index d3276ebcfb47..0e347ff812a3 100644 --- a/arch/sparc64/kernel/iommu.c +++ b/arch/sparc64/kernel/iommu.c @@ -200,12 +200,11 @@ int iommu_table_init(struct iommu *iommu, int tsbsize, /* Allocate and initialize the dummy page which we * set inactive IO PTEs to point to. */ - iommu->dummy_page = __get_free_pages(GFP_KERNEL, 0); + iommu->dummy_page = get_zeroed_page(GFP_KERNEL); if (!iommu->dummy_page) { printk(KERN_ERR "IOMMU: Error, gfp(dummy_page) failed.\n"); goto out_free_map; } - memset((void *)iommu->dummy_page, 0, PAGE_SIZE); iommu->dummy_page_pa = (unsigned long) __pa(iommu->dummy_page); /* Now allocate and setup the IOMMU page table itself. */ diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index a61c38fe75ea..545356b00e2e 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c @@ -225,20 +225,6 @@ static int __init pci_controller_init(const char *model_name, int namelen, struc return 0; } -static int __init pci_is_controller(const char *model_name, int namelen, struct device_node *dp) -{ - int i; - - for (i = 0; i < PCI_NUM_CONTROLLER_TYPES; i++) { - if (!strncmp(model_name, - pci_controller_table[i].model_name, - namelen)) { - return 1; - } - } - return 0; -} - static int __init pci_controller_scan(int (*handler)(const char *, int, struct device_node *)) { struct device_node *dp; @@ -273,13 +259,6 @@ static int __init pci_controller_scan(int (*handler)(const char *, int, struct d return count; } - -/* Is there some PCI controller in the system? */ -int __init pcic_present(void) -{ - return pci_controller_scan(pci_is_controller); -} - /* Find each controller in the system, attach and initialize * software state structure for each and link into the * pci_pbm_root. Setup the controller enough such diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c index 1b2379174988..6eceac51ae62 100644 --- a/arch/sparc64/kernel/process.c +++ b/arch/sparc64/kernel/process.c @@ -113,16 +113,9 @@ void cpu_idle(void) extern char reboot_command []; -extern void (*prom_palette)(int); -extern void (*prom_keyboard)(void); - void machine_halt(void) { sstate_halt(); - if (prom_palette) - prom_palette (1); - if (prom_keyboard) - prom_keyboard(); prom_halt(); panic("Halt failed!"); } @@ -130,10 +123,6 @@ void machine_halt(void) void machine_alt_power_off(void) { sstate_poweroff(); - if (prom_palette) - prom_palette(1); - if (prom_keyboard) - prom_keyboard(); prom_halt_power_off(); panic("Power-off failed!"); } @@ -145,10 +134,6 @@ void machine_restart(char * cmd) sstate_reboot(); p = strchr (reboot_command, '\n'); if (p) *p = 0; - if (prom_palette) - prom_palette (1); - if (prom_keyboard) - prom_keyboard(); if (cmd) prom_reboot(cmd); if (*reboot_command) diff --git a/arch/sparc64/kernel/prom.c b/arch/sparc64/kernel/prom.c index a246e962e5a7..68964ddcde1e 100644 --- a/arch/sparc64/kernel/prom.c +++ b/arch/sparc64/kernel/prom.c @@ -1716,7 +1716,6 @@ static void __init of_console_init(void) of_console_device = dp; - prom_printf(msg, of_console_path); printk(msg, of_console_path); } diff --git a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c index 5964d8653ade..d036dbe72864 100644 --- a/arch/sparc64/kernel/setup.c +++ b/arch/sparc64/kernel/setup.c @@ -68,33 +68,22 @@ struct screen_info screen_info = { 16 /* orig-video-points */ }; -void (*prom_palette)(int); -void (*prom_keyboard)(void); - static void prom_console_write(struct console *con, const char *s, unsigned n) { prom_write(s, n); } -unsigned int boot_flags = 0; -#define BOOTME_DEBUG 0x1 - /* Exported for mm/init.c:paging_init. */ unsigned long cmdline_memory_size = 0; -static struct console prom_debug_console = { - .name = "debug", +static struct console prom_early_console = { + .name = "earlyprom", .write = prom_console_write, - .flags = CON_PRINTBUFFER, + .flags = CON_PRINTBUFFER | CON_BOOT, .index = -1, }; -/* XXX Implement this at some point... */ -void kernel_enter_debugger(void) -{ -} - /* * Process kernel command line switches that are specific to the * SPARC or that require special low-level processing. @@ -103,8 +92,6 @@ static void __init process_switch(char c) { switch (c) { case 'd': - boot_flags |= BOOTME_DEBUG; - break; case 's': break; case 'h': @@ -112,8 +99,7 @@ static void __init process_switch(char c) prom_halt(); break; case 'p': - /* Use PROM debug console. */ - register_console(&prom_debug_console); + /* Just ignore, this behavior is now the default. */ break; case 'P': /* Force UltraSPARC-III P-Cache on. */ @@ -168,8 +154,6 @@ static void __init boot_flags_init(char *commands) } } -extern void panic_setup(char *, int *); - extern unsigned short root_flags; extern unsigned short root_dev; extern unsigned short ram_flags; @@ -296,6 +280,9 @@ void __init setup_arch(char **cmdline_p) *cmdline_p = prom_getbootargs(); strcpy(boot_command_line, *cmdline_p); + boot_flags_init(*cmdline_p); + register_console(&prom_early_console); + if (tlb_type == hypervisor) printk("ARCH: SUN4V\n"); else @@ -307,8 +294,6 @@ void __init setup_arch(char **cmdline_p) conswitchp = &prom_con; #endif - boot_flags_init(*cmdline_p); - idprom_init(); if (!root_flags) diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c index 68db08930399..51fa773f38c9 100644 --- a/arch/sparc64/kernel/sparc64_ksyms.c +++ b/arch/sparc64/kernel/sparc64_ksyms.c @@ -85,7 +85,6 @@ extern int (*handle_mathemu)(struct pt_regs *, struct fpustate *); extern long sparc32_open(const char __user * filename, int flags, int mode); extern int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long from, unsigned long pfn, unsigned long size, pgprot_t prot); -extern void (*prom_palette)(int); extern int __ashrdi3(int, int); @@ -355,5 +354,3 @@ EXPORT_SYMBOL(xor_niagara_2); EXPORT_SYMBOL(xor_niagara_3); EXPORT_SYMBOL(xor_niagara_4); EXPORT_SYMBOL(xor_niagara_5); - -EXPORT_SYMBOL(prom_palette); diff --git a/arch/sparc64/kernel/unaligned.c b/arch/sparc64/kernel/unaligned.c index dc7bf1b6321c..1a511e9f0d3e 100644 --- a/arch/sparc64/kernel/unaligned.c +++ b/arch/sparc64/kernel/unaligned.c @@ -7,6 +7,7 @@ */ +#include #include #include #include @@ -283,7 +284,7 @@ static void log_unaligned(struct pt_regs *regs) { static unsigned long count, last_time; - if (jiffies - last_time > 5 * HZ) + if (time_after(jiffies, last_time + 5 * HZ)) count = 0; if (count < 5) { last_time = jiffies; diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c index e726c45645ff..9e6bca266d88 100644 --- a/arch/sparc64/mm/init.c +++ b/arch/sparc64/mm/init.c @@ -618,9 +618,9 @@ static void __init inherit_prom_mappings(void) read_obp_translations(); /* Now fixup OBP's idea about where we really are mapped. */ - prom_printf("Remapping the kernel... "); + printk("Remapping the kernel... "); remap_kernel(); - prom_printf("done.\n"); + printk("done.\n"); } void prom_world(int enter) @@ -739,11 +739,6 @@ static unsigned long __init choose_bootmap_pfn(unsigned long start_pfn, avoid_end = PAGE_ALIGN(initrd_end); #endif -#ifdef CONFIG_DEBUG_BOOTMEM - prom_printf("choose_bootmap_pfn: kern[%lx:%lx] avoid[%lx:%lx]\n", - kern_base, PAGE_ALIGN(kern_base + kern_size), - avoid_start, avoid_end); -#endif for (i = 0; i < pavail_ents; i++) { unsigned long start, end; @@ -777,10 +772,6 @@ static unsigned long __init choose_bootmap_pfn(unsigned long start_pfn, } /* OK, it doesn't overlap anything, use it. */ -#ifdef CONFIG_DEBUG_BOOTMEM - prom_printf("choose_bootmap_pfn: Using %lx [%lx]\n", - start >> PAGE_SHIFT, start); -#endif return start >> PAGE_SHIFT; } } @@ -920,10 +911,6 @@ static unsigned long __init bootmem_init(unsigned long *pages_avail, unsigned long bootmap_pfn, bytes_avail, size; int i; -#ifdef CONFIG_DEBUG_BOOTMEM - prom_printf("bootmem_init: Scan pavail, "); -#endif - bytes_avail = 0UL; for (i = 0; i < pavail_ents; i++) { end_of_phys_memory = pavail[i].phys_addr + @@ -970,33 +957,20 @@ static unsigned long __init bootmem_init(unsigned long *pages_avail, bootmap_pfn = choose_bootmap_pfn(min_low_pfn, end_pfn); -#ifdef CONFIG_DEBUG_BOOTMEM - prom_printf("init_bootmem(min[%lx], bootmap[%lx], max[%lx])\n", - min_low_pfn, bootmap_pfn, max_low_pfn); -#endif bootmap_size = init_bootmem_node(NODE_DATA(0), bootmap_pfn, min_low_pfn, end_pfn); /* Now register the available physical memory with the * allocator. */ - for (i = 0; i < pavail_ents; i++) { -#ifdef CONFIG_DEBUG_BOOTMEM - prom_printf("free_bootmem(pavail:%d): base[%lx] size[%lx]\n", - i, pavail[i].phys_addr, pavail[i].reg_size); -#endif + for (i = 0; i < pavail_ents; i++) free_bootmem(pavail[i].phys_addr, pavail[i].reg_size); - } #ifdef CONFIG_BLK_DEV_INITRD if (initrd_start) { size = initrd_end - initrd_start; /* Reserve the initrd image area. */ -#ifdef CONFIG_DEBUG_BOOTMEM - prom_printf("reserve_bootmem(initrd): base[%llx] size[%lx]\n", - initrd_start, initrd_end); -#endif reserve_bootmem(initrd_start, size, BOOTMEM_DEFAULT); initrd_start += PAGE_OFFSET; @@ -1004,9 +978,6 @@ static unsigned long __init bootmem_init(unsigned long *pages_avail, } #endif /* Reserve the kernel text/data/bss. */ -#ifdef CONFIG_DEBUG_BOOTMEM - prom_printf("reserve_bootmem(kernel): base[%lx] size[%lx]\n", kern_base, kern_size); -#endif reserve_bootmem(kern_base, kern_size, BOOTMEM_DEFAULT); *pages_avail -= PAGE_ALIGN(kern_size) >> PAGE_SHIFT; @@ -1020,10 +991,6 @@ static unsigned long __init bootmem_init(unsigned long *pages_avail, * in free_all_bootmem. */ size = bootmap_size; -#ifdef CONFIG_DEBUG_BOOTMEM - prom_printf("reserve_bootmem(bootmap): base[%lx] size[%lx]\n", - (bootmap_pfn << PAGE_SHIFT), size); -#endif reserve_bootmem((bootmap_pfn << PAGE_SHIFT), size, BOOTMEM_DEFAULT); for (i = 0; i < pavail_ents; i++) { @@ -1031,10 +998,6 @@ static unsigned long __init bootmem_init(unsigned long *pages_avail, start_pfn = pavail[i].phys_addr >> PAGE_SHIFT; end_pfn = (start_pfn + (pavail[i].reg_size >> PAGE_SHIFT)); -#ifdef CONFIG_DEBUG_BOOTMEM - prom_printf("memory_present(0, %lx, %lx)\n", - start_pfn, end_pfn); -#endif memory_present(0, start_pfn, end_pfn); } @@ -1451,7 +1414,7 @@ void __init paging_init(void) zholes_size); } - prom_printf("Booting Linux...\n"); + printk("Booting Linux...\n"); central_probe(); cpu_probe(); @@ -1549,10 +1512,6 @@ void __init mem_init(void) high_memory = __va(last_valid_pfn << PAGE_SHIFT); -#ifdef CONFIG_DEBUG_BOOTMEM - prom_printf("mem_init: Calling free_all_bootmem().\n"); -#endif - /* We subtract one to account for the mem_map_zero page * allocated below. */ diff --git a/arch/sparc64/prom/misc.c b/arch/sparc64/prom/misc.c index bbec7522826c..47a877a15abd 100644 --- a/arch/sparc64/prom/misc.c +++ b/arch/sparc64/prom/misc.c @@ -55,9 +55,6 @@ void prom_feval(const char *fstring) P1275_INOUT(1, 1), fstring); } -/* We want to do this more nicely some day. */ -extern void (*prom_palette)(int); - #ifdef CONFIG_SMP extern void smp_capture(void); extern void smp_release(void); @@ -72,9 +69,6 @@ void prom_cmdline(void) local_irq_save(flags); - if (prom_palette) - prom_palette(1); - #ifdef CONFIG_SMP smp_capture(); #endif @@ -85,9 +79,6 @@ void prom_cmdline(void) smp_release(); #endif - if (prom_palette) - prom_palette(0); - local_irq_restore(flags); } diff --git a/arch/sparc64/solaris/fs.c b/arch/sparc64/solaris/fs.c index 9311bfe4f2f7..7d035f0d3ae1 100644 --- a/arch/sparc64/solaris/fs.c +++ b/arch/sparc64/solaris/fs.c @@ -434,9 +434,9 @@ asmlinkage int solaris_statvfs(u32 path, u32 buf) error = user_path_walk(A(path),&nd); if (!error) { - struct inode * inode = nd.dentry->d_inode; - error = report_statvfs(nd.mnt, inode, buf); - path_release(&nd); + struct inode *inode = nd.path.dentry->d_inode; + error = report_statvfs(nd.path.mnt, inode, buf); + path_put(&nd.path); } return error; } @@ -464,9 +464,9 @@ asmlinkage int solaris_statvfs64(u32 path, u32 buf) lock_kernel(); error = user_path_walk(A(path), &nd); if (!error) { - struct inode * inode = nd.dentry->d_inode; - error = report_statvfs64(nd.mnt, inode, buf); - path_release(&nd); + struct inode *inode = nd.path.dentry->d_inode; + error = report_statvfs64(nd.path.mnt, inode, buf); + path_put(&nd.path); } unlock_kernel(); return error; diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c index ebb265c07e4d..19d579d74d27 100644 --- a/arch/um/drivers/mconsole_kern.c +++ b/arch/um/drivers/mconsole_kern.c @@ -145,8 +145,8 @@ void mconsole_proc(struct mc_request *req) } up_write(&super->s_umount); - nd.dentry = super->s_root; - nd.mnt = NULL; + nd.path.dentry = super->s_root; + nd.path.mnt = NULL; nd.flags = O_RDONLY + 1; nd.last_type = LAST_ROOT; @@ -159,7 +159,7 @@ void mconsole_proc(struct mc_request *req) goto out_kill; } - file = dentry_open(nd.dentry, nd.mnt, O_RDONLY); + file = dentry_open(nd.path.dentry, nd.path.mnt, O_RDONLY); if (IS_ERR(file)) { mconsole_reply(req, "Failed to open file", 1, 0); goto out_kill; diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index aaed1a3b92d6..3be2305709b7 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -21,6 +21,8 @@ config X86 select HAVE_IDE select HAVE_OPROFILE select HAVE_KPROBES + select HAVE_KVM + config GENERIC_LOCKBREAK def_bool n @@ -119,8 +121,6 @@ config ARCH_HAS_CPU_RELAX config HAVE_SETUP_PER_CPU_AREA def_bool X86_64 -select HAVE_KVM - config ARCH_HIBERNATION_POSSIBLE def_bool y depends on !SMP || !X86_VOYAGER diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug index 864affc9a7b0..702eb39901ca 100644 --- a/arch/x86/Kconfig.debug +++ b/arch/x86/Kconfig.debug @@ -156,7 +156,7 @@ config IO_DELAY_TYPE_NONE choice prompt "IO delay type" - default IO_DELAY_0XED + default IO_DELAY_0X80 config IO_DELAY_0X80 bool "port 0x80 based port-IO delay [recommended]" diff --git a/arch/x86/Makefile b/arch/x86/Makefile index 204af43535c5..f1e739a43d41 100644 --- a/arch/x86/Makefile +++ b/arch/x86/Makefile @@ -229,7 +229,7 @@ zdisk bzdisk: vmlinux fdimage fdimage144 fdimage288 isoimage: vmlinux $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) $@ -install: vdso_install +install: $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) install PHONY += vdso_install diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index 76ec0f8f138a..4eb5ce841106 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -6,7 +6,15 @@ extra-y := head_$(BITS).o init_task.o vmlinux.lds extra-$(CONFIG_X86_64) += head64.o CPPFLAGS_vmlinux.lds += -U$(UTS_MACHINE) -CFLAGS_vsyscall_64.o := $(PROFILING) -g0 + +# +# vsyscalls (which work on the user stack) should have +# no stack-protector checks: +# +nostackp := $(call cc-option, -fno-stack-protector) +CFLAGS_vsyscall_64.o := $(PROFILING) -g0 $(nostackp) +CFLAGS_hpet.o := $(nostackp) +CFLAGS_tsc_64.o := $(nostackp) obj-y := process_$(BITS).o signal_$(BITS).o entry_$(BITS).o obj-y += traps_$(BITS).o irq_$(BITS).o diff --git a/arch/x86/kernel/acpi/cstate.c b/arch/x86/kernel/acpi/cstate.c index 10b67170b133..8ca3557a6d59 100644 --- a/arch/x86/kernel/acpi/cstate.c +++ b/arch/x86/kernel/acpi/cstate.c @@ -126,6 +126,8 @@ int acpi_processor_ffh_cstate_probe(unsigned int cpu, printk(KERN_DEBUG "Monitor-Mwait will be used to enter C-%d " "state\n", cx->type); } + snprintf(cx->desc, ACPI_CX_DESC_LEN, "ACPI FFH INTEL MWAIT 0x%x", + cx->address); out: set_cpus_allowed(current, saved_mask); diff --git a/arch/x86/kernel/asm-offsets_32.c b/arch/x86/kernel/asm-offsets_32.c index afd84463b712..a33d53017997 100644 --- a/arch/x86/kernel/asm-offsets_32.c +++ b/arch/x86/kernel/asm-offsets_32.c @@ -20,10 +20,8 @@ #include -#ifdef CONFIG_LGUEST_GUEST #include #include "../../../drivers/lguest/lg.h" -#endif #define DEFINE(sym, val) \ asm volatile("\n->" #sym " %0 " #val : : "i" (val)) @@ -134,6 +132,10 @@ void foo(void) BLANK(); OFFSET(LGUEST_DATA_irq_enabled, lguest_data, irq_enabled); OFFSET(LGUEST_DATA_pgdir, lguest_data, pgdir); +#endif + +#ifdef CONFIG_LGUEST + BLANK(); OFFSET(LGUEST_PAGES_host_gdt_desc, lguest_pages, state.host_gdt_desc); OFFSET(LGUEST_PAGES_host_idt_desc, lguest_pages, state.host_idt_desc); OFFSET(LGUEST_PAGES_host_cr3, lguest_pages, state.host_cr3); diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c index 9b95edcfc6ae..027e5c003b16 100644 --- a/arch/x86/kernel/cpu/bugs.c +++ b/arch/x86/kernel/cpu/bugs.c @@ -25,14 +25,6 @@ static int __init no_halt(char *s) __setup("no-hlt", no_halt); -static int __init mca_pentium(char *s) -{ - mca_pentium_flag = 1; - return 1; -} - -__setup("mca-pentium", mca_pentium); - static int __init no_387(char *s) { boot_cpu_data.hard_math = 0; diff --git a/arch/x86/kernel/efi.c b/arch/x86/kernel/efi.c index cbdf9bacc575..759e02bec070 100644 --- a/arch/x86/kernel/efi.c +++ b/arch/x86/kernel/efi.c @@ -54,7 +54,7 @@ EXPORT_SYMBOL(efi); struct efi_memory_map memmap; -struct efi efi_phys __initdata; +static struct efi efi_phys __initdata; static efi_system_table_t efi_systab __initdata; static int __init setup_noefi(char *arg) @@ -391,7 +391,7 @@ static void __init runtime_code_page_mkexec(void) if (md->type != EFI_RUNTIME_SERVICES_CODE) continue; - set_memory_x(md->virt_addr, md->num_pages << EFI_PAGE_SHIFT); + set_memory_x(md->virt_addr, md->num_pages); } } @@ -434,7 +434,7 @@ void __init efi_enter_virtual_mode(void) } if (!(md->attribute & EFI_MEMORY_WB)) - set_memory_uc(md->virt_addr, size); + set_memory_uc(md->virt_addr, md->num_pages); systab = (u64) (unsigned long) efi_phys.systab; if (md->phys_addr <= systab && systab < end) { diff --git a/arch/x86/kernel/efi_32.c b/arch/x86/kernel/efi_32.c index cb91f985b4a1..5d23d85624d4 100644 --- a/arch/x86/kernel/efi_32.c +++ b/arch/x86/kernel/efi_32.c @@ -28,6 +28,7 @@ #include #include #include +#include /* * To make EFI call EFI runtime service in physical addressing mode we need diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S index 824e21b80aad..4b87c32b639f 100644 --- a/arch/x86/kernel/entry_32.S +++ b/arch/x86/kernel/entry_32.S @@ -409,7 +409,7 @@ restore_nocheck_notrace: RESTORE_REGS addl $4, %esp # skip orig_eax/error_code CFI_ADJUST_CFA_OFFSET -4 -ENTRY(irq_return) +irq_return: INTERRUPT_RETURN .section .fixup,"ax" iret_exc: diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S index 6be39a387c5a..2ad9a1bc6a73 100644 --- a/arch/x86/kernel/entry_64.S +++ b/arch/x86/kernel/entry_64.S @@ -583,7 +583,7 @@ retint_restore_args: /* return to kernel space */ restore_args: RESTORE_ARGS 0,8,0 -ENTRY(irq_return) +irq_return: INTERRUPT_RETURN .section __ex_table, "a" diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c index 24dbf56928d7..ad2440832de0 100644 --- a/arch/x86/kernel/head64.c +++ b/arch/x86/kernel/head64.c @@ -88,6 +88,9 @@ void __init x86_64_start_kernel(char * real_mode_data) /* Make NULL pointers segfault */ zap_identity_mappings(); + /* Cleanup the over mapped high alias */ + cleanup_highmap(); + for (i = 0; i < IDT_ENTRIES; i++) { #ifdef CONFIG_EARLY_PRINTK set_intr_gate(i, &early_idt_handlers[i]); diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S index 74ef4a41f224..25eb98540a41 100644 --- a/arch/x86/kernel/head_32.S +++ b/arch/x86/kernel/head_32.S @@ -612,7 +612,7 @@ ENTRY(swapper_pg_pmd) ENTRY(swapper_pg_dir) .fill 1024,4,0 #endif -ENTRY(swapper_pg_fixmap) +swapper_pg_fixmap: .fill 1024,4,0 ENTRY(empty_zero_page) .fill 4096,1,0 diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S index 09b38d539b09..eb415043a929 100644 --- a/arch/x86/kernel/head_64.S +++ b/arch/x86/kernel/head_64.S @@ -107,8 +107,13 @@ startup_64: movq %rdx, 0(%rbx, %rax, 8) ident_complete: - /* Fixup the kernel text+data virtual addresses + /* + * Fixup the kernel text+data virtual addresses. Note that + * we might write invalid pmds, when the kernel is relocated + * cleanup_highmap() fixes this up along with the mappings + * beyond _end. */ + leaq level2_kernel_pgt(%rip), %rdi leaq 4096(%rdi), %r8 /* See if it is a valid page table entry */ @@ -250,7 +255,7 @@ ENTRY(secondary_startup_64) lretq /* SMP bootup changes these two */ - __CPUINITDATA + __REFDATA .align 8 ENTRY(initial_code) .quad x86_64_start_kernel diff --git a/arch/x86/kernel/i387.c b/arch/x86/kernel/i387.c index 26719bd2c77c..763dfc407232 100644 --- a/arch/x86/kernel/i387.c +++ b/arch/x86/kernel/i387.c @@ -39,7 +39,7 @@ #define HAVE_HWFP 1 #endif -unsigned int mxcsr_feature_mask __read_mostly = 0xffffffffu; +static unsigned int mxcsr_feature_mask __read_mostly = 0xffffffffu; void mxcsr_feature_mask_init(void) { diff --git a/arch/x86/kernel/i8259_32.c b/arch/x86/kernel/i8259_32.c index 2d25b77102fe..fe631967d625 100644 --- a/arch/x86/kernel/i8259_32.c +++ b/arch/x86/kernel/i8259_32.c @@ -26,8 +26,6 @@ * present in the majority of PC/AT boxes. * plus some generic x86 specific things if generic specifics makes * any sense at all. - * this file should become arch/i386/kernel/irq.c when the old irq.c - * moves to arch independent land */ static int i8259A_auto_eoi; @@ -362,23 +360,12 @@ void __init init_ISA_irqs (void) #endif init_8259A(0); - for (i = 0; i < NR_IRQS; i++) { - irq_desc[i].status = IRQ_DISABLED; - irq_desc[i].action = NULL; - irq_desc[i].depth = 1; - - if (i < 16) { - /* - * 16 old-style INTA-cycle interrupts: - */ - set_irq_chip_and_handler_name(i, &i8259A_chip, - handle_level_irq, "XT"); - } else { - /* - * 'high' PCI IRQs filled in on demand - */ - irq_desc[i].chip = &no_irq_chip; - } + /* + * 16 old-style INTA-cycle interrupts: + */ + for (i = 0; i < 16; i++) { + set_irq_chip_and_handler_name(i, &i8259A_chip, + handle_level_irq, "XT"); } } diff --git a/arch/x86/kernel/io_delay.c b/arch/x86/kernel/io_delay.c index bd49321034db..c706a3061553 100644 --- a/arch/x86/kernel/io_delay.c +++ b/arch/x86/kernel/io_delay.c @@ -13,7 +13,6 @@ #include int io_delay_type __read_mostly = CONFIG_DEFAULT_IO_DELAY_TYPE; -EXPORT_SYMBOL_GPL(io_delay_type); static int __initdata io_delay_override; diff --git a/arch/x86/kernel/kprobes.c b/arch/x86/kernel/kprobes.c index a99e764fd66a..34a591283f5d 100644 --- a/arch/x86/kernel/kprobes.c +++ b/arch/x86/kernel/kprobes.c @@ -581,7 +581,7 @@ static int __kprobes kprobe_handler(struct pt_regs *regs) * When a retprobed function returns, this code saves registers and * calls trampoline_handler() runs, which calls the kretprobe's handler. */ -void __kprobes kretprobe_trampoline_holder(void) +static void __used __kprobes kretprobe_trampoline_holder(void) { asm volatile ( ".global kretprobe_trampoline\n" @@ -673,7 +673,7 @@ void __kprobes kretprobe_trampoline_holder(void) /* * Called from kretprobe_trampoline */ -void * __kprobes trampoline_handler(struct pt_regs *regs) +static __used __kprobes void *trampoline_handler(struct pt_regs *regs) { struct kretprobe_instance *ri = NULL; struct hlist_head *head, empty_rp; diff --git a/arch/x86/kernel/nmi_32.c b/arch/x86/kernel/nmi_32.c index edd413650b3b..6a0aa7038685 100644 --- a/arch/x86/kernel/nmi_32.c +++ b/arch/x86/kernel/nmi_32.c @@ -46,9 +46,6 @@ static unsigned int nmi_hz = HZ; static DEFINE_PER_CPU(short, wd_enabled); -/* local prototypes */ -static int unknown_nmi_panic_callback(struct pt_regs *regs, int cpu); - static int endflag __initdata = 0; #ifdef CONFIG_SMP @@ -391,15 +388,6 @@ __kprobes int nmi_watchdog_tick(struct pt_regs * regs, unsigned reason) return rc; } -int do_nmi_callback(struct pt_regs * regs, int cpu) -{ -#ifdef CONFIG_SYSCTL - if (unknown_nmi_panic) - return unknown_nmi_panic_callback(regs, cpu); -#endif - return 0; -} - #ifdef CONFIG_SYSCTL static int unknown_nmi_panic_callback(struct pt_regs *regs, int cpu) @@ -453,6 +441,15 @@ int proc_nmi_enabled(struct ctl_table *table, int write, struct file *file, #endif +int do_nmi_callback(struct pt_regs *regs, int cpu) +{ +#ifdef CONFIG_SYSCTL + if (unknown_nmi_panic) + return unknown_nmi_panic_callback(regs, cpu); +#endif + return 0; +} + void __trigger_all_cpu_backtrace(void) { int i; diff --git a/arch/x86/kernel/nmi_64.c b/arch/x86/kernel/nmi_64.c index fb99484d21cf..9a4fde74bee1 100644 --- a/arch/x86/kernel/nmi_64.c +++ b/arch/x86/kernel/nmi_64.c @@ -46,9 +46,6 @@ static unsigned int nmi_hz = HZ; static DEFINE_PER_CPU(short, wd_enabled); -/* local prototypes */ -static int unknown_nmi_panic_callback(struct pt_regs *regs, int cpu); - /* Run after command line and cpu_init init, but before all other checks */ void nmi_watchdog_default(void) { @@ -394,15 +391,6 @@ asmlinkage __kprobes void do_nmi(struct pt_regs * regs, long error_code) nmi_exit(); } -int do_nmi_callback(struct pt_regs * regs, int cpu) -{ -#ifdef CONFIG_SYSCTL - if (unknown_nmi_panic) - return unknown_nmi_panic_callback(regs, cpu); -#endif - return 0; -} - void stop_nmi(void) { acpi_nmi_disable(); @@ -464,6 +452,15 @@ int proc_nmi_enabled(struct ctl_table *table, int write, struct file *file, #endif +int do_nmi_callback(struct pt_regs *regs, int cpu) +{ +#ifdef CONFIG_SYSCTL + if (unknown_nmi_panic) + return unknown_nmi_panic_callback(regs, cpu); +#endif + return 0; +} + void __trigger_all_cpu_backtrace(void) { int i; diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c index 65f6acb025c8..faf3229f8fb3 100644 --- a/arch/x86/kernel/pci-gart_64.c +++ b/arch/x86/kernel/pci-gart_64.c @@ -749,6 +749,15 @@ void __init gart_iommu_init(void) */ set_memory_np((unsigned long)__va(iommu_bus_base), iommu_size >> PAGE_SHIFT); + /* + * Tricky. The GART table remaps the physical memory range, + * so the CPU wont notice potential aliases and if the memory + * is remapped to UC later on, we might surprise the PCI devices + * with a stray writeout of a cacheline. So play it sure and + * do an explicit, full-scale wbinvd() _after_ having marked all + * the pages as Not-Present: + */ + wbinvd(); /* * Try to workaround a bug (thanks to BenH) diff --git a/arch/x86/kernel/setup_32.c b/arch/x86/kernel/setup_32.c index 691ab4cb167b..a1d7071a51c9 100644 --- a/arch/x86/kernel/setup_32.c +++ b/arch/x86/kernel/setup_32.c @@ -164,7 +164,6 @@ unsigned long mmu_cr4_features = X86_CR4_PAE; unsigned int machine_id; unsigned int machine_submodel_id; unsigned int BIOS_revision; -unsigned int mca_pentium_flag; /* Boot loader ID as an integer, for the benefit of proc_dointvec */ int bootloader_type; diff --git a/arch/x86/kernel/setup_64.c b/arch/x86/kernel/setup_64.c index c0d8208af12a..6fd804f07821 100644 --- a/arch/x86/kernel/setup_64.c +++ b/arch/x86/kernel/setup_64.c @@ -518,7 +518,7 @@ static void __cpuinit display_cacheinfo(struct cpuinfo_x86 *c) } #ifdef CONFIG_NUMA -static int nearby_node(int apicid) +static int __cpuinit nearby_node(int apicid) { int i, node; @@ -791,7 +791,7 @@ static int __cpuinit intel_num_cpu_cores(struct cpuinfo_x86 *c) return 1; } -static void srat_detect_node(void) +static void __cpuinit srat_detect_node(void) { #ifdef CONFIG_NUMA unsigned node; @@ -1046,7 +1046,7 @@ __setup("noclflush", setup_noclflush); void __cpuinit print_cpu_info(struct cpuinfo_x86 *c) { if (c->x86_model_id[0]) - printk(KERN_INFO "%s", c->x86_model_id); + printk(KERN_CONT "%s", c->x86_model_id); if (c->x86_mask || c->cpuid_level >= 0) printk(KERN_CONT " stepping %02x\n", c->x86_mask); diff --git a/arch/x86/kernel/test_rodata.c b/arch/x86/kernel/test_rodata.c index 4c163772000e..c29e235792af 100644 --- a/arch/x86/kernel/test_rodata.c +++ b/arch/x86/kernel/test_rodata.c @@ -10,8 +10,8 @@ * of the License. */ #include +#include #include -extern int rodata_test_data; int rodata_test(void) { diff --git a/arch/x86/kernel/topology.c b/arch/x86/kernel/topology.c index a40051b71d9b..0fcc95a354f7 100644 --- a/arch/x86/kernel/topology.c +++ b/arch/x86/kernel/topology.c @@ -34,7 +34,7 @@ static DEFINE_PER_CPU(struct x86_cpu, cpu_devices); #ifdef CONFIG_HOTPLUG_CPU -int arch_register_cpu(int num) +int __ref arch_register_cpu(int num) { /* * CPU0 cannot be offlined due to several diff --git a/arch/x86/kernel/traps_64.c b/arch/x86/kernel/traps_64.c index efc66df728b6..045466681911 100644 --- a/arch/x86/kernel/traps_64.c +++ b/arch/x86/kernel/traps_64.c @@ -84,7 +84,7 @@ static inline void conditional_sti(struct pt_regs *regs) static inline void preempt_conditional_sti(struct pt_regs *regs) { - preempt_disable(); + inc_preempt_count(); if (regs->flags & X86_EFLAGS_IF) local_irq_enable(); } @@ -95,7 +95,7 @@ static inline void preempt_conditional_cli(struct pt_regs *regs) local_irq_disable(); /* Make sure to not schedule here because we could be running on an exception stack. */ - preempt_enable_no_resched(); + dec_preempt_count(); } int kstack_depth_to_print = 12; diff --git a/arch/x86/kernel/vmlinux_32.lds.S b/arch/x86/kernel/vmlinux_32.lds.S index f1148ac8abe3..2ffa9656fe7a 100644 --- a/arch/x86/kernel/vmlinux_32.lds.S +++ b/arch/x86/kernel/vmlinux_32.lds.S @@ -38,7 +38,7 @@ SECTIONS /* read-only */ .text : AT(ADDR(.text) - LOAD_OFFSET) { - . = ALIGN(4096); /* not really needed, already page aligned */ + . = ALIGN(PAGE_SIZE); /* not really needed, already page aligned */ *(.text.page_aligned) TEXT_TEXT SCHED_TEXT @@ -70,21 +70,21 @@ SECTIONS RODATA /* writeable */ - . = ALIGN(4096); + . = ALIGN(PAGE_SIZE); .data : AT(ADDR(.data) - LOAD_OFFSET) { /* Data */ DATA_DATA CONSTRUCTORS } :data - . = ALIGN(4096); + . = ALIGN(PAGE_SIZE); .data_nosave : AT(ADDR(.data_nosave) - LOAD_OFFSET) { __nosave_begin = .; *(.data.nosave) - . = ALIGN(4096); + . = ALIGN(PAGE_SIZE); __nosave_end = .; } - . = ALIGN(4096); + . = ALIGN(PAGE_SIZE); .data.page_aligned : AT(ADDR(.data.page_aligned) - LOAD_OFFSET) { *(.data.page_aligned) *(.data.idt) @@ -108,7 +108,7 @@ SECTIONS } /* might get freed after init */ - . = ALIGN(4096); + . = ALIGN(PAGE_SIZE); .smp_locks : AT(ADDR(.smp_locks) - LOAD_OFFSET) { __smp_locks = .; *(.smp_locks) @@ -120,10 +120,10 @@ SECTIONS * after boot. Always make sure that ALIGN() directive is present after * the section which contains __smp_alt_end. */ - . = ALIGN(4096); + . = ALIGN(PAGE_SIZE); /* will be freed after init */ - . = ALIGN(4096); /* Init code and data */ + . = ALIGN(PAGE_SIZE); /* Init code and data */ .init.text : AT(ADDR(.init.text) - LOAD_OFFSET) { __init_begin = .; _sinittext = .; @@ -174,23 +174,23 @@ SECTIONS EXIT_DATA } #if defined(CONFIG_BLK_DEV_INITRD) - . = ALIGN(4096); + . = ALIGN(PAGE_SIZE); .init.ramfs : AT(ADDR(.init.ramfs) - LOAD_OFFSET) { __initramfs_start = .; *(.init.ramfs) __initramfs_end = .; } #endif - . = ALIGN(4096); + . = ALIGN(PAGE_SIZE); .data.percpu : AT(ADDR(.data.percpu) - LOAD_OFFSET) { __per_cpu_start = .; *(.data.percpu) *(.data.percpu.shared_aligned) __per_cpu_end = .; } - . = ALIGN(4096); + . = ALIGN(PAGE_SIZE); /* freed after init ends here */ - + .bss : AT(ADDR(.bss) - LOAD_OFFSET) { __init_end = .; __bss_start = .; /* BSS */ @@ -200,7 +200,7 @@ SECTIONS __bss_stop = .; _end = . ; /* This is where the kernel creates the early boot page tables */ - . = ALIGN(4096); + . = ALIGN(PAGE_SIZE); pg0 = . ; } diff --git a/arch/x86/kernel/vmlinux_64.lds.S b/arch/x86/kernel/vmlinux_64.lds.S index 0992b9946c6f..fab132299735 100644 --- a/arch/x86/kernel/vmlinux_64.lds.S +++ b/arch/x86/kernel/vmlinux_64.lds.S @@ -37,7 +37,7 @@ SECTIONS KPROBES_TEXT *(.fixup) *(.gnu.warning) - _etext = .; /* End of text section */ + _etext = .; /* End of text section */ } :text = 0x9090 . = ALIGN(16); /* Exception table */ @@ -60,7 +60,7 @@ SECTIONS __tracedata_end = .; } - . = ALIGN(PAGE_SIZE); /* Align data segment to page size boundary */ + . = ALIGN(PAGE_SIZE); /* Align data segment to page size boundary */ /* Data */ .data : AT(ADDR(.data) - LOAD_OFFSET) { DATA_DATA @@ -119,7 +119,7 @@ SECTIONS .vsyscall_3 ADDR(.vsyscall_0) + 3072: AT(VLOAD(.vsyscall_3)) { *(.vsyscall_3) } - . = VSYSCALL_VIRT_ADDR + 4096; + . = VSYSCALL_VIRT_ADDR + PAGE_SIZE; #undef VSYSCALL_ADDR #undef VSYSCALL_PHYS_ADDR @@ -129,28 +129,28 @@ SECTIONS #undef VVIRT_OFFSET #undef VVIRT - . = ALIGN(8192); /* init_task */ + . = ALIGN(THREAD_SIZE); /* init_task */ .data.init_task : AT(ADDR(.data.init_task) - LOAD_OFFSET) { *(.data.init_task) }:data.init - . = ALIGN(4096); + . = ALIGN(PAGE_SIZE); .data.page_aligned : AT(ADDR(.data.page_aligned) - LOAD_OFFSET) { *(.data.page_aligned) } /* might get freed after init */ - . = ALIGN(4096); + . = ALIGN(PAGE_SIZE); __smp_alt_begin = .; __smp_locks = .; .smp_locks : AT(ADDR(.smp_locks) - LOAD_OFFSET) { *(.smp_locks) } __smp_locks_end = .; - . = ALIGN(4096); + . = ALIGN(PAGE_SIZE); __smp_alt_end = .; - . = ALIGN(4096); /* Init code and data */ + . = ALIGN(PAGE_SIZE); /* Init code and data */ __init_begin = .; .init.text : AT(ADDR(.init.text) - LOAD_OFFSET) { _sinittext = .; @@ -191,7 +191,7 @@ SECTIONS .altinstructions : AT(ADDR(.altinstructions) - LOAD_OFFSET) { *(.altinstructions) } - __alt_instructions_end = .; + __alt_instructions_end = .; .altinstr_replacement : AT(ADDR(.altinstr_replacement) - LOAD_OFFSET) { *(.altinstr_replacement) } @@ -207,25 +207,25 @@ SECTIONS /* vdso blob that is mapped into user space */ vdso_start = . ; .vdso : AT(ADDR(.vdso) - LOAD_OFFSET) { *(.vdso) } - . = ALIGN(4096); + . = ALIGN(PAGE_SIZE); vdso_end = .; #ifdef CONFIG_BLK_DEV_INITRD - . = ALIGN(4096); + . = ALIGN(PAGE_SIZE); __initramfs_start = .; .init.ramfs : AT(ADDR(.init.ramfs) - LOAD_OFFSET) { *(.init.ramfs) } __initramfs_end = .; #endif - PERCPU(4096) + PERCPU(PAGE_SIZE) - . = ALIGN(4096); + . = ALIGN(PAGE_SIZE); __init_end = .; - . = ALIGN(4096); + . = ALIGN(PAGE_SIZE); __nosave_begin = .; .data_nosave : AT(ADDR(.data_nosave) - LOAD_OFFSET) { *(.data.nosave) } - . = ALIGN(4096); + . = ALIGN(PAGE_SIZE); __nosave_end = .; __bss_start = .; /* BSS */ diff --git a/arch/x86/lib/csum-wrappers_64.c b/arch/x86/lib/csum-wrappers_64.c index fd42a4a095fc..459b58a8a15c 100644 --- a/arch/x86/lib/csum-wrappers_64.c +++ b/arch/x86/lib/csum-wrappers_64.c @@ -1,117 +1,129 @@ -/* Copyright 2002,2003 Andi Kleen, SuSE Labs. +/* + * Copyright 2002, 2003 Andi Kleen, SuSE Labs. * Subject to the GNU Public License v.2 - * + * * Wrappers of assembly checksum functions for x86-64. */ - #include #include -/** - * csum_partial_copy_from_user - Copy and checksum from user space. - * @src: source address (user space) +/** + * csum_partial_copy_from_user - Copy and checksum from user space. + * @src: source address (user space) * @dst: destination address * @len: number of bytes to be copied. * @isum: initial sum that is added into the result (32bit unfolded) * @errp: set to -EFAULT for an bad source address. - * + * * Returns an 32bit unfolded checksum of the buffer. - * src and dst are best aligned to 64bits. - */ + * src and dst are best aligned to 64bits. + */ __wsum csum_partial_copy_from_user(const void __user *src, void *dst, int len, __wsum isum, int *errp) -{ +{ might_sleep(); *errp = 0; - if (likely(access_ok(VERIFY_READ,src, len))) { - /* Why 6, not 7? To handle odd addresses aligned we - would need to do considerable complications to fix the - checksum which is defined as an 16bit accumulator. The - fix alignment code is primarily for performance - compatibility with 32bit and that will handle odd - addresses slowly too. */ - if (unlikely((unsigned long)src & 6)) { - while (((unsigned long)src & 6) && len >= 2) { - __u16 val16; - *errp = __get_user(val16, (const __u16 __user *)src); - if (*errp) - return isum; - *(__u16 *)dst = val16; - isum = (__force __wsum)add32_with_carry( - (__force unsigned)isum, val16); - src += 2; - dst += 2; - len -= 2; - } - } - isum = csum_partial_copy_generic((__force const void *)src, - dst, len, isum, errp, NULL); - if (likely(*errp == 0)) - return isum; - } - *errp = -EFAULT; - memset(dst,0,len); - return isum; -} + if (!likely(access_ok(VERIFY_READ, src, len))) + goto out_err; + + /* + * Why 6, not 7? To handle odd addresses aligned we + * would need to do considerable complications to fix the + * checksum which is defined as an 16bit accumulator. The + * fix alignment code is primarily for performance + * compatibility with 32bit and that will handle odd + * addresses slowly too. + */ + if (unlikely((unsigned long)src & 6)) { + while (((unsigned long)src & 6) && len >= 2) { + __u16 val16; + + *errp = __get_user(val16, (const __u16 __user *)src); + if (*errp) + return isum; + + *(__u16 *)dst = val16; + isum = (__force __wsum)add32_with_carry( + (__force unsigned)isum, val16); + src += 2; + dst += 2; + len -= 2; + } + } + isum = csum_partial_copy_generic((__force const void *)src, + dst, len, isum, errp, NULL); + if (unlikely(*errp)) + goto out_err; + + return isum; + +out_err: + *errp = -EFAULT; + memset(dst, 0, len); + + return isum; +} EXPORT_SYMBOL(csum_partial_copy_from_user); -/** - * csum_partial_copy_to_user - Copy and checksum to user space. +/** + * csum_partial_copy_to_user - Copy and checksum to user space. * @src: source address * @dst: destination address (user space) * @len: number of bytes to be copied. * @isum: initial sum that is added into the result (32bit unfolded) * @errp: set to -EFAULT for an bad destination address. - * + * * Returns an 32bit unfolded checksum of the buffer. * src and dst are best aligned to 64bits. - */ + */ __wsum csum_partial_copy_to_user(const void *src, void __user *dst, int len, __wsum isum, int *errp) -{ +{ might_sleep(); + if (unlikely(!access_ok(VERIFY_WRITE, dst, len))) { *errp = -EFAULT; - return 0; + return 0; } if (unlikely((unsigned long)dst & 6)) { - while (((unsigned long)dst & 6) && len >= 2) { + while (((unsigned long)dst & 6) && len >= 2) { __u16 val16 = *(__u16 *)src; + isum = (__force __wsum)add32_with_carry( (__force unsigned)isum, val16); *errp = __put_user(val16, (__u16 __user *)dst); if (*errp) return isum; - src += 2; - dst += 2; + src += 2; + dst += 2; len -= 2; } } *errp = 0; - return csum_partial_copy_generic(src, (void __force *)dst,len,isum,NULL,errp); -} - + return csum_partial_copy_generic(src, (void __force *)dst, + len, isum, NULL, errp); +} EXPORT_SYMBOL(csum_partial_copy_to_user); -/** +/** * csum_partial_copy_nocheck - Copy and checksum. * @src: source address * @dst: destination address * @len: number of bytes to be copied. * @isum: initial sum that is added into the result (32bit unfolded) - * + * * Returns an 32bit unfolded checksum of the buffer. - */ + */ __wsum csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum) -{ - return csum_partial_copy_generic(src,dst,len,sum,NULL,NULL); -} +{ + return csum_partial_copy_generic(src, dst, len, sum, NULL, NULL); +} EXPORT_SYMBOL(csum_partial_copy_nocheck); __sum16 csum_ipv6_magic(const struct in6_addr *saddr, @@ -119,17 +131,20 @@ __sum16 csum_ipv6_magic(const struct in6_addr *saddr, __u32 len, unsigned short proto, __wsum sum) { __u64 rest, sum64; - + rest = (__force __u64)htonl(len) + (__force __u64)htons(proto) + (__force __u64)sum; - asm(" addq (%[saddr]),%[sum]\n" - " adcq 8(%[saddr]),%[sum]\n" - " adcq (%[daddr]),%[sum]\n" - " adcq 8(%[daddr]),%[sum]\n" - " adcq $0,%[sum]\n" - : [sum] "=r" (sum64) - : "[sum]" (rest),[saddr] "r" (saddr), [daddr] "r" (daddr)); - return csum_fold((__force __wsum)add32_with_carry(sum64 & 0xffffffff, sum64>>32)); -} + asm(" addq (%[saddr]),%[sum]\n" + " adcq 8(%[saddr]),%[sum]\n" + " adcq (%[daddr]),%[sum]\n" + " adcq 8(%[daddr]),%[sum]\n" + " adcq $0,%[sum]\n" + + : [sum] "=r" (sum64) + : "[sum]" (rest), [saddr] "r" (saddr), [daddr] "r" (daddr)); + + return csum_fold( + (__force __wsum)add32_with_carry(sum64 & 0xffffffff, sum64>>32)); +} EXPORT_SYMBOL(csum_ipv6_magic); diff --git a/arch/x86/lib/io_64.c b/arch/x86/lib/io_64.c index 87b4a4e18039..3f1eb59b5f08 100644 --- a/arch/x86/lib/io_64.c +++ b/arch/x86/lib/io_64.c @@ -1,23 +1,25 @@ #include -#include #include +#include -void __memcpy_toio(unsigned long dst,const void*src,unsigned len) +void __memcpy_toio(unsigned long dst, const void *src, unsigned len) { - __inline_memcpy((void *) dst,src,len); + __inline_memcpy((void *)dst, src, len); } EXPORT_SYMBOL(__memcpy_toio); -void __memcpy_fromio(void *dst,unsigned long src,unsigned len) +void __memcpy_fromio(void *dst, unsigned long src, unsigned len) { - __inline_memcpy(dst,(const void *) src,len); + __inline_memcpy(dst, (const void *)src, len); } EXPORT_SYMBOL(__memcpy_fromio); void memset_io(volatile void __iomem *a, int b, size_t c) { - /* XXX: memset can mangle the IO patterns quite a bit. - perhaps it would be better to use a dumb one */ - memset((void *)a,b,c); + /* + * TODO: memset can mangle the IO patterns quite a bit. + * perhaps it would be better to use a dumb one: + */ + memset((void *)a, b, c); } EXPORT_SYMBOL(memset_io); diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index 621afb6343dc..fdc667422df9 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c @@ -186,7 +186,7 @@ static int bad_address(void *p) } #endif -void dump_pagetable(unsigned long address) +static void dump_pagetable(unsigned long address) { #ifdef CONFIG_X86_32 __typeof__(pte_val(__pte(0))) page; diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c index 8106bba41ecb..ee1091a46964 100644 --- a/arch/x86/mm/init_32.c +++ b/arch/x86/mm/init_32.c @@ -47,6 +47,7 @@ #include #include #include +#include unsigned int __VMALLOC_RESERVE = 128 << 20; diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index b59fc238151f..bb652f5a93fb 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c @@ -45,6 +45,7 @@ #include #include #include +#include const struct dma_mapping_ops *dma_ops; EXPORT_SYMBOL(dma_ops); @@ -170,6 +171,33 @@ set_pte_phys(unsigned long vaddr, unsigned long phys, pgprot_t prot) __flush_tlb_one(vaddr); } +/* + * The head.S code sets up the kernel high mapping from: + * __START_KERNEL_map to __START_KERNEL_map + KERNEL_TEXT_SIZE + * + * phys_addr holds the negative offset to the kernel, which is added + * to the compile time generated pmds. This results in invalid pmds up + * to the point where we hit the physaddr 0 mapping. + * + * We limit the mappings to the region from _text to _end. _end is + * rounded up to the 2MB boundary. This catches the invalid pmds as + * well, as they are located before _text: + */ +void __init cleanup_highmap(void) +{ + unsigned long vaddr = __START_KERNEL_map; + unsigned long end = round_up((unsigned long)_end, PMD_SIZE) - 1; + pmd_t *pmd = level2_kernel_pgt; + pmd_t *last_pmd = pmd + PTRS_PER_PMD; + + for (; pmd < last_pmd; pmd++, vaddr += PMD_SIZE) { + if (!pmd_present(*pmd)) + continue; + if (vaddr < (unsigned long) _text || vaddr > end) + set_pmd(pmd, __pmd(0)); + } +} + /* NOTE: this is meant to be run only at boot */ void __init __set_fixmap(enum fixed_addresses idx, unsigned long phys, pgprot_t prot) diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c index 9f42d7e9c158..882328efc3db 100644 --- a/arch/x86/mm/ioremap.c +++ b/arch/x86/mm/ioremap.c @@ -42,6 +42,22 @@ int page_is_ram(unsigned long pagenr) unsigned long addr, end; int i; + /* + * A special case is the first 4Kb of memory; + * This is a BIOS owned area, not kernel ram, but generally + * not listed as such in the E820 table. + */ + if (pagenr == 0) + return 0; + + /* + * Second special case: Some BIOSen report the PC BIOS + * area (640->1Mb) as ram even though it is not. + */ + if (pagenr >= (BIOS_BEGIN >> PAGE_SHIFT) && + pagenr < (BIOS_END >> PAGE_SHIFT)) + return 0; + for (i = 0; i < e820.nr_map; i++) { /* * Not usable memory: @@ -51,14 +67,6 @@ int page_is_ram(unsigned long pagenr) addr = (e820.map[i].addr + PAGE_SIZE-1) >> PAGE_SHIFT; end = (e820.map[i].addr + e820.map[i].size) >> PAGE_SHIFT; - /* - * Sanity check: Some BIOSen report areas as RAM that - * are not. Notably the 640->1Mb area, which is the - * PCI BIOS area. - */ - if (addr >= (BIOS_BEGIN >> PAGE_SHIFT) && - end < (BIOS_END >> PAGE_SHIFT)) - continue; if ((pagenr >= addr) && (pagenr < end)) return 1; @@ -126,6 +134,8 @@ static void __iomem *__ioremap(unsigned long phys_addr, unsigned long size, return NULL; } + WARN_ON_ONCE(page_is_ram(pfn)); + switch (mode) { case IOR_MODE_UNCACHED: default: diff --git a/arch/x86/mm/numa_64.c b/arch/x86/mm/numa_64.c index 1aecc658cd7d..59898fb0a4aa 100644 --- a/arch/x86/mm/numa_64.c +++ b/arch/x86/mm/numa_64.c @@ -494,11 +494,13 @@ void __init numa_initmem_init(unsigned long start_pfn, unsigned long end_pfn) int i; nodes_clear(node_possible_map); + nodes_clear(node_online_map); #ifdef CONFIG_NUMA_EMU if (cmdline && !numa_emulation(start_pfn, end_pfn)) return; nodes_clear(node_possible_map); + nodes_clear(node_online_map); #endif #ifdef CONFIG_ACPI_NUMA @@ -506,6 +508,7 @@ void __init numa_initmem_init(unsigned long start_pfn, unsigned long end_pfn) end_pfn << PAGE_SHIFT)) return; nodes_clear(node_possible_map); + nodes_clear(node_online_map); #endif #ifdef CONFIG_K8_NUMA @@ -513,6 +516,7 @@ void __init numa_initmem_init(unsigned long start_pfn, unsigned long end_pfn) end_pfn< #include #include +#include /* * The current flushing context - we pass it instead of 5 arguments: @@ -26,8 +27,23 @@ struct cpa_data { pgprot_t mask_clr; int numpages; int flushtlb; + unsigned long pfn; }; +#ifdef CONFIG_X86_64 + +static inline unsigned long highmap_start_pfn(void) +{ + return __pa(_text) >> PAGE_SHIFT; +} + +static inline unsigned long highmap_end_pfn(void) +{ + return __pa(round_up((unsigned long)_end, PMD_SIZE)) >> PAGE_SHIFT; +} + +#endif + static inline int within(unsigned long addr, unsigned long start, unsigned long end) { @@ -123,29 +139,14 @@ static void cpa_flush_range(unsigned long start, int numpages, int cache) } } -#define HIGH_MAP_START __START_KERNEL_map -#define HIGH_MAP_END (__START_KERNEL_map + KERNEL_TEXT_SIZE) - - -/* - * Converts a virtual address to a X86-64 highmap address - */ -static unsigned long virt_to_highmap(void *address) -{ -#ifdef CONFIG_X86_64 - return __pa((unsigned long)address) + HIGH_MAP_START - phys_base; -#else - return (unsigned long)address; -#endif -} - /* * Certain areas of memory on x86 require very specific protection flags, * for example the BIOS area or kernel text. Callers don't always get this * right (again, ioremap() on BIOS memory is not uncommon) so this function * checks and fixes these known static required protection bits. */ -static inline pgprot_t static_protections(pgprot_t prot, unsigned long address) +static inline pgprot_t static_protections(pgprot_t prot, unsigned long address, + unsigned long pfn) { pgprot_t forbidden = __pgprot(0); @@ -153,30 +154,23 @@ static inline pgprot_t static_protections(pgprot_t prot, unsigned long address) * The BIOS area between 640k and 1Mb needs to be executable for * PCI BIOS based config access (CONFIG_PCI_GOBIOS) support. */ - if (within(__pa(address), BIOS_BEGIN, BIOS_END)) + if (within(pfn, BIOS_BEGIN >> PAGE_SHIFT, BIOS_END >> PAGE_SHIFT)) pgprot_val(forbidden) |= _PAGE_NX; /* * The kernel text needs to be executable for obvious reasons - * Does not cover __inittext since that is gone later on + * Does not cover __inittext since that is gone later on. On + * 64bit we do not enforce !NX on the low mapping */ if (within(address, (unsigned long)_text, (unsigned long)_etext)) pgprot_val(forbidden) |= _PAGE_NX; - /* - * Do the same for the x86-64 high kernel mapping - */ - if (within(address, virt_to_highmap(_text), virt_to_highmap(_etext))) - pgprot_val(forbidden) |= _PAGE_NX; - /* The .rodata section needs to be read-only */ - if (within(address, (unsigned long)__start_rodata, - (unsigned long)__end_rodata)) - pgprot_val(forbidden) |= _PAGE_RW; /* - * Do the same for the x86-64 high kernel mapping + * The .rodata section needs to be read-only. Using the pfn + * catches all aliases. */ - if (within(address, virt_to_highmap(__start_rodata), - virt_to_highmap(__end_rodata))) + if (within(pfn, __pa((unsigned long)__start_rodata) >> PAGE_SHIFT, + __pa((unsigned long)__end_rodata) >> PAGE_SHIFT)) pgprot_val(forbidden) |= _PAGE_RW; prot = __pgprot(pgprot_val(prot) & ~pgprot_val(forbidden)); @@ -253,7 +247,7 @@ static int try_preserve_large_page(pte_t *kpte, unsigned long address, struct cpa_data *cpa) { - unsigned long nextpage_addr, numpages, pmask, psize, flags, addr; + unsigned long nextpage_addr, numpages, pmask, psize, flags, addr, pfn; pte_t new_pte, old_pte, *tmp; pgprot_t old_prot, new_prot; int i, do_split = 1; @@ -301,7 +295,15 @@ try_preserve_large_page(pte_t *kpte, unsigned long address, pgprot_val(new_prot) &= ~pgprot_val(cpa->mask_clr); pgprot_val(new_prot) |= pgprot_val(cpa->mask_set); - new_prot = static_protections(new_prot, address); + + /* + * old_pte points to the large page base address. So we need + * to add the offset of the virtual address: + */ + pfn = pte_pfn(old_pte) + ((address & (psize - 1)) >> PAGE_SHIFT); + cpa->pfn = pfn; + + new_prot = static_protections(new_prot, address, pfn); /* * We need to check the full range, whether @@ -309,8 +311,9 @@ try_preserve_large_page(pte_t *kpte, unsigned long address, * the pages in the range we try to preserve: */ addr = address + PAGE_SIZE; - for (i = 1; i < cpa->numpages; i++, addr += PAGE_SIZE) { - pgprot_t chk_prot = static_protections(new_prot, addr); + pfn++; + for (i = 1; i < cpa->numpages; i++, addr += PAGE_SIZE, pfn++) { + pgprot_t chk_prot = static_protections(new_prot, addr, pfn); if (pgprot_val(chk_prot) != pgprot_val(new_prot)) goto out_unlock; @@ -505,46 +508,46 @@ out_unlock: return 0; } -static int __change_page_attr(unsigned long address, struct cpa_data *cpa) +static int __change_page_attr(struct cpa_data *cpa, int primary) { + unsigned long address = cpa->vaddr; int do_split, err; unsigned int level; - struct page *kpte_page; - pte_t *kpte; + pte_t *kpte, old_pte; repeat: kpte = lookup_address(address, &level); if (!kpte) - return -EINVAL; + return primary ? -EINVAL : 0; - kpte_page = virt_to_page(kpte); - BUG_ON(PageLRU(kpte_page)); - BUG_ON(PageCompound(kpte_page)); + old_pte = *kpte; + if (!pte_val(old_pte)) { + if (!primary) + return 0; + printk(KERN_WARNING "CPA: called for zero pte. " + "vaddr = %lx cpa->vaddr = %lx\n", address, + cpa->vaddr); + WARN_ON(1); + return -EINVAL; + } if (level == PG_LEVEL_4K) { - pte_t new_pte, old_pte = *kpte; + pte_t new_pte; pgprot_t new_prot = pte_pgprot(old_pte); - - if(!pte_val(old_pte)) { - printk(KERN_WARNING "CPA: called for zero pte. " - "vaddr = %lx cpa->vaddr = %lx\n", address, - cpa->vaddr); - WARN_ON(1); - return -EINVAL; - } + unsigned long pfn = pte_pfn(old_pte); pgprot_val(new_prot) &= ~pgprot_val(cpa->mask_clr); pgprot_val(new_prot) |= pgprot_val(cpa->mask_set); - new_prot = static_protections(new_prot, address); + new_prot = static_protections(new_prot, address, pfn); /* * We need to keep the pfn from the existing PTE, * after all we're only going to change it's attributes * not the memory it points to */ - new_pte = pfn_pte(pte_pfn(old_pte), canon_pgprot(new_prot)); - + new_pte = pfn_pte(pfn, canon_pgprot(new_prot)); + cpa->pfn = pfn; /* * Do we really change anything ? */ @@ -581,67 +584,59 @@ repeat: return err; } -/** - * change_page_attr_addr - Change page table attributes in linear mapping - * @address: Virtual address in linear mapping. - * @prot: New page table attribute (PAGE_*) - * - * Change page attributes of a page in the direct mapping. This is a variant - * of change_page_attr() that also works on memory holes that do not have - * mem_map entry (pfn_valid() is false). - * - * See change_page_attr() documentation for more details. - * - * Modules and drivers should use the set_memory_* APIs instead. - */ -static int change_page_attr_addr(struct cpa_data *cpa) -{ - int err; - unsigned long address = cpa->vaddr; +static int __change_page_attr_set_clr(struct cpa_data *cpa, int checkalias); -#ifdef CONFIG_X86_64 - unsigned long phys_addr = __pa(address); +static int cpa_process_alias(struct cpa_data *cpa) +{ + struct cpa_data alias_cpa; + int ret = 0; + + if (cpa->pfn > max_pfn_mapped) + return 0; /* - * If we are inside the high mapped kernel range, then we - * fixup the low mapping first. __va() returns the virtual - * address in the linear mapping: + * No need to redo, when the primary call touched the direct + * mapping already: */ - if (within(address, HIGH_MAP_START, HIGH_MAP_END)) - address = (unsigned long) __va(phys_addr); -#endif + if (!within(cpa->vaddr, PAGE_OFFSET, + PAGE_OFFSET + (max_pfn_mapped << PAGE_SHIFT))) { - err = __change_page_attr(address, cpa); - if (err) - return err; + alias_cpa = *cpa; + alias_cpa.vaddr = (unsigned long) __va(cpa->pfn << PAGE_SHIFT); + + ret = __change_page_attr_set_clr(&alias_cpa, 0); + } #ifdef CONFIG_X86_64 + if (ret) + return ret; + /* + * No need to redo, when the primary call touched the high + * mapping already: + */ + if (within(cpa->vaddr, (unsigned long) _text, (unsigned long) _end)) + return 0; + /* * If the physical address is inside the kernel map, we need * to touch the high mapped kernel as well: */ - if (within(phys_addr, 0, KERNEL_TEXT_SIZE)) { - /* - * Calc the high mapping address. See __phys_addr() - * for the non obvious details. - * - * Note that NX and other required permissions are - * checked in static_protections(). - */ - address = phys_addr + HIGH_MAP_START - phys_base; + if (!within(cpa->pfn, highmap_start_pfn(), highmap_end_pfn())) + return 0; - /* - * Our high aliases are imprecise, because we check - * everything between 0 and KERNEL_TEXT_SIZE, so do - * not propagate lookup failures back to users: - */ - __change_page_attr(address, cpa); - } + alias_cpa = *cpa; + alias_cpa.vaddr = + (cpa->pfn << PAGE_SHIFT) + __START_KERNEL_map - phys_base; + + /* + * The high mapping range is imprecise, so ignore the return value. + */ + __change_page_attr_set_clr(&alias_cpa, 0); #endif - return err; + return ret; } -static int __change_page_attr_set_clr(struct cpa_data *cpa) +static int __change_page_attr_set_clr(struct cpa_data *cpa, int checkalias) { int ret, numpages = cpa->numpages; @@ -651,10 +646,17 @@ static int __change_page_attr_set_clr(struct cpa_data *cpa) * preservation check. */ cpa->numpages = numpages; - ret = change_page_attr_addr(cpa); + + ret = __change_page_attr(cpa, checkalias); if (ret) return ret; + if (checkalias) { + ret = cpa_process_alias(cpa); + if (ret) + return ret; + } + /* * Adjust the number of pages with the result of the * CPA operation. Either a large page has been @@ -677,7 +679,7 @@ static int change_page_attr_set_clr(unsigned long addr, int numpages, pgprot_t mask_set, pgprot_t mask_clr) { struct cpa_data cpa; - int ret, cache; + int ret, cache, checkalias; /* * Check, if we are requested to change a not supported @@ -688,13 +690,25 @@ static int change_page_attr_set_clr(unsigned long addr, int numpages, if (!pgprot_val(mask_set) && !pgprot_val(mask_clr)) return 0; + /* Ensure we are PAGE_SIZE aligned */ + if (addr & ~PAGE_MASK) { + addr &= PAGE_MASK; + /* + * People should not be passing in unaligned addresses: + */ + WARN_ON_ONCE(1); + } + cpa.vaddr = addr; cpa.numpages = numpages; cpa.mask_set = mask_set; cpa.mask_clr = mask_clr; cpa.flushtlb = 0; - ret = __change_page_attr_set_clr(&cpa); + /* No alias checking for _NX bit modifications */ + checkalias = (pgprot_val(mask_set) | pgprot_val(mask_clr)) != _PAGE_NX; + + ret = __change_page_attr_set_clr(&cpa, checkalias); /* * Check whether we really changed something: @@ -832,7 +846,7 @@ static int __set_pages_p(struct page *page, int numpages) .mask_set = __pgprot(_PAGE_PRESENT | _PAGE_RW), .mask_clr = __pgprot(0)}; - return __change_page_attr_set_clr(&cpa); + return __change_page_attr_set_clr(&cpa, 1); } static int __set_pages_np(struct page *page, int numpages) @@ -842,7 +856,7 @@ static int __set_pages_np(struct page *page, int numpages) .mask_set = __pgprot(0), .mask_clr = __pgprot(_PAGE_PRESENT | _PAGE_RW)}; - return __change_page_attr_set_clr(&cpa); + return __change_page_attr_set_clr(&cpa, 1); } void kernel_map_pages(struct page *page, int numpages, int enable) @@ -861,8 +875,12 @@ void kernel_map_pages(struct page *page, int numpages, int enable) return; /* - * The return value is ignored - the calls cannot fail, - * large pages are disabled at boot time: + * The return value is ignored as the calls cannot fail. + * Large pages are kept enabled at boot time, and are + * split up quickly with DEBUG_PAGEALLOC. If a splitup + * fails here (due to temporary memory shortage) no damage + * is done because we just keep the largepage intact up + * to the next attempt when it will likely be split up: */ if (enable) __set_pages_p(page, numpages); @@ -881,7 +899,24 @@ void kernel_map_pages(struct page *page, int numpages, int enable) */ cpa_fill_pool(); } -#endif + +#ifdef CONFIG_HIBERNATION + +bool kernel_page_present(struct page *page) +{ + unsigned int level; + pte_t *pte; + + if (PageHighMem(page)) + return false; + + pte = lookup_address((unsigned long)page_address(page), &level); + return (pte_val(*pte) & _PAGE_PRESENT); +} + +#endif /* CONFIG_HIBERNATION */ + +#endif /* CONFIG_DEBUG_PAGEALLOC */ /* * The testcases use internal knowledge of the implementation that shouldn't diff --git a/arch/x86/mm/srat_64.c b/arch/x86/mm/srat_64.c index ecd91ea8a8ae..845001c617cc 100644 --- a/arch/x86/mm/srat_64.c +++ b/arch/x86/mm/srat_64.c @@ -166,7 +166,8 @@ static inline int save_add_info(void) {return 0;} * Both SPARSE and RESERVE need nodes_add information. * This code supports one contiguous hot add area per node. */ -static int reserve_hotadd(int node, unsigned long start, unsigned long end) +static int __init +reserve_hotadd(int node, unsigned long start, unsigned long end) { unsigned long s_pfn = start >> PAGE_SHIFT; unsigned long e_pfn = end >> PAGE_SHIFT; diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c index b7c67a187b6b..7b6e3bb9b28c 100644 --- a/arch/x86/pci/common.c +++ b/arch/x86/pci/common.c @@ -541,7 +541,7 @@ void pcibios_disable_device (struct pci_dev *dev) pcibios_disable_irq(dev); } -struct pci_bus *pci_scan_bus_with_sysdata(int busno) +struct pci_bus *__devinit pci_scan_bus_with_sysdata(int busno) { struct pci_bus *bus = NULL; struct pci_sysdata *sd; diff --git a/arch/x86/power/hibernate_asm_64.S b/arch/x86/power/hibernate_asm_64.S index 1deb3244b99b..000415947d93 100644 --- a/arch/x86/power/hibernate_asm_64.S +++ b/arch/x86/power/hibernate_asm_64.S @@ -20,6 +20,7 @@ #include #include #include +#include ENTRY(swsusp_arch_suspend) movq $saved_context, %rax @@ -60,7 +61,7 @@ ENTRY(restore_image) /* Flush TLB */ movq mmu_cr4_features(%rip), %rax movq %rax, %rdx - andq $~(1<<7), %rdx # PGE + andq $~(X86_CR4_PGE), %rdx movq %rdx, %cr4; # turn off PGE movq %cr3, %rcx; # flush TLB movq %rcx, %cr3; @@ -112,7 +113,7 @@ ENTRY(restore_registers) /* Flush TLB, including "global" things (vmalloc) */ movq mmu_cr4_features(%rip), %rax movq %rax, %rdx - andq $~(1<<7), %rdx; # PGE + andq $~(X86_CR4_PGE), %rdx movq %rdx, %cr4; # turn off PGE movq %cr3, %rcx; # flush TLB movq %rcx, %cr3 diff --git a/arch/xtensa/Makefile b/arch/xtensa/Makefile index 56685a883347..4bd1e14c6b90 100644 --- a/arch/xtensa/Makefile +++ b/arch/xtensa/Makefile @@ -59,7 +59,7 @@ LIBGCC := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name) head-y := arch/xtensa/kernel/head.o core-y += arch/xtensa/kernel/ arch/xtensa/mm/ ifneq ($(PLATFORM),) -core-y += arch/xtensa/platform-$(PLATFORM)/ +core-y += arch/xtensa/platforms/$(PLATFORM)/ endif libs-y += arch/xtensa/lib/ $(LIBGCC) diff --git a/arch/xtensa/boot/boot-elf/Makefile b/arch/xtensa/boot/boot-elf/Makefile index 734db7f76583..08e8814f8c71 100644 --- a/arch/xtensa/boot/boot-elf/Makefile +++ b/arch/xtensa/boot/boot-elf/Makefile @@ -14,25 +14,26 @@ OBJCOPY_ARGS := -O elf32-xtensa-le endif export OBJCOPY_ARGS +export CPPFLAGS_boot.lds += -P -C boot-y := bootstrap.o OBJS := $(addprefix $(obj)/,$(boot-y)) -Image: vmlinux $(OBJS) - $(OBJCOPY) --strip-all -R .comment -R .xt.insn -O binary \ +Image: vmlinux $(OBJS) arch/$(ARCH)/boot/boot-elf/boot.lds + $(OBJCOPY) --strip-all -R .comment -R .note.gnu.build-id -O binary \ vmlinux vmlinux.tmp $(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \ --add-section image=vmlinux.tmp \ --set-section-flags image=contents,alloc,load,load,data \ $(OBJS) $@.tmp $(LD) $(LDFLAGS) $(LDFLAGS_vmlinux) \ - -T $(srctree)/arch/$(ARCH)/boot/boot-elf/boot.ld \ + -T arch/$(ARCH)/boot/boot-elf/boot.lds \ -o arch/$(ARCH)/boot/$@.elf $@.tmp rm -f $@.tmp vmlinux.tmp Image.initrd: vmlinux $(OBJS) - $(OBJCOPY) --strip-all -R .comment -R .xt.insn -O binary \ + $(OBJCOPY) --strip-all -R .comment -R .note.gnu.build-id -O binary \ --add-section .initrd=arch/$(ARCH)/boot/ramdisk \ --set-section-flags .initrd=contents,alloc,load,load,data \ vmlinux vmlinux.tmp diff --git a/arch/xtensa/boot/boot-elf/boot.ld b/arch/xtensa/boot/boot-elf/boot.lds.S similarity index 89% rename from arch/xtensa/boot/boot-elf/boot.ld rename to arch/xtensa/boot/boot-elf/boot.lds.S index 4ab06a0a7a6b..849dfcafd518 100644 --- a/arch/xtensa/boot/boot-elf/boot.ld +++ b/arch/xtensa/boot/boot-elf/boot.lds.S @@ -1,4 +1,6 @@ +#include OUTPUT_ARCH(xtensa) +ENTRY(_ResetVector) SECTIONS { @@ -61,7 +63,7 @@ SECTIONS _end = .; _param_start = .; - .ResetVector.text 0xfe000020 : + .ResetVector.text XCHAL_RESET_VECTOR_VADDR : { *(.ResetVector.text) } diff --git a/arch/xtensa/boot/boot-redboot/Makefile b/arch/xtensa/boot/boot-redboot/Makefile index 74d15d08077b..872029b84435 100644 --- a/arch/xtensa/boot/boot-redboot/Makefile +++ b/arch/xtensa/boot/boot-redboot/Makefile @@ -22,7 +22,7 @@ LIBS := arch/xtensa/boot/lib/lib.a arch/xtensa/lib/lib.a LIBGCC := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name) zImage: vmlinux $(OBJS) $(LIBS) - $(OBJCOPY) --strip-all -R .comment -R .xt.insn -O binary \ + $(OBJCOPY) --strip-all -R .comment -R .note.gnu.build-id -O binary \ vmlinux vmlinux.tmp gzip -vf9 vmlinux.tmp $(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \ diff --git a/arch/xtensa/boot/boot-redboot/boot.ld b/arch/xtensa/boot/boot-redboot/boot.ld index 65b726410e8a..774db20d11f7 100644 --- a/arch/xtensa/boot/boot-redboot/boot.ld +++ b/arch/xtensa/boot/boot-redboot/boot.ld @@ -2,7 +2,7 @@ OUTPUT_ARCH(xtensa) SECTIONS { - .start 0xD0200000 : { *(.start) } + .start 0xD1000000 : { *(.start) } .text : { diff --git a/arch/xtensa/kernel/asm-offsets.c b/arch/xtensa/kernel/asm-offsets.c index d5ffe7b6443e..ef63adadf7f4 100644 --- a/arch/xtensa/kernel/asm-offsets.c +++ b/arch/xtensa/kernel/asm-offsets.c @@ -21,7 +21,6 @@ #include #include -#include #include #define DEFINE(sym, val) asm volatile("\n->" #sym " %0 " #val : : "i" (val)) @@ -64,6 +63,8 @@ int main(void) DEFINE(PT_SIZE, sizeof(struct pt_regs)); DEFINE(PT_AREG_END, offsetof (struct pt_regs, areg[XCHAL_NUM_AREGS])); DEFINE(PT_USER_SIZE, offsetof(struct pt_regs, areg[XCHAL_NUM_AREGS])); + DEFINE(PT_XTREGS_OPT, offsetof(struct pt_regs, xtregs_opt)); + DEFINE(XTREGS_OPT_SIZE, sizeof(xtregs_opt_t)); /* struct task_struct */ DEFINE(TASK_PTRACE, offsetof (struct task_struct, ptrace)); @@ -77,7 +78,19 @@ int main(void) /* struct thread_info (offset from start_struct) */ DEFINE(THREAD_RA, offsetof (struct task_struct, thread.ra)); DEFINE(THREAD_SP, offsetof (struct task_struct, thread.sp)); - DEFINE(THREAD_CP_SAVE, offsetof (struct task_struct, thread.cp_save)); + DEFINE(THREAD_CPENABLE, offsetof (struct thread_info, cpenable)); +#if XTENSA_HAVE_COPROCESSORS + DEFINE(THREAD_XTREGS_CP0, offsetof (struct thread_info, xtregs_cp)); + DEFINE(THREAD_XTREGS_CP1, offsetof (struct thread_info, xtregs_cp)); + DEFINE(THREAD_XTREGS_CP2, offsetof (struct thread_info, xtregs_cp)); + DEFINE(THREAD_XTREGS_CP3, offsetof (struct thread_info, xtregs_cp)); + DEFINE(THREAD_XTREGS_CP4, offsetof (struct thread_info, xtregs_cp)); + DEFINE(THREAD_XTREGS_CP5, offsetof (struct thread_info, xtregs_cp)); + DEFINE(THREAD_XTREGS_CP6, offsetof (struct thread_info, xtregs_cp)); + DEFINE(THREAD_XTREGS_CP7, offsetof (struct thread_info, xtregs_cp)); +#endif + DEFINE(THREAD_XTREGS_USER, offsetof (struct thread_info, xtregs_user)); + DEFINE(XTREGS_USER_SIZE, sizeof(xtregs_user_t)); DEFINE(THREAD_CURRENT_DS, offsetof (struct task_struct, thread.current_ds)); /* struct mm_struct */ diff --git a/arch/xtensa/kernel/coprocessor.S b/arch/xtensa/kernel/coprocessor.S index 01bcb9fcfcbd..2bc1e145c0a4 100644 --- a/arch/xtensa/kernel/coprocessor.S +++ b/arch/xtensa/kernel/coprocessor.S @@ -8,193 +8,328 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2003 - 2005 Tensilica Inc. - * - * Marc Gauthier + * Copyright (C) 2003 - 2007 Tensilica Inc. */ -/* - * This module contains a table that describes the layout of the various - * custom registers and states associated with each coprocessor, as well - * as those not associated with any coprocessor ("extra state"). - * This table is included with core dumps and is available via the ptrace - * interface, allowing the layout of such register/state information to - * be modified in the kernel without affecting the debugger. Each - * register or state is identified using a 32-bit "libdb target number" - * assigned when the Xtensa processor is generated. - */ #include +#include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include -#if XCHAL_HAVE_CP +/* + * Entry condition: + * + * a0: trashed, original value saved on stack (PT_AREG0) + * a1: a1 + * a2: new stack pointer, original in DEPC + * a3: dispatch table + * depc: a2, original value saved on stack (PT_DEPC) + * excsave_1: a3 + * + * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC + * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception + */ -#define CP_LAST ((XCHAL_CP_MAX - 1) * COPROCESSOR_INFO_SIZE) +/* IO protection is currently unsupported. */ -ENTRY(release_coprocessors) +ENTRY(fast_io_protect) + wsr a0, EXCSAVE_1 + movi a0, unrecoverable_exception + callx0 a0 - entry a1, 16 - # a2: task - movi a3, 1 << XCHAL_CP_MAX # a3: coprocessor-bit - movi a4, coprocessor_info+CP_LAST # a4: owner-table - # a5: tmp - movi a6, 0 # a6: 0 - rsil a7, LOCKLEVEL # a7: PS +#if XTENSA_HAVE_COPROCESSORS -1: /* Check if task is coprocessor owner of coprocessor[i]. */ +/* + * Macros for lazy context switch. + */ - l32i a5, a4, COPROCESSOR_INFO_OWNER - srli a3, a3, 1 +#define SAVE_CP_REGS(x) \ + .align 4; \ + .Lsave_cp_regs_cp##x: \ + .if XTENSA_HAVE_COPROCESSOR(x); \ + xchal_cp##x##_store a2 a4 a5 a6 a7; \ + .endif; \ + jx a0 + +#define SAVE_CP_REGS_TAB(x) \ + .if XTENSA_HAVE_COPROCESSOR(x); \ + .long .Lsave_cp_regs_cp##x - .Lsave_cp_regs_jump_table; \ + .else; \ + .long 0; \ + .endif; \ + .long THREAD_XTREGS_CP##x + + +#define LOAD_CP_REGS(x) \ + .align 4; \ + .Lload_cp_regs_cp##x: \ + .if XTENSA_HAVE_COPROCESSOR(x); \ + xchal_cp##x##_load a2 a4 a5 a6 a7; \ + .endif; \ + jx a0 + +#define LOAD_CP_REGS_TAB(x) \ + .if XTENSA_HAVE_COPROCESSOR(x); \ + .long .Lload_cp_regs_cp##x - .Lload_cp_regs_jump_table; \ + .else; \ + .long 0; \ + .endif; \ + .long THREAD_XTREGS_CP##x + + SAVE_CP_REGS(0) + SAVE_CP_REGS(1) + SAVE_CP_REGS(2) + SAVE_CP_REGS(3) + SAVE_CP_REGS(4) + SAVE_CP_REGS(5) + SAVE_CP_REGS(6) + SAVE_CP_REGS(7) + + LOAD_CP_REGS(0) + LOAD_CP_REGS(1) + LOAD_CP_REGS(2) + LOAD_CP_REGS(3) + LOAD_CP_REGS(4) + LOAD_CP_REGS(5) + LOAD_CP_REGS(6) + LOAD_CP_REGS(7) + + .align 4 +.Lsave_cp_regs_jump_table: + SAVE_CP_REGS_TAB(0) + SAVE_CP_REGS_TAB(1) + SAVE_CP_REGS_TAB(2) + SAVE_CP_REGS_TAB(3) + SAVE_CP_REGS_TAB(4) + SAVE_CP_REGS_TAB(5) + SAVE_CP_REGS_TAB(6) + SAVE_CP_REGS_TAB(7) + +.Lload_cp_regs_jump_table: + LOAD_CP_REGS_TAB(0) + LOAD_CP_REGS_TAB(1) + LOAD_CP_REGS_TAB(2) + LOAD_CP_REGS_TAB(3) + LOAD_CP_REGS_TAB(4) + LOAD_CP_REGS_TAB(5) + LOAD_CP_REGS_TAB(6) + LOAD_CP_REGS_TAB(7) + +/* + * coprocessor_save(buffer, index) + * a2 a3 + * coprocessor_load(buffer, index) + * a2 a3 + * + * Save or load coprocessor registers for coprocessor 'index'. + * The register values are saved to or loaded from them 'buffer' address. + * + * Note that these functions don't update the coprocessor_owner information! + * + */ + +ENTRY(coprocessor_save) + entry a1, 32 + s32i a0, a1, 0 + movi a0, .Lsave_cp_regs_jump_table + addx8 a3, a3, a0 + l32i a3, a3, 0 beqz a3, 1f - addi a4, a4, -8 - beq a2, a5, 1b - - /* Found an entry: Clear entry CPENABLE bit to disable CP. */ - - rsr a5, CPENABLE - s32i a6, a4, COPROCESSOR_INFO_OWNER - xor a5, a3, a5 - wsr a5, CPENABLE - - bnez a3, 1b - -1: wsr a7, PS - rsync + add a0, a0, a3 + callx0 a0 +1: l32i a0, a1, 0 retw - -ENTRY(disable_coprocessor) - entry sp, 16 - rsil a7, LOCKLEVEL - rsr a3, CPENABLE - movi a4, 1 - ssl a2 - sll a4, a4 - and a4, a3, a4 - xor a3, a3, a4 - wsr a3, CPENABLE - wsr a7, PS - rsync +ENTRY(coprocessor_load) + entry a1, 32 + s32i a0, a1, 0 + movi a0, .Lload_cp_regs_jump_table + addx4 a3, a3, a0 + l32i a3, a3, 0 + beqz a3, 1f + add a0, a0, a3 + callx0 a0 +1: l32i a0, a1, 0 retw -ENTRY(enable_coprocessor) - entry sp, 16 - rsil a7, LOCKLEVEL - rsr a3, CPENABLE - movi a4, 1 - ssl a2 - sll a4, a4 - or a3, a3, a4 - wsr a3, CPENABLE - wsr a7, PS - rsync - retw - - -ENTRY(save_coprocessor_extra) - entry sp, 16 - xchal_extra_store_funcbody - retw - -ENTRY(restore_coprocessor_extra) - entry sp, 16 - xchal_extra_load_funcbody - retw - -ENTRY(save_coprocessor_registers) - entry sp, 16 - xchal_cpi_store_funcbody - retw - -ENTRY(restore_coprocessor_registers) - entry sp, 16 - xchal_cpi_load_funcbody - retw - - /* - * The Xtensa compile-time HAL (core.h) XCHAL_*_SA_CONTENTS_LIBDB macros - * describe the contents of coprocessor & extra save areas in terms of - * undefined CONTENTS_LIBDB_{SREG,UREG,REGF} macros. We define these - * latter macros here; they expand into a table of the format we want. - * The general format is: + * coprocessor_flush(struct task_info*, index) + * a2 a3 + * coprocessor_restore(struct task_info*, index) + * a2 a3 * - * CONTENTS_LIBDB_SREG(libdbnum, offset, size, align, rsv1, name, sregnum, - * bitmask, rsv2, rsv3) - * CONTENTS_LIBDB_UREG(libdbnum, offset, size, align, rsv1, name, uregnum, - * bitmask, rsv2, rsv3) - * CONTENTS_LIBDB_REGF(libdbnum, offset, size, align, rsv1, name, index, - * numentries, contentsize, regname_base, - * regfile_name, rsv2, rsv3) + * Save or load coprocessor registers for coprocessor 'index'. + * The register values are saved to or loaded from the coprocessor area + * inside the task_info structure. + * + * Note that these functions don't update the coprocessor_owner information! * - * For this table, we only care about the , and - * fields. */ -/* Map all XCHAL CONTENTS macros to the reg_entry asm macro defined below: */ -#define CONTENTS_LIBDB_SREG(libdbnum,offset,size,align,rsv1,name,sregnum, \ - bitmask, rsv2, rsv3) \ - reg_entry libdbnum, offset, size ; -#define CONTENTS_LIBDB_UREG(libdbnum,offset,size,align,rsv1,name,uregnum, \ - bitmask, rsv2, rsv3) \ - reg_entry libdbnum, offset, size ; -#define CONTENTS_LIBDB_REGF(libdbnum, offset, size, align, rsv1, name, index, \ - numentries, contentsize, regname_base, \ - regfile_name, rsv2, rsv3) \ - reg_entry libdbnum, offset, size ; +ENTRY(coprocessor_flush) + entry a1, 32 + s32i a0, a1, 0 + movi a0, .Lsave_cp_regs_jump_table + addx8 a3, a3, a0 + l32i a4, a3, 4 + l32i a3, a3, 0 + add a2, a2, a4 + beqz a3, 1f + add a0, a0, a3 + callx0 a0 +1: l32i a0, a1, 0 + retw -/* A single table entry: */ - .macro reg_entry libdbnum, offset, size - .ifne (__last_offset-(__last_group_offset+\offset)) - /* padding entry */ - .word (0xFC000000+__last_offset-(__last_group_offset+\offset)) - .endif - .word \libdbnum /* actual entry */ - .set __last_offset, __last_group_offset+\offset+\size - .endm /* reg_entry */ - - -/* Table entry that marks the beginning of a group (coprocessor or "extra"): */ - .macro reg_group cpnum, num_entries, align - .set __last_group_offset, (__last_offset + \align- 1) & -\align - .ifne \num_entries - .word 0xFD000000+(\cpnum<<16)+\num_entries - .endif - .endm /* reg_group */ +ENTRY(coprocessor_restore) + entry a1, 32 + s32i a0, a1, 0 + movi a0, .Lload_cp_regs_jump_table + addx4 a3, a3, a0 + l32i a4, a3, 4 + l32i a3, a3, 0 + add a2, a2, a4 + beqz a3, 1f + add a0, a0, a3 + callx0 a0 +1: l32i a0, a1, 0 + retw /* - * Register info tables. + * Entry condition: + * + * a0: trashed, original value saved on stack (PT_AREG0) + * a1: a1 + * a2: new stack pointer, original in DEPC + * a3: dispatch table + * depc: a2, original value saved on stack (PT_DEPC) + * excsave_1: a3 + * + * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC + * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception */ - .section .rodata, "a" - .globl _xtensa_reginfo_tables - .globl _xtensa_reginfo_table_size - .align 4 -_xtensa_reginfo_table_size: - .word _xtensa_reginfo_table_end - _xtensa_reginfo_tables +ENTRY(fast_coprocessor_double) + wsr a0, EXCSAVE_1 + movi a0, unrecoverable_exception + callx0 a0 -_xtensa_reginfo_tables: - .set __last_offset, 0 - reg_group 0xFF, XCHAL_EXTRA_SA_CONTENTS_LIBDB_NUM, XCHAL_EXTRA_SA_ALIGN - XCHAL_EXTRA_SA_CONTENTS_LIBDB - reg_group 0, XCHAL_CP0_SA_CONTENTS_LIBDB_NUM, XCHAL_CP0_SA_ALIGN - XCHAL_CP0_SA_CONTENTS_LIBDB - reg_group 1, XCHAL_CP1_SA_CONTENTS_LIBDB_NUM, XCHAL_CP1_SA_ALIGN - XCHAL_CP1_SA_CONTENTS_LIBDB - reg_group 2, XCHAL_CP2_SA_CONTENTS_LIBDB_NUM, XCHAL_CP2_SA_ALIGN - XCHAL_CP2_SA_CONTENTS_LIBDB - reg_group 3, XCHAL_CP3_SA_CONTENTS_LIBDB_NUM, XCHAL_CP3_SA_ALIGN - XCHAL_CP3_SA_CONTENTS_LIBDB - reg_group 4, XCHAL_CP4_SA_CONTENTS_LIBDB_NUM, XCHAL_CP4_SA_ALIGN - XCHAL_CP4_SA_CONTENTS_LIBDB - reg_group 5, XCHAL_CP5_SA_CONTENTS_LIBDB_NUM, XCHAL_CP5_SA_ALIGN - XCHAL_CP5_SA_CONTENTS_LIBDB - reg_group 6, XCHAL_CP6_SA_CONTENTS_LIBDB_NUM, XCHAL_CP6_SA_ALIGN - XCHAL_CP6_SA_CONTENTS_LIBDB - reg_group 7, XCHAL_CP7_SA_CONTENTS_LIBDB_NUM, XCHAL_CP7_SA_ALIGN - XCHAL_CP7_SA_CONTENTS_LIBDB - .word 0xFC000000 /* invalid register number,marks end of table*/ -_xtensa_reginfo_table_end: -#endif + +ENTRY(fast_coprocessor) + + /* Save remaining registers a1-a3 and SAR */ + + xsr a3, EXCSAVE_1 + s32i a3, a2, PT_AREG3 + rsr a3, SAR + s32i a1, a2, PT_AREG1 + s32i a3, a2, PT_SAR + mov a1, a2 + rsr a2, DEPC + s32i a2, a1, PT_AREG2 + + /* + * The hal macros require up to 4 temporary registers. We use a3..a6. + */ + + s32i a4, a1, PT_AREG4 + s32i a5, a1, PT_AREG5 + s32i a6, a1, PT_AREG6 + + /* Find coprocessor number. Subtract first CP EXCCAUSE from EXCCAUSE */ + + rsr a3, EXCCAUSE + addi a3, a3, -EXCCAUSE_COPROCESSOR0_DISABLED + + /* Set corresponding CPENABLE bit -> (sar:cp-index, a3: 1< #include #include +#include /* Unimplemented features. */ -#undef SIGNAL_HANDLING_IN_DOUBLE_EXCEPTION #undef KERNEL_STACK_OVERFLOW_CHECK #undef PREEMPTIBLE_KERNEL #undef ALLOCA_EXCEPTION_IN_IRAM @@ -214,19 +214,7 @@ _user_exception: /* We are back to the original stack pointer (a1) */ -2: -#if XCHAL_EXTRA_SA_SIZE - - /* For user exceptions, save the extra state into the user's TCB. - * Note: We must assume that xchal_extra_store_funcbody destroys a2..a15 - */ - - GET_CURRENT(a2,a1) - addi a2, a2, THREAD_CP_SAVE - xchal_extra_store_funcbody -#endif - - /* Now, jump to the common exception handler. */ +2: /* Now, jump to the common exception handler. */ j common_exception @@ -382,6 +370,10 @@ common_exception: s32i a2, a1, PT_LBEG s32i a3, a1, PT_LEND + /* Save optional registers. */ + + save_xtregs_opt a1 a2 a4 a5 a6 a7 PT_XTREGS_OPT + /* Go to second-level dispatcher. Set up parameters to pass to the * exception handler and call the exception handler. */ @@ -403,75 +395,50 @@ common_exception_return: /* Jump if we are returning from kernel exceptions. */ 1: l32i a3, a1, PT_PS - _bbsi.l a3, PS_UM_BIT, 2f - j kernel_exception_exit + _bbci.l a3, PS_UM_BIT, 4f /* Specific to a user exception exit: * We need to check some flags for signal handling and rescheduling, * and have to restore WB and WS, extra states, and all registers * in the register file that were in use in the user task. - */ - -2: wsr a3, PS /* disable interrupts */ - - /* Check for signals (keep interrupts disabled while we read TI_FLAGS) - * Note: PS.INTLEVEL = 0, PS.EXCM = 1 + * Note that we don't disable interrupts here. */ GET_THREAD_INFO(a2,a1) l32i a4, a2, TI_FLAGS - /* Enable interrupts again. - * Note: When we get here, we certainly have handled any interrupts. - * (Hint: There is only one user exception frame on stack) - */ - - movi a3, 1 << PS_WOE_BIT - _bbsi.l a4, TIF_NEED_RESCHED, 3f _bbci.l a4, TIF_SIGPENDING, 4f -#ifndef SIGNAL_HANDLING_IN_DOUBLE_EXCEPTION l32i a4, a1, PT_DEPC bgeui a4, VALID_DOUBLE_EXCEPTION_ADDRESS, 4f -#endif - /* Reenable interrupts and call do_signal() */ + /* Call do_signal() */ - wsr a3, PS movi a4, do_signal # int do_signal(struct pt_regs*, sigset_t*) mov a6, a1 movi a7, 0 callx4 a4 j 1b -3: /* Reenable interrupts and reschedule */ +3: /* Reschedule */ - wsr a3, PS movi a4, schedule # void schedule (void) callx4 a4 j 1b +4: /* Restore optional registers. */ + + load_xtregs_opt a1 a2 a4 a5 a6 a7 PT_XTREGS_OPT + + wsr a3, PS /* disable interrupts */ + + _bbci.l a3, PS_UM_BIT, kernel_exception_exit + +user_exception_exit: + /* Restore the state of the task and return from the exception. */ -4: /* a2 holds GET_CURRENT(a2,a1) */ - -#if XCHAL_EXTRA_SA_SIZE - - /* For user exceptions, restore the extra state from the user's TCB. */ - - /* Note: a2 still contains GET_CURRENT(a2,a1) */ - addi a2, a2, THREAD_CP_SAVE - xchal_extra_load_funcbody - - /* We must assume that xchal_extra_store_funcbody destroys - * registers a2..a15. FIXME, this list can eventually be - * reduced once real register requirements of the macro are - * finalized. */ - -#endif /* XCHAL_EXTRA_SA_SIZE */ - - /* Switch to the user thread WINDOWBASE. Save SP temporarily in DEPC */ l32i a2, a1, PT_WINDOWBASE @@ -536,10 +503,6 @@ common_exception_return: kernel_exception_exit: - /* Disable interrupts (a3 holds PT_PS) */ - - wsr a3, PS - #ifdef PREEMPTIBLE_KERNEL #ifdef CONFIG_PREEMPT @@ -618,6 +581,8 @@ kernel_exception_exit: common_exception_exit: + /* Restore address registers. */ + _bbsi.l a2, 1, 1f l32i a4, a1, PT_AREG4 l32i a5, a1, PT_AREG5 @@ -1150,7 +1115,6 @@ CATCH * excsave_1: a3 * * Note: We assume the stack pointer is EXC_TABLE_KSTK in the fixup handler. - * Note: We don't need to save a2 in depc (return value) */ ENTRY(fast_syscall_spill_registers) @@ -1166,29 +1130,31 @@ ENTRY(fast_syscall_spill_registers) rsr a0, SAR xsr a3, EXCSAVE_1 # restore a3 and excsave_1 - s32i a0, a2, PT_AREG4 # store SAR to PT_AREG4 s32i a3, a2, PT_AREG3 + s32i a4, a2, PT_AREG4 + s32i a0, a2, PT_AREG5 # store SAR to PT_AREG5 /* The spill routine might clobber a7, a11, and a15. */ - s32i a7, a2, PT_AREG5 - s32i a11, a2, PT_AREG6 - s32i a15, a2, PT_AREG7 + s32i a7, a2, PT_AREG7 + s32i a11, a2, PT_AREG11 + s32i a15, a2, PT_AREG15 - call0 _spill_registers # destroys a3, DEPC, and SAR + call0 _spill_registers # destroys a3, a4, and SAR /* Advance PC, restore registers and SAR, and return from exception. */ - l32i a3, a2, PT_AREG4 + l32i a3, a2, PT_AREG5 + l32i a4, a2, PT_AREG4 l32i a0, a2, PT_AREG0 wsr a3, SAR l32i a3, a2, PT_AREG3 /* Restore clobbered registers. */ - l32i a7, a2, PT_AREG5 - l32i a11, a2, PT_AREG6 - l32i a15, a2, PT_AREG7 + l32i a7, a2, PT_AREG7 + l32i a11, a2, PT_AREG11 + l32i a15, a2, PT_AREG15 movi a2, 0 rfe @@ -1247,16 +1213,6 @@ fast_syscall_spill_registers_fixup: * Note: This frame might be the same as above. */ -#ifdef SIGNAL_HANDLING_IN_DOUBLE_EXCEPTION - /* Restore registers we precautiously saved. - * We have the value of the 'right' a3 - */ - - l32i a7, a2, PT_AREG5 - l32i a11, a2, PT_AREG6 - l32i a15, a2, PT_AREG7 -#endif - /* Setup stack pointer. */ addi a2, a2, -PT_USER_SIZE @@ -1271,9 +1227,9 @@ fast_syscall_spill_registers_fixup: movi a3, exc_table rsr a0, EXCCAUSE - addx4 a0, a0, a3 # find entry in table - l32i a0, a0, EXC_TABLE_FAST_USER # load handler - jx a0 + addx4 a0, a0, a3 # find entry in table + l32i a0, a0, EXC_TABLE_FAST_USER # load handler + jx a0 fast_syscall_spill_registers_fixup_return: @@ -1290,14 +1246,6 @@ fast_syscall_spill_registers_fixup_return: s32i a2, a3, EXC_TABLE_PARAM l32i a2, a3, EXC_TABLE_KSTK -#ifdef SIGNAL_HANDLING_IN_DOUBLE_EXCEPTION - /* Save registers again that might be clobbered. */ - - s32i a7, a2, PT_AREG5 - s32i a11, a2, PT_AREG6 - s32i a15, a2, PT_AREG7 -#endif - /* Load WB at the time the exception occurred. */ rsr a3, SAR # WB is still in SAR @@ -1319,7 +1267,7 @@ fast_syscall_spill_registers_fixup_return: * This is not a real function. The following conditions must be met: * * - must be called with call0. - * - uses DEPC, a3 and SAR. + * - uses a3, a4 and SAR. * - the last 'valid' register of each frame are clobbered. * - the caller must have registered a fixup handler * (or be inside a critical section) @@ -1331,41 +1279,39 @@ ENTRY(_spill_registers) /* * Rotate ws so that the current windowbase is at bit 0. * Assume ws = xxxwww1yy (www1 current window frame). - * Rotate ws right so that a2 = yyxxxwww1. + * Rotate ws right so that a4 = yyxxxwww1. */ - wsr a2, DEPC # preserve a2 - rsr a2, WINDOWBASE - rsr a3, WINDOWSTART - ssr a2 # holds WB - slli a2, a3, WSBITS - or a3, a3, a2 # a2 = xxxwww1yyxxxwww1yy - srl a3, a3 + rsr a4, WINDOWBASE + rsr a3, WINDOWSTART # a3 = xxxwww1yy + ssr a4 # holds WB + slli a4, a3, WSBITS + or a3, a3, a4 # a3 = xxxwww1yyxxxwww1yy + srl a3, a3 # a3 = 00xxxwww1yyxxxwww1 /* We are done if there are no more than the current register frame. */ - extui a3, a3, 1, WSBITS-2 # a3 = 0yyxxxwww - movi a2, (1 << (WSBITS-1)) + extui a3, a3, 1, WSBITS-1 # a3 = 0yyxxxwww + movi a4, (1 << (WSBITS-1)) _beqz a3, .Lnospill # only one active frame? jump /* We want 1 at the top, so that we return to the current windowbase */ - or a3, a3, a2 # 1yyxxxwww + or a3, a3, a4 # 1yyxxxwww /* Skip empty frames - get 'oldest' WINDOWSTART-bit. */ wsr a3, WINDOWSTART # save shifted windowstart - neg a2, a3 - and a3, a2, a3 # first bit set from right: 000010000 + neg a4, a3 + and a3, a4, a3 # first bit set from right: 000010000 - ffs_ws a2, a3 # a2: shifts to skip empty frames + ffs_ws a4, a3 # a4: shifts to skip empty frames movi a3, WSBITS - sub a2, a3, a2 # WSBITS-a2:number of 0-bits from right - ssr a2 # save in SAR for later. + sub a4, a3, a4 # WSBITS-a4:number of 0-bits from right + ssr a4 # save in SAR for later. rsr a3, WINDOWBASE - add a3, a3, a2 - rsr a2, DEPC # restore a2 + add a3, a3, a4 wsr a3, WINDOWBASE rsync @@ -1394,6 +1340,9 @@ ENTRY(_spill_registers) l32e a4, a1, -16 j .Lc12c +.Lnospill: + ret + .Lloop: _bbsi.l a3, 1, .Lc4 _bbci.l a3, 2, .Lc12 @@ -1419,9 +1368,7 @@ ENTRY(_spill_registers) movi a3, 1 sll a3, a3 wsr a3, WINDOWSTART - -.Lnospill: - jx a0 + ret .Lc4: s32e a4, a9, -16 s32e a5, a9, -12 @@ -1830,154 +1777,6 @@ ENTRY(fast_store_prohibited) 1: j _user_exception -#if XCHAL_EXTRA_SA_SIZE - -#warning fast_coprocessor untested - -/* - * Entry condition: - * - * a0: trashed, original value saved on stack (PT_AREG0) - * a1: a1 - * a2: new stack pointer, original in DEPC - * a3: dispatch table - * depc: a2, original value saved on stack (PT_DEPC) - * excsave_1: a3 - * - * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC - * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception - */ - -ENTRY(fast_coprocessor_double) - wsr a0, EXCSAVE_1 - movi a0, unrecoverable_exception - callx0 a0 - -ENTRY(fast_coprocessor) - - /* Fatal if we are in a double exception. */ - - l32i a0, a2, PT_DEPC - _bgeui a0, VALID_DOUBLE_EXCEPTION_ADDRESS, fast_coprocessor_double - - /* Save some registers a1, a3, a4, SAR */ - - xsr a3, EXCSAVE_1 - s32i a3, a2, PT_AREG3 - rsr a3, SAR - s32i a4, a2, PT_AREG4 - s32i a1, a2, PT_AREG1 - s32i a5, a1, PT_AREG5 - s32i a3, a2, PT_SAR - mov a1, a2 - - /* Currently, the HAL macros only guarantee saving a0 and a1. - * These can and will be refined in the future, but for now, - * just save the remaining registers of a2...a15. - */ - s32i a6, a1, PT_AREG6 - s32i a7, a1, PT_AREG7 - s32i a8, a1, PT_AREG8 - s32i a9, a1, PT_AREG9 - s32i a10, a1, PT_AREG10 - s32i a11, a1, PT_AREG11 - s32i a12, a1, PT_AREG12 - s32i a13, a1, PT_AREG13 - s32i a14, a1, PT_AREG14 - s32i a15, a1, PT_AREG15 - - /* Find coprocessor number. Subtract first CP EXCCAUSE from EXCCAUSE */ - - rsr a0, EXCCAUSE - addi a3, a0, -XCHAL_EXCCAUSE_COPROCESSOR0_DISABLED - - /* Set corresponding CPENABLE bit */ - - movi a4, 1 - ssl a3 # SAR: 32 - coprocessor_number - rsr a5, CPENABLE - sll a4, a4 - or a4, a5, a4 - wsr a4, CPENABLE - rsync - movi a5, coprocessor_info # list of owner and offset into cp_save - addx8 a0, a4, a5 # entry for CP - - bne a4, a5, .Lload # bit wasn't set before, cp not in use - - /* Now compare the current task with the owner of the coprocessor. - * If they are the same, there is no reason to save or restore any - * coprocessor state. Having already enabled the coprocessor, - * branch ahead to return. - */ - GET_CURRENT(a5,a1) - l32i a4, a0, COPROCESSOR_INFO_OWNER # a4: current owner for this CP - beq a4, a5, .Ldone - - /* Find location to dump current coprocessor state: - * task_struct->task_cp_save_offset + coprocessor_offset[coprocessor] - * - * Note: a0 pointer to the entry in the coprocessor owner table, - * a3 coprocessor number, - * a4 current owner of coprocessor. - */ - l32i a5, a0, COPROCESSOR_INFO_OFFSET - addi a2, a4, THREAD_CP_SAVE - add a2, a2, a5 - - /* Store current coprocessor states. (a5 still has CP number) */ - - xchal_cpi_store_funcbody - - /* The macro might have destroyed a3 (coprocessor number), but - * SAR still has 32 - coprocessor_number! - */ - movi a3, 32 - rsr a4, SAR - sub a3, a3, a4 - -.Lload: /* A new task now owns the corpocessors. Save its TCB pointer into - * the coprocessor owner table. - * - * Note: a0 pointer to the entry in the coprocessor owner table, - * a3 coprocessor number. - */ - GET_CURRENT(a4,a1) - s32i a4, a0, 0 - - /* Find location from where to restore the current coprocessor state.*/ - - l32i a5, a0, COPROCESSOR_INFO_OFFSET - addi a2, a4, THREAD_CP_SAVE - add a2, a2, a4 - - xchal_cpi_load_funcbody - - /* We must assume that the xchal_cpi_store_funcbody macro destroyed - * registers a2..a15. - */ - -.Ldone: l32i a15, a1, PT_AREG15 - l32i a14, a1, PT_AREG14 - l32i a13, a1, PT_AREG13 - l32i a12, a1, PT_AREG12 - l32i a11, a1, PT_AREG11 - l32i a10, a1, PT_AREG10 - l32i a9, a1, PT_AREG9 - l32i a8, a1, PT_AREG8 - l32i a7, a1, PT_AREG7 - l32i a6, a1, PT_AREG6 - l32i a5, a1, PT_AREG5 - l32i a4, a1, PT_AREG4 - l32i a3, a1, PT_AREG3 - l32i a2, a1, PT_AREG2 - l32i a0, a1, PT_AREG0 - l32i a1, a1, PT_AREG1 - - rfe - -#endif /* XCHAL_EXTRA_SA_SIZE */ - /* * System Calls. * @@ -2086,20 +1885,36 @@ ENTRY(_switch_to) entry a1, 16 - mov a4, a3 # preserve a3 + mov a12, a2 # preserve 'prev' (a2) + mov a13, a3 # and 'next' (a3) - s32i a0, a2, THREAD_RA # save return address - s32i a1, a2, THREAD_SP # save stack pointer + l32i a4, a2, TASK_THREAD_INFO + l32i a5, a3, TASK_THREAD_INFO - /* Disable ints while we manipulate the stack pointer; spill regs. */ + save_xtregs_user a4 a6 a8 a9 a10 a11 THREAD_XTREGS_USER - movi a5, (1 << PS_EXCM_BIT) | LOCKLEVEL - xsr a5, PS + s32i a0, a12, THREAD_RA # save return address + s32i a1, a12, THREAD_SP # save stack pointer + + /* Disable ints while we manipulate the stack pointer. */ + + movi a14, (1 << PS_EXCM_BIT) | LOCKLEVEL + xsr a14, PS rsr a3, EXCSAVE_1 rsync s32i a3, a3, EXC_TABLE_FIXUP /* enter critical section */ - call0 _spill_registers + /* Switch CPENABLE */ + +#if (XTENSA_HAVE_COPROCESSORS || XTENSA_HAVE_IO_PORTS) + l32i a3, a5, THREAD_CPENABLE + xsr a3, CPENABLE + s32i a3, a4, THREAD_CPENABLE +#endif + + /* Flush register file. */ + + call0 _spill_registers # destroys a3, a4, and SAR /* Set kernel stack (and leave critical section) * Note: It's save to set it here. The stack will not be overwritten @@ -2107,19 +1922,21 @@ ENTRY(_switch_to) * we return from kernel space. */ - l32i a0, a4, TASK_THREAD_INFO rsr a3, EXCSAVE_1 # exc_table - movi a1, 0 - addi a0, a0, PT_REGS_OFFSET - s32i a1, a3, EXC_TABLE_FIXUP - s32i a0, a3, EXC_TABLE_KSTK + movi a6, 0 + addi a7, a5, PT_REGS_OFFSET + s32i a6, a3, EXC_TABLE_FIXUP + s32i a7, a3, EXC_TABLE_KSTK /* restore context of the task that 'next' addresses */ - l32i a0, a4, THREAD_RA /* restore return address */ - l32i a1, a4, THREAD_SP /* restore stack pointer */ + l32i a0, a13, THREAD_RA # restore return address + l32i a1, a13, THREAD_SP # restore stack pointer - wsr a5, PS + load_xtregs_user a5 a6 a8 a9 a10 a11 THREAD_XTREGS_USER + + wsr a14, PS + mov a2, a12 # return 'prev' rsync retw diff --git a/arch/xtensa/kernel/module.c b/arch/xtensa/kernel/module.c index ddf14dcf2ad9..3981a466c779 100644 --- a/arch/xtensa/kernel/module.c +++ b/arch/xtensa/kernel/module.c @@ -28,7 +28,7 @@ void *module_alloc(unsigned long size) { if (size == 0) return NULL; - return vmalloc(size); + return vmalloc_exec(size); } void module_free(struct module *mod, void *module_region) diff --git a/arch/xtensa/kernel/process.c b/arch/xtensa/kernel/process.c index f53d7bd9dfb2..9185597eb6a0 100644 --- a/arch/xtensa/kernel/process.c +++ b/arch/xtensa/kernel/process.c @@ -52,6 +52,55 @@ void (*pm_power_off)(void) = NULL; EXPORT_SYMBOL(pm_power_off); +#if XTENSA_HAVE_COPROCESSORS + +void coprocessor_release_all(struct thread_info *ti) +{ + unsigned long cpenable; + int i; + + /* Make sure we don't switch tasks during this operation. */ + + preempt_disable(); + + /* Walk through all cp owners and release it for the requested one. */ + + cpenable = ti->cpenable; + + for (i = 0; i < XCHAL_CP_MAX; i++) { + if (coprocessor_owner[i] == ti) { + coprocessor_owner[i] = 0; + cpenable &= ~(1 << i); + } + } + + ti->cpenable = cpenable; + coprocessor_clear_cpenable(); + + preempt_enable(); +} + +void coprocessor_flush_all(struct thread_info *ti) +{ + unsigned long cpenable; + int i; + + preempt_disable(); + + cpenable = ti->cpenable; + + for (i = 0; i < XCHAL_CP_MAX; i++) { + if ((cpenable & 1) != 0 && coprocessor_owner[i] == ti) + coprocessor_flush(ti, i); + cpenable >>= 1; + } + + preempt_enable(); +} + +#endif + + /* * Powermanagement idle function, if any is provided by the platform. */ @@ -71,15 +120,36 @@ void cpu_idle(void) } /* - * Free current thread data structures etc.. + * This is called when the thread calls exit(). */ - void exit_thread(void) { +#if XTENSA_HAVE_COPROCESSORS + coprocessor_release_all(current_thread_info()); +#endif } +/* + * Flush thread state. This is called when a thread does an execve() + * Note that we flush coprocessor registers for the case execve fails. + */ void flush_thread(void) { +#if XTENSA_HAVE_COPROCESSORS + struct thread_info *ti = current_thread_info(); + coprocessor_flush_all(ti); + coprocessor_release_all(ti); +#endif +} + +/* + * This is called before the thread is copied. + */ +void prepare_to_copy(struct task_struct *tsk) +{ +#if XTENSA_HAVE_COPROCESSORS + coprocessor_flush_all(task_thread_info(tsk)); +#endif } /* @@ -107,6 +177,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, struct task_struct * p, struct pt_regs * regs) { struct pt_regs *childregs; + struct thread_info *ti; unsigned long tos; int user_mode = user_mode(regs); @@ -128,13 +199,14 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, p->set_child_tid = p->clear_child_tid = NULL; p->thread.ra = MAKE_RA_FOR_CALL((unsigned long)ret_from_fork, 0x1); p->thread.sp = (unsigned long)childregs; + if (user_mode(regs)) { int len = childregs->wmask & ~0xf; childregs->areg[1] = usp; memcpy(&childregs->areg[XCHAL_NUM_AREGS - len/4], ®s->areg[XCHAL_NUM_AREGS - len/4], len); - +// FIXME: we need to set THREADPTR in thread_info... if (clone_flags & CLONE_SETTLS) childregs->areg[2] = childregs->areg[6]; @@ -142,6 +214,12 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, /* In kernel space, we start a new thread with a new stack. */ childregs->wmask = 1; } + +#if (XTENSA_HAVE_COPROCESSORS || XTENSA_HAVE_IO_PORTS) + ti = task_thread_info(p); + ti->cpenable = 0; +#endif + return 0; } @@ -179,10 +257,6 @@ unsigned long get_wchan(struct task_struct *p) } /* - * do_copy_regs() gathers information from 'struct pt_regs' and - * 'current->thread.areg[]' to fill in the xtensa_gregset_t - * structure. - * * xtensa_gregset_t and 'struct pt_regs' are vastly different formats * of processor registers. Besides different ordering, * xtensa_gregset_t contains non-live register information that @@ -191,18 +265,19 @@ unsigned long get_wchan(struct task_struct *p) * */ -void do_copy_regs (xtensa_gregset_t *elfregs, struct pt_regs *regs, - struct task_struct *tsk) +void xtensa_elf_core_copy_regs (xtensa_gregset_t *elfregs, struct pt_regs *regs) { - int i, n, wb_offset; + unsigned long wb, ws, wm; + int live, last; - elfregs->xchal_config_id0 = XCHAL_HW_CONFIGID0; - elfregs->xchal_config_id1 = XCHAL_HW_CONFIGID1; + wb = regs->windowbase; + ws = regs->windowstart; + wm = regs->wmask; + ws = ((ws >> wb) | (ws << (WSBITS - wb))) & ((1 << WSBITS) - 1); - __asm__ __volatile__ ("rsr %0, 176\n" : "=a" (i)); - elfregs->cpux = i; - __asm__ __volatile__ ("rsr %0, 208\n" : "=a" (i)); - elfregs->cpuy = i; + /* Don't leak any random bits. */ + + memset(elfregs, 0, sizeof (elfregs)); /* Note: PS.EXCM is not set while user task is running; its * being set in regs->ps is for exception handling convenience. @@ -210,204 +285,22 @@ void do_copy_regs (xtensa_gregset_t *elfregs, struct pt_regs *regs, elfregs->pc = regs->pc; elfregs->ps = (regs->ps & ~(1 << PS_EXCM_BIT)); - elfregs->exccause = regs->exccause; - elfregs->excvaddr = regs->excvaddr; - elfregs->windowbase = regs->windowbase; - elfregs->windowstart = regs->windowstart; elfregs->lbeg = regs->lbeg; elfregs->lend = regs->lend; elfregs->lcount = regs->lcount; elfregs->sar = regs->sar; - elfregs->syscall = regs->syscall; + elfregs->windowstart = ws; - /* Copy register file. - * The layout looks like this: - * - * | a0 ... a15 | Z ... Z | arX ... arY | - * current window unused saved frames - */ - - memset (elfregs->ar, 0, sizeof(elfregs->ar)); - - wb_offset = regs->windowbase * 4; - n = (regs->wmask&1)? 4 : (regs->wmask&2)? 8 : (regs->wmask&4)? 12 : 16; - - for (i = 0; i < n; i++) - elfregs->ar[(wb_offset + i) % XCHAL_NUM_AREGS] = regs->areg[i]; - - n = (regs->wmask >> 4) * 4; - - for (i = XCHAL_NUM_AREGS - n; n > 0; i++, n--) - elfregs->ar[(wb_offset + i) % XCHAL_NUM_AREGS] = regs->areg[i]; + live = (wm & 2) ? 4 : (wm & 4) ? 8 : (wm & 8) ? 12 : 16; + last = XCHAL_NUM_AREGS - (wm >> 4) * 4; + memcpy(elfregs->a, regs->areg, live * 4); + memcpy(elfregs->a + last, regs->areg + last, (wm >> 4) * 16); } -void xtensa_elf_core_copy_regs (xtensa_gregset_t *elfregs, struct pt_regs *regs) +int dump_fpu(void) { - do_copy_regs ((xtensa_gregset_t *)elfregs, regs, current); -} - - -/* The inverse of do_copy_regs(). No error or sanity checking. */ - -void do_restore_regs (xtensa_gregset_t *elfregs, struct pt_regs *regs, - struct task_struct *tsk) -{ - int i, n, wb_offset; - - /* Note: PS.EXCM is not set while user task is running; it - * needs to be set in regs->ps is for exception handling convenience. - */ - - regs->pc = elfregs->pc; - regs->ps = (elfregs->ps | (1 << PS_EXCM_BIT)); - regs->exccause = elfregs->exccause; - regs->excvaddr = elfregs->excvaddr; - regs->windowbase = elfregs->windowbase; - regs->windowstart = elfregs->windowstart; - regs->lbeg = elfregs->lbeg; - regs->lend = elfregs->lend; - regs->lcount = elfregs->lcount; - regs->sar = elfregs->sar; - regs->syscall = elfregs->syscall; - - /* Clear everything. */ - - memset (regs->areg, 0, sizeof(regs->areg)); - - /* Copy regs from live window frame. */ - - wb_offset = regs->windowbase * 4; - n = (regs->wmask&1)? 4 : (regs->wmask&2)? 8 : (regs->wmask&4)? 12 : 16; - - for (i = 0; i < n; i++) - regs->areg[(wb_offset+i) % XCHAL_NUM_AREGS] = elfregs->ar[i]; - - n = (regs->wmask >> 4) * 4; - - for (i = XCHAL_NUM_AREGS - n; n > 0; i++, n--) - regs->areg[(wb_offset+i) % XCHAL_NUM_AREGS] = elfregs->ar[i]; -} - -/* - * do_save_fpregs() gathers information from 'struct pt_regs' and - * 'current->thread' to fill in the elf_fpregset_t structure. - * - * Core files and ptrace use elf_fpregset_t. - */ - -void do_save_fpregs (elf_fpregset_t *fpregs, struct pt_regs *regs, - struct task_struct *tsk) -{ -#if XCHAL_HAVE_CP - - extern unsigned char _xtensa_reginfo_tables[]; - extern unsigned _xtensa_reginfo_table_size; - int i; - unsigned long flags; - - /* Before dumping coprocessor state from memory, - * ensure any live coprocessor contents for this - * task are first saved to memory: - */ - local_irq_save(flags); - - for (i = 0; i < XCHAL_CP_MAX; i++) { - if (tsk == coprocessor_info[i].owner) { - enable_coprocessor(i); - save_coprocessor_registers( - tsk->thread.cp_save+coprocessor_info[i].offset,i); - disable_coprocessor(i); - } - } - - local_irq_restore(flags); - - /* Now dump coprocessor & extra state: */ - memcpy((unsigned char*)fpregs, - _xtensa_reginfo_tables, _xtensa_reginfo_table_size); - memcpy((unsigned char*)fpregs + _xtensa_reginfo_table_size, - tsk->thread.cp_save, XTENSA_CP_EXTRA_SIZE); -#endif -} - -/* - * The inverse of do_save_fpregs(). - * Copies coprocessor and extra state from fpregs into regs and tsk->thread. - * Returns 0 on success, non-zero if layout doesn't match. - */ - -int do_restore_fpregs (elf_fpregset_t *fpregs, struct pt_regs *regs, - struct task_struct *tsk) -{ -#if XCHAL_HAVE_CP - - extern unsigned char _xtensa_reginfo_tables[]; - extern unsigned _xtensa_reginfo_table_size; - int i; - unsigned long flags; - - /* Make sure save area layouts match. - * FIXME: in the future we could allow restoring from - * a different layout of the same registers, by comparing - * fpregs' table with _xtensa_reginfo_tables and matching - * entries and copying registers one at a time. - * Not too sure yet whether that's very useful. - */ - - if( memcmp((unsigned char*)fpregs, - _xtensa_reginfo_tables, _xtensa_reginfo_table_size) ) { - return -1; - } - - /* Before restoring coprocessor state from memory, - * ensure any live coprocessor contents for this - * task are first invalidated. - */ - - local_irq_save(flags); - - for (i = 0; i < XCHAL_CP_MAX; i++) { - if (tsk == coprocessor_info[i].owner) { - enable_coprocessor(i); - save_coprocessor_registers( - tsk->thread.cp_save+coprocessor_info[i].offset,i); - coprocessor_info[i].owner = 0; - disable_coprocessor(i); - } - } - - local_irq_restore(flags); - - /* Now restore coprocessor & extra state: */ - - memcpy(tsk->thread.cp_save, - (unsigned char*)fpregs + _xtensa_reginfo_table_size, - XTENSA_CP_EXTRA_SIZE); -#endif return 0; } -/* - * Fill in the CP structure for a core dump for a particular task. - */ - -int -dump_task_fpu(struct pt_regs *regs, struct task_struct *task, elf_fpregset_t *r) -{ - return 0; /* no coprocessors active on this processor */ -} - -/* - * Fill in the CP structure for a core dump. - * This includes any FPU coprocessor. - * Here, we dump all coprocessors, and other ("extra") custom state. - * - * This function is called by elf_core_dump() in fs/binfmt_elf.c - * (in which case 'regs' comes from calls to do_coredump, see signals.c). - */ -int dump_fpu(struct pt_regs *regs, elf_fpregset_t *r) -{ - return dump_task_fpu(regs, current, r); -} asmlinkage long xtensa_clone(unsigned long clone_flags, unsigned long newsp, @@ -421,8 +314,8 @@ long xtensa_clone(unsigned long clone_flags, unsigned long newsp, } /* - * * xtensa_execve() executes a new program. - * */ + * xtensa_execve() executes a new program. + */ asmlinkage long xtensa_execve(char __user *name, char __user * __user *argv, @@ -437,7 +330,6 @@ long xtensa_execve(char __user *name, char __user * __user *argv, error = PTR_ERR(filename); if (IS_ERR(filename)) goto out; - // FIXME: release coprocessor?? error = do_execve(filename, argv, envp, regs); if (error == 0) { task_lock(current); diff --git a/arch/xtensa/kernel/ptrace.c b/arch/xtensa/kernel/ptrace.c index 5533c7850d53..9486882ef0af 100644 --- a/arch/xtensa/kernel/ptrace.c +++ b/arch/xtensa/kernel/ptrace.c @@ -4,7 +4,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2001 - 2005 Tensilica Inc. + * Copyright (C) 2001 - 2007 Tensilica Inc. * * Joe Taylor * Chris Zankel @@ -28,14 +28,10 @@ #include #include #include - -#define TEST_KERNEL // verify kernel operations FIXME: remove - +#include /* - * Called by kernel/ptrace.c when detaching.. - * - * Make sure single step bits etc are not set. + * Called by kernel/ptrace.c when detaching to disable single stepping. */ void ptrace_disable(struct task_struct *child) @@ -43,136 +39,237 @@ void ptrace_disable(struct task_struct *child) /* Nothing to do.. */ } -long arch_ptrace(struct task_struct *child, long request, long addr, long data) +int ptrace_getregs(struct task_struct *child, void __user *uregs) { - int ret = -EPERM; + struct pt_regs *regs = task_pt_regs(child); + xtensa_gregset_t __user *gregset = uregs; + unsigned long wm = regs->wmask; + unsigned long wb = regs->windowbase; + int live, i; - switch (request) { - case PTRACE_PEEKTEXT: /* read word at location addr. */ - case PTRACE_PEEKDATA: - ret = generic_ptrace_peekdata(child, addr, data); - goto out; + if (!access_ok(VERIFY_WRITE, uregs, sizeof(xtensa_gregset_t))) + return -EIO; - /* Read the word at location addr in the USER area. */ + __put_user(regs->pc, &gregset->pc); + __put_user(regs->ps & ~(1 << PS_EXCM_BIT), &gregset->ps); + __put_user(regs->lbeg, &gregset->lbeg); + __put_user(regs->lend, &gregset->lend); + __put_user(regs->lcount, &gregset->lcount); + __put_user(regs->windowstart, &gregset->windowstart); + __put_user(regs->windowbase, &gregset->windowbase); - case PTRACE_PEEKUSR: - { - struct pt_regs *regs; - unsigned long tmp; + live = (wm & 2) ? 4 : (wm & 4) ? 8 : (wm & 8) ? 12 : 16; - regs = task_pt_regs(child); - tmp = 0; /* Default return value. */ + for (i = 0; i < live; i++) + __put_user(regs->areg[i],gregset->a+((wb*4+i)%XCHAL_NUM_AREGS)); + for (i = XCHAL_NUM_AREGS - (wm >> 4) * 4; i < XCHAL_NUM_AREGS; i++) + __put_user(regs->areg[i],gregset->a+((wb*4+i)%XCHAL_NUM_AREGS)); - switch(addr) { + return 0; +} + +int ptrace_setregs(struct task_struct *child, void __user *uregs) +{ + struct pt_regs *regs = task_pt_regs(child); + xtensa_gregset_t *gregset = uregs; + const unsigned long ps_mask = PS_CALLINC_MASK | PS_OWB_MASK; + unsigned long ps; + unsigned long wb; + + if (!access_ok(VERIFY_WRITE, uregs, sizeof(xtensa_gregset_t))) + return -EIO; + + __get_user(regs->pc, &gregset->pc); + __get_user(ps, &gregset->ps); + __get_user(regs->lbeg, &gregset->lbeg); + __get_user(regs->lend, &gregset->lend); + __get_user(regs->lcount, &gregset->lcount); + __get_user(regs->windowstart, &gregset->windowstart); + __get_user(wb, &gregset->windowbase); + + regs->ps = (regs->ps & ~ps_mask) | (ps & ps_mask) | (1 << PS_EXCM_BIT); + + if (wb >= XCHAL_NUM_AREGS / 4) + return -EFAULT; + + regs->windowbase = wb; + + if (wb != 0 && __copy_from_user(regs->areg + XCHAL_NUM_AREGS - wb * 4, + gregset->a, wb * 16)) + return -EFAULT; + + if (__copy_from_user(regs->areg, gregset->a + wb*4, (WSBITS-wb) * 16)) + return -EFAULT; + + return 0; +} + + +int ptrace_getxregs(struct task_struct *child, void __user *uregs) +{ + struct pt_regs *regs = task_pt_regs(child); + struct thread_info *ti = task_thread_info(child); + elf_xtregs_t __user *xtregs = uregs; + int ret = 0; + + if (!access_ok(VERIFY_WRITE, uregs, sizeof(elf_xtregs_t))) + return -EIO; + +#if XTENSA_HAVE_COPROCESSORS + /* Flush all coprocessor registers to memory. */ + coprocessor_flush_all(ti); + ret |= __copy_to_user(&xtregs->cp0, &ti->xtregs_cp, + sizeof(xtregs_coprocessor_t)); +#endif + ret |= __copy_to_user(&xtregs->opt, ®s->xtregs_opt, + sizeof(xtregs->opt)); + ret |= __copy_to_user(&xtregs->user,&ti->xtregs_user, + sizeof(xtregs->user)); + + return ret ? -EFAULT : 0; +} + +int ptrace_setxregs(struct task_struct *child, void __user *uregs) +{ + struct thread_info *ti = task_thread_info(child); + struct pt_regs *regs = task_pt_regs(child); + elf_xtregs_t *xtregs = uregs; + int ret = 0; + +#if XTENSA_HAVE_COPROCESSORS + /* Flush all coprocessors before we overwrite them. */ + coprocessor_flush_all(ti); + coprocessor_release_all(ti); + + ret |= __copy_from_user(&ti->xtregs_cp, &xtregs->cp0, + sizeof(xtregs_coprocessor_t)); +#endif + ret |= __copy_from_user(®s->xtregs_opt, &xtregs->opt, + sizeof(xtregs->opt)); + ret |= __copy_from_user(&ti->xtregs_user, &xtregs->user, + sizeof(xtregs->user)); + + return ret ? -EFAULT : 0; +} + +int ptrace_peekusr(struct task_struct *child, long regno, long __user *ret) +{ + struct pt_regs *regs; + unsigned long tmp; + + regs = task_pt_regs(child); + tmp = 0; /* Default return value. */ + + switch(regno) { case REG_AR_BASE ... REG_AR_BASE + XCHAL_NUM_AREGS - 1: - { - int ar = addr - REG_AR_BASE - regs->windowbase * 4; - ar &= (XCHAL_NUM_AREGS - 1); - if (ar < 16 && ar + (regs->wmask >> 4) * 4 >= 0) - tmp = regs->areg[ar]; - else - ret = -EIO; + tmp = regs->areg[regno - REG_AR_BASE]; break; - } + case REG_A_BASE ... REG_A_BASE + 15: - tmp = regs->areg[addr - REG_A_BASE]; + tmp = regs->areg[regno - REG_A_BASE]; break; + case REG_PC: tmp = regs->pc; break; + case REG_PS: /* Note: PS.EXCM is not set while user task is running; * its being set in regs is for exception handling * convenience. */ tmp = (regs->ps & ~(1 << PS_EXCM_BIT)); break; + case REG_WB: - tmp = regs->windowbase; - break; + break; /* tmp = 0 */ + case REG_WS: - tmp = regs->windowstart; + { + unsigned long wb = regs->windowbase; + unsigned long ws = regs->windowstart; + tmp = ((ws>>wb) | (ws<<(WSBITS-wb))) & ((1<lbeg; break; + case REG_LEND: tmp = regs->lend; break; + case REG_LCOUNT: tmp = regs->lcount; break; + case REG_SAR: tmp = regs->sar; break; - case REG_DEPC: - tmp = regs->depc; - break; - case REG_EXCCAUSE: - tmp = regs->exccause; - break; - case REG_EXCVADDR: - tmp = regs->excvaddr; - break; + case SYSCALL_NR: tmp = regs->syscall; break; - default: - tmp = 0; - ret = -EIO; - goto out; - } - ret = put_user(tmp, (unsigned long *) data); - goto out; - } - case PTRACE_POKETEXT: /* write the word at location addr. */ + default: + return -EIO; + } + return put_user(tmp, ret); +} + +int ptrace_pokeusr(struct task_struct *child, long regno, long val) +{ + struct pt_regs *regs; + regs = task_pt_regs(child); + + switch (regno) { + case REG_AR_BASE ... REG_AR_BASE + XCHAL_NUM_AREGS - 1: + regs->areg[regno - REG_AR_BASE] = val; + break; + + case REG_A_BASE ... REG_A_BASE + 15: + regs->areg[regno - REG_A_BASE] = val; + break; + + case REG_PC: + regs->pc = val; + break; + + case SYSCALL_NR: + regs->syscall = val; + break; + + default: + return -EIO; + } + return 0; +} + +long arch_ptrace(struct task_struct *child, long request, long addr, long data) +{ + int ret = -EPERM; + + switch (request) { + case PTRACE_PEEKTEXT: /* read word at location addr. */ + case PTRACE_PEEKDATA: + ret = generic_ptrace_peekdata(child, addr, data); + break; + + case PTRACE_PEEKUSR: /* read register specified by addr. */ + ret = ptrace_peekusr(child, addr, (void __user *) data); + break; + + case PTRACE_POKETEXT: /* write the word at location addr. */ case PTRACE_POKEDATA: ret = generic_ptrace_pokedata(child, addr, data); - goto out; - - case PTRACE_POKEUSR: - { - struct pt_regs *regs; - regs = task_pt_regs(child); - - switch (addr) { - case REG_AR_BASE ... REG_AR_BASE + XCHAL_NUM_AREGS - 1: - { - int ar = addr - REG_AR_BASE - regs->windowbase * 4; - if (ar < 16 && ar + (regs->wmask >> 4) * 4 >= 0) - regs->areg[ar & (XCHAL_NUM_AREGS - 1)] = data; - else - ret = -EIO; - break; - } - case REG_A_BASE ... REG_A_BASE + 15: - regs->areg[addr - REG_A_BASE] = data; - break; - case REG_PC: - regs->pc = data; - break; - case SYSCALL_NR: - regs->syscall = data; - break; -#ifdef TEST_KERNEL - case REG_WB: - regs->windowbase = data; - break; - case REG_WS: - regs->windowstart = data; - break; -#endif - - default: - /* The rest are not allowed. */ - ret = -EIO; - break; - } break; - } + + case PTRACE_POKEUSR: /* write register specified by addr. */ + ret = ptrace_pokeusr(child, addr, data); + break; /* continue and stop at next (return from) syscall */ + case PTRACE_SYSCALL: case PTRACE_CONT: /* restart after signal. */ { @@ -217,98 +314,26 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) break; case PTRACE_GETREGS: - { - /* 'data' points to user memory in which to write. - * Mainly due to the non-live register values, we - * reformat the register values into something more - * standard. For convenience, we use the handy - * elf_gregset_t format. */ - - xtensa_gregset_t format; - struct pt_regs *regs = task_pt_regs(child); - - do_copy_regs (&format, regs, child); - - /* Now, copy to user space nice and easy... */ - ret = 0; - if (copy_to_user((void *)data, &format, sizeof(elf_gregset_t))) - ret = -EFAULT; + ret = ptrace_getregs(child, (void __user *) data); break; - } case PTRACE_SETREGS: - { - /* 'data' points to user memory that contains the new - * values in the elf_gregset_t format. */ - - xtensa_gregset_t format; - struct pt_regs *regs = task_pt_regs(child); - - if (copy_from_user(&format,(void *)data,sizeof(elf_gregset_t))){ - ret = -EFAULT; - break; - } - - /* FIXME: Perhaps we want some sanity checks on - * these user-space values? See ARM version. Are - * debuggers a security concern? */ - - do_restore_regs (&format, regs, child); - - ret = 0; + ret = ptrace_setregs(child, (void __user *) data); break; - } - - case PTRACE_GETFPREGS: - { - /* 'data' points to user memory in which to write. - * For convenience, we use the handy - * elf_fpregset_t format. */ - - elf_fpregset_t fpregs; - struct pt_regs *regs = task_pt_regs(child); - - do_save_fpregs (&fpregs, regs, child); - - /* Now, copy to user space nice and easy... */ - ret = 0; - if (copy_to_user((void *)data, &fpregs, sizeof(elf_fpregset_t))) - ret = -EFAULT; + case PTRACE_GETXTREGS: + ret = ptrace_getxregs(child, (void __user *) data); break; - } - case PTRACE_SETFPREGS: - { - /* 'data' points to user memory that contains the new - * values in the elf_fpregset_t format. - */ - elf_fpregset_t fpregs; - struct pt_regs *regs = task_pt_regs(child); - - ret = 0; - if (copy_from_user(&fpregs, (void *)data, sizeof(elf_fpregset_t))) { - ret = -EFAULT; - break; - } - - if (do_restore_fpregs (&fpregs, regs, child)) - ret = -EIO; - break; - } - - case PTRACE_GETFPREGSIZE: - /* 'data' points to 'unsigned long' set to the size - * of elf_fpregset_t - */ - ret = put_user(sizeof(elf_fpregset_t), (unsigned long *) data); + case PTRACE_SETXTREGS: + ret = ptrace_setxregs(child, (void __user *) data); break; default: ret = ptrace_request(child, request, addr, data); - goto out; + break; } - out: + return ret; } diff --git a/arch/xtensa/kernel/setup.c b/arch/xtensa/kernel/setup.c index b80f2cb1b4fb..5e6d75c9f92b 100644 --- a/arch/xtensa/kernel/setup.c +++ b/arch/xtensa/kernel/setup.c @@ -60,11 +60,6 @@ struct ide_ops *ide_ops; extern struct rtc_ops no_rtc_ops; struct rtc_ops *rtc_ops; -#ifdef CONFIG_PC_KEYB -extern struct kbd_ops no_kbd_ops; -struct kbd_ops *kbd_ops; -#endif - #ifdef CONFIG_BLK_DEV_INITRD extern void *initrd_start; extern void *initrd_end; diff --git a/arch/xtensa/kernel/signal.c b/arch/xtensa/kernel/signal.c index 033aae0336d2..f2220b5bdce6 100644 --- a/arch/xtensa/kernel/signal.c +++ b/arch/xtensa/kernel/signal.c @@ -35,13 +35,17 @@ asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset); extern struct task_struct *coproc_owners[]; -extern void release_all_cp (struct task_struct *); - struct rt_sigframe { struct siginfo info; struct ucontext uc; - cp_state_t cpstate; + struct { + xtregs_opt_t opt; + xtregs_user_t user; +#if XTENSA_HAVE_COPROCESSORS + xtregs_coprocessor_t cp; +#endif + } xtregs; unsigned char retcode[6]; unsigned int window[4]; }; @@ -49,8 +53,6 @@ struct rt_sigframe /* * Flush register windows stored in pt_regs to stack. * Returns 1 for errors. - * - * Note that windowbase, windowstart, and wmask are not updated! */ int @@ -116,6 +118,9 @@ flush_window_regs_user(struct pt_regs *regs) base += inc; } + regs->wmask = 1; + regs->windowstart = 1 << wb; + return 0; errout: @@ -131,9 +136,10 @@ errout: */ static int -setup_sigcontext(struct sigcontext __user *sc, cp_state_t *cpstate, - struct pt_regs *regs, unsigned long mask) +setup_sigcontext(struct rt_sigframe __user *frame, struct pt_regs *regs) { + struct sigcontext __user *sc = &frame->uc.uc_mcontext; + struct thread_info *ti = current_thread_info(); int err = 0; #define COPY(x) err |= __put_user(regs->x, &sc->sc_##x) @@ -147,23 +153,32 @@ setup_sigcontext(struct sigcontext __user *sc, cp_state_t *cpstate, err |= flush_window_regs_user(regs); err |= __copy_to_user (sc->sc_a, regs->areg, 16 * 4); + err |= __put_user(0, &sc->sc_xtregs); - // err |= __copy_to_user (sc->sc_a, regs->areg, XCHAL_NUM_AREGS * 4) + if (err) + return err; -#if XCHAL_HAVE_CP -# error Coprocessors unsupported - err |= save_cpextra(cpstate); - err |= __put_user(err ? NULL : cpstate, &sc->sc_cpstate); +#if XTENSA_HAVE_COPROCESSORS + coprocessor_flush_all(ti); + coprocessor_release_all(ti); + err |= __copy_to_user(&frame->xtregs.cp, &ti->xtregs_cp, + sizeof (frame->xtregs.cp)); #endif - /* non-iBCS2 extensions.. */ - err |= __put_user(mask, &sc->oldmask); + err |= __copy_to_user(&frame->xtregs.opt, ®s->xtregs_opt, + sizeof (xtregs_opt_t)); + err |= __copy_to_user(&frame->xtregs.user, &ti->xtregs_user, + sizeof (xtregs_user_t)); + + err |= __put_user(err ? NULL : &frame->xtregs, &sc->sc_xtregs); return err; } static int -restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc) +restore_sigcontext(struct pt_regs *regs, struct rt_sigframe __user *frame) { + struct sigcontext __user *sc = &frame->uc.uc_mcontext; + struct thread_info *ti = current_thread_info(); unsigned int err = 0; unsigned long ps; @@ -181,6 +196,8 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc) regs->windowbase = 0; regs->windowstart = 1; + regs->syscall = -1; /* disable syscall checks */ + /* For PS, restore only PS.CALLINC. * Assume that all other bits are either the same as for the signal * handler, or the user mode value doesn't matter (e.g. PS.OWB). @@ -196,8 +213,9 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc) err |= __copy_from_user(regs->areg, sc->sc_a, 16 * 4); -#if XCHAL_HAVE_CP -# error Coprocessors unsupported + if (err) + return err; + /* The signal handler may have used coprocessors in which * case they are still enabled. We disable them to force a * reloading of the original task's CP state by the lazy @@ -205,20 +223,20 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc) * Also, we essentially discard any coprocessor state that the * signal handler created. */ - if (!err) { - struct task_struct *tsk = current; - release_all_cp(tsk); - err |= __copy_from_user(tsk->thread.cpextra, sc->sc_cpstate, - XTENSA_CP_EXTRA_SIZE); - } +#if XTENSA_HAVE_COPROCESSORS + coprocessor_release_all(ti); + err |= __copy_from_user(&ti->xtregs_cp, &frame->xtregs.cp, + sizeof (frame->xtregs.cp)); #endif + err |= __copy_from_user(&ti->xtregs_user, &frame->xtregs.user, + sizeof (xtregs_user_t)); + err |= __copy_from_user(®s->xtregs_opt, &frame->xtregs.opt, + sizeof (xtregs_opt_t)); - regs->syscall = -1; /* disable syscall checks */ return err; } - /* * Do a signal return; undo the signal stack. */ @@ -247,7 +265,7 @@ asmlinkage long xtensa_rt_sigreturn(long a0, long a1, long a2, long a3, recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); - if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) + if (restore_sigcontext(regs, frame)) goto badframe; ret = regs->areg[2]; @@ -360,18 +378,22 @@ static void setup_frame(int sig, struct k_sigaction *ka, siginfo_t *info, err |= __put_user(sas_ss_flags(regs->areg[1]), &frame->uc.uc_stack.ss_flags); err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); - err |= setup_sigcontext(&frame->uc.uc_mcontext, &frame->cpstate, - regs, set->sig[0]); + err |= setup_sigcontext(frame, regs); err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); - /* Create sys_rt_sigreturn syscall in stack frame */ + if (ka->sa.sa_flags & SA_RESTORER) { + ra = (unsigned long)ka->sa.sa_restorer; + } else { - err |= gen_return_code(frame->retcode); + /* Create sys_rt_sigreturn syscall in stack frame */ - if (err) { - goto give_sigsegv; + err |= gen_return_code(frame->retcode); + + if (err) { + goto give_sigsegv; + } + ra = (unsigned long) frame->retcode; } - /* * Create signal handler execution context. @@ -385,7 +407,6 @@ static void setup_frame(int sig, struct k_sigaction *ka, siginfo_t *info, /* Set up a stack frame for a call4 * Note: PS.CALLINC is set to one by start_thread */ - ra = (unsigned long) frame->retcode; regs->areg[4] = (((unsigned long) ra) & 0x3fffffff) | 0x40000000; regs->areg[6] = (unsigned long) signal; regs->areg[7] = (unsigned long) &frame->info; diff --git a/arch/xtensa/kernel/traps.c b/arch/xtensa/kernel/traps.c index 397bcd6ad08d..c7a021d9f696 100644 --- a/arch/xtensa/kernel/traps.c +++ b/arch/xtensa/kernel/traps.c @@ -118,28 +118,28 @@ static dispatch_init_table_t __initdata dispatch_init_table[] = { { EXCCAUSE_STORE_CACHE_ATTRIBUTE, 0, do_page_fault }, { EXCCAUSE_LOAD_CACHE_ATTRIBUTE, 0, do_page_fault }, /* XCCHAL_EXCCAUSE_FLOATING_POINT unhandled */ -#if (XCHAL_CP_MASK & 1) +#if XTENSA_HAVE_COPROCESSOR(0) COPROCESSOR(0), #endif -#if (XCHAL_CP_MASK & 2) +#if XTENSA_HAVE_COPROCESSOR(1) COPROCESSOR(1), #endif -#if (XCHAL_CP_MASK & 4) +#if XTENSA_HAVE_COPROCESSOR(2) COPROCESSOR(2), #endif -#if (XCHAL_CP_MASK & 8) +#if XTENSA_HAVE_COPROCESSOR(3) COPROCESSOR(3), #endif -#if (XCHAL_CP_MASK & 16) +#if XTENSA_HAVE_COPROCESSOR(4) COPROCESSOR(4), #endif -#if (XCHAL_CP_MASK & 32) +#if XTENSA_HAVE_COPROCESSOR(5) COPROCESSOR(5), #endif -#if (XCHAL_CP_MASK & 64) +#if XTENSA_HAVE_COPROCESSOR(6) COPROCESSOR(6), #endif -#if (XCHAL_CP_MASK & 128) +#if XTENSA_HAVE_COPROCESSOR(7) COPROCESSOR(7), #endif { EXCCAUSE_MAPPED_DEBUG, 0, do_debug }, @@ -349,9 +349,7 @@ void show_regs(struct pt_regs * regs) wmask = regs->wmask & ~1; - for (i = 0; i < 32; i++) { - if (wmask & (1 << (i / 4))) - break; + for (i = 0; i < 16; i++) { if ((i % 8) == 0) printk ("\n" KERN_INFO "a%02d: ", i); printk("%08lx ", regs->areg[i]); diff --git a/arch/xtensa/kernel/vmlinux.lds.S b/arch/xtensa/kernel/vmlinux.lds.S index 7d0f55a4982d..51f4fb6f16f9 100644 --- a/arch/xtensa/kernel/vmlinux.lds.S +++ b/arch/xtensa/kernel/vmlinux.lds.S @@ -136,7 +136,9 @@ SECTIONS __init_begin = .; .init.text : { _sinittext = .; - *(.init.literal) INIT_TEXT + *(.init.literal) *(.cpuinit.literal) + *(.devinit.literal) *(.meminit.literal) + INIT_TEXT _einittext = .; } @@ -161,6 +163,8 @@ SECTIONS .DoubleExceptionVector.literal); RELOCATE_ENTRY(_DoubleExceptionVector_text, .DoubleExceptionVector.text); + RELOCATE_ENTRY(_DebugInterruptVector_text, + .DebugInterruptVector.text); __boot_reloc_table_end = ABSOLUTE(.) ; } diff --git a/arch/xtensa/mm/cache.c b/arch/xtensa/mm/cache.c index 9a1fa9478ae7..3ba990c67676 100644 --- a/arch/xtensa/mm/cache.c +++ b/arch/xtensa/mm/cache.c @@ -25,7 +25,6 @@ #include #include -#include #include #include #include @@ -181,9 +180,9 @@ update_mmu_cache(struct vm_area_struct * vma, unsigned long addr, pte_t pte) #else if (!PageReserved(page) && !test_bit(PG_arch_1, &page->flags) && (vma->vm_flags & VM_EXEC) != 0) { - unsigned long vaddr = addr & PAGE_MASK; - __flush_dcache_page(vaddr); - __invalidate_icache_page(vaddr); + unsigned long paddr = (unsigned long) page_address(page); + __flush_dcache_page(paddr); + __invalidate_icache_page(paddr); set_bit(PG_arch_1, &page->flags); } #endif diff --git a/arch/xtensa/mm/init.c b/arch/xtensa/mm/init.c index b3086f34a8e7..81d0560eaea2 100644 --- a/arch/xtensa/mm/init.c +++ b/arch/xtensa/mm/init.c @@ -309,7 +309,7 @@ void show_mem(void) struct kmem_cache *pgtable_cache __read_mostly; -static void pgd_ctor(void *addr, struct kmem_cache *cache, unsigned long flags) +static void pgd_ctor(struct kmem_cache *cache, void* addr) { pte_t* ptep = (pte_t*)addr; int i; diff --git a/arch/xtensa/mm/misc.S b/arch/xtensa/mm/misc.S index e1f880368e32..c885664211d1 100644 --- a/arch/xtensa/mm/misc.S +++ b/arch/xtensa/mm/misc.S @@ -295,7 +295,7 @@ ENTRY(__tlbtemp_mapping_itlb) ENTRY(__invalidate_icache_page_alias) entry sp, 16 - addi a6, a3, (PAGE_KERNEL | _PAGE_HW_WRITE) + addi a6, a3, (PAGE_KERNEL_EXEC | _PAGE_HW_WRITE) mov a4, a2 witlb a6, a2 isync diff --git a/arch/xtensa/platform-iss/Makefile b/arch/xtensa/platforms/iss/Makefile similarity index 100% rename from arch/xtensa/platform-iss/Makefile rename to arch/xtensa/platforms/iss/Makefile diff --git a/arch/xtensa/platform-iss/console.c b/arch/xtensa/platforms/iss/console.c similarity index 98% rename from arch/xtensa/platform-iss/console.c rename to arch/xtensa/platforms/iss/console.c index 854677d0c3f6..9141e3690731 100644 --- a/arch/xtensa/platform-iss/console.c +++ b/arch/xtensa/platforms/iss/console.c @@ -43,6 +43,7 @@ static DEFINE_SPINLOCK(timer_lock); int errno; +static int __simc (int a, int b, int c, int d, int e, int f) __attribute__((__noinline__)); static int __simc (int a, int b, int c, int d, int e, int f) { int ret; diff --git a/arch/xtensa/platform-iss/io.c b/arch/xtensa/platforms/iss/io.c similarity index 100% rename from arch/xtensa/platform-iss/io.c rename to arch/xtensa/platforms/iss/io.c diff --git a/arch/xtensa/platform-iss/network.c b/arch/xtensa/platforms/iss/network.c similarity index 99% rename from arch/xtensa/platform-iss/network.c rename to arch/xtensa/platforms/iss/network.c index f21b9b0899a8..a2e252217428 100644 --- a/arch/xtensa/platform-iss/network.c +++ b/arch/xtensa/platforms/iss/network.c @@ -31,7 +31,6 @@ #include #include #include -#include #include #include @@ -108,6 +107,7 @@ struct iss_net_private { static int errno; +static int __simc (int a, int b, int c, int d, int e, int f) __attribute__((__noinline__)); static int __simc (int a, int b, int c, int d, int e, int f) { int ret; diff --git a/arch/xtensa/platform-iss/setup.c b/arch/xtensa/platforms/iss/setup.c similarity index 100% rename from arch/xtensa/platform-iss/setup.c rename to arch/xtensa/platforms/iss/setup.c diff --git a/block/blk-core.c b/block/blk-core.c index e9754dc98ec4..775c8516abf5 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -38,7 +38,7 @@ static int __make_request(struct request_queue *q, struct bio *bio); /* * For the allocated request tables */ -struct kmem_cache *request_cachep; +static struct kmem_cache *request_cachep; /* * For queue allocation @@ -127,6 +127,7 @@ void rq_init(struct request_queue *q, struct request *rq) rq->nr_hw_segments = 0; rq->ioprio = 0; rq->special = NULL; + rq->raw_data_len = 0; rq->buffer = NULL; rq->tag = -1; rq->errors = 0; @@ -2015,6 +2016,7 @@ void blk_rq_bio_prep(struct request_queue *q, struct request *rq, rq->hard_cur_sectors = rq->current_nr_sectors; rq->hard_nr_sectors = rq->nr_sectors = bio_sectors(bio); rq->buffer = bio_data(bio); + rq->raw_data_len = bio->bi_size; rq->data_len = bio->bi_size; rq->bio = rq->biotail = bio; diff --git a/block/blk-ioc.c b/block/blk-ioc.c index 80245dc30c75..e34df7c9fc36 100644 --- a/block/blk-ioc.c +++ b/block/blk-ioc.c @@ -17,17 +17,13 @@ static struct kmem_cache *iocontext_cachep; static void cfq_dtor(struct io_context *ioc) { - struct cfq_io_context *cic[1]; - int r; + if (!hlist_empty(&ioc->cic_list)) { + struct cfq_io_context *cic; - /* - * We don't have a specific key to lookup with, so use the gang - * lookup to just retrieve the first item stored. The cfq exit - * function will iterate the full tree, so any member will do. - */ - r = radix_tree_gang_lookup(&ioc->radix_root, (void **) cic, 0, 1); - if (r > 0) - cic[0]->dtor(ioc); + cic = list_entry(ioc->cic_list.first, struct cfq_io_context, + cic_list); + cic->dtor(ioc); + } } /* @@ -57,18 +53,16 @@ EXPORT_SYMBOL(put_io_context); static void cfq_exit(struct io_context *ioc) { - struct cfq_io_context *cic[1]; - int r; - rcu_read_lock(); - /* - * See comment for cfq_dtor() - */ - r = radix_tree_gang_lookup(&ioc->radix_root, (void **) cic, 0, 1); - rcu_read_unlock(); - if (r > 0) - cic[0]->exit(ioc); + if (!hlist_empty(&ioc->cic_list)) { + struct cfq_io_context *cic; + + cic = list_entry(ioc->cic_list.first, struct cfq_io_context, + cic_list); + cic->exit(ioc); + } + rcu_read_unlock(); } /* Called by the exitting task */ @@ -105,6 +99,7 @@ struct io_context *alloc_io_context(gfp_t gfp_flags, int node) ret->nr_batch_requests = 0; /* because this is 0 */ ret->aic = NULL; INIT_RADIX_TREE(&ret->radix_root, GFP_ATOMIC | __GFP_HIGH); + INIT_HLIST_HEAD(&ret->cic_list); ret->ioc_data = NULL; } @@ -176,7 +171,7 @@ void copy_io_context(struct io_context **pdst, struct io_context **psrc) } EXPORT_SYMBOL(copy_io_context); -int __init blk_ioc_init(void) +static int __init blk_ioc_init(void) { iocontext_cachep = kmem_cache_create("blkdev_ioc", sizeof(struct io_context), 0, SLAB_PANIC, NULL); diff --git a/block/blk-map.c b/block/blk-map.c index 955d75c1a58f..09f7fd0bcb73 100644 --- a/block/blk-map.c +++ b/block/blk-map.c @@ -19,6 +19,7 @@ int blk_rq_append_bio(struct request_queue *q, struct request *rq, rq->biotail->bi_next = bio; rq->biotail = bio; + rq->raw_data_len += bio->bi_size; rq->data_len += bio->bi_size; } return 0; @@ -139,10 +140,29 @@ int blk_rq_map_user(struct request_queue *q, struct request *rq, ubuf += ret; } + /* + * __blk_rq_map_user() copies the buffers if starting address + * or length isn't aligned. As the copied buffer is always + * page aligned, we know that there's enough room for padding. + * Extend the last bio and update rq->data_len accordingly. + * + * On unmap, bio_uncopy_user() will use unmodified + * bio_map_data pointed to by bio->bi_private. + */ + if (len & queue_dma_alignment(q)) { + unsigned int pad_len = (queue_dma_alignment(q) & ~len) + 1; + struct bio *bio = rq->biotail; + + bio->bi_io_vec[bio->bi_vcnt - 1].bv_len += pad_len; + bio->bi_size += pad_len; + rq->data_len += pad_len; + } + rq->buffer = rq->data = NULL; return 0; unmap_rq: blk_rq_unmap_user(bio); + rq->bio = NULL; return ret; } EXPORT_SYMBOL(blk_rq_map_user); diff --git a/block/blk-merge.c b/block/blk-merge.c index d3b84bbb776a..7506c4fe0264 100644 --- a/block/blk-merge.c +++ b/block/blk-merge.c @@ -220,7 +220,10 @@ new_segment: bvprv = bvec; } /* segments in rq */ - if (q->dma_drain_size) { + if (q->dma_drain_size && q->dma_drain_needed(rq)) { + if (rq->cmd_flags & REQ_RW) + memset(q->dma_drain_buffer, 0, q->dma_drain_size); + sg->page_link &= ~0x02; sg = sg_next(sg); sg_set_page(sg, virt_to_page(q->dma_drain_buffer), @@ -228,6 +231,7 @@ new_segment: ((unsigned long)q->dma_drain_buffer) & (PAGE_SIZE - 1)); nsegs++; + rq->data_len += q->dma_drain_size; } if (sg) diff --git a/block/blk-settings.c b/block/blk-settings.c index c8d0c5724098..9a8ffdd0ce3d 100644 --- a/block/blk-settings.c +++ b/block/blk-settings.c @@ -296,6 +296,7 @@ EXPORT_SYMBOL(blk_queue_stack_limits); * blk_queue_dma_drain - Set up a drain buffer for excess dma. * * @q: the request queue for the device + * @dma_drain_needed: fn which returns non-zero if drain is necessary * @buf: physically contiguous buffer * @size: size of the buffer in bytes * @@ -315,14 +316,16 @@ EXPORT_SYMBOL(blk_queue_stack_limits); * device can support otherwise there won't be room for the drain * buffer. */ -int blk_queue_dma_drain(struct request_queue *q, void *buf, - unsigned int size) +extern int blk_queue_dma_drain(struct request_queue *q, + dma_drain_needed_fn *dma_drain_needed, + void *buf, unsigned int size) { if (q->max_hw_segments < 2 || q->max_phys_segments < 2) return -EINVAL; /* make room for appending the drain */ --q->max_hw_segments; --q->max_phys_segments; + q->dma_drain_needed = dma_drain_needed; q->dma_drain_buffer = buf; q->dma_drain_size = size; @@ -386,7 +389,7 @@ void blk_queue_update_dma_alignment(struct request_queue *q, int mask) } EXPORT_SYMBOL(blk_queue_update_dma_alignment); -int __init blk_settings_init(void) +static int __init blk_settings_init(void) { blk_max_low_pfn = max_low_pfn - 1; blk_max_pfn = max_pfn - 1; diff --git a/block/bsg.c b/block/bsg.c index 8917c5174dc2..7f3c09549e4b 100644 --- a/block/bsg.c +++ b/block/bsg.c @@ -437,14 +437,14 @@ static int blk_complete_sgv4_hdr_rq(struct request *rq, struct sg_io_v4 *hdr, } if (rq->next_rq) { - hdr->dout_resid = rq->data_len; - hdr->din_resid = rq->next_rq->data_len; + hdr->dout_resid = rq->raw_data_len; + hdr->din_resid = rq->next_rq->raw_data_len; blk_rq_unmap_user(bidi_bio); blk_put_request(rq->next_rq); } else if (rq_data_dir(rq) == READ) - hdr->din_resid = rq->data_len; + hdr->din_resid = rq->raw_data_len; else - hdr->dout_resid = rq->data_len; + hdr->dout_resid = rq->raw_data_len; /* * If the request generated a negative error number, return it diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index ca198e61fa65..0f962ecae91f 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -1145,38 +1145,19 @@ static void cfq_put_queue(struct cfq_queue *cfqq) /* * Call func for each cic attached to this ioc. Returns number of cic's seen. */ -#define CIC_GANG_NR 16 static unsigned int call_for_each_cic(struct io_context *ioc, void (*func)(struct io_context *, struct cfq_io_context *)) { - struct cfq_io_context *cics[CIC_GANG_NR]; - unsigned long index = 0; - unsigned int called = 0; - int nr; + struct cfq_io_context *cic; + struct hlist_node *n; + int called = 0; rcu_read_lock(); - - do { - int i; - - /* - * Perhaps there's a better way - this just gang lookups from - * 0 to the end, restarting after each CIC_GANG_NR from the - * last key + 1. - */ - nr = radix_tree_gang_lookup(&ioc->radix_root, (void **) cics, - index, CIC_GANG_NR); - if (!nr) - break; - - called += nr; - index = 1 + (unsigned long) cics[nr - 1]->key; - - for (i = 0; i < nr; i++) - func(ioc, cics[i]); - } while (nr == CIC_GANG_NR); - + hlist_for_each_entry_rcu(cic, n, &ioc->cic_list, cic_list) { + func(ioc, cic); + called++; + } rcu_read_unlock(); return called; @@ -1190,6 +1171,7 @@ static void cic_free_func(struct io_context *ioc, struct cfq_io_context *cic) spin_lock_irqsave(&ioc->lock, flags); radix_tree_delete(&ioc->radix_root, cic->dead_key); + hlist_del_rcu(&cic->cic_list); spin_unlock_irqrestore(&ioc->lock, flags); kmem_cache_free(cfq_ioc_pool, cic); @@ -1280,6 +1262,7 @@ cfq_alloc_io_context(struct cfq_data *cfqd, gfp_t gfp_mask) if (cic) { cic->last_end_request = jiffies; INIT_LIST_HEAD(&cic->queue_list); + INIT_HLIST_NODE(&cic->cic_list); cic->dtor = cfq_free_io_context; cic->exit = cfq_exit_io_context; elv_ioc_count_inc(ioc_count); @@ -1501,6 +1484,7 @@ cfq_drop_dead_cic(struct cfq_data *cfqd, struct io_context *ioc, rcu_assign_pointer(ioc->ioc_data, NULL); radix_tree_delete(&ioc->radix_root, (unsigned long) cfqd); + hlist_del_rcu(&cic->cic_list); spin_unlock_irqrestore(&ioc->lock, flags); cfq_cic_free(cic); @@ -1561,6 +1545,8 @@ static int cfq_cic_link(struct cfq_data *cfqd, struct io_context *ioc, spin_lock_irqsave(&ioc->lock, flags); ret = radix_tree_insert(&ioc->radix_root, (unsigned long) cfqd, cic); + if (!ret) + hlist_add_head_rcu(&cic->cic_list, &ioc->cic_list); spin_unlock_irqrestore(&ioc->lock, flags); radix_tree_preload_end(); diff --git a/block/elevator.c b/block/elevator.c index bafbae0344d3..88318c383608 100644 --- a/block/elevator.c +++ b/block/elevator.c @@ -134,6 +134,21 @@ static struct elevator_type *elevator_get(const char *name) spin_lock(&elv_list_lock); e = elevator_find(name); + if (!e) { + char elv[ELV_NAME_MAX + strlen("-iosched")]; + + spin_unlock(&elv_list_lock); + + if (!strcmp(name, "anticipatory")) + sprintf(elv, "as-iosched"); + else + sprintf(elv, "%s-iosched", name); + + request_module(elv); + spin_lock(&elv_list_lock); + e = elevator_find(name); + } + if (e && !try_module_get(e->elevator_owner)) e = NULL; diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c index 9675b34638d4..e993cac4911d 100644 --- a/block/scsi_ioctl.c +++ b/block/scsi_ioctl.c @@ -266,7 +266,7 @@ static int blk_complete_sghdr_rq(struct request *rq, struct sg_io_hdr *hdr, hdr->info = 0; if (hdr->masked_status || hdr->host_status || hdr->driver_status) hdr->info |= SG_INFO_CHECK; - hdr->resid = rq->data_len; + hdr->resid = rq->raw_data_len; hdr->sb_len_wr = 0; if (rq->sense_len && hdr->sbp) { @@ -528,6 +528,7 @@ static int __blk_send_generic(struct request_queue *q, struct gendisk *bd_disk, rq = blk_get_request(q, WRITE, __GFP_WAIT); rq->cmd_type = REQ_TYPE_BLOCK_PC; rq->data = NULL; + rq->raw_data_len = 0; rq->data_len = 0; rq->timeout = BLK_DEFAULT_SG_TIMEOUT; memset(rq->cmd, 0, sizeof(rq->cmd)); diff --git a/crypto/Kconfig b/crypto/Kconfig index c3166a1a5bb6..898acc5c1967 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -74,6 +74,7 @@ config CRYPTO_XCBC config CRYPTO_NULL tristate "Null algorithms" select CRYPTO_ALGAPI + select CRYPTO_BLKCIPHER help These are 'Null' algorithms, used by IPsec, which do nothing. @@ -567,6 +568,7 @@ config CRYPTO_TEST depends on m select CRYPTO_ALGAPI select CRYPTO_AEAD + select CRYPTO_BLKCIPHER help Quick & dirty crypto test module. diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c index 9ce983ed60f0..ea92bac42c53 100644 --- a/drivers/acpi/blacklist.c +++ b/drivers/acpi/blacklist.c @@ -186,6 +186,12 @@ static int __init dmi_unknown_osi_linux(const struct dmi_system_id *d) acpi_dmi_osi_linux(-1, d); /* unknown */ return 0; } +static int __init dmi_disable_osi_vista(const struct dmi_system_id *d) +{ + printk(KERN_NOTICE PREFIX "DMI detected: %s\n", d->ident); + acpi_osi_setup("!Windows 2006"); + return 0; +} /* * Most BIOS that invoke OSI(Linux) do nothing with it. @@ -228,10 +234,10 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { * DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 5520"), * DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 6460"), * DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 7510"), - * DMI_MATCH(DMI_PRODUCT_NAME, "Extensa 5220"), * * _OSI(Linux) is a NOP: * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5315"), + * DMI_MATCH(DMI_PRODUCT_NAME, "Extensa 5220"), */ { .callback = dmi_disable_osi_linux, @@ -327,12 +333,20 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { }, { /* OSI(Linux) effect unknown */ .callback = dmi_unknown_osi_linux, - .ident = "Dell OP GX620", + .ident = "Dell OptiPlex GX620", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex GX620"), }, }, + { /* OSI(Linux) causes some USB initialization to not run */ + .callback = dmi_unknown_osi_linux, + .ident = "Dell OptiPlex 755", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 755"), + }, + }, { /* OSI(Linux) effect unknown */ .callback = dmi_unknown_osi_linux, .ident = "Dell PE 1900", @@ -342,6 +356,14 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { }, }, { /* OSI(Linux) is a NOP */ + .callback = dmi_unknown_osi_linux, + .ident = "Dell PE 1950", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 1950"), + }, + }, + { /* OSI(Linux) is a NOP */ .callback = dmi_disable_osi_linux, .ident = "Dell PE R200", .matches = { @@ -357,6 +379,22 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { DMI_MATCH(DMI_PRODUCT_NAME, "Precision WorkStation 390"), }, }, + { /* OSI(Linux) touches USB */ + .callback = dmi_unknown_osi_linux, + .ident = "Dell PR 390", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Precision WorkStation 690"), + }, + }, + { /* OSI(Linux) unknown - ASL looks benign, but may effect dock/SMM */ + .callback = dmi_unknown_osi_linux, + .ident = "Dell PR M4300", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Precision M4300"), + }, + }, { /* OSI(Linux) is a NOP */ .callback = dmi_disable_osi_linux, .ident = "Dell Vostro 1000", @@ -390,10 +428,10 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { * DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pi 1536"), * DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pi 1556"), * DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xi 1546"), + * DMI_MATCH(DMI_PRODUCT_NAME, "ESPRIMO Mobile V5505"), * _OSI(Linux) unknown effect: * DMI_MATCH(DMI_PRODUCT_NAME, "Amilo M1425"), * DMI_MATCH(DMI_PRODUCT_NAME, "Amilo Si 1520"), - * DMI_MATCH(DMI_PRODUCT_NAME, "ESPRIMO Mobile V5505"), */ { .callback = dmi_disable_osi_linux, @@ -402,6 +440,14 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), }, }, + { + .callback = dmi_disable_osi_vista, + .ident = "Fujitsu Siemens", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), + DMI_MATCH(DMI_PRODUCT_NAME, "ESPRIMO Mobile V5505"), + }, + }, /* * Disable OSI(Linux) warnings on all "Hewlett-Packard" * @@ -443,10 +489,11 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { * _OSI(Linux) helps sound * DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad R61"), * DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T61"), + * _OSI(Linux) has Linux specific hooks + * DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X61"), * _OSI(Linux) is a NOP: * DMI_MATCH(DMI_PRODUCT_VERSION, "3000 N100"), - * _OSI(Linux) effect unknown - * DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X61"), + * DMI_MATCH(DMI_PRODUCT_VERSION, "LENOVO3000 V100"), */ { .callback = dmi_enable_osi_linux, @@ -465,7 +512,7 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { }, }, { - .callback = dmi_unknown_osi_linux, + .callback = dmi_enable_osi_linux, .ident = "Lenovo ThinkPad X61", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), @@ -473,7 +520,7 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { }, }, { - .callback = dmi_unknown_osi_linux, + .callback = dmi_disable_osi_linux, .ident = "Lenovo 3000 V100", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), @@ -543,8 +590,9 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { * Disable OSI(Linux) warnings on all "Sony Corporation" * * _OSI(Linux) is a NOP: - * DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SZ650N"), + * DMI_MATCH(DMI_PRODUCT_NAME, "VGN-NR11S_S"), * DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SZ38GP_C"), + * DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SZ650N"), * DMI_MATCH(DMI_PRODUCT_NAME, "VGN-TZ21MN_N"), * _OSI(Linux) unknown effect: * DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FZ11M"), diff --git a/drivers/acpi/event.c b/drivers/acpi/event.c index 5479dc0eeeec..abec1ca94cf4 100644 --- a/drivers/acpi/event.c +++ b/drivers/acpi/event.c @@ -110,7 +110,7 @@ static const struct file_operations acpi_system_event_ops = { #endif /* CONFIG_ACPI_PROC_EVENT */ /* ACPI notifier chain */ -BLOCKING_NOTIFIER_HEAD(acpi_chain_head); +static BLOCKING_NOTIFIER_HEAD(acpi_chain_head); int acpi_notifier_call_chain(struct acpi_device *dev, u32 type, u32 data) { diff --git a/drivers/acpi/executer/exregion.c b/drivers/acpi/executer/exregion.c index 2e9ce94798c7..3f51b7e84a17 100644 --- a/drivers/acpi/executer/exregion.c +++ b/drivers/acpi/executer/exregion.c @@ -338,6 +338,7 @@ acpi_ex_pci_config_space_handler(u32 function, acpi_status status = AE_OK; struct acpi_pci_id *pci_id; u16 pci_register; + u32 value32; ACPI_FUNCTION_TRACE(ex_pci_config_space_handler); @@ -364,9 +365,9 @@ acpi_ex_pci_config_space_handler(u32 function, switch (function) { case ACPI_READ: - *value = 0; status = acpi_os_read_pci_configuration(pci_id, pci_register, - value, bit_width); + &value32, bit_width); + *value = value32; break; case ACPI_WRITE: diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c index 48cb705b274a..c8e3cba423ef 100644 --- a/drivers/acpi/fan.c +++ b/drivers/acpi/fan.c @@ -256,22 +256,28 @@ static int acpi_fan_add(struct acpi_device *device) cdev = thermal_cooling_device_register("Fan", device, &fan_cooling_ops); - if (cdev) + if (IS_ERR(cdev)) { + result = PTR_ERR(cdev); + goto end; + } + if (cdev) { printk(KERN_INFO PREFIX "%s is registered as cooling_device%d\n", device->dev.bus_id, cdev->id); - else - goto end; - acpi_driver_data(device) = cdev; - result = sysfs_create_link(&device->dev.kobj, &cdev->device.kobj, - "thermal_cooling"); - if (result) - return result; - result = sysfs_create_link(&cdev->device.kobj, &device->dev.kobj, - "device"); - if (result) - return result; + acpi_driver_data(device) = cdev; + result = sysfs_create_link(&device->dev.kobj, + &cdev->device.kobj, + "thermal_cooling"); + if (result) + return result; + + result = sysfs_create_link(&cdev->device.kobj, + &device->dev.kobj, + "device"); + if (result) + return result; + } result = acpi_fan_add_fs(device); if (result) diff --git a/drivers/acpi/hardware/hwsleep.c b/drivers/acpi/hardware/hwsleep.c index 058d0be5cbe2..4290e0193097 100644 --- a/drivers/acpi/hardware/hwsleep.c +++ b/drivers/acpi/hardware/hwsleep.c @@ -616,6 +616,7 @@ acpi_status acpi_leave_sleep_state(u8 sleep_state) return_ACPI_STATUS(status); } + arg.integer.value = sleep_state; status = acpi_evaluate_object(NULL, METHOD_NAME__WAK, &arg_list, NULL); if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { ACPI_EXCEPTION((AE_INFO, status, "During Method _WAK")); diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 15e602377655..8edba7b678eb 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -325,7 +325,7 @@ acpi_os_predefined_override(const struct acpi_predefined_names *init_val, } #ifdef CONFIG_ACPI_CUSTOM_DSDT_INITRD -struct acpi_table_header *acpi_find_dsdt_initrd(void) +static struct acpi_table_header *acpi_find_dsdt_initrd(void) { struct file *firmware_file; mm_segment_t oldfs; @@ -419,7 +419,7 @@ acpi_os_table_override(struct acpi_table_header * existing_table, } #ifdef CONFIG_ACPI_CUSTOM_DSDT_INITRD -int __init acpi_no_initrd_override_setup(char *s) +static int __init acpi_no_initrd_override_setup(char *s) { acpi_no_initrd_override = 1; return 1; @@ -1109,7 +1109,7 @@ void __init acpi_dmi_osi_linux(int enable, const struct dmi_system_id *d) * string starting with '!' disables that string * otherwise string is added to list, augmenting built-in strings */ -static int __init acpi_osi_setup(char *str) +int __init acpi_osi_setup(char *str) { if (str == NULL || *str == '\0') { printk(KERN_INFO PREFIX "_OSI method disabled\n"); diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index 75ccf5d18bf4..a3cc8a98255c 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -670,21 +670,26 @@ static int __cpuinit acpi_processor_start(struct acpi_device *device) pr->cdev = thermal_cooling_device_register("Processor", device, &processor_cooling_ops); - if (pr->cdev) + if (IS_ERR(pr->cdev)) { + result = PTR_ERR(pr->cdev); + goto end; + } + if (pr->cdev) { printk(KERN_INFO PREFIX "%s is registered as cooling_device%d\n", device->dev.bus_id, pr->cdev->id); - else - goto end; - result = sysfs_create_link(&device->dev.kobj, &pr->cdev->device.kobj, - "thermal_cooling"); - if (result) - return result; - result = sysfs_create_link(&pr->cdev->device.kobj, &device->dev.kobj, - "device"); - if (result) - return result; + result = sysfs_create_link(&device->dev.kobj, + &pr->cdev->device.kobj, + "thermal_cooling"); + if (result) + return result; + result = sysfs_create_link(&pr->cdev->device.kobj, + &device->dev.kobj, + "device"); + if (result) + return result; + } if (pr->flags.throttling) { printk(KERN_INFO PREFIX "%s [%s] (supports", @@ -809,10 +814,12 @@ static int acpi_processor_remove(struct acpi_device *device, int type) acpi_processor_remove_fs(device); - sysfs_remove_link(&device->dev.kobj, "thermal_cooling"); - sysfs_remove_link(&pr->cdev->device.kobj, "device"); - thermal_cooling_device_unregister(pr->cdev); - pr->cdev = NULL; + if (pr->cdev) { + sysfs_remove_link(&device->dev.kobj, "thermal_cooling"); + sysfs_remove_link(&pr->cdev->device.kobj, "device"); + thermal_cooling_device_unregister(pr->cdev); + pr->cdev = NULL; + } processors[pr->id] = NULL; @@ -826,8 +833,6 @@ static int acpi_processor_remove(struct acpi_device *device, int type) * Acpi processor hotplug support * ****************************************************************************/ -static int is_processor_present(acpi_handle handle); - static int is_processor_present(acpi_handle handle) { acpi_status status; diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 32003fdc91e8..6f3b217699e9 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -364,7 +364,7 @@ int acpi_processor_resume(struct acpi_device * device) return 0; } -#if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86_TSC) +#if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86) static int tsc_halts_in_c(int state) { switch (boot_cpu_data.x86_vendor) { @@ -544,7 +544,7 @@ static void acpi_processor_idle(void) /* Get end time (ticks) */ t2 = inl(acpi_gbl_FADT.xpm_timer_block.address); -#if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86_TSC) +#if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86) /* TSC halts in C2, so notify users */ if (tsc_halts_in_c(ACPI_STATE_C2)) mark_tsc_unstable("possible TSC halt in C2"); @@ -609,7 +609,7 @@ static void acpi_processor_idle(void) acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0); } -#if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86_TSC) +#if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86) /* TSC halts in C3, so notify users */ if (tsc_halts_in_c(ACPI_STATE_C3)) mark_tsc_unstable("TSC halts in C3"); @@ -945,11 +945,16 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr) * Otherwise, ignore this info and continue. */ cx.entry_method = ACPI_CSTATE_HALT; + snprintf(cx.desc, ACPI_CX_DESC_LEN, "ACPI HLT"); } else { continue; } + } else { + snprintf(cx.desc, ACPI_CX_DESC_LEN, "ACPI IOPORT 0x%x", + cx.address); } + obj = &(element->package.elements[2]); if (obj->type != ACPI_TYPE_INTEGER) continue; @@ -1420,6 +1425,14 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev, return 0; local_irq_disable(); + + /* Do not access any ACPI IO ports in suspend path */ + if (acpi_idle_suspend) { + acpi_safe_halt(); + local_irq_enable(); + return 0; + } + if (pr->flags.bm_check) acpi_idle_update_bm_rld(pr, cx); @@ -1487,7 +1500,7 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, acpi_idle_do_entry(cx); t2 = inl(acpi_gbl_FADT.xpm_timer_block.address); -#if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86_TSC) +#if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86) /* TSC could halt in idle, so notify users */ if (tsc_halts_in_c(cx->type)) mark_tsc_unstable("TSC halts in idle");; @@ -1601,7 +1614,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, spin_unlock(&c3_lock); } -#if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86_TSC) +#if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86) /* TSC could halt in idle, so notify users */ if (tsc_halts_in_c(ACPI_STATE_C3)) mark_tsc_unstable("TSC halts in idle"); @@ -1643,6 +1656,11 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr) return -EINVAL; } + for (i = 0; i < CPUIDLE_STATE_MAX; i++) { + dev->states[i].name[0] = '\0'; + dev->states[i].desc[0] = '\0'; + } + for (i = 1; i < ACPI_PROCESSOR_MAX_POWER && i <= max_cstate; i++) { cx = &pr->power.states[i]; state = &dev->states[count]; @@ -1659,6 +1677,7 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr) cpuidle_set_statedata(state, cx); snprintf(state->name, CPUIDLE_NAME_LEN, "C%d", i); + strncpy(state->desc, cx->desc, CPUIDLE_DESC_LEN); state->exit_latency = cx->latency; state->target_residency = cx->latency * latency_factor; state->power_usage = cx->power; diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c index 34f157571080..eba55b7d6c95 100644 --- a/drivers/acpi/utils.c +++ b/drivers/acpi/utils.c @@ -36,16 +36,20 @@ ACPI_MODULE_NAME("utils"); /* -------------------------------------------------------------------------- Object Evaluation Helpers -------------------------------------------------------------------------- */ +static void +acpi_util_eval_error(acpi_handle h, acpi_string p, acpi_status s) +{ #ifdef ACPI_DEBUG_OUTPUT -#define acpi_util_eval_error(h,p,s) {\ - char prefix[80] = {'\0'};\ - struct acpi_buffer buffer = {sizeof(prefix), prefix};\ - acpi_get_name(h, ACPI_FULL_PATHNAME, &buffer);\ - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluate [%s.%s]: %s\n",\ - (char *) prefix, p, acpi_format_exception(s))); } + char prefix[80] = {'\0'}; + struct acpi_buffer buffer = {sizeof(prefix), prefix}; + acpi_get_name(h, ACPI_FULL_PATHNAME, &buffer); + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluate [%s.%s]: %s\n", + (char *) prefix, p, acpi_format_exception(s))); #else -#define acpi_util_eval_error(h,p,s) + return; #endif +} + acpi_status acpi_extract_package(union acpi_object *package, struct acpi_buffer *format, struct acpi_buffer *buffer) diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 7f714fa2a454..12cce69b5441 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -731,6 +731,9 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) device->cdev = thermal_cooling_device_register("LCD", device->dev, &video_cooling_ops); + if (IS_ERR(device->cdev)) + return; + if (device->cdev) { printk(KERN_INFO PREFIX "%s is registered as cooling_device%d\n", diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 29e71bddd6ff..3c06e457b4dc 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -1975,16 +1975,11 @@ static int ahci_port_start(struct ata_port *ap) struct ahci_port_priv *pp; void *mem; dma_addr_t mem_dma; - int rc; pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL); if (!pp) return -ENOMEM; - rc = ata_pad_alloc(ap, dev); - if (rc) - return rc; - mem = dmam_alloc_coherent(dev, AHCI_PORT_PRIV_DMA_SZ, &mem_dma, GFP_KERNEL); if (!mem) diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index 9c2515f67de5..752e7d2f3b2f 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c @@ -1652,7 +1652,7 @@ static int __devinit piix_init_one(struct pci_dev *pdev, u8 tmp; pci_read_config_byte(pdev, PIIX_SCC, &tmp); if (tmp == PIIX_AHCI_DEVICE) { - int rc = piix_disable_ahci(pdev); + rc = piix_disable_ahci(pdev); if (rc) return rc; } diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 004dae4ea5bc..60d1bb556973 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -87,6 +87,28 @@ static struct workqueue_struct *ata_wq; struct workqueue_struct *ata_aux_wq; +struct ata_force_param { + const char *name; + unsigned int cbl; + int spd_limit; + unsigned long xfer_mask; + unsigned int horkage_on; + unsigned int horkage_off; +}; + +struct ata_force_ent { + int port; + int device; + struct ata_force_param param; +}; + +static struct ata_force_ent *ata_force_tbl; +static int ata_force_tbl_size; + +static char ata_force_param_buf[PAGE_SIZE] __initdata; +module_param_string(force, ata_force_param_buf, sizeof(ata_force_param_buf), 0444); +MODULE_PARM_DESC(force, "Force ATA configurations including cable type, link speed and transfer mode (see Documentation/kernel-parameters.txt for details)"); + int atapi_enabled = 1; module_param(atapi_enabled, int, 0444); MODULE_PARM_DESC(atapi_enabled, "Enable discovery of ATAPI devices (0=off, 1=on)"); @@ -129,6 +151,179 @@ MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_VERSION); +/** + * ata_force_cbl - force cable type according to libata.force + * @link: ATA link of interest + * + * Force cable type according to libata.force and whine about it. + * The last entry which has matching port number is used, so it + * can be specified as part of device force parameters. For + * example, both "a:40c,1.00:udma4" and "1.00:40c,udma4" have the + * same effect. + * + * LOCKING: + * EH context. + */ +void ata_force_cbl(struct ata_port *ap) +{ + int i; + + for (i = ata_force_tbl_size - 1; i >= 0; i--) { + const struct ata_force_ent *fe = &ata_force_tbl[i]; + + if (fe->port != -1 && fe->port != ap->print_id) + continue; + + if (fe->param.cbl == ATA_CBL_NONE) + continue; + + ap->cbl = fe->param.cbl; + ata_port_printk(ap, KERN_NOTICE, + "FORCE: cable set to %s\n", fe->param.name); + return; + } +} + +/** + * ata_force_spd_limit - force SATA spd limit according to libata.force + * @link: ATA link of interest + * + * Force SATA spd limit according to libata.force and whine about + * it. When only the port part is specified (e.g. 1:), the limit + * applies to all links connected to both the host link and all + * fan-out ports connected via PMP. If the device part is + * specified as 0 (e.g. 1.00:), it specifies the first fan-out + * link not the host link. Device number 15 always points to the + * host link whether PMP is attached or not. + * + * LOCKING: + * EH context. + */ +static void ata_force_spd_limit(struct ata_link *link) +{ + int linkno, i; + + if (ata_is_host_link(link)) + linkno = 15; + else + linkno = link->pmp; + + for (i = ata_force_tbl_size - 1; i >= 0; i--) { + const struct ata_force_ent *fe = &ata_force_tbl[i]; + + if (fe->port != -1 && fe->port != link->ap->print_id) + continue; + + if (fe->device != -1 && fe->device != linkno) + continue; + + if (!fe->param.spd_limit) + continue; + + link->hw_sata_spd_limit = (1 << fe->param.spd_limit) - 1; + ata_link_printk(link, KERN_NOTICE, + "FORCE: PHY spd limit set to %s\n", fe->param.name); + return; + } +} + +/** + * ata_force_xfermask - force xfermask according to libata.force + * @dev: ATA device of interest + * + * Force xfer_mask according to libata.force and whine about it. + * For consistency with link selection, device number 15 selects + * the first device connected to the host link. + * + * LOCKING: + * EH context. + */ +static void ata_force_xfermask(struct ata_device *dev) +{ + int devno = dev->link->pmp + dev->devno; + int alt_devno = devno; + int i; + + /* allow n.15 for the first device attached to host port */ + if (ata_is_host_link(dev->link) && devno == 0) + alt_devno = 15; + + for (i = ata_force_tbl_size - 1; i >= 0; i--) { + const struct ata_force_ent *fe = &ata_force_tbl[i]; + unsigned long pio_mask, mwdma_mask, udma_mask; + + if (fe->port != -1 && fe->port != dev->link->ap->print_id) + continue; + + if (fe->device != -1 && fe->device != devno && + fe->device != alt_devno) + continue; + + if (!fe->param.xfer_mask) + continue; + + ata_unpack_xfermask(fe->param.xfer_mask, + &pio_mask, &mwdma_mask, &udma_mask); + if (udma_mask) + dev->udma_mask = udma_mask; + else if (mwdma_mask) { + dev->udma_mask = 0; + dev->mwdma_mask = mwdma_mask; + } else { + dev->udma_mask = 0; + dev->mwdma_mask = 0; + dev->pio_mask = pio_mask; + } + + ata_dev_printk(dev, KERN_NOTICE, + "FORCE: xfer_mask set to %s\n", fe->param.name); + return; + } +} + +/** + * ata_force_horkage - force horkage according to libata.force + * @dev: ATA device of interest + * + * Force horkage according to libata.force and whine about it. + * For consistency with link selection, device number 15 selects + * the first device connected to the host link. + * + * LOCKING: + * EH context. + */ +static void ata_force_horkage(struct ata_device *dev) +{ + int devno = dev->link->pmp + dev->devno; + int alt_devno = devno; + int i; + + /* allow n.15 for the first device attached to host port */ + if (ata_is_host_link(dev->link) && devno == 0) + alt_devno = 15; + + for (i = 0; i < ata_force_tbl_size; i++) { + const struct ata_force_ent *fe = &ata_force_tbl[i]; + + if (fe->port != -1 && fe->port != dev->link->ap->print_id) + continue; + + if (fe->device != -1 && fe->device != devno && + fe->device != alt_devno) + continue; + + if (!(~dev->horkage & fe->param.horkage_on) && + !(dev->horkage & fe->param.horkage_off)) + continue; + + dev->horkage |= fe->param.horkage_on; + dev->horkage &= ~fe->param.horkage_off; + + ata_dev_printk(dev, KERN_NOTICE, + "FORCE: horkage modified (%s)\n", fe->param.name); + } +} + /** * ata_tf_to_fis - Convert ATA taskfile to SATA FIS structure * @tf: Taskfile to convert @@ -2067,6 +2262,7 @@ int ata_dev_configure(struct ata_device *dev) /* set horkage */ dev->horkage |= ata_dev_blacklisted(dev); + ata_force_horkage(dev); /* let ACPI work its magic */ rc = ata_acpi_on_devcfg(dev); @@ -3150,6 +3346,7 @@ int ata_do_set_mode(struct ata_link *link, struct ata_device **r_failed_dev) mode_mask = ATA_DMA_MASK_CFA; ata_dev_xfermask(dev); + ata_force_xfermask(dev); pio_mask = ata_pack_xfermask(dev->pio_mask, 0, 0); dma_mask = ata_pack_xfermask(0, dev->mwdma_mask, dev->udma_mask); @@ -4190,6 +4387,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { /* Devices which report 1 sector over size HPA */ { "ST340823A", NULL, ATA_HORKAGE_HPA_SIZE, }, { "ST320413A", NULL, ATA_HORKAGE_HPA_SIZE, }, + { "ST310211A", NULL, ATA_HORKAGE_HPA_SIZE, }, /* Devices which get the IVB wrong */ { "QUANTUM FIREBALLlct10 05", "A03.0900", ATA_HORKAGE_IVB, }, @@ -4492,30 +4690,13 @@ void ata_sg_clean(struct ata_queued_cmd *qc) struct ata_port *ap = qc->ap; struct scatterlist *sg = qc->sg; int dir = qc->dma_dir; - void *pad_buf = NULL; WARN_ON(sg == NULL); - VPRINTK("unmapping %u sg elements\n", qc->mapped_n_elem); + VPRINTK("unmapping %u sg elements\n", qc->n_elem); - /* if we padded the buffer out to 32-bit bound, and data - * xfer direction is from-device, we must copy from the - * pad buffer back into the supplied buffer - */ - if (qc->pad_len && !(qc->tf.flags & ATA_TFLAG_WRITE)) - pad_buf = ap->pad + (qc->tag * ATA_DMA_PAD_SZ); - - if (qc->mapped_n_elem) - dma_unmap_sg(ap->dev, sg, qc->mapped_n_elem, dir); - /* restore last sg */ - if (qc->last_sg) - *qc->last_sg = qc->saved_last_sg; - if (pad_buf) { - struct scatterlist *psg = &qc->extra_sg[1]; - void *addr = kmap_atomic(sg_page(psg), KM_IRQ0); - memcpy(addr + psg->offset, pad_buf, qc->pad_len); - kunmap_atomic(addr, KM_IRQ0); - } + if (qc->n_elem) + dma_unmap_sg(ap->dev, sg, qc->n_elem, dir); qc->flags &= ~ATA_QCFLAG_DMAMAP; qc->sg = NULL; @@ -4657,43 +4838,6 @@ int ata_check_atapi_dma(struct ata_queued_cmd *qc) return 0; } -/** - * atapi_qc_may_overflow - Check whether data transfer may overflow - * @qc: ATA command in question - * - * ATAPI commands which transfer variable length data to host - * might overflow due to application error or hardare bug. This - * function checks whether overflow should be drained and ignored - * for @qc. - * - * LOCKING: - * None. - * - * RETURNS: - * 1 if @qc may overflow; otherwise, 0. - */ -static int atapi_qc_may_overflow(struct ata_queued_cmd *qc) -{ - if (qc->tf.protocol != ATAPI_PROT_PIO && - qc->tf.protocol != ATAPI_PROT_DMA) - return 0; - - if (qc->tf.flags & ATA_TFLAG_WRITE) - return 0; - - switch (qc->cdb[0]) { - case READ_10: - case READ_12: - case WRITE_10: - case WRITE_12: - case GPCMD_READ_CD: - case GPCMD_READ_CD_MSF: - return 0; - } - - return 1; -} - /** * ata_std_qc_defer - Check whether a qc needs to be deferred * @qc: ATA command in question @@ -4781,97 +4925,6 @@ void ata_sg_init(struct ata_queued_cmd *qc, struct scatterlist *sg, qc->cursg = qc->sg; } -static unsigned int ata_sg_setup_extra(struct ata_queued_cmd *qc, - unsigned int *n_elem_extra, - unsigned int *nbytes_extra) -{ - struct ata_port *ap = qc->ap; - unsigned int n_elem = qc->n_elem; - struct scatterlist *lsg, *copy_lsg = NULL, *tsg = NULL, *esg = NULL; - - *n_elem_extra = 0; - *nbytes_extra = 0; - - /* needs padding? */ - qc->pad_len = qc->nbytes & 3; - - if (likely(!qc->pad_len)) - return n_elem; - - /* locate last sg and save it */ - lsg = sg_last(qc->sg, n_elem); - qc->last_sg = lsg; - qc->saved_last_sg = *lsg; - - sg_init_table(qc->extra_sg, ARRAY_SIZE(qc->extra_sg)); - - if (qc->pad_len) { - struct scatterlist *psg = &qc->extra_sg[1]; - void *pad_buf = ap->pad + (qc->tag * ATA_DMA_PAD_SZ); - unsigned int offset; - - WARN_ON(qc->dev->class != ATA_DEV_ATAPI); - - memset(pad_buf, 0, ATA_DMA_PAD_SZ); - - /* psg->page/offset are used to copy to-be-written - * data in this function or read data in ata_sg_clean. - */ - offset = lsg->offset + lsg->length - qc->pad_len; - sg_set_page(psg, nth_page(sg_page(lsg), offset >> PAGE_SHIFT), - qc->pad_len, offset_in_page(offset)); - - if (qc->tf.flags & ATA_TFLAG_WRITE) { - void *addr = kmap_atomic(sg_page(psg), KM_IRQ0); - memcpy(pad_buf, addr + psg->offset, qc->pad_len); - kunmap_atomic(addr, KM_IRQ0); - } - - sg_dma_address(psg) = ap->pad_dma + (qc->tag * ATA_DMA_PAD_SZ); - sg_dma_len(psg) = ATA_DMA_PAD_SZ; - - /* Trim the last sg entry and chain the original and - * padding sg lists. - * - * Because chaining consumes one sg entry, one extra - * sg entry is allocated and the last sg entry is - * copied to it if the length isn't zero after padded - * amount is removed. - * - * If the last sg entry is completely replaced by - * padding sg entry, the first sg entry is skipped - * while chaining. - */ - lsg->length -= qc->pad_len; - if (lsg->length) { - copy_lsg = &qc->extra_sg[0]; - tsg = &qc->extra_sg[0]; - } else { - n_elem--; - tsg = &qc->extra_sg[1]; - } - - esg = &qc->extra_sg[1]; - - (*n_elem_extra)++; - (*nbytes_extra) += 4 - qc->pad_len; - } - - if (copy_lsg) - sg_set_page(copy_lsg, sg_page(lsg), lsg->length, lsg->offset); - - sg_chain(lsg, 1, tsg); - sg_mark_end(esg); - - /* sglist can't start with chaining sg entry, fast forward */ - if (qc->sg == lsg) { - qc->sg = tsg; - qc->cursg = tsg; - } - - return n_elem; -} - /** * ata_sg_setup - DMA-map the scatter-gather table associated with a command. * @qc: Command with scatter-gather table to be mapped. @@ -4888,26 +4941,17 @@ static unsigned int ata_sg_setup_extra(struct ata_queued_cmd *qc, static int ata_sg_setup(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; - unsigned int n_elem, n_elem_extra, nbytes_extra; + unsigned int n_elem; VPRINTK("ENTER, ata%u\n", ap->print_id); - n_elem = ata_sg_setup_extra(qc, &n_elem_extra, &nbytes_extra); + n_elem = dma_map_sg(ap->dev, qc->sg, qc->n_elem, qc->dma_dir); + if (n_elem < 1) + return -1; - if (n_elem) { - n_elem = dma_map_sg(ap->dev, qc->sg, n_elem, qc->dma_dir); - if (n_elem < 1) { - /* restore last sg */ - if (qc->last_sg) - *qc->last_sg = qc->saved_last_sg; - return -1; - } - DPRINTK("%d sg elements mapped\n", n_elem); - } + DPRINTK("%d sg elements mapped\n", n_elem); - qc->n_elem = qc->mapped_n_elem = n_elem; - qc->n_elem += n_elem_extra; - qc->nbytes += nbytes_extra; + qc->n_elem = n_elem; qc->flags |= ATA_QCFLAG_DMAMAP; return 0; @@ -5145,46 +5189,22 @@ static void atapi_send_cdb(struct ata_port *ap, struct ata_queued_cmd *qc) */ static int __atapi_pio_bytes(struct ata_queued_cmd *qc, unsigned int bytes) { - int do_write = (qc->tf.flags & ATA_TFLAG_WRITE); + int rw = (qc->tf.flags & ATA_TFLAG_WRITE) ? WRITE : READ; struct ata_port *ap = qc->ap; - struct ata_eh_info *ehi = &qc->dev->link->eh_info; + struct ata_device *dev = qc->dev; + struct ata_eh_info *ehi = &dev->link->eh_info; struct scatterlist *sg; struct page *page; unsigned char *buf; - unsigned int offset, count; + unsigned int offset, count, consumed; next_sg: sg = qc->cursg; if (unlikely(!sg)) { - /* - * The end of qc->sg is reached and the device expects - * more data to transfer. In order not to overrun qc->sg - * and fulfill length specified in the byte count register, - * - for read case, discard trailing data from the device - * - for write case, padding zero data to the device - */ - u16 pad_buf[1] = { 0 }; - unsigned int i; - - if (bytes > qc->curbytes - qc->nbytes + ATAPI_MAX_DRAIN) { - ata_ehi_push_desc(ehi, "too much trailing data " - "buf=%u cur=%u bytes=%u", - qc->nbytes, qc->curbytes, bytes); - return -1; - } - - /* overflow is exptected for misc ATAPI commands */ - if (bytes && !atapi_qc_may_overflow(qc)) - ata_dev_printk(qc->dev, KERN_WARNING, "ATAPI %u bytes " - "trailing data (cdb=%02x nbytes=%u)\n", - bytes, qc->cdb[0], qc->nbytes); - - for (i = 0; i < (bytes + 1) / 2; i++) - ap->ops->data_xfer(qc->dev, (unsigned char *)pad_buf, 2, do_write); - - qc->curbytes += bytes; - - return 0; + ata_ehi_push_desc(ehi, "unexpected or too much trailing data " + "buf=%u cur=%u bytes=%u", + qc->nbytes, qc->curbytes, bytes); + return -1; } page = sg_page(sg); @@ -5210,18 +5230,16 @@ next_sg: buf = kmap_atomic(page, KM_IRQ0); /* do the actual data transfer */ - ap->ops->data_xfer(qc->dev, buf + offset, count, do_write); + consumed = ap->ops->data_xfer(dev, buf + offset, count, rw); kunmap_atomic(buf, KM_IRQ0); local_irq_restore(flags); } else { buf = page_address(page); - ap->ops->data_xfer(qc->dev, buf + offset, count, do_write); + consumed = ap->ops->data_xfer(dev, buf + offset, count, rw); } - bytes -= count; - if ((count & 1) && bytes) - bytes--; + bytes -= min(bytes, consumed); qc->curbytes += count; qc->cursg_ofs += count; @@ -5230,9 +5248,11 @@ next_sg: qc->cursg_ofs = 0; } + /* consumed can be larger than count only for the last transfer */ + WARN_ON(qc->cursg && count != consumed); + if (bytes) goto next_sg; - return 0; } @@ -5250,6 +5270,7 @@ static void atapi_pio_bytes(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; struct ata_device *dev = qc->dev; + struct ata_eh_info *ehi = &dev->link->eh_info; unsigned int ireason, bc_lo, bc_hi, bytes; int i_write, do_write = (qc->tf.flags & ATA_TFLAG_WRITE) ? 1 : 0; @@ -5267,26 +5288,28 @@ static void atapi_pio_bytes(struct ata_queued_cmd *qc) /* shall be cleared to zero, indicating xfer of data */ if (unlikely(ireason & (1 << 0))) - goto err_out; + goto atapi_check; /* make sure transfer direction matches expected */ i_write = ((ireason & (1 << 1)) == 0) ? 1 : 0; if (unlikely(do_write != i_write)) - goto err_out; + goto atapi_check; if (unlikely(!bytes)) - goto err_out; + goto atapi_check; VPRINTK("ata%u: xfering %d bytes\n", ap->print_id, bytes); - if (__atapi_pio_bytes(qc, bytes)) + if (unlikely(__atapi_pio_bytes(qc, bytes))) goto err_out; ata_altstatus(ap); /* flush */ return; -err_out: - ata_dev_printk(dev, KERN_INFO, "ATAPI check failed\n"); + atapi_check: + ata_ehi_push_desc(ehi, "ATAPI check failed (ireason=0x%x bytes=%u)", + ireason, bytes); + err_out: qc->err_mask |= AC_ERR_HSM; ap->hsm_task_state = HSM_ST_ERR; } @@ -5971,9 +5994,6 @@ void ata_qc_issue(struct ata_queued_cmd *qc) */ BUG_ON(ata_is_data(prot) && (!qc->sg || !qc->n_elem || !qc->nbytes)); - /* ata_sg_setup() may update nbytes */ - qc->raw_nbytes = qc->nbytes; - if (ata_is_dma(prot) || (ata_is_pio(prot) && (ap->flags & ATA_FLAG_PIO_DMA))) if (ata_sg_setup(qc)) @@ -6582,19 +6602,12 @@ void ata_host_resume(struct ata_host *host) int ata_port_start(struct ata_port *ap) { struct device *dev = ap->dev; - int rc; ap->prd = dmam_alloc_coherent(dev, ATA_PRD_TBL_SZ, &ap->prd_dma, GFP_KERNEL); if (!ap->prd) return -ENOMEM; - rc = ata_pad_alloc(ap, dev); - if (rc) - return rc; - - DPRINTK("prd alloc, virt %p, dma %llx\n", ap->prd, - (unsigned long long)ap->prd_dma); return 0; } @@ -6681,7 +6694,8 @@ void ata_link_init(struct ata_port *ap, struct ata_link *link, int pmp) */ int sata_link_init_spd(struct ata_link *link) { - u32 scontrol, spd; + u32 scontrol; + u8 spd; int rc; rc = sata_scr_read(link, SCR_CONTROL, &scontrol); @@ -6692,6 +6706,8 @@ int sata_link_init_spd(struct ata_link *link) if (spd) link->hw_sata_spd_limit &= (1 << spd) - 1; + ata_force_spd_limit(link); + link->sata_spd_limit = link->hw_sata_spd_limit; return 0; @@ -7086,7 +7102,6 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht) DPRINTK("probe begin\n"); for (i = 0; i < host->n_ports; i++) { struct ata_port *ap = host->ports[i]; - int rc; /* probe */ if (ap->ops->error_handler) { @@ -7403,10 +7418,187 @@ int ata_pci_device_resume(struct pci_dev *pdev) #endif /* CONFIG_PCI */ +static int __init ata_parse_force_one(char **cur, + struct ata_force_ent *force_ent, + const char **reason) +{ + /* FIXME: Currently, there's no way to tag init const data and + * using __initdata causes build failure on some versions of + * gcc. Once __initdataconst is implemented, add const to the + * following structure. + */ + static struct ata_force_param force_tbl[] __initdata = { + { "40c", .cbl = ATA_CBL_PATA40 }, + { "80c", .cbl = ATA_CBL_PATA80 }, + { "short40c", .cbl = ATA_CBL_PATA40_SHORT }, + { "unk", .cbl = ATA_CBL_PATA_UNK }, + { "ign", .cbl = ATA_CBL_PATA_IGN }, + { "sata", .cbl = ATA_CBL_SATA }, + { "1.5Gbps", .spd_limit = 1 }, + { "3.0Gbps", .spd_limit = 2 }, + { "noncq", .horkage_on = ATA_HORKAGE_NONCQ }, + { "ncq", .horkage_off = ATA_HORKAGE_NONCQ }, + { "pio0", .xfer_mask = 1 << (ATA_SHIFT_PIO + 0) }, + { "pio1", .xfer_mask = 1 << (ATA_SHIFT_PIO + 1) }, + { "pio2", .xfer_mask = 1 << (ATA_SHIFT_PIO + 2) }, + { "pio3", .xfer_mask = 1 << (ATA_SHIFT_PIO + 3) }, + { "pio4", .xfer_mask = 1 << (ATA_SHIFT_PIO + 4) }, + { "pio5", .xfer_mask = 1 << (ATA_SHIFT_PIO + 5) }, + { "pio6", .xfer_mask = 1 << (ATA_SHIFT_PIO + 6) }, + { "mwdma0", .xfer_mask = 1 << (ATA_SHIFT_MWDMA + 0) }, + { "mwdma1", .xfer_mask = 1 << (ATA_SHIFT_MWDMA + 1) }, + { "mwdma2", .xfer_mask = 1 << (ATA_SHIFT_MWDMA + 2) }, + { "mwdma3", .xfer_mask = 1 << (ATA_SHIFT_MWDMA + 3) }, + { "mwdma4", .xfer_mask = 1 << (ATA_SHIFT_MWDMA + 4) }, + { "udma0", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 0) }, + { "udma16", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 0) }, + { "udma/16", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 0) }, + { "udma1", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 1) }, + { "udma25", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 1) }, + { "udma/25", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 1) }, + { "udma2", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 2) }, + { "udma33", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 2) }, + { "udma/33", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 2) }, + { "udma3", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 3) }, + { "udma44", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 3) }, + { "udma/44", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 3) }, + { "udma4", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 4) }, + { "udma66", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 4) }, + { "udma/66", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 4) }, + { "udma5", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 5) }, + { "udma100", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 5) }, + { "udma/100", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 5) }, + { "udma6", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 6) }, + { "udma133", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 6) }, + { "udma/133", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 6) }, + { "udma7", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 7) }, + }; + char *start = *cur, *p = *cur; + char *id, *val, *endp; + const struct ata_force_param *match_fp = NULL; + int nr_matches = 0, i; + + /* find where this param ends and update *cur */ + while (*p != '\0' && *p != ',') + p++; + + if (*p == '\0') + *cur = p; + else + *cur = p + 1; + + *p = '\0'; + + /* parse */ + p = strchr(start, ':'); + if (!p) { + val = strstrip(start); + goto parse_val; + } + *p = '\0'; + + id = strstrip(start); + val = strstrip(p + 1); + + /* parse id */ + p = strchr(id, '.'); + if (p) { + *p++ = '\0'; + force_ent->device = simple_strtoul(p, &endp, 10); + if (p == endp || *endp != '\0') { + *reason = "invalid device"; + return -EINVAL; + } + } + + force_ent->port = simple_strtoul(id, &endp, 10); + if (p == endp || *endp != '\0') { + *reason = "invalid port/link"; + return -EINVAL; + } + + parse_val: + /* parse val, allow shortcuts so that both 1.5 and 1.5Gbps work */ + for (i = 0; i < ARRAY_SIZE(force_tbl); i++) { + const struct ata_force_param *fp = &force_tbl[i]; + + if (strncasecmp(val, fp->name, strlen(val))) + continue; + + nr_matches++; + match_fp = fp; + + if (strcasecmp(val, fp->name) == 0) { + nr_matches = 1; + break; + } + } + + if (!nr_matches) { + *reason = "unknown value"; + return -EINVAL; + } + if (nr_matches > 1) { + *reason = "ambigious value"; + return -EINVAL; + } + + force_ent->param = *match_fp; + + return 0; +} + +static void __init ata_parse_force_param(void) +{ + int idx = 0, size = 1; + int last_port = -1, last_device = -1; + char *p, *cur, *next; + + /* calculate maximum number of params and allocate force_tbl */ + for (p = ata_force_param_buf; *p; p++) + if (*p == ',') + size++; + + ata_force_tbl = kzalloc(sizeof(ata_force_tbl[0]) * size, GFP_KERNEL); + if (!ata_force_tbl) { + printk(KERN_WARNING "ata: failed to extend force table, " + "libata.force ignored\n"); + return; + } + + /* parse and populate the table */ + for (cur = ata_force_param_buf; *cur != '\0'; cur = next) { + const char *reason = ""; + struct ata_force_ent te = { .port = -1, .device = -1 }; + + next = cur; + if (ata_parse_force_one(&next, &te, &reason)) { + printk(KERN_WARNING "ata: failed to parse force " + "parameter \"%s\" (%s)\n", + cur, reason); + continue; + } + + if (te.port == -1) { + te.port = last_port; + te.device = last_device; + } + + ata_force_tbl[idx++] = te; + + last_port = te.port; + last_device = te.device; + } + + ata_force_tbl_size = idx; +} static int __init ata_init(void) { ata_probe_timeout *= HZ; + + ata_parse_force_param(); + ata_wq = create_workqueue("ata"); if (!ata_wq) return -ENOMEM; @@ -7423,6 +7615,7 @@ static int __init ata_init(void) static void __exit ata_exit(void) { + kfree(ata_force_tbl); destroy_workqueue(ata_wq); destroy_workqueue(ata_aux_wq); } diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 4e31071acc02..698ce2cea52c 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -2393,9 +2393,11 @@ static int ata_eh_revalidate_and_attach(struct ata_link *link, } /* PDIAG- should have been released, ask cable type if post-reset */ - if (ata_is_host_link(link) && ap->ops->cable_detect && - (ehc->i.flags & ATA_EHI_DID_RESET)) - ap->cbl = ap->ops->cable_detect(ap); + if ((ehc->i.flags & ATA_EHI_DID_RESET) && ata_is_host_link(link)) { + if (ap->ops->cable_detect) + ap->cbl = ap->ops->cable_detect(ap); + ata_force_cbl(ap); + } /* Configure new devices forward such that user doesn't see * device detection messages backwards. diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index c02c490122dc..f888babc8283 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -826,30 +826,61 @@ static void ata_scsi_sdev_config(struct scsi_device *sdev) sdev->max_device_blocked = 1; } -static void ata_scsi_dev_config(struct scsi_device *sdev, - struct ata_device *dev) +/** + * atapi_drain_needed - Check whether data transfer may overflow + * @rq: request to be checked + * + * ATAPI commands which transfer variable length data to host + * might overflow due to application error or hardare bug. This + * function checks whether overflow should be drained and ignored + * for @request. + * + * LOCKING: + * None. + * + * RETURNS: + * 1 if ; otherwise, 0. + */ +static int atapi_drain_needed(struct request *rq) +{ + if (likely(!blk_pc_request(rq))) + return 0; + + if (!rq->data_len || (rq->cmd_flags & REQ_RW)) + return 0; + + return atapi_cmd_type(rq->cmd[0]) == ATAPI_MISC; +} + +static int ata_scsi_dev_config(struct scsi_device *sdev, + struct ata_device *dev) { /* configure max sectors */ blk_queue_max_sectors(sdev->request_queue, dev->max_sectors); - /* SATA DMA transfers must be multiples of 4 byte, so - * we need to pad ATAPI transfers using an extra sg. - * Decrement max hw segments accordingly. - */ if (dev->class == ATA_DEV_ATAPI) { struct request_queue *q = sdev->request_queue; - blk_queue_max_hw_segments(q, q->max_hw_segments - 1); + void *buf; /* set the min alignment */ blk_queue_update_dma_alignment(sdev->request_queue, ATA_DMA_PAD_SZ - 1); - } else + + /* configure draining */ + buf = kmalloc(ATAPI_MAX_DRAIN, q->bounce_gfp | GFP_KERNEL); + if (!buf) { + ata_dev_printk(dev, KERN_ERR, + "drain buffer allocation failed\n"); + return -ENOMEM; + } + + blk_queue_dma_drain(q, atapi_drain_needed, buf, ATAPI_MAX_DRAIN); + } else { /* ATA devices must be sector aligned */ blk_queue_update_dma_alignment(sdev->request_queue, ATA_SECT_SIZE - 1); - - if (dev->class == ATA_DEV_ATA) sdev->manage_start_stop = 1; + } if (dev->flags & ATA_DFLAG_AN) set_bit(SDEV_EVT_MEDIA_CHANGE, sdev->supported_events); @@ -861,6 +892,8 @@ static void ata_scsi_dev_config(struct scsi_device *sdev, depth = min(ATA_MAX_QUEUE - 1, depth); scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, depth); } + + return 0; } /** @@ -879,13 +912,14 @@ int ata_scsi_slave_config(struct scsi_device *sdev) { struct ata_port *ap = ata_shost_to_port(sdev->host); struct ata_device *dev = __ata_scsi_find_dev(ap, sdev); + int rc = 0; ata_scsi_sdev_config(sdev); if (dev) - ata_scsi_dev_config(sdev, dev); + rc = ata_scsi_dev_config(sdev, dev); - return 0; + return rc; } /** @@ -905,6 +939,7 @@ int ata_scsi_slave_config(struct scsi_device *sdev) void ata_scsi_slave_destroy(struct scsi_device *sdev) { struct ata_port *ap = ata_shost_to_port(sdev->host); + struct request_queue *q = sdev->request_queue; unsigned long flags; struct ata_device *dev; @@ -920,6 +955,10 @@ void ata_scsi_slave_destroy(struct scsi_device *sdev) ata_port_schedule_eh(ap); } spin_unlock_irqrestore(ap->lock, flags); + + kfree(q->dma_drain_buffer); + q->dma_drain_buffer = NULL; + q->dma_drain_size = 0; } /** @@ -1862,7 +1901,7 @@ unsigned int ata_scsiop_inq_83(struct ata_scsi_args *args, u8 *rbuf, * spin_lock_irqsave(host lock) */ -unsigned int ata_scsiop_inq_89(struct ata_scsi_args *args, u8 *rbuf, +static unsigned int ata_scsiop_inq_89(struct ata_scsi_args *args, u8 *rbuf, unsigned int buflen) { u8 pbuf[60]; @@ -2500,7 +2539,7 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc) * want to set it properly, and for DMA where it is * effectively meaningless. */ - nbytes = min(qc->nbytes, (unsigned int)63 * 1024); + nbytes = min(scmd->request->raw_data_len, (unsigned int)63 * 1024); /* Most ATAPI devices which honor transfer chunk size don't * behave according to the spec when odd chunk size which @@ -3555,7 +3594,7 @@ EXPORT_SYMBOL_GPL(ata_sas_port_alloc); * @ap: Port to initialize * * Called just after data structures for each port are - * initialized. Allocates DMA pad. + * initialized. * * May be used as the port_start() entry in ata_port_operations. * @@ -3564,7 +3603,7 @@ EXPORT_SYMBOL_GPL(ata_sas_port_alloc); */ int ata_sas_port_start(struct ata_port *ap) { - return ata_pad_alloc(ap, ap->dev); + return 0; } EXPORT_SYMBOL_GPL(ata_sas_port_start); @@ -3572,8 +3611,6 @@ EXPORT_SYMBOL_GPL(ata_sas_port_start); * ata_port_stop - Undo ata_sas_port_start() * @ap: Port to shut down * - * Frees the DMA pad. - * * May be used as the port_stop() entry in ata_port_operations. * * LOCKING: @@ -3582,7 +3619,6 @@ EXPORT_SYMBOL_GPL(ata_sas_port_start); void ata_sas_port_stop(struct ata_port *ap) { - ata_pad_free(ap, ap->dev); } EXPORT_SYMBOL_GPL(ata_sas_port_stop); diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h index 409ffb9af163..6036dedfe377 100644 --- a/drivers/ata/libata.h +++ b/drivers/ata/libata.h @@ -61,6 +61,7 @@ extern int atapi_passthru16; extern int libata_fua; extern int libata_noacpi; extern int libata_allow_tpm; +extern void ata_force_cbl(struct ata_port *ap); extern struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev); extern int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev, u64 block, u32 n_block, unsigned int tf_flags, diff --git a/drivers/ata/pata_acpi.c b/drivers/ata/pata_acpi.c index 244098a80ce4..bdc3b9d7395c 100644 --- a/drivers/ata/pata_acpi.c +++ b/drivers/ata/pata_acpi.c @@ -77,8 +77,8 @@ static int pacpi_cable_detect(struct ata_port *ap) static void pacpi_error_handler(struct ata_port *ap) { - return ata_bmdma_drive_eh(ap, pacpi_pre_reset, ata_std_softreset, - NULL, ata_std_postreset); + ata_bmdma_drive_eh(ap, pacpi_pre_reset, ata_std_softreset, NULL, + ata_std_postreset); } /** diff --git a/drivers/ata/pata_amd.c b/drivers/ata/pata_amd.c index ea567e2b1703..4b8d9b592ca4 100644 --- a/drivers/ata/pata_amd.c +++ b/drivers/ata/pata_amd.c @@ -146,9 +146,8 @@ static int amd_pre_reset(struct ata_link *link, unsigned long deadline) static void amd_error_handler(struct ata_port *ap) { - return ata_bmdma_drive_eh(ap, amd_pre_reset, - ata_std_softreset, NULL, - ata_std_postreset); + ata_bmdma_drive_eh(ap, amd_pre_reset, ata_std_softreset, NULL, + ata_std_postreset); } static int amd_cable_detect(struct ata_port *ap) @@ -506,7 +505,6 @@ static struct ata_port_operations amd133_port_ops = { static struct ata_port_operations nv100_port_ops = { .set_piomode = nv100_set_piomode, .set_dmamode = nv100_set_dmamode, - .mode_filter = ata_pci_default_filter, .tf_load = ata_tf_load, .tf_read = ata_tf_read, .check_status = ata_check_status, @@ -541,7 +539,6 @@ static struct ata_port_operations nv100_port_ops = { static struct ata_port_operations nv133_port_ops = { .set_piomode = nv133_set_piomode, .set_dmamode = nv133_set_dmamode, - .mode_filter = ata_pci_default_filter, .tf_load = ata_tf_load, .tf_read = ata_tf_read, .check_status = ata_check_status, diff --git a/drivers/ata/pata_cs5536.c b/drivers/ata/pata_cs5536.c index d753e568588e..1c4ff9b52b5c 100644 --- a/drivers/ata/pata_cs5536.c +++ b/drivers/ata/pata_cs5536.c @@ -40,7 +40,7 @@ #include #define DRV_NAME "pata_cs5536" -#define DRV_VERSION "0.0.6" +#define DRV_VERSION "0.0.7" enum { CFG = 0, @@ -85,7 +85,7 @@ static const u8 pci_reg[4] = { PCI_IDE_CFG, PCI_IDE_DTC, PCI_IDE_CAST, PCI_IDE_ETC, }; -static inline int cs5536_read(struct pci_dev *pdev, int reg, int *val) +static inline int cs5536_read(struct pci_dev *pdev, int reg, u32 *val) { if (unlikely(use_msr)) { u32 dummy; @@ -153,8 +153,8 @@ static void cs5536_set_piomode(struct ata_port *ap, struct ata_device *adev) struct ata_device *pair = ata_dev_pair(adev); int mode = adev->pio_mode - XFER_PIO_0; int cmdmode = mode; - int dshift = ap->port_no ? IDE_D1_SHIFT : IDE_D0_SHIFT; - int cshift = ap->port_no ? IDE_CAST_D1_SHIFT : IDE_CAST_D0_SHIFT; + int dshift = adev->devno ? IDE_D1_SHIFT : IDE_D0_SHIFT; + int cshift = adev->devno ? IDE_CAST_D1_SHIFT : IDE_CAST_D0_SHIFT; u32 dtc, cast, etc; if (pair) @@ -201,7 +201,7 @@ static void cs5536_set_dmamode(struct ata_port *ap, struct ata_device *adev) struct pci_dev *pdev = to_pci_dev(ap->host->dev); u32 dtc, etc; int mode = adev->dma_mode; - int dshift = ap->port_no ? IDE_D1_SHIFT : IDE_D0_SHIFT; + int dshift = adev->devno ? IDE_D1_SHIFT : IDE_D0_SHIFT; if (mode >= XFER_UDMA_0) { cs5536_read(pdev, ETC, &etc); diff --git a/drivers/ata/pata_icside.c b/drivers/ata/pata_icside.c index 5b8586dac63b..f97068be2d79 100644 --- a/drivers/ata/pata_icside.c +++ b/drivers/ata/pata_icside.c @@ -304,12 +304,6 @@ static int icside_dma_init(struct pata_icside_info *info) } -static int pata_icside_port_start(struct ata_port *ap) -{ - /* No PRD to alloc */ - return ata_pad_alloc(ap, ap->dev); -} - static struct scsi_host_template pata_icside_sht = { .module = THIS_MODULE, .name = DRV_NAME, @@ -389,8 +383,6 @@ static struct ata_port_operations pata_icside_port_ops = { .irq_clear = ata_dummy_noret, .irq_on = ata_irq_on, - .port_start = pata_icside_port_start, - .bmdma_stop = pata_icside_bmdma_stop, .bmdma_status = pata_icside_bmdma_status, }; diff --git a/drivers/ata/pata_jmicron.c b/drivers/ata/pata_jmicron.c index 5b8174d94067..00bbbbd50e97 100644 --- a/drivers/ata/pata_jmicron.c +++ b/drivers/ata/pata_jmicron.c @@ -115,7 +115,8 @@ static int jmicron_pre_reset(struct ata_link *link, unsigned long deadline) static void jmicron_error_handler(struct ata_port *ap) { - return ata_bmdma_drive_eh(ap, jmicron_pre_reset, ata_std_softreset, NULL, ata_std_postreset); + ata_bmdma_drive_eh(ap, jmicron_pre_reset, ata_std_softreset, NULL, + ata_std_postreset); } /* No PIO or DMA methods needed for this device */ diff --git a/drivers/ata/pata_legacy.c b/drivers/ata/pata_legacy.c index 6c59969fd50b..50fe08ebe23c 100644 --- a/drivers/ata/pata_legacy.c +++ b/drivers/ata/pata_legacy.c @@ -774,14 +774,14 @@ static struct ata_port_operations opti82c46x_port_ops = { static void qdi6500_set_piomode(struct ata_port *ap, struct ata_device *adev) { struct ata_timing t; - struct legacy_data *qdi = ap->host->private_data; + struct legacy_data *ld_qdi = ap->host->private_data; int active, recovery; u8 timing; /* Get the timing data in cycles */ ata_timing_compute(adev, adev->pio_mode, &t, 30303, 1000); - if (qdi->fast) { + if (ld_qdi->fast) { active = 8 - FIT(t.active, 1, 8); recovery = 18 - FIT(t.recover, 3, 18); } else { @@ -790,9 +790,9 @@ static void qdi6500_set_piomode(struct ata_port *ap, struct ata_device *adev) } timing = (recovery << 4) | active | 0x08; - qdi->clock[adev->devno] = timing; + ld_qdi->clock[adev->devno] = timing; - outb(timing, qdi->timing); + outb(timing, ld_qdi->timing); } /** @@ -808,14 +808,14 @@ static void qdi6500_set_piomode(struct ata_port *ap, struct ata_device *adev) static void qdi6580dp_set_piomode(struct ata_port *ap, struct ata_device *adev) { struct ata_timing t; - struct legacy_data *qdi = ap->host->private_data; + struct legacy_data *ld_qdi = ap->host->private_data; int active, recovery; u8 timing; /* Get the timing data in cycles */ ata_timing_compute(adev, adev->pio_mode, &t, 30303, 1000); - if (qdi->fast) { + if (ld_qdi->fast) { active = 8 - FIT(t.active, 1, 8); recovery = 18 - FIT(t.recover, 3, 18); } else { @@ -824,12 +824,12 @@ static void qdi6580dp_set_piomode(struct ata_port *ap, struct ata_device *adev) } timing = (recovery << 4) | active | 0x08; - qdi->clock[adev->devno] = timing; + ld_qdi->clock[adev->devno] = timing; - outb(timing, qdi->timing + 2 * ap->port_no); + outb(timing, ld_qdi->timing + 2 * ap->port_no); /* Clear the FIFO */ if (adev->class != ATA_DEV_ATA) - outb(0x5F, qdi->timing + 3); + outb(0x5F, ld_qdi->timing + 3); } /** @@ -845,14 +845,14 @@ static void qdi6580dp_set_piomode(struct ata_port *ap, struct ata_device *adev) static void qdi6580_set_piomode(struct ata_port *ap, struct ata_device *adev) { struct ata_timing t; - struct legacy_data *qdi = ap->host->private_data; + struct legacy_data *ld_qdi = ap->host->private_data; int active, recovery; u8 timing; /* Get the timing data in cycles */ ata_timing_compute(adev, adev->pio_mode, &t, 30303, 1000); - if (qdi->fast) { + if (ld_qdi->fast) { active = 8 - FIT(t.active, 1, 8); recovery = 18 - FIT(t.recover, 3, 18); } else { @@ -860,11 +860,11 @@ static void qdi6580_set_piomode(struct ata_port *ap, struct ata_device *adev) recovery = 15 - FIT(t.recover, 0, 15); } timing = (recovery << 4) | active | 0x08; - qdi->clock[adev->devno] = timing; - outb(timing, qdi->timing + 2 * adev->devno); + ld_qdi->clock[adev->devno] = timing; + outb(timing, ld_qdi->timing + 2 * adev->devno); /* Clear the FIFO */ if (adev->class != ATA_DEV_ATA) - outb(0x5F, qdi->timing + 3); + outb(0x5F, ld_qdi->timing + 3); } /** @@ -879,12 +879,12 @@ static unsigned int qdi_qc_issue_prot(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; struct ata_device *adev = qc->dev; - struct legacy_data *qdi = ap->host->private_data; + struct legacy_data *ld_qdi = ap->host->private_data; - if (qdi->clock[adev->devno] != qdi->last) { + if (ld_qdi->clock[adev->devno] != ld_qdi->last) { if (adev->pio_mode) { - qdi->last = qdi->clock[adev->devno]; - outb(qdi->clock[adev->devno], qdi->timing + + ld_qdi->last = ld_qdi->clock[adev->devno]; + outb(ld_qdi->clock[adev->devno], ld_qdi->timing + 2 * ap->port_no); } } @@ -1037,12 +1037,12 @@ static u8 winbond_readcfg(unsigned long port, u8 reg) static void winbond_set_piomode(struct ata_port *ap, struct ata_device *adev) { struct ata_timing t; - struct legacy_data *winbond = ap->host->private_data; + struct legacy_data *ld_winbond = ap->host->private_data; int active, recovery; u8 reg; int timing = 0x88 + (ap->port_no * 4) + (adev->devno * 2); - reg = winbond_readcfg(winbond->timing, 0x81); + reg = winbond_readcfg(ld_winbond->timing, 0x81); /* Get the timing data in cycles */ if (reg & 0x40) /* Fast VLB bus, assume 50MHz */ @@ -1053,7 +1053,7 @@ static void winbond_set_piomode(struct ata_port *ap, struct ata_device *adev) active = (FIT(t.active, 3, 17) - 1) & 0x0F; recovery = (FIT(t.recover, 1, 15) + 1) & 0x0F; timing = (active << 4) | recovery; - winbond_writecfg(winbond->timing, timing, reg); + winbond_writecfg(ld_winbond->timing, timing, reg); /* Load the setup timing */ @@ -1063,7 +1063,7 @@ static void winbond_set_piomode(struct ata_port *ap, struct ata_device *adev) if (!ata_pio_need_iordy(adev)) reg |= 0x02; /* IORDY off */ reg |= (FIT(t.setup, 0, 3) << 6); - winbond_writecfg(winbond->timing, timing + 1, reg); + winbond_writecfg(ld_winbond->timing, timing + 1, reg); } static int winbond_port(struct platform_device *dev, @@ -1278,8 +1278,6 @@ static __init int legacy_init_one(struct legacy_probe *probe) } } fail: - if (host) - ata_host_detach(host); platform_device_unregister(pdev); return ret; } diff --git a/drivers/ata/pata_marvell.c b/drivers/ata/pata_marvell.c index 9afc8a32b226..a81f25d87235 100644 --- a/drivers/ata/pata_marvell.c +++ b/drivers/ata/pata_marvell.c @@ -85,8 +85,8 @@ static int marvell_cable_detect(struct ata_port *ap) static void marvell_error_handler(struct ata_port *ap) { - return ata_bmdma_drive_eh(ap, marvell_pre_reset, ata_std_softreset, - NULL, ata_std_postreset); + ata_bmdma_drive_eh(ap, marvell_pre_reset, ata_std_softreset, NULL, + ata_std_postreset); } /* No PIO or DMA methods needed for this device */ diff --git a/drivers/ata/pata_scc.c b/drivers/ata/pata_scc.c index 55055b27524c..6c016deeaed8 100644 --- a/drivers/ata/pata_scc.c +++ b/drivers/ata/pata_scc.c @@ -1007,6 +1007,8 @@ static const struct ata_port_operations scc_pata_ops = { .qc_issue = ata_qc_issue_prot, .freeze = scc_bmdma_freeze, + .thaw = ata_bmdma_thaw, + .error_handler = scc_error_handler, .post_internal_cmd = scc_bmdma_stop, diff --git a/drivers/ata/sata_fsl.c b/drivers/ata/sata_fsl.c index efcb66b6ccef..9323dd0c7d8d 100644 --- a/drivers/ata/sata_fsl.c +++ b/drivers/ata/sata_fsl.c @@ -601,21 +601,9 @@ static int sata_fsl_port_start(struct ata_port *ap) if (!pp) return -ENOMEM; - /* - * allocate per command dma alignment pad buffer, which is used - * internally by libATA to ensure that all transfers ending on - * unaligned boundaries are padded, to align on Dword boundaries - */ - retval = ata_pad_alloc(ap, dev); - if (retval) { - kfree(pp); - return retval; - } - mem = dma_alloc_coherent(dev, SATA_FSL_PORT_PRIV_DMA_SZ, &mem_dma, GFP_KERNEL); if (!mem) { - ata_pad_free(ap, dev); kfree(pp); return -ENOMEM; } @@ -694,7 +682,6 @@ static void sata_fsl_port_stop(struct ata_port *ap) dma_free_coherent(dev, SATA_FSL_PORT_PRIV_DMA_SZ, pp->cmdslot, pp->cmdslot_paddr); - ata_pad_free(ap, dev); kfree(pp); } diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index 04b571764aff..6ebebde8454a 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -870,7 +870,7 @@ static void mv_start_dma(struct ata_port *ap, void __iomem *port_mmio, struct mv_host_priv *hpriv = ap->host->private_data; int hard_port = mv_hardport_from_port(ap->port_no); void __iomem *hc_mmio = mv_hc_base_from_port( - ap->host->iomap[MV_PRIMARY_BAR], hard_port); + mv_host_base(ap->host), hard_port); u32 hc_irq_cause, ipending; /* clear EDMA event indicators, if any */ @@ -1158,17 +1158,13 @@ static int mv_port_start(struct ata_port *ap) struct mv_port_priv *pp; void __iomem *port_mmio = mv_ap_base(ap); unsigned long flags; - int tag, rc; + int tag; pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL); if (!pp) return -ENOMEM; ap->private_data = pp; - rc = ata_pad_alloc(ap, dev); - if (rc) - return rc; - pp->crqb = dma_pool_alloc(hpriv->crqb_pool, GFP_KERNEL, &pp->crqb_dma); if (!pp->crqb) return -ENOMEM; @@ -1542,7 +1538,7 @@ static void mv_err_intr(struct ata_port *ap, struct ata_queued_cmd *qc) eh_freeze_mask = EDMA_EH_FREEZE_5; if (edma_err_cause & EDMA_ERR_SELF_DIS_5) { - struct mv_port_priv *pp = ap->private_data; + pp = ap->private_data; pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN; ata_ehi_push_desc(ehi, "EDMA self-disable"); } @@ -1550,7 +1546,7 @@ static void mv_err_intr(struct ata_port *ap, struct ata_queued_cmd *qc) eh_freeze_mask = EDMA_EH_FREEZE; if (edma_err_cause & EDMA_ERR_SELF_DIS) { - struct mv_port_priv *pp = ap->private_data; + pp = ap->private_data; pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN; ata_ehi_push_desc(ehi, "EDMA self-disable"); } @@ -2951,7 +2947,8 @@ static int mv_platform_probe(struct platform_device *pdev) hpriv->n_ports = n_ports; host->iomap = NULL; - hpriv->base = ioremap(res->start, res->end - res->start + 1); + hpriv->base = devm_ioremap(&pdev->dev, res->start, + res->end - res->start + 1); hpriv->base -= MV_SATAHC0_REG_BASE; rc = mv_create_dma_pools(hpriv, &pdev->dev); @@ -2983,11 +2980,8 @@ static int __devexit mv_platform_remove(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct ata_host *host = dev_get_drvdata(dev); - struct mv_host_priv *hpriv = host->private_data; - void __iomem *base = hpriv->base; ata_host_detach(host); - iounmap(base); return 0; } @@ -3198,6 +3192,7 @@ MODULE_DESCRIPTION("SCSI low-level driver for Marvell SATA controllers"); MODULE_LICENSE("GPL"); MODULE_DEVICE_TABLE(pci, mv_pci_tbl); MODULE_VERSION(DRV_VERSION); +MODULE_ALIAS("platform:sata_mv"); #ifdef CONFIG_PCI module_param(msi, int, 0444); diff --git a/drivers/ata/sata_promise.c b/drivers/ata/sata_promise.c index a07d319f6e8c..f251a5f569d5 100644 --- a/drivers/ata/sata_promise.c +++ b/drivers/ata/sata_promise.c @@ -543,7 +543,7 @@ static void pdc_fill_sg(struct ata_queued_cmd *qc) idx = 0; for_each_sg(qc->sg, sg, qc->n_elem, si) { u32 addr, offset; - u32 sg_len, len; + u32 sg_len; /* determine if physical DMA addr spans 64K boundary. * Note h/w doesn't support 64-bit, so we unconditionally diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c index b4b1f91ea693..df7988df7908 100644 --- a/drivers/ata/sata_sil24.c +++ b/drivers/ata/sata_sil24.c @@ -1234,7 +1234,6 @@ static int sil24_port_start(struct ata_port *ap) union sil24_cmd_block *cb; size_t cb_size = sizeof(*cb) * SIL24_MAX_CMDS; dma_addr_t cb_dma; - int rc; pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL); if (!pp) @@ -1247,10 +1246,6 @@ static int sil24_port_start(struct ata_port *ap) return -ENOMEM; memset(cb, 0, cb_size); - rc = ata_pad_alloc(ap, dev); - if (rc) - return rc; - pp->cmd_block = cb; pp->cmd_block_dma = cb_dma; diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c index 30caa0337190..0d03f44824fb 100644 --- a/drivers/ata/sata_via.c +++ b/drivers/ata/sata_via.c @@ -333,8 +333,8 @@ static int vt6420_prereset(struct ata_link *link, unsigned long deadline) static void vt6420_error_handler(struct ata_port *ap) { - return ata_bmdma_drive_eh(ap, vt6420_prereset, ata_std_softreset, - NULL, ata_std_postreset); + ata_bmdma_drive_eh(ap, vt6420_prereset, ata_std_softreset, NULL, + ata_std_postreset); } static int vt6421_pata_cable_detect(struct ata_port *ap) diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index bdc03f7e8424..a96ca86a7b4a 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -415,7 +415,7 @@ EXPORT_SYMBOL_GPL(device_power_down); * @dev: Device. * @state: Power state device is entering. */ -int suspend_device(struct device *dev, pm_message_t state) +static int suspend_device(struct device *dev, pm_message_t state) { int error = 0; diff --git a/drivers/block/swim3.c b/drivers/block/swim3.c index b4e462f154ea..730ccea78e45 100644 --- a/drivers/block/swim3.c +++ b/drivers/block/swim3.c @@ -251,10 +251,6 @@ static int floppy_release(struct inode *inode, struct file *filp); static int floppy_check_change(struct gendisk *disk); static int floppy_revalidate(struct gendisk *disk); -#ifndef CONFIG_PMAC_MEDIABAY -#define check_media_bay(which, what) 1 -#endif - static void swim3_select(struct floppy_state *fs, int sel) { struct swim3 __iomem *sw = fs->swim3; diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c index e68821d074b0..7e31d5f1bc8a 100644 --- a/drivers/bluetooth/hci_ldisc.c +++ b/drivers/bluetooth/hci_ldisc.c @@ -208,6 +208,7 @@ static int hci_uart_close(struct hci_dev *hdev) return 0; hci_uart_flush(hdev); + hdev->flush = NULL; return 0; } diff --git a/drivers/char/agp/amd-k7-agp.c b/drivers/char/agp/amd-k7-agp.c index 87be46406daf..d28669992147 100644 --- a/drivers/char/agp/amd-k7-agp.c +++ b/drivers/char/agp/amd-k7-agp.c @@ -41,6 +41,7 @@ static int amd_create_page_map(struct amd_page_map *page_map) if (page_map->real == NULL) return -ENOMEM; +#ifndef CONFIG_X86 SetPageReserved(virt_to_page(page_map->real)); global_cache_flush(); page_map->remapped = ioremap_nocache(virt_to_gart(page_map->real), @@ -52,6 +53,10 @@ static int amd_create_page_map(struct amd_page_map *page_map) return -ENOMEM; } global_cache_flush(); +#else + set_memory_uc((unsigned long)page_map->real, 1); + page_map->remapped = page_map->real; +#endif for (i = 0; i < PAGE_SIZE / sizeof(unsigned long); i++) { writel(agp_bridge->scratch_page, page_map->remapped+i); @@ -63,8 +68,12 @@ static int amd_create_page_map(struct amd_page_map *page_map) static void amd_free_page_map(struct amd_page_map *page_map) { +#ifndef CONFIG_X86 iounmap(page_map->remapped); ClearPageReserved(virt_to_page(page_map->real)); +#else + set_memory_wb((unsigned long)page_map->real, 1); +#endif free_page((unsigned long) page_map->real); } diff --git a/drivers/char/agp/ati-agp.c b/drivers/char/agp/ati-agp.c index 2d46b713c8f2..55c97f623242 100644 --- a/drivers/char/agp/ati-agp.c +++ b/drivers/char/agp/ati-agp.c @@ -60,18 +60,9 @@ static int ati_create_page_map(struct ati_page_map *page_map) if (page_map->real == NULL) return -ENOMEM; - SetPageReserved(virt_to_page(page_map->real)); + set_memory_uc((unsigned long)page_map->real, 1); err = map_page_into_agp(virt_to_page(page_map->real)); - page_map->remapped = ioremap_nocache(virt_to_gart(page_map->real), - PAGE_SIZE); - if (page_map->remapped == NULL || err) { - ClearPageReserved(virt_to_page(page_map->real)); - free_page((unsigned long) page_map->real); - page_map->real = NULL; - return -ENOMEM; - } - /*CACHE_FLUSH();*/ - global_cache_flush(); + page_map->remapped = page_map->real; for (i = 0; i < PAGE_SIZE / sizeof(unsigned long); i++) { writel(agp_bridge->scratch_page, page_map->remapped+i); @@ -85,8 +76,7 @@ static int ati_create_page_map(struct ati_page_map *page_map) static void ati_free_page_map(struct ati_page_map *page_map) { unmap_page_from_agp(virt_to_page(page_map->real)); - iounmap(page_map->remapped); - ClearPageReserved(virt_to_page(page_map->real)); + set_memory_wb((unsigned long)page_map->real, 1); free_page((unsigned long) page_map->real); } diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c index 7484bc759c4c..7fc0c99a3a58 100644 --- a/drivers/char/agp/generic.c +++ b/drivers/char/agp/generic.c @@ -932,9 +932,14 @@ int agp_generic_create_gatt_table(struct agp_bridge_data *bridge) agp_gatt_table = (void *)table; bridge->driver->cache_flush(); +#ifdef CONFIG_X86 + set_memory_uc((unsigned long)table, 1 << page_order); + bridge->gatt_table = (void *)table; +#else bridge->gatt_table = ioremap_nocache(virt_to_gart(table), (PAGE_SIZE * (1 << page_order))); bridge->driver->cache_flush(); +#endif if (bridge->gatt_table == NULL) { for (page = virt_to_page(table); page <= virt_to_page(table_end); page++) @@ -991,7 +996,11 @@ int agp_generic_free_gatt_table(struct agp_bridge_data *bridge) * called, then all agp memory is deallocated and removed * from the table. */ +#ifdef CONFIG_X86 + set_memory_wb((unsigned long)bridge->gatt_table, 1 << page_order); +#else iounmap(bridge->gatt_table); +#endif table = (char *) bridge->gatt_table_real; table_end = table + ((PAGE_SIZE * (1 << page_order)) - 1); diff --git a/drivers/char/agp/sis-agp.c b/drivers/char/agp/sis-agp.c index eb1a1c738190..b6791846809f 100644 --- a/drivers/char/agp/sis-agp.c +++ b/drivers/char/agp/sis-agp.c @@ -14,6 +14,9 @@ #define SIS_TLBCNTRL 0x97 #define SIS_TLBFLUSH 0x98 +#define PCI_DEVICE_ID_SI_662 0x0662 +#define PCI_DEVICE_ID_SI_671 0x0671 + static int __devinitdata agp_sis_force_delay = 0; static int __devinitdata agp_sis_agp_spec = -1; @@ -27,8 +30,8 @@ static int sis_fetch_size(void) values = A_SIZE_8(agp_bridge->driver->aperture_sizes); for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) { if ((temp_size == values[i].size_value) || - ((temp_size & ~(0x03)) == - (values[i].size_value & ~(0x03)))) { + ((temp_size & ~(0x07)) == + (values[i].size_value & ~(0x07)))) { agp_bridge->previous_size = agp_bridge->current_size = (void *) (values + i); @@ -214,6 +217,26 @@ static void __devexit agp_sis_remove(struct pci_dev *pdev) agp_put_bridge(bridge); } +#ifdef CONFIG_PM + +static int agp_sis_suspend(struct pci_dev *pdev, pm_message_t state) +{ + pci_save_state(pdev); + pci_set_power_state(pdev, pci_choose_state(pdev, state)); + + return 0; +} + +static int agp_sis_resume(struct pci_dev *pdev) +{ + pci_set_power_state(pdev, PCI_D0); + pci_restore_state(pdev); + + return sis_driver.configure(); +} + +#endif /* CONFIG_PM */ + static struct pci_device_id agp_sis_pci_table[] = { { .class = (PCI_CLASS_BRIDGE_HOST << 8), @@ -327,6 +350,22 @@ static struct pci_device_id agp_sis_pci_table[] = { .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, }, + { + .class = (PCI_CLASS_BRIDGE_HOST << 8), + .class_mask = ~0, + .vendor = PCI_VENDOR_ID_SI, + .device = PCI_DEVICE_ID_SI_662, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + }, + { + .class = (PCI_CLASS_BRIDGE_HOST << 8), + .class_mask = ~0, + .vendor = PCI_VENDOR_ID_SI, + .device = PCI_DEVICE_ID_SI_671, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + }, { .class = (PCI_CLASS_BRIDGE_HOST << 8), .class_mask = ~0, @@ -393,6 +432,10 @@ static struct pci_driver agp_sis_pci_driver = { .id_table = agp_sis_pci_table, .probe = agp_sis_probe, .remove = agp_sis_remove, +#ifdef CONFIG_PM + .suspend = agp_sis_suspend, + .resume = agp_sis_resume, +#endif }; static int __init agp_sis_init(void) diff --git a/drivers/char/agp/sworks-agp.c b/drivers/char/agp/sworks-agp.c index 551ef25063ef..e08934e58f32 100644 --- a/drivers/char/agp/sworks-agp.c +++ b/drivers/char/agp/sworks-agp.c @@ -52,28 +52,20 @@ static int serverworks_create_page_map(struct serverworks_page_map *page_map) if (page_map->real == NULL) { return -ENOMEM; } - SetPageReserved(virt_to_page(page_map->real)); - global_cache_flush(); - page_map->remapped = ioremap_nocache(virt_to_gart(page_map->real), - PAGE_SIZE); - if (page_map->remapped == NULL) { - ClearPageReserved(virt_to_page(page_map->real)); - free_page((unsigned long) page_map->real); - page_map->real = NULL; - return -ENOMEM; - } - global_cache_flush(); + + set_memory_uc((unsigned long)page_map->real, 1); + page_map->remapped = page_map->real; for (i = 0; i < PAGE_SIZE / sizeof(unsigned long); i++) writel(agp_bridge->scratch_page, page_map->remapped+i); + /* Red Pen: Everyone else does pci posting flush here */ return 0; } static void serverworks_free_page_map(struct serverworks_page_map *page_map) { - iounmap(page_map->remapped); - ClearPageReserved(virt_to_page(page_map->real)); + set_memory_wb((unsigned long)page_map->real, 1); free_page((unsigned long) page_map->real); } diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h index 19d3be5c4b2d..a6789f25009b 100644 --- a/drivers/char/drm/drmP.h +++ b/drivers/char/drm/drmP.h @@ -568,7 +568,7 @@ struct drm_driver { void (*postclose) (struct drm_device *, struct drm_file *); void (*lastclose) (struct drm_device *); int (*unload) (struct drm_device *); - int (*suspend) (struct drm_device *); + int (*suspend) (struct drm_device *, pm_message_t state); int (*resume) (struct drm_device *); int (*dma_ioctl) (struct drm_device *dev, void *data, struct drm_file *file_priv); void (*dma_ready) (struct drm_device *); diff --git a/drivers/char/drm/drm_pciids.h b/drivers/char/drm/drm_pciids.h index f52468843678..715b361f0c2b 100644 --- a/drivers/char/drm/drm_pciids.h +++ b/drivers/char/drm/drm_pciids.h @@ -83,6 +83,7 @@ {0x1002, 0x5460, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY}, \ {0x1002, 0x5462, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY}, \ {0x1002, 0x5464, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY}, \ + {0x1002, 0x5657, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_NEW_MEMMAP}, \ {0x1002, 0x5548, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \ {0x1002, 0x5549, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \ {0x1002, 0x554A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \ @@ -236,6 +237,7 @@ {0x1002, 0x7297, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV560|RADEON_NEW_MEMMAP}, \ {0x1002, 0x7834, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|RADEON_IS_IGP|RADEON_NEW_MEMMAP}, \ {0x1002, 0x7835, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x791e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS690|RADEON_IS_IGP|RADEON_NEW_MEMMAP|RADEON_IS_IGPGART}, \ {0, 0, 0} #define r128_PCI_IDS \ @@ -313,6 +315,7 @@ {0x1039, 0x5300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ {0x1039, 0x6300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ {0x1039, 0x6330, PCI_ANY_ID, PCI_ANY_ID, 0, 0, SIS_CHIP_315}, \ + {0x1039, 0x6351, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ {0x1039, 0x7300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ {0x18CA, 0x0040, PCI_ANY_ID, PCI_ANY_ID, 0, 0, SIS_CHIP_315}, \ {0x18CA, 0x0042, PCI_ANY_ID, PCI_ANY_ID, 0, 0, SIS_CHIP_315}, \ diff --git a/drivers/char/drm/drm_sysfs.c b/drivers/char/drm/drm_sysfs.c index fa36153619e8..05ed5043254f 100644 --- a/drivers/char/drm/drm_sysfs.c +++ b/drivers/char/drm/drm_sysfs.c @@ -36,7 +36,7 @@ static int drm_sysfs_suspend(struct device *dev, pm_message_t state) printk(KERN_ERR "%s\n", __FUNCTION__); if (drm_dev->driver->suspend) - return drm_dev->driver->suspend(drm_dev); + return drm_dev->driver->suspend(drm_dev, state); return 0; } diff --git a/drivers/char/drm/drm_vm.c b/drivers/char/drm/drm_vm.c index cea4105374b2..3d65c4dcd0c6 100644 --- a/drivers/char/drm/drm_vm.c +++ b/drivers/char/drm/drm_vm.c @@ -66,7 +66,7 @@ static pgprot_t drm_io_prot(uint32_t map_type, struct vm_area_struct *vma) } /** - * \c nopage method for AGP virtual memory. + * \c fault method for AGP virtual memory. * * \param vma virtual memory area. * \param address access address. @@ -76,8 +76,7 @@ static pgprot_t drm_io_prot(uint32_t map_type, struct vm_area_struct *vma) * map, get the page, increment the use count and return it. */ #if __OS_HAS_AGP -static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma, - unsigned long address) +static int drm_do_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) { struct drm_file *priv = vma->vm_file->private_data; struct drm_device *dev = priv->head->dev; @@ -89,19 +88,24 @@ static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma, * Find the right map */ if (!drm_core_has_AGP(dev)) - goto vm_nopage_error; + goto vm_fault_error; if (!dev->agp || !dev->agp->cant_use_aperture) - goto vm_nopage_error; + goto vm_fault_error; if (drm_ht_find_item(&dev->map_hash, vma->vm_pgoff, &hash)) - goto vm_nopage_error; + goto vm_fault_error; r_list = drm_hash_entry(hash, struct drm_map_list, hash); map = r_list->map; if (map && map->type == _DRM_AGP) { - unsigned long offset = address - vma->vm_start; + /* + * Using vm_pgoff as a selector forces us to use this unusual + * addressing scheme. + */ + unsigned long offset = (unsigned long)vmf->virtual_address - + vma->vm_start; unsigned long baddr = map->offset + offset; struct drm_agp_mem *agpmem; struct page *page; @@ -123,7 +127,7 @@ static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma, } if (!agpmem) - goto vm_nopage_error; + goto vm_fault_error; /* * Get the page, inc the use count, and return it @@ -131,22 +135,21 @@ static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma, offset = (baddr - agpmem->bound) >> PAGE_SHIFT; page = virt_to_page(__va(agpmem->memory->memory[offset])); get_page(page); + vmf->page = page; DRM_DEBUG ("baddr = 0x%lx page = 0x%p, offset = 0x%lx, count=%d\n", baddr, __va(agpmem->memory->memory[offset]), offset, page_count(page)); - - return page; + return 0; } - vm_nopage_error: - return NOPAGE_SIGBUS; /* Disallow mremap */ +vm_fault_error: + return VM_FAULT_SIGBUS; /* Disallow mremap */ } #else /* __OS_HAS_AGP */ -static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma, - unsigned long address) +static int drm_do_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) { - return NOPAGE_SIGBUS; + return VM_FAULT_SIGBUS; } #endif /* __OS_HAS_AGP */ @@ -160,28 +163,26 @@ static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma, * Get the mapping, find the real physical page to map, get the page, and * return it. */ -static __inline__ struct page *drm_do_vm_shm_nopage(struct vm_area_struct *vma, - unsigned long address) +static int drm_do_vm_shm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) { struct drm_map *map = (struct drm_map *) vma->vm_private_data; unsigned long offset; unsigned long i; struct page *page; - if (address > vma->vm_end) - return NOPAGE_SIGBUS; /* Disallow mremap */ if (!map) - return NOPAGE_SIGBUS; /* Nothing allocated */ + return VM_FAULT_SIGBUS; /* Nothing allocated */ - offset = address - vma->vm_start; + offset = (unsigned long)vmf->virtual_address - vma->vm_start; i = (unsigned long)map->handle + offset; page = vmalloc_to_page((void *)i); if (!page) - return NOPAGE_SIGBUS; + return VM_FAULT_SIGBUS; get_page(page); + vmf->page = page; - DRM_DEBUG("0x%lx\n", address); - return page; + DRM_DEBUG("shm_fault 0x%lx\n", offset); + return 0; } /** @@ -263,7 +264,7 @@ static void drm_vm_shm_close(struct vm_area_struct *vma) } /** - * \c nopage method for DMA virtual memory. + * \c fault method for DMA virtual memory. * * \param vma virtual memory area. * \param address access address. @@ -271,8 +272,7 @@ static void drm_vm_shm_close(struct vm_area_struct *vma) * * Determine the page number from the page offset and get it from drm_device_dma::pagelist. */ -static __inline__ struct page *drm_do_vm_dma_nopage(struct vm_area_struct *vma, - unsigned long address) +static int drm_do_vm_dma_fault(struct vm_area_struct *vma, struct vm_fault *vmf) { struct drm_file *priv = vma->vm_file->private_data; struct drm_device *dev = priv->head->dev; @@ -282,24 +282,23 @@ static __inline__ struct page *drm_do_vm_dma_nopage(struct vm_area_struct *vma, struct page *page; if (!dma) - return NOPAGE_SIGBUS; /* Error */ - if (address > vma->vm_end) - return NOPAGE_SIGBUS; /* Disallow mremap */ + return VM_FAULT_SIGBUS; /* Error */ if (!dma->pagelist) - return NOPAGE_SIGBUS; /* Nothing allocated */ + return VM_FAULT_SIGBUS; /* Nothing allocated */ - offset = address - vma->vm_start; /* vm_[pg]off[set] should be 0 */ - page_nr = offset >> PAGE_SHIFT; + offset = (unsigned long)vmf->virtual_address - vma->vm_start; /* vm_[pg]off[set] should be 0 */ + page_nr = offset >> PAGE_SHIFT; /* page_nr could just be vmf->pgoff */ page = virt_to_page((dma->pagelist[page_nr] + (offset & (~PAGE_MASK)))); get_page(page); + vmf->page = page; - DRM_DEBUG("0x%lx (page %lu)\n", address, page_nr); - return page; + DRM_DEBUG("dma_fault 0x%lx (page %lu)\n", offset, page_nr); + return 0; } /** - * \c nopage method for scatter-gather virtual memory. + * \c fault method for scatter-gather virtual memory. * * \param vma virtual memory area. * \param address access address. @@ -307,8 +306,7 @@ static __inline__ struct page *drm_do_vm_dma_nopage(struct vm_area_struct *vma, * * Determine the map offset from the page offset and get it from drm_sg_mem::pagelist. */ -static __inline__ struct page *drm_do_vm_sg_nopage(struct vm_area_struct *vma, - unsigned long address) +static int drm_do_vm_sg_fault(struct vm_area_struct *vma, struct vm_fault *vmf) { struct drm_map *map = (struct drm_map *) vma->vm_private_data; struct drm_file *priv = vma->vm_file->private_data; @@ -320,77 +318,64 @@ static __inline__ struct page *drm_do_vm_sg_nopage(struct vm_area_struct *vma, struct page *page; if (!entry) - return NOPAGE_SIGBUS; /* Error */ - if (address > vma->vm_end) - return NOPAGE_SIGBUS; /* Disallow mremap */ + return VM_FAULT_SIGBUS; /* Error */ if (!entry->pagelist) - return NOPAGE_SIGBUS; /* Nothing allocated */ + return VM_FAULT_SIGBUS; /* Nothing allocated */ - offset = address - vma->vm_start; + offset = (unsigned long)vmf->virtual_address - vma->vm_start; map_offset = map->offset - (unsigned long)dev->sg->virtual; page_offset = (offset >> PAGE_SHIFT) + (map_offset >> PAGE_SHIFT); page = entry->pagelist[page_offset]; get_page(page); + vmf->page = page; - return page; + return 0; } -static struct page *drm_vm_nopage(struct vm_area_struct *vma, - unsigned long address, int *type) +static int drm_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) { - if (type) - *type = VM_FAULT_MINOR; - return drm_do_vm_nopage(vma, address); + return drm_do_vm_fault(vma, vmf); } -static struct page *drm_vm_shm_nopage(struct vm_area_struct *vma, - unsigned long address, int *type) +static int drm_vm_shm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) { - if (type) - *type = VM_FAULT_MINOR; - return drm_do_vm_shm_nopage(vma, address); + return drm_do_vm_shm_fault(vma, vmf); } -static struct page *drm_vm_dma_nopage(struct vm_area_struct *vma, - unsigned long address, int *type) +static int drm_vm_dma_fault(struct vm_area_struct *vma, struct vm_fault *vmf) { - if (type) - *type = VM_FAULT_MINOR; - return drm_do_vm_dma_nopage(vma, address); + return drm_do_vm_dma_fault(vma, vmf); } -static struct page *drm_vm_sg_nopage(struct vm_area_struct *vma, - unsigned long address, int *type) +static int drm_vm_sg_fault(struct vm_area_struct *vma, struct vm_fault *vmf) { - if (type) - *type = VM_FAULT_MINOR; - return drm_do_vm_sg_nopage(vma, address); + return drm_do_vm_sg_fault(vma, vmf); } /** AGP virtual memory operations */ static struct vm_operations_struct drm_vm_ops = { - .nopage = drm_vm_nopage, + .fault = drm_vm_fault, .open = drm_vm_open, .close = drm_vm_close, }; /** Shared virtual memory operations */ static struct vm_operations_struct drm_vm_shm_ops = { - .nopage = drm_vm_shm_nopage, + .fault = drm_vm_shm_fault, .open = drm_vm_open, .close = drm_vm_shm_close, }; /** DMA virtual memory operations */ static struct vm_operations_struct drm_vm_dma_ops = { - .nopage = drm_vm_dma_nopage, + .fault = drm_vm_dma_fault, .open = drm_vm_open, .close = drm_vm_close, }; /** Scatter-gather virtual memory operations */ static struct vm_operations_struct drm_vm_sg_ops = { - .nopage = drm_vm_sg_nopage, + .fault = drm_vm_sg_fault, .open = drm_vm_open, .close = drm_vm_close, }; @@ -604,7 +589,7 @@ static int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma) /* * On some platforms we can't talk to bus dma address from the CPU, so for * memory of type DRM_AGP, we'll deal with sorting out the real physical - * pages and mappings in nopage() + * pages and mappings in fault() */ #if defined(__powerpc__) pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE; @@ -634,7 +619,7 @@ static int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma) break; case _DRM_CONSISTENT: /* Consistent memory is really like shared memory. But - * it's allocated in a different way, so avoid nopage */ + * it's allocated in a different way, so avoid fault */ if (remap_pfn_range(vma, vma->vm_start, page_to_pfn(virt_to_page(map->handle)), vma->vm_end - vma->vm_start, vma->vm_page_prot)) diff --git a/drivers/char/drm/i915_dma.c b/drivers/char/drm/i915_dma.c index 43986d81ae34..e9d6663bec73 100644 --- a/drivers/char/drm/i915_dma.c +++ b/drivers/char/drm/i915_dma.c @@ -171,7 +171,7 @@ static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init) dev_priv->allow_batchbuffer = 1; /* Program Hardware Status Page */ - if (!IS_G33(dev)) { + if (!I915_NEED_GFX_HWS(dev)) { dev_priv->status_page_dmah = drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE, 0xffffffff); @@ -720,6 +720,9 @@ static int i915_set_status_page(struct drm_device *dev, void *data, drm_i915_private_t *dev_priv = dev->dev_private; drm_i915_hws_addr_t *hws = data; + if (!I915_NEED_GFX_HWS(dev)) + return -EINVAL; + if (!dev_priv) { DRM_ERROR("called with no initialization\n"); return -EINVAL; diff --git a/drivers/char/drm/i915_drv.c b/drivers/char/drm/i915_drv.c index 52e51033d32c..4048f39b7eed 100644 --- a/drivers/char/drm/i915_drv.c +++ b/drivers/char/drm/i915_drv.c @@ -160,6 +160,7 @@ static void i915_save_vga(struct drm_device *dev) dev_priv->saveAR[i] = i915_read_ar(st01, i, 0); inb(st01); outb(dev_priv->saveAR_INDEX, VGA_AR_INDEX); + inb(st01); /* Graphics controller registers */ for (i = 0; i < 9; i++) @@ -225,6 +226,7 @@ static void i915_restore_vga(struct drm_device *dev) i915_write_ar(st01, i, dev_priv->saveAR[i], 0); inb(st01); /* switch back to index mode */ outb(dev_priv->saveAR_INDEX | 0x20, VGA_AR_INDEX); + inb(st01); /* VGA color palette registers */ outb(dev_priv->saveDACMASK, VGA_DACMASK); @@ -236,7 +238,7 @@ static void i915_restore_vga(struct drm_device *dev) } -static int i915_suspend(struct drm_device *dev) +static int i915_suspend(struct drm_device *dev, pm_message_t state) { struct drm_i915_private *dev_priv = dev->dev_private; int i; @@ -247,6 +249,9 @@ static int i915_suspend(struct drm_device *dev) return -ENODEV; } + if (state.event == PM_EVENT_PRETHAW) + return 0; + pci_save_state(dev->pdev); pci_read_config_byte(dev->pdev, LBB, &dev_priv->saveLBB); @@ -276,6 +281,7 @@ static int i915_suspend(struct drm_device *dev) dev_priv->saveDSPATILEOFF = I915_READ(DSPATILEOFF); } i915_save_palette(dev, PIPE_A); + dev_priv->savePIPEASTAT = I915_READ(I915REG_PIPEASTAT); /* Pipe & plane B info */ dev_priv->savePIPEBCONF = I915_READ(PIPEBCONF); @@ -303,6 +309,7 @@ static int i915_suspend(struct drm_device *dev) dev_priv->saveDSPBTILEOFF = I915_READ(DSPBTILEOFF); } i915_save_palette(dev, PIPE_B); + dev_priv->savePIPEBSTAT = I915_READ(I915REG_PIPEBSTAT); /* CRT state */ dev_priv->saveADPA = I915_READ(ADPA); @@ -329,12 +336,26 @@ static int i915_suspend(struct drm_device *dev) dev_priv->saveFBC_CONTROL2 = I915_READ(FBC_CONTROL2); dev_priv->saveFBC_CONTROL = I915_READ(FBC_CONTROL); + /* Interrupt state */ + dev_priv->saveIIR = I915_READ(I915REG_INT_IDENTITY_R); + dev_priv->saveIER = I915_READ(I915REG_INT_ENABLE_R); + dev_priv->saveIMR = I915_READ(I915REG_INT_MASK_R); + /* VGA state */ dev_priv->saveVCLK_DIVISOR_VGA0 = I915_READ(VCLK_DIVISOR_VGA0); dev_priv->saveVCLK_DIVISOR_VGA1 = I915_READ(VCLK_DIVISOR_VGA1); dev_priv->saveVCLK_POST_DIV = I915_READ(VCLK_POST_DIV); dev_priv->saveVGACNTRL = I915_READ(VGACNTRL); + /* Clock gating state */ + dev_priv->saveDSPCLK_GATE_D = I915_READ(DSPCLK_GATE_D); + + /* Cache mode state */ + dev_priv->saveCACHE_MODE_0 = I915_READ(CACHE_MODE_0); + + /* Memory Arbitration state */ + dev_priv->saveMI_ARB_STATE = I915_READ(MI_ARB_STATE); + /* Scratch space */ for (i = 0; i < 16; i++) { dev_priv->saveSWF0[i] = I915_READ(SWF0 + (i << 2)); @@ -345,9 +366,11 @@ static int i915_suspend(struct drm_device *dev) i915_save_vga(dev); - /* Shut down the device */ - pci_disable_device(dev->pdev); - pci_set_power_state(dev->pdev, PCI_D3hot); + if (state.event == PM_EVENT_SUSPEND) { + /* Shut down the device */ + pci_disable_device(dev->pdev); + pci_set_power_state(dev->pdev, PCI_D3hot); + } return 0; } @@ -400,9 +423,7 @@ static int i915_resume(struct drm_device *dev) I915_WRITE(DSPATILEOFF, dev_priv->saveDSPATILEOFF); } - if ((dev_priv->saveDPLL_A & DPLL_VCO_ENABLE) && - (dev_priv->saveDPLL_A & DPLL_VGA_MODE_DIS)) - I915_WRITE(PIPEACONF, dev_priv->savePIPEACONF); + I915_WRITE(PIPEACONF, dev_priv->savePIPEACONF); i915_restore_palette(dev, PIPE_A); /* Enable the plane */ @@ -444,10 +465,9 @@ static int i915_resume(struct drm_device *dev) I915_WRITE(DSPBTILEOFF, dev_priv->saveDSPBTILEOFF); } - if ((dev_priv->saveDPLL_B & DPLL_VCO_ENABLE) && - (dev_priv->saveDPLL_B & DPLL_VGA_MODE_DIS)) - I915_WRITE(PIPEBCONF, dev_priv->savePIPEBCONF); - i915_restore_palette(dev, PIPE_A); + I915_WRITE(PIPEBCONF, dev_priv->savePIPEBCONF); + + i915_restore_palette(dev, PIPE_B); /* Enable the plane */ I915_WRITE(DSPBCNTR, dev_priv->saveDSPBCNTR); I915_WRITE(DSPBBASE, I915_READ(DSPBBASE)); @@ -485,6 +505,15 @@ static int i915_resume(struct drm_device *dev) I915_WRITE(VCLK_POST_DIV, dev_priv->saveVCLK_POST_DIV); udelay(150); + /* Clock gating state */ + I915_WRITE (DSPCLK_GATE_D, dev_priv->saveDSPCLK_GATE_D); + + /* Cache mode state */ + I915_WRITE (CACHE_MODE_0, dev_priv->saveCACHE_MODE_0 | 0xffff0000); + + /* Memory arbitration state */ + I915_WRITE (MI_ARB_STATE, dev_priv->saveMI_ARB_STATE | 0xffff0000); + for (i = 0; i < 16; i++) { I915_WRITE(SWF0 + (i << 2), dev_priv->saveSWF0[i]); I915_WRITE(SWF10 + (i << 2), dev_priv->saveSWF1[i+7]); diff --git a/drivers/char/drm/i915_drv.h b/drivers/char/drm/i915_drv.h index f8308bfb2613..c10d128e34db 100644 --- a/drivers/char/drm/i915_drv.h +++ b/drivers/char/drm/i915_drv.h @@ -134,6 +134,7 @@ typedef struct drm_i915_private { u32 saveVBLANK_A; u32 saveVSYNC_A; u32 saveBCLRPAT_A; + u32 savePIPEASTAT; u32 saveDSPASTRIDE; u32 saveDSPASIZE; u32 saveDSPAPOS; @@ -154,6 +155,7 @@ typedef struct drm_i915_private { u32 saveVBLANK_B; u32 saveVSYNC_B; u32 saveBCLRPAT_B; + u32 savePIPEBSTAT; u32 saveDSPBSTRIDE; u32 saveDSPBSIZE; u32 saveDSPBPOS; @@ -182,6 +184,12 @@ typedef struct drm_i915_private { u32 saveFBC_LL_BASE; u32 saveFBC_CONTROL; u32 saveFBC_CONTROL2; + u32 saveIER; + u32 saveIIR; + u32 saveIMR; + u32 saveCACHE_MODE_0; + u32 saveDSPCLK_GATE_D; + u32 saveMI_ARB_STATE; u32 saveSWF0[16]; u32 saveSWF1[16]; u32 saveSWF2[3]; @@ -450,6 +458,10 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); */ #define DMA_FADD_S 0x20d4 +/* Memory Interface Arbitration State + */ +#define MI_ARB_STATE 0x20e4 + /* Cache mode 0 reg. * - Manipulating render cache behaviour is central * to the concept of zone rendering, tuning this reg can help avoid @@ -460,6 +472,7 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); * bit of interest either set or cleared. EG: (BIT<<16) | BIT to set. */ #define Cache_Mode_0 0x2120 +#define CACHE_MODE_0 0x2120 #define CM0_MASK_SHIFT 16 #define CM0_IZ_OPT_DISABLE (1<<6) #define CM0_ZR_OPT_DISABLE (1<<5) @@ -655,6 +668,8 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); /** P1 value is 2 greater than this field */ # define VGA0_PD_P1_MASK (0x1f << 0) +#define DSPCLK_GATE_D 0x6200 + /* I830 CRTC registers */ #define HTOTAL_A 0x60000 #define HBLANK_A 0x60004 @@ -1101,6 +1116,8 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); #define IS_MOBILE(dev) (IS_I830(dev) || IS_I85X(dev) || IS_I915GM(dev) || \ IS_I945GM(dev) || IS_I965GM(dev) || IS_IGD_GM(dev)) +#define I915_NEED_GFX_HWS(dev) (IS_G33(dev) || IS_IGD_GM(dev)) + #define PRIMARY_RINGBUFFER_SIZE (128*1024) #endif diff --git a/drivers/char/drm/radeon_cp.c b/drivers/char/drm/radeon_cp.c index 5dc799ab86b8..833abc7e55fb 100644 --- a/drivers/char/drm/radeon_cp.c +++ b/drivers/char/drm/radeon_cp.c @@ -825,11 +825,19 @@ static u32 RADEON_READ_MCIND(drm_radeon_private_t *dev_priv, int addr) return ret; } +static u32 RS690_READ_MCIND(drm_radeon_private_t *dev_priv, int addr) +{ + RADEON_WRITE(RS690_MC_INDEX, (addr & RS690_MC_INDEX_MASK)); + return RADEON_READ(RS690_MC_DATA); +} + u32 radeon_read_fb_location(drm_radeon_private_t *dev_priv) { if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515) return RADEON_READ_MCIND(dev_priv, RV515_MC_FB_LOCATION); + else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) + return RS690_READ_MCIND(dev_priv, RS690_MC_FB_LOCATION); else if ((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_RV515) return RADEON_READ_MCIND(dev_priv, R520_MC_FB_LOCATION); else @@ -840,6 +848,8 @@ static void radeon_write_fb_location(drm_radeon_private_t *dev_priv, u32 fb_loc) { if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515) RADEON_WRITE_MCIND(RV515_MC_FB_LOCATION, fb_loc); + else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) + RS690_WRITE_MCIND(RS690_MC_FB_LOCATION, fb_loc); else if ((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_RV515) RADEON_WRITE_MCIND(R520_MC_FB_LOCATION, fb_loc); else @@ -850,6 +860,8 @@ static void radeon_write_agp_location(drm_radeon_private_t *dev_priv, u32 agp_lo { if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515) RADEON_WRITE_MCIND(RV515_MC_AGP_LOCATION, agp_loc); + else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) + RS690_WRITE_MCIND(RS690_MC_AGP_LOCATION, agp_loc); else if ((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_RV515) RADEON_WRITE_MCIND(R520_MC_AGP_LOCATION, agp_loc); else @@ -1362,6 +1374,70 @@ static void radeon_set_igpgart(drm_radeon_private_t * dev_priv, int on) } } +/* Enable or disable RS690 GART on the chip */ +static void radeon_set_rs690gart(drm_radeon_private_t *dev_priv, int on) +{ + u32 temp; + + if (on) { + DRM_DEBUG("programming rs690 gart %08X %08lX %08X\n", + dev_priv->gart_vm_start, + (long)dev_priv->gart_info.bus_addr, + dev_priv->gart_size); + + temp = RS690_READ_MCIND(dev_priv, RS690_MC_MISC_CNTL); + RS690_WRITE_MCIND(RS690_MC_MISC_CNTL, 0x5000); + + RS690_WRITE_MCIND(RS690_MC_AGP_SIZE, + RS690_MC_GART_EN | RS690_MC_AGP_SIZE_32MB); + + temp = RS690_READ_MCIND(dev_priv, RS690_MC_GART_FEATURE_ID); + RS690_WRITE_MCIND(RS690_MC_GART_FEATURE_ID, 0x42040800); + + RS690_WRITE_MCIND(RS690_MC_GART_BASE, + dev_priv->gart_info.bus_addr); + + temp = RS690_READ_MCIND(dev_priv, RS690_MC_AGP_MODE_CONTROL); + RS690_WRITE_MCIND(RS690_MC_AGP_MODE_CONTROL, 0x01400000); + + RS690_WRITE_MCIND(RS690_MC_AGP_BASE, + (unsigned int)dev_priv->gart_vm_start); + + dev_priv->gart_size = 32*1024*1024; + temp = (((dev_priv->gart_vm_start - 1 + dev_priv->gart_size) & + 0xffff0000) | (dev_priv->gart_vm_start >> 16)); + + RS690_WRITE_MCIND(RS690_MC_AGP_LOCATION, temp); + + temp = RS690_READ_MCIND(dev_priv, RS690_MC_AGP_SIZE); + RS690_WRITE_MCIND(RS690_MC_AGP_SIZE, + RS690_MC_GART_EN | RS690_MC_AGP_SIZE_32MB); + + do { + temp = RS690_READ_MCIND(dev_priv, RS690_MC_GART_CACHE_CNTL); + if ((temp & RS690_MC_GART_CLEAR_STATUS) == + RS690_MC_GART_CLEAR_DONE) + break; + DRM_UDELAY(1); + } while (1); + + RS690_WRITE_MCIND(RS690_MC_GART_CACHE_CNTL, + RS690_MC_GART_CC_CLEAR); + do { + temp = RS690_READ_MCIND(dev_priv, RS690_MC_GART_CACHE_CNTL); + if ((temp & RS690_MC_GART_CLEAR_STATUS) == + RS690_MC_GART_CLEAR_DONE) + break; + DRM_UDELAY(1); + } while (1); + + RS690_WRITE_MCIND(RS690_MC_GART_CACHE_CNTL, + RS690_MC_GART_CC_NO_CHANGE); + } else { + RS690_WRITE_MCIND(RS690_MC_AGP_SIZE, RS690_MC_GART_DIS); + } +} + static void radeon_set_pciegart(drm_radeon_private_t * dev_priv, int on) { u32 tmp = RADEON_READ_PCIE(dev_priv, RADEON_PCIE_TX_GART_CNTL); @@ -1396,6 +1472,11 @@ static void radeon_set_pcigart(drm_radeon_private_t * dev_priv, int on) { u32 tmp; + if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) { + radeon_set_rs690gart(dev_priv, on); + return; + } + if (dev_priv->flags & RADEON_IS_IGPGART) { radeon_set_igpgart(dev_priv, on); return; diff --git a/drivers/char/drm/radeon_drv.h b/drivers/char/drm/radeon_drv.h index 4434332c79bc..173ae620223a 100644 --- a/drivers/char/drm/radeon_drv.h +++ b/drivers/char/drm/radeon_drv.h @@ -123,6 +123,7 @@ enum radeon_family { CHIP_R420, CHIP_RV410, CHIP_RS400, + CHIP_RS690, CHIP_RV515, CHIP_R520, CHIP_RV530, @@ -467,6 +468,36 @@ extern int r300_do_cp_cmdbuf(struct drm_device * dev, #define RADEON_IGPGART_ENABLE 0x38 #define RADEON_IGPGART_UNK_39 0x39 +#define RS690_MC_INDEX 0x78 +# define RS690_MC_INDEX_MASK 0x1ff +# define RS690_MC_INDEX_WR_EN (1 << 9) +# define RS690_MC_INDEX_WR_ACK 0x7f +#define RS690_MC_DATA 0x7c + +#define RS690_MC_MISC_CNTL 0x18 +#define RS690_MC_GART_FEATURE_ID 0x2b +#define RS690_MC_GART_BASE 0x2c +#define RS690_MC_GART_CACHE_CNTL 0x2e +# define RS690_MC_GART_CC_NO_CHANGE 0x0 +# define RS690_MC_GART_CC_CLEAR 0x1 +# define RS690_MC_GART_CLEAR_STATUS (1 << 1) +# define RS690_MC_GART_CLEAR_DONE (0 << 1) +# define RS690_MC_GART_CLEAR_PENDING (1 << 1) +#define RS690_MC_AGP_SIZE 0x38 +# define RS690_MC_GART_DIS 0x0 +# define RS690_MC_GART_EN 0x1 +# define RS690_MC_AGP_SIZE_32MB (0 << 1) +# define RS690_MC_AGP_SIZE_64MB (1 << 1) +# define RS690_MC_AGP_SIZE_128MB (2 << 1) +# define RS690_MC_AGP_SIZE_256MB (3 << 1) +# define RS690_MC_AGP_SIZE_512MB (4 << 1) +# define RS690_MC_AGP_SIZE_1GB (5 << 1) +# define RS690_MC_AGP_SIZE_2GB (6 << 1) +#define RS690_MC_AGP_MODE_CONTROL 0x39 +#define RS690_MC_FB_LOCATION 0x100 +#define RS690_MC_AGP_LOCATION 0x101 +#define RS690_MC_AGP_BASE 0x102 + #define R520_MC_IND_INDEX 0x70 #define R520_MC_IND_WR_EN (1<<24) #define R520_MC_IND_DATA 0x74 @@ -1076,6 +1107,13 @@ do { \ RADEON_WRITE(R520_MC_IND_INDEX, 0); \ } while (0) +#define RS690_WRITE_MCIND( addr, val ) \ +do { \ + RADEON_WRITE(RS690_MC_INDEX, RS690_MC_INDEX_WR_EN | ((addr) & RS690_MC_INDEX_MASK)); \ + RADEON_WRITE(RS690_MC_DATA, val); \ + RADEON_WRITE(RS690_MC_INDEX, RS690_MC_INDEX_WR_ACK); \ +} while (0) + #define CP_PACKET0( reg, n ) \ (RADEON_CP_PACKET0 | ((n) << 16) | ((reg) >> 2)) #define CP_PACKET0_TABLE( reg, n ) \ diff --git a/drivers/char/hvc_rtas.c b/drivers/char/hvc_rtas.c index bb09413d5a21..88590d040046 100644 --- a/drivers/char/hvc_rtas.c +++ b/drivers/char/hvc_rtas.c @@ -76,7 +76,7 @@ static struct hv_ops hvc_rtas_get_put_ops = { .put_chars = hvc_rtas_write_console, }; -static int hvc_rtas_init(void) +static int __init hvc_rtas_init(void) { struct hvc_struct *hp; diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index 60f71e6345e3..d73663a52324 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -219,7 +219,8 @@ static void poll_idle_init(struct cpuidle_device *dev) cpuidle_set_statedata(state, NULL); - snprintf(state->name, CPUIDLE_NAME_LEN, "C0 (poll idle)"); + snprintf(state->name, CPUIDLE_NAME_LEN, "C0"); + snprintf(state->desc, CPUIDLE_DESC_LEN, "CPUIDLE CORE POLL IDLE"); state->exit_latency = 0; state->target_residency = 0; state->power_usage = -1; diff --git a/drivers/cpuidle/sysfs.c b/drivers/cpuidle/sysfs.c index 088ea74edd34..69102ca05685 100644 --- a/drivers/cpuidle/sysfs.c +++ b/drivers/cpuidle/sysfs.c @@ -218,16 +218,23 @@ static ssize_t show_state_##_name(struct cpuidle_state *state, char *buf) \ return sprintf(buf, "%u\n", state->_name);\ } -static ssize_t show_state_name(struct cpuidle_state *state, char *buf) -{ - return sprintf(buf, "%s\n", state->name); +#define define_show_state_str_function(_name) \ +static ssize_t show_state_##_name(struct cpuidle_state *state, char *buf) \ +{ \ + if (state->_name[0] == '\0')\ + return sprintf(buf, "\n");\ + return sprintf(buf, "%s\n", state->_name);\ } define_show_state_function(exit_latency) define_show_state_function(power_usage) define_show_state_function(usage) define_show_state_function(time) +define_show_state_str_function(name) +define_show_state_str_function(desc) + define_one_state_ro(name, show_state_name); +define_one_state_ro(desc, show_state_desc); define_one_state_ro(latency, show_state_exit_latency); define_one_state_ro(power, show_state_power_usage); define_one_state_ro(usage, show_state_usage); @@ -235,6 +242,7 @@ define_one_state_ro(time, show_state_time); static struct attribute *cpuidle_state_default_attrs[] = { &attr_name.attr, + &attr_desc.attr, &attr_latency.attr, &attr_power.attr, &attr_usage.attr, diff --git a/drivers/crypto/hifn_795x.c b/drivers/crypto/hifn_795x.c index dfbf24c4033c..3110bf7014f7 100644 --- a/drivers/crypto/hifn_795x.c +++ b/drivers/crypto/hifn_795x.c @@ -463,7 +463,7 @@ struct hifn_device unsigned int pk_clk_freq; -#ifdef CRYPTO_DEV_HIFN_795X_RNG +#ifdef CONFIG_CRYPTO_DEV_HIFN_795X_RNG unsigned int rng_wait_time; ktime_t rngtime; struct hwrng rng; @@ -795,7 +795,7 @@ static struct pci2id { } }; -#ifdef CRYPTO_DEV_HIFN_795X_RNG +#ifdef CONFIG_CRYPTO_DEV_HIFN_795X_RNG static int hifn_rng_data_present(struct hwrng *rng, int wait) { struct hifn_device *dev = (struct hifn_device *)rng->priv; @@ -880,7 +880,7 @@ static int hifn_init_pubrng(struct hifn_device *dev) dprintk("Chip %s: RNG engine has been successfully initialised.\n", dev->name); -#ifdef CRYPTO_DEV_HIFN_795X_RNG +#ifdef CONFIG_CRYPTO_DEV_HIFN_795X_RNG /* First value must be discarded */ hifn_read_1(dev, HIFN_1_RNG_DATA); dev->rngtime = ktime_get(); diff --git a/drivers/hid/hid-input-quirks.c b/drivers/hid/hid-input-quirks.c index a870ba58faa3..dceadd0c1419 100644 --- a/drivers/hid/hid-input-quirks.c +++ b/drivers/hid/hid-input-quirks.c @@ -352,7 +352,7 @@ int hidinput_mapping_quirks(struct hid_usage *usage, return 0; } -void hidinput_event_quirks(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value) +int hidinput_event_quirks(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value) { struct input_dev *input; @@ -362,34 +362,34 @@ void hidinput_event_quirks(struct hid_device *hid, struct hid_field *field, stru || ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_7) && (usage->hid == 0x00090007))) { if (value) hid->quirks |= HID_QUIRK_2WHEEL_MOUSE_HACK_ON; else hid->quirks &= ~HID_QUIRK_2WHEEL_MOUSE_HACK_ON; - return; + return 1; } if ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_B8) && (usage->type == EV_REL) && (usage->code == REL_WHEEL)) { hid->delayed_value = value; - return; + return 1; } if ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_B8) && (usage->hid == 0x000100b8)) { input_event(input, EV_REL, value ? REL_HWHEEL : REL_WHEEL, hid->delayed_value); - return; + return 1; } if ((hid->quirks & HID_QUIRK_INVERT_HWHEEL) && (usage->code == REL_HWHEEL)) { input_event(input, usage->type, usage->code, -value); - return; + return 1; } if ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_ON) && (usage->code == REL_WHEEL)) { input_event(input, usage->type, REL_HWHEEL, value); - return; + return 1; } if ((hid->quirks & HID_QUIRK_APPLE_HAS_FN) && hidinput_apple_event(hid, input, usage, value)) - return; + return 1; /* Handling MS keyboards special buttons */ if (hid->quirks & HID_QUIRK_MICROSOFT_KEYS && @@ -416,8 +416,9 @@ void hidinput_event_quirks(struct hid_device *hid, struct hid_field *field, stru if (hid->quirks & HID_QUIRK_HWHEEL_WHEEL_INVERT && usage->type == EV_REL && usage->code == REL_HWHEEL) { input_event(input, usage->type, REL_WHEEL, -value); - return; + return 1; } + return 0; } diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index 5325d98b4328..5a38fb27d69f 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c @@ -97,6 +97,7 @@ struct hidinput_key_translation { #define APPLE_FLAG_FKEY 0x01 static struct hidinput_key_translation apple_fn_keys[] = { + { KEY_BACKSPACE, KEY_DELETE }, { KEY_F1, KEY_BRIGHTNESSDOWN, APPLE_FLAG_FKEY }, { KEY_F2, KEY_BRIGHTNESSUP, APPLE_FLAG_FKEY }, { KEY_F3, KEY_CYCLEWINDOWS, APPLE_FLAG_FKEY }, /* Exposé */ @@ -109,6 +110,10 @@ static struct hidinput_key_translation apple_fn_keys[] = { { KEY_F10, KEY_MUTE, APPLE_FLAG_FKEY }, { KEY_F11, KEY_VOLUMEDOWN, APPLE_FLAG_FKEY }, { KEY_F12, KEY_VOLUMEUP, APPLE_FLAG_FKEY }, + { KEY_UP, KEY_PAGEUP }, + { KEY_DOWN, KEY_PAGEDOWN }, + { KEY_LEFT, KEY_HOME }, + { KEY_RIGHT, KEY_END }, { } }; @@ -854,7 +859,8 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct return; /* handle input events for quirky devices */ - hidinput_event_quirks(hid, field, usage, value); + if (hidinput_event_quirks(hid, field, usage, value)) + return; if (usage->hat_min < usage->hat_max || usage->hat_dir) { int hat_dir = usage->hat_dir; diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index b77b61e0cd7b..e6d05f6b1c1c 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c @@ -66,6 +66,12 @@ #define USB_DEVICE_ID_APPLE_ALU_ANSI 0x0220 #define USB_DEVICE_ID_APPLE_ALU_ISO 0x0221 #define USB_DEVICE_ID_APPLE_ALU_JIS 0x0222 +#define USB_DEVICE_ID_APPLE_GEYSER4_HF_ANSI 0x0229 +#define USB_DEVICE_ID_APPLE_GEYSER4_HF_ISO 0x022a +#define USB_DEVICE_ID_APPLE_GEYSER4_HF_JIS 0x022b +#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI 0x022c +#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_ISO 0x022d +#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS 0x022e #define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY 0x030a #define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY 0x030b #define USB_DEVICE_ID_APPLE_IRCONTROL4 0x8242 @@ -193,6 +199,17 @@ #define USB_DEVICE_ID_GTCO_502 0x0502 #define USB_DEVICE_ID_GTCO_503 0x0503 #define USB_DEVICE_ID_GTCO_504 0x0504 +#define USB_DEVICE_ID_GTCO_600 0x0600 +#define USB_DEVICE_ID_GTCO_601 0x0601 +#define USB_DEVICE_ID_GTCO_602 0x0602 +#define USB_DEVICE_ID_GTCO_603 0x0603 +#define USB_DEVICE_ID_GTCO_604 0x0604 +#define USB_DEVICE_ID_GTCO_605 0x0605 +#define USB_DEVICE_ID_GTCO_606 0x0606 +#define USB_DEVICE_ID_GTCO_607 0x0607 +#define USB_DEVICE_ID_GTCO_608 0x0608 +#define USB_DEVICE_ID_GTCO_609 0x0609 +#define USB_DEVICE_ID_GTCO_609 0x0609 #define USB_DEVICE_ID_GTCO_1000 0x1000 #define USB_DEVICE_ID_GTCO_1001 0x1001 #define USB_DEVICE_ID_GTCO_1002 0x1002 @@ -200,7 +217,7 @@ #define USB_DEVICE_ID_GTCO_1004 0x1004 #define USB_DEVICE_ID_GTCO_1005 0x1005 #define USB_DEVICE_ID_GTCO_1006 0x1006 - +#define USB_DEVICE_ID_GTCO_1007 0x1007 #define USB_VENDOR_ID_HAPP 0x078b #define USB_DEVICE_ID_UGCI_DRIVING 0x0010 #define USB_DEVICE_ID_UGCI_FLYING 0x0020 @@ -368,6 +385,7 @@ #define USB_DEVICE_ID_VERNIER_GOTEMP 0x0002 #define USB_DEVICE_ID_VERNIER_SKIP 0x0003 #define USB_DEVICE_ID_VERNIER_CYCLOPS 0x0004 +#define USB_DEVICE_ID_VERNIER_LCSPEC 0x0006 #define USB_VENDOR_ID_WACOM 0x056a @@ -496,6 +514,16 @@ static const struct hid_blacklist { { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_502, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_503, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_504, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_600, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_601, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_602, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_603, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_604, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_605, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_606, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_607, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_608, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_609, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1000, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1001, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1002, HID_QUIRK_IGNORE }, @@ -503,6 +531,7 @@ static const struct hid_blacklist { { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1004, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1005, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1006, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1007, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_IMATION, USB_DEVICE_ID_DISC_STAKKA, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_CASSY, HID_QUIRK_IGNORE }, @@ -541,6 +570,7 @@ static const struct hid_blacklist { { USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_GOTEMP, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_SKIP, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_CYCLOPS, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_LCSPEC, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_4_PHIDGETSERVO_20, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_1_PHIDGETSERVO_20, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_8_8_4_IF_KIT, HID_QUIRK_IGNORE }, @@ -593,6 +623,12 @@ static const struct hid_blacklist { { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_ANSI, HID_QUIRK_APPLE_HAS_FN }, { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_ISO, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_APPLE_ISO_KEYBOARD }, { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_JIS, HID_QUIRK_APPLE_HAS_FN }, + { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ANSI, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE }, + { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ISO, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE | HID_QUIRK_APPLE_ISO_KEYBOARD }, + { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_JIS, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE }, + { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI, HID_QUIRK_APPLE_HAS_FN }, + { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ISO, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_APPLE_ISO_KEYBOARD }, + { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS, HID_QUIRK_APPLE_HAS_FN }, { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE }, { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE }, diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 354c91d06a6d..310e497b5838 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -1207,9 +1207,13 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) end_request: if (blk_pc_request(rq)) { unsigned long flags; + unsigned int dlen = rq->data_len; + + if (dma) + rq->data_len = 0; spin_lock_irqsave(&ide_lock, flags); - if (__blk_end_request(rq, 0, rq->data_len)) + if (__blk_end_request(rq, 0, dlen)) BUG(); HWGROUP(drive)->rq = NULL; spin_unlock_irqrestore(&ide_lock, flags); diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index aed8b31ca561..8f5bed471050 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -397,6 +397,7 @@ static inline int idedisk_supports_lba48(const struct hd_driveid *id) static const struct drive_list_entry hpa_list[] = { { "ST340823A", NULL }, { "ST320413A", NULL }, + { "ST310211A", NULL }, { NULL, NULL } }; diff --git a/drivers/ide/ide-generic.c b/drivers/ide/ide-generic.c index 709b9e4d2871..9ebec08eefd9 100644 --- a/drivers/ide/ide-generic.c +++ b/drivers/ide/ide-generic.c @@ -17,9 +17,6 @@ static int __init ide_generic_init(void) u8 idx[MAX_HWIFS]; int i; - if (ide_hwifs[0].io_ports[IDE_DATA_OFFSET]) - ide_get_lock(NULL, NULL); /* for atari only */ - for (i = 0; i < MAX_HWIFS; i++) { ide_hwif_t *hwif = &ide_hwifs[i]; @@ -31,9 +28,6 @@ static int __init ide_generic_init(void) ide_device_add_all(idx, NULL); - if (ide_hwifs[0].io_ports[IDE_DATA_OFFSET]) - ide_release_lock(); /* for atari only */ - return 0; } diff --git a/drivers/ide/legacy/falconide.c b/drivers/ide/legacy/falconide.c index f044048903b3..8949ce71bddc 100644 --- a/drivers/ide/legacy/falconide.c +++ b/drivers/ide/legacy/falconide.c @@ -54,7 +54,7 @@ static void __init falconide_setup_ports(hw_regs_t *hw) for (i = 1; i < 8; i++) hw->io_ports[i] = ATA_HD_BASE + 1 + i * 4; - hw->io_ports[IDE_CONTROL_OFFSET] = ATA_HD_CONTROL; + hw->io_ports[IDE_CONTROL_OFFSET] = ATA_HD_BASE + ATA_HD_CONTROL; hw->irq = IRQ_MFP_IDE; hw->ack_intr = NULL; @@ -84,7 +84,9 @@ static int __init falconide_init(void) ide_init_port_data(hwif, index); ide_init_port_hw(hwif, &hw); + ide_get_lock(NULL, NULL); ide_device_add(idx, NULL); + ide_release_lock(); } return 0; diff --git a/drivers/ide/legacy/ht6560b.c b/drivers/ide/legacy/ht6560b.c index 02d12c74764a..78ca68e60f97 100644 --- a/drivers/ide/legacy/ht6560b.c +++ b/drivers/ide/legacy/ht6560b.c @@ -21,18 +21,21 @@ * "Prefetch" mode bit OFF for ide disks and * ON for anything else. * + * Version 0.08 Need to force prefetch for CDs and other non-disk + * devices. (not sure which devices exactly need + * prefetch) * * HT-6560B EIDE-controller support * To activate controller support use kernel parameter "ide0=ht6560b". * Use hdparm utility to enable PIO mode support. * * Author: Mikko Ala-Fossi - * Jan Evert van Grootheest + * Jan Evert van Grootheest * * Try: http://www.maf.iki.fi/~maf/ht6560b/ */ -#define HT6560B_VERSION "v0.07" +#define HT6560B_VERSION "v0.08" #include #include @@ -130,15 +133,20 @@ static void ht6560b_selectproc (ide_drive_t *drive) u8 select, timing; local_irq_save(flags); - + select = HT_CONFIG(drive); timing = HT_TIMING(drive); - + + /* + * Need to enforce prefetch sometimes because otherwise + * it'll hang (hard). + */ + if (drive->media != ide_disk || !drive->present) + select |= HT_PREFETCH_MODE; + if (select != current_select || timing != current_timing) { current_select = select; current_timing = timing; - if (drive->media != ide_disk || !drive->present) - select |= HT_PREFETCH_MODE; (void)inb(HT_CONFIG_PORT); (void)inb(HT_CONFIG_PORT); (void)inb(HT_CONFIG_PORT); @@ -188,11 +196,12 @@ static int __init try_to_init_ht6560b(void) outb(HT_TIMING_DEFAULT, 0x1f6); /* IDE_SELECT_REG */ (void) inb(0x1f7); /* IDE_STATUS_REG */ - printk("\nht6560b " HT6560B_VERSION + printk("ht6560b " HT6560B_VERSION ": chipset detected and initialized" #ifdef DEBUG " with debug enabled" #endif + "\n" ); return 1; } @@ -323,7 +332,7 @@ static const struct ide_port_info ht6560b_port_info __initdata = { IDE_HFLAG_NO_DMA | IDE_HFLAG_NO_AUTOTUNE | IDE_HFLAG_ABUSE_PREFETCH, - .pio_mask = ATA_PIO5, + .pio_mask = ATA_PIO4, }; static int __init ht6560b_init(void) diff --git a/drivers/ide/legacy/macide.c b/drivers/ide/legacy/macide.c index a61e60737dc7..9a79098d9eb4 100644 --- a/drivers/ide/legacy/macide.c +++ b/drivers/ide/legacy/macide.c @@ -74,7 +74,7 @@ static void __init macide_setup_ports(hw_regs_t *hw, unsigned long base, for (i = 0; i < 8; i++) hw->io_ports[i] = base + i * 4; - hw->io_ports[IDE_CONTROL_OFFSET] = IDE_CONTROL; + hw->io_ports[IDE_CONTROL_OFFSET] = base + IDE_CONTROL; hw->irq = irq; hw->ack_intr = ack_intr; diff --git a/drivers/ide/pci/via82cxxx.c b/drivers/ide/pci/via82cxxx.c index f3f79f805813..9004e7521889 100644 --- a/drivers/ide/pci/via82cxxx.c +++ b/drivers/ide/pci/via82cxxx.c @@ -479,6 +479,7 @@ static int __devinit via_init_one(struct pci_dev *dev, const struct pci_device_i static const struct pci_device_id via_pci_tbl[] = { { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_82C576_1), 0 }, { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_82C586_1), 0 }, + { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_CX700_IDE), 0 }, { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_6410), 1 }, { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_SATA_EIDE), 1 }, { 0, }, diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c index 638b727d42e0..b10ade92efed 100644 --- a/drivers/infiniband/core/cm.c +++ b/drivers/infiniband/core/cm.c @@ -3587,8 +3587,6 @@ static void cm_release_port_obj(struct kobject *obj) { struct cm_port *cm_port; - printk(KERN_ERR "free cm port\n"); - cm_port = container_of(obj, struct cm_port, port_obj); kfree(cm_port); } @@ -3601,8 +3599,6 @@ static void cm_release_dev_obj(struct kobject *obj) { struct cm_device *cm_dev; - printk(KERN_ERR "free cm dev\n"); - cm_dev = container_of(obj, struct cm_device, dev_obj); kfree(cm_dev); } @@ -3616,18 +3612,12 @@ struct class cm_class = { }; EXPORT_SYMBOL(cm_class); -static void cm_remove_fs_obj(struct kobject *obj) -{ - kobject_put(obj->parent); - kobject_put(obj); -} - static int cm_create_port_fs(struct cm_port *port) { int i, ret; ret = kobject_init_and_add(&port->port_obj, &cm_port_obj_type, - kobject_get(&port->cm_dev->dev_obj), + &port->cm_dev->dev_obj, "%d", port->port_num); if (ret) { kfree(port); @@ -3637,7 +3627,7 @@ static int cm_create_port_fs(struct cm_port *port) for (i = 0; i < CM_COUNTER_GROUPS; i++) { ret = kobject_init_and_add(&port->counter_group[i].obj, &cm_counter_obj_type, - kobject_get(&port->port_obj), + &port->port_obj, "%s", counter_group_names[i]); if (ret) goto error; @@ -3647,8 +3637,8 @@ static int cm_create_port_fs(struct cm_port *port) error: while (i--) - cm_remove_fs_obj(&port->counter_group[i].obj); - cm_remove_fs_obj(&port->port_obj); + kobject_put(&port->counter_group[i].obj); + kobject_put(&port->port_obj); return ret; } @@ -3658,9 +3648,9 @@ static void cm_remove_port_fs(struct cm_port *port) int i; for (i = 0; i < CM_COUNTER_GROUPS; i++) - cm_remove_fs_obj(&port->counter_group[i].obj); + kobject_put(&port->counter_group[i].obj); - cm_remove_fs_obj(&port->port_obj); + kobject_put(&port->port_obj); } static void cm_add_one(struct ib_device *device) @@ -3744,7 +3734,7 @@ error1: ib_unregister_mad_agent(port->mad_agent); cm_remove_port_fs(port); } - cm_remove_fs_obj(&cm_dev->dev_obj); + kobject_put(&cm_dev->dev_obj); } static void cm_remove_one(struct ib_device *device) @@ -3771,7 +3761,7 @@ static void cm_remove_one(struct ib_device *device) ib_unregister_mad_agent(port->mad_agent); cm_remove_port_fs(port); } - cm_remove_fs_obj(&cm_dev->dev_obj); + kobject_put(&cm_dev->dev_obj); } static int __init ib_cm_init(void) diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index 1eff1b2c0e08..34507daaf9b6 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -1107,7 +1107,6 @@ static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event) event.param.ud.private_data_len = IB_CM_SIDR_REQ_PRIVATE_DATA_SIZE - offset; } else { - ib_send_cm_mra(cm_id, CMA_CM_MRA_SETTING, NULL, 0); conn_id = cma_new_conn_id(&listen_id->id, ib_event); cma_set_req_event_data(&event, &ib_event->param.req_rcvd, ib_event->private_data, offset); @@ -1130,6 +1129,15 @@ static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event) ret = conn_id->id.event_handler(&conn_id->id, &event); if (!ret) { + /* + * Acquire mutex to prevent user executing rdma_destroy_id() + * while we're accessing the cm_id. + */ + mutex_lock(&lock); + if (cma_comp(conn_id, CMA_CONNECT) && + !cma_is_ud_ps(conn_id->id.ps)) + ib_send_cm_mra(cm_id, CMA_CM_MRA_SETTING, NULL, 0); + mutex_unlock(&lock); cma_enable_remove(conn_id); goto out; } diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c index c864ef70fdf9..5a4b2e65534b 100644 --- a/drivers/infiniband/core/sysfs.c +++ b/drivers/infiniband/core/sysfs.c @@ -686,8 +686,10 @@ int ib_device_register_sysfs(struct ib_device *device) device->ports_parent = kobject_create_and_add("ports", kobject_get(&class_dev->kobj)); - if (!device->ports_parent) + if (!device->ports_parent) { + ret = -ENOMEM; goto err_put; + } if (device->node_type == RDMA_NODE_IB_SWITCH) { ret = add_port(device, 0); diff --git a/drivers/infiniband/hw/cxgb3/iwch_cm.c b/drivers/infiniband/hw/cxgb3/iwch_cm.c index e9a08fa3dffe..320f2b6ddee6 100644 --- a/drivers/infiniband/hw/cxgb3/iwch_cm.c +++ b/drivers/infiniband/hw/cxgb3/iwch_cm.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -1784,6 +1785,17 @@ err: return err; } +static int is_loopback_dst(struct iw_cm_id *cm_id) +{ + struct net_device *dev; + + dev = ip_dev_find(&init_net, cm_id->remote_addr.sin_addr.s_addr); + if (!dev) + return 0; + dev_put(dev); + return 1; +} + int iwch_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) { int err = 0; @@ -1791,6 +1803,11 @@ int iwch_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) struct iwch_ep *ep; struct rtable *rt; + if (is_loopback_dst(cm_id)) { + err = -ENOSYS; + goto out; + } + ep = alloc_ep(sizeof(*ep), GFP_KERNEL); if (!ep) { printk(KERN_ERR MOD "%s - cannot alloc ep.\n", __FUNCTION__); diff --git a/drivers/infiniband/hw/mlx4/mr.c b/drivers/infiniband/hw/mlx4/mr.c index 7dc91a3e712d..fe2c2e94a5f8 100644 --- a/drivers/infiniband/hw/mlx4/mr.c +++ b/drivers/infiniband/hw/mlx4/mr.c @@ -199,7 +199,7 @@ struct ib_fmr *mlx4_ib_fmr_alloc(struct ib_pd *pd, int acc, if (err) goto err_free; - err = mlx4_mr_enable(to_mdev(pd->device)->dev, &fmr->mfmr.mr); + err = mlx4_fmr_enable(to_mdev(pd->device)->dev, &fmr->mfmr); if (err) goto err_mr; diff --git a/drivers/infiniband/hw/mthca/mthca_cq.c b/drivers/infiniband/hw/mthca/mthca_cq.c index 6bd9f1393349..1e1e336d3ef9 100644 --- a/drivers/infiniband/hw/mthca/mthca_cq.c +++ b/drivers/infiniband/hw/mthca/mthca_cq.c @@ -473,7 +473,7 @@ static void handle_error_cqe(struct mthca_dev *dev, struct mthca_cq *cq, if (!(new_wqe & cpu_to_be32(0x3f)) || (!cqe->db_cnt && dbd)) return; - cqe->db_cnt = cpu_to_be16(be16_to_cpu(cqe->db_cnt) - dbd); + be16_add_cpu(&cqe->db_cnt, -dbd); cqe->wqe = new_wqe; cqe->syndrome = SYNDROME_WR_FLUSH_ERR; diff --git a/drivers/infiniband/hw/mthca/mthca_memfree.c b/drivers/infiniband/hw/mthca/mthca_memfree.c index 1f4d27d7c16d..252db0822f6c 100644 --- a/drivers/infiniband/hw/mthca/mthca_memfree.c +++ b/drivers/infiniband/hw/mthca/mthca_memfree.c @@ -542,6 +542,7 @@ struct mthca_user_db_table *mthca_init_user_db_tab(struct mthca_dev *dev) for (i = 0; i < npages; ++i) { db_tab->page[i].refcount = 0; db_tab->page[i].uvirt = 0; + sg_init_table(&db_tab->page[i].mem, 1); } return db_tab; diff --git a/drivers/infiniband/hw/mthca/mthca_mr.c b/drivers/infiniband/hw/mthca/mthca_mr.c index 3b6985557cb2..3538da16e3fe 100644 --- a/drivers/infiniband/hw/mthca/mthca_mr.c +++ b/drivers/infiniband/hw/mthca/mthca_mr.c @@ -686,7 +686,7 @@ err_out_table: mthca_table_put(dev, dev->mr_table.mpt_table, key); err_out_mpt_free: - mthca_free(&dev->mr_table.mpt_alloc, mr->ibmr.lkey); + mthca_free(&dev->mr_table.mpt_alloc, key); return err; } diff --git a/drivers/infiniband/hw/nes/nes_nic.c b/drivers/infiniband/hw/nes/nes_nic.c index b6cc265aa9a4..eee77da61935 100644 --- a/drivers/infiniband/hw/nes/nes_nic.c +++ b/drivers/infiniband/hw/nes/nes_nic.c @@ -148,14 +148,15 @@ static int nes_netdev_open(struct net_device *netdev) struct nes_device *nesdev = nesvnic->nesdev; int ret; int i; - struct nes_vnic *first_nesvnic; + struct nes_vnic *first_nesvnic = NULL; u32 nic_active_bit; u32 nic_active; + struct list_head *list_pos, *list_temp; assert(nesdev != NULL); - first_nesvnic = list_entry(nesdev->nesadapter->nesvnic_list[nesdev->mac_index].next, - struct nes_vnic, list); + if (nesvnic->netdev_open == 1) + return 0; if (netif_msg_ifup(nesvnic)) printk(KERN_INFO PFX "%s: enabling interface\n", netdev->name); @@ -225,7 +226,18 @@ static int nes_netdev_open(struct net_device *netdev) nes_write32(nesdev->regs+NES_CQE_ALLOC, NES_CQE_ALLOC_NOTIFY_NEXT | nesvnic->nic_cq.cq_number); nes_read32(nesdev->regs+NES_CQE_ALLOC); - + list_for_each_safe(list_pos, list_temp, &nesdev->nesadapter->nesvnic_list[nesdev->mac_index]) { + first_nesvnic = container_of(list_pos, struct nes_vnic, list); + if (first_nesvnic->netdev_open == 1) + break; + } + if (first_nesvnic->netdev_open == 0) { + nes_debug(NES_DBG_INIT, "Setting up MAC interrupt mask.\n"); + nes_write_indexed(nesdev, NES_IDX_MAC_INT_MASK + (0x200 * nesdev->mac_index), + ~(NES_MAC_INT_LINK_STAT_CHG | NES_MAC_INT_XGMII_EXT | + NES_MAC_INT_TX_UNDERFLOW | NES_MAC_INT_TX_ERROR)); + first_nesvnic = nesvnic; + } if (first_nesvnic->linkup) { /* Enable network packets */ nesvnic->linkup = 1; @@ -248,6 +260,8 @@ static int nes_netdev_stop(struct net_device *netdev) struct nes_device *nesdev = nesvnic->nesdev; u32 nic_active_mask; u32 nic_active; + struct nes_vnic *first_nesvnic = NULL; + struct list_head *list_pos, *list_temp; nes_debug(NES_DBG_SHUTDOWN, "nesvnic=%p, nesdev=%p, netdev=%p %s\n", nesvnic, nesdev, netdev, netdev->name); @@ -260,9 +274,20 @@ static int nes_netdev_stop(struct net_device *netdev) /* Disable network packets */ napi_disable(&nesvnic->napi); netif_stop_queue(netdev); - if ((nesdev->netdev[0] == netdev) & (nesvnic->logical_port == nesdev->mac_index)) { - nes_write_indexed(nesdev, - NES_IDX_MAC_INT_MASK+(0x200*nesdev->mac_index), 0xffffffff); + list_for_each_safe(list_pos, list_temp, &nesdev->nesadapter->nesvnic_list[nesdev->mac_index]) { + first_nesvnic = container_of(list_pos, struct nes_vnic, list); + if ((first_nesvnic->netdev_open == 1) && (first_nesvnic != nesvnic)) + break; + } + + if (first_nesvnic->netdev_open == 0) + nes_write_indexed(nesdev, NES_IDX_MAC_INT_MASK+(0x200*nesdev->mac_index), 0xffffffff); + else if ((first_nesvnic != nesvnic) && + (PCI_FUNC(first_nesvnic->nesdev->pcidev->devfn) != PCI_FUNC(nesvnic->nesdev->pcidev->devfn))) { + nes_write_indexed(nesdev, NES_IDX_MAC_INT_MASK + (0x200 * nesdev->mac_index), 0xffffffff); + nes_write_indexed(first_nesvnic->nesdev, NES_IDX_MAC_INT_MASK + (0x200 * first_nesvnic->nesdev->mac_index), + ~(NES_MAC_INT_LINK_STAT_CHG | NES_MAC_INT_XGMII_EXT | + NES_MAC_INT_TX_UNDERFLOW | NES_MAC_INT_TX_ERROR)); } nic_active_mask = ~((u32)(1 << nesvnic->nic_index)); @@ -859,7 +884,6 @@ void nes_netdev_set_multicast_list(struct net_device *netdev) for (mc_index=0; mc_index < NES_MULTICAST_PF_MAX; mc_index++) { while (multicast_addr && nesvnic->mcrq_mcast_filter && ((mc_nic_index = nesvnic->mcrq_mcast_filter(nesvnic, multicast_addr->dmi_addr)) == 0)) multicast_addr = multicast_addr->next; - if (mc_nic_index < 0) mc_nic_index = nesvnic->nic_index; if (multicast_addr) { @@ -908,7 +932,7 @@ static int nes_netdev_change_mtu(struct net_device *netdev, int new_mtu) return -EINVAL; netdev->mtu = new_mtu; - nesvnic->max_frame_size = new_mtu+ETH_HLEN; + nesvnic->max_frame_size = new_mtu + VLAN_ETH_HLEN; if (netdev->mtu > 1500) { jumbomode=1; @@ -1470,10 +1494,15 @@ static void nes_netdev_vlan_rx_register(struct net_device *netdev, struct vlan_g { struct nes_vnic *nesvnic = netdev_priv(netdev); struct nes_device *nesdev = nesvnic->nesdev; + struct nes_adapter *nesadapter = nesdev->nesadapter; u32 u32temp; + unsigned long flags; + spin_lock_irqsave(&nesadapter->phy_lock, flags); nesvnic->vlan_grp = grp; + nes_debug(NES_DBG_NETDEV, "%s: %s\n", __func__, netdev->name); + /* Enable/Disable VLAN Stripping */ u32temp = nes_read_indexed(nesdev, NES_IDX_PCIX_DIAG); if (grp) @@ -1482,6 +1511,7 @@ static void nes_netdev_vlan_rx_register(struct net_device *netdev, struct vlan_g u32temp |= 0x02000000; nes_write_indexed(nesdev, NES_IDX_PCIX_DIAG, u32temp); + spin_unlock_irqrestore(&nesadapter->phy_lock, flags); } @@ -1540,7 +1570,7 @@ struct net_device *nes_netdev_init(struct nes_device *nesdev, nesvnic->msg_enable = netif_msg_init(debug, default_msg); nesvnic->netdev_index = nesdev->netdev_count; nesvnic->perfect_filter_index = nesdev->nesadapter->netdev_count; - nesvnic->max_frame_size = netdev->mtu+netdev->hard_header_len; + nesvnic->max_frame_size = netdev->mtu + netdev->hard_header_len + VLAN_HLEN; curr_qp_map = nic_qp_mapping_per_function[PCI_FUNC(nesdev->pcidev->devfn)]; nesvnic->nic.qp_id = curr_qp_map[nesdev->netdev_count].qpid; @@ -1610,7 +1640,7 @@ struct net_device *nes_netdev_init(struct nes_device *nesdev, list_add_tail(&nesvnic->list, &nesdev->nesadapter->nesvnic_list[nesdev->mac_index]); if ((nesdev->netdev_count == 0) && - (PCI_FUNC(nesdev->pcidev->devfn) == nesdev->mac_index)) { + (PCI_FUNC(nesdev->pcidev->devfn) == nesdev->mac_index)) { nes_debug(NES_DBG_INIT, "Setting up PHY interrupt mask. Using register index 0x%04X\n", NES_IDX_PHY_PCS_CONTROL_STATUS0+(0x200*(nesvnic->logical_port&1))); u32temp = nes_read_indexed(nesdev, NES_IDX_PHY_PCS_CONTROL_STATUS0 + @@ -1648,18 +1678,14 @@ struct net_device *nes_netdev_init(struct nes_device *nesdev, nesvnic->linkup = 1; } } - nes_debug(NES_DBG_INIT, "Setting up MAC interrupt mask.\n"); /* clear the MAC interrupt status, assumes direct logical to physical mapping */ - u32temp = nes_read_indexed(nesdev, NES_IDX_MAC_INT_STATUS+(0x200*nesvnic->logical_port)); + u32temp = nes_read_indexed(nesdev, NES_IDX_MAC_INT_STATUS + (0x200 * nesdev->mac_index)); nes_debug(NES_DBG_INIT, "Phy interrupt status = 0x%X.\n", u32temp); - nes_write_indexed(nesdev, NES_IDX_MAC_INT_STATUS+(0x200*nesvnic->logical_port), u32temp); + nes_write_indexed(nesdev, NES_IDX_MAC_INT_STATUS + (0x200 * nesdev->mac_index), u32temp); - if (nesdev->nesadapter->phy_type[nesvnic->logical_port] != NES_PHY_TYPE_IRIS) + if (nesdev->nesadapter->phy_type[nesdev->mac_index] != NES_PHY_TYPE_IRIS) nes_init_phy(nesdev); - nes_write_indexed(nesdev, NES_IDX_MAC_INT_MASK+(0x200*nesvnic->logical_port), - ~(NES_MAC_INT_LINK_STAT_CHG | NES_MAC_INT_XGMII_EXT | - NES_MAC_INT_TX_UNDERFLOW | NES_MAC_INT_TX_ERROR)); } return netdev; diff --git a/drivers/infiniband/hw/nes/nes_verbs.c b/drivers/infiniband/hw/nes/nes_verbs.c index ffd4b425567f..4dafbe16e82a 100644 --- a/drivers/infiniband/hw/nes/nes_verbs.c +++ b/drivers/infiniband/hw/nes/nes_verbs.c @@ -1337,7 +1337,7 @@ static struct ib_qp *nes_create_qp(struct ib_pd *ibpd, NES_MAX_USER_WQ_REGIONS, nes_ucontext->first_free_wq); /* nes_debug(NES_DBG_QP, "find_first_zero_biton wqs returned %u\n", nespd->mmap_db_index); */ - if (nesqp->mmap_sq_db_index > NES_MAX_USER_WQ_REGIONS) { + if (nesqp->mmap_sq_db_index >= NES_MAX_USER_WQ_REGIONS) { nes_debug(NES_DBG_QP, "db index > max user regions, failing create QP\n"); nes_free_resource(nesadapter, nesadapter->allocated_qps, qp_num); diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h index f9b7caa54143..054fab8e27a0 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib.h +++ b/drivers/infiniband/ulp/ipoib/ipoib.h @@ -209,7 +209,6 @@ struct ipoib_cm_tx { unsigned tx_tail; unsigned long flags; u32 mtu; - struct ib_wc ibwc[IPOIB_NUM_WC]; }; struct ipoib_cm_rx_buf { diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c index 7dd2ec473d24..52b1bebfa744 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c @@ -824,7 +824,6 @@ void ipoib_cm_dev_stop(struct net_device *dev) struct ipoib_dev_priv *priv = netdev_priv(dev); struct ipoib_cm_rx *p; unsigned long begin; - LIST_HEAD(list); int ret; if (!IPOIB_CM_SUPPORTED(dev->dev_addr) || !priv->cm.id) @@ -857,9 +856,12 @@ void ipoib_cm_dev_stop(struct net_device *dev) /* * assume the HW is wedged and just free up everything. */ - list_splice_init(&priv->cm.rx_flush_list, &list); - list_splice_init(&priv->cm.rx_error_list, &list); - list_splice_init(&priv->cm.rx_drain_list, &list); + list_splice_init(&priv->cm.rx_flush_list, + &priv->cm.rx_reap_list); + list_splice_init(&priv->cm.rx_error_list, + &priv->cm.rx_reap_list); + list_splice_init(&priv->cm.rx_drain_list, + &priv->cm.rx_reap_list); break; } spin_unlock_irq(&priv->lock); diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c index 9d3e778dc56d..08c4396cf418 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c @@ -780,6 +780,7 @@ static void __ipoib_ib_dev_flush(struct ipoib_dev_priv *priv, int pkey_event) if (ib_find_pkey(priv->ca, priv->port, priv->pkey, &new_index)) { clear_bit(IPOIB_PKEY_ASSIGNED, &priv->flags); ipoib_ib_dev_down(dev, 0); + ipoib_ib_dev_stop(dev, 0); ipoib_pkey_dev_delay_open(dev); return; } diff --git a/drivers/macintosh/mediabay.c b/drivers/macintosh/mediabay.c index 936788272a5f..51a112815f46 100644 --- a/drivers/macintosh/mediabay.c +++ b/drivers/macintosh/mediabay.c @@ -416,7 +416,6 @@ static void poll_media_bay(struct media_bay_info* bay) } } -#ifdef CONFIG_MAC_FLOPPY int check_media_bay(struct device_node *which_bay, int what) { int i; @@ -431,7 +430,6 @@ int check_media_bay(struct device_node *which_bay, int what) return -ENODEV; } EXPORT_SYMBOL(check_media_bay); -#endif /* CONFIG_MAC_FLOPPY */ #ifdef CONFIG_BLK_DEV_IDE_PMAC int check_media_bay_by_base(unsigned long base, int what) diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index a0585fb6da94..7aeceedcf7d4 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c @@ -206,16 +206,10 @@ static void bitmap_checkfree(struct bitmap *bitmap, unsigned long page) /* copy the pathname of a file to a buffer */ char *file_path(struct file *file, char *buf, int count) { - struct dentry *d; - struct vfsmount *v; - if (!buf) return NULL; - d = file->f_path.dentry; - v = file->f_path.mnt; - - buf = d_path(d, v, buf, count); + buf = d_path(&file->f_path, buf, count); return IS_ERR(buf) ? NULL : buf; } diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c index 2928ef228101..51605870f898 100644 --- a/drivers/md/dm-raid1.c +++ b/drivers/md/dm-raid1.c @@ -1695,14 +1695,15 @@ static int mirror_end_io(struct dm_target *ti, struct bio *bio, * information for a retry or there was no other * mirror in-sync. */ - DMERR_LIMIT("Mirror read failed from %s.", - m->dev->name); + DMERR_LIMIT("Mirror read failed."); return -EIO; } + + m = read_record->m; + DMERR("Mirror read failed from %s. Trying alternative device.", m->dev->name); - m = read_record->m; fail_mirror(m, DM_RAID1_READ_ERROR); /* diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index f16062982383..e75b1437b58b 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c @@ -361,7 +361,7 @@ static int lookup_device(const char *path, dev_t *dev) if ((r = path_lookup(path, LOOKUP_FOLLOW, &nd))) return r; - inode = nd.dentry->d_inode; + inode = nd.path.dentry->d_inode; if (!inode) { r = -ENOENT; goto out; @@ -375,7 +375,7 @@ static int lookup_device(const char *path, dev_t *dev) *dev = inode->i_rdev; out: - path_release(&nd); + path_put(&nd.path); return r; } diff --git a/drivers/md/md.c b/drivers/md/md.c index 5fc326d3970e..7da6ec244e15 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -5197,8 +5197,7 @@ 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_path.mnt, - bitmap->file->f_path.dentry," \t\n"); + seq_path(seq, &bitmap->file->f_path, " \t\n"); } seq_printf(seq, "\n"); diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig index 8f4a45346de7..11950698a2e7 100644 --- a/drivers/media/Kconfig +++ b/drivers/media/Kconfig @@ -25,11 +25,16 @@ config VIDEO_DEV To compile this driver as a module, choose M here: the module will be called videodev. +config VIDEO_V4L2_COMMON + tristate + depends on (I2C || I2C=n) && VIDEO_DEV + default (I2C || I2C=n) && VIDEO_DEV + config VIDEO_V4L1 bool "Enable Video For Linux API 1 (DEPRECATED)" - depends on VIDEO_DEV + depends on VIDEO_DEV && VIDEO_V4L2_COMMON + default VIDEO_DEV && VIDEO_V4L2_COMMON select VIDEO_V4L1_COMPAT - default y ---help--- Enables a compatibility API used by most V4L2 devices to allow its usage with legacy applications that supports only V4L1 api. @@ -39,7 +44,7 @@ config VIDEO_V4L1 config VIDEO_V4L1_COMPAT bool "Enable Video For Linux API 1 compatible Layer" depends on VIDEO_DEV - default y + default VIDEO_DEV ---help--- This api were developed to be used at Kernel 2.2 and 2.4, but lacks support for several video standards. There are several @@ -55,8 +60,8 @@ config VIDEO_V4L1_COMPAT config VIDEO_V4L2 bool - depends on VIDEO_DEV - default y + depends on VIDEO_DEV && VIDEO_V4L2_COMMON + default VIDEO_DEV && VIDEO_V4L2_COMMON source "drivers/media/video/Kconfig" @@ -93,7 +98,7 @@ if VIDEO_TUNER_CUSTOMIZE config TUNER_XC2028 tristate "XCeive xc2028/xc3028 tuners" - depends on I2C + depends on I2C && FW_LOADER default m if VIDEO_TUNER_CUSTOMIZE help Say Y here to include support for the xc2028/xc3028 tuners. @@ -180,7 +185,6 @@ config VIDEO_TVEEPROM config DAB boolean "DAB adapters" - default y ---help--- Allow selecting support for for Digital Audio Broadcasting (DAB) Receiver adapters. diff --git a/drivers/media/common/Kconfig b/drivers/media/common/Kconfig index 06ca75911b7f..769c6f8142d2 100644 --- a/drivers/media/common/Kconfig +++ b/drivers/media/common/Kconfig @@ -4,6 +4,6 @@ config VIDEO_SAA7146 config VIDEO_SAA7146_VV tristate - depends on VIDEO_DEV + depends on VIDEO_V4L2 select VIDEOBUF_DMA_SG select VIDEO_SAA7146 diff --git a/drivers/media/common/ir-keymaps.c b/drivers/media/common/ir-keymaps.c index a4a937c90534..2ab5a120470d 100644 --- a/drivers/media/common/ir-keymaps.c +++ b/drivers/media/common/ir-keymaps.c @@ -1987,3 +1987,49 @@ IR_KEYTAB_TYPE ir_codes_behold[IR_KEYTAB_SIZE] = { }; EXPORT_SYMBOL_GPL(ir_codes_behold); + +/* + * Remote control for the Genius TVGO A11MCE + * Adrian Pardini + */ +IR_KEYTAB_TYPE ir_codes_genius_tvgo_a11mce[IR_KEYTAB_SIZE] = { + /* Keys 0 to 9 */ + [0x48] = KEY_0, + [0x09] = KEY_1, + [0x1d] = KEY_2, + [0x1f] = KEY_3, + [0x19] = KEY_4, + [0x1b] = KEY_5, + [0x11] = KEY_6, + [0x17] = KEY_7, + [0x12] = KEY_8, + [0x16] = KEY_9, + + [0x54] = KEY_RECORD, /* recording */ + [0x06] = KEY_MUTE, /* mute */ + [0x10] = KEY_POWER, + [0x40] = KEY_LAST, /* recall */ + [0x4c] = KEY_CHANNELUP, /* channel / program + */ + [0x00] = KEY_CHANNELDOWN, /* channel / program - */ + [0x0d] = KEY_VOLUMEUP, + [0x15] = KEY_VOLUMEDOWN, + [0x4d] = KEY_OK, /* also labeled as Pause */ + [0x1c] = KEY_ZOOM, /* full screen and Stop*/ + [0x02] = KEY_MODE, /* AV Source or Rewind*/ + [0x04] = KEY_LIST, /* -/-- */ + /* small arrows above numbers */ + [0x1a] = KEY_NEXT, /* also Fast Forward */ + [0x0e] = KEY_PREVIOUS, /* also Rewind */ + /* these are in a rather non standard layout and have + an alternate name written */ + [0x1e] = KEY_UP, /* Video Setting */ + [0x0a] = KEY_DOWN, /* Video Default */ + [0x05] = KEY_LEFT, /* Snapshot */ + [0x0c] = KEY_RIGHT, /* Hide Panel */ + /* Four buttons without label */ + [0x49] = KEY_RED, + [0x0b] = KEY_GREEN, + [0x13] = KEY_YELLOW, + [0x50] = KEY_BLUE, +}; +EXPORT_SYMBOL_GPL(ir_codes_genius_tvgo_a11mce); diff --git a/drivers/media/common/saa7146_vbi.c b/drivers/media/common/saa7146_vbi.c index c32dda973e92..bfbd5a841ebf 100644 --- a/drivers/media/common/saa7146_vbi.c +++ b/drivers/media/common/saa7146_vbi.c @@ -413,7 +413,6 @@ static int vbi_open(struct saa7146_dev *dev, struct file *file) V4L2_FIELD_SEQ_TB, // FIXME: does this really work? sizeof(struct saa7146_buf), file); - mutex_init(&fh->vbi_q.lock); init_timer(&fh->vbi_read_timeout); fh->vbi_read_timeout.function = vbi_read_timeout; diff --git a/drivers/media/common/saa7146_video.c b/drivers/media/common/saa7146_video.c index c31ab480d8e1..66fdbd0e6a6d 100644 --- a/drivers/media/common/saa7146_video.c +++ b/drivers/media/common/saa7146_video.c @@ -1417,8 +1417,6 @@ static int video_open(struct saa7146_dev *dev, struct file *file) sizeof(struct saa7146_buf), file); - mutex_init(&fh->video_q.lock); - return 0; } diff --git a/drivers/media/dvb/bt8xx/bt878.c b/drivers/media/dvb/bt8xx/bt878.c index c7bbb40223f5..56d8fab688bb 100644 --- a/drivers/media/dvb/bt8xx/bt878.c +++ b/drivers/media/dvb/bt8xx/bt878.c @@ -75,7 +75,11 @@ EXPORT_SYMBOL(bt878); #if defined(dprintk) #undef dprintk #endif -#define dprintk if(bt878_debug) printk +#define dprintk(fmt, arg...) \ + do { \ + if (bt878_debug) \ + printk(KERN_DEBUG fmt, ##arg); \ + } while (0) static void bt878_mem_free(struct bt878 *bt) { @@ -154,7 +158,7 @@ static int bt878_make_risc(struct bt878 *bt) } if (bt->line_count > 255) { - printk("bt878: buffer size error!\n"); + printk(KERN_ERR "bt878: buffer size error!\n"); return -EINVAL; } return 0; @@ -285,7 +289,8 @@ static irqreturn_t bt878_irq(int irq, void *dev_id) if (astat & (BT878_ASCERR | BT878_AOCERR)) { if (bt878_verbose) { - printk("bt878(%d): irq%s%s risc_pc=%08x\n", + printk(KERN_INFO + "bt878(%d): irq%s%s risc_pc=%08x\n", bt->nr, (astat & BT878_ASCERR) ? " SCERR" : "", @@ -295,8 +300,8 @@ static irqreturn_t bt878_irq(int irq, void *dev_id) } if (astat & (BT878_APABORT | BT878_ARIPERR | BT878_APPERR)) { if (bt878_verbose) { - printk - ("bt878(%d): irq%s%s%s risc_pc=%08x\n", + printk(KERN_INFO + "bt878(%d): irq%s%s%s risc_pc=%08x\n", bt->nr, (astat & BT878_APABORT) ? " PABORT" : "", @@ -308,8 +313,8 @@ static irqreturn_t bt878_irq(int irq, void *dev_id) } if (astat & (BT878_AFDSR | BT878_AFTRGT | BT878_AFBUS)) { if (bt878_verbose) { - printk - ("bt878(%d): irq%s%s%s risc_pc=%08x\n", + printk(KERN_INFO + "bt878(%d): irq%s%s%s risc_pc=%08x\n", bt->nr, (astat & BT878_AFDSR) ? " FDSR" : "", (astat & BT878_AFTRGT) ? " FTRGT" : @@ -510,7 +515,7 @@ static int __devinit bt878_probe(struct pci_dev *dev, */ if ((result = bt878_mem_alloc(bt))) { - printk("bt878: failed to allocate memory!\n"); + printk(KERN_ERR "bt878: failed to allocate memory!\n"); goto fail2; } @@ -536,7 +541,7 @@ static void __devexit bt878_remove(struct pci_dev *pci_dev) struct bt878 *bt = pci_get_drvdata(pci_dev); if (bt878_verbose) - printk("bt878(%d): unloading\n", bt->nr); + printk(KERN_INFO "bt878(%d): unloading\n", bt->nr); /* turn off all capturing, DMA and IRQs */ btand(~0x13, BT878_AGPIO_DMA_CTL); diff --git a/drivers/media/dvb/dvb-usb/ttusb2.c b/drivers/media/dvb/dvb-usb/ttusb2.c index 88dc4367a2e3..3b9da9c25c6e 100644 --- a/drivers/media/dvb/dvb-usb/ttusb2.c +++ b/drivers/media/dvb/dvb-usb/ttusb2.c @@ -144,6 +144,7 @@ static int ttusb2_power_ctrl(struct dvb_usb_device *d, int onoff) static struct tda10086_config tda10086_config = { .demod_address = 0x0e, .invert = 0, + .diseqc_tone = 1, }; static int ttusb2_frontend_attach(struct dvb_usb_adapter *adap) diff --git a/drivers/media/dvb/frontends/tda10086.c b/drivers/media/dvb/frontends/tda10086.c index 9d26ace65151..0d2b69a99ad4 100644 --- a/drivers/media/dvb/frontends/tda10086.c +++ b/drivers/media/dvb/frontends/tda10086.c @@ -106,9 +106,12 @@ static int tda10086_write_mask(struct tda10086_state *state, int reg, int mask, static int tda10086_init(struct dvb_frontend* fe) { struct tda10086_state* state = fe->demodulator_priv; + u8 t22k_off = 0x80; dprintk ("%s\n", __FUNCTION__); + if (state->config->diseqc_tone) + t22k_off = 0; // reset tda10086_write_byte(state, 0x00, 0x00); msleep(10); @@ -158,7 +161,7 @@ static int tda10086_init(struct dvb_frontend* fe) tda10086_write_byte(state, 0x3d, 0x80); // setup SEC - tda10086_write_byte(state, 0x36, 0x80); // all SEC off, no 22k tone + tda10086_write_byte(state, 0x36, t22k_off); // all SEC off, 22k tone tda10086_write_byte(state, 0x34, (((1<<19) * (22000/1000)) / (SACLK/1000))); // } tone frequency tda10086_write_byte(state, 0x35, (((1<<19) * (22000/1000)) / (SACLK/1000)) >> 8); // } @@ -180,16 +183,20 @@ static void tda10086_diseqc_wait(struct tda10086_state *state) static int tda10086_set_tone (struct dvb_frontend* fe, fe_sec_tone_mode_t tone) { struct tda10086_state* state = fe->demodulator_priv; + u8 t22k_off = 0x80; dprintk ("%s\n", __FUNCTION__); + if (state->config->diseqc_tone) + t22k_off = 0; + switch (tone) { case SEC_TONE_OFF: - tda10086_write_byte(state, 0x36, 0x80); + tda10086_write_byte(state, 0x36, t22k_off); break; case SEC_TONE_ON: - tda10086_write_byte(state, 0x36, 0x81); + tda10086_write_byte(state, 0x36, 0x01 + t22k_off); break; } @@ -202,9 +209,13 @@ static int tda10086_send_master_cmd (struct dvb_frontend* fe, struct tda10086_state* state = fe->demodulator_priv; int i; u8 oldval; + u8 t22k_off = 0x80; dprintk ("%s\n", __FUNCTION__); + if (state->config->diseqc_tone) + t22k_off = 0; + if (cmd->msg_len > 6) return -EINVAL; oldval = tda10086_read_byte(state, 0x36); @@ -212,7 +223,8 @@ static int tda10086_send_master_cmd (struct dvb_frontend* fe, for(i=0; i< cmd->msg_len; i++) { tda10086_write_byte(state, 0x48+i, cmd->msg[i]); } - tda10086_write_byte(state, 0x36, 0x88 | ((cmd->msg_len - 1) << 4)); + tda10086_write_byte(state, 0x36, (0x08 + t22k_off) + | ((cmd->msg_len - 1) << 4)); tda10086_diseqc_wait(state); @@ -225,16 +237,20 @@ static int tda10086_send_burst (struct dvb_frontend* fe, fe_sec_mini_cmd_t minic { struct tda10086_state* state = fe->demodulator_priv; u8 oldval = tda10086_read_byte(state, 0x36); + u8 t22k_off = 0x80; dprintk ("%s\n", __FUNCTION__); + if (state->config->diseqc_tone) + t22k_off = 0; + switch(minicmd) { case SEC_MINI_A: - tda10086_write_byte(state, 0x36, 0x84); + tda10086_write_byte(state, 0x36, 0x04 + t22k_off); break; case SEC_MINI_B: - tda10086_write_byte(state, 0x36, 0x86); + tda10086_write_byte(state, 0x36, 0x06 + t22k_off); break; } diff --git a/drivers/media/dvb/frontends/tda10086.h b/drivers/media/dvb/frontends/tda10086.h index ed584a8f4a89..eeceaeee78ff 100644 --- a/drivers/media/dvb/frontends/tda10086.h +++ b/drivers/media/dvb/frontends/tda10086.h @@ -33,6 +33,9 @@ struct tda10086_config /* does the "inversion" need inverted? */ u8 invert; + + /* do we need the diseqc signal with carrier? */ + u8 diseqc_tone; }; #if defined(CONFIG_DVB_TDA10086) || (defined(CONFIG_DVB_TDA10086_MODULE) && defined(MODULE)) diff --git a/drivers/media/dvb/frontends/tda18271-common.c b/drivers/media/dvb/frontends/tda18271-common.c index cebb6b90b7e0..bca570990613 100644 --- a/drivers/media/dvb/frontends/tda18271-common.c +++ b/drivers/media/dvb/frontends/tda18271-common.c @@ -171,7 +171,7 @@ int tda18271_read_extended(struct dvb_frontend *fe) if (ret != 2) tda_err("ERROR: i2c_transfer returned: %d\n", ret); - for (i = 0; i <= TDA18271_NUM_REGS; i++) { + for (i = 0; i < TDA18271_NUM_REGS; i++) { /* don't update write-only registers */ if ((i != R_EB9) && (i != R_EB16) && diff --git a/drivers/media/dvb/frontends/xc5000.h b/drivers/media/dvb/frontends/xc5000.h index e0e84562aed1..32a5f1c86a16 100644 --- a/drivers/media/dvb/frontends/xc5000.h +++ b/drivers/media/dvb/frontends/xc5000.h @@ -45,7 +45,8 @@ struct xc5000_config { /* xc5000 callback command */ #define XC5000_TUNER_RESET 0 -#if defined(CONFIG_DVB_TUNER_XC5000) || defined(CONFIG_DVB_TUNER_XC5000_MODULE) +#if defined(CONFIG_DVB_TUNER_XC5000) || \ + (defined(CONFIG_DVB_TUNER_XC5000_MODULE) && defined(MODULE)) extern struct dvb_frontend* xc5000_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct xc5000_config *cfg); diff --git a/drivers/media/dvb/ttpci/av7110_av.c b/drivers/media/dvb/ttpci/av7110_av.c index aef6e36d7c5c..3e6b650fbb81 100644 --- a/drivers/media/dvb/ttpci/av7110_av.c +++ b/drivers/media/dvb/ttpci/av7110_av.c @@ -966,6 +966,7 @@ static u8 iframe_header[] = { 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x80, 0x00, 0x static int play_iframe(struct av7110 *av7110, char __user *buf, unsigned int len, int nonblock) { int i, n; + int progressive = 0; dprintk(2, "av7110:%p, \n", av7110); @@ -974,6 +975,14 @@ static int play_iframe(struct av7110 *av7110, char __user *buf, unsigned int len return -EBUSY; } + for (i = 0; i < len - 5; i++) { + /* get progressive flag from picture extension */ + if (buf[i] == 0x00 && buf[i+1] == 0x00 && + buf[i+2] == 0x01 && (unsigned char)buf[i+3] == 0xb5 && + (buf[i+4] & 0xf0) == 0x10) + progressive = buf[i+5] & 0x08; + } + /* setting n always > 1, fixes problems when playing stillframes consisting of I- and P-Frames */ n = MIN_IFRAME / len + 1; @@ -985,7 +994,11 @@ static int play_iframe(struct av7110 *av7110, char __user *buf, unsigned int len dvb_play(av7110, buf, len, 0, 1); av7110_ipack_flush(&av7110->ipack[1]); - return 0; + + if (progressive) + return vidcom(av7110, AV_VIDEO_CMD_FREEZE, 1); + else + return 0; } diff --git a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c index 3439c9864f67..2d64d557b977 100644 --- a/drivers/media/dvb/ttpci/budget-av.c +++ b/drivers/media/dvb/ttpci/budget-av.c @@ -896,6 +896,7 @@ static u8 read_pwm(struct budget_av *budget_av) #define SUBID_DVBS_CINERGY1200 0x1154 #define SUBID_DVBS_CYNERGY1200N 0x1155 #define SUBID_DVBS_TV_STAR 0x0014 +#define SUBID_DVBS_TV_STAR_PLUS_X4 0x0015 #define SUBID_DVBS_TV_STAR_CI 0x0016 #define SUBID_DVBS_EASYWATCH_1 0x001a #define SUBID_DVBS_EASYWATCH_2 0x001b @@ -910,6 +911,7 @@ static u8 read_pwm(struct budget_av *budget_av) #define SUBID_DVBC_CINERGY1200 0x1156 #define SUBID_DVBC_CINERGY1200_MK3 0x1176 +#define SUBID_DVBT_EASYWATCH 0x003a #define SUBID_DVBT_KNC1_PLUS 0x0031 #define SUBID_DVBT_KNC1 0x0030 #define SUBID_DVBT_CINERGY1200 0x1157 @@ -957,6 +959,7 @@ static void frontend_init(struct budget_av *budget_av) break; case SUBID_DVBS_TV_STAR: + case SUBID_DVBS_TV_STAR_PLUS_X4: case SUBID_DVBS_TV_STAR_CI: case SUBID_DVBS_CYNERGY1200N: case SUBID_DVBS_EASYWATCH: @@ -1018,6 +1021,7 @@ static void frontend_init(struct budget_av *budget_av) } break; + case SUBID_DVBT_EASYWATCH: case SUBID_DVBT_KNC1: case SUBID_DVBT_KNC1_PLUS: case SUBID_DVBT_CINERGY1200: @@ -1248,7 +1252,9 @@ MAKE_BUDGET_INFO(satewpls1, "Satelco EasyWatch DVB-S light", BUDGET_KNC1S); MAKE_BUDGET_INFO(satewps, "Satelco EasyWatch DVB-S", BUDGET_KNC1S); MAKE_BUDGET_INFO(satewplc, "Satelco EasyWatch DVB-C", BUDGET_KNC1CP); MAKE_BUDGET_INFO(satewcmk3, "Satelco EasyWatch DVB-C MK3", BUDGET_KNC1C_MK3); +MAKE_BUDGET_INFO(satewt, "Satelco EasyWatch DVB-T", BUDGET_KNC1T); MAKE_BUDGET_INFO(knc1sp, "KNC1 DVB-S Plus", BUDGET_KNC1SP); +MAKE_BUDGET_INFO(knc1spx4, "KNC1 DVB-S Plus X4", BUDGET_KNC1SP); MAKE_BUDGET_INFO(knc1cp, "KNC1 DVB-C Plus", BUDGET_KNC1CP); MAKE_BUDGET_INFO(knc1cmk3, "KNC1 DVB-C MK3", BUDGET_KNC1C_MK3); MAKE_BUDGET_INFO(knc1cpmk3, "KNC1 DVB-C Plus MK3", BUDGET_KNC1CP_MK3); @@ -1266,12 +1272,14 @@ static struct pci_device_id pci_tbl[] = { MAKE_EXTENSION_PCI(knc1sp, 0x1131, 0x0011), MAKE_EXTENSION_PCI(knc1sp, 0x1894, 0x0011), MAKE_EXTENSION_PCI(kncxs, 0x1894, 0x0014), + MAKE_EXTENSION_PCI(knc1spx4, 0x1894, 0x0015), MAKE_EXTENSION_PCI(kncxs, 0x1894, 0x0016), MAKE_EXTENSION_PCI(satewpls, 0x1894, 0x001e), MAKE_EXTENSION_PCI(satewpls1, 0x1894, 0x001a), MAKE_EXTENSION_PCI(satewps, 0x1894, 0x001b), MAKE_EXTENSION_PCI(satewplc, 0x1894, 0x002a), MAKE_EXTENSION_PCI(satewcmk3, 0x1894, 0x002c), + MAKE_EXTENSION_PCI(satewt, 0x1894, 0x003a), MAKE_EXTENSION_PCI(knc1c, 0x1894, 0x0020), MAKE_EXTENSION_PCI(knc1cp, 0x1894, 0x0021), MAKE_EXTENSION_PCI(knc1cmk3, 0x1894, 0x0022), diff --git a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c index 9268a82bada6..14b00f57b5de 100644 --- a/drivers/media/dvb/ttpci/budget.c +++ b/drivers/media/dvb/ttpci/budget.c @@ -351,6 +351,7 @@ static struct s5h1420_config s5h1420_config = { static struct tda10086_config tda10086_config = { .demod_address = 0x0e, .invert = 0, + .diseqc_tone = 1, }; static u8 read_pwm(struct budget* budget) diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig index 8d5214f18cf0..1b41b3f77cf9 100644 --- a/drivers/media/radio/Kconfig +++ b/drivers/media/radio/Kconfig @@ -4,12 +4,12 @@ menuconfig RADIO_ADAPTERS bool "Radio Adapters" - depends on VIDEO_DEV + depends on VIDEO_V4L2 default y ---help--- Say Y here to enable selecting AM/FM radio adapters. -if RADIO_ADAPTERS && VIDEO_DEV +if RADIO_ADAPTERS && VIDEO_V4L2 config RADIO_CADET tristate "ADS Cadet AM/FM Tuner" diff --git a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c index 3118bdab3183..53e114857377 100644 --- a/drivers/media/radio/radio-sf16fmi.c +++ b/drivers/media/radio/radio-sf16fmi.c @@ -361,6 +361,7 @@ static int __init fmi_init(void) } if (!request_region(io, 2, "radio-sf16fmi")) { printk(KERN_ERR "radio-sf16fmi: port 0x%x already in use\n", io); + pnp_device_detach(dev); return -EBUSY; } diff --git a/drivers/media/radio/radio-sf16fmr2.c b/drivers/media/radio/radio-sf16fmr2.c index f7c8b000404f..ebc5fbbc38bb 100644 --- a/drivers/media/radio/radio-sf16fmr2.c +++ b/drivers/media/radio/radio-sf16fmr2.c @@ -470,9 +470,8 @@ static int __init fmr2_init(void) mutex_init(&lock); - if (request_region(io, 2, "sf16fmr2")) - { - printk(KERN_ERR "fmr2: port 0x%x already in use\n", io); + if (!request_region(io, 2, "sf16fmr2")) { + printk(KERN_ERR "radio-sf16fmr2: request_region failed!\n"); return -EBUSY; } diff --git a/drivers/media/radio/radio-si470x.c b/drivers/media/radio/radio-si470x.c index 8e4bd4769048..649f14d2c013 100644 --- a/drivers/media/radio/radio-si470x.c +++ b/drivers/media/radio/radio-si470x.c @@ -62,6 +62,29 @@ * - code cleaned of unnecessary rds_commands * - USB Vendor/Product ID for ADS/Tech FM Radio Receiver verified * (thanks to Guillaume RAMOUSSE) + * 2008-01-27 Tobias Lorenz + * Version 1.0.5 + * - number of seek_retries changed to tune_timeout + * - fixed problem with incomplete tune operations by own buffers + * - optimization of variables and printf types + * - improved error logging + * 2008-01-31 Tobias Lorenz + * Oliver Neukum + * Version 1.0.6 + * - fixed coverity checker warnings in *_usb_driver_disconnect + * - probe()/open() race by correct ordering in probe() + * - DMA coherency rules by separate allocation of all buffers + * - use of endianness macros + * - abuse of spinlock, replaced by mutex + * - racy handling of timer in disconnect, + * replaced by delayed_work + * - racy interruptible_sleep_on(), + * replaced with wait_event_interruptible() + * - handle signals in read() + * 2008-02-08 Tobias Lorenz + * Oliver Neukum + * Version 1.0.7 + * - usb autosuspend support * * ToDo: * - add seeking support @@ -74,9 +97,10 @@ /* driver definitions */ #define DRIVER_AUTHOR "Tobias Lorenz " #define DRIVER_NAME "radio-si470x" -#define DRIVER_VERSION KERNEL_VERSION(1, 0, 4) +#define DRIVER_KERNEL_VERSION KERNEL_VERSION(1, 0, 6) #define DRIVER_CARD "Silicon Labs Si470x FM Radio Receiver" #define DRIVER_DESC "USB radio driver for Si470x FM Radio Receivers" +#define DRIVER_VERSION "1.0.6" /* kernel includes */ @@ -89,8 +113,10 @@ #include #include #include +#include #include #include +#include /* USB Device ID List */ @@ -119,56 +145,56 @@ MODULE_PARM_DESC(radio_nr, "Radio Nr"); /* 0: 200 kHz (USA, Australia) */ /* 1: 100 kHz (Europe, Japan) */ /* 2: 50 kHz */ -static int space = 2; -module_param(space, int, 0); +static unsigned short space = 2; +module_param(space, ushort, 0); MODULE_PARM_DESC(radio_nr, "Spacing: 0=200kHz 1=100kHz *2=50kHz*"); /* Bottom of Band (MHz) */ /* 0: 87.5 - 108 MHz (USA, Europe)*/ /* 1: 76 - 108 MHz (Japan wide band) */ /* 2: 76 - 90 MHz (Japan) */ -static int band = 1; -module_param(band, int, 0); +static unsigned short band = 1; +module_param(band, ushort, 0); MODULE_PARM_DESC(radio_nr, "Band: 0=87.5..108MHz *1=76..108MHz* 2=76..90MHz"); /* De-emphasis */ /* 0: 75 us (USA) */ /* 1: 50 us (Europe, Australia, Japan) */ -static int de = 1; -module_param(de, int, 0); +static unsigned short de = 1; +module_param(de, ushort, 0); MODULE_PARM_DESC(radio_nr, "De-emphasis: 0=75us *1=50us*"); /* USB timeout */ -static int usb_timeout = 500; -module_param(usb_timeout, int, 0); +static unsigned int usb_timeout = 500; +module_param(usb_timeout, uint, 0); MODULE_PARM_DESC(usb_timeout, "USB timeout (ms): *500*"); -/* Seek retries */ -static int seek_retries = 100; -module_param(seek_retries, int, 0); -MODULE_PARM_DESC(seek_retries, "Seek retries: *100*"); +/* Tune timeout */ +static unsigned int tune_timeout = 3000; +module_param(tune_timeout, uint, 0); +MODULE_PARM_DESC(tune_timeout, "Tune timeout: *3000*"); /* RDS buffer blocks */ -static int rds_buf = 100; -module_param(rds_buf, int, 0); +static unsigned int rds_buf = 100; +module_param(rds_buf, uint, 0); MODULE_PARM_DESC(rds_buf, "RDS buffer entries: *100*"); /* RDS maximum block errors */ -static int max_rds_errors = 1; +static unsigned short max_rds_errors = 1; /* 0 means 0 errors requiring correction */ /* 1 means 1-2 errors requiring correction (used by original USBRadio.exe) */ /* 2 means 3-5 errors requiring correction */ /* 3 means 6+ errors or errors in checkword, correction not possible */ -module_param(max_rds_errors, int, 0); +module_param(max_rds_errors, ushort, 0); MODULE_PARM_DESC(max_rds_errors, "RDS maximum block errors: *1*"); /* RDS poll frequency */ -static int rds_poll_time = 40; +static unsigned int rds_poll_time = 40; /* 40 is used by the original USBRadio.exe */ /* 50 is used by radio-cadet */ /* 75 should be okay */ /* 80 is the usual RDS receive interval */ -module_param(rds_poll_time, int, 0); +module_param(rds_poll_time, uint, 0); MODULE_PARM_DESC(rds_poll_time, "RDS poll time (ms): *40*"); @@ -393,22 +419,19 @@ MODULE_PARM_DESC(rds_poll_time, "RDS poll time (ms): *40*"); struct si470x_device { /* reference to USB and video device */ struct usb_device *usbdev; + struct usb_interface *intf; struct video_device *videodev; - /* are these really necessary ? */ - int users; - - /* report buffer (maximum 64 bytes) */ - unsigned char buf[64]; + /* driver management */ + unsigned int users; /* Silabs internal registers (0..15) */ unsigned short registers[RADIO_REGISTER_NUM]; /* RDS receive buffer */ - struct work_struct work; + struct delayed_work work; wait_queue_head_t read_queue; - struct timer_list timer; - spinlock_t lock; /* buffer locking */ + struct mutex lock; /* buffer locking */ unsigned char *buffer; /* size is always multiple of three */ unsigned int buf_size; unsigned int rd_index; @@ -434,28 +457,46 @@ struct si470x_device { /* * si470x_get_report - receive a HID report */ -static int si470x_get_report(struct si470x_device *radio, int size) +static int si470x_get_report(struct si470x_device *radio, void *buf, int size) { - return usb_control_msg(radio->usbdev, + unsigned char *report = (unsigned char *) buf; + int retval; + + retval = usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), HID_REQ_GET_REPORT, USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, - radio->buf[0], 2, - radio->buf, size, usb_timeout); + report[0], 2, + buf, size, usb_timeout); + if (retval < 0) + printk(KERN_WARNING DRIVER_NAME + ": si470x_get_report: usb_control_msg returned %d\n", + retval); + + return retval; } /* * si470x_set_report - send a HID report */ -static int si470x_set_report(struct si470x_device *radio, int size) +static int si470x_set_report(struct si470x_device *radio, void *buf, int size) { - return usb_control_msg(radio->usbdev, + unsigned char *report = (unsigned char *) buf; + int retval; + + retval = usb_control_msg(radio->usbdev, usb_sndctrlpipe(radio->usbdev, 0), HID_REQ_SET_REPORT, USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT, - radio->buf[0], 2, - radio->buf, size, usb_timeout); + report[0], 2, + buf, size, usb_timeout); + if (retval < 0) + printk(KERN_WARNING DRIVER_NAME + ": si470x_set_report: usb_control_msg returned %d\n", + retval); + + return retval; } @@ -464,13 +505,16 @@ static int si470x_set_report(struct si470x_device *radio, int size) */ static int si470x_get_register(struct si470x_device *radio, int regnr) { + unsigned char buf[REGISTER_REPORT_SIZE]; int retval; - radio->buf[0] = REGISTER_REPORT(regnr); + buf[0] = REGISTER_REPORT(regnr); + + retval = si470x_get_report(radio, (void *) &buf, sizeof(buf)); - retval = si470x_get_report(radio, REGISTER_REPORT_SIZE); if (retval >= 0) - radio->registers[regnr] = (radio->buf[1] << 8) | radio->buf[2]; + radio->registers[regnr] = be16_to_cpu(get_unaligned( + (unsigned short *) &buf[1])); return (retval < 0) ? -EINVAL : 0; } @@ -481,13 +525,14 @@ static int si470x_get_register(struct si470x_device *radio, int regnr) */ static int si470x_set_register(struct si470x_device *radio, int regnr) { + unsigned char buf[REGISTER_REPORT_SIZE]; int retval; - radio->buf[0] = REGISTER_REPORT(regnr); - radio->buf[1] = (radio->registers[regnr] & 0xff00) >> 8; - radio->buf[2] = (radio->registers[regnr] & 0x00ff); + buf[0] = REGISTER_REPORT(regnr); + put_unaligned(cpu_to_be16(radio->registers[regnr]), + (unsigned short *) &buf[1]); - retval = si470x_set_report(radio, REGISTER_REPORT_SIZE); + retval = si470x_set_report(radio, (void *) &buf, sizeof(buf)); return (retval < 0) ? -EINVAL : 0; } @@ -498,18 +543,19 @@ static int si470x_set_register(struct si470x_device *radio, int regnr) */ static int si470x_get_all_registers(struct si470x_device *radio) { + unsigned char buf[ENTIRE_REPORT_SIZE]; int retval; - int regnr; + unsigned char regnr; - radio->buf[0] = ENTIRE_REPORT; + buf[0] = ENTIRE_REPORT; - retval = si470x_get_report(radio, ENTIRE_REPORT_SIZE); + retval = si470x_get_report(radio, (void *) &buf, sizeof(buf)); if (retval >= 0) for (regnr = 0; regnr < RADIO_REGISTER_NUM; regnr++) - radio->registers[regnr] = - (radio->buf[regnr * RADIO_REGISTER_SIZE + 1] << 8) | - radio->buf[regnr * RADIO_REGISTER_SIZE + 2]; + radio->registers[regnr] = be16_to_cpu(get_unaligned( + (unsigned short *) + &buf[regnr * RADIO_REGISTER_SIZE + 1])); return (retval < 0) ? -EINVAL : 0; } @@ -520,21 +566,28 @@ static int si470x_get_all_registers(struct si470x_device *radio) */ static int si470x_get_rds_registers(struct si470x_device *radio) { + unsigned char buf[RDS_REPORT_SIZE]; int retval; - int regnr; int size; + unsigned char regnr; - radio->buf[0] = RDS_REPORT; + buf[0] = RDS_REPORT; retval = usb_interrupt_msg(radio->usbdev, - usb_rcvctrlpipe(radio->usbdev, 1), - radio->buf, RDS_REPORT_SIZE, &size, usb_timeout); + usb_rcvintpipe(radio->usbdev, 1), + (void *) &buf, sizeof(buf), &size, usb_timeout); + if (size != sizeof(buf)) + printk(KERN_WARNING DRIVER_NAME ": si470x_get_rds_register: " + "return size differs: %d != %zu\n", size, sizeof(buf)); + if (retval < 0) + printk(KERN_WARNING DRIVER_NAME ": si470x_get_rds_registers: " + "usb_interrupt_msg returned %d\n", retval); if (retval >= 0) for (regnr = 0; regnr < RDS_REGISTER_NUM; regnr++) radio->registers[STATUSRSSI + regnr] = - (radio->buf[regnr * RADIO_REGISTER_SIZE + 1] << 8) | - radio->buf[regnr * RADIO_REGISTER_SIZE + 2]; + be16_to_cpu(get_unaligned((unsigned short *) + &buf[regnr * RADIO_REGISTER_SIZE + 1])); return (retval < 0) ? -EINVAL : 0; } @@ -543,9 +596,11 @@ static int si470x_get_rds_registers(struct si470x_device *radio) /* * si470x_set_chan - set the channel */ -static int si470x_set_chan(struct si470x_device *radio, int chan) +static int si470x_set_chan(struct si470x_device *radio, unsigned short chan) { - int retval, i; + int retval; + unsigned long timeout; + bool timed_out = 0; /* start tuning */ radio->registers[CHANNEL] &= ~CHANNEL_CHAN; @@ -555,16 +610,17 @@ static int si470x_set_chan(struct si470x_device *radio, int chan) return retval; /* wait till seek operation has completed */ - i = 0; + timeout = jiffies + msecs_to_jiffies(tune_timeout); do { retval = si470x_get_register(radio, STATUSRSSI); if (retval < 0) return retval; - } while ((radio->registers[STATUSRSSI] & STATUSRSSI_STC) && - (++i < seek_retries)); - if (i >= seek_retries) + timed_out = time_after(jiffies, timeout); + } while (((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0) && + (!timed_out)); + if (timed_out) printk(KERN_WARNING DRIVER_NAME - ": seek does not finish after %d tries\n", i); + ": seek does not finish after %u ms\n", tune_timeout); /* stop tuning */ radio->registers[CHANNEL] &= ~CHANNEL_TUNE; @@ -575,9 +631,10 @@ static int si470x_set_chan(struct si470x_device *radio, int chan) /* * si470x_get_freq - get the frequency */ -static int si470x_get_freq(struct si470x_device *radio) +static unsigned int si470x_get_freq(struct si470x_device *radio) { - int spacing, band_bottom, chan, freq; + unsigned int spacing, band_bottom, freq; + unsigned short chan; int retval; /* Spacing (kHz) */ @@ -616,9 +673,10 @@ static int si470x_get_freq(struct si470x_device *radio) /* * si470x_set_freq - set the frequency */ -static int si470x_set_freq(struct si470x_device *radio, int freq) +static int si470x_set_freq(struct si470x_device *radio, unsigned int freq) { - int spacing, band_bottom, chan; + unsigned int spacing, band_bottom; + unsigned short chan; /* Spacing (kHz) */ switch (space) { @@ -709,9 +767,17 @@ static int si470x_stop(struct si470x_device *radio) */ static int si470x_rds_on(struct si470x_device *radio) { + int retval; + /* sysconfig 1 */ + mutex_lock(&radio->lock); radio->registers[SYSCONFIG1] |= SYSCONFIG1_RDS; - return si470x_set_register(radio, SYSCONFIG1); + retval = si470x_set_register(radio, SYSCONFIG1); + if (retval < 0) + radio->registers[SYSCONFIG1] &= ~SYSCONFIG1_RDS; + mutex_unlock(&radio->lock); + + return retval; } @@ -725,11 +791,10 @@ static int si470x_rds_on(struct si470x_device *radio) */ static void si470x_rds(struct si470x_device *radio) { - unsigned char tmpbuf[3]; unsigned char blocknum; - unsigned char bler; /* rds block errors */ + unsigned short bler; /* rds block errors */ unsigned short rds; - unsigned int i; + unsigned char tmpbuf[3]; /* get rds blocks */ if (si470x_get_rds_registers(radio) < 0) @@ -743,63 +808,58 @@ static void si470x_rds(struct si470x_device *radio) return; } - /* copy four RDS blocks to internal buffer */ - if (spin_trylock(&radio->lock)) { - /* process each rds block */ - for (blocknum = 0; blocknum < 4; blocknum++) { - switch (blocknum) { - default: - bler = (radio->registers[STATUSRSSI] & - STATUSRSSI_BLERA) >> 9; - rds = radio->registers[RDSA]; - break; - case 1: - bler = (radio->registers[READCHAN] & - READCHAN_BLERB) >> 14; - rds = radio->registers[RDSB]; - break; - case 2: - bler = (radio->registers[READCHAN] & - READCHAN_BLERC) >> 12; - rds = radio->registers[RDSC]; - break; - case 3: - bler = (radio->registers[READCHAN] & - READCHAN_BLERD) >> 10; - rds = radio->registers[RDSD]; - break; - }; + /* copy all four RDS blocks to internal buffer */ + mutex_lock(&radio->lock); + for (blocknum = 0; blocknum < 4; blocknum++) { + switch (blocknum) { + default: + bler = (radio->registers[STATUSRSSI] & + STATUSRSSI_BLERA) >> 9; + rds = radio->registers[RDSA]; + break; + case 1: + bler = (radio->registers[READCHAN] & + READCHAN_BLERB) >> 14; + rds = radio->registers[RDSB]; + break; + case 2: + bler = (radio->registers[READCHAN] & + READCHAN_BLERC) >> 12; + rds = radio->registers[RDSC]; + break; + case 3: + bler = (radio->registers[READCHAN] & + READCHAN_BLERD) >> 10; + rds = radio->registers[RDSD]; + break; + }; - /* Fill the V4L2 RDS buffer */ - tmpbuf[0] = rds & 0x00ff; /* LSB */ - tmpbuf[1] = (rds & 0xff00) >> 8;/* MSB */ - tmpbuf[2] = blocknum; /* offset name */ - tmpbuf[2] |= blocknum << 3; /* received offset */ - if (bler > max_rds_errors) - tmpbuf[2] |= 0x80; /* uncorrectable errors */ - else if (bler > 0) - tmpbuf[2] |= 0x40; /* corrected error(s) */ + /* Fill the V4L2 RDS buffer */ + put_unaligned(cpu_to_le16(rds), (unsigned short *) &tmpbuf); + tmpbuf[2] = blocknum; /* offset name */ + tmpbuf[2] |= blocknum << 3; /* received offset */ + if (bler > max_rds_errors) + tmpbuf[2] |= 0x80; /* uncorrectable errors */ + else if (bler > 0) + tmpbuf[2] |= 0x40; /* corrected error(s) */ - /* copy RDS block to internal buffer */ - for (i = 0; i < 3; i++) { - radio->buffer[radio->wr_index] = tmpbuf[i]; - radio->wr_index++; - } + /* copy RDS block to internal buffer */ + memcpy(&radio->buffer[radio->wr_index], &tmpbuf, 3); + radio->wr_index += 3; - /* wrap write pointer */ - if (radio->wr_index >= radio->buf_size) - radio->wr_index = 0; + /* wrap write pointer */ + if (radio->wr_index >= radio->buf_size) + radio->wr_index = 0; - /* check for overflow */ - if (radio->wr_index == radio->rd_index) { - /* increment and wrap read pointer */ - radio->rd_index += 3; - if (radio->rd_index >= radio->buf_size) - radio->rd_index = 0; - } + /* check for overflow */ + if (radio->wr_index == radio->rd_index) { + /* increment and wrap read pointer */ + radio->rd_index += 3; + if (radio->rd_index >= radio->buf_size) + radio->rd_index = 0; } - spin_unlock(&radio->lock); } + mutex_unlock(&radio->lock); /* wake up read queue */ if (radio->wr_index != radio->rd_index) @@ -807,30 +867,19 @@ static void si470x_rds(struct si470x_device *radio) } -/* - * si470x_timer - rds timer function - */ -static void si470x_timer(unsigned long data) -{ - struct si470x_device *radio = (struct si470x_device *) data; - - schedule_work(&radio->work); -} - - /* * si470x_work - rds work function */ static void si470x_work(struct work_struct *work) { struct si470x_device *radio = container_of(work, struct si470x_device, - work); + work.work); if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0) return; si470x_rds(radio); - mod_timer(&radio->timer, jiffies + msecs_to_jiffies(rds_poll_time)); + schedule_delayed_work(&radio->work, msecs_to_jiffies(rds_poll_time)); } @@ -852,44 +901,44 @@ static ssize_t si470x_fops_read(struct file *file, char __user *buf, /* switch on rds reception */ if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0) { si470x_rds_on(radio); - schedule_work(&radio->work); + schedule_delayed_work(&radio->work, + msecs_to_jiffies(rds_poll_time)); } /* block if no new data available */ while (radio->wr_index == radio->rd_index) { if (file->f_flags & O_NONBLOCK) return -EWOULDBLOCK; - interruptible_sleep_on(&radio->read_queue); + if (wait_event_interruptible(radio->read_queue, + radio->wr_index != radio->rd_index) < 0) + return -EINTR; } /* calculate block count from byte count */ count /= 3; /* copy RDS block out of internal buffer and to user buffer */ - if (spin_trylock(&radio->lock)) { - while (block_count < count) { - if (radio->rd_index == radio->wr_index) - break; + mutex_lock(&radio->lock); + while (block_count < count) { + if (radio->rd_index == radio->wr_index) + break; - /* always transfer rds complete blocks */ - if (copy_to_user(buf, - &radio->buffer[radio->rd_index], 3)) - /* retval = -EFAULT; */ - break; + /* always transfer rds complete blocks */ + if (copy_to_user(buf, &radio->buffer[radio->rd_index], 3)) + /* retval = -EFAULT; */ + break; - /* increment and wrap read pointer */ - radio->rd_index += 3; - if (radio->rd_index >= radio->buf_size) - radio->rd_index = 0; + /* increment and wrap read pointer */ + radio->rd_index += 3; + if (radio->rd_index >= radio->buf_size) + radio->rd_index = 0; - /* increment counters */ - block_count++; - buf += 3; - retval += 3; - } - - spin_unlock(&radio->lock); + /* increment counters */ + block_count++; + buf += 3; + retval += 3; } + mutex_unlock(&radio->lock); return retval; } @@ -906,7 +955,8 @@ static unsigned int si470x_fops_poll(struct file *file, /* switch on rds reception */ if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0) { si470x_rds_on(radio); - schedule_work(&radio->work); + schedule_delayed_work(&radio->work, + msecs_to_jiffies(rds_poll_time)); } poll_wait(file, &radio->read_queue, pts); @@ -924,10 +974,22 @@ static unsigned int si470x_fops_poll(struct file *file, static int si470x_fops_open(struct inode *inode, struct file *file) { struct si470x_device *radio = video_get_drvdata(video_devdata(file)); + int retval; radio->users++; - if (radio->users == 1) - return si470x_start(radio); + + retval = usb_autopm_get_interface(radio->intf); + if (retval < 0) { + radio->users--; + return -EIO; + } + + if (radio->users == 1) { + retval = si470x_start(radio); + if (retval < 0) + usb_autopm_put_interface(radio->intf); + return retval; + } return 0; } @@ -939,6 +1001,7 @@ static int si470x_fops_open(struct inode *inode, struct file *file) static int si470x_fops_release(struct inode *inode, struct file *file) { struct si470x_device *radio = video_get_drvdata(video_devdata(file)); + int retval; if (!radio) return -ENODEV; @@ -946,13 +1009,14 @@ static int si470x_fops_release(struct inode *inode, struct file *file) radio->users--; if (radio->users == 0) { /* stop rds reception */ - del_timer_sync(&radio->timer); - flush_scheduled_work(); + cancel_delayed_work_sync(&radio->work); /* cancel read processes */ wake_up_interruptible(&radio->read_queue); - return si470x_stop(radio); + retval = si470x_stop(radio); + usb_autopm_put_interface(radio->intf); + return retval; } return 0; @@ -1030,7 +1094,7 @@ static int si470x_vidioc_querycap(struct file *file, void *priv, strlcpy(capability->driver, DRIVER_NAME, sizeof(capability->driver)); strlcpy(capability->card, DRIVER_CARD, sizeof(capability->card)); sprintf(capability->bus_info, "USB"); - capability->version = DRIVER_VERSION; + capability->version = DRIVER_KERNEL_VERSION; capability->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; return 0; @@ -1067,16 +1131,21 @@ static int si470x_vidioc_s_input(struct file *filp, void *priv, unsigned int i) static int si470x_vidioc_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *qc) { - int i; + unsigned char i; + int retval = -EINVAL; for (i = 0; i < ARRAY_SIZE(si470x_v4l2_queryctrl); i++) { if (qc->id && qc->id == si470x_v4l2_queryctrl[i].id) { memcpy(qc, &(si470x_v4l2_queryctrl[i]), sizeof(*qc)); - return 0; + retval = 0; + break; } } + if (retval < 0) + printk(KERN_WARNING DRIVER_NAME + ": query control failed with %d\n", retval); - return -EINVAL; + return retval; } @@ -1110,21 +1179,29 @@ static int si470x_vidioc_s_ctrl(struct file *file, void *priv, struct v4l2_control *ctrl) { struct si470x_device *radio = video_get_drvdata(video_devdata(file)); + int retval; switch (ctrl->id) { case V4L2_CID_AUDIO_VOLUME: radio->registers[SYSCONFIG2] &= ~SYSCONFIG2_VOLUME; radio->registers[SYSCONFIG2] |= ctrl->value; - return si470x_set_register(radio, SYSCONFIG2); + retval = si470x_set_register(radio, SYSCONFIG2); + break; case V4L2_CID_AUDIO_MUTE: if (ctrl->value == 1) radio->registers[POWERCFG] &= ~POWERCFG_DMUTE; else radio->registers[POWERCFG] |= POWERCFG_DMUTE; - return si470x_set_register(radio, POWERCFG); + retval = si470x_set_register(radio, POWERCFG); + break; + default: + retval = -EINVAL; } + if (retval < 0) + printk(KERN_WARNING DRIVER_NAME + ": set control failed with %d\n", retval); - return -EINVAL; + return retval; } @@ -1163,8 +1240,8 @@ static int si470x_vidioc_s_audio(struct file *file, void *priv, static int si470x_vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *tuner) { - int retval; struct si470x_device *radio = video_get_drvdata(video_devdata(file)); + int retval; if (tuner->index > 0) return -EINVAL; @@ -1220,6 +1297,7 @@ static int si470x_vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *tuner) { struct si470x_device *radio = video_get_drvdata(video_devdata(file)); + int retval; if (tuner->index > 0) return -EINVAL; @@ -1229,7 +1307,12 @@ static int si470x_vidioc_s_tuner(struct file *file, void *priv, else radio->registers[POWERCFG] &= ~POWERCFG_MONO; /* try stereo */ - return si470x_set_register(radio, POWERCFG); + retval = si470x_set_register(radio, POWERCFG); + if (retval < 0) + printk(KERN_WARNING DRIVER_NAME + ": set tuner failed with %d\n", retval); + + return retval; } @@ -1255,11 +1338,17 @@ static int si470x_vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *freq) { struct si470x_device *radio = video_get_drvdata(video_devdata(file)); + int retval; if (freq->type != V4L2_TUNER_RADIO) return -EINVAL; - return si470x_set_freq(radio, freq->frequency); + retval = si470x_set_freq(radio, freq->frequency); + if (retval < 0) + printk(KERN_WARNING DRIVER_NAME + ": set frequency failed with %d\n", retval); + + return 0; } @@ -1299,71 +1388,116 @@ static int si470x_usb_driver_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct si470x_device *radio; + int retval = -ENOMEM; - /* memory and interface allocations */ - radio = kmalloc(sizeof(struct si470x_device), GFP_KERNEL); + /* private data allocation */ + radio = kzalloc(sizeof(struct si470x_device), GFP_KERNEL); if (!radio) - return -ENOMEM; + goto err_initial; + + /* video device allocation */ radio->videodev = video_device_alloc(); - if (!radio->videodev) { - kfree(radio); - return -ENOMEM; - } + if (!radio->videodev) + goto err_radio; + + /* initial configuration */ memcpy(radio->videodev, &si470x_viddev_template, sizeof(si470x_viddev_template)); radio->users = 0; radio->usbdev = interface_to_usbdev(intf); + radio->intf = intf; + mutex_init(&radio->lock); video_set_drvdata(radio->videodev, radio); - if (video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr)) { - printk(KERN_WARNING DRIVER_NAME - ": Could not register video device\n"); - video_device_release(radio->videodev); - kfree(radio); - return -EIO; - } - usb_set_intfdata(intf, radio); /* show some infos about the specific device */ - if (si470x_get_all_registers(radio) < 0) { - video_device_release(radio->videodev); - kfree(radio); - return -EIO; - } - printk(KERN_INFO DRIVER_NAME ": DeviceID=0x%4.4x ChipID=0x%4.4x\n", + retval = -EIO; + if (si470x_get_all_registers(radio) < 0) + goto err_all; + printk(KERN_INFO DRIVER_NAME ": DeviceID=0x%4.4hx ChipID=0x%4.4hx\n", radio->registers[DEVICEID], radio->registers[CHIPID]); /* check if firmware is current */ if ((radio->registers[CHIPID] & CHIPID_FIRMWARE) - < RADIO_SW_VERSION_CURRENT) + < RADIO_SW_VERSION_CURRENT) { printk(KERN_WARNING DRIVER_NAME - ": This driver is known to work with chip version %d, " - "but the device has firmware %d.\n" - DRIVER_NAME - "If you have some trouble using this driver, please " - "report to V4L ML at video4linux-list@redhat.com\n", - radio->registers[CHIPID] & CHIPID_FIRMWARE, - RADIO_SW_VERSION_CURRENT); + ": This driver is known to work with " + "firmware version %hu,\n", RADIO_SW_VERSION_CURRENT); + printk(KERN_WARNING DRIVER_NAME + ": but the device has firmware version %hu.\n", + radio->registers[CHIPID] & CHIPID_FIRMWARE); + printk(KERN_WARNING DRIVER_NAME + ": If you have some trouble using this driver,\n"); + printk(KERN_WARNING DRIVER_NAME + ": please report to V4L ML at " + "video4linux-list@redhat.com\n"); + } /* set initial frequency */ si470x_set_freq(radio, 87.5 * FREQ_MUL); /* available in all regions */ - /* rds initialization */ + /* rds buffer allocation */ radio->buf_size = rds_buf * 3; radio->buffer = kmalloc(radio->buf_size, GFP_KERNEL); - if (!radio->buffer) { - video_device_release(radio->videodev); - kfree(radio); - return -ENOMEM; - } + if (!radio->buffer) + goto err_all; + + /* rds buffer configuration */ radio->wr_index = 0; radio->rd_index = 0; init_waitqueue_head(&radio->read_queue); - /* prepare polling via eventd */ - INIT_WORK(&radio->work, si470x_work); - init_timer(&radio->timer); - radio->timer.function = si470x_timer; - radio->timer.data = (unsigned long) radio; + /* prepare rds work function */ + INIT_DELAYED_WORK(&radio->work, si470x_work); + + /* register video device */ + if (video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr)) { + printk(KERN_WARNING DRIVER_NAME + ": Could not register video device\n"); + goto err_all; + } + usb_set_intfdata(intf, radio); + + return 0; +err_all: + video_device_release(radio->videodev); + kfree(radio->buffer); +err_radio: + kfree(radio); +err_initial: + return retval; +} + + +/* + * si470x_usb_driver_suspend - suspend the device + */ +static int si470x_usb_driver_suspend(struct usb_interface *intf, + pm_message_t message) +{ + struct si470x_device *radio = usb_get_intfdata(intf); + + printk(KERN_INFO DRIVER_NAME ": suspending now...\n"); + + cancel_delayed_work_sync(&radio->work); + + return 0; +} + + +/* + * si470x_usb_driver_resume - resume the device + */ +static int si470x_usb_driver_resume(struct usb_interface *intf) +{ + struct si470x_device *radio = usb_get_intfdata(intf); + + printk(KERN_INFO DRIVER_NAME ": resuming now...\n"); + + mutex_lock(&radio->lock); + if (radio->users && radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) + schedule_delayed_work(&radio->work, + msecs_to_jiffies(rds_poll_time)); + mutex_unlock(&radio->lock); return 0; } @@ -1376,15 +1510,11 @@ static void si470x_usb_driver_disconnect(struct usb_interface *intf) { struct si470x_device *radio = usb_get_intfdata(intf); - del_timer_sync(&radio->timer); - flush_scheduled_work(); - + cancel_delayed_work_sync(&radio->work); usb_set_intfdata(intf, NULL); - if (radio) { - video_unregister_device(radio->videodev); - kfree(radio->buffer); - kfree(radio); - } + video_unregister_device(radio->videodev); + kfree(radio->buffer); + kfree(radio); } @@ -1392,10 +1522,13 @@ static void si470x_usb_driver_disconnect(struct usb_interface *intf) * si470x_usb_driver - usb driver interface */ static struct usb_driver si470x_usb_driver = { - .name = DRIVER_NAME, - .probe = si470x_usb_driver_probe, - .disconnect = si470x_usb_driver_disconnect, - .id_table = si470x_usb_driver_id_table, + .name = DRIVER_NAME, + .probe = si470x_usb_driver_probe, + .disconnect = si470x_usb_driver_disconnect, + .suspend = si470x_usb_driver_suspend, + .resume = si470x_usb_driver_resume, + .id_table = si470x_usb_driver_id_table, + .supports_autosuspend = 1, }; @@ -1409,7 +1542,7 @@ static struct usb_driver si470x_usb_driver = { */ static int __init si470x_module_init(void) { - printk(KERN_INFO DRIVER_DESC "\n"); + printk(KERN_INFO DRIVER_DESC ", Version " DRIVER_VERSION "\n"); return usb_register(&si470x_usb_driver); } @@ -1429,4 +1562,4 @@ module_exit(si470x_module_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_VERSION("1.0.4"); +MODULE_VERSION(DRIVER_VERSION); diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index a2e8987a6195..37072a21d8c9 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -4,14 +4,14 @@ menuconfig VIDEO_CAPTURE_DRIVERS bool "Video capture adapters" - depends on VIDEO_DEV + depends on VIDEO_V4L2 default y ---help--- Say Y here to enable selecting the video adapters for webcams, analog TV, and hybrid analog/digital TV. Some of those devices also supports FM radio. -if VIDEO_CAPTURE_DRIVERS && VIDEO_DEV +if VIDEO_CAPTURE_DRIVERS && VIDEO_V4L2 config VIDEO_ADV_DEBUG bool "Enable advanced debug functionality" diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index 850b8c6f4577..3f209b32eeac 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -10,8 +10,9 @@ msp3400-objs := msp3400-driver.o msp3400-kthreads.o stkwebcam-objs := stk-webcam.o stk-sensor.o -obj-$(CONFIG_VIDEO_DEV) += videodev.o v4l2-common.o compat_ioctl32.o \ - v4l2-int-device.o +obj-$(CONFIG_VIDEO_DEV) += videodev.o compat_ioctl32.o v4l2-int-device.o + +obj-$(CONFIG_VIDEO_V4L2_COMMON) += v4l2-common.o ifeq ($(CONFIG_VIDEO_V4L1_COMPAT),y) obj-$(CONFIG_VIDEO_DEV) += v4l1-compat.o diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index 907dc62c1783..5404fcc5276d 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c @@ -2354,8 +2354,8 @@ static int setup_window(struct bttv_fh *fh, struct bttv *btv, BUG(); } - mutex_lock(&fh->cap.lock); - kfree(fh->ov.clips); + mutex_lock(&fh->cap.vb_lock); + kfree(fh->ov.clips); fh->ov.clips = clips; fh->ov.nclips = n; @@ -2376,7 +2376,7 @@ static int setup_window(struct bttv_fh *fh, struct bttv *btv, bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new); retval = bttv_switch_overlay(btv,fh,new); } - mutex_unlock(&fh->cap.lock); + mutex_unlock(&fh->cap.vb_lock); return retval; } @@ -2576,7 +2576,7 @@ static int bttv_s_fmt_cap(struct file *file, void *priv, fmt = format_by_fourcc(f->fmt.pix.pixelformat); /* update our state informations */ - mutex_lock(&fh->cap.lock); + mutex_lock(&fh->cap.vb_lock); fh->fmt = fmt; fh->cap.field = f->fmt.pix.field; fh->cap.last = V4L2_FIELD_NONE; @@ -2585,7 +2585,7 @@ static int bttv_s_fmt_cap(struct file *file, void *priv, btv->init.fmt = fmt; btv->init.width = f->fmt.pix.width; btv->init.height = f->fmt.pix.height; - mutex_unlock(&fh->cap.lock); + mutex_unlock(&fh->cap.vb_lock); return 0; } @@ -2611,11 +2611,11 @@ static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf) unsigned int i; struct bttv_fh *fh = priv; - mutex_lock(&fh->cap.lock); + mutex_lock(&fh->cap.vb_lock); retval = videobuf_mmap_setup(&fh->cap, gbuffers, gbufsize, V4L2_MEMORY_MMAP); if (retval < 0) { - mutex_unlock(&fh->cap.lock); + mutex_unlock(&fh->cap.vb_lock); return retval; } @@ -2627,7 +2627,7 @@ static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf) for (i = 0; i < gbuffers; i++) mbuf->offsets[i] = i * gbufsize; - mutex_unlock(&fh->cap.lock); + mutex_unlock(&fh->cap.vb_lock); return 0; } #endif @@ -2756,10 +2756,11 @@ static int bttv_overlay(struct file *file, void *f, unsigned int on) if (!check_alloc_btres(btv, fh, RESOURCE_OVERLAY)) return -EBUSY; - mutex_lock(&fh->cap.lock); + mutex_lock(&fh->cap.vb_lock); if (on) { fh->ov.tvnorm = btv->tvnorm; new = videobuf_pci_alloc(sizeof(*new)); + new->crop = btv->crop[!!fh->do_crop].rect; bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new); } else { new = NULL; @@ -2767,7 +2768,7 @@ static int bttv_overlay(struct file *file, void *f, unsigned int on) /* switch over */ retval = bttv_switch_overlay(btv, fh, new); - mutex_unlock(&fh->cap.lock); + mutex_unlock(&fh->cap.vb_lock); return retval; } @@ -2806,7 +2807,7 @@ static int bttv_s_fbuf(struct file *file, void *f, } /* ok, accept it */ - mutex_lock(&fh->cap.lock); + mutex_lock(&fh->cap.vb_lock); btv->fbuf.base = fb->base; btv->fbuf.fmt.width = fb->fmt.width; btv->fbuf.fmt.height = fb->fmt.height; @@ -2838,7 +2839,7 @@ static int bttv_s_fbuf(struct file *file, void *f, retval = bttv_switch_overlay(btv, fh, new); } } - mutex_unlock(&fh->cap.lock); + mutex_unlock(&fh->cap.vb_lock); return retval; } @@ -3090,7 +3091,7 @@ static int bttv_s_crop(struct file *file, void *f, struct v4l2_crop *crop) fh->do_crop = 1; - mutex_lock(&fh->cap.lock); + mutex_lock(&fh->cap.vb_lock); if (fh->width < c.min_scaled_width) { fh->width = c.min_scaled_width; @@ -3108,7 +3109,7 @@ static int bttv_s_crop(struct file *file, void *f, struct v4l2_crop *crop) btv->init.height = c.max_scaled_height; } - mutex_unlock(&fh->cap.lock); + mutex_unlock(&fh->cap.vb_lock); return 0; } @@ -3177,30 +3178,25 @@ static unsigned int bttv_poll(struct file *file, poll_table *wait) buf = list_entry(fh->cap.stream.next,struct bttv_buffer,vb.stream); } else { /* read() capture */ - mutex_lock(&fh->cap.lock); + mutex_lock(&fh->cap.vb_lock); if (NULL == fh->cap.read_buf) { /* need to capture a new frame */ - if (locked_btres(fh->btv,RESOURCE_VIDEO_STREAM)) { - mutex_unlock(&fh->cap.lock); - return POLLERR; - } + if (locked_btres(fh->btv,RESOURCE_VIDEO_STREAM)) + goto err; fh->cap.read_buf = videobuf_pci_alloc(fh->cap.msize); - if (NULL == fh->cap.read_buf) { - mutex_unlock(&fh->cap.lock); - return POLLERR; - } + if (NULL == fh->cap.read_buf) + goto err; fh->cap.read_buf->memory = V4L2_MEMORY_USERPTR; field = videobuf_next_field(&fh->cap); if (0 != fh->cap.ops->buf_prepare(&fh->cap,fh->cap.read_buf,field)) { kfree (fh->cap.read_buf); fh->cap.read_buf = NULL; - mutex_unlock(&fh->cap.lock); - return POLLERR; + goto err; } fh->cap.ops->buf_queue(&fh->cap,fh->cap.read_buf); fh->cap.read_off = 0; } - mutex_unlock(&fh->cap.lock); + mutex_unlock(&fh->cap.vb_lock); buf = (struct bttv_buffer*)fh->cap.read_buf; } @@ -3209,6 +3205,9 @@ static unsigned int bttv_poll(struct file *file, poll_table *wait) buf->vb.state == VIDEOBUF_ERROR) return POLLIN|POLLRDNORM; return 0; +err: + mutex_unlock(&fh->cap.vb_lock); + return POLLERR; } static int bttv_open(struct inode *inode, struct file *file) diff --git a/drivers/media/video/bt8xx/bttv-vbi.c b/drivers/media/video/bt8xx/bttv-vbi.c index 1f0cc79e2a33..75fa82c7c735 100644 --- a/drivers/media/video/bt8xx/bttv-vbi.c +++ b/drivers/media/video/bt8xx/bttv-vbi.c @@ -352,13 +352,13 @@ int bttv_s_fmt_vbi(struct file *file, void *f, struct v4l2_format *frt) because vbi_fmt.end counts field lines times two. */ end = max(frt->fmt.vbi.start[0], start1) * 2 + 2; - mutex_lock(&fh->vbi.lock); + mutex_lock(&fh->vbi.vb_lock); fh->vbi_fmt.fmt = frt->fmt.vbi; fh->vbi_fmt.tvnorm = tvnorm; fh->vbi_fmt.end = end; - mutex_unlock(&fh->vbi.lock); + mutex_unlock(&fh->vbi.vb_lock); rc = 0; diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c index 0aedbeaf94cd..e357f415db06 100644 --- a/drivers/media/video/cx88/cx88-mpeg.c +++ b/drivers/media/video/cx88/cx88-mpeg.c @@ -609,13 +609,19 @@ static int cx8802_request_acquire(struct cx8802_driver *drv) struct cx88_core *core = drv->core; /* Fail a request for hardware if the device is busy. */ - if (core->active_type_id != CX88_BOARD_NONE) + if (core->active_type_id != CX88_BOARD_NONE && + core->active_type_id != drv->type_id) return -EBUSY; if (drv->advise_acquire) { - core->active_type_id = drv->type_id; - drv->advise_acquire(drv); + mutex_lock(&drv->core->lock); + core->active_ref++; + if (core->active_type_id == CX88_BOARD_NONE) { + core->active_type_id = drv->type_id; + drv->advise_acquire(drv); + } + mutex_unlock(&drv->core->lock); mpeg_dbg(1,"%s() Post acquire GPIO=%x\n", __FUNCTION__, cx_read(MO_GP0_IO)); } @@ -628,12 +634,14 @@ static int cx8802_request_release(struct cx8802_driver *drv) { struct cx88_core *core = drv->core; - if (drv->advise_release) + mutex_lock(&drv->core->lock); + if (drv->advise_release && --core->active_ref == 0) { drv->advise_release(drv); core->active_type_id = CX88_BOARD_NONE; mpeg_dbg(1,"%s() Post release GPIO=%x\n", __FUNCTION__, cx_read(MO_GP0_IO)); } + mutex_unlock(&drv->core->lock); return 0; } diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index 4e823f2a539a..37e6d2e4002f 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -336,6 +336,7 @@ struct cx88_core { /* cx88-video needs to access cx8802 for hybrid tuner pll access. */ struct cx8802_dev *dvbdev; enum cx88_board_type active_type_id; + int active_ref; }; struct cx8800_dev; diff --git a/drivers/media/video/em28xx/em28xx-audio.c b/drivers/media/video/em28xx/em28xx-audio.c index 941357c4f3f5..8c67f678266a 100644 --- a/drivers/media/video/em28xx/em28xx-audio.c +++ b/drivers/media/video/em28xx/em28xx-audio.c @@ -35,7 +35,6 @@ #include #include #include -#include #include #include #include @@ -270,8 +269,11 @@ static int snd_em28xx_capture_open(struct snd_pcm_substream *substream) dprintk("opening device and trying to acquire exclusive lock\n"); /* Sets volume, mute, etc */ + dev->mute = 0; + mutex_lock(&dev->lock); ret = em28xx_audio_analog_set(dev); + mutex_unlock(&dev->lock); if (ret < 0) goto err; @@ -303,7 +305,9 @@ static int snd_em28xx_pcm_close(struct snd_pcm_substream *substream) dprintk("closing device\n"); dev->mute = 1; + mutex_lock(&dev->lock); em28xx_audio_analog_set(dev); + mutex_unlock(&dev->lock); if (dev->adev->users == 0 && dev->adev->shutdown == 1) { dprintk("audio users: %d\n", dev->adev->users); diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 2159d0160df2..aae7753fef11 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -393,15 +393,15 @@ struct em28xx_board em28xx_boards[] = { .input = { { .type = EM28XX_VMUX_TELEVISION, .vmux = SAA7115_COMPOSITE2, - .amux = 1, + .amux = EM28XX_AMUX_LINE_IN, }, { .type = EM28XX_VMUX_COMPOSITE1, .vmux = SAA7115_COMPOSITE0, - .amux = 1, + .amux = EM28XX_AMUX_LINE_IN, }, { .type = EM28XX_VMUX_SVIDEO, .vmux = SAA7115_SVIDEO3, - .amux = 1, + .amux = EM28XX_AMUX_LINE_IN, } }, }, }; @@ -441,6 +441,8 @@ struct usb_device_id em28xx_id_table [] = { .driver_info = EM2820_BOARD_PINNACLE_DVC_90 }, { USB_DEVICE(0x2040, 0x6500), .driver_info = EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900 }, + { USB_DEVICE(0x2040, 0x6502), + .driver_info = EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900 }, { USB_DEVICE(0x2040, 0x6513), .driver_info = EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950 }, { USB_DEVICE(0x0ccd, 0x0042), diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index f6b78357f0e5..7d1537cab867 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c @@ -72,7 +72,8 @@ u32 em28xx_request_buffers(struct em28xx *dev, u32 count) const size_t imagesize = PAGE_ALIGN(dev->frame_size); /*needs to be page aligned cause the buffers can be mapped individually! */ void *buff = NULL; u32 i; - em28xx_coredbg("requested %i buffers with size %zi", count, imagesize); + em28xx_coredbg("requested %i buffers with size %zi\n", + count, imagesize); if (count > EM28XX_NUM_FRAMES) count = EM28XX_NUM_FRAMES; @@ -150,7 +151,7 @@ int em28xx_read_reg_req_len(struct em28xx *dev, u8 req, u16 reg, if (reg_debug){ printk(ret < 0 ? " failed!\n" : "%02x values: ", ret); for (byte = 0; byte < len; byte++) { - printk(" %02x", buf[byte]); + printk(" %02x", (unsigned char)buf[byte]); } printk("\n"); } @@ -177,7 +178,8 @@ int em28xx_read_reg_req(struct em28xx *dev, u8 req, u16 reg) 0x0000, reg, &val, 1, HZ); if (reg_debug) - printk(ret < 0 ? " failed!\n" : "%02x\n", val); + printk(ret < 0 ? " failed!\n" : + "%02x\n", (unsigned char) val); if (ret < 0) return ret; @@ -237,7 +239,7 @@ int em28xx_write_regs(struct em28xx *dev, u16 reg, char *buf, int len) * sets only some bits (specified by bitmask) of a register, by first reading * the actual value */ -int em28xx_write_reg_bits(struct em28xx *dev, u16 reg, u8 val, +static int em28xx_write_reg_bits(struct em28xx *dev, u16 reg, u8 val, u8 bitmask) { int oldval; @@ -254,26 +256,31 @@ int em28xx_write_reg_bits(struct em28xx *dev, u16 reg, u8 val, */ static int em28xx_write_ac97(struct em28xx *dev, u8 reg, u8 *val) { - int ret; + int ret, i; u8 addr = reg & 0x7f; if ((ret = em28xx_write_regs(dev, AC97LSB_REG, val, 2)) < 0) return ret; if ((ret = em28xx_write_regs(dev, AC97ADDR_REG, &addr, 1)) < 0) return ret; - if ((ret = em28xx_read_reg(dev, AC97BUSY_REG)) < 0) - return ret; - else if (((u8) ret) & 0x01) { - em28xx_warn ("AC97 command still being executed: not handled properly!\n"); + + /* Wait up to 50 ms for AC97 command to complete */ + for (i = 0; i < 10; i++) { + if ((ret = em28xx_read_reg(dev, AC97BUSY_REG)) < 0) + return ret; + if (!((u8) ret) & 0x01) + return 0; + msleep(5); } + em28xx_warn ("AC97 command still being executed: not handled properly!\n"); return 0; } -int em28xx_set_audio_source(struct em28xx *dev) +static int em28xx_set_audio_source(struct em28xx *dev) { static char *enable = "\x08\x08"; static char *disable = "\x08\x88"; char *video = enable, *line = disable; - int ret, no_ac97; + int ret; u8 input; if (dev->is_em2800) { @@ -293,11 +300,9 @@ int em28xx_set_audio_source(struct em28xx *dev) switch (dev->ctl_ainput) { case EM28XX_AMUX_VIDEO: input = EM28XX_AUDIO_SRC_TUNER; - no_ac97 = 1; break; case EM28XX_AMUX_LINE_IN: input = EM28XX_AUDIO_SRC_LINE; - no_ac97 = 1; break; case EM28XX_AMUX_AC97_VIDEO: input = EM28XX_AUDIO_SRC_LINE; @@ -313,12 +318,11 @@ int em28xx_set_audio_source(struct em28xx *dev) ret = em28xx_write_reg_bits(dev, AUDIOSRC_REG, input, 0xc0); if (ret < 0) return ret; + msleep(5); - if (no_ac97) - return 0; - - /* Sets AC97 mixer registers */ - + /* Sets AC97 mixer registers + This is seems to be needed, even for non-ac97 configs + */ ret = em28xx_write_ac97(dev, VIDEO_AC97, video); if (ret < 0) return ret; @@ -337,9 +341,10 @@ int em28xx_audio_analog_set(struct em28xx *dev) s[0] |= 0x1f - dev->volume; s[1] |= 0x1f - dev->volume; - if (dev->mute) - s[1] |= 0x80; + /* Mute */ + s[1] |= 0x80; ret = em28xx_write_ac97(dev, MASTER_AC97, s); + if (ret < 0) return ret; @@ -357,6 +362,11 @@ int em28xx_audio_analog_set(struct em28xx *dev) /* Selects the proper audio input */ ret = em28xx_set_audio_source(dev); + /* Unmute device */ + if (!dev->mute) + s[1] &= ~0x80; + ret = em28xx_write_ac97(dev, MASTER_AC97, s); + return ret; } EXPORT_SYMBOL_GPL(em28xx_audio_analog_set); @@ -667,7 +677,7 @@ static void em28xx_isocIrq(struct urb *urb) continue; } if (urb->iso_frame_desc[i].actual_length > - dev->max_pkt_size) { + urb->iso_frame_desc[i].length) { em28xx_isocdbg("packet bigger than packet size"); continue; } @@ -713,8 +723,11 @@ void em28xx_uninit_isoc(struct em28xx *dev) for (i = 0; i < EM28XX_NUM_BUFS; i++) { if (dev->urb[i]) { usb_kill_urb(dev->urb[i]); - if (dev->transfer_buffer[i]){ - usb_buffer_free(dev->udev,(EM28XX_NUM_PACKETS*dev->max_pkt_size),dev->transfer_buffer[i],dev->urb[i]->transfer_dma); + if (dev->transfer_buffer[i]) { + usb_buffer_free(dev->udev, + dev->urb[i]->transfer_buffer_length, + dev->transfer_buffer[i], + dev->urb[i]->transfer_dma); } usb_free_urb(dev->urb[i]); } @@ -732,7 +745,10 @@ int em28xx_init_isoc(struct em28xx *dev) { /* change interface to 3 which allows the biggest packet sizes */ int i, errCode; - const int sb_size = EM28XX_NUM_PACKETS * dev->max_pkt_size; + int sb_size; + + em28xx_set_alternate(dev); + sb_size = EM28XX_NUM_PACKETS * dev->max_pkt_size; /* reset streaming vars */ dev->frame_current = NULL; @@ -741,7 +757,7 @@ int em28xx_init_isoc(struct em28xx *dev) /* allocate urbs */ for (i = 0; i < EM28XX_NUM_BUFS; i++) { struct urb *urb; - int j, k; + int j; /* allocate transfer buffer */ urb = usb_alloc_urb(EM28XX_NUM_PACKETS, GFP_KERNEL); if (!urb){ @@ -749,7 +765,9 @@ int em28xx_init_isoc(struct em28xx *dev) em28xx_uninit_isoc(dev); return -ENOMEM; } - dev->transfer_buffer[i] = usb_buffer_alloc(dev->udev, sb_size, GFP_KERNEL,&urb->transfer_dma); + dev->transfer_buffer[i] = usb_buffer_alloc(dev->udev, sb_size, + GFP_KERNEL, + &urb->transfer_dma); if (!dev->transfer_buffer[i]) { em28xx_errdev ("unable to allocate %i bytes for transfer buffer %i\n", @@ -762,22 +780,22 @@ int em28xx_init_isoc(struct em28xx *dev) urb->dev = dev->udev; urb->context = dev; urb->pipe = usb_rcvisocpipe(dev->udev, 0x82); - urb->transfer_flags = URB_ISO_ASAP; + urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; urb->interval = 1; urb->transfer_buffer = dev->transfer_buffer[i]; urb->complete = em28xx_isocIrq; urb->number_of_packets = EM28XX_NUM_PACKETS; urb->transfer_buffer_length = sb_size; - for (j = k = 0; j < EM28XX_NUM_PACKETS; - j++, k += dev->max_pkt_size) { - urb->iso_frame_desc[j].offset = k; - urb->iso_frame_desc[j].length = - dev->max_pkt_size; + for (j = 0; j < EM28XX_NUM_PACKETS; j++) { + urb->iso_frame_desc[j].offset = j * dev->max_pkt_size; + urb->iso_frame_desc[j].length = dev->max_pkt_size; } dev->urb[i] = urb; } /* submit urbs */ + em28xx_coredbg("Submitting %d urbs of %d packets (%d each)\n", + EM28XX_NUM_BUFS, EM28XX_NUM_PACKETS, dev->max_pkt_size); for (i = 0; i < EM28XX_NUM_BUFS; i++) { errCode = usb_submit_urb(dev->urb[i], GFP_KERNEL); if (errCode) { @@ -794,22 +812,31 @@ int em28xx_init_isoc(struct em28xx *dev) int em28xx_set_alternate(struct em28xx *dev) { int errCode, prev_alt = dev->alt; - dev->alt = alt; - if (dev->alt == 0) { - int i; - for(i=0;i< dev->num_alt; i++) - if(dev->alt_max_pkt_size[i]>dev->alt_max_pkt_size[dev->alt]) - dev->alt=i; - } + int i; + unsigned int min_pkt_size = dev->bytesperline+4; + + /* When image size is bigger than a ceirtain value, + the frame size should be increased, otherwise, only + green screen will be received. + */ + if (dev->frame_size > 720*240*2) + min_pkt_size *= 2; + + for (i = 0; i < dev->num_alt; i++) + if (dev->alt_max_pkt_size[i] >= min_pkt_size) + break; + dev->alt = i; if (dev->alt != prev_alt) { + em28xx_coredbg("minimum isoc packet size: %u (alt=%d)\n", + min_pkt_size, dev->alt); dev->max_pkt_size = dev->alt_max_pkt_size[dev->alt]; - em28xx_coredbg("setting alternate %d with wMaxPacketSize=%u\n", dev->alt, - dev->max_pkt_size); + em28xx_coredbg("setting alternate %d with wMaxPacketSize=%u\n", + dev->alt, dev->max_pkt_size); errCode = usb_set_interface(dev->udev, 0, dev->alt); if (errCode < 0) { em28xx_errdev ("cannot change alternate number to %d (error=%i)\n", - dev->alt, errCode); + dev->alt, errCode); return errCode; } } diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index a0c334672488..4abe6701a770 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -189,7 +189,7 @@ static void video_mux(struct em28xx *dev, int index) em28xx_i2c_call_clients(dev, VIDIOC_INT_S_AUDIO_ROUTING, &route); } - em28xx_set_audio_source(dev); + em28xx_audio_analog_set(dev); } /* Usage lock check functions */ @@ -830,6 +830,63 @@ static int vidioc_s_frequency(struct file *file, void *priv, return 0; } +#ifdef CONFIG_VIDEO_ADV_DEBUG +static int em28xx_reg_len(int reg) +{ + switch (reg) { + case AC97LSB_REG: + case HSCALELOW_REG: + case VSCALELOW_REG: + return 2; + default: + return 1; + } +} + +static int vidioc_g_register(struct file *file, void *priv, + struct v4l2_register *reg) +{ + struct em28xx_fh *fh = priv; + struct em28xx *dev = fh->dev; + int ret; + + if (!v4l2_chip_match_host(reg->match_type, reg->match_chip)) + return -EINVAL; + + if (em28xx_reg_len(reg->reg) == 1) { + ret = em28xx_read_reg(dev, reg->reg); + if (ret < 0) + return ret; + + reg->val = ret; + } else { + u64 val = 0; + ret = em28xx_read_reg_req_len(dev, USB_REQ_GET_STATUS, + reg->reg, (char *)&val, 2); + if (ret < 0) + return ret; + + reg->val = cpu_to_le64((__u64)val); + } + + return 0; +} + +static int vidioc_s_register(struct file *file, void *priv, + struct v4l2_register *reg) +{ + struct em28xx_fh *fh = priv; + struct em28xx *dev = fh->dev; + u64 buf; + + buf = le64_to_cpu((__u64)reg->val); + + return em28xx_write_regs(dev, reg->reg, (char *)&buf, + em28xx_reg_len(reg->reg)); +} +#endif + + static int vidioc_cropcap(struct file *file, void *priv, struct v4l2_cropcap *cc) { @@ -1295,8 +1352,6 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) filp->private_data = fh; if (dev->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) { - em28xx_set_alternate(dev); - dev->width = norm_maxw(dev); dev->height = norm_maxh(dev); dev->frame_size = dev->width * dev->height * 2; @@ -1305,6 +1360,7 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) dev->hscale = 0; dev->vscale = 0; + em28xx_set_alternate(dev); em28xx_capture_start(dev, 1); em28xx_resolution_set(dev); @@ -1730,6 +1786,10 @@ static const struct video_device em28xx_video_template = { .vidioc_s_tuner = vidioc_s_tuner, .vidioc_g_frequency = vidioc_g_frequency, .vidioc_s_frequency = vidioc_s_frequency, +#ifdef CONFIG_VIDEO_ADV_DEBUG + .vidioc_g_register = vidioc_g_register, + .vidioc_s_register = vidioc_s_register, +#endif .tvnorms = V4L2_STD_ALL, .current_norm = V4L2_STD_PAL, @@ -1752,6 +1812,10 @@ static struct video_device em28xx_radio_template = { .vidioc_s_ctrl = vidioc_s_ctrl, .vidioc_g_frequency = vidioc_g_frequency, .vidioc_s_frequency = vidioc_s_frequency, +#ifdef CONFIG_VIDEO_ADV_DEBUG + .vidioc_g_register = vidioc_g_register, + .vidioc_s_register = vidioc_s_register, +#endif }; /******************************** usb interface *****************************************/ @@ -1796,10 +1860,10 @@ void em28xx_unregister_extension(struct em28xx_ops *ops) } EXPORT_SYMBOL(em28xx_unregister_extension); -struct video_device *em28xx_vdev_init(struct em28xx *dev, - const struct video_device *template, - const int type, - const char *type_name) +static struct video_device *em28xx_vdev_init(struct em28xx *dev, + const struct video_device *template, + const int type, + const char *type_name) { struct video_device *vfd; @@ -2064,6 +2128,7 @@ static int em28xx_usb_probe(struct usb_interface *interface, snprintf(dev->name, 29, "em28xx #%d", nr); dev->devno = nr; dev->model = id->driver_info; + dev->alt = -1; /* Checks if audio is provided by some interface */ for (i = 0; i < udev->config->desc.bNumInterfaces; i++) { diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index f3bad0c1c517..04e0e48ecabe 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -33,7 +33,7 @@ #define UNSET -1 /* maximum number of em28xx boards */ -#define EM28XX_MAXBOARDS 1 /*FIXME: should be bigger */ +#define EM28XX_MAXBOARDS 4 /*FIXME: should be bigger */ /* maximum number of frames that can be queued */ #define EM28XX_NUM_FRAMES 5 @@ -345,9 +345,6 @@ int em28xx_read_reg(struct em28xx *dev, u16 reg); int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf, int len); int em28xx_write_regs(struct em28xx *dev, u16 reg, char *buf, int len); -int em28xx_write_reg_bits(struct em28xx *dev, u16 reg, u8 val, - u8 bitmask); -int em28xx_set_audio_source(struct em28xx *dev); int em28xx_audio_analog_set(struct em28xx *dev); int em28xx_colorlevels_set_default(struct em28xx *dev); diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 7d7f383b404f..262830da08c8 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -928,27 +928,38 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, + .gpiomask = 0x03, .inputs = {{ .name = name_tv, .vmux = 1, .amux = TV, .tv = 1, - },{ + .gpio = 0x00, + }, { .name = name_comp1, - .vmux = 0, - .amux = LINE2, - },{ - .name = name_comp2, .vmux = 3, - .amux = LINE2, - },{ + .amux = LINE1, + .gpio = 0x02, + }, { + .name = name_comp2, + .vmux = 0, + .amux = LINE1, + .gpio = 0x02, + }, { .name = name_svideo, .vmux = 8, - .amux = LINE2, - }}, + .amux = LINE1, + .gpio = 0x02, + } }, .radio = { .name = name_radio, - .amux = LINE2, + .amux = LINE1, + .gpio = 0x01, + }, + .mute = { + .name = name_mute, + .amux = TV, + .gpio = 0x00, }, }, [SAA7134_BOARD_BMK_MPEX_TUNER] = { @@ -3912,6 +3923,74 @@ struct saa7134_board saa7134_boards[] = { }, .mpeg = SAA7134_MPEG_EMPRESS, }, + [SAA7134_BOARD_TWINHAN_DTV_DVB_3056] = { + .name = "Twinhan Hybrid DTV-DVB 3056 PCI", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_TDA8290, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tuner_config = 2, + .mpeg = SAA7134_MPEG_DVB, + .gpiomask = 0x0200000, + .inputs = {{ + .name = name_tv, + .vmux = 1, + .amux = TV, + .tv = 1, + }, { + .name = name_comp1, + .vmux = 3, + .amux = LINE1, + }, { + .name = name_svideo, + .vmux = 8, /* untested */ + .amux = LINE1, + } }, + .radio = { + .name = name_radio, + .amux = TV, + .gpio = 0x0200000, + }, + }, + [SAA7134_BOARD_GENIUS_TVGO_A11MCE] = { + /* Adrian Pardini */ + .name = "Genius TVGO AM11MCE", + .audio_clock = 0x00200000, + .tuner_type = TUNER_TNF_5335MF, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .gpiomask = 0xf000, + .inputs = {{ + .name = name_tv_mono, + .vmux = 1, + .amux = LINE2, + .gpio = 0x0000, + .tv = 1, + }, { + .name = name_comp1, + .vmux = 3, + .amux = LINE1, + .gpio = 0x2000, + .tv = 1 + }, { + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + .gpio = 0x2000, + } }, + .radio = { + .name = name_radio, + .amux = LINE2, + .gpio = 0x1000, + }, + .mute = { + .name = name_mute, + .amux = LINE2, + .gpio = 0x6000, + }, + }, }; const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); @@ -4509,6 +4588,12 @@ struct pci_device_id saa7134_pci_tbl[] = { .subdevice = 0x3502, /* whats the difference to 0x3306 ?*/ .driver_data = SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS, },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x5168, + .subdevice = 0x3307, /* FlyDVB-T Hybrid Mini PCI */ + .driver_data = SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS, + }, { .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7133, .subvendor = 0x16be, @@ -4521,6 +4606,12 @@ struct pci_device_id saa7134_pci_tbl[] = { .subdevice = 0x0008, .driver_data = SAA7134_BOARD_MEDION_MD8800_QUADRO, },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x16be, + .subdevice = 0x000d, /* triple CTX948_V1.1.1 */ + .driver_data = SAA7134_BOARD_MEDION_MD8800_QUADRO, + }, { .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7133, .subvendor = 0x1461, @@ -4843,7 +4934,13 @@ struct pci_device_id saa7134_pci_tbl[] = { .device = PCI_DEVICE_ID_PHILIPS_SAA7133, .subvendor = 0x4e42, .subdevice = 0x3502, - .driver_data = SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS + .driver_data = SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS, + }, { + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x1822, /*Twinhan Technology Co. Ltd*/ + .subdevice = 0x0022, + .driver_data = SAA7134_BOARD_TWINHAN_DTV_DVB_3056, },{ /* --- boards without eeprom + subsystem ID --- */ .vendor = PCI_VENDOR_ID_PHILIPS, @@ -4995,6 +5092,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) case SAA7134_BOARD_BEHOLD_409: case SAA7134_BOARD_BEHOLD_505FM: case SAA7134_BOARD_BEHOLD_507_9FM: + case SAA7134_BOARD_GENIUS_TVGO_A11MCE: dev->has_remote = SAA7134_REMOTE_GPIO; break; case SAA7134_BOARD_FLYDVBS_LR300: @@ -5232,7 +5330,8 @@ int saa7134_board_init2(struct saa7134_dev *dev) case SAA7134_BOARD_ASUSTeK_P7131_DUAL: case SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA: case SAA7134_BOARD_MEDION_MD8800_QUADRO: - case SAA7134_BOARD_AVERMEDIA_SUPER_007: + case SAA7134_BOARD_AVERMEDIA_SUPER_007: + case SAA7134_BOARD_TWINHAN_DTV_DVB_3056: /* this is a hybrid board, initialize to analog mode * and configure firmware eeprom address */ diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index a9ca5730826f..ea2be9eceeb8 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -779,6 +779,21 @@ static struct tda1004x_config avermedia_super_007_config = { .request_firmware = philips_tda1004x_request_firmware }; +static struct tda1004x_config twinhan_dtv_dvb_3056_config = { + .demod_address = 0x08, + .invert = 1, + .invert_oclk = 0, + .xtal_freq = TDA10046_XTAL_16M, + .agc_config = TDA10046_AGC_TDA827X, + .gpio_config = TDA10046_GP01_I, + .if_freq = TDA10046_FREQ_045, + .i2c_gate = 0x42, + .tuner_address = 0x61, + .tuner_config = 2, + .antenna_switch = 1, + .request_firmware = philips_tda1004x_request_firmware +}; + /* ------------------------------------------------------------------ * special case: this card uses saa713x GPIO22 for the mode switch */ @@ -826,6 +841,7 @@ static struct tda1004x_config ads_tech_duo_config = { static struct tda10086_config flydvbs = { .demod_address = 0x0e, .invert = 0, + .diseqc_tone = 0, }; /* ================================================================== @@ -940,9 +956,9 @@ static int dvb_init(struct saa7134_dev *dev) configure_tda827x_fe(dev, &tda827x_lifeview_config); break; case SAA7134_BOARD_FLYDVB_TRIO: - if(! use_frontend) { //terrestrial + if(! use_frontend) { /* terrestrial */ configure_tda827x_fe(dev, &lifeview_trio_config); - } else { //satellite + } else { /* satellite */ dev->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs, &dev->i2c_adap); if (dev->dvb.frontend) { if (dvb_attach(tda826x_attach, dev->dvb.frontend, 0x63, @@ -1007,8 +1023,9 @@ static int dvb_init(struct saa7134_dev *dev) } break; case SAA7134_BOARD_ASUS_EUROPA2_HYBRID: - dev->dvb.frontend = tda10046_attach(&medion_cardbus, - &dev->i2c_adap); + dev->dvb.frontend = dvb_attach(tda10046_attach, + &medion_cardbus, + &dev->i2c_adap); if (dev->dvb.frontend) { dev->original_demod_sleep = dev->dvb.frontend->ops.sleep; dev->dvb.frontend->ops.sleep = philips_europa_demod_sleep; @@ -1044,6 +1061,9 @@ static int dvb_init(struct saa7134_dev *dev) case SAA7134_BOARD_AVERMEDIA_SUPER_007: configure_tda827x_fe(dev, &avermedia_super_007_config); break; + case SAA7134_BOARD_TWINHAN_DTV_DVB_3056: + configure_tda827x_fe(dev, &twinhan_dtv_dvb_3056_config); + break; default: wprintk("Huh? unknown DVB card?\n"); break; diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c index b1b01fa86720..3d2ec30de227 100644 --- a/drivers/media/video/saa7134/saa7134-empress.c +++ b/drivers/media/video/saa7134/saa7134-empress.c @@ -87,7 +87,7 @@ static int ts_open(struct inode *inode, struct file *file) dprintk("open minor=%d\n",minor); err = -EBUSY; - if (!mutex_trylock(&dev->empress_tsq.lock)) + if (!mutex_trylock(&dev->empress_tsq.vb_lock)) goto done; if (dev->empress_users) goto done_up; @@ -101,7 +101,7 @@ static int ts_open(struct inode *inode, struct file *file) err = 0; done_up: - mutex_unlock(&dev->empress_tsq.lock); + mutex_unlock(&dev->empress_tsq.vb_lock); done: return err; } @@ -110,7 +110,6 @@ static int ts_release(struct inode *inode, struct file *file) { struct saa7134_dev *dev = file->private_data; - mutex_lock(&dev->empress_tsq.lock); videobuf_stop(&dev->empress_tsq); videobuf_mmap_free(&dev->empress_tsq); dev->empress_users--; @@ -122,7 +121,6 @@ static int ts_release(struct inode *inode, struct file *file) saa_writeb(SAA7134_AUDIO_MUTE_CTRL, saa_readb(SAA7134_AUDIO_MUTE_CTRL) | (1 << 6)); - mutex_unlock(&dev->empress_tsq.lock); return 0; } diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index 0db955c2d9b9..b4188819782f 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -406,6 +406,12 @@ int saa7134_input_init1(struct saa7134_dev *dev) mask_keyup = 0x8000000; polling = 50; //ms break; + case SAA7134_BOARD_GENIUS_TVGO_A11MCE: + ir_codes = ir_codes_genius_tvgo_a11mce; + mask_keycode = 0xff; + mask_keydown = 0xf00000; + polling = 50; /* ms */ + break; } if (NULL == ir_codes) { printk("%s: Oops: IR config error [card=%d]\n", diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c index 1184d359e848..39c41ad97d0e 100644 --- a/drivers/media/video/saa7134/saa7134-video.c +++ b/drivers/media/video/saa7134/saa7134-video.c @@ -1414,21 +1414,17 @@ video_poll(struct file *file, struct poll_table_struct *wait) if (!list_empty(&fh->cap.stream)) buf = list_entry(fh->cap.stream.next, struct videobuf_buffer, stream); } else { - mutex_lock(&fh->cap.lock); + mutex_lock(&fh->cap.vb_lock); if (UNSET == fh->cap.read_off) { /* need to capture a new frame */ - if (res_locked(fh->dev,RESOURCE_VIDEO)) { - mutex_unlock(&fh->cap.lock); - return POLLERR; - } - if (0 != fh->cap.ops->buf_prepare(&fh->cap,fh->cap.read_buf,fh->cap.field)) { - mutex_unlock(&fh->cap.lock); - return POLLERR; - } + if (res_locked(fh->dev,RESOURCE_VIDEO)) + goto err; + if (0 != fh->cap.ops->buf_prepare(&fh->cap,fh->cap.read_buf,fh->cap.field)) + goto err; fh->cap.ops->buf_queue(&fh->cap,fh->cap.read_buf); fh->cap.read_off = 0; } - mutex_unlock(&fh->cap.lock); + mutex_unlock(&fh->cap.vb_lock); buf = fh->cap.read_buf; } @@ -1440,6 +1436,10 @@ video_poll(struct file *file, struct poll_table_struct *wait) buf->state == VIDEOBUF_ERROR) return POLLIN|POLLRDNORM; return 0; + +err: + mutex_unlock(&fh->cap.vb_lock); + return POLLERR; } static int video_release(struct inode *inode, struct file *file) diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index b88ca995fafb..f940d0254798 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -252,6 +252,8 @@ struct saa7134_format { #define SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM 128 #define SAA7134_BOARD_BEHOLD_607_9FM 129 #define SAA7134_BOARD_BEHOLD_M6 130 +#define SAA7134_BOARD_TWINHAN_DTV_DVB_3056 131 +#define SAA7134_BOARD_GENIUS_TVGO_A11MCE 132 #define SAA7134_MAXBOARDS 8 #define SAA7134_INPUT_MAX 8 diff --git a/drivers/media/video/stk-sensor.c b/drivers/media/video/stk-sensor.c index 4a9a0b62efa3..e546b014d7ad 100644 --- a/drivers/media/video/stk-sensor.c +++ b/drivers/media/video/stk-sensor.c @@ -225,7 +225,7 @@ /* Returns 0 if OK */ -int stk_sensor_outb(struct stk_camera *dev, u8 reg, u8 val) +static int stk_sensor_outb(struct stk_camera *dev, u8 reg, u8 val) { int i = 0; int tmpval = 0; @@ -250,7 +250,7 @@ int stk_sensor_outb(struct stk_camera *dev, u8 reg, u8 val) return 0; } -int stk_sensor_inb(struct stk_camera *dev, u8 reg, u8 *val) +static int stk_sensor_inb(struct stk_camera *dev, u8 reg, u8 *val) { int i = 0; int tmpval = 0; @@ -380,7 +380,7 @@ int stk_sensor_init(struct stk_camera *dev) STK_ERROR("Strange error reading sensor ID\n"); return -ENODEV; } - if (idh != 0x7F || idl != 0xA2) { + if (idh != 0x7f || idl != 0xa2) { STK_ERROR("Huh? you don't have a sensor from ovt\n"); return -ENODEV; } @@ -409,6 +409,19 @@ static struct regval ov_fmt_uyvy[] = { {REG_COM15, COM15_R00FF }, {0xff, 0xff}, /* END MARKER */ }; +/* V4L2_PIX_FMT_YUYV */ +static struct regval ov_fmt_yuyv[] = { + {REG_TSLB, 0 }, + { 0x4f, 0x80 }, /* "matrix coefficient 1" */ + { 0x50, 0x80 }, /* "matrix coefficient 2" */ + { 0x51, 0 }, /* vb */ + { 0x52, 0x22 }, /* "matrix coefficient 4" */ + { 0x53, 0x5e }, /* "matrix coefficient 5" */ + { 0x54, 0x80 }, /* "matrix coefficient 6" */ + {REG_COM13, COM13_UVSAT|COM13_CMATRIX}, + {REG_COM15, COM15_R00FF }, + {0xff, 0xff}, /* END MARKER */ +}; /* V4L2_PIX_FMT_RGB565X rrrrrggg gggbbbbb */ static struct regval ov_fmt_rgbr[] = { @@ -519,6 +532,10 @@ int stk_sensor_configure(struct stk_camera *dev) com7 |= COM7_YUV; rv = ov_fmt_uyvy; break; + case V4L2_PIX_FMT_YUYV: + com7 |= COM7_YUV; + rv = ov_fmt_yuyv; + break; case V4L2_PIX_FMT_RGB565: com7 |= COM7_RGB; rv = ov_fmt_rgbp; diff --git a/drivers/media/video/stk-webcam.c b/drivers/media/video/stk-webcam.c index d37e5e2594b4..ceba45ad0294 100644 --- a/drivers/media/video/stk-webcam.c +++ b/drivers/media/video/stk-webcam.c @@ -63,7 +63,7 @@ static struct usb_device_id stkwebcam_table[] = { }; MODULE_DEVICE_TABLE(usb, stkwebcam_table); -void stk_camera_cleanup(struct kref *kref) +static void stk_camera_cleanup(struct kref *kref) { struct stk_camera *dev = to_stk_camera(kref); @@ -682,6 +682,7 @@ static int v4l_stk_open(struct inode *inode, struct file *fp) return -ENXIO; fp->private_data = vdev; kref_get(&dev->kref); + usb_autopm_get_interface(dev->interface); return 0; } @@ -703,6 +704,7 @@ static int v4l_stk_release(struct inode *inode, struct file *fp) } if (dev->owner != fp) { + usb_autopm_put_interface(dev->interface); kref_put(&dev->kref, stk_camera_cleanup); return 0; } @@ -713,6 +715,7 @@ static int v4l_stk_release(struct inode *inode, struct file *fp) dev->owner = NULL; + usb_autopm_put_interface(dev->interface); kref_put(&dev->kref, stk_camera_cleanup); return 0; @@ -993,6 +996,10 @@ static int stk_vidioc_enum_fmt_cap(struct file *filp, fmtd->pixelformat = V4L2_PIX_FMT_SBGGR8; strcpy(fmtd->description, "Raw bayer"); break; + case 4: + fmtd->pixelformat = V4L2_PIX_FMT_YUYV; + strcpy(fmtd->description, "yuv4:2:2"); + break; default: return -EINVAL; } @@ -1048,6 +1055,7 @@ static int stk_vidioc_try_fmt_cap(struct file *filp, case V4L2_PIX_FMT_RGB565: case V4L2_PIX_FMT_RGB565X: case V4L2_PIX_FMT_UYVY: + case V4L2_PIX_FMT_YUYV: case V4L2_PIX_FMT_SBGGR8: break; default: @@ -1080,6 +1088,42 @@ static int stk_vidioc_try_fmt_cap(struct file *filp, return 0; } +static int stk_setup_format(struct stk_camera *dev) +{ + int i = 0; + int depth; + if (dev->vsettings.palette == V4L2_PIX_FMT_SBGGR8) + depth = 1; + else + depth = 2; + while (stk_sizes[i].m != dev->vsettings.mode + && i < ARRAY_SIZE(stk_sizes)) + i++; + if (i == ARRAY_SIZE(stk_sizes)) { + STK_ERROR("Something is broken in %s\n", __FUNCTION__); + return -EFAULT; + } + /* This registers controls some timings, not sure of what. */ + stk_camera_write_reg(dev, 0x001b, 0x0e); + if (dev->vsettings.mode == MODE_SXGA) + stk_camera_write_reg(dev, 0x001c, 0x0e); + else + stk_camera_write_reg(dev, 0x001c, 0x46); + /* + * Registers 0x0115 0x0114 are the size of each line (bytes), + * regs 0x0117 0x0116 are the heigth of the image. + */ + stk_camera_write_reg(dev, 0x0115, + ((stk_sizes[i].w * depth) >> 8) & 0xff); + stk_camera_write_reg(dev, 0x0114, + (stk_sizes[i].w * depth) & 0xff); + stk_camera_write_reg(dev, 0x0117, + (stk_sizes[i].h >> 8) & 0xff); + stk_camera_write_reg(dev, 0x0116, + stk_sizes[i].h & 0xff); + return stk_sensor_configure(dev); +} + static int stk_vidioc_s_fmt_cap(struct file *filp, void *priv, struct v4l2_format *fmtd) { @@ -1094,10 +1138,10 @@ static int stk_vidioc_s_fmt_cap(struct file *filp, return -EBUSY; if (dev->owner && dev->owner != filp) return -EBUSY; - dev->owner = filp; ret = stk_vidioc_try_fmt_cap(filp, priv, fmtd); if (ret) return ret; + dev->owner = filp; dev->vsettings.palette = fmtd->fmt.pix.pixelformat; stk_free_buffers(dev); @@ -1105,25 +1149,7 @@ static int stk_vidioc_s_fmt_cap(struct file *filp, dev->vsettings.mode = stk_sizes[fmtd->fmt.pix.priv].m; stk_initialise(dev); - /* This registers controls some timings, not sure of what. */ - stk_camera_write_reg(dev, 0x001b, 0x0e); - if (dev->vsettings.mode == MODE_SXGA) - stk_camera_write_reg(dev, 0x001c, 0x0e); - else - stk_camera_write_reg(dev, 0x001c, 0x46); - /* - * Registers 0x0115 0x0114 are the size of each line (bytes), - * regs 0x0117 0x0116 are the heigth of the image. - */ - stk_camera_write_reg(dev, 0x0115, - (fmtd->fmt.pix.bytesperline >> 8) & 0xff); - stk_camera_write_reg(dev, 0x0114, - fmtd->fmt.pix.bytesperline & 0xff); - stk_camera_write_reg(dev, 0x0117, - (fmtd->fmt.pix.height >> 8) & 0xff); - stk_camera_write_reg(dev, 0x0116, - fmtd->fmt.pix.height & 0xff); - return stk_sensor_configure(dev); + return stk_setup_format(dev); } static int stk_vidioc_reqbufs(struct file *filp, @@ -1288,6 +1314,9 @@ static struct file_operations v4l_stk_fops = { .poll = v4l_stk_poll, .mmap = v4l_stk_mmap, .ioctl = video_ioctl2, +#ifdef CONFIG_COMPAT + .compat_ioctl = v4l_compat_ioctl32, +#endif .llseek = no_llseek }; @@ -1403,7 +1432,7 @@ static int stk_camera_probe(struct usb_interface *interface, dev->vsettings.brightness = 0x7fff; dev->vsettings.palette = V4L2_PIX_FMT_RGB565; dev->vsettings.mode = MODE_VGA; - dev->frame_size = 640*480*2; + dev->frame_size = 640 * 480 * 2; INIT_LIST_HEAD(&dev->sio_avail); INIT_LIST_HEAD(&dev->sio_full); @@ -1417,6 +1446,7 @@ static int stk_camera_probe(struct usb_interface *interface, } stk_create_sysfs_files(&dev->vdev); + usb_autopm_enable(dev->interface); return 0; } @@ -1434,11 +1464,41 @@ static void stk_camera_disconnect(struct usb_interface *interface) kref_put(&dev->kref, stk_camera_cleanup); } +#ifdef CONFIG_PM +int stk_camera_suspend(struct usb_interface *intf, pm_message_t message) +{ + struct stk_camera *dev = usb_get_intfdata(intf); + if (is_streaming(dev)) { + stk_stop_stream(dev); + /* yes, this is ugly */ + set_streaming(dev); + } + return 0; +} + +int stk_camera_resume(struct usb_interface *intf) +{ + struct stk_camera *dev = usb_get_intfdata(intf); + if (!is_initialised(dev)) + return 0; + unset_initialised(dev); + stk_initialise(dev); + stk_setup_format(dev); + if (is_streaming(dev)) + stk_start_stream(dev); + return 0; +} +#endif + static struct usb_driver stk_camera_driver = { .name = "stkwebcam", .probe = stk_camera_probe, .disconnect = stk_camera_disconnect, .id_table = stkwebcam_table, +#ifdef CONFIG_PM + .suspend = stk_camera_suspend, + .resume = stk_camera_resume, +#endif }; diff --git a/drivers/media/video/stk-webcam.h b/drivers/media/video/stk-webcam.h index 7e989d1ac1e0..df4dfefc5327 100644 --- a/drivers/media/video/stk-webcam.h +++ b/drivers/media/video/stk-webcam.h @@ -79,6 +79,7 @@ enum stk_status { #define unset_present(dev) ((dev)->status &= \ ~(S_PRESENT|S_INITIALISED|S_STREAMING)) #define set_initialised(dev) ((dev)->status |= S_INITIALISED) +#define unset_initialised(dev) ((dev)->status &= ~S_INITIALISED) #define set_memallocd(dev) ((dev)->status |= S_MEMALLOCD) #define unset_memallocd(dev) ((dev)->status &= ~S_MEMALLOCD) #define set_streaming(dev) ((dev)->status |= S_STREAMING) @@ -127,8 +128,6 @@ void stk_camera_delete(struct kref *); int stk_camera_write_reg(struct stk_camera *, u16, u8); int stk_camera_read_reg(struct stk_camera *, u16, int *); -int stk_sensor_outb(struct stk_camera *dev, u8 reg, u8 val); -int stk_sensor_inb(struct stk_camera *dev, u8 reg, u8 *val); int stk_sensor_init(struct stk_camera *); int stk_sensor_configure(struct stk_camera *); int stk_sensor_sleep(struct stk_camera *dev); diff --git a/drivers/media/video/tcm825x.c b/drivers/media/video/tcm825x.c index 41cd6a0b0485..fb895f6684a3 100644 --- a/drivers/media/video/tcm825x.c +++ b/drivers/media/video/tcm825x.c @@ -851,7 +851,7 @@ static int tcm825x_probe(struct i2c_client *client) sensor->platform_data = client->dev.platform_data; if (sensor->platform_data == NULL - && !sensor->platform_data->is_okay()) + || !sensor->platform_data->is_okay()) return -ENODEV; sensor->v4l2_int_device = &tcm825x_int_device; diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index ba538f6fbcc3..78a09a2a4857 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -1038,7 +1038,7 @@ static int tuner_resume(struct i2c_client *c) /* ---------------------------------------------------------------------- */ -LIST_HEAD(tuner_list); +static LIST_HEAD(tuner_list); /* Search for existing radio and/or TV tuners on the given I2C adapter. Note that when this function is called from tuner_probe you can be diff --git a/drivers/media/video/tuner-xc2028.c b/drivers/media/video/tuner-xc2028.c index f191f6a48070..50cf876f020f 100644 --- a/drivers/media/video/tuner-xc2028.c +++ b/drivers/media/video/tuner-xc2028.c @@ -754,6 +754,9 @@ skip_std_specific: goto check_device; } + if (new_fw.type & FM) + goto check_device; + /* Load SCODE firmware, if exists */ tuner_dbg("Trying to load scode %d\n", new_fw.scode_nr); diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c index a75560540e79..01ebcec040c4 100644 --- a/drivers/media/video/tvaudio.c +++ b/drivers/media/video/tvaudio.c @@ -1571,14 +1571,14 @@ static int tvaudio_get_ctrl(struct CHIPSTATE *chip, ctrl->value=chip->muted; return 0; case V4L2_CID_AUDIO_VOLUME: - if (!desc->flags & CHIP_HAS_VOLUME) + if (!(desc->flags & CHIP_HAS_VOLUME)) break; ctrl->value = max(chip->left,chip->right); return 0; case V4L2_CID_AUDIO_BALANCE: { int volume; - if (!desc->flags & CHIP_HAS_VOLUME) + if (!(desc->flags & CHIP_HAS_VOLUME)) break; volume = max(chip->left,chip->right); if (volume) @@ -1621,7 +1621,7 @@ static int tvaudio_set_ctrl(struct CHIPSTATE *chip, { int volume,balance; - if (!desc->flags & CHIP_HAS_VOLUME) + if (!(desc->flags & CHIP_HAS_VOLUME)) break; volume = max(chip->left,chip->right); @@ -1642,7 +1642,7 @@ static int tvaudio_set_ctrl(struct CHIPSTATE *chip, case V4L2_CID_AUDIO_BALANCE: { int volume, balance; - if (!desc->flags & CHIP_HAS_VOLUME) + if (!(desc->flags & CHIP_HAS_VOLUME)) break; volume = max(chip->left,chip->right); @@ -1702,7 +1702,7 @@ static int chip_command(struct i2c_client *client, break; case V4L2_CID_AUDIO_VOLUME: case V4L2_CID_AUDIO_BALANCE: - if (!desc->flags & CHIP_HAS_VOLUME) + if (!(desc->flags & CHIP_HAS_VOLUME)) return -EINVAL; break; case V4L2_CID_AUDIO_BASS: diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c index 0b8fbad3c721..dc0da44a5af6 100644 --- a/drivers/media/video/tveeprom.c +++ b/drivers/media/video/tveeprom.c @@ -242,7 +242,7 @@ hauppauge_tuner[] = { TUNER_ABSENT, "TCL M2523_3DBH_E"}, { TUNER_ABSENT, "TCL M2523_3DIH_E"}, { TUNER_ABSENT, "TCL MFPE05_2_U"}, - { TUNER_ABSENT, "Philips FMD1216MEX"}, + { TUNER_PHILIPS_FMD1216ME_MK3, "Philips FMD1216MEX"}, { TUNER_ABSENT, "Philips FRH2036B"}, { TUNER_ABSENT, "Panasonic ENGF75_01GF"}, { TUNER_ABSENT, "MaxLinear MXL5005"}, diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c index c056ff6d810c..34deb68ae568 100644 --- a/drivers/media/video/v4l2-common.c +++ b/drivers/media/video/v4l2-common.c @@ -56,7 +56,6 @@ #include #include #include -#include #define __OLD_VIDIOC_ /* To allow fixing old calls*/ #include #include @@ -82,108 +81,6 @@ MODULE_LICENSE("GPL"); */ -char *v4l2_norm_to_name(v4l2_std_id id) -{ - char *name; - u32 myid = id; - - /* HACK: ppc32 architecture doesn't have __ucmpdi2 function to handle - 64 bit comparations. So, on that architecture, with some gcc variants, - compilation fails. Currently, the max value is 30bit wide. - */ - BUG_ON(myid != id); - - switch (myid) { - case V4L2_STD_PAL: - name="PAL"; break; - case V4L2_STD_PAL_BG: - name="PAL-BG"; break; - case V4L2_STD_PAL_DK: - name="PAL-DK"; break; - case V4L2_STD_PAL_B: - name="PAL-B"; break; - case V4L2_STD_PAL_B1: - name="PAL-B1"; break; - case V4L2_STD_PAL_G: - name="PAL-G"; break; - case V4L2_STD_PAL_H: - name="PAL-H"; break; - case V4L2_STD_PAL_I: - name="PAL-I"; break; - case V4L2_STD_PAL_D: - name="PAL-D"; break; - case V4L2_STD_PAL_D1: - name="PAL-D1"; break; - case V4L2_STD_PAL_K: - name="PAL-K"; break; - case V4L2_STD_PAL_M: - name="PAL-M"; break; - case V4L2_STD_PAL_N: - name="PAL-N"; break; - case V4L2_STD_PAL_Nc: - name="PAL-Nc"; break; - case V4L2_STD_PAL_60: - name="PAL-60"; break; - case V4L2_STD_NTSC: - name="NTSC"; break; - case V4L2_STD_NTSC_M: - name="NTSC-M"; break; - case V4L2_STD_NTSC_M_JP: - name="NTSC-M-JP"; break; - case V4L2_STD_NTSC_443: - name="NTSC-443"; break; - case V4L2_STD_NTSC_M_KR: - name="NTSC-M-KR"; break; - case V4L2_STD_SECAM: - name="SECAM"; break; - case V4L2_STD_SECAM_DK: - name="SECAM-DK"; break; - case V4L2_STD_SECAM_B: - name="SECAM-B"; break; - case V4L2_STD_SECAM_D: - name="SECAM-D"; break; - case V4L2_STD_SECAM_G: - name="SECAM-G"; break; - case V4L2_STD_SECAM_H: - name="SECAM-H"; break; - case V4L2_STD_SECAM_K: - name="SECAM-K"; break; - case V4L2_STD_SECAM_K1: - name="SECAM-K1"; break; - case V4L2_STD_SECAM_L: - name="SECAM-L"; break; - case V4L2_STD_SECAM_LC: - name="SECAM-LC"; break; - default: - name="Unknown"; break; - } - - return name; -} - -/* Fill in the fields of a v4l2_standard structure according to the - 'id' and 'transmission' parameters. Returns negative on error. */ -int v4l2_video_std_construct(struct v4l2_standard *vs, - int id, char *name) -{ - u32 index = vs->index; - - memset(vs, 0, sizeof(struct v4l2_standard)); - vs->index = index; - vs->id = id; - if (id & V4L2_STD_525_60) { - vs->frameperiod.numerator = 1001; - vs->frameperiod.denominator = 30000; - vs->framelines = 525; - } else { - vs->frameperiod.numerator = 1; - vs->frameperiod.denominator = 25; - vs->framelines = 625; - } - strlcpy(vs->name,name,sizeof(vs->name)); - return 0; -} - /* ----------------------------------------------------------------- */ /* priority handling */ @@ -196,6 +93,7 @@ int v4l2_prio_init(struct v4l2_prio_state *global) memset(global,0,sizeof(*global)); return 0; } +EXPORT_SYMBOL(v4l2_prio_init); int v4l2_prio_change(struct v4l2_prio_state *global, enum v4l2_priority *local, enum v4l2_priority new) @@ -211,11 +109,13 @@ int v4l2_prio_change(struct v4l2_prio_state *global, enum v4l2_priority *local, *local = new; return 0; } +EXPORT_SYMBOL(v4l2_prio_change); int v4l2_prio_open(struct v4l2_prio_state *global, enum v4l2_priority *local) { return v4l2_prio_change(global,local,V4L2_PRIORITY_DEFAULT); } +EXPORT_SYMBOL(v4l2_prio_open); int v4l2_prio_close(struct v4l2_prio_state *global, enum v4l2_priority *local) { @@ -223,6 +123,7 @@ int v4l2_prio_close(struct v4l2_prio_state *global, enum v4l2_priority *local) atomic_dec(&global->prios[*local]); return 0; } +EXPORT_SYMBOL(v4l2_prio_close); enum v4l2_priority v4l2_prio_max(struct v4l2_prio_state *global) { @@ -234,6 +135,7 @@ enum v4l2_priority v4l2_prio_max(struct v4l2_prio_state *global) return V4L2_PRIORITY_BACKGROUND; return V4L2_PRIORITY_UNSET; } +EXPORT_SYMBOL(v4l2_prio_max); int v4l2_prio_check(struct v4l2_prio_state *global, enum v4l2_priority *local) { @@ -241,225 +143,7 @@ int v4l2_prio_check(struct v4l2_prio_state *global, enum v4l2_priority *local) return -EBUSY; return 0; } - - -/* ----------------------------------------------------------------- */ -/* some arrays for pretty-printing debug messages of enum types */ - -char *v4l2_field_names[] = { - [V4L2_FIELD_ANY] = "any", - [V4L2_FIELD_NONE] = "none", - [V4L2_FIELD_TOP] = "top", - [V4L2_FIELD_BOTTOM] = "bottom", - [V4L2_FIELD_INTERLACED] = "interlaced", - [V4L2_FIELD_SEQ_TB] = "seq-tb", - [V4L2_FIELD_SEQ_BT] = "seq-bt", - [V4L2_FIELD_ALTERNATE] = "alternate", - [V4L2_FIELD_INTERLACED_TB] = "interlaced-tb", - [V4L2_FIELD_INTERLACED_BT] = "interlaced-bt", -}; - -char *v4l2_type_names[] = { - [V4L2_BUF_TYPE_VIDEO_CAPTURE] = "video-cap", - [V4L2_BUF_TYPE_VIDEO_OVERLAY] = "video-over", - [V4L2_BUF_TYPE_VIDEO_OUTPUT] = "video-out", - [V4L2_BUF_TYPE_VBI_CAPTURE] = "vbi-cap", - [V4L2_BUF_TYPE_VBI_OUTPUT] = "vbi-out", - [V4L2_BUF_TYPE_SLICED_VBI_CAPTURE] = "sliced-vbi-cap", - [V4L2_BUF_TYPE_SLICED_VBI_OUTPUT] = "sliced-vbi-out", - [V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY] = "video-out-over", -}; - - -#define prt_names(a,arr) (((a)>=0)&&((a)name, sizeof(qctrl->name), name); return 0; } +EXPORT_SYMBOL(v4l2_ctrl_query_fill); /* Fill in a struct v4l2_queryctrl with standard values based on the control ID. */ @@ -904,6 +591,7 @@ int v4l2_ctrl_query_fill_std(struct v4l2_queryctrl *qctrl) return -EINVAL; } } +EXPORT_SYMBOL(v4l2_ctrl_query_fill_std); /* Fill in a struct v4l2_querymenu based on the struct v4l2_queryctrl and the menu. The qctrl pointer may be NULL, in which case it is ignored. */ @@ -922,6 +610,7 @@ int v4l2_ctrl_query_menu(struct v4l2_querymenu *qmenu, struct v4l2_queryctrl *qc qmenu->reserved = 0; return 0; } +EXPORT_SYMBOL(v4l2_ctrl_query_menu); /* ctrl_classes points to an array of u32 pointers, the last element is a NULL pointer. Each u32 array is a 0-terminated array of control IDs. @@ -972,7 +661,20 @@ u32 v4l2_ctrl_next(const u32 * const * ctrl_classes, u32 id) return 0; return **ctrl_classes; } +EXPORT_SYMBOL(v4l2_ctrl_next); +int v4l2_chip_match_host(u32 match_type, u32 match_chip) +{ + switch (match_type) { + case V4L2_CHIP_MATCH_HOST: + return match_chip == 0; + default: + return 0; + } +} +EXPORT_SYMBOL(v4l2_chip_match_host); + +#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE)) int v4l2_chip_match_i2c_client(struct i2c_client *c, u32 match_type, u32 match_chip) { switch (match_type) { @@ -984,6 +686,7 @@ int v4l2_chip_match_i2c_client(struct i2c_client *c, u32 match_type, u32 match_c return 0; } } +EXPORT_SYMBOL(v4l2_chip_match_i2c_client); int v4l2_chip_ident_i2c_client(struct i2c_client *c, struct v4l2_chip_ident *chip, u32 ident, u32 revision) @@ -1000,16 +703,7 @@ int v4l2_chip_ident_i2c_client(struct i2c_client *c, struct v4l2_chip_ident *chi } return 0; } - -int v4l2_chip_match_host(u32 match_type, u32 match_chip) -{ - switch (match_type) { - case V4L2_CHIP_MATCH_HOST: - return match_chip == 0; - default: - return 0; - } -} +EXPORT_SYMBOL(v4l2_chip_ident_i2c_client); /* ----------------------------------------------------------------- */ @@ -1038,38 +732,5 @@ int v4l2_i2c_attach(struct i2c_adapter *adapter, int address, struct i2c_driver } return err != -ENOMEM ? 0 : err; } - -/* ----------------------------------------------------------------- */ - -EXPORT_SYMBOL(v4l2_norm_to_name); -EXPORT_SYMBOL(v4l2_video_std_construct); - -EXPORT_SYMBOL(v4l2_prio_init); -EXPORT_SYMBOL(v4l2_prio_change); -EXPORT_SYMBOL(v4l2_prio_open); -EXPORT_SYMBOL(v4l2_prio_close); -EXPORT_SYMBOL(v4l2_prio_max); -EXPORT_SYMBOL(v4l2_prio_check); - -EXPORT_SYMBOL(v4l2_field_names); -EXPORT_SYMBOL(v4l2_type_names); -EXPORT_SYMBOL(v4l_printk_ioctl); - -EXPORT_SYMBOL(v4l2_ctrl_next); -EXPORT_SYMBOL(v4l2_ctrl_check); -EXPORT_SYMBOL(v4l2_ctrl_get_menu); -EXPORT_SYMBOL(v4l2_ctrl_query_menu); -EXPORT_SYMBOL(v4l2_ctrl_query_fill); -EXPORT_SYMBOL(v4l2_ctrl_query_fill_std); - -EXPORT_SYMBOL(v4l2_chip_match_i2c_client); -EXPORT_SYMBOL(v4l2_chip_ident_i2c_client); -EXPORT_SYMBOL(v4l2_chip_match_host); - EXPORT_SYMBOL(v4l2_i2c_attach); - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ +#endif diff --git a/drivers/media/video/videobuf-core.c b/drivers/media/video/videobuf-core.c index 80a14da9acef..eab79ffdf56a 100644 --- a/drivers/media/video/videobuf-core.c +++ b/drivers/media/video/videobuf-core.c @@ -147,7 +147,7 @@ void videobuf_queue_core_init(struct videobuf_queue *q, /* Having implementations for abstract methods are mandatory */ BUG_ON(!q->int_ops); - mutex_init(&q->lock); + mutex_init(&q->vb_lock); INIT_LIST_HEAD(&q->stream); } @@ -189,7 +189,7 @@ int videobuf_queue_is_busy(struct videobuf_queue *q) return 0; } -/* Locking: Caller holds q->lock */ +/* Locking: Caller holds q->vb_lock */ void videobuf_queue_cancel(struct videobuf_queue *q) { unsigned long flags = 0; @@ -220,7 +220,7 @@ void videobuf_queue_cancel(struct videobuf_queue *q) /* --------------------------------------------------------------------- */ -/* Locking: Caller holds q->lock */ +/* Locking: Caller holds q->vb_lock */ enum v4l2_field videobuf_next_field(struct videobuf_queue *q) { enum v4l2_field field = q->field; @@ -239,7 +239,7 @@ enum v4l2_field videobuf_next_field(struct videobuf_queue *q) return field; } -/* Locking: Caller holds q->lock */ +/* Locking: Caller holds q->vb_lock */ static void videobuf_status(struct videobuf_queue *q, struct v4l2_buffer *b, struct videobuf_buffer *vb, enum v4l2_buf_type type) { @@ -295,7 +295,7 @@ static void videobuf_status(struct videobuf_queue *q, struct v4l2_buffer *b, b->sequence = vb->field_count >> 1; } -/* Locking: Caller holds q->lock */ +/* Locking: Caller holds q->vb_lock */ static int __videobuf_mmap_free(struct videobuf_queue *q) { int i; @@ -328,13 +328,13 @@ static int __videobuf_mmap_free(struct videobuf_queue *q) int videobuf_mmap_free(struct videobuf_queue *q) { int ret; - mutex_lock(&q->lock); + mutex_lock(&q->vb_lock); ret = __videobuf_mmap_free(q); - mutex_unlock(&q->lock); + mutex_unlock(&q->vb_lock); return ret; } -/* Locking: Caller holds q->lock */ +/* Locking: Caller holds q->vb_lock */ static int __videobuf_mmap_setup(struct videobuf_queue *q, unsigned int bcount, unsigned int bsize, enum v4l2_memory memory) @@ -384,9 +384,9 @@ int videobuf_mmap_setup(struct videobuf_queue *q, enum v4l2_memory memory) { int ret; - mutex_lock(&q->lock); + mutex_lock(&q->vb_lock); ret = __videobuf_mmap_setup(q, bcount, bsize, memory); - mutex_unlock(&q->lock); + mutex_unlock(&q->vb_lock); return ret; } @@ -408,7 +408,7 @@ int videobuf_reqbufs(struct videobuf_queue *q, return -EINVAL; } - mutex_lock(&q->lock); + mutex_lock(&q->vb_lock); if (req->type != q->type) { dprintk(1, "reqbufs: queue type invalid\n"); retval = -EINVAL; @@ -444,7 +444,7 @@ int videobuf_reqbufs(struct videobuf_queue *q, req->count = retval; done: - mutex_unlock(&q->lock); + mutex_unlock(&q->vb_lock); return retval; } @@ -452,7 +452,7 @@ int videobuf_querybuf(struct videobuf_queue *q, struct v4l2_buffer *b) { int ret = -EINVAL; - mutex_lock(&q->lock); + mutex_lock(&q->vb_lock); if (unlikely(b->type != q->type)) { dprintk(1, "querybuf: Wrong type.\n"); goto done; @@ -470,7 +470,7 @@ int videobuf_querybuf(struct videobuf_queue *q, struct v4l2_buffer *b) ret = 0; done: - mutex_unlock(&q->lock); + mutex_unlock(&q->vb_lock); return ret; } @@ -487,7 +487,7 @@ int videobuf_qbuf(struct videobuf_queue *q, if (b->memory == V4L2_MEMORY_MMAP) down_read(¤t->mm->mmap_sem); - mutex_lock(&q->lock); + mutex_lock(&q->vb_lock); retval = -EBUSY; if (q->reading) { dprintk(1, "qbuf: Reading running...\n"); @@ -573,7 +573,7 @@ int videobuf_qbuf(struct videobuf_queue *q, retval = 0; done: - mutex_unlock(&q->lock); + mutex_unlock(&q->vb_lock); if (b->memory == V4L2_MEMORY_MMAP) up_read(¤t->mm->mmap_sem); @@ -589,7 +589,7 @@ int videobuf_dqbuf(struct videobuf_queue *q, MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); - mutex_lock(&q->lock); + mutex_lock(&q->vb_lock); retval = -EBUSY; if (q->reading) { dprintk(1, "dqbuf: Reading running...\n"); @@ -632,7 +632,7 @@ int videobuf_dqbuf(struct videobuf_queue *q, videobuf_status(q, b, buf, q->type); done: - mutex_unlock(&q->lock); + mutex_unlock(&q->vb_lock); return retval; } @@ -642,7 +642,7 @@ int videobuf_streamon(struct videobuf_queue *q) unsigned long flags = 0; int retval; - mutex_lock(&q->lock); + mutex_lock(&q->vb_lock); retval = -EBUSY; if (q->reading) goto done; @@ -659,11 +659,11 @@ int videobuf_streamon(struct videobuf_queue *q) spin_unlock_irqrestore(q->irqlock, flags); done: - mutex_unlock(&q->lock); + mutex_unlock(&q->vb_lock); return retval; } -/* Locking: Caller holds q->lock */ +/* Locking: Caller holds q->vb_lock */ static int __videobuf_streamoff(struct videobuf_queue *q) { if (!q->streaming) @@ -679,14 +679,14 @@ int videobuf_streamoff(struct videobuf_queue *q) { int retval; - mutex_lock(&q->lock); + mutex_lock(&q->vb_lock); retval = __videobuf_streamoff(q); - mutex_unlock(&q->lock); + mutex_unlock(&q->vb_lock); return retval; } -/* Locking: Caller holds q->lock */ +/* Locking: Caller holds q->vb_lock */ static ssize_t videobuf_read_zerocopy(struct videobuf_queue *q, char __user *data, size_t count, loff_t *ppos) @@ -745,7 +745,7 @@ ssize_t videobuf_read_one(struct videobuf_queue *q, MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); - mutex_lock(&q->lock); + mutex_lock(&q->vb_lock); nbufs = 1; size = 0; q->ops->buf_setup(q, &nbufs, &size); @@ -817,11 +817,11 @@ ssize_t videobuf_read_one(struct videobuf_queue *q, } done: - mutex_unlock(&q->lock); + mutex_unlock(&q->vb_lock); return retval; } -/* Locking: Caller holds q->lock */ +/* Locking: Caller holds q->vb_lock */ static int __videobuf_read_start(struct videobuf_queue *q) { enum v4l2_field field; @@ -882,23 +882,23 @@ int videobuf_read_start(struct videobuf_queue *q) { int rc; - mutex_lock(&q->lock); + mutex_lock(&q->vb_lock); rc = __videobuf_read_start(q); - mutex_unlock(&q->lock); + mutex_unlock(&q->vb_lock); return rc; } void videobuf_read_stop(struct videobuf_queue *q) { - mutex_lock(&q->lock); + mutex_lock(&q->vb_lock); __videobuf_read_stop(q); - mutex_unlock(&q->lock); + mutex_unlock(&q->vb_lock); } void videobuf_stop(struct videobuf_queue *q) { - mutex_lock(&q->lock); + mutex_lock(&q->vb_lock); if (q->streaming) __videobuf_streamoff(q); @@ -906,7 +906,7 @@ void videobuf_stop(struct videobuf_queue *q) if (q->reading) __videobuf_read_stop(q); - mutex_unlock(&q->lock); + mutex_unlock(&q->vb_lock); } @@ -920,7 +920,7 @@ ssize_t videobuf_read_stream(struct videobuf_queue *q, MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); dprintk(2, "%s\n", __FUNCTION__); - mutex_lock(&q->lock); + mutex_lock(&q->vb_lock); retval = -EBUSY; if (q->streaming) goto done; @@ -980,7 +980,7 @@ ssize_t videobuf_read_stream(struct videobuf_queue *q, } done: - mutex_unlock(&q->lock); + mutex_unlock(&q->vb_lock); return retval; } @@ -991,7 +991,7 @@ unsigned int videobuf_poll_stream(struct file *file, struct videobuf_buffer *buf = NULL; unsigned int rc = 0; - mutex_lock(&q->lock); + mutex_lock(&q->vb_lock); if (q->streaming) { if (!list_empty(&q->stream)) buf = list_entry(q->stream.next, @@ -1019,7 +1019,7 @@ unsigned int videobuf_poll_stream(struct file *file, buf->state == VIDEOBUF_ERROR) rc = POLLIN|POLLRDNORM; } - mutex_unlock(&q->lock); + mutex_unlock(&q->vb_lock); return rc; } @@ -1030,10 +1030,10 @@ int videobuf_mmap_mapper(struct videobuf_queue *q, MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); - mutex_lock(&q->lock); + mutex_lock(&q->vb_lock); retval = CALL(q, mmap_mapper, q, vma); q->is_mmapped = 1; - mutex_unlock(&q->lock); + mutex_unlock(&q->vb_lock); return retval; } diff --git a/drivers/media/video/videobuf-dma-sg.c b/drivers/media/video/videobuf-dma-sg.c index 98efd7ab1f50..53fed4b74ce9 100644 --- a/drivers/media/video/videobuf-dma-sg.c +++ b/drivers/media/video/videobuf-dma-sg.c @@ -356,7 +356,7 @@ videobuf_vm_close(struct vm_area_struct *vma) map->count--; if (0 == map->count) { dprintk(1,"munmap %p q=%p\n",map,q); - mutex_lock(&q->lock); + mutex_lock(&q->vb_lock); for (i = 0; i < VIDEO_MAX_FRAME; i++) { if (NULL == q->bufs[i]) continue; @@ -373,7 +373,7 @@ videobuf_vm_close(struct vm_area_struct *vma) q->bufs[i]->baddr = 0; q->ops->buf_release(q,q->bufs[i]); } - mutex_unlock(&q->lock); + mutex_unlock(&q->vb_lock); kfree(map); } return; diff --git a/drivers/media/video/videobuf-vmalloc.c b/drivers/media/video/videobuf-vmalloc.c index 9b3898347ca5..5266ecc91dab 100644 --- a/drivers/media/video/videobuf-vmalloc.c +++ b/drivers/media/video/videobuf-vmalloc.c @@ -70,7 +70,7 @@ videobuf_vm_close(struct vm_area_struct *vma) map->count--; if (0 == map->count) { dprintk(1,"munmap %p q=%p\n",map,q); - mutex_lock(&q->lock); + mutex_lock(&q->vb_lock); for (i = 0; i < VIDEO_MAX_FRAME; i++) { if (NULL == q->bufs[i]) continue; @@ -83,7 +83,7 @@ videobuf_vm_close(struct vm_area_struct *vma) q->bufs[i]->map = NULL; q->bufs[i]->baddr = 0; } - mutex_unlock(&q->lock); + mutex_unlock(&q->vb_lock); kfree(map); } return; @@ -107,7 +107,7 @@ static struct vm_operations_struct videobuf_vm_ops = static void *__videobuf_alloc(size_t size) { - struct videbuf_vmalloc_memory *mem; + struct videobuf_vmalloc_memory *mem; struct videobuf_buffer *vb; vb = kzalloc(size+sizeof(*mem),GFP_KERNEL); @@ -127,9 +127,7 @@ static int __videobuf_iolock (struct videobuf_queue* q, struct v4l2_framebuffer *fbuf) { int pages; - - struct videbuf_vmalloc_memory *mem=vb->priv; - + struct videobuf_vmalloc_memory *mem=vb->priv; BUG_ON(!mem); @@ -195,7 +193,7 @@ static int __videobuf_mmap_free(struct videobuf_queue *q) static int __videobuf_mmap_mapper(struct videobuf_queue *q, struct vm_area_struct *vma) { - struct videbuf_vmalloc_memory *mem; + struct videobuf_vmalloc_memory *mem; struct videobuf_mapping *map; unsigned int first; int retval; @@ -267,7 +265,7 @@ static int __videobuf_copy_to_user ( struct videobuf_queue *q, char __user *data, size_t count, int nonblocking ) { - struct videbuf_vmalloc_memory *mem=q->read_buf->priv; + struct videobuf_vmalloc_memory *mem=q->read_buf->priv; BUG_ON (!mem); MAGIC_CHECK(mem->magic,MAGIC_VMAL_MEM); @@ -288,7 +286,7 @@ static int __videobuf_copy_stream ( struct videobuf_queue *q, int vbihack, int nonblocking ) { unsigned int *fc; - struct videbuf_vmalloc_memory *mem=q->read_buf->priv; + struct videobuf_vmalloc_memory *mem=q->read_buf->priv; BUG_ON (!mem); MAGIC_CHECK(mem->magic,MAGIC_VMAL_MEM); @@ -341,7 +339,7 @@ EXPORT_SYMBOL_GPL(videobuf_queue_vmalloc_init); void *videobuf_to_vmalloc (struct videobuf_buffer *buf) { - struct videbuf_vmalloc_memory *mem=buf->priv; + struct videobuf_vmalloc_memory *mem=buf->priv; BUG_ON (!mem); MAGIC_CHECK(mem->magic,MAGIC_VMAL_MEM); @@ -351,7 +349,7 @@ EXPORT_SYMBOL_GPL(videobuf_to_vmalloc); void videobuf_vmalloc_free (struct videobuf_buffer *buf) { - struct videbuf_vmalloc_memory *mem=buf->priv; + struct videobuf_vmalloc_memory *mem=buf->priv; BUG_ON (!mem); MAGIC_CHECK(mem->magic,MAGIC_VMAL_MEM); diff --git a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c index 28655f8983c6..0d9b63762a48 100644 --- a/drivers/media/video/videodev.c +++ b/drivers/media/video/videodev.c @@ -46,10 +46,373 @@ #include #endif #include +#include #define VIDEO_NUM_DEVICES 256 #define VIDEO_NAME "video4linux" +/* video4linux standard ID conversion to standard name + */ +char *v4l2_norm_to_name(v4l2_std_id id) +{ + char *name; + u32 myid = id; + + /* HACK: ppc32 architecture doesn't have __ucmpdi2 function to handle + 64 bit comparations. So, on that architecture, with some gcc + variants, compilation fails. Currently, the max value is 30bit wide. + */ + BUG_ON(myid != id); + + switch (myid) { + case V4L2_STD_PAL: + name = "PAL"; + break; + case V4L2_STD_PAL_BG: + name = "PAL-BG"; + break; + case V4L2_STD_PAL_DK: + name = "PAL-DK"; + break; + case V4L2_STD_PAL_B: + name = "PAL-B"; + break; + case V4L2_STD_PAL_B1: + name = "PAL-B1"; + break; + case V4L2_STD_PAL_G: + name = "PAL-G"; + break; + case V4L2_STD_PAL_H: + name = "PAL-H"; + break; + case V4L2_STD_PAL_I: + name = "PAL-I"; + break; + case V4L2_STD_PAL_D: + name = "PAL-D"; + break; + case V4L2_STD_PAL_D1: + name = "PAL-D1"; + break; + case V4L2_STD_PAL_K: + name = "PAL-K"; + break; + case V4L2_STD_PAL_M: + name = "PAL-M"; + break; + case V4L2_STD_PAL_N: + name = "PAL-N"; + break; + case V4L2_STD_PAL_Nc: + name = "PAL-Nc"; + break; + case V4L2_STD_PAL_60: + name = "PAL-60"; + break; + case V4L2_STD_NTSC: + name = "NTSC"; + break; + case V4L2_STD_NTSC_M: + name = "NTSC-M"; + break; + case V4L2_STD_NTSC_M_JP: + name = "NTSC-M-JP"; + break; + case V4L2_STD_NTSC_443: + name = "NTSC-443"; + break; + case V4L2_STD_NTSC_M_KR: + name = "NTSC-M-KR"; + break; + case V4L2_STD_SECAM: + name = "SECAM"; + break; + case V4L2_STD_SECAM_DK: + name = "SECAM-DK"; + break; + case V4L2_STD_SECAM_B: + name = "SECAM-B"; + break; + case V4L2_STD_SECAM_D: + name = "SECAM-D"; + break; + case V4L2_STD_SECAM_G: + name = "SECAM-G"; + break; + case V4L2_STD_SECAM_H: + name = "SECAM-H"; + break; + case V4L2_STD_SECAM_K: + name = "SECAM-K"; + break; + case V4L2_STD_SECAM_K1: + name = "SECAM-K1"; + break; + case V4L2_STD_SECAM_L: + name = "SECAM-L"; + break; + case V4L2_STD_SECAM_LC: + name = "SECAM-LC"; + break; + default: + name = "Unknown"; + break; + } + + return name; +} +EXPORT_SYMBOL(v4l2_norm_to_name); + +/* Fill in the fields of a v4l2_standard structure according to the + 'id' and 'transmission' parameters. Returns negative on error. */ +int v4l2_video_std_construct(struct v4l2_standard *vs, + int id, char *name) +{ + u32 index = vs->index; + + memset(vs, 0, sizeof(struct v4l2_standard)); + vs->index = index; + vs->id = id; + if (id & V4L2_STD_525_60) { + vs->frameperiod.numerator = 1001; + vs->frameperiod.denominator = 30000; + vs->framelines = 525; + } else { + vs->frameperiod.numerator = 1; + vs->frameperiod.denominator = 25; + vs->framelines = 625; + } + strlcpy(vs->name, name, sizeof(vs->name)); + return 0; +} +EXPORT_SYMBOL(v4l2_video_std_construct); + +/* ----------------------------------------------------------------- */ +/* some arrays for pretty-printing debug messages of enum types */ + +char *v4l2_field_names[] = { + [V4L2_FIELD_ANY] = "any", + [V4L2_FIELD_NONE] = "none", + [V4L2_FIELD_TOP] = "top", + [V4L2_FIELD_BOTTOM] = "bottom", + [V4L2_FIELD_INTERLACED] = "interlaced", + [V4L2_FIELD_SEQ_TB] = "seq-tb", + [V4L2_FIELD_SEQ_BT] = "seq-bt", + [V4L2_FIELD_ALTERNATE] = "alternate", + [V4L2_FIELD_INTERLACED_TB] = "interlaced-tb", + [V4L2_FIELD_INTERLACED_BT] = "interlaced-bt", +}; +EXPORT_SYMBOL(v4l2_field_names); + +char *v4l2_type_names[] = { + [V4L2_BUF_TYPE_VIDEO_CAPTURE] = "video-cap", + [V4L2_BUF_TYPE_VIDEO_OVERLAY] = "video-over", + [V4L2_BUF_TYPE_VIDEO_OUTPUT] = "video-out", + [V4L2_BUF_TYPE_VBI_CAPTURE] = "vbi-cap", + [V4L2_BUF_TYPE_VBI_OUTPUT] = "vbi-out", + [V4L2_BUF_TYPE_SLICED_VBI_CAPTURE] = "sliced-vbi-cap", + [V4L2_BUF_TYPE_SLICED_VBI_OUTPUT] = "sliced-vbi-out", + [V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY] = "video-out-over", +}; +EXPORT_SYMBOL(v4l2_type_names); + +static char *v4l2_memory_names[] = { + [V4L2_MEMORY_MMAP] = "mmap", + [V4L2_MEMORY_USERPTR] = "userptr", + [V4L2_MEMORY_OVERLAY] = "overlay", +}; + +#define prt_names(a, arr) ((((a) >= 0) && ((a) < ARRAY_SIZE(arr))) ? \ + arr[a] : "unknown") + +/* ------------------------------------------------------------------ */ +/* debug help functions */ + +#ifdef CONFIG_VIDEO_V4L1_COMPAT +static const char *v4l1_ioctls[] = { + [_IOC_NR(VIDIOCGCAP)] = "VIDIOCGCAP", + [_IOC_NR(VIDIOCGCHAN)] = "VIDIOCGCHAN", + [_IOC_NR(VIDIOCSCHAN)] = "VIDIOCSCHAN", + [_IOC_NR(VIDIOCGTUNER)] = "VIDIOCGTUNER", + [_IOC_NR(VIDIOCSTUNER)] = "VIDIOCSTUNER", + [_IOC_NR(VIDIOCGPICT)] = "VIDIOCGPICT", + [_IOC_NR(VIDIOCSPICT)] = "VIDIOCSPICT", + [_IOC_NR(VIDIOCCAPTURE)] = "VIDIOCCAPTURE", + [_IOC_NR(VIDIOCGWIN)] = "VIDIOCGWIN", + [_IOC_NR(VIDIOCSWIN)] = "VIDIOCSWIN", + [_IOC_NR(VIDIOCGFBUF)] = "VIDIOCGFBUF", + [_IOC_NR(VIDIOCSFBUF)] = "VIDIOCSFBUF", + [_IOC_NR(VIDIOCKEY)] = "VIDIOCKEY", + [_IOC_NR(VIDIOCGFREQ)] = "VIDIOCGFREQ", + [_IOC_NR(VIDIOCSFREQ)] = "VIDIOCSFREQ", + [_IOC_NR(VIDIOCGAUDIO)] = "VIDIOCGAUDIO", + [_IOC_NR(VIDIOCSAUDIO)] = "VIDIOCSAUDIO", + [_IOC_NR(VIDIOCSYNC)] = "VIDIOCSYNC", + [_IOC_NR(VIDIOCMCAPTURE)] = "VIDIOCMCAPTURE", + [_IOC_NR(VIDIOCGMBUF)] = "VIDIOCGMBUF", + [_IOC_NR(VIDIOCGUNIT)] = "VIDIOCGUNIT", + [_IOC_NR(VIDIOCGCAPTURE)] = "VIDIOCGCAPTURE", + [_IOC_NR(VIDIOCSCAPTURE)] = "VIDIOCSCAPTURE", + [_IOC_NR(VIDIOCSPLAYMODE)] = "VIDIOCSPLAYMODE", + [_IOC_NR(VIDIOCSWRITEMODE)] = "VIDIOCSWRITEMODE", + [_IOC_NR(VIDIOCGPLAYINFO)] = "VIDIOCGPLAYINFO", + [_IOC_NR(VIDIOCSMICROCODE)] = "VIDIOCSMICROCODE", + [_IOC_NR(VIDIOCGVBIFMT)] = "VIDIOCGVBIFMT", + [_IOC_NR(VIDIOCSVBIFMT)] = "VIDIOCSVBIFMT" +}; +#define V4L1_IOCTLS ARRAY_SIZE(v4l1_ioctls) +#endif + +static const char *v4l2_ioctls[] = { + [_IOC_NR(VIDIOC_QUERYCAP)] = "VIDIOC_QUERYCAP", + [_IOC_NR(VIDIOC_RESERVED)] = "VIDIOC_RESERVED", + [_IOC_NR(VIDIOC_ENUM_FMT)] = "VIDIOC_ENUM_FMT", + [_IOC_NR(VIDIOC_G_FMT)] = "VIDIOC_G_FMT", + [_IOC_NR(VIDIOC_S_FMT)] = "VIDIOC_S_FMT", + [_IOC_NR(VIDIOC_REQBUFS)] = "VIDIOC_REQBUFS", + [_IOC_NR(VIDIOC_QUERYBUF)] = "VIDIOC_QUERYBUF", + [_IOC_NR(VIDIOC_G_FBUF)] = "VIDIOC_G_FBUF", + [_IOC_NR(VIDIOC_S_FBUF)] = "VIDIOC_S_FBUF", + [_IOC_NR(VIDIOC_OVERLAY)] = "VIDIOC_OVERLAY", + [_IOC_NR(VIDIOC_QBUF)] = "VIDIOC_QBUF", + [_IOC_NR(VIDIOC_DQBUF)] = "VIDIOC_DQBUF", + [_IOC_NR(VIDIOC_STREAMON)] = "VIDIOC_STREAMON", + [_IOC_NR(VIDIOC_STREAMOFF)] = "VIDIOC_STREAMOFF", + [_IOC_NR(VIDIOC_G_PARM)] = "VIDIOC_G_PARM", + [_IOC_NR(VIDIOC_S_PARM)] = "VIDIOC_S_PARM", + [_IOC_NR(VIDIOC_G_STD)] = "VIDIOC_G_STD", + [_IOC_NR(VIDIOC_S_STD)] = "VIDIOC_S_STD", + [_IOC_NR(VIDIOC_ENUMSTD)] = "VIDIOC_ENUMSTD", + [_IOC_NR(VIDIOC_ENUMINPUT)] = "VIDIOC_ENUMINPUT", + [_IOC_NR(VIDIOC_G_CTRL)] = "VIDIOC_G_CTRL", + [_IOC_NR(VIDIOC_S_CTRL)] = "VIDIOC_S_CTRL", + [_IOC_NR(VIDIOC_G_TUNER)] = "VIDIOC_G_TUNER", + [_IOC_NR(VIDIOC_S_TUNER)] = "VIDIOC_S_TUNER", + [_IOC_NR(VIDIOC_G_AUDIO)] = "VIDIOC_G_AUDIO", + [_IOC_NR(VIDIOC_S_AUDIO)] = "VIDIOC_S_AUDIO", + [_IOC_NR(VIDIOC_QUERYCTRL)] = "VIDIOC_QUERYCTRL", + [_IOC_NR(VIDIOC_QUERYMENU)] = "VIDIOC_QUERYMENU", + [_IOC_NR(VIDIOC_G_INPUT)] = "VIDIOC_G_INPUT", + [_IOC_NR(VIDIOC_S_INPUT)] = "VIDIOC_S_INPUT", + [_IOC_NR(VIDIOC_G_OUTPUT)] = "VIDIOC_G_OUTPUT", + [_IOC_NR(VIDIOC_S_OUTPUT)] = "VIDIOC_S_OUTPUT", + [_IOC_NR(VIDIOC_ENUMOUTPUT)] = "VIDIOC_ENUMOUTPUT", + [_IOC_NR(VIDIOC_G_AUDOUT)] = "VIDIOC_G_AUDOUT", + [_IOC_NR(VIDIOC_S_AUDOUT)] = "VIDIOC_S_AUDOUT", + [_IOC_NR(VIDIOC_G_MODULATOR)] = "VIDIOC_G_MODULATOR", + [_IOC_NR(VIDIOC_S_MODULATOR)] = "VIDIOC_S_MODULATOR", + [_IOC_NR(VIDIOC_G_FREQUENCY)] = "VIDIOC_G_FREQUENCY", + [_IOC_NR(VIDIOC_S_FREQUENCY)] = "VIDIOC_S_FREQUENCY", + [_IOC_NR(VIDIOC_CROPCAP)] = "VIDIOC_CROPCAP", + [_IOC_NR(VIDIOC_G_CROP)] = "VIDIOC_G_CROP", + [_IOC_NR(VIDIOC_S_CROP)] = "VIDIOC_S_CROP", + [_IOC_NR(VIDIOC_G_JPEGCOMP)] = "VIDIOC_G_JPEGCOMP", + [_IOC_NR(VIDIOC_S_JPEGCOMP)] = "VIDIOC_S_JPEGCOMP", + [_IOC_NR(VIDIOC_QUERYSTD)] = "VIDIOC_QUERYSTD", + [_IOC_NR(VIDIOC_TRY_FMT)] = "VIDIOC_TRY_FMT", + [_IOC_NR(VIDIOC_ENUMAUDIO)] = "VIDIOC_ENUMAUDIO", + [_IOC_NR(VIDIOC_ENUMAUDOUT)] = "VIDIOC_ENUMAUDOUT", + [_IOC_NR(VIDIOC_G_PRIORITY)] = "VIDIOC_G_PRIORITY", + [_IOC_NR(VIDIOC_S_PRIORITY)] = "VIDIOC_S_PRIORITY", + [_IOC_NR(VIDIOC_G_SLICED_VBI_CAP)] = "VIDIOC_G_SLICED_VBI_CAP", + [_IOC_NR(VIDIOC_LOG_STATUS)] = "VIDIOC_LOG_STATUS", + [_IOC_NR(VIDIOC_G_EXT_CTRLS)] = "VIDIOC_G_EXT_CTRLS", + [_IOC_NR(VIDIOC_S_EXT_CTRLS)] = "VIDIOC_S_EXT_CTRLS", + [_IOC_NR(VIDIOC_TRY_EXT_CTRLS)] = "VIDIOC_TRY_EXT_CTRLS", +#if 1 + [_IOC_NR(VIDIOC_ENUM_FRAMESIZES)] = "VIDIOC_ENUM_FRAMESIZES", + [_IOC_NR(VIDIOC_ENUM_FRAMEINTERVALS)] = "VIDIOC_ENUM_FRAMEINTERVALS", + [_IOC_NR(VIDIOC_G_ENC_INDEX)] = "VIDIOC_G_ENC_INDEX", + [_IOC_NR(VIDIOC_ENCODER_CMD)] = "VIDIOC_ENCODER_CMD", + [_IOC_NR(VIDIOC_TRY_ENCODER_CMD)] = "VIDIOC_TRY_ENCODER_CMD", + + [_IOC_NR(VIDIOC_DBG_S_REGISTER)] = "VIDIOC_DBG_S_REGISTER", + [_IOC_NR(VIDIOC_DBG_G_REGISTER)] = "VIDIOC_DBG_G_REGISTER", + + [_IOC_NR(VIDIOC_G_CHIP_IDENT)] = "VIDIOC_G_CHIP_IDENT", +#endif +}; +#define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls) + +static const char *v4l2_int_ioctls[] = { +#ifdef CONFIG_VIDEO_V4L1_COMPAT + [_IOC_NR(DECODER_GET_CAPABILITIES)] = "DECODER_GET_CAPABILITIES", + [_IOC_NR(DECODER_GET_STATUS)] = "DECODER_GET_STATUS", + [_IOC_NR(DECODER_SET_NORM)] = "DECODER_SET_NORM", + [_IOC_NR(DECODER_SET_INPUT)] = "DECODER_SET_INPUT", + [_IOC_NR(DECODER_SET_OUTPUT)] = "DECODER_SET_OUTPUT", + [_IOC_NR(DECODER_ENABLE_OUTPUT)] = "DECODER_ENABLE_OUTPUT", + [_IOC_NR(DECODER_SET_PICTURE)] = "DECODER_SET_PICTURE", + [_IOC_NR(DECODER_SET_GPIO)] = "DECODER_SET_GPIO", + [_IOC_NR(DECODER_INIT)] = "DECODER_INIT", + [_IOC_NR(DECODER_SET_VBI_BYPASS)] = "DECODER_SET_VBI_BYPASS", + [_IOC_NR(DECODER_DUMP)] = "DECODER_DUMP", +#endif + [_IOC_NR(AUDC_SET_RADIO)] = "AUDC_SET_RADIO", + + [_IOC_NR(TUNER_SET_TYPE_ADDR)] = "TUNER_SET_TYPE_ADDR", + [_IOC_NR(TUNER_SET_STANDBY)] = "TUNER_SET_STANDBY", + [_IOC_NR(TUNER_SET_CONFIG)] = "TUNER_SET_CONFIG", + + [_IOC_NR(VIDIOC_INT_S_TUNER_MODE)] = "VIDIOC_INT_S_TUNER_MODE", + [_IOC_NR(VIDIOC_INT_RESET)] = "VIDIOC_INT_RESET", + [_IOC_NR(VIDIOC_INT_AUDIO_CLOCK_FREQ)] = "VIDIOC_INT_AUDIO_CLOCK_FREQ", + [_IOC_NR(VIDIOC_INT_DECODE_VBI_LINE)] = "VIDIOC_INT_DECODE_VBI_LINE", + [_IOC_NR(VIDIOC_INT_S_VBI_DATA)] = "VIDIOC_INT_S_VBI_DATA", + [_IOC_NR(VIDIOC_INT_G_VBI_DATA)] = "VIDIOC_INT_G_VBI_DATA", + [_IOC_NR(VIDIOC_INT_I2S_CLOCK_FREQ)] = "VIDIOC_INT_I2S_CLOCK_FREQ", + [_IOC_NR(VIDIOC_INT_S_STANDBY)] = "VIDIOC_INT_S_STANDBY", + [_IOC_NR(VIDIOC_INT_S_AUDIO_ROUTING)] = "VIDIOC_INT_S_AUDIO_ROUTING", + [_IOC_NR(VIDIOC_INT_G_AUDIO_ROUTING)] = "VIDIOC_INT_G_AUDIO_ROUTING", + [_IOC_NR(VIDIOC_INT_S_VIDEO_ROUTING)] = "VIDIOC_INT_S_VIDEO_ROUTING", + [_IOC_NR(VIDIOC_INT_G_VIDEO_ROUTING)] = "VIDIOC_INT_G_VIDEO_ROUTING", + [_IOC_NR(VIDIOC_INT_S_CRYSTAL_FREQ)] = "VIDIOC_INT_S_CRYSTAL_FREQ", + [_IOC_NR(VIDIOC_INT_INIT)] = "VIDIOC_INT_INIT", + [_IOC_NR(VIDIOC_INT_G_STD_OUTPUT)] = "VIDIOC_INT_G_STD_OUTPUT", + [_IOC_NR(VIDIOC_INT_S_STD_OUTPUT)] = "VIDIOC_INT_S_STD_OUTPUT", +}; +#define V4L2_INT_IOCTLS ARRAY_SIZE(v4l2_int_ioctls) + +/* Common ioctl debug function. This function can be used by + external ioctl messages as well as internal V4L ioctl */ +void v4l_printk_ioctl(unsigned int cmd) +{ + char *dir; + + switch (_IOC_DIR(cmd)) { + case _IOC_NONE: dir = "--"; break; + case _IOC_READ: dir = "r-"; break; + case _IOC_WRITE: dir = "-w"; break; + case _IOC_READ | _IOC_WRITE: dir = "rw"; break; + default: dir = "*ERR*"; break; + } + switch (_IOC_TYPE(cmd)) { + case 'd': + printk("v4l2_int ioctl %s, dir=%s (0x%08x)\n", + (_IOC_NR(cmd) < V4L2_INT_IOCTLS) ? + v4l2_int_ioctls[_IOC_NR(cmd)] : "UNKNOWN", dir, cmd); + break; +#ifdef CONFIG_VIDEO_V4L1_COMPAT + case 'v': + printk("v4l1 ioctl %s, dir=%s (0x%08x)\n", + (_IOC_NR(cmd) < V4L1_IOCTLS) ? + v4l1_ioctls[_IOC_NR(cmd)] : "UNKNOWN", dir, cmd); + break; +#endif + case 'V': + printk("v4l2 ioctl %s, dir=%s (0x%08x)\n", + (_IOC_NR(cmd) < V4L2_IOCTLS) ? + v4l2_ioctls[_IOC_NR(cmd)] : "UNKNOWN", dir, cmd); + break; + + default: + printk("unknown ioctl '%c', dir=%s, #%d (0x%08x)\n", + _IOC_TYPE(cmd), dir, _IOC_NR(cmd), cmd); + } +} +EXPORT_SYMBOL(v4l_printk_ioctl); + /* * sysfs stuff */ @@ -69,11 +432,13 @@ struct video_device *video_device_alloc(void) vfd = kzalloc(sizeof(*vfd),GFP_KERNEL); return vfd; } +EXPORT_SYMBOL(video_device_alloc); void video_device_release(struct video_device *vfd) { kfree(vfd); } +EXPORT_SYMBOL(video_device_release); static void video_release(struct device *cd) { @@ -110,6 +475,7 @@ struct video_device* video_devdata(struct file *file) { return video_device[iminor(file->f_path.dentry->d_inode)]; } +EXPORT_SYMBOL(video_devdata); /* * Open a video device - FIXME: Obsoleted @@ -278,6 +644,7 @@ out: kfree(mbuf); return err; } +EXPORT_SYMBOL(video_usercopy); /* * open/release helper functions -- handle exclusive opens @@ -297,6 +664,7 @@ int video_exclusive_open(struct inode *inode, struct file *file) mutex_unlock(&vfl->lock); return retval; } +EXPORT_SYMBOL(video_exclusive_open); int video_exclusive_release(struct inode *inode, struct file *file) { @@ -305,41 +673,7 @@ int video_exclusive_release(struct inode *inode, struct file *file) vfl->users--; return 0; } - -static char *v4l2_memory_names[] = { - [V4L2_MEMORY_MMAP] = "mmap", - [V4L2_MEMORY_USERPTR] = "userptr", - [V4L2_MEMORY_OVERLAY] = "overlay", -}; - - -/* FIXME: Those stuff are replicated also on v4l2-common.c */ -static char *v4l2_type_names_FIXME[] = { - [V4L2_BUF_TYPE_VIDEO_CAPTURE] = "video-cap", - [V4L2_BUF_TYPE_VIDEO_OVERLAY] = "video-over", - [V4L2_BUF_TYPE_VIDEO_OUTPUT] = "video-out", - [V4L2_BUF_TYPE_VBI_CAPTURE] = "vbi-cap", - [V4L2_BUF_TYPE_VBI_OUTPUT] = "vbi-out", - [V4L2_BUF_TYPE_SLICED_VBI_OUTPUT] = "sliced-vbi-out", - [V4L2_BUF_TYPE_SLICED_VBI_CAPTURE] = "sliced-vbi-capture", - [V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY] = "video-out-over", - [V4L2_BUF_TYPE_PRIVATE] = "private", -}; - -static char *v4l2_field_names_FIXME[] = { - [V4L2_FIELD_ANY] = "any", - [V4L2_FIELD_NONE] = "none", - [V4L2_FIELD_TOP] = "top", - [V4L2_FIELD_BOTTOM] = "bottom", - [V4L2_FIELD_INTERLACED] = "interlaced", - [V4L2_FIELD_SEQ_TB] = "seq-tb", - [V4L2_FIELD_SEQ_BT] = "seq-bt", - [V4L2_FIELD_ALTERNATE] = "alternate", - [V4L2_FIELD_INTERLACED_TB] = "interlaced-tb", - [V4L2_FIELD_INTERLACED_BT] = "interlaced-bt", -}; - -#define prt_names(a,arr) (((a)>=0)&&((a)timestamp.tv_sec%60), p->timestamp.tv_usec, p->index, - prt_names(p->type,v4l2_type_names_FIXME), - p->bytesused,p->flags, - p->field,p->sequence, - prt_names(p->memory,v4l2_memory_names), + prt_names(p->type, v4l2_type_names), + p->bytesused, p->flags, + p->field, p->sequence, + prt_names(p->memory, v4l2_memory_names), p->m.userptr, p->length); dbgarg2 ("timecode= %02d:%02d:%02d type=%d, " "flags=0x%08d, frames=%d, userbits=0x%08x\n", @@ -382,8 +716,8 @@ static inline void v4l_print_pix_fmt (struct video_device *vfd, (fmt->pixelformat >> 8) & 0xff, (fmt->pixelformat >> 16) & 0xff, (fmt->pixelformat >> 24) & 0xff, - prt_names(fmt->field,v4l2_field_names_FIXME), - fmt->bytesperline,fmt->sizeimage,fmt->colorspace); + prt_names(fmt->field, v4l2_field_names), + fmt->bytesperline, fmt->sizeimage, fmt->colorspace); }; @@ -597,7 +931,7 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, /* FIXME: Should be one dump per type */ dbgarg (cmd, "type=%s\n", prt_names(type, - v4l2_type_names_FIXME)); + v4l2_type_names)); switch (type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: @@ -650,7 +984,7 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, /* FIXME: Should be one dump per type */ dbgarg (cmd, "type=%s\n", prt_names(f->type, - v4l2_type_names_FIXME)); + v4l2_type_names)); switch (f->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: @@ -702,7 +1036,7 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, /* FIXME: Should be one dump per type */ dbgarg (cmd, "type=%s\n", prt_names(f->type, - v4l2_type_names_FIXME)); + v4l2_type_names)); switch (f->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: if (vfd->vidioc_try_fmt_cap) @@ -768,8 +1102,8 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, ret=vfd->vidioc_reqbufs(file, fh, p); dbgarg (cmd, "count=%d, type=%s, memory=%s\n", p->count, - prt_names(p->type,v4l2_type_names_FIXME), - prt_names(p->memory,v4l2_memory_names)); + prt_names(p->type, v4l2_type_names), + prt_names(p->memory, v4l2_memory_names)); break; } case VIDIOC_QUERYBUF: @@ -858,7 +1192,7 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, enum v4l2_buf_type i = *(int *)arg; if (!vfd->vidioc_streamon) break; - dbgarg (cmd, "type=%s\n", prt_names(i,v4l2_type_names_FIXME)); + dbgarg(cmd, "type=%s\n", prt_names(i, v4l2_type_names)); ret=vfd->vidioc_streamon(file, fh,i); break; } @@ -868,7 +1202,7 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, if (!vfd->vidioc_streamoff) break; - dbgarg (cmd, "type=%s\n", prt_names(i,v4l2_type_names_FIXME)); + dbgarg(cmd, "type=%s\n", prt_names(i, v4l2_type_names)); ret=vfd->vidioc_streamoff(file, fh, i); break; } @@ -1624,7 +1958,7 @@ out: kfree(mbuf); return err; } - +EXPORT_SYMBOL(video_ioctl2); static const struct file_operations video_fops; @@ -1743,6 +2077,7 @@ fail_minor: mutex_unlock(&videodev_lock); return ret; } +EXPORT_SYMBOL(video_register_device); /** * video_unregister_device - unregister a video4linux device @@ -1762,6 +2097,7 @@ void video_unregister_device(struct video_device *vfd) device_unregister(&vfd->class_dev); mutex_unlock(&videodev_lock); } +EXPORT_SYMBOL(video_unregister_device); /* * Video fs operations @@ -1806,16 +2142,6 @@ static void __exit videodev_exit(void) module_init(videodev_init) module_exit(videodev_exit) -EXPORT_SYMBOL(video_register_device); -EXPORT_SYMBOL(video_unregister_device); -EXPORT_SYMBOL(video_devdata); -EXPORT_SYMBOL(video_usercopy); -EXPORT_SYMBOL(video_exclusive_open); -EXPORT_SYMBOL(video_exclusive_release); -EXPORT_SYMBOL(video_ioctl2); -EXPORT_SYMBOL(video_device_alloc); -EXPORT_SYMBOL(video_device_release); - MODULE_AUTHOR("Alan Cox, Mauro Carvalho Chehab "); MODULE_DESCRIPTION("Device registrar for Video4Linux drivers v2"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/video/zoran.h b/drivers/media/video/zoran.h index 937c4a616c0e..498a43c1f2b1 100644 --- a/drivers/media/video/zoran.h +++ b/drivers/media/video/zoran.h @@ -221,15 +221,15 @@ enum zoran_map_mode { }; enum gpio_type { - GPIO_JPEG_SLEEP = 0, - GPIO_JPEG_RESET, - GPIO_JPEG_FRAME, - GPIO_VID_DIR, - GPIO_VID_EN, - GPIO_VID_RESET, - GPIO_CLK_SEL1, - GPIO_CLK_SEL2, - GPIO_MAX, + ZR_GPIO_JPEG_SLEEP = 0, + ZR_GPIO_JPEG_RESET, + ZR_GPIO_JPEG_FRAME, + ZR_GPIO_VID_DIR, + ZR_GPIO_VID_EN, + ZR_GPIO_VID_RESET, + ZR_GPIO_CLK_SEL1, + ZR_GPIO_CLK_SEL2, + ZR_GPIO_MAX, }; enum gpcs_type { @@ -378,11 +378,11 @@ struct card_info { u32 jpeg_int; /* JPEG interrupt */ u32 vsync_int; /* VSYNC interrupt */ - s8 gpio[GPIO_MAX]; + s8 gpio[ZR_GPIO_MAX]; u8 gpcs[GPCS_MAX]; struct vfe_polarity vfe_pol; - u8 gpio_pol[GPIO_MAX]; + u8 gpio_pol[ZR_GPIO_MAX]; /* is the /GWS line conected? */ u8 gws_not_connected; diff --git a/drivers/media/video/zoran_device.c b/drivers/media/video/zoran_device.c index 68c7c505587e..f97c20692057 100644 --- a/drivers/media/video/zoran_device.c +++ b/drivers/media/video/zoran_device.c @@ -250,7 +250,7 @@ void jpeg_codec_sleep (struct zoran *zr, int sleep) { - GPIO(zr, zr->card.gpio[GPIO_JPEG_SLEEP], !sleep); + GPIO(zr, zr->card.gpio[ZR_GPIO_JPEG_SLEEP], !sleep); if (!sleep) { dprintk(3, KERN_DEBUG @@ -277,9 +277,9 @@ jpeg_codec_reset (struct zoran *zr) 0); udelay(2); } else { - GPIO(zr, zr->card.gpio[GPIO_JPEG_RESET], 0); + GPIO(zr, zr->card.gpio[ZR_GPIO_JPEG_RESET], 0); udelay(2); - GPIO(zr, zr->card.gpio[GPIO_JPEG_RESET], 1); + GPIO(zr, zr->card.gpio[ZR_GPIO_JPEG_RESET], 1); udelay(2); } @@ -688,7 +688,7 @@ static inline void set_frame (struct zoran *zr, int val) { - GPIO(zr, zr->card.gpio[GPIO_JPEG_FRAME], val); + GPIO(zr, zr->card.gpio[ZR_GPIO_JPEG_FRAME], val); } static void @@ -704,8 +704,8 @@ set_videobus_dir (struct zoran *zr, GPIO(zr, 5, 1); break; default: - GPIO(zr, zr->card.gpio[GPIO_VID_DIR], - zr->card.gpio_pol[GPIO_VID_DIR] ? !val : val); + GPIO(zr, zr->card.gpio[ZR_GPIO_VID_DIR], + zr->card.gpio_pol[ZR_GPIO_VID_DIR] ? !val : val); break; } } diff --git a/drivers/media/video/zr364xx.c b/drivers/media/video/zr364xx.c index 1fdbb46de7f3..1b44784d0efb 100644 --- a/drivers/media/video/zr364xx.c +++ b/drivers/media/video/zr364xx.c @@ -93,6 +93,8 @@ static struct usb_device_id device_table[] = { {USB_DEVICE(0x06d6, 0x0034), .driver_info = METHOD0 }, {USB_DEVICE(0x0a17, 0x0062), .driver_info = METHOD2 }, {USB_DEVICE(0x06d6, 0x003b), .driver_info = METHOD0 }, + {USB_DEVICE(0x0a17, 0x004e), .driver_info = METHOD2 }, + {USB_DEVICE(0x041e, 0x405d), .driver_info = METHOD2 }, {} /* Terminating entry */ }; diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 1abc95ca9dfa..982e27b86d10 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -258,6 +258,23 @@ config THINKPAD_ACPI_BAY If you are not sure, say Y here. +config THINKPAD_ACPI_VIDEO + bool "Video output control support" + depends on THINKPAD_ACPI + default y + ---help--- + Allows the thinkpad_acpi driver to provide an interface to control + the various video output ports. + + This feature often won't work well, depending on ThinkPad model, + display state, video output devices in use, whether there is a X + server running, phase of the moon, and the current mood of + Schroedinger's cat. If you can use X.org's RandR to control + your ThinkPad's video output ports instead of this feature, + don't think twice: do it and say N here to save some memory. + + If you are not sure, say Y here. + config THINKPAD_ACPI_HOTKEY_POLL bool "Suport NVRAM polling for hot keys" depends on THINKPAD_ACPI diff --git a/drivers/misc/acer-wmi.c b/drivers/misc/acer-wmi.c index d7aea93081f2..74d12b4a3abd 100644 --- a/drivers/misc/acer-wmi.c +++ b/drivers/misc/acer-wmi.c @@ -271,6 +271,15 @@ static struct dmi_system_id acer_quirks[] = { }, .driver_data = &quirk_acer_travelmate_2490, }, + { + .callback = dmi_matched, + .ident = "Acer TravelMate 4200", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 4200"), + }, + .driver_data = &quirk_acer_travelmate_2490, + }, { .callback = dmi_matched, .ident = "Medion MD 98300", diff --git a/drivers/misc/intel_menlow.c b/drivers/misc/intel_menlow.c index f70984ab1e1b..de16e88eb8d3 100644 --- a/drivers/misc/intel_menlow.c +++ b/drivers/misc/intel_menlow.c @@ -170,10 +170,13 @@ static int intel_menlow_memory_add(struct acpi_device *device) cdev = thermal_cooling_device_register("Memory controller", device, &memory_cooling_ops); - acpi_driver_data(device) = cdev; - if (!cdev) - result = -ENODEV; - else { + if (IS_ERR(cdev)) { + result = PTR_ERR(cdev); + goto end; + } + + if (cdev) { + acpi_driver_data(device) = cdev; result = sysfs_create_link(&device->dev.kobj, &cdev->device.kobj, "thermal_cooling"); if (result) diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c index 7ba1acad5402..bb269d0c677e 100644 --- a/drivers/misc/thinkpad_acpi.c +++ b/drivers/misc/thinkpad_acpi.c @@ -221,6 +221,7 @@ static struct { u32 hotkey:1; u32 hotkey_mask:1; u32 hotkey_wlsw:1; + u32 hotkey_tablet:1; u32 light:1; u32 light_status:1; u32 bright_16levels:1; @@ -301,6 +302,13 @@ TPACPI_HANDLE(hkey, ec, "\\_SB.HKEY", /* 600e/x, 770e, 770x */ "HKEY", /* all others */ ); /* 570 */ +TPACPI_HANDLE(vid, root, "\\_SB.PCI.AGP.VGA", /* 570 */ + "\\_SB.PCI0.AGP0.VID0", /* 600e/x, 770x */ + "\\_SB.PCI0.VID0", /* 770e */ + "\\_SB.PCI0.VID", /* A21e, G4x, R50e, X30, X40 */ + "\\_SB.PCI0.AGP.VID", /* all others */ + ); /* R30, R31 */ + /************************************************************************* * ACPI helpers @@ -1053,6 +1061,9 @@ static struct attribute_set *hotkey_dev_attributes; #define HOTKEY_CONFIG_CRITICAL_END #endif /* CONFIG_THINKPAD_ACPI_HOTKEY_POLL */ +/* HKEY.MHKG() return bits */ +#define TP_HOTKEY_TABLET_MASK (1 << 3) + static int hotkey_get_wlsw(int *status) { if (!acpi_evalf(hkey_handle, status, "WLSW", "d")) @@ -1060,6 +1071,16 @@ static int hotkey_get_wlsw(int *status) return 0; } +static int hotkey_get_tablet_mode(int *status) +{ + int s; + + if (!acpi_evalf(hkey_handle, &s, "MHKG", "d")) + return -EIO; + + return ((s & TP_HOTKEY_TABLET_MASK) != 0); +} + /* * Call with hotkey_mutex held */ @@ -1154,15 +1175,31 @@ static void tpacpi_input_send_radiosw(void) { int wlsw; - mutex_lock(&tpacpi_inputdev_send_mutex); - if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&wlsw)) { + mutex_lock(&tpacpi_inputdev_send_mutex); + input_report_switch(tpacpi_inputdev, SW_RADIO, !!wlsw); input_sync(tpacpi_inputdev); - } - mutex_unlock(&tpacpi_inputdev_send_mutex); + mutex_unlock(&tpacpi_inputdev_send_mutex); + } +} + +static void tpacpi_input_send_tabletsw(void) +{ + int state; + + if (tp_features.hotkey_tablet && + !hotkey_get_tablet_mode(&state)) { + mutex_lock(&tpacpi_inputdev_send_mutex); + + input_report_switch(tpacpi_inputdev, + SW_TABLET_MODE, !!state); + input_sync(tpacpi_inputdev); + + mutex_unlock(&tpacpi_inputdev_send_mutex); + } } static void tpacpi_input_send_key(unsigned int scancode) @@ -1417,6 +1454,14 @@ static void hotkey_poll_setup_safe(int may_warn) mutex_unlock(&hotkey_mutex); } +#else /* CONFIG_THINKPAD_ACPI_HOTKEY_POLL */ + +static void hotkey_poll_setup_safe(int __unused) +{ +} + +#endif /* CONFIG_THINKPAD_ACPI_HOTKEY_POLL */ + static int hotkey_inputdev_open(struct input_dev *dev) { switch (tpacpi_lifecycle) { @@ -1444,7 +1489,6 @@ static void hotkey_inputdev_close(struct input_dev *dev) if (tpacpi_lifecycle == TPACPI_LIFE_RUNNING) hotkey_poll_setup_safe(0); } -#endif /* CONFIG_THINKPAD_ACPI_HOTKEY_POLL */ /* sysfs hotkey enable ------------------------------------------------- */ static ssize_t hotkey_enable_show(struct device *dev, @@ -1666,6 +1710,29 @@ static void hotkey_radio_sw_notify_change(void) "hotkey_radio_sw"); } +/* sysfs hotkey tablet mode (pollable) --------------------------------- */ +static ssize_t hotkey_tablet_mode_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int res, s; + res = hotkey_get_tablet_mode(&s); + if (res < 0) + return res; + + return snprintf(buf, PAGE_SIZE, "%d\n", !!s); +} + +static struct device_attribute dev_attr_hotkey_tablet_mode = + __ATTR(hotkey_tablet_mode, S_IRUGO, hotkey_tablet_mode_show, NULL); + +static void hotkey_tablet_mode_notify_change(void) +{ + if (tp_features.hotkey_tablet) + sysfs_notify(&tpacpi_pdev->dev.kobj, NULL, + "hotkey_tablet_mode"); +} + /* sysfs hotkey report_mode -------------------------------------------- */ static ssize_t hotkey_report_mode_show(struct device *dev, struct device_attribute *attr, @@ -1689,7 +1756,7 @@ static ssize_t hotkey_wakeup_reason_show(struct device *dev, static struct device_attribute dev_attr_hotkey_wakeup_reason = __ATTR(wakeup_reason, S_IRUGO, hotkey_wakeup_reason_show, NULL); -void hotkey_wakeup_reason_notify_change(void) +static void hotkey_wakeup_reason_notify_change(void) { if (tp_features.hotkey_mask) sysfs_notify(&tpacpi_pdev->dev.kobj, NULL, @@ -1708,7 +1775,7 @@ static struct device_attribute dev_attr_hotkey_wakeup_hotunplug_complete = __ATTR(wakeup_hotunplug_complete, S_IRUGO, hotkey_wakeup_hotunplug_complete_show, NULL); -void hotkey_wakeup_hotunplug_complete_notify_change(void) +static void hotkey_wakeup_hotunplug_complete_notify_change(void) { if (tp_features.hotkey_mask) sysfs_notify(&tpacpi_pdev->dev.kobj, NULL, @@ -1878,7 +1945,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) str_supported(tp_features.hotkey)); if (tp_features.hotkey) { - hotkey_dev_attributes = create_attr_set(12, NULL); + hotkey_dev_attributes = create_attr_set(13, NULL); if (!hotkey_dev_attributes) return -ENOMEM; res = add_many_to_attr_set(hotkey_dev_attributes, @@ -1957,6 +2024,18 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) &dev_attr_hotkey_radio_sw.attr); } + /* For X41t, X60t, X61t Tablets... */ + if (!res && acpi_evalf(hkey_handle, &status, "MHKG", "qd")) { + tp_features.hotkey_tablet = 1; + printk(TPACPI_INFO + "possible tablet mode switch found; " + "ThinkPad in %s mode\n", + (status & TP_HOTKEY_TABLET_MASK)? + "tablet" : "laptop"); + res = add_to_attr_set(hotkey_dev_attributes, + &dev_attr_hotkey_tablet_mode.attr); + } + if (!res) res = register_attr_set_with_sysfs( hotkey_dev_attributes, @@ -2006,6 +2085,10 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) set_bit(EV_SW, tpacpi_inputdev->evbit); set_bit(SW_RADIO, tpacpi_inputdev->swbit); } + if (tp_features.hotkey_tablet) { + set_bit(EV_SW, tpacpi_inputdev->evbit); + set_bit(SW_TABLET_MODE, tpacpi_inputdev->swbit); + } dbg_printk(TPACPI_DBG_INIT, "enabling hot key handling\n"); @@ -2023,12 +2106,12 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) (hotkey_report_mode < 2) ? "enabled" : "disabled"); -#ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL tpacpi_inputdev->open = &hotkey_inputdev_open; tpacpi_inputdev->close = &hotkey_inputdev_close; hotkey_poll_setup_safe(1); -#endif + tpacpi_input_send_radiosw(); + tpacpi_input_send_tabletsw(); } return (tp_features.hotkey)? 0 : 1; @@ -2156,11 +2239,15 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event) /* 0x5000-0x5FFF: human interface helpers */ switch (hkey) { case 0x5010: /* Lenovo new BIOS: brightness changed */ - case 0x5009: /* X61t: swivel up (tablet mode) */ - case 0x500a: /* X61t: swivel down (normal mode) */ case 0x500b: /* X61t: tablet pen inserted into bay */ case 0x500c: /* X61t: tablet pen removed from bay */ break; + case 0x5009: /* X41t-X61t: swivel up (tablet mode) */ + case 0x500a: /* X41t-X61t: swivel down (normal mode) */ + tpacpi_input_send_tabletsw(); + hotkey_tablet_mode_notify_change(); + send_acpi_ev = 0; + break; case 0x5001: case 0x5002: /* LID switch events. Do not propagate */ @@ -2219,11 +2306,10 @@ static void hotkey_resume(void) "from firmware\n"); tpacpi_input_send_radiosw(); hotkey_radio_sw_notify_change(); + hotkey_tablet_mode_notify_change(); hotkey_wakeup_reason_notify_change(); hotkey_wakeup_hotunplug_complete_notify_change(); -#ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL hotkey_poll_setup_safe(0); -#endif } /* procfs -------------------------------------------------------------- */ @@ -2676,6 +2762,8 @@ static struct ibm_struct wan_driver_data = { * Video subdriver */ +#ifdef CONFIG_THINKPAD_ACPI_VIDEO + enum video_access_mode { TPACPI_VIDEO_NONE = 0, TPACPI_VIDEO_570, /* 570 */ @@ -2703,13 +2791,6 @@ static int video_orig_autosw; static int video_autosw_get(void); static int video_autosw_set(int enable); -TPACPI_HANDLE(vid, root, "\\_SB.PCI.AGP.VGA", /* 570 */ - "\\_SB.PCI0.AGP0.VID0", /* 600e/x, 770x */ - "\\_SB.PCI0.VID0", /* 770e */ - "\\_SB.PCI0.VID", /* A21e, G4x, R50e, X30, X40 */ - "\\_SB.PCI0.AGP.VID", /* all others */ - ); /* R30, R31 */ - TPACPI_HANDLE(vid2, root, "\\_SB.PCI0.AGPB.VID"); /* G41 */ static int __init video_init(struct ibm_init_struct *iibm) @@ -3019,6 +3100,8 @@ static struct ibm_struct video_driver_data = { .exit = video_exit, }; +#endif /* CONFIG_THINKPAD_ACPI_VIDEO */ + /************************************************************************* * Light (thinklight) subdriver */ @@ -5803,10 +5886,12 @@ static struct ibm_init_struct ibms_init[] __initdata = { .init = wan_init, .data = &wan_driver_data, }, +#ifdef CONFIG_THINKPAD_ACPI_VIDEO { .init = video_init, .data = &video_driver_data, }, +#endif { .init = light_init, .data = &light_driver_data, @@ -5918,7 +6003,7 @@ MODULE_PARM_DESC(hotkey_report_mode, #define TPACPI_PARAM(feature) \ module_param_call(feature, set_ibm_param, NULL, NULL, 0); \ - MODULE_PARM_DESC(feature, "Simulates thinkpad-aci procfs command " \ + MODULE_PARM_DESC(feature, "Simulates thinkpad-acpi procfs command " \ "at module load, see documentation") TPACPI_PARAM(hotkey); diff --git a/drivers/mtd/mtdsuper.c b/drivers/mtd/mtdsuper.c index 9b430f20b640..28cc6787a800 100644 --- a/drivers/mtd/mtdsuper.c +++ b/drivers/mtd/mtdsuper.c @@ -184,26 +184,26 @@ int get_sb_mtd(struct file_system_type *fs_type, int flags, ret = path_lookup(dev_name, LOOKUP_FOLLOW, &nd); DEBUG(1, "MTDSB: path_lookup() returned %d, inode %p\n", - ret, nd.dentry ? nd.dentry->d_inode : NULL); + ret, nd.path.dentry ? nd.path.dentry->d_inode : NULL); if (ret) return ret; ret = -EINVAL; - if (!S_ISBLK(nd.dentry->d_inode->i_mode)) + if (!S_ISBLK(nd.path.dentry->d_inode->i_mode)) goto out; - if (nd.mnt->mnt_flags & MNT_NODEV) { + if (nd.path.mnt->mnt_flags & MNT_NODEV) { ret = -EACCES; goto out; } - if (imajor(nd.dentry->d_inode) != MTD_BLOCK_MAJOR) + if (imajor(nd.path.dentry->d_inode) != MTD_BLOCK_MAJOR) goto not_an_MTD_device; - mtdnr = iminor(nd.dentry->d_inode); - path_release(&nd); + mtdnr = iminor(nd.path.dentry->d_inode); + path_put(&nd.path); return get_sb_mtd_nr(fs_type, flags, dev_name, data, mtdnr, fill_super, mnt); @@ -214,7 +214,7 @@ not_an_MTD_device: "MTD: Attempt to mount non-MTD device \"%s\"\n", dev_name); out: - path_release(&nd); + path_put(&nd.path); return ret; } diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c index eef6fecfff2a..be6e918456d9 100644 --- a/drivers/net/8139too.c +++ b/drivers/net/8139too.c @@ -168,7 +168,7 @@ static int debug = -1; * Warning: 64K ring has hardware issues and may lock up. */ #if defined(CONFIG_SH_DREAMCAST) -#define RX_BUF_IDX 1 /* 16K ring */ +#define RX_BUF_IDX 0 /* 8K ring */ #else #define RX_BUF_IDX 2 /* 32K ring */ #endif diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 50c2b60e1fee..f337800076c0 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -931,6 +931,14 @@ config ENC28J60_WRITEVERIFY Enable the verify after the buffer write useful for debugging purpose. If unsure, say N. +config DM9000_DEBUGLEVEL + int "DM9000 maximum debug level" + depends on DM9000 + default 4 + help + The maximum level of debugging code compiled into the DM9000 + driver. + config SMC911X tristate "SMSC LAN911[5678] support" select CRC32 @@ -2352,6 +2360,16 @@ config GELIC_NET To compile this driver as a module, choose M here: the module will be called ps3_gelic. +config GELIC_WIRELESS + bool "PS3 Wireless support" + depends on GELIC_NET + help + This option adds the support for the wireless feature of PS3. + If you have the wireless-less model of PS3 or have no plan to + use wireless feature, disabling this option saves memory. As + the driver automatically distinguishes the models, you can + safely enable this option even if you have a wireless-less model. + config GIANFAR tristate "Gianfar Ethernet" depends on FSL_SOC diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 9fc7794e88ea..3b1ea321dc05 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -70,7 +70,8 @@ obj-$(CONFIG_BNX2X) += bnx2x.o spidernet-y += spider_net.o spider_net_ethtool.o obj-$(CONFIG_SPIDER_NET) += spidernet.o sungem_phy.o obj-$(CONFIG_GELIC_NET) += ps3_gelic.o -ps3_gelic-objs += ps3_gelic_net.o +gelic_wireless-$(CONFIG_GELIC_WIRELESS) += ps3_gelic_wireless.o +ps3_gelic-objs += ps3_gelic_net.o $(gelic_wireless-y) obj-$(CONFIG_TC35815) += tc35815.o obj-$(CONFIG_SKGE) += skge.o obj-$(CONFIG_SKY2) += sky2.o diff --git a/drivers/net/cxgb3/l2t.c b/drivers/net/cxgb3/l2t.c index 17ed4c3527b7..865faee53e17 100644 --- a/drivers/net/cxgb3/l2t.c +++ b/drivers/net/cxgb3/l2t.c @@ -404,7 +404,7 @@ found: if (neigh->nud_state & NUD_FAILED) { arpq = e->arpq_head; e->arpq_head = e->arpq_tail = NULL; - } else if (neigh_is_connected(neigh)) + } else if (neigh->nud_state & (NUD_CONNECTED|NUD_STALE)) setup_l2e_send_pending(dev, NULL, e); } else { e->state = neigh_is_connected(neigh) ? diff --git a/drivers/net/cxgb3/sge.c b/drivers/net/cxgb3/sge.c index 9ca8c66abd16..979f3fc5e765 100644 --- a/drivers/net/cxgb3/sge.c +++ b/drivers/net/cxgb3/sge.c @@ -1059,6 +1059,14 @@ static void write_tx_pkt_wr(struct adapter *adap, struct sk_buff *skb, htonl(V_WR_TID(q->token))); } +static inline void t3_stop_queue(struct net_device *dev, struct sge_qset *qs, + struct sge_txq *q) +{ + netif_stop_queue(dev); + set_bit(TXQ_ETH, &qs->txq_stopped); + q->stops++; +} + /** * eth_xmit - add a packet to the Ethernet Tx queue * @skb: the packet @@ -1090,31 +1098,18 @@ int t3_eth_xmit(struct sk_buff *skb, struct net_device *dev) ndesc = calc_tx_descs(skb); if (unlikely(credits < ndesc)) { - if (!netif_queue_stopped(dev)) { - netif_stop_queue(dev); - set_bit(TXQ_ETH, &qs->txq_stopped); - q->stops++; - dev_err(&adap->pdev->dev, - "%s: Tx ring %u full while queue awake!\n", - dev->name, q->cntxt_id & 7); - } + t3_stop_queue(dev, qs, q); + dev_err(&adap->pdev->dev, + "%s: Tx ring %u full while queue awake!\n", + dev->name, q->cntxt_id & 7); spin_unlock(&q->lock); return NETDEV_TX_BUSY; } q->in_use += ndesc; - if (unlikely(credits - ndesc < q->stop_thres)) { - q->stops++; - netif_stop_queue(dev); - set_bit(TXQ_ETH, &qs->txq_stopped); -#if !USE_GTS - if (should_restart_tx(q) && - test_and_clear_bit(TXQ_ETH, &qs->txq_stopped)) { - q->restarts++; - netif_wake_queue(dev); - } -#endif - } + if (unlikely(credits - ndesc < q->stop_thres)) + if (USE_GTS || !should_restart_tx(q)) + t3_stop_queue(dev, qs, q); gen = q->gen; q->unacked += ndesc; diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c index 6a20a5491a96..1fe305ca2cf0 100644 --- a/drivers/net/dm9000.c +++ b/drivers/net/dm9000.c @@ -1,7 +1,5 @@ /* - * dm9000.c: Version 1.2 03/18/2003 - * - * A Davicom DM9000 ISA NIC fast Ethernet driver for Linux. + * Davicom DM9000 Fast Ethernet driver for Linux. * Copyright (C) 1997 Sten Wang * * This program is free software; you can redistribute it and/or @@ -14,44 +12,11 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * - * (C)Copyright 1997-1998 DAVICOM Semiconductor,Inc. All Rights Reserved. + * (C) Copyright 1997-1998 DAVICOM Semiconductor,Inc. All Rights Reserved. * - * V0.11 06/20/2001 REG_0A bit3=1, default enable BP with DA match - * 06/22/2001 Support DM9801 progrmming - * E3: R25 = ((R24 + NF) & 0x00ff) | 0xf000 - * E4: R25 = ((R24 + NF) & 0x00ff) | 0xc200 - * R17 = (R17 & 0xfff0) | NF + 3 - * E5: R25 = ((R24 + NF - 3) & 0x00ff) | 0xc200 - * R17 = (R17 & 0xfff0) | NF - * - * v1.00 modify by simon 2001.9.5 - * change for kernel 2.4.x - * - * v1.1 11/09/2001 fix force mode bug - * - * v1.2 03/18/2003 Weilun Huang : - * Fixed phy reset. - * Added tx/rx 32 bit mode. - * Cleaned up for kernel merge. - * - * 03/03/2004 Sascha Hauer - * Port to 2.6 kernel - * - * 24-Sep-2004 Ben Dooks - * Cleanup of code to remove ifdefs - * Allowed platform device data to influence access width - * Reformatting areas of code - * - * 17-Mar-2005 Sascha Hauer - * * removed 2.4 style module parameters - * * removed removed unused stat counter and fixed - * net_device_stats - * * introduced tx_timeout function - * * reworked locking - * - * 01-Jul-2005 Ben Dooks - * * fixed spinlock call without pointer - * * ensure spinlock is initialised + * Additional updates, Copyright: + * Ben Dooks + * Sascha Hauer */ #include @@ -63,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -80,30 +46,7 @@ #define CARDNAME "dm9000" #define PFX CARDNAME ": " - -#define DM9000_TIMER_WUT jiffies+(HZ*2) /* timer wakeup time : 2 second */ - -#define DM9000_DEBUG 0 - -#if DM9000_DEBUG > 2 -#define PRINTK3(args...) printk(CARDNAME ": " args) -#else -#define PRINTK3(args...) do { } while(0) -#endif - -#if DM9000_DEBUG > 1 -#define PRINTK2(args...) printk(CARDNAME ": " args) -#else -#define PRINTK2(args...) do { } while(0) -#endif - -#if DM9000_DEBUG > 0 -#define PRINTK1(args...) printk(CARDNAME ": " args) -#define PRINTK(args...) printk(CARDNAME ": " args) -#else -#define PRINTK1(args...) do { } while(0) -#define PRINTK(args...) printk(KERN_DEBUG args) -#endif +#define DRV_VERSION "1.30" #ifdef CONFIG_BLACKFIN #define readsb insb @@ -112,9 +55,9 @@ #define writesb outsb #define writesw outsw #define writesl outsl -#define DM9000_IRQ_FLAGS (IRQF_SHARED | IRQF_TRIGGER_HIGH) +#define DEFAULT_TRIGGER IRQF_TRIGGER_HIGH #else -#define DM9000_IRQ_FLAGS (IRQF_SHARED | IRQT_RISING) +#define DEFAULT_TRIGGER (0) #endif /* @@ -124,6 +67,24 @@ static int watchdog = 5000; module_param(watchdog, int, 0400); MODULE_PARM_DESC(watchdog, "transmit timeout in milliseconds"); +/* DM9000 register address locking. + * + * The DM9000 uses an address register to control where data written + * to the data register goes. This means that the address register + * must be preserved over interrupts or similar calls. + * + * During interrupt and other critical calls, a spinlock is used to + * protect the system, but the calls themselves save the address + * in the address register in case they are interrupting another + * access to the device. + * + * For general accesses a lock is provided so that calls which are + * allowed to sleep are serialised so that the address register does + * not need to be saved. This lock also serves to serialise access + * to the EEPROM and PHY access registers which are shared between + * these two devices. + */ + /* Structure/enum declaration ------------------------------- */ typedef struct board_info { @@ -137,33 +98,52 @@ typedef struct board_info { u16 dbug_cnt; u8 io_mode; /* 0:word, 2:byte */ u8 phy_addr; + unsigned int flags; + unsigned int in_suspend :1; + + int debug_level; void (*inblk)(void __iomem *port, void *data, int length); void (*outblk)(void __iomem *port, void *data, int length); void (*dumpblk)(void __iomem *port, int length); + struct device *dev; /* parent device */ + struct resource *addr_res; /* resources found */ struct resource *data_res; struct resource *addr_req; /* resources requested */ struct resource *data_req; struct resource *irq_res; - struct timer_list timer; - unsigned char srom[128]; + struct mutex addr_lock; /* phy and eeprom access lock */ + spinlock_t lock; struct mii_if_info mii; u32 msg_enable; } board_info_t; +/* debug code */ + +#define dm9000_dbg(db, lev, msg...) do { \ + if ((lev) < CONFIG_DM9000_DEBUGLEVEL && \ + (lev) < db->debug_level) { \ + dev_dbg(db->dev, msg); \ + } \ +} while (0) + +static inline board_info_t *to_dm9000_board(struct net_device *dev) +{ + return dev->priv; +} + /* function declaration ------------------------------------- */ static int dm9000_probe(struct platform_device *); static int dm9000_open(struct net_device *); static int dm9000_start_xmit(struct sk_buff *, struct net_device *); static int dm9000_stop(struct net_device *); +static int dm9000_ioctl(struct net_device *dev, struct ifreq *req, int cmd); - -static void dm9000_timer(unsigned long); static void dm9000_init_dm9000(struct net_device *); static irqreturn_t dm9000_interrupt(int, void *); @@ -171,20 +151,19 @@ static irqreturn_t dm9000_interrupt(int, void *); static int dm9000_phy_read(struct net_device *dev, int phyaddr_unsused, int reg); static void dm9000_phy_write(struct net_device *dev, int phyaddr_unused, int reg, int value); -static u16 read_srom_word(board_info_t *, int); + +static void dm9000_read_eeprom(board_info_t *, int addr, u8 *to); +static void dm9000_write_eeprom(board_info_t *, int addr, u8 *dp); static void dm9000_rx(struct net_device *); static void dm9000_hash_table(struct net_device *); -//#define DM9000_PROGRAM_EEPROM -#ifdef DM9000_PROGRAM_EEPROM -static void program_eeprom(board_info_t * db); -#endif /* DM9000 network board routine ---------------------------- */ static void dm9000_reset(board_info_t * db) { - PRINTK1("dm9000x: resetting\n"); + dev_dbg(db->dev, "resetting device\n"); + /* RESET device */ writeb(DM9000_NCR, db->io_addr); udelay(200); @@ -300,14 +279,10 @@ static void dm9000_set_io(struct board_info *db, int byte_width) db->inblk = dm9000_inblk_8bit; break; - case 2: - db->dumpblk = dm9000_dumpblk_16bit; - db->outblk = dm9000_outblk_16bit; - db->inblk = dm9000_inblk_16bit; - break; case 3: - printk(KERN_ERR PFX ": 3 byte IO, falling back to 16bit\n"); + dev_dbg(db->dev, ": 3 byte IO, falling back to 16bit\n"); + case 2: db->dumpblk = dm9000_dumpblk_16bit; db->outblk = dm9000_outblk_16bit; db->inblk = dm9000_inblk_16bit; @@ -358,6 +333,139 @@ static void dm9000_poll_controller(struct net_device *dev) } #endif +static int dm9000_ioctl(struct net_device *dev, struct ifreq *req, int cmd) +{ + board_info_t *dm = to_dm9000_board(dev); + + if (!netif_running(dev)) + return -EINVAL; + + return generic_mii_ioctl(&dm->mii, if_mii(req), cmd, NULL); +} + +/* ethtool ops */ + +static void dm9000_get_drvinfo(struct net_device *dev, + struct ethtool_drvinfo *info) +{ + board_info_t *dm = to_dm9000_board(dev); + + strcpy(info->driver, CARDNAME); + strcpy(info->version, DRV_VERSION); + strcpy(info->bus_info, to_platform_device(dm->dev)->name); +} + +static u32 dm9000_get_msglevel(struct net_device *dev) +{ + board_info_t *dm = to_dm9000_board(dev); + + return dm->msg_enable; +} + +static void dm9000_set_msglevel(struct net_device *dev, u32 value) +{ + board_info_t *dm = to_dm9000_board(dev); + + dm->msg_enable = value; +} + +static int dm9000_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + board_info_t *dm = to_dm9000_board(dev); + + mii_ethtool_gset(&dm->mii, cmd); + return 0; +} + +static int dm9000_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + board_info_t *dm = to_dm9000_board(dev); + + return mii_ethtool_sset(&dm->mii, cmd); +} + +static int dm9000_nway_reset(struct net_device *dev) +{ + board_info_t *dm = to_dm9000_board(dev); + return mii_nway_restart(&dm->mii); +} + +static u32 dm9000_get_link(struct net_device *dev) +{ + board_info_t *dm = to_dm9000_board(dev); + return mii_link_ok(&dm->mii); +} + +#define DM_EEPROM_MAGIC (0x444D394B) + +static int dm9000_get_eeprom_len(struct net_device *dev) +{ + return 128; +} + +static int dm9000_get_eeprom(struct net_device *dev, + struct ethtool_eeprom *ee, u8 *data) +{ + board_info_t *dm = to_dm9000_board(dev); + int offset = ee->offset; + int len = ee->len; + int i; + + /* EEPROM access is aligned to two bytes */ + + if ((len & 1) != 0 || (offset & 1) != 0) + return -EINVAL; + + if (dm->flags & DM9000_PLATF_NO_EEPROM) + return -ENOENT; + + ee->magic = DM_EEPROM_MAGIC; + + for (i = 0; i < len; i += 2) + dm9000_read_eeprom(dm, (offset + i) / 2, data + i); + + return 0; +} + +static int dm9000_set_eeprom(struct net_device *dev, + struct ethtool_eeprom *ee, u8 *data) +{ + board_info_t *dm = to_dm9000_board(dev); + int offset = ee->offset; + int len = ee->len; + int i; + + /* EEPROM access is aligned to two bytes */ + + if ((len & 1) != 0 || (offset & 1) != 0) + return -EINVAL; + + if (dm->flags & DM9000_PLATF_NO_EEPROM) + return -ENOENT; + + if (ee->magic != DM_EEPROM_MAGIC) + return -EINVAL; + + for (i = 0; i < len; i += 2) + dm9000_write_eeprom(dm, (offset + i) / 2, data + i); + + return 0; +} + +static const struct ethtool_ops dm9000_ethtool_ops = { + .get_drvinfo = dm9000_get_drvinfo, + .get_settings = dm9000_get_settings, + .set_settings = dm9000_set_settings, + .get_msglevel = dm9000_get_msglevel, + .set_msglevel = dm9000_set_msglevel, + .nway_reset = dm9000_nway_reset, + .get_link = dm9000_get_link, + .get_eeprom_len = dm9000_get_eeprom_len, + .get_eeprom = dm9000_get_eeprom, + .set_eeprom = dm9000_set_eeprom, +}; + + /* dm9000_release_board * * release a board, and any mapped resources @@ -401,6 +509,7 @@ dm9000_probe(struct platform_device *pdev) struct dm9000_plat_data *pdata = pdev->dev.platform_data; struct board_info *db; /* Point a board information structure */ struct net_device *ndev; + const unsigned char *mac_src; unsigned long base; int ret = 0; int iosize; @@ -410,19 +519,22 @@ dm9000_probe(struct platform_device *pdev) /* Init network device */ ndev = alloc_etherdev(sizeof (struct board_info)); if (!ndev) { - printk("%s: could not allocate device.\n", CARDNAME); + dev_err(&pdev->dev, "could not allocate device.\n"); return -ENOMEM; } SET_NETDEV_DEV(ndev, &pdev->dev); - PRINTK2("dm9000_probe()"); + dev_dbg(&pdev->dev, "dm9000_probe()"); /* setup board info structure */ db = (struct board_info *) ndev->priv; memset(db, 0, sizeof (*db)); + db->dev = &pdev->dev; + spin_lock_init(&db->lock); + mutex_init(&db->addr_lock); if (pdev->num_resources < 2) { ret = -ENODEV; @@ -450,7 +562,7 @@ dm9000_probe(struct platform_device *pdev) if (db->addr_res == NULL || db->data_res == NULL || db->irq_res == NULL) { - printk(KERN_ERR PFX "insufficient resources\n"); + dev_err(db->dev, "insufficient resources\n"); ret = -ENOENT; goto out; } @@ -460,7 +572,7 @@ dm9000_probe(struct platform_device *pdev) pdev->name); if (db->addr_req == NULL) { - printk(KERN_ERR PFX "cannot claim address reg area\n"); + dev_err(db->dev, "cannot claim address reg area\n"); ret = -EIO; goto out; } @@ -468,7 +580,7 @@ dm9000_probe(struct platform_device *pdev) db->io_addr = ioremap(db->addr_res->start, i); if (db->io_addr == NULL) { - printk(KERN_ERR "failed to ioremap address reg\n"); + dev_err(db->dev, "failed to ioremap address reg\n"); ret = -EINVAL; goto out; } @@ -478,7 +590,7 @@ dm9000_probe(struct platform_device *pdev) pdev->name); if (db->data_req == NULL) { - printk(KERN_ERR PFX "cannot claim data reg area\n"); + dev_err(db->dev, "cannot claim data reg area\n"); ret = -EIO; goto out; } @@ -486,7 +598,7 @@ dm9000_probe(struct platform_device *pdev) db->io_data = ioremap(db->data_res->start, iosize); if (db->io_data == NULL) { - printk(KERN_ERR "failed to ioremap data reg\n"); + dev_err(db->dev,"failed to ioremap data reg\n"); ret = -EINVAL; goto out; } @@ -525,12 +637,14 @@ dm9000_probe(struct platform_device *pdev) if (pdata->dumpblk != NULL) db->dumpblk = pdata->dumpblk; + + db->flags = pdata->flags; } dm9000_reset(db); /* try two times, DM9000 sometimes gets the first read wrong */ - for (i = 0; i < 2; i++) { + for (i = 0; i < 8; i++) { id_val = ior(db, DM9000_VIDL); id_val |= (u32)ior(db, DM9000_VIDH) << 8; id_val |= (u32)ior(db, DM9000_PIDL) << 16; @@ -538,11 +652,11 @@ dm9000_probe(struct platform_device *pdev) if (id_val == DM9000_ID) break; - printk("%s: read wrong id 0x%08x\n", CARDNAME, id_val); + dev_err(db->dev, "read wrong id 0x%08x\n", id_val); } if (id_val != DM9000_ID) { - printk("%s: wrong id: 0x%08x\n", CARDNAME, id_val); + dev_err(db->dev, "wrong id: 0x%08x\n", id_val); ret = -ENODEV; goto out; } @@ -558,13 +672,13 @@ dm9000_probe(struct platform_device *pdev) ndev->watchdog_timeo = msecs_to_jiffies(watchdog); ndev->stop = &dm9000_stop; ndev->set_multicast_list = &dm9000_hash_table; + ndev->ethtool_ops = &dm9000_ethtool_ops; + ndev->do_ioctl = &dm9000_ioctl; + #ifdef CONFIG_NET_POLL_CONTROLLER ndev->poll_controller = &dm9000_poll_controller; #endif -#ifdef DM9000_PROGRAM_EEPROM - program_eeprom(db); -#endif db->msg_enable = NETIF_MSG_LINK; db->mii.phy_id_mask = 0x1f; db->mii.reg_num_mask = 0x1f; @@ -574,38 +688,37 @@ dm9000_probe(struct platform_device *pdev) db->mii.mdio_read = dm9000_phy_read; db->mii.mdio_write = dm9000_phy_write; - /* Read SROM content */ - for (i = 0; i < 64; i++) - ((u16 *) db->srom)[i] = read_srom_word(db, i); + mac_src = "eeprom"; - /* Set Node Address */ - for (i = 0; i < 6; i++) - ndev->dev_addr[i] = db->srom[i]; + /* try reading the node address from the attached EEPROM */ + for (i = 0; i < 6; i += 2) + dm9000_read_eeprom(db, i / 2, ndev->dev_addr+i); if (!is_valid_ether_addr(ndev->dev_addr)) { /* try reading from mac */ - + + mac_src = "chip"; for (i = 0; i < 6; i++) ndev->dev_addr[i] = ior(db, i+DM9000_PAR); } if (!is_valid_ether_addr(ndev->dev_addr)) - printk("%s: Invalid ethernet MAC address. Please " - "set using ifconfig\n", ndev->name); + dev_warn(db->dev, "%s: Invalid ethernet MAC address. Please " + "set using ifconfig\n", ndev->name); platform_set_drvdata(pdev, ndev); ret = register_netdev(ndev); if (ret == 0) { DECLARE_MAC_BUF(mac); - printk("%s: dm9000 at %p,%p IRQ %d MAC: %s\n", + printk("%s: dm9000 at %p,%p IRQ %d MAC: %s (%s)\n", ndev->name, db->io_addr, db->io_data, ndev->irq, - print_mac(mac, ndev->dev_addr)); + print_mac(mac, ndev->dev_addr), mac_src); } return 0; out: - printk("%s: not found (%d).\n", CARDNAME, ret); + dev_err(db->dev, "not found (%d).\n", ret); dm9000_release_board(pdev, db); free_netdev(ndev); @@ -621,10 +734,22 @@ static int dm9000_open(struct net_device *dev) { board_info_t *db = (board_info_t *) dev->priv; + unsigned long irqflags = db->irq_res->flags & IRQF_TRIGGER_MASK; - PRINTK2("entering dm9000_open\n"); + if (netif_msg_ifup(db)) + dev_dbg(db->dev, "enabling %s\n", dev->name); - if (request_irq(dev->irq, &dm9000_interrupt, DM9000_IRQ_FLAGS, dev->name, dev)) + /* If there is no IRQ type specified, default to something that + * may work, and tell the user that this is a problem */ + + if (irqflags == IRQF_TRIGGER_NONE) { + dev_warn(db->dev, "WARNING: no IRQ resource flags set.\n"); + irqflags = DEFAULT_TRIGGER; + } + + irqflags |= IRQF_SHARED; + + if (request_irq(dev->irq, &dm9000_interrupt, irqflags, dev->name, dev)) return -EAGAIN; /* Initialize DM9000 board */ @@ -634,13 +759,6 @@ dm9000_open(struct net_device *dev) /* Init driver variable */ db->dbug_cnt = 0; - /* set and active a timer process */ - init_timer(&db->timer); - db->timer.expires = DM9000_TIMER_WUT; - db->timer.data = (unsigned long) dev; - db->timer.function = &dm9000_timer; - add_timer(&db->timer); - mii_check_media(&db->mii, netif_msg_link(db), 1); netif_start_queue(dev); @@ -655,7 +773,7 @@ dm9000_init_dm9000(struct net_device *dev) { board_info_t *db = (board_info_t *) dev->priv; - PRINTK1("entering %s\n",__FUNCTION__); + dm9000_dbg(db, 1, "entering %s\n", __func__); /* I/O mode */ db->io_mode = ior(db, DM9000_ISR) >> 6; /* ISR bit7:6 keeps I/O mode */ @@ -665,6 +783,9 @@ dm9000_init_dm9000(struct net_device *dev) iow(db, DM9000_GPCR, GPCR_GEP_CNTL); /* Let GPIO0 output */ iow(db, DM9000_GPR, 0); /* Enable PHY */ + if (db->flags & DM9000_PLATF_EXT_PHY) + iow(db, DM9000_NCR, NCR_EXT_PHY); + /* Program operating register */ iow(db, DM9000_TCR, 0); /* TX Polling clear */ iow(db, DM9000_BPTR, 0x3f); /* Less 3Kb, 200us */ @@ -698,7 +819,7 @@ dm9000_start_xmit(struct sk_buff *skb, struct net_device *dev) unsigned long flags; board_info_t *db = (board_info_t *) dev->priv; - PRINTK3("dm9000_start_xmit\n"); + dm9000_dbg(db, 3, "%s:\n", __func__); if (db->tx_pkt_cnt > 1) return 1; @@ -715,8 +836,8 @@ dm9000_start_xmit(struct sk_buff *skb, struct net_device *dev) /* TX control: First packet immediately send, second packet queue */ if (db->tx_pkt_cnt == 1) { /* Set TX length to DM9000 */ - iow(db, DM9000_TXPLL, skb->len & 0xff); - iow(db, DM9000_TXPLH, (skb->len >> 8) & 0xff); + iow(db, DM9000_TXPLL, skb->len); + iow(db, DM9000_TXPLH, skb->len >> 8); /* Issue TX polling command */ iow(db, DM9000_TCR, TCR_TXREQ); /* Cleared after TX complete */ @@ -757,10 +878,8 @@ dm9000_stop(struct net_device *ndev) { board_info_t *db = (board_info_t *) ndev->priv; - PRINTK1("entering %s\n",__FUNCTION__); - - /* deleted timer */ - del_timer(&db->timer); + if (netif_msg_ifdown(db)) + dev_dbg(db->dev, "shutting down %s\n", ndev->name); netif_stop_queue(ndev); netif_carrier_off(ndev); @@ -788,10 +907,13 @@ dm9000_tx_done(struct net_device *dev, board_info_t * db) db->tx_pkt_cnt--; dev->stats.tx_packets++; + if (netif_msg_tx_done(db)) + dev_dbg(db->dev, "tx done, NSR %02x\n", tx_status); + /* Queue packet check & send */ if (db->tx_pkt_cnt > 0) { - iow(db, DM9000_TXPLL, db->queue_pkt_len & 0xff); - iow(db, DM9000_TXPLH, (db->queue_pkt_len >> 8) & 0xff); + iow(db, DM9000_TXPLL, db->queue_pkt_len); + iow(db, DM9000_TXPLH, db->queue_pkt_len >> 8); iow(db, DM9000_TCR, TCR_TXREQ); dev->trans_start = jiffies; } @@ -803,19 +925,14 @@ static irqreturn_t dm9000_interrupt(int irq, void *dev_id) { struct net_device *dev = dev_id; - board_info_t *db; + board_info_t *db = (board_info_t *) dev->priv; int int_status; u8 reg_save; - PRINTK3("entering %s\n",__FUNCTION__); - - if (!dev) { - PRINTK1("dm9000_interrupt() without DEVICE arg\n"); - return IRQ_HANDLED; - } + dm9000_dbg(db, 3, "entering %s\n", __func__); /* A real interrupt coming */ - db = (board_info_t *) dev->priv; + spin_lock(&db->lock); /* Save previous register address */ @@ -828,6 +945,9 @@ dm9000_interrupt(int irq, void *dev_id) int_status = ior(db, DM9000_ISR); /* Got ISR */ iow(db, DM9000_ISR, int_status); /* Clear ISR status */ + if (netif_msg_intr(db)) + dev_dbg(db->dev, "interrupt status %02x\n", int_status); + /* Received the coming packet */ if (int_status & ISR_PRS) dm9000_rx(dev); @@ -847,27 +967,9 @@ dm9000_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } -/* - * A periodic timer routine - * Dynamic media sense, allocated Rx buffer... - */ -static void -dm9000_timer(unsigned long data) -{ - struct net_device *dev = (struct net_device *) data; - board_info_t *db = (board_info_t *) dev->priv; - - PRINTK3("dm9000_timer()\n"); - - mii_check_media(&db->mii, netif_msg_link(db), 0); - - /* Set timer again */ - db->timer.expires = DM9000_TIMER_WUT; - add_timer(&db->timer); -} - struct dm9000_rxhdr { - u16 RxStatus; + u8 RxPktReady; + u8 RxStatus; u16 RxLen; } __attribute__((__packed__)); @@ -893,7 +995,7 @@ dm9000_rx(struct net_device *dev) /* Status check: this byte must be 0 or 1 */ if (rxbyte > DM9000_PKT_RDY) { - printk("status check failed: %d\n", rxbyte); + dev_warn(db->dev, "status check fail: %d\n", rxbyte); iow(db, DM9000_RCR, 0x00); /* Stop Device */ iow(db, DM9000_ISR, IMR_PAR); /* Stop INT request */ return; @@ -908,30 +1010,38 @@ dm9000_rx(struct net_device *dev) (db->inblk)(db->io_data, &rxhdr, sizeof(rxhdr)); - RxLen = rxhdr.RxLen; + RxLen = le16_to_cpu(rxhdr.RxLen); + + if (netif_msg_rx_status(db)) + dev_dbg(db->dev, "RX: status %02x, length %04x\n", + rxhdr.RxStatus, RxLen); /* Packet Status check */ if (RxLen < 0x40) { GoodPacket = false; - PRINTK1("Bad Packet received (runt)\n"); + if (netif_msg_rx_err(db)) + dev_dbg(db->dev, "RX: Bad Packet (runt)\n"); } if (RxLen > DM9000_PKT_MAX) { - PRINTK1("RST: RX Len:%x\n", RxLen); + dev_dbg(db->dev, "RST: RX Len:%x\n", RxLen); } - if (rxhdr.RxStatus & 0xbf00) { + if (rxhdr.RxStatus & 0xbf) { GoodPacket = false; - if (rxhdr.RxStatus & 0x100) { - PRINTK1("fifo error\n"); + if (rxhdr.RxStatus & 0x01) { + if (netif_msg_rx_err(db)) + dev_dbg(db->dev, "fifo error\n"); dev->stats.rx_fifo_errors++; } - if (rxhdr.RxStatus & 0x200) { - PRINTK1("crc error\n"); + if (rxhdr.RxStatus & 0x02) { + if (netif_msg_rx_err(db)) + dev_dbg(db->dev, "crc error\n"); dev->stats.rx_crc_errors++; } - if (rxhdr.RxStatus & 0x8000) { - PRINTK1("length error\n"); + if (rxhdr.RxStatus & 0x80) { + if (netif_msg_rx_err(db)) + dev_dbg(db->dev, "length error\n"); dev->stats.rx_length_errors++; } } @@ -960,72 +1070,119 @@ dm9000_rx(struct net_device *dev) } while (rxbyte == DM9000_PKT_RDY); } -/* - * Read a word data from SROM - */ -static u16 -read_srom_word(board_info_t * db, int offset) +static unsigned int +dm9000_read_locked(board_info_t *db, int reg) { - iow(db, DM9000_EPAR, offset); - iow(db, DM9000_EPCR, EPCR_ERPRR); - mdelay(8); /* according to the datasheet 200us should be enough, - but it doesn't work */ - iow(db, DM9000_EPCR, 0x0); - return (ior(db, DM9000_EPDRL) + (ior(db, DM9000_EPDRH) << 8)); + unsigned long flags; + unsigned int ret; + + spin_lock_irqsave(&db->lock, flags); + ret = ior(db, reg); + spin_unlock_irqrestore(&db->lock, flags); + + return ret; +} + +static int dm9000_wait_eeprom(board_info_t *db) +{ + unsigned int status; + int timeout = 8; /* wait max 8msec */ + + /* The DM9000 data sheets say we should be able to + * poll the ERRE bit in EPCR to wait for the EEPROM + * operation. From testing several chips, this bit + * does not seem to work. + * + * We attempt to use the bit, but fall back to the + * timeout (which is why we do not return an error + * on expiry) to say that the EEPROM operation has + * completed. + */ + + while (1) { + status = dm9000_read_locked(db, DM9000_EPCR); + + if ((status & EPCR_ERRE) == 0) + break; + + if (timeout-- < 0) { + dev_dbg(db->dev, "timeout waiting EEPROM\n"); + break; + } + } + + return 0; +} + +/* + * Read a word data from EEPROM + */ +static void +dm9000_read_eeprom(board_info_t *db, int offset, u8 *to) +{ + unsigned long flags; + + if (db->flags & DM9000_PLATF_NO_EEPROM) { + to[0] = 0xff; + to[1] = 0xff; + return; + } + + mutex_lock(&db->addr_lock); + + spin_lock_irqsave(&db->lock, flags); + + iow(db, DM9000_EPAR, offset); + iow(db, DM9000_EPCR, EPCR_ERPRR); + + spin_unlock_irqrestore(&db->lock, flags); + + dm9000_wait_eeprom(db); + + /* delay for at-least 150uS */ + msleep(1); + + spin_lock_irqsave(&db->lock, flags); + + iow(db, DM9000_EPCR, 0x0); + + to[0] = ior(db, DM9000_EPDRL); + to[1] = ior(db, DM9000_EPDRH); + + spin_unlock_irqrestore(&db->lock, flags); + + mutex_unlock(&db->addr_lock); } -#ifdef DM9000_PROGRAM_EEPROM /* * Write a word data to SROM */ static void -write_srom_word(board_info_t * db, int offset, u16 val) +dm9000_write_eeprom(board_info_t *db, int offset, u8 *data) { + unsigned long flags; + + if (db->flags & DM9000_PLATF_NO_EEPROM) + return; + + mutex_lock(&db->addr_lock); + + spin_lock_irqsave(&db->lock, flags); iow(db, DM9000_EPAR, offset); - iow(db, DM9000_EPDRH, ((val >> 8) & 0xff)); - iow(db, DM9000_EPDRL, (val & 0xff)); + iow(db, DM9000_EPDRH, data[1]); + iow(db, DM9000_EPDRL, data[0]); iow(db, DM9000_EPCR, EPCR_WEP | EPCR_ERPRW); - mdelay(8); /* same shit */ + spin_unlock_irqrestore(&db->lock, flags); + + dm9000_wait_eeprom(db); + + mdelay(1); /* wait at least 150uS to clear */ + + spin_lock_irqsave(&db->lock, flags); iow(db, DM9000_EPCR, 0); -} + spin_unlock_irqrestore(&db->lock, flags); -/* - * Only for development: - * Here we write static data to the eeprom in case - * we don't have valid content on a new board - */ -static void -program_eeprom(board_info_t * db) -{ - u16 eeprom[] = { 0x0c00, 0x007f, 0x1300, /* MAC Address */ - 0x0000, /* Autoload: accept nothing */ - 0x0a46, 0x9000, /* Vendor / Product ID */ - 0x0000, /* pin control */ - 0x0000, - }; /* Wake-up mode control */ - int i; - for (i = 0; i < 8; i++) - write_srom_word(db, i, eeprom[i]); -} -#endif - - -/* - * Calculate the CRC valude of the Rx packet - * flag = 1 : return the reverse CRC (for the received packet CRC) - * 0 : return the normal CRC (for Hash Table index) - */ - -static unsigned long -cal_CRC(unsigned char *Data, unsigned int Len, u8 flag) -{ - - u32 crc = ether_crc_le(Len, Data); - - if (flag) - return ~crc; - - return crc; + mutex_unlock(&db->addr_lock); } /* @@ -1037,15 +1194,16 @@ dm9000_hash_table(struct net_device *dev) board_info_t *db = (board_info_t *) dev->priv; struct dev_mc_list *mcptr = dev->mc_list; int mc_cnt = dev->mc_count; + int i, oft; u32 hash_val; - u16 i, oft, hash_table[4]; + u16 hash_table[4]; unsigned long flags; - PRINTK2("dm9000_hash_table()\n"); + dm9000_dbg(db, 1, "entering %s\n", __func__); - spin_lock_irqsave(&db->lock,flags); + spin_lock_irqsave(&db->lock, flags); - for (i = 0, oft = 0x10; i < 6; i++, oft++) + for (i = 0, oft = DM9000_PAR; i < 6; i++, oft++) iow(db, oft, dev->dev_addr[i]); /* Clear Hash Table */ @@ -1057,20 +1215,32 @@ dm9000_hash_table(struct net_device *dev) /* the multicast address in Hash Table : 64 bits */ for (i = 0; i < mc_cnt; i++, mcptr = mcptr->next) { - hash_val = cal_CRC((char *) mcptr->dmi_addr, 6, 0) & 0x3f; + hash_val = ether_crc_le(6, mcptr->dmi_addr) & 0x3f; hash_table[hash_val / 16] |= (u16) 1 << (hash_val % 16); } /* Write the hash table to MAC MD table */ - for (i = 0, oft = 0x16; i < 4; i++) { - iow(db, oft++, hash_table[i] & 0xff); - iow(db, oft++, (hash_table[i] >> 8) & 0xff); + for (i = 0, oft = DM9000_MAR; i < 4; i++) { + iow(db, oft++, hash_table[i]); + iow(db, oft++, hash_table[i] >> 8); } - spin_unlock_irqrestore(&db->lock,flags); + spin_unlock_irqrestore(&db->lock, flags); } +/* + * Sleep, either by using msleep() or if we are suspending, then + * use mdelay() to sleep. + */ +static void dm9000_msleep(board_info_t *db, unsigned int ms) +{ + if (db->in_suspend) + mdelay(ms); + else + msleep(ms); +} + /* * Read a word from phyxcer */ @@ -1082,6 +1252,8 @@ dm9000_phy_read(struct net_device *dev, int phy_reg_unused, int reg) unsigned int reg_save; int ret; + mutex_lock(&db->addr_lock); + spin_lock_irqsave(&db->lock,flags); /* Save previous register address */ @@ -1091,7 +1263,15 @@ dm9000_phy_read(struct net_device *dev, int phy_reg_unused, int reg) iow(db, DM9000_EPAR, DM9000_PHY | reg); iow(db, DM9000_EPCR, 0xc); /* Issue phyxcer read command */ - udelay(100); /* Wait read complete */ + + writeb(reg_save, db->io_addr); + spin_unlock_irqrestore(&db->lock,flags); + + dm9000_msleep(db, 1); /* Wait read complete */ + + spin_lock_irqsave(&db->lock,flags); + reg_save = readb(db->io_addr); + iow(db, DM9000_EPCR, 0x0); /* Clear phyxcer read command */ /* The read data keeps on REG_0D & REG_0E */ @@ -1099,9 +1279,9 @@ dm9000_phy_read(struct net_device *dev, int phy_reg_unused, int reg) /* restore the previous address */ writeb(reg_save, db->io_addr); - spin_unlock_irqrestore(&db->lock,flags); + mutex_unlock(&db->addr_lock); return ret; } @@ -1115,6 +1295,8 @@ dm9000_phy_write(struct net_device *dev, int phyaddr_unused, int reg, int value) unsigned long flags; unsigned long reg_save; + mutex_lock(&db->addr_lock); + spin_lock_irqsave(&db->lock,flags); /* Save previous register address */ @@ -1124,25 +1306,38 @@ dm9000_phy_write(struct net_device *dev, int phyaddr_unused, int reg, int value) iow(db, DM9000_EPAR, DM9000_PHY | reg); /* Fill the written data into REG_0D & REG_0E */ - iow(db, DM9000_EPDRL, (value & 0xff)); - iow(db, DM9000_EPDRH, ((value >> 8) & 0xff)); + iow(db, DM9000_EPDRL, value); + iow(db, DM9000_EPDRH, value >> 8); iow(db, DM9000_EPCR, 0xa); /* Issue phyxcer write command */ - udelay(500); /* Wait write complete */ + + writeb(reg_save, db->io_addr); + spin_unlock_irqrestore(&db->lock, flags); + + dm9000_msleep(db, 1); /* Wait write complete */ + + spin_lock_irqsave(&db->lock,flags); + reg_save = readb(db->io_addr); + iow(db, DM9000_EPCR, 0x0); /* Clear phyxcer write command */ /* restore the previous address */ writeb(reg_save, db->io_addr); - spin_unlock_irqrestore(&db->lock,flags); + spin_unlock_irqrestore(&db->lock, flags); + mutex_unlock(&db->addr_lock); } static int dm9000_drv_suspend(struct platform_device *dev, pm_message_t state) { struct net_device *ndev = platform_get_drvdata(dev); + board_info_t *db; if (ndev) { + db = (board_info_t *) ndev->priv; + db->in_suspend = 1; + if (netif_running(ndev)) { netif_device_detach(ndev); dm9000_shutdown(ndev); @@ -1165,6 +1360,8 @@ dm9000_drv_resume(struct platform_device *dev) netif_device_attach(ndev); } + + db->in_suspend = 0; } return 0; } @@ -1180,8 +1377,7 @@ dm9000_drv_remove(struct platform_device *pdev) dm9000_release_board(pdev, (board_info_t *) ndev->priv); free_netdev(ndev); /* free device structure */ - PRINTK1("clean_module() exit\n"); - + dev_dbg(&pdev->dev, "released and freed device\n"); return 0; } @@ -1199,7 +1395,7 @@ static struct platform_driver dm9000_driver = { static int __init dm9000_init(void) { - printk(KERN_INFO "%s Ethernet Driver\n", CARDNAME); + printk(KERN_INFO "%s Ethernet Driver, V%s\n", CARDNAME, DRV_VERSION); return platform_driver_register(&dm9000_driver); /* search board and register */ } diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c index d876787ce336..85e66f4c7886 100644 --- a/drivers/net/e1000/e1000_ethtool.c +++ b/drivers/net/e1000/e1000_ethtool.c @@ -50,7 +50,7 @@ struct e1000_stats { int stat_offset; }; -#define E1000_STAT(m) sizeof(((struct e1000_adapter *)0)->m), \ +#define E1000_STAT(m) FIELD_SIZEOF(struct e1000_adapter, m), \ offsetof(struct e1000_adapter, m) static const struct e1000_stats e1000_gstrings_stats[] = { { "rx_packets", E1000_STAT(stats.gprc) }, diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 7c5b05a82f0e..0991648c53dc 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -926,8 +926,6 @@ e1000_probe(struct pci_dev *pdev, { struct net_device *netdev; struct e1000_adapter *adapter; - unsigned long mmio_start, mmio_len; - unsigned long flash_start, flash_len; static int cards_found = 0; static int global_quad_port_a = 0; /* global ksp3 port a indication */ @@ -970,11 +968,9 @@ e1000_probe(struct pci_dev *pdev, adapter->hw.back = adapter; adapter->msg_enable = (1 << debug) - 1; - mmio_start = pci_resource_start(pdev, BAR_0); - mmio_len = pci_resource_len(pdev, BAR_0); - err = -EIO; - adapter->hw.hw_addr = ioremap(mmio_start, mmio_len); + adapter->hw.hw_addr = ioremap(pci_resource_start(pdev, BAR_0), + pci_resource_len(pdev, BAR_0)); if (!adapter->hw.hw_addr) goto err_ioremap; @@ -1009,10 +1005,6 @@ e1000_probe(struct pci_dev *pdev, #endif strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1); - netdev->mem_start = mmio_start; - netdev->mem_end = mmio_start + mmio_len; - netdev->base_addr = adapter->hw.io_base; - adapter->bd_number = cards_found; /* setup the private structure */ @@ -1025,9 +1017,9 @@ e1000_probe(struct pci_dev *pdev, * because it depends on mac_type */ if ((adapter->hw.mac_type == e1000_ich8lan) && (pci_resource_flags(pdev, 1) & IORESOURCE_MEM)) { - flash_start = pci_resource_start(pdev, 1); - flash_len = pci_resource_len(pdev, 1); - adapter->hw.flash_address = ioremap(flash_start, flash_len); + adapter->hw.flash_address = + ioremap(pci_resource_start(pdev, 1), + pci_resource_len(pdev, 1)); if (!adapter->hw.flash_address) goto err_flashmap; } @@ -1203,6 +1195,14 @@ e1000_probe(struct pci_dev *pdev, printk("%s\n", print_mac(mac, netdev->dev_addr)); + if (adapter->hw.bus_type == e1000_bus_type_pci_express) { + DPRINTK(PROBE, WARNING, "This device (id %04x:%04x) will no " + "longer be supported by this driver in the future.\n", + pdev->vendor, pdev->device); + DPRINTK(PROBE, WARNING, "please use the \"e1000e\" " + "driver instead.\n"); + } + /* reset the hardware with the new settings */ e1000_reset(adapter); diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index f58f017ee47a..3031d6d16247 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -1055,23 +1055,6 @@ static void e1000_release_hw_control(struct e1000_adapter *adapter) } } -static void e1000_release_manageability(struct e1000_adapter *adapter) -{ - if (adapter->flags & FLAG_MNG_PT_ENABLED) { - struct e1000_hw *hw = &adapter->hw; - - u32 manc = er32(MANC); - - /* re-enable hardware interception of ARP */ - manc |= E1000_MANC_ARP_EN; - manc &= ~E1000_MANC_EN_MNG2HOST; - - /* don't explicitly have to mess with MANC2H since - * MANC has an enable disable that gates MANC2H */ - ew32(MANC, manc); - } -} - /** * @e1000_alloc_ring - allocate memory for a ring structure **/ @@ -1561,9 +1544,6 @@ static void e1000_init_manageability(struct e1000_adapter *adapter) manc = er32(MANC); - /* disable hardware interception of ARP */ - manc &= ~(E1000_MANC_ARP_EN); - /* enable receiving management packets to the host. this will probably * generate destination unreachable messages from the host OS, but * the packets will be handled on SMBUS */ @@ -1690,6 +1670,9 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter) else rctl |= E1000_RCTL_LPE; + /* Enable hardware CRC frame stripping */ + rctl |= E1000_RCTL_SECRC; + /* Setup buffer sizes */ rctl &= ~E1000_RCTL_SZ_4096; rctl |= E1000_RCTL_BSEX; @@ -1755,9 +1738,6 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter) /* Enable Packet split descriptors */ rctl |= E1000_RCTL_DTYP_PS; - - /* Enable hardware CRC frame stripping */ - rctl |= E1000_RCTL_SECRC; psrctl |= adapter->rx_ps_bsize0 >> E1000_PSRCTL_BSIZE0_SHIFT; @@ -2008,7 +1988,7 @@ static void e1000_power_down_phy(struct e1000_adapter *adapter) u16 mii_reg; /* WoL is enabled */ - if (!adapter->wol) + if (adapter->wol) return; /* non-copper PHY? */ @@ -2140,8 +2120,6 @@ void e1000e_reset(struct e1000_adapter *adapter) phy_data &= ~IGP02E1000_PM_SPD; e1e_wphy(hw, IGP02E1000_PHY_POWER_MGMT, phy_data); } - - e1000_release_manageability(adapter); } int e1000e_up(struct e1000_adapter *adapter) @@ -3487,8 +3465,6 @@ static int e1000_suspend(struct pci_dev *pdev, pm_message_t state) pci_enable_wake(pdev, PCI_D3cold, 0); } - e1000_release_manageability(adapter); - /* make sure adapter isn't asleep if manageability is enabled */ if (adapter->flags & FLAG_MNG_PT_ENABLED) { pci_enable_wake(pdev, PCI_D3hot, 1); @@ -4054,8 +4030,6 @@ static void __devexit e1000_remove(struct pci_dev *pdev) flush_scheduled_work(); - e1000_release_manageability(adapter); - /* Release control of h/w to f/w. If f/w is AMT enabled, this * would have already happened in close and is redundant. */ e1000_release_hw_control(adapter); diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index d4843d014bc9..801b4d9cd972 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -166,21 +166,24 @@ * Hardware access: */ -#define DEV_NEED_TIMERIRQ 0x0001 /* set the timer irq flag in the irq mask */ -#define DEV_NEED_LINKTIMER 0x0002 /* poll link settings. Relies on the timer irq */ -#define DEV_HAS_LARGEDESC 0x0004 /* device supports jumbo frames and needs packet format 2 */ -#define DEV_HAS_HIGH_DMA 0x0008 /* device supports 64bit dma */ -#define DEV_HAS_CHECKSUM 0x0010 /* device supports tx and rx checksum offloads */ -#define DEV_HAS_VLAN 0x0020 /* device supports vlan tagging and striping */ -#define DEV_HAS_MSI 0x0040 /* device supports MSI */ -#define DEV_HAS_MSI_X 0x0080 /* device supports MSI-X */ -#define DEV_HAS_POWER_CNTRL 0x0100 /* device supports power savings */ -#define DEV_HAS_PAUSEFRAME_TX 0x0200 /* device supports tx pause frames */ -#define DEV_HAS_STATISTICS_V1 0x0400 /* device supports hw statistics version 1 */ -#define DEV_HAS_STATISTICS_V2 0x0800 /* device supports hw statistics version 2 */ -#define DEV_HAS_TEST_EXTENDED 0x1000 /* device supports extended diagnostic test */ -#define DEV_HAS_MGMT_UNIT 0x2000 /* device supports management unit */ -#define DEV_HAS_CORRECT_MACADDR 0x4000 /* device supports correct mac address order */ +#define DEV_NEED_TIMERIRQ 0x00001 /* set the timer irq flag in the irq mask */ +#define DEV_NEED_LINKTIMER 0x00002 /* poll link settings. Relies on the timer irq */ +#define DEV_HAS_LARGEDESC 0x00004 /* device supports jumbo frames and needs packet format 2 */ +#define DEV_HAS_HIGH_DMA 0x00008 /* device supports 64bit dma */ +#define DEV_HAS_CHECKSUM 0x00010 /* device supports tx and rx checksum offloads */ +#define DEV_HAS_VLAN 0x00020 /* device supports vlan tagging and striping */ +#define DEV_HAS_MSI 0x00040 /* device supports MSI */ +#define DEV_HAS_MSI_X 0x00080 /* device supports MSI-X */ +#define DEV_HAS_POWER_CNTRL 0x00100 /* device supports power savings */ +#define DEV_HAS_STATISTICS_V1 0x00200 /* device supports hw statistics version 1 */ +#define DEV_HAS_STATISTICS_V2 0x00400 /* device supports hw statistics version 2 */ +#define DEV_HAS_TEST_EXTENDED 0x00800 /* device supports extended diagnostic test */ +#define DEV_HAS_MGMT_UNIT 0x01000 /* device supports management unit */ +#define DEV_HAS_CORRECT_MACADDR 0x02000 /* device supports correct mac address order */ +#define DEV_HAS_COLLISION_FIX 0x04000 /* device supports tx collision fix */ +#define DEV_HAS_PAUSEFRAME_TX_V1 0x08000 /* device supports tx pause frames version 1 */ +#define DEV_HAS_PAUSEFRAME_TX_V2 0x10000 /* device supports tx pause frames version 2 */ +#define DEV_HAS_PAUSEFRAME_TX_V3 0x20000 /* device supports tx pause frames version 3 */ enum { NvRegIrqStatus = 0x000, @@ -266,9 +269,12 @@ enum { #define NVREG_RNDSEED_FORCE3 0x7400 NvRegTxDeferral = 0xA0, -#define NVREG_TX_DEFERRAL_DEFAULT 0x15050f -#define NVREG_TX_DEFERRAL_RGMII_10_100 0x16070f -#define NVREG_TX_DEFERRAL_RGMII_1000 0x14050f +#define NVREG_TX_DEFERRAL_DEFAULT 0x15050f +#define NVREG_TX_DEFERRAL_RGMII_10_100 0x16070f +#define NVREG_TX_DEFERRAL_RGMII_1000 0x14050f +#define NVREG_TX_DEFERRAL_RGMII_STRETCH_10 0x16190f +#define NVREG_TX_DEFERRAL_RGMII_STRETCH_100 0x16300f +#define NVREG_TX_DEFERRAL_MII_STRETCH 0x152000 NvRegRxDeferral = 0xA4, #define NVREG_RX_DEFERRAL_DEFAULT 0x16 NvRegMacAddrA = 0xA8, @@ -318,8 +324,10 @@ enum { NvRegTxRingPhysAddrHigh = 0x148, NvRegRxRingPhysAddrHigh = 0x14C, NvRegTxPauseFrame = 0x170, -#define NVREG_TX_PAUSEFRAME_DISABLE 0x01ff0080 -#define NVREG_TX_PAUSEFRAME_ENABLE 0x01800010 +#define NVREG_TX_PAUSEFRAME_DISABLE 0x0fff0080 +#define NVREG_TX_PAUSEFRAME_ENABLE_V1 0x01800010 +#define NVREG_TX_PAUSEFRAME_ENABLE_V2 0x056003f0 +#define NVREG_TX_PAUSEFRAME_ENABLE_V3 0x09f00880 NvRegMIIStatus = 0x180, #define NVREG_MIISTAT_ERROR 0x0001 #define NVREG_MIISTAT_LINKCHANGE 0x0008 @@ -2751,7 +2759,12 @@ static void nv_update_pause(struct net_device *dev, u32 pause_flags) if (np->pause_flags & NV_PAUSEFRAME_TX_CAPABLE) { u32 regmisc = readl(base + NvRegMisc1) & ~NVREG_MISC1_PAUSE_TX; if (pause_flags & NV_PAUSEFRAME_TX_ENABLE) { - writel(NVREG_TX_PAUSEFRAME_ENABLE, base + NvRegTxPauseFrame); + u32 pause_enable = NVREG_TX_PAUSEFRAME_ENABLE_V1; + if (np->driver_data & DEV_HAS_PAUSEFRAME_TX_V2) + pause_enable = NVREG_TX_PAUSEFRAME_ENABLE_V2; + if (np->driver_data & DEV_HAS_PAUSEFRAME_TX_V3) + pause_enable = NVREG_TX_PAUSEFRAME_ENABLE_V3; + writel(pause_enable, base + NvRegTxPauseFrame); writel(regmisc|NVREG_MISC1_PAUSE_TX, base + NvRegMisc1); np->pause_flags |= NV_PAUSEFRAME_TX_ENABLE; } else { @@ -2785,6 +2798,7 @@ static int nv_update_linkspeed(struct net_device *dev) int retval = 0; u32 control_1000, status_1000, phyreg, pause_flags, txreg; u32 txrxFlags = 0; + u32 phy_exp; /* BMSR_LSTATUS is latched, read it twice: * we want the current value. @@ -2912,13 +2926,25 @@ set_speed: phyreg |= PHY_1000; writel(phyreg, base + NvRegPhyInterface); + phy_exp = mii_rw(dev, np->phyaddr, MII_EXPANSION, MII_READ) & EXPANSION_NWAY; /* autoneg capable */ if (phyreg & PHY_RGMII) { - if ((np->linkspeed & NVREG_LINKSPEED_MASK) == NVREG_LINKSPEED_1000) + if ((np->linkspeed & NVREG_LINKSPEED_MASK) == NVREG_LINKSPEED_1000) { txreg = NVREG_TX_DEFERRAL_RGMII_1000; - else - txreg = NVREG_TX_DEFERRAL_RGMII_10_100; + } else { + if (!phy_exp && !np->duplex && (np->driver_data & DEV_HAS_COLLISION_FIX)) { + if ((np->linkspeed & NVREG_LINKSPEED_MASK) == NVREG_LINKSPEED_10) + txreg = NVREG_TX_DEFERRAL_RGMII_STRETCH_10; + else + txreg = NVREG_TX_DEFERRAL_RGMII_STRETCH_100; + } else { + txreg = NVREG_TX_DEFERRAL_RGMII_10_100; + } + } } else { - txreg = NVREG_TX_DEFERRAL_DEFAULT; + if (!phy_exp && !np->duplex && (np->driver_data & DEV_HAS_COLLISION_FIX)) + txreg = NVREG_TX_DEFERRAL_MII_STRETCH; + else + txreg = NVREG_TX_DEFERRAL_DEFAULT; } writel(txreg, base + NvRegTxDeferral); @@ -5155,7 +5181,9 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i } np->pause_flags = NV_PAUSEFRAME_RX_CAPABLE | NV_PAUSEFRAME_RX_REQ | NV_PAUSEFRAME_AUTONEG; - if (id->driver_data & DEV_HAS_PAUSEFRAME_TX) { + if ((id->driver_data & DEV_HAS_PAUSEFRAME_TX_V1) || + (id->driver_data & DEV_HAS_PAUSEFRAME_TX_V2) || + (id->driver_data & DEV_HAS_PAUSEFRAME_TX_V3)) { np->pause_flags |= NV_PAUSEFRAME_TX_CAPABLE | NV_PAUSEFRAME_TX_REQ; } @@ -5559,107 +5587,107 @@ static struct pci_device_id pci_tbl[] = { }, { /* MCP55 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_14), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, }, { /* MCP55 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_15), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, }, { /* MCP61 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_16), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, }, { /* MCP61 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_17), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, }, { /* MCP61 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_18), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, }, { /* MCP61 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_19), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, }, { /* MCP65 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_20), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, }, { /* MCP65 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_21), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, }, { /* MCP65 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_22), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, }, { /* MCP65 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_23), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, }, { /* MCP67 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_24), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, }, { /* MCP67 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_25), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, }, { /* MCP67 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_26), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, }, { /* MCP67 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_27), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, }, { /* MCP73 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_28), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX, }, { /* MCP73 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_29), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX, }, { /* MCP73 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_30), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX, }, { /* MCP73 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_31), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX, }, { /* MCP77 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_32), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX, }, { /* MCP77 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_33), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX, }, { /* MCP77 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_34), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX, }, { /* MCP77 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_35), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX, }, { /* MCP79 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_36), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX, }, { /* MCP79 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_37), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX, }, { /* MCP79 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_38), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX, }, { /* MCP79 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_39), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX, }, {0,}, }; diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 0431e9ed0fac..4244fc282f21 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -130,8 +130,8 @@ static void free_skb_resources(struct gfar_private *priv); static void gfar_set_multi(struct net_device *dev); static void gfar_set_hash_for_addr(struct net_device *dev, u8 *addr); static void gfar_configure_serdes(struct net_device *dev); -extern int gfar_local_mdio_write(struct gfar_mii *regs, int mii_id, int regnum, u16 value); -extern int gfar_local_mdio_read(struct gfar_mii *regs, int mii_id, int regnum); +extern int gfar_local_mdio_write(struct gfar_mii __iomem *regs, int mii_id, int regnum, u16 value); +extern int gfar_local_mdio_read(struct gfar_mii __iomem *regs, int mii_id, int regnum); #ifdef CONFIG_GFAR_NAPI static int gfar_poll(struct napi_struct *napi, int budget); #endif diff --git a/drivers/net/gianfar_mii.c b/drivers/net/gianfar_mii.c index 6a647d95e6ea..24327629bf03 100644 --- a/drivers/net/gianfar_mii.c +++ b/drivers/net/gianfar_mii.c @@ -51,7 +51,7 @@ * the local mdio pins, which may not be the same as system mdio bus, used for * controlling the external PHYs, for example. */ -int gfar_local_mdio_write(struct gfar_mii *regs, int mii_id, +int gfar_local_mdio_write(struct gfar_mii __iomem *regs, int mii_id, int regnum, u16 value) { /* Set the PHY address and the register address we want to write */ @@ -77,7 +77,7 @@ int gfar_local_mdio_write(struct gfar_mii *regs, int mii_id, * and are always tied to the local mdio pins, which may not be the * same as system mdio bus, used for controlling the external PHYs, for eg. */ -int gfar_local_mdio_read(struct gfar_mii *regs, int mii_id, int regnum) +int gfar_local_mdio_read(struct gfar_mii __iomem *regs, int mii_id, int regnum) { u16 value; diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c index cfcd15af501e..30c9b3b0d131 100644 --- a/drivers/net/hamradio/mkiss.c +++ b/drivers/net/hamradio/mkiss.c @@ -289,7 +289,6 @@ static void ax_bump(struct mkiss *ax) *ax->rbuff &= ~0x20; } } - spin_unlock_bh(&ax->buflock); count = ax->rcount; @@ -297,17 +296,17 @@ static void ax_bump(struct mkiss *ax) printk(KERN_ERR "mkiss: %s: memory squeeze, dropping packet.\n", ax->dev->name); ax->stats.rx_dropped++; + spin_unlock_bh(&ax->buflock); return; } - spin_lock_bh(&ax->buflock); memcpy(skb_put(skb,count), ax->rbuff, count); - spin_unlock_bh(&ax->buflock); skb->protocol = ax25_type_trans(skb, ax->dev); netif_rx(skb); ax->dev->last_rx = jiffies; ax->stats.rx_packets++; ax->stats.rx_bytes += count; + spin_unlock_bh(&ax->buflock); } static void kiss_unesc(struct mkiss *ax, unsigned char s) diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c index f69721e4eaa1..0447f9bcd27a 100644 --- a/drivers/net/igb/igb_ethtool.c +++ b/drivers/net/igb/igb_ethtool.c @@ -43,7 +43,7 @@ struct igb_stats { int stat_offset; }; -#define IGB_STAT(m) sizeof(((struct igb_adapter *)0)->m), \ +#define IGB_STAT(m) FIELD_SIZEOF(struct igb_adapter, m), \ offsetof(struct igb_adapter, m) static const struct igb_stats igb_gstrings_stats[] = { { "rx_packets", IGB_STAT(stats.gprc) }, diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index d4eb8e2d8720..bff280eff5e3 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -606,9 +606,6 @@ static void igb_init_manageability(struct igb_adapter *adapter) u32 manc2h = rd32(E1000_MANC2H); u32 manc = rd32(E1000_MANC); - /* disable hardware interception of ARP */ - manc &= ~(E1000_MANC_ARP_EN); - /* enable receiving management packets to the host */ /* this will probably generate destination unreachable messages * from the host OS, but the packets will be handled on SMBUS */ @@ -623,25 +620,6 @@ static void igb_init_manageability(struct igb_adapter *adapter) } } -static void igb_release_manageability(struct igb_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - - if (adapter->en_mng_pt) { - u32 manc = rd32(E1000_MANC); - - /* re-enable hardware interception of ARP */ - manc |= E1000_MANC_ARP_EN; - manc &= ~E1000_MANC_EN_MNG2HOST; - - /* don't explicitly have to mess with MANC2H since - * MANC has an enable disable that gates MANC2H */ - - /* XXX stop the hardware watchdog ? */ - wr32(E1000_MANC, manc); - } -} - /** * igb_configure - configure the hardware for RX and TX * @adapter: private board structure @@ -844,7 +822,6 @@ void igb_reset(struct igb_adapter *adapter) igb_reset_adaptive(&adapter->hw); adapter->hw.phy.ops.get_phy_info(&adapter->hw); - igb_release_manageability(adapter); } /** @@ -1178,9 +1155,6 @@ static void __devexit igb_remove(struct pci_dev *pdev) flush_scheduled_work(); - - igb_release_manageability(adapter); - /* Release control of h/w to f/w. If f/w is AMT enabled, this * would have already happened in close and is redundant. */ igb_release_hw_control(adapter); @@ -3955,8 +3929,6 @@ static int igb_suspend(struct pci_dev *pdev, pm_message_t state) pci_enable_wake(pdev, PCI_D3cold, 0); } - igb_release_manageability(adapter); - /* make sure adapter isn't asleep if manageability is enabled */ if (adapter->en_mng_pt) { pci_enable_wake(pdev, PCI_D3hot, 1); diff --git a/drivers/net/ixgb/ixgb_ethtool.c b/drivers/net/ixgb/ixgb_ethtool.c index a267dd862520..53a9fd086f96 100644 --- a/drivers/net/ixgb/ixgb_ethtool.c +++ b/drivers/net/ixgb/ixgb_ethtool.c @@ -49,7 +49,7 @@ struct ixgb_stats { int stat_offset; }; -#define IXGB_STAT(m) sizeof(((struct ixgb_adapter *)0)->m), \ +#define IXGB_STAT(m) FIELD_SIZEOF(struct ixgb_adapter, m), \ offsetof(struct ixgb_adapter, m) static struct ixgb_stats ixgb_gstrings_stats[] = { {"rx_packets", IXGB_STAT(net_stats.rx_packets)}, diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index ead49e54f31b..23d0a4afe0e1 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -220,7 +220,6 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_adapter *adapter, tx_ring->stats.bytes += tx_buffer_info->length; if (cleaned) { struct sk_buff *skb = tx_buffer_info->skb; -#ifdef NETIF_F_TSO unsigned int segs, bytecount; segs = skb_shinfo(skb)->gso_segs ?: 1; /* multiply data chunks by size of headers */ @@ -228,10 +227,6 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_adapter *adapter, skb->len; total_tx_packets += segs; total_tx_bytes += bytecount; -#else - total_tx_packets++; - total_tx_bytes += skb->len; -#endif } ixgbe_unmap_and_free_tx_resource(adapter, tx_buffer_info); @@ -1942,6 +1937,10 @@ static int ixgbe_open(struct net_device *netdev) int err; u32 num_rx_queues = adapter->num_rx_queues; + /* disallow open during test */ + if (test_bit(__IXGBE_TESTING, &adapter->state)) + return -EBUSY; + try_intr_reinit: /* allocate transmit descriptors */ err = ixgbe_setup_all_tx_resources(adapter); @@ -2278,11 +2277,29 @@ static bool ixgbe_tx_csum(struct ixgbe_adapter *adapter, IXGBE_ADVTXD_DTYP_CTXT); if (skb->ip_summed == CHECKSUM_PARTIAL) { - if (skb->protocol == htons(ETH_P_IP)) + switch (skb->protocol) { + case __constant_htons(ETH_P_IP): type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_IPV4; + if (ip_hdr(skb)->protocol == IPPROTO_TCP) + type_tucmd_mlhl |= + IXGBE_ADVTXD_TUCMD_L4T_TCP; + break; - if (skb->sk->sk_protocol == IPPROTO_TCP) - type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_L4T_TCP; + case __constant_htons(ETH_P_IPV6): + /* XXX what about other V6 headers?? */ + if (ipv6_hdr(skb)->nexthdr == IPPROTO_TCP) + type_tucmd_mlhl |= + IXGBE_ADVTXD_TUCMD_L4T_TCP; + break; + + default: + if (unlikely(net_ratelimit())) { + DPRINTK(PROBE, WARNING, + "partial checksum but proto=%x!\n", + skb->protocol); + } + break; + } } context_desc->type_tucmd_mlhl = cpu_to_le32(type_tucmd_mlhl); @@ -2778,6 +2795,14 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, hw->mac.type, hw->phy.type, (part_num >> 8), (part_num & 0xff)); + if (link_width <= IXGBE_PCI_LINK_WIDTH_4) { + dev_warn(&pdev->dev, "PCI-Express bandwidth available for " + "this card is not sufficient for optimal " + "performance.\n"); + dev_warn(&pdev->dev, "For optimal performance a x8 " + "PCI-Express slot is required.\n"); + } + /* reset the hardware with the new settings */ ixgbe_start_hw(hw); diff --git a/drivers/net/mlx4/mr.c b/drivers/net/mlx4/mr.c index 679dfdb6807f..79b317b88c86 100644 --- a/drivers/net/mlx4/mr.c +++ b/drivers/net/mlx4/mr.c @@ -578,13 +578,6 @@ int mlx4_fmr_alloc(struct mlx4_dev *dev, u32 pd, u32 access, int max_pages, goto err_free; } - fmr->mpt = mlx4_table_find(&priv->mr_table.dmpt_table, - key_to_hw_index(fmr->mr.key), NULL); - if (!fmr->mpt) { - err = -ENOMEM; - goto err_free; - } - return 0; err_free: @@ -595,7 +588,19 @@ EXPORT_SYMBOL_GPL(mlx4_fmr_alloc); int mlx4_fmr_enable(struct mlx4_dev *dev, struct mlx4_fmr *fmr) { - return mlx4_mr_enable(dev, &fmr->mr); + struct mlx4_priv *priv = mlx4_priv(dev); + int err; + + err = mlx4_mr_enable(dev, &fmr->mr); + if (err) + return err; + + fmr->mpt = mlx4_table_find(&priv->mr_table.dmpt_table, + key_to_hw_index(fmr->mr.key), NULL); + if (!fmr->mpt) + return -ENOMEM; + + return 0; } EXPORT_SYMBOL_GPL(mlx4_fmr_enable); diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c index 31e047dd7bb3..501e451be911 100644 --- a/drivers/net/netconsole.c +++ b/drivers/net/netconsole.c @@ -309,8 +309,8 @@ static ssize_t show_local_mac(struct netconsole_target *nt, char *buf) struct net_device *dev = nt->np.dev; DECLARE_MAC_BUF(mac); - return snprintf(buf, PAGE_SIZE, "%s\n", - print_mac(mac, dev->dev_addr)); + return snprintf(buf, PAGE_SIZE, "%s\n", dev ? + print_mac(mac, dev->dev_addr) : "ff:ff:ff:ff:ff:ff"); } static ssize_t show_remote_mac(struct netconsole_target *nt, char *buf) diff --git a/drivers/net/ni52.c b/drivers/net/ni52.c index 6b3384a24f07..26aa8fe1fb2d 100644 --- a/drivers/net/ni52.c +++ b/drivers/net/ni52.c @@ -33,20 +33,20 @@ * I have also done a look in the following sources: (mail me if you need them) * crynwr-packet-driver by Russ Nelson * Garret A. Wollman's (fourth) i82586-driver for BSD - * (before getting an i82596 (yes 596 not 586) manual, the existing drivers helped - * me a lot to understand this tricky chip.) + * (before getting an i82596 (yes 596 not 586) manual, the existing drivers + * helped me a lot to understand this tricky chip.) * * Known Problems: * The internal sysbus seems to be slow. So we often lose packets because of * overruns while receiving from a fast remote host. - * This can slow down TCP connections. Maybe the newer ni5210 cards are better. - * my experience is, that if a machine sends with more than about 500-600K/s - * the fifo/sysbus overflows. + * This can slow down TCP connections. Maybe the newer ni5210 cards are + * better. My experience is, that if a machine sends with more than about + * 500-600K/s the fifo/sysbus overflows. * * IMPORTANT NOTE: * On fast networks, it's a (very) good idea to have 16K shared memory. With - * 8K, we can store only 4 receive frames, so it can (easily) happen that a remote - * machine 'overruns' our system. + * 8K, we can store only 4 receive frames, so it can (easily) happen that a + * remote machine 'overruns' our system. * * Known i82586/card problems (I'm sure, there are many more!): * Running the NOP-mode, the i82586 sometimes seems to forget to report @@ -60,7 +60,8 @@ * * results from ftp performance tests with Linux 1.2.5 * send and receive about 350-400 KByte/s (peak up to 460 kbytes/s) - * sending in NOP-mode: peak performance up to 530K/s (but better don't run this mode) + * sending in NOP-mode: peak performance up to 530K/s (but better don't + * run this mode) */ /* @@ -94,7 +95,8 @@ * * 26.March.94: patches for Linux 1.0 and iomem-auto-probe (MH) * - * 30.Sep.93: Added nop-chain .. driver now runs with only one Xmit-Buff, too (MH) + * 30.Sep.93: Added nop-chain .. driver now runs with only one Xmit-Buff, + * too (MH) * * < 30.Sep.93: first versions */ @@ -102,7 +104,7 @@ static int debuglevel; /* debug-printk 0: off 1: a few 2: more */ static int automatic_resume; /* experimental .. better should be zero */ static int rfdadd; /* rfdadd=1 may be better for 8K MEM cards */ -static int fifo=0x8; /* don't change */ +static int fifo = 0x8; /* don't change */ #include #include @@ -127,14 +129,15 @@ static int fifo=0x8; /* don't change */ #define DEBUG /* debug on */ #define SYSBUSVAL 1 /* 8 Bit */ -#define ni_attn586() {outb(0,dev->base_addr+NI52_ATTENTION);} -#define ni_reset586() {outb(0,dev->base_addr+NI52_RESET);} -#define ni_disint() {outb(0,dev->base_addr+NI52_INTDIS);} -#define ni_enaint() {outb(0,dev->base_addr+NI52_INTENA);} +#define ni_attn586() { outb(0, dev->base_addr + NI52_ATTENTION); } +#define ni_reset586() { outb(0, dev->base_addr + NI52_RESET); } +#define ni_disint() { outb(0, dev->base_addr + NI52_INTDIS); } +#define ni_enaint() { outb(0, dev->base_addr + NI52_INTENA); } -#define make32(ptr16) (p->memtop + (short) (ptr16) ) -#define make24(ptr32) ( ((char *) (ptr32)) - p->base) -#define make16(ptr32) ((unsigned short) ((unsigned long)(ptr32) - (unsigned long) p->memtop )) +#define make32(ptr16) (p->memtop + (short) (ptr16)) +#define make24(ptr32) ((unsigned long)(ptr32)) - p->base +#define make16(ptr32) ((unsigned short) ((unsigned long)(ptr32)\ + - (unsigned long) p->memtop)) /******************* how to calculate the buffers ***************************** @@ -159,96 +162,112 @@ sizeof(nop_cmd) = 8; /**************************************************************************/ -/* different DELAYs */ -#define DELAY(x) mdelay(32 * x); -#define DELAY_16(); { udelay(16); } -#define DELAY_18(); { udelay(4); } - -/* wait for command with timeout: */ -#define WAIT_4_SCB_CMD() \ -{ int i; \ - for(i=0;i<16384;i++) { \ - if(!p->scb->cmd_cuc) break; \ - DELAY_18(); \ - if(i == 16383) { \ - printk("%s: scb_cmd timed out: %04x,%04x .. disabling i82586!!\n",dev->name,p->scb->cmd_cuc,p->scb->cus); \ - if(!p->reseted) { p->reseted = 1; ni_reset586(); } } } } - -#define WAIT_4_SCB_CMD_RUC() { int i; \ - for(i=0;i<16384;i++) { \ - if(!p->scb->cmd_ruc) break; \ - DELAY_18(); \ - if(i == 16383) { \ - printk("%s: scb_cmd (ruc) timed out: %04x,%04x .. disabling i82586!!\n",dev->name,p->scb->cmd_ruc,p->scb->rus); \ - if(!p->reseted) { p->reseted = 1; ni_reset586(); } } } } - -#define WAIT_4_STAT_COMPL(addr) { int i; \ - for(i=0;i<32767;i++) { \ - if((addr)->cmd_status & STAT_COMPL) break; \ - DELAY_16(); DELAY_16(); } } #define NI52_TOTAL_SIZE 16 #define NI52_ADDR0 0x02 #define NI52_ADDR1 0x07 #define NI52_ADDR2 0x01 -static int ni52_probe1(struct net_device *dev,int ioaddr); -static irqreturn_t ni52_interrupt(int irq,void *dev_id); +static int ni52_probe1(struct net_device *dev, int ioaddr); +static irqreturn_t ni52_interrupt(int irq, void *dev_id); static int ni52_open(struct net_device *dev); static int ni52_close(struct net_device *dev); -static int ni52_send_packet(struct sk_buff *,struct net_device *); +static int ni52_send_packet(struct sk_buff *, struct net_device *); static struct net_device_stats *ni52_get_stats(struct net_device *dev); static void set_multicast_list(struct net_device *dev); static void ni52_timeout(struct net_device *dev); -#if 0 -static void ni52_dump(struct net_device *,void *); -#endif /* helper-functions */ static int init586(struct net_device *dev); -static int check586(struct net_device *dev,char *where,unsigned size); +static int check586(struct net_device *dev, char *where, unsigned size); static void alloc586(struct net_device *dev); static void startrecv586(struct net_device *dev); -static void *alloc_rfa(struct net_device *dev,void *ptr); +static void *alloc_rfa(struct net_device *dev, void *ptr); static void ni52_rcv_int(struct net_device *dev); static void ni52_xmt_int(struct net_device *dev); static void ni52_rnr_int(struct net_device *dev); -struct priv -{ +struct priv { struct net_device_stats stats; unsigned long base; char *memtop; - long int lock; - int reseted; - volatile struct rfd_struct *rfd_last,*rfd_top,*rfd_first; - volatile struct scp_struct *scp; /* volatile is important */ - volatile struct iscp_struct *iscp; /* volatile is important */ - volatile struct scb_struct *scb; /* volatile is important */ - volatile struct tbd_struct *xmit_buffs[NUM_XMIT_BUFFS]; + spinlock_t spinlock; + int reset; + struct rfd_struct *rfd_last, *rfd_top, *rfd_first; + struct scp_struct *scp; + struct iscp_struct *iscp; + struct scb_struct *scb; + struct tbd_struct *xmit_buffs[NUM_XMIT_BUFFS]; #if (NUM_XMIT_BUFFS == 1) - volatile struct transmit_cmd_struct *xmit_cmds[2]; - volatile struct nop_cmd_struct *nop_cmds[2]; + struct transmit_cmd_struct *xmit_cmds[2]; + struct nop_cmd_struct *nop_cmds[2]; #else - volatile struct transmit_cmd_struct *xmit_cmds[NUM_XMIT_BUFFS]; - volatile struct nop_cmd_struct *nop_cmds[NUM_XMIT_BUFFS]; + struct transmit_cmd_struct *xmit_cmds[NUM_XMIT_BUFFS]; + struct nop_cmd_struct *nop_cmds[NUM_XMIT_BUFFS]; #endif - volatile int nop_point,num_recv_buffs; - volatile char *xmit_cbuffs[NUM_XMIT_BUFFS]; - volatile int xmit_count,xmit_last; + int nop_point, num_recv_buffs; + char *xmit_cbuffs[NUM_XMIT_BUFFS]; + int xmit_count, xmit_last; }; +/* wait for command with timeout: */ +static void wait_for_scb_cmd(struct net_device *dev) +{ + struct priv *p = dev->priv; + int i; + for (i = 0; i < 16384; i++) { + if (readb(&p->scb->cmd_cuc) == 0) + break; + udelay(4); + if (i == 16383) { + printk(KERN_ERR "%s: scb_cmd timed out: %04x,%04x .. disabling i82586!!\n", + dev->name, readb(&p->scb->cmd_cuc), readb(&p->scb->cus)); + if (!p->reset) { + p->reset = 1; + ni_reset586(); + } + } + } +} + +static void wait_for_scb_cmd_ruc(struct net_device *dev) +{ + struct priv *p = dev->priv; + int i; + for (i = 0; i < 16384; i++) { + if (readb(&p->scb->cmd_ruc) == 0) + break; + udelay(4); + if (i == 16383) { + printk(KERN_ERR "%s: scb_cmd (ruc) timed out: %04x,%04x .. disabling i82586!!\n", + dev->name, p->scb->cmd_ruc, p->scb->rus); + if (!p->reset) { + p->reset = 1; + ni_reset586(); + } + } + } +} + +static void wait_for_stat_compl(void *p) +{ + struct nop_cmd_struct *addr = p; + int i; + for (i = 0; i < 32767; i++) { + if (readw(&((addr)->cmd_status)) & STAT_COMPL) + break; + udelay(32); + } +} + /********************************************** * close device */ static int ni52_close(struct net_device *dev) { free_irq(dev->irq, dev); - ni_reset586(); /* the hard way to stop the receiver */ - netif_stop_queue(dev); - return 0; } @@ -265,55 +284,53 @@ static int ni52_open(struct net_device *dev) startrecv586(dev); ni_enaint(); - ret = request_irq(dev->irq, &ni52_interrupt,0,dev->name,dev); - if (ret) - { + ret = request_irq(dev->irq, &ni52_interrupt, 0, dev->name, dev); + if (ret) { ni_reset586(); return ret; } - netif_start_queue(dev); - return 0; /* most done by init */ } /********************************************** * Check to see if there's an 82586 out there. */ -static int check586(struct net_device *dev,char *where,unsigned size) +static int check586(struct net_device *dev, char *where, unsigned size) { struct priv pb; struct priv *p = /* (struct priv *) dev->priv*/ &pb; char *iscp_addrs[2]; int i; - p->base = (unsigned long) isa_bus_to_virt((unsigned long)where) + size - 0x01000000; + p->base = (unsigned long) isa_bus_to_virt((unsigned long)where) + + size - 0x01000000; p->memtop = isa_bus_to_virt((unsigned long)where) + size; p->scp = (struct scp_struct *)(p->base + SCP_DEFAULT_ADDRESS); - memset((char *)p->scp,0, sizeof(struct scp_struct)); - for(i=0;iscp)[i]) + memset_io((char *)p->scp, 0, sizeof(struct scp_struct)); + for (i = 0; i < sizeof(struct scp_struct); i++) + /* memory was writeable? */ + if (readb((char *)p->scp + i)) return 0; - p->scp->sysbus = SYSBUSVAL; /* 1 = 8Bit-Bus, 0 = 16 Bit */ - if(p->scp->sysbus != SYSBUSVAL) + writeb(SYSBUSVAL, &p->scp->sysbus); /* 1 = 8Bit-Bus, 0 = 16 Bit */ + if (readb(&p->scp->sysbus) != SYSBUSVAL) return 0; iscp_addrs[0] = isa_bus_to_virt((unsigned long)where); - iscp_addrs[1]= (char *) p->scp - sizeof(struct iscp_struct); + iscp_addrs[1] = (char *) p->scp - sizeof(struct iscp_struct); - for(i=0;i<2;i++) - { + for (i = 0; i < 2; i++) { p->iscp = (struct iscp_struct *) iscp_addrs[i]; - memset((char *)p->iscp,0, sizeof(struct iscp_struct)); + memset_io((char *)p->iscp, 0, sizeof(struct iscp_struct)); - p->scp->iscp = make24(p->iscp); - p->iscp->busy = 1; + writel(make24(p->iscp), &p->scp->iscp); + writeb(1, &p->iscp->busy); ni_reset586(); ni_attn586(); - DELAY(1); /* wait a while... */ - - if(p->iscp->busy) /* i82586 clears 'busy' after successful init */ + mdelay(32); /* wait a while... */ + /* i82586 clears 'busy' after successful init */ + if (readb(&p->iscp->busy)) return 0; } return 1; @@ -327,36 +344,39 @@ static void alloc586(struct net_device *dev) struct priv *p = (struct priv *) dev->priv; ni_reset586(); - DELAY(1); + mdelay(32); + + spin_lock_init(&p->spinlock); p->scp = (struct scp_struct *) (p->base + SCP_DEFAULT_ADDRESS); p->scb = (struct scb_struct *) isa_bus_to_virt(dev->mem_start); - p->iscp = (struct iscp_struct *) ((char *)p->scp - sizeof(struct iscp_struct)); + p->iscp = (struct iscp_struct *) + ((char *)p->scp - sizeof(struct iscp_struct)); - memset((char *) p->iscp,0,sizeof(struct iscp_struct)); - memset((char *) p->scp ,0,sizeof(struct scp_struct)); + memset_io(p->iscp, 0, sizeof(struct iscp_struct)); + memset_io(p->scp , 0, sizeof(struct scp_struct)); - p->scp->iscp = make24(p->iscp); - p->scp->sysbus = SYSBUSVAL; - p->iscp->scb_offset = make16(p->scb); + writel(make24(p->iscp), &p->scp->iscp); + writeb(SYSBUSVAL, &p->scp->sysbus); + writew(make16(p->scb), &p->iscp->scb_offset); - p->iscp->busy = 1; + writeb(1, &p->iscp->busy); ni_reset586(); ni_attn586(); - DELAY(1); + mdelay(32); - if(p->iscp->busy) - printk("%s: Init-Problems (alloc).\n",dev->name); + if (readb(&p->iscp->busy)) + printk(KERN_ERR "%s: Init-Problems (alloc).\n", dev->name); - p->reseted = 0; + p->reset = 0; - memset((char *)p->scb,0,sizeof(struct scb_struct)); + memset_io((char *)p->scb, 0, sizeof(struct scb_struct)); } /* set: io,irq,memstart,memend or set it when calling insmod */ -static int irq=9; -static int io=0x300; +static int irq = 9; +static int io = 0x300; static long memstart; /* e.g 0xd0000 */ static long memend; /* e.g 0xd4000 */ @@ -413,7 +433,7 @@ out: return ERR_PTR(err); } -static int __init ni52_probe1(struct net_device *dev,int ioaddr) +static int __init ni52_probe1(struct net_device *dev, int ioaddr) { int i, size, retval; @@ -425,90 +445,96 @@ static int __init ni52_probe1(struct net_device *dev,int ioaddr) if (!request_region(ioaddr, NI52_TOTAL_SIZE, DRV_NAME)) return -EBUSY; - if( !(inb(ioaddr+NI52_MAGIC1) == NI52_MAGICVAL1) || + if (!(inb(ioaddr+NI52_MAGIC1) == NI52_MAGICVAL1) || !(inb(ioaddr+NI52_MAGIC2) == NI52_MAGICVAL2)) { retval = -ENODEV; goto out; } - for(i=0;idev_addr[i] = inb(dev->base_addr+i); - if(dev->dev_addr[0] != NI52_ADDR0 || dev->dev_addr[1] != NI52_ADDR1 + if (dev->dev_addr[0] != NI52_ADDR0 || dev->dev_addr[1] != NI52_ADDR1 || dev->dev_addr[2] != NI52_ADDR2) { retval = -ENODEV; goto out; } - printk(KERN_INFO "%s: NI5210 found at %#3lx, ",dev->name,dev->base_addr); + printk(KERN_INFO "%s: NI5210 found at %#3lx, ", + dev->name, dev->base_addr); /* * check (or search) IO-Memory, 8K and 16K */ #ifdef MODULE size = dev->mem_end - dev->mem_start; - if(size != 0x2000 && size != 0x4000) { - printk("\n%s: Illegal memory size %d. Allowed is 0x2000 or 0x4000 bytes.\n",dev->name,size); + if (size != 0x2000 && size != 0x4000) { + printk("\n"); + printk(KERN_ERR "%s: Invalid memory size %d. Allowed is 0x2000 or 0x4000 bytes.\n", dev->name, size); retval = -ENODEV; goto out; } - if(!check586(dev,(char *) dev->mem_start,size)) { - printk("?memcheck, Can't find memory at 0x%lx with size %d!\n",dev->mem_start,size); + if (!check586(dev, (char *)dev->mem_start, size)) { + printk(KERN_ERR "?memcheck, Can't find memory at 0x%lx with size %d!\n", dev->mem_start, size); retval = -ENODEV; goto out; } #else - if(dev->mem_start != 0) /* no auto-mem-probe */ - { + if (dev->mem_start != 0) { + /* no auto-mem-probe */ size = 0x4000; /* check for 16K mem */ - if(!check586(dev,(char *) dev->mem_start,size)) { + if (!check586(dev, (char *) dev->mem_start, size)) { size = 0x2000; /* check for 8K mem */ - if(!check586(dev,(char *) dev->mem_start,size)) { - printk("?memprobe, Can't find memory at 0x%lx!\n",dev->mem_start); + if (!check586(dev, (char *)dev->mem_start, size)) { + printk(KERN_ERR "?memprobe, Can't find memory at 0x%lx!\n", dev->mem_start); retval = -ENODEV; goto out; } } - } - else - { - static long memaddrs[] = { 0xc8000,0xca000,0xcc000,0xce000,0xd0000,0xd2000, - 0xd4000,0xd6000,0xd8000,0xda000,0xdc000, 0 }; - for(i=0;;i++) - { - if(!memaddrs[i]) { - printk("?memprobe, Can't find io-memory!\n"); + } else { + static const unsigned long memaddrs[] = { + 0xc8000, 0xca000, 0xcc000, 0xce000, 0xd0000, 0xd2000, + 0xd4000, 0xd6000, 0xd8000, 0xda000, 0xdc000, 0 + }; + for (i = 0;; i++) { + if (!memaddrs[i]) { + printk(KERN_ERR "?memprobe, Can't find io-memory!\n"); retval = -ENODEV; goto out; } dev->mem_start = memaddrs[i]; size = 0x2000; /* check for 8K mem */ - if(check586(dev,(char *)dev->mem_start,size)) /* 8K-check */ + if (check586(dev, (char *)dev->mem_start, size)) + /* 8K-check */ break; size = 0x4000; /* check for 16K mem */ - if(check586(dev,(char *)dev->mem_start,size)) /* 16K-check */ + if (check586(dev, (char *)dev->mem_start, size)) + /* 16K-check */ break; } } - dev->mem_end = dev->mem_start + size; /* set mem_end showed by 'ifconfig' */ + /* set mem_end showed by 'ifconfig' */ + dev->mem_end = dev->mem_start + size; #endif - memset((char *) dev->priv,0,sizeof(struct priv)); + memset((char *)dev->priv, 0, sizeof(struct priv)); - ((struct priv *) (dev->priv))->memtop = isa_bus_to_virt(dev->mem_start) + size; - ((struct priv *) (dev->priv))->base = (unsigned long) isa_bus_to_virt(dev->mem_start) + size - 0x01000000; + ((struct priv *)(dev->priv))->memtop = + isa_bus_to_virt(dev->mem_start) + size; + ((struct priv *)(dev->priv))->base = (unsigned long) + isa_bus_to_virt(dev->mem_start) + size - 0x01000000; alloc586(dev); /* set number of receive-buffs according to memsize */ - if(size == 0x2000) + if (size == 0x2000) ((struct priv *) dev->priv)->num_recv_buffs = NUM_RECV_BUFFS_8; else ((struct priv *) dev->priv)->num_recv_buffs = NUM_RECV_BUFFS_16; - printk("Memaddr: 0x%lx, Memsize: %d, ",dev->mem_start,size); + printk(KERN_DEBUG "Memaddr: 0x%lx, Memsize: %d, ", + dev->mem_start, size); - if(dev->irq < 2) - { + if (dev->irq < 2) { unsigned long irq_mask; irq_mask = probe_irq_on(); @@ -517,18 +543,16 @@ static int __init ni52_probe1(struct net_device *dev,int ioaddr) mdelay(20); dev->irq = probe_irq_off(irq_mask); - if(!dev->irq) - { + if (!dev->irq) { printk("?autoirq, Failed to detect IRQ line!\n"); retval = -EAGAIN; goto out; } - printk("IRQ %d (autodetected).\n",dev->irq); - } - else { - if(dev->irq == 2) + printk("IRQ %d (autodetected).\n", dev->irq); + } else { + if (dev->irq == 2) dev->irq = 9; - printk("IRQ %d (assigned and not checked!).\n",dev->irq); + printk("IRQ %d (assigned and not checked!).\n", dev->irq); } dev->open = ni52_open; @@ -555,56 +579,58 @@ out: static int init586(struct net_device *dev) { void *ptr; - int i,result=0; - struct priv *p = (struct priv *) dev->priv; - volatile struct configure_cmd_struct *cfg_cmd; - volatile struct iasetup_cmd_struct *ias_cmd; - volatile struct tdr_cmd_struct *tdr_cmd; - volatile struct mcsetup_cmd_struct *mc_cmd; - struct dev_mc_list *dmi=dev->mc_list; - int num_addrs=dev->mc_count; + int i, result = 0; + struct priv *p = (struct priv *)dev->priv; + struct configure_cmd_struct *cfg_cmd; + struct iasetup_cmd_struct *ias_cmd; + struct tdr_cmd_struct *tdr_cmd; + struct mcsetup_cmd_struct *mc_cmd; + struct dev_mc_list *dmi = dev->mc_list; + int num_addrs = dev->mc_count; ptr = (void *) ((char *)p->scb + sizeof(struct scb_struct)); cfg_cmd = (struct configure_cmd_struct *)ptr; /* configure-command */ - cfg_cmd->cmd_status = 0; - cfg_cmd->cmd_cmd = CMD_CONFIGURE | CMD_LAST; - cfg_cmd->cmd_link = 0xffff; + writew(0, &cfg_cmd->cmd_status); + writew(CMD_CONFIGURE | CMD_LAST, &cfg_cmd->cmd_cmd); + writew(0xFFFF, &cfg_cmd->cmd_link); - cfg_cmd->byte_cnt = 0x0a; /* number of cfg bytes */ - cfg_cmd->fifo = fifo; /* fifo-limit (8=tx:32/rx:64) */ - cfg_cmd->sav_bf = 0x40; /* hold or discard bad recv frames (bit 7) */ - cfg_cmd->adr_len = 0x2e; /* addr_len |!src_insert |pre-len |loopback */ - cfg_cmd->priority = 0x00; - cfg_cmd->ifs = 0x60; - cfg_cmd->time_low = 0x00; - cfg_cmd->time_high = 0xf2; - cfg_cmd->promisc = 0; - if(dev->flags & IFF_ALLMULTI) { + /* number of cfg bytes */ + writeb(0x0a, &cfg_cmd->byte_cnt); + /* fifo-limit (8=tx:32/rx:64) */ + writeb(fifo, &cfg_cmd->fifo); + /* hold or discard bad recv frames (bit 7) */ + writeb(0x40, &cfg_cmd->sav_bf); + /* addr_len |!src_insert |pre-len |loopback */ + writeb(0x2e, &cfg_cmd->adr_len); + writeb(0x00, &cfg_cmd->priority); + writeb(0x60, &cfg_cmd->ifs);; + writeb(0x00, &cfg_cmd->time_low); + writeb(0xf2, &cfg_cmd->time_high); + writeb(0x00, &cfg_cmd->promisc);; + if (dev->flags & IFF_ALLMULTI) { int len = ((char *) p->iscp - (char *) ptr - 8) / 6; - if(num_addrs > len) { - printk("%s: switching to promisc. mode\n",dev->name); - dev->flags|=IFF_PROMISC; + if (num_addrs > len) { + printk(KERN_ERR "%s: switching to promisc. mode\n", + dev->name); + dev->flags |= IFF_PROMISC; } } - if(dev->flags&IFF_PROMISC) - { - cfg_cmd->promisc=1; - dev->flags|=IFF_PROMISC; - } - cfg_cmd->carr_coll = 0x00; + if (dev->flags & IFF_PROMISC) + writeb(0x01, &cfg_cmd->promisc); + writeb(0x00, &cfg_cmd->carr_coll); + writew(make16(cfg_cmd), &p->scb->cbl_offset); + writew(0, &p->scb->cmd_ruc); - p->scb->cbl_offset = make16(cfg_cmd); - p->scb->cmd_ruc = 0; - - p->scb->cmd_cuc = CUC_START; /* cmd.-unit start */ + writeb(CUC_START, &p->scb->cmd_cuc); /* cmd.-unit start */ ni_attn586(); - WAIT_4_STAT_COMPL(cfg_cmd); + wait_for_stat_compl(cfg_cmd); - if((cfg_cmd->cmd_status & (STAT_OK|STAT_COMPL)) != (STAT_COMPL|STAT_OK)) - { - printk("%s: configure command failed: %x\n",dev->name,cfg_cmd->cmd_status); + if ((readw(&cfg_cmd->cmd_status) & (STAT_OK|STAT_COMPL)) != + (STAT_COMPL|STAT_OK)) { + printk(KERN_ERR "%s: configure command failed: %x\n", + dev->name, readw(&cfg_cmd->cmd_status)); return 1; } @@ -614,21 +640,22 @@ static int init586(struct net_device *dev) ias_cmd = (struct iasetup_cmd_struct *)ptr; - ias_cmd->cmd_status = 0; - ias_cmd->cmd_cmd = CMD_IASETUP | CMD_LAST; - ias_cmd->cmd_link = 0xffff; + writew(0, &ias_cmd->cmd_status); + writew(CMD_IASETUP | CMD_LAST, &ias_cmd->cmd_cmd); + writew(0xffff, &ias_cmd->cmd_link); - memcpy((char *)&ias_cmd->iaddr,(char *) dev->dev_addr,ETH_ALEN); + memcpy_toio((char *)&ias_cmd->iaddr, (char *)dev->dev_addr, ETH_ALEN); - p->scb->cbl_offset = make16(ias_cmd); + writew(make16(ias_cmd), &p->scb->cbl_offset); - p->scb->cmd_cuc = CUC_START; /* cmd.-unit start */ + writeb(CUC_START, &p->scb->cmd_cuc); /* cmd.-unit start */ ni_attn586(); - WAIT_4_STAT_COMPL(ias_cmd); + wait_for_stat_compl(ias_cmd); - if((ias_cmd->cmd_status & (STAT_OK|STAT_COMPL)) != (STAT_OK|STAT_COMPL)) { - printk("%s (ni52): individual address setup command failed: %04x\n",dev->name,ias_cmd->cmd_status); + if ((readw(&ias_cmd->cmd_status) & (STAT_OK|STAT_COMPL)) != + (STAT_OK|STAT_COMPL)) { + printk(KERN_ERR "%s (ni52): individual address setup command failed: %04x\n", dev->name, readw(&ias_cmd->cmd_status)); return 1; } @@ -638,117 +665,119 @@ static int init586(struct net_device *dev) tdr_cmd = (struct tdr_cmd_struct *)ptr; - tdr_cmd->cmd_status = 0; - tdr_cmd->cmd_cmd = CMD_TDR | CMD_LAST; - tdr_cmd->cmd_link = 0xffff; - tdr_cmd->status = 0; + writew(0, &tdr_cmd->cmd_status); + writew(CMD_TDR | CMD_LAST, &tdr_cmd->cmd_cmd); + writew(0xffff, &tdr_cmd->cmd_link); + writew(0, &tdr_cmd->status); - p->scb->cbl_offset = make16(tdr_cmd); - p->scb->cmd_cuc = CUC_START; /* cmd.-unit start */ + writew(make16(tdr_cmd), &p->scb->cbl_offset); + writeb(CUC_START, &p->scb->cmd_cuc); /* cmd.-unit start */ ni_attn586(); - WAIT_4_STAT_COMPL(tdr_cmd); + wait_for_stat_compl(tdr_cmd); - if(!(tdr_cmd->cmd_status & STAT_COMPL)) - { - printk("%s: Problems while running the TDR.\n",dev->name); - } - else - { - DELAY_16(); /* wait for result */ - result = tdr_cmd->status; - - p->scb->cmd_cuc = p->scb->cus & STAT_MASK; + if (!(readw(&tdr_cmd->cmd_status) & STAT_COMPL)) + printk(KERN_ERR "%s: Problems while running the TDR.\n", + dev->name); + else { + udelay(16); + result = readw(&tdr_cmd->status); + writeb(readb(&p->scb->cus) & STAT_MASK, &p->scb->cmd_cuc); ni_attn586(); /* ack the interrupts */ - if(result & TDR_LNK_OK) + if (result & TDR_LNK_OK) ; - else if(result & TDR_XCVR_PRB) - printk("%s: TDR: Transceiver problem. Check the cable(s)!\n",dev->name); - else if(result & TDR_ET_OPN) - printk("%s: TDR: No correct termination %d clocks away.\n",dev->name,result & TDR_TIMEMASK); - else if(result & TDR_ET_SRT) - { - if (result & TDR_TIMEMASK) /* time == 0 -> strange :-) */ - printk("%s: TDR: Detected a short circuit %d clocks away.\n",dev->name,result & TDR_TIMEMASK); - } - else - printk("%s: TDR: Unknown status %04x\n",dev->name,result); + else if (result & TDR_XCVR_PRB) + printk(KERN_ERR "%s: TDR: Transceiver problem. Check the cable(s)!\n", + dev->name); + else if (result & TDR_ET_OPN) + printk(KERN_ERR "%s: TDR: No correct termination %d clocks away.\n", + dev->name, result & TDR_TIMEMASK); + else if (result & TDR_ET_SRT) { + /* time == 0 -> strange :-) */ + if (result & TDR_TIMEMASK) + printk(KERN_ERR "%s: TDR: Detected a short circuit %d clocks away.\n", + dev->name, result & TDR_TIMEMASK); + } else + printk(KERN_ERR "%s: TDR: Unknown status %04x\n", + dev->name, result); } /* * Multicast setup */ - if(num_addrs && !(dev->flags & IFF_PROMISC) ) - { + if (num_addrs && !(dev->flags & IFF_PROMISC)) { mc_cmd = (struct mcsetup_cmd_struct *) ptr; - mc_cmd->cmd_status = 0; - mc_cmd->cmd_cmd = CMD_MCSETUP | CMD_LAST; - mc_cmd->cmd_link = 0xffff; - mc_cmd->mc_cnt = num_addrs * 6; + writew(0, &mc_cmd->cmd_status); + writew(CMD_MCSETUP | CMD_LAST, &mc_cmd->cmd_cmd); + writew(0xffff, &mc_cmd->cmd_link); + writew(num_addrs * 6, &mc_cmd->mc_cnt); - for(i=0;inext) - memcpy((char *) mc_cmd->mc_list[i], dmi->dmi_addr,6); + for (i = 0; i < num_addrs; i++, dmi = dmi->next) + memcpy_toio((char *) mc_cmd->mc_list[i], + dmi->dmi_addr, 6); - p->scb->cbl_offset = make16(mc_cmd); - p->scb->cmd_cuc = CUC_START; + writew(make16(mc_cmd), &p->scb->cbl_offset); + writeb(CUC_START, &p->scb->cmd_cuc); ni_attn586(); - WAIT_4_STAT_COMPL(mc_cmd); + wait_for_stat_compl(mc_cmd); - if( (mc_cmd->cmd_status & (STAT_COMPL|STAT_OK)) != (STAT_COMPL|STAT_OK) ) - printk("%s: Can't apply multicast-address-list.\n",dev->name); + if ((readw(&mc_cmd->cmd_status) & (STAT_COMPL|STAT_OK)) + != (STAT_COMPL|STAT_OK)) + printk(KERN_ERR "%s: Can't apply multicast-address-list.\n", dev->name); } /* * alloc nop/xmit-cmds */ #if (NUM_XMIT_BUFFS == 1) - for(i=0;i<2;i++) - { - p->nop_cmds[i] = (struct nop_cmd_struct *)ptr; - p->nop_cmds[i]->cmd_cmd = CMD_NOP; - p->nop_cmds[i]->cmd_status = 0; - p->nop_cmds[i]->cmd_link = make16((p->nop_cmds[i])); + for (i = 0; i < 2; i++) { + p->nop_cmds[i] = (struct nop_cmd_struct *)ptr; + writew(CMD_NOP, &p->nop_cmds[i]->cmd_cmd); + writew(0, &p->nop_cmds[i]->cmd_status); + writew(make16(p->nop_cmds[i]), &p->nop_cmds[i]->cmd_link); ptr = (char *) ptr + sizeof(struct nop_cmd_struct); } #else - for(i=0;inop_cmds[i] = (struct nop_cmd_struct *)ptr; - p->nop_cmds[i]->cmd_cmd = CMD_NOP; - p->nop_cmds[i]->cmd_status = 0; - p->nop_cmds[i]->cmd_link = make16((p->nop_cmds[i])); + for (i = 0; i < NUM_XMIT_BUFFS; i++) { + p->nop_cmds[i] = (struct nop_cmd_struct *)ptr; + writew(CMD_NOP, &p->nop_cmds[i]->cmd_cmd); + writew(0, &p->nop_cmds[i]->cmd_status); + writew(make16(p->nop_cmds[i]), &p->nop_cmds[i]->cmd_link); ptr = (char *) ptr + sizeof(struct nop_cmd_struct); } #endif - ptr = alloc_rfa(dev,(void *)ptr); /* init receive-frame-area */ + ptr = alloc_rfa(dev, (void *)ptr); /* init receive-frame-area */ /* * alloc xmit-buffs / init xmit_cmds */ - for(i=0;ixmit_cmds[i] = (struct transmit_cmd_struct *)ptr; /*transmit cmd/buff 0*/ + for (i = 0; i < NUM_XMIT_BUFFS; i++) { + /* Transmit cmd/buff 0 */ + p->xmit_cmds[i] = (struct transmit_cmd_struct *)ptr; ptr = (char *) ptr + sizeof(struct transmit_cmd_struct); p->xmit_cbuffs[i] = (char *)ptr; /* char-buffs */ ptr = (char *) ptr + XMIT_BUFF_SIZE; p->xmit_buffs[i] = (struct tbd_struct *)ptr; /* TBD */ ptr = (char *) ptr + sizeof(struct tbd_struct); - if((void *)ptr > (void *)p->iscp) - { - printk("%s: not enough shared-mem for your configuration!\n",dev->name); + if ((void *)ptr > (void *)p->iscp) { + printk(KERN_ERR "%s: not enough shared-mem for your configuration!\n", + dev->name); return 1; } - memset((char *)(p->xmit_cmds[i]) ,0, sizeof(struct transmit_cmd_struct)); - memset((char *)(p->xmit_buffs[i]),0, sizeof(struct tbd_struct)); - p->xmit_cmds[i]->cmd_link = make16(p->nop_cmds[(i+1)%NUM_XMIT_BUFFS]); - p->xmit_cmds[i]->cmd_status = STAT_COMPL; - p->xmit_cmds[i]->cmd_cmd = CMD_XMIT | CMD_INT; - p->xmit_cmds[i]->tbd_offset = make16((p->xmit_buffs[i])); - p->xmit_buffs[i]->next = 0xffff; - p->xmit_buffs[i]->buffer = make24((p->xmit_cbuffs[i])); + memset_io((char *)(p->xmit_cmds[i]), 0, + sizeof(struct transmit_cmd_struct)); + memset_io((char *)(p->xmit_buffs[i]), 0, + sizeof(struct tbd_struct)); + writew(make16(p->nop_cmds[(i+1)%NUM_XMIT_BUFFS]), + &p->xmit_cmds[i]->cmd_link); + writew(STAT_COMPL, &p->xmit_cmds[i]->cmd_status); + writew(CMD_XMIT|CMD_INT, &p->xmit_cmds[i]->cmd_cmd); + writew(make16(p->xmit_buffs[i]), &p->xmit_cmds[i]->tbd_offset); + writew(0xffff, &p->xmit_buffs[i]->next); + writel(make24(p->xmit_cbuffs[i]), &p->xmit_buffs[i]->buffer); } p->xmit_count = 0; @@ -761,21 +790,21 @@ static int init586(struct net_device *dev) * 'start transmitter' */ #ifndef NO_NOPCOMMANDS - p->scb->cbl_offset = make16(p->nop_cmds[0]); - p->scb->cmd_cuc = CUC_START; + writew(make16(p->nop_cmds[0]), &p->scb->cbl_offset); + writeb(CUC_START, &p->scb->cmd_cuc); ni_attn586(); - WAIT_4_SCB_CMD(); + wait_for_scb_cmd(dev); #else - p->xmit_cmds[0]->cmd_link = make16(p->xmit_cmds[0]); - p->xmit_cmds[0]->cmd_cmd = CMD_XMIT | CMD_SUSPEND | CMD_INT; + writew(make16(p->xmit_cmds[0]), &p->xmit_cmds[0]->cmd_link); + writew(CMD_XMIT | CMD_SUSPEND | CMD_INT, &p->xmit_cmds[0]->cmd_cmd); #endif /* * ack. interrupts */ - p->scb->cmd_cuc = p->scb->cus & STAT_MASK; + writeb(readb(&p->scb->cus) & STAT_MASK, &p->scb->cmd_cuc); ni_attn586(); - DELAY_16(); + udelay(16); ni_enaint(); @@ -787,43 +816,45 @@ static int init586(struct net_device *dev) * It sets up the Receive Frame Area (RFA). */ -static void *alloc_rfa(struct net_device *dev,void *ptr) +static void *alloc_rfa(struct net_device *dev, void *ptr) { - volatile struct rfd_struct *rfd = (struct rfd_struct *)ptr; - volatile struct rbd_struct *rbd; + struct rfd_struct *rfd = (struct rfd_struct *)ptr; + struct rbd_struct *rbd; int i; struct priv *p = (struct priv *) dev->priv; - memset((char *) rfd,0,sizeof(struct rfd_struct)*(p->num_recv_buffs+rfdadd)); + memset_io((char *) rfd, 0, + sizeof(struct rfd_struct) * (p->num_recv_buffs + rfdadd)); p->rfd_first = rfd; - for(i = 0; i < (p->num_recv_buffs+rfdadd); i++) { - rfd[i].next = make16(rfd + (i+1) % (p->num_recv_buffs+rfdadd) ); - rfd[i].rbd_offset = 0xffff; + for (i = 0; i < (p->num_recv_buffs + rfdadd); i++) { + writew(make16(rfd + (i+1) % (p->num_recv_buffs+rfdadd)), + &rfd[i].next); + writew(0xffff, &rfd[i].rbd_offset); } - rfd[p->num_recv_buffs-1+rfdadd].last = RFD_SUSP; /* RU suspend */ + /* RU suspend */ + writeb(RFD_SUSP, &rfd[p->num_recv_buffs-1+rfdadd].last); - ptr = (void *) (rfd + (p->num_recv_buffs + rfdadd) ); + ptr = (void *) (rfd + (p->num_recv_buffs + rfdadd)); rbd = (struct rbd_struct *) ptr; ptr = (void *) (rbd + p->num_recv_buffs); /* clr descriptors */ - memset((char *) rbd,0,sizeof(struct rbd_struct)*(p->num_recv_buffs)); + memset_io((char *)rbd, 0, + sizeof(struct rbd_struct) * (p->num_recv_buffs)); - for(i=0;inum_recv_buffs;i++) - { - rbd[i].next = make16((rbd + (i+1) % p->num_recv_buffs)); - rbd[i].size = RECV_BUFF_SIZE; - rbd[i].buffer = make24(ptr); + for (i = 0; i < p->num_recv_buffs; i++) { + writew(make16(rbd + (i+1) % p->num_recv_buffs), &rbd[i].next); + writew(RECV_BUFF_SIZE, &rbd[i].size); + writel(make24(ptr), &rbd[i].buffer); ptr = (char *) ptr + RECV_BUFF_SIZE; } - p->rfd_top = p->rfd_first; p->rfd_last = p->rfd_first + (p->num_recv_buffs - 1 + rfdadd); - p->scb->rfa_offset = make16(p->rfd_first); - p->rfd_first->rbd_offset = make16(rbd); + writew(make16(p->rfd_first), &p->scb->rfa_offset); + writew(make16(rbd), &p->rfd_first->rbd_offset); return ptr; } @@ -833,73 +864,71 @@ static void *alloc_rfa(struct net_device *dev,void *ptr) * Interrupt Handler ... */ -static irqreturn_t ni52_interrupt(int irq,void *dev_id) +static irqreturn_t ni52_interrupt(int irq, void *dev_id) { struct net_device *dev = dev_id; - unsigned short stat; - int cnt=0; + unsigned int stat; + int cnt = 0; struct priv *p; - if (!dev) { - printk ("ni5210-interrupt: irq %d for unknown device.\n",irq); - return IRQ_NONE; - } p = (struct priv *) dev->priv; - if(debuglevel > 1) + if (debuglevel > 1) printk("I"); - WAIT_4_SCB_CMD(); /* wait for last command */ + spin_lock(&p->spinlock); - while((stat=p->scb->cus & STAT_MASK)) - { - p->scb->cmd_cuc = stat; + wait_for_scb_cmd(dev); /* wait for last command */ + + while ((stat = readb(&p->scb->cus) & STAT_MASK)) { + writeb(stat, &p->scb->cmd_cuc); ni_attn586(); - if(stat & STAT_FR) /* received a frame */ + if (stat & STAT_FR) /* received a frame */ ni52_rcv_int(dev); - if(stat & STAT_RNR) /* RU went 'not ready' */ - { + if (stat & STAT_RNR) { /* RU went 'not ready' */ printk("(R)"); - if(p->scb->rus & RU_SUSPEND) /* special case: RU_SUSPEND */ - { - WAIT_4_SCB_CMD(); + if (readb(&p->scb->rus) & RU_SUSPEND) { + /* special case: RU_SUSPEND */ + wait_for_scb_cmd(dev); p->scb->cmd_ruc = RUC_RESUME; ni_attn586(); - WAIT_4_SCB_CMD_RUC(); - } - else - { - printk("%s: Receiver-Unit went 'NOT READY': %04x/%02x.\n",dev->name,(int) stat,(int) p->scb->rus); + wait_for_scb_cmd_ruc(dev); + } else { + printk(KERN_ERR "%s: Receiver-Unit went 'NOT READY': %04x/%02x.\n", + dev->name, stat, readb(&p->scb->rus)); ni52_rnr_int(dev); } } - if(stat & STAT_CX) /* command with I-bit set complete */ + /* Command with I-bit set complete */ + if (stat & STAT_CX) ni52_xmt_int(dev); #ifndef NO_NOPCOMMANDS - if(stat & STAT_CNA) /* CU went 'not ready' */ - { - if(netif_running(dev)) - printk("%s: oops! CU has left active state. stat: %04x/%02x.\n",dev->name,(int) stat,(int) p->scb->cus); + if (stat & STAT_CNA) { /* CU went 'not ready' */ + if (netif_running(dev)) + printk(KERN_ERR "%s: oops! CU has left active state. stat: %04x/%02x.\n", + dev->name, stat, readb(&p->scb->cus)); } #endif - if(debuglevel > 1) - printk("%d",cnt++); + if (debuglevel > 1) + printk("%d", cnt++); - WAIT_4_SCB_CMD(); /* wait for ack. (ni52_xmt_int can be faster than ack!!) */ - if(p->scb->cmd_cuc) /* timed out? */ - { - printk("%s: Acknowledge timed out.\n",dev->name); + /* Wait for ack. (ni52_xmt_int can be faster than ack!!) */ + wait_for_scb_cmd(dev); + if (p->scb->cmd_cuc) { /* timed out? */ + printk(KERN_ERR "%s: Acknowledge timed out.\n", + dev->name); ni_disint(); break; } } + spin_unlock(&p->spinlock); - if(debuglevel > 1) + if (debuglevel > 1) printk("i"); return IRQ_HANDLED; } @@ -910,121 +939,91 @@ static irqreturn_t ni52_interrupt(int irq,void *dev_id) static void ni52_rcv_int(struct net_device *dev) { - int status,cnt=0; + int status, cnt = 0; unsigned short totlen; struct sk_buff *skb; struct rbd_struct *rbd; - struct priv *p = (struct priv *) dev->priv; + struct priv *p = (struct priv *)dev->priv; - if(debuglevel > 0) + if (debuglevel > 0) printk("R"); - for(;(status = p->rfd_top->stat_high) & RFD_COMPL;) - { - rbd = (struct rbd_struct *) make32(p->rfd_top->rbd_offset); - - if(status & RFD_OK) /* frame received without error? */ - { - if( (totlen = rbd->status) & RBD_LAST) /* the first and the last buffer? */ - { - totlen &= RBD_MASK; /* length of this frame */ - rbd->status = 0; - skb = (struct sk_buff *) dev_alloc_skb(totlen+2); - if(skb != NULL) - { - skb_reserve(skb,2); - skb_put(skb,totlen); - skb_copy_to_linear_data(skb,(char *) p->base+(unsigned long) rbd->buffer,totlen); - skb->protocol=eth_type_trans(skb,dev); - netif_rx(skb); - dev->last_rx = jiffies; - p->stats.rx_packets++; - p->stats.rx_bytes += totlen; - } - else - p->stats.rx_dropped++; - } - else - { - int rstat; - /* free all RBD's until RBD_LAST is set */ - totlen = 0; - while(!((rstat=rbd->status) & RBD_LAST)) - { - totlen += rstat & RBD_MASK; - if(!rstat) - { - printk("%s: Whoops .. no end mark in RBD list\n",dev->name); - break; - } - rbd->status = 0; - rbd = (struct rbd_struct *) make32(rbd->next); - } - totlen += rstat & RBD_MASK; - rbd->status = 0; - printk("%s: received oversized frame! length: %d\n",dev->name,totlen); + for (; (status = readb(&p->rfd_top->stat_high)) & RFD_COMPL;) { + rbd = (struct rbd_struct *) make32(p->rfd_top->rbd_offset); + if (status & RFD_OK) { /* frame received without error? */ + totlen = readw(&rbd->status); + if (totlen & RBD_LAST) { + /* the first and the last buffer? */ + totlen &= RBD_MASK; /* length of this frame */ + writew(0x00, &rbd->status); + skb = (struct sk_buff *)dev_alloc_skb(totlen+2); + if (skb != NULL) { + skb_reserve(skb, 2); + skb_put(skb, totlen); + skb_copy_to_linear_data(skb, (char *)p->base + (unsigned long) rbd->buffer, totlen); + skb->protocol = eth_type_trans(skb, dev); + netif_rx(skb); + dev->last_rx = jiffies; + p->stats.rx_packets++; + p->stats.rx_bytes += totlen; + } else p->stats.rx_dropped++; + } else { + int rstat; + /* free all RBD's until RBD_LAST is set */ + totlen = 0; + while (!((rstat = readw(&rbd->status)) & RBD_LAST)) { + totlen += rstat & RBD_MASK; + if (!rstat) { + printk(KERN_ERR "%s: Whoops .. no end mark in RBD list\n", dev->name); + break; + } + writew(0, &rbd->status); + rbd = (struct rbd_struct *) make32(readl(&rbd->next)); + } + totlen += rstat & RBD_MASK; + writew(0, &rbd->status); + printk(KERN_ERR "%s: received oversized frame! length: %d\n", + dev->name, totlen); + p->stats.rx_dropped++; } - } - else /* frame !(ok), only with 'save-bad-frames' */ - { - printk("%s: oops! rfd-error-status: %04x\n",dev->name,status); + } else {/* frame !(ok), only with 'save-bad-frames' */ + printk(KERN_ERR "%s: oops! rfd-error-status: %04x\n", + dev->name, status); p->stats.rx_errors++; } - p->rfd_top->stat_high = 0; - p->rfd_top->last = RFD_SUSP; /* maybe exchange by RFD_LAST */ - p->rfd_top->rbd_offset = 0xffff; - p->rfd_last->last = 0; /* delete RFD_SUSP */ + writeb(0, &p->rfd_top->stat_high); + writeb(RFD_SUSP, &p->rfd_top->last); /* maybe exchange by RFD_LAST */ + writew(0xffff, &p->rfd_top->rbd_offset); + writeb(0, &p->rfd_last->last); /* delete RFD_SUSP */ p->rfd_last = p->rfd_top; p->rfd_top = (struct rfd_struct *) make32(p->rfd_top->next); /* step to next RFD */ - p->scb->rfa_offset = make16(p->rfd_top); + writew(make16(p->rfd_top), &p->scb->rfa_offset); - if(debuglevel > 0) - printk("%d",cnt++); + if (debuglevel > 0) + printk("%d", cnt++); } - if(automatic_resume) - { - WAIT_4_SCB_CMD(); - p->scb->cmd_ruc = RUC_RESUME; + if (automatic_resume) { + wait_for_scb_cmd(dev); + writeb(RUC_RESUME, &p->scb->cmd_ruc); ni_attn586(); - WAIT_4_SCB_CMD_RUC(); + wait_for_scb_cmd_ruc(dev); } #ifdef WAIT_4_BUSY { int i; - for(i=0;i<1024;i++) - { - if(p->rfd_top->status) + for (i = 0; i < 1024; i++) { + if (p->rfd_top->status) break; - DELAY_16(); - if(i == 1023) - printk("%s: RU hasn't fetched next RFD (not busy/complete)\n",dev->name); + udelay(16); + if (i == 1023) + printk(KERN_ERR "%s: RU hasn't fetched next RFD (not busy/complete)\n", dev->name); } } #endif - -#if 0 - if(!at_least_one) - { - int i; - volatile struct rfd_struct *rfds=p->rfd_top; - volatile struct rbd_struct *rbds; - printk("%s: received a FC intr. without having a frame: %04x %d\n",dev->name,status,old_at_least); - for(i=0;i< (p->num_recv_buffs+4);i++) - { - rbds = (struct rbd_struct *) make32(rfds->rbd_offset); - printk("%04x:%04x ",rfds->status,rbds->status); - rfds = (struct rfd_struct *) make32(rfds->next); - } - printk("\nerrs: %04x %04x stat: %04x\n",(int)p->scb->rsc_errs,(int)p->scb->ovrn_errs,(int)p->scb->status); - printk("\nerrs: %04x %04x rus: %02x, cus: %02x\n",(int)p->scb->rsc_errs,(int)p->scb->ovrn_errs,(int)p->scb->rus,(int)p->scb->cus); - } - old_at_least = at_least_one; -#endif - - if(debuglevel > 0) + if (debuglevel > 0) printk("r"); } @@ -1038,16 +1037,16 @@ static void ni52_rnr_int(struct net_device *dev) p->stats.rx_errors++; - WAIT_4_SCB_CMD(); /* wait for the last cmd, WAIT_4_FULLSTAT?? */ - p->scb->cmd_ruc = RUC_ABORT; /* usually the RU is in the 'no resource'-state .. abort it now. */ + wait_for_scb_cmd(dev); /* wait for the last cmd, WAIT_4_FULLSTAT?? */ + writeb(RUC_ABORT, &p->scb->cmd_ruc); /* usually the RU is in the 'no resource'-state .. abort it now. */ ni_attn586(); - WAIT_4_SCB_CMD_RUC(); /* wait for accept cmd. */ + wait_for_scb_cmd_ruc(dev); /* wait for accept cmd. */ - alloc_rfa(dev,(char *)p->rfd_first); -/* maybe add a check here, before restarting the RU */ + alloc_rfa(dev, (char *)p->rfd_first); + /* maybe add a check here, before restarting the RU */ startrecv586(dev); /* restart RU */ - printk("%s: Receive-Unit restarted. Status: %04x\n",dev->name,p->scb->rus); + printk(KERN_ERR "%s: Receive-Unit restarted. Status: %04x\n", dev->name, p->scb->rus); } @@ -1060,43 +1059,41 @@ static void ni52_xmt_int(struct net_device *dev) int status; struct priv *p = (struct priv *) dev->priv; - if(debuglevel > 0) + if (debuglevel > 0) printk("X"); - status = p->xmit_cmds[p->xmit_last]->cmd_status; - if(!(status & STAT_COMPL)) - printk("%s: strange .. xmit-int without a 'COMPLETE'\n",dev->name); + status = readw(&p->xmit_cmds[p->xmit_last]->cmd_status); + if (!(status & STAT_COMPL)) + printk(KERN_ERR "%s: strange .. xmit-int without a 'COMPLETE'\n", dev->name); - if(status & STAT_OK) - { + if (status & STAT_OK) { p->stats.tx_packets++; p->stats.collisions += (status & TCMD_MAXCOLLMASK); - } - else - { + } else { p->stats.tx_errors++; - if(status & TCMD_LATECOLL) { - printk("%s: late collision detected.\n",dev->name); + if (status & TCMD_LATECOLL) { + printk(KERN_ERR "%s: late collision detected.\n", + dev->name); p->stats.collisions++; - } - else if(status & TCMD_NOCARRIER) { + } else if (status & TCMD_NOCARRIER) { p->stats.tx_carrier_errors++; - printk("%s: no carrier detected.\n",dev->name); - } - else if(status & TCMD_LOSTCTS) - printk("%s: loss of CTS detected.\n",dev->name); - else if(status & TCMD_UNDERRUN) { + printk(KERN_ERR "%s: no carrier detected.\n", + dev->name); + } else if (status & TCMD_LOSTCTS) + printk(KERN_ERR "%s: loss of CTS detected.\n", + dev->name); + else if (status & TCMD_UNDERRUN) { p->stats.tx_fifo_errors++; - printk("%s: DMA underrun detected.\n",dev->name); - } - else if(status & TCMD_MAXCOLL) { - printk("%s: Max. collisions exceeded.\n",dev->name); + printk(KERN_ERR "%s: DMA underrun detected.\n", + dev->name); + } else if (status & TCMD_MAXCOLL) { + printk(KERN_ERR "%s: Max. collisions exceeded.\n", + dev->name); p->stats.collisions += 16; } } - #if (NUM_XMIT_BUFFS > 1) - if( (++p->xmit_last) == NUM_XMIT_BUFFS) + if ((++p->xmit_last) == NUM_XMIT_BUFFS) p->xmit_last = 0; #endif netif_wake_queue(dev); @@ -1110,41 +1107,51 @@ static void startrecv586(struct net_device *dev) { struct priv *p = (struct priv *) dev->priv; - WAIT_4_SCB_CMD(); - WAIT_4_SCB_CMD_RUC(); - p->scb->rfa_offset = make16(p->rfd_first); - p->scb->cmd_ruc = RUC_START; + wait_for_scb_cmd(dev); + wait_for_scb_cmd_ruc(dev); + writew(make16(p->rfd_first), &p->scb->rfa_offset); + writeb(RUC_START, &p->scb->cmd_ruc); ni_attn586(); /* start cmd. */ - WAIT_4_SCB_CMD_RUC(); /* wait for accept cmd. (no timeout!!) */ + wait_for_scb_cmd_ruc(dev); + /* wait for accept cmd. (no timeout!!) */ } static void ni52_timeout(struct net_device *dev) { struct priv *p = (struct priv *) dev->priv; #ifndef NO_NOPCOMMANDS - if(p->scb->cus & CU_ACTIVE) /* COMMAND-UNIT active? */ - { + if (readb(&p->scb->cus) & CU_ACTIVE) { /* COMMAND-UNIT active? */ netif_wake_queue(dev); #ifdef DEBUG - printk("%s: strange ... timeout with CU active?!?\n",dev->name); - printk("%s: X0: %04x N0: %04x N1: %04x %d\n",dev->name,(int)p->xmit_cmds[0]->cmd_status,(int)p->nop_cmds[0]->cmd_status,(int)p->nop_cmds[1]->cmd_status,(int)p->nop_point); + printk(KERN_ERR "%s: strange ... timeout with CU active?!?\n", + dev->name); + printk(KERN_ERR "%s: X0: %04x N0: %04x N1: %04x %d\n", + dev->name, (int)p->xmit_cmds[0]->cmd_status, + readw(&p->nop_cmds[0]->cmd_status), + readw(&p->nop_cmds[1]->cmd_status), + p->nop_point); #endif - p->scb->cmd_cuc = CUC_ABORT; + writeb(CUC_ABORT, &p->scb->cmd_cuc); ni_attn586(); - WAIT_4_SCB_CMD(); - p->scb->cbl_offset = make16(p->nop_cmds[p->nop_point]); - p->scb->cmd_cuc = CUC_START; + wait_for_scb_cmd(dev); + writew(make16(p->nop_cmds[p->nop_point]), &p->scb->cbl_offset); + writeb(CUC_START, &p->scb->cmd_cuc); ni_attn586(); - WAIT_4_SCB_CMD(); + wait_for_scb_cmd(dev); dev->trans_start = jiffies; return 0; } #endif { #ifdef DEBUG - printk("%s: xmitter timed out, try to restart! stat: %02x\n",dev->name,p->scb->cus); - printk("%s: command-stats: %04x %04x\n",dev->name,p->xmit_cmds[0]->cmd_status,p->xmit_cmds[1]->cmd_status); - printk("%s: check, whether you set the right interrupt number!\n",dev->name); + printk(KERN_ERR "%s: xmitter timed out, try to restart! stat: %02x\n", + dev->name, readb(&p->scb->cus)); + printk(KERN_ERR "%s: command-stats: %04x %04x\n", + dev->name, + readw(&p->xmit_cmds[0]->cmd_status), + readw(&p->xmit_cmds[1]->cmd_status)); + printk(KERN_ERR "%s: check, whether you set the right interrupt number!\n", + dev->name); #endif ni52_close(dev); ni52_open(dev); @@ -1158,110 +1165,99 @@ static void ni52_timeout(struct net_device *dev) static int ni52_send_packet(struct sk_buff *skb, struct net_device *dev) { - int len,i; + int len, i; #ifndef NO_NOPCOMMANDS int next_nop; #endif struct priv *p = (struct priv *) dev->priv; - if(skb->len > XMIT_BUFF_SIZE) - { - printk("%s: Sorry, max. framelength is %d bytes. The length of your frame is %d bytes.\n",dev->name,XMIT_BUFF_SIZE,skb->len); + if (skb->len > XMIT_BUFF_SIZE) { + printk(KERN_ERR "%s: Sorry, max. framelength is %d bytes. The length of your frame is %d bytes.\n", dev->name, XMIT_BUFF_SIZE, skb->len); return 0; } netif_stop_queue(dev); -#if(NUM_XMIT_BUFFS > 1) - if(test_and_set_bit(0,(void *) &p->lock)) { - printk("%s: Queue was locked\n",dev->name); - return 1; + skb_copy_from_linear_data(skb, (char *)p->xmit_cbuffs[p->xmit_count], + skb->len); + len = skb->len; + if (len < ETH_ZLEN) { + len = ETH_ZLEN; + memset((char *)p->xmit_cbuffs[p->xmit_count]+skb->len, 0, + len - skb->len); } - else -#endif - { - skb_copy_from_linear_data(skb, (char *) p->xmit_cbuffs[p->xmit_count], skb->len); - len = skb->len; - if (len < ETH_ZLEN) { - len = ETH_ZLEN; - memset((char *)p->xmit_cbuffs[p->xmit_count]+skb->len, 0, len - skb->len); - } #if (NUM_XMIT_BUFFS == 1) # ifdef NO_NOPCOMMANDS #ifdef DEBUG - if(p->scb->cus & CU_ACTIVE) - { - printk("%s: Hmmm .. CU is still running and we wanna send a new packet.\n",dev->name); - printk("%s: stat: %04x %04x\n",dev->name,p->scb->cus,p->xmit_cmds[0]->cmd_status); - } + if (p->scb->cus & CU_ACTIVE) { + printk(KERN_ERR "%s: Hmmm .. CU is still running and we wanna send a new packet.\n", dev->name); + printk(KERN_ERR "%s: stat: %04x %04x\n", + dev->name, readb(&p->scb->cus), + readw(&p->xmit_cmds[0]->cmd_status)); + } #endif - - p->xmit_buffs[0]->size = TBD_LAST | len; - for(i=0;i<16;i++) - { - p->xmit_cmds[0]->cmd_status = 0; - WAIT_4_SCB_CMD(); - if( (p->scb->cus & CU_STATUS) == CU_SUSPEND) - p->scb->cmd_cuc = CUC_RESUME; - else - { - p->scb->cbl_offset = make16(p->xmit_cmds[0]); - p->scb->cmd_cuc = CUC_START; - } - - ni_attn586(); - dev->trans_start = jiffies; - if(!i) - dev_kfree_skb(skb); - WAIT_4_SCB_CMD(); - if( (p->scb->cus & CU_ACTIVE)) /* test it, because CU sometimes doesn't start immediately */ - break; - if(p->xmit_cmds[0]->cmd_status) - break; - if(i==15) - printk("%s: Can't start transmit-command.\n",dev->name); + writew(TBD_LAST | len, &p->xmit_buffs[0]->size);; + for (i = 0; i < 16; i++) { + writew(0, &p->xmit_cmds[0]->cmd_status); + wait_for_scb_cmd(dev); + if ((readb(&p->scb->cus) & CU_STATUS) == CU_SUSPEND) + writeb(CUC_RESUME, &p->scb->cmd_cuc); + else { + writew(make16(p->xmit_cmds[0]), &p->scb->cbl_offset); + writeb(CUC_START, &p->scb->cmd_cuc); } -# else - next_nop = (p->nop_point + 1) & 0x1; - p->xmit_buffs[0]->size = TBD_LAST | len; - - p->xmit_cmds[0]->cmd_link = p->nop_cmds[next_nop]->cmd_link - = make16((p->nop_cmds[next_nop])); - p->xmit_cmds[0]->cmd_status = p->nop_cmds[next_nop]->cmd_status = 0; - - p->nop_cmds[p->nop_point]->cmd_link = make16((p->xmit_cmds[0])); + ni_attn586(); dev->trans_start = jiffies; - p->nop_point = next_nop; - dev_kfree_skb(skb); + if (!i) + dev_kfree_skb(skb); + wait_for_scb_cmd(dev); + /* test it, because CU sometimes doesn't start immediately */ + if (readb(&p->scb->cus) & CU_ACTIVE) + break; + if (readw(&p->xmit_cmds[0]->cmd_status)) + break; + if (i == 15) + printk(KERN_WARNING "%s: Can't start transmit-command.\n", dev->name); + } +# else + next_nop = (p->nop_point + 1) & 0x1; + writew(TBD_LAST | len, &p->xmit_buffs[0]->size); + writew(make16(p->nop_cmds[next_nop]), &p->xmit_cmds[0]->cmd_link); + writew(make16(p->nop_cmds[next_nop]), + &p->nop_cmds[next_nop]->cmd_link); + writew(0, &p->xmit_cmds[0]->cmd_status); + writew(0, &p->nop_cmds[next_nop]->cmd_status); + + writew(make16(p->xmit_cmds[0]), &p->nop_cmds[p->nop_point]->cmd_link); + dev->trans_start = jiffies; + p->nop_point = next_nop; + dev_kfree_skb(skb); # endif #else - p->xmit_buffs[p->xmit_count]->size = TBD_LAST | len; - if( (next_nop = p->xmit_count + 1) == NUM_XMIT_BUFFS ) - next_nop = 0; - - p->xmit_cmds[p->xmit_count]->cmd_status = 0; - /* linkpointer of xmit-command already points to next nop cmd */ - p->nop_cmds[next_nop]->cmd_link = make16((p->nop_cmds[next_nop])); - p->nop_cmds[next_nop]->cmd_status = 0; - - p->nop_cmds[p->xmit_count]->cmd_link = make16((p->xmit_cmds[p->xmit_count])); - dev->trans_start = jiffies; - p->xmit_count = next_nop; - - { - unsigned long flags; - save_flags(flags); - cli(); - if(p->xmit_count != p->xmit_last) - netif_wake_queue(dev); - p->lock = 0; - restore_flags(flags); - } - dev_kfree_skb(skb); -#endif + writew(TBD_LAST | len, &p->xmit_buffs[p->xmit_count]->size); + next_nop = p->xmit_count + 1 + if (next_nop == NUM_XMIT_BUFFS) + next_nop = 0; + writew(0, &p->xmit_cmds[p->xmit_count]->cmd_status); + /* linkpointer of xmit-command already points to next nop cmd */ + writew(make16(p->nop_cmds[next_nop]), + &p->nop_cmds[next_nop]->cmd_link); + writew(0, &p->nop_cmds[next_nop]->cmd_status); + writew(make16(p->xmit_cmds[p->xmit_count]), + &p->nop_cmds[p->xmit_count]->cmd_link); + dev->trans_start = jiffies; + p->xmit_count = next_nop; + { + unsigned long flags; + spin_lock_irqsave(&p->spinlock); + if (p->xmit_count != p->xmit_last) + netif_wake_queue(dev); + spin_unlock_irqrestore(&p->spinlock); } + dev_kfree_skb(skb); +#endif return 0; } @@ -1272,16 +1268,17 @@ static int ni52_send_packet(struct sk_buff *skb, struct net_device *dev) static struct net_device_stats *ni52_get_stats(struct net_device *dev) { struct priv *p = (struct priv *) dev->priv; - unsigned short crc,aln,rsc,ovrn; + unsigned short crc, aln, rsc, ovrn; - crc = p->scb->crc_errs; /* get error-statistic from the ni82586 */ - p->scb->crc_errs = 0; - aln = p->scb->aln_errs; - p->scb->aln_errs = 0; - rsc = p->scb->rsc_errs; - p->scb->rsc_errs = 0; - ovrn = p->scb->ovrn_errs; - p->scb->ovrn_errs = 0; + /* Get error-statistics from the ni82586 */ + crc = readw(&p->scb->crc_errs); + writew(0, &p->scb->crc_errs); + aln = readw(&p->scb->aln_errs); + writew(0, &p->scb->aln_errs); + rsc = readw(&p->scb->rsc_errs); + writew(0, &p->scb->rsc_errs); + ovrn = readw(&p->scb->ovrn_errs); + writew(0, &p->scb->ovrn_errs); p->stats.rx_crc_errors += crc; p->stats.rx_fifo_errors += ovrn; @@ -1320,8 +1317,9 @@ MODULE_PARM_DESC(memend, "NI5210 memory end address,required"); int __init init_module(void) { - if(io <= 0x0 || !memend || !memstart || irq < 2) { - printk("ni52: Autoprobing not allowed for modules.\nni52: Set symbols 'io' 'irq' 'memstart' and 'memend'\n"); + if (io <= 0x0 || !memend || !memstart || irq < 2) { + printk(KERN_ERR "ni52: Autoprobing not allowed for modules.\n"); + printk(KERN_ERR "ni52: Set symbols 'io' 'irq' 'memstart' and 'memend'\n"); return -ENODEV; } dev_ni52 = ni52_probe(-1); @@ -1338,42 +1336,6 @@ void __exit cleanup_module(void) } #endif /* MODULE */ -#if 0 -/* - * DUMP .. we expect a not running CMD unit and enough space - */ -void ni52_dump(struct net_device *dev,void *ptr) -{ - struct priv *p = (struct priv *) dev->priv; - struct dump_cmd_struct *dump_cmd = (struct dump_cmd_struct *) ptr; - int i; - - p->scb->cmd_cuc = CUC_ABORT; - ni_attn586(); - WAIT_4_SCB_CMD(); - WAIT_4_SCB_CMD_RUC(); - - dump_cmd->cmd_status = 0; - dump_cmd->cmd_cmd = CMD_DUMP | CMD_LAST; - dump_cmd->dump_offset = make16((dump_cmd + 1)); - dump_cmd->cmd_link = 0xffff; - - p->scb->cbl_offset = make16(dump_cmd); - p->scb->cmd_cuc = CUC_START; - ni_attn586(); - WAIT_4_STAT_COMPL(dump_cmd); - - if( (dump_cmd->cmd_status & (STAT_COMPL|STAT_OK)) != (STAT_COMPL|STAT_OK) ) - printk("%s: Can't get dump information.\n",dev->name); - - for(i=0;i<170;i++) { - printk("%02x ",(int) ((unsigned char *) (dump_cmd + 1))[i]); - if(i % 24 == 23) - printk("\n"); - } - printk("\n"); -} -#endif MODULE_LICENSE("GPL"); /* diff --git a/drivers/net/ni52.h b/drivers/net/ni52.h index a33ea0884aaf..1f28a4d1a319 100644 --- a/drivers/net/ni52.h +++ b/drivers/net/ni52.h @@ -36,12 +36,12 @@ struct scp_struct { - unsigned short zero_dum0; /* has to be zero */ - unsigned char sysbus; /* 0=16Bit,1=8Bit */ - unsigned char zero_dum1; /* has to be zero for 586 */ - unsigned short zero_dum2; - unsigned short zero_dum3; - char *iscp; /* pointer to the iscp-block */ + u16 zero_dum0; /* has to be zero */ + u8 sysbus; /* 0=16Bit,1=8Bit */ + u8 zero_dum1; /* has to be zero for 586 */ + u8 zero_dum2; + u8 zero_dum3; + u32 iscp; /* pointer to the iscp-block */ }; @@ -50,10 +50,10 @@ struct scp_struct */ struct iscp_struct { - unsigned char busy; /* 586 clears after successful init */ - unsigned char zero_dummy; /* has to be zero */ - unsigned short scb_offset; /* pointeroffset to the scb_base */ - char *scb_base; /* base-address of all 16-bit offsets */ + u8 busy; /* 586 clears after successful init */ + u8 zero_dummy; /* has to be zero */ + u16 scb_offset; /* pointeroffset to the scb_base */ + u32 scb_base; /* base-address of all 16-bit offsets */ }; /* @@ -61,16 +61,16 @@ struct iscp_struct */ struct scb_struct { - unsigned char rus; - unsigned char cus; - unsigned char cmd_ruc; /* command word: RU part */ - unsigned char cmd_cuc; /* command word: CU part & ACK */ - unsigned short cbl_offset; /* pointeroffset, command block list */ - unsigned short rfa_offset; /* pointeroffset, receive frame area */ - unsigned short crc_errs; /* CRC-Error counter */ - unsigned short aln_errs; /* alignmenterror counter */ - unsigned short rsc_errs; /* Resourceerror counter */ - unsigned short ovrn_errs; /* OVerrunerror counter */ + u8 rus; + u8 cus; + u8 cmd_ruc; /* command word: RU part */ + u8 cmd_cuc; /* command word: CU part & ACK */ + u16 cbl_offset; /* pointeroffset, command block list */ + u16 rfa_offset; /* pointeroffset, receive frame area */ + u16 crc_errs; /* CRC-Error counter */ + u16 aln_errs; /* alignmenterror counter */ + u16 rsc_errs; /* Resourceerror counter */ + u16 ovrn_errs; /* OVerrunerror counter */ }; /* @@ -119,16 +119,16 @@ struct scb_struct */ struct rfd_struct { - unsigned char stat_low; /* status word */ - unsigned char stat_high; /* status word */ - unsigned char rfd_sf; /* 82596 mode only */ - unsigned char last; /* Bit15,Last Frame on List / Bit14,suspend */ - unsigned short next; /* linkoffset to next RFD */ - unsigned short rbd_offset; /* pointeroffset to RBD-buffer */ - unsigned char dest[6]; /* ethernet-address, destination */ - unsigned char source[6]; /* ethernet-address, source */ - unsigned short length; /* 802.3 frame-length */ - unsigned short zero_dummy; /* dummy */ + u8 stat_low; /* status word */ + u8 stat_high; /* status word */ + u8 rfd_sf; /* 82596 mode only */ + u8 last; /* Bit15,Last Frame on List / Bit14,suspend */ + u16 next; /* linkoffset to next RFD */ + u16 rbd_offset; /* pointeroffset to RBD-buffer */ + u8 dest[6]; /* ethernet-address, destination */ + u8 source[6]; /* ethernet-address, source */ + u16 length; /* 802.3 frame-length */ + u16 zero_dummy; /* dummy */ }; #define RFD_LAST 0x80 /* last: last rfd in the list */ @@ -153,11 +153,11 @@ struct rfd_struct */ struct rbd_struct { - unsigned short status; /* status word,number of used bytes in buff */ - unsigned short next; /* pointeroffset to next RBD */ - char *buffer; /* receive buffer address pointer */ - unsigned short size; /* size of this buffer */ - unsigned short zero_dummy; /* dummy */ + u16 status; /* status word,number of used bytes in buff */ + u16 next; /* pointeroffset to next RBD */ + u32 buffer; /* receive buffer address pointer */ + u16 size; /* size of this buffer */ + u16 zero_dummy; /* dummy */ }; #define RBD_LAST 0x8000 /* last buffer */ @@ -195,9 +195,9 @@ struct rbd_struct */ struct nop_cmd_struct { - unsigned short cmd_status; /* status of this command */ - unsigned short cmd_cmd; /* the command itself (+bits) */ - unsigned short cmd_link; /* offsetpointer to next command */ + u16 cmd_status; /* status of this command */ + u16 cmd_cmd; /* the command itself (+bits) */ + u16 cmd_link; /* offsetpointer to next command */ }; /* @@ -205,10 +205,10 @@ struct nop_cmd_struct */ struct iasetup_cmd_struct { - unsigned short cmd_status; - unsigned short cmd_cmd; - unsigned short cmd_link; - unsigned char iaddr[6]; + u16 cmd_status; + u16 cmd_cmd; + u16 cmd_link; + u8 iaddr[6]; }; /* @@ -216,21 +216,21 @@ struct iasetup_cmd_struct */ struct configure_cmd_struct { - unsigned short cmd_status; - unsigned short cmd_cmd; - unsigned short cmd_link; - unsigned char byte_cnt; /* size of the config-cmd */ - unsigned char fifo; /* fifo/recv monitor */ - unsigned char sav_bf; /* save bad frames (bit7=1)*/ - unsigned char adr_len; /* adr_len(0-2),al_loc(3),pream(4-5),loopbak(6-7)*/ - unsigned char priority; /* lin_prio(0-2),exp_prio(4-6),bof_metd(7) */ - unsigned char ifs; /* inter frame spacing */ - unsigned char time_low; /* slot time low */ - unsigned char time_high; /* slot time high(0-2) and max. retries(4-7) */ - unsigned char promisc; /* promisc-mode(0) , et al (1-7) */ - unsigned char carr_coll; /* carrier(0-3)/collision(4-7) stuff */ - unsigned char fram_len; /* minimal frame len */ - unsigned char dummy; /* dummy */ + u16 cmd_status; + u16 cmd_cmd; + u16 cmd_link; + u8 byte_cnt; /* size of the config-cmd */ + u8 fifo; /* fifo/recv monitor */ + u8 sav_bf; /* save bad frames (bit7=1)*/ + u8 adr_len; /* adr_len(0-2),al_loc(3),pream(4-5),loopbak(6-7)*/ + u8 priority; /* lin_prio(0-2),exp_prio(4-6),bof_metd(7) */ + u8 ifs; /* inter frame spacing */ + u8 time_low; /* slot time low */ + u8 time_high; /* slot time high(0-2) and max. retries(4-7) */ + u8 promisc; /* promisc-mode(0) , et al (1-7) */ + u8 carr_coll; /* carrier(0-3)/collision(4-7) stuff */ + u8 fram_len; /* minimal frame len */ + u8 dummy; /* dummy */ }; /* @@ -238,11 +238,11 @@ struct configure_cmd_struct */ struct mcsetup_cmd_struct { - unsigned short cmd_status; - unsigned short cmd_cmd; - unsigned short cmd_link; - unsigned short mc_cnt; /* number of bytes in the MC-List */ - unsigned char mc_list[0][6]; /* pointer to 6 bytes entries */ + u16 cmd_status; + u16 cmd_cmd; + u16 cmd_link; + u16 mc_cnt; /* number of bytes in the MC-List */ + u8 mc_list[0][6]; /* pointer to 6 bytes entries */ }; /* @@ -250,10 +250,10 @@ struct mcsetup_cmd_struct */ struct dump_cmd_struct { - unsigned short cmd_status; - unsigned short cmd_cmd; - unsigned short cmd_link; - unsigned short dump_offset; /* pointeroffset to DUMP space */ + u16 cmd_status; + u16 cmd_cmd; + u16 cmd_link; + u16 dump_offset; /* pointeroffset to DUMP space */ }; /* @@ -261,12 +261,12 @@ struct dump_cmd_struct */ struct transmit_cmd_struct { - unsigned short cmd_status; - unsigned short cmd_cmd; - unsigned short cmd_link; - unsigned short tbd_offset; /* pointeroffset to TBD */ - unsigned char dest[6]; /* destination address of the frame */ - unsigned short length; /* user defined: 802.3 length / Ether type */ + u16 cmd_status; + u16 cmd_cmd; + u16 cmd_link; + u16 tbd_offset; /* pointeroffset to TBD */ + u8 dest[6]; /* destination address of the frame */ + u16 length; /* user defined: 802.3 length / Ether type */ }; #define TCMD_ERRMASK 0x0fa0 @@ -281,10 +281,10 @@ struct transmit_cmd_struct struct tdr_cmd_struct { - unsigned short cmd_status; - unsigned short cmd_cmd; - unsigned short cmd_link; - unsigned short status; + u16 cmd_status; + u16 cmd_cmd; + u16 cmd_link; + u16 status; }; #define TDR_LNK_OK 0x8000 /* No link problem identified */ @@ -298,9 +298,9 @@ struct tdr_cmd_struct */ struct tbd_struct { - unsigned short size; /* size + EOF-Flag(15) */ - unsigned short next; /* pointeroffset to next TBD */ - char *buffer; /* pointer to buffer */ + u16 size; /* size + EOF-Flag(15) */ + u16 next; /* pointeroffset to next TBD */ + u32 buffer; /* pointer to buffer */ }; #define TBD_LAST 0x8000 /* EOF-Flag, indicates last buffer in list */ diff --git a/drivers/net/niu.c b/drivers/net/niu.c index 2fe14b0c5c67..e98ce1e4965b 100644 --- a/drivers/net/niu.c +++ b/drivers/net/niu.c @@ -33,8 +33,8 @@ #define DRV_MODULE_NAME "niu" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "0.6" -#define DRV_MODULE_RELDATE "January 5, 2008" +#define DRV_MODULE_VERSION "0.7" +#define DRV_MODULE_RELDATE "February 18, 2008" static char version[] __devinitdata = DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; @@ -5147,7 +5147,12 @@ static void niu_set_rx_mode(struct net_device *dev) index++; } } else { - for (i = 0; i < niu_num_alt_addr(np); i++) { + int alt_start; + if (np->flags & NIU_FLAGS_XMAC) + alt_start = 0; + else + alt_start = 1; + for (i = alt_start; i < niu_num_alt_addr(np); i++) { err = niu_enable_alt_mac(np, i, 0); if (err) printk(KERN_WARNING PFX "%s: Error %d " diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c index f18eca9831e8..250eb1954c34 100644 --- a/drivers/net/pcmcia/smc91c92_cs.c +++ b/drivers/net/pcmcia/smc91c92_cs.c @@ -559,8 +559,16 @@ 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. */ - if (link->prod_id[3]) { - station_addr = link->prod_id[3]; + 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 (cvt_ascii_address(dev, station_addr) == 0) { rc = 0; goto free_cfg_mem; diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c index c4b74e9fed20..4eb322e5273d 100644 --- a/drivers/net/pcnet32.c +++ b/drivers/net/pcnet32.c @@ -174,7 +174,11 @@ static int homepna[MAX_UNITS]; #define RX_RING_SIZE (1 << (PCNET32_LOG_RX_BUFFERS)) #define RX_MAX_RING_SIZE (1 << (PCNET32_LOG_MAX_RX_BUFFERS)) -#define PKT_BUF_SZ 1544 +#define PKT_BUF_SKB 1544 +/* actual buffer length after being aligned */ +#define PKT_BUF_SIZE (PKT_BUF_SKB - NET_IP_ALIGN) +/* chip wants twos complement of the (aligned) buffer length */ +#define NEG_BUF_SIZE (NET_IP_ALIGN - PKT_BUF_SKB) /* Offsets from base I/O address. */ #define PCNET32_WIO_RDP 0x10 @@ -604,7 +608,7 @@ static void pcnet32_realloc_rx_ring(struct net_device *dev, /* now allocate any new buffers needed */ for (; new < size; new++ ) { struct sk_buff *rx_skbuff; - new_skb_list[new] = dev_alloc_skb(PKT_BUF_SZ); + new_skb_list[new] = dev_alloc_skb(PKT_BUF_SKB); if (!(rx_skbuff = new_skb_list[new])) { /* keep the original lists and buffers */ if (netif_msg_drv(lp)) @@ -613,20 +617,20 @@ static void pcnet32_realloc_rx_ring(struct net_device *dev, dev->name); goto free_all_new; } - skb_reserve(rx_skbuff, 2); + skb_reserve(rx_skbuff, NET_IP_ALIGN); new_dma_addr_list[new] = pci_map_single(lp->pci_dev, rx_skbuff->data, - PKT_BUF_SZ - 2, PCI_DMA_FROMDEVICE); + PKT_BUF_SIZE, PCI_DMA_FROMDEVICE); new_rx_ring[new].base = cpu_to_le32(new_dma_addr_list[new]); - new_rx_ring[new].buf_length = cpu_to_le16(2 - PKT_BUF_SZ); + new_rx_ring[new].buf_length = cpu_to_le16(NEG_BUF_SIZE); new_rx_ring[new].status = cpu_to_le16(0x8000); } /* and free any unneeded buffers */ for (; new < lp->rx_ring_size; new++) { if (lp->rx_skbuff[new]) { pci_unmap_single(lp->pci_dev, lp->rx_dma_addr[new], - PKT_BUF_SZ - 2, PCI_DMA_FROMDEVICE); + PKT_BUF_SIZE, PCI_DMA_FROMDEVICE); dev_kfree_skb(lp->rx_skbuff[new]); } } @@ -651,7 +655,7 @@ static void pcnet32_realloc_rx_ring(struct net_device *dev, for (; --new >= lp->rx_ring_size; ) { if (new_skb_list[new]) { pci_unmap_single(lp->pci_dev, new_dma_addr_list[new], - PKT_BUF_SZ - 2, PCI_DMA_FROMDEVICE); + PKT_BUF_SIZE, PCI_DMA_FROMDEVICE); dev_kfree_skb(new_skb_list[new]); } } @@ -678,7 +682,7 @@ static void pcnet32_purge_rx_ring(struct net_device *dev) wmb(); /* Make sure adapter sees owner change */ if (lp->rx_skbuff[i]) { pci_unmap_single(lp->pci_dev, lp->rx_dma_addr[i], - PKT_BUF_SZ - 2, PCI_DMA_FROMDEVICE); + PKT_BUF_SIZE, PCI_DMA_FROMDEVICE); dev_kfree_skb_any(lp->rx_skbuff[i]); } lp->rx_skbuff[i] = NULL; @@ -1201,7 +1205,7 @@ static void pcnet32_rx_entry(struct net_device *dev, pkt_len = (le32_to_cpu(rxp->msg_length) & 0xfff) - 4; /* Discard oversize frames. */ - if (unlikely(pkt_len > PKT_BUF_SZ - 2)) { + if (unlikely(pkt_len > PKT_BUF_SIZE)) { if (netif_msg_drv(lp)) printk(KERN_ERR "%s: Impossible packet size %d!\n", dev->name, pkt_len); @@ -1218,26 +1222,26 @@ static void pcnet32_rx_entry(struct net_device *dev, if (pkt_len > rx_copybreak) { struct sk_buff *newskb; - if ((newskb = dev_alloc_skb(PKT_BUF_SZ))) { - skb_reserve(newskb, 2); + if ((newskb = dev_alloc_skb(PKT_BUF_SKB))) { + skb_reserve(newskb, NET_IP_ALIGN); skb = lp->rx_skbuff[entry]; pci_unmap_single(lp->pci_dev, lp->rx_dma_addr[entry], - PKT_BUF_SZ - 2, + PKT_BUF_SIZE, PCI_DMA_FROMDEVICE); skb_put(skb, pkt_len); lp->rx_skbuff[entry] = newskb; lp->rx_dma_addr[entry] = pci_map_single(lp->pci_dev, newskb->data, - PKT_BUF_SZ - 2, + PKT_BUF_SIZE, PCI_DMA_FROMDEVICE); rxp->base = cpu_to_le32(lp->rx_dma_addr[entry]); rx_in_place = 1; } else skb = NULL; } else { - skb = dev_alloc_skb(pkt_len + 2); + skb = dev_alloc_skb(pkt_len + NET_IP_ALIGN); } if (skb == NULL) { @@ -1250,7 +1254,7 @@ static void pcnet32_rx_entry(struct net_device *dev, } skb->dev = dev; if (!rx_in_place) { - skb_reserve(skb, 2); /* 16 byte align */ + skb_reserve(skb, NET_IP_ALIGN); skb_put(skb, pkt_len); /* Make room */ pci_dma_sync_single_for_cpu(lp->pci_dev, lp->rx_dma_addr[entry], @@ -1291,7 +1295,7 @@ static int pcnet32_rx(struct net_device *dev, int budget) * The docs say that the buffer length isn't touched, but Andrew * Boyd of QNX reports that some revs of the 79C965 clear it. */ - rxp->buf_length = cpu_to_le16(2 - PKT_BUF_SZ); + rxp->buf_length = cpu_to_le16(NEG_BUF_SIZE); wmb(); /* Make sure owner changes after others are visible */ rxp->status = cpu_to_le16(0x8000); entry = (++lp->cur_rx) & lp->rx_mod_mask; @@ -1774,8 +1778,8 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) memset(dev->dev_addr, 0, sizeof(dev->dev_addr)); if (pcnet32_debug & NETIF_MSG_PROBE) { - for (i = 0; i < 6; i++) - printk(" %2.2x", dev->dev_addr[i]); + DECLARE_MAC_BUF(mac); + printk(" %s", print_mac(mac, dev->dev_addr)); /* Version 0x2623 and 0x2624 */ if (((chip_version + 1) & 0xfffe) == 0x2624) { @@ -2396,7 +2400,7 @@ static int pcnet32_init_ring(struct net_device *dev) if (rx_skbuff == NULL) { if (! (rx_skbuff = lp->rx_skbuff[i] = - dev_alloc_skb(PKT_BUF_SZ))) { + dev_alloc_skb(PKT_BUF_SKB))) { /* there is not much, we can do at this point */ if (netif_msg_drv(lp)) printk(KERN_ERR @@ -2404,16 +2408,16 @@ static int pcnet32_init_ring(struct net_device *dev) dev->name); return -1; } - skb_reserve(rx_skbuff, 2); + skb_reserve(rx_skbuff, NET_IP_ALIGN); } rmb(); if (lp->rx_dma_addr[i] == 0) lp->rx_dma_addr[i] = pci_map_single(lp->pci_dev, rx_skbuff->data, - PKT_BUF_SZ - 2, PCI_DMA_FROMDEVICE); + PKT_BUF_SIZE, PCI_DMA_FROMDEVICE); lp->rx_ring[i].base = cpu_to_le32(lp->rx_dma_addr[i]); - lp->rx_ring[i].buf_length = cpu_to_le16(2 - PKT_BUF_SZ); + lp->rx_ring[i].buf_length = cpu_to_le16(NEG_BUF_SIZE); wmb(); /* Make sure owner changes after all others are visible */ lp->rx_ring[i].status = cpu_to_le16(0x8000); } diff --git a/drivers/net/phy/fixed.c b/drivers/net/phy/fixed.c index 73b6d39ef6b0..ca9b040f9ad9 100644 --- a/drivers/net/phy/fixed.c +++ b/drivers/net/phy/fixed.c @@ -236,12 +236,12 @@ module_init(fixed_mdio_bus_init); static void __exit fixed_mdio_bus_exit(void) { struct fixed_mdio_bus *fmb = &platform_fmb; - struct fixed_phy *fp; + struct fixed_phy *fp, *tmp; mdiobus_unregister(&fmb->mii_bus); platform_device_unregister(pdev); - list_for_each_entry(fp, &fmb->phys, node) { + list_for_each_entry_safe(fp, tmp, &fmb->phys, node) { list_del(&fp->node); kfree(fp); } diff --git a/drivers/net/ps3_gelic_net.c b/drivers/net/ps3_gelic_net.c index 055af081e027..7eb6e7e848f4 100644 --- a/drivers/net/ps3_gelic_net.c +++ b/drivers/net/ps3_gelic_net.c @@ -46,29 +46,25 @@ #include #include "ps3_gelic_net.h" +#include "ps3_gelic_wireless.h" #define DRV_NAME "Gelic Network Driver" -#define DRV_VERSION "1.0" +#define DRV_VERSION "2.0" MODULE_AUTHOR("SCE Inc."); MODULE_DESCRIPTION("Gelic Network driver"); MODULE_LICENSE("GPL"); -static inline struct device *ctodev(struct gelic_net_card *card) -{ - return &card->dev->core; -} -static inline u64 bus_id(struct gelic_net_card *card) -{ - return card->dev->bus_id; -} -static inline u64 dev_id(struct gelic_net_card *card) -{ - return card->dev->dev_id; -} + +static inline void gelic_card_enable_rxdmac(struct gelic_card *card); +static inline void gelic_card_disable_rxdmac(struct gelic_card *card); +static inline void gelic_card_disable_txdmac(struct gelic_card *card); +static inline void gelic_card_reset_chain(struct gelic_card *card, + struct gelic_descr_chain *chain, + struct gelic_descr *start_descr); /* set irq_mask */ -static int gelic_net_set_irq_mask(struct gelic_net_card *card, u64 mask) +int gelic_card_set_irq_mask(struct gelic_card *card, u64 mask) { int status; @@ -76,54 +72,110 @@ static int gelic_net_set_irq_mask(struct gelic_net_card *card, u64 mask) mask, 0); if (status) dev_info(ctodev(card), - "lv1_net_set_interrupt_mask failed %d\n", status); + "%s failed %d\n", __func__, status); return status; } -static inline void gelic_net_rx_irq_on(struct gelic_net_card *card) + +static inline void gelic_card_rx_irq_on(struct gelic_card *card) { - gelic_net_set_irq_mask(card, card->ghiintmask | GELIC_NET_RXINT); + card->irq_mask |= GELIC_CARD_RXINT; + gelic_card_set_irq_mask(card, card->irq_mask); } -static inline void gelic_net_rx_irq_off(struct gelic_net_card *card) +static inline void gelic_card_rx_irq_off(struct gelic_card *card) { - gelic_net_set_irq_mask(card, card->ghiintmask & ~GELIC_NET_RXINT); + card->irq_mask &= ~GELIC_CARD_RXINT; + gelic_card_set_irq_mask(card, card->irq_mask); } + +static void gelic_card_get_ether_port_status(struct gelic_card *card, + int inform) +{ + u64 v2; + struct net_device *ether_netdev; + + lv1_net_control(bus_id(card), dev_id(card), + GELIC_LV1_GET_ETH_PORT_STATUS, + GELIC_LV1_VLAN_TX_ETHERNET, 0, 0, + &card->ether_port_status, &v2); + + if (inform) { + ether_netdev = card->netdev[GELIC_PORT_ETHERNET]; + if (card->ether_port_status & GELIC_LV1_ETHER_LINK_UP) + netif_carrier_on(ether_netdev); + else + netif_carrier_off(ether_netdev); + } +} + +void gelic_card_up(struct gelic_card *card) +{ + pr_debug("%s: called\n", __func__); + down(&card->updown_lock); + if (atomic_inc_return(&card->users) == 1) { + pr_debug("%s: real do\n", __func__); + /* enable irq */ + gelic_card_set_irq_mask(card, card->irq_mask); + /* start rx */ + gelic_card_enable_rxdmac(card); + + napi_enable(&card->napi); + } + up(&card->updown_lock); + pr_debug("%s: done\n", __func__); +} + +void gelic_card_down(struct gelic_card *card) +{ + u64 mask; + pr_debug("%s: called\n", __func__); + down(&card->updown_lock); + if (atomic_dec_if_positive(&card->users) == 0) { + pr_debug("%s: real do\n", __func__); + napi_disable(&card->napi); + /* + * Disable irq. Wireless interrupts will + * be disabled later if any + */ + mask = card->irq_mask & (GELIC_CARD_WLAN_EVENT_RECEIVED | + GELIC_CARD_WLAN_COMMAND_COMPLETED); + gelic_card_set_irq_mask(card, mask); + /* stop rx */ + gelic_card_disable_rxdmac(card); + gelic_card_reset_chain(card, &card->rx_chain, + card->descr + GELIC_NET_TX_DESCRIPTORS); + /* stop tx */ + gelic_card_disable_txdmac(card); + } + up(&card->updown_lock); + pr_debug("%s: done\n", __func__); +} + /** - * gelic_net_get_descr_status -- returns the status of a descriptor + * gelic_descr_get_status -- returns the status of a descriptor * @descr: descriptor to look at * * returns the status as in the dmac_cmd_status field of the descriptor */ -static enum gelic_net_descr_status -gelic_net_get_descr_status(struct gelic_net_descr *descr) +static enum gelic_descr_dma_status +gelic_descr_get_status(struct gelic_descr *descr) { - u32 cmd_status; - - cmd_status = descr->dmac_cmd_status; - cmd_status >>= GELIC_NET_DESCR_IND_PROC_SHIFT; - return cmd_status; + return be32_to_cpu(descr->dmac_cmd_status) & GELIC_DESCR_DMA_STAT_MASK; } /** - * gelic_net_set_descr_status -- sets the status of a descriptor + * gelic_descr_set_status -- sets the status of a descriptor * @descr: descriptor to change * @status: status to set in the descriptor * * changes the status to the specified value. Doesn't change other bits * in the status */ -static void gelic_net_set_descr_status(struct gelic_net_descr *descr, - enum gelic_net_descr_status status) +static void gelic_descr_set_status(struct gelic_descr *descr, + enum gelic_descr_dma_status status) { - u32 cmd_status; - - /* read the status */ - cmd_status = descr->dmac_cmd_status; - /* clean the upper 4 bits */ - cmd_status &= GELIC_NET_DESCR_IND_PROC_MASKO; - /* add the status to it */ - cmd_status |= ((u32)status) << GELIC_NET_DESCR_IND_PROC_SHIFT; - /* and write it back */ - descr->dmac_cmd_status = cmd_status; + descr->dmac_cmd_status = cpu_to_be32(status | + (be32_to_cpu(descr->dmac_cmd_status) & + ~GELIC_DESCR_DMA_STAT_MASK)); /* * dma_cmd_status field is used to indicate whether the descriptor * is valid or not. @@ -134,24 +186,24 @@ static void gelic_net_set_descr_status(struct gelic_net_descr *descr, } /** - * gelic_net_free_chain - free descriptor chain + * gelic_card_free_chain - free descriptor chain * @card: card structure * @descr_in: address of desc */ -static void gelic_net_free_chain(struct gelic_net_card *card, - struct gelic_net_descr *descr_in) +static void gelic_card_free_chain(struct gelic_card *card, + struct gelic_descr *descr_in) { - struct gelic_net_descr *descr; + struct gelic_descr *descr; for (descr = descr_in; descr && descr->bus_addr; descr = descr->next) { dma_unmap_single(ctodev(card), descr->bus_addr, - GELIC_NET_DESCR_SIZE, DMA_BIDIRECTIONAL); + GELIC_DESCR_SIZE, DMA_BIDIRECTIONAL); descr->bus_addr = 0; } } /** - * gelic_net_init_chain - links descriptor chain + * gelic_card_init_chain - links descriptor chain * @card: card structure * @chain: address of chain * @start_descr: address of descriptor array @@ -162,22 +214,22 @@ static void gelic_net_free_chain(struct gelic_net_card *card, * * returns 0 on success, <0 on failure */ -static int gelic_net_init_chain(struct gelic_net_card *card, - struct gelic_net_descr_chain *chain, - struct gelic_net_descr *start_descr, int no) +static int gelic_card_init_chain(struct gelic_card *card, + struct gelic_descr_chain *chain, + struct gelic_descr *start_descr, int no) { int i; - struct gelic_net_descr *descr; + struct gelic_descr *descr; descr = start_descr; memset(descr, 0, sizeof(*descr) * no); /* set up the hardware pointers in each descriptor */ for (i = 0; i < no; i++, descr++) { - gelic_net_set_descr_status(descr, GELIC_NET_DESCR_NOT_IN_USE); + gelic_descr_set_status(descr, GELIC_DESCR_DMA_NOT_IN_USE); descr->bus_addr = dma_map_single(ctodev(card), descr, - GELIC_NET_DESCR_SIZE, + GELIC_DESCR_SIZE, DMA_BIDIRECTIONAL); if (!descr->bus_addr) @@ -193,7 +245,7 @@ static int gelic_net_init_chain(struct gelic_net_card *card, /* chain bus addr of hw descriptor */ descr = start_descr; for (i = 0; i < no; i++, descr++) { - descr->next_descr_addr = descr->next->bus_addr; + descr->next_descr_addr = cpu_to_be32(descr->next->bus_addr); } chain->head = start_descr; @@ -208,13 +260,38 @@ iommu_error: for (i--, descr--; 0 <= i; i--, descr--) if (descr->bus_addr) dma_unmap_single(ctodev(card), descr->bus_addr, - GELIC_NET_DESCR_SIZE, + GELIC_DESCR_SIZE, DMA_BIDIRECTIONAL); return -ENOMEM; } /** - * gelic_net_prepare_rx_descr - reinitializes a rx descriptor + * gelic_card_reset_chain - reset status of a descriptor chain + * @card: card structure + * @chain: address of chain + * @start_descr: address of descriptor array + * + * Reset the status of dma descriptors to ready state + * and re-initialize the hardware chain for later use + */ +static void gelic_card_reset_chain(struct gelic_card *card, + struct gelic_descr_chain *chain, + struct gelic_descr *start_descr) +{ + struct gelic_descr *descr; + + for (descr = start_descr; start_descr != descr->next; descr++) { + gelic_descr_set_status(descr, GELIC_DESCR_DMA_CARDOWNED); + descr->next_descr_addr = cpu_to_be32(descr->next->bus_addr); + } + + chain->head = start_descr; + chain->tail = (descr - 1); + + (descr - 1)->next_descr_addr = 0; +} +/** + * gelic_descr_prepare_rx - reinitializes a rx descriptor * @card: card structure * @descr: descriptor to re-init * @@ -223,29 +300,27 @@ iommu_error: * allocates a new rx skb, iommu-maps it and attaches it to the descriptor. * Activate the descriptor state-wise */ -static int gelic_net_prepare_rx_descr(struct gelic_net_card *card, - struct gelic_net_descr *descr) +static int gelic_descr_prepare_rx(struct gelic_card *card, + struct gelic_descr *descr) { int offset; unsigned int bufsize; - if (gelic_net_get_descr_status(descr) != GELIC_NET_DESCR_NOT_IN_USE) { + if (gelic_descr_get_status(descr) != GELIC_DESCR_DMA_NOT_IN_USE) dev_info(ctodev(card), "%s: ERROR status \n", __func__); - } /* we need to round up the buffer size to a multiple of 128 */ bufsize = ALIGN(GELIC_NET_MAX_MTU, GELIC_NET_RXBUF_ALIGN); /* and we need to have it 128 byte aligned, therefore we allocate a * bit more */ - descr->skb = netdev_alloc_skb(card->netdev, - bufsize + GELIC_NET_RXBUF_ALIGN - 1); + descr->skb = dev_alloc_skb(bufsize + GELIC_NET_RXBUF_ALIGN - 1); if (!descr->skb) { descr->buf_addr = 0; /* tell DMAC don't touch memory */ dev_info(ctodev(card), "%s:allocate skb failed !!\n", __func__); return -ENOMEM; } - descr->buf_size = bufsize; + descr->buf_size = cpu_to_be32(bufsize); descr->dmac_cmd_status = 0; descr->result_size = 0; descr->valid_size = 0; @@ -256,63 +331,64 @@ static int gelic_net_prepare_rx_descr(struct gelic_net_card *card, if (offset) skb_reserve(descr->skb, GELIC_NET_RXBUF_ALIGN - offset); /* io-mmu-map the skb */ - descr->buf_addr = dma_map_single(ctodev(card), descr->skb->data, - GELIC_NET_MAX_MTU, - DMA_FROM_DEVICE); + descr->buf_addr = cpu_to_be32(dma_map_single(ctodev(card), + descr->skb->data, + GELIC_NET_MAX_MTU, + DMA_FROM_DEVICE)); if (!descr->buf_addr) { dev_kfree_skb_any(descr->skb); descr->skb = NULL; dev_info(ctodev(card), "%s:Could not iommu-map rx buffer\n", __func__); - gelic_net_set_descr_status(descr, GELIC_NET_DESCR_NOT_IN_USE); + gelic_descr_set_status(descr, GELIC_DESCR_DMA_NOT_IN_USE); return -ENOMEM; } else { - gelic_net_set_descr_status(descr, GELIC_NET_DESCR_CARDOWNED); + gelic_descr_set_status(descr, GELIC_DESCR_DMA_CARDOWNED); return 0; } } /** - * gelic_net_release_rx_chain - free all skb of rx descr + * gelic_card_release_rx_chain - free all skb of rx descr * @card: card structure * */ -static void gelic_net_release_rx_chain(struct gelic_net_card *card) +static void gelic_card_release_rx_chain(struct gelic_card *card) { - struct gelic_net_descr *descr = card->rx_chain.head; + struct gelic_descr *descr = card->rx_chain.head; do { if (descr->skb) { dma_unmap_single(ctodev(card), - descr->buf_addr, + be32_to_cpu(descr->buf_addr), descr->skb->len, DMA_FROM_DEVICE); descr->buf_addr = 0; dev_kfree_skb_any(descr->skb); descr->skb = NULL; - gelic_net_set_descr_status(descr, - GELIC_NET_DESCR_NOT_IN_USE); + gelic_descr_set_status(descr, + GELIC_DESCR_DMA_NOT_IN_USE); } descr = descr->next; } while (descr != card->rx_chain.head); } /** - * gelic_net_fill_rx_chain - fills descriptors/skbs in the rx chains + * gelic_card_fill_rx_chain - fills descriptors/skbs in the rx chains * @card: card structure * * fills all descriptors in the rx chain: allocates skbs * and iommu-maps them. - * returns 0 on success, <0 on failure + * returns 0 on success, < 0 on failure */ -static int gelic_net_fill_rx_chain(struct gelic_net_card *card) +static int gelic_card_fill_rx_chain(struct gelic_card *card) { - struct gelic_net_descr *descr = card->rx_chain.head; + struct gelic_descr *descr = card->rx_chain.head; int ret; do { if (!descr->skb) { - ret = gelic_net_prepare_rx_descr(card, descr); + ret = gelic_descr_prepare_rx(card, descr); if (ret) goto rewind; } @@ -321,41 +397,41 @@ static int gelic_net_fill_rx_chain(struct gelic_net_card *card) return 0; rewind: - gelic_net_release_rx_chain(card); + gelic_card_release_rx_chain(card); return ret; } /** - * gelic_net_alloc_rx_skbs - allocates rx skbs in rx descriptor chains + * gelic_card_alloc_rx_skbs - allocates rx skbs in rx descriptor chains * @card: card structure * - * returns 0 on success, <0 on failure + * returns 0 on success, < 0 on failure */ -static int gelic_net_alloc_rx_skbs(struct gelic_net_card *card) +static int gelic_card_alloc_rx_skbs(struct gelic_card *card) { - struct gelic_net_descr_chain *chain; + struct gelic_descr_chain *chain; int ret; chain = &card->rx_chain; - ret = gelic_net_fill_rx_chain(card); - chain->head = card->rx_top->prev; /* point to the last */ + ret = gelic_card_fill_rx_chain(card); + chain->tail = card->rx_top->prev; /* point to the last */ return ret; } /** - * gelic_net_release_tx_descr - processes a used tx descriptor + * gelic_descr_release_tx - processes a used tx descriptor * @card: card structure * @descr: descriptor to release * * releases a used tx descriptor (unmapping, freeing of skb) */ -static void gelic_net_release_tx_descr(struct gelic_net_card *card, - struct gelic_net_descr *descr) +static void gelic_descr_release_tx(struct gelic_card *card, + struct gelic_descr *descr) { struct sk_buff *skb = descr->skb; - BUG_ON(!(descr->data_status & (1 << GELIC_NET_TXDESC_TAIL))); + BUG_ON(!(be32_to_cpu(descr->data_status) & GELIC_DESCR_TX_TAIL)); - dma_unmap_single(ctodev(card), descr->buf_addr, skb->len, + dma_unmap_single(ctodev(card), be32_to_cpu(descr->buf_addr), skb->len, DMA_TO_DEVICE); dev_kfree_skb_any(skb); @@ -369,59 +445,75 @@ static void gelic_net_release_tx_descr(struct gelic_net_card *card, descr->skb = NULL; /* set descr status */ - gelic_net_set_descr_status(descr, GELIC_NET_DESCR_NOT_IN_USE); + gelic_descr_set_status(descr, GELIC_DESCR_DMA_NOT_IN_USE); } +static void gelic_card_stop_queues(struct gelic_card *card) +{ + netif_stop_queue(card->netdev[GELIC_PORT_ETHERNET]); + + if (card->netdev[GELIC_PORT_WIRELESS]) + netif_stop_queue(card->netdev[GELIC_PORT_WIRELESS]); +} +static void gelic_card_wake_queues(struct gelic_card *card) +{ + netif_wake_queue(card->netdev[GELIC_PORT_ETHERNET]); + + if (card->netdev[GELIC_PORT_WIRELESS]) + netif_wake_queue(card->netdev[GELIC_PORT_WIRELESS]); +} /** - * gelic_net_release_tx_chain - processes sent tx descriptors + * gelic_card_release_tx_chain - processes sent tx descriptors * @card: adapter structure * @stop: net_stop sequence * * releases the tx descriptors that gelic has finished with */ -static void gelic_net_release_tx_chain(struct gelic_net_card *card, int stop) +static void gelic_card_release_tx_chain(struct gelic_card *card, int stop) { - struct gelic_net_descr_chain *tx_chain; - enum gelic_net_descr_status status; + struct gelic_descr_chain *tx_chain; + enum gelic_descr_dma_status status; + struct net_device *netdev; int release = 0; for (tx_chain = &card->tx_chain; tx_chain->head != tx_chain->tail && tx_chain->tail; tx_chain->tail = tx_chain->tail->next) { - status = gelic_net_get_descr_status(tx_chain->tail); + status = gelic_descr_get_status(tx_chain->tail); + netdev = tx_chain->tail->skb->dev; switch (status) { - case GELIC_NET_DESCR_RESPONSE_ERROR: - case GELIC_NET_DESCR_PROTECTION_ERROR: - case GELIC_NET_DESCR_FORCE_END: + case GELIC_DESCR_DMA_RESPONSE_ERROR: + case GELIC_DESCR_DMA_PROTECTION_ERROR: + case GELIC_DESCR_DMA_FORCE_END: if (printk_ratelimit()) dev_info(ctodev(card), "%s: forcing end of tx descriptor " \ "with status %x\n", __func__, status); - card->netdev->stats.tx_dropped++; + netdev->stats.tx_dropped++; break; - case GELIC_NET_DESCR_COMPLETE: + case GELIC_DESCR_DMA_COMPLETE: if (tx_chain->tail->skb) { - card->netdev->stats.tx_packets++; - card->netdev->stats.tx_bytes += + netdev->stats.tx_packets++; + netdev->stats.tx_bytes += tx_chain->tail->skb->len; } break; - case GELIC_NET_DESCR_CARDOWNED: + case GELIC_DESCR_DMA_CARDOWNED: /* pending tx request */ default: - /* any other value (== GELIC_NET_DESCR_NOT_IN_USE) */ + /* any other value (== GELIC_DESCR_DMA_NOT_IN_USE) */ if (!stop) goto out; } - gelic_net_release_tx_descr(card, tx_chain->tail); + gelic_descr_release_tx(card, tx_chain->tail); release ++; } out: if (!stop && release) - netif_wake_queue(card->netdev); + gelic_card_wake_queues(card); } /** @@ -432,9 +524,9 @@ out: * netdev interface. It also sets up multicast, allmulti and promisc * flags appropriately */ -static void gelic_net_set_multi(struct net_device *netdev) +void gelic_net_set_multi(struct net_device *netdev) { - struct gelic_net_card *card = netdev_priv(netdev); + struct gelic_card *card = netdev_card(netdev); struct dev_mc_list *mc; unsigned int i; uint8_t *p; @@ -456,8 +548,8 @@ static void gelic_net_set_multi(struct net_device *netdev) "lv1_net_add_multicast_address failed, %d\n", status); - if (netdev->flags & IFF_ALLMULTI - || netdev->mc_count > GELIC_NET_MC_COUNT_MAX) { /* list max */ + if ((netdev->flags & IFF_ALLMULTI) || + (netdev->mc_count > GELIC_NET_MC_COUNT_MAX)) { status = lv1_net_add_multicast_address(bus_id(card), dev_id(card), 0, 1); @@ -468,7 +560,7 @@ static void gelic_net_set_multi(struct net_device *netdev) return; } - /* set multicast address */ + /* set multicast addresses */ for (mc = netdev->mc_list; mc; mc = mc->next) { addr = 0; p = mc->dmi_addr; @@ -487,31 +579,42 @@ static void gelic_net_set_multi(struct net_device *netdev) } /** - * gelic_net_enable_rxdmac - enables the receive DMA controller + * gelic_card_enable_rxdmac - enables the receive DMA controller * @card: card structure * - * gelic_net_enable_rxdmac enables the DMA controller by setting RX_DMA_EN + * gelic_card_enable_rxdmac enables the DMA controller by setting RX_DMA_EN * in the GDADMACCNTR register */ -static inline void gelic_net_enable_rxdmac(struct gelic_net_card *card) +static inline void gelic_card_enable_rxdmac(struct gelic_card *card) { int status; +#ifdef DEBUG + if (gelic_descr_get_status(card->rx_chain.head) != + GELIC_DESCR_DMA_CARDOWNED) { + printk(KERN_ERR "%s: status=%x\n", __func__, + be32_to_cpu(card->rx_chain.head->dmac_cmd_status)); + printk(KERN_ERR "%s: nextphy=%x\n", __func__, + be32_to_cpu(card->rx_chain.head->next_descr_addr)); + printk(KERN_ERR "%s: head=%p\n", __func__, + card->rx_chain.head); + } +#endif status = lv1_net_start_rx_dma(bus_id(card), dev_id(card), - card->rx_chain.tail->bus_addr, 0); + card->rx_chain.head->bus_addr, 0); if (status) dev_info(ctodev(card), "lv1_net_start_rx_dma failed, status=%d\n", status); } /** - * gelic_net_disable_rxdmac - disables the receive DMA controller + * gelic_card_disable_rxdmac - disables the receive DMA controller * @card: card structure * - * gelic_net_disable_rxdmac terminates processing on the DMA controller by + * gelic_card_disable_rxdmac terminates processing on the DMA controller by * turing off DMA and issueing a force end */ -static inline void gelic_net_disable_rxdmac(struct gelic_net_card *card) +static inline void gelic_card_disable_rxdmac(struct gelic_card *card) { int status; @@ -523,13 +626,13 @@ static inline void gelic_net_disable_rxdmac(struct gelic_net_card *card) } /** - * gelic_net_disable_txdmac - disables the transmit DMA controller + * gelic_card_disable_txdmac - disables the transmit DMA controller * @card: card structure * - * gelic_net_disable_txdmac terminates processing on the DMA controller by + * gelic_card_disable_txdmac terminates processing on the DMA controller by * turing off DMA and issueing a force end */ -static inline void gelic_net_disable_txdmac(struct gelic_net_card *card) +static inline void gelic_card_disable_txdmac(struct gelic_card *card) { int status; @@ -546,51 +649,37 @@ static inline void gelic_net_disable_txdmac(struct gelic_net_card *card) * * always returns 0 */ -static int gelic_net_stop(struct net_device *netdev) +int gelic_net_stop(struct net_device *netdev) { - struct gelic_net_card *card = netdev_priv(netdev); + struct gelic_card *card; + + pr_debug("%s: start\n", __func__); - napi_disable(&card->napi); netif_stop_queue(netdev); - - /* turn off DMA, force end */ - gelic_net_disable_rxdmac(card); - gelic_net_disable_txdmac(card); - - gelic_net_set_irq_mask(card, 0); - - /* disconnect event port */ - free_irq(card->netdev->irq, card->netdev); - ps3_sb_event_receive_port_destroy(card->dev, card->netdev->irq); - card->netdev->irq = NO_IRQ; - netif_carrier_off(netdev); - /* release chains */ - gelic_net_release_tx_chain(card, 1); - gelic_net_release_rx_chain(card); - - gelic_net_free_chain(card, card->tx_top); - gelic_net_free_chain(card, card->rx_top); + card = netdev_card(netdev); + gelic_card_down(card); + pr_debug("%s: done\n", __func__); return 0; } /** - * gelic_net_get_next_tx_descr - returns the next available tx descriptor + * gelic_card_get_next_tx_descr - returns the next available tx descriptor * @card: device structure to get descriptor from * * returns the address of the next descriptor, or NULL if not available. */ -static struct gelic_net_descr * -gelic_net_get_next_tx_descr(struct gelic_net_card *card) +static struct gelic_descr * +gelic_card_get_next_tx_descr(struct gelic_card *card) { if (!card->tx_chain.head) return NULL; /* see if the next descriptor is free */ if (card->tx_chain.tail != card->tx_chain.head->next && - gelic_net_get_descr_status(card->tx_chain.head) == - GELIC_NET_DESCR_NOT_IN_USE) + gelic_descr_get_status(card->tx_chain.head) == + GELIC_DESCR_DMA_NOT_IN_USE) return card->tx_chain.head; else return NULL; @@ -606,32 +695,33 @@ gelic_net_get_next_tx_descr(struct gelic_net_card *card) * depending on hardware checksum settings. This function assumes a wmb() * has executed before. */ -static void gelic_net_set_txdescr_cmdstat(struct gelic_net_descr *descr, - struct sk_buff *skb) +static void gelic_descr_set_tx_cmdstat(struct gelic_descr *descr, + struct sk_buff *skb) { if (skb->ip_summed != CHECKSUM_PARTIAL) - descr->dmac_cmd_status = GELIC_NET_DMAC_CMDSTAT_NOCS | - GELIC_NET_DMAC_CMDSTAT_END_FRAME; + descr->dmac_cmd_status = + cpu_to_be32(GELIC_DESCR_DMA_CMD_NO_CHKSUM | + GELIC_DESCR_TX_DMA_FRAME_TAIL); else { /* is packet ip? * if yes: tcp? udp? */ if (skb->protocol == htons(ETH_P_IP)) { if (ip_hdr(skb)->protocol == IPPROTO_TCP) descr->dmac_cmd_status = - GELIC_NET_DMAC_CMDSTAT_TCPCS | - GELIC_NET_DMAC_CMDSTAT_END_FRAME; + cpu_to_be32(GELIC_DESCR_DMA_CMD_TCP_CHKSUM | + GELIC_DESCR_TX_DMA_FRAME_TAIL); else if (ip_hdr(skb)->protocol == IPPROTO_UDP) descr->dmac_cmd_status = - GELIC_NET_DMAC_CMDSTAT_UDPCS | - GELIC_NET_DMAC_CMDSTAT_END_FRAME; + cpu_to_be32(GELIC_DESCR_DMA_CMD_UDP_CHKSUM | + GELIC_DESCR_TX_DMA_FRAME_TAIL); else /* * the stack should checksum non-tcp and non-udp * packets on his own: NETIF_F_IP_CSUM */ descr->dmac_cmd_status = - GELIC_NET_DMAC_CMDSTAT_NOCS | - GELIC_NET_DMAC_CMDSTAT_END_FRAME; + cpu_to_be32(GELIC_DESCR_DMA_CMD_NO_CHKSUM | + GELIC_DESCR_TX_DMA_FRAME_TAIL); } } } @@ -662,7 +752,7 @@ static inline struct sk_buff *gelic_put_vlan_tag(struct sk_buff *skb, } /** - * gelic_net_prepare_tx_descr_v - get dma address of skb_data + * gelic_descr_prepare_tx - setup a descriptor for sending packets * @card: card structure * @descr: descriptor structure * @skb: packet to use @@ -670,16 +760,19 @@ static inline struct sk_buff *gelic_put_vlan_tag(struct sk_buff *skb, * returns 0 on success, <0 on failure. * */ -static int gelic_net_prepare_tx_descr_v(struct gelic_net_card *card, - struct gelic_net_descr *descr, - struct sk_buff *skb) +static int gelic_descr_prepare_tx(struct gelic_card *card, + struct gelic_descr *descr, + struct sk_buff *skb) { dma_addr_t buf; - if (card->vlan_index != -1) { + if (card->vlan_required) { struct sk_buff *skb_tmp; + enum gelic_port_type type; + + type = netdev_port(skb->dev)->type; skb_tmp = gelic_put_vlan_tag(skb, - card->vlan_id[card->vlan_index]); + card->vlan[type].tx); if (!skb_tmp) return -ENOMEM; skb = skb_tmp; @@ -694,12 +787,12 @@ static int gelic_net_prepare_tx_descr_v(struct gelic_net_card *card, return -ENOMEM; } - descr->buf_addr = buf; - descr->buf_size = skb->len; + descr->buf_addr = cpu_to_be32(buf); + descr->buf_size = cpu_to_be32(skb->len); descr->skb = skb; descr->data_status = 0; descr->next_descr_addr = 0; /* terminate hw descr */ - gelic_net_set_txdescr_cmdstat(descr, skb); + gelic_descr_set_tx_cmdstat(descr, skb); /* bump free descriptor pointer */ card->tx_chain.head = descr->next; @@ -707,20 +800,20 @@ static int gelic_net_prepare_tx_descr_v(struct gelic_net_card *card, } /** - * gelic_net_kick_txdma - enables TX DMA processing + * gelic_card_kick_txdma - enables TX DMA processing * @card: card structure * @descr: descriptor address to enable TX processing at * */ -static int gelic_net_kick_txdma(struct gelic_net_card *card, - struct gelic_net_descr *descr) +static int gelic_card_kick_txdma(struct gelic_card *card, + struct gelic_descr *descr) { int status = 0; if (card->tx_dma_progress) return 0; - if (gelic_net_get_descr_status(descr) == GELIC_NET_DESCR_CARDOWNED) { + if (gelic_descr_get_status(descr) == GELIC_DESCR_DMA_CARDOWNED) { card->tx_dma_progress = 1; status = lv1_net_start_tx_dma(bus_id(card), dev_id(card), descr->bus_addr, 0); @@ -738,56 +831,56 @@ static int gelic_net_kick_txdma(struct gelic_net_card *card, * * returns 0 on success, <0 on failure */ -static int gelic_net_xmit(struct sk_buff *skb, struct net_device *netdev) +int gelic_net_xmit(struct sk_buff *skb, struct net_device *netdev) { - struct gelic_net_card *card = netdev_priv(netdev); - struct gelic_net_descr *descr; + struct gelic_card *card = netdev_card(netdev); + struct gelic_descr *descr; int result; unsigned long flags; - spin_lock_irqsave(&card->tx_dma_lock, flags); + spin_lock_irqsave(&card->tx_lock, flags); - gelic_net_release_tx_chain(card, 0); + gelic_card_release_tx_chain(card, 0); - descr = gelic_net_get_next_tx_descr(card); + descr = gelic_card_get_next_tx_descr(card); if (!descr) { /* * no more descriptors free */ - netif_stop_queue(netdev); - spin_unlock_irqrestore(&card->tx_dma_lock, flags); + gelic_card_stop_queues(card); + spin_unlock_irqrestore(&card->tx_lock, flags); return NETDEV_TX_BUSY; } - result = gelic_net_prepare_tx_descr_v(card, descr, skb); + result = gelic_descr_prepare_tx(card, descr, skb); if (result) { /* * DMA map failed. As chanses are that failure * would continue, just release skb and return */ - card->netdev->stats.tx_dropped++; + netdev->stats.tx_dropped++; dev_kfree_skb_any(skb); - spin_unlock_irqrestore(&card->tx_dma_lock, flags); + spin_unlock_irqrestore(&card->tx_lock, flags); return NETDEV_TX_OK; } /* * link this prepared descriptor to previous one * to achieve high performance */ - descr->prev->next_descr_addr = descr->bus_addr; + descr->prev->next_descr_addr = cpu_to_be32(descr->bus_addr); /* * as hardware descriptor is modified in the above lines, * ensure that the hardware sees it */ wmb(); - if (gelic_net_kick_txdma(card, descr)) { + if (gelic_card_kick_txdma(card, descr)) { /* * kick failed. * release descriptors which were just prepared */ - card->netdev->stats.tx_dropped++; - gelic_net_release_tx_descr(card, descr); - gelic_net_release_tx_descr(card, descr->next); + netdev->stats.tx_dropped++; + gelic_descr_release_tx(card, descr); + gelic_descr_release_tx(card, descr->next); card->tx_chain.tail = descr->next->next; dev_info(ctodev(card), "%s: kick failure\n", __func__); } else { @@ -795,7 +888,7 @@ static int gelic_net_xmit(struct sk_buff *skb, struct net_device *netdev) netdev->trans_start = jiffies; } - spin_unlock_irqrestore(&card->tx_dma_lock, flags); + spin_unlock_irqrestore(&card->tx_lock, flags); return NETDEV_TX_OK; } @@ -803,30 +896,34 @@ static int gelic_net_xmit(struct sk_buff *skb, struct net_device *netdev) * gelic_net_pass_skb_up - takes an skb from a descriptor and passes it on * @descr: descriptor to process * @card: card structure + * @netdev: net_device structure to be passed packet * * iommu-unmaps the skb, fills out skb structure and passes the data to the * stack. The descriptor state is not changed. */ -static void gelic_net_pass_skb_up(struct gelic_net_descr *descr, - struct gelic_net_card *card) +static void gelic_net_pass_skb_up(struct gelic_descr *descr, + struct gelic_card *card, + struct net_device *netdev) + { - struct sk_buff *skb; - struct net_device *netdev; + struct sk_buff *skb = descr->skb; u32 data_status, data_error; - data_status = descr->data_status; - data_error = descr->data_error; - netdev = card->netdev; + data_status = be32_to_cpu(descr->data_status); + data_error = be32_to_cpu(descr->data_error); /* unmap skb buffer */ - skb = descr->skb; - dma_unmap_single(ctodev(card), descr->buf_addr, GELIC_NET_MAX_MTU, + dma_unmap_single(ctodev(card), be32_to_cpu(descr->buf_addr), + GELIC_NET_MAX_MTU, DMA_FROM_DEVICE); - skb_put(skb, descr->valid_size? descr->valid_size : descr->result_size); + skb_put(skb, be32_to_cpu(descr->valid_size)? + be32_to_cpu(descr->valid_size) : + be32_to_cpu(descr->result_size)); if (!descr->valid_size) dev_info(ctodev(card), "buffer full %x %x %x\n", - descr->result_size, descr->buf_size, - descr->dmac_cmd_status); + be32_to_cpu(descr->result_size), + be32_to_cpu(descr->buf_size), + be32_to_cpu(descr->dmac_cmd_status)); descr->skb = NULL; /* @@ -838,8 +935,8 @@ static void gelic_net_pass_skb_up(struct gelic_net_descr *descr, /* checksum offload */ if (card->rx_csum) { - if ((data_status & GELIC_NET_DATA_STATUS_CHK_MASK) && - (!(data_error & GELIC_NET_DATA_ERROR_CHK_MASK))) + if ((data_status & GELIC_DESCR_DATA_STATUS_CHK_MASK) && + (!(data_error & GELIC_DESCR_DATA_ERROR_CHK_MASK))) skb->ip_summed = CHECKSUM_UNNECESSARY; else skb->ip_summed = CHECKSUM_NONE; @@ -847,15 +944,15 @@ static void gelic_net_pass_skb_up(struct gelic_net_descr *descr, skb->ip_summed = CHECKSUM_NONE; /* update netdevice statistics */ - card->netdev->stats.rx_packets++; - card->netdev->stats.rx_bytes += skb->len; + netdev->stats.rx_packets++; + netdev->stats.rx_bytes += skb->len; /* pass skb up to stack */ netif_receive_skb(skb); } /** - * gelic_net_decode_one_descr - processes an rx descriptor + * gelic_card_decode_one_descr - processes an rx descriptor * @card: card structure * * returns 1 if a packet has been sent to the stack, otherwise 0 @@ -863,36 +960,56 @@ static void gelic_net_pass_skb_up(struct gelic_net_descr *descr, * processes an rx descriptor by iommu-unmapping the data buffer and passing * the packet up to the stack */ -static int gelic_net_decode_one_descr(struct gelic_net_card *card) +static int gelic_card_decode_one_descr(struct gelic_card *card) { - enum gelic_net_descr_status status; - struct gelic_net_descr_chain *chain = &card->rx_chain; - struct gelic_net_descr *descr = chain->tail; + enum gelic_descr_dma_status status; + struct gelic_descr_chain *chain = &card->rx_chain; + struct gelic_descr *descr = chain->head; + struct net_device *netdev = NULL; int dmac_chain_ended; - status = gelic_net_get_descr_status(descr); + status = gelic_descr_get_status(descr); /* is this descriptor terminated with next_descr == NULL? */ dmac_chain_ended = - descr->dmac_cmd_status & GELIC_NET_DMAC_CMDSTAT_RXDCEIS; + be32_to_cpu(descr->dmac_cmd_status) & + GELIC_DESCR_RX_DMA_CHAIN_END; - if (status == GELIC_NET_DESCR_CARDOWNED) + if (status == GELIC_DESCR_DMA_CARDOWNED) return 0; - if (status == GELIC_NET_DESCR_NOT_IN_USE) { + if (status == GELIC_DESCR_DMA_NOT_IN_USE) { dev_dbg(ctodev(card), "dormant descr? %p\n", descr); return 0; } - if ((status == GELIC_NET_DESCR_RESPONSE_ERROR) || - (status == GELIC_NET_DESCR_PROTECTION_ERROR) || - (status == GELIC_NET_DESCR_FORCE_END)) { + /* netdevice select */ + if (card->vlan_required) { + unsigned int i; + u16 vid; + vid = *(u16 *)(descr->skb->data) & VLAN_VID_MASK; + for (i = 0; i < GELIC_PORT_MAX; i++) { + if (card->vlan[i].rx == vid) { + netdev = card->netdev[i]; + break; + } + }; + if (GELIC_PORT_MAX <= i) { + pr_info("%s: unknown packet vid=%x\n", __func__, vid); + goto refill; + } + } else + netdev = card->netdev[GELIC_PORT_ETHERNET]; + + if ((status == GELIC_DESCR_DMA_RESPONSE_ERROR) || + (status == GELIC_DESCR_DMA_PROTECTION_ERROR) || + (status == GELIC_DESCR_DMA_FORCE_END)) { dev_info(ctodev(card), "dropping RX descriptor with state %x\n", status); - card->netdev->stats.rx_dropped++; + netdev->stats.rx_dropped++; goto refill; } - if (status == GELIC_NET_DESCR_BUFFER_FULL) { + if (status == GELIC_DESCR_DMA_BUFFER_FULL) { /* * Buffer full would occur if and only if * the frame length was longer than the size of this @@ -909,14 +1026,14 @@ static int gelic_net_decode_one_descr(struct gelic_net_card *card) * descriptoers any other than FRAME_END here should * be treated as error. */ - if (status != GELIC_NET_DESCR_FRAME_END) { + if (status != GELIC_DESCR_DMA_FRAME_END) { dev_dbg(ctodev(card), "RX descriptor with state %x\n", status); goto refill; } /* ok, we've got a packet in descr */ - gelic_net_pass_skb_up(descr, card); + gelic_net_pass_skb_up(descr, card, netdev); refill: /* * So that always DMAC can see the end @@ -926,21 +1043,21 @@ refill: descr->next_descr_addr = 0; /* change the descriptor state: */ - gelic_net_set_descr_status(descr, GELIC_NET_DESCR_NOT_IN_USE); + gelic_descr_set_status(descr, GELIC_DESCR_DMA_NOT_IN_USE); /* * this call can fail, but for now, just leave this * decriptor without skb */ - gelic_net_prepare_rx_descr(card, descr); + gelic_descr_prepare_rx(card, descr); - chain->head = descr; - chain->tail = descr->next; + chain->tail = descr; + chain->head = descr->next; /* * Set this descriptor the end of the chain. */ - descr->prev->next_descr_addr = descr->bus_addr; + descr->prev->next_descr_addr = cpu_to_be32(descr->bus_addr); /* * If dmac chain was met, DMAC stopped. @@ -956,29 +1073,27 @@ refill: /** * gelic_net_poll - NAPI poll function called by the stack to return packets - * @netdev: interface device structure + * @napi: napi structure * @budget: number of packets we can pass to the stack at most * - * returns 0 if no more packets available to the driver/stack. Returns 1, - * if the quota is exceeded, but the driver has still packets. + * returns the number of the processed packets * */ static int gelic_net_poll(struct napi_struct *napi, int budget) { - struct gelic_net_card *card = container_of(napi, struct gelic_net_card, napi); - struct net_device *netdev = card->netdev; + struct gelic_card *card = container_of(napi, struct gelic_card, napi); int packets_done = 0; while (packets_done < budget) { - if (!gelic_net_decode_one_descr(card)) + if (!gelic_card_decode_one_descr(card)) break; packets_done++; } if (packets_done < budget) { - netif_rx_complete(netdev, napi); - gelic_net_rx_irq_on(card); + napi_complete(napi); + gelic_card_rx_irq_on(card); } return packets_done; } @@ -989,7 +1104,7 @@ static int gelic_net_poll(struct napi_struct *napi, int budget) * * returns 0 on success, <0 on failure */ -static int gelic_net_change_mtu(struct net_device *netdev, int new_mtu) +int gelic_net_change_mtu(struct net_device *netdev, int new_mtu) { /* no need to re-alloc skbs or so -- the max mtu is about 2.3k * and mtu is outbound only anyway */ @@ -1002,13 +1117,12 @@ static int gelic_net_change_mtu(struct net_device *netdev, int new_mtu) } /** - * gelic_net_interrupt - event handler for gelic_net + * gelic_card_interrupt - event handler for gelic_net */ -static irqreturn_t gelic_net_interrupt(int irq, void *ptr) +static irqreturn_t gelic_card_interrupt(int irq, void *ptr) { unsigned long flags; - struct net_device *netdev = ptr; - struct gelic_net_card *card = netdev_priv(netdev); + struct gelic_card *card = ptr; u64 status; status = card->irq_status; @@ -1016,24 +1130,37 @@ static irqreturn_t gelic_net_interrupt(int irq, void *ptr) if (!status) return IRQ_NONE; + status &= card->irq_mask; + if (card->rx_dma_restart_required) { card->rx_dma_restart_required = 0; - gelic_net_enable_rxdmac(card); + gelic_card_enable_rxdmac(card); } - if (status & GELIC_NET_RXINT) { - gelic_net_rx_irq_off(card); - netif_rx_schedule(netdev, &card->napi); + if (status & GELIC_CARD_RXINT) { + gelic_card_rx_irq_off(card); + napi_schedule(&card->napi); } - if (status & GELIC_NET_TXINT) { - spin_lock_irqsave(&card->tx_dma_lock, flags); + if (status & GELIC_CARD_TXINT) { + spin_lock_irqsave(&card->tx_lock, flags); card->tx_dma_progress = 0; - gelic_net_release_tx_chain(card, 0); + gelic_card_release_tx_chain(card, 0); /* kick outstanding tx descriptor if any */ - gelic_net_kick_txdma(card, card->tx_chain.tail); - spin_unlock_irqrestore(&card->tx_dma_lock, flags); + gelic_card_kick_txdma(card, card->tx_chain.tail); + spin_unlock_irqrestore(&card->tx_lock, flags); } + + /* ether port status changed */ + if (status & GELIC_CARD_PORT_STATUS_CHANGED) + gelic_card_get_ether_port_status(card, 1); + +#ifdef CONFIG_GELIC_WIRELESS + if (status & (GELIC_CARD_WLAN_EVENT_RECEIVED | + GELIC_CARD_WLAN_COMMAND_COMPLETED)) + gelic_wl_interrupt(card->netdev[GELIC_PORT_WIRELESS], status); +#endif + return IRQ_HANDLED; } @@ -1044,54 +1171,16 @@ static irqreturn_t gelic_net_interrupt(int irq, void *ptr) * * see Documentation/networking/netconsole.txt */ -static void gelic_net_poll_controller(struct net_device *netdev) +void gelic_net_poll_controller(struct net_device *netdev) { - struct gelic_net_card *card = netdev_priv(netdev); + struct gelic_card *card = netdev_card(netdev); - gelic_net_set_irq_mask(card, 0); - gelic_net_interrupt(netdev->irq, netdev); - gelic_net_set_irq_mask(card, card->ghiintmask); + gelic_card_set_irq_mask(card, 0); + gelic_card_interrupt(netdev->irq, netdev); + gelic_card_set_irq_mask(card, card->irq_mask); } #endif /* CONFIG_NET_POLL_CONTROLLER */ -/** - * gelic_net_open_device - open device and map dma region - * @card: card structure - */ -static int gelic_net_open_device(struct gelic_net_card *card) -{ - int result; - - result = ps3_sb_event_receive_port_setup(card->dev, PS3_BINDING_CPU_ANY, - &card->netdev->irq); - - if (result) { - dev_info(ctodev(card), - "%s:%d: gelic_net_open_device failed (%d)\n", - __func__, __LINE__, result); - result = -EPERM; - goto fail_alloc_irq; - } - - result = request_irq(card->netdev->irq, gelic_net_interrupt, - IRQF_DISABLED, card->netdev->name, card->netdev); - - if (result) { - dev_info(ctodev(card), "%s:%d: request_irq failed (%d)\n", - __func__, __LINE__, result); - goto fail_request_irq; - } - - return 0; - -fail_request_irq: - ps3_sb_event_receive_port_destroy(card->dev, card->netdev->irq); - card->netdev->irq = NO_IRQ; -fail_alloc_irq: - return result; -} - - /** * gelic_net_open - called upon ifonfig up * @netdev: interface device structure @@ -1101,169 +1190,88 @@ fail_alloc_irq: * gelic_net_open allocates all the descriptors and memory needed for * operation, sets up multicast list and enables interrupts */ -static int gelic_net_open(struct net_device *netdev) +int gelic_net_open(struct net_device *netdev) { - struct gelic_net_card *card = netdev_priv(netdev); + struct gelic_card *card = netdev_card(netdev); - dev_dbg(ctodev(card), " -> %s:%d\n", __func__, __LINE__); + dev_dbg(ctodev(card), " -> %s %p\n", __func__, netdev); - gelic_net_open_device(card); - - if (gelic_net_init_chain(card, &card->tx_chain, - card->descr, GELIC_NET_TX_DESCRIPTORS)) - goto alloc_tx_failed; - if (gelic_net_init_chain(card, &card->rx_chain, - card->descr + GELIC_NET_TX_DESCRIPTORS, - GELIC_NET_RX_DESCRIPTORS)) - goto alloc_rx_failed; - - /* head of chain */ - card->tx_top = card->tx_chain.head; - card->rx_top = card->rx_chain.head; - dev_dbg(ctodev(card), "descr rx %p, tx %p, size %#lx, num %#x\n", - card->rx_top, card->tx_top, sizeof(struct gelic_net_descr), - GELIC_NET_RX_DESCRIPTORS); - /* allocate rx skbs */ - if (gelic_net_alloc_rx_skbs(card)) - goto alloc_skbs_failed; - - napi_enable(&card->napi); - - card->tx_dma_progress = 0; - card->ghiintmask = GELIC_NET_RXINT | GELIC_NET_TXINT; - - gelic_net_set_irq_mask(card, card->ghiintmask); - gelic_net_enable_rxdmac(card); + gelic_card_up(card); netif_start_queue(netdev); - netif_carrier_on(netdev); + gelic_card_get_ether_port_status(card, 1); + dev_dbg(ctodev(card), " <- %s\n", __func__); return 0; - -alloc_skbs_failed: - gelic_net_free_chain(card, card->rx_top); -alloc_rx_failed: - gelic_net_free_chain(card, card->tx_top); -alloc_tx_failed: - return -ENOMEM; } -static void gelic_net_get_drvinfo (struct net_device *netdev, - struct ethtool_drvinfo *info) +void gelic_net_get_drvinfo(struct net_device *netdev, + struct ethtool_drvinfo *info) { strncpy(info->driver, DRV_NAME, sizeof(info->driver) - 1); strncpy(info->version, DRV_VERSION, sizeof(info->version) - 1); } -static int gelic_net_get_settings(struct net_device *netdev, - struct ethtool_cmd *cmd) +static int gelic_ether_get_settings(struct net_device *netdev, + struct ethtool_cmd *cmd) { - struct gelic_net_card *card = netdev_priv(netdev); - int status; - u64 v1, v2; - int speed, duplex; + struct gelic_card *card = netdev_card(netdev); - speed = duplex = -1; - status = lv1_net_control(bus_id(card), dev_id(card), - GELIC_NET_GET_ETH_PORT_STATUS, GELIC_NET_PORT, 0, 0, - &v1, &v2); - if (status) { - /* link down */ - } else { - if (v1 & GELIC_NET_FULL_DUPLEX) { - duplex = DUPLEX_FULL; - } else { - duplex = DUPLEX_HALF; - } + gelic_card_get_ether_port_status(card, 0); - if (v1 & GELIC_NET_SPEED_10 ) { - speed = SPEED_10; - } else if (v1 & GELIC_NET_SPEED_100) { - speed = SPEED_100; - } else if (v1 & GELIC_NET_SPEED_1000) { - speed = SPEED_1000; - } + if (card->ether_port_status & GELIC_LV1_ETHER_FULL_DUPLEX) + cmd->duplex = DUPLEX_FULL; + else + cmd->duplex = DUPLEX_HALF; + + switch (card->ether_port_status & GELIC_LV1_ETHER_SPEED_MASK) { + case GELIC_LV1_ETHER_SPEED_10: + cmd->speed = SPEED_10; + break; + case GELIC_LV1_ETHER_SPEED_100: + cmd->speed = SPEED_100; + break; + case GELIC_LV1_ETHER_SPEED_1000: + cmd->speed = SPEED_1000; + break; + default: + pr_info("%s: speed unknown\n", __func__); + cmd->speed = SPEED_10; + break; } + cmd->supported = SUPPORTED_TP | SUPPORTED_Autoneg | SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full; cmd->advertising = cmd->supported; - cmd->speed = speed; - cmd->duplex = duplex; cmd->autoneg = AUTONEG_ENABLE; /* always enabled */ cmd->port = PORT_TP; return 0; } -static u32 gelic_net_get_link(struct net_device *netdev) +u32 gelic_net_get_rx_csum(struct net_device *netdev) { - struct gelic_net_card *card = netdev_priv(netdev); - int status; - u64 v1, v2; - int link; - - status = lv1_net_control(bus_id(card), dev_id(card), - GELIC_NET_GET_ETH_PORT_STATUS, GELIC_NET_PORT, 0, 0, - &v1, &v2); - if (status) - return 0; /* link down */ - - if (v1 & GELIC_NET_LINK_UP) - link = 1; - else - link = 0; - - return link; -} - -static int gelic_net_nway_reset(struct net_device *netdev) -{ - if (netif_running(netdev)) { - gelic_net_stop(netdev); - gelic_net_open(netdev); - } - return 0; -} - -static u32 gelic_net_get_tx_csum(struct net_device *netdev) -{ - return (netdev->features & NETIF_F_IP_CSUM) != 0; -} - -static int gelic_net_set_tx_csum(struct net_device *netdev, u32 data) -{ - if (data) - netdev->features |= NETIF_F_IP_CSUM; - else - netdev->features &= ~NETIF_F_IP_CSUM; - - return 0; -} - -static u32 gelic_net_get_rx_csum(struct net_device *netdev) -{ - struct gelic_net_card *card = netdev_priv(netdev); + struct gelic_card *card = netdev_card(netdev); return card->rx_csum; } -static int gelic_net_set_rx_csum(struct net_device *netdev, u32 data) +int gelic_net_set_rx_csum(struct net_device *netdev, u32 data) { - struct gelic_net_card *card = netdev_priv(netdev); + struct gelic_card *card = netdev_card(netdev); card->rx_csum = data; return 0; } -static struct ethtool_ops gelic_net_ethtool_ops = { +static struct ethtool_ops gelic_ether_ethtool_ops = { .get_drvinfo = gelic_net_get_drvinfo, - .get_settings = gelic_net_get_settings, - .get_link = gelic_net_get_link, - .nway_reset = gelic_net_nway_reset, - .get_tx_csum = gelic_net_get_tx_csum, - .set_tx_csum = gelic_net_set_tx_csum, + .get_settings = gelic_ether_get_settings, + .get_link = ethtool_op_get_link, + .get_tx_csum = ethtool_op_get_tx_csum, + .set_tx_csum = ethtool_op_set_tx_csum, .get_rx_csum = gelic_net_get_rx_csum, .set_rx_csum = gelic_net_set_rx_csum, }; @@ -1277,9 +1285,9 @@ static struct ethtool_ops gelic_net_ethtool_ops = { */ static void gelic_net_tx_timeout_task(struct work_struct *work) { - struct gelic_net_card *card = - container_of(work, struct gelic_net_card, tx_timeout_task); - struct net_device *netdev = card->netdev; + struct gelic_card *card = + container_of(work, struct gelic_card, tx_timeout_task); + struct net_device *netdev = card->netdev[GELIC_PORT_ETHERNET]; dev_info(ctodev(card), "%s:Timed out. Restarting... \n", __func__); @@ -1302,11 +1310,11 @@ out: * * called, if tx hangs. Schedules a task that resets the interface */ -static void gelic_net_tx_timeout(struct net_device *netdev) +void gelic_net_tx_timeout(struct net_device *netdev) { - struct gelic_net_card *card; + struct gelic_card *card; - card = netdev_priv(netdev); + card = netdev_card(netdev); atomic_inc(&card->tx_timeout_task_counter); if (netdev->flags & IFF_UP) schedule_work(&card->tx_timeout_task); @@ -1315,12 +1323,13 @@ static void gelic_net_tx_timeout(struct net_device *netdev) } /** - * gelic_net_setup_netdev_ops - initialization of net_device operations + * gelic_ether_setup_netdev_ops - initialization of net_device operations * @netdev: net_device structure * * fills out function pointers in the net_device structure */ -static void gelic_net_setup_netdev_ops(struct net_device *netdev) +static void gelic_ether_setup_netdev_ops(struct net_device *netdev, + struct napi_struct *napi) { netdev->open = &gelic_net_open; netdev->stop = &gelic_net_stop; @@ -1330,163 +1339,239 @@ static void gelic_net_setup_netdev_ops(struct net_device *netdev) /* tx watchdog */ netdev->tx_timeout = &gelic_net_tx_timeout; netdev->watchdog_timeo = GELIC_NET_WATCHDOG_TIMEOUT; - netdev->ethtool_ops = &gelic_net_ethtool_ops; + /* NAPI */ + netif_napi_add(netdev, napi, + gelic_net_poll, GELIC_NET_NAPI_WEIGHT); + netdev->ethtool_ops = &gelic_ether_ethtool_ops; +#ifdef CONFIG_NET_POLL_CONTROLLER + netdev->poll_controller = gelic_net_poll_controller; +#endif } /** - * gelic_net_setup_netdev - initialization of net_device + * gelic_ether_setup_netdev - initialization of net_device + * @netdev: net_device structure * @card: card structure * * Returns 0 on success or <0 on failure * - * gelic_net_setup_netdev initializes the net_device structure + * gelic_ether_setup_netdev initializes the net_device structure + * and register it. **/ -static int gelic_net_setup_netdev(struct gelic_net_card *card) +int gelic_net_setup_netdev(struct net_device *netdev, struct gelic_card *card) { - struct net_device *netdev = card->netdev; - struct sockaddr addr; - unsigned int i; int status; u64 v1, v2; DECLARE_MAC_BUF(mac); - SET_NETDEV_DEV(netdev, &card->dev->core); - spin_lock_init(&card->tx_dma_lock); - - card->rx_csum = GELIC_NET_RX_CSUM_DEFAULT; - - gelic_net_setup_netdev_ops(netdev); - - netif_napi_add(netdev, &card->napi, - gelic_net_poll, GELIC_NET_NAPI_WEIGHT); - netdev->features = NETIF_F_IP_CSUM; status = lv1_net_control(bus_id(card), dev_id(card), - GELIC_NET_GET_MAC_ADDRESS, + GELIC_LV1_GET_MAC_ADDRESS, 0, 0, 0, &v1, &v2); + v1 <<= 16; if (status || !is_valid_ether_addr((u8 *)&v1)) { dev_info(ctodev(card), "%s:lv1_net_control GET_MAC_ADDR failed %d\n", __func__, status); return -EINVAL; } - v1 <<= 16; - memcpy(addr.sa_data, &v1, ETH_ALEN); - memcpy(netdev->dev_addr, addr.sa_data, ETH_ALEN); - dev_info(ctodev(card), "MAC addr %s\n", - print_mac(mac, netdev->dev_addr)); + memcpy(netdev->dev_addr, &v1, ETH_ALEN); - card->vlan_index = -1; /* no vlan */ - for (i = 0; i < GELIC_NET_VLAN_MAX; i++) { - status = lv1_net_control(bus_id(card), dev_id(card), - GELIC_NET_GET_VLAN_ID, - i + 1, /* index; one based */ - 0, 0, &v1, &v2); - if (status == GELIC_NET_VLAN_NO_ENTRY) { - dev_dbg(ctodev(card), - "GELIC_VLAN_ID no entry:%d, VLAN disabled\n", - status); - card->vlan_id[i] = 0; - } else if (status) { - dev_dbg(ctodev(card), - "%s:GELIC_NET_VLAN_ID faild, status=%d\n", - __func__, status); - card->vlan_id[i] = 0; - } else { - card->vlan_id[i] = (u32)v1; - dev_dbg(ctodev(card), "vlan_id:%d, %lx\n", i, v1); - } - } - - if (card->vlan_id[GELIC_NET_VLAN_WIRED - 1]) { - card->vlan_index = GELIC_NET_VLAN_WIRED - 1; + if (card->vlan_required) { netdev->hard_header_len += VLAN_HLEN; + /* + * As vlan is internally used, + * we can not receive vlan packets + */ + netdev->features |= NETIF_F_VLAN_CHALLENGED; } status = register_netdev(netdev); if (status) { - dev_err(ctodev(card), "%s:Couldn't register net_device: %d\n", - __func__, status); + dev_err(ctodev(card), "%s:Couldn't register %s %d\n", + __func__, netdev->name, status); return status; } + dev_info(ctodev(card), "%s: MAC addr %s\n", + netdev->name, + print_mac(mac, netdev->dev_addr)); return 0; } /** - * gelic_net_alloc_card - allocates net_device and card structure + * gelic_alloc_card_net - allocates net_device and card structure * * returns the card structure or NULL in case of errors * * the card and net_device structures are linked to each other */ -static struct gelic_net_card *gelic_net_alloc_card(void) +#define GELIC_ALIGN (32) +static struct gelic_card *gelic_alloc_card_net(struct net_device **netdev) { - struct net_device *netdev; - struct gelic_net_card *card; + struct gelic_card *card; + struct gelic_port *port; + void *p; size_t alloc_size; - - alloc_size = sizeof (*card) + - sizeof (struct gelic_net_descr) * GELIC_NET_RX_DESCRIPTORS + - sizeof (struct gelic_net_descr) * GELIC_NET_TX_DESCRIPTORS; /* - * we assume private data is allocated 32 bytes (or more) aligned - * so that gelic_net_descr should be 32 bytes aligned. - * Current alloc_etherdev() does do it because NETDEV_ALIGN - * is 32. - * check this assumption here. + * gelic requires dma descriptor is 32 bytes aligned and + * the hypervisor requires irq_status is 8 bytes aligned. */ - BUILD_BUG_ON(NETDEV_ALIGN < 32); - BUILD_BUG_ON(offsetof(struct gelic_net_card, irq_status) % 8); - BUILD_BUG_ON(offsetof(struct gelic_net_card, descr) % 32); + BUILD_BUG_ON(offsetof(struct gelic_card, irq_status) % 8); + BUILD_BUG_ON(offsetof(struct gelic_card, descr) % 32); + alloc_size = + sizeof(struct gelic_card) + + sizeof(struct gelic_descr) * GELIC_NET_RX_DESCRIPTORS + + sizeof(struct gelic_descr) * GELIC_NET_TX_DESCRIPTORS + + GELIC_ALIGN - 1; - netdev = alloc_etherdev(alloc_size); - if (!netdev) + p = kzalloc(alloc_size, GFP_KERNEL); + if (!p) return NULL; + card = PTR_ALIGN(p, GELIC_ALIGN); + card->unalign = p; + + /* + * alloc netdev + */ + *netdev = alloc_etherdev(sizeof(struct gelic_port)); + if (!netdev) { + kfree(card->unalign); + return NULL; + } + port = netdev_priv(*netdev); + + /* gelic_port */ + port->netdev = *netdev; + port->card = card; + port->type = GELIC_PORT_ETHERNET; + + /* gelic_card */ + card->netdev[GELIC_PORT_ETHERNET] = *netdev; - card = netdev_priv(netdev); - card->netdev = netdev; INIT_WORK(&card->tx_timeout_task, gelic_net_tx_timeout_task); init_waitqueue_head(&card->waitq); atomic_set(&card->tx_timeout_task_counter, 0); + init_MUTEX(&card->updown_lock); + atomic_set(&card->users, 0); return card; } +static void gelic_card_get_vlan_info(struct gelic_card *card) +{ + u64 v1, v2; + int status; + unsigned int i; + struct { + int tx; + int rx; + } vlan_id_ix[2] = { + [GELIC_PORT_ETHERNET] = { + .tx = GELIC_LV1_VLAN_TX_ETHERNET, + .rx = GELIC_LV1_VLAN_RX_ETHERNET + }, + [GELIC_PORT_WIRELESS] = { + .tx = GELIC_LV1_VLAN_TX_WIRELESS, + .rx = GELIC_LV1_VLAN_RX_WIRELESS + } + }; + + for (i = 0; i < ARRAY_SIZE(vlan_id_ix); i++) { + /* tx tag */ + status = lv1_net_control(bus_id(card), dev_id(card), + GELIC_LV1_GET_VLAN_ID, + vlan_id_ix[i].tx, + 0, 0, &v1, &v2); + if (status || !v1) { + if (status != LV1_NO_ENTRY) + dev_dbg(ctodev(card), + "get vlan id for tx(%d) failed(%d)\n", + vlan_id_ix[i].tx, status); + card->vlan[i].tx = 0; + card->vlan[i].rx = 0; + continue; + } + card->vlan[i].tx = (u16)v1; + + /* rx tag */ + status = lv1_net_control(bus_id(card), dev_id(card), + GELIC_LV1_GET_VLAN_ID, + vlan_id_ix[i].rx, + 0, 0, &v1, &v2); + if (status || !v1) { + if (status != LV1_NO_ENTRY) + dev_info(ctodev(card), + "get vlan id for rx(%d) failed(%d)\n", + vlan_id_ix[i].rx, status); + card->vlan[i].tx = 0; + card->vlan[i].rx = 0; + continue; + } + card->vlan[i].rx = (u16)v1; + + dev_dbg(ctodev(card), "vlan_id[%d] tx=%02x rx=%02x\n", + i, card->vlan[i].tx, card->vlan[i].rx); + } + + if (card->vlan[GELIC_PORT_ETHERNET].tx) { + BUG_ON(!card->vlan[GELIC_PORT_WIRELESS].tx); + card->vlan_required = 1; + } else + card->vlan_required = 0; + + /* check wirelss capable firmware */ + if (ps3_compare_firmware_version(1, 6, 0) < 0) { + card->vlan[GELIC_PORT_WIRELESS].tx = 0; + card->vlan[GELIC_PORT_WIRELESS].rx = 0; + } + + dev_info(ctodev(card), "internal vlan %s\n", + card->vlan_required? "enabled" : "disabled"); +} /** * ps3_gelic_driver_probe - add a device to the control of this driver */ -static int ps3_gelic_driver_probe (struct ps3_system_bus_device *dev) +static int ps3_gelic_driver_probe(struct ps3_system_bus_device *dev) { - struct gelic_net_card *card = gelic_net_alloc_card(); + struct gelic_card *card; + struct net_device *netdev; int result; - if (!card) { - dev_info(&dev->core, "gelic_net_alloc_card failed\n"); - result = -ENOMEM; - goto fail_alloc_card; - } - - ps3_system_bus_set_driver_data(dev, card); - card->dev = dev; - + pr_debug("%s: called\n", __func__); result = ps3_open_hv_device(dev); if (result) { - dev_dbg(&dev->core, "ps3_open_hv_device failed\n"); + dev_dbg(&dev->core, "%s:ps3_open_hv_device failed\n", + __func__); goto fail_open; } result = ps3_dma_region_create(dev->d_region); if (result) { - dev_dbg(&dev->core, "ps3_dma_region_create failed(%d)\n", - result); + dev_dbg(&dev->core, "%s:ps3_dma_region_create failed(%d)\n", + __func__, result); BUG_ON("check region type"); goto fail_dma_region; } + /* alloc card/netdevice */ + card = gelic_alloc_card_net(&netdev); + if (!card) { + dev_info(&dev->core, "%s:gelic_net_alloc_card failed\n", + __func__); + result = -ENOMEM; + goto fail_alloc_card; + } + ps3_system_bus_set_driver_data(dev, card); + card->dev = dev; + + /* get internal vlan info */ + gelic_card_get_vlan_info(card); + + /* setup interrupt */ result = lv1_net_set_interrupt_status_indicator(bus_id(card), dev_id(card), ps3_mm_phys_to_lpar(__pa(&card->irq_status)), @@ -1494,34 +1579,101 @@ static int ps3_gelic_driver_probe (struct ps3_system_bus_device *dev) if (result) { dev_dbg(&dev->core, - "lv1_net_set_interrupt_status_indicator failed: %s\n", - ps3_result(result)); + "%s:set_interrupt_status_indicator failed: %s\n", + __func__, ps3_result(result)); result = -EIO; goto fail_status_indicator; } - result = gelic_net_setup_netdev(card); + result = ps3_sb_event_receive_port_setup(dev, PS3_BINDING_CPU_ANY, + &card->irq); if (result) { - dev_dbg(&dev->core, "%s:%d: ps3_dma_region_create failed: " - "(%d)\n", __func__, __LINE__, result); + dev_info(ctodev(card), + "%s:gelic_net_open_device failed (%d)\n", + __func__, result); + result = -EPERM; + goto fail_alloc_irq; + } + result = request_irq(card->irq, gelic_card_interrupt, + IRQF_DISABLED, netdev->name, card); + + if (result) { + dev_info(ctodev(card), "%s:request_irq failed (%d)\n", + __func__, result); + goto fail_request_irq; + } + + /* setup card structure */ + card->irq_mask = GELIC_CARD_RXINT | GELIC_CARD_TXINT | + GELIC_CARD_PORT_STATUS_CHANGED; + card->rx_csum = GELIC_CARD_RX_CSUM_DEFAULT; + + + if (gelic_card_init_chain(card, &card->tx_chain, + card->descr, GELIC_NET_TX_DESCRIPTORS)) + goto fail_alloc_tx; + if (gelic_card_init_chain(card, &card->rx_chain, + card->descr + GELIC_NET_TX_DESCRIPTORS, + GELIC_NET_RX_DESCRIPTORS)) + goto fail_alloc_rx; + + /* head of chain */ + card->tx_top = card->tx_chain.head; + card->rx_top = card->rx_chain.head; + dev_dbg(ctodev(card), "descr rx %p, tx %p, size %#lx, num %#x\n", + card->rx_top, card->tx_top, sizeof(struct gelic_descr), + GELIC_NET_RX_DESCRIPTORS); + /* allocate rx skbs */ + if (gelic_card_alloc_rx_skbs(card)) + goto fail_alloc_skbs; + + spin_lock_init(&card->tx_lock); + card->tx_dma_progress = 0; + + /* setup net_device structure */ + netdev->irq = card->irq; + SET_NETDEV_DEV(netdev, &card->dev->core); + gelic_ether_setup_netdev_ops(netdev, &card->napi); + result = gelic_net_setup_netdev(netdev, card); + if (result) { + dev_dbg(&dev->core, "%s: setup_netdev failed %d", + __func__, result); goto fail_setup_netdev; } +#ifdef CONFIG_GELIC_WIRELESS + if (gelic_wl_driver_probe(card)) { + dev_dbg(&dev->core, "%s: WL init failed\n", __func__); + goto fail_setup_netdev; + } +#endif + pr_debug("%s: done\n", __func__); return 0; fail_setup_netdev: +fail_alloc_skbs: + gelic_card_free_chain(card, card->rx_chain.head); +fail_alloc_rx: + gelic_card_free_chain(card, card->tx_chain.head); +fail_alloc_tx: + free_irq(card->irq, card); + netdev->irq = NO_IRQ; +fail_request_irq: + ps3_sb_event_receive_port_destroy(dev, card->irq); +fail_alloc_irq: lv1_net_set_interrupt_status_indicator(bus_id(card), bus_id(card), - 0 , 0); + 0, 0); fail_status_indicator: + ps3_system_bus_set_driver_data(dev, NULL); + kfree(netdev_card(netdev)->unalign); + free_netdev(netdev); +fail_alloc_card: ps3_dma_region_free(dev->d_region); fail_dma_region: ps3_close_hv_device(dev); fail_open: - ps3_system_bus_set_driver_data(dev, NULL); - free_netdev(card->netdev); -fail_alloc_card: return result; } @@ -1529,9 +1681,34 @@ fail_alloc_card: * ps3_gelic_driver_remove - remove a device from the control of this driver */ -static int ps3_gelic_driver_remove (struct ps3_system_bus_device *dev) +static int ps3_gelic_driver_remove(struct ps3_system_bus_device *dev) { - struct gelic_net_card *card = ps3_system_bus_get_driver_data(dev); + struct gelic_card *card = ps3_system_bus_get_driver_data(dev); + struct net_device *netdev0; + pr_debug("%s: called\n", __func__); + +#ifdef CONFIG_GELIC_WIRELESS + gelic_wl_driver_remove(card); +#endif + /* stop interrupt */ + gelic_card_set_irq_mask(card, 0); + + /* turn off DMA, force end */ + gelic_card_disable_rxdmac(card); + gelic_card_disable_txdmac(card); + + /* release chains */ + gelic_card_release_tx_chain(card, 1); + gelic_card_release_rx_chain(card); + + gelic_card_free_chain(card, card->tx_top); + gelic_card_free_chain(card, card->rx_top); + + netdev0 = card->netdev[GELIC_PORT_ETHERNET]; + /* disconnect event port */ + free_irq(card->irq, card); + netdev0->irq = NO_IRQ; + ps3_sb_event_receive_port_destroy(card->dev, card->irq); wait_event(card->waitq, atomic_read(&card->tx_timeout_task_counter) == 0); @@ -1539,8 +1716,9 @@ static int ps3_gelic_driver_remove (struct ps3_system_bus_device *dev) lv1_net_set_interrupt_status_indicator(bus_id(card), dev_id(card), 0 , 0); - unregister_netdev(card->netdev); - free_netdev(card->netdev); + unregister_netdev(netdev0); + kfree(netdev_card(netdev0)->unalign); + free_netdev(netdev0); ps3_system_bus_set_driver_data(dev, NULL); @@ -1548,6 +1726,7 @@ static int ps3_gelic_driver_remove (struct ps3_system_bus_device *dev) ps3_close_hv_device(dev); + pr_debug("%s: done\n", __func__); return 0; } @@ -1572,8 +1751,8 @@ static void __exit ps3_gelic_driver_exit (void) ps3_system_bus_driver_unregister(&ps3_gelic_driver); } -module_init (ps3_gelic_driver_init); -module_exit (ps3_gelic_driver_exit); +module_init(ps3_gelic_driver_init); +module_exit(ps3_gelic_driver_exit); MODULE_ALIAS(PS3_MODULE_ALIAS_GELIC); diff --git a/drivers/net/ps3_gelic_net.h b/drivers/net/ps3_gelic_net.h index 968560269a3b..1d39d06797e4 100644 --- a/drivers/net/ps3_gelic_net.h +++ b/drivers/net/ps3_gelic_net.h @@ -35,198 +35,323 @@ #define GELIC_NET_MAX_MTU VLAN_ETH_FRAME_LEN #define GELIC_NET_MIN_MTU VLAN_ETH_ZLEN #define GELIC_NET_RXBUF_ALIGN 128 -#define GELIC_NET_RX_CSUM_DEFAULT 1 /* hw chksum */ +#define GELIC_CARD_RX_CSUM_DEFAULT 1 /* hw chksum */ #define GELIC_NET_WATCHDOG_TIMEOUT 5*HZ #define GELIC_NET_NAPI_WEIGHT (GELIC_NET_RX_DESCRIPTORS) #define GELIC_NET_BROADCAST_ADDR 0xffffffffffffL -#define GELIC_NET_VLAN_POS (VLAN_ETH_ALEN * 2) -#define GELIC_NET_VLAN_MAX 4 + #define GELIC_NET_MC_COUNT_MAX 32 /* multicast address list */ -enum gelic_net_int0_status { - GELIC_NET_GDTDCEINT = 24, - GELIC_NET_GRFANMINT = 28, -}; +/* virtual interrupt status register bits */ + /* INT1 */ +#define GELIC_CARD_TX_RAM_FULL_ERR 0x0000000000000001L +#define GELIC_CARD_RX_RAM_FULL_ERR 0x0000000000000002L +#define GELIC_CARD_TX_SHORT_FRAME_ERR 0x0000000000000004L +#define GELIC_CARD_TX_INVALID_DESCR_ERR 0x0000000000000008L +#define GELIC_CARD_RX_FIFO_FULL_ERR 0x0000000000002000L +#define GELIC_CARD_RX_DESCR_CHAIN_END 0x0000000000004000L +#define GELIC_CARD_RX_INVALID_DESCR_ERR 0x0000000000008000L +#define GELIC_CARD_TX_RESPONCE_ERR 0x0000000000010000L +#define GELIC_CARD_RX_RESPONCE_ERR 0x0000000000100000L +#define GELIC_CARD_TX_PROTECTION_ERR 0x0000000000400000L +#define GELIC_CARD_RX_PROTECTION_ERR 0x0000000004000000L +#define GELIC_CARD_TX_TCP_UDP_CHECKSUM_ERR 0x0000000008000000L +#define GELIC_CARD_PORT_STATUS_CHANGED 0x0000000020000000L +#define GELIC_CARD_WLAN_EVENT_RECEIVED 0x0000000040000000L +#define GELIC_CARD_WLAN_COMMAND_COMPLETED 0x0000000080000000L + /* INT 0 */ +#define GELIC_CARD_TX_FLAGGED_DESCR 0x0004000000000000L +#define GELIC_CARD_RX_FLAGGED_DESCR 0x0040000000000000L +#define GELIC_CARD_TX_TRANSFER_END 0x0080000000000000L +#define GELIC_CARD_TX_DESCR_CHAIN_END 0x0100000000000000L +#define GELIC_CARD_NUMBER_OF_RX_FRAME 0x1000000000000000L +#define GELIC_CARD_ONE_TIME_COUNT_TIMER 0x4000000000000000L +#define GELIC_CARD_FREE_RUN_COUNT_TIMER 0x8000000000000000L -/* GHIINT1STS bits */ -enum gelic_net_int1_status { - GELIC_NET_GDADCEINT = 14, -}; +/* initial interrupt mask */ +#define GELIC_CARD_TXINT GELIC_CARD_TX_DESCR_CHAIN_END -/* interrupt mask */ -#define GELIC_NET_TXINT (1L << (GELIC_NET_GDTDCEINT + 32)) - -#define GELIC_NET_RXINT0 (1L << (GELIC_NET_GRFANMINT + 32)) -#define GELIC_NET_RXINT1 (1L << GELIC_NET_GDADCEINT) -#define GELIC_NET_RXINT (GELIC_NET_RXINT0 | GELIC_NET_RXINT1) +#define GELIC_CARD_RXINT (GELIC_CARD_RX_DESCR_CHAIN_END | \ + GELIC_CARD_NUMBER_OF_RX_FRAME) /* RX descriptor data_status bits */ -#define GELIC_NET_RXDMADU 0x80000000 /* destination MAC addr unknown */ -#define GELIC_NET_RXLSTFBF 0x40000000 /* last frame buffer */ -#define GELIC_NET_RXIPCHK 0x20000000 /* IP checksum performed */ -#define GELIC_NET_RXTCPCHK 0x10000000 /* TCP/UDP checksup performed */ -#define GELIC_NET_RXIPSPKT 0x08000000 /* IPsec packet */ -#define GELIC_NET_RXIPSAHPRT 0x04000000 /* IPsec AH protocol performed */ -#define GELIC_NET_RXIPSESPPRT 0x02000000 /* IPsec ESP protocol performed */ -#define GELIC_NET_RXSESPAH 0x01000000 /* - * IPsec ESP protocol auth - * performed - */ +enum gelic_descr_rx_status { + GELIC_DESCR_RXDMADU = 0x80000000, /* destination MAC addr unknown */ + GELIC_DESCR_RXLSTFBF = 0x40000000, /* last frame buffer */ + GELIC_DESCR_RXIPCHK = 0x20000000, /* IP checksum performed */ + GELIC_DESCR_RXTCPCHK = 0x10000000, /* TCP/UDP checksup performed */ + GELIC_DESCR_RXWTPKT = 0x00C00000, /* + * wakeup trigger packet + * 01: Magic Packet (TM) + * 10: ARP packet + * 11: Multicast MAC addr + */ + GELIC_DESCR_RXVLNPKT = 0x00200000, /* VLAN packet */ + /* bit 20..16 reserved */ + GELIC_DESCR_RXRRECNUM = 0x0000ff00, /* reception receipt number */ + /* bit 7..0 reserved */ +}; -#define GELIC_NET_RXWTPKT 0x00C00000 /* - * wakeup trigger packet - * 01: Magic Packet (TM) - * 10: ARP packet - * 11: Multicast MAC addr - */ -#define GELIC_NET_RXVLNPKT 0x00200000 /* VLAN packet */ -/* bit 20..16 reserved */ -#define GELIC_NET_RXRRECNUM 0x0000ff00 /* reception receipt number */ -#define GELIC_NET_RXRRECNUM_SHIFT 8 -/* bit 7..0 reserved */ +#define GELIC_DESCR_DATA_STATUS_CHK_MASK \ + (GELIC_DESCR_RXIPCHK | GELIC_DESCR_RXTCPCHK) -#define GELIC_NET_TXDESC_TAIL 0 -#define GELIC_NET_DATA_STATUS_CHK_MASK (GELIC_NET_RXIPCHK | GELIC_NET_RXTCPCHK) + /* TX descriptor data_status bits */ +enum gelic_descr_tx_status { + GELIC_DESCR_TX_TAIL = 0x00000001, /* gelic treated this + * descriptor was end of + * a tx frame + */ +}; -/* RX descriptor data_error bits */ -/* bit 31 reserved */ -#define GELIC_NET_RXALNERR 0x40000000 /* alignement error 10/100M */ -#define GELIC_NET_RXOVERERR 0x20000000 /* oversize error */ -#define GELIC_NET_RXRNTERR 0x10000000 /* Runt error */ -#define GELIC_NET_RXIPCHKERR 0x08000000 /* IP checksum error */ -#define GELIC_NET_RXTCPCHKERR 0x04000000 /* TCP/UDP checksum error */ -#define GELIC_NET_RXUMCHSP 0x02000000 /* unmatched sp on sp */ -#define GELIC_NET_RXUMCHSPI 0x01000000 /* unmatched SPI on SAD */ -#define GELIC_NET_RXUMCHSAD 0x00800000 /* unmatched SAD */ -#define GELIC_NET_RXIPSAHERR 0x00400000 /* auth error on AH protocol - * processing */ -#define GELIC_NET_RXIPSESPAHERR 0x00200000 /* auth error on ESP protocol - * processing */ -#define GELIC_NET_RXDRPPKT 0x00100000 /* drop packet */ -#define GELIC_NET_RXIPFMTERR 0x00080000 /* IP packet format error */ -/* bit 18 reserved */ -#define GELIC_NET_RXDATAERR 0x00020000 /* IP packet format error */ -#define GELIC_NET_RXCALERR 0x00010000 /* cariier extension length - * error */ -#define GELIC_NET_RXCREXERR 0x00008000 /* carrier extention error */ -#define GELIC_NET_RXMLTCST 0x00004000 /* multicast address frame */ -/* bit 13..0 reserved */ -#define GELIC_NET_DATA_ERROR_CHK_MASK \ - (GELIC_NET_RXIPCHKERR | GELIC_NET_RXTCPCHKERR) +/* RX descriptor data error bits */ +enum gelic_descr_rx_error { + /* bit 31 reserved */ + GELIC_DESCR_RXALNERR = 0x40000000, /* alignement error 10/100M */ + GELIC_DESCR_RXOVERERR = 0x20000000, /* oversize error */ + GELIC_DESCR_RXRNTERR = 0x10000000, /* Runt error */ + GELIC_DESCR_RXIPCHKERR = 0x08000000, /* IP checksum error */ + GELIC_DESCR_RXTCPCHKERR = 0x04000000, /* TCP/UDP checksum error */ + GELIC_DESCR_RXDRPPKT = 0x00100000, /* drop packet */ + GELIC_DESCR_RXIPFMTERR = 0x00080000, /* IP packet format error */ + /* bit 18 reserved */ + GELIC_DESCR_RXDATAERR = 0x00020000, /* IP packet format error */ + GELIC_DESCR_RXCALERR = 0x00010000, /* cariier extension length + * error */ + GELIC_DESCR_RXCREXERR = 0x00008000, /* carrier extention error */ + GELIC_DESCR_RXMLTCST = 0x00004000, /* multicast address frame */ + /* bit 13..0 reserved */ +}; +#define GELIC_DESCR_DATA_ERROR_CHK_MASK \ + (GELIC_DESCR_RXIPCHKERR | GELIC_DESCR_RXTCPCHKERR) +/* DMA command and status (RX and TX)*/ +enum gelic_descr_dma_status { + GELIC_DESCR_DMA_COMPLETE = 0x00000000, /* used in tx */ + GELIC_DESCR_DMA_BUFFER_FULL = 0x00000000, /* used in rx */ + GELIC_DESCR_DMA_RESPONSE_ERROR = 0x10000000, /* used in rx, tx */ + GELIC_DESCR_DMA_PROTECTION_ERROR = 0x20000000, /* used in rx, tx */ + GELIC_DESCR_DMA_FRAME_END = 0x40000000, /* used in rx */ + GELIC_DESCR_DMA_FORCE_END = 0x50000000, /* used in rx, tx */ + GELIC_DESCR_DMA_CARDOWNED = 0xa0000000, /* used in rx, tx */ + GELIC_DESCR_DMA_NOT_IN_USE = 0xb0000000, /* any other value */ +}; + +#define GELIC_DESCR_DMA_STAT_MASK (0xf0000000) /* tx descriptor command and status */ -#define GELIC_NET_DMAC_CMDSTAT_NOCS 0xa0080000 /* middle of frame */ -#define GELIC_NET_DMAC_CMDSTAT_TCPCS 0xa00a0000 -#define GELIC_NET_DMAC_CMDSTAT_UDPCS 0xa00b0000 -#define GELIC_NET_DMAC_CMDSTAT_END_FRAME 0x00040000 /* end of frame */ +enum gelic_descr_tx_dma_status { + /* [19] */ + GELIC_DESCR_TX_DMA_IKE = 0x00080000, /* IPSEC off */ + /* [18] */ + GELIC_DESCR_TX_DMA_FRAME_TAIL = 0x00040000, /* last descriptor of + * the packet + */ + /* [17..16] */ + GELIC_DESCR_TX_DMA_TCP_CHKSUM = 0x00020000, /* TCP packet */ + GELIC_DESCR_TX_DMA_UDP_CHKSUM = 0x00030000, /* UDP packet */ + GELIC_DESCR_TX_DMA_NO_CHKSUM = 0x00000000, /* no checksum */ -#define GELIC_NET_DMAC_CMDSTAT_RXDCEIS 0x00000002 /* descriptor chain end - * interrupt status */ - -#define GELIC_NET_DMAC_CMDSTAT_CHAIN_END 0x00000002 /* RXDCEIS:DMA stopped */ -#define GELIC_NET_DESCR_IND_PROC_SHIFT 28 -#define GELIC_NET_DESCR_IND_PROC_MASKO 0x0fffffff - - -enum gelic_net_descr_status { - GELIC_NET_DESCR_COMPLETE = 0x00, /* used in tx */ - GELIC_NET_DESCR_BUFFER_FULL = 0x00, /* used in rx */ - GELIC_NET_DESCR_RESPONSE_ERROR = 0x01, /* used in rx and tx */ - GELIC_NET_DESCR_PROTECTION_ERROR = 0x02, /* used in rx and tx */ - GELIC_NET_DESCR_FRAME_END = 0x04, /* used in rx */ - GELIC_NET_DESCR_FORCE_END = 0x05, /* used in rx and tx */ - GELIC_NET_DESCR_CARDOWNED = 0x0a, /* used in rx and tx */ - GELIC_NET_DESCR_NOT_IN_USE = 0x0b /* any other value */ + /* [1] */ + GELIC_DESCR_TX_DMA_CHAIN_END = 0x00000002, /* DMA terminated + * due to chain end + */ }; + +#define GELIC_DESCR_DMA_CMD_NO_CHKSUM \ + (GELIC_DESCR_DMA_CARDOWNED | GELIC_DESCR_TX_DMA_IKE | \ + GELIC_DESCR_TX_DMA_NO_CHKSUM) + +#define GELIC_DESCR_DMA_CMD_TCP_CHKSUM \ + (GELIC_DESCR_DMA_CARDOWNED | GELIC_DESCR_TX_DMA_IKE | \ + GELIC_DESCR_TX_DMA_TCP_CHKSUM) + +#define GELIC_DESCR_DMA_CMD_UDP_CHKSUM \ + (GELIC_DESCR_DMA_CARDOWNED | GELIC_DESCR_TX_DMA_IKE | \ + GELIC_DESCR_TX_DMA_UDP_CHKSUM) + +enum gelic_descr_rx_dma_status { + /* [ 1 ] */ + GELIC_DESCR_RX_DMA_CHAIN_END = 0x00000002, /* DMA terminated + * due to chain end + */ +}; + /* for lv1_net_control */ -#define GELIC_NET_GET_MAC_ADDRESS 0x0000000000000001 -#define GELIC_NET_GET_ETH_PORT_STATUS 0x0000000000000002 -#define GELIC_NET_SET_NEGOTIATION_MODE 0x0000000000000003 -#define GELIC_NET_GET_VLAN_ID 0x0000000000000004 +enum gelic_lv1_net_control_code { + GELIC_LV1_GET_MAC_ADDRESS = 1, + GELIC_LV1_GET_ETH_PORT_STATUS = 2, + GELIC_LV1_SET_NEGOTIATION_MODE = 3, + GELIC_LV1_GET_VLAN_ID = 4, + GELIC_LV1_GET_CHANNEL = 6, + GELIC_LV1_POST_WLAN_CMD = 9, + GELIC_LV1_GET_WLAN_CMD_RESULT = 10, + GELIC_LV1_GET_WLAN_EVENT = 11 +}; -#define GELIC_NET_LINK_UP 0x0000000000000001 -#define GELIC_NET_FULL_DUPLEX 0x0000000000000002 -#define GELIC_NET_AUTO_NEG 0x0000000000000004 -#define GELIC_NET_SPEED_10 0x0000000000000010 -#define GELIC_NET_SPEED_100 0x0000000000000020 -#define GELIC_NET_SPEED_1000 0x0000000000000040 +/* status returened from GET_ETH_PORT_STATUS */ +enum gelic_lv1_ether_port_status { + GELIC_LV1_ETHER_LINK_UP = 0x0000000000000001L, + GELIC_LV1_ETHER_FULL_DUPLEX = 0x0000000000000002L, + GELIC_LV1_ETHER_AUTO_NEG = 0x0000000000000004L, -#define GELIC_NET_VLAN_ALL 0x0000000000000001 -#define GELIC_NET_VLAN_WIRED 0x0000000000000002 -#define GELIC_NET_VLAN_WIRELESS 0x0000000000000003 -#define GELIC_NET_VLAN_PSP 0x0000000000000004 -#define GELIC_NET_VLAN_PORT0 0x0000000000000010 -#define GELIC_NET_VLAN_PORT1 0x0000000000000011 -#define GELIC_NET_VLAN_PORT2 0x0000000000000012 -#define GELIC_NET_VLAN_DAEMON_CLIENT_BSS 0x0000000000000013 -#define GELIC_NET_VLAN_LIBERO_CLIENT_BSS 0x0000000000000014 -#define GELIC_NET_VLAN_NO_ENTRY -6 + GELIC_LV1_ETHER_SPEED_10 = 0x0000000000000010L, + GELIC_LV1_ETHER_SPEED_100 = 0x0000000000000020L, + GELIC_LV1_ETHER_SPEED_1000 = 0x0000000000000040L, + GELIC_LV1_ETHER_SPEED_MASK = 0x0000000000000070L +}; -#define GELIC_NET_PORT 2 /* for port status */ +enum gelic_lv1_vlan_index { + /* for outgoing packets */ + GELIC_LV1_VLAN_TX_ETHERNET = 0x0000000000000002L, + GELIC_LV1_VLAN_TX_WIRELESS = 0x0000000000000003L, + /* for incoming packets */ + GELIC_LV1_VLAN_RX_ETHERNET = 0x0000000000000012L, + GELIC_LV1_VLAN_RX_WIRELESS = 0x0000000000000013L +}; /* size of hardware part of gelic descriptor */ -#define GELIC_NET_DESCR_SIZE (32) -struct gelic_net_descr { +#define GELIC_DESCR_SIZE (32) + +enum gelic_port_type { + GELIC_PORT_ETHERNET = 0, + GELIC_PORT_WIRELESS = 1, + GELIC_PORT_MAX +}; + +struct gelic_descr { /* as defined by the hardware */ - u32 buf_addr; - u32 buf_size; - u32 next_descr_addr; - u32 dmac_cmd_status; - u32 result_size; - u32 valid_size; /* all zeroes for tx */ - u32 data_status; - u32 data_error; /* all zeroes for tx */ + __be32 buf_addr; + __be32 buf_size; + __be32 next_descr_addr; + __be32 dmac_cmd_status; + __be32 result_size; + __be32 valid_size; /* all zeroes for tx */ + __be32 data_status; + __be32 data_error; /* all zeroes for tx */ /* used in the driver */ struct sk_buff *skb; dma_addr_t bus_addr; - struct gelic_net_descr *next; - struct gelic_net_descr *prev; - struct vlan_ethhdr vlan; + struct gelic_descr *next; + struct gelic_descr *prev; } __attribute__((aligned(32))); -struct gelic_net_descr_chain { +struct gelic_descr_chain { /* we walk from tail to head */ - struct gelic_net_descr *head; - struct gelic_net_descr *tail; + struct gelic_descr *head; + struct gelic_descr *tail; }; -struct gelic_net_card { - struct net_device *netdev; +struct gelic_vlan_id { + u16 tx; + u16 rx; +}; + +struct gelic_card { struct napi_struct napi; + struct net_device *netdev[GELIC_PORT_MAX]; /* * hypervisor requires irq_status should be * 8 bytes aligned, but u64 member is * always disposed in that manner */ u64 irq_status; - u64 ghiintmask; + u64 irq_mask; struct ps3_system_bus_device *dev; - u32 vlan_id[GELIC_NET_VLAN_MAX]; - int vlan_index; + struct gelic_vlan_id vlan[GELIC_PORT_MAX]; + int vlan_required; - struct gelic_net_descr_chain tx_chain; - struct gelic_net_descr_chain rx_chain; + struct gelic_descr_chain tx_chain; + struct gelic_descr_chain rx_chain; int rx_dma_restart_required; - /* gurad dmac descriptor chain*/ - spinlock_t chain_lock; - int rx_csum; - /* guard tx_dma_progress */ - spinlock_t tx_dma_lock; + /* + * tx_lock guards tx descriptor list and + * tx_dma_progress. + */ + spinlock_t tx_lock; int tx_dma_progress; struct work_struct tx_timeout_task; atomic_t tx_timeout_task_counter; wait_queue_head_t waitq; - struct gelic_net_descr *tx_top, *rx_top; - struct gelic_net_descr descr[0]; + /* only first user should up the card */ + struct semaphore updown_lock; + atomic_t users; + + u64 ether_port_status; + /* original address returned by kzalloc */ + void *unalign; + + /* + * each netdevice has copy of irq + */ + unsigned int irq; + struct gelic_descr *tx_top, *rx_top; + struct gelic_descr descr[0]; /* must be the last */ }; +struct gelic_port { + struct gelic_card *card; + struct net_device *netdev; + enum gelic_port_type type; + long priv[0]; /* long for alignment */ +}; -extern unsigned long p_to_lp(long pa); +static inline struct gelic_card *port_to_card(struct gelic_port *p) +{ + return p->card; +} +static inline struct net_device *port_to_netdev(struct gelic_port *p) +{ + return p->netdev; +} +static inline struct gelic_card *netdev_card(struct net_device *d) +{ + return ((struct gelic_port *)netdev_priv(d))->card; +} +static inline struct gelic_port *netdev_port(struct net_device *d) +{ + return (struct gelic_port *)netdev_priv(d); +} +static inline struct device *ctodev(struct gelic_card *card) +{ + return &card->dev->core; +} +static inline u64 bus_id(struct gelic_card *card) +{ + return card->dev->bus_id; +} +static inline u64 dev_id(struct gelic_card *card) +{ + return card->dev->dev_id; +} + +static inline void *port_priv(struct gelic_port *port) +{ + return port->priv; +} + +extern int gelic_card_set_irq_mask(struct gelic_card *card, u64 mask); +/* shared netdev ops */ +extern void gelic_card_up(struct gelic_card *card); +extern void gelic_card_down(struct gelic_card *card); +extern int gelic_net_open(struct net_device *netdev); +extern int gelic_net_stop(struct net_device *netdev); +extern int gelic_net_xmit(struct sk_buff *skb, struct net_device *netdev); +extern void gelic_net_set_multi(struct net_device *netdev); +extern void gelic_net_tx_timeout(struct net_device *netdev); +extern int gelic_net_change_mtu(struct net_device *netdev, int new_mtu); +extern int gelic_net_setup_netdev(struct net_device *netdev, + struct gelic_card *card); + +/* shared ethtool ops */ +extern void gelic_net_get_drvinfo(struct net_device *netdev, + struct ethtool_drvinfo *info); +extern u32 gelic_net_get_rx_csum(struct net_device *netdev); +extern int gelic_net_set_rx_csum(struct net_device *netdev, u32 data); +extern void gelic_net_poll_controller(struct net_device *netdev); #endif /* _GELIC_NET_H */ diff --git a/drivers/net/ps3_gelic_wireless.c b/drivers/net/ps3_gelic_wireless.c new file mode 100644 index 000000000000..750d2a99cb4f --- /dev/null +++ b/drivers/net/ps3_gelic_wireless.c @@ -0,0 +1,2753 @@ +/* + * PS3 gelic network driver. + * + * Copyright (C) 2007 Sony Computer Entertainment Inc. + * Copyright 2007 Sony Corporation + * + * 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 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. + */ +#undef DEBUG + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "ps3_gelic_net.h" +#include "ps3_gelic_wireless.h" + + +static int gelic_wl_start_scan(struct gelic_wl_info *wl, int always_scan); +static int gelic_wl_try_associate(struct net_device *netdev); + +/* + * tables + */ + +/* 802.11b/g channel to freq in MHz */ +static const int channel_freq[] = { + 2412, 2417, 2422, 2427, 2432, + 2437, 2442, 2447, 2452, 2457, + 2462, 2467, 2472, 2484 +}; +#define NUM_CHANNELS ARRAY_SIZE(channel_freq) + +/* in bps */ +static const int bitrate_list[] = { + 1000000, + 2000000, + 5500000, + 11000000, + 6000000, + 9000000, + 12000000, + 18000000, + 24000000, + 36000000, + 48000000, + 54000000 +}; +#define NUM_BITRATES ARRAY_SIZE(bitrate_list) + +/* + * wpa2 support requires the hypervisor version 2.0 or later + */ +static inline int wpa2_capable(void) +{ + return (0 <= ps3_compare_firmware_version(2, 0, 0)); +} + +static inline int precise_ie(void) +{ + return 0; /* FIXME */ +} +/* + * post_eurus_cmd helpers + */ +struct eurus_cmd_arg_info { + int pre_arg; /* command requres arg1, arg2 at POST COMMAND */ + int post_arg; /* command requires arg1, arg2 at GET_RESULT */ +}; + +static const struct eurus_cmd_arg_info cmd_info[GELIC_EURUS_CMD_MAX_INDEX] = { + [GELIC_EURUS_CMD_SET_COMMON_CFG] = { .pre_arg = 1}, + [GELIC_EURUS_CMD_SET_WEP_CFG] = { .pre_arg = 1}, + [GELIC_EURUS_CMD_SET_WPA_CFG] = { .pre_arg = 1}, + [GELIC_EURUS_CMD_GET_COMMON_CFG] = { .post_arg = 1}, + [GELIC_EURUS_CMD_GET_WEP_CFG] = { .post_arg = 1}, + [GELIC_EURUS_CMD_GET_WPA_CFG] = { .post_arg = 1}, + [GELIC_EURUS_CMD_GET_RSSI_CFG] = { .post_arg = 1}, + [GELIC_EURUS_CMD_GET_SCAN] = { .post_arg = 1}, +}; + +#ifdef DEBUG +static const char *cmdstr(enum gelic_eurus_command ix) +{ + switch (ix) { + case GELIC_EURUS_CMD_ASSOC: + return "ASSOC"; + case GELIC_EURUS_CMD_DISASSOC: + return "DISASSOC"; + case GELIC_EURUS_CMD_START_SCAN: + return "SCAN"; + case GELIC_EURUS_CMD_GET_SCAN: + return "GET SCAN"; + case GELIC_EURUS_CMD_SET_COMMON_CFG: + return "SET_COMMON_CFG"; + case GELIC_EURUS_CMD_GET_COMMON_CFG: + return "GET_COMMON_CFG"; + case GELIC_EURUS_CMD_SET_WEP_CFG: + return "SET_WEP_CFG"; + case GELIC_EURUS_CMD_GET_WEP_CFG: + return "GET_WEP_CFG"; + case GELIC_EURUS_CMD_SET_WPA_CFG: + return "SET_WPA_CFG"; + case GELIC_EURUS_CMD_GET_WPA_CFG: + return "GET_WPA_CFG"; + case GELIC_EURUS_CMD_GET_RSSI_CFG: + return "GET_RSSI"; + default: + break; + } + return ""; +}; +#else +static inline const char *cmdstr(enum gelic_eurus_command ix) +{ + return ""; +} +#endif + +/* synchronously do eurus commands */ +static void gelic_eurus_sync_cmd_worker(struct work_struct *work) +{ + struct gelic_eurus_cmd *cmd; + struct gelic_card *card; + struct gelic_wl_info *wl; + + u64 arg1, arg2; + + pr_debug("%s: <-\n", __func__); + cmd = container_of(work, struct gelic_eurus_cmd, work); + BUG_ON(cmd_info[cmd->cmd].pre_arg && + cmd_info[cmd->cmd].post_arg); + wl = cmd->wl; + card = port_to_card(wl_port(wl)); + + if (cmd_info[cmd->cmd].pre_arg) { + arg1 = ps3_mm_phys_to_lpar(__pa(cmd->buffer)); + arg2 = cmd->buf_size; + } else { + arg1 = 0; + arg2 = 0; + } + init_completion(&wl->cmd_done_intr); + pr_debug("%s: cmd='%s' start\n", __func__, cmdstr(cmd->cmd)); + cmd->status = lv1_net_control(bus_id(card), dev_id(card), + GELIC_LV1_POST_WLAN_CMD, + cmd->cmd, arg1, arg2, + &cmd->tag, &cmd->size); + if (cmd->status) { + complete(&cmd->done); + pr_info("%s: cmd issue failed\n", __func__); + return; + } + + wait_for_completion(&wl->cmd_done_intr); + + if (cmd_info[cmd->cmd].post_arg) { + arg1 = ps3_mm_phys_to_lpar(__pa(cmd->buffer)); + arg2 = cmd->buf_size; + } else { + arg1 = 0; + arg2 = 0; + } + + cmd->status = lv1_net_control(bus_id(card), dev_id(card), + GELIC_LV1_GET_WLAN_CMD_RESULT, + cmd->tag, arg1, arg2, + &cmd->cmd_status, &cmd->size); +#ifdef DEBUG + if (cmd->status || cmd->cmd_status) { + pr_debug("%s: cmd done tag=%#lx arg1=%#lx, arg2=%#lx\n", __func__, + cmd->tag, arg1, arg2); + pr_debug("%s: cmd done status=%#x cmd_status=%#lx size=%#lx\n", + __func__, cmd->status, cmd->cmd_status, cmd->size); + } +#endif + complete(&cmd->done); + pr_debug("%s: cmd='%s' done\n", __func__, cmdstr(cmd->cmd)); +} + +static struct gelic_eurus_cmd *gelic_eurus_sync_cmd(struct gelic_wl_info *wl, + unsigned int eurus_cmd, + void *buffer, + unsigned int buf_size) +{ + struct gelic_eurus_cmd *cmd; + + /* allocate cmd */ + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (!cmd) + return NULL; + + /* initialize members */ + cmd->cmd = eurus_cmd; + cmd->buffer = buffer; + cmd->buf_size = buf_size; + cmd->wl = wl; + INIT_WORK(&cmd->work, gelic_eurus_sync_cmd_worker); + init_completion(&cmd->done); + queue_work(wl->eurus_cmd_queue, &cmd->work); + + /* wait for command completion */ + wait_for_completion(&cmd->done); + + return cmd; +} + +static u32 gelic_wl_get_link(struct net_device *netdev) +{ + struct gelic_wl_info *wl = port_wl(netdev_port(netdev)); + u32 ret; + + pr_debug("%s: <-\n", __func__); + down(&wl->assoc_stat_lock); + if (wl->assoc_stat == GELIC_WL_ASSOC_STAT_ASSOCIATED) + ret = 1; + else + ret = 0; + up(&wl->assoc_stat_lock); + pr_debug("%s: ->\n", __func__); + return ret; +} + +static void gelic_wl_send_iwap_event(struct gelic_wl_info *wl, u8 *bssid) +{ + union iwreq_data data; + + memset(&data, 0, sizeof(data)); + if (bssid) + memcpy(data.ap_addr.sa_data, bssid, ETH_ALEN); + data.ap_addr.sa_family = ARPHRD_ETHER; + wireless_send_event(port_to_netdev(wl_port(wl)), SIOCGIWAP, + &data, NULL); +} + +/* + * wireless extension handlers and helpers + */ + +/* SIOGIWNAME */ +static int gelic_wl_get_name(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *iwreq, char *extra) +{ + strcpy(iwreq->name, "IEEE 802.11bg"); + return 0; +} + +static void gelic_wl_get_ch_info(struct gelic_wl_info *wl) +{ + struct gelic_card *card = port_to_card(wl_port(wl)); + u64 ch_info_raw, tmp; + int status; + + if (!test_and_set_bit(GELIC_WL_STAT_CH_INFO, &wl->stat)) { + status = lv1_net_control(bus_id(card), dev_id(card), + GELIC_LV1_GET_CHANNEL, 0, 0, 0, + &ch_info_raw, + &tmp); + /* some fw versions may return error */ + if (status) { + if (status != LV1_NO_ENTRY) + pr_info("%s: available ch unknown\n", __func__); + wl->ch_info = 0x07ff;/* 11 ch */ + } else + /* 16 bits of MSB has available channels */ + wl->ch_info = ch_info_raw >> 48; + } + return; +} + +/* SIOGIWRANGE */ +static int gelic_wl_get_range(struct net_device *netdev, + struct iw_request_info *info, + union iwreq_data *iwreq, char *extra) +{ + struct iw_point *point = &iwreq->data; + struct iw_range *range = (struct iw_range *)extra; + struct gelic_wl_info *wl = port_wl(netdev_port(netdev)); + unsigned int i, chs; + + pr_debug("%s: <-\n", __func__); + point->length = sizeof(struct iw_range); + memset(range, 0, sizeof(struct iw_range)); + + range->we_version_compiled = WIRELESS_EXT; + range->we_version_source = 22; + + /* available channels and frequencies */ + gelic_wl_get_ch_info(wl); + + for (i = 0, chs = 0; + i < NUM_CHANNELS && chs < IW_MAX_FREQUENCIES; i++) + if (wl->ch_info & (1 << i)) { + range->freq[chs].i = i + 1; + range->freq[chs].m = channel_freq[i]; + range->freq[chs].e = 6; + chs++; + } + range->num_frequency = chs; + range->old_num_frequency = chs; + range->num_channels = chs; + range->old_num_channels = chs; + + /* bitrates */ + for (i = 0; i < NUM_BITRATES; i++) + range->bitrate[i] = bitrate_list[i]; + range->num_bitrates = i; + + /* signal levels */ + range->max_qual.qual = 100; /* relative value */ + range->max_qual.level = 100; + range->avg_qual.qual = 50; + range->avg_qual.level = 50; + range->sensitivity = 0; + + /* Event capability */ + IW_EVENT_CAPA_SET_KERNEL(range->event_capa); + IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP); + IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN); + + /* encryption capability */ + range->enc_capa = IW_ENC_CAPA_WPA | + IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP; + if (wpa2_capable()) + range->enc_capa |= IW_ENC_CAPA_WPA2; + range->encoding_size[0] = 5; /* 40bit WEP */ + range->encoding_size[1] = 13; /* 104bit WEP */ + range->encoding_size[2] = 32; /* WPA-PSK */ + range->num_encoding_sizes = 3; + range->max_encoding_tokens = GELIC_WEP_KEYS; + + pr_debug("%s: ->\n", __func__); + return 0; + +} + +/* SIOC{G,S}IWSCAN */ +static int gelic_wl_set_scan(struct net_device *netdev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct gelic_wl_info *wl = port_wl(netdev_priv(netdev)); + + return gelic_wl_start_scan(wl, 1); +} + +#define OUI_LEN 3 +static const u8 rsn_oui[OUI_LEN] = { 0x00, 0x0f, 0xac }; +static const u8 wpa_oui[OUI_LEN] = { 0x00, 0x50, 0xf2 }; + +/* + * synthesize WPA/RSN IE data + * See WiFi WPA specification and IEEE 802.11-2007 7.3.2.25 + * for the format + */ +static size_t gelic_wl_synthesize_ie(u8 *buf, + struct gelic_eurus_scan_info *scan) +{ + + const u8 *oui_header; + u8 *start = buf; + int rsn; + int ccmp; + + pr_debug("%s: <- sec=%16x\n", __func__, scan->security); + switch (be16_to_cpu(scan->security) & GELIC_EURUS_SCAN_SEC_MASK) { + case GELIC_EURUS_SCAN_SEC_WPA: + rsn = 0; + break; + case GELIC_EURUS_SCAN_SEC_WPA2: + rsn = 1; + break; + default: + /* WEP or none. No IE returned */ + return 0; + } + + switch (be16_to_cpu(scan->security) & GELIC_EURUS_SCAN_SEC_WPA_MASK) { + case GELIC_EURUS_SCAN_SEC_WPA_TKIP: + ccmp = 0; + break; + case GELIC_EURUS_SCAN_SEC_WPA_AES: + ccmp = 1; + break; + default: + if (rsn) { + ccmp = 1; + pr_info("%s: no cipher info. defaulted to CCMP\n", + __func__); + } else { + ccmp = 0; + pr_info("%s: no cipher info. defaulted to TKIP\n", + __func__); + } + } + + if (rsn) + oui_header = rsn_oui; + else + oui_header = wpa_oui; + + /* element id */ + if (rsn) + *buf++ = MFIE_TYPE_RSN; + else + *buf++ = MFIE_TYPE_GENERIC; + + /* length filed; set later */ + buf++; + + /* wpa special header */ + if (!rsn) { + memcpy(buf, wpa_oui, OUI_LEN); + buf += OUI_LEN; + *buf++ = 0x01; + } + + /* version */ + *buf++ = 0x01; /* version 1.0 */ + *buf++ = 0x00; + + /* group cipher */ + memcpy(buf, oui_header, OUI_LEN); + buf += OUI_LEN; + + if (ccmp) + *buf++ = 0x04; /* CCMP */ + else + *buf++ = 0x02; /* TKIP */ + + /* pairwise key count always 1 */ + *buf++ = 0x01; + *buf++ = 0x00; + + /* pairwise key suit */ + memcpy(buf, oui_header, OUI_LEN); + buf += OUI_LEN; + if (ccmp) + *buf++ = 0x04; /* CCMP */ + else + *buf++ = 0x02; /* TKIP */ + + /* AKM count is 1 */ + *buf++ = 0x01; + *buf++ = 0x00; + + /* AKM suite is assumed as PSK*/ + memcpy(buf, oui_header, OUI_LEN); + buf += OUI_LEN; + *buf++ = 0x02; /* PSK */ + + /* RSN capabilities is 0 */ + *buf++ = 0x00; + *buf++ = 0x00; + + /* set length field */ + start[1] = (buf - start - 2); + + pr_debug("%s: ->\n", __func__); + return (buf - start); +} + +struct ie_item { + u8 *data; + u8 len; +}; + +struct ie_info { + struct ie_item wpa; + struct ie_item rsn; +}; + +static void gelic_wl_parse_ie(u8 *data, size_t len, + struct ie_info *ie_info) +{ + size_t data_left = len; + u8 *pos = data; + u8 item_len; + u8 item_id; + + pr_debug("%s: data=%p len=%ld \n", __func__, + data, len); + memset(ie_info, 0, sizeof(struct ie_info)); + + while (0 < data_left) { + item_id = *pos++; + item_len = *pos++; + + switch (item_id) { + case MFIE_TYPE_GENERIC: + if (!memcmp(pos, wpa_oui, OUI_LEN) && + pos[OUI_LEN] == 0x01) { + ie_info->wpa.data = pos - 2; + ie_info->wpa.len = item_len + 2; + } + break; + case MFIE_TYPE_RSN: + ie_info->rsn.data = pos - 2; + /* length includes the header */ + ie_info->rsn.len = item_len + 2; + break; + default: + pr_debug("%s: ignore %#x,%d\n", __func__, + item_id, item_len); + break; + } + pos += item_len; + data_left -= item_len + 2; + } + pr_debug("%s: wpa=%p,%d wpa2=%p,%d\n", __func__, + ie_info->wpa.data, ie_info->wpa.len, + ie_info->rsn.data, ie_info->rsn.len); +} + + +/* + * translate the scan informations from hypervisor to a + * independent format + */ +static char *gelic_wl_translate_scan(struct net_device *netdev, + char *ev, + char *stop, + struct gelic_wl_scan_info *network) +{ + struct iw_event iwe; + struct gelic_eurus_scan_info *scan = network->hwinfo; + char *tmp; + u8 rate; + unsigned int i, j, len; + u8 buf[MAX_WPA_IE_LEN]; + + pr_debug("%s: <-\n", __func__); + + /* first entry should be AP's mac address */ + iwe.cmd = SIOCGIWAP; + iwe.u.ap_addr.sa_family = ARPHRD_ETHER; + memcpy(iwe.u.ap_addr.sa_data, &scan->bssid[2], ETH_ALEN); + ev = iwe_stream_add_event(ev, stop, &iwe, IW_EV_ADDR_LEN); + + /* ESSID */ + iwe.cmd = SIOCGIWESSID; + iwe.u.data.flags = 1; + iwe.u.data.length = strnlen(scan->essid, 32); + ev = iwe_stream_add_point(ev, stop, &iwe, scan->essid); + + /* FREQUENCY */ + iwe.cmd = SIOCGIWFREQ; + iwe.u.freq.m = be16_to_cpu(scan->channel); + iwe.u.freq.e = 0; /* table value in MHz */ + iwe.u.freq.i = 0; + ev = iwe_stream_add_event(ev, stop, &iwe, IW_EV_FREQ_LEN); + + /* RATES */ + iwe.cmd = SIOCGIWRATE; + iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0; + /* to stuff multiple values in one event */ + tmp = ev + IW_EV_LCP_LEN; + /* put them in ascendant order (older is first) */ + i = 0; + j = 0; + pr_debug("%s: rates=%d rate=%d\n", __func__, + network->rate_len, network->rate_ext_len); + while (i < network->rate_len) { + if (j < network->rate_ext_len && + ((scan->ext_rate[j] & 0x7f) < (scan->rate[i] & 0x7f))) + rate = scan->ext_rate[j++] & 0x7f; + else + rate = scan->rate[i++] & 0x7f; + iwe.u.bitrate.value = rate * 500000; /* 500kbps unit */ + tmp = iwe_stream_add_value(ev, tmp, stop, &iwe, + IW_EV_PARAM_LEN); + } + while (j < network->rate_ext_len) { + iwe.u.bitrate.value = (scan->ext_rate[j++] & 0x7f) * 500000; + tmp = iwe_stream_add_value(ev, tmp, stop, &iwe, + IW_EV_PARAM_LEN); + } + /* Check if we added any rate */ + if (IW_EV_LCP_LEN < (tmp - ev)) + ev = tmp; + + /* ENCODE */ + iwe.cmd = SIOCGIWENCODE; + if (be16_to_cpu(scan->capability) & WLAN_CAPABILITY_PRIVACY) + iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; + else + iwe.u.data.flags = IW_ENCODE_DISABLED; + iwe.u.data.length = 0; + ev = iwe_stream_add_point(ev, stop, &iwe, scan->essid); + + /* MODE */ + iwe.cmd = SIOCGIWMODE; + if (be16_to_cpu(scan->capability) & + (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS)) { + if (be16_to_cpu(scan->capability) & WLAN_CAPABILITY_ESS) + iwe.u.mode = IW_MODE_MASTER; + else + iwe.u.mode = IW_MODE_ADHOC; + ev = iwe_stream_add_event(ev, stop, &iwe, IW_EV_UINT_LEN); + } + + /* QUAL */ + iwe.cmd = IWEVQUAL; + iwe.u.qual.updated = IW_QUAL_ALL_UPDATED | + IW_QUAL_QUAL_INVALID | IW_QUAL_NOISE_INVALID; + iwe.u.qual.level = be16_to_cpu(scan->rssi); + iwe.u.qual.qual = be16_to_cpu(scan->rssi); + iwe.u.qual.noise = 0; + ev = iwe_stream_add_event(ev, stop, &iwe, IW_EV_QUAL_LEN); + + /* RSN */ + memset(&iwe, 0, sizeof(iwe)); + if (be16_to_cpu(scan->size) <= sizeof(*scan)) { + /* If wpa[2] capable station, synthesize IE and put it */ + len = gelic_wl_synthesize_ie(buf, scan); + if (len) { + iwe.cmd = IWEVGENIE; + iwe.u.data.length = len; + ev = iwe_stream_add_point(ev, stop, &iwe, buf); + } + } else { + /* this scan info has IE data */ + struct ie_info ie_info; + size_t data_len; + + data_len = be16_to_cpu(scan->size) - sizeof(*scan); + + gelic_wl_parse_ie(scan->elements, data_len, &ie_info); + + if (ie_info.wpa.len && (ie_info.wpa.len <= sizeof(buf))) { + memcpy(buf, ie_info.wpa.data, ie_info.wpa.len); + iwe.cmd = IWEVGENIE; + iwe.u.data.length = ie_info.wpa.len; + ev = iwe_stream_add_point(ev, stop, &iwe, buf); + } + + if (ie_info.rsn.len && (ie_info.rsn.len <= sizeof(buf))) { + memset(&iwe, 0, sizeof(iwe)); + memcpy(buf, ie_info.rsn.data, ie_info.rsn.len); + iwe.cmd = IWEVGENIE; + iwe.u.data.length = ie_info.rsn.len; + ev = iwe_stream_add_point(ev, stop, &iwe, buf); + } + } + + pr_debug("%s: ->\n", __func__); + return ev; +} + + +static int gelic_wl_get_scan(struct net_device *netdev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct gelic_wl_info *wl = port_wl(netdev_priv(netdev)); + struct gelic_wl_scan_info *scan_info; + char *ev = extra; + char *stop = ev + wrqu->data.length; + int ret = 0; + unsigned long this_time = jiffies; + + pr_debug("%s: <-\n", __func__); + if (down_interruptible(&wl->scan_lock)) + return -EAGAIN; + + switch (wl->scan_stat) { + case GELIC_WL_SCAN_STAT_SCANNING: + /* If a scan in progress, caller should call me again */ + ret = -EAGAIN; + goto out; + break; + + case GELIC_WL_SCAN_STAT_INIT: + /* last scan request failed or never issued */ + ret = -ENODEV; + goto out; + break; + case GELIC_WL_SCAN_STAT_GOT_LIST: + /* ok, use current list */ + break; + } + + list_for_each_entry(scan_info, &wl->network_list, list) { + if (wl->scan_age == 0 || + time_after(scan_info->last_scanned + wl->scan_age, + this_time)) + ev = gelic_wl_translate_scan(netdev, ev, stop, + scan_info); + else + pr_debug("%s:entry too old\n", __func__); + + if (stop - ev <= IW_EV_ADDR_LEN) { + ret = -E2BIG; + goto out; + } + } + + wrqu->data.length = ev - extra; + wrqu->data.flags = 0; +out: + up(&wl->scan_lock); + pr_debug("%s: -> %d %d\n", __func__, ret, wrqu->data.length); + return ret; +} + +#ifdef DEBUG +static void scan_list_dump(struct gelic_wl_info *wl) +{ + struct gelic_wl_scan_info *scan_info; + int i; + DECLARE_MAC_BUF(mac); + + i = 0; + list_for_each_entry(scan_info, &wl->network_list, list) { + pr_debug("%s: item %d\n", __func__, i++); + pr_debug("valid=%d eurusindex=%d last=%lx\n", + scan_info->valid, scan_info->eurus_index, + scan_info->last_scanned); + pr_debug("r_len=%d r_ext_len=%d essid_len=%d\n", + scan_info->rate_len, scan_info->rate_ext_len, + scan_info->essid_len); + /* -- */ + pr_debug("bssid=%s\n", + print_mac(mac, &scan_info->hwinfo->bssid[2])); + pr_debug("essid=%s\n", scan_info->hwinfo->essid); + } +} +#endif + +static int gelic_wl_set_auth(struct net_device *netdev, + struct iw_request_info *info, + union iwreq_data *data, char *extra) +{ + struct iw_param *param = &data->param; + struct gelic_wl_info *wl = port_wl(netdev_port(netdev)); + unsigned long irqflag; + int ret = 0; + + pr_debug("%s: <- %d\n", __func__, param->flags & IW_AUTH_INDEX); + spin_lock_irqsave(&wl->lock, irqflag); + switch (param->flags & IW_AUTH_INDEX) { + case IW_AUTH_WPA_VERSION: + if (param->value & IW_AUTH_WPA_VERSION_DISABLED) { + pr_debug("%s: NO WPA selected\n", __func__); + wl->wpa_level = GELIC_WL_WPA_LEVEL_NONE; + wl->group_cipher_method = GELIC_WL_CIPHER_WEP; + wl->pairwise_cipher_method = GELIC_WL_CIPHER_WEP; + } + if (param->value & IW_AUTH_WPA_VERSION_WPA) { + pr_debug("%s: WPA version 1 selected\n", __func__); + wl->wpa_level = GELIC_WL_WPA_LEVEL_WPA; + wl->group_cipher_method = GELIC_WL_CIPHER_TKIP; + wl->pairwise_cipher_method = GELIC_WL_CIPHER_TKIP; + wl->auth_method = GELIC_EURUS_AUTH_OPEN; + } + if (param->value & IW_AUTH_WPA_VERSION_WPA2) { + /* + * As the hypervisor may not tell the cipher + * information of the AP if it is WPA2, + * you will not decide suitable cipher from + * its beacon. + * You should have knowledge about the AP's + * cipher infomation in other method prior to + * the association. + */ + if (!precise_ie()) + pr_info("%s: WPA2 may not work\n", __func__); + if (wpa2_capable()) { + wl->wpa_level = GELIC_WL_WPA_LEVEL_WPA2; + wl->group_cipher_method = GELIC_WL_CIPHER_AES; + wl->pairwise_cipher_method = + GELIC_WL_CIPHER_AES; + wl->auth_method = GELIC_EURUS_AUTH_OPEN; + } else + ret = -EINVAL; + } + break; + + case IW_AUTH_CIPHER_PAIRWISE: + if (param->value & + (IW_AUTH_CIPHER_WEP104 | IW_AUTH_CIPHER_WEP40)) { + pr_debug("%s: WEP selected\n", __func__); + wl->pairwise_cipher_method = GELIC_WL_CIPHER_WEP; + } + if (param->value & IW_AUTH_CIPHER_TKIP) { + pr_debug("%s: TKIP selected\n", __func__); + wl->pairwise_cipher_method = GELIC_WL_CIPHER_TKIP; + } + if (param->value & IW_AUTH_CIPHER_CCMP) { + pr_debug("%s: CCMP selected\n", __func__); + wl->pairwise_cipher_method = GELIC_WL_CIPHER_AES; + } + if (param->value & IW_AUTH_CIPHER_NONE) { + pr_debug("%s: no auth selected\n", __func__); + wl->pairwise_cipher_method = GELIC_WL_CIPHER_NONE; + } + break; + case IW_AUTH_CIPHER_GROUP: + if (param->value & + (IW_AUTH_CIPHER_WEP104 | IW_AUTH_CIPHER_WEP40)) { + pr_debug("%s: WEP selected\n", __func__); + wl->group_cipher_method = GELIC_WL_CIPHER_WEP; + } + if (param->value & IW_AUTH_CIPHER_TKIP) { + pr_debug("%s: TKIP selected\n", __func__); + wl->group_cipher_method = GELIC_WL_CIPHER_TKIP; + } + if (param->value & IW_AUTH_CIPHER_CCMP) { + pr_debug("%s: CCMP selected\n", __func__); + wl->group_cipher_method = GELIC_WL_CIPHER_AES; + } + if (param->value & IW_AUTH_CIPHER_NONE) { + pr_debug("%s: no auth selected\n", __func__); + wl->group_cipher_method = GELIC_WL_CIPHER_NONE; + } + break; + case IW_AUTH_80211_AUTH_ALG: + if (param->value & IW_AUTH_ALG_SHARED_KEY) { + pr_debug("%s: shared key specified\n", __func__); + wl->auth_method = GELIC_EURUS_AUTH_SHARED; + } else if (param->value & IW_AUTH_ALG_OPEN_SYSTEM) { + pr_debug("%s: open system specified\n", __func__); + wl->auth_method = GELIC_EURUS_AUTH_OPEN; + } else + ret = -EINVAL; + break; + + case IW_AUTH_WPA_ENABLED: + if (param->value) { + pr_debug("%s: WPA enabled\n", __func__); + wl->wpa_level = GELIC_WL_WPA_LEVEL_WPA; + } else { + pr_debug("%s: WPA disabled\n", __func__); + wl->wpa_level = GELIC_WL_WPA_LEVEL_NONE; + } + break; + + case IW_AUTH_KEY_MGMT: + if (param->value & IW_AUTH_KEY_MGMT_PSK) + break; + /* intentionally fall through */ + default: + ret = -EOPNOTSUPP; + break; + }; + + if (!ret) + set_bit(GELIC_WL_STAT_CONFIGURED, &wl->stat); + + spin_unlock_irqrestore(&wl->lock, irqflag); + pr_debug("%s: -> %d\n", __func__, ret); + return ret; +} + +static int gelic_wl_get_auth(struct net_device *netdev, + struct iw_request_info *info, + union iwreq_data *iwreq, char *extra) +{ + struct iw_param *param = &iwreq->param; + struct gelic_wl_info *wl = port_wl(netdev_port(netdev)); + unsigned long irqflag; + int ret = 0; + + pr_debug("%s: <- %d\n", __func__, param->flags & IW_AUTH_INDEX); + spin_lock_irqsave(&wl->lock, irqflag); + switch (param->flags & IW_AUTH_INDEX) { + case IW_AUTH_WPA_VERSION: + switch (wl->wpa_level) { + case GELIC_WL_WPA_LEVEL_WPA: + param->value |= IW_AUTH_WPA_VERSION_WPA; + break; + case GELIC_WL_WPA_LEVEL_WPA2: + param->value |= IW_AUTH_WPA_VERSION_WPA2; + break; + default: + param->value |= IW_AUTH_WPA_VERSION_DISABLED; + } + break; + + case IW_AUTH_80211_AUTH_ALG: + if (wl->auth_method == GELIC_EURUS_AUTH_SHARED) + param->value = IW_AUTH_ALG_SHARED_KEY; + else if (wl->auth_method == GELIC_EURUS_AUTH_OPEN) + param->value = IW_AUTH_ALG_OPEN_SYSTEM; + break; + + case IW_AUTH_WPA_ENABLED: + switch (wl->wpa_level) { + case GELIC_WL_WPA_LEVEL_WPA: + case GELIC_WL_WPA_LEVEL_WPA2: + param->value = 1; + break; + default: + param->value = 0; + break; + } + break; + default: + ret = -EOPNOTSUPP; + } + + spin_unlock_irqrestore(&wl->lock, irqflag); + pr_debug("%s: -> %d\n", __func__, ret); + return ret; +} + +/* SIOC{S,G}IWESSID */ +static int gelic_wl_set_essid(struct net_device *netdev, + struct iw_request_info *info, + union iwreq_data *data, char *extra) +{ + struct gelic_wl_info *wl = port_wl(netdev_priv(netdev)); + unsigned long irqflag; + + pr_debug("%s: <- l=%d f=%d\n", __func__, + data->essid.length, data->essid.flags); + if (IW_ESSID_MAX_SIZE < data->essid.length) + return -EINVAL; + + spin_lock_irqsave(&wl->lock, irqflag); + if (data->essid.flags) { + wl->essid_len = data->essid.length; + memcpy(wl->essid, extra, wl->essid_len); + pr_debug("%s: essid = '%s'\n", __func__, extra); + set_bit(GELIC_WL_STAT_ESSID_SET, &wl->stat); + } else { + pr_debug("%s: ESSID any \n", __func__); + clear_bit(GELIC_WL_STAT_ESSID_SET, &wl->stat); + } + set_bit(GELIC_WL_STAT_CONFIGURED, &wl->stat); + spin_unlock_irqrestore(&wl->lock, irqflag); + + + gelic_wl_try_associate(netdev); /* FIXME */ + pr_debug("%s: -> \n", __func__); + return 0; +} + +static int gelic_wl_get_essid(struct net_device *netdev, + struct iw_request_info *info, + union iwreq_data *data, char *extra) +{ + struct gelic_wl_info *wl = port_wl(netdev_priv(netdev)); + unsigned long irqflag; + + pr_debug("%s: <- \n", __func__); + down(&wl->assoc_stat_lock); + spin_lock_irqsave(&wl->lock, irqflag); + if (test_bit(GELIC_WL_STAT_ESSID_SET, &wl->stat) || + wl->assoc_stat == GELIC_WL_ASSOC_STAT_ASSOCIATED) { + memcpy(extra, wl->essid, wl->essid_len); + data->essid.length = wl->essid_len; + data->essid.flags = 1; + } else + data->essid.flags = 0; + + up(&wl->assoc_stat_lock); + spin_unlock_irqrestore(&wl->lock, irqflag); + pr_debug("%s: -> len=%d \n", __func__, data->essid.length); + + return 0; +} + +/* SIO{S,G}IWENCODE */ +static int gelic_wl_set_encode(struct net_device *netdev, + struct iw_request_info *info, + union iwreq_data *data, char *extra) +{ + struct gelic_wl_info *wl = port_wl(netdev_priv(netdev)); + struct iw_point *enc = &data->encoding; + __u16 flags; + unsigned int irqflag; + int key_index, index_specified; + int ret = 0; + + pr_debug("%s: <- \n", __func__); + flags = enc->flags & IW_ENCODE_FLAGS; + key_index = enc->flags & IW_ENCODE_INDEX; + + pr_debug("%s: key_index = %d\n", __func__, key_index); + pr_debug("%s: key_len = %d\n", __func__, enc->length); + pr_debug("%s: flag=%x\n", __func__, enc->flags & IW_ENCODE_FLAGS); + + if (GELIC_WEP_KEYS < key_index) + return -EINVAL; + + spin_lock_irqsave(&wl->lock, irqflag); + if (key_index) { + index_specified = 1; + key_index--; + } else { + index_specified = 0; + key_index = wl->current_key; + } + + if (flags & IW_ENCODE_NOKEY) { + /* if just IW_ENCODE_NOKEY, change current key index */ + if (!flags && index_specified) { + wl->current_key = key_index; + goto done; + } + + if (flags & IW_ENCODE_DISABLED) { + if (!index_specified) { + /* disable encryption */ + wl->group_cipher_method = GELIC_WL_CIPHER_NONE; + wl->pairwise_cipher_method = + GELIC_WL_CIPHER_NONE; + /* invalidate all key */ + wl->key_enabled = 0; + } else + clear_bit(key_index, &wl->key_enabled); + } + + if (flags & IW_ENCODE_OPEN) + wl->auth_method = GELIC_EURUS_AUTH_OPEN; + if (flags & IW_ENCODE_RESTRICTED) { + pr_info("%s: shared key mode enabled\n", __func__); + wl->auth_method = GELIC_EURUS_AUTH_SHARED; + } + } else { + if (IW_ENCODING_TOKEN_MAX < enc->length) { + ret = -EINVAL; + goto done; + } + wl->key_len[key_index] = enc->length; + memcpy(wl->key[key_index], extra, enc->length); + set_bit(key_index, &wl->key_enabled); + wl->pairwise_cipher_method = GELIC_WL_CIPHER_WEP; + wl->group_cipher_method = GELIC_WL_CIPHER_WEP; + } + set_bit(GELIC_WL_STAT_CONFIGURED, &wl->stat); +done: + spin_unlock_irqrestore(&wl->lock, irqflag); + pr_debug("%s: -> \n", __func__); + return ret; +} + +static int gelic_wl_get_encode(struct net_device *netdev, + struct iw_request_info *info, + union iwreq_data *data, char *extra) +{ + struct gelic_wl_info *wl = port_wl(netdev_priv(netdev)); + struct iw_point *enc = &data->encoding; + unsigned int irqflag; + unsigned int key_index, index_specified; + int ret = 0; + + pr_debug("%s: <- \n", __func__); + key_index = enc->flags & IW_ENCODE_INDEX; + pr_debug("%s: flag=%#x point=%p len=%d extra=%p\n", __func__, + enc->flags, enc->pointer, enc->length, extra); + if (GELIC_WEP_KEYS < key_index) + return -EINVAL; + + spin_lock_irqsave(&wl->lock, irqflag); + if (key_index) { + index_specified = 1; + key_index--; + } else { + index_specified = 0; + key_index = wl->current_key; + } + + if (wl->group_cipher_method == GELIC_WL_CIPHER_WEP) { + switch (wl->auth_method) { + case GELIC_EURUS_AUTH_OPEN: + enc->flags = IW_ENCODE_OPEN; + break; + case GELIC_EURUS_AUTH_SHARED: + enc->flags = IW_ENCODE_RESTRICTED; + break; + } + } else + enc->flags = IW_ENCODE_DISABLED; + + if (test_bit(key_index, &wl->key_enabled)) { + if (enc->length < wl->key_len[key_index]) { + ret = -EINVAL; + goto done; + } + enc->length = wl->key_len[key_index]; + memcpy(extra, wl->key[key_index], wl->key_len[key_index]); + } else { + enc->length = 0; + enc->flags |= IW_ENCODE_NOKEY; + } + enc->flags |= key_index + 1; + pr_debug("%s: -> flag=%x len=%d\n", __func__, + enc->flags, enc->length); + +done: + spin_unlock_irqrestore(&wl->lock, irqflag); + return ret; +} + +/* SIOC{S,G}IWAP */ +static int gelic_wl_set_ap(struct net_device *netdev, + struct iw_request_info *info, + union iwreq_data *data, char *extra) +{ + struct gelic_wl_info *wl = port_wl(netdev_priv(netdev)); + unsigned long irqflag; + + pr_debug("%s: <-\n", __func__); + if (data->ap_addr.sa_family != ARPHRD_ETHER) + return -EINVAL; + + spin_lock_irqsave(&wl->lock, irqflag); + if (is_valid_ether_addr(data->ap_addr.sa_data)) { + memcpy(wl->bssid, data->ap_addr.sa_data, + ETH_ALEN); + set_bit(GELIC_WL_STAT_BSSID_SET, &wl->stat); + set_bit(GELIC_WL_STAT_CONFIGURED, &wl->stat); + pr_debug("%s: bss=%02x:%02x:%02x:%02x:%02x:%02x\n", + __func__, + wl->bssid[0], wl->bssid[1], + wl->bssid[2], wl->bssid[3], + wl->bssid[4], wl->bssid[5]); + } else { + pr_debug("%s: clear bssid\n", __func__); + clear_bit(GELIC_WL_STAT_BSSID_SET, &wl->stat); + memset(wl->bssid, 0, ETH_ALEN); + } + spin_unlock_irqrestore(&wl->lock, irqflag); + pr_debug("%s: ->\n", __func__); + return 0; +} + +static int gelic_wl_get_ap(struct net_device *netdev, + struct iw_request_info *info, + union iwreq_data *data, char *extra) +{ + struct gelic_wl_info *wl = port_wl(netdev_priv(netdev)); + unsigned long irqflag; + + pr_debug("%s: <-\n", __func__); + down(&wl->assoc_stat_lock); + spin_lock_irqsave(&wl->lock, irqflag); + if (wl->assoc_stat == GELIC_WL_ASSOC_STAT_ASSOCIATED) { + data->ap_addr.sa_family = ARPHRD_ETHER; + memcpy(data->ap_addr.sa_data, wl->active_bssid, + ETH_ALEN); + } else + memset(data->ap_addr.sa_data, 0, ETH_ALEN); + + spin_unlock_irqrestore(&wl->lock, irqflag); + up(&wl->assoc_stat_lock); + pr_debug("%s: ->\n", __func__); + return 0; +} + +/* SIOC{S,G}IWENCODEEXT */ +static int gelic_wl_set_encodeext(struct net_device *netdev, + struct iw_request_info *info, + union iwreq_data *data, char *extra) +{ + struct gelic_wl_info *wl = port_wl(netdev_priv(netdev)); + struct iw_point *enc = &data->encoding; + struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; + __u16 alg; + __u16 flags; + unsigned int irqflag; + int key_index; + int ret = 0; + + pr_debug("%s: <- \n", __func__); + flags = enc->flags & IW_ENCODE_FLAGS; + alg = ext->alg; + key_index = enc->flags & IW_ENCODE_INDEX; + + pr_debug("%s: key_index = %d\n", __func__, key_index); + pr_debug("%s: key_len = %d\n", __func__, enc->length); + pr_debug("%s: flag=%x\n", __func__, enc->flags & IW_ENCODE_FLAGS); + pr_debug("%s: ext_flag=%x\n", __func__, ext->ext_flags); + pr_debug("%s: ext_key_len=%x\n", __func__, ext->key_len); + + if (GELIC_WEP_KEYS < key_index) + return -EINVAL; + + spin_lock_irqsave(&wl->lock, irqflag); + if (key_index) + key_index--; + else + key_index = wl->current_key; + + if (!enc->length && (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)) { + /* reques to change default key index */ + pr_debug("%s: request to change default key to %d\n", + __func__, key_index); + wl->current_key = key_index; + goto done; + } + + if (alg == IW_ENCODE_ALG_NONE || (flags & IW_ENCODE_DISABLED)) { + pr_debug("%s: alg disabled\n", __func__); + wl->wpa_level = GELIC_WL_WPA_LEVEL_NONE; + wl->group_cipher_method = GELIC_WL_CIPHER_NONE; + wl->pairwise_cipher_method = GELIC_WL_CIPHER_NONE; + wl->auth_method = GELIC_EURUS_AUTH_OPEN; /* should be open */ + } else if (alg == IW_ENCODE_ALG_WEP) { + pr_debug("%s: WEP requested\n", __func__); + if (flags & IW_ENCODE_OPEN) { + pr_debug("%s: open key mode\n", __func__); + wl->auth_method = GELIC_EURUS_AUTH_OPEN; + } + if (flags & IW_ENCODE_RESTRICTED) { + pr_debug("%s: shared key mode\n", __func__); + wl->auth_method = GELIC_EURUS_AUTH_SHARED; + } + if (IW_ENCODING_TOKEN_MAX < ext->key_len) { + pr_info("%s: key is too long %d\n", __func__, + ext->key_len); + ret = -EINVAL; + goto done; + } + /* OK, update the key */ + wl->key_len[key_index] = ext->key_len; + memset(wl->key[key_index], 0, IW_ENCODING_TOKEN_MAX); + memcpy(wl->key[key_index], ext->key, ext->key_len); + set_bit(key_index, &wl->key_enabled); + /* remember wep info changed */ + set_bit(GELIC_WL_STAT_CONFIGURED, &wl->stat); + } else if ((alg == IW_ENCODE_ALG_TKIP) || (alg == IW_ENCODE_ALG_CCMP)) { + pr_debug("%s: TKIP/CCMP requested alg=%d\n", __func__, alg); + /* check key length */ + if (IW_ENCODING_TOKEN_MAX < ext->key_len) { + pr_info("%s: key is too long %d\n", __func__, + ext->key_len); + ret = -EINVAL; + goto done; + } + if (alg == IW_ENCODE_ALG_CCMP) { + pr_debug("%s: AES selected\n", __func__); + wl->group_cipher_method = GELIC_WL_CIPHER_AES; + wl->pairwise_cipher_method = GELIC_WL_CIPHER_AES; + wl->wpa_level = GELIC_WL_WPA_LEVEL_WPA2; + } else { + pr_debug("%s: TKIP selected, WPA forced\n", __func__); + wl->group_cipher_method = GELIC_WL_CIPHER_TKIP; + wl->pairwise_cipher_method = GELIC_WL_CIPHER_TKIP; + /* FIXME: how do we do if WPA2 + TKIP? */ + wl->wpa_level = GELIC_WL_WPA_LEVEL_WPA; + } + if (flags & IW_ENCODE_RESTRICTED) + BUG(); + wl->auth_method = GELIC_EURUS_AUTH_OPEN; + /* We should use same key for both and unicast */ + if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) + pr_debug("%s: group key \n", __func__); + else + pr_debug("%s: unicast key \n", __func__); + /* OK, update the key */ + wl->key_len[key_index] = ext->key_len; + memset(wl->key[key_index], 0, IW_ENCODING_TOKEN_MAX); + memcpy(wl->key[key_index], ext->key, ext->key_len); + set_bit(key_index, &wl->key_enabled); + /* remember info changed */ + set_bit(GELIC_WL_STAT_CONFIGURED, &wl->stat); + } +done: + spin_unlock_irqrestore(&wl->lock, irqflag); + pr_debug("%s: -> \n", __func__); + return ret; +} + +static int gelic_wl_get_encodeext(struct net_device *netdev, + struct iw_request_info *info, + union iwreq_data *data, char *extra) +{ + struct gelic_wl_info *wl = port_wl(netdev_priv(netdev)); + struct iw_point *enc = &data->encoding; + struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; + unsigned int irqflag; + int key_index; + int ret = 0; + int max_key_len; + + pr_debug("%s: <- \n", __func__); + + max_key_len = enc->length - sizeof(struct iw_encode_ext); + if (max_key_len < 0) + return -EINVAL; + key_index = enc->flags & IW_ENCODE_INDEX; + + pr_debug("%s: key_index = %d\n", __func__, key_index); + pr_debug("%s: key_len = %d\n", __func__, enc->length); + pr_debug("%s: flag=%x\n", __func__, enc->flags & IW_ENCODE_FLAGS); + + if (GELIC_WEP_KEYS < key_index) + return -EINVAL; + + spin_lock_irqsave(&wl->lock, irqflag); + if (key_index) + key_index--; + else + key_index = wl->current_key; + + memset(ext, 0, sizeof(struct iw_encode_ext)); + switch (wl->group_cipher_method) { + case GELIC_WL_CIPHER_WEP: + ext->alg = IW_ENCODE_ALG_WEP; + enc->flags |= IW_ENCODE_ENABLED; + break; + case GELIC_WL_CIPHER_TKIP: + ext->alg = IW_ENCODE_ALG_TKIP; + enc->flags |= IW_ENCODE_ENABLED; + break; + case GELIC_WL_CIPHER_AES: + ext->alg = IW_ENCODE_ALG_CCMP; + enc->flags |= IW_ENCODE_ENABLED; + break; + case GELIC_WL_CIPHER_NONE: + default: + ext->alg = IW_ENCODE_ALG_NONE; + enc->flags |= IW_ENCODE_NOKEY; + break; + } + + if (!(enc->flags & IW_ENCODE_NOKEY)) { + if (max_key_len < wl->key_len[key_index]) { + ret = -E2BIG; + goto out; + } + if (test_bit(key_index, &wl->key_enabled)) + memcpy(ext->key, wl->key[key_index], + wl->key_len[key_index]); + else + pr_debug("%s: disabled key requested ix=%d\n", + __func__, key_index); + } +out: + spin_unlock_irqrestore(&wl->lock, irqflag); + pr_debug("%s: -> \n", __func__); + return ret; +} +/* SIOC{S,G}IWMODE */ +static int gelic_wl_set_mode(struct net_device *netdev, + struct iw_request_info *info, + union iwreq_data *data, char *extra) +{ + __u32 mode = data->mode; + int ret; + + pr_debug("%s: <- \n", __func__); + if (mode == IW_MODE_INFRA) + ret = 0; + else + ret = -EOPNOTSUPP; + pr_debug("%s: -> %d\n", __func__, ret); + return ret; +} + +static int gelic_wl_get_mode(struct net_device *netdev, + struct iw_request_info *info, + union iwreq_data *data, char *extra) +{ + __u32 *mode = &data->mode; + pr_debug("%s: <- \n", __func__); + *mode = IW_MODE_INFRA; + pr_debug("%s: ->\n", __func__); + return 0; +} + +/* SIOCIWFIRSTPRIV */ +static int hex2bin(u8 *str, u8 *bin, unsigned int len) +{ + unsigned int i; + static unsigned char *hex = "0123456789ABCDEF"; + unsigned char *p, *q; + u8 tmp; + + if (len != WPA_PSK_LEN * 2) + return -EINVAL; + + for (i = 0; i < WPA_PSK_LEN * 2; i += 2) { + p = strchr(hex, toupper(str[i])); + q = strchr(hex, toupper(str[i + 1])); + if (!p || !q) { + pr_info("%s: unconvertible PSK digit=%d\n", + __func__, i); + return -EINVAL; + } + tmp = ((p - hex) << 4) + (q - hex); + *bin++ = tmp; + } + return 0; +}; + +static int gelic_wl_priv_set_psk(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, char *extra) +{ + struct gelic_wl_info *wl = port_wl(netdev_priv(net_dev)); + unsigned int len; + unsigned int irqflag; + int ret = 0; + + pr_debug("%s:<- len=%d\n", __func__, data->data.length); + len = data->data.length - 1; + if (len <= 2) + return -EINVAL; + + spin_lock_irqsave(&wl->lock, irqflag); + if (extra[0] == '"' && extra[len - 1] == '"') { + pr_debug("%s: passphrase mode\n", __func__); + /* pass phrase */ + if (GELIC_WL_EURUS_PSK_MAX_LEN < (len - 2)) { + pr_info("%s: passphrase too long\n", __func__); + ret = -E2BIG; + goto out; + } + memset(wl->psk, 0, sizeof(wl->psk)); + wl->psk_len = len - 2; + memcpy(wl->psk, &(extra[1]), wl->psk_len); + wl->psk_type = GELIC_EURUS_WPA_PSK_PASSPHRASE; + } else { + ret = hex2bin(extra, wl->psk, len); + if (ret) + goto out; + wl->psk_len = WPA_PSK_LEN; + wl->psk_type = GELIC_EURUS_WPA_PSK_BIN; + } + set_bit(GELIC_WL_STAT_WPA_PSK_SET, &wl->stat); +out: + spin_unlock_irqrestore(&wl->lock, irqflag); + pr_debug("%s:->\n", __func__); + return ret; +} + +static int gelic_wl_priv_get_psk(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, char *extra) +{ + struct gelic_wl_info *wl = port_wl(netdev_priv(net_dev)); + char *p; + unsigned int irqflag; + unsigned int i; + + pr_debug("%s:<-\n", __func__); + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + spin_lock_irqsave(&wl->lock, irqflag); + p = extra; + if (test_bit(GELIC_WL_STAT_WPA_PSK_SET, &wl->stat)) { + if (wl->psk_type == GELIC_EURUS_WPA_PSK_BIN) { + for (i = 0; i < wl->psk_len; i++) { + sprintf(p, "%02xu", wl->psk[i]); + p += 2; + } + *p = '\0'; + data->data.length = wl->psk_len * 2; + } else { + *p++ = '"'; + memcpy(p, wl->psk, wl->psk_len); + p += wl->psk_len; + *p++ = '"'; + *p = '\0'; + data->data.length = wl->psk_len + 2; + } + } else + /* no psk set */ + data->data.length = 0; + spin_unlock_irqrestore(&wl->lock, irqflag); + pr_debug("%s:-> %d\n", __func__, data->data.length); + return 0; +} + +/* SIOCGIWNICKN */ +static int gelic_wl_get_nick(struct net_device *net_dev, + struct iw_request_info *info, + union iwreq_data *data, char *extra) +{ + strcpy(extra, "gelic_wl"); + data->data.length = strlen(extra); + data->data.flags = 1; + return 0; +} + + +/* --- */ + +static struct iw_statistics *gelic_wl_get_wireless_stats( + struct net_device *netdev) +{ + + struct gelic_wl_info *wl = port_wl(netdev_priv(netdev)); + struct gelic_eurus_cmd *cmd; + struct iw_statistics *is; + struct gelic_eurus_rssi_info *rssi; + + pr_debug("%s: <-\n", __func__); + + is = &wl->iwstat; + memset(is, 0, sizeof(*is)); + cmd = gelic_eurus_sync_cmd(wl, GELIC_EURUS_CMD_GET_RSSI_CFG, + wl->buf, sizeof(*rssi)); + if (cmd && !cmd->status && !cmd->cmd_status) { + rssi = wl->buf; + is->qual.level = be16_to_cpu(rssi->rssi); + is->qual.updated = IW_QUAL_LEVEL_UPDATED | + IW_QUAL_QUAL_INVALID | IW_QUAL_NOISE_INVALID; + } else + /* not associated */ + is->qual.updated = IW_QUAL_ALL_INVALID; + + kfree(cmd); + pr_debug("%s: ->\n", __func__); + return is; +} + +/* + * scanning helpers + */ +static int gelic_wl_start_scan(struct gelic_wl_info *wl, int always_scan) +{ + struct gelic_eurus_cmd *cmd; + int ret = 0; + + pr_debug("%s: <- always=%d\n", __func__, always_scan); + if (down_interruptible(&wl->scan_lock)) + return -ERESTARTSYS; + + /* + * If already a scan in progress, do not trigger more + */ + if (wl->scan_stat == GELIC_WL_SCAN_STAT_SCANNING) { + pr_debug("%s: scanning now\n", __func__); + goto out; + } + + init_completion(&wl->scan_done); + /* + * If we have already a bss list, don't try to get new + */ + if (!always_scan && wl->scan_stat == GELIC_WL_SCAN_STAT_GOT_LIST) { + pr_debug("%s: already has the list\n", __func__); + complete(&wl->scan_done); + goto out; + } + /* + * issue start scan request + */ + wl->scan_stat = GELIC_WL_SCAN_STAT_SCANNING; + cmd = gelic_eurus_sync_cmd(wl, GELIC_EURUS_CMD_START_SCAN, + NULL, 0); + if (!cmd || cmd->status || cmd->cmd_status) { + wl->scan_stat = GELIC_WL_SCAN_STAT_INIT; + complete(&wl->scan_done); + ret = -ENOMEM; + goto out; + } + kfree(cmd); +out: + up(&wl->scan_lock); + pr_debug("%s: ->\n", __func__); + return ret; +} + +/* + * retrieve scan result from the chip (hypervisor) + * this function is invoked by schedule work. + */ +static void gelic_wl_scan_complete_event(struct gelic_wl_info *wl) +{ + struct gelic_eurus_cmd *cmd = NULL; + struct gelic_wl_scan_info *target, *tmp; + struct gelic_wl_scan_info *oldest = NULL; + struct gelic_eurus_scan_info *scan_info; + unsigned int scan_info_size; + union iwreq_data data; + unsigned long this_time = jiffies; + unsigned int data_len, i, found, r; + DECLARE_MAC_BUF(mac); + + pr_debug("%s:start\n", __func__); + down(&wl->scan_lock); + + if (wl->scan_stat != GELIC_WL_SCAN_STAT_SCANNING) { + /* + * stop() may be called while scanning, ignore result + */ + pr_debug("%s: scan complete when stat != scanning(%d)\n", + __func__, wl->scan_stat); + goto out; + } + + cmd = gelic_eurus_sync_cmd(wl, GELIC_EURUS_CMD_GET_SCAN, + wl->buf, PAGE_SIZE); + if (!cmd || cmd->status || cmd->cmd_status) { + wl->scan_stat = GELIC_WL_SCAN_STAT_INIT; + pr_info("%s:cmd failed\n", __func__); + kfree(cmd); + goto out; + } + data_len = cmd->size; + pr_debug("%s: data_len = %d\n", __func__, data_len); + kfree(cmd); + + /* OK, bss list retrieved */ + wl->scan_stat = GELIC_WL_SCAN_STAT_GOT_LIST; + + /* mark all entries are old */ + list_for_each_entry_safe(target, tmp, &wl->network_list, list) { + target->valid = 0; + /* expire too old entries */ + if (time_before(target->last_scanned + wl->scan_age, + this_time)) { + kfree(target->hwinfo); + target->hwinfo = NULL; + list_move_tail(&target->list, &wl->network_free_list); + } + } + + /* put them in the newtork_list */ + scan_info = wl->buf; + scan_info_size = 0; + i = 0; + while (scan_info_size < data_len) { + pr_debug("%s:size=%d bssid=%s scan_info=%p\n", __func__, + be16_to_cpu(scan_info->size), + print_mac(mac, &scan_info->bssid[2]), scan_info); + found = 0; + oldest = NULL; + list_for_each_entry(target, &wl->network_list, list) { + if (!compare_ether_addr(&target->hwinfo->bssid[2], + &scan_info->bssid[2])) { + found = 1; + pr_debug("%s: same BBS found scanned list\n", + __func__); + break; + } + if (!oldest || + (target->last_scanned < oldest->last_scanned)) + oldest = target; + } + + if (!found) { + /* not found in the list */ + if (list_empty(&wl->network_free_list)) { + /* expire oldest */ + target = oldest; + } else { + target = list_entry(wl->network_free_list.next, + struct gelic_wl_scan_info, + list); + } + } + + /* update the item */ + target->last_scanned = this_time; + target->valid = 1; + target->eurus_index = i; + kfree(target->hwinfo); + target->hwinfo = kzalloc(be16_to_cpu(scan_info->size), + GFP_KERNEL); + if (!target->hwinfo) { + pr_info("%s: kzalloc failed\n", __func__); + i++; + scan_info_size += be16_to_cpu(scan_info->size); + scan_info = (void *)scan_info + + be16_to_cpu(scan_info->size); + continue; + } + /* copy hw scan info */ + memcpy(target->hwinfo, scan_info, scan_info->size); + target->essid_len = strnlen(scan_info->essid, + sizeof(scan_info->essid)); + target->rate_len = 0; + for (r = 0; r < MAX_RATES_LENGTH; r++) + if (scan_info->rate[r]) + target->rate_len++; + if (8 < target->rate_len) + pr_info("%s: AP returns %d rates\n", __func__, + target->rate_len); + target->rate_ext_len = 0; + for (r = 0; r < MAX_RATES_EX_LENGTH; r++) + if (scan_info->ext_rate[r]) + target->rate_ext_len++; + list_move_tail(&target->list, &wl->network_list); + /* bump pointer */ + i++; + scan_info_size += be16_to_cpu(scan_info->size); + scan_info = (void *)scan_info + be16_to_cpu(scan_info->size); + } + memset(&data, 0, sizeof(data)); + wireless_send_event(port_to_netdev(wl_port(wl)), SIOCGIWSCAN, &data, + NULL); +out: + complete(&wl->scan_done); + up(&wl->scan_lock); + pr_debug("%s:end\n", __func__); +} + +/* + * Select an appropriate bss from current scan list regarding + * current settings from userspace. + * The caller must hold wl->scan_lock, + * and on the state of wl->scan_state == GELIC_WL_SCAN_GOT_LIST + */ +static void update_best(struct gelic_wl_scan_info **best, + struct gelic_wl_scan_info *candid, + int *best_weight, + int *weight) +{ + if (*best_weight < ++(*weight)) { + *best_weight = *weight; + *best = candid; + } +} + +static +struct gelic_wl_scan_info *gelic_wl_find_best_bss(struct gelic_wl_info *wl) +{ + struct gelic_wl_scan_info *scan_info; + struct gelic_wl_scan_info *best_bss; + int weight, best_weight; + u16 security; + DECLARE_MAC_BUF(mac); + + pr_debug("%s: <-\n", __func__); + + best_bss = NULL; + best_weight = 0; + + list_for_each_entry(scan_info, &wl->network_list, list) { + pr_debug("%s: station %p\n", __func__, scan_info); + + if (!scan_info->valid) { + pr_debug("%s: station invalid\n", __func__); + continue; + } + + /* If bss specified, check it only */ + if (test_bit(GELIC_WL_STAT_BSSID_SET, &wl->stat)) { + if (!compare_ether_addr(&scan_info->hwinfo->bssid[2], + wl->bssid)) { + best_bss = scan_info; + pr_debug("%s: bssid matched\n", __func__); + break; + } else { + pr_debug("%s: bssid unmached\n", __func__); + continue; + } + } + + weight = 0; + + /* security */ + security = be16_to_cpu(scan_info->hwinfo->security) & + GELIC_EURUS_SCAN_SEC_MASK; + if (wl->wpa_level == GELIC_WL_WPA_LEVEL_WPA2) { + if (security == GELIC_EURUS_SCAN_SEC_WPA2) + update_best(&best_bss, scan_info, + &best_weight, &weight); + else + continue; + } else if (wl->wpa_level == GELIC_WL_WPA_LEVEL_WPA) { + if (security == GELIC_EURUS_SCAN_SEC_WPA) + update_best(&best_bss, scan_info, + &best_weight, &weight); + else + continue; + } else if (wl->wpa_level == GELIC_WL_WPA_LEVEL_NONE && + wl->group_cipher_method == GELIC_WL_CIPHER_WEP) { + if (security == GELIC_EURUS_SCAN_SEC_WEP) + update_best(&best_bss, scan_info, + &best_weight, &weight); + else + continue; + } + + /* If ESSID is set, check it */ + if (test_bit(GELIC_WL_STAT_ESSID_SET, &wl->stat)) { + if ((scan_info->essid_len == wl->essid_len) && + !strncmp(wl->essid, + scan_info->hwinfo->essid, + scan_info->essid_len)) + update_best(&best_bss, scan_info, + &best_weight, &weight); + else + continue; + } + } + +#ifdef DEBUG + pr_debug("%s: -> bss=%p\n", __func__, best_bss); + if (best_bss) { + pr_debug("%s:addr=%s\n", __func__, + print_mac(mac, &best_bss->hwinfo->bssid[2])); + } +#endif + return best_bss; +} + +/* + * Setup WEP configuration to the chip + * The caller must hold wl->scan_lock, + * and on the state of wl->scan_state == GELIC_WL_SCAN_GOT_LIST + */ +static int gelic_wl_do_wep_setup(struct gelic_wl_info *wl) +{ + unsigned int i; + struct gelic_eurus_wep_cfg *wep; + struct gelic_eurus_cmd *cmd; + int wep104 = 0; + int have_key = 0; + int ret = 0; + + pr_debug("%s: <-\n", __func__); + /* we can assume no one should uses the buffer */ + wep = wl->buf; + memset(wep, 0, sizeof(*wep)); + + if (wl->group_cipher_method == GELIC_WL_CIPHER_WEP) { + pr_debug("%s: WEP mode\n", __func__); + for (i = 0; i < GELIC_WEP_KEYS; i++) { + if (!test_bit(i, &wl->key_enabled)) + continue; + + pr_debug("%s: key#%d enabled\n", __func__, i); + have_key = 1; + if (wl->key_len[i] == 13) + wep104 = 1; + else if (wl->key_len[i] != 5) { + pr_info("%s: wrong wep key[%d]=%d\n", + __func__, i, wl->key_len[i]); + ret = -EINVAL; + goto out; + } + memcpy(wep->key[i], wl->key[i], wl->key_len[i]); + } + + if (!have_key) { + pr_info("%s: all wep key disabled\n", __func__); + ret = -EINVAL; + goto out; + } + + if (wep104) { + pr_debug("%s: 104bit key\n", __func__); + wep->security = cpu_to_be16(GELIC_EURUS_WEP_SEC_104BIT); + } else { + pr_debug("%s: 40bit key\n", __func__); + wep->security = cpu_to_be16(GELIC_EURUS_WEP_SEC_40BIT); + } + } else { + pr_debug("%s: NO encryption\n", __func__); + wep->security = cpu_to_be16(GELIC_EURUS_WEP_SEC_NONE); + } + + /* issue wep setup */ + cmd = gelic_eurus_sync_cmd(wl, GELIC_EURUS_CMD_SET_WEP_CFG, + wep, sizeof(*wep)); + if (!cmd) + ret = -ENOMEM; + else if (cmd->status || cmd->cmd_status) + ret = -ENXIO; + + kfree(cmd); +out: + pr_debug("%s: ->\n", __func__); + return ret; +} + +#ifdef DEBUG +static const char *wpasecstr(enum gelic_eurus_wpa_security sec) +{ + switch (sec) { + case GELIC_EURUS_WPA_SEC_NONE: + return "NONE"; + break; + case GELIC_EURUS_WPA_SEC_WPA_TKIP_TKIP: + return "WPA_TKIP_TKIP"; + break; + case GELIC_EURUS_WPA_SEC_WPA_TKIP_AES: + return "WPA_TKIP_AES"; + break; + case GELIC_EURUS_WPA_SEC_WPA_AES_AES: + return "WPA_AES_AES"; + break; + case GELIC_EURUS_WPA_SEC_WPA2_TKIP_TKIP: + return "WPA2_TKIP_TKIP"; + break; + case GELIC_EURUS_WPA_SEC_WPA2_TKIP_AES: + return "WPA2_TKIP_AES"; + break; + case GELIC_EURUS_WPA_SEC_WPA2_AES_AES: + return "WPA2_AES_AES"; + break; + } + return ""; +}; +#endif + +static int gelic_wl_do_wpa_setup(struct gelic_wl_info *wl) +{ + struct gelic_eurus_wpa_cfg *wpa; + struct gelic_eurus_cmd *cmd; + u16 security; + int ret = 0; + + pr_debug("%s: <-\n", __func__); + /* we can assume no one should uses the buffer */ + wpa = wl->buf; + memset(wpa, 0, sizeof(*wpa)); + + if (!test_bit(GELIC_WL_STAT_WPA_PSK_SET, &wl->stat)) + pr_info("%s: PSK not configured yet\n", __func__); + + /* copy key */ + memcpy(wpa->psk, wl->psk, wl->psk_len); + + /* set security level */ + if (wl->wpa_level == GELIC_WL_WPA_LEVEL_WPA2) { + if (wl->group_cipher_method == GELIC_WL_CIPHER_AES) { + security = GELIC_EURUS_WPA_SEC_WPA2_AES_AES; + } else { + if (wl->pairwise_cipher_method == GELIC_WL_CIPHER_AES && + precise_ie()) + security = GELIC_EURUS_WPA_SEC_WPA2_TKIP_AES; + else + security = GELIC_EURUS_WPA_SEC_WPA2_TKIP_TKIP; + } + } else { + if (wl->group_cipher_method == GELIC_WL_CIPHER_AES) { + security = GELIC_EURUS_WPA_SEC_WPA_AES_AES; + } else { + if (wl->pairwise_cipher_method == GELIC_WL_CIPHER_AES && + precise_ie()) + security = GELIC_EURUS_WPA_SEC_WPA_TKIP_AES; + else + security = GELIC_EURUS_WPA_SEC_WPA_TKIP_TKIP; + } + } + wpa->security = cpu_to_be16(security); + + /* PSK type */ + wpa->psk_type = cpu_to_be16(wl->psk_type); +#ifdef DEBUG + pr_debug("%s: sec=%s psktype=%s\nn", __func__, + wpasecstr(wpa->security), + (wpa->psk_type == GELIC_EURUS_WPA_PSK_BIN) ? + "BIN" : "passphrase"); +#if 0 + /* + * don't enable here if you plan to submit + * the debug log because this dumps your precious + * passphrase/key. + */ + pr_debug("%s: psk=%s\n", + (wpa->psk_type == GELIC_EURUS_WPA_PSK_BIN) ? + (char *)"N/A" : (char *)wpa->psk); +#endif +#endif + /* issue wpa setup */ + cmd = gelic_eurus_sync_cmd(wl, GELIC_EURUS_CMD_SET_WPA_CFG, + wpa, sizeof(*wpa)); + if (!cmd) + ret = -ENOMEM; + else if (cmd->status || cmd->cmd_status) + ret = -ENXIO; + kfree(cmd); + pr_debug("%s: --> %d\n", __func__, ret); + return ret; +} + +/* + * Start association. caller must hold assoc_stat_lock + */ +static int gelic_wl_associate_bss(struct gelic_wl_info *wl, + struct gelic_wl_scan_info *bss) +{ + struct gelic_eurus_cmd *cmd; + struct gelic_eurus_common_cfg *common; + int ret = 0; + unsigned long rc; + + pr_debug("%s: <-\n", __func__); + + /* do common config */ + common = wl->buf; + memset(common, 0, sizeof(*common)); + common->bss_type = cpu_to_be16(GELIC_EURUS_BSS_INFRA); + common->op_mode = cpu_to_be16(GELIC_EURUS_OPMODE_11BG); + + common->scan_index = cpu_to_be16(bss->eurus_index); + switch (wl->auth_method) { + case GELIC_EURUS_AUTH_OPEN: + common->auth_method = cpu_to_be16(GELIC_EURUS_AUTH_OPEN); + break; + case GELIC_EURUS_AUTH_SHARED: + common->auth_method = cpu_to_be16(GELIC_EURUS_AUTH_SHARED); + break; + } + +#ifdef DEBUG + scan_list_dump(wl); +#endif + pr_debug("%s: common cfg index=%d bsstype=%d auth=%d\n", __func__, + be16_to_cpu(common->scan_index), + be16_to_cpu(common->bss_type), + be16_to_cpu(common->auth_method)); + + cmd = gelic_eurus_sync_cmd(wl, GELIC_EURUS_CMD_SET_COMMON_CFG, + common, sizeof(*common)); + if (!cmd || cmd->status || cmd->cmd_status) { + ret = -ENOMEM; + kfree(cmd); + goto out; + } + kfree(cmd); + + /* WEP/WPA */ + switch (wl->wpa_level) { + case GELIC_WL_WPA_LEVEL_NONE: + /* If WEP or no security, setup WEP config */ + ret = gelic_wl_do_wep_setup(wl); + break; + case GELIC_WL_WPA_LEVEL_WPA: + case GELIC_WL_WPA_LEVEL_WPA2: + ret = gelic_wl_do_wpa_setup(wl); + break; + }; + + if (ret) { + pr_debug("%s: WEP/WPA setup failed %d\n", __func__, + ret); + } + + /* start association */ + init_completion(&wl->assoc_done); + wl->assoc_stat = GELIC_WL_ASSOC_STAT_ASSOCIATING; + cmd = gelic_eurus_sync_cmd(wl, GELIC_EURUS_CMD_ASSOC, + NULL, 0); + if (!cmd || cmd->status || cmd->cmd_status) { + pr_debug("%s: assoc request failed\n", __func__); + wl->assoc_stat = GELIC_WL_ASSOC_STAT_DISCONN; + kfree(cmd); + ret = -ENOMEM; + gelic_wl_send_iwap_event(wl, NULL); + goto out; + } + kfree(cmd); + + /* wait for connected event */ + rc = wait_for_completion_timeout(&wl->assoc_done, HZ * 4);/*FIXME*/ + + if (!rc) { + /* timeouted. Maybe key or cyrpt mode is wrong */ + pr_info("%s: connect timeout \n", __func__); + cmd = gelic_eurus_sync_cmd(wl, GELIC_EURUS_CMD_DISASSOC, + NULL, 0); + kfree(cmd); + wl->assoc_stat = GELIC_WL_ASSOC_STAT_DISCONN; + gelic_wl_send_iwap_event(wl, NULL); + ret = -ENXIO; + } else { + wl->assoc_stat = GELIC_WL_ASSOC_STAT_ASSOCIATED; + /* copy bssid */ + memcpy(wl->active_bssid, &bss->hwinfo->bssid[2], ETH_ALEN); + + /* send connect event */ + gelic_wl_send_iwap_event(wl, wl->active_bssid); + pr_info("%s: connected\n", __func__); + } +out: + pr_debug("%s: ->\n", __func__); + return ret; +} + +/* + * connected event + */ +static void gelic_wl_connected_event(struct gelic_wl_info *wl, + u64 event) +{ + u64 desired_event = 0; + + switch (wl->wpa_level) { + case GELIC_WL_WPA_LEVEL_NONE: + desired_event = GELIC_LV1_WL_EVENT_CONNECTED; + break; + case GELIC_WL_WPA_LEVEL_WPA: + case GELIC_WL_WPA_LEVEL_WPA2: + desired_event = GELIC_LV1_WL_EVENT_WPA_CONNECTED; + break; + } + + if (desired_event == event) { + pr_debug("%s: completed \n", __func__); + complete(&wl->assoc_done); + netif_carrier_on(port_to_netdev(wl_port(wl))); + } else + pr_debug("%s: event %#lx under wpa\n", + __func__, event); +} + +/* + * disconnect event + */ +static void gelic_wl_disconnect_event(struct gelic_wl_info *wl, + u64 event) +{ + struct gelic_eurus_cmd *cmd; + int lock; + + /* + * If we fall here in the middle of association, + * associate_bss() should be waiting for complation of + * wl->assoc_done. + * As it waits with timeout, just leave assoc_done + * uncompleted, then it terminates with timeout + */ + if (down_trylock(&wl->assoc_stat_lock)) { + pr_debug("%s: already locked\n", __func__); + lock = 0; + } else { + pr_debug("%s: obtain lock\n", __func__); + lock = 1; + } + + cmd = gelic_eurus_sync_cmd(wl, GELIC_EURUS_CMD_DISASSOC, NULL, 0); + kfree(cmd); + + /* send disconnected event to the supplicant */ + if (wl->assoc_stat == GELIC_WL_ASSOC_STAT_ASSOCIATED) + gelic_wl_send_iwap_event(wl, NULL); + + wl->assoc_stat = GELIC_WL_ASSOC_STAT_DISCONN; + netif_carrier_off(port_to_netdev(wl_port(wl))); + + if (lock) + up(&wl->assoc_stat_lock); +} +/* + * event worker + */ +#ifdef DEBUG +static const char *eventstr(enum gelic_lv1_wl_event event) +{ + static char buf[32]; + char *ret; + if (event & GELIC_LV1_WL_EVENT_DEVICE_READY) + ret = "EURUS_READY"; + else if (event & GELIC_LV1_WL_EVENT_SCAN_COMPLETED) + ret = "SCAN_COMPLETED"; + else if (event & GELIC_LV1_WL_EVENT_DEAUTH) + ret = "DEAUTH"; + else if (event & GELIC_LV1_WL_EVENT_BEACON_LOST) + ret = "BEACON_LOST"; + else if (event & GELIC_LV1_WL_EVENT_CONNECTED) + ret = "CONNECTED"; + else if (event & GELIC_LV1_WL_EVENT_WPA_CONNECTED) + ret = "WPA_CONNECTED"; + else if (event & GELIC_LV1_WL_EVENT_WPA_ERROR) + ret = "WPA_ERROR"; + else { + sprintf(buf, "Unknown(%#x)", event); + ret = buf; + } + return ret; +} +#else +static const char *eventstr(enum gelic_lv1_wl_event event) +{ + return NULL; +} +#endif +static void gelic_wl_event_worker(struct work_struct *work) +{ + struct gelic_wl_info *wl; + struct gelic_port *port; + u64 event, tmp; + int status; + + pr_debug("%s:start\n", __func__); + wl = container_of(work, struct gelic_wl_info, event_work.work); + port = wl_port(wl); + while (1) { + status = lv1_net_control(bus_id(port->card), dev_id(port->card), + GELIC_LV1_GET_WLAN_EVENT, 0, 0, 0, + &event, &tmp); + if (status) { + if (status != LV1_NO_ENTRY) + pr_debug("%s:wlan event failed %d\n", + __func__, status); + /* got all events */ + pr_debug("%s:end\n", __func__); + return; + } + pr_debug("%s: event=%s\n", __func__, eventstr(event)); + switch (event) { + case GELIC_LV1_WL_EVENT_SCAN_COMPLETED: + gelic_wl_scan_complete_event(wl); + break; + case GELIC_LV1_WL_EVENT_BEACON_LOST: + case GELIC_LV1_WL_EVENT_DEAUTH: + gelic_wl_disconnect_event(wl, event); + break; + case GELIC_LV1_WL_EVENT_CONNECTED: + case GELIC_LV1_WL_EVENT_WPA_CONNECTED: + gelic_wl_connected_event(wl, event); + break; + default: + break; + } + } /* while */ +} +/* + * association worker + */ +static void gelic_wl_assoc_worker(struct work_struct *work) +{ + struct gelic_wl_info *wl; + + struct gelic_wl_scan_info *best_bss; + int ret; + + wl = container_of(work, struct gelic_wl_info, assoc_work.work); + + down(&wl->assoc_stat_lock); + + if (wl->assoc_stat != GELIC_WL_ASSOC_STAT_DISCONN) + goto out; + + ret = gelic_wl_start_scan(wl, 0); + if (ret == -ERESTARTSYS) { + pr_debug("%s: scan start failed association\n", __func__); + schedule_delayed_work(&wl->assoc_work, HZ/10); /*FIXME*/ + goto out; + } else if (ret) { + pr_info("%s: scan prerequisite failed\n", __func__); + goto out; + } + + /* + * Wait for bss scan completion + * If we have scan list already, gelic_wl_start_scan() + * returns OK and raises the complete. Thus, + * it's ok to wait unconditionally here + */ + wait_for_completion(&wl->scan_done); + + pr_debug("%s: scan done\n", __func__); + down(&wl->scan_lock); + if (wl->scan_stat != GELIC_WL_SCAN_STAT_GOT_LIST) { + gelic_wl_send_iwap_event(wl, NULL); + pr_info("%s: no scan list. association failed\n", __func__); + goto scan_lock_out; + } + + /* find best matching bss */ + best_bss = gelic_wl_find_best_bss(wl); + if (!best_bss) { + gelic_wl_send_iwap_event(wl, NULL); + pr_info("%s: no bss matched. association failed\n", __func__); + goto scan_lock_out; + } + + /* ok, do association */ + ret = gelic_wl_associate_bss(wl, best_bss); + if (ret) + pr_info("%s: association failed %d\n", __func__, ret); +scan_lock_out: + up(&wl->scan_lock); +out: + up(&wl->assoc_stat_lock); +} +/* + * Interrupt handler + * Called from the ethernet interrupt handler + * Processes wireless specific virtual interrupts only + */ +void gelic_wl_interrupt(struct net_device *netdev, u64 status) +{ + struct gelic_wl_info *wl = port_wl(netdev_priv(netdev)); + + if (status & GELIC_CARD_WLAN_COMMAND_COMPLETED) { + pr_debug("%s:cmd complete\n", __func__); + complete(&wl->cmd_done_intr); + } + + if (status & GELIC_CARD_WLAN_EVENT_RECEIVED) { + pr_debug("%s:event received\n", __func__); + queue_delayed_work(wl->event_queue, &wl->event_work, 0); + } +} + +/* + * driver helpers + */ +#define IW_IOCTL(n) [(n) - SIOCSIWCOMMIT] +static const iw_handler gelic_wl_wext_handler[] = +{ + IW_IOCTL(SIOCGIWNAME) = gelic_wl_get_name, + IW_IOCTL(SIOCGIWRANGE) = gelic_wl_get_range, + IW_IOCTL(SIOCSIWSCAN) = gelic_wl_set_scan, + IW_IOCTL(SIOCGIWSCAN) = gelic_wl_get_scan, + IW_IOCTL(SIOCSIWAUTH) = gelic_wl_set_auth, + IW_IOCTL(SIOCGIWAUTH) = gelic_wl_get_auth, + IW_IOCTL(SIOCSIWESSID) = gelic_wl_set_essid, + IW_IOCTL(SIOCGIWESSID) = gelic_wl_get_essid, + IW_IOCTL(SIOCSIWENCODE) = gelic_wl_set_encode, + IW_IOCTL(SIOCGIWENCODE) = gelic_wl_get_encode, + IW_IOCTL(SIOCSIWAP) = gelic_wl_set_ap, + IW_IOCTL(SIOCGIWAP) = gelic_wl_get_ap, + IW_IOCTL(SIOCSIWENCODEEXT) = gelic_wl_set_encodeext, + IW_IOCTL(SIOCGIWENCODEEXT) = gelic_wl_get_encodeext, + IW_IOCTL(SIOCSIWMODE) = gelic_wl_set_mode, + IW_IOCTL(SIOCGIWMODE) = gelic_wl_get_mode, + IW_IOCTL(SIOCGIWNICKN) = gelic_wl_get_nick, +}; + +static struct iw_priv_args gelic_wl_private_args[] = +{ + { + .cmd = GELIC_WL_PRIV_SET_PSK, + .set_args = IW_PRIV_TYPE_CHAR | + (GELIC_WL_EURUS_PSK_MAX_LEN + 2), + .name = "set_psk" + }, + { + .cmd = GELIC_WL_PRIV_GET_PSK, + .get_args = IW_PRIV_TYPE_CHAR | + (GELIC_WL_EURUS_PSK_MAX_LEN + 2), + .name = "get_psk" + } +}; + +static const iw_handler gelic_wl_private_handler[] = +{ + gelic_wl_priv_set_psk, + gelic_wl_priv_get_psk, +}; + +static const struct iw_handler_def gelic_wl_wext_handler_def = { + .num_standard = ARRAY_SIZE(gelic_wl_wext_handler), + .standard = gelic_wl_wext_handler, + .get_wireless_stats = gelic_wl_get_wireless_stats, + .num_private = ARRAY_SIZE(gelic_wl_private_handler), + .num_private_args = ARRAY_SIZE(gelic_wl_private_args), + .private = gelic_wl_private_handler, + .private_args = gelic_wl_private_args, +}; + +static struct net_device *gelic_wl_alloc(struct gelic_card *card) +{ + struct net_device *netdev; + struct gelic_port *port; + struct gelic_wl_info *wl; + unsigned int i; + + pr_debug("%s:start\n", __func__); + netdev = alloc_etherdev(sizeof(struct gelic_port) + + sizeof(struct gelic_wl_info)); + pr_debug("%s: netdev =%p card=%p \np", __func__, netdev, card); + if (!netdev) + return NULL; + + port = netdev_priv(netdev); + port->netdev = netdev; + port->card = card; + port->type = GELIC_PORT_WIRELESS; + + wl = port_wl(port); + pr_debug("%s: wl=%p port=%p\n", __func__, wl, port); + + /* allocate scan list */ + wl->networks = kzalloc(sizeof(struct gelic_wl_scan_info) * + GELIC_WL_BSS_MAX_ENT, GFP_KERNEL); + + if (!wl->networks) + goto fail_bss; + + wl->eurus_cmd_queue = create_singlethread_workqueue("gelic_cmd"); + if (!wl->eurus_cmd_queue) + goto fail_cmd_workqueue; + + wl->event_queue = create_singlethread_workqueue("gelic_event"); + if (!wl->event_queue) + goto fail_event_workqueue; + + INIT_LIST_HEAD(&wl->network_free_list); + INIT_LIST_HEAD(&wl->network_list); + for (i = 0; i < GELIC_WL_BSS_MAX_ENT; i++) + list_add_tail(&wl->networks[i].list, + &wl->network_free_list); + init_completion(&wl->cmd_done_intr); + + INIT_DELAYED_WORK(&wl->event_work, gelic_wl_event_worker); + INIT_DELAYED_WORK(&wl->assoc_work, gelic_wl_assoc_worker); + init_MUTEX(&wl->scan_lock); + init_MUTEX(&wl->assoc_stat_lock); + + init_completion(&wl->scan_done); + /* for the case that no scan request is issued and stop() is called */ + complete(&wl->scan_done); + + spin_lock_init(&wl->lock); + + wl->scan_age = 5*HZ; /* FIXME */ + + /* buffer for receiving scanned list etc */ + BUILD_BUG_ON(PAGE_SIZE < + sizeof(struct gelic_eurus_scan_info) * + GELIC_EURUS_MAX_SCAN); + wl->buf = (void *)get_zeroed_page(GFP_KERNEL); + if (!wl->buf) { + pr_info("%s:buffer allocation failed\n", __func__); + goto fail_getpage; + } + pr_debug("%s:end\n", __func__); + return netdev; + +fail_getpage: + destroy_workqueue(wl->event_queue); +fail_event_workqueue: + destroy_workqueue(wl->eurus_cmd_queue); +fail_cmd_workqueue: + kfree(wl->networks); +fail_bss: + free_netdev(netdev); + pr_debug("%s:end error\n", __func__); + return NULL; + +} + +static void gelic_wl_free(struct gelic_wl_info *wl) +{ + struct gelic_wl_scan_info *scan_info; + unsigned int i; + + pr_debug("%s: <-\n", __func__); + + pr_debug("%s: destroy queues\n", __func__); + destroy_workqueue(wl->eurus_cmd_queue); + destroy_workqueue(wl->event_queue); + + scan_info = wl->networks; + for (i = 0; i < GELIC_WL_BSS_MAX_ENT; i++, scan_info++) + kfree(scan_info->hwinfo); + kfree(wl->networks); + + free_netdev(port_to_netdev(wl_port(wl))); + + pr_debug("%s: ->\n", __func__); +} + +static int gelic_wl_try_associate(struct net_device *netdev) +{ + struct gelic_wl_info *wl = port_wl(netdev_priv(netdev)); + int ret = -1; + unsigned int i; + + pr_debug("%s: <-\n", __func__); + + /* check constraits for start association */ + /* for no access restriction AP */ + if (wl->group_cipher_method == GELIC_WL_CIPHER_NONE) { + if (test_bit(GELIC_WL_STAT_CONFIGURED, + &wl->stat)) + goto do_associate; + else { + pr_debug("%s: no wep, not configured\n", __func__); + return ret; + } + } + + /* for WEP, one of four keys should be set */ + if (wl->group_cipher_method == GELIC_WL_CIPHER_WEP) { + /* one of keys set */ + for (i = 0; i < GELIC_WEP_KEYS; i++) { + if (test_bit(i, &wl->key_enabled)) + goto do_associate; + } + pr_debug("%s: WEP, but no key specified\n", __func__); + return ret; + } + + /* for WPA[2], psk should be set */ + if ((wl->group_cipher_method == GELIC_WL_CIPHER_TKIP) || + (wl->group_cipher_method == GELIC_WL_CIPHER_AES)) { + if (test_bit(GELIC_WL_STAT_WPA_PSK_SET, + &wl->stat)) + goto do_associate; + else { + pr_debug("%s: AES/TKIP, but PSK not configured\n", + __func__); + return ret; + } + } + +do_associate: + ret = schedule_delayed_work(&wl->assoc_work, 0); + pr_debug("%s: start association work %d\n", __func__, ret); + return ret; +} + +/* + * netdev handlers + */ +static int gelic_wl_open(struct net_device *netdev) +{ + struct gelic_card *card = netdev_card(netdev); + + pr_debug("%s:->%p\n", __func__, netdev); + + gelic_card_up(card); + + /* try to associate */ + gelic_wl_try_associate(netdev); + + netif_start_queue(netdev); + + pr_debug("%s:<-\n", __func__); + return 0; +} + +/* + * reset state machine + */ +static int gelic_wl_reset_state(struct gelic_wl_info *wl) +{ + struct gelic_wl_scan_info *target; + struct gelic_wl_scan_info *tmp; + + /* empty scan list */ + list_for_each_entry_safe(target, tmp, &wl->network_list, list) { + list_move_tail(&target->list, &wl->network_free_list); + } + wl->scan_stat = GELIC_WL_SCAN_STAT_INIT; + + /* clear configuration */ + wl->auth_method = GELIC_EURUS_AUTH_OPEN; + wl->group_cipher_method = GELIC_WL_CIPHER_NONE; + wl->pairwise_cipher_method = GELIC_WL_CIPHER_NONE; + wl->wpa_level = GELIC_WL_WPA_LEVEL_NONE; + + wl->key_enabled = 0; + wl->current_key = 0; + + wl->psk_type = GELIC_EURUS_WPA_PSK_PASSPHRASE; + wl->psk_len = 0; + + wl->essid_len = 0; + memset(wl->essid, 0, sizeof(wl->essid)); + memset(wl->bssid, 0, sizeof(wl->bssid)); + memset(wl->active_bssid, 0, sizeof(wl->active_bssid)); + + wl->assoc_stat = GELIC_WL_ASSOC_STAT_DISCONN; + + memset(&wl->iwstat, 0, sizeof(wl->iwstat)); + /* all status bit clear */ + wl->stat = 0; + return 0; +} + +/* + * Tell eurus to terminate association + */ +static void gelic_wl_disconnect(struct net_device *netdev) +{ + struct gelic_port *port = netdev_priv(netdev); + struct gelic_wl_info *wl = port_wl(port); + struct gelic_eurus_cmd *cmd; + + /* + * If scann process is running on chip, + * further requests will be rejected + */ + if (wl->scan_stat == GELIC_WL_SCAN_STAT_SCANNING) + wait_for_completion_timeout(&wl->scan_done, HZ); + + cmd = gelic_eurus_sync_cmd(wl, GELIC_EURUS_CMD_DISASSOC, NULL, 0); + kfree(cmd); + gelic_wl_send_iwap_event(wl, NULL); +}; + +static int gelic_wl_stop(struct net_device *netdev) +{ + struct gelic_port *port = netdev_priv(netdev); + struct gelic_wl_info *wl = port_wl(port); + struct gelic_card *card = netdev_card(netdev); + + pr_debug("%s:<-\n", __func__); + + /* + * Cancel pending association work. + * event work can run after netdev down + */ + cancel_delayed_work(&wl->assoc_work); + + if (wl->assoc_stat == GELIC_WL_ASSOC_STAT_ASSOCIATED) + gelic_wl_disconnect(netdev); + + /* reset our state machine */ + gelic_wl_reset_state(wl); + + netif_stop_queue(netdev); + + gelic_card_down(card); + + pr_debug("%s:->\n", __func__); + return 0; +} + +/* -- */ + +static struct ethtool_ops gelic_wl_ethtool_ops = { + .get_drvinfo = gelic_net_get_drvinfo, + .get_link = gelic_wl_get_link, + .get_tx_csum = ethtool_op_get_tx_csum, + .set_tx_csum = ethtool_op_set_tx_csum, + .get_rx_csum = gelic_net_get_rx_csum, + .set_rx_csum = gelic_net_set_rx_csum, +}; + +static void gelic_wl_setup_netdev_ops(struct net_device *netdev) +{ + struct gelic_wl_info *wl; + wl = port_wl(netdev_priv(netdev)); + BUG_ON(!wl); + netdev->open = &gelic_wl_open; + netdev->stop = &gelic_wl_stop; + netdev->hard_start_xmit = &gelic_net_xmit; + netdev->set_multicast_list = &gelic_net_set_multi; + netdev->change_mtu = &gelic_net_change_mtu; + netdev->wireless_data = &wl->wireless_data; + netdev->wireless_handlers = &gelic_wl_wext_handler_def; + /* tx watchdog */ + netdev->tx_timeout = &gelic_net_tx_timeout; + netdev->watchdog_timeo = GELIC_NET_WATCHDOG_TIMEOUT; + + netdev->ethtool_ops = &gelic_wl_ethtool_ops; +#ifdef CONFIG_NET_POLL_CONTROLLER + netdev->poll_controller = gelic_net_poll_controller; +#endif +} + +/* + * driver probe/remove + */ +int gelic_wl_driver_probe(struct gelic_card *card) +{ + int ret; + struct net_device *netdev; + + pr_debug("%s:start\n", __func__); + + if (ps3_compare_firmware_version(1, 6, 0) < 0) + return 0; + if (!card->vlan[GELIC_PORT_WIRELESS].tx) + return 0; + + /* alloc netdevice for wireless */ + netdev = gelic_wl_alloc(card); + if (!netdev) + return -ENOMEM; + + /* setup net_device structure */ + gelic_wl_setup_netdev_ops(netdev); + + /* setup some of net_device and register it */ + ret = gelic_net_setup_netdev(netdev, card); + if (ret) + goto fail_setup; + card->netdev[GELIC_PORT_WIRELESS] = netdev; + + /* add enable wireless interrupt */ + card->irq_mask |= GELIC_CARD_WLAN_EVENT_RECEIVED | + GELIC_CARD_WLAN_COMMAND_COMPLETED; + /* to allow wireless commands while both interfaces are down */ + gelic_card_set_irq_mask(card, GELIC_CARD_WLAN_EVENT_RECEIVED | + GELIC_CARD_WLAN_COMMAND_COMPLETED); + pr_debug("%s:end\n", __func__); + return 0; + +fail_setup: + gelic_wl_free(port_wl(netdev_port(netdev))); + + return ret; +} + +int gelic_wl_driver_remove(struct gelic_card *card) +{ + struct gelic_wl_info *wl; + struct net_device *netdev; + + pr_debug("%s:start\n", __func__); + + if (ps3_compare_firmware_version(1, 6, 0) < 0) + return 0; + if (!card->vlan[GELIC_PORT_WIRELESS].tx) + return 0; + + netdev = card->netdev[GELIC_PORT_WIRELESS]; + wl = port_wl(netdev_priv(netdev)); + + /* if the interface was not up, but associated */ + if (wl->assoc_stat == GELIC_WL_ASSOC_STAT_ASSOCIATED) + gelic_wl_disconnect(netdev); + + complete(&wl->cmd_done_intr); + + /* cancel all work queue */ + cancel_delayed_work(&wl->assoc_work); + cancel_delayed_work(&wl->event_work); + flush_workqueue(wl->eurus_cmd_queue); + flush_workqueue(wl->event_queue); + + unregister_netdev(netdev); + + /* disable wireless interrupt */ + pr_debug("%s: disable intr\n", __func__); + card->irq_mask &= ~(GELIC_CARD_WLAN_EVENT_RECEIVED | + GELIC_CARD_WLAN_COMMAND_COMPLETED); + /* free bss list, netdev*/ + gelic_wl_free(wl); + pr_debug("%s:end\n", __func__); + return 0; +} diff --git a/drivers/net/ps3_gelic_wireless.h b/drivers/net/ps3_gelic_wireless.h new file mode 100644 index 000000000000..103697166720 --- /dev/null +++ b/drivers/net/ps3_gelic_wireless.h @@ -0,0 +1,329 @@ +/* + * PS3 gelic network driver. + * + * Copyright (C) 2007 Sony Computer Entertainment Inc. + * Copyright 2007 Sony 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 version 2. + * + * 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. + */ +#ifndef _GELIC_WIRELESS_H +#define _GELIC_WIRELESS_H + +#include +#include + + +/* return value from GELIC_LV1_GET_WLAN_EVENT netcontrol */ +enum gelic_lv1_wl_event { + GELIC_LV1_WL_EVENT_DEVICE_READY = 0x01, /* Eurus ready */ + GELIC_LV1_WL_EVENT_SCAN_COMPLETED = 0x02, /* Scan has completed */ + GELIC_LV1_WL_EVENT_DEAUTH = 0x04, /* Deauthed by the AP */ + GELIC_LV1_WL_EVENT_BEACON_LOST = 0x08, /* Beacon lost detected */ + GELIC_LV1_WL_EVENT_CONNECTED = 0x10, /* Connected to AP */ + GELIC_LV1_WL_EVENT_WPA_CONNECTED = 0x20, /* WPA connection */ + GELIC_LV1_WL_EVENT_WPA_ERROR = 0x40, /* MIC error */ +}; + +/* arguments for GELIC_LV1_POST_WLAN_COMMAND netcontrol */ +enum gelic_eurus_command { + GELIC_EURUS_CMD_ASSOC = 1, /* association start */ + GELIC_EURUS_CMD_DISASSOC = 2, /* disassociate */ + GELIC_EURUS_CMD_START_SCAN = 3, /* scan start */ + GELIC_EURUS_CMD_GET_SCAN = 4, /* get scan result */ + GELIC_EURUS_CMD_SET_COMMON_CFG = 5, /* set common config */ + GELIC_EURUS_CMD_GET_COMMON_CFG = 6, /* set common config */ + GELIC_EURUS_CMD_SET_WEP_CFG = 7, /* set WEP config */ + GELIC_EURUS_CMD_GET_WEP_CFG = 8, /* get WEP config */ + GELIC_EURUS_CMD_SET_WPA_CFG = 9, /* set WPA config */ + GELIC_EURUS_CMD_GET_WPA_CFG = 10, /* get WPA config */ + GELIC_EURUS_CMD_GET_RSSI_CFG = 11, /* get RSSI info. */ + GELIC_EURUS_CMD_MAX_INDEX +}; + +/* for GELIC_EURUS_CMD_COMMON_CFG */ +enum gelic_eurus_bss_type { + GELIC_EURUS_BSS_INFRA = 0, + GELIC_EURUS_BSS_ADHOC = 1, /* not supported */ +}; + +enum gelic_eurus_auth_method { + GELIC_EURUS_AUTH_OPEN = 0, /* FIXME: WLAN_AUTH_OPEN */ + GELIC_EURUS_AUTH_SHARED = 1, /* not supported */ +}; + +enum gelic_eurus_opmode { + GELIC_EURUS_OPMODE_11BG = 0, /* 802.11b/g */ + GELIC_EURUS_OPMODE_11B = 1, /* 802.11b only */ + GELIC_EURUS_OPMODE_11G = 2, /* 802.11g only */ +}; + +struct gelic_eurus_common_cfg { + /* all fields are big endian */ + u16 scan_index; + u16 bss_type; /* infra or adhoc */ + u16 auth_method; /* shared key or open */ + u16 op_mode; /* B/G */ +} __attribute__((packed)); + + +/* for GELIC_EURUS_CMD_WEP_CFG */ +enum gelic_eurus_wep_security { + GELIC_EURUS_WEP_SEC_NONE = 0, + GELIC_EURUS_WEP_SEC_40BIT = 1, + GELIC_EURUS_WEP_SEC_104BIT = 2, +}; + +struct gelic_eurus_wep_cfg { + /* all fields are big endian */ + u16 security; + u8 key[4][16]; +} __attribute__((packed)); + +/* for GELIC_EURUS_CMD_WPA_CFG */ +enum gelic_eurus_wpa_security { + GELIC_EURUS_WPA_SEC_NONE = 0x0000, + /* group=TKIP, pairwise=TKIP */ + GELIC_EURUS_WPA_SEC_WPA_TKIP_TKIP = 0x0001, + /* group=AES, pairwise=AES */ + GELIC_EURUS_WPA_SEC_WPA_AES_AES = 0x0002, + /* group=TKIP, pairwise=TKIP */ + GELIC_EURUS_WPA_SEC_WPA2_TKIP_TKIP = 0x0004, + /* group=AES, pairwise=AES */ + GELIC_EURUS_WPA_SEC_WPA2_AES_AES = 0x0008, + /* group=TKIP, pairwise=AES */ + GELIC_EURUS_WPA_SEC_WPA_TKIP_AES = 0x0010, + /* group=TKIP, pairwise=AES */ + GELIC_EURUS_WPA_SEC_WPA2_TKIP_AES = 0x0020, +}; + +enum gelic_eurus_wpa_psk_type { + GELIC_EURUS_WPA_PSK_PASSPHRASE = 0, /* passphrase string */ + GELIC_EURUS_WPA_PSK_BIN = 1, /* 32 bytes binary key */ +}; + +#define GELIC_WL_EURUS_PSK_MAX_LEN 64 +#define WPA_PSK_LEN 32 /* WPA spec says 256bit */ + +struct gelic_eurus_wpa_cfg { + /* all fields are big endian */ + u16 security; + u16 psk_type; /* psk key encoding type */ + u8 psk[GELIC_WL_EURUS_PSK_MAX_LEN]; /* psk key; hex or passphrase */ +} __attribute__((packed)); + +/* for GELIC_EURUS_CMD_{START,GET}_SCAN */ +enum gelic_eurus_scan_capability { + GELIC_EURUS_SCAN_CAP_ADHOC = 0x0000, + GELIC_EURUS_SCAN_CAP_INFRA = 0x0001, + GELIC_EURUS_SCAN_CAP_MASK = 0x0001, +}; + +enum gelic_eurus_scan_sec_type { + GELIC_EURUS_SCAN_SEC_NONE = 0x0000, + GELIC_EURUS_SCAN_SEC_WEP = 0x0100, + GELIC_EURUS_SCAN_SEC_WPA = 0x0200, + GELIC_EURUS_SCAN_SEC_WPA2 = 0x0400, + GELIC_EURUS_SCAN_SEC_MASK = 0x0f00, +}; + +enum gelic_eurus_scan_sec_wep_type { + GELIC_EURUS_SCAN_SEC_WEP_UNKNOWN = 0x0000, + GELIC_EURUS_SCAN_SEC_WEP_40 = 0x0001, + GELIC_EURUS_SCAN_SEC_WEP_104 = 0x0002, + GELIC_EURUS_SCAN_SEC_WEP_MASK = 0x0003, +}; + +enum gelic_eurus_scan_sec_wpa_type { + GELIC_EURUS_SCAN_SEC_WPA_UNKNOWN = 0x0000, + GELIC_EURUS_SCAN_SEC_WPA_TKIP = 0x0001, + GELIC_EURUS_SCAN_SEC_WPA_AES = 0x0002, + GELIC_EURUS_SCAN_SEC_WPA_MASK = 0x0003, +}; + +/* + * hw BSS information structure returned from GELIC_EURUS_CMD_GET_SCAN + */ +struct gelic_eurus_scan_info { + /* all fields are big endian */ + __be16 size; + __be16 rssi; /* percentage */ + __be16 channel; /* channel number */ + __be16 beacon_period; /* FIXME: in msec unit */ + __be16 capability; + __be16 security; + u8 bssid[8]; /* last ETH_ALEN are valid. bssid[0],[1] are unused */ + u8 essid[32]; /* IW_ESSID_MAX_SIZE */ + u8 rate[16]; /* first MAX_RATES_LENGTH(12) are valid */ + u8 ext_rate[16]; /* first MAX_RATES_EX_LENGTH(16) are valid */ + __be32 reserved1; + __be32 reserved2; + __be32 reserved3; + __be32 reserved4; + u8 elements[0]; /* ie */ +} __attribute__ ((packed)); + +/* the hypervisor returns bbs up to 16 */ +#define GELIC_EURUS_MAX_SCAN (16) +struct gelic_wl_scan_info { + struct list_head list; + struct gelic_eurus_scan_info *hwinfo; + + int valid; /* set 1 if this entry was in latest scanned list + * from Eurus */ + unsigned int eurus_index; /* index in the Eurus list */ + unsigned long last_scanned; /* acquired time */ + + unsigned int rate_len; + unsigned int rate_ext_len; + unsigned int essid_len; +}; + +/* for GELIC_EURUS_CMD_GET_RSSI */ +struct gelic_eurus_rssi_info { + /* big endian */ + __be16 rssi; +} __attribute__ ((packed)); + + +/* for 'stat' member of gelic_wl_info */ +enum gelic_wl_info_status_bit { + GELIC_WL_STAT_CONFIGURED, + GELIC_WL_STAT_CH_INFO, /* ch info aquired */ + GELIC_WL_STAT_ESSID_SET, /* ESSID specified by userspace */ + GELIC_WL_STAT_BSSID_SET, /* BSSID specified by userspace */ + GELIC_WL_STAT_WPA_PSK_SET, /* PMK specified by userspace */ + GELIC_WL_STAT_WPA_LEVEL_SET, /* WEP or WPA[2] selected */ +}; + +/* for 'scan_stat' member of gelic_wl_info */ +enum gelic_wl_scan_state { + /* just initialized or get last scan result failed */ + GELIC_WL_SCAN_STAT_INIT, + /* scan request issued, accepted or chip is scanning */ + GELIC_WL_SCAN_STAT_SCANNING, + /* scan results retrieved */ + GELIC_WL_SCAN_STAT_GOT_LIST, +}; + +/* for 'cipher_method' */ +enum gelic_wl_cipher_method { + GELIC_WL_CIPHER_NONE, + GELIC_WL_CIPHER_WEP, + GELIC_WL_CIPHER_TKIP, + GELIC_WL_CIPHER_AES, +}; + +/* for 'wpa_level' */ +enum gelic_wl_wpa_level { + GELIC_WL_WPA_LEVEL_NONE, + GELIC_WL_WPA_LEVEL_WPA, + GELIC_WL_WPA_LEVEL_WPA2, +}; + +/* for 'assoc_stat' */ +enum gelic_wl_assoc_state { + GELIC_WL_ASSOC_STAT_DISCONN, + GELIC_WL_ASSOC_STAT_ASSOCIATING, + GELIC_WL_ASSOC_STAT_ASSOCIATED, +}; +/* part of private data alloc_etherdev() allocated */ +#define GELIC_WEP_KEYS 4 +struct gelic_wl_info { + /* bss list */ + struct semaphore scan_lock; + struct list_head network_list; + struct list_head network_free_list; + struct gelic_wl_scan_info *networks; + + unsigned long scan_age; /* last scanned time */ + enum gelic_wl_scan_state scan_stat; + struct completion scan_done; + + /* eurus command queue */ + struct workqueue_struct *eurus_cmd_queue; + struct completion cmd_done_intr; + + /* eurus event handling */ + struct workqueue_struct *event_queue; + struct delayed_work event_work; + + /* wl status bits */ + unsigned long stat; + enum gelic_eurus_auth_method auth_method; /* open/shared */ + enum gelic_wl_cipher_method group_cipher_method; + enum gelic_wl_cipher_method pairwise_cipher_method; + enum gelic_wl_wpa_level wpa_level; /* wpa/wpa2 */ + + /* association handling */ + struct semaphore assoc_stat_lock; + struct delayed_work assoc_work; + enum gelic_wl_assoc_state assoc_stat; + struct completion assoc_done; + + spinlock_t lock; + u16 ch_info; /* available channels. bit0 = ch1 */ + /* WEP keys */ + u8 key[GELIC_WEP_KEYS][IW_ENCODING_TOKEN_MAX]; + unsigned long key_enabled; + unsigned int key_len[GELIC_WEP_KEYS]; + unsigned int current_key; + /* WWPA PSK */ + u8 psk[GELIC_WL_EURUS_PSK_MAX_LEN]; + enum gelic_eurus_wpa_psk_type psk_type; + unsigned int psk_len; + + u8 essid[IW_ESSID_MAX_SIZE]; + u8 bssid[ETH_ALEN]; /* userland requested */ + u8 active_bssid[ETH_ALEN]; /* associated bssid */ + unsigned int essid_len; + + /* buffer for hypervisor IO */ + void *buf; + + struct iw_public_data wireless_data; + struct iw_statistics iwstat; +}; + +#define GELIC_WL_BSS_MAX_ENT 32 +#define GELIC_WL_ASSOC_RETRY 50 +static inline struct gelic_port *wl_port(struct gelic_wl_info *wl) +{ + return container_of((void *)wl, struct gelic_port, priv); +} +static inline struct gelic_wl_info *port_wl(struct gelic_port *port) +{ + return port_priv(port); +} + +struct gelic_eurus_cmd { + struct work_struct work; + struct gelic_wl_info *wl; + unsigned int cmd; /* command code */ + u64 tag; + u64 size; + void *buffer; + unsigned int buf_size; + struct completion done; + int status; + u64 cmd_status; +}; + +/* private ioctls to pass PSK */ +#define GELIC_WL_PRIV_SET_PSK (SIOCIWFIRSTPRIV + 0) +#define GELIC_WL_PRIV_GET_PSK (SIOCIWFIRSTPRIV + 1) + +extern int gelic_wl_driver_probe(struct gelic_card *card); +extern int gelic_wl_driver_remove(struct gelic_card *card); +extern void gelic_wl_interrupt(struct net_device *netdev, u64 status); +#endif /* _GELIC_WIRELESS_H */ diff --git a/drivers/net/r6040.c b/drivers/net/r6040.c index 2334f4ebf907..19184e486ae9 100644 --- a/drivers/net/r6040.c +++ b/drivers/net/r6040.c @@ -61,7 +61,6 @@ /* Time in jiffies before concluding the transmitter is hung. */ #define TX_TIMEOUT (6000 * HZ / 1000) -#define TIMER_WUT (jiffies + HZ * 1)/* timer wakeup time : 1 second */ /* RDC MAC I/O Size */ #define R6040_IO_SIZE 256 @@ -174,8 +173,6 @@ struct r6040_private { struct net_device *dev; struct mii_if_info mii_if; struct napi_struct napi; - struct net_device_stats stats; - u16 napi_rx_running; void __iomem *base; }; @@ -235,17 +232,53 @@ static void mdio_write(struct net_device *dev, int mii_id, int reg, int val) phy_write(ioaddr, lp->phy_addr, reg, val); } -static void r6040_tx_timeout(struct net_device *dev) +static void r6040_free_txbufs(struct net_device *dev) { - struct r6040_private *priv = netdev_priv(dev); + struct r6040_private *lp = netdev_priv(dev); + int i; - disable_irq(dev->irq); - napi_disable(&priv->napi); - spin_lock(&priv->lock); - dev->stats.tx_errors++; - spin_unlock(&priv->lock); + for (i = 0; i < TX_DCNT; i++) { + if (lp->tx_insert_ptr->skb_ptr) { + pci_unmap_single(lp->pdev, lp->tx_insert_ptr->buf, + MAX_BUF_SIZE, PCI_DMA_TODEVICE); + dev_kfree_skb(lp->tx_insert_ptr->skb_ptr); + lp->rx_insert_ptr->skb_ptr = NULL; + } + lp->tx_insert_ptr = lp->tx_insert_ptr->vndescp; + } +} - netif_stop_queue(dev); +static void r6040_free_rxbufs(struct net_device *dev) +{ + struct r6040_private *lp = netdev_priv(dev); + int i; + + for (i = 0; i < RX_DCNT; i++) { + if (lp->rx_insert_ptr->skb_ptr) { + pci_unmap_single(lp->pdev, lp->rx_insert_ptr->buf, + MAX_BUF_SIZE, PCI_DMA_FROMDEVICE); + dev_kfree_skb(lp->rx_insert_ptr->skb_ptr); + lp->rx_insert_ptr->skb_ptr = NULL; + } + lp->rx_insert_ptr = lp->rx_insert_ptr->vndescp; + } +} + +static void r6040_init_ring_desc(struct r6040_descriptor *desc_ring, + dma_addr_t desc_dma, int size) +{ + struct r6040_descriptor *desc = desc_ring; + dma_addr_t mapping = desc_dma; + + while (size-- > 0) { + mapping += sizeof(sizeof(*desc)); + desc->ndesc = cpu_to_le32(mapping); + desc->vndescp = desc + 1; + desc++; + } + desc--; + desc->ndesc = cpu_to_le32(desc_dma); + desc->vndescp = desc_ring; } /* Allocate skb buffer for rx descriptor */ @@ -256,7 +289,7 @@ static void rx_buf_alloc(struct r6040_private *lp, struct net_device *dev) descptr = lp->rx_insert_ptr; while (lp->rx_free_desc < RX_DCNT) { - descptr->skb_ptr = dev_alloc_skb(MAX_BUF_SIZE); + descptr->skb_ptr = netdev_alloc_skb(dev, MAX_BUF_SIZE); if (!descptr->skb_ptr) break; @@ -272,6 +305,63 @@ static void rx_buf_alloc(struct r6040_private *lp, struct net_device *dev) lp->rx_insert_ptr = descptr; } +static void r6040_alloc_txbufs(struct net_device *dev) +{ + struct r6040_private *lp = netdev_priv(dev); + void __iomem *ioaddr = lp->base; + + lp->tx_free_desc = TX_DCNT; + + lp->tx_remove_ptr = lp->tx_insert_ptr = lp->tx_ring; + r6040_init_ring_desc(lp->tx_ring, lp->tx_ring_dma, TX_DCNT); + + iowrite16(lp->tx_ring_dma, ioaddr + MTD_SA0); + iowrite16(lp->tx_ring_dma >> 16, ioaddr + MTD_SA1); +} + +static void r6040_alloc_rxbufs(struct net_device *dev) +{ + struct r6040_private *lp = netdev_priv(dev); + void __iomem *ioaddr = lp->base; + + lp->rx_free_desc = 0; + + lp->rx_remove_ptr = lp->rx_insert_ptr = lp->rx_ring; + r6040_init_ring_desc(lp->rx_ring, lp->rx_ring_dma, RX_DCNT); + + rx_buf_alloc(lp, dev); + + iowrite16(lp->rx_ring_dma, ioaddr + MRD_SA0); + iowrite16(lp->rx_ring_dma >> 16, ioaddr + MRD_SA1); +} + +static void r6040_tx_timeout(struct net_device *dev) +{ + struct r6040_private *priv = netdev_priv(dev); + void __iomem *ioaddr = priv->base; + + printk(KERN_WARNING "%s: transmit timed out, status %4.4x, PHY status " + "%4.4x\n", + dev->name, ioread16(ioaddr + MIER), + mdio_read(dev, priv->mii_if.phy_id, MII_BMSR)); + + disable_irq(dev->irq); + napi_disable(&priv->napi); + spin_lock(&priv->lock); + /* Clear all descriptors */ + r6040_free_txbufs(dev); + r6040_free_rxbufs(dev); + r6040_alloc_txbufs(dev); + r6040_alloc_rxbufs(dev); + + /* Reset MAC */ + iowrite16(MAC_RST, ioaddr + MCR1); + spin_unlock(&priv->lock); + enable_irq(dev->irq); + + dev->stats.tx_errors++; + netif_wake_queue(dev); +} static struct net_device_stats *r6040_get_stats(struct net_device *dev) { @@ -280,11 +370,11 @@ static struct net_device_stats *r6040_get_stats(struct net_device *dev) unsigned long flags; spin_lock_irqsave(&priv->lock, flags); - priv->stats.rx_crc_errors += ioread8(ioaddr + ME_CNT1); - priv->stats.multicast += ioread8(ioaddr + ME_CNT0); + dev->stats.rx_crc_errors += ioread8(ioaddr + ME_CNT1); + dev->stats.multicast += ioread8(ioaddr + ME_CNT0); spin_unlock_irqrestore(&priv->lock, flags); - return &priv->stats; + return &dev->stats; } /* Stop RDC MAC and Free the allocated resource */ @@ -293,7 +383,6 @@ static void r6040_down(struct net_device *dev) struct r6040_private *lp = netdev_priv(dev); void __iomem *ioaddr = lp->base; struct pci_dev *pdev = lp->pdev; - int i; int limit = 2048; u16 *adrp; u16 cmd; @@ -313,27 +402,12 @@ static void r6040_down(struct net_device *dev) iowrite16(adrp[1], ioaddr + MID_0M); iowrite16(adrp[2], ioaddr + MID_0H); free_irq(dev->irq, dev); + /* Free RX buffer */ - for (i = 0; i < RX_DCNT; i++) { - if (lp->rx_insert_ptr->skb_ptr) { - pci_unmap_single(lp->pdev, lp->rx_insert_ptr->buf, - MAX_BUF_SIZE, PCI_DMA_FROMDEVICE); - dev_kfree_skb(lp->rx_insert_ptr->skb_ptr); - lp->rx_insert_ptr->skb_ptr = NULL; - } - lp->rx_insert_ptr = lp->rx_insert_ptr->vndescp; - } + r6040_free_rxbufs(dev); /* Free TX buffer */ - for (i = 0; i < TX_DCNT; i++) { - if (lp->tx_insert_ptr->skb_ptr) { - pci_unmap_single(lp->pdev, lp->tx_insert_ptr->buf, - MAX_BUF_SIZE, PCI_DMA_TODEVICE); - dev_kfree_skb(lp->tx_insert_ptr->skb_ptr); - lp->rx_insert_ptr->skb_ptr = NULL; - } - lp->tx_insert_ptr = lp->tx_insert_ptr->vndescp; - } + r6040_free_txbufs(dev); /* Free Descriptor memory */ pci_free_consistent(pdev, RX_DESC_SIZE, lp->rx_ring, lp->rx_ring_dma); @@ -432,19 +506,24 @@ static int r6040_rx(struct net_device *dev, int limit) /* Check for errors */ err = ioread16(ioaddr + MLSR); - if (err & 0x0400) priv->stats.rx_errors++; + if (err & 0x0400) + dev->stats.rx_errors++; /* RX FIFO over-run */ - if (err & 0x8000) priv->stats.rx_fifo_errors++; + if (err & 0x8000) + dev->stats.rx_fifo_errors++; /* RX descriptor unavailable */ - if (err & 0x0080) priv->stats.rx_frame_errors++; + if (err & 0x0080) + dev->stats.rx_frame_errors++; /* Received packet with length over buffer lenght */ - if (err & 0x0020) priv->stats.rx_over_errors++; + if (err & 0x0020) + dev->stats.rx_over_errors++; /* Received packet with too long or short */ - if (err & (0x0010|0x0008)) priv->stats.rx_length_errors++; + if (err & (0x0010 | 0x0008)) + dev->stats.rx_length_errors++; /* Received packet with CRC errors */ if (err & 0x0004) { spin_lock(&priv->lock); - priv->stats.rx_crc_errors++; + dev->stats.rx_crc_errors++; spin_unlock(&priv->lock); } @@ -469,8 +548,8 @@ static int r6040_rx(struct net_device *dev, int limit) /* Send to upper layer */ netif_receive_skb(skb_ptr); dev->last_rx = jiffies; - priv->dev->stats.rx_packets++; - priv->dev->stats.rx_bytes += descptr->len; + dev->stats.rx_packets++; + dev->stats.rx_bytes += descptr->len; /* To next descriptor */ descptr = descptr->vndescp; priv->rx_free_desc--; @@ -498,11 +577,13 @@ static void r6040_tx(struct net_device *dev) /* Check for errors */ err = ioread16(ioaddr + MLSR); - if (err & 0x0200) priv->stats.rx_fifo_errors++; - if (err & (0x2000 | 0x4000)) priv->stats.tx_carrier_errors++; + if (err & 0x0200) + dev->stats.rx_fifo_errors++; + if (err & (0x2000 | 0x4000)) + dev->stats.tx_carrier_errors++; if (descptr->status & 0x8000) - break; /* Not complte */ + break; /* Not complete */ skb_ptr = descptr->skb_ptr; pci_unmap_single(priv->pdev, descptr->buf, skb_ptr->len, PCI_DMA_TODEVICE); @@ -545,7 +626,6 @@ static irqreturn_t r6040_interrupt(int irq, void *dev_id) struct r6040_private *lp = netdev_priv(dev); void __iomem *ioaddr = lp->base; u16 status; - int handled = 1; /* Mask off RDC MAC interrupt */ iowrite16(MSK_INT, ioaddr + MIER); @@ -565,7 +645,7 @@ static irqreturn_t r6040_interrupt(int irq, void *dev_id) if (status & 0x10) r6040_tx(dev); - return IRQ_RETVAL(handled); + return IRQ_HANDLED; } #ifdef CONFIG_NET_POLL_CONTROLLER @@ -577,53 +657,15 @@ static void r6040_poll_controller(struct net_device *dev) } #endif -static void r6040_init_ring_desc(struct r6040_descriptor *desc_ring, - dma_addr_t desc_dma, int size) -{ - struct r6040_descriptor *desc = desc_ring; - dma_addr_t mapping = desc_dma; - - while (size-- > 0) { - mapping += sizeof(sizeof(*desc)); - desc->ndesc = cpu_to_le32(mapping); - desc->vndescp = desc + 1; - desc++; - } - desc--; - desc->ndesc = cpu_to_le32(desc_dma); - desc->vndescp = desc_ring; -} - /* Init RDC MAC */ static void r6040_up(struct net_device *dev) { struct r6040_private *lp = netdev_priv(dev); void __iomem *ioaddr = lp->base; - /* Initialize */ - lp->tx_free_desc = TX_DCNT; - lp->rx_free_desc = 0; - /* Init descriptor */ - lp->tx_remove_ptr = lp->tx_insert_ptr = lp->tx_ring; - lp->rx_remove_ptr = lp->rx_insert_ptr = lp->rx_ring; - /* Init TX descriptor */ - r6040_init_ring_desc(lp->tx_ring, lp->tx_ring_dma, TX_DCNT); - - /* Init RX descriptor */ - r6040_init_ring_desc(lp->rx_ring, lp->rx_ring_dma, RX_DCNT); - - /* Allocate buffer for RX descriptor */ - rx_buf_alloc(lp, dev); - - /* - * TX and RX descriptor start registers. - * Lower 16-bits to MxD_SA0. Higher 16-bits to MxD_SA1. - */ - iowrite16(lp->tx_ring_dma, ioaddr + MTD_SA0); - iowrite16(lp->tx_ring_dma >> 16, ioaddr + MTD_SA1); - - iowrite16(lp->rx_ring_dma, ioaddr + MRD_SA0); - iowrite16(lp->rx_ring_dma >> 16, ioaddr + MRD_SA1); + /* Initialise and alloc RX/TX buffers */ + r6040_alloc_txbufs(dev); + r6040_alloc_rxbufs(dev); /* Buffer Size Register */ iowrite16(MAX_BUF_SIZE, ioaddr + MR_BSR); @@ -689,8 +731,7 @@ static void r6040_timer(unsigned long data) } /* Timer active again */ - lp->timer.expires = TIMER_WUT; - add_timer(&lp->timer); + mod_timer(&lp->timer, jiffies + round_jiffies(HZ)); } /* Read/set MAC address routines */ @@ -746,14 +787,10 @@ static int r6040_open(struct net_device *dev) napi_enable(&lp->napi); netif_start_queue(dev); - if (lp->switch_sig != ICPLUS_PHY_ID) { - /* set and active a timer process */ - init_timer(&lp->timer); - lp->timer.expires = TIMER_WUT; - lp->timer.data = (unsigned long)dev; - lp->timer.function = &r6040_timer; - add_timer(&lp->timer); - } + /* set and active a timer process */ + setup_timer(&lp->timer, r6040_timer, (unsigned long) dev); + if (lp->switch_sig != ICPLUS_PHY_ID) + mod_timer(&lp->timer, jiffies + HZ); return 0; } diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c index 2e9e88be7b33..202fdf356621 100644 --- a/drivers/net/sis190.c +++ b/drivers/net/sis190.c @@ -1630,7 +1630,8 @@ static inline void sis190_init_rxfilter(struct net_device *dev) SIS_PCI_COMMIT(); } -static int sis190_get_mac_addr(struct pci_dev *pdev, struct net_device *dev) +static int __devinit sis190_get_mac_addr(struct pci_dev *pdev, + struct net_device *dev) { u8 from; diff --git a/drivers/net/tsi108_eth.c b/drivers/net/tsi108_eth.c index 35d15e850075..6f33f84d37b0 100644 --- a/drivers/net/tsi108_eth.c +++ b/drivers/net/tsi108_eth.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -297,18 +298,11 @@ static void tsi108_check_phy(struct net_device *dev) u32 speed; unsigned long flags; - /* Do a dummy read, as for some reason the first read - * after a link becomes up returns link down, even if - * it's been a while since the link came up. - */ - spin_lock_irqsave(&phy_lock, flags); if (!data->phy_ok) goto out; - tsi108_read_mii(data, MII_BMSR); - duplex = mii_check_media(&data->mii_if, netif_msg_link(data), data->init_media); data->init_media = 0; @@ -345,22 +339,21 @@ static void tsi108_check_phy(struct net_device *dev) TSI_WRITE(TSI108_MAC_CFG2, mac_cfg2_reg); TSI_WRITE(TSI108_EC_PORTCTRL, portctrl_reg); - - if (data->link_up == 0) { - /* The manual says it can take 3-4 usecs for the speed change - * to take effect. - */ - udelay(5); - - spin_lock(&data->txlock); - if (is_valid_ether_addr(dev->dev_addr) && data->txfree) - netif_wake_queue(dev); - - data->link_up = 1; - spin_unlock(&data->txlock); - } } + if (data->link_up == 0) { + /* The manual says it can take 3-4 usecs for the speed change + * to take effect. + */ + udelay(5); + + spin_lock(&data->txlock); + if (is_valid_ether_addr(dev->dev_addr) && data->txfree) + netif_wake_queue(dev); + + data->link_up = 1; + spin_unlock(&data->txlock); + } } else { if (data->link_up == 1) { netif_stop_queue(dev); @@ -1274,12 +1267,11 @@ static void tsi108_init_phy(struct net_device *dev) * PHY_STAT register before the link up status bit is set. */ - data->link_up = 1; + data->link_up = 0; while (!((phyval = tsi108_read_mii(data, MII_BMSR)) & BMSR_LSTATUS)) { if (i++ > (MII_READ_DELAY / 10)) { - data->link_up = 0; break; } spin_unlock_irqrestore(&phy_lock, flags); @@ -1287,6 +1279,7 @@ static void tsi108_init_phy(struct net_device *dev) spin_lock_irqsave(&phy_lock, flags); } + data->mii_if.supports_gmii = mii_check_gmii_support(&data->mii_if); printk(KERN_DEBUG "PHY_STAT reg contains %08x\n", phyval); data->phy_ok = 1; data->init_media = 1; @@ -1527,12 +1520,46 @@ static void tsi108_init_mac(struct net_device *dev) TSI_WRITE(TSI108_EC_INTMASK, ~0); } +static int tsi108_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct tsi108_prv_data *data = netdev_priv(dev); + unsigned long flags; + int rc; + + spin_lock_irqsave(&data->txlock, flags); + rc = mii_ethtool_gset(&data->mii_if, cmd); + spin_unlock_irqrestore(&data->txlock, flags); + + return rc; +} + +static int tsi108_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct tsi108_prv_data *data = netdev_priv(dev); + unsigned long flags; + int rc; + + spin_lock_irqsave(&data->txlock, flags); + rc = mii_ethtool_sset(&data->mii_if, cmd); + spin_unlock_irqrestore(&data->txlock, flags); + + return rc; +} + static int tsi108_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { struct tsi108_prv_data *data = netdev_priv(dev); + if (!netif_running(dev)) + return -EINVAL; return generic_mii_ioctl(&data->mii_if, if_mii(rq), cmd, NULL); } +static const struct ethtool_ops tsi108_ethtool_ops = { + .get_link = ethtool_op_get_link, + .get_settings = tsi108_get_settings, + .set_settings = tsi108_set_settings, +}; + static int tsi108_init_one(struct platform_device *pdev) { @@ -1584,7 +1611,6 @@ tsi108_init_one(struct platform_device *pdev) data->mii_if.phy_id = einfo->phy; data->mii_if.phy_id_mask = 0x1f; data->mii_if.reg_num_mask = 0x1f; - data->mii_if.supports_gmii = mii_check_gmii_support(&data->mii_if); data->phy = einfo->phy; data->phy_type = einfo->phy_type; @@ -1598,6 +1624,7 @@ tsi108_init_one(struct platform_device *pdev) dev->get_stats = tsi108_get_stats; netif_napi_add(dev, &data->napi, tsi108_poll, 64); dev->do_ioctl = tsi108_do_ioctl; + dev->ethtool_ops = &tsi108_ethtool_ops; /* Apparently, the Linux networking code won't use scatter-gather * if the hardware doesn't do checksums. However, it's faster @@ -1629,6 +1656,7 @@ tsi108_init_one(struct platform_device *pdev) goto register_fail; } + platform_set_drvdata(pdev, dev); printk(KERN_INFO "%s: Tsi108 Gigabit Ethernet, MAC: %s\n", dev->name, print_mac(mac, dev->dev_addr)); #ifdef DEBUG diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index ddc87149fe31..dfdaec020739 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c @@ -1256,7 +1256,7 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf, if (ctl->flags & IEEE80211_TXCTL_NO_ACK) flags |= AR5K_TXDESC_NOACK; - pktlen = skb->len + FCS_LEN; + pktlen = skb->len; if (!(ctl->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT)) { keyidx = ctl->key_idx; @@ -1952,7 +1952,7 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf, } ds->ds_data = bf->skbaddr; - ret = ah->ah_setup_tx_desc(ah, ds, skb->len + FCS_LEN, + ret = ah->ah_setup_tx_desc(ah, ds, skb->len, ieee80211_get_hdrlen_from_skb(skb), AR5K_PKT_TYPE_BEACON, (ctl->power_level * 2), ctl->tx_rate, 1, AR5K_TXKEYIX_INVALID, antenna, flags, 0, 0); diff --git a/drivers/net/wireless/ath5k/hw.c b/drivers/net/wireless/ath5k/hw.c index 3a4bf4035a23..1ab57aa6e4dc 100644 --- a/drivers/net/wireless/ath5k/hw.c +++ b/drivers/net/wireless/ath5k/hw.c @@ -3506,7 +3506,7 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, { u32 frame_type; struct ath5k_hw_2w_tx_desc *tx_desc; - unsigned int buff_len; + unsigned int frame_len; tx_desc = (struct ath5k_hw_2w_tx_desc *)&desc->ds_ctl0; @@ -3537,22 +3537,25 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, /* Setup control descriptor */ /* Verify and set frame length */ - if (pkt_len & ~AR5K_2W_TX_DESC_CTL0_FRAME_LEN) + + /* remove padding we might have added before */ + frame_len = pkt_len - (hdr_len & 3) + FCS_LEN; + + if (frame_len & ~AR5K_2W_TX_DESC_CTL0_FRAME_LEN) return -EINVAL; - tx_desc->tx_control_0 = pkt_len & AR5K_2W_TX_DESC_CTL0_FRAME_LEN; + tx_desc->tx_control_0 = frame_len & AR5K_2W_TX_DESC_CTL0_FRAME_LEN; /* Verify and set buffer length */ - buff_len = pkt_len - FCS_LEN; /* NB: beacon's BufLen must be a multiple of 4 bytes */ if(type == AR5K_PKT_TYPE_BEACON) - buff_len = roundup(buff_len, 4); + pkt_len = roundup(pkt_len, 4); - if (buff_len & ~AR5K_2W_TX_DESC_CTL1_BUF_LEN) + if (pkt_len & ~AR5K_2W_TX_DESC_CTL1_BUF_LEN) return -EINVAL; - tx_desc->tx_control_1 = buff_len & AR5K_2W_TX_DESC_CTL1_BUF_LEN; + tx_desc->tx_control_1 = pkt_len & AR5K_2W_TX_DESC_CTL1_BUF_LEN; /* * Verify and set header length @@ -3634,7 +3637,7 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, { struct ath5k_hw_4w_tx_desc *tx_desc; struct ath5k_hw_tx_status *tx_status; - unsigned int buff_len; + unsigned int frame_len; ATH5K_TRACE(ah->ah_sc); tx_desc = (struct ath5k_hw_4w_tx_desc *)&desc->ds_ctl0; @@ -3669,22 +3672,25 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, /* Setup control descriptor */ /* Verify and set frame length */ - if (pkt_len & ~AR5K_4W_TX_DESC_CTL0_FRAME_LEN) + + /* remove padding we might have added before */ + frame_len = pkt_len - (hdr_len & 3) + FCS_LEN; + + if (frame_len & ~AR5K_4W_TX_DESC_CTL0_FRAME_LEN) return -EINVAL; - tx_desc->tx_control_0 = pkt_len & AR5K_4W_TX_DESC_CTL0_FRAME_LEN; + tx_desc->tx_control_0 = frame_len & AR5K_4W_TX_DESC_CTL0_FRAME_LEN; /* Verify and set buffer length */ - buff_len = pkt_len - FCS_LEN; /* NB: beacon's BufLen must be a multiple of 4 bytes */ if(type == AR5K_PKT_TYPE_BEACON) - buff_len = roundup(buff_len, 4); + pkt_len = roundup(pkt_len, 4); - if (buff_len & ~AR5K_4W_TX_DESC_CTL1_BUF_LEN) + if (pkt_len & ~AR5K_4W_TX_DESC_CTL1_BUF_LEN) return -EINVAL; - tx_desc->tx_control_1 = buff_len & AR5K_4W_TX_DESC_CTL1_BUF_LEN; + tx_desc->tx_control_1 = pkt_len & AR5K_4W_TX_DESC_CTL1_BUF_LEN; tx_desc->tx_control_0 |= AR5K_REG_SM(tx_power, AR5K_4W_TX_DESC_CTL0_XMIT_POWER) | diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index 08a011f0834a..f13346ba9dd2 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h @@ -14,6 +14,12 @@ #include "lo.h" #include "phy.h" + +/* The unique identifier of the firmware that's officially supported by + * this driver version. */ +#define B43_SUPPORTED_FIRMWARE_ID "FW13" + + #ifdef CONFIG_B43_DEBUG # define B43_DEBUG 1 #else diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index ef65c41af00f..51dfce16178a 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -58,6 +58,8 @@ MODULE_AUTHOR("Stefano Brivio"); MODULE_AUTHOR("Michael Buesch"); MODULE_LICENSE("GPL"); +MODULE_FIRMWARE(B43_SUPPORTED_FIRMWARE_ID); + static int modparam_bad_frames_preempt; module_param_named(bad_frames_preempt, modparam_bad_frames_preempt, int, 0444); @@ -1859,11 +1861,11 @@ static int b43_upload_microcode(struct b43_wldev *dev) err = -EOPNOTSUPP; goto error; } - b43dbg(dev->wl, "Loading firmware version %u.%u " - "(20%.2i-%.2i-%.2i %.2i:%.2i:%.2i)\n", - fwrev, fwpatch, - (fwdate >> 12) & 0xF, (fwdate >> 8) & 0xF, fwdate & 0xFF, - (fwtime >> 11) & 0x1F, (fwtime >> 5) & 0x3F, fwtime & 0x1F); + b43info(dev->wl, "Loading firmware version %u.%u " + "(20%.2i-%.2i-%.2i %.2i:%.2i:%.2i)\n", + fwrev, fwpatch, + (fwdate >> 12) & 0xF, (fwdate >> 8) & 0xF, fwdate & 0xFF, + (fwtime >> 11) & 0x1F, (fwtime >> 5) & 0x3F, fwtime & 0x1F); dev->fw.rev = fwrev; dev->fw.patch = fwpatch; @@ -4200,6 +4202,33 @@ static struct ssb_driver b43_ssb_driver = { .resume = b43_resume, }; +static void b43_print_driverinfo(void) +{ + const char *feat_pci = "", *feat_pcmcia = "", *feat_nphy = "", + *feat_leds = "", *feat_rfkill = ""; + +#ifdef CONFIG_B43_PCI_AUTOSELECT + feat_pci = "P"; +#endif +#ifdef CONFIG_B43_PCMCIA + feat_pcmcia = "M"; +#endif +#ifdef CONFIG_B43_NPHY + feat_nphy = "N"; +#endif +#ifdef CONFIG_B43_LEDS + feat_leds = "L"; +#endif +#ifdef CONFIG_B43_RFKILL + feat_rfkill = "R"; +#endif + printk(KERN_INFO "Broadcom 43xx driver loaded " + "[ Features: %s%s%s%s%s, Firmware-ID: " + B43_SUPPORTED_FIRMWARE_ID " ]\n", + feat_pci, feat_pcmcia, feat_nphy, + feat_leds, feat_rfkill); +} + static int __init b43_init(void) { int err; @@ -4211,6 +4240,7 @@ static int __init b43_init(void) err = ssb_driver_register(&b43_ssb_driver); if (err) goto err_pcmcia_exit; + b43_print_driverinfo(); return err; diff --git a/drivers/net/wireless/b43legacy/b43legacy.h b/drivers/net/wireless/b43legacy/b43legacy.h index c80edd2b9044..93d45b71799a 100644 --- a/drivers/net/wireless/b43legacy/b43legacy.h +++ b/drivers/net/wireless/b43legacy/b43legacy.h @@ -23,6 +23,10 @@ #include "phy.h" +/* The unique identifier of the firmware that's officially supported by this + * driver version. */ +#define B43legacy_SUPPORTED_FIRMWARE_ID "FW10" + #define B43legacy_IRQWAIT_MAX_RETRIES 20 #define B43legacy_RX_MAX_SSI 60 /* best guess at max ssi */ diff --git a/drivers/net/wireless/b43legacy/dma.c b/drivers/net/wireless/b43legacy/dma.c index 6e08405e8026..e87b427d5e43 100644 --- a/drivers/net/wireless/b43legacy/dma.c +++ b/drivers/net/wireless/b43legacy/dma.c @@ -354,7 +354,8 @@ return 0; } -u16 b43legacy_dmacontroller_base(int dma64bit, int controller_idx) +static u16 b43legacy_dmacontroller_base(enum b43legacy_dmatype type, + int controller_idx) { static const u16 map64[] = { B43legacy_MMIO_DMA64_BASE0, @@ -373,7 +374,7 @@ u16 b43legacy_dmacontroller_base(int dma64bit, int controller_idx) B43legacy_MMIO_DMA32_BASE5, }; - if (dma64bit) { + if (type == B43legacy_DMA_64BIT) { B43legacy_WARN_ON(!(controller_idx >= 0 && controller_idx < ARRAY_SIZE(map64))); return map64[controller_idx]; @@ -480,8 +481,9 @@ static void free_ringmemory(struct b43legacy_dmaring *ring) } /* Reset the RX DMA channel */ -int b43legacy_dmacontroller_rx_reset(struct b43legacy_wldev *dev, - u16 mmio_base, int dma64) +static int b43legacy_dmacontroller_rx_reset(struct b43legacy_wldev *dev, + u16 mmio_base, + enum b43legacy_dmatype type) { int i; u32 value; @@ -489,13 +491,14 @@ int b43legacy_dmacontroller_rx_reset(struct b43legacy_wldev *dev, might_sleep(); - offset = dma64 ? B43legacy_DMA64_RXCTL : B43legacy_DMA32_RXCTL; + offset = (type == B43legacy_DMA_64BIT) ? + B43legacy_DMA64_RXCTL : B43legacy_DMA32_RXCTL; b43legacy_write32(dev, mmio_base + offset, 0); for (i = 0; i < 10; i++) { - offset = dma64 ? B43legacy_DMA64_RXSTATUS : - B43legacy_DMA32_RXSTATUS; + offset = (type == B43legacy_DMA_64BIT) ? + B43legacy_DMA64_RXSTATUS : B43legacy_DMA32_RXSTATUS; value = b43legacy_read32(dev, mmio_base + offset); - if (dma64) { + if (type == B43legacy_DMA_64BIT) { value &= B43legacy_DMA64_RXSTAT; if (value == B43legacy_DMA64_RXSTAT_DISABLED) { i = -1; @@ -519,8 +522,9 @@ int b43legacy_dmacontroller_rx_reset(struct b43legacy_wldev *dev, } /* Reset the RX DMA channel */ -int b43legacy_dmacontroller_tx_reset(struct b43legacy_wldev *dev, - u16 mmio_base, int dma64) +static int b43legacy_dmacontroller_tx_reset(struct b43legacy_wldev *dev, + u16 mmio_base, + enum b43legacy_dmatype type) { int i; u32 value; @@ -529,10 +533,10 @@ int b43legacy_dmacontroller_tx_reset(struct b43legacy_wldev *dev, might_sleep(); for (i = 0; i < 10; i++) { - offset = dma64 ? B43legacy_DMA64_TXSTATUS : - B43legacy_DMA32_TXSTATUS; + offset = (type == B43legacy_DMA_64BIT) ? + B43legacy_DMA64_TXSTATUS : B43legacy_DMA32_TXSTATUS; value = b43legacy_read32(dev, mmio_base + offset); - if (dma64) { + if (type == B43legacy_DMA_64BIT) { value &= B43legacy_DMA64_TXSTAT; if (value == B43legacy_DMA64_TXSTAT_DISABLED || value == B43legacy_DMA64_TXSTAT_IDLEWAIT || @@ -547,13 +551,14 @@ int b43legacy_dmacontroller_tx_reset(struct b43legacy_wldev *dev, } msleep(1); } - offset = dma64 ? B43legacy_DMA64_TXCTL : B43legacy_DMA32_TXCTL; + offset = (type == B43legacy_DMA_64BIT) ? B43legacy_DMA64_TXCTL : + B43legacy_DMA32_TXCTL; b43legacy_write32(dev, mmio_base + offset, 0); for (i = 0; i < 10; i++) { - offset = dma64 ? B43legacy_DMA64_TXSTATUS : - B43legacy_DMA32_TXSTATUS; + offset = (type == B43legacy_DMA_64BIT) ? + B43legacy_DMA64_TXSTATUS : B43legacy_DMA32_TXSTATUS; value = b43legacy_read32(dev, mmio_base + offset); - if (dma64) { + if (type == B43legacy_DMA_64BIT) { value &= B43legacy_DMA64_TXSTAT; if (value == B43legacy_DMA64_TXSTAT_DISABLED) { i = -1; @@ -578,6 +583,32 @@ int b43legacy_dmacontroller_tx_reset(struct b43legacy_wldev *dev, return 0; } +/* Check if a DMA mapping address is invalid. */ +static bool b43legacy_dma_mapping_error(struct b43legacy_dmaring *ring, + dma_addr_t addr, + size_t buffersize) +{ + if (unlikely(dma_mapping_error(addr))) + return 1; + + switch (ring->type) { + case B43legacy_DMA_30BIT: + if ((u64)addr + buffersize > (1ULL << 30)) + return 1; + break; + case B43legacy_DMA_32BIT: + if ((u64)addr + buffersize > (1ULL << 32)) + return 1; + break; + case B43legacy_DMA_64BIT: + /* Currently we can't have addresses beyond 64 bits in the kernel. */ + break; + } + + /* The address is OK. */ + return 0; +} + static int setup_rx_descbuffer(struct b43legacy_dmaring *ring, struct b43legacy_dmadesc_generic *desc, struct b43legacy_dmadesc_meta *meta, @@ -595,7 +626,7 @@ static int setup_rx_descbuffer(struct b43legacy_dmaring *ring, return -ENOMEM; dmaaddr = map_descbuffer(ring, skb->data, ring->rx_buffersize, 0); - if (dma_mapping_error(dmaaddr)) { + if (b43legacy_dma_mapping_error(ring, dmaaddr, ring->rx_buffersize)) { /* ugh. try to realloc in zone_dma */ gfp_flags |= GFP_DMA; @@ -608,7 +639,7 @@ static int setup_rx_descbuffer(struct b43legacy_dmaring *ring, ring->rx_buffersize, 0); } - if (dma_mapping_error(dmaaddr)) { + if (b43legacy_dma_mapping_error(ring, dmaaddr, ring->rx_buffersize)) { dev_kfree_skb_any(skb); return -EIO; } @@ -674,7 +705,7 @@ static int dmacontroller_setup(struct b43legacy_dmaring *ring) u32 trans = ssb_dma_translation(ring->dev->dev); if (ring->tx) { - if (ring->dma64) { + if (ring->type == B43legacy_DMA_64BIT) { u64 ringbase = (u64)(ring->dmabase); addrext = ((ringbase >> 32) & SSB_DMA_TRANSLATION_MASK) @@ -709,7 +740,7 @@ static int dmacontroller_setup(struct b43legacy_dmaring *ring) err = alloc_initial_descbuffers(ring); if (err) goto out; - if (ring->dma64) { + if (ring->type == B43legacy_DMA_64BIT) { u64 ringbase = (u64)(ring->dmabase); addrext = ((ringbase >> 32) & SSB_DMA_TRANSLATION_MASK) @@ -760,16 +791,16 @@ static void dmacontroller_cleanup(struct b43legacy_dmaring *ring) { if (ring->tx) { b43legacy_dmacontroller_tx_reset(ring->dev, ring->mmio_base, - ring->dma64); - if (ring->dma64) { + ring->type); + if (ring->type == B43legacy_DMA_64BIT) { b43legacy_dma_write(ring, B43legacy_DMA64_TXRINGLO, 0); b43legacy_dma_write(ring, B43legacy_DMA64_TXRINGHI, 0); } else b43legacy_dma_write(ring, B43legacy_DMA32_TXRING, 0); } else { b43legacy_dmacontroller_rx_reset(ring->dev, ring->mmio_base, - ring->dma64); - if (ring->dma64) { + ring->type); + if (ring->type == B43legacy_DMA_64BIT) { b43legacy_dma_write(ring, B43legacy_DMA64_RXRINGLO, 0); b43legacy_dma_write(ring, B43legacy_DMA64_RXRINGHI, 0); } else @@ -824,11 +855,10 @@ static u64 supported_dma_mask(struct b43legacy_wldev *dev) /* Main initialization function. */ static -struct b43legacy_dmaring *b43legacy_setup_dmaring( - struct b43legacy_wldev *dev, - int controller_index, - int for_tx, - int dma64) +struct b43legacy_dmaring *b43legacy_setup_dmaring(struct b43legacy_wldev *dev, + int controller_index, + int for_tx, + enum b43legacy_dmatype type) { struct b43legacy_dmaring *ring; int err; @@ -838,6 +868,7 @@ struct b43legacy_dmaring *b43legacy_setup_dmaring( ring = kzalloc(sizeof(*ring), GFP_KERNEL); if (!ring) goto out; + ring->type = type; nr_slots = B43legacy_RXRING_SLOTS; if (for_tx) @@ -855,12 +886,12 @@ struct b43legacy_dmaring *b43legacy_setup_dmaring( goto err_kfree_meta; /* test for ability to dma to txhdr_cache */ - dma_test = dma_map_single(dev->dev->dev, - ring->txhdr_cache, - sizeof(struct b43legacy_txhdr_fw3), - DMA_TO_DEVICE); + dma_test = dma_map_single(dev->dev->dev, ring->txhdr_cache, + sizeof(struct b43legacy_txhdr_fw3), + DMA_TO_DEVICE); - if (dma_mapping_error(dma_test)) { + if (b43legacy_dma_mapping_error(ring, dma_test, + sizeof(struct b43legacy_txhdr_fw3))) { /* ugh realloc */ kfree(ring->txhdr_cache); ring->txhdr_cache = kcalloc(nr_slots, @@ -874,7 +905,8 @@ struct b43legacy_dmaring *b43legacy_setup_dmaring( sizeof(struct b43legacy_txhdr_fw3), DMA_TO_DEVICE); - if (dma_mapping_error(dma_test)) + if (b43legacy_dma_mapping_error(ring, dma_test, + sizeof(struct b43legacy_txhdr_fw3))) goto err_kfree_txhdr_cache; } @@ -885,11 +917,9 @@ struct b43legacy_dmaring *b43legacy_setup_dmaring( ring->dev = dev; ring->nr_slots = nr_slots; - ring->mmio_base = b43legacy_dmacontroller_base(dma64, - controller_index); + ring->mmio_base = b43legacy_dmacontroller_base(type, controller_index); ring->index = controller_index; - ring->dma64 = !!dma64; - if (dma64) + if (type == B43legacy_DMA_64BIT) ring->ops = &dma64_ops; else ring->ops = &dma32_ops; @@ -939,10 +969,10 @@ static void b43legacy_destroy_dmaring(struct b43legacy_dmaring *ring) if (!ring) return; - b43legacydbg(ring->dev->wl, "DMA-%s 0x%04X (%s) max used slots:" - " %d/%d\n", (ring->dma64) ? "64" : "32", ring->mmio_base, - (ring->tx) ? "TX" : "RX", - ring->max_used_slots, ring->nr_slots); + b43legacydbg(ring->dev->wl, "DMA-%u 0x%04X (%s) max used slots:" + " %d/%d\n", (unsigned int)(ring->type), ring->mmio_base, + (ring->tx) ? "TX" : "RX", ring->max_used_slots, + ring->nr_slots); /* Device IRQs are disabled prior entering this function, * so no need to take care of concurrency with rx handler stuff. */ @@ -988,11 +1018,22 @@ int b43legacy_dma_init(struct b43legacy_wldev *dev) struct b43legacy_dmaring *ring; int err; u64 dmamask; - int dma64 = 0; + enum b43legacy_dmatype type; dmamask = supported_dma_mask(dev); - if (dmamask == DMA_64BIT_MASK) - dma64 = 1; + switch (dmamask) { + default: + B43legacy_WARN_ON(1); + case DMA_30BIT_MASK: + type = B43legacy_DMA_30BIT; + break; + case DMA_32BIT_MASK: + type = B43legacy_DMA_32BIT; + break; + case DMA_64BIT_MASK: + type = B43legacy_DMA_64BIT; + break; + } err = ssb_dma_set_mask(dev->dev, dmamask); if (err) { @@ -1010,52 +1051,50 @@ int b43legacy_dma_init(struct b43legacy_wldev *dev) err = -ENOMEM; /* setup TX DMA channels. */ - ring = b43legacy_setup_dmaring(dev, 0, 1, dma64); + ring = b43legacy_setup_dmaring(dev, 0, 1, type); if (!ring) goto out; dma->tx_ring0 = ring; - ring = b43legacy_setup_dmaring(dev, 1, 1, dma64); + ring = b43legacy_setup_dmaring(dev, 1, 1, type); if (!ring) goto err_destroy_tx0; dma->tx_ring1 = ring; - ring = b43legacy_setup_dmaring(dev, 2, 1, dma64); + ring = b43legacy_setup_dmaring(dev, 2, 1, type); if (!ring) goto err_destroy_tx1; dma->tx_ring2 = ring; - ring = b43legacy_setup_dmaring(dev, 3, 1, dma64); + ring = b43legacy_setup_dmaring(dev, 3, 1, type); if (!ring) goto err_destroy_tx2; dma->tx_ring3 = ring; - ring = b43legacy_setup_dmaring(dev, 4, 1, dma64); + ring = b43legacy_setup_dmaring(dev, 4, 1, type); if (!ring) goto err_destroy_tx3; dma->tx_ring4 = ring; - ring = b43legacy_setup_dmaring(dev, 5, 1, dma64); + ring = b43legacy_setup_dmaring(dev, 5, 1, type); if (!ring) goto err_destroy_tx4; dma->tx_ring5 = ring; /* setup RX DMA channels. */ - ring = b43legacy_setup_dmaring(dev, 0, 0, dma64); + ring = b43legacy_setup_dmaring(dev, 0, 0, type); if (!ring) goto err_destroy_tx5; dma->rx_ring0 = ring; if (dev->dev->id.revision < 5) { - ring = b43legacy_setup_dmaring(dev, 3, 0, dma64); + ring = b43legacy_setup_dmaring(dev, 3, 0, type); if (!ring) goto err_destroy_rx0; dma->rx_ring3 = ring; } - b43legacydbg(dev->wl, "%d-bit DMA initialized\n", - (dmamask == DMA_64BIT_MASK) ? 64 : - (dmamask == DMA_32BIT_MASK) ? 32 : 30); + b43legacydbg(dev->wl, "%u-bit DMA initialized\n", (unsigned int)type); err = 0; out: return err; @@ -1194,9 +1233,13 @@ static int dma_tx_fragment(struct b43legacy_dmaring *ring, } meta_hdr->dmaaddr = map_descbuffer(ring, (unsigned char *)header, - sizeof(struct b43legacy_txhdr_fw3), 1); - if (dma_mapping_error(meta_hdr->dmaaddr)) + sizeof(struct b43legacy_txhdr_fw3), 1); + if (b43legacy_dma_mapping_error(ring, meta_hdr->dmaaddr, + sizeof(struct b43legacy_txhdr_fw3))) { + ring->current_slot = old_top_slot; + ring->used_slots = old_used_slots; return -EIO; + } ops->fill_descriptor(ring, desc, meta_hdr->dmaaddr, sizeof(struct b43legacy_txhdr_fw3), 1, 0, 0); @@ -1211,7 +1254,7 @@ static int dma_tx_fragment(struct b43legacy_dmaring *ring, meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1); /* create a bounce buffer in zone_dma on mapping failure. */ - if (dma_mapping_error(meta->dmaaddr)) { + if (b43legacy_dma_mapping_error(ring, meta->dmaaddr, skb->len)) { bounce_skb = __dev_alloc_skb(skb->len, GFP_ATOMIC | GFP_DMA); if (!bounce_skb) { ring->current_slot = old_top_slot; @@ -1225,7 +1268,7 @@ static int dma_tx_fragment(struct b43legacy_dmaring *ring, skb = bounce_skb; meta->skb = skb; meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1); - if (dma_mapping_error(meta->dmaaddr)) { + if (b43legacy_dma_mapping_error(ring, meta->dmaaddr, skb->len)) { ring->current_slot = old_top_slot; ring->used_slots = old_used_slots; err = -EIO; diff --git a/drivers/net/wireless/b43legacy/dma.h b/drivers/net/wireless/b43legacy/dma.h index 26f6ab08de75..2dd488c5be2d 100644 --- a/drivers/net/wireless/b43legacy/dma.h +++ b/drivers/net/wireless/b43legacy/dma.h @@ -218,6 +218,12 @@ struct b43legacy_dma_ops { void (*set_current_rxslot)(struct b43legacy_dmaring *ring, int slot); }; +enum b43legacy_dmatype { + B43legacy_DMA_30BIT = 30, + B43legacy_DMA_32BIT = 32, + B43legacy_DMA_64BIT = 64, +}; + struct b43legacy_dmaring { /* Lowlevel DMA ops. */ const struct b43legacy_dma_ops *ops; @@ -250,8 +256,8 @@ struct b43legacy_dmaring { int index; /* Boolean. Is this a TX ring? */ bool tx; - /* Boolean. 64bit DMA if true, 32bit DMA otherwise. */ - bool dma64; + /* The type of DMA engine used. */ + enum b43legacy_dmatype type; /* Boolean. Is this ring stopped at ieee80211 level? */ bool stopped; /* Lock, only used for TX. */ @@ -284,15 +290,6 @@ void b43legacy_dma_write(struct b43legacy_dmaring *ring, int b43legacy_dma_init(struct b43legacy_wldev *dev); void b43legacy_dma_free(struct b43legacy_wldev *dev); -int b43legacy_dmacontroller_rx_reset(struct b43legacy_wldev *dev, - u16 dmacontroller_mmio_base, - int dma64); -int b43legacy_dmacontroller_tx_reset(struct b43legacy_wldev *dev, - u16 dmacontroller_mmio_base, - int dma64); - -u16 b43legacy_dmacontroller_base(int dma64bit, int dmacontroller_idx); - void b43legacy_dma_tx_suspend(struct b43legacy_wldev *dev); void b43legacy_dma_tx_resume(struct b43legacy_wldev *dev); @@ -320,20 +317,6 @@ void b43legacy_dma_free(struct b43legacy_wldev *dev) { } static inline -int b43legacy_dmacontroller_rx_reset(struct b43legacy_wldev *dev, - u16 dmacontroller_mmio_base, - int dma64) -{ - return 0; -} -static inline -int b43legacy_dmacontroller_tx_reset(struct b43legacy_wldev *dev, - u16 dmacontroller_mmio_base, - int dma64) -{ - return 0; -} -static inline void b43legacy_dma_get_tx_stats(struct b43legacy_wldev *dev, struct ieee80211_tx_queue_stats *stats) { diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index 53f7f2e97615..c39de422e220 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -3,7 +3,7 @@ * Broadcom B43legacy wireless driver * * Copyright (c) 2005 Martin Langer - * Copyright (c) 2005-2007 Stefano Brivio + * Copyright (c) 2005-2008 Stefano Brivio * Copyright (c) 2005, 2006 Michael Buesch * Copyright (c) 2005 Danny van Dyk * Copyright (c) 2005 Andreas Jaggi @@ -60,6 +60,8 @@ MODULE_AUTHOR("Stefano Brivio"); MODULE_AUTHOR("Michael Buesch"); MODULE_LICENSE("GPL"); +MODULE_FIRMWARE(B43legacy_SUPPORTED_FIRMWARE_ID); + #if defined(CONFIG_B43LEGACY_DMA) && defined(CONFIG_B43LEGACY_PIO) static int modparam_pio; module_param_named(pio, modparam_pio, int, 0444); @@ -1640,10 +1642,11 @@ static int b43legacy_upload_microcode(struct b43legacy_wldev *dev) err = -EOPNOTSUPP; goto error; } - b43legacydbg(dev->wl, "Loading firmware version 0x%X, patch level %u " - "(20%.2i-%.2i-%.2i %.2i:%.2i:%.2i)\n", fwrev, fwpatch, - (fwdate >> 12) & 0xF, (fwdate >> 8) & 0xF, fwdate & 0xFF, - (fwtime >> 11) & 0x1F, (fwtime >> 5) & 0x3F, fwtime & 0x1F); + b43legacyinfo(dev->wl, "Loading firmware version 0x%X, patch level %u " + "(20%.2i-%.2i-%.2i %.2i:%.2i:%.2i)\n", fwrev, fwpatch, + (fwdate >> 12) & 0xF, (fwdate >> 8) & 0xF, fwdate & 0xFF, + (fwtime >> 11) & 0x1F, (fwtime >> 5) & 0x3F, + fwtime & 0x1F); dev->fw.rev = fwrev; dev->fw.patch = fwpatch; @@ -3806,6 +3809,32 @@ static struct ssb_driver b43legacy_ssb_driver = { .resume = b43legacy_resume, }; +static void b43legacy_print_driverinfo(void) +{ + const char *feat_pci = "", *feat_leds = "", *feat_rfkill = "", + *feat_pio = "", *feat_dma = ""; + +#ifdef CONFIG_B43LEGACY_PCI_AUTOSELECT + feat_pci = "P"; +#endif +#ifdef CONFIG_B43LEGACY_LEDS + feat_leds = "L"; +#endif +#ifdef CONFIG_B43LEGACY_RFKILL + feat_rfkill = "R"; +#endif +#ifdef CONFIG_B43LEGACY_PIO + feat_pio = "I"; +#endif +#ifdef CONFIG_B43LEGACY_DMA + feat_dma = "D"; +#endif + printk(KERN_INFO "Broadcom 43xx driver loaded " + "[ Features: %s%s%s%s%s, Firmware-ID: " + B43legacy_SUPPORTED_FIRMWARE_ID " ]\n", + feat_pci, feat_leds, feat_rfkill, feat_pio, feat_dma); +} + static int __init b43legacy_init(void) { int err; @@ -3816,6 +3845,8 @@ static int __init b43legacy_init(void) if (err) goto err_dfs_exit; + b43legacy_print_driverinfo(); + return err; err_dfs_exit: diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 3e6ad7b92c83..a56d9fc6354f 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -3365,7 +3365,6 @@ static void ipw_rx_queue_reset(struct ipw_priv *priv, /* Set us so that we have processed and used all buffers, but have * not restocked the Rx queue with fresh buffers */ rxq->read = rxq->write = 0; - rxq->processed = RX_QUEUE_SIZE - 1; rxq->free_count = 0; spin_unlock_irqrestore(&rxq->lock, flags); } @@ -3607,7 +3606,22 @@ static int ipw_load(struct ipw_priv *priv) * Driver allocates buffers of this size for Rx */ -static inline int ipw_queue_space(const struct clx2_queue *q) +/** + * ipw_rx_queue_space - Return number of free slots available in queue. + */ +static int ipw_rx_queue_space(const struct ipw_rx_queue *q) +{ + int s = q->read - q->write; + if (s <= 0) + s += RX_QUEUE_SIZE; + /* keep some buffer to not confuse full and empty queue */ + s -= 2; + if (s < 0) + s = 0; + return s; +} + +static inline int ipw_tx_queue_space(const struct clx2_queue *q) { int s = q->last_used - q->first_empty; if (s <= 0) @@ -4947,7 +4961,7 @@ static int ipw_queue_tx_reclaim(struct ipw_priv *priv, priv->tx_packets++; } done: - if ((ipw_queue_space(q) > q->low_mark) && + if ((ipw_tx_queue_space(q) > q->low_mark) && (qindex >= 0) && (priv->status & STATUS_ASSOCIATED) && netif_running(priv->net_dev)) netif_wake_queue(priv->net_dev); @@ -4965,7 +4979,7 @@ static int ipw_queue_tx_hcmd(struct ipw_priv *priv, int hcmd, void *buf, struct clx2_queue *q = &txq->q; struct tfd_frame *tfd; - if (ipw_queue_space(q) < (sync ? 1 : 2)) { + if (ipw_tx_queue_space(q) < (sync ? 1 : 2)) { IPW_ERROR("No space for Tx\n"); return -EBUSY; } @@ -5070,7 +5084,7 @@ static void ipw_rx_queue_restock(struct ipw_priv *priv) spin_lock_irqsave(&rxq->lock, flags); write = rxq->write; - while ((rxq->write != rxq->processed) && (rxq->free_count)) { + while ((ipw_rx_queue_space(rxq) > 0) && (rxq->free_count)) { element = rxq->rx_free.next; rxb = list_entry(element, struct ipw_rx_mem_buffer, list); list_del(element); @@ -5187,7 +5201,6 @@ static struct ipw_rx_queue *ipw_rx_queue_alloc(struct ipw_priv *priv) /* Set us so that we have processed and used all buffers, but have * not restocked the Rx queue with fresh buffers */ rxq->read = rxq->write = 0; - rxq->processed = RX_QUEUE_SIZE - 1; rxq->free_count = 0; return rxq; @@ -8223,13 +8236,17 @@ static void ipw_rx(struct ipw_priv *priv) struct ieee80211_hdr_4addr *header; u32 r, w, i; u8 network_packet; + u8 fill_rx = 0; DECLARE_MAC_BUF(mac); DECLARE_MAC_BUF(mac2); DECLARE_MAC_BUF(mac3); r = ipw_read32(priv, IPW_RX_READ_INDEX); w = ipw_read32(priv, IPW_RX_WRITE_INDEX); - i = (priv->rxq->processed + 1) % RX_QUEUE_SIZE; + i = priv->rxq->read; + + if (ipw_rx_queue_space (priv->rxq) > (RX_QUEUE_SIZE / 2)) + fill_rx = 1; while (i != r) { rxb = priv->rxq->queue[i]; @@ -8404,11 +8421,17 @@ static void ipw_rx(struct ipw_priv *priv) list_add_tail(&rxb->list, &priv->rxq->rx_used); i = (i + 1) % RX_QUEUE_SIZE; + + /* If there are a lot of unsued frames, restock the Rx queue + * so the ucode won't assert */ + if (fill_rx) { + priv->rxq->read = i; + ipw_rx_queue_replenish(priv); + } } /* Backtrack one entry */ - priv->rxq->processed = (i ? i : RX_QUEUE_SIZE) - 1; - + priv->rxq->read = i; ipw_rx_queue_restock(priv); } @@ -10336,7 +10359,7 @@ static int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb, q->first_empty = ipw_queue_inc_wrap(q->first_empty, q->n_bd); ipw_write32(priv, q->reg_w, q->first_empty); - if (ipw_queue_space(q) < q->high_mark) + if (ipw_tx_queue_space(q) < q->high_mark) netif_stop_queue(priv->net_dev); return NETDEV_TX_OK; @@ -10357,7 +10380,7 @@ static int ipw_net_is_queue_full(struct net_device *dev, int pri) struct clx2_tx_queue *txq = &priv->txq[0]; #endif /* CONFIG_IPW2200_QOS */ - if (ipw_queue_space(&txq->q) < txq->q.high_mark) + if (ipw_tx_queue_space(&txq->q) < txq->q.high_mark) return 1; return 0; diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 5ee1ad69898b..40b71bc2c4a4 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -687,6 +687,12 @@ static int iwl3945_enqueue_hcmd(struct iwl3945_priv *priv, struct iwl3945_host_c BUG_ON((fix_size > TFD_MAX_PAYLOAD_SIZE) && !(cmd->meta.flags & CMD_SIZE_HUGE)); + + if (iwl3945_is_rfkill(priv)) { + IWL_DEBUG_INFO("Not sending command - RF KILL"); + return -EIO; + } + if (iwl3945_queue_space(q) < ((cmd->meta.flags & CMD_ASYNC) ? 2 : 1)) { IWL_ERROR("No space for Tx\n"); return -ENOSPC; @@ -1580,7 +1586,7 @@ static inline int iwl3945_eeprom_acquire_semaphore(struct iwl3945_priv *priv) */ int iwl3945_eeprom_init(struct iwl3945_priv *priv) { - __le16 *e = (__le16 *)&priv->eeprom; + u16 *e = (u16 *)&priv->eeprom; u32 gp = iwl3945_read32(priv, CSR_EEPROM_GP); u32 r; int sz = sizeof(priv->eeprom); @@ -1623,7 +1629,7 @@ int iwl3945_eeprom_init(struct iwl3945_priv *priv) IWL_ERROR("Time out reading EEPROM[%d]", addr); return -ETIMEDOUT; } - e[addr / 2] = cpu_to_le16(r >> 16); + e[addr / 2] = le16_to_cpu((__force __le16)(r >> 16)); } return 0; @@ -2806,7 +2812,8 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv, #endif /* drop all data frame if we are not associated */ - if ((!iwl3945_is_associated(priv) || !priv->assoc_id) && + if ((!iwl3945_is_associated(priv) || + ((priv->iw_mode == IEEE80211_IF_TYPE_STA) && !priv->assoc_id)) && ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA)) { IWL_DEBUG_DROP("Dropping - !iwl3945_is_associated\n"); goto drop_unlock; @@ -4281,7 +4288,7 @@ static void iwl3945_rx_handle(struct iwl3945_priv *priv) int reclaim; unsigned long flags; u8 fill_rx = 0; - u32 count = 0; + u32 count = 8; /* uCode's read index (stored in shared DRAM) indicates the last Rx * buffer that the driver may process (last buffer filled by ucode). */ @@ -6256,6 +6263,8 @@ static void __iwl3945_down(struct iwl3945_priv *priv) STATUS_RF_KILL_HW | test_bit(STATUS_RF_KILL_SW, &priv->status) << STATUS_RF_KILL_SW | + test_bit(STATUS_GEO_CONFIGURED, &priv->status) << + STATUS_GEO_CONFIGURED | test_bit(STATUS_IN_SUSPEND, &priv->status) << STATUS_IN_SUSPEND; goto exit; @@ -6267,6 +6276,8 @@ static void __iwl3945_down(struct iwl3945_priv *priv) STATUS_RF_KILL_HW | test_bit(STATUS_RF_KILL_SW, &priv->status) << STATUS_RF_KILL_SW | + test_bit(STATUS_GEO_CONFIGURED, &priv->status) << + STATUS_GEO_CONFIGURED | test_bit(STATUS_IN_SUSPEND, &priv->status) << STATUS_IN_SUSPEND | test_bit(STATUS_FW_ERROR, &priv->status) << diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index f423241b9567..a23d4798653b 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -692,6 +692,11 @@ static int iwl4965_enqueue_hcmd(struct iwl4965_priv *priv, struct iwl4965_host_c BUG_ON((fix_size > TFD_MAX_PAYLOAD_SIZE) && !(cmd->meta.flags & CMD_SIZE_HUGE)); + if (iwl4965_is_rfkill(priv)) { + IWL_DEBUG_INFO("Not sending command - RF KILL"); + return -EIO; + } + if (iwl4965_queue_space(q) < ((cmd->meta.flags & CMD_ASYNC) ? 2 : 1)) { IWL_ERROR("No space for Tx\n"); return -ENOSPC; @@ -1654,7 +1659,7 @@ static inline void iwl4965_eeprom_release_semaphore(struct iwl4965_priv *priv) */ int iwl4965_eeprom_init(struct iwl4965_priv *priv) { - __le16 *e = (__le16 *)&priv->eeprom; + u16 *e = (u16 *)&priv->eeprom; u32 gp = iwl4965_read32(priv, CSR_EEPROM_GP); u32 r; int sz = sizeof(priv->eeprom); @@ -1698,7 +1703,7 @@ int iwl4965_eeprom_init(struct iwl4965_priv *priv) rc = -ETIMEDOUT; goto done; } - e[addr / 2] = cpu_to_le16(r >> 16); + e[addr / 2] = le16_to_cpu((__force __le16)(r >> 16)); } rc = 0; @@ -2935,7 +2940,7 @@ static int iwl4965_tx_skb(struct iwl4965_priv *priv, /* drop all data frame if we are not associated */ if (((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) && (!iwl4965_is_associated(priv) || - !priv->assoc_id || + ((priv->iw_mode == IEEE80211_IF_TYPE_STA) && !priv->assoc_id) || !priv->assoc_station_added)) { IWL_DEBUG_DROP("Dropping - !iwl4965_is_associated\n"); goto drop_unlock; @@ -4664,7 +4669,7 @@ static void iwl4965_rx_handle(struct iwl4965_priv *priv) int reclaim; unsigned long flags; u8 fill_rx = 0; - u32 count = 0; + u32 count = 8; /* uCode's read index (stored in shared DRAM) indicates the last Rx * buffer that the driver may process (last buffer filled by ucode). */ @@ -6680,6 +6685,8 @@ static void __iwl4965_down(struct iwl4965_priv *priv) STATUS_RF_KILL_HW | test_bit(STATUS_RF_KILL_SW, &priv->status) << STATUS_RF_KILL_SW | + test_bit(STATUS_GEO_CONFIGURED, &priv->status) << + STATUS_GEO_CONFIGURED | test_bit(STATUS_IN_SUSPEND, &priv->status) << STATUS_IN_SUSPEND; goto exit; @@ -6691,6 +6698,8 @@ static void __iwl4965_down(struct iwl4965_priv *priv) STATUS_RF_KILL_HW | test_bit(STATUS_RF_KILL_SW, &priv->status) << STATUS_RF_KILL_SW | + test_bit(STATUS_GEO_CONFIGURED, &priv->status) << + STATUS_GEO_CONFIGURED | test_bit(STATUS_IN_SUSPEND, &priv->status) << STATUS_IN_SUSPEND | test_bit(STATUS_FW_ERROR, &priv->status) << diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index d3ecf89abd93..8ce2ddf8024f 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c @@ -2300,7 +2300,7 @@ static void rndis_update_wireless_stats(struct work_struct *work) struct usbnet *usbdev = priv->usbdev; struct iw_statistics iwstats; __le32 rssi, tmp; - int len, ret, bitrate, j; + int len, ret, j; unsigned long flags; int update_jiffies = STATS_UPDATE_JIFFIES; void *buf; @@ -2352,14 +2352,10 @@ static void rndis_update_wireless_stats(struct work_struct *work) if (ret == 0) iwstats.discard.misc += le32_to_cpu(tmp); - /* Workaround transfer stalls on poor quality links. */ - len = sizeof(tmp); - ret = rndis_query_oid(usbdev, OID_GEN_LINK_SPEED, &tmp, &len); - if (ret == 0) { - bitrate = le32_to_cpu(tmp) * 100; - if (bitrate > 11000000) - goto end; - + /* Workaround transfer stalls on poor quality links. + * TODO: find right way to fix these stalls (as stalls do not happen + * with ndiswrapper/windows driver). */ + if (iwstats.qual.qual <= 25) { /* Decrease stats worker interval to catch stalls. * faster. Faster than 400-500ms causes packet loss, * Slower doesn't catch stalls fast enough. diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 86ded4066f5b..4ca9730e5e92 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -1839,11 +1839,11 @@ static struct usb_device_id rt2500usb_device_table[] = { /* Hercules */ { USB_DEVICE(0x06f8, 0xe000), USB_DEVICE_DATA(&rt2500usb_ops) }, /* Melco */ + { USB_DEVICE(0x0411, 0x005e), USB_DEVICE_DATA(&rt2500usb_ops) }, { USB_DEVICE(0x0411, 0x0066), USB_DEVICE_DATA(&rt2500usb_ops) }, { USB_DEVICE(0x0411, 0x0067), USB_DEVICE_DATA(&rt2500usb_ops) }, { USB_DEVICE(0x0411, 0x008b), USB_DEVICE_DATA(&rt2500usb_ops) }, { USB_DEVICE(0x0411, 0x0097), USB_DEVICE_DATA(&rt2500usb_ops) }, - /* MSI */ { USB_DEVICE(0x0db0, 0x6861), USB_DEVICE_DATA(&rt2500usb_ops) }, { USB_DEVICE(0x0db0, 0x6865), USB_DEVICE_DATA(&rt2500usb_ops) }, diff --git a/drivers/net/wireless/wavelan.h b/drivers/net/wireless/wavelan.h index 27172cde5a39..9ab360558ffd 100644 --- a/drivers/net/wireless/wavelan.h +++ b/drivers/net/wireless/wavelan.h @@ -85,7 +85,7 @@ union hacs_u #define HASR_MMC_INTR 0x0002 /* Interrupt request from MMC */ #define HASR_MMC_BUSY 0x0004 /* MMC busy indication */ #define HASR_PSA_BUSY 0x0008 /* LAN parameter storage area busy */ -}; +} __attribute__ ((packed)); typedef struct ha_t ha_t; struct ha_t @@ -292,7 +292,7 @@ struct mmw_t #define MMW_EXT_ANT_INTERNAL 0x00 /* Internal antenna */ #define MMW_EXT_ANT_EXTERNAL 0x03 /* External antenna */ #define MMW_EXT_ANT_IQ_TEST 0x1C /* IQ test pattern (set to 0) */ -}; +} __attribute__ ((packed)); #define MMW_SIZE 37 @@ -347,7 +347,7 @@ struct mmr_t unsigned char mmr_unused4[1]; /* unused */ unsigned char mmr_fee_data_l; /* Read data from EEPROM (low) */ unsigned char mmr_fee_data_h; /* Read data from EEPROM (high) */ -}; +} __attribute__ ((packed)); #define MMR_SIZE 36 diff --git a/drivers/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c index 8134c7e198a5..b07ba2a14119 100644 --- a/drivers/oprofile/buffer_sync.c +++ b/drivers/oprofile/buffer_sync.c @@ -187,23 +187,22 @@ void sync_stop(void) end_sync(); } - + /* Optimisation. We can manage without taking the dcookie sem * because we cannot reach this code without at least one * dcookie user still being registered (namely, the reader * of the event buffer). */ -static inline unsigned long fast_get_dcookie(struct dentry * dentry, - struct vfsmount * vfsmnt) +static inline unsigned long fast_get_dcookie(struct path *path) { unsigned long cookie; - - if (dentry->d_cookie) - return (unsigned long)dentry; - get_dcookie(dentry, vfsmnt, &cookie); + + if (path->dentry->d_cookie) + return (unsigned long)path->dentry; + get_dcookie(path, &cookie); return cookie; } - + /* Look up the dcookie for the task's first VM_EXECUTABLE mapping, * which corresponds loosely to "application name". This is * not strictly necessary but allows oprofile to associate @@ -222,8 +221,7 @@ 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_path.dentry, - vma->vm_file->f_path.mnt); + cookie = fast_get_dcookie(&vma->vm_file->f_path); break; } @@ -248,8 +246,7 @@ 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_path.dentry, - vma->vm_file->f_path.mnt); + cookie = fast_get_dcookie(&vma->vm_file->f_path); *offset = (vma->vm_pgoff << PAGE_SHIFT) + addr - vma->vm_start; } else { diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index e569645d59e2..4a23654184fc 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c @@ -158,6 +158,7 @@ run_osc_out: /** * __pci_osc_support_set - register OS support to Firmware * @flags: OS support bits + * @hid: hardware ID * * Update OS support fields and doing a _OSC Query to obtain an update * from Firmware on supported control bits. @@ -241,8 +242,6 @@ EXPORT_SYMBOL(pci_osc_control_set); * choose from highest power _SxD to lowest power _SxW * else // no _PRW at S-state x * choose highest power _SxD or any lower power - * - * currently we simply return _SxD, if present. */ static pci_power_t acpi_pci_choose_state(struct pci_dev *pdev, diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c index 662b4c279cfc..c283a9a70d83 100644 --- a/drivers/pnp/pnpacpi/core.c +++ b/drivers/pnp/pnpacpi/core.c @@ -36,7 +36,7 @@ static int num = 0; * have irqs (PIC, Timer) because we call acpi_register_gsi. * Finally, only devices that have a CRS method need to be in this list. */ -static struct __initdata acpi_device_id excluded_id_list[] = { +static struct acpi_device_id excluded_id_list[] __initdata = { {"PNP0C09", 0}, /* EC */ {"PNP0C0F", 0}, /* Link device */ {"PNP0000", 0}, /* PIC */ diff --git a/drivers/pnp/pnpbios/core.c b/drivers/pnp/pnpbios/core.c index f7e67197a568..a8a51500e1e9 100644 --- a/drivers/pnp/pnpbios/core.c +++ b/drivers/pnp/pnpbios/core.c @@ -105,8 +105,6 @@ static int pnp_dock_event(int dock, struct pnp_docking_station_info *info) char *argv[3], **envp, *buf, *scratch; int i = 0, value; - if (!current->fs->root) - return -EAGAIN; if (!(envp = kcalloc(20, sizeof(char *), GFP_KERNEL))) return -ENOMEM; if (!(buf = kzalloc(256, GFP_KERNEL))) { diff --git a/drivers/ps3/ps3-lpm.c b/drivers/ps3/ps3-lpm.c index 4c066545d176..6c9592ce4996 100644 --- a/drivers/ps3/ps3-lpm.c +++ b/drivers/ps3/ps3-lpm.c @@ -76,7 +76,6 @@ * * @pm_control: Shadow of the processor's pm_control register. * @pm_start_stop: Shadow of the processor's pm_start_stop register. - * @pm_interval: Shadow of the processor's pm_interval register. * @group_control: Shadow of the processor's group_control register. * @debug_bus_control: Shadow of the processor's debug_bus_control register. * @@ -91,7 +90,6 @@ struct ps3_lpm_shadow_regs { u64 pm_control; u64 pm_start_stop; - u64 pm_interval; u64 group_control; u64 debug_bus_control; }; @@ -181,9 +179,9 @@ void ps3_set_bookmark(u64 bookmark) * includes cycles before the call. */ - asm volatile("or 29, 29, 29;"); /* db10cyc */ + asm volatile("nop;nop;nop;nop;nop;nop;nop;nop;nop;"); mtspr(SPRN_BKMK, bookmark); - asm volatile("or 29, 29, 29;"); /* db10cyc */ + asm volatile("nop;nop;nop;nop;nop;nop;nop;nop;nop;"); } EXPORT_SYMBOL_GPL(ps3_set_bookmark); @@ -408,7 +406,14 @@ u32 ps3_read_pm(u32 cpu, enum pm_reg_name reg) case pm_start_stop: return lpm_priv->shadow.pm_start_stop; case pm_interval: - return lpm_priv->shadow.pm_interval; + result = lv1_set_lpm_interval(lpm_priv->lpm_id, 0, 0, &val); + if (result) { + val = 0; + dev_dbg(sbd_core(), "%s:%u: lv1 set_inteval failed: " + "reg %u, %s\n", __func__, __LINE__, reg, + ps3_result(result)); + } + return (u32)val; case group_control: return lpm_priv->shadow.group_control; case debug_bus_control: @@ -475,10 +480,8 @@ void ps3_write_pm(u32 cpu, enum pm_reg_name reg, u32 val) lpm_priv->shadow.pm_control = val; break; case pm_interval: - if (val != lpm_priv->shadow.pm_interval) - result = lv1_set_lpm_interval(lpm_priv->lpm_id, val, - PS3_WRITE_PM_MASK, &dummy); - lpm_priv->shadow.pm_interval = val; + result = lv1_set_lpm_interval(lpm_priv->lpm_id, val, + PS3_WRITE_PM_MASK, &dummy); break; case pm_start_stop: if (val != lpm_priv->shadow.pm_start_stop) @@ -1140,7 +1143,6 @@ int ps3_lpm_open(enum ps3_lpm_tb_type tb_type, void *tb_cache, lpm_priv->shadow.pm_control = PS3_LPM_SHADOW_REG_INIT; lpm_priv->shadow.pm_start_stop = PS3_LPM_SHADOW_REG_INIT; - lpm_priv->shadow.pm_interval = PS3_LPM_SHADOW_REG_INIT; lpm_priv->shadow.group_control = PS3_LPM_SHADOW_REG_INIT; lpm_priv->shadow.debug_bus_control = PS3_LPM_SHADOW_REG_INIT; diff --git a/drivers/ps3/ps3-sys-manager.c b/drivers/ps3/ps3-sys-manager.c index c3c3aba3ffce..d4f6f960dd18 100644 --- a/drivers/ps3/ps3-sys-manager.c +++ b/drivers/ps3/ps3-sys-manager.c @@ -28,10 +28,6 @@ #include "vuart.h" -MODULE_AUTHOR("Sony Corporation"); -MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("PS3 System Manager"); - /** * ps3_sys_manager - PS3 system manager driver. * @@ -142,9 +138,11 @@ enum ps3_sys_manager_attr { /** * enum ps3_sys_manager_event - External event type, reported by system manager. - * @PS3_SM_EVENT_POWER_PRESSED: payload.value not used. + * @PS3_SM_EVENT_POWER_PRESSED: payload.value = + * enum ps3_sys_manager_button_event. * @PS3_SM_EVENT_POWER_RELEASED: payload.value = time pressed in millisec. - * @PS3_SM_EVENT_RESET_PRESSED: payload.value not used. + * @PS3_SM_EVENT_RESET_PRESSED: payload.value = + * enum ps3_sys_manager_button_event. * @PS3_SM_EVENT_RESET_RELEASED: payload.value = time pressed in millisec. * @PS3_SM_EVENT_THERMAL_ALERT: payload.value = thermal zone id. * @PS3_SM_EVENT_THERMAL_CLEARED: payload.value = thermal zone id. @@ -161,6 +159,17 @@ enum ps3_sys_manager_event { /* no info on controller events */ }; +/** + * enum ps3_sys_manager_button_event - Button event payload values. + * @PS3_SM_BUTTON_EVENT_HARD: Hardware generated event. + * @PS3_SM_BUTTON_EVENT_SOFT: Software generated event. + */ + +enum ps3_sys_manager_button_event { + PS3_SM_BUTTON_EVENT_HARD = 0, + PS3_SM_BUTTON_EVENT_SOFT = 1, +}; + /** * enum ps3_sys_manager_next_op - Operation to perform after lpar is destroyed. */ @@ -181,7 +190,9 @@ enum ps3_sys_manager_next_op { * @PS3_SM_WAKE_P_O_R: Power on reset. * * Additional wakeup sources when specifying PS3_SM_NEXT_OP_SYS_SHUTDOWN. - * System will always wake from the PS3_SM_WAKE_DEFAULT sources. + * The system will always wake from the PS3_SM_WAKE_DEFAULT sources. + * Sources listed here are the only ones available to guests in the + * other-os lpar. */ enum ps3_sys_manager_wake_source { @@ -189,7 +200,7 @@ enum ps3_sys_manager_wake_source { PS3_SM_WAKE_DEFAULT = 0, PS3_SM_WAKE_RTC = 0x00000040, PS3_SM_WAKE_RTC_ERROR = 0x00000080, - PS3_SM_WAKE_P_O_R = 0x10000000, + PS3_SM_WAKE_P_O_R = 0x80000000, }; /** @@ -418,8 +429,10 @@ static int ps3_sys_manager_handle_event(struct ps3_system_bus_device *dev) switch (event.type) { case PS3_SM_EVENT_POWER_PRESSED: - dev_dbg(&dev->core, "%s:%d: POWER_PRESSED\n", - __func__, __LINE__); + dev_dbg(&dev->core, "%s:%d: POWER_PRESSED (%s)\n", + __func__, __LINE__, + (event.value == PS3_SM_BUTTON_EVENT_SOFT ? "soft" + : "hard")); ps3_sm_force_power_off = 1; /* * A memory barrier is use here to sync memory since @@ -434,8 +447,10 @@ static int ps3_sys_manager_handle_event(struct ps3_system_bus_device *dev) __func__, __LINE__, event.value); break; case PS3_SM_EVENT_RESET_PRESSED: - dev_dbg(&dev->core, "%s:%d: RESET_PRESSED\n", - __func__, __LINE__); + dev_dbg(&dev->core, "%s:%d: RESET_PRESSED (%s)\n", + __func__, __LINE__, + (event.value == PS3_SM_BUTTON_EVENT_SOFT ? "soft" + : "hard")); ps3_sm_force_power_off = 0; /* * A memory barrier is use here to sync memory since @@ -622,7 +637,7 @@ static void ps3_sys_manager_final_restart(struct ps3_system_bus_device *dev) ps3_vuart_cancel_async(dev); ps3_sys_manager_send_attr(dev, 0); - ps3_sys_manager_send_next_op(dev, PS3_SM_NEXT_OP_LPAR_REBOOT, + ps3_sys_manager_send_next_op(dev, PS3_SM_NEXT_OP_SYS_REBOOT, PS3_SM_WAKE_DEFAULT); ps3_sys_manager_send_request_shutdown(dev); @@ -699,4 +714,7 @@ static int __init ps3_sys_manager_init(void) module_init(ps3_sys_manager_init); /* Module remove not supported. */ +MODULE_AUTHOR("Sony Corporation"); +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("PS3 System Manager"); MODULE_ALIAS(PS3_MODULE_ALIAS_SYSTEM_MANAGER); diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index d984e0fae630..ccf46c96adb4 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -1149,12 +1149,14 @@ static void __dasd_device_process_final_queue(struct dasd_device *device, { struct list_head *l, *n; struct dasd_ccw_req *cqr; + struct dasd_block *block; list_for_each_safe(l, n, final_queue) { cqr = list_entry(l, struct dasd_ccw_req, devlist); list_del_init(&cqr->devlist); - if (cqr->block) - spin_lock_bh(&cqr->block->queue_lock); + block = cqr->block; + if (block) + spin_lock_bh(&block->queue_lock); switch (cqr->status) { case DASD_CQR_SUCCESS: cqr->status = DASD_CQR_DONE; @@ -1172,15 +1174,13 @@ static void __dasd_device_process_final_queue(struct dasd_device *device, cqr, cqr->status); BUG(); } - if (cqr->block) - spin_unlock_bh(&cqr->block->queue_lock); if (cqr->callback != NULL) (cqr->callback)(cqr, cqr->callback_data); + if (block) + spin_unlock_bh(&block->queue_lock); } } - - /* * Take a look at the first request on the ccw queue and check * if it reached its expire time. If so, terminate the IO. diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c index 3faf0538b328..e6c94dbfdeaa 100644 --- a/drivers/s390/block/dcssblk.c +++ b/drivers/s390/block/dcssblk.c @@ -666,7 +666,7 @@ dcssblk_make_request(struct request_queue *q, struct bio *bio) page_addr = (unsigned long) page_address(bvec->bv_page) + bvec->bv_offset; source_addr = dev_info->start + (index<<12) + bytes_done; - if (unlikely(page_addr & 4095) != 0 || (bvec->bv_len & 4095) != 0) + if (unlikely((page_addr & 4095) != 0) || (bvec->bv_len & 4095) != 0) // More paranoia. goto fail; if (bio_data_dir(bio) == READ) { diff --git a/drivers/s390/char/sclp.c b/drivers/s390/char/sclp.c index 25629b92dec3..2c7a1ee6b041 100644 --- a/drivers/s390/char/sclp.c +++ b/drivers/s390/char/sclp.c @@ -29,10 +29,10 @@ static ext_int_info_t ext_int_info_hwc; /* Lock to protect internal data consistency. */ static DEFINE_SPINLOCK(sclp_lock); -/* Mask of events that we can receive from the sclp interface. */ +/* Mask of events that we can send to the sclp interface. */ static sccb_mask_t sclp_receive_mask; -/* Mask of events that we can send to the sclp interface. */ +/* Mask of events that we can receive from the sclp interface. */ static sccb_mask_t sclp_send_mask; /* List of registered event listeners and senders. */ @@ -380,7 +380,7 @@ sclp_interrupt_handler(__u16 code) } sclp_running_state = sclp_running_state_idle; } - if (evbuf_pending && sclp_receive_mask != 0 && + if (evbuf_pending && sclp_activation_state == sclp_activation_state_active) __sclp_queue_read_req(); spin_unlock(&sclp_lock); @@ -459,8 +459,8 @@ sclp_dispatch_state_change(void) reg = NULL; list_for_each(l, &sclp_reg_list) { reg = list_entry(l, struct sclp_register, list); - receive_mask = reg->receive_mask & sclp_receive_mask; - send_mask = reg->send_mask & sclp_send_mask; + receive_mask = reg->send_mask & sclp_receive_mask; + send_mask = reg->receive_mask & sclp_send_mask; if (reg->sclp_receive_mask != receive_mask || reg->sclp_send_mask != send_mask) { reg->sclp_receive_mask = receive_mask; @@ -615,8 +615,8 @@ struct init_sccb { u16 mask_length; sccb_mask_t receive_mask; sccb_mask_t send_mask; - sccb_mask_t sclp_send_mask; sccb_mask_t sclp_receive_mask; + sccb_mask_t sclp_send_mask; } __attribute__((packed)); /* Prepare init mask request. Called while sclp_lock is locked. */ diff --git a/drivers/s390/char/sclp.h b/drivers/s390/char/sclp.h index aa8186d18aee..bac80e856f97 100644 --- a/drivers/s390/char/sclp.h +++ b/drivers/s390/char/sclp.h @@ -122,11 +122,13 @@ struct sclp_req { /* of some routines it wants to be called from the low level driver */ struct sclp_register { struct list_head list; - /* event masks this user is registered for */ + /* User wants to receive: */ sccb_mask_t receive_mask; + /* User wants to send: */ sccb_mask_t send_mask; - /* actually present events */ + /* H/W can receive: */ sccb_mask_t sclp_receive_mask; + /* H/W can send: */ sccb_mask_t sclp_send_mask; /* called if event type availability changes */ void (*state_change_fn)(struct sclp_register *); diff --git a/drivers/s390/char/sclp_config.c b/drivers/s390/char/sclp_config.c index 9dc77f14fa52..b8f35bc52b7b 100644 --- a/drivers/s390/char/sclp_config.c +++ b/drivers/s390/char/sclp_config.c @@ -64,7 +64,7 @@ static int __init sclp_conf_init(void) return rc; } - if (!(sclp_conf_register.sclp_receive_mask & EVTYP_CONFMGMDATA_MASK)) { + if (!(sclp_conf_register.sclp_send_mask & EVTYP_CONFMGMDATA_MASK)) { printk(KERN_WARNING TAG "no configuration management.\n"); sclp_unregister(&sclp_conf_register); rc = -ENOSYS; diff --git a/drivers/s390/char/sclp_cpi_sys.c b/drivers/s390/char/sclp_cpi_sys.c index 41617032afdc..9f37456222e9 100644 --- a/drivers/s390/char/sclp_cpi_sys.c +++ b/drivers/s390/char/sclp_cpi_sys.c @@ -129,7 +129,7 @@ static int cpi_req(void) "to hardware console.\n"); goto out; } - if (!(sclp_cpi_event.sclp_send_mask & EVTYP_CTLPROGIDENT_MASK)) { + if (!(sclp_cpi_event.sclp_receive_mask & EVTYP_CTLPROGIDENT_MASK)) { printk(KERN_WARNING "cpi: no control program " "identification support\n"); rc = -EOPNOTSUPP; diff --git a/drivers/s390/char/sclp_rw.c b/drivers/s390/char/sclp_rw.c index ad7195d3de0c..da09781b32f7 100644 --- a/drivers/s390/char/sclp_rw.c +++ b/drivers/s390/char/sclp_rw.c @@ -452,10 +452,10 @@ sclp_emit_buffer(struct sclp_buffer *buffer, return -EIO; sccb = buffer->sccb; - if (sclp_rw_event.sclp_send_mask & EVTYP_MSG_MASK) + if (sclp_rw_event.sclp_receive_mask & EVTYP_MSG_MASK) /* Use normal write message */ sccb->msg_buf.header.type = EVTYP_MSG; - else if (sclp_rw_event.sclp_send_mask & EVTYP_PMSGCMD_MASK) + else if (sclp_rw_event.sclp_receive_mask & EVTYP_PMSGCMD_MASK) /* Use write priority message */ sccb->msg_buf.header.type = EVTYP_PMSGCMD; else diff --git a/drivers/s390/char/sclp_vt220.c b/drivers/s390/char/sclp_vt220.c index f47f4a768be5..92f527201792 100644 --- a/drivers/s390/char/sclp_vt220.c +++ b/drivers/s390/char/sclp_vt220.c @@ -202,7 +202,7 @@ sclp_vt220_callback(struct sclp_req *request, void *data) static int __sclp_vt220_emit(struct sclp_vt220_request *request) { - if (!(sclp_vt220_register.sclp_send_mask & EVTYP_VT220MSG_MASK)) { + if (!(sclp_vt220_register.sclp_receive_mask & EVTYP_VT220MSG_MASK)) { request->sclp_req.status = SCLP_REQ_FAILED; return -EIO; } diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index d35dc3f25d06..fec004f62bcf 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c @@ -32,7 +32,7 @@ #include "io_sch.h" static struct timer_list recovery_timer; -static spinlock_t recovery_lock; +static DEFINE_SPINLOCK(recovery_lock); static int recovery_phase; static const unsigned long recovery_delay[] = { 3, 30, 300 }; @@ -1535,7 +1535,7 @@ static int recovery_check(struct device *dev, void *data) return 0; } -static void recovery_func(unsigned long data) +static void recovery_work_func(struct work_struct *unused) { int redo = 0; @@ -1553,6 +1553,17 @@ static void recovery_func(unsigned long data) CIO_MSG_EVENT(2, "recovery: end\n"); } +static DECLARE_WORK(recovery_work, recovery_work_func); + +static void recovery_func(unsigned long data) +{ + /* + * We can't do our recovery in softirq context and it's not + * performance critical, so we schedule it. + */ + schedule_work(&recovery_work); +} + void ccw_device_schedule_recovery(void) { unsigned long flags; diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c index 097fc0967e9d..2b5bfb7c69e5 100644 --- a/drivers/s390/cio/qdio.c +++ b/drivers/s390/cio/qdio.c @@ -32,7 +32,7 @@ #include #include - +#include #include #include #include @@ -1215,9 +1215,6 @@ tiqdio_is_inbound_q_done(struct qdio_q *q) if (!no_used) return 1; - if (!q->siga_sync && !irq->is_qebsm) - /* we'll check for more primed buffers in qeth_stop_polling */ - return 0; if (irq->is_qebsm) { count = 1; start_buf = q->first_to_check; @@ -3332,13 +3329,7 @@ qdio_activate(struct ccw_device *cdev, int flags) } } - wait_event_interruptible_timeout(cdev->private->wait_q, - ((irq_ptr->state == - QDIO_IRQ_STATE_STOPPED) || - (irq_ptr->state == - QDIO_IRQ_STATE_ERR)), - QDIO_ACTIVATE_TIMEOUT); - + msleep(QDIO_ACTIVATE_TIMEOUT); switch (irq_ptr->state) { case QDIO_IRQ_STATE_STOPPED: case QDIO_IRQ_STATE_ERR: diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h index 37870e4e938e..da8a272fd75b 100644 --- a/drivers/s390/cio/qdio.h +++ b/drivers/s390/cio/qdio.h @@ -57,10 +57,10 @@ of the queue to 0 */ #define QDIO_ESTABLISH_TIMEOUT (1*HZ) -#define QDIO_ACTIVATE_TIMEOUT (5*HZ) #define QDIO_CLEANUP_CLEAR_TIMEOUT (20*HZ) #define QDIO_CLEANUP_HALT_TIMEOUT (10*HZ) #define QDIO_FORCE_CHECK_TIMEOUT (10*HZ) +#define QDIO_ACTIVATE_TIMEOUT (5) /* 5 ms */ enum qdio_irq_states { QDIO_IRQ_STATE_INACTIVE, diff --git a/drivers/s390/net/claw.h b/drivers/s390/net/claw.h index 1ee9a6f06541..1a89d989f348 100644 --- a/drivers/s390/net/claw.h +++ b/drivers/s390/net/claw.h @@ -114,11 +114,20 @@ do { \ debug_event(claw_dbf_##name,level,(void*)(addr),len); \ } while (0) +/* Allow to sort out low debug levels early to avoid wasted sprints */ +static inline int claw_dbf_passes(debug_info_t *dbf_grp, int level) +{ + return (level <= dbf_grp->level); +} + #define CLAW_DBF_TEXT_(level,name,text...) \ -do { \ - sprintf(debug_buffer, text); \ - debug_text_event(claw_dbf_##name,level, debug_buffer);\ -} while (0) + do { \ + if (claw_dbf_passes(claw_dbf_##name, level)) { \ + sprintf(debug_buffer, text); \ + debug_text_event(claw_dbf_##name, level, \ + debug_buffer); \ + } \ + } while (0) /******************************************************* * Define Control Blocks * @@ -278,8 +287,6 @@ struct claw_env { __u16 write_size; /* write buffer size */ __u16 dev_id; /* device ident */ __u8 packing; /* are we packing? */ - volatile __u8 queme_switch; /* gate for imed packing */ - volatile unsigned long pk_delay; /* Delay for adaptive packing */ __u8 in_use; /* device active flag */ struct net_device *ndev; /* backward ptr to the net dev*/ }; diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c index 7bfe8d707a34..f51ed9972587 100644 --- a/drivers/s390/net/lcs.c +++ b/drivers/s390/net/lcs.c @@ -94,7 +94,7 @@ static int lcs_register_debug_facility(void) { lcs_dbf_setup = debug_register("lcs_setup", 2, 1, 8); - lcs_dbf_trace = debug_register("lcs_trace", 2, 2, 8); + lcs_dbf_trace = debug_register("lcs_trace", 4, 1, 8); if (lcs_dbf_setup == NULL || lcs_dbf_trace == NULL) { PRINT_ERR("Not enough memory for debug facility.\n"); lcs_unregister_debug_facility(); diff --git a/drivers/s390/net/lcs.h b/drivers/s390/net/lcs.h index 8976fb0b070a..d58fea52557d 100644 --- a/drivers/s390/net/lcs.h +++ b/drivers/s390/net/lcs.h @@ -16,11 +16,19 @@ do { \ debug_event(lcs_dbf_##name,level,(void*)(addr),len); \ } while (0) +/* Allow to sort out low debug levels early to avoid wasted sprints */ +static inline int lcs_dbf_passes(debug_info_t *dbf_grp, int level) +{ + return (level <= dbf_grp->level); +} + #define LCS_DBF_TEXT_(level,name,text...) \ -do { \ - sprintf(debug_buffer, text); \ - debug_text_event(lcs_dbf_##name,level, debug_buffer);\ -} while (0) + do { \ + if (lcs_dbf_passes(lcs_dbf_##name, level)) { \ + sprintf(debug_buffer, text); \ + debug_text_event(lcs_dbf_##name, level, debug_buffer); \ + } \ + } while (0) /** * sysfs related stuff diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c index f3d893cfe61d..874a19994489 100644 --- a/drivers/s390/net/netiucv.c +++ b/drivers/s390/net/netiucv.c @@ -97,12 +97,22 @@ MODULE_DESCRIPTION ("Linux for S/390 IUCV network driver"); DECLARE_PER_CPU(char[256], iucv_dbf_txt_buf); -#define IUCV_DBF_TEXT_(name,level,text...) \ - do { \ - char* iucv_dbf_txt_buf = get_cpu_var(iucv_dbf_txt_buf); \ - sprintf(iucv_dbf_txt_buf, text); \ - debug_text_event(iucv_dbf_##name,level,iucv_dbf_txt_buf); \ - put_cpu_var(iucv_dbf_txt_buf); \ +/* Allow to sort out low debug levels early to avoid wasted sprints */ +static inline int iucv_dbf_passes(debug_info_t *dbf_grp, int level) +{ + return (level <= dbf_grp->level); +} + +#define IUCV_DBF_TEXT_(name, level, text...) \ + do { \ + if (iucv_dbf_passes(iucv_dbf_##name, level)) { \ + char* iucv_dbf_txt_buf = \ + get_cpu_var(iucv_dbf_txt_buf); \ + sprintf(iucv_dbf_txt_buf, text); \ + debug_text_event(iucv_dbf_##name, level, \ + iucv_dbf_txt_buf); \ + put_cpu_var(iucv_dbf_txt_buf); \ + } \ } while (0) #define IUCV_DBF_SPRINTF(name,level,text...) \ @@ -137,6 +147,7 @@ PRINT_##importance(header "%02x %02x %02x %02x %02x %02x %02x %02x " \ #define PRINTK_HEADER " iucv: " /* for debugging */ static struct device_driver netiucv_driver = { + .owner = THIS_MODULE, .name = "netiucv", .bus = &iucv_bus, }; @@ -572,9 +583,9 @@ static void netiucv_callback_connres(struct iucv_path *path, u8 ipuser[16]) } /** - * Dummy NOP action for all statemachines + * NOP action for statemachines */ -static void fsm_action_nop(fsm_instance *fi, int event, void *arg) +static void netiucv_action_nop(fsm_instance *fi, int event, void *arg) { } @@ -1110,7 +1121,7 @@ static const fsm_node dev_fsm[] = { { DEV_STATE_RUNNING, DEV_EVENT_STOP, dev_action_stop }, { DEV_STATE_RUNNING, DEV_EVENT_CONDOWN, dev_action_conndown }, - { DEV_STATE_RUNNING, DEV_EVENT_CONUP, fsm_action_nop }, + { DEV_STATE_RUNNING, DEV_EVENT_CONUP, netiucv_action_nop }, }; static const int DEV_FSM_LEN = sizeof(dev_fsm) / sizeof(fsm_node); diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 2074701f7e76..c72014a3e7d4 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -5140,7 +5140,7 @@ static void ipr_build_ata_ioadl(struct ipr_cmnd *ipr_cmd, struct ipr_ioarcb *ioarcb = &ipr_cmd->ioarcb; struct ipr_ioadl_desc *ioadl = ipr_cmd->ioadl; struct ipr_ioadl_desc *last_ioadl = NULL; - int len = qc->nbytes + qc->pad_len; + int len = qc->nbytes; struct scatterlist *sg; unsigned int si; @@ -5206,7 +5206,7 @@ static unsigned int ipr_qc_issue(struct ata_queued_cmd *qc) ioarcb->cmd_pkt.request_type = IPR_RQTYPE_ATA_PASSTHRU; ioarcb->cmd_pkt.flags_hi |= IPR_FLAGS_HI_NO_LINK_DESC; ioarcb->cmd_pkt.flags_hi |= IPR_FLAGS_HI_NO_ULEN_CHK; - ipr_cmd->dma_use_sg = qc->pad_len ? qc->n_elem + 1 : qc->n_elem; + ipr_cmd->dma_use_sg = qc->n_elem; ipr_build_ata_ioadl(ipr_cmd, qc); regs->flags |= IPR_ATA_FLAG_STATUS_ON_GOOD_COMPLETION; diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c index 0996f866f14c..7cd05b599a12 100644 --- a/drivers/scsi/libsas/sas_ata.c +++ b/drivers/scsi/libsas/sas_ata.c @@ -178,8 +178,8 @@ static unsigned int sas_ata_qc_issue(struct ata_queued_cmd *qc) task->uldd_task = qc; if (ata_is_atapi(qc->tf.protocol)) { memcpy(task->ata_task.atapi_packet, qc->cdb, qc->dev->cdb_len); - task->total_xfer_len = qc->nbytes + qc->pad_len; - task->num_scatter = qc->pad_len ? qc->n_elem + 1 : qc->n_elem; + task->total_xfer_len = qc->nbytes; + task->num_scatter = qc->n_elem; } else { for_each_sg(qc->sg, sg, qc->n_elem, si) xfer += sg->length; diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 135c1d054701..ba21d97d1855 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -1014,10 +1014,6 @@ static int scsi_init_sgtable(struct request *req, struct scsi_data_buffer *sdb, } req->buffer = NULL; - if (blk_pc_request(req)) - sdb->length = req->data_len; - else - sdb->length = req->nr_sectors << 9; /* * Next, walk the list, and fill in the addresses and sizes of @@ -1026,6 +1022,10 @@ static int scsi_init_sgtable(struct request *req, struct scsi_data_buffer *sdb, count = blk_rq_map_sg(req->q, req, sdb->table.sgl); BUG_ON(count > sdb->table.nents); sdb->table.nents = count; + if (blk_pc_request(req)) + sdb->length = req->data_len; + else + sdb->length = req->nr_sectors << 9; return BLKPREP_OK; } diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index ddf639144538..9ce12cb2cebc 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c @@ -393,7 +393,7 @@ static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag) if (cflag & CRTSCTS) { fcr_val |= SCFCR_MCE; } else { -#ifdef CONFIG_CPU_SUBTYPE_SH7343 +#if defined(CONFIG_CPU_SUBTYPE_SH7343) || defined(CONFIG_CPU_SUBTYPE_SH7366) /* Nothing */ #elif defined(CONFIG_CPU_SUBTYPE_SH7763) || \ defined(CONFIG_CPU_SUBTYPE_SH7780) || \ diff --git a/drivers/serial/sh-sci.h b/drivers/serial/sh-sci.h index f5764ebcfe07..01a9dd715f5d 100644 --- a/drivers/serial/sh-sci.h +++ b/drivers/serial/sh-sci.h @@ -97,13 +97,18 @@ # define SCSCR_INIT(port) 0x0038 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ # define SCIF_ONLY # define PORT_PSCR 0xA405011E +#elif defined(CONFIG_CPU_SUBTYPE_SH7366) +# define SCPDR0 0xA405013E /* 16 bit SCIF0 PSDR */ +# define SCSPTR0 SCPDR0 +# define SCIF_ORER 0x0001 /* overrun error bit */ +# define SCSCR_INIT(port) 0x0038 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ +# define SCIF_ONLY #elif defined(CONFIG_CPU_SUBTYPE_SH4_202) # define SCSPTR2 0xffe80020 /* 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 #elif defined(CONFIG_CPU_SUBTYPE_SH5_101) || defined(CONFIG_CPU_SUBTYPE_SH5_103) -# include # define SCIF_BASE_ADDR 0x01030000 # define SCIF_ADDR_SH5 PHYS_PERIPHERAL_BLOCK+SCIF_BASE_ADDR # define SCIF_PTR2_OFFS 0x0000020 @@ -577,7 +582,7 @@ static inline int sci_rxd_in(struct uart_port *port) return ctrl_inw(SCSPTR3) & 0x0001 ? 1 : 0; /* SCIF */ return 1; } -#elif defined(CONFIG_CPU_SUBTYPE_SH7722) +#elif defined(CONFIG_CPU_SUBTYPE_SH7722) || defined(CONFIG_CPU_SUBTYPE_SH7366) static inline int sci_rxd_in(struct uart_port *port) { if (port->mapbase == 0xffe00000) diff --git a/drivers/sh/maple/maple.c b/drivers/sh/maple/maple.c index e52a6296ca46..9cfcfd8dad5e 100644 --- a/drivers/sh/maple/maple.c +++ b/drivers/sh/maple/maple.c @@ -31,6 +31,7 @@ #include #include #include +#include MODULE_AUTHOR("Yaegshi Takeshi, Paul Mundt, M.R. Brown, Adrian McMenamin"); MODULE_DESCRIPTION("Maple bus driver for Dreamcast"); @@ -53,12 +54,12 @@ static struct device maple_bus; static int subdevice_map[MAPLE_PORTS]; static unsigned long *maple_sendbuf, *maple_sendptr, *maple_lastptr; static unsigned long maple_pnp_time; -static int started, scanning, liststatus; +static int started, scanning, liststatus, realscan; static struct kmem_cache *maple_queue_cache; struct maple_device_specify { - int port; - int unit; + int port; + int unit; }; /** @@ -68,22 +69,22 @@ struct maple_device_specify { */ int maple_driver_register(struct device_driver *drv) { - if (!drv) - return -EINVAL; - drv->bus = &maple_bus_type; - return driver_register(drv); + if (!drv) + return -EINVAL; + drv->bus = &maple_bus_type; + return driver_register(drv); } EXPORT_SYMBOL_GPL(maple_driver_register); /* set hardware registers to enable next round of dma */ static void maplebus_dma_reset(void) { - ctrl_outl(MAPLE_MAGIC, MAPLE_RESET); - /* set trig type to 0 for software trigger, 1 for hardware (VBLANK) */ - ctrl_outl(1, MAPLE_TRIGTYPE); - ctrl_outl(MAPLE_2MBPS | MAPLE_TIMEOUT(50000), MAPLE_SPEED); - ctrl_outl(PHYSADDR(maple_sendbuf), MAPLE_DMAADDR); - ctrl_outl(1, MAPLE_ENABLE); + ctrl_outl(MAPLE_MAGIC, MAPLE_RESET); + /* set trig type to 0 for software trigger, 1 for hardware (VBLANK) */ + ctrl_outl(1, MAPLE_TRIGTYPE); + ctrl_outl(MAPLE_2MBPS | MAPLE_TIMEOUT(50000), MAPLE_SPEED); + ctrl_outl(PHYSADDR(maple_sendbuf), MAPLE_DMAADDR); + ctrl_outl(1, MAPLE_ENABLE); } /** @@ -94,27 +95,36 @@ static void maplebus_dma_reset(void) * @function: the function code for the device */ void maple_getcond_callback(struct maple_device *dev, - void (*callback) (struct mapleq * mq), - unsigned long interval, unsigned long function) + void (*callback) (struct mapleq *mq), + unsigned long interval, unsigned long function) { - dev->callback = callback; - dev->interval = interval; - dev->function = cpu_to_be32(function); - dev->when = jiffies; + dev->callback = callback; + dev->interval = interval; + dev->function = cpu_to_be32(function); + dev->when = jiffies; } EXPORT_SYMBOL_GPL(maple_getcond_callback); static int maple_dma_done(void) { - return (ctrl_inl(MAPLE_STATE) & 1) == 0; + return (ctrl_inl(MAPLE_STATE) & 1) == 0; } static void maple_release_device(struct device *dev) { - if (dev->type) { - kfree(dev->type->name); - kfree(dev->type); - } + struct maple_device *mdev; + struct mapleq *mq; + if (!dev) + return; + mdev = to_maple_dev(dev); + mq = mdev->mq; + if (mq) { + if (mq->recvbufdcsp) + kmem_cache_free(maple_queue_cache, mq->recvbufdcsp); + kfree(mq); + mq = NULL; + } + kfree(mdev); } /** @@ -123,60 +133,64 @@ static void maple_release_device(struct device *dev) */ void maple_add_packet(struct mapleq *mq) { - mutex_lock(&maple_list_lock); - list_add(&mq->list, &maple_waitq); - mutex_unlock(&maple_list_lock); + mutex_lock(&maple_list_lock); + list_add(&mq->list, &maple_waitq); + mutex_unlock(&maple_list_lock); } EXPORT_SYMBOL_GPL(maple_add_packet); -static struct mapleq *maple_allocq(struct maple_device *dev) +static struct mapleq *maple_allocq(struct maple_device *mdev) { - struct mapleq *mq; + struct mapleq *mq; - mq = kmalloc(sizeof(*mq), GFP_KERNEL); - if (!mq) - return NULL; + mq = kmalloc(sizeof(*mq), GFP_KERNEL); + if (!mq) + return NULL; - mq->dev = dev; - mq->recvbufdcsp = kmem_cache_zalloc(maple_queue_cache, GFP_KERNEL); - mq->recvbuf = (void *) P2SEGADDR(mq->recvbufdcsp); - if (!mq->recvbuf) { - kfree(mq); - return NULL; - } + mq->dev = mdev; + mq->recvbufdcsp = kmem_cache_zalloc(maple_queue_cache, GFP_KERNEL); + mq->recvbuf = (void *) P2SEGADDR(mq->recvbufdcsp); + if (!mq->recvbuf) { + kfree(mq); + return NULL; + } - return mq; + return mq; } static struct maple_device *maple_alloc_dev(int port, int unit) { - struct maple_device *dev; + struct maple_device *mdev; - dev = kzalloc(sizeof(*dev), GFP_KERNEL); - if (!dev) - return NULL; + mdev = kzalloc(sizeof(*mdev), GFP_KERNEL); + if (!mdev) + return NULL; - dev->port = port; - dev->unit = unit; - dev->mq = maple_allocq(dev); + mdev->port = port; + mdev->unit = unit; + mdev->mq = maple_allocq(mdev); - if (!dev->mq) { - kfree(dev); - return NULL; - } - - return dev; + if (!mdev->mq) { + kfree(mdev); + return NULL; + } + mdev->dev.bus = &maple_bus_type; + mdev->dev.parent = &maple_bus; + mdev->function = 0; + return mdev; } static void maple_free_dev(struct maple_device *mdev) { - if (!mdev) - return; - if (mdev->mq) { - kmem_cache_free(maple_queue_cache, mdev->mq->recvbufdcsp); - kfree(mdev->mq); - } - kfree(mdev); + if (!mdev) + return; + if (mdev->mq) { + if (mdev->mq->recvbufdcsp) + kmem_cache_free(maple_queue_cache, + mdev->mq->recvbufdcsp); + kfree(mdev->mq); + } + kfree(mdev); } /* process the command queue into a maple command block @@ -184,153 +198,162 @@ static void maple_free_dev(struct maple_device *mdev) */ static void maple_build_block(struct mapleq *mq) { - int port, unit, from, to, len; - unsigned long *lsendbuf = mq->sendbuf; + int port, unit, from, to, len; + unsigned long *lsendbuf = mq->sendbuf; - port = mq->dev->port & 3; - unit = mq->dev->unit; - len = mq->length; - from = port << 6; - to = (port << 6) | (unit > 0 ? (1 << (unit - 1)) & 0x1f : 0x20); + port = mq->dev->port & 3; + unit = mq->dev->unit; + len = mq->length; + from = port << 6; + to = (port << 6) | (unit > 0 ? (1 << (unit - 1)) & 0x1f : 0x20); - *maple_lastptr &= 0x7fffffff; - maple_lastptr = maple_sendptr; + *maple_lastptr &= 0x7fffffff; + maple_lastptr = maple_sendptr; - *maple_sendptr++ = (port << 16) | len | 0x80000000; - *maple_sendptr++ = PHYSADDR(mq->recvbuf); - *maple_sendptr++ = - mq->command | (to << 8) | (from << 16) | (len << 24); + *maple_sendptr++ = (port << 16) | len | 0x80000000; + *maple_sendptr++ = PHYSADDR(mq->recvbuf); + *maple_sendptr++ = + mq->command | (to << 8) | (from << 16) | (len << 24); - while (len-- > 0) - *maple_sendptr++ = *lsendbuf++; + while (len-- > 0) + *maple_sendptr++ = *lsendbuf++; } /* build up command queue */ static void maple_send(void) { - int i; - int maple_packets; - struct mapleq *mq, *nmq; + int i; + int maple_packets; + struct mapleq *mq, *nmq; - if (!list_empty(&maple_sentq)) - return; - if (list_empty(&maple_waitq) || !maple_dma_done()) - return; - maple_packets = 0; - maple_sendptr = maple_lastptr = maple_sendbuf; - list_for_each_entry_safe(mq, nmq, &maple_waitq, list) { - maple_build_block(mq); - list_move(&mq->list, &maple_sentq); - if (maple_packets++ > MAPLE_MAXPACKETS) - break; - } - if (maple_packets > 0) { - for (i = 0; i < (1 << MAPLE_DMA_PAGES); i++) - dma_cache_sync(0, maple_sendbuf + i * PAGE_SIZE, - PAGE_SIZE, DMA_BIDIRECTIONAL); - } + if (!list_empty(&maple_sentq)) + return; + if (list_empty(&maple_waitq) || !maple_dma_done()) + return; + maple_packets = 0; + maple_sendptr = maple_lastptr = maple_sendbuf; + list_for_each_entry_safe(mq, nmq, &maple_waitq, list) { + maple_build_block(mq); + list_move(&mq->list, &maple_sentq); + if (maple_packets++ > MAPLE_MAXPACKETS) + break; + } + if (maple_packets > 0) { + for (i = 0; i < (1 << MAPLE_DMA_PAGES); i++) + dma_cache_sync(0, maple_sendbuf + i * PAGE_SIZE, + PAGE_SIZE, DMA_BIDIRECTIONAL); + } } static int attach_matching_maple_driver(struct device_driver *driver, - void *devptr) + void *devptr) { - struct maple_driver *maple_drv; - struct maple_device *mdev; + struct maple_driver *maple_drv; + struct maple_device *mdev; - mdev = devptr; - maple_drv = to_maple_driver(driver); - if (mdev->devinfo.function & be32_to_cpu(maple_drv->function)) { - if (maple_drv->connect(mdev) == 0) { - mdev->driver = maple_drv; - return 1; - } - } - return 0; + mdev = devptr; + maple_drv = to_maple_driver(driver); + if (mdev->devinfo.function & be32_to_cpu(maple_drv->function)) { + if (maple_drv->connect(mdev) == 0) { + mdev->driver = maple_drv; + return 1; + } + } + return 0; } static void maple_detach_driver(struct maple_device *mdev) { - if (!mdev) - return; - if (mdev->driver) { - if (mdev->driver->disconnect) - mdev->driver->disconnect(mdev); - } - mdev->driver = NULL; - if (mdev->registered) { - maple_release_device(&mdev->dev); - device_unregister(&mdev->dev); - } - mdev->registered = 0; - maple_free_dev(mdev); + if (!mdev) + return; + if (mdev->driver) { + if (mdev->driver->disconnect) + mdev->driver->disconnect(mdev); + } + mdev->driver = NULL; + device_unregister(&mdev->dev); + mdev = NULL; } /* process initial MAPLE_COMMAND_DEVINFO for each device or port */ -static void maple_attach_driver(struct maple_device *dev) +static void maple_attach_driver(struct maple_device *mdev) { - char *p; + char *p, *recvbuf; + unsigned long function; + int matched, retval; - char *recvbuf; - unsigned long function; - int matched, retval; + recvbuf = mdev->mq->recvbuf; + /* copy the data as individual elements in + * case of memory optimisation */ + memcpy(&mdev->devinfo.function, recvbuf + 4, 4); + memcpy(&mdev->devinfo.function_data[0], recvbuf + 8, 12); + memcpy(&mdev->devinfo.area_code, recvbuf + 20, 1); + memcpy(&mdev->devinfo.connector_direction, recvbuf + 21, 1); + memcpy(&mdev->devinfo.product_name[0], recvbuf + 22, 30); + memcpy(&mdev->devinfo.product_licence[0], recvbuf + 52, 60); + memcpy(&mdev->devinfo.standby_power, recvbuf + 112, 2); + memcpy(&mdev->devinfo.max_power, recvbuf + 114, 2); + memcpy(mdev->product_name, mdev->devinfo.product_name, 30); + mdev->product_name[30] = '\0'; + memcpy(mdev->product_licence, mdev->devinfo.product_licence, 60); + mdev->product_licence[60] = '\0'; - recvbuf = dev->mq->recvbuf; - memcpy(&dev->devinfo, recvbuf + 4, sizeof(dev->devinfo)); - memcpy(dev->product_name, dev->devinfo.product_name, 30); - memcpy(dev->product_licence, dev->devinfo.product_licence, 60); - dev->product_name[30] = '\0'; - dev->product_licence[60] = '\0'; + for (p = mdev->product_name + 29; mdev->product_name <= p; p--) + if (*p == ' ') + *p = '\0'; + else + break; + for (p = mdev->product_licence + 59; mdev->product_licence <= p; p--) + if (*p == ' ') + *p = '\0'; + else + break; - for (p = dev->product_name + 29; dev->product_name <= p; p--) - if (*p == ' ') - *p = '\0'; - else - break; + if (realscan) { + printk(KERN_INFO "Maple device detected: %s\n", + mdev->product_name); + printk(KERN_INFO "Maple device: %s\n", mdev->product_licence); + } - for (p = dev->product_licence + 59; dev->product_licence <= p; p--) - if (*p == ' ') - *p = '\0'; - else - break; + function = be32_to_cpu(mdev->devinfo.function); - function = be32_to_cpu(dev->devinfo.function); + if (function > 0x200) { + /* Do this silently - as not a real device */ + function = 0; + mdev->driver = &maple_dummy_driver; + sprintf(mdev->dev.bus_id, "%d:0.port", mdev->port); + } else { + if (realscan) + printk(KERN_INFO + "Maple bus at (%d, %d): Function 0x%lX\n", + mdev->port, mdev->unit, function); - if (function > 0x200) { - /* Do this silently - as not a real device */ - function = 0; - dev->driver = &maple_dummy_driver; - sprintf(dev->dev.bus_id, "%d:0.port", dev->port); - } else { - printk(KERN_INFO - "Maple bus at (%d, %d): Connected function 0x%lX\n", - dev->port, dev->unit, function); + matched = + bus_for_each_drv(&maple_bus_type, NULL, mdev, + attach_matching_maple_driver); - matched = - bus_for_each_drv(&maple_bus_type, NULL, dev, - attach_matching_maple_driver); - - if (matched == 0) { - /* Driver does not exist yet */ - printk(KERN_INFO - "No maple driver found for this device\n"); - dev->driver = &maple_dummy_driver; - } - - sprintf(dev->dev.bus_id, "%d:0%d.%lX", dev->port, - dev->unit, function); - } - dev->function = function; - dev->dev.bus = &maple_bus_type; - dev->dev.parent = &maple_bus; - dev->dev.release = &maple_release_device; - retval = device_register(&dev->dev); - if (retval) { - printk(KERN_INFO - "Maple bus: Attempt to register device (%x, %x) failed.\n", - dev->port, dev->unit); - maple_free_dev(dev); - } - dev->registered = 1; + if (matched == 0) { + /* Driver does not exist yet */ + if (realscan) + printk(KERN_INFO + "No maple driver found.\n"); + mdev->driver = &maple_dummy_driver; + } + sprintf(mdev->dev.bus_id, "%d:0%d.%lX", mdev->port, + mdev->unit, function); + } + mdev->function = function; + mdev->dev.release = &maple_release_device; + retval = device_register(&mdev->dev); + if (retval) { + printk(KERN_INFO + "Maple bus: Attempt to register device" + " (%x, %x) failed.\n", + mdev->port, mdev->unit); + maple_free_dev(mdev); + mdev = NULL; + return; + } } /* @@ -340,270 +363,262 @@ static void maple_attach_driver(struct maple_device *dev) */ static int detach_maple_device(struct device *device, void *portptr) { - struct maple_device_specify *ds; - struct maple_device *mdev; + struct maple_device_specify *ds; + struct maple_device *mdev; - ds = portptr; - mdev = to_maple_dev(device); - if (mdev->port == ds->port && mdev->unit == ds->unit) - return 1; - return 0; + ds = portptr; + mdev = to_maple_dev(device); + if (mdev->port == ds->port && mdev->unit == ds->unit) + return 1; + return 0; } static int setup_maple_commands(struct device *device, void *ignored) { - struct maple_device *maple_dev = to_maple_dev(device); + struct maple_device *maple_dev = to_maple_dev(device); - if ((maple_dev->interval > 0) - && time_after(jiffies, maple_dev->when)) { - maple_dev->when = jiffies + maple_dev->interval; - maple_dev->mq->command = MAPLE_COMMAND_GETCOND; - maple_dev->mq->sendbuf = &maple_dev->function; - maple_dev->mq->length = 1; - maple_add_packet(maple_dev->mq); - liststatus++; - } else { - if (time_after(jiffies, maple_pnp_time)) { - maple_dev->mq->command = MAPLE_COMMAND_DEVINFO; - maple_dev->mq->length = 0; - maple_add_packet(maple_dev->mq); - liststatus++; - } - } + if ((maple_dev->interval > 0) + && time_after(jiffies, maple_dev->when)) { + maple_dev->when = jiffies + maple_dev->interval; + maple_dev->mq->command = MAPLE_COMMAND_GETCOND; + maple_dev->mq->sendbuf = &maple_dev->function; + maple_dev->mq->length = 1; + maple_add_packet(maple_dev->mq); + liststatus++; + } else { + if (time_after(jiffies, maple_pnp_time)) { + maple_dev->mq->command = MAPLE_COMMAND_DEVINFO; + maple_dev->mq->length = 0; + maple_add_packet(maple_dev->mq); + liststatus++; + } + } - return 0; + return 0; } /* VBLANK bottom half - implemented via workqueue */ static void maple_vblank_handler(struct work_struct *work) { - if (!maple_dma_done()) - return; - if (!list_empty(&maple_sentq)) - return; - ctrl_outl(0, MAPLE_ENABLE); - liststatus = 0; - bus_for_each_dev(&maple_bus_type, NULL, NULL, - setup_maple_commands); - if (time_after(jiffies, maple_pnp_time)) - maple_pnp_time = jiffies + MAPLE_PNP_INTERVAL; - if (liststatus && list_empty(&maple_sentq)) { - INIT_LIST_HEAD(&maple_sentq); - maple_send(); - } - maplebus_dma_reset(); + if (!maple_dma_done()) + return; + if (!list_empty(&maple_sentq)) + return; + ctrl_outl(0, MAPLE_ENABLE); + liststatus = 0; + bus_for_each_dev(&maple_bus_type, NULL, NULL, + setup_maple_commands); + if (time_after(jiffies, maple_pnp_time)) + maple_pnp_time = jiffies + MAPLE_PNP_INTERVAL; + if (liststatus && list_empty(&maple_sentq)) { + INIT_LIST_HEAD(&maple_sentq); + maple_send(); + } + maplebus_dma_reset(); } /* handle devices added via hotplugs - placing them on queue for DEVINFO*/ static void maple_map_subunits(struct maple_device *mdev, int submask) { - int retval, k, devcheck; - struct maple_device *mdev_add; - struct maple_device_specify ds; + int retval, k, devcheck; + struct maple_device *mdev_add; + struct maple_device_specify ds; - for (k = 0; k < 5; k++) { - ds.port = mdev->port; - ds.unit = k + 1; - retval = - bus_for_each_dev(&maple_bus_type, NULL, &ds, - detach_maple_device); - if (retval) { - submask = submask >> 1; - continue; - } - devcheck = submask & 0x01; - if (devcheck) { - mdev_add = maple_alloc_dev(mdev->port, k + 1); - if (!mdev_add) - return; - mdev_add->mq->command = MAPLE_COMMAND_DEVINFO; - mdev_add->mq->length = 0; - maple_add_packet(mdev_add->mq); - scanning = 1; - } - submask = submask >> 1; - } + for (k = 0; k < 5; k++) { + ds.port = mdev->port; + ds.unit = k + 1; + retval = + bus_for_each_dev(&maple_bus_type, NULL, &ds, + detach_maple_device); + if (retval) { + submask = submask >> 1; + continue; + } + devcheck = submask & 0x01; + if (devcheck) { + mdev_add = maple_alloc_dev(mdev->port, k + 1); + if (!mdev_add) + return; + mdev_add->mq->command = MAPLE_COMMAND_DEVINFO; + mdev_add->mq->length = 0; + maple_add_packet(mdev_add->mq); + scanning = 1; + } + submask = submask >> 1; + } } /* mark a device as removed */ static void maple_clean_submap(struct maple_device *mdev) { - int killbit; + int killbit; - killbit = (mdev->unit > 0 ? (1 << (mdev->unit - 1)) & 0x1f : 0x20); - killbit = ~killbit; - killbit &= 0xFF; - subdevice_map[mdev->port] = subdevice_map[mdev->port] & killbit; + killbit = (mdev->unit > 0 ? (1 << (mdev->unit - 1)) & 0x1f : 0x20); + killbit = ~killbit; + killbit &= 0xFF; + subdevice_map[mdev->port] = subdevice_map[mdev->port] & killbit; } /* handle empty port or hotplug removal */ static void maple_response_none(struct maple_device *mdev, - struct mapleq *mq) + struct mapleq *mq) { - if (mdev->unit != 0) { - list_del(&mq->list); - maple_clean_submap(mdev); - printk(KERN_INFO - "Maple bus device detaching at (%d, %d)\n", - mdev->port, mdev->unit); - maple_detach_driver(mdev); - return; - } - if (!started) { - printk(KERN_INFO "No maple devices attached to port %d\n", - mdev->port); - return; - } - maple_clean_submap(mdev); + if (mdev->unit != 0) { + list_del(&mq->list); + maple_clean_submap(mdev); + printk(KERN_INFO + "Maple bus device detaching at (%d, %d)\n", + mdev->port, mdev->unit); + maple_detach_driver(mdev); + return; + } + if (!started) { + printk(KERN_INFO "No maple devices attached to port %d\n", + mdev->port); + return; + } + maple_clean_submap(mdev); } /* preprocess hotplugs or scans */ static void maple_response_devinfo(struct maple_device *mdev, - char *recvbuf) + char *recvbuf) { - char submask; - if ((!started) || (scanning == 2)) { - maple_attach_driver(mdev); - return; - } - if (mdev->unit == 0) { - submask = recvbuf[2] & 0x1F; - if (submask ^ subdevice_map[mdev->port]) { - maple_map_subunits(mdev, submask); - subdevice_map[mdev->port] = submask; - } - } + char submask; + if ((!started) || (scanning == 2)) { + maple_attach_driver(mdev); + return; + } + if (mdev->unit == 0) { + submask = recvbuf[2] & 0x1F; + if (submask ^ subdevice_map[mdev->port]) { + maple_map_subunits(mdev, submask); + subdevice_map[mdev->port] = submask; + } + } } /* maple dma end bottom half - implemented via workqueue */ static void maple_dma_handler(struct work_struct *work) { - struct mapleq *mq, *nmq; - struct maple_device *dev; - char *recvbuf; - enum maple_code code; + struct mapleq *mq, *nmq; + struct maple_device *dev; + char *recvbuf; + enum maple_code code; - if (!maple_dma_done()) - return; - ctrl_outl(0, MAPLE_ENABLE); - if (!list_empty(&maple_sentq)) { - list_for_each_entry_safe(mq, nmq, &maple_sentq, list) { - recvbuf = mq->recvbuf; - code = recvbuf[0]; - dev = mq->dev; - switch (code) { - case MAPLE_RESPONSE_NONE: - maple_response_none(dev, mq); - break; + if (!maple_dma_done()) + return; + ctrl_outl(0, MAPLE_ENABLE); + if (!list_empty(&maple_sentq)) { + list_for_each_entry_safe(mq, nmq, &maple_sentq, list) { + recvbuf = mq->recvbuf; + code = recvbuf[0]; + dev = mq->dev; + switch (code) { + case MAPLE_RESPONSE_NONE: + maple_response_none(dev, mq); + break; - case MAPLE_RESPONSE_DEVINFO: - maple_response_devinfo(dev, recvbuf); - break; + case MAPLE_RESPONSE_DEVINFO: + maple_response_devinfo(dev, recvbuf); + break; - case MAPLE_RESPONSE_DATATRF: - if (dev->callback) - dev->callback(mq); - break; + case MAPLE_RESPONSE_DATATRF: + if (dev->callback) + dev->callback(mq); + break; - case MAPLE_RESPONSE_FILEERR: - case MAPLE_RESPONSE_AGAIN: - case MAPLE_RESPONSE_BADCMD: - case MAPLE_RESPONSE_BADFUNC: - printk(KERN_DEBUG - "Maple non-fatal error 0x%X\n", - code); - break; + case MAPLE_RESPONSE_FILEERR: + case MAPLE_RESPONSE_AGAIN: + case MAPLE_RESPONSE_BADCMD: + case MAPLE_RESPONSE_BADFUNC: + printk(KERN_DEBUG + "Maple non-fatal error 0x%X\n", + code); + break; - case MAPLE_RESPONSE_ALLINFO: - printk(KERN_DEBUG - "Maple - extended device information not supported\n"); - break; + case MAPLE_RESPONSE_ALLINFO: + printk(KERN_DEBUG + "Maple - extended device information" + " not supported\n"); + break; - case MAPLE_RESPONSE_OK: - break; + case MAPLE_RESPONSE_OK: + break; - default: - break; - } - } - INIT_LIST_HEAD(&maple_sentq); - if (scanning == 1) { - maple_send(); - scanning = 2; - } else - scanning = 0; + default: + break; + } + } + INIT_LIST_HEAD(&maple_sentq); + if (scanning == 1) { + maple_send(); + scanning = 2; + } else + scanning = 0; - if (started == 0) - started = 1; - } - maplebus_dma_reset(); + if (started == 0) + started = 1; + } + maplebus_dma_reset(); } static irqreturn_t maplebus_dma_interrupt(int irq, void *dev_id) { - /* Load everything into the bottom half */ - schedule_work(&maple_dma_process); - return IRQ_HANDLED; + /* Load everything into the bottom half */ + schedule_work(&maple_dma_process); + return IRQ_HANDLED; } static irqreturn_t maplebus_vblank_interrupt(int irq, void *dev_id) { - schedule_work(&maple_vblank_process); - return IRQ_HANDLED; + schedule_work(&maple_vblank_process); + return IRQ_HANDLED; } -static struct irqaction maple_dma_irq = { - .name = "maple bus DMA handler", - .handler = maplebus_dma_interrupt, - .flags = IRQF_SHARED, -}; - -static struct irqaction maple_vblank_irq = { - .name = "maple bus VBLANK handler", - .handler = maplebus_vblank_interrupt, - .flags = IRQF_SHARED, -}; - static int maple_set_dma_interrupt_handler(void) { - return setup_irq(HW_EVENT_MAPLE_DMA, &maple_dma_irq); + return request_irq(HW_EVENT_MAPLE_DMA, maplebus_dma_interrupt, + IRQF_SHARED, "maple bus DMA", &maple_dummy_driver); } static int maple_set_vblank_interrupt_handler(void) { - return setup_irq(HW_EVENT_VSYNC, &maple_vblank_irq); + return request_irq(HW_EVENT_VSYNC, maplebus_vblank_interrupt, + IRQF_SHARED, "maple bus VBLANK", &maple_dummy_driver); } static int maple_get_dma_buffer(void) { - maple_sendbuf = - (void *) __get_free_pages(GFP_KERNEL | __GFP_ZERO, - MAPLE_DMA_PAGES); - if (!maple_sendbuf) - return -ENOMEM; - return 0; + maple_sendbuf = + (void *) __get_free_pages(GFP_KERNEL | __GFP_ZERO, + MAPLE_DMA_PAGES); + if (!maple_sendbuf) + return -ENOMEM; + return 0; } static int match_maple_bus_driver(struct device *devptr, - struct device_driver *drvptr) + struct device_driver *drvptr) { - struct maple_driver *maple_drv; - struct maple_device *maple_dev; + struct maple_driver *maple_drv; + struct maple_device *maple_dev; - maple_drv = container_of(drvptr, struct maple_driver, drv); - maple_dev = container_of(devptr, struct maple_device, dev); - /* Trap empty port case */ - if (maple_dev->devinfo.function == 0xFFFFFFFF) - return 0; - else if (maple_dev->devinfo.function & - be32_to_cpu(maple_drv->function)) - return 1; - return 0; + maple_drv = container_of(drvptr, struct maple_driver, drv); + maple_dev = container_of(devptr, struct maple_device, dev); + /* Trap empty port case */ + if (maple_dev->devinfo.function == 0xFFFFFFFF) + return 0; + else if (maple_dev->devinfo.function & + be32_to_cpu(maple_drv->function)) + return 1; + return 0; } -static int maple_bus_uevent(struct device *dev, struct kobj_uevent_env *env) +static int maple_bus_uevent(struct device *dev, + struct kobj_uevent_env *env) { - return 0; + return 0; } static void maple_bus_release(struct device *dev) @@ -611,124 +626,122 @@ static void maple_bus_release(struct device *dev) } static struct maple_driver maple_dummy_driver = { - .drv = { - .name = "maple_dummy_driver", - .bus = &maple_bus_type, - }, + .drv = { + .name = "maple_dummy_driver", + .bus = &maple_bus_type, + }, }; struct bus_type maple_bus_type = { - .name = "maple", - .match = match_maple_bus_driver, - .uevent = maple_bus_uevent, + .name = "maple", + .match = match_maple_bus_driver, + .uevent = maple_bus_uevent, }; EXPORT_SYMBOL_GPL(maple_bus_type); static struct device maple_bus = { - .bus_id = "maple", - .release = maple_bus_release, + .bus_id = "maple", + .release = maple_bus_release, }; static int __init maple_bus_init(void) { - int retval, i; - struct maple_device *mdev[MAPLE_PORTS]; - ctrl_outl(0, MAPLE_STATE); + int retval, i; + struct maple_device *mdev[MAPLE_PORTS]; + ctrl_outl(0, MAPLE_STATE); - retval = device_register(&maple_bus); - if (retval) - goto cleanup; + retval = device_register(&maple_bus); + if (retval) + goto cleanup; - retval = bus_register(&maple_bus_type); - if (retval) - goto cleanup_device; + retval = bus_register(&maple_bus_type); + if (retval) + goto cleanup_device; - retval = driver_register(&maple_dummy_driver.drv); + retval = driver_register(&maple_dummy_driver.drv); + if (retval) + goto cleanup_bus; - if (retval) - goto cleanup_bus; + /* allocate memory for maple bus dma */ + retval = maple_get_dma_buffer(); + if (retval) { + printk(KERN_INFO + "Maple bus: Failed to allocate Maple DMA buffers\n"); + goto cleanup_basic; + } - /* allocate memory for maple bus dma */ - retval = maple_get_dma_buffer(); - if (retval) { - printk(KERN_INFO - "Maple bus: Failed to allocate Maple DMA buffers\n"); - goto cleanup_basic; - } + /* set up DMA interrupt handler */ + retval = maple_set_dma_interrupt_handler(); + if (retval) { + printk(KERN_INFO + "Maple bus: Failed to grab maple DMA IRQ\n"); + goto cleanup_dma; + } - /* set up DMA interrupt handler */ - retval = maple_set_dma_interrupt_handler(); - if (retval) { - printk(KERN_INFO - "Maple bus: Failed to grab maple DMA IRQ\n"); - goto cleanup_dma; - } + /* set up VBLANK interrupt handler */ + retval = maple_set_vblank_interrupt_handler(); + if (retval) { + printk(KERN_INFO "Maple bus: Failed to grab VBLANK IRQ\n"); + goto cleanup_irq; + } - /* set up VBLANK interrupt handler */ - retval = maple_set_vblank_interrupt_handler(); - if (retval) { - printk(KERN_INFO "Maple bus: Failed to grab VBLANK IRQ\n"); - goto cleanup_irq; - } + maple_queue_cache = + kmem_cache_create("maple_queue_cache", 0x400, 0, + SLAB_POISON|SLAB_HWCACHE_ALIGN, NULL); - maple_queue_cache = - kmem_cache_create("maple_queue_cache", 0x400, 0, - SLAB_HWCACHE_ALIGN, NULL); + if (!maple_queue_cache) + goto cleanup_bothirqs; - if (!maple_queue_cache) - goto cleanup_bothirqs; + /* setup maple ports */ + for (i = 0; i < MAPLE_PORTS; i++) { + mdev[i] = maple_alloc_dev(i, 0); + if (!mdev[i]) { + while (i-- > 0) + maple_free_dev(mdev[i]); + goto cleanup_cache; + } + mdev[i]->mq->command = MAPLE_COMMAND_DEVINFO; + mdev[i]->mq->length = 0; + maple_add_packet(mdev[i]->mq); + /* delay aids hardware detection */ + mdelay(5); + subdevice_map[i] = 0; + } - /* setup maple ports */ - for (i = 0; i < MAPLE_PORTS; i++) { - mdev[i] = maple_alloc_dev(i, 0); - if (!mdev[i]) { - while (i-- > 0) - maple_free_dev(mdev[i]); - goto cleanup_cache; - } - mdev[i]->registered = 0; - mdev[i]->mq->command = MAPLE_COMMAND_DEVINFO; - mdev[i]->mq->length = 0; - maple_attach_driver(mdev[i]); - maple_add_packet(mdev[i]->mq); - subdevice_map[i] = 0; - } + realscan = 1; + /* setup maplebus hardware */ + maplebus_dma_reset(); + /* initial detection */ + maple_send(); + maple_pnp_time = jiffies; + printk(KERN_INFO "Maple bus core now registered.\n"); - /* setup maplebus hardware */ - maplebus_dma_reset(); - - /* initial detection */ - maple_send(); - - maple_pnp_time = jiffies; - - printk(KERN_INFO "Maple bus core now registered.\n"); - - return 0; + return 0; cleanup_cache: - kmem_cache_destroy(maple_queue_cache); + kmem_cache_destroy(maple_queue_cache); cleanup_bothirqs: - free_irq(HW_EVENT_VSYNC, 0); + free_irq(HW_EVENT_VSYNC, 0); cleanup_irq: - free_irq(HW_EVENT_MAPLE_DMA, 0); + free_irq(HW_EVENT_MAPLE_DMA, 0); cleanup_dma: - free_pages((unsigned long) maple_sendbuf, MAPLE_DMA_PAGES); + free_pages((unsigned long) maple_sendbuf, MAPLE_DMA_PAGES); cleanup_basic: - driver_unregister(&maple_dummy_driver.drv); + driver_unregister(&maple_dummy_driver.drv); cleanup_bus: - bus_unregister(&maple_bus_type); + bus_unregister(&maple_bus_type); cleanup_device: - device_unregister(&maple_bus); + device_unregister(&maple_bus); cleanup: - printk(KERN_INFO "Maple bus registration failed\n"); - return retval; + printk(KERN_INFO "Maple bus registration failed\n"); + return retval; } -subsys_initcall(maple_bus_init); +/* Push init to later to ensure hardware gets detected */ +fs_initcall(maple_bus_init); diff --git a/drivers/thermal/thermal.c b/drivers/thermal/thermal.c index e782b3e7fcdb..8b86e53ccf7a 100644 --- a/drivers/thermal/thermal.c +++ b/drivers/thermal/thermal.c @@ -306,12 +306,23 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz, { struct thermal_cooling_device_instance *dev; struct thermal_cooling_device_instance *pos; + struct thermal_zone_device *pos1; + struct thermal_cooling_device *pos2; int result; if (trip >= tz->trips || (trip < 0 && trip != THERMAL_TRIPS_NONE)) return -EINVAL; - if (!tz || !cdev) + list_for_each_entry(pos1, &thermal_tz_list, node) { + if (pos1 == tz) + break; + } + list_for_each_entry(pos2, &thermal_cdev_list, node) { + if (pos2 == cdev) + break; + } + + if (tz != pos1 || cdev != pos2) return -EINVAL; dev = @@ -437,20 +448,20 @@ struct thermal_cooling_device *thermal_cooling_device_register(char *type, int result; if (strlen(type) >= THERMAL_NAME_LENGTH) - return NULL; + return ERR_PTR(-EINVAL); if (!ops || !ops->get_max_state || !ops->get_cur_state || !ops->set_cur_state) - return NULL; + return ERR_PTR(-EINVAL); cdev = kzalloc(sizeof(struct thermal_cooling_device), GFP_KERNEL); if (!cdev) - return NULL; + return ERR_PTR(-ENOMEM); result = get_idr(&thermal_cdev_idr, &thermal_idr_lock, &cdev->id); if (result) { kfree(cdev); - return NULL; + return ERR_PTR(result); } strcpy(cdev->type, type); @@ -462,7 +473,7 @@ struct thermal_cooling_device *thermal_cooling_device_register(char *type, if (result) { release_idr(&thermal_cdev_idr, &thermal_idr_lock, cdev->id); kfree(cdev); - return NULL; + return ERR_PTR(result); } /* sys I/F */ @@ -498,7 +509,7 @@ struct thermal_cooling_device *thermal_cooling_device_register(char *type, unregister: release_idr(&thermal_cdev_idr, &thermal_idr_lock, cdev->id); device_unregister(&cdev->device); - return NULL; + return ERR_PTR(result); } EXPORT_SYMBOL(thermal_cooling_device_register); @@ -570,17 +581,17 @@ struct thermal_zone_device *thermal_zone_device_register(char *type, int count; if (strlen(type) >= THERMAL_NAME_LENGTH) - return NULL; + return ERR_PTR(-EINVAL); if (trips > THERMAL_MAX_TRIPS || trips < 0) - return NULL; + return ERR_PTR(-EINVAL); if (!ops || !ops->get_temp) - return NULL; + return ERR_PTR(-EINVAL); tz = kzalloc(sizeof(struct thermal_zone_device), GFP_KERNEL); if (!tz) - return NULL; + return ERR_PTR(-ENOMEM); INIT_LIST_HEAD(&tz->cooling_devices); idr_init(&tz->idr); @@ -588,7 +599,7 @@ struct thermal_zone_device *thermal_zone_device_register(char *type, result = get_idr(&thermal_tz_idr, &thermal_idr_lock, &tz->id); if (result) { kfree(tz); - return NULL; + return ERR_PTR(result); } strcpy(tz->type, type); @@ -601,7 +612,7 @@ struct thermal_zone_device *thermal_zone_device_register(char *type, if (result) { release_idr(&thermal_tz_idr, &thermal_idr_lock, tz->id); kfree(tz); - return NULL; + return ERR_PTR(result); } /* sys I/F */ @@ -643,7 +654,7 @@ struct thermal_zone_device *thermal_zone_device_register(char *type, unregister: release_idr(&thermal_tz_idr, &thermal_idr_lock, tz->id); device_unregister(&tz->device); - return NULL; + return ERR_PTR(result); } EXPORT_SYMBOL(thermal_zone_device_register); diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c index 3301167d4f2a..017a196d041f 100644 --- a/drivers/usb/gadget/file_storage.c +++ b/drivers/usb/gadget/file_storage.c @@ -3563,8 +3563,7 @@ static ssize_t show_file(struct device *dev, struct device_attribute *attr, down_read(&fsg->filesem); if (backing_file_is_open(curlun)) { // Get the complete pathname - p = d_path(curlun->filp->f_path.dentry, - curlun->filp->f_path.mnt, buf, PAGE_SIZE - 1); + p = d_path(&curlun->filp->f_path, buf, PAGE_SIZE - 1); if (IS_ERR(p)) rc = PTR_ERR(p); else { @@ -3981,9 +3980,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_path.dentry, - curlun->filp->f_path.mnt, - pathbuf, PATH_MAX); + p = d_path(&curlun->filp->f_path, + pathbuf, PATH_MAX); if (IS_ERR(p)) p = NULL; } diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c index d775eb6590b6..62f9c6e387cc 100644 --- a/drivers/video/aty/atyfb_base.c +++ b/drivers/video/aty/atyfb_base.c @@ -1913,61 +1913,6 @@ static int atyfb_mmap(struct fb_info *info, struct vm_area_struct *vma) par->mmaped = 1; return 0; } - -static struct { - u32 yoffset; - u8 r[2][256]; - u8 g[2][256]; - u8 b[2][256]; -} atyfb_save; - -static void atyfb_save_palette(struct atyfb_par *par, int enter) -{ - int i, tmp; - - for (i = 0; i < 256; i++) { - tmp = aty_ld_8(DAC_CNTL, par) & 0xfc; - if (M64_HAS(EXTRA_BRIGHT)) - tmp |= 0x2; - aty_st_8(DAC_CNTL, tmp, par); - aty_st_8(DAC_MASK, 0xff, par); - - 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); - } -} - -static void atyfb_palette(int enter) -{ - struct atyfb_par *par; - struct fb_info *info; - int i; - - for (i = 0; i < FB_MAX; i++) { - info = registered_fb[i]; - if (info && info->fbops == &atyfb_ops) { - par = (struct atyfb_par *) info->par; - - atyfb_save_palette(par, enter); - if (enter) { - atyfb_save.yoffset = info->var.yoffset; - info->var.yoffset = 0; - set_off_pitch(par, info); - } else { - info->var.yoffset = atyfb_save.yoffset; - set_off_pitch(par, info); - } - aty_st_le32(CRTC_OFF_PITCH, par->crtc.off_pitch, par); - break; - } - } -} #endif /* __sparc__ */ @@ -2670,10 +2615,6 @@ static int __devinit aty_init(struct fb_info *info) goto aty_init_exit; } -#ifdef __sparc__ - atyfb_save_palette(par, 0); -#endif - #ifdef CONFIG_FB_ATY_CT if (!noaccel && M64_HAS(INTEGRATED)) aty_init_cursor(info); @@ -2900,8 +2841,6 @@ static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, #ifdef __sparc__ -extern void (*prom_palette) (int); - static int __devinit atyfb_setup_sparc(struct pci_dev *pdev, struct fb_info *info, unsigned long addr) { @@ -3536,9 +3475,6 @@ static int __devinit atyfb_pci_probe(struct pci_dev *pdev, const struct pci_devi goto err_release_io; #ifdef __sparc__ - if (!prom_palette) - prom_palette = atyfb_palette; - /* * Add /dev/fb mmap values. */ diff --git a/drivers/video/cg14.c b/drivers/video/cg14.c index 41f6dbf61be7..fdc9f43ec30a 100644 --- a/drivers/video/cg14.c +++ b/drivers/video/cg14.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include diff --git a/drivers/video/sbuslib.c b/drivers/video/sbuslib.c index 963a454b7074..4deaac05b938 100644 --- a/drivers/video/sbuslib.c +++ b/drivers/video/sbuslib.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index afcdc69e37d6..254d115cafab 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -402,6 +402,18 @@ config IT8712F_WDT To compile this driver as a module, choose M here: the module will be called it8712f_wdt. +config HP_WATCHDOG + tristate "HP Proliant iLO 2 Hardware Watchdog Timer" + depends on X86 + help + A software monitoring watchdog and NMI sourcing driver. This driver + will detect lockups and provide stack trace. Also, when an NMI + occurs this driver will make the necessary BIOS calls to log + the cause of the NMI. This is a driver that will only load on a + HP ProLiant system with a minimum of iLO2 support. + To compile this driver as a module, choose M here: the + module will be called hpwdt. + config SC1200_WDT tristate "National Semiconductor PC87307/PC97307 (ala SC1200) Watchdog" depends on X86 @@ -633,6 +645,19 @@ config WDT_RM9K_GPI To compile this driver as a module, choose M here: the module will be called rm9k_wdt. +config SIBYTE_WDOG + tristate "Sibyte SoC hardware watchdog" + depends on CPU_SB1 + help + Watchdog driver for the built in watchdog hardware in Sibyte + SoC processors. There are apparently two watchdog timers + on such processors; this driver supports only the first one, + because currently Linux only supports exporting one watchdog + to userspace. + + To compile this driver as a loadable module, choose M here. + The module will be called sb_wdog. + config AR7_WDT tristate "TI AR7 Watchdog Timer" depends on AR7 diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index ebc21146d40c..f3fb170fe5c6 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -67,6 +67,7 @@ obj-$(CONFIG_WAFER_WDT) += wafer5823wdt.o obj-$(CONFIG_I6300ESB_WDT) += i6300esb.o obj-$(CONFIG_ITCO_WDT) += iTCO_wdt.o iTCO_vendor_support.o obj-$(CONFIG_IT8712F_WDT) += it8712f_wdt.o +obj-$(CONFIG_HP_WATCHDOG) += hpwdt.o obj-$(CONFIG_SC1200_WDT) += sc1200wdt.o obj-$(CONFIG_SCx200_WDT) += scx200_wdt.o obj-$(CONFIG_PC87413_WDT) += pc87413_wdt.o @@ -92,6 +93,7 @@ obj-$(CONFIG_SBC_EPX_C3_WATCHDOG) += sbc_epx_c3.o obj-$(CONFIG_INDYDOG) += indydog.o obj-$(CONFIG_WDT_MTX1) += mtx-1_wdt.o obj-$(CONFIG_WDT_RM9K_GPI) += rm9k_wdt.o +obj-$(CONFIG_SIBYTE_WDOG) += sb_wdog.o obj-$(CONFIG_AR7_WDT) += ar7_wdt.o obj-$(CONFIG_TXX9_WDT) += txx9wdt.o diff --git a/drivers/watchdog/bfin_wdt.c b/drivers/watchdog/bfin_wdt.c index 472be10f0686..1237113dc14a 100644 --- a/drivers/watchdog/bfin_wdt.c +++ b/drivers/watchdog/bfin_wdt.c @@ -29,6 +29,7 @@ #define stamp(fmt, args...) pr_debug("%s:%i: " fmt "\n", __func__, __LINE__, ## args) #define stampit() stamp("here i am") +#define pr_init(fmt, args...) ({ static const __initdata char __fmt[] = fmt; printk(__fmt, ## args); }) #define WATCHDOG_NAME "bfin-wdt" #define PFX WATCHDOG_NAME ": " @@ -445,19 +446,19 @@ static int __init bfin_wdt_init(void) ret = register_reboot_notifier(&bfin_wdt_notifier); if (ret) { - printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", ret); + pr_init(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", ret); return ret; } ret = misc_register(&bfin_wdt_miscdev); if (ret) { - printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", + pr_init(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", WATCHDOG_MINOR, ret); unregister_reboot_notifier(&bfin_wdt_notifier); return ret; } - printk(KERN_INFO PFX "initialized: timeout=%d sec (nowayout=%d)\n", + pr_init(KERN_INFO PFX "initialized: timeout=%d sec (nowayout=%d)\n", timeout, nowayout); return 0; diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c new file mode 100644 index 000000000000..a2e174b09fe7 --- /dev/null +++ b/drivers/watchdog/hpwdt.c @@ -0,0 +1,926 @@ +/* + * HP WatchDog Driver + * based on + * + * SoftDog 0.05: A Software Watchdog Device + * + * (c) Copyright 2007 Hewlett-Packard Development Company, L.P. + * Thomas Mingarelli + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PCI_BIOS32_SD_VALUE 0x5F32335F /* "_32_" */ +#define CRU_BIOS_SIGNATURE_VALUE 0x55524324 +#define PCI_BIOS32_PARAGRAPH_LEN 16 +#define PCI_ROM_BASE1 0x000F0000 +#define ROM_SIZE 0x10000 + +struct bios32_service_dir { + u32 signature; + u32 entry_point; + u8 revision; + u8 length; + u8 checksum; + u8 reserved[5]; +}; + +/* + * smbios_entry_point - defines SMBIOS entry point structure + * + * anchor[4] - anchor string (_SM_) + * checksum - checksum of the entry point structure + * length - length of the entry point structure + * major_ver - major version (02h for revision 2.1) + * minor_ver - minor version (01h for revision 2.1) + * max_struct_size - size of the largest SMBIOS structure + * revision - entry point structure revision implemented + * formatted_area[5] - reserved + * intermediate_anchor[5] - intermediate anchor string (_DMI_) + * intermediate_checksum - intermediate checksum + * table_length - structure table length + * table_address - structure table address + * table_num_structs - number of SMBIOS structures present + * bcd_revision - BCD revision + */ +struct smbios_entry_point { + u8 anchor[4]; + u8 checksum; + u8 length; + u8 major_ver; + u8 minor_ver; + u16 max_struct_size; + u8 revision; + u8 formatted_area[5]; + u8 intermediate_anchor[5]; + u8 intermediate_checksum; + u16 table_length; + u64 table_address; + u16 table_num_structs; + u8 bcd_revision; +}; + +/* type 212 */ +struct smbios_cru64_info { + u8 type; + u8 byte_length; + u16 handle; + u32 signature; + u64 physical_address; + u32 double_length; + u32 double_offset; +}; +#define SMBIOS_CRU64_INFORMATION 212 + +struct cmn_registers { + union { + struct { + u8 ral; + u8 rah; + u16 rea2; + }; + u32 reax; + } u1; + union { + struct { + u8 rbl; + u8 rbh; + u8 reb2l; + u8 reb2h; + }; + u32 rebx; + } u2; + union { + struct { + u8 rcl; + u8 rch; + u16 rec2; + }; + u32 recx; + } u3; + union { + struct { + u8 rdl; + u8 rdh; + u16 red2; + }; + u32 redx; + } u4; + + u32 resi; + u32 redi; + u16 rds; + u16 res; + u32 reflags; +} __attribute__((packed)); + +#define DEFAULT_MARGIN 30 +static unsigned int soft_margin = DEFAULT_MARGIN; /* in seconds */ +static unsigned int reload; /* the computed soft_margin */ +static int nowayout = WATCHDOG_NOWAYOUT; +static char expect_release; +static unsigned long hpwdt_is_open; + +static void __iomem *pci_mem_addr; /* the PCI-memory address */ +static unsigned long __iomem *hpwdt_timer_reg; +static unsigned long __iomem *hpwdt_timer_con; + +static DEFINE_SPINLOCK(rom_lock); + +static void *cru_rom_addr; + +static struct cmn_registers cmn_regs; + +static struct pci_device_id hpwdt_devices[] = { + { + .vendor = PCI_VENDOR_ID_COMPAQ, + .device = 0xB203, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + }, + {0}, /* terminate list */ +}; +MODULE_DEVICE_TABLE(pci, hpwdt_devices); + +/* + * bios_checksum + */ +static int __devinit bios_checksum(const char __iomem *ptr, int len) +{ + char sum = 0; + int i; + + /* + * calculate checksum of size bytes. This should add up + * to zero if we have a valid header. + */ + for (i = 0; i < len; i++) + sum += ptr[i]; + + return ((sum == 0) && (len > 0)); +} + +#ifndef CONFIG_X86_64 +/* --32 Bit Bios------------------------------------------------------------ */ + +#define HPWDT_ARCH 32 + +asmlinkage void asminline_call(struct cmn_registers *pi86Regs, + unsigned long *pRomEntry) +{ + asm("pushl %ebp \n\t" + "movl %esp, %ebp \n\t" + "pusha \n\t" + "pushf \n\t" + "push %es \n\t" + "push %ds \n\t" + "pop %es \n\t" + "movl 8(%ebp),%eax \n\t" + "movl 4(%eax),%ebx \n\t" + "movl 8(%eax),%ecx \n\t" + "movl 12(%eax),%edx \n\t" + "movl 16(%eax),%esi \n\t" + "movl 20(%eax),%edi \n\t" + "movl (%eax),%eax \n\t" + "push %cs \n\t" + "call *12(%ebp) \n\t" + "pushf \n\t" + "pushl %eax \n\t" + "movl 8(%ebp),%eax \n\t" + "movl %ebx,4(%eax) \n\t" + "movl %ecx,8(%eax) \n\t" + "movl %edx,12(%eax) \n\t" + "movl %esi,16(%eax) \n\t" + "movl %edi,20(%eax) \n\t" + "movw %ds,24(%eax) \n\t" + "movw %es,26(%eax) \n\t" + "popl %ebx \n\t" + "movl %ebx,(%eax) \n\t" + "popl %ebx \n\t" + "movl %ebx,28(%eax) \n\t" + "pop %es \n\t" + "popf \n\t" + "popa \n\t" + "leave \n\t" "ret"); +} + +/* + * cru_detect + * + * Routine Description: + * This function uses the 32-bit BIOS Service Directory record to + * search for a $CRU record. + * + * Return Value: + * 0 : SUCCESS + * <0 : FAILURE + */ +static int __devinit cru_detect(unsigned long map_entry, + unsigned long map_offset) +{ + void *bios32_map; + unsigned long *bios32_entrypoint; + unsigned long cru_physical_address; + unsigned long cru_length; + unsigned long physical_bios_base = 0; + unsigned long physical_bios_offset = 0; + int retval = -ENODEV; + + bios32_map = ioremap(map_entry, (2 * PAGE_SIZE)); + + if (bios32_map == NULL) + return -ENODEV; + + bios32_entrypoint = bios32_map + map_offset; + + cmn_regs.u1.reax = CRU_BIOS_SIGNATURE_VALUE; + + asminline_call(&cmn_regs, bios32_entrypoint); + + if (cmn_regs.u1.ral != 0) { + printk(KERN_WARNING + "hpwdt: Call succeeded but with an error: 0x%x\n", + cmn_regs.u1.ral); + } else { + physical_bios_base = cmn_regs.u2.rebx; + physical_bios_offset = cmn_regs.u4.redx; + cru_length = cmn_regs.u3.recx; + cru_physical_address = + physical_bios_base + physical_bios_offset; + + /* If the values look OK, then map it in. */ + if ((physical_bios_base + physical_bios_offset)) { + cru_rom_addr = + ioremap(cru_physical_address, cru_length); + if (cru_rom_addr) + retval = 0; + } + + printk(KERN_DEBUG "hpwdt: CRU Base Address: 0x%lx\n", + physical_bios_base); + printk(KERN_DEBUG "hpwdt: CRU Offset Address: 0x%lx\n", + physical_bios_offset); + printk(KERN_DEBUG "hpwdt: CRU Length: 0x%lx\n", + cru_length); + printk(KERN_DEBUG "hpwdt: CRU Mapped Address: 0x%x\n", + (unsigned int)&cru_rom_addr); + } + iounmap(bios32_map); + return retval; +} + +/* + * bios32_present + * + * Routine Description: + * This function finds the 32-bit BIOS Service Directory + * + * Return Value: + * 0 : SUCCESS + * <0 : FAILURE + */ +static int __devinit bios32_present(const char __iomem *p) +{ + struct bios32_service_dir *bios_32_ptr; + int length; + unsigned long map_entry, map_offset; + + bios_32_ptr = (struct bios32_service_dir *) p; + + /* + * Search for signature by checking equal to the swizzled value + * instead of calling another routine to perform a strcmp. + */ + if (bios_32_ptr->signature == PCI_BIOS32_SD_VALUE) { + length = bios_32_ptr->length * PCI_BIOS32_PARAGRAPH_LEN; + if (bios_checksum(p, length)) { + /* + * According to the spec, we're looking for the + * first 4KB-aligned address below the entrypoint + * listed in the header. The Service Directory code + * is guaranteed to occupy no more than 2 4KB pages. + */ + map_entry = bios_32_ptr->entry_point & ~(PAGE_SIZE - 1); + map_offset = bios_32_ptr->entry_point - map_entry; + + return cru_detect(map_entry, map_offset); + } + } + return -ENODEV; +} + +static int __devinit detect_cru_service(void) +{ + char __iomem *p, *q; + int rc = -1; + + /* + * Search from 0x0f0000 through 0x0fffff, inclusive. + */ + p = ioremap(PCI_ROM_BASE1, ROM_SIZE); + if (p == NULL) + return -ENOMEM; + + for (q = p; q < p + ROM_SIZE; q += 16) { + rc = bios32_present(q); + if (!rc) + break; + } + iounmap(p); + return rc; +} + +#else +/* --64 Bit Bios------------------------------------------------------------ */ + +#define HPWDT_ARCH 64 + +asmlinkage void asminline_call(struct cmn_registers *pi86Regs, + unsigned long *pRomEntry) +{ + asm("pushq %rbp \n\t" + "movq %rsp, %rbp \n\t" + "pushq %rax \n\t" + "pushq %rbx \n\t" + "pushq %rdx \n\t" + "pushq %r12 \n\t" + "pushq %r9 \n\t" + "movq %rsi, %r12 \n\t" + "movq %rdi, %r9 \n\t" + "movl 4(%r9),%ebx \n\t" + "movl 8(%r9),%ecx \n\t" + "movl 12(%r9),%edx \n\t" + "movl 16(%r9),%esi \n\t" + "movl 20(%r9),%edi \n\t" + "movl (%r9),%eax \n\t" + "call *%r12 \n\t" + "pushfq \n\t" + "popq %r12 \n\t" + "popfq \n\t" + "movl %eax, (%r9) \n\t" + "movl %ebx, 4(%r9) \n\t" + "movl %ecx, 8(%r9) \n\t" + "movl %edx, 12(%r9) \n\t" + "movl %esi, 16(%r9) \n\t" + "movl %edi, 20(%r9) \n\t" + "movq %r12, %rax \n\t" + "movl %eax, 28(%r9) \n\t" + "popq %r9 \n\t" + "popq %r12 \n\t" + "popq %rdx \n\t" + "popq %rbx \n\t" + "popq %rax \n\t" + "leave \n\t" "ret"); +} + +/* + * dmi_find_cru + * + * Routine Description: + * This function checks wether or not a SMBIOS/DMI record is + * the 64bit CRU info or not + * + * Return Value: + * 0 : SUCCESS - if record found + * <0 : FAILURE - if record not found + */ +static void __devinit dmi_find_cru(const struct dmi_header *dm) +{ + struct smbios_cru64_info *smbios_cru64_ptr; + unsigned long cru_physical_address; + + if (dm->type == SMBIOS_CRU64_INFORMATION) { + smbios_cru64_ptr = (struct smbios_cru64_info *) dm; + if (smbios_cru64_ptr->signature == CRU_BIOS_SIGNATURE_VALUE) { + cru_physical_address = + smbios_cru64_ptr->physical_address + + smbios_cru64_ptr->double_offset; + cru_rom_addr = ioremap(cru_physical_address, + smbios_cru64_ptr->double_length); + } + } +} + +/* + * dmi_table + * + * Routine Description: + * Decode the SMBIOS/DMI table and check if we have a 64bit CRU record + * or not. + * + * We have to be cautious here. We have seen BIOSes with DMI pointers + * pointing to completely the wrong place for example + */ +static void __devinit dmi_table(u8 *buf, int len, int num, + void (*decode)(const struct dmi_header *)) +{ + u8 *data = buf; + int i = 0; + + /* + * Stop when we see all the items the table claimed to have + * OR we run off the end of the table (also happens) + */ + while ((i < num) && (data - buf + sizeof(struct dmi_header)) <= len) { + const struct dmi_header *dm = (const struct dmi_header *)data; + + /* + * We want to know the total length (formated area and strings) + * before decoding to make sure we won't run off the table in + * dmi_decode or dmi_string + */ + data += dm->length; + while ((data - buf < len - 1) && (data[0] || data[1])) + data++; + if (data - buf < len - 1) + decode(dm); + data += 2; + i++; + } +} + +/* + * smbios_present + * + * Routine Description: + * This function parses the SMBIOS entry point table to retrieve + * the 64 bit CRU Service. + * + * Return Value: + * 0 : SUCCESS + * <0 : FAILURE + */ +static int __devinit smbios_present(const char __iomem *p) +{ + struct smbios_entry_point *eps = + (struct smbios_entry_point *) p; + int length; + u8 *buf; + + /* check if we have indeed the SMBIOS table entry point */ + if ((strncmp((char *)eps->anchor, "_SM_", + sizeof(eps->anchor))) == 0) { + length = eps->length; + + /* SMBIOS v2.1 implementation might use 0x1e */ + if ((length == 0x1e) && + (eps->major_ver == 2) && + (eps->minor_ver == 1)) + length = 0x1f; + + /* + * Now we will check: + * - SMBIOS checksum must be 0 + * - intermediate anchor should be _DMI_ + * - intermediate checksum should be 0 + */ + if ((bios_checksum(p, length)) && + (strncmp((char *)eps->intermediate_anchor, "_DMI_", + sizeof(eps->intermediate_anchor)) == 0) && + (bios_checksum(p+0x10, 15))) { + buf = ioremap(eps->table_address, eps->table_length); + if (buf == NULL) + return -ENODEV; + + + /* Scan the DMI table for the 64 bit CRU service */ + dmi_table(buf, eps->table_length, + eps->table_num_structs, dmi_find_cru); + + iounmap(buf); + return 0; + } + } + + return -ENODEV; +} + +static int __devinit smbios_scan_machine(void) +{ + char __iomem *p, *q; + int rc; + + if (efi_enabled) { + if (efi.smbios == EFI_INVALID_TABLE_ADDR) + return -ENODEV; + + p = ioremap(efi.smbios, 32); + if (p == NULL) + return -ENOMEM; + + rc = smbios_present(p); + iounmap(p); + } else { + /* + * Search from 0x0f0000 through 0x0fffff, inclusive. + */ + p = ioremap(PCI_ROM_BASE1, ROM_SIZE); + if (p == NULL) + return -ENOMEM; + + for (q = p; q < p + ROM_SIZE; q += 16) { + rc = smbios_present(q); + if (!rc) { + break; + } + } + iounmap(p); + } +} + +static int __devinit detect_cru_service(void) +{ + cru_rom_addr = NULL; + + smbios_scan_machine(); /* will become dmi_walk(dmi_find_cru); */ + + /* if cru_rom_addr has been set then we found a CRU service */ + return ((cru_rom_addr != NULL)? 0: -ENODEV); +} + +/* ------------------------------------------------------------------------- */ + +#endif + +/* + * NMI Handler + */ +static int hpwdt_pretimeout(struct notifier_block *nb, unsigned long ulReason, + void *data) +{ + static unsigned long rom_pl; + static int die_nmi_called; + + if (ulReason != DIE_NMI && ulReason != DIE_NMI_IPI) + return NOTIFY_OK; + + spin_lock_irqsave(&rom_lock, rom_pl); + if (!die_nmi_called) + asminline_call(&cmn_regs, cru_rom_addr); + die_nmi_called = 1; + spin_unlock_irqrestore(&rom_lock, rom_pl); + if (cmn_regs.u1.ral == 0) { + printk(KERN_WARNING "hpwdt: An NMI occurred, " + "but unable to determine source.\n"); + } else { + panic("An NMI occurred, please see the Integrated " + "Management Log for details.\n"); + } + + return NOTIFY_STOP; +} + +/* + * Watchdog operations + */ +static void hpwdt_start(void) +{ + reload = (soft_margin * 1000) / 128; + iowrite16(reload, hpwdt_timer_reg); + iowrite16(0x85, hpwdt_timer_con); +} + +static void hpwdt_stop(void) +{ + unsigned long data; + + data = ioread16(hpwdt_timer_con); + data &= 0xFE; + iowrite16(data, hpwdt_timer_con); +} + +static void hpwdt_ping(void) +{ + iowrite16(reload, hpwdt_timer_reg); +} + +static int hpwdt_change_timer(int new_margin) +{ + /* Arbitrary, can't find the card's limits */ + if (new_margin < 30 || new_margin > 600) { + printk(KERN_WARNING + "hpwdt: New value passed in is invalid: %d seconds.\n", + new_margin); + return -EINVAL; + } + + soft_margin = new_margin; + printk(KERN_DEBUG + "hpwdt: New timer passed in is %d seconds.\n", + new_margin); + reload = (soft_margin * 1000) / 128; + + return 0; +} + +/* + * /dev/watchdog handling + */ +static int hpwdt_open(struct inode *inode, struct file *file) +{ + /* /dev/watchdog can only be opened once */ + if (test_and_set_bit(0, &hpwdt_is_open)) + return -EBUSY; + + /* Start the watchdog */ + hpwdt_start(); + hpwdt_ping(); + + return nonseekable_open(inode, file); +} + +static int hpwdt_release(struct inode *inode, struct file *file) +{ + /* Stop the watchdog */ + if (expect_release == 42) { + hpwdt_stop(); + } else { + printk(KERN_CRIT + "hpwdt: Unexpected close, not stopping watchdog!\n"); + hpwdt_ping(); + } + + expect_release = 0; + + /* /dev/watchdog is being closed, make sure it can be re-opened */ + clear_bit(0, &hpwdt_is_open); + + return 0; +} + +static ssize_t hpwdt_write(struct file *file, const char __user *data, + size_t len, loff_t *ppos) +{ + /* See if we got the magic character 'V' and reload the timer */ + if (len) { + if (!nowayout) { + size_t i; + + /* note: just in case someone wrote the magic character + * five months ago... */ + expect_release = 0; + + /* scan to see whether or not we got the magic char. */ + for (i = 0; i != len; i++) { + char c; + if (get_user(c, data+i)) + return -EFAULT; + if (c == 'V') + expect_release = 42; + } + } + + /* someone wrote to us, we should reload the timer */ + hpwdt_ping(); + } + + return len; +} + +static struct watchdog_info ident = { + .options = WDIOF_SETTIMEOUT | + WDIOF_KEEPALIVEPING | + WDIOF_MAGICCLOSE, + .identity = "HP iLO2 HW Watchdog Timer", +}; + +static long hpwdt_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + void __user *argp = (void __user *)arg; + int __user *p = argp; + int new_margin; + int ret = -ENOTTY; + + switch (cmd) { + case WDIOC_GETSUPPORT: + ret = 0; + if (copy_to_user(argp, &ident, sizeof(ident))) + ret = -EFAULT; + break; + + case WDIOC_GETSTATUS: + case WDIOC_GETBOOTSTATUS: + ret = put_user(0, p); + break; + + case WDIOC_KEEPALIVE: + hpwdt_ping(); + ret = 0; + break; + + case WDIOC_SETTIMEOUT: + ret = get_user(new_margin, p); + if (ret) + break; + + ret = hpwdt_change_timer(new_margin); + if (ret) + break; + + hpwdt_ping(); + /* Fall */ + case WDIOC_GETTIMEOUT: + ret = put_user(soft_margin, p); + break; + } + return ret; +} + +/* + * Kernel interfaces + */ +static struct file_operations hpwdt_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .write = hpwdt_write, + .unlocked_ioctl = hpwdt_ioctl, + .open = hpwdt_open, + .release = hpwdt_release, +}; + +static struct miscdevice hpwdt_miscdev = { + .minor = WATCHDOG_MINOR, + .name = "watchdog", + .fops = &hpwdt_fops, +}; + +static struct notifier_block die_notifier = { + .notifier_call = hpwdt_pretimeout, + .priority = 0x7FFFFFFF, +}; + +/* + * Init & Exit + */ + +static int __devinit hpwdt_init_one(struct pci_dev *dev, + const struct pci_device_id *ent) +{ + int retval; + + /* + * First let's find out if we are on an iLO2 server. We will + * not run on a legacy ASM box. + */ + if (dev->subsystem_vendor != PCI_VENDOR_ID_HP) { + dev_warn(&dev->dev, + "This server does not have an iLO2 ASIC.\n"); + return -ENODEV; + } + + if (pci_enable_device(dev)) { + dev_warn(&dev->dev, + "Not possible to enable PCI Device: 0x%x:0x%x.\n", + ent->vendor, ent->device); + return -ENODEV; + } + + pci_mem_addr = pci_iomap(dev, 1, 0x80); + if (!pci_mem_addr) { + dev_warn(&dev->dev, + "Unable to detect the iLO2 server memory.\n"); + retval = -ENOMEM; + goto error_pci_iomap; + } + hpwdt_timer_reg = pci_mem_addr + 0x70; + hpwdt_timer_con = pci_mem_addr + 0x72; + + /* Make sure that we have a valid soft_margin */ + if (hpwdt_change_timer(soft_margin)) + hpwdt_change_timer(DEFAULT_MARGIN); + + /* + * We need to map the ROM to get the CRU service. + * For 32 bit Operating Systems we need to go through the 32 Bit + * BIOS Service Directory + * For 64 bit Operating Systems we get that service through SMBIOS. + */ + retval = detect_cru_service(); + if (retval < 0) { + dev_warn(&dev->dev, + "Unable to detect the %d Bit CRU Service.\n", + HPWDT_ARCH); + goto error_get_cru; + } + + /* + * We know this is the only CRU call we need to make so lets keep as + * few instructions as possible once the NMI comes in. + */ + cmn_regs.u1.rah = 0x0D; + cmn_regs.u1.ral = 0x02; + + retval = register_die_notifier(&die_notifier); + if (retval != 0) { + dev_warn(&dev->dev, + "Unable to register a die notifier (err=%d).\n", + retval); + goto error_die_notifier; + } + + retval = misc_register(&hpwdt_miscdev); + if (retval < 0) { + dev_warn(&dev->dev, + "Unable to register miscdev on minor=%d (err=%d).\n", + WATCHDOG_MINOR, retval); + goto error_misc_register; + } + + printk(KERN_INFO + "hp Watchdog Timer Driver: 1.00" + ", timer margin: %d seconds( nowayout=%d).\n", + soft_margin, nowayout); + + return 0; + +error_misc_register: + unregister_die_notifier(&die_notifier); +error_die_notifier: + if (cru_rom_addr) + iounmap(cru_rom_addr); +error_get_cru: + pci_iounmap(dev, pci_mem_addr); +error_pci_iomap: + pci_disable_device(dev); + return retval; +} + +static void __devexit hpwdt_exit(struct pci_dev *dev) +{ + if (!nowayout) + hpwdt_stop(); + + misc_deregister(&hpwdt_miscdev); + unregister_die_notifier(&die_notifier); + + if (cru_rom_addr) + iounmap(cru_rom_addr); + pci_iounmap(dev, pci_mem_addr); + pci_disable_device(dev); +} + +static struct pci_driver hpwdt_driver = { + .name = "hpwdt", + .id_table = hpwdt_devices, + .probe = hpwdt_init_one, + .remove = __devexit_p(hpwdt_exit), +}; + +static void __exit hpwdt_cleanup(void) +{ + pci_unregister_driver(&hpwdt_driver); +} + +static int __init hpwdt_init(void) +{ + return pci_register_driver(&hpwdt_driver); +} + +MODULE_AUTHOR("Tom Mingarelli"); +MODULE_DESCRIPTION("hp watchdog driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); + +module_param(soft_margin, int, 0); +MODULE_PARM_DESC(soft_margin, "Watchdog timeout in seconds"); + +module_param(nowayout, int, 0); +MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" + __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); + +module_init(hpwdt_init); +module_exit(hpwdt_cleanup); diff --git a/drivers/watchdog/mtx-1_wdt.c b/drivers/watchdog/mtx-1_wdt.c index 98451747d3cd..789831b3fa00 100644 --- a/drivers/watchdog/mtx-1_wdt.c +++ b/drivers/watchdog/mtx-1_wdt.c @@ -45,10 +45,13 @@ #include #include #include +#include + #include #include #include +#include #define MTX1_WDT_INTERVAL (5 * HZ) @@ -61,6 +64,7 @@ static struct { volatile int queue; int default_ticks; unsigned long inuse; + unsigned gpio; } mtx1_wdt_device; static void mtx1_wdt_trigger(unsigned long unused) @@ -73,7 +77,8 @@ static void mtx1_wdt_trigger(unsigned long unused) * toggle GPIO2_15 */ tmp = au_readl(GPIO2_DIR); - tmp = (tmp & ~(1<<15)) | ((~tmp) & (1<<15)); + tmp = (tmp & ~(1 << mtx1_wdt_device.gpio)) | + ((~tmp) & (1 << mtx1_wdt_device.gpio)); au_writel (tmp, GPIO2_DIR); if (mtx1_wdt_device.queue && ticks) @@ -93,7 +98,7 @@ static void mtx1_wdt_start(void) { if (!mtx1_wdt_device.queue) { mtx1_wdt_device.queue = 1; - au_writel (au_readl(GPIO2_DIR) | (u32)(1<<15), GPIO2_DIR); + gpio_set_value(mtx1_wdt_device.gpio, 1); mod_timer(&mtx1_wdt_device.timer, jiffies + MTX1_WDT_INTERVAL); } mtx1_wdt_device.running++; @@ -103,7 +108,7 @@ static int mtx1_wdt_stop(void) { if (mtx1_wdt_device.queue) { mtx1_wdt_device.queue = 0; - au_writel (au_readl(GPIO2_DIR) & ~((u32)(1<<15)), GPIO2_DIR); + gpio_set_value(mtx1_wdt_device.gpio, 0); } ticks = mtx1_wdt_device.default_ticks; @@ -197,10 +202,12 @@ static struct miscdevice mtx1_wdt_misc = { }; -static int __init mtx1_wdt_init(void) +static int mtx1_wdt_probe(struct platform_device *pdev) { int ret; + mtx1_wdt_device.gpio = pdev->resource[0].start; + if ((ret = misc_register(&mtx1_wdt_misc)) < 0) { printk(KERN_ERR " mtx-1_wdt : failed to register\n"); return ret; @@ -222,13 +229,30 @@ static int __init mtx1_wdt_init(void) return 0; } -static void __exit mtx1_wdt_exit(void) +static int mtx1_wdt_remove(struct platform_device *pdev) { if (mtx1_wdt_device.queue) { mtx1_wdt_device.queue = 0; wait_for_completion(&mtx1_wdt_device.stop); } misc_deregister(&mtx1_wdt_misc); + return 0; +} + +static struct platform_driver mtx1_wdt = { + .probe = mtx1_wdt_probe, + .remove = mtx1_wdt_remove, + .driver.name = "mtx1-wdt", +}; + +static int __init mtx1_wdt_init(void) +{ + return platform_driver_register(&mtx1_wdt); +} + +static void __exit mtx1_wdt_exit(void) +{ + platform_driver_unregister(&mtx1_wdt); } module_init(mtx1_wdt_init); @@ -237,3 +261,4 @@ module_exit(mtx1_wdt_exit); MODULE_AUTHOR("Michael Stickel, Florian Fainelli"); MODULE_DESCRIPTION("Driver for the MTX-1 watchdog"); MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); diff --git a/drivers/watchdog/sb_wdog.c b/drivers/watchdog/sb_wdog.c new file mode 100644 index 000000000000..b94431433695 --- /dev/null +++ b/drivers/watchdog/sb_wdog.c @@ -0,0 +1,353 @@ +/* + * Watchdog driver for SiByte SB1 SoCs + * + * Copyright (C) 2007 OnStor, Inc. * Andrew Sharp + * + * This driver is intended to make the second of two hardware watchdogs + * on the Sibyte 12XX and 11XX SoCs available to the user. There are two + * such devices available on the SoC, but it seems that there isn't an + * enumeration class for watchdogs in Linux like there is for RTCs. + * The second is used rather than the first because it uses IRQ 1, + * thereby avoiding all that IRQ 0 problematic nonsense. + * + * I have not tried this driver on a 1480 processor; it might work + * just well enough to really screw things up. + * + * It is a simple timer, and there is an interrupt that is raised the + * first time the timer expires. The second time it expires, the chip + * is reset and there is no way to redirect that NMI. Which could + * be problematic in some cases where this chip is sitting on the HT + * bus and has just taken responsibility for providing a cache block. + * Since the reset can't be redirected to the external reset pin, it is + * possible that other HT connected processors might hang and not reset. + * For Linux, a soft reset would probably be even worse than a hard reset. + * There you have it. + * + * The timer takes 23 bits of a 64 bit register (?) as a count value, + * and decrements the count every microsecond, for a max value of + * 0x7fffff usec or about 8.3ish seconds. + * + * This watchdog borrows some user semantics from the softdog driver, + * in that if you close the fd, it leaves the watchdog running, unless + * you previously wrote a 'V' to the fd, in which case it disables + * the watchdog when you close the fd like some other drivers. + * + * Based on various other watchdog drivers, which are probably all + * loosely based on something Alan Cox wrote years ago. + * + * (c) Copyright 1996 Alan Cox , All Rights Reserved. + * http://www.redhat.com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 1 or 2 as published by the Free Software Foundation. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + + +/* + * set the initial count value of a timer + * + * wdog is the iomem address of the cfg register + */ +void sbwdog_set(char __iomem *wdog, unsigned long t) +{ + __raw_writeb(0, wdog - 0x10); + __raw_writeq(t & 0x7fffffUL, wdog); +} + +/* + * cause the timer to [re]load it's initial count and start counting + * all over again + * + * wdog is the iomem address of the cfg register + */ +void sbwdog_pet(char __iomem *wdog) +{ + __raw_writeb(__raw_readb(wdog) | 1, wdog); +} + +static unsigned long sbwdog_gate; /* keeps it to one thread only */ +static char __iomem *kern_dog = (char __iomem *)(IO_BASE + (A_SCD_WDOG_CFG_0)); +static char __iomem *user_dog = (char __iomem *)(IO_BASE + (A_SCD_WDOG_CFG_1)); +static unsigned long timeout = 0x7fffffUL; /* useconds: 8.3ish secs. */ +static int expect_close; + +static struct watchdog_info ident = { + .options = WDIOF_CARDRESET | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, + .identity = "SiByte Watchdog", +}; + +/* + * Allow only a single thread to walk the dog + */ +static int sbwdog_open(struct inode *inode, struct file *file) +{ + nonseekable_open(inode, file); + if (test_and_set_bit(0, &sbwdog_gate)) { + return -EBUSY; + } + __module_get(THIS_MODULE); + + /* + * Activate the timer + */ + sbwdog_set(user_dog, timeout); + __raw_writeb(1, user_dog); + + return 0; +} + +/* + * Put the dog back in the kennel. + */ +static int sbwdog_release(struct inode *inode, struct file *file) +{ + if (expect_close == 42) { + __raw_writeb(0, user_dog); + module_put(THIS_MODULE); + } else { + printk(KERN_CRIT "%s: Unexpected close, not stopping watchdog!\n", + ident.identity); + sbwdog_pet(user_dog); + } + clear_bit(0, &sbwdog_gate); + expect_close = 0; + + return 0; +} + +/* + * 42 - the answer + */ +static ssize_t sbwdog_write(struct file *file, const char __user *data, + size_t len, loff_t *ppos) +{ + int i; + + if (len) { + /* + * restart the timer + */ + expect_close = 0; + + for (i = 0; i != len; i++) { + char c; + + if (get_user(c, data + i)) { + return -EFAULT; + } + if (c == 'V') { + expect_close = 42; + } + } + sbwdog_pet(user_dog); + } + + return len; +} + +static int sbwdog_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + int ret = -ENOTTY; + unsigned long time; + void __user *argp = (void __user *)arg; + int __user *p = argp; + + switch (cmd) { + case WDIOC_GETSUPPORT: + ret = copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; + break; + + case WDIOC_GETSTATUS: + case WDIOC_GETBOOTSTATUS: + ret = put_user(0, p); + break; + + case WDIOC_SETTIMEOUT: + ret = get_user(time, p); + if (ret) { + break; + } + + time *= 1000000; + if (time > 0x7fffffUL) { + ret = -EINVAL; + break; + } + timeout = time; + sbwdog_set(user_dog, timeout); + sbwdog_pet(user_dog); + + case WDIOC_GETTIMEOUT: + /* + * get the remaining count from the ... count register + * which is 1*8 before the config register + */ + ret = put_user(__raw_readq(user_dog - 8) / 1000000, p); + break; + + case WDIOC_KEEPALIVE: + sbwdog_pet(user_dog); + ret = 0; + break; + } + return ret; +} + +/* + * Notifier for system down + */ +static int +sbwdog_notify_sys(struct notifier_block *this, unsigned long code, void *erf) +{ + if (code == SYS_DOWN || code == SYS_HALT) { + /* + * sit and sit + */ + __raw_writeb(0, user_dog); + __raw_writeb(0, kern_dog); + } + + return NOTIFY_DONE; +} + +static const struct file_operations sbwdog_fops = +{ + .owner = THIS_MODULE, + .llseek = no_llseek, + .write = sbwdog_write, + .ioctl = sbwdog_ioctl, + .open = sbwdog_open, + .release = sbwdog_release, +}; + +static struct miscdevice sbwdog_miscdev = +{ + .minor = WATCHDOG_MINOR, + .name = "watchdog", + .fops = &sbwdog_fops, +}; + +static struct notifier_block sbwdog_notifier = { + .notifier_call = sbwdog_notify_sys, +}; + +/* + * interrupt handler + * + * doesn't do a whole lot for user, but oh so cleverly written so kernel + * code can use it to re-up the watchdog, thereby saving the kernel from + * having to create and maintain a timer, just to tickle another timer, + * which is just so wrong. + */ +irqreturn_t sbwdog_interrupt(int irq, void *addr) +{ + unsigned long wd_init; + char *wd_cfg_reg = (char *)addr; + u8 cfg; + + cfg = __raw_readb(wd_cfg_reg); + wd_init = __raw_readq(wd_cfg_reg - 8) & 0x7fffff; + + /* + * if it's the second watchdog timer, it's for those users + */ + if (wd_cfg_reg == user_dog) { + printk(KERN_CRIT + "%s in danger of initiating system reset in %ld.%01ld seconds\n", + ident.identity, wd_init / 1000000, (wd_init / 100000) % 10); + } else { + cfg |= 1; + } + + __raw_writeb(cfg, wd_cfg_reg); + + return IRQ_HANDLED; +} + +static int __init sbwdog_init(void) +{ + int ret; + + /* + * register a reboot notifier + */ + ret = register_reboot_notifier(&sbwdog_notifier); + if (ret) { + printk (KERN_ERR "%s: cannot register reboot notifier (err=%d)\n", + ident.identity, ret); + return ret; + } + + /* + * get the resources + */ + ret = misc_register(&sbwdog_miscdev); + if (ret == 0) { + printk(KERN_INFO "%s: timeout is %ld.%ld secs\n", ident.identity, + timeout / 1000000, (timeout / 100000) % 10); + } + + ret = request_irq(1, sbwdog_interrupt, IRQF_DISABLED | IRQF_SHARED, + ident.identity, (void *)user_dog); + if (ret) { + printk(KERN_ERR "%s: failed to request irq 1 - %d\n", ident.identity, + ret); + misc_deregister(&sbwdog_miscdev); + } + + return ret; +} + +static void __exit sbwdog_exit(void) +{ + misc_deregister(&sbwdog_miscdev); +} + +module_init(sbwdog_init); +module_exit(sbwdog_exit); + +MODULE_AUTHOR("Andrew Sharp "); +MODULE_DESCRIPTION("SiByte Watchdog"); + +module_param(timeout, ulong, 0); +MODULE_PARM_DESC(timeout, + "Watchdog timeout in microseconds (max/default 8388607 or 8.3ish secs)"); + +MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); + +/* + * example code that can be put in a platform code area to utilize the + * first watchdog timer for the kernels own purpose. + + void +platform_wd_setup(void) +{ + int ret; + + ret = request_irq(0, sbwdog_interrupt, IRQF_DISABLED | IRQF_SHARED, + "Kernel Watchdog", IOADDR(A_SCD_WDOG_CFG_0)); + if (ret) { + printk(KERN_CRIT "Watchdog IRQ zero(0) failed to be requested - %d\n", + ret); + } +} + + + */ diff --git a/fs/afs/mntpt.c b/fs/afs/mntpt.c index 5ce43b63c60e..a3510b8ba3e7 100644 --- a/fs/afs/mntpt.c +++ b/fs/afs/mntpt.c @@ -218,16 +218,16 @@ static void *afs_mntpt_follow_link(struct dentry *dentry, struct nameidata *nd) _enter("%p{%s},{%s:%p{%s},}", dentry, dentry->d_name.name, - nd->mnt->mnt_devname, + nd->path.mnt->mnt_devname, dentry, - nd->dentry->d_name.name); + nd->path.dentry->d_name.name); - dput(nd->dentry); - nd->dentry = dget(dentry); + dput(nd->path.dentry); + nd->path.dentry = dget(dentry); - newmnt = afs_mntpt_do_automount(nd->dentry); + newmnt = afs_mntpt_do_automount(nd->path.dentry); if (IS_ERR(newmnt)) { - path_release(nd); + path_put(&nd->path); return (void *)newmnt; } @@ -235,17 +235,16 @@ static void *afs_mntpt_follow_link(struct dentry *dentry, struct nameidata *nd) err = do_add_mount(newmnt, nd, MNT_SHRINKABLE, &afs_vfsmounts); switch (err) { case 0: - dput(nd->dentry); - mntput(nd->mnt); - nd->mnt = newmnt; - nd->dentry = dget(newmnt->mnt_root); + path_put(&nd->path); + nd->path.mnt = newmnt; + nd->path.dentry = dget(newmnt->mnt_root); schedule_delayed_work(&afs_mntpt_expiry_timer, afs_mntpt_expiry_timeout * HZ); break; case -EBUSY: /* someone else made a mount here whilst we were busy */ - while (d_mountpoint(nd->dentry) && - follow_down(&nd->mnt, &nd->dentry)) + while (d_mountpoint(nd->path.dentry) && + follow_down(&nd->path.mnt, &nd->path.dentry)) ; err = 0; default: diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c index 2bbcc8151dc3..a54a946a50ae 100644 --- a/fs/autofs4/root.c +++ b/fs/autofs4/root.c @@ -368,7 +368,8 @@ static void *autofs4_follow_link(struct dentry *dentry, struct nameidata *nd) * so we don't need to follow the mount. */ if (d_mountpoint(dentry)) { - if (!autofs4_follow_mount(&nd->mnt, &nd->dentry)) { + if (!autofs4_follow_mount(&nd->path.mnt, + &nd->path.dentry)) { status = -ENOENT; goto out_error; } @@ -382,7 +383,7 @@ done: return NULL; out_error: - path_release(nd); + path_put(&nd->path); return ERR_PTR(status); } diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c index d8a02f1e08cc..0498b181dd52 100644 --- a/fs/binfmt_flat.c +++ b/fs/binfmt_flat.c @@ -443,12 +443,12 @@ static int load_flat_file(struct linux_binprm * bprm, if (strncmp(hdr->magic, "bFLT", 4)) { /* + * Previously, here was a printk to tell people + * "BINFMT_FLAT: bad header magic". + * But for the kernel which also use ELF FD-PIC format, this + * error message is confusing. * because a lot of people do not manage to produce good - * flat binaries, we leave this printk to help them realise - * the problem. We only print the error if its not a script file */ - if (strncmp(hdr->magic, "#!", 2)) - printk("BINFMT_FLAT: bad header magic\n"); ret = -ENOEXEC; goto err; } diff --git a/fs/bio.c b/fs/bio.c index 242e409dab4b..3312fcc3c098 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -903,7 +903,7 @@ void bio_set_pages_dirty(struct bio *bio) } } -void bio_release_pages(struct bio *bio) +static void bio_release_pages(struct bio *bio) { struct bio_vec *bvec = bio->bi_io_vec; int i; diff --git a/fs/block_dev.c b/fs/block_dev.c index e63067d25cdb..7d822fae7765 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -31,6 +31,8 @@ struct bdev_inode { struct inode vfs_inode; }; +static const struct address_space_operations def_blk_aops; + static inline struct bdev_inode *BDEV_I(struct inode *inode) { return container_of(inode, struct bdev_inode, vfs_inode); @@ -171,203 +173,6 @@ blkdev_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, iov, offset, nr_segs, blkdev_get_blocks, NULL); } -#if 0 -static void blk_end_aio(struct bio *bio, int error) -{ - struct kiocb *iocb = bio->bi_private; - atomic_t *bio_count = &iocb->ki_bio_count; - - if (bio_data_dir(bio) == READ) - bio_check_pages_dirty(bio); - else { - bio_release_pages(bio); - bio_put(bio); - } - - /* iocb->ki_nbytes stores error code from LLDD */ - if (error) - iocb->ki_nbytes = -EIO; - - if (atomic_dec_and_test(bio_count)) { - if ((long)iocb->ki_nbytes < 0) - aio_complete(iocb, iocb->ki_nbytes, 0); - else - aio_complete(iocb, iocb->ki_left, 0); - } - - return 0; -} - -#define VEC_SIZE 16 -struct pvec { - unsigned short nr; - unsigned short idx; - struct page *page[VEC_SIZE]; -}; - -#define PAGES_SPANNED(addr, len) \ - (DIV_ROUND_UP((addr) + (len), PAGE_SIZE) - (addr) / PAGE_SIZE); - -/* - * get page pointer for user addr, we internally cache struct page array for - * (addr, count) range in pvec to avoid frequent call to get_user_pages. If - * internal page list is exhausted, a batch count of up to VEC_SIZE is used - * to get next set of page struct. - */ -static struct page *blk_get_page(unsigned long addr, size_t count, int rw, - struct pvec *pvec) -{ - int ret, nr_pages; - if (pvec->idx == pvec->nr) { - nr_pages = PAGES_SPANNED(addr, count); - nr_pages = min(nr_pages, VEC_SIZE); - down_read(¤t->mm->mmap_sem); - ret = get_user_pages(current, current->mm, addr, nr_pages, - rw == READ, 0, pvec->page, NULL); - up_read(¤t->mm->mmap_sem); - if (ret < 0) - return ERR_PTR(ret); - pvec->nr = ret; - pvec->idx = 0; - } - return pvec->page[pvec->idx++]; -} - -/* return a page back to pvec array */ -static void blk_unget_page(struct page *page, struct pvec *pvec) -{ - pvec->page[--pvec->idx] = page; -} - -static ssize_t -blkdev_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, - loff_t pos, unsigned long nr_segs) -{ - struct inode *inode = iocb->ki_filp->f_mapping->host; - unsigned blkbits = blksize_bits(bdev_hardsect_size(I_BDEV(inode))); - unsigned blocksize_mask = (1 << blkbits) - 1; - unsigned long seg = 0; /* iov segment iterator */ - unsigned long nvec; /* number of bio vec needed */ - unsigned long cur_off; /* offset into current page */ - unsigned long cur_len; /* I/O len of current page, up to PAGE_SIZE */ - - unsigned long addr; /* user iovec address */ - size_t count; /* user iovec len */ - size_t nbytes = iocb->ki_nbytes = iocb->ki_left; /* total xfer size */ - loff_t size; /* size of block device */ - struct bio *bio; - atomic_t *bio_count = &iocb->ki_bio_count; - struct page *page; - struct pvec pvec; - - pvec.nr = 0; - pvec.idx = 0; - - if (pos & blocksize_mask) - return -EINVAL; - - size = i_size_read(inode); - if (pos + nbytes > size) { - nbytes = size - pos; - iocb->ki_left = nbytes; - } - - /* - * check first non-zero iov alignment, the remaining - * iov alignment is checked inside bio loop below. - */ - do { - addr = (unsigned long) iov[seg].iov_base; - count = min(iov[seg].iov_len, nbytes); - if (addr & blocksize_mask || count & blocksize_mask) - return -EINVAL; - } while (!count && ++seg < nr_segs); - atomic_set(bio_count, 1); - - while (nbytes) { - /* roughly estimate number of bio vec needed */ - nvec = (nbytes + PAGE_SIZE - 1) / PAGE_SIZE; - nvec = max(nvec, nr_segs - seg); - nvec = min(nvec, (unsigned long) BIO_MAX_PAGES); - - /* bio_alloc should not fail with GFP_KERNEL flag */ - bio = bio_alloc(GFP_KERNEL, nvec); - bio->bi_bdev = I_BDEV(inode); - bio->bi_end_io = blk_end_aio; - bio->bi_private = iocb; - bio->bi_sector = pos >> blkbits; -same_bio: - cur_off = addr & ~PAGE_MASK; - cur_len = PAGE_SIZE - cur_off; - if (count < cur_len) - cur_len = count; - - page = blk_get_page(addr, count, rw, &pvec); - if (unlikely(IS_ERR(page))) - goto backout; - - if (bio_add_page(bio, page, cur_len, cur_off)) { - pos += cur_len; - addr += cur_len; - count -= cur_len; - nbytes -= cur_len; - - if (count) - goto same_bio; - while (++seg < nr_segs) { - addr = (unsigned long) iov[seg].iov_base; - count = iov[seg].iov_len; - if (!count) - continue; - if (unlikely(addr & blocksize_mask || - count & blocksize_mask)) { - page = ERR_PTR(-EINVAL); - goto backout; - } - count = min(count, nbytes); - goto same_bio; - } - } else { - blk_unget_page(page, &pvec); - } - - /* bio is ready, submit it */ - if (rw == READ) - bio_set_pages_dirty(bio); - atomic_inc(bio_count); - submit_bio(rw, bio); - } - -completion: - iocb->ki_left -= nbytes; - nbytes = iocb->ki_left; - iocb->ki_pos += nbytes; - - blk_run_address_space(inode->i_mapping); - if (atomic_dec_and_test(bio_count)) - aio_complete(iocb, nbytes, 0); - - return -EIOCBQUEUED; - -backout: - /* - * back out nbytes count constructed so far for this bio, - * we will throw away current bio. - */ - nbytes += bio->bi_size; - bio_release_pages(bio); - bio_put(bio); - - /* - * if no bio was submmitted, return the error code. - * otherwise, proceed with pending I/O completion. - */ - if (atomic_read(bio_count) == 1) - return PTR_ERR(page); - goto completion; -} -#endif - static int blkdev_writepage(struct page *page, struct writeback_control *wbc) { return block_write_full_page(page, blkdev_get_block, wbc); @@ -1334,7 +1139,7 @@ static long block_ioctl(struct file *file, unsigned cmd, unsigned long arg) return blkdev_ioctl(file->f_mapping->host, file, cmd, arg); } -const struct address_space_operations def_blk_aops = { +static const struct address_space_operations def_blk_aops = { .readpage = blkdev_readpage, .writepage = blkdev_writepage, .sync_page = block_sync_page, @@ -1397,19 +1202,19 @@ struct block_device *lookup_bdev(const char *path) if (error) return ERR_PTR(error); - inode = nd.dentry->d_inode; + inode = nd.path.dentry->d_inode; error = -ENOTBLK; if (!S_ISBLK(inode->i_mode)) goto fail; error = -EACCES; - if (nd.mnt->mnt_flags & MNT_NODEV) + if (nd.path.mnt->mnt_flags & MNT_NODEV) goto fail; error = -ENOMEM; bdev = bd_acquire(inode); if (!bdev) goto fail; out: - path_release(&nd); + path_put(&nd.path); return bdev; fail: bdev = ERR_PTR(error); diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c index 413ee2349d1a..6ad447529961 100644 --- a/fs/cifs/cifs_dfs_ref.c +++ b/fs/cifs/cifs_dfs_ref.c @@ -259,18 +259,18 @@ static int add_mount_helper(struct vfsmount *newmnt, struct nameidata *nd, int err; mntget(newmnt); - err = do_add_mount(newmnt, nd, nd->mnt->mnt_flags, mntlist); + err = do_add_mount(newmnt, nd, nd->path.mnt->mnt_flags, mntlist); switch (err) { case 0: - dput(nd->dentry); - mntput(nd->mnt); - nd->mnt = newmnt; - nd->dentry = dget(newmnt->mnt_root); + dput(nd->path.dentry); + mntput(nd->path.mnt); + nd->path.mnt = newmnt; + nd->path.dentry = dget(newmnt->mnt_root); break; case -EBUSY: /* someone else made a mount here whilst we were busy */ - while (d_mountpoint(nd->dentry) && - follow_down(&nd->mnt, &nd->dentry)) + while (d_mountpoint(nd->path.dentry) && + follow_down(&nd->path.mnt, &nd->path.dentry)) ; err = 0; default: @@ -307,8 +307,8 @@ cifs_dfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd) xid = GetXid(); - dput(nd->dentry); - nd->dentry = dget(dentry); + dput(nd->path.dentry); + nd->path.dentry = dget(dentry); cifs_sb = CIFS_SB(dentry->d_inode->i_sb); ses = cifs_sb->tcon->ses; @@ -340,7 +340,8 @@ cifs_dfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd) rc = -EINVAL; goto out_err; } - mnt = cifs_dfs_do_refmount(nd->mnt, nd->dentry, + mnt = cifs_dfs_do_refmount(nd->path.mnt, + nd->path.dentry, referrals[i].node_name); cFYI(1, ("%s: cifs_dfs_do_refmount:%s , mnt:%p", __FUNCTION__, @@ -357,7 +358,7 @@ cifs_dfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd) if (IS_ERR(mnt)) goto out_err; - nd->mnt->mnt_flags |= MNT_SHRINKABLE; + nd->path.mnt->mnt_flags |= MNT_SHRINKABLE; rc = add_mount_helper(mnt, nd, &cifs_dfs_automount_list); out: @@ -367,7 +368,7 @@ out: cFYI(1, ("leaving %s" , __FUNCTION__)); return ERR_PTR(rc); out_err: - path_release(nd); + path_put(&nd->path); goto out; } diff --git a/fs/coda/pioctl.c b/fs/coda/pioctl.c index 2bf3026adc80..c21a1f552a63 100644 --- a/fs/coda/pioctl.c +++ b/fs/coda/pioctl.c @@ -75,12 +75,12 @@ static int coda_pioctl(struct inode * inode, struct file * filp, if ( error ) { return error; } else { - target_inode = nd.dentry->d_inode; + target_inode = nd.path.dentry->d_inode; } /* return if it is not a Coda inode */ if ( target_inode->i_sb != inode->i_sb ) { - path_release(&nd); + path_put(&nd.path); return -EINVAL; } @@ -89,7 +89,7 @@ static int coda_pioctl(struct inode * inode, struct file * filp, error = venus_pioctl(inode->i_sb, &(cnp->c_fid), cmd, &data); - path_release(&nd); + path_put(&nd.path); return error; } diff --git a/fs/compat.c b/fs/compat.c index ee80ff341d37..2ce4456aad30 100644 --- a/fs/compat.c +++ b/fs/compat.c @@ -241,10 +241,10 @@ asmlinkage long compat_sys_statfs(const char __user *path, struct compat_statfs error = user_path_walk(path, &nd); if (!error) { struct kstatfs tmp; - error = vfs_statfs(nd.dentry, &tmp); + error = vfs_statfs(nd.path.dentry, &tmp); if (!error) error = put_compat_statfs(buf, &tmp); - path_release(&nd); + path_put(&nd.path); } return error; } @@ -309,10 +309,10 @@ asmlinkage long compat_sys_statfs64(const char __user *path, compat_size_t sz, s error = user_path_walk(path, &nd); if (!error) { struct kstatfs tmp; - error = vfs_statfs(nd.dentry, &tmp); + error = vfs_statfs(nd.path.dentry, &tmp); if (!error) error = put_compat_statfs64(buf, &tmp); - path_release(&nd); + path_put(&nd.path); } return error; } @@ -702,9 +702,6 @@ static int do_nfs4_super_data_conv(void *raw_data) real->flags = raw->flags; real->version = raw->version; } - else { - return -EINVAL; - } return 0; } diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index ee32c0eac7c1..c6e72aebd16b 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -2853,7 +2853,7 @@ static void compat_ioctl_error(struct file *filp, unsigned int fd, /* find the name of the device. */ path = (char *)__get_free_page(GFP_KERNEL); if (path) { - fn = d_path(filp->f_path.dentry, filp->f_path.mnt, path, PAGE_SIZE); + fn = d_path(&filp->f_path, path, PAGE_SIZE); if (IS_ERR(fn)) fn = "?"; } diff --git a/fs/configfs/symlink.c b/fs/configfs/symlink.c index 22700d2857da..78929ea84ff2 100644 --- a/fs/configfs/symlink.c +++ b/fs/configfs/symlink.c @@ -99,11 +99,11 @@ static int get_target(const char *symname, struct nameidata *nd, ret = path_lookup(symname, LOOKUP_FOLLOW|LOOKUP_DIRECTORY, nd); if (!ret) { - if (nd->dentry->d_sb == configfs_sb) { - *target = configfs_get_config_item(nd->dentry); + if (nd->path.dentry->d_sb == configfs_sb) { + *target = configfs_get_config_item(nd->path.dentry); if (!*target) { ret = -ENOENT; - path_release(nd); + path_put(&nd->path); } } else ret = -EPERM; @@ -141,7 +141,7 @@ int configfs_symlink(struct inode *dir, struct dentry *dentry, const char *symna ret = create_link(parent_item, target_item, dentry); config_item_put(target_item); - path_release(&nd); + path_put(&nd.path); out_put: config_item_put(parent_item); diff --git a/fs/dcache.c b/fs/dcache.c index 44f6cf23b70e..43455776711e 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -95,6 +95,14 @@ static void d_free(struct dentry *dentry) call_rcu(&dentry->d_u.d_rcu, d_callback); } +static void dentry_lru_remove(struct dentry *dentry) +{ + if (!list_empty(&dentry->d_lru)) { + list_del_init(&dentry->d_lru); + dentry_stat.nr_unused--; + } +} + /* * Release the dentry's inode, using the filesystem * d_iput() operation if defined. @@ -211,13 +219,7 @@ repeat: unhash_it: __d_drop(dentry); kill_it: - /* If dentry was on d_lru list - * delete it from there - */ - if (!list_empty(&dentry->d_lru)) { - list_del(&dentry->d_lru); - dentry_stat.nr_unused--; - } + dentry_lru_remove(dentry); dentry = d_kill(dentry); if (dentry) goto repeat; @@ -285,10 +287,7 @@ int d_invalidate(struct dentry * dentry) static inline struct dentry * __dget_locked(struct dentry *dentry) { atomic_inc(&dentry->d_count); - if (!list_empty(&dentry->d_lru)) { - dentry_stat.nr_unused--; - list_del_init(&dentry->d_lru); - } + dentry_lru_remove(dentry); return dentry; } @@ -404,10 +403,7 @@ static void prune_one_dentry(struct dentry * dentry) if (dentry->d_op && dentry->d_op->d_delete) dentry->d_op->d_delete(dentry); - if (!list_empty(&dentry->d_lru)) { - list_del(&dentry->d_lru); - dentry_stat.nr_unused--; - } + dentry_lru_remove(dentry); __d_drop(dentry); dentry = d_kill(dentry); spin_lock(&dcache_lock); @@ -596,10 +592,7 @@ static void shrink_dcache_for_umount_subtree(struct dentry *dentry) /* detach this root from the system */ spin_lock(&dcache_lock); - if (!list_empty(&dentry->d_lru)) { - dentry_stat.nr_unused--; - list_del_init(&dentry->d_lru); - } + dentry_lru_remove(dentry); __d_drop(dentry); spin_unlock(&dcache_lock); @@ -613,11 +606,7 @@ static void shrink_dcache_for_umount_subtree(struct dentry *dentry) spin_lock(&dcache_lock); list_for_each_entry(loop, &dentry->d_subdirs, d_u.d_child) { - if (!list_empty(&loop->d_lru)) { - dentry_stat.nr_unused--; - list_del_init(&loop->d_lru); - } - + dentry_lru_remove(loop); __d_drop(loop); cond_resched_lock(&dcache_lock); } @@ -799,10 +788,7 @@ resume: struct dentry *dentry = list_entry(tmp, struct dentry, d_u.d_child); next = tmp->next; - if (!list_empty(&dentry->d_lru)) { - dentry_stat.nr_unused--; - list_del_init(&dentry->d_lru); - } + dentry_lru_remove(dentry); /* * move only zero ref count dentries to the end * of the unused list for prune_dcache @@ -1776,9 +1762,8 @@ shouldnt_be_hashed: * * "buflen" should be positive. Caller holds the dcache_lock. */ -static char * __d_path( struct dentry *dentry, struct vfsmount *vfsmnt, - struct dentry *root, struct vfsmount *rootmnt, - char *buffer, int buflen) +static char *__d_path(struct dentry *dentry, struct vfsmount *vfsmnt, + struct path *root, char *buffer, int buflen) { char * end = buffer+buflen; char * retval; @@ -1803,7 +1788,7 @@ static char * __d_path( struct dentry *dentry, struct vfsmount *vfsmnt, for (;;) { struct dentry * parent; - if (dentry == root && vfsmnt == rootmnt) + if (dentry == root->dentry && vfsmnt == root->mnt) break; if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) { /* Global root? */ @@ -1844,13 +1829,23 @@ Elong: return ERR_PTR(-ENAMETOOLONG); } -/* write full pathname into buffer and return start of pathname */ -char * d_path(struct dentry *dentry, struct vfsmount *vfsmnt, - char *buf, int buflen) +/** + * d_path - return the path of a dentry + * @path: path to report + * @buf: buffer to return value in + * @buflen: buffer length + * + * Convert a dentry into an ASCII path name. If the entry has been deleted + * the string " (deleted)" is appended. Note that this is ambiguous. + * + * Returns the buffer or an error code if the path was too long. + * + * "buflen" should be positive. Caller holds the dcache_lock. + */ +char *d_path(struct path *path, char *buf, int buflen) { char *res; - struct vfsmount *rootmnt; - struct dentry *root; + struct path root; /* * We have various synthetic filesystems that never get mounted. On @@ -1859,18 +1854,17 @@ char * d_path(struct dentry *dentry, struct vfsmount *vfsmnt, * user wants to identify the object in /proc/pid/fd/. The little hack * below allows us to generate a name for these objects on demand: */ - if (dentry->d_op && dentry->d_op->d_dname) - return dentry->d_op->d_dname(dentry, buf, buflen); + if (path->dentry->d_op && path->dentry->d_op->d_dname) + return path->dentry->d_op->d_dname(path->dentry, buf, buflen); read_lock(¤t->fs->lock); - rootmnt = mntget(current->fs->rootmnt); - root = dget(current->fs->root); + root = current->fs->root; + path_get(¤t->fs->root); read_unlock(¤t->fs->lock); spin_lock(&dcache_lock); - res = __d_path(dentry, vfsmnt, root, rootmnt, buf, buflen); + res = __d_path(path->dentry, path->mnt, &root, buf, buflen); spin_unlock(&dcache_lock); - dput(root); - mntput(rootmnt); + path_put(&root); return res; } @@ -1916,28 +1910,27 @@ char *dynamic_dname(struct dentry *dentry, char *buffer, int buflen, asmlinkage long sys_getcwd(char __user *buf, unsigned long size) { int error; - struct vfsmount *pwdmnt, *rootmnt; - struct dentry *pwd, *root; + struct path pwd, root; char *page = (char *) __get_free_page(GFP_USER); if (!page) return -ENOMEM; read_lock(¤t->fs->lock); - pwdmnt = mntget(current->fs->pwdmnt); - pwd = dget(current->fs->pwd); - rootmnt = mntget(current->fs->rootmnt); - root = dget(current->fs->root); + pwd = current->fs->pwd; + path_get(¤t->fs->pwd); + root = current->fs->root; + path_get(¤t->fs->root); read_unlock(¤t->fs->lock); error = -ENOENT; /* Has the current directory has been unlinked? */ spin_lock(&dcache_lock); - if (pwd->d_parent == pwd || !d_unhashed(pwd)) { + if (pwd.dentry->d_parent == pwd.dentry || !d_unhashed(pwd.dentry)) { unsigned long len; char * cwd; - cwd = __d_path(pwd, pwdmnt, root, rootmnt, page, PAGE_SIZE); + cwd = __d_path(pwd.dentry, pwd.mnt, &root, page, PAGE_SIZE); spin_unlock(&dcache_lock); error = PTR_ERR(cwd); @@ -1955,10 +1948,8 @@ asmlinkage long sys_getcwd(char __user *buf, unsigned long size) spin_unlock(&dcache_lock); out: - dput(pwd); - mntput(pwdmnt); - dput(root); - mntput(rootmnt); + path_put(&pwd); + path_put(&root); free_page((unsigned long) page); return error; } diff --git a/fs/dcookies.c b/fs/dcookies.c index 792cbf55fa95..855d4b1d619a 100644 --- a/fs/dcookies.c +++ b/fs/dcookies.c @@ -24,6 +24,7 @@ #include #include #include +#include #include /* The dcookies are allocated from a kmem_cache and @@ -31,8 +32,7 @@ * code here is particularly performance critical */ struct dcookie_struct { - struct dentry * dentry; - struct vfsmount * vfsmnt; + struct path path; struct list_head hash_list; }; @@ -51,7 +51,7 @@ static inline int is_live(void) /* The dentry is locked, its address will do for the cookie */ static inline unsigned long dcookie_value(struct dcookie_struct * dcs) { - return (unsigned long)dcs->dentry; + return (unsigned long)dcs->path.dentry; } @@ -89,19 +89,17 @@ static void hash_dcookie(struct dcookie_struct * dcs) } -static struct dcookie_struct * alloc_dcookie(struct dentry * dentry, - struct vfsmount * vfsmnt) +static struct dcookie_struct *alloc_dcookie(struct path *path) { - struct dcookie_struct * dcs = kmem_cache_alloc(dcookie_cache, GFP_KERNEL); + struct dcookie_struct *dcs = kmem_cache_alloc(dcookie_cache, + GFP_KERNEL); if (!dcs) return NULL; - dentry->d_cookie = dcs; - - dcs->dentry = dget(dentry); - dcs->vfsmnt = mntget(vfsmnt); + path->dentry->d_cookie = dcs; + dcs->path = *path; + path_get(path); hash_dcookie(dcs); - return dcs; } @@ -109,8 +107,7 @@ static struct dcookie_struct * alloc_dcookie(struct dentry * dentry, /* This is the main kernel-side routine that retrieves the cookie * value for a dentry/vfsmnt pair. */ -int get_dcookie(struct dentry * dentry, struct vfsmount * vfsmnt, - unsigned long * cookie) +int get_dcookie(struct path *path, unsigned long *cookie) { int err = 0; struct dcookie_struct * dcs; @@ -122,10 +119,10 @@ int get_dcookie(struct dentry * dentry, struct vfsmount * vfsmnt, goto out; } - dcs = dentry->d_cookie; + dcs = path->dentry->d_cookie; if (!dcs) - dcs = alloc_dcookie(dentry, vfsmnt); + dcs = alloc_dcookie(path); if (!dcs) { err = -ENOMEM; @@ -174,7 +171,7 @@ asmlinkage long sys_lookup_dcookie(u64 cookie64, char __user * buf, size_t len) goto out; /* FIXME: (deleted) ? */ - path = d_path(dcs->dentry, dcs->vfsmnt, kbuf, PAGE_SIZE); + path = d_path(&dcs->path, kbuf, PAGE_SIZE); if (IS_ERR(path)) { err = PTR_ERR(path); @@ -254,9 +251,8 @@ out_kmem: static void free_dcookie(struct dcookie_struct * dcs) { - dcs->dentry->d_cookie = NULL; - dput(dcs->dentry); - mntput(dcs->vfsmnt); + dcs->path.dentry->d_cookie = NULL; + path_put(&dcs->path); kmem_cache_free(dcookie_cache, dcs); } diff --git a/fs/dquot.c b/fs/dquot.c index def4e969df77..9c7feb62eed1 100644 --- a/fs/dquot.c +++ b/fs/dquot.c @@ -1633,16 +1633,17 @@ int vfs_quota_on(struct super_block *sb, int type, int format_id, char *path) error = path_lookup(path, LOOKUP_FOLLOW, &nd); if (error < 0) return error; - error = security_quota_on(nd.dentry); + error = security_quota_on(nd.path.dentry); if (error) goto out_path; /* Quota file not on the same filesystem? */ - if (nd.mnt->mnt_sb != sb) + if (nd.path.mnt->mnt_sb != sb) error = -EXDEV; else - error = vfs_quota_on_inode(nd.dentry->d_inode, type, format_id); + error = vfs_quota_on_inode(nd.path.dentry->d_inode, type, + format_id); out_path: - path_release(&nd); + path_put(&nd.path); return error; } diff --git a/fs/ecryptfs/dentry.c b/fs/ecryptfs/dentry.c index cb20b964419f..841a032050a7 100644 --- a/fs/ecryptfs/dentry.c +++ b/fs/ecryptfs/dentry.c @@ -51,13 +51,13 @@ static int ecryptfs_d_revalidate(struct dentry *dentry, struct nameidata *nd) if (!lower_dentry->d_op || !lower_dentry->d_op->d_revalidate) goto out; - dentry_save = nd->dentry; - vfsmount_save = nd->mnt; - nd->dentry = lower_dentry; - nd->mnt = lower_mnt; + dentry_save = nd->path.dentry; + vfsmount_save = nd->path.mnt; + nd->path.dentry = lower_dentry; + nd->path.mnt = lower_mnt; rc = lower_dentry->d_op->d_revalidate(lower_dentry, nd); - nd->dentry = dentry_save; - nd->mnt = vfsmount_save; + nd->path.dentry = dentry_save; + nd->path.mnt = vfsmount_save; if (dentry->d_inode) { struct inode *lower_inode = ecryptfs_inode_to_lower(dentry->d_inode); diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index edd1e44e9d47..e23861152101 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c @@ -77,13 +77,13 @@ ecryptfs_create_underlying_file(struct inode *lower_dir_inode, struct vfsmount *vfsmount_save; int rc; - dentry_save = nd->dentry; - vfsmount_save = nd->mnt; - nd->dentry = lower_dentry; - nd->mnt = lower_mnt; + dentry_save = nd->path.dentry; + vfsmount_save = nd->path.mnt; + nd->path.dentry = lower_dentry; + nd->path.mnt = lower_mnt; rc = vfs_create(lower_dir_inode, lower_dentry, mode, nd); - nd->dentry = dentry_save; - nd->mnt = vfsmount_save; + nd->path.dentry = dentry_save; + nd->path.mnt = vfsmount_save; return rc; } @@ -819,14 +819,14 @@ ecryptfs_permission(struct inode *inode, int mask, struct nameidata *nd) int rc; if (nd) { - struct vfsmount *vfsmnt_save = nd->mnt; - struct dentry *dentry_save = nd->dentry; + struct vfsmount *vfsmnt_save = nd->path.mnt; + struct dentry *dentry_save = nd->path.dentry; - nd->mnt = ecryptfs_dentry_to_lower_mnt(nd->dentry); - nd->dentry = ecryptfs_dentry_to_lower(nd->dentry); + nd->path.mnt = ecryptfs_dentry_to_lower_mnt(nd->path.dentry); + nd->path.dentry = ecryptfs_dentry_to_lower(nd->path.dentry); rc = permission(ecryptfs_inode_to_lower(inode), mask, nd); - nd->mnt = vfsmnt_save; - nd->dentry = dentry_save; + nd->path.mnt = vfsmnt_save; + nd->path.dentry = dentry_save; } else rc = permission(ecryptfs_inode_to_lower(inode), mask, NULL); return rc; diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c index 778c420e4cac..d25ac9500a92 100644 --- a/fs/ecryptfs/main.c +++ b/fs/ecryptfs/main.c @@ -513,8 +513,8 @@ static int ecryptfs_read_super(struct super_block *sb, const char *dev_name) ecryptfs_printk(KERN_WARNING, "path_lookup() failed\n"); goto out; } - lower_root = nd.dentry; - lower_mnt = nd.mnt; + lower_root = nd.path.dentry; + lower_mnt = nd.path.mnt; ecryptfs_set_superblock_lower(sb, lower_root->d_sb); sb->s_maxbytes = lower_root->d_sb->s_maxbytes; sb->s_blocksize = lower_root->d_sb->s_blocksize; @@ -526,7 +526,7 @@ static int ecryptfs_read_super(struct super_block *sb, const char *dev_name) rc = 0; goto out; out_free: - path_release(&nd); + path_put(&nd.path); out: return rc; } diff --git a/fs/exec.c b/fs/exec.c index 9ff6069094d8..a44b142fb460 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -112,7 +112,7 @@ asmlinkage long sys_uselib(const char __user * library) goto out; error = -EINVAL; - if (!S_ISREG(nd.dentry->d_inode->i_mode)) + if (!S_ISREG(nd.path.dentry->d_inode->i_mode)) goto exit; error = vfs_permission(&nd, MAY_READ | MAY_EXEC); @@ -148,7 +148,7 @@ out: return error; exit: release_open_intent(&nd); - path_release(&nd); + path_put(&nd.path); goto out; } @@ -652,7 +652,7 @@ struct file *open_exec(const char *name) file = ERR_PTR(err); if (!err) { - struct inode *inode = nd.dentry->d_inode; + struct inode *inode = nd.path.dentry->d_inode; file = ERR_PTR(-EACCES); if (S_ISREG(inode->i_mode)) { int err = vfs_permission(&nd, MAY_EXEC); @@ -672,7 +672,7 @@ out: } } release_open_intent(&nd); - path_release(&nd); + path_put(&nd.path); } goto out; } diff --git a/fs/ext3/super.c b/fs/ext3/super.c index 8e02cbfb1123..18769cc32377 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c @@ -2758,16 +2758,16 @@ static int ext3_quota_on(struct super_block *sb, int type, int format_id, if (err) return err; /* Quotafile not on the same filesystem? */ - if (nd.mnt->mnt_sb != sb) { - path_release(&nd); + if (nd.path.mnt->mnt_sb != sb) { + path_put(&nd.path); return -EXDEV; } /* Quotafile not of fs root? */ - if (nd.dentry->d_parent->d_inode != sb->s_root->d_inode) + if (nd.path.dentry->d_parent->d_inode != sb->s_root->d_inode) printk(KERN_WARNING "EXT3-fs: Quota file not on filesystem root. " "Journalled quota will not work.\n"); - path_release(&nd); + path_put(&nd.path); return vfs_quota_on(sb, type, format_id, path); } diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 0072da75221f..13383ba18f1d 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -3158,16 +3158,16 @@ static int ext4_quota_on(struct super_block *sb, int type, int format_id, if (err) return err; /* Quotafile not on the same filesystem? */ - if (nd.mnt->mnt_sb != sb) { - path_release(&nd); + if (nd.path.mnt->mnt_sb != sb) { + path_put(&nd.path); return -EXDEV; } /* Quotafile not of fs root? */ - if (nd.dentry->d_parent->d_inode != sb->s_root->d_inode) + if (nd.path.dentry->d_parent->d_inode != sb->s_root->d_inode) printk(KERN_WARNING "EXT4-fs: Quota file not on filesystem root. " "Journalled quota will not work.\n"); - path_release(&nd); + path_put(&nd.path); return vfs_quota_on(sb, type, format_id, path); } diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index 43d511bba52d..4bee6aa845e4 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c @@ -884,12 +884,13 @@ static struct super_block* get_gfs2_sb(const char *dev_name) dev_name); goto out; } - error = vfs_getattr(nd.mnt, nd.dentry, &stat); + error = vfs_getattr(nd.path.mnt, nd.path.dentry, &stat); fstype = get_fs_type("gfs2"); list_for_each_entry(s, &fstype->fs_supers, s_instances) { if ((S_ISBLK(stat.mode) && s->s_dev == stat.rdev) || - (S_ISDIR(stat.mode) && s == nd.dentry->d_inode->i_sb)) { + (S_ISDIR(stat.mode) && + s == nd.path.dentry->d_inode->i_sb)) { sb = s; goto free_nd; } @@ -899,7 +900,7 @@ static struct super_block* get_gfs2_sb(const char *dev_name) "mount point %s\n", dev_name); free_nd: - path_release(&nd); + path_put(&nd.path); out: return sb; } diff --git a/fs/inotify_user.c b/fs/inotify_user.c index 3ab09a65c456..7b94a1e3c015 100644 --- a/fs/inotify_user.c +++ b/fs/inotify_user.c @@ -41,9 +41,9 @@ static struct kmem_cache *event_cachep __read_mostly; static struct vfsmount *inotify_mnt __read_mostly; /* these are configurable via /proc/sys/fs/inotify/ */ -int inotify_max_user_instances __read_mostly; -int inotify_max_user_watches __read_mostly; -int inotify_max_queued_events __read_mostly; +static int inotify_max_user_instances __read_mostly; +static int inotify_max_user_watches __read_mostly; +static int inotify_max_queued_events __read_mostly; /* * Lock ordering: @@ -367,7 +367,7 @@ static int find_inode(const char __user *dirname, struct nameidata *nd, /* you can only watch an inode if you have read permissions on it */ error = vfs_permission(nd, MAY_READ); if (error) - path_release(nd); + path_put(&nd->path); return error; } @@ -667,7 +667,7 @@ asmlinkage long sys_inotify_add_watch(int fd, const char __user *path, u32 mask) goto fput_and_out; /* inode held in place by reference to nd; dev by fget on fd */ - inode = nd.dentry->d_inode; + inode = nd.path.dentry->d_inode; dev = filp->private_data; mutex_lock(&dev->up_mutex); @@ -676,7 +676,7 @@ asmlinkage long sys_inotify_add_watch(int fd, const char __user *path, u32 mask) ret = create_watch(dev, inode, mask); mutex_unlock(&dev->up_mutex); - path_release(&nd); + path_put(&nd.path); fput_and_out: fput_light(filp, fput_needed); return ret; diff --git a/fs/namei.c b/fs/namei.c index 52703986323a..941c8e8228c0 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -231,7 +231,7 @@ int permission(struct inode *inode, int mask, struct nameidata *nd) struct vfsmount *mnt = NULL; if (nd) - mnt = nd->mnt; + mnt = nd->path.mnt; if (mask & MAY_WRITE) { umode_t mode = inode->i_mode; @@ -296,7 +296,7 @@ int permission(struct inode *inode, int mask, struct nameidata *nd) */ int vfs_permission(struct nameidata *nd, int mask) { - return permission(nd->dentry->d_inode, mask, nd); + return permission(nd->path.dentry->d_inode, mask, nd); } /** @@ -362,21 +362,31 @@ int deny_write_access(struct file * file) return 0; } -void path_release(struct nameidata *nd) -{ - dput(nd->dentry); - mntput(nd->mnt); -} - -/* - * umount() mustn't call path_release()/mntput() as that would clear - * mnt_expiry_mark +/** + * path_get - get a reference to a path + * @path: path to get the reference to + * + * Given a path increment the reference count to the dentry and the vfsmount. */ -void path_release_on_umount(struct nameidata *nd) +void path_get(struct path *path) { - dput(nd->dentry); - mntput_no_expire(nd->mnt); + mntget(path->mnt); + dget(path->dentry); } +EXPORT_SYMBOL(path_get); + +/** + * path_put - put a reference to a path + * @path: path to put the reference to + * + * Given a path decrement the reference count to the dentry and the vfsmount. + */ +void path_put(struct path *path) +{ + dput(path->dentry); + mntput(path->mnt); +} +EXPORT_SYMBOL(path_put); /** * release_open_intent - free up open intent resources @@ -539,16 +549,16 @@ walk_init_root(const char *name, struct nameidata *nd) struct fs_struct *fs = current->fs; read_lock(&fs->lock); - if (fs->altroot && !(nd->flags & LOOKUP_NOALT)) { - nd->mnt = mntget(fs->altrootmnt); - nd->dentry = dget(fs->altroot); + if (fs->altroot.dentry && !(nd->flags & LOOKUP_NOALT)) { + nd->path = fs->altroot; + path_get(&fs->altroot); read_unlock(&fs->lock); if (__emul_lookup_dentry(name,nd)) return 0; read_lock(&fs->lock); } - nd->mnt = mntget(fs->rootmnt); - nd->dentry = dget(fs->root); + nd->path = fs->root; + path_get(&fs->root); read_unlock(&fs->lock); return 1; } @@ -561,7 +571,7 @@ static __always_inline int __vfs_follow_link(struct nameidata *nd, const char *l goto fail; if (*link == '/') { - path_release(nd); + path_put(&nd->path); if (!walk_init_root(link, nd)) /* weird __emul_prefix() stuff did it */ goto out; @@ -577,31 +587,31 @@ out: */ name = __getname(); if (unlikely(!name)) { - path_release(nd); + path_put(&nd->path); return -ENOMEM; } strcpy(name, nd->last.name); nd->last.name = name; return 0; fail: - path_release(nd); + path_put(&nd->path); return PTR_ERR(link); } -static inline void dput_path(struct path *path, struct nameidata *nd) +static void path_put_conditional(struct path *path, struct nameidata *nd) { dput(path->dentry); - if (path->mnt != nd->mnt) + if (path->mnt != nd->path.mnt) mntput(path->mnt); } static inline void path_to_nameidata(struct path *path, struct nameidata *nd) { - dput(nd->dentry); - if (nd->mnt != path->mnt) - mntput(nd->mnt); - nd->mnt = path->mnt; - nd->dentry = path->dentry; + dput(nd->path.dentry); + if (nd->path.mnt != path->mnt) + mntput(nd->path.mnt); + nd->path.mnt = path->mnt; + nd->path.dentry = path->dentry; } static __always_inline int __do_follow_link(struct path *path, struct nameidata *nd) @@ -613,7 +623,7 @@ static __always_inline int __do_follow_link(struct path *path, struct nameidata touch_atime(path->mnt, dentry); nd_set_link(nd, NULL); - if (path->mnt != nd->mnt) { + if (path->mnt != nd->path.mnt) { path_to_nameidata(path, nd); dget(dentry); } @@ -628,8 +638,7 @@ static __always_inline int __do_follow_link(struct path *path, struct nameidata if (dentry->d_inode->i_op->put_link) dentry->d_inode->i_op->put_link(dentry, nd, cookie); } - dput(dentry); - mntput(path->mnt); + path_put(path); return error; } @@ -661,8 +670,8 @@ static inline int do_follow_link(struct path *path, struct nameidata *nd) nd->depth--; return err; loop: - dput_path(path, nd); - path_release(nd); + path_put_conditional(path, nd); + path_put(&nd->path); return err; } @@ -743,37 +752,37 @@ static __always_inline void follow_dotdot(struct nameidata *nd) while(1) { struct vfsmount *parent; - struct dentry *old = nd->dentry; + struct dentry *old = nd->path.dentry; read_lock(&fs->lock); - if (nd->dentry == fs->root && - nd->mnt == fs->rootmnt) { + if (nd->path.dentry == fs->root.dentry && + nd->path.mnt == fs->root.mnt) { read_unlock(&fs->lock); break; } read_unlock(&fs->lock); spin_lock(&dcache_lock); - if (nd->dentry != nd->mnt->mnt_root) { - nd->dentry = dget(nd->dentry->d_parent); + if (nd->path.dentry != nd->path.mnt->mnt_root) { + nd->path.dentry = dget(nd->path.dentry->d_parent); spin_unlock(&dcache_lock); dput(old); break; } spin_unlock(&dcache_lock); spin_lock(&vfsmount_lock); - parent = nd->mnt->mnt_parent; - if (parent == nd->mnt) { + parent = nd->path.mnt->mnt_parent; + if (parent == nd->path.mnt) { spin_unlock(&vfsmount_lock); break; } mntget(parent); - nd->dentry = dget(nd->mnt->mnt_mountpoint); + nd->path.dentry = dget(nd->path.mnt->mnt_mountpoint); spin_unlock(&vfsmount_lock); dput(old); - mntput(nd->mnt); - nd->mnt = parent; + mntput(nd->path.mnt); + nd->path.mnt = parent; } - follow_mount(&nd->mnt, &nd->dentry); + follow_mount(&nd->path.mnt, &nd->path.dentry); } /* @@ -784,8 +793,8 @@ static __always_inline void follow_dotdot(struct nameidata *nd) static int do_lookup(struct nameidata *nd, struct qstr *name, struct path *path) { - struct vfsmount *mnt = nd->mnt; - struct dentry *dentry = __d_lookup(nd->dentry, name); + struct vfsmount *mnt = nd->path.mnt; + struct dentry *dentry = __d_lookup(nd->path.dentry, name); if (!dentry) goto need_lookup; @@ -798,7 +807,7 @@ done: return 0; need_lookup: - dentry = real_lookup(nd->dentry, name, nd); + dentry = real_lookup(nd->path.dentry, name, nd); if (IS_ERR(dentry)) goto fail; goto done; @@ -835,7 +844,7 @@ static int __link_path_walk(const char *name, struct nameidata *nd) if (!*name) goto return_reval; - inode = nd->dentry->d_inode; + inode = nd->path.dentry->d_inode; if (nd->depth) lookup_flags = LOOKUP_FOLLOW | (nd->flags & LOOKUP_CONTINUE); @@ -883,7 +892,7 @@ static int __link_path_walk(const char *name, struct nameidata *nd) if (this.name[1] != '.') break; follow_dotdot(nd); - inode = nd->dentry->d_inode; + inode = nd->path.dentry->d_inode; /* fallthrough */ case 1: continue; @@ -892,8 +901,9 @@ static int __link_path_walk(const char *name, struct nameidata *nd) * See if the low-level filesystem might want * to use its own hash.. */ - if (nd->dentry->d_op && nd->dentry->d_op->d_hash) { - err = nd->dentry->d_op->d_hash(nd->dentry, &this); + if (nd->path.dentry->d_op && nd->path.dentry->d_op->d_hash) { + err = nd->path.dentry->d_op->d_hash(nd->path.dentry, + &this); if (err < 0) break; } @@ -915,7 +925,7 @@ static int __link_path_walk(const char *name, struct nameidata *nd) if (err) goto return_err; err = -ENOENT; - inode = nd->dentry->d_inode; + inode = nd->path.dentry->d_inode; if (!inode) break; err = -ENOTDIR; @@ -943,13 +953,14 @@ last_component: if (this.name[1] != '.') break; follow_dotdot(nd); - inode = nd->dentry->d_inode; + inode = nd->path.dentry->d_inode; /* fallthrough */ case 1: goto return_reval; } - if (nd->dentry->d_op && nd->dentry->d_op->d_hash) { - err = nd->dentry->d_op->d_hash(nd->dentry, &this); + if (nd->path.dentry->d_op && nd->path.dentry->d_op->d_hash) { + err = nd->path.dentry->d_op->d_hash(nd->path.dentry, + &this); if (err < 0) break; } @@ -962,7 +973,7 @@ last_component: err = do_follow_link(&next, nd); if (err) goto return_err; - inode = nd->dentry->d_inode; + inode = nd->path.dentry->d_inode; } else path_to_nameidata(&next, nd); err = -ENOENT; @@ -990,20 +1001,21 @@ return_reval: * We bypassed the ordinary revalidation routines. * We may need to check the cached dentry for staleness. */ - if (nd->dentry && nd->dentry->d_sb && - (nd->dentry->d_sb->s_type->fs_flags & FS_REVAL_DOT)) { + if (nd->path.dentry && nd->path.dentry->d_sb && + (nd->path.dentry->d_sb->s_type->fs_flags & FS_REVAL_DOT)) { err = -ESTALE; /* Note: we do not d_invalidate() */ - if (!nd->dentry->d_op->d_revalidate(nd->dentry, nd)) + if (!nd->path.dentry->d_op->d_revalidate( + nd->path.dentry, nd)) break; } return_base: return 0; out_dput: - dput_path(&next, nd); + path_put_conditional(&next, nd); break; } - path_release(nd); + path_put(&nd->path); return_err: return err; } @@ -1021,20 +1033,19 @@ static int link_path_walk(const char *name, struct nameidata *nd) int result; /* make sure the stuff we saved doesn't go away */ - dget(save.dentry); - mntget(save.mnt); + dget(save.path.dentry); + mntget(save.path.mnt); result = __link_path_walk(name, nd); if (result == -ESTALE) { *nd = save; - dget(nd->dentry); - mntget(nd->mnt); + dget(nd->path.dentry); + mntget(nd->path.mnt); nd->flags |= LOOKUP_REVAL; result = __link_path_walk(name, nd); } - dput(save.dentry); - mntput(save.mnt); + path_put(&save.path); return result; } @@ -1054,9 +1065,9 @@ static int __emul_lookup_dentry(const char *name, struct nameidata *nd) if (path_walk(name, nd)) return 0; /* something went wrong... */ - if (!nd->dentry->d_inode || S_ISDIR(nd->dentry->d_inode->i_mode)) { - struct dentry *old_dentry = nd->dentry; - struct vfsmount *old_mnt = nd->mnt; + if (!nd->path.dentry->d_inode || + S_ISDIR(nd->path.dentry->d_inode->i_mode)) { + struct path old_path = nd->path; struct qstr last = nd->last; int last_type = nd->last_type; struct fs_struct *fs = current->fs; @@ -1067,19 +1078,17 @@ static int __emul_lookup_dentry(const char *name, struct nameidata *nd) */ nd->last_type = LAST_ROOT; read_lock(&fs->lock); - nd->mnt = mntget(fs->rootmnt); - nd->dentry = dget(fs->root); + nd->path = fs->root; + path_get(&fs->root); read_unlock(&fs->lock); if (path_walk(name, nd) == 0) { - if (nd->dentry->d_inode) { - dput(old_dentry); - mntput(old_mnt); + if (nd->path.dentry->d_inode) { + path_put(&old_path); return 1; } - path_release(nd); + path_put(&nd->path); } - nd->dentry = old_dentry; - nd->mnt = old_mnt; + nd->path = old_path; nd->last = last; nd->last_type = last_type; } @@ -1090,29 +1099,22 @@ void set_fs_altroot(void) { char *emul = __emul_prefix(); struct nameidata nd; - struct vfsmount *mnt = NULL, *oldmnt; - struct dentry *dentry = NULL, *olddentry; + struct path path = {}, old_path; int err; struct fs_struct *fs = current->fs; if (!emul) goto set_it; err = path_lookup(emul, LOOKUP_FOLLOW|LOOKUP_DIRECTORY|LOOKUP_NOALT, &nd); - if (!err) { - mnt = nd.mnt; - dentry = nd.dentry; - } + if (!err) + path = nd.path; set_it: write_lock(&fs->lock); - oldmnt = fs->altrootmnt; - olddentry = fs->altroot; - fs->altrootmnt = mnt; - fs->altroot = dentry; + old_path = fs->altroot; + fs->altroot = path; write_unlock(&fs->lock); - if (olddentry) { - dput(olddentry); - mntput(oldmnt); - } + if (old_path.dentry) + path_put(&old_path); } /* Returns 0 and nd will be valid on success; Retuns error, otherwise. */ @@ -1130,21 +1132,21 @@ static int do_path_lookup(int dfd, const char *name, if (*name=='/') { read_lock(&fs->lock); - if (fs->altroot && !(nd->flags & LOOKUP_NOALT)) { - nd->mnt = mntget(fs->altrootmnt); - nd->dentry = dget(fs->altroot); + if (fs->altroot.dentry && !(nd->flags & LOOKUP_NOALT)) { + nd->path = fs->altroot; + path_get(&fs->altroot); read_unlock(&fs->lock); if (__emul_lookup_dentry(name,nd)) goto out; /* found in altroot */ read_lock(&fs->lock); } - nd->mnt = mntget(fs->rootmnt); - nd->dentry = dget(fs->root); + nd->path = fs->root; + path_get(&fs->root); read_unlock(&fs->lock); } else if (dfd == AT_FDCWD) { read_lock(&fs->lock); - nd->mnt = mntget(fs->pwdmnt); - nd->dentry = dget(fs->pwd); + nd->path = fs->pwd; + path_get(&fs->pwd); read_unlock(&fs->lock); } else { struct dentry *dentry; @@ -1164,17 +1166,17 @@ static int do_path_lookup(int dfd, const char *name, if (retval) goto fput_fail; - nd->mnt = mntget(file->f_path.mnt); - nd->dentry = dget(dentry); + nd->path = file->f_path; + path_get(&file->f_path); fput_light(file, fput_needed); } retval = path_walk(name, nd); out: - if (unlikely(!retval && !audit_dummy_context() && nd->dentry && - nd->dentry->d_inode)) - audit_inode(name, nd->dentry); + if (unlikely(!retval && !audit_dummy_context() && nd->path.dentry && + nd->path.dentry->d_inode)) + audit_inode(name, nd->path.dentry); out_fail: return retval; @@ -1208,13 +1210,13 @@ int vfs_path_lookup(struct dentry *dentry, struct vfsmount *mnt, nd->flags = flags; nd->depth = 0; - nd->mnt = mntget(mnt); - nd->dentry = dget(dentry); + nd->path.mnt = mntget(mnt); + nd->path.dentry = dget(dentry); retval = path_walk(name, nd); - if (unlikely(!retval && !audit_dummy_context() && nd->dentry && - nd->dentry->d_inode)) - audit_inode(name, nd->dentry); + if (unlikely(!retval && !audit_dummy_context() && nd->path.dentry && + nd->path.dentry->d_inode)) + audit_inode(name, nd->path.dentry); return retval; @@ -1236,7 +1238,7 @@ static int __path_lookup_intent_open(int dfd, const char *name, if (IS_ERR(nd->intent.open.file)) { if (err == 0) { err = PTR_ERR(nd->intent.open.file); - path_release(nd); + path_put(&nd->path); } } else if (err != 0) release_open_intent(nd); @@ -1333,10 +1335,10 @@ static struct dentry *lookup_hash(struct nameidata *nd) { int err; - err = permission(nd->dentry->d_inode, MAY_EXEC, nd); + err = permission(nd->path.dentry->d_inode, MAY_EXEC, nd); if (err) return ERR_PTR(err); - return __lookup_hash(&nd->last, nd->dentry, nd); + return __lookup_hash(&nd->last, nd->path.dentry, nd); } static int __lookup_one_len(const char *name, struct qstr *this, @@ -1595,7 +1597,7 @@ int vfs_create(struct inode *dir, struct dentry *dentry, int mode, int may_open(struct nameidata *nd, int acc_mode, int flag) { - struct dentry *dentry = nd->dentry; + struct dentry *dentry = nd->path.dentry; struct inode *inode = dentry->d_inode; int error; @@ -1616,7 +1618,7 @@ int may_open(struct nameidata *nd, int acc_mode, int flag) if (S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) { flag &= ~O_TRUNC; } else if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode)) { - if (nd->mnt->mnt_flags & MNT_NODEV) + if (nd->path.mnt->mnt_flags & MNT_NODEV) return -EACCES; flag &= ~O_TRUNC; @@ -1678,14 +1680,14 @@ static int open_namei_create(struct nameidata *nd, struct path *path, int flag, int mode) { int error; - struct dentry *dir = nd->dentry; + struct dentry *dir = nd->path.dentry; if (!IS_POSIXACL(dir->d_inode)) mode &= ~current->fs->umask; error = vfs_create(dir->d_inode, path->dentry, mode, nd); mutex_unlock(&dir->d_inode->i_mutex); - dput(nd->dentry); - nd->dentry = path->dentry; + dput(nd->path.dentry); + nd->path.dentry = path->dentry; if (error) return error; /* Don't check for write permission, don't truncate */ @@ -1752,11 +1754,11 @@ int open_namei(int dfd, const char *pathname, int flag, if (nd->last_type != LAST_NORM || nd->last.name[nd->last.len]) goto exit; - dir = nd->dentry; + dir = nd->path.dentry; nd->flags &= ~LOOKUP_PARENT; mutex_lock(&dir->d_inode->i_mutex); path.dentry = lookup_hash(nd); - path.mnt = nd->mnt; + path.mnt = nd->path.mnt; do_last: error = PTR_ERR(path.dentry); @@ -1812,11 +1814,11 @@ ok: return 0; exit_dput: - dput_path(&path, nd); + path_put_conditional(&path, nd); exit: if (!IS_ERR(nd->intent.open.file)) release_open_intent(nd); - path_release(nd); + path_put(&nd->path); return error; do_link: @@ -1861,10 +1863,10 @@ do_link: __putname(nd->last.name); goto exit; } - dir = nd->dentry; + dir = nd->path.dentry; mutex_lock(&dir->d_inode->i_mutex); path.dentry = lookup_hash(nd); - path.mnt = nd->mnt; + path.mnt = nd->path.mnt; __putname(nd->last.name); goto do_last; } @@ -1877,13 +1879,13 @@ do_link: * Simple function to lookup and return a dentry and create it * if it doesn't exist. Is SMP-safe. * - * Returns with nd->dentry->d_inode->i_mutex locked. + * Returns with nd->path.dentry->d_inode->i_mutex locked. */ struct dentry *lookup_create(struct nameidata *nd, int is_dir) { struct dentry *dentry = ERR_PTR(-EEXIST); - mutex_lock_nested(&nd->dentry->d_inode->i_mutex, I_MUTEX_PARENT); + mutex_lock_nested(&nd->path.dentry->d_inode->i_mutex, I_MUTEX_PARENT); /* * Yucky last component or no last component at all? * (foo/., foo/.., /////) @@ -1962,19 +1964,19 @@ asmlinkage long sys_mknodat(int dfd, const char __user *filename, int mode, dentry = lookup_create(&nd, 0); error = PTR_ERR(dentry); - if (!IS_POSIXACL(nd.dentry->d_inode)) + if (!IS_POSIXACL(nd.path.dentry->d_inode)) mode &= ~current->fs->umask; if (!IS_ERR(dentry)) { switch (mode & S_IFMT) { case 0: case S_IFREG: - error = vfs_create(nd.dentry->d_inode,dentry,mode,&nd); + error = vfs_create(nd.path.dentry->d_inode,dentry,mode,&nd); break; case S_IFCHR: case S_IFBLK: - error = vfs_mknod(nd.dentry->d_inode,dentry,mode, + error = vfs_mknod(nd.path.dentry->d_inode,dentry,mode, new_decode_dev(dev)); break; case S_IFIFO: case S_IFSOCK: - error = vfs_mknod(nd.dentry->d_inode,dentry,mode,0); + error = vfs_mknod(nd.path.dentry->d_inode,dentry,mode,0); break; case S_IFDIR: error = -EPERM; @@ -1984,8 +1986,8 @@ asmlinkage long sys_mknodat(int dfd, const char __user *filename, int mode, } dput(dentry); } - mutex_unlock(&nd.dentry->d_inode->i_mutex); - path_release(&nd); + mutex_unlock(&nd.path.dentry->d_inode->i_mutex); + path_put(&nd.path); out: putname(tmp); @@ -2039,13 +2041,13 @@ asmlinkage long sys_mkdirat(int dfd, const char __user *pathname, int mode) if (IS_ERR(dentry)) goto out_unlock; - if (!IS_POSIXACL(nd.dentry->d_inode)) + if (!IS_POSIXACL(nd.path.dentry->d_inode)) mode &= ~current->fs->umask; - error = vfs_mkdir(nd.dentry->d_inode, dentry, mode); + error = vfs_mkdir(nd.path.dentry->d_inode, dentry, mode); dput(dentry); out_unlock: - mutex_unlock(&nd.dentry->d_inode->i_mutex); - path_release(&nd); + mutex_unlock(&nd.path.dentry->d_inode->i_mutex); + path_put(&nd.path); out: putname(tmp); out_err: @@ -2143,17 +2145,17 @@ static long do_rmdir(int dfd, const char __user *pathname) error = -EBUSY; goto exit1; } - mutex_lock_nested(&nd.dentry->d_inode->i_mutex, I_MUTEX_PARENT); + mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT); dentry = lookup_hash(&nd); error = PTR_ERR(dentry); if (IS_ERR(dentry)) goto exit2; - error = vfs_rmdir(nd.dentry->d_inode, dentry); + error = vfs_rmdir(nd.path.dentry->d_inode, dentry); dput(dentry); exit2: - mutex_unlock(&nd.dentry->d_inode->i_mutex); + mutex_unlock(&nd.path.dentry->d_inode->i_mutex); exit1: - path_release(&nd); + path_put(&nd.path); exit: putname(name); return error; @@ -2219,7 +2221,7 @@ static long do_unlinkat(int dfd, const char __user *pathname) error = -EISDIR; if (nd.last_type != LAST_NORM) goto exit1; - mutex_lock_nested(&nd.dentry->d_inode->i_mutex, I_MUTEX_PARENT); + mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT); dentry = lookup_hash(&nd); error = PTR_ERR(dentry); if (!IS_ERR(dentry)) { @@ -2229,15 +2231,15 @@ static long do_unlinkat(int dfd, const char __user *pathname) inode = dentry->d_inode; if (inode) atomic_inc(&inode->i_count); - error = vfs_unlink(nd.dentry->d_inode, dentry); + error = vfs_unlink(nd.path.dentry->d_inode, dentry); exit2: dput(dentry); } - mutex_unlock(&nd.dentry->d_inode->i_mutex); + mutex_unlock(&nd.path.dentry->d_inode->i_mutex); if (inode) iput(inode); /* truncate the inode here */ exit1: - path_release(&nd); + path_put(&nd.path); exit: putname(name); return error; @@ -2310,11 +2312,11 @@ asmlinkage long sys_symlinkat(const char __user *oldname, if (IS_ERR(dentry)) goto out_unlock; - error = vfs_symlink(nd.dentry->d_inode, dentry, from, S_IALLUGO); + error = vfs_symlink(nd.path.dentry->d_inode, dentry, from, S_IALLUGO); dput(dentry); out_unlock: - mutex_unlock(&nd.dentry->d_inode->i_mutex); - path_release(&nd); + mutex_unlock(&nd.path.dentry->d_inode->i_mutex); + path_put(&nd.path); out: putname(to); out_putname: @@ -2399,20 +2401,20 @@ asmlinkage long sys_linkat(int olddfd, const char __user *oldname, if (error) goto out; error = -EXDEV; - if (old_nd.mnt != nd.mnt) + if (old_nd.path.mnt != nd.path.mnt) goto out_release; new_dentry = lookup_create(&nd, 0); error = PTR_ERR(new_dentry); if (IS_ERR(new_dentry)) goto out_unlock; - error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry); + error = vfs_link(old_nd.path.dentry, nd.path.dentry->d_inode, new_dentry); dput(new_dentry); out_unlock: - mutex_unlock(&nd.dentry->d_inode->i_mutex); + mutex_unlock(&nd.path.dentry->d_inode->i_mutex); out_release: - path_release(&nd); + path_put(&nd.path); out: - path_release(&old_nd); + path_put(&old_nd.path); exit: putname(to); @@ -2588,15 +2590,15 @@ static int do_rename(int olddfd, const char *oldname, goto exit1; error = -EXDEV; - if (oldnd.mnt != newnd.mnt) + if (oldnd.path.mnt != newnd.path.mnt) goto exit2; - old_dir = oldnd.dentry; + old_dir = oldnd.path.dentry; error = -EBUSY; if (oldnd.last_type != LAST_NORM) goto exit2; - new_dir = newnd.dentry; + new_dir = newnd.path.dentry; if (newnd.last_type != LAST_NORM) goto exit2; @@ -2640,9 +2642,9 @@ exit4: exit3: unlock_rename(new_dir, old_dir); exit2: - path_release(&newnd); + path_put(&newnd.path); exit1: - path_release(&oldnd); + path_put(&oldnd.path); exit: return error; } @@ -2816,7 +2818,6 @@ EXPORT_SYMBOL(page_symlink); EXPORT_SYMBOL(page_symlink_inode_operations); EXPORT_SYMBOL(path_lookup); EXPORT_SYMBOL(vfs_path_lookup); -EXPORT_SYMBOL(path_release); EXPORT_SYMBOL(permission); EXPORT_SYMBOL(vfs_permission); EXPORT_SYMBOL(file_permission); diff --git a/fs/namespace.c b/fs/namespace.c index 63ced21c12dc..7953c96a2071 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -157,13 +157,13 @@ static void __touch_mnt_namespace(struct mnt_namespace *ns) static void detach_mnt(struct vfsmount *mnt, struct nameidata *old_nd) { - old_nd->dentry = mnt->mnt_mountpoint; - old_nd->mnt = mnt->mnt_parent; + old_nd->path.dentry = mnt->mnt_mountpoint; + old_nd->path.mnt = mnt->mnt_parent; mnt->mnt_parent = mnt; mnt->mnt_mountpoint = mnt->mnt_root; list_del_init(&mnt->mnt_child); list_del_init(&mnt->mnt_hash); - old_nd->dentry->d_mounted--; + old_nd->path.dentry->d_mounted--; } void mnt_set_mountpoint(struct vfsmount *mnt, struct dentry *dentry, @@ -176,10 +176,10 @@ void mnt_set_mountpoint(struct vfsmount *mnt, struct dentry *dentry, static void attach_mnt(struct vfsmount *mnt, struct nameidata *nd) { - mnt_set_mountpoint(nd->mnt, nd->dentry, mnt); + mnt_set_mountpoint(nd->path.mnt, nd->path.dentry, mnt); list_add_tail(&mnt->mnt_hash, mount_hashtable + - hash(nd->mnt, nd->dentry)); - list_add_tail(&mnt->mnt_child, &nd->mnt->mnt_mounts); + hash(nd->path.mnt, nd->path.dentry)); + list_add_tail(&mnt->mnt_child, &nd->path.mnt->mnt_mounts); } /* @@ -408,10 +408,11 @@ static int show_vfsmnt(struct seq_file *m, void *v) { 0, NULL } }; struct proc_fs_info *fs_infop; + struct path mnt_path = { .dentry = mnt->mnt_root, .mnt = mnt }; mangle(m, mnt->mnt_devname ? mnt->mnt_devname : "none"); seq_putc(m, ' '); - seq_path(m, mnt, mnt->mnt_root, " \t\n\\"); + seq_path(m, &mnt_path, " \t\n\\"); seq_putc(m, ' '); mangle(m, mnt->mnt_sb->s_type->name); if (mnt->mnt_sb->s_subtype && mnt->mnt_sb->s_subtype[0]) { @@ -443,6 +444,7 @@ struct seq_operations mounts_op = { static int show_vfsstat(struct seq_file *m, void *v) { struct vfsmount *mnt = list_entry(v, struct vfsmount, mnt_list); + struct path mnt_path = { .dentry = mnt->mnt_root, .mnt = mnt }; int err = 0; /* device */ @@ -454,7 +456,7 @@ static int show_vfsstat(struct seq_file *m, void *v) /* mount point */ seq_puts(m, " mounted on "); - seq_path(m, mnt, mnt->mnt_root, " \t\n\\"); + seq_path(m, &mnt_path, " \t\n\\"); seq_putc(m, ' '); /* file system type */ @@ -593,7 +595,7 @@ static int do_umount(struct vfsmount *mnt, int flags) * (2) the usage count == 1 [parent vfsmount] + 1 [sys_umount] */ if (flags & MNT_EXPIRE) { - if (mnt == current->fs->rootmnt || + if (mnt == current->fs->root.mnt || flags & (MNT_FORCE | MNT_DETACH)) return -EINVAL; @@ -628,7 +630,7 @@ static int do_umount(struct vfsmount *mnt, int flags) * /reboot - static binary that would close all descriptors and * call reboot(9). Then init(8) could umount root and exec /reboot. */ - if (mnt == current->fs->rootmnt && !(flags & MNT_DETACH)) { + if (mnt == current->fs->root.mnt && !(flags & MNT_DETACH)) { /* * Special case for "unmounting" root ... * we just try to remount it readonly. @@ -679,18 +681,20 @@ asmlinkage long sys_umount(char __user * name, int flags) if (retval) goto out; retval = -EINVAL; - if (nd.dentry != nd.mnt->mnt_root) + if (nd.path.dentry != nd.path.mnt->mnt_root) goto dput_and_out; - if (!check_mnt(nd.mnt)) + if (!check_mnt(nd.path.mnt)) goto dput_and_out; retval = -EPERM; if (!capable(CAP_SYS_ADMIN)) goto dput_and_out; - retval = do_umount(nd.mnt, flags); + retval = do_umount(nd.path.mnt, flags); dput_and_out: - path_release_on_umount(&nd); + /* we mustn't call path_put() as that would clear mnt_expiry_mark */ + dput(nd.path.dentry); + mntput_no_expire(nd.path.mnt); out: return retval; } @@ -713,10 +717,10 @@ static int mount_is_safe(struct nameidata *nd) return 0; return -EPERM; #ifdef notyet - if (S_ISLNK(nd->dentry->d_inode->i_mode)) + if (S_ISLNK(nd->path.dentry->d_inode->i_mode)) return -EPERM; - if (nd->dentry->d_inode->i_mode & S_ISVTX) { - if (current->uid != nd->dentry->d_inode->i_uid) + if (nd->path.dentry->d_inode->i_mode & S_ISVTX) { + if (current->uid != nd->path.dentry->d_inode->i_uid) return -EPERM; } if (vfs_permission(nd, MAY_WRITE)) @@ -765,8 +769,8 @@ struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry, q = q->mnt_parent; } p = s; - nd.mnt = q; - nd.dentry = p->mnt_mountpoint; + nd.path.mnt = q; + nd.path.dentry = p->mnt_mountpoint; q = clone_mnt(p, p->mnt_root, flag); if (!q) goto Enomem; @@ -875,8 +879,8 @@ static int attach_recursive_mnt(struct vfsmount *source_mnt, struct nameidata *nd, struct nameidata *parent_nd) { LIST_HEAD(tree_list); - struct vfsmount *dest_mnt = nd->mnt; - struct dentry *dest_dentry = nd->dentry; + struct vfsmount *dest_mnt = nd->path.mnt; + struct dentry *dest_dentry = nd->path.dentry; struct vfsmount *child, *p; if (propagate_mnt(dest_mnt, dest_dentry, source_mnt, &tree_list)) @@ -911,13 +915,13 @@ static int graft_tree(struct vfsmount *mnt, struct nameidata *nd) if (mnt->mnt_sb->s_flags & MS_NOUSER) return -EINVAL; - if (S_ISDIR(nd->dentry->d_inode->i_mode) != + if (S_ISDIR(nd->path.dentry->d_inode->i_mode) != S_ISDIR(mnt->mnt_root->d_inode->i_mode)) return -ENOTDIR; err = -ENOENT; - mutex_lock(&nd->dentry->d_inode->i_mutex); - if (IS_DEADDIR(nd->dentry->d_inode)) + mutex_lock(&nd->path.dentry->d_inode->i_mutex); + if (IS_DEADDIR(nd->path.dentry->d_inode)) goto out_unlock; err = security_sb_check_sb(mnt, nd); @@ -925,10 +929,10 @@ static int graft_tree(struct vfsmount *mnt, struct nameidata *nd) goto out_unlock; err = -ENOENT; - if (IS_ROOT(nd->dentry) || !d_unhashed(nd->dentry)) + if (IS_ROOT(nd->path.dentry) || !d_unhashed(nd->path.dentry)) err = attach_recursive_mnt(mnt, nd, NULL); out_unlock: - mutex_unlock(&nd->dentry->d_inode->i_mutex); + mutex_unlock(&nd->path.dentry->d_inode->i_mutex); if (!err) security_sb_post_addmount(mnt, nd); return err; @@ -940,14 +944,14 @@ out_unlock: */ static noinline int do_change_type(struct nameidata *nd, int flag) { - struct vfsmount *m, *mnt = nd->mnt; + struct vfsmount *m, *mnt = nd->path.mnt; int recurse = flag & MS_REC; int type = flag & ~MS_REC; if (!capable(CAP_SYS_ADMIN)) return -EPERM; - if (nd->dentry != nd->mnt->mnt_root) + if (nd->path.dentry != nd->path.mnt->mnt_root) return -EINVAL; down_write(&namespace_sem); @@ -979,17 +983,17 @@ static noinline int do_loopback(struct nameidata *nd, char *old_name, down_write(&namespace_sem); err = -EINVAL; - if (IS_MNT_UNBINDABLE(old_nd.mnt)) - goto out; + if (IS_MNT_UNBINDABLE(old_nd.path.mnt)) + goto out; - if (!check_mnt(nd->mnt) || !check_mnt(old_nd.mnt)) + if (!check_mnt(nd->path.mnt) || !check_mnt(old_nd.path.mnt)) goto out; err = -ENOMEM; if (recurse) - mnt = copy_tree(old_nd.mnt, old_nd.dentry, 0); + mnt = copy_tree(old_nd.path.mnt, old_nd.path.dentry, 0); else - mnt = clone_mnt(old_nd.mnt, old_nd.dentry, 0); + mnt = clone_mnt(old_nd.path.mnt, old_nd.path.dentry, 0); if (!mnt) goto out; @@ -1005,7 +1009,7 @@ static noinline int do_loopback(struct nameidata *nd, char *old_name, out: up_write(&namespace_sem); - path_release(&old_nd); + path_put(&old_nd.path); return err; } @@ -1019,24 +1023,24 @@ static noinline int do_remount(struct nameidata *nd, int flags, int mnt_flags, void *data) { int err; - struct super_block *sb = nd->mnt->mnt_sb; + struct super_block *sb = nd->path.mnt->mnt_sb; if (!capable(CAP_SYS_ADMIN)) return -EPERM; - if (!check_mnt(nd->mnt)) + if (!check_mnt(nd->path.mnt)) return -EINVAL; - if (nd->dentry != nd->mnt->mnt_root) + if (nd->path.dentry != nd->path.mnt->mnt_root) return -EINVAL; down_write(&sb->s_umount); err = do_remount_sb(sb, flags, data, 0); if (!err) - nd->mnt->mnt_flags = mnt_flags; + nd->path.mnt->mnt_flags = mnt_flags; up_write(&sb->s_umount); if (!err) - security_sb_post_remount(nd->mnt, flags, data); + security_sb_post_remount(nd->path.mnt, flags, data); return err; } @@ -1067,61 +1071,65 @@ static noinline int do_move_mount(struct nameidata *nd, char *old_name) return err; down_write(&namespace_sem); - while (d_mountpoint(nd->dentry) && follow_down(&nd->mnt, &nd->dentry)) + while (d_mountpoint(nd->path.dentry) && + follow_down(&nd->path.mnt, &nd->path.dentry)) ; err = -EINVAL; - if (!check_mnt(nd->mnt) || !check_mnt(old_nd.mnt)) + if (!check_mnt(nd->path.mnt) || !check_mnt(old_nd.path.mnt)) goto out; err = -ENOENT; - mutex_lock(&nd->dentry->d_inode->i_mutex); - if (IS_DEADDIR(nd->dentry->d_inode)) + mutex_lock(&nd->path.dentry->d_inode->i_mutex); + if (IS_DEADDIR(nd->path.dentry->d_inode)) goto out1; - if (!IS_ROOT(nd->dentry) && d_unhashed(nd->dentry)) + if (!IS_ROOT(nd->path.dentry) && d_unhashed(nd->path.dentry)) goto out1; err = -EINVAL; - if (old_nd.dentry != old_nd.mnt->mnt_root) + if (old_nd.path.dentry != old_nd.path.mnt->mnt_root) goto out1; - if (old_nd.mnt == old_nd.mnt->mnt_parent) + if (old_nd.path.mnt == old_nd.path.mnt->mnt_parent) goto out1; - if (S_ISDIR(nd->dentry->d_inode->i_mode) != - S_ISDIR(old_nd.dentry->d_inode->i_mode)) + if (S_ISDIR(nd->path.dentry->d_inode->i_mode) != + S_ISDIR(old_nd.path.dentry->d_inode->i_mode)) goto out1; /* * Don't move a mount residing in a shared parent. */ - if (old_nd.mnt->mnt_parent && IS_MNT_SHARED(old_nd.mnt->mnt_parent)) + if (old_nd.path.mnt->mnt_parent && + IS_MNT_SHARED(old_nd.path.mnt->mnt_parent)) goto out1; /* * Don't move a mount tree containing unbindable mounts to a destination * mount which is shared. */ - if (IS_MNT_SHARED(nd->mnt) && tree_contains_unbindable(old_nd.mnt)) + if (IS_MNT_SHARED(nd->path.mnt) && + tree_contains_unbindable(old_nd.path.mnt)) goto out1; err = -ELOOP; - for (p = nd->mnt; p->mnt_parent != p; p = p->mnt_parent) - if (p == old_nd.mnt) + for (p = nd->path.mnt; p->mnt_parent != p; p = p->mnt_parent) + if (p == old_nd.path.mnt) goto out1; - if ((err = attach_recursive_mnt(old_nd.mnt, nd, &parent_nd))) + err = attach_recursive_mnt(old_nd.path.mnt, nd, &parent_nd); + if (err) goto out1; spin_lock(&vfsmount_lock); /* if the mount is moved, it should no longer be expire * automatically */ - list_del_init(&old_nd.mnt->mnt_expire); + list_del_init(&old_nd.path.mnt->mnt_expire); spin_unlock(&vfsmount_lock); out1: - mutex_unlock(&nd->dentry->d_inode->i_mutex); + mutex_unlock(&nd->path.dentry->d_inode->i_mutex); out: up_write(&namespace_sem); if (!err) - path_release(&parent_nd); - path_release(&old_nd); + path_put(&parent_nd.path); + path_put(&old_nd.path); return err; } @@ -1160,16 +1168,17 @@ int do_add_mount(struct vfsmount *newmnt, struct nameidata *nd, down_write(&namespace_sem); /* Something was mounted here while we slept */ - while (d_mountpoint(nd->dentry) && follow_down(&nd->mnt, &nd->dentry)) + while (d_mountpoint(nd->path.dentry) && + follow_down(&nd->path.mnt, &nd->path.dentry)) ; err = -EINVAL; - if (!check_mnt(nd->mnt)) + if (!check_mnt(nd->path.mnt)) goto unlock; /* Refuse the same filesystem on the same mount point */ err = -EBUSY; - if (nd->mnt->mnt_sb == newmnt->mnt_sb && - nd->mnt->mnt_root == nd->dentry) + if (nd->path.mnt->mnt_sb == newmnt->mnt_sb && + nd->path.mnt->mnt_root == nd->path.dentry) goto unlock; err = -EINVAL; @@ -1505,7 +1514,7 @@ long do_mount(char *dev_name, char *dir_name, char *type_page, retval = do_new_mount(&nd, type_page, flags, mnt_flags, dev_name, data_page); dput_out: - path_release(&nd); + path_put(&nd.path); return retval; } @@ -1552,17 +1561,17 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns, while (p) { q->mnt_ns = new_ns; if (fs) { - if (p == fs->rootmnt) { + if (p == fs->root.mnt) { rootmnt = p; - fs->rootmnt = mntget(q); + fs->root.mnt = mntget(q); } - if (p == fs->pwdmnt) { + if (p == fs->pwd.mnt) { pwdmnt = p; - fs->pwdmnt = mntget(q); + fs->pwd.mnt = mntget(q); } - if (p == fs->altrootmnt) { + if (p == fs->altroot.mnt) { altrootmnt = p; - fs->altrootmnt = mntget(q); + fs->altroot.mnt = mntget(q); } } p = next_mnt(p, mnt_ns->root); @@ -1643,44 +1652,35 @@ out1: * Replace the fs->{rootmnt,root} with {mnt,dentry}. Put the old values. * It can block. Requires the big lock held. */ -void set_fs_root(struct fs_struct *fs, struct vfsmount *mnt, - struct dentry *dentry) +void set_fs_root(struct fs_struct *fs, struct path *path) { - struct dentry *old_root; - struct vfsmount *old_rootmnt; + struct path old_root; + write_lock(&fs->lock); old_root = fs->root; - old_rootmnt = fs->rootmnt; - fs->rootmnt = mntget(mnt); - fs->root = dget(dentry); + fs->root = *path; + path_get(path); write_unlock(&fs->lock); - if (old_root) { - dput(old_root); - mntput(old_rootmnt); - } + if (old_root.dentry) + path_put(&old_root); } /* * Replace the fs->{pwdmnt,pwd} with {mnt,dentry}. Put the old values. * It can block. Requires the big lock held. */ -void set_fs_pwd(struct fs_struct *fs, struct vfsmount *mnt, - struct dentry *dentry) +void set_fs_pwd(struct fs_struct *fs, struct path *path) { - struct dentry *old_pwd; - struct vfsmount *old_pwdmnt; + struct path old_pwd; write_lock(&fs->lock); old_pwd = fs->pwd; - old_pwdmnt = fs->pwdmnt; - fs->pwdmnt = mntget(mnt); - fs->pwd = dget(dentry); + fs->pwd = *path; + path_get(path); write_unlock(&fs->lock); - if (old_pwd) { - dput(old_pwd); - mntput(old_pwdmnt); - } + if (old_pwd.dentry) + path_put(&old_pwd); } static void chroot_fs_refs(struct nameidata *old_nd, struct nameidata *new_nd) @@ -1695,12 +1695,12 @@ static void chroot_fs_refs(struct nameidata *old_nd, struct nameidata *new_nd) if (fs) { atomic_inc(&fs->count); task_unlock(p); - if (fs->root == old_nd->dentry - && fs->rootmnt == old_nd->mnt) - set_fs_root(fs, new_nd->mnt, new_nd->dentry); - if (fs->pwd == old_nd->dentry - && fs->pwdmnt == old_nd->mnt) - set_fs_pwd(fs, new_nd->mnt, new_nd->dentry); + if (fs->root.dentry == old_nd->path.dentry + && fs->root.mnt == old_nd->path.mnt) + set_fs_root(fs, &new_nd->path); + if (fs->pwd.dentry == old_nd->path.dentry + && fs->pwd.mnt == old_nd->path.mnt) + set_fs_pwd(fs, &new_nd->path); put_fs_struct(fs); } else task_unlock(p); @@ -1750,7 +1750,7 @@ asmlinkage long sys_pivot_root(const char __user * new_root, if (error) goto out0; error = -EINVAL; - if (!check_mnt(new_nd.mnt)) + if (!check_mnt(new_nd.path.mnt)) goto out1; error = __user_walk(put_old, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &old_nd); @@ -1759,74 +1759,78 @@ asmlinkage long sys_pivot_root(const char __user * new_root, error = security_sb_pivotroot(&old_nd, &new_nd); if (error) { - path_release(&old_nd); + path_put(&old_nd.path); goto out1; } read_lock(¤t->fs->lock); - user_nd.mnt = mntget(current->fs->rootmnt); - user_nd.dentry = dget(current->fs->root); + user_nd.path = current->fs->root; + path_get(¤t->fs->root); read_unlock(¤t->fs->lock); down_write(&namespace_sem); - mutex_lock(&old_nd.dentry->d_inode->i_mutex); + mutex_lock(&old_nd.path.dentry->d_inode->i_mutex); error = -EINVAL; - if (IS_MNT_SHARED(old_nd.mnt) || - IS_MNT_SHARED(new_nd.mnt->mnt_parent) || - IS_MNT_SHARED(user_nd.mnt->mnt_parent)) + if (IS_MNT_SHARED(old_nd.path.mnt) || + IS_MNT_SHARED(new_nd.path.mnt->mnt_parent) || + IS_MNT_SHARED(user_nd.path.mnt->mnt_parent)) goto out2; - if (!check_mnt(user_nd.mnt)) + if (!check_mnt(user_nd.path.mnt)) goto out2; error = -ENOENT; - if (IS_DEADDIR(new_nd.dentry->d_inode)) + if (IS_DEADDIR(new_nd.path.dentry->d_inode)) goto out2; - if (d_unhashed(new_nd.dentry) && !IS_ROOT(new_nd.dentry)) + if (d_unhashed(new_nd.path.dentry) && !IS_ROOT(new_nd.path.dentry)) goto out2; - if (d_unhashed(old_nd.dentry) && !IS_ROOT(old_nd.dentry)) + if (d_unhashed(old_nd.path.dentry) && !IS_ROOT(old_nd.path.dentry)) goto out2; error = -EBUSY; - if (new_nd.mnt == user_nd.mnt || old_nd.mnt == user_nd.mnt) + if (new_nd.path.mnt == user_nd.path.mnt || + old_nd.path.mnt == user_nd.path.mnt) goto out2; /* loop, on the same file system */ error = -EINVAL; - if (user_nd.mnt->mnt_root != user_nd.dentry) + if (user_nd.path.mnt->mnt_root != user_nd.path.dentry) goto out2; /* not a mountpoint */ - if (user_nd.mnt->mnt_parent == user_nd.mnt) + if (user_nd.path.mnt->mnt_parent == user_nd.path.mnt) goto out2; /* not attached */ - if (new_nd.mnt->mnt_root != new_nd.dentry) + if (new_nd.path.mnt->mnt_root != new_nd.path.dentry) goto out2; /* not a mountpoint */ - if (new_nd.mnt->mnt_parent == new_nd.mnt) + if (new_nd.path.mnt->mnt_parent == new_nd.path.mnt) goto out2; /* not attached */ - tmp = old_nd.mnt; /* make sure we can reach put_old from new_root */ + /* make sure we can reach put_old from new_root */ + tmp = old_nd.path.mnt; spin_lock(&vfsmount_lock); - if (tmp != new_nd.mnt) { + if (tmp != new_nd.path.mnt) { for (;;) { if (tmp->mnt_parent == tmp) goto out3; /* already mounted on put_old */ - if (tmp->mnt_parent == new_nd.mnt) + if (tmp->mnt_parent == new_nd.path.mnt) break; tmp = tmp->mnt_parent; } - if (!is_subdir(tmp->mnt_mountpoint, new_nd.dentry)) + if (!is_subdir(tmp->mnt_mountpoint, new_nd.path.dentry)) goto out3; - } else if (!is_subdir(old_nd.dentry, new_nd.dentry)) + } else if (!is_subdir(old_nd.path.dentry, new_nd.path.dentry)) goto out3; - detach_mnt(new_nd.mnt, &parent_nd); - detach_mnt(user_nd.mnt, &root_parent); - attach_mnt(user_nd.mnt, &old_nd); /* mount old root on put_old */ - attach_mnt(new_nd.mnt, &root_parent); /* mount new_root on / */ + detach_mnt(new_nd.path.mnt, &parent_nd); + detach_mnt(user_nd.path.mnt, &root_parent); + /* mount old root on put_old */ + attach_mnt(user_nd.path.mnt, &old_nd); + /* mount new_root on / */ + attach_mnt(new_nd.path.mnt, &root_parent); touch_mnt_namespace(current->nsproxy->mnt_ns); spin_unlock(&vfsmount_lock); chroot_fs_refs(&user_nd, &new_nd); security_sb_post_pivotroot(&user_nd, &new_nd); error = 0; - path_release(&root_parent); - path_release(&parent_nd); + path_put(&root_parent.path); + path_put(&parent_nd.path); out2: - mutex_unlock(&old_nd.dentry->d_inode->i_mutex); + mutex_unlock(&old_nd.path.dentry->d_inode->i_mutex); up_write(&namespace_sem); - path_release(&user_nd); - path_release(&old_nd); + path_put(&user_nd.path); + path_put(&old_nd.path); out1: - path_release(&new_nd); + path_put(&new_nd.path); out0: unlock_kernel(); return error; @@ -1839,6 +1843,7 @@ static void __init init_mount_tree(void) { struct vfsmount *mnt; struct mnt_namespace *ns; + struct path root; mnt = do_kern_mount("rootfs", 0, "rootfs", NULL); if (IS_ERR(mnt)) @@ -1857,8 +1862,11 @@ static void __init init_mount_tree(void) init_task.nsproxy->mnt_ns = ns; get_mnt_ns(ns); - set_fs_pwd(current->fs, ns->root, ns->root->mnt_root); - set_fs_root(current->fs, ns->root, ns->root->mnt_root); + root.mnt = ns->root; + root.dentry = ns->root->mnt_root; + + set_fs_pwd(current->fs, &root); + set_fs_root(current->fs, &root); } void __init mnt_init(void) diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c index bd185a572a23..ecc06c619494 100644 --- a/fs/nfs/callback.c +++ b/fs/nfs/callback.c @@ -105,7 +105,7 @@ static void nfs_callback_svc(struct svc_rqst *rqstp) */ int nfs_callback_up(void) { - struct svc_serv *serv; + struct svc_serv *serv = NULL; int ret = 0; lock_kernel(); @@ -122,24 +122,30 @@ int nfs_callback_up(void) ret = svc_create_xprt(serv, "tcp", nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS); if (ret <= 0) - goto out_destroy; + goto out_err; nfs_callback_tcpport = ret; dprintk("Callback port = 0x%x\n", nfs_callback_tcpport); ret = svc_create_thread(nfs_callback_svc, serv); if (ret < 0) - goto out_destroy; + goto out_err; nfs_callback_info.serv = serv; wait_for_completion(&nfs_callback_info.started); out: + /* + * svc_create creates the svc_serv with sv_nrthreads == 1, and then + * svc_create_thread increments that. So we need to call svc_destroy + * on both success and failure so that the refcount is 1 when the + * thread exits. + */ + if (serv) + svc_destroy(serv); mutex_unlock(&nfs_callback_mutex); unlock_kernel(); return ret; -out_destroy: +out_err: dprintk("Couldn't create callback socket or server thread; err = %d\n", ret); - svc_destroy(serv); -out_err: nfs_callback_info.users--; goto out; } diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 476cb0f837fd..ae04892a5e5d 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -154,7 +154,6 @@ typedef struct { struct nfs_entry *entry; decode_dirent_t decode; int plus; - int error; unsigned long timestamp; int timestamp_valid; } nfs_readdir_descriptor_t; @@ -213,7 +212,6 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page *page) return 0; error: unlock_page(page); - desc->error = error; return -EIO; } @@ -483,13 +481,13 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent, goto out; } timestamp = jiffies; - desc->error = NFS_PROTO(inode)->readdir(file->f_path.dentry, cred, *desc->dir_cookie, - page, + status = NFS_PROTO(inode)->readdir(file->f_path.dentry, cred, + *desc->dir_cookie, page, NFS_SERVER(inode)->dtsize, desc->plus); desc->page = page; desc->ptr = kmap(page); /* matching kunmap in nfs_do_filldir */ - if (desc->error >= 0) { + if (status >= 0) { desc->timestamp = timestamp; desc->timestamp_valid = 1; if ((status = dir_decode(desc)) == 0) diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c index be4ce1c3a3d8..607f6eb9cdb5 100644 --- a/fs/nfs/namespace.c +++ b/fs/nfs/namespace.c @@ -107,38 +107,40 @@ static void * nfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd) BUG_ON(IS_ROOT(dentry)); dprintk("%s: enter\n", __FUNCTION__); - dput(nd->dentry); - nd->dentry = dget(dentry); + dput(nd->path.dentry); + nd->path.dentry = dget(dentry); /* Look it up again */ - parent = dget_parent(nd->dentry); + parent = dget_parent(nd->path.dentry); err = server->nfs_client->rpc_ops->lookup(parent->d_inode, - &nd->dentry->d_name, + &nd->path.dentry->d_name, &fh, &fattr); dput(parent); if (err != 0) goto out_err; if (fattr.valid & NFS_ATTR_FATTR_V4_REFERRAL) - mnt = nfs_do_refmount(nd->mnt, nd->dentry); + mnt = nfs_do_refmount(nd->path.mnt, nd->path.dentry); else - mnt = nfs_do_submount(nd->mnt, nd->dentry, &fh, &fattr); + mnt = nfs_do_submount(nd->path.mnt, nd->path.dentry, &fh, + &fattr); err = PTR_ERR(mnt); if (IS_ERR(mnt)) goto out_err; mntget(mnt); - err = do_add_mount(mnt, nd, nd->mnt->mnt_flags|MNT_SHRINKABLE, &nfs_automount_list); + err = do_add_mount(mnt, nd, nd->path.mnt->mnt_flags|MNT_SHRINKABLE, + &nfs_automount_list); if (err < 0) { mntput(mnt); if (err == -EBUSY) goto out_follow; goto out_err; } - mntput(nd->mnt); - dput(nd->dentry); - nd->mnt = mnt; - nd->dentry = dget(mnt->mnt_root); + mntput(nd->path.mnt); + dput(nd->path.dentry); + nd->path.mnt = mnt; + nd->path.dentry = dget(mnt->mnt_root); schedule_delayed_work(&nfs_automount_task, nfs_mountpoint_expiry_timeout); out: dprintk("%s: done, returned %d\n", __FUNCTION__, err); @@ -146,10 +148,11 @@ out: dprintk("<-- nfs_follow_mountpoint() = %d\n", err); return ERR_PTR(err); out_err: - path_release(nd); + path_put(&nd->path); goto out; out_follow: - while(d_mountpoint(nd->dentry) && follow_down(&nd->mnt, &nd->dentry)) + while (d_mountpoint(nd->path.dentry) && + follow_down(&nd->path.mnt, &nd->path.dentry)) ; err = 0; goto out; diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 027e1095256e..7ce07862c2fb 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -1384,11 +1384,11 @@ out_close: struct dentry * nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd) { - struct dentry *parent; struct path path = { - .mnt = nd->mnt, + .mnt = nd->path.mnt, .dentry = dentry, }; + struct dentry *parent; struct iattr attr; struct rpc_cred *cred; struct nfs4_state *state; @@ -1433,7 +1433,7 @@ int nfs4_open_revalidate(struct inode *dir, struct dentry *dentry, int openflags, struct nameidata *nd) { struct path path = { - .mnt = nd->mnt, + .mnt = nd->path.mnt, .dentry = dentry, }; struct rpc_cred *cred; @@ -1885,7 +1885,7 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, int flags, struct nameidata *nd) { struct path path = { - .mnt = nd->mnt, + .mnt = nd->path.mnt, .dentry = dentry, }; struct nfs4_state *state; diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index f9c7432471dc..6233eb5e98c1 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c @@ -682,8 +682,8 @@ static void nfs_increment_seqid(int status, struct nfs_seqid *seqid) if (seqid->sequence->flags & NFS_SEQID_CONFIRMED) return; printk(KERN_WARNING "NFS: v4 server returned a bad" - "sequence-id error on an" - "unconfirmed sequence %p!\n", + " sequence-id error on an" + " unconfirmed sequence %p!\n", seqid->sequence); case -NFS4ERR_STALE_CLIENTID: case -NFS4ERR_STALE_STATEID: diff --git a/fs/nfs/super.c b/fs/nfs/super.c index 7f4505f6ac6f..1fb381843650 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c @@ -190,6 +190,10 @@ static match_table_t nfs_secflavor_tokens = { { Opt_sec_lkeyi, "lkeyi" }, { Opt_sec_lkeyp, "lkeyp" }, + { Opt_sec_spkm, "spkm3" }, + { Opt_sec_spkmi, "spkm3i" }, + { Opt_sec_spkmp, "spkm3p" }, + { Opt_sec_err, NULL } }; diff --git a/fs/nfsctl.c b/fs/nfsctl.c index 51f1b31acbf6..aed8145d9087 100644 --- a/fs/nfsctl.c +++ b/fs/nfsctl.c @@ -41,9 +41,9 @@ static struct file *do_open(char *name, int flags) error = may_open(&nd, MAY_WRITE, FMODE_WRITE); if (!error) - return dentry_open(nd.dentry, nd.mnt, flags); + return dentry_open(nd.path.dentry, nd.path.mnt, flags); - path_release(&nd); + path_put(&nd.path); return ERR_PTR(error); } diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c index 346570f6d848..8a6f7c924c75 100644 --- a/fs/nfsd/export.c +++ b/fs/nfsd/export.c @@ -63,10 +63,8 @@ static void expkey_put(struct kref *ref) struct svc_expkey *key = container_of(ref, struct svc_expkey, h.ref); if (test_bit(CACHE_VALID, &key->h.flags) && - !test_bit(CACHE_NEGATIVE, &key->h.flags)) { - dput(key->ek_dentry); - mntput(key->ek_mnt); - } + !test_bit(CACHE_NEGATIVE, &key->h.flags)) + path_put(&key->ek_path); auth_domain_put(key->ek_client); kfree(key); } @@ -169,15 +167,14 @@ static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen) goto out; dprintk("Found the path %s\n", buf); - key.ek_mnt = nd.mnt; - key.ek_dentry = nd.dentry; - + key.ek_path = nd.path; + ek = svc_expkey_update(&key, ek); if (ek) cache_put(&ek->h, &svc_expkey_cache); else err = -ENOMEM; - path_release(&nd); + path_put(&nd.path); } cache_flush(); out: @@ -206,7 +203,7 @@ static int expkey_show(struct seq_file *m, if (test_bit(CACHE_VALID, &h->flags) && !test_bit(CACHE_NEGATIVE, &h->flags)) { seq_printf(m, " "); - seq_path(m, ek->ek_mnt, ek->ek_dentry, "\\ \t\n"); + seq_path(m, &ek->ek_path, "\\ \t\n"); } seq_printf(m, "\n"); return 0; @@ -243,8 +240,8 @@ static inline void expkey_update(struct cache_head *cnew, struct svc_expkey *new = container_of(cnew, struct svc_expkey, h); struct svc_expkey *item = container_of(citem, struct svc_expkey, h); - new->ek_mnt = mntget(item->ek_mnt); - new->ek_dentry = dget(item->ek_dentry); + new->ek_path = item->ek_path; + path_get(&item->ek_path); } static struct cache_head *expkey_alloc(void) @@ -332,10 +329,9 @@ static void nfsd4_fslocs_free(struct nfsd4_fs_locations *fsloc) static void svc_export_put(struct kref *ref) { struct svc_export *exp = container_of(ref, struct svc_export, h.ref); - dput(exp->ex_dentry); - mntput(exp->ex_mnt); + path_put(&exp->ex_path); auth_domain_put(exp->ex_client); - kfree(exp->ex_path); + kfree(exp->ex_pathname); nfsd4_fslocs_free(&exp->ex_fslocs); kfree(exp); } @@ -349,7 +345,7 @@ static void svc_export_request(struct cache_detail *cd, char *pth; qword_add(bpp, blen, exp->ex_client->name); - pth = d_path(exp->ex_dentry, exp->ex_mnt, *bpp, *blen); + pth = d_path(&exp->ex_path, *bpp, *blen); if (IS_ERR(pth)) { /* is this correct? */ (*bpp)[0] = '\n'; @@ -507,8 +503,8 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen) struct svc_export exp, *expp; int an_int; - nd.dentry = NULL; - exp.ex_path = NULL; + nd.path.dentry = NULL; + exp.ex_pathname = NULL; /* fs locations */ exp.ex_fslocs.locations = NULL; @@ -547,11 +543,11 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen) exp.h.flags = 0; exp.ex_client = dom; - exp.ex_mnt = nd.mnt; - exp.ex_dentry = nd.dentry; - exp.ex_path = kstrdup(buf, GFP_KERNEL); + exp.ex_path.mnt = nd.path.mnt; + exp.ex_path.dentry = nd.path.dentry; + exp.ex_pathname = kstrdup(buf, GFP_KERNEL); err = -ENOMEM; - if (!exp.ex_path) + if (!exp.ex_pathname) goto out; /* expiry */ @@ -610,7 +606,7 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen) goto out; } - err = check_export(nd.dentry->d_inode, exp.ex_flags, + err = check_export(nd.path.dentry->d_inode, exp.ex_flags, exp.ex_uuid); if (err) goto out; } @@ -628,9 +624,9 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen) out: nfsd4_fslocs_free(&exp.ex_fslocs); kfree(exp.ex_uuid); - kfree(exp.ex_path); - if (nd.dentry) - path_release(&nd); + kfree(exp.ex_pathname); + if (nd.path.dentry) + path_put(&nd.path); out_no_path: if (dom) auth_domain_put(dom); @@ -653,7 +649,7 @@ static int svc_export_show(struct seq_file *m, return 0; } exp = container_of(h, struct svc_export, h); - seq_path(m, exp->ex_mnt, exp->ex_dentry, " \t\n\\"); + seq_path(m, &exp->ex_path, " \t\n\\"); seq_putc(m, '\t'); seq_escape(m, exp->ex_client->name, " \t\n\\"); seq_putc(m, '('); @@ -680,8 +676,8 @@ static int svc_export_match(struct cache_head *a, struct cache_head *b) struct svc_export *orig = container_of(a, struct svc_export, h); struct svc_export *new = container_of(b, struct svc_export, h); return orig->ex_client == new->ex_client && - orig->ex_dentry == new->ex_dentry && - orig->ex_mnt == new->ex_mnt; + orig->ex_path.dentry == new->ex_path.dentry && + orig->ex_path.mnt == new->ex_path.mnt; } static void svc_export_init(struct cache_head *cnew, struct cache_head *citem) @@ -691,9 +687,9 @@ static void svc_export_init(struct cache_head *cnew, struct cache_head *citem) kref_get(&item->ex_client->ref); new->ex_client = item->ex_client; - new->ex_dentry = dget(item->ex_dentry); - new->ex_mnt = mntget(item->ex_mnt); - new->ex_path = NULL; + new->ex_path.dentry = dget(item->ex_path.dentry); + new->ex_path.mnt = mntget(item->ex_path.mnt); + new->ex_pathname = NULL; new->ex_fslocs.locations = NULL; new->ex_fslocs.locations_count = 0; new->ex_fslocs.migrated = 0; @@ -711,8 +707,8 @@ static void export_update(struct cache_head *cnew, struct cache_head *citem) new->ex_fsid = item->ex_fsid; new->ex_uuid = item->ex_uuid; item->ex_uuid = NULL; - new->ex_path = item->ex_path; - item->ex_path = NULL; + new->ex_pathname = item->ex_pathname; + item->ex_pathname = NULL; new->ex_fslocs.locations = item->ex_fslocs.locations; item->ex_fslocs.locations = NULL; new->ex_fslocs.locations_count = item->ex_fslocs.locations_count; @@ -755,8 +751,8 @@ svc_export_lookup(struct svc_export *exp) struct cache_head *ch; int hash; hash = hash_ptr(exp->ex_client, EXPORT_HASHBITS); - hash ^= hash_ptr(exp->ex_dentry, EXPORT_HASHBITS); - hash ^= hash_ptr(exp->ex_mnt, EXPORT_HASHBITS); + hash ^= hash_ptr(exp->ex_path.dentry, EXPORT_HASHBITS); + hash ^= hash_ptr(exp->ex_path.mnt, EXPORT_HASHBITS); ch = sunrpc_cache_lookup(&svc_export_cache, &exp->h, hash); @@ -772,8 +768,8 @@ svc_export_update(struct svc_export *new, struct svc_export *old) struct cache_head *ch; int hash; hash = hash_ptr(old->ex_client, EXPORT_HASHBITS); - hash ^= hash_ptr(old->ex_dentry, EXPORT_HASHBITS); - hash ^= hash_ptr(old->ex_mnt, EXPORT_HASHBITS); + hash ^= hash_ptr(old->ex_path.dentry, EXPORT_HASHBITS); + hash ^= hash_ptr(old->ex_path.mnt, EXPORT_HASHBITS); ch = sunrpc_cache_update(&svc_export_cache, &new->h, &old->h, @@ -815,8 +811,7 @@ static int exp_set_key(svc_client *clp, int fsid_type, u32 *fsidv, key.ek_client = clp; key.ek_fsidtype = fsid_type; memcpy(key.ek_fsid, fsidv, key_len(fsid_type)); - key.ek_mnt = exp->ex_mnt; - key.ek_dentry = exp->ex_dentry; + key.ek_path = exp->ex_path; key.h.expiry_time = NEVER; key.h.flags = 0; @@ -865,13 +860,13 @@ static svc_export *exp_get_by_name(svc_client *clp, struct vfsmount *mnt, { struct svc_export *exp, key; int err; - + if (!clp) return ERR_PTR(-ENOENT); key.ex_client = clp; - key.ex_mnt = mnt; - key.ex_dentry = dentry; + key.ex_path.mnt = mnt; + key.ex_path.dentry = dentry; exp = svc_export_lookup(&key); if (exp == NULL) @@ -968,7 +963,7 @@ static int exp_fsid_hash(svc_client *clp, struct svc_export *exp) static int exp_hash(struct auth_domain *clp, struct svc_export *exp) { u32 fsid[2]; - struct inode *inode = exp->ex_dentry->d_inode; + struct inode *inode = exp->ex_path.dentry->d_inode; dev_t dev = inode->i_sb->s_dev; if (old_valid_dev(dev)) { @@ -982,7 +977,7 @@ static int exp_hash(struct auth_domain *clp, struct svc_export *exp) static void exp_unhash(struct svc_export *exp) { struct svc_expkey *ek; - struct inode *inode = exp->ex_dentry->d_inode; + struct inode *inode = exp->ex_path.dentry->d_inode; ek = exp_get_key(exp->ex_client, inode->i_sb->s_dev, inode->i_ino); if (!IS_ERR(ek)) { @@ -1030,15 +1025,16 @@ exp_export(struct nfsctl_export *nxp) goto out_unlock; err = -EINVAL; - exp = exp_get_by_name(clp, nd.mnt, nd.dentry, NULL); + exp = exp_get_by_name(clp, nd.path.mnt, nd.path.dentry, NULL); memset(&new, 0, sizeof(new)); /* must make sure there won't be an ex_fsid clash */ if ((nxp->ex_flags & NFSEXP_FSID) && (!IS_ERR(fsid_key = exp_get_fsid_key(clp, nxp->ex_dev))) && - fsid_key->ek_mnt && - (fsid_key->ek_mnt != nd.mnt || fsid_key->ek_dentry != nd.dentry) ) + fsid_key->ek_path.mnt && + (fsid_key->ek_path.mnt != nd.path.mnt || + fsid_key->ek_path.dentry != nd.path.dentry)) goto finish; if (!IS_ERR(exp)) { @@ -1054,7 +1050,7 @@ exp_export(struct nfsctl_export *nxp) goto finish; } - err = check_export(nd.dentry->d_inode, nxp->ex_flags, NULL); + err = check_export(nd.path.dentry->d_inode, nxp->ex_flags, NULL); if (err) goto finish; err = -ENOMEM; @@ -1063,12 +1059,11 @@ exp_export(struct nfsctl_export *nxp) new.h.expiry_time = NEVER; new.h.flags = 0; - new.ex_path = kstrdup(nxp->ex_path, GFP_KERNEL); - if (!new.ex_path) + new.ex_pathname = kstrdup(nxp->ex_path, GFP_KERNEL); + if (!new.ex_pathname) goto finish; new.ex_client = clp; - new.ex_mnt = nd.mnt; - new.ex_dentry = nd.dentry; + new.ex_path = nd.path; new.ex_flags = nxp->ex_flags; new.ex_anon_uid = nxp->ex_anon_uid; new.ex_anon_gid = nxp->ex_anon_gid; @@ -1089,15 +1084,14 @@ exp_export(struct nfsctl_export *nxp) } else err = 0; finish: - if (new.ex_path) - kfree(new.ex_path); + kfree(new.ex_pathname); if (exp) exp_put(exp); if (fsid_key && !IS_ERR(fsid_key)) cache_put(&fsid_key->h, &svc_expkey_cache); if (clp) auth_domain_put(clp); - path_release(&nd); + path_put(&nd.path); out_unlock: exp_writeunlock(); out: @@ -1148,8 +1142,8 @@ exp_unexport(struct nfsctl_export *nxp) goto out_domain; err = -EINVAL; - exp = exp_get_by_name(dom, nd.mnt, nd.dentry, NULL); - path_release(&nd); + exp = exp_get_by_name(dom, nd.path.mnt, nd.path.dentry, NULL); + path_put(&nd.path); if (IS_ERR(exp)) goto out_domain; @@ -1185,12 +1179,12 @@ exp_rootfh(svc_client *clp, char *path, struct knfsd_fh *f, int maxsize) printk("nfsd: exp_rootfh path not found %s", path); return err; } - inode = nd.dentry->d_inode; + inode = nd.path.dentry->d_inode; dprintk("nfsd: exp_rootfh(%s [%p] %s:%s/%ld)\n", - path, nd.dentry, clp->name, + path, nd.path.dentry, clp->name, inode->i_sb->s_id, inode->i_ino); - exp = exp_parent(clp, nd.mnt, nd.dentry, NULL); + exp = exp_parent(clp, nd.path.mnt, nd.path.dentry, NULL); if (IS_ERR(exp)) { err = PTR_ERR(exp); goto out; @@ -1200,7 +1194,7 @@ exp_rootfh(svc_client *clp, char *path, struct knfsd_fh *f, int maxsize) * fh must be initialized before calling fh_compose */ fh_init(&fh, maxsize); - if (fh_compose(&fh, exp, nd.dentry, NULL)) + if (fh_compose(&fh, exp, nd.path.dentry, NULL)) err = -EINVAL; else err = 0; @@ -1208,7 +1202,7 @@ exp_rootfh(svc_client *clp, char *path, struct knfsd_fh *f, int maxsize) fh_put(&fh); exp_put(exp); out: - path_release(&nd); + path_put(&nd.path); return err; } @@ -1220,7 +1214,7 @@ static struct svc_export *exp_find(struct auth_domain *clp, int fsid_type, if (IS_ERR(ek)) return ERR_CAST(ek); - exp = exp_get_by_name(clp, ek->ek_mnt, ek->ek_dentry, reqp); + exp = exp_get_by_name(clp, ek->ek_path.mnt, ek->ek_path.dentry, reqp); cache_put(&ek->h, &svc_expkey_cache); if (IS_ERR(exp)) @@ -1359,7 +1353,7 @@ exp_pseudoroot(struct svc_rqst *rqstp, struct svc_fh *fhp) exp = rqst_exp_find(rqstp, FSID_NUM, fsidv); if (IS_ERR(exp)) return nfserrno(PTR_ERR(exp)); - rv = fh_compose(fhp, exp, exp->ex_dentry, NULL); + rv = fh_compose(fhp, exp, exp->ex_path.dentry, NULL); if (rv) goto out; rv = check_nfsd_access(exp, rqstp); diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c index eac82830bfd7..c721a1e6e9dd 100644 --- a/fs/nfsd/nfs3proc.c +++ b/fs/nfsd/nfs3proc.c @@ -67,7 +67,7 @@ nfsd3_proc_getattr(struct svc_rqst *rqstp, struct nfsd_fhandle *argp, if (nfserr) RETURN_STATUS(nfserr); - err = vfs_getattr(resp->fh.fh_export->ex_mnt, + err = vfs_getattr(resp->fh.fh_export->ex_path.mnt, resp->fh.fh_dentry, &resp->stat); nfserr = nfserrno(err); diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c index d7647f70e02b..17d0dd997204 100644 --- a/fs/nfsd/nfs3xdr.c +++ b/fs/nfsd/nfs3xdr.c @@ -218,7 +218,7 @@ encode_post_op_attr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp) int err; struct kstat stat; - err = vfs_getattr(fhp->fh_export->ex_mnt, dentry, &stat); + err = vfs_getattr(fhp->fh_export->ex_path.mnt, dentry, &stat); if (!err) { *p++ = xdr_one; /* attributes follow */ lease_get_mtime(dentry->d_inode, &stat.mtime); @@ -270,7 +270,7 @@ void fill_post_wcc(struct svc_fh *fhp) if (fhp->fh_post_saved) printk("nfsd: inode locked twice during operation.\n"); - err = vfs_getattr(fhp->fh_export->ex_mnt, fhp->fh_dentry, + err = vfs_getattr(fhp->fh_export->ex_path.mnt, fhp->fh_dentry, &fhp->fh_post_attr); if (err) fhp->fh_post_saved = 0; diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c index 1602cd00dd45..1ff90625860f 100644 --- a/fs/nfsd/nfs4recover.c +++ b/fs/nfsd/nfs4recover.c @@ -120,9 +120,9 @@ out_no_tfm: static void nfsd4_sync_rec_dir(void) { - mutex_lock(&rec_dir.dentry->d_inode->i_mutex); - nfsd_sync_dir(rec_dir.dentry); - mutex_unlock(&rec_dir.dentry->d_inode->i_mutex); + mutex_lock(&rec_dir.path.dentry->d_inode->i_mutex); + nfsd_sync_dir(rec_dir.path.dentry); + mutex_unlock(&rec_dir.path.dentry->d_inode->i_mutex); } int @@ -142,9 +142,9 @@ nfsd4_create_clid_dir(struct nfs4_client *clp) nfs4_save_user(&uid, &gid); /* lock the parent */ - mutex_lock(&rec_dir.dentry->d_inode->i_mutex); + mutex_lock(&rec_dir.path.dentry->d_inode->i_mutex); - dentry = lookup_one_len(dname, rec_dir.dentry, HEXDIR_LEN-1); + dentry = lookup_one_len(dname, rec_dir.path.dentry, HEXDIR_LEN-1); if (IS_ERR(dentry)) { status = PTR_ERR(dentry); goto out_unlock; @@ -154,11 +154,11 @@ nfsd4_create_clid_dir(struct nfs4_client *clp) dprintk("NFSD: nfsd4_create_clid_dir: DIRECTORY EXISTS\n"); goto out_put; } - status = vfs_mkdir(rec_dir.dentry->d_inode, dentry, S_IRWXU); + status = vfs_mkdir(rec_dir.path.dentry->d_inode, dentry, S_IRWXU); out_put: dput(dentry); out_unlock: - mutex_unlock(&rec_dir.dentry->d_inode->i_mutex); + mutex_unlock(&rec_dir.path.dentry->d_inode->i_mutex); if (status == 0) { clp->cl_firststate = 1; nfsd4_sync_rec_dir(); @@ -221,7 +221,7 @@ nfsd4_list_rec_dir(struct dentry *dir, recdir_func *f) nfs4_save_user(&uid, &gid); - filp = dentry_open(dget(dir), mntget(rec_dir.mnt), O_RDONLY); + filp = dentry_open(dget(dir), mntget(rec_dir.path.mnt), O_RDONLY); status = PTR_ERR(filp); if (IS_ERR(filp)) goto out; @@ -286,9 +286,9 @@ nfsd4_unlink_clid_dir(char *name, int namlen) dprintk("NFSD: nfsd4_unlink_clid_dir. name %.*s\n", namlen, name); - mutex_lock(&rec_dir.dentry->d_inode->i_mutex); - dentry = lookup_one_len(name, rec_dir.dentry, namlen); - mutex_unlock(&rec_dir.dentry->d_inode->i_mutex); + mutex_lock(&rec_dir.path.dentry->d_inode->i_mutex); + dentry = lookup_one_len(name, rec_dir.path.dentry, namlen); + mutex_unlock(&rec_dir.path.dentry->d_inode->i_mutex); if (IS_ERR(dentry)) { status = PTR_ERR(dentry); return status; @@ -297,7 +297,7 @@ nfsd4_unlink_clid_dir(char *name, int namlen) if (!dentry->d_inode) goto out; - status = nfsd4_clear_clid_dir(rec_dir.dentry, dentry); + status = nfsd4_clear_clid_dir(rec_dir.path.dentry, dentry); out: dput(dentry); return status; @@ -347,12 +347,12 @@ nfsd4_recdir_purge_old(void) { if (!rec_dir_init) return; - status = nfsd4_list_rec_dir(rec_dir.dentry, purge_old); + status = nfsd4_list_rec_dir(rec_dir.path.dentry, purge_old); if (status == 0) nfsd4_sync_rec_dir(); if (status) printk("nfsd4: failed to purge old clients from recovery" - " directory %s\n", rec_dir.dentry->d_name.name); + " directory %s\n", rec_dir.path.dentry->d_name.name); return; } @@ -373,10 +373,10 @@ int nfsd4_recdir_load(void) { int status; - status = nfsd4_list_rec_dir(rec_dir.dentry, load_recdir); + status = nfsd4_list_rec_dir(rec_dir.path.dentry, load_recdir); if (status) printk("nfsd4: failed loading clients from recovery" - " directory %s\n", rec_dir.dentry->d_name.name); + " directory %s\n", rec_dir.path.dentry->d_name.name); return status; } @@ -415,5 +415,5 @@ nfsd4_shutdown_recdir(void) if (!rec_dir_init) return; rec_dir_init = 0; - path_release(&rec_dir); + path_put(&rec_dir.path); } diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index f6744bc03dae..bcb97d8e8b8b 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -3261,11 +3261,11 @@ nfs4_reset_recoverydir(char *recdir) if (status) return status; status = -ENOTDIR; - if (S_ISDIR(nd.dentry->d_inode->i_mode)) { + if (S_ISDIR(nd.path.dentry->d_inode->i_mode)) { nfs4_set_recdir(recdir); status = 0; } - path_release(&nd); + path_put(&nd.path); return status; } diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index b0592e7c378d..0e6a179eccaf 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -1330,9 +1330,9 @@ static char *nfsd4_path(struct svc_rqst *rqstp, struct svc_export *exp, __be32 * *stat = exp_pseudoroot(rqstp, &tmp_fh); if (*stat) return NULL; - rootpath = tmp_fh.fh_export->ex_path; + rootpath = tmp_fh.fh_export->ex_pathname; - path = exp->ex_path; + path = exp->ex_pathname; if (strncmp(path, rootpath, strlen(rootpath))) { dprintk("nfsd: fs_locations failed;" @@ -1481,7 +1481,7 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp, goto out; } - err = vfs_getattr(exp->ex_mnt, dentry, &stat); + err = vfs_getattr(exp->ex_path.mnt, dentry, &stat); if (err) goto out_nfserr; if ((bmval0 & (FATTR4_WORD0_FILES_FREE | FATTR4_WORD0_FILES_TOTAL | @@ -1838,9 +1838,9 @@ out_acl: * and this is the root of a cross-mounted filesystem. */ if (ignore_crossmnt == 0 && - exp->ex_mnt->mnt_root->d_inode == dentry->d_inode) { - err = vfs_getattr(exp->ex_mnt->mnt_parent, - exp->ex_mnt->mnt_mountpoint, &stat); + exp->ex_path.mnt->mnt_root->d_inode == dentry->d_inode) { + err = vfs_getattr(exp->ex_path.mnt->mnt_parent, + exp->ex_path.mnt->mnt_mountpoint, &stat); if (err) goto out_nfserr; } diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c index 8fbd2dc08a92..0130b345234d 100644 --- a/fs/nfsd/nfsfh.c +++ b/fs/nfsd/nfsfh.c @@ -47,7 +47,7 @@ static int nfsd_acceptable(void *expv, struct dentry *dentry) return 1; tdentry = dget(dentry); - while (tdentry != exp->ex_dentry && ! IS_ROOT(tdentry)) { + while (tdentry != exp->ex_path.dentry && !IS_ROOT(tdentry)) { /* make sure parents give x permission to user */ int err; parent = dget_parent(tdentry); @@ -59,9 +59,9 @@ static int nfsd_acceptable(void *expv, struct dentry *dentry) dput(tdentry); tdentry = parent; } - if (tdentry != exp->ex_dentry) + if (tdentry != exp->ex_path.dentry) dprintk("nfsd_acceptable failed at %p %s\n", tdentry, tdentry->d_name.name); - rv = (tdentry == exp->ex_dentry); + rv = (tdentry == exp->ex_path.dentry); dput(tdentry); return rv; } @@ -209,9 +209,9 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access) fileid_type = fh->fh_fileid_type; if (fileid_type == FILEID_ROOT) - dentry = dget(exp->ex_dentry); + dentry = dget(exp->ex_path.dentry); else { - dentry = exportfs_decode_fh(exp->ex_mnt, fid, + dentry = exportfs_decode_fh(exp->ex_path.mnt, fid, data_left, fileid_type, nfsd_acceptable, exp); } @@ -299,7 +299,7 @@ out: static void _fh_update(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry) { - if (dentry != exp->ex_dentry) { + if (dentry != exp->ex_path.dentry) { struct fid *fid = (struct fid *) (fhp->fh_handle.fh_auth + fhp->fh_handle.fh_size/4 - 1); int maxsize = (fhp->fh_maxsize - fhp->fh_handle.fh_size)/4; @@ -344,12 +344,12 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, struct inode * inode = dentry->d_inode; struct dentry *parent = dentry->d_parent; __u32 *datap; - dev_t ex_dev = exp->ex_dentry->d_inode->i_sb->s_dev; - int root_export = (exp->ex_dentry == exp->ex_dentry->d_sb->s_root); + dev_t ex_dev = exp->ex_path.dentry->d_inode->i_sb->s_dev; + int root_export = (exp->ex_path.dentry == exp->ex_path.dentry->d_sb->s_root); dprintk("nfsd: fh_compose(exp %02x:%02x/%ld %s/%s, ino=%ld)\n", MAJOR(ex_dev), MINOR(ex_dev), - (long) exp->ex_dentry->d_inode->i_ino, + (long) exp->ex_path.dentry->d_inode->i_ino, parent->d_name.name, dentry->d_name.name, (inode ? inode->i_ino : 0)); @@ -391,7 +391,7 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, /* FALL THROUGH */ case FSID_MAJOR_MINOR: case FSID_ENCODE_DEV: - if (!(exp->ex_dentry->d_inode->i_sb->s_type->fs_flags + if (!(exp->ex_path.dentry->d_inode->i_sb->s_type->fs_flags & FS_REQUIRES_DEV)) goto retry; break; @@ -454,7 +454,7 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, fhp->fh_handle.ofh_dev = old_encode_dev(ex_dev); fhp->fh_handle.ofh_xdev = fhp->fh_handle.ofh_dev; fhp->fh_handle.ofh_xino = - ino_t_to_u32(exp->ex_dentry->d_inode->i_ino); + ino_t_to_u32(exp->ex_path.dentry->d_inode->i_ino); fhp->fh_handle.ofh_dirino = ino_t_to_u32(parent_ino(dentry)); if (inode) _fh_update_old(dentry, exp, &fhp->fh_handle); @@ -465,7 +465,7 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, datap = fhp->fh_handle.fh_auth+0; fhp->fh_handle.fh_fsid_type = fsid_type; mk_fsid(fsid_type, datap, ex_dev, - exp->ex_dentry->d_inode->i_ino, + exp->ex_path.dentry->d_inode->i_ino, exp->ex_fsid, exp->ex_uuid); len = key_len(fsid_type); @@ -571,7 +571,7 @@ enum fsid_source fsid_source(struct svc_fh *fhp) case FSID_DEV: case FSID_ENCODE_DEV: case FSID_MAJOR_MINOR: - if (fhp->fh_export->ex_dentry->d_inode->i_sb->s_type->fs_flags + if (fhp->fh_export->ex_path.dentry->d_inode->i_sb->s_type->fs_flags & FS_REQUIRES_DEV) return FSIDSOURCE_DEV; break; diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c index 977a71f64e19..6cfc96a12483 100644 --- a/fs/nfsd/nfsproc.c +++ b/fs/nfsd/nfsproc.c @@ -41,7 +41,7 @@ static __be32 nfsd_return_attrs(__be32 err, struct nfsd_attrstat *resp) { if (err) return err; - return nfserrno(vfs_getattr(resp->fh.fh_export->ex_mnt, + return nfserrno(vfs_getattr(resp->fh.fh_export->ex_path.mnt, resp->fh.fh_dentry, &resp->stat)); } @@ -49,7 +49,7 @@ static __be32 nfsd_return_dirop(__be32 err, struct nfsd_diropres *resp) { if (err) return err; - return nfserrno(vfs_getattr(resp->fh.fh_export->ex_mnt, + return nfserrno(vfs_getattr(resp->fh.fh_export->ex_path.mnt, resp->fh.fh_dentry, &resp->stat)); } @@ -164,7 +164,7 @@ nfsd_proc_read(struct svc_rqst *rqstp, struct nfsd_readargs *argp, &resp->count); if (nfserr) return nfserr; - return nfserrno(vfs_getattr(resp->fh.fh_export->ex_mnt, + return nfserrno(vfs_getattr(resp->fh.fh_export->ex_path.mnt, resp->fh.fh_dentry, &resp->stat)); } diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c index 61ad61743d94..afd08e2c90a5 100644 --- a/fs/nfsd/nfsxdr.c +++ b/fs/nfsd/nfsxdr.c @@ -207,7 +207,7 @@ encode_fattr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp, __be32 *nfs2svc_encode_fattr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp) { struct kstat stat; - vfs_getattr(fhp->fh_export->ex_mnt, fhp->fh_dentry, &stat); + vfs_getattr(fhp->fh_export->ex_path.mnt, fhp->fh_dentry, &stat); return encode_fattr(rqstp, p, fhp, &stat); } diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index cc75e4fcd02b..46f59d5365a0 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -101,7 +101,7 @@ nfsd_cross_mnt(struct svc_rqst *rqstp, struct dentry **dpp, { struct svc_export *exp = *expp, *exp2 = NULL; struct dentry *dentry = *dpp; - struct vfsmount *mnt = mntget(exp->ex_mnt); + struct vfsmount *mnt = mntget(exp->ex_path.mnt); struct dentry *mounts = dget(dentry); int err = 0; @@ -156,15 +156,15 @@ nfsd_lookup_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp, if (isdotent(name, len)) { if (len==1) dentry = dget(dparent); - else if (dparent != exp->ex_dentry) { + else if (dparent != exp->ex_path.dentry) dentry = dget_parent(dparent); - } else if (!EX_NOHIDE(exp)) + else if (!EX_NOHIDE(exp)) dentry = dget(dparent); /* .. == . just like at / */ else { /* checking mountpoint crossing is very different when stepping up */ struct svc_export *exp2 = NULL; struct dentry *dp; - struct vfsmount *mnt = mntget(exp->ex_mnt); + struct vfsmount *mnt = mntget(exp->ex_path.mnt); dentry = dget(dparent); while(dentry == mnt->mnt_root && follow_up(&mnt, &dentry)) ; @@ -721,7 +721,8 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, DQUOT_INIT(inode); } - *filp = dentry_open(dget(dentry), mntget(fhp->fh_export->ex_mnt), flags); + *filp = dentry_open(dget(dentry), mntget(fhp->fh_export->ex_path.mnt), + flags); if (IS_ERR(*filp)) host_err = PTR_ERR(*filp); out_nfserr: @@ -1462,7 +1463,7 @@ nfsd_readlink(struct svc_rqst *rqstp, struct svc_fh *fhp, char *buf, int *lenp) if (!inode->i_op || !inode->i_op->readlink) goto out; - touch_atime(fhp->fh_export->ex_mnt, dentry); + touch_atime(fhp->fh_export->ex_path.mnt, dentry); /* N.B. Why does this call need a get_fs()?? * Remove the set_fs and watch the fireworks:-) --okir */ diff --git a/fs/open.c b/fs/open.c index 43fcd6031969..54198538b67e 100644 --- a/fs/open.c +++ b/fs/open.c @@ -127,10 +127,10 @@ asmlinkage long sys_statfs(const char __user * path, struct statfs __user * buf) error = user_path_walk(path, &nd); if (!error) { struct statfs tmp; - error = vfs_statfs_native(nd.dentry, &tmp); + error = vfs_statfs_native(nd.path.dentry, &tmp); if (!error && copy_to_user(buf, &tmp, sizeof(tmp))) error = -EFAULT; - path_release(&nd); + path_put(&nd.path); } return error; } @@ -146,10 +146,10 @@ asmlinkage long sys_statfs64(const char __user *path, size_t sz, struct statfs64 error = user_path_walk(path, &nd); if (!error) { struct statfs64 tmp; - error = vfs_statfs64(nd.dentry, &tmp); + error = vfs_statfs64(nd.path.dentry, &tmp); if (!error && copy_to_user(buf, &tmp, sizeof(tmp))) error = -EFAULT; - path_release(&nd); + path_put(&nd.path); } return error; } @@ -233,7 +233,7 @@ static long do_sys_truncate(const char __user * path, loff_t length) error = user_path_walk(path, &nd); if (error) goto out; - inode = nd.dentry->d_inode; + inode = nd.path.dentry->d_inode; /* For directories it's -EISDIR, for other non-regulars - -EINVAL */ error = -EISDIR; @@ -271,13 +271,13 @@ static long do_sys_truncate(const char __user * path, loff_t length) error = locks_verify_truncate(inode, NULL, length); if (!error) { DQUOT_INIT(inode); - error = do_truncate(nd.dentry, length, 0, NULL); + error = do_truncate(nd.path.dentry, length, 0, NULL); } put_write_and_out: put_write_access(inode); dput_and_out: - path_release(&nd); + path_put(&nd.path); out: return error; } @@ -455,14 +455,14 @@ asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode) res = vfs_permission(&nd, mode); /* SuS v2 requires we report a read only fs too */ if(res || !(mode & S_IWOTH) || - special_file(nd.dentry->d_inode->i_mode)) + special_file(nd.path.dentry->d_inode->i_mode)) goto out_path_release; - if(IS_RDONLY(nd.dentry->d_inode)) + if(IS_RDONLY(nd.path.dentry->d_inode)) res = -EROFS; out_path_release: - path_release(&nd); + path_put(&nd.path); out: current->fsuid = old_fsuid; current->fsgid = old_fsgid; @@ -490,10 +490,10 @@ asmlinkage long sys_chdir(const char __user * filename) if (error) goto dput_and_out; - set_fs_pwd(current->fs, nd.mnt, nd.dentry); + set_fs_pwd(current->fs, &nd.path); dput_and_out: - path_release(&nd); + path_put(&nd.path); out: return error; } @@ -501,9 +501,7 @@ out: asmlinkage long sys_fchdir(unsigned int fd) { struct file *file; - struct dentry *dentry; struct inode *inode; - struct vfsmount *mnt; int error; error = -EBADF; @@ -511,9 +509,7 @@ asmlinkage long sys_fchdir(unsigned int fd) if (!file) goto out; - dentry = file->f_path.dentry; - mnt = file->f_path.mnt; - inode = dentry->d_inode; + inode = file->f_path.dentry->d_inode; error = -ENOTDIR; if (!S_ISDIR(inode->i_mode)) @@ -521,7 +517,7 @@ asmlinkage long sys_fchdir(unsigned int fd) error = file_permission(file, MAY_EXEC); if (!error) - set_fs_pwd(current->fs, mnt, dentry); + set_fs_pwd(current->fs, &file->f_path); out_putf: fput(file); out: @@ -545,11 +541,11 @@ asmlinkage long sys_chroot(const char __user * filename) if (!capable(CAP_SYS_CHROOT)) goto dput_and_out; - set_fs_root(current->fs, nd.mnt, nd.dentry); + set_fs_root(current->fs, &nd.path); set_fs_altroot(); error = 0; dput_and_out: - path_release(&nd); + path_put(&nd.path); out: return error; } @@ -602,7 +598,7 @@ asmlinkage long sys_fchmodat(int dfd, const char __user *filename, error = __user_walk_fd(dfd, filename, LOOKUP_FOLLOW, &nd); if (error) goto out; - inode = nd.dentry->d_inode; + inode = nd.path.dentry->d_inode; error = -EROFS; if (IS_RDONLY(inode)) @@ -617,11 +613,11 @@ asmlinkage long sys_fchmodat(int dfd, const char __user *filename, mode = inode->i_mode; newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; - error = notify_change(nd.dentry, &newattrs); + error = notify_change(nd.path.dentry, &newattrs); mutex_unlock(&inode->i_mutex); dput_and_out: - path_release(&nd); + path_put(&nd.path); out: return error; } @@ -675,8 +671,8 @@ asmlinkage long sys_chown(const char __user * filename, uid_t user, gid_t group) error = user_path_walk(filename, &nd); if (error) goto out; - error = chown_common(nd.dentry, user, group); - path_release(&nd); + error = chown_common(nd.path.dentry, user, group); + path_put(&nd.path); out: return error; } @@ -695,8 +691,8 @@ asmlinkage long sys_fchownat(int dfd, const char __user *filename, uid_t user, error = __user_walk_fd(dfd, filename, follow, &nd); if (error) goto out; - error = chown_common(nd.dentry, user, group); - path_release(&nd); + error = chown_common(nd.path.dentry, user, group); + path_put(&nd.path); out: return error; } @@ -709,8 +705,8 @@ asmlinkage long sys_lchown(const char __user * filename, uid_t user, gid_t group error = user_path_walk_link(filename, &nd); if (error) goto out; - error = chown_common(nd.dentry, user, group); - path_release(&nd); + error = chown_common(nd.path.dentry, user, group); + path_put(&nd.path); out: return error; } @@ -863,7 +859,7 @@ struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry *dentry goto out; if (IS_ERR(dentry)) goto out_err; - nd->intent.open.file = __dentry_open(dget(dentry), mntget(nd->mnt), + nd->intent.open.file = __dentry_open(dget(dentry), mntget(nd->path.mnt), nd->intent.open.flags - 1, nd->intent.open.file, open); @@ -891,9 +887,10 @@ struct file *nameidata_to_filp(struct nameidata *nd, int flags) filp = nd->intent.open.file; /* Has the filesystem initialised the file for us? */ if (filp->f_path.dentry == NULL) - filp = __dentry_open(nd->dentry, nd->mnt, flags, filp, NULL); + filp = __dentry_open(nd->path.dentry, nd->path.mnt, flags, filp, + NULL); else - path_release(nd); + path_put(&nd->path); return filp; } diff --git a/fs/proc/base.c b/fs/proc/base.c index 7c6b4ec83cb7..88f8edf18258 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -153,7 +153,7 @@ static int get_nr_threads(struct task_struct *tsk) return count; } -static int proc_cwd_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt) +static int proc_cwd_link(struct inode *inode, struct path *path) { struct task_struct *task = get_proc_task(inode); struct fs_struct *fs = NULL; @@ -165,8 +165,8 @@ static int proc_cwd_link(struct inode *inode, struct dentry **dentry, struct vfs } if (fs) { read_lock(&fs->lock); - *mnt = mntget(fs->pwdmnt); - *dentry = dget(fs->pwd); + *path = fs->pwd; + path_get(&fs->pwd); read_unlock(&fs->lock); result = 0; put_fs_struct(fs); @@ -174,7 +174,7 @@ static int proc_cwd_link(struct inode *inode, struct dentry **dentry, struct vfs return result; } -static int proc_root_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt) +static int proc_root_link(struct inode *inode, struct path *path) { struct task_struct *task = get_proc_task(inode); struct fs_struct *fs = NULL; @@ -186,8 +186,8 @@ static int proc_root_link(struct inode *inode, struct dentry **dentry, struct vf } if (fs) { read_lock(&fs->lock); - *mnt = mntget(fs->rootmnt); - *dentry = dget(fs->root); + *path = fs->root; + path_get(&fs->root); read_unlock(&fs->lock); result = 0; put_fs_struct(fs); @@ -1164,39 +1164,36 @@ static void *proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd) int error = -EACCES; /* We don't need a base pointer in the /proc filesystem */ - path_release(nd); + path_put(&nd->path); /* Are we allowed to snoop on the tasks file descriptors? */ if (!proc_fd_access_allowed(inode)) goto out; - error = PROC_I(inode)->op.proc_get_link(inode, &nd->dentry, &nd->mnt); + error = PROC_I(inode)->op.proc_get_link(inode, &nd->path); nd->last_type = LAST_BIND; out: return ERR_PTR(error); } -static int do_proc_readlink(struct dentry *dentry, struct vfsmount *mnt, - char __user *buffer, int buflen) +static int do_proc_readlink(struct path *path, char __user *buffer, int buflen) { - struct inode * inode; char *tmp = (char*)__get_free_page(GFP_TEMPORARY); - char *path; + char *pathname; int len; if (!tmp) return -ENOMEM; - inode = dentry->d_inode; - path = d_path(dentry, mnt, tmp, PAGE_SIZE); - len = PTR_ERR(path); - if (IS_ERR(path)) + pathname = d_path(path, tmp, PAGE_SIZE); + len = PTR_ERR(pathname); + if (IS_ERR(pathname)) goto out; - len = tmp + PAGE_SIZE - 1 - path; + len = tmp + PAGE_SIZE - 1 - pathname; if (len > buflen) len = buflen; - if (copy_to_user(buffer, path, len)) + if (copy_to_user(buffer, pathname, len)) len = -EFAULT; out: free_page((unsigned long)tmp); @@ -1207,20 +1204,18 @@ static int proc_pid_readlink(struct dentry * dentry, char __user * buffer, int b { int error = -EACCES; struct inode *inode = dentry->d_inode; - struct dentry *de; - struct vfsmount *mnt = NULL; + struct path path; /* Are we allowed to snoop on the tasks file descriptors? */ if (!proc_fd_access_allowed(inode)) goto out; - error = PROC_I(inode)->op.proc_get_link(inode, &de, &mnt); + error = PROC_I(inode)->op.proc_get_link(inode, &path); if (error) goto out; - error = do_proc_readlink(de, mnt, buffer, buflen); - dput(de); - mntput(mnt); + error = do_proc_readlink(&path, buffer, buflen); + path_put(&path); out: return error; } @@ -1447,8 +1442,7 @@ out: #define PROC_FDINFO_MAX 64 -static int proc_fd_info(struct inode *inode, struct dentry **dentry, - struct vfsmount **mnt, char *info) +static int proc_fd_info(struct inode *inode, struct path *path, char *info) { struct task_struct *task = get_proc_task(inode); struct files_struct *files = NULL; @@ -1467,10 +1461,10 @@ static int proc_fd_info(struct inode *inode, struct dentry **dentry, spin_lock(&files->file_lock); file = fcheck_files(files, fd); if (file) { - if (mnt) - *mnt = mntget(file->f_path.mnt); - if (dentry) - *dentry = dget(file->f_path.dentry); + if (path) { + *path = file->f_path; + path_get(&file->f_path); + } if (info) snprintf(info, PROC_FDINFO_MAX, "pos:\t%lli\n" @@ -1487,10 +1481,9 @@ static int proc_fd_info(struct inode *inode, struct dentry **dentry, return -ENOENT; } -static int proc_fd_link(struct inode *inode, struct dentry **dentry, - struct vfsmount **mnt) +static int proc_fd_link(struct inode *inode, struct path *path) { - return proc_fd_info(inode, dentry, mnt, NULL); + return proc_fd_info(inode, path, NULL); } static int tid_fd_revalidate(struct dentry *dentry, struct nameidata *nd) @@ -1684,7 +1677,7 @@ static ssize_t proc_fdinfo_read(struct file *file, char __user *buf, size_t len, loff_t *ppos) { char tmp[PROC_FDINFO_MAX]; - int err = proc_fd_info(file->f_path.dentry->d_inode, NULL, NULL, tmp); + int err = proc_fd_info(file->f_path.dentry->d_inode, NULL, tmp); if (!err) err = simple_read_from_buffer(buf, len, ppos, tmp, strlen(tmp)); return err; diff --git a/fs/proc/internal.h b/fs/proc/internal.h index ea496ffeabe7..1c81c8f1aeed 100644 --- a/fs/proc/internal.h +++ b/fs/proc/internal.h @@ -48,7 +48,7 @@ extern int maps_protect; extern void create_seq_entry(char *name, mode_t mode, const struct file_operations *f); -extern int proc_exe_link(struct inode *, struct dentry **, struct vfsmount **); +extern int proc_exe_link(struct inode *, struct path *); extern int proc_tid_stat(struct seq_file *m, struct pid_namespace *ns, struct pid *pid, struct task_struct *task); extern int proc_tgid_stat(struct seq_file *m, struct pid_namespace *ns, diff --git a/fs/proc/nommu.c b/fs/proc/nommu.c index 5d9147b9d738..941e95114b5a 100644 --- a/fs/proc/nommu.c +++ b/fs/proc/nommu.c @@ -67,7 +67,7 @@ int nommu_vma_show(struct seq_file *m, struct vm_area_struct *vma) if (len < 1) len = 1; seq_printf(m, "%*c", len, ' '); - seq_path(m, file->f_path.mnt, file->f_path.dentry, ""); + seq_path(m, &file->f_path, ""); } seq_putc(m, '\n'); diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c index b9cb23c08f63..614c34b6d1c2 100644 --- a/fs/proc/proc_sysctl.c +++ b/fs/proc/proc_sysctl.c @@ -407,7 +407,7 @@ static int proc_sys_permission(struct inode *inode, int mask, struct nameidata * if (!nd || !depth) goto out; - dentry = nd->dentry; + dentry = nd->path.dentry; table = do_proc_sys_lookup(dentry->d_parent, &dentry->d_name, &head); /* If the entry does not exist deny permission */ diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index ae4d3f2c8cb2..49958cffbd8d 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -75,7 +75,7 @@ int task_statm(struct mm_struct *mm, int *shared, int *text, return mm->total_vm; } -int proc_exe_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt) +int proc_exe_link(struct inode *inode, struct path *path) { struct vm_area_struct * vma; int result = -ENOENT; @@ -98,8 +98,8 @@ int proc_exe_link(struct inode *inode, struct dentry **dentry, struct vfsmount * } if (vma) { - *mnt = mntget(vma->vm_file->f_path.mnt); - *dentry = dget(vma->vm_file->f_path.dentry); + *path = vma->vm_file->f_path; + path_get(&vma->vm_file->f_path); result = 0; } @@ -271,7 +271,7 @@ static int show_map(struct seq_file *m, void *v) */ if (file) { pad_len_spaces(m, len); - seq_path(m, file->f_path.mnt, file->f_path.dentry, "\n"); + seq_path(m, &file->f_path, "\n"); } else { const char *name = arch_vma_name(vma); if (!name) { diff --git a/fs/proc/task_nommu.c b/fs/proc/task_nommu.c index abfc6f5e56ca..8011528518bd 100644 --- a/fs/proc/task_nommu.c +++ b/fs/proc/task_nommu.c @@ -103,7 +103,7 @@ int task_statm(struct mm_struct *mm, int *shared, int *text, return size; } -int proc_exe_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt) +int proc_exe_link(struct inode *inode, struct path *path) { struct vm_list_struct *vml; struct vm_area_struct *vma; @@ -126,8 +126,8 @@ int proc_exe_link(struct inode *inode, struct dentry **dentry, struct vfsmount * } if (vma) { - *mnt = mntget(vma->vm_file->f_path.mnt); - *dentry = dget(vma->vm_file->f_path.dentry); + *path = vma->vm_file->f_path; + path_get(&vma->vm_file->f_path); result = 0; } diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index 6033f0c3bd0b..6841452e0dea 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c @@ -2026,29 +2026,29 @@ static int reiserfs_quota_on(struct super_block *sb, int type, int format_id, if (err) return err; /* Quotafile not on the same filesystem? */ - if (nd.mnt->mnt_sb != sb) { - path_release(&nd); + if (nd.path.mnt->mnt_sb != sb) { + path_put(&nd.path); return -EXDEV; } /* We must not pack tails for quota files on reiserfs for quota IO to work */ - if (!REISERFS_I(nd.dentry->d_inode)->i_flags & i_nopack_mask) { + if (!REISERFS_I(nd.path.dentry->d_inode)->i_flags & i_nopack_mask) { reiserfs_warning(sb, "reiserfs: Quota file must have tail packing disabled."); - path_release(&nd); + path_put(&nd.path); return -EINVAL; } /* Not journalling quota? No more tests needed... */ if (!REISERFS_SB(sb)->s_qf_names[USRQUOTA] && !REISERFS_SB(sb)->s_qf_names[GRPQUOTA]) { - path_release(&nd); + path_put(&nd.path); return vfs_quota_on(sb, type, format_id, path); } /* Quotafile not of fs root? */ - if (nd.dentry->d_parent->d_inode != sb->s_root->d_inode) + if (nd.path.dentry->d_parent->d_inode != sb->s_root->d_inode) reiserfs_warning(sb, "reiserfs: Quota file not on filesystem root. " "Journalled quota will not work."); - path_release(&nd); + path_put(&nd.path); return vfs_quota_on(sb, type, format_id, path); } diff --git a/fs/seq_file.c b/fs/seq_file.c index ca71c115bdaa..853770274f20 100644 --- a/fs/seq_file.c +++ b/fs/seq_file.c @@ -342,13 +342,11 @@ int seq_printf(struct seq_file *m, const char *f, ...) } EXPORT_SYMBOL(seq_printf); -int seq_path(struct seq_file *m, - struct vfsmount *mnt, struct dentry *dentry, - char *esc) +int seq_path(struct seq_file *m, struct path *path, char *esc) { if (m->count < m->size) { char *s = m->buf + m->count; - char *p = d_path(dentry, mnt, s, m->size - m->count); + char *p = d_path(path, s, m->size - m->count); if (!IS_ERR(p)) { while (s <= p) { char c = *p++; diff --git a/fs/stat.c b/fs/stat.c index 68510068a641..9cf41f719d50 100644 --- a/fs/stat.c +++ b/fs/stat.c @@ -62,8 +62,8 @@ int vfs_stat_fd(int dfd, char __user *name, struct kstat *stat) error = __user_walk_fd(dfd, name, LOOKUP_FOLLOW, &nd); if (!error) { - error = vfs_getattr(nd.mnt, nd.dentry, stat); - path_release(&nd); + error = vfs_getattr(nd.path.mnt, nd.path.dentry, stat); + path_put(&nd.path); } return error; } @@ -82,8 +82,8 @@ int vfs_lstat_fd(int dfd, char __user *name, struct kstat *stat) error = __user_walk_fd(dfd, name, 0, &nd); if (!error) { - error = vfs_getattr(nd.mnt, nd.dentry, stat); - path_release(&nd); + error = vfs_getattr(nd.path.mnt, nd.path.dentry, stat); + path_put(&nd.path); } return error; } @@ -302,17 +302,18 @@ asmlinkage long sys_readlinkat(int dfd, const char __user *path, error = __user_walk_fd(dfd, path, 0, &nd); if (!error) { - struct inode * inode = nd.dentry->d_inode; + struct inode *inode = nd.path.dentry->d_inode; error = -EINVAL; if (inode->i_op && inode->i_op->readlink) { - error = security_inode_readlink(nd.dentry); + error = security_inode_readlink(nd.path.dentry); if (!error) { - touch_atime(nd.mnt, nd.dentry); - error = inode->i_op->readlink(nd.dentry, buf, bufsiz); + touch_atime(nd.path.mnt, nd.path.dentry); + error = inode->i_op->readlink(nd.path.dentry, + buf, bufsiz); } } - path_release(&nd); + path_put(&nd.path); } return error; } diff --git a/fs/utimes.c b/fs/utimes.c index e5588cd8530e..b18da9c0b97f 100644 --- a/fs/utimes.c +++ b/fs/utimes.c @@ -84,7 +84,7 @@ long do_utimes(int dfd, char __user *filename, struct timespec *times, int flags if (error) goto out; - dentry = nd.dentry; + dentry = nd.path.dentry; } inode = dentry->d_inode; @@ -138,7 +138,7 @@ dput_and_out: if (f) fput(f); else - path_release(&nd); + path_put(&nd.path); out: return error; } diff --git a/fs/xattr.c b/fs/xattr.c index f7c8f87bb390..3acab1615460 100644 --- a/fs/xattr.c +++ b/fs/xattr.c @@ -262,8 +262,8 @@ sys_setxattr(char __user *path, char __user *name, void __user *value, error = user_path_walk(path, &nd); if (error) return error; - error = setxattr(nd.dentry, name, value, size, flags); - path_release(&nd); + error = setxattr(nd.path.dentry, name, value, size, flags); + path_put(&nd.path); return error; } @@ -277,8 +277,8 @@ sys_lsetxattr(char __user *path, char __user *name, void __user *value, error = user_path_walk_link(path, &nd); if (error) return error; - error = setxattr(nd.dentry, name, value, size, flags); - path_release(&nd); + error = setxattr(nd.path.dentry, name, value, size, flags); + path_put(&nd.path); return error; } @@ -347,8 +347,8 @@ sys_getxattr(char __user *path, char __user *name, void __user *value, error = user_path_walk(path, &nd); if (error) return error; - error = getxattr(nd.dentry, name, value, size); - path_release(&nd); + error = getxattr(nd.path.dentry, name, value, size); + path_put(&nd.path); return error; } @@ -362,8 +362,8 @@ sys_lgetxattr(char __user *path, char __user *name, void __user *value, error = user_path_walk_link(path, &nd); if (error) return error; - error = getxattr(nd.dentry, name, value, size); - path_release(&nd); + error = getxattr(nd.path.dentry, name, value, size); + path_put(&nd.path); return error; } @@ -421,8 +421,8 @@ sys_listxattr(char __user *path, char __user *list, size_t size) error = user_path_walk(path, &nd); if (error) return error; - error = listxattr(nd.dentry, list, size); - path_release(&nd); + error = listxattr(nd.path.dentry, list, size); + path_put(&nd.path); return error; } @@ -435,8 +435,8 @@ sys_llistxattr(char __user *path, char __user *list, size_t size) error = user_path_walk_link(path, &nd); if (error) return error; - error = listxattr(nd.dentry, list, size); - path_release(&nd); + error = listxattr(nd.path.dentry, list, size); + path_put(&nd.path); return error; } @@ -482,8 +482,8 @@ sys_removexattr(char __user *path, char __user *name) error = user_path_walk(path, &nd); if (error) return error; - error = removexattr(nd.dentry, name); - path_release(&nd); + error = removexattr(nd.path.dentry, name); + path_put(&nd.path); return error; } @@ -496,8 +496,8 @@ sys_lremovexattr(char __user *path, char __user *name) error = user_path_walk_link(path, &nd); if (error) return error; - error = removexattr(nd.dentry, name); - path_release(&nd); + error = removexattr(nd.path.dentry, name); + path_put(&nd.path); return error; } diff --git a/fs/xfs/Kbuild b/fs/xfs/Kbuild deleted file mode 100644 index 2566e96706f1..000000000000 --- a/fs/xfs/Kbuild +++ /dev/null @@ -1,6 +0,0 @@ -# -# The xfs people like to share Makefile with 2.6 and 2.4. -# Utilise file named Kbuild file which has precedence over Makefile. -# - -include $(srctree)/$(obj)/Makefile-linux-2.6 diff --git a/fs/xfs/Makefile b/fs/xfs/Makefile index 49e3e7e5e3dc..36ec614e699a 100644 --- a/fs/xfs/Makefile +++ b/fs/xfs/Makefile @@ -1 +1,117 @@ -include $(TOPDIR)/fs/xfs/Makefile-linux-$(VERSION).$(PATCHLEVEL) +# +# Copyright (c) 2000-2005 Silicon Graphics, 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. +# +# This program is distributed in the hope that it would 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 the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# + +EXTRA_CFLAGS += -I$(src) -I$(src)/linux-2.6 -funsigned-char + +XFS_LINUX := linux-2.6 + +ifeq ($(CONFIG_XFS_DEBUG),y) + EXTRA_CFLAGS += -g +endif + +obj-$(CONFIG_XFS_FS) += xfs.o + +xfs-$(CONFIG_XFS_QUOTA) += $(addprefix quota/, \ + xfs_dquot.o \ + xfs_dquot_item.o \ + xfs_trans_dquot.o \ + xfs_qm_syscalls.o \ + xfs_qm_bhv.o \ + xfs_qm.o) + +ifeq ($(CONFIG_XFS_QUOTA),y) +xfs-$(CONFIG_PROC_FS) += quota/xfs_qm_stats.o +endif + +xfs-$(CONFIG_XFS_RT) += xfs_rtalloc.o +xfs-$(CONFIG_XFS_POSIX_ACL) += xfs_acl.o +xfs-$(CONFIG_PROC_FS) += $(XFS_LINUX)/xfs_stats.o +xfs-$(CONFIG_SYSCTL) += $(XFS_LINUX)/xfs_sysctl.o +xfs-$(CONFIG_COMPAT) += $(XFS_LINUX)/xfs_ioctl32.o + + +xfs-y += xfs_alloc.o \ + xfs_alloc_btree.o \ + xfs_attr.o \ + xfs_attr_leaf.o \ + xfs_bit.o \ + xfs_bmap.o \ + xfs_bmap_btree.o \ + xfs_btree.o \ + xfs_buf_item.o \ + xfs_da_btree.o \ + xfs_dir2.o \ + xfs_dir2_block.o \ + xfs_dir2_data.o \ + xfs_dir2_leaf.o \ + xfs_dir2_node.o \ + xfs_dir2_sf.o \ + xfs_error.o \ + xfs_extfree_item.o \ + xfs_filestream.o \ + xfs_fsops.o \ + xfs_ialloc.o \ + xfs_ialloc_btree.o \ + xfs_iget.o \ + xfs_inode.o \ + xfs_inode_item.o \ + xfs_iomap.o \ + xfs_itable.o \ + xfs_dfrag.o \ + xfs_log.o \ + xfs_log_recover.o \ + xfs_mount.o \ + xfs_mru_cache.o \ + xfs_rename.o \ + xfs_trans.o \ + xfs_trans_ail.o \ + xfs_trans_buf.o \ + xfs_trans_extfree.o \ + xfs_trans_inode.o \ + xfs_trans_item.o \ + xfs_utils.o \ + xfs_vfsops.o \ + xfs_vnodeops.o \ + xfs_rw.o \ + xfs_dmops.o \ + xfs_qmops.o + +xfs-$(CONFIG_XFS_TRACE) += xfs_dir2_trace.o + +# Objects in linux/ +xfs-y += $(addprefix $(XFS_LINUX)/, \ + kmem.o \ + xfs_aops.o \ + xfs_buf.o \ + xfs_export.o \ + xfs_file.o \ + xfs_fs_subr.o \ + xfs_globals.o \ + xfs_ioctl.o \ + xfs_iops.o \ + xfs_lrw.o \ + xfs_super.o \ + xfs_vnode.o) + +# Objects in support/ +xfs-y += $(addprefix support/, \ + debug.o \ + uuid.o) + +xfs-$(CONFIG_XFS_TRACE) += support/ktrace.o + diff --git a/fs/xfs/Makefile-linux-2.6 b/fs/xfs/Makefile-linux-2.6 deleted file mode 100644 index 97316451fc6d..000000000000 --- a/fs/xfs/Makefile-linux-2.6 +++ /dev/null @@ -1,117 +0,0 @@ -# -# Copyright (c) 2000-2005 Silicon Graphics, 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. -# -# This program is distributed in the hope that it would 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 the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -# - -EXTRA_CFLAGS += -Ifs/xfs -Ifs/xfs/linux-2.6 -funsigned-char - -XFS_LINUX := linux-2.6 - -ifeq ($(CONFIG_XFS_DEBUG),y) - EXTRA_CFLAGS += -g -endif - -obj-$(CONFIG_XFS_FS) += xfs.o - -xfs-$(CONFIG_XFS_QUOTA) += $(addprefix quota/, \ - xfs_dquot.o \ - xfs_dquot_item.o \ - xfs_trans_dquot.o \ - xfs_qm_syscalls.o \ - xfs_qm_bhv.o \ - xfs_qm.o) - -ifeq ($(CONFIG_XFS_QUOTA),y) -xfs-$(CONFIG_PROC_FS) += quota/xfs_qm_stats.o -endif - -xfs-$(CONFIG_XFS_RT) += xfs_rtalloc.o -xfs-$(CONFIG_XFS_POSIX_ACL) += xfs_acl.o -xfs-$(CONFIG_PROC_FS) += $(XFS_LINUX)/xfs_stats.o -xfs-$(CONFIG_SYSCTL) += $(XFS_LINUX)/xfs_sysctl.o -xfs-$(CONFIG_COMPAT) += $(XFS_LINUX)/xfs_ioctl32.o - - -xfs-y += xfs_alloc.o \ - xfs_alloc_btree.o \ - xfs_attr.o \ - xfs_attr_leaf.o \ - xfs_bit.o \ - xfs_bmap.o \ - xfs_bmap_btree.o \ - xfs_btree.o \ - xfs_buf_item.o \ - xfs_da_btree.o \ - xfs_dir2.o \ - xfs_dir2_block.o \ - xfs_dir2_data.o \ - xfs_dir2_leaf.o \ - xfs_dir2_node.o \ - xfs_dir2_sf.o \ - xfs_error.o \ - xfs_extfree_item.o \ - xfs_filestream.o \ - xfs_fsops.o \ - xfs_ialloc.o \ - xfs_ialloc_btree.o \ - xfs_iget.o \ - xfs_inode.o \ - xfs_inode_item.o \ - xfs_iomap.o \ - xfs_itable.o \ - xfs_dfrag.o \ - xfs_log.o \ - xfs_log_recover.o \ - xfs_mount.o \ - xfs_mru_cache.o \ - xfs_rename.o \ - xfs_trans.o \ - xfs_trans_ail.o \ - xfs_trans_buf.o \ - xfs_trans_extfree.o \ - xfs_trans_inode.o \ - xfs_trans_item.o \ - xfs_utils.o \ - xfs_vfsops.o \ - xfs_vnodeops.o \ - xfs_rw.o \ - xfs_dmops.o \ - xfs_qmops.o - -xfs-$(CONFIG_XFS_TRACE) += xfs_dir2_trace.o - -# Objects in linux/ -xfs-y += $(addprefix $(XFS_LINUX)/, \ - kmem.o \ - xfs_aops.o \ - xfs_buf.o \ - xfs_export.o \ - xfs_file.o \ - xfs_fs_subr.o \ - xfs_globals.o \ - xfs_ioctl.o \ - xfs_iops.o \ - xfs_lrw.o \ - xfs_super.o \ - xfs_vnode.o) - -# Objects in support/ -xfs-y += $(addprefix support/, \ - debug.o \ - uuid.o) - -xfs-$(CONFIG_XFS_TRACE) += support/ktrace.o - diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c index 4c82a050a3a8..a9952e490ac9 100644 --- a/fs/xfs/linux-2.6/xfs_ioctl.c +++ b/fs/xfs/linux-2.6/xfs_ioctl.c @@ -91,10 +91,10 @@ xfs_find_handle( if (error) return error; - ASSERT(nd.dentry); - ASSERT(nd.dentry->d_inode); - inode = igrab(nd.dentry->d_inode); - path_release(&nd); + ASSERT(nd.path.dentry); + ASSERT(nd.path.dentry->d_inode); + inode = igrab(nd.path.dentry->d_inode); + path_put(&nd.path); break; } diff --git a/include/acpi/processor.h b/include/acpi/processor.h index cdc8004cfd12..06480bcabfdc 100644 --- a/include/acpi/processor.h +++ b/include/acpi/processor.h @@ -32,9 +32,11 @@ #define DOMAIN_COORD_TYPE_SW_ANY 0xfd #define DOMAIN_COORD_TYPE_HW_ALL 0xfe -#define ACPI_CSTATE_SYSTEMIO (0) -#define ACPI_CSTATE_FFH (1) -#define ACPI_CSTATE_HALT (2) +#define ACPI_CSTATE_SYSTEMIO 0 +#define ACPI_CSTATE_FFH 1 +#define ACPI_CSTATE_HALT 2 + +#define ACPI_CX_DESC_LEN 32 /* Power Management */ @@ -74,6 +76,7 @@ struct acpi_processor_cx { u64 time; struct acpi_processor_cx_policy promotion; struct acpi_processor_cx_policy demotion; + char desc[ACPI_CX_DESC_LEN]; }; struct acpi_processor_power { diff --git a/include/asm-frv/unistd.h b/include/asm-frv/unistd.h index e8c986667532..f184eb8c047c 100644 --- a/include/asm-frv/unistd.h +++ b/include/asm-frv/unistd.h @@ -328,9 +328,11 @@ #define __NR_epoll_pwait 319 #define __NR_utimensat 320 #define __NR_signalfd 321 -/* #define __NR_timerfd 322 removed */ +#define __NR_timerfd_create 322 #define __NR_eventfd 323 #define __NR_fallocate 324 +#define __NR_timerfd_settime 325 +#define __NR_timerfd_gettime 326 #ifdef __KERNEL__ diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index f784d2f34149..f054778e916c 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -238,6 +238,9 @@ *(.kprobes.text) \ VMLINUX_SYMBOL(__kprobes_text_end) = .; +/* Section used for early init (in .S files) */ +#define HEAD_TEXT *(.head.text) + /* init and exit section handling */ #define INIT_DATA \ *(.init.data) \ diff --git a/include/asm-m68knommu/cacheflush.h b/include/asm-m68knommu/cacheflush.h index 29bc0aad2ebc..87e5dc0413b4 100644 --- a/include/asm-m68knommu/cacheflush.h +++ b/include/asm-m68knommu/cacheflush.h @@ -54,28 +54,28 @@ static inline void __flush_cache_all(void) #if defined(CONFIG_M527x) || defined(CONFIG_M528x) __asm__ __volatile__ ( "movel #0x81000200, %%d0\n\t" - "movec %%d0, %%CACR\n\t" + "movec %%d0, %%CACR\n\t" "nop\n\t" : : : "d0" ); #endif /* CONFIG_M527x || CONFIG_M528x */ #if defined(CONFIG_M5206) || defined(CONFIG_M5206e) || defined(CONFIG_M5272) __asm__ __volatile__ ( - "movel #0x81000100, %%d0\n\t" - "movec %%d0, %%CACR\n\t" + "movel #0x81000100, %%d0\n\t" + "movec %%d0, %%CACR\n\t" "nop\n\t" : : : "d0" ); #endif /* CONFIG_M5206 || CONFIG_M5206e || CONFIG_M5272 */ #ifdef CONFIG_M5249 __asm__ __volatile__ ( - "movel #0xa1000200, %%d0\n\t" - "movec %%d0, %%CACR\n\t" + "movel #0xa1000200, %%d0\n\t" + "movec %%d0, %%CACR\n\t" "nop\n\t" : : : "d0" ); #endif /* CONFIG_M5249 */ #ifdef CONFIG_M532x __asm__ __volatile__ ( - "movel #0x81000200, %%d0\n\t" - "movec %%d0, %%CACR\n\t" + "movel #0x81000200, %%d0\n\t" + "movec %%d0, %%CACR\n\t" "nop\n\t" : : : "d0" ); #endif /* CONFIG_M532x */ diff --git a/include/asm-m68knommu/system.h b/include/asm-m68knommu/system.h index 039ab3f81732..64c64432bbb8 100644 --- a/include/asm-m68knommu/system.h +++ b/include/asm-m68knommu/system.h @@ -104,7 +104,7 @@ asmlinkage void resume(void); #define mb() asm volatile ("" : : :"memory") #define rmb() asm volatile ("" : : :"memory") #define wmb() asm volatile ("" : : :"memory") -#define set_mb(var, value) do { xchg(&var, value); } while (0) +#define set_mb(var, value) ({ (var) = (value); wmb(); }) #ifdef CONFIG_SMP #define smp_mb() mb() diff --git a/include/asm-mips/mach-ip27/dma-coherence.h b/include/asm-mips/mach-ip27/dma-coherence.h index 3fdbbf68e952..ed7e6222dc15 100644 --- a/include/asm-mips/mach-ip27/dma-coherence.h +++ b/include/asm-mips/mach-ip27/dma-coherence.h @@ -35,7 +35,7 @@ static dma_addr_t plat_map_dma_mem_page(struct device *dev, struct page *page) static unsigned long plat_dma_addr_to_phys(dma_addr_t dma_addr) { - return dma_addr & (0xffUL << 56); + return dma_addr & ~(0xffUL << 56); } static inline void plat_unmap_dma_mem(dma_addr_t dma_addr) diff --git a/include/asm-mips/qemu.h b/include/asm-mips/qemu.h deleted file mode 100644 index 487ced4a40de..000000000000 --- a/include/asm-mips/qemu.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * 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. - * - * Copyright (C) 2005 by Ralf Baechle (ralf@linux-mips.org) - */ -#ifndef __ASM_QEMU_H -#define __ASM_QEMU_H - -/* - * Interrupt numbers - */ -#define Q_PIC_IRQ_BASE 0 -#define Q_COUNT_COMPARE_IRQ 23 - -/* - * Qemu clock rate. Unlike on real MIPS this has no relation to the - * instruction issue rate, so the choosen value is pure fiction, just needs - * to match the value in Qemu itself. - */ -#define QEMU_C0_COUNTER_CLOCK 100000000 - -/* - * Magic qemu system control location. - */ -#define QEMU_RESTART_REG 0xBFBF0000 -#define QEMU_HALT_REG 0xBFBF0004 - -#endif /* __ASM_QEMU_H */ diff --git a/include/asm-mips/sni.h b/include/asm-mips/sni.h index e716447e5e03..8c1eb02c6d16 100644 --- a/include/asm-mips/sni.h +++ b/include/asm-mips/sni.h @@ -228,7 +228,14 @@ extern void sni_pcimt_irq_init(void); extern void sni_cpu_time_init(void); /* eisa init for RM200/400 */ +#ifdef CONFIG_EISA extern int sni_eisa_root_init(void); +#else +static inline int sni_eisa_root_init(void) +{ + return 0; +} +#endif /* common irq stuff */ extern void (*sni_hwint)(void); diff --git a/include/asm-mips/unistd.h b/include/asm-mips/unistd.h index fa9a587b3bf1..4964c82f85f9 100644 --- a/include/asm-mips/unistd.h +++ b/include/asm-mips/unistd.h @@ -341,16 +341,19 @@ #define __NR_timerfd (__NR_Linux + 318) #define __NR_eventfd (__NR_Linux + 319) #define __NR_fallocate (__NR_Linux + 320) +#define __NR_timerfd_create (__NR_Linux + 321) +#define __NR_timerfd_gettime (__NR_Linux + 322) +#define __NR_timerfd_settime (__NR_Linux + 323) /* * Offset of the last Linux o32 flavoured syscall */ -#define __NR_Linux_syscalls 320 +#define __NR_Linux_syscalls 323 #endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */ #define __NR_O32_Linux 4000 -#define __NR_O32_Linux_syscalls 320 +#define __NR_O32_Linux_syscalls 323 #if _MIPS_SIM == _MIPS_SIM_ABI64 @@ -638,16 +641,19 @@ #define __NR_timerfd (__NR_Linux + 277) #define __NR_eventfd (__NR_Linux + 278) #define __NR_fallocate (__NR_Linux + 279) +#define __NR_timerfd_create (__NR_Linux + 280) +#define __NR_timerfd_gettime (__NR_Linux + 281) +#define __NR_timerfd_settime (__NR_Linux + 282) /* * Offset of the last Linux 64-bit flavoured syscall */ -#define __NR_Linux_syscalls 279 +#define __NR_Linux_syscalls 282 #endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */ #define __NR_64_Linux 5000 -#define __NR_64_Linux_syscalls 279 +#define __NR_64_Linux_syscalls 282 #if _MIPS_SIM == _MIPS_SIM_NABI32 @@ -939,16 +945,19 @@ #define __NR_timerfd (__NR_Linux + 281) #define __NR_eventfd (__NR_Linux + 282) #define __NR_fallocate (__NR_Linux + 283) +#define __NR_timerfd_create (__NR_Linux + 284) +#define __NR_timerfd_gettime (__NR_Linux + 285) +#define __NR_timerfd_settime (__NR_Linux + 286) /* * Offset of the last N32 flavoured syscall */ -#define __NR_Linux_syscalls 283 +#define __NR_Linux_syscalls 286 #endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */ #define __NR_N32_Linux 6000 -#define __NR_N32_Linux_syscalls 283 +#define __NR_N32_Linux_syscalls 286 #ifdef __KERNEL__ diff --git a/include/asm-powerpc/systbl.h b/include/asm-powerpc/systbl.h index e996521fb3a6..ae7085c65692 100644 --- a/include/asm-powerpc/systbl.h +++ b/include/asm-powerpc/systbl.h @@ -309,8 +309,10 @@ SYSCALL_SPU(getcpu) COMPAT_SYS(epoll_pwait) COMPAT_SYS_SPU(utimensat) COMPAT_SYS_SPU(signalfd) -SYSCALL(ni_syscall) +SYSCALL_SPU(timerfd_create) SYSCALL_SPU(eventfd) COMPAT_SYS_SPU(sync_file_range2) COMPAT_SYS(fallocate) SYSCALL(subpage_prot) +COMPAT_SYS_SPU(timerfd_settime) +COMPAT_SYS_SPU(timerfd_gettime) diff --git a/include/asm-powerpc/unistd.h b/include/asm-powerpc/unistd.h index fedc4b8e49e2..ce91bb662063 100644 --- a/include/asm-powerpc/unistd.h +++ b/include/asm-powerpc/unistd.h @@ -328,15 +328,17 @@ #define __NR_epoll_pwait 303 #define __NR_utimensat 304 #define __NR_signalfd 305 -#define __NR_timerfd 306 +#define __NR_timerfd_create 306 #define __NR_eventfd 307 #define __NR_sync_file_range2 308 #define __NR_fallocate 309 #define __NR_subpage_prot 310 +#define __NR_timerfd_settime 311 +#define __NR_timerfd_gettime 312 #ifdef __KERNEL__ -#define __NR_syscalls 311 +#define __NR_syscalls 313 #define __NR__exit __NR_exit #define NR_syscalls __NR_syscalls diff --git a/include/asm-ppc/page.h b/include/asm-ppc/page.h index ad4c5a1bc9d6..37e4756b6b2d 100644 --- a/include/asm-ppc/page.h +++ b/include/asm-ppc/page.h @@ -125,6 +125,8 @@ extern __inline__ int get_order(unsigned long size) return 32 - lz; } +typedef struct page *pgtable_t; + #endif /* __ASSEMBLY__ */ #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \ diff --git a/include/asm-s390/bitops.h b/include/asm-s390/bitops.h index ab83c844d04c..965394e69452 100644 --- a/include/asm-s390/bitops.h +++ b/include/asm-s390/bitops.h @@ -456,16 +456,18 @@ static inline unsigned long __ffz_word_loop(const unsigned long *addr, asm volatile( #ifndef __s390x__ - " ahi %1,31\n" - " srl %1,5\n" + " ahi %1,-1\n" + " sra %1,5\n" + " jz 1f\n" "0: c %2,0(%0,%3)\n" " jne 1f\n" " la %0,4(%0)\n" " brct %1,0b\n" "1:\n" #else - " aghi %1,63\n" - " srlg %1,%1,6\n" + " aghi %1,-1\n" + " srag %1,%1,6\n" + " jz 1f\n" "0: cg %2,0(%0,%3)\n" " jne 1f\n" " la %0,8(%0)\n" @@ -491,16 +493,18 @@ static inline unsigned long __ffs_word_loop(const unsigned long *addr, asm volatile( #ifndef __s390x__ - " ahi %1,31\n" - " srl %1,5\n" + " ahi %1,-1\n" + " sra %1,5\n" + " jz 1f\n" "0: c %2,0(%0,%3)\n" " jne 1f\n" " la %0,4(%0)\n" " brct %1,0b\n" "1:\n" #else - " aghi %1,63\n" - " srlg %1,%1,6\n" + " aghi %1,-1\n" + " srag %1,%1,6\n" + " jz 1f\n" "0: cg %2,0(%0,%3)\n" " jne 1f\n" " la %0,8(%0)\n" diff --git a/include/asm-sh/bugs.h b/include/asm-sh/bugs.h index def8128b8b78..cfda7d5bf026 100644 --- a/include/asm-sh/bugs.h +++ b/include/asm-sh/bugs.h @@ -39,7 +39,7 @@ static void __init check_bugs(void) *p++ = '4'; *p++ = 'a'; break; - case CPU_SH7343 ... CPU_SH7722: + case CPU_SH7343 ... CPU_SH7366: *p++ = '4'; *p++ = 'a'; *p++ = 'l'; diff --git a/include/asm-sh/cpu-sh4/freq.h b/include/asm-sh/cpu-sh4/freq.h index 1ac10b9a078f..ec028c649215 100644 --- a/include/asm-sh/cpu-sh4/freq.h +++ b/include/asm-sh/cpu-sh4/freq.h @@ -10,12 +10,14 @@ #ifndef __ASM_CPU_SH4_FREQ_H #define __ASM_CPU_SH4_FREQ_H -#if defined(CONFIG_CPU_SUBTYPE_SH7722) +#if defined(CONFIG_CPU_SUBTYPE_SH7722) || defined(CONFIG_CPU_SUBTYPE_SH7366) #define FRQCR 0xa4150000 #define VCLKCR 0xa4150004 #define SCLKACR 0xa4150008 #define SCLKBCR 0xa415000c +#if defined(CONFIG_CPU_SUBTYPE_SH7722) #define IrDACLKCR 0xa4150010 +#endif #elif defined(CONFIG_CPU_SUBTYPE_SH7763) || \ defined(CONFIG_CPU_SUBTYPE_SH7780) #define FRQCR 0xffc80000 diff --git a/include/asm-sh/cpu-sh5/cacheflush.h b/include/asm-sh/cpu-sh5/cacheflush.h index 98edb5b1da32..5a11f0b7e66a 100644 --- a/include/asm-sh/cpu-sh5/cacheflush.h +++ b/include/asm-sh/cpu-sh5/cacheflush.h @@ -3,15 +3,13 @@ #ifndef __ASSEMBLY__ -#include - struct vm_area_struct; struct page; struct mm_struct; extern void flush_cache_all(void); extern void flush_cache_mm(struct mm_struct *mm); -extern void flush_cache_sigtramp(unsigned long start, unsigned long end); +extern void flush_cache_sigtramp(unsigned long vaddr); extern void flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end); extern void flush_cache_page(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn); @@ -27,7 +25,7 @@ extern void flush_icache_user_range(struct vm_area_struct *vma, #define flush_dcache_mmap_unlock(mapping) do { } while (0) #define flush_icache_page(vma, page) do { } while (0) -#define p3_cache_init() do { } while (0) +void p3_cache_init(void); #endif /* __ASSEMBLY__ */ diff --git a/include/asm-sh/cpu-sh5/mmu_context.h b/include/asm-sh/cpu-sh5/mmu_context.h index df857fc09960..68a1d2cff457 100644 --- a/include/asm-sh/cpu-sh5/mmu_context.h +++ b/include/asm-sh/cpu-sh5/mmu_context.h @@ -16,12 +16,6 @@ /* This has to be a common function because the next location to fill * information is shared. */ extern void __do_tlb_refill(unsigned long address, unsigned long long is_text_not_data, pte_t *pte); - -/* Profiling counter. */ -#ifdef CONFIG_SH64_PROC_TLB -extern unsigned long long calls_to_do_fast_page_fault; -#endif - #endif /* __ASSEMBLY__ */ #endif /* __ASM_SH_CPU_SH5_MMU_CONTEXT_H */ diff --git a/include/asm-sh/hp6xx.h b/include/asm-sh/hp6xx.h index 53ca5643d9c7..0d4165a32dcd 100644 --- a/include/asm-sh/hp6xx.h +++ b/include/asm-sh/hp6xx.h @@ -10,9 +10,9 @@ * */ -#define HP680_BTN_IRQ 32 /* IRQ0_IRQ */ -#define HP680_TS_IRQ 35 /* IRQ3_IRQ */ -#define HP680_HD64461_IRQ 36 /* IRQ4_IRQ */ +#define HP680_BTN_IRQ 32 /* IRQ0_IRQ */ +#define HP680_TS_IRQ 35 /* IRQ3_IRQ */ +#define HP680_HD64461_IRQ 36 /* IRQ4_IRQ */ #define DAC_LCD_BRIGHTNESS 0 #define DAC_SPEAKER_VOLUME 1 @@ -55,26 +55,4 @@ #define PJDR 0xa4000130 #define PKDR 0xa4000132 -static inline void hp6xx_led_red(int on) -{ - u16 v16; - v16 = ctrl_inw(CONFIG_HD64461_IOBASE + HD64461_GPBDR - 0x10000); - if (on) - ctrl_outw(v16 & (~HD64461_GPBDR_LED_RED), CONFIG_HD64461_IOBASE + HD64461_GPBDR - 0x10000); - else - ctrl_outw(v16 | HD64461_GPBDR_LED_RED, CONFIG_HD64461_IOBASE + HD64461_GPBDR - 0x10000); -} - -static inline void hp6xx_led_green(int on) -{ - u8 v8; - - v8 = ctrl_inb(PKDR); - if (on) - ctrl_outb(v8 & (~PKDR_LED_GREEN), PKDR); - else - ctrl_outb(v8 | PKDR_LED_GREEN, PKDR); -} - - #endif /* __ASM_SH_HP6XX_H */ diff --git a/include/asm-sh/io.h b/include/asm-sh/io.h index 94900c089519..356e50d06745 100644 --- a/include/asm-sh/io.h +++ b/include/asm-sh/io.h @@ -38,6 +38,7 @@ */ #define __IO_PREFIX generic #include +#include #define maybebadio(port) \ printk(KERN_ERR "bad PC-like io %s:%u for port 0x%lx at 0x%08x\n", \ @@ -181,13 +182,13 @@ __BUILD_MEMORY_STRING(w, u16) #define iowrite32(v,a) writel((v),(a)) #define iowrite32be(v,a) __raw_writel(cpu_to_be32((v)),(a)) -#define ioread8_rep(a,d,c) insb((a),(d),(c)) -#define ioread16_rep(a,d,c) insw((a),(d),(c)) -#define ioread32_rep(a,d,c) insl((a),(d),(c)) +#define ioread8_rep(a, d, c) readsb((a), (d), (c)) +#define ioread16_rep(a, d, c) readsw((a), (d), (c)) +#define ioread32_rep(a, d, c) readsl((a), (d), (c)) -#define iowrite8_rep(a,s,c) outsb((a),(s),(c)) -#define iowrite16_rep(a,s,c) outsw((a),(s),(c)) -#define iowrite32_rep(a,s,c) outsl((a),(s),(c)) +#define iowrite8_rep(a, s, c) writesb((a), (s), (c)) +#define iowrite16_rep(a, s, c) writesw((a), (s), (c)) +#define iowrite32_rep(a, s, c) writesl((a), (s), (c)) #define mmiowb() wmb() /* synco on SH-4A, otherwise a nop */ @@ -207,6 +208,8 @@ static inline void __set_io_port_base(unsigned long pbase) generic_io_base = pbase; } +#define __ioport_map(p, n) sh_mv.mv_ioport_map((p), (n)) + /* We really want to try and get these to memcpy etc */ extern void memcpy_fromio(void *, volatile void __iomem *, unsigned long); extern void memcpy_toio(volatile void __iomem *, const void *, unsigned long); @@ -309,7 +312,14 @@ __ioremap_mode(unsigned long offset, unsigned long size, unsigned long flags) { #ifdef CONFIG_SUPERH32 unsigned long last_addr = offset + size - 1; +#endif + void __iomem *ret; + ret = __ioremap_trapped(offset, size); + if (ret) + return ret; + +#ifdef CONFIG_SUPERH32 /* * For P1 and P2 space this is trivial, as everything is already * mapped. Uncached access for P1 addresses are done through P2. diff --git a/include/asm-sh/io_trapped.h b/include/asm-sh/io_trapped.h new file mode 100644 index 000000000000..f1251d4f0ba9 --- /dev/null +++ b/include/asm-sh/io_trapped.h @@ -0,0 +1,58 @@ +#ifndef __ASM_SH_IO_TRAPPED_H +#define __ASM_SH_IO_TRAPPED_H + +#include +#include +#include + +#define IO_TRAPPED_MAGIC 0xfeedbeef + +struct trapped_io { + unsigned int magic; + struct resource *resource; + unsigned int num_resources; + unsigned int minimum_bus_width; + struct list_head list; + void __iomem *virt_base; +} __aligned(PAGE_SIZE); + +#ifdef CONFIG_IO_TRAPPED +int register_trapped_io(struct trapped_io *tiop); +int handle_trapped_io(struct pt_regs *regs, unsigned long address); + +void __iomem *match_trapped_io_handler(struct list_head *list, + unsigned long offset, + unsigned long size); + +#ifdef CONFIG_HAS_IOMEM +extern struct list_head trapped_mem; + +static inline void __iomem * +__ioremap_trapped(unsigned long offset, unsigned long size) +{ + return match_trapped_io_handler(&trapped_mem, offset, size); +} +#else +#define __ioremap_trapped(offset, size) NULL +#endif + +#ifdef CONFIG_HAS_IOPORT +extern struct list_head trapped_io; + +static inline void __iomem * +__ioport_map_trapped(unsigned long offset, unsigned long size) +{ + return match_trapped_io_handler(&trapped_io, offset, size); +} +#else +#define __ioport_map_trapped(offset, size) NULL +#endif + +#else +#define register_trapped_io(tiop) (-1) +#define handle_trapped_io(tiop, address) 0 +#define __ioremap_trapped(offset, size) NULL +#define __ioport_map_trapped(offset, size) NULL +#endif + +#endif /* __ASM_SH_IO_TRAPPED_H */ diff --git a/include/asm-sh/ioctls.h b/include/asm-sh/ioctls.h index 35805df010a0..c212c371a4a5 100644 --- a/include/asm-sh/ioctls.h +++ b/include/asm-sh/ioctls.h @@ -78,6 +78,10 @@ #define TIOCSBRK _IO('T', 39) /* 0x5427 */ /* BSD compatibility */ #define TIOCCBRK _IO('T', 40) /* 0x5428 */ /* BSD compatibility */ #define TIOCGSID _IOR('T', 41, pid_t) /* 0x5429 */ /* Return the session ID of FD */ +#define TCGETS2 _IOR('T', 42, struct termios2) +#define TCSETS2 _IOW('T', 43, struct termios2) +#define TCSETSW2 _IOW('T', 44, struct termios2) +#define TCSETSF2 _IOW('T', 45, struct termios2) #define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ #define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */ diff --git a/include/asm-sh/irq.h b/include/asm-sh/irq.h index 11850f65c922..ca66e5df69dc 100644 --- a/include/asm-sh/irq.h +++ b/include/asm-sh/irq.h @@ -50,4 +50,8 @@ extern void irq_ctx_exit(int cpu); # define irq_ctx_exit(cpu) do { } while (0) #endif +#ifdef CONFIG_CPU_SH5 +#include +#endif + #endif /* __ASM_SH_IRQ_H */ diff --git a/include/asm-sh/mmu_context_64.h b/include/asm-sh/mmu_context_64.h index 020be744b088..9649f1c07caf 100644 --- a/include/asm-sh/mmu_context_64.h +++ b/include/asm-sh/mmu_context_64.h @@ -66,6 +66,9 @@ static inline void set_asid(unsigned long asid) : "=r" (sr), "=r" (pc) : "0" (sr)); } +/* arch/sh/kernel/cpu/sh5/entry.S */ +extern unsigned long switch_and_save_asid(unsigned long new_asid); + /* No spare register to twiddle, so use a software cache */ extern pgd_t *mmu_pdtp_cache; diff --git a/include/asm-sh/page.h b/include/asm-sh/page.h index 134562dc8c45..304c30b5d947 100644 --- a/include/asm-sh/page.h +++ b/include/asm-sh/page.h @@ -55,11 +55,14 @@ extern void clear_page(void *to); extern void copy_page(void *to, void *from); #if !defined(CONFIG_CACHE_OFF) && defined(CONFIG_MMU) && \ - (defined(CONFIG_CPU_SH4) || defined(CONFIG_SH7705_CACHE_32KB)) + (defined(CONFIG_CPU_SH5) || defined(CONFIG_CPU_SH4) || \ + defined(CONFIG_SH7705_CACHE_32KB)) struct page; struct vm_area_struct; extern void clear_user_page(void *to, unsigned long address, struct page *page); -#ifdef CONFIG_CPU_SH4 +extern void copy_user_page(void *to, void *from, unsigned long address, + struct page *page); +#if defined(CONFIG_CPU_SH4) extern void copy_user_highpage(struct page *to, struct page *from, unsigned long vaddr, struct vm_area_struct *vma); #define __HAVE_ARCH_COPY_USER_HIGHPAGE diff --git a/include/asm-sh/pgtable_64.h b/include/asm-sh/pgtable_64.h index 972211671c9a..f9dd9d311441 100644 --- a/include/asm-sh/pgtable_64.h +++ b/include/asm-sh/pgtable_64.h @@ -137,6 +137,14 @@ static __inline__ void pmd_set(pmd_t *pmdp,pte_t *ptep) #define _PAGE_SZHUGE (_PAGE_SIZE0 | _PAGE_SIZE1) #endif +/* + * Stub out _PAGE_SZHUGE if we don't have a good definition for it, + * to make pte_mkhuge() happy. + */ +#ifndef _PAGE_SZHUGE +# define _PAGE_SZHUGE (0) +#endif + /* * Default flags for a Kernel page. * This is fundametally also SHARED because the main use of this define @@ -179,6 +187,11 @@ static __inline__ void pmd_set(pmd_t *pmdp,pte_t *ptep) _PAGE_WRITE | _PAGE_EXECUTE) #define PAGE_KERNEL __pgprot(_KERNPG_TABLE) +#define PAGE_KERNEL_NOCACHE \ + __pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | \ + _PAGE_EXECUTE | _PAGE_ACCESSED | \ + _PAGE_DIRTY | _PAGE_SHARED) + /* Make it a device mapping for maximum safety (e.g. for mapping device registers into user-space via /dev/map). */ #define pgprot_noncached(x) __pgprot(((x).pgprot & ~(_PAGE_CACHABLE)) | _PAGE_DEVICE) diff --git a/include/asm-sh/processor.h b/include/asm-sh/processor.h index c9b14161f73d..19fe47c1ca17 100644 --- a/include/asm-sh/processor.h +++ b/include/asm-sh/processor.h @@ -33,7 +33,7 @@ enum cpu_type { CPU_SH7763, CPU_SH7770, CPU_SH7780, CPU_SH7781, CPU_SH7785, CPU_SHX3, /* SH4AL-DSP types */ - CPU_SH7343, CPU_SH7722, + CPU_SH7343, CPU_SH7722, CPU_SH7366, /* SH-5 types */ CPU_SH5_101, CPU_SH5_103, diff --git a/include/asm-sh/r7780rp.h b/include/asm-sh/r7780rp.h index bdecea0840a0..1770460a4616 100644 --- a/include/asm-sh/r7780rp.h +++ b/include/asm-sh/r7780rp.h @@ -195,7 +195,4 @@ unsigned char *highlander_init_irq_r7780mp(void); unsigned char *highlander_init_irq_r7780rp(void); unsigned char *highlander_init_irq_r7785rp(void); -#define __IO_PREFIX r7780rp -#include - #endif /* __ASM_SH_RENESAS_R7780RP */ diff --git a/include/asm-sh/rts7751r2d.h b/include/asm-sh/rts7751r2d.h index 83b9c111f171..0a800157b826 100644 --- a/include/asm-sh/rts7751r2d.h +++ b/include/asm-sh/rts7751r2d.h @@ -67,7 +67,4 @@ void init_rts7751r2d_IRQ(void); int rts7751r2d_irq_demux(int); -#define __IO_PREFIX rts7751r2d -#include - #endif /* __ASM_SH_RENESAS_RTS7751R2D */ diff --git a/include/asm-sh/system.h b/include/asm-sh/system.h index 772cd1a0a674..5145aa2a0ce9 100644 --- a/include/asm-sh/system.h +++ b/include/asm-sh/system.h @@ -182,6 +182,11 @@ BUILD_TRAP_HANDLER(fpu_state_restore); #define arch_align_stack(x) (x) +struct mem_access { + unsigned long (*from)(void *dst, const void *src, unsigned long cnt); + unsigned long (*to)(void *dst, const void *src, unsigned long cnt); +}; + #ifdef CONFIG_SUPERH32 # include "system_32.h" #else diff --git a/include/asm-sh/system_32.h b/include/asm-sh/system_32.h index 7ff08d956ba8..f11bcf0855ed 100644 --- a/include/asm-sh/system_32.h +++ b/include/asm-sh/system_32.h @@ -96,4 +96,7 @@ do { \ : "=&r" (__dummy)); \ } while (0) +int handle_unaligned_access(opcode_t instruction, struct pt_regs *regs, + struct mem_access *ma); + #endif /* __ASM_SH_SYSTEM_32_H */ diff --git a/include/asm-sh/termbits.h b/include/asm-sh/termbits.h index 7ee1b42eeab0..77db116948cf 100644 --- a/include/asm-sh/termbits.h +++ b/include/asm-sh/termbits.h @@ -140,6 +140,7 @@ struct ktermios { #define HUPCL 0002000 #define CLOCAL 0004000 #define CBAUDEX 0010000 +#define BOTHER 0010000 #define B57600 0010001 #define B115200 0010002 #define B230400 0010003 @@ -155,10 +156,12 @@ struct ktermios { #define B3000000 0010015 #define B3500000 0010016 #define B4000000 0010017 -#define CIBAUD 002003600000 /* input baud rate (not used) */ +#define CIBAUD 002003600000 /* input baud rate */ #define CMSPAR 010000000000 /* mark or space (stick) parity */ #define CRTSCTS 020000000000 /* flow control */ +#define IBSHIFT 16 /* Shift from CBAUD to CIBAUD */ + /* c_lflag bits */ #define ISIG 0000001 #define ICANON 0000002 diff --git a/include/asm-sh/termios.h b/include/asm-sh/termios.h index e7c8f86ef890..0a8c793c76f2 100644 --- a/include/asm-sh/termios.h +++ b/include/asm-sh/termios.h @@ -80,8 +80,10 @@ struct termio { copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \ }) -#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios)) -#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios)) +#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios2)) +#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios2)) +#define user_termios_to_kernel_termios_1(k, u) copy_from_user(k, u, sizeof(struct termios)) +#define kernel_termios_to_user_termios_1(u, k) copy_to_user(u, k, sizeof(struct termios)) #endif /* __KERNEL__ */ diff --git a/include/asm-sh/tlb.h b/include/asm-sh/tlb.h index 56ad1fb888a2..88ff1ae8a6b8 100644 --- a/include/asm-sh/tlb.h +++ b/include/asm-sh/tlb.h @@ -20,6 +20,7 @@ */ #define tlb_flush(tlb) flush_tlb_mm((tlb)->mm) +#include #include #endif /* __ASSEMBLY__ */ diff --git a/include/asm-sh/uaccess.h b/include/asm-sh/uaccess.h index ff24ce95b238..b3440c305b5d 100644 --- a/include/asm-sh/uaccess.h +++ b/include/asm-sh/uaccess.h @@ -1,5 +1,34 @@ +#ifndef __ASM_SH_UACCESS_H +#define __ASM_SH_UACCESS_H + #ifdef CONFIG_SUPERH32 # include "uaccess_32.h" #else # include "uaccess_64.h" #endif + +static inline unsigned long +copy_from_user(void *to, const void __user *from, unsigned long n) +{ + unsigned long __copy_from = (unsigned long) from; + __kernel_size_t __copy_size = (__kernel_size_t) n; + + if (__copy_size && __access_ok(__copy_from, __copy_size)) + return __copy_user(to, from, __copy_size); + + return __copy_size; +} + +static inline unsigned long +copy_to_user(void __user *to, const void *from, unsigned long n) +{ + unsigned long __copy_to = (unsigned long) to; + __kernel_size_t __copy_size = (__kernel_size_t) n; + + if (__copy_size && __access_ok(__copy_to, __copy_size)) + return __copy_user(to, from, __copy_size); + + return __copy_size; +} + +#endif /* __ASM_SH_UACCESS_H */ diff --git a/include/asm-sh/uaccess_32.h b/include/asm-sh/uaccess_32.h index b6082f3c1dc4..c0318b608893 100644 --- a/include/asm-sh/uaccess_32.h +++ b/include/asm-sh/uaccess_32.h @@ -10,8 +10,8 @@ * Copyright (C) 1996, 1997, 1998 by Ralf Baechle * and i386 version. */ -#ifndef __ASM_SH_UACCESS_H -#define __ASM_SH_UACCESS_H +#ifndef __ASM_SH_UACCESS_32_H +#define __ASM_SH_UACCESS_32_H #include #include @@ -302,24 +302,6 @@ extern void __put_user_unknown(void); /* Return the number of bytes NOT copied */ __kernel_size_t __copy_user(void *to, const void *from, __kernel_size_t n); -#define copy_to_user(to,from,n) ({ \ -void *__copy_to = (void *) (to); \ -__kernel_size_t __copy_size = (__kernel_size_t) (n); \ -__kernel_size_t __copy_res; \ -if(__copy_size && __access_ok((unsigned long)__copy_to, __copy_size)) { \ -__copy_res = __copy_user(__copy_to, (void *) (from), __copy_size); \ -} else __copy_res = __copy_size; \ -__copy_res; }) - -#define copy_from_user(to,from,n) ({ \ -void *__copy_to = (void *) (to); \ -void *__copy_from = (void *) (from); \ -__kernel_size_t __copy_size = (__kernel_size_t) (n); \ -__kernel_size_t __copy_res; \ -if(__copy_size && __access_ok((unsigned long)__copy_from, __copy_size)) { \ -__copy_res = __copy_user(__copy_to, __copy_from, __copy_size); \ -} else __copy_res = __copy_size; \ -__copy_res; }) static __always_inline unsigned long __copy_from_user(void *to, const void __user *from, unsigned long n) @@ -507,4 +489,4 @@ struct exception_table_entry extern int fixup_exception(struct pt_regs *regs); -#endif /* __ASM_SH_UACCESS_H */ +#endif /* __ASM_SH_UACCESS_32_H */ diff --git a/include/asm-sh/uaccess_64.h b/include/asm-sh/uaccess_64.h index d54ec082d25a..f956b7b316c7 100644 --- a/include/asm-sh/uaccess_64.h +++ b/include/asm-sh/uaccess_64.h @@ -202,15 +202,6 @@ extern void __put_user_unknown(void); /* XXX: should be such that: 4byte and the rest. */ extern __kernel_size_t __copy_user(void *__to, const void *__from, __kernel_size_t __n); -#define copy_to_user(to,from,n) ({ \ -void *__copy_to = (void *) (to); \ -__kernel_size_t __copy_size = (__kernel_size_t) (n); \ -__kernel_size_t __copy_res; \ -if(__copy_size && __access_ok((unsigned long)__copy_to, __copy_size)) { \ -__copy_res = __copy_user(__copy_to, (void *) (from), __copy_size); \ -} else __copy_res = __copy_size; \ -__copy_res; }) - #define copy_to_user_ret(to,from,n,retval) ({ \ if (copy_to_user(to,from,n)) \ return retval; \ @@ -225,16 +216,6 @@ if (__copy_to_user(to,from,n)) \ return retval; \ }) -#define copy_from_user(to,from,n) ({ \ -void *__copy_to = (void *) (to); \ -void *__copy_from = (void *) (from); \ -__kernel_size_t __copy_size = (__kernel_size_t) (n); \ -__kernel_size_t __copy_res; \ -if(__copy_size && __access_ok((unsigned long)__copy_from, __copy_size)) { \ -__copy_res = __copy_user(__copy_to, __copy_from, __copy_size); \ -} else __copy_res = __copy_size; \ -__copy_res; }) - #define copy_from_user_ret(to,from,n,retval) ({ \ if (copy_from_user(to,from,n)) \ return retval; \ diff --git a/include/asm-sh/unistd_32.h b/include/asm-sh/unistd_32.h index 433fd1b48fa2..0b07212ec659 100644 --- a/include/asm-sh/unistd_32.h +++ b/include/asm-sh/unistd_32.h @@ -330,11 +330,13 @@ #define __NR_epoll_pwait 319 #define __NR_utimensat 320 #define __NR_signalfd 321 -/* #define __NR_timerfd 322 removed */ +#define __NR_timerfd_create 322 #define __NR_eventfd 323 #define __NR_fallocate 324 +#define __NR_timerfd_settime 325 +#define __NR_timerfd_gettime 326 -#define NR_syscalls 325 +#define NR_syscalls 327 #ifdef __KERNEL__ diff --git a/include/asm-sh/unistd_64.h b/include/asm-sh/unistd_64.h index 108d2ba897fe..9d21eab52427 100644 --- a/include/asm-sh/unistd_64.h +++ b/include/asm-sh/unistd_64.h @@ -90,7 +90,7 @@ #define __NR_sigpending 73 #define __NR_sethostname 74 #define __NR_setrlimit 75 -#define __NR_getrlimit 76 /* Back compatible 2Gig limited rlimit */ +#define __NR_getrlimit 76 /* Back compatible 2Gig limited rlimit */ #define __NR_getrusage 77 #define __NR_gettimeofday 78 #define __NR_settimeofday 79 @@ -370,9 +370,11 @@ #define __NR_epoll_pwait 347 #define __NR_utimensat 348 #define __NR_signalfd 349 -/* #define __NR_timerfd 350 removed */ +#define __NR_timerfd_create 350 #define __NR_eventfd 351 #define __NR_fallocate 352 +#define __NR_timerfd_settime 353 +#define __NR_timerfd_gettime 354 #ifdef __KERNEL__ diff --git a/include/asm-sparc64/ptrace.h b/include/asm-sparc64/ptrace.h index 8617c3a5143b..67341cff2e6b 100644 --- a/include/asm-sparc64/ptrace.h +++ b/include/asm-sparc64/ptrace.h @@ -102,6 +102,7 @@ do { current_thread_info()->syscall_noerror = 1; \ } while (0) #define user_mode(regs) (!((regs)->tstate & TSTATE_PRIV)) #define instruction_pointer(regs) ((regs)->tpc) +#define regs_return_value(regs) ((regs)->u_regs[UREG_I0]) #ifdef CONFIG_SMP extern unsigned long profile_pc(struct pt_regs *); #else diff --git a/include/asm-x86/cacheflush.h b/include/asm-x86/cacheflush.h index 6a22212b4b20..5396c212d8c0 100644 --- a/include/asm-x86/cacheflush.h +++ b/include/asm-x86/cacheflush.h @@ -48,12 +48,15 @@ void cpa_init(void); #ifdef CONFIG_DEBUG_RODATA void mark_rodata_ro(void); +extern const int rodata_test_data; #endif + #ifdef CONFIG_DEBUG_RODATA_TEST -void rodata_test(void); +int rodata_test(void); #else -static inline void rodata_test(void) +static inline int rodata_test(void) { + return 0; } #endif diff --git a/include/asm-x86/desc_64.h b/include/asm-x86/desc_64.h deleted file mode 100644 index 8b137891791f..000000000000 --- a/include/asm-x86/desc_64.h +++ /dev/null @@ -1 +0,0 @@ - diff --git a/include/asm-x86/i387.h b/include/asm-x86/i387.h index 6b1895ccd6b7..f377b76b2f34 100644 --- a/include/asm-x86/i387.h +++ b/include/asm-x86/i387.h @@ -20,7 +20,6 @@ #include extern void fpu_init(void); -extern unsigned int mxcsr_feature_mask; extern void mxcsr_feature_mask_init(void); extern void init_fpu(struct task_struct *child); extern asmlinkage void math_state_restore(void); diff --git a/include/asm-x86/kdebug.h b/include/asm-x86/kdebug.h index dd442a1632c0..99dcbafa1511 100644 --- a/include/asm-x86/kdebug.h +++ b/include/asm-x86/kdebug.h @@ -31,7 +31,6 @@ extern void show_trace(struct task_struct *t, struct pt_regs *regs, unsigned long *sp, unsigned long bp); extern void __show_regs(struct pt_regs *regs); extern void show_regs(struct pt_regs *regs); -extern void dump_pagetable(unsigned long); extern unsigned long oops_begin(void); extern void oops_end(unsigned long, struct pt_regs *, int signr); diff --git a/include/asm-x86/pgtable_64.h b/include/asm-x86/pgtable_64.h index bd4740a60f29..0a0b77bc736a 100644 --- a/include/asm-x86/pgtable_64.h +++ b/include/asm-x86/pgtable_64.h @@ -188,6 +188,7 @@ static inline unsigned long pmd_bad(pmd_t pmd) #define pgd_offset(mm, addr) ((mm)->pgd + pgd_index(addr)) #define pgd_offset_k(address) (init_level4_pgt + pgd_index(address)) #define pgd_present(pgd) (pgd_val(pgd) & _PAGE_PRESENT) +static inline int pgd_large(pgd_t pgd) { return 0; } #define mk_kernel_pgd(address) ((pgd_t){ (address) | _KERNPG_TABLE }) /* PUD - Level3 access */ @@ -246,6 +247,7 @@ static inline int pud_large(pud_t pte) #define __swp_entry_to_pte(x) ((pte_t) { .pte = (x).val }) extern int kern_addr_valid(unsigned long addr); +extern void cleanup_highmap(void); #define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \ remap_pfn_range(vma, vaddr, pfn, size, prot) diff --git a/include/asm-x86/processor.h b/include/asm-x86/processor.h index 149920dcd341..45a2f0ab33d0 100644 --- a/include/asm-x86/processor.h +++ b/include/asm-x86/processor.h @@ -302,10 +302,6 @@ union i387_union { }; #ifdef CONFIG_X86_32 -/* - * the following now lives in the per cpu area: - * extern int cpu_llc_id[NR_CPUS]; - */ DECLARE_PER_CPU(u8, cpu_llc_id); #else DECLARE_PER_CPU(struct orig_ist, orig_ist); @@ -671,7 +667,6 @@ extern void init_gdt(int cpu); extern unsigned int machine_id; extern unsigned int machine_submodel_id; extern unsigned int BIOS_revision; -extern unsigned int mca_pentium_flag; /* Boot loader type from the setup header */ extern int bootloader_type; diff --git a/include/asm-xtensa/cacheflush.h b/include/asm-xtensa/cacheflush.h index b773c57e75a5..94c4c53a099e 100644 --- a/include/asm-xtensa/cacheflush.h +++ b/include/asm-xtensa/cacheflush.h @@ -70,6 +70,8 @@ extern void __flush_invalidate_dcache_page_alias(unsigned long, unsigned long); #endif #if (ICACHE_WAY_SIZE > PAGE_SIZE) extern void __invalidate_icache_page_alias(unsigned long, unsigned long); +#else +# define __invalidate_icache_page_alias(v,p) do { } while(0) #endif /* diff --git a/include/asm-xtensa/coprocessor.h b/include/asm-xtensa/coprocessor.h index aa2121034558..1cbcf9001a41 100644 --- a/include/asm-xtensa/coprocessor.h +++ b/include/asm-xtensa/coprocessor.h @@ -5,81 +5,173 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2003 - 2005 Tensilica Inc. + * Copyright (C) 2003 - 2007 Tensilica Inc. */ + #ifndef _XTENSA_COPROCESSOR_H #define _XTENSA_COPROCESSOR_H -#include +#include #include +#include -#if !XCHAL_HAVE_CP +#ifdef __ASSEMBLY__ +# include -#define XTENSA_CP_EXTRA_OFFSET 0 -#define XTENSA_CP_EXTRA_ALIGN 1 /* must be a power of 2 */ -#define XTENSA_CP_EXTRA_SIZE 0 +.macro xchal_sa_start a b + .set .Lxchal_pofs_, 0 + .set .Lxchal_ofs_, 0 +.endm -#else +.macro xchal_sa_align ptr minofs maxofs ofsalign totalign + .set .Lxchal_ofs_, .Lxchal_ofs_ + .Lxchal_pofs_ + \totalign - 1 + .set .Lxchal_ofs_, (.Lxchal_ofs_ & -\totalign) - .Lxchal_pofs_ +.endm -#define XTOFS(last_start,last_size,align) \ - ((last_start+last_size+align-1) & -align) +#define _SELECT ( XTHAL_SAS_TIE | XTHAL_SAS_OPT \ + | XTHAL_SAS_CC \ + | XTHAL_SAS_CALR | XTHAL_SAS_CALE ) -#define XTENSA_CP_EXTRA_OFFSET 0 -#define XTENSA_CP_EXTRA_ALIGN XCHAL_EXTRA_SA_ALIGN +.macro save_xtregs_opt ptr clb at1 at2 at3 at4 offset + .if XTREGS_OPT_SIZE > 0 + addi \clb, \ptr, \offset + xchal_ncp_store \clb \at1 \at2 \at3 \at4 select=_SELECT + .endif +.endm -#define XTENSA_CPE_CP0_OFFSET \ - XTOFS(XTENSA_CP_EXTRA_OFFSET, XCHAL_EXTRA_SA_SIZE, XCHAL_CP0_SA_ALIGN) -#define XTENSA_CPE_CP1_OFFSET \ - XTOFS(XTENSA_CPE_CP0_OFFSET, XCHAL_CP0_SA_SIZE, XCHAL_CP1_SA_ALIGN) -#define XTENSA_CPE_CP2_OFFSET \ - XTOFS(XTENSA_CPE_CP1_OFFSET, XCHAL_CP1_SA_SIZE, XCHAL_CP2_SA_ALIGN) -#define XTENSA_CPE_CP3_OFFSET \ - XTOFS(XTENSA_CPE_CP2_OFFSET, XCHAL_CP2_SA_SIZE, XCHAL_CP3_SA_ALIGN) -#define XTENSA_CPE_CP4_OFFSET \ - XTOFS(XTENSA_CPE_CP3_OFFSET, XCHAL_CP3_SA_SIZE, XCHAL_CP4_SA_ALIGN) -#define XTENSA_CPE_CP5_OFFSET \ - XTOFS(XTENSA_CPE_CP4_OFFSET, XCHAL_CP4_SA_SIZE, XCHAL_CP5_SA_ALIGN) -#define XTENSA_CPE_CP6_OFFSET \ - XTOFS(XTENSA_CPE_CP5_OFFSET, XCHAL_CP5_SA_SIZE, XCHAL_CP6_SA_ALIGN) -#define XTENSA_CPE_CP7_OFFSET \ - XTOFS(XTENSA_CPE_CP6_OFFSET, XCHAL_CP6_SA_SIZE, XCHAL_CP7_SA_ALIGN) -#define XTENSA_CP_EXTRA_SIZE \ - XTOFS(XTENSA_CPE_CP7_OFFSET, XCHAL_CP7_SA_SIZE, 16) +.macro load_xtregs_opt ptr clb at1 at2 at3 at4 offset + .if XTREGS_OPT_SIZE > 0 + addi \clb, \ptr, \offset + xchal_ncp_load \clb \at1 \at2 \at3 \at4 select=_SELECT + .endif +.endm +#undef _SELECT + +#define _SELECT ( XTHAL_SAS_TIE | XTHAL_SAS_OPT \ + | XTHAL_SAS_NOCC \ + | XTHAL_SAS_CALR | XTHAL_SAS_CALE | XTHAL_SAS_GLOB ) + +.macro save_xtregs_user ptr clb at1 at2 at3 at4 offset + .if XTREGS_USER_SIZE > 0 + addi \clb, \ptr, \offset + xchal_ncp_store \clb \at1 \at2 \at3 \at4 select=_SELECT + .endif +.endm + +.macro load_xtregs_user ptr clb at1 at2 at3 at4 offset + .if XTREGS_USER_SIZE > 0 + addi \clb, \ptr, \offset + xchal_ncp_load \clb \at1 \at2 \at3 \at4 select=_SELECT + .endif +.endm +#undef _SELECT + + + +#endif /* __ASSEMBLY__ */ -#if XCHAL_CP_NUM > 0 -# ifndef __ASSEMBLY__ /* - * Tasks that own contents of (last user) each coprocessor. - * Entries are 0 for not-owned or non-existent coprocessors. - * Note: The size of this structure is fixed to 8 bytes in entry.S + * XTENSA_HAVE_COPROCESSOR(x) returns 1 if coprocessor x is configured. + * + * XTENSA_HAVE_IO_PORT(x) returns 1 if io-port x is configured. + * */ -typedef struct { - struct task_struct *owner; /* owner */ - int offset; /* offset in cpextra space. */ -} coprocessor_info_t; -# else -# define COPROCESSOR_INFO_OWNER 0 -# define COPROCESSOR_INFO_OFFSET 4 -# define COPROCESSOR_INFO_SIZE 8 -# endif -#endif -#endif /* XCHAL_HAVE_CP */ +#define XTENSA_HAVE_COPROCESSOR(x) \ + ((XCHAL_CP_MASK ^ XCHAL_CP_PORT_MASK) & (1 << (x))) +#define XTENSA_HAVE_COPROCESSORS \ + (XCHAL_CP_MASK ^ XCHAL_CP_PORT_MASK) +#define XTENSA_HAVE_IO_PORT(x) \ + (XCHAL_CP_PORT_MASK & (1 << (x))) +#define XTENSA_HAVE_IO_PORTS \ + XCHAL_CP_PORT_MASK #ifndef __ASSEMBLY__ -# if XCHAL_CP_NUM > 0 -struct task_struct; -extern void release_coprocessors (struct task_struct*); -extern void save_coprocessor_registers(void*, int); -# else -# define release_coprocessors(task) -# endif -typedef unsigned char cp_state_t[XTENSA_CP_EXTRA_SIZE] - __attribute__ ((aligned (XTENSA_CP_EXTRA_ALIGN))); + +#if XCHAL_HAVE_CP + +#define RSR_CPENABLE(x) do { \ + __asm__ __volatile__("rsr %0," __stringify(CPENABLE) : "=a" (x)); \ + } while(0); +#define WSR_CPENABLE(x) do { \ + __asm__ __volatile__("wsr %0," __stringify(CPENABLE) "; rsync" \ + :: "a" (x)); \ + } while(0); + +#endif /* XCHAL_HAVE_CP */ + + +/* + * Additional registers. + * We define three types of additional registers: + * ext: extra registers that are used by the compiler + * cpn: optional registers that can be used by a user application + * cpX: coprocessor registers that can only be used if the corresponding + * CPENABLE bit is set. + */ + +#define XCHAL_SA_REG(list,cc,abi,type,y,name,z,align,size,...) \ + __REG ## list (cc, abi, type, name, size, align) + +#define __REG0(cc,abi,t,name,s,a) __REG0_ ## cc (abi,name) +#define __REG1(cc,abi,t,name,s,a) __REG1_ ## cc (name) +#define __REG2(cc,abi,type,...) __REG2_ ## type (__VA_ARGS__) + +#define __REG0_0(abi,name) +#define __REG0_1(abi,name) __REG0_1 ## abi (name) +#define __REG0_10(name) __u32 name; +#define __REG0_11(name) __u32 name; +#define __REG0_12(name) + +#define __REG1_0(name) __u32 name; +#define __REG1_1(name) + +#define __REG2_0(n,s,a) __u32 name; +#define __REG2_1(n,s,a) unsigned char n[s] __attribute__ ((aligned(a))); +#define __REG2_2(n,s,a) unsigned char n[s] __attribute__ ((aligned(a))); + +typedef struct { XCHAL_NCP_SA_LIST(0) } xtregs_opt_t + __attribute__ ((aligned (XCHAL_NCP_SA_ALIGN))); +typedef struct { XCHAL_NCP_SA_LIST(1) } xtregs_user_t + __attribute__ ((aligned (XCHAL_NCP_SA_ALIGN))); + +#if XTENSA_HAVE_COPROCESSORS + +typedef struct { XCHAL_CP0_SA_LIST(2) } xtregs_cp0_t + __attribute__ ((aligned (XCHAL_CP0_SA_ALIGN))); +typedef struct { XCHAL_CP1_SA_LIST(2) } xtregs_cp1_t + __attribute__ ((aligned (XCHAL_CP1_SA_ALIGN))); +typedef struct { XCHAL_CP2_SA_LIST(2) } xtregs_cp2_t + __attribute__ ((aligned (XCHAL_CP2_SA_ALIGN))); +typedef struct { XCHAL_CP3_SA_LIST(2) } xtregs_cp3_t + __attribute__ ((aligned (XCHAL_CP3_SA_ALIGN))); +typedef struct { XCHAL_CP4_SA_LIST(2) } xtregs_cp4_t + __attribute__ ((aligned (XCHAL_CP4_SA_ALIGN))); +typedef struct { XCHAL_CP5_SA_LIST(2) } xtregs_cp5_t + __attribute__ ((aligned (XCHAL_CP5_SA_ALIGN))); +typedef struct { XCHAL_CP6_SA_LIST(2) } xtregs_cp6_t + __attribute__ ((aligned (XCHAL_CP6_SA_ALIGN))); +typedef struct { XCHAL_CP7_SA_LIST(2) } xtregs_cp7_t + __attribute__ ((aligned (XCHAL_CP7_SA_ALIGN))); + +extern struct thread_info* coprocessor_owner[XCHAL_CP_MAX]; +extern void coprocessor_save(void*, int); +extern void coprocessor_load(void*, int); +extern void coprocessor_flush(struct thread_info*, int); +extern void coprocessor_restore(struct thread_info*, int); + +extern void coprocessor_release_all(struct thread_info*); +extern void coprocessor_flush_all(struct thread_info*); + +static inline void coprocessor_clear_cpenable(void) +{ + unsigned long i = 0; + WSR_CPENABLE(i); +} + +#endif /* XTENSA_HAVE_COPROCESSORS */ #endif /* !__ASSEMBLY__ */ - - #endif /* _XTENSA_COPROCESSOR_H */ diff --git a/include/asm-xtensa/elf.h b/include/asm-xtensa/elf.h index 467384542502..ca6e5101a2cb 100644 --- a/include/asm-xtensa/elf.h +++ b/include/asm-xtensa/elf.h @@ -72,115 +72,32 @@ /* ELF register definitions. This is needed for core dump support. */ -/* - * elf_gregset_t contains the application-level state in the following order: - * Processor info: config_version, cpuxy - * Processor state: pc, ps, exccause, excvaddr, wb, ws, - * lbeg, lend, lcount, sar - * GP regs: ar0 - arXX - */ - typedef unsigned long elf_greg_t; typedef struct { - elf_greg_t xchal_config_id0; - elf_greg_t xchal_config_id1; - elf_greg_t cpux; - elf_greg_t cpuy; elf_greg_t pc; elf_greg_t ps; - elf_greg_t exccause; - elf_greg_t excvaddr; - elf_greg_t windowbase; - elf_greg_t windowstart; elf_greg_t lbeg; elf_greg_t lend; elf_greg_t lcount; elf_greg_t sar; - elf_greg_t syscall; - elf_greg_t ar[64]; + elf_greg_t windowstart; + elf_greg_t windowbase; + elf_greg_t reserved[8+48]; + elf_greg_t a[64]; } xtensa_gregset_t; #define ELF_NGREG (sizeof(xtensa_gregset_t) / sizeof(elf_greg_t)) typedef elf_greg_t elf_gregset_t[ELF_NGREG]; -/* - * Compute the size of the coprocessor and extra state layout (register info) - * table (in bytes). - * This is actually the maximum size of the table, as opposed to the size, - * which is available from the _xtensa_reginfo_table_size global variable. - * - * (See also arch/xtensa/kernel/coprocessor.S) - * - */ - -#ifndef XCHAL_EXTRA_SA_CONTENTS_LIBDB_NUM -# define XTENSA_CPE_LTABLE_SIZE 0 -#else -# define XTENSA_CPE_SEGMENT(num) (num ? (1+num) : 0) -# define XTENSA_CPE_LTABLE_ENTRIES \ - ( XTENSA_CPE_SEGMENT(XCHAL_EXTRA_SA_CONTENTS_LIBDB_NUM) \ - + XTENSA_CPE_SEGMENT(XCHAL_CP0_SA_CONTENTS_LIBDB_NUM) \ - + XTENSA_CPE_SEGMENT(XCHAL_CP1_SA_CONTENTS_LIBDB_NUM) \ - + XTENSA_CPE_SEGMENT(XCHAL_CP2_SA_CONTENTS_LIBDB_NUM) \ - + XTENSA_CPE_SEGMENT(XCHAL_CP3_SA_CONTENTS_LIBDB_NUM) \ - + XTENSA_CPE_SEGMENT(XCHAL_CP4_SA_CONTENTS_LIBDB_NUM) \ - + XTENSA_CPE_SEGMENT(XCHAL_CP5_SA_CONTENTS_LIBDB_NUM) \ - + XTENSA_CPE_SEGMENT(XCHAL_CP6_SA_CONTENTS_LIBDB_NUM) \ - + XTENSA_CPE_SEGMENT(XCHAL_CP7_SA_CONTENTS_LIBDB_NUM) \ - + 1 /* final entry */ \ - ) -# define XTENSA_CPE_LTABLE_SIZE (XTENSA_CPE_LTABLE_ENTRIES * 8) -#endif - - -/* - * Instantiations of the elf_fpregset_t type contain, in most - * architectures, the floating point (FPU) register set. - * For Xtensa, this type is extended to contain all custom state, - * ie. coprocessor and "extra" (non-coprocessor) state (including, - * for example, TIE-defined states and register files; as well - * as other optional processor state). - * This includes FPU state if a floating-point coprocessor happens - * to have been configured within the Xtensa processor. - * - * TOTAL_FPREGS_SIZE is the required size (without rounding) - * of elf_fpregset_t. It provides space for the following: - * - * a) 32-bit mask of active coprocessors for this task (similar - * to CPENABLE in single-threaded Xtensa processor systems) - * - * b) table describing the layout of custom states (ie. of - * individual registers, etc) within the save areas - * - * c) save areas for each coprocessor and for non-coprocessor - * ("extra") state - * - * Note that save areas may require up to 16-byte alignment when - * accessed by save/restore sequences. We do not need to ensure - * such alignment in an elf_fpregset_t structure because custom - * state is not directly loaded/stored into it; rather, save area - * contents are copied to elf_fpregset_t from the active save areas - * (see 'struct task_struct' definition in processor.h for that) - * using memcpy(). But we do allow space for such alignment, - * to allow optimizations of layout and copying. - */ -#if 0 -#define TOTAL_FPREGS_SIZE \ - (4 + XTENSA_CPE_LTABLE_SIZE + XTENSA_CP_EXTRA_SIZE) -#define ELF_NFPREG \ - ((TOTAL_FPREGS_SIZE + sizeof(elf_fpreg_t) - 1) / sizeof(elf_fpreg_t)) -#else -#define TOTAL_FPREGS_SIZE 0 -#define ELF_NFPREG 0 -#endif +#define ELF_NFPREG 18 typedef unsigned int elf_fpreg_t; typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; #define ELF_CORE_COPY_REGS(_eregs, _pregs) \ - xtensa_elf_core_copy_regs (&_eregs, _pregs); + xtensa_elf_core_copy_regs ((xtensa_gregset_t*)&(_eregs), _pregs); extern void xtensa_elf_core_copy_regs (xtensa_gregset_t *, struct pt_regs *); @@ -257,6 +174,21 @@ extern void xtensa_elf_core_copy_regs (xtensa_gregset_t *, struct pt_regs *); _r->areg[12]=0; _r->areg[13]=0; _r->areg[14]=0; _r->areg[15]=0; \ } while (0) +typedef struct { + xtregs_opt_t opt; + xtregs_user_t user; +#if XTENSA_HAVE_COPROCESSORS + xtregs_cp0_t cp0; + xtregs_cp1_t cp1; + xtregs_cp2_t cp2; + xtregs_cp3_t cp3; + xtregs_cp4_t cp4; + xtregs_cp5_t cp5; + xtregs_cp6_t cp6; + xtregs_cp7_t cp7; +#endif +} elf_xtregs_t; + #define SET_PERSONALITY(ex, ibcs2) set_personality(PER_LINUX_32BIT) struct task_struct; diff --git a/include/asm-xtensa/module.h b/include/asm-xtensa/module.h index ffb25bfdf6a1..d9b34bee4d42 100644 --- a/include/asm-xtensa/module.h +++ b/include/asm-xtensa/module.h @@ -15,9 +15,11 @@ struct mod_arch_specific { - /* Module support is not completely implemented. */ + /* No special elements, yet. */ }; +#define MODULE_ARCH_VERMAGIC "xtensa-" __stringify(XCHAL_CORE_ID) " " + #define Elf_Shdr Elf32_Shdr #define Elf_Sym Elf32_Sym #define Elf_Ehdr Elf32_Ehdr diff --git a/include/asm-xtensa/pgalloc.h b/include/asm-xtensa/pgalloc.h index 8d1544eb461e..4f4a7987eded 100644 --- a/include/asm-xtensa/pgalloc.h +++ b/include/asm-xtensa/pgalloc.h @@ -47,7 +47,7 @@ static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, return kmem_cache_alloc(pgtable_cache, GFP_KERNEL|__GFP_REPEAT); } -static inline pte_token_t pte_alloc_one(struct mm_struct *mm, +static inline pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long addr) { struct page *page; diff --git a/include/asm-xtensa/pgtable.h b/include/asm-xtensa/pgtable.h index c0fcc1c9660c..c8b024a48b4d 100644 --- a/include/asm-xtensa/pgtable.h +++ b/include/asm-xtensa/pgtable.h @@ -66,11 +66,9 @@ */ #define VMALLOC_START 0xC0000000 -#define VMALLOC_END 0xC6FEFFFF -#define TLBTEMP_BASE_1 0xC6FF0000 -#define TLBTEMP_BASE_2 0xC6FF8000 -#define MODULE_START 0xC7000000 -#define MODULE_END 0xC7FFFFFF +#define VMALLOC_END 0xC7FEFFFF +#define TLBTEMP_BASE_1 0xC7FF0000 +#define TLBTEMP_BASE_2 0xC7FF8000 /* * Xtensa Linux config PTE layout (when present): diff --git a/include/asm-xtensa/processor.h b/include/asm-xtensa/processor.h index 96408f436624..4918a4e96d42 100644 --- a/include/asm-xtensa/processor.h +++ b/include/asm-xtensa/processor.h @@ -103,10 +103,6 @@ struct thread_struct { unsigned long dbreaka[XCHAL_NUM_DBREAK]; unsigned long dbreakc[XCHAL_NUM_DBREAK]; - /* Allocate storage for extra state and coprocessor state. */ - unsigned char cp_save[XTENSA_CP_EXTRA_SIZE] - __attribute__ ((aligned(XTENSA_CP_EXTRA_ALIGN))); - /* Make structure 16 bytes aligned. */ int align[0] __attribute__ ((aligned(16))); }; @@ -162,21 +158,16 @@ struct thread_struct { struct task_struct; struct mm_struct; -// FIXME: do we need release_thread for CP?? /* Free all resources held by a thread. */ #define release_thread(thread) do { } while(0) -// FIXME: do we need prepare_to_copy (lazy status) for CP?? /* Prepare to copy thread state - unlazy all lazy status */ -#define prepare_to_copy(tsk) do { } while (0) +extern void prepare_to_copy(struct task_struct*); -/* - * create a kernel thread without removing it from tasklists - */ +/* Create a kernel thread without removing it from tasklists */ extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); /* Copy and release all segment info associated with a VM */ - #define copy_segments(p, mm) do { } while(0) #define release_segments(mm) do { } while(0) #define forget_segments() do { } while (0) diff --git a/include/asm-xtensa/ptrace.h b/include/asm-xtensa/ptrace.h index 77ff02d307bb..422c73e26937 100644 --- a/include/asm-xtensa/ptrace.h +++ b/include/asm-xtensa/ptrace.h @@ -53,33 +53,30 @@ /* Registers used by strace */ -#define REG_A_BASE 0xfc000000 -#define REG_AR_BASE 0x04000000 -#define REG_PC 0x14000000 -#define REG_PS 0x080000e6 -#define REG_WB 0x08000048 -#define REG_WS 0x08000049 -#define REG_LBEG 0x08000000 -#define REG_LEND 0x08000001 -#define REG_LCOUNT 0x08000002 -#define REG_SAR 0x08000003 -#define REG_DEPC 0x080000c0 -#define REG_EXCCAUSE 0x080000e8 -#define REG_EXCVADDR 0x080000ee -#define SYSCALL_NR 0x1 +#define REG_A_BASE 0x0000 +#define REG_AR_BASE 0x0100 +#define REG_PC 0x0020 +#define REG_PS 0x02e6 +#define REG_WB 0x0248 +#define REG_WS 0x0249 +#define REG_LBEG 0x0200 +#define REG_LEND 0x0201 +#define REG_LCOUNT 0x0202 +#define REG_SAR 0x0203 -#define AR_REGNO_TO_A_REGNO(ar, wb) (ar - wb*4) & ~(XCHAL_NUM_AREGS - 1) +#define SYSCALL_NR 0x00ff /* Other PTRACE_ values defined in using values 0-9,16,17,24 */ -#define PTRACE_GETREGS 12 -#define PTRACE_SETREGS 13 -#define PTRACE_GETFPREGS 14 -#define PTRACE_SETFPREGS 15 -#define PTRACE_GETFPREGSIZE 18 +#define PTRACE_GETREGS 12 +#define PTRACE_SETREGS 13 +#define PTRACE_GETXTREGS 18 +#define PTRACE_SETXTREGS 19 #ifndef __ASSEMBLY__ +#ifdef __KERNEL__ + /* * This struct defines the way the registers are stored on the * kernel stack during a system call or other kernel entry. @@ -102,6 +99,9 @@ struct pt_regs { unsigned long icountlevel; /* 60 */ int reserved[1]; /* 64 */ + /* Additional configurable registers that are used by the compiler. */ + xtregs_opt_t xtregs_opt; + /* Make sure the areg field is 16 bytes aligned. */ int align[0] __attribute__ ((aligned(16))); @@ -111,8 +111,6 @@ struct pt_regs { unsigned long areg[16]; /* 128 (64) */ }; -#ifdef __KERNEL__ - #include # define task_pt_regs(tsk) ((struct pt_regs*) \ diff --git a/include/asm-xtensa/regs.h b/include/asm-xtensa/regs.h index c913d259faaa..d4baed246928 100644 --- a/include/asm-xtensa/regs.h +++ b/include/asm-xtensa/regs.h @@ -100,7 +100,14 @@ #define EXCCAUSE_DTLB_SIZE_RESTRICTION 27 #define EXCCAUSE_LOAD_CACHE_ATTRIBUTE 28 #define EXCCAUSE_STORE_CACHE_ATTRIBUTE 29 -#define EXCCAUSE_FLOATING_POINT 40 +#define EXCCAUSE_COPROCESSOR0_DISABLED 32 +#define EXCCAUSE_COPROCESSOR1_DISABLED 33 +#define EXCCAUSE_COPROCESSOR2_DISABLED 34 +#define EXCCAUSE_COPROCESSOR3_DISABLED 35 +#define EXCCAUSE_COPROCESSOR4_DISABLED 36 +#define EXCCAUSE_COPROCESSOR5_DISABLED 37 +#define EXCCAUSE_COPROCESSOR6_DISABLED 38 +#define EXCCAUSE_COPROCESSOR7_DISABLED 39 /* PS register fields. */ diff --git a/include/asm-xtensa/sigcontext.h b/include/asm-xtensa/sigcontext.h index e3381cee5059..03383af8c3b7 100644 --- a/include/asm-xtensa/sigcontext.h +++ b/include/asm-xtensa/sigcontext.h @@ -13,9 +13,6 @@ struct sigcontext { - unsigned long oldmask; - - /* CPU registers */ unsigned long sc_pc; unsigned long sc_ps; unsigned long sc_lbeg; @@ -25,6 +22,7 @@ struct sigcontext { unsigned long sc_acclo; unsigned long sc_acchi; unsigned long sc_a[16]; + void *sc_xtregs; }; #endif /* _XTENSA_SIGCONTEXT_H */ diff --git a/include/asm-xtensa/stat.h b/include/asm-xtensa/stat.h index 149f4bce092f..c4992038cee0 100644 --- a/include/asm-xtensa/stat.h +++ b/include/asm-xtensa/stat.h @@ -5,25 +5,23 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2001 - 2005 Tensilica Inc. + * Copyright (C) 2001 - 2007 Tensilica Inc. */ #ifndef _XTENSA_STAT_H #define _XTENSA_STAT_H -#include - #define STAT_HAVE_NSEC 1 struct stat { unsigned long st_dev; - ino_t st_ino; - mode_t st_mode; - nlink_t st_nlink; - uid_t st_uid; - gid_t st_gid; - unsigned int st_rdev; - off_t st_size; + unsigned long st_ino; + unsigned int st_mode; + unsigned int st_nlink; + unsigned int st_uid; + unsigned int st_gid; + unsigned long st_rdev; + long st_size; unsigned long st_blksize; unsigned long st_blocks; unsigned long st_atime; @@ -36,8 +34,6 @@ struct stat { unsigned long __unused5; }; -/* This matches struct stat64 in glibc-2.3 */ - struct stat64 { unsigned long long st_dev; /* Device */ unsigned long long st_ino; /* File serial number */ @@ -47,20 +43,14 @@ struct stat64 { unsigned int st_gid; /* Group ID of the file's group. */ unsigned long long st_rdev; /* Device number, if device. */ long long st_size; /* Size of file, in bytes. */ - long st_blksize; /* Optimal block size for I/O. */ + unsigned long st_blksize; /* Optimal block size for I/O. */ unsigned long __unused2; -#ifdef __XTENSA_EB__ - unsigned long __unused3; - long st_blocks; /* Number 512-byte blocks allocated. */ -#else - long st_blocks; /* Number 512-byte blocks allocated. */ - unsigned long __unused3; -#endif - long st_atime; /* Time of last access. */ + unsigned long long st_blocks; /* Number 512-byte blocks allocated. */ + unsigned long st_atime; /* Time of last access. */ unsigned long st_atime_nsec; - long st_mtime; /* Time of last modification. */ + unsigned long st_mtime; /* Time of last modification. */ unsigned long st_mtime_nsec; - long st_ctime; /* Time of last status change. */ + unsigned long st_ctime; /* Time of last status change. */ unsigned long st_ctime_nsec; unsigned long __unused4; unsigned long __unused5; diff --git a/include/asm-xtensa/system.h b/include/asm-xtensa/system.h index e0cb9116d8ab..62b1e8f3c13c 100644 --- a/include/asm-xtensa/system.h +++ b/include/asm-xtensa/system.h @@ -46,42 +46,6 @@ static inline int irqs_disabled(void) return flags & 0xf; } -#define RSR_CPENABLE(x) do { \ - __asm__ __volatile__("rsr %0," __stringify(CPENABLE) : "=a" (x)); \ - } while(0); -#define WSR_CPENABLE(x) do { \ - __asm__ __volatile__("wsr %0," __stringify(CPENABLE)";rsync" \ - :: "a" (x));} while(0); - -#define clear_cpenable() __clear_cpenable() - -static inline void __clear_cpenable(void) -{ -#if XCHAL_HAVE_CP - unsigned long i = 0; - WSR_CPENABLE(i); -#endif -} - -static inline void enable_coprocessor(int i) -{ -#if XCHAL_HAVE_CP - int cp; - RSR_CPENABLE(cp); - cp |= 1 << i; - WSR_CPENABLE(cp); -#endif -} - -static inline void disable_coprocessor(int i) -{ -#if XCHAL_HAVE_CP - int cp; - RSR_CPENABLE(cp); - cp &= ~(1 << i); - WSR_CPENABLE(cp); -#endif -} #define smp_read_barrier_depends() do { } while(0) #define read_barrier_depends() do { } while(0) @@ -111,7 +75,6 @@ extern void *_switch_to(void *last, void *next); #define switch_to(prev,next,last) \ do { \ - clear_cpenable(); \ (last) = _switch_to(prev, next); \ } while(0) @@ -244,7 +207,7 @@ static inline void spill_registers(void) "wsr a13," __stringify(SAR) "\n\t" "wsr a14," __stringify(PS) "\n\t" :: "a" (&a0), "a" (&ps) - : "a2", "a3", "a12", "a13", "a14", "a15", "memory"); + : "a2", "a3", "a4", "a7", "a11", "a12", "a13", "a14", "a15", "memory"); } #define arch_align_stack(x) (x) diff --git a/include/asm-xtensa/thread_info.h b/include/asm-xtensa/thread_info.h index 52c958285bcb..a2c640682ed9 100644 --- a/include/asm-xtensa/thread_info.h +++ b/include/asm-xtensa/thread_info.h @@ -27,6 +27,21 @@ #ifndef __ASSEMBLY__ +#if XTENSA_HAVE_COPROCESSORS + +typedef struct xtregs_coprocessor { + xtregs_cp0_t cp0; + xtregs_cp1_t cp1; + xtregs_cp2_t cp2; + xtregs_cp3_t cp3; + xtregs_cp4_t cp4; + xtregs_cp5_t cp5; + xtregs_cp6_t cp6; + xtregs_cp7_t cp7; +} xtregs_coprocessor_t; + +#endif + struct thread_info { struct task_struct *task; /* main task structure */ struct exec_domain *exec_domain; /* execution domain */ @@ -38,7 +53,13 @@ struct thread_info { mm_segment_t addr_limit; /* thread address space */ struct restart_block restart_block; + unsigned long cpenable; + /* Allocate storage for extra user states and coprocessor states. */ +#if XTENSA_HAVE_COPROCESSORS + xtregs_coprocessor_t xtregs_cp; +#endif + xtregs_user_t xtregs_user; }; #else /* !__ASSEMBLY__ */ diff --git a/include/asm-xtensa/timex.h b/include/asm-xtensa/timex.h index a5fca59fba9e..b83a8181d448 100644 --- a/include/asm-xtensa/timex.h +++ b/include/asm-xtensa/timex.h @@ -63,10 +63,10 @@ extern cycles_t cacheflush_time; * Register access. */ -#define WSR_CCOUNT(r) __asm__("wsr %0,"__stringify(CCOUNT) :: "a" (r)) -#define RSR_CCOUNT(r) __asm__("rsr %0,"__stringify(CCOUNT) : "=a" (r)) -#define WSR_CCOMPARE(x,r) __asm__("wsr %0,"__stringify(CCOMPARE)"+"__stringify(x) :: "a"(r)) -#define RSR_CCOMPARE(x,r) __asm__("rsr %0,"__stringify(CCOMPARE)"+"__stringify(x) : "=a"(r)) +#define WSR_CCOUNT(r) asm volatile ("wsr %0,"__stringify(CCOUNT) :: "a" (r)) +#define RSR_CCOUNT(r) asm volatile ("rsr %0,"__stringify(CCOUNT) : "=a" (r)) +#define WSR_CCOMPARE(x,r) asm volatile ("wsr %0,"__stringify(CCOMPARE)"+"__stringify(x) :: "a"(r)) +#define RSR_CCOMPARE(x,r) asm volatile ("rsr %0,"__stringify(CCOMPARE)"+"__stringify(x) : "=a"(r)) static inline unsigned long get_ccount (void) { diff --git a/include/asm-xtensa/uaccess.h b/include/asm-xtensa/uaccess.h index d6352da05b10..b8528426ab1f 100644 --- a/include/asm-xtensa/uaccess.h +++ b/include/asm-xtensa/uaccess.h @@ -26,6 +26,7 @@ #include #include #include +#include /* * These assembly macros mirror the C macros that follow below. They @@ -118,7 +119,7 @@ * destroyed (actually, (TASK_SIZE + 1 - size)) */ .macro user_ok aa, as, at, error - movi \at, (TASK_SIZE+1) + movi \at, __XTENSA_UL_CONST(TASK_SIZE) bgeu \as, \at, \error sub \at, \at, \as bgeu \aa, \at, \error @@ -226,20 +227,21 @@ extern long __put_user_bad(void); __pu_err; \ }) -#define __put_user_size(x,ptr,size,retval) \ -do { \ - retval = 0; \ - switch (size) { \ - case 1: __put_user_asm(x,ptr,retval,1,"s8i"); break; \ - case 2: __put_user_asm(x,ptr,retval,2,"s16i"); break; \ - case 4: __put_user_asm(x,ptr,retval,4,"s32i"); break; \ - case 8: { \ - __typeof__(*ptr) __v64 = x; \ - retval = __copy_to_user(ptr,&__v64,8); \ - break; \ - } \ - default: __put_user_bad(); \ - } \ +#define __put_user_size(x,ptr,size,retval) \ +do { \ + int __cb; \ + retval = 0; \ + switch (size) { \ + case 1: __put_user_asm(x,ptr,retval,1,"s8i",__cb); break; \ + case 2: __put_user_asm(x,ptr,retval,2,"s16i",__cb); break; \ + case 4: __put_user_asm(x,ptr,retval,4,"s32i",__cb); break; \ + case 8: { \ + __typeof__(*ptr) __v64 = x; \ + retval = __copy_to_user(ptr,&__v64,8); \ + break; \ + } \ + default: __put_user_bad(); \ + } \ } while (0) @@ -267,14 +269,14 @@ do { \ #define __check_align_1 "" #define __check_align_2 \ - " _bbci.l %2, 0, 1f \n" \ - " movi %0, %3 \n" \ + " _bbci.l %3, 0, 1f \n" \ + " movi %0, %4 \n" \ " _j 2f \n" #define __check_align_4 \ - " _bbsi.l %2, 0, 0f \n" \ - " _bbci.l %2, 1, 1f \n" \ - "0: movi %0, %3 \n" \ + " _bbsi.l %3, 0, 0f \n" \ + " _bbci.l %3, 1, 1f \n" \ + "0: movi %0, %4 \n" \ " _j 2f \n" @@ -286,24 +288,24 @@ do { \ * WARNING: If you modify this macro at all, verify that the * __check_align_* macros still work. */ -#define __put_user_asm(x, addr, err, align, insn) \ - __asm__ __volatile__( \ - __check_align_##align \ - "1: "insn" %1, %2, 0 \n" \ - "2: \n" \ - " .section .fixup,\"ax\" \n" \ - " .align 4 \n" \ - "4: \n" \ - " .long 2b \n" \ - "5: \n" \ - " l32r %2, 4b \n" \ - " movi %0, %3 \n" \ - " jx %2 \n" \ - " .previous \n" \ - " .section __ex_table,\"a\" \n" \ - " .long 1b, 5b \n" \ - " .previous" \ - :"=r" (err) \ +#define __put_user_asm(x, addr, err, align, insn, cb) \ + __asm__ __volatile__( \ + __check_align_##align \ + "1: "insn" %2, %3, 0 \n" \ + "2: \n" \ + " .section .fixup,\"ax\" \n" \ + " .align 4 \n" \ + "4: \n" \ + " .long 2b \n" \ + "5: \n" \ + " l32r %1, 4b \n" \ + " movi %0, %4 \n" \ + " jx %1 \n" \ + " .previous \n" \ + " .section __ex_table,\"a\" \n" \ + " .long 1b, 5b \n" \ + " .previous" \ + :"=r" (err), "=r" (cb) \ :"r" ((int)(x)), "r" (addr), "i" (-EFAULT), "0" (err)) #define __get_user_nocheck(x,ptr,size) \ @@ -328,11 +330,12 @@ extern long __get_user_bad(void); #define __get_user_size(x,ptr,size,retval) \ do { \ + int __cb; \ retval = 0; \ switch (size) { \ - case 1: __get_user_asm(x,ptr,retval,1,"l8ui"); break; \ - case 2: __get_user_asm(x,ptr,retval,2,"l16ui"); break; \ - case 4: __get_user_asm(x,ptr,retval,4,"l32i"); break; \ + case 1: __get_user_asm(x,ptr,retval,1,"l8ui",__cb); break; \ + case 2: __get_user_asm(x,ptr,retval,2,"l16ui",__cb); break; \ + case 4: __get_user_asm(x,ptr,retval,4,"l32i",__cb); break; \ case 8: retval = __copy_from_user(&x,ptr,8); break; \ default: (x) = __get_user_bad(); \ } \ @@ -343,25 +346,25 @@ do { \ * WARNING: If you modify this macro at all, verify that the * __check_align_* macros still work. */ -#define __get_user_asm(x, addr, err, align, insn) \ +#define __get_user_asm(x, addr, err, align, insn, cb) \ __asm__ __volatile__( \ __check_align_##align \ - "1: "insn" %1, %2, 0 \n" \ + "1: "insn" %2, %3, 0 \n" \ "2: \n" \ " .section .fixup,\"ax\" \n" \ " .align 4 \n" \ "4: \n" \ " .long 2b \n" \ "5: \n" \ - " l32r %2, 4b \n" \ - " movi %1, 0 \n" \ - " movi %0, %3 \n" \ - " jx %2 \n" \ + " l32r %1, 4b \n" \ + " movi %2, 0 \n" \ + " movi %0, %4 \n" \ + " jx %1 \n" \ " .previous \n" \ " .section __ex_table,\"a\" \n" \ " .long 1b, 5b \n" \ " .previous" \ - :"=r" (err), "=r" (x) \ + :"=r" (err), "=r" (cb), "=r" (x) \ :"r" (addr), "i" (-EFAULT), "0" (err)) diff --git a/include/asm-xtensa/variant-fsf/tie-asm.h b/include/asm-xtensa/variant-fsf/tie-asm.h new file mode 100644 index 000000000000..68a73bf4ffc5 --- /dev/null +++ b/include/asm-xtensa/variant-fsf/tie-asm.h @@ -0,0 +1,70 @@ +/* + * This header file contains assembly-language definitions (assembly + * macros, etc.) for this specific Xtensa processor's TIE extensions + * and options. It is customized to this Xtensa processor configuration. + * + * 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. + * + * Copyright (C) 1999-2008 Tensilica Inc. + */ + +#ifndef _XTENSA_CORE_TIE_ASM_H +#define _XTENSA_CORE_TIE_ASM_H + +/* Selection parameter values for save-area save/restore macros: */ +/* Option vs. TIE: */ +#define XTHAL_SAS_TIE 0x0001 /* custom extension or coprocessor */ +#define XTHAL_SAS_OPT 0x0002 /* optional (and not a coprocessor) */ +/* Whether used automatically by compiler: */ +#define XTHAL_SAS_NOCC 0x0004 /* not used by compiler w/o special opts/code */ +#define XTHAL_SAS_CC 0x0008 /* used by compiler without special opts/code */ +/* ABI handling across function calls: */ +#define XTHAL_SAS_CALR 0x0010 /* caller-saved */ +#define XTHAL_SAS_CALE 0x0020 /* callee-saved */ +#define XTHAL_SAS_GLOB 0x0040 /* global across function calls (in thread) */ +/* Misc */ +#define XTHAL_SAS_ALL 0xFFFF /* include all default NCP contents */ + + + +/* Macro to save all non-coprocessor (extra) custom TIE and optional state + * (not including zero-overhead loop registers). + * Save area ptr (clobbered): ptr (1 byte aligned) + * Scratch regs (clobbered): at1..at4 (only first XCHAL_NCP_NUM_ATMPS needed) + */ + .macro xchal_ncp_store ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL + xchal_sa_start \continue, \ofs + .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~\select + xchal_sa_align \ptr, 0, 1024-4, 4, 4 + rur \at1, THREADPTR // threadptr option + s32i \at1, \ptr, .Lxchal_ofs_ + 0 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 + .endif + .endm // xchal_ncp_store + +/* Macro to save all non-coprocessor (extra) custom TIE and optional state + * (not including zero-overhead loop registers). + * Save area ptr (clobbered): ptr (1 byte aligned) + * Scratch regs (clobbered): at1..at4 (only first XCHAL_NCP_NUM_ATMPS needed) + */ + .macro xchal_ncp_load ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL + xchal_sa_start \continue, \ofs + .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~\select + xchal_sa_align \ptr, 0, 1024-4, 4, 4 + l32i \at1, \ptr, .Lxchal_ofs_ + 0 + wur \at1, THREADPTR // threadptr option + .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 + .endif + .endm // xchal_ncp_load + + + +#define XCHAL_NCP_NUM_ATMPS 1 + + +#define XCHAL_SA_NUM_ATMPS 1 + +#endif /*_XTENSA_CORE_TIE_ASM_H*/ + diff --git a/include/asm-xtensa/variant-fsf/tie.h b/include/asm-xtensa/variant-fsf/tie.h index a73c71664918..bf4020116df5 100644 --- a/include/asm-xtensa/variant-fsf/tie.h +++ b/include/asm-xtensa/variant-fsf/tie.h @@ -1,22 +1,77 @@ /* - * Xtensa processor core configuration information. + * This header file describes this specific Xtensa processor's TIE extensions + * that extend basic Xtensa core functionality. It is customized to this + * Xtensa processor configuration. * * 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. * - * Copyright (C) 1999-2006 Tensilica Inc. + * Copyright (C) 1999-2007 Tensilica Inc. */ -#ifndef XTENSA_TIE_H -#define XTENSA_TIE_H - -/*---------------------------------------------------------------------- - COPROCESSORS and EXTRA STATE - ----------------------------------------------------------------------*/ +#ifndef _XTENSA_CORE_TIE_H +#define _XTENSA_CORE_TIE_H #define XCHAL_CP_NUM 0 /* number of coprocessors */ -#define XCHAL_CP_MASK 0x00 +#define XCHAL_CP_MAX 0 /* max CP ID + 1 (0 if none) */ +#define XCHAL_CP_MASK 0x00 /* bitmask of all CPs by ID */ +#define XCHAL_CP_PORT_MASK 0x00 /* bitmask of only port CPs */ -#endif /*XTENSA_CONFIG_TIE_H*/ +/* Basic parameters of each coprocessor: */ +#define XCHAL_CP7_NAME "XTIOP" +#define XCHAL_CP7_IDENT XTIOP +#define XCHAL_CP7_SA_SIZE 0 /* size of state save area */ +#define XCHAL_CP7_SA_ALIGN 1 /* min alignment of save area */ +#define XCHAL_CP_ID_XTIOP 7 /* coprocessor ID (0..7) */ + +/* Filler info for unassigned coprocessors, to simplify arrays etc: */ +#define XCHAL_NCP_SA_SIZE 0 +#define XCHAL_NCP_SA_ALIGN 1 +#define XCHAL_CP0_SA_SIZE 0 +#define XCHAL_CP0_SA_ALIGN 1 +#define XCHAL_CP1_SA_SIZE 0 +#define XCHAL_CP1_SA_ALIGN 1 +#define XCHAL_CP2_SA_SIZE 0 +#define XCHAL_CP2_SA_ALIGN 1 +#define XCHAL_CP3_SA_SIZE 0 +#define XCHAL_CP3_SA_ALIGN 1 +#define XCHAL_CP4_SA_SIZE 0 +#define XCHAL_CP4_SA_ALIGN 1 +#define XCHAL_CP5_SA_SIZE 0 +#define XCHAL_CP5_SA_ALIGN 1 +#define XCHAL_CP6_SA_SIZE 0 +#define XCHAL_CP6_SA_ALIGN 1 + +/* Save area for non-coprocessor optional and custom (TIE) state: */ +#define XCHAL_NCP_SA_SIZE 0 +#define XCHAL_NCP_SA_ALIGN 1 + +/* Total save area for optional and custom state (NCP + CPn): */ +#define XCHAL_TOTAL_SA_SIZE 0 /* with 16-byte align padding */ +#define XCHAL_TOTAL_SA_ALIGN 1 /* actual minimum alignment */ + +#define XCHAL_NCP_SA_NUM 0 +#define XCHAL_NCP_SA_LIST(s) +#define XCHAL_CP0_SA_NUM 0 +#define XCHAL_CP0_SA_LIST(s) +#define XCHAL_CP1_SA_NUM 0 +#define XCHAL_CP1_SA_LIST(s) +#define XCHAL_CP2_SA_NUM 0 +#define XCHAL_CP2_SA_LIST(s) +#define XCHAL_CP3_SA_NUM 0 +#define XCHAL_CP3_SA_LIST(s) +#define XCHAL_CP4_SA_NUM 0 +#define XCHAL_CP4_SA_LIST(s) +#define XCHAL_CP5_SA_NUM 0 +#define XCHAL_CP5_SA_LIST(s) +#define XCHAL_CP6_SA_NUM 0 +#define XCHAL_CP6_SA_LIST(s) +#define XCHAL_CP7_SA_NUM 0 +#define XCHAL_CP7_SA_LIST(s) + +/* Byte length of instruction from its first nibble (op0 field), per FLIX. */ +#define XCHAL_OP0_FORMAT_LENGTHS 3,3,3,3,3,3,3,3,2,2,2,2,2,2,3,3 + +#endif /*_XTENSA_CORE_TIE_H*/ diff --git a/include/linux/Kbuild b/include/linux/Kbuild index 5cae9b5960ea..aada32fffec2 100644 --- a/include/linux/Kbuild +++ b/include/linux/Kbuild @@ -70,7 +70,6 @@ header-y += fuse.h header-y += genetlink.h header-y += gen_stats.h header-y += gigaset_dev.h -header-y += hdsmart.h header-y += hysdn_if.h header-y += i2o-dev.h header-y += i8k.h @@ -211,6 +210,7 @@ unifdef-y += hayesesp.h unifdef-y += hdlcdrv.h unifdef-y += hdlc.h unifdef-y += hdreg.h +unifdef-y += hdsmart.h unifdef-y += hiddev.h unifdef-y += hpet.h unifdef-y += i2c.h diff --git a/include/linux/acpi.h b/include/linux/acpi.h index ddbe7efe590e..2c7e003356ac 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -203,6 +203,7 @@ extern bool wmi_has_guid(const char *guid); extern int acpi_blacklisted(void); #ifdef CONFIG_DMI extern void acpi_dmi_osi_linux(int enable, const struct dmi_system_id *d); +extern int acpi_osi_setup(char *str); #endif #ifdef CONFIG_ACPI_NUMA diff --git a/include/linux/aio.h b/include/linux/aio.h index a9931e2e5624..0d0b7f629bd3 100644 --- a/include/linux/aio.h +++ b/include/linux/aio.h @@ -105,7 +105,6 @@ struct kiocb { wait_queue_t ki_wait; loff_t ki_pos; - atomic_t ki_bio_count; /* num bio used for this iocb */ void *private; /* State that we remember to be able to restart/retry */ unsigned short ki_opcode; diff --git a/include/linux/audit.h b/include/linux/audit.h index 97153027207a..2af9ec025015 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -534,8 +534,7 @@ extern void audit_log_n_untrustedstring(struct audit_buffer *ab, const char *string); extern void audit_log_d_path(struct audit_buffer *ab, const char *prefix, - struct dentry *dentry, - struct vfsmount *vfsmnt); + struct path *path); extern void audit_log_lost(const char *message); /* Private API (for audit.c only) */ extern int audit_filter_user(struct netlink_skb_parms *cb, int type); @@ -552,7 +551,7 @@ extern int audit_enabled; #define audit_log_hex(a,b,l) do { ; } while (0) #define audit_log_untrustedstring(a,s) do { ; } while (0) #define audit_log_n_untrustedstring(a,n,s) do { ; } while (0) -#define audit_log_d_path(b,p,d,v) do { ; } while (0) +#define audit_log_d_path(b, p, d) do { ; } while (0) #define audit_enabled 0 #endif #endif diff --git a/include/linux/bio.h b/include/linux/bio.h index 4da441337d6e..4c59bdccd3ee 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -326,7 +326,6 @@ extern struct bio *bio_map_kern(struct request_queue *, void *, unsigned int, gfp_t); extern void bio_set_pages_dirty(struct bio *bio); extern void bio_check_pages_dirty(struct bio *bio); -extern void bio_release_pages(struct bio *bio); extern struct bio *bio_copy_user(struct request_queue *, unsigned long, unsigned int, int); extern int bio_uncopy_user(struct bio *); void zero_fill_bio(struct bio *bio); diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index e1888cc5b8ae..6fe67d1939c2 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -216,6 +216,7 @@ struct request { unsigned int cmd_len; unsigned char cmd[BLK_MAX_CDB]; + unsigned int raw_data_len; unsigned int data_len; unsigned int sense_len; void *data; @@ -258,6 +259,7 @@ struct bio_vec; typedef int (merge_bvec_fn) (struct request_queue *, struct bio *, struct bio_vec *); typedef void (prepare_flush_fn) (struct request_queue *, struct request *); typedef void (softirq_done_fn)(struct request *); +typedef int (dma_drain_needed_fn)(struct request *); enum blk_queue_state { Queue_down, @@ -294,6 +296,7 @@ struct request_queue merge_bvec_fn *merge_bvec_fn; prepare_flush_fn *prepare_flush_fn; softirq_done_fn *softirq_done_fn; + dma_drain_needed_fn *dma_drain_needed; /* * Dispatch queue sorting @@ -698,8 +701,9 @@ extern void blk_queue_max_hw_segments(struct request_queue *, unsigned short); extern void blk_queue_max_segment_size(struct request_queue *, unsigned int); extern void blk_queue_hardsect_size(struct request_queue *, unsigned short); extern void blk_queue_stack_limits(struct request_queue *t, struct request_queue *b); -extern int blk_queue_dma_drain(struct request_queue *q, void *buf, - unsigned int size); +extern int blk_queue_dma_drain(struct request_queue *q, + dma_drain_needed_fn *dma_drain_needed, + void *buf, unsigned int size); extern void blk_queue_segment_boundary(struct request_queue *, unsigned long); extern void blk_queue_prep_rq(struct request_queue *, prep_rq_fn *pfn); extern void blk_queue_merge_bvec(struct request_queue *, merge_bvec_fn *); diff --git a/include/linux/configfs.h b/include/linux/configfs.h index 8c6967f3fb11..4b287ad9371a 100644 --- a/include/linux/configfs.h +++ b/include/linux/configfs.h @@ -37,6 +37,7 @@ #ifdef __KERNEL__ +#include #include #include #include diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h index 385d45b616db..6b72a4584086 100644 --- a/include/linux/cpuidle.h +++ b/include/linux/cpuidle.h @@ -19,6 +19,7 @@ #define CPUIDLE_STATE_MAX 8 #define CPUIDLE_NAME_LEN 16 +#define CPUIDLE_DESC_LEN 32 struct cpuidle_device; @@ -29,6 +30,7 @@ struct cpuidle_device; struct cpuidle_state { char name[CPUIDLE_NAME_LEN]; + char desc[CPUIDLE_DESC_LEN]; void *driver_data; unsigned int flags; diff --git a/include/linux/dcache.h b/include/linux/dcache.h index c2c153f97e8f..6bd646096fa6 100644 --- a/include/linux/dcache.h +++ b/include/linux/dcache.h @@ -10,6 +10,7 @@ #include struct nameidata; +struct path; struct vfsmount; /* @@ -300,8 +301,8 @@ extern int d_validate(struct dentry *, struct dentry *); */ extern char *dynamic_dname(struct dentry *, char *, int, const char *, ...); -extern char * d_path(struct dentry *, struct vfsmount *, char *, int); - +extern char *d_path(struct path *, char *, int); + /* Allocation counts.. */ /** diff --git a/include/linux/dcookies.h b/include/linux/dcookies.h index 98c69ab80c84..24c806f12a6c 100644 --- a/include/linux/dcookies.h +++ b/include/linux/dcookies.h @@ -13,6 +13,7 @@ #ifdef CONFIG_PROFILING #include +#include #include struct dcookie_user; @@ -43,8 +44,7 @@ void dcookie_unregister(struct dcookie_user * user); * * Returns 0 on success, with *cookie filled in */ -int get_dcookie(struct dentry * dentry, struct vfsmount * vfsmnt, - unsigned long * cookie); +int get_dcookie(struct path *path, unsigned long *cookie); #else @@ -57,13 +57,12 @@ static inline void dcookie_unregister(struct dcookie_user * user) { return; } - -static inline int get_dcookie(struct dentry * dentry, - struct vfsmount * vfsmnt, unsigned long * cookie) + +static inline int get_dcookie(struct path *path, unsigned long *cookie) { return -ENOSYS; -} - +} + #endif /* CONFIG_PROFILING */ - + #endif /* DCOOKIES_H */ diff --git a/include/linux/dm9000.h b/include/linux/dm9000.h index 0008e2ad0c9f..a3750462f9e3 100644 --- a/include/linux/dm9000.h +++ b/include/linux/dm9000.h @@ -19,6 +19,8 @@ #define DM9000_PLATF_8BITONLY (0x0001) #define DM9000_PLATF_16BITONLY (0x0002) #define DM9000_PLATF_32BITONLY (0x0004) +#define DM9000_PLATF_EXT_PHY (0x0008) +#define DM9000_PLATF_NO_EEPROM (0x0010) /* platfrom data for platfrom device structure's platfrom_data field */ diff --git a/include/linux/fs.h b/include/linux/fs.h index 18cfbf76ec5b..b84b848431f2 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1284,8 +1284,10 @@ struct super_operations { * * I_DIRTY_SYNC Inode is dirty, but doesn't have to be written on * fdatasync(). i_atime is the usual cause. - * I_DIRTY_DATASYNC Inode is dirty and must be written on fdatasync(), f.e. - * because i_size changed. + * I_DIRTY_DATASYNC Data-related inode changes pending. We keep track of + * these changes separately from I_DIRTY_SYNC so that we + * don't have to write inode on fdatasync() when only + * mtime has changed in it. * I_DIRTY_PAGES Inode has dirty pages. Inode itself may be clean. * I_NEW get_new_inode() sets i_state to I_LOCK|I_NEW. Both * are cleared by unlock_new_inode(), called from iget(). @@ -1588,7 +1590,6 @@ extern void bd_set_size(struct block_device *, loff_t size); extern void bd_forget(struct inode *inode); extern void bdput(struct block_device *); extern struct block_device *open_by_devnum(dev_t, unsigned); -extern const struct address_space_operations def_blk_aops; #else static inline void bd_forget(struct inode *inode) {} #endif diff --git a/include/linux/fs_struct.h b/include/linux/fs_struct.h index 11a36ceddf73..282f54219129 100644 --- a/include/linux/fs_struct.h +++ b/include/linux/fs_struct.h @@ -1,15 +1,13 @@ #ifndef _LINUX_FS_STRUCT_H #define _LINUX_FS_STRUCT_H -struct dentry; -struct vfsmount; +#include struct fs_struct { atomic_t count; rwlock_t lock; int umask; - struct dentry * root, * pwd, * altroot; - struct vfsmount * rootmnt, * pwdmnt, * altrootmnt; + struct path root, pwd, altroot; }; #define INIT_FS { \ @@ -22,8 +20,8 @@ extern struct kmem_cache *fs_cachep; extern void exit_fs(struct task_struct *); extern void set_fs_altroot(void); -extern void set_fs_root(struct fs_struct *, struct vfsmount *, struct dentry *); -extern void set_fs_pwd(struct fs_struct *, struct vfsmount *, struct dentry *); +extern void set_fs_root(struct fs_struct *, struct path *); +extern void set_fs_pwd(struct fs_struct *, struct path *); extern struct fs_struct *copy_fs_struct(struct fs_struct *); extern void put_fs_struct(struct fs_struct *); diff --git a/include/linux/hdsmart.h b/include/linux/hdsmart.h index e69192159d40..4f4faf9d4238 100644 --- a/include/linux/hdsmart.h +++ b/include/linux/hdsmart.h @@ -17,7 +17,7 @@ #ifndef _LINUX_HDSMART_H #define _LINUX_HDSMART_H -#ifndef __KERNEL +#ifndef __KERNEL__ #define OFFLINE_FULL_SCAN 0 #define SHORT_SELF_TEST 1 #define EXTEND_SELF_TEST 2 @@ -121,6 +121,6 @@ typedef struct ata_smart_selftestlog_s { unsigned char resevered[2]; unsigned char chksum; } __attribute__ ((packed)) ata_smart_selftestlog_t; -#endif /* __KERNEL__ * +#endif /* __KERNEL__ */ #endif /* _LINUX_HDSMART_H */ diff --git a/include/linux/hid.h b/include/linux/hid.h index 3902690647b0..74ff57596eb1 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -528,7 +528,7 @@ int hid_set_field(struct hid_field *, unsigned, __s32); int hid_input_report(struct hid_device *, int type, u8 *, int, int); int hidinput_find_field(struct hid_device *hid, unsigned int type, unsigned int code, struct hid_field **field); int hidinput_mapping_quirks(struct hid_usage *, struct input_dev *, unsigned long **, int *); -void hidinput_event_quirks(struct hid_device *, struct hid_field *, struct hid_usage *, __s32); +int hidinput_event_quirks(struct hid_device *, struct hid_field *, struct hid_usage *, __s32); int hidinput_apple_event(struct hid_device *, struct input_dev *, struct hid_usage *, __s32); void hid_input_field(struct hid_device *hid, struct hid_field *field, __u8 *data, int interrupt); void hid_output_report(struct hid_report *report, __u8 *data); diff --git a/include/linux/if_ether.h b/include/linux/if_ether.h index e157c1399b61..42dc6a3571ec 100644 --- a/include/linux/if_ether.h +++ b/include/linux/if_ether.h @@ -129,8 +129,7 @@ extern ssize_t sysfs_format_mac(char *buf, const unsigned char *addr, int len); /* * Display a 6 byte device address (MAC) in a readable format. */ -extern char *print_mac(char *buf, const unsigned char *addr); -#define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x" +extern __pure char *print_mac(char *buf, const unsigned char *addr); #define MAC_BUF_SIZE 18 #define DECLARE_MAC_BUF(var) char var[MAC_BUF_SIZE] __maybe_unused diff --git a/include/linux/init.h b/include/linux/init.h index a404a0055dd7..fb58c0493cf2 100644 --- a/include/linux/init.h +++ b/include/linux/init.h @@ -42,6 +42,7 @@ discard it in modules) */ #define __init __section(.init.text) __cold #define __initdata __section(.init.data) +#define __initconst __section(.init.rodata) #define __exitdata __section(.exit.data) #define __exit_call __used __section(.exitcall.exit) @@ -106,6 +107,7 @@ #define __memexitconst __section(.memexit.rodata) /* For assembly routines */ +#define __HEAD .section ".head.text","ax" #define __INIT .section ".init.text","ax" #define __FINIT .previous diff --git a/include/linux/iocontext.h b/include/linux/iocontext.h index 593b222d9dcc..1b4ccf25b4d2 100644 --- a/include/linux/iocontext.h +++ b/include/linux/iocontext.h @@ -50,6 +50,7 @@ struct cfq_io_context { sector_t seek_mean; struct list_head queue_list; + struct hlist_node cic_list; void (*dtor)(struct io_context *); /* destructor */ void (*exit)(struct io_context *); /* called on task exit */ @@ -77,6 +78,7 @@ struct io_context { struct as_io_context *aic; struct radix_tree_root radix_root; + struct hlist_head cic_list; void *ioc_data; }; diff --git a/include/linux/ktime.h b/include/linux/ktime.h index 36c542b70c6d..2cd7fa73d1af 100644 --- a/include/linux/ktime.h +++ b/include/linux/ktime.h @@ -310,6 +310,8 @@ static inline ktime_t ktime_sub_us(const ktime_t kt, const u64 usec) return ktime_sub_ns(kt, usec * 1000); } +extern ktime_t ktime_add_safe(const ktime_t lhs, const ktime_t rhs); + /* * The resolution of the clocks. The resolution value is returned in * the clock_getres() system call to give application programmers an diff --git a/include/linux/libata.h b/include/linux/libata.h index bc5a8d0c7090..ce7603a73156 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -278,7 +278,6 @@ enum { /* size of buffer to pad xfers ending on unaligned boundaries */ ATA_DMA_PAD_SZ = 4, - ATA_DMA_PAD_BUF_SZ = ATA_DMA_PAD_SZ * ATA_MAX_QUEUE, /* ering size */ ATA_ERING_SIZE = 32, @@ -457,24 +456,18 @@ struct ata_queued_cmd { unsigned long flags; /* ATA_QCFLAG_xxx */ unsigned int tag; unsigned int n_elem; - unsigned int mapped_n_elem; int dma_dir; - unsigned int pad_len; unsigned int sect_size; unsigned int nbytes; - unsigned int raw_nbytes; unsigned int curbytes; struct scatterlist *cursg; unsigned int cursg_ofs; - struct scatterlist *last_sg; - struct scatterlist saved_last_sg; struct scatterlist sgent; - struct scatterlist extra_sg[2]; struct scatterlist *sg; @@ -619,9 +612,6 @@ struct ata_port { struct ata_prd *prd; /* our SG list */ dma_addr_t prd_dma; /* and its DMA mapping */ - void *pad; /* array of DMA pad buffers */ - dma_addr_t pad_dma; - struct ata_ioports ioaddr; /* ATA cmd/ctl/dma register blocks */ u8 ctl; /* cache of ATA control register */ @@ -1207,7 +1197,7 @@ static inline struct ata_link *ata_port_next_link(struct ata_link *link) return ap->pmp_link; } - if (++link - ap->pmp_link < ap->nr_pmp_links) + if (++link < ap->nr_pmp_links + ap->pmp_link) return link; return NULL; } @@ -1363,12 +1353,9 @@ static inline void ata_qc_reinit(struct ata_queued_cmd *qc) qc->flags = 0; qc->cursg = NULL; qc->cursg_ofs = 0; - qc->nbytes = qc->raw_nbytes = qc->curbytes = 0; + qc->nbytes = qc->curbytes = 0; qc->n_elem = 0; - qc->mapped_n_elem = 0; qc->err_mask = 0; - qc->pad_len = 0; - qc->last_sg = NULL; qc->sect_size = ATA_SECT_SIZE; ata_tf_init(qc->dev, &qc->tf); @@ -1423,19 +1410,6 @@ static inline unsigned int __ac_err_mask(u8 status) return mask; } -static inline int ata_pad_alloc(struct ata_port *ap, struct device *dev) -{ - ap->pad_dma = 0; - ap->pad = dmam_alloc_coherent(dev, ATA_DMA_PAD_BUF_SZ, - &ap->pad_dma, GFP_KERNEL); - return (ap->pad == NULL) ? -ENOMEM : 0; -} - -static inline void ata_pad_free(struct ata_port *ap, struct device *dev) -{ - dmam_free_coherent(dev, ATA_DMA_PAD_BUF_SZ, ap->pad, ap->pad_dma); -} - static inline struct ata_port *ata_shost_to_port(struct Scsi_Host *host) { return *(struct ata_port **)&host->hostdata[0]; diff --git a/include/linux/maple.h b/include/linux/maple.h index bad9a7b319de..3f01e2bae1a1 100644 --- a/include/linux/maple.h +++ b/include/linux/maple.h @@ -7,74 +7,74 @@ extern struct bus_type maple_bus_type; /* Maple Bus command and response codes */ enum maple_code { - MAPLE_RESPONSE_FILEERR = -5, - MAPLE_RESPONSE_AGAIN = -4, /* request should be retransmitted */ - MAPLE_RESPONSE_BADCMD = -3, - MAPLE_RESPONSE_BADFUNC = -2, - MAPLE_RESPONSE_NONE = -1, /* unit didn't respond at all */ - MAPLE_COMMAND_DEVINFO = 1, - MAPLE_COMMAND_ALLINFO = 2, - MAPLE_COMMAND_RESET = 3, - MAPLE_COMMAND_KILL = 4, - MAPLE_RESPONSE_DEVINFO = 5, - MAPLE_RESPONSE_ALLINFO = 6, - MAPLE_RESPONSE_OK = 7, - MAPLE_RESPONSE_DATATRF = 8, - MAPLE_COMMAND_GETCOND = 9, - MAPLE_COMMAND_GETMINFO = 10, - MAPLE_COMMAND_BREAD = 11, - MAPLE_COMMAND_BWRITE = 12, - MAPLE_COMMAND_SETCOND = 14 + MAPLE_RESPONSE_FILEERR = -5, + MAPLE_RESPONSE_AGAIN = -4, /* request should be retransmitted */ + MAPLE_RESPONSE_BADCMD = -3, + MAPLE_RESPONSE_BADFUNC = -2, + MAPLE_RESPONSE_NONE = -1, /* unit didn't respond at all */ + MAPLE_COMMAND_DEVINFO = 1, + MAPLE_COMMAND_ALLINFO = 2, + MAPLE_COMMAND_RESET = 3, + MAPLE_COMMAND_KILL = 4, + MAPLE_RESPONSE_DEVINFO = 5, + MAPLE_RESPONSE_ALLINFO = 6, + MAPLE_RESPONSE_OK = 7, + MAPLE_RESPONSE_DATATRF = 8, + MAPLE_COMMAND_GETCOND = 9, + MAPLE_COMMAND_GETMINFO = 10, + MAPLE_COMMAND_BREAD = 11, + MAPLE_COMMAND_BWRITE = 12, + MAPLE_COMMAND_SETCOND = 14 }; struct mapleq { - struct list_head list; - struct maple_device *dev; - void *sendbuf, *recvbuf, *recvbufdcsp; - unsigned char length; - enum maple_code command; + struct list_head list; + struct maple_device *dev; + void *sendbuf, *recvbuf, *recvbufdcsp; + unsigned char length; + enum maple_code command; }; struct maple_devinfo { - unsigned long function; - unsigned long function_data[3]; - unsigned char area_code; - unsigned char connector_directon; - char product_name[31]; - char product_licence[61]; - unsigned short standby_power; - unsigned short max_power; + unsigned long function; + unsigned long function_data[3]; + unsigned char area_code; + unsigned char connector_direction; + char product_name[31]; + char product_licence[61]; + unsigned short standby_power; + unsigned short max_power; }; struct maple_device { - struct maple_driver *driver; - struct mapleq *mq; - void *private_data; - void (*callback) (struct mapleq * mq); - unsigned long when, interval, function; - struct maple_devinfo devinfo; - unsigned char port, unit; - char product_name[32]; - char product_licence[64]; - int registered; - struct device dev; + struct maple_driver *driver; + struct mapleq *mq; + void *private_data; + void (*callback) (struct mapleq * mq); + unsigned long when, interval, function; + struct maple_devinfo devinfo; + unsigned char port, unit; + char product_name[32]; + char product_licence[64]; + struct device dev; }; struct maple_driver { - unsigned long function; - int (*connect) (struct maple_device * dev); - void (*disconnect) (struct maple_device * dev); - struct device_driver drv; + unsigned long function; + int (*connect) (struct maple_device * dev); + void (*disconnect) (struct maple_device * dev); + struct device_driver drv; + int registered; }; void maple_getcond_callback(struct maple_device *dev, - void (*callback) (struct mapleq * mq), - unsigned long interval, - unsigned long function); + void (*callback) (struct mapleq * mq), + unsigned long interval, + unsigned long function); int maple_driver_register(struct device_driver *drv); void maple_add_packet(struct mapleq *mq); #define to_maple_dev(n) container_of(n, struct maple_device, dev) #define to_maple_driver(n) container_of(n, struct maple_driver, drv) -#endif /* __LINUX_MAPLE_H */ +#endif /* __LINUX_MAPLE_H */ diff --git a/include/linux/mm.h b/include/linux/mm.h index 26c7124b841a..3b3e1341163f 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -1171,12 +1171,18 @@ static inline void enable_debug_pagealloc(void) { debug_pagealloc_enabled = 1; } +#ifdef CONFIG_HIBERNATION +extern bool kernel_page_present(struct page *page); +#endif /* CONFIG_HIBERNATION */ #else static inline void kernel_map_pages(struct page *page, int numpages, int enable) {} static inline void enable_debug_pagealloc(void) { } +#ifdef CONFIG_HIBERNATION +static inline bool kernel_page_present(struct page *page) { return true; } +#endif /* CONFIG_HIBERNATION */ #endif extern struct vm_area_struct *get_gate_vma(struct task_struct *tsk); diff --git a/include/linux/module.h b/include/linux/module.h index 330bec08c2c4..819c4e889bf1 100644 --- a/include/linux/module.h +++ b/include/linux/module.h @@ -567,8 +567,7 @@ static inline void print_modules(void) { } -static inline void module_update_markers(struct module *probe_module, - int *refcount) +static inline void module_update_markers(void) { } diff --git a/include/linux/namei.h b/include/linux/namei.h index c13e411491f4..24d88e98a626 100644 --- a/include/linux/namei.h +++ b/include/linux/namei.h @@ -3,6 +3,7 @@ #include #include +#include struct vfsmount; @@ -15,8 +16,7 @@ struct open_intent { enum { MAX_NESTED_LINKS = 8 }; struct nameidata { - struct dentry *dentry; - struct vfsmount *mnt; + struct path path; struct qstr last; unsigned int flags; int last_type; @@ -29,11 +29,6 @@ struct nameidata { } intent; }; -struct path { - struct vfsmount *mnt; - struct dentry *dentry; -}; - /* * Type of the last component on LOOKUP_PARENT */ @@ -71,8 +66,6 @@ extern int __user_walk_fd(int dfd, const char __user *, unsigned, struct nameida extern int path_lookup(const char *, unsigned, struct nameidata *); extern int vfs_path_lookup(struct dentry *, struct vfsmount *, const char *, unsigned int, struct nameidata *); -extern void path_release(struct nameidata *); -extern void path_release_on_umount(struct nameidata *); extern int __user_path_lookup_open(const char __user *, unsigned lookup_flags, struct nameidata *nd, int open_flags); extern int path_lookup_open(int dfd, const char *name, unsigned lookup_flags, struct nameidata *, int open_flags); diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 7128a02f1d37..a2f003239c85 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -604,6 +604,10 @@ struct net_device unsigned char broadcast[MAX_ADDR_LEN]; /* hw bcast add */ + /* ingress path synchronizer */ + spinlock_t ingress_lock; + struct Qdisc *qdisc_ingress; + /* * Cache line mostly used on queue transmit path (qdisc) */ @@ -617,10 +621,6 @@ struct net_device /* Partially transmitted GSO packet. */ struct sk_buff *gso_skb; - /* ingress path synchronizer */ - spinlock_t ingress_lock; - struct Qdisc *qdisc_ingress; - /* * One part is mostly used on xmit path (device) */ diff --git a/include/linux/nfsd/export.h b/include/linux/nfsd/export.h index 3a1687251367..5431512b2757 100644 --- a/include/linux/nfsd/export.h +++ b/include/linux/nfsd/export.h @@ -84,9 +84,8 @@ struct svc_export { struct cache_head h; struct auth_domain * ex_client; int ex_flags; - struct vfsmount * ex_mnt; - struct dentry * ex_dentry; - char * ex_path; + struct path ex_path; + char *ex_pathname; uid_t ex_anon_uid; gid_t ex_anon_gid; int ex_fsid; @@ -107,8 +106,7 @@ struct svc_expkey { int ek_fsidtype; u32 ek_fsid[6]; - struct vfsmount * ek_mnt; - struct dentry * ek_dentry; + struct path ek_path; }; #define EX_SECURE(exp) (!((exp)->ex_flags & NFSEXP_INSECURE_PORT)) diff --git a/include/linux/path.h b/include/linux/path.h new file mode 100644 index 000000000000..915e0c382a51 --- /dev/null +++ b/include/linux/path.h @@ -0,0 +1,15 @@ +#ifndef _LINUX_PATH_H +#define _LINUX_PATH_H + +struct dentry; +struct vfsmount; + +struct path { + struct vfsmount *mnt; + struct dentry *dentry; +}; + +extern void path_get(struct path *); +extern void path_put(struct path *); + +#endif /* _LINUX_PATH_H */ diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index df6dd79a0d3b..0519e53d5eb2 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -1351,6 +1351,7 @@ #define PCI_DEVICE_ID_VIA_8231_4 0x8235 #define PCI_DEVICE_ID_VIA_8365_1 0x8305 #define PCI_DEVICE_ID_VIA_CX700 0x8324 +#define PCI_DEVICE_ID_VIA_CX700_IDE 0x0581 #define PCI_DEVICE_ID_VIA_VX800 0x8353 #define PCI_DEVICE_ID_VIA_8371_1 0x8391 #define PCI_DEVICE_ID_VIA_82C598_1 0x8598 diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h index d6a4f69bdc92..d9a9e718ad19 100644 --- a/include/linux/proc_fs.h +++ b/include/linux/proc_fs.h @@ -269,7 +269,7 @@ extern void kclist_add(struct kcore_list *, void *, size_t); #endif union proc_op { - int (*proc_get_link)(struct inode *, struct dentry **, struct vfsmount **); + int (*proc_get_link)(struct inode *, struct path *); int (*proc_read)(struct task_struct *task, char *page); int (*proc_show)(struct seq_file *m, struct pid_namespace *ns, struct pid *pid, diff --git a/include/linux/seq_file.h b/include/linux/seq_file.h index 648dfeb444db..67c2563961f3 100644 --- a/include/linux/seq_file.h +++ b/include/linux/seq_file.h @@ -8,8 +8,7 @@ struct seq_operations; struct file; -struct vfsmount; -struct dentry; +struct path; struct inode; struct seq_file { @@ -42,7 +41,7 @@ int seq_puts(struct seq_file *m, const char *s); int seq_printf(struct seq_file *, const char *, ...) __attribute__ ((format (printf,2,3))); -int seq_path(struct seq_file *, struct vfsmount *, struct dentry *, char *); +int seq_path(struct seq_file *, struct path *, char *); int single_open(struct file *, int (*)(struct seq_file *, void *), void *); int single_release(struct inode *, struct file *); diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 412672a79e8a..bbd8d0027e2f 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -232,6 +232,8 @@ typedef unsigned char *sk_buff_data_t; * @mark: Generic packet mark * @nfct: Associated connection, if any * @ipvs_property: skbuff is owned by ipvs + * @peeked: this packet has been seen already, so stats have been + * done for it, don't do them again * @nf_trace: netfilter packet trace flag * @nfctinfo: Relationship of this skb to the connection * @nfct_reasm: netfilter conntrack re-assembly pointer diff --git a/include/linux/slub_def.h b/include/linux/slub_def.h index 5e6d3d634d5b..57deecc79d52 100644 --- a/include/linux/slub_def.h +++ b/include/linux/slub_def.h @@ -71,6 +71,7 @@ struct kmem_cache { /* Allocation and freeing of slabs */ int objects; /* Number of objects in slab */ + gfp_t allocflags; /* gfp flags to use on each alloc */ int refcount; /* Refcount for slab cache destroy */ void (*ctor)(struct kmem_cache *, void *); int inuse; /* Offset to metadata */ @@ -110,7 +111,7 @@ struct kmem_cache { * We keep the general caches in an array of slab caches that are used for * 2^x bytes of allocations. */ -extern struct kmem_cache kmalloc_caches[PAGE_SHIFT]; +extern struct kmem_cache kmalloc_caches[PAGE_SHIFT + 1]; /* * Sorry that the following has to be that ugly but some versions of GCC @@ -188,12 +189,16 @@ static __always_inline struct kmem_cache *kmalloc_slab(size_t size) void *kmem_cache_alloc(struct kmem_cache *, gfp_t); void *__kmalloc(size_t size, gfp_t flags); +static __always_inline void *kmalloc_large(size_t size, gfp_t flags) +{ + return (void *)__get_free_pages(flags | __GFP_COMP, get_order(size)); +} + static __always_inline void *kmalloc(size_t size, gfp_t flags) { if (__builtin_constant_p(size)) { - if (size > PAGE_SIZE / 2) - return (void *)__get_free_pages(flags | __GFP_COMP, - get_order(size)); + if (size > PAGE_SIZE) + return kmalloc_large(size, flags); if (!(flags & SLUB_DMA)) { struct kmem_cache *s = kmalloc_slab(size); @@ -214,7 +219,7 @@ void *kmem_cache_alloc_node(struct kmem_cache *, gfp_t flags, int node); static __always_inline void *kmalloc_node(size_t size, gfp_t flags, int node) { if (__builtin_constant_p(size) && - size <= PAGE_SIZE / 2 && !(flags & SLUB_DMA)) { + size <= PAGE_SIZE && !(flags & SLUB_DMA)) { struct kmem_cache *s = kmalloc_slab(size); if (!s) diff --git a/include/linux/videodev.h b/include/linux/videodev.h index 52e3d5fd5be4..9385a566aed8 100644 --- a/include/linux/videodev.h +++ b/include/linux/videodev.h @@ -12,6 +12,7 @@ #ifndef __LINUX_VIDEODEV_H #define __LINUX_VIDEODEV_H +#include #include #if defined(CONFIG_VIDEO_V4L1_COMPAT) || !defined (__KERNEL__) diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index 439474f24e34..17a80177a674 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -62,6 +62,7 @@ #define __user #include #endif +#include #include /* diff --git a/include/media/ir-common.h b/include/media/ir-common.h index 831547d79683..a4274203f252 100644 --- a/include/media/ir-common.h +++ b/include/media/ir-common.h @@ -142,6 +142,7 @@ extern IR_KEYTAB_TYPE ir_codes_tt_1500[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_fusionhdtv_mce[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_behold[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_pinnacle_pctv_hd[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_genius_tvgo_a11mce[IR_KEYTAB_SIZE]; #endif diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h index 475d0d8275e0..316a58453134 100644 --- a/include/media/v4l2-common.h +++ b/include/media/v4l2-common.h @@ -61,8 +61,6 @@ v4l_client_printk(KERN_DEBUG, client, fmt , ## arg); \ } while (0) -/* Prints the ioctl in a human-readable format */ -extern void v4l_printk_ioctl(unsigned int cmd); /* Use this macro for non-I2C drivers. Pass the driver name as the first arg. */ #define v4l_print_ioctl(name, cmd) \ diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h index c544c6f90893..f2114459995d 100644 --- a/include/media/v4l2-dev.h +++ b/include/media/v4l2-dev.h @@ -44,6 +44,8 @@ extern unsigned int v4l2_video_std_fps(struct v4l2_standard *vs); extern char *v4l2_norm_to_name(v4l2_std_id id); extern int v4l2_video_std_construct(struct v4l2_standard *vs, int id, char *name); +/* Prints the ioctl in a human-readable format */ +extern void v4l_printk_ioctl(unsigned int cmd); /* prority handling */ struct v4l2_prio_state { diff --git a/include/media/videobuf-core.h b/include/media/videobuf-core.h index 97f14d469595..99033945cdee 100644 --- a/include/media/videobuf-core.h +++ b/include/media/videobuf-core.h @@ -149,7 +149,7 @@ struct videobuf_qtype_ops { }; struct videobuf_queue { - struct mutex lock; + struct mutex vb_lock; spinlock_t *irqlock; void *dev; /* on pci, points to struct pci_dev */ diff --git a/include/media/videobuf-vmalloc.h b/include/media/videobuf-vmalloc.h index 26a8958d23d1..ec63ab0fab93 100644 --- a/include/media/videobuf-vmalloc.h +++ b/include/media/videobuf-vmalloc.h @@ -17,7 +17,7 @@ /* --------------------------------------------------------------------- */ -struct videbuf_vmalloc_memory +struct videobuf_vmalloc_memory { u32 magic; diff --git a/include/net/ax25.h b/include/net/ax25.h index 32a57e1dee3a..717e2192d521 100644 --- a/include/net/ax25.h +++ b/include/net/ax25.h @@ -324,6 +324,7 @@ extern void ax25_dama_on(ax25_cb *); extern void ax25_dama_off(ax25_cb *); /* ax25_ds_timer.c */ +extern void ax25_ds_setup_timer(ax25_dev *); extern void ax25_ds_set_timer(ax25_dev *); extern void ax25_ds_del_timer(ax25_dev *); extern void ax25_ds_timer(ax25_cb *); @@ -416,6 +417,7 @@ extern void ax25_calculate_rtt(ax25_cb *); extern void ax25_disconnect(ax25_cb *, int); /* ax25_timer.c */ +extern void ax25_setup_timers(ax25_cb *); extern void ax25_start_heartbeat(ax25_cb *); extern void ax25_start_t1timer(ax25_cb *); extern void ax25_start_t2timer(ax25_cb *); diff --git a/include/net/ndisc.h b/include/net/ndisc.h index 6684f7efbeeb..59b70624b056 100644 --- a/include/net/ndisc.h +++ b/include/net/ndisc.h @@ -103,7 +103,6 @@ extern void ndisc_send_redirect(struct sk_buff *skb, extern int ndisc_mc_map(struct in6_addr *addr, char *buf, struct net_device *dev, int dir); -struct rt6_info * dflt_rt_lookup(void); /* * IGMP diff --git a/include/net/sock.h b/include/net/sock.h index 8a7889b35810..fd9876087651 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -180,6 +180,7 @@ struct sock_common { * @sk_sndmsg_off: cached offset for sendmsg * @sk_send_head: front of stuff to transmit * @sk_security: used by security modules + * @sk_mark: generic packet mark * @sk_write_pending: a write to stream socket waits to start * @sk_state_change: callback to indicate change in the state of the sock * @sk_data_ready: callback to indicate there is data to be processed diff --git a/include/net/xfrm.h b/include/net/xfrm.h index ac72116636ca..eea7785cc757 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -508,7 +508,10 @@ struct xfrm_skb_cb { } header; /* Sequence number for replay protection. */ - u64 seq; + union { + u64 output; + __be32 input; + } seq; }; #define XFRM_SKB_CB(__skb) ((struct xfrm_skb_cb *)&((__skb)->cb[0])) diff --git a/init/do_mounts.c b/init/do_mounts.c index f86573126f83..3885e70e7759 100644 --- a/init/do_mounts.c +++ b/init/do_mounts.c @@ -193,10 +193,10 @@ static int __init do_mount_root(char *name, char *fs, int flags, void *data) return err; sys_chdir("/root"); - ROOT_DEV = current->fs->pwdmnt->mnt_sb->s_dev; + ROOT_DEV = current->fs->pwd.mnt->mnt_sb->s_dev; printk("VFS: Mounted root (%s filesystem)%s.\n", - current->fs->pwdmnt->mnt_sb->s_type->name, - current->fs->pwdmnt->mnt_sb->s_flags & MS_RDONLY ? + current->fs->pwd.mnt->mnt_sb->s_type->name, + current->fs->pwd.mnt->mnt_sb->s_flags & MS_RDONLY ? " readonly" : ""); return 0; } diff --git a/kernel/audit.c b/kernel/audit.c index c8555b180213..2eeea9a14240 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -1312,26 +1312,26 @@ void audit_log_untrustedstring(struct audit_buffer *ab, const char *string) /* This is a helper-function to print the escaped d_path */ void audit_log_d_path(struct audit_buffer *ab, const char *prefix, - struct dentry *dentry, struct vfsmount *vfsmnt) + struct path *path) { - char *p, *path; + char *p, *pathname; if (prefix) audit_log_format(ab, " %s", prefix); /* We will allow 11 spaces for ' (deleted)' to be appended */ - path = kmalloc(PATH_MAX+11, ab->gfp_mask); - if (!path) { + pathname = kmalloc(PATH_MAX+11, ab->gfp_mask); + if (!pathname) { audit_log_format(ab, ""); return; } - p = d_path(dentry, vfsmnt, path, PATH_MAX+11); + p = d_path(path, pathname, PATH_MAX+11); if (IS_ERR(p)) { /* Should never happen since we send PATH_MAX */ /* FIXME: can we save some information here? */ audit_log_format(ab, ""); } else audit_log_untrustedstring(ab, p); - kfree(path); + kfree(pathname); } /** diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c index f4fcf58f20f8..9ef5e0aacc3c 100644 --- a/kernel/audit_tree.c +++ b/kernel/audit_tree.c @@ -549,8 +549,8 @@ void audit_trim_trees(void) if (err) goto skip_it; - root_mnt = collect_mounts(nd.mnt, nd.dentry); - path_release(&nd); + root_mnt = collect_mounts(nd.path.mnt, nd.path.dentry); + path_put(&nd.path); if (!root_mnt) goto skip_it; @@ -583,17 +583,17 @@ skip_it: static int is_under(struct vfsmount *mnt, struct dentry *dentry, struct nameidata *nd) { - if (mnt != nd->mnt) { + if (mnt != nd->path.mnt) { for (;;) { if (mnt->mnt_parent == mnt) return 0; - if (mnt->mnt_parent == nd->mnt) + if (mnt->mnt_parent == nd->path.mnt) break; mnt = mnt->mnt_parent; } dentry = mnt->mnt_mountpoint; } - return is_subdir(dentry, nd->dentry); + return is_subdir(dentry, nd->path.dentry); } int audit_make_tree(struct audit_krule *rule, char *pathname, u32 op) @@ -641,8 +641,8 @@ int audit_add_tree_rule(struct audit_krule *rule) err = path_lookup(tree->pathname, 0, &nd); if (err) goto Err; - mnt = collect_mounts(nd.mnt, nd.dentry); - path_release(&nd); + mnt = collect_mounts(nd.path.mnt, nd.path.dentry); + path_put(&nd.path); if (!mnt) { err = -ENOMEM; goto Err; @@ -701,8 +701,8 @@ int audit_tag_tree(char *old, char *new) err = path_lookup(new, 0, &nd); if (err) return err; - tagged = collect_mounts(nd.mnt, nd.dentry); - path_release(&nd); + tagged = collect_mounts(nd.path.mnt, nd.path.dentry); + path_put(&nd.path); if (!tagged) return -ENOMEM; @@ -711,9 +711,9 @@ int audit_tag_tree(char *old, char *new) drop_collected_mounts(tagged); return err; } - mnt = mntget(nd.mnt); - dentry = dget(nd.dentry); - path_release(&nd); + mnt = mntget(nd.path.mnt); + dentry = dget(nd.path.dentry); + path_put(&nd.path); if (dentry == tagged->mnt_root && dentry == mnt->mnt_root) follow_up(&mnt, &dentry); @@ -744,13 +744,13 @@ int audit_tag_tree(char *old, char *new) spin_lock(&vfsmount_lock); if (!is_under(mnt, dentry, &nd)) { spin_unlock(&vfsmount_lock); - path_release(&nd); + path_put(&nd.path); put_tree(tree); mutex_lock(&audit_filter_mutex); continue; } spin_unlock(&vfsmount_lock); - path_release(&nd); + path_put(&nd.path); list_for_each_entry(p, &list, mnt_list) { failed = tag_chunk(p->mnt_root->d_inode, tree); diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c index 6f19fd477aac..2f2914b7cc30 100644 --- a/kernel/auditfilter.c +++ b/kernel/auditfilter.c @@ -169,8 +169,8 @@ static struct audit_parent *audit_init_parent(struct nameidata *ndp) inotify_init_watch(&parent->wdata); /* grab a ref so inotify watch hangs around until we take audit_filter_mutex */ get_inotify_watch(&parent->wdata); - wd = inotify_add_watch(audit_ih, &parent->wdata, ndp->dentry->d_inode, - AUDIT_IN_WATCH); + wd = inotify_add_watch(audit_ih, &parent->wdata, + ndp->path.dentry->d_inode, AUDIT_IN_WATCH); if (wd < 0) { audit_free_parent(&parent->wdata); return ERR_PTR(wd); @@ -1161,11 +1161,11 @@ static int audit_get_nd(char *path, struct nameidata **ndp, static void audit_put_nd(struct nameidata *ndp, struct nameidata *ndw) { if (ndp) { - path_release(ndp); + path_put(&ndp->path); kfree(ndp); } if (ndw) { - path_release(ndw); + path_put(&ndw->path); kfree(ndw); } } @@ -1214,8 +1214,8 @@ static int audit_add_watch(struct audit_krule *krule, struct nameidata *ndp, /* update watch filter fields */ if (ndw) { - watch->dev = ndw->dentry->d_inode->i_sb->s_dev; - watch->ino = ndw->dentry->d_inode->i_ino; + watch->dev = ndw->path.dentry->d_inode->i_sb->s_dev; + watch->ino = ndw->path.dentry->d_inode->i_ino; } /* The audit_filter_mutex must not be held during inotify calls because @@ -1225,7 +1225,8 @@ static int audit_add_watch(struct audit_krule *krule, struct nameidata *ndp, */ mutex_unlock(&audit_filter_mutex); - if (inotify_find_watch(audit_ih, ndp->dentry->d_inode, &i_watch) < 0) { + if (inotify_find_watch(audit_ih, ndp->path.dentry->d_inode, + &i_watch) < 0) { parent = audit_init_parent(ndp); if (IS_ERR(parent)) { /* caller expects mutex locked */ diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 1c06ecf38d7b..2087d6de67ea 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -208,8 +208,7 @@ struct audit_context { int name_count; struct audit_names names[AUDIT_NAMES]; char * filterkey; /* key for rule that triggered record */ - struct dentry * pwd; - struct vfsmount * pwdmnt; + struct path pwd; struct audit_context *previous; /* For nested syscalls */ struct audit_aux_data *aux; struct audit_aux_data *aux_pids; @@ -786,12 +785,9 @@ static inline void audit_free_names(struct audit_context *context) __putname(context->names[i].name); } context->name_count = 0; - if (context->pwd) - dput(context->pwd); - if (context->pwdmnt) - mntput(context->pwdmnt); - context->pwd = NULL; - context->pwdmnt = NULL; + path_put(&context->pwd); + context->pwd.dentry = NULL; + context->pwd.mnt = NULL; } static inline void audit_free_aux(struct audit_context *context) @@ -930,8 +926,7 @@ static void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk if ((vma->vm_flags & VM_EXECUTABLE) && vma->vm_file) { audit_log_d_path(ab, "exe=", - vma->vm_file->f_path.dentry, - vma->vm_file->f_path.mnt); + &vma->vm_file->f_path); break; } vma = vma->vm_next; @@ -1005,9 +1000,10 @@ static int audit_log_single_execve_arg(struct audit_context *context, * for strings that are too long, we should not have created * any. */ - if (unlikely((len = -1) || len > MAX_ARG_STRLEN - 1)) { + if (unlikely((len == -1) || len > MAX_ARG_STRLEN - 1)) { WARN_ON(1); send_sig(SIGKILL, current, 0); + return -1; } /* walk the whole argument looking for non-ascii chars */ @@ -1025,6 +1021,7 @@ static int audit_log_single_execve_arg(struct audit_context *context, if (ret) { WARN_ON(1); send_sig(SIGKILL, current, 0); + return -1; } buf[to_send] = '\0'; has_cntl = audit_string_contains_control(buf, to_send); @@ -1088,6 +1085,7 @@ static int audit_log_single_execve_arg(struct audit_context *context, if (ret) { WARN_ON(1); send_sig(SIGKILL, current, 0); + return -1; } buf[to_send] = '\0'; @@ -1341,10 +1339,10 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts context->target_sid, context->target_comm)) call_panic = 1; - if (context->pwd && context->pwdmnt) { + if (context->pwd.dentry && context->pwd.mnt) { ab = audit_log_start(context, GFP_KERNEL, AUDIT_CWD); if (ab) { - audit_log_d_path(ab, "cwd=", context->pwd, context->pwdmnt); + audit_log_d_path(ab, "cwd=", &context->pwd); audit_log_end(ab); } } @@ -1367,8 +1365,7 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts case 0: /* name was specified as a relative path and the * directory component is the cwd */ - audit_log_d_path(ab, " name=", context->pwd, - context->pwdmnt); + audit_log_d_path(ab, " name=", &context->pwd); break; default: /* log the name's directory component */ @@ -1695,10 +1692,10 @@ void __audit_getname(const char *name) context->names[context->name_count].ino = (unsigned long)-1; context->names[context->name_count].osid = 0; ++context->name_count; - if (!context->pwd) { + if (!context->pwd.dentry) { read_lock(¤t->fs->lock); - context->pwd = dget(current->fs->pwd); - context->pwdmnt = mntget(current->fs->pwdmnt); + context->pwd = current->fs->pwd; + path_get(¤t->fs->pwd); read_unlock(¤t->fs->lock); } diff --git a/kernel/exit.c b/kernel/exit.c index 3b893e78ce61..506a957b665a 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -512,14 +512,10 @@ static void __put_fs_struct(struct fs_struct *fs) { /* No need to hold fs->lock if we are killing it */ if (atomic_dec_and_test(&fs->count)) { - dput(fs->root); - mntput(fs->rootmnt); - dput(fs->pwd); - mntput(fs->pwdmnt); - if (fs->altroot) { - dput(fs->altroot); - mntput(fs->altrootmnt); - } + path_put(&fs->root); + path_put(&fs->pwd); + if (fs->altroot.dentry) + path_put(&fs->altroot); kmem_cache_free(fs_cachep, fs); } } diff --git a/kernel/fork.c b/kernel/fork.c index 4363a4eb84e3..dd249c37b3a3 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -600,16 +600,16 @@ static struct fs_struct *__copy_fs_struct(struct fs_struct *old) rwlock_init(&fs->lock); fs->umask = old->umask; read_lock(&old->lock); - fs->rootmnt = mntget(old->rootmnt); - fs->root = dget(old->root); - fs->pwdmnt = mntget(old->pwdmnt); - fs->pwd = dget(old->pwd); - if (old->altroot) { - fs->altrootmnt = mntget(old->altrootmnt); - fs->altroot = dget(old->altroot); + fs->root = old->root; + path_get(&old->root); + fs->pwd = old->pwd; + path_get(&old->pwd); + if (old->altroot.dentry) { + fs->altroot = old->altroot; + path_get(&old->altroot); } else { - fs->altrootmnt = NULL; - fs->altroot = NULL; + fs->altroot.mnt = NULL; + fs->altroot.dentry = NULL; } read_unlock(&old->lock); } diff --git a/kernel/futex.c b/kernel/futex.c index a6baaec44b8f..221f2128a437 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -2116,7 +2116,7 @@ asmlinkage long sys_futex(u32 __user *uaddr, int op, u32 val, t = timespec_to_ktime(ts); if (cmd == FUTEX_WAIT) - t = ktime_add(ktime_get(), t); + t = ktime_add_safe(ktime_get(), t); tp = &t; } /* diff --git a/kernel/futex_compat.c b/kernel/futex_compat.c index 133d558db452..7d5e4b016f39 100644 --- a/kernel/futex_compat.c +++ b/kernel/futex_compat.c @@ -176,7 +176,7 @@ asmlinkage long compat_sys_futex(u32 __user *uaddr, int op, u32 val, t = timespec_to_ktime(ts); if (cmd == FUTEX_WAIT) - t = ktime_add(ktime_get(), t); + t = ktime_add_safe(ktime_get(), t); tp = &t; } if (cmd == FUTEX_REQUEUE || cmd == FUTEX_CMP_REQUEUE) diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index 3f4a57c7895d..98bee013f71f 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c @@ -325,6 +325,23 @@ u64 ktime_divns(const ktime_t kt, s64 div) } #endif /* BITS_PER_LONG >= 64 */ +/* + * Add two ktime values and do a safety check for overflow: + */ +ktime_t ktime_add_safe(const ktime_t lhs, const ktime_t rhs) +{ + ktime_t res = ktime_add(lhs, rhs); + + /* + * We use KTIME_SEC_MAX here, the maximum timeout which we can + * return to user space in a timespec: + */ + if (res.tv64 < 0 || res.tv64 < lhs.tv64 || res.tv64 < rhs.tv64) + res = ktime_set(KTIME_SEC_MAX, 0); + + return res; +} + /* * Check, whether the timer is on the callback pending list */ @@ -425,6 +442,8 @@ static int hrtimer_reprogram(struct hrtimer *timer, ktime_t expires = ktime_sub(timer->expires, base->offset); int res; + WARN_ON_ONCE(timer->expires.tv64 < 0); + /* * When the callback is running, we do not reprogram the clock event * device. The timer callback is either running on a different CPU or @@ -435,6 +454,15 @@ static int hrtimer_reprogram(struct hrtimer *timer, if (hrtimer_callback_running(timer)) return 0; + /* + * CLOCK_REALTIME timer might be requested with an absolute + * expiry time which is less than base->offset. Nothing wrong + * about that, just avoid to call into the tick code, which + * has now objections against negative expiry values. + */ + if (expires.tv64 < 0) + return -ETIME; + if (expires.tv64 >= expires_next->tv64) return 0; @@ -682,13 +710,7 @@ u64 hrtimer_forward(struct hrtimer *timer, ktime_t now, ktime_t interval) */ orun++; } - timer->expires = ktime_add(timer->expires, interval); - /* - * Make sure, that the result did not wrap with a very large - * interval. - */ - if (timer->expires.tv64 < 0) - timer->expires = ktime_set(KTIME_SEC_MAX, 0); + timer->expires = ktime_add_safe(timer->expires, interval); return orun; } @@ -839,7 +861,7 @@ hrtimer_start(struct hrtimer *timer, ktime_t tim, const enum hrtimer_mode mode) new_base = switch_hrtimer_base(timer, base); if (mode == HRTIMER_MODE_REL) { - tim = ktime_add(tim, new_base->get_time()); + tim = ktime_add_safe(tim, new_base->get_time()); /* * CONFIG_TIME_LOW_RES is a temporary way for architectures * to signal that they simply return xtime in @@ -848,16 +870,8 @@ hrtimer_start(struct hrtimer *timer, ktime_t tim, const enum hrtimer_mode mode) * timeouts. This will go away with the GTOD framework. */ #ifdef CONFIG_TIME_LOW_RES - tim = ktime_add(tim, base->resolution); + tim = ktime_add_safe(tim, base->resolution); #endif - /* - * Careful here: User space might have asked for a - * very long sleep, so the add above might result in a - * negative number, which enqueues the timer in front - * of the queue. - */ - if (tim.tv64 < 0) - tim.tv64 = KTIME_MAX; } timer->expires = tim; diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c index cc54c6276356..fdb3fbe2b0c4 100644 --- a/kernel/irq/chip.c +++ b/kernel/irq/chip.c @@ -245,6 +245,17 @@ static unsigned int default_startup(unsigned int irq) return 0; } +/* + * default shutdown function + */ +static void default_shutdown(unsigned int irq) +{ + struct irq_desc *desc = irq_desc + irq; + + desc->chip->mask(irq); + desc->status |= IRQ_MASKED; +} + /* * Fixup enable/disable function pointers */ @@ -256,8 +267,15 @@ void irq_chip_set_defaults(struct irq_chip *chip) chip->disable = default_disable; if (!chip->startup) chip->startup = default_startup; + /* + * We use chip->disable, when the user provided its own. When + * we have default_disable set for chip->disable, then we need + * to use default_shutdown, otherwise the irq line is not + * disabled on free_irq(): + */ if (!chip->shutdown) - chip->shutdown = chip->disable; + chip->shutdown = chip->disable != default_disable ? + chip->disable : default_shutdown; if (!chip->name) chip->name = chip->typename; if (!chip->end) diff --git a/kernel/irq/spurious.c b/kernel/irq/spurious.c index a6b2bc831dd0..088dabbf2d6a 100644 --- a/kernel/irq/spurious.c +++ b/kernel/irq/spurious.c @@ -6,6 +6,7 @@ * This file contains spurious interrupt handling. */ +#include #include #include #include @@ -179,7 +180,7 @@ void note_interrupt(unsigned int irq, struct irq_desc *desc, * otherwise the couter becomes a doomsday timer for otherwise * working systems */ - if (jiffies - desc->last_unhandled > HZ/10) + if (time_after(jiffies, desc->last_unhandled + HZ/10)) desc->irqs_unhandled = 1; else desc->irqs_unhandled++; diff --git a/kernel/kmod.c b/kernel/kmod.c index bb7df2a28bd7..22be3ff3f363 100644 --- a/kernel/kmod.c +++ b/kernel/kmod.c @@ -173,10 +173,7 @@ static int ____call_usermodehelper(void *data) */ set_user_nice(current, 0); - retval = -EPERM; - if (current->fs->root) - retval = kernel_execve(sub_info->path, - sub_info->argv, sub_info->envp); + retval = kernel_execve(sub_info->path, sub_info->argv, sub_info->envp); /* Exec failed? */ sub_info->retval = retval; diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c index 022c9c3cee6f..a9b04203a66d 100644 --- a/kernel/posix-timers.c +++ b/kernel/posix-timers.c @@ -767,9 +767,11 @@ common_timer_set(struct k_itimer *timr, int flags, /* SIGEV_NONE timers are not queued ! See common_timer_get */ if (((timr->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE)) { /* Setup correct expiry time for relative timers */ - if (mode == HRTIMER_MODE_REL) - timer->expires = ktime_add(timer->expires, - timer->base->get_time()); + if (mode == HRTIMER_MODE_REL) { + timer->expires = + ktime_add_safe(timer->expires, + timer->base->get_time()); + } return 0; } diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c index 95250d7c8d91..72a020cabb4c 100644 --- a/kernel/power/snapshot.c +++ b/kernel/power/snapshot.c @@ -875,8 +875,8 @@ static inline void *saveable_highmem_page(unsigned long pfn) { return NULL; } #endif /* CONFIG_HIGHMEM */ /** - * saveable - Determine whether a non-highmem page should be included in - * the suspend image. + * saveable_page - Determine whether a non-highmem page should be included + * in the suspend image. * * We should save the page if it isn't Nosave, and is not in the range * of pages statically defined as 'unsaveable', and it isn't a part of @@ -897,7 +897,8 @@ static struct page *saveable_page(unsigned long pfn) if (swsusp_page_is_forbidden(page) || swsusp_page_is_free(page)) return NULL; - if (PageReserved(page) && pfn_is_nosave(pfn)) + if (PageReserved(page) + && (!kernel_page_present(page) || pfn_is_nosave(pfn))) return NULL; return page; @@ -938,6 +939,25 @@ static inline void do_copy_page(long *dst, long *src) *dst++ = *src++; } + +/** + * safe_copy_page - check if the page we are going to copy is marked as + * present in the kernel page tables (this always is the case if + * CONFIG_DEBUG_PAGEALLOC is not set and in that case + * kernel_page_present() always returns 'true'). + */ +static void safe_copy_page(void *dst, struct page *s_page) +{ + if (kernel_page_present(s_page)) { + do_copy_page(dst, page_address(s_page)); + } else { + kernel_map_pages(s_page, 1, 1); + do_copy_page(dst, page_address(s_page)); + kernel_map_pages(s_page, 1, 0); + } +} + + #ifdef CONFIG_HIGHMEM static inline struct page * page_is_saveable(struct zone *zone, unsigned long pfn) @@ -946,8 +966,7 @@ page_is_saveable(struct zone *zone, unsigned long pfn) saveable_highmem_page(pfn) : saveable_page(pfn); } -static inline void -copy_data_page(unsigned long dst_pfn, unsigned long src_pfn) +static void copy_data_page(unsigned long dst_pfn, unsigned long src_pfn) { struct page *s_page, *d_page; void *src, *dst; @@ -961,29 +980,26 @@ copy_data_page(unsigned long dst_pfn, unsigned long src_pfn) kunmap_atomic(src, KM_USER0); kunmap_atomic(dst, KM_USER1); } else { - src = page_address(s_page); if (PageHighMem(d_page)) { /* Page pointed to by src may contain some kernel * data modified by kmap_atomic() */ - do_copy_page(buffer, src); + safe_copy_page(buffer, s_page); dst = kmap_atomic(pfn_to_page(dst_pfn), KM_USER0); memcpy(dst, buffer, PAGE_SIZE); kunmap_atomic(dst, KM_USER0); } else { - dst = page_address(d_page); - do_copy_page(dst, src); + safe_copy_page(page_address(d_page), s_page); } } } #else #define page_is_saveable(zone, pfn) saveable_page(pfn) -static inline void -copy_data_page(unsigned long dst_pfn, unsigned long src_pfn) +static inline void copy_data_page(unsigned long dst_pfn, unsigned long src_pfn) { - do_copy_page(page_address(pfn_to_page(dst_pfn)), - page_address(pfn_to_page(src_pfn))); + safe_copy_page(page_address(pfn_to_page(dst_pfn)), + pfn_to_page(src_pfn)); } #endif /* CONFIG_HIGHMEM */ diff --git a/kernel/time/timer_list.c b/kernel/time/timer_list.c index d3d94c1a0fd2..67fe8fc21fb1 100644 --- a/kernel/time/timer_list.c +++ b/kernel/time/timer_list.c @@ -65,9 +65,9 @@ print_timer(struct seq_file *m, struct hrtimer *timer, int idx, u64 now) SEQ_printf(m, ", %s/%d", tmp, timer->start_pid); #endif SEQ_printf(m, "\n"); - SEQ_printf(m, " # expires at %Lu nsecs [in %Lu nsecs]\n", + SEQ_printf(m, " # expires at %Lu nsecs [in %Ld nsecs]\n", (unsigned long long)ktime_to_ns(timer->expires), - (unsigned long long)(ktime_to_ns(timer->expires) - now)); + (long long)(ktime_to_ns(timer->expires) - now)); } static void diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index a370fe828a79..ab408aa9b6d6 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -82,6 +82,9 @@ config HEADERS_CHECK config DEBUG_SECTION_MISMATCH bool "Enable full Section mismatch analysis" depends on UNDEFINED + # This option is on purpose disabled for now. + # It will be enabled when we are down to a resonable number + # of section mismatch warnings (< 10 for an allyesconfig build) help The section mismatch analysis checks if there are illegal references from one section to another section. diff --git a/mm/memory.c b/mm/memory.c index 717aa0e3be2d..ce3c9e4492d8 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -2711,6 +2711,13 @@ void print_vma_addr(char *prefix, unsigned long ip) struct mm_struct *mm = current->mm; struct vm_area_struct *vma; + /* + * Do not print if we are in atomic + * contexts (in exception stacks, etc.): + */ + if (preempt_count()) + return; + down_read(&mm->mmap_sem); vma = find_vma(mm, ip); if (vma && vma->vm_file) { @@ -2719,7 +2726,7 @@ void print_vma_addr(char *prefix, unsigned long ip) if (buf) { char *p, *s; - p = d_path(f->f_dentry, f->f_vfsmnt, buf, PAGE_SIZE); + p = d_path(&f->f_path, buf, PAGE_SIZE); if (IS_ERR(p)) p = "?"; s = strrchr(p, '/'); diff --git a/mm/mempolicy.c b/mm/mempolicy.c index 8d246c3b340f..6c7ba1a63d23 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -1996,7 +1996,7 @@ int show_numa_map(struct seq_file *m, void *v) if (file) { seq_printf(m, " file="); - seq_path(m, file->f_path.mnt, file->f_path.dentry, "\n\t= "); + seq_path(m, &file->f_path, "\n\t= "); } else if (vma->vm_start <= mm->brk && vma->vm_end >= mm->start_brk) { seq_printf(m, " heap"); } else if (vma->vm_start <= mm->start_stack && diff --git a/mm/slab.c b/mm/slab.c index 40c00dacbe4b..473e6c2eaefb 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -2630,6 +2630,7 @@ static struct slab *alloc_slabmgmt(struct kmem_cache *cachep, void *objp, slabp->colouroff = colour_off; slabp->s_mem = objp + colour_off; slabp->nodeid = nodeid; + slabp->free = 0; return slabp; } @@ -2683,7 +2684,6 @@ static void cache_init_objs(struct kmem_cache *cachep, slab_bufctl(slabp)[i] = i + 1; } slab_bufctl(slabp)[i - 1] = BUFCTL_END; - slabp->free = 0; } static void kmem_flagcheck(struct kmem_cache *cachep, gfp_t flags) @@ -2816,7 +2816,6 @@ static int cache_grow(struct kmem_cache *cachep, if (!slabp) goto opps1; - slabp->nodeid = nodeid; slab_map_pages(cachep, slabp, objp); cache_init_objs(cachep, slabp); diff --git a/mm/slub.c b/mm/slub.c index e2989ae243b5..74c65af0a54f 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -149,13 +149,6 @@ static inline void ClearSlabDebug(struct page *page) /* Enable to test recovery from slab corruption on boot */ #undef SLUB_RESILIENCY_TEST -/* - * Currently fastpath is not supported if preemption is enabled. - */ -#if defined(CONFIG_FAST_CMPXCHG_LOCAL) && !defined(CONFIG_PREEMPT) -#define SLUB_FASTPATH -#endif - #if PAGE_SHIFT <= 12 /* @@ -211,6 +204,8 @@ static inline void ClearSlabDebug(struct page *page) /* Internal SLUB flags */ #define __OBJECT_POISON 0x80000000 /* Poison object */ #define __SYSFS_ADD_DEFERRED 0x40000000 /* Not yet visible via sysfs */ +#define __KMALLOC_CACHE 0x20000000 /* objects freed using kfree */ +#define __PAGE_ALLOC_FALLBACK 0x10000000 /* Allow fallback to page alloc */ /* Not all arches define cache_line_size */ #ifndef cache_line_size @@ -308,7 +303,7 @@ static inline int is_end(void *addr) return (unsigned long)addr & PAGE_MAPPING_ANON; } -void *slab_address(struct page *page) +static void *slab_address(struct page *page) { return page->end - PAGE_MAPPING_ANON; } @@ -1078,14 +1073,7 @@ static struct page *allocate_slab(struct kmem_cache *s, gfp_t flags, int node) struct page *page; int pages = 1 << s->order; - if (s->order) - flags |= __GFP_COMP; - - if (s->flags & SLAB_CACHE_DMA) - flags |= SLUB_DMA; - - if (s->flags & SLAB_RECLAIM_ACCOUNT) - flags |= __GFP_RECLAIMABLE; + flags |= s->allocflags; if (node == -1) page = alloc_pages(flags, s->order); @@ -1519,11 +1507,7 @@ static void *__slab_alloc(struct kmem_cache *s, { void **object; struct page *new; -#ifdef SLUB_FASTPATH - unsigned long flags; - local_irq_save(flags); -#endif if (!c->page) goto new_slab; @@ -1546,10 +1530,6 @@ load_freelist: unlock_out: slab_unlock(c->page); stat(c, ALLOC_SLOWPATH); -out: -#ifdef SLUB_FASTPATH - local_irq_restore(flags); -#endif return object; another_slab: @@ -1581,8 +1561,22 @@ new_slab: c->page = new; goto load_freelist; } - object = NULL; - goto out; + + /* + * No memory available. + * + * If the slab uses higher order allocs but the object is + * smaller than a page size then we can fallback in emergencies + * to the page allocator via kmalloc_large. The page allocator may + * have failed to obtain a higher order page and we can try to + * allocate a single page if the object fits into a single page. + * That is only possible if certain conditions are met that are being + * checked when a slab is created. + */ + if (!(gfpflags & __GFP_NORETRY) && (s->flags & __PAGE_ALLOC_FALLBACK)) + return kmalloc_large(s->objsize, gfpflags); + + return NULL; debug: object = c->page->freelist; if (!alloc_debug_processing(s, c->page, object, addr)) @@ -1609,34 +1603,6 @@ static __always_inline void *slab_alloc(struct kmem_cache *s, { void **object; struct kmem_cache_cpu *c; - -/* - * The SLUB_FASTPATH path is provisional and is currently disabled if the - * kernel is compiled with preemption or if the arch does not support - * fast cmpxchg operations. There are a couple of coming changes that will - * simplify matters and allow preemption. Ultimately we may end up making - * SLUB_FASTPATH the default. - * - * 1. The introduction of the per cpu allocator will avoid array lookups - * through get_cpu_slab(). A special register can be used instead. - * - * 2. The introduction of per cpu atomic operations (cpu_ops) means that - * we can realize the logic here entirely with per cpu atomics. The - * per cpu atomic ops will take care of the preemption issues. - */ - -#ifdef SLUB_FASTPATH - c = get_cpu_slab(s, raw_smp_processor_id()); - do { - object = c->freelist; - if (unlikely(is_end(object) || !node_match(c, node))) { - object = __slab_alloc(s, gfpflags, node, addr, c); - break; - } - stat(c, ALLOC_FASTPATH); - } while (cmpxchg_local(&c->freelist, object, object[c->offset]) - != object); -#else unsigned long flags; local_irq_save(flags); @@ -1651,7 +1617,6 @@ static __always_inline void *slab_alloc(struct kmem_cache *s, stat(c, ALLOC_FASTPATH); } local_irq_restore(flags); -#endif if (unlikely((gfpflags & __GFP_ZERO) && object)) memset(object, 0, c->objsize); @@ -1688,11 +1653,6 @@ static void __slab_free(struct kmem_cache *s, struct page *page, void **object = (void *)x; struct kmem_cache_cpu *c; -#ifdef SLUB_FASTPATH - unsigned long flags; - - local_irq_save(flags); -#endif c = get_cpu_slab(s, raw_smp_processor_id()); stat(c, FREE_SLOWPATH); slab_lock(page); @@ -1724,9 +1684,6 @@ checks_ok: out_unlock: slab_unlock(page); -#ifdef SLUB_FASTPATH - local_irq_restore(flags); -#endif return; slab_empty: @@ -1739,9 +1696,6 @@ slab_empty: } slab_unlock(page); stat(c, FREE_SLAB); -#ifdef SLUB_FASTPATH - local_irq_restore(flags); -#endif discard_slab(s, page); return; @@ -1767,34 +1721,6 @@ static __always_inline void slab_free(struct kmem_cache *s, { void **object = (void *)x; struct kmem_cache_cpu *c; - -#ifdef SLUB_FASTPATH - void **freelist; - - c = get_cpu_slab(s, raw_smp_processor_id()); - debug_check_no_locks_freed(object, s->objsize); - do { - freelist = c->freelist; - barrier(); - /* - * If the compiler would reorder the retrieval of c->page to - * come before c->freelist then an interrupt could - * change the cpu slab before we retrieve c->freelist. We - * could be matching on a page no longer active and put the - * object onto the freelist of the wrong slab. - * - * On the other hand: If we already have the freelist pointer - * then any change of cpu_slab will cause the cmpxchg to fail - * since the freelist pointers are unique per slab. - */ - if (unlikely(page != c->page || c->node < 0)) { - __slab_free(s, page, x, addr, c->offset); - break; - } - object[c->offset] = freelist; - stat(c, FREE_FASTPATH); - } while (cmpxchg_local(&c->freelist, freelist, object) != freelist); -#else unsigned long flags; local_irq_save(flags); @@ -1808,7 +1734,6 @@ static __always_inline void slab_free(struct kmem_cache *s, __slab_free(s, page, x, addr, c->offset); local_irq_restore(flags); -#endif } void kmem_cache_free(struct kmem_cache *s, void *x) @@ -2329,10 +2254,33 @@ static int calculate_sizes(struct kmem_cache *s) size = ALIGN(size, align); s->size = size; - s->order = calculate_order(size); + if ((flags & __KMALLOC_CACHE) && + PAGE_SIZE / size < slub_min_objects) { + /* + * Kmalloc cache that would not have enough objects in + * an order 0 page. Kmalloc slabs can fallback to + * page allocator order 0 allocs so take a reasonably large + * order that will allows us a good number of objects. + */ + s->order = max(slub_max_order, PAGE_ALLOC_COSTLY_ORDER); + s->flags |= __PAGE_ALLOC_FALLBACK; + s->allocflags |= __GFP_NOWARN; + } else + s->order = calculate_order(size); + if (s->order < 0) return 0; + s->allocflags = 0; + if (s->order) + s->allocflags |= __GFP_COMP; + + if (s->flags & SLAB_CACHE_DMA) + s->allocflags |= SLUB_DMA; + + if (s->flags & SLAB_RECLAIM_ACCOUNT) + s->allocflags |= __GFP_RECLAIMABLE; + /* * Determine the number of objects per slab */ @@ -2484,11 +2432,11 @@ EXPORT_SYMBOL(kmem_cache_destroy); * Kmalloc subsystem *******************************************************************/ -struct kmem_cache kmalloc_caches[PAGE_SHIFT] __cacheline_aligned; +struct kmem_cache kmalloc_caches[PAGE_SHIFT + 1] __cacheline_aligned; EXPORT_SYMBOL(kmalloc_caches); #ifdef CONFIG_ZONE_DMA -static struct kmem_cache *kmalloc_caches_dma[PAGE_SHIFT]; +static struct kmem_cache *kmalloc_caches_dma[PAGE_SHIFT + 1]; #endif static int __init setup_slub_min_order(char *str) @@ -2536,7 +2484,7 @@ static struct kmem_cache *create_kmalloc_cache(struct kmem_cache *s, down_write(&slub_lock); if (!kmem_cache_open(s, gfp_flags, name, size, ARCH_KMALLOC_MINALIGN, - flags, NULL)) + flags | __KMALLOC_CACHE, NULL)) goto panic; list_add(&s->list, &slab_caches); @@ -2670,9 +2618,8 @@ void *__kmalloc(size_t size, gfp_t flags) { struct kmem_cache *s; - if (unlikely(size > PAGE_SIZE / 2)) - return (void *)__get_free_pages(flags | __GFP_COMP, - get_order(size)); + if (unlikely(size > PAGE_SIZE)) + return kmalloc_large(size, flags); s = get_slab(size, flags); @@ -2688,9 +2635,8 @@ void *__kmalloc_node(size_t size, gfp_t flags, int node) { struct kmem_cache *s; - if (unlikely(size > PAGE_SIZE / 2)) - return (void *)__get_free_pages(flags | __GFP_COMP, - get_order(size)); + if (unlikely(size > PAGE_SIZE)) + return kmalloc_large(size, flags); s = get_slab(size, flags); @@ -3001,7 +2947,7 @@ void __init kmem_cache_init(void) caches++; } - for (i = KMALLOC_SHIFT_LOW; i < PAGE_SHIFT; i++) { + for (i = KMALLOC_SHIFT_LOW; i <= PAGE_SHIFT; i++) { create_kmalloc_cache(&kmalloc_caches[i], "kmalloc", 1 << i, GFP_KERNEL); caches++; @@ -3028,7 +2974,7 @@ void __init kmem_cache_init(void) slab_state = UP; /* Provide the correct kmalloc names now that the caches are up */ - for (i = KMALLOC_SHIFT_LOW; i < PAGE_SHIFT; i++) + for (i = KMALLOC_SHIFT_LOW; i <= PAGE_SHIFT; i++) kmalloc_caches[i]. name = kasprintf(GFP_KERNEL, "kmalloc-%d", 1 << i); @@ -3057,6 +3003,9 @@ static int slab_unmergeable(struct kmem_cache *s) if (slub_nomerge || (s->flags & SLUB_NEVER_MERGE)) return 1; + if ((s->flags & __PAGE_ALLOC_FALLBACK)) + return 1; + if (s->ctor) return 1; @@ -3218,9 +3167,9 @@ void *__kmalloc_track_caller(size_t size, gfp_t gfpflags, void *caller) { struct kmem_cache *s; - if (unlikely(size > PAGE_SIZE / 2)) - return (void *)__get_free_pages(gfpflags | __GFP_COMP, - get_order(size)); + if (unlikely(size > PAGE_SIZE)) + return kmalloc_large(size, gfpflags); + s = get_slab(size, gfpflags); if (unlikely(ZERO_OR_NULL_PTR(s))) @@ -3234,9 +3183,9 @@ void *__kmalloc_node_track_caller(size_t size, gfp_t gfpflags, { struct kmem_cache *s; - if (unlikely(size > PAGE_SIZE / 2)) - return (void *)__get_free_pages(gfpflags | __GFP_COMP, - get_order(size)); + if (unlikely(size > PAGE_SIZE)) + return kmalloc_large(size, gfpflags); + s = get_slab(size, gfpflags); if (unlikely(ZERO_OR_NULL_PTR(s))) diff --git a/mm/swapfile.c b/mm/swapfile.c index 02ccab5ad9d9..2da149cfc9ac 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -1394,7 +1394,7 @@ static int swap_show(struct seq_file *swap, void *v) } file = ptr->swap_file; - len = seq_path(swap, file->f_path.mnt, file->f_path.dentry, " \t\n\\"); + len = seq_path(swap, &file->f_path, " \t\n\\"); seq_printf(swap, "%*s%s\t%u\t%u\t%d\n", len < 40 ? 40 - len : 1, " ", S_ISBLK(file->f_path.dentry->d_inode->i_mode) ? diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index 77f04e49a1a0..fc60c6d096b9 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c @@ -366,7 +366,8 @@ static int vlan_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct net_device_stats *stats = &dev->stats; struct vlan_ethhdr *veth = (struct vlan_ethhdr *)(skb->data); - + DECLARE_MAC_BUF(mac); + DECLARE_MAC_BUF(mac2); /* Handle non-VLAN frames if they are sent to us, for example by DHCP. * * NOTE: THIS ASSUMES DIX ETHERNET, SPECIFICALLY NOT SUPPORTING @@ -404,11 +405,8 @@ static int vlan_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) pr_debug("%s: about to send skb: %p to dev: %s\n", __FUNCTION__, skb, skb->dev->name); - pr_debug(" " MAC_FMT " " MAC_FMT " %4hx %4hx %4hx\n", - veth->h_dest[0], veth->h_dest[1], veth->h_dest[2], - veth->h_dest[3], veth->h_dest[4], veth->h_dest[5], - veth->h_source[0], veth->h_source[1], veth->h_source[2], - veth->h_source[3], veth->h_source[4], veth->h_source[5], + pr_debug(" %s %s %4hx %4hx %4hx\n", + print_mac(mac, veth->h_dest), print_mac(mac2, veth->h_source), veth->h_vlan_proto, veth->h_vlan_TCI, veth->h_vlan_encapsulated_proto); diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c index 0117b9fb8480..9e3d81cb9f08 100644 --- a/net/9p/trans_virtio.c +++ b/net/9p/trans_virtio.c @@ -183,8 +183,7 @@ pack_sg_list(struct scatterlist *sg, int start, int limit, char *data, sg_set_buf(&sg[index++], data, s); count -= s; data += s; - if (index > limit) - BUG(); + BUG_ON(index > limit); } return index-start; diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c index 8fc64e3150a2..48bfcc741f25 100644 --- a/net/ax25/af_ax25.c +++ b/net/ax25/af_ax25.c @@ -510,11 +510,7 @@ ax25_cb *ax25_create_cb(void) skb_queue_head_init(&ax25->ack_queue); skb_queue_head_init(&ax25->reseq_queue); - init_timer(&ax25->timer); - init_timer(&ax25->t1timer); - init_timer(&ax25->t2timer); - init_timer(&ax25->t3timer); - init_timer(&ax25->idletimer); + ax25_setup_timers(ax25); ax25_fillin_cb(ax25, NULL); @@ -1928,12 +1924,10 @@ static int ax25_info_show(struct seq_file *seq, void *v) ax25->paclen); if (ax25->sk != NULL) { - bh_lock_sock(ax25->sk); - seq_printf(seq," %d %d %ld\n", + seq_printf(seq, " %d %d %lu\n", atomic_read(&ax25->sk->sk_wmem_alloc), atomic_read(&ax25->sk->sk_rmem_alloc), - ax25->sk->sk_socket != NULL ? SOCK_INODE(ax25->sk->sk_socket)->i_ino : 0L); - bh_unlock_sock(ax25->sk); + sock_i_ino(ax25->sk)); } else { seq_puts(seq, " * * *\n"); } diff --git a/net/ax25/ax25_dev.c b/net/ax25/ax25_dev.c index 528c874d9828..a7a0e0c9698b 100644 --- a/net/ax25/ax25_dev.c +++ b/net/ax25/ax25_dev.c @@ -82,7 +82,7 @@ void ax25_dev_device_up(struct net_device *dev) ax25_dev->values[AX25_VALUES_DS_TIMEOUT]= AX25_DEF_DS_TIMEOUT; #if defined(CONFIG_AX25_DAMA_SLAVE) || defined(CONFIG_AX25_DAMA_MASTER) - init_timer(&ax25_dev->dama.slave_timer); + ax25_ds_setup_timer(ax25_dev); #endif spin_lock_bh(&ax25_dev_lock); diff --git a/net/ax25/ax25_ds_timer.c b/net/ax25/ax25_ds_timer.c index c4e3b025d21c..2ce79df00680 100644 --- a/net/ax25/ax25_ds_timer.c +++ b/net/ax25/ax25_ds_timer.c @@ -40,13 +40,10 @@ static void ax25_ds_timeout(unsigned long); * 1/10th of a second. */ -static void ax25_ds_add_timer(ax25_dev *ax25_dev) +void ax25_ds_setup_timer(ax25_dev *ax25_dev) { - struct timer_list *t = &ax25_dev->dama.slave_timer; - t->data = (unsigned long) ax25_dev; - t->function = &ax25_ds_timeout; - t->expires = jiffies + HZ; - add_timer(t); + setup_timer(&ax25_dev->dama.slave_timer, ax25_ds_timeout, + (unsigned long)ax25_dev); } void ax25_ds_del_timer(ax25_dev *ax25_dev) @@ -60,10 +57,9 @@ void ax25_ds_set_timer(ax25_dev *ax25_dev) if (ax25_dev == NULL) /* paranoia */ return; - del_timer(&ax25_dev->dama.slave_timer); ax25_dev->dama.slave_timeout = msecs_to_jiffies(ax25_dev->values[AX25_VALUES_DS_TIMEOUT]) / 10; - ax25_ds_add_timer(ax25_dev); + mod_timer(&ax25_dev->dama.slave_timer, jiffies + HZ); } /* diff --git a/net/ax25/ax25_out.c b/net/ax25/ax25_out.c index 92b517af7260..bf706f83a5c9 100644 --- a/net/ax25/ax25_out.c +++ b/net/ax25/ax25_out.c @@ -117,6 +117,12 @@ void ax25_output(ax25_cb *ax25, int paclen, struct sk_buff *skb) unsigned char *p; int frontlen, len, fragno, ka9qfrag, first = 1; + if (paclen < 16) { + WARN_ON_ONCE(1); + kfree_skb(skb); + return; + } + if ((skb->len - 1) > paclen) { if (*skb->data == AX25_P_TEXT) { skb_pull(skb, 1); /* skip PID */ @@ -251,8 +257,6 @@ void ax25_kick(ax25_cb *ax25) if (start == end) return; - ax25->vs = start; - /* * Transmit data until either we're out of data to send or * the window is full. Send a poll on the final I frame if @@ -261,8 +265,13 @@ void ax25_kick(ax25_cb *ax25) /* * Dequeue the frame and copy it. + * Check for race with ax25_clear_queues(). */ skb = skb_dequeue(&ax25->write_queue); + if (!skb) + return; + + ax25->vs = start; do { if ((skbn = skb_clone(skb, GFP_ATOMIC)) == NULL) { diff --git a/net/ax25/ax25_route.c b/net/ax25/ax25_route.c index 38c7f3087ec3..8672cd84fdf9 100644 --- a/net/ax25/ax25_route.c +++ b/net/ax25/ax25_route.c @@ -45,7 +45,7 @@ void ax25_rt_device_down(struct net_device *dev) { ax25_route *s, *t, *ax25_rt; - write_lock(&ax25_route_lock); + write_lock_bh(&ax25_route_lock); ax25_rt = ax25_route_list; while (ax25_rt != NULL) { s = ax25_rt; @@ -68,7 +68,7 @@ void ax25_rt_device_down(struct net_device *dev) } } } - write_unlock(&ax25_route_lock); + write_unlock_bh(&ax25_route_lock); } static int __must_check ax25_rt_add(struct ax25_routes_struct *route) @@ -82,7 +82,7 @@ static int __must_check ax25_rt_add(struct ax25_routes_struct *route) if (route->digi_count > AX25_MAX_DIGIS) return -EINVAL; - write_lock(&ax25_route_lock); + write_lock_bh(&ax25_route_lock); ax25_rt = ax25_route_list; while (ax25_rt != NULL) { @@ -92,7 +92,7 @@ static int __must_check ax25_rt_add(struct ax25_routes_struct *route) ax25_rt->digipeat = NULL; if (route->digi_count != 0) { if ((ax25_rt->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) { - write_unlock(&ax25_route_lock); + write_unlock_bh(&ax25_route_lock); return -ENOMEM; } ax25_rt->digipeat->lastrepeat = -1; @@ -102,14 +102,14 @@ static int __must_check ax25_rt_add(struct ax25_routes_struct *route) ax25_rt->digipeat->calls[i] = route->digi_addr[i]; } } - write_unlock(&ax25_route_lock); + write_unlock_bh(&ax25_route_lock); return 0; } ax25_rt = ax25_rt->next; } if ((ax25_rt = kmalloc(sizeof(ax25_route), GFP_ATOMIC)) == NULL) { - write_unlock(&ax25_route_lock); + write_unlock_bh(&ax25_route_lock); return -ENOMEM; } @@ -120,7 +120,7 @@ static int __must_check ax25_rt_add(struct ax25_routes_struct *route) ax25_rt->ip_mode = ' '; if (route->digi_count != 0) { if ((ax25_rt->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) { - write_unlock(&ax25_route_lock); + write_unlock_bh(&ax25_route_lock); kfree(ax25_rt); return -ENOMEM; } @@ -133,7 +133,7 @@ static int __must_check ax25_rt_add(struct ax25_routes_struct *route) } ax25_rt->next = ax25_route_list; ax25_route_list = ax25_rt; - write_unlock(&ax25_route_lock); + write_unlock_bh(&ax25_route_lock); return 0; } @@ -152,7 +152,7 @@ static int ax25_rt_del(struct ax25_routes_struct *route) if ((ax25_dev = ax25_addr_ax25dev(&route->port_addr)) == NULL) return -EINVAL; - write_lock(&ax25_route_lock); + write_lock_bh(&ax25_route_lock); ax25_rt = ax25_route_list; while (ax25_rt != NULL) { @@ -174,7 +174,7 @@ static int ax25_rt_del(struct ax25_routes_struct *route) } } } - write_unlock(&ax25_route_lock); + write_unlock_bh(&ax25_route_lock); return 0; } @@ -188,7 +188,7 @@ static int ax25_rt_opt(struct ax25_route_opt_struct *rt_option) if ((ax25_dev = ax25_addr_ax25dev(&rt_option->port_addr)) == NULL) return -EINVAL; - write_lock(&ax25_route_lock); + write_lock_bh(&ax25_route_lock); ax25_rt = ax25_route_list; while (ax25_rt != NULL) { @@ -216,7 +216,7 @@ static int ax25_rt_opt(struct ax25_route_opt_struct *rt_option) } out: - write_unlock(&ax25_route_lock); + write_unlock_bh(&ax25_route_lock); return err; } @@ -492,7 +492,7 @@ void __exit ax25_rt_free(void) { ax25_route *s, *ax25_rt = ax25_route_list; - write_lock(&ax25_route_lock); + write_lock_bh(&ax25_route_lock); while (ax25_rt != NULL) { s = ax25_rt; ax25_rt = ax25_rt->next; @@ -500,5 +500,5 @@ void __exit ax25_rt_free(void) kfree(s->digipeat); kfree(s); } - write_unlock(&ax25_route_lock); + write_unlock_bh(&ax25_route_lock); } diff --git a/net/ax25/ax25_timer.c b/net/ax25/ax25_timer.c index 72594867fab6..db29ea71e80a 100644 --- a/net/ax25/ax25_timer.c +++ b/net/ax25/ax25_timer.c @@ -40,63 +40,45 @@ static void ax25_t2timer_expiry(unsigned long); static void ax25_t3timer_expiry(unsigned long); static void ax25_idletimer_expiry(unsigned long); +void ax25_setup_timers(ax25_cb *ax25) +{ + setup_timer(&ax25->timer, ax25_heartbeat_expiry, (unsigned long)ax25); + setup_timer(&ax25->t1timer, ax25_t1timer_expiry, (unsigned long)ax25); + setup_timer(&ax25->t2timer, ax25_t2timer_expiry, (unsigned long)ax25); + setup_timer(&ax25->t3timer, ax25_t3timer_expiry, (unsigned long)ax25); + setup_timer(&ax25->idletimer, ax25_idletimer_expiry, + (unsigned long)ax25); +} + void ax25_start_heartbeat(ax25_cb *ax25) { - del_timer(&ax25->timer); - - ax25->timer.data = (unsigned long)ax25; - ax25->timer.function = &ax25_heartbeat_expiry; - ax25->timer.expires = jiffies + 5 * HZ; - - add_timer(&ax25->timer); + mod_timer(&ax25->timer, jiffies + 5 * HZ); } void ax25_start_t1timer(ax25_cb *ax25) { - del_timer(&ax25->t1timer); - - ax25->t1timer.data = (unsigned long)ax25; - ax25->t1timer.function = &ax25_t1timer_expiry; - ax25->t1timer.expires = jiffies + ax25->t1; - - add_timer(&ax25->t1timer); + mod_timer(&ax25->t1timer, jiffies + ax25->t1); } void ax25_start_t2timer(ax25_cb *ax25) { - del_timer(&ax25->t2timer); - - ax25->t2timer.data = (unsigned long)ax25; - ax25->t2timer.function = &ax25_t2timer_expiry; - ax25->t2timer.expires = jiffies + ax25->t2; - - add_timer(&ax25->t2timer); + mod_timer(&ax25->t2timer, jiffies + ax25->t2); } void ax25_start_t3timer(ax25_cb *ax25) { - del_timer(&ax25->t3timer); - - if (ax25->t3 > 0) { - ax25->t3timer.data = (unsigned long)ax25; - ax25->t3timer.function = &ax25_t3timer_expiry; - ax25->t3timer.expires = jiffies + ax25->t3; - - add_timer(&ax25->t3timer); - } + if (ax25->t3 > 0) + mod_timer(&ax25->t3timer, jiffies + ax25->t3); + else + del_timer(&ax25->t3timer); } void ax25_start_idletimer(ax25_cb *ax25) { - del_timer(&ax25->idletimer); - - if (ax25->idle > 0) { - ax25->idletimer.data = (unsigned long)ax25; - ax25->idletimer.function = &ax25_idletimer_expiry; - ax25->idletimer.expires = jiffies + ax25->idle; - - add_timer(&ax25->idletimer); - } + if (ax25->idle > 0) + mod_timer(&ax25->idletimer, jiffies + ax25->idle); + else + del_timer(&ax25->idletimer); } void ax25_stop_heartbeat(ax25_cb *ax25) diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 5fc7be206f62..f8880261da0e 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -260,7 +260,6 @@ int hci_conn_del(struct hci_conn *conn) tasklet_enable(&hdev->tx_task); skb_queue_purge(&conn->data_q); hci_conn_del_sysfs(conn); - hci_dev_put(hdev); return 0; } diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 372b0d3b75a8..930b58e7149a 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -24,6 +24,7 @@ /* Bluetooth HCI core. */ +#include #include #include @@ -1321,7 +1322,7 @@ static inline void hci_sched_acl(struct hci_dev *hdev) if (!test_bit(HCI_RAW, &hdev->flags)) { /* ACL tx timeout must be longer than maximum * link supervision timeout (40.9 seconds) */ - if (!hdev->acl_cnt && (jiffies - hdev->acl_last_tx) > (HZ * 45)) + if (!hdev->acl_cnt && time_after(jiffies, hdev->acl_last_tx + HZ * 45)) hci_acl_tx_to(hdev); } @@ -1543,7 +1544,7 @@ static void hci_cmd_task(unsigned long arg) BT_DBG("%s cmd %d", hdev->name, atomic_read(&hdev->cmd_cnt)); - if (!atomic_read(&hdev->cmd_cnt) && (jiffies - hdev->cmd_last_tx) > HZ) { + if (!atomic_read(&hdev->cmd_cnt) && time_after(jiffies, hdev->cmd_last_tx + HZ)) { BT_ERR("%s command tx timeout", hdev->name); atomic_set(&hdev->cmd_cnt, 1); } diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c index e13cf5ef144c..84360c117d4e 100644 --- a/net/bluetooth/hci_sysfs.c +++ b/net/bluetooth/hci_sysfs.c @@ -320,28 +320,34 @@ void hci_conn_add_sysfs(struct hci_conn *conn) queue_work(btaddconn, &conn->work); } +/* + * The rfcomm tty device will possibly retain even when conn + * is down, and sysfs doesn't support move zombie device, + * so we should move the device before conn device is destroyed. + */ static int __match_tty(struct device *dev, void *data) { - /* The rfcomm tty device will possibly retain even when conn - * is down, and sysfs doesn't support move zombie device, - * so we should move the device before conn device is destroyed. - * Due to the only child device of hci_conn dev is rfcomm - * tty_dev, here just return 1 - */ - return 1; + return !strncmp(dev->bus_id, "rfcomm", 6); } static void del_conn(struct work_struct *work) { - struct device *dev; struct hci_conn *conn = container_of(work, struct hci_conn, work); + struct hci_dev *hdev = conn->hdev; - while (dev = device_find_child(&conn->dev, NULL, __match_tty)) { + while (1) { + struct device *dev; + + dev = device_find_child(&conn->dev, NULL, __match_tty); + if (!dev) + break; device_move(dev, NULL); put_device(dev); } + device_del(&conn->dev); put_device(&conn->dev); + hci_dev_put(hdev); } void hci_conn_del_sysfs(struct hci_conn *conn) diff --git a/net/core/dev.c b/net/core/dev.c index b3e19ae57f95..908f07c3bd7d 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1071,8 +1071,6 @@ int dev_close(struct net_device *dev) */ call_netdevice_notifiers(NETDEV_GOING_DOWN, dev); - dev_deactivate(dev); - clear_bit(__LINK_STATE_START, &dev->state); /* Synchronize to scheduled poll. We cannot touch poll list, @@ -1083,6 +1081,8 @@ int dev_close(struct net_device *dev) */ smp_mb__after_clear_bit(); /* Commit netif_running(). */ + dev_deactivate(dev); + /* * Call the device specific close. This cannot fail. * Only if device is UP diff --git a/net/core/skbuff.c b/net/core/skbuff.c index cfc07dac636c..0d0fd28a9041 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -2106,11 +2106,10 @@ int skb_append_datato_frags(struct sock *sk, struct sk_buff *skb, /** * skb_pull_rcsum - pull skb and update receive checksum * @skb: buffer to update - * @start: start of data before pull * @len: length of data pulled * * This function performs an skb_pull on the packet and updates - * update the CHECKSUM_COMPLETE checksum. It should be used on + * the CHECKSUM_COMPLETE checksum. It should be used on * receive path processing instead of skb_pull unless you know * that the checksum difference is zero (e.g., a valid IP header) * or you are setting ip_summed to CHECKSUM_NONE. diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c index 9d4555ec0b59..8219b7e0968d 100644 --- a/net/ipv4/ah4.c +++ b/net/ipv4/ah4.c @@ -96,7 +96,7 @@ static int ah_output(struct xfrm_state *x, struct sk_buff *skb) ah->reserved = 0; ah->spi = x->id.spi; - ah->seq_no = htonl(XFRM_SKB_CB(skb)->seq); + ah->seq_no = htonl(XFRM_SKB_CB(skb)->seq.output); spin_lock_bh(&x->lock); err = ah_mac_digest(ahp, skb, ah->auth_data); diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c index 258d17631b4b..091e6709f831 100644 --- a/net/ipv4/esp4.c +++ b/net/ipv4/esp4.c @@ -199,7 +199,7 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb) } esph->spi = x->id.spi; - esph->seq_no = htonl(XFRM_SKB_CB(skb)->seq); + esph->seq_no = htonl(XFRM_SKB_CB(skb)->seq.output); sg_init_table(sg, nfrags); skb_to_sgvec(skb, sg, @@ -210,7 +210,8 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb) aead_givcrypt_set_callback(req, 0, esp_output_done, skb); aead_givcrypt_set_crypt(req, sg, sg, clen, iv); aead_givcrypt_set_assoc(req, asg, sizeof(*esph)); - aead_givcrypt_set_giv(req, esph->enc_data, XFRM_SKB_CB(skb)->seq); + aead_givcrypt_set_giv(req, esph->enc_data, + XFRM_SKB_CB(skb)->seq.output); ESP_SKB_CB(skb)->tmp = tmp; err = crypto_aead_givencrypt(req); diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index f5fba3f71c06..1ff446d0fa8b 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c @@ -1762,11 +1762,9 @@ static struct leaf *trie_leafindex(struct trie *t, int index) { struct leaf *l = trie_firstleaf(t); - while (index-- > 0) { + while (l && index-- > 0) l = trie_nextleaf(l); - if (!l) - break; - } + return l; } @@ -2461,6 +2459,84 @@ static const struct file_operations fib_trie_fops = { .release = seq_release_net, }; +struct fib_route_iter { + struct seq_net_private p; + struct trie *main_trie; + loff_t pos; + t_key key; +}; + +static struct leaf *fib_route_get_idx(struct fib_route_iter *iter, loff_t pos) +{ + struct leaf *l = NULL; + struct trie *t = iter->main_trie; + + /* use cache location of last found key */ + if (iter->pos > 0 && pos >= iter->pos && (l = fib_find_node(t, iter->key))) + pos -= iter->pos; + else { + iter->pos = 0; + l = trie_firstleaf(t); + } + + while (l && pos-- > 0) { + iter->pos++; + l = trie_nextleaf(l); + } + + if (l) + iter->key = pos; /* remember it */ + else + iter->pos = 0; /* forget it */ + + return l; +} + +static void *fib_route_seq_start(struct seq_file *seq, loff_t *pos) + __acquires(RCU) +{ + struct fib_route_iter *iter = seq->private; + struct fib_table *tb; + + rcu_read_lock(); + tb = fib_get_table(iter->p.net, RT_TABLE_MAIN); + if (!tb) + return NULL; + + iter->main_trie = (struct trie *) tb->tb_data; + if (*pos == 0) + return SEQ_START_TOKEN; + else + return fib_route_get_idx(iter, *pos - 1); +} + +static void *fib_route_seq_next(struct seq_file *seq, void *v, loff_t *pos) +{ + struct fib_route_iter *iter = seq->private; + struct leaf *l = v; + + ++*pos; + if (v == SEQ_START_TOKEN) { + iter->pos = 0; + l = trie_firstleaf(iter->main_trie); + } else { + iter->pos++; + l = trie_nextleaf(l); + } + + if (l) + iter->key = l->key; + else + iter->pos = 0; + return l; +} + +static void fib_route_seq_stop(struct seq_file *seq, void *v) + __releases(RCU) +{ + rcu_read_unlock(); +} + static unsigned fib_flag_trans(int type, __be32 mask, const struct fib_info *fi) { static unsigned type2flags[RTN_MAX + 1] = { @@ -2484,7 +2560,6 @@ static unsigned fib_flag_trans(int type, __be32 mask, const struct fib_info *fi) */ static int fib_route_seq_show(struct seq_file *seq, void *v) { - const struct fib_trie_iter *iter = seq->private; struct leaf *l = v; struct leaf_info *li; struct hlist_node *node; @@ -2496,12 +2571,6 @@ static int fib_route_seq_show(struct seq_file *seq, void *v) return 0; } - if (iter->trie == iter->trie_local) - return 0; - - if (IS_TNODE(l)) - return 0; - hlist_for_each_entry_rcu(li, node, &l->list, hlist) { struct fib_alias *fa; __be32 mask, prefix; @@ -2544,16 +2613,16 @@ static int fib_route_seq_show(struct seq_file *seq, void *v) } static const struct seq_operations fib_route_seq_ops = { - .start = fib_trie_seq_start, - .next = fib_trie_seq_next, - .stop = fib_trie_seq_stop, + .start = fib_route_seq_start, + .next = fib_route_seq_next, + .stop = fib_route_seq_stop, .show = fib_route_seq_show, }; static int fib_route_seq_open(struct inode *inode, struct file *file) { return seq_open_net(inode, file, &fib_route_seq_ops, - sizeof(struct fib_trie_iter)); + sizeof(struct fib_route_iter)); } static const struct file_operations fib_route_fops = { diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c index 9cac6c034abd..1aba606f6bbb 100644 --- a/net/ipv4/inet_hashtables.c +++ b/net/ipv4/inet_hashtables.c @@ -120,8 +120,6 @@ void inet_listen_wlock(struct inet_hashinfo *hashinfo) } } -EXPORT_SYMBOL(inet_listen_wlock); - /* * Don't inline this cruft. Here are some nice properties to exploit here. The * BSD API does not allow a listening sock to specify the remote port nor the @@ -494,7 +492,6 @@ out: return ret; } } -EXPORT_SYMBOL_GPL(__inet_hash_connect); /* * Bind a port for a connect operation and hash it. diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c index 754b0a5bbfe9..de0572c88859 100644 --- a/net/ipv4/ip_sockglue.c +++ b/net/ipv4/ip_sockglue.c @@ -514,11 +514,6 @@ static int do_ip_setsockopt(struct sock *sk, int level, val &= ~3; val |= inet->tos & 3; } - if (IPTOS_PREC(val) >= IPTOS_PREC_CRITIC_ECP && - !capable(CAP_NET_ADMIN)) { - err = -EPERM; - break; - } if (inet->tos != val) { inet->tos = val; sk->sk_priority = rt_tos2priority(val); diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c index a52b5853aaa8..10013ccee8dd 100644 --- a/net/ipv4/ipconfig.c +++ b/net/ipv4/ipconfig.c @@ -1390,7 +1390,7 @@ static int __init ip_auto_config(void) * Clue in the operator. */ printk("IP-Config: Complete:"); - printk("\n device=%s", ic_dev->name); + printk("\n device=%s", ic_dev->name); printk(", addr=%u.%u.%u.%u", NIPQUAD(ic_myaddr)); printk(", mask=%u.%u.%u.%u", NIPQUAD(ic_netmask)); printk(", gw=%u.%u.%u.%u", NIPQUAD(ic_gateway)); diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 63414ea427c5..00156bf421ca 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -719,7 +719,7 @@ static void tcp_v4_reqsk_send_ack(struct sk_buff *skb, } /* - * Send a SYN-ACK after having received an ACK. + * Send a SYN-ACK after having received a SYN. * This still operates on a request_sock only, not on a big * socket. */ diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index bddac0e8780f..f0aa97738746 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -752,14 +752,6 @@ static int __init inet6_init(void) BUILD_BUG_ON(sizeof(struct inet6_skb_parm) > sizeof(dummy_skb->cb)); -#ifdef MODULE -#if 0 /* FIXME --RR */ - if (!mod_member_present(&__this_module, can_unload)) - return -EINVAL; - - __this_module.can_unload = &ipv6_unload; -#endif -#endif err = proto_register(&tcpv6_prot, 1); if (err) goto out; diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c index 379c8e04c36c..2ff0c8233e47 100644 --- a/net/ipv6/ah6.c +++ b/net/ipv6/ah6.c @@ -283,7 +283,7 @@ static int ah6_output(struct xfrm_state *x, struct sk_buff *skb) ah->reserved = 0; ah->spi = x->id.spi; - ah->seq_no = htonl(XFRM_SKB_CB(skb)->seq); + ah->seq_no = htonl(XFRM_SKB_CB(skb)->seq.output); spin_lock_bh(&x->lock); err = ah_mac_digest(ahp, skb, ah->auth_data); diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c index 8e0f1428c716..0ec1402320ea 100644 --- a/net/ipv6/esp6.c +++ b/net/ipv6/esp6.c @@ -188,7 +188,7 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb) *skb_mac_header(skb) = IPPROTO_ESP; esph->spi = x->id.spi; - esph->seq_no = htonl(XFRM_SKB_CB(skb)->seq); + esph->seq_no = htonl(XFRM_SKB_CB(skb)->seq.output); sg_init_table(sg, nfrags); skb_to_sgvec(skb, sg, @@ -199,7 +199,8 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb) aead_givcrypt_set_callback(req, 0, esp_output_done, skb); aead_givcrypt_set_crypt(req, sg, sg, clen, iv); aead_givcrypt_set_assoc(req, asg, sizeof(*esph)); - aead_givcrypt_set_giv(req, esph->enc_data, XFRM_SKB_CB(skb)->seq); + aead_givcrypt_set_giv(req, esph->enc_data, + XFRM_SKB_CB(skb)->seq.output); ESP_SKB_CB(skb)->tmp = tmp; err = crypto_aead_givencrypt(req); diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index f93407cf6515..bab72b6f1444 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c @@ -1151,7 +1151,7 @@ static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp, fn = fn->parent; } /* No more references are possible at this point. */ - if (atomic_read(&rt->rt6i_ref) != 1) BUG(); + BUG_ON(atomic_read(&rt->rt6i_ref) != 1); } inet6_rt_notify(RTM_DELROUTE, rt, info); diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 9ac6ca2521c3..8b67ca07467d 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -621,7 +621,7 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) * or if the skb it not generated by a local socket. (This last * check should be redundant, but it's free.) */ - if (!np || np->pmtudisc >= IPV6_PMTUDISC_DO) { + if (!skb->local_df) { skb->dev = skb->dst->dev; icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, skb->dev); IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_FRAGFAILS); @@ -1420,6 +1420,10 @@ int ip6_push_pending_frames(struct sock *sk) tmp_skb->sk = NULL; } + /* Allow local fragmentation. */ + if (np->pmtudisc < IPV6_PMTUDISC_DO) + skb->local_df = 1; + ipv6_addr_copy(final_dst, &fl->fl6_dst); __skb_pull(skb, skb_network_header_len(skb)); if (opt && opt->opt_flen) diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 9031e521c1df..cd940647bd12 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -550,6 +550,7 @@ ip4ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, ip_rt_put(rt); goto out; } + skb2->dst = (struct dst_entry *)rt; } else { ip_rt_put(rt); if (ip_route_input(skb2, eiph->daddr, eiph->saddr, eiph->tos, diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c index b34c58c65656..79ccfb080733 100644 --- a/net/ipv6/xfrm6_output.c +++ b/net/ipv6/xfrm6_output.c @@ -36,7 +36,7 @@ static int xfrm6_tunnel_check_size(struct sk_buff *skb) if (mtu < IPV6_MIN_MTU) mtu = IPV6_MIN_MTU; - if (skb->len > mtu) { + if (!skb->local_df && skb->len > mtu) { skb->dev = dst->dev; icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, skb->dev); ret = -EMSGSIZE; diff --git a/net/key/af_key.c b/net/key/af_key.c index b3ac85e808ac..1c853927810a 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -2291,6 +2291,7 @@ static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h return 0; out: + xp->dead = 1; xfrm_policy_destroy(xp); return err; } diff --git a/net/mac80211/ieee80211.c b/net/mac80211/ieee80211.c index 67b7c75c430d..28bcdf9fc3df 100644 --- a/net/mac80211/ieee80211.c +++ b/net/mac80211/ieee80211.c @@ -165,6 +165,7 @@ static int ieee80211_open(struct net_device *dev) struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_if_init_conf conf; int res; + bool need_hw_reconfig = 0; sdata = IEEE80211_DEV_TO_SUB_IF(dev); @@ -218,7 +219,7 @@ static int ieee80211_open(struct net_device *dev) res = local->ops->start(local_to_hw(local)); if (res) return res; - ieee80211_hw_config(local); + need_hw_reconfig = 1; ieee80211_led_radio(local, local->hw.conf.radio_enabled); } @@ -282,6 +283,8 @@ static int ieee80211_open(struct net_device *dev) atomic_inc(&local->iff_promiscs); local->open_count++; + if (need_hw_reconfig) + ieee80211_hw_config(local); netif_start_queue(dev); diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c index 202d7fa09483..62567959b66e 100644 --- a/net/netfilter/nf_conntrack_proto_tcp.c +++ b/net/netfilter/nf_conntrack_proto_tcp.c @@ -945,7 +945,7 @@ static int tcp_packet(struct nf_conn *ct, ct->proto.tcp.state = new_state; if (old_state != new_state - && new_state == TCP_CONNTRACK_CLOSE) + && new_state == TCP_CONNTRACK_FIN_WAIT) ct->proto.tcp.seen[dir].flags |= IP_CT_TCP_FLAG_CLOSE_INIT; timeout = ct->proto.tcp.retrans >= nf_ct_tcp_max_retrans && tcp_timeouts[new_state] > nf_ct_tcp_timeout_max_retrans diff --git a/net/netfilter/xt_SECMARK.c b/net/netfilter/xt_SECMARK.c index 7708e2084ce2..c0284856ccd4 100644 --- a/net/netfilter/xt_SECMARK.c +++ b/net/netfilter/xt_SECMARK.c @@ -111,7 +111,7 @@ secmark_tg_check(const char *tablename, const void *entry, return true; } -void secmark_tg_destroy(const struct xt_target *target, void *targinfo) +static void secmark_tg_destroy(const struct xt_target *target, void *targinfo) { switch (mode) { case SECMARK_MODE_SEL: diff --git a/net/netlabel/netlabel_cipso_v4.c b/net/netlabel/netlabel_cipso_v4.c index c7ad64d664ad..fdc14a0d21af 100644 --- a/net/netlabel/netlabel_cipso_v4.c +++ b/net/netlabel/netlabel_cipso_v4.c @@ -718,36 +718,35 @@ static int netlbl_cipsov4_remove(struct sk_buff *skb, struct genl_info *info) * NetLabel Generic NETLINK Command Definitions */ -static struct genl_ops netlbl_cipsov4_genl_c_add = { +static struct genl_ops netlbl_cipsov4_ops[] = { + { .cmd = NLBL_CIPSOV4_C_ADD, .flags = GENL_ADMIN_PERM, .policy = netlbl_cipsov4_genl_policy, .doit = netlbl_cipsov4_add, .dumpit = NULL, -}; - -static struct genl_ops netlbl_cipsov4_genl_c_remove = { + }, + { .cmd = NLBL_CIPSOV4_C_REMOVE, .flags = GENL_ADMIN_PERM, .policy = netlbl_cipsov4_genl_policy, .doit = netlbl_cipsov4_remove, .dumpit = NULL, -}; - -static struct genl_ops netlbl_cipsov4_genl_c_list = { + }, + { .cmd = NLBL_CIPSOV4_C_LIST, .flags = 0, .policy = netlbl_cipsov4_genl_policy, .doit = netlbl_cipsov4_list, .dumpit = NULL, -}; - -static struct genl_ops netlbl_cipsov4_genl_c_listall = { + }, + { .cmd = NLBL_CIPSOV4_C_LISTALL, .flags = 0, .policy = netlbl_cipsov4_genl_policy, .doit = NULL, .dumpit = netlbl_cipsov4_listall, + }, }; /* @@ -762,30 +761,20 @@ static struct genl_ops netlbl_cipsov4_genl_c_listall = { * mechanism. Returns zero on success, negative values on failure. * */ -int netlbl_cipsov4_genl_init(void) +int __init netlbl_cipsov4_genl_init(void) { - int ret_val; + int ret_val, i; ret_val = genl_register_family(&netlbl_cipsov4_gnl_family); if (ret_val != 0) return ret_val; - ret_val = genl_register_ops(&netlbl_cipsov4_gnl_family, - &netlbl_cipsov4_genl_c_add); - if (ret_val != 0) - return ret_val; - ret_val = genl_register_ops(&netlbl_cipsov4_gnl_family, - &netlbl_cipsov4_genl_c_remove); - if (ret_val != 0) - return ret_val; - ret_val = genl_register_ops(&netlbl_cipsov4_gnl_family, - &netlbl_cipsov4_genl_c_list); - if (ret_val != 0) - return ret_val; - ret_val = genl_register_ops(&netlbl_cipsov4_gnl_family, - &netlbl_cipsov4_genl_c_listall); - if (ret_val != 0) - return ret_val; + for (i = 0; i < ARRAY_SIZE(netlbl_cipsov4_ops); i++) { + ret_val = genl_register_ops(&netlbl_cipsov4_gnl_family, + &netlbl_cipsov4_ops[i]); + if (ret_val != 0) + return ret_val; + } return 0; } diff --git a/net/netlabel/netlabel_domainhash.c b/net/netlabel/netlabel_domainhash.c index 9a8ea0195c4f..02c2f7c0b255 100644 --- a/net/netlabel/netlabel_domainhash.c +++ b/net/netlabel/netlabel_domainhash.c @@ -150,11 +150,11 @@ static struct netlbl_dom_map *netlbl_domhsh_search_def(const char *domain) entry = netlbl_domhsh_search(domain); if (entry == NULL) { entry = rcu_dereference(netlbl_domhsh_def); - if (entry != NULL && entry->valid) - return entry; + if (entry != NULL && !entry->valid) + entry = NULL; } - return NULL; + return entry; } /* @@ -171,7 +171,7 @@ static struct netlbl_dom_map *netlbl_domhsh_search_def(const char *domain) * values on error. * */ -int netlbl_domhsh_init(u32 size) +int __init netlbl_domhsh_init(u32 size) { u32 iter; struct netlbl_domhsh_tbl *hsh_tbl; diff --git a/net/netlabel/netlabel_mgmt.c b/net/netlabel/netlabel_mgmt.c index e2258dc3c845..22c191267808 100644 --- a/net/netlabel/netlabel_mgmt.c +++ b/net/netlabel/netlabel_mgmt.c @@ -517,68 +517,63 @@ version_failure: * NetLabel Generic NETLINK Command Definitions */ -static struct genl_ops netlbl_mgmt_genl_c_add = { +static struct genl_ops netlbl_mgmt_genl_ops[] = { + { .cmd = NLBL_MGMT_C_ADD, .flags = GENL_ADMIN_PERM, .policy = netlbl_mgmt_genl_policy, .doit = netlbl_mgmt_add, .dumpit = NULL, -}; - -static struct genl_ops netlbl_mgmt_genl_c_remove = { + }, + { .cmd = NLBL_MGMT_C_REMOVE, .flags = GENL_ADMIN_PERM, .policy = netlbl_mgmt_genl_policy, .doit = netlbl_mgmt_remove, .dumpit = NULL, -}; - -static struct genl_ops netlbl_mgmt_genl_c_listall = { + }, + { .cmd = NLBL_MGMT_C_LISTALL, .flags = 0, .policy = netlbl_mgmt_genl_policy, .doit = NULL, .dumpit = netlbl_mgmt_listall, -}; - -static struct genl_ops netlbl_mgmt_genl_c_adddef = { + }, + { .cmd = NLBL_MGMT_C_ADDDEF, .flags = GENL_ADMIN_PERM, .policy = netlbl_mgmt_genl_policy, .doit = netlbl_mgmt_adddef, .dumpit = NULL, -}; - -static struct genl_ops netlbl_mgmt_genl_c_removedef = { + }, + { .cmd = NLBL_MGMT_C_REMOVEDEF, .flags = GENL_ADMIN_PERM, .policy = netlbl_mgmt_genl_policy, .doit = netlbl_mgmt_removedef, .dumpit = NULL, -}; - -static struct genl_ops netlbl_mgmt_genl_c_listdef = { + }, + { .cmd = NLBL_MGMT_C_LISTDEF, .flags = 0, .policy = netlbl_mgmt_genl_policy, .doit = netlbl_mgmt_listdef, .dumpit = NULL, -}; - -static struct genl_ops netlbl_mgmt_genl_c_protocols = { + }, + { .cmd = NLBL_MGMT_C_PROTOCOLS, .flags = 0, .policy = netlbl_mgmt_genl_policy, .doit = NULL, .dumpit = netlbl_mgmt_protocols, -}; - -static struct genl_ops netlbl_mgmt_genl_c_version = { + }, + { .cmd = NLBL_MGMT_C_VERSION, .flags = 0, .policy = netlbl_mgmt_genl_policy, .doit = netlbl_mgmt_version, .dumpit = NULL, + }, }; /* @@ -593,46 +588,20 @@ static struct genl_ops netlbl_mgmt_genl_c_version = { * mechanism. Returns zero on success, negative values on failure. * */ -int netlbl_mgmt_genl_init(void) +int __init netlbl_mgmt_genl_init(void) { - int ret_val; + int ret_val, i; ret_val = genl_register_family(&netlbl_mgmt_gnl_family); if (ret_val != 0) return ret_val; - ret_val = genl_register_ops(&netlbl_mgmt_gnl_family, - &netlbl_mgmt_genl_c_add); - if (ret_val != 0) - return ret_val; - ret_val = genl_register_ops(&netlbl_mgmt_gnl_family, - &netlbl_mgmt_genl_c_remove); - if (ret_val != 0) - return ret_val; - ret_val = genl_register_ops(&netlbl_mgmt_gnl_family, - &netlbl_mgmt_genl_c_listall); - if (ret_val != 0) - return ret_val; - ret_val = genl_register_ops(&netlbl_mgmt_gnl_family, - &netlbl_mgmt_genl_c_adddef); - if (ret_val != 0) - return ret_val; - ret_val = genl_register_ops(&netlbl_mgmt_gnl_family, - &netlbl_mgmt_genl_c_removedef); - if (ret_val != 0) - return ret_val; - ret_val = genl_register_ops(&netlbl_mgmt_gnl_family, - &netlbl_mgmt_genl_c_listdef); - if (ret_val != 0) - return ret_val; - ret_val = genl_register_ops(&netlbl_mgmt_gnl_family, - &netlbl_mgmt_genl_c_protocols); - if (ret_val != 0) - return ret_val; - ret_val = genl_register_ops(&netlbl_mgmt_gnl_family, - &netlbl_mgmt_genl_c_version); - if (ret_val != 0) - return ret_val; + for (i = 0; i < ARRAY_SIZE(netlbl_mgmt_genl_ops); i++) { + ret_val = genl_register_ops(&netlbl_mgmt_gnl_family, + &netlbl_mgmt_genl_ops[i]); + if (ret_val != 0) + return ret_val; + } return 0; } diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c index 42e81fd8cc49..4478f2f6079d 100644 --- a/net/netlabel/netlabel_unlabeled.c +++ b/net/netlabel/netlabel_unlabeled.c @@ -180,6 +180,7 @@ static void netlbl_unlabel_audit_addr4(struct audit_buffer *audit_buf, } } +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) /** * netlbl_unlabel_audit_addr6 - Audit an IPv6 address * @audit_buf: audit buffer @@ -213,6 +214,7 @@ static void netlbl_unlabel_audit_addr6(struct audit_buffer *audit_buf, audit_log_format(audit_buf, " src_prefixlen=%d", mask_len); } } +#endif /* IPv6 */ /* * Unlabeled Connection Hash Table Functions @@ -617,8 +619,6 @@ static int netlbl_unlhsh_add(struct net *net, int ifindex; struct net_device *dev; struct netlbl_unlhsh_iface *iface; - struct in_addr *addr4, *mask4; - struct in6_addr *addr6, *mask6; struct audit_buffer *audit_buf = NULL; char *secctx = NULL; u32 secctx_len; @@ -651,7 +651,9 @@ static int netlbl_unlhsh_add(struct net *net, audit_buf = netlbl_audit_start_common(AUDIT_MAC_UNLBL_STCADD, audit_info); switch (addr_len) { - case sizeof(struct in_addr): + case sizeof(struct in_addr): { + struct in_addr *addr4, *mask4; + addr4 = (struct in_addr *)addr; mask4 = (struct in_addr *)mask; ret_val = netlbl_unlhsh_add_addr4(iface, addr4, mask4, secid); @@ -661,8 +663,11 @@ static int netlbl_unlhsh_add(struct net *net, addr4->s_addr, mask4->s_addr); break; + } #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) - case sizeof(struct in6_addr): + case sizeof(struct in6_addr): { + struct in6_addr *addr6, *mask6; + addr6 = (struct in6_addr *)addr; mask6 = (struct in6_addr *)mask; ret_val = netlbl_unlhsh_add_addr6(iface, addr6, mask6, secid); @@ -671,6 +676,7 @@ static int netlbl_unlhsh_add(struct net *net, dev_name, addr6, mask6); break; + } #endif /* IPv6 */ default: ret_val = -EINVAL; @@ -1547,68 +1553,63 @@ unlabel_staticlistdef_return: * NetLabel Generic NETLINK Command Definitions */ -static struct genl_ops netlbl_unlabel_genl_c_staticadd = { +static struct genl_ops netlbl_unlabel_genl_ops[] = { + { .cmd = NLBL_UNLABEL_C_STATICADD, .flags = GENL_ADMIN_PERM, .policy = netlbl_unlabel_genl_policy, .doit = netlbl_unlabel_staticadd, .dumpit = NULL, -}; - -static struct genl_ops netlbl_unlabel_genl_c_staticremove = { + }, + { .cmd = NLBL_UNLABEL_C_STATICREMOVE, .flags = GENL_ADMIN_PERM, .policy = netlbl_unlabel_genl_policy, .doit = netlbl_unlabel_staticremove, .dumpit = NULL, -}; - -static struct genl_ops netlbl_unlabel_genl_c_staticlist = { + }, + { .cmd = NLBL_UNLABEL_C_STATICLIST, .flags = 0, .policy = netlbl_unlabel_genl_policy, .doit = NULL, .dumpit = netlbl_unlabel_staticlist, -}; - -static struct genl_ops netlbl_unlabel_genl_c_staticadddef = { + }, + { .cmd = NLBL_UNLABEL_C_STATICADDDEF, .flags = GENL_ADMIN_PERM, .policy = netlbl_unlabel_genl_policy, .doit = netlbl_unlabel_staticadddef, .dumpit = NULL, -}; - -static struct genl_ops netlbl_unlabel_genl_c_staticremovedef = { + }, + { .cmd = NLBL_UNLABEL_C_STATICREMOVEDEF, .flags = GENL_ADMIN_PERM, .policy = netlbl_unlabel_genl_policy, .doit = netlbl_unlabel_staticremovedef, .dumpit = NULL, -}; - -static struct genl_ops netlbl_unlabel_genl_c_staticlistdef = { + }, + { .cmd = NLBL_UNLABEL_C_STATICLISTDEF, .flags = 0, .policy = netlbl_unlabel_genl_policy, .doit = NULL, .dumpit = netlbl_unlabel_staticlistdef, -}; - -static struct genl_ops netlbl_unlabel_genl_c_accept = { + }, + { .cmd = NLBL_UNLABEL_C_ACCEPT, .flags = GENL_ADMIN_PERM, .policy = netlbl_unlabel_genl_policy, .doit = netlbl_unlabel_accept, .dumpit = NULL, -}; - -static struct genl_ops netlbl_unlabel_genl_c_list = { + }, + { .cmd = NLBL_UNLABEL_C_LIST, .flags = 0, .policy = netlbl_unlabel_genl_policy, .doit = netlbl_unlabel_list, .dumpit = NULL, + }, }; /* @@ -1623,53 +1624,20 @@ static struct genl_ops netlbl_unlabel_genl_c_list = { * mechanism. Returns zero on success, negative values on failure. * */ -int netlbl_unlabel_genl_init(void) +int __init netlbl_unlabel_genl_init(void) { - int ret_val; + int ret_val, i; ret_val = genl_register_family(&netlbl_unlabel_gnl_family); if (ret_val != 0) return ret_val; - ret_val = genl_register_ops(&netlbl_unlabel_gnl_family, - &netlbl_unlabel_genl_c_staticadd); - if (ret_val != 0) - return ret_val; - - ret_val = genl_register_ops(&netlbl_unlabel_gnl_family, - &netlbl_unlabel_genl_c_staticremove); - if (ret_val != 0) - return ret_val; - - ret_val = genl_register_ops(&netlbl_unlabel_gnl_family, - &netlbl_unlabel_genl_c_staticlist); - if (ret_val != 0) - return ret_val; - - ret_val = genl_register_ops(&netlbl_unlabel_gnl_family, - &netlbl_unlabel_genl_c_staticadddef); - if (ret_val != 0) - return ret_val; - - ret_val = genl_register_ops(&netlbl_unlabel_gnl_family, - &netlbl_unlabel_genl_c_staticremovedef); - if (ret_val != 0) - return ret_val; - - ret_val = genl_register_ops(&netlbl_unlabel_gnl_family, - &netlbl_unlabel_genl_c_staticlistdef); - if (ret_val != 0) - return ret_val; - - ret_val = genl_register_ops(&netlbl_unlabel_gnl_family, - &netlbl_unlabel_genl_c_accept); - if (ret_val != 0) - return ret_val; - - ret_val = genl_register_ops(&netlbl_unlabel_gnl_family, - &netlbl_unlabel_genl_c_list); - if (ret_val != 0) - return ret_val; + for (i = 0; i < ARRAY_SIZE(netlbl_unlabel_genl_ops); i++) { + ret_val = genl_register_ops(&netlbl_unlabel_gnl_family, + &netlbl_unlabel_genl_ops[i]); + if (ret_val != 0) + return ret_val; + } return 0; } @@ -1693,7 +1661,7 @@ static struct notifier_block netlbl_unlhsh_netdev_notifier = { * non-zero values on error. * */ -int netlbl_unlabel_init(u32 size) +int __init netlbl_unlabel_init(u32 size) { u32 iter; struct netlbl_unlhsh_tbl *hsh_tbl; @@ -1741,10 +1709,6 @@ int netlbl_unlabel_getattr(const struct sk_buff *skb, u16 family, struct netlbl_lsm_secattr *secattr) { - struct iphdr *hdr4; - struct ipv6hdr *hdr6; - struct netlbl_unlhsh_addr4 *addr4; - struct netlbl_unlhsh_addr6 *addr6; struct netlbl_unlhsh_iface *iface; rcu_read_lock(); @@ -1752,21 +1716,29 @@ int netlbl_unlabel_getattr(const struct sk_buff *skb, if (iface == NULL) goto unlabel_getattr_nolabel; switch (family) { - case PF_INET: + case PF_INET: { + struct iphdr *hdr4; + struct netlbl_unlhsh_addr4 *addr4; + hdr4 = ip_hdr(skb); addr4 = netlbl_unlhsh_search_addr4(hdr4->saddr, iface); if (addr4 == NULL) goto unlabel_getattr_nolabel; secattr->attr.secid = addr4->secid; break; + } #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) - case PF_INET6: + case PF_INET6: { + struct ipv6hdr *hdr6; + struct netlbl_unlhsh_addr6 *addr6; + hdr6 = ipv6_hdr(skb); addr6 = netlbl_unlhsh_search_addr6(&hdr6->saddr, iface); if (addr6 == NULL) goto unlabel_getattr_nolabel; secattr->attr.secid = addr6->secid; break; + } #endif /* IPv6 */ default: goto unlabel_getattr_nolabel; @@ -1793,7 +1765,7 @@ unlabel_getattr_nolabel: * and to send unlabeled network traffic by default. * */ -int netlbl_unlabel_defconf(void) +int __init netlbl_unlabel_defconf(void) { int ret_val; struct netlbl_dom_map *entry; diff --git a/net/netlabel/netlabel_user.c b/net/netlabel/netlabel_user.c index 85a96a3fddaa..b17d4203806e 100644 --- a/net/netlabel/netlabel_user.c +++ b/net/netlabel/netlabel_user.c @@ -59,7 +59,7 @@ * non-zero on failure. * */ -int netlbl_netlink_init(void) +int __init netlbl_netlink_init(void) { int ret_val; @@ -96,7 +96,6 @@ int netlbl_netlink_init(void) struct audit_buffer *netlbl_audit_start_common(int type, struct netlbl_audit *audit_info) { - struct audit_context *audit_ctx = current->audit_context; struct audit_buffer *audit_buf; char *secctx; u32 secctx_len; @@ -104,7 +103,7 @@ struct audit_buffer *netlbl_audit_start_common(int type, if (audit_enabled == 0) return NULL; - audit_buf = audit_log_start(audit_ctx, GFP_ATOMIC, type); + audit_buf = audit_log_start(current->audit_context, GFP_ATOMIC, type); if (audit_buf == NULL) return NULL; diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index 150579a21469..d16929c9b4bc 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c @@ -230,10 +230,8 @@ static void genl_unregister_mc_groups(struct genl_family *family) { struct genl_multicast_group *grp, *tmp; - genl_lock(); list_for_each_entry_safe(grp, tmp, &family->mcast_groups, list) __genl_unregister_mc_group(family, grp); - genl_unlock(); } /** @@ -396,10 +394,10 @@ int genl_unregister_family(struct genl_family *family) { struct genl_family *rc; - genl_unregister_mc_groups(family); - genl_lock(); + genl_unregister_mc_groups(family); + list_for_each_entry(rc, genl_family_chain(family->id), family_list) { if (family->id != rc->id || strcmp(rc->name, family->name)) continue; diff --git a/net/rxrpc/ar-accept.c b/net/rxrpc/ar-accept.c index 92a87fde8bfe..bdfb77417794 100644 --- a/net/rxrpc/ar-accept.c +++ b/net/rxrpc/ar-accept.c @@ -156,8 +156,7 @@ static int rxrpc_accept_incoming_call(struct rxrpc_local *local, false); spin_unlock(&call->lock); notification = NULL; - if (ret < 0) - BUG(); + BUG_ON(ret < 0); } spin_unlock(&call->conn->state_lock); diff --git a/net/rxrpc/ar-ack.c b/net/rxrpc/ar-ack.c index 657ee69f2133..3ac1672e1070 100644 --- a/net/rxrpc/ar-ack.c +++ b/net/rxrpc/ar-ack.c @@ -814,8 +814,7 @@ static int rxrpc_post_message(struct rxrpc_call *call, u32 mark, u32 error, spin_lock_bh(&call->lock); ret = rxrpc_queue_rcv_skb(call, skb, true, fatal); spin_unlock_bh(&call->lock); - if (ret < 0) - BUG(); + BUG_ON(ret < 0); } return 0; diff --git a/net/socket.c b/net/socket.c index 7651de008502..b6d35cd72a50 100644 --- a/net/socket.c +++ b/net/socket.c @@ -701,6 +701,9 @@ static ssize_t sock_splice_read(struct file *file, loff_t *ppos, { struct socket *sock = file->private_data; + if (unlikely(!sock->ops->splice_read)) + return -EINVAL; + return sock->ops->splice_read(sock, ppos, pipe, len, flags); } diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index 0e3ead7e11b9..1b395a41a8b2 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c @@ -495,7 +495,7 @@ rpc_lookup_parent(char *path, struct nameidata *nd) static void rpc_release_path(struct nameidata *nd) { - path_release(nd); + path_put(&nd->path); rpc_put_mount(); } @@ -668,7 +668,8 @@ rpc_lookup_negative(char *path, struct nameidata *nd) if ((error = rpc_lookup_parent(path, nd)) != 0) return ERR_PTR(error); - dentry = rpc_lookup_create(nd->dentry, nd->last.name, nd->last.len, 1); + dentry = rpc_lookup_create(nd->path.dentry, nd->last.name, nd->last.len, + 1); if (IS_ERR(dentry)) rpc_release_path(nd); return dentry; @@ -695,7 +696,7 @@ rpc_mkdir(char *path, struct rpc_clnt *rpc_client) dentry = rpc_lookup_negative(path, &nd); if (IS_ERR(dentry)) return dentry; - dir = nd.dentry->d_inode; + dir = nd.path.dentry->d_inode; if ((error = __rpc_mkdir(dir, dentry)) != 0) goto err_dput; RPC_I(dentry->d_inode)->private = rpc_client; diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index eea75888805e..b8788fd5e3c6 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -718,16 +718,16 @@ static struct sock *unix_find_other(struct net *net, goto put_fail; err = -ECONNREFUSED; - if (!S_ISSOCK(nd.dentry->d_inode->i_mode)) + if (!S_ISSOCK(nd.path.dentry->d_inode->i_mode)) goto put_fail; - u=unix_find_socket_byinode(net, nd.dentry->d_inode); + u = unix_find_socket_byinode(net, nd.path.dentry->d_inode); if (!u) goto put_fail; if (u->sk_type == type) - touch_atime(nd.mnt, nd.dentry); + touch_atime(nd.path.mnt, nd.path.dentry); - path_release(&nd); + path_put(&nd.path); err=-EPROTOTYPE; if (u->sk_type != type) { @@ -748,7 +748,7 @@ static struct sock *unix_find_other(struct net *net, return u; put_fail: - path_release(&nd); + path_put(&nd.path); fail: *error=err; return NULL; @@ -819,12 +819,12 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) */ mode = S_IFSOCK | (SOCK_INODE(sock)->i_mode & ~current->fs->umask); - err = vfs_mknod(nd.dentry->d_inode, dentry, mode, 0); + err = vfs_mknod(nd.path.dentry->d_inode, dentry, mode, 0); if (err) goto out_mknod_dput; - mutex_unlock(&nd.dentry->d_inode->i_mutex); - dput(nd.dentry); - nd.dentry = dentry; + mutex_unlock(&nd.path.dentry->d_inode->i_mutex); + dput(nd.path.dentry); + nd.path.dentry = dentry; addr->hash = UNIX_HASH_SIZE; } @@ -842,8 +842,8 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) list = &unix_socket_table[addr->hash]; } else { list = &unix_socket_table[dentry->d_inode->i_ino & (UNIX_HASH_SIZE-1)]; - u->dentry = nd.dentry; - u->mnt = nd.mnt; + u->dentry = nd.path.dentry; + u->mnt = nd.path.mnt; } err = 0; @@ -861,8 +861,8 @@ out: out_mknod_dput: dput(dentry); out_mknod_unlock: - mutex_unlock(&nd.dentry->d_inode->i_mutex); - path_release(&nd); + mutex_unlock(&nd.path.dentry->d_inode->i_mutex); + path_put(&nd.path); out_mknod_parent: if (err==-EEXIST) err=-EADDRINUSE; diff --git a/net/xfrm/Kconfig b/net/xfrm/Kconfig index 8f9dbec319be..9201ef8ad90e 100644 --- a/net/xfrm/Kconfig +++ b/net/xfrm/Kconfig @@ -38,7 +38,7 @@ config XFRM_MIGRATE config XFRM_STATISTICS bool "Transformation statistics (EXPERIMENTAL)" - depends on XFRM && PROC_FS && EXPERIMENTAL + depends on INET && XFRM && PROC_FS && EXPERIMENTAL ---help--- This statistics is not a SNMP/MIB specification but shows statistics about transformation error (or almost error) factor diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c index 4d6ebc633a94..62188c6a06dd 100644 --- a/net/xfrm/xfrm_input.c +++ b/net/xfrm/xfrm_input.c @@ -109,7 +109,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type) if (encap_type < 0) { async = 1; x = xfrm_input_state(skb); - seq = XFRM_SKB_CB(skb)->seq; + seq = XFRM_SKB_CB(skb)->seq.input; goto resume; } @@ -175,7 +175,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type) spin_unlock(&x->lock); - XFRM_SKB_CB(skb)->seq = seq; + XFRM_SKB_CB(skb)->seq.input = seq; nexthdr = x->type->input(x, skb); diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c index fc690368325f..569d377932c4 100644 --- a/net/xfrm/xfrm_output.c +++ b/net/xfrm/xfrm_output.c @@ -62,7 +62,7 @@ static int xfrm_output_one(struct sk_buff *skb, int err) } if (x->type->flags & XFRM_TYPE_REPLAY_PROT) { - XFRM_SKB_CB(skb)->seq = ++x->replay.oseq; + XFRM_SKB_CB(skb)->seq.output = ++x->replay.oseq; if (unlikely(x->replay.oseq == 0)) { XFRM_INC_STATS(LINUX_MIB_XFRMOUTSTATESEQERROR); x->replay.oseq--; diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 47219f98053f..9fc4c315f6cd 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -331,15 +331,31 @@ static void xfrm_dst_hash_transfer(struct hlist_head *list, struct hlist_head *ndsttable, unsigned int nhashmask) { - struct hlist_node *entry, *tmp; + struct hlist_node *entry, *tmp, *entry0 = NULL; struct xfrm_policy *pol; + unsigned int h0 = 0; +redo: hlist_for_each_entry_safe(pol, entry, tmp, list, bydst) { unsigned int h; h = __addr_hash(&pol->selector.daddr, &pol->selector.saddr, pol->family, nhashmask); - hlist_add_head(&pol->bydst, ndsttable+h); + if (!entry0) { + hlist_del(entry); + hlist_add_head(&pol->bydst, ndsttable+h); + h0 = h; + } else { + if (h != h0) + continue; + hlist_del(entry); + hlist_add_after(entry0, &pol->bydst); + } + entry0 = entry; + } + if (!hlist_empty(list)) { + entry0 = NULL; + goto redo; } } diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 78338079b7f5..f971ca5645f8 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -1105,6 +1105,7 @@ static struct xfrm_policy *xfrm_policy_construct(struct xfrm_userpolicy_info *p, return xp; error: *errp = err; + xp->dead = 1; xfrm_policy_destroy(xp); return NULL; } diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c index 3929e5b35e79..4a03191ad176 100644 --- a/scripts/kconfig/symbol.c +++ b/scripts/kconfig/symbol.c @@ -298,22 +298,30 @@ void sym_calc_value(struct symbol *sym) if (sym_is_choice_value(sym) && sym->visible == yes) { prop = sym_get_choice_prop(sym); newval.tri = (prop_get_symbol(prop)->curr.val == sym) ? yes : no; - } else if (EXPR_OR(sym->visible, sym->rev_dep.tri) != no) { - sym->flags |= SYMBOL_WRITE; - if (sym_has_value(sym)) - newval.tri = sym->def[S_DEF_USER].tri; - else if (!sym_is_choice(sym)) { - prop = sym_get_default_prop(sym); - if (prop) - newval.tri = expr_calc_value(prop->expr); - } - newval.tri = EXPR_OR(EXPR_AND(newval.tri, sym->visible), sym->rev_dep.tri); - } else if (!sym_is_choice(sym)) { - prop = sym_get_default_prop(sym); - if (prop) { + } else { + if (sym->visible != no) { + /* if the symbol is visible use the user value + * if available, otherwise try the default value + */ sym->flags |= SYMBOL_WRITE; - newval.tri = expr_calc_value(prop->expr); + if (sym_has_value(sym)) { + newval.tri = EXPR_AND(sym->def[S_DEF_USER].tri, + sym->visible); + goto calc_newval; + } } + if (sym->rev_dep.tri != no) + sym->flags |= SYMBOL_WRITE; + if (!sym_is_choice(sym)) { + prop = sym_get_default_prop(sym); + if (prop) { + sym->flags |= SYMBOL_WRITE; + newval.tri = EXPR_AND(expr_calc_value(prop->expr), + prop->visible.tri); + } + } + calc_newval: + newval.tri = EXPR_OR(newval.tri, sym->rev_dep.tri); } if (newval.tri == mod && sym_get_type(sym) == S_BOOLEAN) newval.tri = yes; diff --git a/scripts/kernel-doc b/scripts/kernel-doc index 6c18a14386a4..26146cbaa504 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -1624,7 +1624,6 @@ sub dump_function($$) { $prototype =~ s/^static +//; $prototype =~ s/^extern +//; - $prototype =~ s/^fastcall +//; $prototype =~ s/^asmlinkage +//; $prototype =~ s/^inline +//; $prototype =~ s/^__inline__ +//; diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 61742771c65d..695b5d657cf5 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -1200,7 +1200,7 @@ static void report_sec_mismatch(const char *modname, enum mismatch mismatch, "annotate %s with a matching annotation.\n", from, sec2annotation(fromsec), fromsym, from_p, to, sec2annotation(tosec), tosym, to_p, - fromsym, tosym, fromsym); + tosym, fromsym, tosym); break; case INIT_TO_EXIT: fprintf(stderr, diff --git a/security/selinux/avc.c b/security/selinux/avc.c index e8529e2f51e5..187964e88af1 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c @@ -568,10 +568,11 @@ void avc_audit(u32 ssid, u32 tsid, audit_log_format(ab, " capability=%d", a->u.cap); break; case AVC_AUDIT_DATA_FS: - if (a->u.fs.dentry) { - struct dentry *dentry = a->u.fs.dentry; - if (a->u.fs.mnt) { - audit_log_d_path(ab, "path=", dentry, a->u.fs.mnt); + if (a->u.fs.path.dentry) { + struct dentry *dentry = a->u.fs.path.dentry; + if (a->u.fs.path.mnt) { + audit_log_d_path(ab, "path=", + &a->u.fs.path); } else { audit_log_format(ab, " name="); audit_log_untrustedstring(ab, dentry->d_name.name); @@ -626,8 +627,12 @@ void avc_audit(u32 ssid, u32 tsid, case AF_UNIX: u = unix_sk(sk); if (u->dentry) { + struct path path = { + .dentry = u->dentry, + .mnt = u->mnt + }; audit_log_d_path(ab, "path=", - u->dentry, u->mnt); + &path); break; } if (!u->addr) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 44f16d9041e3..75c2e99bfb81 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -1356,8 +1356,8 @@ static inline int dentry_has_perm(struct task_struct *tsk, struct inode *inode = dentry->d_inode; struct avc_audit_data ad; AVC_AUDIT_DATA_INIT(&ad,FS); - ad.u.fs.mnt = mnt; - ad.u.fs.dentry = dentry; + ad.u.fs.path.mnt = mnt; + ad.u.fs.path.dentry = dentry; return inode_has_perm(tsk, inode, av, &ad); } @@ -1375,15 +1375,12 @@ static int file_has_perm(struct task_struct *tsk, { struct task_security_struct *tsec = tsk->security; struct file_security_struct *fsec = file->f_security; - struct vfsmount *mnt = file->f_path.mnt; - struct dentry *dentry = file->f_path.dentry; - struct inode *inode = dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; struct avc_audit_data ad; int rc; AVC_AUDIT_DATA_INIT(&ad, FS); - ad.u.fs.mnt = mnt; - ad.u.fs.dentry = dentry; + ad.u.fs.path = file->f_path; if (tsec->sid != fsec->sid) { rc = avc_has_perm(tsec->sid, fsec->sid, @@ -1418,7 +1415,7 @@ static int may_create(struct inode *dir, sbsec = dir->i_sb->s_security; AVC_AUDIT_DATA_INIT(&ad, FS); - ad.u.fs.dentry = dentry; + ad.u.fs.path.dentry = dentry; rc = avc_has_perm(tsec->sid, dsec->sid, SECCLASS_DIR, DIR__ADD_NAME | DIR__SEARCH, @@ -1476,7 +1473,7 @@ static int may_link(struct inode *dir, isec = dentry->d_inode->i_security; AVC_AUDIT_DATA_INIT(&ad, FS); - ad.u.fs.dentry = dentry; + ad.u.fs.path.dentry = dentry; av = DIR__SEARCH; av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME); @@ -1523,7 +1520,7 @@ static inline int may_rename(struct inode *old_dir, AVC_AUDIT_DATA_INIT(&ad, FS); - ad.u.fs.dentry = old_dentry; + ad.u.fs.path.dentry = old_dentry; rc = avc_has_perm(tsec->sid, old_dsec->sid, SECCLASS_DIR, DIR__REMOVE_NAME | DIR__SEARCH, &ad); if (rc) @@ -1539,7 +1536,7 @@ static inline int may_rename(struct inode *old_dir, return rc; } - ad.u.fs.dentry = new_dentry; + ad.u.fs.path.dentry = new_dentry; av = DIR__ADD_NAME | DIR__SEARCH; if (new_dentry->d_inode) av |= DIR__REMOVE_NAME; @@ -1918,8 +1915,7 @@ static int selinux_bprm_set_security(struct linux_binprm *bprm) } AVC_AUDIT_DATA_INIT(&ad, FS); - ad.u.fs.mnt = bprm->file->f_path.mnt; - ad.u.fs.dentry = bprm->file->f_path.dentry; + ad.u.fs.path = bprm->file->f_path; if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) newsid = tsec->sid; @@ -2315,7 +2311,7 @@ static int selinux_sb_kern_mount(struct super_block *sb, void *data) return rc; AVC_AUDIT_DATA_INIT(&ad,FS); - ad.u.fs.dentry = sb->s_root; + ad.u.fs.path.dentry = sb->s_root; return superblock_has_perm(current, sb, FILESYSTEM__MOUNT, &ad); } @@ -2324,7 +2320,7 @@ static int selinux_sb_statfs(struct dentry *dentry) struct avc_audit_data ad; AVC_AUDIT_DATA_INIT(&ad,FS); - ad.u.fs.dentry = dentry->d_sb->s_root; + ad.u.fs.path.dentry = dentry->d_sb->s_root; return superblock_has_perm(current, dentry->d_sb, FILESYSTEM__GETATTR, &ad); } @@ -2341,10 +2337,10 @@ static int selinux_mount(char * dev_name, return rc; if (flags & MS_REMOUNT) - return superblock_has_perm(current, nd->mnt->mnt_sb, + return superblock_has_perm(current, nd->path.mnt->mnt_sb, FILESYSTEM__REMOUNT, NULL); else - return dentry_has_perm(current, nd->mnt, nd->dentry, + return dentry_has_perm(current, nd->path.mnt, nd->path.dentry, FILE__MOUNTON); } @@ -2587,7 +2583,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, char *name, void *value return -EPERM; AVC_AUDIT_DATA_INIT(&ad,FS); - ad.u.fs.dentry = dentry; + ad.u.fs.path.dentry = dentry; rc = avc_has_perm(tsec->sid, isec->sid, isec->sclass, FILE__RELABELFROM, &ad); diff --git a/security/selinux/include/avc.h b/security/selinux/include/avc.h index 80c28fa6621c..8e23d7a873a4 100644 --- a/security/selinux/include/avc.h +++ b/security/selinux/include/avc.h @@ -13,6 +13,7 @@ #include #include #include +#include #include #include "flask.h" #include "av_permissions.h" @@ -30,8 +31,6 @@ extern int selinux_enforcing; struct avc_entry; struct task_struct; -struct vfsmount; -struct dentry; struct inode; struct sock; struct sk_buff; @@ -46,8 +45,7 @@ struct avc_audit_data { struct task_struct *tsk; union { struct { - struct vfsmount *mnt; - struct dentry *dentry; + struct path path; struct inode *inode; } fs; struct { diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 5b690482f8cb..25cbfa3f71f4 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -325,7 +325,7 @@ static int smack_sb_statfs(struct dentry *dentry) static int smack_sb_mount(char *dev_name, struct nameidata *nd, char *type, unsigned long flags, void *data) { - struct superblock_smack *sbp = nd->mnt->mnt_sb->s_security; + struct superblock_smack *sbp = nd->path.mnt->mnt_sb->s_security; return smk_curacc(sbp->smk_floor, MAY_WRITE); } @@ -1251,9 +1251,8 @@ static void smack_to_secattr(char *smack, struct netlbl_lsm_secattr *nlsp) switch (smack_net_nltype) { case NETLBL_NLTYPE_CIPSOV4: - nlsp->domain = NULL; - nlsp->flags = NETLBL_SECATTR_DOMAIN; - nlsp->flags |= NETLBL_SECATTR_MLS_LVL; + nlsp->domain = kstrdup(smack, GFP_ATOMIC); + nlsp->flags = NETLBL_SECATTR_DOMAIN | NETLBL_SECATTR_MLS_LVL; rc = smack_to_cipso(smack, &cipso); if (rc == 0) { @@ -1282,15 +1281,14 @@ static int smack_netlabel(struct sock *sk) { struct socket_smack *ssp; struct netlbl_lsm_secattr secattr; - int rc = 0; + int rc; ssp = sk->sk_security; netlbl_secattr_init(&secattr); smack_to_secattr(ssp->smk_out, &secattr); - if (secattr.flags != NETLBL_SECATTR_NONE) - rc = netlbl_sock_setattr(sk, &secattr); - + rc = netlbl_sock_setattr(sk, &secattr); netlbl_secattr_destroy(&secattr); + return rc; } @@ -1313,6 +1311,7 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name, struct inode_smack *nsp = inode->i_security; struct socket_smack *ssp; struct socket *sock; + int rc = 0; if (value == NULL || size > SMK_LABELLEN) return -EACCES; @@ -1341,7 +1340,10 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name, ssp->smk_in = sp; else if (strcmp(name, XATTR_SMACK_IPOUT) == 0) { ssp->smk_out = sp; - return smack_netlabel(sock->sk); + rc = smack_netlabel(sock->sk); + if (rc != 0) + printk(KERN_WARNING "Smack: \"%s\" netlbl error %d.\n", + __func__, -rc); } else return -EOPNOTSUPP; @@ -2214,6 +2216,9 @@ static void smack_sock_graft(struct sock *sk, struct socket *parent) ssp->smk_packet[0] = '\0'; rc = smack_netlabel(sk); + if (rc != 0) + printk(KERN_WARNING "Smack: \"%s\" netlbl error %d.\n", + __func__, -rc); } /** @@ -2345,6 +2350,20 @@ static int smack_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) return 0; } +/* + * smack_secctx_to_secid - return the secid for a smack label + * @secdata: smack label + * @seclen: how long result is + * @secid: outgoing integer + * + * Exists for audit and networking code. + */ +static int smack_secctx_to_secid(char *secdata, u32 seclen, u32 *secid) +{ + *secid = smack_to_secid(secdata); + return 0; +} + /* * smack_release_secctx - don't do anything. * @key_ref: unused @@ -2475,6 +2494,7 @@ static struct security_operations smack_ops = { .key_permission = smack_key_permission, #endif /* CONFIG_KEYS */ .secid_to_secctx = smack_secid_to_secctx, + .secctx_to_secid = smack_secctx_to_secid, .release_secctx = smack_release_secctx, }; diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c index 15aa37f65b39..358c92c1a153 100644 --- a/security/smack/smackfs.c +++ b/security/smack/smackfs.c @@ -24,6 +24,7 @@ #include #include #include +#include #include "smack.h" /* @@ -45,6 +46,7 @@ enum smk_inos { */ static DEFINE_MUTEX(smack_list_lock); static DEFINE_MUTEX(smack_cipso_lock); +static DEFINE_MUTEX(smack_ambient_lock); /* * This is the "ambient" label for network traffic. @@ -342,6 +344,9 @@ void smk_cipso_doi(void) struct cipso_v4_doi *doip; struct netlbl_audit audit_info; + audit_info.loginuid = audit_get_loginuid(current); + audit_info.secid = smack_to_secid(current->security); + rc = netlbl_cfg_map_del(NULL, &audit_info); if (rc != 0) printk(KERN_WARNING "%s:%d remove rc = %d\n", @@ -363,6 +368,30 @@ void smk_cipso_doi(void) __func__, __LINE__, rc); } +/** + * smk_unlbl_ambient - initialize the unlabeled domain + */ +void smk_unlbl_ambient(char *oldambient) +{ + int rc; + struct netlbl_audit audit_info; + + audit_info.loginuid = audit_get_loginuid(current); + audit_info.secid = smack_to_secid(current->security); + + if (oldambient != NULL) { + rc = netlbl_cfg_map_del(oldambient, &audit_info); + if (rc != 0) + printk(KERN_WARNING "%s:%d remove rc = %d\n", + __func__, __LINE__, rc); + } + + rc = netlbl_cfg_unlbl_add_map(smack_net_ambient, &audit_info); + if (rc != 0) + printk(KERN_WARNING "%s:%d add rc = %d\n", + __func__, __LINE__, rc); +} + /* * Seq_file read operations for /smack/cipso */ @@ -709,7 +738,6 @@ static ssize_t smk_read_ambient(struct file *filp, char __user *buf, size_t cn, loff_t *ppos) { ssize_t rc; - char out[SMK_LABELLEN]; int asize; if (*ppos != 0) @@ -717,23 +745,18 @@ static ssize_t smk_read_ambient(struct file *filp, char __user *buf, /* * Being careful to avoid a problem in the case where * smack_net_ambient gets changed in midstream. - * Since smack_net_ambient is always set with a value - * from the label list, including initially, and those - * never get freed, the worst case is that the pointer - * gets changed just after this strncpy, in which case - * the value passed up is incorrect. Locking around - * smack_net_ambient wouldn't be any better than this - * copy scheme as by the time the caller got to look - * at the ambient value it would have cleared the lock - * and been changed. */ - strncpy(out, smack_net_ambient, SMK_LABELLEN); - asize = strlen(out) + 1; + mutex_lock(&smack_ambient_lock); - if (cn < asize) - return -EINVAL; + asize = strlen(smack_net_ambient) + 1; - rc = simple_read_from_buffer(buf, cn, ppos, out, asize); + if (cn >= asize) + rc = simple_read_from_buffer(buf, cn, ppos, + smack_net_ambient, asize); + else + rc = -EINVAL; + + mutex_unlock(&smack_ambient_lock); return rc; } @@ -751,6 +774,7 @@ static ssize_t smk_write_ambient(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { char in[SMK_LABELLEN]; + char *oldambient; char *smack; if (!capable(CAP_MAC_ADMIN)) @@ -766,7 +790,13 @@ static ssize_t smk_write_ambient(struct file *file, const char __user *buf, if (smack == NULL) return -EINVAL; + mutex_lock(&smack_ambient_lock); + + oldambient = smack_net_ambient; smack_net_ambient = smack; + smk_unlbl_ambient(oldambient); + + mutex_unlock(&smack_ambient_lock); return count; } @@ -974,6 +1004,7 @@ static int __init init_smk_fs(void) sema_init(&smack_write_sem, 1); smk_cipso_doi(); + smk_unlbl_ambient(NULL); return err; } diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index f97c1ba43a28..47cfa5186e34 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c @@ -149,13 +149,13 @@ struct snd_seq_client *snd_seq_client_use_ptr(int clientid) } spin_unlock_irqrestore(&clients_lock, flags); #ifdef CONFIG_KMOD - if (!in_interrupt() && current->fs->root) { + if (!in_interrupt()) { static char client_requested[SNDRV_SEQ_GLOBAL_CLIENTS]; static char card_requested[SNDRV_CARDS]; if (clientid < SNDRV_SEQ_GLOBAL_CLIENTS) { int idx; - if (! client_requested[clientid] && current->fs->root) { + if (!client_requested[clientid]) { client_requested[clientid] = 1; for (idx = 0; idx < 15; idx++) { if (seq_client_load[idx] < 0) diff --git a/sound/core/seq/seq_device.c b/sound/core/seq/seq_device.c index 155dc7da4722..2f00ad28a2b7 100644 --- a/sound/core/seq/seq_device.c +++ b/sound/core/seq/seq_device.c @@ -149,9 +149,6 @@ void snd_seq_device_load_drivers(void) if (snd_seq_in_init) return; - if (! current->fs->root) - return; - mutex_lock(&ops_mutex); list_for_each_entry(ops, &opslist, list) { if (! (ops->driver & DRIVER_LOADED) && diff --git a/sound/core/sound.c b/sound/core/sound.c index 00cca4d6e562..812f91b3de5b 100644 --- a/sound/core/sound.c +++ b/sound/core/sound.c @@ -71,8 +71,6 @@ static DEFINE_MUTEX(sound_mutex); */ void snd_request_card(int card) { - if (! current->fs->root) - return; if (snd_card_locked(card)) return; if (card < 0 || card >= cards_limit) @@ -86,8 +84,6 @@ static void snd_request_other(int minor) { char *str; - if (! current->fs->root) - return; switch (minor) { case SNDRV_MINOR_SEQUENCER: str = "snd-seq"; break; case SNDRV_MINOR_TIMER: str = "snd-timer"; break; diff --git a/sound/core/timer.c b/sound/core/timer.c index aece465934b8..9d8184a2c2d0 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c @@ -150,8 +150,6 @@ static struct snd_timer *snd_timer_find(struct snd_timer_id *tid) static void snd_timer_request(struct snd_timer_id *tid) { - if (! current->fs->root) - return; switch (tid->dev_class) { case SNDRV_TIMER_CLASS_GLOBAL: if (tid->device < timer_limit) diff --git a/sound/ppc/daca.c b/sound/ppc/daca.c index 8432c16cd6ff..ca9452901a50 100644 --- a/sound/ppc/daca.c +++ b/sound/ppc/daca.c @@ -250,9 +250,8 @@ int __init snd_pmac_daca_init(struct snd_pmac *chip) struct pmac_daca *mix; #ifdef CONFIG_KMOD - if (current->fs->root) - request_module("i2c-powermac"); -#endif /* CONFIG_KMOD */ + request_module("i2c-powermac"); +#endif /* CONFIG_KMOD */ mix = kzalloc(sizeof(*mix), GFP_KERNEL); if (! mix) diff --git a/sound/ppc/tumbler.c b/sound/ppc/tumbler.c index 71a7a9765429..3f8d7164cef9 100644 --- a/sound/ppc/tumbler.c +++ b/sound/ppc/tumbler.c @@ -1351,9 +1351,8 @@ int __init snd_pmac_tumbler_init(struct snd_pmac *chip) char *chipname; #ifdef CONFIG_KMOD - if (current->fs->root) - request_module("i2c-powermac"); -#endif /* CONFIG_KMOD */ + request_module("i2c-powermac"); +#endif /* CONFIG_KMOD */ mix = kzalloc(sizeof(*mix), GFP_KERNEL); if (! mix)