diff options
631 files changed, 13452 insertions, 7682 deletions
diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile index 8918a32c6b3..b1eb661e630 100644 --- a/Documentation/DocBook/Makefile +++ b/Documentation/DocBook/Makefile @@ -143,7 +143,8 @@ quiet_cmd_db2pdf = PDF $@ $(call cmd,db2pdf) -main_idx = Documentation/DocBook/index.html +index = index.html +main_idx = Documentation/DocBook/$(index) build_main_index = rm -rf $(main_idx) && \ echo '<h1>Linux Kernel HTML Documentation</h1>' >> $(main_idx) && \ echo '<h2>Kernel Version: $(KERNELVERSION)</h2>' >> $(main_idx) && \ @@ -232,7 +233,7 @@ clean-files := $(DOCBOOKS) \ $(patsubst %.xml, %.pdf, $(DOCBOOKS)) \ $(patsubst %.xml, %.html, $(DOCBOOKS)) \ $(patsubst %.xml, %.9, $(DOCBOOKS)) \ - $(C-procfs-example) + $(C-procfs-example) $(index) clean-dirs := $(patsubst %.xml,%,$(DOCBOOKS)) man diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking index 76efe5b71d7..3120f8dd2c3 100644 --- a/Documentation/filesystems/Locking +++ b/Documentation/filesystems/Locking @@ -512,16 +512,24 @@ locking rules: BKL mmap_sem PageLocked(page) open: no yes close: no yes -fault: no yes -page_mkwrite: no yes no +fault: no yes can return with page locked +page_mkwrite: no yes can return with page locked access: no yes - ->page_mkwrite() is called when a previously read-only page is -about to become writeable. The file system is responsible for -protecting against truncate races. Once appropriate action has been -taking to lock out truncate, the page range should be verified to be -within i_size. The page mapping should also be checked that it is not -NULL. + ->fault() is called when a previously not present pte is about +to be faulted in. The filesystem must find and return the page associated +with the passed in "pgoff" in the vm_fault structure. If it is possible that +the page may be truncated and/or invalidated, then the filesystem must lock +the page, then ensure it is not already truncated (the page lock will block +subsequent truncate), and then return with VM_FAULT_LOCKED, and the page +locked. The VM will unlock the page. + + ->page_mkwrite() is called when a previously read-only pte is +about to become writeable. The filesystem again must ensure that there are +no truncate/invalidate races, and then return with the page locked. If +the page has been truncated, the filesystem should not look up a new page +like the ->fault() handler, but simply return with VM_FAULT_NOPAGE, which +will cause the VM to retry the fault. ->access() is called when get_user_pages() fails in acces_process_vm(), typically used to debug a process through diff --git a/Documentation/input/bcm5974.txt b/Documentation/input/bcm5974.txt new file mode 100644 index 00000000000..5e22dcf6d48 --- /dev/null +++ b/Documentation/input/bcm5974.txt @@ -0,0 +1,65 @@ +BCM5974 Driver (bcm5974) +------------------------ + Copyright (C) 2008-2009 Henrik Rydberg <rydberg@euromail.se> + +The USB initialization and package decoding was made by Scott Shawcroft as +part of the touchd user-space driver project: + Copyright (C) 2008 Scott Shawcroft (scott.shawcroft@gmail.com) + +The BCM5974 driver is based on the appletouch driver: + Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com) + Copyright (C) 2005 Johannes Berg (johannes@sipsolutions.net) + Copyright (C) 2005 Stelian Pop (stelian@popies.net) + Copyright (C) 2005 Frank Arnold (frank@scirocco-5v-turbo.de) + Copyright (C) 2005 Peter Osterlund (petero2@telia.com) + Copyright (C) 2005 Michael Hanselmann (linux-kernel@hansmi.ch) + Copyright (C) 2006 Nicolas Boichat (nicolas@boichat.ch) + +This driver adds support for the multi-touch trackpad on the new Apple +Macbook Air and Macbook Pro laptops. It replaces the appletouch driver on +those computers, and integrates well with the synaptics driver of the Xorg +system. + +Known to work on Macbook Air, Macbook Pro Penryn and the new unibody +Macbook 5 and Macbook Pro 5. + +Usage +----- + +The driver loads automatically for the supported usb device ids, and +becomes available both as an event device (/dev/input/event*) and as a +mouse via the mousedev driver (/dev/input/mice). + +USB Race +-------- + +The Apple multi-touch trackpads report both mouse and keyboard events via +different interfaces of the same usb device. This creates a race condition +with the HID driver, which, if not told otherwise, will find the standard +HID mouse and keyboard, and claim the whole device. To remedy, the usb +product id must be listed in the mouse_ignore list of the hid driver. + +Debug output +------------ + +To ease the development for new hardware version, verbose packet output can +be switched on with the debug kernel module parameter. The range [1-9] +yields different levels of verbosity. Example (as root): + +echo -n 9 > /sys/module/bcm5974/parameters/debug + +tail -f /var/log/debug + +echo -n 0 > /sys/module/bcm5974/parameters/debug + +Trivia +------ + +The driver was developed at the ubuntu forums in June 2008 [1], and now has +a more permanent home at bitmath.org [2]. + +Links +----- + +[1] http://ubuntuforums.org/showthread.php?t=840040 +[2] http://http://bitmath.org/code/ diff --git a/Documentation/input/multi-touch-protocol.txt b/Documentation/input/multi-touch-protocol.txt new file mode 100644 index 00000000000..9f09557aea3 --- /dev/null +++ b/Documentation/input/multi-touch-protocol.txt @@ -0,0 +1,140 @@ +Multi-touch (MT) Protocol +------------------------- + Copyright (C) 2009 Henrik Rydberg <rydberg@euromail.se> + + +Introduction +------------ + +In order to utilize the full power of the new multi-touch devices, a way to +report detailed finger data to user space is needed. This document +describes the multi-touch (MT) protocol which allows kernel drivers to +report details for an arbitrary number of fingers. + + +Usage +----- + +Anonymous finger details are sent sequentially as separate packets of ABS +events. Only the ABS_MT events are recognized as part of a finger +packet. The end of a packet is marked by calling the input_mt_sync() +function, which generates a SYN_MT_REPORT event. The end of multi-touch +transfer is marked by calling the usual input_sync() function. + +A set of ABS_MT events with the desired properties is defined. The events +are divided into categories, to allow for partial implementation. The +minimum set consists of ABS_MT_TOUCH_MAJOR, ABS_MT_POSITION_X and +ABS_MT_POSITION_Y, which allows for multiple fingers to be tracked. If the +device supports it, the ABS_MT_WIDTH_MAJOR may be used to provide the size +of the approaching finger. Anisotropy and direction may be specified with +ABS_MT_TOUCH_MINOR, ABS_MT_WIDTH_MINOR and ABS_MT_ORIENTATION. Devices with +more granular information may specify general shapes as blobs, i.e., as a +sequence of rectangular shapes grouped together by an +ABS_MT_BLOB_ID. Finally, the ABS_MT_TOOL_TYPE may be used to specify +whether the touching tool is a finger or a pen or something else. + + +Event Semantics +--------------- + +The word "contact" is used to describe a tool which is in direct contact +with the surface. A finger, a pen or a rubber all classify as contacts. + +ABS_MT_TOUCH_MAJOR + +The length of the major axis of the contact. The length should be given in +surface units. If the surface has an X times Y resolution, the largest +possible value of ABS_MT_TOUCH_MAJOR is sqrt(X^2 + Y^2), the diagonal. + +ABS_MT_TOUCH_MINOR + +The length, in surface units, of the minor axis of the contact. If the +contact is circular, this event can be omitted. + +ABS_MT_WIDTH_MAJOR + +The length, in surface units, of the major axis of the approaching +tool. This should be understood as the size of the tool itself. The +orientation of the contact and the approaching tool are assumed to be the +same. + +ABS_MT_WIDTH_MINOR + +The length, in surface units, of the minor axis of the approaching +tool. Omit if circular. + +The above four values can be used to derive additional information about +the contact. The ratio ABS_MT_TOUCH_MAJOR / ABS_MT_WIDTH_MAJOR approximates +the notion of pressure. The fingers of the hand and the palm all have +different characteristic widths [1]. + +ABS_MT_ORIENTATION + +The orientation of the ellipse. The value should describe half a revolution +clockwise around the touch center. The scale of the value is arbitrary, but +zero should be returned for an ellipse aligned along the Y axis of the +surface. As an example, an index finger placed straight onto the axis could +return zero orientation, something negative when twisted to the left, and +something positive when twisted to the right. This value can be omitted if +the touching object is circular, or if the information is not available in +the kernel driver. + +ABS_MT_POSITION_X + +The surface X coordinate of the center of the touching ellipse. + +ABS_MT_POSITION_Y + +The surface Y coordinate of the center of the touching ellipse. + +ABS_MT_TOOL_TYPE + +The type of approaching tool. A lot of kernel drivers cannot distinguish +between different tool types, such as a finger or a pen. In such cases, the +event should be omitted. The protocol currently supports MT_TOOL_FINGER and +MT_TOOL_PEN [2]. + +ABS_MT_BLOB_ID + +The BLOB_ID groups several packets together into one arbitrarily shaped +contact. This is a low-level anonymous grouping, and should not be confused +with the high-level contactID, explained below. Most kernel drivers will +not have this capability, and can safely omit the event. + + +Finger Tracking +--------------- + +The kernel driver should generate an arbitrary enumeration of the set of +anonymous contacts currently on the surface. The order in which the packets +appear in the event stream is not important. + +The process of finger tracking, i.e., to assign a unique contactID to each +initiated contact on the surface, is left to user space; preferably the +multi-touch X driver [3]. In that driver, the contactID stays the same and +unique until the contact vanishes (when the finger leaves the surface). The +problem of assigning a set of anonymous fingers to a set of identified +fingers is a euclidian bipartite matching problem at each event update, and +relies on a sufficiently rapid update rate. + +Notes +----- + +In order to stay compatible with existing applications, the data +reported in a finger packet must not be recognized as single-touch +events. In addition, all finger data must bypass input filtering, +since subsequent events of the same type refer to different fingers. + +The first kernel driver to utilize the MT protocol is the bcm5974 driver, +where examples can be found. + +[1] With the extension ABS_MT_APPROACH_X and ABS_MT_APPROACH_Y, the +difference between the contact position and the approaching tool position +could be used to derive tilt. +[2] The list can of course be extended. +[3] The multi-touch X driver is currently in the prototyping stage. At the +time of writing (April 2009), the MT protocol is not yet merged, and the +prototype implements finger matching, basic mouse support and two-finger +scrolling. The project aims at improving the quality of current multi-touch +functionality available in the synaptics X driver, and in addition +implement more advanced gestures. diff --git a/Documentation/isdn/00-INDEX b/Documentation/isdn/00-INDEX index 9fee5f2e5c6..5a2d69989a8 100644 --- a/Documentation/isdn/00-INDEX +++ b/Documentation/isdn/00-INDEX @@ -2,8 +2,14 @@ - this file (info on ISDN implementation for Linux) CREDITS - list of the kind folks that brought you this stuff. +HiSax.cert + - information about the ITU approval certification of the HiSax driver. INTERFACE - - description of Linklevel and Hardwarelevel ISDN interface. + - description of isdn4linux Link Level and Hardware Level interfaces. +INTERFACE.fax + - description of the fax subinterface of isdn4linux. +INTERFACE.CAPI + - description of kernel CAPI Link Level to Hardware Level interface. README - general info on what you need and what to do for Linux ISDN. README.FAQ @@ -12,6 +18,8 @@ README.audio - info for running audio over ISDN. README.fax - info for using Fax over ISDN. +README.gigaset + - info on the drivers for Siemens Gigaset ISDN adapters. README.icn - info on the ICN-ISDN-card and its driver. README.HiSax @@ -37,7 +45,8 @@ README.diversion README.sc - info on driver for Spellcaster cards. README.x25 - _ info for running X.25 over ISDN. + - info for running X.25 over ISDN. README.hysdn - - info on driver for Hypercope active HYSDN cards - + - info on driver for Hypercope active HYSDN cards +README.mISDN + - info on the Modular ISDN subsystem (mISDN). diff --git a/Documentation/isdn/INTERFACE.CAPI b/Documentation/isdn/INTERFACE.CAPI new file mode 100644 index 00000000000..786d619b36e --- /dev/null +++ b/Documentation/isdn/INTERFACE.CAPI @@ -0,0 +1,213 @@ +Kernel CAPI Interface to Hardware Drivers +----------------------------------------- + +1. Overview + +From the CAPI 2.0 specification: +COMMON-ISDN-API (CAPI) is an application programming interface standard used +to access ISDN equipment connected to basic rate interfaces (BRI) and primary +rate interfaces (PRI). + +Kernel CAPI operates as a dispatching layer between CAPI applications and CAPI +hardware drivers. Hardware drivers register ISDN devices (controllers, in CAPI +lingo) with Kernel CAPI to indicate their readiness to provide their service +to CAPI applications. CAPI applications also register with Kernel CAPI, +requesting association with a CAPI device. Kernel CAPI then dispatches the +application registration to an available device, forwarding it to the +corresponding hardware driver. Kernel CAPI then forwards CAPI messages in both +directions between the application and the hardware driver. + +Format and semantics of CAPI messages are specified in the CAPI 2.0 standard. +This standard is freely available from http://www.capi.org. + + +2. Driver and Device Registration + +CAPI drivers optionally register themselves with Kernel CAPI by calling the +Kernel CAPI function register_capi_driver() with a pointer to a struct +capi_driver. This structure must be filled with the name and revision of the +driver, and optionally a pointer to a callback function, add_card(). The +registration can be revoked by calling the function unregister_capi_driver() +with a pointer to the same struct capi_driver. + +CAPI drivers must register each of the ISDN devices they control with Kernel +CAPI by calling the Kernel CAPI function attach_capi_ctr() with a pointer to a +struct capi_ctr before they can be used. This structure must be filled with +the names of the driver and controller, and a number of callback function +pointers which are subsequently used by Kernel CAPI for communicating with the +driver. The registration can be revoked by calling the function +detach_capi_ctr() with a pointer to the same struct capi_ctr. + +Before the device can be actually used, the driver must fill in the device +information fields 'manu', 'version', 'profile' and 'serial' in the capi_ctr +structure of the device, and signal its readiness by calling capi_ctr_ready(). +From then on, Kernel CAPI may call the registered callback functions for the +device. + +If the device becomes unusable for any reason (shutdown, disconnect ...), the +driver has to call capi_ctr_reseted(). This will prevent further calls to the +callback functions by Kernel CAPI. + + +3. Application Registration and Communication + +Kernel CAPI forwards registration requests from applications (calls to CAPI +operation CAPI_REGISTER) to an appropriate hardware driver by calling its +register_appl() callback function. A unique Application ID (ApplID, u16) is +allocated by Kernel CAPI and passed to register_appl() along with the +parameter structure provided by the application. This is analogous to the +open() operation on regular files or character devices. + +After a successful return from register_appl(), CAPI messages from the +application may be passed to the driver for the device via calls to the +send_message() callback function. The CAPI message to send is stored in the +data portion of an skb. Conversely, the driver may call Kernel CAPI's +capi_ctr_handle_message() function to pass a received CAPI message to Kernel +CAPI for forwarding to an application, specifying its ApplID. + +Deregistration requests (CAPI operation CAPI_RELEASE) from applications are +forwarded as calls to the release_appl() callback function, passing the same +ApplID as with register_appl(). After return from release_appl(), no CAPI +messages for that application may be passed to or from the device anymore. + + +4. Data Structures + +4.1 struct capi_driver + +This structure describes a Kernel CAPI driver itself. It is used in the +register_capi_driver() and unregister_capi_driver() functions, and contains +the following non-private fields, all to be set by the driver before calling +register_capi_driver(): + +char name[32] + the name of the driver, as a zero-terminated ASCII string +char revision[32] + the revision number of the driver, as a zero-terminated ASCII string +int (*add_card)(struct capi_driver *driver, capicardparams *data) + a callback function pointer (may be NULL) + + +4.2 struct capi_ctr + +This structure describes an ISDN device (controller) handled by a Kernel CAPI +driver. After registration via the attach_capi_ctr() function it is passed to +all controller specific lower layer interface and callback functions to +identify the controller to operate on. + +It contains the following non-private fields: + +- to be set by the driver before calling attach_capi_ctr(): + +struct module *owner + pointer to the driver module owning the device + +void *driverdata + an opaque pointer to driver specific data, not touched by Kernel CAPI + +char name[32] + the name of the controller, as a zero-terminated ASCII string + +char *driver_name + the name of the driver, as a zero-terminated ASCII string + +int (*load_firmware)(struct capi_ctr *ctrlr, capiloaddata *ldata) + (optional) pointer to a callback function for sending firmware and + configuration data to the device + +void (*reset_ctr)(struct capi_ctr *ctrlr) + pointer to a callback function for performing a reset on the device, + releasing all registered applications + +void (*register_appl)(struct capi_ctr *ctrlr, u16 applid, + capi_register_params *rparam) +void (*release_appl)(struct capi_ctr *ctrlr, u16 applid) + pointers to callback functions for registration and deregistration of + applications with the device + +u16 (*send_message)(struct capi_ctr *ctrlr, struct sk_buff *skb) + pointer to a callback function for sending a CAPI message to the + device + +char *(*procinfo)(struct capi_ctr *ctrlr) + pointer to a callback function returning the entry for the device in + the CAPI controller info table, /proc/capi/controller + +read_proc_t *ctr_read_proc + pointer to the read_proc callback function for the device's proc file + system entry, /proc/capi/controllers/<n>; will be called with a + pointer to the device's capi_ctr structure as the last (data) argument + +- to be filled in before calling capi_ctr_ready(): + +u8 manu[CAPI_MANUFACTURER_LEN] + value to return for CAPI_GET_MANUFACTURER + +capi_version version + value to return for CAPI_GET_VERSION + +capi_profile profile + value to return for CAPI_GET_PROFILE + +u8 serial[CAPI_SERIAL_LEN] + value to return for CAPI_GET_SERIAL + + +5. Lower Layer Interface Functions + +(declared in <linux/isdn/capilli.h>) + +void register_capi_driver(struct capi_driver *drvr) +void unregister_capi_driver(struct capi_driver *drvr) + register/unregister a driver with Kernel CAPI + +int attach_capi_ctr(struct capi_ctr *ctrlr) +int detach_capi_ctr(struct capi_ctr *ctrlr) + register/unregister a device (controller) with Kernel CAPI + +void capi_ctr_ready(struct capi_ctr *ctrlr) +void capi_ctr_reseted(struct capi_ctr *ctrlr) + signal controller ready/not ready + +void capi_ctr_suspend_output(struct capi_ctr *ctrlr) +void capi_ctr_resume_output(struct capi_ctr *ctrlr) + signal suspend/resume + +void capi_ctr_handle_message(struct capi_ctr * ctrlr, u16 applid, + struct sk_buff *skb) + pass a received CAPI message to Kernel CAPI + for forwarding to the specified application + + +6. Helper Functions and Macros + +Library functions (from <linux/isdn/capilli.h>): + +void capilib_new_ncci(struct list_head *head, u16 applid, + u32 ncci, u32 winsize) +void capilib_free_ncci(struct list_head *head, u16 applid, u32 ncci) +void capilib_release_appl(struct list_head *head, u16 applid) +void capilib_release(struct list_head *head) +void capilib_data_b3_conf(struct list_head *head, u16 applid, + u32 ncci, u16 msgid) +u16 capilib_data_b3_req(struct list_head *head, u16 applid, + u32 ncci, u16 msgid) + + +Macros to extract/set element values from/in a CAPI message header +(from <linux/isdn/capiutil.h>): + +Get Macro Set Macro Element (Type) + +CAPIMSG_LEN(m) CAPIMSG_SETLEN(m, len) Total Length (u16) +CAPIMSG_APPID(m) CAPIMSG_SETAPPID(m, applid) ApplID (u16) +CAPIMSG_COMMAND(m) CAPIMSG_SETCOMMAND(m,cmd) Command (u8) +CAPIMSG_SUBCOMMAND(m) CAPIMSG_SETSUBCOMMAND(m, cmd) Subcommand (u8) +CAPIMSG_CMD(m) - Command*256 + + Subcommand (u16) +CAPIMSG_MSGID(m) CAPIMSG_SETMSGID(m, msgid) Message Number (u16) + +CAPIMSG_CONTROL(m) CAPIMSG_SETCONTROL(m, contr) Controller/PLCI/NCCI + (u32) +CAPIMSG_DATALEN(m) CAPIMSG_SETDATALEN(m, len) Data Length (u16) + diff --git a/Documentation/kernel-doc-nano-HOWTO.txt b/Documentation/kernel-doc-nano-HOWTO.txt index 026ec7d5738..4d04572b654 100644 --- a/Documentation/kernel-doc-nano-HOWTO.txt +++ b/Documentation/kernel-doc-nano-HOWTO.txt @@ -269,7 +269,10 @@ Use the argument mechanism to document members or constants. Inside a struct description, you can use the "private:" and "public:" comment tags. Structure fields that are inside a "private:" area -are not listed in the generated output documentation. +are not listed in the generated output documentation. The "private:" +and "public:" tags must begin immediately following a "/*" comment +marker. They may optionally include comments between the ":" and the +ending "*/" marker. Example: @@ -283,7 +286,7 @@ Example: struct my_struct { int a; int b; -/* private: */ +/* private: internal use only */ int c; }; diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 90b3924071b..e87bdbfbcc7 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -17,6 +17,12 @@ are specified on the kernel command line with the module name plus usbcore.blinkenlights=1 +Hyphens (dashes) and underscores are equivalent in parameter names, so + log_buf_len=1M print-fatal-signals=1 +can also be entered as + log-buf-len=1M print_fatal_signals=1 + + This document may not be entirely up to date and comprehensive. The command "modinfo -p ${modulename}" shows a current list of all parameters of a loadable module. Loadable modules, after being loaded into the running kernel, also @@ -345,7 +351,7 @@ and is between 256 and 4096 characters. It is defined in the file not play well with APC CPU idle - disable it if you have APC and your system crashes randomly. - apic= [APIC,i386] Advanced Programmable Interrupt Controller + apic= [APIC,X86-32] Advanced Programmable Interrupt Controller Change the output verbosity whilst booting Format: { quiet (default) | verbose | debug } Change the amount of debugging information output @@ -702,7 +708,7 @@ and is between 256 and 4096 characters. It is defined in the file to discrete, to make X server driver able to add WB entry later. This parameter enables that. - enable_timer_pin_1 [i386,x86-64] + enable_timer_pin_1 [X86] Enable PIN 1 of APIC timer Can be useful to work around chipset bugs (in particular on some ATI chipsets). @@ -775,7 +781,7 @@ and is between 256 and 4096 characters. It is defined in the file hashdist= [KNL,NUMA] Large hashes allocated during boot are distributed across NUMA nodes. Defaults on - for IA-64, off otherwise. + for 64bit NUMA, off otherwise. Format: 0 | 1 (for off | on) hcl= [IA-64] SGI's Hardware Graph compatibility layer diff --git a/Documentation/lockdep-design.txt b/Documentation/lockdep-design.txt index 938ea22f2cc..e20d913d591 100644 --- a/Documentation/lockdep-design.txt +++ b/Documentation/lockdep-design.txt @@ -54,9 +54,9 @@ locking error messages, inside curlies. A contrived example: The bit position indicates STATE, STATE-read, for each of the states listed above, and the character displayed in each indicates: - '.' acquired while irqs disabled - '+' acquired in irq context - '-' acquired with irqs enabled + '.' acquired while irqs disabled and not in irq context + '-' acquired in irq context + '+' acquired with irqs enabled '?' acquired in irq context with irqs enabled. Unused mutexes cannot be part of the cause of an error. diff --git a/Documentation/sysctl/vm.txt b/Documentation/sysctl/vm.txt index 97c4b328432..b716d33912d 100644 --- a/Documentation/sysctl/vm.txt +++ b/Documentation/sysctl/vm.txt @@ -90,6 +90,10 @@ will itself start writeback. If dirty_bytes is written, dirty_ratio becomes a function of its value (dirty_bytes / the amount of dirtyable system memory). +Note: the minimum value allowed for dirty_bytes is two pages (in bytes); any +value lower than this limit will be ignored and the old configuration will be +retained. + ============================================================== dirty_expire_centisecs diff --git a/Documentation/sysfs-rules.txt b/Documentation/sysfs-rules.txt index 6049a2a84dd..5d8bc2cd250 100644 --- a/Documentation/sysfs-rules.txt +++ b/Documentation/sysfs-rules.txt @@ -113,7 +113,7 @@ versions of the sysfs interface. "devices" directory at /sys/subsystem/<name>/devices. If /sys/subsystem exists, /sys/bus, /sys/class and /sys/block can be - ignored. If it does not exist, you have always to scan all three + ignored. If it does not exist, you always have to scan all three places, as the kernel is free to move a subsystem from one place to the other, as long as the devices are still reachable by the same subsystem name. diff --git a/MAINTAINERS b/MAINTAINERS index c547f4a2bb6..2b349ba4add 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3434,11 +3434,10 @@ L: linuxppc-dev@ozlabs.org S: Maintained LINUX FOR POWERPC EMBEDDED MPC5XXX -P: Sylvain Munaut -M: tnt@246tNt.com P: Grant Likely M: grant.likely@secretlab.ca L: linuxppc-dev@ozlabs.org +T: git git://git.secretlab.ca/git/linux-2.6.git S: Maintained LINUX FOR POWERPC EMBEDDED PPC4XX @@ -3456,6 +3455,7 @@ P: Grant Likely M: grant.likely@secretlab.ca W: http://wiki.secretlab.ca/index.php/Linux_on_Xilinx_Virtex L: linuxppc-dev@ozlabs.org +T: git git://git.secretlab.ca/git/linux-2.6.git S: Maintained LINUX FOR POWERPC EMBEDDED PPC8XX @@ -4189,7 +4189,7 @@ P: Joel Becker M: joel.becker@oracle.com L: ocfs2-devel@oss.oracle.com (moderated for non-subscribers) W: http://oss.oracle.com/projects/ocfs2/ -T: git git://git.kernel.org/pub/scm/linux/kernel/git/mfasheh/ocfs2.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/jlbec/ocfs2.git S: Supported F: Documentation/filesystems/ocfs2.txt F: Documentation/filesystems/dlmfs.txt @@ -4521,6 +4521,19 @@ M: jim@jtan.com L: cbe-oss-dev@ozlabs.org S: Maintained +PTRACE SUPPORT +P: Roland McGrath +M: roland@redhat.com +P: Oleg Nesterov +M: oleg@redhat.com +L: linux-kernel@vger.kernel.org +S: Maintained +F: include/asm-generic/syscall.h +F: include/linux/ptrace.h +F: include/linux/regset.h +F: include/linux/tracehook.h +F: kernel/ptrace.c + PVRUSB2 VIDEO4LINUX DRIVER P: Mike Isely M: isely@pobox.com @@ -4666,13 +4679,13 @@ F: kernel/rcutorture.c RDC R-321X SoC P: Florian Fainelli -M: florian.fainelli@telecomint.eu +M: florian@openwrt.org L: linux-kernel@vger.kernel.org S: Maintained RDC R6040 FAST ETHERNET DRIVER P: Florian Fainelli -M: florian.fainelli@telecomint.eu +M: florian@openwrt.org L: netdev@vger.kernel.org S: Maintained F: drivers/net/r6040.c @@ -1,8 +1,8 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 30 -EXTRAVERSION = -rc3 -NAME = Temporary Tasmanian Devil +EXTRAVERSION = -rc5 +NAME = Vindictive Armadillo # *DOCUMENTATION* # To see a list of typical targets execute "make help" @@ -1293,7 +1293,7 @@ help: @echo ' dir/ - Build all files in dir and below' @echo ' dir/file.[ois] - Build specified target only' @echo ' dir/file.ko - Build module including final link' - @echo ' prepare - Set up for building external modules' + @echo ' modules_prepare - Set up for building external modules' @echo ' tags/TAGS - Generate tags file for editors' @echo ' cscope - Generate cscope index' @echo ' kernelrelease - Output the release version string' @@ -1421,7 +1421,9 @@ $(clean-dirs): $(Q)$(MAKE) $(clean)=$(patsubst _clean_%,%,$@) clean: rm-dirs := $(MODVERDIR) -clean: rm-files := $(KBUILD_EXTMOD)/Module.symvers +clean: rm-files := $(KBUILD_EXTMOD)/Module.symvers \ + $(KBUILD_EXTMOD)/Module.markers \ + $(KBUILD_EXTMOD)/modules.order clean: $(clean-dirs) $(call cmd,rmdirs) $(call cmd,rmfiles) diff --git a/arch/alpha/include/asm/barrier.h b/arch/alpha/include/asm/barrier.h index ac78eba909b..ce8860a0b32 100644 --- a/arch/alpha/include/asm/barrier.h +++ b/arch/alpha/include/asm/barrier.h @@ -16,11 +16,13 @@ __asm__ __volatile__("wmb": : :"memory") __asm__ __volatile__("mb": : :"memory") #ifdef CONFIG_SMP +#define __ASM_SMP_MB "\tmb\n" #define smp_mb() mb() #define smp_rmb() rmb() #define smp_wmb() wmb() #define smp_read_barrier_depends() read_barrier_depends() #else +#define __ASM_SMP_MB #define smp_mb() barrier() #define smp_rmb() barrier() #define smp_wmb() barrier() diff --git a/arch/alpha/include/asm/futex.h b/arch/alpha/include/asm/futex.h index 6a332a9f099..945de222ab9 100644 --- a/arch/alpha/include/asm/futex.h +++ b/arch/alpha/include/asm/futex.h @@ -1,6 +1,116 @@ -#ifndef _ASM_FUTEX_H -#define _ASM_FUTEX_H +#ifndef _ASM_ALPHA_FUTEX_H +#define _ASM_ALPHA_FUTEX_H -#include <asm-generic/futex.h> +#ifdef __KERNEL__ -#endif +#include <linux/futex.h> +#include <linux/uaccess.h> +#include <asm/errno.h> +#include <asm/barrier.h> + +#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \ + __asm__ __volatile__( \ + __ASM_SMP_MB \ + "1: ldl_l %0,0(%2)\n" \ + insn \ + "2: stl_c %1,0(%2)\n" \ + " beq %1,4f\n" \ + " mov $31,%1\n" \ + "3: .subsection 2\n" \ + "4: br 1b\n" \ + " .previous\n" \ + " .section __ex_table,\"a\"\n" \ + " .long 1b-.\n" \ + " lda $31,3b-1b(%1)\n" \ + " .long 2b-.\n" \ + " lda $31,3b-2b(%1)\n" \ + " .previous\n" \ + : "=&r" (oldval), "=&r"(ret) \ + : "r" (uaddr), "r"(oparg) \ + : "memory") + +static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr) +{ + int op = (encoded_op >> 28) & 7; + int cmp = (encoded_op >> 24) & 15; + int oparg = (encoded_op << 8) >> 20; + int cmparg = (encoded_op << 20) >> 20; + int oldval = 0, ret; + if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) + oparg = 1 << oparg; + + if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) + return -EFAULT; + + pagefault_disable(); + + switch (op) { + case FUTEX_OP_SET: + __futex_atomic_op("mov %3,%1\n", ret, oldval, uaddr, oparg); + break; + case FUTEX_OP_ADD: + __futex_atomic_op("addl %0,%3,%1\n", ret, oldval, uaddr, oparg); + break; + case FUTEX_OP_OR: + __futex_atomic_op("or %0,%3,%1\n", ret, oldval, uaddr, oparg); + break; + case FUTEX_OP_ANDN: + __futex_atomic_op("andnot %0,%3,%1\n", ret, oldval, uaddr, oparg); + break; + case FUTEX_OP_XOR: + __futex_atomic_op("xor %0,%3,%1\n", ret, oldval, uaddr, oparg); + break; + default: + ret = -ENOSYS; + } + + pagefault_enable(); + + if (!ret) { + switch (cmp) { + case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break; + case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break; + case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break; + case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break; + case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break; + case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break; + default: ret = -ENOSYS; + } + } + return ret; +} + +static inline int +futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval) +{ + int prev, cmp; + + if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) + return -EFAULT; + + __asm__ __volatile__ ( + __ASM_SMP_MB + "1: ldl_l %0,0(%2)\n" + " cmpeq %0,%3,%1\n" + " beq %1,3f\n" + " mov %4,%1\n" + "2: stl_c %1,0(%2)\n" + " beq %1,4f\n" + "3: .subsection 2\n" + "4: br 1b\n" + " .previous\n" + " .section __ex_table,\"a\"\n" + " .long 1b-.\n" + " lda $31,3b-1b(%0)\n" + " .long 2b-.\n" + " lda $31,3b-2b(%0)\n" + " .previous\n" + : "=&r"(prev), "=&r"(cmp) + : "r"(uaddr), "r"((long)oldval), "r"(newval) + : "memory"); + + return prev; +} + +#endif /* __KERNEL__ */ +#endif /* _ASM_ALPHA_FUTEX_H */ diff --git a/arch/alpha/include/asm/percpu.h b/arch/alpha/include/asm/percpu.h index e9e0bb5a23b..06c5c7a4afd 100644 --- a/arch/alpha/include/asm/percpu.h +++ b/arch/alpha/include/asm/percpu.h @@ -1,7 +1,9 @@ #ifndef __ALPHA_PERCPU_H #define __ALPHA_PERCPU_H + #include <linux/compiler.h> #include <linux/threads.h> +#include <linux/percpu-defs.h> /* * Determine the real variable name from the name visible in the @@ -73,6 +75,28 @@ extern unsigned long __per_cpu_offset[NR_CPUS]; #endif /* SMP */ -#include <asm-generic/percpu.h> +#ifdef CONFIG_SMP +#define PER_CPU_BASE_SECTION ".data.percpu" +#else +#define PER_CPU_BASE_SECTION ".data" +#endif + +#ifdef CONFIG_SMP + +#ifdef MODULE +#define PER_CPU_SHARED_ALIGNED_SECTION "" +#else +#define PER_CPU_SHARED_ALIGNED_SECTION ".shared_aligned" +#endif +#define PER_CPU_FIRST_SECTION ".first" + +#else + +#define PER_CPU_SHARED_ALIGNED_SECTION "" +#define PER_CPU_FIRST_SECTION "" + +#endif + +#define PER_CPU_ATTRIBUTES #endif /* __ALPHA_PERCPU_H */ diff --git a/arch/alpha/include/asm/uaccess.h b/arch/alpha/include/asm/uaccess.h index 163f3053001..b49ec2f8d6e 100644 --- a/arch/alpha/include/asm/uaccess.h +++ b/arch/alpha/include/asm/uaccess.h @@ -507,5 +507,7 @@ struct exception_table_entry (pc) + (_fixup)->fixup.bits.nextinsn; \ }) +#define ARCH_HAS_SORT_EXTABLE +#define ARCH_HAS_SEARCH_EXTABLE #endif /* __ALPHA_UACCESS_H */ diff --git a/arch/alpha/kernel/Makefile b/arch/alpha/kernel/Makefile index a427538252f..7739a62440a 100644 --- a/arch/alpha/kernel/Makefile +++ b/arch/alpha/kernel/Makefile @@ -8,7 +8,7 @@ EXTRA_CFLAGS := -Werror -Wno-sign-compare obj-y := entry.o traps.o process.o init_task.o osf_sys.o irq.o \ irq_alpha.o signal.o setup.o ptrace.o time.o \ - alpha_ksyms.o systbls.o err_common.o io.o binfmt_loader.o + alpha_ksyms.o systbls.o err_common.o io.o obj-$(CONFIG_VGA_HOSE) += console.o obj-$(CONFIG_SMP) += smp.o @@ -43,6 +43,10 @@ else # Misc support obj-$(CONFIG_ALPHA_SRM) += srmcons.o +ifdef CONFIG_BINFMT_AOUT +obj-y += binfmt_loader.o +endif + # Core logic support obj-$(CONFIG_ALPHA_APECS) += core_apecs.o obj-$(CONFIG_ALPHA_CIA) += core_cia.o diff --git a/arch/alpha/kernel/binfmt_loader.c b/arch/alpha/kernel/binfmt_loader.c index 4a0af906b00..3fcfad41013 100644 --- a/arch/alpha/kernel/binfmt_loader.c +++ b/arch/alpha/kernel/binfmt_loader.c @@ -46,6 +46,6 @@ static struct linux_binfmt loader_format = { static int __init init_loader_binfmt(void) { - return register_binfmt(&loader_format); + return insert_binfmt(&loader_format); } arch_initcall(init_loader_binfmt); diff --git a/arch/alpha/kernel/err_ev6.c b/arch/alpha/kernel/err_ev6.c index 985e5c1681a..8ca6345bf13 100644 --- a/arch/alpha/kernel/err_ev6.c +++ b/arch/alpha/kernel/err_ev6.c @@ -229,7 +229,7 @@ ev6_process_logout_frame(struct el_common *mchk_header, int print) } void -ev6_machine_check(u64 vector, u64 la_ptr) +ev6_machine_check(unsigned long vector, unsigned long la_ptr) { struct el_common *mchk_header = (struct el_common *)la_ptr; diff --git a/arch/alpha/kernel/err_ev7.c b/arch/alpha/kernel/err_ev7.c index 73770c6ca01..d738a67112d 100644 --- a/arch/alpha/kernel/err_ev7.c +++ b/arch/alpha/kernel/err_ev7.c @@ -117,7 +117,7 @@ ev7_collect_logout_frame_subpackets(struct el_subpacket *el_ptr, } void -ev7_machine_check(u64 vector, u64 la_ptr) +ev7_machine_check(unsigned long vector, unsigned long la_ptr) { struct el_subpacket *el_ptr = (struct el_subpacket *)la_ptr; char *saved_err_prefix = err_print_prefix; @@ -246,7 +246,7 @@ ev7_process_pal_subpacket(struct el_subpacket *header) switch(header->type) { case EL_TYPE__PAL__LOGOUT_FRAME: - printk("%s*** MCHK occurred on LPID %ld (RBOX %llx)\n", + printk("%s*** MCHK occurred on LPID %lld (RBOX %llx)\n", err_print_prefix, packet->by_type.logout.whami, packet->by_type.logout.rbox_whami); diff --git a/arch/alpha/kernel/err_impl.h b/arch/alpha/kernel/err_impl.h index 3c12258158e..0c010ca4611 100644 --- a/arch/alpha/kernel/err_impl.h +++ b/arch/alpha/kernel/err_impl.h @@ -60,26 +60,26 @@ extern struct ev7_lf_subpackets * ev7_collect_logout_frame_subpackets(struct el_subpacket *, struct ev7_lf_subpackets *); extern void ev7_register_error_handlers(void); -extern void ev7_machine_check(u64, u64); +extern void ev7_machine_check(unsigned long, unsigned long); /* * err_ev6.c */ extern void ev6_register_error_handlers(void); extern int ev6_process_logout_frame(struct el_common *, int); -extern void ev6_machine_check(u64, u64); +extern void ev6_machine_check(unsigned long, unsigned long); /* * err_marvel.c */ -extern void marvel_machine_check(u64, u64); +extern void marvel_machine_check(unsigned long, unsigned long); extern void marvel_register_error_handlers(void); /* * err_titan.c */ extern int titan_process_logout_frame(struct el_common *, int); -extern void titan_machine_check(u64, u64); +extern void titan_machine_check(unsigned long, unsigned long); extern void titan_register_error_handlers(void); extern int privateer_process_logout_frame(struct el_common *, int); -extern void privateer_machine_check(u64, u64); +extern void privateer_machine_check(unsigned long, unsigned long); diff --git a/arch/alpha/kernel/err_marvel.c b/arch/alpha/kernel/err_marvel.c index 6bfd243efba..52a79dfc13c 100644 --- a/arch/alpha/kernel/err_marvel.c +++ b/arch/alpha/kernel/err_marvel.c @@ -1042,7 +1042,7 @@ marvel_process_logout_frame(struct ev7_lf_subpackets *lf_subpackets, int print) } void -marvel_machine_check(u64 vector, u64 la_ptr) +marvel_machine_check(unsigned long vector, unsigned long la_ptr) { struct el_subpacket *el_ptr = (struct el_subpacket *)la_ptr; int (*process_frame)(struct ev7_lf_subpackets *, int) = NULL; diff --git a/arch/alpha/kernel/err_titan.c b/arch/alpha/kernel/err_titan.c index c7e28a88d6e..f7ed97ce0df 100644 --- a/arch/alpha/kernel/err_titan.c +++ b/arch/alpha/kernel/err_titan.c @@ -380,7 +380,7 @@ titan_process_logout_frame(struct el_common *mchk_header, int print) } void -titan_machine_check(u64 vector, u64 la_ptr) +titan_machine_check(unsigned long vector, unsigned long la_ptr) { struct el_common *mchk_header = (struct el_common *)la_ptr; struct el_TITAN_sysdata_mcheck *tmchk = @@ -702,7 +702,7 @@ privateer_process_logout_frame(struct el_common *mchk_header, int print) } void -privateer_machine_check(u64 vector, u64 la_ptr) +privateer_machine_check(unsigned long vector, unsigned long la_ptr) { struct el_common *mchk_header = (struct el_common *)la_ptr; struct el_TITAN_sysdata_mcheck *tmchk = diff --git a/arch/alpha/kernel/proto.h b/arch/alpha/kernel/proto.h index 567f2598d09..3d2627ec986 100644 --- a/arch/alpha/kernel/proto.h +++ b/arch/alpha/kernel/proto.h @@ -36,7 +36,6 @@ extern void cia_pci_tbi(struct pci_controller *, dma_addr_t, dma_addr_t); extern struct pci_ops irongate_pci_ops; extern int irongate_pci_clr_err(void); extern void irongate_init_arch(void); -extern void irongate_machine_check(u64, u64); #define irongate_pci_tbi ((void *)0) /* core_lca.c */ @@ -49,7 +48,7 @@ extern void lca_pci_tbi(struct pci_controller *, dma_addr_t, dma_addr_t); extern struct pci_ops marvel_pci_ops; extern void marvel_init_arch(void); extern void marvel_kill_arch(int); -extern void marvel_machine_check(u64, u64); +extern void marvel_machine_check(unsigned long, unsigned long); extern void marvel_pci_tbi(struct pci_controller *, dma_addr_t, dma_addr_t); extern int marvel_pa_to_nid(unsigned long); extern int marvel_cpuid_to_nid(int); @@ -86,7 +85,7 @@ extern void t2_pci_tbi(struct pci_controller *, dma_addr_t, dma_addr_t); extern struct pci_ops titan_pci_ops; extern void titan_init_arch(void); extern void titan_kill_arch(int); -extern void titan_machine_check(u64, u64); +extern void titan_machine_check(unsigned long, unsigned long); extern void titan_pci_tbi(struct pci_controller *, dma_addr_t, dma_addr_t); extern struct _alpha_agp_info *titan_agp_info(void); diff --git a/arch/alpha/mm/extable.c b/arch/alpha/mm/extable.c index dc7aeda1577..62dc379d301 100644 --- a/arch/alpha/mm/extable.c +++ b/arch/alpha/mm/extable.c @@ -3,11 +3,49 @@ */ #include <linux/module.h> +#include <linux/sort.h> #include <asm/uaccess.h> +static inline unsigned long ex_to_addr(const struct exception_table_entry *x) +{ + return (unsigned long)&x->insn + x->insn; +} + +static void swap_ex(void *a, void *b, int size) +{ + struct exception_table_entry *ex_a = a, *ex_b = b; + unsigned long addr_a = ex_to_addr(ex_a), addr_b = ex_to_addr(ex_b); + unsigned int t = ex_a->fixup.unit; + + ex_a->fixup.unit = ex_b->fixup.unit; + ex_b->fixup.unit = t; + ex_a->insn = (int)(addr_b - (unsigned long)&ex_a->insn); + ex_b->insn = (int)(addr_a - (unsigned long)&ex_b->insn); +} + +/* + * The exception table needs to be sorted so that the binary + * search that we use to find entries in it works properly. + * This is used both for the kernel exception table and for + * the exception tables of modules that get loaded. + */ +static int cmp_ex(const void *a, const void *b) +{ + const struct exception_table_entry *x = a, *y = b; + + /* avoid overflow */ + if (ex_to_addr(x) > ex_to_addr(y)) + return 1; + if (ex_to_addr(x) < ex_to_addr(y)) + return -1; + return 0; +} + void sort_extable(struct exception_table_entry *start, struct exception_table_entry *finish) { + sort(start, finish - start, sizeof(struct exception_table_entry), + cmp_ex, swap_ex); } const struct exception_table_entry * @@ -20,7 +58,7 @@ search_extable(const struct exception_table_entry *first, unsigned long mid_value; mid = (last - first) / 2 + first; - mid_value = (unsigned long)&mid->insn + mid->insn; + mid_value = ex_to_addr(mid); if (mid_value == value) return mid; else if (mid_value < value) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index e02b893fb90..e60ec54df33 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -454,6 +454,7 @@ config ARCH_MXC select ARCH_MTD_XIP select GENERIC_GPIO select ARCH_REQUIRE_GPIOLIB + select HAVE_CLK help Support for Freescale MXC/iMX-based family of processors @@ -486,8 +487,6 @@ config ARCH_PXA select HAVE_CLK select COMMON_CLKDEV select ARCH_REQUIRE_GPIOLIB - select HAVE_CLK - select COMMON_CLKDEV select GENERIC_TIME select GENERIC_CLOCKEVENTS select TICK_ONESHOT @@ -585,6 +584,8 @@ config ARCH_DAVINCI select ARCH_REQUIRE_GPIOLIB select HAVE_CLK select ZONE_DMA + select HAVE_IDE + select COMMON_CLKDEV help Support for TI's DaVinci platform. @@ -740,6 +741,56 @@ if !MMU source "arch/arm/Kconfig-nommu" endif +config ARM_ERRATA_411920 + bool "ARM errata: Invalidation of the Instruction Cache operation can fail" + depends on CPU_V6 && !SMP + help + Invalidation of the Instruction Cache operation can + fail. This erratum is present in 1136 (before r1p4), 1156 and 1176. + It does not affect the MPCore. This option enables the ARM Ltd. + recommended workaround. + +config ARM_ERRATA_430973 + bool "ARM errata: Stale prediction on replaced interworking branch" + depends on CPU_V7 + help + This option enables the workaround for the 430973 Cortex-A8 + (r1p0..r1p2) erratum. If a code sequence containing an ARM/Thumb + interworking branch is replaced with another code sequence at the + same virtual address, whether due to self-modifying code or virtual + to physical address re-mapping, Cortex-A8 does not recover from the + stale interworking branch prediction. This results in Cortex-A8 + executing the new code sequence in the incorrect ARM or Thumb state. + The workaround enables the BTB/BTAC operations by setting ACTLR.IBE + and also flushes the branch target cache at every context switch. + Note that setting specific bits in the ACTLR register may not be + available in non-secure mode. + +config ARM_ERRATA_458693 + bool "ARM errata: Processor deadlock when a false hazard is created" + depends on CPU_V7 + help + This option enables the workaround for the 458693 Cortex-A8 (r2p0) + erratum. For very specific sequences of memory operations, it is + possible for a hazard condition intended for a cache line to instead + be incorrectly associated with a different cache line. This false + hazard might then cause a processor deadlock. The workaround enables + the L1 caching of the NEON accesses and disables the PLD instruction + in the ACTLR register. Note that setting specific bits in the ACTLR + register may not be available in non-secure mode. + +config ARM_ERRATA_460075 + bool "ARM errata: Data written to the L2 cache can be overwritten with stale data" + depends on CPU_V7 + help + This option enables the workaround for the 460075 Cortex-A8 (r2p0) + erratum. Any asynchronous access to the L2 cache may encounter a + situation in which recent store transactions to the L2 cache are lost + and overwritten with stale memory contents from external memory. The + workaround disables the write-allocate mode for the L2 cache via the + ACTLR register. Note that setting specific bits in the ACTLR register + may not be available in non-secure mode. + endmenu source "arch/arm/common/Kconfig" @@ -1171,12 +1222,6 @@ config CPU_FREQ_IMX If in doubt, say N. -config CPU_FREQ_PXA - bool - depends on CPU_FREQ && ARCH_PXA && PXA25x - default y - select CPU_FREQ_DEFAULT_GOV_USERSPACE - endif source "drivers/cpuidle/Kconfig" diff --git a/arch/arm/configs/davinci_all_defconfig b/arch/arm/configs/davinci_all_defconfig new file mode 100644 index 00000000000..eb2738b5be5 --- /dev/null +++ b/arch/arm/configs/davinci_all_defconfig @@ -0,0 +1,1784 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.30-rc2 +# Wed Apr 15 08:16:53 2009 +# +CONFIG_ARM=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_GENERIC_GPIO=y +CONFIG_GENERIC_TIME=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_MMU=y +# CONFIG_NO_IOPORT is not set +CONFIG_GENERIC_HARDIRQS=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_ARCH_HAS_ILOG2_U32 is not set +# CONFIG_ARCH_HAS_ILOG2_U64 is not set +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_ZONE_DMA=y +CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y +CONFIG_VECTORS_BASE=0xffff0000 +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +# CONFIG_SWAP is not set +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +CONFIG_POSIX_MQUEUE=y +CONFIG_POSIX_MQUEUE_SYSCTL=y +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_TASKSTATS is not set +# CONFIG_AUDIT is not set + +# +# RCU Subsystem +# +CONFIG_CLASSIC_RCU=y +# CONFIG_TREE_RCU is not set +# CONFIG_PREEMPT_RCU is not set +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_PREEMPT_RCU_TRACE is not set +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=14 +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_CGROUPS is not set +CONFIG_SYSFS_DEPRECATED=y +CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_RELAY is not set +# CONFIG_NAMESPACES is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_RD_GZIP=y +# CONFIG_RD_BZIP2 is not set +# CONFIG_RD_LZMA is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +CONFIG_EMBEDDED=y +CONFIG_UID16=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +# CONFIG_KALLSYMS_EXTRA_PASS is not set +# CONFIG_STRIP_ASM_SYMS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_SLUB_DEBUG=y +CONFIG_COMPAT_BRK=y +# CONFIG_SLAB is not set +CONFIG_SLUB=y +# CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +# CONFIG_MARKERS is not set +CONFIG_HAVE_OPROFILE=y +# CONFIG_KPROBES is not set +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_CLK=y +# CONFIG_SLOW_WORK is not set +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +CONFIG_MODVERSIONS=y +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_BLOCK=y +# CONFIG_LBD is not set +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_INTEGRITY is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +# CONFIG_IOSCHED_DEADLINE is not set +# CONFIG_IOSCHED_CFQ is not set +CONFIG_DEFAULT_AS=y +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="anticipatory" +# CONFIG_FREEZER is not set + +# +# System Type +# +# CONFIG_ARCH_AAEC2000 is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_AT91 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_GEMINI is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_IOP13XX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_KIRKWOOD is not set +# CONFIG_ARCH_KS8695 is not set +# CONFIG_ARCH_NS9XXX is not set +# CONFIG_ARCH_LOKI is not set +# CONFIG_ARCH_MV78XX0 is not set +# CONFIG_ARCH_MXC is not set +# CONFIG_ARCH_ORION5X is not set +# CONFIG_ARCH_PNX4008 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_MMP is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_S3C64XX is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +CONFIG_ARCH_DAVINCI=y +# CONFIG_ARCH_OMAP is not set +# CONFIG_ARCH_MSM is not set +# CONFIG_ARCH_W90X900 is not set + +# +# TI DaVinci Implementations +# + +# +# DaVinci Core Type +# +CONFIG_ARCH_DAVINCI_DM644x=y + +# +# DaVinci Board Type +# +CONFIG_MACH_DAVINCI_EVM=y +CONFIG_DAVINCI_MUX=y +CONFIG_DAVINCI_MUX_DEBUG=y +CONFIG_DAVINCI_MUX_WARNINGS=y +CONFIG_DAVINCI_RESET_CLOCKS=y + +# +# Processor Type +# +CONFIG_CPU_32=y +CONFIG_CPU_ARM926T=y +CONFIG_CPU_32v5=y +CONFIG_CPU_ABRT_EV5TJ=y +CONFIG_CPU_PABRT_NOIFAR=y +CONFIG_CPU_CACHE_VIVT=y +CONFIG_CPU_COPY_V4WB=y +CONFIG_CPU_TLB_V4WBI=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y + +# +# Processor Features +# +CONFIG_ARM_THUMB=y +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_WRITETHROUGH is not set +# CONFIG_CPU_CACHE_ROUND_ROBIN is not set +# CONFIG_OUTER_CACHE is not set +CONFIG_COMMON_CLKDEV=y + +# +# Bus support +# +# CONFIG_PCI_SYSCALL is not set +# CONFIG_ARCH_SUPPORTS_MSI is not set +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_VMSPLIT_3G=y +# CONFIG_VMSPLIT_2G is not set +# CONFIG_VMSPLIT_1G is not set +CONFIG_PAGE_OFFSET=0xC0000000 +CONFIG_PREEMPT=y +CONFIG_HZ=100 +CONFIG_AEABI=y +# CONFIG_OABI_COMPAT is not set +CONFIG_ARCH_FLATMEM_HAS_HOLES=y +# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set +# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set +# CONFIG_HIGHMEM is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4096 +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=1 +CONFIG_BOUNCE=y +CONFIG_VIRT_TO_BUS=y +CONFIG_UNEVICTABLE_LRU=y +CONFIG_HAVE_MLOCK=y +CONFIG_HAVE_MLOCKED_PAGE_BIT=y +CONFIG_LEDS=y +# CONFIG_LEDS_CPU is not set +CONFIG_ALIGNMENT_TRAP=y + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="" +# CONFIG_XIP_KERNEL is not set +# CONFIG_KEXEC is not set + +# +# CPU Power Management +# +# CONFIG_CPU_IDLE is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +# CONFIG_VFP is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_HAVE_AOUT=y +# CONFIG_BINFMT_AOUT is not set +# CONFIG_BINFMT_MISC is not set + +# +# Power management options +# +# CONFIG_PM is not set +CONFIG_ARCH_SUSPEND_POSSIBLE=y +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=m +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=m +# CONFIG_IPV6_PRIVACY is not set +# CONFIG_IPV6_ROUTER_PREF is not set +# CONFIG_IPV6_OPTIMISTIC_DAD is not set +# CONFIG_INET6_AH is not set +# CONFIG_INET6_ESP is not set +# CONFIG_INET6_IPCOMP is not set +# CONFIG_IPV6_MIP6 is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +CONFIG_INET6_XFRM_MODE_TRANSPORT=m +CONFIG_INET6_XFRM_MODE_TUNNEL=m +CONFIG_INET6_XFRM_MODE_BEET=m +# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set +CONFIG_IPV6_SIT=m +CONFIG_IPV6_NDISC_NODETYPE=y +# CONFIG_IPV6_TUNNEL is not set +# CONFIG_IPV6_MULTIPLE_TABLES is not set +# CONFIG_IPV6_MROUTE is not set +# CONFIG_NETWORK_SECMARK is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +CONFIG_NETFILTER_ADVANCED=y + +# +# Core Netfilter Configuration +# +# CONFIG_NETFILTER_NETLINK_QUEUE is not set +# CONFIG_NETFILTER_NETLINK_LOG is not set +# CONFIG_NF_CONNTRACK is not set +# CONFIG_NETFILTER_XTABLES is not set +# CONFIG_IP_VS is not set + +# +# IP: Netfilter Configuration +# +# CONFIG_NF_DEFRAG_IPV4 is not set +# CONFIG_IP_NF_QUEUE is not set +# CONFIG_IP_NF_IPTABLES is not set +# CONFIG_IP_NF_ARPTABLES is not set + +# +# IPv6: Netfilter Configuration +# +# CONFIG_IP6_NF_QUEUE is not set +# CONFIG_IP6_NF_IPTABLES 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_NET_DSA 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_PHONET is not set +# CONFIG_NET_SCHED is not set +# CONFIG_DCB 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 +# CONFIG_WIRELESS is not set +# CONFIG_WIMAX 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 is not set +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_CONNECTOR is not set +CONFIG_MTD=m +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_TESTS is not set +# CONFIG_MTD_REDBOOT_PARTS is not set +# CONFIG_MTD_AFS_PARTS is not set +# CONFIG_MTD_AR7_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=m +CONFIG_MTD_BLKDEVS=m +CONFIG_MTD_BLOCK=m +# CONFIG_MTD_BLOCK_RO is not set +# 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=m +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=m +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_CFI_INTELEXT is not set +CONFIG_MTD_CFI_AMDSTD=m +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=m +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +CONFIG_MTD_PHYSMAP=m +# CONFIG_MTD_PHYSMAP_COMPAT is not set +# CONFIG_MTD_ARM_INTEGRATOR is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set +CONFIG_MTD_NAND=m +# CONFIG_MTD_NAND_VERIFY_WRITE is not set +# CONFIG_MTD_NAND_ECC_SMC is not set +# CONFIG_MTD_NAND_MUSEUM_IDS is not set +# CONFIG_MTD_NAND_GPIO is not set +CONFIG_MTD_NAND_IDS=m +# CONFIG_MTD_NAND_DISKONCHIP is not set +# CONFIG_MTD_NAND_NANDSIM is not set +# CONFIG_MTD_NAND_PLATFORM is not set +# CONFIG_MTD_ALAUDA is not set +CONFIG_MTD_NAND_DAVINCI=m +# CONFIG_MTD_ONENAND is not set + +# +# LPDDR flash memory drivers +# +# CONFIG_MTD_LPDDR is not set + +# +# UBI - Unsorted block images +# +# CONFIG_MTD_UBI is not set +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=m +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_UB is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=1 +CONFIG_BLK_DEV_RAM_SIZE=32768 +# CONFIG_BLK_DEV_XIP is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +CONFIG_MISC_DEVICES=y +# CONFIG_ICS932S401 is not set +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_ISL29003 is not set +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +CONFIG_EEPROM_AT24=y +# CONFIG_EEPROM_LEGACY is not set +# CONFIG_EEPROM_93CX6 is not set +CONFIG_HAVE_IDE=y +CONFIG_IDE=m + +# +# Please see Documentation/ide/ide.txt for help/info on IDE drives +# +CONFIG_IDE_XFER_MODE=y +CONFIG_IDE_TIMINGS=y +# CONFIG_BLK_DEV_IDE_SATA is not set +CONFIG_IDE_GD=m +CONFIG_IDE_GD_ATA=y +# CONFIG_IDE_GD_ATAPI is not set +# CONFIG_BLK_DEV_IDECD is not set +# CONFIG_BLK_DEV_IDETAPE is not set +# CONFIG_IDE_TASK_IOCTL is not set +CONFIG_IDE_PROC_FS=y + +# +# IDE chipset support/bugfixes +# +# CONFIG_BLK_DEV_PLATFORM is not set +CONFIG_BLK_DEV_IDEDMA_SFF=y +CONFIG_BLK_DEV_PALMCHIP_BK3710=m +CONFIG_BLK_DEV_IDEDMA=y + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=m +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=m +# 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_LIBFC is not set +# CONFIG_LIBFCOE is not set +# CONFIG_SCSI_DEBUG is not set +# CONFIG_SCSI_DH is not set +# CONFIG_SCSI_OSD_INITIATOR is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set +CONFIG_NETDEVICES=y +CONFIG_COMPAT_NET_DEV_OPS=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_MACVLAN is not set +# CONFIG_EQUALIZER is not set +CONFIG_TUN=m +# CONFIG_VETH is not set +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +# CONFIG_MARVELL_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +CONFIG_LXT_PHY=y +# CONFIG_CICADA_PHY is not set +# CONFIG_VITESSE_PHY is not set +# CONFIG_SMSC_PHY is not set +# CONFIG_BROADCOM_PHY is not set +# CONFIG_ICPLUS_PHY is not set +# CONFIG_REALTEK_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_STE10XP is not set +CONFIG_LSI_ET1011C_PHY=y +# CONFIG_FIXED_PHY is not set +# CONFIG_MDIO_BITBANG is not set +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_AX88796 is not set +# CONFIG_SMC91X is not set +# CONFIG_DM9000 is not set +# CONFIG_ETHOC is not set +# CONFIG_SMC911X is not set +# CONFIG_SMSC911X is not set +# CONFIG_DNET 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_IBM_NEW_EMAC_NO_FLOW_CTRL is not set +# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set +# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR 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 + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# + +# +# 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_PPP=m +# CONFIG_PPP_MULTILINK is not set +# CONFIG_PPP_FILTER is not set +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_PPP_DEFLATE=m +# CONFIG_PPP_BSDCOMP is not set +# CONFIG_PPP_MPPE is not set +# CONFIG_PPPOE is not set +# CONFIG_PPPOL2TP is not set +# CONFIG_SLIP is not set +CONFIG_SLHC=m +CONFIG_NETCONSOLE=y +# CONFIG_NETCONSOLE_DYNAMIC is not set +CONFIG_NETPOLL=y +CONFIG_NETPOLL_TRAP=y +CONFIG_NET_POLL_CONTROLLER=y +# CONFIG_ISDN 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=m +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=m + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +CONFIG_KEYBOARD_ATKBD=m +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_LKKBD is not set +CONFIG_KEYBOARD_XTKBD=m +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_STOWAWAY is not set +CONFIG_KEYBOARD_GPIO=y +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +CONFIG_INPUT_TOUCHSCREEN=y +# CONFIG_TOUCHSCREEN_AD7879_I2C is not set +# CONFIG_TOUCHSCREEN_AD7879 is not set +# CONFIG_TOUCHSCREEN_FUJITSU is not set +# CONFIG_TOUCHSCREEN_GUNZE is not set +# CONFIG_TOUCHSCREEN_ELO is not set +# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set +# CONFIG_TOUCHSCREEN_MTOUCH is not set +# CONFIG_TOUCHSCREEN_INEXIO is not set +# CONFIG_TOUCHSCREEN_MK712 is not set +# CONFIG_TOUCHSCREEN_PENMOUNT is not set +# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set +# CONFIG_TOUCHSCREEN_TOUCHWIN is not set +# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set +# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set +# CONFIG_TOUCHSCREEN_TSC2007 is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +CONFIG_SERIO=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_CONSOLE_TRANSLATIONS=y +# CONFIG_VT_CONSOLE is not set +CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +CONFIG_DEVKMEM=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=3 +CONFIG_SERIAL_8250_RUNTIME_UARTS=3 +# 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_DEVPTS_MULTIPLE_INSTANCES is not set +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 +# CONFIG_IPMI_HANDLER is not set +CONFIG_HW_RANDOM=m +# CONFIG_HW_RANDOM_TIMERIOMEM is not set +# CONFIG_R3964 is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_HELPER_AUTO=y + +# +# I2C Hardware Bus support +# + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +CONFIG_I2C_DAVINCI=y +# CONFIG_I2C_GPIO is not set +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_SIMTEC is not set + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_TAOS_EVM is not set +# CONFIG_I2C_TINY_USB is not set + +# +# Other I2C/SMBus bus drivers +# +# CONFIG_I2C_PCA_PLATFORM is not set +# CONFIG_I2C_STUB is not set + +# +# Miscellaneous I2C Chip support +# +# CONFIG_DS1682 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set +# CONFIG_SPI is not set +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_GPIOLIB=y +# CONFIG_DEBUG_GPIO is not set +# CONFIG_GPIO_SYSFS is not set + +# +# Memory mapped GPIO expanders: +# + +# +# I2C GPIO expanders: +# +# CONFIG_GPIO_MAX732X is not set +# CONFIG_GPIO_PCA953X is not set +CONFIG_GPIO_PCF857X=m + +# +# PCI GPIO expanders: +# + +# +# SPI GPIO expanders: +# +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_SENSORS_AD7414 is not set +# CONFIG_SENSORS_AD7418 is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1029 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ADT7462 is not set +# CONFIG_SENSORS_ADT7470 is not set +# CONFIG_SENSORS_ADT7473 is not set +# CONFIG_SENSORS_ADT7475 is not set +# CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_DS1621 is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_F71882FG is not set +# CONFIG_SENSORS_F75375S is not set +# CONFIG_SENSORS_G760A is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_LM63 is not set +# CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM77 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set +# CONFIG_SENSORS_LM83 is not set +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set +# CONFIG_SENSORS_LM93 is not set +# CONFIG_SENSORS_LTC4215 is not set +# CONFIG_SENSORS_LTC4245 is not set +# CONFIG_SENSORS_LM95241 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_MAX6650 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_PC87427 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_SHT15 is not set +# CONFIG_SENSORS_DME1737 is not set +# 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_VT1211 is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83791D is not set +# 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_THERMAL_HWMON is not set +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set +CONFIG_DAVINCI_WATCHDOG=m + +# +# USB-based Watchdog Cards +# +# CONFIG_USBPCWATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_ASIC3 is not set +# CONFIG_HTC_EGPIO is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_TPS65010 is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_T7L66XB is not set +# CONFIG_MFD_TC6387XB is not set +# CONFIG_MFD_TC6393XB is not set +# CONFIG_PMIC_DA903X is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_PCF50633 is not set + +# +# Multimedia devices +# + +# +# Multimedia core support +# +CONFIG_VIDEO_DEV=y +CONFIG_VIDEO_V4L2_COMMON=y +CONFIG_VIDEO_ALLOW_V4L1=y +CONFIG_VIDEO_V4L1_COMPAT=y +# CONFIG_DVB_CORE is not set +CONFIG_VIDEO_MEDIA=y + +# +# Multimedia drivers +# +# CONFIG_MEDIA_ATTACH is not set +CONFIG_MEDIA_TUNER=y +# CONFIG_MEDIA_TUNER_CUSTOMISE is not set +CONFIG_MEDIA_TUNER_SIMPLE=y +CONFIG_MEDIA_TUNER_TDA8290=y +CONFIG_MEDIA_TUNER_TDA9887=y +CONFIG_MEDIA_TUNER_TEA5761=y +CONFIG_MEDIA_TUNER_TEA5767=y +CONFIG_MEDIA_TUNER_MT20XX=y +CONFIG_MEDIA_TUNER_XC2028=y +CONFIG_MEDIA_TUNER_XC5000=y +CONFIG_MEDIA_TUNER_MC44S803=y +CONFIG_VIDEO_V4L2=y +CONFIG_VIDEO_V4L1=y +CONFIG_VIDEO_CAPTURE_DRIVERS=y +# CONFIG_VIDEO_ADV_DEBUG is not set +# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set +CONFIG_VIDEO_HELPER_CHIPS_AUTO=y +# CONFIG_VIDEO_VIVI is not set +# CONFIG_VIDEO_CPIA is not set +# CONFIG_VIDEO_CPIA2 is not set +# CONFIG_VIDEO_SAA5246A is not set +# CONFIG_VIDEO_SAA5249 is not set +# CONFIG_SOC_CAMERA is not set +# CONFIG_V4L_USB_DRIVERS is not set +# CONFIG_RADIO_ADAPTERS is not set +CONFIG_DAB=y +# CONFIG_USB_DABUSB is not set + +# +# Graphics support +# +# CONFIG_VGASTATE is not set +CONFIG_VIDEO_OUTPUT_CONTROL=m +CONFIG_FB=y +CONFIG_FIRMWARE_EDID=y +# CONFIG_FB_DDC is not set +# CONFIG_FB_BOOT_VESA_SUPPORT is not set +# CONFIG_FB_CFB_FILLRECT is not set +# CONFIG_FB_CFB_COPYAREA is not set +# CONFIG_FB_CFB_IMAGEBLIT is not set +# 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 +# CONFIG_FB_FOREIGN_ENDIAN is not set +# CONFIG_FB_SYS_FOPS is not set +# CONFIG_FB_SVGALIB is not set +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set +# CONFIG_FB_MODE_HELPERS is not set +# CONFIG_FB_TILEBLITTING is not set + +# +# Frame buffer hardware drivers +# +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FB_METRONOME is not set +# CONFIG_FB_MB862XX is not set +# CONFIG_FB_BROADSHEET 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_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set +# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set +# CONFIG_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y +CONFIG_LOGO=y +CONFIG_LOGO_LINUX_MONO=y +CONFIG_LOGO_LINUX_VGA16=y +CONFIG_LOGO_LINUX_CLUT224=y +CONFIG_SOUND=m +# CONFIG_SOUND_OSS_CORE is not set +CONFIG_SND=m +CONFIG_SND_TIMER=m +CONFIG_SND_PCM=m +CONFIG_SND_JACK=y +# CONFIG_SND_SEQUENCER is not set +# CONFIG_SND_MIXER_OSS is not set +# CONFIG_SND_PCM_OSS is not set +# CONFIG_SND_HRTIMER is not set +# 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 +CONFIG_SND_DRIVERS=y +# CONFIG_SND_DUMMY is not set +# CONFIG_SND_MTPAV is not set +# CONFIG_SND_SERIAL_U16550 is not set +# CONFIG_SND_MPU401 is not set +CONFIG_SND_ARM=y +CONFIG_SND_USB=y +# CONFIG_SND_USB_AUDIO is not set +# CONFIG_SND_USB_CAIAQ is not set +CONFIG_SND_SOC=m +# CONFIG_SND_DAVINCI_SOC is not set +CONFIG_SND_SOC_I2C_AND_SPI=m +# CONFIG_SND_SOC_ALL_CODECS is not set +# 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_HID_PID is not set +# CONFIG_USB_HIDDEV is not set + +# +# USB HID Boot Protocol drivers +# +# CONFIG_USB_KBD is not set +# CONFIG_USB_MOUSE is not set + +# +# Special HID drivers +# +CONFIG_HID_A4TECH=m +CONFIG_HID_APPLE=m +CONFIG_HID_BELKIN=m +CONFIG_HID_CHERRY=m +CONFIG_HID_CHICONY=m +CONFIG_HID_CYPRESS=m +# CONFIG_DRAGONRISE_FF is not set +CONFIG_HID_EZKEY=m +# CONFIG_HID_KYE is not set +CONFIG_HID_GYRATION=m +# CONFIG_HID_KENSINGTON is not set +CONFIG_HID_LOGITECH=m +# CONFIG_LOGITECH_FF is not set +# CONFIG_LOGIRUMBLEPAD2_FF is not set +CONFIG_HID_MICROSOFT=m +CONFIG_HID_MONTEREY=m +# CONFIG_HID_NTRIG is not set +CONFIG_HID_PANTHERLORD=m +# CONFIG_PANTHERLORD_FF is not set +CONFIG_HID_PETALYNX=m +CONFIG_HID_SAMSUNG=m +CONFIG_HID_SONY=m +CONFIG_HID_SUNPLUS=m +# CONFIG_GREENASIA_FF is not set +# CONFIG_HID_TOPSEED is not set +# CONFIG_THRUSTMASTER_FF is not set +# CONFIG_ZEROPLUS_FF 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=m +# 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=y +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_OTG is not set +# CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_OTG_BLACKLIST_HUB is not set +CONFIG_USB_MON=m +# CONFIG_USB_WUSB is not set +# CONFIG_USB_WUSB_CBAF is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_C67X00_HCD is not set +# CONFIG_USB_OXU210HP_HCD is not set +# CONFIG_USB_ISP116X_HCD is not set +# CONFIG_USB_ISP1760_HCD is not set +# CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_R8A66597_HCD is not set +# CONFIG_USB_HWA_HCD is not set +CONFIG_USB_MUSB_HDRC=m +CONFIG_USB_MUSB_SOC=y + +# +# DaVinci 35x and 644x USB support +# +# CONFIG_USB_MUSB_HOST is not set +CONFIG_USB_MUSB_PERIPHERAL=y +# CONFIG_USB_MUSB_OTG is not set +CONFIG_USB_GADGET_MUSB_HDRC=y +CONFIG_MUSB_PIO_ONLY=y +# CONFIG_USB_MUSB_DEBUG is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set +# CONFIG_USB_WDM is not set +# CONFIG_USB_TMC is not set + +# +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may +# + +# +# also be needed; see USB_STORAGE Help for more info +# +CONFIG_USB_STORAGE=m +# 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_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_ONETOUCH is not set +# CONFIG_USB_STORAGE_KARMA is not set +# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set +# CONFIG_USB_LIBUSUAL is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK 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_SEVSEG 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_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_TEST=m +# CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_VST is not set +CONFIG_USB_GADGET=m +# CONFIG_USB_GADGET_DEBUG is not set +CONFIG_USB_GADGET_DEBUG_FILES=y +CONFIG_USB_GADGET_DEBUG_FS=y +CONFIG_USB_GADGET_VBUS_DRAW=2 +CONFIG_USB_GADGET_SELECTED=y +# CONFIG_USB_GADGET_AT91 is not set +# CONFIG_USB_GADGET_ATMEL_USBA is not set +# CONFIG_USB_GADGET_FSL_USB2 is not set +# CONFIG_USB_GADGET_LH7A40X is not set +# CONFIG_USB_GADGET_OMAP is not set +# CONFIG_USB_GADGET_PXA25X is not set +# CONFIG_USB_GADGET_PXA27X is not set +# CONFIG_USB_GADGET_S3C2410 is not set +# CONFIG_USB_GADGET_IMX is not set +# CONFIG_USB_GADGET_M66592 is not set +# CONFIG_USB_GADGET_AMD5536UDC is not set +# CONFIG_USB_GADGET_FSL_QE is not set +# CONFIG_USB_GADGET_CI13XXX is not set +# CONFIG_USB_GADGET_NET2280 is not set +# CONFIG_USB_GADGET_GOKU 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 is not set +CONFIG_USB_G_PRINTER=m +CONFIG_USB_CDC_COMPOSITE=m + +# +# OTG and related infrastructure +# +CONFIG_USB_OTG_UTILS=y +# CONFIG_USB_GPIO_VBUS is not set +# CONFIG_NOP_USB_XCEIV is not set +CONFIG_MMC=m +# CONFIG_MMC_DEBUG is not set +# CONFIG_MMC_UNSAFE_RESUME is not set + +# +# MMC/SD/SDIO Card Drivers +# +CONFIG_MMC_BLOCK=m +# CONFIG_MMC_BLOCK_BOUNCE is not set +# CONFIG_SDIO_UART is not set +# CONFIG_MMC_TEST is not set + +# +# MMC/SD/SDIO Host Controller Drivers +# +# CONFIG_MMC_SDHCI is not set +# CONFIG_MEMSTICK is not set +# CONFIG_ACCESSIBILITY is not set +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=m + +# +# LED drivers +# +# CONFIG_LEDS_PCA9532 is not set +CONFIG_LEDS_GPIO=m +CONFIG_LEDS_GPIO_PLATFORM=y +# CONFIG_LEDS_LP5521 is not set +# CONFIG_LEDS_PCA955X is not set +# CONFIG_LEDS_BD2802 is not set + +# +# LED Triggers +# +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=m +# CONFIG_LEDS_TRIGGER_IDE_DISK is not set +CONFIG_LEDS_TRIGGER_HEARTBEAT=m +# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set +# CONFIG_LEDS_TRIGGER_GPIO is not set +# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set + +# +# iptables trigger is under Netfilter config (LED target) +# +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=m + +# +# 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 + +# +# I2C RTC drivers +# +# CONFIG_RTC_DRV_DS1307 is not set +# CONFIG_RTC_DRV_DS1374 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_MAX6900 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_M41T80 is not set +# CONFIG_RTC_DRV_S35390A is not set +# CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_RX8581 is not set + +# +# SPI RTC drivers +# + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_CMOS is not set +# CONFIG_RTC_DRV_DS1286 is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 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_M48T35 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_BQ4802 is not set +# CONFIG_RTC_DRV_V3020 is not set + +# +# on-CPU RTC drivers +# +# CONFIG_DMADEVICES is not set +# CONFIG_AUXDISPLAY is not set +# CONFIG_REGULATOR is not set +# CONFIG_UIO is not set +# CONFIG_STAGING 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_DEFAULTS_TO_ORDERED is not set +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +# CONFIG_EXT3_FS_SECURITY is not set +# CONFIG_EXT4_FS is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +CONFIG_FILE_LOCKING=y +CONFIG_XFS_FS=m +# CONFIG_XFS_QUOTA is not set +# CONFIG_XFS_POSIX_ACL is not set +# CONFIG_XFS_RT is not set +# CONFIG_XFS_DEBUG is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_BTRFS_FS is not set +CONFIG_DNOTIFY=y +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +CONFIG_AUTOFS4_FS=m +# CONFIG_FUSE_FS is not set + +# +# Caches +# +# CONFIG_FSCACHE is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set +CONFIG_MISC_FILESYSTEMS=y +# 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_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 is not set +# 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=y +# CONFIG_SQUASHFS is not set +# CONFIG_VXFS_FS is not set +CONFIG_MINIX_FS=m +# CONFIG_OMFS_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_NILFS2_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +# CONFIG_NFS_V4 is not set +CONFIG_ROOT_NFS=y +CONFIG_NFSD=m +CONFIG_NFSD_V3=y +# CONFIG_NFSD_V3_ACL is not set +# CONFIG_NFSD_V4 is not set +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=m +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set +CONFIG_SMB_FS=m +# CONFIG_SMB_NLS_DEFAULT is not set +# CONFIG_CIFS 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 is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +# CONFIG_EFI_PARTITION is not set +# CONFIG_SYSV68_PARTITION is not set +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +CONFIG_NLS_ASCII=m +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +CONFIG_NLS_UTF8=m +# CONFIG_DLM is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=1024 +# 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=y +# CONFIG_DEBUG_SHIRQ is not set +CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 +CONFIG_DETECT_HUNG_TASK=y +# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set +CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0 +CONFIG_SCHED_DEBUG=y +# CONFIG_SCHEDSTATS is not set +CONFIG_TIMER_STATS=y +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_SLUB_STATS is not set +CONFIG_DEBUG_PREEMPT=y +CONFIG_DEBUG_RT_MUTEXES=y +CONFIG_DEBUG_PI_LIST=y +# CONFIG_RT_MUTEX_TESTER is not set +# CONFIG_DEBUG_SPINLOCK is not set +CONFIG_DEBUG_MUTEXES=y +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_BUGVERBOSE=y +# CONFIG_DEBUG_INFO is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_WRITECOUNT is not set +# CONFIG_DEBUG_MEMORY_INIT is not set +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_BOOT_PRINTK_DELAY is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_RCU_CPU_STALL_DETECTOR is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_LATENCYTOP is not set +# CONFIG_SYSCTL_SYSCALL_CHECK is not set +# CONFIG_PAGE_POISONING is not set +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_TRACING_SUPPORT=y + +# +# Tracers +# +# CONFIG_FUNCTION_TRACER is not set +# CONFIG_IRQSOFF_TRACER is not set +# CONFIG_PREEMPT_TRACER is not set +# CONFIG_SCHED_TRACER is not set +# CONFIG_CONTEXT_SWITCH_TRACER is not set +# CONFIG_EVENT_TRACER is not set +# CONFIG_BOOT_TRACER is not set +# CONFIG_TRACE_BRANCH_PROFILING is not set +# CONFIG_STACK_TRACER is not set +# CONFIG_KMEMTRACE is not set +# CONFIG_WORKQUEUE_TRACER is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_DYNAMIC_DEBUG is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +CONFIG_ARM_UNWIND=y +CONFIG_DEBUG_USER=y +CONFIG_DEBUG_ERRORS=y +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_LL is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +# CONFIG_SECURITY_FILE_CAPABILITIES is not set +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +# CONFIG_CRYPTO_FIPS is not set +# CONFIG_CRYPTO_MANAGER is not set +# CONFIG_CRYPTO_MANAGER2 is not set +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_CRYPTD is not set +# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_SEQIV is not set + +# +# Block modes +# +# CONFIG_CRYPTO_CBC is not set +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +# CONFIG_CRYPTO_ECB is not set +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_XTS is not set + +# +# Hash modes +# +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_XCBC is not set + +# +# Digest +# +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_WP512 is not set + +# +# Ciphers +# +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_TWOFISH is not set + +# +# Compression +# +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_ZLIB is not set +# CONFIG_CRYPTO_LZO is not set + +# +# Random Number Generation +# +# CONFIG_CRYPTO_ANSI_CPRNG is not set +# CONFIG_CRYPTO_HW is not set +# CONFIG_BINARY_PRINTF is not set + +# +# Library routines +# +CONFIG_BITREVERSE=y +CONFIG_GENERIC_FIND_LAST_BIT=y +CONFIG_CRC_CCITT=m +# CONFIG_CRC16 is not set +CONFIG_CRC_T10DIF=m +# CONFIG_CRC_ITU_T is not set +CONFIG_CRC32=y +# CONFIG_CRC7 is not set +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=m +CONFIG_DECOMPRESS_GZIP=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y +CONFIG_NLATTR=y diff --git a/arch/arm/configs/kirkwood_defconfig b/arch/arm/configs/kirkwood_defconfig index c367ae44012..dcf8153a947 100644 --- a/arch/arm/configs/kirkwood_defconfig +++ b/arch/arm/configs/kirkwood_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.29-rc5 -# Tue Mar 3 21:45:57 2009 +# Linux kernel version: 2.6.30-rc4 +# Mon May 4 11:58:57 2009 # CONFIG_ARM=y CONFIG_SYS_SUPPORTS_APM_EMULATION=y @@ -66,20 +66,20 @@ CONFIG_NAMESPACES=y # CONFIG_BLK_DEV_INITRD is not set CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y # CONFIG_EMBEDDED is not set CONFIG_UID16=y CONFIG_SYSCTL_SYSCALL=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_ALL is not set # CONFIG_KALLSYMS_EXTRA_PASS is not set +# CONFIG_STRIP_ASM_SYMS 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 @@ -89,6 +89,7 @@ CONFIG_AIO=y CONFIG_VM_EVENT_COUNTERS=y CONFIG_PCI_QUIRKS=y CONFIG_SLUB_DEBUG=y +CONFIG_COMPAT_BRK=y # CONFIG_SLAB is not set CONFIG_SLUB=y # CONFIG_SLOB is not set @@ -101,6 +102,7 @@ CONFIG_KPROBES=y CONFIG_KRETPROBES=y CONFIG_HAVE_KPROBES=y CONFIG_HAVE_KRETPROBES=y +# CONFIG_SLOW_WORK is not set CONFIG_HAVE_GENERIC_DMA_COHERENT=y CONFIG_SLABINFO=y CONFIG_RT_MUTEXES=y @@ -113,7 +115,6 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_SRCVERSION_ALL is not set CONFIG_BLOCK=y # CONFIG_LBD is not set -# CONFIG_BLK_DEV_IO_TRACE is not set # CONFIG_BLK_DEV_BSG is not set # CONFIG_BLK_DEV_INTEGRITY is not set @@ -142,6 +143,7 @@ CONFIG_DEFAULT_IOSCHED="cfq" # CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_EBSA110 is not set # CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_GEMINI is not set # CONFIG_ARCH_FOOTBRIDGE is not set # CONFIG_ARCH_NETX is not set # CONFIG_ARCH_H720X is not set @@ -162,6 +164,7 @@ CONFIG_ARCH_KIRKWOOD=y # CONFIG_ARCH_ORION5X is not set # CONFIG_ARCH_PNX4008 is not set # CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_MMP is not set # CONFIG_ARCH_RPC is not set # CONFIG_ARCH_SA1100 is not set # CONFIG_ARCH_S3C2410 is not set @@ -217,6 +220,7 @@ CONFIG_PCI_SYSCALL=y CONFIG_PCI_LEGACY=y # CONFIG_PCI_DEBUG is not set # CONFIG_PCI_STUB is not set +# CONFIG_PCI_IOV is not set # CONFIG_PCCARD is not set # @@ -237,6 +241,7 @@ CONFIG_AEABI=y CONFIG_ARCH_FLATMEM_HAS_HOLES=y # CONFIG_ARCH_SPARSEMEM_DEFAULT is not set # CONFIG_ARCH_SELECT_MEMORY_MODEL is not set +# CONFIG_HIGHMEM is not set CONFIG_SELECT_MEMORY_MODEL=y CONFIG_FLATMEM_MANUAL=y # CONFIG_DISCONTIGMEM_MANUAL is not set @@ -249,6 +254,8 @@ CONFIG_SPLIT_PTLOCK_CPUS=4096 CONFIG_ZONE_DMA_FLAG=0 CONFIG_VIRT_TO_BUS=y CONFIG_UNEVICTABLE_LRU=y +CONFIG_HAVE_MLOCK=y +CONFIG_HAVE_MLOCKED_PAGE_BIT=y CONFIG_ALIGNMENT_TRAP=y # @@ -293,7 +300,6 @@ CONFIG_NET=y # # Networking options # -CONFIG_COMPAT_NET_DEV_OPS=y CONFIG_PACKET=y CONFIG_PACKET_MMAP=y CONFIG_UNIX=y @@ -324,7 +330,7 @@ CONFIG_IP_PNP_BOOTP=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_LRO=y CONFIG_INET_DIAG=y CONFIG_INET_TCP_DIAG=y # CONFIG_TCP_CONG_ADVANCED is not set @@ -357,6 +363,7 @@ CONFIG_NET_DSA_MV88E6123_61_65=y # CONFIG_LAPB is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set +# CONFIG_PHONET is not set # CONFIG_NET_SCHED is not set # CONFIG_DCB is not set @@ -365,20 +372,20 @@ CONFIG_NET_DSA_MV88E6123_61_65=y # CONFIG_NET_PKTGEN=m # CONFIG_NET_TCPPROBE is not set +# CONFIG_NET_DROP_MONITOR 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 -# CONFIG_PHONET is not set CONFIG_WIRELESS=y CONFIG_CFG80211=y # CONFIG_CFG80211_REG_DEBUG is not set -# CONFIG_NL80211 is not set CONFIG_WIRELESS_OLD_REGULATORY=y CONFIG_WIRELESS_EXT=y CONFIG_WIRELESS_EXT_SYSFS=y CONFIG_LIB80211=y +# CONFIG_LIB80211_DEBUG is not set CONFIG_MAC80211=y # @@ -513,7 +520,6 @@ CONFIG_MTD_NAND_ORION=y # LPDDR flash memory drivers # # CONFIG_MTD_LPDDR is not set -# CONFIG_MTD_QINFO_PROBE is not set # # UBI - Unsorted block images @@ -592,8 +598,10 @@ CONFIG_SCSI_LOWLEVEL=y # CONFIG_MEGARAID_NEWGEN is not set # CONFIG_MEGARAID_LEGACY is not set # CONFIG_MEGARAID_SAS is not set +# CONFIG_SCSI_MPT2SAS is not set # CONFIG_SCSI_HPTIOP is not set # CONFIG_LIBFC is not set +# CONFIG_LIBFCOE is not set # CONFIG_FCOE is not set # CONFIG_SCSI_DMX3191D is not set # CONFIG_SCSI_FUTURE_DOMAIN is not set @@ -614,6 +622,7 @@ CONFIG_SCSI_LOWLEVEL=y # CONFIG_SCSI_DEBUG is not set # CONFIG_SCSI_SRP is not set # CONFIG_SCSI_DH is not set +# CONFIG_SCSI_OSD_INITIATOR is not set CONFIG_ATA=y # CONFIG_ATA_NONSTANDARD is not set CONFIG_SATA_PMP=y @@ -687,6 +696,7 @@ CONFIG_SATA_MV=y # CONFIG_IEEE1394 is not set # CONFIG_I2O is not set CONFIG_NETDEVICES=y +CONFIG_COMPAT_NET_DEV_OPS=y # CONFIG_DUMMY is not set # CONFIG_BONDING is not set # CONFIG_MACVLAN is not set @@ -724,8 +734,10 @@ CONFIG_MII=y # CONFIG_SMC91X is not set # CONFIG_DM9000 is not set # CONFIG_ENC28J60 is not set +# CONFIG_ETHOC is not set # CONFIG_SMC911X is not set # CONFIG_SMSC911X is not set +# CONFIG_DNET is not set # CONFIG_NET_TULIP is not set # CONFIG_HP100 is not set # CONFIG_IBM_NEW_EMAC_ZMII is not set @@ -763,6 +775,7 @@ CONFIG_NETDEV_1000=y # CONFIG_E1000E is not set # CONFIG_IP1000 is not set # CONFIG_IGB is not set +# CONFIG_IGBVF is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set @@ -777,6 +790,7 @@ CONFIG_MV643XX_ETH=y # CONFIG_QLA3XXX is not set # CONFIG_ATL1 is not set # CONFIG_ATL1E is not set +# CONFIG_ATL1C is not set # CONFIG_JME is not set # CONFIG_NETDEV_10000 is not set # CONFIG_TR is not set @@ -789,10 +803,11 @@ CONFIG_WLAN_80211=y CONFIG_LIBERTAS=y # CONFIG_LIBERTAS_USB is not set CONFIG_LIBERTAS_SDIO=y +# CONFIG_LIBERTAS_SPI is not set # CONFIG_LIBERTAS_DEBUG is not set # CONFIG_LIBERTAS_THINFIRM is not set -# CONFIG_HERMES is not set # CONFIG_ATMEL is not set +# CONFIG_AT76C50X_USB is not set # CONFIG_PRISM54 is not set # CONFIG_USB_ZD1201 is not set # CONFIG_USB_NET_RNDIS_WLAN is not set @@ -800,20 +815,20 @@ CONFIG_LIBERTAS_SDIO=y # CONFIG_RTL8187 is not set # CONFIG_ADM8211 is not set # CONFIG_MAC80211_HWSIM is not set +# CONFIG_MWL8K is not set # CONFIG_P54_COMMON is not set # CONFIG_ATH5K is not set # CONFIG_ATH9K is not set +# CONFIG_AR9170_USB is not set # CONFIG_IPW2100 is not set # CONFIG_IPW2200 is not set -# CONFIG_IWLCORE is not set -# CONFIG_IWLWIFI_LEDS is not set -# CONFIG_IWLAGN is not set -# CONFIG_IWL3945 is not set +# CONFIG_IWLWIFI is not set # CONFIG_HOSTAP is not set # CONFIG_B43 is not set # CONFIG_B43LEGACY is not set # CONFIG_ZD1211RW is not set # CONFIG_RT2X00 is not set +# CONFIG_HERMES is not set # # Enable WiMAX (Networking options) to see the WiMAX drivers @@ -908,6 +923,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=2 # # Non-8250 serial port support # +# CONFIG_SERIAL_MAX3100 is not set CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y # CONFIG_SERIAL_JSM is not set @@ -982,7 +998,6 @@ CONFIG_I2C_MV64XXX=y # CONFIG_SENSORS_PCF8574 is not set # CONFIG_PCF8575 is not set # CONFIG_SENSORS_PCA9539 is not set -# CONFIG_SENSORS_PCF8591 is not set # CONFIG_SENSORS_MAX6875 is not set # CONFIG_SENSORS_TSL2550 is not set # CONFIG_I2C_DEBUG_CORE is not set @@ -1082,15 +1097,17 @@ CONFIG_USB_HID=y # # Special HID drivers # -CONFIG_HID_COMPAT=y CONFIG_HID_A4TECH=y CONFIG_HID_APPLE=y CONFIG_HID_BELKIN=y CONFIG_HID_CHERRY=y CONFIG_HID_CHICONY=y CONFIG_HID_CYPRESS=y +# CONFIG_DRAGONRISE_FF is not set CONFIG_HID_EZKEY=y +CONFIG_HID_KYE=y CONFIG_HID_GYRATION=y +CONFIG_HID_KENSINGTON=y CONFIG_HID_LOGITECH=y # CONFIG_LOGITECH_FF is not set # CONFIG_LOGIRUMBLEPAD2_FF is not set @@ -1152,11 +1169,11 @@ CONFIG_USB_PRINTER=m # CONFIG_USB_TMC is not set # -# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed; +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may # # -# see USB_STORAGE Help for more information +# also be needed; see USB_STORAGE Help for more info # CONFIG_USB_STORAGE=y # CONFIG_USB_STORAGE_DEBUG is not set @@ -1198,7 +1215,6 @@ CONFIG_USB_STORAGE_JUMPSHOT=y # 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 @@ -1215,6 +1231,7 @@ CONFIG_USB_STORAGE_JUMPSHOT=y # OTG and related infrastructure # # CONFIG_USB_GPIO_VBUS is not set +# CONFIG_NOP_USB_XCEIV is not set # CONFIG_UWB is not set CONFIG_MMC=y # CONFIG_MMC_DEBUG is not set @@ -1245,7 +1262,11 @@ CONFIG_LEDS_CLASS=y # # CONFIG_LEDS_PCA9532 is not set CONFIG_LEDS_GPIO=y +CONFIG_LEDS_GPIO_PLATFORM=y +# CONFIG_LEDS_LP5521 is not set # CONFIG_LEDS_PCA955X is not set +# CONFIG_LEDS_DAC124S085 is not set +# CONFIG_LEDS_BD2802 is not set # # LED Triggers @@ -1255,6 +1276,10 @@ CONFIG_LEDS_TRIGGER_TIMER=y CONFIG_LEDS_TRIGGER_HEARTBEAT=y # CONFIG_LEDS_TRIGGER_BACKLIGHT is not set CONFIG_LEDS_TRIGGER_DEFAULT_ON=y + +# +# iptables trigger is under Netfilter config (LED target) +# CONFIG_RTC_LIB=y CONFIG_RTC_CLASS=y CONFIG_RTC_HCTOSYS=y @@ -1329,7 +1354,9 @@ CONFIG_DMA_ENGINE=y # DMA Clients # # CONFIG_NET_DMA is not set +# CONFIG_ASYNC_TX_DMA is not set # CONFIG_DMATEST is not set +# CONFIG_AUXDISPLAY is not set # CONFIG_REGULATOR is not set # CONFIG_UIO is not set # CONFIG_STAGING is not set @@ -1341,6 +1368,7 @@ CONFIG_EXT2_FS=y # CONFIG_EXT2_FS_XATTR is not set # CONFIG_EXT2_FS_XIP is not set CONFIG_EXT3_FS=y +# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set # CONFIG_EXT3_FS_XATTR is not set # CONFIG_EXT4_FS is not set CONFIG_JBD=y @@ -1361,6 +1389,11 @@ CONFIG_INOTIFY_USER=y # CONFIG_FUSE_FS is not set # +# Caches +# +# CONFIG_FSCACHE is not set + +# # CD-ROM/DVD Filesystems # CONFIG_ISO9660_FS=m @@ -1419,6 +1452,7 @@ CONFIG_CRAMFS=y # CONFIG_ROMFS_FS is not set # CONFIG_SYSV_FS is not set # CONFIG_UFS_FS is not set +# CONFIG_NILFS2_FS is not set CONFIG_NETWORK_FILESYSTEMS=y CONFIG_NFS_FS=y CONFIG_NFS_V3=y @@ -1430,7 +1464,6 @@ CONFIG_LOCKD=y CONFIG_LOCKD_V4=y CONFIG_NFS_COMMON=y CONFIG_SUNRPC=y -# CONFIG_SUNRPC_REGISTER_V4 is not set # CONFIG_RPCSEC_GSS_KRB5 is not set # CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set @@ -1502,6 +1535,9 @@ CONFIG_DEBUG_KERNEL=y CONFIG_DETECT_SOFTLOCKUP=y # CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 +CONFIG_DETECT_HUNG_TASK=y +# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set +CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0 # CONFIG_SCHED_DEBUG is not set # CONFIG_SCHEDSTATS is not set # CONFIG_TIMER_STATS is not set @@ -1538,10 +1574,12 @@ CONFIG_DEBUG_MEMORY_INIT=y # CONFIG_FAULT_INJECTION is not set # CONFIG_LATENCYTOP is not set CONFIG_SYSCTL_SYSCALL_CHECK=y +# CONFIG_PAGE_POISONING is not set CONFIG_NOP_TRACER=y CONFIG_HAVE_FUNCTION_TRACER=y CONFIG_RING_BUFFER=y CONFIG_TRACING=y +CONFIG_TRACING_SUPPORT=y # # Tracers @@ -1551,11 +1589,15 @@ CONFIG_TRACING=y # CONFIG_PREEMPT_TRACER is not set # CONFIG_SCHED_TRACER is not set # CONFIG_CONTEXT_SWITCH_TRACER is not set +# CONFIG_EVENT_TRACER is not set # CONFIG_BOOT_TRACER is not set # CONFIG_TRACE_BRANCH_PROFILING is not set # CONFIG_STACK_TRACER is not set +# CONFIG_KMEMTRACE is not set +# CONFIG_WORKQUEUE_TRACER is not set +# CONFIG_BLK_DEV_IO_TRACE is not set # CONFIG_FTRACE_STARTUP_TEST is not set -# CONFIG_DYNAMIC_PRINTK_DEBUG is not set +# CONFIG_DYNAMIC_DEBUG is not set # CONFIG_SAMPLES is not set CONFIG_HAVE_ARCH_KGDB=y # CONFIG_KGDB is not set @@ -1587,10 +1629,12 @@ CONFIG_CRYPTO_BLKCIPHER2=y CONFIG_CRYPTO_HASH=y CONFIG_CRYPTO_HASH2=y CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_PCOMP=y CONFIG_CRYPTO_MANAGER=y CONFIG_CRYPTO_MANAGER2=y # CONFIG_CRYPTO_GF128MUL is not set # CONFIG_CRYPTO_NULL is not set +CONFIG_CRYPTO_WORKQUEUE=y # CONFIG_CRYPTO_CRYPTD is not set # CONFIG_CRYPTO_AUTHENC is not set # CONFIG_CRYPTO_TEST is not set @@ -1659,6 +1703,7 @@ CONFIG_CRYPTO_ARC4=y # Compression # # CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_ZLIB is not set # CONFIG_CRYPTO_LZO is not set # @@ -1667,6 +1712,7 @@ CONFIG_CRYPTO_ARC4=y # CONFIG_CRYPTO_ANSI_CPRNG is not set CONFIG_CRYPTO_HW=y # CONFIG_CRYPTO_DEV_HIFN_795X is not set +CONFIG_BINARY_PRINTF=y # # Library routines @@ -1682,7 +1728,7 @@ CONFIG_CRC32=y CONFIG_LIBCRC32C=y CONFIG_ZLIB_INFLATE=y CONFIG_ZLIB_DEFLATE=y -CONFIG_PLIST=y CONFIG_HAS_IOMEM=y CONFIG_HAS_IOPORT=y CONFIG_HAS_DMA=y +CONFIG_NLATTR=y diff --git a/arch/arm/configs/mv78xx0_defconfig b/arch/arm/configs/mv78xx0_defconfig index b0698722e0c..398274b0771 100644 --- a/arch/arm/configs/mv78xx0_defconfig +++ b/arch/arm/configs/mv78xx0_defconfig @@ -1,11 +1,11 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.26-rc5 -# Fri Jun 13 02:57:32 2008 +# Linux kernel version: 2.6.30-rc4 +# Mon May 4 14:22:12 2009 # CONFIG_ARM=y CONFIG_SYS_SUPPORTS_APM_EMULATION=y -# CONFIG_GENERIC_GPIO is not set +CONFIG_GENERIC_GPIO=y CONFIG_GENERIC_TIME=y CONFIG_GENERIC_CLOCKEVENTS=y CONFIG_MMU=y @@ -22,8 +22,7 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y # CONFIG_ARCH_HAS_ILOG2_U64 is not set CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_CALIBRATE_DELAY=y -CONFIG_ARCH_SUPPORTS_AOUT=y -CONFIG_ZONE_DMA=y +CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y CONFIG_VECTORS_BASE=0xffff0000 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" @@ -43,10 +42,19 @@ CONFIG_SYSVIPC_SYSCTL=y # CONFIG_BSD_PROCESS_ACCT is not set # CONFIG_TASKSTATS is not set # CONFIG_AUDIT is not set + +# +# RCU Subsystem +# +CONFIG_CLASSIC_RCU=y +# CONFIG_TREE_RCU is not set +# CONFIG_PREEMPT_RCU is not set +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_PREEMPT_RCU_TRACE is not set # CONFIG_IKCONFIG is not set CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_CGROUPS is not set # CONFIG_GROUP_SCHED is not set +# CONFIG_CGROUPS is not set CONFIG_SYSFS_DEPRECATED=y CONFIG_SYSFS_DEPRECATED_V2=y # CONFIG_RELAY is not set @@ -54,32 +62,35 @@ CONFIG_SYSFS_DEPRECATED_V2=y # CONFIG_BLK_DEV_INITRD is not set CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y CONFIG_EMBEDDED=y CONFIG_UID16=y CONFIG_SYSCTL_SYSCALL=y -CONFIG_SYSCTL_SYSCALL_CHECK=y CONFIG_KALLSYMS=y CONFIG_KALLSYMS_ALL=y # CONFIG_KALLSYMS_EXTRA_PASS is not set +# CONFIG_STRIP_ASM_SYMS 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_AIO=y CONFIG_VM_EVENT_COUNTERS=y +CONFIG_PCI_QUIRKS=y # CONFIG_SLUB_DEBUG is not set +CONFIG_COMPAT_BRK=y # CONFIG_SLAB is not set CONFIG_SLUB=y # CONFIG_SLOB is not set CONFIG_PROFILING=y +CONFIG_TRACEPOINTS=y # CONFIG_MARKERS is not set CONFIG_OPROFILE=y CONFIG_HAVE_OPROFILE=y @@ -87,10 +98,9 @@ CONFIG_KPROBES=y CONFIG_KRETPROBES=y CONFIG_HAVE_KPROBES=y CONFIG_HAVE_KRETPROBES=y -# CONFIG_HAVE_DMA_ATTRS is not set -CONFIG_PROC_PAGE_MONITOR=y +# CONFIG_SLOW_WORK is not set +CONFIG_HAVE_GENERIC_DMA_COHERENT=y CONFIG_RT_MUTEXES=y -# CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 CONFIG_MODULES=y # CONFIG_MODULE_FORCE_LOAD is not set @@ -98,12 +108,10 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_FORCE_UNLOAD is not set # CONFIG_MODVERSIONS is not set # CONFIG_MODULE_SRCVERSION_ALL is not set -# CONFIG_KMOD 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 +# CONFIG_BLK_DEV_INTEGRITY is not set # # IO Schedulers @@ -117,7 +125,7 @@ CONFIG_IOSCHED_CFQ=y CONFIG_DEFAULT_CFQ=y # CONFIG_DEFAULT_NOOP is not set CONFIG_DEFAULT_IOSCHED="cfq" -CONFIG_CLASSIC_RCU=y +# CONFIG_FREEZER is not set # # System Type @@ -127,11 +135,10 @@ CONFIG_CLASSIC_RCU=y # CONFIG_ARCH_REALVIEW is not set # CONFIG_ARCH_VERSATILE is not set # CONFIG_ARCH_AT91 is not set -# CONFIG_ARCH_CLPS7500 is not set # CONFIG_ARCH_CLPS711X is not set -# CONFIG_ARCH_CO285 is not set # CONFIG_ARCH_EBSA110 is not set # CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_GEMINI is not set # CONFIG_ARCH_FOOTBRIDGE is not set # CONFIG_ARCH_NETX is not set # CONFIG_ARCH_H720X is not set @@ -152,28 +159,23 @@ CONFIG_ARCH_MV78XX0=y # CONFIG_ARCH_ORION5X is not set # CONFIG_ARCH_PNX4008 is not set # CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_MMP is not set # CONFIG_ARCH_RPC is not set # CONFIG_ARCH_SA1100 is not set # CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_S3C64XX is not set # CONFIG_ARCH_SHARK is not set # CONFIG_ARCH_LH7A40X is not set # CONFIG_ARCH_DAVINCI is not set # CONFIG_ARCH_OMAP is not set -# CONFIG_ARCH_MSM7X00A is not set +# CONFIG_ARCH_MSM is not set +# CONFIG_ARCH_W90X900 is not set # # Marvell MV78xx0 Implementations # CONFIG_MACH_DB78X00_BP=y CONFIG_MACH_RD78X00_MASA=y - -# -# Boot options -# - -# -# Power management -# CONFIG_PLAT_ORION=y # @@ -199,6 +201,7 @@ CONFIG_ARM_THUMB=y # CONFIG_CPU_DCACHE_DISABLE is not set CONFIG_OUTER_CACHE=y CONFIG_CACHE_FEROCEON_L2=y +# CONFIG_CACHE_FEROCEON_L2_WRITETHROUGH is not set # # Bus support @@ -208,6 +211,8 @@ CONFIG_PCI_SYSCALL=y # CONFIG_ARCH_SUPPORTS_MSI is not set CONFIG_PCI_LEGACY=y # CONFIG_PCI_DEBUG is not set +# CONFIG_PCI_STUB is not set +# CONFIG_PCI_IOV is not set # CONFIG_PCCARD is not set # @@ -217,25 +222,33 @@ CONFIG_TICK_ONESHOT=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_VMSPLIT_3G=y +# CONFIG_VMSPLIT_2G is not set +# CONFIG_VMSPLIT_1G is not set +CONFIG_PAGE_OFFSET=0xC0000000 CONFIG_PREEMPT=y CONFIG_HZ=100 CONFIG_AEABI=y CONFIG_OABI_COMPAT=y -# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set +CONFIG_ARCH_FLATMEM_HAS_HOLES=y +# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set +# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set +CONFIG_HIGHMEM=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_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=4096 -# CONFIG_RESOURCES_64BIT is not set -CONFIG_ZONE_DMA_FLAG=1 +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 CONFIG_BOUNCE=y CONFIG_VIRT_TO_BUS=y +CONFIG_UNEVICTABLE_LRU=y +CONFIG_HAVE_MLOCK=y +CONFIG_HAVE_MLOCKED_PAGE_BIT=y CONFIG_ALIGNMENT_TRAP=y # @@ -248,6 +261,11 @@ CONFIG_CMDLINE="" # CONFIG_KEXEC is not set # +# CPU Power Management +# +# CONFIG_CPU_IDLE is not set + +# # Floating point emulation # @@ -263,6 +281,8 @@ CONFIG_VFP=y # Userspace binary formats # CONFIG_BINFMT_ELF=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_HAVE_AOUT=y # CONFIG_BINFMT_AOUT is not set # CONFIG_BINFMT_MISC is not set @@ -271,10 +291,6 @@ CONFIG_BINFMT_ELF=y # # CONFIG_PM is not set CONFIG_ARCH_SUSPEND_POSSIBLE=y - -# -# Networking -# CONFIG_NET=y # @@ -310,7 +326,7 @@ CONFIG_IP_PNP_BOOTP=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_LRO=y CONFIG_INET_DIAG=y CONFIG_INET_TCP_DIAG=y # CONFIG_TCP_CONG_ADVANCED is not set @@ -325,6 +341,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic" # CONFIG_TIPC is not set # CONFIG_ATM is not set # CONFIG_BRIDGE is not set +# CONFIG_NET_DSA is not set # CONFIG_VLAN_8021Q is not set # CONFIG_DECNET is not set # CONFIG_LLC2 is not set @@ -334,26 +351,23 @@ CONFIG_DEFAULT_TCP_CONG="cubic" # CONFIG_LAPB is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set +# CONFIG_PHONET is not set # CONFIG_NET_SCHED is not set +# CONFIG_DCB is not set # # Network testing # CONFIG_NET_PKTGEN=m # CONFIG_NET_TCPPROBE is not set +# CONFIG_NET_DROP_MONITOR 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_WIRELESS is not set +# CONFIG_WIMAX is not set # CONFIG_RFKILL is not set # CONFIG_NET_9P is not set @@ -368,6 +382,8 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y CONFIG_FW_LOADER=y +# CONFIG_FIRMWARE_IN_KERNEL is not set +CONFIG_EXTRA_FIRMWARE="" # CONFIG_DEBUG_DRIVER is not set # CONFIG_DEBUG_DEVRES is not set # CONFIG_SYS_HYPERVISOR is not set @@ -376,6 +392,7 @@ CONFIG_MTD=y # CONFIG_MTD_DEBUG is not set # CONFIG_MTD_CONCAT is not set CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_TESTS is not set # CONFIG_MTD_REDBOOT_PARTS is not set CONFIG_MTD_CMDLINE_PARTS=y # CONFIG_MTD_AFS_PARTS is not set @@ -429,9 +446,7 @@ CONFIG_MTD_CFI_UTIL=y # # CONFIG_MTD_COMPLEX_MAPPINGS is not set CONFIG_MTD_PHYSMAP=y -CONFIG_MTD_PHYSMAP_START=0x0 -CONFIG_MTD_PHYSMAP_LEN=0x0 -CONFIG_MTD_PHYSMAP_BANKWIDTH=0 +# CONFIG_MTD_PHYSMAP_COMPAT is not set # CONFIG_MTD_ARM_INTEGRATOR is not set # CONFIG_MTD_IMPA7 is not set # CONFIG_MTD_INTEL_VR_NOR is not set @@ -456,6 +471,7 @@ CONFIG_MTD_NAND=y CONFIG_MTD_NAND_VERIFY_WRITE=y # CONFIG_MTD_NAND_ECC_SMC is not set # CONFIG_MTD_NAND_MUSEUM_IDS is not set +# CONFIG_MTD_NAND_GPIO is not set CONFIG_MTD_NAND_IDS=y # CONFIG_MTD_NAND_DISKONCHIP is not set # CONFIG_MTD_NAND_CAFE is not set @@ -466,6 +482,11 @@ CONFIG_MTD_NAND_ORION=y # CONFIG_MTD_ONENAND is not set # +# LPDDR flash memory drivers +# +# CONFIG_MTD_LPDDR is not set + +# # UBI - Unsorted block images # # CONFIG_MTD_UBI is not set @@ -486,10 +507,20 @@ CONFIG_BLK_DEV_LOOP=y # CONFIG_ATA_OVER_ETH is not set 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_ICS932S401 is not set # CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_HP_ILO is not set +# CONFIG_ISL29003 is not set +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +# CONFIG_EEPROM_AT24 is not set +# CONFIG_EEPROM_LEGACY is not set +# CONFIG_EEPROM_93CX6 is not set CONFIG_HAVE_IDE=y # CONFIG_IDE is not set @@ -547,7 +578,11 @@ CONFIG_SCSI_LOWLEVEL=y # CONFIG_MEGARAID_NEWGEN is not set # CONFIG_MEGARAID_LEGACY is not set # CONFIG_MEGARAID_SAS is not set +# CONFIG_SCSI_MPT2SAS is not set # CONFIG_SCSI_HPTIOP is not set +# CONFIG_LIBFC is not set +# CONFIG_LIBFCOE is not set +# CONFIG_FCOE is not set # CONFIG_SCSI_DMX3191D is not set # CONFIG_SCSI_FUTURE_DOMAIN is not set # CONFIG_SCSI_IPS is not set @@ -566,6 +601,8 @@ CONFIG_SCSI_LOWLEVEL=y # CONFIG_SCSI_NSP32 is not set # CONFIG_SCSI_DEBUG is not set # CONFIG_SCSI_SRP is not set +# CONFIG_SCSI_DH is not set +# CONFIG_SCSI_OSD_INITIATOR is not set CONFIG_ATA=y # CONFIG_ATA_NONSTANDARD is not set CONFIG_SATA_PMP=y @@ -632,11 +669,15 @@ CONFIG_SATA_MV=y # # IEEE 1394 (FireWire) support # + +# +# Enable only one of the two stacks, unless you know what you are doing +# # 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_COMPAT_NET_DEV_OPS=y # CONFIG_DUMMY is not set # CONFIG_BONDING is not set # CONFIG_MACVLAN is not set @@ -644,7 +685,26 @@ CONFIG_NETDEVICES=y # CONFIG_TUN is not set # CONFIG_VETH is not set # CONFIG_ARCNET is not set -# CONFIG_PHYLIB is not set +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +CONFIG_MARVELL_PHY=y +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set +# CONFIG_VITESSE_PHY is not set +# CONFIG_SMSC_PHY is not set +# CONFIG_BROADCOM_PHY is not set +# CONFIG_ICPLUS_PHY is not set +# CONFIG_REALTEK_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_LSI_ET1011C_PHY is not set +# CONFIG_FIXED_PHY is not set +# CONFIG_MDIO_BITBANG is not set CONFIG_NET_ETHERNET=y CONFIG_MII=y # CONFIG_AX88796 is not set @@ -654,19 +714,25 @@ CONFIG_MII=y # CONFIG_NET_VENDOR_3COM is not set # CONFIG_SMC91X is not set # CONFIG_DM9000 is not set +# CONFIG_ETHOC is not set +# CONFIG_SMC911X is not set +# CONFIG_SMSC911X is not set +# CONFIG_DNET 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_IBM_NEW_EMAC_NO_FLOW_CTRL is not set +# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set +# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR 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_EEPRO100 is not set # CONFIG_E100 is not set # CONFIG_FEALNX is not set # CONFIG_NATSEMI is not set @@ -676,18 +742,20 @@ CONFIG_NET_PCI=y # CONFIG_R6040 is not set # CONFIG_SIS900 is not set # CONFIG_EPIC100 is not set +# CONFIG_SMSC9420 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_ATL2 is not set 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_IGBVF is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set @@ -701,6 +769,9 @@ CONFIG_NETDEV_1000=y CONFIG_MV643XX_ETH=y # CONFIG_QLA3XXX is not set # CONFIG_ATL1 is not set +# CONFIG_ATL1E is not set +# CONFIG_ATL1C is not set +# CONFIG_JME is not set # CONFIG_NETDEV_10000 is not set # CONFIG_TR is not set @@ -709,7 +780,10 @@ CONFIG_MV643XX_ETH=y # # CONFIG_WLAN_PRE80211 is not set # CONFIG_WLAN_80211 is not set -# CONFIG_IWLWIFI_LEDS is not set + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# # # USB Network Adapters @@ -786,11 +860,11 @@ CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y # CONFIG_SERIAL_JSM is not set CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=16 # CONFIG_IPMI_HANDLER is not set # CONFIG_HW_RANDOM is not set -# CONFIG_NVRAM is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set # CONFIG_RAW_DRIVER is not set @@ -799,44 +873,63 @@ CONFIG_DEVPORT=y CONFIG_I2C=y CONFIG_I2C_BOARDINFO=y CONFIG_I2C_CHARDEV=y +CONFIG_I2C_HELPER_AUTO=y # # I2C Hardware Bus support # + +# +# PC SMBus host controller drivers +# # CONFIG_I2C_ALI1535 is not set # CONFIG_I2C_ALI1563 is not set # CONFIG_I2C_ALI15X3 is not set # CONFIG_I2C_AMD756 is not set # CONFIG_I2C_AMD8111 is not set # CONFIG_I2C_I801 is not set -# CONFIG_I2C_I810 is not set +# CONFIG_I2C_ISCH is not set # CONFIG_I2C_PIIX4 is not set # CONFIG_I2C_NFORCE2 is not set -# CONFIG_I2C_OCORES is not set -# CONFIG_I2C_PARPORT_LIGHT is not set -# CONFIG_I2C_PROSAVAGE is not set -# CONFIG_I2C_SAVAGE4 is not set -# CONFIG_I2C_SIMTEC is not set # CONFIG_I2C_SIS5595 is not set # CONFIG_I2C_SIS630 is not set # CONFIG_I2C_SIS96X is not set -# CONFIG_I2C_TAOS_EVM is not set -# CONFIG_I2C_STUB is not set -# CONFIG_I2C_TINY_USB is not set # CONFIG_I2C_VIA is not set # CONFIG_I2C_VIAPRO is not set + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +# CONFIG_I2C_GPIO is not set +CONFIG_I2C_MV64XXX=y +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_SIMTEC is not set + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_TAOS_EVM is not set +# CONFIG_I2C_TINY_USB is not set + +# +# Graphics adapter I2C/DDC channel drivers +# # CONFIG_I2C_VOODOO3 is not set + +# +# Other I2C/SMBus bus drivers +# # CONFIG_I2C_PCA_PLATFORM is not set -CONFIG_I2C_MV64XXX=y +# CONFIG_I2C_STUB is not set # # Miscellaneous I2C Chip support # # CONFIG_DS1682 is not set -# CONFIG_EEPROM_LEGACY is not set # CONFIG_SENSORS_PCF8574 is not set # CONFIG_PCF8575 is not set -# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_PCA9539 is not set # CONFIG_SENSORS_MAX6875 is not set # CONFIG_SENSORS_TSL2550 is not set # CONFIG_I2C_DEBUG_CORE is not set @@ -848,6 +941,7 @@ CONFIG_I2C_MV64XXX=y # CONFIG_POWER_SUPPLY is not set CONFIG_HWMON=y # CONFIG_HWMON_VID is not set +# CONFIG_SENSORS_AD7414 is not set # CONFIG_SENSORS_AD7418 is not set # CONFIG_SENSORS_ADM1021 is not set # CONFIG_SENSORS_ADM1025 is not set @@ -855,14 +949,17 @@ CONFIG_HWMON=y # CONFIG_SENSORS_ADM1029 is not set # CONFIG_SENSORS_ADM1031 is not set # CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ADT7462 is not set # CONFIG_SENSORS_ADT7470 is not set # CONFIG_SENSORS_ADT7473 is not set +# CONFIG_SENSORS_ADT7475 is not set # CONFIG_SENSORS_ATXP1 is not set # CONFIG_SENSORS_DS1621 is not set # CONFIG_SENSORS_I5K_AMB is not set # CONFIG_SENSORS_F71805F is not set # CONFIG_SENSORS_F71882FG is not set # CONFIG_SENSORS_F75375S is not set +# CONFIG_SENSORS_G760A is not set # CONFIG_SENSORS_GL518SM is not set # CONFIG_SENSORS_GL520SM is not set # CONFIG_SENSORS_IT87 is not set @@ -877,10 +974,15 @@ CONFIG_HWMON=y # CONFIG_SENSORS_LM90 is not set # CONFIG_SENSORS_LM92 is not set # CONFIG_SENSORS_LM93 is not set +# CONFIG_SENSORS_LTC4215 is not set +# CONFIG_SENSORS_LTC4245 is not set +# CONFIG_SENSORS_LM95241 is not set # CONFIG_SENSORS_MAX1619 is not set # CONFIG_SENSORS_MAX6650 is not set # CONFIG_SENSORS_PC87360 is not set # CONFIG_SENSORS_PC87427 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_SHT15 is not set # CONFIG_SENSORS_SIS5595 is not set # CONFIG_SENSORS_DME1737 is not set # CONFIG_SENSORS_SMSC47M1 is not set @@ -900,20 +1002,28 @@ CONFIG_HWMON=y # 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_THERMAL_HWMON is not set # CONFIG_WATCHDOG is not set +CONFIG_SSB_POSSIBLE=y # # Sonics Silicon Backplane # -CONFIG_SSB_POSSIBLE=y # CONFIG_SSB is not set # # Multifunction device drivers # +# CONFIG_MFD_CORE is not set # CONFIG_MFD_SM501 is not set -# CONFIG_MFD_ASIC3 is not set # CONFIG_HTC_PASIC3 is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_PMIC_DA903X is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_PCF50633 is not set # # Multimedia devices @@ -944,10 +1054,6 @@ CONFIG_SSB_POSSIBLE=y # Display device support # # CONFIG_DISPLAY_SUPPORT is not set - -# -# Sound -# # CONFIG_SOUND is not set CONFIG_HID_SUPPORT=y CONFIG_HID=y @@ -958,9 +1064,36 @@ CONFIG_HID=y # USB Input Devices # CONFIG_USB_HID=y -# CONFIG_USB_HIDINPUT_POWERBOOK is not set -# CONFIG_HID_FF is not set +# CONFIG_HID_PID is not set # CONFIG_USB_HIDDEV is not set + +# +# Special HID drivers +# +# CONFIG_HID_A4TECH is not set +# CONFIG_HID_APPLE is not set +# CONFIG_HID_BELKIN is not set +# CONFIG_HID_CHERRY is not set +# CONFIG_HID_CHICONY is not set +# CONFIG_HID_CYPRESS is not set +# CONFIG_DRAGONRISE_FF is not set +# CONFIG_HID_EZKEY is not set +# CONFIG_HID_KYE is not set +# CONFIG_HID_GYRATION is not set +# CONFIG_HID_KENSINGTON is not set +# CONFIG_HID_LOGITECH is not set +# CONFIG_HID_MICROSOFT is not set +# CONFIG_HID_MONTEREY is not set +# CONFIG_HID_NTRIG is not set +# CONFIG_HID_PANTHERLORD is not set +# CONFIG_HID_PETALYNX is not set +# CONFIG_HID_SAMSUNG is not set +# CONFIG_HID_SONY is not set +# CONFIG_HID_SUNPLUS is not set +# CONFIG_GREENASIA_FF is not set +# CONFIG_HID_TOPSEED is not set +# CONFIG_THRUSTMASTER_FF is not set +# CONFIG_ZEROPLUS_FF is not set CONFIG_USB_SUPPORT=y CONFIG_USB_ARCH_HAS_HCD=y CONFIG_USB_ARCH_HAS_OHCI=y @@ -978,6 +1111,9 @@ CONFIG_USB_DEVICE_CLASS=y # CONFIG_USB_OTG is not set # CONFIG_USB_OTG_WHITELIST is not set # CONFIG_USB_OTG_BLACKLIST_HUB is not set +# CONFIG_USB_MON is not set +# CONFIG_USB_WUSB is not set +# CONFIG_USB_WUSB_CBAF is not set # # USB Host Controller Drivers @@ -986,12 +1122,15 @@ CONFIG_USB_DEVICE_CLASS=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_ROOT_HUB_TT=y CONFIG_USB_EHCI_TT_NEWSCHED=y +# CONFIG_USB_OXU210HP_HCD is not set # CONFIG_USB_ISP116X_HCD is not set # CONFIG_USB_ISP1760_HCD is not set # CONFIG_USB_OHCI_HCD is not set # CONFIG_USB_UHCI_HCD is not set # CONFIG_USB_SL811_HCD is not set # CONFIG_USB_R8A66597_HCD is not set +# CONFIG_USB_WHCI_HCD is not set +# CONFIG_USB_HWA_HCD is not set # # USB Device Class drivers @@ -999,20 +1138,20 @@ CONFIG_USB_EHCI_TT_NEWSCHED=y # CONFIG_USB_ACM is not set CONFIG_USB_PRINTER=y # CONFIG_USB_WDM is not set +# CONFIG_USB_TMC is not set # -# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may # # -# may also be needed; see USB_STORAGE Help for more information +# also be needed; see USB_STORAGE Help for more info # 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 is not set CONFIG_USB_STORAGE_SDDR09=y CONFIG_USB_STORAGE_SDDR55=y @@ -1028,7 +1167,6 @@ CONFIG_USB_STORAGE_JUMPSHOT=y # # CONFIG_USB_MDC800 is not set # CONFIG_USB_MICROTEK is not set -# CONFIG_USB_MON is not set # # USB port drivers @@ -1041,7 +1179,7 @@ CONFIG_USB_STORAGE_JUMPSHOT=y # 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_SEVSEG is not set # CONFIG_USB_RIO500 is not set # CONFIG_USB_LEGOTOWER is not set # CONFIG_USB_LCD is not set @@ -1049,7 +1187,6 @@ CONFIG_USB_STORAGE_JUMPSHOT=y # 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 @@ -1059,14 +1196,29 @@ CONFIG_USB_STORAGE_JUMPSHOT=y # CONFIG_USB_IOWARRIOR is not set # CONFIG_USB_TEST is not set # CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_VST is not set # CONFIG_USB_GADGET is not set + +# +# OTG and related infrastructure +# +# CONFIG_USB_GPIO_VBUS is not set +# CONFIG_NOP_USB_XCEIV is not set +# CONFIG_UWB is not set # CONFIG_MMC is not set +# CONFIG_MEMSTICK is not set +# CONFIG_ACCESSIBILITY is not set CONFIG_NEW_LEDS=y CONFIG_LEDS_CLASS=y # # LED drivers # +# CONFIG_LEDS_PCA9532 is not set +# CONFIG_LEDS_GPIO is not set +# CONFIG_LEDS_LP5521 is not set +# CONFIG_LEDS_PCA955X is not set +# CONFIG_LEDS_BD2802 is not set # # LED Triggers @@ -1074,7 +1226,12 @@ CONFIG_LEDS_CLASS=y CONFIG_LEDS_TRIGGERS=y CONFIG_LEDS_TRIGGER_TIMER=y CONFIG_LEDS_TRIGGER_HEARTBEAT=y +# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set # CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set + +# +# iptables trigger is under Netfilter config (LED target) +# CONFIG_RTC_LIB=y CONFIG_RTC_CLASS=y CONFIG_RTC_HCTOSYS=y @@ -1105,6 +1262,8 @@ CONFIG_RTC_DRV_RS5C372=y CONFIG_RTC_DRV_M41T80=y # CONFIG_RTC_DRV_M41T80_WDT is not set # CONFIG_RTC_DRV_S35390A is not set +# CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_RX8581 is not set # # SPI RTC drivers @@ -1114,18 +1273,25 @@ CONFIG_RTC_DRV_M41T80=y # Platform RTC drivers # # CONFIG_RTC_DRV_CMOS is not set +# CONFIG_RTC_DRV_DS1286 is not set # CONFIG_RTC_DRV_DS1511 is not set # CONFIG_RTC_DRV_DS1553 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_M48T35 is not set # CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_BQ4802 is not set # CONFIG_RTC_DRV_V3020 is not set # # on-CPU RTC drivers # +# CONFIG_DMADEVICES is not set +# CONFIG_AUXDISPLAY is not set +# CONFIG_REGULATOR is not set # CONFIG_UIO is not set +# CONFIG_STAGING is not set # # File systems @@ -1134,14 +1300,25 @@ CONFIG_EXT2_FS=y # CONFIG_EXT2_FS_XATTR is not set # CONFIG_EXT2_FS_XIP is not set CONFIG_EXT3_FS=y +# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set # CONFIG_EXT3_FS_XATTR is not set -# CONFIG_EXT4DEV_FS is not set +CONFIG_EXT4_FS=m +# CONFIG_EXT4DEV_COMPAT is not set +CONFIG_EXT4_FS_XATTR=y +# CONFIG_EXT4_FS_POSIX_ACL is not set +# CONFIG_EXT4_FS_SECURITY is not set CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_JBD2=m +# CONFIG_JBD2_DEBUG is not set +CONFIG_FS_MBCACHE=m # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set # CONFIG_FS_POSIX_ACL is not set +CONFIG_FILE_LOCKING=y # CONFIG_XFS_FS is not set # CONFIG_OCFS2_FS is not set +# CONFIG_BTRFS_FS is not set CONFIG_DNOTIFY=y CONFIG_INOTIFY=y CONFIG_INOTIFY_USER=y @@ -1151,6 +1328,11 @@ CONFIG_INOTIFY_USER=y # CONFIG_FUSE_FS is not set # +# Caches +# +# CONFIG_FSCACHE is not set + +# # CD-ROM/DVD Filesystems # CONFIG_ISO9660_FS=m @@ -1174,15 +1356,13 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" # CONFIG_PROC_FS=y CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y CONFIG_SYSFS=y CONFIG_TMPFS=y # CONFIG_TMPFS_POSIX_ACL is not set # CONFIG_HUGETLB_PAGE is not set # CONFIG_CONFIGFS_FS is not set - -# -# Miscellaneous filesystems -# +CONFIG_MISC_FILESYSTEMS=y # CONFIG_ADFS_FS is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set @@ -1202,25 +1382,27 @@ CONFIG_JFFS2_ZLIB=y CONFIG_JFFS2_RTIME=y # CONFIG_JFFS2_RUBIN is not set CONFIG_CRAMFS=y +# CONFIG_SQUASHFS is not set # CONFIG_VXFS_FS is not set # CONFIG_MINIX_FS is not set +# CONFIG_OMFS_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_NILFS2_FS is not set CONFIG_NETWORK_FILESYSTEMS=y CONFIG_NFS_FS=y CONFIG_NFS_V3=y # CONFIG_NFS_V3_ACL is not set # CONFIG_NFS_V4 is not set -# CONFIG_NFSD is not set CONFIG_ROOT_NFS=y +# CONFIG_NFSD is not set CONFIG_LOCKD=y CONFIG_LOCKD_V4=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 @@ -1301,11 +1483,16 @@ CONFIG_ENABLE_MUST_CHECK=y CONFIG_FRAME_WARN=1024 CONFIG_MAGIC_SYSRQ=y # 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=y # CONFIG_DEBUG_SHIRQ is not set CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 +CONFIG_DETECT_HUNG_TASK=y +# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set +CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0 CONFIG_SCHED_DEBUG=y CONFIG_SCHEDSTATS=y # CONFIG_TIMER_STATS is not set @@ -1320,22 +1507,55 @@ CONFIG_DEBUG_PREEMPT=y # CONFIG_LOCK_STAT is not set # CONFIG_DEBUG_SPINLOCK_SLEEP is not set # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +CONFIG_STACKTRACE=y # CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_HIGHMEM is not set # CONFIG_DEBUG_BUGVERBOSE is not set CONFIG_DEBUG_INFO=y # CONFIG_DEBUG_VM is not set # CONFIG_DEBUG_WRITECOUNT is not set +# CONFIG_DEBUG_MEMORY_INIT is not set # CONFIG_DEBUG_LIST is not set # CONFIG_DEBUG_SG is not set -CONFIG_FRAME_POINTER=y +# CONFIG_DEBUG_NOTIFIERS is not set # CONFIG_BOOT_PRINTK_DELAY is not set # CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_RCU_CPU_STALL_DETECTOR is not set # CONFIG_KPROBES_SANITY_TEST is not set # CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set # CONFIG_LKDTM is not set # CONFIG_FAULT_INJECTION is not set # CONFIG_LATENCYTOP is not set +CONFIG_SYSCTL_SYSCALL_CHECK=y +# CONFIG_PAGE_POISONING is not set +CONFIG_NOP_TRACER=y +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_RING_BUFFER=y +CONFIG_TRACING=y +CONFIG_TRACING_SUPPORT=y + +# +# Tracers +# +# CONFIG_FUNCTION_TRACER is not set +# CONFIG_IRQSOFF_TRACER is not set +# CONFIG_PREEMPT_TRACER is not set +# CONFIG_SCHED_TRACER is not set +# CONFIG_CONTEXT_SWITCH_TRACER is not set +# CONFIG_EVENT_TRACER is not set +# CONFIG_BOOT_TRACER is not set +# CONFIG_TRACE_BRANCH_PROFILING is not set +# CONFIG_STACK_TRACER is not set +# CONFIG_KMEMTRACE is not set +# CONFIG_WORKQUEUE_TRACER is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_FTRACE_STARTUP_TEST is not set +# CONFIG_DYNAMIC_DEBUG is not set # CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +CONFIG_ARM_UNWIND=y CONFIG_DEBUG_USER=y CONFIG_DEBUG_ERRORS=y # CONFIG_DEBUG_STACK_USAGE is not set @@ -1347,17 +1567,27 @@ CONFIG_DEBUG_LL=y # # CONFIG_KEYS is not set # CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set # CONFIG_SECURITY_FILE_CAPABILITIES is not set CONFIG_CRYPTO=y # # Crypto core or helper # +# CONFIG_CRYPTO_FIPS is not set CONFIG_CRYPTO_ALGAPI=m +CONFIG_CRYPTO_ALGAPI2=m +CONFIG_CRYPTO_AEAD2=m CONFIG_CRYPTO_BLKCIPHER=m +CONFIG_CRYPTO_BLKCIPHER2=m +CONFIG_CRYPTO_HASH2=m +CONFIG_CRYPTO_RNG2=m +CONFIG_CRYPTO_PCOMP=m CONFIG_CRYPTO_MANAGER=m +CONFIG_CRYPTO_MANAGER2=m # CONFIG_CRYPTO_GF128MUL is not set # CONFIG_CRYPTO_NULL is not set +CONFIG_CRYPTO_WORKQUEUE=m # CONFIG_CRYPTO_CRYPTD is not set # CONFIG_CRYPTO_AUTHENC is not set # CONFIG_CRYPTO_TEST is not set @@ -1393,6 +1623,10 @@ CONFIG_CRYPTO_PCBC=m # CONFIG_CRYPTO_MD4 is not set # CONFIG_CRYPTO_MD5 is not set # CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set # CONFIG_CRYPTO_SHA1 is not set # CONFIG_CRYPTO_SHA256 is not set # CONFIG_CRYPTO_SHA512 is not set @@ -1422,25 +1656,32 @@ CONFIG_CRYPTO_PCBC=m # Compression # # CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_ZLIB is not set # CONFIG_CRYPTO_LZO is not set + +# +# Random Number Generation +# +# CONFIG_CRYPTO_ANSI_CPRNG is not set CONFIG_CRYPTO_HW=y # CONFIG_CRYPTO_DEV_HIFN_795X is not set +CONFIG_BINARY_PRINTF=y # # Library routines # CONFIG_BITREVERSE=y -# CONFIG_GENERIC_FIND_FIRST_BIT is not set -# CONFIG_GENERIC_FIND_NEXT_BIT is not set +CONFIG_GENERIC_FIND_LAST_BIT=y # CONFIG_CRC_CCITT is not set -# CONFIG_CRC16 is not set +CONFIG_CRC16=m +# CONFIG_CRC_T10DIF is not set CONFIG_CRC_ITU_T=m CONFIG_CRC32=y # CONFIG_CRC7 is not set # CONFIG_LIBCRC32C is not set CONFIG_ZLIB_INFLATE=y CONFIG_ZLIB_DEFLATE=y -CONFIG_PLIST=y CONFIG_HAS_IOMEM=y CONFIG_HAS_IOPORT=y CONFIG_HAS_DMA=y +CONFIG_NLATTR=y diff --git a/arch/arm/configs/mx31moboard_defconfig b/arch/arm/configs/mx31moboard_defconfig deleted file mode 100644 index e90f86d6dee..00000000000 --- a/arch/arm/configs/mx31moboard_defconfig +++ /dev/null @@ -1,790 +0,0 @@ -# -# Automatically generated make config: don't edit -# Linux kernel version: 2.6.27-rc5 -# Fri Oct 24 11:41:22 2008 -# -CONFIG_ARM=y -CONFIG_SYS_SUPPORTS_APM_EMULATION=y -CONFIG_GENERIC_GPIO=y -CONFIG_GENERIC_TIME=y -CONFIG_GENERIC_CLOCKEVENTS=y -CONFIG_MMU=y -# CONFIG_NO_IOPORT is not set -CONFIG_GENERIC_HARDIRQS=y -CONFIG_STACKTRACE_SUPPORT=y -CONFIG_HAVE_LATENCYTOP_SUPPORT=y -CONFIG_LOCKDEP_SUPPORT=y -CONFIG_TRACE_IRQFLAGS_SUPPORT=y -CONFIG_HARDIRQS_SW_RESEND=y -CONFIG_GENERIC_IRQ_PROBE=y -CONFIG_RWSEM_GENERIC_SPINLOCK=y -# CONFIG_ARCH_HAS_ILOG2_U32 is not set -# CONFIG_ARCH_HAS_ILOG2_U64 is not set -CONFIG_GENERIC_HWEIGHT=y -CONFIG_GENERIC_CALIBRATE_DELAY=y -CONFIG_ARCH_SUPPORTS_AOUT=y -CONFIG_ZONE_DMA=y -CONFIG_ARCH_MTD_XIP=y -CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y -CONFIG_VECTORS_BASE=0xffff0000 -CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" - -# -# General setup -# -CONFIG_EXPERIMENTAL=y -CONFIG_BROKEN_ON_SMP=y -CONFIG_LOCK_KERNEL=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_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_SYSFS_DEPRECATED=y -CONFIG_SYSFS_DEPRECATED_V2=y -# CONFIG_RELAY is not set -# CONFIG_NAMESPACES is not set -# CONFIG_BLK_DEV_INITRD is not set -CONFIG_CC_OPTIMIZE_FOR_SIZE=y -CONFIG_SYSCTL=y -CONFIG_EMBEDDED=y -CONFIG_UID16=y -CONFIG_SYSCTL_SYSCALL=y -CONFIG_KALLSYMS=y -# CONFIG_KALLSYMS_EXTRA_PASS is not set -CONFIG_HOTPLUG=y -CONFIG_PRINTK=y -CONFIG_BUG=y -CONFIG_ELF_CORE=y -CONFIG_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_KPROBES is not set -# CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is not set -# CONFIG_HAVE_IOREMAP_PROT is not set -CONFIG_HAVE_KPROBES=y -CONFIG_HAVE_KRETPROBES=y -# CONFIG_HAVE_ARCH_TRACEHOOK is not set -# CONFIG_HAVE_DMA_ATTRS is not set -# CONFIG_USE_GENERIC_SMP_HELPERS is not set -# CONFIG_HAVE_CLK is not set -CONFIG_PROC_PAGE_MONITOR=y -CONFIG_HAVE_GENERIC_DMA_COHERENT=y -CONFIG_SLABINFO=y -CONFIG_RT_MUTEXES=y -# CONFIG_TINY_SHMEM is not set -CONFIG_BASE_SMALL=0 -CONFIG_MODULES=y -# CONFIG_MODULE_FORCE_LOAD is not set -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 is not set -# CONFIG_BLK_DEV_IO_TRACE is not set -# CONFIG_LSF is not set -# CONFIG_BLK_DEV_BSG is not set -# CONFIG_BLK_DEV_INTEGRITY 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 - -# -# System Type -# -# CONFIG_ARCH_AAEC2000 is not set -# CONFIG_ARCH_INTEGRATOR is not set -# CONFIG_ARCH_REALVIEW is not set -# CONFIG_ARCH_VERSATILE is not set -# CONFIG_ARCH_AT91 is not set -# CONFIG_ARCH_CLPS7500 is not set -# CONFIG_ARCH_CLPS711X is not set -# CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_EP93XX is not set -# CONFIG_ARCH_FOOTBRIDGE is not set -# CONFIG_ARCH_NETX is not set -# CONFIG_ARCH_H720X is not set -# CONFIG_ARCH_IMX is not set -# CONFIG_ARCH_IOP13XX is not set -# CONFIG_ARCH_IOP32X is not set -# CONFIG_ARCH_IOP33X is not set -# CONFIG_ARCH_IXP23XX is not set -# CONFIG_ARCH_IXP2000 is not set -# CONFIG_ARCH_IXP4XX is not set -# CONFIG_ARCH_L7200 is not set -# CONFIG_ARCH_KIRKWOOD is not set -# CONFIG_ARCH_KS8695 is not set -# CONFIG_ARCH_NS9XXX is not set -# CONFIG_ARCH_LOKI is not set -# CONFIG_ARCH_MV78XX0 is not set -CONFIG_ARCH_MXC=y -# CONFIG_ARCH_ORION5X is not set -# CONFIG_ARCH_PNX4008 is not set -# CONFIG_ARCH_PXA is not set -# CONFIG_ARCH_RPC is not set -# CONFIG_ARCH_SA1100 is not set -# CONFIG_ARCH_S3C2410 is not set -# CONFIG_ARCH_SHARK is not set -# CONFIG_ARCH_LH7A40X is not set -# CONFIG_ARCH_DAVINCI is not set -# CONFIG_ARCH_OMAP is not set -# CONFIG_ARCH_MSM7X00A is not set - -# -# Boot options -# - -# -# Power management -# - -# -# Freescale MXC Implementations -# -# CONFIG_ARCH_MX2 is not set -CONFIG_ARCH_MX3=y - -# -# MX3 Options -# -# CONFIG_MACH_MX31ADS is not set -# CONFIG_MACH_PCM037 is not set -# CONFIG_MACH_MX31LITE is not set -CONFIG_MACH_MX31MOBOARD=y -# CONFIG_MXC_IRQ_PRIOR is not set - -# -# Processor Type -# -CONFIG_CPU_32=y -CONFIG_CPU_V6=y -# CONFIG_CPU_32v6K is not set -CONFIG_CPU_32v6=y -CONFIG_CPU_ABRT_EV6=y -CONFIG_CPU_PABRT_NOIFAR=y -CONFIG_CPU_CACHE_V6=y -CONFIG_CPU_CACHE_VIPT=y -CONFIG_CPU_COPY_V6=y -CONFIG_CPU_TLB_V6=y -CONFIG_CPU_HAS_ASID=y -CONFIG_CPU_CP15=y -CONFIG_CPU_CP15_MMU=y - -# -# Processor Features -# -CONFIG_ARM_THUMB=y -# CONFIG_CPU_ICACHE_DISABLE is not set -# CONFIG_CPU_DCACHE_DISABLE is not set -# CONFIG_CPU_BPREDICT_DISABLE is not set -# CONFIG_OUTER_CACHE is not set - -# -# Bus support -# -# CONFIG_PCI_SYSCALL is not set -# CONFIG_ARCH_SUPPORTS_MSI is not set -# CONFIG_PCCARD is not set - -# -# Kernel Features -# -CONFIG_TICK_ONESHOT=y -CONFIG_NO_HZ=y -CONFIG_HIGH_RES_TIMERS=y -CONFIG_GENERIC_CLOCKEVENTS_BUILD=y -CONFIG_PREEMPT=y -CONFIG_HZ=100 -CONFIG_AEABI=y -# CONFIG_OABI_COMPAT is not set -CONFIG_ARCH_FLATMEM_HAS_HOLES=y -# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set -CONFIG_SELECT_MEMORY_MODEL=y -CONFIG_FLATMEM_MANUAL=y -# CONFIG_DISCONTIGMEM_MANUAL is not set -# CONFIG_SPARSEMEM_MANUAL is not set -CONFIG_FLATMEM=y -CONFIG_FLAT_NODE_MEM_MAP=y -# CONFIG_SPARSEMEM_STATIC is not set -# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set -CONFIG_PAGEFLAGS_EXTENDED=y -CONFIG_SPLIT_PTLOCK_CPUS=4 -# CONFIG_RESOURCES_64BIT is not set -CONFIG_ZONE_DMA_FLAG=1 -CONFIG_BOUNCE=y -CONFIG_VIRT_TO_BUS=y -CONFIG_ALIGNMENT_TRAP=y - -# -# Boot options -# -CONFIG_ZBOOT_ROM_TEXT=0x0 -CONFIG_ZBOOT_ROM_BSS=0x0 -CONFIG_CMDLINE="noinitrd console=ttymxc0,115200 root=/dev/mtdblock2 rw ip=off" -# CONFIG_XIP_KERNEL is not set -# CONFIG_KEXEC is not set - -# -# Floating point emulation -# - -# -# At least one emulation must be selected -# -CONFIG_VFP=y - -# -# Userspace binary formats -# -CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_AOUT is not set -# CONFIG_BINFMT_MISC is not set - -# -# Power management options -# -# CONFIG_PM is not set -CONFIG_ARCH_SUSPEND_POSSIBLE=y -CONFIG_NET=y - -# -# Networking options -# -CONFIG_PACKET=y -# CONFIG_PACKET_MMAP is not set -CONFIG_UNIX=y -# 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 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 is not set -# 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_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_UEVENT_HELPER_PATH="/sbin/hotplug" -CONFIG_STANDALONE=y -CONFIG_PREVENT_FIRMWARE_BUILD=y -CONFIG_FW_LOADER=m -CONFIG_FIRMWARE_IN_KERNEL=y -CONFIG_EXTRA_FIRMWARE="" -# CONFIG_SYS_HYPERVISOR is not set -# CONFIG_CONNECTOR is not set -CONFIG_MTD=y -# CONFIG_MTD_DEBUG is not set -# CONFIG_MTD_CONCAT is not set -CONFIG_MTD_PARTITIONS=y -CONFIG_MTD_REDBOOT_PARTS=y -CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1 -# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set -CONFIG_MTD_REDBOOT_PARTS_READONLY=y -# CONFIG_MTD_CMDLINE_PARTS is not set -# CONFIG_MTD_AFS_PARTS is not set -# CONFIG_MTD_AR7_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=y -CONFIG_MTD_CFI_NOSWAP=y -# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set -# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set -CONFIG_MTD_CFI_GEOMETRY=y -# CONFIG_MTD_MAP_BANK_WIDTH_1 is not set -CONFIG_MTD_MAP_BANK_WIDTH_2=y -# CONFIG_MTD_MAP_BANK_WIDTH_4 is not set -# 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 is not set -# CONFIG_MTD_CFI_I4 is not set -# CONFIG_MTD_CFI_I8 is not set -# CONFIG_MTD_OTP is not set -# CONFIG_MTD_CFI_INTELEXT is not set -CONFIG_MTD_CFI_AMDSTD=y -# CONFIG_MTD_CFI_STAA is not set -CONFIG_MTD_CFI_UTIL=y -# CONFIG_MTD_RAM is not set -# CONFIG_MTD_ROM is not set -# CONFIG_MTD_ABSENT is not set -# CONFIG_MTD_XIP is not set - -# -# Mapping drivers for chip access -# -# CONFIG_MTD_COMPLEX_MAPPINGS is not set -CONFIG_MTD_PHYSMAP=y -CONFIG_MTD_PHYSMAP_START=0x0 -CONFIG_MTD_PHYSMAP_LEN=0x0 -CONFIG_MTD_PHYSMAP_BANKWIDTH=2 -# CONFIG_MTD_ARM_INTEGRATOR is not set -# CONFIG_MTD_PLATRAM is not set - -# -# Self-contained MTD device drivers -# -# CONFIG_MTD_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 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 is not set -# CONFIG_SCSI_DMA is not set -# CONFIG_SCSI_NETLINK is not set -# CONFIG_ATA is not set -# CONFIG_MD is not set -CONFIG_NETDEVICES=y -# 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_SMC91X=y -# CONFIG_DM9000 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_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_IWLWIFI_LEDS 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 - -# -# Input device support -# -# CONFIG_INPUT is not set - -# -# Hardware I/O ports -# -# CONFIG_SERIO is not set -# CONFIG_GAMEPORT is not set - -# -# Character devices -# -# CONFIG_VT is not set -CONFIG_DEVKMEM=y -# CONFIG_SERIAL_NONSTANDARD is not set - -# -# Serial drivers -# -# CONFIG_SERIAL_8250 is not set - -# -# Non-8250 serial port support -# -CONFIG_SERIAL_IMX=y -CONFIG_SERIAL_IMX_CONSOLE=y -CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y -CONFIG_UNIX98_PTYS=y -# CONFIG_LEGACY_PTYS is not set -# CONFIG_IPMI_HANDLER is not set -# CONFIG_HW_RANDOM is not set -# CONFIG_NVRAM is not set -# CONFIG_R3964 is not set -# CONFIG_RAW_DRIVER is not set -# CONFIG_TCG_TPM is not set -# CONFIG_I2C is not set -# CONFIG_SPI is not set -CONFIG_ARCH_REQUIRE_GPIOLIB=y -CONFIG_GPIOLIB=y -# CONFIG_GPIO_SYSFS is not set - -# -# I2C GPIO expanders: -# - -# -# PCI GPIO expanders: -# - -# -# SPI GPIO expanders: -# -# 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_CORE is not set -# CONFIG_MFD_SM501 is not set -# CONFIG_HTC_EGPIO is not set -# CONFIG_HTC_PASIC3 is not set -# CONFIG_MFD_TMIO is not set -# CONFIG_MFD_T7L66XB is not set -# CONFIG_MFD_TC6387XB is not set -# CONFIG_MFD_TC6393XB is not set - -# -# Multimedia devices -# - -# -# Multimedia core support -# -# CONFIG_VIDEO_DEV is not set -# CONFIG_DVB_CORE is not set -# CONFIG_VIDEO_MEDIA is not set - -# -# Multimedia drivers -# -# 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 -# CONFIG_SOUND is not set -# CONFIG_USB_SUPPORT is not set -# CONFIG_MMC is not set -# CONFIG_NEW_LEDS is not set -CONFIG_RTC_LIB=y -# CONFIG_RTC_CLASS is not set -# CONFIG_DMADEVICES is not set - -# -# Voltage and Current regulators -# -# CONFIG_REGULATOR is not set -# CONFIG_REGULATOR_FIXED_VOLTAGE is not set -# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set -# CONFIG_REGULATOR_BQ24022 is not set -# 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_OCFS2_FS is not set -# CONFIG_DNOTIFY is not set -CONFIG_INOTIFY=y -CONFIG_INOTIFY_USER=y -# CONFIG_QUOTA is not set -# CONFIG_AUTOFS_FS is not set -# CONFIG_AUTOFS4_FS is not set -# CONFIG_FUSE_FS is not set - -# -# CD-ROM/DVD Filesystems -# -# CONFIG_ISO9660_FS is not set -# CONFIG_UDF_FS is not set - -# -# DOS/FAT/NT Filesystems -# -# CONFIG_MSDOS_FS is not set -# CONFIG_VFAT_FS is not set -# CONFIG_NTFS_FS is not set - -# -# Pseudo filesystems -# -CONFIG_PROC_FS=y -CONFIG_PROC_SYSCTL=y -CONFIG_SYSFS=y -CONFIG_TMPFS=y -# CONFIG_TMPFS_POSIX_ACL 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_JFFS2_FS=y -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 is not set -# 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 is not set -# CONFIG_VXFS_FS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_OMFS_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 is not set -# CONFIG_NFS_V4 is not set -CONFIG_ROOT_NFS=y -# CONFIG_NFSD is not set -CONFIG_LOCKD=y -CONFIG_NFS_COMMON=y -CONFIG_SUNRPC=y -# CONFIG_RPCSEC_GSS_KRB5 is not set -# CONFIG_RPCSEC_GSS_SPKM3 is not set -# CONFIG_SMB_FS 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 is not set -CONFIG_MSDOS_PARTITION=y -# CONFIG_NLS is not set -# CONFIG_DLM is not set - -# -# Kernel hacking -# -# CONFIG_PRINTK_TIME is not set -# CONFIG_ENABLE_WARN_DEPRECATED is not set -# CONFIG_ENABLE_MUST_CHECK is not set -CONFIG_FRAME_WARN=1024 -# 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_DEBUG_BUGVERBOSE is not set -# CONFIG_DEBUG_MEMORY_INIT is not set -CONFIG_FRAME_POINTER=y -# CONFIG_LATENCYTOP is not set -CONFIG_SYSCTL_SYSCALL_CHECK=y -CONFIG_HAVE_FTRACE=y -CONFIG_HAVE_DYNAMIC_FTRACE=y -# CONFIG_FTRACE is not set -# CONFIG_IRQSOFF_TRACER is not set -# CONFIG_PREEMPT_TRACER is not set -# CONFIG_SCHED_TRACER is not set -# CONFIG_CONTEXT_SWITCH_TRACER is not set -# CONFIG_SAMPLES is not set -CONFIG_HAVE_ARCH_KGDB=y -# CONFIG_DEBUG_USER is not set - -# -# Security options -# -# CONFIG_KEYS is not set -# CONFIG_SECURITY is not set -# CONFIG_SECURITY_FILE_CAPABILITIES is not set -# CONFIG_CRYPTO is not set - -# -# Library routines -# -CONFIG_BITREVERSE=y -# CONFIG_GENERIC_FIND_FIRST_BIT is not set -# CONFIG_GENERIC_FIND_NEXT_BIT is not set -# CONFIG_CRC_CCITT is not set -# CONFIG_CRC16 is not set -# CONFIG_CRC_T10DIF is not set -# CONFIG_CRC_ITU_T is not set -CONFIG_CRC32=y -# CONFIG_CRC7 is not set -# CONFIG_LIBCRC32C is not set -CONFIG_ZLIB_INFLATE=y -CONFIG_ZLIB_DEFLATE=y -CONFIG_PLIST=y -CONFIG_HAS_IOMEM=y -CONFIG_HAS_IOPORT=y -CONFIG_HAS_DMA=y diff --git a/arch/arm/configs/mx3_defconfig b/arch/arm/configs/mx3_defconfig index 72a8201a537..20ada526f6d 100644 --- a/arch/arm/configs/mx3_defconfig +++ b/arch/arm/configs/mx3_defconfig @@ -197,7 +197,7 @@ CONFIG_MXC_PWM=y # CONFIG_CPU_32=y CONFIG_CPU_V6=y -CONFIG_CPU_32v6K=y +# CONFIG_CPU_32v6K is not set CONFIG_CPU_32v6=y CONFIG_CPU_ABRT_EV6=y CONFIG_CPU_PABRT_NOIFAR=y diff --git a/arch/arm/configs/orion5x_defconfig b/arch/arm/configs/orion5x_defconfig index 020e6a8a9e5..5b98f764511 100644 --- a/arch/arm/configs/orion5x_defconfig +++ b/arch/arm/configs/orion5x_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.27-rc4 -# Fri Aug 22 12:38:51 2008 +# Linux kernel version: 2.6.30-rc4 +# Mon May 4 14:07:25 2009 # CONFIG_ARM=y CONFIG_SYS_SUPPORTS_APM_EMULATION=y @@ -22,8 +22,6 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y # CONFIG_ARCH_HAS_ILOG2_U64 is not set CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_CALIBRATE_DELAY=y -CONFIG_ARCH_SUPPORTS_AOUT=y -CONFIG_ZONE_DMA=y CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y CONFIG_VECTORS_BASE=0xffff0000 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" @@ -44,10 +42,19 @@ CONFIG_SYSVIPC_SYSCTL=y # CONFIG_BSD_PROCESS_ACCT is not set # CONFIG_TASKSTATS is not set # CONFIG_AUDIT is not set + +# +# RCU Subsystem +# +CONFIG_CLASSIC_RCU=y +# CONFIG_TREE_RCU is not set +# CONFIG_PREEMPT_RCU is not set +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_PREEMPT_RCU_TRACE is not set # CONFIG_IKCONFIG is not set CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_CGROUPS is not set # CONFIG_GROUP_SCHED is not set +# CONFIG_CGROUPS is not set CONFIG_SYSFS_DEPRECATED=y CONFIG_SYSFS_DEPRECATED_V2=y # CONFIG_RELAY is not set @@ -55,48 +62,45 @@ CONFIG_SYSFS_DEPRECATED_V2=y # CONFIG_BLK_DEV_INITRD is not set CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y CONFIG_EMBEDDED=y CONFIG_UID16=y CONFIG_SYSCTL_SYSCALL=y CONFIG_KALLSYMS=y CONFIG_KALLSYMS_ALL=y # CONFIG_KALLSYMS_EXTRA_PASS is not set +# CONFIG_STRIP_ASM_SYMS 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_AIO=y CONFIG_VM_EVENT_COUNTERS=y +CONFIG_PCI_QUIRKS=y # CONFIG_SLUB_DEBUG is not set +CONFIG_COMPAT_BRK=y # CONFIG_SLAB is not set CONFIG_SLUB=y # CONFIG_SLOB is not set CONFIG_PROFILING=y +CONFIG_TRACEPOINTS=y # CONFIG_MARKERS is not set CONFIG_OPROFILE=y CONFIG_HAVE_OPROFILE=y CONFIG_KPROBES=y -# CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is not set CONFIG_KRETPROBES=y -# CONFIG_HAVE_IOREMAP_PROT is not set CONFIG_HAVE_KPROBES=y CONFIG_HAVE_KRETPROBES=y -# CONFIG_HAVE_ARCH_TRACEHOOK is not set -# CONFIG_HAVE_DMA_ATTRS is not set -# CONFIG_USE_GENERIC_SMP_HELPERS is not set -# CONFIG_HAVE_CLK is not set -CONFIG_PROC_PAGE_MONITOR=y +# CONFIG_SLOW_WORK is not set CONFIG_HAVE_GENERIC_DMA_COHERENT=y CONFIG_RT_MUTEXES=y -# CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 CONFIG_MODULES=y # CONFIG_MODULE_FORCE_LOAD is not set @@ -104,11 +108,8 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_FORCE_UNLOAD is not set # CONFIG_MODVERSIONS is not set # CONFIG_MODULE_SRCVERSION_ALL is not set -CONFIG_KMOD=y 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 # CONFIG_BLK_DEV_INTEGRITY is not set @@ -124,7 +125,7 @@ CONFIG_IOSCHED_CFQ=y CONFIG_DEFAULT_CFQ=y # CONFIG_DEFAULT_NOOP is not set CONFIG_DEFAULT_IOSCHED="cfq" -CONFIG_CLASSIC_RCU=y +# CONFIG_FREEZER is not set # # System Type @@ -134,10 +135,10 @@ CONFIG_CLASSIC_RCU=y # CONFIG_ARCH_REALVIEW is not set # CONFIG_ARCH_VERSATILE is not set # CONFIG_ARCH_AT91 is not set -# CONFIG_ARCH_CLPS7500 is not set # CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_EBSA110 is not set # CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_GEMINI is not set # CONFIG_ARCH_FOOTBRIDGE is not set # CONFIG_ARCH_NETX is not set # CONFIG_ARCH_H720X is not set @@ -158,14 +159,17 @@ CONFIG_CLASSIC_RCU=y CONFIG_ARCH_ORION5X=y # CONFIG_ARCH_PNX4008 is not set # CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_MMP is not set # CONFIG_ARCH_RPC is not set # CONFIG_ARCH_SA1100 is not set # CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_S3C64XX is not set # CONFIG_ARCH_SHARK is not set # CONFIG_ARCH_LH7A40X is not set # CONFIG_ARCH_DAVINCI is not set # CONFIG_ARCH_OMAP is not set -# CONFIG_ARCH_MSM7X00A is not set +# CONFIG_ARCH_MSM is not set +# CONFIG_ARCH_W90X900 is not set # # Orion Implementations @@ -175,6 +179,7 @@ CONFIG_MACH_RD88F5182=y CONFIG_MACH_KUROBOX_PRO=y CONFIG_MACH_DNS323=y CONFIG_MACH_TS209=y +CONFIG_MACH_TERASTATION_PRO2=y CONFIG_MACH_LINKSTATION_PRO=y CONFIG_MACH_LINKSTATION_MINI=y CONFIG_MACH_TS409=y @@ -187,14 +192,6 @@ CONFIG_MACH_WNR854T=y CONFIG_MACH_RD88F5181L_GE=y CONFIG_MACH_RD88F5181L_FXO=y CONFIG_MACH_RD88F6183AP_GE=y - -# -# Boot options -# - -# -# Power management -# CONFIG_PLAT_ORION=y # @@ -228,6 +225,8 @@ CONFIG_PCI_SYSCALL=y # CONFIG_ARCH_SUPPORTS_MSI is not set CONFIG_PCI_LEGACY=y # CONFIG_PCI_DEBUG is not set +# CONFIG_PCI_STUB is not set +# CONFIG_PCI_IOV is not set # CONFIG_PCCARD is not set # @@ -237,25 +236,32 @@ CONFIG_TICK_ONESHOT=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_VMSPLIT_3G=y +# CONFIG_VMSPLIT_2G is not set +# CONFIG_VMSPLIT_1G is not set +CONFIG_PAGE_OFFSET=0xC0000000 CONFIG_PREEMPT=y CONFIG_HZ=100 CONFIG_AEABI=y CONFIG_OABI_COMPAT=y -# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set +CONFIG_ARCH_FLATMEM_HAS_HOLES=y +# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set +# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set +# CONFIG_HIGHMEM is not set CONFIG_SELECT_MEMORY_MODEL=y CONFIG_FLATMEM_MANUAL=y # CONFIG_DISCONTIGMEM_MANUAL is not set # CONFIG_SPARSEMEM_MANUAL is not set CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y -# CONFIG_SPARSEMEM_STATIC is not set -# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=4096 -# CONFIG_RESOURCES_64BIT is not set -CONFIG_ZONE_DMA_FLAG=1 -CONFIG_BOUNCE=y +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 CONFIG_VIRT_TO_BUS=y +CONFIG_UNEVICTABLE_LRU=y +CONFIG_HAVE_MLOCK=y +CONFIG_HAVE_MLOCKED_PAGE_BIT=y CONFIG_LEDS=y CONFIG_LEDS_CPU=y CONFIG_ALIGNMENT_TRAP=y @@ -270,6 +276,11 @@ CONFIG_CMDLINE="" # CONFIG_KEXEC is not set # +# CPU Power Management +# +# CONFIG_CPU_IDLE is not set + +# # Floating point emulation # @@ -285,13 +296,18 @@ CONFIG_VFP=y # Userspace binary formats # CONFIG_BINFMT_ELF=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_HAVE_AOUT=y # CONFIG_BINFMT_AOUT is not set # CONFIG_BINFMT_MISC is not set # # Power management options # -# CONFIG_PM is not set +CONFIG_PM=y +# CONFIG_PM_DEBUG is not set +# CONFIG_SUSPEND is not set +# CONFIG_APM_EMULATION is not set CONFIG_ARCH_SUSPEND_POSSIBLE=y CONFIG_NET=y @@ -328,7 +344,7 @@ CONFIG_IP_PNP_BOOTP=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_LRO=y CONFIG_INET_DIAG=y CONFIG_INET_TCP_DIAG=y # CONFIG_TCP_CONG_ADVANCED is not set @@ -343,6 +359,15 @@ CONFIG_DEFAULT_TCP_CONG="cubic" # CONFIG_TIPC is not set # CONFIG_ATM is not set # CONFIG_BRIDGE is not set +CONFIG_NET_DSA=y +CONFIG_NET_DSA_TAG_DSA=y +CONFIG_NET_DSA_TAG_EDSA=y +# CONFIG_NET_DSA_TAG_TRAILER is not set +CONFIG_NET_DSA_MV88E6XXX=y +# CONFIG_NET_DSA_MV88E6060 is not set +CONFIG_NET_DSA_MV88E6XXX_NEED_PPU=y +CONFIG_NET_DSA_MV88E6131=y +CONFIG_NET_DSA_MV88E6123_61_65=y # CONFIG_VLAN_8021Q is not set # CONFIG_DECNET is not set # CONFIG_LLC2 is not set @@ -352,27 +377,29 @@ CONFIG_DEFAULT_TCP_CONG="cubic" # CONFIG_LAPB is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set +# CONFIG_PHONET is not set # CONFIG_NET_SCHED is not set +# CONFIG_DCB is not set # # Network testing # CONFIG_NET_PKTGEN=m # CONFIG_NET_TCPPROBE is not set +# CONFIG_NET_DROP_MONITOR 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_WIRELESS=y # CONFIG_CFG80211 is not set +# CONFIG_WIRELESS_OLD_REGULATORY is not set CONFIG_WIRELESS_EXT=y CONFIG_WIRELESS_EXT_SYSFS=y +# CONFIG_LIB80211 is not set # CONFIG_MAC80211 is not set -# CONFIG_IEEE80211 is not set +# CONFIG_WIMAX is not set # CONFIG_RFKILL is not set # CONFIG_NET_9P is not set @@ -397,6 +424,7 @@ CONFIG_MTD=y # CONFIG_MTD_DEBUG is not set # CONFIG_MTD_CONCAT is not set CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_TESTS is not set # CONFIG_MTD_REDBOOT_PARTS is not set CONFIG_MTD_CMDLINE_PARTS=y # CONFIG_MTD_AFS_PARTS is not set @@ -450,9 +478,7 @@ CONFIG_MTD_CFI_UTIL=y # # CONFIG_MTD_COMPLEX_MAPPINGS is not set CONFIG_MTD_PHYSMAP=y -CONFIG_MTD_PHYSMAP_START=0x0 -CONFIG_MTD_PHYSMAP_LEN=0x0 -CONFIG_MTD_PHYSMAP_BANKWIDTH=0 +# CONFIG_MTD_PHYSMAP_COMPAT is not set # CONFIG_MTD_ARM_INTEGRATOR is not set # CONFIG_MTD_IMPA7 is not set # CONFIG_MTD_INTEL_VR_NOR is not set @@ -477,6 +503,7 @@ CONFIG_MTD_NAND=y CONFIG_MTD_NAND_VERIFY_WRITE=y # CONFIG_MTD_NAND_ECC_SMC is not set # CONFIG_MTD_NAND_MUSEUM_IDS is not set +# CONFIG_MTD_NAND_GPIO is not set CONFIG_MTD_NAND_IDS=y # CONFIG_MTD_NAND_DISKONCHIP is not set # CONFIG_MTD_NAND_CAFE is not set @@ -487,6 +514,11 @@ CONFIG_MTD_NAND_ORION=y # CONFIG_MTD_ONENAND is not set # +# LPDDR flash memory drivers +# +# CONFIG_MTD_LPDDR is not set + +# # UBI - Unsorted block images # # CONFIG_MTD_UBI is not set @@ -507,11 +539,20 @@ CONFIG_BLK_DEV_LOOP=y # CONFIG_ATA_OVER_ETH is not set 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_ICS932S401 is not set # CONFIG_ENCLOSURE_SERVICES is not set # CONFIG_HP_ILO is not set +# CONFIG_ISL29003 is not set +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +# CONFIG_EEPROM_AT24 is not set +# CONFIG_EEPROM_LEGACY is not set +# CONFIG_EEPROM_93CX6 is not set CONFIG_HAVE_IDE=y # CONFIG_IDE is not set @@ -569,7 +610,11 @@ CONFIG_SCSI_LOWLEVEL=y # CONFIG_MEGARAID_NEWGEN is not set # CONFIG_MEGARAID_LEGACY is not set # CONFIG_MEGARAID_SAS is not set +# CONFIG_SCSI_MPT2SAS is not set # CONFIG_SCSI_HPTIOP is not set +# CONFIG_LIBFC is not set +# CONFIG_LIBFCOE is not set +# CONFIG_FCOE is not set # CONFIG_SCSI_DMX3191D is not set # CONFIG_SCSI_FUTURE_DOMAIN is not set # CONFIG_SCSI_IPS is not set @@ -589,6 +634,7 @@ CONFIG_SCSI_LOWLEVEL=y # CONFIG_SCSI_DEBUG is not set # CONFIG_SCSI_SRP is not set # CONFIG_SCSI_DH is not set +# CONFIG_SCSI_OSD_INITIATOR is not set CONFIG_ATA=y # CONFIG_ATA_NONSTANDARD is not set CONFIG_SATA_PMP=y @@ -663,6 +709,7 @@ CONFIG_SATA_MV=y # CONFIG_IEEE1394 is not set # CONFIG_I2O is not set CONFIG_NETDEVICES=y +CONFIG_COMPAT_NET_DEV_OPS=y # CONFIG_DUMMY is not set # CONFIG_BONDING is not set # CONFIG_MACVLAN is not set @@ -670,7 +717,26 @@ CONFIG_NETDEVICES=y # CONFIG_TUN is not set # CONFIG_VETH is not set # CONFIG_ARCNET is not set -# CONFIG_PHYLIB is not set +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +CONFIG_MARVELL_PHY=y +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set +# CONFIG_VITESSE_PHY is not set +# CONFIG_SMSC_PHY is not set +# CONFIG_BROADCOM_PHY is not set +# CONFIG_ICPLUS_PHY is not set +# CONFIG_REALTEK_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_LSI_ET1011C_PHY is not set +# CONFIG_FIXED_PHY is not set +# CONFIG_MDIO_BITBANG is not set CONFIG_NET_ETHERNET=y CONFIG_MII=y # CONFIG_AX88796 is not set @@ -680,19 +746,25 @@ CONFIG_MII=y # CONFIG_NET_VENDOR_3COM is not set # CONFIG_SMC91X is not set # CONFIG_DM9000 is not set +# CONFIG_ETHOC is not set +# CONFIG_SMC911X is not set +# CONFIG_SMSC911X is not set +# CONFIG_DNET 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_IBM_NEW_EMAC_NO_FLOW_CTRL is not set +# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set +# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR 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_EEPRO100 is not set # CONFIG_E100 is not set # CONFIG_FEALNX is not set # CONFIG_NATSEMI is not set @@ -702,10 +774,12 @@ CONFIG_NET_PCI=y # CONFIG_R6040 is not set # CONFIG_SIS900 is not set # CONFIG_EPIC100 is not set +# CONFIG_SMSC9420 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_ATL2 is not set CONFIG_NETDEV_1000=y # CONFIG_ACENIC is not set # CONFIG_DL2K is not set @@ -713,6 +787,7 @@ CONFIG_NETDEV_1000=y # CONFIG_E1000E is not set # CONFIG_IP1000 is not set # CONFIG_IGB is not set +# CONFIG_IGBVF is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set @@ -727,6 +802,8 @@ CONFIG_MV643XX_ETH=y # CONFIG_QLA3XXX is not set # CONFIG_ATL1 is not set # CONFIG_ATL1E is not set +# CONFIG_ATL1C is not set +# CONFIG_JME is not set # CONFIG_NETDEV_10000 is not set # CONFIG_TR is not set @@ -735,7 +812,10 @@ CONFIG_MV643XX_ETH=y # # CONFIG_WLAN_PRE80211 is not set # CONFIG_WLAN_80211 is not set -# CONFIG_IWLWIFI_LEDS is not set + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# # # USB Network Adapters @@ -819,11 +899,11 @@ CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y # CONFIG_SERIAL_JSM is not set CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=16 # CONFIG_IPMI_HANDLER is not set # CONFIG_HW_RANDOM is not set -# CONFIG_NVRAM is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set # CONFIG_RAW_DRIVER is not set @@ -886,12 +966,9 @@ CONFIG_I2C_MV64XXX=y # Miscellaneous I2C Chip support # # CONFIG_DS1682 is not set -# CONFIG_EEPROM_AT24 is not set -# CONFIG_EEPROM_LEGACY 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_SENSORS_MAX6875 is not set # CONFIG_SENSORS_TSL2550 is not set # CONFIG_I2C_DEBUG_CORE is not set @@ -911,14 +988,17 @@ CONFIG_HWMON=y # CONFIG_SENSORS_ADM1029 is not set # CONFIG_SENSORS_ADM1031 is not set # CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ADT7462 is not set # CONFIG_SENSORS_ADT7470 is not set # CONFIG_SENSORS_ADT7473 is not set +# CONFIG_SENSORS_ADT7475 is not set # CONFIG_SENSORS_ATXP1 is not set # CONFIG_SENSORS_DS1621 is not set # CONFIG_SENSORS_I5K_AMB is not set # CONFIG_SENSORS_F71805F is not set # CONFIG_SENSORS_F71882FG is not set # CONFIG_SENSORS_F75375S is not set +# CONFIG_SENSORS_G760A is not set # CONFIG_SENSORS_GL518SM is not set # CONFIG_SENSORS_GL520SM is not set # CONFIG_SENSORS_IT87 is not set @@ -933,10 +1013,15 @@ CONFIG_SENSORS_LM75=y # CONFIG_SENSORS_LM90 is not set # CONFIG_SENSORS_LM92 is not set # CONFIG_SENSORS_LM93 is not set +# CONFIG_SENSORS_LTC4215 is not set +# CONFIG_SENSORS_LTC4245 is not set +# CONFIG_SENSORS_LM95241 is not set # CONFIG_SENSORS_MAX1619 is not set # CONFIG_SENSORS_MAX6650 is not set # CONFIG_SENSORS_PC87360 is not set # CONFIG_SENSORS_PC87427 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_SHT15 is not set # CONFIG_SENSORS_SIS5595 is not set # CONFIG_SENSORS_DME1737 is not set # CONFIG_SENSORS_SMSC47M1 is not set @@ -956,12 +1041,14 @@ CONFIG_SENSORS_LM75=y # 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_THERMAL_HWMON is not set # CONFIG_WATCHDOG is not set +CONFIG_SSB_POSSIBLE=y # # Sonics Silicon Backplane # -CONFIG_SSB_POSSIBLE=y # CONFIG_SSB is not set # @@ -970,9 +1057,12 @@ CONFIG_SSB_POSSIBLE=y # CONFIG_MFD_CORE is not set # CONFIG_MFD_SM501 is not set # CONFIG_HTC_PASIC3 is not set +# CONFIG_TWL4030_CORE is not set # CONFIG_MFD_TMIO is not set -# CONFIG_MFD_T7L66XB is not set -# CONFIG_MFD_TC6387XB is not set +# CONFIG_PMIC_DA903X is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_PCF50633 is not set # # Multimedia devices @@ -1013,9 +1103,36 @@ CONFIG_HID=y # USB Input Devices # CONFIG_USB_HID=y -# CONFIG_USB_HIDINPUT_POWERBOOK is not set -# CONFIG_HID_FF is not set +# CONFIG_HID_PID is not set # CONFIG_USB_HIDDEV is not set + +# +# Special HID drivers +# +# CONFIG_HID_A4TECH is not set +# CONFIG_HID_APPLE is not set +# CONFIG_HID_BELKIN is not set +# CONFIG_HID_CHERRY is not set +# CONFIG_HID_CHICONY is not set +# CONFIG_HID_CYPRESS is not set +# CONFIG_DRAGONRISE_FF is not set +# CONFIG_HID_EZKEY is not set +# CONFIG_HID_KYE is not set +# CONFIG_HID_GYRATION is not set +# CONFIG_HID_KENSINGTON is not set +# CONFIG_HID_LOGITECH is not set +# CONFIG_HID_MICROSOFT is not set +# CONFIG_HID_MONTEREY is not set +# CONFIG_HID_NTRIG is not set +# CONFIG_HID_PANTHERLORD is not set +# CONFIG_HID_PETALYNX is not set +# CONFIG_HID_SAMSUNG is not set +# CONFIG_HID_SONY is not set +# CONFIG_HID_SUNPLUS is not set +# CONFIG_GREENASIA_FF is not set +# CONFIG_HID_TOPSEED is not set +# CONFIG_THRUSTMASTER_FF is not set +# CONFIG_ZEROPLUS_FF is not set CONFIG_USB_SUPPORT=y CONFIG_USB_ARCH_HAS_HCD=y CONFIG_USB_ARCH_HAS_OHCI=y @@ -1030,10 +1147,13 @@ CONFIG_USB=y CONFIG_USB_DEVICEFS=y CONFIG_USB_DEVICE_CLASS=y # CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_SUSPEND is not set # CONFIG_USB_OTG is not set # CONFIG_USB_OTG_WHITELIST is not set # CONFIG_USB_OTG_BLACKLIST_HUB is not set # CONFIG_USB_MON is not set +# CONFIG_USB_WUSB is not set +# CONFIG_USB_WUSB_CBAF is not set # # USB Host Controller Drivers @@ -1042,12 +1162,15 @@ CONFIG_USB_DEVICE_CLASS=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_ROOT_HUB_TT=y CONFIG_USB_EHCI_TT_NEWSCHED=y +# CONFIG_USB_OXU210HP_HCD is not set # CONFIG_USB_ISP116X_HCD is not set # CONFIG_USB_ISP1760_HCD is not set # CONFIG_USB_OHCI_HCD is not set # CONFIG_USB_UHCI_HCD is not set # CONFIG_USB_SL811_HCD is not set # CONFIG_USB_R8A66597_HCD is not set +# CONFIG_USB_WHCI_HCD is not set +# CONFIG_USB_HWA_HCD is not set # # USB Device Class drivers @@ -1055,20 +1178,20 @@ CONFIG_USB_EHCI_TT_NEWSCHED=y # CONFIG_USB_ACM is not set CONFIG_USB_PRINTER=y # CONFIG_USB_WDM is not set +# CONFIG_USB_TMC is not set # -# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may # # -# may also be needed; see USB_STORAGE Help for more information +# also be needed; see USB_STORAGE Help for more info # 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 is not set CONFIG_USB_STORAGE_SDDR09=y CONFIG_USB_STORAGE_SDDR55=y @@ -1076,7 +1199,6 @@ CONFIG_USB_STORAGE_JUMPSHOT=y # CONFIG_USB_STORAGE_ALAUDA is not set # CONFIG_USB_STORAGE_ONETOUCH is not set # CONFIG_USB_STORAGE_KARMA is not set -# CONFIG_USB_STORAGE_SIERRA is not set # CONFIG_USB_STORAGE_CYPRESS_ATACB is not set # CONFIG_USB_LIBUSUAL is not set @@ -1097,6 +1219,7 @@ CONFIG_USB_STORAGE_JUMPSHOT=y # CONFIG_USB_EMI62 is not set # CONFIG_USB_EMI26 is not set # CONFIG_USB_ADUTUX is not set +# CONFIG_USB_SEVSEG is not set # CONFIG_USB_RIO500 is not set # CONFIG_USB_LEGOTOWER is not set # CONFIG_USB_LCD is not set @@ -1104,7 +1227,6 @@ CONFIG_USB_STORAGE_JUMPSHOT=y # 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 @@ -1114,8 +1236,18 @@ CONFIG_USB_STORAGE_JUMPSHOT=y # CONFIG_USB_IOWARRIOR is not set # CONFIG_USB_TEST is not set # CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_VST is not set # CONFIG_USB_GADGET is not set + +# +# OTG and related infrastructure +# +# CONFIG_USB_GPIO_VBUS is not set +# CONFIG_NOP_USB_XCEIV is not set +# CONFIG_UWB is not set # CONFIG_MMC is not set +# CONFIG_MEMSTICK is not set +# CONFIG_ACCESSIBILITY is not set CONFIG_NEW_LEDS=y CONFIG_LEDS_CLASS=y @@ -1124,7 +1256,10 @@ CONFIG_LEDS_CLASS=y # # CONFIG_LEDS_PCA9532 is not set CONFIG_LEDS_GPIO=y +CONFIG_LEDS_GPIO_PLATFORM=y +# CONFIG_LEDS_LP5521 is not set # CONFIG_LEDS_PCA955X is not set +# CONFIG_LEDS_BD2802 is not set # # LED Triggers @@ -1132,7 +1267,12 @@ CONFIG_LEDS_GPIO=y CONFIG_LEDS_TRIGGERS=y CONFIG_LEDS_TRIGGER_TIMER=y CONFIG_LEDS_TRIGGER_HEARTBEAT=y +# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set CONFIG_LEDS_TRIGGER_DEFAULT_ON=y + +# +# iptables trigger is under Netfilter config (LED target) +# CONFIG_RTC_LIB=y CONFIG_RTC_CLASS=y CONFIG_RTC_HCTOSYS=y @@ -1164,6 +1304,7 @@ CONFIG_RTC_DRV_M41T80=y # CONFIG_RTC_DRV_M41T80_WDT is not set CONFIG_RTC_DRV_S35390A=y # CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_RX8581 is not set # # SPI RTC drivers @@ -1173,12 +1314,15 @@ CONFIG_RTC_DRV_S35390A=y # Platform RTC drivers # # CONFIG_RTC_DRV_CMOS is not set +# CONFIG_RTC_DRV_DS1286 is not set # CONFIG_RTC_DRV_DS1511 is not set # CONFIG_RTC_DRV_DS1553 is not set # CONFIG_RTC_DRV_DS1742 is not set # CONFIG_RTC_DRV_STK17TA8 is not set CONFIG_RTC_DRV_M48T86=y +# CONFIG_RTC_DRV_M48T35 is not set # CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_BQ4802 is not set # CONFIG_RTC_DRV_V3020 is not set # @@ -1196,16 +1340,12 @@ CONFIG_DMA_ENGINE=y # DMA Clients # # CONFIG_NET_DMA is not set +# CONFIG_ASYNC_TX_DMA is not set # CONFIG_DMATEST is not set - -# -# Voltage and Current regulators -# +# CONFIG_AUXDISPLAY is not set # CONFIG_REGULATOR is not set -# CONFIG_REGULATOR_FIXED_VOLTAGE is not set -# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set -# CONFIG_REGULATOR_BQ24022 is not set # CONFIG_UIO is not set +# CONFIG_STAGING is not set # # File systems @@ -1214,14 +1354,25 @@ CONFIG_EXT2_FS=y # CONFIG_EXT2_FS_XATTR is not set # CONFIG_EXT2_FS_XIP is not set CONFIG_EXT3_FS=y +# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set # CONFIG_EXT3_FS_XATTR is not set -# CONFIG_EXT4DEV_FS is not set +CONFIG_EXT4_FS=m +# CONFIG_EXT4DEV_COMPAT is not set +CONFIG_EXT4_FS_XATTR=y +# CONFIG_EXT4_FS_POSIX_ACL is not set +# CONFIG_EXT4_FS_SECURITY is not set CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_JBD2=m +# CONFIG_JBD2_DEBUG is not set +CONFIG_FS_MBCACHE=m # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set # CONFIG_FS_POSIX_ACL is not set +CONFIG_FILE_LOCKING=y # CONFIG_XFS_FS is not set # CONFIG_OCFS2_FS is not set +# CONFIG_BTRFS_FS is not set CONFIG_DNOTIFY=y CONFIG_INOTIFY=y CONFIG_INOTIFY_USER=y @@ -1231,6 +1382,11 @@ CONFIG_INOTIFY_USER=y # CONFIG_FUSE_FS is not set # +# Caches +# +# CONFIG_FSCACHE is not set + +# # CD-ROM/DVD Filesystems # CONFIG_ISO9660_FS=m @@ -1254,15 +1410,13 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" # CONFIG_PROC_FS=y CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y CONFIG_SYSFS=y CONFIG_TMPFS=y # CONFIG_TMPFS_POSIX_ACL is not set # CONFIG_HUGETLB_PAGE is not set # CONFIG_CONFIGFS_FS is not set - -# -# Miscellaneous filesystems -# +CONFIG_MISC_FILESYSTEMS=y # CONFIG_ADFS_FS is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set @@ -1282,6 +1436,7 @@ CONFIG_JFFS2_ZLIB=y CONFIG_JFFS2_RTIME=y # CONFIG_JFFS2_RUBIN is not set CONFIG_CRAMFS=y +# CONFIG_SQUASHFS is not set # CONFIG_VXFS_FS is not set # CONFIG_MINIX_FS is not set # CONFIG_OMFS_FS is not set @@ -1290,6 +1445,7 @@ CONFIG_CRAMFS=y # CONFIG_ROMFS_FS is not set # CONFIG_SYSV_FS is not set # CONFIG_UFS_FS is not set +# CONFIG_NILFS2_FS is not set CONFIG_NETWORK_FILESYSTEMS=y CONFIG_NFS_FS=y CONFIG_NFS_V3=y @@ -1381,13 +1537,16 @@ CONFIG_ENABLE_MUST_CHECK=y CONFIG_FRAME_WARN=1024 CONFIG_MAGIC_SYSRQ=y # 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=y # CONFIG_DEBUG_SHIRQ is not set CONFIG_DETECT_SOFTLOCKUP=y # CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 +CONFIG_DETECT_HUNG_TASK=y +# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set +CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0 CONFIG_SCHED_DEBUG=y CONFIG_SCHEDSTATS=y # CONFIG_TIMER_STATS is not set @@ -1411,25 +1570,46 @@ CONFIG_DEBUG_INFO=y # CONFIG_DEBUG_MEMORY_INIT is not set # CONFIG_DEBUG_LIST is not set # CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set CONFIG_FRAME_POINTER=y # CONFIG_BOOT_PRINTK_DELAY is not set # CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_RCU_CPU_STALL_DETECTOR is not set # CONFIG_KPROBES_SANITY_TEST is not set # CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set # CONFIG_LKDTM is not set # CONFIG_FAULT_INJECTION is not set CONFIG_LATENCYTOP=y CONFIG_SYSCTL_SYSCALL_CHECK=y -CONFIG_HAVE_FTRACE=y -CONFIG_HAVE_DYNAMIC_FTRACE=y -# CONFIG_FTRACE is not set +# CONFIG_PAGE_POISONING is not set +CONFIG_NOP_TRACER=y +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_RING_BUFFER=y +CONFIG_TRACING=y +CONFIG_TRACING_SUPPORT=y + +# +# Tracers +# +# CONFIG_FUNCTION_TRACER is not set # CONFIG_IRQSOFF_TRACER is not set # CONFIG_PREEMPT_TRACER is not set # CONFIG_SCHED_TRACER is not set # CONFIG_CONTEXT_SWITCH_TRACER is not set +# CONFIG_EVENT_TRACER is not set +# CONFIG_BOOT_TRACER is not set +# CONFIG_TRACE_BRANCH_PROFILING is not set +# CONFIG_STACK_TRACER is not set +# CONFIG_KMEMTRACE is not set +# CONFIG_WORKQUEUE_TRACER is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_FTRACE_STARTUP_TEST is not set +# CONFIG_DYNAMIC_DEBUG is not set # CONFIG_SAMPLES is not set CONFIG_HAVE_ARCH_KGDB=y # CONFIG_KGDB is not set +CONFIG_ARM_UNWIND=y CONFIG_DEBUG_USER=y CONFIG_DEBUG_ERRORS=y # CONFIG_DEBUG_STACK_USAGE is not set @@ -1441,18 +1621,27 @@ CONFIG_DEBUG_LL=y # # CONFIG_KEYS is not set # CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set # CONFIG_SECURITY_FILE_CAPABILITIES is not set -CONFIG_ASYNC_CORE=y CONFIG_CRYPTO=y # # Crypto core or helper # +# CONFIG_CRYPTO_FIPS is not set CONFIG_CRYPTO_ALGAPI=m +CONFIG_CRYPTO_ALGAPI2=m +CONFIG_CRYPTO_AEAD2=m CONFIG_CRYPTO_BLKCIPHER=m +CONFIG_CRYPTO_BLKCIPHER2=m +CONFIG_CRYPTO_HASH2=m +CONFIG_CRYPTO_RNG2=m +CONFIG_CRYPTO_PCOMP=m CONFIG_CRYPTO_MANAGER=m +CONFIG_CRYPTO_MANAGER2=m # CONFIG_CRYPTO_GF128MUL is not set # CONFIG_CRYPTO_NULL is not set +CONFIG_CRYPTO_WORKQUEUE=m # CONFIG_CRYPTO_CRYPTD is not set # CONFIG_CRYPTO_AUTHENC is not set # CONFIG_CRYPTO_TEST is not set @@ -1521,18 +1710,24 @@ CONFIG_CRYPTO_PCBC=m # Compression # # CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_ZLIB is not set # CONFIG_CRYPTO_LZO is not set + +# +# Random Number Generation +# +# CONFIG_CRYPTO_ANSI_CPRNG is not set CONFIG_CRYPTO_HW=y # CONFIG_CRYPTO_DEV_HIFN_795X is not set +CONFIG_BINARY_PRINTF=y # # Library routines # CONFIG_BITREVERSE=y -# CONFIG_GENERIC_FIND_FIRST_BIT is not set -# CONFIG_GENERIC_FIND_NEXT_BIT is not set +CONFIG_GENERIC_FIND_LAST_BIT=y # CONFIG_CRC_CCITT is not set -# CONFIG_CRC16 is not set +CONFIG_CRC16=m CONFIG_CRC_T10DIF=y CONFIG_CRC_ITU_T=m CONFIG_CRC32=y @@ -1540,7 +1735,7 @@ CONFIG_CRC32=y # CONFIG_LIBCRC32C is not set CONFIG_ZLIB_INFLATE=y CONFIG_ZLIB_DEFLATE=y -CONFIG_PLIST=y CONFIG_HAS_IOMEM=y CONFIG_HAS_IOPORT=y CONFIG_HAS_DMA=y +CONFIG_NLATTR=y diff --git a/arch/arm/configs/viper_defconfig b/arch/arm/configs/viper_defconfig index 30f463d2fa8..6ab5dd5868d 100644 --- a/arch/arm/configs/viper_defconfig +++ b/arch/arm/configs/viper_defconfig @@ -298,7 +298,6 @@ CONFIG_CPU_FREQ_GOV_POWERSAVE=m CONFIG_CPU_FREQ_GOV_USERSPACE=m CONFIG_CPU_FREQ_GOV_ONDEMAND=m CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m -CONFIG_CPU_FREQ_PXA=y # # Floating point emulation diff --git a/arch/arm/include/asm/elf.h b/arch/arm/include/asm/elf.h index d7da19bcf92..c207504de84 100644 --- a/arch/arm/include/asm/elf.h +++ b/arch/arm/include/asm/elf.h @@ -45,13 +45,15 @@ typedef struct user_fp elf_fpregset_t; #define EF_ARM_HASENTRY 0x00000002 /* All */ #define EF_ARM_RELEXEC 0x00000001 /* All */ -#define R_ARM_NONE 0 -#define R_ARM_PC24 1 -#define R_ARM_ABS32 2 -#define R_ARM_CALL 28 -#define R_ARM_JUMP24 29 -#define R_ARM_V4BX 40 -#define R_ARM_PREL31 42 +#define R_ARM_NONE 0 +#define R_ARM_PC24 1 +#define R_ARM_ABS32 2 +#define R_ARM_CALL 28 +#define R_ARM_JUMP24 29 +#define R_ARM_V4BX 40 +#define R_ARM_PREL31 42 +#define R_ARM_MOVW_ABS_NC 43 +#define R_ARM_MOVT_ABS 44 /* * These are used to set parameters in the core dumps. diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c index d1731e39b49..bac03c81489 100644 --- a/arch/arm/kernel/module.c +++ b/arch/arm/kernel/module.c @@ -169,6 +169,21 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex, *(u32 *)loc = offset & 0x7fffffff; break; + case R_ARM_MOVW_ABS_NC: + case R_ARM_MOVT_ABS: + offset = *(u32 *)loc; + offset = ((offset & 0xf0000) >> 4) | (offset & 0xfff); + offset = (offset ^ 0x8000) - 0x8000; + + offset += sym->st_value; + if (ELF32_R_TYPE(rel->r_info) == R_ARM_MOVT_ABS) + offset >>= 16; + + *(u32 *)loc &= 0xfff0f000; + *(u32 *)loc |= ((offset & 0xf000) << 4) | + (offset & 0x0fff); + break; + default: printk(KERN_ERR "%s: unknown relocation: %u\n", module->name, ELF32_R_TYPE(rel->r_info)); diff --git a/arch/arm/mach-davinci/Kconfig b/arch/arm/mach-davinci/Kconfig index bac988e7a4c..a9c78bc72b8 100644 --- a/arch/arm/mach-davinci/Kconfig +++ b/arch/arm/mach-davinci/Kconfig @@ -4,19 +4,56 @@ menu "TI DaVinci Implementations" comment "DaVinci Core Type" -config ARCH_DAVINCI644x - default y +config ARCH_DAVINCI_DM644x bool "DaVinci 644x based system" comment "DaVinci Board Type" config MACH_DAVINCI_EVM - bool "TI DaVinci EVM" + bool "TI DM644x EVM" default y - depends on ARCH_DAVINCI644x + depends on ARCH_DAVINCI_DM644x help Configure this option to specify the whether the board used - for development is a DaVinci EVM + for development is a DM644x EVM + + +config DAVINCI_MUX + bool "DAVINCI multiplexing support" + depends on ARCH_DAVINCI + default y + help + Pin multiplexing support for DAVINCI boards. If your bootloader + sets the multiplexing correctly, say N. Otherwise, or if unsure, + say Y. + +config DAVINCI_MUX_DEBUG + bool "Multiplexing debug output" + depends on DAVINCI_MUX + help + Makes the multiplexing functions print out a lot of debug info. + This is useful if you want to find out the correct values of the + multiplexing registers. + +config DAVINCI_MUX_WARNINGS + bool "Warn about pins the bootloader didn't set up" + depends on DAVINCI_MUX + help + Choose Y here to warn whenever driver initialization logic needs + to change the pin multiplexing setup. When there are no warnings + printed, it's safe to deselect DAVINCI_MUX for your product. + +config DAVINCI_RESET_CLOCKS + bool "Reset unused clocks during boot" + depends on ARCH_DAVINCI + help + Say Y if you want to reset unused clocks during boot. + This option saves power, but assumes all drivers are + using the clock framework. Broken drivers that do not + yet use clock framework may not work with this option. + If you are booting from another operating system, you + probably do not want this option enabled until your + device drivers work properly. endmenu diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile index 4dc458597f4..1674661942f 100644 --- a/arch/arm/mach-davinci/Makefile +++ b/arch/arm/mach-davinci/Makefile @@ -5,7 +5,12 @@ # Common objects obj-y := time.o irq.o clock.o serial.o io.o id.o psc.o \ - gpio.o mux.o devices.o usb.o + gpio.o devices.o dma.o usb.o + +obj-$(CONFIG_DAVINCI_MUX) += mux.o + +# Chip specific +obj-$(CONFIG_ARCH_DAVINCI_DM644x) += dm644x.o # Board specific -obj-$(CONFIG_MACH_DAVINCI_EVM) += board-evm.o +obj-$(CONFIG_MACH_DAVINCI_EVM) += board-dm644x-evm.o diff --git a/arch/arm/mach-davinci/board-evm.c b/arch/arm/mach-davinci/board-dm644x-evm.c index 0b97a528902..b2e7f9c63bc 100644 --- a/arch/arm/mach-davinci/board-evm.c +++ b/arch/arm/mach-davinci/board-dm644x-evm.c @@ -15,15 +15,20 @@ #include <linux/platform_device.h> #include <linux/gpio.h> #include <linux/leds.h> +#include <linux/memory.h> +#include <linux/etherdevice.h> #include <linux/i2c.h> #include <linux/i2c/pcf857x.h> #include <linux/i2c/at24.h> #include <linux/mtd/mtd.h> +#include <linux/mtd/nand.h> #include <linux/mtd/partitions.h> #include <linux/mtd/physmap.h> #include <linux/io.h> +#include <linux/phy.h> +#include <linux/clk.h> #include <asm/setup.h> #include <asm/mach-types.h> @@ -32,25 +37,34 @@ #include <asm/mach/map.h> #include <asm/mach/flash.h> -#include <mach/hardware.h> +#include <mach/dm644x.h> #include <mach/common.h> #include <mach/i2c.h> +#include <mach/serial.h> +#include <mach/mux.h> +#include <mach/psc.h> +#include <mach/nand.h> -/* other misc. init functions */ -void __init davinci_psc_init(void); -void __init davinci_irq_init(void); -void __init davinci_map_common_io(void); -void __init davinci_init_common_hw(void); +#define DM644X_EVM_PHY_MASK (0x2) +#define DM644X_EVM_MDIO_FREQUENCY (2200000) /* PHY bus frequency */ -#if defined(CONFIG_MTD_PHYSMAP) || \ - defined(CONFIG_MTD_PHYSMAP_MODULE) +#define DAVINCI_CFC_ATA_BASE 0x01C66000 + +#define DAVINCI_ASYNC_EMIF_CONTROL_BASE 0x01e00000 +#define DAVINCI_ASYNC_EMIF_DATA_CE0_BASE 0x02000000 +#define DAVINCI_ASYNC_EMIF_DATA_CE1_BASE 0x04000000 +#define DAVINCI_ASYNC_EMIF_DATA_CE2_BASE 0x06000000 +#define DAVINCI_ASYNC_EMIF_DATA_CE3_BASE 0x08000000 + +#define LXT971_PHY_ID (0x001378e2) +#define LXT971_PHY_MASK (0xfffffff0) static struct mtd_partition davinci_evm_norflash_partitions[] = { - /* bootloader (U-Boot, etc) in first 4 sectors */ + /* bootloader (UBL, U-Boot, etc) in first 5 sectors */ { .name = "bootloader", .offset = 0, - .size = 4 * SZ_64K, + .size = 5 * SZ_64K, .mask_flags = MTD_WRITEABLE, /* force read-only */ }, /* bootloader params in the next 1 sectors */ @@ -100,10 +114,89 @@ static struct platform_device davinci_evm_norflash_device = { .resource = &davinci_evm_norflash_resource, }; -#endif +/* DM644x EVM includes a 64 MByte small-page NAND flash (16K blocks). + * It may used instead of the (default) NOR chip to boot, using TI's + * tools to install the secondary boot loader (UBL) and U-Boot. + */ +struct mtd_partition davinci_evm_nandflash_partition[] = { + /* Bootloader layout depends on whose u-boot is installed, but we + * can hide all the details. + * - block 0 for u-boot environment ... in mainline u-boot + * - block 1 for UBL (plus up to four backup copies in blocks 2..5) + * - blocks 6...? for u-boot + * - blocks 16..23 for u-boot environment ... in TI's u-boot + */ + { + .name = "bootloader", + .offset = 0, + .size = SZ_256K + SZ_128K, + .mask_flags = MTD_WRITEABLE, /* force read-only */ + }, + /* Kernel */ + { + .name = "kernel", + .offset = MTDPART_OFS_APPEND, + .size = SZ_4M, + .mask_flags = 0, + }, + /* File system (older GIT kernels started this on the 5MB mark) */ + { + .name = "filesystem", + .offset = MTDPART_OFS_APPEND, + .size = MTDPART_SIZ_FULL, + .mask_flags = 0, + } + /* A few blocks at end hold a flash BBT ... created by TI's CCS + * using flashwriter_nand.out, but ignored by TI's versions of + * Linux and u-boot. We boot faster by using them. + */ +}; -#if defined(CONFIG_BLK_DEV_PALMCHIP_BK3710) || \ - defined(CONFIG_BLK_DEV_PALMCHIP_BK3710_MODULE) +static struct davinci_nand_pdata davinci_evm_nandflash_data = { + .parts = davinci_evm_nandflash_partition, + .nr_parts = ARRAY_SIZE(davinci_evm_nandflash_partition), + .ecc_mode = NAND_ECC_HW, + .options = NAND_USE_FLASH_BBT, +}; + +static struct resource davinci_evm_nandflash_resource[] = { + { + .start = DAVINCI_ASYNC_EMIF_DATA_CE0_BASE, + .end = DAVINCI_ASYNC_EMIF_DATA_CE0_BASE + SZ_16M - 1, + .flags = IORESOURCE_MEM, + }, { + .start = DAVINCI_ASYNC_EMIF_CONTROL_BASE, + .end = DAVINCI_ASYNC_EMIF_CONTROL_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device davinci_evm_nandflash_device = { + .name = "davinci_nand", + .id = 0, + .dev = { + .platform_data = &davinci_evm_nandflash_data, + }, + .num_resources = ARRAY_SIZE(davinci_evm_nandflash_resource), + .resource = davinci_evm_nandflash_resource, +}; + +static u64 davinci_fb_dma_mask = DMA_BIT_MASK(32); + +static struct platform_device davinci_fb_device = { + .name = "davincifb", + .id = -1, + .dev = { + .dma_mask = &davinci_fb_dma_mask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, + .num_resources = 0, +}; + +static struct platform_device rtc_dev = { + .name = "rtc_davinci_evm", + .id = -1, +}; static struct resource ide_resources[] = { { @@ -131,8 +224,6 @@ static struct platform_device ide_dev = { }, }; -#endif - /*----------------------------------------------------------------------*/ /* @@ -311,7 +402,9 @@ evm_u35_setup(struct i2c_client *client, int gpio, unsigned ngpio, void *c) gpio_request(gpio + 7, "nCF_SEL"); gpio_direction_output(gpio + 7, 1); - /* irlml6401 sustains over 3A, switches 5V in under 8 msec */ + /* irlml6401 switches over 1A, in under 8 msec; + * now it can be managed by nDRV_VBUS ... + */ setup_usb(500, 8); return 0; @@ -343,14 +436,120 @@ static struct pcf857x_platform_data pcf_data_u35 = { * - 0x0039, 1 byte NTSC vs PAL (bit 0x80 == PAL) * - ... newer boards may have more */ +static struct memory_accessor *at24_mem_acc; + +static void at24_setup(struct memory_accessor *mem_acc, void *context) +{ + DECLARE_MAC_BUF(mac_str); + char mac_addr[6]; + + at24_mem_acc = mem_acc; + + /* Read MAC addr from EEPROM */ + if (at24_mem_acc->read(at24_mem_acc, mac_addr, 0x7f00, 6) == 6) { + printk(KERN_INFO "Read MAC addr from EEPROM: %s\n", + print_mac(mac_str, mac_addr)); + } +} + static struct at24_platform_data eeprom_info = { .byte_len = (256*1024) / 8, .page_size = 64, .flags = AT24_FLAG_ADDR16, + .setup = at24_setup, }; +int dm6446evm_eeprom_read(void *buf, off_t off, size_t count) +{ + if (at24_mem_acc) + return at24_mem_acc->read(at24_mem_acc, buf, off, count); + return -ENODEV; +} +EXPORT_SYMBOL(dm6446evm_eeprom_read); + +int dm6446evm_eeprom_write(void *buf, off_t off, size_t count) +{ + if (at24_mem_acc) + return at24_mem_acc->write(at24_mem_acc, buf, off, count); + return -ENODEV; +} +EXPORT_SYMBOL(dm6446evm_eeprom_write); + +/* + * MSP430 supports RTC, card detection, input from IR remote, and + * a bit more. It triggers interrupts on GPIO(7) from pressing + * buttons on the IR remote, and for card detect switches. + */ +static struct i2c_client *dm6446evm_msp; + +static int dm6446evm_msp_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + dm6446evm_msp = client; + return 0; +} + +static int dm6446evm_msp_remove(struct i2c_client *client) +{ + dm6446evm_msp = NULL; + return 0; +} + +static const struct i2c_device_id dm6446evm_msp_ids[] = { + { "dm6446evm_msp", 0, }, + { /* end of list */ }, +}; + +static struct i2c_driver dm6446evm_msp_driver = { + .driver.name = "dm6446evm_msp", + .id_table = dm6446evm_msp_ids, + .probe = dm6446evm_msp_probe, + .remove = dm6446evm_msp_remove, +}; + +static int dm6444evm_msp430_get_pins(void) +{ + static const char txbuf[2] = { 2, 4, }; + char buf[4]; + struct i2c_msg msg[2] = { + { + .addr = dm6446evm_msp->addr, + .flags = 0, + .len = 2, + .buf = (void __force *)txbuf, + }, + { + .addr = dm6446evm_msp->addr, + .flags = I2C_M_RD, + .len = 4, + .buf = buf, + }, + }; + int status; + + if (!dm6446evm_msp) + return -ENXIO; + + /* Command 4 == get input state, returns port 2 and port3 data + * S Addr W [A] len=2 [A] cmd=4 [A] + * RS Addr R [A] [len=4] A [cmd=4] A [port2] A [port3] N P + */ + status = i2c_transfer(dm6446evm_msp->adapter, msg, 2); + if (status < 0) + return status; + + dev_dbg(&dm6446evm_msp->dev, + "PINS: %02x %02x %02x %02x\n", + buf[0], buf[1], buf[2], buf[3]); + + return (buf[3] << 8) | buf[2]; +} + static struct i2c_board_info __initdata i2c_info[] = { { + I2C_BOARD_INFO("dm6446evm_msp", 0x23), + }, + { I2C_BOARD_INFO("pcf8574", 0x38), .platform_data = &pcf_data_u2, }, @@ -368,7 +567,6 @@ static struct i2c_board_info __initdata i2c_info[] = { }, /* ALSO: * - tvl320aic33 audio codec (0x1b) - * - msp430 microcontroller (0x23) * - tvp5146 video decoder (0x5d) */ }; @@ -384,51 +582,109 @@ static struct davinci_i2c_platform_data i2c_pdata = { static void __init evm_init_i2c(void) { davinci_init_i2c(&i2c_pdata); + i2c_add_driver(&dm6446evm_msp_driver); i2c_register_board_info(1, i2c_info, ARRAY_SIZE(i2c_info)); } static struct platform_device *davinci_evm_devices[] __initdata = { -#if defined(CONFIG_MTD_PHYSMAP) || \ - defined(CONFIG_MTD_PHYSMAP_MODULE) - &davinci_evm_norflash_device, -#endif -#if defined(CONFIG_BLK_DEV_PALMCHIP_BK3710) || \ - defined(CONFIG_BLK_DEV_PALMCHIP_BK3710_MODULE) - &ide_dev, -#endif + &davinci_fb_device, + &rtc_dev, +}; + +static struct davinci_uart_config uart_config __initdata = { + .enabled_uarts = (1 << 0), }; static void __init davinci_evm_map_io(void) { davinci_map_common_io(); + dm644x_init(); } -static __init void davinci_evm_init(void) +static int davinci_phy_fixup(struct phy_device *phydev) { - davinci_psc_init(); + unsigned int control; + /* CRITICAL: Fix for increasing PHY signal drive strength for + * TX lockup issue. On DaVinci EVM, the Intel LXT971 PHY + * signal strength was low causing TX to fail randomly. The + * fix is to Set bit 11 (Increased MII drive strength) of PHY + * register 26 (Digital Config register) on this phy. */ + control = phy_read(phydev, 26); + phy_write(phydev, 26, (control | 0x800)); + return 0; +} #if defined(CONFIG_BLK_DEV_PALMCHIP_BK3710) || \ defined(CONFIG_BLK_DEV_PALMCHIP_BK3710_MODULE) +#define HAS_ATA 1 +#else +#define HAS_ATA 0 +#endif + #if defined(CONFIG_MTD_PHYSMAP) || \ defined(CONFIG_MTD_PHYSMAP_MODULE) - printk(KERN_WARNING "WARNING: both IDE and NOR flash are enabled, " - "but share pins.\n\t Disable IDE for NOR support.\n"); +#define HAS_NOR 1 +#else +#define HAS_NOR 0 #endif + +#if defined(CONFIG_MTD_NAND_DAVINCI) || \ + defined(CONFIG_MTD_NAND_DAVINCI_MODULE) +#define HAS_NAND 1 +#else +#define HAS_NAND 0 #endif +static __init void davinci_evm_init(void) +{ + struct clk *aemif_clk; + + aemif_clk = clk_get(NULL, "aemif"); + clk_enable(aemif_clk); + + if (HAS_ATA) { + if (HAS_NAND || HAS_NOR) + pr_warning("WARNING: both IDE and Flash are " + "enabled, but they share AEMIF pins.\n" + "\tDisable IDE for NAND/NOR support.\n"); + davinci_cfg_reg(DM644X_HPIEN_DISABLE); + davinci_cfg_reg(DM644X_ATAEN); + davinci_cfg_reg(DM644X_HDIREN); + platform_device_register(&ide_dev); + } else if (HAS_NAND || HAS_NOR) { + davinci_cfg_reg(DM644X_HPIEN_DISABLE); + davinci_cfg_reg(DM644X_ATAEN_DISABLE); + + /* only one device will be jumpered and detected */ + if (HAS_NAND) { + platform_device_register(&davinci_evm_nandflash_device); + evm_leds[7].default_trigger = "nand-disk"; + if (HAS_NOR) + pr_warning("WARNING: both NAND and NOR flash " + "are enabled; disable one of them.\n"); + } else if (HAS_NOR) + platform_device_register(&davinci_evm_norflash_device); + } + platform_add_devices(davinci_evm_devices, ARRAY_SIZE(davinci_evm_devices)); evm_init_i2c(); + + davinci_serial_init(&uart_config); + + /* Register the fixup for PHY on DaVinci */ + phy_register_fixup_for_uid(LXT971_PHY_ID, LXT971_PHY_MASK, + davinci_phy_fixup); + } static __init void davinci_evm_irq_init(void) { - davinci_init_common_hw(); davinci_irq_init(); } -MACHINE_START(DAVINCI_EVM, "DaVinci EVM") +MACHINE_START(DAVINCI_EVM, "DaVinci DM644x EVM") /* Maintainer: MontaVista Software <source@mvista.com> */ .phys_io = IO_PHYS, .io_pg_offst = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc, diff --git a/arch/arm/mach-davinci/clock.c b/arch/arm/mach-davinci/clock.c index abb92b7eca0..f0baaa15a57 100644 --- a/arch/arm/mach-davinci/clock.c +++ b/arch/arm/mach-davinci/clock.c @@ -1,7 +1,8 @@ /* - * TI DaVinci clock config file + * Clock and PLL control for DaVinci devices * - * Copyright (C) 2006 Texas Instruments. + * Copyright (C) 2006-2007 Texas Instruments. + * Copyright (C) 2008-2009 Deep Root Systems, LLC * * 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 @@ -13,6 +14,7 @@ #include <linux/kernel.h> #include <linux/init.h> #include <linux/errno.h> +#include <linux/clk.h> #include <linux/err.h> #include <linux/mutex.h> #include <linux/platform_device.h> @@ -21,98 +23,50 @@ #include <mach/hardware.h> #include <mach/psc.h> +#include <mach/cputype.h> #include "clock.h" -/* PLL/Reset register offsets */ -#define PLLM 0x110 - static LIST_HEAD(clocks); static DEFINE_MUTEX(clocks_mutex); static DEFINE_SPINLOCK(clockfw_lock); -static unsigned int commonrate; -static unsigned int armrate; -static unsigned int fixedrate = 27000000; /* 27 MHZ */ - -extern void davinci_psc_config(unsigned int domain, unsigned int id, char enable); - -/* - * Returns a clock. Note that we first try to use device id on the bus - * and clock name. If this fails, we try to use clock name only. - */ -struct clk *clk_get(struct device *dev, const char *id) +static unsigned psc_domain(struct clk *clk) { - struct clk *p, *clk = ERR_PTR(-ENOENT); - int idno; - - if (dev == NULL || dev->bus != &platform_bus_type) - idno = -1; - else - idno = to_platform_device(dev)->id; - - mutex_lock(&clocks_mutex); - - list_for_each_entry(p, &clocks, node) { - if (p->id == idno && - strcmp(id, p->name) == 0 && try_module_get(p->owner)) { - clk = p; - goto found; - } - } - - list_for_each_entry(p, &clocks, node) { - if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) { - clk = p; - break; - } - } - -found: - mutex_unlock(&clocks_mutex); - - return clk; + return (clk->flags & PSC_DSP) + ? DAVINCI_GPSC_DSPDOMAIN + : DAVINCI_GPSC_ARMDOMAIN; } -EXPORT_SYMBOL(clk_get); -void clk_put(struct clk *clk) +static void __clk_enable(struct clk *clk) { - if (clk && !IS_ERR(clk)) - module_put(clk->owner); -} -EXPORT_SYMBOL(clk_put); - -static int __clk_enable(struct clk *clk) -{ - if (clk->flags & ALWAYS_ENABLED) - return 0; - - davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, clk->lpsc, 1); - return 0; + if (clk->parent) + __clk_enable(clk->parent); + if (clk->usecount++ == 0 && (clk->flags & CLK_PSC)) + davinci_psc_config(psc_domain(clk), clk->lpsc, 1); } static void __clk_disable(struct clk *clk) { - if (clk->usecount) + if (WARN_ON(clk->usecount == 0)) return; - - davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, clk->lpsc, 0); + if (--clk->usecount == 0 && !(clk->flags & CLK_PLL)) + davinci_psc_config(psc_domain(clk), clk->lpsc, 0); + if (clk->parent) + __clk_disable(clk->parent); } int clk_enable(struct clk *clk) { unsigned long flags; - int ret = 0; if (clk == NULL || IS_ERR(clk)) return -EINVAL; - if (clk->usecount++ == 0) { - spin_lock_irqsave(&clockfw_lock, flags); - ret = __clk_enable(clk); - spin_unlock_irqrestore(&clockfw_lock, flags); - } + spin_lock_irqsave(&clockfw_lock, flags); + __clk_enable(clk); + spin_unlock_irqrestore(&clockfw_lock, flags); - return ret; + return 0; } EXPORT_SYMBOL(clk_enable); @@ -123,11 +77,9 @@ void clk_disable(struct clk *clk) if (clk == NULL || IS_ERR(clk)) return; - if (clk->usecount > 0 && !(--clk->usecount)) { - spin_lock_irqsave(&clockfw_lock, flags); - __clk_disable(clk); - spin_unlock_irqrestore(&clockfw_lock, flags); - } + spin_lock_irqsave(&clockfw_lock, flags); + __clk_disable(clk); + spin_unlock_irqrestore(&clockfw_lock, flags); } EXPORT_SYMBOL(clk_disable); @@ -136,7 +88,7 @@ unsigned long clk_get_rate(struct clk *clk) if (clk == NULL || IS_ERR(clk)) return -EINVAL; - return *(clk->rate); + return clk->rate; } EXPORT_SYMBOL(clk_get_rate); @@ -145,7 +97,7 @@ long clk_round_rate(struct clk *clk, unsigned long rate) if (clk == NULL || IS_ERR(clk)) return -EINVAL; - return *(clk->rate); + return clk->rate; } EXPORT_SYMBOL(clk_round_rate); @@ -164,10 +116,23 @@ int clk_register(struct clk *clk) if (clk == NULL || IS_ERR(clk)) return -EINVAL; + if (WARN(clk->parent && !clk->parent->rate, + "CLK: %s parent %s has no rate!\n", + clk->name, clk->parent->name)) + return -EINVAL; + mutex_lock(&clocks_mutex); - list_add(&clk->node, &clocks); + list_add_tail(&clk->node, &clocks); mutex_unlock(&clocks_mutex); + /* If rate is already set, use it */ + if (clk->rate) + return 0; + + /* Otherwise, default to parent rate */ + if (clk->parent) + clk->rate = clk->parent->rate; + return 0; } EXPORT_SYMBOL(clk_register); @@ -183,84 +148,150 @@ void clk_unregister(struct clk *clk) } EXPORT_SYMBOL(clk_unregister); -static struct clk davinci_clks[] = { - { - .name = "ARMCLK", - .rate = &armrate, - .lpsc = -1, - .flags = ALWAYS_ENABLED, - }, - { - .name = "UART", - .rate = &fixedrate, - .lpsc = DAVINCI_LPSC_UART0, - }, - { - .name = "EMACCLK", - .rate = &commonrate, - .lpsc = DAVINCI_LPSC_EMAC_WRAPPER, - }, - { - .name = "I2CCLK", - .rate = &fixedrate, - .lpsc = DAVINCI_LPSC_I2C, - }, - { - .name = "IDECLK", - .rate = &commonrate, - .lpsc = DAVINCI_LPSC_ATA, - }, - { - .name = "McBSPCLK", - .rate = &commonrate, - .lpsc = DAVINCI_LPSC_McBSP, - }, - { - .name = "MMCSDCLK", - .rate = &commonrate, - .lpsc = DAVINCI_LPSC_MMC_SD, - }, - { - .name = "SPICLK", - .rate = &commonrate, - .lpsc = DAVINCI_LPSC_SPI, - }, - { - .name = "gpio", - .rate = &commonrate, - .lpsc = DAVINCI_LPSC_GPIO, - }, - { - .name = "usb", - .rate = &commonrate, - .lpsc = DAVINCI_LPSC_USB, - }, - { - .name = "AEMIFCLK", - .rate = &commonrate, - .lpsc = DAVINCI_LPSC_AEMIF, - .usecount = 1, +#ifdef CONFIG_DAVINCI_RESET_CLOCKS +/* + * Disable any unused clocks left on by the bootloader + */ +static int __init clk_disable_unused(void) +{ + struct clk *ck; + + spin_lock_irq(&clockfw_lock); + list_for_each_entry(ck, &clocks, node) { + if (ck->usecount > 0) + continue; + if (!(ck->flags & CLK_PSC)) + continue; + + /* ignore if in Disabled or SwRstDisable states */ + if (!davinci_psc_is_clk_active(ck->lpsc)) + continue; + + pr_info("Clocks: disable unused %s\n", ck->name); + davinci_psc_config(psc_domain(ck), ck->lpsc, 0); } -}; + spin_unlock_irq(&clockfw_lock); + + return 0; +} +late_initcall(clk_disable_unused); +#endif -int __init davinci_clk_init(void) +static void clk_sysclk_recalc(struct clk *clk) { - struct clk *clkp; - int count = 0; - u32 pll_mult; - - pll_mult = davinci_readl(DAVINCI_PLL_CNTRL0_BASE + PLLM); - commonrate = ((pll_mult + 1) * 27000000) / 6; - armrate = ((pll_mult + 1) * 27000000) / 2; - - for (clkp = davinci_clks; count < ARRAY_SIZE(davinci_clks); - count++, clkp++) { - clk_register(clkp); - - /* Turn on clocks that have been enabled in the - * table above */ - if (clkp->usecount) - clk_enable(clkp); + u32 v, plldiv; + struct pll_data *pll; + + /* If this is the PLL base clock, no more calculations needed */ + if (clk->pll_data) + return; + + if (WARN_ON(!clk->parent)) + return; + + clk->rate = clk->parent->rate; + + /* Otherwise, the parent must be a PLL */ + if (WARN_ON(!clk->parent->pll_data)) + return; + + pll = clk->parent->pll_data; + + /* If pre-PLL, source clock is before the multiplier and divider(s) */ + if (clk->flags & PRE_PLL) + clk->rate = pll->input_rate; + + if (!clk->div_reg) + return; + + v = __raw_readl(pll->base + clk->div_reg); + if (v & PLLDIV_EN) { + plldiv = (v & PLLDIV_RATIO_MASK) + 1; + if (plldiv) + clk->rate /= plldiv; + } +} + +static void __init clk_pll_init(struct clk *clk) +{ + u32 ctrl, mult = 1, prediv = 1, postdiv = 1; + u8 bypass; + struct pll_data *pll = clk->pll_data; + + pll->base = IO_ADDRESS(pll->phys_base); + ctrl = __raw_readl(pll->base + PLLCTL); + clk->rate = pll->input_rate = clk->parent->rate; + + if (ctrl & PLLCTL_PLLEN) { + bypass = 0; + mult = __raw_readl(pll->base + PLLM); + mult = (mult & PLLM_PLLM_MASK) + 1; + } else + bypass = 1; + + if (pll->flags & PLL_HAS_PREDIV) { + prediv = __raw_readl(pll->base + PREDIV); + if (prediv & PLLDIV_EN) + prediv = (prediv & PLLDIV_RATIO_MASK) + 1; + else + prediv = 1; + } + + /* pre-divider is fixed, but (some?) chips won't report that */ + if (cpu_is_davinci_dm355() && pll->num == 1) + prediv = 8; + + if (pll->flags & PLL_HAS_POSTDIV) { + postdiv = __raw_readl(pll->base + POSTDIV); + if (postdiv & PLLDIV_EN) + postdiv = (postdiv & PLLDIV_RATIO_MASK) + 1; + else + postdiv = 1; + } + + if (!bypass) { + clk->rate /= prediv; + clk->rate *= mult; + clk->rate /= postdiv; + } + + pr_debug("PLL%d: input = %lu MHz [ ", + pll->num, clk->parent->rate / 1000000); + if (bypass) + pr_debug("bypass "); + if (prediv > 1) + pr_debug("/ %d ", prediv); + if (mult > 1) + pr_debug("* %d ", mult); + if (postdiv > 1) + pr_debug("/ %d ", postdiv); + pr_debug("] --> %lu MHz output.\n", clk->rate / 1000000); +} + +int __init davinci_clk_init(struct davinci_clk *clocks) + { + struct davinci_clk *c; + struct clk *clk; + + for (c = clocks; c->lk.clk; c++) { + clk = c->lk.clk; + + if (clk->pll_data) + clk_pll_init(clk); + + /* Calculate rates for PLL-derived clocks */ + else if (clk->flags & CLK_PLL) + clk_sysclk_recalc(clk); + + if (clk->lpsc) + clk->flags |= CLK_PSC; + + clkdev_add(&c->lk); + clk_register(clk); + + /* Turn on clocks that Linux doesn't otherwise manage */ + if (clk->flags & ALWAYS_ENABLED) + clk_enable(clk); } return 0; @@ -285,12 +316,52 @@ static void davinci_ck_stop(struct seq_file *m, void *v) { } -static int davinci_ck_show(struct seq_file *m, void *v) +#define CLKNAME_MAX 10 /* longest clock name */ +#define NEST_DELTA 2 +#define NEST_MAX 4 + +static void +dump_clock(struct seq_file *s, unsigned nest, struct clk *parent) { - struct clk *cp; + char *state; + char buf[CLKNAME_MAX + NEST_DELTA * NEST_MAX]; + struct clk *clk; + unsigned i; + + if (parent->flags & CLK_PLL) + state = "pll"; + else if (parent->flags & CLK_PSC) + state = "psc"; + else + state = ""; + + /* <nest spaces> name <pad to end> */ + memset(buf, ' ', sizeof(buf) - 1); + buf[sizeof(buf) - 1] = 0; + i = strlen(parent->name); + memcpy(buf + nest, parent->name, + min(i, (unsigned)(sizeof(buf) - 1 - nest))); + + seq_printf(s, "%s users=%2d %-3s %9ld Hz\n", + buf, parent->usecount, state, clk_get_rate(parent)); + /* REVISIT show device associations too */ + + /* cost is now small, but not linear... */ + list_for_each_entry(clk, &clocks, node) { + if (clk->parent == parent) + dump_clock(s, nest + NEST_DELTA, clk); + } +} - list_for_each_entry(cp, &clocks, node) - seq_printf(m,"%s %d %d\n", cp->name, *(cp->rate), cp->usecount); +static int davinci_ck_show(struct seq_file *m, void *v) +{ + /* Show clock tree; we know the main oscillator is first. + * We trust nonzero usecounts equate to PSC enables... + */ + mutex_lock(&clocks_mutex); + if (!list_empty(&clocks)) + dump_clock(m, 0, list_first_entry(&clocks, struct clk, node)); + mutex_unlock(&clocks_mutex); return 0; } @@ -321,4 +392,4 @@ static int __init davinci_ck_proc_init(void) } __initcall(davinci_ck_proc_init); -#endif /* CONFIG_DEBUG_PROC_FS */ +#endif /* CONFIG_DEBUG_PROC_FS */ diff --git a/arch/arm/mach-davinci/clock.h b/arch/arm/mach-davinci/clock.h index ed47079a52e..35736ec202f 100644 --- a/arch/arm/mach-davinci/clock.h +++ b/arch/arm/mach-davinci/clock.h @@ -1,7 +1,8 @@ /* * TI DaVinci clock definitions * - * Copyright (C) 2006 Texas Instruments. + * Copyright (C) 2006-2007 Texas Instruments. + * Copyright (C) 2008-2009 Deep Root Systems, LLC * * 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 @@ -11,23 +12,85 @@ #ifndef __ARCH_ARM_DAVINCI_CLOCK_H #define __ARCH_ARM_DAVINCI_CLOCK_H +#include <linux/list.h> +#include <asm/clkdev.h> + +#define DAVINCI_PLL1_BASE 0x01c40800 +#define DAVINCI_PLL2_BASE 0x01c40c00 +#define MAX_PLL 2 + +/* PLL/Reset register offsets */ +#define PLLCTL 0x100 +#define PLLCTL_PLLEN BIT(0) +#define PLLCTL_CLKMODE BIT(8) + +#define PLLM 0x110 +#define PLLM_PLLM_MASK 0xff + +#define PREDIV 0x114 +#define PLLDIV1 0x118 +#define PLLDIV2 0x11c +#define PLLDIV3 0x120 +#define POSTDIV 0x128 +#define BPDIV 0x12c +#define PLLCMD 0x138 +#define PLLSTAT 0x13c +#define PLLALNCTL 0x140 +#define PLLDCHANGE 0x144 +#define PLLCKEN 0x148 +#define PLLCKSTAT 0x14c +#define PLLSYSTAT 0x150 +#define PLLDIV4 0x160 +#define PLLDIV5 0x164 +#define PLLDIV6 0x168 +#define PLLDIV7 0x16c +#define PLLDIV8 0x170 +#define PLLDIV9 0x174 +#define PLLDIV_EN BIT(15) +#define PLLDIV_RATIO_MASK 0x1f + +struct pll_data { + u32 phys_base; + void __iomem *base; + u32 num; + u32 flags; + u32 input_rate; +}; +#define PLL_HAS_PREDIV 0x01 +#define PLL_HAS_POSTDIV 0x02 + struct clk { struct list_head node; struct module *owner; const char *name; - unsigned int *rate; - int id; - __s8 usecount; - __u8 flags; - __u8 lpsc; + unsigned long rate; + u8 usecount; + u8 flags; + u8 lpsc; + struct clk *parent; + struct pll_data *pll_data; + u32 div_reg; }; /* Clock flags */ -#define RATE_CKCTL 1 -#define RATE_FIXED 2 -#define RATE_PROPAGATES 4 -#define VIRTUAL_CLOCK 8 -#define ALWAYS_ENABLED 16 -#define ENABLE_REG_32BIT 32 +#define ALWAYS_ENABLED BIT(1) +#define CLK_PSC BIT(2) +#define PSC_DSP BIT(3) /* PSC uses DSP domain, not ARM */ +#define CLK_PLL BIT(4) /* PLL-derived clock */ +#define PRE_PLL BIT(5) /* source is before PLL mult/div */ + +struct davinci_clk { + struct clk_lookup lk; +}; + +#define CLK(dev, con, ck) \ + { \ + .lk = { \ + .dev_id = dev, \ + .con_id = con, \ + .clk = ck, \ + }, \ + } +int davinci_clk_init(struct davinci_clk *clocks); #endif diff --git a/arch/arm/mach-davinci/devices.c b/arch/arm/mach-davinci/devices.c index 808633f9f03..a31370b93dd 100644 --- a/arch/arm/mach-davinci/devices.c +++ b/arch/arm/mach-davinci/devices.c @@ -21,6 +21,10 @@ #include <mach/hardware.h> #include <mach/i2c.h> #include <mach/irqs.h> +#include <mach/cputype.h> +#include <mach/mux.h> + +#define DAVINCI_I2C_BASE 0x01C21000 static struct resource i2c_resources[] = { { @@ -43,6 +47,9 @@ static struct platform_device davinci_i2c_device = { void __init davinci_init_i2c(struct davinci_i2c_platform_data *pdata) { + if (cpu_is_davinci_dm644x()) + davinci_cfg_reg(DM644X_I2C); + davinci_i2c_device.dev.platform_data = pdata; (void) platform_device_register(&davinci_i2c_device); } diff --git a/arch/arm/mach-davinci/dm644x.c b/arch/arm/mach-davinci/dm644x.c new file mode 100644 index 00000000000..d428ef192ea --- /dev/null +++ b/arch/arm/mach-davinci/dm644x.c @@ -0,0 +1,461 @@ +/* + * TI DaVinci DM644x chip specific setup + * + * Author: Kevin Hilman, Deep Root Systems, LLC + * + * 2007 (c) Deep Root Systems, LLC. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/clk.h> +#include <linux/platform_device.h> + +#include <mach/dm644x.h> +#include <mach/clock.h> +#include <mach/cputype.h> +#include <mach/edma.h> +#include <mach/irqs.h> +#include <mach/psc.h> +#include <mach/mux.h> + +#include "clock.h" +#include "mux.h" + +/* + * Device specific clocks + */ +#define DM644X_REF_FREQ 27000000 + +static struct pll_data pll1_data = { + .num = 1, + .phys_base = DAVINCI_PLL1_BASE, +}; + +static struct pll_data pll2_data = { + .num = 2, + .phys_base = DAVINCI_PLL2_BASE, +}; + +static struct clk ref_clk = { + .name = "ref_clk", + .rate = DM644X_REF_FREQ, +}; + +static struct clk pll1_clk = { + .name = "pll1", + .parent = &ref_clk, + .pll_data = &pll1_data, + .flags = CLK_PLL, +}; + +static struct clk pll1_sysclk1 = { + .name = "pll1_sysclk1", + .parent = &pll1_clk, + .flags = CLK_PLL, + .div_reg = PLLDIV1, +}; + +static struct clk pll1_sysclk2 = { + .name = "pll1_sysclk2", + .parent = &pll1_clk, + .flags = CLK_PLL, + .div_reg = PLLDIV2, +}; + +static struct clk pll1_sysclk3 = { + .name = "pll1_sysclk3", + .parent = &pll1_clk, + .flags = CLK_PLL, + .div_reg = PLLDIV3, +}; + +static struct clk pll1_sysclk5 = { + .name = "pll1_sysclk5", + .parent = &pll1_clk, + .flags = CLK_PLL, + .div_reg = PLLDIV5, +}; + +static struct clk pll1_aux_clk = { + .name = "pll1_aux_clk", + .parent = &pll1_clk, + .flags = CLK_PLL | PRE_PLL, +}; + +static struct clk pll1_sysclkbp = { + .name = "pll1_sysclkbp", + .parent = &pll1_clk, + .flags = CLK_PLL | PRE_PLL, + .div_reg = BPDIV +}; + +static struct clk pll2_clk = { + .name = "pll2", + .parent = &ref_clk, + .pll_data = &pll2_data, + .flags = CLK_PLL, +}; + +static struct clk pll2_sysclk1 = { + .name = "pll2_sysclk1", + .parent = &pll2_clk, + .flags = CLK_PLL, + .div_reg = PLLDIV1, +}; + +static struct clk pll2_sysclk2 = { + .name = "pll2_sysclk2", + .parent = &pll2_clk, + .flags = CLK_PLL, + .div_reg = PLLDIV2, +}; + +static struct clk pll2_sysclkbp = { + .name = "pll2_sysclkbp", + .parent = &pll2_clk, + .flags = CLK_PLL | PRE_PLL, + .div_reg = BPDIV +}; + +static struct clk dsp_clk = { + .name = "dsp", + .parent = &pll1_sysclk1, + .lpsc = DAVINCI_LPSC_GEM, + .flags = PSC_DSP, + .usecount = 1, /* REVISIT how to disable? */ +}; + +static struct clk arm_clk = { + .name = "arm", + .parent = &pll1_sysclk2, + .lpsc = DAVINCI_LPSC_ARM, + .flags = ALWAYS_ENABLED, +}; + +static struct clk vicp_clk = { + .name = "vicp", + .parent = &pll1_sysclk2, + .lpsc = DAVINCI_LPSC_IMCOP, + .flags = PSC_DSP, + .usecount = 1, /* REVISIT how to disable? */ +}; + +static struct clk vpss_master_clk = { + .name = "vpss_master", + .parent = &pll1_sysclk3, + .lpsc = DAVINCI_LPSC_VPSSMSTR, + .flags = CLK_PSC, +}; + +static struct clk vpss_slave_clk = { + .name = "vpss_slave", + .parent = &pll1_sysclk3, + .lpsc = DAVINCI_LPSC_VPSSSLV, +}; + +static struct clk uart0_clk = { + .name = "uart0", + .parent = &pll1_aux_clk, + .lpsc = DAVINCI_LPSC_UART0, +}; + +static struct clk uart1_clk = { + .name = "uart1", + .parent = &pll1_aux_clk, + .lpsc = DAVINCI_LPSC_UART1, +}; + +static struct clk uart2_clk = { + .name = "uart2", + .parent = &pll1_aux_clk, + .lpsc = DAVINCI_LPSC_UART2, +}; + +static struct clk emac_clk = { + .name = "emac", + .parent = &pll1_sysclk5, + .lpsc = DAVINCI_LPSC_EMAC_WRAPPER, +}; + +static struct clk i2c_clk = { + .name = "i2c", + .parent = &pll1_aux_clk, + .lpsc = DAVINCI_LPSC_I2C, +}; + +static struct clk ide_clk = { + .name = "ide", + .parent = &pll1_sysclk5, + .lpsc = DAVINCI_LPSC_ATA, +}; + +static struct clk asp_clk = { + .name = "asp0", + .parent = &pll1_sysclk5, + .lpsc = DAVINCI_LPSC_McBSP, +}; + +static struct clk mmcsd_clk = { + .name = "mmcsd", + .parent = &pll1_sysclk5, + .lpsc = DAVINCI_LPSC_MMC_SD, +}; + +static struct clk spi_clk = { + .name = "spi", + .parent = &pll1_sysclk5, + .lpsc = DAVINCI_LPSC_SPI, +}; + +static struct clk gpio_clk = { + .name = "gpio", + .parent = &pll1_sysclk5, + .lpsc = DAVINCI_LPSC_GPIO, +}; + +static struct clk usb_clk = { + .name = "usb", + .parent = &pll1_sysclk5, + .lpsc = DAVINCI_LPSC_USB, +}; + +static struct clk vlynq_clk = { + .name = "vlynq", + .parent = &pll1_sysclk5, + .lpsc = DAVINCI_LPSC_VLYNQ, +}; + +static struct clk aemif_clk = { + .name = "aemif", + .parent = &pll1_sysclk5, + .lpsc = DAVINCI_LPSC_AEMIF, +}; + +static struct clk pwm0_clk = { + .name = "pwm0", + .parent = &pll1_aux_clk, + .lpsc = DAVINCI_LPSC_PWM0, +}; + +static struct clk pwm1_clk = { + .name = "pwm1", + .parent = &pll1_aux_clk, + .lpsc = DAVINCI_LPSC_PWM1, +}; + +static struct clk pwm2_clk = { + .name = "pwm2", + .parent = &pll1_aux_clk, + .lpsc = DAVINCI_LPSC_PWM2, +}; + +static struct clk timer0_clk = { + .name = "timer0", + .parent = &pll1_aux_clk, + .lpsc = DAVINCI_LPSC_TIMER0, +}; + +static struct clk timer1_clk = { + .name = "timer1", + .parent = &pll1_aux_clk, + .lpsc = DAVINCI_LPSC_TIMER1, +}; + +static struct clk timer2_clk = { + .name = "timer2", + .parent = &pll1_aux_clk, + .lpsc = DAVINCI_LPSC_TIMER2, + .usecount = 1, /* REVISIT: why cant' this be disabled? */ +}; + +struct davinci_clk dm644x_clks[] = { + CLK(NULL, "ref", &ref_clk), + CLK(NULL, "pll1", &pll1_clk), + CLK(NULL, "pll1_sysclk1", &pll1_sysclk1), + CLK(NULL, "pll1_sysclk2", &pll1_sysclk2), + CLK(NULL, "pll1_sysclk3", &pll1_sysclk3), + CLK(NULL, "pll1_sysclk5", &pll1_sysclk5), + CLK(NULL, "pll1_aux", &pll1_aux_clk), + CLK(NULL, "pll1_sysclkbp", &pll1_sysclkbp), + CLK(NULL, "pll2", &pll2_clk), + CLK(NULL, "pll2_sysclk1", &pll2_sysclk1), + CLK(NULL, "pll2_sysclk2", &pll2_sysclk2), + CLK(NULL, "pll2_sysclkbp", &pll2_sysclkbp), + CLK(NULL, "dsp", &dsp_clk), + CLK(NULL, "arm", &arm_clk), + CLK(NULL, "vicp", &vicp_clk), + CLK(NULL, "vpss_master", &vpss_master_clk), + CLK(NULL, "vpss_slave", &vpss_slave_clk), + CLK(NULL, "arm", &arm_clk), + CLK(NULL, "uart0", &uart0_clk), + CLK(NULL, "uart1", &uart1_clk), + CLK(NULL, "uart2", &uart2_clk), + CLK("davinci_emac.1", NULL, &emac_clk), + CLK("i2c_davinci.1", NULL, &i2c_clk), + CLK("palm_bk3710", NULL, &ide_clk), + CLK("soc-audio.0", NULL, &asp_clk), + CLK("davinci_mmc.0", NULL, &mmcsd_clk), + CLK(NULL, "spi", &spi_clk), + CLK(NULL, "gpio", &gpio_clk), + CLK(NULL, "usb", &usb_clk), + CLK(NULL, "vlynq", &vlynq_clk), + CLK(NULL, "aemif", &aemif_clk), + CLK(NULL, "pwm0", &pwm0_clk), + CLK(NULL, "pwm1", &pwm1_clk), + CLK(NULL, "pwm2", &pwm2_clk), + CLK(NULL, "timer0", &timer0_clk), + CLK(NULL, "timer1", &timer1_clk), + CLK("watchdog", NULL, &timer2_clk), + CLK(NULL, NULL, NULL), +}; + +#if defined(CONFIG_TI_DAVINCI_EMAC) || defined(CONFIG_TI_DAVINCI_EMAC_MODULE) + +static struct resource dm644x_emac_resources[] = { + { + .start = DM644X_EMAC_BASE, + .end = DM644X_EMAC_BASE + 0x47ff, + .flags = IORESOURCE_MEM, + }, + { + .start = IRQ_EMACINT, + .end = IRQ_EMACINT, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device dm644x_emac_device = { + .name = "davinci_emac", + .id = 1, + .num_resources = ARRAY_SIZE(dm644x_emac_resources), + .resource = dm644x_emac_resources, +}; + +#endif + +/* + * Device specific mux setup + * + * soc description mux mode mode mux dbg + * reg offset mask mode + */ +static const struct mux_config dm644x_pins[] = { +MUX_CFG(DM644X, HDIREN, 0, 16, 1, 1, true) +MUX_CFG(DM644X, ATAEN, 0, 17, 1, 1, true) +MUX_CFG(DM644X, ATAEN_DISABLE, 0, 17, 1, 0, true) + +MUX_CFG(DM644X, HPIEN_DISABLE, 0, 29, 1, 0, true) + +MUX_CFG(DM644X, AEAW, 0, 0, 31, 31, true) + +MUX_CFG(DM644X, MSTK, 1, 9, 1, 0, false) + +MUX_CFG(DM644X, I2C, 1, 7, 1, 1, false) + +MUX_CFG(DM644X, MCBSP, 1, 10, 1, 1, false) + +MUX_CFG(DM644X, UART1, 1, 1, 1, 1, true) +MUX_CFG(DM644X, UART2, 1, 2, 1, 1, true) + +MUX_CFG(DM644X, PWM0, 1, 4, 1, 1, false) + +MUX_CFG(DM644X, PWM1, 1, 5, 1, 1, false) + +MUX_CFG(DM644X, PWM2, 1, 6, 1, 1, false) + +MUX_CFG(DM644X, VLYNQEN, 0, 15, 1, 1, false) +MUX_CFG(DM644X, VLSCREN, 0, 14, 1, 1, false) +MUX_CFG(DM644X, VLYNQWD, 0, 12, 3, 3, false) + +MUX_CFG(DM644X, EMACEN, 0, 31, 1, 1, true) + +MUX_CFG(DM644X, GPIO3V, 0, 31, 1, 0, true) + +MUX_CFG(DM644X, GPIO0, 0, 24, 1, 0, true) +MUX_CFG(DM644X, GPIO3, 0, 25, 1, 0, false) +MUX_CFG(DM644X, GPIO43_44, 1, 7, 1, 0, false) +MUX_CFG(DM644X, GPIO46_47, 0, 22, 1, 0, true) + +MUX_CFG(DM644X, RGB666, 0, 22, 1, 1, true) + +MUX_CFG(DM644X, LOEEN, 0, 24, 1, 1, true) +MUX_CFG(DM644X, LFLDEN, 0, 25, 1, 1, false) +}; + + +/*----------------------------------------------------------------------*/ + +static const s8 dma_chan_dm644x_no_event[] = { + 0, 1, 12, 13, 14, + 15, 25, 30, 31, 45, + 46, 47, 55, 56, 57, + 58, 59, 60, 61, 62, + 63, + -1 +}; + +static struct edma_soc_info dm644x_edma_info = { + .n_channel = 64, + .n_region = 4, + .n_slot = 128, + .n_tc = 2, + .noevent = dma_chan_dm644x_no_event, +}; + +static struct resource edma_resources[] = { + { + .name = "edma_cc", + .start = 0x01c00000, + .end = 0x01c00000 + SZ_64K - 1, + .flags = IORESOURCE_MEM, + }, + { + .name = "edma_tc0", + .start = 0x01c10000, + .end = 0x01c10000 + SZ_1K - 1, + .flags = IORESOURCE_MEM, + }, + { + .name = "edma_tc1", + .start = 0x01c10400, + .end = 0x01c10400 + SZ_1K - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = IRQ_CCINT0, + .flags = IORESOURCE_IRQ, + }, + { + .start = IRQ_CCERRINT, + .flags = IORESOURCE_IRQ, + }, + /* not using TC*_ERR */ +}; + +static struct platform_device dm644x_edma_device = { + .name = "edma", + .id = -1, + .dev.platform_data = &dm644x_edma_info, + .num_resources = ARRAY_SIZE(edma_resources), + .resource = edma_resources, +}; + +/*----------------------------------------------------------------------*/ +void __init dm644x_init(void) +{ + davinci_clk_init(dm644x_clks); + davinci_mux_register(dm644x_pins, ARRAY_SIZE(dm644x_pins)); +} + +static int __init dm644x_init_devices(void) +{ + if (!cpu_is_davinci_dm644x()) + return 0; + + platform_device_register(&dm644x_edma_device); + return 0; +} +postcore_initcall(dm644x_init_devices); diff --git a/arch/arm/mach-davinci/dma.c b/arch/arm/mach-davinci/dma.c new file mode 100644 index 00000000000..15e9eb158bb --- /dev/null +++ b/arch/arm/mach-davinci/dma.c @@ -0,0 +1,1135 @@ +/* + * EDMA3 support for DaVinci + * + * Copyright (C) 2006-2009 Texas Instruments. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/interrupt.h> +#include <linux/platform_device.h> +#include <linux/spinlock.h> +#include <linux/compiler.h> +#include <linux/io.h> + +#include <mach/cputype.h> +#include <mach/memory.h> +#include <mach/hardware.h> +#include <mach/irqs.h> +#include <mach/edma.h> +#include <mach/mux.h> + + +/* Offsets matching "struct edmacc_param" */ +#define PARM_OPT 0x00 +#define PARM_SRC 0x04 +#define PARM_A_B_CNT 0x08 +#define PARM_DST 0x0c +#define PARM_SRC_DST_BIDX 0x10 +#define PARM_LINK_BCNTRLD 0x14 +#define PARM_SRC_DST_CIDX 0x18 +#define PARM_CCNT 0x1c + +#define PARM_SIZE 0x20 + +/* Offsets for EDMA CC global channel registers and their shadows */ +#define SH_ER 0x00 /* 64 bits */ +#define SH_ECR 0x08 /* 64 bits */ +#define SH_ESR 0x10 /* 64 bits */ +#define SH_CER 0x18 /* 64 bits */ +#define SH_EER 0x20 /* 64 bits */ +#define SH_EECR 0x28 /* 64 bits */ +#define SH_EESR 0x30 /* 64 bits */ +#define SH_SER 0x38 /* 64 bits */ +#define SH_SECR 0x40 /* 64 bits */ +#define SH_IER 0x50 /* 64 bits */ +#define SH_IECR 0x58 /* 64 bits */ +#define SH_IESR 0x60 /* 64 bits */ +#define SH_IPR 0x68 /* 64 bits */ +#define SH_ICR 0x70 /* 64 bits */ +#define SH_IEVAL 0x78 +#define SH_QER 0x80 +#define SH_QEER 0x84 +#define SH_QEECR 0x88 +#define SH_QEESR 0x8c +#define SH_QSER 0x90 +#define SH_QSECR 0x94 +#define SH_SIZE 0x200 + +/* Offsets for EDMA CC global registers */ +#define EDMA_REV 0x0000 +#define EDMA_CCCFG 0x0004 +#define EDMA_QCHMAP 0x0200 /* 8 registers */ +#define EDMA_DMAQNUM 0x0240 /* 8 registers (4 on OMAP-L1xx) */ +#define EDMA_QDMAQNUM 0x0260 +#define EDMA_QUETCMAP 0x0280 +#define EDMA_QUEPRI 0x0284 +#define EDMA_EMR 0x0300 /* 64 bits */ +#define EDMA_EMCR 0x0308 /* 64 bits */ +#define EDMA_QEMR 0x0310 +#define EDMA_QEMCR 0x0314 +#define EDMA_CCERR 0x0318 +#define EDMA_CCERRCLR 0x031c +#define EDMA_EEVAL 0x0320 +#define EDMA_DRAE 0x0340 /* 4 x 64 bits*/ +#define EDMA_QRAE 0x0380 /* 4 registers */ +#define EDMA_QUEEVTENTRY 0x0400 /* 2 x 16 registers */ +#define EDMA_QSTAT 0x0600 /* 2 registers */ +#define EDMA_QWMTHRA 0x0620 +#define EDMA_QWMTHRB 0x0624 +#define EDMA_CCSTAT 0x0640 + +#define EDMA_M 0x1000 /* global channel registers */ +#define EDMA_ECR 0x1008 +#define EDMA_ECRH 0x100C +#define EDMA_SHADOW0 0x2000 /* 4 regions shadowing global channels */ +#define EDMA_PARM 0x4000 /* 128 param entries */ + +#define DAVINCI_DMA_3PCC_BASE 0x01C00000 + +#define PARM_OFFSET(param_no) (EDMA_PARM + ((param_no) << 5)) + +#define EDMA_MAX_DMACH 64 +#define EDMA_MAX_PARAMENTRY 512 +#define EDMA_MAX_EVQUE 2 /* FIXME too small */ + + +/*****************************************************************************/ + +static void __iomem *edmacc_regs_base; + +static inline unsigned int edma_read(int offset) +{ + return (unsigned int)__raw_readl(edmacc_regs_base + offset); +} + +static inline void edma_write(int offset, int val) +{ + __raw_writel(val, edmacc_regs_base + offset); +} +static inline void edma_modify(int offset, unsigned and, unsigned or) +{ + unsigned val = edma_read(offset); + val &= and; + val |= or; + edma_write(offset, val); +} +static inline void edma_and(int offset, unsigned and) +{ + unsigned val = edma_read(offset); + val &= and; + edma_write(offset, val); +} +static inline void edma_or(int offset, unsigned or) +{ + unsigned val = edma_read(offset); + val |= or; + edma_write(offset, val); +} +static inline unsigned int edma_read_array(int offset, int i) +{ + return edma_read(offset + (i << 2)); +} +static inline void edma_write_array(int offset, int i, unsigned val) +{ + edma_write(offset + (i << 2), val); +} +static inline void edma_modify_array(int offset, int i, + unsigned and, unsigned or) +{ + edma_modify(offset + (i << 2), and, or); +} +static inline void edma_or_array(int offset, int i, unsigned or) +{ + edma_or(offset + (i << 2), or); +} +static inline void edma_or_array2(int offset, int i, int j, unsigned or) +{ + edma_or(offset + ((i*2 + j) << 2), or); +} +static inline void edma_write_array2(int offset, int i, int j, unsigned val) +{ + edma_write(offset + ((i*2 + j) << 2), val); +} +static inline unsigned int edma_shadow0_read(int offset) +{ + return edma_read(EDMA_SHADOW0 + offset); +} +static inline unsigned int edma_shadow0_read_array(int offset, int i) +{ + return edma_read(EDMA_SHADOW0 + offset + (i << 2)); +} +static inline void edma_shadow0_write(int offset, unsigned val) +{ + edma_write(EDMA_SHADOW0 + offset, val); +} +static inline void edma_shadow0_write_array(int offset, int i, unsigned val) +{ + edma_write(EDMA_SHADOW0 + offset + (i << 2), val); +} +static inline unsigned int edma_parm_read(int offset, int param_no) +{ + return edma_read(EDMA_PARM + offset + (param_no << 5)); +} +static inline void edma_parm_write(int offset, int param_no, unsigned val) +{ + edma_write(EDMA_PARM + offset + (param_no << 5), val); +} +static inline void edma_parm_modify(int offset, int param_no, + unsigned and, unsigned or) +{ + edma_modify(EDMA_PARM + offset + (param_no << 5), and, or); +} +static inline void edma_parm_and(int offset, int param_no, unsigned and) +{ + edma_and(EDMA_PARM + offset + (param_no << 5), and); +} +static inline void edma_parm_or(int offset, int param_no, unsigned or) +{ + edma_or(EDMA_PARM + offset + (param_no << 5), or); +} + +/*****************************************************************************/ + +/* actual number of DMA channels and slots on this silicon */ +static unsigned num_channels; +static unsigned num_slots; + +static struct dma_interrupt_data { + void (*callback)(unsigned channel, unsigned short ch_status, + void *data); + void *data; +} intr_data[EDMA_MAX_DMACH]; + +/* The edma_inuse bit for each PaRAM slot is clear unless the + * channel is in use ... by ARM or DSP, for QDMA, or whatever. + */ +static DECLARE_BITMAP(edma_inuse, EDMA_MAX_PARAMENTRY); + +/* The edma_noevent bit for each channel is clear unless + * it doesn't trigger DMA events on this platform. It uses a + * bit of SOC-specific initialization code. + */ +static DECLARE_BITMAP(edma_noevent, EDMA_MAX_DMACH); + +/* dummy param set used to (re)initialize parameter RAM slots */ +static const struct edmacc_param dummy_paramset = { + .link_bcntrld = 0xffff, + .ccnt = 1, +}; + +static const int __initconst +queue_tc_mapping[EDMA_MAX_EVQUE + 1][2] = { +/* {event queue no, TC no} */ + {0, 0}, + {1, 1}, + {-1, -1} +}; + +static const int __initconst +queue_priority_mapping[EDMA_MAX_EVQUE + 1][2] = { + /* {event queue no, Priority} */ + {0, 3}, + {1, 7}, + {-1, -1} +}; + +/*****************************************************************************/ + +static void map_dmach_queue(unsigned ch_no, enum dma_event_q queue_no) +{ + int bit = (ch_no & 0x7) * 4; + + /* default to low priority queue */ + if (queue_no == EVENTQ_DEFAULT) + queue_no = EVENTQ_1; + + queue_no &= 7; + edma_modify_array(EDMA_DMAQNUM, (ch_no >> 3), + ~(0x7 << bit), queue_no << bit); +} + +static void __init map_queue_tc(int queue_no, int tc_no) +{ + int bit = queue_no * 4; + edma_modify(EDMA_QUETCMAP, ~(0x7 << bit), ((tc_no & 0x7) << bit)); +} + +static void __init assign_priority_to_queue(int queue_no, int priority) +{ + int bit = queue_no * 4; + edma_modify(EDMA_QUEPRI, ~(0x7 << bit), ((priority & 0x7) << bit)); +} + +static inline void +setup_dma_interrupt(unsigned lch, + void (*callback)(unsigned channel, u16 ch_status, void *data), + void *data) +{ + if (!callback) { + edma_shadow0_write_array(SH_IECR, lch >> 5, + (1 << (lch & 0x1f))); + } + + intr_data[lch].callback = callback; + intr_data[lch].data = data; + + if (callback) { + edma_shadow0_write_array(SH_ICR, lch >> 5, + (1 << (lch & 0x1f))); + edma_shadow0_write_array(SH_IESR, lch >> 5, + (1 << (lch & 0x1f))); + } +} + +/****************************************************************************** + * + * DMA interrupt handler + * + *****************************************************************************/ +static irqreturn_t dma_irq_handler(int irq, void *data) +{ + int i; + unsigned int cnt = 0; + + dev_dbg(data, "dma_irq_handler\n"); + + if ((edma_shadow0_read_array(SH_IPR, 0) == 0) + && (edma_shadow0_read_array(SH_IPR, 1) == 0)) + return IRQ_NONE; + + while (1) { + int j; + if (edma_shadow0_read_array(SH_IPR, 0)) + j = 0; + else if (edma_shadow0_read_array(SH_IPR, 1)) + j = 1; + else + break; + dev_dbg(data, "IPR%d %08x\n", j, + edma_shadow0_read_array(SH_IPR, j)); + for (i = 0; i < 32; i++) { + int k = (j << 5) + i; + if (edma_shadow0_read_array(SH_IPR, j) & (1 << i)) { + /* Clear the corresponding IPR bits */ + edma_shadow0_write_array(SH_ICR, j, (1 << i)); + if (intr_data[k].callback) { + intr_data[k].callback(k, DMA_COMPLETE, + intr_data[k].data); + } + } + } + cnt++; + if (cnt > 10) + break; + } + edma_shadow0_write(SH_IEVAL, 1); + return IRQ_HANDLED; +} + +/****************************************************************************** + * + * DMA error interrupt handler + * + *****************************************************************************/ +static irqreturn_t dma_ccerr_handler(int irq, void *data) +{ + int i; + unsigned int cnt = 0; + + dev_dbg(data, "dma_ccerr_handler\n"); + + if ((edma_read_array(EDMA_EMR, 0) == 0) && + (edma_read_array(EDMA_EMR, 1) == 0) && + (edma_read(EDMA_QEMR) == 0) && (edma_read(EDMA_CCERR) == 0)) + return IRQ_NONE; + + while (1) { + int j = -1; + if (edma_read_array(EDMA_EMR, 0)) + j = 0; + else if (edma_read_array(EDMA_EMR, 1)) + j = 1; + if (j >= 0) { + dev_dbg(data, "EMR%d %08x\n", j, + edma_read_array(EDMA_EMR, j)); + for (i = 0; i < 32; i++) { + int k = (j << 5) + i; + if (edma_read_array(EDMA_EMR, j) & (1 << i)) { + /* Clear the corresponding EMR bits */ + edma_write_array(EDMA_EMCR, j, 1 << i); + /* Clear any SER */ + edma_shadow0_write_array(SH_SECR, j, + (1 << i)); + if (intr_data[k].callback) { + intr_data[k].callback(k, + DMA_CC_ERROR, + intr_data + [k].data); + } + } + } + } else if (edma_read(EDMA_QEMR)) { + dev_dbg(data, "QEMR %02x\n", + edma_read(EDMA_QEMR)); + for (i = 0; i < 8; i++) { + if (edma_read(EDMA_QEMR) & (1 << i)) { + /* Clear the corresponding IPR bits */ + edma_write(EDMA_QEMCR, 1 << i); + edma_shadow0_write(SH_QSECR, (1 << i)); + + /* NOTE: not reported!! */ + } + } + } else if (edma_read(EDMA_CCERR)) { + dev_dbg(data, "CCERR %08x\n", + edma_read(EDMA_CCERR)); + /* FIXME: CCERR.BIT(16) ignored! much better + * to just write CCERRCLR with CCERR value... + */ + for (i = 0; i < 8; i++) { + if (edma_read(EDMA_CCERR) & (1 << i)) { + /* Clear the corresponding IPR bits */ + edma_write(EDMA_CCERRCLR, 1 << i); + + /* NOTE: not reported!! */ + } + } + } + if ((edma_read_array(EDMA_EMR, 0) == 0) + && (edma_read_array(EDMA_EMR, 1) == 0) + && (edma_read(EDMA_QEMR) == 0) + && (edma_read(EDMA_CCERR) == 0)) { + break; + } + cnt++; + if (cnt > 10) + break; + } + edma_write(EDMA_EEVAL, 1); + return IRQ_HANDLED; +} + +/****************************************************************************** + * + * Transfer controller error interrupt handlers + * + *****************************************************************************/ + +#define tc_errs_handled false /* disabled as long as they're NOPs */ + +static irqreturn_t dma_tc0err_handler(int irq, void *data) +{ + dev_dbg(data, "dma_tc0err_handler\n"); + return IRQ_HANDLED; +} + +static irqreturn_t dma_tc1err_handler(int irq, void *data) +{ + dev_dbg(data, "dma_tc1err_handler\n"); + return IRQ_HANDLED; +} + +/*-----------------------------------------------------------------------*/ + +/* Resource alloc/free: dma channels, parameter RAM slots */ + +/** + * edma_alloc_channel - allocate DMA channel and paired parameter RAM + * @channel: specific channel to allocate; negative for "any unmapped channel" + * @callback: optional; to be issued on DMA completion or errors + * @data: passed to callback + * @eventq_no: an EVENTQ_* constant, used to choose which Transfer + * Controller (TC) executes requests using this channel. Use + * EVENTQ_DEFAULT unless you really need a high priority queue. + * + * This allocates a DMA channel and its associated parameter RAM slot. + * The parameter RAM is initialized to hold a dummy transfer. + * + * Normal use is to pass a specific channel number as @channel, to make + * use of hardware events mapped to that channel. When the channel will + * be used only for software triggering or event chaining, channels not + * mapped to hardware events (or mapped to unused events) are preferable. + * + * DMA transfers start from a channel using edma_start(), or by + * chaining. When the transfer described in that channel's parameter RAM + * slot completes, that slot's data may be reloaded through a link. + * + * DMA errors are only reported to the @callback associated with the + * channel driving that transfer, but transfer completion callbacks can + * be sent to another channel under control of the TCC field in + * the option word of the transfer's parameter RAM set. Drivers must not + * use DMA transfer completion callbacks for channels they did not allocate. + * (The same applies to TCC codes used in transfer chaining.) + * + * Returns the number of the channel, else negative errno. + */ +int edma_alloc_channel(int channel, + void (*callback)(unsigned channel, u16 ch_status, void *data), + void *data, + enum dma_event_q eventq_no) +{ + if (channel < 0) { + channel = 0; + for (;;) { + channel = find_next_bit(edma_noevent, + num_channels, channel); + if (channel == num_channels) + return -ENOMEM; + if (!test_and_set_bit(channel, edma_inuse)) + break; + channel++; + } + } else if (channel >= num_channels) { + return -EINVAL; + } else if (test_and_set_bit(channel, edma_inuse)) { + return -EBUSY; + } + + /* ensure access through shadow region 0 */ + edma_or_array2(EDMA_DRAE, 0, channel >> 5, 1 << (channel & 0x1f)); + + /* ensure no events are pending */ + edma_stop(channel); + memcpy_toio(edmacc_regs_base + PARM_OFFSET(channel), + &dummy_paramset, PARM_SIZE); + + if (callback) + setup_dma_interrupt(channel, callback, data); + + map_dmach_queue(channel, eventq_no); + + return channel; +} +EXPORT_SYMBOL(edma_alloc_channel); + + +/** + * edma_free_channel - deallocate DMA channel + * @channel: dma channel returned from edma_alloc_channel() + * + * This deallocates the DMA channel and associated parameter RAM slot + * allocated by edma_alloc_channel(). + * + * Callers are responsible for ensuring the channel is inactive, and + * will not be reactivated by linking, chaining, or software calls to + * edma_start(). + */ +void edma_free_channel(unsigned channel) +{ + if (channel >= num_channels) + return; + + setup_dma_interrupt(channel, NULL, NULL); + /* REVISIT should probably take out of shadow region 0 */ + + memcpy_toio(edmacc_regs_base + PARM_OFFSET(channel), + &dummy_paramset, PARM_SIZE); + clear_bit(channel, edma_inuse); +} +EXPORT_SYMBOL(edma_free_channel); + +/** + * edma_alloc_slot - allocate DMA parameter RAM + * @slot: specific slot to allocate; negative for "any unused slot" + * + * This allocates a parameter RAM slot, initializing it to hold a + * dummy transfer. Slots allocated using this routine have not been + * mapped to a hardware DMA channel, and will normally be used by + * linking to them from a slot associated with a DMA channel. + * + * Normal use is to pass EDMA_SLOT_ANY as the @slot, but specific + * slots may be allocated on behalf of DSP firmware. + * + * Returns the number of the slot, else negative errno. + */ +int edma_alloc_slot(int slot) +{ + if (slot < 0) { + slot = num_channels; + for (;;) { + slot = find_next_zero_bit(edma_inuse, + num_slots, slot); + if (slot == num_slots) + return -ENOMEM; + if (!test_and_set_bit(slot, edma_inuse)) + break; + } + } else if (slot < num_channels || slot >= num_slots) { + return -EINVAL; + } else if (test_and_set_bit(slot, edma_inuse)) { + return -EBUSY; + } + + memcpy_toio(edmacc_regs_base + PARM_OFFSET(slot), + &dummy_paramset, PARM_SIZE); + + return slot; +} +EXPORT_SYMBOL(edma_alloc_slot); + +/** + * edma_free_slot - deallocate DMA parameter RAM + * @slot: parameter RAM slot returned from edma_alloc_slot() + * + * This deallocates the parameter RAM slot allocated by edma_alloc_slot(). + * Callers are responsible for ensuring the slot is inactive, and will + * not be activated. + */ +void edma_free_slot(unsigned slot) +{ + if (slot < num_channels || slot >= num_slots) + return; + + memcpy_toio(edmacc_regs_base + PARM_OFFSET(slot), + &dummy_paramset, PARM_SIZE); + clear_bit(slot, edma_inuse); +} +EXPORT_SYMBOL(edma_free_slot); + +/*-----------------------------------------------------------------------*/ + +/* Parameter RAM operations (i) -- read/write partial slots */ + +/** + * edma_set_src - set initial DMA source address in parameter RAM slot + * @slot: parameter RAM slot being configured + * @src_port: physical address of source (memory, controller FIFO, etc) + * @addressMode: INCR, except in very rare cases + * @fifoWidth: ignored unless @addressMode is FIFO, else specifies the + * width to use when addressing the fifo (e.g. W8BIT, W32BIT) + * + * Note that the source address is modified during the DMA transfer + * according to edma_set_src_index(). + */ +void edma_set_src(unsigned slot, dma_addr_t src_port, + enum address_mode mode, enum fifo_width width) +{ + if (slot < num_slots) { + unsigned int i = edma_parm_read(PARM_OPT, slot); + + if (mode) { + /* set SAM and program FWID */ + i = (i & ~(EDMA_FWID)) | (SAM | ((width & 0x7) << 8)); + } else { + /* clear SAM */ + i &= ~SAM; + } + edma_parm_write(PARM_OPT, slot, i); + + /* set the source port address + in source register of param structure */ + edma_parm_write(PARM_SRC, slot, src_port); + } +} +EXPORT_SYMBOL(edma_set_src); + +/** + * edma_set_dest - set initial DMA destination address in parameter RAM slot + * @slot: parameter RAM slot being configured + * @dest_port: physical address of destination (memory, controller FIFO, etc) + * @addressMode: INCR, except in very rare cases + * @fifoWidth: ignored unless @addressMode is FIFO, else specifies the + * width to use when addressing the fifo (e.g. W8BIT, W32BIT) + * + * Note that the destination address is modified during the DMA transfer + * according to edma_set_dest_index(). + */ +void edma_set_dest(unsigned slot, dma_addr_t dest_port, + enum address_mode mode, enum fifo_width width) +{ + if (slot < num_slots) { + unsigned int i = edma_parm_read(PARM_OPT, slot); + + if (mode) { + /* set DAM and program FWID */ + i = (i & ~(EDMA_FWID)) | (DAM | ((width & 0x7) << 8)); + } else { + /* clear DAM */ + i &= ~DAM; + } + edma_parm_write(PARM_OPT, slot, i); + /* set the destination port address + in dest register of param structure */ + edma_parm_write(PARM_DST, slot, dest_port); + } +} +EXPORT_SYMBOL(edma_set_dest); + +/** + * edma_get_position - returns the current transfer points + * @slot: parameter RAM slot being examined + * @src: pointer to source port position + * @dst: pointer to destination port position + * + * Returns current source and destination addresses for a particular + * parameter RAM slot. Its channel should not be active when this is called. + */ +void edma_get_position(unsigned slot, dma_addr_t *src, dma_addr_t *dst) +{ + struct edmacc_param temp; + + edma_read_slot(slot, &temp); + if (src != NULL) + *src = temp.src; + if (dst != NULL) + *dst = temp.dst; +} +EXPORT_SYMBOL(edma_get_position); + +/** + * edma_set_src_index - configure DMA source address indexing + * @slot: parameter RAM slot being configured + * @src_bidx: byte offset between source arrays in a frame + * @src_cidx: byte offset between source frames in a block + * + * Offsets are specified to support either contiguous or discontiguous + * memory transfers, or repeated access to a hardware register, as needed. + * When accessing hardware registers, both offsets are normally zero. + */ +void edma_set_src_index(unsigned slot, s16 src_bidx, s16 src_cidx) +{ + if (slot < num_slots) { + edma_parm_modify(PARM_SRC_DST_BIDX, slot, + 0xffff0000, src_bidx); + edma_parm_modify(PARM_SRC_DST_CIDX, slot, + 0xffff0000, src_cidx); + } +} +EXPORT_SYMBOL(edma_set_src_index); + +/** + * edma_set_dest_index - configure DMA destination address indexing + * @slot: parameter RAM slot being configured + * @dest_bidx: byte offset between destination arrays in a frame + * @dest_cidx: byte offset between destination frames in a block + * + * Offsets are specified to support either contiguous or discontiguous + * memory transfers, or repeated access to a hardware register, as needed. + * When accessing hardware registers, both offsets are normally zero. + */ +void edma_set_dest_index(unsigned slot, s16 dest_bidx, s16 dest_cidx) +{ + if (slot < num_slots) { + edma_parm_modify(PARM_SRC_DST_BIDX, slot, + 0x0000ffff, dest_bidx << 16); + edma_parm_modify(PARM_SRC_DST_CIDX, slot, + 0x0000ffff, dest_cidx << 16); + } +} +EXPORT_SYMBOL(edma_set_dest_index); + +/** + * edma_set_transfer_params - configure DMA transfer parameters + * @slot: parameter RAM slot being configured + * @acnt: how many bytes per array (at least one) + * @bcnt: how many arrays per frame (at least one) + * @ccnt: how many frames per block (at least one) + * @bcnt_rld: used only for A-Synchronized transfers; this specifies + * the value to reload into bcnt when it decrements to zero + * @sync_mode: ASYNC or ABSYNC + * + * See the EDMA3 documentation to understand how to configure and link + * transfers using the fields in PaRAM slots. If you are not doing it + * all at once with edma_write_slot(), you will use this routine + * plus two calls each for source and destination, setting the initial + * address and saying how to index that address. + * + * An example of an A-Synchronized transfer is a serial link using a + * single word shift register. In that case, @acnt would be equal to + * that word size; the serial controller issues a DMA synchronization + * event to transfer each word, and memory access by the DMA transfer + * controller will be word-at-a-time. + * + * An example of an AB-Synchronized transfer is a device using a FIFO. + * In that case, @acnt equals the FIFO width and @bcnt equals its depth. + * The controller with the FIFO issues DMA synchronization events when + * the FIFO threshold is reached, and the DMA transfer controller will + * transfer one frame to (or from) the FIFO. It will probably use + * efficient burst modes to access memory. + */ +void edma_set_transfer_params(unsigned slot, + u16 acnt, u16 bcnt, u16 ccnt, + u16 bcnt_rld, enum sync_dimension sync_mode) +{ + if (slot < num_slots) { + edma_parm_modify(PARM_LINK_BCNTRLD, slot, + 0x0000ffff, bcnt_rld << 16); + if (sync_mode == ASYNC) + edma_parm_and(PARM_OPT, slot, ~SYNCDIM); + else + edma_parm_or(PARM_OPT, slot, SYNCDIM); + /* Set the acount, bcount, ccount registers */ + edma_parm_write(PARM_A_B_CNT, slot, (bcnt << 16) | acnt); + edma_parm_write(PARM_CCNT, slot, ccnt); + } +} +EXPORT_SYMBOL(edma_set_transfer_params); + +/** + * edma_link - link one parameter RAM slot to another + * @from: parameter RAM slot originating the link + * @to: parameter RAM slot which is the link target + * + * The originating slot should not be part of any active DMA transfer. + */ +void edma_link(unsigned from, unsigned to) +{ + if (from >= num_slots) + return; + if (to >= num_slots) + return; + edma_parm_modify(PARM_LINK_BCNTRLD, from, 0xffff0000, PARM_OFFSET(to)); +} +EXPORT_SYMBOL(edma_link); + +/** + * edma_unlink - cut link from one parameter RAM slot + * @from: parameter RAM slot originating the link + * + * The originating slot should not be part of any active DMA transfer. + * Its link is set to 0xffff. + */ +void edma_unlink(unsigned from) +{ + if (from >= num_slots) + return; + edma_parm_or(PARM_LINK_BCNTRLD, from, 0xffff); +} +EXPORT_SYMBOL(edma_unlink); + +/*-----------------------------------------------------------------------*/ + +/* Parameter RAM operations (ii) -- read/write whole parameter sets */ + +/** + * edma_write_slot - write parameter RAM data for slot + * @slot: number of parameter RAM slot being modified + * @param: data to be written into parameter RAM slot + * + * Use this to assign all parameters of a transfer at once. This + * allows more efficient setup of transfers than issuing multiple + * calls to set up those parameters in small pieces, and provides + * complete control over all transfer options. + */ +void edma_write_slot(unsigned slot, const struct edmacc_param *param) +{ + if (slot >= num_slots) + return; + memcpy_toio(edmacc_regs_base + PARM_OFFSET(slot), param, PARM_SIZE); +} +EXPORT_SYMBOL(edma_write_slot); + +/** + * edma_read_slot - read parameter RAM data from slot + * @slot: number of parameter RAM slot being copied + * @param: where to store copy of parameter RAM data + * + * Use this to read data from a parameter RAM slot, perhaps to + * save them as a template for later reuse. + */ +void edma_read_slot(unsigned slot, struct edmacc_param *param) +{ + if (slot >= num_slots) + return; + memcpy_fromio(param, edmacc_regs_base + PARM_OFFSET(slot), PARM_SIZE); +} +EXPORT_SYMBOL(edma_read_slot); + +/*-----------------------------------------------------------------------*/ + +/* Various EDMA channel control operations */ + +/** + * edma_pause - pause dma on a channel + * @channel: on which edma_start() has been called + * + * This temporarily disables EDMA hardware events on the specified channel, + * preventing them from triggering new transfers on its behalf + */ +void edma_pause(unsigned channel) +{ + if (channel < num_channels) { + unsigned int mask = (1 << (channel & 0x1f)); + + edma_shadow0_write_array(SH_EECR, channel >> 5, mask); + } +} +EXPORT_SYMBOL(edma_pause); + +/** + * edma_resume - resumes dma on a paused channel + * @channel: on which edma_pause() has been called + * + * This re-enables EDMA hardware events on the specified channel. + */ +void edma_resume(unsigned channel) +{ + if (channel < num_channels) { + unsigned int mask = (1 << (channel & 0x1f)); + + edma_shadow0_write_array(SH_EESR, channel >> 5, mask); + } +} +EXPORT_SYMBOL(edma_resume); + +/** + * edma_start - start dma on a channel + * @channel: channel being activated + * + * Channels with event associations will be triggered by their hardware + * events, and channels without such associations will be triggered by + * software. (At this writing there is no interface for using software + * triggers except with channels that don't support hardware triggers.) + * + * Returns zero on success, else negative errno. + */ +int edma_start(unsigned channel) +{ + if (channel < num_channels) { + int j = channel >> 5; + unsigned int mask = (1 << (channel & 0x1f)); + + /* EDMA channels without event association */ + if (test_bit(channel, edma_noevent)) { + pr_debug("EDMA: ESR%d %08x\n", j, + edma_shadow0_read_array(SH_ESR, j)); + edma_shadow0_write_array(SH_ESR, j, mask); + return 0; + } + + /* EDMA channel with event association */ + pr_debug("EDMA: ER%d %08x\n", j, + edma_shadow0_read_array(SH_ER, j)); + /* Clear any pending error */ + edma_write_array(EDMA_EMCR, j, mask); + /* Clear any SER */ + edma_shadow0_write_array(SH_SECR, j, mask); + edma_shadow0_write_array(SH_EESR, j, mask); + pr_debug("EDMA: EER%d %08x\n", j, + edma_shadow0_read_array(SH_EER, j)); + return 0; + } + + return -EINVAL; +} +EXPORT_SYMBOL(edma_start); + +/** + * edma_stop - stops dma on the channel passed + * @channel: channel being deactivated + * + * When @lch is a channel, any active transfer is paused and + * all pending hardware events are cleared. The current transfer + * may not be resumed, and the channel's Parameter RAM should be + * reinitialized before being reused. + */ +void edma_stop(unsigned channel) +{ + if (channel < num_channels) { + int j = channel >> 5; + unsigned int mask = (1 << (channel & 0x1f)); + + edma_shadow0_write_array(SH_EECR, j, mask); + edma_shadow0_write_array(SH_ECR, j, mask); + edma_shadow0_write_array(SH_SECR, j, mask); + edma_write_array(EDMA_EMCR, j, mask); + + pr_debug("EDMA: EER%d %08x\n", j, + edma_shadow0_read_array(SH_EER, j)); + + /* REVISIT: consider guarding against inappropriate event + * chaining by overwriting with dummy_paramset. + */ + } +} +EXPORT_SYMBOL(edma_stop); + +/****************************************************************************** + * + * It cleans ParamEntry qand bring back EDMA to initial state if media has + * been removed before EDMA has finished.It is usedful for removable media. + * Arguments: + * ch_no - channel no + * + * Return: zero on success, or corresponding error no on failure + * + * FIXME this should not be needed ... edma_stop() should suffice. + * + *****************************************************************************/ + +void edma_clean_channel(unsigned channel) +{ + if (channel < num_channels) { + int j = (channel >> 5); + unsigned int mask = 1 << (channel & 0x1f); + + pr_debug("EDMA: EMR%d %08x\n", j, + edma_read_array(EDMA_EMR, j)); + edma_shadow0_write_array(SH_ECR, j, mask); + /* Clear the corresponding EMR bits */ + edma_write_array(EDMA_EMCR, j, mask); + /* Clear any SER */ + edma_shadow0_write_array(SH_SECR, j, mask); + edma_write(EDMA_CCERRCLR, (1 << 16) | 0x3); + } +} +EXPORT_SYMBOL(edma_clean_channel); + +/* + * edma_clear_event - clear an outstanding event on the DMA channel + * Arguments: + * channel - channel number + */ +void edma_clear_event(unsigned channel) +{ + if (channel >= num_channels) + return; + if (channel < 32) + edma_write(EDMA_ECR, 1 << channel); + else + edma_write(EDMA_ECRH, 1 << (channel - 32)); +} +EXPORT_SYMBOL(edma_clear_event); + +/*-----------------------------------------------------------------------*/ + +static int __init edma_probe(struct platform_device *pdev) +{ + struct edma_soc_info *info = pdev->dev.platform_data; + int i; + int status; + const s8 *noevent; + int irq = 0, err_irq = 0; + struct resource *r; + resource_size_t len; + + if (!info) + return -ENODEV; + + r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "edma_cc"); + if (!r) + return -ENODEV; + + len = r->end - r->start + 1; + + r = request_mem_region(r->start, len, r->name); + if (!r) + return -EBUSY; + + edmacc_regs_base = ioremap(r->start, len); + if (!edmacc_regs_base) { + status = -EBUSY; + goto fail1; + } + + num_channels = min_t(unsigned, info->n_channel, EDMA_MAX_DMACH); + num_slots = min_t(unsigned, info->n_slot, EDMA_MAX_PARAMENTRY); + + dev_dbg(&pdev->dev, "DMA REG BASE ADDR=%p\n", edmacc_regs_base); + + for (i = 0; i < num_slots; i++) + memcpy_toio(edmacc_regs_base + PARM_OFFSET(i), + &dummy_paramset, PARM_SIZE); + + noevent = info->noevent; + if (noevent) { + while (*noevent != -1) + set_bit(*noevent++, edma_noevent); + } + + irq = platform_get_irq(pdev, 0); + status = request_irq(irq, dma_irq_handler, 0, "edma", &pdev->dev); + if (status < 0) { + dev_dbg(&pdev->dev, "request_irq %d failed --> %d\n", + irq, status); + goto fail; + } + + err_irq = platform_get_irq(pdev, 1); + status = request_irq(err_irq, dma_ccerr_handler, 0, + "edma_error", &pdev->dev); + if (status < 0) { + dev_dbg(&pdev->dev, "request_irq %d failed --> %d\n", + err_irq, status); + goto fail; + } + + if (tc_errs_handled) { + status = request_irq(IRQ_TCERRINT0, dma_tc0err_handler, 0, + "edma_tc0", &pdev->dev); + if (status < 0) { + dev_dbg(&pdev->dev, "request_irq %d failed --> %d\n", + IRQ_TCERRINT0, status); + return status; + } + status = request_irq(IRQ_TCERRINT, dma_tc1err_handler, 0, + "edma_tc1", &pdev->dev); + if (status < 0) { + dev_dbg(&pdev->dev, "request_irq %d --> %d\n", + IRQ_TCERRINT, status); + return status; + } + } + + /* Everything lives on transfer controller 1 until otherwise specified. + * This way, long transfers on the low priority queue + * started by the codec engine will not cause audio defects. + */ + for (i = 0; i < num_channels; i++) + map_dmach_queue(i, EVENTQ_1); + + /* Event queue to TC mapping */ + for (i = 0; queue_tc_mapping[i][0] != -1; i++) + map_queue_tc(queue_tc_mapping[i][0], queue_tc_mapping[i][1]); + + /* Event queue priority mapping */ + for (i = 0; queue_priority_mapping[i][0] != -1; i++) + assign_priority_to_queue(queue_priority_mapping[i][0], + queue_priority_mapping[i][1]); + + for (i = 0; i < info->n_region; i++) { + edma_write_array2(EDMA_DRAE, i, 0, 0x0); + edma_write_array2(EDMA_DRAE, i, 1, 0x0); + edma_write_array(EDMA_QRAE, i, 0x0); + } + + return 0; + +fail: + if (err_irq) + free_irq(err_irq, NULL); + if (irq) + free_irq(irq, NULL); + iounmap(edmacc_regs_base); +fail1: + release_mem_region(r->start, len); + return status; +} + + +static struct platform_driver edma_driver = { + .driver.name = "edma", +}; + +static int __init edma_init(void) +{ + return platform_driver_probe(&edma_driver, edma_probe); +} +arch_initcall(edma_init); + diff --git a/arch/arm/mach-davinci/gpio.c b/arch/arm/mach-davinci/gpio.c index b49e9d092aa..1aba41c6351 100644 --- a/arch/arm/mach-davinci/gpio.c +++ b/arch/arm/mach-davinci/gpio.c @@ -20,6 +20,7 @@ #include <linux/irq.h> #include <linux/bitops.h> +#include <mach/cputype.h> #include <mach/irqs.h> #include <mach/hardware.h> #include <mach/gpio.h> @@ -36,9 +37,10 @@ struct davinci_gpio { static struct davinci_gpio chips[DIV_ROUND_UP(DAVINCI_N_GPIO, 32)]; +static unsigned __initdata ngpio; /* create a non-inlined version */ -static struct gpio_controller *__iomem __init gpio2controller(unsigned gpio) +static struct gpio_controller __iomem * __init gpio2controller(unsigned gpio) { return __gpio_to_controller(gpio); } @@ -114,9 +116,30 @@ static int __init davinci_gpio_setup(void) { int i, base; - for (i = 0, base = 0; - i < ARRAY_SIZE(chips); - i++, base += 32) { + /* The gpio banks conceptually expose a segmented bitmap, + * and "ngpio" is one more than the largest zero-based + * bit index that's valid. + */ + if (cpu_is_davinci_dm355()) { /* or dm335() */ + ngpio = 104; + } else if (cpu_is_davinci_dm644x()) { /* or dm337() */ + ngpio = 71; + } else if (cpu_is_davinci_dm646x()) { + /* NOTE: each bank has several "reserved" bits, + * unusable as GPIOs. Only 33 of the GPIO numbers + * are usable, and we're not rejecting the others. + */ + ngpio = 43; + } else { + /* if cpu_is_davinci_dm643x() ngpio = 111 */ + pr_err("GPIO setup: how many GPIOs?\n"); + return -EINVAL; + } + + if (WARN_ON(DAVINCI_N_GPIO < ngpio)) + ngpio = DAVINCI_N_GPIO; + + for (i = 0, base = 0; base < ngpio; i++, base += 32) { chips[i].chip.label = "DaVinci"; chips[i].chip.direction_input = davinci_direction_in; @@ -125,7 +148,7 @@ static int __init davinci_gpio_setup(void) chips[i].chip.set = davinci_gpio_set; chips[i].chip.base = base; - chips[i].chip.ngpio = DAVINCI_N_GPIO - base; + chips[i].chip.ngpio = ngpio - base; if (chips[i].chip.ngpio > 32) chips[i].chip.ngpio = 32; @@ -143,11 +166,11 @@ pure_initcall(davinci_gpio_setup); * We expect irqs will normally be set up as input pins, but they can also be * used as output pins ... which is convenient for testing. * - * NOTE: GPIO0..GPIO7 also have direct INTC hookups, which work in addition - * to their GPIOBNK0 irq (but with a bit less overhead). But we don't have - * a good way to hook those up ... + * NOTE: The first few GPIOs also have direct INTC hookups in addition + * to their GPIOBNK0 irq, with a bit less overhead but less flexibility + * on triggering (e.g. no edge options). We don't try to use those. * - * All those INTC hookups (GPIO0..GPIO7 plus five IRQ banks) can also + * All those INTC hookups (direct, plus several IRQ banks) can also * serve as EDMA event triggers. */ @@ -235,29 +258,42 @@ gpio_irq_handler(unsigned irq, struct irq_desc *desc) } /* - * NOTE: for suspend/resume, probably best to make a sysdev (and class) - * with its suspend/resume calls hooking into the results of the set_wake() + * NOTE: for suspend/resume, probably best to make a platform_device with + * suspend_late/resume_resume calls hooking into results of the set_wake() * calls ... so if no gpios are wakeup events the clock can be disabled, * with outputs left at previously set levels, and so that VDD3P3V.IOPWDN0 - * can be set appropriately for GPIOV33 pins. + * (dm6446) can be set appropriately for GPIOV33 pins. */ static int __init davinci_gpio_irq_setup(void) { unsigned gpio, irq, bank; + unsigned bank_irq; struct clk *clk; + u32 binten = 0; + + if (cpu_is_davinci_dm355()) { /* or dm335() */ + bank_irq = IRQ_DM355_GPIOBNK0; + } else if (cpu_is_davinci_dm644x()) { + bank_irq = IRQ_GPIOBNK0; + } else if (cpu_is_davinci_dm646x()) { + bank_irq = IRQ_DM646X_GPIOBNK0; + } else { + printk(KERN_ERR "Don't know first GPIO bank IRQ.\n"); + return -EINVAL; + } clk = clk_get(NULL, "gpio"); if (IS_ERR(clk)) { printk(KERN_ERR "Error %ld getting gpio clock?\n", PTR_ERR(clk)); - return 0; + return PTR_ERR(clk); } - clk_enable(clk); - for (gpio = 0, irq = gpio_to_irq(0), bank = IRQ_GPIOBNK0; - gpio < DAVINCI_N_GPIO; bank++) { + for (gpio = 0, irq = gpio_to_irq(0), bank = 0; + gpio < ngpio; + bank++, bank_irq++) { struct gpio_controller *__iomem g = gpio2controller(gpio); unsigned i; @@ -265,28 +301,28 @@ static int __init davinci_gpio_irq_setup(void) __raw_writel(~0, &g->clr_rising); /* set up all irqs in this bank */ - set_irq_chained_handler(bank, gpio_irq_handler); - set_irq_chip_data(bank, g); - set_irq_data(bank, (void *)irq); + set_irq_chained_handler(bank_irq, gpio_irq_handler); + set_irq_chip_data(bank_irq, g); + set_irq_data(bank_irq, (void *)irq); - for (i = 0; i < 16 && gpio < DAVINCI_N_GPIO; - i++, irq++, gpio++) { + for (i = 0; i < 16 && gpio < ngpio; i++, irq++, gpio++) { set_irq_chip(irq, &gpio_irqchip); set_irq_chip_data(irq, g); set_irq_handler(irq, handle_simple_irq); set_irq_flags(irq, IRQF_VALID); } + + binten |= BIT(bank); } /* BINTEN -- per-bank interrupt enable. genirq would also let these * bits be set/cleared dynamically. */ - __raw_writel(0x1f, (void *__iomem) + __raw_writel(binten, (void *__iomem) IO_ADDRESS(DAVINCI_GPIO_BASE + 0x08)); printk(KERN_INFO "DaVinci: %d gpio irqs\n", irq - gpio_to_irq(0)); return 0; } - arch_initcall(davinci_gpio_irq_setup); diff --git a/arch/arm/mach-davinci/id.c b/arch/arm/mach-davinci/id.c index bf067d60491..018b994cd79 100644 --- a/arch/arm/mach-davinci/id.c +++ b/arch/arm/mach-davinci/id.c @@ -15,7 +15,9 @@ #include <linux/init.h> #include <linux/io.h> -#define JTAG_ID_BASE 0x01c40028 +#define JTAG_ID_BASE IO_ADDRESS(0x01c40028) + +static unsigned int davinci_revision; struct davinci_id { u8 variant; /* JTAG ID bits 31:28 */ @@ -33,6 +35,20 @@ static struct davinci_id davinci_ids[] __initdata = { .manufacturer = 0x017, .type = 0x64460000, }, + { + /* DM646X */ + .part_no = 0xb770, + .variant = 0x0, + .manufacturer = 0x017, + .type = 0x64670000, + }, + { + /* DM355 */ + .part_no = 0xb73b, + .variant = 0x0, + .manufacturer = 0x00f, + .type = 0x03550000, + }, }; /* @@ -42,7 +58,7 @@ static u16 __init davinci_get_part_no(void) { u32 dev_id, part_no; - dev_id = davinci_readl(JTAG_ID_BASE); + dev_id = __raw_readl(JTAG_ID_BASE); part_no = ((dev_id >> 12) & 0xffff); @@ -56,13 +72,19 @@ static u8 __init davinci_get_variant(void) { u32 variant; - variant = davinci_readl(JTAG_ID_BASE); + variant = __raw_readl(JTAG_ID_BASE); variant = (variant >> 28) & 0xf; return variant; } +unsigned int davinci_rev(void) +{ + return davinci_revision >> 16; +} +EXPORT_SYMBOL(davinci_rev); + void __init davinci_check_revision(void) { int i; @@ -75,7 +97,7 @@ void __init davinci_check_revision(void) /* First check only the major version in a safe way */ for (i = 0; i < ARRAY_SIZE(davinci_ids); i++) { if (part_no == (davinci_ids[i].part_no)) { - system_rev = davinci_ids[i].type; + davinci_revision = davinci_ids[i].type; break; } } @@ -84,10 +106,11 @@ void __init davinci_check_revision(void) for (i = 0; i < ARRAY_SIZE(davinci_ids); i++) { if (part_no == davinci_ids[i].part_no && variant == davinci_ids[i].variant) { - system_rev = davinci_ids[i].type; + davinci_revision = davinci_ids[i].type; break; } } - printk("DaVinci DM%04x variant 0x%x\n", system_rev >> 16, variant); + printk(KERN_INFO "DaVinci DM%04x variant 0x%x\n", + davinci_rev(), variant); } diff --git a/arch/arm/mach-davinci/include/mach/board-dm6446evm.h b/arch/arm/mach-davinci/include/mach/board-dm6446evm.h new file mode 100644 index 00000000000..3216f21c123 --- /dev/null +++ b/arch/arm/mach-davinci/include/mach/board-dm6446evm.h @@ -0,0 +1,20 @@ +/* + * DaVinci DM6446 EVM board specific headers + * + * Author: Kevin Hilman, Deep Root Systems, LLC + * + * 2007 (c) Deep Root Systems, LLC. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or ifndef. + */ + +#ifndef _MACH_DAVINCI_DM6446EVM_H +#define _MACH_DAVINCI_DM6446EVM_H + +#include <linux/types.h> + +int dm6446evm_eeprom_read(char *buf, off_t off, size_t count); +int dm6446evm_eeprom_write(char *buf, off_t off, size_t count); + +#endif diff --git a/arch/arm/mach-davinci/include/mach/clkdev.h b/arch/arm/mach-davinci/include/mach/clkdev.h new file mode 100644 index 00000000000..730c49d1ebd --- /dev/null +++ b/arch/arm/mach-davinci/include/mach/clkdev.h @@ -0,0 +1,13 @@ +#ifndef __MACH_CLKDEV_H +#define __MACH_CLKDEV_H + +static inline int __clk_get(struct clk *clk) +{ + return 1; +} + +static inline void __clk_put(struct clk *clk) +{ +} + +#endif diff --git a/arch/arm/mach-davinci/include/mach/clock.h b/arch/arm/mach-davinci/include/mach/clock.h index 38bdd49bc18..a3b04021987 100644 --- a/arch/arm/mach-davinci/include/mach/clock.h +++ b/arch/arm/mach-davinci/include/mach/clock.h @@ -17,6 +17,5 @@ struct clk; extern int clk_register(struct clk *clk); extern void clk_unregister(struct clk *clk); -extern int davinci_clk_init(void); #endif diff --git a/arch/arm/mach-davinci/include/mach/common.h b/arch/arm/mach-davinci/include/mach/common.h index 4b522e5c70e..19177097625 100644 --- a/arch/arm/mach-davinci/include/mach/common.h +++ b/arch/arm/mach-davinci/include/mach/common.h @@ -16,6 +16,12 @@ struct sys_timer; extern struct sys_timer davinci_timer; +extern void davinci_irq_init(void); +extern void davinci_map_common_io(void); + +/* parameters describe VBUS sourcing for host mode */ +extern void setup_usb(unsigned mA, unsigned potpgt_msec); + /* parameters describe VBUS sourcing for host mode */ extern void setup_usb(unsigned mA, unsigned potpgt_msec); diff --git a/arch/arm/mach-davinci/include/mach/cputype.h b/arch/arm/mach-davinci/include/mach/cputype.h new file mode 100644 index 00000000000..27cfb1b3a66 --- /dev/null +++ b/arch/arm/mach-davinci/include/mach/cputype.h @@ -0,0 +1,49 @@ +/* + * DaVinci CPU type detection + * + * Author: Kevin Hilman, Deep Root Systems, LLC + * + * Defines the cpu_is_*() macros for runtime detection of DaVinci + * device type. In addtion, if support for a given device is not + * compiled in to the kernel, the macros return 0 so that + * resulting code can be optimized out. + * + * 2009 (c) Deep Root Systems, LLC. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ +#ifndef _ASM_ARCH_CPU_H +#define _ASM_ARCH_CPU_H + +extern unsigned int davinci_rev(void); + +#define IS_DAVINCI_CPU(type, id) \ +static inline int is_davinci_dm ##type(void) \ +{ \ + return (davinci_rev() == (id)) ? 1 : 0; \ +} + +IS_DAVINCI_CPU(644x, 0x6446) +IS_DAVINCI_CPU(646x, 0x6467) +IS_DAVINCI_CPU(355, 0x355) + +#ifdef CONFIG_ARCH_DAVINCI_DM644x +#define cpu_is_davinci_dm644x() is_davinci_dm644x() +#else +#define cpu_is_davinci_dm644x() 0 +#endif + +#ifdef CONFIG_ARCH_DAVINCI_DM646x +#define cpu_is_davinci_dm646x() is_davinci_dm646x() +#else +#define cpu_is_davinci_dm646x() 0 +#endif + +#ifdef CONFIG_ARCH_DAVINCI_DM355 +#define cpu_is_davinci_dm355() is_davinci_dm355() +#else +#define cpu_is_davinci_dm355() 0 +#endif + +#endif diff --git a/arch/arm/mach-davinci/include/mach/dm644x.h b/arch/arm/mach-davinci/include/mach/dm644x.h new file mode 100644 index 00000000000..3dcb9f4e58b --- /dev/null +++ b/arch/arm/mach-davinci/include/mach/dm644x.h @@ -0,0 +1,37 @@ +/* + * This file contains the processor specific definitions + * of the TI DM644x. + * + * Copyright (C) 2008 Texas Instruments. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +#ifndef __ASM_ARCH_DM644X_H +#define __ASM_ARCH_DM644X_H + +#include <linux/platform_device.h> +#include <mach/hardware.h> + +#define DM644X_EMAC_BASE (0x01C80000) +#define DM644X_EMAC_CNTRL_OFFSET (0x0000) +#define DM644X_EMAC_CNTRL_MOD_OFFSET (0x1000) +#define DM644X_EMAC_CNTRL_RAM_OFFSET (0x2000) +#define DM644X_EMAC_MDIO_OFFSET (0x4000) +#define DM644X_EMAC_CNTRL_RAM_SIZE (0x2000) + +void __init dm644x_init(void); + +#endif /* __ASM_ARCH_DM644X_H */ diff --git a/arch/arm/mach-davinci/include/mach/edma.h b/arch/arm/mach-davinci/include/mach/edma.h new file mode 100644 index 00000000000..f6fc5396daf --- /dev/null +++ b/arch/arm/mach-davinci/include/mach/edma.h @@ -0,0 +1,228 @@ +/* + * TI DAVINCI dma definitions + * + * Copyright (C) 2006-2009 Texas Instruments. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``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 THE AUTHOR 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. + * + * 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. + * + */ + +/* + * This EDMA3 programming framework exposes two basic kinds of resource: + * + * Channel Triggers transfers, usually from a hardware event but + * also manually or by "chaining" from DMA completions. + * Each channel is coupled to a Parameter RAM (PaRAM) slot. + * + * Slot Each PaRAM slot holds a DMA transfer descriptor (PaRAM + * "set"), source and destination addresses, a link to a + * next PaRAM slot (if any), options for the transfer, and + * instructions for updating those addresses. There are + * more than twice as many slots as event channels. + * + * Each PaRAM set describes a sequence of transfers, either for one large + * buffer or for several discontiguous smaller buffers. An EDMA transfer + * is driven only from a channel, which performs the transfers specified + * in its PaRAM slot until there are no more transfers. When that last + * transfer completes, the "link" field may be used to reload the channel's + * PaRAM slot with a new transfer descriptor. + * + * The EDMA Channel Controller (CC) maps requests from channels into physical + * Transfer Controller (TC) requests when the channel triggers (by hardware + * or software events, or by chaining). The two physical DMA channels provided + * by the TCs are thus shared by many logical channels. + * + * DaVinci hardware also has a "QDMA" mechanism which is not currently + * supported through this interface. (DSP firmware uses it though.) + */ + +#ifndef EDMA_H_ +#define EDMA_H_ + +/* PaRAM slots are laid out like this */ +struct edmacc_param { + unsigned int opt; + unsigned int src; + unsigned int a_b_cnt; + unsigned int dst; + unsigned int src_dst_bidx; + unsigned int link_bcntrld; + unsigned int src_dst_cidx; + unsigned int ccnt; +}; + +#define CCINT0_INTERRUPT 16 +#define CCERRINT_INTERRUPT 17 +#define TCERRINT0_INTERRUPT 18 +#define TCERRINT1_INTERRUPT 19 + +/* fields in edmacc_param.opt */ +#define SAM BIT(0) +#define DAM BIT(1) +#define SYNCDIM BIT(2) +#define STATIC BIT(3) +#define EDMA_FWID (0x07 << 8) +#define TCCMODE BIT(11) +#define EDMA_TCC(t) ((t) << 12) +#define TCINTEN BIT(20) +#define ITCINTEN BIT(21) +#define TCCHEN BIT(22) +#define ITCCHEN BIT(23) + +#define TRWORD (0x7<<2) +#define PAENTRY (0x1ff<<5) + +/* Drivers should avoid using these symbolic names for dm644x + * channels, and use platform_device IORESOURCE_DMA resources + * instead. (Other DaVinci chips have different peripherals + * and thus have different DMA channel mappings.) + */ +#define DAVINCI_DMA_MCBSP_TX 2 +#define DAVINCI_DMA_MCBSP_RX 3 +#define DAVINCI_DMA_VPSS_HIST 4 +#define DAVINCI_DMA_VPSS_H3A 5 +#define DAVINCI_DMA_VPSS_PRVU 6 +#define DAVINCI_DMA_VPSS_RSZ 7 +#define DAVINCI_DMA_IMCOP_IMXINT 8 +#define DAVINCI_DMA_IMCOP_VLCDINT 9 +#define DAVINCI_DMA_IMCO_PASQINT 10 +#define DAVINCI_DMA_IMCOP_DSQINT 11 +#define DAVINCI_DMA_SPI_SPIX 16 +#define DAVINCI_DMA_SPI_SPIR 17 +#define DAVINCI_DMA_UART0_URXEVT0 18 +#define DAVINCI_DMA_UART0_UTXEVT0 19 +#define DAVINCI_DMA_UART1_URXEVT1 20 +#define DAVINCI_DMA_UART1_UTXEVT1 21 +#define DAVINCI_DMA_UART2_URXEVT2 22 +#define DAVINCI_DMA_UART2_UTXEVT2 23 +#define DAVINCI_DMA_MEMSTK_MSEVT 24 +#define DAVINCI_DMA_MMCRXEVT 26 +#define DAVINCI_DMA_MMCTXEVT 27 +#define DAVINCI_DMA_I2C_ICREVT 28 +#define DAVINCI_DMA_I2C_ICXEVT 29 +#define DAVINCI_DMA_GPIO_GPINT0 32 +#define DAVINCI_DMA_GPIO_GPINT1 33 +#define DAVINCI_DMA_GPIO_GPINT2 34 +#define DAVINCI_DMA_GPIO_GPINT3 35 +#define DAVINCI_DMA_GPIO_GPINT4 36 +#define DAVINCI_DMA_GPIO_GPINT5 37 +#define DAVINCI_DMA_GPIO_GPINT6 38 +#define DAVINCI_DMA_GPIO_GPINT7 39 +#define DAVINCI_DMA_GPIO_GPBNKINT0 40 +#define DAVINCI_DMA_GPIO_GPBNKINT1 41 +#define DAVINCI_DMA_GPIO_GPBNKINT2 42 +#define DAVINCI_DMA_GPIO_GPBNKINT3 43 +#define DAVINCI_DMA_GPIO_GPBNKINT4 44 +#define DAVINCI_DMA_TIMER0_TINT0 48 +#define DAVINCI_DMA_TIMER1_TINT1 49 +#define DAVINCI_DMA_TIMER2_TINT2 50 +#define DAVINCI_DMA_TIMER3_TINT3 51 +#define DAVINCI_DMA_PWM0 52 +#define DAVINCI_DMA_PWM1 53 +#define DAVINCI_DMA_PWM2 54 + +/*ch_status paramater of callback function possible values*/ +#define DMA_COMPLETE 1 +#define DMA_CC_ERROR 2 +#define DMA_TC1_ERROR 3 +#define DMA_TC2_ERROR 4 + +enum address_mode { + INCR = 0, + FIFO = 1 +}; + +enum fifo_width { + W8BIT = 0, + W16BIT = 1, + W32BIT = 2, + W64BIT = 3, + W128BIT = 4, + W256BIT = 5 +}; + +enum dma_event_q { + EVENTQ_0 = 0, + EVENTQ_1 = 1, + EVENTQ_DEFAULT = -1 +}; + +enum sync_dimension { + ASYNC = 0, + ABSYNC = 1 +}; + +#define EDMA_CHANNEL_ANY -1 /* for edma_alloc_channel() */ +#define EDMA_SLOT_ANY -1 /* for edma_alloc_slot() */ + +/* alloc/free DMA channels and their dedicated parameter RAM slots */ +int edma_alloc_channel(int channel, + void (*callback)(unsigned channel, u16 ch_status, void *data), + void *data, enum dma_event_q); +void edma_free_channel(unsigned channel); + +/* alloc/free parameter RAM slots */ +int edma_alloc_slot(int slot); +void edma_free_slot(unsigned slot); + +/* calls that operate on part of a parameter RAM slot */ +void edma_set_src(unsigned slot, dma_addr_t src_port, + enum address_mode mode, enum fifo_width); +void edma_set_dest(unsigned slot, dma_addr_t dest_port, + enum address_mode mode, enum fifo_width); +void edma_get_position(unsigned slot, dma_addr_t *src, dma_addr_t *dst); +void edma_set_src_index(unsigned slot, s16 src_bidx, s16 src_cidx); +void edma_set_dest_index(unsigned slot, s16 dest_bidx, s16 dest_cidx); +void edma_set_transfer_params(unsigned slot, u16 acnt, u16 bcnt, u16 ccnt, + u16 bcnt_rld, enum sync_dimension sync_mode); +void edma_link(unsigned from, unsigned to); +void edma_unlink(unsigned from); + +/* calls that operate on an entire parameter RAM slot */ +void edma_write_slot(unsigned slot, const struct edmacc_param *params); +void edma_read_slot(unsigned slot, struct edmacc_param *params); + +/* channel control operations */ +int edma_start(unsigned channel); +void edma_stop(unsigned channel); +void edma_clean_channel(unsigned channel); +void edma_clear_event(unsigned channel); +void edma_pause(unsigned channel); +void edma_resume(unsigned channel); + +/* UNRELATED TO DMA */ +int davinci_alloc_iram(unsigned size); +void davinci_free_iram(unsigned addr, unsigned size); + +/* platform_data for EDMA driver */ +struct edma_soc_info { + + /* how many dma resources of each type */ + unsigned n_channel; + unsigned n_region; + unsigned n_slot; + unsigned n_tc; + + /* list of channels with no even trigger; terminated by "-1" */ + const s8 *noevent; +}; + +#endif diff --git a/arch/arm/mach-davinci/include/mach/gpio.h b/arch/arm/mach-davinci/include/mach/gpio.h index b456f079f43..efe3281364e 100644 --- a/arch/arm/mach-davinci/include/mach/gpio.h +++ b/arch/arm/mach-davinci/include/mach/gpio.h @@ -15,9 +15,11 @@ #include <linux/io.h> #include <asm-generic/gpio.h> -#include <mach/hardware.h> + #include <mach/irqs.h> +#define DAVINCI_GPIO_BASE 0x01C67000 + /* * basic gpio routines * @@ -26,23 +28,18 @@ * go through boot loaders. * * the gpio clock will be turned on when gpios are used, and you may also - * need to pay attention to PINMUX0 and PINMUX1 to be sure those pins are + * need to pay attention to PINMUX registers to be sure those pins are * used as gpios, not with other peripherals. * * On-chip GPIOs are numbered 0..(DAVINCI_N_GPIO-1). For documentation, - * and maybe for later updates, code should write GPIO(N) or: - * - GPIOV18(N) for 1.8V pins, N in 0..53; same as GPIO(0)..GPIO(53) - * - GPIOV33(N) for 3.3V pins, N in 0..17; same as GPIO(54)..GPIO(70) - * - * For GPIO IRQs use gpio_to_irq(GPIO(N)) or gpio_to_irq(GPIOV33(N)) etc - * for now, that's != GPIO(N) + * and maybe for later updates, code may write GPIO(N). These may be + * all 1.8V signals, all 3.3V ones, or a mix of the two. A given chip + * may not support all the GPIOs in that range. * * GPIOs can also be on external chips, numbered after the ones built-in * to the DaVinci chip. For now, they won't be usable as IRQ sources. */ -#define GPIO(X) (X) /* 0 <= X <= 70 */ -#define GPIOV18(X) (X) /* 1.8V i/o; 0 <= X <= 53 */ -#define GPIOV33(X) ((X)+54) /* 3.3V i/o; 0 <= X <= 17 */ +#define GPIO(X) (X) /* 0 <= X <= (DAVINCI_N_GPIO - 1) */ struct gpio_controller { u32 dir; @@ -71,12 +68,14 @@ __gpio_to_controller(unsigned gpio) { void *__iomem ptr; - if (gpio < 32) + if (gpio < 32 * 1) ptr = IO_ADDRESS(DAVINCI_GPIO_BASE + 0x10); - else if (gpio < 64) + else if (gpio < 32 * 2) ptr = IO_ADDRESS(DAVINCI_GPIO_BASE + 0x38); - else if (gpio < DAVINCI_N_GPIO) + else if (gpio < 32 * 3) ptr = IO_ADDRESS(DAVINCI_GPIO_BASE + 0x60); + else if (gpio < 32 * 4) + ptr = IO_ADDRESS(DAVINCI_GPIO_BASE + 0x88); else ptr = NULL; return ptr; diff --git a/arch/arm/mach-davinci/include/mach/hardware.h b/arch/arm/mach-davinci/include/mach/hardware.h index a2e8969afac..48c77934d51 100644 --- a/arch/arm/mach-davinci/include/mach/hardware.h +++ b/arch/arm/mach-davinci/include/mach/hardware.h @@ -1,9 +1,9 @@ /* - * Common hardware definitions + * Hardware definitions common to all DaVinci family processors * - * Author: Kevin Hilman, MontaVista Software, Inc. <source@mvista.com> + * Author: Kevin Hilman, Deep Root Systems, LLC * - * 2007 (c) MontaVista Software, Inc. This file is licensed under + * 2007 (c) Deep Root Systems, LLC. This file is licensed under * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. @@ -12,41 +12,16 @@ #define __ASM_ARCH_HARDWARE_H /* - * Base register addresses + * Before you add anything to ths file: + * + * This header is for defines common to ALL DaVinci family chips. + * Anything that is chip specific should go in <chipname>.h, + * and the chip/board init code should then explicitly include + * <chipname>.h */ -#define DAVINCI_DMA_3PCC_BASE (0x01C00000) -#define DAVINCI_DMA_3PTC0_BASE (0x01C10000) -#define DAVINCI_DMA_3PTC1_BASE (0x01C10400) -#define DAVINCI_I2C_BASE (0x01C21000) -#define DAVINCI_PWM0_BASE (0x01C22000) -#define DAVINCI_PWM1_BASE (0x01C22400) -#define DAVINCI_PWM2_BASE (0x01C22800) -#define DAVINCI_SYSTEM_MODULE_BASE (0x01C40000) -#define DAVINCI_PLL_CNTRL0_BASE (0x01C40800) -#define DAVINCI_PLL_CNTRL1_BASE (0x01C40C00) -#define DAVINCI_PWR_SLEEP_CNTRL_BASE (0x01C41000) -#define DAVINCI_SYSTEM_DFT_BASE (0x01C42000) -#define DAVINCI_IEEE1394_BASE (0x01C60000) -#define DAVINCI_USB_OTG_BASE (0x01C64000) -#define DAVINCI_CFC_ATA_BASE (0x01C66000) -#define DAVINCI_SPI_BASE (0x01C66800) -#define DAVINCI_GPIO_BASE (0x01C67000) -#define DAVINCI_UHPI_BASE (0x01C67800) -#define DAVINCI_VPSS_REGS_BASE (0x01C70000) -#define DAVINCI_EMAC_CNTRL_REGS_BASE (0x01C80000) -#define DAVINCI_EMAC_WRAPPER_CNTRL_REGS_BASE (0x01C81000) -#define DAVINCI_EMAC_WRAPPER_RAM_BASE (0x01C82000) -#define DAVINCI_MDIO_CNTRL_REGS_BASE (0x01C84000) -#define DAVINCI_IMCOP_BASE (0x01CC0000) -#define DAVINCI_ASYNC_EMIF_CNTRL_BASE (0x01E00000) -#define DAVINCI_VLYNQ_BASE (0x01E01000) -#define DAVINCI_MCBSP_BASE (0x01E02000) -#define DAVINCI_MMC_SD_BASE (0x01E10000) -#define DAVINCI_MS_BASE (0x01E20000) -#define DAVINCI_ASYNC_EMIF_DATA_CE0_BASE (0x02000000) -#define DAVINCI_ASYNC_EMIF_DATA_CE1_BASE (0x04000000) -#define DAVINCI_ASYNC_EMIF_DATA_CE2_BASE (0x06000000) -#define DAVINCI_ASYNC_EMIF_DATA_CE3_BASE (0x08000000) -#define DAVINCI_VLYNQ_REMOTE_BASE (0x0C000000) +#define DAVINCI_SYSTEM_MODULE_BASE 0x01C40000 + +/* System control register offsets */ +#define DM64XX_VDD3P3V_PWDN 0x48 #endif /* __ASM_ARCH_HARDWARE_H */ diff --git a/arch/arm/mach-davinci/include/mach/io.h b/arch/arm/mach-davinci/include/mach/io.h index a48795fd241..2479785405a 100644 --- a/arch/arm/mach-davinci/include/mach/io.h +++ b/arch/arm/mach-davinci/include/mach/io.h @@ -40,22 +40,12 @@ #else #define IOMEM(x) ((void __force __iomem *)(x)) -/* - * Functions to access the DaVinci IO region - * - * NOTE: - Use davinci_read/write[bwl] for physical register addresses - * - Use __raw_read/write[bwl]() for virtual register addresses - * - Use IO_ADDRESS(phys_addr) to convert registers to virtual addresses - * - DO NOT use hardcoded virtual addresses to allow changing the - * IO address space again if needed - */ -#define davinci_readb(a) __raw_readb(IO_ADDRESS(a)) -#define davinci_readw(a) __raw_readw(IO_ADDRESS(a)) -#define davinci_readl(a) __raw_readl(IO_ADDRESS(a)) +#define __arch_ioremap(p, s, t) davinci_ioremap(p, s, t) +#define __arch_iounmap(v) davinci_iounmap(v) -#define davinci_writeb(v, a) __raw_writeb(v, IO_ADDRESS(a)) -#define davinci_writew(v, a) __raw_writew(v, IO_ADDRESS(a)) -#define davinci_writel(v, a) __raw_writel(v, IO_ADDRESS(a)) +void __iomem *davinci_ioremap(unsigned long phys, size_t size, + unsigned int type); +void davinci_iounmap(volatile void __iomem *addr); #endif /* __ASSEMBLER__ */ #endif /* __ASM_ARCH_IO_H */ diff --git a/arch/arm/mach-davinci/include/mach/irqs.h b/arch/arm/mach-davinci/include/mach/irqs.h index f4c5ca6da9f..18066074c99 100644 --- a/arch/arm/mach-davinci/include/mach/irqs.h +++ b/arch/arm/mach-davinci/include/mach/irqs.h @@ -96,10 +96,111 @@ #define IRQ_EMUINT 63 #define DAVINCI_N_AINTC_IRQ 64 -#define DAVINCI_N_GPIO 71 +#define DAVINCI_N_GPIO 104 #define NR_IRQS (DAVINCI_N_AINTC_IRQ + DAVINCI_N_GPIO) #define ARCH_TIMER_IRQ IRQ_TINT1_TINT34 +/* DaVinci DM6467-specific Interrupts */ +#define IRQ_DM646X_VP_VERTINT0 0 +#define IRQ_DM646X_VP_VERTINT1 1 +#define IRQ_DM646X_VP_VERTINT2 2 +#define IRQ_DM646X_VP_VERTINT3 3 +#define IRQ_DM646X_VP_ERRINT 4 +#define IRQ_DM646X_RESERVED_1 5 +#define IRQ_DM646X_RESERVED_2 6 +#define IRQ_DM646X_WDINT 7 +#define IRQ_DM646X_CRGENINT0 8 +#define IRQ_DM646X_CRGENINT1 9 +#define IRQ_DM646X_TSIFINT0 10 +#define IRQ_DM646X_TSIFINT1 11 +#define IRQ_DM646X_VDCEINT 12 +#define IRQ_DM646X_USBINT 13 +#define IRQ_DM646X_USBDMAINT 14 +#define IRQ_DM646X_PCIINT 15 +#define IRQ_DM646X_TCERRINT2 20 +#define IRQ_DM646X_TCERRINT3 21 +#define IRQ_DM646X_IDE 22 +#define IRQ_DM646X_HPIINT 23 +#define IRQ_DM646X_EMACRXTHINT 24 +#define IRQ_DM646X_EMACRXINT 25 +#define IRQ_DM646X_EMACTXINT 26 +#define IRQ_DM646X_EMACMISCINT 27 +#define IRQ_DM646X_MCASP0TXINT 28 +#define IRQ_DM646X_MCASP0RXINT 29 +#define IRQ_DM646X_RESERVED_3 31 +#define IRQ_DM646X_MCASP1TXINT 32 +#define IRQ_DM646X_VLQINT 38 +#define IRQ_DM646X_UARTINT2 42 +#define IRQ_DM646X_SPINT0 43 +#define IRQ_DM646X_SPINT1 44 +#define IRQ_DM646X_DSP2ARMINT 45 +#define IRQ_DM646X_RESERVED_4 46 +#define IRQ_DM646X_PSCINT 47 +#define IRQ_DM646X_GPIO0 48 +#define IRQ_DM646X_GPIO1 49 +#define IRQ_DM646X_GPIO2 50 +#define IRQ_DM646X_GPIO3 51 +#define IRQ_DM646X_GPIO4 52 +#define IRQ_DM646X_GPIO5 53 +#define IRQ_DM646X_GPIO6 54 +#define IRQ_DM646X_GPIO7 55 +#define IRQ_DM646X_GPIOBNK0 56 +#define IRQ_DM646X_GPIOBNK1 57 +#define IRQ_DM646X_GPIOBNK2 58 +#define IRQ_DM646X_DDRINT 59 +#define IRQ_DM646X_AEMIFINT 60 + +/* DaVinci DM355-specific Interrupts */ +#define IRQ_DM355_CCDC_VDINT0 0 +#define IRQ_DM355_CCDC_VDINT1 1 +#define IRQ_DM355_CCDC_VDINT2 2 +#define IRQ_DM355_IPIPE_HST 3 +#define IRQ_DM355_H3AINT 4 +#define IRQ_DM355_IPIPE_SDR 5 +#define IRQ_DM355_IPIPEIFINT 6 +#define IRQ_DM355_OSDINT 7 +#define IRQ_DM355_VENCINT 8 +#define IRQ_DM355_IMCOPINT 11 +#define IRQ_DM355_RTOINT 13 +#define IRQ_DM355_TINT4 13 +#define IRQ_DM355_TINT2_TINT12 13 +#define IRQ_DM355_UARTINT2 14 +#define IRQ_DM355_TINT5 14 +#define IRQ_DM355_TINT2_TINT34 14 +#define IRQ_DM355_TINT6 15 +#define IRQ_DM355_TINT3_TINT12 15 +#define IRQ_DM355_SPINT1_0 17 +#define IRQ_DM355_SPINT1_1 18 +#define IRQ_DM355_SPINT2_0 19 +#define IRQ_DM355_SPINT2_1 21 +#define IRQ_DM355_TINT7 22 +#define IRQ_DM355_TINT3_TINT34 22 +#define IRQ_DM355_SDIOINT0 23 +#define IRQ_DM355_MMCINT0 26 +#define IRQ_DM355_MSINT 26 +#define IRQ_DM355_MMCINT1 27 +#define IRQ_DM355_PWMINT3 28 +#define IRQ_DM355_SDIOINT1 31 +#define IRQ_DM355_SPINT0_0 42 +#define IRQ_DM355_SPINT0_1 43 +#define IRQ_DM355_GPIO0 44 +#define IRQ_DM355_GPIO1 45 +#define IRQ_DM355_GPIO2 46 +#define IRQ_DM355_GPIO3 47 +#define IRQ_DM355_GPIO4 48 +#define IRQ_DM355_GPIO5 49 +#define IRQ_DM355_GPIO6 50 +#define IRQ_DM355_GPIO7 51 +#define IRQ_DM355_GPIO8 52 +#define IRQ_DM355_GPIO9 53 +#define IRQ_DM355_GPIOBNK0 54 +#define IRQ_DM355_GPIOBNK1 55 +#define IRQ_DM355_GPIOBNK2 56 +#define IRQ_DM355_GPIOBNK3 57 +#define IRQ_DM355_GPIOBNK4 58 +#define IRQ_DM355_GPIOBNK5 59 +#define IRQ_DM355_GPIOBNK6 60 + #endif /* __ASM_ARCH_IRQS_H */ diff --git a/arch/arm/mach-davinci/include/mach/mux.h b/arch/arm/mach-davinci/include/mach/mux.h index c24b6782804..bae22cb3e27 100644 --- a/arch/arm/mach-davinci/include/mach/mux.h +++ b/arch/arm/mach-davinci/include/mach/mux.h @@ -1,55 +1,183 @@ /* - * DaVinci pin multiplexing defines + * Table of the DAVINCI register configurations for the PINMUX combinations * * Author: Vladimir Barinov, MontaVista Software, Inc. <source@mvista.com> * + * Based on linux/include/asm-arm/arch-omap/mux.h: + * Copyright (C) 2003 - 2005 Nokia Corporation + * + * Written by Tony Lindgren + * * 2007 (c) MontaVista Software, Inc. This file is licensed under * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. + * + * Copyright (C) 2008 Texas Instruments. */ -#ifndef __ASM_ARCH_MUX_H -#define __ASM_ARCH_MUX_H - -#define DAVINCI_MUX_AEAW0 0 -#define DAVINCI_MUX_AEAW1 1 -#define DAVINCI_MUX_AEAW2 2 -#define DAVINCI_MUX_AEAW3 3 -#define DAVINCI_MUX_AEAW4 4 -#define DAVINCI_MUX_AECS4 10 -#define DAVINCI_MUX_AECS5 11 -#define DAVINCI_MUX_VLYNQWD0 12 -#define DAVINCI_MUX_VLYNQWD1 13 -#define DAVINCI_MUX_VLSCREN 14 -#define DAVINCI_MUX_VLYNQEN 15 -#define DAVINCI_MUX_HDIREN 16 -#define DAVINCI_MUX_ATAEN 17 -#define DAVINCI_MUX_RGB666 22 -#define DAVINCI_MUX_RGB888 23 -#define DAVINCI_MUX_LOEEN 24 -#define DAVINCI_MUX_LFLDEN 25 -#define DAVINCI_MUX_CWEN 26 -#define DAVINCI_MUX_CFLDEN 27 -#define DAVINCI_MUX_HPIEN 29 -#define DAVINCI_MUX_1394EN 30 -#define DAVINCI_MUX_EMACEN 31 - -#define DAVINCI_MUX_LEVEL2 32 -#define DAVINCI_MUX_UART0 (DAVINCI_MUX_LEVEL2 + 0) -#define DAVINCI_MUX_UART1 (DAVINCI_MUX_LEVEL2 + 1) -#define DAVINCI_MUX_UART2 (DAVINCI_MUX_LEVEL2 + 2) -#define DAVINCI_MUX_U2FLO (DAVINCI_MUX_LEVEL2 + 3) -#define DAVINCI_MUX_PWM0 (DAVINCI_MUX_LEVEL2 + 4) -#define DAVINCI_MUX_PWM1 (DAVINCI_MUX_LEVEL2 + 5) -#define DAVINCI_MUX_PWM2 (DAVINCI_MUX_LEVEL2 + 6) -#define DAVINCI_MUX_I2C (DAVINCI_MUX_LEVEL2 + 7) -#define DAVINCI_MUX_SPI (DAVINCI_MUX_LEVEL2 + 8) -#define DAVINCI_MUX_MSTK (DAVINCI_MUX_LEVEL2 + 9) -#define DAVINCI_MUX_ASP (DAVINCI_MUX_LEVEL2 + 10) -#define DAVINCI_MUX_CLK0 (DAVINCI_MUX_LEVEL2 + 16) -#define DAVINCI_MUX_CLK1 (DAVINCI_MUX_LEVEL2 + 17) -#define DAVINCI_MUX_TIMIN (DAVINCI_MUX_LEVEL2 + 18) - -extern void davinci_mux_peripheral(unsigned int mux, unsigned int enable); - -#endif /* __ASM_ARCH_MUX_H */ + +#ifndef __INC_MACH_MUX_H +#define __INC_MACH_MUX_H + +/* System module registers */ +#define PINMUX0 0x00 +#define PINMUX1 0x04 +/* dm355 only */ +#define PINMUX2 0x08 +#define PINMUX3 0x0c +#define PINMUX4 0x10 +#define INTMUX 0x18 +#define EVTMUX 0x1c + +struct mux_config { + const char *name; + const char *mux_reg_name; + const unsigned char mux_reg; + const unsigned char mask_offset; + const unsigned char mask; + const unsigned char mode; + bool debug; +}; + +enum davinci_dm644x_index { + /* ATA and HDDIR functions */ + DM644X_HDIREN, + DM644X_ATAEN, + DM644X_ATAEN_DISABLE, + + /* HPI functions */ + DM644X_HPIEN_DISABLE, + + /* AEAW functions */ + DM644X_AEAW, + + /* Memory Stick */ + DM644X_MSTK, + + /* I2C */ + DM644X_I2C, + + /* ASP function */ + DM644X_MCBSP, + + /* UART1 */ + DM644X_UART1, + + /* UART2 */ + DM644X_UART2, + + /* PWM0 */ + DM644X_PWM0, + + /* PWM1 */ + DM644X_PWM1, + + /* PWM2 */ + DM644X_PWM2, + + /* VLYNQ function */ + DM644X_VLYNQEN, + DM644X_VLSCREN, + DM644X_VLYNQWD, + + /* EMAC and MDIO function */ + DM644X_EMACEN, + + /* GPIO3V[0:16] pins */ + DM644X_GPIO3V, + + /* GPIO pins */ + DM644X_GPIO0, + DM644X_GPIO3, + DM644X_GPIO43_44, + DM644X_GPIO46_47, + + /* VPBE */ + DM644X_RGB666, + + /* LCD */ + DM644X_LOEEN, + DM644X_LFLDEN, +}; + +enum davinci_dm646x_index { + /* ATA function */ + DM646X_ATAEN, + + /* AUDIO Clock */ + DM646X_AUDCK1, + DM646X_AUDCK0, + + /* CRGEN Control */ + DM646X_CRGMUX, + + /* VPIF Control */ + DM646X_STSOMUX_DISABLE, + DM646X_STSIMUX_DISABLE, + DM646X_PTSOMUX_DISABLE, + DM646X_PTSIMUX_DISABLE, + + /* TSIF Control */ + DM646X_STSOMUX, + DM646X_STSIMUX, + DM646X_PTSOMUX_PARALLEL, + DM646X_PTSIMUX_PARALLEL, + DM646X_PTSOMUX_SERIAL, + DM646X_PTSIMUX_SERIAL, +}; + +enum davinci_dm355_index { + /* MMC/SD 0 */ + DM355_MMCSD0, + + /* MMC/SD 1 */ + DM355_SD1_CLK, + DM355_SD1_CMD, + DM355_SD1_DATA3, + DM355_SD1_DATA2, + DM355_SD1_DATA1, + DM355_SD1_DATA0, + + /* I2C */ + DM355_I2C_SDA, + DM355_I2C_SCL, + + /* ASP0 function */ + DM355_MCBSP0_BDX, + DM355_MCBSP0_X, + DM355_MCBSP0_BFSX, + DM355_MCBSP0_BDR, + DM355_MCBSP0_R, + DM355_MCBSP0_BFSR, + + /* SPI0 */ + DM355_SPI0_SDI, + DM355_SPI0_SDENA0, + DM355_SPI0_SDENA1, + + /* IRQ muxing */ + DM355_INT_EDMA_CC, + DM355_INT_EDMA_TC0_ERR, + DM355_INT_EDMA_TC1_ERR, + + /* EDMA event muxing */ + DM355_EVT8_ASP1_TX, + DM355_EVT9_ASP1_RX, + DM355_EVT26_MMC0_RX, +}; + +#ifdef CONFIG_DAVINCI_MUX +/* setup pin muxing */ +extern void davinci_mux_init(void); +extern int davinci_mux_register(const struct mux_config *pins, + unsigned long size); +extern int davinci_cfg_reg(unsigned long reg_cfg); +#else +/* boot loader does it all (no warnings from CONFIG_DAVINCI_MUX_WARNINGS) */ +static inline void davinci_mux_init(void) {} +static inline int davinci_mux_register(const struct mux_config *pins, + unsigned long size) { return 0; } +static inline int davinci_cfg_reg(unsigned long reg_cfg) { return 0; } +#endif + +#endif /* __INC_MACH_MUX_H */ diff --git a/arch/arm/mach-davinci/include/mach/psc.h b/arch/arm/mach-davinci/include/mach/psc.h index 4977aa071e1..55a90d419fa 100644 --- a/arch/arm/mach-davinci/include/mach/psc.h +++ b/arch/arm/mach-davinci/include/mach/psc.h @@ -38,8 +38,6 @@ #define DAVINCI_LPSC_TPTC1 4 #define DAVINCI_LPSC_EMAC 5 #define DAVINCI_LPSC_EMAC_WRAPPER 6 -#define DAVINCI_LPSC_MDIO 7 -#define DAVINCI_LPSC_IEEE1394 8 #define DAVINCI_LPSC_USB 9 #define DAVINCI_LPSC_ATA 10 #define DAVINCI_LPSC_VLYNQ 11 @@ -47,7 +45,6 @@ #define DAVINCI_LPSC_DDR_EMIF 13 #define DAVINCI_LPSC_AEMIF 14 #define DAVINCI_LPSC_MMC_SD 15 -#define DAVINCI_LPSC_MEMSTICK 16 #define DAVINCI_LPSC_McBSP 17 #define DAVINCI_LPSC_I2C 18 #define DAVINCI_LPSC_UART0 19 @@ -73,4 +70,54 @@ #define DAVINCI_LPSC_GEM 39 #define DAVINCI_LPSC_IMCOP 40 +#define DM355_LPSC_TIMER3 5 +#define DM355_LPSC_SPI1 6 +#define DM355_LPSC_MMC_SD1 7 +#define DM355_LPSC_McBSP1 8 +#define DM355_LPSC_PWM3 10 +#define DM355_LPSC_SPI2 11 +#define DM355_LPSC_RTO 12 +#define DM355_LPSC_VPSS_DAC 41 + +/* + * LPSC Assignments + */ +#define DM646X_LPSC_ARM 0 +#define DM646X_LPSC_C64X_CPU 1 +#define DM646X_LPSC_HDVICP0 2 +#define DM646X_LPSC_HDVICP1 3 +#define DM646X_LPSC_TPCC 4 +#define DM646X_LPSC_TPTC0 5 +#define DM646X_LPSC_TPTC1 6 +#define DM646X_LPSC_TPTC2 7 +#define DM646X_LPSC_TPTC3 8 +#define DM646X_LPSC_PCI 13 +#define DM646X_LPSC_EMAC 14 +#define DM646X_LPSC_VDCE 15 +#define DM646X_LPSC_VPSSMSTR 16 +#define DM646X_LPSC_VPSSSLV 17 +#define DM646X_LPSC_TSIF0 18 +#define DM646X_LPSC_TSIF1 19 +#define DM646X_LPSC_DDR_EMIF 20 +#define DM646X_LPSC_AEMIF 21 +#define DM646X_LPSC_McASP0 22 +#define DM646X_LPSC_McASP1 23 +#define DM646X_LPSC_CRGEN0 24 +#define DM646X_LPSC_CRGEN1 25 +#define DM646X_LPSC_UART0 26 +#define DM646X_LPSC_UART1 27 +#define DM646X_LPSC_UART2 28 +#define DM646X_LPSC_PWM0 29 +#define DM646X_LPSC_PWM1 30 +#define DM646X_LPSC_I2C 31 +#define DM646X_LPSC_SPI 32 +#define DM646X_LPSC_GPIO 33 +#define DM646X_LPSC_TIMER0 34 +#define DM646X_LPSC_TIMER1 35 +#define DM646X_LPSC_ARM_INTC 45 + +extern int davinci_psc_is_clk_active(unsigned int id); +extern void davinci_psc_config(unsigned int domain, unsigned int id, + char enable); + #endif /* __ASM_ARCH_PSC_H */ diff --git a/arch/arm/mach-davinci/include/mach/serial.h b/arch/arm/mach-davinci/include/mach/serial.h index fb8cb229bfd..632847d74a1 100644 --- a/arch/arm/mach-davinci/include/mach/serial.h +++ b/arch/arm/mach-davinci/include/mach/serial.h @@ -13,8 +13,23 @@ #include <mach/io.h> -#define DAVINCI_UART0_BASE (IO_PHYS + 0x20000) -#define DAVINCI_UART1_BASE (IO_PHYS + 0x20400) -#define DAVINCI_UART2_BASE (IO_PHYS + 0x20800) +#define DAVINCI_MAX_NR_UARTS 3 +#define DAVINCI_UART0_BASE (IO_PHYS + 0x20000) +#define DAVINCI_UART1_BASE (IO_PHYS + 0x20400) +#define DAVINCI_UART2_BASE (IO_PHYS + 0x20800) + +#define DM355_UART2_BASE (IO_PHYS + 0x206000) + +/* DaVinci UART register offsets */ +#define UART_DAVINCI_PWREMU 0x0c +#define UART_DM646X_SCR 0x10 +#define UART_DM646X_SCR_TX_WATERMARK 0x08 + +struct davinci_uart_config { + /* Bit field of UARTs present; bit 0 --> UART1 */ + unsigned int enabled_uarts; +}; + +extern void davinci_serial_init(struct davinci_uart_config *); #endif /* __ASM_ARCH_SERIAL_H */ diff --git a/arch/arm/mach-davinci/io.c b/arch/arm/mach-davinci/io.c index 299515f70b8..a548abb513e 100644 --- a/arch/arm/mach-davinci/io.c +++ b/arch/arm/mach-davinci/io.c @@ -51,7 +51,26 @@ void __init davinci_map_common_io(void) davinci_check_revision(); } -void __init davinci_init_common_hw(void) +#define BETWEEN(p, st, sz) ((p) >= (st) && (p) < ((st) + (sz))) +#define XLATE(p, pst, vst) ((void __iomem *)((p) - (pst) + (vst))) + +/* + * Intercept ioremap() requests for addresses in our fixed mapping regions. + */ +void __iomem *davinci_ioremap(unsigned long p, size_t size, unsigned int type) +{ + if (BETWEEN(p, IO_PHYS, IO_SIZE)) + return XLATE(p, IO_PHYS, IO_VIRT); + + return __arm_ioremap(p, size, type); +} +EXPORT_SYMBOL(davinci_ioremap); + +void davinci_iounmap(volatile void __iomem *addr) { - davinci_clk_init(); + unsigned long virt = (unsigned long)addr; + + if (virt >= VMALLOC_START && virt < VMALLOC_END) + __iounmap(addr); } +EXPORT_SYMBOL(davinci_iounmap); diff --git a/arch/arm/mach-davinci/irq.c b/arch/arm/mach-davinci/irq.c index 38021af8359..5a324c90e29 100644 --- a/arch/arm/mach-davinci/irq.c +++ b/arch/arm/mach-davinci/irq.c @@ -25,6 +25,7 @@ #include <linux/io.h> #include <mach/hardware.h> +#include <mach/cputype.h> #include <asm/mach/irq.h> #define IRQ_BIT(irq) ((irq) & 0x1f) @@ -40,14 +41,18 @@ #define IRQ_INTPRI0_REG_OFFSET 0x0030 #define IRQ_INTPRI7_REG_OFFSET 0x004C +const u8 *davinci_def_priorities; + +#define INTC_BASE IO_ADDRESS(DAVINCI_ARM_INTC_BASE) + static inline unsigned int davinci_irq_readl(int offset) { - return davinci_readl(DAVINCI_ARM_INTC_BASE + offset); + return __raw_readl(INTC_BASE + offset); } static inline void davinci_irq_writel(unsigned long value, int offset) { - davinci_writel(value, DAVINCI_ARM_INTC_BASE + offset); + __raw_writel(value, INTC_BASE + offset); } /* Disable interrupt */ @@ -108,9 +113,8 @@ static struct irq_chip davinci_irq_chip_0 = { .unmask = davinci_unmask_irq, }; - /* FIQ are pri 0-1; otherwise 2-7, with 7 lowest priority */ -static const u8 default_priorities[DAVINCI_N_AINTC_IRQ] __initdata = { +static const u8 dm644x_default_priorities[DAVINCI_N_AINTC_IRQ] __initdata = { [IRQ_VDINT0] = 2, [IRQ_VDINT1] = 6, [IRQ_VDINT2] = 6, @@ -177,11 +181,149 @@ static const u8 default_priorities[DAVINCI_N_AINTC_IRQ] __initdata = { [IRQ_EMUINT] = 7, }; +static const u8 dm646x_default_priorities[DAVINCI_N_AINTC_IRQ] = { + [IRQ_DM646X_VP_VERTINT0] = 7, + [IRQ_DM646X_VP_VERTINT1] = 7, + [IRQ_DM646X_VP_VERTINT2] = 7, + [IRQ_DM646X_VP_VERTINT3] = 7, + [IRQ_DM646X_VP_ERRINT] = 7, + [IRQ_DM646X_RESERVED_1] = 7, + [IRQ_DM646X_RESERVED_2] = 7, + [IRQ_DM646X_WDINT] = 7, + [IRQ_DM646X_CRGENINT0] = 7, + [IRQ_DM646X_CRGENINT1] = 7, + [IRQ_DM646X_TSIFINT0] = 7, + [IRQ_DM646X_TSIFINT1] = 7, + [IRQ_DM646X_VDCEINT] = 7, + [IRQ_DM646X_USBINT] = 7, + [IRQ_DM646X_USBDMAINT] = 7, + [IRQ_DM646X_PCIINT] = 7, + [IRQ_CCINT0] = 7, /* dma */ + [IRQ_CCERRINT] = 7, /* dma */ + [IRQ_TCERRINT0] = 7, /* dma */ + [IRQ_TCERRINT] = 7, /* dma */ + [IRQ_DM646X_TCERRINT2] = 7, + [IRQ_DM646X_TCERRINT3] = 7, + [IRQ_DM646X_IDE] = 7, + [IRQ_DM646X_HPIINT] = 7, + [IRQ_DM646X_EMACRXTHINT] = 7, + [IRQ_DM646X_EMACRXINT] = 7, + [IRQ_DM646X_EMACTXINT] = 7, + [IRQ_DM646X_EMACMISCINT] = 7, + [IRQ_DM646X_MCASP0TXINT] = 7, + [IRQ_DM646X_MCASP0RXINT] = 7, + [IRQ_AEMIFINT] = 7, + [IRQ_DM646X_RESERVED_3] = 7, + [IRQ_DM646X_MCASP1TXINT] = 7, /* clockevent */ + [IRQ_TINT0_TINT34] = 7, /* clocksource */ + [IRQ_TINT1_TINT12] = 7, /* DSP timer */ + [IRQ_TINT1_TINT34] = 7, /* system tick */ + [IRQ_PWMINT0] = 7, + [IRQ_PWMINT1] = 7, + [IRQ_DM646X_VLQINT] = 7, + [IRQ_I2C] = 7, + [IRQ_UARTINT0] = 7, + [IRQ_UARTINT1] = 7, + [IRQ_DM646X_UARTINT2] = 7, + [IRQ_DM646X_SPINT0] = 7, + [IRQ_DM646X_SPINT1] = 7, + [IRQ_DM646X_DSP2ARMINT] = 7, + [IRQ_DM646X_RESERVED_4] = 7, + [IRQ_DM646X_PSCINT] = 7, + [IRQ_DM646X_GPIO0] = 7, + [IRQ_DM646X_GPIO1] = 7, + [IRQ_DM646X_GPIO2] = 7, + [IRQ_DM646X_GPIO3] = 7, + [IRQ_DM646X_GPIO4] = 7, + [IRQ_DM646X_GPIO5] = 7, + [IRQ_DM646X_GPIO6] = 7, + [IRQ_DM646X_GPIO7] = 7, + [IRQ_DM646X_GPIOBNK0] = 7, + [IRQ_DM646X_GPIOBNK1] = 7, + [IRQ_DM646X_GPIOBNK2] = 7, + [IRQ_DM646X_DDRINT] = 7, + [IRQ_DM646X_AEMIFINT] = 7, + [IRQ_COMMTX] = 7, + [IRQ_COMMRX] = 7, + [IRQ_EMUINT] = 7, +}; + +static const u8 dm355_default_priorities[DAVINCI_N_AINTC_IRQ] = { + [IRQ_DM355_CCDC_VDINT0] = 2, + [IRQ_DM355_CCDC_VDINT1] = 6, + [IRQ_DM355_CCDC_VDINT2] = 6, + [IRQ_DM355_IPIPE_HST] = 6, + [IRQ_DM355_H3AINT] = 6, + [IRQ_DM355_IPIPE_SDR] = 6, + [IRQ_DM355_IPIPEIFINT] = 6, + [IRQ_DM355_OSDINT] = 7, + [IRQ_DM355_VENCINT] = 6, + [IRQ_ASQINT] = 6, + [IRQ_IMXINT] = 6, + [IRQ_USBINT] = 4, + [IRQ_DM355_RTOINT] = 4, + [IRQ_DM355_UARTINT2] = 7, + [IRQ_DM355_TINT6] = 7, + [IRQ_CCINT0] = 5, /* dma */ + [IRQ_CCERRINT] = 5, /* dma */ + [IRQ_TCERRINT0] = 5, /* dma */ + [IRQ_TCERRINT] = 5, /* dma */ + [IRQ_DM355_SPINT2_1] = 7, + [IRQ_DM355_TINT7] = 4, + [IRQ_DM355_SDIOINT0] = 7, + [IRQ_MBXINT] = 7, + [IRQ_MBRINT] = 7, + [IRQ_MMCINT] = 7, + [IRQ_DM355_MMCINT1] = 7, + [IRQ_DM355_PWMINT3] = 7, + [IRQ_DDRINT] = 7, + [IRQ_AEMIFINT] = 7, + [IRQ_DM355_SDIOINT1] = 4, + [IRQ_TINT0_TINT12] = 2, /* clockevent */ + [IRQ_TINT0_TINT34] = 2, /* clocksource */ + [IRQ_TINT1_TINT12] = 7, /* DSP timer */ + [IRQ_TINT1_TINT34] = 7, /* system tick */ + [IRQ_PWMINT0] = 7, + [IRQ_PWMINT1] = 7, + [IRQ_PWMINT2] = 7, + [IRQ_I2C] = 3, + [IRQ_UARTINT0] = 3, + [IRQ_UARTINT1] = 3, + [IRQ_DM355_SPINT0_0] = 3, + [IRQ_DM355_SPINT0_1] = 3, + [IRQ_DM355_GPIO0] = 3, + [IRQ_DM355_GPIO1] = 7, + [IRQ_DM355_GPIO2] = 4, + [IRQ_DM355_GPIO3] = 4, + [IRQ_DM355_GPIO4] = 7, + [IRQ_DM355_GPIO5] = 7, + [IRQ_DM355_GPIO6] = 7, + [IRQ_DM355_GPIO7] = 7, + [IRQ_DM355_GPIO8] = 7, + [IRQ_DM355_GPIO9] = 7, + [IRQ_DM355_GPIOBNK0] = 7, + [IRQ_DM355_GPIOBNK1] = 7, + [IRQ_DM355_GPIOBNK2] = 7, + [IRQ_DM355_GPIOBNK3] = 7, + [IRQ_DM355_GPIOBNK4] = 7, + [IRQ_DM355_GPIOBNK5] = 7, + [IRQ_DM355_GPIOBNK6] = 7, + [IRQ_COMMTX] = 7, + [IRQ_COMMRX] = 7, + [IRQ_EMUINT] = 7, +}; + /* ARM Interrupt Controller Initialization */ void __init davinci_irq_init(void) { unsigned i; - const u8 *priority = default_priorities; + + if (cpu_is_davinci_dm644x()) + davinci_def_priorities = dm644x_default_priorities; + else if (cpu_is_davinci_dm646x()) + davinci_def_priorities = dm646x_default_priorities; + else if (cpu_is_davinci_dm355()) + davinci_def_priorities = dm355_default_priorities; /* Clear all interrupt requests */ davinci_irq_writel(~0x0, FIQ_REG0_OFFSET); @@ -209,8 +351,8 @@ void __init davinci_irq_init(void) unsigned j; u32 pri; - for (j = 0, pri = 0; j < 32; j += 4, priority++) - pri |= (*priority & 0x07) << j; + for (j = 0, pri = 0; j < 32; j += 4, davinci_def_priorities++) + pri |= (*davinci_def_priorities & 0x07) << j; davinci_irq_writel(pri, i); } diff --git a/arch/arm/mach-davinci/mux.c b/arch/arm/mach-davinci/mux.c index 8ff9d8aca60..bbba0b247a4 100644 --- a/arch/arm/mach-davinci/mux.c +++ b/arch/arm/mach-davinci/mux.c @@ -1,41 +1,103 @@ /* - * DaVinci pin multiplexing configurations + * Utility to set the DAVINCI MUX register from a table in mux.h * * Author: Vladimir Barinov, MontaVista Software, Inc. <source@mvista.com> * + * Based on linux/arch/arm/plat-omap/mux.c: + * Copyright (C) 2003 - 2005 Nokia Corporation + * + * Written by Tony Lindgren + * * 2007 (c) MontaVista Software, Inc. This file is licensed under * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. + * + * Copyright (C) 2008 Texas Instruments. */ #include <linux/io.h> +#include <linux/module.h> #include <linux/spinlock.h> #include <mach/hardware.h> - #include <mach/mux.h> -/* System control register offsets */ -#define PINMUX0 0x00 -#define PINMUX1 0x04 +static const struct mux_config *mux_table; +static unsigned long pin_table_sz; + +int __init davinci_mux_register(const struct mux_config *pins, + unsigned long size) +{ + mux_table = pins; + pin_table_sz = size; -static DEFINE_SPINLOCK(mux_lock); + return 0; +} -void davinci_mux_peripheral(unsigned int mux, unsigned int enable) +/* + * Sets the DAVINCI MUX register based on the table + */ +int __init_or_module davinci_cfg_reg(const unsigned long index) { - u32 pinmux, muxreg = PINMUX0; + static DEFINE_SPINLOCK(mux_spin_lock); + void __iomem *base = IO_ADDRESS(DAVINCI_SYSTEM_MODULE_BASE); + unsigned long flags; + const struct mux_config *cfg; + unsigned int reg_orig = 0, reg = 0; + unsigned int mask, warn = 0; + + if (!mux_table) + BUG(); + + if (index >= pin_table_sz) { + printk(KERN_ERR "Invalid pin mux index: %lu (%lu)\n", + index, pin_table_sz); + dump_stack(); + return -ENODEV; + } + + cfg = &mux_table[index]; + + if (cfg->name == NULL) { + printk(KERN_ERR "No entry for the specified index\n"); + return -ENODEV; + } + + /* Update the mux register in question */ + if (cfg->mask) { + unsigned tmp1, tmp2; + + spin_lock_irqsave(&mux_spin_lock, flags); + reg_orig = __raw_readl(base + cfg->mux_reg); + + mask = (cfg->mask << cfg->mask_offset); + tmp1 = reg_orig & mask; + reg = reg_orig & ~mask; + + tmp2 = (cfg->mode << cfg->mask_offset); + reg |= tmp2; + + if (tmp1 != tmp2) + warn = 1; + + __raw_writel(reg, base + cfg->mux_reg); + spin_unlock_irqrestore(&mux_spin_lock, flags); + } + + if (warn) { +#ifdef CONFIG_DAVINCI_MUX_WARNINGS + printk(KERN_WARNING "MUX: initialized %s\n", cfg->name); +#endif + } - if (mux >= DAVINCI_MUX_LEVEL2) { - muxreg = PINMUX1; - mux -= DAVINCI_MUX_LEVEL2; +#ifdef CONFIG_DAVINCI_MUX_DEBUG + if (cfg->debug || warn) { + printk(KERN_WARNING "MUX: Setting register %s\n", cfg->name); + printk(KERN_WARNING " %s (0x%08x) = 0x%08x -> 0x%08x\n", + cfg->mux_reg_name, cfg->mux_reg, reg_orig, reg); } +#endif - spin_lock(&mux_lock); - pinmux = davinci_readl(DAVINCI_SYSTEM_MODULE_BASE + muxreg); - if (enable) - pinmux |= (1 << mux); - else - pinmux &= ~(1 << mux); - davinci_writel(pinmux, DAVINCI_SYSTEM_MODULE_BASE + muxreg); - spin_unlock(&mux_lock); + return 0; } +EXPORT_SYMBOL(davinci_cfg_reg); diff --git a/arch/arm/mach-davinci/mux.h b/arch/arm/mach-davinci/mux.h new file mode 100644 index 00000000000..adc86941337 --- /dev/null +++ b/arch/arm/mach-davinci/mux.h @@ -0,0 +1,51 @@ +/* + * Pin-multiplex helper macros for TI DaVinci family devices + * + * Author: Vladimir Barinov, MontaVista Software, Inc. <source@mvista.com> + * + * 2007 (c) MontaVista Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + * + * Copyright (C) 2008 Texas Instruments. + */ +#ifndef _MACH_DAVINCI_MUX_H_ +#define _MACH_DAVINCI_MUX_H_ + +#include <mach/mux.h> + +#define MUX_CFG(soc, desc, muxreg, mode_offset, mode_mask, mux_mode, dbg)\ +[soc##_##desc] = { \ + .name = #desc, \ + .debug = dbg, \ + .mux_reg_name = "PINMUX"#muxreg, \ + .mux_reg = PINMUX##muxreg, \ + .mask_offset = mode_offset, \ + .mask = mode_mask, \ + .mode = mux_mode, \ + }, + +#define INT_CFG(soc, desc, mode_offset, mode_mask, mux_mode, dbg) \ +[soc##_##desc] = { \ + .name = #desc, \ + .debug = dbg, \ + .mux_reg_name = "INTMUX", \ + .mux_reg = INTMUX, \ + .mask_offset = mode_offset, \ + .mask = mode_mask, \ + .mode = mux_mode, \ + }, + +#define EVT_CFG(soc, desc, mode_offset, mode_mask, mux_mode, dbg) \ +[soc##_##desc] = { \ + .name = #desc, \ + .debug = dbg, \ + .mux_reg_name = "EVTMUX", \ + .mux_reg = EVTMUX, \ + .mask_offset = mode_offset, \ + .mask = mode_mask, \ + .mode = mux_mode, \ + }, + +#endif /* _MACH_DAVINCI_MUX_H */ diff --git a/arch/arm/mach-davinci/psc.c b/arch/arm/mach-davinci/psc.c index 58754f066d5..84171abf5f7 100644 --- a/arch/arm/mach-davinci/psc.c +++ b/arch/arm/mach-davinci/psc.c @@ -23,10 +23,13 @@ #include <linux/init.h> #include <linux/io.h> +#include <mach/cputype.h> #include <mach/hardware.h> #include <mach/psc.h> #include <mach/mux.h> +#define DAVINCI_PWR_SLEEP_CNTRL_BASE 0x01C41000 + /* PSC register offsets */ #define EPCPR 0x070 #define PTCMD 0x120 @@ -36,102 +39,61 @@ #define MDSTAT 0x800 #define MDCTL 0xA00 -/* System control register offsets */ -#define VDD3P3V_PWDN 0x48 +#define MDSTAT_STATE_MASK 0x1f -static void davinci_psc_mux(unsigned int id) +/* Return nonzero iff the domain's clock is active */ +int __init davinci_psc_is_clk_active(unsigned int id) { - switch (id) { - case DAVINCI_LPSC_ATA: - davinci_mux_peripheral(DAVINCI_MUX_HDIREN, 1); - davinci_mux_peripheral(DAVINCI_MUX_ATAEN, 1); - break; - case DAVINCI_LPSC_MMC_SD: - /* VDD power manupulations are done in U-Boot for CPMAC - * so applies to MMC as well - */ - /*Set up the pull regiter for MMC */ - davinci_writel(0, DAVINCI_SYSTEM_MODULE_BASE + VDD3P3V_PWDN); - davinci_mux_peripheral(DAVINCI_MUX_MSTK, 0); - break; - case DAVINCI_LPSC_I2C: - davinci_mux_peripheral(DAVINCI_MUX_I2C, 1); - break; - case DAVINCI_LPSC_McBSP: - davinci_mux_peripheral(DAVINCI_MUX_ASP, 1); - break; - default: - break; - } + void __iomem *psc_base = IO_ADDRESS(DAVINCI_PWR_SLEEP_CNTRL_BASE); + u32 mdstat = __raw_readl(psc_base + MDSTAT + 4 * id); + + /* if clocked, state can be "Enable" or "SyncReset" */ + return mdstat & BIT(12); } /* Enable or disable a PSC domain */ void davinci_psc_config(unsigned int domain, unsigned int id, char enable) { - u32 epcpr, ptcmd, ptstat, pdstat, pdctl1, mdstat, mdctl, mdstat_mask; + u32 epcpr, ptcmd, ptstat, pdstat, pdctl1, mdstat, mdctl; + void __iomem *psc_base = IO_ADDRESS(DAVINCI_PWR_SLEEP_CNTRL_BASE); + u32 next_state = enable ? 0x3 : 0x2; /* 0x3 enables, 0x2 disables */ - mdctl = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + MDCTL + 4 * id); - if (enable) - mdctl |= 0x00000003; /* Enable Module */ - else - mdctl &= 0xFFFFFFF2; /* Disable Module */ - davinci_writel(mdctl, DAVINCI_PWR_SLEEP_CNTRL_BASE + MDCTL + 4 * id); + mdctl = __raw_readl(psc_base + MDCTL + 4 * id); + mdctl &= ~MDSTAT_STATE_MASK; + mdctl |= next_state; + __raw_writel(mdctl, psc_base + MDCTL + 4 * id); - pdstat = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + PDSTAT); + pdstat = __raw_readl(psc_base + PDSTAT); if ((pdstat & 0x00000001) == 0) { - pdctl1 = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + PDCTL1); + pdctl1 = __raw_readl(psc_base + PDCTL1); pdctl1 |= 0x1; - davinci_writel(pdctl1, DAVINCI_PWR_SLEEP_CNTRL_BASE + PDCTL1); + __raw_writel(pdctl1, psc_base + PDCTL1); ptcmd = 1 << domain; - davinci_writel(ptcmd, DAVINCI_PWR_SLEEP_CNTRL_BASE + PTCMD); + __raw_writel(ptcmd, psc_base + PTCMD); do { - epcpr = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + - EPCPR); + epcpr = __raw_readl(psc_base + EPCPR); } while ((((epcpr >> domain) & 1) == 0)); - pdctl1 = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + PDCTL1); + pdctl1 = __raw_readl(psc_base + PDCTL1); pdctl1 |= 0x100; - davinci_writel(pdctl1, DAVINCI_PWR_SLEEP_CNTRL_BASE + PDCTL1); + __raw_writel(pdctl1, psc_base + PDCTL1); do { - ptstat = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + + ptstat = __raw_readl(psc_base + PTSTAT); } while (!(((ptstat >> domain) & 1) == 0)); } else { ptcmd = 1 << domain; - davinci_writel(ptcmd, DAVINCI_PWR_SLEEP_CNTRL_BASE + PTCMD); + __raw_writel(ptcmd, psc_base + PTCMD); do { - ptstat = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + - PTSTAT); + ptstat = __raw_readl(psc_base + PTSTAT); } while (!(((ptstat >> domain) & 1) == 0)); } - if (enable) - mdstat_mask = 0x3; - else - mdstat_mask = 0x2; - do { - mdstat = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + - MDSTAT + 4 * id); - } while (!((mdstat & 0x0000001F) == mdstat_mask)); - - if (enable) - davinci_psc_mux(id); -} - -void __init davinci_psc_init(void) -{ - davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_VPSSMSTR, 1); - davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_VPSSSLV, 1); - davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_TPCC, 1); - davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_TPTC0, 1); - davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_TPTC1, 1); - davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_GPIO, 1); - - /* Turn on WatchDog timer LPSC. Needed for RESET to work */ - davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_TIMER2, 1); + mdstat = __raw_readl(psc_base + MDSTAT + 4 * id); + } while (!((mdstat & MDSTAT_STATE_MASK) == next_state)); } diff --git a/arch/arm/mach-davinci/serial.c b/arch/arm/mach-davinci/serial.c index 3010f997125..69507579652 100644 --- a/arch/arm/mach-davinci/serial.c +++ b/arch/arm/mach-davinci/serial.c @@ -32,32 +32,47 @@ #include <mach/hardware.h> #include <mach/serial.h> #include <mach/irqs.h> +#include <mach/cputype.h> +#include "clock.h" -#define UART_DAVINCI_PWREMU 0x0c - -static inline unsigned int davinci_serial_in(struct plat_serial8250_port *up, - int offset) +static inline unsigned int serial_read_reg(struct plat_serial8250_port *up, + int offset) { offset <<= up->regshift; - return (unsigned int)__raw_readb(up->membase + offset); + return (unsigned int)__raw_readl(IO_ADDRESS(up->mapbase) + offset); } -static inline void davinci_serial_outp(struct plat_serial8250_port *p, - int offset, int value) +static inline void serial_write_reg(struct plat_serial8250_port *p, int offset, + int value) { offset <<= p->regshift; - __raw_writeb(value, p->membase + offset); + __raw_writel(value, IO_ADDRESS(p->mapbase) + offset); } static struct plat_serial8250_port serial_platform_data[] = { { - .membase = (char *)IO_ADDRESS(DAVINCI_UART0_BASE), - .mapbase = (unsigned long)DAVINCI_UART0_BASE, + .mapbase = DAVINCI_UART0_BASE, .irq = IRQ_UARTINT0, - .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, + .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | + UPF_IOREMAP, + .iotype = UPIO_MEM, + .regshift = 2, + }, + { + .mapbase = DAVINCI_UART1_BASE, + .irq = IRQ_UARTINT1, + .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | + UPF_IOREMAP, + .iotype = UPIO_MEM, + .regshift = 2, + }, + { + .mapbase = DAVINCI_UART2_BASE, + .irq = IRQ_UARTINT2, + .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | + UPF_IOREMAP, .iotype = UPIO_MEM, .regshift = 2, - .uartclk = 27000000, }, { .flags = 0 @@ -74,22 +89,68 @@ static struct platform_device serial_device = { static void __init davinci_serial_reset(struct plat_serial8250_port *p) { - /* reset both transmitter and receiver: bits 14,13 = UTRST, URRST */ unsigned int pwremu = 0; - davinci_serial_outp(p, UART_IER, 0); /* disable all interrupts */ + serial_write_reg(p, UART_IER, 0); /* disable all interrupts */ - davinci_serial_outp(p, UART_DAVINCI_PWREMU, pwremu); + /* reset both transmitter and receiver: bits 14,13 = UTRST, URRST */ + serial_write_reg(p, UART_DAVINCI_PWREMU, pwremu); mdelay(10); pwremu |= (0x3 << 13); pwremu |= 0x1; - davinci_serial_outp(p, UART_DAVINCI_PWREMU, pwremu); + serial_write_reg(p, UART_DAVINCI_PWREMU, pwremu); + + if (cpu_is_davinci_dm646x()) + serial_write_reg(p, UART_DM646X_SCR, + UART_DM646X_SCR_TX_WATERMARK); +} + +void __init davinci_serial_init(struct davinci_uart_config *info) +{ + int i; + char name[16]; + struct clk *uart_clk; + struct device *dev = &serial_device.dev; + + /* + * Make sure the serial ports are muxed on at this point. + * You have to mux them off in device drivers later on + * if not needed. + */ + for (i = 0; i < DAVINCI_MAX_NR_UARTS; i++) { + struct plat_serial8250_port *p = serial_platform_data + i; + + if (!(info->enabled_uarts & (1 << i))) { + p->flags = 0; + continue; + } + + if (cpu_is_davinci_dm646x()) + p->iotype = UPIO_MEM32; + + if (cpu_is_davinci_dm355()) { + if (i == 2) { + p->mapbase = (unsigned long)DM355_UART2_BASE; + p->irq = IRQ_DM355_UARTINT2; + } + } + + sprintf(name, "uart%d", i); + uart_clk = clk_get(dev, name); + if (IS_ERR(uart_clk)) + printk(KERN_ERR "%s:%d: failed to get UART%d clock\n", + __func__, __LINE__, i); + else { + clk_enable(uart_clk); + p->uartclk = clk_get_rate(uart_clk); + davinci_serial_reset(p); + } + } } static int __init davinci_init(void) { - davinci_serial_reset(&serial_platform_data[0]); return platform_device_register(&serial_device); } diff --git a/arch/arm/mach-davinci/time.c b/arch/arm/mach-davinci/time.c index 6c227d4ba99..494e01bff5c 100644 --- a/arch/arm/mach-davinci/time.c +++ b/arch/arm/mach-davinci/time.c @@ -16,6 +16,9 @@ #include <linux/clockchips.h> #include <linux/spinlock.h> #include <linux/io.h> +#include <linux/clk.h> +#include <linux/err.h> +#include <linux/device.h> #include <mach/hardware.h> #include <asm/system.h> @@ -24,8 +27,11 @@ #include <asm/mach/time.h> #include <asm/errno.h> #include <mach/io.h> +#include <mach/cputype.h> +#include "clock.h" static struct clock_event_device clockevent_davinci; +static unsigned int davinci_clock_tick_rate; #define DAVINCI_TIMER0_BASE (IO_PHYS + 0x21400) #define DAVINCI_TIMER1_BASE (IO_PHYS + 0x21800) @@ -99,9 +105,9 @@ struct timer_s { unsigned int id; unsigned long period; unsigned long opts; - unsigned long reg_base; - unsigned long tim_reg; - unsigned long prd_reg; + void __iomem *base; + unsigned long tim_off; + unsigned long prd_off; unsigned long enamode_shift; struct irqaction irqaction; }; @@ -114,15 +120,15 @@ static struct timer_s timers[]; static int timer32_config(struct timer_s *t) { - u32 tcr = davinci_readl(t->reg_base + TCR); + u32 tcr = __raw_readl(t->base + TCR); /* disable timer */ tcr &= ~(TCR_ENAMODE_MASK << t->enamode_shift); - davinci_writel(tcr, t->reg_base + TCR); + __raw_writel(tcr, t->base + TCR); /* reset counter to zero, set new period */ - davinci_writel(0, t->tim_reg); - davinci_writel(t->period, t->prd_reg); + __raw_writel(0, t->base + t->tim_off); + __raw_writel(t->period, t->base + t->prd_off); /* Set enable mode */ if (t->opts & TIMER_OPTS_ONESHOT) { @@ -131,13 +137,13 @@ static int timer32_config(struct timer_s *t) tcr |= TCR_ENAMODE_PERIODIC << t->enamode_shift; } - davinci_writel(tcr, t->reg_base + TCR); + __raw_writel(tcr, t->base + TCR); return 0; } static inline u32 timer32_read(struct timer_s *t) { - return davinci_readl(t->tim_reg); + return __raw_readl(t->base + t->tim_off); } static irqreturn_t timer_interrupt(int irq, void *dev_id) @@ -176,51 +182,54 @@ static struct timer_s timers[] = { static void __init timer_init(void) { - u32 bases[] = {DAVINCI_TIMER0_BASE, DAVINCI_TIMER1_BASE}; + u32 phys_bases[] = {DAVINCI_TIMER0_BASE, DAVINCI_TIMER1_BASE}; int i; /* Global init of each 64-bit timer as a whole */ for(i=0; i<2; i++) { - u32 tgcr, base = bases[i]; + u32 tgcr; + void __iomem *base = IO_ADDRESS(phys_bases[i]); /* Disabled, Internal clock source */ - davinci_writel(0, base + TCR); + __raw_writel(0, base + TCR); /* reset both timers, no pre-scaler for timer34 */ tgcr = 0; - davinci_writel(tgcr, base + TGCR); + __raw_writel(tgcr, base + TGCR); /* Set both timers to unchained 32-bit */ tgcr = TGCR_TIMMODE_32BIT_UNCHAINED << TGCR_TIMMODE_SHIFT; - davinci_writel(tgcr, base + TGCR); + __raw_writel(tgcr, base + TGCR); /* Unreset timers */ tgcr |= (TGCR_UNRESET << TGCR_TIM12RS_SHIFT) | (TGCR_UNRESET << TGCR_TIM34RS_SHIFT); - davinci_writel(tgcr, base + TGCR); + __raw_writel(tgcr, base + TGCR); /* Init both counters to zero */ - davinci_writel(0, base + TIM12); - davinci_writel(0, base + TIM34); + __raw_writel(0, base + TIM12); + __raw_writel(0, base + TIM34); } /* Init of each timer as a 32-bit timer */ for (i=0; i< ARRAY_SIZE(timers); i++) { struct timer_s *t = &timers[i]; + u32 phys_base; if (t->name) { t->id = i; - t->reg_base = (IS_TIMER1(t->id) ? + phys_base = (IS_TIMER1(t->id) ? DAVINCI_TIMER1_BASE : DAVINCI_TIMER0_BASE); + t->base = IO_ADDRESS(phys_base); if (IS_TIMER_BOT(t->id)) { t->enamode_shift = 6; - t->tim_reg = t->reg_base + TIM12; - t->prd_reg = t->reg_base + PRD12; + t->tim_off = TIM12; + t->prd_off = PRD12; } else { t->enamode_shift = 22; - t->tim_reg = t->reg_base + TIM34; - t->prd_reg = t->reg_base + PRD34; + t->tim_off = TIM34; + t->prd_off = PRD34; } /* Register interrupt */ @@ -274,7 +283,7 @@ static void davinci_set_mode(enum clock_event_mode mode, switch (mode) { case CLOCK_EVT_MODE_PERIODIC: - t->period = CLOCK_TICK_RATE / (HZ); + t->period = davinci_clock_tick_rate / (HZ); t->opts = TIMER_OPTS_PERIODIC; timer32_config(t); break; @@ -301,21 +310,29 @@ static struct clock_event_device clockevent_davinci = { static void __init davinci_timer_init(void) { + struct clk *timer_clk; + static char err[] __initdata = KERN_ERR "%s: can't register clocksource!\n"; /* init timer hw */ timer_init(); + timer_clk = clk_get(NULL, "timer0"); + BUG_ON(IS_ERR(timer_clk)); + clk_enable(timer_clk); + + davinci_clock_tick_rate = clk_get_rate(timer_clk); + /* setup clocksource */ clocksource_davinci.mult = - clocksource_khz2mult(CLOCK_TICK_RATE/1000, + clocksource_khz2mult(davinci_clock_tick_rate/1000, clocksource_davinci.shift); if (clocksource_register(&clocksource_davinci)) printk(err, clocksource_davinci.name); /* setup clockevent */ - clockevent_davinci.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC, + clockevent_davinci.mult = div_sc(davinci_clock_tick_rate, NSEC_PER_SEC, clockevent_davinci.shift); clockevent_davinci.max_delta_ns = clockevent_delta2ns(0xfffffffe, &clockevent_davinci); @@ -333,42 +350,52 @@ struct sys_timer davinci_timer = { /* reset board using watchdog timer */ void davinci_watchdog_reset(void) { - u32 tgcr, wdtcr, base = DAVINCI_WDOG_BASE; + u32 tgcr, wdtcr; + void __iomem *base = IO_ADDRESS(DAVINCI_WDOG_BASE); + struct device dev; + struct clk *wd_clk; + char *name = "watchdog"; + + dev_set_name(&dev, name); + wd_clk = clk_get(&dev, NULL); + if (WARN_ON(IS_ERR(wd_clk))) + return; + clk_enable(wd_clk); /* disable, internal clock source */ - davinci_writel(0, base + TCR); + __raw_writel(0, base + TCR); /* reset timer, set mode to 64-bit watchdog, and unreset */ tgcr = 0; - davinci_writel(tgcr, base + TCR); + __raw_writel(tgcr, base + TCR); tgcr = TGCR_TIMMODE_64BIT_WDOG << TGCR_TIMMODE_SHIFT; tgcr |= (TGCR_UNRESET << TGCR_TIM12RS_SHIFT) | (TGCR_UNRESET << TGCR_TIM34RS_SHIFT); - davinci_writel(tgcr, base + TCR); + __raw_writel(tgcr, base + TCR); /* clear counter and period regs */ - davinci_writel(0, base + TIM12); - davinci_writel(0, base + TIM34); - davinci_writel(0, base + PRD12); - davinci_writel(0, base + PRD34); + __raw_writel(0, base + TIM12); + __raw_writel(0, base + TIM34); + __raw_writel(0, base + PRD12); + __raw_writel(0, base + PRD34); /* enable */ - wdtcr = davinci_readl(base + WDTCR); + wdtcr = __raw_readl(base + WDTCR); wdtcr |= WDTCR_WDEN_ENABLE << WDTCR_WDEN_SHIFT; - davinci_writel(wdtcr, base + WDTCR); + __raw_writel(wdtcr, base + WDTCR); /* put watchdog in pre-active state */ wdtcr = (WDTCR_WDKEY_SEQ0 << WDTCR_WDKEY_SHIFT) | (WDTCR_WDEN_ENABLE << WDTCR_WDEN_SHIFT); - davinci_writel(wdtcr, base + WDTCR); + __raw_writel(wdtcr, base + WDTCR); /* put watchdog in active state */ wdtcr = (WDTCR_WDKEY_SEQ1 << WDTCR_WDKEY_SHIFT) | (WDTCR_WDEN_ENABLE << WDTCR_WDEN_SHIFT); - davinci_writel(wdtcr, base + WDTCR); + __raw_writel(wdtcr, base + WDTCR); /* write an invalid value to the WDKEY field to trigger * a watchdog reset */ wdtcr = 0x00004000; - davinci_writel(wdtcr, base + WDTCR); + __raw_writel(wdtcr, base + WDTCR); } diff --git a/arch/arm/mach-davinci/usb.c b/arch/arm/mach-davinci/usb.c index 2429b79f6da..abedb633718 100644 --- a/arch/arm/mach-davinci/usb.c +++ b/arch/arm/mach-davinci/usb.c @@ -14,6 +14,8 @@ #include <mach/hardware.h> #include <mach/irqs.h> +#define DAVINCI_USB_OTG_BASE 0x01C64000 + #if defined(CONFIG_USB_MUSB_HDRC) || defined(CONFIG_USB_MUSB_HDRC_MODULE) static struct musb_hdrc_eps_bits musb_eps[] = { { "ep1_tx", 8, }, diff --git a/arch/arm/mach-ixp4xx/ixp4xx_npe.c b/arch/arm/mach-ixp4xx/ixp4xx_npe.c index 25231023490..7bb8e778e4b 100644 --- a/arch/arm/mach-ixp4xx/ixp4xx_npe.c +++ b/arch/arm/mach-ixp4xx/ixp4xx_npe.c @@ -714,7 +714,7 @@ static int __init npe_init_module(void) } if (!found) - return -ENOSYS; + return -ENODEV; return 0; } diff --git a/arch/arm/mach-omap1/board-h2-mmc.c b/arch/arm/mach-omap1/board-h2-mmc.c index 44d4a966bed..46098f54682 100644 --- a/arch/arm/mach-omap1/board-h2-mmc.c +++ b/arch/arm/mach-omap1/board-h2-mmc.c @@ -26,19 +26,13 @@ static int mmc_set_power(struct device *dev, int slot, int power_on, int vdd) { - if (power_on) - gpio_direction_output(H2_TPS_GPIO_MMC_PWR_EN, 1); - else - gpio_direction_output(H2_TPS_GPIO_MMC_PWR_EN, 0); - + gpio_set_value(H2_TPS_GPIO_MMC_PWR_EN, power_on); return 0; } static int mmc_late_init(struct device *dev) { - int ret; - - ret = gpio_request(H2_TPS_GPIO_MMC_PWR_EN, "MMC power"); + int ret = gpio_request(H2_TPS_GPIO_MMC_PWR_EN, "MMC power"); if (ret < 0) return ret; @@ -47,7 +41,7 @@ static int mmc_late_init(struct device *dev) return ret; } -static void mmc_shutdown(struct device *dev) +static void mmc_cleanup(struct device *dev) { gpio_free(H2_TPS_GPIO_MMC_PWR_EN); } @@ -60,7 +54,7 @@ static void mmc_shutdown(struct device *dev) static struct omap_mmc_platform_data mmc1_data = { .nr_slots = 1, .init = mmc_late_init, - .shutdown = mmc_shutdown, + .cleanup = mmc_cleanup, .dma_mask = 0xffffffff, .slots[0] = { .set_power = mmc_set_power, diff --git a/arch/arm/mach-omap1/board-h3-mmc.c b/arch/arm/mach-omap1/board-h3-mmc.c index 0d8a3c195e2..5e8877ce35e 100644 --- a/arch/arm/mach-omap1/board-h3-mmc.c +++ b/arch/arm/mach-omap1/board-h3-mmc.c @@ -26,11 +26,7 @@ static int mmc_set_power(struct device *dev, int slot, int power_on, int vdd) { - if (power_on) - gpio_direction_output(H3_TPS_GPIO_MMC_PWR_EN, 1); - else - gpio_direction_output(H3_TPS_GPIO_MMC_PWR_EN, 0); - + gpio_set_value(H3_TPS_GPIO_MMC_PWR_EN, power_on); return 0; } diff --git a/arch/arm/mach-omap1/board-h3.c b/arch/arm/mach-omap1/board-h3.c index 4695965114c..f597968733b 100644 --- a/arch/arm/mach-omap1/board-h3.c +++ b/arch/arm/mach-omap1/board-h3.c @@ -39,12 +39,10 @@ #include <asm/mach/flash.h> #include <asm/mach/map.h> -#include <mach/gpioexpander.h> #include <mach/irqs.h> #include <mach/mux.h> #include <mach/tc.h> #include <mach/nand.h> -#include <mach/irda.h> #include <mach/usb.h> #include <mach/keypad.h> #include <mach/dma.h> @@ -276,104 +274,6 @@ static struct platform_device h3_kp_device = { .resource = h3_kp_resources, }; - -/* Select between the IrDA and aGPS module - */ -static int h3_select_irda(struct device *dev, int state) -{ - unsigned char expa; - int err = 0; - - if ((err = read_gpio_expa(&expa, 0x26))) { - printk(KERN_ERR "Error reading from I/O EXPANDER \n"); - return err; - } - - /* 'P6' enable/disable IRDA_TX and IRDA_RX */ - if (state & IR_SEL) { /* IrDA */ - if ((err = write_gpio_expa(expa | 0x40, 0x26))) { - printk(KERN_ERR "Error writing to I/O EXPANDER \n"); - return err; - } - } else { - if ((err = write_gpio_expa(expa & ~0x40, 0x26))) { - printk(KERN_ERR "Error writing to I/O EXPANDER \n"); - return err; - } - } - return err; -} - -static void set_trans_mode(struct work_struct *work) -{ - struct omap_irda_config *irda_config = - container_of(work, struct omap_irda_config, gpio_expa.work); - int mode = irda_config->mode; - unsigned char expa; - int err = 0; - - if ((err = read_gpio_expa(&expa, 0x27)) != 0) { - printk(KERN_ERR "Error reading from I/O expander\n"); - } - - expa &= ~0x03; - - if (mode & IR_SIRMODE) { - expa |= 0x01; - } else { /* MIR/FIR */ - expa |= 0x03; - } - - if ((err = write_gpio_expa(expa, 0x27)) != 0) { - printk(KERN_ERR "Error writing to I/O expander\n"); - } -} - -static int h3_transceiver_mode(struct device *dev, int mode) -{ - struct omap_irda_config *irda_config = dev->platform_data; - - irda_config->mode = mode; - cancel_delayed_work(&irda_config->gpio_expa); - PREPARE_DELAYED_WORK(&irda_config->gpio_expa, set_trans_mode); - schedule_delayed_work(&irda_config->gpio_expa, 0); - - return 0; -} - -static struct omap_irda_config h3_irda_data = { - .transceiver_cap = IR_SIRMODE | IR_MIRMODE | IR_FIRMODE, - .transceiver_mode = h3_transceiver_mode, - .select_irda = h3_select_irda, - .rx_channel = OMAP_DMA_UART3_RX, - .tx_channel = OMAP_DMA_UART3_TX, - .dest_start = UART3_THR, - .src_start = UART3_RHR, - .tx_trigger = 0, - .rx_trigger = 0, -}; - -static struct resource h3_irda_resources[] = { - [0] = { - .start = INT_UART3, - .end = INT_UART3, - .flags = IORESOURCE_IRQ, - }, -}; - -static u64 irda_dmamask = 0xffffffff; - -static struct platform_device h3_irda_device = { - .name = "omapirda", - .id = 0, - .dev = { - .platform_data = &h3_irda_data, - .dma_mask = &irda_dmamask, - }, - .num_resources = ARRAY_SIZE(h3_irda_resources), - .resource = h3_irda_resources, -}; - static struct platform_device h3_lcd_device = { .name = "lcd_h3", .id = -1, @@ -395,7 +295,6 @@ static struct platform_device *devices[] __initdata = { &nand_device, &smc91x_device, &intlat_device, - &h3_irda_device, &h3_kp_device, &h3_lcd_device, }; diff --git a/arch/arm/mach-omap1/board-nokia770.c b/arch/arm/mach-omap1/board-nokia770.c index 7bc7a3cb9c5..d1ed1365319 100644 --- a/arch/arm/mach-omap1/board-nokia770.c +++ b/arch/arm/mach-omap1/board-nokia770.c @@ -181,11 +181,7 @@ static struct omap_usb_config nokia770_usb_config __initdata = { static int nokia770_mmc_set_power(struct device *dev, int slot, int power_on, int vdd) { - if (power_on) - gpio_set_value(NOKIA770_GPIO_MMC_POWER, 1); - else - gpio_set_value(NOKIA770_GPIO_MMC_POWER, 0); - + gpio_set_value(NOKIA770_GPIO_MMC_POWER, power_on); return 0; } diff --git a/arch/arm/mach-omap1/mcbsp.c b/arch/arm/mach-omap1/mcbsp.c index d040c3f1027..a2d7814896b 100644 --- a/arch/arm/mach-omap1/mcbsp.c +++ b/arch/arm/mach-omap1/mcbsp.c @@ -40,8 +40,8 @@ static void omap1_mcbsp_request(unsigned int id) */ if (id == OMAP_MCBSP1 || id == OMAP_MCBSP3) { if (dsp_use++ == 0) { - api_clk = clk_get(NULL, "api_clk"); - dsp_clk = clk_get(NULL, "dsp_clk"); + api_clk = clk_get(NULL, "api_ck"); + dsp_clk = clk_get(NULL, "dsp_ck"); if (!IS_ERR(api_clk) && !IS_ERR(dsp_clk)) { clk_enable(api_clk); clk_enable(dsp_clk); diff --git a/arch/arm/mach-omap2/board-h4.c b/arch/arm/mach-omap2/board-h4.c index a0267a9ab46..e7d017cdc43 100644 --- a/arch/arm/mach-omap2/board-h4.c +++ b/arch/arm/mach-omap2/board-h4.c @@ -33,10 +33,8 @@ #include <mach/control.h> #include <mach/gpio.h> -#include <mach/gpioexpander.h> #include <mach/mux.h> #include <mach/usb.h> -#include <mach/irda.h> #include <mach/board.h> #include <mach/common.h> #include <mach/keypad.h> @@ -138,98 +136,6 @@ static struct platform_device h4_flash_device = { .resource = &h4_flash_resource, }; -/* Select between the IrDA and aGPS module - */ -static int h4_select_irda(struct device *dev, int state) -{ - unsigned char expa; - int err = 0; - - if ((err = read_gpio_expa(&expa, 0x21))) { - printk(KERN_ERR "Error reading from I/O expander\n"); - return err; - } - - /* 'P6' enable/disable IRDA_TX and IRDA_RX */ - if (state & IR_SEL) { /* IrDa */ - if ((err = write_gpio_expa(expa | 0x01, 0x21))) { - printk(KERN_ERR "Error writing to I/O expander\n"); - return err; - } - } else { - if ((err = write_gpio_expa(expa & ~0x01, 0x21))) { - printk(KERN_ERR "Error writing to I/O expander\n"); - return err; - } - } - return err; -} - -static void set_trans_mode(struct work_struct *work) -{ - struct omap_irda_config *irda_config = - container_of(work, struct omap_irda_config, gpio_expa.work); - int mode = irda_config->mode; - unsigned char expa; - int err = 0; - - if ((err = read_gpio_expa(&expa, 0x20)) != 0) { - printk(KERN_ERR "Error reading from I/O expander\n"); - } - - expa &= ~0x01; - - if (!(mode & IR_SIRMODE)) { /* MIR/FIR */ - expa |= 0x01; - } - - if ((err = write_gpio_expa(expa, 0x20)) != 0) { - printk(KERN_ERR "Error writing to I/O expander\n"); - } -} - -static int h4_transceiver_mode(struct device *dev, int mode) -{ - struct omap_irda_config *irda_config = dev->platform_data; - - irda_config->mode = mode; - cancel_delayed_work(&irda_config->gpio_expa); - PREPARE_DELAYED_WORK(&irda_config->gpio_expa, set_trans_mode); - schedule_delayed_work(&irda_config->gpio_expa, 0); - - return 0; -} - -static struct omap_irda_config h4_irda_data = { - .transceiver_cap = IR_SIRMODE | IR_MIRMODE | IR_FIRMODE, - .transceiver_mode = h4_transceiver_mode, - .select_irda = h4_select_irda, - .rx_channel = OMAP24XX_DMA_UART3_RX, - .tx_channel = OMAP24XX_DMA_UART3_TX, - .dest_start = OMAP_UART3_BASE, - .src_start = OMAP_UART3_BASE, - .tx_trigger = OMAP24XX_DMA_UART3_TX, - .rx_trigger = OMAP24XX_DMA_UART3_RX, -}; - -static struct resource h4_irda_resources[] = { - [0] = { - .start = INT_24XX_UART3_IRQ, - .end = INT_24XX_UART3_IRQ, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct platform_device h4_irda_device = { - .name = "omapirda", - .id = -1, - .dev = { - .platform_data = &h4_irda_data, - }, - .num_resources = 1, - .resource = h4_irda_resources, -}; - static struct omap_kp_platform_data h4_kp_data = { .rows = 6, .cols = 7, @@ -255,7 +161,6 @@ static struct platform_device h4_lcd_device = { static struct platform_device *h4_devices[] __initdata = { &h4_flash_device, - &h4_irda_device, &h4_kp_device, &h4_lcd_device, }; diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c index 744740ae1b9..3a7a29d1f9a 100644 --- a/arch/arm/mach-omap2/board-omap3beagle.c +++ b/arch/arm/mach-omap2/board-omap3beagle.c @@ -42,6 +42,7 @@ #include <mach/nand.h> #include <mach/mux.h> #include <mach/usb.h> +#include <mach/timer-gp.h> #include "mmc-twl4030.h" @@ -186,6 +187,9 @@ static void __init omap3_beagle_init_irq(void) { omap2_init_common_hw(NULL); omap_init_irq(); +#ifdef CONFIG_OMAP_32K_TIMER + omap2_gp_clockevent_set_gptimer(12); +#endif omap_gpio_init(); } diff --git a/arch/arm/mach-omap2/board-rx51.c b/arch/arm/mach-omap2/board-rx51.c index 3a0daac6c83..374ff63c3eb 100644 --- a/arch/arm/mach-omap2/board-rx51.c +++ b/arch/arm/mach-omap2/board-rx51.c @@ -15,7 +15,6 @@ #include <linux/err.h> #include <linux/clk.h> #include <linux/io.h> -#include <linux/delay.h> #include <linux/gpio.h> #include <mach/hardware.h> diff --git a/arch/arm/mach-omap2/clock24xx.c b/arch/arm/mach-omap2/clock24xx.c index 1e839c5a28c..efc59c49341 100644 --- a/arch/arm/mach-omap2/clock24xx.c +++ b/arch/arm/mach-omap2/clock24xx.c @@ -60,12 +60,13 @@ struct omap_clk { }, \ } -#define CK_243X (1 << 0) -#define CK_242X (1 << 1) +#define CK_243X RATE_IN_243X +#define CK_242X RATE_IN_242X static struct omap_clk omap24xx_clks[] = { /* external root sources */ CLK(NULL, "func_32k_ck", &func_32k_ck, CK_243X | CK_242X), + CLK(NULL, "secure_32k_ck", &secure_32k_ck, CK_243X | CK_242X), CLK(NULL, "osc_ck", &osc_ck, CK_243X | CK_242X), CLK(NULL, "sys_ck", &sys_ck, CK_243X | CK_242X), CLK(NULL, "alt_ck", &alt_ck, CK_243X | CK_242X), @@ -711,7 +712,7 @@ int __init omap2_clk_init(void) { struct prcm_config *prcm; struct omap_clk *c; - u32 clkrate, cpu_mask; + u32 clkrate; if (cpu_is_omap242x()) cpu_mask = RATE_IN_242X; @@ -720,21 +721,15 @@ int __init omap2_clk_init(void) clk_init(&omap2_clk_functions); + for (c = omap24xx_clks; c < omap24xx_clks + ARRAY_SIZE(omap24xx_clks); c++) + clk_init_one(c->lk.clk); + osc_ck.rate = omap2_osc_clk_recalc(&osc_ck); propagate_rate(&osc_ck); sys_ck.rate = omap2_sys_clk_recalc(&sys_ck); propagate_rate(&sys_ck); for (c = omap24xx_clks; c < omap24xx_clks + ARRAY_SIZE(omap24xx_clks); c++) - clk_init_one(c->lk.clk); - - cpu_mask = 0; - if (cpu_is_omap2420()) - cpu_mask |= CK_242X; - if (cpu_is_omap2430()) - cpu_mask |= CK_243X; - - for (c = omap24xx_clks; c < omap24xx_clks + ARRAY_SIZE(omap24xx_clks); c++) if (c->cpu & cpu_mask) { clkdev_add(&c->lk); clk_register(c->lk.clk); diff --git a/arch/arm/mach-omap2/clock24xx.h b/arch/arm/mach-omap2/clock24xx.h index 33c3e5b1432..88c5acb40fc 100644 --- a/arch/arm/mach-omap2/clock24xx.h +++ b/arch/arm/mach-omap2/clock24xx.h @@ -625,6 +625,14 @@ static struct clk func_32k_ck = { .clkdm_name = "wkup_clkdm", }; +static struct clk secure_32k_ck = { + .name = "secure_32k_ck", + .ops = &clkops_null, + .rate = 32768, + .flags = RATE_FIXED, + .clkdm_name = "wkup_clkdm", +}; + /* Typical 12/13MHz in standalone mode, will be 26Mhz in chassis mode */ static struct clk osc_ck = { /* (*12, *13, 19.2, *26, 38.4)MHz */ .name = "osc_ck", @@ -1790,7 +1798,7 @@ static struct clk gpt12_ick = { static struct clk gpt12_fck = { .name = "gpt12_fck", .ops = &clkops_omap2_dflt_wait, - .parent = &func_32k_ck, + .parent = &secure_32k_ck, .clkdm_name = "core_l4_clkdm", .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), .enable_bit = OMAP24XX_EN_GPT12_SHIFT, diff --git a/arch/arm/mach-omap2/clock34xx.h b/arch/arm/mach-omap2/clock34xx.h index 70ec10deb65..6763b8f7302 100644 --- a/arch/arm/mach-omap2/clock34xx.h +++ b/arch/arm/mach-omap2/clock34xx.h @@ -2052,7 +2052,7 @@ static struct clk dss_ick = { static struct clk cam_mclk = { .name = "cam_mclk", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_dflt, .parent = &dpll4_m5x2_ck, .enable_reg = OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_FCLKEN), .enable_bit = OMAP3430_EN_CAM_SHIFT, @@ -2063,7 +2063,7 @@ static struct clk cam_mclk = { static struct clk cam_ick = { /* Handles both L3 and L4 clocks */ .name = "cam_ick", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_dflt, .parent = &l4_ick, .init = &omap2_init_clk_clkdm, .enable_reg = OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_ICLKEN), @@ -2074,7 +2074,7 @@ static struct clk cam_ick = { static struct clk csi2_96m_fck = { .name = "csi2_96m_fck", - .ops = &clkops_omap2_dflt_wait, + .ops = &clkops_omap2_dflt, .parent = &core_96m_fck, .init = &omap2_init_clk_clkdm, .enable_reg = OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_FCLKEN), @@ -2901,7 +2901,6 @@ static struct clk sr_l4_ick = { /* SECURE_32K_FCK clocks */ -/* XXX This clock no longer exists in 3430 TRM rev F */ static struct clk gpt12_fck = { .name = "gpt12_fck", .ops = &clkops_null, diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c index d6b4b2f8722..496983ade97 100644 --- a/arch/arm/mach-omap2/devices.c +++ b/arch/arm/mach-omap2/devices.c @@ -25,7 +25,6 @@ #include <mach/board.h> #include <mach/mux.h> #include <mach/gpio.h> -#include <mach/eac.h> #include <mach/mmc.h> #if defined(CONFIG_VIDEO_OMAP2) || defined(CONFIG_VIDEO_OMAP2_MODULE) @@ -366,38 +365,6 @@ static void omap_init_mcspi(void) static inline void omap_init_mcspi(void) {} #endif -#ifdef CONFIG_SND_OMAP24XX_EAC - -#define OMAP2_EAC_BASE 0x48090000 - -static struct resource omap2_eac_resources[] = { - { - .start = OMAP2_EAC_BASE, - .end = OMAP2_EAC_BASE + 0x109, - .flags = IORESOURCE_MEM, - }, -}; - -static struct platform_device omap2_eac_device = { - .name = "omap24xx-eac", - .id = -1, - .num_resources = ARRAY_SIZE(omap2_eac_resources), - .resource = omap2_eac_resources, - .dev = { - .platform_data = NULL, - }, -}; - -void omap_init_eac(struct eac_platform_data *pdata) -{ - omap2_eac_device.dev.platform_data = pdata; - platform_device_register(&omap2_eac_device); -} - -#else -void omap_init_eac(struct eac_platform_data *pdata) {} -#endif - #ifdef CONFIG_OMAP_SHA1_MD5 static struct resource sha1_md5_resources[] = { { diff --git a/arch/arm/mach-omap2/irq.c b/arch/arm/mach-omap2/irq.c index 9ba20d985dd..998c5c45587 100644 --- a/arch/arm/mach-omap2/irq.c +++ b/arch/arm/mach-omap2/irq.c @@ -73,9 +73,9 @@ static int omap_check_spurious(unsigned int irq) u32 sir, spurious; sir = intc_bank_read_reg(&irq_banks[0], INTC_SIR); - spurious = sir >> 6; + spurious = sir >> 7; - if (spurious > 1) { + if (spurious) { printk(KERN_WARNING "Spurious irq %i: 0x%08x, please flush " "posted write for irq %i\n", irq, sir, previous_irq); diff --git a/arch/arm/mach-omap2/timer-gp.c b/arch/arm/mach-omap2/timer-gp.c index 1cb2c0909c2..f36aba12090 100644 --- a/arch/arm/mach-omap2/timer-gp.c +++ b/arch/arm/mach-omap2/timer-gp.c @@ -3,6 +3,8 @@ * * OMAP2 GP timer support. * + * Copyright (C) 2009 Nokia Corporation + * * Update to use new clocksource/clockevent layers * Author: Kevin Hilman, MontaVista Software, Inc. <source@mvista.com> * Copyright (C) 2007 MontaVista Software, Inc. @@ -36,8 +38,13 @@ #include <asm/mach/time.h> #include <mach/dmtimer.h> +/* MAX_GPTIMER_ID: number of GPTIMERs on the chip */ +#define MAX_GPTIMER_ID 12 + static struct omap_dm_timer *gptimer; static struct clock_event_device clockevent_gpt; +static u8 __initdata gptimer_id = 1; +static u8 __initdata inited; static irqreturn_t omap2_gp_timer_interrupt(int irq, void *dev_id) { @@ -95,20 +102,53 @@ static struct clock_event_device clockevent_gpt = { .set_mode = omap2_gp_timer_set_mode, }; +/** + * omap2_gp_clockevent_set_gptimer - set which GPTIMER is used for clockevents + * @id: GPTIMER to use (1..MAX_GPTIMER_ID) + * + * Define the GPTIMER that the system should use for the tick timer. + * Meant to be called from board-*.c files in the event that GPTIMER1, the + * default, is unsuitable. Returns -EINVAL on error or 0 on success. + */ +int __init omap2_gp_clockevent_set_gptimer(u8 id) +{ + if (id < 1 || id > MAX_GPTIMER_ID) + return -EINVAL; + + BUG_ON(inited); + + gptimer_id = id; + + return 0; +} + static void __init omap2_gp_clockevent_init(void) { u32 tick_rate; + int src; + + inited = 1; - gptimer = omap_dm_timer_request_specific(1); + gptimer = omap_dm_timer_request_specific(gptimer_id); BUG_ON(gptimer == NULL); #if defined(CONFIG_OMAP_32K_TIMER) - omap_dm_timer_set_source(gptimer, OMAP_TIMER_SRC_32_KHZ); + src = OMAP_TIMER_SRC_32_KHZ; #else - omap_dm_timer_set_source(gptimer, OMAP_TIMER_SRC_SYS_CLK); + src = OMAP_TIMER_SRC_SYS_CLK; + WARN(gptimer_id == 12, "WARNING: GPTIMER12 can only use the " + "secure 32KiHz clock source\n"); #endif + + if (gptimer_id != 12) + WARN(IS_ERR_VALUE(omap_dm_timer_set_source(gptimer, src)), + "timer-gp: omap_dm_timer_set_source() failed\n"); + tick_rate = clk_get_rate(omap_dm_timer_get_fclk(gptimer)); + pr_info("OMAP clockevent source: GPTIMER%d at %u Hz\n", + gptimer_id, tick_rate); + omap2_gp_timer_irq.dev_id = (void *)gptimer; setup_irq(omap_dm_timer_get_irq(gptimer), &omap2_gp_timer_irq); omap_dm_timer_set_int_enable(gptimer, OMAP_TIMER_INT_OVERFLOW); @@ -125,6 +165,8 @@ static void __init omap2_gp_clockevent_init(void) clockevents_register_device(&clockevent_gpt); } +/* Clocksource code */ + #ifdef CONFIG_OMAP_32K_TIMER /* * When 32k-timer is enabled, don't use GPTimer for clocksource diff --git a/arch/arm/mach-omap2/usb-tusb6010.c b/arch/arm/mach-omap2/usb-tusb6010.c index 15e509013de..8df55f40f4c 100644 --- a/arch/arm/mach-omap2/usb-tusb6010.c +++ b/arch/arm/mach-omap2/usb-tusb6010.c @@ -187,7 +187,7 @@ int tusb6010_platform_retime(unsigned is_refclk) unsigned sysclk_ps; int status; - if (!refclk_psec) + if (!refclk_psec || sysclk_ps == 0) return -ENODEV; sysclk_ps = is_refclk ? refclk_psec : TUSB6010_OSCCLK_60; diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig index 3e66d9099ea..17d3fbd368a 100644 --- a/arch/arm/mach-pxa/Kconfig +++ b/arch/arm/mach-pxa/Kconfig @@ -289,12 +289,12 @@ config MACH_LITTLETON config MACH_TAVOREVB bool "PXA930 Evaluation Board (aka TavorEVB)" select PXA3xx - select PXA930 + select CPU_PXA930 config MACH_SAAR bool "PXA930 Handheld Platform (aka SAAR)" select PXA3xx - select PXA930 + select CPU_PXA930 config MACH_ARMCORE bool "CompuLab CM-X255/CM-X270 modules" diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c index cdf21dd135b..930e364ccde 100644 --- a/arch/arm/mach-pxa/corgi.c +++ b/arch/arm/mach-pxa/corgi.c @@ -427,12 +427,22 @@ static struct pxa2xx_spi_master corgi_spi_info = { .num_chipselect = 3, }; +static void corgi_wait_for_hsync(void) +{ + while (gpio_get_value(CORGI_GPIO_HSYNC)) + cpu_relax(); + + while (!gpio_get_value(CORGI_GPIO_HSYNC)) + cpu_relax(); +} + static struct ads7846_platform_data corgi_ads7846_info = { .model = 7846, .vref_delay_usecs = 100, .x_plate_ohms = 419, .y_plate_ohms = 486, .gpio_pendown = CORGI_GPIO_TP_INT, + .wait_for_sync = corgi_wait_for_hsync, }; static void corgi_ads7846_cs(u32 command) diff --git a/arch/arm/mach-pxa/littleton.c b/arch/arm/mach-pxa/littleton.c index e13f6a81c22..c872b9feb4d 100644 --- a/arch/arm/mach-pxa/littleton.c +++ b/arch/arm/mach-pxa/littleton.c @@ -334,6 +334,11 @@ static struct led_info littleton_da9034_leds[] = { }, }; +static struct da9034_touch_pdata littleton_da9034_touch = { + .x_inverted = 1, + .interval_ms = 20, +}; + static struct da903x_subdev_info littleton_da9034_subdevs[] = { { .name = "da903x-led", @@ -350,6 +355,10 @@ static struct da903x_subdev_info littleton_da9034_subdevs[] = { }, { .name = "da903x-backlight", .id = DA9034_ID_WLED, + }, { + .name = "da9034-touch", + .id = DA9034_ID_TOUCH, + .platform_data = &littleton_da9034_touch, }, }; diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c index 8c61ddac119..c18e34acafc 100644 --- a/arch/arm/mach-pxa/spitz.c +++ b/arch/arm/mach-pxa/spitz.c @@ -299,12 +299,22 @@ static struct pxa2xx_spi_master spitz_spi_info = { .num_chipselect = 3, }; +static void spitz_wait_for_hsync(void) +{ + while (gpio_get_value(SPITZ_GPIO_HSYNC)) + cpu_relax(); + + while (!gpio_get_value(SPITZ_GPIO_HSYNC)) + cpu_relax(); +} + static struct ads7846_platform_data spitz_ads7846_info = { .model = 7846, .vref_delay_usecs = 100, .x_plate_ohms = 419, .y_plate_ohms = 486, .gpio_pendown = SPITZ_GPIO_TP_INT, + .wait_for_sync = spitz_wait_for_hsync, }; static void spitz_ads7846_cs(u32 command) diff --git a/arch/arm/mach-pxa/zylonite_pxa300.c b/arch/arm/mach-pxa/zylonite_pxa300.c index c1f73205d07..c256c57642c 100644 --- a/arch/arm/mach-pxa/zylonite_pxa300.c +++ b/arch/arm/mach-pxa/zylonite_pxa300.c @@ -72,6 +72,7 @@ static mfp_cfg_t common_mfp_cfg[] __initdata = { GPIO25_AC97_SDATA_IN_0, GPIO27_AC97_SDATA_OUT, GPIO28_AC97_SYNC, + GPIO17_GPIO, /* SDATA_IN_1 but unused - configure to GPIO */ /* SSP3 */ GPIO91_SSP3_SCLK, @@ -126,6 +127,10 @@ static mfp_cfg_t common_mfp_cfg[] __initdata = { /* Standard I2C */ GPIO21_I2C_SCL, GPIO22_I2C_SDA, + + /* GPIO */ + GPIO18_GPIO, /* GPIO Expander #0 INT_N */ + GPIO19_GPIO, /* GPIO Expander #1 INT_N */ }; static mfp_cfg_t pxa300_mfp_cfg[] __initdata = { diff --git a/arch/arm/mach-pxa/zylonite_pxa320.c b/arch/arm/mach-pxa/zylonite_pxa320.c index 4e1c488c690..cc5a2283360 100644 --- a/arch/arm/mach-pxa/zylonite_pxa320.c +++ b/arch/arm/mach-pxa/zylonite_pxa320.c @@ -68,6 +68,7 @@ static mfp_cfg_t mfp_cfg[] __initdata = { GPIO38_AC97_SYNC, GPIO39_AC97_BITCLK, GPIO40_AC97_nACRESET, + GPIO36_GPIO, /* SDATA_IN_1 but unused - configure to GPIO */ /* SSP3 */ GPIO89_SSP3_SCLK, diff --git a/arch/arm/mach-s3c2412/pm.c b/arch/arm/mach-s3c2412/pm.c index c9cfe40e21f..a7417c479ff 100644 --- a/arch/arm/mach-s3c2412/pm.c +++ b/arch/arm/mach-s3c2412/pm.c @@ -21,6 +21,7 @@ #include <linux/io.h> #include <mach/hardware.h> +#include <asm/cacheflush.h> #include <asm/irq.h> #include <mach/regs-power.h> @@ -39,6 +40,8 @@ static void s3c2412_cpu_suspend(void) { unsigned long tmp; + flush_cache_all(); + /* set our standby method to sleep */ tmp = __raw_readl(S3C2412_PWRCFG); diff --git a/arch/arm/mach-s3c6400/include/mach/map.h b/arch/arm/mach-s3c6400/include/mach/map.h index baf1c0f1ea5..8199972ed5b 100644 --- a/arch/arm/mach-s3c6400/include/mach/map.h +++ b/arch/arm/mach-s3c6400/include/mach/map.h @@ -40,6 +40,8 @@ #define S3C64XX_PA_FB (0x77100000) #define S3C64XX_PA_SYSCON (0x7E00F000) +#define S3C64XX_PA_IIS0 (0x7F002000) +#define S3C64XX_PA_IIS1 (0x7F003000) #define S3C64XX_PA_TIMER (0x7F006000) #define S3C64XX_PA_IIC0 (0x7F004000) #define S3C64XX_PA_IIC1 (0x7F00F000) diff --git a/arch/arm/mach-sa1100/lart.c b/arch/arm/mach-sa1100/lart.c index 0cd52692d2f..1f940df0e5a 100644 --- a/arch/arm/mach-sa1100/lart.c +++ b/arch/arm/mach-sa1100/lart.c @@ -9,6 +9,7 @@ #include <mach/hardware.h> #include <asm/setup.h> #include <asm/mach-types.h> +#include <asm/page.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> diff --git a/arch/arm/mm/cache-v6.S b/arch/arm/mm/cache-v6.S index 2c6c2a7c05a..8f5c13f4c93 100644 --- a/arch/arm/mm/cache-v6.S +++ b/arch/arm/mm/cache-v6.S @@ -20,6 +20,31 @@ #define D_CACHE_LINE_SIZE 32 #define BTB_FLUSH_SIZE 8 +#ifdef CONFIG_ARM_ERRATA_411920 +/* + * Invalidate the entire I cache (this code is a workaround for the ARM1136 + * erratum 411920 - Invalidate Instruction Cache operation can fail. This + * erratum is present in 1136, 1156 and 1176. It does not affect the MPCore. + * + * Registers: + * r0 - set to 0 + * r1 - corrupted + */ +ENTRY(v6_icache_inval_all) + mov r0, #0 + mrs r1, cpsr + cpsid ifa @ disable interrupts + mcr p15, 0, r0, c7, c5, 0 @ invalidate entire I-cache + mcr p15, 0, r0, c7, c5, 0 @ invalidate entire I-cache + mcr p15, 0, r0, c7, c5, 0 @ invalidate entire I-cache + mcr p15, 0, r0, c7, c5, 0 @ invalidate entire I-cache + msr cpsr_cx, r1 @ restore interrupts + .rept 11 @ ARM Ltd recommends at least + nop @ 11 NOPs + .endr + mov pc, lr +#endif + /* * v6_flush_cache_all() * @@ -31,8 +56,12 @@ ENTRY(v6_flush_kern_cache_all) mov r0, #0 #ifdef HARVARD_CACHE mcr p15, 0, r0, c7, c14, 0 @ D cache clean+invalidate +#ifndef CONFIG_ARM_ERRATA_411920 mcr p15, 0, r0, c7, c5, 0 @ I+BTB cache invalidate #else + b v6_icache_inval_all +#endif +#else mcr p15, 0, r0, c7, c15, 0 @ Cache clean+invalidate #endif mov pc, lr @@ -103,8 +132,12 @@ ENTRY(v6_coherent_user_range) mov r0, #0 #ifdef HARVARD_CACHE mcr p15, 0, r0, c7, c10, 4 @ drain write buffer +#ifndef CONFIG_ARM_ERRATA_411920 mcr p15, 0, r0, c7, c5, 0 @ I+BTB cache invalidate #else + b v6_icache_inval_all +#endif +#else mcr p15, 0, r0, c7, c5, 6 @ invalidate BTB #endif mov pc, lr diff --git a/arch/arm/mm/flush.c b/arch/arm/mm/flush.c index 4e283481cee..c07222eb5ce 100644 --- a/arch/arm/mm/flush.c +++ b/arch/arm/mm/flush.c @@ -18,6 +18,10 @@ #include "mm.h" +#ifdef CONFIG_ARM_ERRATA_411920 +extern void v6_icache_inval_all(void); +#endif + #ifdef CONFIG_CPU_CACHE_VIPT #define ALIAS_FLUSH_START 0xffff4000 @@ -32,10 +36,15 @@ static void flush_pfn_alias(unsigned long pfn, unsigned long vaddr) asm( "mcrr p15, 0, %1, %0, c14\n" " mcr p15, 0, %2, c7, c10, 4\n" +#ifndef CONFIG_ARM_ERRATA_411920 " mcr p15, 0, %2, c7, c5, 0\n" +#endif : : "r" (to), "r" (to + PAGE_SIZE - L1_CACHE_BYTES), "r" (zero) : "cc"); +#ifdef CONFIG_ARM_ERRATA_411920 + v6_icache_inval_all(); +#endif } void flush_cache_mm(struct mm_struct *mm) @@ -48,11 +57,16 @@ void flush_cache_mm(struct mm_struct *mm) if (cache_is_vipt_aliasing()) { asm( "mcr p15, 0, %0, c7, c14, 0\n" + " mcr p15, 0, %0, c7, c10, 4\n" +#ifndef CONFIG_ARM_ERRATA_411920 " mcr p15, 0, %0, c7, c5, 0\n" - " mcr p15, 0, %0, c7, c10, 4" +#endif : : "r" (0) : "cc"); +#ifdef CONFIG_ARM_ERRATA_411920 + v6_icache_inval_all(); +#endif } } @@ -67,11 +81,16 @@ void flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned if (cache_is_vipt_aliasing()) { asm( "mcr p15, 0, %0, c7, c14, 0\n" + " mcr p15, 0, %0, c7, c10, 4\n" +#ifndef CONFIG_ARM_ERRATA_411920 " mcr p15, 0, %0, c7, c5, 0\n" - " mcr p15, 0, %0, c7, c10, 4" +#endif : : "r" (0) : "cc"); +#ifdef CONFIG_ARM_ERRATA_411920 + v6_icache_inval_all(); +#endif } } diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S index c221e26ac1d..3397f1e64d7 100644 --- a/arch/arm/mm/proc-v7.S +++ b/arch/arm/mm/proc-v7.S @@ -96,6 +96,9 @@ ENTRY(cpu_v7_switch_mm) mov r2, #0 ldr r1, [r1, #MM_CONTEXT_ID] @ get mm->context.id orr r0, r0, #TTB_FLAGS +#ifdef CONFIG_ARM_ERRATA_430973 + mcr p15, 0, r2, c7, c5, 6 @ flush BTAC/BTB +#endif mcr p15, 0, r2, c13, c0, 1 @ set reserved context ID isb 1: mcr p15, 0, r0, c2, c0, 0 @ set TTB 0 @@ -181,6 +184,22 @@ __v7_setup: stmia r12, {r0-r5, r7, r9, r11, lr} bl v7_flush_dcache_all ldmia r12, {r0-r5, r7, r9, r11, lr} +#ifdef CONFIG_ARM_ERRATA_430973 + mrc p15, 0, r10, c1, c0, 1 @ read aux control register + orr r10, r10, #(1 << 6) @ set IBE to 1 + mcr p15, 0, r10, c1, c0, 1 @ write aux control register +#endif +#ifdef CONFIG_ARM_ERRATA_458693 + mrc p15, 0, r10, c1, c0, 1 @ read aux control register + orr r10, r10, #(1 << 5) @ set L1NEON to 1 + orr r10, r10, #(1 << 9) @ set PLDNOP to 1 + mcr p15, 0, r10, c1, c0, 1 @ write aux control register +#endif +#ifdef CONFIG_ARM_ERRATA_460075 + mrc p15, 1, r10, c9, c0, 2 @ read L2 cache aux ctrl register + orr r10, r10, #(1 << 22) @ set the Write Allocate disable bit + mcr p15, 1, r10, c9, c0, 2 @ write the L2 cache aux ctrl register +#endif mov r10, #0 #ifdef HARVARD_CACHE mcr p15, 0, r10, c7, c5, 0 @ I+BTB cache invalidate diff --git a/arch/arm/plat-mxc/dma-mx1-mx2.c b/arch/arm/plat-mxc/dma-mx1-mx2.c index e364a5ed10f..77646436c00 100644 --- a/arch/arm/plat-mxc/dma-mx1-mx2.c +++ b/arch/arm/plat-mxc/dma-mx1-mx2.c @@ -693,12 +693,15 @@ int imx_dma_request(int channel, const char *name) local_irq_restore(flags); return -EBUSY; } + memset(imxdma, 0, sizeof(imxdma)); + imxdma->name = name; + local_irq_restore(flags); /* request_irq() can block */ #ifdef CONFIG_ARCH_MX2 ret = request_irq(MXC_INT_DMACH0 + channel, dma_irq_handler, 0, "DMA", NULL); if (ret) { - local_irq_restore(flags); + imxdma->name = NULL; printk(KERN_CRIT "Can't register IRQ %d for DMA channel %d\n", MXC_INT_DMACH0 + channel, channel); return ret; @@ -708,13 +711,6 @@ int imx_dma_request(int channel, const char *name) imxdma->watchdog.data = channel; #endif - imxdma->name = name; - imxdma->irq_handler = NULL; - imxdma->err_handler = NULL; - imxdma->data = NULL; - imxdma->sg = NULL; - - local_irq_restore(flags); return ret; } EXPORT_SYMBOL(imx_dma_request); @@ -737,10 +733,7 @@ void imx_dma_free(int channel) local_irq_save(flags); /* Disable interrupts */ - __raw_writel(__raw_readl(DMA_BASE + DMA_DIMR) | (1 << channel), - DMA_BASE + DMA_DIMR); - __raw_writel(__raw_readl(DMA_BASE + DMA_CCR(channel)) & ~CCR_CEN, - DMA_BASE + DMA_CCR(channel)); + imx_dma_disable(channel); imxdma->name = NULL; #ifdef CONFIG_ARCH_MX2 diff --git a/arch/arm/plat-mxc/gpio.c b/arch/arm/plat-mxc/gpio.c index c6483bad8a2..89e95798cc3 100644 --- a/arch/arm/plat-mxc/gpio.c +++ b/arch/arm/plat-mxc/gpio.c @@ -124,7 +124,7 @@ static void mx3_gpio_irq_handler(u32 irq, struct irq_desc *desc) irq_stat = __raw_readl(port->base + GPIO_ISR) & __raw_readl(port->base + GPIO_IMR); - BUG_ON(!irq_stat); + mxc_gpio_irq_handler(port, irq_stat); } #endif diff --git a/arch/arm/plat-mxc/include/mach/board-mx27ads.h b/arch/arm/plat-mxc/include/mach/board-mx27ads.h index 1cac9d1135c..d42f4e6116f 100644 --- a/arch/arm/plat-mxc/include/mach/board-mx27ads.h +++ b/arch/arm/plat-mxc/include/mach/board-mx27ads.h @@ -47,7 +47,7 @@ /* * Base address of PBC controller, CS4 */ -#define PBC_BASE_ADDRESS 0xEB000000 +#define PBC_BASE_ADDRESS 0xf4300000 #define PBC_REG_ADDR(offset) (void __force __iomem *) \ (PBC_BASE_ADDRESS + (offset)) diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c index 2e0614552ac..29efc279287 100644 --- a/arch/arm/plat-omap/clock.c +++ b/arch/arm/plat-omap/clock.c @@ -239,6 +239,13 @@ void recalculate_root_clocks(void) } } +/** + * clk_init_one - initialize any fields in the struct clk before clk init + * @clk: struct clk * to initialize + * + * Initialize any struct clk fields needed before normal clk initialization + * can run. No return value. + */ void clk_init_one(struct clk *clk) { INIT_LIST_HEAD(&clk->children); diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c index 21cc0142b97..7fc8c045ad5 100644 --- a/arch/arm/plat-omap/dma.c +++ b/arch/arm/plat-omap/dma.c @@ -760,19 +760,12 @@ void omap_free_dma(int lch) { unsigned long flags; - spin_lock_irqsave(&dma_chan_lock, flags); if (dma_chan[lch].dev_id == -1) { pr_err("omap_dma: trying to free unallocated DMA channel %d\n", lch); - spin_unlock_irqrestore(&dma_chan_lock, flags); return; } - dma_chan[lch].dev_id = -1; - dma_chan[lch].next_lch = -1; - dma_chan[lch].callback = NULL; - spin_unlock_irqrestore(&dma_chan_lock, flags); - if (cpu_class_is_omap1()) { /* Disable all DMA interrupts for the channel. */ dma_write(0, CICR(lch)); @@ -798,6 +791,12 @@ void omap_free_dma(int lch) dma_write(0, CCR(lch)); omap_clear_dma(lch); } + + spin_lock_irqsave(&dma_chan_lock, flags); + dma_chan[lch].dev_id = -1; + dma_chan[lch].next_lch = -1; + dma_chan[lch].callback = NULL; + spin_unlock_irqrestore(&dma_chan_lock, flags); } EXPORT_SYMBOL(omap_free_dma); diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c index bfd47570cc9..55bb9963129 100644 --- a/arch/arm/plat-omap/dmtimer.c +++ b/arch/arm/plat-omap/dmtimer.c @@ -238,7 +238,7 @@ static struct omap_dm_timer omap3_dm_timers[] = { { .phys_base = 0x49040000, .irq = INT_24XX_GPTIMER9 }, { .phys_base = 0x48086000, .irq = INT_24XX_GPTIMER10 }, { .phys_base = 0x48088000, .irq = INT_24XX_GPTIMER11 }, - { .phys_base = 0x48304000, .irq = INT_24XX_GPTIMER12 }, + { .phys_base = 0x48304000, .irq = INT_34XX_GPT12_IRQ }, }; static const char *omap3_dm_source_names[] __initdata = { @@ -321,11 +321,9 @@ static void omap_dm_timer_reset(struct omap_dm_timer *timer) l |= 0x2 << 8; /* Set clock activity to perserve f-clock on idle */ /* - * Enable wake-up only for GPT1 on OMAP2 CPUs. - * FIXME: All timers should have wake-up enabled and clear - * PRCM status. + * Enable wake-up on OMAP2 CPUs. */ - if (cpu_class_is_omap2() && (timer == &dm_timers[0])) + if (cpu_class_is_omap2()) l |= 1 << 2; omap_dm_timer_write_reg(timer, OMAP_TIMER_OCP_CFG_REG, l); @@ -511,7 +509,7 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_stop); #ifdef CONFIG_ARCH_OMAP1 -void omap_dm_timer_set_source(struct omap_dm_timer *timer, int source) +int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source) { int n = (timer - dm_timers) << 1; u32 l; @@ -519,23 +517,31 @@ void omap_dm_timer_set_source(struct omap_dm_timer *timer, int source) l = omap_readl(MOD_CONF_CTRL_1) & ~(0x03 << n); l |= source << n; omap_writel(l, MOD_CONF_CTRL_1); + + return 0; } EXPORT_SYMBOL_GPL(omap_dm_timer_set_source); #else -void omap_dm_timer_set_source(struct omap_dm_timer *timer, int source) +int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source) { + int ret = -EINVAL; + if (source < 0 || source >= 3) - return; + return -EINVAL; clk_disable(timer->fclk); - clk_set_parent(timer->fclk, dm_source_clocks[source]); + ret = clk_set_parent(timer->fclk, dm_source_clocks[source]); clk_enable(timer->fclk); - /* When the functional clock disappears, too quick writes seem to - * cause an abort. */ + /* + * When the functional clock disappears, too quick writes seem + * to cause an abort. XXX Is this still necessary? + */ __delay(150000); + + return ret; } EXPORT_SYMBOL_GPL(omap_dm_timer_set_source); diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c index d3fa41e3d8c..17d7afe42b8 100644 --- a/arch/arm/plat-omap/gpio.c +++ b/arch/arm/plat-omap/gpio.c @@ -758,8 +758,12 @@ static void _clear_gpio_irqbank(struct gpio_bank *bank, int gpio_mask) /* Workaround for clearing DSP GPIO interrupts to allow retention */ #if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) + reg = bank->base + OMAP24XX_GPIO_IRQSTATUS2; if (cpu_is_omap24xx() || cpu_is_omap34xx()) - __raw_writel(gpio_mask, bank->base + OMAP24XX_GPIO_IRQSTATUS2); + __raw_writel(gpio_mask, reg); + + /* Flush posted write for the irq status to avoid spurious interrupts */ + __raw_readl(reg); #endif } @@ -921,13 +925,10 @@ static int _set_gpio_wakeup(struct gpio_bank *bank, int gpio, int enable) case METHOD_MPUIO: case METHOD_GPIO_1610: spin_lock_irqsave(&bank->lock, flags); - if (enable) { + if (enable) bank->suspend_wakeup |= (1 << gpio); - enable_irq_wake(bank->irq); - } else { - disable_irq_wake(bank->irq); + else bank->suspend_wakeup &= ~(1 << gpio); - } spin_unlock_irqrestore(&bank->lock, flags); return 0; #endif @@ -940,13 +941,10 @@ static int _set_gpio_wakeup(struct gpio_bank *bank, int gpio, int enable) return -EINVAL; } spin_lock_irqsave(&bank->lock, flags); - if (enable) { + if (enable) bank->suspend_wakeup |= (1 << gpio); - enable_irq_wake(bank->irq); - } else { - disable_irq_wake(bank->irq); + else bank->suspend_wakeup &= ~(1 << gpio); - } spin_unlock_irqrestore(&bank->lock, flags); return 0; #endif diff --git a/arch/arm/plat-omap/include/mach/dmtimer.h b/arch/arm/plat-omap/include/mach/dmtimer.h index 6dc70313821..20f1054c0a8 100644 --- a/arch/arm/plat-omap/include/mach/dmtimer.h +++ b/arch/arm/plat-omap/include/mach/dmtimer.h @@ -64,7 +64,7 @@ void omap_dm_timer_trigger(struct omap_dm_timer *timer); void omap_dm_timer_start(struct omap_dm_timer *timer); void omap_dm_timer_stop(struct omap_dm_timer *timer); -void omap_dm_timer_set_source(struct omap_dm_timer *timer, int source); +int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source); void omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload, unsigned int value); void omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload, unsigned int value); void omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable, unsigned int match); diff --git a/arch/arm/plat-omap/include/mach/eac.h b/arch/arm/plat-omap/include/mach/eac.h deleted file mode 100644 index 9e62cf03027..00000000000 --- a/arch/arm/plat-omap/include/mach/eac.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * arch/arm/plat-omap/include/mach2/eac.h - * - * Defines for Enhanced Audio Controller - * - * Contact: Jarkko Nikula <jarkko.nikula@nokia.com> - * - * Copyright (C) 2006 Nokia Corporation - * Copyright (C) 2004 Texas Instruments, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __ASM_ARM_ARCH_OMAP2_EAC_H -#define __ASM_ARM_ARCH_OMAP2_EAC_H - -#include <mach/io.h> -#include <mach/hardware.h> -#include <asm/irq.h> - -#include <sound/core.h> - -/* master codec clock source */ -#define EAC_MCLK_EXT_MASK 0x100 -enum eac_mclk_src { - EAC_MCLK_INT_11290000, /* internal 96 MHz / 8.5 = 11.29 Mhz */ - EAC_MCLK_EXT_11289600 = EAC_MCLK_EXT_MASK, - EAC_MCLK_EXT_12288000, - EAC_MCLK_EXT_2x11289600, - EAC_MCLK_EXT_2x12288000, -}; - -/* codec port interface mode */ -enum eac_codec_mode { - EAC_CODEC_PCM, - EAC_CODEC_AC97, - EAC_CODEC_I2S_MASTER, /* codec port, I.e. EAC is the master */ - EAC_CODEC_I2S_SLAVE, -}; - -/* configuration structure for I2S mode */ -struct eac_i2s_conf { - /* if enabled, then first data slot (left channel) is signaled as - * positive level of frame sync EAC.AC_FS */ - unsigned polarity_changed_mode:1; - /* if enabled, then serial data starts one clock cycle after the - * of EAC.AC_FS for first audio slot */ - unsigned sync_delay_enable:1; -}; - -/* configuration structure for EAC codec port */ -struct eac_codec { - enum eac_mclk_src mclk_src; - - enum eac_codec_mode codec_mode; - union { - struct eac_i2s_conf i2s; - } codec_conf; - - int default_rate; /* audio sampling rate */ - - int (* set_power)(void *private_data, int dac, int adc); - int (* register_controls)(void *private_data, - struct snd_card *card); - const char *short_name; - - void *private_data; -}; - -/* structure for passing platform dependent data to the EAC driver */ -struct eac_platform_data { - int (* init)(struct device *eac_dev); - void (* cleanup)(struct device *eac_dev); - /* these callbacks are used to configure & control external MCLK - * source. NULL if not used */ - int (* enable_ext_clocks)(struct device *eac_dev); - void (* disable_ext_clocks)(struct device *eac_dev); -}; - -extern void omap_init_eac(struct eac_platform_data *pdata); - -extern int eac_register_codec(struct device *eac_dev, struct eac_codec *codec); -extern void eac_unregister_codec(struct device *eac_dev); - -extern int eac_set_mode(struct device *eac_dev, int play, int rec); - -#endif /* __ASM_ARM_ARCH_OMAP2_EAC_H */ diff --git a/arch/arm/plat-omap/include/mach/gpioexpander.h b/arch/arm/plat-omap/include/mach/gpioexpander.h deleted file mode 100644 index 90444a0d6b1..00000000000 --- a/arch/arm/plat-omap/include/mach/gpioexpander.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * arch/arm/plat-omap/include/mach/gpioexpander.h - * - * - * Copyright (C) 2004 Texas Instruments, Inc. - * - * This package 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 PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - */ - -#ifndef __ASM_ARCH_OMAP_GPIOEXPANDER_H -#define __ASM_ARCH_OMAP_GPIOEXPANDER_H - -/* Function Prototypes for GPIO Expander functions */ - -#ifdef CONFIG_GPIOEXPANDER_OMAP -int read_gpio_expa(u8 *, int); -int write_gpio_expa(u8 , int); -#else -static inline int read_gpio_expa(u8 *val, int addr) -{ - return 0; -} -static inline int write_gpio_expa(u8 val, int addr) -{ - return 0; -} -#endif - -#endif /* __ASM_ARCH_OMAP_GPIOEXPANDER_H */ diff --git a/arch/arm/plat-omap/include/mach/irda.h b/arch/arm/plat-omap/include/mach/irda.h index 8372a00d8e0..40f60339d1c 100644 --- a/arch/arm/plat-omap/include/mach/irda.h +++ b/arch/arm/plat-omap/include/mach/irda.h @@ -21,10 +21,6 @@ struct omap_irda_config { int transceiver_cap; int (*transceiver_mode)(struct device *dev, int mode); int (*select_irda)(struct device *dev, int state); - /* Very specific to the needs of some platforms (h3,h4) - * having calls which can sleep in irda_set_speed. - */ - struct delayed_work gpio_expa; int rx_channel; int tx_channel; unsigned long dest_start; diff --git a/arch/arm/plat-omap/include/mach/mmc.h b/arch/arm/plat-omap/include/mach/mmc.h index 4435bd434e1..81d5b36534b 100644 --- a/arch/arm/plat-omap/include/mach/mmc.h +++ b/arch/arm/plat-omap/include/mach/mmc.h @@ -79,7 +79,6 @@ struct omap_mmc_platform_data { /* use the internal clock */ unsigned internal_clock:1; - s16 power_pin; int switch_pin; /* gpio (card detect) */ int gpio_wp; /* gpio (write protect) */ diff --git a/arch/arm/plat-omap/include/mach/timer-gp.h b/arch/arm/plat-omap/include/mach/timer-gp.h new file mode 100644 index 00000000000..c88d346b59d --- /dev/null +++ b/arch/arm/plat-omap/include/mach/timer-gp.h @@ -0,0 +1,17 @@ +/* + * OMAP2/3 GPTIMER support.headers + * + * Copyright (C) 2009 Nokia Corporation + * + * 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. + */ + +#ifndef __ARCH_ARM_PLAT_OMAP_INCLUDE_MACH_TIMER_GP_H +#define __ARCH_ARM_PLAT_OMAP_INCLUDE_MACH_TIMER_GP_H + +int __init omap2_gp_clockevent_set_gptimer(u8 id); + +#endif + diff --git a/arch/arm/plat-pxa/gpio.c b/arch/arm/plat-pxa/gpio.c index af819bf21b6..abc79d44aca 100644 --- a/arch/arm/plat-pxa/gpio.c +++ b/arch/arm/plat-pxa/gpio.c @@ -121,6 +121,8 @@ static int __init pxa_init_gpio_chip(int gpio_end) return -ENOMEM; } + memset(chips, 0, nbanks * sizeof(struct pxa_gpio_chip)); + for (i = 0, gpio = 0; i < nbanks; i++, gpio += 32) { struct gpio_chip *c = &chips[i].chip; @@ -143,6 +145,21 @@ static int __init pxa_init_gpio_chip(int gpio_end) return 0; } +/* Update only those GRERx and GFERx edge detection register bits if those + * bits are set in c->irq_mask + */ +static inline void update_edge_detect(struct pxa_gpio_chip *c) +{ + uint32_t grer, gfer; + + grer = __raw_readl(c->regbase + GRER_OFFSET) & ~c->irq_mask; + gfer = __raw_readl(c->regbase + GFER_OFFSET) & ~c->irq_mask; + grer |= c->irq_edge_rise & c->irq_mask; + gfer |= c->irq_edge_fall & c->irq_mask; + __raw_writel(grer, c->regbase + GRER_OFFSET); + __raw_writel(gfer, c->regbase + GFER_OFFSET); +} + static int pxa_gpio_irq_type(unsigned int irq, unsigned int type) { struct pxa_gpio_chip *c; @@ -181,8 +198,7 @@ static int pxa_gpio_irq_type(unsigned int irq, unsigned int type) else c->irq_edge_fall &= ~mask; - __raw_writel(c->irq_edge_rise & c->irq_mask, c->regbase + GRER_OFFSET); - __raw_writel(c->irq_edge_fall & c->irq_mask, c->regbase + GFER_OFFSET); + update_edge_detect(c); pr_debug("%s: IRQ%d (GPIO%d) - edge%s%s\n", __func__, irq, gpio, ((type & IRQ_TYPE_EDGE_RISING) ? " rising" : ""), @@ -244,8 +260,7 @@ static void pxa_unmask_muxed_gpio(unsigned int irq) struct pxa_gpio_chip *c = gpio_to_chip(gpio); c->irq_mask |= GPIO_bit(gpio); - __raw_writel(c->irq_edge_rise & c->irq_mask, c->regbase + GRER_OFFSET); - __raw_writel(c->irq_edge_fall & c->irq_mask, c->regbase + GFER_OFFSET); + update_edge_detect(c); } static struct irq_chip pxa_muxed_gpio_chip = { diff --git a/arch/avr32/Makefile b/arch/avr32/Makefile index 0b97e14f73f..c21a3290d54 100644 --- a/arch/avr32/Makefile +++ b/arch/avr32/Makefile @@ -43,8 +43,6 @@ core-y += arch/avr32/mm/ drivers-$(CONFIG_OPROFILE) += arch/avr32/oprofile/ libs-y += arch/avr32/lib/ -CLEAN_FILES += include/asm-avr32/.arch include/asm-avr32/arch - BOOT_TARGETS := vmlinux.elf vmlinux.bin uImage uImage.srec .PHONY: $(BOOT_TARGETS) install diff --git a/arch/cris/Makefile b/arch/cris/Makefile index 3662cfb7b61..71e17d3eedd 100644 --- a/arch/cris/Makefile +++ b/arch/cris/Makefile @@ -70,7 +70,7 @@ SRC_ARCH = $(srctree)/arch/cris # cris object files path OBJ_ARCH = $(objtree)/arch/cris -boot := arch/cris/$(SARCH)/boot +boot := arch/cris/boot MACHINE := arch/cris/$(SARCH) all: zImage @@ -81,15 +81,15 @@ zImage Image: vmlinux archprepare: archclean: - $(Q)if [ -e arch/cris/$(SARCH)/boot ]; then \ - $(MAKE) $(clean)=arch/cris/$(SARCH)/boot; \ + $(Q)if [ -e arch/cris/boot ]; then \ + $(MAKE) $(clean)=arch/cris/boot; \ fi CLEAN_FILES += \ - $(MACHINE)/boot/zImage \ - $(MACHINE)/boot/compressed/decompress.bin \ - $(MACHINE)/boot/compressed/piggy.gz \ - $(MACHINE)/boot/rescue/rescue.bin + $(boot)/zImage \ + $(boot)/compressed/decompress.bin \ + $(boot)/compressed/piggy.gz \ + $(boot)/rescue/rescue.bin # MRPROPER_FILES += diff --git a/arch/cris/arch-v10/boot/compressed/README b/arch/cris/arch-v10/boot/compressed/README deleted file mode 100644 index 48b3db9924b..00000000000 --- a/arch/cris/arch-v10/boot/compressed/README +++ /dev/null @@ -1,25 +0,0 @@ -Creation of the self-extracting compressed kernel image (vmlinuz) ------------------------------------------------------------------ -$Id: README,v 1.1 2001/12/17 13:59:27 bjornw Exp $ - -This can be slightly confusing because it's a process with many steps. - -The kernel object built by the arch/etrax100/Makefile, vmlinux, is split -by that makefile into text and data binary files, vmlinux.text and -vmlinux.data. - -Those files together with a ROM filesystem can be catted together and -burned into a flash or executed directly at the DRAM origin. - -They can also be catted together and compressed with gzip, which is what -happens in this makefile. Together they make up piggy.img. - -The decompressor is built into the file decompress.o. It is turned into -the binary file decompress.bin, which is catted together with piggy.img -into the file vmlinuz. It can be executed in an arbitrary place in flash. - -Be careful - it assumes some things about free locations in DRAM. It -assumes the DRAM starts at 0x40000000 and that it is at least 8 MB, -so it puts its code at 0x40700000, and initial stack at 0x40800000. - --Bjorn diff --git a/arch/cris/arch-v10/boot/compressed/misc.c b/arch/cris/arch-v10/boot/compressed/misc.c deleted file mode 100644 index a4db1507d3b..00000000000 --- a/arch/cris/arch-v10/boot/compressed/misc.c +++ /dev/null @@ -1,246 +0,0 @@ -/* - * misc.c - * - * This is a collection of several routines from gzip-1.0.3 - * adapted for Linux. - * - * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994 - * puts by Nick Holloway 1993, better puts by Martin Mares 1995 - * adaptation for Linux/CRIS Axis Communications AB, 1999 - * - */ - -/* where the piggybacked kernel image expects itself to live. - * it is the same address we use when we network load an uncompressed - * image into DRAM, and it is the address the kernel is linked to live - * at by vmlinux.lds.S - */ - -#define KERNEL_LOAD_ADR 0x40004000 - - -#include <linux/types.h> -#include <arch/svinto.h> - -/* - * gzip declarations - */ - -#define OF(args) args -#define STATIC static - -void *memset(void *s, int c, size_t n); -void *memcpy(void *__dest, __const void *__src, size_t __n); - -#define memzero(s, n) memset((s), 0, (n)) - -typedef unsigned char uch; -typedef unsigned short ush; -typedef unsigned long ulg; - -#define WSIZE 0x8000 /* Window size must be at least 32k, */ - /* and a power of two */ - -static uch *inbuf; /* input buffer */ -static uch window[WSIZE]; /* Sliding window buffer */ - -unsigned inptr = 0; /* index of next byte to be processed in inbuf - * After decompression it will contain the - * compressed size, and head.S will read it. - */ - -static unsigned outcnt = 0; /* bytes in output buffer */ - -/* gzip flag byte */ -#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ -#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */ -#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ -#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ -#define COMMENT 0x10 /* bit 4 set: file comment present */ -#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */ -#define RESERVED 0xC0 /* bit 6,7: reserved */ - -#define get_byte() (inbuf[inptr++]) - -/* Diagnostic functions */ -#ifdef DEBUG -# define Assert(cond, msg) do { \ - if (!(cond)) \ - error(msg); \ - } while (0) -# define Trace(x) fprintf x -# define Tracev(x) do { \ - if (verbose) \ - fprintf x; \ - } while (0) -# define Tracevv(x) do { \ - if (verbose > 1) \ - fprintf x; \ - } while (0) -# define Tracec(c, x) do { \ - if (verbose && (c)) \ - fprintf x; \ - } while (0) -# define Tracecv(c, x) do { \ - if (verbose > 1 && (c)) \ - fprintf x; \ - } while (0) -#else -# define Assert(cond, msg) -# define Trace(x) -# define Tracev(x) -# define Tracevv(x) -# define Tracec(c, x) -# define Tracecv(c, x) -#endif - -static void flush_window(void); -static void error(char *m); - -extern char *input_data; /* lives in head.S */ - -static long bytes_out = 0; -static uch *output_data; -static unsigned long output_ptr = 0; -static void puts(const char *); - -/* the "heap" is put directly after the BSS ends, at end */ - -extern int _end; -static long free_mem_ptr = (long)&_end; -static long free_mem_end_ptr; - -#include "../../../../../lib/inflate.c" - -/* decompressor info and error messages to serial console */ - -static void -puts(const char *s) -{ -#ifndef CONFIG_ETRAX_DEBUG_PORT_NULL - while (*s) { -#ifdef CONFIG_ETRAX_DEBUG_PORT0 - while (!(*R_SERIAL0_STATUS & (1 << 5))) ; - *R_SERIAL0_TR_DATA = *s++; -#endif -#ifdef CONFIG_ETRAX_DEBUG_PORT1 - while (!(*R_SERIAL1_STATUS & (1 << 5))) ; - *R_SERIAL1_TR_DATA = *s++; -#endif -#ifdef CONFIG_ETRAX_DEBUG_PORT2 - while (!(*R_SERIAL2_STATUS & (1 << 5))) ; - *R_SERIAL2_TR_DATA = *s++; -#endif -#ifdef CONFIG_ETRAX_DEBUG_PORT3 - while (!(*R_SERIAL3_STATUS & (1 << 5))) ; - *R_SERIAL3_TR_DATA = *s++; -#endif - } -#endif -} - -void *memset(void *s, int c, size_t n) -{ - int i; - char *ss = (char *)s; - - for (i = 0; i < n; i++) - ss[i] = c; - - return s; -} - -void *memcpy(void *__dest, __const void *__src, size_t __n) -{ - int i; - char *d = (char *)__dest, *s = (char *)__src; - - for (i = 0; i < __n; i++) - d[i] = s[i]; - - return __dest; -} - -/* =========================================================================== - * Write the output window window[0..outcnt-1] and update crc and bytes_out. - * (Used for the decompressed data only.) - */ - -static void flush_window(void) -{ - ulg c = crc; /* temporary variable */ - unsigned n; - uch *in, *out, ch; - - in = window; - out = &output_data[output_ptr]; - for (n = 0; n < outcnt; n++) { - ch = *out = *in; - out++; - in++; - c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8); - } - crc = c; - bytes_out += (ulg)outcnt; - output_ptr += (ulg)outcnt; - outcnt = 0; -} - -static void error(char *x) -{ - puts("\n\n"); - puts(x); - puts("\n\n -- System halted\n"); - - while (1); /* Halt */ -} - -void setup_normal_output_buffer(void) -{ - output_data = (char *)KERNEL_LOAD_ADR; -} - -void decompress_kernel(void) -{ - char revision; - - /* input_data is set in head.S */ - inbuf = input_data; - -#ifdef CONFIG_ETRAX_DEBUG_PORT0 - *R_SERIAL0_XOFF = 0; - *R_SERIAL0_BAUD = 0x99; - *R_SERIAL0_TR_CTRL = 0x40; -#endif -#ifdef CONFIG_ETRAX_DEBUG_PORT1 - *R_SERIAL1_XOFF = 0; - *R_SERIAL1_BAUD = 0x99; - *R_SERIAL1_TR_CTRL = 0x40; -#endif -#ifdef CONFIG_ETRAX_DEBUG_PORT2 - *R_GEN_CONFIG = 0x08; - *R_SERIAL2_XOFF = 0; - *R_SERIAL2_BAUD = 0x99; - *R_SERIAL2_TR_CTRL = 0x40; -#endif -#ifdef CONFIG_ETRAX_DEBUG_PORT3 - *R_GEN_CONFIG = 0x100; - *R_SERIAL3_XOFF = 0; - *R_SERIAL3_BAUD = 0x99; - *R_SERIAL3_TR_CTRL = 0x40; -#endif - - setup_normal_output_buffer(); - - makecrc(); - - __asm__ volatile ("move $vr,%0" : "=rm" (revision)); - if (revision < 10) { - puts("You need an ETRAX 100LX to run linux 2.6\n"); - while (1); - } - - puts("Uncompressing Linux...\n"); - gunzip(); - puts("Done. Now booting the kernel.\n"); -} diff --git a/arch/cris/arch-v10/kernel/entry.S b/arch/cris/arch-v10/kernel/entry.S index 72f5cd319b9..2c18d08cd91 100644 --- a/arch/cris/arch-v10/kernel/entry.S +++ b/arch/cris/arch-v10/kernel/entry.S @@ -536,10 +536,10 @@ multiple_interrupt: movem $r13, [$sp] push $r10 ; push orig_r10 clear.d [$sp=$sp-4] ; frametype == 0, normal frame - + move.d $sp, $r10 jsr do_multiple_IRQ - + jump ret_from_intr do_sigtrap: @@ -585,7 +585,7 @@ _ugdb_handle_breakpoint: pop $r0 ; Restore r0. ba do_sigtrap ; SIGTRAP the offending process. pop $dccr ; Restore dccr in delay slot. - + .global kernel_execve kernel_execve: move.d __NR_execve, $r9 @@ -929,6 +929,14 @@ sys_call_table: .long sys_fallocate .long sys_timerfd_settime /* 325 */ .long sys_timerfd_gettime + .long sys_signalfd4 + .long sys_eventfd2 + .long sys_epoll_create1 + .long sys_dup3 /* 330 */ + .long sys_pipe2 + .long sys_inotify_init1 + .long sys_preadv + .long sys_pwritev /* * NOTE!! This doesn't have to be exact - we just have diff --git a/arch/cris/arch-v32/boot/Makefile b/arch/cris/arch-v32/boot/Makefile deleted file mode 100644 index 99896ad60b3..00000000000 --- a/arch/cris/arch-v32/boot/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -# -# arch/cris/arch-v32/boot/Makefile -# - -OBJCOPYFLAGS = -O binary -R .note -R .comment - -subdir- := compressed rescue -targets := Image - -$(obj)/Image: vmlinux FORCE - $(call if_changed,objcopy) - @echo ' Kernel: $@ is ready' - -$(obj)/compressed/vmlinux: $(obj)/Image FORCE - $(Q)$(MAKE) $(build)=$(obj)/compressed $@ - $(Q)$(MAKE) $(build)=$(obj)/rescue $(obj)/rescue/rescue.bin - -$(obj)/zImage: $(obj)/compressed/vmlinux - @cp $< $@ - @echo ' Kernel: $@ is ready' diff --git a/arch/cris/arch-v32/boot/compressed/Makefile b/arch/cris/arch-v32/boot/compressed/Makefile deleted file mode 100644 index e176b8b69d9..00000000000 --- a/arch/cris/arch-v32/boot/compressed/Makefile +++ /dev/null @@ -1,26 +0,0 @@ -# -# arch/cris/arch-v32/boot/compressed/Makefile -# - -asflags-y += -I$(srctree)/include/asm/mach/ -I$(srctree)/include/asm/arch -ccflags-y += -O2 -I$(srctree)/include/asm/mach/ -I$(srctree)/include/asm/arch -ldflags-y += -T$(srctree)/$(src)/decompress.lds -OBJECTS = $(obj)/head.o $(obj)/misc.o -OBJCOPYFLAGS = -O binary --remove-section=.bss - -quiet_cmd_image = BUILD $@ -cmd_image = cat $(obj)/decompress.bin $(obj)/piggy.gz > $@ - -targets := vmlinux piggy.gz decompress.o decompress.bin - -$(obj)/decompress.o: $(OBJECTS) FORCE - $(call if_changed,ld) - -$(obj)/decompress.bin: $(obj)/decompress.o FORCE - $(call if_changed,objcopy) - -$(obj)/vmlinux: $(obj)/piggy.gz $(obj)/decompress.bin FORCE - $(call if_changed,image) - -$(obj)/piggy.gz: $(obj)/../Image FORCE - $(call if_changed,gzip) diff --git a/arch/cris/arch-v32/boot/rescue/Makefile b/arch/cris/arch-v32/boot/rescue/Makefile deleted file mode 100644 index 566aac663a3..00000000000 --- a/arch/cris/arch-v32/boot/rescue/Makefile +++ /dev/null @@ -1,26 +0,0 @@ -# -# Makefile for rescue (bootstrap) code -# - -CC = gcc-cris -mlinux -march=v32 $(LINUXINCLUDE) -ccflags-y += -O2 -I $(srctree)/include/asm/arch/mach/ \ - -I $(srctree)/include/asm/arch -asflags-y += -I $(srctree)/include/asm/arch/mach/ -I $(srctree)/include/asm/arch -LD = gcc-cris -mlinux -march=v32 -nostdlib -ldflags-y += -T $(srctree)/$(src)/rescue.lds -LDPOSTFLAGS = -lgcc -OBJCOPYFLAGS = -O binary --remove-section=.bss -obj-$(CONFIG_ETRAX_AXISFLASHMAP) = head.o -OBJECT := $(obj)/head.o - -targets := rescue.o rescue.bin - -quiet_cmd_ldlibgcc = LD $@ -cmd_ldlibgcc = $(LD) $(LDFLAGS) $(filter-out FORCE,$^) $(LDPOSTFLAGS) -o $@ - -$(obj)/rescue.o: $(OBJECTS) FORCE - $(call if_changed,ldlibgcc) - -$(obj)/rescue.bin: $(obj)/rescue.o FORCE - $(call if_changed,objcopy) - cp -p $(obj)/rescue.bin $(objtree) diff --git a/arch/cris/arch-v32/drivers/mach-a3/gpio.c b/arch/cris/arch-v32/drivers/mach-a3/gpio.c index 7a87bc0ae2e..97357cfd17b 100644 --- a/arch/cris/arch-v32/drivers/mach-a3/gpio.c +++ b/arch/cris/arch-v32/drivers/mach-a3/gpio.c @@ -681,7 +681,7 @@ static int virtual_gpio_ioctl(struct file *file, unsigned int cmd, shadow |= ~readl(dir_oe[priv->minor]) | (arg & changeable_bits[priv->minor]); i2c_write(VIRT_I2C_ADDR, (void *)&shadow, sizeof(shadow)); - spin_lock_irqrestore(&gpio_lock, flags); + spin_unlock_irqrestore(&gpio_lock, flags); break; case IO_CLRBITS: spin_lock_irqsave(&gpio_lock, flags); @@ -690,7 +690,7 @@ static int virtual_gpio_ioctl(struct file *file, unsigned int cmd, shadow |= ~readl(dir_oe[priv->minor]) & ~(arg & changeable_bits[priv->minor]); i2c_write(VIRT_I2C_ADDR, (void *)&shadow, sizeof(shadow)); - spin_lock_irqrestore(&gpio_lock, flags); + spin_unlock_irqrestore(&gpio_lock, flags); break; case IO_HIGHALARM: /* Set alarm when bits with 1 in arg go high. */ diff --git a/arch/cris/arch-v32/kernel/Makefile b/arch/cris/arch-v32/kernel/Makefile index 993d987b007..40358355d0c 100644 --- a/arch/cris/arch-v32/kernel/Makefile +++ b/arch/cris/arch-v32/kernel/Makefile @@ -9,8 +9,6 @@ obj-y := entry.o traps.o irq.o debugport.o \ process.o ptrace.o setup.o signal.o traps.o time.o \ cache.o cacheflush.o -obj-$(CONFIG_ETRAXFS_SIM) += vcs_hook.o - obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_ETRAX_KGDB) += kgdb.o kgdb_asm.o obj-$(CONFIG_ETRAX_FAST_TIMER) += fasttimer.o diff --git a/arch/cris/arch-v32/kernel/entry.S b/arch/cris/arch-v32/kernel/entry.S index 5e674c8f7c5..435b9671bd4 100644 --- a/arch/cris/arch-v32/kernel/entry.S +++ b/arch/cris/arch-v32/kernel/entry.S @@ -852,6 +852,14 @@ sys_call_table: .long sys_fallocate .long sys_timerfd_settime /* 325 */ .long sys_timerfd_gettime + .long sys_signalfd4 + .long sys_eventfd2 + .long sys_epoll_create1 + .long sys_dup3 /* 330 */ + .long sys_pipe2 + .long sys_inotify_init1 + .long sys_preadv + .long sys_pwritev /* * NOTE!! This doesn't have to be exact - we just have diff --git a/arch/cris/arch-v10/boot/.gitignore b/arch/cris/boot/.gitignore index 171a0853caf..171a0853caf 100644 --- a/arch/cris/arch-v10/boot/.gitignore +++ b/arch/cris/boot/.gitignore diff --git a/arch/cris/arch-v10/boot/Makefile b/arch/cris/boot/Makefile index 21720301443..144f3afa011 100644 --- a/arch/cris/arch-v10/boot/Makefile +++ b/arch/cris/boot/Makefile @@ -1,8 +1,12 @@ # -# arch/cris/arch-v10/boot/Makefile +# arch/cris/boot/Makefile # -OBJCOPYFLAGS = -O binary --remove-section=.bss +objcopyflags-$(CONFIG_ETRAX_ARCH_V10) += -R .note -R .comment +objcopyflags-$(CONFIG_ETRAX_ARCH_V32) += --remove-section=.bss + +OBJCOPYFLAGS = -O binary $(objcopyflags-y) + subdir- := compressed rescue targets := Image diff --git a/arch/cris/arch-v10/boot/compressed/Makefile b/arch/cris/boot/compressed/Makefile index 6fe0ffaf3be..8fe9338c177 100644 --- a/arch/cris/arch-v10/boot/compressed/Makefile +++ b/arch/cris/boot/compressed/Makefile @@ -1,11 +1,23 @@ # -# arch/cris/arch-v10/boot/compressed/Makefile +# arch/cris/boot/compressed/Makefile # asflags-y += $(LINUXINCLUDE) ccflags-y += -O2 $(LINUXINCLUDE) -ldflags-y += -T $(srctree)/$(src)/decompress.lds -OBJECTS = $(obj)/head.o $(obj)/misc.o + +# asflags-$(CONFIG_ETRAX_ARCH_V32) += -I$(srctree)/include/asm/mach \ +# -I$(srctree)/include/asm/arch +# ccflags-$(CONFIG_ETRAX_ARCH_V32) += -O2 -I$(srctree)/include/asm/mach +# -I$(srctree)/include/asm/arch + +arch-$(CONFIG_ETRAX_ARCH_V10) = v10 +arch-$(CONFIG_ETRAX_ARCH_V32) = v32 + +ldflags-y += -T $(srctree)/$(src)/decompress_$(arch-y).lds + +OBJECTS-$(CONFIG_ETRAX_ARCH_V32) = $(obj)/head_v32.o +OBJECTS-$(CONFIG_ETRAX_ARCH_V10) = $(obj)/head_v10.o +OBJECTS= $(OBJECTS-y) $(obj)/misc.o OBJCOPYFLAGS = -O binary --remove-section=.bss quiet_cmd_image = BUILD $@ @@ -24,4 +36,3 @@ $(obj)/vmlinux: $(obj)/piggy.gz $(obj)/decompress.bin FORCE $(obj)/piggy.gz: $(obj)/../Image FORCE $(call if_changed,gzip) - diff --git a/arch/cris/arch-v32/boot/compressed/README b/arch/cris/boot/compressed/README index 182c5d75784..182c5d75784 100644 --- a/arch/cris/arch-v32/boot/compressed/README +++ b/arch/cris/boot/compressed/README diff --git a/arch/cris/arch-v10/boot/compressed/decompress.lds b/arch/cris/boot/compressed/decompress_v10.lds index e80f4594d54..e80f4594d54 100644 --- a/arch/cris/arch-v10/boot/compressed/decompress.lds +++ b/arch/cris/boot/compressed/decompress_v10.lds diff --git a/arch/cris/arch-v32/boot/compressed/decompress.lds b/arch/cris/boot/compressed/decompress_v32.lds index 3c837feca3a..3c837feca3a 100644 --- a/arch/cris/arch-v32/boot/compressed/decompress.lds +++ b/arch/cris/boot/compressed/decompress_v32.lds diff --git a/arch/cris/arch-v10/boot/compressed/head.S b/arch/cris/boot/compressed/head_v10.S index 0bb4dcc2925..9edb8ade7e1 100644 --- a/arch/cris/arch-v10/boot/compressed/head.S +++ b/arch/cris/boot/compressed/head_v10.S @@ -30,7 +30,7 @@ beq dram_init_finished nop -#include "../../lib/dram_init.S" +#include "../../arch-v10/lib/dram_init.S" dram_init_finished: @@ -123,4 +123,4 @@ _cmd_line_magic: .dword 0 _cmd_line_addr: .dword 0 -#include "../../lib/hw_settings.S" +#include "../../arch-v10/lib/hw_settings.S" diff --git a/arch/cris/arch-v32/boot/compressed/head.S b/arch/cris/boot/compressed/head_v32.S index a4a65c5c669..f483005f3d4 100644 --- a/arch/cris/arch-v32/boot/compressed/head.S +++ b/arch/cris/boot/compressed/head_v32.S @@ -17,7 +17,7 @@ .globl input_data .text -_start: +start: di ;; Start clocks for used blocks. @@ -29,9 +29,9 @@ _start: nop #if defined CONFIG_ETRAXFS -#include "../../mach-fs/dram_init.S" +#include "../../arch-v32/mach-fs/dram_init.S" #elif defined CONFIG_CRIS_MACH_ARTPEC3 -#include "../../mach-a3/dram_init.S" +#include "../../arch-v32/mach-a3/dram_init.S" #else #error Only ETRAXFS and ARTPEC-3 supported! #endif @@ -137,9 +137,9 @@ _boot_source: .dword 0 #if defined CONFIG_ETRAXFS -#include "../../mach-fs/hw_settings.S" +#include "../../arch-v32/mach-fs/hw_settings.S" #elif defined CONFIG_CRIS_MACH_ARTPEC3 -#include "../../mach-a3/hw_settings.S" +#include "../../arch-v32/mach-a3/hw_settings.S" #else #error Only ETRAXFS and ARTPEC-3 supported! #endif diff --git a/arch/cris/arch-v32/boot/compressed/misc.c b/arch/cris/boot/compressed/misc.c index 3595e16e82b..47bc190ba6d 100644 --- a/arch/cris/arch-v32/boot/compressed/misc.c +++ b/arch/cris/boot/compressed/misc.c @@ -18,8 +18,9 @@ #define KERNEL_LOAD_ADR 0x40004000 - #include <linux/types.h> + +#ifdef CONFIG_ETRAX_ARCH_V32 #include <hwregs/reg_rdwr.h> #include <hwregs/reg_map.h> #include <hwregs/ser_defs.h> @@ -27,6 +28,9 @@ #ifdef CONFIG_CRIS_MACH_ARTPEC3 #include <hwregs/clkgen_defs.h> #endif +#else +#include <arch/svinto.h> +#endif /* * gzip declarations @@ -35,12 +39,10 @@ #define OF(args) args #define STATIC static -void* memset(void* s, int c, size_t n); -void* memcpy(void* __dest, __const void* __src, - size_t __n); - -#define memzero(s, n) memset ((s), 0, (n)) +void *memset(void *s, int c, size_t n); +void *memcpy(void *__dest, __const void *__src, size_t __n); +#define memzero(s, n) memset((s), 0, (n)) typedef unsigned char uch; typedef unsigned short ush; @@ -68,27 +70,43 @@ static unsigned outcnt = 0; /* bytes in output buffer */ #define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */ #define RESERVED 0xC0 /* bit 6,7: reserved */ -#define get_byte() inbuf[inptr++] +#define get_byte() (inbuf[inptr++]) /* Diagnostic functions */ #ifdef DEBUG -# define Assert(cond,msg) {if(!(cond)) error(msg);} +# define Assert(cond, msg) do { \ + if (!(cond)) \ + error(msg); \ + } while (0) # define Trace(x) fprintf x -# define Tracev(x) {if (verbose) fprintf x ;} -# define Tracevv(x) {if (verbose>1) fprintf x ;} -# define Tracec(c,x) {if (verbose && (c)) fprintf x ;} -# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;} +# define Tracev(x) do { \ + if (verbose) \ + fprintf x; \ + } while (0) +# define Tracevv(x) do { \ + if (verbose > 1) \ + fprintf x; \ + } while (0) +# define Tracec(c, x) do { \ + if (verbose && (c)) \ + fprintf x; \ + } while (0) +# define Tracecv(c, x) do { \ + if (verbose > 1 && (c)) \ + fprintf x; \ + } while (0) #else -# define Assert(cond,msg) +# define Assert(cond, msg) # define Trace(x) # define Tracev(x) # define Tracevv(x) -# define Tracec(c,x) -# define Tracecv(c,x) +# define Tracec(c, x) +# define Tracecv(c, x) #endif static void flush_window(void); static void error(char *m); +static void puts(const char *); extern char *input_data; /* lives in head.S */ @@ -96,10 +114,6 @@ static long bytes_out; static uch *output_data; static unsigned long output_ptr; -static void error(char *m); - -static void puts(const char *); - /* the "heap" is put directly after the BSS ends, at end */ extern int _end; @@ -110,8 +124,8 @@ static long free_mem_end_ptr; /* decompressor info and error messages to serial console */ -static inline void -serout(const char *s, reg_scope_instances regi_ser) +#ifdef CONFIG_ETRAX_ARCH_V32 +static inline void serout(const char *s, reg_scope_instances regi_ser) { reg_ser_rs_stat_din rs; reg_ser_rw_dout dout = {.data = *s}; @@ -123,23 +137,47 @@ serout(const char *s, reg_scope_instances regi_ser) REG_WR(ser, regi_ser, rw_dout, dout); } +#endif -static void -puts(const char *s) +static void puts(const char *s) { #ifndef CONFIG_ETRAX_DEBUG_PORT_NULL while (*s) { #ifdef CONFIG_ETRAX_DEBUG_PORT0 +#ifdef CONFIG_ETRAX_ARCH_V32 serout(s, regi_ser0); +#else + while (!(*R_SERIAL0_STATUS & (1 << 5))) + ; + *R_SERIAL0_TR_DATA = *s++; +#endif #endif #ifdef CONFIG_ETRAX_DEBUG_PORT1 +#ifdef CONFIG_ETRAX_ARCH_V32 serout(s, regi_ser1); +#else + while (!(*R_SERIAL1_STATUS & (1 << 5))) + ; + *R_SERIAL1_TR_DATA = *s++; +#endif #endif #ifdef CONFIG_ETRAX_DEBUG_PORT2 +#ifdef CONFIG_ETRAX_ARCH_V32 serout(s, regi_ser2); +#else + while (!(*R_SERIAL2_STATUS & (1 << 5))) + ; + *R_SERIAL2_TR_DATA = *s++; +#endif #endif #ifdef CONFIG_ETRAX_DEBUG_PORT3 +#ifdef CONFIG_ETRAX_ARCH_V32 serout(s, regi_ser3); +#else + while (!(*R_SERIAL3_STATUS & (1 << 5))) + ; + *R_SERIAL3_TR_DATA = *s++; +#endif #endif *s++; } @@ -147,8 +185,7 @@ puts(const char *s) #endif } -void* -memset(void* s, int c, size_t n) +void *memset(void *s, int c, size_t n) { int i; char *ss = (char*)s; @@ -158,14 +195,13 @@ memset(void* s, int c, size_t n) return s; } -void* -memcpy(void* __dest, __const void* __src, - size_t __n) +void *memcpy(void *__dest, __const void *__src, size_t __n) { int i; char *d = (char *)__dest, *s = (char *)__src; - for (i=0;i<__n;i++) d[i] = s[i]; + for (i = 0; i < __n; i++) + d[i] = s[i]; return __dest; } @@ -175,43 +211,42 @@ memcpy(void* __dest, __const void* __src, * (Used for the decompressed data only.) */ -static void -flush_window() +static void flush_window(void) { - ulg c = crc; /* temporary variable */ - unsigned n; - uch *in, *out, ch; - - in = window; - out = &output_data[output_ptr]; - for (n = 0; n < outcnt; n++) { - ch = *out++ = *in++; - c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8); - } - crc = c; - bytes_out += (ulg)outcnt; - output_ptr += (ulg)outcnt; - outcnt = 0; + ulg c = crc; /* temporary variable */ + unsigned n; + uch *in, *out, ch; + + in = window; + out = &output_data[output_ptr]; + for (n = 0; n < outcnt; n++) { + ch = *out = *in; + out++; + in++; + c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8); + } + crc = c; + bytes_out += (ulg)outcnt; + output_ptr += (ulg)outcnt; + outcnt = 0; } -static void -error(char *x) +static void error(char *x) { - puts("\r\n\n"); + puts("\n\n"); puts(x); - puts("\r\n\n -- System halted\n"); + puts("\n\n -- System halted\n"); while(1); /* Halt */ } -void -setup_normal_output_buffer(void) +void setup_normal_output_buffer(void) { output_data = (char *)KERNEL_LOAD_ADR; } -static inline void -serial_setup(reg_scope_instances regi_ser) +#ifdef CONFIG_ETRAX_ARCH_V32 +static inline void serial_setup(reg_scope_instances regi_ser) { reg_ser_rw_xoff xoff; reg_ser_rw_tr_ctrl tr_ctrl; @@ -252,12 +287,16 @@ serial_setup(reg_scope_instances regi_ser) REG_WR(ser, regi_ser, rw_rec_ctrl, rec_ctrl); REG_WR(ser, regi_ser, rw_rec_baud_div, rec_baud); } +#endif -void -decompress_kernel(void) +void decompress_kernel(void) { char revision; + char compile_rev; +#ifdef CONFIG_ETRAX_ARCH_V32 + /* Need at least a CRISv32 to run. */ + compile_rev = 32; #if defined(CONFIG_ETRAX_DEBUG_PORT1) || \ defined(CONFIG_ETRAX_DEBUG_PORT2) || \ defined(CONFIG_ETRAX_DEBUG_PORT3) @@ -277,6 +316,7 @@ decompress_kernel(void) hwprot = REG_RD(pinmux, regi_pinmux, rw_hwprot); #endif + #ifdef CONFIG_ETRAX_DEBUG_PORT0 serial_setup(regi_ser0); #endif @@ -300,19 +340,52 @@ decompress_kernel(void) /* input_data is set in head.S */ inbuf = input_data; +#else /* CRISv10 */ + /* Need at least a crisv10 to run. */ + compile_rev = 10; + + /* input_data is set in head.S */ + inbuf = input_data; + +#ifdef CONFIG_ETRAX_DEBUG_PORT0 + *R_SERIAL0_XOFF = 0; + *R_SERIAL0_BAUD = 0x99; + *R_SERIAL0_TR_CTRL = 0x40; +#endif +#ifdef CONFIG_ETRAX_DEBUG_PORT1 + *R_SERIAL1_XOFF = 0; + *R_SERIAL1_BAUD = 0x99; + *R_SERIAL1_TR_CTRL = 0x40; +#endif +#ifdef CONFIG_ETRAX_DEBUG_PORT2 + *R_GEN_CONFIG = 0x08; + *R_SERIAL2_XOFF = 0; + *R_SERIAL2_BAUD = 0x99; + *R_SERIAL2_TR_CTRL = 0x40; +#endif +#ifdef CONFIG_ETRAX_DEBUG_PORT3 + *R_GEN_CONFIG = 0x100; + *R_SERIAL3_XOFF = 0; + *R_SERIAL3_BAUD = 0x99; + *R_SERIAL3_TR_CTRL = 0x40; +#endif +#endif setup_normal_output_buffer(); makecrc(); __asm__ volatile ("move $vr,%0" : "=rm" (revision)); - if (revision < 32) - { - puts("You need an ETRAX FS to run Linux 2.6/crisv32.\r\n"); + if (revision < compile_rev) { +#ifdef CONFIG_ETRAX_ARCH_V32 + puts("You need an ETRAX FS to run Linux 2.6/crisv32\n"); +#else + puts("You need an ETRAX 100LX to run linux 2.6\n"); +#endif while(1); } - puts("Uncompressing Linux...\r\n"); + puts("Uncompressing Linux...\n"); gunzip(); - puts("Done. Now booting the kernel.\r\n"); + puts("Done. Now booting the kernel\n"); } diff --git a/arch/cris/arch-v10/boot/rescue/Makefile b/arch/cris/boot/rescue/Makefile index 82ab59b968e..52bd0bd1dd2 100644 --- a/arch/cris/arch-v10/boot/rescue/Makefile +++ b/arch/cris/boot/rescue/Makefile @@ -2,16 +2,26 @@ # Makefile for rescue (bootstrap) code # -ccflags-y += -O2 $(LINUXINCLUDE) +# CC = gcc-cris -mlinux -march=v32 $(LINUXINCLUDE) +# ccflags-$(CONFIG_ETRAX_ARCH_V32) += -I$(srctree)/include/asm/arch/mach/ \ +# -I$(srctree)/include/asm/arch +# asflags-y += -I $(srctree)/include/asm/arch/mach/ -I $(srctree)/include/asm/arch +# LD = gcc-cris -mlinux -march=v32 -nostdlib + asflags-y += $(LINUXINCLUDE) -ldflags-y += -T $(srctree)/$(src)/rescue.lds +ccflags-y += -O2 $(LINUXINCLUDE) +arch-$(CONFIG_ETRAX_ARCH_V10) = v10 +arch-$(CONFIG_ETRAX_ARCH_V32) = v32 + +ldflags-y += -T $(srctree)/$(src)/rescue_$(arch-y).lds OBJCOPYFLAGS = -O binary --remove-section=.bss -obj-$(CONFIG_ETRAX_AXISFLASHMAP) = head.o -OBJECT := $(obj)/head.o +obj-$(CONFIG_ETRAX_ARCH_V32) = $(obj)/head_v32.o +obj-$(CONFIG_ETRAX_ARCH_V10) = $(obj)/head_v10.o +OBJECTS := $(obj-y) targets := rescue.o rescue.bin -$(obj)/rescue.o: $(OBJECT) FORCE +$(obj)/rescue.o: $(OBJECTS) FORCE $(call if_changed,ld) $(obj)/rescue.bin: $(obj)/rescue.o FORCE @@ -26,6 +36,7 @@ $(obj)/testrescue.bin: $(obj)/testrescue.o dd if=testrescue_tmp.bin of=$(obj)/testrescue.bin bs=1 count=784 rm tr.bin tmp2423 testrescue_tmp.bin + $(obj)/kimagerescue.bin: $(obj)/kimagerescue.o $(OBJCOPY) $(OBJCOPYFLAGS) $(obj)/kimagerescue.o ktr.bin # Pad it to 784 bytes, that's what the rescue loader expects @@ -33,3 +44,4 @@ $(obj)/kimagerescue.bin: $(obj)/kimagerescue.o cat ktr.bin tmp2423 >kimagerescue_tmp.bin dd if=kimagerescue_tmp.bin of=$(obj)/kimagerescue.bin bs=1 count=784 rm ktr.bin tmp2423 kimagerescue_tmp.bin + diff --git a/arch/cris/arch-v10/boot/rescue/head.S b/arch/cris/boot/rescue/head_v10.S index fb503d1eeea..2fafe247a25 100644 --- a/arch/cris/arch-v10/boot/rescue/head.S +++ b/arch/cris/boot/rescue/head_v10.S @@ -155,7 +155,7 @@ no_newjump: #endif ;; We need to setup the bus registers before we start using the DRAM -#include "../../lib/dram_init.S" +#include "../../../arch-v10/lib/dram_init.S" ;; we now should go through the checksum-table and check the listed ;; partitions for errors. diff --git a/arch/cris/arch-v32/boot/rescue/head.S b/arch/cris/boot/rescue/head_v32.S index 5f846b7700a..5f846b7700a 100644 --- a/arch/cris/arch-v32/boot/rescue/head.S +++ b/arch/cris/boot/rescue/head_v32.S diff --git a/arch/cris/arch-v10/boot/rescue/kimagerescue.S b/arch/cris/boot/rescue/kimagerescue.S index 6f7b3e61260..6f7b3e61260 100644 --- a/arch/cris/arch-v10/boot/rescue/kimagerescue.S +++ b/arch/cris/boot/rescue/kimagerescue.S diff --git a/arch/cris/arch-v10/boot/rescue/rescue.lds b/arch/cris/boot/rescue/rescue_v10.lds index 0b52a9490db..0b52a9490db 100644 --- a/arch/cris/arch-v10/boot/rescue/rescue.lds +++ b/arch/cris/boot/rescue/rescue_v10.lds diff --git a/arch/cris/arch-v32/boot/rescue/rescue.lds b/arch/cris/boot/rescue/rescue_v32.lds index 8ac646bc1a2..8ac646bc1a2 100644 --- a/arch/cris/arch-v32/boot/rescue/rescue.lds +++ b/arch/cris/boot/rescue/rescue_v32.lds diff --git a/arch/cris/arch-v10/boot/rescue/testrescue.S b/arch/cris/boot/rescue/testrescue.S index fc7ec674eca..fc7ec674eca 100644 --- a/arch/cris/arch-v10/boot/rescue/testrescue.S +++ b/arch/cris/boot/rescue/testrescue.S diff --git a/arch/cris/arch-v10/boot/tools/build.c b/arch/cris/boot/tools/build.c index c8adef36416..c8adef36416 100644 --- a/arch/cris/arch-v10/boot/tools/build.c +++ b/arch/cris/boot/tools/build.c diff --git a/arch/cris/include/asm/unistd.h b/arch/cris/include/asm/unistd.h index 235d076379d..c17079388bb 100644 --- a/arch/cris/include/asm/unistd.h +++ b/arch/cris/include/asm/unistd.h @@ -281,7 +281,7 @@ #define __NR_mbind 274 #define __NR_get_mempolicy 275 #define __NR_set_mempolicy 276 -#define __NR_mq_open 277 +#define __NR_mq_open 277 #define __NR_mq_unlink (__NR_mq_open+1) #define __NR_mq_timedsend (__NR_mq_open+2) #define __NR_mq_timedreceive (__NR_mq_open+3) @@ -331,10 +331,18 @@ #define __NR_fallocate 324 #define __NR_timerfd_settime 325 #define __NR_timerfd_gettime 326 +#define __NR_signalfd4 327 +#define __NR_eventfd2 328 +#define __NR_epoll_create1 329 +#define __NR_dup3 330 +#define __NR_pipe2 331 +#define __NR_inotify_init1 332 +#define __NR_preadv 333 +#define __NR_pwritev 334 #ifdef __KERNEL__ -#define NR_syscalls 327 +#define NR_syscalls 335 #include <arch/unistd.h> diff --git a/arch/ia64/include/asm/idle.h b/arch/ia64/include/asm/idle.h new file mode 100644 index 00000000000..b7685015a8b --- /dev/null +++ b/arch/ia64/include/asm/idle.h @@ -0,0 +1,7 @@ +#ifndef _ASM_IA64_IDLE_H +#define _ASM_IA64_IDLE_H + +static inline void enter_idle(void) { } +static inline void exit_idle(void) { } + +#endif /* _ASM_IA64_IDLE_H */ diff --git a/arch/ia64/include/asm/xen/events.h b/arch/ia64/include/asm/xen/events.h index 73248781fba..b8370c8b619 100644 --- a/arch/ia64/include/asm/xen/events.h +++ b/arch/ia64/include/asm/xen/events.h @@ -36,14 +36,9 @@ static inline int xen_irqs_disabled(struct pt_regs *regs) return !(ia64_psr(regs)->i); } -static inline void xen_do_IRQ(int irq, struct pt_regs *regs) +static inline void handle_irq(int irq, struct pt_regs *regs) { - struct pt_regs *old_regs; - old_regs = set_irq_regs(regs); - irq_enter(); __do_IRQ(irq); - irq_exit(); - set_irq_regs(old_regs); } #define irq_ctx_init(cpu) do { } while (0) diff --git a/arch/ia64/xen/xensetup.S b/arch/ia64/xen/xensetup.S index 28fed1fcc07..aff8346ea19 100644 --- a/arch/ia64/xen/xensetup.S +++ b/arch/ia64/xen/xensetup.S @@ -54,8 +54,6 @@ END(startup_xen) #define isBP p3 // are we the Bootstrap Processor? - .text - GLOBAL_ENTRY(xen_setup_hook) mov r8=XEN_PV_DOMAIN_ASM (isBP) movl r9=xen_domain_type;; diff --git a/arch/m32r/boot/compressed/Makefile b/arch/m32r/boot/compressed/Makefile index d908e1d3c07..560484ae35e 100644 --- a/arch/m32r/boot/compressed/Makefile +++ b/arch/m32r/boot/compressed/Makefile @@ -6,7 +6,6 @@ targets := vmlinux vmlinux.bin vmlinux.bin.gz head.o misc.o \ piggy.o vmlinux.lds -EXTRA_AFLAGS := -traditional OBJECTS = $(obj)/head.o $(obj)/misc.o diff --git a/arch/m32r/include/asm/assembler.h b/arch/m32r/include/asm/assembler.h index 26351539b5f..728799fc70a 100644 --- a/arch/m32r/include/asm/assembler.h +++ b/arch/m32r/include/asm/assembler.h @@ -9,14 +9,15 @@ * This file contains M32R architecture specific macro definitions. */ +#include <linux/stringify.h> + +#undef __STR -#ifndef __STR #ifdef __ASSEMBLY__ #define __STR(x) x #else -#define __STR(x) #x +#define __STR(x) __stringify(x) #endif -#endif /* __STR */ #ifdef CONFIG_SMP #define M32R_LOCK __STR(lock) diff --git a/arch/m32r/kernel/Makefile b/arch/m32r/kernel/Makefile index 09200d4886e..b1a4b603659 100644 --- a/arch/m32r/kernel/Makefile +++ b/arch/m32r/kernel/Makefile @@ -9,5 +9,3 @@ obj-y := process.o entry.o traps.o align.o irq.o setup.o time.o \ obj-$(CONFIG_SMP) += smp.o smpboot.o obj-$(CONFIG_MODULES) += module.o - -EXTRA_AFLAGS := -traditional diff --git a/arch/microblaze/include/asm/of_platform.h b/arch/microblaze/include/asm/of_platform.h index 187c0eedaec..37491276c6c 100644 --- a/arch/microblaze/include/asm/of_platform.h +++ b/arch/microblaze/include/asm/of_platform.h @@ -36,16 +36,6 @@ static const struct of_device_id of_default_bus_ids[] = { {}, }; -/* Platform drivers register/unregister */ -static inline int of_register_platform_driver(struct of_platform_driver *drv) -{ - return of_register_driver(drv, &of_platform_bus_type); -} -static inline void of_unregister_platform_driver(struct of_platform_driver *drv) -{ - of_unregister_driver(drv); -} - /* Platform devices and busses creation */ extern struct of_device *of_platform_device_create(struct device_node *np, const char *bus_id, diff --git a/arch/microblaze/kernel/cpu/cpuinfo-static.c b/arch/microblaze/kernel/cpu/cpuinfo-static.c index cfe44effdb7..450ca6bb828 100644 --- a/arch/microblaze/kernel/cpu/cpuinfo-static.c +++ b/arch/microblaze/kernel/cpu/cpuinfo-static.c @@ -14,8 +14,8 @@ #include <asm/cpuinfo.h> #include <asm/pvr.h> -const static char family_string[] = CONFIG_XILINX_MICROBLAZE0_FAMILY; -const static char cpu_ver_string[] = CONFIG_XILINX_MICROBLAZE0_HW_VER; +static const char family_string[] = CONFIG_XILINX_MICROBLAZE0_FAMILY; +static const char cpu_ver_string[] = CONFIG_XILINX_MICROBLAZE0_HW_VER; #define err_printk(x) \ early_printk("ERROR: Microblaze " x "- different for kernel and DTS\n"); diff --git a/arch/microblaze/kernel/sys_microblaze.c b/arch/microblaze/kernel/sys_microblaze.c index ba0568c2cc1..31905ff590b 100644 --- a/arch/microblaze/kernel/sys_microblaze.c +++ b/arch/microblaze/kernel/sys_microblaze.c @@ -131,7 +131,7 @@ sys_ipc(uint call, int first, int second, int third, void *ptr, long fifth) ret = sys_shmctl(first, second, (struct shmid_ds *) ptr); break; } - return -EINVAL; + return ret; } asmlinkage int sys_vfork(struct pt_regs *regs) diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 4c780455136..a0d1146a057 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -181,6 +181,10 @@ config SYS_SUPPORTS_APM_EMULATION default y if PMAC_APM_EMU bool +config DTC + bool + default y + config DEFAULT_UIMAGE bool help diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile index 4458abb67c5..8da2bf963b5 100644 --- a/arch/powerpc/boot/Makefile +++ b/arch/powerpc/boot/Makefile @@ -33,7 +33,7 @@ ifeq ($(call cc-option-yn, -fstack-protector),y) BOOTCFLAGS += -fno-stack-protector endif -BOOTCFLAGS += -I$(obj) -I$(srctree)/$(obj) -I$(srctree)/$(src)/libfdt +BOOTCFLAGS += -I$(obj) -I$(srctree)/$(obj) DTS_FLAGS ?= -p 1024 @@ -53,9 +53,14 @@ zliblinuxheader := zlib.h zconf.h zutil.h $(addprefix $(obj)/,$(zlib) cuboot-c2k.o gunzip_util.o main.o prpmc2800.o): \ $(addprefix $(obj)/,$(zliblinuxheader)) $(addprefix $(obj)/,$(zlibheader)) -src-libfdt := fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c +libfdt := fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c +libfdtheader := fdt.h libfdt.h libfdt_internal.h + +$(addprefix $(obj)/,$(libfdt) libfdt-wrapper.o simpleboot.o): \ + $(addprefix $(obj)/,$(libfdtheader)) + src-wlib := string.S crt0.S crtsavres.S stdio.c main.c \ - $(addprefix libfdt/,$(src-libfdt)) libfdt-wrapper.c \ + $(libfdt) libfdt-wrapper.c \ ns16550.c serial.c simple_alloc.c div64.S util.S \ gunzip_util.c elf_util.c $(zlib) devtree.c oflib.c ofconsole.c \ 4xx.c ebony.c mv64x60.c mpsc.c mv64x60_i2c.c cuboot.c bamboo.c \ @@ -96,6 +101,12 @@ $(addprefix $(obj)/,$(zlibheader)): $(obj)/%: $(srctree)/lib/zlib_inflate/% $(addprefix $(obj)/,$(zliblinuxheader)): $(obj)/%: $(srctree)/include/linux/% $(call cmd,copy_zliblinuxheader) +quiet_cmd_copy_libfdt = COPY $@ + cmd_copy_libfdt = cp $< $@ + +$(addprefix $(obj)/,$(libfdt) $(libfdtheader)): $(obj)/%: $(srctree)/scripts/dtc/libfdt/% + $(call cmd,copy_libfdt) + $(obj)/empty.c: @touch $@ @@ -103,6 +114,7 @@ $(obj)/zImage.lds $(obj)/zImage.coff.lds $(obj)/zImage.ps3.lds: $(obj)/%: $(srct @cp $< $@ clean-files := $(zlib) $(zlibheader) $(zliblinuxheader) \ + $(libfdt) $(libfdtheader) \ empty.c zImage.coff.lds zImage.ps3.lds zImage.lds quiet_cmd_bootcc = BOOTCC $@ @@ -114,6 +126,8 @@ quiet_cmd_bootas = BOOTAS $@ quiet_cmd_bootar = BOOTAR $@ cmd_bootar = $(CROSS32AR) -cr $@.$$$$ $(filter-out FORCE,$^); mv $@.$$$$ $@ +$(obj-libfdt): $(obj)/%.o: $(srctree)/scripts/dtc/libfdt/%.c FORCE + $(call if_changed_dep,bootcc) $(patsubst %.c,%.o, $(filter %.c, $(src-boot))): %.o: %.c FORCE $(Q)mkdir -p $(dir $@) $(call if_changed_dep,bootcc) @@ -124,7 +138,7 @@ $(patsubst %.S,%.o, $(filter %.S, $(src-boot))): %.o: %.S FORCE $(obj)/wrapper.a: $(obj-wlib) FORCE $(call if_changed,bootar) -hostprogs-y := addnote addRamDisk hack-coff mktree dtc +hostprogs-y := addnote addRamDisk hack-coff mktree targets += $(patsubst $(obj)/%,%,$(obj-boot) wrapper.a) extra-y := $(obj)/wrapper.a $(obj-plat) $(obj)/empty.o \ @@ -133,47 +147,10 @@ extra-y := $(obj)/wrapper.a $(obj-plat) $(obj)/empty.o \ dtstree := $(srctree)/$(src)/dts wrapper :=$(srctree)/$(src)/wrapper -wrapperbits := $(extra-y) $(addprefix $(obj)/,addnote hack-coff mktree dtc) \ +wrapperbits := $(extra-y) $(addprefix $(obj)/,addnote hack-coff mktree) \ $(wrapper) FORCE ############# -# Bits for building dtc -# DTC_GENPARSER := 1 # Uncomment to rebuild flex/bison output - -dtc-objs := dtc.o flattree.o fstree.o data.o livetree.o treesource.o srcpos.o checks.o -dtc-objs += dtc-lexer.lex.o dtc-parser.tab.o -dtc-objs := $(addprefix dtc-src/, $(dtc-objs)) - -# prerequisites on generated files needs to be explicit -$(obj)/dtc-src/dtc-parser.tab.o: $(obj)/dtc-src/dtc-parser.tab.c $(obj)/dtc-src/dtc-parser.tab.h -$(obj)/dtc-src/dtc-lexer.lex.o: $(obj)/dtc-src/dtc-lexer.lex.c $(obj)/dtc-src/dtc-parser.tab.h - -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 - -quiet_cmd_bison = BISON $@ - cmd_bison = $(BISON) -o$@ -d $<; cp $@ $@_shipped -quiet_cmd_flex = FLEX $@ - cmd_flex = $(FLEX) -o$@ $<; cp $@ $@_shipped - -$(obj)/dtc-src/dtc-parser.tab.c: $(src)/dtc-src/dtc-parser.y FORCE - $(call if_changed,bison) - -$(obj)/dtc-src/dtc-parser.tab.h: $(obj)/dtc-src/dtc-parser.tab.c - -$(obj)/dtc-src/dtc-lexer.lex.c: $(src)/dtc-src/dtc-lexer.l FORCE - $(call if_changed,flex) -endif - -############# # Bits for building various flavours of zImage ifneq ($(CROSS32_COMPILE),) @@ -347,8 +324,10 @@ $(obj)/treeImage.%: vmlinux $(obj)/%.dtb $(wrapperbits) $(call if_changed,wrap,treeboot-$*,,$(obj)/$*.dtb) # Rule to build device tree blobs -$(obj)/%.dtb: $(dtstree)/%.dts $(obj)/dtc - $(obj)/dtc -O dtb -o $(obj)/$*.dtb -b 0 $(DTS_FLAGS) $(dtstree)/$*.dts +DTC = $(objtree)/scripts/dtc/dtc + +$(obj)/%.dtb: $(dtstree)/%.dts + $(DTC) -O dtb -o $(obj)/$*.dtb -b 0 $(DTS_FLAGS) $(dtstree)/$*.dts # If there isn't a platform selected then just strip the vmlinux. ifeq (,$(image-y)) diff --git a/arch/powerpc/boot/simpleboot.c b/arch/powerpc/boot/simpleboot.c index c58a0dada99..21cd48074ec 100644 --- a/arch/powerpc/boot/simpleboot.c +++ b/arch/powerpc/boot/simpleboot.c @@ -19,7 +19,7 @@ #include "types.h" #include "io.h" #include "stdio.h" -#include "libfdt/libfdt.h" +#include <libfdt.h> BSS_STACK(4*1024); diff --git a/arch/powerpc/include/asm/of_platform.h b/arch/powerpc/include/asm/of_platform.h index 53b46507ffd..d4aaa348944 100644 --- a/arch/powerpc/include/asm/of_platform.h +++ b/arch/powerpc/include/asm/of_platform.h @@ -11,16 +11,6 @@ * */ -/* Platform drivers register/unregister */ -static inline int of_register_platform_driver(struct of_platform_driver *drv) -{ - return of_register_driver(drv, &of_platform_bus_type); -} -static inline void of_unregister_platform_driver(struct of_platform_driver *drv) -{ - of_unregister_driver(drv); -} - /* Platform devices and busses creation */ extern struct of_device *of_platform_device_create(struct device_node *np, const char *bus_id, diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index cd1b687544f..f9c40f869c6 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c @@ -382,7 +382,8 @@ static struct cpu_spec __initdata cpu_specs[] = { .icache_bsize = 128, .dcache_bsize = 128, .machine_check = machine_check_generic, - .oprofile_cpu_type = "ppc64/compat-power5+", + .oprofile_cpu_type = "ppc64/ibm-compat-v1", + .oprofile_type = PPC_OPROFILE_POWER4, .platform = "power5+", }, { /* Power6 */ @@ -416,7 +417,8 @@ static struct cpu_spec __initdata cpu_specs[] = { .icache_bsize = 128, .dcache_bsize = 128, .machine_check = machine_check_generic, - .oprofile_cpu_type = "ppc64/compat-power6", + .oprofile_cpu_type = "ppc64/ibm-compat-v1", + .oprofile_type = PPC_OPROFILE_POWER4, .platform = "power6", }, { /* 2.06-compliant processor, i.e. Power7 "architected" mode */ @@ -429,7 +431,8 @@ static struct cpu_spec __initdata cpu_specs[] = { .icache_bsize = 128, .dcache_bsize = 128, .machine_check = machine_check_generic, - .oprofile_cpu_type = "ppc64/compat-power7", + .oprofile_type = PPC_OPROFILE_POWER4, + .oprofile_cpu_type = "ppc64/ibm-compat-v1", .platform = "power7", }, { /* Power7 */ @@ -1833,8 +1836,10 @@ static void __init setup_cpu_spec(unsigned long offset, struct cpu_spec *s) * and, in that case, keep the current value for * oprofile_cpu_type. */ - if (old.oprofile_cpu_type == NULL) - t->oprofile_cpu_type = s->oprofile_cpu_type; + if (old.oprofile_cpu_type == NULL) { + t->oprofile_cpu_type = old.oprofile_cpu_type; + t->oprofile_type = old.oprofile_type; + } } *PTRRELOC(&cur_cpu_spec) = &the_cpu_spec; diff --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h index 563933e06a3..4f8c199584e 100644 --- a/arch/x86/include/asm/mce.h +++ b/arch/x86/include/asm/mce.h @@ -137,6 +137,7 @@ DECLARE_PER_CPU(mce_banks_t, mce_poll_banks); enum mcp_flags { MCP_TIMESTAMP = (1 << 0), /* log time stamp */ MCP_UC = (1 << 1), /* log uncorrected errors */ + MCP_DONTLOG = (1 << 2), /* only clear, don't log */ }; extern void machine_check_poll(enum mcp_flags flags, mce_banks_t *b); diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c index 42c33cebf00..8c0be0902da 100644 --- a/arch/x86/kernel/amd_iommu_init.c +++ b/arch/x86/kernel/amd_iommu_init.c @@ -49,10 +49,10 @@ #define IVHD_DEV_EXT_SELECT 0x46 #define IVHD_DEV_EXT_SELECT_RANGE 0x47 -#define IVHD_FLAG_HT_TUN_EN 0x00 -#define IVHD_FLAG_PASSPW_EN 0x01 -#define IVHD_FLAG_RESPASSPW_EN 0x02 -#define IVHD_FLAG_ISOC_EN 0x03 +#define IVHD_FLAG_HT_TUN_EN_MASK 0x01 +#define IVHD_FLAG_PASSPW_EN_MASK 0x02 +#define IVHD_FLAG_RESPASSPW_EN_MASK 0x04 +#define IVHD_FLAG_ISOC_EN_MASK 0x08 #define IVMD_FLAG_EXCL_RANGE 0x08 #define IVMD_FLAG_UNITY_MAP 0x01 @@ -569,19 +569,19 @@ static void __init init_iommu_from_acpi(struct amd_iommu *iommu, * First set the recommended feature enable bits from ACPI * into the IOMMU control registers */ - h->flags & IVHD_FLAG_HT_TUN_EN ? + h->flags & IVHD_FLAG_HT_TUN_EN_MASK ? iommu_feature_enable(iommu, CONTROL_HT_TUN_EN) : iommu_feature_disable(iommu, CONTROL_HT_TUN_EN); - h->flags & IVHD_FLAG_PASSPW_EN ? + h->flags & IVHD_FLAG_PASSPW_EN_MASK ? iommu_feature_enable(iommu, CONTROL_PASSPW_EN) : iommu_feature_disable(iommu, CONTROL_PASSPW_EN); - h->flags & IVHD_FLAG_RESPASSPW_EN ? + h->flags & IVHD_FLAG_RESPASSPW_EN_MASK ? iommu_feature_enable(iommu, CONTROL_RESPASSPW_EN) : iommu_feature_disable(iommu, CONTROL_RESPASSPW_EN); - h->flags & IVHD_FLAG_ISOC_EN ? + h->flags & IVHD_FLAG_ISOC_EN_MASK ? iommu_feature_enable(iommu, CONTROL_ISOC_EN) : iommu_feature_disable(iommu, CONTROL_ISOC_EN); diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index c4f667896c2..c1caefc82e6 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -1203,6 +1203,8 @@ void __cpuinit cpu_init(void) load_TR_desc(); load_LDT(&init_mm.context); + t->x86_tss.io_bitmap_base = offsetof(struct tss_struct, io_bitmap); + #ifdef CONFIG_DOUBLEFAULT /* Set up doublefault TSS pointer in the GDT */ __set_tss_desc(cpu, GDT_ENTRY_DOUBLEFAULT_TSS, &doublefault_tss); diff --git a/arch/x86/kernel/cpu/mcheck/mce_64.c b/arch/x86/kernel/cpu/mcheck/mce_64.c index 863f89568b1..6fb0b359d2a 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_64.c +++ b/arch/x86/kernel/cpu/mcheck/mce_64.c @@ -239,9 +239,10 @@ void machine_check_poll(enum mcp_flags flags, mce_banks_t *b) * Don't get the IP here because it's unlikely to * have anything to do with the actual error location. */ - - mce_log(&m); - add_taint(TAINT_MACHINE_CHECK); + if (!(flags & MCP_DONTLOG)) { + mce_log(&m); + add_taint(TAINT_MACHINE_CHECK); + } /* * Clear state for this bank. @@ -452,13 +453,14 @@ void mce_log_therm_throt_event(__u64 status) */ static int check_interval = 5 * 60; /* 5 minutes */ -static int next_interval; /* in jiffies */ +static DEFINE_PER_CPU(int, next_interval); /* in jiffies */ static void mcheck_timer(unsigned long); static DEFINE_PER_CPU(struct timer_list, mce_timer); static void mcheck_timer(unsigned long data) { struct timer_list *t = &per_cpu(mce_timer, data); + int *n; WARN_ON(smp_processor_id() != data); @@ -470,14 +472,14 @@ static void mcheck_timer(unsigned long data) * Alert userspace if needed. If we logged an MCE, reduce the * polling interval, otherwise increase the polling interval. */ + n = &__get_cpu_var(next_interval); if (mce_notify_user()) { - next_interval = max(next_interval/2, HZ/100); + *n = max(*n/2, HZ/100); } else { - next_interval = min(next_interval * 2, - (int)round_jiffies_relative(check_interval*HZ)); + *n = min(*n*2, (int)round_jiffies_relative(check_interval*HZ)); } - t->expires = jiffies + next_interval; + t->expires = jiffies + *n; add_timer(t); } @@ -584,7 +586,7 @@ static void mce_init(void *dummy) * Log the machine checks left over from the previous reset. */ bitmap_fill(all_banks, MAX_NR_BANKS); - machine_check_poll(MCP_UC, &all_banks); + machine_check_poll(MCP_UC|(!mce_bootlog ? MCP_DONTLOG : 0), &all_banks); set_in_cr4(X86_CR4_MCE); @@ -632,14 +634,13 @@ static void mce_cpu_features(struct cpuinfo_x86 *c) static void mce_init_timer(void) { struct timer_list *t = &__get_cpu_var(mce_timer); + int *n = &__get_cpu_var(next_interval); - /* data race harmless because everyone sets to the same value */ - if (!next_interval) - next_interval = check_interval * HZ; - if (!next_interval) + *n = check_interval * HZ; + if (!*n) return; setup_timer(t, mcheck_timer, smp_processor_id()); - t->expires = round_jiffies(jiffies + next_interval); + t->expires = round_jiffies(jiffies + *n); add_timer(t); } @@ -907,7 +908,6 @@ static void mce_cpu_restart(void *data) /* Reinit MCEs after user configuration changes */ static void mce_restart(void) { - next_interval = check_interval * HZ; on_each_cpu(mce_cpu_restart, NULL, 1); } @@ -1110,7 +1110,8 @@ static int __cpuinit mce_cpu_callback(struct notifier_block *nfb, break; case CPU_DOWN_FAILED: case CPU_DOWN_FAILED_FROZEN: - t->expires = round_jiffies(jiffies + next_interval); + t->expires = round_jiffies(jiffies + + __get_cpu_var(next_interval)); add_timer_on(t, cpu); smp_call_function_single(cpu, mce_reenable_cpu, &action, 1); break; diff --git a/arch/x86/kernel/cpu/mcheck/mce_intel_64.c b/arch/x86/kernel/cpu/mcheck/mce_intel_64.c index d6b72df89d6..cef3ee30744 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_intel_64.c +++ b/arch/x86/kernel/cpu/mcheck/mce_intel_64.c @@ -151,10 +151,11 @@ static void print_update(char *type, int *hdr, int num) static void cmci_discover(int banks, int boot) { unsigned long *owned = (void *)&__get_cpu_var(mce_banks_owned); + unsigned long flags; int hdr = 0; int i; - spin_lock(&cmci_discover_lock); + spin_lock_irqsave(&cmci_discover_lock, flags); for (i = 0; i < banks; i++) { u64 val; @@ -184,7 +185,7 @@ static void cmci_discover(int banks, int boot) WARN_ON(!test_bit(i, __get_cpu_var(mce_poll_banks))); } } - spin_unlock(&cmci_discover_lock); + spin_unlock_irqrestore(&cmci_discover_lock, flags); if (hdr) printk(KERN_CONT "\n"); } @@ -211,13 +212,14 @@ void cmci_recheck(void) */ void cmci_clear(void) { + unsigned long flags; int i; int banks; u64 val; if (!cmci_supported(&banks)) return; - spin_lock(&cmci_discover_lock); + spin_lock_irqsave(&cmci_discover_lock, flags); for (i = 0; i < banks; i++) { if (!test_bit(i, __get_cpu_var(mce_banks_owned))) continue; @@ -227,7 +229,7 @@ void cmci_clear(void) wrmsrl(MSR_IA32_MC0_CTL2 + i, val); __clear_bit(i, __get_cpu_var(mce_banks_owned)); } - spin_unlock(&cmci_discover_lock); + spin_unlock_irqrestore(&cmci_discover_lock, flags); } /* diff --git a/arch/x86/kernel/cpu/proc.c b/arch/x86/kernel/cpu/proc.c index f93047fed79..d5e30397246 100644 --- a/arch/x86/kernel/cpu/proc.c +++ b/arch/x86/kernel/cpu/proc.c @@ -14,7 +14,7 @@ static void show_cpuinfo_core(struct seq_file *m, struct cpuinfo_x86 *c, if (c->x86_max_cores * smp_num_siblings > 1) { seq_printf(m, "physical id\t: %d\n", c->phys_proc_id); seq_printf(m, "siblings\t: %d\n", - cpumask_weight(cpu_sibling_mask(cpu))); + cpumask_weight(cpu_core_mask(cpu))); seq_printf(m, "core id\t\t: %d\n", c->cpu_core_id); seq_printf(m, "cpu cores\t: %d\n", c->booted_cores); seq_printf(m, "apicid\t\t: %d\n", c->apicid); diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c index ef2c3563357..00628130292 100644 --- a/arch/x86/kernel/e820.c +++ b/arch/x86/kernel/e820.c @@ -1074,12 +1074,13 @@ u64 __init early_reserve_e820(u64 startt, u64 sizet, u64 align) u64 addr; u64 start; - start = startt; - while (size < sizet && (start + 1)) + for (start = startt; ; start += size) { start = find_e820_area_size(start, &size, align); - - if (size < sizet) - return 0; + if (!(start + 1)) + return 0; + if (size >= sizet) + break; + } #ifdef CONFIG_X86_32 if (start >= MAXMEM) diff --git a/arch/x86/kernel/machine_kexec_32.c b/arch/x86/kernel/machine_kexec_32.c index e7368c1da01..c1c429d0013 100644 --- a/arch/x86/kernel/machine_kexec_32.c +++ b/arch/x86/kernel/machine_kexec_32.c @@ -194,7 +194,7 @@ void machine_kexec(struct kimage *image) unsigned int preserve_context); #ifdef CONFIG_KEXEC_JUMP - if (kexec_image->preserve_context) + if (image->preserve_context) save_processor_state(); #endif @@ -253,7 +253,7 @@ void machine_kexec(struct kimage *image) image->preserve_context); #ifdef CONFIG_KEXEC_JUMP - if (kexec_image->preserve_context) + if (image->preserve_context) restore_processor_state(); #endif diff --git a/arch/x86/kernel/machine_kexec_64.c b/arch/x86/kernel/machine_kexec_64.c index 89cea4d4467..84c3bf209e9 100644 --- a/arch/x86/kernel/machine_kexec_64.c +++ b/arch/x86/kernel/machine_kexec_64.c @@ -274,7 +274,7 @@ void machine_kexec(struct kimage *image) int save_ftrace_enabled; #ifdef CONFIG_KEXEC_JUMP - if (kexec_image->preserve_context) + if (image->preserve_context) save_processor_state(); #endif @@ -333,7 +333,7 @@ void machine_kexec(struct kimage *image) image->preserve_context); #ifdef CONFIG_KEXEC_JUMP - if (kexec_image->preserve_context) + if (image->preserve_context) restore_processor_state(); #endif diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c index fd3da1dda1c..ae4f7b5d710 100644 --- a/arch/x86/mm/init.c +++ b/arch/x86/mm/init.c @@ -7,6 +7,7 @@ #include <asm/page.h> #include <asm/page_types.h> #include <asm/sections.h> +#include <asm/setup.h> #include <asm/system.h> #include <asm/tlbflush.h> @@ -304,8 +305,23 @@ unsigned long __init_refok init_memory_mapping(unsigned long start, #endif #ifdef CONFIG_X86_64 - if (!after_bootmem) + if (!after_bootmem && !start) { + pud_t *pud; + pmd_t *pmd; + mmu_cr4_features = read_cr4(); + + /* + * _brk_end cannot change anymore, but it and _end may be + * located on different 2M pages. cleanup_highmap(), however, + * can only consider _end when it runs, so destroy any + * mappings beyond _brk_end here. + */ + pud = pud_offset(pgd_offset_k(_brk_end), _brk_end); + pmd = pmd_offset(pud, _brk_end - 1); + while (++pmd <= pmd_offset(pud, (unsigned long)_end - 1)) + pmd_clear(pmd); + } #endif __flush_tlb_all(); diff --git a/arch/x86/mm/kmmio.c b/arch/x86/mm/kmmio.c index 4f115e00486..50dc802a1c4 100644 --- a/arch/x86/mm/kmmio.c +++ b/arch/x86/mm/kmmio.c @@ -87,7 +87,7 @@ static struct kmmio_probe *get_kmmio_probe(unsigned long addr) { struct kmmio_probe *p; list_for_each_entry_rcu(p, &kmmio_probes, list) { - if (addr >= p->addr && addr <= (p->addr + p->len)) + if (addr >= p->addr && addr < (p->addr + p->len)) return p; } return NULL; diff --git a/arch/x86/mm/srat_32.c b/arch/x86/mm/srat_32.c index 16ae70fc57e..29a0e37114f 100644 --- a/arch/x86/mm/srat_32.c +++ b/arch/x86/mm/srat_32.c @@ -216,7 +216,7 @@ int __init get_memcfg_from_srat(void) if (num_memory_chunks == 0) { printk(KERN_WARNING - "could not finy any ACPI SRAT memory areas.\n"); + "could not find any ACPI SRAT memory areas.\n"); goto out_fail; } diff --git a/arch/x86/mm/srat_64.c b/arch/x86/mm/srat_64.c index 33c5fa57e43..01765955baa 100644 --- a/arch/x86/mm/srat_64.c +++ b/arch/x86/mm/srat_64.c @@ -361,6 +361,7 @@ static void __init unparse_node(int node) { int i; node_clear(node, nodes_parsed); + node_clear(node, cpu_nodes_parsed); for (i = 0; i < MAX_LOCAL_APIC; i++) { if (apicid_to_node[i] == node) apicid_to_node[i] = NUMA_NO_NODE; diff --git a/arch/x86/vdso/vclock_gettime.c b/arch/x86/vdso/vclock_gettime.c index d9d35824c56..6a40b78b46a 100644 --- a/arch/x86/vdso/vclock_gettime.c +++ b/arch/x86/vdso/vclock_gettime.c @@ -104,11 +104,13 @@ notrace int __vdso_gettimeofday(struct timeval *tv, struct timezone *tz) { long ret; if (likely(gtod->sysctl_enabled && gtod->clock.vread)) { - BUILD_BUG_ON(offsetof(struct timeval, tv_usec) != - offsetof(struct timespec, tv_nsec) || - sizeof(*tv) != sizeof(struct timespec)); - do_realtime((struct timespec *)tv); - tv->tv_usec /= 1000; + if (likely(tv != NULL)) { + BUILD_BUG_ON(offsetof(struct timeval, tv_usec) != + offsetof(struct timespec, tv_nsec) || + sizeof(*tv) != sizeof(struct timespec)); + do_realtime((struct timespec *)tv); + tv->tv_usec /= 1000; + } if (unlikely(tz != NULL)) { /* Avoid memcpy. Some old compilers fail to inline it */ tz->tz_minuteswest = gtod->sys_tz.tz_minuteswest; diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index 9842b121240..e25a78e1113 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c @@ -1794,6 +1794,11 @@ __init pgd_t *xen_setup_kernel_pagetable(pgd_t *pgd, pin_pagetable_pfn(MMUEXT_PIN_L3_TABLE, PFN_DOWN(__pa(swapper_pg_dir))); + reserve_early(__pa(xen_start_info->pt_base), + __pa(xen_start_info->pt_base + + xen_start_info->nr_pt_frames * PAGE_SIZE), + "XEN PAGETABLES"); + return swapper_pg_dir; } #endif /* CONFIG_X86_64 */ diff --git a/drivers/Makefile b/drivers/Makefile index 2618a6169a1..1266ead6ace 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -36,7 +36,7 @@ obj-$(CONFIG_FB_INTEL) += video/intelfb/ obj-y += serial/ obj-$(CONFIG_PARPORT) += parport/ -obj-y += base/ block/ misc/ mfd/ media/ +obj-y += base/ block/ misc/ mfd/ obj-$(CONFIG_NUBUS) += nubus/ obj-y += macintosh/ obj-$(CONFIG_IDE) += ide/ @@ -71,7 +71,7 @@ obj-$(CONFIG_GAMEPORT) += input/gameport/ obj-$(CONFIG_INPUT) += input/ obj-$(CONFIG_I2O) += message/ obj-$(CONFIG_RTC_LIB) += rtc/ -obj-y += i2c/ +obj-y += i2c/ media/ obj-$(CONFIG_W1) += w1/ obj-$(CONFIG_POWER_SUPPLY) += power/ obj-$(CONFIG_HWMON) += hwmon/ diff --git a/drivers/acpi/acpica/rscalc.c b/drivers/acpi/acpica/rscalc.c index b6667ff059e..88b5a2c4814 100644 --- a/drivers/acpi/acpica/rscalc.c +++ b/drivers/acpi/acpica/rscalc.c @@ -543,6 +543,13 @@ acpi_rs_get_pci_routing_table_length(union acpi_operand_object *package_object, package_element = *top_object_list; + /* We must have a valid Package object */ + + if (!package_element || + (package_element->common.type != ACPI_TYPE_PACKAGE)) { + return_ACPI_STATUS (AE_AML_OPERAND_TYPE); + } + /* * The sub_object_list will now point to an array of the * four IRQ elements: Address, Pin, Source and source_index diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index 942d14ac879..d51a17c0f59 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c @@ -72,6 +72,7 @@ * ICH2 spec c #20 - IDE PRD must not cross a 64K boundary * and must be dword aligned * ICH2 spec c #24 - UDMA mode 4,5 t85/86 should be 6ns not 3.3 + * ICH7 errata #16 - MWDMA1 timings are incorrect * * Should have been BIOS fixed: * 450NX: errata #19 - DMA hangs on old 450NX @@ -94,7 +95,7 @@ #include <linux/dmi.h> #define DRV_NAME "ata_piix" -#define DRV_VERSION "2.12" +#define DRV_VERSION "2.13" enum { PIIX_IOCFG = 0x54, /* IDE I/O configuration register */ @@ -136,6 +137,7 @@ enum piix_controller_ids { ich_pata_33, /* ICH up to UDMA 33 only */ ich_pata_66, /* ICH up to 66 Mhz */ ich_pata_100, /* ICH up to UDMA 100 */ + ich_pata_100_nomwdma1, /* ICH up to UDMA 100 but with no MWDMA1*/ ich5_sata, ich6_sata, ich6m_sata, @@ -216,8 +218,8 @@ static const struct pci_device_id piix_pci_tbl[] = { /* ICH6 (and 6) (i915) UDMA 100 */ { 0x8086, 0x266F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, /* ICH7/7-R (i945, i975) UDMA 100*/ - { 0x8086, 0x27DF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, - { 0x8086, 0x269E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, + { 0x8086, 0x27DF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100_nomwdma1 }, + { 0x8086, 0x269E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100_nomwdma1 }, /* ICH8 Mobile PATA Controller */ { 0x8086, 0x2850, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, @@ -487,6 +489,15 @@ static struct ata_port_info piix_port_info[] = { .port_ops = &ich_pata_ops, }, + [ich_pata_100_nomwdma1] = + { + .flags = PIIX_PATA_FLAGS | PIIX_FLAG_CHECKINTR, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2_ONLY, + .udma_mask = ATA_UDMA5, + .port_ops = &ich_pata_ops, + }, + [ich5_sata] = { .flags = PIIX_SATA_FLAGS, @@ -594,6 +605,7 @@ static const struct ich_laptop ich_laptop[] = { { 0x24CA, 0x1025, 0x003d }, /* ICH4 on ACER TM290 */ { 0x266F, 0x1025, 0x0066 }, /* ICH6 on ACER Aspire 1694WLMi */ { 0x2653, 0x1043, 0x82D8 }, /* ICH6M on Asus Eee 701 */ + { 0x27df, 0x104d, 0x900e }, /* ICH7 on Sony TZ-90 */ /* end marker */ { 0, } }; diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 17c5d48a75d..c9242301cfa 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -4091,7 +4091,9 @@ int ata_dev_revalidate(struct ata_device *dev, unsigned int new_class, /* fail early if !ATA && !ATAPI to avoid issuing [P]IDENTIFY to PMP */ if (ata_class_enabled(new_class) && - new_class != ATA_DEV_ATA && new_class != ATA_DEV_ATAPI) { + new_class != ATA_DEV_ATA && + new_class != ATA_DEV_ATAPI && + new_class != ATA_DEV_SEMB) { ata_dev_printk(dev, KERN_INFO, "class mismatch %u != %u\n", dev->class, new_class); rc = -ENODEV; diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 01831312c36..94919ad03df 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -2783,6 +2783,12 @@ static int ata_eh_revalidate_and_attach(struct ata_link *link, } else if (dev->class == ATA_DEV_UNKNOWN && ehc->tries[dev->devno] && ata_class_enabled(ehc->classes[dev->devno])) { + /* Temporarily set dev->class, it will be + * permanently set once all configurations are + * complete. This is necessary because new + * device configuration is done in two + * separate loops. + */ dev->class = ehc->classes[dev->devno]; if (dev->class == ATA_DEV_PMP) @@ -2790,6 +2796,11 @@ static int ata_eh_revalidate_and_attach(struct ata_link *link, else rc = ata_dev_read_id(dev, &dev->class, readid_flags, dev->id); + + /* read_id might have changed class, store and reset */ + ehc->classes[dev->devno] = dev->class; + dev->class = ATA_DEV_UNKNOWN; + switch (rc) { case 0: /* clear error info accumulated during probe */ @@ -2799,13 +2810,11 @@ static int ata_eh_revalidate_and_attach(struct ata_link *link, case -ENOENT: /* IDENTIFY was issued to non-existent * device. No need to reset. Just - * thaw and kill the device. + * thaw and ignore the device. */ ata_eh_thaw_port(ap); - dev->class = ATA_DEV_UNKNOWN; break; default: - dev->class = ATA_DEV_UNKNOWN; goto err; } } @@ -2826,11 +2835,15 @@ static int ata_eh_revalidate_and_attach(struct ata_link *link, dev->class == ATA_DEV_PMP) continue; + dev->class = ehc->classes[dev->devno]; + ehc->i.flags |= ATA_EHI_PRINTINFO; rc = ata_dev_configure(dev); ehc->i.flags &= ~ATA_EHI_PRINTINFO; - if (rc) + if (rc) { + dev->class = ATA_DEV_UNKNOWN; goto err; + } spin_lock_irqsave(ap->lock, flags); ap->pflags |= ATA_PFLAG_SCSI_HOTPLUG; @@ -3494,6 +3507,8 @@ static void ata_eh_handle_port_suspend(struct ata_port *ap) */ static void ata_eh_handle_port_resume(struct ata_port *ap) { + struct ata_link *link; + struct ata_device *dev; unsigned long flags; int rc = 0; @@ -3508,6 +3523,17 @@ static void ata_eh_handle_port_resume(struct ata_port *ap) WARN_ON(!(ap->pflags & ATA_PFLAG_SUSPENDED)); + /* + * Error timestamps are in jiffies which doesn't run while + * suspended and PHY events during resume isn't too uncommon. + * When the two are combined, it can lead to unnecessary speed + * downs if the machine is suspended and resumed repeatedly. + * Clear error history. + */ + ata_for_each_link(link, ap, HOST_FIRST) + ata_for_each_dev(dev, link, ALL) + ata_ering_clear(&dev->ering); + ata_acpi_set_state(ap, PMSG_ON); if (ap->ops->port_resume) diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 2733b0c90b7..68d9132d8f6 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -313,7 +313,7 @@ ata_scsi_em_message_show(struct device *dev, struct device_attribute *attr, return ap->ops->em_show(ap, buf); return -EINVAL; } -DEVICE_ATTR(em_message, S_IRUGO | S_IWUGO, +DEVICE_ATTR(em_message, S_IRUGO | S_IWUSR, ata_scsi_em_message_show, ata_scsi_em_message_store); EXPORT_SYMBOL_GPL(dev_attr_em_message); @@ -366,7 +366,7 @@ ata_scsi_activity_store(struct device *dev, struct device_attribute *attr, } return -EINVAL; } -DEVICE_ATTR(sw_activity, S_IWUGO | S_IRUGO, ata_scsi_activity_show, +DEVICE_ATTR(sw_activity, S_IWUSR | S_IRUGO, ata_scsi_activity_show, ata_scsi_activity_store); EXPORT_SYMBOL_GPL(dev_attr_sw_activity); diff --git a/drivers/ata/pata_pdc202xx_old.c b/drivers/ata/pata_pdc202xx_old.c index 5fedb3d4032..2f3c9bed63d 100644 --- a/drivers/ata/pata_pdc202xx_old.c +++ b/drivers/ata/pata_pdc202xx_old.c @@ -2,7 +2,7 @@ * pata_pdc202xx_old.c - Promise PDC202xx PATA for new ATA layer * (C) 2005 Red Hat Inc * Alan Cox <alan@lxorguk.ukuu.org.uk> - * (C) 2007 Bartlomiej Zolnierkiewicz + * (C) 2007,2009 Bartlomiej Zolnierkiewicz * * Based in part on linux/drivers/ide/pci/pdc202xx_old.c * @@ -158,7 +158,7 @@ static void pdc2026x_bmdma_start(struct ata_queued_cmd *qc) u32 len; /* Check we keep host level locking here */ - if (adev->dma_mode >= XFER_UDMA_2) + if (adev->dma_mode > XFER_UDMA_2) iowrite8(ioread8(clock) | sel66, clock); else iowrite8(ioread8(clock) & ~sel66, clock); @@ -212,7 +212,7 @@ static void pdc2026x_bmdma_stop(struct ata_queued_cmd *qc) iowrite8(ioread8(clock) & ~sel66, clock); } /* Flip back to 33Mhz for PIO */ - if (adev->dma_mode >= XFER_UDMA_2) + if (adev->dma_mode > XFER_UDMA_2) iowrite8(ioread8(clock) & ~sel66, clock); ata_bmdma_stop(qc); pdc202xx_set_piomode(ap, adev); diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index 870dcfd8235..23714aefb82 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -293,6 +293,10 @@ enum { FISCFG_WAIT_DEV_ERR = (1 << 8), /* wait for host on DevErr */ FISCFG_SINGLE_SYNC = (1 << 16), /* SYNC on DMA activation */ + PHY_MODE9_GEN2 = 0x398, + PHY_MODE9_GEN1 = 0x39c, + PHYCFG_OFS = 0x3a0, /* only in 65n devices */ + MV5_PHY_MODE = 0x74, MV5_LTMODE = 0x30, MV5_PHY_CTL = 0x0C, @@ -609,6 +613,8 @@ static int mv_soc_reset_hc(struct mv_host_priv *hpriv, static void mv_soc_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio); static void mv_soc_reset_bus(struct ata_host *host, void __iomem *mmio); +static void mv_soc_65n_phy_errata(struct mv_host_priv *hpriv, + void __iomem *mmio, unsigned int port); static void mv_reset_pci_bus(struct ata_host *host, void __iomem *mmio); static void mv_reset_channel(struct mv_host_priv *hpriv, void __iomem *mmio, unsigned int port_no); @@ -807,6 +813,14 @@ static const struct mv_hw_ops mv_soc_ops = { .reset_bus = mv_soc_reset_bus, }; +static const struct mv_hw_ops mv_soc_65n_ops = { + .phy_errata = mv_soc_65n_phy_errata, + .enable_leds = mv_soc_enable_leds, + .reset_hc = mv_soc_reset_hc, + .reset_flash = mv_soc_reset_flash, + .reset_bus = mv_soc_reset_bus, +}; + /* * Functions */ @@ -3397,6 +3411,53 @@ static void mv_soc_reset_bus(struct ata_host *host, void __iomem *mmio) return; } +static void mv_soc_65n_phy_errata(struct mv_host_priv *hpriv, + void __iomem *mmio, unsigned int port) +{ + void __iomem *port_mmio = mv_port_base(mmio, port); + u32 reg; + + reg = readl(port_mmio + PHY_MODE3); + reg &= ~(0x3 << 27); /* SELMUPF (bits 28:27) to 1 */ + reg |= (0x1 << 27); + reg &= ~(0x3 << 29); /* SELMUPI (bits 30:29) to 1 */ + reg |= (0x1 << 29); + writel(reg, port_mmio + PHY_MODE3); + + reg = readl(port_mmio + PHY_MODE4); + reg &= ~0x1; /* SATU_OD8 (bit 0) to 0, reserved bit 16 must be set */ + reg |= (0x1 << 16); + writel(reg, port_mmio + PHY_MODE4); + + reg = readl(port_mmio + PHY_MODE9_GEN2); + reg &= ~0xf; /* TXAMP[3:0] (bits 3:0) to 8 */ + reg |= 0x8; + reg &= ~(0x1 << 14); /* TXAMP[4] (bit 14) to 0 */ + writel(reg, port_mmio + PHY_MODE9_GEN2); + + reg = readl(port_mmio + PHY_MODE9_GEN1); + reg &= ~0xf; /* TXAMP[3:0] (bits 3:0) to 8 */ + reg |= 0x8; + reg &= ~(0x1 << 14); /* TXAMP[4] (bit 14) to 0 */ + writel(reg, port_mmio + PHY_MODE9_GEN1); +} + +/** + * soc_is_65 - check if the soc is 65 nano device + * + * Detect the type of the SoC, this is done by reading the PHYCFG_OFS + * register, this register should contain non-zero value and it exists only + * in the 65 nano devices, when reading it from older devices we get 0. + */ +static bool soc_is_65n(struct mv_host_priv *hpriv) +{ + void __iomem *port0_mmio = mv_port_base(hpriv->base, 0); + + if (readl(port0_mmio + PHYCFG_OFS)) + return true; + return false; +} + static void mv_setup_ifcfg(void __iomem *port_mmio, int want_gen2i) { u32 ifcfg = readl(port_mmio + SATA_IFCFG); @@ -3737,7 +3798,10 @@ static int mv_chip_id(struct ata_host *host, unsigned int board_idx) } break; case chip_soc: - hpriv->ops = &mv_soc_ops; + if (soc_is_65n(hpriv)) + hpriv->ops = &mv_soc_65n_ops; + else + hpriv->ops = &mv_soc_ops; hp_flags |= MV_HP_FLAG_SOC | MV_HP_GEN_IIE | MV_HP_ERRATA_60X1C0; break; @@ -3800,7 +3864,8 @@ static int mv_init_host(struct ata_host *host, unsigned int board_idx) n_hc = mv_get_hc_count(host->ports[0]->flags); for (port = 0; port < host->n_ports; port++) - hpriv->ops->read_preamp(hpriv, port, mmio); + if (hpriv->ops->read_preamp) + hpriv->ops->read_preamp(hpriv, port, mmio); rc = hpriv->ops->reset_hc(hpriv, mmio, n_hc); if (rc) diff --git a/drivers/base/iommu.c b/drivers/base/iommu.c index 9f0e672f4be..8ad4ffea692 100644 --- a/drivers/base/iommu.c +++ b/drivers/base/iommu.c @@ -18,6 +18,8 @@ #include <linux/bug.h> #include <linux/types.h> +#include <linux/module.h> +#include <linux/slab.h> #include <linux/errno.h> #include <linux/iommu.h> diff --git a/drivers/base/platform.c b/drivers/base/platform.c index b5b6c973a2e..8b4708e0624 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -217,7 +217,6 @@ int platform_device_add_data(struct platform_device *pdev, const void *data, if (d) { memcpy(d, data, size); pdev->dev.platform_data = d; - pdev->platform_data = d; } return d ? 0 : -ENOMEM; } @@ -247,21 +246,6 @@ int platform_device_add(struct platform_device *pdev) else dev_set_name(&pdev->dev, pdev->name); - /* We will remove platform_data field from struct device - * if all platform devices pass its platform specific data - * from platform_device. The conversion is going to be a - * long time, so we allow the two cases coexist to make - * this kind of fix more easily*/ - if (pdev->platform_data && pdev->dev.platform_data) { - printk(KERN_ERR - "%s: use which platform_data?\n", - dev_name(&pdev->dev)); - } else if (pdev->platform_data) { - pdev->dev.platform_data = pdev->platform_data; - } else if (pdev->dev.platform_data) { - pdev->platform_data = pdev->dev.platform_data; - } - for (i = 0; i < pdev->num_resources; i++) { struct resource *p, *r = &pdev->resource[i]; @@ -1028,7 +1012,7 @@ static __initdata LIST_HEAD(early_platform_device_list); /** * early_platform_driver_register - * @edrv: early_platform driver structure + * @epdrv: early_platform driver structure * @buf: string passed from early_param() */ int __init early_platform_driver_register(struct early_platform_driver *epdrv, @@ -1112,7 +1096,7 @@ void __init early_platform_driver_register_all(char *class_str) /** * early_platform_match - * @edrv: early platform driver structure + * @epdrv: early platform driver structure * @id: id to match against */ static __init struct platform_device * @@ -1130,7 +1114,7 @@ early_platform_match(struct early_platform_driver *epdrv, int id) /** * early_platform_left - * @edrv: early platform driver structure + * @epdrv: early platform driver structure * @id: return true if id or above exists */ static __init int early_platform_left(struct early_platform_driver *epdrv, diff --git a/drivers/char/random.c b/drivers/char/random.c index f824ef8a927..b2ced39d76b 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -1665,15 +1665,20 @@ EXPORT_SYMBOL(secure_dccp_sequence_number); * value is not cryptographically secure but for several uses the cost of * depleting entropy is too high */ +DEFINE_PER_CPU(__u32 [4], get_random_int_hash); unsigned int get_random_int(void) { - /* - * Use IP's RNG. It suits our purpose perfectly: it re-keys itself - * every second, from the entropy pool (and thus creates a limited - * drain on it), and uses halfMD4Transform within the second. We - * also mix it with jiffies and the PID: - */ - return secure_ip_id((__force __be32)(current->pid + jiffies)); + struct keydata *keyptr; + __u32 *hash = get_cpu_var(get_random_int_hash); + int ret; + + keyptr = get_keyptr(); + hash[0] += current->pid + jiffies + get_cycles() + (int)(long)&ret; + + ret = half_md4_transform(hash, keyptr->secret); + put_cpu_var(get_random_int_hash); + + return ret; } /* diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c index a2dee0eb6da..e6ce632a393 100644 --- a/drivers/char/vt_ioctl.c +++ b/drivers/char/vt_ioctl.c @@ -400,6 +400,9 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, case KIOCSOUND: if (!perm) goto eperm; + /* FIXME: This is an old broken API but we need to keep it + supported and somehow separate the historic advertised + tick rate from any real one */ if (arg) arg = CLOCK_TICK_RATE / arg; kd_mksound(arg, 0); @@ -417,6 +420,9 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, */ ticks = HZ * ((arg >> 16) & 0xffff) / 1000; count = ticks ? (arg & 0xffff) : 0; + /* FIXME: This is an old broken API but we need to keep it + supported and somehow separate the historic advertised + tick rate from any real one */ if (count) count = CLOCK_TICK_RATE / count; kd_mksound(count, ticks); diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c index 92438e9dacc..5a87384ea4f 100644 --- a/drivers/dma/dmaengine.c +++ b/drivers/dma/dmaengine.c @@ -804,11 +804,14 @@ dma_async_memcpy_buf_to_buf(struct dma_chan *chan, void *dest, dma_addr_t dma_dest, dma_src; dma_cookie_t cookie; int cpu; + unsigned long flags; dma_src = dma_map_single(dev->dev, src, len, DMA_TO_DEVICE); dma_dest = dma_map_single(dev->dev, dest, len, DMA_FROM_DEVICE); - tx = dev->device_prep_dma_memcpy(chan, dma_dest, dma_src, len, - DMA_CTRL_ACK); + flags = DMA_CTRL_ACK | + DMA_COMPL_SRC_UNMAP_SINGLE | + DMA_COMPL_DEST_UNMAP_SINGLE; + tx = dev->device_prep_dma_memcpy(chan, dma_dest, dma_src, len, flags); if (!tx) { dma_unmap_single(dev->dev, dma_src, len, DMA_TO_DEVICE); @@ -850,11 +853,12 @@ dma_async_memcpy_buf_to_pg(struct dma_chan *chan, struct page *page, dma_addr_t dma_dest, dma_src; dma_cookie_t cookie; int cpu; + unsigned long flags; dma_src = dma_map_single(dev->dev, kdata, len, DMA_TO_DEVICE); dma_dest = dma_map_page(dev->dev, page, offset, len, DMA_FROM_DEVICE); - tx = dev->device_prep_dma_memcpy(chan, dma_dest, dma_src, len, - DMA_CTRL_ACK); + flags = DMA_CTRL_ACK | DMA_COMPL_SRC_UNMAP_SINGLE; + tx = dev->device_prep_dma_memcpy(chan, dma_dest, dma_src, len, flags); if (!tx) { dma_unmap_single(dev->dev, dma_src, len, DMA_TO_DEVICE); @@ -898,12 +902,13 @@ dma_async_memcpy_pg_to_pg(struct dma_chan *chan, struct page *dest_pg, dma_addr_t dma_dest, dma_src; dma_cookie_t cookie; int cpu; + unsigned long flags; dma_src = dma_map_page(dev->dev, src_pg, src_off, len, DMA_TO_DEVICE); dma_dest = dma_map_page(dev->dev, dest_pg, dest_off, len, DMA_FROM_DEVICE); - tx = dev->device_prep_dma_memcpy(chan, dma_dest, dma_src, len, - DMA_CTRL_ACK); + flags = DMA_CTRL_ACK; + tx = dev->device_prep_dma_memcpy(chan, dma_dest, dma_src, len, flags); if (!tx) { dma_unmap_page(dev->dev, dma_src, len, DMA_TO_DEVICE); diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c index a27c0fb1bc1..fb7da5141e9 100644 --- a/drivers/dma/dmatest.c +++ b/drivers/dma/dmatest.c @@ -531,9 +531,7 @@ static int __init dmatest_init(void) chan = dma_request_channel(mask, filter, NULL); if (chan) { err = dmatest_add_channel(chan); - if (err == 0) - continue; - else { + if (err) { dma_release_channel(chan); break; /* add_channel failed, punt */ } diff --git a/drivers/dma/ioat_dma.c b/drivers/dma/ioat_dma.c index e4fc33c1c32..1955ee8d6d2 100644 --- a/drivers/dma/ioat_dma.c +++ b/drivers/dma/ioat_dma.c @@ -1063,22 +1063,31 @@ static void ioat_dma_cleanup_tasklet(unsigned long data) static void ioat_dma_unmap(struct ioat_dma_chan *ioat_chan, struct ioat_desc_sw *desc) { - /* - * yes we are unmapping both _page and _single - * alloc'd regions with unmap_page. Is this - * *really* that bad? - */ - if (!(desc->async_tx.flags & DMA_COMPL_SKIP_DEST_UNMAP)) - pci_unmap_page(ioat_chan->device->pdev, - pci_unmap_addr(desc, dst), - pci_unmap_len(desc, len), - PCI_DMA_FROMDEVICE); - - if (!(desc->async_tx.flags & DMA_COMPL_SKIP_SRC_UNMAP)) - pci_unmap_page(ioat_chan->device->pdev, - pci_unmap_addr(desc, src), - pci_unmap_len(desc, len), - PCI_DMA_TODEVICE); + if (!(desc->async_tx.flags & DMA_COMPL_SKIP_DEST_UNMAP)) { + if (desc->async_tx.flags & DMA_COMPL_DEST_UNMAP_SINGLE) + pci_unmap_single(ioat_chan->device->pdev, + pci_unmap_addr(desc, dst), + pci_unmap_len(desc, len), + PCI_DMA_FROMDEVICE); + else + pci_unmap_page(ioat_chan->device->pdev, + pci_unmap_addr(desc, dst), + pci_unmap_len(desc, len), + PCI_DMA_FROMDEVICE); + } + + if (!(desc->async_tx.flags & DMA_COMPL_SKIP_SRC_UNMAP)) { + if (desc->async_tx.flags & DMA_COMPL_SRC_UNMAP_SINGLE) + pci_unmap_single(ioat_chan->device->pdev, + pci_unmap_addr(desc, src), + pci_unmap_len(desc, len), + PCI_DMA_TODEVICE); + else + pci_unmap_page(ioat_chan->device->pdev, + pci_unmap_addr(desc, src), + pci_unmap_len(desc, len), + PCI_DMA_TODEVICE); + } } /** @@ -1363,6 +1372,7 @@ static int ioat_dma_self_test(struct ioatdma_device *device) int err = 0; struct completion cmp; unsigned long tmo; + unsigned long flags; src = kzalloc(sizeof(u8) * IOAT_TEST_SIZE, GFP_KERNEL); if (!src) @@ -1392,8 +1402,9 @@ static int ioat_dma_self_test(struct ioatdma_device *device) DMA_TO_DEVICE); dma_dest = dma_map_single(dma_chan->device->dev, dest, IOAT_TEST_SIZE, DMA_FROM_DEVICE); + flags = DMA_COMPL_SRC_UNMAP_SINGLE | DMA_COMPL_DEST_UNMAP_SINGLE; tx = device->common.device_prep_dma_memcpy(dma_chan, dma_dest, dma_src, - IOAT_TEST_SIZE, 0); + IOAT_TEST_SIZE, flags); if (!tx) { dev_err(&device->pdev->dev, "Self-test prep failed, disabling\n"); diff --git a/drivers/dma/ipu/ipu_idmac.c b/drivers/dma/ipu/ipu_idmac.c index e202a6ce557..9a5bc1a7389 100644 --- a/drivers/dma/ipu/ipu_idmac.c +++ b/drivers/dma/ipu/ipu_idmac.c @@ -1272,7 +1272,8 @@ static irqreturn_t idmac_interrupt(int irq, void *dev_id) /* Other interrupts do not interfere with this channel */ spin_lock(&ichan->lock); if (unlikely(chan_id != IDMAC_SDC_0 && chan_id != IDMAC_SDC_1 && - ((curbuf >> chan_id) & 1) == ichan->active_buffer)) { + ((curbuf >> chan_id) & 1) == ichan->active_buffer && + !list_is_last(ichan->queue.next, &ichan->queue))) { int i = 100; /* This doesn't help. See comment in ipu_disable_channel() */ @@ -1547,7 +1548,7 @@ static irqreturn_t ic_sof_irq(int irq, void *dev_id) struct idmac_channel *ichan = dev_id; printk(KERN_DEBUG "Got SOF IRQ %d on Channel %d\n", irq, ichan->dma_chan.chan_id); - disable_irq(irq); + disable_irq_nosync(irq); return IRQ_HANDLED; } @@ -1556,7 +1557,7 @@ static irqreturn_t ic_eof_irq(int irq, void *dev_id) struct idmac_channel *ichan = dev_id; printk(KERN_DEBUG "Got EOF IRQ %d on Channel %d\n", irq, ichan->dma_chan.chan_id); - disable_irq(irq); + disable_irq_nosync(irq); return IRQ_HANDLED; } diff --git a/drivers/firmware/iscsi_ibft.c b/drivers/firmware/iscsi_ibft.c index 7b7ddc2d51c..420a96e7f2d 100644 --- a/drivers/firmware/iscsi_ibft.c +++ b/drivers/firmware/iscsi_ibft.c @@ -754,11 +754,11 @@ static int __init ibft_check_nic_for(struct ibft_nic *nic, int entry) rc = 1; break; case ibft_eth_ip_addr: - if (!memcmp(nic->dhcp, nulls, sizeof(nic->dhcp))) + if (memcmp(nic->ip_addr, nulls, sizeof(nic->ip_addr))) rc = 1; break; case ibft_eth_subnet_mask: - if (!memcmp(nic->dhcp, nulls, sizeof(nic->dhcp))) + if (nic->subnet_mask_prefix) rc = 1; break; case ibft_eth_origin: diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index 3a22eb9be37..17b24c580c0 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -71,6 +71,7 @@ config DRM_I915 select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT select FB + select FRAMEBUFFER_CONSOLE if !EMBEDDED tristate "i915 driver" help Choose this option if you have a system that has Intel 830M, 845G, diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index a04639dc633..45890447fee 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -561,7 +561,6 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, int saved_x, saved_y; struct drm_encoder *encoder; bool ret = true; - bool depth_changed, bpp_changed; adjusted_mode = drm_mode_duplicate(dev, mode); @@ -570,15 +569,6 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, if (!crtc->enabled) return true; - if (old_fb && crtc->fb) { - depth_changed = (old_fb->depth != crtc->fb->depth); - bpp_changed = (old_fb->bits_per_pixel != - crtc->fb->bits_per_pixel); - } else { - depth_changed = true; - bpp_changed = true; - } - saved_mode = crtc->mode; saved_x = crtc->x; saved_y = crtc->y; @@ -590,15 +580,6 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, crtc->x = x; crtc->y = y; - if (drm_mode_equal(&saved_mode, &crtc->mode)) { - if (saved_x != crtc->x || saved_y != crtc->y || - depth_changed || bpp_changed) { - ret = !crtc_funcs->mode_set_base(crtc, crtc->x, crtc->y, - old_fb); - goto done; - } - } - /* Pass our mode to the connectors and the CRTC to give them a chance to * adjust it according to limitations or connector properties, and also * a chance to reject the mode entirely. diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index c4ada8b6295..f01def16a66 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -456,7 +456,8 @@ int drm_ioctl(struct inode *inode, struct file *filp, retcode = -EINVAL; } else if (((ioctl->flags & DRM_ROOT_ONLY) && !capable(CAP_SYS_ADMIN)) || ((ioctl->flags & DRM_AUTH) && !file_priv->authenticated) || - ((ioctl->flags & DRM_MASTER) && !file_priv->is_master)) { + ((ioctl->flags & DRM_MASTER) && !file_priv->is_master) || + (!(ioctl->flags & DRM_CONTROL_ALLOW) && (file_priv->minor->type == DRM_MINOR_CONTROL))) { retcode = -EACCES; } else { if (cmd & (IOC_IN | IOC_OUT)) { diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c index ef878615c49..b9631e3a1ea 100644 --- a/drivers/gpu/drm/drm_stub.c +++ b/drivers/gpu/drm/drm_stub.c @@ -402,14 +402,14 @@ int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent, if (dev->driver->load) { ret = dev->driver->load(dev, ent->driver_data); if (ret) - goto err_g3; + goto err_g4; } /* setup the grouping for the legacy output */ if (drm_core_check_feature(dev, DRIVER_MODESET)) { ret = drm_mode_group_init_legacy_group(dev, &dev->primary->mode_group); if (ret) - goto err_g3; + goto err_g4; } list_add_tail(&dev->driver_item, &driver->device_list); @@ -420,8 +420,11 @@ int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent, return 0; -err_g3: +err_g4: drm_put_minor(&dev->primary); +err_g3: + if (drm_core_check_feature(dev, DRIVER_MODESET)) + drm_put_minor(&dev->control); err_g2: pci_disable_device(pdev); err_g1: @@ -502,11 +505,11 @@ void drm_put_dev(struct drm_device *dev) dev->agp = NULL; } - drm_ht_remove(&dev->map_hash); - drm_ctxbitmap_cleanup(dev); - list_for_each_entry_safe(r_list, list_temp, &dev->maplist, head) drm_rmmap(dev, r_list->map); + drm_ht_remove(&dev->map_hash); + + drm_ctxbitmap_cleanup(dev); if (drm_core_check_feature(dev, DRIVER_MODESET)) drm_put_minor(&dev->control); diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c index 022876ae34f..8f9372921f8 100644 --- a/drivers/gpu/drm/drm_sysfs.c +++ b/drivers/gpu/drm/drm_sysfs.c @@ -489,9 +489,7 @@ int drm_sysfs_device_add(struct drm_minor *minor) return 0; - device_unregister(&minor->kdev); err_out: - return err; } diff --git a/drivers/gpu/drm/r128/r128_cce.c b/drivers/gpu/drm/r128/r128_cce.c index 32de4cedc36..077c0455a6b 100644 --- a/drivers/gpu/drm/r128/r128_cce.c +++ b/drivers/gpu/drm/r128/r128_cce.c @@ -511,9 +511,9 @@ static int r128_do_init_cce(struct drm_device * dev, drm_r128_init_t * init) #if __OS_HAS_AGP if (!dev_priv->is_pci) { - drm_core_ioremap(dev_priv->cce_ring, dev); - drm_core_ioremap(dev_priv->ring_rptr, dev); - drm_core_ioremap(dev->agp_buffer_map, dev); + drm_core_ioremap_wc(dev_priv->cce_ring, dev); + drm_core_ioremap_wc(dev_priv->ring_rptr, dev); + drm_core_ioremap_wc(dev->agp_buffer_map, dev); if (!dev_priv->cce_ring->handle || !dev_priv->ring_rptr->handle || !dev->agp_buffer_map->handle) { diff --git a/drivers/gpu/drm/radeon/radeon_drv.h b/drivers/gpu/drm/radeon/radeon_drv.h index ed4d27e6ee6..8071d965f14 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.h +++ b/drivers/gpu/drm/radeon/radeon_drv.h @@ -99,9 +99,10 @@ * 1.27- Add support for IGP GART * 1.28- Add support for VBL on CRTC2 * 1.29- R500 3D cmd buffer support + * 1.30- Add support for occlusion queries */ #define DRIVER_MAJOR 1 -#define DRIVER_MINOR 29 +#define DRIVER_MINOR 30 #define DRIVER_PATCHLEVEL 0 /* diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c index 7359d9d88e4..acbce5745b0 100644 --- a/drivers/hid/hid-apple.c +++ b/drivers/hid/hid-apple.c @@ -151,7 +151,7 @@ static int hidinput_apple_event(struct hid_device *hid, struct input_dev *input, if (fnmode) { int do_translate; - trans = apple_find_translation((hid->product < 0x220 || + trans = apple_find_translation((hid->product < 0x21d || hid->product >= 0x300) ? powerbook_fn_keys : apple_fn_keys, usage->code); diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 5746a5903bc..8551693d645 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1293,6 +1293,7 @@ static const struct hid_device_id hid_blacklist[] = { { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FORCE3D_PRO) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G25_WHEEL) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2) }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_SIDEWINDER_GV) }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_NE4K) }, @@ -1824,6 +1825,9 @@ int hid_check_keys_pressed(struct hid_device *hid) struct hid_input *hidinput; int i; + if (!(hid->claimed & HID_CLAIMED_INPUT)) + return 0; + list_for_each_entry(hidinput, &hid->inputs, list) { for (i = 0; i < BITS_TO_LONGS(KEY_MAX); i++) if (hidinput->input->key[i]) diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index bdeda4c7cc1..4d5ee2bbc62 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -113,6 +113,11 @@ #define USB_VENDOR_ID_BERKSHIRE 0x0c98 #define USB_DEVICE_ID_BERKSHIRE_PCWD 0x1140 +#define USB_VENDOR_ID_CH 0x068e +#define USB_DEVICE_ID_CH_PRO_PEDALS 0x00f2 +#define USB_DEVICE_ID_CH_COMBATSTICK 0x00f4 +#define USB_DEVICE_ID_CH_FLIGHT_SIM_YOKE 0x00ff + #define USB_VENDOR_ID_CHERRY 0x046a #define USB_DEVICE_ID_CHERRY_CYMOTION 0x0023 @@ -292,6 +297,7 @@ #define USB_DEVICE_ID_LOGITECH_FORCE3D_PRO 0xc286 #define USB_DEVICE_ID_LOGITECH_WHEEL 0xc294 #define USB_DEVICE_ID_LOGITECH_MOMO_WHEEL 0xc295 +#define USB_DEVICE_ID_LOGITECH_G25_WHEEL 0xc299 #define USB_DEVICE_ID_LOGITECH_ELITE_KBD 0xc30a #define USB_DEVICE_ID_S510_RECEIVER 0xc50c #define USB_DEVICE_ID_S510_RECEIVER_2 0xc517 diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c index 7b80cb69498..7afbaa0efd1 100644 --- a/drivers/hid/hid-lg.c +++ b/drivers/hid/hid-lg.c @@ -297,6 +297,8 @@ static const struct hid_device_id lg_devices[] = { .driver_data = LG_FF }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2), .driver_data = LG_FF }, + { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G25_WHEEL), + .driver_data = LG_FF }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2), .driver_data = LG_FF2 }, { } diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c index e263d473117..00ccf4b1985 100644 --- a/drivers/hid/hidraw.c +++ b/drivers/hid/hidraw.c @@ -285,8 +285,10 @@ static long hidraw_ioctl(struct file *file, unsigned int cmd, if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGRAWNAME(0))) { int len; - if (!hid->name) - return 0; + if (!hid->name) { + ret = 0; + break; + } len = strlen(hid->name) + 1; if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); @@ -297,8 +299,10 @@ static long hidraw_ioctl(struct file *file, unsigned int cmd, if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGRAWPHYS(0))) { int len; - if (!hid->phys) - return 0; + if (!hid->phys) { + ret = 0; + break; + } len = strlen(hid->phys) + 1; if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index 4306cb1b8ce..ac8049b5f1e 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c @@ -662,8 +662,8 @@ void usbhid_close(struct hid_device *hid) spin_lock_irq(&usbhid->lock); if (!--hid->open) { spin_unlock_irq(&usbhid->lock); + hid_cancel_delayed_stuff(usbhid); usb_kill_urb(usbhid->urbin); - flush_scheduled_work(); usbhid->intf->needs_remote_wakeup = 0; } else { spin_unlock_irq(&usbhid->lock); @@ -898,7 +898,7 @@ static int usbhid_parse(struct hid_device *hid) goto err; } - hid->quirks = quirks; + hid->quirks |= quirks; return 0; err: diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index 4391717d251..d8f7423f363 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c @@ -50,6 +50,9 @@ static const struct hid_blacklist { { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM, HID_QUIRK_NOGET }, { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM, HID_QUIRK_NOGET }, { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC, HID_QUIRK_NOGET }, + { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_COMBATSTICK, HID_QUIRK_NOGET }, + { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_FLIGHT_SIM_YOKE, HID_QUIRK_NOGET }, + { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_PRO_PEDALS, HID_QUIRK_NOGET }, { USB_VENDOR_ID_DMI, USB_DEVICE_ID_DMI_ENC, HID_QUIRK_NOGET }, { USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET }, { USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET }, diff --git a/drivers/hwmon/asus_atk0110.c b/drivers/hwmon/asus_atk0110.c index 0897edef257..bff0103610c 100644 --- a/drivers/hwmon/asus_atk0110.c +++ b/drivers/hwmon/asus_atk0110.c @@ -348,6 +348,7 @@ static int validate_hwmon_pack(struct atk_data *data, union acpi_object *obj) return 0; } +#ifdef DEBUG static char const *atk_sensor_type(union acpi_object *flags) { u64 type = flags->integer.value & ATK_TYPE_MASK; @@ -370,6 +371,7 @@ static char const *atk_sensor_type(union acpi_object *flags) return what; } +#endif static void atk_print_sensor(struct atk_data *data, union acpi_object *obj) { diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c index dbfb30c588d..0bdab959b73 100644 --- a/drivers/hwmon/w83781d.c +++ b/drivers/hwmon/w83781d.c @@ -1462,7 +1462,8 @@ static struct w83781d_data *w83781d_update_device(struct device *dev) data->pwm[i] = w83781d_read_value(data, W83781D_REG_PWM[i]); - if ((data->type != w83782d || !client->driver) + /* Only W83782D on SMBus has PWM3 and PWM4 */ + if ((data->type != w83782d || !client) && i == 1) break; } diff --git a/drivers/i2c/algos/i2c-algo-bit.c b/drivers/i2c/algos/i2c-algo-bit.c index d420cc5f563..e25e13980af 100644 --- a/drivers/i2c/algos/i2c-algo-bit.c +++ b/drivers/i2c/algos/i2c-algo-bit.c @@ -104,7 +104,7 @@ static int sclhi(struct i2c_algo_bit_data *adap) * chips may hold it low ("clock stretching") while they * are processing data internally. */ - if (time_after_eq(jiffies, start + adap->timeout)) + if (time_after(jiffies, start + adap->timeout)) return -ETIMEDOUT; cond_resched(); } diff --git a/drivers/i2c/algos/i2c-algo-pca.c b/drivers/i2c/algos/i2c-algo-pca.c index 6318f7ddc1d..78d42aae008 100644 --- a/drivers/i2c/algos/i2c-algo-pca.c +++ b/drivers/i2c/algos/i2c-algo-pca.c @@ -287,10 +287,21 @@ static int pca_xfer(struct i2c_adapter *i2c_adap, case 0x30: /* Data byte in I2CDAT has been transmitted; NOT ACK has been received */ DEB2("NOT ACK received after data byte\n"); + pca_stop(adap); goto out; case 0x38: /* Arbitration lost during SLA+W, SLA+R or data bytes */ DEB2("Arbitration lost\n"); + /* + * The PCA9564 data sheet (2006-09-01) says "A + * START condition will be transmitted when the + * bus becomes free (STOP or SCL and SDA high)" + * when the STA bit is set (p. 11). + * + * In case this won't work, try pca_reset() + * instead. + */ + pca_start(adap); goto out; case 0x58: /* Data byte has been received; NOT ACK has been returned */ diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index a48c8aee021..f1c6ca7e285 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -467,7 +467,7 @@ config I2C_PXA_SLAVE config I2C_S3C2410 tristate "S3C2410 I2C Driver" - depends on ARCH_S3C2410 + depends on ARCH_S3C2410 || ARCH_S3C64XX help Say Y here to include support for I2C controller in the Samsung S3C2410 based System-on-Chip devices. diff --git a/drivers/i2c/busses/i2c-ali1535.c b/drivers/i2c/busses/i2c-ali1535.c index 981e080b32a..d108450df06 100644 --- a/drivers/i2c/busses/i2c-ali1535.c +++ b/drivers/i2c/busses/i2c-ali1535.c @@ -284,7 +284,7 @@ static int ali1535_transaction(struct i2c_adapter *adap) && (timeout++ < MAX_TIMEOUT)); /* If the SMBus is still busy, we give up */ - if (timeout >= MAX_TIMEOUT) { + if (timeout > MAX_TIMEOUT) { result = -ETIMEDOUT; dev_err(&adap->dev, "SMBus Timeout!\n"); } diff --git a/drivers/i2c/busses/i2c-ali15x3.c b/drivers/i2c/busses/i2c-ali15x3.c index 39066dee46e..d627fceb790 100644 --- a/drivers/i2c/busses/i2c-ali15x3.c +++ b/drivers/i2c/busses/i2c-ali15x3.c @@ -306,7 +306,7 @@ static int ali15x3_transaction(struct i2c_adapter *adap) && (timeout++ < MAX_TIMEOUT)); /* If the SMBus is still busy, we give up */ - if (timeout >= MAX_TIMEOUT) { + if (timeout > MAX_TIMEOUT) { result = -ETIMEDOUT; dev_err(&adap->dev, "SMBus Timeout!\n"); } diff --git a/drivers/i2c/busses/i2c-amd756.c b/drivers/i2c/busses/i2c-amd756.c index 220f4a1eee1..f7d6fe9c49b 100644 --- a/drivers/i2c/busses/i2c-amd756.c +++ b/drivers/i2c/busses/i2c-amd756.c @@ -126,7 +126,7 @@ static int amd756_transaction(struct i2c_adapter *adap) } while ((temp & (GS_HST_STS | GS_SMB_STS)) && (timeout++ < MAX_TIMEOUT)); /* If the SMBus is still busy, we give up */ - if (timeout >= MAX_TIMEOUT) { + if (timeout > MAX_TIMEOUT) { dev_dbg(&adap->dev, "Busy wait timeout (%04x)\n", temp); goto abort; } @@ -143,7 +143,7 @@ static int amd756_transaction(struct i2c_adapter *adap) } while ((temp & GS_HST_STS) && (timeout++ < MAX_TIMEOUT)); /* If the SMBus is still busy, we give up */ - if (timeout >= MAX_TIMEOUT) { + if (timeout > MAX_TIMEOUT) { dev_dbg(&adap->dev, "Completion timeout!\n"); goto abort; } diff --git a/drivers/i2c/busses/i2c-cpm.c b/drivers/i2c/busses/i2c-cpm.c index 3fcf78e906d..b5db8b88361 100644 --- a/drivers/i2c/busses/i2c-cpm.c +++ b/drivers/i2c/busses/i2c-cpm.c @@ -531,16 +531,16 @@ static int __devinit cpm_i2c_setup(struct cpm_i2c *cpm) rbdf = cpm->rbase; for (i = 0; i < CPM_MAXBD; i++) { - cpm->rxbuf[i] = dma_alloc_coherent( - NULL, CPM_MAX_READ + 1, &cpm->rxdma[i], GFP_KERNEL); + cpm->rxbuf[i] = dma_alloc_coherent(&cpm->ofdev->dev, + CPM_MAX_READ + 1, + &cpm->rxdma[i], GFP_KERNEL); if (!cpm->rxbuf[i]) { ret = -ENOMEM; goto out_muram; } out_be32(&rbdf[i].cbd_bufaddr, ((cpm->rxdma[i] + 1) & ~1)); - cpm->txbuf[i] = (unsigned char *)dma_alloc_coherent( - NULL, CPM_MAX_READ + 1, &cpm->txdma[i], GFP_KERNEL); + cpm->txbuf[i] = (unsigned char *)dma_alloc_coherent(&cpm->ofdev->dev, CPM_MAX_READ + 1, &cpm->txdma[i], GFP_KERNEL); if (!cpm->txbuf[i]) { ret = -ENOMEM; goto out_muram; @@ -585,10 +585,10 @@ static int __devinit cpm_i2c_setup(struct cpm_i2c *cpm) out_muram: for (i = 0; i < CPM_MAXBD; i++) { if (cpm->rxbuf[i]) - dma_free_coherent(NULL, CPM_MAX_READ + 1, + dma_free_coherent(&cpm->ofdev->dev, CPM_MAX_READ + 1, cpm->rxbuf[i], cpm->rxdma[i]); if (cpm->txbuf[i]) - dma_free_coherent(NULL, CPM_MAX_READ + 1, + dma_free_coherent(&cpm->ofdev->dev, CPM_MAX_READ + 1, cpm->txbuf[i], cpm->txdma[i]); } cpm_muram_free(cpm->dp_addr); @@ -619,9 +619,9 @@ static void cpm_i2c_shutdown(struct cpm_i2c *cpm) /* Free all memory */ for (i = 0; i < CPM_MAXBD; i++) { - dma_free_coherent(NULL, CPM_MAX_READ + 1, + dma_free_coherent(&cpm->ofdev->dev, CPM_MAX_READ + 1, cpm->rxbuf[i], cpm->rxdma[i]); - dma_free_coherent(NULL, CPM_MAX_READ + 1, + dma_free_coherent(&cpm->ofdev->dev, CPM_MAX_READ + 1, cpm->txbuf[i], cpm->txdma[i]); } diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index 10411848fd7..9d2c5adf5d4 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -237,7 +237,7 @@ static int i801_transaction(int xact) status = inb_p(SMBHSTSTS); } while ((status & SMBHSTSTS_HOST_BUSY) && (timeout++ < MAX_TIMEOUT)); - result = i801_check_post(status, timeout >= MAX_TIMEOUT); + result = i801_check_post(status, timeout > MAX_TIMEOUT); if (result < 0) return result; @@ -257,9 +257,9 @@ static void i801_wait_hwpec(void) } while ((!(status & SMBHSTSTS_INTR)) && (timeout++ < MAX_TIMEOUT)); - if (timeout >= MAX_TIMEOUT) { + if (timeout > MAX_TIMEOUT) dev_dbg(&I801_dev->dev, "PEC Timeout!\n"); - } + outb_p(status, SMBHSTSTS); } @@ -344,7 +344,7 @@ static int i801_block_transaction_byte_by_byte(union i2c_smbus_data *data, while ((!(status & SMBHSTSTS_BYTE_DONE)) && (timeout++ < MAX_TIMEOUT)); - result = i801_check_post(status, timeout >= MAX_TIMEOUT); + result = i801_check_post(status, timeout > MAX_TIMEOUT); if (result < 0) return result; diff --git a/drivers/i2c/busses/i2c-isch.c b/drivers/i2c/busses/i2c-isch.c index b9c01aa9003..9f6b8e0f863 100644 --- a/drivers/i2c/busses/i2c-isch.c +++ b/drivers/i2c/busses/i2c-isch.c @@ -112,7 +112,7 @@ static int sch_transaction(void) } while ((temp & 0x08) && (timeout++ < MAX_TIMEOUT)); /* If the SMBus is still busy, we give up */ - if (timeout >= MAX_TIMEOUT) { + if (timeout > MAX_TIMEOUT) { dev_err(&sch_adapter.dev, "SMBus Timeout!\n"); result = -ETIMEDOUT; } diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c index 4af5c09f0e8..dd778d7ae04 100644 --- a/drivers/i2c/busses/i2c-mpc.c +++ b/drivers/i2c/busses/i2c-mpc.c @@ -164,7 +164,7 @@ static int i2c_wait(struct mpc_i2c *i2c, unsigned timeout, int writing) return 0; } -#ifdef CONFIG_PPC_52xx +#ifdef CONFIG_PPC_MPC52xx static const struct mpc_i2c_divider mpc_i2c_dividers_52xx[] = { {20, 0x20}, {22, 0x21}, {24, 0x22}, {26, 0x23}, {28, 0x24}, {30, 0x01}, {32, 0x25}, {34, 0x02}, @@ -188,7 +188,7 @@ static const struct mpc_i2c_divider mpc_i2c_dividers_52xx[] = { int mpc_i2c_get_fdr_52xx(struct device_node *node, u32 clock, int prescaler) { - const struct mpc52xx_i2c_divider *div = NULL; + const struct mpc_i2c_divider *div = NULL; unsigned int pvr = mfspr(SPRN_PVR); u32 divider; int i; @@ -203,7 +203,7 @@ int mpc_i2c_get_fdr_52xx(struct device_node *node, u32 clock, int prescaler) * We want to choose an FDR/DFSR that generates an I2C bus speed that * is equal to or lower than the requested speed. */ - for (i = 0; i < ARRAY_SIZE(mpc52xx_i2c_dividers); i++) { + for (i = 0; i < ARRAY_SIZE(mpc_i2c_dividers_52xx); i++) { div = &mpc_i2c_dividers_52xx[i]; /* Old MPC5200 rev A CPUs do not support the high bits */ if (div->fdr & 0xc0 && pvr == 0x80822011) @@ -219,20 +219,23 @@ static void mpc_i2c_setclock_52xx(struct device_node *node, struct mpc_i2c *i2c, u32 clock, u32 prescaler) { - int fdr = mpc52xx_i2c_get_fdr(node, clock, prescaler); + int ret, fdr; + + ret = mpc_i2c_get_fdr_52xx(node, clock, prescaler); + fdr = (ret >= 0) ? ret : 0x3f; /* backward compatibility */ - if (fdr < 0) - fdr = 0x3f; /* backward compatibility */ writeb(fdr & 0xff, i2c->base + MPC_I2C_FDR); - dev_info(i2c->dev, "clock %d Hz (fdr=%d)\n", clock, fdr); + + if (ret >= 0) + dev_info(i2c->dev, "clock %d Hz (fdr=%d)\n", clock, fdr); } -#else /* !CONFIG_PPC_52xx */ +#else /* !CONFIG_PPC_MPC52xx */ static void mpc_i2c_setclock_52xx(struct device_node *node, struct mpc_i2c *i2c, u32 clock, u32 prescaler) { } -#endif /* CONFIG_PPC_52xx*/ +#endif /* CONFIG_PPC_MPC52xx*/ #ifdef CONFIG_FSL_SOC static const struct mpc_i2c_divider mpc_i2c_dividers_8xxx[] = { @@ -321,14 +324,17 @@ static void mpc_i2c_setclock_8xxx(struct device_node *node, struct mpc_i2c *i2c, u32 clock, u32 prescaler) { - int fdr = mpc_i2c_get_fdr_8xxx(node, clock, prescaler); + int ret, fdr; + + ret = mpc_i2c_get_fdr_8xxx(node, clock, prescaler); + fdr = (ret >= 0) ? ret : 0x1031; /* backward compatibility */ - if (fdr < 0) - fdr = 0x1031; /* backward compatibility */ writeb(fdr & 0xff, i2c->base + MPC_I2C_FDR); writeb((fdr >> 8) & 0xff, i2c->base + MPC_I2C_DFSRR); - dev_info(i2c->dev, "clock %d Hz (dfsrr=%d fdr=%d)\n", - clock, fdr >> 8, fdr & 0xff); + + if (ret >= 0) + dev_info(i2c->dev, "clock %d Hz (dfsrr=%d fdr=%d)\n", + clock, fdr >> 8, fdr & 0xff); } #else /* !CONFIG_FSL_SOC */ diff --git a/drivers/i2c/busses/i2c-nforce2.c b/drivers/i2c/busses/i2c-nforce2.c index 2ff4683703a..ec11d1c4e77 100644 --- a/drivers/i2c/busses/i2c-nforce2.c +++ b/drivers/i2c/busses/i2c-nforce2.c @@ -173,7 +173,7 @@ static int nforce2_check_status(struct i2c_adapter *adap) temp = inb_p(NVIDIA_SMB_STS); } while ((!temp) && (timeout++ < MAX_TIMEOUT)); - if (timeout >= MAX_TIMEOUT) { + if (timeout > MAX_TIMEOUT) { dev_dbg(&adap->dev, "SMBus Timeout!\n"); if (smbus->can_abort) nforce2_abort(adap); diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c index c1405c8f6ba..acc7143d965 100644 --- a/drivers/i2c/busses/i2c-pxa.c +++ b/drivers/i2c/busses/i2c-pxa.c @@ -265,10 +265,10 @@ static int i2c_pxa_wait_bus_not_busy(struct pxa_i2c *i2c) show_state(i2c); } - if (timeout <= 0) + if (timeout < 0) show_state(i2c); - return timeout <= 0 ? I2C_RETRY : 0; + return timeout < 0 ? I2C_RETRY : 0; } static int i2c_pxa_wait_master(struct pxa_i2c *i2c) @@ -612,7 +612,7 @@ static int i2c_pxa_pio_set_master(struct pxa_i2c *i2c) show_state(i2c); } - if (timeout <= 0) { + if (timeout < 0) { show_state(i2c); dev_err(&i2c->adap.dev, "i2c_pxa: timeout waiting for bus free\n"); diff --git a/drivers/i2c/busses/i2c-sis5595.c b/drivers/i2c/busses/i2c-sis5595.c index f320ab27da4..139f0c7f12a 100644 --- a/drivers/i2c/busses/i2c-sis5595.c +++ b/drivers/i2c/busses/i2c-sis5595.c @@ -256,7 +256,7 @@ static int sis5595_transaction(struct i2c_adapter *adap) } while (!(temp & 0x40) && (timeout++ < MAX_TIMEOUT)); /* If the SMBus is still busy, we give up */ - if (timeout >= MAX_TIMEOUT) { + if (timeout > MAX_TIMEOUT) { dev_dbg(&adap->dev, "SMBus Timeout!\n"); result = -ETIMEDOUT; } diff --git a/drivers/i2c/busses/i2c-sis630.c b/drivers/i2c/busses/i2c-sis630.c index 50c3610e602..70ca41e90e5 100644 --- a/drivers/i2c/busses/i2c-sis630.c +++ b/drivers/i2c/busses/i2c-sis630.c @@ -173,7 +173,7 @@ static int sis630_transaction_wait(struct i2c_adapter *adap, int size) } while (!(temp & 0x0e) && (timeout++ < MAX_TIMEOUT)); /* If the SMBus is still busy, we give up */ - if (timeout >= MAX_TIMEOUT) { + if (timeout > MAX_TIMEOUT) { dev_dbg(&adap->dev, "SMBus Timeout!\n"); result = -ETIMEDOUT; } diff --git a/drivers/i2c/busses/i2c-sis96x.c b/drivers/i2c/busses/i2c-sis96x.c index 7e1594b4057..8295885b2fd 100644 --- a/drivers/i2c/busses/i2c-sis96x.c +++ b/drivers/i2c/busses/i2c-sis96x.c @@ -132,7 +132,7 @@ static int sis96x_transaction(int size) } while (!(temp & 0x0e) && (timeout++ < MAX_TIMEOUT)); /* If the SMBus is still busy, we give up */ - if (timeout >= MAX_TIMEOUT) { + if (timeout > MAX_TIMEOUT) { dev_dbg(&sis96x_adapter.dev, "SMBus Timeout! (0x%02x)\n", temp); result = -ETIMEDOUT; } diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 3d4e0996976..925eb9e245d 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -312,7 +312,6 @@ static int cdrom_decode_status(ide_drive_t *drive, u8 stat) ide_hwif_t *hwif = drive->hwif; struct request *rq = hwif->rq; int err, sense_key, do_end_request = 0; - u8 quiet = rq->cmd_flags & REQ_QUIET; /* get the IDE error register */ err = ide_read_error(drive); @@ -347,7 +346,7 @@ static int cdrom_decode_status(ide_drive_t *drive, u8 stat) } else { cdrom_saw_media_change(drive); - if (blk_fs_request(rq) && !quiet) + if (blk_fs_request(rq) && !blk_rq_quiet(rq)) printk(KERN_ERR PFX "%s: tray open\n", drive->name); } @@ -382,7 +381,7 @@ static int cdrom_decode_status(ide_drive_t *drive, u8 stat) * No point in retrying after an illegal request or data * protect error. */ - if (!quiet) + if (!blk_rq_quiet(rq)) ide_dump_status(drive, "command error", stat); do_end_request = 1; break; @@ -391,14 +390,14 @@ static int cdrom_decode_status(ide_drive_t *drive, u8 stat) * No point in re-trying a zillion times on a bad sector. * If we got here the error is not correctable. */ - if (!quiet) + if (!blk_rq_quiet(rq)) ide_dump_status(drive, "media error " "(bad sector)", stat); do_end_request = 1; break; case BLANK_CHECK: /* disk appears blank? */ - if (!quiet) + if (!blk_rq_quiet(rq)) ide_dump_status(drive, "media error (blank)", stat); do_end_request = 1; diff --git a/drivers/infiniband/hw/ipath/ipath_fs.c b/drivers/infiniband/hw/ipath/ipath_fs.c index 8dc2bb78160..b3684060465 100644 --- a/drivers/infiniband/hw/ipath/ipath_fs.c +++ b/drivers/infiniband/hw/ipath/ipath_fs.c @@ -347,7 +347,7 @@ static int ipathfs_fill_super(struct super_block *sb, void *data, spin_unlock_irqrestore(&ipath_devs_lock, flags); ret = create_device_files(sb, dd); if (ret) { - deactivate_super(sb); + deactivate_locked_super(sb); goto bail; } spin_lock_irqsave(&ipath_devs_lock, flags); diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c index 13d7674b293..75223f50de5 100644 --- a/drivers/infiniband/ulp/iser/iscsi_iser.c +++ b/drivers/infiniband/ulp/iser/iscsi_iser.c @@ -599,6 +599,7 @@ static struct scsi_host_template iscsi_iser_sht = { .eh_abort_handler = iscsi_eh_abort, .eh_device_reset_handler= iscsi_eh_device_reset, .eh_target_reset_handler= iscsi_eh_target_reset, + .target_alloc = iscsi_target_alloc, .use_clustering = DISABLE_CLUSTERING, .proc_name = "iscsi_iser", .this_id = -1, diff --git a/drivers/input/ff-memless.c b/drivers/input/ff-memless.c index bc4e40f3ede..2d1415e1683 100644 --- a/drivers/input/ff-memless.c +++ b/drivers/input/ff-memless.c @@ -226,7 +226,7 @@ static int get_compatible_type(struct ff_device *ff, int effect_type) */ static void ml_combine_effects(struct ff_effect *effect, struct ml_effect_state *state, - int gain) + unsigned int gain) { struct ff_effect *new = state->effect; unsigned int strong, weak, i; diff --git a/drivers/input/input.c b/drivers/input/input.c index 935a1835de2..e54e002665b 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -29,6 +29,23 @@ MODULE_LICENSE("GPL"); #define INPUT_DEVICES 256 +/* + * EV_ABS events which should not be cached are listed here. + */ +static unsigned int input_abs_bypass_init_data[] __initdata = { + ABS_MT_TOUCH_MAJOR, + ABS_MT_TOUCH_MINOR, + ABS_MT_WIDTH_MAJOR, + ABS_MT_WIDTH_MINOR, + ABS_MT_ORIENTATION, + ABS_MT_POSITION_X, + ABS_MT_POSITION_Y, + ABS_MT_TOOL_TYPE, + ABS_MT_BLOB_ID, + 0 +}; +static unsigned long input_abs_bypass[BITS_TO_LONGS(ABS_CNT)]; + static LIST_HEAD(input_dev_list); static LIST_HEAD(input_handler_list); @@ -161,6 +178,10 @@ static void input_handle_event(struct input_dev *dev, disposition = INPUT_PASS_TO_HANDLERS; } break; + case SYN_MT_REPORT: + dev->sync = 0; + disposition = INPUT_PASS_TO_HANDLERS; + break; } break; @@ -192,6 +213,11 @@ static void input_handle_event(struct input_dev *dev, case EV_ABS: if (is_event_supported(code, dev->absbit, ABS_MAX)) { + if (test_bit(code, input_abs_bypass)) { + disposition = INPUT_PASS_TO_HANDLERS; + break; + } + value = input_defuzz_abs_event(value, dev->abs[code], dev->absfuzz[code]); @@ -1634,10 +1660,20 @@ static const struct file_operations input_fops = { .open = input_open_file, }; +static void __init input_init_abs_bypass(void) +{ + const unsigned int *p; + + for (p = input_abs_bypass_init_data; *p; p++) + input_abs_bypass[BIT_WORD(*p)] |= BIT_MASK(*p); +} + static int __init input_init(void) { int err; + input_init_abs_bypass(); + err = class_register(&input_class); if (err) { printk(KERN_ERR "input: unable to register input_dev class\n"); diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c index 4224f011284..012a5e75399 100644 --- a/drivers/input/joydev.c +++ b/drivers/input/joydev.c @@ -843,7 +843,13 @@ static const struct input_device_id joydev_blacklist[] = { INPUT_DEVICE_ID_MATCH_KEYBIT, .evbit = { BIT_MASK(EV_KEY) }, .keybit = { [BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH) }, - }, /* Avoid itouchpads, touchscreens and tablets */ + }, /* Avoid itouchpads and touchscreens */ + { + .flags = INPUT_DEVICE_ID_MATCH_EVBIT | + INPUT_DEVICE_ID_MATCH_KEYBIT, + .evbit = { BIT_MASK(EV_KEY) }, + .keybit = { [BIT_WORD(BTN_DIGI)] = BIT_MASK(BTN_DIGI) }, + }, /* Avoid tablets, digitisers and similar devices */ { } /* Terminating entry */ }; diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index 444dec07e5d..df3f8aa6811 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c @@ -895,6 +895,13 @@ static unsigned int atkbd_amilo_pa1510_forced_release_keys[] = { }; /* + * Amilo Xi 3650 key release for light touch bar not working + */ +static unsigned int atkbd_amilo_xi3650_forced_release_keys[] = { + 0x67, 0xed, 0x90, 0xa2, 0x99, 0xa4, 0xae, 0xb0, -1U +}; + +/* * atkbd_set_keycode_table() initializes keyboard's keycode table * according to the selected scancode set */ @@ -1560,6 +1567,15 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = { .callback = atkbd_setup_forced_release, .driver_data = atkbd_amilo_pa1510_forced_release_keys, }, + { + .ident = "Fujitsu Amilo Xi 3650", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), + DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xi 3650"), + }, + .callback = atkbd_setup_forced_release, + .driver_data = atkbd_amilo_xi3650_forced_release_keys, + }, { } }; diff --git a/drivers/input/keyboard/omap-keypad.c b/drivers/input/keyboard/omap-keypad.c index 058fa8b02c2..87ec7b18ac6 100644 --- a/drivers/input/keyboard/omap-keypad.c +++ b/drivers/input/keyboard/omap-keypad.c @@ -100,8 +100,20 @@ static irqreturn_t omap_kp_interrupt(int irq, void *dev_id) /* disable keyboard interrupt and schedule for handling */ if (cpu_is_omap24xx()) { int i; - for (i = 0; i < omap_kp->rows; i++) - disable_irq(gpio_to_irq(row_gpios[i])); + + for (i = 0; i < omap_kp->rows; i++) { + int gpio_irq = gpio_to_irq(row_gpios[i]); + /* + * The interrupt which we're currently handling should + * be disabled _nosync() to avoid deadlocks waiting + * for this handler to complete. All others should + * be disabled the regular way for SMP safety. + */ + if (gpio_irq == irq) + disable_irq_nosync(gpio_irq); + else + disable_irq(gpio_irq); + } } else /* disable keyboard interrupt and schedule for handling */ omap_writew(1, OMAP_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT); diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index cbedf957cc5..daecc75c72e 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c @@ -37,6 +37,7 @@ #define ALPS_FW_BK_2 0x40 static const struct alps_model_info alps_model_data[] = { + { { 0x32, 0x02, 0x14 }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Toshiba Salellite Pro M10 */ { { 0x33, 0x02, 0x0a }, 0x88, 0xf8, ALPS_OLDPROTO }, /* UMAX-530T */ { { 0x53, 0x02, 0x0a }, 0xf8, 0xf8, 0 }, { { 0x53, 0x02, 0x14 }, 0xf8, 0xf8, 0 }, diff --git a/drivers/input/mouse/appletouch.c b/drivers/input/mouse/appletouch.c index 454b96112f0..e0140fdc02a 100644 --- a/drivers/input/mouse/appletouch.c +++ b/drivers/input/mouse/appletouch.c @@ -255,15 +255,22 @@ MODULE_PARM_DESC(debug, "Activate debugging output"); */ static int atp_geyser_init(struct usb_device *udev) { - char data[8]; + char *data; int size; int i; + int ret; + + data = kmalloc(8, GFP_KERNEL); + if (!data) { + err("Out of memory"); + return -ENOMEM; + } size = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), ATP_GEYSER_MODE_READ_REQUEST_ID, USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, ATP_GEYSER_MODE_REQUEST_VALUE, - ATP_GEYSER_MODE_REQUEST_INDEX, &data, 8, 5000); + ATP_GEYSER_MODE_REQUEST_INDEX, data, 8, 5000); if (size != 8) { dprintk("atp_geyser_init: read error\n"); @@ -271,7 +278,8 @@ static int atp_geyser_init(struct usb_device *udev) dprintk("appletouch[%d]: %d\n", i, data[i]); err("Failed to read mode from device."); - return -EIO; + ret = -EIO; + goto out_free; } /* Apply the mode switch */ @@ -281,7 +289,7 @@ static int atp_geyser_init(struct usb_device *udev) ATP_GEYSER_MODE_WRITE_REQUEST_ID, USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, ATP_GEYSER_MODE_REQUEST_VALUE, - ATP_GEYSER_MODE_REQUEST_INDEX, &data, 8, 5000); + ATP_GEYSER_MODE_REQUEST_INDEX, data, 8, 5000); if (size != 8) { dprintk("atp_geyser_init: write error\n"); @@ -289,9 +297,13 @@ static int atp_geyser_init(struct usb_device *udev) dprintk("appletouch[%d]: %d\n", i, data[i]); err("Failed to request geyser raw mode"); - return -EIO; + ret = -EIO; + goto out_free; } - return 0; + ret = 0; +out_free: + kfree(data); + return ret; } /* diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c index 2998a6ac9ae..2d8fc0bf692 100644 --- a/drivers/input/mouse/bcm5974.c +++ b/drivers/input/mouse/bcm5974.c @@ -51,6 +51,10 @@ #define USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI 0x0230 #define USB_DEVICE_ID_APPLE_WELLSPRING2_ISO 0x0231 #define USB_DEVICE_ID_APPLE_WELLSPRING2_JIS 0x0232 +/* Macbook5,1 (unibody), aka wellspring3 */ +#define USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI 0x0236 +#define USB_DEVICE_ID_APPLE_WELLSPRING3_ISO 0x0237 +#define USB_DEVICE_ID_APPLE_WELLSPRING3_JIS 0x0238 #define BCM5974_DEVICE(prod) { \ .match_flags = (USB_DEVICE_ID_MATCH_DEVICE | \ @@ -72,6 +76,10 @@ static const struct usb_device_id bcm5974_table[] = { BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI), BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING2_ISO), BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING2_JIS), + /* Macbook5,1 */ + BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI), + BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING3_ISO), + BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING3_JIS), /* Terminating entry */ {} }; @@ -96,14 +104,23 @@ struct bt_data { u8 rel_y; /* relative y coordinate */ }; -/* trackpad header structure */ -struct tp_header { - u8 unknown1[16]; /* constants, timers, etc */ - u8 fingers; /* number of fingers on trackpad */ - u8 unknown2[9]; /* constants, timers, etc */ +/* trackpad header types */ +enum tp_type { + TYPE1, /* plain trackpad */ + TYPE2 /* button integrated in trackpad */ }; -/* trackpad finger structure */ +/* trackpad finger data offsets, le16-aligned */ +#define FINGER_TYPE1 (13 * sizeof(__le16)) +#define FINGER_TYPE2 (15 * sizeof(__le16)) + +/* trackpad button data offsets */ +#define BUTTON_TYPE2 15 + +/* list of device capability bits */ +#define HAS_INTEGRATED_BUTTON 1 + +/* trackpad finger structure, le16-aligned */ struct tp_finger { __le16 origin; /* zero when switching track finger */ __le16 abs_x; /* absolute x coodinate */ @@ -117,13 +134,11 @@ struct tp_finger { __le16 force_minor; /* trackpad force, minor axis? */ __le16 unused[3]; /* zeros */ __le16 multi; /* one finger: varies, more fingers: constant */ -}; +} __attribute__((packed,aligned(2))); -/* trackpad data structure, empirically at least ten fingers */ -struct tp_data { - struct tp_header header; - struct tp_finger finger[16]; -}; +/* trackpad finger data size, empirically at least ten fingers */ +#define SIZEOF_FINGER sizeof(struct tp_finger) +#define SIZEOF_ALL_FINGERS (16 * SIZEOF_FINGER) /* device-specific parameters */ struct bcm5974_param { @@ -136,9 +151,12 @@ struct bcm5974_param { /* device-specific configuration */ struct bcm5974_config { int ansi, iso, jis; /* the product id of this device */ + int caps; /* device capability bitmask */ int bt_ep; /* the endpoint of the button interface */ int bt_datalen; /* data length of the button interface */ int tp_ep; /* the endpoint of the trackpad interface */ + enum tp_type tp_type; /* type of trackpad interface */ + int tp_offset; /* offset to trackpad finger data */ int tp_datalen; /* data length of the trackpad interface */ struct bcm5974_param p; /* finger pressure limits */ struct bcm5974_param w; /* finger width limits */ @@ -158,7 +176,7 @@ struct bcm5974 { struct urb *bt_urb; /* button usb request block */ struct bt_data *bt_data; /* button transferred data */ struct urb *tp_urb; /* trackpad usb request block */ - struct tp_data *tp_data; /* trackpad transferred data */ + u8 *tp_data; /* trackpad transferred data */ int fingers; /* number of fingers on trackpad */ }; @@ -183,8 +201,9 @@ static const struct bcm5974_config bcm5974_config_table[] = { USB_DEVICE_ID_APPLE_WELLSPRING_ANSI, USB_DEVICE_ID_APPLE_WELLSPRING_ISO, USB_DEVICE_ID_APPLE_WELLSPRING_JIS, + 0, 0x84, sizeof(struct bt_data), - 0x81, sizeof(struct tp_data), + 0x81, TYPE1, FINGER_TYPE1, FINGER_TYPE1 + SIZEOF_ALL_FINGERS, { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 256 }, { DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 }, { DIM_X, DIM_X / SN_COORD, -4824, 5342 }, @@ -194,13 +213,26 @@ static const struct bcm5974_config bcm5974_config_table[] = { USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI, USB_DEVICE_ID_APPLE_WELLSPRING2_ISO, USB_DEVICE_ID_APPLE_WELLSPRING2_JIS, + 0, 0x84, sizeof(struct bt_data), - 0x81, sizeof(struct tp_data), + 0x81, TYPE1, FINGER_TYPE1, FINGER_TYPE1 + SIZEOF_ALL_FINGERS, { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 256 }, { DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 }, { DIM_X, DIM_X / SN_COORD, -4824, 4824 }, { DIM_Y, DIM_Y / SN_COORD, -172, 4290 } }, + { + USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI, + USB_DEVICE_ID_APPLE_WELLSPRING3_ISO, + USB_DEVICE_ID_APPLE_WELLSPRING3_JIS, + HAS_INTEGRATED_BUTTON, + 0x84, sizeof(struct bt_data), + 0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS, + { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 300 }, + { DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 }, + { DIM_X, DIM_X / SN_COORD, -4460, 5166 }, + { DIM_Y, DIM_Y / SN_COORD, -75, 6700 } + }, {} }; @@ -257,6 +289,7 @@ static void setup_events_to_report(struct input_dev *input_dev, __set_bit(BTN_TOOL_FINGER, input_dev->keybit); __set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit); __set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit); + __set_bit(BTN_TOOL_QUADTAP, input_dev->keybit); __set_bit(BTN_LEFT, input_dev->keybit); } @@ -266,6 +299,11 @@ static int report_bt_state(struct bcm5974 *dev, int size) if (size != sizeof(struct bt_data)) return -EIO; + dprintk(7, + "bcm5974: button data: %x %x %x %x\n", + dev->bt_data->unknown1, dev->bt_data->button, + dev->bt_data->rel_x, dev->bt_data->rel_y); + input_report_key(dev->input, BTN_LEFT, dev->bt_data->button); input_sync(dev->input); @@ -276,29 +314,37 @@ static int report_bt_state(struct bcm5974 *dev, int size) static int report_tp_state(struct bcm5974 *dev, int size) { const struct bcm5974_config *c = &dev->cfg; - const struct tp_finger *f = dev->tp_data->finger; + const struct tp_finger *f; struct input_dev *input = dev->input; - const int fingers = (size - 26) / 28; - int raw_p, raw_w, raw_x, raw_y; - int ptest = 0, origin = 0, nmin = 0, nmax = 0; + int raw_p, raw_w, raw_x, raw_y, raw_n; + int ptest = 0, origin = 0, ibt = 0, nmin = 0, nmax = 0; int abs_p = 0, abs_w = 0, abs_x = 0, abs_y = 0; - if (size < 26 || (size - 26) % 28 != 0) + if (size < c->tp_offset || (size - c->tp_offset) % SIZEOF_FINGER != 0) return -EIO; + /* finger data, le16-aligned */ + f = (const struct tp_finger *)(dev->tp_data + c->tp_offset); + raw_n = (size - c->tp_offset) / SIZEOF_FINGER; + /* always track the first finger; when detached, start over */ - if (fingers) { + if (raw_n) { raw_p = raw2int(f->force_major); raw_w = raw2int(f->size_major); raw_x = raw2int(f->abs_x); raw_y = raw2int(f->abs_y); dprintk(9, - "bcm5974: raw: p: %+05d w: %+05d x: %+05d y: %+05d\n", - raw_p, raw_w, raw_x, raw_y); + "bcm5974: " + "raw: p: %+05d w: %+05d x: %+05d y: %+05d n: %d\n", + raw_p, raw_w, raw_x, raw_y, raw_n); ptest = int2bound(&c->p, raw_p); origin = raw2int(f->origin); + + /* set the integrated button if applicable */ + if (c->tp_type == TYPE2) + ibt = raw2int(dev->tp_data[BUTTON_TYPE2]); } /* while tracking finger still valid, count all fingers */ @@ -307,12 +353,13 @@ static int report_tp_state(struct bcm5974 *dev, int size) abs_w = int2bound(&c->w, raw_w); abs_x = int2bound(&c->x, raw_x - c->x.devmin); abs_y = int2bound(&c->y, c->y.devmax - raw_y); - for (; f != dev->tp_data->finger + fingers; f++) { + while (raw_n--) { ptest = int2bound(&c->p, raw2int(f->force_major)); if (ptest > PRESSURE_LOW) nmax++; if (ptest > PRESSURE_HIGH) nmin++; + f++; } } @@ -324,7 +371,8 @@ static int report_tp_state(struct bcm5974 *dev, int size) input_report_key(input, BTN_TOUCH, dev->fingers > 0); input_report_key(input, BTN_TOOL_FINGER, dev->fingers == 1); input_report_key(input, BTN_TOOL_DOUBLETAP, dev->fingers == 2); - input_report_key(input, BTN_TOOL_TRIPLETAP, dev->fingers > 2); + input_report_key(input, BTN_TOOL_TRIPLETAP, dev->fingers == 3); + input_report_key(input, BTN_TOOL_QUADTAP, dev->fingers > 3); input_report_abs(input, ABS_PRESSURE, abs_p); input_report_abs(input, ABS_TOOL_WIDTH, abs_w); @@ -335,11 +383,15 @@ static int report_tp_state(struct bcm5974 *dev, int size) dprintk(8, "bcm5974: abs: p: %+05d w: %+05d x: %+05d y: %+05d " - "nmin: %d nmax: %d n: %d\n", - abs_p, abs_w, abs_x, abs_y, nmin, nmax, dev->fingers); + "nmin: %d nmax: %d n: %d ibt: %d\n", abs_p, abs_w, + abs_x, abs_y, nmin, nmax, dev->fingers, ibt); } + /* type 2 reports button events via ibt only */ + if (c->tp_type == TYPE2) + input_report_key(input, BTN_LEFT, ibt); + input_sync(input); return 0; @@ -649,6 +701,8 @@ static int bcm5974_probe(struct usb_interface *iface, input_dev->name = "bcm5974"; input_dev->phys = dev->phys; usb_to_input_id(dev->udev, &input_dev->id); + /* report driver capabilities via the version field */ + input_dev->id.version = cfg->caps; input_dev->dev.parent = &iface->dev; input_set_drvdata(input_dev, dev); diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c index 6ab0eb1ada1..4bc78892ba9 100644 --- a/drivers/input/mouse/elantech.c +++ b/drivers/input/mouse/elantech.c @@ -1,7 +1,7 @@ /* - * Elantech Touchpad driver (v5) + * Elantech Touchpad driver (v6) * - * Copyright (C) 2007-2008 Arjan Opmeer <arjan@opmeer.net> + * Copyright (C) 2007-2009 Arjan Opmeer <arjan@opmeer.net> * * 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 @@ -178,6 +178,7 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse) struct elantech_data *etd = psmouse->private; unsigned char *packet = psmouse->packet; int fingers; + static int old_fingers; if (etd->fw_version_maj == 0x01) { /* byte 0: D U p1 p2 1 p3 R L @@ -190,6 +191,14 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse) fingers = (packet[0] & 0xc0) >> 6; } + if (etd->jumpy_cursor) { + /* Discard packets that are likely to have bogus coordinates */ + if (fingers > old_fingers) { + elantech_debug("elantech.c: discarding packet\n"); + goto discard_packet_v1; + } + } + input_report_key(dev, BTN_TOUCH, fingers != 0); /* byte 2: x7 x6 x5 x4 x3 x2 x1 x0 @@ -216,6 +225,9 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse) } input_sync(dev); + + discard_packet_v1: + old_fingers = fingers; } /* @@ -363,9 +375,14 @@ static int elantech_set_absolute_mode(struct psmouse *psmouse) rc = -1; break; } + } + + if (rc == 0) { /* - * Read back reg 0x10. The touchpad is probably initalising - * and not ready until we read back the value we just wrote. + * Read back reg 0x10. For hardware version 1 we must make + * sure the absolute mode bit is set. For hardware version 2 + * the touchpad is probably initalising and not ready until + * we read back the value we just wrote. */ do { rc = elantech_read_reg(psmouse, 0x10, &val); @@ -373,12 +390,18 @@ static int elantech_set_absolute_mode(struct psmouse *psmouse) break; tries--; elantech_debug("elantech.c: retrying read (%d).\n", - tries); + tries); msleep(ETP_READ_BACK_DELAY); } while (tries > 0); - if (rc) + + if (rc) { pr_err("elantech.c: failed to read back register 0x10.\n"); - break; + } else if (etd->hw_version == 1 && + !(val & ETP_R10_ABSOLUTE_MODE)) { + pr_err("elantech.c: touchpad refuses " + "to switch to absolute mode.\n"); + rc = -1; + } } if (rc) @@ -662,6 +685,17 @@ int elantech_init(struct psmouse *psmouse) param[0], param[1], param[2]); etd->capabilities = param[0]; + /* + * This firmware seems to suffer from misreporting coordinates when + * a touch action starts causing the mouse cursor or scrolled page + * to jump. Enable a workaround. + */ + if (etd->fw_version_maj == 0x02 && etd->fw_version_min == 0x22) { + pr_info("elantech.c: firmware version 2.34 detected, " + "enabling jumpy cursor workaround\n"); + etd->jumpy_cursor = 1; + } + if (elantech_set_absolute_mode(psmouse)) { pr_err("elantech.c: failed to put touchpad into absolute mode.\n"); goto init_fail; diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h index bee282b540b..ed848cc8081 100644 --- a/drivers/input/mouse/elantech.h +++ b/drivers/input/mouse/elantech.h @@ -1,7 +1,7 @@ /* - * Elantech Touchpad driver (v5) + * Elantech Touchpad driver (v6) * - * Copyright (C) 2007-2008 Arjan Opmeer <arjan@opmeer.net> + * Copyright (C) 2007-2009 Arjan Opmeer <arjan@opmeer.net> * * 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 @@ -104,6 +104,7 @@ struct elantech_data { unsigned char fw_version_min; unsigned char hw_version; unsigned char paritycheck; + unsigned char jumpy_cursor; unsigned char parity[256]; }; diff --git a/drivers/input/mouse/lifebook.c b/drivers/input/mouse/lifebook.c index df81b0aaa9f..15ac3205ac0 100644 --- a/drivers/input/mouse/lifebook.c +++ b/drivers/input/mouse/lifebook.c @@ -61,6 +61,12 @@ static const struct dmi_system_id lifebook_dmi_table[] = { }, }, { + .ident = "Lifebook B-2130", + .matches = { + DMI_MATCH(DMI_BOARD_NAME, "ZEPHYR"), + }, + }, + { .ident = "Lifebook B213x/B2150", .matches = { DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook B2131/B2133/B2150"), diff --git a/drivers/input/serio/sa1111ps2.c b/drivers/input/serio/sa1111ps2.c index 57953c0eb82..f412c69478a 100644 --- a/drivers/input/serio/sa1111ps2.c +++ b/drivers/input/serio/sa1111ps2.c @@ -77,7 +77,7 @@ static irqreturn_t ps2_txint(int irq, void *dev_id) spin_lock(&ps2if->lock); status = sa1111_readl(ps2if->base + SA1111_PS2STAT); if (ps2if->head == ps2if->tail) { - disable_irq(irq); + disable_irq_nosync(irq); /* done */ } else if (status & PS2STAT_TXE) { sa1111_writel(ps2if->buf[ps2if->tail], ps2if->base + SA1111_PS2DATA); diff --git a/drivers/input/tablet/wacom.h b/drivers/input/tablet/wacom.h index 677680e9f54..9710bfd49cf 100644 --- a/drivers/input/tablet/wacom.h +++ b/drivers/input/tablet/wacom.h @@ -11,7 +11,7 @@ * Copyright (c) 2000 Daniel Egger <egger@suse.de> * Copyright (c) 2001 Frederic Lepied <flepied@mandrakesoft.com> * Copyright (c) 2004 Panagiotis Issaris <panagiotis.issaris@mech.kuleuven.ac.be> - * Copyright (c) 2002-2008 Ping Cheng <pingc@wacom.com> + * Copyright (c) 2002-2009 Ping Cheng <pingc@wacom.com> * * ChangeLog: * v0.1 (vp) - Initial release @@ -67,6 +67,7 @@ * v1.47 (pc) - Added support for Bamboo * v1.48 (pc) - Added support for Bamboo1, BambooFun, and Cintiq 12WX * v1.49 (pc) - Added support for USB Tablet PC (0x90, 0x93, and 0x9A) + * v1.50 (pc) - Fixed a TabletPC touch bug in 2.6.28 */ /* @@ -87,7 +88,7 @@ /* * Version Information */ -#define DRIVER_VERSION "v1.49" +#define DRIVER_VERSION "v1.50" #define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>" #define DRIVER_DESC "USB Wacom Graphire and Wacom Intuos tablet driver" #define DRIVER_LICENSE "GPL" diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index 484496daa0f..b8624f27abf 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c @@ -289,6 +289,7 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi 5000); /* 5 secs */ } while (result < 0 && limit++ < 5); + /* No need to parse the Descriptor. It isn't an error though */ if (result < 0) goto out; @@ -368,9 +369,8 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi } } - result = 0; - out: + result = 0; kfree(report); return result; } @@ -425,6 +425,15 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i endpoint = &intf->cur_altsetting->endpoint[0].desc; + /* Initialize touch_x_max and touch_y_max in case it is not defined */ + if (wacom_wac->features->type == TABLETPC) { + features->touch_x_max = 1023; + features->touch_y_max = 1023; + } else { + features->touch_x_max = 0; + features->touch_y_max = 0; + } + /* TabletPC need to retrieve the physical and logical maximum from report descriptor */ if (wacom_wac->features->type == TABLETPC) { if (usb_get_extra_descriptor(interface, HID_DEVICET_HID, &hid_desc)) { diff --git a/drivers/input/touchscreen/tsc2007.c b/drivers/input/touchscreen/tsc2007.c index 4ab07024689..948e167557f 100644 --- a/drivers/input/touchscreen/tsc2007.c +++ b/drivers/input/touchscreen/tsc2007.c @@ -200,8 +200,9 @@ static int tsc2007_read_values(struct tsc2007 *tsc) static enum hrtimer_restart tsc2007_timer(struct hrtimer *handle) { struct tsc2007 *ts = container_of(handle, struct tsc2007, timer); + unsigned long flags; - spin_lock_irq(&ts->lock); + spin_lock_irqsave(&ts->lock, flags); if (unlikely(!ts->get_pendown_state() && ts->pendown)) { struct input_dev *input = ts->input; @@ -222,7 +223,7 @@ static enum hrtimer_restart tsc2007_timer(struct hrtimer *handle) tsc2007_send_event(ts); } - spin_unlock_irq(&ts->lock); + spin_unlock_irqrestore(&ts->lock, flags); return HRTIMER_NORESTART; } @@ -235,7 +236,7 @@ static irqreturn_t tsc2007_irq(int irq, void *handle) spin_lock_irqsave(&ts->lock, flags); if (likely(ts->get_pendown_state())) { - disable_irq(ts->irq); + disable_irq_nosync(ts->irq); hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_DELAY), HRTIMER_MODE_REL); } diff --git a/drivers/input/touchscreen/ucb1400_ts.c b/drivers/input/touchscreen/ucb1400_ts.c index e868264fe79..f100c7f4c1d 100644 --- a/drivers/input/touchscreen/ucb1400_ts.c +++ b/drivers/input/touchscreen/ucb1400_ts.c @@ -256,7 +256,7 @@ static irqreturn_t ucb1400_hard_irq(int irqnr, void *devid) struct ucb1400_ts *ucb = devid; if (irqnr == ucb->irq) { - disable_irq(ucb->irq); + disable_irq_nosync(ucb->irq); ucb->irq_pending = 1; wake_up(&ucb->ts_wait); return IRQ_HANDLED; diff --git a/drivers/isdn/capi/capifs.c b/drivers/isdn/capi/capifs.c index b129409925a..bff72d81f26 100644 --- a/drivers/isdn/capi/capifs.c +++ b/drivers/isdn/capi/capifs.c @@ -75,15 +75,17 @@ static int capifs_remount(struct super_block *s, int *flags, char *data) } } - kfree(s->s_options); - s->s_options = new_opt; + mutex_lock(&s->s_root->d_inode->i_mutex); + replace_mount_options(s, new_opt); config.setuid = setuid; config.setgid = setgid; config.uid = uid; config.gid = gid; config.mode = mode; + mutex_unlock(&s->s_root->d_inode->i_mutex); + return 0; } @@ -154,13 +156,16 @@ void capifs_new_ncci(unsigned int number, dev_t device) if (!inode) return; inode->i_ino = number+2; + + dentry = get_node(number); + + /* config contents is protected by root's i_mutex */ inode->i_uid = config.setuid ? config.uid : current_fsuid(); inode->i_gid = config.setgid ? config.gid : current_fsgid(); inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; init_special_inode(inode, S_IFCHR|config.mode, device); //inode->i_op = &capifs_file_inode_operations; - dentry = get_node(number); if (!IS_ERR(dentry) && !dentry->d_inode) d_instantiate(dentry, inode); mutex_unlock(&capifs_root->d_inode->i_mutex); diff --git a/drivers/isdn/capi/kcapi.c b/drivers/isdn/capi/kcapi.c index 5360c4fd473..f33170368cd 100644 --- a/drivers/isdn/capi/kcapi.c +++ b/drivers/isdn/capi/kcapi.c @@ -270,6 +270,15 @@ static void recv_handler(struct work_struct *work) mutex_unlock(&ap->recv_mtx); } +/** + * capi_ctr_handle_message() - handle incoming CAPI message + * @card: controller descriptor structure. + * @appl: application ID. + * @skb: message. + * + * Called by hardware driver to pass a CAPI message to the application. + */ + void capi_ctr_handle_message(struct capi_ctr * card, u16 appl, struct sk_buff *skb) { struct capi20_appl *ap; @@ -348,6 +357,13 @@ error: EXPORT_SYMBOL(capi_ctr_handle_message); +/** + * capi_ctr_ready() - signal CAPI controller ready + * @card: controller descriptor structure. + * + * Called by hardware driver to signal that the controller is up and running. + */ + void capi_ctr_ready(struct capi_ctr * card) { card->cardstate = CARD_RUNNING; @@ -360,6 +376,14 @@ void capi_ctr_ready(struct capi_ctr * card) EXPORT_SYMBOL(capi_ctr_ready); +/** + * capi_ctr_reseted() - signal CAPI controller reset + * @card: controller descriptor structure. + * + * Called by hardware driver to signal that the controller is down and + * unavailable for use. + */ + void capi_ctr_reseted(struct capi_ctr * card) { u16 appl; @@ -391,6 +415,13 @@ void capi_ctr_reseted(struct capi_ctr * card) EXPORT_SYMBOL(capi_ctr_reseted); +/** + * capi_ctr_suspend_output() - suspend controller + * @card: controller descriptor structure. + * + * Called by hardware driver to stop data flow. + */ + void capi_ctr_suspend_output(struct capi_ctr *card) { if (!card->blocked) { @@ -401,6 +432,13 @@ void capi_ctr_suspend_output(struct capi_ctr *card) EXPORT_SYMBOL(capi_ctr_suspend_output); +/** + * capi_ctr_resume_output() - resume controller + * @card: controller descriptor structure. + * + * Called by hardware driver to resume data flow. + */ + void capi_ctr_resume_output(struct capi_ctr *card) { if (card->blocked) { @@ -413,6 +451,14 @@ EXPORT_SYMBOL(capi_ctr_resume_output); /* ------------------------------------------------------------- */ +/** + * attach_capi_ctr() - register CAPI controller + * @card: controller descriptor structure. + * + * Called by hardware driver to register a controller with the CAPI subsystem. + * Return value: 0 on success, error code < 0 on error + */ + int attach_capi_ctr(struct capi_ctr *card) { @@ -459,6 +505,15 @@ attach_capi_ctr(struct capi_ctr *card) EXPORT_SYMBOL(attach_capi_ctr); +/** + * detach_capi_ctr() - unregister CAPI controller + * @card: controller descriptor structure. + * + * Called by hardware driver to remove the registration of a controller + * with the CAPI subsystem. + * Return value: 0 on success, error code < 0 on error + */ + int detach_capi_ctr(struct capi_ctr *card) { if (card->cardstate != CARD_DETECTED) @@ -479,6 +534,13 @@ int detach_capi_ctr(struct capi_ctr *card) EXPORT_SYMBOL(detach_capi_ctr); +/** + * register_capi_driver() - register CAPI driver + * @driver: driver descriptor structure. + * + * Called by hardware driver to register itself with the CAPI subsystem. + */ + void register_capi_driver(struct capi_driver *driver) { unsigned long flags; @@ -490,6 +552,13 @@ void register_capi_driver(struct capi_driver *driver) EXPORT_SYMBOL(register_capi_driver); +/** + * unregister_capi_driver() - unregister CAPI driver + * @driver: driver descriptor structure. + * + * Called by hardware driver to unregister itself from the CAPI subsystem. + */ + void unregister_capi_driver(struct capi_driver *driver) { unsigned long flags; @@ -505,6 +574,13 @@ EXPORT_SYMBOL(unregister_capi_driver); /* -------- CAPI2.0 Interface ---------------------------------- */ /* ------------------------------------------------------------- */ +/** + * capi20_isinstalled() - CAPI 2.0 operation CAPI_INSTALLED + * + * Return value: CAPI result code (CAPI_NOERROR if at least one ISDN controller + * is ready for use, CAPI_REGNOTINSTALLED otherwise) + */ + u16 capi20_isinstalled(void) { int i; @@ -517,6 +593,18 @@ u16 capi20_isinstalled(void) EXPORT_SYMBOL(capi20_isinstalled); +/** + * capi20_register() - CAPI 2.0 operation CAPI_REGISTER + * @ap: CAPI application descriptor structure. + * + * Register an application's presence with CAPI. + * A unique application ID is assigned and stored in @ap->applid. + * After this function returns successfully, the message receive + * callback function @ap->recv_message() may be called at any time + * until capi20_release() has been called for the same @ap. + * Return value: CAPI result code + */ + u16 capi20_register(struct capi20_appl *ap) { int i; @@ -571,6 +659,16 @@ u16 capi20_register(struct capi20_appl *ap) EXPORT_SYMBOL(capi20_register); +/** + * capi20_release() - CAPI 2.0 operation CAPI_RELEASE + * @ap: CAPI application descriptor structure. + * + * Terminate an application's registration with CAPI. + * After this function returns successfully, the message receive + * callback function @ap->recv_message() will no longer be called. + * Return value: CAPI result code + */ + u16 capi20_release(struct capi20_appl *ap) { int i; @@ -603,6 +701,15 @@ u16 capi20_release(struct capi20_appl *ap) EXPORT_SYMBOL(capi20_release); +/** + * capi20_put_message() - CAPI 2.0 operation CAPI_PUT_MESSAGE + * @ap: CAPI application descriptor structure. + * @skb: CAPI message. + * + * Transfer a single message to CAPI. + * Return value: CAPI result code + */ + u16 capi20_put_message(struct capi20_appl *ap, struct sk_buff *skb) { struct capi_ctr *card; @@ -668,6 +775,16 @@ u16 capi20_put_message(struct capi20_appl *ap, struct sk_buff *skb) EXPORT_SYMBOL(capi20_put_message); +/** + * capi20_get_manufacturer() - CAPI 2.0 operation CAPI_GET_MANUFACTURER + * @contr: controller number. + * @buf: result buffer (64 bytes). + * + * Retrieve information about the manufacturer of the specified ISDN controller + * or (for @contr == 0) the driver itself. + * Return value: CAPI result code + */ + u16 capi20_get_manufacturer(u32 contr, u8 *buf) { struct capi_ctr *card; @@ -685,6 +802,16 @@ u16 capi20_get_manufacturer(u32 contr, u8 *buf) EXPORT_SYMBOL(capi20_get_manufacturer); +/** + * capi20_get_version() - CAPI 2.0 operation CAPI_GET_VERSION + * @contr: controller number. + * @verp: result structure. + * + * Retrieve version information for the specified ISDN controller + * or (for @contr == 0) the driver itself. + * Return value: CAPI result code + */ + u16 capi20_get_version(u32 contr, struct capi_version *verp) { struct capi_ctr *card; @@ -703,6 +830,16 @@ u16 capi20_get_version(u32 contr, struct capi_version *verp) EXPORT_SYMBOL(capi20_get_version); +/** + * capi20_get_serial() - CAPI 2.0 operation CAPI_GET_SERIAL_NUMBER + * @contr: controller number. + * @serial: result buffer (8 bytes). + * + * Retrieve the serial number of the specified ISDN controller + * or (for @contr == 0) the driver itself. + * Return value: CAPI result code + */ + u16 capi20_get_serial(u32 contr, u8 *serial) { struct capi_ctr *card; @@ -721,6 +858,16 @@ u16 capi20_get_serial(u32 contr, u8 *serial) EXPORT_SYMBOL(capi20_get_serial); +/** + * capi20_get_profile() - CAPI 2.0 operation CAPI_GET_PROFILE + * @contr: controller number. + * @profp: result structure. + * + * Retrieve capability information for the specified ISDN controller + * or (for @contr == 0) the number of installed controllers. + * Return value: CAPI result code + */ + u16 capi20_get_profile(u32 contr, struct capi_profile *profp) { struct capi_ctr *card; @@ -903,6 +1050,15 @@ static int old_capi_manufacturer(unsigned int cmd, void __user *data) } #endif +/** + * capi20_manufacturer() - CAPI 2.0 operation CAPI_MANUFACTURER + * @cmd: command. + * @data: parameter. + * + * Perform manufacturer specific command. + * Return value: CAPI result code + */ + int capi20_manufacturer(unsigned int cmd, void __user *data) { struct capi_ctr *card; @@ -981,6 +1137,21 @@ int capi20_manufacturer(unsigned int cmd, void __user *data) EXPORT_SYMBOL(capi20_manufacturer); /* temporary hack */ + +/** + * capi20_set_callback() - set CAPI application notification callback function + * @ap: CAPI application descriptor structure. + * @callback: callback function (NULL to remove). + * + * If not NULL, the callback function will be called to notify the + * application of the addition or removal of a controller. + * The first argument (cmd) will tell whether the controller was added + * (KCI_CONTRUP) or removed (KCI_CONTRDOWN). + * The second argument (contr) will be the controller number. + * For cmd==KCI_CONTRUP the third argument (data) will be a pointer to the + * new controller's capability profile structure. + */ + void capi20_set_callback(struct capi20_appl *ap, void (*callback) (unsigned int cmd, __u32 contr, void *data)) { diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index 1fb91edc7de..47c68bc75a1 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c @@ -986,6 +986,9 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start) oldindex = index; oldpage = page; + bitmap->filemap[bitmap->file_pages++] = page; + bitmap->last_page_size = count; + if (outofdate) { /* * if bitmap is out of date, dirty the @@ -998,15 +1001,9 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start) write_page(bitmap, page, 1); ret = -EIO; - if (bitmap->flags & BITMAP_WRITE_ERROR) { - /* release, page not in filemap yet */ - put_page(page); + if (bitmap->flags & BITMAP_WRITE_ERROR) goto err; - } } - - bitmap->filemap[bitmap->file_pages++] = page; - bitmap->last_page_size = count; } paddr = kmap_atomic(page, KM_USER0); if (bitmap->flags & BITMAP_HOSTENDIAN) @@ -1016,9 +1013,11 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start) kunmap_atomic(paddr, KM_USER0); if (b) { /* if the disk bit is set, set the memory bit */ - bitmap_set_memory_bits(bitmap, i << CHUNK_BLOCK_SHIFT(bitmap), - ((i+1) << (CHUNK_BLOCK_SHIFT(bitmap)) >= start) - ); + int needed = ((sector_t)(i+1) << (CHUNK_BLOCK_SHIFT(bitmap)) + >= start); + bitmap_set_memory_bits(bitmap, + (sector_t)i << CHUNK_BLOCK_SHIFT(bitmap), + needed); bit_cnt++; set_page_attr(bitmap, page, BITMAP_PAGE_CLEAN); } @@ -1154,8 +1153,9 @@ void bitmap_daemon_work(struct bitmap *bitmap) spin_lock_irqsave(&bitmap->lock, flags); clear_page_attr(bitmap, page, BITMAP_PAGE_CLEAN); } - bmc = bitmap_get_counter(bitmap, j << CHUNK_BLOCK_SHIFT(bitmap), - &blocks, 0); + bmc = bitmap_get_counter(bitmap, + (sector_t)j << CHUNK_BLOCK_SHIFT(bitmap), + &blocks, 0); if (bmc) { /* if (j < 100) printk("bitmap: j=%lu, *bmc = 0x%x\n", j, *bmc); @@ -1169,7 +1169,8 @@ void bitmap_daemon_work(struct bitmap *bitmap) } else if (*bmc == 1) { /* we can clear the bit */ *bmc = 0; - bitmap_count_page(bitmap, j << CHUNK_BLOCK_SHIFT(bitmap), + bitmap_count_page(bitmap, + (sector_t)j << CHUNK_BLOCK_SHIFT(bitmap), -1); /* clear the bit */ @@ -1514,7 +1515,7 @@ void bitmap_dirty_bits(struct bitmap *bitmap, unsigned long s, unsigned long e) unsigned long chunk; for (chunk = s; chunk <= e; chunk++) { - sector_t sec = chunk << CHUNK_BLOCK_SHIFT(bitmap); + sector_t sec = (sector_t)chunk << CHUNK_BLOCK_SHIFT(bitmap); bitmap_set_memory_bits(bitmap, sec, 1); bitmap_file_set_bit(bitmap, sec); } diff --git a/drivers/md/md.c b/drivers/md/md.c index 612343fdde9..fccc8343a25 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -3066,11 +3066,8 @@ array_state_store(mddev_t *mddev, const char *buf, size_t len) } else err = -EBUSY; spin_unlock_irq(&mddev->write_lock); - } else { - mddev->ro = 0; - mddev->recovery_cp = MaxSector; - err = do_md_run(mddev); - } + } else + err = -EINVAL; break; case active: if (mddev->pers) { @@ -4297,6 +4294,7 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open) { int err = 0; struct gendisk *disk = mddev->gendisk; + mdk_rdev_t *rdev; if (atomic_read(&mddev->openers) > is_open) { printk("md: %s still in use.\n",mdname(mddev)); @@ -4339,6 +4337,13 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open) /* tell userspace to handle 'inactive' */ sysfs_notify_dirent(mddev->sysfs_state); + list_for_each_entry(rdev, &mddev->disks, same_set) + if (rdev->raid_disk >= 0) { + char nm[20]; + sprintf(nm, "rd%d", rdev->raid_disk); + sysfs_remove_link(&mddev->kobj, nm); + } + set_capacity(disk, 0); mddev->changed = 1; @@ -4359,7 +4364,6 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open) * Free resources if final stop */ if (mode == 0) { - mdk_rdev_t *rdev; printk(KERN_INFO "md: %s stopped.\n", mdname(mddev)); @@ -4371,13 +4375,6 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open) } mddev->bitmap_offset = 0; - list_for_each_entry(rdev, &mddev->disks, same_set) - if (rdev->raid_disk >= 0) { - char nm[20]; - sprintf(nm, "rd%d", rdev->raid_disk); - sysfs_remove_link(&mddev->kobj, nm); - } - /* make sure all md_delayed_delete calls have finished */ flush_scheduled_work(); @@ -5705,37 +5702,38 @@ static void status_unused(struct seq_file *seq) static void status_resync(struct seq_file *seq, mddev_t * mddev) { - sector_t max_blocks, resync, res; - unsigned long dt, db, rt; + sector_t max_sectors, resync, res; + unsigned long dt, db; + sector_t rt; int scale; unsigned int per_milli; - resync = (mddev->curr_resync - atomic_read(&mddev->recovery_active))/2; + resync = mddev->curr_resync - atomic_read(&mddev->recovery_active); if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) - max_blocks = mddev->resync_max_sectors >> 1; + max_sectors = mddev->resync_max_sectors; else - max_blocks = mddev->dev_sectors / 2; + max_sectors = mddev->dev_sectors; /* * Should not happen. */ - if (!max_blocks) { + if (!max_sectors) { MD_BUG(); return; } /* Pick 'scale' such that (resync>>scale)*1000 will fit - * in a sector_t, and (max_blocks>>scale) will fit in a + * in a sector_t, and (max_sectors>>scale) will fit in a * u32, as those are the requirements for sector_div. * Thus 'scale' must be at least 10 */ scale = 10; if (sizeof(sector_t) > sizeof(unsigned long)) { - while ( max_blocks/2 > (1ULL<<(scale+32))) + while ( max_sectors/2 > (1ULL<<(scale+32))) scale++; } res = (resync>>scale)*1000; - sector_div(res, (u32)((max_blocks>>scale)+1)); + sector_div(res, (u32)((max_sectors>>scale)+1)); per_milli = res; { @@ -5756,25 +5754,35 @@ static void status_resync(struct seq_file *seq, mddev_t * mddev) (test_bit(MD_RECOVERY_SYNC, &mddev->recovery) ? "resync" : "recovery"))), per_milli/10, per_milli % 10, - (unsigned long long) resync, - (unsigned long long) max_blocks); + (unsigned long long) resync/2, + (unsigned long long) max_sectors/2); /* - * We do not want to overflow, so the order of operands and - * the * 100 / 100 trick are important. We do a +1 to be - * safe against division by zero. We only estimate anyway. - * * dt: time from mark until now * db: blocks written from mark until now * rt: remaining time + * + * rt is a sector_t, so could be 32bit or 64bit. + * So we divide before multiply in case it is 32bit and close + * to the limit. + * We scale the divisor (db) by 32 to avoid loosing precision + * near the end of resync when the number of remaining sectors + * is close to 'db'. + * We then divide rt by 32 after multiplying by db to compensate. + * The '+1' avoids division by zero if db is very small. */ dt = ((jiffies - mddev->resync_mark) / HZ); if (!dt) dt++; db = (mddev->curr_mark_cnt - atomic_read(&mddev->recovery_active)) - mddev->resync_mark_cnt; - rt = (dt * ((unsigned long)(max_blocks-resync) / (db/2/100+1)))/100; - seq_printf(seq, " finish=%lu.%lumin", rt / 60, (rt % 60)/6); + rt = max_sectors - resync; /* number of remaining sectors */ + sector_div(rt, db/32+1); + rt *= dt; + rt >>= 5; + + seq_printf(seq, " finish=%lu.%lumin", (unsigned long)rt / 60, + ((unsigned long)rt % 60)/6); seq_printf(seq, " speed=%ldK/sec", db/2/dt); } @@ -5965,7 +5973,7 @@ static int md_seq_show(struct seq_file *seq, void *v) return 0; } -static struct seq_operations md_seq_ops = { +static const struct seq_operations md_seq_ops = { .start = md_seq_start, .next = md_seq_next, .stop = md_seq_stop, diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 81a54f17417..499620afb44 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -1809,17 +1809,17 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i r10_bio->sector = sect; raid10_find_phys(conf, r10_bio); - /* Need to check if this section will still be + + /* Need to check if the array will still be * degraded */ - for (j=0; j<conf->copies;j++) { - int d = r10_bio->devs[j].devnum; - if (conf->mirrors[d].rdev == NULL || - test_bit(Faulty, &conf->mirrors[d].rdev->flags)) { + for (j=0; j<conf->raid_disks; j++) + if (conf->mirrors[j].rdev == NULL || + test_bit(Faulty, &conf->mirrors[j].rdev->flags)) { still_degraded = 1; break; } - } + must_sync = bitmap_start_sync(mddev->bitmap, sect, &sync_blocks, still_degraded); diff --git a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c index 1dba8f0832a..5cf6c45b91f 100644 --- a/drivers/media/radio/radio-sf16fmi.c +++ b/drivers/media/radio/radio-sf16fmi.c @@ -153,7 +153,7 @@ static int vidioc_g_tuner(struct file *file, void *priv, mult = (fmi->flags & V4L2_TUNER_CAP_LOW) ? 1 : 1000; v->rangelow = RSF16_MINFREQ / mult; v->rangehigh = RSF16_MAXFREQ / mult; - v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_MODE_STEREO; + v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; v->capability = fmi->flags & V4L2_TUNER_CAP_LOW; v->audmode = V4L2_TUNER_MODE_STEREO; v->signal = fmi_getsigstr(fmi); diff --git a/drivers/media/radio/radio-sf16fmr2.c b/drivers/media/radio/radio-sf16fmr2.c index c09ca8600ea..935ff9bcdfc 100644 --- a/drivers/media/radio/radio-sf16fmr2.c +++ b/drivers/media/radio/radio-sf16fmr2.c @@ -233,7 +233,7 @@ static int vidioc_g_tuner(struct file *file, void *priv, mult = (fmr2->flags & V4L2_TUNER_CAP_LOW) ? 1 : 1000; v->rangelow = RSF16_MINFREQ / mult; v->rangehigh = RSF16_MAXFREQ / mult; - v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_MODE_STEREO; + v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; v->capability = fmr2->flags&V4L2_TUNER_CAP_LOW; v->audmode = fmr2->stereo ? V4L2_TUNER_MODE_STEREO: V4L2_TUNER_MODE_MONO; diff --git a/drivers/media/video/au0828/au0828-core.c b/drivers/media/video/au0828/au0828-core.c index 4cee0b92eee..a1e4c0d769a 100644 --- a/drivers/media/video/au0828/au0828-core.c +++ b/drivers/media/video/au0828/au0828-core.c @@ -192,8 +192,6 @@ static int au0828_usb_probe(struct usb_interface *interface, dev->usbdev = usbdev; dev->boardnr = id->driver_info; - usb_set_intfdata(interface, dev); - /* Create the v4l2_device */ retval = v4l2_device_register(&interface->dev, &dev->v4l2_dev); if (retval) { @@ -222,6 +220,10 @@ static int au0828_usb_probe(struct usb_interface *interface, /* Digital TV */ au0828_dvb_register(dev); + /* Store the pointer to the au0828_dev so it can be accessed in + au0828_usb_disconnect */ + usb_set_intfdata(interface, dev); + printk(KERN_INFO "Registered device AU0828 [%s]\n", dev->board.name == NULL ? "Unset" : dev->board.name); diff --git a/drivers/media/video/cafe_ccic.c b/drivers/media/video/cafe_ccic.c index 5f582726985..c4d181dde1c 100644 --- a/drivers/media/video/cafe_ccic.c +++ b/drivers/media/video/cafe_ccic.c @@ -774,6 +774,7 @@ static int cafe_cam_init(struct cafe_camera *cam) ret = __cafe_cam_reset(cam); if (ret) goto out; + chip.ident = V4L2_IDENT_NONE; chip.match.type = V4L2_CHIP_MATCH_I2C_ADDR; chip.match.addr = cam->sensor_addr; ret = sensor_call(cam, core, g_chip_ident, &chip); diff --git a/drivers/media/video/cx18/cx18-audio.c b/drivers/media/video/cx18/cx18-audio.c index 1519e91c677..7a8ad5963de 100644 --- a/drivers/media/video/cx18/cx18-audio.c +++ b/drivers/media/video/cx18/cx18-audio.c @@ -44,7 +44,7 @@ int cx18_audio_set_io(struct cx18 *cx) /* handle muxer chips */ v4l2_subdev_call(cx->sd_extmux, audio, s_routing, - in->audio_input, 0, 0); + (u32) in->muxer_input, 0, 0); err = cx18_call_hw_err(cx, cx->card->hw_audio_ctrl, audio, s_routing, in->audio_input, 0, 0); diff --git a/drivers/media/video/cx18/cx18-i2c.c b/drivers/media/video/cx18/cx18-i2c.c index b9b7064a2be..8591e4fc359 100644 --- a/drivers/media/video/cx18/cx18-i2c.c +++ b/drivers/media/video/cx18/cx18-i2c.c @@ -211,7 +211,7 @@ static struct i2c_algo_bit_data cx18_i2c_algo_template = { /* init + register i2c algo-bit adapter */ int init_cx18_i2c(struct cx18 *cx) { - int i; + int i, err; CX18_DEBUG_I2C("i2c init\n"); for (i = 0; i < 2; i++) { @@ -268,8 +268,18 @@ int init_cx18_i2c(struct cx18 *cx) cx18_call_hw(cx, CX18_HW_GPIO_RESET_CTRL, core, reset, (u32) CX18_GPIO_RESET_I2C); - return i2c_bit_add_bus(&cx->i2c_adap[0]) || - i2c_bit_add_bus(&cx->i2c_adap[1]); + err = i2c_bit_add_bus(&cx->i2c_adap[0]); + if (err) + goto err; + err = i2c_bit_add_bus(&cx->i2c_adap[1]); + if (err) + goto err_del_bus_0; + return 0; + + err_del_bus_0: + i2c_del_adapter(&cx->i2c_adap[0]); + err: + return err; } void exit_cx18_i2c(struct cx18 *cx) diff --git a/drivers/media/video/cx231xx/Kconfig b/drivers/media/video/cx231xx/Kconfig index 91156546a07..477d4ab5e9a 100644 --- a/drivers/media/video/cx231xx/Kconfig +++ b/drivers/media/video/cx231xx/Kconfig @@ -1,12 +1,11 @@ config VIDEO_CX231XX - tristate "Conexant cx231xx USB video capture support" - depends on VIDEO_DEV && I2C && INPUT - select VIDEO_TUNER - select VIDEO_TVEEPROM - select VIDEO_IR - select VIDEOBUF_VMALLOC - select VIDEO_CX25840 - select VIDEO_CX231XX_ALSA + tristate "Conexant cx231xx USB video capture support" + depends on VIDEO_DEV && I2C && INPUT + select VIDEO_TUNER + select VIDEO_TVEEPROM + select VIDEO_IR + select VIDEOBUF_VMALLOC + select VIDEO_CX25840 ---help--- This is a video4linux driver for Conexant 231xx USB based TV cards. @@ -15,21 +14,22 @@ config VIDEO_CX231XX module will be called cx231xx config VIDEO_CX231XX_ALSA - tristate "Conexant Cx231xx ALSA audio module" - depends on VIDEO_CX231XX && SND - select SND_PCM + tristate "Conexant Cx231xx ALSA audio module" + depends on VIDEO_CX231XX && SND + select SND_PCM - ---help--- - This is an ALSA driver for Cx231xx USB based TV cards. + ---help--- + This is an ALSA driver for Cx231xx USB based TV cards. - To compile this driver as a module, choose M here: the - module will be called cx231xx-alsa + To compile this driver as a module, choose M here: the + module will be called cx231xx-alsa config VIDEO_CX231XX_DVB - tristate "DVB/ATSC Support for Cx231xx based TV cards" - depends on VIDEO_CX231XX && DVB_CORE - select VIDEOBUF_DVB - select MEDIA_TUNER_XC5000 if !DVB_FE_CUSTOMISE - ---help--- - This adds support for DVB cards based on the - Conexant cx231xx chips. + tristate "DVB/ATSC Support for Cx231xx based TV cards" + depends on VIDEO_CX231XX && DVB_CORE + select VIDEOBUF_DVB + select MEDIA_TUNER_XC5000 if !DVB_FE_CUSTOMISE + + ---help--- + This adds support for DVB cards based on the + Conexant cx231xx chips. diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c index a3c0565be1a..6d6293f7d42 100644 --- a/drivers/media/video/cx23885/cx23885-cards.c +++ b/drivers/media/video/cx23885/cx23885-cards.c @@ -441,9 +441,9 @@ int cx23885_tuner_callback(void *priv, int component, int command, int arg) case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP: /* Two identical tuners on two different i2c buses, * we need to reset the correct gpio. */ - if (port->nr == 0) + if (port->nr == 1) bitmask = 0x01; - else if (port->nr == 1) + else if (port->nr == 2) bitmask = 0x04; break; } diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c index f48454ab390..1dc070da865 100644 --- a/drivers/media/video/cx23885/cx23885-dvb.c +++ b/drivers/media/video/cx23885/cx23885-dvb.c @@ -314,6 +314,7 @@ static struct zl10353_config dvico_fusionhdtv_xc3028 = { .demod_address = 0x0f, .if2 = 45600, .no_tuner = 1, + .disable_i2c_gate_ctrl = 1, }; static struct stv0900_config netup_stv0900_config = { @@ -471,7 +472,7 @@ static int dvb_register(struct cx23885_tsport *port) static struct xc2028_ctrl ctl = { .fname = XC2028_DEFAULT_FIRMWARE, .max_len = 64, - .scode_table = XC3028_FE_OREN538, + .demod = XC3028_FE_OREN538, }; fe = dvb_attach(xc2028_attach, diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c index b0195e8ee4d..db2ac9a99ac 100644 --- a/drivers/media/video/ivtv/ivtv-driver.c +++ b/drivers/media/video/ivtv/ivtv-driver.c @@ -305,14 +305,17 @@ int ivtv_waitq(wait_queue_head_t *waitq) /* Generic utility functions */ int ivtv_msleep_timeout(unsigned int msecs, int intr) { - int ret; int timeout = msecs_to_jiffies(msecs); do { set_current_state(intr ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE); timeout = schedule_timeout(timeout); - if (intr && (ret = signal_pending(current))) - return ret; + if (intr) { + int ret = signal_pending(current); + + if (ret) + return ret; + } } while (timeout); return 0; } diff --git a/drivers/media/video/ivtv/ivtv-gpio.c b/drivers/media/video/ivtv/ivtv-gpio.c index ceb05bdcaf6..85ac707228e 100644 --- a/drivers/media/video/ivtv/ivtv-gpio.c +++ b/drivers/media/video/ivtv/ivtv-gpio.c @@ -190,8 +190,8 @@ static int subdev_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) mask = itv->card->gpio_audio_detect.mask; if (mask == 0 || (read_reg(IVTV_REG_GPIO_IN) & mask)) - vt->rxsubchans = V4L2_TUNER_MODE_STEREO | - V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2; + vt->rxsubchans = V4L2_TUNER_SUB_STEREO | + V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; else vt->rxsubchans = V4L2_TUNER_SUB_MONO; return 0; diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c index 4a2d464f055..c342a9fe983 100644 --- a/drivers/media/video/ivtv/ivtv-ioctl.c +++ b/drivers/media/video/ivtv/ivtv-ioctl.c @@ -180,7 +180,7 @@ int ivtv_set_speed(struct ivtv *itv, int speed) /* Wait for any DMA to finish */ prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE); - while (itv->i_flags & IVTV_F_I_DMA) { + while (test_bit(IVTV_F_I_DMA, &itv->i_flags)) { got_sig = signal_pending(current); if (got_sig) break; @@ -1710,7 +1710,8 @@ static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg) we are waiting unlock first and later lock again. */ mutex_unlock(&itv->serialize_lock); prepare_to_wait(&itv->event_waitq, &wait, TASK_INTERRUPTIBLE); - if ((itv->i_flags & (IVTV_F_I_EV_DEC_STOPPED|IVTV_F_I_EV_VSYNC)) == 0) + if (!test_bit(IVTV_F_I_EV_DEC_STOPPED, &itv->i_flags) && + !test_bit(IVTV_F_I_EV_VSYNC, &itv->i_flags)) schedule(); finish_wait(&itv->event_waitq, &wait); mutex_lock(&itv->serialize_lock); diff --git a/drivers/media/video/ivtv/ivtv-irq.c b/drivers/media/video/ivtv/ivtv-irq.c index 01c14d2b381..cd9db0bf33b 100644 --- a/drivers/media/video/ivtv/ivtv-irq.c +++ b/drivers/media/video/ivtv/ivtv-irq.c @@ -196,7 +196,7 @@ static int stream_enc_dma_append(struct ivtv_stream *s, u32 data[CX2341X_MBOX_MA bytes_needed, s->name); return -1; } - if (rc && !s->buffers_stolen && (s->s_flags & IVTV_F_S_APPL_IO)) { + if (rc && !s->buffers_stolen && test_bit(IVTV_F_S_APPL_IO, &s->s_flags)) { IVTV_WARN("All %s stream buffers are full. Dropping data.\n", s->name); IVTV_WARN("Cause: the application is not reading fast enough.\n"); } diff --git a/drivers/media/video/ivtv/ivtv-yuv.c b/drivers/media/video/ivtv/ivtv-yuv.c index 7912ed6b72e..c0875378acc 100644 --- a/drivers/media/video/ivtv/ivtv-yuv.c +++ b/drivers/media/video/ivtv/ivtv-yuv.c @@ -1063,7 +1063,8 @@ static int ivtv_yuv_udma_frame(struct ivtv *itv, struct ivtv_dma_frame *args) prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE); /* if no UDMA is pending and no UDMA is in progress, then the DMA is finished */ - while (itv->i_flags & (IVTV_F_I_UDMA_PENDING | IVTV_F_I_UDMA)) { + while (test_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags) || + test_bit(IVTV_F_I_UDMA, &itv->i_flags)) { /* don't interrupt if the DMA is in progress but break off a still pending DMA. */ got_sig = signal_pending(current); diff --git a/drivers/media/video/ivtv/ivtvfb.c b/drivers/media/video/ivtv/ivtvfb.c index 66e6eb51307..fa6bb85cb4b 100644 --- a/drivers/media/video/ivtv/ivtvfb.c +++ b/drivers/media/video/ivtv/ivtvfb.c @@ -298,7 +298,8 @@ static int ivtvfb_prep_dec_dma_to_device(struct ivtv *itv, prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE); /* if no UDMA is pending and no UDMA is in progress, then the DMA is finished */ - while (itv->i_flags & (IVTV_F_I_UDMA_PENDING | IVTV_F_I_UDMA)) { + while (test_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags) || + test_bit(IVTV_F_I_UDMA, &itv->i_flags)) { /* don't interrupt if the DMA is in progress but break off a still pending DMA. */ got_sig = signal_pending(current); diff --git a/drivers/media/video/mx3_camera.c b/drivers/media/video/mx3_camera.c index c462b811e99..2d0781118eb 100644 --- a/drivers/media/video/mx3_camera.c +++ b/drivers/media/video/mx3_camera.c @@ -1063,10 +1063,6 @@ static struct soc_camera_host_ops mx3_soc_camera_host_ops = { .owner = THIS_MODULE, .add = mx3_camera_add_device, .remove = mx3_camera_remove_device, -#ifdef CONFIG_PM - .suspend = mx3_camera_suspend, - .resume = mx3_camera_resume, -#endif .set_crop = mx3_camera_set_crop, .set_fmt = mx3_camera_set_fmt, .try_fmt = mx3_camera_try_fmt, diff --git a/drivers/media/video/s2255drv.c b/drivers/media/video/s2255drv.c index 5202cadb2aa..30f4698be90 100644 --- a/drivers/media/video/s2255drv.c +++ b/drivers/media/video/s2255drv.c @@ -1237,6 +1237,7 @@ static int s2255_set_mode(struct s2255_dev *dev, unsigned long chn, buffer[1] = (u32) chn_rev; buffer[2] = CMD_SET_MODE; memcpy(&buffer[3], &dev->mode[chn], sizeof(struct s2255_mode)); + dev->setmode_ready[chn] = 0; res = s2255_write_config(dev->udev, (unsigned char *)buffer, 512); if (debug) dump_verify_mode(dev, mode); @@ -1245,7 +1246,6 @@ static int s2255_set_mode(struct s2255_dev *dev, unsigned long chn, /* wait at least 3 frames before continuing */ if (mode->restart) { - dev->setmode_ready[chn] = 0; wait_event_timeout(dev->wait_setmode[chn], (dev->setmode_ready[chn] != 0), msecs_to_jiffies(S2255_SETMODE_TIMEOUT)); diff --git a/drivers/media/video/saa5246a.c b/drivers/media/video/saa5246a.c index da47b2f0528..155804b061e 100644 --- a/drivers/media/video/saa5246a.c +++ b/drivers/media/video/saa5246a.c @@ -1092,9 +1092,8 @@ static int saa5246a_probe(struct i2c_client *client, /* Register it */ err = video_register_device(t->vdev, VFL_TYPE_VTX, -1); if (err < 0) { - kfree(t); video_device_release(t->vdev); - t->vdev = NULL; + kfree(t); return err; } return 0; diff --git a/drivers/media/video/saa5249.c b/drivers/media/video/saa5249.c index 48b27fe4808..271d6e931b7 100644 --- a/drivers/media/video/saa5249.c +++ b/drivers/media/video/saa5249.c @@ -598,6 +598,7 @@ static int saa5249_probe(struct i2c_client *client, /* Now create a video4linux device */ t->vdev = video_device_alloc(); if (t->vdev == NULL) { + kfree(t); kfree(client); return -ENOMEM; } @@ -617,9 +618,8 @@ static int saa5249_probe(struct i2c_client *client, /* Register it */ err = video_register_device(t->vdev, VFL_TYPE_VTX, -1); if (err < 0) { - kfree(t); video_device_release(t->vdev); - t->vdev = NULL; + kfree(t); return err; } return 0; diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/video/uvc/uvc_driver.c index 399412d7f02..507dc85646b 100644 --- a/drivers/media/video/uvc/uvc_driver.c +++ b/drivers/media/video/uvc/uvc_driver.c @@ -1726,14 +1726,17 @@ static int uvc_suspend(struct usb_interface *intf, pm_message_t message) static int __uvc_resume(struct usb_interface *intf, int reset) { struct uvc_device *dev = usb_get_intfdata(intf); - int ret; uvc_trace(UVC_TRACE_SUSPEND, "Resuming interface %u\n", intf->cur_altsetting->desc.bInterfaceNumber); if (intf->cur_altsetting->desc.bInterfaceSubClass == SC_VIDEOCONTROL) { - if (reset && (ret = uvc_ctrl_resume_device(dev)) < 0) - return ret; + if (reset) { + int ret = uvc_ctrl_resume_device(dev); + + if (ret < 0) + return ret; + } return uvc_status_resume(dev); } diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c index a95e17329c5..6ce974d7362 100644 --- a/drivers/media/video/uvc/uvc_video.c +++ b/drivers/media/video/uvc/uvc_video.c @@ -742,7 +742,7 @@ static int uvc_alloc_urb_buffers(struct uvc_video_device *video, /* Buffers are already allocated, bail out. */ if (video->urb_size) - return 0; + return video->urb_size / psize; /* Compute the number of packets. Bulk endpoints might transfer UVC * payloads accross multiple URBs. diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c index 88f10d6cbc9..be64a502ea2 100644 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/video/v4l2-ioctl.c @@ -42,6 +42,12 @@ printk(KERN_DEBUG "%s: " fmt, vfd->name, ## arg);\ } while (0) +/* Zero out the end of the struct pointed to by p. Everthing after, but + * not including, the specified field is cleared. */ +#define CLEAR_AFTER_FIELD(p, field) \ + memset((u8 *)(p) + offsetof(typeof(*(p)), field) + sizeof((p)->field), \ + 0, sizeof(*(p)) - offsetof(typeof(*(p)), field) - sizeof((p)->field)) + struct std_descr { v4l2_std_id std; const char *descr; @@ -544,39 +550,39 @@ static int check_fmt(const struct v4l2_ioctl_ops *ops, enum v4l2_buf_type type) switch (type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: - if (ops->vidioc_try_fmt_vid_cap) + if (ops->vidioc_g_fmt_vid_cap) return 0; break; case V4L2_BUF_TYPE_VIDEO_OVERLAY: - if (ops->vidioc_try_fmt_vid_overlay) + if (ops->vidioc_g_fmt_vid_overlay) return 0; break; case V4L2_BUF_TYPE_VIDEO_OUTPUT: - if (ops->vidioc_try_fmt_vid_out) + if (ops->vidioc_g_fmt_vid_out) return 0; break; case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: - if (ops->vidioc_try_fmt_vid_out_overlay) + if (ops->vidioc_g_fmt_vid_out_overlay) return 0; break; case V4L2_BUF_TYPE_VBI_CAPTURE: - if (ops->vidioc_try_fmt_vbi_cap) + if (ops->vidioc_g_fmt_vbi_cap) return 0; break; case V4L2_BUF_TYPE_VBI_OUTPUT: - if (ops->vidioc_try_fmt_vbi_out) + if (ops->vidioc_g_fmt_vbi_out) return 0; break; case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: - if (ops->vidioc_try_fmt_sliced_vbi_cap) + if (ops->vidioc_g_fmt_sliced_vbi_cap) return 0; break; case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: - if (ops->vidioc_try_fmt_sliced_vbi_out) + if (ops->vidioc_g_fmt_sliced_vbi_out) return 0; break; case V4L2_BUF_TYPE_PRIVATE: - if (ops->vidioc_try_fmt_type_private) + if (ops->vidioc_g_fmt_type_private) return 0; break; } @@ -782,44 +788,53 @@ static long __video_do_ioctl(struct file *file, switch (f->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: + CLEAR_AFTER_FIELD(f, fmt.pix); v4l_print_pix_fmt(vfd, &f->fmt.pix); if (ops->vidioc_s_fmt_vid_cap) ret = ops->vidioc_s_fmt_vid_cap(file, fh, f); break; case V4L2_BUF_TYPE_VIDEO_OVERLAY: + CLEAR_AFTER_FIELD(f, fmt.win); if (ops->vidioc_s_fmt_vid_overlay) ret = ops->vidioc_s_fmt_vid_overlay(file, fh, f); break; case V4L2_BUF_TYPE_VIDEO_OUTPUT: + CLEAR_AFTER_FIELD(f, fmt.pix); v4l_print_pix_fmt(vfd, &f->fmt.pix); if (ops->vidioc_s_fmt_vid_out) ret = ops->vidioc_s_fmt_vid_out(file, fh, f); break; case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: + CLEAR_AFTER_FIELD(f, fmt.win); if (ops->vidioc_s_fmt_vid_out_overlay) ret = ops->vidioc_s_fmt_vid_out_overlay(file, fh, f); break; case V4L2_BUF_TYPE_VBI_CAPTURE: + CLEAR_AFTER_FIELD(f, fmt.vbi); if (ops->vidioc_s_fmt_vbi_cap) ret = ops->vidioc_s_fmt_vbi_cap(file, fh, f); break; case V4L2_BUF_TYPE_VBI_OUTPUT: + CLEAR_AFTER_FIELD(f, fmt.vbi); if (ops->vidioc_s_fmt_vbi_out) ret = ops->vidioc_s_fmt_vbi_out(file, fh, f); break; case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: + CLEAR_AFTER_FIELD(f, fmt.sliced); if (ops->vidioc_s_fmt_sliced_vbi_cap) ret = ops->vidioc_s_fmt_sliced_vbi_cap(file, fh, f); break; case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: + CLEAR_AFTER_FIELD(f, fmt.sliced); if (ops->vidioc_s_fmt_sliced_vbi_out) ret = ops->vidioc_s_fmt_sliced_vbi_out(file, fh, f); break; case V4L2_BUF_TYPE_PRIVATE: + /* CLEAR_AFTER_FIELD(f, fmt.raw_data); <- does nothing */ if (ops->vidioc_s_fmt_type_private) ret = ops->vidioc_s_fmt_type_private(file, fh, f); @@ -836,46 +851,55 @@ static long __video_do_ioctl(struct file *file, v4l2_type_names)); switch (f->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: + CLEAR_AFTER_FIELD(f, fmt.pix); if (ops->vidioc_try_fmt_vid_cap) ret = ops->vidioc_try_fmt_vid_cap(file, fh, f); if (!ret) v4l_print_pix_fmt(vfd, &f->fmt.pix); break; case V4L2_BUF_TYPE_VIDEO_OVERLAY: + CLEAR_AFTER_FIELD(f, fmt.win); if (ops->vidioc_try_fmt_vid_overlay) ret = ops->vidioc_try_fmt_vid_overlay(file, fh, f); break; case V4L2_BUF_TYPE_VIDEO_OUTPUT: + CLEAR_AFTER_FIELD(f, fmt.pix); if (ops->vidioc_try_fmt_vid_out) ret = ops->vidioc_try_fmt_vid_out(file, fh, f); if (!ret) v4l_print_pix_fmt(vfd, &f->fmt.pix); break; case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: + CLEAR_AFTER_FIELD(f, fmt.win); if (ops->vidioc_try_fmt_vid_out_overlay) ret = ops->vidioc_try_fmt_vid_out_overlay(file, fh, f); break; case V4L2_BUF_TYPE_VBI_CAPTURE: + CLEAR_AFTER_FIELD(f, fmt.vbi); if (ops->vidioc_try_fmt_vbi_cap) ret = ops->vidioc_try_fmt_vbi_cap(file, fh, f); break; case V4L2_BUF_TYPE_VBI_OUTPUT: + CLEAR_AFTER_FIELD(f, fmt.vbi); if (ops->vidioc_try_fmt_vbi_out) ret = ops->vidioc_try_fmt_vbi_out(file, fh, f); break; case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: + CLEAR_AFTER_FIELD(f, fmt.sliced); if (ops->vidioc_try_fmt_sliced_vbi_cap) ret = ops->vidioc_try_fmt_sliced_vbi_cap(file, fh, f); break; case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: + CLEAR_AFTER_FIELD(f, fmt.sliced); if (ops->vidioc_try_fmt_sliced_vbi_out) ret = ops->vidioc_try_fmt_sliced_vbi_out(file, fh, f); break; case V4L2_BUF_TYPE_PRIVATE: + /* CLEAR_AFTER_FIELD(f, fmt.raw_data); <- does nothing */ if (ops->vidioc_try_fmt_type_private) ret = ops->vidioc_try_fmt_type_private(file, fh, f); @@ -898,6 +922,9 @@ static long __video_do_ioctl(struct file *file, if (ret) break; + if (p->type < V4L2_BUF_TYPE_PRIVATE) + CLEAR_AFTER_FIELD(p, memory); + ret = ops->vidioc_reqbufs(file, fh, p); dbgarg(cmd, "count=%d, type=%s, memory=%s\n", p->count, diff --git a/drivers/media/video/zoran/zoran_driver.c b/drivers/media/video/zoran/zoran_driver.c index 092333b1c34..643cccaa1aa 100644 --- a/drivers/media/video/zoran/zoran_driver.c +++ b/drivers/media/video/zoran/zoran_driver.c @@ -1863,22 +1863,20 @@ static int zoran_querycap(struct file *file, void *__fh, struct v4l2_capability static int zoran_enum_fmt(struct zoran *zr, struct v4l2_fmtdesc *fmt, int flag) { - int num = -1, i; - - for (i = 0; i < NUM_FORMATS; i++) { - if (zoran_formats[i].flags & flag) - num++; - if (num == fmt->index) - break; + unsigned int num, i; + + for (num = i = 0; i < NUM_FORMATS; i++) { + if (zoran_formats[i].flags & flag && num++ == fmt->index) { + strncpy(fmt->description, zoran_formats[i].name, + sizeof(fmt->description) - 1); + /* fmt struct pre-zeroed, so adding '\0' not neeed */ + fmt->pixelformat = zoran_formats[i].fourcc; + if (zoran_formats[i].flags & ZORAN_FORMAT_COMPRESSED) + fmt->flags |= V4L2_FMT_FLAG_COMPRESSED; + return 0; + } } - if (fmt->index < 0 /* late, but not too late */ || i == NUM_FORMATS) - return -EINVAL; - - strncpy(fmt->description, zoran_formats[i].name, sizeof(fmt->description)-1); - fmt->pixelformat = zoran_formats[i].fourcc; - if (zoran_formats[i].flags & ZORAN_FORMAT_COMPRESSED) - fmt->flags |= V4L2_FMT_FLAG_COMPRESSED; - return 0; + return -EINVAL; } static int zoran_enum_fmt_vid_cap(struct file *file, void *__fh, diff --git a/drivers/misc/isl29003.c b/drivers/misc/isl29003.c index 2e2a5923d4c..a71e245801e 100644 --- a/drivers/misc/isl29003.c +++ b/drivers/misc/isl29003.c @@ -64,6 +64,7 @@ struct isl29003_data { struct i2c_client *client; struct mutex lock; u8 reg_cache[ISL29003_NUM_CACHABLE_REGS]; + u8 power_state_before_suspend; }; static int gain_range[] = { @@ -411,6 +412,9 @@ static int __devexit isl29003_remove(struct i2c_client *client) #ifdef CONFIG_PM static int isl29003_suspend(struct i2c_client *client, pm_message_t mesg) { + struct isl29003_data *data = i2c_get_clientdata(client); + + data->power_state_before_suspend = isl29003_get_power_state(client); return isl29003_set_power_state(client, 0); } @@ -421,10 +425,11 @@ static int isl29003_resume(struct i2c_client *client) /* restore registers from cache */ for (i = 0; i < ARRAY_SIZE(data->reg_cache); i++) - if (!i2c_smbus_write_byte_data(client, i, data->reg_cache[i])) + if (i2c_smbus_write_byte_data(client, i, data->reg_cache[i])) return -EIO; - return 0; + return isl29003_set_power_state(client, + data->power_state_before_suspend); } #else diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index fe8041e619e..b25e9b6516a 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -254,6 +254,14 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) brq.data.blocks = req->nr_sectors; /* + * The block layer doesn't support all sector count + * restrictions, so we need to be prepared for too big + * requests. + */ + if (brq.data.blocks > card->host->max_blk_count) + brq.data.blocks = card->host->max_blk_count; + + /* * After a read error, we redo the request one sector at a time * in order to accurately determine which sectors can be read * successfully. diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index fa073ab3fa3..26491173275 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -706,7 +706,7 @@ static void mmc_power_up(struct mmc_host *host) * This delay should be sufficient to allow the power supply * to reach the minimum voltage. */ - mmc_delay(2); + mmc_delay(10); host->ios.clock = host->f_min; host->ios.power_mode = MMC_POWER_ON; @@ -716,7 +716,7 @@ static void mmc_power_up(struct mmc_host *host) * This delay must be at least 74 clock sizes, or 1 ms, or the * time required to reach a stable voltage. */ - mmc_delay(2); + mmc_delay(10); } static void mmc_power_off(struct mmc_host *host) diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index a663429b3d5..36875dcfa49 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c @@ -514,6 +514,7 @@ static int __devinit mmci_probe(struct amba_device *dev, void *id) } host = mmc_priv(mmc); + host->mmc = mmc; /* Bits 12 thru 19 is the designer */ host->hw_designer = (dev->periphid >> 12) & 0xff; /* Bits 20 thru 23 is the revison */ @@ -545,7 +546,6 @@ static int __devinit mmci_probe(struct amba_device *dev, void *id) host->mclk = clk_get_rate(host->clk); DBG(host, "eventual mclk rate: %u Hz\n", host->mclk); } - host->mmc = mmc; host->base = ioremap(dev->res.start, SZ_4K); if (!host->base) { ret = -ENOMEM; diff --git a/drivers/mmc/host/mvsdio.c b/drivers/mmc/host/mvsdio.c index b5c375d94ab..c643d0fe118 100644 --- a/drivers/mmc/host/mvsdio.c +++ b/drivers/mmc/host/mvsdio.c @@ -825,24 +825,23 @@ static int __exit mvsd_remove(struct platform_device *pdev) } #ifdef CONFIG_PM -static int mvsd_suspend(struct platform_device *dev, pm_message_t state, - u32 level) +static int mvsd_suspend(struct platform_device *dev, pm_message_t state) { struct mmc_host *mmc = platform_get_drvdata(dev); int ret = 0; - if (mmc && level == SUSPEND_DISABLE) + if (mmc) ret = mmc_suspend_host(mmc, state); return ret; } -static int mvsd_resume(struct platform_device *dev, u32 level) +static int mvsd_resume(struct platform_device *dev) { - struct mmc_host *mmc = platform_dev_get_drvdata(dev); + struct mmc_host *mmc = platform_get_drvdata(dev); int ret = 0; - if (mmc && level == RESUME_ENABLE) + if (mmc) ret = mmc_resume_host(mmc); return ret; diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c index 5570849188c..bfa25c01c87 100644 --- a/drivers/mmc/host/omap.c +++ b/drivers/mmc/host/omap.c @@ -157,8 +157,6 @@ struct mmc_omap_host { struct timer_list dma_timer; unsigned dma_len; - short power_pin; - struct mmc_omap_slot *slots[OMAP_MMC_MAX_SLOTS]; struct mmc_omap_slot *current_slot; spinlock_t slot_lock; diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c index cd37962ec44..65be27995d5 100644 --- a/drivers/mmc/host/sdhci-pci.c +++ b/drivers/mmc/host/sdhci-pci.c @@ -522,8 +522,8 @@ static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot( host = sdhci_alloc_host(&pdev->dev, sizeof(struct sdhci_pci_slot)); if (IS_ERR(host)) { - ret = PTR_ERR(host); - goto unmap; + dev_err(&pdev->dev, "cannot allocate host\n"); + return ERR_PTR(PTR_ERR(host)); } slot = sdhci_priv(host); @@ -541,7 +541,7 @@ static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot( ret = pci_request_region(pdev, bar, mmc_hostname(host->mmc)); if (ret) { dev_err(&pdev->dev, "cannot request region\n"); - return ERR_PTR(ret); + goto free; } addr = pci_resource_start(pdev, bar); @@ -572,6 +572,8 @@ unmap: release: pci_release_region(pdev, bar); + +free: sdhci_free_host(host); return ERR_PTR(ret); diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index f20a834f430..65c6f996bbd 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -125,7 +125,7 @@ #define SDHCI_INT_DATA_MASK (SDHCI_INT_DATA_END | SDHCI_INT_DMA_END | \ SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL | \ SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_DATA_CRC | \ - SDHCI_INT_DATA_END_BIT) + SDHCI_INT_DATA_END_BIT | SDHCI_ADMA_ERROR) #define SDHCI_INT_ALL_MASK ((unsigned int)-1) #define SDHCI_ACMD12_ERR 0x3C diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c index 8185b1f3e5e..cc6369ea67d 100644 --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c @@ -54,7 +54,7 @@ #define SR_SRWD 0x80 /* SR write protect */ /* Define max times to check status register before we give up. */ -#define MAX_READY_WAIT_COUNT 100000 +#define MAX_READY_WAIT_JIFFIES (10 * HZ) /* eg. M25P128 specs 6s max sector erase */ #define CMD_SIZE 4 #ifdef CONFIG_M25PXX_USE_FAST_READ @@ -139,20 +139,20 @@ static inline int write_enable(struct m25p *flash) */ static int wait_till_ready(struct m25p *flash) { - int count; + unsigned long deadline; int sr; - /* one chip guarantees max 5 msec wait here after page writes, - * but potentially three seconds (!) after page erase. - */ - for (count = 0; count < MAX_READY_WAIT_COUNT; count++) { + deadline = jiffies + MAX_READY_WAIT_JIFFIES; + + do { if ((sr = read_sr(flash)) < 0) break; else if (!(sr & SR_WIP)) return 0; - /* REVISIT sometimes sleeping would be best */ - } + cond_resched(); + + } while (!time_after_eq(jiffies, deadline)); return 1; } @@ -246,10 +246,12 @@ static int m25p80_erase(struct mtd_info *mtd, struct erase_info *instr) mutex_lock(&flash->lock); /* whole-chip erase? */ - if (len == flash->mtd.size && erase_chip(flash)) { - instr->state = MTD_ERASE_FAILED; - mutex_unlock(&flash->lock); - return -EIO; + if (len == flash->mtd.size) { + if (erase_chip(flash)) { + instr->state = MTD_ERASE_FAILED; + mutex_unlock(&flash->lock); + return -EIO; + } /* REVISIT in some cases we could speed up erasing large regions * by using OPCODE_SE instead of OPCODE_BE_4K. We may have set up diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index fdd6ae85939..bccb4b1ffc4 100644 --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c @@ -48,11 +48,11 @@ static LIST_HEAD(mtd_notifiers); */ static void mtd_release(struct device *dev) { - struct mtd_info *mtd = dev_to_mtd(dev); + dev_t index = MTD_DEVT(dev_to_mtd(dev)->index); /* remove /dev/mtdXro node if needed */ - if (MTD_DEVT(mtd->index)) - device_destroy(mtd_class, MTD_DEVT(mtd->index) + 1); + if (index) + device_destroy(mtd_class, index + 1); } static ssize_t mtd_type_show(struct device *dev, @@ -132,6 +132,17 @@ static ssize_t mtd_writesize_show(struct device *dev, } static DEVICE_ATTR(writesize, S_IRUGO, mtd_writesize_show, NULL); +static ssize_t mtd_subpagesize_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct mtd_info *mtd = dev_to_mtd(dev); + unsigned int subpagesize = mtd->writesize >> mtd->subpage_sft; + + return snprintf(buf, PAGE_SIZE, "%u\n", subpagesize); + +} +static DEVICE_ATTR(subpagesize, S_IRUGO, mtd_subpagesize_show, NULL); + static ssize_t mtd_oobsize_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -169,6 +180,7 @@ static struct attribute *mtd_attrs[] = { &dev_attr_size.attr, &dev_attr_erasesize.attr, &dev_attr_writesize.attr, + &dev_attr_subpagesize.attr, &dev_attr_oobsize.attr, &dev_attr_numeraseregions.attr, &dev_attr_name.attr, diff --git a/drivers/mtd/mtdsuper.c b/drivers/mtd/mtdsuper.c index 92285d0089c..af8b42e0a55 100644 --- a/drivers/mtd/mtdsuper.c +++ b/drivers/mtd/mtdsuper.c @@ -74,8 +74,7 @@ static int get_sb_mtd_aux(struct file_system_type *fs_type, int flags, ret = fill_super(sb, data, flags & MS_SILENT ? 1 : 0); if (ret < 0) { - up_write(&sb->s_umount); - deactivate_super(sb); + deactivate_locked_super(sb); return ret; } diff --git a/drivers/net/arm/ixp4xx_eth.c b/drivers/net/arm/ixp4xx_eth.c index 448487e22fa..a740053d3af 100644 --- a/drivers/net/arm/ixp4xx_eth.c +++ b/drivers/net/arm/ixp4xx_eth.c @@ -338,12 +338,12 @@ static int ixp4xx_mdio_register(void) if (cpu_is_ixp43x()) { /* IXP43x lacks NPE-B and uses NPE-C for MII PHY access */ if (!(ixp4xx_read_feature_bits() & IXP4XX_FEATURE_NPEC_ETH)) - return -ENOSYS; + return -ENODEV; mdio_regs = (struct eth_regs __iomem *)IXP4XX_EthC_BASE_VIRT; } else { /* All MII PHY accesses use NPE-B Ethernet registers */ if (!(ixp4xx_read_feature_bits() & IXP4XX_FEATURE_NPEB_ETH0)) - return -ENOSYS; + return -ENODEV; mdio_regs = (struct eth_regs __iomem *)IXP4XX_EthB_BASE_VIRT; } @@ -1174,7 +1174,7 @@ static int __devinit eth_init_one(struct platform_device *pdev) regs_phys = IXP4XX_EthC_BASE_PHYS; break; default: - err = -ENOSYS; + err = -ENODEV; goto err_free; } @@ -1189,15 +1189,10 @@ static int __devinit eth_init_one(struct platform_device *pdev) goto err_free; } - if (register_netdev(dev)) { - err = -EIO; - goto err_npe_rel; - } - port->mem_res = request_mem_region(regs_phys, REGS_SIZE, dev->name); if (!port->mem_res) { err = -EBUSY; - goto err_unreg; + goto err_npe_rel; } port->plat = plat; @@ -1215,20 +1210,25 @@ static int __devinit eth_init_one(struct platform_device *pdev) snprintf(phy_id, BUS_ID_SIZE, PHY_ID_FMT, "0", plat->phy); port->phydev = phy_connect(dev, phy_id, &ixp4xx_adjust_link, 0, PHY_INTERFACE_MODE_MII); - if (IS_ERR(port->phydev)) { - printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name); - return PTR_ERR(port->phydev); - } + if ((err = IS_ERR(port->phydev))) + goto err_free_mem; port->phydev->irq = PHY_POLL; + if ((err = register_netdev(dev))) + goto err_phy_dis; + printk(KERN_INFO "%s: MII PHY %i on %s\n", dev->name, plat->phy, npe_name(port->npe)); return 0; -err_unreg: - unregister_netdev(dev); +err_phy_dis: + phy_disconnect(port->phydev); +err_free_mem: + npe_port_tab[NPE_ID(port->id)] = NULL; + platform_set_drvdata(pdev, NULL); + release_resource(port->mem_res); err_npe_rel: npe_release(port->npe); err_free: @@ -1242,6 +1242,7 @@ static int __devexit eth_remove_one(struct platform_device *pdev) struct port *port = netdev_priv(dev); unregister_netdev(dev); + phy_disconnect(port->phydev); npe_port_tab[NPE_ID(port->id)] = NULL; platform_set_drvdata(pdev, NULL); npe_release(port->npe); diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index d47839184a0..b0cb29d4cc0 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -54,8 +54,8 @@ #define DRV_MODULE_NAME "bnx2" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "2.0.0" -#define DRV_MODULE_RELDATE "April 2, 2009" +#define DRV_MODULE_VERSION "2.0.1" +#define DRV_MODULE_RELDATE "May 6, 2009" #define FW_MIPS_FILE_06 "bnx2/bnx2-mips-06-4.6.16.fw" #define FW_RV2P_FILE_06 "bnx2/bnx2-rv2p-06-4.6.16.fw" #define FW_MIPS_FILE_09 "bnx2/bnx2-mips-09-4.6.17.fw" @@ -2600,6 +2600,7 @@ bnx2_get_hw_tx_cons(struct bnx2_napi *bnapi) /* Tell compiler that status block fields can change. */ barrier(); cons = *bnapi->hw_tx_cons_ptr; + barrier(); if (unlikely((cons & MAX_TX_DESC_CNT) == MAX_TX_DESC_CNT)) cons++; return cons; @@ -2879,6 +2880,7 @@ bnx2_get_hw_rx_cons(struct bnx2_napi *bnapi) /* Tell compiler that status block fields can change. */ barrier(); cons = *bnapi->hw_rx_cons_ptr; + barrier(); if (unlikely((cons & MAX_RX_DESC_CNT) == MAX_RX_DESC_CNT)) cons++; return cons; diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c index 553a8991977..46d312bedfb 100644 --- a/drivers/net/bonding/bond_alb.c +++ b/drivers/net/bonding/bond_alb.c @@ -1706,10 +1706,8 @@ void bond_alb_handle_active_change(struct bonding *bond, struct slave *new_slave * Called with RTNL */ int bond_alb_set_mac_address(struct net_device *bond_dev, void *addr) - __releases(&bond->curr_slave_lock) - __releases(&bond->lock) __acquires(&bond->lock) - __acquires(&bond->curr_slave_lock) + __releases(&bond->lock) { struct bonding *bond = netdev_priv(bond_dev); struct sockaddr *sa = addr; @@ -1745,9 +1743,6 @@ int bond_alb_set_mac_address(struct net_device *bond_dev, void *addr) } } - write_unlock_bh(&bond->curr_slave_lock); - read_unlock(&bond->lock); - if (swap_slave) { alb_swap_mac_addr(bond, swap_slave, bond->curr_active_slave); alb_fasten_mac_swap(bond, swap_slave, bond->curr_active_slave); @@ -1755,16 +1750,15 @@ int bond_alb_set_mac_address(struct net_device *bond_dev, void *addr) alb_set_slave_mac_addr(bond->curr_active_slave, bond_dev->dev_addr, bond->alb_info.rlb_enabled); + read_lock(&bond->lock); alb_send_learning_packets(bond->curr_active_slave, bond_dev->dev_addr); if (bond->alb_info.rlb_enabled) { /* inform clients mac address has changed */ rlb_req_update_slave_clients(bond, bond->curr_active_slave); } + read_unlock(&bond->lock); } - read_lock(&bond->lock); - write_lock_bh(&bond->curr_slave_lock); - return 0; } diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 63369b6b14d..74824028f85 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -2213,33 +2213,24 @@ static int bond_slave_info_query(struct net_device *bond_dev, struct ifslave *in { struct bonding *bond = netdev_priv(bond_dev); struct slave *slave; - int i, found = 0; - - if (info->slave_id < 0) { - return -ENODEV; - } + int i, res = -ENODEV; read_lock(&bond->lock); bond_for_each_slave(bond, slave, i) { if (i == (int)info->slave_id) { - found = 1; + res = 0; + strcpy(info->slave_name, slave->dev->name); + info->link = slave->link; + info->state = slave->state; + info->link_failure_count = slave->link_failure_count; break; } } read_unlock(&bond->lock); - if (found) { - strcpy(info->slave_name, slave->dev->name); - info->link = slave->link; - info->state = slave->state; - info->link_failure_count = slave->link_failure_count; - } else { - return -ENODEV; - } - - return 0; + return res; } /*-------------------------------- Monitoring -------------------------------*/ @@ -5167,16 +5158,15 @@ int bond_create(char *name, struct bond_params *params) up_write(&bonding_rwsem); rtnl_unlock(); /* allows sysfs registration of net device */ res = bond_create_sysfs_entry(netdev_priv(bond_dev)); - if (res < 0) { - rtnl_lock(); - down_write(&bonding_rwsem); - bond_deinit(bond_dev); - unregister_netdevice(bond_dev); - goto out_rtnl; - } + if (res < 0) + goto out_unreg; return 0; +out_unreg: + rtnl_lock(); + down_write(&bonding_rwsem); + unregister_netdevice(bond_dev); out_bond: bond_deinit(bond_dev); out_netdev: @@ -5191,7 +5181,6 @@ static int __init bonding_init(void) { int i; int res; - struct bonding *bond; printk(KERN_INFO "%s", version); @@ -5222,13 +5211,6 @@ static int __init bonding_init(void) goto out; err: - list_for_each_entry(bond, &bond_dev_list, bond_list) { - bond_work_cancel_all(bond); - destroy_workqueue(bond->wq); - } - - bond_destroy_sysfs(); - rtnl_lock(); bond_free_all(); rtnl_unlock(); diff --git a/drivers/net/cxgb3/t3_hw.c b/drivers/net/cxgb3/t3_hw.c index e1bd690ff83..4f68aeb2679 100644 --- a/drivers/net/cxgb3/t3_hw.c +++ b/drivers/net/cxgb3/t3_hw.c @@ -3779,7 +3779,7 @@ int t3_prep_adapter(struct adapter *adapter, const struct adapter_info *ai, adapter->params.info = ai; adapter->params.nports = ai->nports0 + ai->nports1; - adapter->params.chan_map = !!ai->nports0 | (!!ai->nports1 << 1); + adapter->params.chan_map = (!!ai->nports0) | (!!ai->nports1 << 1); adapter->params.rev = t3_read_reg(adapter, A_PL_REV); /* * We used to only run the "adapter check task" once a second if diff --git a/drivers/net/e100.c b/drivers/net/e100.c index 5c0b457c786..0f9ee134855 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c @@ -2728,7 +2728,7 @@ static void __devexit e100_remove(struct pci_dev *pdev) #define E100_82552_SMARTSPEED 0x14 /* SmartSpeed Ctrl register */ #define E100_82552_REV_ANEG 0x0200 /* Reverse auto-negotiation */ #define E100_82552_ANEG_NOW 0x0400 /* Auto-negotiate now */ -static int e100_suspend(struct pci_dev *pdev, pm_message_t state) +static void __e100_shutdown(struct pci_dev *pdev, bool *enable_wake) { struct net_device *netdev = pci_get_drvdata(pdev); struct nic *nic = netdev_priv(netdev); @@ -2749,19 +2749,32 @@ static int e100_suspend(struct pci_dev *pdev, pm_message_t state) E100_82552_SMARTSPEED, smartspeed | E100_82552_REV_ANEG | E100_82552_ANEG_NOW); } - if (pci_enable_wake(pdev, PCI_D3cold, true)) - pci_enable_wake(pdev, PCI_D3hot, true); + *enable_wake = true; } else { - pci_enable_wake(pdev, PCI_D3hot, false); + *enable_wake = false; } pci_disable_device(pdev); - pci_set_power_state(pdev, PCI_D3hot); +} - return 0; +static int __e100_power_off(struct pci_dev *pdev, bool wake) +{ + if (wake) { + return pci_prepare_to_sleep(pdev); + } else { + pci_wake_from_d3(pdev, false); + return pci_set_power_state(pdev, PCI_D3hot); + } } #ifdef CONFIG_PM +static int e100_suspend(struct pci_dev *pdev, pm_message_t state) +{ + bool wake; + __e100_shutdown(pdev, &wake); + return __e100_power_off(pdev, wake); +} + static int e100_resume(struct pci_dev *pdev) { struct net_device *netdev = pci_get_drvdata(pdev); @@ -2792,7 +2805,10 @@ static int e100_resume(struct pci_dev *pdev) static void e100_shutdown(struct pci_dev *pdev) { - e100_suspend(pdev, PMSG_SUSPEND); + bool wake; + __e100_shutdown(pdev, &wake); + if (system_state == SYSTEM_POWER_OFF) + __e100_power_off(pdev, wake); } /* ------------------ PCI Error Recovery infrastructure -------------- */ diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 6a46ceed943..b1419e21b46 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -3738,7 +3738,7 @@ static irqreturn_t e1000_intr(int irq, void *data) struct e1000_hw *hw = &adapter->hw; u32 rctl, icr = er32(ICR); - if (unlikely((!icr) || test_bit(__E1000_RESETTING, &adapter->flags))) + if (unlikely((!icr) || test_bit(__E1000_DOWN, &adapter->flags))) return IRQ_NONE; /* Not our interrupt */ /* IMS will not auto-mask if INT_ASSERTED is not set, and if it is diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h index 6e317caf429..16a41389575 100644 --- a/drivers/net/ehea/ehea.h +++ b/drivers/net/ehea/ehea.h @@ -40,7 +40,7 @@ #include <asm/io.h> #define DRV_NAME "ehea" -#define DRV_VERSION "EHEA_0100" +#define DRV_VERSION "EHEA_0101" /* eHEA capability flags */ #define DLPAR_PORT_ADD_REM 1 diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index 604c844d076..b22dab9153f 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c @@ -545,14 +545,17 @@ static inline struct sk_buff *get_skb_by_index(struct sk_buff **skb_array, x &= (arr_len - 1); pref = skb_array[x]; - prefetchw(pref); - prefetchw(pref + EHEA_CACHE_LINE); - - pref = (skb_array[x]->data); - prefetch(pref); - prefetch(pref + EHEA_CACHE_LINE); - prefetch(pref + EHEA_CACHE_LINE * 2); - prefetch(pref + EHEA_CACHE_LINE * 3); + if (pref) { + prefetchw(pref); + prefetchw(pref + EHEA_CACHE_LINE); + + pref = (skb_array[x]->data); + prefetch(pref); + prefetch(pref + EHEA_CACHE_LINE); + prefetch(pref + EHEA_CACHE_LINE * 2); + prefetch(pref + EHEA_CACHE_LINE * 3); + } + skb = skb_array[skb_index]; skb_array[skb_index] = NULL; return skb; @@ -569,12 +572,14 @@ static inline struct sk_buff *get_skb_by_index_ll(struct sk_buff **skb_array, x &= (arr_len - 1); pref = skb_array[x]; - prefetchw(pref); - prefetchw(pref + EHEA_CACHE_LINE); + if (pref) { + prefetchw(pref); + prefetchw(pref + EHEA_CACHE_LINE); - pref = (skb_array[x]->data); - prefetchw(pref); - prefetchw(pref + EHEA_CACHE_LINE); + pref = (skb_array[x]->data); + prefetchw(pref); + prefetchw(pref + EHEA_CACHE_LINE); + } skb = skb_array[wqe_index]; skb_array[wqe_index] = NULL; diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 11d5db16ed9..f9a846b1b92 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -1880,6 +1880,7 @@ static void nv_init_tx(struct net_device *dev) np->tx_pkts_in_progress = 0; np->tx_change_owner = NULL; np->tx_end_flip = NULL; + np->tx_stop = 0; for (i = 0; i < np->tx_ring_size; i++) { if (!nv_optimized(np)) { @@ -2530,6 +2531,8 @@ static void nv_tx_timeout(struct net_device *dev) struct fe_priv *np = netdev_priv(dev); u8 __iomem *base = get_hwbase(dev); u32 status; + union ring_type put_tx; + int saved_tx_limit; if (np->msi_flags & NV_MSI_X_ENABLED) status = readl(base + NvRegMSIXIrqStatus) & NVREG_IRQSTAT_MASK; @@ -2589,24 +2592,32 @@ static void nv_tx_timeout(struct net_device *dev) /* 1) stop tx engine */ nv_stop_tx(dev); - /* 2) check that the packets were not sent already: */ + /* 2) complete any outstanding tx and do not give HW any limited tx pkts */ + saved_tx_limit = np->tx_limit; + np->tx_limit = 0; /* prevent giving HW any limited pkts */ + np->tx_stop = 0; /* prevent waking tx queue */ if (!nv_optimized(np)) nv_tx_done(dev, np->tx_ring_size); else nv_tx_done_optimized(dev, np->tx_ring_size); - /* 3) if there are dead entries: clear everything */ - if (np->get_tx_ctx != np->put_tx_ctx) { - printk(KERN_DEBUG "%s: tx_timeout: dead entries!\n", dev->name); - nv_drain_tx(dev); - nv_init_tx(dev); - setup_hw_rings(dev, NV_SETUP_TX_RING); - } + /* save current HW postion */ + if (np->tx_change_owner) + put_tx.ex = np->tx_change_owner->first_tx_desc; + else + put_tx = np->put_tx; - netif_wake_queue(dev); + /* 3) clear all tx state */ + nv_drain_tx(dev); + nv_init_tx(dev); + + /* 4) restore state to current HW position */ + np->get_tx = np->put_tx = put_tx; + np->tx_limit = saved_tx_limit; - /* 4) restart tx engine */ + /* 5) restart tx engine */ nv_start_tx(dev); + netif_wake_queue(dev); spin_unlock_irq(&np->lock); } diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 08c801490c7..e25343588fc 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -2006,7 +2006,7 @@ static void igb_setup_rctl(struct igb_adapter *adapter) struct e1000_hw *hw = &adapter->hw; u32 rctl; u32 srrctl = 0; - int i, j; + int i; rctl = rd32(E1000_RCTL); @@ -2071,8 +2071,6 @@ static void igb_setup_rctl(struct igb_adapter *adapter) if (adapter->vfs_allocated_count) { u32 vmolr; - j = adapter->rx_ring[0].reg_idx; - /* set all queue drop enable bits */ wr32(E1000_QDE, ALL_QUEUES); srrctl |= E1000_SRRCTL_DROP_EN; @@ -2080,16 +2078,16 @@ static void igb_setup_rctl(struct igb_adapter *adapter) /* disable queue 0 to prevent tail write w/o re-config */ wr32(E1000_RXDCTL(0), 0); - vmolr = rd32(E1000_VMOLR(j)); + vmolr = rd32(E1000_VMOLR(adapter->vfs_allocated_count)); if (rctl & E1000_RCTL_LPE) vmolr |= E1000_VMOLR_LPE; - if (adapter->num_rx_queues > 0) + if (adapter->num_rx_queues > 1) vmolr |= E1000_VMOLR_RSSE; - wr32(E1000_VMOLR(j), vmolr); + wr32(E1000_VMOLR(adapter->vfs_allocated_count), vmolr); } for (i = 0; i < adapter->num_rx_queues; i++) { - j = adapter->rx_ring[i].reg_idx; + int j = adapter->rx_ring[i].reg_idx; wr32(E1000_SRRCTL(j), srrctl); } diff --git a/drivers/net/ixgbe/ixgbe_common.c b/drivers/net/ixgbe/ixgbe_common.c index 5567519676d..186a65069b3 100644 --- a/drivers/net/ixgbe/ixgbe_common.c +++ b/drivers/net/ixgbe/ixgbe_common.c @@ -50,7 +50,6 @@ static u16 ixgbe_calc_eeprom_checksum(struct ixgbe_hw *hw); static void ixgbe_enable_rar(struct ixgbe_hw *hw, u32 index); static void ixgbe_disable_rar(struct ixgbe_hw *hw, u32 index); static s32 ixgbe_mta_vector(struct ixgbe_hw *hw, u8 *mc_addr); -static void ixgbe_add_mc_addr(struct ixgbe_hw *hw, u8 *mc_addr); static void ixgbe_add_uc_addr(struct ixgbe_hw *hw, u8 *addr, u32 vmdq); /** @@ -1377,8 +1376,7 @@ s32 ixgbe_update_uc_addr_list_generic(struct ixgbe_hw *hw, u8 *addr_list, * Clear accounting of old secondary address list, * don't count RAR[0] */ - uc_addr_in_use = hw->addr_ctrl.rar_used_count - - hw->addr_ctrl.mc_addr_in_rar_count - 1; + uc_addr_in_use = hw->addr_ctrl.rar_used_count - 1; hw->addr_ctrl.rar_used_count -= uc_addr_in_use; hw->addr_ctrl.overflow_promisc = 0; @@ -1493,40 +1491,6 @@ static void ixgbe_set_mta(struct ixgbe_hw *hw, u8 *mc_addr) } /** - * ixgbe_add_mc_addr - Adds a multicast address. - * @hw: pointer to hardware structure - * @mc_addr: new multicast address - * - * Adds it to unused receive address register or to the multicast table. - **/ -static void ixgbe_add_mc_addr(struct ixgbe_hw *hw, u8 *mc_addr) -{ - u32 rar_entries = hw->mac.num_rar_entries; - u32 rar; - - hw_dbg(hw, " MC Addr =%.2X %.2X %.2X %.2X %.2X %.2X\n", - mc_addr[0], mc_addr[1], mc_addr[2], - mc_addr[3], mc_addr[4], mc_addr[5]); - - /* - * Place this multicast address in the RAR if there is room, - * else put it in the MTA - */ - if (hw->addr_ctrl.rar_used_count < rar_entries) { - /* use RAR from the end up for multicast */ - rar = rar_entries - hw->addr_ctrl.mc_addr_in_rar_count - 1; - hw->mac.ops.set_rar(hw, rar, mc_addr, 0, IXGBE_RAH_AV); - hw_dbg(hw, "Added a multicast address to RAR[%d]\n", rar); - hw->addr_ctrl.rar_used_count++; - hw->addr_ctrl.mc_addr_in_rar_count++; - } else { - ixgbe_set_mta(hw, mc_addr); - } - - hw_dbg(hw, "ixgbe_add_mc_addr Complete\n"); -} - -/** * ixgbe_update_mc_addr_list_generic - Updates MAC list of multicast addresses * @hw: pointer to hardware structure * @mc_addr_list: the list of new multicast addresses @@ -1542,7 +1506,6 @@ s32 ixgbe_update_mc_addr_list_generic(struct ixgbe_hw *hw, u8 *mc_addr_list, u32 mc_addr_count, ixgbe_mc_addr_itr next) { u32 i; - u32 rar_entries = hw->mac.num_rar_entries; u32 vmdq; /* @@ -1550,18 +1513,8 @@ s32 ixgbe_update_mc_addr_list_generic(struct ixgbe_hw *hw, u8 *mc_addr_list, * use. */ hw->addr_ctrl.num_mc_addrs = mc_addr_count; - hw->addr_ctrl.rar_used_count -= hw->addr_ctrl.mc_addr_in_rar_count; - hw->addr_ctrl.mc_addr_in_rar_count = 0; hw->addr_ctrl.mta_in_use = 0; - /* Zero out the other receive addresses. */ - hw_dbg(hw, "Clearing RAR[%d-%d]\n", hw->addr_ctrl.rar_used_count, - rar_entries - 1); - for (i = hw->addr_ctrl.rar_used_count; i < rar_entries; i++) { - IXGBE_WRITE_REG(hw, IXGBE_RAL(i), 0); - IXGBE_WRITE_REG(hw, IXGBE_RAH(i), 0); - } - /* Clear the MTA */ hw_dbg(hw, " Clearing MTA\n"); for (i = 0; i < hw->mac.mcft_size; i++) @@ -1570,7 +1523,7 @@ s32 ixgbe_update_mc_addr_list_generic(struct ixgbe_hw *hw, u8 *mc_addr_list, /* Add the new addresses */ for (i = 0; i < mc_addr_count; i++) { hw_dbg(hw, " Adding the multicast addresses:\n"); - ixgbe_add_mc_addr(hw, next(hw, &mc_addr_list, &vmdq)); + ixgbe_set_mta(hw, next(hw, &mc_addr_list, &vmdq)); } /* Enable mta */ diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 01884256f4c..07e778d3e5d 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -3646,6 +3646,8 @@ static int ixgbe_resume(struct pci_dev *pdev) ixgbe_reset(adapter); + IXGBE_WRITE_REG(&adapter->hw, IXGBE_WUS, ~0); + if (netif_running(netdev)) { err = ixgbe_open(adapter->netdev); if (err) @@ -4575,7 +4577,6 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, const struct ixgbe_info *ii = ixgbe_info_tbl[ent->driver_data]; static int cards_found; int i, err, pci_using_dac; - u16 pm_value = 0; u32 part_num, eec; err = pci_enable_device(pdev); @@ -4763,11 +4764,8 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, switch (pdev->device) { case IXGBE_DEV_ID_82599_KX4: -#define IXGBE_PCIE_PMCSR 0x44 - adapter->wol = IXGBE_WUFC_MAG; - pci_read_config_word(pdev, IXGBE_PCIE_PMCSR, &pm_value); - pci_write_config_word(pdev, IXGBE_PCIE_PMCSR, - (pm_value | (1 << 8))); + adapter->wol = (IXGBE_WUFC_MAG | IXGBE_WUFC_EX | + IXGBE_WUFC_MC | IXGBE_WUFC_BC); break; default: adapter->wol = 0; diff --git a/drivers/net/mlx4/en_netdev.c b/drivers/net/mlx4/en_netdev.c index 438678ab2a1..7bcc49de163 100644 --- a/drivers/net/mlx4/en_netdev.c +++ b/drivers/net/mlx4/en_netdev.c @@ -583,7 +583,7 @@ int mlx4_en_start_port(struct net_device *dev) err = mlx4_en_activate_cq(priv, cq); if (err) { mlx4_err(mdev, "Failed activating Rx CQ\n"); - goto rx_err; + goto cq_err; } for (j = 0; j < cq->size; j++) cq->buf[j].owner_sr_opcode = MLX4_CQE_OWNER_MASK; diff --git a/drivers/net/mlx4/en_rx.c b/drivers/net/mlx4/en_rx.c index 0cbb78ca7b2..9ee873e872b 100644 --- a/drivers/net/mlx4/en_rx.c +++ b/drivers/net/mlx4/en_rx.c @@ -610,6 +610,10 @@ static struct sk_buff *mlx4_en_rx_skb(struct mlx4_en_priv *priv, used_frags = mlx4_en_complete_rx_desc(priv, rx_desc, skb_frags, skb_shinfo(skb)->frags, page_alloc, length); + if (unlikely(!used_frags)) { + kfree_skb(skb); + return NULL; + } skb_shinfo(skb)->nr_frags = used_frags; /* Copy headers into the skb linear buffer */ @@ -947,7 +951,6 @@ static int mlx4_en_config_rss_qp(struct mlx4_en_priv *priv, if (err) { mlx4_err(mdev, "Failed to allocate qp #%d\n", qpn); goto out; - return err; } qp->event = mlx4_en_sqp_event; diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index b3185bf2c15..a400d7115f7 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -393,12 +393,12 @@ struct mv643xx_eth_private { struct work_struct tx_timeout_task; struct napi_struct napi; + u8 oom; u8 work_link; u8 work_tx; u8 work_tx_end; u8 work_rx; u8 work_rx_refill; - u8 work_rx_oom; int skb_size; struct sk_buff_head rx_recycle; @@ -661,7 +661,7 @@ static int rxq_refill(struct rx_queue *rxq, int budget) dma_get_cache_alignment() - 1); if (skb == NULL) { - mp->work_rx_oom |= 1 << rxq->index; + mp->oom = 1; goto oom; } @@ -1255,7 +1255,6 @@ static void mib_counters_update(struct mv643xx_eth_private *mp) spin_lock_bh(&mp->mib_counters_lock); p->good_octets_received += mib_read(mp, 0x00); - p->good_octets_received += (u64)mib_read(mp, 0x04) << 32; p->bad_octets_received += mib_read(mp, 0x08); p->internal_mac_transmit_err += mib_read(mp, 0x0c); p->good_frames_received += mib_read(mp, 0x10); @@ -1269,7 +1268,6 @@ static void mib_counters_update(struct mv643xx_eth_private *mp) p->frames_512_to_1023_octets += mib_read(mp, 0x30); p->frames_1024_to_max_octets += mib_read(mp, 0x34); p->good_octets_sent += mib_read(mp, 0x38); - p->good_octets_sent += (u64)mib_read(mp, 0x3c) << 32; p->good_frames_sent += mib_read(mp, 0x40); p->excessive_collision += mib_read(mp, 0x44); p->multicast_frames_sent += mib_read(mp, 0x48); @@ -2167,8 +2165,10 @@ static int mv643xx_eth_poll(struct napi_struct *napi, int budget) mp = container_of(napi, struct mv643xx_eth_private, napi); - mp->work_rx_refill |= mp->work_rx_oom; - mp->work_rx_oom = 0; + if (unlikely(mp->oom)) { + mp->oom = 0; + del_timer(&mp->rx_oom); + } work_done = 0; while (work_done < budget) { @@ -2182,8 +2182,10 @@ static int mv643xx_eth_poll(struct napi_struct *napi, int budget) continue; } - queue_mask = mp->work_tx | mp->work_tx_end | - mp->work_rx | mp->work_rx_refill; + queue_mask = mp->work_tx | mp->work_tx_end | mp->work_rx; + if (likely(!mp->oom)) + queue_mask |= mp->work_rx_refill; + if (!queue_mask) { if (mv643xx_eth_collect_events(mp)) continue; @@ -2204,7 +2206,7 @@ static int mv643xx_eth_poll(struct napi_struct *napi, int budget) txq_maybe_wake(mp->txq + queue); } else if (mp->work_rx & queue_mask) { work_done += rxq_process(mp->rxq + queue, work_tbd); - } else if (mp->work_rx_refill & queue_mask) { + } else if (!mp->oom && (mp->work_rx_refill & queue_mask)) { work_done += rxq_refill(mp->rxq + queue, work_tbd); } else { BUG(); @@ -2212,7 +2214,7 @@ static int mv643xx_eth_poll(struct napi_struct *napi, int budget) } if (work_done < budget) { - if (mp->work_rx_oom) + if (mp->oom) mod_timer(&mp->rx_oom, jiffies + (HZ / 10)); napi_complete(napi); wrlp(mp, INT_MASK, INT_TX_END | INT_RX | INT_EXT); @@ -2372,7 +2374,7 @@ static int mv643xx_eth_open(struct net_device *dev) rxq_refill(mp->rxq + i, INT_MAX); } - if (mp->work_rx_oom) { + if (mp->oom) { mp->rx_oom.expires = jiffies + (HZ / 10); add_timer(&mp->rx_oom); } diff --git a/drivers/net/ne2k-pci.c b/drivers/net/ne2k-pci.c index eb66f658f9d..7d83896b8c2 100644 --- a/drivers/net/ne2k-pci.c +++ b/drivers/net/ne2k-pci.c @@ -374,18 +374,17 @@ static int __devinit ne2k_pci_init_one (struct pci_dev *pdev, dev->ethtool_ops = &ne2k_pci_ethtool_ops; NS8390_init(dev, 0); + memcpy(dev->dev_addr, SA_prom, 6); + memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); + i = register_netdev(dev); if (i) goto err_out_free_netdev; - for(i = 0; i < 6; i++) - dev->dev_addr[i] = SA_prom[i]; printk("%s: %s found at %#lx, IRQ %d, %pM.\n", dev->name, pci_clone_list[chip_idx].name, ioaddr, dev->irq, dev->dev_addr); - memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); - return 0; err_out_free_netdev: diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c index eceadf787a6..bf4af5248cb 100644 --- a/drivers/net/netconsole.c +++ b/drivers/net/netconsole.c @@ -664,7 +664,7 @@ static int netconsole_netdev_event(struct notifier_block *this, struct netconsole_target *nt; struct net_device *dev = ptr; - if (!(event == NETDEV_CHANGENAME)) + if (!(event == NETDEV_CHANGENAME || event == NETDEV_UNREGISTER)) goto done; spin_lock_irqsave(&target_list_lock, flags); @@ -675,6 +675,15 @@ static int netconsole_netdev_event(struct notifier_block *this, case NETDEV_CHANGENAME: strlcpy(nt->np.dev_name, dev->name, IFNAMSIZ); break; + case NETDEV_UNREGISTER: + if (!nt->enabled) + break; + netpoll_cleanup(&nt->np); + nt->enabled = 0; + printk(KERN_INFO "netconsole: network logging stopped" + ", interface %s unregistered\n", + dev->name); + break; } } netconsole_target_put(nt); diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig index 8ee21030e9a..dfc6cf765fb 100644 --- a/drivers/net/usb/Kconfig +++ b/drivers/net/usb/Kconfig @@ -180,6 +180,20 @@ config USB_NET_CDCETHER IEEE 802 "local assignment" bit is set in the address, a "usbX" name is used instead. +config USB_NET_CDC_EEM + tristate "CDC EEM support" + depends on USB_USBNET && EXPERIMENTAL + help + This option supports devices conforming to the Communication Device + Class (CDC) Ethernet Emulation Model, a specification that's easy to + implement in device firmware. The CDC EEM specifications are available + from <http://www.usb.org/>. + + This driver creates an interface named "ethX", where X depends on + what other networking devices you have in use. However, if the + IEEE 802 "local assignment" bit is set in the address, a "usbX" + name is used instead. + config USB_NET_DM9601 tristate "Davicom DM9601 based USB 1.1 10/100 ethernet devices" depends on USB_USBNET diff --git a/drivers/net/usb/Makefile b/drivers/net/usb/Makefile index 88a87eeb376..c8aef62cf2b 100644 --- a/drivers/net/usb/Makefile +++ b/drivers/net/usb/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_USB_RTL8150) += rtl8150.o obj-$(CONFIG_USB_HSO) += hso.o obj-$(CONFIG_USB_NET_AX8817X) += asix.o obj-$(CONFIG_USB_NET_CDCETHER) += cdc_ether.o +obj-$(CONFIG_USB_NET_CDC_EEM) += cdc_eem.o obj-$(CONFIG_USB_NET_DM9601) += dm9601.o obj-$(CONFIG_USB_NET_SMSC95XX) += smsc95xx.o obj-$(CONFIG_USB_NET_GL620A) += gl620a.o diff --git a/drivers/net/usb/cdc_eem.c b/drivers/net/usb/cdc_eem.c new file mode 100644 index 00000000000..80e01778dd3 --- /dev/null +++ b/drivers/net/usb/cdc_eem.c @@ -0,0 +1,381 @@ +/* + * USB CDC EEM network interface driver + * Copyright (C) 2009 Oberthur Technologies + * by Omar Laazimani, Olivier Condemine + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/netdevice.h> +#include <linux/etherdevice.h> +#include <linux/ctype.h> +#include <linux/ethtool.h> +#include <linux/workqueue.h> +#include <linux/mii.h> +#include <linux/usb.h> +#include <linux/crc32.h> +#include <linux/usb/cdc.h> +#include <linux/usb/usbnet.h> + + +/* + * This driver is an implementation of the CDC "Ethernet Emulation + * Model" (EEM) specification, which encapsulates Ethernet frames + * for transport over USB using a simpler USB device model than the + * previous CDC "Ethernet Control Model" (ECM, or "CDC Ethernet"). + * + * For details, see www.usb.org/developers/devclass_docs/CDC_EEM10.pdf + * + * This version has been tested with GIGAntIC WuaoW SIM Smart Card on 2.6.24, + * 2.6.27 and 2.6.30rc2 kernel. + * It has also been validated on Openmoko Om 2008.12 (based on 2.6.24 kernel). + * build on 23-April-2009 + */ + +#define EEM_HEAD 2 /* 2 byte header */ + +/*-------------------------------------------------------------------------*/ + +static void eem_linkcmd_complete(struct urb *urb) +{ + dev_kfree_skb(urb->context); + usb_free_urb(urb); +} + +static void eem_linkcmd(struct usbnet *dev, struct sk_buff *skb) +{ + struct urb *urb; + int status; + + urb = usb_alloc_urb(0, GFP_ATOMIC); + if (!urb) + goto fail; + + usb_fill_bulk_urb(urb, dev->udev, dev->out, + skb->data, skb->len, eem_linkcmd_complete, skb); + + status = usb_submit_urb(urb, GFP_ATOMIC); + if (status) { + usb_free_urb(urb); +fail: + dev_kfree_skb(skb); + devwarn(dev, "link cmd failure\n"); + return; + } +} + +static int eem_bind(struct usbnet *dev, struct usb_interface *intf) +{ + int status = 0; + + status = usbnet_get_endpoints(dev, intf); + if (status < 0) { + usb_set_intfdata(intf, NULL); + usb_driver_release_interface(driver_of(intf), intf); + return status; + } + + /* no jumbogram (16K) support for now */ + + dev->net->hard_header_len += EEM_HEAD + ETH_FCS_LEN; + + return 0; +} + +/* + * EEM permits packing multiple Ethernet frames into USB transfers + * (a "bundle"), but for TX we don't try to do that. + */ +static struct sk_buff *eem_tx_fixup(struct usbnet *dev, struct sk_buff *skb, + gfp_t flags) +{ + struct sk_buff *skb2 = NULL; + u16 len = skb->len; + u32 crc = 0; + int padlen = 0; + + /* When ((len + EEM_HEAD + ETH_FCS_LEN) % dev->maxpacket) is + * zero, stick two bytes of zero length EEM packet on the end. + * Else the framework would add invalid single byte padding, + * since it can't know whether ZLPs will be handled right by + * all the relevant hardware and software. + */ + if (!((len + EEM_HEAD + ETH_FCS_LEN) % dev->maxpacket)) + padlen += 2; + + if (!skb_cloned(skb)) { + int headroom = skb_headroom(skb); + int tailroom = skb_tailroom(skb); + + if ((tailroom >= ETH_FCS_LEN + padlen) + && (headroom >= EEM_HEAD)) + goto done; + + if ((headroom + tailroom) + > (EEM_HEAD + ETH_FCS_LEN + padlen)) { + skb->data = memmove(skb->head + + EEM_HEAD, + skb->data, + skb->len); + skb_set_tail_pointer(skb, len); + goto done; + } + } + + skb2 = skb_copy_expand(skb, EEM_HEAD, ETH_FCS_LEN + padlen, flags); + if (!skb2) + return NULL; + + dev_kfree_skb_any(skb); + skb = skb2; + +done: + /* we don't use the "no Ethernet CRC" option */ + crc = crc32_le(~0, skb->data, skb->len); + crc = ~crc; + + put_unaligned_le32(crc, skb_put(skb, 4)); + + /* EEM packet header format: + * b0..13: length of ethernet frame + * b14: bmCRC (1 == valid Ethernet CRC) + * b15: bmType (0 == data) + */ + len = skb->len; + put_unaligned_le16(BIT(14) | len, skb_push(skb, 2)); + + /* Bundle a zero length EEM packet if needed */ + if (padlen) + put_unaligned_le16(0, skb_put(skb, 2)); + + return skb; +} + +static int eem_rx_fixup(struct usbnet *dev, struct sk_buff *skb) +{ + /* + * Our task here is to strip off framing, leaving skb with one + * data frame for the usbnet framework code to process. But we + * may have received multiple EEM payloads, or command payloads. + * So we must process _everything_ as if it's a header, except + * maybe the last data payload + * + * REVISIT the framework needs updating so that when we consume + * all payloads (the last or only message was a command, or a + * zero length EEM packet) that is not accounted as an rx_error. + */ + do { + struct sk_buff *skb2 = NULL; + u16 header; + u16 len = 0; + + /* incomplete EEM header? */ + if (skb->len < EEM_HEAD) + return 0; + + /* + * EEM packet header format: + * b0..14: EEM type dependant (Data or Command) + * b15: bmType + */ + header = get_unaligned_le16(skb->data); + skb_pull(skb, EEM_HEAD); + + /* + * The bmType bit helps to denote when EEM + * packet is data or command : + * bmType = 0 : EEM data payload + * bmType = 1 : EEM (link) command + */ + if (header & BIT(15)) { + u16 bmEEMCmd; + + /* + * EEM (link) command packet: + * b0..10: bmEEMCmdParam + * b11..13: bmEEMCmd + * b14: bmReserved (must be 0) + * b15: 1 (EEM command) + */ + if (header & BIT(14)) { + devdbg(dev, "reserved command %04x\n", header); + continue; + } + + bmEEMCmd = (header >> 11) & 0x7; + switch (bmEEMCmd) { + + /* Responding to echo requests is mandatory. */ + case 0: /* Echo command */ + len = header & 0x7FF; + + /* bogus command? */ + if (skb->len < len) + return 0; + + skb2 = skb_clone(skb, GFP_ATOMIC); + if (unlikely(!skb2)) + goto next; + skb_trim(skb2, len); + put_unaligned_le16(BIT(15) | (1 << 11) | len, + skb_push(skb2, 2)); + eem_linkcmd(dev, skb2); + break; + + /* + * Host may choose to ignore hints. + * - suspend: peripheral ready to suspend + * - response: suggest N millisec polling + * - response complete: suggest N sec polling + */ + case 2: /* Suspend hint */ + case 3: /* Response hint */ + case 4: /* Response complete hint */ + continue; + + /* + * Hosts should never receive host-to-peripheral + * or reserved command codes; or responses to an + * echo command we didn't send. + */ + case 1: /* Echo response */ + case 5: /* Tickle */ + default: /* reserved */ + devwarn(dev, "unexpected link command %d\n", + bmEEMCmd); + continue; + } + + } else { + u32 crc, crc2; + int is_last; + + /* zero length EEM packet? */ + if (header == 0) + continue; + + /* + * EEM data packet header : + * b0..13: length of ethernet frame + * b14: bmCRC + * b15: 0 (EEM data) + */ + len = header & 0x3FFF; + + /* bogus EEM payload? */ + if (skb->len < len) + return 0; + + /* bogus ethernet frame? */ + if (len < (ETH_HLEN + ETH_FCS_LEN)) + goto next; + + /* + * Treat the last payload differently: framework + * code expects our "fixup" to have stripped off + * headers, so "skb" is a data packet (or error). + * Else if it's not the last payload, keep "skb" + * for further processing. + */ + is_last = (len == skb->len); + if (is_last) + skb2 = skb; + else { + skb2 = skb_clone(skb, GFP_ATOMIC); + if (unlikely(!skb2)) + return 0; + } + + crc = get_unaligned_le32(skb2->data + + len - ETH_FCS_LEN); + skb_trim(skb2, len - ETH_FCS_LEN); + + /* + * The bmCRC helps to denote when the CRC field in + * the Ethernet frame contains a calculated CRC: + * bmCRC = 1 : CRC is calculated + * bmCRC = 0 : CRC = 0xDEADBEEF + */ + if (header & BIT(14)) + crc2 = ~crc32_le(~0, skb2->data, len); + else + crc2 = 0xdeadbeef; + + if (is_last) + return crc == crc2; + + if (unlikely(crc != crc2)) { + dev->stats.rx_errors++; + dev_kfree_skb_any(skb2); + } else + usbnet_skb_return(dev, skb2); + } + +next: + skb_pull(skb, len); + } while (skb->len); + + return 1; +} + +static const struct driver_info eem_info = { + .description = "CDC EEM Device", + .flags = FLAG_ETHER, + .bind = eem_bind, + .rx_fixup = eem_rx_fixup, + .tx_fixup = eem_tx_fixup, +}; + +/*-------------------------------------------------------------------------*/ + +static const struct usb_device_id products[] = { +{ + USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_EEM, + USB_CDC_PROTO_EEM), + .driver_info = (unsigned long) &eem_info, +}, +{ + /* EMPTY == end of list */ +}, +}; +MODULE_DEVICE_TABLE(usb, products); + +static struct usb_driver eem_driver = { + .name = "cdc_eem", + .id_table = products, + .probe = usbnet_probe, + .disconnect = usbnet_disconnect, + .suspend = usbnet_suspend, + .resume = usbnet_resume, +}; + + +static int __init eem_init(void) +{ + return usb_register(&eem_driver); +} +module_init(eem_init); + +static void __exit eem_exit(void) +{ + usb_deregister(&eem_driver); +} +module_exit(eem_exit); + +MODULE_AUTHOR("Omar Laazimani <omar.oberthur@gmail.com>"); +MODULE_DESCRIPTION("USB CDC EEM"); +MODULE_LICENSE("GPL"); diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c index dc166532659..5a7283372b5 100644 --- a/drivers/net/usb/smsc95xx.c +++ b/drivers/net/usb/smsc95xx.c @@ -941,6 +941,16 @@ static int smsc95xx_reset(struct usbnet *dev) if (netif_msg_ifup(dev)) devdbg(dev, "ID_REV = 0x%08x", read_buf); + /* Configure GPIO pins as LED outputs */ + write_buf = LED_GPIO_CFG_SPD_LED | LED_GPIO_CFG_LNK_LED | + LED_GPIO_CFG_FDX_LED; + ret = smsc95xx_write_reg(dev, LED_GPIO_CFG, write_buf); + if (ret < 0) { + devwarn(dev, "Failed to write LED_GPIO_CFG register, ret=%d", + ret); + return ret; + } + /* Init Tx */ write_buf = 0; ret = smsc95xx_write_reg(dev, FLOW, write_buf); @@ -1231,6 +1241,11 @@ static const struct usb_device_id products[] = { USB_DEVICE(0x0424, 0x9500), .driver_info = (unsigned long) &smsc95xx_info, }, + { + /* SMSC9512/9514 USB Hub & Ethernet Device */ + USB_DEVICE(0x0424, 0xec00), + .driver_info = (unsigned long) &smsc95xx_info, + }, { }, /* END */ }; MODULE_DEVICE_TABLE(usb, products); diff --git a/drivers/net/usb/smsc95xx.h b/drivers/net/usb/smsc95xx.h index 66b5c84f302..86bc44977fb 100644 --- a/drivers/net/usb/smsc95xx.h +++ b/drivers/net/usb/smsc95xx.h @@ -99,6 +99,9 @@ #define PM_CTL_WUPS_MULTI_ (0x00000003) #define LED_GPIO_CFG (0x24) +#define LED_GPIO_CFG_SPD_LED (0x01000000) +#define LED_GPIO_CFG_LNK_LED (0x00100000) +#define LED_GPIO_CFG_FDX_LED (0x00010000) #define GPIO_CFG (0x28) diff --git a/drivers/net/veth.c b/drivers/net/veth.c index 015db1cece7..8e56fcf0a0e 100644 --- a/drivers/net/veth.c +++ b/drivers/net/veth.c @@ -210,14 +210,11 @@ rx_drop: static struct net_device_stats *veth_get_stats(struct net_device *dev) { - struct veth_priv *priv; - struct net_device_stats *dev_stats; - int cpu; + struct veth_priv *priv = netdev_priv(dev); + struct net_device_stats *dev_stats = &dev->stats; + unsigned int cpu; struct veth_net_stats *stats; - priv = netdev_priv(dev); - dev_stats = &dev->stats; - dev_stats->rx_packets = 0; dev_stats->tx_packets = 0; dev_stats->rx_bytes = 0; @@ -225,16 +222,17 @@ static struct net_device_stats *veth_get_stats(struct net_device *dev) dev_stats->tx_dropped = 0; dev_stats->rx_dropped = 0; - for_each_online_cpu(cpu) { - stats = per_cpu_ptr(priv->stats, cpu); + if (priv->stats) + for_each_online_cpu(cpu) { + stats = per_cpu_ptr(priv->stats, cpu); - dev_stats->rx_packets += stats->rx_packets; - dev_stats->tx_packets += stats->tx_packets; - dev_stats->rx_bytes += stats->rx_bytes; - dev_stats->tx_bytes += stats->tx_bytes; - dev_stats->tx_dropped += stats->tx_dropped; - dev_stats->rx_dropped += stats->rx_dropped; - } + dev_stats->rx_packets += stats->rx_packets; + dev_stats->tx_packets += stats->tx_packets; + dev_stats->rx_bytes += stats->rx_bytes; + dev_stats->tx_bytes += stats->tx_bytes; + dev_stats->tx_dropped += stats->tx_dropped; + dev_stats->rx_dropped += stats->rx_dropped; + } return dev_stats; } @@ -261,6 +259,8 @@ static int veth_close(struct net_device *dev) netif_carrier_off(dev); netif_carrier_off(priv->peer); + free_percpu(priv->stats); + priv->stats = NULL; return 0; } @@ -291,15 +291,6 @@ static int veth_dev_init(struct net_device *dev) return 0; } -static void veth_dev_free(struct net_device *dev) -{ - struct veth_priv *priv; - - priv = netdev_priv(dev); - free_percpu(priv->stats); - free_netdev(dev); -} - static const struct net_device_ops veth_netdev_ops = { .ndo_init = veth_dev_init, .ndo_open = veth_open, @@ -317,7 +308,7 @@ static void veth_setup(struct net_device *dev) dev->netdev_ops = &veth_netdev_ops; dev->ethtool_ops = &veth_ethtool_ops; dev->features |= NETIF_F_LLTX; - dev->destructor = veth_dev_free; + dev->destructor = free_netdev; } /* diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 9c82a39497e..4d1d47953fc 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -616,10 +616,11 @@ static int virtnet_open(struct net_device *dev) static bool virtnet_send_command(struct virtnet_info *vi, u8 class, u8 cmd, struct scatterlist *data, int out, int in) { - struct scatterlist sg[VIRTNET_SEND_COMMAND_SG_MAX + 2]; + struct scatterlist *s, sg[VIRTNET_SEND_COMMAND_SG_MAX + 2]; struct virtio_net_ctrl_hdr ctrl; virtio_net_ctrl_ack status = ~0; unsigned int tmp; + int i; if (!virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ)) { BUG(); /* Caller should know better */ @@ -637,7 +638,8 @@ static bool virtnet_send_command(struct virtnet_info *vi, u8 class, u8 cmd, sg_init_table(sg, out + in); sg_set_buf(&sg[0], &ctrl, sizeof(ctrl)); - memcpy(&sg[1], data, sizeof(struct scatterlist) * (out + in - 2)); + for_each_sg(data, s, out + in - 2, i) + sg_set_buf(&sg[i + 1], sg_virt(s), s->length); sg_set_buf(&sg[out + in - 1], &status, sizeof(status)); if (vi->cvq->vq_ops->add_buf(vi->cvq, sg, out, in, vi) != 0) @@ -692,7 +694,7 @@ static void virtnet_set_rx_mode(struct net_device *dev) promisc = ((dev->flags & IFF_PROMISC) != 0); allmulti = ((dev->flags & IFF_ALLMULTI) != 0); - sg_set_buf(sg, &promisc, sizeof(promisc)); + sg_init_one(sg, &promisc, sizeof(promisc)); if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_RX, VIRTIO_NET_CTRL_RX_PROMISC, @@ -700,7 +702,7 @@ static void virtnet_set_rx_mode(struct net_device *dev) dev_warn(&dev->dev, "Failed to %sable promisc mode.\n", promisc ? "en" : "dis"); - sg_set_buf(sg, &allmulti, sizeof(allmulti)); + sg_init_one(sg, &allmulti, sizeof(allmulti)); if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_RX, VIRTIO_NET_CTRL_RX_ALLMULTI, @@ -716,6 +718,8 @@ static void virtnet_set_rx_mode(struct net_device *dev) return; } + sg_init_table(sg, 2); + /* Store the unicast list and count in the front of the buffer */ mac_data->entries = dev->uc_count; addr = dev->uc_list; @@ -744,24 +748,24 @@ static void virtnet_set_rx_mode(struct net_device *dev) kfree(buf); } -static void virnet_vlan_rx_add_vid(struct net_device *dev, u16 vid) +static void virtnet_vlan_rx_add_vid(struct net_device *dev, u16 vid) { struct virtnet_info *vi = netdev_priv(dev); struct scatterlist sg; - sg_set_buf(&sg, &vid, sizeof(vid)); + sg_init_one(&sg, &vid, sizeof(vid)); if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_VLAN, VIRTIO_NET_CTRL_VLAN_ADD, &sg, 1, 0)) dev_warn(&dev->dev, "Failed to add VLAN ID %d.\n", vid); } -static void virnet_vlan_rx_kill_vid(struct net_device *dev, u16 vid) +static void virtnet_vlan_rx_kill_vid(struct net_device *dev, u16 vid) { struct virtnet_info *vi = netdev_priv(dev); struct scatterlist sg; - sg_set_buf(&sg, &vid, sizeof(vid)); + sg_init_one(&sg, &vid, sizeof(vid)); if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_VLAN, VIRTIO_NET_CTRL_VLAN_DEL, &sg, 1, 0)) @@ -794,8 +798,8 @@ static const struct net_device_ops virtnet_netdev = { .ndo_set_mac_address = virtnet_set_mac_address, .ndo_set_rx_mode = virtnet_set_rx_mode, .ndo_change_mtu = virtnet_change_mtu, - .ndo_vlan_rx_add_vid = virnet_vlan_rx_add_vid, - .ndo_vlan_rx_kill_vid = virnet_vlan_rx_kill_vid, + .ndo_vlan_rx_add_vid = virtnet_vlan_rx_add_vid, + .ndo_vlan_rx_kill_vid = virtnet_vlan_rx_kill_vid, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = virtnet_netpoll, #endif diff --git a/drivers/net/wan/ixp4xx_hss.c b/drivers/net/wan/ixp4xx_hss.c index 3bf7d3f447d..765a7f5d6aa 100644 --- a/drivers/net/wan/ixp4xx_hss.c +++ b/drivers/net/wan/ixp4xx_hss.c @@ -1249,7 +1249,7 @@ static int __devinit hss_init_one(struct platform_device *pdev) return -ENOMEM; if ((port->npe = npe_request(0)) == NULL) { - err = -ENOSYS; + err = -ENODEV; goto err_free; } @@ -1311,7 +1311,7 @@ static int __init hss_init_module(void) if ((ixp4xx_read_feature_bits() & (IXP4XX_FEATURE_HDLC | IXP4XX_FEATURE_HSS)) != (IXP4XX_FEATURE_HDLC | IXP4XX_FEATURE_HSS)) - return -ENOSYS; + return -ENODEV; spin_lock_init(&npe_lock); diff --git a/drivers/net/wireless/ath5k/debug.c b/drivers/net/wireless/ath5k/debug.c index 9770bb3d40f..4904a07e4b5 100644 --- a/drivers/net/wireless/ath5k/debug.c +++ b/drivers/net/wireless/ath5k/debug.c @@ -424,7 +424,7 @@ ath5k_debug_dump_bands(struct ath5k_softc *sc) for (b = 0; b < IEEE80211_NUM_BANDS; b++) { struct ieee80211_supported_band *band = &sc->sbands[b]; - char bname[5]; + char bname[6]; switch (band->band) { case IEEE80211_BAND_2GHZ: strcpy(bname, "2 GHz"); diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 23644cf884f..e7c65c4f741 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -925,11 +925,11 @@ void iwl_bg_scan_completed(struct work_struct *work) IWL_DEBUG_SCAN(priv, "SCAN complete scan\n"); + ieee80211_scan_completed(priv->hw, false); + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; - ieee80211_scan_completed(priv->hw, false); - /* Since setting the TXPOWER may have been deferred while * performing the scan, fire one off */ mutex_lock(&priv->mutex); diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 5798fe49c77..44ab03a12e4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -719,6 +719,14 @@ static int iwl_set_tkip_dynamic_key_info(struct iwl_priv *priv, { unsigned long flags; int ret = 0; + __le16 key_flags = 0; + + key_flags |= (STA_KEY_FLG_TKIP | STA_KEY_FLG_MAP_KEY_MSK); + key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS); + key_flags &= ~STA_KEY_FLG_INVALID; + + if (sta_id == priv->hw_params.bcast_sta_id) + key_flags |= STA_KEY_MULTICAST_MSK; keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; @@ -738,6 +746,9 @@ static int iwl_set_tkip_dynamic_key_info(struct iwl_priv *priv, WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET, "no space for a new key"); + priv->stations[sta_id].sta.key.key_flags = key_flags; + + /* This copy is acutally not needed: we get the key with each TX */ memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key, 16); @@ -754,9 +765,7 @@ void iwl_update_tkip_key(struct iwl_priv *priv, { u8 sta_id = IWL_INVALID_STATION; unsigned long flags; - __le16 key_flags = 0; int i; - DECLARE_MAC_BUF(mac); sta_id = iwl_find_station(priv, addr); if (sta_id == IWL_INVALID_STATION) { @@ -771,16 +780,8 @@ void iwl_update_tkip_key(struct iwl_priv *priv, return; } - key_flags |= (STA_KEY_FLG_TKIP | STA_KEY_FLG_MAP_KEY_MSK); - key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS); - key_flags &= ~STA_KEY_FLG_INVALID; - - if (sta_id == priv->hw_params.bcast_sta_id) - key_flags |= STA_KEY_MULTICAST_MSK; - spin_lock_irqsave(&priv->sta_lock, flags); - priv->stations[sta_id].sta.key.key_flags = key_flags; priv->stations[sta_id].sta.key.tkip_rx_tsc_byte2 = (u8) iv32; for (i = 0; i < 5; i++) diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 617c4235d97..4cce6613350 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -1694,7 +1694,6 @@ void iwl3945_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq) rxq->free_count = 0; spin_unlock_irqrestore(&rxq->lock, flags); } -EXPORT_SYMBOL(iwl3945_rx_queue_reset); /* * this should be called while priv->lock is locked @@ -1745,7 +1744,6 @@ static void iwl3945_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rx rxq->bd = NULL; rxq->rb_stts = NULL; } -EXPORT_SYMBOL(iwl3945_rx_queue_free); /* Convert linear signal-to-noise ratio into dB */ diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index db91db77650..bebf735cd4b 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c @@ -2558,6 +2558,11 @@ static int rndis_wext_bind(struct usbnet *usbdev, struct usb_interface *intf) mutex_init(&priv->command_lock); spin_lock_init(&priv->stats_lock); + /* because rndis_command() sleeps we need to use workqueue */ + priv->workqueue = create_singlethread_workqueue("rndis_wlan"); + INIT_WORK(&priv->work, rndis_wext_worker); + INIT_DELAYED_WORK(&priv->stats_work, rndis_update_wireless_stats); + /* try bind rndis_host */ retval = generic_rndis_bind(usbdev, intf, FLAG_RNDIS_PHYM_WIRELESS); if (retval < 0) @@ -2603,16 +2608,17 @@ static int rndis_wext_bind(struct usbnet *usbdev, struct usb_interface *intf) disassociate(usbdev, 1); netif_carrier_off(usbdev->net); - /* because rndis_command() sleeps we need to use workqueue */ - priv->workqueue = create_singlethread_workqueue("rndis_wlan"); - INIT_DELAYED_WORK(&priv->stats_work, rndis_update_wireless_stats); queue_delayed_work(priv->workqueue, &priv->stats_work, round_jiffies_relative(STATS_UPDATE_JIFFIES)); - INIT_WORK(&priv->work, rndis_wext_worker); return 0; fail: + cancel_delayed_work_sync(&priv->stats_work); + cancel_work_sync(&priv->work); + flush_workqueue(priv->workqueue); + destroy_workqueue(priv->workqueue); + kfree(priv); return retval; } diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 001b328adf8..a563fbe559d 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -59,6 +59,10 @@ #define DMA_32BIT_PFN IOVA_PFN(DMA_BIT_MASK(32)) #define DMA_64BIT_PFN IOVA_PFN(DMA_BIT_MASK(64)) +#ifndef PHYSICAL_PAGE_MASK +#define PHYSICAL_PAGE_MASK PAGE_MASK +#endif + /* global iommu list, set NULL for ignored DMAR units */ static struct intel_iommu **g_iommus; @@ -1216,7 +1220,7 @@ static void dmar_init_reserved_ranges(void) if (!r->flags || !(r->flags & IORESOURCE_MEM)) continue; addr = r->start; - addr &= PAGE_MASK; + addr &= PHYSICAL_PAGE_MASK; size = r->end - addr; size = PAGE_ALIGN(size); iova = reserve_iova(&reserved_iova_list, IOVA_PFN(addr), @@ -2173,7 +2177,8 @@ static dma_addr_t __intel_map_single(struct device *hwdev, phys_addr_t paddr, * is not a big problem */ ret = domain_page_mapping(domain, start_paddr, - ((u64)paddr) & PAGE_MASK, size, prot); + ((u64)paddr) & PHYSICAL_PAGE_MASK, + size, prot); if (ret) goto error; @@ -2463,8 +2468,8 @@ static int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, int ne addr = page_to_phys(sg_page(sg)) + sg->offset; size = aligned_size((u64)addr, sg->length); ret = domain_page_mapping(domain, start_addr + offset, - ((u64)addr) & PAGE_MASK, - size, prot); + ((u64)addr) & PHYSICAL_PAGE_MASK, + size, prot); if (ret) { /* clear the page */ dma_pte_clear_range(domain, start_addr, diff --git a/drivers/rtc/rtc-twl4030.c b/drivers/rtc/rtc-twl4030.c index a6341e4f9a0..9c8c70c497d 100644 --- a/drivers/rtc/rtc-twl4030.c +++ b/drivers/rtc/rtc-twl4030.c @@ -495,9 +495,7 @@ static int twl4030_rtc_suspend(struct platform_device *pdev, pm_message_t state) { irqstat = rtc_irq_bits; - /* REVISIT alarm may need to wake us from sleep */ - mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M | - BIT_RTC_INTERRUPTS_REG_IT_ALARM_M); + mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M); return 0; } diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index 616c60ffcf2..3ac27ee4739 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c @@ -97,9 +97,7 @@ static void __init zfcp_init_device_configure(char *busid, u64 wwpn, u64 lun) ccw_device_set_online(adapter->ccw_device); zfcp_erp_wait(adapter); - wait_event(adapter->erp_done_wqh, - !(atomic_read(&unit->status) & - ZFCP_STATUS_UNIT_SCSI_WORK_PENDING)); + flush_work(&unit->scsi_work); down(&zfcp_data.config_sema); zfcp_unit_put(unit); @@ -279,6 +277,7 @@ struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *port, u64 fcp_lun) atomic_set(&unit->refcount, 0); init_waitqueue_head(&unit->remove_wq); + INIT_WORK(&unit->scsi_work, zfcp_scsi_scan); unit->port = port; unit->fcp_lun = fcp_lun; @@ -525,6 +524,8 @@ int zfcp_adapter_enqueue(struct ccw_device *ccw_device) atomic_clear_mask(ZFCP_STATUS_COMMON_REMOVE, &adapter->status); + zfcp_fc_nameserver_init(adapter); + if (!zfcp_adapter_scsi_register(adapter)) return 0; @@ -553,7 +554,6 @@ void zfcp_adapter_dequeue(struct zfcp_adapter *adapter) cancel_work_sync(&adapter->scan_work); cancel_work_sync(&adapter->stat_work); - cancel_delayed_work_sync(&adapter->nsp.work); zfcp_adapter_scsi_unregister(adapter); sysfs_remove_group(&adapter->ccw_device->dev.kobj, &zfcp_sysfs_adapter_attrs); @@ -671,8 +671,7 @@ void zfcp_port_dequeue(struct zfcp_port *port) list_del(&port->list); write_unlock_irq(&zfcp_data.config_lock); if (port->rport) - fc_remote_port_delete(port->rport); - port->rport = NULL; + port->rport->dd_data = NULL; zfcp_adapter_put(port->adapter); sysfs_remove_group(&port->sysfs_device.kobj, &zfcp_sysfs_port_attrs); device_unregister(&port->sysfs_device); diff --git a/drivers/s390/scsi/zfcp_ccw.c b/drivers/s390/scsi/zfcp_ccw.c index cfb0dcb6e3f..733fe3bf628 100644 --- a/drivers/s390/scsi/zfcp_ccw.c +++ b/drivers/s390/scsi/zfcp_ccw.c @@ -108,7 +108,6 @@ static int zfcp_ccw_set_online(struct ccw_device *ccw_device) /* initialize request counter */ BUG_ON(!zfcp_reqlist_isempty(adapter)); adapter->req_no = 0; - zfcp_fc_nameserver_init(adapter); zfcp_erp_modify_adapter_status(adapter, "ccsonl1", NULL, ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET); diff --git a/drivers/s390/scsi/zfcp_cfdc.c b/drivers/s390/scsi/zfcp_cfdc.c index 10cbfd172a2..8305c874e86 100644 --- a/drivers/s390/scsi/zfcp_cfdc.c +++ b/drivers/s390/scsi/zfcp_cfdc.c @@ -4,7 +4,7 @@ * Userspace interface for accessing the * Access Control Lists / Control File Data Channel * - * Copyright IBM Corporation 2008 + * Copyright IBM Corporation 2008, 2009 */ #define KMSG_COMPONENT "zfcp" @@ -197,6 +197,7 @@ static long zfcp_cfdc_dev_ioctl(struct file *file, unsigned int command, retval = -ENXIO; goto free_buffer; } + zfcp_adapter_get(adapter); retval = zfcp_cfdc_sg_setup(data->command, fsf_cfdc->sg, data_user->control_file); diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index a0318630f04..4c362a9069f 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h @@ -255,7 +255,6 @@ enum zfcp_wka_status { /* logical unit status */ #define ZFCP_STATUS_UNIT_SHARED 0x00000004 #define ZFCP_STATUS_UNIT_READONLY 0x00000008 -#define ZFCP_STATUS_UNIT_SCSI_WORK_PENDING 0x00000020 /* FSF request status (this does not have a common part) */ #define ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT 0x00000002 @@ -530,6 +529,7 @@ struct zfcp_unit { struct zfcp_erp_action erp_action; /* pending error recovery */ atomic_t erp_counter; struct zfcp_latencies latencies; + struct work_struct scsi_work; }; /* FSF request */ diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index 631bdb1dfd6..fdc9b4352a6 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -719,6 +719,7 @@ static void zfcp_erp_adapter_strategy_close(struct zfcp_erp_action *act) zfcp_qdio_close(adapter); zfcp_fsf_req_dismiss_all(adapter); adapter->fsf_req_seq_no = 0; + zfcp_fc_wka_port_force_offline(&adapter->nsp); /* all ports and units are closed */ zfcp_erp_modify_adapter_status(adapter, "erascl1", NULL, ZFCP_STATUS_COMMON_OPEN, ZFCP_CLEAR); @@ -1176,48 +1177,6 @@ static void zfcp_erp_action_dequeue(struct zfcp_erp_action *erp_action) } } -struct zfcp_erp_add_work { - struct zfcp_unit *unit; - struct work_struct work; -}; - -static void zfcp_erp_scsi_scan(struct work_struct *work) -{ - struct zfcp_erp_add_work *p = - container_of(work, struct zfcp_erp_add_work, work); - struct zfcp_unit *unit = p->unit; - struct fc_rport *rport = unit->port->rport; - - if (rport && rport->port_state == FC_PORTSTATE_ONLINE) - scsi_scan_target(&rport->dev, 0, rport->scsi_target_id, - scsilun_to_int((struct scsi_lun *)&unit->fcp_lun), 0); - atomic_clear_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING, &unit->status); - zfcp_unit_put(unit); - wake_up(&unit->port->adapter->erp_done_wqh); - kfree(p); -} - -static void zfcp_erp_schedule_work(struct zfcp_unit *unit) -{ - struct zfcp_erp_add_work *p; - - p = kzalloc(sizeof(*p), GFP_KERNEL); - if (!p) { - dev_err(&unit->port->adapter->ccw_device->dev, - "Registering unit 0x%016Lx on port 0x%016Lx failed\n", - (unsigned long long)unit->fcp_lun, - (unsigned long long)unit->port->wwpn); - return; - } - - zfcp_unit_get(unit); - atomic_set_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING, &unit->status); - INIT_WORK(&p->work, zfcp_erp_scsi_scan); - p->unit = unit; - if (!queue_work(zfcp_data.work_queue, &p->work)) - zfcp_unit_put(unit); -} - static void zfcp_erp_action_cleanup(struct zfcp_erp_action *act, int result) { struct zfcp_adapter *adapter = act->adapter; @@ -1226,11 +1185,11 @@ static void zfcp_erp_action_cleanup(struct zfcp_erp_action *act, int result) switch (act->action) { case ZFCP_ERP_ACTION_REOPEN_UNIT: - flush_work(&port->rport_work); if ((result == ZFCP_ERP_SUCCEEDED) && !unit->device) { - if (!(atomic_read(&unit->status) & - ZFCP_STATUS_UNIT_SCSI_WORK_PENDING)) - zfcp_erp_schedule_work(unit); + zfcp_unit_get(unit); + if (scsi_queue_work(unit->port->adapter->scsi_host, + &unit->scsi_work) <= 0) + zfcp_unit_put(unit); } zfcp_unit_put(unit); break; @@ -1352,6 +1311,11 @@ static int zfcp_erp_thread(void *data) while (!(atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_ERP_THREAD_KILL)) { + + zfcp_rec_dbf_event_thread_lock("erthrd1", adapter); + ignore = down_interruptible(&adapter->erp_ready_sem); + zfcp_rec_dbf_event_thread_lock("erthrd2", adapter); + write_lock_irqsave(&adapter->erp_lock, flags); next = adapter->erp_ready_head.next; write_unlock_irqrestore(&adapter->erp_lock, flags); @@ -1363,10 +1327,6 @@ static int zfcp_erp_thread(void *data) if (zfcp_erp_strategy(act) != ZFCP_ERP_DISMISSED) zfcp_erp_wakeup(adapter); } - - zfcp_rec_dbf_event_thread_lock("erthrd1", adapter); - ignore = down_interruptible(&adapter->erp_ready_sem); - zfcp_rec_dbf_event_thread_lock("erthrd2", adapter); } atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, &adapter->status); diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h index f6399ca97bc..2e31b536548 100644 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h @@ -106,6 +106,7 @@ extern void zfcp_fc_plogi_evaluate(struct zfcp_port *, struct fsf_plogi *); extern void zfcp_test_link(struct zfcp_port *); extern void zfcp_fc_link_test_work(struct work_struct *); extern void zfcp_fc_nameserver_init(struct zfcp_adapter *); +extern void zfcp_fc_wka_port_force_offline(struct zfcp_wka_port *); /* zfcp_fsf.c */ extern int zfcp_fsf_open_port(struct zfcp_erp_action *); @@ -158,6 +159,7 @@ extern void zfcp_scsi_rport_work(struct work_struct *); extern void zfcp_scsi_schedule_rport_register(struct zfcp_port *); extern void zfcp_scsi_schedule_rport_block(struct zfcp_port *); extern void zfcp_scsi_schedule_rports_block(struct zfcp_adapter *); +extern void zfcp_scsi_scan(struct work_struct *); /* zfcp_sysfs.c */ extern struct attribute_group zfcp_sysfs_unit_attrs; diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c index e8d032b9dfb..19ae0842047 100644 --- a/drivers/s390/scsi/zfcp_fc.c +++ b/drivers/s390/scsi/zfcp_fc.c @@ -98,13 +98,6 @@ static void zfcp_wka_port_offline(struct work_struct *work) struct zfcp_wka_port *wka_port = container_of(dw, struct zfcp_wka_port, work); - /* Don't wait forvever. If the wka_port is too busy take it offline - through a new call later */ - if (!wait_event_timeout(wka_port->completion_wq, - atomic_read(&wka_port->refcount) == 0, - HZ >> 1)) - return; - mutex_lock(&wka_port->mutex); if ((atomic_read(&wka_port->refcount) != 0) || (wka_port->status != ZFCP_WKA_PORT_ONLINE)) @@ -142,6 +135,14 @@ void zfcp_fc_nameserver_init(struct zfcp_adapter *adapter) INIT_DELAYED_WORK(&wka_port->work, zfcp_wka_port_offline); } +void zfcp_fc_wka_port_force_offline(struct zfcp_wka_port *wka) +{ + cancel_delayed_work_sync(&wka->work); + mutex_lock(&wka->mutex); + wka->status = ZFCP_WKA_PORT_OFFLINE; + mutex_unlock(&wka->mutex); +} + static void _zfcp_fc_incoming_rscn(struct zfcp_fsf_req *fsf_req, u32 range, struct fcp_rscn_element *elem) { @@ -372,7 +373,8 @@ static void zfcp_fc_adisc_handler(unsigned long data) if (adisc->els.status) { /* request rejected or timed out */ - zfcp_erp_port_forced_reopen(port, 0, "fcadh_1", NULL); + zfcp_erp_port_forced_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, + "fcadh_1", NULL); goto out; } @@ -431,11 +433,6 @@ void zfcp_fc_link_test_work(struct work_struct *work) container_of(work, struct zfcp_port, test_link_work); int retval; - if (!(atomic_read(&port->status) & ZFCP_STATUS_COMMON_UNBLOCKED)) { - zfcp_port_put(port); - return; /* port erp is running and will update rport status */ - } - zfcp_port_get(port); port->rport_task = RPORT_DEL; zfcp_scsi_rport_work(&port->rport_work); @@ -542,6 +539,9 @@ static void zfcp_validate_port(struct zfcp_port *port) { struct zfcp_adapter *adapter = port->adapter; + if (!(atomic_read(&port->status) & ZFCP_STATUS_COMMON_NOESC)) + return; + atomic_clear_mask(ZFCP_STATUS_COMMON_NOESC, &port->status); if ((port->supported_classes != 0) || @@ -602,10 +602,8 @@ static int zfcp_scan_eval_gpn_ft(struct zfcp_gpn_ft *gpn_ft, int max_entries) if (acc->wwpn == fc_host_port_name(adapter->scsi_host)) continue; port = zfcp_get_port_by_wwpn(adapter, acc->wwpn); - if (port) { - zfcp_port_get(port); + if (port) continue; - } port = zfcp_port_enqueue(adapter, acc->wwpn, ZFCP_STATUS_COMMON_NOESC, d_id); @@ -637,7 +635,8 @@ int zfcp_scan_ports(struct zfcp_adapter *adapter) max_entries = chain ? ZFCP_GPN_FT_MAX_ENTRIES : ZFCP_GPN_FT_ENTRIES; max_bytes = chain ? ZFCP_GPN_FT_MAX_SIZE : ZFCP_CT_SIZE_ONE_PAGE; - if (fc_host_port_type(adapter->scsi_host) != FC_PORTTYPE_NPORT) + if (fc_host_port_type(adapter->scsi_host) != FC_PORTTYPE_NPORT && + fc_host_port_type(adapter->scsi_host) != FC_PORTTYPE_NPIV) return 0; ret = zfcp_wka_port_get(&adapter->nsp); diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index b29f3121b66..74dee32afba 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -172,12 +172,16 @@ static void zfcp_fsf_link_down_info_eval(struct zfcp_fsf_req *req, char *id, struct fsf_link_down_info *link_down) { struct zfcp_adapter *adapter = req->adapter; + unsigned long flags; if (atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED) return; atomic_set_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, &adapter->status); + + read_lock_irqsave(&zfcp_data.config_lock, flags); zfcp_scsi_schedule_rports_block(adapter); + read_unlock_irqrestore(&zfcp_data.config_lock, flags); if (!link_down) goto out; @@ -645,30 +649,30 @@ static void zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *req) } } -static int zfcp_fsf_req_sbal_get(struct zfcp_adapter *adapter) - __releases(&adapter->req_q_lock) - __acquires(&adapter->req_q_lock) +static int zfcp_fsf_sbal_check(struct zfcp_adapter *adapter) { struct zfcp_qdio_queue *req_q = &adapter->req_q; - long ret; - if (atomic_read(&req_q->count) <= -REQUEST_LIST_SIZE) - return -EIO; - if (atomic_read(&req_q->count) > 0) - return 0; + spin_lock_bh(&adapter->req_q_lock); + if (atomic_read(&req_q->count)) + return 1; + spin_unlock_bh(&adapter->req_q_lock); + return 0; +} + +static int zfcp_fsf_req_sbal_get(struct zfcp_adapter *adapter) +{ + long ret; - atomic_dec(&req_q->count); spin_unlock_bh(&adapter->req_q_lock); ret = wait_event_interruptible_timeout(adapter->request_wq, - atomic_read(&req_q->count) >= 0, - 5 * HZ); - spin_lock_bh(&adapter->req_q_lock); - atomic_inc(&req_q->count); - + zfcp_fsf_sbal_check(adapter), 5 * HZ); if (ret > 0) return 0; if (!ret) atomic_inc(&adapter->qdio_outb_full); + + spin_lock_bh(&adapter->req_q_lock); return -EIO; } @@ -766,8 +770,9 @@ static struct zfcp_fsf_req *zfcp_fsf_req_create(struct zfcp_adapter *adapter, static int zfcp_fsf_req_send(struct zfcp_fsf_req *req) { struct zfcp_adapter *adapter = req->adapter; - unsigned long flags; - int idx; + unsigned long flags; + int idx; + int with_qtcb = (req->qtcb != NULL); /* put allocated FSF request into hash table */ spin_lock_irqsave(&adapter->req_list_lock, flags); @@ -789,7 +794,7 @@ static int zfcp_fsf_req_send(struct zfcp_fsf_req *req) } /* Don't increase for unsolicited status */ - if (req->qtcb) + if (with_qtcb) adapter->fsf_req_seq_no++; adapter->req_no++; @@ -1253,13 +1258,13 @@ int zfcp_fsf_exchange_config_data_sync(struct zfcp_adapter *adapter, spin_lock_bh(&adapter->req_q_lock); if (zfcp_fsf_req_sbal_get(adapter)) - goto out; + goto out_unlock; req = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_CONFIG_DATA, 0, NULL); if (IS_ERR(req)) { retval = PTR_ERR(req); - goto out; + goto out_unlock; } sbale = zfcp_qdio_sbale_req(req); @@ -1278,14 +1283,16 @@ int zfcp_fsf_exchange_config_data_sync(struct zfcp_adapter *adapter, zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT); retval = zfcp_fsf_req_send(req); -out: spin_unlock_bh(&adapter->req_q_lock); if (!retval) wait_event(req->completion_wq, req->status & ZFCP_STATUS_FSFREQ_COMPLETED); zfcp_fsf_req_free(req); + return retval; +out_unlock: + spin_unlock_bh(&adapter->req_q_lock); return retval; } @@ -1352,13 +1359,13 @@ int zfcp_fsf_exchange_port_data_sync(struct zfcp_adapter *adapter, spin_lock_bh(&adapter->req_q_lock); if (zfcp_fsf_req_sbal_get(adapter)) - goto out; + goto out_unlock; req = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_PORT_DATA, 0, NULL); if (IS_ERR(req)) { retval = PTR_ERR(req); - goto out; + goto out_unlock; } if (data) @@ -1371,14 +1378,18 @@ int zfcp_fsf_exchange_port_data_sync(struct zfcp_adapter *adapter, req->handler = zfcp_fsf_exchange_port_data_handler; zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT); retval = zfcp_fsf_req_send(req); -out: spin_unlock_bh(&adapter->req_q_lock); + if (!retval) wait_event(req->completion_wq, req->status & ZFCP_STATUS_FSFREQ_COMPLETED); zfcp_fsf_req_free(req); return retval; + +out_unlock: + spin_unlock_bh(&adapter->req_q_lock); + return retval; } static void zfcp_fsf_open_port_handler(struct zfcp_fsf_req *req) @@ -2472,8 +2483,6 @@ out: static void zfcp_fsf_control_file_handler(struct zfcp_fsf_req *req) { - if (req->qtcb->header.fsf_status != FSF_GOOD) - req->status |= ZFCP_STATUS_FSFREQ_ERROR; } /** diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index 58201e1ae47..e8fbeaeb5fb 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -171,7 +171,7 @@ static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) write_unlock_irqrestore(&adapter->abort_lock, flags); zfcp_scsi_dbf_event_abort("lte1", adapter, scpnt, NULL, old_req_id); - return SUCCESS; + return FAILED; /* completion could be in progress */ } old_req->data = NULL; @@ -486,10 +486,12 @@ static void zfcp_set_rport_dev_loss_tmo(struct fc_rport *rport, u32 timeout) */ static void zfcp_scsi_dev_loss_tmo_callbk(struct fc_rport *rport) { - struct zfcp_port *port = rport->dd_data; + struct zfcp_port *port; write_lock_irq(&zfcp_data.config_lock); - port->rport = NULL; + port = rport->dd_data; + if (port) + port->rport = NULL; write_unlock_irq(&zfcp_data.config_lock); } @@ -503,9 +505,18 @@ static void zfcp_scsi_dev_loss_tmo_callbk(struct fc_rport *rport) */ static void zfcp_scsi_terminate_rport_io(struct fc_rport *rport) { - struct zfcp_port *port = rport->dd_data; + struct zfcp_port *port; + + write_lock_irq(&zfcp_data.config_lock); + port = rport->dd_data; + if (port) + zfcp_port_get(port); + write_unlock_irq(&zfcp_data.config_lock); - zfcp_erp_port_reopen(port, 0, "sctrpi1", NULL); + if (port) { + zfcp_erp_port_reopen(port, 0, "sctrpi1", NULL); + zfcp_port_put(port); + } } static void zfcp_scsi_rport_register(struct zfcp_port *port) @@ -534,8 +545,10 @@ static void zfcp_scsi_rport_register(struct zfcp_port *port) static void zfcp_scsi_rport_block(struct zfcp_port *port) { - if (port->rport) - fc_remote_port_delete(port->rport); + struct fc_rport *rport = port->rport; + + if (rport) + fc_remote_port_delete(rport); } void zfcp_scsi_schedule_rport_register(struct zfcp_port *port) @@ -583,6 +596,23 @@ void zfcp_scsi_rport_work(struct work_struct *work) } +void zfcp_scsi_scan(struct work_struct *work) +{ + struct zfcp_unit *unit = container_of(work, struct zfcp_unit, + scsi_work); + struct fc_rport *rport; + + flush_work(&unit->port->rport_work); + rport = unit->port->rport; + + if (rport && rport->port_state == FC_PORTSTATE_ONLINE) + scsi_scan_target(&rport->dev, 0, rport->scsi_target_id, + scsilun_to_int((struct scsi_lun *) + &unit->fcp_lun), 0); + + zfcp_unit_put(unit); +} + struct fc_function_template zfcp_transport_functions = { .show_starget_port_id = 1, .show_starget_port_name = 1, diff --git a/drivers/s390/scsi/zfcp_sysfs.c b/drivers/s390/scsi/zfcp_sysfs.c index 9a3b8e261c0..3e51e64d110 100644 --- a/drivers/s390/scsi/zfcp_sysfs.c +++ b/drivers/s390/scsi/zfcp_sysfs.c @@ -254,12 +254,21 @@ static ssize_t zfcp_sysfs_unit_remove_store(struct device *dev, write_lock_irq(&zfcp_data.config_lock); unit = zfcp_get_unit_by_lun(port, fcp_lun); - if (unit && (atomic_read(&unit->refcount) == 0)) { - zfcp_unit_get(unit); - atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &unit->status); - list_move(&unit->list, &unit_remove_lh); - } else - unit = NULL; + if (unit) { + write_unlock_irq(&zfcp_data.config_lock); + /* wait for possible timeout during SCSI probe */ + flush_work(&unit->scsi_work); + write_lock_irq(&zfcp_data.config_lock); + + if (atomic_read(&unit->refcount) == 0) { + zfcp_unit_get(unit); + atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, + &unit->status); + list_move(&unit->list, &unit_remove_lh); + } else { + unit = NULL; + } + } write_unlock_irq(&zfcp_data.config_lock); diff --git a/drivers/scsi/cxgb3i/cxgb3i.h b/drivers/scsi/cxgb3i/cxgb3i.h index d362860e750..59b0958d2d1 100644 --- a/drivers/scsi/cxgb3i/cxgb3i.h +++ b/drivers/scsi/cxgb3i/cxgb3i.h @@ -34,7 +34,7 @@ #include "cxgb3i_offload.h" #include "cxgb3i_ddp.h" -#define CXGB3I_SCSI_QDEPTH_DFLT 128 +#define CXGB3I_SCSI_HOST_QDEPTH 1024 #define CXGB3I_MAX_TARGET CXGB3I_MAX_CONN #define CXGB3I_MAX_LUN 512 #define ISCSI_PDU_NONPAYLOAD_MAX \ diff --git a/drivers/scsi/cxgb3i/cxgb3i_ddp.c b/drivers/scsi/cxgb3i/cxgb3i_ddp.c index d06a661c209..99c91254790 100644 --- a/drivers/scsi/cxgb3i/cxgb3i_ddp.c +++ b/drivers/scsi/cxgb3i/cxgb3i_ddp.c @@ -120,20 +120,26 @@ static void clear_ddp_map(struct cxgb3i_ddp_info *ddp, unsigned int tag, } static inline int ddp_find_unused_entries(struct cxgb3i_ddp_info *ddp, - int start, int max, int count, + unsigned int start, unsigned int max, + unsigned int count, struct cxgb3i_gather_list *gl) { - unsigned int i, j; + unsigned int i, j, k; + /* not enough entries */ + if ((max - start) < count) + return -EBUSY; + + max -= count; spin_lock(&ddp->map_lock); - for (i = start; i <= max;) { - for (j = 0; j < count; j++) { - if (ddp->gl_map[i + j]) + for (i = start; i < max;) { + for (j = 0, k = i; j < count; j++, k++) { + if (ddp->gl_map[k]) break; } if (j == count) { - for (j = 0; j < count; j++) - ddp->gl_map[i + j] = gl; + for (j = 0, k = i; j < count; j++, k++) + ddp->gl_map[k] = gl; spin_unlock(&ddp->map_lock); return i; } @@ -354,7 +360,7 @@ int cxgb3i_ddp_tag_reserve(struct t3cdev *tdev, unsigned int tid, struct cxgb3i_ddp_info *ddp = tdev->ulp_iscsi; struct pagepod_hdr hdr; unsigned int npods; - int idx = -1, idx_max; + int idx = -1; int err = -ENOMEM; u32 sw_tag = *tagp; u32 tag; @@ -367,17 +373,17 @@ int cxgb3i_ddp_tag_reserve(struct t3cdev *tdev, unsigned int tid, } npods = (gl->nelem + PPOD_PAGES_MAX - 1) >> PPOD_PAGES_SHIFT; - idx_max = ddp->nppods - npods + 1; if (ddp->idx_last == ddp->nppods) - idx = ddp_find_unused_entries(ddp, 0, idx_max, npods, gl); + idx = ddp_find_unused_entries(ddp, 0, ddp->nppods, npods, gl); else { idx = ddp_find_unused_entries(ddp, ddp->idx_last + 1, - idx_max, npods, gl); - if (idx < 0 && ddp->idx_last >= npods) + ddp->nppods, npods, gl); + if (idx < 0 && ddp->idx_last >= npods) { idx = ddp_find_unused_entries(ddp, 0, - ddp->idx_last - npods + 1, + min(ddp->idx_last + npods, ddp->nppods), npods, gl); + } } if (idx < 0) { ddp_log_debug("xferlen %u, gl %u, npods %u NO DDP.\n", diff --git a/drivers/scsi/cxgb3i/cxgb3i_iscsi.c b/drivers/scsi/cxgb3i/cxgb3i_iscsi.c index fff8e432764..9212400b9b1 100644 --- a/drivers/scsi/cxgb3i/cxgb3i_iscsi.c +++ b/drivers/scsi/cxgb3i/cxgb3i_iscsi.c @@ -876,13 +876,14 @@ static struct scsi_host_template cxgb3i_host_template = { .proc_name = "cxgb3i", .queuecommand = iscsi_queuecommand, .change_queue_depth = iscsi_change_queue_depth, - .can_queue = CXGB3I_SCSI_QDEPTH_DFLT - 1, + .can_queue = CXGB3I_SCSI_HOST_QDEPTH, .sg_tablesize = SG_ALL, .max_sectors = 0xFFFF, - .cmd_per_lun = CXGB3I_SCSI_QDEPTH_DFLT, + .cmd_per_lun = ISCSI_DEF_CMD_PER_LUN, .eh_abort_handler = iscsi_eh_abort, .eh_device_reset_handler = iscsi_eh_device_reset, .eh_target_reset_handler = iscsi_eh_target_reset, + .target_alloc = iscsi_target_alloc, .use_clustering = DISABLE_CLUSTERING, .this_id = -1, }; diff --git a/drivers/scsi/cxgb3i/cxgb3i_offload.c b/drivers/scsi/cxgb3i/cxgb3i_offload.c index 4d8654cdbda..e11c9c180f3 100644 --- a/drivers/scsi/cxgb3i/cxgb3i_offload.c +++ b/drivers/scsi/cxgb3i/cxgb3i_offload.c @@ -1737,7 +1737,7 @@ int cxgb3i_c3cn_send_pdus(struct s3_conn *c3cn, struct sk_buff *skb) c3cn_tx_debug("c3cn 0x%p, snd %u - %u > %u.\n", c3cn, c3cn->write_seq, c3cn->snd_una, cxgb3_snd_win); - err = -EAGAIN; + err = -ENOBUFS; goto out_err; } @@ -1775,6 +1775,8 @@ done: out_err: if (copied == 0 && err == -EPIPE) copied = c3cn->err ? c3cn->err : -EPIPE; + else + copied = err; goto done; } diff --git a/drivers/scsi/cxgb3i/cxgb3i_pdu.c b/drivers/scsi/cxgb3i/cxgb3i_pdu.c index 7eebc9a7cb3..70910507117 100644 --- a/drivers/scsi/cxgb3i/cxgb3i_pdu.c +++ b/drivers/scsi/cxgb3i/cxgb3i_pdu.c @@ -400,17 +400,18 @@ int cxgb3i_conn_xmit_pdu(struct iscsi_task *task) return 0; } - if (err < 0 && err != -EAGAIN) { - kfree_skb(skb); - cxgb3i_tx_debug("itt 0x%x, skb 0x%p, len %u/%u, xmit err %d.\n", - task->itt, skb, skb->len, skb->data_len, err); - iscsi_conn_printk(KERN_ERR, task->conn, "xmit err %d.\n", err); - iscsi_conn_failure(task->conn, ISCSI_ERR_XMIT_FAILED); + if (err == -EAGAIN || err == -ENOBUFS) { + /* reset skb to send when we are called again */ + tdata->skb = skb; return err; } - /* reset skb to send when we are called again */ - tdata->skb = skb; - return -EAGAIN; + + kfree_skb(skb); + cxgb3i_tx_debug("itt 0x%x, skb 0x%p, len %u/%u, xmit err %d.\n", + task->itt, skb, skb->len, skb->data_len, err); + iscsi_conn_printk(KERN_ERR, task->conn, "xmit err %d.\n", err); + iscsi_conn_failure(task->conn, ISCSI_ERR_XMIT_FAILED); + return err; } int cxgb3i_pdu_init(void) diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index 94e1e318977..03e1926f40b 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c @@ -57,7 +57,7 @@ DEFINE_RWLOCK(fcoe_hostlist_lock); DEFINE_TIMER(fcoe_timer, NULL, 0, 0); DEFINE_PER_CPU(struct fcoe_percpu_s, fcoe_percpu); -/* Function Prototyes */ +/* Function Prototypes */ static int fcoe_reset(struct Scsi_Host *shost); static int fcoe_xmit(struct fc_lport *, struct fc_frame *); static int fcoe_rcv(struct sk_buff *, struct net_device *, @@ -138,7 +138,6 @@ static struct scsi_host_template fcoe_shost_template = { /** * fcoe_lport_config() - sets up the fc_lport * @lp: ptr to the fc_lport - * @shost: ptr to the parent scsi host * * Returns: 0 for success */ @@ -256,6 +255,7 @@ static int fcoe_netdev_config(struct fc_lport *lp, struct net_device *netdev) rtnl_lock(); memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN); dev_unicast_add(fc->real_dev, flogi_maddr, ETH_ALEN); + dev_mc_add(fc->real_dev, FIP_ALL_ENODE_MACS, ETH_ALEN, 0); rtnl_unlock(); /* @@ -380,7 +380,7 @@ static int fcoe_if_destroy(struct net_device *netdev) dev_mc_delete(fc->real_dev, FIP_ALL_ENODE_MACS, ETH_ALEN, 0); rtnl_unlock(); - /* Free the per-CPU revieve threads */ + /* Free the per-CPU receive threads */ fcoe_percpu_clean(lp); /* Free existing skbs */ @@ -720,7 +720,7 @@ static void fcoe_percpu_thread_destroy(unsigned int cpu) } #else /* - * This a non-SMP scenario where the singluar Rx thread is + * This a non-SMP scenario where the singular Rx thread is * being removed. Free all skbs and stop the thread. */ spin_lock_bh(&p->fcoe_rx_list.lock); @@ -777,7 +777,7 @@ static struct notifier_block fcoe_cpu_notifier = { * @skb: the receive skb * @dev: associated net device * @ptype: context - * @odldev: last device + * @olddev: last device * * this function will receive the packet and build fc frame and pass it up * @@ -884,7 +884,6 @@ err2: kfree_skb(skb); return -1; } -EXPORT_SYMBOL_GPL(fcoe_rcv); /** * fcoe_start_io() - pass to netdev to start xmit for fcoe @@ -905,7 +904,7 @@ static inline int fcoe_start_io(struct sk_buff *skb) } /** - * fcoe_get_paged_crc_eof() - in case we need alloc a page for crc_eof + * fcoe_get_paged_crc_eof() - in case we need to alloc a page for crc_eof * @skb: the skb to be xmitted * @tlen: total len * @@ -947,7 +946,7 @@ static int fcoe_get_paged_crc_eof(struct sk_buff *skb, int tlen) /** * fcoe_fc_crc() - calculates FC CRC in this fcoe skb - * @fp: the fc_frame containg data to be checksummed + * @fp: the fc_frame containing data to be checksummed * * This uses crc32() to calculate the crc for fc frame * Return : 32 bit crc @@ -1011,7 +1010,7 @@ int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp) wlen = skb->len / FCOE_WORD_TO_BYTE; if (!lp->link_up) { - kfree(skb); + kfree_skb(skb); return 0; } @@ -1062,7 +1061,7 @@ int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp) cp = NULL; } - /* adjust skb netowrk/transport offsets to match mac/fcoe/fc */ + /* adjust skb network/transport offsets to match mac/fcoe/fc */ skb_push(skb, elen + hlen); skb_reset_mac_header(skb); skb_reset_network_header(skb); @@ -1123,7 +1122,6 @@ int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp) return 0; } -EXPORT_SYMBOL_GPL(fcoe_xmit); /** * fcoe_percpu_receive_thread() - recv thread per cpu @@ -1296,17 +1294,16 @@ void fcoe_watchdog(ulong vp) /** - * fcoe_check_wait_queue() - put the skb into fcoe pending xmit queue - * @lp: the fc_port for this skb - * @skb: the associated skb to be xmitted + * fcoe_check_wait_queue() - attempt to clear the transmit backlog + * @lp: the fc_lport * * This empties the wait_queue, dequeue the head of the wait_queue queue * and calls fcoe_start_io() for each packet, if all skb have been * transmitted, return qlen or -1 if a error occurs, then restore - * wait_queue and try again later. + * wait_queue and try again later. * * The wait_queue is used when the skb transmit fails. skb will go - * in the wait_queue which will be emptied by the time function OR + * in the wait_queue which will be emptied by the timer function or * by the next skb transmit. * * Returns: 0 for success @@ -1355,10 +1352,6 @@ out: */ static void fcoe_dev_setup() { - /* - * here setup a interface specific wd time to - * monitor the link state - */ register_netdevice_notifier(&fcoe_notifier); } @@ -1437,10 +1430,9 @@ out: /** * fcoe_if_to_netdev() - parse a name buffer to get netdev - * @ifname: fixed array for output parsed ifname * @buffer: incoming buffer to be copied * - * Returns: NULL or ptr to netdeive + * Returns: NULL or ptr to net_device */ static struct net_device *fcoe_if_to_netdev(const char *buffer) { @@ -1458,7 +1450,7 @@ static struct net_device *fcoe_if_to_netdev(const char *buffer) } /** - * fcoe_netdev_to_module_owner() - finds out the nic drive moddule of the netdev + * fcoe_netdev_to_module_owner() - finds out the driver module of the netdev * @netdev: the target netdev * * Returns: ptr to the struct module, NULL for failure @@ -1488,7 +1480,7 @@ fcoe_netdev_to_module_owner(const struct net_device *netdev) * Holds the Ethernet driver module by try_module_get() for * the corresponding netdev. * - * Returns: 0 for succsss + * Returns: 0 for success */ static int fcoe_ethdrv_get(const struct net_device *netdev) { @@ -1510,7 +1502,7 @@ static int fcoe_ethdrv_get(const struct net_device *netdev) * Releases the Ethernet driver module by module_put for * the corresponding netdev. * - * Returns: 0 for succsss + * Returns: 0 for success */ static int fcoe_ethdrv_put(const struct net_device *netdev) { @@ -1528,7 +1520,7 @@ static int fcoe_ethdrv_put(const struct net_device *netdev) /** * fcoe_destroy() - handles the destroy from sysfs - * @buffer: expcted to be a eth if name + * @buffer: expected to be an eth if name * @kp: associated kernel param * * Returns: 0 for success @@ -1565,7 +1557,7 @@ out_nodev: /** * fcoe_create() - Handles the create call from sysfs - * @buffer: expcted to be a eth if name + * @buffer: expected to be an eth if name * @kp: associated kernel param * * Returns: 0 for success @@ -1652,7 +1644,6 @@ int fcoe_link_ok(struct fc_lport *lp) return rc; } -EXPORT_SYMBOL_GPL(fcoe_link_ok); /** * fcoe_percpu_clean() - Clear the pending skbs for an lport @@ -1684,7 +1675,6 @@ void fcoe_percpu_clean(struct fc_lport *lp) spin_unlock_bh(&pp->fcoe_rx_list.lock); } } -EXPORT_SYMBOL_GPL(fcoe_percpu_clean); /** * fcoe_clean_pending_queue() - Dequeue a skb and free it @@ -1705,7 +1695,6 @@ void fcoe_clean_pending_queue(struct fc_lport *lp) } spin_unlock_bh(&fc->fcoe_pending_queue.lock); } -EXPORT_SYMBOL_GPL(fcoe_clean_pending_queue); /** * fcoe_reset() - Resets the fcoe @@ -1719,11 +1708,10 @@ int fcoe_reset(struct Scsi_Host *shost) fc_lport_reset(lport); return 0; } -EXPORT_SYMBOL_GPL(fcoe_reset); /** * fcoe_hostlist_lookup_softc() - find the corresponding lport by a given device - * @device: this is currently ptr to net_device + * @dev: this is currently ptr to net_device * * Returns: NULL or the located fcoe_softc */ @@ -1757,11 +1745,10 @@ struct fc_lport *fcoe_hostlist_lookup(const struct net_device *netdev) return (fc) ? fc->ctlr.lp : NULL; } -EXPORT_SYMBOL_GPL(fcoe_hostlist_lookup); /** * fcoe_hostlist_add() - Add a lport to lports list - * @lp: ptr to the fc_lport to badded + * @lp: ptr to the fc_lport to be added * * Returns: 0 for success */ @@ -1778,11 +1765,10 @@ int fcoe_hostlist_add(const struct fc_lport *lp) } return 0; } -EXPORT_SYMBOL_GPL(fcoe_hostlist_add); /** * fcoe_hostlist_remove() - remove a lport from lports list - * @lp: ptr to the fc_lport to badded + * @lp: ptr to the fc_lport to be removed * * Returns: 0 for success */ @@ -1798,7 +1784,6 @@ int fcoe_hostlist_remove(const struct fc_lport *lp) return 0; } -EXPORT_SYMBOL_GPL(fcoe_hostlist_remove); /** * fcoe_init() - fcoe module loading initialization diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c index f410f4abb54..62ba0f39c6b 100644 --- a/drivers/scsi/fcoe/libfcoe.c +++ b/drivers/scsi/fcoe/libfcoe.c @@ -122,7 +122,7 @@ static void fcoe_ctlr_reset_fcfs(struct fcoe_ctlr *fip) } /** - * fcoe_ctrl_destroy() - Disable and tear-down the FCoE controller. + * fcoe_ctlr_destroy() - Disable and tear-down the FCoE controller. * @fip: FCoE controller. * * This is called by FCoE drivers before freeing the &fcoe_ctlr. diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index c09d77591f9..dd689ded860 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -3654,6 +3654,7 @@ static int ipr_slave_configure(struct scsi_device *sdev) { struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *) sdev->host->hostdata; struct ipr_resource_entry *res; + struct ata_port *ap = NULL; unsigned long lock_flags = 0; spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); @@ -3672,12 +3673,16 @@ static int ipr_slave_configure(struct scsi_device *sdev) } if (ipr_is_vset_device(res) || ipr_is_scsi_disk(res)) sdev->allow_restart = 1; - if (ipr_is_gata(res) && res->sata_port) { + if (ipr_is_gata(res) && res->sata_port) + ap = res->sata_port->ap; + spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); + + if (ap) { scsi_adjust_queue_depth(sdev, 0, IPR_MAX_CMD_PER_ATA_LUN); - ata_sas_slave_configure(sdev, res->sata_port->ap); - } else { + ata_sas_slave_configure(sdev, ap); + } else scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun); - } + return 0; } spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); return 0; diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index b3e5e08e44a..b7c092d63bb 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -463,7 +463,7 @@ static int iscsi_sw_tcp_pdu_init(struct iscsi_task *task, } if (err) { - iscsi_conn_failure(conn, err); + /* got invalid offset/len */ return -EIO; } return 0; @@ -851,6 +851,7 @@ static struct scsi_host_template iscsi_sw_tcp_sht = { .use_clustering = DISABLE_CLUSTERING, .slave_alloc = iscsi_sw_tcp_slave_alloc, .slave_configure = iscsi_sw_tcp_slave_configure, + .target_alloc = iscsi_target_alloc, .proc_name = "iscsi_tcp", .this_id = -1, }; diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c index e57556ea5b4..4c880656990 100644 --- a/drivers/scsi/libfc/fc_disc.c +++ b/drivers/scsi/libfc/fc_disc.c @@ -113,6 +113,11 @@ void fc_disc_stop_rports(struct fc_disc *disc) lport->tt.rport_logoff(rport); } + list_for_each_entry_safe(rdata, next, &disc->rogue_rports, peers) { + rport = PRIV_TO_RPORT(rdata); + lport->tt.rport_logoff(rport); + } + mutex_unlock(&disc->disc_mutex); } @@ -131,23 +136,32 @@ static void fc_disc_rport_callback(struct fc_lport *lport, { struct fc_rport_libfc_priv *rdata = rport->dd_data; struct fc_disc *disc = &lport->disc; - int found = 0; FC_DEBUG_DISC("Received a %d event for port (%6x)\n", event, rport->port_id); - if (event == RPORT_EV_CREATED) { + switch (event) { + case RPORT_EV_CREATED: if (disc) { - found = 1; mutex_lock(&disc->disc_mutex); list_add_tail(&rdata->peers, &disc->rports); mutex_unlock(&disc->disc_mutex); } + break; + case RPORT_EV_LOGO: + case RPORT_EV_FAILED: + case RPORT_EV_STOP: + mutex_lock(&disc->disc_mutex); + mutex_lock(&rdata->rp_mutex); + if (rdata->trans_state == FC_PORTSTATE_ROGUE) + list_del(&rdata->peers); + mutex_unlock(&rdata->rp_mutex); + mutex_unlock(&disc->disc_mutex); + break; + default: + break; } - if (!found) - FC_DEBUG_DISC("The rport (%6x) is not maintained " - "by the discovery layer\n", rport->port_id); } /** @@ -439,6 +453,7 @@ static int fc_disc_new_target(struct fc_disc *disc, rdata = rport->dd_data; rdata->ops = &fc_disc_rport_ops; rdata->rp_state = RPORT_ST_INIT; + list_add_tail(&rdata->peers, &disc->rogue_rports); lport->tt.rport_login(rport); } } @@ -461,21 +476,29 @@ static void fc_disc_del_target(struct fc_disc *disc, struct fc_rport *rport) /** * fc_disc_done() - Discovery has been completed * @disc: FC discovery context + * Locking Note: This function expects that the disc mutex is locked before + * it is called. The discovery callback is then made with the lock released, + * and the lock is re-taken before returning from this function */ static void fc_disc_done(struct fc_disc *disc) { struct fc_lport *lport = disc->lport; + enum fc_disc_event event; FC_DEBUG_DISC("Discovery complete for port (%6x)\n", fc_host_port_id(lport->host)); - disc->disc_callback(lport, disc->event); + event = disc->event; disc->event = DISC_EV_NONE; if (disc->requested) fc_disc_gpn_ft_req(disc); else disc->pending = 0; + + mutex_unlock(&disc->disc_mutex); + disc->disc_callback(lport, event); + mutex_lock(&disc->disc_mutex); } /** @@ -622,6 +645,8 @@ static int fc_disc_gpn_ft_parse(struct fc_disc *disc, void *buf, size_t len) rdata = rport->dd_data; rdata->ops = &fc_disc_rport_ops; rdata->local_port = lport; + list_add_tail(&rdata->peers, + &disc->rogue_rports); lport->tt.rport_login(rport); } else FC_DBG("Failed to allocate memory for " @@ -681,8 +706,8 @@ static void fc_disc_timeout(struct work_struct *work) * @fp: response frame * @lp_arg: Fibre Channel host port instance * - * Locking Note: This function expects that the disc_mutex is locked - * before it is called. + * Locking Note: This function is called without disc mutex held, and + * should do all its processing with the mutex held */ static void fc_disc_gpn_ft_resp(struct fc_seq *sp, struct fc_frame *fp, void *disc_arg) @@ -695,11 +720,13 @@ static void fc_disc_gpn_ft_resp(struct fc_seq *sp, struct fc_frame *fp, unsigned int len; int error; + mutex_lock(&disc->disc_mutex); FC_DEBUG_DISC("Received a GPN_FT response on port (%6x)\n", fc_host_port_id(disc->lport->host)); if (IS_ERR(fp)) { fc_disc_error(disc, fp); + mutex_unlock(&disc->disc_mutex); return; } @@ -744,6 +771,8 @@ static void fc_disc_gpn_ft_resp(struct fc_seq *sp, struct fc_frame *fp, disc->seq_count++; } fc_frame_free(fp); + + mutex_unlock(&disc->disc_mutex); } /** @@ -757,7 +786,6 @@ static void fc_disc_gpn_ft_resp(struct fc_seq *sp, struct fc_frame *fp, static void fc_disc_single(struct fc_disc *disc, struct fc_disc_port *dp) { struct fc_lport *lport; - struct fc_rport *rport; struct fc_rport *new_rport; struct fc_rport_libfc_priv *rdata; @@ -766,15 +794,12 @@ static void fc_disc_single(struct fc_disc *disc, struct fc_disc_port *dp) if (dp->ids.port_id == fc_host_port_id(lport->host)) goto out; - rport = lport->tt.rport_lookup(lport, dp->ids.port_id); - if (rport) - fc_disc_del_target(disc, rport); - new_rport = lport->tt.rport_create(dp); if (new_rport) { rdata = new_rport->dd_data; rdata->ops = &fc_disc_rport_ops; kfree(dp); + list_add_tail(&rdata->peers, &disc->rogue_rports); lport->tt.rport_login(new_rport); } return; @@ -836,6 +861,7 @@ int fc_disc_init(struct fc_lport *lport) INIT_DELAYED_WORK(&disc->disc_work, fc_disc_timeout); mutex_init(&disc->disc_mutex); INIT_LIST_HEAD(&disc->rports); + INIT_LIST_HEAD(&disc->rogue_rports); disc->lport = lport; disc->delay = FC_DISC_DELAY; diff --git a/drivers/scsi/libfc/fc_elsct.c b/drivers/scsi/libfc/fc_elsct.c index dd47fe619d1..5878b34bff1 100644 --- a/drivers/scsi/libfc/fc_elsct.c +++ b/drivers/scsi/libfc/fc_elsct.c @@ -41,7 +41,7 @@ static struct fc_seq *fc_elsct_send(struct fc_lport *lport, void *arg, u32 timer_msec) { enum fc_rctl r_ctl; - u32 did; + u32 did = FC_FID_NONE; enum fc_fh_type fh_type; int rc; diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index f555ae99ad4..521f996f9b1 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -713,7 +713,7 @@ done: static void fc_fcp_recv(struct fc_seq *seq, struct fc_frame *fp, void *arg) { struct fc_fcp_pkt *fsp = (struct fc_fcp_pkt *)arg; - struct fc_lport *lp; + struct fc_lport *lport = fsp->lp; struct fc_frame_header *fh; struct fcp_txrdy *dd; u8 r_ctl; @@ -724,9 +724,8 @@ static void fc_fcp_recv(struct fc_seq *seq, struct fc_frame *fp, void *arg) fh = fc_frame_header_get(fp); r_ctl = fh->fh_r_ctl; - lp = fsp->lp; - if (!(lp->state & LPORT_ST_READY)) + if (!(lport->state & LPORT_ST_READY)) goto out; if (fc_fcp_lock_pkt(fsp)) goto out; @@ -779,7 +778,7 @@ errout: if (IS_ERR(fp)) fc_fcp_error(fsp, fp); else if (rc == -ENOMEM) - fc_fcp_reduce_can_queue(lp); + fc_fcp_reduce_can_queue(lport); } static void fc_fcp_resp(struct fc_fcp_pkt *fsp, struct fc_frame *fp) diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index b8178ef398d..e0c247724d2 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -618,6 +618,11 @@ int fc_fabric_logoff(struct fc_lport *lport) { lport->tt.disc_stop_final(lport); mutex_lock(&lport->lp_mutex); + if (lport->dns_rp) + lport->tt.rport_logoff(lport->dns_rp); + mutex_unlock(&lport->lp_mutex); + lport->tt.rport_flush_queue(); + mutex_lock(&lport->lp_mutex); fc_lport_enter_logo(lport); mutex_unlock(&lport->lp_mutex); cancel_delayed_work_sync(&lport->retry_work); @@ -639,7 +644,12 @@ EXPORT_SYMBOL(fc_fabric_logoff); */ int fc_lport_destroy(struct fc_lport *lport) { + mutex_lock(&lport->lp_mutex); + lport->state = LPORT_ST_NONE; + lport->link_up = 0; lport->tt.frame_send = fc_frame_drop; + mutex_unlock(&lport->lp_mutex); + lport->tt.fcp_abort_io(lport); lport->tt.exch_mgr_reset(lport, 0, 0); return 0; @@ -1032,17 +1042,19 @@ static void fc_lport_rft_id_resp(struct fc_seq *sp, struct fc_frame *fp, FC_DEBUG_LPORT("Received a RFT_ID response\n"); - if (IS_ERR(fp)) { - fc_lport_error(lport, fp); - goto err; - } - if (lport->state != LPORT_ST_RFT_ID) { FC_DBG("Received a RFT_ID response, but in state %s\n", fc_lport_state(lport)); + if (IS_ERR(fp)) + goto err; goto out; } + if (IS_ERR(fp)) { + fc_lport_error(lport, fp); + goto err; + } + fh = fc_frame_header_get(fp); ct = fc_frame_payload_get(fp, sizeof(*ct)); @@ -1084,17 +1096,19 @@ static void fc_lport_rpn_id_resp(struct fc_seq *sp, struct fc_frame *fp, FC_DEBUG_LPORT("Received a RPN_ID response\n"); - if (IS_ERR(fp)) { - fc_lport_error(lport, fp); - goto err; - } - if (lport->state != LPORT_ST_RPN_ID) { FC_DBG("Received a RPN_ID response, but in state %s\n", fc_lport_state(lport)); + if (IS_ERR(fp)) + goto err; goto out; } + if (IS_ERR(fp)) { + fc_lport_error(lport, fp); + goto err; + } + fh = fc_frame_header_get(fp); ct = fc_frame_payload_get(fp, sizeof(*ct)); if (fh && ct && fh->fh_type == FC_TYPE_CT && @@ -1134,17 +1148,19 @@ static void fc_lport_scr_resp(struct fc_seq *sp, struct fc_frame *fp, FC_DEBUG_LPORT("Received a SCR response\n"); - if (IS_ERR(fp)) { - fc_lport_error(lport, fp); - goto err; - } - if (lport->state != LPORT_ST_SCR) { FC_DBG("Received a SCR response, but in state %s\n", fc_lport_state(lport)); + if (IS_ERR(fp)) + goto err; goto out; } + if (IS_ERR(fp)) { + fc_lport_error(lport, fp); + goto err; + } + op = fc_frame_payload_op(fp); if (op == ELS_LS_ACC) fc_lport_enter_ready(lport); @@ -1360,17 +1376,19 @@ static void fc_lport_logo_resp(struct fc_seq *sp, struct fc_frame *fp, FC_DEBUG_LPORT("Received a LOGO response\n"); - if (IS_ERR(fp)) { - fc_lport_error(lport, fp); - goto err; - } - if (lport->state != LPORT_ST_LOGO) { FC_DBG("Received a LOGO response, but in state %s\n", fc_lport_state(lport)); + if (IS_ERR(fp)) + goto err; goto out; } + if (IS_ERR(fp)) { + fc_lport_error(lport, fp); + goto err; + } + op = fc_frame_payload_op(fp); if (op == ELS_LS_ACC) fc_lport_enter_reset(lport); @@ -1400,10 +1418,6 @@ static void fc_lport_enter_logo(struct fc_lport *lport) fc_lport_state_enter(lport, LPORT_ST_LOGO); - /* DNS session should be closed so we can release it here */ - if (lport->dns_rp) - lport->tt.rport_logoff(lport->dns_rp); - fp = fc_frame_alloc(lport, sizeof(*logo)); if (!fp) { fc_lport_error(lport, fp); @@ -1444,17 +1458,19 @@ static void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp, FC_DEBUG_LPORT("Received a FLOGI response\n"); - if (IS_ERR(fp)) { - fc_lport_error(lport, fp); - goto err; - } - if (lport->state != LPORT_ST_FLOGI) { FC_DBG("Received a FLOGI response, but in state %s\n", fc_lport_state(lport)); + if (IS_ERR(fp)) + goto err; goto out; } + if (IS_ERR(fp)) { + fc_lport_error(lport, fp); + goto err; + } + fh = fc_frame_header_get(fp); did = ntoh24(fh->fh_d_id); if (fc_frame_payload_op(fp) == ELS_LS_ACC && did != 0) { diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index 0472bb73221..747d73c5c8a 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -267,6 +267,10 @@ static void fc_rport_work(struct work_struct *work) "(%6x).\n", ids.port_id); event = RPORT_EV_FAILED; } + if (rport->port_id != FC_FID_DIR_SERV) + if (rport_ops->event_callback) + rport_ops->event_callback(lport, rport, + RPORT_EV_FAILED); put_device(&rport->dev); rport = new_rport; rdata = new_rport->dd_data; @@ -325,11 +329,20 @@ int fc_rport_login(struct fc_rport *rport) int fc_rport_logoff(struct fc_rport *rport) { struct fc_rport_libfc_priv *rdata = rport->dd_data; + struct fc_lport *lport = rdata->local_port; mutex_lock(&rdata->rp_mutex); FC_DEBUG_RPORT("Remove port (%6x)\n", rport->port_id); + if (rdata->rp_state == RPORT_ST_NONE) { + FC_DEBUG_RPORT("(%6x): Port (%6x) in NONE state," + " not removing", fc_host_port_id(lport->host), + rport->port_id); + mutex_unlock(&rdata->rp_mutex); + goto out; + } + fc_rport_enter_logo(rport); /* @@ -349,6 +362,7 @@ int fc_rport_logoff(struct fc_rport *rport) mutex_unlock(&rdata->rp_mutex); +out: return 0; } @@ -430,6 +444,7 @@ static void fc_rport_error(struct fc_rport *rport, struct fc_frame *fp) case RPORT_ST_PRLI: case RPORT_ST_LOGO: rdata->event = RPORT_EV_FAILED; + fc_rport_state_enter(rport, RPORT_ST_NONE); queue_work(rport_event_queue, &rdata->event_work); break; @@ -494,7 +509,7 @@ static void fc_rport_plogi_resp(struct fc_seq *sp, struct fc_frame *fp, struct fc_rport *rport = rp_arg; struct fc_rport_libfc_priv *rdata = rport->dd_data; struct fc_lport *lport = rdata->local_port; - struct fc_els_flogi *plp; + struct fc_els_flogi *plp = NULL; unsigned int tov; u16 csp_seq; u16 cssp_seq; @@ -505,17 +520,19 @@ static void fc_rport_plogi_resp(struct fc_seq *sp, struct fc_frame *fp, FC_DEBUG_RPORT("Received a PLOGI response from port (%6x)\n", rport->port_id); - if (IS_ERR(fp)) { - fc_rport_error_retry(rport, fp); - goto err; - } - if (rdata->rp_state != RPORT_ST_PLOGI) { FC_DBG("Received a PLOGI response, but in state %s\n", fc_rport_state(rport)); + if (IS_ERR(fp)) + goto err; goto out; } + if (IS_ERR(fp)) { + fc_rport_error_retry(rport, fp); + goto err; + } + op = fc_frame_payload_op(fp); if (op == ELS_LS_ACC && (plp = fc_frame_payload_get(fp, sizeof(*plp))) != NULL) { @@ -614,17 +631,19 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp, FC_DEBUG_RPORT("Received a PRLI response from port (%6x)\n", rport->port_id); - if (IS_ERR(fp)) { - fc_rport_error_retry(rport, fp); - goto err; - } - if (rdata->rp_state != RPORT_ST_PRLI) { FC_DBG("Received a PRLI response, but in state %s\n", fc_rport_state(rport)); + if (IS_ERR(fp)) + goto err; goto out; } + if (IS_ERR(fp)) { + fc_rport_error_retry(rport, fp); + goto err; + } + op = fc_frame_payload_op(fp); if (op == ELS_LS_ACC) { pp = fc_frame_payload_get(fp, sizeof(*pp)); @@ -646,6 +665,7 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp, } else { FC_DBG("Bad ELS response\n"); rdata->event = RPORT_EV_FAILED; + fc_rport_state_enter(rport, RPORT_ST_NONE); queue_work(rport_event_queue, &rdata->event_work); } @@ -678,23 +698,26 @@ static void fc_rport_logo_resp(struct fc_seq *sp, struct fc_frame *fp, FC_DEBUG_RPORT("Received a LOGO response from port (%6x)\n", rport->port_id); - if (IS_ERR(fp)) { - fc_rport_error_retry(rport, fp); - goto err; - } - if (rdata->rp_state != RPORT_ST_LOGO) { FC_DEBUG_RPORT("Received a LOGO response, but in state %s\n", fc_rport_state(rport)); + if (IS_ERR(fp)) + goto err; goto out; } + if (IS_ERR(fp)) { + fc_rport_error_retry(rport, fp); + goto err; + } + op = fc_frame_payload_op(fp); if (op == ELS_LS_ACC) { fc_rport_enter_rtv(rport); } else { FC_DBG("Bad ELS response\n"); rdata->event = RPORT_EV_LOGO; + fc_rport_state_enter(rport, RPORT_ST_NONE); queue_work(rport_event_queue, &rdata->event_work); } @@ -764,17 +787,19 @@ static void fc_rport_rtv_resp(struct fc_seq *sp, struct fc_frame *fp, FC_DEBUG_RPORT("Received a RTV response from port (%6x)\n", rport->port_id); - if (IS_ERR(fp)) { - fc_rport_error(rport, fp); - goto err; - } - if (rdata->rp_state != RPORT_ST_RTV) { FC_DBG("Received a RTV response, but in state %s\n", fc_rport_state(rport)); + if (IS_ERR(fp)) + goto err; goto out; } + if (IS_ERR(fp)) { + fc_rport_error(rport, fp); + goto err; + } + op = fc_frame_payload_op(fp); if (op == ELS_LS_ACC) { struct fc_els_rtv_acc *rtv; @@ -1007,6 +1032,8 @@ static void fc_rport_recv_plogi_req(struct fc_rport *rport, default: FC_DEBUG_RPORT("incoming PLOGI from %x in unexpected " "state %d\n", sid, rdata->rp_state); + fc_frame_free(fp); + return; break; } @@ -1098,6 +1125,8 @@ static void fc_rport_recv_prli_req(struct fc_rport *rport, reason = ELS_RJT_NONE; break; default: + fc_frame_free(rx_fp); + return; break; } len = fr_len(rx_fp) - sizeof(*fh); @@ -1227,6 +1256,11 @@ static void fc_rport_recv_prlo_req(struct fc_rport *rport, struct fc_seq *sp, "while in state %s\n", ntoh24(fh->fh_s_id), fc_rport_state(rport)); + if (rdata->rp_state == RPORT_ST_NONE) { + fc_frame_free(fp); + return; + } + rjt_data.fp = NULL; rjt_data.reason = ELS_RJT_UNAB; rjt_data.explan = ELS_EXPL_NONE; @@ -1256,7 +1290,13 @@ static void fc_rport_recv_logo_req(struct fc_rport *rport, struct fc_seq *sp, "while in state %s\n", ntoh24(fh->fh_s_id), fc_rport_state(rport)); + if (rdata->rp_state == RPORT_ST_NONE) { + fc_frame_free(fp); + return; + } + rdata->event = RPORT_EV_LOGO; + fc_rport_state_enter(rport, RPORT_ST_NONE); queue_work(rport_event_queue, &rdata->event_work); lport->tt.seq_els_rsp_send(sp, ELS_LS_ACC, NULL); diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 68962835916..e72b4ad47d3 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -1463,6 +1463,16 @@ int iscsi_change_queue_depth(struct scsi_device *sdev, int depth) } EXPORT_SYMBOL_GPL(iscsi_change_queue_depth); +int iscsi_target_alloc(struct scsi_target *starget) +{ + struct iscsi_cls_session *cls_session = starget_to_session(starget); + struct iscsi_session *session = cls_session->dd_data; + + starget->can_queue = session->scsi_cmds_max; + return 0; +} +EXPORT_SYMBOL_GPL(iscsi_target_alloc); + void iscsi_session_recovery_timedout(struct iscsi_cls_session *cls_session) { struct iscsi_session *session = cls_session->dd_data; diff --git a/drivers/scsi/libiscsi_tcp.c b/drivers/scsi/libiscsi_tcp.c index 91f8ce4d8d0..b579ca9f483 100644 --- a/drivers/scsi/libiscsi_tcp.c +++ b/drivers/scsi/libiscsi_tcp.c @@ -1036,8 +1036,11 @@ flush: rc = conn->session->tt->init_pdu(task, r2t->data_offset + r2t->sent, r2t->data_count); - if (rc) + if (rc) { + iscsi_conn_failure(conn, ISCSI_ERR_XMIT_FAILED); return rc; + } + r2t->sent += r2t->data_count; goto flush; } diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index dcba267db71..1105f9a111b 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h @@ -443,6 +443,7 @@ struct lpfc_hba { uint32_t hba_flag; /* hba generic flags */ #define HBA_ERATT_HANDLED 0x1 /* This flag is set when eratt handled */ +#define DEFER_ERATT 0x4 /* Deferred error attention in progress */ struct lpfc_dmabuf slim2p; MAILBOX_t *mbox; @@ -723,4 +724,3 @@ lpfc_sli_read_hs(struct lpfc_hba *phba) return; } - diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 40cf0f4f327..c14f0cbdb12 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -51,7 +51,7 @@ #define LPFC_LINK_SPEED_STRING "0, 1, 2, 4, 8" /** - * lpfc_jedec_to_ascii: Hex to ascii convertor according to JEDEC rules. + * lpfc_jedec_to_ascii - Hex to ascii convertor according to JEDEC rules * @incr: integer to convert. * @hdw: ascii string holding converted integer plus a string terminator. * @@ -82,7 +82,7 @@ lpfc_jedec_to_ascii(int incr, char hdw[]) } /** - * lpfc_drvr_version_show: Return the Emulex driver string with version number. + * lpfc_drvr_version_show - Return the Emulex driver string with version number * @dev: class unused variable. * @attr: device attribute, not used. * @buf: on return contains the module description text. @@ -152,7 +152,7 @@ lpfc_bg_reftag_err_show(struct device *dev, struct device_attribute *attr, } /** - * lpfc_info_show: Return some pci info about the host in ascii. + * lpfc_info_show - Return some pci info about the host in ascii * @dev: class converted to a Scsi_host structure. * @attr: device attribute, not used. * @buf: on return contains the formatted text from lpfc_info(). @@ -169,7 +169,7 @@ lpfc_info_show(struct device *dev, struct device_attribute *attr, } /** - * lpfc_serialnum_show: Return the hba serial number in ascii. + * lpfc_serialnum_show - Return the hba serial number in ascii * @dev: class converted to a Scsi_host structure. * @attr: device attribute, not used. * @buf: on return contains the formatted text serial number. @@ -188,7 +188,7 @@ lpfc_serialnum_show(struct device *dev, struct device_attribute *attr, } /** - * lpfc_temp_sensor_show: Return the temperature sensor level. + * lpfc_temp_sensor_show - Return the temperature sensor level * @dev: class converted to a Scsi_host structure. * @attr: device attribute, not used. * @buf: on return contains the formatted support level. @@ -210,7 +210,7 @@ lpfc_temp_sensor_show(struct device *dev, struct device_attribute *attr, } /** - * lpfc_modeldesc_show: Return the model description of the hba. + * lpfc_modeldesc_show - Return the model description of the hba * @dev: class converted to a Scsi_host structure. * @attr: device attribute, not used. * @buf: on return contains the scsi vpd model description. @@ -229,7 +229,7 @@ lpfc_modeldesc_show(struct device *dev, struct device_attribute *attr, } /** - * lpfc_modelname_show: Return the model name of the hba. + * lpfc_modelname_show - Return the model name of the hba * @dev: class converted to a Scsi_host structure. * @attr: device attribute, not used. * @buf: on return contains the scsi vpd model name. @@ -248,7 +248,7 @@ lpfc_modelname_show(struct device *dev, struct device_attribute *attr, } /** - * lpfc_programtype_show: Return the program type of the hba. + * lpfc_programtype_show - Return the program type of the hba * @dev: class converted to a Scsi_host structure. * @attr: device attribute, not used. * @buf: on return contains the scsi vpd program type. @@ -267,7 +267,7 @@ lpfc_programtype_show(struct device *dev, struct device_attribute *attr, } /** - * lpfc_mlomgmt_show: Return the Menlo Maintenance sli flag. + * lpfc_mlomgmt_show - Return the Menlo Maintenance sli flag * @dev: class converted to a Scsi_host structure. * @attr: device attribute, not used. * @buf: on return contains the Menlo Maintenance sli flag. @@ -286,7 +286,7 @@ lpfc_mlomgmt_show(struct device *dev, struct device_attribute *attr, char *buf) } /** - * lpfc_vportnum_show: Return the port number in ascii of the hba. + * lpfc_vportnum_show - Return the port number in ascii of the hba * @dev: class converted to a Scsi_host structure. * @attr: device attribute, not used. * @buf: on return contains scsi vpd program type. @@ -305,7 +305,7 @@ lpfc_vportnum_show(struct device *dev, struct device_attribute *attr, } /** - * lpfc_fwrev_show: Return the firmware rev running in the hba. + * lpfc_fwrev_show - Return the firmware rev running in the hba * @dev: class converted to a Scsi_host structure. * @attr: device attribute, not used. * @buf: on return contains the scsi vpd program type. @@ -326,7 +326,7 @@ lpfc_fwrev_show(struct device *dev, struct device_attribute *attr, } /** - * lpfc_hdw_show: Return the jedec information about the hba. + * lpfc_hdw_show - Return the jedec information about the hba * @dev: class converted to a Scsi_host structure. * @attr: device attribute, not used. * @buf: on return contains the scsi vpd program type. @@ -347,7 +347,7 @@ lpfc_hdw_show(struct device *dev, struct device_attribute *attr, char *buf) } /** - * lpfc_option_rom_version_show: Return the adapter ROM FCode version. + * lpfc_option_rom_version_show - Return the adapter ROM FCode version * @dev: class converted to a Scsi_host structure. * @attr: device attribute, not used. * @buf: on return contains the ROM and FCode ascii strings. @@ -366,7 +366,7 @@ lpfc_option_rom_version_show(struct device *dev, struct device_attribute *attr, } /** - * lpfc_state_show: Return the link state of the port. + * lpfc_state_show - Return the link state of the port * @dev: class converted to a Scsi_host structure. * @attr: device attribute, not used. * @buf: on return contains text describing the state of the link. @@ -451,7 +451,7 @@ lpfc_link_state_show(struct device *dev, struct device_attribute *attr, } /** - * lpfc_num_discovered_ports_show: Return sum of mapped and unmapped vports. + * lpfc_num_discovered_ports_show - Return sum of mapped and unmapped vports * @dev: class device that is converted into a Scsi_host. * @attr: device attribute, not used. * @buf: on return contains the sum of fc mapped and unmapped. @@ -474,7 +474,7 @@ lpfc_num_discovered_ports_show(struct device *dev, } /** - * lpfc_issue_lip: Misnomer, name carried over from long ago. + * lpfc_issue_lip - Misnomer, name carried over from long ago * @shost: Scsi_Host pointer. * * Description: @@ -529,7 +529,7 @@ lpfc_issue_lip(struct Scsi_Host *shost) } /** - * lpfc_do_offline: Issues a mailbox command to bring the link down. + * lpfc_do_offline - Issues a mailbox command to bring the link down * @phba: lpfc_hba pointer. * @type: LPFC_EVT_OFFLINE, LPFC_EVT_WARM_START, LPFC_EVT_KILL. * @@ -537,7 +537,7 @@ lpfc_issue_lip(struct Scsi_Host *shost) * Assumes any error from lpfc_do_offline() will be negative. * Can wait up to 5 seconds for the port ring buffers count * to reach zero, prints a warning if it is not zero and continues. - * lpfc_workq_post_event() returns a non-zero return coce if call fails. + * lpfc_workq_post_event() returns a non-zero return code if call fails. * * Returns: * -EIO error posting the event @@ -591,7 +591,7 @@ lpfc_do_offline(struct lpfc_hba *phba, uint32_t type) } /** - * lpfc_selective_reset: Offline then onlines the port. + * lpfc_selective_reset - Offline then onlines the port * @phba: lpfc_hba pointer. * * Description: @@ -632,7 +632,7 @@ lpfc_selective_reset(struct lpfc_hba *phba) } /** - * lpfc_issue_reset: Selectively resets an adapter. + * lpfc_issue_reset - Selectively resets an adapter * @dev: class device that is converted into a Scsi_host. * @attr: device attribute, not used. * @buf: containing the string "selective". @@ -672,7 +672,7 @@ lpfc_issue_reset(struct device *dev, struct device_attribute *attr, } /** - * lpfc_nport_evt_cnt_show: Return the number of nport events. + * lpfc_nport_evt_cnt_show - Return the number of nport events * @dev: class device that is converted into a Scsi_host. * @attr: device attribute, not used. * @buf: on return contains the ascii number of nport events. @@ -691,7 +691,7 @@ lpfc_nport_evt_cnt_show(struct device *dev, struct device_attribute *attr, } /** - * lpfc_board_mode_show: Return the state of the board. + * lpfc_board_mode_show - Return the state of the board * @dev: class device that is converted into a Scsi_host. * @attr: device attribute, not used. * @buf: on return contains the state of the adapter. @@ -720,7 +720,7 @@ lpfc_board_mode_show(struct device *dev, struct device_attribute *attr, } /** - * lpfc_board_mode_store: Puts the hba in online, offline, warm or error state. + * lpfc_board_mode_store - Puts the hba in online, offline, warm or error state * @dev: class device that is converted into a Scsi_host. * @attr: device attribute, not used. * @buf: containing one of the strings "online", "offline", "warm" or "error". @@ -766,14 +766,14 @@ lpfc_board_mode_store(struct device *dev, struct device_attribute *attr, } /** - * lpfc_get_hba_info: Return various bits of informaton about the adapter. + * lpfc_get_hba_info - Return various bits of informaton about the adapter * @phba: pointer to the adapter structure. - * @mxri max xri count. - * @axri available xri count. - * @mrpi max rpi count. - * @arpi available rpi count. - * @mvpi max vpi count. - * @avpi available vpi count. + * @mxri: max xri count. + * @axri: available xri count. + * @mrpi: max rpi count. + * @arpi: available rpi count. + * @mvpi: max vpi count. + * @avpi: available vpi count. * * Description: * If an integer pointer for an count is not null then the value for the @@ -846,7 +846,7 @@ lpfc_get_hba_info(struct lpfc_hba *phba, } /** - * lpfc_max_rpi_show: Return maximum rpi. + * lpfc_max_rpi_show - Return maximum rpi * @dev: class device that is converted into a Scsi_host. * @attr: device attribute, not used. * @buf: on return contains the maximum rpi count in decimal or "Unknown". @@ -874,7 +874,7 @@ lpfc_max_rpi_show(struct device *dev, struct device_attribute *attr, } /** - * lpfc_used_rpi_show: Return maximum rpi minus available rpi. + * lpfc_used_rpi_show - Return maximum rpi minus available rpi * @dev: class device that is converted into a Scsi_host. * @attr: device attribute, not used. * @buf: containing the used rpi count in decimal or "Unknown". @@ -902,7 +902,7 @@ lpfc_used_rpi_show(struct device *dev, struct device_attribute *attr, } /** - * lpfc_max_xri_show: Return maximum xri. + * lpfc_max_xri_show - Return maximum xri * @dev: class device that is converted into a Scsi_host. * @attr: device attribute, not used. * @buf: on return contains the maximum xri count in decimal or "Unknown". @@ -930,7 +930,7 @@ lpfc_max_xri_show(struct device *dev, struct device_attribute *attr, } /** - * lpfc_used_xri_show: Return maximum xpi minus the available xpi. + * lpfc_used_xri_show - Return maximum xpi minus the available xpi * @dev: class device that is converted into a Scsi_host. * @attr: device attribute, not used. * @buf: on return contains the used xri count in decimal or "Unknown". @@ -958,7 +958,7 @@ lpfc_used_xri_show(struct device *dev, struct device_attribute *attr, } /** - * lpfc_max_vpi_show: Return maximum vpi. + * lpfc_max_vpi_show - Return maximum vpi * @dev: class device that is converted into a Scsi_host. * @attr: device attribute, not used. * @buf: on return contains the maximum vpi count in decimal or "Unknown". @@ -986,7 +986,7 @@ lpfc_max_vpi_show(struct device *dev, struct device_attribute *attr, } /** - * lpfc_used_vpi_show: Return maximum vpi minus the available vpi. + * lpfc_used_vpi_show - Return maximum vpi minus the available vpi * @dev: class device that is converted into a Scsi_host. * @attr: device attribute, not used. * @buf: on return contains the used vpi count in decimal or "Unknown". @@ -1014,7 +1014,7 @@ lpfc_used_vpi_show(struct device *dev, struct device_attribute *attr, } /** - * lpfc_npiv_info_show: Return text about NPIV support for the adapter. + * lpfc_npiv_info_show - Return text about NPIV support for the adapter * @dev: class device that is converted into a Scsi_host. * @attr: device attribute, not used. * @buf: text that must be interpreted to determine if npiv is supported. @@ -1042,7 +1042,7 @@ lpfc_npiv_info_show(struct device *dev, struct device_attribute *attr, } /** - * lpfc_poll_show: Return text about poll support for the adapter. + * lpfc_poll_show - Return text about poll support for the adapter * @dev: class device that is converted into a Scsi_host. * @attr: device attribute, not used. * @buf: on return contains the cfg_poll in hex. @@ -1064,7 +1064,7 @@ lpfc_poll_show(struct device *dev, struct device_attribute *attr, } /** - * lpfc_poll_store: Set the value of cfg_poll for the adapter. + * lpfc_poll_store - Set the value of cfg_poll for the adapter * @dev: class device that is converted into a Scsi_host. * @attr: device attribute, not used. * @buf: one or more lpfc_polling_flags values. @@ -1136,7 +1136,7 @@ lpfc_poll_store(struct device *dev, struct device_attribute *attr, } /** - * lpfc_param_show: Return a cfg attribute value in decimal. + * lpfc_param_show - Return a cfg attribute value in decimal * * Description: * Macro that given an attr e.g. hba_queue_depth expands @@ -1164,7 +1164,7 @@ lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \ } /** - * lpfc_param_hex_show: Return a cfg attribute value in hex. + * lpfc_param_hex_show - Return a cfg attribute value in hex * * Description: * Macro that given an attr e.g. hba_queue_depth expands @@ -1173,7 +1173,7 @@ lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \ * lpfc_##attr##_show: Return the hex value of an adapters cfg_xxx field. * @dev: class device that is converted into a Scsi_host. * @attr: device attribute, not used. - * @buf: on return contains the attribute value in hexidecimal. + * @buf: on return contains the attribute value in hexadecimal. * * Returns: size of formatted string. **/ @@ -1192,7 +1192,7 @@ lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \ } /** - * lpfc_param_init: Intializes a cfg attribute. + * lpfc_param_init - Intializes a cfg attribute * * Description: * Macro that given an attr e.g. hba_queue_depth expands @@ -1226,7 +1226,7 @@ lpfc_##attr##_init(struct lpfc_hba *phba, int val) \ } /** - * lpfc_param_set: Set a cfg attribute value. + * lpfc_param_set - Set a cfg attribute value * * Description: * Macro that given an attr e.g. hba_queue_depth expands @@ -1260,7 +1260,7 @@ lpfc_##attr##_set(struct lpfc_hba *phba, int val) \ } /** - * lpfc_param_store: Set a vport attribute value. + * lpfc_param_store - Set a vport attribute value * * Description: * Macro that given an attr e.g. hba_queue_depth expands @@ -1300,7 +1300,7 @@ lpfc_##attr##_store(struct device *dev, struct device_attribute *attr, \ } /** - * lpfc_vport_param_show: Return decimal formatted cfg attribute value. + * lpfc_vport_param_show - Return decimal formatted cfg attribute value * * Description: * Macro that given an attr e.g. hba_queue_depth expands @@ -1326,17 +1326,17 @@ lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \ } /** - * lpfc_vport_param_hex_show: Return hex formatted attribute value. + * lpfc_vport_param_hex_show - Return hex formatted attribute value * * Description: * Macro that given an attr e.g. * hba_queue_depth expands into a function with the name * lpfc_hba_queue_depth_show * - * lpfc_##attr##_show: prints the attribute value in hexidecimal. + * lpfc_##attr##_show: prints the attribute value in hexadecimal. * @dev: class device that is converted into a Scsi_host. * @attr: device attribute, not used. - * @buf: on return contains the attribute value in hexidecimal. + * @buf: on return contains the attribute value in hexadecimal. * * Returns: length of formatted string. **/ @@ -1353,7 +1353,7 @@ lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \ } /** - * lpfc_vport_param_init: Initialize a vport cfg attribute. + * lpfc_vport_param_init - Initialize a vport cfg attribute * * Description: * Macro that given an attr e.g. hba_queue_depth expands @@ -1386,7 +1386,7 @@ lpfc_##attr##_init(struct lpfc_vport *vport, int val) \ } /** - * lpfc_vport_param_set: Set a vport cfg attribute. + * lpfc_vport_param_set - Set a vport cfg attribute * * Description: * Macro that given an attr e.g. hba_queue_depth expands @@ -1417,7 +1417,7 @@ lpfc_##attr##_set(struct lpfc_vport *vport, int val) \ } /** - * lpfc_vport_param_store: Set a vport attribute. + * lpfc_vport_param_store - Set a vport attribute * * Description: * Macro that given an attr e.g. hba_queue_depth @@ -1576,7 +1576,7 @@ static DEVICE_ATTR(lpfc_temp_sensor, S_IRUGO, lpfc_temp_sensor_show, NULL); static char *lpfc_soft_wwn_key = "C99G71SL8032A"; /** - * lpfc_soft_wwn_enable_store: Allows setting of the wwn if the key is valid. + * lpfc_soft_wwn_enable_store - Allows setting of the wwn if the key is valid * @dev: class device that is converted into a Scsi_host. * @attr: device attribute, not used. * @buf: containing the string lpfc_soft_wwn_key. @@ -1623,10 +1623,10 @@ static DEVICE_ATTR(lpfc_soft_wwn_enable, S_IWUSR, NULL, lpfc_soft_wwn_enable_store); /** - * lpfc_soft_wwpn_show: Return the cfg soft ww port name of the adapter. + * lpfc_soft_wwpn_show - Return the cfg soft ww port name of the adapter * @dev: class device that is converted into a Scsi_host. * @attr: device attribute, not used. - * @buf: on return contains the wwpn in hexidecimal. + * @buf: on return contains the wwpn in hexadecimal. * * Returns: size of formatted string. **/ @@ -1643,10 +1643,10 @@ lpfc_soft_wwpn_show(struct device *dev, struct device_attribute *attr, } /** - * lpfc_soft_wwpn_store: Set the ww port name of the adapter. + * lpfc_soft_wwpn_store - Set the ww port name of the adapter * @dev class device that is converted into a Scsi_host. * @attr: device attribute, not used. - * @buf: contains the wwpn in hexidecimal. + * @buf: contains the wwpn in hexadecimal. * @count: number of wwpn bytes in buf * * Returns: @@ -1729,10 +1729,10 @@ static DEVICE_ATTR(lpfc_soft_wwpn, S_IRUGO | S_IWUSR,\ lpfc_soft_wwpn_show, lpfc_soft_wwpn_store); /** - * lpfc_soft_wwnn_show: Return the cfg soft ww node name for the adapter. + * lpfc_soft_wwnn_show - Return the cfg soft ww node name for the adapter * @dev: class device that is converted into a Scsi_host. * @attr: device attribute, not used. - * @buf: on return contains the wwnn in hexidecimal. + * @buf: on return contains the wwnn in hexadecimal. * * Returns: size of formatted string. **/ @@ -1747,9 +1747,9 @@ lpfc_soft_wwnn_show(struct device *dev, struct device_attribute *attr, } /** - * lpfc_soft_wwnn_store: sets the ww node name of the adapter. + * lpfc_soft_wwnn_store - sets the ww node name of the adapter * @cdev: class device that is converted into a Scsi_host. - * @buf: contains the ww node name in hexidecimal. + * @buf: contains the ww node name in hexadecimal. * @count: number of wwnn bytes in buf. * * Returns: @@ -1845,7 +1845,7 @@ MODULE_PARM_DESC(lpfc_nodev_tmo, "for a device to come back"); /** - * lpfc_nodev_tmo_show: Return the hba dev loss timeout value. + * lpfc_nodev_tmo_show - Return the hba dev loss timeout value * @dev: class converted to a Scsi_host structure. * @attr: device attribute, not used. * @buf: on return contains the dev loss timeout in decimal. @@ -1864,7 +1864,7 @@ lpfc_nodev_tmo_show(struct device *dev, struct device_attribute *attr, } /** - * lpfc_nodev_tmo_init: Set the hba nodev timeout value. + * lpfc_nodev_tmo_init - Set the hba nodev timeout value * @vport: lpfc vport structure pointer. * @val: contains the nodev timeout value. * @@ -1905,7 +1905,7 @@ lpfc_nodev_tmo_init(struct lpfc_vport *vport, int val) } /** - * lpfc_update_rport_devloss_tmo: Update dev loss tmo value. + * lpfc_update_rport_devloss_tmo - Update dev loss tmo value * @vport: lpfc vport structure pointer. * * Description: @@ -1926,7 +1926,7 @@ lpfc_update_rport_devloss_tmo(struct lpfc_vport *vport) } /** - * lpfc_nodev_tmo_set: Set the vport nodev tmo and devloss tmo values. + * lpfc_nodev_tmo_set - Set the vport nodev tmo and devloss tmo values * @vport: lpfc vport structure pointer. * @val: contains the tmo value. * @@ -1982,7 +1982,7 @@ lpfc_vport_param_init(devloss_tmo, LPFC_DEF_DEVLOSS_TMO, lpfc_vport_param_show(devloss_tmo) /** - * lpfc_devloss_tmo_set: Sets vport nodev tmo, devloss tmo values, changed bit. + * lpfc_devloss_tmo_set - Sets vport nodev tmo, devloss tmo values, changed bit * @vport: lpfc vport structure pointer. * @val: contains the tmo value. * @@ -2094,7 +2094,7 @@ MODULE_PARM_DESC(lpfc_restrict_login, lpfc_vport_param_show(restrict_login); /** - * lpfc_restrict_login_init: Set the vport restrict login flag. + * lpfc_restrict_login_init - Set the vport restrict login flag * @vport: lpfc vport structure pointer. * @val: contains the restrict login value. * @@ -2128,7 +2128,7 @@ lpfc_restrict_login_init(struct lpfc_vport *vport, int val) } /** - * lpfc_restrict_login_set: Set the vport restrict login flag. + * lpfc_restrict_login_set - Set the vport restrict login flag * @vport: lpfc vport structure pointer. * @val: contains the restrict login value. * @@ -2201,7 +2201,7 @@ LPFC_VPORT_ATTR_R(scan_down, 1, 0, 1, */ /** - * lpfc_topology_set: Set the adapters topology field. + * lpfc_topology_set - Set the adapters topology field * @phba: lpfc_hba pointer. * @val: topology value. * @@ -2216,18 +2216,41 @@ LPFC_VPORT_ATTR_R(scan_down, 1, 0, 1, * non-zero return value from lpfc_issue_lip() * -EINVAL val out of range **/ -static int -lpfc_topology_set(struct lpfc_hba *phba, int val) +static ssize_t +lpfc_topology_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { + struct Scsi_Host *shost = class_to_shost(dev); + struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; + struct lpfc_hba *phba = vport->phba; + int val = 0; + int nolip = 0; + const char *val_buf = buf; int err; uint32_t prev_val; + + if (!strncmp(buf, "nolip ", strlen("nolip "))) { + nolip = 1; + val_buf = &buf[strlen("nolip ")]; + } + + if (!isdigit(val_buf[0])) + return -EINVAL; + if (sscanf(val_buf, "%i", &val) != 1) + return -EINVAL; + if (val >= 0 && val <= 6) { prev_val = phba->cfg_topology; phba->cfg_topology = val; + if (nolip) + return strlen(buf); + err = lpfc_issue_lip(lpfc_shost_from_vport(phba->pport)); - if (err) + if (err) { phba->cfg_topology = prev_val; - return err; + return -EINVAL; + } else + return strlen(buf); } lpfc_printf_log(phba, KERN_ERR, LOG_INIT, "%d:0467 lpfc_topology attribute cannot be set to %d, " @@ -2240,14 +2263,12 @@ module_param(lpfc_topology, int, 0); MODULE_PARM_DESC(lpfc_topology, "Select Fibre Channel topology"); lpfc_param_show(topology) lpfc_param_init(topology, 0, 0, 6) -lpfc_param_store(topology) static DEVICE_ATTR(lpfc_topology, S_IRUGO | S_IWUSR, lpfc_topology_show, lpfc_topology_store); /** - * lpfc_stat_data_ctrl_store: write call back for lpfc_stat_data_ctrl - * sysfs file. + * lpfc_stat_data_ctrl_store - write call back for lpfc_stat_data_ctrl sysfs file * @dev: Pointer to class device. * @buf: Data buffer. * @count: Size of the data buffer. @@ -2282,7 +2303,7 @@ lpfc_stat_data_ctrl_store(struct device *dev, struct device_attribute *attr, unsigned long base, step, bucket_type; if (!strncmp(buf, "setbucket", strlen("setbucket"))) { - if (strlen(buf) > LPFC_MAX_DATA_CTRL_LEN) + if (strlen(buf) > (LPFC_MAX_DATA_CTRL_LEN - 1)) return -EINVAL; strcpy(bucket_data, buf); @@ -2411,8 +2432,7 @@ lpfc_stat_data_ctrl_store(struct device *dev, struct device_attribute *attr, /** - * lpfc_stat_data_ctrl_show: Read callback function for - * lpfc_stat_data_ctrl sysfs file. + * lpfc_stat_data_ctrl_show - Read function for lpfc_stat_data_ctrl sysfs file * @dev: Pointer to class device object. * @buf: Data buffer. * @@ -2489,8 +2509,7 @@ static DEVICE_ATTR(lpfc_stat_data_ctrl, S_IRUGO | S_IWUSR, /** - * sysfs_drvr_stat_data_read: Read callback function for lpfc_drvr_stat_data - * sysfs attribute. + * sysfs_drvr_stat_data_read - Read function for lpfc_drvr_stat_data attribute * @kobj: Pointer to the kernel object * @bin_attr: Attribute object * @buff: Buffer pointer @@ -2585,7 +2604,7 @@ static struct bin_attribute sysfs_drvr_stat_data_attr = { */ /** - * lpfc_link_speed_set: Set the adapters link speed. + * lpfc_link_speed_set - Set the adapters link speed * @phba: lpfc_hba pointer. * @val: link speed value. * @@ -2601,12 +2620,29 @@ static struct bin_attribute sysfs_drvr_stat_data_attr = { * non-zero return value from lpfc_issue_lip() * -EINVAL val out of range **/ -static int -lpfc_link_speed_set(struct lpfc_hba *phba, int val) +static ssize_t +lpfc_link_speed_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { + struct Scsi_Host *shost = class_to_shost(dev); + struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; + struct lpfc_hba *phba = vport->phba; + int val = 0; + int nolip = 0; + const char *val_buf = buf; int err; uint32_t prev_val; + if (!strncmp(buf, "nolip ", strlen("nolip "))) { + nolip = 1; + val_buf = &buf[strlen("nolip ")]; + } + + if (!isdigit(val_buf[0])) + return -EINVAL; + if (sscanf(val_buf, "%i", &val) != 1) + return -EINVAL; + if (((val == LINK_SPEED_1G) && !(phba->lmt & LMT_1Gb)) || ((val == LINK_SPEED_2G) && !(phba->lmt & LMT_2Gb)) || ((val == LINK_SPEED_4G) && !(phba->lmt & LMT_4Gb)) || @@ -2614,14 +2650,19 @@ lpfc_link_speed_set(struct lpfc_hba *phba, int val) ((val == LINK_SPEED_10G) && !(phba->lmt & LMT_10Gb))) return -EINVAL; - if ((val >= 0 && val <= LPFC_MAX_LINK_SPEED) + if ((val >= 0 && val <= 8) && (LPFC_LINK_SPEED_BITMAP & (1 << val))) { prev_val = phba->cfg_link_speed; phba->cfg_link_speed = val; + if (nolip) + return strlen(buf); + err = lpfc_issue_lip(lpfc_shost_from_vport(phba->pport)); - if (err) + if (err) { phba->cfg_link_speed = prev_val; - return err; + return -EINVAL; + } else + return strlen(buf); } lpfc_printf_log(phba, KERN_ERR, LOG_INIT, @@ -2637,7 +2678,7 @@ MODULE_PARM_DESC(lpfc_link_speed, "Select link speed"); lpfc_param_show(link_speed) /** - * lpfc_link_speed_init: Set the adapters link speed. + * lpfc_link_speed_init - Set the adapters link speed * @phba: lpfc_hba pointer. * @val: link speed value. * @@ -2668,7 +2709,6 @@ lpfc_link_speed_init(struct lpfc_hba *phba, int val) return -EINVAL; } -lpfc_param_store(link_speed) static DEVICE_ATTR(lpfc_link_speed, S_IRUGO | S_IWUSR, lpfc_link_speed_show, lpfc_link_speed_store); @@ -2865,7 +2905,7 @@ MODULE_PARM_DESC(lpfc_prot_guard, "host protection guard type"); /* - * lpfc_sg_seg_cnt: Initial Maximum DMA Segment Count + * lpfc_sg_seg_cnt - Initial Maximum DMA Segment Count * This value can be set to values between 64 and 256. The default value is * 64, but may be increased to allow for larger Max I/O sizes. The scsi layer * will be allowed to request I/Os of sizes up to (MAX_SEG_COUNT * SEG_SIZE). @@ -2967,7 +3007,7 @@ struct device_attribute *lpfc_vport_attrs[] = { }; /** - * sysfs_ctlreg_write: Write method for writing to ctlreg. + * sysfs_ctlreg_write - Write method for writing to ctlreg * @kobj: kernel kobject that contains the kernel class device. * @bin_attr: kernel attributes passed to us. * @buf: contains the data to be written to the adapter IOREG space. @@ -3017,7 +3057,7 @@ sysfs_ctlreg_write(struct kobject *kobj, struct bin_attribute *bin_attr, } /** - * sysfs_ctlreg_read: Read method for reading from ctlreg. + * sysfs_ctlreg_read - Read method for reading from ctlreg * @kobj: kernel kobject that contains the kernel class device. * @bin_attr: kernel attributes passed to us. * @buf: if succesful contains the data from the adapter IOREG space. @@ -3078,7 +3118,7 @@ static struct bin_attribute sysfs_ctlreg_attr = { }; /** - * sysfs_mbox_idle: frees the sysfs mailbox. + * sysfs_mbox_idle - frees the sysfs mailbox * @phba: lpfc_hba pointer **/ static void @@ -3095,7 +3135,7 @@ sysfs_mbox_idle(struct lpfc_hba *phba) } /** - * sysfs_mbox_write: Write method for writing information via mbox. + * sysfs_mbox_write - Write method for writing information via mbox * @kobj: kernel kobject that contains the kernel class device. * @bin_attr: kernel attributes passed to us. * @buf: contains the data to be written to sysfs mbox. @@ -3170,7 +3210,7 @@ sysfs_mbox_write(struct kobject *kobj, struct bin_attribute *bin_attr, } /** - * sysfs_mbox_read: Read method for reading information via mbox. + * sysfs_mbox_read - Read method for reading information via mbox * @kobj: kernel kobject that contains the kernel class device. * @bin_attr: kernel attributes passed to us. * @buf: contains the data to be read from sysfs mbox. @@ -3374,7 +3414,7 @@ static struct bin_attribute sysfs_mbox_attr = { }; /** - * lpfc_alloc_sysfs_attr: Creates the ctlreg and mbox entries. + * lpfc_alloc_sysfs_attr - Creates the ctlreg and mbox entries * @vport: address of lpfc vport structure. * * Return codes: @@ -3415,7 +3455,7 @@ out: } /** - * lpfc_free_sysfs_attr: Removes the ctlreg and mbox entries. + * lpfc_free_sysfs_attr - Removes the ctlreg and mbox entries * @vport: address of lpfc vport structure. **/ void @@ -3437,7 +3477,7 @@ lpfc_free_sysfs_attr(struct lpfc_vport *vport) */ /** - * lpfc_get_host_port_id: Copy the vport DID into the scsi host port id. + * lpfc_get_host_port_id - Copy the vport DID into the scsi host port id * @shost: kernel scsi host pointer. **/ static void @@ -3450,7 +3490,7 @@ lpfc_get_host_port_id(struct Scsi_Host *shost) } /** - * lpfc_get_host_port_type: Set the value of the scsi host port type. + * lpfc_get_host_port_type - Set the value of the scsi host port type * @shost: kernel scsi host pointer. **/ static void @@ -3482,7 +3522,7 @@ lpfc_get_host_port_type(struct Scsi_Host *shost) } /** - * lpfc_get_host_port_state: Set the value of the scsi host port state. + * lpfc_get_host_port_state - Set the value of the scsi host port state * @shost: kernel scsi host pointer. **/ static void @@ -3520,7 +3560,7 @@ lpfc_get_host_port_state(struct Scsi_Host *shost) } /** - * lpfc_get_host_speed: Set the value of the scsi host speed. + * lpfc_get_host_speed - Set the value of the scsi host speed * @shost: kernel scsi host pointer. **/ static void @@ -3556,7 +3596,7 @@ lpfc_get_host_speed(struct Scsi_Host *shost) } /** - * lpfc_get_host_fabric_name: Set the value of the scsi host fabric name. + * lpfc_get_host_fabric_name - Set the value of the scsi host fabric name * @shost: kernel scsi host pointer. **/ static void @@ -3582,7 +3622,7 @@ lpfc_get_host_fabric_name (struct Scsi_Host *shost) } /** - * lpfc_get_stats: Return statistical information about the adapter. + * lpfc_get_stats - Return statistical information about the adapter * @shost: kernel scsi host pointer. * * Notes: @@ -3707,7 +3747,7 @@ lpfc_get_stats(struct Scsi_Host *shost) } /** - * lpfc_reset_stats: Copy the adapter link stats information. + * lpfc_reset_stats - Copy the adapter link stats information * @shost: kernel scsi host pointer. **/ static void @@ -3788,7 +3828,7 @@ lpfc_reset_stats(struct Scsi_Host *shost) */ /** - * lpfc_get_node_by_target: Return the nodelist for a target. + * lpfc_get_node_by_target - Return the nodelist for a target * @starget: kernel scsi target pointer. * * Returns: @@ -3817,7 +3857,7 @@ lpfc_get_node_by_target(struct scsi_target *starget) } /** - * lpfc_get_starget_port_id: Set the target port id to the ndlp DID or -1. + * lpfc_get_starget_port_id - Set the target port id to the ndlp DID or -1 * @starget: kernel scsi target pointer. **/ static void @@ -3829,7 +3869,7 @@ lpfc_get_starget_port_id(struct scsi_target *starget) } /** - * lpfc_get_starget_node_name: Set the target node name. + * lpfc_get_starget_node_name - Set the target node name * @starget: kernel scsi target pointer. * * Description: Set the target node name to the ndlp node name wwn or zero. @@ -3844,7 +3884,7 @@ lpfc_get_starget_node_name(struct scsi_target *starget) } /** - * lpfc_get_starget_port_name: Set the target port name. + * lpfc_get_starget_port_name - Set the target port name * @starget: kernel scsi target pointer. * * Description: set the target port name to the ndlp port name wwn or zero. @@ -3859,7 +3899,7 @@ lpfc_get_starget_port_name(struct scsi_target *starget) } /** - * lpfc_set_rport_loss_tmo: Set the rport dev loss tmo. + * lpfc_set_rport_loss_tmo - Set the rport dev loss tmo * @rport: fc rport address. * @timeout: new value for dev loss tmo. * @@ -3877,7 +3917,7 @@ lpfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout) } /** - * lpfc_rport_show_function: Return rport target information. + * lpfc_rport_show_function - Return rport target information * * Description: * Macro that uses field to generate a function with the name lpfc_show_rport_ @@ -3905,7 +3945,7 @@ lpfc_show_rport_##field (struct device *dev, \ static FC_RPORT_ATTR(field, S_IRUGO, lpfc_show_rport_##field, NULL) /** - * lpfc_set_vport_symbolic_name: Set the vport's symbolic name. + * lpfc_set_vport_symbolic_name - Set the vport's symbolic name * @fc_vport: The fc_vport who's symbolic name has been changed. * * Description: @@ -4048,7 +4088,7 @@ struct fc_function_template lpfc_vport_transport_functions = { }; /** - * lpfc_get_cfgparam: Used during probe_one to init the adapter structure. + * lpfc_get_cfgparam - Used during probe_one to init the adapter structure * @phba: lpfc_hba pointer. **/ void @@ -4097,7 +4137,7 @@ lpfc_get_cfgparam(struct lpfc_hba *phba) } /** - * lpfc_get_vport_cfgparam: Used during port create, init the vport structure. + * lpfc_get_vport_cfgparam - Used during port create, init the vport structure * @vport: lpfc_vport pointer. **/ void diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index 07f4976319a..f88ce3f2619 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h @@ -184,6 +184,8 @@ void lpfc_sli_poll_fcp_ring(struct lpfc_hba *); struct lpfc_iocbq * lpfc_sli_get_iocbq(struct lpfc_hba *); void lpfc_sli_release_iocbq(struct lpfc_hba *, struct lpfc_iocbq *); uint16_t lpfc_sli_next_iotag(struct lpfc_hba *, struct lpfc_iocbq *); +void lpfc_sli_cancel_iocbs(struct lpfc_hba *, struct list_head *, uint32_t, + uint32_t); void lpfc_reset_barrier(struct lpfc_hba * phba); int lpfc_sli_brdready(struct lpfc_hba *, uint32_t); diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c index 81cdcf46c47..52be5644e07 100644 --- a/drivers/scsi/lpfc/lpfc_debugfs.c +++ b/drivers/scsi/lpfc/lpfc_debugfs.c @@ -47,7 +47,7 @@ #include "lpfc_debugfs.h" #ifdef CONFIG_SCSI_LPFC_DEBUG_FS -/** +/* * debugfs interface * * To access this interface the user should: @@ -95,7 +95,7 @@ module_param(lpfc_debugfs_max_slow_ring_trc, int, 0); MODULE_PARM_DESC(lpfc_debugfs_max_slow_ring_trc, "Set debugfs slow ring trace depth"); -int lpfc_debugfs_mask_disc_trc; +static int lpfc_debugfs_mask_disc_trc; module_param(lpfc_debugfs_mask_disc_trc, int, 0); MODULE_PARM_DESC(lpfc_debugfs_mask_disc_trc, "Set debugfs discovery trace mask"); @@ -127,7 +127,7 @@ static atomic_t lpfc_debugfs_seq_trc_cnt = ATOMIC_INIT(0); static unsigned long lpfc_debugfs_start_time = 0L; /** - * lpfc_debugfs_disc_trc_data - Dump discovery logging to a buffer. + * lpfc_debugfs_disc_trc_data - Dump discovery logging to a buffer * @vport: The vport to gather the log info from. * @buf: The buffer to dump log into. * @size: The maximum amount of data to process. @@ -187,7 +187,7 @@ lpfc_debugfs_disc_trc_data(struct lpfc_vport *vport, char *buf, int size) } /** - * lpfc_debugfs_slow_ring_trc_data - Dump slow ring logging to a buffer. + * lpfc_debugfs_slow_ring_trc_data - Dump slow ring logging to a buffer * @phba: The HBA to gather the log info from. * @buf: The buffer to dump log into. * @size: The maximum amount of data to process. @@ -250,7 +250,7 @@ lpfc_debugfs_slow_ring_trc_data(struct lpfc_hba *phba, char *buf, int size) static int lpfc_debugfs_last_hbq = -1; /** - * lpfc_debugfs_hbqinfo_data - Dump host buffer queue info to a buffer. + * lpfc_debugfs_hbqinfo_data - Dump host buffer queue info to a buffer * @phba: The HBA to gather host buffer info from. * @buf: The buffer to dump log into. * @size: The maximum amount of data to process. @@ -369,7 +369,7 @@ skipit: static int lpfc_debugfs_last_hba_slim_off; /** - * lpfc_debugfs_dumpHBASlim_data - Dump HBA SLIM info to a buffer. + * lpfc_debugfs_dumpHBASlim_data - Dump HBA SLIM info to a buffer * @phba: The HBA to gather SLIM info from. * @buf: The buffer to dump log into. * @size: The maximum amount of data to process. @@ -399,8 +399,7 @@ lpfc_debugfs_dumpHBASlim_data(struct lpfc_hba *phba, char *buf, int size) len += snprintf(buf+len, size-len, "HBA SLIM\n"); lpfc_memcpy_from_slim(buffer, - ((uint8_t *)phba->MBslimaddr) + lpfc_debugfs_last_hba_slim_off, - 1024); + phba->MBslimaddr + lpfc_debugfs_last_hba_slim_off, 1024); ptr = (uint32_t *)&buffer[0]; off = lpfc_debugfs_last_hba_slim_off; @@ -426,7 +425,7 @@ lpfc_debugfs_dumpHBASlim_data(struct lpfc_hba *phba, char *buf, int size) } /** - * lpfc_debugfs_dumpHostSlim_data - Dump host SLIM info to a buffer. + * lpfc_debugfs_dumpHostSlim_data - Dump host SLIM info to a buffer * @phba: The HBA to gather Host SLIM info from. * @buf: The buffer to dump log into. * @size: The maximum amount of data to process. @@ -501,7 +500,7 @@ lpfc_debugfs_dumpHostSlim_data(struct lpfc_hba *phba, char *buf, int size) } /** - * lpfc_debugfs_nodelist_data - Dump target node list to a buffer. + * lpfc_debugfs_nodelist_data - Dump target node list to a buffer * @vport: The vport to gather target node info from. * @buf: The buffer to dump log into. * @size: The maximum amount of data to process. @@ -599,7 +598,7 @@ lpfc_debugfs_nodelist_data(struct lpfc_vport *vport, char *buf, int size) #endif /** - * lpfc_debugfs_disc_trc - Store discovery trace log. + * lpfc_debugfs_disc_trc - Store discovery trace log * @vport: The vport to associate this trace string with for retrieval. * @mask: Log entry classification. * @fmt: Format string to be displayed when dumping the log. @@ -643,7 +642,7 @@ lpfc_debugfs_disc_trc(struct lpfc_vport *vport, int mask, char *fmt, } /** - * lpfc_debugfs_slow_ring_trc - Store slow ring trace log. + * lpfc_debugfs_slow_ring_trc - Store slow ring trace log * @phba: The phba to associate this trace string with for retrieval. * @fmt: Format string to be displayed when dumping the log. * @data1: 1st data parameter to be applied to @fmt. @@ -682,7 +681,7 @@ lpfc_debugfs_slow_ring_trc(struct lpfc_hba *phba, char *fmt, #ifdef CONFIG_SCSI_LPFC_DEBUG_FS /** - * lpfc_debugfs_disc_trc_open - Open the discovery trace log. + * lpfc_debugfs_disc_trc_open - Open the discovery trace log * @inode: The inode pointer that contains a vport pointer. * @file: The file pointer to attach the log output. * @@ -732,7 +731,7 @@ out: } /** - * lpfc_debugfs_slow_ring_trc_open - Open the Slow Ring trace log. + * lpfc_debugfs_slow_ring_trc_open - Open the Slow Ring trace log * @inode: The inode pointer that contains a vport pointer. * @file: The file pointer to attach the log output. * @@ -782,7 +781,7 @@ out: } /** - * lpfc_debugfs_hbqinfo_open - Open the hbqinfo debugfs buffer. + * lpfc_debugfs_hbqinfo_open - Open the hbqinfo debugfs buffer * @inode: The inode pointer that contains a vport pointer. * @file: The file pointer to attach the log output. * @@ -824,7 +823,7 @@ out: } /** - * lpfc_debugfs_dumpHBASlim_open - Open the Dump HBA SLIM debugfs buffer. + * lpfc_debugfs_dumpHBASlim_open - Open the Dump HBA SLIM debugfs buffer * @inode: The inode pointer that contains a vport pointer. * @file: The file pointer to attach the log output. * @@ -866,7 +865,7 @@ out: } /** - * lpfc_debugfs_dumpHostSlim_open - Open the Dump Host SLIM debugfs buffer. + * lpfc_debugfs_dumpHostSlim_open - Open the Dump Host SLIM debugfs buffer * @inode: The inode pointer that contains a vport pointer. * @file: The file pointer to attach the log output. * @@ -993,7 +992,7 @@ lpfc_debugfs_dumpDataDif_write(struct file *file, const char __user *buf, /** - * lpfc_debugfs_nodelist_open - Open the nodelist debugfs file. + * lpfc_debugfs_nodelist_open - Open the nodelist debugfs file * @inode: The inode pointer that contains a vport pointer. * @file: The file pointer to attach the log output. * @@ -1035,7 +1034,7 @@ out: } /** - * lpfc_debugfs_lseek - Seek through a debugfs file. + * lpfc_debugfs_lseek - Seek through a debugfs file * @file: The file pointer to seek through. * @off: The offset to seek to or the amount to seek by. * @whence: Indicates how to seek. @@ -1073,7 +1072,7 @@ lpfc_debugfs_lseek(struct file *file, loff_t off, int whence) } /** - * lpfc_debugfs_read - Read a debugfs file. + * lpfc_debugfs_read - Read a debugfs file * @file: The file pointer to read from. * @buf: The buffer to copy the data to. * @nbytes: The number of bytes to read. @@ -1098,7 +1097,7 @@ lpfc_debugfs_read(struct file *file, char __user *buf, } /** - * lpfc_debugfs_release - Release the buffer used to store debugfs file data. + * lpfc_debugfs_release - Release the buffer used to store debugfs file data * @inode: The inode pointer that contains a vport pointer. (unused) * @file: The file pointer that contains the buffer to release. * @@ -1210,7 +1209,7 @@ static atomic_t lpfc_debugfs_hba_count; #endif /** - * lpfc_debugfs_initialize - Initialize debugfs for a vport. + * lpfc_debugfs_initialize - Initialize debugfs for a vport * @vport: The vport pointer to initialize. * * Description: @@ -1434,7 +1433,7 @@ debug_failed: } /** - * lpfc_debugfs_terminate - Tear down debugfs infrastructure for this vport. + * lpfc_debugfs_terminate - Tear down debugfs infrastructure for this vport * @vport: The vport pointer to remove from debugfs. * * Description: diff --git a/drivers/scsi/lpfc/lpfc_disc.h b/drivers/scsi/lpfc/lpfc_disc.h index f29e548a90d..ffd10897207 100644 --- a/drivers/scsi/lpfc/lpfc_disc.h +++ b/drivers/scsi/lpfc/lpfc_disc.h @@ -99,6 +99,7 @@ struct lpfc_nodelist { #define NLP_USG_FREE_ACK_BIT 0x8 /* Indicate ndlp memory free invoked */ struct timer_list nlp_delayfunc; /* Used for delayed ELS cmds */ + struct lpfc_hba *phba; struct fc_rport *rport; /* Corresponding FC transport port structure */ struct lpfc_vport *vport; diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index a7302480bc4..b8b34cf5c3d 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -55,7 +55,7 @@ static void lpfc_register_new_vport(struct lpfc_hba *phba, static int lpfc_max_els_tries = 3; /** - * lpfc_els_chk_latt: Check host link attention event for a vport. + * lpfc_els_chk_latt - Check host link attention event for a vport * @vport: pointer to a host virtual N_Port data structure. * * This routine checks whether there is an outstanding host link @@ -116,7 +116,7 @@ lpfc_els_chk_latt(struct lpfc_vport *vport) } /** - * lpfc_prep_els_iocb: Allocate and prepare a lpfc iocb data structure. + * lpfc_prep_els_iocb - Allocate and prepare a lpfc iocb data structure * @vport: pointer to a host virtual N_Port data structure. * @expectRsp: flag indicating whether response is expected. * @cmdSize: size of the ELS command. @@ -290,7 +290,7 @@ els_iocb_free_pcmb_exit: } /** - * lpfc_issue_fabric_reglogin: Issue fabric registration login for a vport. + * lpfc_issue_fabric_reglogin - Issue fabric registration login for a vport * @vport: pointer to a host virtual N_Port data structure. * * This routine issues a fabric registration login for a @vport. An @@ -386,7 +386,7 @@ fail: } /** - * lpfc_cmpl_els_flogi_fabric: Completion function for flogi to a fabric port. + * lpfc_cmpl_els_flogi_fabric - Completion function for flogi to a fabric port * @vport: pointer to a host virtual N_Port data structure. * @ndlp: pointer to a node-list data structure. * @sp: pointer to service parameter data structure. @@ -509,7 +509,7 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, } /** - * lpfc_cmpl_els_flogi_nport: Completion function for flogi to an N_Port. + * lpfc_cmpl_els_flogi_nport - Completion function for flogi to an N_Port * @vport: pointer to a host virtual N_Port data structure. * @ndlp: pointer to a node-list data structure. * @sp: pointer to service parameter data structure. @@ -626,7 +626,7 @@ fail: } /** - * lpfc_cmpl_els_flogi: Completion callback function for flogi. + * lpfc_cmpl_els_flogi - Completion callback function for flogi * @phba: pointer to lpfc hba data structure. * @cmdiocb: pointer to lpfc command iocb data structure. * @rspiocb: pointer to lpfc response iocb data structure. @@ -751,7 +751,7 @@ out: } /** - * lpfc_issue_els_flogi: Issue an flogi iocb command for a vport. + * lpfc_issue_els_flogi - Issue an flogi iocb command for a vport * @vport: pointer to a host virtual N_Port data structure. * @ndlp: pointer to a node-list data structure. * @retry: number of retries to the command IOCB. @@ -849,7 +849,7 @@ lpfc_issue_els_flogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, } /** - * lpfc_els_abort_flogi: Abort all outstanding flogi iocbs. + * lpfc_els_abort_flogi - Abort all outstanding flogi iocbs * @phba: pointer to lpfc hba data structure. * * This routine aborts all the outstanding Fabric Login (FLOGI) IOCBs @@ -898,7 +898,7 @@ lpfc_els_abort_flogi(struct lpfc_hba *phba) } /** - * lpfc_initial_flogi: Issue an initial fabric login for a vport. + * lpfc_initial_flogi - Issue an initial fabric login for a vport * @vport: pointer to a host virtual N_Port data structure. * * This routine issues an initial Fabric Login (FLOGI) for the @vport @@ -949,7 +949,7 @@ lpfc_initial_flogi(struct lpfc_vport *vport) } /** - * lpfc_initial_fdisc: Issue an initial fabric discovery for a vport. + * lpfc_initial_fdisc - Issue an initial fabric discovery for a vport * @vport: pointer to a host virtual N_Port data structure. * * This routine issues an initial Fabric Discover (FDISC) for the @vport @@ -998,7 +998,7 @@ lpfc_initial_fdisc(struct lpfc_vport *vport) } /** - * lpfc_more_plogi: Check and issue remaining plogis for a vport. + * lpfc_more_plogi - Check and issue remaining plogis for a vport * @vport: pointer to a host virtual N_Port data structure. * * This routine checks whether there are more remaining Port Logins @@ -1031,7 +1031,7 @@ lpfc_more_plogi(struct lpfc_vport *vport) } /** - * lpfc_plogi_confirm_nport: Confirm pologi wwpn matches stored ndlp. + * lpfc_plogi_confirm_nport - Confirm pologi wwpn matches stored ndlp * @phba: pointer to lpfc hba data structure. * @prsp: pointer to response IOCB payload. * @ndlp: pointer to a node-list data structure. @@ -1165,7 +1165,7 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp, } /** - * lpfc_end_rscn: Check and handle more rscn for a vport. + * lpfc_end_rscn - Check and handle more rscn for a vport * @vport: pointer to a host virtual N_Port data structure. * * This routine checks whether more Registration State Change @@ -1197,7 +1197,7 @@ lpfc_end_rscn(struct lpfc_vport *vport) } /** - * lpfc_cmpl_els_plogi: Completion callback function for plogi. + * lpfc_cmpl_els_plogi - Completion callback function for plogi * @phba: pointer to lpfc hba data structure. * @cmdiocb: pointer to lpfc command iocb data structure. * @rspiocb: pointer to lpfc response iocb data structure. @@ -1322,7 +1322,7 @@ out: } /** - * lpfc_issue_els_plogi: Issue an plogi iocb command for a vport. + * lpfc_issue_els_plogi - Issue an plogi iocb command for a vport * @vport: pointer to a host virtual N_Port data structure. * @did: destination port identifier. * @retry: number of retries to the command IOCB. @@ -1401,7 +1401,7 @@ lpfc_issue_els_plogi(struct lpfc_vport *vport, uint32_t did, uint8_t retry) } /** - * lpfc_cmpl_els_prli: Completion callback function for prli. + * lpfc_cmpl_els_prli - Completion callback function for prli * @phba: pointer to lpfc hba data structure. * @cmdiocb: pointer to lpfc command iocb data structure. * @rspiocb: pointer to lpfc response iocb data structure. @@ -1472,7 +1472,7 @@ out: } /** - * lpfc_issue_els_prli: Issue a prli iocb command for a vport. + * lpfc_issue_els_prli - Issue a prli iocb command for a vport * @vport: pointer to a host virtual N_Port data structure. * @ndlp: pointer to a node-list data structure. * @retry: number of retries to the command IOCB. @@ -1562,7 +1562,7 @@ lpfc_issue_els_prli(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, } /** - * lpfc_rscn_disc: Perform rscn discovery for a vport. + * lpfc_rscn_disc - Perform rscn discovery for a vport * @vport: pointer to a host virtual N_Port data structure. * * This routine performs Registration State Change Notification (RSCN) @@ -1588,7 +1588,7 @@ lpfc_rscn_disc(struct lpfc_vport *vport) } /** - * lpfc_adisc_done: Complete the adisc phase of discovery. + * lpfc_adisc_done - Complete the adisc phase of discovery * @vport: pointer to lpfc_vport hba data structure that finished all ADISCs. * * This function is called when the final ADISC is completed during discovery. @@ -1639,7 +1639,7 @@ lpfc_adisc_done(struct lpfc_vport *vport) } /** - * lpfc_more_adisc: Issue more adisc as needed. + * lpfc_more_adisc - Issue more adisc as needed * @vport: pointer to a host virtual N_Port data structure. * * This routine determines whether there are more ndlps on a @vport @@ -1672,7 +1672,7 @@ lpfc_more_adisc(struct lpfc_vport *vport) } /** - * lpfc_cmpl_els_adisc: Completion callback function for adisc. + * lpfc_cmpl_els_adisc - Completion callback function for adisc * @phba: pointer to lpfc hba data structure. * @cmdiocb: pointer to lpfc command iocb data structure. * @rspiocb: pointer to lpfc response iocb data structure. @@ -1760,7 +1760,7 @@ out: } /** - * lpfc_issue_els_adisc: Issue an address discover iocb to an node on a vport. + * lpfc_issue_els_adisc - Issue an address discover iocb to an node on a vport * @vport: pointer to a virtual N_Port data structure. * @ndlp: pointer to a node-list data structure. * @retry: number of retries to the command IOCB. @@ -1833,7 +1833,7 @@ lpfc_issue_els_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, } /** - * lpfc_cmpl_els_logo: Completion callback function for logo. + * lpfc_cmpl_els_logo - Completion callback function for logo * @phba: pointer to lpfc hba data structure. * @cmdiocb: pointer to lpfc command iocb data structure. * @rspiocb: pointer to lpfc response iocb data structure. @@ -1910,7 +1910,7 @@ out: } /** - * lpfc_issue_els_logo: Issue a logo to an node on a vport. + * lpfc_issue_els_logo - Issue a logo to an node on a vport * @vport: pointer to a virtual N_Port data structure. * @ndlp: pointer to a node-list data structure. * @retry: number of retries to the command IOCB. @@ -1991,7 +1991,7 @@ lpfc_issue_els_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, } /** - * lpfc_cmpl_els_cmd: Completion callback function for generic els command. + * lpfc_cmpl_els_cmd - Completion callback function for generic els command * @phba: pointer to lpfc hba data structure. * @cmdiocb: pointer to lpfc command iocb data structure. * @rspiocb: pointer to lpfc response iocb data structure. @@ -2031,7 +2031,7 @@ lpfc_cmpl_els_cmd(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, } /** - * lpfc_issue_els_scr: Issue a scr to an node on a vport. + * lpfc_issue_els_scr - Issue a scr to an node on a vport * @vport: pointer to a host virtual N_Port data structure. * @nportid: N_Port identifier to the remote node. * @retry: number of retries to the command IOCB. @@ -2125,7 +2125,7 @@ lpfc_issue_els_scr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry) } /** - * lpfc_issue_els_farpr: Issue a farp to an node on a vport. + * lpfc_issue_els_farpr - Issue a farp to an node on a vport * @vport: pointer to a host virtual N_Port data structure. * @nportid: N_Port identifier to the remote node. * @retry: number of retries to the command IOCB. @@ -2236,7 +2236,7 @@ lpfc_issue_els_farpr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry) } /** - * lpfc_cancel_retry_delay_tmo: Cancel the timer with delayed iocb-cmd retry. + * lpfc_cancel_retry_delay_tmo - Cancel the timer with delayed iocb-cmd retry * @vport: pointer to a host virtual N_Port data structure. * @nlp: pointer to a node-list data structure. * @@ -2291,7 +2291,7 @@ lpfc_cancel_retry_delay_tmo(struct lpfc_vport *vport, struct lpfc_nodelist *nlp) } /** - * lpfc_els_retry_delay: Timer function with a ndlp delayed function timer. + * lpfc_els_retry_delay - Timer function with a ndlp delayed function timer * @ptr: holder for the pointer to the timer function associated data (ndlp). * * This routine is invoked by the ndlp delayed-function timer to check @@ -2333,7 +2333,7 @@ lpfc_els_retry_delay(unsigned long ptr) } /** - * lpfc_els_retry_delay_handler: Work thread handler for ndlp delayed function. + * lpfc_els_retry_delay_handler - Work thread handler for ndlp delayed function * @ndlp: pointer to a node-list data structure. * * This routine is the worker-thread handler for processing the @ndlp delayed @@ -2404,7 +2404,7 @@ lpfc_els_retry_delay_handler(struct lpfc_nodelist *ndlp) } /** - * lpfc_els_retry: Make retry decision on an els command iocb. + * lpfc_els_retry - Make retry decision on an els command iocb * @phba: pointer to lpfc hba data structure. * @cmdiocb: pointer to lpfc command iocb data structure. * @rspiocb: pointer to lpfc response iocb data structure. @@ -2732,7 +2732,7 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, } /** - * lpfc_els_free_data: Free lpfc dma buffer and data structure with an iocb. + * lpfc_els_free_data - Free lpfc dma buffer and data structure with an iocb * @phba: pointer to lpfc hba data structure. * @buf_ptr1: pointer to the lpfc DMA buffer data structure. * @@ -2764,7 +2764,7 @@ lpfc_els_free_data(struct lpfc_hba *phba, struct lpfc_dmabuf *buf_ptr1) } /** - * lpfc_els_free_bpl: Free lpfc dma buffer and data structure with bpl. + * lpfc_els_free_bpl - Free lpfc dma buffer and data structure with bpl * @phba: pointer to lpfc hba data structure. * @buf_ptr: pointer to the lpfc dma buffer data structure. * @@ -2784,7 +2784,7 @@ lpfc_els_free_bpl(struct lpfc_hba *phba, struct lpfc_dmabuf *buf_ptr) } /** - * lpfc_els_free_iocb: Free a command iocb and its associated resources. + * lpfc_els_free_iocb - Free a command iocb and its associated resources * @phba: pointer to lpfc hba data structure. * @elsiocb: pointer to lpfc els command iocb data structure. * @@ -2877,7 +2877,7 @@ lpfc_els_free_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *elsiocb) } /** - * lpfc_cmpl_els_logo_acc: Completion callback function to logo acc response. + * lpfc_cmpl_els_logo_acc - Completion callback function to logo acc response * @phba: pointer to lpfc hba data structure. * @cmdiocb: pointer to lpfc command iocb data structure. * @rspiocb: pointer to lpfc response iocb data structure. @@ -2931,7 +2931,7 @@ lpfc_cmpl_els_logo_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, } /** - * lpfc_mbx_cmpl_dflt_rpi: Completion callbk func for unreg dflt rpi mbox cmd. + * lpfc_mbx_cmpl_dflt_rpi - Completion callbk func for unreg dflt rpi mbox cmd * @phba: pointer to lpfc hba data structure. * @pmb: pointer to the driver internal queue element for mailbox command. * @@ -2965,7 +2965,7 @@ lpfc_mbx_cmpl_dflt_rpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) } /** - * lpfc_cmpl_els_rsp: Completion callback function for els response iocb cmd. + * lpfc_cmpl_els_rsp - Completion callback function for els response iocb cmd * @phba: pointer to lpfc hba data structure. * @cmdiocb: pointer to lpfc command iocb data structure. * @rspiocb: pointer to lpfc response iocb data structure. @@ -3136,7 +3136,7 @@ out: } /** - * lpfc_els_rsp_acc: Prepare and issue an acc response iocb command. + * lpfc_els_rsp_acc - Prepare and issue an acc response iocb command * @vport: pointer to a host virtual N_Port data structure. * @flag: the els command code to be accepted. * @oldiocb: pointer to the original lpfc command iocb data structure. @@ -3275,7 +3275,7 @@ lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag, } /** - * lpfc_els_rsp_reject: Propare and issue a rjt response iocb command. + * lpfc_els_rsp_reject - Propare and issue a rjt response iocb command * @vport: pointer to a virtual N_Port data structure. * @rejectError: * @oldiocb: pointer to the original lpfc command iocb data structure. @@ -3356,7 +3356,7 @@ lpfc_els_rsp_reject(struct lpfc_vport *vport, uint32_t rejectError, } /** - * lpfc_els_rsp_adisc_acc: Prepare and issue acc response to adisc iocb cmd. + * lpfc_els_rsp_adisc_acc - Prepare and issue acc response to adisc iocb cmd * @vport: pointer to a virtual N_Port data structure. * @oldiocb: pointer to the original lpfc command iocb data structure. * @ndlp: pointer to a node-list data structure. @@ -3431,7 +3431,7 @@ lpfc_els_rsp_adisc_acc(struct lpfc_vport *vport, struct lpfc_iocbq *oldiocb, } /** - * lpfc_els_rsp_prli_acc: Prepare and issue acc response to prli iocb cmd. + * lpfc_els_rsp_prli_acc - Prepare and issue acc response to prli iocb cmd * @vport: pointer to a virtual N_Port data structure. * @oldiocb: pointer to the original lpfc command iocb data structure. * @ndlp: pointer to a node-list data structure. @@ -3529,7 +3529,7 @@ lpfc_els_rsp_prli_acc(struct lpfc_vport *vport, struct lpfc_iocbq *oldiocb, } /** - * lpfc_els_rsp_rnid_acc: Issue rnid acc response iocb command. + * lpfc_els_rsp_rnid_acc - Issue rnid acc response iocb command * @vport: pointer to a virtual N_Port data structure. * @format: rnid command format. * @oldiocb: pointer to the original lpfc command iocb data structure. @@ -3635,7 +3635,7 @@ lpfc_els_rsp_rnid_acc(struct lpfc_vport *vport, uint8_t format, } /** - * lpfc_els_disc_adisc: Issue remaining adisc iocbs to npr nodes of a vport. + * lpfc_els_disc_adisc - Issue remaining adisc iocbs to npr nodes of a vport * @vport: pointer to a host virtual N_Port data structure. * * This routine issues Address Discover (ADISC) ELS commands to those @@ -3693,7 +3693,7 @@ lpfc_els_disc_adisc(struct lpfc_vport *vport) } /** - * lpfc_els_disc_plogi: Issue plogi for all npr nodes of a vport before adisc. + * lpfc_els_disc_plogi - Issue plogi for all npr nodes of a vport before adisc * @vport: pointer to a host virtual N_Port data structure. * * This routine issues Port Login (PLOGI) ELS commands to all the N_Ports @@ -3752,7 +3752,7 @@ lpfc_els_disc_plogi(struct lpfc_vport *vport) } /** - * lpfc_els_flush_rscn: Clean up any rscn activities with a vport. + * lpfc_els_flush_rscn - Clean up any rscn activities with a vport * @vport: pointer to a host virtual N_Port data structure. * * This routine cleans up any Registration State Change Notification @@ -3791,7 +3791,7 @@ lpfc_els_flush_rscn(struct lpfc_vport *vport) } /** - * lpfc_rscn_payload_check: Check whether there is a pending rscn to a did. + * lpfc_rscn_payload_check - Check whether there is a pending rscn to a did * @vport: pointer to a host virtual N_Port data structure. * @did: remote destination port identifier. * @@ -3866,7 +3866,7 @@ return_did_out: } /** - * lpfc_rscn_recovery_check: Send recovery event to vport nodes matching rscn + * lpfc_rscn_recovery_check - Send recovery event to vport nodes matching rscn * @vport: pointer to a host virtual N_Port data structure. * * This routine sends recovery (NLP_EVT_DEVICE_RECOVERY) event to the @@ -3895,7 +3895,7 @@ lpfc_rscn_recovery_check(struct lpfc_vport *vport) } /** - * lpfc_send_rscn_event: Send an RSCN event to management application. + * lpfc_send_rscn_event - Send an RSCN event to management application * @vport: pointer to a host virtual N_Port data structure. * @cmdiocb: pointer to lpfc command iocb data structure. * @@ -3938,7 +3938,7 @@ lpfc_send_rscn_event(struct lpfc_vport *vport, } /** - * lpfc_els_rcv_rscn: Process an unsolicited rscn iocb. + * lpfc_els_rcv_rscn - Process an unsolicited rscn iocb * @vport: pointer to a host virtual N_Port data structure. * @cmdiocb: pointer to lpfc command iocb data structure. * @ndlp: pointer to a node-list data structure. @@ -4134,7 +4134,7 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, } /** - * lpfc_els_handle_rscn: Handle rscn for a vport. + * lpfc_els_handle_rscn - Handle rscn for a vport * @vport: pointer to a host virtual N_Port data structure. * * This routine handles the Registration State Configuration Notification @@ -4222,7 +4222,7 @@ lpfc_els_handle_rscn(struct lpfc_vport *vport) } /** - * lpfc_els_rcv_flogi: Process an unsolicited flogi iocb. + * lpfc_els_rcv_flogi - Process an unsolicited flogi iocb * @vport: pointer to a host virtual N_Port data structure. * @cmdiocb: pointer to lpfc command iocb data structure. * @ndlp: pointer to a node-list data structure. @@ -4336,7 +4336,7 @@ lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, } /** - * lpfc_els_rcv_rnid: Process an unsolicited rnid iocb. + * lpfc_els_rcv_rnid - Process an unsolicited rnid iocb * @vport: pointer to a host virtual N_Port data structure. * @cmdiocb: pointer to lpfc command iocb data structure. * @ndlp: pointer to a node-list data structure. @@ -4391,7 +4391,7 @@ lpfc_els_rcv_rnid(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, } /** - * lpfc_els_rcv_lirr: Process an unsolicited lirr iocb. + * lpfc_els_rcv_lirr - Process an unsolicited lirr iocb * @vport: pointer to a host virtual N_Port data structure. * @cmdiocb: pointer to lpfc command iocb data structure. * @ndlp: pointer to a node-list data structure. @@ -4419,7 +4419,7 @@ lpfc_els_rcv_lirr(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, } /** - * lpfc_els_rsp_rps_acc: Completion callbk func for MBX_READ_LNK_STAT mbox cmd. + * lpfc_els_rsp_rps_acc - Completion callbk func for MBX_READ_LNK_STAT mbox cmd * @phba: pointer to lpfc hba data structure. * @pmb: pointer to the driver internal queue element for mailbox command. * @@ -4513,7 +4513,7 @@ lpfc_els_rsp_rps_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) } /** - * lpfc_els_rcv_rps: Process an unsolicited rps iocb. + * lpfc_els_rcv_rps - Process an unsolicited rps iocb * @vport: pointer to a host virtual N_Port data structure. * @cmdiocb: pointer to lpfc command iocb data structure. * @ndlp: pointer to a node-list data structure. @@ -4590,7 +4590,7 @@ reject_out: } /** - * lpfc_els_rsp_rpl_acc: Issue an accept rpl els command. + * lpfc_els_rsp_rpl_acc - Issue an accept rpl els command * @vport: pointer to a host virtual N_Port data structure. * @cmdsize: size of the ELS command. * @oldiocb: pointer to the original lpfc command iocb data structure. @@ -4662,7 +4662,7 @@ lpfc_els_rsp_rpl_acc(struct lpfc_vport *vport, uint16_t cmdsize, } /** - * lpfc_els_rcv_rpl: Process an unsolicited rpl iocb. + * lpfc_els_rcv_rpl - Process an unsolicited rpl iocb * @vport: pointer to a host virtual N_Port data structure. * @cmdiocb: pointer to lpfc command iocb data structure. * @ndlp: pointer to a node-list data structure. @@ -4721,7 +4721,7 @@ lpfc_els_rcv_rpl(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, } /** - * lpfc_els_rcv_farp: Process an unsolicited farp request els command. + * lpfc_els_rcv_farp - Process an unsolicited farp request els command * @vport: pointer to a virtual N_Port data structure. * @cmdiocb: pointer to lpfc command iocb data structure. * @ndlp: pointer to a node-list data structure. @@ -4804,7 +4804,7 @@ lpfc_els_rcv_farp(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, } /** - * lpfc_els_rcv_farpr: Process an unsolicited farp response iocb. + * lpfc_els_rcv_farpr - Process an unsolicited farp response iocb * @vport: pointer to a host virtual N_Port data structure. * @cmdiocb: pointer to lpfc command iocb data structure. * @ndlp: pointer to a node-list data structure. @@ -4842,7 +4842,7 @@ lpfc_els_rcv_farpr(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, } /** - * lpfc_els_rcv_fan: Process an unsolicited fan iocb command. + * lpfc_els_rcv_fan - Process an unsolicited fan iocb command * @vport: pointer to a host virtual N_Port data structure. * @cmdiocb: pointer to lpfc command iocb data structure. * @fan_ndlp: pointer to a node-list data structure. @@ -4890,7 +4890,7 @@ lpfc_els_rcv_fan(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, } /** - * lpfc_els_timeout: Handler funciton to the els timer. + * lpfc_els_timeout - Handler funciton to the els timer * @ptr: holder for the timer function associated data. * * This routine is invoked by the ELS timer after timeout. It posts the ELS @@ -4919,7 +4919,7 @@ lpfc_els_timeout(unsigned long ptr) } /** - * lpfc_els_timeout_handler: Process an els timeout event. + * lpfc_els_timeout_handler - Process an els timeout event * @vport: pointer to a virtual N_Port data structure. * * This routine is the actual handler function that processes an ELS timeout @@ -4994,7 +4994,7 @@ lpfc_els_timeout_handler(struct lpfc_vport *vport) } /** - * lpfc_els_flush_cmd: Clean up the outstanding els commands to a vport. + * lpfc_els_flush_cmd - Clean up the outstanding els commands to a vport * @vport: pointer to a host virtual N_Port data structure. * * This routine is used to clean up all the outstanding ELS commands on a @@ -5058,25 +5058,15 @@ lpfc_els_flush_cmd(struct lpfc_vport *vport) } spin_unlock_irq(&phba->hbalock); - while (!list_empty(&completions)) { - piocb = list_get_first(&completions, struct lpfc_iocbq, list); - cmd = &piocb->iocb; - list_del_init(&piocb->list); - - if (!piocb->iocb_cmpl) - lpfc_sli_release_iocbq(phba, piocb); - else { - cmd->ulpStatus = IOSTAT_LOCAL_REJECT; - cmd->un.ulpWord[4] = IOERR_SLI_ABORTED; - (piocb->iocb_cmpl) (phba, piocb, piocb); - } - } + /* Cancell all the IOCBs from the completions list */ + lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT, + IOERR_SLI_ABORTED); return; } /** - * lpfc_els_flush_all_cmd: Clean up all the outstanding els commands to a HBA. + * lpfc_els_flush_all_cmd - Clean up all the outstanding els commands to a HBA * @phba: pointer to lpfc hba data structure. * * This routine is used to clean up all the outstanding ELS commands on a @@ -5121,23 +5111,16 @@ lpfc_els_flush_all_cmd(struct lpfc_hba *phba) lpfc_sli_issue_abort_iotag(phba, pring, piocb); } spin_unlock_irq(&phba->hbalock); - while (!list_empty(&completions)) { - piocb = list_get_first(&completions, struct lpfc_iocbq, list); - cmd = &piocb->iocb; - list_del_init(&piocb->list); - if (!piocb->iocb_cmpl) - lpfc_sli_release_iocbq(phba, piocb); - else { - cmd->ulpStatus = IOSTAT_LOCAL_REJECT; - cmd->un.ulpWord[4] = IOERR_SLI_ABORTED; - (piocb->iocb_cmpl) (phba, piocb, piocb); - } - } + + /* Cancel all the IOCBs from the completions list */ + lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT, + IOERR_SLI_ABORTED); + return; } /** - * lpfc_send_els_failure_event: Posts an ELS command failure event. + * lpfc_send_els_failure_event - Posts an ELS command failure event * @phba: Pointer to hba context object. * @cmdiocbp: Pointer to command iocb which reported error. * @rspiocbp: Pointer to response iocb which reported error. @@ -5204,7 +5187,7 @@ lpfc_send_els_failure_event(struct lpfc_hba *phba, } /** - * lpfc_send_els_event: Posts unsolicited els event. + * lpfc_send_els_event - Posts unsolicited els event * @vport: Pointer to vport object. * @ndlp: Pointer FC node object. * @cmd: ELS command code. @@ -5284,7 +5267,7 @@ lpfc_send_els_event(struct lpfc_vport *vport, /** - * lpfc_els_unsol_buffer: Process an unsolicited event data buffer. + * lpfc_els_unsol_buffer - Process an unsolicited event data buffer * @phba: pointer to lpfc hba data structure. * @pring: pointer to a SLI ring. * @vport: pointer to a host virtual N_Port data structure. @@ -5592,7 +5575,7 @@ dropit: } /** - * lpfc_find_vport_by_vpid: Find a vport on a HBA through vport identifier. + * lpfc_find_vport_by_vpid - Find a vport on a HBA through vport identifier * @phba: pointer to lpfc hba data structure. * @vpi: host virtual N_Port identifier. * @@ -5622,7 +5605,7 @@ lpfc_find_vport_by_vpid(struct lpfc_hba *phba, uint16_t vpi) } /** - * lpfc_els_unsol_event: Process an unsolicited event from an els sli ring. + * lpfc_els_unsol_event - Process an unsolicited event from an els sli ring * @phba: pointer to lpfc hba data structure. * @pring: pointer to a SLI ring. * @elsiocb: pointer to lpfc els iocb data structure. @@ -5710,7 +5693,7 @@ lpfc_els_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, } /** - * lpfc_do_scr_ns_plogi: Issue a plogi to the name server for scr. + * lpfc_do_scr_ns_plogi - Issue a plogi to the name server for scr * @phba: pointer to lpfc hba data structure. * @vport: pointer to a virtual N_Port data structure. * @@ -5781,7 +5764,7 @@ lpfc_do_scr_ns_plogi(struct lpfc_hba *phba, struct lpfc_vport *vport) } /** - * lpfc_cmpl_reg_new_vport: Completion callback function to register new vport. + * lpfc_cmpl_reg_new_vport - Completion callback function to register new vport * @phba: pointer to lpfc hba data structure. * @pmb: pointer to the driver internal queue element for mailbox command. * @@ -5850,7 +5833,7 @@ lpfc_cmpl_reg_new_vport(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) } /** - * lpfc_register_new_vport: Register a new vport with a HBA. + * lpfc_register_new_vport - Register a new vport with a HBA * @phba: pointer to lpfc hba data structure. * @vport: pointer to a host virtual N_Port data structure. * @ndlp: pointer to a node-list data structure. @@ -5899,7 +5882,7 @@ mbox_err_exit: } /** - * lpfc_cmpl_els_fdisc: Completion function for fdisc iocb command. + * lpfc_cmpl_els_fdisc - Completion function for fdisc iocb command * @phba: pointer to lpfc hba data structure. * @cmdiocb: pointer to lpfc command iocb data structure. * @rspiocb: pointer to lpfc response iocb data structure. @@ -6007,7 +5990,7 @@ out: } /** - * lpfc_issue_els_fdisc: Issue a fdisc iocb command. + * lpfc_issue_els_fdisc - Issue a fdisc iocb command * @vport: pointer to a virtual N_Port data structure. * @ndlp: pointer to a node-list data structure. * @retry: number of retries to the command IOCB. @@ -6101,7 +6084,7 @@ lpfc_issue_els_fdisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, } /** - * lpfc_cmpl_els_npiv_logo: Completion function with vport logo. + * lpfc_cmpl_els_npiv_logo - Completion function with vport logo * @phba: pointer to lpfc hba data structure. * @cmdiocb: pointer to lpfc command iocb data structure. * @rspiocb: pointer to lpfc response iocb data structure. @@ -6136,7 +6119,7 @@ lpfc_cmpl_els_npiv_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, } /** - * lpfc_issue_els_npiv_logo: Issue a logo off a vport. + * lpfc_issue_els_npiv_logo - Issue a logo off a vport * @vport: pointer to a virtual N_Port data structure. * @ndlp: pointer to a node-list data structure. * @@ -6197,7 +6180,7 @@ lpfc_issue_els_npiv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) } /** - * lpfc_fabric_block_timeout: Handler function to the fabric block timer. + * lpfc_fabric_block_timeout - Handler function to the fabric block timer * @ptr: holder for the timer function associated data. * * This routine is invoked by the fabric iocb block timer after @@ -6226,7 +6209,7 @@ lpfc_fabric_block_timeout(unsigned long ptr) } /** - * lpfc_resume_fabric_iocbs: Issue a fabric iocb from driver internal list. + * lpfc_resume_fabric_iocbs - Issue a fabric iocb from driver internal list * @phba: pointer to lpfc hba data structure. * * This routine issues one fabric iocb from the driver internal list to @@ -6285,7 +6268,7 @@ repeat: } /** - * lpfc_unblock_fabric_iocbs: Unblock issuing fabric iocb command. + * lpfc_unblock_fabric_iocbs - Unblock issuing fabric iocb command * @phba: pointer to lpfc hba data structure. * * This routine unblocks the issuing fabric iocb command. The function @@ -6303,7 +6286,7 @@ lpfc_unblock_fabric_iocbs(struct lpfc_hba *phba) } /** - * lpfc_block_fabric_iocbs: Block issuing fabric iocb command. + * lpfc_block_fabric_iocbs - Block issuing fabric iocb command * @phba: pointer to lpfc hba data structure. * * This routine blocks the issuing fabric iocb for a specified amount of @@ -6325,7 +6308,7 @@ lpfc_block_fabric_iocbs(struct lpfc_hba *phba) } /** - * lpfc_cmpl_fabric_iocb: Completion callback function for fabric iocb. + * lpfc_cmpl_fabric_iocb - Completion callback function for fabric iocb * @phba: pointer to lpfc hba data structure. * @cmdiocb: pointer to lpfc command iocb data structure. * @rspiocb: pointer to lpfc response iocb data structure. @@ -6384,7 +6367,7 @@ lpfc_cmpl_fabric_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, } /** - * lpfc_issue_fabric_iocb: Issue a fabric iocb command. + * lpfc_issue_fabric_iocb - Issue a fabric iocb command * @phba: pointer to lpfc hba data structure. * @iocb: pointer to lpfc command iocb data structure. * @@ -6453,7 +6436,7 @@ lpfc_issue_fabric_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *iocb) } /** - * lpfc_fabric_abort_vport: Abort a vport's iocbs from driver fabric iocb list. + * lpfc_fabric_abort_vport - Abort a vport's iocbs from driver fabric iocb list * @vport: pointer to a virtual N_Port data structure. * * This routine aborts all the IOCBs associated with a @vport from the @@ -6468,7 +6451,6 @@ static void lpfc_fabric_abort_vport(struct lpfc_vport *vport) LIST_HEAD(completions); struct lpfc_hba *phba = vport->phba; struct lpfc_iocbq *tmp_iocb, *piocb; - IOCB_t *cmd; spin_lock_irq(&phba->hbalock); list_for_each_entry_safe(piocb, tmp_iocb, &phba->fabric_iocb_list, @@ -6481,19 +6463,13 @@ static void lpfc_fabric_abort_vport(struct lpfc_vport *vport) } spin_unlock_irq(&phba->hbalock); - while (!list_empty(&completions)) { - piocb = list_get_first(&completions, struct lpfc_iocbq, list); - list_del_init(&piocb->list); - - cmd = &piocb->iocb; - cmd->ulpStatus = IOSTAT_LOCAL_REJECT; - cmd->un.ulpWord[4] = IOERR_SLI_ABORTED; - (piocb->iocb_cmpl) (phba, piocb, piocb); - } + /* Cancel all the IOCBs from the completions list */ + lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT, + IOERR_SLI_ABORTED); } /** - * lpfc_fabric_abort_nport: Abort a ndlp's iocbs from driver fabric iocb list. + * lpfc_fabric_abort_nport - Abort a ndlp's iocbs from driver fabric iocb list * @ndlp: pointer to a node-list data structure. * * This routine aborts all the IOCBs associated with an @ndlp from the @@ -6506,10 +6482,9 @@ static void lpfc_fabric_abort_vport(struct lpfc_vport *vport) void lpfc_fabric_abort_nport(struct lpfc_nodelist *ndlp) { LIST_HEAD(completions); - struct lpfc_hba *phba = ndlp->vport->phba; + struct lpfc_hba *phba = ndlp->phba; struct lpfc_iocbq *tmp_iocb, *piocb; struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING]; - IOCB_t *cmd; spin_lock_irq(&phba->hbalock); list_for_each_entry_safe(piocb, tmp_iocb, &phba->fabric_iocb_list, @@ -6521,19 +6496,13 @@ void lpfc_fabric_abort_nport(struct lpfc_nodelist *ndlp) } spin_unlock_irq(&phba->hbalock); - while (!list_empty(&completions)) { - piocb = list_get_first(&completions, struct lpfc_iocbq, list); - list_del_init(&piocb->list); - - cmd = &piocb->iocb; - cmd->ulpStatus = IOSTAT_LOCAL_REJECT; - cmd->un.ulpWord[4] = IOERR_SLI_ABORTED; - (piocb->iocb_cmpl) (phba, piocb, piocb); - } + /* Cancel all the IOCBs from the completions list */ + lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT, + IOERR_SLI_ABORTED); } /** - * lpfc_fabric_abort_hba: Abort all iocbs on driver fabric iocb list. + * lpfc_fabric_abort_hba - Abort all iocbs on driver fabric iocb list * @phba: pointer to lpfc hba data structure. * * This routine aborts all the IOCBs currently on the driver internal @@ -6546,20 +6515,12 @@ void lpfc_fabric_abort_nport(struct lpfc_nodelist *ndlp) void lpfc_fabric_abort_hba(struct lpfc_hba *phba) { LIST_HEAD(completions); - struct lpfc_iocbq *piocb; - IOCB_t *cmd; spin_lock_irq(&phba->hbalock); list_splice_init(&phba->fabric_iocb_list, &completions); spin_unlock_irq(&phba->hbalock); - while (!list_empty(&completions)) { - piocb = list_get_first(&completions, struct lpfc_iocbq, list); - list_del_init(&piocb->list); - - cmd = &piocb->iocb; - cmd->ulpStatus = IOSTAT_LOCAL_REJECT; - cmd->un.ulpWord[4] = IOERR_SLI_ABORTED; - (piocb->iocb_cmpl) (phba, piocb, piocb); - } + /* Cancel all the IOCBs from the completions list */ + lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT, + IOERR_SLI_ABORTED); } diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 311ed6dea72..e764ce0bf70 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -78,7 +78,7 @@ lpfc_terminate_rport_io(struct fc_rport *rport) return; } - phba = ndlp->vport->phba; + phba = ndlp->phba; lpfc_debugfs_disc_trc(ndlp->vport, LPFC_DISC_TRC_RPORT, "rport terminate: sid:x%x did:x%x flg:x%x", @@ -276,7 +276,7 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) } /** - * lpfc_alloc_fast_evt: Allocates data structure for posting event. + * lpfc_alloc_fast_evt - Allocates data structure for posting event * @phba: Pointer to hba context object. * * This function is called from the functions which need to post @@ -303,7 +303,7 @@ lpfc_alloc_fast_evt(struct lpfc_hba *phba) { } /** - * lpfc_free_fast_evt: Frees event data structure. + * lpfc_free_fast_evt - Frees event data structure * @phba: Pointer to hba context object. * @evt: Event object which need to be freed. * @@ -319,7 +319,7 @@ lpfc_free_fast_evt(struct lpfc_hba *phba, } /** - * lpfc_send_fastpath_evt: Posts events generated from fast path. + * lpfc_send_fastpath_evt - Posts events generated from fast path * @phba: Pointer to hba context object. * @evtp: Event data structure. * @@ -1858,13 +1858,18 @@ lpfc_disable_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) NLP_STE_UNUSED_NODE); } /** - * lpfc_initialize_node: Initialize all fields of node object. + * lpfc_initialize_node - Initialize all fields of node object * @vport: Pointer to Virtual Port object. * @ndlp: Pointer to FC node object. * @did: FC_ID of the node. - * This function is always called when node object need to - * be initialized. It initializes all the fields of the node - * object. + * + * This function is always called when node object need to be initialized. + * It initializes all the fields of the node object. Although the reference + * to phba from @ndlp can be obtained indirectly through it's reference to + * @vport, a direct reference to phba is taken here by @ndlp. This is due + * to the life-span of the @ndlp might go beyond the existence of @vport as + * the final release of ndlp is determined by its reference count. And, the + * operation on @ndlp needs the reference to phba. **/ static inline void lpfc_initialize_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, @@ -1877,6 +1882,7 @@ lpfc_initialize_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, ndlp->nlp_delayfunc.data = (unsigned long)ndlp; ndlp->nlp_DID = did; ndlp->vport = vport; + ndlp->phba = vport->phba; ndlp->nlp_sid = NLP_NO_SID; kref_init(&ndlp->kref); NLP_INT_NODE_ACT(ndlp); @@ -2086,7 +2092,6 @@ lpfc_no_rpi(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) struct lpfc_sli *psli; struct lpfc_sli_ring *pring; struct lpfc_iocbq *iocb, *next_iocb; - IOCB_t *icmd; uint32_t rpi, i; lpfc_fabric_abort_nport(ndlp); @@ -2122,19 +2127,9 @@ lpfc_no_rpi(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) } } - while (!list_empty(&completions)) { - iocb = list_get_first(&completions, struct lpfc_iocbq, list); - list_del_init(&iocb->list); - - if (!iocb->iocb_cmpl) - lpfc_sli_release_iocbq(phba, iocb); - else { - icmd = &iocb->iocb; - icmd->ulpStatus = IOSTAT_LOCAL_REJECT; - icmd->un.ulpWord[4] = IOERR_SLI_ABORTED; - (iocb->iocb_cmpl)(phba, iocb, iocb); - } - } + /* Cancel all the IOCBs from the completions list */ + lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT, + IOERR_SLI_ABORTED); return 0; } @@ -2186,9 +2181,13 @@ lpfc_unreg_all_rpis(struct lpfc_vport *vport) mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl; mbox->context1 = NULL; rc = lpfc_sli_issue_mbox_wait(phba, mbox, LPFC_MBOX_TMO); - if (rc == MBX_NOT_FINISHED) { + if (rc != MBX_TIMEOUT) mempool_free(mbox, phba->mbox_mem_pool); - } + + if ((rc == MBX_TIMEOUT) || (rc == MBX_NOT_FINISHED)) + lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX | LOG_VPORT, + "1836 Could not issue " + "unreg_login(all_rpis) status %d\n", rc); } } @@ -2206,12 +2205,14 @@ lpfc_unreg_default_rpis(struct lpfc_vport *vport) mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl; mbox->context1 = NULL; rc = lpfc_sli_issue_mbox_wait(phba, mbox, LPFC_MBOX_TMO); - if (rc == MBX_NOT_FINISHED) { + if (rc != MBX_TIMEOUT) + mempool_free(mbox, phba->mbox_mem_pool); + + if ((rc == MBX_TIMEOUT) || (rc == MBX_NOT_FINISHED)) lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX | LOG_VPORT, "1815 Could not issue " - "unreg_did (default rpis)\n"); - mempool_free(mbox, phba->mbox_mem_pool); - } + "unreg_did (default rpis) status %d\n", + rc); } } @@ -2470,14 +2471,13 @@ lpfc_setup_disc_node(struct lpfc_vport *vport, uint32_t did) if (ndlp->nlp_flag & NLP_RCV_PLOGI) return NULL; - spin_lock_irq(shost->host_lock); - ndlp->nlp_flag |= NLP_NPR_2B_DISC; - spin_unlock_irq(shost->host_lock); - /* Since this node is marked for discovery, * delay timeout is not needed. */ lpfc_cancel_retry_delay_tmo(vport, ndlp); + spin_lock_irq(shost->host_lock); + ndlp->nlp_flag |= NLP_NPR_2B_DISC; + spin_unlock_irq(shost->host_lock); } else ndlp = NULL; } else { @@ -2740,19 +2740,9 @@ lpfc_free_tx(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) } spin_unlock_irq(&phba->hbalock); - while (!list_empty(&completions)) { - iocb = list_get_first(&completions, struct lpfc_iocbq, list); - list_del_init(&iocb->list); - - if (!iocb->iocb_cmpl) - lpfc_sli_release_iocbq(phba, iocb); - else { - icmd = &iocb->iocb; - icmd->ulpStatus = IOSTAT_LOCAL_REJECT; - icmd->un.ulpWord[4] = IOERR_SLI_ABORTED; - (iocb->iocb_cmpl) (phba, iocb, iocb); - } - } + /* Cancel all the IOCBs from the completions list */ + lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT, + IOERR_SLI_ABORTED); } static void @@ -3173,7 +3163,7 @@ lpfc_nlp_release(struct kref *kref) lpfc_nlp_remove(ndlp->vport, ndlp); /* clear the ndlp active flag for all release cases */ - phba = ndlp->vport->phba; + phba = ndlp->phba; spin_lock_irqsave(&phba->ndlp_lock, flags); NLP_CLR_NODE_ACT(ndlp); spin_unlock_irqrestore(&phba->ndlp_lock, flags); @@ -3181,7 +3171,7 @@ lpfc_nlp_release(struct kref *kref) /* free ndlp memory for final ndlp release */ if (NLP_CHK_FREE_REQ(ndlp)) { kfree(ndlp->lat_data); - mempool_free(ndlp, ndlp->vport->phba->nlp_mem_pool); + mempool_free(ndlp, ndlp->phba->nlp_mem_pool); } } @@ -3204,7 +3194,7 @@ lpfc_nlp_get(struct lpfc_nodelist *ndlp) * ndlp reference count that is in the process of being * released. */ - phba = ndlp->vport->phba; + phba = ndlp->phba; spin_lock_irqsave(&phba->ndlp_lock, flags); if (!NLP_CHK_NODE_ACT(ndlp) || NLP_CHK_FREE_ACK(ndlp)) { spin_unlock_irqrestore(&phba->ndlp_lock, flags); @@ -3240,7 +3230,7 @@ lpfc_nlp_put(struct lpfc_nodelist *ndlp) "node put: did:x%x flg:x%x refcnt:x%x", ndlp->nlp_DID, ndlp->nlp_flag, atomic_read(&ndlp->kref.refcount)); - phba = ndlp->vport->phba; + phba = ndlp->phba; spin_lock_irqsave(&phba->ndlp_lock, flags); /* Check the ndlp memory free acknowledge flag to avoid the * possible race condition that kref_put got invoked again diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 06874e6009e..86d1bdcbf2d 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -60,7 +60,7 @@ static struct scsi_transport_template *lpfc_vport_transport_template = NULL; static DEFINE_IDR(lpfc_hba_index); /** - * lpfc_config_port_prep: Perform lpfc initialization prior to config port. + * lpfc_config_port_prep - Perform lpfc initialization prior to config port * @phba: pointer to lpfc hba data structure. * * This routine will do LPFC initialization prior to issuing the CONFIG_PORT @@ -221,7 +221,7 @@ out_free_mbox: } /** - * lpfc_config_async_cmpl: Completion handler for config async event mbox cmd. + * lpfc_config_async_cmpl - Completion handler for config async event mbox cmd * @phba: pointer to lpfc hba data structure. * @pmboxq: pointer to the driver internal queue element for mailbox command. * @@ -242,8 +242,7 @@ lpfc_config_async_cmpl(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq) } /** - * lpfc_dump_wakeup_param_cmpl: Completion handler for dump memory mailbox - * command used for getting wake up parameters. + * lpfc_dump_wakeup_param_cmpl - dump memory mailbox command completion handler * @phba: pointer to lpfc hba data structure. * @pmboxq: pointer to the driver internal queue element for mailbox command. * @@ -287,7 +286,7 @@ lpfc_dump_wakeup_param_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq) } /** - * lpfc_config_port_post: Perform lpfc initialization after config port. + * lpfc_config_port_post - Perform lpfc initialization after config port * @phba: pointer to lpfc hba data structure. * * This routine will do LPFC initialization after the CONFIG_PORT mailbox @@ -303,6 +302,7 @@ int lpfc_config_port_post(struct lpfc_hba *phba) { struct lpfc_vport *vport = phba->pport; + struct Scsi_Host *shost = lpfc_shost_from_vport(vport); LPFC_MBOXQ_t *pmb; MAILBOX_t *mb; struct lpfc_dmabuf *mp; @@ -360,6 +360,11 @@ lpfc_config_port_post(struct lpfc_hba *phba) sizeof (struct lpfc_name)); memcpy(&vport->fc_portname, &vport->fc_sparam.portName, sizeof (struct lpfc_name)); + + /* Update the fc_host data structures with new wwn. */ + fc_host_node_name(shost) = wwn_to_u64(vport->fc_nodename.u.wwn); + fc_host_port_name(shost) = wwn_to_u64(vport->fc_portname.u.wwn); + /* If no serial number in VPD data, use low 6 bytes of WWNN */ /* This should be consolidated into parse_vpd ? - mr */ if (phba->SerialNumber[0] == 0) { @@ -551,7 +556,7 @@ lpfc_config_port_post(struct lpfc_hba *phba) } /** - * lpfc_hba_down_prep: Perform lpfc uninitialization prior to HBA reset. + * lpfc_hba_down_prep - Perform lpfc uninitialization prior to HBA reset * @phba: pointer to lpfc HBA data structure. * * This routine will do LPFC uninitialization before the HBA is reset when @@ -583,7 +588,7 @@ lpfc_hba_down_prep(struct lpfc_hba *phba) } /** - * lpfc_hba_down_post: Perform lpfc uninitialization after HBA reset. + * lpfc_hba_down_post - Perform lpfc uninitialization after HBA reset * @phba: pointer to lpfc HBA data structure. * * This routine will do uninitialization after the HBA is reset when bring @@ -599,8 +604,6 @@ lpfc_hba_down_post(struct lpfc_hba *phba) struct lpfc_sli *psli = &phba->sli; struct lpfc_sli_ring *pring; struct lpfc_dmabuf *mp, *next_mp; - struct lpfc_iocbq *iocb; - IOCB_t *cmd = NULL; LIST_HEAD(completions); int i; @@ -628,20 +631,9 @@ lpfc_hba_down_post(struct lpfc_hba *phba) pring->txcmplq_cnt = 0; spin_unlock_irq(&phba->hbalock); - while (!list_empty(&completions)) { - iocb = list_get_first(&completions, struct lpfc_iocbq, - list); - cmd = &iocb->iocb; - list_del_init(&iocb->list); - - if (!iocb->iocb_cmpl) - lpfc_sli_release_iocbq(phba, iocb); - else { - cmd->ulpStatus = IOSTAT_LOCAL_REJECT; - cmd->un.ulpWord[4] = IOERR_SLI_ABORTED; - (iocb->iocb_cmpl) (phba, iocb, iocb); - } - } + /* Cancel all the IOCBs from the completions list */ + lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT, + IOERR_SLI_ABORTED); lpfc_sli_abort_iocb_ring(phba, pring); spin_lock_irq(&phba->hbalock); @@ -652,7 +644,7 @@ lpfc_hba_down_post(struct lpfc_hba *phba) } /** - * lpfc_hb_timeout: The HBA-timer timeout handler. + * lpfc_hb_timeout - The HBA-timer timeout handler * @ptr: unsigned long holds the pointer to lpfc hba data structure. * * This is the HBA-timer timeout handler registered to the lpfc driver. When @@ -686,7 +678,7 @@ lpfc_hb_timeout(unsigned long ptr) } /** - * lpfc_hb_mbox_cmpl: The lpfc heart-beat mailbox command callback function. + * lpfc_hb_mbox_cmpl - The lpfc heart-beat mailbox command callback function * @phba: pointer to lpfc hba data structure. * @pmboxq: pointer to the driver internal queue element for mailbox command. * @@ -721,7 +713,7 @@ lpfc_hb_mbox_cmpl(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq) } /** - * lpfc_hb_timeout_handler: The HBA-timer timeout handler. + * lpfc_hb_timeout_handler - The HBA-timer timeout handler * @phba: pointer to lpfc hba data structure. * * This is the actual HBA-timer timeout handler to be invoked by the worker @@ -830,7 +822,7 @@ lpfc_hb_timeout_handler(struct lpfc_hba *phba) } /** - * lpfc_offline_eratt: Bring lpfc offline on hardware error attention. + * lpfc_offline_eratt - Bring lpfc offline on hardware error attention * @phba: pointer to lpfc hba data structure. * * This routine is called to bring the HBA offline when HBA hardware error @@ -857,7 +849,73 @@ lpfc_offline_eratt(struct lpfc_hba *phba) } /** - * lpfc_handle_eratt: The HBA hardware error handler. + * lpfc_handle_deferred_eratt - The HBA hardware deferred error handler + * @phba: pointer to lpfc hba data structure. + * + * This routine is invoked to handle the deferred HBA hardware error + * conditions. This type of error is indicated by HBA by setting ER1 + * and another ER bit in the host status register. The driver will + * wait until the ER1 bit clears before handling the error condition. + **/ +static void +lpfc_handle_deferred_eratt(struct lpfc_hba *phba) +{ + uint32_t old_host_status = phba->work_hs; + struct lpfc_sli_ring *pring; + struct lpfc_sli *psli = &phba->sli; + + lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + "0479 Deferred Adapter Hardware Error " + "Data: x%x x%x x%x\n", + phba->work_hs, + phba->work_status[0], phba->work_status[1]); + + spin_lock_irq(&phba->hbalock); + psli->sli_flag &= ~LPFC_SLI2_ACTIVE; + spin_unlock_irq(&phba->hbalock); + + + /* + * Firmware stops when it triggred erratt. That could cause the I/Os + * dropped by the firmware. Error iocb (I/O) on txcmplq and let the + * SCSI layer retry it after re-establishing link. + */ + pring = &psli->ring[psli->fcp_ring]; + lpfc_sli_abort_iocb_ring(phba, pring); + + /* + * There was a firmware error. Take the hba offline and then + * attempt to restart it. + */ + lpfc_offline_prep(phba); + lpfc_offline(phba); + + /* Wait for the ER1 bit to clear.*/ + while (phba->work_hs & HS_FFER1) { + msleep(100); + phba->work_hs = readl(phba->HSregaddr); + /* If driver is unloading let the worker thread continue */ + if (phba->pport->load_flag & FC_UNLOADING) { + phba->work_hs = 0; + break; + } + } + + /* + * This is to ptrotect against a race condition in which + * first write to the host attention register clear the + * host status register. + */ + if ((!phba->work_hs) && (!(phba->pport->load_flag & FC_UNLOADING))) + phba->work_hs = old_host_status & ~HS_FFER1; + + phba->hba_flag &= ~DEFER_ERATT; + phba->work_status[0] = readl(phba->MBslimaddr + 0xa8); + phba->work_status[1] = readl(phba->MBslimaddr + 0xac); +} + +/** + * lpfc_handle_eratt - The HBA hardware error handler * @phba: pointer to lpfc hba data structure. * * This routine is invoked to handle the following HBA hardware error @@ -895,6 +953,9 @@ lpfc_handle_eratt(struct lpfc_hba *phba) (char *) &board_event, LPFC_NL_VENDOR_ID); + if (phba->hba_flag & DEFER_ERATT) + lpfc_handle_deferred_eratt(phba); + if (phba->work_hs & HS_FFER6) { /* Re-establishing Link */ lpfc_printf_log(phba, KERN_INFO, LOG_LINK_EVENT, @@ -976,7 +1037,7 @@ lpfc_handle_eratt(struct lpfc_hba *phba) } /** - * lpfc_handle_latt: The HBA link event handler. + * lpfc_handle_latt - The HBA link event handler * @phba: pointer to lpfc hba data structure. * * This routine is invoked from the worker thread to handle a HBA host @@ -1063,7 +1124,7 @@ lpfc_handle_latt_err_exit: } /** - * lpfc_parse_vpd: Parse VPD (Vital Product Data). + * lpfc_parse_vpd - Parse VPD (Vital Product Data) * @phba: pointer to lpfc hba data structure. * @vpd: pointer to the vital product data. * @len: length of the vital product data in bytes. @@ -1213,7 +1274,7 @@ lpfc_parse_vpd(struct lpfc_hba *phba, uint8_t *vpd, int len) } /** - * lpfc_get_hba_model_desc: Retrieve HBA device model name and description. + * lpfc_get_hba_model_desc - Retrieve HBA device model name and description * @phba: pointer to lpfc hba data structure. * @mdp: pointer to the data structure to hold the derived model name. * @descp: pointer to the data structure to hold the derived description. @@ -1322,7 +1383,8 @@ lpfc_get_hba_model_desc(struct lpfc_hba *phba, uint8_t *mdp, uint8_t *descp) m = (typeof(m)){"LPe11000", max_speed, "PCIe"}; break; case PCI_DEVICE_ID_ZEPHYR_DCSP: - m = (typeof(m)){"LPe11002-SP", max_speed, "PCIe"}; + m = (typeof(m)){"LP2105", max_speed, "PCIe"}; + GE = 1; break; case PCI_DEVICE_ID_ZMID: m = (typeof(m)){"LPe1150", max_speed, "PCIe"}; @@ -1392,7 +1454,7 @@ lpfc_get_hba_model_desc(struct lpfc_hba *phba, uint8_t *mdp, uint8_t *descp) } /** - * lpfc_post_buffer: Post IOCB(s) with DMA buffer descriptor(s) to a IOCB ring. + * lpfc_post_buffer - Post IOCB(s) with DMA buffer descriptor(s) to a IOCB ring * @phba: pointer to lpfc hba data structure. * @pring: pointer to a IOCB ring. * @cnt: the number of IOCBs to be posted to the IOCB ring. @@ -1493,7 +1555,7 @@ lpfc_post_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, int cnt) } /** - * lpfc_post_rcv_buf: Post the initial receive IOCB buffers to ELS ring. + * lpfc_post_rcv_buf - Post the initial receive IOCB buffers to ELS ring * @phba: pointer to lpfc hba data structure. * * This routine posts initial receive IOCB buffers to the ELS ring. The @@ -1518,7 +1580,7 @@ lpfc_post_rcv_buf(struct lpfc_hba *phba) #define S(N,V) (((V)<<(N))|((V)>>(32-(N)))) /** - * lpfc_sha_init: Set up initial array of hash table entries. + * lpfc_sha_init - Set up initial array of hash table entries * @HashResultPointer: pointer to an array as hash table. * * This routine sets up the initial values to the array of hash table entries @@ -1535,7 +1597,7 @@ lpfc_sha_init(uint32_t * HashResultPointer) } /** - * lpfc_sha_iterate: Iterate initial hash table with the working hash table. + * lpfc_sha_iterate - Iterate initial hash table with the working hash table * @HashResultPointer: pointer to an initial/result hash table. * @HashWorkingPointer: pointer to an working hash table. * @@ -1592,7 +1654,7 @@ lpfc_sha_iterate(uint32_t * HashResultPointer, uint32_t * HashWorkingPointer) } /** - * lpfc_challenge_key: Create challenge key based on WWPN of the HBA. + * lpfc_challenge_key - Create challenge key based on WWPN of the HBA * @RandomChallenge: pointer to the entry of host challenge random number array. * @HashWorking: pointer to the entry of the working hash array. * @@ -1608,7 +1670,7 @@ lpfc_challenge_key(uint32_t * RandomChallenge, uint32_t * HashWorking) } /** - * lpfc_hba_init: Perform special handling for LC HBA initialization. + * lpfc_hba_init - Perform special handling for LC HBA initialization * @phba: pointer to lpfc hba data structure. * @hbainit: pointer to an array of unsigned 32-bit integers. * @@ -1637,7 +1699,7 @@ lpfc_hba_init(struct lpfc_hba *phba, uint32_t *hbainit) } /** - * lpfc_cleanup: Performs vport cleanups before deleting a vport. + * lpfc_cleanup - Performs vport cleanups before deleting a vport * @vport: pointer to a virtual N_Port data structure. * * This routine performs the necessary cleanups before deleting the @vport. @@ -1724,7 +1786,7 @@ lpfc_cleanup(struct lpfc_vport *vport) } /** - * lpfc_stop_vport_timers: Stop all the timers associated with a vport. + * lpfc_stop_vport_timers - Stop all the timers associated with a vport * @vport: pointer to a virtual N_Port data structure. * * This routine stops all the timers associated with a @vport. This function @@ -1741,7 +1803,7 @@ lpfc_stop_vport_timers(struct lpfc_vport *vport) } /** - * lpfc_stop_phba_timers: Stop all the timers associated with an HBA. + * lpfc_stop_phba_timers - Stop all the timers associated with an HBA * @phba: pointer to lpfc hba data structure. * * This routine stops all the timers associated with a HBA. This function is @@ -1761,7 +1823,7 @@ lpfc_stop_phba_timers(struct lpfc_hba *phba) } /** - * lpfc_block_mgmt_io: Mark a HBA's management interface as blocked. + * lpfc_block_mgmt_io - Mark a HBA's management interface as blocked * @phba: pointer to lpfc hba data structure. * * This routine marks a HBA's management interface as blocked. Once the HBA's @@ -1781,7 +1843,7 @@ lpfc_block_mgmt_io(struct lpfc_hba * phba) } /** - * lpfc_online: Initialize and bring a HBA online. + * lpfc_online - Initialize and bring a HBA online * @phba: pointer to lpfc hba data structure. * * This routine initializes the HBA and brings a HBA online. During this @@ -1839,7 +1901,7 @@ lpfc_online(struct lpfc_hba *phba) } /** - * lpfc_unblock_mgmt_io: Mark a HBA's management interface to be not blocked. + * lpfc_unblock_mgmt_io - Mark a HBA's management interface to be not blocked * @phba: pointer to lpfc hba data structure. * * This routine marks a HBA's management interface as not blocked. Once the @@ -1860,7 +1922,7 @@ lpfc_unblock_mgmt_io(struct lpfc_hba * phba) } /** - * lpfc_offline_prep: Prepare a HBA to be brought offline. + * lpfc_offline_prep - Prepare a HBA to be brought offline * @phba: pointer to lpfc hba data structure. * * This routine is invoked to prepare a HBA to be brought offline. It performs @@ -1917,7 +1979,7 @@ lpfc_offline_prep(struct lpfc_hba * phba) } /** - * lpfc_offline: Bring a HBA offline. + * lpfc_offline - Bring a HBA offline * @phba: pointer to lpfc hba data structure. * * This routine actually brings a HBA offline. It stops all the timers @@ -1962,7 +2024,7 @@ lpfc_offline(struct lpfc_hba *phba) } /** - * lpfc_scsi_free: Free all the SCSI buffers and IOCBs from driver lists. + * lpfc_scsi_free - Free all the SCSI buffers and IOCBs from driver lists * @phba: pointer to lpfc hba data structure. * * This routine is to free all the SCSI buffers and IOCBs from the driver @@ -2001,7 +2063,7 @@ lpfc_scsi_free(struct lpfc_hba *phba) } /** - * lpfc_create_port: Create an FC port. + * lpfc_create_port - Create an FC port * @phba: pointer to lpfc hba data structure. * @instance: a unique integer ID to this FC port. * @dev: pointer to the device data structure. @@ -2091,7 +2153,7 @@ out: } /** - * destroy_port: Destroy an FC port. + * destroy_port - destroy an FC port * @vport: pointer to an lpfc virtual N_Port data structure. * * This routine destroys a FC port from the upper layer protocol. All the @@ -2116,7 +2178,7 @@ destroy_port(struct lpfc_vport *vport) } /** - * lpfc_get_instance: Get a unique integer ID. + * lpfc_get_instance - Get a unique integer ID * * This routine allocates a unique integer ID from lpfc_hba_index pool. It * uses the kernel idr facility to perform the task. @@ -2139,7 +2201,7 @@ lpfc_get_instance(void) } /** - * lpfc_scan_finished: method for SCSI layer to detect whether scan is done. + * lpfc_scan_finished - method for SCSI layer to detect whether scan is done * @shost: pointer to SCSI host data structure. * @time: elapsed time of the scan in jiffies. * @@ -2197,7 +2259,7 @@ finished: } /** - * lpfc_host_attrib_init: Initialize SCSI host attributes on a FC port. + * lpfc_host_attrib_init - Initialize SCSI host attributes on a FC port * @shost: pointer to SCSI host data structure. * * This routine initializes a given SCSI host attributes on a FC port. The @@ -2252,7 +2314,7 @@ void lpfc_host_attrib_init(struct Scsi_Host *shost) } /** - * lpfc_enable_msix: Enable MSI-X interrupt mode. + * lpfc_enable_msix - Enable MSI-X interrupt mode * @phba: pointer to lpfc hba data structure. * * This routine is invoked to enable the MSI-X interrupt vectors. The kernel @@ -2366,7 +2428,7 @@ msi_fail_out: } /** - * lpfc_disable_msix: Disable MSI-X interrupt mode. + * lpfc_disable_msix - Disable MSI-X interrupt mode * @phba: pointer to lpfc hba data structure. * * This routine is invoked to release the MSI-X vectors and then disable the @@ -2385,7 +2447,7 @@ lpfc_disable_msix(struct lpfc_hba *phba) } /** - * lpfc_enable_msi: Enable MSI interrupt mode. + * lpfc_enable_msi - Enable MSI interrupt mode * @phba: pointer to lpfc hba data structure. * * This routine is invoked to enable the MSI interrupt mode. The kernel @@ -2423,7 +2485,7 @@ lpfc_enable_msi(struct lpfc_hba *phba) } /** - * lpfc_disable_msi: Disable MSI interrupt mode. + * lpfc_disable_msi - Disable MSI interrupt mode * @phba: pointer to lpfc hba data structure. * * This routine is invoked to disable the MSI interrupt mode. The driver @@ -2441,7 +2503,7 @@ lpfc_disable_msi(struct lpfc_hba *phba) } /** - * lpfc_log_intr_mode: Log the active interrupt mode + * lpfc_log_intr_mode - Log the active interrupt mode * @phba: pointer to lpfc hba data structure. * @intr_mode: active interrupt mode adopted. * @@ -2490,7 +2552,7 @@ lpfc_stop_port(struct lpfc_hba *phba) } /** - * lpfc_enable_intr: Enable device interrupt. + * lpfc_enable_intr - Enable device interrupt * @phba: pointer to lpfc hba data structure. * * This routine is invoked to enable device interrupt and associate driver's @@ -2547,7 +2609,7 @@ lpfc_enable_intr(struct lpfc_hba *phba, uint32_t cfg_mode) } /** - * lpfc_disable_intr: Disable device interrupt. + * lpfc_disable_intr - Disable device interrupt * @phba: pointer to lpfc hba data structure. * * This routine is invoked to disable device interrupt and disassociate the @@ -2574,7 +2636,7 @@ lpfc_disable_intr(struct lpfc_hba *phba) } /** - * lpfc_pci_probe_one: lpfc PCI probe func to register device to PCI subsystem. + * lpfc_pci_probe_one - lpfc PCI probe func to register device to PCI subsystem * @pdev: pointer to PCI device * @pid: pointer to PCI device identifier * @@ -3010,7 +3072,7 @@ out: } /** - * lpfc_pci_remove_one: lpfc PCI func to unregister device from PCI subsystem. + * lpfc_pci_remove_one - lpfc PCI func to unregister device from PCI subsystem * @pdev: pointer to PCI device * * This routine is to be registered to the kernel's PCI subsystem. When an @@ -3033,8 +3095,6 @@ lpfc_pci_remove_one(struct pci_dev *pdev) lpfc_free_sysfs_attr(vport); - kthread_stop(phba->worker_thread); - /* Release all the vports against this physical port */ vports = lpfc_create_vport_work_array(phba); if (vports != NULL) @@ -3052,7 +3112,12 @@ lpfc_pci_remove_one(struct pci_dev *pdev) * clears the rings, discards all mailbox commands, and resets * the HBA. */ + + /* HBA interrupt will be diabled after this call */ lpfc_sli_hba_down(phba); + /* Stop kthread signal shall trigger work_done one more time */ + kthread_stop(phba->worker_thread); + /* Final cleanup of txcmplq and reset the HBA */ lpfc_sli_brdrestart(phba); lpfc_stop_phba_timers(phba); @@ -3095,7 +3160,7 @@ lpfc_pci_remove_one(struct pci_dev *pdev) } /** - * lpfc_pci_suspend_one: lpfc PCI func to suspend device for power management. + * lpfc_pci_suspend_one - lpfc PCI func to suspend device for power management * @pdev: pointer to PCI device * @msg: power management message * @@ -3139,7 +3204,7 @@ lpfc_pci_suspend_one(struct pci_dev *pdev, pm_message_t msg) } /** - * lpfc_pci_resume_one: lpfc PCI func to resume device for power management. + * lpfc_pci_resume_one - lpfc PCI func to resume device for power management * @pdev: pointer to PCI device * * This routine is to be registered to the kernel's PCI subsystem to support @@ -3204,7 +3269,7 @@ lpfc_pci_resume_one(struct pci_dev *pdev) } /** - * lpfc_io_error_detected: Driver method for handling PCI I/O error detected. + * lpfc_io_error_detected - Driver method for handling PCI I/O error detected * @pdev: pointer to PCI device. * @state: the current PCI connection state. * @@ -3254,7 +3319,7 @@ static pci_ers_result_t lpfc_io_error_detected(struct pci_dev *pdev, } /** - * lpfc_io_slot_reset: Restart a PCI device from scratch. + * lpfc_io_slot_reset - Restart a PCI device from scratch * @pdev: pointer to PCI device. * * This routine is registered to the PCI subsystem for error handling. This is @@ -3313,7 +3378,7 @@ static pci_ers_result_t lpfc_io_slot_reset(struct pci_dev *pdev) } /** - * lpfc_io_resume: Resume PCI I/O operation. + * lpfc_io_resume - Resume PCI I/O operation * @pdev: pointer to PCI device * * This routine is registered to the PCI subsystem for error handling. It is @@ -3426,7 +3491,7 @@ static struct pci_driver lpfc_driver = { }; /** - * lpfc_init: lpfc module initialization routine. + * lpfc_init - lpfc module initialization routine * * This routine is to be invoked when the lpfc module is loaded into the * kernel. The special kernel macro module_init() is used to indicate the @@ -3472,7 +3537,7 @@ lpfc_init(void) } /** - * lpfc_exit: lpfc module removal routine. + * lpfc_exit - lpfc module removal routine * * This routine is invoked when the lpfc module is removed from the kernel. * The special kernel macro module_exit() is used to indicate the role of diff --git a/drivers/scsi/lpfc/lpfc_logmsg.h b/drivers/scsi/lpfc/lpfc_logmsg.h index a85b7c196bb..1aa85709b01 100644 --- a/drivers/scsi/lpfc/lpfc_logmsg.h +++ b/drivers/scsi/lpfc/lpfc_logmsg.h @@ -27,7 +27,7 @@ #define LOG_FCP 0x40 /* FCP traffic history */ #define LOG_NODE 0x80 /* Node table events */ #define LOG_TEMP 0x100 /* Temperature sensor events */ -#define LOG_BG 0x200 /* BlockBuard events */ +#define LOG_BG 0x200 /* BlockGuard events */ #define LOG_MISC 0x400 /* Miscellaneous events */ #define LOG_SLI 0x800 /* SLI events */ #define LOG_FCP_ERROR 0x1000 /* log errors, not underruns */ diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c index 34eeb086a66..134fc7fc212 100644 --- a/drivers/scsi/lpfc/lpfc_mbox.c +++ b/drivers/scsi/lpfc/lpfc_mbox.c @@ -39,7 +39,7 @@ #include "lpfc_compat.h" /** - * lpfc_dump_mem: Prepare a mailbox command for retrieving HBA's VPD memory. + * lpfc_dump_mem - Prepare a mailbox command for retrieving HBA's VPD memory * @phba: pointer to lpfc hba data structure. * @pmb: pointer to the driver internal queue element for mailbox command. * @offset: offset for dumping VPD memory mailbox command. @@ -77,9 +77,10 @@ lpfc_dump_mem(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb, uint16_t offset) } /** - * lpfc_dump_mem: Prepare a mailbox command for retrieving wakeup params. + * lpfc_dump_wakeup_param - Prepare mailbox command for retrieving wakeup params * @phba: pointer to lpfc hba data structure. * @pmb: pointer to the driver internal queue element for mailbox command. + * * This function create a dump memory mailbox command to dump wake up * parameters. */ @@ -109,7 +110,7 @@ lpfc_dump_wakeup_param(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) } /** - * lpfc_read_nv: Prepare a mailbox command for reading HBA's NVRAM param. + * lpfc_read_nv - Prepare a mailbox command for reading HBA's NVRAM param * @phba: pointer to lpfc hba data structure. * @pmb: pointer to the driver internal queue element for mailbox command. * @@ -132,7 +133,7 @@ lpfc_read_nv(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) } /** - * lpfc_config_async: Prepare a mailbox command for enabling HBA async event. + * lpfc_config_async - Prepare a mailbox command for enabling HBA async event * @phba: pointer to lpfc hba data structure. * @pmb: pointer to the driver internal queue element for mailbox command. * @ring: ring number for the asynchronous event to be configured. @@ -159,7 +160,7 @@ lpfc_config_async(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb, } /** - * lpfc_heart_beat: Prepare a mailbox command for heart beat. + * lpfc_heart_beat - Prepare a mailbox command for heart beat * @phba: pointer to lpfc hba data structure. * @pmb: pointer to the driver internal queue element for mailbox command. * @@ -184,7 +185,7 @@ lpfc_heart_beat(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) } /** - * lpfc_read_la: Prepare a mailbox command for reading HBA link attention. + * lpfc_read_la - Prepare a mailbox command for reading HBA link attention * @phba: pointer to lpfc hba data structure. * @pmb: pointer to the driver internal queue element for mailbox command. * @mp: DMA buffer memory for reading the link attention information into. @@ -228,7 +229,7 @@ lpfc_read_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb, struct lpfc_dmabuf *mp) } /** - * lpfc_clear_la: Prepare a mailbox command for clearing HBA link attention. + * lpfc_clear_la - Prepare a mailbox command for clearing HBA link attention * @phba: pointer to lpfc hba data structure. * @pmb: pointer to the driver internal queue element for mailbox command. * @@ -257,7 +258,7 @@ lpfc_clear_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) } /** - * lpfc_config_link: Prepare a mailbox command for configuring link on a HBA. + * lpfc_config_link - Prepare a mailbox command for configuring link on a HBA * @phba: pointer to lpfc hba data structure. * @pmb: pointer to the driver internal queue element for mailbox command. * @@ -305,7 +306,7 @@ lpfc_config_link(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) } /** - * lpfc_config_msi: Prepare a mailbox command for configuring msi-x. + * lpfc_config_msi - Prepare a mailbox command for configuring msi-x * @phba: pointer to lpfc hba data structure. * @pmb: pointer to the driver internal queue element for mailbox command. * @@ -383,7 +384,7 @@ lpfc_config_msi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) } /** - * lpfc_init_link: Prepare a mailbox command for initialize link on a HBA. + * lpfc_init_link - Prepare a mailbox command for initialize link on a HBA * @phba: pointer to lpfc hba data structure. * @pmb: pointer to the driver internal queue element for mailbox command. * @topology: the link topology for the link to be initialized to. @@ -463,7 +464,7 @@ lpfc_init_link(struct lpfc_hba * phba, } /** - * lpfc_read_sparam: Prepare a mailbox command for reading HBA parameters. + * lpfc_read_sparam - Prepare a mailbox command for reading HBA parameters * @phba: pointer to lpfc hba data structure. * @pmb: pointer to the driver internal queue element for mailbox command. * @vpi: virtual N_Port identifier. @@ -523,7 +524,7 @@ lpfc_read_sparam(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb, int vpi) } /** - * lpfc_unreg_did: Prepare a mailbox command for unregistering DID. + * lpfc_unreg_did - Prepare a mailbox command for unregistering DID * @phba: pointer to lpfc hba data structure. * @vpi: virtual N_Port identifier. * @did: remote port identifier. @@ -555,7 +556,7 @@ lpfc_unreg_did(struct lpfc_hba * phba, uint16_t vpi, uint32_t did, } /** - * lpfc_read_config: Prepare a mailbox command for reading HBA configuration. + * lpfc_read_config - Prepare a mailbox command for reading HBA configuration * @phba: pointer to lpfc hba data structure. * @pmb: pointer to the driver internal queue element for mailbox command. * @@ -581,7 +582,7 @@ lpfc_read_config(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) } /** - * lpfc_read_lnk_stat: Prepare a mailbox command for reading HBA link stats. + * lpfc_read_lnk_stat - Prepare a mailbox command for reading HBA link stats * @phba: pointer to lpfc hba data structure. * @pmb: pointer to the driver internal queue element for mailbox command. * @@ -606,7 +607,7 @@ lpfc_read_lnk_stat(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) } /** - * lpfc_reg_login: Prepare a mailbox command for registering remote login. + * lpfc_reg_login - Prepare a mailbox command for registering remote login * @phba: pointer to lpfc hba data structure. * @vpi: virtual N_Port identifier. * @did: remote port identifier. @@ -677,7 +678,7 @@ lpfc_reg_login(struct lpfc_hba *phba, uint16_t vpi, uint32_t did, } /** - * lpfc_unreg_login: Prepare a mailbox command for unregistering remote login. + * lpfc_unreg_login - Prepare a mailbox command for unregistering remote login * @phba: pointer to lpfc hba data structure. * @vpi: virtual N_Port identifier. * @rpi: remote port identifier @@ -709,7 +710,7 @@ lpfc_unreg_login(struct lpfc_hba *phba, uint16_t vpi, uint32_t rpi, } /** - * lpfc_reg_vpi: Prepare a mailbox command for registering vport identifier. + * lpfc_reg_vpi - Prepare a mailbox command for registering vport identifier * @phba: pointer to lpfc hba data structure. * @vpi: virtual N_Port identifier. * @sid: Fibre Channel S_ID (N_Port_ID assigned to a virtual N_Port). @@ -741,7 +742,7 @@ lpfc_reg_vpi(struct lpfc_hba *phba, uint16_t vpi, uint32_t sid, } /** - * lpfc_unreg_vpi: Prepare a mailbox command for unregistering vport id. + * lpfc_unreg_vpi - Prepare a mailbox command for unregistering vport id * @phba: pointer to lpfc hba data structure. * @vpi: virtual N_Port identifier. * @pmb: pointer to the driver internal queue element for mailbox command. @@ -771,7 +772,7 @@ lpfc_unreg_vpi(struct lpfc_hba *phba, uint16_t vpi, LPFC_MBOXQ_t *pmb) } /** - * lpfc_config_pcb_setup: Set up IOCB rings in the Port Control Block (PCB) + * lpfc_config_pcb_setup - Set up IOCB rings in the Port Control Block (PCB) * @phba: pointer to lpfc hba data structure. * * This routine sets up and initializes the IOCB rings in the Port Control @@ -835,7 +836,7 @@ lpfc_config_pcb_setup(struct lpfc_hba * phba) } /** - * lpfc_read_rev: Prepare a mailbox command for reading HBA revision. + * lpfc_read_rev - Prepare a mailbox command for reading HBA revision * @phba: pointer to lpfc hba data structure. * @pmb: pointer to the driver internal queue element for mailbox command. * @@ -861,7 +862,7 @@ lpfc_read_rev(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) } /** - * lpfc_build_hbq_profile2: Set up the HBQ Selection Profile 2. + * lpfc_build_hbq_profile2 - Set up the HBQ Selection Profile 2 * @hbqmb: pointer to the HBQ configuration data structure in mailbox command. * @hbq_desc: pointer to the HBQ selection profile descriptor. * @@ -880,7 +881,7 @@ lpfc_build_hbq_profile2(struct config_hbq_var *hbqmb, } /** - * lpfc_build_hbq_profile3: Set up the HBQ Selection Profile 3. + * lpfc_build_hbq_profile3 - Set up the HBQ Selection Profile 3 * @hbqmb: pointer to the HBQ configuration data structure in mailbox command. * @hbq_desc: pointer to the HBQ selection profile descriptor. * @@ -902,7 +903,7 @@ lpfc_build_hbq_profile3(struct config_hbq_var *hbqmb, } /** - * lpfc_build_hbq_profile5: Set up the HBQ Selection Profile 5. + * lpfc_build_hbq_profile5 - Set up the HBQ Selection Profile 5 * @hbqmb: pointer to the HBQ configuration data structure in mailbox command. * @hbq_desc: pointer to the HBQ selection profile descriptor. * @@ -925,7 +926,7 @@ lpfc_build_hbq_profile5(struct config_hbq_var *hbqmb, } /** - * lpfc_config_hbq: Prepare a mailbox command for configuring an HBQ. + * lpfc_config_hbq - Prepare a mailbox command for configuring an HBQ * @phba: pointer to lpfc hba data structure. * @id: HBQ identifier. * @hbq_desc: pointer to the HBA descriptor data structure. @@ -999,7 +1000,7 @@ lpfc_config_hbq(struct lpfc_hba *phba, uint32_t id, } /** - * lpfc_config_ring: Prepare a mailbox command for configuring an IOCB ring. + * lpfc_config_ring - Prepare a mailbox command for configuring an IOCB ring * @phba: pointer to lpfc hba data structure. * @ring: * @pmb: pointer to the driver internal queue element for mailbox command. @@ -1057,7 +1058,7 @@ lpfc_config_ring(struct lpfc_hba * phba, int ring, LPFC_MBOXQ_t * pmb) } /** - * lpfc_config_port: Prepare a mailbox command for configuring port. + * lpfc_config_port - Prepare a mailbox command for configuring port * @phba: pointer to lpfc hba data structure. * @pmb: pointer to the driver internal queue element for mailbox command. * @@ -1227,7 +1228,7 @@ lpfc_config_port(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) } /** - * lpfc_kill_board: Prepare a mailbox command for killing board. + * lpfc_kill_board - Prepare a mailbox command for killing board * @phba: pointer to lpfc hba data structure. * @pmb: pointer to the driver internal queue element for mailbox command. * @@ -1253,7 +1254,7 @@ lpfc_kill_board(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) } /** - * lpfc_mbox_put: Put a mailbox cmd into the tail of driver's mailbox queue. + * lpfc_mbox_put - Put a mailbox cmd into the tail of driver's mailbox queue * @phba: pointer to lpfc hba data structure. * @mbq: pointer to the driver internal queue element for mailbox command. * @@ -1277,7 +1278,7 @@ lpfc_mbox_put(struct lpfc_hba * phba, LPFC_MBOXQ_t * mbq) } /** - * lpfc_mbox_get: Remove a mailbox cmd from the head of driver's mailbox queue. + * lpfc_mbox_get - Remove a mailbox cmd from the head of driver's mailbox queue * @phba: pointer to lpfc hba data structure. * * Driver maintains a internal mailbox command queue implemented as a linked @@ -1304,7 +1305,7 @@ lpfc_mbox_get(struct lpfc_hba * phba) } /** - * lpfc_mbox_cmpl_put: Put mailbox command into mailbox command complete list. + * lpfc_mbox_cmpl_put - Put mailbox command into mailbox command complete list * @phba: pointer to lpfc hba data structure. * @mbq: pointer to the driver internal queue element for mailbox command. * @@ -1327,7 +1328,7 @@ lpfc_mbox_cmpl_put(struct lpfc_hba * phba, LPFC_MBOXQ_t * mbq) } /** - * lpfc_mbox_tmo_val: Retrieve mailbox command timeout value. + * lpfc_mbox_tmo_val - Retrieve mailbox command timeout value * @phba: pointer to lpfc hba data structure. * @cmd: mailbox command code. * diff --git a/drivers/scsi/lpfc/lpfc_mem.c b/drivers/scsi/lpfc/lpfc_mem.c index a4bba206924..35a97673339 100644 --- a/drivers/scsi/lpfc/lpfc_mem.c +++ b/drivers/scsi/lpfc/lpfc_mem.c @@ -41,7 +41,7 @@ /** - * lpfc_mem_alloc: create and allocate all PCI and memory pools + * lpfc_mem_alloc - create and allocate all PCI and memory pools * @phba: HBA to allocate pools for * * Description: Creates and allocates PCI pools lpfc_scsi_dma_buf_pool, @@ -136,12 +136,12 @@ lpfc_mem_alloc(struct lpfc_hba * phba) } /** - * lpfc_mem_free: Frees all PCI and memory allocated by lpfc_mem_alloc + * lpfc_mem_free - Frees all PCI and memory allocated by lpfc_mem_alloc * @phba: HBA to free memory for * * Description: Frees PCI pools lpfc_scsi_dma_buf_pool, lpfc_mbuf_pool, * lpfc_hbq_pool. Frees kmalloc-backed mempools for LPFC_MBOXQ_t and - * lpfc_nodelist. Also frees the VPI bitmask. + * lpfc_nodelist. Also frees the VPI bitmask * * Returns: None **/ @@ -212,7 +212,7 @@ lpfc_mem_free(struct lpfc_hba * phba) } /** - * lpfc_mbuf_alloc: Allocate an mbuf from the lpfc_mbuf_pool PCI pool + * lpfc_mbuf_alloc - Allocate an mbuf from the lpfc_mbuf_pool PCI pool * @phba: HBA which owns the pool to allocate from * @mem_flags: indicates if this is a priority (MEM_PRI) allocation * @handle: used to return the DMA-mapped address of the mbuf @@ -249,7 +249,7 @@ lpfc_mbuf_alloc(struct lpfc_hba *phba, int mem_flags, dma_addr_t *handle) } /** - * __lpfc_mem_free: Free an mbuf from the lpfc_mbuf_pool PCI pool (locked) + * __lpfc_mbuf_free - Free an mbuf from the lpfc_mbuf_pool PCI pool (locked) * @phba: HBA which owns the pool to return to * @virt: mbuf to free * @dma: the DMA-mapped address of the lpfc_mbuf_pool to be freed @@ -278,7 +278,7 @@ __lpfc_mbuf_free(struct lpfc_hba * phba, void *virt, dma_addr_t dma) } /** - * lpfc_mem_free: Free an mbuf from the lpfc_mbuf_pool PCI pool (unlocked) + * lpfc_mbuf_free - Free an mbuf from the lpfc_mbuf_pool PCI pool (unlocked) * @phba: HBA which owns the pool to return to * @virt: mbuf to free * @dma: the DMA-mapped address of the lpfc_mbuf_pool to be freed @@ -291,7 +291,6 @@ __lpfc_mbuf_free(struct lpfc_hba * phba, void *virt, dma_addr_t dma) * Returns: None **/ void - lpfc_mbuf_free(struct lpfc_hba * phba, void *virt, dma_addr_t dma) { unsigned long iflags; @@ -303,7 +302,7 @@ lpfc_mbuf_free(struct lpfc_hba * phba, void *virt, dma_addr_t dma) } /** - * lpfc_els_hbq_alloc: Allocate an HBQ buffer + * lpfc_els_hbq_alloc - Allocate an HBQ buffer * @phba: HBA to allocate HBQ buffer for * * Description: Allocates a DMA-mapped HBQ buffer from the lpfc_hbq_pool PCI @@ -335,7 +334,7 @@ lpfc_els_hbq_alloc(struct lpfc_hba *phba) } /** - * lpfc_mem_hbq_free: Frees an HBQ buffer allocated with lpfc_els_hbq_alloc + * lpfc_mem_hbq_free - Frees an HBQ buffer allocated with lpfc_els_hbq_alloc * @phba: HBA buffer was allocated for * @hbqbp: HBQ container returned by lpfc_els_hbq_alloc * @@ -355,7 +354,7 @@ lpfc_els_hbq_free(struct lpfc_hba *phba, struct hbq_dmabuf *hbqbp) } /** - * lpfc_in_buf_free: Free a DMA buffer + * lpfc_in_buf_free - Free a DMA buffer * @phba: HBA buffer is associated with * @mp: Buffer to free * diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index 8f548adae9c..08cdc77af41 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c @@ -192,7 +192,6 @@ lpfc_els_abort(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) struct lpfc_sli *psli = &phba->sli; struct lpfc_sli_ring *pring = &psli->ring[LPFC_ELS_RING]; struct lpfc_iocbq *iocb, *next_iocb; - IOCB_t *cmd; /* Abort outstanding I/O on NPort <nlp_DID> */ lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_DISCOVERY, @@ -223,19 +222,10 @@ lpfc_els_abort(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) } spin_unlock_irq(&phba->hbalock); - while (!list_empty(&completions)) { - iocb = list_get_first(&completions, struct lpfc_iocbq, list); - cmd = &iocb->iocb; - list_del_init(&iocb->list); - - if (!iocb->iocb_cmpl) - lpfc_sli_release_iocbq(phba, iocb); - else { - cmd->ulpStatus = IOSTAT_LOCAL_REJECT; - cmd->un.ulpWord[4] = IOERR_SLI_ABORTED; - (iocb->iocb_cmpl) (phba, iocb, iocb); - } - } + /* Cancel all the IOCBs from the completions list */ + lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT, + IOERR_SLI_ABORTED); + lpfc_cancel_retry_delay_tmo(phba->pport, ndlp); return 0; } diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index 36fd2e75da1..167b66dd34c 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -112,7 +112,7 @@ lpfc_debug_save_dif(struct scsi_cmnd *cmnd) } /** - * lpfc_update_stats: Update statistical data for the command completion. + * lpfc_update_stats - Update statistical data for the command completion * @phba: Pointer to HBA object. * @lpfc_cmd: lpfc scsi command object pointer. * @@ -165,8 +165,7 @@ lpfc_update_stats(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd) } /** - * lpfc_send_sdev_queuedepth_change_event: Posts a queuedepth change - * event. + * lpfc_send_sdev_queuedepth_change_event - Posts a queuedepth change event * @phba: Pointer to HBA context object. * @vport: Pointer to vport object. * @ndlp: Pointer to FC node associated with the target. @@ -220,7 +219,7 @@ lpfc_send_sdev_queuedepth_change_event(struct lpfc_hba *phba, } /** - * lpfc_rampdown_queue_depth: Post RAMP_DOWN_QUEUE event to worker thread. + * lpfc_rampdown_queue_depth - Post RAMP_DOWN_QUEUE event to worker thread * @phba: The Hba for which this call is being executed. * * This routine is called when there is resource error in driver or firmware. @@ -261,7 +260,7 @@ lpfc_rampdown_queue_depth(struct lpfc_hba *phba) } /** - * lpfc_rampup_queue_depth: Post RAMP_UP_QUEUE event for worker thread. + * lpfc_rampup_queue_depth - Post RAMP_UP_QUEUE event for worker thread * @phba: The Hba for which this call is being executed. * * This routine post WORKER_RAMP_UP_QUEUE event for @phba vport. This routine @@ -273,14 +272,14 @@ lpfc_rampdown_queue_depth(struct lpfc_hba *phba) **/ static inline void lpfc_rampup_queue_depth(struct lpfc_vport *vport, - struct scsi_device *sdev) + uint32_t queue_depth) { unsigned long flags; struct lpfc_hba *phba = vport->phba; uint32_t evt_posted; atomic_inc(&phba->num_cmd_success); - if (vport->cfg_lun_queue_depth <= sdev->queue_depth) + if (vport->cfg_lun_queue_depth <= queue_depth) return; spin_lock_irqsave(&phba->hbalock, flags); if (((phba->last_ramp_up_time + QUEUE_RAMP_UP_INTERVAL) > jiffies) || @@ -303,7 +302,7 @@ lpfc_rampup_queue_depth(struct lpfc_vport *vport, } /** - * lpfc_ramp_down_queue_handler: WORKER_RAMP_DOWN_QUEUE event handler. + * lpfc_ramp_down_queue_handler - WORKER_RAMP_DOWN_QUEUE event handler * @phba: The Hba for which this call is being executed. * * This routine is called to process WORKER_RAMP_DOWN_QUEUE event for worker @@ -361,7 +360,7 @@ lpfc_ramp_down_queue_handler(struct lpfc_hba *phba) } /** - * lpfc_ramp_up_queue_handler: WORKER_RAMP_UP_QUEUE event handler. + * lpfc_ramp_up_queue_handler - WORKER_RAMP_UP_QUEUE event handler * @phba: The Hba for which this call is being executed. * * This routine is called to process WORKER_RAMP_UP_QUEUE event for worker @@ -410,7 +409,7 @@ lpfc_ramp_up_queue_handler(struct lpfc_hba *phba) } /** - * lpfc_scsi_dev_block: set all scsi hosts to block state. + * lpfc_scsi_dev_block - set all scsi hosts to block state * @phba: Pointer to HBA context object. * * This function walks vport list and set each SCSI host to block state @@ -439,7 +438,7 @@ lpfc_scsi_dev_block(struct lpfc_hba *phba) } /** - * lpfc_new_scsi_buf: Scsi buffer allocator. + * lpfc_new_scsi_buf - Scsi buffer allocator * @vport: The virtual port for which this call being executed. * * This routine allocates a scsi buffer, which contains all the necessary @@ -563,7 +562,7 @@ lpfc_new_scsi_buf(struct lpfc_vport *vport) } /** - * lpfc_get_scsi_buf: Get a scsi buffer from lpfc_scsi_buf_list list of Hba. + * lpfc_get_scsi_buf - Get a scsi buffer from lpfc_scsi_buf_list list of Hba * @phba: The Hba for which this call is being executed. * * This routine removes a scsi buffer from head of @phba lpfc_scsi_buf_list list @@ -592,7 +591,7 @@ lpfc_get_scsi_buf(struct lpfc_hba * phba) } /** - * lpfc_release_scsi_buf: Return a scsi buffer back to hba lpfc_scsi_buf_list list. + * lpfc_release_scsi_buf - Return a scsi buffer back to hba's lpfc_scsi_buf_list * @phba: The Hba for which this call is being executed. * @psb: The scsi buffer which is being released. * @@ -611,7 +610,7 @@ lpfc_release_scsi_buf(struct lpfc_hba *phba, struct lpfc_scsi_buf *psb) } /** - * lpfc_scsi_prep_dma_buf: Routine to do DMA mapping for scsi buffer. + * lpfc_scsi_prep_dma_buf - Routine to do DMA mapping for scsi buffer * @phba: The Hba for which this call is being executed. * @lpfc_cmd: The scsi buffer which is going to be mapped. * @@ -738,7 +737,7 @@ lpfc_scsi_prep_dma_buf(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd) * Due to difference in data length between DIF/non-DIF paths, * we need to set word 4 of IOCB here */ - iocb_cmd->un.fcpi.fcpi_parm = le32_to_cpu(scsi_bufflen(scsi_cmnd)); + iocb_cmd->un.fcpi.fcpi_parm = scsi_bufflen(scsi_cmnd); return 0; } @@ -823,9 +822,9 @@ lpfc_cmd_blksize(struct scsi_cmnd *sc) /** * lpfc_get_cmd_dif_parms - Extract DIF parameters from SCSI command * @sc: in: SCSI command - * @apptagmask out: app tag mask - * @apptagval out: app tag value - * @reftag out: ref tag (reference tag) + * @apptagmask: out: app tag mask + * @apptagval: out: app tag value + * @reftag: out: ref tag (reference tag) * * Description: * Extract DIF paramters from the command if possible. Otherwise, @@ -1413,7 +1412,7 @@ out: } /** - * lpfc_send_scsi_error_event: Posts an event when there is SCSI error. + * lpfc_send_scsi_error_event - Posts an event when there is SCSI error * @phba: Pointer to hba context object. * @vport: Pointer to vport object. * @lpfc_cmd: Pointer to lpfc scsi command which reported the error. @@ -1505,7 +1504,7 @@ lpfc_send_scsi_error_event(struct lpfc_hba *phba, struct lpfc_vport *vport, } /** - * lpfc_scsi_unprep_dma_buf: Routine to un-map DMA mapping of scatter gather. + * lpfc_scsi_unprep_dma_buf - Routine to un-map DMA mapping of scatter gather * @phba: The Hba for which this call is being executed. * @psb: The scsi buffer which is going to be un-mapped. * @@ -1530,7 +1529,7 @@ lpfc_scsi_unprep_dma_buf(struct lpfc_hba * phba, struct lpfc_scsi_buf * psb) } /** - * lpfc_handler_fcp_err: FCP response handler. + * lpfc_handler_fcp_err - FCP response handler * @vport: The virtual port for which this call is being executed. * @lpfc_cmd: Pointer to lpfc_scsi_buf data structure. * @rsp_iocb: The response IOCB which contains FCP error. @@ -1674,7 +1673,7 @@ lpfc_handle_fcp_err(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd, } /** - * lpfc_scsi_cmd_iocb_cmpl: Scsi cmnd IOCB completion routine. + * lpfc_scsi_cmd_iocb_cmpl - Scsi cmnd IOCB completion routine * @phba: The Hba for which this call is being executed. * @pIocbIn: The command IOCBQ for the scsi cmnd. * @pIocbOut: The response IOCBQ for the scsi cmnd . @@ -1694,10 +1693,12 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, struct lpfc_nodelist *pnode = rdata->pnode; struct scsi_cmnd *cmd = lpfc_cmd->pCmd; int result; - struct scsi_device *sdev, *tmp_sdev; + struct scsi_device *tmp_sdev; int depth = 0; unsigned long flags; struct lpfc_fast_path_event *fast_path_evt; + struct Scsi_Host *shost = cmd->device->host; + uint32_t queue_depth, scsi_id; lpfc_cmd->result = pIocbOut->iocb.un.ulpWord[4]; lpfc_cmd->status = pIocbOut->iocb.ulpStatus; @@ -1808,11 +1809,10 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, lpfc_update_stats(phba, lpfc_cmd); result = cmd->result; - sdev = cmd->device; if (vport->cfg_max_scsicmpl_time && time_after(jiffies, lpfc_cmd->start_time + msecs_to_jiffies(vport->cfg_max_scsicmpl_time))) { - spin_lock_irqsave(sdev->host->host_lock, flags); + spin_lock_irqsave(shost->host_lock, flags); if (pnode && NLP_CHK_NODE_ACT(pnode)) { if (pnode->cmd_qdepth > atomic_read(&pnode->cmd_pending) && @@ -1825,22 +1825,26 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, pnode->last_change_time = jiffies; } - spin_unlock_irqrestore(sdev->host->host_lock, flags); + spin_unlock_irqrestore(shost->host_lock, flags); } else if (pnode && NLP_CHK_NODE_ACT(pnode)) { if ((pnode->cmd_qdepth < LPFC_MAX_TGT_QDEPTH) && time_after(jiffies, pnode->last_change_time + msecs_to_jiffies(LPFC_TGTQ_INTERVAL))) { - spin_lock_irqsave(sdev->host->host_lock, flags); + spin_lock_irqsave(shost->host_lock, flags); pnode->cmd_qdepth += pnode->cmd_qdepth * LPFC_TGTQ_RAMPUP_PCENT / 100; if (pnode->cmd_qdepth > LPFC_MAX_TGT_QDEPTH) pnode->cmd_qdepth = LPFC_MAX_TGT_QDEPTH; pnode->last_change_time = jiffies; - spin_unlock_irqrestore(sdev->host->host_lock, flags); + spin_unlock_irqrestore(shost->host_lock, flags); } } lpfc_scsi_unprep_dma_buf(phba, lpfc_cmd); + + /* The sdev is not guaranteed to be valid post scsi_done upcall. */ + queue_depth = cmd->device->queue_depth; + scsi_id = cmd->device->id; cmd->scsi_done(cmd); if (phba->cfg_poll & ENABLE_FCP_RING_POLLING) { @@ -1848,28 +1852,28 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, * If there is a thread waiting for command completion * wake up the thread. */ - spin_lock_irqsave(sdev->host->host_lock, flags); + spin_lock_irqsave(shost->host_lock, flags); lpfc_cmd->pCmd = NULL; if (lpfc_cmd->waitq) wake_up(lpfc_cmd->waitq); - spin_unlock_irqrestore(sdev->host->host_lock, flags); + spin_unlock_irqrestore(shost->host_lock, flags); lpfc_release_scsi_buf(phba, lpfc_cmd); return; } if (!result) - lpfc_rampup_queue_depth(vport, sdev); + lpfc_rampup_queue_depth(vport, queue_depth); if (!result && pnode && NLP_CHK_NODE_ACT(pnode) && ((jiffies - pnode->last_ramp_up_time) > LPFC_Q_RAMP_UP_INTERVAL * HZ) && ((jiffies - pnode->last_q_full_time) > LPFC_Q_RAMP_UP_INTERVAL * HZ) && - (vport->cfg_lun_queue_depth > sdev->queue_depth)) { - shost_for_each_device(tmp_sdev, sdev->host) { + (vport->cfg_lun_queue_depth > queue_depth)) { + shost_for_each_device(tmp_sdev, shost) { if (vport->cfg_lun_queue_depth > tmp_sdev->queue_depth){ - if (tmp_sdev->id != sdev->id) + if (tmp_sdev->id != scsi_id) continue; if (tmp_sdev->ordered_tags) scsi_adjust_queue_depth(tmp_sdev, @@ -1885,7 +1889,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, } lpfc_send_sdev_queuedepth_change_event(phba, vport, pnode, 0xFFFFFFFF, - sdev->queue_depth - 1, sdev->queue_depth); + queue_depth , queue_depth + 1); } /* @@ -1896,8 +1900,8 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, NLP_CHK_NODE_ACT(pnode)) { pnode->last_q_full_time = jiffies; - shost_for_each_device(tmp_sdev, sdev->host) { - if (tmp_sdev->id != sdev->id) + shost_for_each_device(tmp_sdev, shost) { + if (tmp_sdev->id != scsi_id) continue; depth = scsi_track_queue_full(tmp_sdev, tmp_sdev->queue_depth - 1); @@ -1909,7 +1913,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, * scsi_track_queue_full. */ if (depth == -1) - depth = sdev->host->cmd_per_lun; + depth = shost->cmd_per_lun; if (depth) { lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP, @@ -1925,17 +1929,17 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, * If there is a thread waiting for command completion * wake up the thread. */ - spin_lock_irqsave(sdev->host->host_lock, flags); + spin_lock_irqsave(shost->host_lock, flags); lpfc_cmd->pCmd = NULL; if (lpfc_cmd->waitq) wake_up(lpfc_cmd->waitq); - spin_unlock_irqrestore(sdev->host->host_lock, flags); + spin_unlock_irqrestore(shost->host_lock, flags); lpfc_release_scsi_buf(phba, lpfc_cmd); } /** - * lpfc_fcpcmd_to_iocb - copy the fcp_cmd data into the IOCB. + * lpfc_fcpcmd_to_iocb - copy the fcp_cmd data into the IOCB * @data: A pointer to the immediate command data portion of the IOCB. * @fcp_cmnd: The FCP Command that is provided by the SCSI layer. * @@ -1953,7 +1957,7 @@ lpfc_fcpcmd_to_iocb(uint8_t *data, struct fcp_cmnd *fcp_cmnd) } /** - * lpfc_scsi_prep_cmnd: Routine to convert scsi cmnd to FCP information unit. + * lpfc_scsi_prep_cmnd - Routine to convert scsi cmnd to FCP information unit * @vport: The virtual port for which this call is being executed. * @lpfc_cmd: The scsi command which needs to send. * @pnode: Pointer to lpfc_nodelist. @@ -2047,7 +2051,7 @@ lpfc_scsi_prep_cmnd(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd, } /** - * lpfc_scsi_prep_task_mgmt_cmnd: Convert scsi TM cmnd to FCP information unit. + * lpfc_scsi_prep_task_mgmt_cmnd - Convert scsi TM cmnd to FCP information unit * @vport: The virtual port for which this call is being executed. * @lpfc_cmd: Pointer to lpfc_scsi_buf data structure. * @lun: Logical unit number. @@ -2110,7 +2114,7 @@ lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_vport *vport, } /** - * lpc_taskmgmt_def_cmpl: IOCB completion routine for task management command. + * lpfc_taskmgmt_def_cmpl - IOCB completion routine for task management command * @phba: The Hba for which this call is being executed. * @cmdiocbq: Pointer to lpfc_iocbq data structure. * @rspiocbq: Pointer to lpfc_iocbq data structure. @@ -2131,7 +2135,7 @@ lpfc_tskmgmt_def_cmpl(struct lpfc_hba *phba, } /** - * lpfc_scsi_tgt_reset: Target reset handler. + * lpfc_scsi_tgt_reset - Target reset handler * @lpfc_cmd: Pointer to lpfc_scsi_buf data structure * @vport: The virtual port for which this call is being executed. * @tgt_id: Target ID. @@ -2198,7 +2202,7 @@ lpfc_scsi_tgt_reset(struct lpfc_scsi_buf *lpfc_cmd, struct lpfc_vport *vport, } /** - * lpfc_info: Info entry point of scsi_host_template data structure. + * lpfc_info - Info entry point of scsi_host_template data structure * @host: The scsi host for which this call is being executed. * * This routine provides module information about hba. @@ -2236,7 +2240,7 @@ lpfc_info(struct Scsi_Host *host) } /** - * lpfc_poll_rearm_time: Routine to modify fcp_poll timer of hba. + * lpfc_poll_rearm_time - Routine to modify fcp_poll timer of hba * @phba: The Hba for which this call is being executed. * * This routine modifies fcp_poll_timer field of @phba by cfg_poll_tmo. @@ -2253,7 +2257,7 @@ static __inline__ void lpfc_poll_rearm_timer(struct lpfc_hba * phba) } /** - * lpfc_poll_start_timer: Routine to start fcp_poll_timer of HBA. + * lpfc_poll_start_timer - Routine to start fcp_poll_timer of HBA * @phba: The Hba for which this call is being executed. * * This routine starts the fcp_poll_timer of @phba. @@ -2264,7 +2268,7 @@ void lpfc_poll_start_timer(struct lpfc_hba * phba) } /** - * lpfc_poll_timeout: Restart polling timer. + * lpfc_poll_timeout - Restart polling timer * @ptr: Map to lpfc_hba data structure pointer. * * This routine restarts fcp_poll timer, when FCP ring polling is enable @@ -2283,8 +2287,7 @@ void lpfc_poll_timeout(unsigned long ptr) } /** - * lpfc_queuecommand: Queuecommand entry point of Scsi Host Templater data - * structure. + * lpfc_queuecommand - scsi_host_template queuecommand entry point * @cmnd: Pointer to scsi_cmnd data structure. * @done: Pointer to done routine. * @@ -2450,7 +2453,7 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *)) } /** - * lpfc_block_error_handler: Routine to block error handler. + * lpfc_block_error_handler - Routine to block error handler * @cmnd: Pointer to scsi_cmnd data structure. * * This routine blocks execution till fc_rport state is not FC_PORSTAT_BLCOEKD. @@ -2472,8 +2475,7 @@ lpfc_block_error_handler(struct scsi_cmnd *cmnd) } /** - * lpfc_abort_handler: Eh_abort_handler entry point of Scsi Host Template data - *structure. + * lpfc_abort_handler - scsi_host_template eh_abort_handler entry point * @cmnd: Pointer to scsi_cmnd data structure. * * This routine aborts @cmnd pending in base driver. @@ -2578,8 +2580,7 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd) } /** - * lpfc_device_reset_handler: eh_device_reset entry point of Scsi Host Template - *data structure. + * lpfc_device_reset_handler - scsi_host_template eh_device_reset entry point * @cmnd: Pointer to scsi_cmnd data structure. * * This routine does a device reset by sending a TARGET_RESET task management @@ -2587,7 +2588,7 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd) * * Return code : * 0x2003 - Error - * 0ex2002 - Success + * 0x2002 - Success **/ static int lpfc_device_reset_handler(struct scsi_cmnd *cmnd) @@ -2707,8 +2708,7 @@ lpfc_device_reset_handler(struct scsi_cmnd *cmnd) } /** - * lpfc_bus_reset_handler: eh_bus_reset_handler entry point of Scsi Host - * Template data structure. + * lpfc_bus_reset_handler - scsi_host_template eh_bus_reset_handler entry point * @cmnd: Pointer to scsi_cmnd data structure. * * This routine does target reset to all target on @cmnd->device->host. @@ -2808,8 +2808,7 @@ lpfc_bus_reset_handler(struct scsi_cmnd *cmnd) } /** - * lpfc_slave_alloc: slave_alloc entry point of Scsi Host Template data - * structure. + * lpfc_slave_alloc - scsi_host_template slave_alloc entry point * @sdev: Pointer to scsi_device. * * This routine populates the cmds_per_lun count + 2 scsi_bufs into this host's @@ -2883,8 +2882,7 @@ lpfc_slave_alloc(struct scsi_device *sdev) } /** - * lpfc_slave_configure: slave_configure entry point of Scsi Host Templater data - * structure. + * lpfc_slave_configure - scsi_host_template slave_configure entry point * @sdev: Pointer to scsi_device. * * This routine configures following items @@ -2925,7 +2923,7 @@ lpfc_slave_configure(struct scsi_device *sdev) } /** - * lpfc_slave_destroy: slave_destroy entry point of SHT data structure. + * lpfc_slave_destroy - slave_destroy entry point of SHT data structure * @sdev: Pointer to scsi_device. * * This routine sets @sdev hostatdata filed to null. diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index a36a120561e..eb5c75c45ba 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -68,7 +68,7 @@ typedef enum _lpfc_iocb_type { } lpfc_iocb_type; /** - * lpfc_cmd_iocb: Get next command iocb entry in the ring. + * lpfc_cmd_iocb - Get next command iocb entry in the ring * @phba: Pointer to HBA context object. * @pring: Pointer to driver SLI ring object. * @@ -85,7 +85,7 @@ lpfc_cmd_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) } /** - * lpfc_resp_iocb: Get next response iocb entry in the ring. + * lpfc_resp_iocb - Get next response iocb entry in the ring * @phba: Pointer to HBA context object. * @pring: Pointer to driver SLI ring object. * @@ -102,7 +102,7 @@ lpfc_resp_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) } /** - * __lpfc_sli_get_iocbq: Allocates an iocb object from iocb pool. + * __lpfc_sli_get_iocbq - Allocates an iocb object from iocb pool * @phba: Pointer to HBA context object. * * This function is called with hbalock held. This function @@ -121,7 +121,7 @@ __lpfc_sli_get_iocbq(struct lpfc_hba *phba) } /** - * lpfc_sli_get_iocbq: Allocates an iocb object from iocb pool. + * lpfc_sli_get_iocbq - Allocates an iocb object from iocb pool * @phba: Pointer to HBA context object. * * This function is called with no lock held. This function @@ -142,7 +142,7 @@ lpfc_sli_get_iocbq(struct lpfc_hba *phba) } /** - * __lpfc_sli_release_iocbq: Release iocb to the iocb pool. + * __lpfc_sli_release_iocbq - Release iocb to the iocb pool * @phba: Pointer to HBA context object. * @iocbq: Pointer to driver iocb object. * @@ -164,7 +164,7 @@ __lpfc_sli_release_iocbq(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq) } /** - * lpfc_sli_release_iocbq: Release iocb to the iocb pool. + * lpfc_sli_release_iocbq - Release iocb to the iocb pool * @phba: Pointer to HBA context object. * @iocbq: Pointer to driver iocb object. * @@ -185,8 +185,40 @@ lpfc_sli_release_iocbq(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq) } /** - * lpfc_sli_iocb_cmd_type: Get the iocb type. - * @iocb_cmnd : iocb command code. + * lpfc_sli_cancel_iocbs - Cancel all iocbs from a list. + * @phba: Pointer to HBA context object. + * @iocblist: List of IOCBs. + * @ulpstatus: ULP status in IOCB command field. + * @ulpWord4: ULP word-4 in IOCB command field. + * + * This function is called with a list of IOCBs to cancel. It cancels the IOCB + * on the list by invoking the complete callback function associated with the + * IOCB with the provided @ulpstatus and @ulpword4 set to the IOCB commond + * fields. + **/ +void +lpfc_sli_cancel_iocbs(struct lpfc_hba *phba, struct list_head *iocblist, + uint32_t ulpstatus, uint32_t ulpWord4) +{ + struct lpfc_iocbq *piocb; + + while (!list_empty(iocblist)) { + list_remove_head(iocblist, piocb, struct lpfc_iocbq, list); + + if (!piocb->iocb_cmpl) + lpfc_sli_release_iocbq(phba, piocb); + else { + piocb->iocb.ulpStatus = ulpstatus; + piocb->iocb.un.ulpWord[4] = ulpWord4; + (piocb->iocb_cmpl) (phba, piocb, piocb); + } + } + return; +} + +/** + * lpfc_sli_iocb_cmd_type - Get the iocb type + * @iocb_cmnd: iocb command code. * * This function is called by ring event handler function to get the iocb type. * This function translates the iocb command to an iocb command type used to @@ -295,7 +327,7 @@ lpfc_sli_iocb_cmd_type(uint8_t iocb_cmnd) } /** - * lpfc_sli_ring_map: Issue config_ring mbox for all rings. + * lpfc_sli_ring_map - Issue config_ring mbox for all rings * @phba: Pointer to HBA context object. * * This function is called from SLI initialization code @@ -338,7 +370,7 @@ lpfc_sli_ring_map(struct lpfc_hba *phba) } /** - * lpfc_sli_ringtxcmpl_put: Adds new iocb to the txcmplq. + * lpfc_sli_ringtxcmpl_put - Adds new iocb to the txcmplq * @phba: Pointer to HBA context object. * @pring: Pointer to driver SLI ring object. * @piocb: Pointer to the driver iocb object. @@ -370,7 +402,7 @@ lpfc_sli_ringtxcmpl_put(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, } /** - * lpfc_sli_ringtx_get: Get first element of the txq. + * lpfc_sli_ringtx_get - Get first element of the txq * @phba: Pointer to HBA context object. * @pring: Pointer to driver SLI ring object. * @@ -391,7 +423,7 @@ lpfc_sli_ringtx_get(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) } /** - * lpfc_sli_next_iocb_slot: Get next iocb slot in the ring. + * lpfc_sli_next_iocb_slot - Get next iocb slot in the ring * @phba: Pointer to HBA context object. * @pring: Pointer to driver SLI ring object. * @@ -445,7 +477,7 @@ lpfc_sli_next_iocb_slot (struct lpfc_hba *phba, struct lpfc_sli_ring *pring) } /** - * lpfc_sli_next_iotag: Get an iotag for the iocb. + * lpfc_sli_next_iotag - Get an iotag for the iocb * @phba: Pointer to HBA context object. * @iocbq: Pointer to driver iocb object. * @@ -520,7 +552,7 @@ lpfc_sli_next_iotag(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq) } /** - * lpfc_sli_submit_iocb: Submit an iocb to the firmware. + * lpfc_sli_submit_iocb - Submit an iocb to the firmware * @phba: Pointer to HBA context object. * @pring: Pointer to driver SLI ring object. * @iocb: Pointer to iocb slot in the ring. @@ -577,7 +609,7 @@ lpfc_sli_submit_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, } /** - * lpfc_sli_update_full_ring: Update the chip attention register. + * lpfc_sli_update_full_ring - Update the chip attention register * @phba: Pointer to HBA context object. * @pring: Pointer to driver SLI ring object. * @@ -608,7 +640,7 @@ lpfc_sli_update_full_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) } /** - * lpfc_sli_update_ring: Update chip attention register. + * lpfc_sli_update_ring - Update chip attention register * @phba: Pointer to HBA context object. * @pring: Pointer to driver SLI ring object. * @@ -632,7 +664,7 @@ lpfc_sli_update_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) } /** - * lpfc_sli_resume_iocb: Process iocbs in the txq. + * lpfc_sli_resume_iocb - Process iocbs in the txq * @phba: Pointer to HBA context object. * @pring: Pointer to driver SLI ring object. * @@ -672,7 +704,7 @@ lpfc_sli_resume_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) } /** - * lpfc_sli_next_hbq_slot: Get next hbq entry for the HBQ. + * lpfc_sli_next_hbq_slot - Get next hbq entry for the HBQ * @phba: Pointer to HBA context object. * @hbqno: HBQ number. * @@ -717,7 +749,7 @@ lpfc_sli_next_hbq_slot(struct lpfc_hba *phba, uint32_t hbqno) } /** - * lpfc_sli_hbqbuf_free_all: Free all the hbq buffers. + * lpfc_sli_hbqbuf_free_all - Free all the hbq buffers * @phba: Pointer to HBA context object. * * This function is called with no lock held to free all the @@ -771,7 +803,7 @@ lpfc_sli_hbqbuf_free_all(struct lpfc_hba *phba) } /** - * lpfc_sli_hbq_to_firmware: Post the hbq buffer to firmware. + * lpfc_sli_hbq_to_firmware - Post the hbq buffer to firmware * @phba: Pointer to HBA context object. * @hbqno: HBQ number. * @hbq_buf: Pointer to HBQ buffer. @@ -818,8 +850,8 @@ static struct lpfc_hbq_init lpfc_els_hbq = { .profile = 0, .ring_mask = (1 << LPFC_ELS_RING), .buffer_count = 0, - .init_count = 20, - .add_count = 5, + .init_count = 40, + .add_count = 40, }; /* HBQ for the extra ring if needed */ @@ -841,7 +873,7 @@ struct lpfc_hbq_init *lpfc_hbq_defs[] = { }; /** - * lpfc_sli_hbqbuf_fill_hbqs: Post more hbq buffers to HBQ. + * lpfc_sli_hbqbuf_fill_hbqs - Post more hbq buffers to HBQ * @phba: Pointer to HBA context object. * @hbqno: HBQ number. * @count: Number of HBQ buffers to be posted. @@ -901,7 +933,7 @@ err: } /** - * lpfc_sli_hbqbuf_add_hbqs: Post more HBQ buffers to firmware. + * lpfc_sli_hbqbuf_add_hbqs - Post more HBQ buffers to firmware * @phba: Pointer to HBA context object. * @qno: HBQ number. * @@ -917,7 +949,7 @@ lpfc_sli_hbqbuf_add_hbqs(struct lpfc_hba *phba, uint32_t qno) } /** - * lpfc_sli_hbqbuf_init_hbqs: Post initial buffers to the HBQ. + * lpfc_sli_hbqbuf_init_hbqs - Post initial buffers to the HBQ * @phba: Pointer to HBA context object. * @qno: HBQ queue number. * @@ -933,7 +965,7 @@ lpfc_sli_hbqbuf_init_hbqs(struct lpfc_hba *phba, uint32_t qno) } /** - * lpfc_sli_hbqbuf_find: Find the hbq buffer associated with a tag. + * lpfc_sli_hbqbuf_find - Find the hbq buffer associated with a tag * @phba: Pointer to HBA context object. * @tag: Tag of the hbq buffer. * @@ -966,7 +998,7 @@ lpfc_sli_hbqbuf_find(struct lpfc_hba *phba, uint32_t tag) } /** - * lpfc_sli_free_hbq: Give back the hbq buffer to firmware. + * lpfc_sli_free_hbq - Give back the hbq buffer to firmware * @phba: Pointer to HBA context object. * @hbq_buffer: Pointer to HBQ buffer. * @@ -988,7 +1020,7 @@ lpfc_sli_free_hbq(struct lpfc_hba *phba, struct hbq_dmabuf *hbq_buffer) } /** - * lpfc_sli_chk_mbx_command: Check if the mailbox is a legitimate mailbox. + * lpfc_sli_chk_mbx_command - Check if the mailbox is a legitimate mailbox * @mbxCommand: mailbox command code. * * This function is called by the mailbox event handler function to verify @@ -1064,8 +1096,7 @@ lpfc_sli_chk_mbx_command(uint8_t mbxCommand) } /** - * lpfc_sli_wake_mbox_wait: Completion handler for mbox issued from - * lpfc_sli_issue_mbox_wait. + * lpfc_sli_wake_mbox_wait - lpfc_sli_issue_mbox_wait mbox completion handler * @phba: Pointer to HBA context object. * @pmboxq: Pointer to mailbox command. * @@ -1096,7 +1127,7 @@ lpfc_sli_wake_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq) /** - * lpfc_sli_def_mbox_cmpl: Default mailbox completion handler. + * lpfc_sli_def_mbox_cmpl - Default mailbox completion handler * @phba: Pointer to HBA context object. * @pmb: Pointer to mailbox object. * @@ -1140,7 +1171,7 @@ lpfc_sli_def_mbox_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) } /** - * lpfc_sli_handle_mb_event: Handle mailbox completions from firmware. + * lpfc_sli_handle_mb_event - Handle mailbox completions from firmware * @phba: Pointer to HBA context object. * * This function is called with no lock held. This function processes all @@ -1260,7 +1291,7 @@ lpfc_sli_handle_mb_event(struct lpfc_hba *phba) } /** - * lpfc_sli_get_buff: Get the buffer associated with the buffer tag. + * lpfc_sli_get_buff - Get the buffer associated with the buffer tag * @phba: Pointer to HBA context object. * @pring: Pointer to driver SLI ring object. * @tag: buffer tag. @@ -1288,7 +1319,7 @@ lpfc_sli_get_buff(struct lpfc_hba *phba, /** - * lpfc_sli_process_unsol_iocb: Unsolicited iocb handler. + * lpfc_sli_process_unsol_iocb - Unsolicited iocb handler * @phba: Pointer to HBA context object. * @pring: Pointer to driver SLI ring object. * @saveq: Pointer to the unsolicited iocb. @@ -1484,7 +1515,7 @@ lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, } /** - * lpfc_sli_iocbq_lookup: Find command iocb for the given response iocb. + * lpfc_sli_iocbq_lookup - Find command iocb for the given response iocb * @phba: Pointer to HBA context object. * @pring: Pointer to driver SLI ring object. * @prspiocb: Pointer to response iocb object. @@ -1521,7 +1552,7 @@ lpfc_sli_iocbq_lookup(struct lpfc_hba *phba, } /** - * lpfc_sli_process_sol_iocb: process solicited iocb completion. + * lpfc_sli_process_sol_iocb - process solicited iocb completion * @phba: Pointer to HBA context object. * @pring: Pointer to driver SLI ring object. * @saveq: Pointer to the response iocb to be processed. @@ -1597,7 +1628,7 @@ lpfc_sli_process_sol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, * Ring <ringno> handler: unexpected completion IoTag * <IoTag> */ - lpfc_printf_vlog(cmdiocbp->vport, KERN_WARNING, LOG_SLI, + lpfc_printf_log(phba, KERN_WARNING, LOG_SLI, "0322 Ring %d handler: " "unexpected completion IoTag x%x " "Data: x%x x%x x%x x%x\n", @@ -1614,7 +1645,7 @@ lpfc_sli_process_sol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, } /** - * lpfc_sli_rsp_pointers_error: Response ring pointer error handler. + * lpfc_sli_rsp_pointers_error - Response ring pointer error handler * @phba: Pointer to HBA context object. * @pring: Pointer to driver SLI ring object. * @@ -1652,7 +1683,7 @@ lpfc_sli_rsp_pointers_error(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) } /** - * lpfc_poll_eratt: Error attention polling timer timeout handler. + * lpfc_poll_eratt - Error attention polling timer timeout handler * @ptr: Pointer to address of HBA context object. * * This function is invoked by the Error Attention polling timer when the @@ -1682,7 +1713,7 @@ void lpfc_poll_eratt(unsigned long ptr) } /** - * lpfc_sli_poll_fcp_ring: Handle FCP ring completion in polling mode. + * lpfc_sli_poll_fcp_ring - Handle FCP ring completion in polling mode * @phba: Pointer to HBA context object. * * This function is called from lpfc_queuecommand, lpfc_poll_timeout, @@ -1845,7 +1876,7 @@ void lpfc_sli_poll_fcp_ring(struct lpfc_hba *phba) } /** - * lpfc_sli_handle_fast_ring_event: Handle ring events on FCP ring. + * lpfc_sli_handle_fast_ring_event - Handle ring events on FCP ring * @phba: Pointer to HBA context object. * @pring: Pointer to driver SLI ring object. * @mask: Host attention register mask for this ring. @@ -2037,7 +2068,7 @@ lpfc_sli_handle_fast_ring_event(struct lpfc_hba *phba, } /** - * lpfc_sli_handle_slow_ring_event: Handle ring events for non-FCP rings. + * lpfc_sli_handle_slow_ring_event - Handle ring events for non-FCP rings * @phba: Pointer to HBA context object. * @pring: Pointer to driver SLI ring object. * @mask: Host attention register mask for this ring. @@ -2311,7 +2342,7 @@ lpfc_sli_handle_slow_ring_event(struct lpfc_hba *phba, } /** - * lpfc_sli_abort_iocb_ring: Abort all iocbs in the ring. + * lpfc_sli_abort_iocb_ring - Abort all iocbs in the ring * @phba: Pointer to HBA context object. * @pring: Pointer to driver SLI ring object. * @@ -2325,7 +2356,6 @@ lpfc_sli_abort_iocb_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) { LIST_HEAD(completions); struct lpfc_iocbq *iocb, *next_iocb; - IOCB_t *cmd = NULL; if (pring->ringno == LPFC_ELS_RING) { lpfc_fabric_abort_hba(phba); @@ -2344,23 +2374,13 @@ lpfc_sli_abort_iocb_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) spin_unlock_irq(&phba->hbalock); - while (!list_empty(&completions)) { - iocb = list_get_first(&completions, struct lpfc_iocbq, list); - cmd = &iocb->iocb; - list_del_init(&iocb->list); - - if (!iocb->iocb_cmpl) - lpfc_sli_release_iocbq(phba, iocb); - else { - cmd->ulpStatus = IOSTAT_LOCAL_REJECT; - cmd->un.ulpWord[4] = IOERR_SLI_ABORTED; - (iocb->iocb_cmpl) (phba, iocb, iocb); - } - } + /* Cancel all the IOCBs from the completions list */ + lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT, + IOERR_SLI_ABORTED); } /** - * lpfc_sli_flush_fcp_rings: flush all iocbs in the fcp ring. + * lpfc_sli_flush_fcp_rings - flush all iocbs in the fcp ring * @phba: Pointer to HBA context object. * * This function flushes all iocbs in the fcp ring and frees all the iocb @@ -2374,8 +2394,6 @@ lpfc_sli_flush_fcp_rings(struct lpfc_hba *phba) { LIST_HEAD(txq); LIST_HEAD(txcmplq); - struct lpfc_iocbq *iocb; - IOCB_t *cmd = NULL; struct lpfc_sli *psli = &phba->sli; struct lpfc_sli_ring *pring; @@ -2393,38 +2411,16 @@ lpfc_sli_flush_fcp_rings(struct lpfc_hba *phba) spin_unlock_irq(&phba->hbalock); /* Flush the txq */ - while (!list_empty(&txq)) { - iocb = list_get_first(&txq, struct lpfc_iocbq, list); - cmd = &iocb->iocb; - list_del_init(&iocb->list); - - if (!iocb->iocb_cmpl) - lpfc_sli_release_iocbq(phba, iocb); - else { - cmd->ulpStatus = IOSTAT_LOCAL_REJECT; - cmd->un.ulpWord[4] = IOERR_SLI_DOWN; - (iocb->iocb_cmpl) (phba, iocb, iocb); - } - } + lpfc_sli_cancel_iocbs(phba, &txq, IOSTAT_LOCAL_REJECT, + IOERR_SLI_DOWN); /* Flush the txcmpq */ - while (!list_empty(&txcmplq)) { - iocb = list_get_first(&txcmplq, struct lpfc_iocbq, list); - cmd = &iocb->iocb; - list_del_init(&iocb->list); - - if (!iocb->iocb_cmpl) - lpfc_sli_release_iocbq(phba, iocb); - else { - cmd->ulpStatus = IOSTAT_LOCAL_REJECT; - cmd->un.ulpWord[4] = IOERR_SLI_DOWN; - (iocb->iocb_cmpl) (phba, iocb, iocb); - } - } + lpfc_sli_cancel_iocbs(phba, &txcmplq, IOSTAT_LOCAL_REJECT, + IOERR_SLI_DOWN); } /** - * lpfc_sli_brdready: Check for host status bits. + * lpfc_sli_brdready - Check for host status bits * @phba: Pointer to HBA context object. * @mask: Bit mask to be checked. * @@ -2484,7 +2480,7 @@ lpfc_sli_brdready(struct lpfc_hba *phba, uint32_t mask) #define BARRIER_TEST_PATTERN (0xdeadbeef) /** - * lpfc_reset_barrier: Make HBA ready for HBA reset. + * lpfc_reset_barrier - Make HBA ready for HBA reset * @phba: Pointer to HBA context object. * * This function is called before resetting an HBA. This @@ -2564,7 +2560,7 @@ restore_hc: } /** - * lpfc_sli_brdkill: Issue a kill_board mailbox command. + * lpfc_sli_brdkill - Issue a kill_board mailbox command * @phba: Pointer to HBA context object. * * This function issues a kill_board mailbox command and waits for @@ -2651,7 +2647,7 @@ lpfc_sli_brdkill(struct lpfc_hba *phba) } /** - * lpfc_sli_brdreset: Reset the HBA. + * lpfc_sli_brdreset - Reset the HBA * @phba: Pointer to HBA context object. * * This function resets the HBA by writing HC_INITFF to the control @@ -2714,7 +2710,7 @@ lpfc_sli_brdreset(struct lpfc_hba *phba) } /** - * lpfc_sli_brdrestart: Restart the HBA. + * lpfc_sli_brdrestart - Restart the HBA * @phba: Pointer to HBA context object. * * This function is called in the SLI initialization code path to @@ -2781,7 +2777,7 @@ lpfc_sli_brdrestart(struct lpfc_hba *phba) } /** - * lpfc_sli_chipset_init: Wait for the restart of the HBA after a restart. + * lpfc_sli_chipset_init - Wait for the restart of the HBA after a restart * @phba: Pointer to HBA context object. * * This function is called after a HBA restart to wait for successful @@ -2876,7 +2872,7 @@ lpfc_sli_chipset_init(struct lpfc_hba *phba) } /** - * lpfc_sli_hbq_count: Get the number of HBQs to be configured. + * lpfc_sli_hbq_count - Get the number of HBQs to be configured * * This function calculates and returns the number of HBQs required to be * configured. @@ -2888,7 +2884,7 @@ lpfc_sli_hbq_count(void) } /** - * lpfc_sli_hbq_entry_count: Calculate total number of hbq entries. + * lpfc_sli_hbq_entry_count - Calculate total number of hbq entries * * This function adds the number of hbq entries in every HBQ to get * the total number of hbq entries required for the HBA and returns @@ -2907,7 +2903,7 @@ lpfc_sli_hbq_entry_count(void) } /** - * lpfc_sli_hbq_size: Calculate memory required for all hbq entries. + * lpfc_sli_hbq_size - Calculate memory required for all hbq entries * * This function calculates amount of memory required for all hbq entries * to be configured and returns the total memory required. @@ -2919,7 +2915,7 @@ lpfc_sli_hbq_size(void) } /** - * lpfc_sli_hbq_setup: configure and initialize HBQs. + * lpfc_sli_hbq_setup - configure and initialize HBQs * @phba: Pointer to HBA context object. * * This function is called during the SLI initialization to configure @@ -2988,7 +2984,7 @@ lpfc_sli_hbq_setup(struct lpfc_hba *phba) } /** - * lpfc_sli_config_port: Issue config port mailbox command. + * lpfc_sli_config_port - Issue config port mailbox command * @phba: Pointer to HBA context object. * @sli_mode: sli mode - 2/3 * @@ -3114,7 +3110,7 @@ do_prep_failed: /** - * lpfc_sli_hba_setup: SLI intialization function. + * lpfc_sli_hba_setup - SLI intialization function * @phba: Pointer to HBA context object. * * This function is the main SLI intialization function. This function @@ -3206,7 +3202,7 @@ lpfc_sli_hba_setup_error: /** - * lpfc_mbox_timeout: Timeout call back function for mbox timer. + * lpfc_mbox_timeout - Timeout call back function for mbox timer * @ptr: context object - pointer to hba structure. * * This is the callback function for mailbox timer. The mailbox @@ -3237,7 +3233,7 @@ lpfc_mbox_timeout(unsigned long ptr) /** - * lpfc_mbox_timeout_handler: Worker thread function to handle mailbox timeout. + * lpfc_mbox_timeout_handler - Worker thread function to handle mailbox timeout * @phba: Pointer to HBA context object. * * This function is called from worker thread when a mailbox command times out. @@ -3252,6 +3248,21 @@ lpfc_mbox_timeout_handler(struct lpfc_hba *phba) struct lpfc_sli *psli = &phba->sli; struct lpfc_sli_ring *pring; + /* Check the pmbox pointer first. There is a race condition + * between the mbox timeout handler getting executed in the + * worklist and the mailbox actually completing. When this + * race condition occurs, the mbox_active will be NULL. + */ + spin_lock_irq(&phba->hbalock); + if (pmbox == NULL) { + lpfc_printf_log(phba, KERN_WARNING, + LOG_MBOX | LOG_SLI, + "0353 Active Mailbox cleared - mailbox timeout " + "exiting\n"); + spin_unlock_irq(&phba->hbalock); + return; + } + /* Mbox cmd <mbxCommand> timeout */ lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI, "0310 Mailbox command x%x timeout Data: x%x x%x x%p\n", @@ -3259,6 +3270,7 @@ lpfc_mbox_timeout_handler(struct lpfc_hba *phba) phba->pport->port_state, phba->sli.sli_flag, phba->sli.mbox_active); + spin_unlock_irq(&phba->hbalock); /* Setting state unknown so lpfc_sli_abort_iocb_ring * would get IOCB_ERROR from lpfc_sli_issue_iocb, allowing @@ -3295,7 +3307,7 @@ lpfc_mbox_timeout_handler(struct lpfc_hba *phba) } /** - * lpfc_sli_issue_mbox: Issue a mailbox command to firmware. + * lpfc_sli_issue_mbox - Issue a mailbox command to firmware * @phba: Pointer to HBA context object. * @pmbox: Pointer to mailbox object. * @flag: Flag indicating how the mailbox need to be processed. @@ -3365,6 +3377,12 @@ lpfc_sli_issue_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, uint32_t flag) goto out_not_finished; } + /* If HBA has a deferred error attention, fail the iocb. */ + if (unlikely(phba->hba_flag & DEFER_ERATT)) { + spin_unlock_irqrestore(&phba->hbalock, drvr_flag); + goto out_not_finished; + } + psli = &phba->sli; mb = &pmbox->mb; @@ -3632,7 +3650,7 @@ out_not_finished: } /** - * __lpfc_sli_ringtx_put: Add an iocb to the txq. + * __lpfc_sli_ringtx_put - Add an iocb to the txq * @phba: Pointer to HBA context object. * @pring: Pointer to driver SLI ring object. * @piocb: Pointer to address of newly added command iocb. @@ -3651,7 +3669,7 @@ __lpfc_sli_ringtx_put(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, } /** - * lpfc_sli_next_iocb: Get the next iocb in the txq. + * lpfc_sli_next_iocb - Get the next iocb in the txq * @phba: Pointer to HBA context object. * @pring: Pointer to driver SLI ring object. * @piocb: Pointer to address of newly added command iocb. @@ -3683,7 +3701,7 @@ lpfc_sli_next_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, } /** - * __lpfc_sli_issue_iocb: Lockless version of lpfc_sli_issue_iocb. + * __lpfc_sli_issue_iocb - Lockless version of lpfc_sli_issue_iocb * @phba: Pointer to HBA context object. * @pring: Pointer to driver SLI ring object. * @piocb: Pointer to command iocb. @@ -3729,6 +3747,10 @@ __lpfc_sli_issue_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, if (unlikely(pci_channel_offline(phba->pcidev))) return IOCB_ERROR; + /* If HBA has a deferred error attention, fail the iocb. */ + if (unlikely(phba->hba_flag & DEFER_ERATT)) + return IOCB_ERROR; + /* * We should never get an IOCB if we are in a < LINK_DOWN state */ @@ -3813,7 +3835,7 @@ __lpfc_sli_issue_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, /** - * lpfc_sli_issue_iocb: Wrapper function for __lpfc_sli_issue_iocb. + * lpfc_sli_issue_iocb - Wrapper function for __lpfc_sli_issue_iocb * @phba: Pointer to HBA context object. * @pring: Pointer to driver SLI ring object. * @piocb: Pointer to command iocb. @@ -3840,7 +3862,7 @@ lpfc_sli_issue_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, } /** - * lpfc_extra_ring_setup: Extra ring setup function. + * lpfc_extra_ring_setup - Extra ring setup function * @phba: Pointer to HBA context object. * * This function is called while driver attaches with the @@ -3886,7 +3908,7 @@ lpfc_extra_ring_setup( struct lpfc_hba *phba) } /** - * lpfc_sli_async_event_handler: ASYNC iocb handler function. + * lpfc_sli_async_event_handler - ASYNC iocb handler function * @phba: Pointer to HBA context object. * @pring: Pointer to driver SLI ring object. * @iocbq: Pointer to iocb object. @@ -3907,6 +3929,7 @@ lpfc_sli_async_event_handler(struct lpfc_hba * phba, uint16_t temp; struct temp_event temp_event_data; struct Scsi_Host *shost; + uint32_t *iocb_w; icmd = &iocbq->iocb; evt_code = icmd->un.asyncstat.evt_code; @@ -3914,13 +3937,23 @@ lpfc_sli_async_event_handler(struct lpfc_hba * phba, if ((evt_code != ASYNC_TEMP_WARN) && (evt_code != ASYNC_TEMP_SAFE)) { + iocb_w = (uint32_t *) icmd; lpfc_printf_log(phba, KERN_ERR, LOG_SLI, "0346 Ring %d handler: unexpected ASYNC_STATUS" - " evt_code 0x%x\n", + " evt_code 0x%x \n" + "W0 0x%08x W1 0x%08x W2 0x%08x W3 0x%08x\n" + "W4 0x%08x W5 0x%08x W6 0x%08x W7 0x%08x\n" + "W8 0x%08x W9 0x%08x W10 0x%08x W11 0x%08x\n" + "W12 0x%08x W13 0x%08x W14 0x%08x W15 0x%08x\n", pring->ringno, - icmd->un.asyncstat.evt_code); + icmd->un.asyncstat.evt_code, + iocb_w[0], iocb_w[1], iocb_w[2], iocb_w[3], + iocb_w[4], iocb_w[5], iocb_w[6], iocb_w[7], + iocb_w[8], iocb_w[9], iocb_w[10], iocb_w[11], + iocb_w[12], iocb_w[13], iocb_w[14], iocb_w[15]); + return; } temp_event_data.data = (uint32_t)temp; @@ -3954,7 +3987,7 @@ lpfc_sli_async_event_handler(struct lpfc_hba * phba, /** - * lpfc_sli_setup: SLI ring setup function. + * lpfc_sli_setup - SLI ring setup function * @phba: Pointer to HBA context object. * * lpfc_sli_setup sets up rings of the SLI interface with @@ -4076,7 +4109,7 @@ lpfc_sli_setup(struct lpfc_hba *phba) } /** - * lpfc_sli_queue_setup: Queue initialization function. + * lpfc_sli_queue_setup - Queue initialization function * @phba: Pointer to HBA context object. * * lpfc_sli_queue_setup sets up mailbox queues and iocb queues for each @@ -4115,7 +4148,7 @@ lpfc_sli_queue_setup(struct lpfc_hba *phba) } /** - * lpfc_sli_host_down: Vport cleanup function. + * lpfc_sli_host_down - Vport cleanup function * @vport: Pointer to virtual port object. * * lpfc_sli_host_down is called to clean up the resources @@ -4179,22 +4212,14 @@ lpfc_sli_host_down(struct lpfc_vport *vport) spin_unlock_irqrestore(&phba->hbalock, flags); - while (!list_empty(&completions)) { - list_remove_head(&completions, iocb, struct lpfc_iocbq, list); - - if (!iocb->iocb_cmpl) - lpfc_sli_release_iocbq(phba, iocb); - else { - iocb->iocb.ulpStatus = IOSTAT_LOCAL_REJECT; - iocb->iocb.un.ulpWord[4] = IOERR_SLI_DOWN; - (iocb->iocb_cmpl) (phba, iocb, iocb); - } - } + /* Cancel all the IOCBs from the completions list */ + lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT, + IOERR_SLI_DOWN); return 1; } /** - * lpfc_sli_hba_down: Resource cleanup function for the HBA. + * lpfc_sli_hba_down - Resource cleanup function for the HBA * @phba: Pointer to HBA context object. * * This function cleans up all iocb, buffers, mailbox commands @@ -4216,8 +4241,6 @@ lpfc_sli_hba_down(struct lpfc_hba *phba) struct lpfc_sli_ring *pring; struct lpfc_dmabuf *buf_ptr; LPFC_MBOXQ_t *pmb; - struct lpfc_iocbq *iocb; - IOCB_t *cmd = NULL; int i; unsigned long flags = 0; @@ -4245,18 +4268,9 @@ lpfc_sli_hba_down(struct lpfc_hba *phba) } spin_unlock_irqrestore(&phba->hbalock, flags); - while (!list_empty(&completions)) { - list_remove_head(&completions, iocb, struct lpfc_iocbq, list); - cmd = &iocb->iocb; - - if (!iocb->iocb_cmpl) - lpfc_sli_release_iocbq(phba, iocb); - else { - cmd->ulpStatus = IOSTAT_LOCAL_REJECT; - cmd->un.ulpWord[4] = IOERR_SLI_DOWN; - (iocb->iocb_cmpl) (phba, iocb, iocb); - } - } + /* Cancel all the IOCBs from the completions list */ + lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT, + IOERR_SLI_DOWN); spin_lock_irqsave(&phba->hbalock, flags); list_splice_init(&phba->elsbuf, &completions); @@ -4299,7 +4313,7 @@ lpfc_sli_hba_down(struct lpfc_hba *phba) } /** - * lpfc_sli_pcimem_bcopy: SLI memory copy function. + * lpfc_sli_pcimem_bcopy - SLI memory copy function * @srcp: Source memory pointer. * @destp: Destination memory pointer. * @cnt: Number of words required to be copied. @@ -4329,7 +4343,7 @@ lpfc_sli_pcimem_bcopy(void *srcp, void *destp, uint32_t cnt) /** - * lpfc_sli_ringpostbuf_put: Function to add a buffer to postbufq. + * lpfc_sli_ringpostbuf_put - Function to add a buffer to postbufq * @phba: Pointer to HBA context object. * @pring: Pointer to driver SLI ring object. * @mp: Pointer to driver buffer object. @@ -4352,8 +4366,7 @@ lpfc_sli_ringpostbuf_put(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, } /** - * lpfc_sli_get_buffer_tag: Tag allocation function for a buffer posted - * using CMD_QUE_XRI64_CX iocb. + * lpfc_sli_get_buffer_tag - allocates a tag for a CMD_QUE_XRI64_CX buffer * @phba: Pointer to HBA context object. * * When HBQ is enabled, buffers are searched based on tags. This function @@ -4378,8 +4391,7 @@ lpfc_sli_get_buffer_tag(struct lpfc_hba *phba) } /** - * lpfc_sli_ring_taggedbuf_get: Search HBQ buffer associated with - * posted using CMD_QUE_XRI64_CX iocb. + * lpfc_sli_ring_taggedbuf_get - find HBQ buffer associated with given tag * @phba: Pointer to HBA context object. * @pring: Pointer to driver SLI ring object. * @tag: Buffer tag. @@ -4422,8 +4434,7 @@ lpfc_sli_ring_taggedbuf_get(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, } /** - * lpfc_sli_ringpostbuf_get: SLI2 buffer search function for - * unsolicited ct and els events. + * lpfc_sli_ringpostbuf_get - search buffers for unsolicited CT and ELS events * @phba: Pointer to HBA context object. * @pring: Pointer to driver SLI ring object. * @phys: DMA address of the buffer. @@ -4466,7 +4477,7 @@ lpfc_sli_ringpostbuf_get(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, } /** - * lpfc_sli_abort_els_cmpl: Completion handler for the els abort iocbs. + * lpfc_sli_abort_els_cmpl - Completion handler for the els abort iocbs * @phba: Pointer to HBA context object. * @cmdiocb: Pointer to driver command iocb object. * @rspiocb: Pointer to driver response iocb object. @@ -4542,7 +4553,7 @@ lpfc_sli_abort_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, } /** - * lpfc_ignore_els_cmpl: Completion handler for aborted ELS command. + * lpfc_ignore_els_cmpl - Completion handler for aborted ELS command * @phba: Pointer to HBA context object. * @cmdiocb: Pointer to driver command iocb object. * @rspiocb: Pointer to driver response iocb object. @@ -4572,7 +4583,7 @@ lpfc_ignore_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, } /** - * lpfc_sli_issue_abort_iotag: Abort function for a command iocb. + * lpfc_sli_issue_abort_iotag - Abort function for a command iocb * @phba: Pointer to HBA context object. * @pring: Pointer to driver SLI ring object. * @cmdiocb: Pointer to driver command iocb object. @@ -4658,15 +4669,14 @@ abort_iotag_exit: } /** - * lpfc_sli_validate_fcp_iocb: Filtering function, used to find commands - * associated with a vport/SCSI target/lun. + * lpfc_sli_validate_fcp_iocb - find commands associated with a vport or LUN * @iocbq: Pointer to driver iocb object. * @vport: Pointer to driver virtual port object. * @tgt_id: SCSI ID of the target. * @lun_id: LUN ID of the scsi device. * @ctx_cmd: LPFC_CTX_LUN/LPFC_CTX_TGT/LPFC_CTX_HOST * - * This function acts as iocb filter for functions which abort or count + * This function acts as an iocb filter for functions which abort or count * all FCP iocbs pending on a lun/SCSI target/SCSI host. It will return * 0 if the filtering criteria is met for the given iocb and will return * 1 if the filtering criteria is not met. @@ -4724,7 +4734,7 @@ lpfc_sli_validate_fcp_iocb(struct lpfc_iocbq *iocbq, struct lpfc_vport *vport, } /** - * lpfc_sli_sum_iocb: Function to count the number of FCP iocbs pending. + * lpfc_sli_sum_iocb - Function to count the number of FCP iocbs pending * @vport: Pointer to virtual port. * @tgt_id: SCSI ID of the target. * @lun_id: LUN ID of the scsi device. @@ -4762,8 +4772,7 @@ lpfc_sli_sum_iocb(struct lpfc_vport *vport, uint16_t tgt_id, uint64_t lun_id, } /** - * lpfc_sli_abort_fcp_cmpl: Completion handler function for an aborted - * FCP iocb. + * lpfc_sli_abort_fcp_cmpl - Completion handler function for aborted FCP IOCBs * @phba: Pointer to HBA context object * @cmdiocb: Pointer to command iocb object. * @rspiocb: Pointer to response iocb object. @@ -4781,8 +4790,7 @@ lpfc_sli_abort_fcp_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, } /** - * lpfc_sli_abort_iocb: This function issue abort for all SCSI commands - * pending on a SCSI host(vport)/target/lun. + * lpfc_sli_abort_iocb - issue abort for all commands on a host/target/LUN * @vport: Pointer to virtual port. * @pring: Pointer to driver SLI ring object. * @tgt_id: SCSI ID of the target. @@ -4854,8 +4862,7 @@ lpfc_sli_abort_iocb(struct lpfc_vport *vport, struct lpfc_sli_ring *pring, } /** - * lpfc_sli_wake_iocb_wait: iocb completion handler for iocb issued using - * lpfc_sli_issue_iocb_wait. + * lpfc_sli_wake_iocb_wait - lpfc_sli_issue_iocb_wait's completion handler * @phba: Pointer to HBA context object. * @cmdiocbq: Pointer to command iocb. * @rspiocbq: Pointer to response iocb. @@ -4893,7 +4900,7 @@ lpfc_sli_wake_iocb_wait(struct lpfc_hba *phba, } /** - * lpfc_sli_issue_iocb_wait: Synchronous function to issue iocb commands. + * lpfc_sli_issue_iocb_wait - Synchronous function to issue iocb commands * @phba: Pointer to HBA context object.. * @pring: Pointer to sli ring. * @piocb: Pointer to command iocb. @@ -5000,7 +5007,7 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba *phba, } /** - * lpfc_sli_issue_mbox_wait: Synchronous function to issue mailbox. + * lpfc_sli_issue_mbox_wait - Synchronous function to issue mailbox * @phba: Pointer to HBA context object. * @pmboxq: Pointer to driver mailbox object. * @timeout: Timeout in number of seconds. @@ -5070,7 +5077,7 @@ lpfc_sli_issue_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq, } /** - * lpfc_sli_flush_mbox_queue: mailbox queue cleanup function. + * lpfc_sli_flush_mbox_queue - mailbox queue cleanup function * @phba: Pointer to HBA context. * * This function is called to cleanup any pending mailbox @@ -5113,7 +5120,7 @@ lpfc_sli_flush_mbox_queue(struct lpfc_hba * phba) } /** - * lpfc_sli_check_eratt: check error attention events + * lpfc_sli_check_eratt - check error attention events * @phba: Pointer to HBA context. * * This function is called form timer soft interrupt context to check HBA's @@ -5145,11 +5152,31 @@ lpfc_sli_check_eratt(struct lpfc_hba *phba) return 0; } + /* + * If there is deferred error attention, do not check for error + * attention + */ + if (unlikely(phba->hba_flag & DEFER_ERATT)) { + spin_unlock_irq(&phba->hbalock); + return 0; + } + /* Read chip Host Attention (HA) register */ ha_copy = readl(phba->HAregaddr); if (ha_copy & HA_ERATT) { /* Read host status register to retrieve error event */ lpfc_sli_read_hs(phba); + + /* Check if there is a deferred error condition is active */ + if ((HS_FFER1 & phba->work_hs) && + ((HS_FFER2 | HS_FFER3 | HS_FFER4 | HS_FFER5 | + HS_FFER6 | HS_FFER7) & phba->work_hs)) { + phba->hba_flag |= DEFER_ERATT; + /* Clear all interrupt enable conditions */ + writel(0, phba->HCregaddr); + readl(phba->HCregaddr); + } + /* Set the driver HA work bitmap */ phba->work_ha |= HA_ERATT; /* Indicate polling handles this ERATT */ @@ -5162,7 +5189,7 @@ lpfc_sli_check_eratt(struct lpfc_hba *phba) } /** - * lpfc_sp_intr_handler: The slow-path interrupt handler of lpfc driver. + * lpfc_sp_intr_handler - The slow-path interrupt handler of lpfc driver * @irq: Interrupt number. * @dev_id: The device context pointer. * @@ -5238,6 +5265,16 @@ lpfc_sp_intr_handler(int irq, void *dev_id) /* Indicate interrupt handler handles ERATT */ phba->hba_flag |= HBA_ERATT_HANDLED; } + + /* + * If there is deferred error attention, do not check for any + * interrupt. + */ + if (unlikely(phba->hba_flag & DEFER_ERATT)) { + spin_unlock_irq(&phba->hbalock); + return IRQ_NONE; + } + /* Clear up only attention source related to slow-path */ writel((ha_copy & (HA_MBATT | HA_R2_CLR_MSK)), phba->HAregaddr); @@ -5309,8 +5346,22 @@ lpfc_sp_intr_handler(int irq, void *dev_id) } } spin_lock_irqsave(&phba->hbalock, iflag); - if (work_ha_copy & HA_ERATT) + if (work_ha_copy & HA_ERATT) { lpfc_sli_read_hs(phba); + /* + * Check if there is a deferred error condition + * is active + */ + if ((HS_FFER1 & phba->work_hs) && + ((HS_FFER2 | HS_FFER3 | HS_FFER4 | HS_FFER5 | + HS_FFER6 | HS_FFER7) & phba->work_hs)) { + phba->hba_flag |= DEFER_ERATT; + /* Clear all interrupt enable conditions */ + writel(0, phba->HCregaddr); + readl(phba->HCregaddr); + } + } + if ((work_ha_copy & HA_MBATT) && (phba->sli.mbox_active)) { pmb = phba->sli.mbox_active; pmbox = &pmb->mb; @@ -5423,7 +5474,7 @@ send_current_mbox: } /* lpfc_sp_intr_handler */ /** - * lpfc_fp_intr_handler: The fast-path interrupt handler of lpfc driver. + * lpfc_fp_intr_handler - The fast-path interrupt handler of lpfc driver * @irq: Interrupt number. * @dev_id: The device context pointer. * @@ -5474,6 +5525,14 @@ lpfc_fp_intr_handler(int irq, void *dev_id) ha_copy = readl(phba->HAregaddr); /* Clear up only attention source related to fast-path */ spin_lock_irqsave(&phba->hbalock, iflag); + /* + * If there is deferred error attention, do not check for + * any interrupt. + */ + if (unlikely(phba->hba_flag & DEFER_ERATT)) { + spin_unlock_irq(&phba->hbalock); + return IRQ_NONE; + } writel((ha_copy & (HA_R0_CLR_MSK | HA_R1_CLR_MSK)), phba->HAregaddr); readl(phba->HAregaddr); /* flush */ @@ -5510,7 +5569,7 @@ lpfc_fp_intr_handler(int irq, void *dev_id) } /* lpfc_fp_intr_handler */ /** - * lpfc_intr_handler: The device-level interrupt handler of lpfc driver. + * lpfc_intr_handler - The device-level interrupt handler of lpfc driver * @irq: Interrupt number. * @dev_id: The device context pointer. * @@ -5566,6 +5625,14 @@ lpfc_intr_handler(int irq, void *dev_id) phba->hba_flag |= HBA_ERATT_HANDLED; } + /* + * If there is deferred error attention, do not check for any interrupt. + */ + if (unlikely(phba->hba_flag & DEFER_ERATT)) { + spin_unlock_irq(&phba->hbalock); + return IRQ_NONE; + } + /* Clear attention sources except link and error attentions */ writel((phba->ha_copy & ~(HA_LATT | HA_ERATT)), phba->HAregaddr); readl(phba->HAregaddr); /* flush */ diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h index 7e32e95c539..e599519e307 100644 --- a/drivers/scsi/lpfc/lpfc_version.h +++ b/drivers/scsi/lpfc/lpfc_version.h @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2004-2008 Emulex. All rights reserved. * + * Copyright (C) 2004-2009 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * * www.emulex.com * * * @@ -18,7 +18,7 @@ * included with this package. * *******************************************************************/ -#define LPFC_DRIVER_VERSION "8.3.0" +#define LPFC_DRIVER_VERSION "8.3.1" #define LPFC_DRIVER_NAME "lpfc" #define LPFC_SP_DRIVER_HANDLER_NAME "lpfc:sp" @@ -26,4 +26,4 @@ #define LPFC_MODULE_DESC "Emulex LightPulse Fibre Channel SCSI driver " \ LPFC_DRIVER_VERSION -#define LPFC_COPYRIGHT "Copyright(c) 2004-2008 Emulex. All rights reserved." +#define LPFC_COPYRIGHT "Copyright(c) 2004-2009 Emulex. All rights reserved." diff --git a/drivers/scsi/lpfc/lpfc_vport.c b/drivers/scsi/lpfc/lpfc_vport.c index 63b54c66756..917ad56b0af 100644 --- a/drivers/scsi/lpfc/lpfc_vport.c +++ b/drivers/scsi/lpfc/lpfc_vport.c @@ -206,7 +206,7 @@ lpfc_unique_wwpn(struct lpfc_hba *phba, struct lpfc_vport *new_vport) } /** - * lpfc_discovery_wait: Wait for driver discovery to quiesce. + * lpfc_discovery_wait - Wait for driver discovery to quiesce * @vport: The virtual port for which this call is being executed. * * This driver calls this routine specifically from lpfc_vport_delete @@ -741,7 +741,7 @@ lpfc_destroy_vport_work_array(struct lpfc_hba *phba, struct lpfc_vport **vports) /** - * lpfc_vport_reset_stat_data: Reset the statistical data for the vport. + * lpfc_vport_reset_stat_data - Reset the statistical data for the vport * @vport: Pointer to vport object. * * This function resets the statistical data for the vport. This function @@ -763,8 +763,7 @@ lpfc_vport_reset_stat_data(struct lpfc_vport *vport) /** - * lpfc_alloc_bucket: Allocate data buffer required for collecting - * statistical data. + * lpfc_alloc_bucket - Allocate data buffer required for statistical data * @vport: Pointer to vport object. * * This function allocates data buffer required for all the FC @@ -797,8 +796,7 @@ lpfc_alloc_bucket(struct lpfc_vport *vport) } /** - * lpfc_free_bucket: Free data buffer required for collecting - * statistical data. + * lpfc_free_bucket - Free data buffer required for statistical data * @vport: Pointer to vport object. * * Th function frees statistical data buffer of all the FC diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c index a91f5143cea..f3da592f7bc 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.c +++ b/drivers/scsi/mpt2sas/mpt2sas_base.c @@ -636,6 +636,14 @@ _base_unmask_interrupts(struct MPT2SAS_ADAPTER *ioc) static irqreturn_t _base_interrupt(int irq, void *bus_id) { + union reply_descriptor { + u64 word; + struct { + u32 low; + u32 high; + } u; + }; + union reply_descriptor rd; u32 post_index, post_index_next, completed_cmds; u8 request_desript_type; u16 smid; @@ -656,7 +664,8 @@ _base_interrupt(int irq, void *bus_id) completed_cmds = 0; do { - if (ioc->reply_post_free[post_index].Words == ~0ULL) + rd.word = ioc->reply_post_free[post_index].Words; + if (rd.u.low == UINT_MAX || rd.u.high == UINT_MAX) goto out; reply = 0; cb_idx = 0xFF; @@ -721,7 +730,7 @@ _base_interrupt(int irq, void *bus_id) for (i = 0 ; i < completed_cmds; i++) { post_index = post_index_next; /* poison the reply post descriptor */ - ioc->reply_post_free[post_index_next].Words = ~0ULL; + ioc->reply_post_free[post_index_next].Words = ULLONG_MAX; post_index_next = (post_index == (ioc->reply_post_queue_depth - 1)) ? 0 : post_index + 1; @@ -1387,6 +1396,64 @@ mpt2sas_base_put_smid_target_assist(struct MPT2SAS_ADAPTER *ioc, u16 smid, } /** + * _base_display_dell_branding - Disply branding string + * @ioc: per adapter object + * + * Return nothing. + */ +static void +_base_display_dell_branding(struct MPT2SAS_ADAPTER *ioc) +{ + char dell_branding[MPT2SAS_DELL_BRANDING_SIZE]; + + if (ioc->pdev->subsystem_vendor != PCI_VENDOR_ID_DELL) + return; + + memset(dell_branding, 0, MPT2SAS_DELL_BRANDING_SIZE); + switch (ioc->pdev->subsystem_device) { + case MPT2SAS_DELL_6GBPS_SAS_HBA_SSDID: + strncpy(dell_branding, MPT2SAS_DELL_6GBPS_SAS_HBA_BRANDING, + MPT2SAS_DELL_BRANDING_SIZE - 1); + break; + case MPT2SAS_DELL_PERC_H200_ADAPTER_SSDID: + strncpy(dell_branding, MPT2SAS_DELL_PERC_H200_ADAPTER_BRANDING, + MPT2SAS_DELL_BRANDING_SIZE - 1); + break; + case MPT2SAS_DELL_PERC_H200_INTEGRATED_SSDID: + strncpy(dell_branding, + MPT2SAS_DELL_PERC_H200_INTEGRATED_BRANDING, + MPT2SAS_DELL_BRANDING_SIZE - 1); + break; + case MPT2SAS_DELL_PERC_H200_MODULAR_SSDID: + strncpy(dell_branding, + MPT2SAS_DELL_PERC_H200_MODULAR_BRANDING, + MPT2SAS_DELL_BRANDING_SIZE - 1); + break; + case MPT2SAS_DELL_PERC_H200_EMBEDDED_SSDID: + strncpy(dell_branding, + MPT2SAS_DELL_PERC_H200_EMBEDDED_BRANDING, + MPT2SAS_DELL_BRANDING_SIZE - 1); + break; + case MPT2SAS_DELL_PERC_H200_SSDID: + strncpy(dell_branding, MPT2SAS_DELL_PERC_H200_BRANDING, + MPT2SAS_DELL_BRANDING_SIZE - 1); + break; + case MPT2SAS_DELL_6GBPS_SAS_SSDID: + strncpy(dell_branding, MPT2SAS_DELL_6GBPS_SAS_BRANDING, + MPT2SAS_DELL_BRANDING_SIZE - 1); + break; + default: + sprintf(dell_branding, "0x%4X", ioc->pdev->subsystem_device); + break; + } + + printk(MPT2SAS_INFO_FMT "%s: Vendor(0x%04X), Device(0x%04X)," + " SSVID(0x%04X), SSDID(0x%04X)\n", ioc->name, dell_branding, + ioc->pdev->vendor, ioc->pdev->device, ioc->pdev->subsystem_vendor, + ioc->pdev->subsystem_device); +} + +/** * _base_display_ioc_capabilities - Disply IOC's capabilities. * @ioc: per adapter object * @@ -1427,6 +1494,8 @@ _base_display_ioc_capabilities(struct MPT2SAS_ADAPTER *ioc) i++; } + _base_display_dell_branding(ioc); + i = 0; printk("), "); printk("Capabilities=("); @@ -3068,7 +3137,7 @@ _base_make_ioc_operational(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, /* initialize Reply Post Free Queue */ for (i = 0; i < ioc->reply_post_queue_depth; i++) - ioc->reply_post_free[i].Words = ~0ULL; + ioc->reply_post_free[i].Words = ULLONG_MAX; r = _base_send_ioc_init(ioc, VF_ID, sleep_flag); if (r) diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h index 6945ff4d382..babd4cc0cb2 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.h +++ b/drivers/scsi/mpt2sas/mpt2sas_base.h @@ -68,11 +68,11 @@ #define MPT2SAS_DRIVER_NAME "mpt2sas" #define MPT2SAS_AUTHOR "LSI Corporation <DL-MPTFusionLinux@lsi.com>" #define MPT2SAS_DESCRIPTION "LSI MPT Fusion SAS 2.0 Device Driver" -#define MPT2SAS_DRIVER_VERSION "00.100.11.16" +#define MPT2SAS_DRIVER_VERSION "01.100.02.00" #define MPT2SAS_MAJOR_VERSION 00 #define MPT2SAS_MINOR_VERSION 100 -#define MPT2SAS_BUILD_VERSION 11 -#define MPT2SAS_RELEASE_VERSION 16 +#define MPT2SAS_BUILD_VERSION 02 +#define MPT2SAS_RELEASE_VERSION 00 /* * Set MPT2SAS_SG_DEPTH value based on user input. @@ -130,6 +130,30 @@ #define MPT2SAS_ERR_FMT KERN_ERR MPT2SAS_FMT /* + * Dell HBA branding + */ +#define MPT2SAS_DELL_BRANDING_SIZE 32 + +#define MPT2SAS_DELL_6GBPS_SAS_HBA_BRANDING "Dell 6Gbps SAS HBA" +#define MPT2SAS_DELL_PERC_H200_ADAPTER_BRANDING "Dell PERC H200 Adapter" +#define MPT2SAS_DELL_PERC_H200_INTEGRATED_BRANDING "Dell PERC H200 Integrated" +#define MPT2SAS_DELL_PERC_H200_MODULAR_BRANDING "Dell PERC H200 Modular" +#define MPT2SAS_DELL_PERC_H200_EMBEDDED_BRANDING "Dell PERC H200 Embedded" +#define MPT2SAS_DELL_PERC_H200_BRANDING "Dell PERC H200" +#define MPT2SAS_DELL_6GBPS_SAS_BRANDING "Dell 6Gbps SAS" + +/* + * Dell HBA SSDIDs + */ +#define MPT2SAS_DELL_6GBPS_SAS_HBA_SSDID 0x1F1C +#define MPT2SAS_DELL_PERC_H200_ADAPTER_SSDID 0x1F1D +#define MPT2SAS_DELL_PERC_H200_INTEGRATED_SSDID 0x1F1E +#define MPT2SAS_DELL_PERC_H200_MODULAR_SSDID 0x1F1F +#define MPT2SAS_DELL_PERC_H200_EMBEDDED_SSDID 0x1F20 +#define MPT2SAS_DELL_PERC_H200_SSDID 0x1F21 +#define MPT2SAS_DELL_6GBPS_SAS_SSDID 0x1F22 + +/* * per target private data */ #define MPT_TARGET_FLAGS_RAID_COMPONENT 0x01 diff --git a/drivers/scsi/mpt2sas/mpt2sas_ctl.c b/drivers/scsi/mpt2sas/mpt2sas_ctl.c index 2d4f85c9d7a..ba6ab170bdf 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_ctl.c +++ b/drivers/scsi/mpt2sas/mpt2sas_ctl.c @@ -64,6 +64,9 @@ static struct fasync_struct *async_queue; static DECLARE_WAIT_QUEUE_HEAD(ctl_poll_wait); +static int _ctl_send_release(struct MPT2SAS_ADAPTER *ioc, u8 buffer_type, + u8 *issue_reset); + /** * enum block_state - blocking state * @NON_BLOCKING: non blocking @@ -378,10 +381,22 @@ _ctl_verify_adapter(int ioc_number, struct MPT2SAS_ADAPTER **iocpp) void mpt2sas_ctl_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase) { + int i; + u8 issue_reset; + switch (reset_phase) { case MPT2_IOC_PRE_RESET: dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: " "MPT2_IOC_PRE_RESET\n", ioc->name, __func__)); + for (i = 0; i < MPI2_DIAG_BUF_TYPE_COUNT; i++) { + if (!(ioc->diag_buffer_status[i] & + MPT2_DIAG_BUFFER_IS_REGISTERED)) + continue; + if ((ioc->diag_buffer_status[i] & + MPT2_DIAG_BUFFER_IS_RELEASED)) + continue; + _ctl_send_release(ioc, i, &issue_reset); + } break; case MPT2_IOC_AFTER_RESET: dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: " @@ -395,6 +410,17 @@ mpt2sas_ctl_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase) case MPT2_IOC_DONE_RESET: dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: " "MPT2_IOC_DONE_RESET\n", ioc->name, __func__)); + + for (i = 0; i < MPI2_DIAG_BUF_TYPE_COUNT; i++) { + if (!(ioc->diag_buffer_status[i] & + MPT2_DIAG_BUFFER_IS_REGISTERED)) + continue; + if ((ioc->diag_buffer_status[i] & + MPT2_DIAG_BUFFER_IS_RELEASED)) + continue; + ioc->diag_buffer_status[i] |= + MPT2_DIAG_BUFFER_IS_DIAG_RESET; + } break; } } @@ -714,8 +740,10 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc, if (tm_request->TaskType == MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK) { - if (_ctl_do_task_abort(ioc, &karg, tm_request)) + if (_ctl_do_task_abort(ioc, &karg, tm_request)) { + mpt2sas_base_free_smid(ioc, smid); goto out; + } } mutex_lock(&ioc->tm_cmds.mutex); @@ -915,9 +943,9 @@ _ctl_getiocinfo(void __user *arg) karg.pci_information.u.bits.function = PCI_FUNC(ioc->pdev->devfn); karg.pci_information.segment_id = pci_domain_nr(ioc->pdev->bus); karg.firmware_version = ioc->facts.FWVersion.Word; - strncpy(karg.driver_version, MPT2SAS_DRIVER_VERSION, - MPT2_IOCTL_VERSION_LENGTH); - karg.driver_version[MPT2_IOCTL_VERSION_LENGTH - 1] = '\0'; + strcpy(karg.driver_version, MPT2SAS_DRIVER_NAME); + strcat(karg.driver_version, "-"); + strcat(karg.driver_version, MPT2SAS_DRIVER_VERSION); karg.bios_version = le32_to_cpu(ioc->bios_pg3.BiosVersion); if (copy_to_user(arg, &karg, sizeof(karg))) { @@ -1551,81 +1579,38 @@ _ctl_diag_query(void __user *arg) } /** - * _ctl_diag_release - request to send Diag Release Message to firmware - * @arg - user space buffer containing ioctl content - * @state - NON_BLOCKING or BLOCKING + * _ctl_send_release - Diag Release Message + * @ioc: per adapter object + * @buffer_type - specifies either TRACE or SNAPSHOT + * @issue_reset - specifies whether host reset is required. * - * This allows ownership of the specified buffer to returned to the driver, - * allowing an application to read the buffer without fear that firmware is - * overwritting information in the buffer. */ -static long -_ctl_diag_release(void __user *arg, enum block_state state) +static int +_ctl_send_release(struct MPT2SAS_ADAPTER *ioc, u8 buffer_type, u8 *issue_reset) { - struct mpt2_diag_release karg; - struct MPT2SAS_ADAPTER *ioc; - void *request_data; - int rc; Mpi2DiagReleaseRequest_t *mpi_request; Mpi2DiagReleaseReply_t *mpi_reply; - u8 buffer_type; - unsigned long timeleft; u16 smid; u16 ioc_status; - u8 issue_reset = 0; - - if (copy_from_user(&karg, arg, sizeof(karg))) { - printk(KERN_ERR "failure at %s:%d/%s()!\n", - __FILE__, __LINE__, __func__); - return -EFAULT; - } - if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc) - return -ENODEV; + u32 ioc_state; + int rc; + unsigned long timeleft; dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, __func__)); - buffer_type = karg.unique_id & 0x000000ff; - if (!_ctl_diag_capability(ioc, buffer_type)) { - printk(MPT2SAS_ERR_FMT "%s: doesn't have capability for " - "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type); - return -EPERM; - } - - if ((ioc->diag_buffer_status[buffer_type] & - MPT2_DIAG_BUFFER_IS_REGISTERED) == 0) { - printk(MPT2SAS_ERR_FMT "%s: buffer_type(0x%02x) is not " - "registered\n", ioc->name, __func__, buffer_type); - return -EINVAL; - } - - if (karg.unique_id != ioc->unique_id[buffer_type]) { - printk(MPT2SAS_ERR_FMT "%s: unique_id(0x%08x) is not " - "registered\n", ioc->name, __func__, karg.unique_id); - return -EINVAL; - } - - if (ioc->diag_buffer_status[buffer_type] & - MPT2_DIAG_BUFFER_IS_RELEASED) { - printk(MPT2SAS_ERR_FMT "%s: buffer_type(0x%02x) " - "is already released\n", ioc->name, __func__, - buffer_type); - return 0; - } - - request_data = ioc->diag_buffer[buffer_type]; + rc = 0; + *issue_reset = 0; - if (!request_data) { - printk(MPT2SAS_ERR_FMT "%s: doesn't have memory allocated for " - "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type); - return -ENOMEM; + ioc_state = mpt2sas_base_get_iocstate(ioc, 1); + if (ioc_state != MPI2_IOC_STATE_OPERATIONAL) { + dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: " + "skipping due to FAULT state\n", ioc->name, + __func__)); + rc = -EAGAIN; + goto out; } - if (state == NON_BLOCKING && !mutex_trylock(&ioc->ctl_cmds.mutex)) - return -EAGAIN; - else if (mutex_lock_interruptible(&ioc->ctl_cmds.mutex)) - return -ERESTARTSYS; - if (ioc->ctl_cmds.status != MPT2_CMD_NOT_USED) { printk(MPT2SAS_ERR_FMT "%s: ctl_cmd in use\n", ioc->name, __func__); @@ -1641,7 +1626,6 @@ _ctl_diag_release(void __user *arg, enum block_state state) goto out; } - rc = 0; ioc->ctl_cmds.status = MPT2_CMD_PENDING; memset(ioc->ctl_cmds.reply, 0, ioc->reply_sz); mpi_request = mpt2sas_base_get_msg_frame(ioc, smid); @@ -1660,8 +1644,9 @@ _ctl_diag_release(void __user *arg, enum block_state state) _debug_dump_mf(mpi_request, sizeof(Mpi2DiagReleaseRequest_t)/4); if (!(ioc->ctl_cmds.status & MPT2_CMD_RESET)) - issue_reset = 1; - goto issue_host_reset; + *issue_reset = 1; + rc = -EFAULT; + goto out; } /* process the completed Reply Message Frame */ @@ -1687,14 +1672,101 @@ _ctl_diag_release(void __user *arg, enum block_state state) rc = -EFAULT; } - issue_host_reset: + out: + ioc->ctl_cmds.status = MPT2_CMD_NOT_USED; + return rc; +} + +/** + * _ctl_diag_release - request to send Diag Release Message to firmware + * @arg - user space buffer containing ioctl content + * @state - NON_BLOCKING or BLOCKING + * + * This allows ownership of the specified buffer to returned to the driver, + * allowing an application to read the buffer without fear that firmware is + * overwritting information in the buffer. + */ +static long +_ctl_diag_release(void __user *arg, enum block_state state) +{ + struct mpt2_diag_release karg; + struct MPT2SAS_ADAPTER *ioc; + void *request_data; + int rc; + u8 buffer_type; + u8 issue_reset = 0; + + if (copy_from_user(&karg, arg, sizeof(karg))) { + printk(KERN_ERR "failure at %s:%d/%s()!\n", + __FILE__, __LINE__, __func__); + return -EFAULT; + } + if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc) + return -ENODEV; + + dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, + __func__)); + + buffer_type = karg.unique_id & 0x000000ff; + if (!_ctl_diag_capability(ioc, buffer_type)) { + printk(MPT2SAS_ERR_FMT "%s: doesn't have capability for " + "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type); + return -EPERM; + } + + if ((ioc->diag_buffer_status[buffer_type] & + MPT2_DIAG_BUFFER_IS_REGISTERED) == 0) { + printk(MPT2SAS_ERR_FMT "%s: buffer_type(0x%02x) is not " + "registered\n", ioc->name, __func__, buffer_type); + return -EINVAL; + } + + if (karg.unique_id != ioc->unique_id[buffer_type]) { + printk(MPT2SAS_ERR_FMT "%s: unique_id(0x%08x) is not " + "registered\n", ioc->name, __func__, karg.unique_id); + return -EINVAL; + } + + if (ioc->diag_buffer_status[buffer_type] & + MPT2_DIAG_BUFFER_IS_RELEASED) { + printk(MPT2SAS_ERR_FMT "%s: buffer_type(0x%02x) " + "is already released\n", ioc->name, __func__, + buffer_type); + return 0; + } + + request_data = ioc->diag_buffer[buffer_type]; + + if (!request_data) { + printk(MPT2SAS_ERR_FMT "%s: doesn't have memory allocated for " + "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type); + return -ENOMEM; + } + + /* buffers were released by due to host reset */ + if ((ioc->diag_buffer_status[buffer_type] & + MPT2_DIAG_BUFFER_IS_DIAG_RESET)) { + ioc->diag_buffer_status[buffer_type] |= + MPT2_DIAG_BUFFER_IS_RELEASED; + ioc->diag_buffer_status[buffer_type] &= + ~MPT2_DIAG_BUFFER_IS_DIAG_RESET; + printk(MPT2SAS_ERR_FMT "%s: buffer_type(0x%02x) " + "was released due to host reset\n", ioc->name, __func__, + buffer_type); + return 0; + } + + if (state == NON_BLOCKING && !mutex_trylock(&ioc->ctl_cmds.mutex)) + return -EAGAIN; + else if (mutex_lock_interruptible(&ioc->ctl_cmds.mutex)) + return -ERESTARTSYS; + + rc = _ctl_send_release(ioc, buffer_type, &issue_reset); + if (issue_reset) mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP, FORCE_BIG_HAMMER); - out: - - ioc->ctl_cmds.status = MPT2_CMD_NOT_USED; mutex_unlock(&ioc->ctl_cmds.mutex); return rc; } diff --git a/drivers/scsi/mpt2sas/mpt2sas_ctl.h b/drivers/scsi/mpt2sas/mpt2sas_ctl.h index dbb6c0cf888..4da11435533 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_ctl.h +++ b/drivers/scsi/mpt2sas/mpt2sas_ctl.h @@ -50,7 +50,7 @@ #endif #define MPT2SAS_DEV_NAME "mpt2ctl" -#define MPT2_MAGIC_NUMBER 'm' +#define MPT2_MAGIC_NUMBER 'L' #define MPT2_IOCTL_DEFAULT_TIMEOUT (10) /* in seconds */ /** @@ -295,8 +295,9 @@ struct mpt2_ioctl_btdh_mapping { /* status bits for ioc->diag_buffer_status */ -#define MPT2_DIAG_BUFFER_IS_REGISTERED (0x01) -#define MPT2_DIAG_BUFFER_IS_RELEASED (0x02) +#define MPT2_DIAG_BUFFER_IS_REGISTERED (0x01) +#define MPT2_DIAG_BUFFER_IS_RELEASED (0x02) +#define MPT2_DIAG_BUFFER_IS_DIAG_RESET (0x04) /* application flags for mpt2_diag_register, mpt2_diag_query */ #define MPT2_APP_FLAGS_APP_OWNED (0x0001) diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c index 0c463c483c0..e3a7967259e 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c +++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c @@ -119,7 +119,7 @@ struct sense_info { */ struct fw_event_work { struct list_head list; - struct delayed_work work; + struct work_struct work; struct MPT2SAS_ADAPTER *ioc; u8 VF_ID; u8 host_reset_handling; @@ -516,12 +516,8 @@ _scsih_sas_device_add(struct MPT2SAS_ADAPTER *ioc, handle = sas_device->handle; parent_handle = sas_device->parent_handle; sas_address = sas_device->sas_address; - if (!mpt2sas_transport_port_add(ioc, handle, parent_handle)) { + if (!mpt2sas_transport_port_add(ioc, handle, parent_handle)) _scsih_sas_device_remove(ioc, sas_device); - } else if (!sas_device->starget) { - mpt2sas_transport_port_remove(ioc, sas_address, parent_handle); - _scsih_sas_device_remove(ioc, sas_device); - } } /** @@ -1203,7 +1199,9 @@ scsih_target_destroy(struct scsi_target *starget) rphy = dev_to_rphy(starget->dev.parent); sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc, rphy->identify.sas_address); - if (sas_device) + if (sas_device && (sas_device->starget == starget) && + (sas_device->id == starget->id) && + (sas_device->channel == starget->channel)) sas_device->starget = NULL; spin_unlock_irqrestore(&ioc->sas_device_lock, flags); @@ -2009,8 +2007,8 @@ _scsih_fw_event_add(struct MPT2SAS_ADAPTER *ioc, struct fw_event_work *fw_event) spin_lock_irqsave(&ioc->fw_event_lock, flags); list_add_tail(&fw_event->list, &ioc->fw_event_list); - INIT_DELAYED_WORK(&fw_event->work, _firmware_event_work); - queue_delayed_work(ioc->firmware_event_thread, &fw_event->work, 1); + INIT_WORK(&fw_event->work, _firmware_event_work); + queue_work(ioc->firmware_event_thread, &fw_event->work); spin_unlock_irqrestore(&ioc->fw_event_lock, flags); } @@ -2054,7 +2052,7 @@ _scsih_fw_event_requeue(struct MPT2SAS_ADAPTER *ioc, struct fw_event_work return; spin_lock_irqsave(&ioc->fw_event_lock, flags); - queue_delayed_work(ioc->firmware_event_thread, &fw_event->work, delay); + queue_work(ioc->firmware_event_thread, &fw_event->work); spin_unlock_irqrestore(&ioc->fw_event_lock, flags); } @@ -2863,8 +2861,9 @@ scsih_io_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, u32 reply) struct sense_info data; const void *sense_data = mpt2sas_base_get_sense_buffer(ioc, smid); - memcpy(scmd->sense_buffer, sense_data, + u32 sz = min_t(u32, SCSI_SENSE_BUFFERSIZE, le32_to_cpu(mpi_reply->SenseCount)); + memcpy(scmd->sense_buffer, sense_data, sz); _scsih_normalize_sense(scmd->sense_buffer, &data); /* failure prediction threshold exceeded */ if (data.asc == 0x5D) @@ -3923,7 +3922,7 @@ _scsih_sas_broadcast_primative_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, mpt2sas_scsih_issue_tm(ioc, handle, lun, MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK, smid, 30); - termination_count += le32_to_cpu(mpi_reply->TerminationCount); + ioc->tm_cmds.status = MPT2_CMD_NOT_USED; if ((mpi_reply->IOCStatus == MPI2_IOCSTATUS_SUCCESS) && (mpi_reply->ResponseCode == @@ -3933,10 +3932,10 @@ _scsih_sas_broadcast_primative_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, continue; mpt2sas_scsih_issue_tm(ioc, handle, lun, - MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET, smid, 30); + MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET, 0, 30); + ioc->tm_cmds.status = MPT2_CMD_NOT_USED; termination_count += le32_to_cpu(mpi_reply->TerminationCount); } - ioc->tm_cmds.status = MPT2_CMD_NOT_USED; ioc->broadcast_aen_busy = 0; mutex_unlock(&ioc->tm_cmds.mutex); @@ -4962,7 +4961,7 @@ static void _firmware_event_work(struct work_struct *work) { struct fw_event_work *fw_event = container_of(work, - struct fw_event_work, work.work); + struct fw_event_work, work); unsigned long flags; struct MPT2SAS_ADAPTER *ioc = fw_event->ioc; diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c index 2a5f0777148..1ce6b24abab 100644 --- a/drivers/scsi/osd/osd_initiator.c +++ b/drivers/scsi/osd/osd_initiator.c @@ -205,6 +205,74 @@ static unsigned _osd_req_alist_elem_size(struct osd_request *or, unsigned len) osdv2_attr_list_elem_size(len); } +static void _osd_req_alist_elem_encode(struct osd_request *or, + void *attr_last, const struct osd_attr *oa) +{ + if (osd_req_is_ver1(or)) { + struct osdv1_attributes_list_element *attr = attr_last; + + attr->attr_page = cpu_to_be32(oa->attr_page); + attr->attr_id = cpu_to_be32(oa->attr_id); + attr->attr_bytes = cpu_to_be16(oa->len); + memcpy(attr->attr_val, oa->val_ptr, oa->len); + } else { + struct osdv2_attributes_list_element *attr = attr_last; + + attr->attr_page = cpu_to_be32(oa->attr_page); + attr->attr_id = cpu_to_be32(oa->attr_id); + attr->attr_bytes = cpu_to_be16(oa->len); + memcpy(attr->attr_val, oa->val_ptr, oa->len); + } +} + +static int _osd_req_alist_elem_decode(struct osd_request *or, + void *cur_p, struct osd_attr *oa, unsigned max_bytes) +{ + unsigned inc; + if (osd_req_is_ver1(or)) { + struct osdv1_attributes_list_element *attr = cur_p; + + if (max_bytes < sizeof(*attr)) + return -1; + + oa->len = be16_to_cpu(attr->attr_bytes); + inc = _osd_req_alist_elem_size(or, oa->len); + if (inc > max_bytes) + return -1; + + oa->attr_page = be32_to_cpu(attr->attr_page); + oa->attr_id = be32_to_cpu(attr->attr_id); + + /* OSD1: On empty attributes we return a pointer to 2 bytes + * of zeros. This keeps similar behaviour with OSD2. + * (See below) + */ + oa->val_ptr = likely(oa->len) ? attr->attr_val : + (u8 *)&attr->attr_bytes; + } else { + struct osdv2_attributes_list_element *attr = cur_p; + + if (max_bytes < sizeof(*attr)) + return -1; + + oa->len = be16_to_cpu(attr->attr_bytes); + inc = _osd_req_alist_elem_size(or, oa->len); + if (inc > max_bytes) + return -1; + + oa->attr_page = be32_to_cpu(attr->attr_page); + oa->attr_id = be32_to_cpu(attr->attr_id); + + /* OSD2: For convenience, on empty attributes, we return 8 bytes + * of zeros here. This keeps the same behaviour with OSD2r04, + * and is nice with null terminating ASCII fields. + * oa->val_ptr == NULL marks the end-of-list, or error. + */ + oa->val_ptr = likely(oa->len) ? attr->attr_val : attr->reserved; + } + return inc; +} + static unsigned _osd_req_alist_size(struct osd_request *or, void *list_head) { return osd_req_is_ver1(or) ? @@ -282,9 +350,9 @@ _osd_req_sec_params(struct osd_request *or) struct osd_cdb *ocdb = &or->cdb; if (osd_req_is_ver1(or)) - return &ocdb->v1.sec_params; + return (struct osd_security_parameters *)&ocdb->v1.sec_params; else - return &ocdb->v2.sec_params; + return (struct osd_security_parameters *)&ocdb->v2.sec_params; } void osd_dev_init(struct osd_dev *osdd, struct scsi_device *scsi_device) @@ -612,9 +680,9 @@ static int _osd_req_list_objects(struct osd_request *or, WARN_ON(or->in.bio); bio = bio_map_kern(q, list, len, or->alloc_flags); - if (!bio) { + if (IS_ERR(bio)) { OSD_ERR("!!! Failed to allocate list_objects BIO\n"); - return -ENOMEM; + return PTR_ERR(bio); } bio->bi_rw &= ~(1 << BIO_RW); @@ -798,7 +866,6 @@ int osd_req_add_set_attr_list(struct osd_request *or, attr_last = or->set_attr.buff + total_bytes; for (; nelem; --nelem) { - struct osd_attributes_list_element *attr; unsigned elem_size = _osd_req_alist_elem_size(or, oa->len); total_bytes += elem_size; @@ -811,11 +878,7 @@ int osd_req_add_set_attr_list(struct osd_request *or, or->set_attr.buff + or->set_attr.total_bytes; } - attr = attr_last; - attr->attr_page = cpu_to_be32(oa->attr_page); - attr->attr_id = cpu_to_be32(oa->attr_id); - attr->attr_bytes = cpu_to_be16(oa->len); - memcpy(attr->attr_val, oa->val_ptr, oa->len); + _osd_req_alist_elem_encode(or, attr_last, oa); attr_last += elem_size; ++oa; @@ -1070,15 +1133,10 @@ int osd_req_decode_get_attr_list(struct osd_request *or, } for (n = 0; (n < *nelem) && (cur_bytes < returned_bytes); ++n) { - struct osd_attributes_list_element *attr = cur_p; - unsigned inc; + int inc = _osd_req_alist_elem_decode(or, cur_p, oa, + returned_bytes - cur_bytes); - oa->len = be16_to_cpu(attr->attr_bytes); - inc = _osd_req_alist_elem_size(or, oa->len); - OSD_DEBUG("oa->len=%d inc=%d cur_bytes=%d\n", - oa->len, inc, cur_bytes); - cur_bytes += inc; - if (cur_bytes > returned_bytes) { + if (inc < 0) { OSD_ERR("BAD FOOD from target. list not valid!" "c=%d r=%d n=%d\n", cur_bytes, returned_bytes, n); @@ -1086,10 +1144,7 @@ int osd_req_decode_get_attr_list(struct osd_request *or, break; } - oa->attr_page = be32_to_cpu(attr->attr_page); - oa->attr_id = be32_to_cpu(attr->attr_id); - oa->val_ptr = attr->attr_val; - + cur_bytes += inc; cur_p += inc; ++oa; } @@ -1159,6 +1214,24 @@ static int _osd_req_finalize_attr_page(struct osd_request *or) return ret; } +static inline void osd_sec_parms_set_out_offset(bool is_v1, + struct osd_security_parameters *sec_parms, osd_cdb_offset offset) +{ + if (is_v1) + sec_parms->v1.data_out_integrity_check_offset = offset; + else + sec_parms->v2.data_out_integrity_check_offset = offset; +} + +static inline void osd_sec_parms_set_in_offset(bool is_v1, + struct osd_security_parameters *sec_parms, osd_cdb_offset offset) +{ + if (is_v1) + sec_parms->v1.data_in_integrity_check_offset = offset; + else + sec_parms->v2.data_in_integrity_check_offset = offset; +} + static int _osd_req_finalize_data_integrity(struct osd_request *or, bool has_in, bool has_out, const u8 *cap_key) { @@ -1182,8 +1255,8 @@ static int _osd_req_finalize_data_integrity(struct osd_request *or, or->out_data_integ.get_attributes_bytes = cpu_to_be64( or->enc_get_attr.total_bytes); - sec_parms->data_out_integrity_check_offset = - osd_req_encode_offset(or, or->out.total_bytes, &pad); + osd_sec_parms_set_out_offset(osd_req_is_ver1(or), sec_parms, + osd_req_encode_offset(or, or->out.total_bytes, &pad)); ret = _req_append_segment(or, pad, &seg, or->out.last_seg, &or->out); @@ -1203,8 +1276,8 @@ static int _osd_req_finalize_data_integrity(struct osd_request *or, }; unsigned pad; - sec_parms->data_in_integrity_check_offset = - osd_req_encode_offset(or, or->in.total_bytes, &pad); + osd_sec_parms_set_in_offset(osd_req_is_ver1(or), sec_parms, + osd_req_encode_offset(or, or->in.total_bytes, &pad)); ret = _req_append_segment(or, pad, &seg, or->in.last_seg, &or->in); diff --git a/drivers/scsi/osd/osd_uld.c b/drivers/scsi/osd/osd_uld.c index f644c9571ea..22b59e13ba8 100644 --- a/drivers/scsi/osd/osd_uld.c +++ b/drivers/scsi/osd/osd_uld.c @@ -173,26 +173,26 @@ static const struct file_operations osd_fops = { .unlocked_ioctl = osd_uld_ioctl, }; -struct osd_dev *osduld_path_lookup(const char *path) +struct osd_dev *osduld_path_lookup(const char *name) { - struct nameidata nd; + struct path path; struct inode *inode; struct cdev *cdev; struct osd_uld_device *uninitialized_var(oud); int error; - if (!path || !*path) { + if (!name || !*name) { OSD_ERR("Mount with !path || !*path\n"); return ERR_PTR(-EINVAL); } - error = path_lookup(path, LOOKUP_FOLLOW, &nd); + error = kern_path(name, LOOKUP_FOLLOW, &path); if (error) { - OSD_ERR("path_lookup of %s faild=>%d\n", path, error); + OSD_ERR("path_lookup of %s failed=>%d\n", name, error); return ERR_PTR(error); } - inode = nd.path.dentry->d_inode; + inode = path.dentry->d_inode; error = -EINVAL; /* Not the right device e.g osd_uld_device */ if (!S_ISCHR(inode->i_mode)) { OSD_DEBUG("!S_ISCHR()\n"); @@ -202,15 +202,15 @@ struct osd_dev *osduld_path_lookup(const char *path) cdev = inode->i_cdev; if (!cdev) { OSD_ERR("Before mounting an OSD Based filesystem\n"); - OSD_ERR(" user-mode must open+close the %s device\n", path); - OSD_ERR(" Example: bash: echo < %s\n", path); + OSD_ERR(" user-mode must open+close the %s device\n", name); + OSD_ERR(" Example: bash: echo < %s\n", name); goto out; } /* The Magic wand. Is it our char-dev */ /* TODO: Support sg devices */ if (cdev->owner != THIS_MODULE) { - OSD_ERR("Error mounting %s - is not an OSD device\n", path); + OSD_ERR("Error mounting %s - is not an OSD device\n", name); goto out; } @@ -220,7 +220,7 @@ struct osd_dev *osduld_path_lookup(const char *path) error = 0; out: - path_put(&nd.path); + path_put(&path); return error ? ERR_PTR(error) : &oud->od; } EXPORT_SYMBOL(osduld_path_lookup); diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index d1cb64ad1a3..bb218c8b6e9 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -1291,10 +1291,8 @@ static inline int scsi_target_queue_ready(struct Scsi_Host *shost, if (--starget->target_blocked == 0) { SCSI_LOG_MLQUEUE(3, starget_printk(KERN_INFO, starget, "unblocking target at zero depth\n")); - } else { - blk_plug_device(sdev->request_queue); + } else return 0; - } } if (scsi_target_is_busy(starget)) { diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 3fcb64b91c4..84044233b63 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -50,6 +50,7 @@ #include <linux/string_helpers.h> #include <linux/async.h> #include <asm/uaccess.h> +#include <asm/unaligned.h> #include <scsi/scsi.h> #include <scsi/scsi_cmnd.h> @@ -1344,12 +1345,8 @@ static int read_capacity_16(struct scsi_disk *sdkp, struct scsi_device *sdp, return -EINVAL; } - sector_size = (buffer[8] << 24) | (buffer[9] << 16) | - (buffer[10] << 8) | buffer[11]; - lba = (((u64)buffer[0] << 56) | ((u64)buffer[1] << 48) | - ((u64)buffer[2] << 40) | ((u64)buffer[3] << 32) | - ((u64)buffer[4] << 24) | ((u64)buffer[5] << 16) | - ((u64)buffer[6] << 8) | (u64)buffer[7]); + sector_size = get_unaligned_be32(&buffer[8]); + lba = get_unaligned_be64(&buffer[0]); sd_read_protection_type(sdkp, buffer); @@ -1400,10 +1397,8 @@ static int read_capacity_10(struct scsi_disk *sdkp, struct scsi_device *sdp, return -EINVAL; } - sector_size = (buffer[4] << 24) | (buffer[5] << 16) | - (buffer[6] << 8) | buffer[7]; - lba = (buffer[0] << 24) | (buffer[1] << 16) | - (buffer[2] << 8) | buffer[3]; + sector_size = get_unaligned_be32(&buffer[4]); + lba = get_unaligned_be32(&buffer[0]); if ((sizeof(sdkp->capacity) == 4) && (lba == 0xffffffff)) { sd_printk(KERN_ERR, sdkp, "Too big for this kernel. Use a " diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 82312df9b0b..e1716f14cd4 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -179,7 +179,7 @@ typedef struct sg_device { /* holds the state of each scsi generic device */ /* tasklet or soft irq callback */ static void sg_rq_end_io(struct request *rq, int uptodate); static int sg_start_req(Sg_request *srp, unsigned char *cmd); -static void sg_finish_rem_req(Sg_request * srp); +static int sg_finish_rem_req(Sg_request * srp); static int sg_build_indirect(Sg_scatter_hold * schp, Sg_fd * sfp, int buff_size); static ssize_t sg_new_read(Sg_fd * sfp, char __user *buf, size_t count, Sg_request * srp); @@ -518,7 +518,7 @@ sg_new_read(Sg_fd * sfp, char __user *buf, size_t count, Sg_request * srp) goto err_out; } err_out: - sg_finish_rem_req(srp); + err = sg_finish_rem_req(srp); return (0 == err) ? count : err; } @@ -1696,9 +1696,10 @@ static int sg_start_req(Sg_request *srp, unsigned char *cmd) return res; } -static void -sg_finish_rem_req(Sg_request * srp) +static int sg_finish_rem_req(Sg_request * srp) { + int ret = 0; + Sg_fd *sfp = srp->parentfp; Sg_scatter_hold *req_schp = &srp->data; @@ -1710,12 +1711,14 @@ sg_finish_rem_req(Sg_request * srp) if (srp->rq) { if (srp->bio) - blk_rq_unmap_user(srp->bio); + ret = blk_rq_unmap_user(srp->bio); blk_put_request(srp->rq); } sg_remove_request(sfp, srp); + + return ret; } static int diff --git a/drivers/scsi/sr_ioctl.c b/drivers/scsi/sr_ioctl.c index d92ff512d21..291236e6e43 100644 --- a/drivers/scsi/sr_ioctl.c +++ b/drivers/scsi/sr_ioctl.c @@ -309,6 +309,11 @@ int sr_drive_status(struct cdrom_device_info *cdi, int slot) if (0 == sr_test_unit_ready(cd->device, &sshdr)) return CDS_DISC_OK; + /* SK/ASC/ASCQ of 2/4/1 means "unit is becoming ready" */ + if (scsi_sense_valid(&sshdr) && sshdr.sense_key == NOT_READY + && sshdr.asc == 0x04 && sshdr.ascq == 0x01) + return CDS_DRIVE_NOT_READY; + if (!cdrom_get_media_event(cdi, &med)) { if (med.media_present) return CDS_DISC_OK; diff --git a/drivers/serial/crisv10.c b/drivers/serial/crisv10.c index 7ba7d70f04d..7be52fe288e 100644 --- a/drivers/serial/crisv10.c +++ b/drivers/serial/crisv10.c @@ -23,16 +23,18 @@ static char *serial_version = "$Revision: 1.25 $"; #include <linux/mm.h> #include <linux/slab.h> #include <linux/init.h> -#include <asm/uaccess.h> #include <linux/kernel.h> #include <linux/mutex.h> #include <linux/bitops.h> +#include <linux/seq_file.h> +#include <linux/delay.h> +#include <linux/module.h> +#include <linux/uaccess.h> +#include <linux/io.h> -#include <asm/io.h> #include <asm/irq.h> #include <asm/dma.h> #include <asm/system.h> -#include <linux/delay.h> #include <arch/svinto.h> @@ -456,7 +458,6 @@ static struct e100_serial rs_table[] = { #define NR_PORTS (sizeof(rs_table)/sizeof(struct e100_serial)) -static struct ktermios *serial_termios[NR_PORTS]; #ifdef CONFIG_ETRAX_SERIAL_FAST_TIMER static struct fast_timer fast_timers[NR_PORTS]; #endif @@ -4257,151 +4258,132 @@ rs_open(struct tty_struct *tty, struct file * filp) return 0; } +#ifdef CONFIG_PROC_FS /* * /proc fs routines.... */ -static int line_info(char *buf, struct e100_serial *info) +static void seq_line_info(struct seq_file *m, struct e100_serial *info) { - char stat_buf[30]; - int ret; unsigned long tmp; - ret = sprintf(buf, "%d: uart:E100 port:%lX irq:%d", - info->line, (unsigned long)info->ioport, info->irq); + seq_printf(m, "%d: uart:E100 port:%lX irq:%d", + info->line, (unsigned long)info->ioport, info->irq); if (!info->ioport || (info->type == PORT_UNKNOWN)) { - ret += sprintf(buf+ret, "\n"); - return ret; + seq_printf(m, "\n"); + return; } - stat_buf[0] = 0; - stat_buf[1] = 0; - if (!E100_RTS_GET(info)) - strcat(stat_buf, "|RTS"); - if (!E100_CTS_GET(info)) - strcat(stat_buf, "|CTS"); - if (!E100_DTR_GET(info)) - strcat(stat_buf, "|DTR"); - if (!E100_DSR_GET(info)) - strcat(stat_buf, "|DSR"); - if (!E100_CD_GET(info)) - strcat(stat_buf, "|CD"); - if (!E100_RI_GET(info)) - strcat(stat_buf, "|RI"); - - ret += sprintf(buf+ret, " baud:%d", info->baud); - - ret += sprintf(buf+ret, " tx:%lu rx:%lu", + seq_printf(m, " baud:%d", info->baud); + seq_printf(m, " tx:%lu rx:%lu", (unsigned long)info->icount.tx, (unsigned long)info->icount.rx); tmp = CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE); - if (tmp) { - ret += sprintf(buf+ret, " tx_pend:%lu/%lu", - (unsigned long)tmp, - (unsigned long)SERIAL_XMIT_SIZE); - } + if (tmp) + seq_printf(m, " tx_pend:%lu/%lu", + (unsigned long)tmp, + (unsigned long)SERIAL_XMIT_SIZE); - ret += sprintf(buf+ret, " rx_pend:%lu/%lu", - (unsigned long)info->recv_cnt, - (unsigned long)info->max_recv_cnt); + seq_printf(m, " rx_pend:%lu/%lu", + (unsigned long)info->recv_cnt, + (unsigned long)info->max_recv_cnt); #if 1 if (info->port.tty) { - if (info->port.tty->stopped) - ret += sprintf(buf+ret, " stopped:%i", - (int)info->port.tty->stopped); + seq_printf(m, " stopped:%i", + (int)info->port.tty->stopped); if (info->port.tty->hw_stopped) - ret += sprintf(buf+ret, " hw_stopped:%i", - (int)info->port.tty->hw_stopped); + seq_printf(m, " hw_stopped:%i", + (int)info->port.tty->hw_stopped); } { unsigned char rstat = info->ioport[REG_STATUS]; - if (rstat & IO_MASK(R_SERIAL0_STATUS, xoff_detect) ) - ret += sprintf(buf+ret, " xoff_detect:1"); + if (rstat & IO_MASK(R_SERIAL0_STATUS, xoff_detect)) + seq_printf(m, " xoff_detect:1"); } #endif - - - if (info->icount.frame) - ret += sprintf(buf+ret, " fe:%lu", - (unsigned long)info->icount.frame); + seq_printf(m, " fe:%lu", (unsigned long)info->icount.frame); if (info->icount.parity) - ret += sprintf(buf+ret, " pe:%lu", - (unsigned long)info->icount.parity); + seq_printf(m, " pe:%lu", (unsigned long)info->icount.parity); if (info->icount.brk) - ret += sprintf(buf+ret, " brk:%lu", - (unsigned long)info->icount.brk); + seq_printf(m, " brk:%lu", (unsigned long)info->icount.brk); if (info->icount.overrun) - ret += sprintf(buf+ret, " oe:%lu", - (unsigned long)info->icount.overrun); + seq_printf(m, " oe:%lu", (unsigned long)info->icount.overrun); /* * Last thing is the RS-232 status lines */ - ret += sprintf(buf+ret, " %s\n", stat_buf+1); - return ret; + if (!E100_RTS_GET(info)) + seq_puts(m, "|RTS"); + if (!E100_CTS_GET(info)) + seq_puts(m, "|CTS"); + if (!E100_DTR_GET(info)) + seq_puts(m, "|DTR"); + if (!E100_DSR_GET(info)) + seq_puts(m, "|DSR"); + if (!E100_CD_GET(info)) + seq_puts(m, "|CD"); + if (!E100_RI_GET(info)) + seq_puts(m, "|RI"); + seq_puts(m, "\n"); } -int rs_read_proc(char *page, char **start, off_t off, int count, - int *eof, void *data) + +static int crisv10_proc_show(struct seq_file *m, void *v) { - int i, len = 0, l; - off_t begin = 0; + int i; - len += sprintf(page, "serinfo:1.0 driver:%s\n", - serial_version); - for (i = 0; i < NR_PORTS && len < 4000; i++) { + seq_printf(m, "serinfo:1.0 driver:%s\n", serial_version); + + for (i = 0; i < NR_PORTS; i++) { if (!rs_table[i].enabled) continue; - l = line_info(page + len, &rs_table[i]); - len += l; - if (len+begin > off+count) - goto done; - if (len+begin < off) { - begin += len; - len = 0; - } + seq_line_info(m, &rs_table[i]); } #ifdef DEBUG_LOG_INCLUDED for (i = 0; i < debug_log_pos; i++) { - len += sprintf(page + len, "%-4i %lu.%lu ", i, debug_log[i].time, timer_data_to_ns(debug_log[i].timer_data)); - len += sprintf(page + len, debug_log[i].string, debug_log[i].value); - if (len+begin > off+count) - goto done; - if (len+begin < off) { - begin += len; - len = 0; - } + seq_printf(m, "%-4i %lu.%lu ", + i, debug_log[i].time, + timer_data_to_ns(debug_log[i].timer_data)); + seq_printf(m, debug_log[i].string, debug_log[i].value); } - len += sprintf(page + len, "debug_log %i/%i %li bytes\n", - i, DEBUG_LOG_SIZE, begin+len); + seq_printf(m, "debug_log %i/%i\n", i, DEBUG_LOG_SIZE); debug_log_pos = 0; #endif + return 0; +} - *eof = 1; -done: - if (off >= len+begin) - return 0; - *start = page + (off-begin); - return ((count < begin+len-off) ? count : begin+len-off); +static int crisv10_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, crisv10_proc_show, NULL); } +static const struct file_operations crisv10_proc_fops = { + .owner = THIS_MODULE, + .open = crisv10_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; +#endif + + /* Finally, routines used to initialize the serial driver. */ -static void -show_serial_version(void) +static void show_serial_version(void) { printk(KERN_INFO - "ETRAX 100LX serial-driver %s, (c) 2000-2004 Axis Communications AB\r\n", + "ETRAX 100LX serial-driver %s, " + "(c) 2000-2004 Axis Communications AB\r\n", &serial_version[11]); /* "$Revision: x.yy" */ } @@ -4425,13 +4407,14 @@ static const struct tty_operations rs_ops = { .break_ctl = rs_break, .send_xchar = rs_send_xchar, .wait_until_sent = rs_wait_until_sent, - .read_proc = rs_read_proc, .tiocmget = rs_tiocmget, - .tiocmset = rs_tiocmset + .tiocmset = rs_tiocmset, +#ifdef CONFIG_PROC_FS + .proc_fops = &crisv10_proc_fops, +#endif }; -static int __init -rs_init(void) +static int __init rs_init(void) { int i; struct e100_serial *info; diff --git a/drivers/serial/jsm/jsm.h b/drivers/serial/jsm/jsm.h index 8871aaa3dba..c0a3e2734e2 100644 --- a/drivers/serial/jsm/jsm.h +++ b/drivers/serial/jsm/jsm.h @@ -130,8 +130,6 @@ struct jsm_board struct pci_dev *pci_dev; u32 maxports; /* MAX ports this board can handle */ - spinlock_t bd_lock; /* Used to protect board */ - spinlock_t bd_intr_lock; /* Used to protect the poller tasklet and * the interrupt routine from each other. */ diff --git a/drivers/serial/jsm/jsm_driver.c b/drivers/serial/jsm/jsm_driver.c index d2d32a19862..b3604aa322a 100644 --- a/drivers/serial/jsm/jsm_driver.c +++ b/drivers/serial/jsm/jsm_driver.c @@ -88,7 +88,6 @@ static int __devinit jsm_probe_one(struct pci_dev *pdev, const struct pci_device else brd->maxports = 2; - spin_lock_init(&brd->bd_lock); spin_lock_init(&brd->bd_intr_lock); /* store which revision we have */ diff --git a/drivers/serial/s3c6400.c b/drivers/serial/s3c6400.c index 06936d13393..3e378523368 100644 --- a/drivers/serial/s3c6400.c +++ b/drivers/serial/s3c6400.c @@ -102,6 +102,7 @@ static struct s3c24xx_uart_info s3c6400_uart_inf = { .name = "Samsung S3C6400 UART", .type = PORT_S3C6400, .fifosize = 64, + .has_divslot = 1, .rx_fifomask = S3C2440_UFSTAT_RXMASK, .rx_fifoshift = S3C2440_UFSTAT_RXSHIFT, .rx_fifofull = S3C2440_UFSTAT_RXFULL, diff --git a/drivers/serial/samsung.c b/drivers/serial/samsung.c index e06686ae858..93b5d75db12 100644 --- a/drivers/serial/samsung.c +++ b/drivers/serial/samsung.c @@ -508,6 +508,7 @@ s3c24xx_serial_setsource(struct uart_port *port, struct s3c24xx_uart_clksrc *c) struct baud_calc { struct s3c24xx_uart_clksrc *clksrc; unsigned int calc; + unsigned int divslot; unsigned int quot; struct clk *src; }; @@ -517,6 +518,7 @@ static int s3c24xx_serial_calcbaud(struct baud_calc *calc, struct s3c24xx_uart_clksrc *clksrc, unsigned int baud) { + struct s3c24xx_uart_port *ourport = to_ourport(port); unsigned long rate; calc->src = clk_get(port->dev, clksrc->name); @@ -527,8 +529,24 @@ static int s3c24xx_serial_calcbaud(struct baud_calc *calc, rate /= clksrc->divisor; calc->clksrc = clksrc; - calc->quot = (rate + (8 * baud)) / (16 * baud); - calc->calc = (rate / (calc->quot * 16)); + + if (ourport->info->has_divslot) { + unsigned long div = rate / baud; + + /* The UDIVSLOT register on the newer UARTs allows us to + * get a divisor adjustment of 1/16th on the baud clock. + * + * We don't keep the UDIVSLOT value (the 16ths we calculated + * by not multiplying the baud by 16) as it is easy enough + * to recalculate. + */ + + calc->quot = div / 16; + calc->calc = rate / div; + } else { + calc->quot = (rate + (8 * baud)) / (16 * baud); + calc->calc = (rate / (calc->quot * 16)); + } calc->quot--; return 1; @@ -611,6 +629,30 @@ static unsigned int s3c24xx_serial_getclk(struct uart_port *port, return best->quot; } +/* udivslot_table[] + * + * This table takes the fractional value of the baud divisor and gives + * the recommended setting for the UDIVSLOT register. + */ +static u16 udivslot_table[16] = { + [0] = 0x0000, + [1] = 0x0080, + [2] = 0x0808, + [3] = 0x0888, + [4] = 0x2222, + [5] = 0x4924, + [6] = 0x4A52, + [7] = 0x54AA, + [8] = 0x5555, + [9] = 0xD555, + [10] = 0xD5D5, + [11] = 0xDDD5, + [12] = 0xDDDD, + [13] = 0xDFDD, + [14] = 0xDFDF, + [15] = 0xFFDF, +}; + static void s3c24xx_serial_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) @@ -623,6 +665,7 @@ static void s3c24xx_serial_set_termios(struct uart_port *port, unsigned int baud, quot; unsigned int ulcon; unsigned int umcon; + unsigned int udivslot = 0; /* * We don't support modem control lines. @@ -644,6 +687,7 @@ static void s3c24xx_serial_set_termios(struct uart_port *port, /* check to see if we need to change clock source */ if (ourport->clksrc != clksrc || ourport->baudclk != clk) { + dbg("selecting clock %p\n", clk); s3c24xx_serial_setsource(port, clksrc); if (ourport->baudclk != NULL && !IS_ERR(ourport->baudclk)) { @@ -658,6 +702,13 @@ static void s3c24xx_serial_set_termios(struct uart_port *port, ourport->baudclk_rate = clk ? clk_get_rate(clk) : 0; } + if (ourport->info->has_divslot) { + unsigned int div = ourport->baudclk_rate / baud; + + udivslot = udivslot_table[div & 15]; + dbg("udivslot = %04x (div %d)\n", udivslot, div & 15); + } + switch (termios->c_cflag & CSIZE) { case CS5: dbg("config: 5bits/char\n"); @@ -697,12 +748,16 @@ static void s3c24xx_serial_set_termios(struct uart_port *port, spin_lock_irqsave(&port->lock, flags); - dbg("setting ulcon to %08x, brddiv to %d\n", ulcon, quot); + dbg("setting ulcon to %08x, brddiv to %d, udivslot %08x\n", + ulcon, quot, udivslot); wr_regl(port, S3C2410_ULCON, ulcon); wr_regl(port, S3C2410_UBRDIV, quot); wr_regl(port, S3C2410_UMCON, umcon); + if (ourport->info->has_divslot) + wr_regl(port, S3C2443_DIVSLOT, udivslot); + dbg("uart: ulcon = 0x%08x, ucon = 0x%08x, ufcon = 0x%08x\n", rd_regl(port, S3C2410_ULCON), rd_regl(port, S3C2410_UCON), diff --git a/drivers/serial/samsung.h b/drivers/serial/samsung.h index 571d6b90d20..7afb94843a0 100644 --- a/drivers/serial/samsung.h +++ b/drivers/serial/samsung.h @@ -21,6 +21,10 @@ struct s3c24xx_uart_info { unsigned long tx_fifoshift; unsigned long tx_fifofull; + /* uart port features */ + + unsigned int has_divslot:1; + /* clock source control */ int (*get_clksrc)(struct uart_port *, struct s3c24xx_uart_clksrc *clk); diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c index 885194a0741..3f3c08c6ba4 100644 --- a/drivers/spi/pxa2xx_spi.c +++ b/drivers/spi/pxa2xx_spi.c @@ -1373,6 +1373,9 @@ static void cleanup(struct spi_device *spi) { struct chip_data *chip = spi_get_ctldata(spi); + if (!chip) + return; + if (gpio_is_valid(chip->gpio_cs)) gpio_free(chip->gpio_cs); diff --git a/drivers/staging/comedi/TODO b/drivers/staging/comedi/TODO index 55781295846..15c9348fb93 100644 --- a/drivers/staging/comedi/TODO +++ b/drivers/staging/comedi/TODO @@ -11,4 +11,3 @@ Please send patches to Greg Kroah-Hartman <greg@kroah.com> and copy: Ian Abbott <abbotti@mev.co.uk> Frank Mori Hess <fmhess@users.sourceforge.net> - David Schleef <ds@schleef.org> diff --git a/drivers/staging/rt2870/rt2870.h b/drivers/staging/rt2870/rt2870.h index a42caa37080..a69cf338e49 100644 --- a/drivers/staging/rt2870/rt2870.h +++ b/drivers/staging/rt2870/rt2870.h @@ -145,6 +145,7 @@ {USB_DEVICE(0x0789,0x0162)}, /* Logitec */ \ {USB_DEVICE(0x0789,0x0163)}, /* Logitec */ \ {USB_DEVICE(0x0789,0x0164)}, /* Logitec */ \ + {USB_DEVICE(0x7392,0x7717)}, /* Edimax */ \ { }/* Terminating entry */ \ } diff --git a/drivers/staging/rtl8187se/r8180.h b/drivers/staging/rtl8187se/r8180.h index 12215fc61dd..db446b7e2e0 100644 --- a/drivers/staging/rtl8187se/r8180.h +++ b/drivers/staging/rtl8187se/r8180.h @@ -19,7 +19,7 @@ #define R8180H -#define RTL8180_MODULE_NAME "rtl8180" +#define RTL8180_MODULE_NAME "r8180" #define DMESG(x,a...) printk(KERN_INFO RTL8180_MODULE_NAME ": " x "\n", ## a) #define DMESGW(x,a...) printk(KERN_WARNING RTL8180_MODULE_NAME ": WW:" x "\n", ## a) #define DMESGE(x,a...) printk(KERN_WARNING RTL8180_MODULE_NAME ": EE:" x "\n", ## a) diff --git a/drivers/staging/rtl8187se/r8180_core.c b/drivers/staging/rtl8187se/r8180_core.c index 6ecd12de429..e10413cee0d 100644 --- a/drivers/staging/rtl8187se/r8180_core.c +++ b/drivers/staging/rtl8187se/r8180_core.c @@ -640,11 +640,9 @@ void rtl8180_proc_init_one(struct net_device *dev) { struct proc_dir_entry *e; struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - priv->dir_dev = create_proc_entry(dev->name, - S_IFDIR | S_IRUGO | S_IXUGO, - rtl8180_proc); + priv->dir_dev = rtl8180_proc; if (!priv->dir_dev) { - DMESGE("Unable to initialize /proc/net/rtl8180/%s\n", + DMESGE("Unable to initialize /proc/net/r8180/%s\n", dev->name); return; } @@ -654,7 +652,7 @@ void rtl8180_proc_init_one(struct net_device *dev) if (!e) { DMESGE("Unable to initialize " - "/proc/net/rtl8180/%s/stats-hw\n", + "/proc/net/r8180/%s/stats-hw\n", dev->name); } @@ -663,7 +661,7 @@ void rtl8180_proc_init_one(struct net_device *dev) if (!e) { DMESGE("Unable to initialize " - "/proc/net/rtl8180/%s/stats-rx\n", + "/proc/net/r8180/%s/stats-rx\n", dev->name); } @@ -673,7 +671,7 @@ void rtl8180_proc_init_one(struct net_device *dev) if (!e) { DMESGE("Unable to initialize " - "/proc/net/rtl8180/%s/stats-tx\n", + "/proc/net/r8180/%s/stats-tx\n", dev->name); } #if 0 @@ -702,7 +700,7 @@ void rtl8180_proc_init_one(struct net_device *dev) if (!e) { DMESGE("Unable to initialize " - "/proc/net/rtl8180/%s/registers\n", + "/proc/net/r8180/%s/registers\n", dev->name); } } @@ -977,13 +975,6 @@ void check_tx_ring(struct net_device *dev, int pri) *tmp & (1<<15)? "ok": "err", *(tmp+4)); } - DMESG("nic at %d", - (nic-nicbegin) / 8 /4); - DMESG("tail at %d", ((int)tail - (int)begin) /8 /4); - DMESG("head at %d", ((int)head - (int)begin) /8 /4); - DMESG("check free desc returns %d", check_nic_enought_desc(dev,pri)); - DMESG("free desc is %d\n", get_curr_tx_free_desc(dev,pri)); - //rtl8180_reset(dev); return; } @@ -1736,17 +1727,7 @@ short alloc_tx_desc_ring(struct net_device *dev, int bufsize, int count, * descriptor's buffer must be 256 byte aligned * we shouldn't be here, since we set DMA mask ! */ - DMESGW("Fixing TX alignment"); - desc = (u32*)((u8*)desc + 256); -#if (defined(CONFIG_HIGHMEM64G) || defined(CONFIG_64BIT_PHYS_ADDR)) - desc = (u32*)((u64)desc &~ 0xff); - dma_desc = (dma_addr_t)((u8*)dma_desc + 256); - dma_desc = (dma_addr_t)((u64)dma_desc &~ 0xff); -#else - desc = (u32*)((u32)desc &~ 0xff); - dma_desc = (dma_addr_t)((u8*)dma_desc + 256); - dma_desc = (dma_addr_t)((u32)dma_desc &~ 0xff); -#endif + WARN(1, "DMA buffer is not aligned\n"); } tmp=desc; for (i=0;i<count;i++) @@ -1984,18 +1965,7 @@ short alloc_rx_desc_ring(struct net_device *dev, u16 bufsize, int count) * descriptor's buffer must be 256 byte aligned * should never happen since we specify the DMA mask */ - - DMESGW("Fixing RX alignment"); - desc = (u32*)((u8*)desc + 256); -#if (defined(CONFIG_HIGHMEM64G) || defined(CONFIG_64BIT_PHYS_ADDR)) - desc = (u32*)((u64)desc &~ 0xff); - dma_desc = (dma_addr_t)((u8*)dma_desc + 256); - dma_desc = (dma_addr_t)((u64)dma_desc &~ 0xff); -#else - desc = (u32*)((u32)desc &~ 0xff); - dma_desc = (dma_addr_t)((u8*)dma_desc + 256); - dma_desc = (dma_addr_t)((u32)dma_desc &~ 0xff); -#endif + WARN(1, "DMA buffer is not aligned\n"); } priv->rxring=desc; diff --git a/drivers/staging/winbond/wbusb.c b/drivers/staging/winbond/wbusb.c index 9c3f9439f35..3b2d52819b4 100644 --- a/drivers/staging/winbond/wbusb.c +++ b/drivers/staging/winbond/wbusb.c @@ -386,7 +386,7 @@ static int wb35_probe(struct usb_interface *intf, const struct usb_device_id *id if (err) goto error_free_hw; - usb_set_intfdata(intf, priv); + usb_set_intfdata(intf, dev); return 0; @@ -415,10 +415,15 @@ static void wb35_hw_halt(struct wbsoft_priv *adapter) static void wb35_disconnect(struct usb_interface *intf) { - struct wbsoft_priv *priv = usb_get_intfdata(intf); + struct ieee80211_hw *hw = usb_get_intfdata(intf); + struct wbsoft_priv *priv = hw->priv; wb35_hw_halt(priv); + ieee80211_stop_queues(hw); + ieee80211_unregister_hw(hw); + ieee80211_free_hw(hw); + usb_set_intfdata(intf, NULL); usb_put_dev(interface_to_usbdev(intf)); } diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile index 89299a5ce16..0716cdb44cd 100644 --- a/drivers/usb/Makefile +++ b/drivers/usb/Makefile @@ -27,6 +27,8 @@ obj-$(CONFIG_USB_WUSB) += wusbcore/ obj-$(CONFIG_USB_ACM) += class/ obj-$(CONFIG_USB_PRINTER) += class/ +obj-$(CONFIG_USB_WDM) += class/ +obj-$(CONFIG_USB_TMC) += class/ obj-$(CONFIG_USB_STORAGE) += storage/ obj-$(CONFIG_USB) += storage/ diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c index 6789089e246..56802d2e994 100644 --- a/drivers/usb/atm/cxacru.c +++ b/drivers/usb/atm/cxacru.c @@ -227,8 +227,14 @@ static ssize_t cxacru_sysfs_showattr_s8(s8 value, char *buf) static ssize_t cxacru_sysfs_showattr_dB(s16 value, char *buf) { - return snprintf(buf, PAGE_SIZE, "%d.%02u\n", - value / 100, abs(value) % 100); + if (likely(value >= 0)) { + return snprintf(buf, PAGE_SIZE, "%u.%02u\n", + value / 100, value % 100); + } else { + value = -value; + return snprintf(buf, PAGE_SIZE, "-%u.%02u\n", + value / 100, value % 100); + } } static ssize_t cxacru_sysfs_showattr_bool(u32 value, char *buf) diff --git a/drivers/usb/gadget/usbstring.c b/drivers/usb/gadget/usbstring.c index 4154be375c7..58c4d37d312 100644 --- a/drivers/usb/gadget/usbstring.c +++ b/drivers/usb/gadget/usbstring.c @@ -38,7 +38,7 @@ static int utf8_to_utf16le(const char *s, __le16 *cp, unsigned len) uchar = (c & 0x1f) << 6; c = (u8) *s++; - if ((c & 0xc0) != 0xc0) + if ((c & 0xc0) != 0x80) goto fail; c &= 0x3f; uchar |= c; @@ -49,13 +49,13 @@ static int utf8_to_utf16le(const char *s, __le16 *cp, unsigned len) uchar = (c & 0x0f) << 12; c = (u8) *s++; - if ((c & 0xc0) != 0xc0) + if ((c & 0xc0) != 0x80) goto fail; c &= 0x3f; uchar |= c << 6; c = (u8) *s++; - if ((c & 0xc0) != 0xc0) + if ((c & 0xc0) != 0x80) goto fail; c &= 0x3f; uchar |= c; diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 8100f1d2590..0ab8474b00c 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -56,6 +56,7 @@ static __u16 vendor = FTDI_VID; static __u16 product; struct ftdi_private { + struct kref kref; ftdi_chip_type_t chip_type; /* type of device, either SIO or FT8U232AM */ int baud_base; /* baud base clock for divisor setting */ @@ -669,6 +670,8 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(ADI_VID, ADI_GNICE_PID), .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, { USB_DEVICE(JETI_VID, JETI_SPC1201_PID) }, + { USB_DEVICE(MARVELL_VID, MARVELL_SHEEVAPLUG_PID), + .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, { }, /* Optional parameter entry */ { } /* Terminating entry */ }; @@ -1352,6 +1355,7 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port) return -ENOMEM; } + kref_init(&priv->kref); spin_lock_init(&priv->rx_lock); spin_lock_init(&priv->tx_lock); init_waitqueue_head(&priv->delta_msr_wait); @@ -1468,6 +1472,13 @@ static void ftdi_shutdown(struct usb_serial *serial) dbg("%s", __func__); } +static void ftdi_sio_priv_release(struct kref *k) +{ + struct ftdi_private *priv = container_of(k, struct ftdi_private, kref); + + kfree(priv); +} + static int ftdi_sio_port_remove(struct usb_serial_port *port) { struct ftdi_private *priv = usb_get_serial_port_data(port); @@ -1482,7 +1493,7 @@ static int ftdi_sio_port_remove(struct usb_serial_port *port) if (priv) { usb_set_serial_port_data(port, NULL); - kfree(priv); + kref_put(&priv->kref, ftdi_sio_priv_release); } return 0; @@ -1547,7 +1558,8 @@ static int ftdi_open(struct tty_struct *tty, dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __func__, result); - + else + kref_get(&priv->kref); return result; } /* ftdi_open */ @@ -1589,11 +1601,11 @@ static void ftdi_close(struct tty_struct *tty, mutex_unlock(&port->serial->disc_mutex); /* cancel any scheduled reading */ - cancel_delayed_work(&priv->rx_work); - flush_scheduled_work(); + cancel_delayed_work_sync(&priv->rx_work); /* shutdown our bulk read */ usb_kill_urb(port->read_urb); + kref_put(&priv->kref, ftdi_sio_priv_release); } /* ftdi_close */ diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h index c09f658a448..12330fa1c09 100644 --- a/drivers/usb/serial/ftdi_sio.h +++ b/drivers/usb/serial/ftdi_sio.h @@ -920,6 +920,12 @@ #define JETI_SPC1201_PID 0x04b2 /* + * Marvell SheevaPlug + */ +#define MARVELL_VID 0x9e88 +#define MARVELL_SHEEVAPLUG_PID 0x9e8f + +/* * BmRequestType: 1100 0000b * bRequest: FTDI_E2_READ * wValue: 0 diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index fa65a3b0860..4b8b69045fe 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -160,8 +160,9 @@ UNUSUAL_DEV( 0x0420, 0x0001, 0x0100, 0x0100, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE ), -/* Reported by Andrew Nayenko <relan@bk.ru> */ -UNUSUAL_DEV( 0x0421, 0x0019, 0x0592, 0x0592, +/* Reported by Andrew Nayenko <relan@bk.ru> + * Updated for new firmware by Phillip Potter <phillipinda@hotmail.com> */ +UNUSUAL_DEV( 0x0421, 0x0019, 0x0592, 0x0610, "Nokia", "Nokia 6288", US_SC_DEVICE, US_PR_DEVICE, NULL, diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 7826bdce4bb..0048f1185a6 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -1128,13 +1128,6 @@ config FB_INTEL 830M/845G/852GM/855GM/865G/915G/915GM/945G/945GM/965G/965GM chipsets. Say Y if you have and plan to use such a board. - If you say Y here and want DDC/I2C support you must first say Y to - "I2C support" and "I2C bit-banging support" in the character devices - section. - - If you say M here then "I2C support" and "I2C bit-banging support" - can be build either as modules or built-in. - To compile this driver as a module, choose M here: the module will be called intelfb. @@ -1207,11 +1200,10 @@ config FB_MATROX_G pixel and 32 bpp packed pixel. You can also use font widths different from 8. - If you need support for G400 secondary head, you must first say Y to - "I2C support" in the character devices section, and then to - "Matrox I2C support" and "G400 second head support" here in the - framebuffer section. G450/G550 secondary head and digital output - are supported without additional modules. + If you need support for G400 secondary head, you must say Y to + "Matrox I2C support" and "G400 second head support" right below. + G450/G550 secondary head and digital output are supported without + additional modules. The driver starts in monitor mode. You must use the matroxset tool (available at <ftp://platan.vc.cvut.cz/pub/linux/matrox-latest/>) to @@ -1310,13 +1302,6 @@ config FB_RADEON a framebuffer device. There are both PCI and AGP versions. You don't need to choose this to run the Radeon in plain VGA mode. - If you say Y here and want DDC/I2C support you must first say Y to - "I2C support" and "I2C bit-banging support" in the character devices - section. - - If you say M here then "I2C support" and "I2C bit-banging support" - can be build either as modules or built-in. - There is a product page at http://apps.ati.com/ATIcompare/ diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 0dbd6c68d76..d8d0be5151e 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -56,7 +56,6 @@ obj-$(CONFIG_FB_CT65550) += chipsfb.o obj-$(CONFIG_FB_IMSTT) += imsttfb.o obj-$(CONFIG_FB_FM2) += fm2fb.o obj-$(CONFIG_FB_VT8623) += vt8623fb.o -obj-$(CONFIG_FB_CYBLA) += cyblafb.o obj-$(CONFIG_FB_TRIDENT) += tridentfb.o obj-$(CONFIG_FB_LE80578) += vermilion/ obj-$(CONFIG_FB_S3) += s3fb.o diff --git a/drivers/video/cfbfillrect.c b/drivers/video/cfbfillrect.c index 64b35766b2a..ba9f58b2a5e 100644 --- a/drivers/video/cfbfillrect.c +++ b/drivers/video/cfbfillrect.c @@ -9,10 +9,6 @@ * * NOTES: * - * The code for depths like 24 that don't have integer number of pixels per - * long is broken and needs to be fixed. For now I turned these types of - * mode off. - * * Also need to add code to deal with cards endians that are different than * the native cpu endians. I also need to deal with MSB position in the word. * @@ -139,7 +135,7 @@ bitfill_unaligned(struct fb_info *p, unsigned long __iomem *dst, int dst_idx, // Trailing bits if (last) - FB_WRITEL(comp(pat, FB_READL(dst), first), dst); + FB_WRITEL(comp(pat, FB_READL(dst), last), dst); } } @@ -281,7 +277,7 @@ bitfill_unaligned_rev(struct fb_info *p, unsigned long __iomem *dst, void cfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect) { - unsigned long pat, fg; + unsigned long pat, pat2, fg; unsigned long width = rect->width, height = rect->height; int bits = BITS_PER_LONG, bytes = bits >> 3; u32 bpp = p->var.bits_per_pixel; @@ -297,7 +293,7 @@ void cfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect) else fg = rect->color; - pat = pixel_to_pat( bpp, fg); + pat = pixel_to_pat(bpp, fg); dst = (unsigned long __iomem *)((unsigned long)p->screen_base & ~(bytes-1)); dst_idx = ((unsigned long)p->screen_base & (bytes - 1))*8; @@ -333,17 +329,16 @@ void cfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect) dst_idx += p->fix.line_length*8; } } else { - int right; - int r; - int rot = (left-dst_idx) % bpp; + int right, r; void (*fill_op)(struct fb_info *p, unsigned long __iomem *dst, int dst_idx, unsigned long pat, int left, int right, unsigned n, int bits) = NULL; - - /* rotate pattern to correct start position */ - pat = pat << rot | pat >> (bpp-rot); - - right = bpp-left; +#ifdef __LITTLE_ENDIAN + right = left; + left = bpp - right; +#else + right = bpp - left; +#endif switch (rect->rop) { case ROP_XOR: fill_op = bitfill_unaligned_rev; @@ -352,17 +347,18 @@ void cfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect) fill_op = bitfill_unaligned; break; default: - printk( KERN_ERR "cfb_fillrect(): unknown rop, defaulting to ROP_COPY\n"); + printk(KERN_ERR "cfb_fillrect(): unknown rop, defaulting to ROP_COPY\n"); fill_op = bitfill_unaligned; break; } while (height--) { - dst += dst_idx >> (ffs(bits) - 1); + dst += dst_idx / bits; dst_idx &= (bits - 1); - fill_op(p, dst, dst_idx, pat, left, right, + r = dst_idx % bpp; + /* rotate pattern to the correct start position */ + pat2 = le_long_to_cpu(rolx(cpu_to_le_long(pat), r, bpp)); + fill_op(p, dst, dst_idx, pat2, left, right, width*bpp, bits); - r = (p->fix.line_length*8) % bpp; - pat = pat << (bpp-r) | pat >> r; dst_idx += p->fix.line_length*8; } } diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c index d012edda6d1..38e86b84dce 100644 --- a/drivers/video/console/vgacon.c +++ b/drivers/video/console/vgacon.c @@ -1282,7 +1282,7 @@ static int vgacon_font_get(struct vc_data *c, struct console_font *font) font->charcount = vga_512_chars ? 512 : 256; if (!font->data) return 0; - return vgacon_do_font_op(&state, font->data, 0, 0); + return vgacon_do_font_op(&state, font->data, 0, vga_512_chars); } #else diff --git a/drivers/video/fb_draw.h b/drivers/video/fb_draw.h index 1db622192bd..04c01faaf77 100644 --- a/drivers/video/fb_draw.h +++ b/drivers/video/fb_draw.h @@ -33,11 +33,11 @@ pixel_to_pat( u32 bpp, u32 pixel) case 8: return 0x0101010101010101ul*pixel; case 12: - return 0x0001001001001001ul*pixel; + return 0x1001001001001001ul*pixel; case 16: return 0x0001000100010001ul*pixel; case 24: - return 0x0000000001000001ul*pixel; + return 0x0001000001000001ul*pixel; case 32: return 0x0000000100000001ul*pixel; default: @@ -58,11 +58,11 @@ pixel_to_pat( u32 bpp, u32 pixel) case 8: return 0x01010101ul*pixel; case 12: - return 0x00001001ul*pixel; + return 0x01001001ul*pixel; case 16: return 0x00010001ul*pixel; case 24: - return 0x00000001ul*pixel; + return 0x01000001ul*pixel; case 32: return 0x00000001ul*pixel; default: @@ -167,4 +167,17 @@ static inline unsigned long fb_rev_pixels_in_long(unsigned long val, #endif /* CONFIG_FB_CFB_REV_PIXELS_IN_BYTE */ +#define cpu_to_le_long _cpu_to_le_long(BITS_PER_LONG) +#define _cpu_to_le_long(x) __cpu_to_le_long(x) +#define __cpu_to_le_long(x) cpu_to_le##x + +#define le_long_to_cpu _le_long_to_cpu(BITS_PER_LONG) +#define _le_long_to_cpu(x) __le_long_to_cpu(x) +#define __le_long_to_cpu(x) le##x##_to_cpu + +static inline unsigned long rolx(unsigned long word, unsigned int shift, unsigned int x) +{ + return (word << shift) | (word >> (x - shift)); +} + #endif /* FB_DRAW_H */ diff --git a/drivers/video/mx3fb.c b/drivers/video/mx3fb.c index 21b3692092f..9894de1c9b9 100644 --- a/drivers/video/mx3fb.c +++ b/drivers/video/mx3fb.c @@ -1152,11 +1152,11 @@ static struct fb_ops mx3fb_ops = { */ static int mx3fb_suspend(struct platform_device *pdev, pm_message_t state) { - struct mx3fb_data *drv_data = platform_get_drvdata(pdev); - struct mx3fb_info *mx3_fbi = drv_data->fbi->par; + struct mx3fb_data *mx3fb = platform_get_drvdata(pdev); + struct mx3fb_info *mx3_fbi = mx3fb->fbi->par; acquire_console_sem(); - fb_set_suspend(drv_data->fbi, 1); + fb_set_suspend(mx3fb->fbi, 1); release_console_sem(); if (mx3_fbi->blank == FB_BLANK_UNBLANK) { @@ -1172,16 +1172,16 @@ static int mx3fb_suspend(struct platform_device *pdev, pm_message_t state) */ static int mx3fb_resume(struct platform_device *pdev) { - struct mx3fb_data *drv_data = platform_get_drvdata(pdev); - struct mx3fb_info *mx3_fbi = drv_data->fbi->par; + struct mx3fb_data *mx3fb = platform_get_drvdata(pdev); + struct mx3fb_info *mx3_fbi = mx3fb->fbi->par; if (mx3_fbi->blank == FB_BLANK_UNBLANK) { sdc_enable_channel(mx3_fbi); - sdc_set_brightness(mx3fb, drv_data->backlight_level); + sdc_set_brightness(mx3fb, mx3fb->backlight_level); } acquire_console_sem(); - fb_set_suspend(drv_data->fbi, 0); + fb_set_suspend(mx3fb->fbi, 0); release_console_sem(); return 0; diff --git a/drivers/video/sysfillrect.c b/drivers/video/sysfillrect.c index f94d6b6e29e..33ee3d34f9d 100644 --- a/drivers/video/sysfillrect.c +++ b/drivers/video/sysfillrect.c @@ -124,7 +124,7 @@ bitfill_unaligned(struct fb_info *p, unsigned long *dst, int dst_idx, /* Trailing bits */ if (last) - *dst = comp(pat, *dst, first); + *dst = comp(pat, *dst, last); } } @@ -242,7 +242,7 @@ bitfill_unaligned_rev(struct fb_info *p, unsigned long *dst, int dst_idx, void sys_fillrect(struct fb_info *p, const struct fb_fillrect *rect) { - unsigned long pat, fg; + unsigned long pat, pat2, fg; unsigned long width = rect->width, height = rect->height; int bits = BITS_PER_LONG, bytes = bits >> 3; u32 bpp = p->var.bits_per_pixel; @@ -292,17 +292,16 @@ void sys_fillrect(struct fb_info *p, const struct fb_fillrect *rect) dst_idx += p->fix.line_length*8; } } else { - int right; - int r; - int rot = (left-dst_idx) % bpp; + int right, r; void (*fill_op)(struct fb_info *p, unsigned long *dst, int dst_idx, unsigned long pat, int left, int right, unsigned n, int bits) = NULL; - - /* rotate pattern to correct start position */ - pat = pat << rot | pat >> (bpp-rot); - - right = bpp-left; +#ifdef __LITTLE_ENDIAN + right = left; + left = bpp - right; +#else + right = bpp - left; +#endif switch (rect->rop) { case ROP_XOR: fill_op = bitfill_unaligned_rev; @@ -311,18 +310,19 @@ void sys_fillrect(struct fb_info *p, const struct fb_fillrect *rect) fill_op = bitfill_unaligned; break; default: - printk(KERN_ERR "cfb_fillrect(): unknown rop, " + printk(KERN_ERR "sys_fillrect(): unknown rop, " "defaulting to ROP_COPY\n"); fill_op = bitfill_unaligned; break; } while (height--) { - dst += dst_idx >> (ffs(bits) - 1); + dst += dst_idx / bits; dst_idx &= (bits - 1); - fill_op(p, dst, dst_idx, pat, left, right, + r = dst_idx % bpp; + /* rotate pattern to the correct start position */ + pat2 = le_long_to_cpu(rolx(cpu_to_le_long(pat), r, bpp)); + fill_op(p, dst, dst_idx, pat2, left, right, width*bpp, bits); - r = (p->fix.line_length*8) % bpp; - pat = pat << (bpp-r) | pat >> r; dst_idx += p->fix.line_length*8; } } diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c index e327b84820d..a0fec298216 100644 --- a/drivers/video/via/viafbdev.c +++ b/drivers/video/via/viafbdev.c @@ -2103,7 +2103,7 @@ static void viafb_remove_proc(struct proc_dir_entry *viafb_entry) static int __devinit via_pci_probe(void) { - unsigned int default_xres, default_yres; + unsigned long default_xres, default_yres; char *tmpc, *tmpm; char *tmpc_sec, *tmpm_sec; int vmode_index; @@ -2196,8 +2196,8 @@ static int __devinit via_pci_probe(void) viafb_FB_MM = viaparinfo->fbmem_virt; tmpm = viafb_mode; tmpc = strsep(&tmpm, "x"); - strict_strtoul(tmpc, 0, (unsigned long *)&default_xres); - strict_strtoul(tmpm, 0, (unsigned long *)&default_yres); + strict_strtoul(tmpc, 0, &default_xres); + strict_strtoul(tmpm, 0, &default_yres); vmode_index = viafb_get_mode_index(default_xres, default_yres, 0); DEBUG_MSG(KERN_INFO "0->index=%d\n", vmode_index); diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c index efa4b363ce7..f5bbd9e8341 100644 --- a/drivers/xen/balloon.c +++ b/drivers/xen/balloon.c @@ -513,7 +513,8 @@ static ssize_t show_target(struct sys_device *dev, struct sysdev_attribute *attr char *buf) { return sprintf(buf, "%llu\n", - (u64)balloon_stats.target_pages << PAGE_SHIFT); + (unsigned long long)balloon_stats.target_pages + << PAGE_SHIFT); } static ssize_t store_target(struct sys_device *dev, diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c index 5f8ab8adb5f..ab5547ff29a 100644 --- a/fs/9p/vfs_super.c +++ b/fs/9p/vfs_super.c @@ -37,6 +37,7 @@ #include <linux/mount.h> #include <linux/idr.h> #include <linux/sched.h> +#include <linux/smp_lock.h> #include <net/9p/9p.h> #include <net/9p/client.h> @@ -155,6 +156,7 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags, root = d_alloc_root(inode); if (!root) { + iput(inode); retval = -ENOMEM; goto release_sb; } @@ -173,10 +175,7 @@ P9_DPRINTK(P9_DEBUG_VFS, " simple set mount, return 0\n"); return 0; release_sb: - if (sb) { - up_write(&sb->s_umount); - deactivate_super(sb); - } + deactivate_locked_super(sb); free_stat: kfree(st); @@ -230,9 +229,12 @@ static int v9fs_show_options(struct seq_file *m, struct vfsmount *mnt) static void v9fs_umount_begin(struct super_block *sb) { - struct v9fs_session_info *v9ses = sb->s_fs_info; + struct v9fs_session_info *v9ses; + lock_kernel(); + v9ses = sb->s_fs_info; v9fs_session_cancel(v9ses); + unlock_kernel(); } static const struct super_operations v9fs_super_ops = { diff --git a/fs/affs/super.c b/fs/affs/super.c index 5ce695e707f..63f5183f263 100644 --- a/fs/affs/super.c +++ b/fs/affs/super.c @@ -507,8 +507,7 @@ affs_remount(struct super_block *sb, int *flags, char *data) kfree(new_opts); return -EINVAL; } - kfree(sb->s_options); - sb->s_options = new_opts; + replace_mount_options(sb, new_opts); sbi->s_flags = mount_flags; sbi->s_mode = mode; diff --git a/fs/afs/super.c b/fs/afs/super.c index aee239a048c..76828e5f8a3 100644 --- a/fs/afs/super.c +++ b/fs/afs/super.c @@ -405,21 +405,20 @@ static int afs_get_sb(struct file_system_type *fs_type, sb->s_flags = flags; ret = afs_fill_super(sb, ¶ms); if (ret < 0) { - up_write(&sb->s_umount); - deactivate_super(sb); + deactivate_locked_super(sb); goto error; } - sb->s_options = new_opts; + save_mount_options(sb, new_opts); sb->s_flags |= MS_ACTIVE; } else { _debug("reuse"); - kfree(new_opts); ASSERTCMP(sb->s_flags, &, MS_ACTIVE); } simple_set_mnt(mnt, sb); afs_put_volume(params.volume); afs_put_cell(params.cell); + kfree(new_opts); _leave(" = 0 [%p]", sb); return 0; diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c index 75f7ddacf7d..3077d8f1652 100644 --- a/fs/autofs4/expire.c +++ b/fs/autofs4/expire.c @@ -70,8 +70,10 @@ static int autofs4_mount_busy(struct vfsmount *mnt, struct dentry *dentry) * Otherwise it's an offset mount and we need to check * if we can umount its mount, if there is one. */ - if (!d_mountpoint(dentry)) + if (!d_mountpoint(dentry)) { + status = 0; goto done; + } } /* Update the expiry counter if fs is busy */ diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c index 70cfc4b84ae..fdb66faa24f 100644 --- a/fs/binfmt_elf_fdpic.c +++ b/fs/binfmt_elf_fdpic.c @@ -1388,7 +1388,7 @@ static void fill_prstatus(struct elf_prstatus *prstatus, prstatus->pr_sigpend = p->pending.signal.sig[0]; prstatus->pr_sighold = p->blocked.sig[0]; prstatus->pr_pid = task_pid_vnr(p); - prstatus->pr_ppid = task_pid_vnr(p->parent); + prstatus->pr_ppid = task_pid_vnr(p->real_parent); prstatus->pr_pgrp = task_pgrp_vnr(p); prstatus->pr_sid = task_session_vnr(p); if (thread_group_leader(p)) { @@ -1433,7 +1433,7 @@ static int fill_psinfo(struct elf_prpsinfo *psinfo, struct task_struct *p, psinfo->pr_psargs[len] = 0; psinfo->pr_pid = task_pid_vnr(p); - psinfo->pr_ppid = task_pid_vnr(p->parent); + psinfo->pr_ppid = task_pid_vnr(p->real_parent); psinfo->pr_pgrp = task_pgrp_vnr(p); psinfo->pr_sid = task_session_vnr(p); diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 3536bdb2d7c..6dfae5b28f5 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -502,8 +502,7 @@ static int btrfs_get_sb(struct file_system_type *fs_type, int flags, if (s->s_root) { if ((flags ^ s->s_flags) & MS_RDONLY) { - up_write(&s->s_umount); - deactivate_super(s); + deactivate_locked_super(s); error = -EBUSY; goto error_close_devices; } @@ -517,8 +516,7 @@ static int btrfs_get_sb(struct file_system_type *fs_type, int flags, error = btrfs_fill_super(s, fs_devices, data, flags & MS_SILENT ? 1 : 0); if (error) { - up_write(&s->s_umount); - deactivate_super(s); + deactivate_locked_super(s); goto error_free_subvol_name; } @@ -535,15 +533,13 @@ static int btrfs_get_sb(struct file_system_type *fs_type, int flags, mutex_unlock(&s->s_root->d_inode->i_mutex); if (IS_ERR(root)) { - up_write(&s->s_umount); - deactivate_super(s); + deactivate_locked_super(s); error = PTR_ERR(root); goto error_free_subvol_name; } if (!root->d_inode) { dput(root); - up_write(&s->s_umount); - deactivate_super(s); + deactivate_locked_super(s); error = -ENXIO; goto error_free_subvol_name; } diff --git a/fs/buffer.c b/fs/buffer.c index b3e5be7514f..aed297739eb 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -2397,7 +2397,8 @@ block_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf, if ((page->mapping != inode->i_mapping) || (page_offset(page) > size)) { /* page got truncated out from underneath us */ - goto out_unlock; + unlock_page(page); + goto out; } /* page is wholly or partially inside EOF */ @@ -2411,14 +2412,15 @@ block_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf, ret = block_commit_write(page, 0, end); if (unlikely(ret)) { + unlock_page(page); if (ret == -ENOMEM) ret = VM_FAULT_OOM; else /* -ENOSPC, -EIO, etc */ ret = VM_FAULT_SIGBUS; - } + } else + ret = VM_FAULT_LOCKED; -out_unlock: - unlock_page(page); +out: return ret; } diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index 9d1fb6ec8a5..f20c4069c22 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES @@ -1,3 +1,16 @@ +Version 1.58 +------------ +Guard against buffer overruns in various UCS-2 to UTF-8 string conversions +when the UTF-8 string is composed of unusually long (more than 4 byte) converted +characters. Add support for mounting root of a share which redirects immediately +to DFS target. Convert string conversion functions from Unicode to more +accurately mark string length before allocating memory (which may help the +rare cases where a UTF-8 string is much larger than the UCS2 string that +we converted from). Fix endianness of the vcnum field used during +session setup to distinguish multiple mounts to same server from different +userids. Raw NTLMSSP fixed (it requires /proc/fs/cifs/experimental +flag to be set to 2, and mount must enable krb5 to turn on extended security). + Version 1.57 ------------ Improve support for multiple security contexts to the same server. We diff --git a/fs/cifs/README b/fs/cifs/README index 07434181623..db208ddb989 100644 --- a/fs/cifs/README +++ b/fs/cifs/README @@ -651,7 +651,15 @@ Experimental When set to 1 used to enable certain experimental signing turned on in case buffer was modified just before it was sent, also this flag will be used to use the new experimental directory change - notification code). + notification code). When set to 2 enables + an additional experimental feature, "raw ntlmssp" + session establishment support (which allows + specifying "sec=ntlmssp" on mount). The Linux cifs + module will use ntlmv2 authentication encapsulated + in "raw ntlmssp" (not using SPNEGO) when + "sec=ntlmssp" is specified on mount. + This support also requires building cifs with + the CONFIG_CIFS_EXPERIMENTAL configuration flag. These experimental features and tracing can be enabled by changing flags in /proc/fs/cifs (after the cifs module has been installed or built into the diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c index 5fdbf8a1447..83d62759c7c 100644 --- a/fs/cifs/cifs_dfs_ref.c +++ b/fs/cifs/cifs_dfs_ref.c @@ -340,28 +340,24 @@ cifs_dfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd) cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); for (i = 0; i < num_referrals; i++) { + int len; dump_referral(referrals+i); - /* connect to a storage node */ - if (referrals[i].flags & DFSREF_STORAGE_SERVER) { - int len; - len = strlen(referrals[i].node_name); - if (len < 2) { - cERROR(1, ("%s: Net Address path too short: %s", + /* connect to a node */ + len = strlen(referrals[i].node_name); + if (len < 2) { + cERROR(1, ("%s: Net Address path too short: %s", __func__, referrals[i].node_name)); - rc = -EINVAL; - goto out_err; - } - mnt = cifs_dfs_do_refmount(nd->path.mnt, - nd->path.dentry, - referrals + i); - cFYI(1, ("%s: cifs_dfs_do_refmount:%s , mnt:%p", - __func__, + rc = -EINVAL; + goto out_err; + } + mnt = cifs_dfs_do_refmount(nd->path.mnt, + nd->path.dentry, referrals + i); + cFYI(1, ("%s: cifs_dfs_do_refmount:%s , mnt:%p", __func__, referrals[i].node_name, mnt)); - /* complete mount procedure if we accured submount */ - if (!IS_ERR(mnt)) - break; - } + /* complete mount procedure if we accured submount */ + if (!IS_ERR(mnt)) + break; } /* we need it cause for() above could exit without valid submount */ diff --git a/fs/cifs/cifs_unicode.c b/fs/cifs/cifs_unicode.c index 7d75272a6b3..60e3c4253de 100644 --- a/fs/cifs/cifs_unicode.c +++ b/fs/cifs/cifs_unicode.c @@ -1,7 +1,7 @@ /* * fs/cifs/cifs_unicode.c * - * Copyright (c) International Business Machines Corp., 2000,2005 + * Copyright (c) International Business Machines Corp., 2000,2009 * Modified by Steve French (sfrench@us.ibm.com) * * This program is free software; you can redistribute it and/or modify @@ -26,31 +26,157 @@ #include "cifs_debug.h" /* - * NAME: cifs_strfromUCS() - * - * FUNCTION: Convert little-endian unicode string to character string + * cifs_ucs2_bytes - how long will a string be after conversion? + * @ucs - pointer to input string + * @maxbytes - don't go past this many bytes of input string + * @codepage - destination codepage * + * Walk a ucs2le string and return the number of bytes that the string will + * be after being converted to the given charset, not including any null + * termination required. Don't walk past maxbytes in the source buffer. */ int -cifs_strfromUCS_le(char *to, const __le16 *from, - int len, const struct nls_table *codepage) +cifs_ucs2_bytes(const __le16 *from, int maxbytes, + const struct nls_table *codepage) { int i; - int outlen = 0; + int charlen, outlen = 0; + int maxwords = maxbytes / 2; + char tmp[NLS_MAX_CHARSET_SIZE]; - for (i = 0; (i < len) && from[i]; i++) { - int charlen; - /* 2.4.0 kernel or greater */ - charlen = - codepage->uni2char(le16_to_cpu(from[i]), &to[outlen], - NLS_MAX_CHARSET_SIZE); - if (charlen > 0) { + for (i = 0; from[i] && i < maxwords; i++) { + charlen = codepage->uni2char(le16_to_cpu(from[i]), tmp, + NLS_MAX_CHARSET_SIZE); + if (charlen > 0) outlen += charlen; - } else { - to[outlen++] = '?'; + else + outlen++; + } + + return outlen; +} + +/* + * cifs_mapchar - convert a little-endian char to proper char in codepage + * @target - where converted character should be copied + * @src_char - 2 byte little-endian source character + * @cp - codepage to which character should be converted + * @mapchar - should character be mapped according to mapchars mount option? + * + * This function handles the conversion of a single character. It is the + * responsibility of the caller to ensure that the target buffer is large + * enough to hold the result of the conversion (at least NLS_MAX_CHARSET_SIZE). + */ +static int +cifs_mapchar(char *target, const __le16 src_char, const struct nls_table *cp, + bool mapchar) +{ + int len = 1; + + if (!mapchar) + goto cp_convert; + + /* + * BB: Cannot handle remapping UNI_SLASH until all the calls to + * build_path_from_dentry are modified, as they use slash as + * separator. + */ + switch (le16_to_cpu(src_char)) { + case UNI_COLON: + *target = ':'; + break; + case UNI_ASTERIK: + *target = '*'; + break; + case UNI_QUESTION: + *target = '?'; + break; + case UNI_PIPE: + *target = '|'; + break; + case UNI_GRTRTHAN: + *target = '>'; + break; + case UNI_LESSTHAN: + *target = '<'; + break; + default: + goto cp_convert; + } + +out: + return len; + +cp_convert: + len = cp->uni2char(le16_to_cpu(src_char), target, + NLS_MAX_CHARSET_SIZE); + if (len <= 0) { + *target = '?'; + len = 1; + } + goto out; +} + +/* + * cifs_from_ucs2 - convert utf16le string to local charset + * @to - destination buffer + * @from - source buffer + * @tolen - destination buffer size (in bytes) + * @fromlen - source buffer size (in bytes) + * @codepage - codepage to which characters should be converted + * @mapchar - should characters be remapped according to the mapchars option? + * + * Convert a little-endian ucs2le string (as sent by the server) to a string + * in the provided codepage. The tolen and fromlen parameters are to ensure + * that the code doesn't walk off of the end of the buffer (which is always + * a danger if the alignment of the source buffer is off). The destination + * string is always properly null terminated and fits in the destination + * buffer. Returns the length of the destination string in bytes (including + * null terminator). + * + * Note that some windows versions actually send multiword UTF-16 characters + * instead of straight UCS-2. The linux nls routines however aren't able to + * deal with those characters properly. In the event that we get some of + * those characters, they won't be translated properly. + */ +int +cifs_from_ucs2(char *to, const __le16 *from, int tolen, int fromlen, + const struct nls_table *codepage, bool mapchar) +{ + int i, charlen, safelen; + int outlen = 0; + int nullsize = nls_nullsize(codepage); + int fromwords = fromlen / 2; + char tmp[NLS_MAX_CHARSET_SIZE]; + + /* + * because the chars can be of varying widths, we need to take care + * not to overflow the destination buffer when we get close to the + * end of it. Until we get to this offset, we don't need to check + * for overflow however. + */ + safelen = tolen - (NLS_MAX_CHARSET_SIZE + nullsize); + + for (i = 0; i < fromwords && from[i]; i++) { + /* + * check to see if converting this character might make the + * conversion bleed into the null terminator + */ + if (outlen >= safelen) { + charlen = cifs_mapchar(tmp, from[i], codepage, mapchar); + if ((outlen + charlen) > (tolen - nullsize)) + break; } + + /* put converted char into 'to' buffer */ + charlen = cifs_mapchar(&to[outlen], from[i], codepage, mapchar); + outlen += charlen; } - to[outlen] = 0; + + /* properly null-terminate string */ + for (i = 0; i < nullsize; i++) + to[outlen++] = 0; + return outlen; } @@ -88,3 +214,41 @@ cifs_strtoUCS(__le16 *to, const char *from, int len, return i; } +/* + * cifs_strndup_from_ucs - copy a string from wire format to the local codepage + * @src - source string + * @maxlen - don't walk past this many bytes in the source string + * @is_unicode - is this a unicode string? + * @codepage - destination codepage + * + * Take a string given by the server, convert it to the local codepage and + * put it in a new buffer. Returns a pointer to the new string or NULL on + * error. + */ +char * +cifs_strndup_from_ucs(const char *src, const int maxlen, const bool is_unicode, + const struct nls_table *codepage) +{ + int len; + char *dst; + + if (is_unicode) { + len = cifs_ucs2_bytes((__le16 *) src, maxlen, codepage); + len += nls_nullsize(codepage); + dst = kmalloc(len, GFP_KERNEL); + if (!dst) + return NULL; + cifs_from_ucs2(dst, (__le16 *) src, len, maxlen, codepage, + false); + } else { + len = strnlen(src, maxlen); + len++; + dst = kmalloc(len, GFP_KERNEL); + if (!dst) + return NULL; + strlcpy(dst, src, len); + } + + return dst; +} + diff --git a/fs/cifs/cifs_unicode.h b/fs/cifs/cifs_unicode.h index 14eb9a2395d..650638275a6 100644 --- a/fs/cifs/cifs_unicode.h +++ b/fs/cifs/cifs_unicode.h @@ -5,7 +5,7 @@ * Convert a unicode character to upper or lower case using * compressed tables. * - * Copyright (c) International Business Machines Corp., 2000,2007 + * Copyright (c) International Business Machines Corp., 2000,2009 * * 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 @@ -37,6 +37,19 @@ #define UNIUPR_NOLOWER /* Example to not expand lower case tables */ +/* + * Windows maps these to the user defined 16 bit Unicode range since they are + * reserved symbols (along with \ and /), otherwise illegal to store + * in filenames in NTFS + */ +#define UNI_ASTERIK (__u16) ('*' + 0xF000) +#define UNI_QUESTION (__u16) ('?' + 0xF000) +#define UNI_COLON (__u16) (':' + 0xF000) +#define UNI_GRTRTHAN (__u16) ('>' + 0xF000) +#define UNI_LESSTHAN (__u16) ('<' + 0xF000) +#define UNI_PIPE (__u16) ('|' + 0xF000) +#define UNI_SLASH (__u16) ('\\' + 0xF000) + /* Just define what we want from uniupr.h. We don't want to define the tables * in each source file. */ @@ -59,8 +72,14 @@ extern struct UniCaseRange UniLowerRange[]; #endif /* UNIUPR_NOLOWER */ #ifdef __KERNEL__ -int cifs_strfromUCS_le(char *, const __le16 *, int, const struct nls_table *); +int cifs_from_ucs2(char *to, const __le16 *from, int tolen, int fromlen, + const struct nls_table *codepage, bool mapchar); +int cifs_ucs2_bytes(const __le16 *from, int maxbytes, + const struct nls_table *codepage); int cifs_strtoUCS(__le16 *, const char *, int, const struct nls_table *); +char *cifs_strndup_from_ucs(const char *src, const int maxlen, + const bool is_unicode, + const struct nls_table *codepage); #endif /* diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 0d6d8b57365..5e6d35804d7 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -35,6 +35,7 @@ #include <linux/delay.h> #include <linux/kthread.h> #include <linux/freezer.h> +#include <linux/smp_lock.h> #include "cifsfs.h" #include "cifspdu.h" #define DECLARE_GLOBALS_HERE @@ -530,6 +531,7 @@ static void cifs_umount_begin(struct super_block *sb) if (tcon == NULL) return; + lock_kernel(); read_lock(&cifs_tcp_ses_lock); if (tcon->tc_count == 1) tcon->tidStatus = CifsExiting; @@ -548,6 +550,7 @@ static void cifs_umount_begin(struct super_block *sb) } /* BB FIXME - finish add checks for tidStatus BB */ + unlock_kernel(); return; } @@ -599,8 +602,7 @@ cifs_get_sb(struct file_system_type *fs_type, rc = cifs_read_super(sb, data, dev_name, flags & MS_SILENT ? 1 : 0); if (rc) { - up_write(&sb->s_umount); - deactivate_super(sb); + deactivate_locked_super(sb); return rc; } sb->s_flags |= MS_ACTIVE; diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index 77e190dc288..051b71cfdea 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h @@ -100,5 +100,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg); extern const struct export_operations cifs_export_ops; #endif /* EXPERIMENTAL */ -#define CIFS_VERSION "1.57" +#define CIFS_VERSION "1.58" #endif /* _CIFSFS_H */ diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index df40ab64cd9..a61ab772c6f 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -82,8 +82,8 @@ enum securityEnum { LANMAN, /* Legacy LANMAN auth */ NTLM, /* Legacy NTLM012 auth with NTLM hash */ NTLMv2, /* Legacy NTLM auth with NTLMv2 hash */ - RawNTLMSSP, /* NTLMSSP without SPNEGO */ - NTLMSSP, /* NTLMSSP via SPNEGO */ + RawNTLMSSP, /* NTLMSSP without SPNEGO, NTLMv2 hash */ + NTLMSSP, /* NTLMSSP via SPNEGO, NTLMv2 hash */ Kerberos, /* Kerberos via SPNEGO */ MSKerberos, /* MS Kerberos via SPNEGO */ }; @@ -531,6 +531,7 @@ static inline void free_dfs_info_array(struct dfs_info3_param *param, #define CIFSSEC_MAY_PLNTXT 0 #endif /* weak passwords */ #define CIFSSEC_MAY_SEAL 0x00040 /* not supported yet */ +#define CIFSSEC_MAY_NTLMSSP 0x00080 /* raw ntlmssp with ntlmv2 */ #define CIFSSEC_MUST_SIGN 0x01001 /* note that only one of the following can be set so the @@ -543,22 +544,23 @@ require use of the stronger protocol */ #define CIFSSEC_MUST_LANMAN 0x10010 #define CIFSSEC_MUST_PLNTXT 0x20020 #ifdef CONFIG_CIFS_UPCALL -#define CIFSSEC_MASK 0x3F03F /* allows weak security but also krb5 */ +#define CIFSSEC_MASK 0xAF0AF /* allows weak security but also krb5 */ #else -#define CIFSSEC_MASK 0x37037 /* current flags supported if weak */ +#define CIFSSEC_MASK 0xA70A7 /* current flags supported if weak */ #endif /* UPCALL */ #else /* do not allow weak pw hash */ #ifdef CONFIG_CIFS_UPCALL -#define CIFSSEC_MASK 0x0F00F /* flags supported if no weak allowed */ +#define CIFSSEC_MASK 0x8F08F /* flags supported if no weak allowed */ #else -#define CIFSSEC_MASK 0x07007 /* flags supported if no weak allowed */ +#define CIFSSEC_MASK 0x87087 /* flags supported if no weak allowed */ #endif /* UPCALL */ #endif /* WEAK_PW_HASH */ #define CIFSSEC_MUST_SEAL 0x40040 /* not supported yet */ +#define CIFSSEC_MUST_NTLMSSP 0x80080 /* raw ntlmssp with ntlmv2 */ #define CIFSSEC_DEF (CIFSSEC_MAY_SIGN | CIFSSEC_MAY_NTLM | CIFSSEC_MAY_NTLMV2) #define CIFSSEC_MAX (CIFSSEC_MUST_SIGN | CIFSSEC_MUST_NTLMV2) -#define CIFSSEC_AUTH_MASK (CIFSSEC_MAY_NTLM | CIFSSEC_MAY_NTLMV2 | CIFSSEC_MAY_LANMAN | CIFSSEC_MAY_PLNTXT | CIFSSEC_MAY_KRB5) +#define CIFSSEC_AUTH_MASK (CIFSSEC_MAY_NTLM | CIFSSEC_MAY_NTLMV2 | CIFSSEC_MAY_LANMAN | CIFSSEC_MAY_PLNTXT | CIFSSEC_MAY_KRB5 | CIFSSEC_MAY_NTLMSSP) /* ***************************************************************** * All constants go here diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 4167716d32f..fae083930ee 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -260,8 +260,7 @@ extern int CIFSUnixCreateSymLink(const int xid, const struct nls_table *nls_codepage); extern int CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon, - const unsigned char *searchName, - char *syminfo, const int buflen, + const unsigned char *searchName, char **syminfo, const struct nls_table *nls_codepage); extern int CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon, @@ -307,8 +306,6 @@ extern int CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon, const unsigned char *searchName, __u64 *inode_number, const struct nls_table *nls_codepage, int remap_special_chars); -extern int cifs_convertUCSpath(char *target, const __le16 *source, int maxlen, - const struct nls_table *codepage); extern int cifsConvertToUCS(__le16 *target, const char *source, int maxlen, const struct nls_table *cp, int mapChars); diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index a0845dc7b8a..75e6623a863 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -1,7 +1,7 @@ /* * fs/cifs/cifssmb.c * - * Copyright (C) International Business Machines Corp., 2002,2008 + * Copyright (C) International Business Machines Corp., 2002,2009 * Author(s): Steve French (sfrench@us.ibm.com) * * Contains the routines for constructing the SMB PDUs themselves @@ -81,41 +81,6 @@ static struct { #endif /* CONFIG_CIFS_WEAK_PW_HASH */ #endif /* CIFS_POSIX */ -/* Allocates buffer into dst and copies smb string from src to it. - * caller is responsible for freeing dst if function returned 0. - * returns: - * on success - 0 - * on failure - errno - */ -static int -cifs_strncpy_to_host(char **dst, const char *src, const int maxlen, - const bool is_unicode, const struct nls_table *nls_codepage) -{ - int plen; - - if (is_unicode) { - plen = UniStrnlen((wchar_t *)src, maxlen); - *dst = kmalloc(plen + 2, GFP_KERNEL); - if (!*dst) - goto cifs_strncpy_to_host_ErrExit; - cifs_strfromUCS_le(*dst, (__le16 *)src, plen, nls_codepage); - } else { - plen = strnlen(src, maxlen); - *dst = kmalloc(plen + 2, GFP_KERNEL); - if (!*dst) - goto cifs_strncpy_to_host_ErrExit; - strncpy(*dst, src, plen); - } - (*dst)[plen] = 0; - (*dst)[plen+1] = 0; /* harmless for ASCII case, needed for Unicode */ - return 0; - -cifs_strncpy_to_host_ErrExit: - cERROR(1, ("Failed to allocate buffer for string\n")); - return -ENOMEM; -} - - /* Mark as invalid, all open files on tree connections since they were closed when session to server was lost */ static void mark_open_files_invalid(struct cifsTconInfo *pTcon) @@ -484,6 +449,14 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) cFYI(1, ("Kerberos only mechanism, enable extended security")); pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC; } +#ifdef CONFIG_CIFS_EXPERIMENTAL + else if ((secFlags & CIFSSEC_MUST_NTLMSSP) == CIFSSEC_MUST_NTLMSSP) + pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC; + else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_NTLMSSP) { + cFYI(1, ("NTLMSSP only mechanism, enable extended security")); + pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC; + } +#endif count = 0; for (i = 0; i < CIFS_NUM_PROT; i++) { @@ -620,6 +593,8 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) server->secType = NTLMv2; else if (secFlags & CIFSSEC_MAY_KRB5) server->secType = Kerberos; + else if (secFlags & CIFSSEC_MAY_NTLMSSP) + server->secType = NTLMSSP; else if (secFlags & CIFSSEC_MAY_LANMAN) server->secType = LANMAN; /* #ifdef CONFIG_CIFS_EXPERIMENTAL @@ -2417,8 +2392,7 @@ winCreateHardLinkRetry: int CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon, - const unsigned char *searchName, - char *symlinkinfo, const int buflen, + const unsigned char *searchName, char **symlinkinfo, const struct nls_table *nls_codepage) { /* SMB_QUERY_FILE_UNIX_LINK */ @@ -2428,6 +2402,7 @@ CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon, int bytes_returned; int name_len; __u16 params, byte_count; + char *data_start; cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName)); @@ -2482,30 +2457,26 @@ querySymLinkRetry: /* decode response */ rc = validate_t2((struct smb_t2_rsp *)pSMBr); - if (rc || (pSMBr->ByteCount < 2)) /* BB also check enough total bytes returned */ - rc = -EIO; /* bad smb */ + if (rc || (pSMBr->ByteCount < 2)) + rc = -EIO; else { - __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); - __u16 count = le16_to_cpu(pSMBr->t2.DataCount); + bool is_unicode; + u16 count = le16_to_cpu(pSMBr->t2.DataCount); + + data_start = ((char *) &pSMBr->hdr.Protocol) + + le16_to_cpu(pSMBr->t2.DataOffset); + + if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) + is_unicode = true; + else + is_unicode = false; - if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) { - name_len = UniStrnlen((wchar_t *) ((char *) - &pSMBr->hdr.Protocol + data_offset), - min_t(const int, buflen, count) / 2); /* BB FIXME investigate remapping reserved chars here */ - cifs_strfromUCS_le(symlinkinfo, - (__le16 *) ((char *)&pSMBr->hdr.Protocol - + data_offset), - name_len, nls_codepage); - } else { - strncpy(symlinkinfo, - (char *) &pSMBr->hdr.Protocol + - data_offset, - min_t(const int, buflen, count)); - } - symlinkinfo[buflen] = 0; - /* just in case so calling code does not go off the end of buffer */ + *symlinkinfo = cifs_strndup_from_ucs(data_start, count, + is_unicode, nls_codepage); + if (!symlinkinfo) + rc = -ENOMEM; } } cifs_buf_release(pSMB); @@ -2603,7 +2574,6 @@ validate_ntransact(char *buf, char **ppparm, char **ppdata, *pparmlen = parm_count; return 0; } -#endif /* CIFS_EXPERIMENTAL */ int CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon, @@ -2613,7 +2583,6 @@ CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon, { int rc = 0; int bytes_returned; - int name_len; struct smb_com_transaction_ioctl_req *pSMB; struct smb_com_transaction_ioctl_rsp *pSMBr; @@ -2650,59 +2619,55 @@ CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon, } else { /* decode response */ __u32 data_offset = le32_to_cpu(pSMBr->DataOffset); __u32 data_count = le32_to_cpu(pSMBr->DataCount); - if ((pSMBr->ByteCount < 2) || (data_offset > 512)) + if ((pSMBr->ByteCount < 2) || (data_offset > 512)) { /* BB also check enough total bytes returned */ rc = -EIO; /* bad smb */ - else { - if (data_count && (data_count < 2048)) { - char *end_of_smb = 2 /* sizeof byte count */ + - pSMBr->ByteCount + - (char *)&pSMBr->ByteCount; + goto qreparse_out; + } + if (data_count && (data_count < 2048)) { + char *end_of_smb = 2 /* sizeof byte count */ + + pSMBr->ByteCount + (char *)&pSMBr->ByteCount; - struct reparse_data *reparse_buf = + struct reparse_data *reparse_buf = (struct reparse_data *) ((char *)&pSMBr->hdr.Protocol + data_offset); - if ((char *)reparse_buf >= end_of_smb) { - rc = -EIO; - goto qreparse_out; - } - if ((reparse_buf->LinkNamesBuf + - reparse_buf->TargetNameOffset + - reparse_buf->TargetNameLen) > - end_of_smb) { - cFYI(1, ("reparse buf beyond SMB")); - rc = -EIO; - goto qreparse_out; - } + if ((char *)reparse_buf >= end_of_smb) { + rc = -EIO; + goto qreparse_out; + } + if ((reparse_buf->LinkNamesBuf + + reparse_buf->TargetNameOffset + + reparse_buf->TargetNameLen) > end_of_smb) { + cFYI(1, ("reparse buf beyond SMB")); + rc = -EIO; + goto qreparse_out; + } - if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) { - name_len = UniStrnlen((wchar_t *) + if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) { + cifs_from_ucs2(symlinkinfo, (__le16 *) (reparse_buf->LinkNamesBuf + reparse_buf->TargetNameOffset), - min(buflen/2, - reparse_buf->TargetNameLen / 2)); - cifs_strfromUCS_le(symlinkinfo, - (__le16 *) (reparse_buf->LinkNamesBuf + - reparse_buf->TargetNameOffset), - name_len, nls_codepage); - } else { /* ASCII names */ - strncpy(symlinkinfo, - reparse_buf->LinkNamesBuf + - reparse_buf->TargetNameOffset, - min_t(const int, buflen, - reparse_buf->TargetNameLen)); - } - } else { - rc = -EIO; - cFYI(1, ("Invalid return data count on " - "get reparse info ioctl")); + buflen, + reparse_buf->TargetNameLen, + nls_codepage, 0); + } else { /* ASCII names */ + strncpy(symlinkinfo, + reparse_buf->LinkNamesBuf + + reparse_buf->TargetNameOffset, + min_t(const int, buflen, + reparse_buf->TargetNameLen)); } - symlinkinfo[buflen] = 0; /* just in case so the caller - does not go off the end of the buffer */ - cFYI(1, ("readlink result - %s", symlinkinfo)); + } else { + rc = -EIO; + cFYI(1, ("Invalid return data count on " + "get reparse info ioctl")); } + symlinkinfo[buflen] = 0; /* just in case so the caller + does not go off the end of the buffer */ + cFYI(1, ("readlink result - %s", symlinkinfo)); } + qreparse_out: cifs_buf_release(pSMB); @@ -2711,6 +2676,7 @@ qreparse_out: return rc; } +#endif /* CIFS_EXPERIMENTAL */ #ifdef CONFIG_CIFS_POSIX @@ -3928,27 +3894,6 @@ GetInodeNumOut: return rc; } -/* computes length of UCS string converted to host codepage - * @src: UCS string - * @maxlen: length of the input string in UCS characters - * (not in bytes) - * - * return: size of input string in host codepage - */ -static int hostlen_fromUCS(const __le16 *src, const int maxlen, - const struct nls_table *nls_codepage) { - int i; - int hostlen = 0; - char to[4]; - int charlen; - for (i = 0; (i < maxlen) && src[i]; ++i) { - charlen = nls_codepage->uni2char(le16_to_cpu(src[i]), - to, NLS_MAX_CHARSET_SIZE); - hostlen += charlen > 0 ? charlen : 1; - } - return hostlen; -} - /* parses DFS refferal V3 structure * caller is responsible for freeing target_nodes * returns: @@ -3994,7 +3939,7 @@ parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr, cFYI(1, ("num_referrals: %d dfs flags: 0x%x ... \n", *num_of_nodes, - le16_to_cpu(pSMBr->DFSFlags))); + le32_to_cpu(pSMBr->DFSFlags))); *target_nodes = kzalloc(sizeof(struct dfs_info3_param) * *num_of_nodes, GFP_KERNEL); @@ -4010,14 +3955,14 @@ parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr, int max_len; struct dfs_info3_param *node = (*target_nodes)+i; - node->flags = le16_to_cpu(pSMBr->DFSFlags); + node->flags = le32_to_cpu(pSMBr->DFSFlags); if (is_unicode) { __le16 *tmp = kmalloc(strlen(searchName)*2 + 2, GFP_KERNEL); cifsConvertToUCS((__le16 *) tmp, searchName, PATH_MAX, nls_codepage, remap); - node->path_consumed = hostlen_fromUCS(tmp, - le16_to_cpu(pSMBr->PathConsumed)/2, + node->path_consumed = cifs_ucs2_bytes(tmp, + le16_to_cpu(pSMBr->PathConsumed), nls_codepage); kfree(tmp); } else @@ -4029,20 +3974,24 @@ parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr, /* copy DfsPath */ temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset); max_len = data_end - temp; - rc = cifs_strncpy_to_host(&(node->path_name), temp, - max_len, is_unicode, nls_codepage); - if (rc) + node->path_name = cifs_strndup_from_ucs(temp, max_len, + is_unicode, nls_codepage); + if (IS_ERR(node->path_name)) { + rc = PTR_ERR(node->path_name); + node->path_name = NULL; goto parse_DFS_referrals_exit; + } /* copy link target UNC */ temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset); max_len = data_end - temp; - rc = cifs_strncpy_to_host(&(node->node_name), temp, - max_len, is_unicode, nls_codepage); - if (rc) + node->node_name = cifs_strndup_from_ucs(temp, max_len, + is_unicode, nls_codepage); + if (IS_ERR(node->node_name)) { + rc = PTR_ERR(node->node_name); + node->node_name = NULL; goto parse_DFS_referrals_exit; - - ref += le16_to_cpu(ref->Size); + } } parse_DFS_referrals_exit: diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index bacdef1546b..4aa81a507b7 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -1,7 +1,7 @@ /* * fs/cifs/connect.c * - * Copyright (C) International Business Machines Corp., 2002,2008 + * Copyright (C) International Business Machines Corp., 2002,2009 * Author(s): Steve French (sfrench@us.ibm.com) * * This library is free software; you can redistribute it and/or modify @@ -32,6 +32,7 @@ #include <linux/kthread.h> #include <linux/pagevec.h> #include <linux/freezer.h> +#include <linux/namei.h> #include <asm/uaccess.h> #include <asm/processor.h> #include <net/ipv6.h> @@ -978,6 +979,13 @@ cifs_parse_mount_options(char *options, const char *devname, return 1; } else if (strnicmp(value, "krb5", 4) == 0) { vol->secFlg |= CIFSSEC_MAY_KRB5; +#ifdef CONFIG_CIFS_EXPERIMENTAL + } else if (strnicmp(value, "ntlmsspi", 8) == 0) { + vol->secFlg |= CIFSSEC_MAY_NTLMSSP | + CIFSSEC_MUST_SIGN; + } else if (strnicmp(value, "ntlmssp", 7) == 0) { + vol->secFlg |= CIFSSEC_MAY_NTLMSSP; +#endif } else if (strnicmp(value, "ntlmv2i", 7) == 0) { vol->secFlg |= CIFSSEC_MAY_NTLMV2 | CIFSSEC_MUST_SIGN; @@ -2278,6 +2286,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, #ifdef CONFIG_CIFS_DFS_UPCALL struct dfs_info3_param *referrals = NULL; unsigned int num_referrals = 0; + int referral_walks_count = 0; try_mount_again: #endif full_path = NULL; @@ -2525,6 +2534,16 @@ remote_path_check: /* get referral if needed */ if (rc == -EREMOTE) { #ifdef CONFIG_CIFS_DFS_UPCALL + if (referral_walks_count > MAX_NESTED_LINKS) { + /* + * BB: when we implement proper loop detection, + * we will remove this check. But now we need it + * to prevent an indefinite loop if 'DFS tree' is + * misconfigured (i.e. has loops). + */ + rc = -ELOOP; + goto mount_fail_check; + } /* convert forward to back slashes in prepath here if needed */ if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) == 0) convert_delimiter(cifs_sb->prepath, @@ -2558,6 +2577,7 @@ remote_path_check: cleanup_volume_info(&volume_info); FreeXid(xid); kfree(full_path); + referral_walks_count++; goto try_mount_again; } #else /* No DFS support, return error on mount */ @@ -2592,1041 +2612,6 @@ out: return rc; } -static int -CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses, - char session_key[CIFS_SESS_KEY_SIZE], - const struct nls_table *nls_codepage) -{ - struct smb_hdr *smb_buffer; - struct smb_hdr *smb_buffer_response; - SESSION_SETUP_ANDX *pSMB; - SESSION_SETUP_ANDX *pSMBr; - char *bcc_ptr; - char *user; - char *domain; - int rc = 0; - int remaining_words = 0; - int bytes_returned = 0; - int len; - __u32 capabilities; - __u16 count; - - cFYI(1, ("In sesssetup")); - if (ses == NULL) - return -EINVAL; - user = ses->userName; - domain = ses->domainName; - smb_buffer = cifs_buf_get(); - - if (smb_buffer == NULL) - return -ENOMEM; - - smb_buffer_response = smb_buffer; - pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer; - - /* send SMBsessionSetup here */ - header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX, - NULL /* no tCon exists yet */ , 13 /* wct */ ); - - smb_buffer->Mid = GetNextMid(ses->server); - pSMB->req_no_secext.AndXCommand = 0xFF; - pSMB->req_no_secext.MaxBufferSize = cpu_to_le16(ses->server->maxBuf); - pSMB->req_no_secext.MaxMpxCount = cpu_to_le16(ses->server->maxReq); - - if (ses->server->secMode & - (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) - smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; - - capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS | - CAP_LARGE_WRITE_X | CAP_LARGE_READ_X; - if (ses->capabilities & CAP_UNICODE) { - smb_buffer->Flags2 |= SMBFLG2_UNICODE; - capabilities |= CAP_UNICODE; - } - if (ses->capabilities & CAP_STATUS32) { - smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS; - capabilities |= CAP_STATUS32; - } - if (ses->capabilities & CAP_DFS) { - smb_buffer->Flags2 |= SMBFLG2_DFS; - capabilities |= CAP_DFS; - } - pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities); - - pSMB->req_no_secext.CaseInsensitivePasswordLength = - cpu_to_le16(CIFS_SESS_KEY_SIZE); - - pSMB->req_no_secext.CaseSensitivePasswordLength = - cpu_to_le16(CIFS_SESS_KEY_SIZE); - bcc_ptr = pByteArea(smb_buffer); - memcpy(bcc_ptr, (char *) session_key, CIFS_SESS_KEY_SIZE); - bcc_ptr += CIFS_SESS_KEY_SIZE; - memcpy(bcc_ptr, (char *) session_key, CIFS_SESS_KEY_SIZE); - bcc_ptr += CIFS_SESS_KEY_SIZE; - - if (ses->capabilities & CAP_UNICODE) { - if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode */ - *bcc_ptr = 0; - bcc_ptr++; - } - if (user == NULL) - bytes_returned = 0; /* skip null user */ - else - bytes_returned = - cifs_strtoUCS((__le16 *) bcc_ptr, user, 100, - nls_codepage); - /* convert number of 16 bit words to bytes */ - bcc_ptr += 2 * bytes_returned; - bcc_ptr += 2; /* trailing null */ - if (domain == NULL) - bytes_returned = - cifs_strtoUCS((__le16 *) bcc_ptr, - "CIFS_LINUX_DOM", 32, nls_codepage); - else - bytes_returned = - cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64, - nls_codepage); - bcc_ptr += 2 * bytes_returned; - bcc_ptr += 2; - bytes_returned = - cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ", - 32, nls_codepage); - bcc_ptr += 2 * bytes_returned; - bytes_returned = - cifs_strtoUCS((__le16 *) bcc_ptr, utsname()->release, - 32, nls_codepage); - bcc_ptr += 2 * bytes_returned; - bcc_ptr += 2; - bytes_returned = - cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS, - 64, nls_codepage); - bcc_ptr += 2 * bytes_returned; - bcc_ptr += 2; - } else { - if (user != NULL) { - strncpy(bcc_ptr, user, 200); - bcc_ptr += strnlen(user, 200); - } - *bcc_ptr = 0; - bcc_ptr++; - if (domain == NULL) { - strcpy(bcc_ptr, "CIFS_LINUX_DOM"); - bcc_ptr += strlen("CIFS_LINUX_DOM") + 1; - } else { - strncpy(bcc_ptr, domain, 64); - bcc_ptr += strnlen(domain, 64); - *bcc_ptr = 0; - bcc_ptr++; - } - strcpy(bcc_ptr, "Linux version "); - bcc_ptr += strlen("Linux version "); - strcpy(bcc_ptr, utsname()->release); - bcc_ptr += strlen(utsname()->release) + 1; - strcpy(bcc_ptr, CIFS_NETWORK_OPSYS); - bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1; - } - count = (long) bcc_ptr - (long) pByteArea(smb_buffer); - smb_buffer->smb_buf_length += count; - pSMB->req_no_secext.ByteCount = cpu_to_le16(count); - - rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, - &bytes_returned, CIFS_LONG_OP); - if (rc) { -/* rc = map_smb_to_linux_error(smb_buffer_response); now done in SendReceive */ - } else if ((smb_buffer_response->WordCount == 3) - || (smb_buffer_response->WordCount == 4)) { - __u16 action = le16_to_cpu(pSMBr->resp.Action); - __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength); - if (action & GUEST_LOGIN) - cFYI(1, ("Guest login")); /* BB mark SesInfo struct? */ - ses->Suid = smb_buffer_response->Uid; /* UID left in wire format - (little endian) */ - cFYI(1, ("UID = %d ", ses->Suid)); - /* response can have either 3 or 4 word count - Samba sends 3 */ - bcc_ptr = pByteArea(smb_buffer_response); - if ((pSMBr->resp.hdr.WordCount == 3) - || ((pSMBr->resp.hdr.WordCount == 4) - && (blob_len < pSMBr->resp.ByteCount))) { - if (pSMBr->resp.hdr.WordCount == 4) - bcc_ptr += blob_len; - - if (smb_buffer->Flags2 & SMBFLG2_UNICODE) { - if ((long) (bcc_ptr) % 2) { - remaining_words = - (BCC(smb_buffer_response) - 1) / 2; - /* Unicode strings must be word - aligned */ - bcc_ptr++; - } else { - remaining_words = - BCC(smb_buffer_response) / 2; - } - len = - UniStrnlen((wchar_t *) bcc_ptr, - remaining_words - 1); -/* We look for obvious messed up bcc or strings in response so we do not go off - the end since (at least) WIN2K and Windows XP have a major bug in not null - terminating last Unicode string in response */ - kfree(ses->serverOS); - ses->serverOS = kzalloc(2 * (len + 1), - GFP_KERNEL); - if (ses->serverOS == NULL) - goto sesssetup_nomem; - cifs_strfromUCS_le(ses->serverOS, - (__le16 *)bcc_ptr, - len, nls_codepage); - bcc_ptr += 2 * (len + 1); - remaining_words -= len + 1; - ses->serverOS[2 * len] = 0; - ses->serverOS[1 + (2 * len)] = 0; - if (remaining_words > 0) { - len = UniStrnlen((wchar_t *)bcc_ptr, - remaining_words-1); - kfree(ses->serverNOS); - ses->serverNOS = kzalloc(2 * (len + 1), - GFP_KERNEL); - if (ses->serverNOS == NULL) - goto sesssetup_nomem; - cifs_strfromUCS_le(ses->serverNOS, - (__le16 *)bcc_ptr, - len, nls_codepage); - bcc_ptr += 2 * (len + 1); - ses->serverNOS[2 * len] = 0; - ses->serverNOS[1 + (2 * len)] = 0; - if (strncmp(ses->serverNOS, - "NT LAN Manager 4", 16) == 0) { - cFYI(1, ("NT4 server")); - ses->flags |= CIFS_SES_NT4; - } - remaining_words -= len + 1; - if (remaining_words > 0) { - len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words); - /* last string is not always null terminated - (for e.g. for Windows XP & 2000) */ - kfree(ses->serverDomain); - ses->serverDomain = - kzalloc(2*(len+1), - GFP_KERNEL); - if (ses->serverDomain == NULL) - goto sesssetup_nomem; - cifs_strfromUCS_le(ses->serverDomain, - (__le16 *)bcc_ptr, - len, nls_codepage); - bcc_ptr += 2 * (len + 1); - ses->serverDomain[2*len] = 0; - ses->serverDomain[1+(2*len)] = 0; - } else { /* else no more room so create - dummy domain string */ - kfree(ses->serverDomain); - ses->serverDomain = - kzalloc(2, GFP_KERNEL); - } - } else { /* no room so create dummy domain - and NOS string */ - - /* if these kcallocs fail not much we - can do, but better to not fail the - sesssetup itself */ - kfree(ses->serverDomain); - ses->serverDomain = - kzalloc(2, GFP_KERNEL); - kfree(ses->serverNOS); - ses->serverNOS = - kzalloc(2, GFP_KERNEL); - } - } else { /* ASCII */ - len = strnlen(bcc_ptr, 1024); - if (((long) bcc_ptr + len) - (long) - pByteArea(smb_buffer_response) - <= BCC(smb_buffer_response)) { - kfree(ses->serverOS); - ses->serverOS = kzalloc(len + 1, - GFP_KERNEL); - if (ses->serverOS == NULL) - goto sesssetup_nomem; - strncpy(ses->serverOS, bcc_ptr, len); - - bcc_ptr += len; - /* null terminate the string */ - bcc_ptr[0] = 0; - bcc_ptr++; - - len = strnlen(bcc_ptr, 1024); - kfree(ses->serverNOS); - ses->serverNOS = kzalloc(len + 1, - GFP_KERNEL); - if (ses->serverNOS == NULL) - goto sesssetup_nomem; - strncpy(ses->serverNOS, bcc_ptr, len); - bcc_ptr += len; - bcc_ptr[0] = 0; - bcc_ptr++; - - len = strnlen(bcc_ptr, 1024); - kfree(ses->serverDomain); - ses->serverDomain = kzalloc(len + 1, - GFP_KERNEL); - if (ses->serverDomain == NULL) - goto sesssetup_nomem; - strncpy(ses->serverDomain, bcc_ptr, - len); - bcc_ptr += len; - bcc_ptr[0] = 0; - bcc_ptr++; - } else - cFYI(1, - ("Variable field of length %d " - "extends beyond end of smb ", - len)); - } - } else { - cERROR(1, ("Security Blob Length extends beyond " - "end of SMB")); - } - } else { - cERROR(1, ("Invalid Word count %d: ", - smb_buffer_response->WordCount)); - rc = -EIO; - } -sesssetup_nomem: /* do not return an error on nomem for the info strings, - since that could make reconnection harder, and - reconnection might be needed to free memory */ - cifs_buf_release(smb_buffer); - - return rc; -} - -static int -CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, - struct cifsSesInfo *ses, bool *pNTLMv2_flag, - const struct nls_table *nls_codepage) -{ - struct smb_hdr *smb_buffer; - struct smb_hdr *smb_buffer_response; - SESSION_SETUP_ANDX *pSMB; - SESSION_SETUP_ANDX *pSMBr; - char *bcc_ptr; - char *domain; - int rc = 0; - int remaining_words = 0; - int bytes_returned = 0; - int len; - int SecurityBlobLength = sizeof(NEGOTIATE_MESSAGE); - PNEGOTIATE_MESSAGE SecurityBlob; - PCHALLENGE_MESSAGE SecurityBlob2; - __u32 negotiate_flags, capabilities; - __u16 count; - - cFYI(1, ("In NTLMSSP sesssetup (negotiate)")); - if (ses == NULL) - return -EINVAL; - domain = ses->domainName; - *pNTLMv2_flag = false; - smb_buffer = cifs_buf_get(); - if (smb_buffer == NULL) { - return -ENOMEM; - } - smb_buffer_response = smb_buffer; - pSMB = (SESSION_SETUP_ANDX *) smb_buffer; - pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response; - - /* send SMBsessionSetup here */ - header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX, - NULL /* no tCon exists yet */ , 12 /* wct */ ); - - smb_buffer->Mid = GetNextMid(ses->server); - pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; - pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT); - - pSMB->req.AndXCommand = 0xFF; - pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf); - pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq); - - if (ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) - smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; - - capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS | - CAP_EXTENDED_SECURITY; - if (ses->capabilities & CAP_UNICODE) { - smb_buffer->Flags2 |= SMBFLG2_UNICODE; - capabilities |= CAP_UNICODE; - } - if (ses->capabilities & CAP_STATUS32) { - smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS; - capabilities |= CAP_STATUS32; - } - if (ses->capabilities & CAP_DFS) { - smb_buffer->Flags2 |= SMBFLG2_DFS; - capabilities |= CAP_DFS; - } - pSMB->req.Capabilities = cpu_to_le32(capabilities); - - bcc_ptr = (char *) &pSMB->req.SecurityBlob; - SecurityBlob = (PNEGOTIATE_MESSAGE) bcc_ptr; - strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8); - SecurityBlob->MessageType = NtLmNegotiate; - negotiate_flags = - NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_OEM | - NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM | - NTLMSSP_NEGOTIATE_56 | - /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128; - if (sign_CIFS_PDUs) - negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN; -/* if (ntlmv2_support) - negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;*/ - /* setup pointers to domain name and workstation name */ - bcc_ptr += SecurityBlobLength; - - SecurityBlob->WorkstationName.Buffer = 0; - SecurityBlob->WorkstationName.Length = 0; - SecurityBlob->WorkstationName.MaximumLength = 0; - - /* Domain not sent on first Sesssetup in NTLMSSP, instead it is sent - along with username on auth request (ie the response to challenge) */ - SecurityBlob->DomainName.Buffer = 0; - SecurityBlob->DomainName.Length = 0; - SecurityBlob->DomainName.MaximumLength = 0; - if (ses->capabilities & CAP_UNICODE) { - if ((long) bcc_ptr % 2) { - *bcc_ptr = 0; - bcc_ptr++; - } - - bytes_returned = - cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ", - 32, nls_codepage); - bcc_ptr += 2 * bytes_returned; - bytes_returned = - cifs_strtoUCS((__le16 *) bcc_ptr, utsname()->release, 32, - nls_codepage); - bcc_ptr += 2 * bytes_returned; - bcc_ptr += 2; /* null terminate Linux version */ - bytes_returned = - cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS, - 64, nls_codepage); - bcc_ptr += 2 * bytes_returned; - *(bcc_ptr + 1) = 0; - *(bcc_ptr + 2) = 0; - bcc_ptr += 2; /* null terminate network opsys string */ - *(bcc_ptr + 1) = 0; - *(bcc_ptr + 2) = 0; - bcc_ptr += 2; /* null domain */ - } else { /* ASCII */ - strcpy(bcc_ptr, "Linux version "); - bcc_ptr += strlen("Linux version "); - strcpy(bcc_ptr, utsname()->release); - bcc_ptr += strlen(utsname()->release) + 1; - strcpy(bcc_ptr, CIFS_NETWORK_OPSYS); - bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1; - bcc_ptr++; /* empty domain field */ - *bcc_ptr = 0; - } - SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags); - pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength); - count = (long) bcc_ptr - (long) pByteArea(smb_buffer); - smb_buffer->smb_buf_length += count; - pSMB->req.ByteCount = cpu_to_le16(count); - - rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, - &bytes_returned, CIFS_LONG_OP); - - if (smb_buffer_response->Status.CifsError == - cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED)) - rc = 0; - - if (rc) { -/* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */ - } else if ((smb_buffer_response->WordCount == 3) - || (smb_buffer_response->WordCount == 4)) { - __u16 action = le16_to_cpu(pSMBr->resp.Action); - __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength); - - if (action & GUEST_LOGIN) - cFYI(1, ("Guest login")); - /* Do we want to set anything in SesInfo struct when guest login? */ - - bcc_ptr = pByteArea(smb_buffer_response); - /* response can have either 3 or 4 word count - Samba sends 3 */ - - SecurityBlob2 = (PCHALLENGE_MESSAGE) bcc_ptr; - if (SecurityBlob2->MessageType != NtLmChallenge) { - cFYI(1, ("Unexpected NTLMSSP message type received %d", - SecurityBlob2->MessageType)); - } else if (ses) { - ses->Suid = smb_buffer_response->Uid; /* UID left in le format */ - cFYI(1, ("UID = %d", ses->Suid)); - if ((pSMBr->resp.hdr.WordCount == 3) - || ((pSMBr->resp.hdr.WordCount == 4) - && (blob_len < - pSMBr->resp.ByteCount))) { - - if (pSMBr->resp.hdr.WordCount == 4) { - bcc_ptr += blob_len; - cFYI(1, ("Security Blob Length %d", - blob_len)); - } - - cFYI(1, ("NTLMSSP Challenge rcvd")); - - memcpy(ses->server->cryptKey, - SecurityBlob2->Challenge, - CIFS_CRYPTO_KEY_SIZE); - if (SecurityBlob2->NegotiateFlags & - cpu_to_le32(NTLMSSP_NEGOTIATE_NTLMV2)) - *pNTLMv2_flag = true; - - if ((SecurityBlob2->NegotiateFlags & - cpu_to_le32(NTLMSSP_NEGOTIATE_ALWAYS_SIGN)) - || (sign_CIFS_PDUs > 1)) - ses->server->secMode |= - SECMODE_SIGN_REQUIRED; - if ((SecurityBlob2->NegotiateFlags & - cpu_to_le32(NTLMSSP_NEGOTIATE_SIGN)) && (sign_CIFS_PDUs)) - ses->server->secMode |= - SECMODE_SIGN_ENABLED; - - if (smb_buffer->Flags2 & SMBFLG2_UNICODE) { - if ((long) (bcc_ptr) % 2) { - remaining_words = - (BCC(smb_buffer_response) - - 1) / 2; - /* Must word align unicode strings */ - bcc_ptr++; - } else { - remaining_words = - BCC - (smb_buffer_response) / 2; - } - len = - UniStrnlen((wchar_t *) bcc_ptr, - remaining_words - 1); -/* We look for obvious messed up bcc or strings in response so we do not go off - the end since (at least) WIN2K and Windows XP have a major bug in not null - terminating last Unicode string in response */ - kfree(ses->serverOS); - ses->serverOS = - kzalloc(2 * (len + 1), GFP_KERNEL); - cifs_strfromUCS_le(ses->serverOS, - (__le16 *) - bcc_ptr, len, - nls_codepage); - bcc_ptr += 2 * (len + 1); - remaining_words -= len + 1; - ses->serverOS[2 * len] = 0; - ses->serverOS[1 + (2 * len)] = 0; - if (remaining_words > 0) { - len = UniStrnlen((wchar_t *) - bcc_ptr, - remaining_words - - 1); - kfree(ses->serverNOS); - ses->serverNOS = - kzalloc(2 * (len + 1), - GFP_KERNEL); - cifs_strfromUCS_le(ses-> - serverNOS, - (__le16 *) - bcc_ptr, - len, - nls_codepage); - bcc_ptr += 2 * (len + 1); - ses->serverNOS[2 * len] = 0; - ses->serverNOS[1 + - (2 * len)] = 0; - remaining_words -= len + 1; - if (remaining_words > 0) { - len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words); - /* last string not always null terminated - (for e.g. for Windows XP & 2000) */ - kfree(ses->serverDomain); - ses->serverDomain = - kzalloc(2 * - (len + - 1), - GFP_KERNEL); - cifs_strfromUCS_le - (ses->serverDomain, - (__le16 *)bcc_ptr, - len, nls_codepage); - bcc_ptr += - 2 * (len + 1); - ses->serverDomain[2*len] - = 0; - ses->serverDomain - [1 + (2 * len)] - = 0; - } /* else no more room so create dummy domain string */ - else { - kfree(ses->serverDomain); - ses->serverDomain = - kzalloc(2, - GFP_KERNEL); - } - } else { /* no room so create dummy domain and NOS string */ - kfree(ses->serverDomain); - ses->serverDomain = - kzalloc(2, GFP_KERNEL); - kfree(ses->serverNOS); - ses->serverNOS = - kzalloc(2, GFP_KERNEL); - } - } else { /* ASCII */ - len = strnlen(bcc_ptr, 1024); - if (((long) bcc_ptr + len) - (long) - pByteArea(smb_buffer_response) - <= BCC(smb_buffer_response)) { - kfree(ses->serverOS); - ses->serverOS = - kzalloc(len + 1, - GFP_KERNEL); - strncpy(ses->serverOS, - bcc_ptr, len); - - bcc_ptr += len; - bcc_ptr[0] = 0; /* null terminate string */ - bcc_ptr++; - - len = strnlen(bcc_ptr, 1024); - kfree(ses->serverNOS); - ses->serverNOS = - kzalloc(len + 1, - GFP_KERNEL); - strncpy(ses->serverNOS, bcc_ptr, len); - bcc_ptr += len; - bcc_ptr[0] = 0; - bcc_ptr++; - - len = strnlen(bcc_ptr, 1024); - kfree(ses->serverDomain); - ses->serverDomain = - kzalloc(len + 1, - GFP_KERNEL); - strncpy(ses->serverDomain, - bcc_ptr, len); - bcc_ptr += len; - bcc_ptr[0] = 0; - bcc_ptr++; - } else - cFYI(1, - ("field of length %d " - "extends beyond end of smb", - len)); - } - } else { - cERROR(1, ("Security Blob Length extends beyond" - " end of SMB")); - } - } else { - cERROR(1, ("No session structure passed in.")); - } - } else { - cERROR(1, ("Invalid Word count %d:", - smb_buffer_response->WordCount)); - rc = -EIO; - } - - cifs_buf_release(smb_buffer); - - return rc; -} -static int -CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, - char *ntlm_session_key, bool ntlmv2_flag, - const struct nls_table *nls_codepage) -{ - struct smb_hdr *smb_buffer; - struct smb_hdr *smb_buffer_response; - SESSION_SETUP_ANDX *pSMB; - SESSION_SETUP_ANDX *pSMBr; - char *bcc_ptr; - char *user; - char *domain; - int rc = 0; - int remaining_words = 0; - int bytes_returned = 0; - int len; - int SecurityBlobLength = sizeof(AUTHENTICATE_MESSAGE); - PAUTHENTICATE_MESSAGE SecurityBlob; - __u32 negotiate_flags, capabilities; - __u16 count; - - cFYI(1, ("In NTLMSSPSessSetup (Authenticate)")); - if (ses == NULL) - return -EINVAL; - user = ses->userName; - domain = ses->domainName; - smb_buffer = cifs_buf_get(); - if (smb_buffer == NULL) { - return -ENOMEM; - } - smb_buffer_response = smb_buffer; - pSMB = (SESSION_SETUP_ANDX *)smb_buffer; - pSMBr = (SESSION_SETUP_ANDX *)smb_buffer_response; - - /* send SMBsessionSetup here */ - header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX, - NULL /* no tCon exists yet */ , 12 /* wct */ ); - - smb_buffer->Mid = GetNextMid(ses->server); - pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT); - pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; - pSMB->req.AndXCommand = 0xFF; - pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf); - pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq); - - pSMB->req.hdr.Uid = ses->Suid; - - if (ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) - smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; - - capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS | - CAP_EXTENDED_SECURITY; - if (ses->capabilities & CAP_UNICODE) { - smb_buffer->Flags2 |= SMBFLG2_UNICODE; - capabilities |= CAP_UNICODE; - } - if (ses->capabilities & CAP_STATUS32) { - smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS; - capabilities |= CAP_STATUS32; - } - if (ses->capabilities & CAP_DFS) { - smb_buffer->Flags2 |= SMBFLG2_DFS; - capabilities |= CAP_DFS; - } - pSMB->req.Capabilities = cpu_to_le32(capabilities); - - bcc_ptr = (char *)&pSMB->req.SecurityBlob; - SecurityBlob = (PAUTHENTICATE_MESSAGE)bcc_ptr; - strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8); - SecurityBlob->MessageType = NtLmAuthenticate; - bcc_ptr += SecurityBlobLength; - negotiate_flags = NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET | - NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO | - 0x80000000 | NTLMSSP_NEGOTIATE_128; - if (sign_CIFS_PDUs) - negotiate_flags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN; - if (ntlmv2_flag) - negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2; - -/* setup pointers to domain name and workstation name */ - - SecurityBlob->WorkstationName.Buffer = 0; - SecurityBlob->WorkstationName.Length = 0; - SecurityBlob->WorkstationName.MaximumLength = 0; - SecurityBlob->SessionKey.Length = 0; - SecurityBlob->SessionKey.MaximumLength = 0; - SecurityBlob->SessionKey.Buffer = 0; - - SecurityBlob->LmChallengeResponse.Length = 0; - SecurityBlob->LmChallengeResponse.MaximumLength = 0; - SecurityBlob->LmChallengeResponse.Buffer = 0; - - SecurityBlob->NtChallengeResponse.Length = - cpu_to_le16(CIFS_SESS_KEY_SIZE); - SecurityBlob->NtChallengeResponse.MaximumLength = - cpu_to_le16(CIFS_SESS_KEY_SIZE); - memcpy(bcc_ptr, ntlm_session_key, CIFS_SESS_KEY_SIZE); - SecurityBlob->NtChallengeResponse.Buffer = - cpu_to_le32(SecurityBlobLength); - SecurityBlobLength += CIFS_SESS_KEY_SIZE; - bcc_ptr += CIFS_SESS_KEY_SIZE; - - if (ses->capabilities & CAP_UNICODE) { - if (domain == NULL) { - SecurityBlob->DomainName.Buffer = 0; - SecurityBlob->DomainName.Length = 0; - SecurityBlob->DomainName.MaximumLength = 0; - } else { - __u16 ln = cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64, - nls_codepage); - ln *= 2; - SecurityBlob->DomainName.MaximumLength = - cpu_to_le16(ln); - SecurityBlob->DomainName.Buffer = - cpu_to_le32(SecurityBlobLength); - bcc_ptr += ln; - SecurityBlobLength += ln; - SecurityBlob->DomainName.Length = cpu_to_le16(ln); - } - if (user == NULL) { - SecurityBlob->UserName.Buffer = 0; - SecurityBlob->UserName.Length = 0; - SecurityBlob->UserName.MaximumLength = 0; - } else { - __u16 ln = cifs_strtoUCS((__le16 *) bcc_ptr, user, 64, - nls_codepage); - ln *= 2; - SecurityBlob->UserName.MaximumLength = - cpu_to_le16(ln); - SecurityBlob->UserName.Buffer = - cpu_to_le32(SecurityBlobLength); - bcc_ptr += ln; - SecurityBlobLength += ln; - SecurityBlob->UserName.Length = cpu_to_le16(ln); - } - - /* SecurityBlob->WorkstationName.Length = - cifs_strtoUCS((__le16 *) bcc_ptr, "AMACHINE",64, nls_codepage); - SecurityBlob->WorkstationName.Length *= 2; - SecurityBlob->WorkstationName.MaximumLength = - cpu_to_le16(SecurityBlob->WorkstationName.Length); - SecurityBlob->WorkstationName.Buffer = - cpu_to_le32(SecurityBlobLength); - bcc_ptr += SecurityBlob->WorkstationName.Length; - SecurityBlobLength += SecurityBlob->WorkstationName.Length; - SecurityBlob->WorkstationName.Length = - cpu_to_le16(SecurityBlob->WorkstationName.Length); */ - - if ((long) bcc_ptr % 2) { - *bcc_ptr = 0; - bcc_ptr++; - } - bytes_returned = - cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ", - 32, nls_codepage); - bcc_ptr += 2 * bytes_returned; - bytes_returned = - cifs_strtoUCS((__le16 *) bcc_ptr, utsname()->release, 32, - nls_codepage); - bcc_ptr += 2 * bytes_returned; - bcc_ptr += 2; /* null term version string */ - bytes_returned = - cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS, - 64, nls_codepage); - bcc_ptr += 2 * bytes_returned; - *(bcc_ptr + 1) = 0; - *(bcc_ptr + 2) = 0; - bcc_ptr += 2; /* null terminate network opsys string */ - *(bcc_ptr + 1) = 0; - *(bcc_ptr + 2) = 0; - bcc_ptr += 2; /* null domain */ - } else { /* ASCII */ - if (domain == NULL) { - SecurityBlob->DomainName.Buffer = 0; - SecurityBlob->DomainName.Length = 0; - SecurityBlob->DomainName.MaximumLength = 0; - } else { - __u16 ln; - negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED; - strncpy(bcc_ptr, domain, 63); - ln = strnlen(domain, 64); - SecurityBlob->DomainName.MaximumLength = - cpu_to_le16(ln); - SecurityBlob->DomainName.Buffer = - cpu_to_le32(SecurityBlobLength); - bcc_ptr += ln; - SecurityBlobLength += ln; - SecurityBlob->DomainName.Length = cpu_to_le16(ln); - } - if (user == NULL) { - SecurityBlob->UserName.Buffer = 0; - SecurityBlob->UserName.Length = 0; - SecurityBlob->UserName.MaximumLength = 0; - } else { - __u16 ln; - strncpy(bcc_ptr, user, 63); - ln = strnlen(user, 64); - SecurityBlob->UserName.MaximumLength = cpu_to_le16(ln); - SecurityBlob->UserName.Buffer = - cpu_to_le32(SecurityBlobLength); - bcc_ptr += ln; - SecurityBlobLength += ln; - SecurityBlob->UserName.Length = cpu_to_le16(ln); - } - /* BB fill in our workstation name if known BB */ - - strcpy(bcc_ptr, "Linux version "); - bcc_ptr += strlen("Linux version "); - strcpy(bcc_ptr, utsname()->release); - bcc_ptr += strlen(utsname()->release) + 1; - strcpy(bcc_ptr, CIFS_NETWORK_OPSYS); - bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1; - bcc_ptr++; /* null domain */ - *bcc_ptr = 0; - } - SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags); - pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength); - count = (long) bcc_ptr - (long) pByteArea(smb_buffer); - smb_buffer->smb_buf_length += count; - pSMB->req.ByteCount = cpu_to_le16(count); - - rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, - &bytes_returned, CIFS_LONG_OP); - if (rc) { -/* rc = map_smb_to_linux_error(smb_buffer_response) done in SendReceive now */ - } else if ((smb_buffer_response->WordCount == 3) || - (smb_buffer_response->WordCount == 4)) { - __u16 action = le16_to_cpu(pSMBr->resp.Action); - __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength); - if (action & GUEST_LOGIN) - cFYI(1, ("Guest login")); /* BB Should we set anything - in SesInfo struct ? */ -/* if (SecurityBlob2->MessageType != NtLm??) { - cFYI("Unexpected message type on auth response is %d")); - } */ - - if (ses) { - cFYI(1, - ("Check challenge UID %d vs auth response UID %d", - ses->Suid, smb_buffer_response->Uid)); - /* UID left in wire format */ - ses->Suid = smb_buffer_response->Uid; - bcc_ptr = pByteArea(smb_buffer_response); - /* response can have either 3 or 4 word count - Samba sends 3 */ - if ((pSMBr->resp.hdr.WordCount == 3) - || ((pSMBr->resp.hdr.WordCount == 4) - && (blob_len < - pSMBr->resp.ByteCount))) { - if (pSMBr->resp.hdr.WordCount == 4) { - bcc_ptr += - blob_len; - cFYI(1, - ("Security Blob Length %d ", - blob_len)); - } - - cFYI(1, - ("NTLMSSP response to Authenticate ")); - - if (smb_buffer->Flags2 & SMBFLG2_UNICODE) { - if ((long) (bcc_ptr) % 2) { - remaining_words = - (BCC(smb_buffer_response) - - 1) / 2; - bcc_ptr++; /* Unicode strings must be word aligned */ - } else { - remaining_words = BCC(smb_buffer_response) / 2; - } - len = UniStrnlen((wchar_t *) bcc_ptr, - remaining_words - 1); -/* We look for obvious messed up bcc or strings in response so we do not go off - the end since (at least) WIN2K and Windows XP have a major bug in not null - terminating last Unicode string in response */ - kfree(ses->serverOS); - ses->serverOS = - kzalloc(2 * (len + 1), GFP_KERNEL); - cifs_strfromUCS_le(ses->serverOS, - (__le16 *) - bcc_ptr, len, - nls_codepage); - bcc_ptr += 2 * (len + 1); - remaining_words -= len + 1; - ses->serverOS[2 * len] = 0; - ses->serverOS[1 + (2 * len)] = 0; - if (remaining_words > 0) { - len = UniStrnlen((wchar_t *) - bcc_ptr, - remaining_words - - 1); - kfree(ses->serverNOS); - ses->serverNOS = - kzalloc(2 * (len + 1), - GFP_KERNEL); - cifs_strfromUCS_le(ses-> - serverNOS, - (__le16 *) - bcc_ptr, - len, - nls_codepage); - bcc_ptr += 2 * (len + 1); - ses->serverNOS[2 * len] = 0; - ses->serverNOS[1+(2*len)] = 0; - remaining_words -= len + 1; - if (remaining_words > 0) { - len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words); - /* last string not always null terminated (e.g. for Windows XP & 2000) */ - kfree(ses->serverDomain); - ses->serverDomain = - kzalloc(2 * - (len + - 1), - GFP_KERNEL); - cifs_strfromUCS_le - (ses-> - serverDomain, - (__le16 *) - bcc_ptr, len, - nls_codepage); - bcc_ptr += - 2 * (len + 1); - ses-> - serverDomain[2 - * len] - = 0; - ses-> - serverDomain[1 - + - (2 - * - len)] - = 0; - } /* else no more room so create dummy domain string */ - else { - kfree(ses->serverDomain); - ses->serverDomain = kzalloc(2,GFP_KERNEL); - } - } else { /* no room so create dummy domain and NOS string */ - kfree(ses->serverDomain); - ses->serverDomain = kzalloc(2, GFP_KERNEL); - kfree(ses->serverNOS); - ses->serverNOS = kzalloc(2, GFP_KERNEL); - } - } else { /* ASCII */ - len = strnlen(bcc_ptr, 1024); - if (((long) bcc_ptr + len) - - (long) pByteArea(smb_buffer_response) - <= BCC(smb_buffer_response)) { - kfree(ses->serverOS); - ses->serverOS = kzalloc(len + 1, GFP_KERNEL); - strncpy(ses->serverOS,bcc_ptr, len); - - bcc_ptr += len; - bcc_ptr[0] = 0; /* null terminate the string */ - bcc_ptr++; - - len = strnlen(bcc_ptr, 1024); - kfree(ses->serverNOS); - ses->serverNOS = kzalloc(len+1, - GFP_KERNEL); - strncpy(ses->serverNOS, - bcc_ptr, len); - bcc_ptr += len; - bcc_ptr[0] = 0; - bcc_ptr++; - - len = strnlen(bcc_ptr, 1024); - kfree(ses->serverDomain); - ses->serverDomain = - kzalloc(len+1, - GFP_KERNEL); - strncpy(ses->serverDomain, - bcc_ptr, len); - bcc_ptr += len; - bcc_ptr[0] = 0; - bcc_ptr++; - } else - cFYI(1, ("field of length %d " - "extends beyond end of smb ", - len)); - } - } else { - cERROR(1, ("Security Blob extends beyond end " - "of SMB")); - } - } else { - cERROR(1, ("No session structure passed in.")); - } - } else { - cERROR(1, ("Invalid Word count %d: ", - smb_buffer_response->WordCount)); - rc = -EIO; - } - - cifs_buf_release(smb_buffer); - - return rc; -} - int CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, const char *tree, struct cifsTconInfo *tcon, @@ -3638,7 +2623,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, TCONX_RSP *pSMBr; unsigned char *bcc_ptr; int rc = 0; - int length; + int length, bytes_left; __u16 count; if (ses == NULL) @@ -3726,14 +2711,22 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length, CIFS_STD_OP); - /* if (rc) rc = map_smb_to_linux_error(smb_buffer_response); */ /* above now done in SendReceive */ if ((rc == 0) && (tcon != NULL)) { + bool is_unicode; + tcon->tidStatus = CifsGood; tcon->need_reconnect = false; tcon->tid = smb_buffer_response->Tid; bcc_ptr = pByteArea(smb_buffer_response); - length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2); + bytes_left = BCC(smb_buffer_response); + length = strnlen(bcc_ptr, bytes_left - 2); + if (smb_buffer->Flags2 & SMBFLG2_UNICODE) + is_unicode = true; + else + is_unicode = false; + + /* skip service field (NB: this field is always ASCII) */ if (length == 3) { if ((bcc_ptr[0] == 'I') && (bcc_ptr[1] == 'P') && @@ -3748,39 +2741,16 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, } } bcc_ptr += length + 1; + bytes_left -= (length + 1); strncpy(tcon->treeName, tree, MAX_TREE_SIZE); - if (smb_buffer->Flags2 & SMBFLG2_UNICODE) { - length = UniStrnlen((wchar_t *) bcc_ptr, 512); - if ((bcc_ptr + (2 * length)) - - pByteArea(smb_buffer_response) <= - BCC(smb_buffer_response)) { - kfree(tcon->nativeFileSystem); - tcon->nativeFileSystem = - kzalloc((4 * length) + 2, GFP_KERNEL); - if (tcon->nativeFileSystem) { - cifs_strfromUCS_le( - tcon->nativeFileSystem, - (__le16 *) bcc_ptr, - length, nls_codepage); - cFYI(1, ("nativeFileSystem=%s", - tcon->nativeFileSystem)); - } - } - /* else do not bother copying these information fields*/ - } else { - length = strnlen(bcc_ptr, 1024); - if ((bcc_ptr + length) - - pByteArea(smb_buffer_response) <= - BCC(smb_buffer_response)) { - kfree(tcon->nativeFileSystem); - tcon->nativeFileSystem = - kzalloc(length + 1, GFP_KERNEL); - if (tcon->nativeFileSystem) - strncpy(tcon->nativeFileSystem, bcc_ptr, - length); - } - /* else do not bother copying these information fields*/ - } + + /* mostly informational -- no need to fail on error here */ + tcon->nativeFileSystem = cifs_strndup_from_ucs(bcc_ptr, + bytes_left, is_unicode, + nls_codepage); + + cFYI(1, ("nativeFileSystem=%s", tcon->nativeFileSystem)); + if ((smb_buffer_response->WordCount == 3) || (smb_buffer_response->WordCount == 7)) /* field is in same location */ @@ -3819,8 +2789,6 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, struct nls_table *nls_info) { int rc = 0; - char ntlm_session_key[CIFS_SESS_KEY_SIZE]; - bool ntlmv2_flag = false; int first_time = 0; struct TCP_Server_Info *server = pSesInfo->server; @@ -3852,83 +2820,19 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, pSesInfo->capabilities = server->capabilities; if (linuxExtEnabled == 0) pSesInfo->capabilities &= (~CAP_UNIX); - /* pSesInfo->sequence_number = 0;*/ + cFYI(1, ("Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d", server->secMode, server->capabilities, server->timeAdj)); - if (experimEnabled < 2) - rc = CIFS_SessSetup(xid, pSesInfo, first_time, nls_info); - else if (extended_security - && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY) - && (server->secType == NTLMSSP)) { - rc = -EOPNOTSUPP; - } else if (extended_security - && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY) - && (server->secType == RawNTLMSSP)) { - cFYI(1, ("NTLMSSP sesssetup")); - rc = CIFSNTLMSSPNegotiateSessSetup(xid, pSesInfo, &ntlmv2_flag, - nls_info); - if (!rc) { - if (ntlmv2_flag) { - char *v2_response; - cFYI(1, ("more secure NTLM ver2 hash")); - if (CalcNTLMv2_partial_mac_key(pSesInfo, - nls_info)) { - rc = -ENOMEM; - goto ss_err_exit; - } else - v2_response = kmalloc(16 + 64 /* blob*/, - GFP_KERNEL); - if (v2_response) { - CalcNTLMv2_response(pSesInfo, - v2_response); - /* if (first_time) - cifs_calculate_ntlmv2_mac_key */ - kfree(v2_response); - /* BB Put dummy sig in SessSetup PDU? */ - } else { - rc = -ENOMEM; - goto ss_err_exit; - } - - } else { - SMBNTencrypt(pSesInfo->password, - server->cryptKey, - ntlm_session_key); - - if (first_time) - cifs_calculate_mac_key( - &server->mac_signing_key, - ntlm_session_key, - pSesInfo->password); - } - /* for better security the weaker lanman hash not sent - in AuthSessSetup so we no longer calculate it */ - - rc = CIFSNTLMSSPAuthSessSetup(xid, pSesInfo, - ntlm_session_key, - ntlmv2_flag, - nls_info); - } - } else { /* old style NTLM 0.12 session setup */ - SMBNTencrypt(pSesInfo->password, server->cryptKey, - ntlm_session_key); - - if (first_time) - cifs_calculate_mac_key(&server->mac_signing_key, - ntlm_session_key, - pSesInfo->password); - - rc = CIFSSessSetup(xid, pSesInfo, ntlm_session_key, nls_info); - } + rc = CIFS_SessSetup(xid, pSesInfo, first_time, nls_info); if (rc) { cERROR(1, ("Send error in SessSetup = %d", rc)); } else { cFYI(1, ("CIFS Session Established successfully")); - spin_lock(&GlobalMid_Lock); - pSesInfo->status = CifsGood; - pSesInfo->need_reconnect = false; - spin_unlock(&GlobalMid_Lock); + spin_lock(&GlobalMid_Lock); + pSesInfo->status = CifsGood; + pSesInfo->need_reconnect = false; + spin_unlock(&GlobalMid_Lock); } ss_err_exit: diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index 461750e0136..11431ed72a7 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -281,6 +281,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, int create_options = CREATE_NOT_DIR; int oplock = 0; int oflags; + bool posix_create = false; /* * BB below access is probably too much for mknod to request * but we have to do query and setpathinfo so requesting @@ -328,11 +329,13 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, negotation. EREMOTE indicates DFS junction, which is not handled in posix open */ - if ((rc == 0) && (newinode == NULL)) - goto cifs_create_get_file_info; /* query inode info */ - else if (rc == 0) /* success, no need to query */ - goto cifs_create_set_dentry; - else if ((rc != -EIO) && (rc != -EREMOTE) && + if (rc == 0) { + posix_create = true; + if (newinode == NULL) /* query inode info */ + goto cifs_create_get_file_info; + else /* success, no need to query */ + goto cifs_create_set_dentry; + } else if ((rc != -EIO) && (rc != -EREMOTE) && (rc != -EOPNOTSUPP)) /* path not found or net err */ goto cifs_create_out; /* else fallthrough to retry, using older open call, this is @@ -464,7 +467,7 @@ cifs_create_set_dentry: if ((nd == NULL) || (!(nd->flags & LOOKUP_OPEN))) { /* mknod case - do not leave file open */ CIFSSMBClose(xid, tcon, fileHandle); - } else if (newinode) { + } else if (!(posix_create) && (newinode)) { cifs_fill_fileinfo(newinode, fileHandle, cifs_sb->tcon, write_only); } diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 50ca088d886..38c06f82657 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -129,15 +129,12 @@ static inline int cifs_posix_open_inode_helper(struct inode *inode, struct file *file, struct cifsInodeInfo *pCifsInode, struct cifsFileInfo *pCifsFile, int oplock, u16 netfid) { - struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); -/* struct timespec temp; */ /* BB REMOVEME BB */ file->private_data = kmalloc(sizeof(struct cifsFileInfo), GFP_KERNEL); if (file->private_data == NULL) return -ENOMEM; pCifsFile = cifs_init_private(file->private_data, inode, file, netfid); write_lock(&GlobalSMBSeslock); - list_add(&pCifsFile->tlist, &cifs_sb->tcon->openFileList); pCifsInode = CIFS_I(file->f_path.dentry->d_inode); if (pCifsInode == NULL) { @@ -145,17 +142,6 @@ static inline int cifs_posix_open_inode_helper(struct inode *inode, return -EINVAL; } - /* want handles we can use to read with first - in the list so we do not have to walk the - list to search for one in write_begin */ - if ((file->f_flags & O_ACCMODE) == O_WRONLY) { - list_add_tail(&pCifsFile->flist, - &pCifsInode->openFileList); - } else { - list_add(&pCifsFile->flist, - &pCifsInode->openFileList); - } - if (pCifsInode->clientCanCacheRead) { /* we have the inode open somewhere else no need to discard cache data */ diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index f36b4e40e44..9c869a6dcba 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -962,13 +962,21 @@ undo_setattr: goto out_close; } + +/* + * If dentry->d_inode is null (usually meaning the cached dentry + * is a negative dentry) then we would attempt a standard SMB delete, but + * if that fails we can not attempt the fall back mechanisms on EACESS + * but will return the EACESS to the caller. Note that the VFS does not call + * unlink on negative dentries currently. + */ int cifs_unlink(struct inode *dir, struct dentry *dentry) { int rc = 0; int xid; char *full_path = NULL; struct inode *inode = dentry->d_inode; - struct cifsInodeInfo *cifsInode = CIFS_I(inode); + struct cifsInodeInfo *cifs_inode; struct super_block *sb = dir->i_sb; struct cifs_sb_info *cifs_sb = CIFS_SB(sb); struct cifsTconInfo *tcon = cifs_sb->tcon; @@ -1012,7 +1020,7 @@ psx_del_no_retry: rc = cifs_rename_pending_delete(full_path, dentry, xid); if (rc == 0) drop_nlink(inode); - } else if (rc == -EACCES && dosattr == 0) { + } else if ((rc == -EACCES) && (dosattr == 0) && inode) { attrs = kzalloc(sizeof(*attrs), GFP_KERNEL); if (attrs == NULL) { rc = -ENOMEM; @@ -1020,7 +1028,8 @@ psx_del_no_retry: } /* try to reset dos attributes */ - origattr = cifsInode->cifsAttrs; + cifs_inode = CIFS_I(inode); + origattr = cifs_inode->cifsAttrs; if (origattr == 0) origattr |= ATTR_NORMAL; dosattr = origattr & ~ATTR_READONLY; @@ -1041,13 +1050,13 @@ psx_del_no_retry: out_reval: if (inode) { - cifsInode = CIFS_I(inode); - cifsInode->time = 0; /* will force revalidate to get info + cifs_inode = CIFS_I(inode); + cifs_inode->time = 0; /* will force revalidate to get info when needed */ inode->i_ctime = current_fs_time(sb); } dir->i_ctime = dir->i_mtime = current_fs_time(sb); - cifsInode = CIFS_I(dir); + cifs_inode = CIFS_I(dir); CIFS_I(dir)->time = 0; /* force revalidate of dir as well */ kfree(full_path); diff --git a/fs/cifs/link.c b/fs/cifs/link.c index 63f644000ce..ea9d11e3dcb 100644 --- a/fs/cifs/link.c +++ b/fs/cifs/link.c @@ -119,16 +119,11 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd) full_path = build_path_from_dentry(direntry); if (!full_path) - goto out_no_free; + goto out; cFYI(1, ("Full path: %s inode = 0x%p", full_path, inode)); cifs_sb = CIFS_SB(inode->i_sb); pTcon = cifs_sb->tcon; - target_path = kmalloc(PATH_MAX, GFP_KERNEL); - if (!target_path) { - target_path = ERR_PTR(-ENOMEM); - goto out; - } /* We could change this to: if (pTcon->unix_ext) @@ -138,8 +133,7 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd) if (pTcon->ses->capabilities & CAP_UNIX) rc = CIFSSMBUnixQuerySymLink(xid, pTcon, full_path, - target_path, - PATH_MAX-1, + &target_path, cifs_sb->local_nls); else { /* BB add read reparse point symlink code here */ @@ -148,22 +142,16 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd) /* BB Add MAC style xsymlink check here if enabled */ } - if (rc == 0) { - -/* BB Add special case check for Samba DFS symlinks */ - - target_path[PATH_MAX-1] = 0; - } else { + if (rc != 0) { kfree(target_path); target_path = ERR_PTR(rc); } -out: kfree(full_path); -out_no_free: +out: FreeXid(xid); nd_set_link(nd, target_path); - return NULL; /* No cookie */ + return NULL; } int @@ -224,98 +212,6 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname) return rc; } -int -cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen) -{ - struct inode *inode = direntry->d_inode; - int rc = -EACCES; - int xid; - int oplock = 0; - struct cifs_sb_info *cifs_sb; - struct cifsTconInfo *pTcon; - char *full_path = NULL; - char *tmpbuffer; - int len; - __u16 fid; - - xid = GetXid(); - cifs_sb = CIFS_SB(inode->i_sb); - pTcon = cifs_sb->tcon; - -/* BB would it be safe against deadlock to grab this sem - even though rename itself grabs the sem and calls lookup? */ -/* mutex_lock(&inode->i_sb->s_vfs_rename_mutex);*/ - full_path = build_path_from_dentry(direntry); -/* mutex_unlock(&inode->i_sb->s_vfs_rename_mutex);*/ - - if (full_path == NULL) { - FreeXid(xid); - return -ENOMEM; - } - - cFYI(1, - ("Full path: %s inode = 0x%p pBuffer = 0x%p buflen = %d", - full_path, inode, pBuffer, buflen)); - if (buflen > PATH_MAX) - len = PATH_MAX; - else - len = buflen; - tmpbuffer = kmalloc(len, GFP_KERNEL); - if (tmpbuffer == NULL) { - kfree(full_path); - FreeXid(xid); - return -ENOMEM; - } - -/* BB add read reparse point symlink code and - Unix extensions symlink code here BB */ -/* We could disable this based on pTcon->unix_ext flag instead ... but why? */ - if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) - rc = CIFSSMBUnixQuerySymLink(xid, pTcon, full_path, - tmpbuffer, - len - 1, - cifs_sb->local_nls); - else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { - cERROR(1, ("SFU style symlinks not implemented yet")); - /* add open and read as in fs/cifs/inode.c */ - } else { - rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, GENERIC_READ, - OPEN_REPARSE_POINT, &fid, &oplock, NULL, - cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & - CIFS_MOUNT_MAP_SPECIAL_CHR); - if (!rc) { - rc = CIFSSMBQueryReparseLinkInfo(xid, pTcon, full_path, - tmpbuffer, - len - 1, - fid, - cifs_sb->local_nls); - if (CIFSSMBClose(xid, pTcon, fid)) { - cFYI(1, ("Error closing junction point " - "(open for ioctl)")); - } - /* If it is a DFS junction earlier we would have gotten - PATH_NOT_COVERED returned from server so we do - not need to request the DFS info here */ - } - } - /* BB Anything else to do to handle recursive links? */ - /* BB Should we be using page ops here? */ - - /* BB null terminate returned string in pBuffer? BB */ - if (rc == 0) { - rc = vfs_readlink(direntry, pBuffer, len, tmpbuffer); - cFYI(1, - ("vfs_readlink called from cifs_readlink returned %d", - rc)); - } - - kfree(tmpbuffer); - kfree(full_path); - FreeXid(xid); - return rc; -} - void cifs_put_link(struct dentry *direntry, struct nameidata *nd, void *cookie) { char *p = nd_get_link(nd); diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index 4c89c572891..e079a9190ec 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c @@ -635,77 +635,6 @@ dump_smb(struct smb_hdr *smb_buf, int smb_buf_length) return; } -/* Windows maps these to the user defined 16 bit Unicode range since they are - reserved symbols (along with \ and /), otherwise illegal to store - in filenames in NTFS */ -#define UNI_ASTERIK (__u16) ('*' + 0xF000) -#define UNI_QUESTION (__u16) ('?' + 0xF000) -#define UNI_COLON (__u16) (':' + 0xF000) -#define UNI_GRTRTHAN (__u16) ('>' + 0xF000) -#define UNI_LESSTHAN (__u16) ('<' + 0xF000) -#define UNI_PIPE (__u16) ('|' + 0xF000) -#define UNI_SLASH (__u16) ('\\' + 0xF000) - -/* Convert 16 bit Unicode pathname from wire format to string in current code - page. Conversion may involve remapping up the seven characters that are - only legal in POSIX-like OS (if they are present in the string). Path - names are little endian 16 bit Unicode on the wire */ -int -cifs_convertUCSpath(char *target, const __le16 *source, int maxlen, - const struct nls_table *cp) -{ - int i, j, len; - __u16 src_char; - - for (i = 0, j = 0; i < maxlen; i++) { - src_char = le16_to_cpu(source[i]); - switch (src_char) { - case 0: - goto cUCS_out; /* BB check this BB */ - case UNI_COLON: - target[j] = ':'; - break; - case UNI_ASTERIK: - target[j] = '*'; - break; - case UNI_QUESTION: - target[j] = '?'; - break; - /* BB We can not handle remapping slash until - all the calls to build_path_from_dentry - are modified, as they use slash as separator BB */ - /* case UNI_SLASH: - target[j] = '\\'; - break;*/ - case UNI_PIPE: - target[j] = '|'; - break; - case UNI_GRTRTHAN: - target[j] = '>'; - break; - case UNI_LESSTHAN: - target[j] = '<'; - break; - default: - len = cp->uni2char(src_char, &target[j], - NLS_MAX_CHARSET_SIZE); - if (len > 0) { - j += len; - continue; - } else { - target[j] = '?'; - } - } - j++; - /* make sure we do not overrun callers allocated temp buffer */ - if (j >= (2 * NAME_MAX)) - break; - } -cUCS_out: - target[j] = 0; - return j; -} - /* Convert 16 bit Unicode pathname to wire format from string in current code page. Conversion may involve remapping up the seven characters that are only legal in POSIX-like OS (if they are present in the string). Path diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c index 8703d68f5b2..e2fe998989a 100644 --- a/fs/cifs/netmisc.c +++ b/fs/cifs/netmisc.c @@ -79,6 +79,7 @@ static const struct smb_to_posix_error mapping_table_ERRDOS[] = { {ErrQuota, -EDQUOT}, {ErrNotALink, -ENOLINK}, {ERRnetlogonNotStarted, -ENOPROTOOPT}, + {ERRsymlink, -EOPNOTSUPP}, {ErrTooManyLinks, -EMLINK}, {0, 0} }; @@ -714,6 +715,7 @@ static const struct { ERRDOS, ERRnoaccess, 0xc000028f}, { ERRDOS, ERRnoaccess, 0xc0000290}, { ERRDOS, ERRbadfunc, 0xc000029c}, { + ERRDOS, ERRsymlink, NT_STATUS_STOPPED_ON_SYMLINK}, { ERRDOS, ERRinvlevel, 0x007c0001}, }; /***************************************************************************** diff --git a/fs/cifs/nterr.h b/fs/cifs/nterr.h index 588abbb9d08..257267367d4 100644 --- a/fs/cifs/nterr.h +++ b/fs/cifs/nterr.h @@ -35,8 +35,6 @@ struct nt_err_code_struct { extern const struct nt_err_code_struct nt_errs[]; /* Win32 Status codes. */ - -#define STATUS_BUFFER_OVERFLOW 0x80000005 #define STATUS_MORE_ENTRIES 0x0105 #define ERROR_INVALID_PARAMETER 0x0057 #define ERROR_INSUFFICIENT_BUFFER 0x007a @@ -50,6 +48,13 @@ extern const struct nt_err_code_struct nt_errs[]; #define STATUS_SOME_UNMAPPED 0x0107 #define STATUS_BUFFER_OVERFLOW 0x80000005 #define NT_STATUS_NO_MORE_ENTRIES 0x8000001a +#define NT_STATUS_MEDIA_CHANGED 0x8000001c +#define NT_STATUS_END_OF_MEDIA 0x8000001e +#define NT_STATUS_MEDIA_CHECK 0x80000020 +#define NT_STATUS_NO_DATA_DETECTED 0x8000001c +#define NT_STATUS_STOPPED_ON_SYMLINK 0x8000002d +#define NT_STATUS_DEVICE_REQUIRES_CLEANING 0x80000288 +#define NT_STATUS_DEVICE_DOOR_OPEN 0x80000288 #define NT_STATUS_UNSUCCESSFUL 0xC0000000 | 0x0001 #define NT_STATUS_NOT_IMPLEMENTED 0xC0000000 | 0x0002 #define NT_STATUS_INVALID_INFO_CLASS 0xC0000000 | 0x0003 diff --git a/fs/cifs/ntlmssp.h b/fs/cifs/ntlmssp.h index c377d8065d9..49c9a4e7531 100644 --- a/fs/cifs/ntlmssp.h +++ b/fs/cifs/ntlmssp.h @@ -27,29 +27,39 @@ #define UnknownMessage cpu_to_le32(8) /* Negotiate Flags */ -#define NTLMSSP_NEGOTIATE_UNICODE 0x01 /* Text strings are in unicode */ -#define NTLMSSP_NEGOTIATE_OEM 0x02 /* Text strings are in OEM */ -#define NTLMSSP_REQUEST_TARGET 0x04 /* Server return its auth realm */ -#define NTLMSSP_NEGOTIATE_SIGN 0x0010 /* Request signature capability */ -#define NTLMSSP_NEGOTIATE_SEAL 0x0020 /* Request confidentiality */ -#define NTLMSSP_NEGOTIATE_DGRAM 0x0040 -#define NTLMSSP_NEGOTIATE_LM_KEY 0x0080 /* Sign/seal use LM session key */ -#define NTLMSSP_NEGOTIATE_NTLM 0x0200 /* NTLM authentication */ -#define NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED 0x1000 +#define NTLMSSP_NEGOTIATE_UNICODE 0x01 /* Text strings are unicode */ +#define NTLMSSP_NEGOTIATE_OEM 0x02 /* Text strings are in OEM */ +#define NTLMSSP_REQUEST_TARGET 0x04 /* Srv returns its auth realm */ +/* define reserved9 0x08 */ +#define NTLMSSP_NEGOTIATE_SIGN 0x0010 /* Request signing capability */ +#define NTLMSSP_NEGOTIATE_SEAL 0x0020 /* Request confidentiality */ +#define NTLMSSP_NEGOTIATE_DGRAM 0x0040 +#define NTLMSSP_NEGOTIATE_LM_KEY 0x0080 /* Use LM session key */ +/* defined reserved 8 0x0100 */ +#define NTLMSSP_NEGOTIATE_NTLM 0x0200 /* NTLM authentication */ +#define NTLMSSP_NEGOTIATE_NT_ONLY 0x0400 /* Lanman not allowed */ +#define NTLMSSP_ANONYMOUS 0x0800 +#define NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED 0x1000 /* reserved6 */ #define NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED 0x2000 -#define NTLMSSP_NEGOTIATE_LOCAL_CALL 0x4000 /* client/server on same machine */ -#define NTLMSSP_NEGOTIATE_ALWAYS_SIGN 0x8000 /* Sign for all security levels */ -#define NTLMSSP_TARGET_TYPE_DOMAIN 0x10000 -#define NTLMSSP_TARGET_TYPE_SERVER 0x20000 -#define NTLMSSP_TARGET_TYPE_SHARE 0x40000 -#define NTLMSSP_NEGOTIATE_NTLMV2 0x80000 -#define NTLMSSP_REQUEST_INIT_RESP 0x100000 -#define NTLMSSP_REQUEST_ACCEPT_RESP 0x200000 -#define NTLMSSP_REQUEST_NOT_NT_KEY 0x400000 +#define NTLMSSP_NEGOTIATE_LOCAL_CALL 0x4000 /* client/server same machine */ +#define NTLMSSP_NEGOTIATE_ALWAYS_SIGN 0x8000 /* Sign. All security levels */ +#define NTLMSSP_TARGET_TYPE_DOMAIN 0x10000 +#define NTLMSSP_TARGET_TYPE_SERVER 0x20000 +#define NTLMSSP_TARGET_TYPE_SHARE 0x40000 +#define NTLMSSP_NEGOTIATE_EXTENDED_SEC 0x80000 /* NB:not related to NTLMv2 pwd*/ +/* #define NTLMSSP_REQUEST_INIT_RESP 0x100000 */ +#define NTLMSSP_NEGOTIATE_IDENTIFY 0x100000 +#define NTLMSSP_REQUEST_ACCEPT_RESP 0x200000 /* reserved5 */ +#define NTLMSSP_REQUEST_NON_NT_KEY 0x400000 #define NTLMSSP_NEGOTIATE_TARGET_INFO 0x800000 -#define NTLMSSP_NEGOTIATE_128 0x20000000 -#define NTLMSSP_NEGOTIATE_KEY_XCH 0x40000000 -#define NTLMSSP_NEGOTIATE_56 0x80000000 +/* #define reserved4 0x1000000 */ +#define NTLMSSP_NEGOTIATE_VERSION 0x2000000 /* we do not set */ +/* #define reserved3 0x4000000 */ +/* #define reserved2 0x8000000 */ +/* #define reserved1 0x10000000 */ +#define NTLMSSP_NEGOTIATE_128 0x20000000 +#define NTLMSSP_NEGOTIATE_KEY_XCH 0x40000000 +#define NTLMSSP_NEGOTIATE_56 0x80000000 /* Although typedefs are not commonly used for structure definitions */ /* in the Linux kernel, in this particular case they are useful */ @@ -60,32 +70,36 @@ typedef struct _SECURITY_BUFFER { __le16 Length; __le16 MaximumLength; - __le32 Buffer; /* offset to buffer */ + __le32 BufferOffset; /* offset to buffer */ } __attribute__((packed)) SECURITY_BUFFER; typedef struct _NEGOTIATE_MESSAGE { __u8 Signature[sizeof(NTLMSSP_SIGNATURE)]; - __le32 MessageType; /* 1 */ + __le32 MessageType; /* NtLmNegotiate = 1 */ __le32 NegotiateFlags; SECURITY_BUFFER DomainName; /* RFC 1001 style and ASCII */ SECURITY_BUFFER WorkstationName; /* RFC 1001 and ASCII */ + /* SECURITY_BUFFER for version info not present since we + do not set the version is present flag */ char DomainString[0]; /* followed by WorkstationString */ } __attribute__((packed)) NEGOTIATE_MESSAGE, *PNEGOTIATE_MESSAGE; typedef struct _CHALLENGE_MESSAGE { __u8 Signature[sizeof(NTLMSSP_SIGNATURE)]; - __le32 MessageType; /* 2 */ + __le32 MessageType; /* NtLmChallenge = 2 */ SECURITY_BUFFER TargetName; __le32 NegotiateFlags; __u8 Challenge[CIFS_CRYPTO_KEY_SIZE]; __u8 Reserved[8]; SECURITY_BUFFER TargetInfoArray; + /* SECURITY_BUFFER for version info not present since we + do not set the version is present flag */ } __attribute__((packed)) CHALLENGE_MESSAGE, *PCHALLENGE_MESSAGE; typedef struct _AUTHENTICATE_MESSAGE { - __u8 Signature[sizeof (NTLMSSP_SIGNATURE)]; - __le32 MessageType; /* 3 */ + __u8 Signature[sizeof(NTLMSSP_SIGNATURE)]; + __le32 MessageType; /* NtLmsAuthenticate = 3 */ SECURITY_BUFFER LmChallengeResponse; SECURITY_BUFFER NtChallengeResponse; SECURITY_BUFFER DomainName; @@ -93,5 +107,7 @@ typedef struct _AUTHENTICATE_MESSAGE { SECURITY_BUFFER WorkstationName; SECURITY_BUFFER SessionKey; __le32 NegotiateFlags; + /* SECURITY_BUFFER for version info not present since we + do not set the version is present flag */ char UserString[0]; } __attribute__((packed)) AUTHENTICATE_MESSAGE, *PAUTHENTICATE_MESSAGE; diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index 1a8be622833..964e097c820 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c @@ -31,6 +31,13 @@ #include "cifs_fs_sb.h" #include "cifsfs.h" +/* + * To be safe - for UCS to UTF-8 with strings loaded with the rare long + * characters alloc more to account for such multibyte target UTF-8 + * characters. + */ +#define UNICODE_NAME_MAX ((4 * NAME_MAX) + 2) + #ifdef CONFIG_CIFS_DEBUG2 static void dump_cifs_file_struct(struct file *file, char *label) { @@ -438,6 +445,38 @@ static void unix_fill_in_inode(struct inode *tmp_inode, } } +/* BB eventually need to add the following helper function to + resolve NT_STATUS_STOPPED_ON_SYMLINK return code when + we try to do FindFirst on (NTFS) directory symlinks */ +/* +int get_symlink_reparse_path(char *full_path, struct cifs_sb_info *cifs_sb, + int xid) +{ + __u16 fid; + int len; + int oplock = 0; + int rc; + struct cifsTconInfo *ptcon = cifs_sb->tcon; + char *tmpbuffer; + + rc = CIFSSMBOpen(xid, ptcon, full_path, FILE_OPEN, GENERIC_READ, + OPEN_REPARSE_POINT, &fid, &oplock, NULL, + cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); + if (!rc) { + tmpbuffer = kmalloc(maxpath); + rc = CIFSSMBQueryReparseLinkInfo(xid, ptcon, full_path, + tmpbuffer, + maxpath -1, + fid, + cifs_sb->local_nls); + if (CIFSSMBClose(xid, ptcon, fid)) { + cFYI(1, ("Error closing temporary reparsepoint open)")); + } + } +} + */ + static int initiate_cifs_search(const int xid, struct file *file) { int rc = 0; @@ -493,7 +532,10 @@ ffirst_retry: CIFS_MOUNT_MAP_SPECIAL_CHR, CIFS_DIR_SEP(cifs_sb)); if (rc == 0) cifsFile->invalidHandle = false; - if ((rc == -EOPNOTSUPP) && + /* BB add following call to handle readdir on new NTFS symlink errors + else if STATUS_STOPPED_ON_SYMLINK + call get_symlink_reparse_path and retry with new path */ + else if ((rc == -EOPNOTSUPP) && (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) { cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SERVER_INUM; goto ffirst_retry; @@ -822,7 +864,7 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon, /* inode num, inode type and filename returned */ static int cifs_get_name_from_search_buf(struct qstr *pqst, char *current_entry, __u16 level, unsigned int unicode, - struct cifs_sb_info *cifs_sb, int max_len, __u64 *pinum) + struct cifs_sb_info *cifs_sb, unsigned int max_len, __u64 *pinum) { int rc = 0; unsigned int len = 0; @@ -881,14 +923,12 @@ static int cifs_get_name_from_search_buf(struct qstr *pqst, } if (unicode) { - /* BB fixme - test with long names */ - /* Note converted filename can be longer than in unicode */ - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR) - pqst->len = cifs_convertUCSpath((char *)pqst->name, - (__le16 *)filename, len/2, nlt); - else - pqst->len = cifs_strfromUCS_le((char *)pqst->name, - (__le16 *)filename, len/2, nlt); + pqst->len = cifs_from_ucs2((char *) pqst->name, + (__le16 *) filename, + UNICODE_NAME_MAX, + min(len, max_len), nlt, + cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); } else { pqst->name = filename; pqst->len = len; @@ -898,8 +938,8 @@ static int cifs_get_name_from_search_buf(struct qstr *pqst, return rc; } -static int cifs_filldir(char *pfindEntry, struct file *file, - filldir_t filldir, void *direntry, char *scratch_buf, int max_len) +static int cifs_filldir(char *pfindEntry, struct file *file, filldir_t filldir, + void *direntry, char *scratch_buf, unsigned int max_len) { int rc = 0; struct qstr qstring; @@ -996,7 +1036,7 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir) int num_to_fill = 0; char *tmp_buf = NULL; char *end_of_smb; - int max_len; + unsigned int max_len; xid = GetXid(); @@ -1070,11 +1110,7 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir) cifsFile->srch_inf.ntwrk_buf_start); end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + max_len; - /* To be safe - for UCS to UTF-8 with strings loaded - with the rare long characters alloc more to account for - such multibyte target UTF-8 characters. cifs_unicode.c, - which actually does the conversion, has the same limit */ - tmp_buf = kmalloc((2 * NAME_MAX) + 4, GFP_KERNEL); + tmp_buf = kmalloc(UNICODE_NAME_MAX, GFP_KERNEL); for (i = 0; (i < num_to_fill) && (rc == 0); i++) { if (current_entry == NULL) { /* evaluate whether this case is an error */ diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c index c652c73760d..897a052270f 100644 --- a/fs/cifs/sess.c +++ b/fs/cifs/sess.c @@ -3,7 +3,7 @@ * * SMB/CIFS session setup handling routines * - * Copyright (c) International Business Machines Corp., 2006, 2007 + * Copyright (c) International Business Machines Corp., 2006, 2009 * Author(s): Steve French (sfrench@us.ibm.com) * * This library is free software; you can redistribute it and/or modify @@ -111,7 +111,7 @@ static __le16 get_next_vcnum(struct cifsSesInfo *ses) get_vc_num_exit: write_unlock(&cifs_tcp_ses_lock); - return le16_to_cpu(vcnum); + return cpu_to_le16(vcnum); } static __u32 cifs_ssetup_hdr(struct cifsSesInfo *ses, SESSION_SETUP_ANDX *pSMB) @@ -277,12 +277,11 @@ static void ascii_ssetup_strings(char **pbcc_area, struct cifsSesInfo *ses, *pbcc_area = bcc_ptr; } -static int decode_unicode_ssetup(char **pbcc_area, int bleft, - struct cifsSesInfo *ses, - const struct nls_table *nls_cp) +static void +decode_unicode_ssetup(char **pbcc_area, int bleft, struct cifsSesInfo *ses, + const struct nls_table *nls_cp) { - int rc = 0; - int words_left, len; + int len; char *data = *pbcc_area; cFYI(1, ("bleft %d", bleft)); @@ -300,63 +299,29 @@ static int decode_unicode_ssetup(char **pbcc_area, int bleft, ++bleft; } - words_left = bleft / 2; - - /* save off server operating system */ - len = UniStrnlen((wchar_t *) data, words_left); - - if (len >= words_left) - return rc; - kfree(ses->serverOS); - /* UTF-8 string will not grow more than four times as big as UCS-16 */ - ses->serverOS = kzalloc((4 * len) + 2 /* trailing null */, GFP_KERNEL); - if (ses->serverOS != NULL) { - cifs_strfromUCS_le(ses->serverOS, (__le16 *)data, len, nls_cp); - cFYI(1, ("serverOS=%s", ses->serverOS)); - } - data += 2 * (len + 1); - words_left -= len + 1; - - /* save off server network operating system */ - len = UniStrnlen((wchar_t *) data, words_left); - - if (len >= words_left) - return rc; + ses->serverOS = cifs_strndup_from_ucs(data, bleft, true, nls_cp); + cFYI(1, ("serverOS=%s", ses->serverOS)); + len = (UniStrnlen((wchar_t *) data, bleft / 2) * 2) + 2; + data += len; + bleft -= len; + if (bleft <= 0) + return; kfree(ses->serverNOS); - ses->serverNOS = kzalloc((4 * len) + 2 /* trailing null */, GFP_KERNEL); - if (ses->serverNOS != NULL) { - cifs_strfromUCS_le(ses->serverNOS, (__le16 *)data, len, - nls_cp); - cFYI(1, ("serverNOS=%s", ses->serverNOS)); - if (strncmp(ses->serverNOS, "NT LAN Manager 4", 16) == 0) { - cFYI(1, ("NT4 server")); - ses->flags |= CIFS_SES_NT4; - } - } - data += 2 * (len + 1); - words_left -= len + 1; - - /* save off server domain */ - len = UniStrnlen((wchar_t *) data, words_left); - - if (len > words_left) - return rc; + ses->serverNOS = cifs_strndup_from_ucs(data, bleft, true, nls_cp); + cFYI(1, ("serverNOS=%s", ses->serverNOS)); + len = (UniStrnlen((wchar_t *) data, bleft / 2) * 2) + 2; + data += len; + bleft -= len; + if (bleft <= 0) + return; kfree(ses->serverDomain); - ses->serverDomain = kzalloc((4 * len) + 2, GFP_KERNEL); - if (ses->serverDomain != NULL) { - cifs_strfromUCS_le(ses->serverDomain, (__le16 *)data, len, - nls_cp); - cFYI(1, ("serverDomain=%s", ses->serverDomain)); - } - data += 2 * (len + 1); - words_left -= len + 1; - - cFYI(1, ("words left: %d", words_left)); + ses->serverDomain = cifs_strndup_from_ucs(data, bleft, true, nls_cp); + cFYI(1, ("serverDomain=%s", ses->serverDomain)); - return rc; + return; } static int decode_ascii_ssetup(char **pbcc_area, int bleft, @@ -413,6 +378,186 @@ static int decode_ascii_ssetup(char **pbcc_area, int bleft, return rc; } +static int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len, + struct cifsSesInfo *ses) +{ + CHALLENGE_MESSAGE *pblob = (CHALLENGE_MESSAGE *)bcc_ptr; + + if (blob_len < sizeof(CHALLENGE_MESSAGE)) { + cERROR(1, ("challenge blob len %d too small", blob_len)); + return -EINVAL; + } + + if (memcmp(pblob->Signature, "NTLMSSP", 8)) { + cERROR(1, ("blob signature incorrect %s", pblob->Signature)); + return -EINVAL; + } + if (pblob->MessageType != NtLmChallenge) { + cERROR(1, ("Incorrect message type %d", pblob->MessageType)); + return -EINVAL; + } + + memcpy(ses->server->cryptKey, pblob->Challenge, CIFS_CRYPTO_KEY_SIZE); + /* BB we could decode pblob->NegotiateFlags; some may be useful */ + /* In particular we can examine sign flags */ + /* BB spec says that if AvId field of MsvAvTimestamp is populated then + we must set the MIC field of the AUTHENTICATE_MESSAGE */ + + return 0; +} + +#ifdef CONFIG_CIFS_EXPERIMENTAL +/* BB Move to ntlmssp.c eventually */ + +/* We do not malloc the blob, it is passed in pbuffer, because + it is fixed size, and small, making this approach cleaner */ +static void build_ntlmssp_negotiate_blob(unsigned char *pbuffer, + struct cifsSesInfo *ses) +{ + NEGOTIATE_MESSAGE *sec_blob = (NEGOTIATE_MESSAGE *)pbuffer; + __u32 flags; + + memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8); + sec_blob->MessageType = NtLmNegotiate; + + /* BB is NTLMV2 session security format easier to use here? */ + flags = NTLMSSP_NEGOTIATE_56 | NTLMSSP_REQUEST_TARGET | + NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE | + NTLMSSP_NEGOTIATE_NT_ONLY | NTLMSSP_NEGOTIATE_NTLM; + if (ses->server->secMode & + (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) + flags |= NTLMSSP_NEGOTIATE_SIGN; + if (ses->server->secMode & SECMODE_SIGN_REQUIRED) + flags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN; + + sec_blob->NegotiateFlags |= cpu_to_le32(flags); + + sec_blob->WorkstationName.BufferOffset = 0; + sec_blob->WorkstationName.Length = 0; + sec_blob->WorkstationName.MaximumLength = 0; + + /* Domain name is sent on the Challenge not Negotiate NTLMSSP request */ + sec_blob->DomainName.BufferOffset = 0; + sec_blob->DomainName.Length = 0; + sec_blob->DomainName.MaximumLength = 0; +} + +/* We do not malloc the blob, it is passed in pbuffer, because its + maximum possible size is fixed and small, making this approach cleaner. + This function returns the length of the data in the blob */ +static int build_ntlmssp_auth_blob(unsigned char *pbuffer, + struct cifsSesInfo *ses, + const struct nls_table *nls_cp, int first) +{ + AUTHENTICATE_MESSAGE *sec_blob = (AUTHENTICATE_MESSAGE *)pbuffer; + __u32 flags; + unsigned char *tmp; + char ntlm_session_key[CIFS_SESS_KEY_SIZE]; + + memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8); + sec_blob->MessageType = NtLmAuthenticate; + + flags = NTLMSSP_NEGOTIATE_56 | + NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_TARGET_INFO | + NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE | + NTLMSSP_NEGOTIATE_NT_ONLY | NTLMSSP_NEGOTIATE_NTLM; + if (ses->server->secMode & + (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) + flags |= NTLMSSP_NEGOTIATE_SIGN; + if (ses->server->secMode & SECMODE_SIGN_REQUIRED) + flags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN; + + tmp = pbuffer + sizeof(AUTHENTICATE_MESSAGE); + sec_blob->NegotiateFlags |= cpu_to_le32(flags); + + sec_blob->LmChallengeResponse.BufferOffset = + cpu_to_le32(sizeof(AUTHENTICATE_MESSAGE)); + sec_blob->LmChallengeResponse.Length = 0; + sec_blob->LmChallengeResponse.MaximumLength = 0; + + /* calculate session key, BB what about adding similar ntlmv2 path? */ + SMBNTencrypt(ses->password, ses->server->cryptKey, ntlm_session_key); + if (first) + cifs_calculate_mac_key(&ses->server->mac_signing_key, + ntlm_session_key, ses->password); + + memcpy(tmp, ntlm_session_key, CIFS_SESS_KEY_SIZE); + sec_blob->NtChallengeResponse.BufferOffset = cpu_to_le32(tmp - pbuffer); + sec_blob->NtChallengeResponse.Length = cpu_to_le16(CIFS_SESS_KEY_SIZE); + sec_blob->NtChallengeResponse.MaximumLength = + cpu_to_le16(CIFS_SESS_KEY_SIZE); + + tmp += CIFS_SESS_KEY_SIZE; + + if (ses->domainName == NULL) { + sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer); + sec_blob->DomainName.Length = 0; + sec_blob->DomainName.MaximumLength = 0; + tmp += 2; + } else { + int len; + len = cifs_strtoUCS((__le16 *)tmp, ses->domainName, + MAX_USERNAME_SIZE, nls_cp); + len *= 2; /* unicode is 2 bytes each */ + len += 2; /* trailing null */ + sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer); + sec_blob->DomainName.Length = cpu_to_le16(len); + sec_blob->DomainName.MaximumLength = cpu_to_le16(len); + tmp += len; + } + + if (ses->userName == NULL) { + sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - pbuffer); + sec_blob->UserName.Length = 0; + sec_blob->UserName.MaximumLength = 0; + tmp += 2; + } else { + int len; + len = cifs_strtoUCS((__le16 *)tmp, ses->userName, + MAX_USERNAME_SIZE, nls_cp); + len *= 2; /* unicode is 2 bytes each */ + len += 2; /* trailing null */ + sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - pbuffer); + sec_blob->UserName.Length = cpu_to_le16(len); + sec_blob->UserName.MaximumLength = cpu_to_le16(len); + tmp += len; + } + + sec_blob->WorkstationName.BufferOffset = cpu_to_le32(tmp - pbuffer); + sec_blob->WorkstationName.Length = 0; + sec_blob->WorkstationName.MaximumLength = 0; + tmp += 2; + + sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - pbuffer); + sec_blob->SessionKey.Length = 0; + sec_blob->SessionKey.MaximumLength = 0; + return tmp - pbuffer; +} + + +static void setup_ntlmssp_neg_req(SESSION_SETUP_ANDX *pSMB, + struct cifsSesInfo *ses) +{ + build_ntlmssp_negotiate_blob(&pSMB->req.SecurityBlob[0], ses); + pSMB->req.SecurityBlobLength = cpu_to_le16(sizeof(NEGOTIATE_MESSAGE)); + + return; +} + +static int setup_ntlmssp_auth_req(SESSION_SETUP_ANDX *pSMB, + struct cifsSesInfo *ses, + const struct nls_table *nls, int first_time) +{ + int bloblen; + + bloblen = build_ntlmssp_auth_blob(&pSMB->req.SecurityBlob[0], ses, nls, + first_time); + pSMB->req.SecurityBlobLength = cpu_to_le16(bloblen); + + return bloblen; +} +#endif + int CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time, const struct nls_table *nls_cp) @@ -431,6 +576,7 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time, __u16 action; int bytes_remaining; struct key *spnego_key = NULL; + __le32 phase = NtLmNegotiate; /* NTLMSSP, if needed, is multistage */ if (ses == NULL) return -EINVAL; @@ -438,6 +584,10 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time, type = ses->server->secType; cFYI(1, ("sess setup type %d", type)); +ssetup_ntlmssp_authenticate: + if (phase == NtLmChallenge) + phase = NtLmAuthenticate; /* if ntlmssp, now final phase */ + if (type == LANMAN) { #ifndef CONFIG_CIFS_WEAK_PW_HASH /* LANMAN and plaintext are less secure and off by default. @@ -651,9 +801,53 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time, goto ssetup_exit; #endif /* CONFIG_CIFS_UPCALL */ } else { +#ifdef CONFIG_CIFS_EXPERIMENTAL + if ((experimEnabled > 1) && (type == RawNTLMSSP)) { + if ((pSMB->req.hdr.Flags2 & SMBFLG2_UNICODE) == 0) { + cERROR(1, ("NTLMSSP requires Unicode support")); + rc = -ENOSYS; + goto ssetup_exit; + } + + cFYI(1, ("ntlmssp session setup phase %d", phase)); + pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; + capabilities |= CAP_EXTENDED_SECURITY; + pSMB->req.Capabilities |= cpu_to_le32(capabilities); + if (phase == NtLmNegotiate) { + setup_ntlmssp_neg_req(pSMB, ses); + iov[1].iov_len = sizeof(NEGOTIATE_MESSAGE); + } else if (phase == NtLmAuthenticate) { + int blob_len; + blob_len = setup_ntlmssp_auth_req(pSMB, ses, + nls_cp, + first_time); + iov[1].iov_len = blob_len; + /* Make sure that we tell the server that we + are using the uid that it just gave us back + on the response (challenge) */ + smb_buf->Uid = ses->Suid; + } else { + cERROR(1, ("invalid phase %d", phase)); + rc = -ENOSYS; + goto ssetup_exit; + } + iov[1].iov_base = &pSMB->req.SecurityBlob[0]; + /* unicode strings must be word aligned */ + if ((iov[0].iov_len + iov[1].iov_len) % 2) { + *bcc_ptr = 0; + bcc_ptr++; + } + unicode_oslm_strings(&bcc_ptr, nls_cp); + } else { + cERROR(1, ("secType %d not supported!", type)); + rc = -ENOSYS; + goto ssetup_exit; + } +#else cERROR(1, ("secType %d not supported!", type)); rc = -ENOSYS; goto ssetup_exit; +#endif } iov[2].iov_base = str_area; @@ -669,12 +863,23 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time, /* SMB request buf freed in SendReceive2 */ cFYI(1, ("ssetup rc from sendrecv2 is %d", rc)); - if (rc) - goto ssetup_exit; pSMB = (SESSION_SETUP_ANDX *)iov[0].iov_base; smb_buf = (struct smb_hdr *)iov[0].iov_base; + if ((type == RawNTLMSSP) && (smb_buf->Status.CifsError == + cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED))) { + if (phase != NtLmNegotiate) { + cERROR(1, ("Unexpected more processing error")); + goto ssetup_exit; + } + /* NTLMSSP Negotiate sent now processing challenge (response) */ + phase = NtLmChallenge; /* process ntlmssp challenge */ + rc = 0; /* MORE_PROC rc is not an error here, but expected */ + } + if (rc) + goto ssetup_exit; + if ((smb_buf->WordCount != 3) && (smb_buf->WordCount != 4)) { rc = -EIO; cERROR(1, ("bad word count %d", smb_buf->WordCount)); @@ -693,12 +898,18 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time, if (smb_buf->WordCount == 4) { __u16 blob_len; blob_len = le16_to_cpu(pSMB->resp.SecurityBlobLength); - bcc_ptr += blob_len; if (blob_len > bytes_remaining) { cERROR(1, ("bad security blob length %d", blob_len)); rc = -EINVAL; goto ssetup_exit; } + if (phase == NtLmChallenge) { + rc = decode_ntlmssp_challenge(bcc_ptr, blob_len, ses); + /* now goto beginning for ntlmssp authenticate phase */ + if (rc) + goto ssetup_exit; + } + bcc_ptr += blob_len; bytes_remaining -= blob_len; } @@ -709,8 +920,7 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time, ++bcc_ptr; --bytes_remaining; } - rc = decode_unicode_ssetup(&bcc_ptr, bytes_remaining, - ses, nls_cp); + decode_unicode_ssetup(&bcc_ptr, bytes_remaining, ses, nls_cp); } else { rc = decode_ascii_ssetup(&bcc_ptr, bytes_remaining, ses, nls_cp); @@ -728,5 +938,9 @@ ssetup_exit: } else if (resp_buf_type == CIFS_LARGE_BUFFER) cifs_buf_release(iov[0].iov_base); + /* if ntlmssp, and negotiate succeeded, proceed to authenticate phase */ + if ((phase == NtLmChallenge) && (rc == 0)) + goto ssetup_ntlmssp_authenticate; + return rc; } diff --git a/fs/cifs/smberr.h b/fs/cifs/smberr.h index 7f50e8577c1..c5084d27db7 100644 --- a/fs/cifs/smberr.h +++ b/fs/cifs/smberr.h @@ -110,6 +110,7 @@ /* Below errors are used internally (do not come over the wire) for passthrough from STATUS codes to POSIX only */ +#define ERRsymlink 0xFFFD #define ErrTooManyLinks 0xFFFE /* Following error codes may be generated with the ERRSRV error class.*/ diff --git a/fs/configfs/symlink.c b/fs/configfs/symlink.c index 932a92b3148..c8afa6b1d91 100644 --- a/fs/configfs/symlink.c +++ b/fs/configfs/symlink.c @@ -135,7 +135,7 @@ int configfs_symlink(struct inode *dir, struct dentry *dentry, const char *symna struct path path; struct configfs_dirent *sd; struct config_item *parent_item; - struct config_item *target_item; + struct config_item *target_item = NULL; struct config_item_type *type; ret = -EPERM; /* What lack-of-symlink returns */ diff --git a/fs/dcache.c b/fs/dcache.c index 1fcffebfb44..75659a6fd1f 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -481,7 +481,7 @@ restart: if ((flags & DCACHE_REFERENCED) && (dentry->d_flags & DCACHE_REFERENCED)) { dentry->d_flags &= ~DCACHE_REFERENCED; - list_move_tail(&dentry->d_lru, &referenced); + list_move(&dentry->d_lru, &referenced); spin_unlock(&dentry->d_lock); } else { list_move_tail(&dentry->d_lru, &tmp); diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c index 63a4a59e414..21165cf934f 100644 --- a/fs/devpts/inode.c +++ b/fs/devpts/inode.c @@ -389,11 +389,10 @@ static int devpts_get_sb(struct file_system_type *fs_type, return 0; out_dput: - dput(s->s_root); + dput(s->s_root); /* undo dget() in simple_set_mnt() */ out_undo_sget: - up_write(&s->s_umount); - deactivate_super(s); + deactivate_locked_super(s); return error; } diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index 93bc0f8174a..2f0945d6329 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c @@ -667,7 +667,7 @@ ecryptfs_readlink(struct dentry *dentry, char __user *buf, int bufsiz) lower_buf = kmalloc(lower_bufsiz, GFP_KERNEL); if (lower_buf == NULL) { printk(KERN_ERR "%s: Out of memory whilst attempting to " - "kmalloc [%d] bytes\n", __func__, lower_bufsiz); + "kmalloc [%zd] bytes\n", __func__, lower_bufsiz); rc = -ENOMEM; goto out; } @@ -690,7 +690,7 @@ ecryptfs_readlink(struct dentry *dentry, char __user *buf, int bufsiz) } /* Check for bufsiz <= 0 done in sys_readlinkat() */ rc = copy_to_user(buf, plaintext_name, - min((unsigned) bufsiz, plaintext_name_size)); + min((size_t) bufsiz, plaintext_name_size)); if (rc) rc = -EFAULT; else diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c index ccabd5faa04..9f0aa9883c2 100644 --- a/fs/ecryptfs/main.c +++ b/fs/ecryptfs/main.c @@ -614,9 +614,8 @@ static int ecryptfs_get_sb(struct file_system_type *fs_type, int flags, } goto out; out_abort: - dput(sb->s_root); - up_write(&sb->s_umount); - deactivate_super(sb); + dput(sb->s_root); /* aka mnt->mnt_root, as set by get_sb_nodev() */ + deactivate_locked_super(sb); out: return rc; } diff --git a/fs/eventpoll.c b/fs/eventpoll.c index a89f370fadb..5458e80fc55 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c @@ -1212,7 +1212,7 @@ SYSCALL_DEFINE1(epoll_create1, int, flags) SYSCALL_DEFINE1(epoll_create, int, size) { - if (size < 0) + if (size <= 0) return -EINVAL; return sys_epoll_create1(0); diff --git a/fs/exec.c b/fs/exec.c index a3a8ce83940..895823d0149 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -69,17 +69,18 @@ int suid_dumpable = 0; static LIST_HEAD(formats); static DEFINE_RWLOCK(binfmt_lock); -int register_binfmt(struct linux_binfmt * fmt) +int __register_binfmt(struct linux_binfmt * fmt, int insert) { if (!fmt) return -EINVAL; write_lock(&binfmt_lock); - list_add(&fmt->lh, &formats); + insert ? list_add(&fmt->lh, &formats) : + list_add_tail(&fmt->lh, &formats); write_unlock(&binfmt_lock); return 0; } -EXPORT_SYMBOL(register_binfmt); +EXPORT_SYMBOL(__register_binfmt); void unregister_binfmt(struct linux_binfmt * fmt) { @@ -104,40 +105,28 @@ static inline void put_binfmt(struct linux_binfmt * fmt) SYSCALL_DEFINE1(uselib, const char __user *, library) { struct file *file; - struct nameidata nd; char *tmp = getname(library); int error = PTR_ERR(tmp); - if (!IS_ERR(tmp)) { - error = path_lookup_open(AT_FDCWD, tmp, - LOOKUP_FOLLOW, &nd, - FMODE_READ|FMODE_EXEC); - putname(tmp); - } - if (error) + if (IS_ERR(tmp)) + goto out; + + file = do_filp_open(AT_FDCWD, tmp, + O_LARGEFILE | O_RDONLY | FMODE_EXEC, 0, + MAY_READ | MAY_EXEC | MAY_OPEN); + putname(tmp); + error = PTR_ERR(file); + if (IS_ERR(file)) goto out; error = -EINVAL; - if (!S_ISREG(nd.path.dentry->d_inode->i_mode)) + if (!S_ISREG(file->f_path.dentry->d_inode->i_mode)) goto exit; error = -EACCES; - if (nd.path.mnt->mnt_flags & MNT_NOEXEC) - goto exit; - - error = inode_permission(nd.path.dentry->d_inode, - MAY_READ | MAY_EXEC | MAY_OPEN); - if (error) - goto exit; - error = ima_path_check(&nd.path, MAY_READ | MAY_EXEC | MAY_OPEN); - if (error) + if (file->f_path.mnt->mnt_flags & MNT_NOEXEC) goto exit; - file = nameidata_to_filp(&nd, O_RDONLY|O_LARGEFILE); - error = PTR_ERR(file); - if (IS_ERR(file)) - goto out; - fsnotify_open(file->f_path.dentry); error = -ENOEXEC; @@ -159,13 +148,10 @@ SYSCALL_DEFINE1(uselib, const char __user *, library) } read_unlock(&binfmt_lock); } +exit: fput(file); out: return error; -exit: - release_open_intent(&nd); - path_put(&nd.path); - goto out; } #ifdef CONFIG_MMU @@ -660,47 +646,33 @@ EXPORT_SYMBOL(setup_arg_pages); struct file *open_exec(const char *name) { - struct nameidata nd; struct file *file; int err; - err = path_lookup_open(AT_FDCWD, name, LOOKUP_FOLLOW, &nd, - FMODE_READ|FMODE_EXEC); - if (err) + file = do_filp_open(AT_FDCWD, name, + O_LARGEFILE | O_RDONLY | FMODE_EXEC, 0, + MAY_EXEC | MAY_OPEN); + if (IS_ERR(file)) goto out; err = -EACCES; - if (!S_ISREG(nd.path.dentry->d_inode->i_mode)) - goto out_path_put; - - if (nd.path.mnt->mnt_flags & MNT_NOEXEC) - goto out_path_put; - - err = inode_permission(nd.path.dentry->d_inode, MAY_EXEC | MAY_OPEN); - if (err) - goto out_path_put; - err = ima_path_check(&nd.path, MAY_EXEC | MAY_OPEN); - if (err) - goto out_path_put; + if (!S_ISREG(file->f_path.dentry->d_inode->i_mode)) + goto exit; - file = nameidata_to_filp(&nd, O_RDONLY|O_LARGEFILE); - if (IS_ERR(file)) - return file; + if (file->f_path.mnt->mnt_flags & MNT_NOEXEC) + goto exit; fsnotify_open(file->f_path.dentry); err = deny_write_access(file); - if (err) { - fput(file); - goto out; - } + if (err) + goto exit; +out: return file; - out_path_put: - release_open_intent(&nd); - path_put(&nd.path); - out: +exit: + fput(file); return ERR_PTR(err); } EXPORT_SYMBOL(open_exec); diff --git a/fs/fcntl.c b/fs/fcntl.c index cc8e4de2fee..1ad703150de 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c @@ -117,11 +117,13 @@ SYSCALL_DEFINE2(dup2, unsigned int, oldfd, unsigned int, newfd) { if (unlikely(newfd == oldfd)) { /* corner case */ struct files_struct *files = current->files; + int retval = oldfd; + rcu_read_lock(); if (!fcheck_files(files, oldfd)) - oldfd = -EBADF; + retval = -EBADF; rcu_read_unlock(); - return oldfd; + return retval; } return sys_dup3(oldfd, newfd, 0); } diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 459b73dd45e..d1bc4d33ccb 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -19,6 +19,7 @@ #include <linux/random.h> #include <linux/sched.h> #include <linux/exportfs.h> +#include <linux/smp_lock.h> MODULE_AUTHOR("Miklos Szeredi <miklos@szeredi.hu>"); MODULE_DESCRIPTION("Filesystem in Userspace"); @@ -259,7 +260,9 @@ struct inode *fuse_iget(struct super_block *sb, u64 nodeid, static void fuse_umount_begin(struct super_block *sb) { + lock_kernel(); fuse_abort_conn(get_fuse_conn_super(sb)); + unlock_kernel(); } static void fuse_send_destroy(struct fuse_conn *fc) diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c index 1afd9f26bcb..ff498109048 100644 --- a/fs/gfs2/glock.c +++ b/fs/gfs2/glock.c @@ -1304,6 +1304,7 @@ static int gfs2_shrink_glock_memory(int nr, gfp_t gfp_mask) nr--; if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0) gfs2_glock_put(gl); + got_ref = 0; } spin_lock(&lru_lock); if (may_demote) diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index 650a730707b..1ff9473ea75 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c @@ -1282,21 +1282,21 @@ static int gfs2_get_sb(struct file_system_type *fs_type, int flags, static struct super_block *get_gfs2_sb(const char *dev_name) { struct super_block *sb; - struct nameidata nd; + struct path path; int error; - error = path_lookup(dev_name, LOOKUP_FOLLOW, &nd); + error = kern_path(dev_name, LOOKUP_FOLLOW, &path); if (error) { printk(KERN_WARNING "GFS2: path_lookup on %s returned error %d\n", dev_name, error); return NULL; } - sb = nd.path.dentry->d_inode->i_sb; + sb = path.dentry->d_inode->i_sb; if (sb && (sb->s_type == &gfs2_fs_type)) atomic_inc(&sb->s_active); else sb = NULL; - path_put(&nd.path); + path_put(&path); return sb; } diff --git a/fs/hpfs/super.c b/fs/hpfs/super.c index fecf402d7b8..fc77965be84 100644 --- a/fs/hpfs/super.c +++ b/fs/hpfs/super.c @@ -423,8 +423,7 @@ static int hpfs_remount_fs(struct super_block *s, int *flags, char *data) if (!(*flags & MS_RDONLY)) mark_dirty(s); - kfree(s->s_options); - s->s_options = new_opts; + replace_mount_options(s, new_opts); return 0; diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index 153d9681192..c1462d43e72 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c @@ -312,16 +312,6 @@ out: return retval; } -/* - * Read a page. Again trivial. If it didn't already exist - * in the page cache, it is zero-filled. - */ -static int hugetlbfs_readpage(struct file *file, struct page * page) -{ - unlock_page(page); - return -EINVAL; -} - static int hugetlbfs_write_begin(struct file *file, struct address_space *mapping, loff_t pos, unsigned len, unsigned flags, @@ -701,7 +691,6 @@ static void hugetlbfs_destroy_inode(struct inode *inode) } static const struct address_space_operations hugetlbfs_aops = { - .readpage = hugetlbfs_readpage, .write_begin = hugetlbfs_write_begin, .write_end = hugetlbfs_write_end, .set_page_dirty = hugetlbfs_set_page_dirty, diff --git a/fs/inode.c b/fs/inode.c index 6ad14a1cd8c..0571983755d 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -99,7 +99,7 @@ static DEFINE_MUTEX(iprune_mutex); */ struct inodes_stat_t inodes_stat; -static struct kmem_cache * inode_cachep __read_mostly; +static struct kmem_cache *inode_cachep __read_mostly; static void wake_up_inode(struct inode *inode) { @@ -124,7 +124,7 @@ struct inode *inode_init_always(struct super_block *sb, struct inode *inode) static struct inode_operations empty_iops; static const struct file_operations empty_fops; - struct address_space * const mapping = &inode->i_data; + struct address_space *const mapping = &inode->i_data; inode->i_sb = sb; inode->i_blkbits = sb->s_blocksize_bits; @@ -216,7 +216,7 @@ static struct inode *alloc_inode(struct super_block *sb) return NULL; } -void destroy_inode(struct inode *inode) +void destroy_inode(struct inode *inode) { BUG_ON(inode_has_buffers(inode)); security_inode_free(inode); @@ -252,12 +252,11 @@ void inode_init_once(struct inode *inode) mutex_init(&inode->inotify_mutex); #endif } - EXPORT_SYMBOL(inode_init_once); static void init_once(void *foo) { - struct inode * inode = (struct inode *) foo; + struct inode *inode = (struct inode *) foo; inode_init_once(inode); } @@ -265,7 +264,7 @@ static void init_once(void *foo) /* * inode_lock must be held */ -void __iget(struct inode * inode) +void __iget(struct inode *inode) { if (atomic_read(&inode->i_count)) { atomic_inc(&inode->i_count); @@ -289,7 +288,7 @@ void clear_inode(struct inode *inode) { might_sleep(); invalidate_inode_buffers(inode); - + BUG_ON(inode->i_data.nrpages); BUG_ON(!(inode->i_state & I_FREEING)); BUG_ON(inode->i_state & I_CLEAR); @@ -303,7 +302,6 @@ void clear_inode(struct inode *inode) cd_forget(inode); inode->i_state = I_CLEAR; } - EXPORT_SYMBOL(clear_inode); /* @@ -351,8 +349,8 @@ static int invalidate_list(struct list_head *head, struct list_head *dispose) next = head->next; for (;;) { - struct list_head * tmp = next; - struct inode * inode; + struct list_head *tmp = next; + struct inode *inode; /* * We can reschedule here without worrying about the list's @@ -391,7 +389,7 @@ static int invalidate_list(struct list_head *head, struct list_head *dispose) * fails because there are busy inodes then a non zero value is returned. * If the discard is successful all the inodes have been discarded. */ -int invalidate_inodes(struct super_block * sb) +int invalidate_inodes(struct super_block *sb) { int busy; LIST_HEAD(throw_away); @@ -407,7 +405,6 @@ int invalidate_inodes(struct super_block * sb) return busy; } - EXPORT_SYMBOL(invalidate_inodes); static int can_unuse(struct inode *inode) @@ -504,7 +501,7 @@ static int shrink_icache_memory(int nr, gfp_t gfp_mask) * Nasty deadlock avoidance. We may hold various FS locks, * and we don't want to recurse into the FS that called us * in clear_inode() and friends.. - */ + */ if (!(gfp_mask & __GFP_FS)) return -1; prune_icache(nr); @@ -524,10 +521,13 @@ static void __wait_on_freeing_inode(struct inode *inode); * by hand after calling find_inode now! This simplifies iunique and won't * add any additional branch in the common code. */ -static struct inode * find_inode(struct super_block * sb, struct hlist_head *head, int (*test)(struct inode *, void *), void *data) +static struct inode *find_inode(struct super_block *sb, + struct hlist_head *head, + int (*test)(struct inode *, void *), + void *data) { struct hlist_node *node; - struct inode * inode = NULL; + struct inode *inode = NULL; repeat: hlist_for_each_entry(inode, node, head, i_hash) { @@ -548,10 +548,11 @@ repeat: * find_inode_fast is the fast path version of find_inode, see the comment at * iget_locked for details. */ -static struct inode * find_inode_fast(struct super_block * sb, struct hlist_head *head, unsigned long ino) +static struct inode *find_inode_fast(struct super_block *sb, + struct hlist_head *head, unsigned long ino) { struct hlist_node *node; - struct inode * inode = NULL; + struct inode *inode = NULL; repeat: hlist_for_each_entry(inode, node, head, i_hash) { @@ -631,10 +632,10 @@ struct inode *new_inode(struct super_block *sb) * here to attempt to avoid that. */ static unsigned int last_ino; - struct inode * inode; + struct inode *inode; spin_lock_prefetch(&inode_lock); - + inode = alloc_inode(sb); if (inode) { spin_lock(&inode_lock); @@ -645,7 +646,6 @@ struct inode *new_inode(struct super_block *sb) } return inode; } - EXPORT_SYMBOL(new_inode); void unlock_new_inode(struct inode *inode) @@ -674,7 +674,6 @@ void unlock_new_inode(struct inode *inode) inode->i_state &= ~(I_LOCK|I_NEW); wake_up_inode(inode); } - EXPORT_SYMBOL(unlock_new_inode); /* @@ -683,13 +682,17 @@ EXPORT_SYMBOL(unlock_new_inode); * We no longer cache the sb_flags in i_flags - see fs.h * -- rmk@arm.uk.linux.org */ -static struct inode * get_new_inode(struct super_block *sb, struct hlist_head *head, int (*test)(struct inode *, void *), int (*set)(struct inode *, void *), void *data) +static struct inode *get_new_inode(struct super_block *sb, + struct hlist_head *head, + int (*test)(struct inode *, void *), + int (*set)(struct inode *, void *), + void *data) { - struct inode * inode; + struct inode *inode; inode = alloc_inode(sb); if (inode) { - struct inode * old; + struct inode *old; spin_lock(&inode_lock); /* We released the lock, so.. */ @@ -731,13 +734,14 @@ set_failed: * get_new_inode_fast is the fast path version of get_new_inode, see the * comment at iget_locked for details. */ -static struct inode * get_new_inode_fast(struct super_block *sb, struct hlist_head *head, unsigned long ino) +static struct inode *get_new_inode_fast(struct super_block *sb, + struct hlist_head *head, unsigned long ino) { - struct inode * inode; + struct inode *inode; inode = alloc_inode(sb); if (inode) { - struct inode * old; + struct inode *old; spin_lock(&inode_lock); /* We released the lock, so.. */ @@ -823,7 +827,6 @@ struct inode *igrab(struct inode *inode) spin_unlock(&inode_lock); return inode; } - EXPORT_SYMBOL(igrab); /** @@ -924,7 +927,6 @@ struct inode *ilookup5_nowait(struct super_block *sb, unsigned long hashval, return ifind(sb, head, test, data, 0); } - EXPORT_SYMBOL(ilookup5_nowait); /** @@ -953,7 +955,6 @@ struct inode *ilookup5(struct super_block *sb, unsigned long hashval, return ifind(sb, head, test, data, 1); } - EXPORT_SYMBOL(ilookup5); /** @@ -976,7 +977,6 @@ struct inode *ilookup(struct super_block *sb, unsigned long ino) return ifind_fast(sb, head, ino); } - EXPORT_SYMBOL(ilookup); /** @@ -1015,7 +1015,6 @@ struct inode *iget5_locked(struct super_block *sb, unsigned long hashval, */ return get_new_inode(sb, head, test, set, data); } - EXPORT_SYMBOL(iget5_locked); /** @@ -1047,7 +1046,6 @@ struct inode *iget_locked(struct super_block *sb, unsigned long ino) */ return get_new_inode_fast(sb, head, ino); } - EXPORT_SYMBOL(iget_locked); int insert_inode_locked(struct inode *inode) @@ -1076,7 +1074,6 @@ int insert_inode_locked(struct inode *inode) iput(old); } } - EXPORT_SYMBOL(insert_inode_locked); int insert_inode_locked4(struct inode *inode, unsigned long hashval, @@ -1106,7 +1103,6 @@ int insert_inode_locked4(struct inode *inode, unsigned long hashval, iput(old); } } - EXPORT_SYMBOL(insert_inode_locked4); /** @@ -1124,7 +1120,6 @@ void __insert_inode_hash(struct inode *inode, unsigned long hashval) hlist_add_head(&inode->i_hash, head); spin_unlock(&inode_lock); } - EXPORT_SYMBOL(__insert_inode_hash); /** @@ -1139,7 +1134,6 @@ void remove_inode_hash(struct inode *inode) hlist_del_init(&inode->i_hash); spin_unlock(&inode_lock); } - EXPORT_SYMBOL(remove_inode_hash); /* @@ -1187,7 +1181,6 @@ void generic_delete_inode(struct inode *inode) BUG_ON(inode->i_state != I_CLEAR); destroy_inode(inode); } - EXPORT_SYMBOL(generic_delete_inode); static void generic_forget_inode(struct inode *inode) @@ -1237,12 +1230,11 @@ void generic_drop_inode(struct inode *inode) else generic_forget_inode(inode); } - EXPORT_SYMBOL_GPL(generic_drop_inode); /* * Called when we're dropping the last reference - * to an inode. + * to an inode. * * Call the FS "drop()" function, defaulting to * the legacy UNIX filesystem behaviour.. @@ -1262,7 +1254,7 @@ static inline void iput_final(struct inode *inode) } /** - * iput - put an inode + * iput - put an inode * @inode: inode to put * * Puts an inode, dropping its usage count. If the inode use count hits @@ -1279,7 +1271,6 @@ void iput(struct inode *inode) iput_final(inode); } } - EXPORT_SYMBOL(iput); /** @@ -1290,10 +1281,10 @@ EXPORT_SYMBOL(iput); * Returns the block number on the device holding the inode that * is the disk block number for the block of the file requested. * That is, asked for block 4 of inode 1 the function will return the - * disk block relative to the disk start that holds that block of the + * disk block relative to the disk start that holds that block of the * file. */ -sector_t bmap(struct inode * inode, sector_t block) +sector_t bmap(struct inode *inode, sector_t block) { sector_t res = 0; if (inode->i_mapping->a_ops->bmap) @@ -1425,7 +1416,6 @@ void file_update_time(struct file *file) mark_inode_dirty_sync(inode); mnt_drop_write(file->f_path.mnt); } - EXPORT_SYMBOL(file_update_time); int inode_needs_sync(struct inode *inode) @@ -1436,7 +1426,6 @@ int inode_needs_sync(struct inode *inode) return 1; return 0; } - EXPORT_SYMBOL(inode_needs_sync); int inode_wait(void *word) diff --git a/fs/ioctl.c b/fs/ioctl.c index ac2d47e4392..82d9c42b8ba 100644 --- a/fs/ioctl.c +++ b/fs/ioctl.c @@ -258,7 +258,7 @@ int __generic_block_fiemap(struct inode *inode, long long length = 0, map_len = 0; u64 logical = 0, phys = 0, size = 0; u32 flags = FIEMAP_EXTENT_MERGED; - int ret = 0; + int ret = 0, past_eof = 0, whole_file = 0; if ((ret = fiemap_check_flags(fieinfo, FIEMAP_FLAG_SYNC))) return ret; @@ -266,6 +266,9 @@ int __generic_block_fiemap(struct inode *inode, start_blk = logical_to_blk(inode, start); length = (long long)min_t(u64, len, i_size_read(inode)); + if (length < len) + whole_file = 1; + map_len = length; do { @@ -282,11 +285,26 @@ int __generic_block_fiemap(struct inode *inode, /* HOLE */ if (!buffer_mapped(&tmp)) { + length -= blk_to_logical(inode, 1); + start_blk++; + + /* + * we want to handle the case where there is an + * allocated block at the front of the file, and then + * nothing but holes up to the end of the file properly, + * to make sure that extent at the front gets properly + * marked with FIEMAP_EXTENT_LAST + */ + if (!past_eof && + blk_to_logical(inode, start_blk) >= + blk_to_logical(inode, 0)+i_size_read(inode)) + past_eof = 1; + /* * first hole after going past the EOF, this is our * last extent */ - if (length <= 0) { + if (past_eof && size) { flags = FIEMAP_EXTENT_MERGED|FIEMAP_EXTENT_LAST; ret = fiemap_fill_next_extent(fieinfo, logical, phys, size, @@ -294,15 +312,37 @@ int __generic_block_fiemap(struct inode *inode, break; } - length -= blk_to_logical(inode, 1); - /* if we have holes up to/past EOF then we're done */ - if (length <= 0) + if (length <= 0 || past_eof) break; - - start_blk++; } else { - if (length <= 0 && size) { + /* + * we have gone over the length of what we wanted to + * map, and it wasn't the entire file, so add the extent + * we got last time and exit. + * + * This is for the case where say we want to map all the + * way up to the second to the last block in a file, but + * the last block is a hole, making the second to last + * block FIEMAP_EXTENT_LAST. In this case we want to + * see if there is a hole after the second to last block + * so we can mark it properly. If we found data after + * we exceeded the length we were requesting, then we + * are good to go, just add the extent to the fieinfo + * and break + */ + if (length <= 0 && !whole_file) { + ret = fiemap_fill_next_extent(fieinfo, logical, + phys, size, + flags); + break; + } + + /* + * if size != 0 then we know we already have an extent + * to add, so add it. + */ + if (size) { ret = fiemap_fill_next_extent(fieinfo, logical, phys, size, flags); @@ -319,19 +359,14 @@ int __generic_block_fiemap(struct inode *inode, start_blk += logical_to_blk(inode, size); /* - * if we are past the EOF we need to loop again to see - * if there is a hole so we can mark this extent as the - * last one, and if not keep mapping things until we - * find a hole, or we run out of slots in the extent - * array + * If we are past the EOF, then we need to make sure as + * soon as we find a hole that the last extent we found + * is marked with FIEMAP_EXTENT_LAST */ - if (length <= 0) - continue; - - ret = fiemap_fill_next_extent(fieinfo, logical, phys, - size, flags); - if (ret) - break; + if (!past_eof && + logical+size >= + blk_to_logical(inode, 0)+i_size_read(inode)) + past_eof = 1; } cond_resched(); } while (1); diff --git a/fs/libfs.c b/fs/libfs.c index cd223190c4e..80046ddf506 100644 --- a/fs/libfs.c +++ b/fs/libfs.c @@ -246,8 +246,7 @@ int get_sb_pseudo(struct file_system_type *fs_type, char *name, return 0; Enomem: - up_write(&s->s_umount); - deactivate_super(s); + deactivate_locked_super(s); return -ENOMEM; } diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c index abf83881f68..1a54ae14a19 100644 --- a/fs/lockd/svc.c +++ b/fs/lockd/svc.c @@ -104,6 +104,16 @@ static void set_grace_period(void) schedule_delayed_work(&grace_period_end, grace_period); } +static void restart_grace(void) +{ + if (nlmsvc_ops) { + cancel_delayed_work_sync(&grace_period_end); + locks_end_grace(&lockd_manager); + nlmsvc_invalidate_all(); + set_grace_period(); + } +} + /* * This is the lockd kernel thread */ @@ -149,10 +159,7 @@ lockd(void *vrqstp) if (signalled()) { flush_signals(current); - if (nlmsvc_ops) { - nlmsvc_invalidate_all(); - set_grace_period(); - } + restart_grace(); continue; } diff --git a/fs/namei.c b/fs/namei.c index 78f253cd2d4..967c3db9272 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -1130,8 +1130,8 @@ int vfs_path_lookup(struct dentry *dentry, struct vfsmount *mnt, * @nd: pointer to nameidata * @open_flags: open intent flags */ -int path_lookup_open(int dfd, const char *name, unsigned int lookup_flags, - struct nameidata *nd, int open_flags) +static int path_lookup_open(int dfd, const char *name, + unsigned int lookup_flags, struct nameidata *nd, int open_flags) { struct file *filp = get_empty_filp(); int err; @@ -1637,18 +1637,19 @@ static int open_will_write_to_fs(int flag, struct inode *inode) * open_to_namei_flags() for more details. */ struct file *do_filp_open(int dfd, const char *pathname, - int open_flag, int mode) + int open_flag, int mode, int acc_mode) { struct file *filp; struct nameidata nd; - int acc_mode, error; + int error; struct path path; struct dentry *dir; int count = 0; int will_write; int flag = open_to_namei_flags(open_flag); - acc_mode = MAY_OPEN | ACC_MODE(flag); + if (!acc_mode) + acc_mode = MAY_OPEN | ACC_MODE(flag); /* O_TRUNC implies we need access checks for write permissions */ if (flag & O_TRUNC) @@ -1869,7 +1870,7 @@ do_link: */ struct file *filp_open(const char *filename, int flags, int mode) { - return do_filp_open(AT_FDCWD, filename, flags, mode); + return do_filp_open(AT_FDCWD, filename, flags, mode, 0); } EXPORT_SYMBOL(filp_open); diff --git a/fs/namespace.c b/fs/namespace.c index 41196209a90..134d494158d 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -695,12 +695,16 @@ static inline void mangle(struct seq_file *m, const char *s) */ int generic_show_options(struct seq_file *m, struct vfsmount *mnt) { - const char *options = mnt->mnt_sb->s_options; + const char *options; + + rcu_read_lock(); + options = rcu_dereference(mnt->mnt_sb->s_options); if (options != NULL && options[0]) { seq_putc(m, ','); mangle(m, options); } + rcu_read_unlock(); return 0; } @@ -721,11 +725,22 @@ EXPORT_SYMBOL(generic_show_options); */ void save_mount_options(struct super_block *sb, char *options) { - kfree(sb->s_options); - sb->s_options = kstrdup(options, GFP_KERNEL); + BUG_ON(sb->s_options); + rcu_assign_pointer(sb->s_options, kstrdup(options, GFP_KERNEL)); } EXPORT_SYMBOL(save_mount_options); +void replace_mount_options(struct super_block *sb, char *options) +{ + char *old = sb->s_options; + rcu_assign_pointer(sb->s_options, options); + if (old) { + synchronize_rcu(); + kfree(old); + } +} +EXPORT_SYMBOL(replace_mount_options); + #ifdef CONFIG_PROC_FS /* iterator */ static void *m_start(struct seq_file *m, loff_t *pos) @@ -1073,9 +1088,7 @@ static int do_umount(struct vfsmount *mnt, int flags) */ if (flags & MNT_FORCE && sb->s_op->umount_begin) { - lock_kernel(); sb->s_op->umount_begin(sb); - unlock_kernel(); } /* diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 5a97bcfe03e..ec7e27d00bc 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c @@ -517,10 +517,10 @@ static int nfs_vm_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) ret = nfs_updatepage(filp, page, 0, pagelen); out_unlock: + if (!ret) + return VM_FAULT_LOCKED; unlock_page(page); - if (ret) - ret = VM_FAULT_SIGBUS; - return ret; + return VM_FAULT_SIGBUS; } static struct vm_operations_struct nfs_file_vm_ops = { diff --git a/fs/nfs/super.c b/fs/nfs/super.c index 6717200923f..d2d67781c57 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c @@ -683,9 +683,12 @@ static int nfs_show_stats(struct seq_file *m, struct vfsmount *mnt) */ static void nfs_umount_begin(struct super_block *sb) { - struct nfs_server *server = NFS_SB(sb); + struct nfs_server *server; struct rpc_clnt *rpc; + lock_kernel(); + + server = NFS_SB(sb); /* -EIO all pending I/O */ rpc = server->client_acl; if (!IS_ERR(rpc)) @@ -693,6 +696,8 @@ static void nfs_umount_begin(struct super_block *sb) rpc = server->client; if (!IS_ERR(rpc)) rpc_killall_tasks(rpc); + + unlock_kernel(); } /* @@ -2106,8 +2111,7 @@ out_err_nosb: error_splat_root: dput(mntroot); error_splat_super: - up_write(&s->s_umount); - deactivate_super(s); + deactivate_locked_super(s); goto out; } @@ -2203,8 +2207,7 @@ out_err_noserver: return error; error_splat_super: - up_write(&s->s_umount); - deactivate_super(s); + deactivate_locked_super(s); dprintk("<-- nfs_xdev_get_sb() = %d [splat]\n", error); return error; } @@ -2464,8 +2467,7 @@ out_free: error_splat_root: dput(mntroot); error_splat_super: - up_write(&s->s_umount); - deactivate_super(s); + deactivate_locked_super(s); goto out; } @@ -2559,8 +2561,7 @@ out_err_noserver: return error; error_splat_super: - up_write(&s->s_umount); - deactivate_super(s); + deactivate_locked_super(s); dprintk("<-- nfs4_xdev_get_sb() = %d [splat]\n", error); return error; } @@ -2644,8 +2645,7 @@ out_err_noserver: return error; error_splat_super: - up_write(&s->s_umount); - deactivate_super(s); + deactivate_locked_super(s); dprintk("<-- nfs4_referral_get_sb() = %d [splat]\n", error); return error; } diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c index 5275097a756..b5348405046 100644 --- a/fs/nfsd/nfs4recover.c +++ b/fs/nfsd/nfs4recover.c @@ -229,7 +229,7 @@ nfsd4_list_rec_dir(struct dentry *dir, recdir_func *f) goto out; status = vfs_readdir(filp, nfsd4_build_namelist, &names); fput(filp); - mutex_lock(&dir->d_inode->i_mutex); + mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT); while (!list_empty(&names)) { entry = list_entry(names.next, struct name_list, list); @@ -264,7 +264,7 @@ 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); + mutex_lock_nested(&rec_dir.dentry->d_inode->i_mutex, I_MUTEX_PARENT); dentry = lookup_one_len(name, rec_dir.dentry, namlen); if (IS_ERR(dentry)) { status = PTR_ERR(dentry); diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index c65a27b76a9..3b711f5147a 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -580,7 +580,6 @@ free_session(struct kref *kref) struct nfsd4_cache_entry *e = &ses->se_slots[i].sl_cache_entry; nfsd4_release_respages(e->ce_respages, e->ce_resused); } - kfree(ses->se_slots); kfree(ses); } diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index b820c311931..b73549d293b 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -2214,6 +2214,15 @@ nfsd4_encode_dirent_fattr(struct nfsd4_readdir *cd, dentry = lookup_one_len(name, cd->rd_fhp->fh_dentry, namlen); if (IS_ERR(dentry)) return nfserrno(PTR_ERR(dentry)); + if (!dentry->d_inode) { + /* + * nfsd_buffered_readdir drops the i_mutex between + * readdir and calling this callback, leaving a window + * where this directory entry could have gone away. + */ + dput(dentry); + return nfserr_noent; + } exp_get(exp); /* @@ -2276,6 +2285,7 @@ nfsd4_encode_dirent(void *ccdv, const char *name, int namlen, struct nfsd4_readdir *cd = container_of(ccd, struct nfsd4_readdir, common); int buflen; __be32 *p = cd->buffer; + __be32 *cookiep; __be32 nfserr = nfserr_toosmall; /* In nfsv4, "." and ".." never make it onto the wire.. */ @@ -2292,7 +2302,7 @@ nfsd4_encode_dirent(void *ccdv, const char *name, int namlen, goto fail; *p++ = xdr_one; /* mark entry present */ - cd->offset = p; /* remember pointer */ + cookiep = p; p = xdr_encode_hyper(p, NFS_OFFSET_MAX); /* offset of next entry */ p = xdr_encode_array(p, name, namlen); /* name length & name */ @@ -2306,6 +2316,8 @@ nfsd4_encode_dirent(void *ccdv, const char *name, int namlen, goto fail; case nfserr_dropit: goto fail; + case nfserr_noent: + goto skip_entry; default: /* * If the client requested the RDATTR_ERROR attribute, @@ -2324,6 +2336,8 @@ nfsd4_encode_dirent(void *ccdv, const char *name, int namlen, } cd->buflen -= (p - cd->buffer); cd->buffer = p; + cd->offset = cookiep; +skip_entry: cd->common.err = nfs_ok; return 0; fail: diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c index bed766e435b..1634319e240 100644 --- a/fs/notify/inotify/inotify_user.c +++ b/fs/notify/inotify/inotify_user.c @@ -220,7 +220,7 @@ static struct inotify_kernel_event * kernel_event(s32 wd, u32 mask, u32 cookie, rem = 0; } - kevent->name = kmalloc(len + rem, GFP_KERNEL); + kevent->name = kmalloc(len + rem, GFP_NOFS); if (unlikely(!kevent->name)) { kmem_cache_free(event_cachep, kevent); return NULL; diff --git a/fs/ocfs2/dcache.c b/fs/ocfs2/dcache.c index 7d604480557..b574431a031 100644 --- a/fs/ocfs2/dcache.c +++ b/fs/ocfs2/dcache.c @@ -290,6 +290,21 @@ out_attach: else mlog_errno(ret); + /* + * In case of error, manually free the allocation and do the iput(). + * We need to do this because error here means no d_instantiate(), + * which means iput() will not be called during dput(dentry). + */ + if (ret < 0 && !alias) { + ocfs2_lock_res_free(&dl->dl_lockres); + BUG_ON(dl->dl_count != 1); + spin_lock(&dentry_attach_lock); + dentry->d_fsdata = NULL; + spin_unlock(&dentry_attach_lock); + kfree(dl); + iput(inode); + } + dput(alias); return ret; diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c index e71160cda11..c5752305627 100644 --- a/fs/ocfs2/dir.c +++ b/fs/ocfs2/dir.c @@ -2697,7 +2697,7 @@ static int ocfs2_dx_dir_index_block(struct inode *dir, u32 *num_dx_entries, struct buffer_head *dirent_bh) { - int ret, namelen, i; + int ret = 0, namelen, i; char *de_buf, *limit; struct ocfs2_dir_entry *de; struct buffer_head *dx_leaf_bh; @@ -2934,7 +2934,7 @@ static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh, */ BUG_ON(alloc > 2); - ret = ocfs2_reserve_clusters(osb, alloc, &data_ac); + ret = ocfs2_reserve_clusters(osb, alloc + dx_alloc, &data_ac); if (ret) { mlog_errno(ret); goto out; diff --git a/fs/ocfs2/export.c b/fs/ocfs2/export.c index de3da8eb558..15713cbb865 100644 --- a/fs/ocfs2/export.c +++ b/fs/ocfs2/export.c @@ -100,7 +100,8 @@ static struct dentry *ocfs2_get_dentry(struct super_block *sb, /* If the inode allocator bit is clear, this inode must be stale */ if (!set) { - mlog(0, "inode %llu suballoc bit is clear\n", blkno); + mlog(0, "inode %llu suballoc bit is clear\n", + (unsigned long long)blkno); status = -ESTALE; goto unlock_nfs_sync; } @@ -114,7 +115,7 @@ check_err: if (status < 0) { if (status == -ESTALE) { mlog(0, "stale inode ino: %llu generation: %u\n", - blkno, handle->ih_generation); + (unsigned long long)blkno, handle->ih_generation); } result = ERR_PTR(status); goto bail; @@ -129,8 +130,8 @@ check_err: check_gen: if (handle->ih_generation != inode->i_generation) { iput(inode); - mlog(0, "stale inode ino: %llu generation: %u\n", blkno, - handle->ih_generation); + mlog(0, "stale inode ino: %llu generation: %u\n", + (unsigned long long)blkno, handle->ih_generation); result = ERR_PTR(-ESTALE); goto bail; } diff --git a/fs/ocfs2/journal.h b/fs/ocfs2/journal.h index 619dd7f6c05..eb7b76331eb 100644 --- a/fs/ocfs2/journal.h +++ b/fs/ocfs2/journal.h @@ -437,8 +437,9 @@ static inline int ocfs2_unlink_credits(struct super_block *sb) } /* dinode + orphan dir dinode + inode alloc dinode + orphan dir entry + - * inode alloc group descriptor + orphan dir index leaf */ -#define OCFS2_DELETE_INODE_CREDITS (3 * OCFS2_INODE_UPDATE_CREDITS + 3) + * inode alloc group descriptor + orphan dir index root + + * orphan dir index leaf */ +#define OCFS2_DELETE_INODE_CREDITS (3 * OCFS2_INODE_UPDATE_CREDITS + 4) /* dinode update, old dir dinode update, new dir dinode update, old * dir dir entry, new dir dir entry, dir entry update for renaming diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c index 2220f93f668..33464c6b60a 100644 --- a/fs/ocfs2/namei.c +++ b/fs/ocfs2/namei.c @@ -1025,10 +1025,8 @@ static int ocfs2_rename(struct inode *old_dir, struct inode *orphan_dir = NULL; struct ocfs2_dinode *newfe = NULL; char orphan_name[OCFS2_ORPHAN_NAMELEN + 1]; - struct buffer_head *orphan_entry_bh = NULL; struct buffer_head *newfe_bh = NULL; struct buffer_head *old_inode_bh = NULL; - struct buffer_head *insert_entry_bh = NULL; struct ocfs2_super *osb = NULL; u64 newfe_blkno, old_de_ino; handle_t *handle = NULL; @@ -1455,8 +1453,6 @@ bail: brelse(old_inode_bh); brelse(old_dir_bh); brelse(new_dir_bh); - brelse(orphan_entry_bh); - brelse(insert_entry_bh); mlog_exit(status); diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c index b4ca5911caa..8439f6b324b 100644 --- a/fs/ocfs2/suballoc.c +++ b/fs/ocfs2/suballoc.c @@ -2197,26 +2197,29 @@ static int ocfs2_get_suballoc_slot_bit(struct ocfs2_super *osb, u64 blkno, struct buffer_head *inode_bh = NULL; struct ocfs2_dinode *inode_fe; - mlog_entry("blkno: %llu\n", blkno); + mlog_entry("blkno: %llu\n", (unsigned long long)blkno); /* dirty read disk */ status = ocfs2_read_blocks_sync(osb, blkno, 1, &inode_bh); if (status < 0) { - mlog(ML_ERROR, "read block %llu failed %d\n", blkno, status); + mlog(ML_ERROR, "read block %llu failed %d\n", + (unsigned long long)blkno, status); goto bail; } inode_fe = (struct ocfs2_dinode *) inode_bh->b_data; if (!OCFS2_IS_VALID_DINODE(inode_fe)) { - mlog(ML_ERROR, "invalid inode %llu requested\n", blkno); + mlog(ML_ERROR, "invalid inode %llu requested\n", + (unsigned long long)blkno); status = -EINVAL; goto bail; } - if (le16_to_cpu(inode_fe->i_suballoc_slot) != OCFS2_INVALID_SLOT && + if (le16_to_cpu(inode_fe->i_suballoc_slot) != (u16)OCFS2_INVALID_SLOT && (u32)le16_to_cpu(inode_fe->i_suballoc_slot) > osb->max_slots - 1) { mlog(ML_ERROR, "inode %llu has invalid suballoc slot %u\n", - blkno, (u32)le16_to_cpu(inode_fe->i_suballoc_slot)); + (unsigned long long)blkno, + (u32)le16_to_cpu(inode_fe->i_suballoc_slot)); status = -EINVAL; goto bail; } @@ -2251,7 +2254,8 @@ static int ocfs2_test_suballoc_bit(struct ocfs2_super *osb, u64 bg_blkno; int status; - mlog_entry("blkno: %llu bit: %u\n", blkno, (unsigned int)bit); + mlog_entry("blkno: %llu bit: %u\n", (unsigned long long)blkno, + (unsigned int)bit); alloc_fe = (struct ocfs2_dinode *)alloc_bh->b_data; if ((bit + 1) > ocfs2_bits_per_group(&alloc_fe->id2.i_chain)) { @@ -2266,7 +2270,8 @@ static int ocfs2_test_suballoc_bit(struct ocfs2_super *osb, status = ocfs2_read_group_descriptor(suballoc, alloc_fe, bg_blkno, &group_bh); if (status < 0) { - mlog(ML_ERROR, "read group %llu failed %d\n", bg_blkno, status); + mlog(ML_ERROR, "read group %llu failed %d\n", + (unsigned long long)bg_blkno, status); goto bail; } @@ -2300,7 +2305,7 @@ int ocfs2_test_inode_bit(struct ocfs2_super *osb, u64 blkno, int *res) struct inode *inode_alloc_inode; struct buffer_head *alloc_bh = NULL; - mlog_entry("blkno: %llu", blkno); + mlog_entry("blkno: %llu", (unsigned long long)blkno); status = ocfs2_get_suballoc_slot_bit(osb, blkno, &suballoc_slot, &suballoc_bit); diff --git a/fs/ocfs2/symlink.c b/fs/ocfs2/symlink.c index ed0a0cfd68d..579dd1b1110 100644 --- a/fs/ocfs2/symlink.c +++ b/fs/ocfs2/symlink.c @@ -39,6 +39,7 @@ #include <linux/slab.h> #include <linux/pagemap.h> #include <linux/utsname.h> +#include <linux/namei.h> #define MLOG_MASK_PREFIX ML_NAMEI #include <cluster/masklog.h> @@ -54,26 +55,6 @@ #include "buffer_head_io.h" -static char *ocfs2_page_getlink(struct dentry * dentry, - struct page **ppage); -static char *ocfs2_fast_symlink_getlink(struct inode *inode, - struct buffer_head **bh); - -/* get the link contents into pagecache */ -static char *ocfs2_page_getlink(struct dentry * dentry, - struct page **ppage) -{ - struct page * page; - struct address_space *mapping = dentry->d_inode->i_mapping; - page = read_mapping_page(mapping, 0, NULL); - if (IS_ERR(page)) - goto sync_fail; - *ppage = page; - return kmap(page); - -sync_fail: - return (char*)page; -} static char *ocfs2_fast_symlink_getlink(struct inode *inode, struct buffer_head **bh) @@ -128,40 +109,55 @@ out: return ret; } -static void *ocfs2_follow_link(struct dentry *dentry, - struct nameidata *nd) +static void *ocfs2_fast_follow_link(struct dentry *dentry, + struct nameidata *nd) { - int status; - char *link; + int status = 0; + int len; + char *target, *link = ERR_PTR(-ENOMEM); struct inode *inode = dentry->d_inode; - struct page *page = NULL; struct buffer_head *bh = NULL; - - if (ocfs2_inode_is_fast_symlink(inode)) - link = ocfs2_fast_symlink_getlink(inode, &bh); - else - link = ocfs2_page_getlink(dentry, &page); - if (IS_ERR(link)) { - status = PTR_ERR(link); + + mlog_entry_void(); + + BUG_ON(!ocfs2_inode_is_fast_symlink(inode)); + target = ocfs2_fast_symlink_getlink(inode, &bh); + if (IS_ERR(target)) { + status = PTR_ERR(target); mlog_errno(status); goto bail; } - status = vfs_follow_link(nd, link); + /* Fast symlinks can't be large */ + len = strlen(target); + link = kzalloc(len + 1, GFP_NOFS); + if (!link) { + status = -ENOMEM; + mlog_errno(status); + goto bail; + } + + memcpy(link, target, len); + nd_set_link(nd, link); bail: - if (page) { - kunmap(page); - page_cache_release(page); - } brelse(bh); - return ERR_PTR(status); + mlog_exit(status); + return status ? ERR_PTR(status) : link; +} + +static void ocfs2_fast_put_link(struct dentry *dentry, struct nameidata *nd, void *cookie) +{ + char *link = cookie; + + kfree(link); } const struct inode_operations ocfs2_symlink_inode_operations = { .readlink = page_readlink, - .follow_link = ocfs2_follow_link, + .follow_link = page_follow_link_light, + .put_link = page_put_link, .getattr = ocfs2_getattr, .setattr = ocfs2_setattr, .setxattr = generic_setxattr, @@ -171,7 +167,8 @@ const struct inode_operations ocfs2_symlink_inode_operations = { }; const struct inode_operations ocfs2_fast_symlink_inode_operations = { .readlink = ocfs2_readlink, - .follow_link = ocfs2_follow_link, + .follow_link = ocfs2_fast_follow_link, + .put_link = ocfs2_fast_put_link, .getattr = ocfs2_getattr, .setattr = ocfs2_setattr, .setxattr = generic_setxattr, diff --git a/fs/open.c b/fs/open.c index 377eb25b6ab..bdfbf03615a 100644 --- a/fs/open.c +++ b/fs/open.c @@ -1033,7 +1033,7 @@ long do_sys_open(int dfd, const char __user *filename, int flags, int mode) if (!IS_ERR(tmp)) { fd = get_unused_fd_flags(flags); if (fd >= 0) { - struct file *f = do_filp_open(dfd, tmp, flags, mode); + struct file *f = do_filp_open(dfd, tmp, flags, mode, 0); if (IS_ERR(f)) { put_unused_fd(fd); fd = PTR_ERR(f); diff --git a/fs/proc/array.c b/fs/proc/array.c index 7e4877d9dcb..725a650bbbb 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -80,6 +80,7 @@ #include <linux/delayacct.h> #include <linux/seq_file.h> #include <linux/pid_namespace.h> +#include <linux/ptrace.h> #include <linux/tracehook.h> #include <asm/pgtable.h> @@ -352,6 +353,7 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns, char state; pid_t ppid = 0, pgid = -1, sid = -1; int num_threads = 0; + int permitted; struct mm_struct *mm; unsigned long long start_time; unsigned long cmin_flt = 0, cmaj_flt = 0; @@ -364,11 +366,14 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns, state = *get_task_state(task); vsize = eip = esp = 0; + permitted = ptrace_may_access(task, PTRACE_MODE_READ); mm = get_task_mm(task); if (mm) { vsize = task_vsize(mm); - eip = KSTK_EIP(task); - esp = KSTK_ESP(task); + if (permitted) { + eip = KSTK_EIP(task); + esp = KSTK_ESP(task); + } } get_task_comm(tcomm, task); @@ -424,7 +429,7 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns, unlock_task_sighand(task, &flags); } - if (!whole || num_threads < 2) + if (permitted && (!whole || num_threads < 2)) wchan = get_wchan(task); if (!whole) { min_flt = task->min_flt; @@ -476,7 +481,7 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns, rsslim, mm ? mm->start_code : 0, mm ? mm->end_code : 0, - mm ? mm->start_stack : 0, + (permitted && mm) ? mm->start_stack : 0, esp, eip, /* The signal information here is obsolete. diff --git a/fs/proc/base.c b/fs/proc/base.c index aa763ab0077..fb45615943c 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -322,7 +322,10 @@ static int proc_pid_wchan(struct task_struct *task, char *buffer) wchan = get_wchan(task); if (lookup_symbol_name(wchan, symname) < 0) - return sprintf(buffer, "%lu", wchan); + if (!ptrace_may_access(task, PTRACE_MODE_READ)) + return 0; + else + return sprintf(buffer, "%lu", wchan); else return sprintf(buffer, "%s", symname); } diff --git a/fs/proc/meminfo.c b/fs/proc/meminfo.c index 74ea974f5ca..c6b0302af4c 100644 --- a/fs/proc/meminfo.c +++ b/fs/proc/meminfo.c @@ -35,7 +35,7 @@ static int meminfo_proc_show(struct seq_file *m, void *v) #define K(x) ((x) << (PAGE_SHIFT - 10)) si_meminfo(&i); si_swapinfo(&i); - committed = atomic_long_read(&vm_committed_space); + committed = percpu_counter_read_positive(&vm_committed_as); allowed = ((totalram_pages - hugetlb_total_pages()) * sysctl_overcommit_ratio / 100) + total_swap_pages; diff --git a/fs/proc/root.c b/fs/proc/root.c index 1e15a2b176e..b080b791d9e 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c @@ -67,8 +67,7 @@ static int proc_get_sb(struct file_system_type *fs_type, sb->s_flags = flags; err = proc_fill_super(sb); if (err) { - up_write(&sb->s_umount); - deactivate_super(sb); + deactivate_locked_super(sb); return err; } diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 39e4ad4f59f..6f61b7cc32e 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -665,6 +665,10 @@ static ssize_t pagemap_read(struct file *file, char __user *buf, goto out_task; ret = 0; + + if (!count) + goto out_task; + mm = get_task_mm(task); if (!mm) goto out_task; diff --git a/fs/reiserfs/dir.c b/fs/reiserfs/dir.c index 67a80d7e59e..45ee3d357c7 100644 --- a/fs/reiserfs/dir.c +++ b/fs/reiserfs/dir.c @@ -41,6 +41,18 @@ static int reiserfs_dir_fsync(struct file *filp, struct dentry *dentry, #define store_ih(where,what) copy_item_head (where, what) +static inline bool is_privroot_deh(struct dentry *dir, + struct reiserfs_de_head *deh) +{ + int ret = 0; +#ifdef CONFIG_REISERFS_FS_XATTR + struct dentry *privroot = REISERFS_SB(dir->d_sb)->priv_root; + ret = (dir == dir->d_parent && privroot->d_inode && + deh->deh_objectid == INODE_PKEY(privroot->d_inode)->k_objectid); +#endif + return ret; +} + int reiserfs_readdir_dentry(struct dentry *dentry, void *dirent, filldir_t filldir, loff_t *pos) { @@ -138,18 +150,8 @@ int reiserfs_readdir_dentry(struct dentry *dentry, void *dirent, } /* Ignore the .reiserfs_priv entry */ - if (reiserfs_xattrs(inode->i_sb) && - !old_format_only(inode->i_sb) && - dentry == inode->i_sb->s_root && - REISERFS_SB(inode->i_sb)->priv_root && - REISERFS_SB(inode->i_sb)->priv_root->d_inode - && deh_objectid(deh) == - le32_to_cpu(INODE_PKEY - (REISERFS_SB(inode->i_sb)-> - priv_root->d_inode)-> - k_objectid)) { + if (is_privroot_deh(dentry, deh)) continue; - } d_off = deh_offset(deh); *pos = d_off; diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c index efd4d720718..27157912863 100644 --- a/fs/reiserfs/namei.c +++ b/fs/reiserfs/namei.c @@ -338,21 +338,8 @@ static struct dentry *reiserfs_lookup(struct inode *dir, struct dentry *dentry, &path_to_entry, &de); pathrelse(&path_to_entry); if (retval == NAME_FOUND) { - /* Hide the .reiserfs_priv directory */ - if (reiserfs_xattrs(dir->i_sb) && - !old_format_only(dir->i_sb) && - REISERFS_SB(dir->i_sb)->priv_root && - REISERFS_SB(dir->i_sb)->priv_root->d_inode && - de.de_objectid == - le32_to_cpu(INODE_PKEY - (REISERFS_SB(dir->i_sb)->priv_root->d_inode)-> - k_objectid)) { - reiserfs_write_unlock(dir->i_sb); - return ERR_PTR(-EACCES); - } - - inode = - reiserfs_iget(dir->i_sb, (struct cpu_key *)&(de.de_dir_id)); + inode = reiserfs_iget(dir->i_sb, + (struct cpu_key *)&(de.de_dir_id)); if (!inode || IS_ERR(inode)) { reiserfs_write_unlock(dir->i_sb); return ERR_PTR(-EACCES); diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index 0ae6486d904..1215a4f50cd 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c @@ -1316,8 +1316,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) } out_ok: - kfree(s->s_options); - s->s_options = new_opts; + replace_mount_options(s, new_opts); return 0; out_err: @@ -1842,7 +1841,8 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent) goto error; } - if ((errval = reiserfs_xattr_init(s, s->s_flags))) { + if ((errval = reiserfs_lookup_privroot(s)) || + (errval = reiserfs_xattr_init(s, s->s_flags))) { dput(s->s_root); s->s_root = NULL; goto error; @@ -1855,7 +1855,8 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent) reiserfs_info(s, "using 3.5.x disk format\n"); } - if ((errval = reiserfs_xattr_init(s, s->s_flags))) { + if ((errval = reiserfs_lookup_privroot(s)) || + (errval = reiserfs_xattr_init(s, s->s_flags))) { dput(s->s_root); s->s_root = NULL; goto error; diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c index f83f52bae39..2237e10c7c7 100644 --- a/fs/reiserfs/xattr.c +++ b/fs/reiserfs/xattr.c @@ -113,41 +113,28 @@ static int xattr_rmdir(struct inode *dir, struct dentry *dentry) #define xattr_may_create(flags) (!flags || flags & XATTR_CREATE) -/* Returns and possibly creates the xattr dir. */ -static struct dentry *lookup_or_create_dir(struct dentry *parent, - const char *name, int flags) +static struct dentry *open_xa_root(struct super_block *sb, int flags) { - struct dentry *dentry; - BUG_ON(!parent); + struct dentry *privroot = REISERFS_SB(sb)->priv_root; + struct dentry *xaroot; + if (!privroot->d_inode) + return ERR_PTR(-ENODATA); - dentry = lookup_one_len(name, parent, strlen(name)); - if (IS_ERR(dentry)) - return dentry; - else if (!dentry->d_inode) { - int err = -ENODATA; - - if (xattr_may_create(flags)) { - mutex_lock_nested(&parent->d_inode->i_mutex, - I_MUTEX_XATTR); - err = xattr_mkdir(parent->d_inode, dentry, 0700); - mutex_unlock(&parent->d_inode->i_mutex); - } + mutex_lock_nested(&privroot->d_inode->i_mutex, I_MUTEX_XATTR); + xaroot = dget(REISERFS_SB(sb)->xattr_root); + if (!xaroot->d_inode) { + int err = -ENODATA; + if (xattr_may_create(flags)) + err = xattr_mkdir(privroot->d_inode, xaroot, 0700); if (err) { - dput(dentry); - dentry = ERR_PTR(err); + dput(xaroot); + xaroot = ERR_PTR(err); } } - return dentry; -} - -static struct dentry *open_xa_root(struct super_block *sb, int flags) -{ - struct dentry *privroot = REISERFS_SB(sb)->priv_root; - if (!privroot) - return ERR_PTR(-ENODATA); - return lookup_or_create_dir(privroot, XAROOT_NAME, flags); + mutex_unlock(&privroot->d_inode->i_mutex); + return xaroot; } static struct dentry *open_xa_dir(const struct inode *inode, int flags) @@ -163,10 +150,22 @@ static struct dentry *open_xa_dir(const struct inode *inode, int flags) le32_to_cpu(INODE_PKEY(inode)->k_objectid), inode->i_generation); - xadir = lookup_or_create_dir(xaroot, namebuf, flags); + mutex_lock_nested(&xaroot->d_inode->i_mutex, I_MUTEX_XATTR); + + xadir = lookup_one_len(namebuf, xaroot, strlen(namebuf)); + if (!IS_ERR(xadir) && !xadir->d_inode) { + int err = -ENODATA; + if (xattr_may_create(flags)) + err = xattr_mkdir(xaroot->d_inode, xadir, 0700); + if (err) { + dput(xadir); + xadir = ERR_PTR(err); + } + } + + mutex_unlock(&xaroot->d_inode->i_mutex); dput(xaroot); return xadir; - } /* The following are side effects of other operations that aren't explicitly @@ -184,6 +183,7 @@ fill_with_dentries(void *buf, const char *name, int namelen, loff_t offset, { struct reiserfs_dentry_buf *dbuf = buf; struct dentry *dentry; + WARN_ON_ONCE(!mutex_is_locked(&dbuf->xadir->d_inode->i_mutex)); if (dbuf->count == ARRAY_SIZE(dbuf->dentries)) return -ENOSPC; @@ -349,6 +349,7 @@ static struct dentry *xattr_lookup(struct inode *inode, const char *name, if (IS_ERR(xadir)) return ERR_CAST(xadir); + mutex_lock_nested(&xadir->d_inode->i_mutex, I_MUTEX_XATTR); xafile = lookup_one_len(name, xadir, strlen(name)); if (IS_ERR(xafile)) { err = PTR_ERR(xafile); @@ -360,18 +361,15 @@ static struct dentry *xattr_lookup(struct inode *inode, const char *name, if (!xafile->d_inode) { err = -ENODATA; - if (xattr_may_create(flags)) { - mutex_lock_nested(&xadir->d_inode->i_mutex, - I_MUTEX_XATTR); + if (xattr_may_create(flags)) err = xattr_create(xadir->d_inode, xafile, 0700|S_IFREG); - mutex_unlock(&xadir->d_inode->i_mutex); - } } if (err) dput(xafile); out: + mutex_unlock(&xadir->d_inode->i_mutex); dput(xadir); if (err) return ERR_PTR(err); @@ -435,6 +433,7 @@ static int lookup_and_delete_xattr(struct inode *inode, const char *name) if (IS_ERR(xadir)) return PTR_ERR(xadir); + mutex_lock_nested(&xadir->d_inode->i_mutex, I_MUTEX_XATTR); dentry = lookup_one_len(name, xadir, strlen(name)); if (IS_ERR(dentry)) { err = PTR_ERR(dentry); @@ -442,14 +441,13 @@ static int lookup_and_delete_xattr(struct inode *inode, const char *name) } if (dentry->d_inode) { - mutex_lock_nested(&xadir->d_inode->i_mutex, I_MUTEX_XATTR); err = xattr_unlink(xadir->d_inode, dentry); - mutex_unlock(&xadir->d_inode->i_mutex); update_ctime(inode); } dput(dentry); out_dput: + mutex_unlock(&xadir->d_inode->i_mutex); dput(xadir); return err; } @@ -843,7 +841,7 @@ ssize_t reiserfs_listxattr(struct dentry * dentry, char *buffer, size_t size) if (!dentry->d_inode) return -EINVAL; - if (!reiserfs_xattrs(dentry->d_sb) || + if (!dentry->d_sb->s_xattr || get_inode_sd_version(dentry->d_inode) == STAT_DATA_V1) return -EOPNOTSUPP; @@ -906,19 +904,22 @@ static int create_privroot(struct dentry *dentry) { int err; struct inode *inode = dentry->d_parent->d_inode; - mutex_lock_nested(&inode->i_mutex, I_MUTEX_XATTR); + WARN_ON_ONCE(!mutex_is_locked(&inode->i_mutex)); + err = xattr_mkdir(inode, dentry, 0700); - mutex_unlock(&inode->i_mutex); - if (err) { - dput(dentry); - dentry = NULL; + if (err || !dentry->d_inode) { + reiserfs_warning(dentry->d_sb, "jdm-20006", + "xattrs/ACLs enabled and couldn't " + "find/create .reiserfs_priv. " + "Failing mount."); + return -EOPNOTSUPP; } - if (dentry && dentry->d_inode) - reiserfs_info(dentry->d_sb, "Created %s - reserved for xattr " - "storage.\n", PRIVROOT_NAME); + dentry->d_inode->i_flags |= S_PRIVATE; + reiserfs_info(dentry->d_sb, "Created %s - reserved for xattr " + "storage.\n", PRIVROOT_NAME); - return err; + return 0; } static int xattr_mount_check(struct super_block *s) @@ -950,11 +951,9 @@ static int xattr_lookup_poison(struct dentry *dentry, struct qstr *q1, struct qstr *name) { struct dentry *priv_root = REISERFS_SB(dentry->d_sb)->priv_root; - if (name->len == priv_root->d_name.len && - name->hash == priv_root->d_name.hash && - !memcmp(name->name, priv_root->d_name.name, name->len)) { + if (container_of(q1, struct dentry, d_name) == priv_root) return -ENOENT; - } else if (q1->len == name->len && + if (q1->len == name->len && !memcmp(q1->name, name->name, name->len)) return 0; return 1; @@ -964,59 +963,60 @@ static const struct dentry_operations xattr_lookup_poison_ops = { .d_compare = xattr_lookup_poison, }; +int reiserfs_lookup_privroot(struct super_block *s) +{ + struct dentry *dentry; + int err = 0; + + /* If we don't have the privroot located yet - go find it */ + mutex_lock(&s->s_root->d_inode->i_mutex); + dentry = lookup_one_len(PRIVROOT_NAME, s->s_root, + strlen(PRIVROOT_NAME)); + if (!IS_ERR(dentry)) { + REISERFS_SB(s)->priv_root = dentry; + s->s_root->d_op = &xattr_lookup_poison_ops; + if (dentry->d_inode) + dentry->d_inode->i_flags |= S_PRIVATE; + } else + err = PTR_ERR(dentry); + mutex_unlock(&s->s_root->d_inode->i_mutex); + + return err; +} + /* We need to take a copy of the mount flags since things like * MS_RDONLY don't get set until *after* we're called. * mount_flags != mount_options */ int reiserfs_xattr_init(struct super_block *s, int mount_flags) { int err = 0; + struct dentry *privroot = REISERFS_SB(s)->priv_root; #ifdef CONFIG_REISERFS_FS_XATTR err = xattr_mount_check(s); if (err) goto error; -#endif - /* If we don't have the privroot located yet - go find it */ - if (!REISERFS_SB(s)->priv_root) { - struct dentry *dentry; - dentry = lookup_one_len(PRIVROOT_NAME, s->s_root, - strlen(PRIVROOT_NAME)); - if (!IS_ERR(dentry)) { -#ifdef CONFIG_REISERFS_FS_XATTR - if (!(mount_flags & MS_RDONLY) && !dentry->d_inode) - err = create_privroot(dentry); -#endif - if (!dentry->d_inode) { - dput(dentry); - dentry = NULL; - } - } else - err = PTR_ERR(dentry); - - if (!err && dentry) { - s->s_root->d_op = &xattr_lookup_poison_ops; - dentry->d_inode->i_flags |= S_PRIVATE; - REISERFS_SB(s)->priv_root = dentry; -#ifdef CONFIG_REISERFS_FS_XATTR - /* xattrs are unavailable */ - } else if (!(mount_flags & MS_RDONLY)) { - /* If we're read-only it just means that the dir - * hasn't been created. Not an error -- just no - * xattrs on the fs. We'll check again if we - * go read-write */ - reiserfs_warning(s, "jdm-20006", - "xattrs/ACLs enabled and couldn't " - "find/create .reiserfs_priv. " - "Failing mount."); - err = -EOPNOTSUPP; -#endif - } + if (!privroot->d_inode && !(mount_flags & MS_RDONLY)) { + mutex_lock(&s->s_root->d_inode->i_mutex); + err = create_privroot(REISERFS_SB(s)->priv_root); + mutex_unlock(&s->s_root->d_inode->i_mutex); } -#ifdef CONFIG_REISERFS_FS_XATTR - if (!err) + if (privroot->d_inode) { s->s_xattr = reiserfs_xattr_handlers; + mutex_lock(&privroot->d_inode->i_mutex); + if (!REISERFS_SB(s)->xattr_root) { + struct dentry *dentry; + dentry = lookup_one_len(XAROOT_NAME, privroot, + strlen(XAROOT_NAME)); + if (!IS_ERR(dentry)) + REISERFS_SB(s)->xattr_root = dentry; + else + err = PTR_ERR(dentry); + } + mutex_unlock(&privroot->d_inode->i_mutex); + } error: if (err) { @@ -1026,11 +1026,12 @@ error: #endif /* The super_block MS_POSIXACL must mirror the (no)acl mount option. */ - s->s_flags = s->s_flags & ~MS_POSIXACL; #ifdef CONFIG_REISERFS_FS_POSIX_ACL if (reiserfs_posixacl(s)) s->s_flags |= MS_POSIXACL; + else #endif + s->s_flags &= ~MS_POSIXACL; return err; } diff --git a/fs/reiserfs/xattr_security.c b/fs/reiserfs/xattr_security.c index 4d3c20e787c..a92c8792c0f 100644 --- a/fs/reiserfs/xattr_security.c +++ b/fs/reiserfs/xattr_security.c @@ -55,8 +55,16 @@ int reiserfs_security_init(struct inode *dir, struct inode *inode, struct reiserfs_security_handle *sec) { int blocks = 0; - int error = security_inode_init_security(inode, dir, &sec->name, - &sec->value, &sec->length); + int error; + + sec->name = NULL; + + /* Don't add selinux attributes on xattrs - they'll never get used */ + if (IS_PRIVATE(dir)) + return 0; + + error = security_inode_init_security(inode, dir, &sec->name, + &sec->value, &sec->length); if (error) { if (error == -EOPNOTSUPP) error = 0; diff --git a/fs/romfs/super.c b/fs/romfs/super.c index c53b5ef8a02..4ab3c03d8f9 100644 --- a/fs/romfs/super.c +++ b/fs/romfs/super.c @@ -298,7 +298,8 @@ static struct inode *romfs_iget(struct super_block *sb, unsigned long pos) struct romfs_inode ri; struct inode *i; unsigned long nlen; - unsigned nextfh, ret; + unsigned nextfh; + int ret; umode_t mode; /* we might have to traverse a chain of "hard link" file entries to get diff --git a/fs/super.c b/fs/super.c index 786fe7d7279..1943fdf655f 100644 --- a/fs/super.c +++ b/fs/super.c @@ -208,6 +208,34 @@ void deactivate_super(struct super_block *s) EXPORT_SYMBOL(deactivate_super); /** + * deactivate_locked_super - drop an active reference to superblock + * @s: superblock to deactivate + * + * Equivalent of up_write(&s->s_umount); deactivate_super(s);, except that + * it does not unlock it until it's all over. As the result, it's safe to + * use to dispose of new superblock on ->get_sb() failure exits - nobody + * will see the sucker until it's all over. Equivalent using up_write + + * deactivate_super is safe for that purpose only if superblock is either + * safe to use or has NULL ->s_root when we unlock. + */ +void deactivate_locked_super(struct super_block *s) +{ + struct file_system_type *fs = s->s_type; + if (atomic_dec_and_lock(&s->s_active, &sb_lock)) { + s->s_count -= S_BIAS-1; + spin_unlock(&sb_lock); + vfs_dq_off(s, 0); + fs->kill_sb(s); + put_filesystem(fs); + put_super(s); + } else { + up_write(&s->s_umount); + } +} + +EXPORT_SYMBOL(deactivate_locked_super); + +/** * grab_super - acquire an active reference * @s: reference we are trying to make active * @@ -797,8 +825,7 @@ int get_sb_ns(struct file_system_type *fs_type, int flags, void *data, sb->s_flags = flags; err = fill_super(sb, data, flags & MS_SILENT ? 1 : 0); if (err) { - up_write(&sb->s_umount); - deactivate_super(sb); + deactivate_locked_super(sb); return err; } @@ -854,8 +881,7 @@ int get_sb_bdev(struct file_system_type *fs_type, if (s->s_root) { if ((flags ^ s->s_flags) & MS_RDONLY) { - up_write(&s->s_umount); - deactivate_super(s); + deactivate_locked_super(s); error = -EBUSY; goto error_bdev; } @@ -870,8 +896,7 @@ int get_sb_bdev(struct file_system_type *fs_type, sb_set_blocksize(s, block_size(bdev)); error = fill_super(s, data, flags & MS_SILENT ? 1 : 0); if (error) { - up_write(&s->s_umount); - deactivate_super(s); + deactivate_locked_super(s); goto error; } @@ -897,7 +922,7 @@ void kill_block_super(struct super_block *sb) struct block_device *bdev = sb->s_bdev; fmode_t mode = sb->s_mode; - bdev->bd_super = 0; + bdev->bd_super = NULL; generic_shutdown_super(sb); sync_blockdev(bdev); close_bdev_exclusive(bdev, mode); @@ -921,8 +946,7 @@ int get_sb_nodev(struct file_system_type *fs_type, error = fill_super(s, data, flags & MS_SILENT ? 1 : 0); if (error) { - up_write(&s->s_umount); - deactivate_super(s); + deactivate_locked_super(s); return error; } s->s_flags |= MS_ACTIVE; @@ -952,8 +976,7 @@ int get_sb_single(struct file_system_type *fs_type, s->s_flags = flags; error = fill_super(s, data, flags & MS_SILENT ? 1 : 0); if (error) { - up_write(&s->s_umount); - deactivate_super(s); + deactivate_locked_super(s); return error; } s->s_flags |= MS_ACTIVE; @@ -1006,8 +1029,7 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void return mnt; out_sb: dput(mnt->mnt_root); - up_write(&mnt->mnt_sb->s_umount); - deactivate_super(mnt->mnt_sb); + deactivate_locked_super(mnt->mnt_sb); out_free_secdata: free_secdata(secdata); out_mnt: diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index faa44f90608..e9f7a754c4f 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -2055,8 +2055,7 @@ static int ubifs_get_sb(struct file_system_type *fs_type, int flags, return 0; out_deact: - up_write(&sb->s_umount); - deactivate_super(sb); + deactivate_locked_super(sb); out_close: ubi_close_volume(ubi); return err; diff --git a/fs/ufs/dir.c b/fs/ufs/dir.c index dbbbc466876..6321b797061 100644 --- a/fs/ufs/dir.c +++ b/fs/ufs/dir.c @@ -666,6 +666,6 @@ not_empty: const struct file_operations ufs_dir_operations = { .read = generic_read_dir, .readdir = ufs_readdir, - .fsync = file_fsync, + .fsync = ufs_sync_file, .llseek = generic_file_llseek, }; diff --git a/fs/ufs/file.c b/fs/ufs/file.c index 625ef17c6f8..2bd3a161571 100644 --- a/fs/ufs/file.c +++ b/fs/ufs/file.c @@ -30,7 +30,7 @@ #include "ufs.h" -static int ufs_sync_file(struct file *file, struct dentry *dentry, int datasync) +int ufs_sync_file(struct file *file, struct dentry *dentry, int datasync) { struct inode *inode = dentry->d_inode; int err; diff --git a/fs/ufs/ufs.h b/fs/ufs/ufs.h index 69b3427d788..d0c4acd4f1f 100644 --- a/fs/ufs/ufs.h +++ b/fs/ufs/ufs.h @@ -98,8 +98,8 @@ extern void ufs_set_link(struct inode *dir, struct ufs_dir_entry *de, /* file.c */ extern const struct inode_operations ufs_file_inode_operations; extern const struct file_operations ufs_file_operations; - extern const struct address_space_operations ufs_aops; +extern int ufs_sync_file(struct file *, struct dentry *, int); /* ialloc.c */ extern void ufs_free_inode (struct inode *inode); diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index 3a6ed426327..ca7c6005a48 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c @@ -5880,7 +5880,7 @@ xfs_getbmap( void *arg) /* formatter arg */ { __int64_t bmvend; /* last block requested */ - int error; /* return value */ + int error = 0; /* return value */ __int64_t fixlen; /* length for -1 case */ int i; /* extent number */ int lock; /* lock state */ @@ -5890,39 +5890,18 @@ xfs_getbmap( int nexleft; /* # of user extents left */ int subnex; /* # of bmapi's can do */ int nmap; /* number of map entries */ - struct getbmapx out; /* output structure */ + struct getbmapx *out; /* output structure */ int whichfork; /* data or attr fork */ int prealloced; /* this is a file with * preallocated data space */ int iflags; /* interface flags */ int bmapi_flags; /* flags for xfs_bmapi */ + int cur_ext = 0; mp = ip->i_mount; iflags = bmv->bmv_iflags; - whichfork = iflags & BMV_IF_ATTRFORK ? XFS_ATTR_FORK : XFS_DATA_FORK; - /* If the BMV_IF_NO_DMAPI_READ interface bit specified, do not - * generate a DMAPI read event. Otherwise, if the DM_EVENT_READ - * bit is set for the file, generate a read event in order - * that the DMAPI application may do its thing before we return - * the extents. Usually this means restoring user file data to - * regions of the file that look like holes. - * - * The "old behavior" (from XFS_IOC_GETBMAP) is to not specify - * BMV_IF_NO_DMAPI_READ so that read events are generated. - * If this were not true, callers of ioctl( XFS_IOC_GETBMAP ) - * could misinterpret holes in a DMAPI file as true holes, - * when in fact they may represent offline user data. - */ - if ((iflags & BMV_IF_NO_DMAPI_READ) == 0 && - DM_EVENT_ENABLED(ip, DM_EVENT_READ) && - whichfork == XFS_DATA_FORK) { - error = XFS_SEND_DATA(mp, DM_EVENT_READ, ip, 0, 0, 0, NULL); - if (error) - return XFS_ERROR(error); - } - if (whichfork == XFS_ATTR_FORK) { if (XFS_IFORK_Q(ip)) { if (ip->i_d.di_aformat != XFS_DINODE_FMT_EXTENTS && @@ -5936,11 +5915,37 @@ xfs_getbmap( ip->i_mount); return XFS_ERROR(EFSCORRUPTED); } - } else if (ip->i_d.di_format != XFS_DINODE_FMT_EXTENTS && - ip->i_d.di_format != XFS_DINODE_FMT_BTREE && - ip->i_d.di_format != XFS_DINODE_FMT_LOCAL) - return XFS_ERROR(EINVAL); - if (whichfork == XFS_DATA_FORK) { + + prealloced = 0; + fixlen = 1LL << 32; + } else { + /* + * If the BMV_IF_NO_DMAPI_READ interface bit specified, do + * not generate a DMAPI read event. Otherwise, if the + * DM_EVENT_READ bit is set for the file, generate a read + * event in order that the DMAPI application may do its thing + * before we return the extents. Usually this means restoring + * user file data to regions of the file that look like holes. + * + * The "old behavior" (from XFS_IOC_GETBMAP) is to not specify + * BMV_IF_NO_DMAPI_READ so that read events are generated. + * If this were not true, callers of ioctl(XFS_IOC_GETBMAP) + * could misinterpret holes in a DMAPI file as true holes, + * when in fact they may represent offline user data. + */ + if (DM_EVENT_ENABLED(ip, DM_EVENT_READ) && + !(iflags & BMV_IF_NO_DMAPI_READ)) { + error = XFS_SEND_DATA(mp, DM_EVENT_READ, ip, + 0, 0, 0, NULL); + if (error) + return XFS_ERROR(error); + } + + if (ip->i_d.di_format != XFS_DINODE_FMT_EXTENTS && + ip->i_d.di_format != XFS_DINODE_FMT_BTREE && + ip->i_d.di_format != XFS_DINODE_FMT_LOCAL) + return XFS_ERROR(EINVAL); + if (xfs_get_extsz_hint(ip) || ip->i_d.di_flags & (XFS_DIFLAG_PREALLOC|XFS_DIFLAG_APPEND)){ prealloced = 1; @@ -5949,42 +5954,41 @@ xfs_getbmap( prealloced = 0; fixlen = ip->i_size; } - } else { - prealloced = 0; - fixlen = 1LL << 32; } if (bmv->bmv_length == -1) { fixlen = XFS_FSB_TO_BB(mp, XFS_B_TO_FSB(mp, fixlen)); - bmv->bmv_length = MAX( (__int64_t)(fixlen - bmv->bmv_offset), - (__int64_t)0); - } else if (bmv->bmv_length < 0) - return XFS_ERROR(EINVAL); - if (bmv->bmv_length == 0) { + bmv->bmv_length = + max_t(__int64_t, fixlen - bmv->bmv_offset, 0); + } else if (bmv->bmv_length == 0) { bmv->bmv_entries = 0; return 0; + } else if (bmv->bmv_length < 0) { + return XFS_ERROR(EINVAL); } + nex = bmv->bmv_count - 1; if (nex <= 0) return XFS_ERROR(EINVAL); bmvend = bmv->bmv_offset + bmv->bmv_length; - xfs_ilock(ip, XFS_IOLOCK_SHARED); - if (((iflags & BMV_IF_DELALLOC) == 0) && - (whichfork == XFS_DATA_FORK) && - (ip->i_delayed_blks || ip->i_size > ip->i_d.di_size)) { - /* xfs_fsize_t last_byte = xfs_file_last_byte(ip); */ - error = xfs_flush_pages(ip, (xfs_off_t)0, - -1, 0, FI_REMAPF); - if (error) { - xfs_iunlock(ip, XFS_IOLOCK_SHARED); - return error; + if (bmv->bmv_count > ULONG_MAX / sizeof(struct getbmapx)) + return XFS_ERROR(ENOMEM); + out = kmem_zalloc(bmv->bmv_count * sizeof(struct getbmapx), KM_MAYFAIL); + if (!out) + return XFS_ERROR(ENOMEM); + + xfs_ilock(ip, XFS_IOLOCK_SHARED); + if (whichfork == XFS_DATA_FORK && !(iflags & BMV_IF_DELALLOC)) { + if (ip->i_delayed_blks || ip->i_size > ip->i_d.di_size) { + error = xfs_flush_pages(ip, 0, -1, 0, FI_REMAPF); + if (error) + goto out_unlock_iolock; } - } - ASSERT(whichfork == XFS_ATTR_FORK || (iflags & BMV_IF_DELALLOC) || - ip->i_delayed_blks == 0); + ASSERT(ip->i_delayed_blks == 0); + } lock = xfs_ilock_map_shared(ip); @@ -5995,23 +5999,25 @@ xfs_getbmap( if (nex > XFS_IFORK_NEXTENTS(ip, whichfork) * 2 + 1) nex = XFS_IFORK_NEXTENTS(ip, whichfork) * 2 + 1; - bmapi_flags = xfs_bmapi_aflag(whichfork) | - ((iflags & BMV_IF_PREALLOC) ? 0 : XFS_BMAPI_IGSTATE); + bmapi_flags = xfs_bmapi_aflag(whichfork); + if (!(iflags & BMV_IF_PREALLOC)) + bmapi_flags |= XFS_BMAPI_IGSTATE; /* * Allocate enough space to handle "subnex" maps at a time. */ + error = ENOMEM; subnex = 16; - map = kmem_alloc(subnex * sizeof(*map), KM_SLEEP); + map = kmem_alloc(subnex * sizeof(*map), KM_MAYFAIL); + if (!map) + goto out_unlock_ilock; bmv->bmv_entries = 0; - if ((XFS_IFORK_NEXTENTS(ip, whichfork) == 0)) { - if (((iflags & BMV_IF_DELALLOC) == 0) || - whichfork == XFS_ATTR_FORK) { - error = 0; - goto unlock_and_return; - } + if (XFS_IFORK_NEXTENTS(ip, whichfork) == 0 && + (whichfork == XFS_ATTR_FORK || !(iflags & BMV_IF_DELALLOC))) { + error = 0; + goto out_free_map; } nexleft = nex; @@ -6023,53 +6029,61 @@ xfs_getbmap( bmapi_flags, NULL, 0, map, &nmap, NULL, NULL); if (error) - goto unlock_and_return; + goto out_free_map; ASSERT(nmap <= subnex); for (i = 0; i < nmap && nexleft && bmv->bmv_length; i++) { - out.bmv_oflags = 0; + out[cur_ext].bmv_oflags = 0; if (map[i].br_state == XFS_EXT_UNWRITTEN) - out.bmv_oflags |= BMV_OF_PREALLOC; + out[cur_ext].bmv_oflags |= BMV_OF_PREALLOC; else if (map[i].br_startblock == DELAYSTARTBLOCK) - out.bmv_oflags |= BMV_OF_DELALLOC; - out.bmv_offset = XFS_FSB_TO_BB(mp, map[i].br_startoff); - out.bmv_length = XFS_FSB_TO_BB(mp, map[i].br_blockcount); - out.bmv_unused1 = out.bmv_unused2 = 0; + out[cur_ext].bmv_oflags |= BMV_OF_DELALLOC; + out[cur_ext].bmv_offset = + XFS_FSB_TO_BB(mp, map[i].br_startoff); + out[cur_ext].bmv_length = + XFS_FSB_TO_BB(mp, map[i].br_blockcount); + out[cur_ext].bmv_unused1 = 0; + out[cur_ext].bmv_unused2 = 0; ASSERT(((iflags & BMV_IF_DELALLOC) != 0) || (map[i].br_startblock != DELAYSTARTBLOCK)); if (map[i].br_startblock == HOLESTARTBLOCK && whichfork == XFS_ATTR_FORK) { /* came to the end of attribute fork */ - out.bmv_oflags |= BMV_OF_LAST; - goto unlock_and_return; - } else { - int full = 0; /* user array is full */ - - if (!xfs_getbmapx_fix_eof_hole(ip, &out, - prealloced, bmvend, - map[i].br_startblock)) { - goto unlock_and_return; - } - - /* format results & advance arg */ - error = formatter(&arg, &out, &full); - if (error || full) - goto unlock_and_return; - nexleft--; - bmv->bmv_offset = - out.bmv_offset + out.bmv_length; - bmv->bmv_length = MAX((__int64_t)0, - (__int64_t)(bmvend - bmv->bmv_offset)); - bmv->bmv_entries++; + out[cur_ext].bmv_oflags |= BMV_OF_LAST; + goto out_free_map; } + + if (!xfs_getbmapx_fix_eof_hole(ip, &out[cur_ext], + prealloced, bmvend, + map[i].br_startblock)) + goto out_free_map; + + nexleft--; + bmv->bmv_offset = + out[cur_ext].bmv_offset + + out[cur_ext].bmv_length; + bmv->bmv_length = + max_t(__int64_t, 0, bmvend - bmv->bmv_offset); + bmv->bmv_entries++; + cur_ext++; } } while (nmap && nexleft && bmv->bmv_length); -unlock_and_return: + out_free_map: + kmem_free(map); + out_unlock_ilock: xfs_iunlock_map_shared(ip, lock); + out_unlock_iolock: xfs_iunlock(ip, XFS_IOLOCK_SHARED); - kmem_free(map); + for (i = 0; i < cur_ext; i++) { + int full = 0; /* user array is full */ + + /* format results & advance arg */ + error = formatter(&arg, &out[i], &full); + if (error || full) + break; + } return error; } diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index e7ae08d1df4..123b20c8cbf 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -1258,8 +1258,10 @@ xfs_file_last_byte( * necessary. */ if (ip->i_df.if_flags & XFS_IFEXTENTS) { + xfs_ilock(ip, XFS_ILOCK_SHARED); error = xfs_bmap_last_offset(NULL, ip, &last_block, XFS_DATA_FORK); + xfs_iunlock(ip, XFS_ILOCK_SHARED); if (error) { last_block = 0; } diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index b101990df02..65a99725d0c 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -291,14 +291,17 @@ xfs_mount_validate_sb( sbp->sb_sectsize > XFS_MAX_SECTORSIZE || sbp->sb_sectlog < XFS_MIN_SECTORSIZE_LOG || sbp->sb_sectlog > XFS_MAX_SECTORSIZE_LOG || + sbp->sb_sectsize != (1 << sbp->sb_sectlog) || sbp->sb_blocksize < XFS_MIN_BLOCKSIZE || sbp->sb_blocksize > XFS_MAX_BLOCKSIZE || sbp->sb_blocklog < XFS_MIN_BLOCKSIZE_LOG || sbp->sb_blocklog > XFS_MAX_BLOCKSIZE_LOG || + sbp->sb_blocksize != (1 << sbp->sb_blocklog) || sbp->sb_inodesize < XFS_DINODE_MIN_SIZE || sbp->sb_inodesize > XFS_DINODE_MAX_SIZE || sbp->sb_inodelog < XFS_DINODE_MIN_LOG || sbp->sb_inodelog > XFS_DINODE_MAX_LOG || + sbp->sb_inodesize != (1 << sbp->sb_inodelog) || (sbp->sb_blocklog - sbp->sb_inodelog != sbp->sb_inopblog) || (sbp->sb_rextsize * sbp->sb_blocksize > XFS_MAX_RTEXTSIZE) || (sbp->sb_rextsize * sbp->sb_blocksize < XFS_MIN_RTEXTSIZE) || diff --git a/include/asm-generic/atomic.h b/include/asm-generic/atomic.h index 7abdaa91ccd..3673a13b670 100644 --- a/include/asm-generic/atomic.h +++ b/include/asm-generic/atomic.h @@ -132,9 +132,9 @@ static inline long atomic_long_add_unless(atomic_long_t *l, long a, long u) #define atomic_long_inc_not_zero(l) atomic64_inc_not_zero((atomic64_t *)(l)) #define atomic_long_cmpxchg(l, old, new) \ - (atomic_cmpxchg((atomic64_t *)(l), (old), (new))) + (atomic64_cmpxchg((atomic64_t *)(l), (old), (new))) #define atomic_long_xchg(v, new) \ - (atomic_xchg((atomic64_t *)(l), (new))) + (atomic64_xchg((atomic64_t *)(l), (new))) #else /* BITS_PER_LONG == 64 */ diff --git a/include/asm-generic/bug.h b/include/asm-generic/bug.h index e727fe0d145..4b6755984d2 100644 --- a/include/asm-generic/bug.h +++ b/include/asm-generic/bug.h @@ -58,12 +58,13 @@ struct bug_entry { */ #ifndef __WARN #ifndef __ASSEMBLY__ -extern void warn_slowpath(const char *file, const int line, +extern void warn_slowpath_fmt(const char *file, const int line, const char *fmt, ...) __attribute__((format(printf, 3, 4))); +extern void warn_slowpath_null(const char *file, const int line); #define WANT_WARN_ON_SLOWPATH #endif -#define __WARN() warn_slowpath(__FILE__, __LINE__, NULL) -#define __WARN_printf(arg...) warn_slowpath(__FILE__, __LINE__, arg) +#define __WARN() warn_slowpath_null(__FILE__, __LINE__) +#define __WARN_printf(arg...) warn_slowpath_fmt(__FILE__, __LINE__, arg) #else #define __WARN_printf(arg...) do { printk(arg); __WARN(); } while (0) #endif diff --git a/include/linux/Kbuild b/include/linux/Kbuild index ca9b9b9bd33..3f0eaa397ef 100644 --- a/include/linux/Kbuild +++ b/include/linux/Kbuild @@ -138,6 +138,7 @@ header-y += qnxtypes.h header-y += radeonfb.h header-y += raw.h header-y += resource.h +header-y += romfs_fs.h header-y += rose.h header-y += serial_reg.h header-y += smbno.h @@ -314,7 +315,6 @@ unifdef-y += irqnr.h unifdef-y += reboot.h unifdef-y += reiserfs_fs.h unifdef-y += reiserfs_xattr.h -unifdef-y += romfs_fs.h unifdef-y += route.h unifdef-y += rtc.h unifdef-y += rtnetlink.h diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h index 6638b8148de..61ee18c1bdb 100644 --- a/include/linux/binfmts.h +++ b/include/linux/binfmts.h @@ -82,7 +82,19 @@ struct linux_binfmt { int hasvdso; }; -extern int register_binfmt(struct linux_binfmt *); +extern int __register_binfmt(struct linux_binfmt *fmt, int insert); + +/* Registration of default binfmt handlers */ +static inline int register_binfmt(struct linux_binfmt *fmt) +{ + return __register_binfmt(fmt, 0); +} +/* Same as above, but adds a new binfmt at the top of the list */ +static inline int insert_binfmt(struct linux_binfmt *fmt) +{ + return __register_binfmt(fmt, 1); +} + extern void unregister_binfmt(struct linux_binfmt *); extern int prepare_binprm(struct linux_binprm *); diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 2755d5c6da2..b4f71f1a4af 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -601,6 +601,7 @@ enum { blk_failfast_driver(rq)) #define blk_rq_started(rq) ((rq)->cmd_flags & REQ_STARTED) #define blk_rq_io_stat(rq) ((rq)->cmd_flags & REQ_IO_STAT) +#define blk_rq_quiet(rq) ((rq)->cmd_flags & REQ_QUIET) #define blk_account_rq(rq) (blk_rq_started(rq) && (blk_fs_request(rq) || blk_discard_rq(rq))) diff --git a/include/linux/device.h b/include/linux/device.h index 6a69caaac18..5d5c197bad4 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -384,13 +384,8 @@ struct device { struct device_driver *driver; /* which driver has allocated this device */ void *driver_data; /* data private to the driver */ - - void *platform_data; /* We will remove platform_data - field if all platform devices - pass its platform specific data - from platform_device->platform_data, - other kind of devices should not - use platform_data. */ + void *platform_data; /* Platform specific data, device + core doesn't touch it */ struct dev_pm_info power; #ifdef CONFIG_NUMA diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h index 2e2aa3df170..ffefba81c81 100644 --- a/include/linux/dmaengine.h +++ b/include/linux/dmaengine.h @@ -78,12 +78,18 @@ enum dma_transaction_type { * dependency chains * @DMA_COMPL_SKIP_SRC_UNMAP - set to disable dma-unmapping the source buffer(s) * @DMA_COMPL_SKIP_DEST_UNMAP - set to disable dma-unmapping the destination(s) + * @DMA_COMPL_SRC_UNMAP_SINGLE - set to do the source dma-unmapping as single + * (if not set, do the source dma-unmapping as page) + * @DMA_COMPL_DEST_UNMAP_SINGLE - set to do the destination dma-unmapping as single + * (if not set, do the destination dma-unmapping as page) */ enum dma_ctrl_flags { DMA_PREP_INTERRUPT = (1 << 0), DMA_CTRL_ACK = (1 << 1), DMA_COMPL_SKIP_SRC_UNMAP = (1 << 2), DMA_COMPL_SKIP_DEST_UNMAP = (1 << 3), + DMA_COMPL_SRC_UNMAP_SINGLE = (1 << 4), + DMA_COMPL_DEST_UNMAP_SINGLE = (1 << 5), }; /** diff --git a/include/linux/fs.h b/include/linux/fs.h index 5bed436f435..3b534e527e0 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1775,6 +1775,7 @@ void kill_block_super(struct super_block *sb); void kill_anon_super(struct super_block *sb); void kill_litter_super(struct super_block *sb); void deactivate_super(struct super_block *sb); +void deactivate_locked_super(struct super_block *sb); int set_anon_super(struct super_block *s, void *data); struct super_block *sget(struct file_system_type *type, int (*test)(struct super_block *,void *), @@ -2117,7 +2118,7 @@ extern struct file *create_write_pipe(int flags); extern void free_write_pipe(struct file *); extern struct file *do_filp_open(int dfd, const char *pathname, - int open_flag, int mode); + int open_flag, int mode, int acc_mode); extern int may_open(struct path *, int, int); extern int kernel_read(struct file *, unsigned long, char *, unsigned long); @@ -2367,6 +2368,7 @@ extern void file_update_time(struct file *file); extern int generic_show_options(struct seq_file *m, struct vfsmount *mnt); extern void save_mount_options(struct super_block *sb, char *options); +extern void replace_mount_options(struct super_block *sb, char *options); static inline ino_t parent_ino(struct dentry *dentry) { diff --git a/include/linux/input.h b/include/linux/input.h index 6b28048fc56..0e6ff5de358 100644 --- a/include/linux/input.h +++ b/include/linux/input.h @@ -106,6 +106,7 @@ struct input_absinfo { #define SYN_REPORT 0 #define SYN_CONFIG 1 +#define SYN_MT_REPORT 2 /* * Keys and buttons @@ -445,6 +446,7 @@ struct input_absinfo { #define BTN_STYLUS2 0x14c #define BTN_TOOL_DOUBLETAP 0x14d #define BTN_TOOL_TRIPLETAP 0x14e +#define BTN_TOOL_QUADTAP 0x14f /* Four fingers on trackpad */ #define BTN_WHEEL 0x150 #define BTN_GEAR_DOWN 0x150 @@ -644,6 +646,17 @@ struct input_absinfo { #define ABS_TOOL_WIDTH 0x1c #define ABS_VOLUME 0x20 #define ABS_MISC 0x28 + +#define ABS_MT_TOUCH_MAJOR 0x30 /* Major axis of touching ellipse */ +#define ABS_MT_TOUCH_MINOR 0x31 /* Minor axis (omit if circular) */ +#define ABS_MT_WIDTH_MAJOR 0x32 /* Major axis of approaching ellipse */ +#define ABS_MT_WIDTH_MINOR 0x33 /* Minor axis (omit if circular) */ +#define ABS_MT_ORIENTATION 0x34 /* Ellipse orientation */ +#define ABS_MT_POSITION_X 0x35 /* Center X ellipse position */ +#define ABS_MT_POSITION_Y 0x36 /* Center Y ellipse position */ +#define ABS_MT_TOOL_TYPE 0x37 /* Type of touching device */ +#define ABS_MT_BLOB_ID 0x38 /* Group a set of packets as a blob */ + #define ABS_MAX 0x3f #define ABS_CNT (ABS_MAX+1) @@ -743,6 +756,12 @@ struct input_absinfo { #define BUS_ATARI 0x1B /* + * MT_TOOL types + */ +#define MT_TOOL_FINGER 0 +#define MT_TOOL_PEN 1 + +/* * Values describing the status of a force-feedback effect */ #define FF_STATUS_STOPPED 0x00 @@ -1311,6 +1330,11 @@ static inline void input_sync(struct input_dev *dev) input_event(dev, EV_SYN, SYN_REPORT, 0); } +static inline void input_mt_sync(struct input_dev *dev) +{ + input_event(dev, EV_SYN, SYN_MT_REPORT, 0); +} + void input_set_capability(struct input_dev *dev, unsigned int type, unsigned int code); static inline void input_set_abs_params(struct input_dev *dev, int axis, int min, int max, int fuzz, int flat) diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h index a9e3b76aa88..25b9ca93d23 100644 --- a/include/linux/memcontrol.h +++ b/include/linux/memcontrol.h @@ -56,7 +56,7 @@ extern void mem_cgroup_move_lists(struct page *page, enum lru_list from, enum lru_list to); extern void mem_cgroup_uncharge_page(struct page *page); extern void mem_cgroup_uncharge_cache_page(struct page *page); -extern int mem_cgroup_shrink_usage(struct page *page, +extern int mem_cgroup_shmem_charge_fallback(struct page *page, struct mm_struct *mm, gfp_t gfp_mask); extern unsigned long mem_cgroup_isolate_pages(unsigned long nr_to_scan, @@ -155,7 +155,7 @@ static inline void mem_cgroup_uncharge_cache_page(struct page *page) { } -static inline int mem_cgroup_shrink_usage(struct page *page, +static inline int mem_cgroup_shmem_charge_fallback(struct page *page, struct mm_struct *mm, gfp_t gfp_mask) { return 0; diff --git a/include/linux/mman.h b/include/linux/mman.h index 30d1073bac3..9872d6ca58a 100644 --- a/include/linux/mman.h +++ b/include/linux/mman.h @@ -12,21 +12,18 @@ #ifdef __KERNEL__ #include <linux/mm.h> +#include <linux/percpu_counter.h> #include <asm/atomic.h> extern int sysctl_overcommit_memory; extern int sysctl_overcommit_ratio; -extern atomic_long_t vm_committed_space; +extern struct percpu_counter vm_committed_as; -#ifdef CONFIG_SMP -extern void vm_acct_memory(long pages); -#else static inline void vm_acct_memory(long pages) { - atomic_long_add(pages, &vm_committed_space); + percpu_counter_add(&vm_committed_as, pages); } -#endif static inline void vm_unacct_memory(long pages) { diff --git a/include/linux/namei.h b/include/linux/namei.h index fc2e0357987..518098fe63a 100644 --- a/include/linux/namei.h +++ b/include/linux/namei.h @@ -69,7 +69,6 @@ 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 int path_lookup_open(int dfd, const char *name, unsigned lookup_flags, struct nameidata *, int open_flags); extern struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry *dentry, int (*open)(struct inode *, struct file *)); extern struct file *nameidata_to_filp(struct nameidata *nd, int flags); diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 2e7783f4a75..5a96a1a406e 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -104,7 +104,7 @@ struct wireless_dev; # else # define LL_MAX_HEADER 96 # endif -#elif defined(CONFIG_TR) +#elif defined(CONFIG_TR) || defined(CONFIG_TR_MODULE) # define LL_MAX_HEADER 48 #else # define LL_MAX_HEADER 32 @@ -500,7 +500,7 @@ struct netdev_queue { * * int (*ndo_set_mac_address)(struct net_device *dev, void *addr); * This function is called when the Media Access Control address - * needs to be changed. If not this interface is not defined, the + * needs to be changed. If this interface is not defined, the * mac address can not be changed. * * int (*ndo_validate_addr)(struct net_device *dev); diff --git a/include/linux/netfilter/nfnetlink_conntrack.h b/include/linux/netfilter/nfnetlink_conntrack.h index 29fe9ea1d34..1a865e48b8e 100644 --- a/include/linux/netfilter/nfnetlink_conntrack.h +++ b/include/linux/netfilter/nfnetlink_conntrack.h @@ -100,6 +100,7 @@ enum ctattr_protoinfo_tcp { enum ctattr_protoinfo_dccp { CTA_PROTOINFO_DCCP_UNSPEC, CTA_PROTOINFO_DCCP_STATE, + CTA_PROTOINFO_DCCP_ROLE, __CTA_PROTOINFO_DCCP_MAX, }; #define CTA_PROTOINFO_DCCP_MAX (__CTA_PROTOINFO_DCCP_MAX - 1) diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h index 7b1a652066c..c9efe039dc5 100644 --- a/include/linux/netfilter/x_tables.h +++ b/include/linux/netfilter/x_tables.h @@ -354,9 +354,6 @@ struct xt_table /* What hooks you will enter on */ unsigned int valid_hooks; - /* Lock for the curtain */ - struct mutex lock; - /* Man behind the curtain... */ struct xt_table_info *private; @@ -434,8 +431,74 @@ extern void xt_proto_fini(struct net *net, u_int8_t af); extern struct xt_table_info *xt_alloc_table_info(unsigned int size); extern void xt_free_table_info(struct xt_table_info *info); -extern void xt_table_entry_swap_rcu(struct xt_table_info *old, - struct xt_table_info *new); + +/* + * Per-CPU spinlock associated with per-cpu table entries, and + * with a counter for the "reading" side that allows a recursive + * reader to avoid taking the lock and deadlocking. + * + * "reading" is used by ip/arp/ip6 tables rule processing which runs per-cpu. + * It needs to ensure that the rules are not being changed while the packet + * is being processed. In some cases, the read lock will be acquired + * twice on the same CPU; this is okay because of the count. + * + * "writing" is used when reading counters. + * During replace any readers that are using the old tables have to complete + * before freeing the old table. This is handled by the write locking + * necessary for reading the counters. + */ +struct xt_info_lock { + spinlock_t lock; + unsigned char readers; +}; +DECLARE_PER_CPU(struct xt_info_lock, xt_info_locks); + +/* + * Note: we need to ensure that preemption is disabled before acquiring + * the per-cpu-variable, so we do it as a two step process rather than + * using "spin_lock_bh()". + * + * We _also_ need to disable bottom half processing before updating our + * nesting count, to make sure that the only kind of re-entrancy is this + * code being called by itself: since the count+lock is not an atomic + * operation, we can allow no races. + * + * _Only_ that special combination of being per-cpu and never getting + * re-entered asynchronously means that the count is safe. + */ +static inline void xt_info_rdlock_bh(void) +{ + struct xt_info_lock *lock; + + local_bh_disable(); + lock = &__get_cpu_var(xt_info_locks); + if (likely(!lock->readers++)) + spin_lock(&lock->lock); +} + +static inline void xt_info_rdunlock_bh(void) +{ + struct xt_info_lock *lock = &__get_cpu_var(xt_info_locks); + + if (likely(!--lock->readers)) + spin_unlock(&lock->lock); + local_bh_enable(); +} + +/* + * The "writer" side needs to get exclusive access to the lock, + * regardless of readers. This must be called with bottom half + * processing (and thus also preemption) disabled. + */ +static inline void xt_info_wrlock(unsigned int cpu) +{ + spin_lock(&per_cpu(xt_info_locks, cpu).lock); +} + +static inline void xt_info_wrunlock(unsigned int cpu) +{ + spin_unlock(&per_cpu(xt_info_locks, cpu).lock); +} /* * This helper is performance critical and must be inlined diff --git a/include/linux/netfilter/xt_LED.h b/include/linux/netfilter/xt_LED.h index 4c91a0d770d..f5509e7524d 100644 --- a/include/linux/netfilter/xt_LED.h +++ b/include/linux/netfilter/xt_LED.h @@ -1,6 +1,8 @@ #ifndef _XT_LED_H #define _XT_LED_H +#include <linux/types.h> + struct xt_led_info { char id[27]; /* Unique ID for this trigger in the LED class */ __u8 always_blink; /* Blink even if the LED is already on */ diff --git a/include/linux/netfilter/xt_cluster.h b/include/linux/netfilter/xt_cluster.h index 5e0a0d07b52..886682656f0 100644 --- a/include/linux/netfilter/xt_cluster.h +++ b/include/linux/netfilter/xt_cluster.h @@ -12,4 +12,6 @@ struct xt_cluster_match_info { u_int32_t flags; }; +#define XT_CLUSTER_NODES_MAX 32 + #endif /* _XT_CLUSTER_MATCH_H */ diff --git a/include/linux/nls.h b/include/linux/nls.h index 6a882208301..52b1a76c1b4 100644 --- a/include/linux/nls.h +++ b/include/linux/nls.h @@ -58,6 +58,25 @@ static inline int nls_strnicmp(struct nls_table *t, const unsigned char *s1, return 0; } +/* + * nls_nullsize - return length of null character for codepage + * @codepage - codepage for which to return length of NULL terminator + * + * Since we can't guarantee that the null terminator will be a particular + * length, we have to check against the codepage. If there's a problem + * determining it, assume a single-byte NULL terminator. + */ +static inline int +nls_nullsize(const struct nls_table *codepage) +{ + int charlen; + char tmp[NLS_MAX_CHARSET_SIZE]; + + charlen = codepage->uni2char(0, tmp, NLS_MAX_CHARSET_SIZE); + + return charlen > 0 ? charlen : 1; +} + #define MODULE_ALIAS_NLS(name) MODULE_ALIAS("nls_" __stringify(name)) #endif /* _LINUX_NLS_H */ diff --git a/include/linux/of_platform.h b/include/linux/of_platform.h index 3d327b67d7e..90840665133 100644 --- a/include/linux/of_platform.h +++ b/include/linux/of_platform.h @@ -51,6 +51,16 @@ extern int of_register_driver(struct of_platform_driver *drv, struct bus_type *bus); extern void of_unregister_driver(struct of_platform_driver *drv); +/* Platform drivers register/unregister */ +static inline int of_register_platform_driver(struct of_platform_driver *drv) +{ + return of_register_driver(drv, &of_platform_bus_type); +} +static inline void of_unregister_platform_driver(struct of_platform_driver *drv) +{ + of_unregister_driver(drv); +} + #include <asm/of_platform.h> extern struct of_device *of_find_device_by_node(struct device_node *np); diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h index 72736fd8223..b67bb5d7b22 100644 --- a/include/linux/platform_device.h +++ b/include/linux/platform_device.h @@ -20,7 +20,6 @@ struct platform_device { struct device dev; u32 num_resources; struct resource * resource; - void *platform_data; struct platform_device_id *id_entry; }; diff --git a/include/linux/reiserfs_fs_sb.h b/include/linux/reiserfs_fs_sb.h index 6b361d23a49..6473650c28f 100644 --- a/include/linux/reiserfs_fs_sb.h +++ b/include/linux/reiserfs_fs_sb.h @@ -402,7 +402,7 @@ struct reiserfs_sb_info { int reserved_blocks; /* amount of blocks reserved for further allocations */ spinlock_t bitmap_lock; /* this lock on now only used to protect reserved_blocks variable */ struct dentry *priv_root; /* root of /.reiserfs_priv */ - struct dentry *xattr_root; /* root of /.reiserfs_priv/.xa */ + struct dentry *xattr_root; /* root of /.reiserfs_priv/xattrs */ int j_errno; #ifdef CONFIG_QUOTA char *s_qf_names[MAXQUOTAS]; @@ -488,7 +488,6 @@ enum reiserfs_mount_options { #define reiserfs_data_log(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_DATA_LOG)) #define reiserfs_data_ordered(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_DATA_ORDERED)) #define reiserfs_data_writeback(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_DATA_WRITEBACK)) -#define reiserfs_xattrs(s) ((s)->s_xattr != NULL) #define reiserfs_xattrs_user(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_XATTRS_USER)) #define reiserfs_posixacl(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_POSIXACL)) #define reiserfs_xattrs_optional(s) (reiserfs_xattrs_user(s) || reiserfs_posixacl(s)) diff --git a/include/linux/reiserfs_xattr.h b/include/linux/reiserfs_xattr.h index dcae01e63e4..cdedc01036e 100644 --- a/include/linux/reiserfs_xattr.h +++ b/include/linux/reiserfs_xattr.h @@ -38,6 +38,7 @@ struct nameidata; int reiserfs_xattr_register_handlers(void) __init; void reiserfs_xattr_unregister_handlers(void); int reiserfs_xattr_init(struct super_block *sb, int mount_flags); +int reiserfs_lookup_privroot(struct super_block *sb); int reiserfs_delete_xattrs(struct inode *inode); int reiserfs_chown_xattrs(struct inode *inode, struct iattr *attrs); @@ -97,7 +98,7 @@ static inline size_t reiserfs_xattr_jcreate_nblocks(struct inode *inode) if ((REISERFS_I(inode)->i_flags & i_has_xattr_dir) == 0) { nblocks += JOURNAL_BLOCKS_PER_OBJECT(inode->i_sb); - if (REISERFS_SB(inode->i_sb)->xattr_root == NULL) + if (!REISERFS_SB(inode->i_sb)->xattr_root->d_inode) nblocks += JOURNAL_BLOCKS_PER_OBJECT(inode->i_sb); } diff --git a/include/linux/romfs_fs.h b/include/linux/romfs_fs.h index e20bbf9eb36..c490fbc43fe 100644 --- a/include/linux/romfs_fs.h +++ b/include/linux/romfs_fs.h @@ -53,9 +53,4 @@ struct romfs_inode { #define ROMFH_PAD (ROMFH_SIZE-1) #define ROMFH_MASK (~ROMFH_PAD) -#ifdef __KERNEL__ - -/* Not much now */ - -#endif /* __KERNEL__ */ #endif diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h index 1758d9f5b5c..08afe43118f 100644 --- a/include/linux/sunrpc/xprt.h +++ b/include/linux/sunrpc/xprt.h @@ -261,6 +261,7 @@ void xprt_conditional_disconnect(struct rpc_xprt *xprt, unsigned int cookie); #define XPRT_BINDING (5) #define XPRT_CLOSING (6) #define XPRT_CONNECTION_ABORT (7) +#define XPRT_CONNECTION_CLOSE (8) static inline void xprt_set_connected(struct rpc_xprt *xprt) { diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index 40617c1d897..30520844b8d 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h @@ -433,6 +433,7 @@ asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg); asmlinkage long sys_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg); #endif +asmlinkage long sys_pipe2(int __user *fildes, int flags); asmlinkage long sys_dup(unsigned int fildes); asmlinkage long sys_dup2(unsigned int oldfd, unsigned int newfd); asmlinkage long sys_dup3(unsigned int oldfd, unsigned int newfd, int flags); diff --git a/include/linux/usb/cdc.h b/include/linux/usb/cdc.h index 3c86ed25a04..c24124a42ce 100644 --- a/include/linux/usb/cdc.h +++ b/include/linux/usb/cdc.h @@ -17,6 +17,7 @@ #define USB_CDC_SUBCLASS_DMM 0x09 #define USB_CDC_SUBCLASS_MDLM 0x0a #define USB_CDC_SUBCLASS_OBEX 0x0b +#define USB_CDC_SUBCLASS_EEM 0x0c #define USB_CDC_PROTO_NONE 0 @@ -28,6 +29,8 @@ #define USB_CDC_ACM_PROTO_AT_CDMA 6 #define USB_CDC_ACM_PROTO_VENDOR 0xff +#define USB_CDC_PROTO_EEM 7 + /*-------------------------------------------------------------------------*/ /* diff --git a/include/linux/virtio_net.h b/include/linux/virtio_net.h index 242348bb376..cec79adbe3e 100644 --- a/include/linux/virtio_net.h +++ b/include/linux/virtio_net.h @@ -4,6 +4,7 @@ * compatible drivers/servers. */ #include <linux/types.h> #include <linux/virtio_config.h> +#include <linux/if_ether.h> /* The ID for virtio_net */ #define VIRTIO_ID_NET 1 diff --git a/include/linux/wait.h b/include/linux/wait.h index 5d631c17eae..bc024632f36 100644 --- a/include/linux/wait.h +++ b/include/linux/wait.h @@ -440,13 +440,15 @@ void abort_exclusive_wait(wait_queue_head_t *q, wait_queue_t *wait, int autoremove_wake_function(wait_queue_t *wait, unsigned mode, int sync, void *key); int wake_bit_function(wait_queue_t *wait, unsigned mode, int sync, void *key); -#define DEFINE_WAIT(name) \ +#define DEFINE_WAIT_FUNC(name, function) \ wait_queue_t name = { \ .private = current, \ - .func = autoremove_wake_function, \ + .func = function, \ .task_list = LIST_HEAD_INIT((name).task_list), \ } +#define DEFINE_WAIT(name) DEFINE_WAIT_FUNC(name, autoremove_wake_function) + #define DEFINE_WAIT_BIT(name, word, bit) \ struct wait_bit_queue name = { \ .key = __WAIT_BIT_KEY_INITIALIZER(word, bit), \ diff --git a/include/net/9p/client.h b/include/net/9p/client.h index 4012e07162e..e26812274b7 100644 --- a/include/net/9p/client.h +++ b/include/net/9p/client.h @@ -98,7 +98,6 @@ enum p9_req_status_t { struct p9_req_t { int status; int t_err; - u16 flush_tag; wait_queue_head_t *wq; struct p9_fcall *tc; struct p9_fcall *rc; diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index f69f015bbcc..ed3aea1605e 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -101,6 +101,7 @@ enum { /* HCI timeouts */ #define HCI_CONNECT_TIMEOUT (40000) /* 40 seconds */ #define HCI_DISCONN_TIMEOUT (2000) /* 2 seconds */ +#define HCI_PAIRING_TIMEOUT (60000) /* 60 seconds */ #define HCI_IDLE_TIMEOUT (6000) /* 6 seconds */ #define HCI_INIT_TIMEOUT (10000) /* 10 seconds */ diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 01f9316b4c2..73aead222b3 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -171,6 +171,7 @@ struct hci_conn { __u8 auth_type; __u8 sec_level; __u8 power_save; + __u16 disc_timeout; unsigned long pend; unsigned int sent; @@ -180,7 +181,8 @@ struct hci_conn { struct timer_list disc_timer; struct timer_list idle_timer; - struct work_struct work; + struct work_struct work_add; + struct work_struct work_del; struct device dev; @@ -348,9 +350,9 @@ static inline void hci_conn_put(struct hci_conn *conn) if (conn->type == ACL_LINK) { del_timer(&conn->idle_timer); if (conn->state == BT_CONNECTED) { - timeo = msecs_to_jiffies(HCI_DISCONN_TIMEOUT); + timeo = msecs_to_jiffies(conn->disc_timeout); if (!conn->out) - timeo *= 5; + timeo *= 2; } else timeo = msecs_to_jiffies(10); } else @@ -455,6 +457,7 @@ int hci_recv_fragment(struct hci_dev *hdev, int type, void *data, int count); int hci_register_sysfs(struct hci_dev *hdev); void hci_unregister_sysfs(struct hci_dev *hdev); +void hci_conn_init_sysfs(struct hci_conn *conn); void hci_conn_add_sysfs(struct hci_conn *conn); void hci_conn_del_sysfs(struct hci_conn *conn); diff --git a/include/net/tcp.h b/include/net/tcp.h index 1b94b9bfe2d..646dbe3962e 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -41,6 +41,7 @@ #include <net/ip.h> #include <net/tcp_states.h> #include <net/inet_ecn.h> +#include <net/dst.h> #include <linux/seq_file.h> @@ -530,6 +531,17 @@ static inline void tcp_fast_path_check(struct sock *sk) tcp_fast_path_on(tp); } +/* Compute the actual rto_min value */ +static inline u32 tcp_rto_min(struct sock *sk) +{ + struct dst_entry *dst = __sk_dst_get(sk); + u32 rto_min = TCP_RTO_MIN; + + if (dst && dst_metric_locked(dst, RTAX_RTO_MIN)) + rto_min = dst_metric_rtt(dst, RTAX_RTO_MIN); + return rto_min; +} + /* Compute the actual receive window we are currently advertising. * Rcv_nxt can be after the window if our peer push more data * than the offered window. @@ -895,7 +907,7 @@ static inline int tcp_prequeue(struct sock *sk, struct sk_buff *skb) wake_up_interruptible(sk->sk_sleep); if (!inet_csk_ack_scheduled(sk)) inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK, - (3 * TCP_RTO_MIN) / 4, + (3 * tcp_rto_min(sk)) / 4, TCP_RTO_MAX); } return 1; diff --git a/include/scsi/fc/fc_fs.h b/include/scsi/fc/fc_fs.h index 1b7af3a64c7..ac4cd38c860 100644 --- a/include/scsi/fc/fc_fs.h +++ b/include/scsi/fc/fc_fs.h @@ -149,6 +149,7 @@ enum fc_rctl { * Well-known fabric addresses. */ enum fc_well_known_fid { + FC_FID_NONE = 0x000000, /* No destination */ FC_FID_BCAST = 0xffffff, /* broadcast */ FC_FID_FLOGI = 0xfffffe, /* fabric login */ FC_FID_FCTRL = 0xfffffd, /* fabric controller */ diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index 0303a6a098c..45f9cc642c4 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -637,6 +637,7 @@ struct fc_disc { enum fc_disc_event); struct list_head rports; + struct list_head rogue_rports; struct fc_lport *lport; struct mutex disc_mutex; struct fc_gpn_ft_resp partial_buf; /* partial name buffer */ diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h index 7ffaed2f94d..0289f5745fb 100644 --- a/include/scsi/libiscsi.h +++ b/include/scsi/libiscsi.h @@ -36,6 +36,7 @@ struct scsi_transport_template; struct scsi_host_template; struct scsi_device; struct Scsi_Host; +struct scsi_target; struct scsi_cmnd; struct socket; struct iscsi_transport; @@ -350,6 +351,7 @@ extern struct Scsi_Host *iscsi_host_alloc(struct scsi_host_template *sht, bool xmit_can_sleep); extern void iscsi_host_remove(struct Scsi_Host *shost); extern void iscsi_host_free(struct Scsi_Host *shost); +extern int iscsi_target_alloc(struct scsi_target *starget); /* * session management diff --git a/include/scsi/osd_protocol.h b/include/scsi/osd_protocol.h index cd3cbf76465..62b2ab8c69d 100644 --- a/include/scsi/osd_protocol.h +++ b/include/scsi/osd_protocol.h @@ -24,17 +24,18 @@ enum { OSDv1_ADDITIONAL_CDB_LENGTH = 192, OSDv1_TOTAL_CDB_LEN = OSDv1_ADDITIONAL_CDB_LENGTH + 8, OSDv1_CAP_LEN = 80, + /* Latest supported version */ -/* OSD_ADDITIONAL_CDB_LENGTH = 216,*/ + OSDv2_ADDITIONAL_CDB_LENGTH = 228, OSD_ADDITIONAL_CDB_LENGTH = - OSDv1_ADDITIONAL_CDB_LENGTH, /* FIXME: Pete rev-001 sup */ + OSDv2_ADDITIONAL_CDB_LENGTH, OSD_TOTAL_CDB_LEN = OSD_ADDITIONAL_CDB_LENGTH + 8, -/* OSD_CAP_LEN = 104,*/ - OSD_CAP_LEN = OSDv1_CAP_LEN,/* FIXME: Pete rev-001 sup */ + OSD_CAP_LEN = 104, OSD_SYSTEMID_LEN = 20, - OSD_CRYPTO_KEYID_SIZE = 20, - /*FIXME: OSDv2_CRYPTO_KEYID_SIZE = 32,*/ + OSDv1_CRYPTO_KEYID_SIZE = 20, + OSDv2_CRYPTO_KEYID_SIZE = 32, + OSD_CRYPTO_KEYID_SIZE = OSDv2_CRYPTO_KEYID_SIZE, OSD_CRYPTO_SEED_SIZE = 4, OSD_CRYPTO_NONCE_SIZE = 12, OSD_MAX_SENSE_LEN = 252, /* from SPC-3 */ @@ -164,7 +165,11 @@ struct osd_cdb_head { /* called allocation_length in some commands */ /*32*/ __be64 length; /*40*/ __be64 start_address; -/*48*/ __be32 list_identifier;/* Rarely used */ + union { +/*48*/ __be32 list_identifier;/* Rarely used */ + /* OSD2r05 5.2.5 CDB continuation length */ +/*48*/ __be32 cdb_continuation_length; + }; } __packed v2; }; /*52*/ union { /* selected attributes mode Page/List/Single */ @@ -204,29 +209,40 @@ struct osd_cdb_head { /*80*/ /*160 v1*/ -/*184 v2*/ -struct osd_security_parameters { -/*160*/u8 integrity_check_value[OSD_CRYPTO_KEYID_SIZE]; +struct osdv1_security_parameters { +/*160*/u8 integrity_check_value[OSDv1_CRYPTO_KEYID_SIZE]; /*180*/u8 request_nonce[OSD_CRYPTO_NONCE_SIZE]; /*192*/osd_cdb_offset data_in_integrity_check_offset; /*196*/osd_cdb_offset data_out_integrity_check_offset; } __packed; /*200 v1*/ -/*224 v2*/ -/* FIXME: osdv2_security_parameters */ +/*184 v2*/ +struct osdv2_security_parameters { +/*184*/u8 integrity_check_value[OSDv2_CRYPTO_KEYID_SIZE]; +/*216*/u8 request_nonce[OSD_CRYPTO_NONCE_SIZE]; +/*228*/osd_cdb_offset data_in_integrity_check_offset; +/*232*/osd_cdb_offset data_out_integrity_check_offset; +} __packed; +/*236 v2*/ + +struct osd_security_parameters { + union { + struct osdv1_security_parameters v1; + struct osdv2_security_parameters v2; + }; +}; struct osdv1_cdb { struct osd_cdb_head h; u8 caps[OSDv1_CAP_LEN]; - struct osd_security_parameters sec_params; + struct osdv1_security_parameters sec_params; } __packed; struct osdv2_cdb { struct osd_cdb_head h; u8 caps[OSD_CAP_LEN]; - struct osd_security_parameters sec_params; - /* FIXME: osdv2_security_parameters */ + struct osdv2_security_parameters sec_params; } __packed; struct osd_cdb { @@ -301,14 +317,25 @@ struct osd_attributes_list_attrid { } __packed; /* + * NOTE: v1: is not aligned. + */ +struct osdv1_attributes_list_element { + __be32 attr_page; + __be32 attr_id; + __be16 attr_bytes; /* valid bytes at attr_val without padding */ + u8 attr_val[0]; +} __packed; + +/* * osd2r03: 7.1.3.3 List entry format for retrieved attributes and * for setting attributes - * NOTE: v2 is 8-bytes aligned, v1 is not aligned. + * NOTE: v2 is 8-bytes aligned */ -struct osd_attributes_list_element { +struct osdv2_attributes_list_element { __be32 attr_page; __be32 attr_id; - __be16 attr_bytes; + u8 reserved[6]; + __be16 attr_bytes; /* valid bytes at attr_val without padding */ u8 attr_val[0]; } __packed; @@ -324,13 +351,13 @@ enum { static inline unsigned osdv1_attr_list_elem_size(unsigned len) { - return ALIGN(len + sizeof(struct osd_attributes_list_element), + return ALIGN(len + sizeof(struct osdv1_attributes_list_element), OSDv1_ATTRIBUTES_ELEM_ALIGN); } static inline unsigned osdv2_attr_list_elem_size(unsigned len) { - return ALIGN(len + sizeof(struct osd_attributes_list_element), + return ALIGN(len + sizeof(struct osdv2_attributes_list_element), OSD_ATTRIBUTES_ELEM_ALIGN); } @@ -419,15 +446,35 @@ struct osd_data_out_integrity_info { __be64 data_bytes; __be64 set_attributes_bytes; __be64 get_attributes_bytes; - __be64 integrity_check_value; + __u8 integrity_check_value[OSD_CRYPTO_KEYID_SIZE]; } __packed; +/* Same osd_data_out_integrity_info is used for OSD2/OSD1. The only difference + * Is the sizeof the structure since in OSD1 the last array is smaller. Use + * below for version independent handling of this structure + */ +static inline int osd_data_out_integrity_info_sizeof(bool is_ver1) +{ + return sizeof(struct osd_data_out_integrity_info) - + (is_ver1 * (OSDv2_CRYPTO_KEYID_SIZE - OSDv1_CRYPTO_KEYID_SIZE)); +} + struct osd_data_in_integrity_info { __be64 data_bytes; __be64 retrieved_attributes_bytes; - __be64 integrity_check_value; + __u8 integrity_check_value[OSD_CRYPTO_KEYID_SIZE]; } __packed; +/* Same osd_data_in_integrity_info is used for OSD2/OSD1. The only difference + * Is the sizeof the structure since in OSD1 the last array is smaller. Use + * below for version independent handling of this structure + */ +static inline int osd_data_in_integrity_info_sizeof(bool is_ver1) +{ + return sizeof(struct osd_data_in_integrity_info) - + (is_ver1 * (OSDv2_CRYPTO_KEYID_SIZE - OSDv1_CRYPTO_KEYID_SIZE)); +} + struct osd_timestamp { u8 time[6]; /* number of milliseconds since 1/1/1970 UT (big endian) */ } __packed; @@ -477,7 +524,7 @@ enum osd_capability_bit_masks { OSD_SEC_CAP_NONE1 = BIT(8), OSD_SEC_CAP_NONE2 = BIT(9), - OSD_SEC_CAP_NONE3 = BIT(10), + OSD_SEC_GBL_REM = BIT(10), /*v2 only*/ OSD_SEC_CAP_QUERY = BIT(11), /*v2 only*/ OSD_SEC_CAP_M_OBJECT = BIT(12), /*v2 only*/ OSD_SEC_CAP_POL_SEC = BIT(13), @@ -552,8 +599,7 @@ struct osdv1_capability { struct osd_capability { struct osd_capability_head h; -/* struct osd_cap_object_descriptor od;*/ - struct osdv1_cap_object_descriptor od; /* FIXME: Pete rev-001 sup */ + struct osd_cap_object_descriptor od; } __packed; /** diff --git a/include/sound/version.h b/include/sound/version.h index a7e74e23ad2..456f1359e1c 100644 --- a/include/sound/version.h +++ b/include/sound/version.h @@ -1,3 +1,3 @@ /* include/version.h */ -#define CONFIG_SND_VERSION "1.0.19" +#define CONFIG_SND_VERSION "1.0.20" #define CONFIG_SND_DATE "" diff --git a/init/initramfs.c b/init/initramfs.c index 9ee7b781041..4c00edc5968 100644 --- a/init/initramfs.c +++ b/init/initramfs.c @@ -574,11 +574,10 @@ static int __init populate_rootfs(void) if (initrd_start) { #ifdef CONFIG_BLK_DEV_RAM int fd; - printk(KERN_INFO "checking if image is initramfs...\n"); + printk(KERN_INFO "Trying to unpack rootfs image as initramfs...\n"); err = unpack_to_rootfs((char *)initrd_start, initrd_end - initrd_start); if (!err) { - printk(KERN_INFO "rootfs image is initramfs; unpacking...\n"); free_initrd(); return 0; } else { @@ -596,15 +595,11 @@ static int __init populate_rootfs(void) free_initrd(); } #else - printk(KERN_INFO "Unpacking initramfs..."); + printk(KERN_INFO "Unpacking initramfs...\n"); err = unpack_to_rootfs((char *)initrd_start, initrd_end - initrd_start); - if (err) { - printk(" failed!\n"); - printk(KERN_EMERG "%s\n", err); - } else { - printk(" done\n"); - } + if (err) + printk(KERN_EMERG "Initramfs unpacking failed: %s\n", err); free_initrd(); #endif } diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c index a6fe71fd5d1..713098ee5a0 100644 --- a/kernel/auditfilter.c +++ b/kernel/auditfilter.c @@ -1028,7 +1028,7 @@ static void audit_update_watch(struct audit_parent *parent, if (audit_enabled) { struct audit_buffer *ab; - ab = audit_log_start(NULL, GFP_KERNEL, + ab = audit_log_start(NULL, GFP_NOFS, AUDIT_CONFIG_CHANGE); audit_log_format(ab, "auid=%u ses=%u", audit_get_loginuid(current), @@ -1067,7 +1067,7 @@ static void audit_remove_parent_watches(struct audit_parent *parent) e = container_of(r, struct audit_entry, rule); if (audit_enabled) { struct audit_buffer *ab; - ab = audit_log_start(NULL, GFP_KERNEL, + ab = audit_log_start(NULL, GFP_NOFS, AUDIT_CONFIG_CHANGE); audit_log_format(ab, "auid=%u ses=%u", audit_get_loginuid(current), diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 382109b5bae..a7267bfd376 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -1133,8 +1133,7 @@ static int cgroup_get_sb(struct file_system_type *fs_type, free_cg_links: free_cg_links(&tmp_cg_links); drop_new_super: - up_write(&sb->s_umount); - deactivate_super(sb); + deactivate_locked_super(sb); return ret; } diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c index d82142be8dd..26e08754744 100644 --- a/kernel/irq/handle.c +++ b/kernel/irq/handle.c @@ -363,8 +363,6 @@ irqreturn_t handle_IRQ_event(unsigned int irq, struct irqaction *action) irqreturn_t ret, retval = IRQ_NONE; unsigned int status = 0; - WARN_ONCE(!in_irq(), "BUG: IRQ handler called from non-hardirq context!"); - if (!(action->flags & IRQF_DISABLED)) local_irq_enable_in_hardirq(); diff --git a/kernel/kprobes.c b/kernel/kprobes.c index a5e74ddee0e..c0fa54b276d 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c @@ -319,6 +319,22 @@ struct kprobe __kprobes *get_kprobe(void *addr) return NULL; } +/* Arm a kprobe with text_mutex */ +static void __kprobes arm_kprobe(struct kprobe *kp) +{ + mutex_lock(&text_mutex); + arch_arm_kprobe(kp); + mutex_unlock(&text_mutex); +} + +/* Disarm a kprobe with text_mutex */ +static void __kprobes disarm_kprobe(struct kprobe *kp) +{ + mutex_lock(&text_mutex); + arch_disarm_kprobe(kp); + mutex_unlock(&text_mutex); +} + /* * Aggregate handlers for multiple kprobes support - these handlers * take care of invoking the individual kprobe handlers on p->list @@ -538,7 +554,7 @@ static int __kprobes add_new_kprobe(struct kprobe *ap, struct kprobe *p) ap->flags &= ~KPROBE_FLAG_DISABLED; if (!kprobes_all_disarmed) /* Arm the breakpoint again. */ - arch_arm_kprobe(ap); + arm_kprobe(ap); } return 0; } @@ -789,11 +805,8 @@ static int __kprobes __unregister_kprobe_top(struct kprobe *p) * enabled and not gone - otherwise, the breakpoint would * already have been removed. We save on flushing icache. */ - if (!kprobes_all_disarmed && !kprobe_disabled(old_p)) { - mutex_lock(&text_mutex); - arch_disarm_kprobe(p); - mutex_unlock(&text_mutex); - } + if (!kprobes_all_disarmed && !kprobe_disabled(old_p)) + disarm_kprobe(p); hlist_del_rcu(&old_p->hlist); } else { if (p->break_handler && !kprobe_gone(p)) @@ -810,7 +823,7 @@ noclean: if (!kprobe_disabled(old_p)) { try_to_disable_aggr_kprobe(old_p); if (!kprobes_all_disarmed && kprobe_disabled(old_p)) - arch_disarm_kprobe(old_p); + disarm_kprobe(old_p); } } return 0; @@ -1364,7 +1377,7 @@ int __kprobes disable_kprobe(struct kprobe *kp) try_to_disable_aggr_kprobe(p); if (!kprobes_all_disarmed && kprobe_disabled(p)) - arch_disarm_kprobe(p); + disarm_kprobe(p); out: mutex_unlock(&kprobe_mutex); return ret; @@ -1393,7 +1406,7 @@ int __kprobes enable_kprobe(struct kprobe *kp) } if (!kprobes_all_disarmed && kprobe_disabled(p)) - arch_arm_kprobe(p); + arm_kprobe(p); p->flags &= ~KPROBE_FLAG_DISABLED; if (p != kp) diff --git a/kernel/panic.c b/kernel/panic.c index 3dcaa166135..874ecf1307a 100644 --- a/kernel/panic.c +++ b/kernel/panic.c @@ -340,7 +340,7 @@ void oops_exit(void) } #ifdef WANT_WARN_ON_SLOWPATH -void warn_slowpath(const char *file, int line, const char *fmt, ...) +void warn_slowpath_fmt(const char *file, int line, const char *fmt, ...) { va_list args; char function[KSYM_SYMBOL_LEN]; @@ -356,7 +356,7 @@ void warn_slowpath(const char *file, int line, const char *fmt, ...) if (board) printk(KERN_WARNING "Hardware name: %s\n", board); - if (fmt) { + if (*fmt) { va_start(args, fmt); vprintk(fmt, args); va_end(args); @@ -367,7 +367,14 @@ void warn_slowpath(const char *file, int line, const char *fmt, ...) print_oops_end_marker(); add_taint(TAINT_WARN); } -EXPORT_SYMBOL(warn_slowpath); +EXPORT_SYMBOL(warn_slowpath_fmt); + +void warn_slowpath_null(const char *file, int line) +{ + static const char *empty = ""; + warn_slowpath_fmt(file, line, empty); +} +EXPORT_SYMBOL(warn_slowpath_null); #endif #ifdef CONFIG_CC_STACKPROTECTOR diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c index c9dcf98b446..bece7c0b67b 100644 --- a/kernel/posix-cpu-timers.c +++ b/kernel/posix-cpu-timers.c @@ -1420,19 +1420,19 @@ void run_posix_cpu_timers(struct task_struct *tsk) * timer call will interfere. */ list_for_each_entry_safe(timer, next, &firing, it.cpu.entry) { - int firing; + int cpu_firing; + spin_lock(&timer->it_lock); list_del_init(&timer->it.cpu.entry); - firing = timer->it.cpu.firing; + cpu_firing = timer->it.cpu.firing; timer->it.cpu.firing = 0; /* * The firing flag is -1 if we collided with a reset * of the timer, which already reported this * almost-firing as an overrun. So don't generate an event. */ - if (likely(firing >= 0)) { + if (likely(cpu_firing >= 0)) cpu_timer_fire(timer); - } spin_unlock(&timer->it_lock); } } diff --git a/kernel/sched.c b/kernel/sched.c index b902e587a3a..26efa475bdc 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -4732,7 +4732,7 @@ void account_process_tick(struct task_struct *p, int user_tick) if (user_tick) account_user_time(p, one_jiffy, one_jiffy_scaled); - else if (p != rq->idle) + else if ((p != rq->idle) || (irq_count() != HARDIRQ_OFFSET)) account_system_time(p, HARDIRQ_OFFSET, one_jiffy, one_jiffy_scaled); else diff --git a/kernel/sysctl.c b/kernel/sysctl.c index e3d2c7dd59b..ea78fa101ad 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -103,6 +103,9 @@ static unsigned long one_ul = 1; static int one_hundred = 100; static int one_thousand = 1000; +/* this is needed for the proc_doulongvec_minmax of vm_dirty_bytes */ +static unsigned long dirty_bytes_min = 2 * PAGE_SIZE; + /* this is needed for the proc_dointvec_minmax for [fs_]overflow UID and GID */ static int maxolduid = 65535; static int minolduid; @@ -1006,7 +1009,7 @@ static struct ctl_table vm_table[] = { .mode = 0644, .proc_handler = &dirty_bytes_handler, .strategy = &sysctl_intvec, - .extra1 = &one_ul, + .extra1 = &dirty_bytes_min, }, { .procname = "dirty_writeback_centisecs", diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c index 21a5ca84951..83c4417b6a3 100644 --- a/kernel/time/tick-common.c +++ b/kernel/time/tick-common.c @@ -93,7 +93,17 @@ void tick_handle_periodic(struct clock_event_device *dev) for (;;) { if (!clockevents_program_event(dev, next, ktime_get())) return; - tick_periodic(cpu); + /* + * Have to be careful here. If we're in oneshot mode, + * before we call tick_periodic() in a loop, we need + * to be sure we're using a real hardware clocksource. + * Otherwise we could get trapped in an infinite + * loop, as the tick_periodic() increments jiffies, + * when then will increment time, posibly causing + * the loop to trigger again and again. + */ + if (timekeeping_valid_for_hres()) + tick_periodic(cpu); next = ktime_add(next, tick_period); } } diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 1ce5dc6372b..a884c09006c 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -3448,6 +3448,7 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos, if (!ref) break; + ref->ref = 1; ref->buffer = info->tr->buffer; ref->page = ring_buffer_alloc_read_page(ref->buffer); if (!ref->page) { diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 812c28207ba..6cdcf38f2da 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -891,7 +891,6 @@ config DYNAMIC_DEBUG default n depends on PRINTK depends on DEBUG_FS - select PRINTK_DEBUG help Compiles debug level messages into the kernel, which would not diff --git a/lib/dma-debug.c b/lib/dma-debug.c index d3da7edc034..69da09a085a 100644 --- a/lib/dma-debug.c +++ b/lib/dma-debug.c @@ -400,60 +400,9 @@ out_err: return -ENOMEM; } -static int device_dma_allocations(struct device *dev) -{ - struct dma_debug_entry *entry; - unsigned long flags; - int count = 0, i; - - for (i = 0; i < HASH_SIZE; ++i) { - spin_lock_irqsave(&dma_entry_hash[i].lock, flags); - list_for_each_entry(entry, &dma_entry_hash[i].list, list) { - if (entry->dev == dev) - count += 1; - } - spin_unlock_irqrestore(&dma_entry_hash[i].lock, flags); - } - - return count; -} - -static int dma_debug_device_change(struct notifier_block *nb, - unsigned long action, void *data) -{ - struct device *dev = data; - int count; - - - switch (action) { - case BUS_NOTIFY_UNBIND_DRIVER: - count = device_dma_allocations(dev); - if (count == 0) - break; - err_printk(dev, NULL, "DMA-API: device driver has pending " - "DMA allocations while released from device " - "[count=%d]\n", count); - break; - default: - break; - } - - return 0; -} - void dma_debug_add_bus(struct bus_type *bus) { - struct notifier_block *nb; - - nb = kzalloc(sizeof(struct notifier_block), GFP_KERNEL); - if (nb == NULL) { - printk(KERN_ERR "dma_debug_add_bus: out of memory\n"); - return; - } - - nb->notifier_call = dma_debug_device_change; - - bus_register_notifier(bus, nb); + /* FIXME: register notifier */ } /* diff --git a/mm/Kconfig b/mm/Kconfig index 57971d2ab84..c2b57d81e15 100644 --- a/mm/Kconfig +++ b/mm/Kconfig @@ -225,3 +225,31 @@ config HAVE_MLOCKED_PAGE_BIT config MMU_NOTIFIER bool + +config NOMMU_INITIAL_TRIM_EXCESS + int "Turn on mmap() excess space trimming before booting" + depends on !MMU + default 1 + help + The NOMMU mmap() frequently needs to allocate large contiguous chunks + of memory on which to store mappings, but it can only ask the system + allocator for chunks in 2^N*PAGE_SIZE amounts - which is frequently + more than it requires. To deal with this, mmap() is able to trim off + the excess and return it to the allocator. + + If trimming is enabled, the excess is trimmed off and returned to the + system allocator, which can cause extra fragmentation, particularly + if there are a lot of transient processes. + + If trimming is disabled, the excess is kept, but not used, which for + long-term mappings means that the space is wasted. + + Trimming can be dynamically controlled through a sysctl option + (/proc/sys/vm/nr_trim_pages) which specifies the minimum number of + excess pages there must be before trimming should occur, or zero if + no trimming is to occur. + + This option specifies the initial value of this option. The default + of 1 says that all excess pages should be trimmed. + + See Documentation/nommu-mmap.txt for more information. diff --git a/mm/memcontrol.c b/mm/memcontrol.c index e44fb0fbb80..01c2d8f1468 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -1024,9 +1024,7 @@ static struct mem_cgroup *try_get_mem_cgroup_from_swapcache(struct page *page) return NULL; pc = lookup_page_cgroup(page); - /* - * Used bit of swapcache is solid under page lock. - */ + lock_page_cgroup(pc); if (PageCgroupUsed(pc)) { mem = pc->mem_cgroup; if (mem && !css_tryget(&mem->css)) @@ -1040,6 +1038,7 @@ static struct mem_cgroup *try_get_mem_cgroup_from_swapcache(struct page *page) mem = NULL; rcu_read_unlock(); } + unlock_page_cgroup(pc); return mem; } @@ -1618,37 +1617,28 @@ void mem_cgroup_end_migration(struct mem_cgroup *mem, } /* - * A call to try to shrink memory usage under specified resource controller. - * This is typically used for page reclaiming for shmem for reducing side - * effect of page allocation from shmem, which is used by some mem_cgroup. + * A call to try to shrink memory usage on charge failure at shmem's swapin. + * Calling hierarchical_reclaim is not enough because we should update + * last_oom_jiffies to prevent pagefault_out_of_memory from invoking global OOM. + * Moreover considering hierarchy, we should reclaim from the mem_over_limit, + * not from the memcg which this page would be charged to. + * try_charge_swapin does all of these works properly. */ -int mem_cgroup_shrink_usage(struct page *page, +int mem_cgroup_shmem_charge_fallback(struct page *page, struct mm_struct *mm, gfp_t gfp_mask) { struct mem_cgroup *mem = NULL; - int progress = 0; - int retry = MEM_CGROUP_RECLAIM_RETRIES; + int ret; if (mem_cgroup_disabled()) return 0; - if (page) - mem = try_get_mem_cgroup_from_swapcache(page); - if (!mem && mm) - mem = try_get_mem_cgroup_from_mm(mm); - if (unlikely(!mem)) - return 0; - do { - progress = mem_cgroup_hierarchical_reclaim(mem, - gfp_mask, true, false); - progress += mem_cgroup_check_under_limit(mem); - } while (!progress && --retry); + ret = mem_cgroup_try_charge_swapin(mm, page, gfp_mask, &mem); + if (!ret) + mem_cgroup_cancel_charge_swapin(mem); /* it does !mem check */ - css_put(&mem->css); - if (!retry) - return -ENOMEM; - return 0; + return ret; } static DEFINE_MUTEX(set_limit_mutex); diff --git a/mm/memory.c b/mm/memory.c index cf6873e91c6..4126dd16778 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -1971,6 +1971,15 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct *vma, ret = tmp; goto unwritable_page; } + if (unlikely(!(tmp & VM_FAULT_LOCKED))) { + lock_page(old_page); + if (!old_page->mapping) { + ret = 0; /* retry the fault */ + unlock_page(old_page); + goto unwritable_page; + } + } else + VM_BUG_ON(!PageLocked(old_page)); /* * Since we dropped the lock we need to revalidate @@ -1980,9 +1989,11 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct *vma, */ page_table = pte_offset_map_lock(mm, pmd, address, &ptl); - page_cache_release(old_page); - if (!pte_same(*page_table, orig_pte)) + if (!pte_same(*page_table, orig_pte)) { + unlock_page(old_page); + page_cache_release(old_page); goto unlock; + } page_mkwrite = 1; } @@ -2094,9 +2105,6 @@ gotten: unlock: pte_unmap_unlock(page_table, ptl); if (dirty_page) { - if (vma->vm_file) - file_update_time(vma->vm_file); - /* * Yes, Virginia, this is actually required to prevent a race * with clear_page_dirty_for_io() from clearing the page dirty @@ -2105,16 +2113,41 @@ unlock: * * do_no_page is protected similarly. */ - wait_on_page_locked(dirty_page); - set_page_dirty_balance(dirty_page, page_mkwrite); + if (!page_mkwrite) { + wait_on_page_locked(dirty_page); + set_page_dirty_balance(dirty_page, page_mkwrite); + } put_page(dirty_page); + if (page_mkwrite) { + struct address_space *mapping = dirty_page->mapping; + + set_page_dirty(dirty_page); + unlock_page(dirty_page); + page_cache_release(dirty_page); + if (mapping) { + /* + * Some device drivers do not set page.mapping + * but still dirty their pages + */ + balance_dirty_pages_ratelimited(mapping); + } + } + + /* file_update_time outside page_lock */ + if (vma->vm_file) + file_update_time(vma->vm_file); } return ret; oom_free_new: page_cache_release(new_page); oom: - if (old_page) + if (old_page) { + if (page_mkwrite) { + unlock_page(old_page); + page_cache_release(old_page); + } page_cache_release(old_page); + } return VM_FAULT_OOM; unwritable_page: @@ -2458,8 +2491,7 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma, if (mem_cgroup_try_charge_swapin(mm, page, GFP_KERNEL, &ptr)) { ret = VM_FAULT_OOM; - unlock_page(page); - goto out; + goto out_page; } /* @@ -2521,6 +2553,7 @@ out: out_nomap: mem_cgroup_cancel_charge_swapin(ptr); pte_unmap_unlock(page_table, ptl); +out_page: unlock_page(page); page_cache_release(page); return ret; @@ -2664,27 +2697,22 @@ static int __do_fault(struct mm_struct *mm, struct vm_area_struct *vma, int tmp; unlock_page(page); - vmf.flags |= FAULT_FLAG_MKWRITE; + vmf.flags = FAULT_FLAG_WRITE|FAULT_FLAG_MKWRITE; tmp = vma->vm_ops->page_mkwrite(vma, &vmf); if (unlikely(tmp & (VM_FAULT_ERROR | VM_FAULT_NOPAGE))) { ret = tmp; - anon = 1; /* no anon but release vmf.page */ - goto out_unlocked; - } - lock_page(page); - /* - * XXX: this is not quite right (racy vs - * invalidate) to unlock and relock the page - * like this, however a better fix requires - * reworking page_mkwrite locking API, which - * is better done later. - */ - if (!page->mapping) { - ret = 0; - anon = 1; /* no anon but release vmf.page */ - goto out; + goto unwritable_page; } + if (unlikely(!(tmp & VM_FAULT_LOCKED))) { + lock_page(page); + if (!page->mapping) { + ret = 0; /* retry the fault */ + unlock_page(page); + goto unwritable_page; + } + } else + VM_BUG_ON(!PageLocked(page)); page_mkwrite = 1; } } @@ -2736,19 +2764,35 @@ static int __do_fault(struct mm_struct *mm, struct vm_area_struct *vma, pte_unmap_unlock(page_table, ptl); out: - unlock_page(vmf.page); -out_unlocked: - if (anon) - page_cache_release(vmf.page); - else if (dirty_page) { - if (vma->vm_file) - file_update_time(vma->vm_file); + if (dirty_page) { + struct address_space *mapping = page->mapping; - set_page_dirty_balance(dirty_page, page_mkwrite); + if (set_page_dirty(dirty_page)) + page_mkwrite = 1; + unlock_page(dirty_page); put_page(dirty_page); + if (page_mkwrite && mapping) { + /* + * Some device drivers do not set page.mapping but still + * dirty their pages + */ + balance_dirty_pages_ratelimited(mapping); + } + + /* file_update_time outside page_lock */ + if (vma->vm_file) + file_update_time(vma->vm_file); + } else { + unlock_page(vmf.page); + if (anon) + page_cache_release(vmf.page); } return ret; + +unwritable_page: + page_cache_release(page); + return ret; } static int do_linear_fault(struct mm_struct *mm, struct vm_area_struct *vma, diff --git a/mm/mmap.c b/mm/mmap.c index 3303d1ba8e8..6b7b1a95944 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -85,7 +85,7 @@ EXPORT_SYMBOL(vm_get_page_prot); int sysctl_overcommit_memory = OVERCOMMIT_GUESS; /* heuristic overcommit */ int sysctl_overcommit_ratio = 50; /* default is 50% */ int sysctl_max_map_count __read_mostly = DEFAULT_MAX_MAP_COUNT; -atomic_long_t vm_committed_space = ATOMIC_LONG_INIT(0); +struct percpu_counter vm_committed_as; /* * Check that a process has enough memory to allocate a new virtual @@ -179,11 +179,7 @@ int __vm_enough_memory(struct mm_struct *mm, long pages, int cap_sys_admin) if (mm) allowed -= mm->total_vm / 32; - /* - * cast `allowed' as a signed long because vm_committed_space - * sometimes has a negative value - */ - if (atomic_long_read(&vm_committed_space) < (long)allowed) + if (percpu_counter_read_positive(&vm_committed_as) < allowed) return 0; error: vm_unacct_memory(pages); @@ -2481,4 +2477,8 @@ void mm_drop_all_locks(struct mm_struct *mm) */ void __init mmap_init(void) { + int ret; + + ret = percpu_counter_init(&vm_committed_as, 0); + VM_BUG_ON(ret); } diff --git a/mm/nommu.c b/mm/nommu.c index 72eda4aee2c..b571ef70742 100644 --- a/mm/nommu.c +++ b/mm/nommu.c @@ -62,11 +62,11 @@ void *high_memory; struct page *mem_map; unsigned long max_mapnr; unsigned long num_physpages; -atomic_long_t vm_committed_space = ATOMIC_LONG_INIT(0); +struct percpu_counter vm_committed_as; int sysctl_overcommit_memory = OVERCOMMIT_GUESS; /* heuristic overcommit */ int sysctl_overcommit_ratio = 50; /* default is 50% */ int sysctl_max_map_count = DEFAULT_MAX_MAP_COUNT; -int sysctl_nr_trim_pages = 1; /* page trimming behaviour */ +int sysctl_nr_trim_pages = CONFIG_NOMMU_INITIAL_TRIM_EXCESS; int heap_stack_gap = 0; atomic_long_t mmap_pages_allocated; @@ -463,6 +463,10 @@ SYSCALL_DEFINE1(brk, unsigned long, brk) */ void __init mmap_init(void) { + int ret; + + ret = percpu_counter_init(&vm_committed_as, 0); + VM_BUG_ON(ret); vm_region_jar = KMEM_CACHE(vm_region, SLAB_PANIC); } @@ -511,8 +515,6 @@ static void add_nommu_region(struct vm_region *region) validate_nommu_regions(); - BUG_ON(region->vm_start & ~PAGE_MASK); - parent = NULL; p = &nommu_region_tree.rb_node; while (*p) { @@ -1847,12 +1849,9 @@ int __vm_enough_memory(struct mm_struct *mm, long pages, int cap_sys_admin) if (mm) allowed -= mm->total_vm / 32; - /* - * cast `allowed' as a signed long because vm_committed_space - * sometimes has a negative value - */ - if (atomic_long_read(&vm_committed_space) < (long)allowed) + if (percpu_counter_read_positive(&vm_committed_as) < allowed) return 0; + error: vm_unacct_memory(pages); diff --git a/mm/oom_kill.c b/mm/oom_kill.c index 2f3166e308d..92bcf1db16b 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c @@ -514,34 +514,32 @@ void clear_zonelist_oom(struct zonelist *zonelist, gfp_t gfp_mask) */ static void __out_of_memory(gfp_t gfp_mask, int order) { - if (sysctl_oom_kill_allocating_task) { - oom_kill_process(current, gfp_mask, order, 0, NULL, - "Out of memory (oom_kill_allocating_task)"); - - } else { - unsigned long points; - struct task_struct *p; - -retry: - /* - * Rambo mode: Shoot down a process and hope it solves whatever - * issues we may have. - */ - p = select_bad_process(&points, NULL); + struct task_struct *p; + unsigned long points; - if (PTR_ERR(p) == -1UL) + if (sysctl_oom_kill_allocating_task) + if (!oom_kill_process(current, gfp_mask, order, 0, NULL, + "Out of memory (oom_kill_allocating_task)")) return; +retry: + /* + * Rambo mode: Shoot down a process and hope it solves whatever + * issues we may have. + */ + p = select_bad_process(&points, NULL); - /* Found nothing?!?! Either we hang forever, or we panic. */ - if (!p) { - read_unlock(&tasklist_lock); - panic("Out of memory and no killable processes...\n"); - } + if (PTR_ERR(p) == -1UL) + return; - if (oom_kill_process(p, gfp_mask, order, points, NULL, - "Out of memory")) - goto retry; + /* Found nothing?!?! Either we hang forever, or we panic. */ + if (!p) { + read_unlock(&tasklist_lock); + panic("Out of memory and no killable processes...\n"); } + + if (oom_kill_process(p, gfp_mask, order, points, NULL, + "Out of memory")) + goto retry; } /* diff --git a/mm/page_alloc.c b/mm/page_alloc.c index e2f26991fff..fe753ecf2aa 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -2681,6 +2681,7 @@ static void __meminit zone_init_free_lists(struct zone *zone) static int zone_batchsize(struct zone *zone) { +#ifdef CONFIG_MMU int batch; /* @@ -2706,9 +2707,26 @@ static int zone_batchsize(struct zone *zone) * of pages of one half of the possible page colors * and the other with pages of the other colors. */ - batch = (1 << (fls(batch + batch/2)-1)) - 1; + batch = rounddown_pow_of_two(batch + batch/2) - 1; return batch; + +#else + /* The deferral and batching of frees should be suppressed under NOMMU + * conditions. + * + * The problem is that NOMMU needs to be able to allocate large chunks + * of contiguous memory as there's no hardware page translation to + * assemble apparent contiguous memory from discontiguous pages. + * + * Queueing large contiguous runs of pages for batching, however, + * causes the pages to actually be freed in smaller chunks. As there + * can be a significant delay between the individual batches being + * recycled, this leads to the once large chunks of space being + * fragmented and becoming unavailable for high-order allocations. + */ + return 0; +#endif } static void setup_pageset(struct per_cpu_pageset *p, unsigned long batch) diff --git a/mm/shmem.c b/mm/shmem.c index f9cb20ebb99..b25f95ce3db 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -1340,8 +1340,12 @@ repeat: shmem_swp_unmap(entry); spin_unlock(&info->lock); if (error == -ENOMEM) { - /* allow reclaim from this memory cgroup */ - error = mem_cgroup_shrink_usage(swappage, + /* + * reclaim from proper memory cgroup and + * call memcg's OOM if needed. + */ + error = mem_cgroup_shmem_charge_fallback( + swappage, current->mm, gfp); if (error) { diff --git a/mm/swap.c b/mm/swap.c index bede23ce64e..cb29ae5d33a 100644 --- a/mm/swap.c +++ b/mm/swap.c @@ -491,49 +491,6 @@ unsigned pagevec_lookup_tag(struct pagevec *pvec, struct address_space *mapping, EXPORT_SYMBOL(pagevec_lookup_tag); -#ifdef CONFIG_SMP -/* - * We tolerate a little inaccuracy to avoid ping-ponging the counter between - * CPUs - */ -#define ACCT_THRESHOLD max(16, NR_CPUS * 2) - -static DEFINE_PER_CPU(long, committed_space); - -void vm_acct_memory(long pages) -{ - long *local; - - preempt_disable(); - local = &__get_cpu_var(committed_space); - *local += pages; - if (*local > ACCT_THRESHOLD || *local < -ACCT_THRESHOLD) { - atomic_long_add(*local, &vm_committed_space); - *local = 0; - } - preempt_enable(); -} - -#ifdef CONFIG_HOTPLUG_CPU - -/* Drop the CPU's cached committed space back into the central pool. */ -static int cpu_swap_callback(struct notifier_block *nfb, - unsigned long action, - void *hcpu) -{ - long *committed; - - committed = &per_cpu(committed_space, (long)hcpu); - if (action == CPU_DEAD || action == CPU_DEAD_FROZEN) { - atomic_long_add(*committed, &vm_committed_space); - *committed = 0; - drain_cpu_pagevecs((long)hcpu); - } - return NOTIFY_OK; -} -#endif /* CONFIG_HOTPLUG_CPU */ -#endif /* CONFIG_SMP */ - /* * Perform any setup for the swap system */ @@ -554,7 +511,4 @@ void __init swap_setup(void) * Right now other parts of the system means that we * _really_ don't want to cluster much more */ -#ifdef CONFIG_HOTPLUG_CPU - hotcpu_notifier(cpu_swap_callback, 0); -#endif } diff --git a/mm/vmalloc.c b/mm/vmalloc.c index fab19876b4d..083716ea38c 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -402,6 +402,7 @@ overflow: printk(KERN_WARNING "vmap allocation for size %lu failed: " "use vmalloc=<size> to increase size.\n", size); + kfree(va); return ERR_PTR(-EBUSY); } diff --git a/mm/vmscan.c b/mm/vmscan.c index eac9577941f..5fa3eda1f03 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -1471,7 +1471,7 @@ static void shrink_zone(int priority, struct zone *zone, for_each_evictable_lru(l) { int file = is_file_lru(l); - int scan; + unsigned long scan; scan = zone_nr_pages(zone, sc, l); if (priority) { diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index 2b7390e377b..d1e10546eb8 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c @@ -492,6 +492,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event, continue; dev_change_flags(vlandev, flgs & ~IFF_UP); + vlan_transfer_operstate(dev, vlandev); } break; @@ -507,6 +508,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event, continue; dev_change_flags(vlandev, flgs | IFF_UP); + vlan_transfer_operstate(dev, vlandev); } break; diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index 6b092136401..b4b9068e55a 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c @@ -462,6 +462,7 @@ static int vlan_dev_open(struct net_device *dev) if (vlan->flags & VLAN_FLAG_GVRP) vlan_gvrp_request_join(dev); + netif_carrier_on(dev); return 0; clear_allmulti: @@ -471,6 +472,7 @@ del_unicast: if (compare_ether_addr(dev->dev_addr, real_dev->dev_addr)) dev_unicast_delete(real_dev, dev->dev_addr, ETH_ALEN); out: + netif_carrier_off(dev); return err; } @@ -492,6 +494,7 @@ static int vlan_dev_stop(struct net_device *dev) if (compare_ether_addr(dev->dev_addr, real_dev->dev_addr)) dev_unicast_delete(real_dev, dev->dev_addr, dev->addr_len); + netif_carrier_off(dev); return 0; } @@ -612,6 +615,8 @@ static int vlan_dev_init(struct net_device *dev) struct net_device *real_dev = vlan_dev_info(dev)->real_dev; int subclass = 0; + netif_carrier_off(dev); + /* IFF_BROADCAST|IFF_MULTICAST; ??? */ dev->flags = real_dev->flags & ~(IFF_UP | IFF_PROMISC | IFF_ALLMULTI); dev->iflink = real_dev->ifindex; diff --git a/net/9p/client.c b/net/9p/client.c index 1eb580c38fb..dd43a8289b0 100644 --- a/net/9p/client.c +++ b/net/9p/client.c @@ -203,7 +203,6 @@ static struct p9_req_t *p9_tag_alloc(struct p9_client *c, u16 tag) p9pdu_reset(req->tc); p9pdu_reset(req->rc); - req->flush_tag = 0; req->tc->tag = tag-1; req->status = REQ_STATUS_ALLOC; @@ -324,35 +323,9 @@ static void p9_free_req(struct p9_client *c, struct p9_req_t *r) */ void p9_client_cb(struct p9_client *c, struct p9_req_t *req) { - struct p9_req_t *other_req; - unsigned long flags; - P9_DPRINTK(P9_DEBUG_MUX, " tag %d\n", req->tc->tag); - - if (req->status == REQ_STATUS_ERROR) - wake_up(req->wq); - - if (req->flush_tag) { /* flush receive path */ - P9_DPRINTK(P9_DEBUG_9P, "<<< RFLUSH %d\n", req->tc->tag); - spin_lock_irqsave(&c->lock, flags); - other_req = p9_tag_lookup(c, req->flush_tag); - if (other_req->status != REQ_STATUS_FLSH) /* stale flush */ - spin_unlock_irqrestore(&c->lock, flags); - else { - other_req->status = REQ_STATUS_FLSHD; - spin_unlock_irqrestore(&c->lock, flags); - wake_up(other_req->wq); - } - p9_free_req(c, req); - } else { /* normal receive path */ - P9_DPRINTK(P9_DEBUG_MUX, "normal: tag %d\n", req->tc->tag); - spin_lock_irqsave(&c->lock, flags); - if (req->status != REQ_STATUS_FLSHD) - req->status = REQ_STATUS_RCVD; - spin_unlock_irqrestore(&c->lock, flags); - wake_up(req->wq); - P9_DPRINTK(P9_DEBUG_MUX, "wakeup: %d\n", req->tc->tag); - } + wake_up(req->wq); + P9_DPRINTK(P9_DEBUG_MUX, "wakeup: %d\n", req->tc->tag); } EXPORT_SYMBOL(p9_client_cb); @@ -486,9 +459,15 @@ static int p9_client_flush(struct p9_client *c, struct p9_req_t *oldreq) if (IS_ERR(req)) return PTR_ERR(req); - req->flush_tag = oldtag; - /* we don't free anything here because RPC isn't complete */ + /* if we haven't received a response for oldreq, + remove it from the list. */ + spin_lock(&c->lock); + if (oldreq->status == REQ_STATUS_FLSH) + list_del(&oldreq->req_list); + spin_unlock(&c->lock); + + p9_free_req(c, req); return 0; } @@ -509,7 +488,6 @@ p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...) struct p9_req_t *req; unsigned long flags; int sigpending; - int flushed = 0; P9_DPRINTK(P9_DEBUG_MUX, "client %p op %d\n", c, type); @@ -546,42 +524,28 @@ p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...) goto reterr; } - /* if it was a flush we just transmitted, return our tag */ - if (type == P9_TFLUSH) - return req; -again: P9_DPRINTK(P9_DEBUG_MUX, "wait %p tag: %d\n", req->wq, tag); err = wait_event_interruptible(*req->wq, req->status >= REQ_STATUS_RCVD); - P9_DPRINTK(P9_DEBUG_MUX, "wait %p tag: %d returned %d (flushed=%d)\n", - req->wq, tag, err, flushed); + P9_DPRINTK(P9_DEBUG_MUX, "wait %p tag: %d returned %d\n", + req->wq, tag, err); if (req->status == REQ_STATUS_ERROR) { P9_DPRINTK(P9_DEBUG_ERROR, "req_status error %d\n", req->t_err); err = req->t_err; - } else if (err == -ERESTARTSYS && flushed) { - P9_DPRINTK(P9_DEBUG_MUX, "flushed - going again\n"); - goto again; - } else if (req->status == REQ_STATUS_FLSHD) { - P9_DPRINTK(P9_DEBUG_MUX, "flushed - erestartsys\n"); - err = -ERESTARTSYS; } - if ((err == -ERESTARTSYS) && (c->status == Connected) && (!flushed)) { + if ((err == -ERESTARTSYS) && (c->status == Connected)) { P9_DPRINTK(P9_DEBUG_MUX, "flushing\n"); - spin_lock_irqsave(&c->lock, flags); - if (req->status == REQ_STATUS_SENT) - req->status = REQ_STATUS_FLSH; - spin_unlock_irqrestore(&c->lock, flags); sigpending = 1; - flushed = 1; clear_thread_flag(TIF_SIGPENDING); - if (c->trans_mod->cancel(c, req)) { - err = p9_client_flush(c, req); - if (err == 0) - goto again; - } + if (c->trans_mod->cancel(c, req)) + p9_client_flush(c, req); + + /* if we received the response anyway, don't signal error */ + if (req->status == REQ_STATUS_RCVD) + err = 0; } if (sigpending) { @@ -1244,19 +1208,53 @@ struct p9_wstat *p9_client_stat(struct p9_fid *fid) ret->name, ret->uid, ret->gid, ret->muid, ret->extension, ret->n_uid, ret->n_gid, ret->n_muid); + p9_free_req(clnt, req); + return ret; + free_and_error: p9_free_req(clnt, req); error: - return ret; + kfree(ret); + return ERR_PTR(err); } EXPORT_SYMBOL(p9_client_stat); +static int p9_client_statsize(struct p9_wstat *wst, int optional) +{ + int ret; + + /* size[2] type[2] dev[4] qid[13] */ + /* mode[4] atime[4] mtime[4] length[8]*/ + /* name[s] uid[s] gid[s] muid[s] */ + ret = 2+2+4+13+4+4+4+8+2+2+2+2; + + if (wst->name) + ret += strlen(wst->name); + if (wst->uid) + ret += strlen(wst->uid); + if (wst->gid) + ret += strlen(wst->gid); + if (wst->muid) + ret += strlen(wst->muid); + + if (optional) { + ret += 2+4+4+4; /* extension[s] n_uid[4] n_gid[4] n_muid[4] */ + if (wst->extension) + ret += strlen(wst->extension); + } + + return ret; +} + int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst) { int err; struct p9_req_t *req; struct p9_client *clnt; + err = 0; + clnt = fid->clnt; + wst->size = p9_client_statsize(wst, clnt->dotu); P9_DPRINTK(P9_DEBUG_9P, ">>> TWSTAT fid %d\n", fid->fid); P9_DPRINTK(P9_DEBUG_9P, " sz=%x type=%x dev=%x qid=%x.%llx.%x\n" @@ -1268,10 +1266,8 @@ int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst) wst->atime, wst->mtime, (unsigned long long)wst->length, wst->name, wst->uid, wst->gid, wst->muid, wst->extension, wst->n_uid, wst->n_gid, wst->n_muid); - err = 0; - clnt = fid->clnt; - req = p9_client_rpc(clnt, P9_TWSTAT, "dwS", fid->fid, 0, wst); + req = p9_client_rpc(clnt, P9_TWSTAT, "dwS", fid->fid, wst->size, wst); if (IS_ERR(req)) { err = PTR_ERR(req); goto error; diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c index c613ed08a5e..a2a1814c7a8 100644 --- a/net/9p/trans_fd.c +++ b/net/9p/trans_fd.c @@ -213,8 +213,8 @@ static void p9_conn_cancel(struct p9_conn *m, int err) spin_unlock_irqrestore(&m->client->lock, flags); list_for_each_entry_safe(req, rtmp, &cancel_list, req_list) { - list_del(&req->req_list); P9_DPRINTK(P9_DEBUG_ERROR, "call back req %p\n", req); + list_del(&req->req_list); p9_client_cb(m->client, req); } } @@ -336,7 +336,8 @@ static void p9_read_work(struct work_struct *work) "mux %p pkt: size: %d bytes tag: %d\n", m, n, tag); m->req = p9_tag_lookup(m->client, tag); - if (!m->req) { + if (!m->req || (m->req->status != REQ_STATUS_SENT && + m->req->status != REQ_STATUS_FLSH)) { P9_DPRINTK(P9_DEBUG_ERROR, "Unexpected packet tag %d\n", tag); err = -EIO; @@ -361,10 +362,11 @@ static void p9_read_work(struct work_struct *work) if ((m->req) && (m->rpos == m->rsize)) { /* packet is read in */ P9_DPRINTK(P9_DEBUG_TRANS, "got new packet\n"); spin_lock(&m->client->lock); + if (m->req->status != REQ_STATUS_ERROR) + m->req->status = REQ_STATUS_RCVD; list_del(&m->req->req_list); spin_unlock(&m->client->lock); p9_client_cb(m->client, m->req); - m->rbuf = NULL; m->rpos = 0; m->rsize = 0; @@ -454,6 +456,7 @@ static void p9_write_work(struct work_struct *work) req = list_entry(m->unsent_req_list.next, struct p9_req_t, req_list); req->status = REQ_STATUS_SENT; + P9_DPRINTK(P9_DEBUG_TRANS, "move req %p\n", req); list_move_tail(&req->req_list, &m->req_list); m->wbuf = req->tc->sdata; @@ -683,12 +686,13 @@ static int p9_fd_cancel(struct p9_client *client, struct p9_req_t *req) P9_DPRINTK(P9_DEBUG_TRANS, "client %p req %p\n", client, req); spin_lock(&client->lock); - list_del(&req->req_list); if (req->status == REQ_STATUS_UNSENT) { + list_del(&req->req_list); req->status = REQ_STATUS_FLSHD; ret = 0; - } + } else if (req->status == REQ_STATUS_SENT) + req->status = REQ_STATUS_FLSH; spin_unlock(&client->lock); diff --git a/net/9p/trans_rdma.c b/net/9p/trans_rdma.c index 7fa0eb20b2f..ac4990041eb 100644 --- a/net/9p/trans_rdma.c +++ b/net/9p/trans_rdma.c @@ -295,6 +295,7 @@ handle_recv(struct p9_client *client, struct p9_trans_rdma *rdma, goto err_out; req->rc = c->rc; + req->status = REQ_STATUS_RCVD; p9_client_cb(client, req); return; diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c index 2d7781ec663..bb8579a141a 100644 --- a/net/9p/trans_virtio.c +++ b/net/9p/trans_virtio.c @@ -134,6 +134,7 @@ static void req_done(struct virtqueue *vq) P9_DPRINTK(P9_DEBUG_TRANS, ": rc %p\n", rc); P9_DPRINTK(P9_DEBUG_TRANS, ": lookup tag %d\n", rc->tag); req = p9_tag_lookup(chan->client, rc->tag); + req->status = REQ_STATUS_RCVD; p9_client_cb(chan->client, req); } } diff --git a/net/Kconfig b/net/Kconfig index ce77db4fcec..c19f549c8e7 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -119,12 +119,6 @@ menuconfig NETFILTER <file:Documentation/Changes> under "iptables" for the location of these packages. - Make sure to say N to "Fast switching" below if you intend to say Y - here, as Fast switching currently bypasses netfilter. - - Chances are that you should say Y here if you compile a kernel which - will run as a router and N for regular hosts. If unsure, say N. - if NETFILTER config NETFILTER_DEBUG diff --git a/net/atm/br2684.c b/net/atm/br2684.c index 334fcd4a4ea..3100a8940af 100644 --- a/net/atm/br2684.c +++ b/net/atm/br2684.c @@ -549,6 +549,7 @@ static void br2684_setup(struct net_device *netdev) struct br2684_dev *brdev = BRPRIV(netdev); ether_setup(netdev); + brdev->net_dev = netdev; netdev->netdev_ops = &br2684_netdev_ops; diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 1181db08d9d..61309b26f27 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -215,6 +215,7 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst) conn->state = BT_OPEN; conn->power_save = 1; + conn->disc_timeout = HCI_DISCONN_TIMEOUT; switch (type) { case ACL_LINK: @@ -247,6 +248,8 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst) if (hdev->notify) hdev->notify(hdev, HCI_NOTIFY_CONN_ADD); + hci_conn_init_sysfs(conn); + tasklet_enable(&hdev->tx_task); return conn; @@ -424,12 +427,9 @@ int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type) if (sec_level == BT_SECURITY_SDP) return 1; - if (sec_level == BT_SECURITY_LOW) { - if (conn->ssp_mode > 0 && conn->hdev->ssp_mode > 0) - return hci_conn_auth(conn, sec_level, auth_type); - else - return 1; - } + if (sec_level == BT_SECURITY_LOW && + (!conn->ssp_mode || !conn->hdev->ssp_mode)) + return 1; if (conn->link_mode & HCI_LM_ENCRYPT) return hci_conn_auth(conn, sec_level, auth_type); diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 15f40ea8d54..4e7cb88e5da 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -883,6 +883,7 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s if (conn->type == ACL_LINK) { conn->state = BT_CONFIG; hci_conn_hold(conn); + conn->disc_timeout = HCI_DISCONN_TIMEOUT; } else conn->state = BT_CONNECTED; @@ -1063,9 +1064,14 @@ static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *s hci_proto_connect_cfm(conn, ev->status); hci_conn_put(conn); } - } else + } else { hci_auth_cfm(conn, ev->status); + hci_conn_hold(conn); + conn->disc_timeout = HCI_DISCONN_TIMEOUT; + hci_conn_put(conn); + } + if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) { if (!ev->status) { struct hci_cp_set_conn_encrypt cp; @@ -1479,7 +1485,21 @@ static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb) { + struct hci_ev_pin_code_req *ev = (void *) skb->data; + struct hci_conn *conn; + BT_DBG("%s", hdev->name); + + hci_dev_lock(hdev); + + conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); + if (conn) { + hci_conn_hold(conn); + conn->disc_timeout = HCI_PAIRING_TIMEOUT; + hci_conn_put(conn); + } + + hci_dev_unlock(hdev); } static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb) @@ -1489,7 +1509,21 @@ static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) { + struct hci_ev_link_key_notify *ev = (void *) skb->data; + struct hci_conn *conn; + BT_DBG("%s", hdev->name); + + hci_dev_lock(hdev); + + conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); + if (conn) { + hci_conn_hold(conn); + conn->disc_timeout = HCI_DISCONN_TIMEOUT; + hci_conn_put(conn); + } + + hci_dev_unlock(hdev); } static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb) diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c index ed82796d4a0..a05d45eb3ba 100644 --- a/net/bluetooth/hci_sysfs.c +++ b/net/bluetooth/hci_sysfs.c @@ -9,8 +9,7 @@ struct class *bt_class = NULL; EXPORT_SYMBOL_GPL(bt_class); -static struct workqueue_struct *btaddconn; -static struct workqueue_struct *btdelconn; +static struct workqueue_struct *bt_workq; static inline char *link_typetostr(int type) { @@ -88,9 +87,13 @@ static struct device_type bt_link = { static void add_conn(struct work_struct *work) { - struct hci_conn *conn = container_of(work, struct hci_conn, work); + struct hci_conn *conn = container_of(work, struct hci_conn, work_add); + struct hci_dev *hdev = conn->hdev; + + /* ensure previous del is complete */ + flush_work(&conn->work_del); - flush_workqueue(btdelconn); + dev_set_name(&conn->dev, "%s:%d", hdev->name, conn->handle); if (device_add(&conn->dev) < 0) { BT_ERR("Failed to register connection device"); @@ -98,27 +101,6 @@ static void add_conn(struct work_struct *work) } } -void hci_conn_add_sysfs(struct hci_conn *conn) -{ - struct hci_dev *hdev = conn->hdev; - - BT_DBG("conn %p", conn); - - conn->dev.type = &bt_link; - conn->dev.class = bt_class; - conn->dev.parent = &hdev->dev; - - dev_set_name(&conn->dev, "%s:%d", hdev->name, conn->handle); - - dev_set_drvdata(&conn->dev, conn); - - device_initialize(&conn->dev); - - INIT_WORK(&conn->work, add_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, @@ -131,9 +113,15 @@ static int __match_tty(struct device *dev, void *data) static void del_conn(struct work_struct *work) { - struct hci_conn *conn = container_of(work, struct hci_conn, work); + struct hci_conn *conn = container_of(work, struct hci_conn, work_del); struct hci_dev *hdev = conn->hdev; + /* ensure previous add is complete */ + flush_work(&conn->work_add); + + if (!device_is_registered(&conn->dev)) + return; + while (1) { struct device *dev; @@ -149,16 +137,36 @@ static void del_conn(struct work_struct *work) hci_dev_put(hdev); } -void hci_conn_del_sysfs(struct hci_conn *conn) +void hci_conn_init_sysfs(struct hci_conn *conn) { + struct hci_dev *hdev = conn->hdev; + BT_DBG("conn %p", conn); - if (!device_is_registered(&conn->dev)) - return; + conn->dev.type = &bt_link; + conn->dev.class = bt_class; + conn->dev.parent = &hdev->dev; + + dev_set_drvdata(&conn->dev, conn); + + device_initialize(&conn->dev); + + INIT_WORK(&conn->work_add, add_conn); + INIT_WORK(&conn->work_del, del_conn); +} - INIT_WORK(&conn->work, del_conn); +void hci_conn_add_sysfs(struct hci_conn *conn) +{ + BT_DBG("conn %p", conn); - queue_work(btdelconn, &conn->work); + queue_work(bt_workq, &conn->work_add); +} + +void hci_conn_del_sysfs(struct hci_conn *conn) +{ + BT_DBG("conn %p", conn); + + queue_work(bt_workq, &conn->work_del); } static inline char *host_typetostr(int type) @@ -435,20 +443,13 @@ void hci_unregister_sysfs(struct hci_dev *hdev) int __init bt_sysfs_init(void) { - btaddconn = create_singlethread_workqueue("btaddconn"); - if (!btaddconn) + bt_workq = create_singlethread_workqueue("bluetooth"); + if (!bt_workq) return -ENOMEM; - btdelconn = create_singlethread_workqueue("btdelconn"); - if (!btdelconn) { - destroy_workqueue(btaddconn); - return -ENOMEM; - } - bt_class = class_create(THIS_MODULE, "bluetooth"); if (IS_ERR(bt_class)) { - destroy_workqueue(btdelconn); - destroy_workqueue(btaddconn); + destroy_workqueue(bt_workq); return PTR_ERR(bt_class); } @@ -457,8 +458,7 @@ int __init bt_sysfs_init(void) void bt_sysfs_cleanup(void) { - destroy_workqueue(btaddconn); - destroy_workqueue(btdelconn); + destroy_workqueue(bt_workq); class_destroy(bt_class); } diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index 3953ac4214c..e4a418fcb35 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c @@ -788,15 +788,23 @@ static unsigned int br_nf_local_out(unsigned int hook, struct sk_buff *skb, return NF_STOLEN; } +#if defined(CONFIG_NF_CONNTRACK_IPV4) || defined(CONFIG_NF_CONNTRACK_IPV4_MODULE) static int br_nf_dev_queue_xmit(struct sk_buff *skb) { - if (skb->protocol == htons(ETH_P_IP) && + if (skb->nfct != NULL && + (skb->protocol == htons(ETH_P_IP) || IS_VLAN_IP(skb)) && skb->len > skb->dev->mtu && !skb_is_gso(skb)) return ip_fragment(skb, br_dev_queue_push_xmit); else return br_dev_queue_push_xmit(skb); } +#else +static int br_nf_dev_queue_xmit(struct sk_buff *skb) +{ + return br_dev_queue_push_xmit(skb); +} +#endif /* PF_BRIDGE/POST_ROUTING ********************************************/ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff *skb, diff --git a/net/core/datagram.c b/net/core/datagram.c index d0de644b378..b01a76abe1d 100644 --- a/net/core/datagram.c +++ b/net/core/datagram.c @@ -64,13 +64,25 @@ static inline int connection_based(struct sock *sk) return sk->sk_type == SOCK_SEQPACKET || sk->sk_type == SOCK_STREAM; } +static int receiver_wake_function(wait_queue_t *wait, unsigned mode, int sync, + void *key) +{ + unsigned long bits = (unsigned long)key; + + /* + * Avoid a wakeup if event not interesting for us + */ + if (bits && !(bits & (POLLIN | POLLERR))) + return 0; + return autoremove_wake_function(wait, mode, sync, key); +} /* * Wait for a packet.. */ static int wait_for_packet(struct sock *sk, int *err, long *timeo_p) { int error; - DEFINE_WAIT(wait); + DEFINE_WAIT_FUNC(wait, receiver_wake_function); prepare_to_wait_exclusive(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); diff --git a/net/core/dev.c b/net/core/dev.c index 308a7d0c277..e2e9e4af3ac 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1735,11 +1735,12 @@ u16 skb_tx_hash(const struct net_device *dev, const struct sk_buff *skb) { u32 hash; - if (skb_rx_queue_recorded(skb)) { - hash = skb_get_rx_queue(skb); - } else if (skb->sk && skb->sk->sk_hash) { + if (skb_rx_queue_recorded(skb)) + return skb_get_rx_queue(skb) % dev->real_num_tx_queues; + + if (skb->sk && skb->sk->sk_hash) hash = skb->sk->sk_hash; - } else + else hash = skb->protocol; hash = jhash_1word(hash, skb_tx_hashrnd); diff --git a/net/core/skbuff.c b/net/core/skbuff.c index ce6356cd9f7..d152394b261 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -502,7 +502,9 @@ int skb_recycle_check(struct sk_buff *skb, int skb_size) shinfo->gso_segs = 0; shinfo->gso_type = 0; shinfo->ip6_frag_id = 0; + shinfo->tx_flags.flags = 0; shinfo->frag_list = NULL; + memset(&shinfo->hwtstamps, 0, sizeof(shinfo->hwtstamps)); memset(skb, 0, offsetof(struct sk_buff, tail)); skb->data = skb->head + NET_SKB_PAD; @@ -1365,9 +1367,8 @@ static void sock_spd_release(struct splice_pipe_desc *spd, unsigned int i) static inline struct page *linear_to_page(struct page *page, unsigned int *len, unsigned int *offset, - struct sk_buff *skb) + struct sk_buff *skb, struct sock *sk) { - struct sock *sk = skb->sk; struct page *p = sk->sk_sndmsg_page; unsigned int off; @@ -1405,13 +1406,14 @@ new_page: */ static inline int spd_fill_page(struct splice_pipe_desc *spd, struct page *page, unsigned int *len, unsigned int offset, - struct sk_buff *skb, int linear) + struct sk_buff *skb, int linear, + struct sock *sk) { if (unlikely(spd->nr_pages == PIPE_BUFFERS)) return 1; if (linear) { - page = linear_to_page(page, len, &offset, skb); + page = linear_to_page(page, len, &offset, skb, sk); if (!page) return 1; } else @@ -1442,7 +1444,8 @@ static inline void __segment_seek(struct page **page, unsigned int *poff, static inline int __splice_segment(struct page *page, unsigned int poff, unsigned int plen, unsigned int *off, unsigned int *len, struct sk_buff *skb, - struct splice_pipe_desc *spd, int linear) + struct splice_pipe_desc *spd, int linear, + struct sock *sk) { if (!*len) return 1; @@ -1465,7 +1468,7 @@ static inline int __splice_segment(struct page *page, unsigned int poff, /* the linear region may spread across several pages */ flen = min_t(unsigned int, flen, PAGE_SIZE - poff); - if (spd_fill_page(spd, page, &flen, poff, skb, linear)) + if (spd_fill_page(spd, page, &flen, poff, skb, linear, sk)) return 1; __segment_seek(&page, &poff, &plen, flen); @@ -1481,8 +1484,8 @@ static inline int __splice_segment(struct page *page, unsigned int poff, * pipe is full or if we already spliced the requested length. */ static int __skb_splice_bits(struct sk_buff *skb, unsigned int *offset, - unsigned int *len, - struct splice_pipe_desc *spd) + unsigned int *len, struct splice_pipe_desc *spd, + struct sock *sk) { int seg; @@ -1492,7 +1495,7 @@ static int __skb_splice_bits(struct sk_buff *skb, unsigned int *offset, if (__splice_segment(virt_to_page(skb->data), (unsigned long) skb->data & (PAGE_SIZE - 1), skb_headlen(skb), - offset, len, skb, spd, 1)) + offset, len, skb, spd, 1, sk)) return 1; /* @@ -1502,7 +1505,7 @@ static int __skb_splice_bits(struct sk_buff *skb, unsigned int *offset, const skb_frag_t *f = &skb_shinfo(skb)->frags[seg]; if (__splice_segment(f->page, f->page_offset, f->size, - offset, len, skb, spd, 0)) + offset, len, skb, spd, 0, sk)) return 1; } @@ -1528,12 +1531,13 @@ int skb_splice_bits(struct sk_buff *skb, unsigned int offset, .ops = &sock_pipe_buf_ops, .spd_release = sock_spd_release, }; + struct sock *sk = skb->sk; /* * __skb_splice_bits() only fails if the output has no room left, * so no point in going over the frag_list for the error case. */ - if (__skb_splice_bits(skb, &offset, &tlen, &spd)) + if (__skb_splice_bits(skb, &offset, &tlen, &spd, sk)) goto done; else if (!tlen) goto done; @@ -1545,14 +1549,13 @@ int skb_splice_bits(struct sk_buff *skb, unsigned int offset, struct sk_buff *list = skb_shinfo(skb)->frag_list; for (; list && tlen; list = list->next) { - if (__skb_splice_bits(list, &offset, &tlen, &spd)) + if (__skb_splice_bits(list, &offset, &tlen, &spd, sk)) break; } } done: if (spd.nr_pages) { - struct sock *sk = skb->sk; int ret; /* diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig index b2cf91e4cca..9d26a3da37e 100644 --- a/net/ipv4/Kconfig +++ b/net/ipv4/Kconfig @@ -407,7 +407,7 @@ config INET_XFRM_MODE_BEET If unsure, say Y. config INET_LRO - tristate "Large Receive Offload (ipv4/tcp)" + bool "Large Receive Offload (ipv4/tcp)" ---help--- Support for Large Receive Offload (ipv4/tcp). diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index 5ba533d234d..831fe1879dc 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c @@ -253,9 +253,9 @@ unsigned int arpt_do_table(struct sk_buff *skb, indev = in ? in->name : nulldevname; outdev = out ? out->name : nulldevname; - rcu_read_lock_bh(); - private = rcu_dereference(table->private); - table_base = rcu_dereference(private->entries[smp_processor_id()]); + xt_info_rdlock_bh(); + private = table->private; + table_base = private->entries[smp_processor_id()]; e = get_entry(table_base, private->hook_entry[hook]); back = get_entry(table_base, private->underflow[hook]); @@ -273,6 +273,7 @@ unsigned int arpt_do_table(struct sk_buff *skb, hdr_len = sizeof(*arp) + (2 * sizeof(struct in_addr)) + (2 * skb->dev->addr_len); + ADD_COUNTER(e->counters, hdr_len, 1); t = arpt_get_target(e); @@ -328,8 +329,7 @@ unsigned int arpt_do_table(struct sk_buff *skb, e = (void *)e + e->next_offset; } } while (!hotdrop); - - rcu_read_unlock_bh(); + xt_info_rdunlock_bh(); if (hotdrop) return NF_DROP; @@ -711,9 +711,12 @@ static void get_counters(const struct xt_table_info *t, /* Instead of clearing (by a previous call to memset()) * the counters and using adds, we set the counters * with data used by 'current' CPU - * We dont care about preemption here. + * + * Bottom half has to be disabled to prevent deadlock + * if new softirq were to run and call ipt_do_table */ - curcpu = raw_smp_processor_id(); + local_bh_disable(); + curcpu = smp_processor_id(); i = 0; ARPT_ENTRY_ITERATE(t->entries[curcpu], @@ -726,73 +729,22 @@ static void get_counters(const struct xt_table_info *t, if (cpu == curcpu) continue; i = 0; + xt_info_wrlock(cpu); ARPT_ENTRY_ITERATE(t->entries[cpu], t->size, add_entry_to_counter, counters, &i); + xt_info_wrunlock(cpu); } -} - - -/* We're lazy, and add to the first CPU; overflow works its fey magic - * and everything is OK. */ -static int -add_counter_to_entry(struct arpt_entry *e, - const struct xt_counters addme[], - unsigned int *i) -{ - ADD_COUNTER(e->counters, addme[*i].bcnt, addme[*i].pcnt); - - (*i)++; - return 0; -} - -/* Take values from counters and add them back onto the current cpu */ -static void put_counters(struct xt_table_info *t, - const struct xt_counters counters[]) -{ - unsigned int i, cpu; - - local_bh_disable(); - cpu = smp_processor_id(); - i = 0; - ARPT_ENTRY_ITERATE(t->entries[cpu], - t->size, - add_counter_to_entry, - counters, - &i); local_bh_enable(); } -static inline int -zero_entry_counter(struct arpt_entry *e, void *arg) -{ - e->counters.bcnt = 0; - e->counters.pcnt = 0; - return 0; -} - -static void -clone_counters(struct xt_table_info *newinfo, const struct xt_table_info *info) -{ - unsigned int cpu; - const void *loc_cpu_entry = info->entries[raw_smp_processor_id()]; - - memcpy(newinfo, info, offsetof(struct xt_table_info, entries)); - for_each_possible_cpu(cpu) { - memcpy(newinfo->entries[cpu], loc_cpu_entry, info->size); - ARPT_ENTRY_ITERATE(newinfo->entries[cpu], newinfo->size, - zero_entry_counter, NULL); - } -} - static struct xt_counters *alloc_counters(struct xt_table *table) { unsigned int countersize; struct xt_counters *counters; struct xt_table_info *private = table->private; - struct xt_table_info *info; /* We need atomic snapshot of counters: rest doesn't change * (other than comefrom, which userspace doesn't care @@ -802,30 +754,11 @@ static struct xt_counters *alloc_counters(struct xt_table *table) counters = vmalloc_node(countersize, numa_node_id()); if (counters == NULL) - goto nomem; - - info = xt_alloc_table_info(private->size); - if (!info) - goto free_counters; - - clone_counters(info, private); - - mutex_lock(&table->lock); - xt_table_entry_swap_rcu(private, info); - synchronize_net(); /* Wait until smoke has cleared */ + return ERR_PTR(-ENOMEM); - get_counters(info, counters); - put_counters(private, counters); - mutex_unlock(&table->lock); - - xt_free_table_info(info); + get_counters(private, counters); return counters; - - free_counters: - vfree(counters); - nomem: - return ERR_PTR(-ENOMEM); } static int copy_entries_to_user(unsigned int total_size, @@ -1094,8 +1027,9 @@ static int __do_replace(struct net *net, const char *name, (newinfo->number <= oldinfo->initial_entries)) module_put(t->me); - /* Get the old counters. */ + /* Get the old counters, and synchronize with replace */ get_counters(oldinfo, counters); + /* Decrease module usage counts and free resource */ loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()]; ARPT_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry, @@ -1165,10 +1099,23 @@ static int do_replace(struct net *net, void __user *user, unsigned int len) return ret; } +/* We're lazy, and add to the first CPU; overflow works its fey magic + * and everything is OK. */ +static int +add_counter_to_entry(struct arpt_entry *e, + const struct xt_counters addme[], + unsigned int *i) +{ + ADD_COUNTER(e->counters, addme[*i].bcnt, addme[*i].pcnt); + + (*i)++; + return 0; +} + static int do_add_counters(struct net *net, void __user *user, unsigned int len, int compat) { - unsigned int i; + unsigned int i, curcpu; struct xt_counters_info tmp; struct xt_counters *paddc; unsigned int num_counters; @@ -1224,26 +1171,26 @@ static int do_add_counters(struct net *net, void __user *user, unsigned int len, goto free; } - mutex_lock(&t->lock); + local_bh_disable(); private = t->private; if (private->number != num_counters) { ret = -EINVAL; goto unlock_up_free; } - preempt_disable(); i = 0; /* Choose the copy that is on our node */ - loc_cpu_entry = private->entries[smp_processor_id()]; + curcpu = smp_processor_id(); + loc_cpu_entry = private->entries[curcpu]; + xt_info_wrlock(curcpu); ARPT_ENTRY_ITERATE(loc_cpu_entry, private->size, add_counter_to_entry, paddc, &i); - preempt_enable(); + xt_info_wrunlock(curcpu); unlock_up_free: - mutex_unlock(&t->lock); - + local_bh_enable(); xt_table_unlock(t); module_put(t->me); free: diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index 810c0b62c7d..2ec8d7290c4 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -338,10 +338,9 @@ ipt_do_table(struct sk_buff *skb, tgpar.hooknum = hook; IP_NF_ASSERT(table->valid_hooks & (1 << hook)); - - rcu_read_lock_bh(); - private = rcu_dereference(table->private); - table_base = rcu_dereference(private->entries[smp_processor_id()]); + xt_info_rdlock_bh(); + private = table->private; + table_base = private->entries[smp_processor_id()]; e = get_entry(table_base, private->hook_entry[hook]); @@ -436,8 +435,7 @@ ipt_do_table(struct sk_buff *skb, e = (void *)e + e->next_offset; } } while (!hotdrop); - - rcu_read_unlock_bh(); + xt_info_rdunlock_bh(); #ifdef DEBUG_ALLOW_ALL return NF_ACCEPT; @@ -896,10 +894,13 @@ get_counters(const struct xt_table_info *t, /* Instead of clearing (by a previous call to memset()) * the counters and using adds, we set the counters - * with data used by 'current' CPU - * We dont care about preemption here. + * with data used by 'current' CPU. + * + * Bottom half has to be disabled to prevent deadlock + * if new softirq were to run and call ipt_do_table */ - curcpu = raw_smp_processor_id(); + local_bh_disable(); + curcpu = smp_processor_id(); i = 0; IPT_ENTRY_ITERATE(t->entries[curcpu], @@ -912,74 +913,22 @@ get_counters(const struct xt_table_info *t, if (cpu == curcpu) continue; i = 0; + xt_info_wrlock(cpu); IPT_ENTRY_ITERATE(t->entries[cpu], t->size, add_entry_to_counter, counters, &i); + xt_info_wrunlock(cpu); } - -} - -/* We're lazy, and add to the first CPU; overflow works its fey magic - * and everything is OK. */ -static int -add_counter_to_entry(struct ipt_entry *e, - const struct xt_counters addme[], - unsigned int *i) -{ - ADD_COUNTER(e->counters, addme[*i].bcnt, addme[*i].pcnt); - - (*i)++; - return 0; -} - -/* Take values from counters and add them back onto the current cpu */ -static void put_counters(struct xt_table_info *t, - const struct xt_counters counters[]) -{ - unsigned int i, cpu; - - local_bh_disable(); - cpu = smp_processor_id(); - i = 0; - IPT_ENTRY_ITERATE(t->entries[cpu], - t->size, - add_counter_to_entry, - counters, - &i); local_bh_enable(); } - -static inline int -zero_entry_counter(struct ipt_entry *e, void *arg) -{ - e->counters.bcnt = 0; - e->counters.pcnt = 0; - return 0; -} - -static void -clone_counters(struct xt_table_info *newinfo, const struct xt_table_info *info) -{ - unsigned int cpu; - const void *loc_cpu_entry = info->entries[raw_smp_processor_id()]; - - memcpy(newinfo, info, offsetof(struct xt_table_info, entries)); - for_each_possible_cpu(cpu) { - memcpy(newinfo->entries[cpu], loc_cpu_entry, info->size); - IPT_ENTRY_ITERATE(newinfo->entries[cpu], newinfo->size, - zero_entry_counter, NULL); - } -} - static struct xt_counters * alloc_counters(struct xt_table *table) { unsigned int countersize; struct xt_counters *counters; struct xt_table_info *private = table->private; - struct xt_table_info *info; /* We need atomic snapshot of counters: rest doesn't change (other than comefrom, which userspace doesn't care @@ -988,30 +937,11 @@ static struct xt_counters * alloc_counters(struct xt_table *table) counters = vmalloc_node(countersize, numa_node_id()); if (counters == NULL) - goto nomem; + return ERR_PTR(-ENOMEM); - info = xt_alloc_table_info(private->size); - if (!info) - goto free_counters; - - clone_counters(info, private); - - mutex_lock(&table->lock); - xt_table_entry_swap_rcu(private, info); - synchronize_net(); /* Wait until smoke has cleared */ - - get_counters(info, counters); - put_counters(private, counters); - mutex_unlock(&table->lock); - - xt_free_table_info(info); + get_counters(private, counters); return counters; - - free_counters: - vfree(counters); - nomem: - return ERR_PTR(-ENOMEM); } static int @@ -1306,8 +1236,9 @@ __do_replace(struct net *net, const char *name, unsigned int valid_hooks, (newinfo->number <= oldinfo->initial_entries)) module_put(t->me); - /* Get the old counters. */ + /* Get the old counters, and synchronize with replace */ get_counters(oldinfo, counters); + /* Decrease module usage counts and free resource */ loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()]; IPT_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry, @@ -1377,11 +1308,23 @@ do_replace(struct net *net, void __user *user, unsigned int len) return ret; } +/* We're lazy, and add to the first CPU; overflow works its fey magic + * and everything is OK. */ +static int +add_counter_to_entry(struct ipt_entry *e, + const struct xt_counters addme[], + unsigned int *i) +{ + ADD_COUNTER(e->counters, addme[*i].bcnt, addme[*i].pcnt); + + (*i)++; + return 0; +} static int do_add_counters(struct net *net, void __user *user, unsigned int len, int compat) { - unsigned int i; + unsigned int i, curcpu; struct xt_counters_info tmp; struct xt_counters *paddc; unsigned int num_counters; @@ -1437,25 +1380,26 @@ do_add_counters(struct net *net, void __user *user, unsigned int len, int compat goto free; } - mutex_lock(&t->lock); + local_bh_disable(); private = t->private; if (private->number != num_counters) { ret = -EINVAL; goto unlock_up_free; } - preempt_disable(); i = 0; /* Choose the copy that is on our node */ - loc_cpu_entry = private->entries[raw_smp_processor_id()]; + curcpu = smp_processor_id(); + loc_cpu_entry = private->entries[curcpu]; + xt_info_wrlock(curcpu); IPT_ENTRY_ITERATE(loc_cpu_entry, private->size, add_counter_to_entry, paddc, &i); - preempt_enable(); + xt_info_wrunlock(curcpu); unlock_up_free: - mutex_unlock(&t->lock); + local_bh_enable(); xt_table_unlock(t); module_put(t->me); free: diff --git a/net/ipv4/route.c b/net/ipv4/route.c index c40debe51b3..c4c60e9f068 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -3397,7 +3397,7 @@ int __init ip_rt_init(void) 0, &rt_hash_log, &rt_hash_mask, - 0); + rhash_entries ? 0 : 512 * 1024); memset(rt_hash_table, 0, (rt_hash_mask + 1) * sizeof(struct rt_hash_bucket)); rt_hash_lock_init(); diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index c96a6bb2543..eec3e6f9956 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -597,16 +597,6 @@ static void tcp_event_data_recv(struct sock *sk, struct sk_buff *skb) tcp_grow_window(sk, skb); } -static u32 tcp_rto_min(struct sock *sk) -{ - struct dst_entry *dst = __sk_dst_get(sk); - u32 rto_min = TCP_RTO_MIN; - - if (dst && dst_metric_locked(dst, RTAX_RTO_MIN)) - rto_min = dst_metric_rtt(dst, RTAX_RTO_MIN); - return rto_min; -} - /* Called to compute a smoothed rtt estimate. The data fed to this * routine either comes from timestamps, or from segments that were * known _not_ to have been retransmitted [see Karn/Partridge diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 800ae854247..219e165aea1 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -365,9 +365,9 @@ ip6t_do_table(struct sk_buff *skb, IP_NF_ASSERT(table->valid_hooks & (1 << hook)); - rcu_read_lock_bh(); - private = rcu_dereference(table->private); - table_base = rcu_dereference(private->entries[smp_processor_id()]); + xt_info_rdlock_bh(); + private = table->private; + table_base = private->entries[smp_processor_id()]; e = get_entry(table_base, private->hook_entry[hook]); @@ -466,7 +466,7 @@ ip6t_do_table(struct sk_buff *skb, #ifdef CONFIG_NETFILTER_DEBUG ((struct ip6t_entry *)table_base)->comefrom = NETFILTER_LINK_POISON; #endif - rcu_read_unlock_bh(); + xt_info_rdunlock_bh(); #ifdef DEBUG_ALLOW_ALL return NF_ACCEPT; @@ -926,9 +926,12 @@ get_counters(const struct xt_table_info *t, /* Instead of clearing (by a previous call to memset()) * the counters and using adds, we set the counters * with data used by 'current' CPU - * We dont care about preemption here. + * + * Bottom half has to be disabled to prevent deadlock + * if new softirq were to run and call ipt_do_table */ - curcpu = raw_smp_processor_id(); + local_bh_disable(); + curcpu = smp_processor_id(); i = 0; IP6T_ENTRY_ITERATE(t->entries[curcpu], @@ -941,72 +944,22 @@ get_counters(const struct xt_table_info *t, if (cpu == curcpu) continue; i = 0; + xt_info_wrlock(cpu); IP6T_ENTRY_ITERATE(t->entries[cpu], t->size, add_entry_to_counter, counters, &i); + xt_info_wrunlock(cpu); } -} - -/* We're lazy, and add to the first CPU; overflow works its fey magic - * and everything is OK. */ -static int -add_counter_to_entry(struct ip6t_entry *e, - const struct xt_counters addme[], - unsigned int *i) -{ - ADD_COUNTER(e->counters, addme[*i].bcnt, addme[*i].pcnt); - - (*i)++; - return 0; -} - -/* Take values from counters and add them back onto the current cpu */ -static void put_counters(struct xt_table_info *t, - const struct xt_counters counters[]) -{ - unsigned int i, cpu; - - local_bh_disable(); - cpu = smp_processor_id(); - i = 0; - IP6T_ENTRY_ITERATE(t->entries[cpu], - t->size, - add_counter_to_entry, - counters, - &i); local_bh_enable(); } -static inline int -zero_entry_counter(struct ip6t_entry *e, void *arg) -{ - e->counters.bcnt = 0; - e->counters.pcnt = 0; - return 0; -} - -static void -clone_counters(struct xt_table_info *newinfo, const struct xt_table_info *info) -{ - unsigned int cpu; - const void *loc_cpu_entry = info->entries[raw_smp_processor_id()]; - - memcpy(newinfo, info, offsetof(struct xt_table_info, entries)); - for_each_possible_cpu(cpu) { - memcpy(newinfo->entries[cpu], loc_cpu_entry, info->size); - IP6T_ENTRY_ITERATE(newinfo->entries[cpu], newinfo->size, - zero_entry_counter, NULL); - } -} - static struct xt_counters *alloc_counters(struct xt_table *table) { unsigned int countersize; struct xt_counters *counters; struct xt_table_info *private = table->private; - struct xt_table_info *info; /* We need atomic snapshot of counters: rest doesn't change (other than comefrom, which userspace doesn't care @@ -1015,30 +968,11 @@ static struct xt_counters *alloc_counters(struct xt_table *table) counters = vmalloc_node(countersize, numa_node_id()); if (counters == NULL) - goto nomem; + return ERR_PTR(-ENOMEM); - info = xt_alloc_table_info(private->size); - if (!info) - goto free_counters; - - clone_counters(info, private); - - mutex_lock(&table->lock); - xt_table_entry_swap_rcu(private, info); - synchronize_net(); /* Wait until smoke has cleared */ - - get_counters(info, counters); - put_counters(private, counters); - mutex_unlock(&table->lock); - - xt_free_table_info(info); + get_counters(private, counters); return counters; - - free_counters: - vfree(counters); - nomem: - return ERR_PTR(-ENOMEM); } static int @@ -1334,8 +1268,9 @@ __do_replace(struct net *net, const char *name, unsigned int valid_hooks, (newinfo->number <= oldinfo->initial_entries)) module_put(t->me); - /* Get the old counters. */ + /* Get the old counters, and synchronize with replace */ get_counters(oldinfo, counters); + /* Decrease module usage counts and free resource */ loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()]; IP6T_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry, @@ -1405,11 +1340,24 @@ do_replace(struct net *net, void __user *user, unsigned int len) return ret; } +/* We're lazy, and add to the first CPU; overflow works its fey magic + * and everything is OK. */ +static int +add_counter_to_entry(struct ip6t_entry *e, + const struct xt_counters addme[], + unsigned int *i) +{ + ADD_COUNTER(e->counters, addme[*i].bcnt, addme[*i].pcnt); + + (*i)++; + return 0; +} + static int do_add_counters(struct net *net, void __user *user, unsigned int len, int compat) { - unsigned int i; + unsigned int i, curcpu; struct xt_counters_info tmp; struct xt_counters *paddc; unsigned int num_counters; @@ -1465,25 +1413,28 @@ do_add_counters(struct net *net, void __user *user, unsigned int len, goto free; } - mutex_lock(&t->lock); + + local_bh_disable(); private = t->private; if (private->number != num_counters) { ret = -EINVAL; goto unlock_up_free; } - preempt_disable(); i = 0; /* Choose the copy that is on our node */ - loc_cpu_entry = private->entries[raw_smp_processor_id()]; + curcpu = smp_processor_id(); + xt_info_wrlock(curcpu); + loc_cpu_entry = private->entries[curcpu]; IP6T_ENTRY_ITERATE(loc_cpu_entry, private->size, add_counter_to_entry, paddc, &i); - preempt_enable(); + xt_info_wrunlock(curcpu); + unlock_up_free: - mutex_unlock(&t->lock); + local_bh_enable(); xt_table_unlock(t); module_put(t->me); free: diff --git a/net/ipv6/netfilter/ip6t_ipv6header.c b/net/ipv6/netfilter/ip6t_ipv6header.c index 14e6724d567..91490ad9302 100644 --- a/net/ipv6/netfilter/ip6t_ipv6header.c +++ b/net/ipv6/netfilter/ip6t_ipv6header.c @@ -50,14 +50,14 @@ ipv6header_mt6(const struct sk_buff *skb, const struct xt_match_param *par) struct ipv6_opt_hdr _hdr; int hdrlen; - /* Is there enough space for the next ext header? */ - if (len < (int)sizeof(struct ipv6_opt_hdr)) - return false; /* No more exthdr -> evaluate */ if (nexthdr == NEXTHDR_NONE) { temp |= MASK_NONE; break; } + /* Is there enough space for the next ext header? */ + if (len < (int)sizeof(struct ipv6_opt_hdr)) + return false; /* ESP -> evaluate */ if (nexthdr == NEXTHDR_ESP) { temp |= MASK_ESP; diff --git a/net/mac80211/main.c b/net/mac80211/main.c index fbcbed6cad0..14134193cd1 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -757,6 +757,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, local->hw.conf.long_frame_max_tx_count = 4; local->hw.conf.short_frame_max_tx_count = 7; local->hw.conf.radio_enabled = true; + local->user_power_level = -1; INIT_LIST_HEAD(&local->interfaces); mutex_init(&local->iflist_mtx); @@ -909,6 +910,13 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) if (result < 0) goto fail_sta_info; + result = ieee80211_wep_init(local); + if (result < 0) { + printk(KERN_DEBUG "%s: Failed to initialize wep: %d\n", + wiphy_name(local->hw.wiphy), result); + goto fail_wep; + } + rtnl_lock(); result = dev_alloc_name(local->mdev, local->mdev->name); if (result < 0) @@ -930,14 +938,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) goto fail_rate; } - result = ieee80211_wep_init(local); - - if (result < 0) { - printk(KERN_DEBUG "%s: Failed to initialize wep: %d\n", - wiphy_name(local->hw.wiphy), result); - goto fail_wep; - } - /* add one default STA interface if supported */ if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) { result = ieee80211_if_add(local, "wlan%d", NULL, @@ -967,13 +967,13 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) return 0; -fail_wep: - rate_control_deinitialize(local); fail_rate: unregister_netdevice(local->mdev); local->mdev = NULL; fail_dev: rtnl_unlock(); + ieee80211_wep_free(local); +fail_wep: sta_info_stop(local); fail_sta_info: debugfs_hw_del(local); diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c index 3824990d340..70df3dcc3cf 100644 --- a/net/mac80211/rc80211_minstrel.c +++ b/net/mac80211/rc80211_minstrel.c @@ -476,7 +476,7 @@ minstrel_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp) return NULL; for (i = 0; i < IEEE80211_NUM_BANDS; i++) { - sband = hw->wiphy->bands[hw->conf.channel->band]; + sband = hw->wiphy->bands[i]; if (sband->n_bitrates > max_rates) max_rates = sband->n_bitrates; } diff --git a/net/mac80211/rc80211_pid_algo.c b/net/mac80211/rc80211_pid_algo.c index b16801cde06..01d59a8e334 100644 --- a/net/mac80211/rc80211_pid_algo.c +++ b/net/mac80211/rc80211_pid_algo.c @@ -317,13 +317,44 @@ rate_control_pid_rate_init(void *priv, struct ieee80211_supported_band *sband, struct ieee80211_sta *sta, void *priv_sta) { struct rc_pid_sta_info *spinfo = priv_sta; + struct rc_pid_info *pinfo = priv; + struct rc_pid_rateinfo *rinfo = pinfo->rinfo; struct sta_info *si; + int i, j, tmp; + bool s; /* TODO: This routine should consider using RSSI from previous packets * as we need to have IEEE 802.1X auth succeed immediately after assoc.. * Until that method is implemented, we will use the lowest supported * rate as a workaround. */ + /* Sort the rates. This is optimized for the most common case (i.e. + * almost-sorted CCK+OFDM rates). Kind of bubble-sort with reversed + * mapping too. */ + for (i = 0; i < sband->n_bitrates; i++) { + rinfo[i].index = i; + rinfo[i].rev_index = i; + if (RC_PID_FAST_START) + rinfo[i].diff = 0; + else + rinfo[i].diff = i * pinfo->norm_offset; + } + for (i = 1; i < sband->n_bitrates; i++) { + s = 0; + for (j = 0; j < sband->n_bitrates - i; j++) + if (unlikely(sband->bitrates[rinfo[j].index].bitrate > + sband->bitrates[rinfo[j + 1].index].bitrate)) { + tmp = rinfo[j].index; + rinfo[j].index = rinfo[j + 1].index; + rinfo[j + 1].index = tmp; + rinfo[rinfo[j].index].rev_index = j; + rinfo[rinfo[j + 1].index].rev_index = j + 1; + s = 1; + } + if (!s) + break; + } + spinfo->txrate_idx = rate_lowest_index(sband, sta); /* HACK */ si = container_of(sta, struct sta_info, sta); @@ -336,21 +367,22 @@ static void *rate_control_pid_alloc(struct ieee80211_hw *hw, struct rc_pid_info *pinfo; struct rc_pid_rateinfo *rinfo; struct ieee80211_supported_band *sband; - int i, j, tmp; - bool s; + int i, max_rates = 0; #ifdef CONFIG_MAC80211_DEBUGFS struct rc_pid_debugfs_entries *de; #endif - sband = hw->wiphy->bands[hw->conf.channel->band]; - pinfo = kmalloc(sizeof(*pinfo), GFP_ATOMIC); if (!pinfo) return NULL; - /* We can safely assume that sband won't change unless we get - * reinitialized. */ - rinfo = kmalloc(sizeof(*rinfo) * sband->n_bitrates, GFP_ATOMIC); + for (i = 0; i < IEEE80211_NUM_BANDS; i++) { + sband = hw->wiphy->bands[i]; + if (sband->n_bitrates > max_rates) + max_rates = sband->n_bitrates; + } + + rinfo = kmalloc(sizeof(*rinfo) * max_rates, GFP_ATOMIC); if (!rinfo) { kfree(pinfo); return NULL; @@ -368,33 +400,6 @@ static void *rate_control_pid_alloc(struct ieee80211_hw *hw, pinfo->rinfo = rinfo; pinfo->oldrate = 0; - /* Sort the rates. This is optimized for the most common case (i.e. - * almost-sorted CCK+OFDM rates). Kind of bubble-sort with reversed - * mapping too. */ - for (i = 0; i < sband->n_bitrates; i++) { - rinfo[i].index = i; - rinfo[i].rev_index = i; - if (RC_PID_FAST_START) - rinfo[i].diff = 0; - else - rinfo[i].diff = i * pinfo->norm_offset; - } - for (i = 1; i < sband->n_bitrates; i++) { - s = 0; - for (j = 0; j < sband->n_bitrates - i; j++) - if (unlikely(sband->bitrates[rinfo[j].index].bitrate > - sband->bitrates[rinfo[j + 1].index].bitrate)) { - tmp = rinfo[j].index; - rinfo[j].index = rinfo[j + 1].index; - rinfo[j + 1].index = tmp; - rinfo[rinfo[j].index].rev_index = j; - rinfo[rinfo[j + 1].index].rev_index = j + 1; - s = 1; - } - if (!s) - break; - } - #ifdef CONFIG_MAC80211_DEBUGFS de = &pinfo->dentries; de->target = debugfs_create_u32("target_pf", S_IRUSR | S_IWUSR, diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 3fb04a86444..63656266d56 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -772,7 +772,7 @@ ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx) hdrlen = ieee80211_hdrlen(hdr->frame_control); /* internal error, why is TX_FRAGMENTED set? */ - if (WARN_ON(skb->len <= frag_threshold)) + if (WARN_ON(skb->len + FCS_LEN <= frag_threshold)) return TX_DROP; /* diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index 2329c5f5055..cb3ad741ebf 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig @@ -275,6 +275,8 @@ config NF_CT_NETLINK help This option enables support for a netlink-based userspace interface +endif # NF_CONNTRACK + # transparent proxy support config NETFILTER_TPROXY tristate "Transparent proxying support (EXPERIMENTAL)" @@ -290,8 +292,6 @@ config NETFILTER_TPROXY To compile it as a module, choose M here. If unsure, say N. -endif # NF_CONNTRACK - config NETFILTER_XTABLES tristate "Netfilter Xtables support (required for ip_tables)" default m if NETFILTER_ADVANCED=n @@ -837,6 +837,7 @@ config NETFILTER_XT_MATCH_SOCKET depends on NETFILTER_TPROXY depends on NETFILTER_XTABLES depends on NETFILTER_ADVANCED + depends on !NF_CONNTRACK || NF_CONNTRACK select NF_DEFRAG_IPV4 help This option adds a `socket' match, which can be used to match diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c index 60aba45023f..77bfdfeb966 100644 --- a/net/netfilter/ipvs/ip_vs_conn.c +++ b/net/netfilter/ipvs/ip_vs_conn.c @@ -260,7 +260,10 @@ struct ip_vs_conn *ip_vs_ct_in_get list_for_each_entry(cp, &ip_vs_conn_tab[hash], c_list) { if (cp->af == af && ip_vs_addr_equal(af, s_addr, &cp->caddr) && - ip_vs_addr_equal(af, d_addr, &cp->vaddr) && + /* protocol should only be IPPROTO_IP if + * d_addr is a fwmark */ + ip_vs_addr_equal(protocol == IPPROTO_IP ? AF_UNSPEC : af, + d_addr, &cp->vaddr) && s_port == cp->cport && d_port == cp->vport && cp->flags & IP_VS_CONN_F_TEMPLATE && protocol == cp->protocol) { @@ -698,7 +701,9 @@ ip_vs_conn_new(int af, int proto, const union nf_inet_addr *caddr, __be16 cport, cp->cport = cport; ip_vs_addr_copy(af, &cp->vaddr, vaddr); cp->vport = vport; - ip_vs_addr_copy(af, &cp->daddr, daddr); + /* proto should only be IPPROTO_IP if d_addr is a fwmark */ + ip_vs_addr_copy(proto == IPPROTO_IP ? AF_UNSPEC : af, + &cp->daddr, daddr); cp->dport = dport; cp->flags = flags; spin_lock_init(&cp->lock); diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c index cb3e031335e..8dddb17a947 100644 --- a/net/netfilter/ipvs/ip_vs_core.c +++ b/net/netfilter/ipvs/ip_vs_core.c @@ -278,7 +278,7 @@ ip_vs_sched_persist(struct ip_vs_service *svc, */ if (svc->fwmark) { union nf_inet_addr fwmark = { - .all = { 0, 0, 0, htonl(svc->fwmark) } + .ip = htonl(svc->fwmark) }; ct = ip_vs_ct_in_get(svc->af, IPPROTO_IP, &snet, 0, @@ -306,7 +306,7 @@ ip_vs_sched_persist(struct ip_vs_service *svc, */ if (svc->fwmark) { union nf_inet_addr fwmark = { - .all = { 0, 0, 0, htonl(svc->fwmark) } + .ip = htonl(svc->fwmark) }; ct = ip_vs_conn_new(svc->af, IPPROTO_IP, diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index f13fc57e1ec..c523f0b8cee 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -1186,28 +1186,6 @@ ctnetlink_change_conntrack(struct nf_conn *ct, struct nlattr *cda[]) return 0; } -static inline void -ctnetlink_event_report(struct nf_conn *ct, u32 pid, int report) -{ - unsigned int events = 0; - - if (test_bit(IPS_EXPECTED_BIT, &ct->status)) - events |= IPCT_RELATED; - else - events |= IPCT_NEW; - - nf_conntrack_event_report(IPCT_STATUS | - IPCT_HELPER | - IPCT_REFRESH | - IPCT_PROTOINFO | - IPCT_NATSEQADJ | - IPCT_MARK | - events, - ct, - pid, - report); -} - static struct nf_conn * ctnetlink_create_conntrack(struct nlattr *cda[], struct nf_conntrack_tuple *otuple, @@ -1373,6 +1351,7 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb, err = -ENOENT; if (nlh->nlmsg_flags & NLM_F_CREATE) { struct nf_conn *ct; + enum ip_conntrack_events events; ct = ctnetlink_create_conntrack(cda, &otuple, &rtuple, u3); @@ -1383,9 +1362,18 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb, err = 0; nf_conntrack_get(&ct->ct_general); spin_unlock_bh(&nf_conntrack_lock); - ctnetlink_event_report(ct, - NETLINK_CB(skb).pid, - nlmsg_report(nlh)); + if (test_bit(IPS_EXPECTED_BIT, &ct->status)) + events = IPCT_RELATED; + else + events = IPCT_NEW; + + nf_conntrack_event_report(IPCT_STATUS | + IPCT_HELPER | + IPCT_PROTOINFO | + IPCT_NATSEQADJ | + IPCT_MARK | events, + ct, NETLINK_CB(skb).pid, + nlmsg_report(nlh)); nf_ct_put(ct); } else spin_unlock_bh(&nf_conntrack_lock); @@ -1404,9 +1392,13 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb, if (err == 0) { nf_conntrack_get(&ct->ct_general); spin_unlock_bh(&nf_conntrack_lock); - ctnetlink_event_report(ct, - NETLINK_CB(skb).pid, - nlmsg_report(nlh)); + nf_conntrack_event_report(IPCT_STATUS | + IPCT_HELPER | + IPCT_PROTOINFO | + IPCT_NATSEQADJ | + IPCT_MARK, + ct, NETLINK_CB(skb).pid, + nlmsg_report(nlh)); nf_ct_put(ct); } else spin_unlock_bh(&nf_conntrack_lock); diff --git a/net/netfilter/nf_conntrack_proto_dccp.c b/net/netfilter/nf_conntrack_proto_dccp.c index 50dac8dbe7d..8e757dd5339 100644 --- a/net/netfilter/nf_conntrack_proto_dccp.c +++ b/net/netfilter/nf_conntrack_proto_dccp.c @@ -633,6 +633,8 @@ static int dccp_to_nlattr(struct sk_buff *skb, struct nlattr *nla, if (!nest_parms) goto nla_put_failure; NLA_PUT_U8(skb, CTA_PROTOINFO_DCCP_STATE, ct->proto.dccp.state); + NLA_PUT_U8(skb, CTA_PROTOINFO_DCCP_ROLE, + ct->proto.dccp.role[IP_CT_DIR_ORIGINAL]); nla_nest_end(skb, nest_parms); read_unlock_bh(&dccp_lock); return 0; @@ -644,6 +646,7 @@ nla_put_failure: static const struct nla_policy dccp_nla_policy[CTA_PROTOINFO_DCCP_MAX + 1] = { [CTA_PROTOINFO_DCCP_STATE] = { .type = NLA_U8 }, + [CTA_PROTOINFO_DCCP_ROLE] = { .type = NLA_U8 }, }; static int nlattr_to_dccp(struct nlattr *cda[], struct nf_conn *ct) @@ -661,11 +664,21 @@ static int nlattr_to_dccp(struct nlattr *cda[], struct nf_conn *ct) return err; if (!tb[CTA_PROTOINFO_DCCP_STATE] || - nla_get_u8(tb[CTA_PROTOINFO_DCCP_STATE]) >= CT_DCCP_IGNORE) + !tb[CTA_PROTOINFO_DCCP_ROLE] || + nla_get_u8(tb[CTA_PROTOINFO_DCCP_ROLE]) > CT_DCCP_ROLE_MAX || + nla_get_u8(tb[CTA_PROTOINFO_DCCP_STATE]) >= CT_DCCP_IGNORE) { return -EINVAL; + } write_lock_bh(&dccp_lock); ct->proto.dccp.state = nla_get_u8(tb[CTA_PROTOINFO_DCCP_STATE]); + if (nla_get_u8(tb[CTA_PROTOINFO_DCCP_ROLE]) == CT_DCCP_ROLE_CLIENT) { + ct->proto.dccp.role[IP_CT_DIR_ORIGINAL] = CT_DCCP_ROLE_CLIENT; + ct->proto.dccp.role[IP_CT_DIR_REPLY] = CT_DCCP_ROLE_SERVER; + } else { + ct->proto.dccp.role[IP_CT_DIR_ORIGINAL] = CT_DCCP_ROLE_SERVER; + ct->proto.dccp.role[IP_CT_DIR_REPLY] = CT_DCCP_ROLE_CLIENT; + } write_unlock_bh(&dccp_lock); return 0; } @@ -777,6 +790,7 @@ static struct nf_conntrack_l4proto dccp_proto6 __read_mostly = { .print_conntrack = dccp_print_conntrack, #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) .to_nlattr = dccp_to_nlattr, + .nlattr_size = dccp_nlattr_size, .from_nlattr = nlattr_to_dccp, .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr, .nlattr_tuple_size = nf_ct_port_nlattr_tuple_size, diff --git a/net/netfilter/nf_conntrack_proto_udplite.c b/net/netfilter/nf_conntrack_proto_udplite.c index 4614696c1b8..0badedc542d 100644 --- a/net/netfilter/nf_conntrack_proto_udplite.c +++ b/net/netfilter/nf_conntrack_proto_udplite.c @@ -204,6 +204,7 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite6 __read_mostly = .error = udplite_error, #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr, + .nlattr_tuple_size = nf_ct_port_nlattr_tuple_size, .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple, .nla_policy = nf_ct_port_nla_policy, #endif diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c index 509a95621f9..150e5cf62f8 100644 --- a/net/netfilter/x_tables.c +++ b/net/netfilter/x_tables.c @@ -625,20 +625,6 @@ void xt_free_table_info(struct xt_table_info *info) } EXPORT_SYMBOL(xt_free_table_info); -void xt_table_entry_swap_rcu(struct xt_table_info *oldinfo, - struct xt_table_info *newinfo) -{ - unsigned int cpu; - - for_each_possible_cpu(cpu) { - void *p = oldinfo->entries[cpu]; - rcu_assign_pointer(oldinfo->entries[cpu], newinfo->entries[cpu]); - newinfo->entries[cpu] = p; - } - -} -EXPORT_SYMBOL_GPL(xt_table_entry_swap_rcu); - /* Find table by name, grabs mutex & ref. Returns ERR_PTR() on error. */ struct xt_table *xt_find_table_lock(struct net *net, u_int8_t af, const char *name) @@ -676,32 +662,43 @@ void xt_compat_unlock(u_int8_t af) EXPORT_SYMBOL_GPL(xt_compat_unlock); #endif +DEFINE_PER_CPU(struct xt_info_lock, xt_info_locks); +EXPORT_PER_CPU_SYMBOL_GPL(xt_info_locks); + + struct xt_table_info * xt_replace_table(struct xt_table *table, unsigned int num_counters, struct xt_table_info *newinfo, int *error) { - struct xt_table_info *oldinfo, *private; + struct xt_table_info *private; /* Do the substitution. */ - mutex_lock(&table->lock); + local_bh_disable(); private = table->private; + /* Check inside lock: is the old number correct? */ if (num_counters != private->number) { duprintf("num_counters != table->private->number (%u/%u)\n", num_counters, private->number); - mutex_unlock(&table->lock); + local_bh_enable(); *error = -EAGAIN; return NULL; } - oldinfo = private; - rcu_assign_pointer(table->private, newinfo); - newinfo->initial_entries = oldinfo->initial_entries; - mutex_unlock(&table->lock); - synchronize_net(); - return oldinfo; + table->private = newinfo; + newinfo->initial_entries = private->initial_entries; + + /* + * Even though table entries have now been swapped, other CPU's + * may still be using the old entries. This is okay, because + * resynchronization happens because of the locking done + * during the get_counters() routine. + */ + local_bh_enable(); + + return private; } EXPORT_SYMBOL_GPL(xt_replace_table); @@ -734,7 +731,6 @@ struct xt_table *xt_register_table(struct net *net, struct xt_table *table, /* Simplifies replace_table code. */ table->private = bootstrap; - mutex_init(&table->lock); if (!xt_replace_table(table, 0, newinfo, &ret)) goto unlock; @@ -1147,7 +1143,14 @@ static struct pernet_operations xt_net_ops = { static int __init xt_init(void) { - int i, rv; + unsigned int i; + int rv; + + for_each_possible_cpu(i) { + struct xt_info_lock *lock = &per_cpu(xt_info_locks, i); + spin_lock_init(&lock->lock); + lock->readers = 0; + } xt = kmalloc(sizeof(struct xt_af) * NFPROTO_NUMPROTO, GFP_KERNEL); if (!xt) diff --git a/net/netfilter/xt_cluster.c b/net/netfilter/xt_cluster.c index 6c4847662b8..69a639f3540 100644 --- a/net/netfilter/xt_cluster.c +++ b/net/netfilter/xt_cluster.c @@ -135,7 +135,13 @@ static bool xt_cluster_mt_checkentry(const struct xt_mtchk_param *par) { struct xt_cluster_match_info *info = par->matchinfo; - if (info->node_mask >= (1 << info->total_nodes)) { + if (info->total_nodes > XT_CLUSTER_NODES_MAX) { + printk(KERN_ERR "xt_cluster: you have exceeded the maximum " + "number of cluster nodes (%u > %u)\n", + info->total_nodes, XT_CLUSTER_NODES_MAX); + return false; + } + if (info->node_mask >= (1ULL << info->total_nodes)) { printk(KERN_ERR "xt_cluster: this node mask cannot be " "higher than the total number of nodes\n"); return false; diff --git a/net/netfilter/xt_recent.c b/net/netfilter/xt_recent.c index 791e030ea90..eb0ceb84652 100644 --- a/net/netfilter/xt_recent.c +++ b/net/netfilter/xt_recent.c @@ -474,7 +474,7 @@ static ssize_t recent_old_proc_write(struct file *file, struct recent_table *t = pde->data; struct recent_entry *e; char buf[sizeof("+255.255.255.255")], *c = buf; - __be32 addr; + union nf_inet_addr addr = {}; int add; if (size > sizeof(buf)) @@ -506,14 +506,13 @@ static ssize_t recent_old_proc_write(struct file *file, add = 1; break; } - addr = in_aton(c); + addr.ip = in_aton(c); spin_lock_bh(&recent_lock); - e = recent_entry_lookup(t, (const void *)&addr, NFPROTO_IPV4, 0); + e = recent_entry_lookup(t, &addr, NFPROTO_IPV4, 0); if (e == NULL) { if (add) - recent_entry_init(t, (const void *)&addr, - NFPROTO_IPV4, 0); + recent_entry_init(t, &addr, NFPROTO_IPV4, 0); } else { if (add) recent_entry_update(t, e); diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index 173fcc4b050..0759f32e9dc 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c @@ -254,7 +254,7 @@ replay: } tp->ops = tp_ops; tp->protocol = protocol; - tp->prio = nprio ? : tcf_auto_prio(*back); + tp->prio = nprio ? : TC_H_MAJ(tcf_auto_prio(*back)); tp->q = q; tp->classify = tp_ops->classify; tp->classid = parent; diff --git a/net/sched/sch_fifo.c b/net/sched/sch_fifo.c index 92cfc9d7e3b..69188e8358b 100644 --- a/net/sched/sch_fifo.c +++ b/net/sched/sch_fifo.c @@ -51,7 +51,7 @@ static int fifo_init(struct Qdisc *sch, struct nlattr *opt) u32 limit = qdisc_dev(sch)->tx_queue_len ? : 1; if (sch->ops == &bfifo_qdisc_ops) - limit *= qdisc_dev(sch)->mtu; + limit *= psched_mtu(qdisc_dev(sch)); q->limit = limit; } else { diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index a0bfe53f162..06ca058572f 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c @@ -672,10 +672,8 @@ xprt_init_autodisconnect(unsigned long data) if (test_and_set_bit(XPRT_LOCKED, &xprt->state)) goto out_abort; spin_unlock(&xprt->transport_lock); - if (xprt_connecting(xprt)) - xprt_release_write(xprt, NULL); - else - queue_work(rpciod_workqueue, &xprt->task_cleanup); + set_bit(XPRT_CONNECTION_CLOSE, &xprt->state); + queue_work(rpciod_workqueue, &xprt->task_cleanup); return; out_abort: spin_unlock(&xprt->transport_lock); diff --git a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c index 629a28764da..42a6f9f2028 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c +++ b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c @@ -265,7 +265,7 @@ static int fast_reg_read_chunks(struct svcxprt_rdma *xprt, frmr->page_list->page_list[page_no] = ib_dma_map_single(xprt->sc_cm_id->device, page_address(rqstp->rq_arg.pages[page_no]), - PAGE_SIZE, DMA_TO_DEVICE); + PAGE_SIZE, DMA_FROM_DEVICE); if (ib_dma_mapping_error(xprt->sc_cm_id->device, frmr->page_list->page_list[page_no])) goto fatal_err; diff --git a/net/sunrpc/xprtrdma/svc_rdma_sendto.c b/net/sunrpc/xprtrdma/svc_rdma_sendto.c index 6c26a675435..8b510c5e877 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_sendto.c +++ b/net/sunrpc/xprtrdma/svc_rdma_sendto.c @@ -183,6 +183,7 @@ static int fast_reg_xdr(struct svcxprt_rdma *xprt, fatal_err: printk("svcrdma: Error fast registering memory for xprt %p\n", xprt); + vec->frmr = NULL; svc_rdma_put_frmr(xprt, frmr); return -EIO; } @@ -516,6 +517,7 @@ static int send_reply(struct svcxprt_rdma *rdma, "svcrdma: could not post a receive buffer, err=%d." "Closing transport %p.\n", ret, rdma); set_bit(XPT_CLOSE, &rdma->sc_xprt.xpt_flags); + svc_rdma_put_frmr(rdma, vec->frmr); svc_rdma_put_context(ctxt, 0); return -ENOTCONN; } @@ -606,6 +608,7 @@ static int send_reply(struct svcxprt_rdma *rdma, return 0; err: + svc_rdma_unmap_dma(ctxt); svc_rdma_put_frmr(rdma, vec->frmr); svc_rdma_put_context(ctxt, 1); return -EIO; diff --git a/net/sunrpc/xprtrdma/svc_rdma_transport.c b/net/sunrpc/xprtrdma/svc_rdma_transport.c index 3d810e7df3f..4b0c2fa15e0 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_transport.c +++ b/net/sunrpc/xprtrdma/svc_rdma_transport.c @@ -520,8 +520,9 @@ int svc_rdma_post_recv(struct svcxprt_rdma *xprt) svc_xprt_get(&xprt->sc_xprt); ret = ib_post_recv(xprt->sc_qp, &recv_wr, &bad_recv_wr); if (ret) { - svc_xprt_put(&xprt->sc_xprt); + svc_rdma_unmap_dma(ctxt); svc_rdma_put_context(ctxt, 1); + svc_xprt_put(&xprt->sc_xprt); } return ret; diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index d40ff50887a..e1859614601 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -807,6 +807,9 @@ static void xs_reset_transport(struct sock_xprt *transport) * * This is used when all requests are complete; ie, no DRC state remains * on the server we want to save. + * + * The caller _must_ be holding XPRT_LOCKED in order to avoid issues with + * xs_reset_transport() zeroing the socket from underneath a writer. */ static void xs_close(struct rpc_xprt *xprt) { @@ -824,6 +827,14 @@ static void xs_close(struct rpc_xprt *xprt) xprt_disconnect_done(xprt); } +static void xs_tcp_close(struct rpc_xprt *xprt) +{ + if (test_and_clear_bit(XPRT_CONNECTION_CLOSE, &xprt->state)) + xs_close(xprt); + else + xs_tcp_shutdown(xprt); +} + /** * xs_destroy - prepare to shutdown a transport * @xprt: doomed transport @@ -1772,6 +1783,15 @@ static void xs_tcp_setup_socket(struct rpc_xprt *xprt, xprt, -status, xprt_connected(xprt), sock->sk->sk_state); switch (status) { + default: + printk("%s: connect returned unhandled error %d\n", + __func__, status); + case -EADDRNOTAVAIL: + /* We're probably in TIME_WAIT. Get rid of existing socket, + * and retry + */ + set_bit(XPRT_CONNECTION_CLOSE, &xprt->state); + xprt_force_disconnect(xprt); case -ECONNREFUSED: case -ECONNRESET: case -ENETUNREACH: @@ -1782,10 +1802,6 @@ static void xs_tcp_setup_socket(struct rpc_xprt *xprt, xprt_clear_connecting(xprt); return; } - /* get rid of existing socket, and retry */ - xs_tcp_shutdown(xprt); - printk("%s: connect returned unhandled error %d\n", - __func__, status); out_eagain: status = -EAGAIN; out: @@ -1994,7 +2010,7 @@ static struct rpc_xprt_ops xs_tcp_ops = { .buf_free = rpc_free, .send_request = xs_tcp_send_request, .set_retrans_timeout = xprt_set_retrans_timeout_def, - .close = xs_tcp_shutdown, + .close = xs_tcp_close, .destroy = xs_destroy, .print_stats = xs_tcp_print_stats, }; diff --git a/net/wimax/op-msg.c b/net/wimax/op-msg.c index 5d149c1b5f0..9ad4d893a56 100644 --- a/net/wimax/op-msg.c +++ b/net/wimax/op-msg.c @@ -149,7 +149,8 @@ struct sk_buff *wimax_msg_alloc(struct wimax_dev *wimax_dev, } result = nla_put(skb, WIMAX_GNL_MSG_DATA, size, msg); if (result < 0) { - dev_err(dev, "no memory to add payload in attribute\n"); + dev_err(dev, "no memory to add payload (msg %p size %zu) in " + "attribute: %d\n", msg, size, result); goto error_nla_put; } genlmsg_end(skb, genl_msg); @@ -299,10 +300,10 @@ int wimax_msg(struct wimax_dev *wimax_dev, const char *pipe_name, struct sk_buff *skb; skb = wimax_msg_alloc(wimax_dev, pipe_name, buf, size, gfp_flags); - if (skb == NULL) - goto error_msg_new; - result = wimax_msg_send(wimax_dev, skb); -error_msg_new: + if (IS_ERR(skb)) + result = PTR_ERR(skb); + else + result = wimax_msg_send(wimax_dev, skb); return result; } EXPORT_SYMBOL_GPL(wimax_msg); diff --git a/net/wimax/stack.c b/net/wimax/stack.c index a0ee76b5251..933e1422b09 100644 --- a/net/wimax/stack.c +++ b/net/wimax/stack.c @@ -338,8 +338,21 @@ out: */ void wimax_state_change(struct wimax_dev *wimax_dev, enum wimax_st new_state) { + /* + * A driver cannot take the wimax_dev out of the + * __WIMAX_ST_NULL state unless by calling wimax_dev_add(). If + * the wimax_dev's state is still NULL, we ignore any request + * to change its state because it means it hasn't been yet + * registered. + * + * There is no need to complain about it, as routines that + * call this might be shared from different code paths that + * are called before or after wimax_dev_add() has done its + * job. + */ mutex_lock(&wimax_dev->mutex); - __wimax_state_change(wimax_dev, new_state); + if (wimax_dev->state > __WIMAX_ST_NULL) + __wimax_state_change(wimax_dev, new_state); mutex_unlock(&wimax_dev->mutex); return; } @@ -376,7 +389,7 @@ EXPORT_SYMBOL_GPL(wimax_state_get); void wimax_dev_init(struct wimax_dev *wimax_dev) { INIT_LIST_HEAD(&wimax_dev->id_table_node); - __wimax_state_set(wimax_dev, WIMAX_ST_UNINITIALIZED); + __wimax_state_set(wimax_dev, __WIMAX_ST_NULL); mutex_init(&wimax_dev->mutex); mutex_init(&wimax_dev->mutex_reset); } diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 6c1993d9990..08265ca1578 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -907,6 +907,7 @@ EXPORT_SYMBOL(freq_reg_info); int freq_reg_info(struct wiphy *wiphy, u32 center_freq, u32 *bandwidth, const struct ieee80211_reg_rule **reg_rule) { + assert_cfg80211_lock(); return freq_reg_info_regd(wiphy, center_freq, bandwidth, reg_rule, NULL); } @@ -1133,7 +1134,8 @@ static bool reg_is_world_roaming(struct wiphy *wiphy) if (is_world_regdom(cfg80211_regdomain->alpha2) || (wiphy->regd && is_world_regdom(wiphy->regd->alpha2))) return true; - if (last_request->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE && + if (last_request && + last_request->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE && wiphy->custom_regulatory) return true; return false; @@ -1142,6 +1144,12 @@ static bool reg_is_world_roaming(struct wiphy *wiphy) /* Reap the advantages of previously found beacons */ static void reg_process_beacons(struct wiphy *wiphy) { + /* + * Means we are just firing up cfg80211, so no beacons would + * have been processed yet. + */ + if (!last_request) + return; if (!reg_is_world_roaming(wiphy)) return; wiphy_update_beacon_reg(wiphy); @@ -1176,6 +1184,8 @@ static void handle_channel_custom(struct wiphy *wiphy, struct ieee80211_supported_band *sband; struct ieee80211_channel *chan; + assert_cfg80211_lock(); + sband = wiphy->bands[band]; BUG_ON(chan_idx >= sband->n_channels); chan = &sband->channels[chan_idx]; @@ -1214,10 +1224,13 @@ void wiphy_apply_custom_regulatory(struct wiphy *wiphy, const struct ieee80211_regdomain *regd) { enum ieee80211_band band; + + mutex_lock(&cfg80211_mutex); for (band = 0; band < IEEE80211_NUM_BANDS; band++) { if (wiphy->bands[band]) handle_band_custom(wiphy, band, regd); } + mutex_unlock(&cfg80211_mutex); } EXPORT_SYMBOL(wiphy_apply_custom_regulatory); @@ -1423,7 +1436,7 @@ new_request: return call_crda(last_request->alpha2); } -/* This currently only processes user and driver regulatory hints */ +/* This processes *all* regulatory hints */ static void reg_process_hint(struct regulatory_request *reg_request) { int r = 0; diff --git a/net/wireless/scan.c b/net/wireless/scan.c index 2ae65b39b52..1f260c40b6c 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c @@ -395,6 +395,7 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev, memcpy(ies, res->pub.information_elements, ielen); found->ies_allocated = true; found->pub.information_elements = ies; + found->pub.len_information_elements = ielen; } } } diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 82271720d97..5f1f86565f1 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -794,7 +794,7 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, { static xfrm_address_t saddr_wildcard = { }; struct net *net = xp_net(pol); - unsigned int h; + unsigned int h, h_wildcard; struct hlist_node *entry; struct xfrm_state *x, *x0, *to_put; int acquire_in_progress = 0; @@ -819,8 +819,8 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, if (best) goto found; - h = xfrm_dst_hash(net, daddr, &saddr_wildcard, tmpl->reqid, family); - hlist_for_each_entry(x, entry, net->xfrm.state_bydst+h, bydst) { + h_wildcard = xfrm_dst_hash(net, daddr, &saddr_wildcard, tmpl->reqid, family); + hlist_for_each_entry(x, entry, net->xfrm.state_bydst+h_wildcard, bydst) { if (x->props.family == family && x->props.reqid == tmpl->reqid && !(x->props.flags & XFRM_STATE_WILDRECV) && diff --git a/scripts/Makefile b/scripts/Makefile index aafdf064fee..9dd5b25a1d5 100644 --- a/scripts/Makefile +++ b/scripts/Makefile @@ -21,6 +21,7 @@ hostprogs-y += unifdef subdir-$(CONFIG_MODVERSIONS) += genksyms subdir-y += mod subdir-$(CONFIG_SECURITY_SELINUX) += selinux +subdir-$(CONFIG_DTC) += dtc # Let clean descend into subdirs subdir- += basic kconfig package selinux diff --git a/scripts/dtc/Makefile b/scripts/dtc/Makefile new file mode 100644 index 00000000000..01cdb36fc58 --- /dev/null +++ b/scripts/dtc/Makefile @@ -0,0 +1,54 @@ +# scripts/dtc makefile + +hostprogs-y := dtc +always := $(hostprogs-y) + +dtc-objs := dtc.o flattree.o fstree.o data.o livetree.o treesource.o \ + srcpos.o checks.o +dtc-objs += dtc-lexer.lex.o dtc-parser.tab.o + +# Source files need to get at the userspace version of libfdt_env.h to compile + +HOSTCFLAGS_DTC := -I$(src) -I$(src)/libfdt + +HOSTCFLAGS_checks.o := $(HOSTCFLAGS_DTC) +HOSTCFLAGS_data.o := $(HOSTCFLAGS_DTC) +HOSTCFLAGS_dtc.o := $(HOSTCFLAGS_DTC) +HOSTCFLAGS_flattree.o := $(HOSTCFLAGS_DTC) +HOSTCFLAGS_fstree.o := $(HOSTCFLAGS_DTC) +HOSTCFLAGS_livetree.o := $(HOSTCFLAGS_DTC) +HOSTCFLAGS_srcpos.o := $(HOSTCFLAGS_DTC) +HOSTCFLAGS_treesource.o := $(HOSTCFLAGS_DTC) + +HOSTCFLAGS_dtc-lexer.lex.o := $(HOSTCFLAGS_DTC) +HOSTCFLAGS_dtc-parser.tab.o := $(HOSTCFLAGS_DTC) + +# dependencies on generated files need to be listed explicitly +$(obj)/dtc-parser.tab.o: $(obj)/dtc-parser.tab.c $(obj)/dtc-parser.tab.h +$(obj)/dtc-lexer.lex.o: $(obj)/dtc-lexer.lex.c $(obj)/dtc-parser.tab.h + +targets += dtc-parser.tab.c dtc-lexer.lex.c + +clean-files += dtc-parser.tab.h + +# GENERATE_PARSER := 1 # Uncomment to rebuild flex/bison output + +ifdef GENERATE_PARSER + +BISON = bison +FLEX = flex + +quiet_cmd_bison = BISON $@ + cmd_bison = $(BISON) -o$@ -d $<; cp $@ $@_shipped +quiet_cmd_flex = FLEX $@ + cmd_flex = $(FLEX) -o$@ $<; cp $@ $@_shipped + +$(obj)/dtc-parser.tab.c: $(src)/dtc-parser.y FORCE + $(call if_changed,bison) + +$(obj)/dtc-parser.tab.h: $(obj)/dtc-parser.tab.c + +$(obj)/dtc-lexer.lex.c: $(src)/dtc-lexer.l FORCE + $(call if_changed,flex) + +endif diff --git a/arch/powerpc/boot/dtc-src/Makefile.dtc b/scripts/dtc/Makefile.dtc index 6ddf9ecac66..6ddf9ecac66 100644 --- a/arch/powerpc/boot/dtc-src/Makefile.dtc +++ b/scripts/dtc/Makefile.dtc diff --git a/arch/powerpc/boot/dtc-src/checks.c b/scripts/dtc/checks.c index 95485796f25..95485796f25 100644 --- a/arch/powerpc/boot/dtc-src/checks.c +++ b/scripts/dtc/checks.c diff --git a/arch/powerpc/boot/dtc-src/data.c b/scripts/dtc/data.c index dd2e3d39d4c..dd2e3d39d4c 100644 --- a/arch/powerpc/boot/dtc-src/data.c +++ b/scripts/dtc/data.c diff --git a/arch/powerpc/boot/dtc-src/dtc-lexer.l b/scripts/dtc/dtc-lexer.l index 44dbfd3f097..44dbfd3f097 100644 --- a/arch/powerpc/boot/dtc-src/dtc-lexer.l +++ b/scripts/dtc/dtc-lexer.l diff --git a/arch/powerpc/boot/dtc-src/dtc-lexer.lex.c_shipped b/scripts/dtc/dtc-lexer.lex.c_shipped index ac392cb040f..ac392cb040f 100644 --- a/arch/powerpc/boot/dtc-src/dtc-lexer.lex.c_shipped +++ b/scripts/dtc/dtc-lexer.lex.c_shipped diff --git a/arch/powerpc/boot/dtc-src/dtc-parser.tab.c_shipped b/scripts/dtc/dtc-parser.tab.c_shipped index 27129377e5d..27129377e5d 100644 --- a/arch/powerpc/boot/dtc-src/dtc-parser.tab.c_shipped +++ b/scripts/dtc/dtc-parser.tab.c_shipped diff --git a/arch/powerpc/boot/dtc-src/dtc-parser.tab.h_shipped b/scripts/dtc/dtc-parser.tab.h_shipped index ba99100d55c..ba99100d55c 100644 --- a/arch/powerpc/boot/dtc-src/dtc-parser.tab.h_shipped +++ b/scripts/dtc/dtc-parser.tab.h_shipped diff --git a/arch/powerpc/boot/dtc-src/dtc-parser.y b/scripts/dtc/dtc-parser.y index b2ab562420e..b2ab562420e 100644 --- a/arch/powerpc/boot/dtc-src/dtc-parser.y +++ b/scripts/dtc/dtc-parser.y diff --git a/arch/powerpc/boot/dtc-src/dtc.c b/scripts/dtc/dtc.c index d8fd43b4ac1..d8fd43b4ac1 100644 --- a/arch/powerpc/boot/dtc-src/dtc.c +++ b/scripts/dtc/dtc.c diff --git a/arch/powerpc/boot/dtc-src/dtc.h b/scripts/dtc/dtc.h index 08d54c87008..08d54c87008 100644 --- a/arch/powerpc/boot/dtc-src/dtc.h +++ b/scripts/dtc/dtc.h diff --git a/arch/powerpc/boot/dtc-src/flattree.c b/scripts/dtc/flattree.c index 76acd28c068..76acd28c068 100644 --- a/arch/powerpc/boot/dtc-src/flattree.c +++ b/scripts/dtc/flattree.c diff --git a/arch/powerpc/boot/dtc-src/fstree.c b/scripts/dtc/fstree.c index 766b2694d93..766b2694d93 100644 --- a/arch/powerpc/boot/dtc-src/fstree.c +++ b/scripts/dtc/fstree.c diff --git a/arch/powerpc/boot/libfdt/Makefile.libfdt b/scripts/dtc/libfdt/Makefile.libfdt index 6c42acfa21e..6c42acfa21e 100644 --- a/arch/powerpc/boot/libfdt/Makefile.libfdt +++ b/scripts/dtc/libfdt/Makefile.libfdt diff --git a/arch/powerpc/boot/libfdt/fdt.c b/scripts/dtc/libfdt/fdt.c index 2acaec5923a..2acaec5923a 100644 --- a/arch/powerpc/boot/libfdt/fdt.c +++ b/scripts/dtc/libfdt/fdt.c diff --git a/arch/powerpc/boot/libfdt/fdt.h b/scripts/dtc/libfdt/fdt.h index 48ccfd91000..48ccfd91000 100644 --- a/arch/powerpc/boot/libfdt/fdt.h +++ b/scripts/dtc/libfdt/fdt.h diff --git a/arch/powerpc/boot/libfdt/fdt_ro.c b/scripts/dtc/libfdt/fdt_ro.c index fbbba44fcd0..fbbba44fcd0 100644 --- a/arch/powerpc/boot/libfdt/fdt_ro.c +++ b/scripts/dtc/libfdt/fdt_ro.c diff --git a/arch/powerpc/boot/libfdt/fdt_rw.c b/scripts/dtc/libfdt/fdt_rw.c index 8e7ec4cb7bc..8e7ec4cb7bc 100644 --- a/arch/powerpc/boot/libfdt/fdt_rw.c +++ b/scripts/dtc/libfdt/fdt_rw.c diff --git a/arch/powerpc/boot/libfdt/fdt_strerror.c b/scripts/dtc/libfdt/fdt_strerror.c index e6c3ceee8c5..e6c3ceee8c5 100644 --- a/arch/powerpc/boot/libfdt/fdt_strerror.c +++ b/scripts/dtc/libfdt/fdt_strerror.c diff --git a/arch/powerpc/boot/libfdt/fdt_sw.c b/scripts/dtc/libfdt/fdt_sw.c index 698329e0cca..698329e0cca 100644 --- a/arch/powerpc/boot/libfdt/fdt_sw.c +++ b/scripts/dtc/libfdt/fdt_sw.c diff --git a/arch/powerpc/boot/libfdt/fdt_wip.c b/scripts/dtc/libfdt/fdt_wip.c index a4652c6e787..a4652c6e787 100644 --- a/arch/powerpc/boot/libfdt/fdt_wip.c +++ b/scripts/dtc/libfdt/fdt_wip.c diff --git a/arch/powerpc/boot/libfdt/libfdt.h b/scripts/dtc/libfdt/libfdt.h index ce80e4fb41b..ce80e4fb41b 100644 --- a/arch/powerpc/boot/libfdt/libfdt.h +++ b/scripts/dtc/libfdt/libfdt.h diff --git a/arch/powerpc/boot/dtc-src/libfdt_env.h b/scripts/dtc/libfdt/libfdt_env.h index 449bf602daf..449bf602daf 100644 --- a/arch/powerpc/boot/dtc-src/libfdt_env.h +++ b/scripts/dtc/libfdt/libfdt_env.h diff --git a/arch/powerpc/boot/libfdt/libfdt_internal.h b/scripts/dtc/libfdt/libfdt_internal.h index 46eb93e4af5..46eb93e4af5 100644 --- a/arch/powerpc/boot/libfdt/libfdt_internal.h +++ b/scripts/dtc/libfdt/libfdt_internal.h diff --git a/arch/powerpc/boot/dtc-src/livetree.c b/scripts/dtc/livetree.c index 0ca3de550b3..0ca3de550b3 100644 --- a/arch/powerpc/boot/dtc-src/livetree.c +++ b/scripts/dtc/livetree.c diff --git a/arch/powerpc/boot/dtc-src/srcpos.c b/scripts/dtc/srcpos.c index 9641b7628b4..9641b7628b4 100644 --- a/arch/powerpc/boot/dtc-src/srcpos.c +++ b/scripts/dtc/srcpos.c diff --git a/arch/powerpc/boot/dtc-src/srcpos.h b/scripts/dtc/srcpos.h index e17c7c04db8..e17c7c04db8 100644 --- a/arch/powerpc/boot/dtc-src/srcpos.h +++ b/scripts/dtc/srcpos.h diff --git a/arch/powerpc/boot/dtc-src/treesource.c b/scripts/dtc/treesource.c index ebeb6eb2790..ebeb6eb2790 100644 --- a/arch/powerpc/boot/dtc-src/treesource.c +++ b/scripts/dtc/treesource.c diff --git a/arch/powerpc/boot/dtc-src/version_gen.h b/scripts/dtc/version_gen.h index 658ff42429d..658ff42429d 100644 --- a/arch/powerpc/boot/dtc-src/version_gen.h +++ b/scripts/dtc/version_gen.h diff --git a/scripts/kernel-doc b/scripts/kernel-doc index 0f11870116d..3208a3a7e7f 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -1411,7 +1411,8 @@ sub dump_struct($$) { my $file = shift; my $nested; - if ($x =~/(struct|union)\s+(\w+)\s*{(.*)}/) { + if ($x =~ /(struct|union)\s+(\w+)\s*{(.*)}/) { + #my $decl_type = $1; $declaration_name = $2; my $members = $3; @@ -1420,8 +1421,8 @@ sub dump_struct($$) { $nested = $1; # ignore members marked private: - $members =~ s/\/\*.*?private:.*?public:.*?\*\///gos; - $members =~ s/\/\*.*?private:.*//gos; + $members =~ s/\/\*\s*private:.*?\/\*\s*public:.*?\*\///gos; + $members =~ s/\/\*\s*private:.*//gos; # strip comments: $members =~ s/\/\*.*?\*\///gos; $nested =~ s/\/\*.*?\*\///gos; diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 8d46ea7d671..161b7846733 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -384,11 +384,19 @@ static int parse_elf(struct elf_info *info, const char *filename) return 0; } /* Fix endianness in ELF header */ - hdr->e_shoff = TO_NATIVE(hdr->e_shoff); - hdr->e_shstrndx = TO_NATIVE(hdr->e_shstrndx); - hdr->e_shnum = TO_NATIVE(hdr->e_shnum); - hdr->e_machine = TO_NATIVE(hdr->e_machine); - hdr->e_type = TO_NATIVE(hdr->e_type); + hdr->e_type = TO_NATIVE(hdr->e_type); + hdr->e_machine = TO_NATIVE(hdr->e_machine); + hdr->e_version = TO_NATIVE(hdr->e_version); + hdr->e_entry = TO_NATIVE(hdr->e_entry); + hdr->e_phoff = TO_NATIVE(hdr->e_phoff); + hdr->e_shoff = TO_NATIVE(hdr->e_shoff); + hdr->e_flags = TO_NATIVE(hdr->e_flags); + hdr->e_ehsize = TO_NATIVE(hdr->e_ehsize); + hdr->e_phentsize = TO_NATIVE(hdr->e_phentsize); + hdr->e_phnum = TO_NATIVE(hdr->e_phnum); + hdr->e_shentsize = TO_NATIVE(hdr->e_shentsize); + hdr->e_shnum = TO_NATIVE(hdr->e_shnum); + hdr->e_shstrndx = TO_NATIVE(hdr->e_shstrndx); sechdrs = (void *)hdr + hdr->e_shoff; info->sechdrs = sechdrs; @@ -402,13 +410,16 @@ static int parse_elf(struct elf_info *info, const char *filename) /* Fix endianness in section headers */ for (i = 0; i < hdr->e_shnum; i++) { - sechdrs[i].sh_type = TO_NATIVE(sechdrs[i].sh_type); - sechdrs[i].sh_offset = TO_NATIVE(sechdrs[i].sh_offset); - sechdrs[i].sh_size = TO_NATIVE(sechdrs[i].sh_size); - sechdrs[i].sh_link = TO_NATIVE(sechdrs[i].sh_link); - sechdrs[i].sh_name = TO_NATIVE(sechdrs[i].sh_name); - sechdrs[i].sh_info = TO_NATIVE(sechdrs[i].sh_info); - sechdrs[i].sh_addr = TO_NATIVE(sechdrs[i].sh_addr); + sechdrs[i].sh_name = TO_NATIVE(sechdrs[i].sh_name); + sechdrs[i].sh_type = TO_NATIVE(sechdrs[i].sh_type); + sechdrs[i].sh_flags = TO_NATIVE(sechdrs[i].sh_flags); + sechdrs[i].sh_addr = TO_NATIVE(sechdrs[i].sh_addr); + sechdrs[i].sh_offset = TO_NATIVE(sechdrs[i].sh_offset); + sechdrs[i].sh_size = TO_NATIVE(sechdrs[i].sh_size); + sechdrs[i].sh_link = TO_NATIVE(sechdrs[i].sh_link); + sechdrs[i].sh_info = TO_NATIVE(sechdrs[i].sh_info); + sechdrs[i].sh_addralign = TO_NATIVE(sechdrs[i].sh_addralign); + sechdrs[i].sh_entsize = TO_NATIVE(sechdrs[i].sh_entsize); } /* Find symbol table. */ for (i = 1; i < hdr->e_shnum; i++) { @@ -716,41 +727,37 @@ int match(const char *sym, const char * const pat[]) /* sections that we do not want to do full section mismatch check on */ static const char *section_white_list[] = - { ".debug*", ".stab*", ".note*", ".got*", ".toc*", NULL }; +{ + ".comment*", + ".debug*", + ".mdebug*", /* alpha, score, mips etc. */ + ".pdr", /* alpha, score, mips etc. */ + ".stab*", + ".note*", + ".got*", + ".toc*", + NULL +}; /* - * Is this section one we do not want to check? - * This is often debug sections. - * If we are going to check this section then - * test if section name ends with a dot and a number. - * This is used to find sections where the linker have - * appended a dot-number to make the name unique. + * This is used to find sections missing the SHF_ALLOC flag. * The cause of this is often a section specified in assembler - * without "ax" / "aw" and the same section used in .c - * code where gcc add these. + * without "ax" / "aw". */ -static int check_section(const char *modname, const char *sec) -{ - const char *e = sec + strlen(sec) - 1; - if (match(sec, section_white_list)) - return 1; - - if (*e && isdigit(*e)) { - /* consume all digits */ - while (*e && e != sec && isdigit(*e)) - e--; - if (*e == '.' && !strstr(sec, ".linkonce")) { - warn("%s (%s): unexpected section name.\n" - "The (.[number]+) following section name are " - "ld generated and not expected.\n" - "Did you forget to use \"ax\"/\"aw\" " - "in a .S file?\n" - "Note that for example <linux/init.h> contains\n" - "section definitions for use in .S files.\n\n", - modname, sec); - } +static void check_section(const char *modname, struct elf_info *elf, + Elf_Shdr *sechdr) +{ + const char *sec = sech_name(elf, sechdr); + + if (sechdr->sh_type == SHT_PROGBITS && + !(sechdr->sh_flags & SHF_ALLOC) && + !match(sec, section_white_list)) { + warn("%s (%s): unexpected non-allocatable section.\n" + "Did you forget to use \"ax\"/\"aw\" in a .S file?\n" + "Note that for example <linux/init.h> contains\n" + "section definitions for use in .S files.\n\n", + modname, sec); } - return 0; } @@ -928,8 +935,7 @@ static int section_mismatch(const char *fromsec, const char *tosec) * *probe_one, *_console, *_timer * * Pattern 3: - * Whitelist all refereces from .text.head to .init.data - * Whitelist all refereces from .text.head to .init.text + * Whitelist all references from .head.text to any init section * * Pattern 4: * Some symbols belong to init section but still it is ok to reference @@ -1359,7 +1365,7 @@ static void section_rela(const char *modname, struct elf_info *elf, fromsec = sech_name(elf, sechdr); fromsec += strlen(".rela"); /* if from section (name) is know good then skip it */ - if (check_section(modname, fromsec)) + if (match(fromsec, section_white_list)) return; for (rela = start; rela < stop; rela++) { @@ -1403,7 +1409,7 @@ static void section_rel(const char *modname, struct elf_info *elf, fromsec = sech_name(elf, sechdr); fromsec += strlen(".rel"); /* if from section (name) is know good then skip it */ - if (check_section(modname, fromsec)) + if (match(fromsec, section_white_list)) return; for (rel = start; rel < stop; rel++) { @@ -1466,6 +1472,7 @@ static void check_sec_ref(struct module *mod, const char *modname, /* Walk through all sections */ for (i = 0; i < elf->hdr->e_shnum; i++) { + check_section(modname, elf, &elf->sechdrs[i]); /* We want to process only relocation sections and not .init */ if (sechdrs[i].sh_type == SHT_RELA) section_rela(modname, elf, &elf->sechdrs[i]); @@ -1990,6 +1997,7 @@ static void read_markers(const char *fname) if (!mod->skip) add_marker(mod, marker, fmt); } + release_file(file, size); return; fail: fatal("parse error in markers list file\n"); diff --git a/scripts/setlocalversion b/scripts/setlocalversion index 47e75b69a2e..32c8554f394 100755 --- a/scripts/setlocalversion +++ b/scripts/setlocalversion @@ -10,13 +10,12 @@ cd "${1:-.}" || usage # Check for git and a git repo. if head=`git rev-parse --verify --short HEAD 2>/dev/null`; then - # Do we have an untagged version? - if git name-rev --tags HEAD | grep -E '^HEAD[[:space:]]+(.*~[0-9]*|undefined)$' > /dev/null; then - if tag=`git describe 2>/dev/null`; then - echo $tag | awk -F- '{printf("-%05d-%s", $(NF-1),$(NF))}' - else - printf '%s%s' -g $head - fi + # Do we have an untagged tag? + if atag=`git describe 2>/dev/null`; then + echo "$atag" | awk -F- '{printf("-%05d-%s", $(NF-1),$(NF))}' + # add -g${head}, if there is no usable tag + else + printf '%s%s' -g $head fi # Is this git on svn? diff --git a/scripts/tags.sh b/scripts/tags.sh index 5bd8b1003d4..4a34ec591e8 100755 --- a/scripts/tags.sh +++ b/scripts/tags.sh @@ -164,10 +164,12 @@ case "$1" in ;; "tags") + rm -f tags xtags ctags ;; "TAGS") + rm -f TAGS xtags etags ;; esac diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index ba808ef6bab..2fcad7c33ea 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -3153,7 +3153,7 @@ static int selinux_file_send_sigiotask(struct task_struct *tsk, struct fown_struct *fown, int signum) { struct file *file; - u32 sid = current_sid(); + u32 sid = task_sid(tsk); u32 perm; struct file_security_struct *fsec; diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index d4d41b3efc7..ddfb9cccf46 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c @@ -1720,14 +1720,14 @@ static bool tomoyo_policy_loader_exists(void) * policies are not loaded yet. * Thus, let do_execve() call this function everytime. */ - struct nameidata nd; + struct path path; - if (path_lookup(tomoyo_loader, LOOKUP_FOLLOW, &nd)) { + if (kern_path(tomoyo_loader, LOOKUP_FOLLOW, &path)) { printk(KERN_INFO "Not activating Mandatory Access Control now " "since %s doesn't exist.\n", tomoyo_loader); return false; } - path_put(&nd.path); + path_put(&path); return true; } diff --git a/security/tomoyo/realpath.c b/security/tomoyo/realpath.c index bf8e2b45168..40927a84cb6 100644 --- a/security/tomoyo/realpath.c +++ b/security/tomoyo/realpath.c @@ -165,11 +165,11 @@ char *tomoyo_realpath_from_path(struct path *path) */ char *tomoyo_realpath(const char *pathname) { - struct nameidata nd; + struct path path; - if (pathname && path_lookup(pathname, LOOKUP_FOLLOW, &nd) == 0) { - char *buf = tomoyo_realpath_from_path(&nd.path); - path_put(&nd.path); + if (pathname && kern_path(pathname, LOOKUP_FOLLOW, &path) == 0) { + char *buf = tomoyo_realpath_from_path(&path); + path_put(&path); return buf; } return NULL; @@ -184,11 +184,11 @@ char *tomoyo_realpath(const char *pathname) */ char *tomoyo_realpath_nofollow(const char *pathname) { - struct nameidata nd; + struct path path; - if (pathname && path_lookup(pathname, 0, &nd) == 0) { - char *buf = tomoyo_realpath_from_path(&nd.path); - path_put(&nd.path); + if (pathname && kern_path(pathname, 0, &path) == 0) { + char *buf = tomoyo_realpath_from_path(&path); + path_put(&path); return buf; } return NULL; diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index 63d088f2265..a2a792c18c4 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -249,6 +249,12 @@ static int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *substream) new_hw_ptr = hw_base + pos; } } + /* Skip the jiffies check for hardwares with BATCH flag. + * Such hardware usually just increases the position at each IRQ, + * thus it can't give any strange position. + */ + if (runtime->hw.info & SNDRV_PCM_INFO_BATCH) + goto no_jiffies_check; hdelta = new_hw_ptr - old_hw_ptr; jdelta = jiffies - runtime->hw_ptr_jiffies; if (((hdelta * HZ) / runtime->rate) > jdelta + HZ/100) { @@ -272,6 +278,7 @@ static int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *substream) hw_base -= hw_base % runtime->buffer_size; delta = 0; } + no_jiffies_check: if (delta > runtime->period_size + runtime->period_size / 2) { hw_ptr_error(substream, "Lost interrupts? " diff --git a/sound/drivers/serial-u16550.c b/sound/drivers/serial-u16550.c index b2b6d50c942..a25fb7b1f44 100644 --- a/sound/drivers/serial-u16550.c +++ b/sound/drivers/serial-u16550.c @@ -963,16 +963,11 @@ static int __devinit snd_serial_probe(struct platform_device *devptr) if (err < 0) goto _err; - sprintf(card->longname, "%s at 0x%lx, irq %d speed %d div %d outs %d ins %d adaptor %s droponfull %d", + sprintf(card->longname, "%s [%s] at %#lx, irq %d", card->shortname, - uart->base, - uart->irq, - uart->speed, - (int)uart->divisor, - outs[dev], - ins[dev], adaptor_names[uart->adaptor], - uart->drop_on_full); + uart->base, + uart->irq); snd_card_set_dev(card, &devptr->dev); diff --git a/sound/isa/msnd/msnd.c b/sound/isa/msnd/msnd.c index 906454413ed..3a1526ae172 100644 --- a/sound/isa/msnd/msnd.c +++ b/sound/isa/msnd/msnd.c @@ -438,7 +438,8 @@ static void snd_msnd_capture_reset_queue(struct snd_msnd *chip, static struct snd_pcm_hardware snd_msnd_playback = { .info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_MMAP_VALID, + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_BATCH, .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE, .rates = SNDRV_PCM_RATE_8000_48000, .rate_min = 8000, @@ -456,7 +457,8 @@ static struct snd_pcm_hardware snd_msnd_playback = { static struct snd_pcm_hardware snd_msnd_capture = { .info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_MMAP_VALID, + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_BATCH, .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE, .rates = SNDRV_PCM_RATE_8000_48000, .rate_min = 8000, diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c index a299340519d..ce3f2e90f4d 100644 --- a/sound/pci/bt87x.c +++ b/sound/pci/bt87x.c @@ -349,7 +349,8 @@ static struct snd_pcm_hardware snd_bt87x_digital_hw = { .info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID, + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_BATCH, .formats = SNDRV_PCM_FMTBIT_S16_LE, .rates = 0, /* set at runtime */ .channels_min = 2, @@ -365,7 +366,8 @@ static struct snd_pcm_hardware snd_bt87x_analog_hw = { .info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID, + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_BATCH, .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8, .rates = SNDRV_PCM_RATE_KNOT, .rate_min = ANALOG_CLOCK / CLOCK_DIV_MAX, diff --git a/sound/pci/echoaudio/indigodjx.c b/sound/pci/echoaudio/indigodjx.c index 3482ef69f49..2e44316530a 100644 --- a/sound/pci/echoaudio/indigodjx.c +++ b/sound/pci/echoaudio/indigodjx.c @@ -88,6 +88,7 @@ static struct snd_pcm_hardware pcm_hardware_skel = { .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_64000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000, .rate_min = 32000, diff --git a/sound/pci/echoaudio/indigoiox.c b/sound/pci/echoaudio/indigoiox.c index aebee27a40f..eb3819f9654 100644 --- a/sound/pci/echoaudio/indigoiox.c +++ b/sound/pci/echoaudio/indigoiox.c @@ -89,6 +89,7 @@ static struct snd_pcm_hardware pcm_hardware_skel = { .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_64000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000, .rate_min = 32000, diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 917bc5d3ac2..03b3646018a 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -4079,7 +4079,12 @@ static int stac92xx_init(struct hda_codec *codec) pinctl = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0); /* if PINCTL already set then skip */ - if (!(pinctl & AC_PINCTL_IN_EN)) { + /* Also, if both INPUT and OUTPUT are set, + * it must be a BIOS bug; need to override, too + */ + if (!(pinctl & AC_PINCTL_IN_EN) || + (pinctl & AC_PINCTL_OUT_EN)) { + pinctl &= ~AC_PINCTL_OUT_EN; pinctl |= AC_PINCTL_IN_EN; stac92xx_auto_set_pinctl(codec, nid, pinctl); diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c index 8b79969034b..7cc38a11e99 100644 --- a/sound/pci/korg1212/korg1212.c +++ b/sound/pci/korg1212/korg1212.c @@ -1238,7 +1238,8 @@ static struct snd_pcm_hardware snd_korg1212_playback_info = { .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_INTERLEAVED), + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BATCH), .formats = SNDRV_PCM_FMTBIT_S16_LE, .rates = (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000), @@ -1258,7 +1259,8 @@ static struct snd_pcm_hardware snd_korg1212_capture_info = { .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_INTERLEAVED), + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BATCH), .formats = SNDRV_PCM_FMTBIT_S16_LE, .rates = (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000), diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c index 809b233dd4a..1ef58c51c21 100644 --- a/sound/pci/via82xx.c +++ b/sound/pci/via82xx.c @@ -1687,7 +1687,7 @@ static int snd_via8233_pcmdxs_volume_put(struct snd_kcontrol *kcontrol, return change; } -static const DECLARE_TLV_DB_SCALE(db_scale_dxs, -9450, 150, 1); +static const DECLARE_TLV_DB_SCALE(db_scale_dxs, -4650, 150, 1); static struct snd_kcontrol_new snd_via8233_pcmdxs_volume_control __devinitdata = { .name = "PCM Playback Volume", diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c b/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c index 01066c95580..d057e648964 100644 --- a/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c +++ b/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c @@ -240,7 +240,8 @@ static int pdacf_pcm_prepare(struct snd_pcm_substream *subs) static struct snd_pcm_hardware pdacf_pcm_capture_hw = { .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME | - SNDRV_PCM_INFO_MMAP_VALID), + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_BATCH), .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE | SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE, diff --git a/sound/soc/au1x/dbdma2.c b/sound/soc/au1x/dbdma2.c index 30490a25914..594c6c5b783 100644 --- a/sound/soc/au1x/dbdma2.c +++ b/sound/soc/au1x/dbdma2.c @@ -82,7 +82,7 @@ static struct au1xpsc_audio_dmadata *au1xpsc_audio_pcmdma[2]; /* PCM hardware DMA capabilities - platform specific */ static const struct snd_pcm_hardware au1xpsc_pcm_hardware = { .info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_INTERLEAVED, + SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BATCH, .formats = AU1XPSC_PCM_FMTS, .period_bytes_min = AU1XPSC_PERIOD_MIN_BYTES, .period_bytes_max = 4096 * 1024 - 1, diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c index 921b205de28..df7c8c281d2 100644 --- a/sound/soc/codecs/twl4030.c +++ b/sound/soc/codecs/twl4030.c @@ -836,6 +836,12 @@ static DECLARE_TLV_DB_SCALE(analog_tlv, -2400, 200, 0); static DECLARE_TLV_DB_SCALE(output_tvl, -1200, 600, 1); /* + * Gain control for earpiece amplifier + * 0 dB to 12 dB in 6 dB steps (mute instead of -6) + */ +static DECLARE_TLV_DB_SCALE(output_ear_tvl, -600, 600, 1); + +/* * Capture gain after the ADCs * from 0 dB to 31 dB in 1 dB steps */ @@ -900,7 +906,7 @@ static const struct snd_kcontrol_new twl4030_snd_controls[] = { 4, 3, 0, output_tvl), SOC_SINGLE_TLV_TWL4030("Earpiece Playback Volume", - TWL4030_REG_EAR_CTL, 4, 3, 0, output_tvl), + TWL4030_REG_EAR_CTL, 4, 3, 0, output_ear_tvl), /* Common capture gain controls */ SOC_DOUBLE_R_TLV("TX1 Digital Capture Volume", diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c index 3b1d0993bed..0275321ff8a 100644 --- a/sound/soc/codecs/wm8350.c +++ b/sound/soc/codecs/wm8350.c @@ -968,7 +968,7 @@ static int wm8350_pcm_trigger(struct snd_pcm_substream *substream, * required for LRC in master mode. The DACs or ADCs need a * valid audio path i.e. pin -> ADC or DAC -> pin before * the LRC will be enabled in master mode. */ - if (!master && cmd != SNDRV_PCM_TRIGGER_START) + if (!master || cmd != SNDRV_PCM_TRIGGER_START) return 0; if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c index c518c3e5aa3..40cd274eb1e 100644 --- a/sound/soc/codecs/wm8990.c +++ b/sound/soc/codecs/wm8990.c @@ -729,7 +729,7 @@ SND_SOC_DAPM_MIXER_E("INMIXL", WM8990_INTDRIVBITS, WM8990_INMIXL_PWR_BIT, 0, inmixer_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), /* AINLMUX */ -SND_SOC_DAPM_MUX_E("AILNMUX", WM8990_INTDRIVBITS, WM8990_AINLMUX_PWR_BIT, 0, +SND_SOC_DAPM_MUX_E("AINLMUX", WM8990_INTDRIVBITS, WM8990_AINLMUX_PWR_BIT, 0, &wm8990_dapm_ainlmux_controls, inmixer_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), @@ -740,7 +740,7 @@ SND_SOC_DAPM_MIXER_E("INMIXR", WM8990_INTDRIVBITS, WM8990_INMIXR_PWR_BIT, 0, inmixer_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), /* AINRMUX */ -SND_SOC_DAPM_MUX_E("AIRNMUX", WM8990_INTDRIVBITS, WM8990_AINRMUX_PWR_BIT, 0, +SND_SOC_DAPM_MUX_E("AINRMUX", WM8990_INTDRIVBITS, WM8990_AINRMUX_PWR_BIT, 0, &wm8990_dapm_ainrmux_controls, inmixer_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), @@ -848,40 +848,40 @@ static const struct snd_soc_dapm_route audio_map[] = { {"LIN12 PGA", "LIN2 Switch", "LIN2"}, /* LIN34 PGA */ {"LIN34 PGA", "LIN3 Switch", "LIN3"}, - {"LIN34 PGA", "LIN4 Switch", "LIN4"}, + {"LIN34 PGA", "LIN4 Switch", "LIN4/RXN"}, /* INMIXL */ {"INMIXL", "Record Left Volume", "LOMIX"}, {"INMIXL", "LIN2 Volume", "LIN2"}, {"INMIXL", "LINPGA12 Switch", "LIN12 PGA"}, {"INMIXL", "LINPGA34 Switch", "LIN34 PGA"}, - /* AILNMUX */ - {"AILNMUX", "INMIXL Mix", "INMIXL"}, - {"AILNMUX", "DIFFINL Mix", "LIN12PGA"}, - {"AILNMUX", "DIFFINL Mix", "LIN34PGA"}, - {"AILNMUX", "RXVOICE Mix", "LIN4/RXN"}, - {"AILNMUX", "RXVOICE Mix", "RIN4/RXP"}, + /* AINLMUX */ + {"AINLMUX", "INMIXL Mix", "INMIXL"}, + {"AINLMUX", "DIFFINL Mix", "LIN12 PGA"}, + {"AINLMUX", "DIFFINL Mix", "LIN34 PGA"}, + {"AINLMUX", "RXVOICE Mix", "LIN4/RXN"}, + {"AINLMUX", "RXVOICE Mix", "RIN4/RXP"}, /* ADC */ - {"Left ADC", NULL, "AILNMUX"}, + {"Left ADC", NULL, "AINLMUX"}, /* RIN12 PGA */ {"RIN12 PGA", "RIN1 Switch", "RIN1"}, {"RIN12 PGA", "RIN2 Switch", "RIN2"}, /* RIN34 PGA */ {"RIN34 PGA", "RIN3 Switch", "RIN3"}, - {"RIN34 PGA", "RIN4 Switch", "RIN4"}, + {"RIN34 PGA", "RIN4 Switch", "RIN4/RXP"}, /* INMIXL */ {"INMIXR", "Record Right Volume", "ROMIX"}, {"INMIXR", "RIN2 Volume", "RIN2"}, {"INMIXR", "RINPGA12 Switch", "RIN12 PGA"}, {"INMIXR", "RINPGA34 Switch", "RIN34 PGA"}, - /* AIRNMUX */ - {"AIRNMUX", "INMIXR Mix", "INMIXR"}, - {"AIRNMUX", "DIFFINR Mix", "RIN12PGA"}, - {"AIRNMUX", "DIFFINR Mix", "RIN34PGA"}, - {"AIRNMUX", "RXVOICE Mix", "RIN4/RXN"}, - {"AIRNMUX", "RXVOICE Mix", "RIN4/RXP"}, + /* AINRMUX */ + {"AINRMUX", "INMIXR Mix", "INMIXR"}, + {"AINRMUX", "DIFFINR Mix", "RIN12 PGA"}, + {"AINRMUX", "DIFFINR Mix", "RIN34 PGA"}, + {"AINRMUX", "RXVOICE Mix", "LIN4/RXN"}, + {"AINRMUX", "RXVOICE Mix", "RIN4/RXP"}, /* ADC */ - {"Right ADC", NULL, "AIRNMUX"}, + {"Right ADC", NULL, "AINRMUX"}, /* LOMIX */ {"LOMIX", "LOMIX RIN3 Bypass Switch", "RIN3"}, @@ -922,7 +922,7 @@ static const struct snd_soc_dapm_route audio_map[] = { {"LOPMIX", "LOPMIX Left Mixer PGA Switch", "LOPGA"}, /* OUT3MIX */ - {"OUT3MIX", "OUT3MIX LIN4/RXP Bypass Switch", "LIN4/RXP"}, + {"OUT3MIX", "OUT3MIX LIN4/RXP Bypass Switch", "LIN4/RXN"}, {"OUT3MIX", "OUT3MIX Left Out PGA Switch", "LOPGA"}, /* OUT4MIX */ @@ -949,7 +949,7 @@ static const struct snd_soc_dapm_route audio_map[] = { /* Output Pins */ {"LON", NULL, "LONMIX"}, {"LOP", NULL, "LOPMIX"}, - {"OUT", NULL, "OUT3MIX"}, + {"OUT3", NULL, "OUT3MIX"}, {"LOUT", NULL, "LOUT PGA"}, {"SPKN", NULL, "SPKMIX"}, {"ROUT", NULL, "ROUT PGA"}, diff --git a/sound/soc/fsl/mpc5200_psc_i2s.c b/sound/soc/fsl/mpc5200_psc_i2s.c index 3aa729df27b..1111c710118 100644 --- a/sound/soc/fsl/mpc5200_psc_i2s.c +++ b/sound/soc/fsl/mpc5200_psc_i2s.c @@ -504,7 +504,8 @@ static struct snd_soc_dai psc_i2s_dai_template = { static const struct snd_pcm_hardware psc_i2s_pcm_hardware = { .info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER, + SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_BATCH, .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_BE | SNDRV_PCM_FMTBIT_S24_BE | SNDRV_PCM_FMTBIT_S32_BE, .rate_min = 8000, diff --git a/sound/soc/sh/dma-sh7760.c b/sound/soc/sh/dma-sh7760.c index 0dad3a0bb92..baddb1242c7 100644 --- a/sound/soc/sh/dma-sh7760.c +++ b/sound/soc/sh/dma-sh7760.c @@ -103,7 +103,8 @@ static struct snd_pcm_hardware camelot_pcm_hardware = { .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID), + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_BATCH), .formats = DMABRG_FMTS, .rates = DMABRG_RATES, .rate_min = 8000, diff --git a/sound/sparc/dbri.c b/sound/sparc/dbri.c index af95ff1e126..1d2e51b3f91 100644 --- a/sound/sparc/dbri.c +++ b/sound/sparc/dbri.c @@ -1975,7 +1975,8 @@ static struct snd_pcm_hardware snd_dbri_pcm_hw = { .info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID, + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_BATCH, .formats = SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW | SNDRV_PCM_FMTBIT_U8 | diff --git a/sound/usb/usx2y/usbusx2yaudio.c b/sound/usb/usx2y/usbusx2yaudio.c index 9a608fa8515..dd1ab617784 100644 --- a/sound/usb/usx2y/usbusx2yaudio.c +++ b/sound/usb/usx2y/usbusx2yaudio.c @@ -870,7 +870,8 @@ static struct snd_pcm_hardware snd_usX2Y_2c = { .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID), + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_BATCH), .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_3LE, .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000, .rate_min = 44100, |