diff options
662 files changed, 5679 insertions, 46572 deletions
diff --git a/Documentation/DocBook/device-drivers.tmpl b/Documentation/DocBook/device-drivers.tmpl index 2f7fd436084..9c27e5125dd 100644 --- a/Documentation/DocBook/device-drivers.tmpl +++ b/Documentation/DocBook/device-drivers.tmpl @@ -102,9 +102,12 @@ X!Iinclude/linux/kobject.h  !Iinclude/linux/device.h       </sect1>       <sect1><title>Device Drivers Base</title> +!Idrivers/base/init.c  !Edrivers/base/driver.c  !Edrivers/base/core.c +!Edrivers/base/syscore.c  !Edrivers/base/class.c +!Idrivers/base/node.c  !Edrivers/base/firmware_class.c  !Edrivers/base/transport_class.c  <!-- Cannot be included, because @@ -113,7 +116,7 @@ X!Iinclude/linux/kobject.h       exceed allowed 44 characters maximum  X!Edrivers/base/attribute_container.c  --> -!Edrivers/base/sys.c +!Edrivers/base/dd.c  <!--  X!Edrivers/base/interface.c  --> @@ -121,6 +124,11 @@ X!Edrivers/base/interface.c  !Edrivers/base/platform.c  !Edrivers/base/bus.c       </sect1> +     <sect1><title>Device Drivers DMA Management</title> +!Edrivers/base/dma-buf.c +!Edrivers/base/dma-coherent.c +!Edrivers/base/dma-mapping.c +     </sect1>       <sect1><title>Device Drivers Power Management</title>  !Edrivers/base/power/main.c       </sect1> @@ -219,7 +227,7 @@ X!Isound/sound_firmware.c    <chapter id="uart16x50">       <title>16x50 UART Driver</title>  !Edrivers/tty/serial/serial_core.c -!Edrivers/tty/serial/8250.c +!Edrivers/tty/serial/8250/8250.c    </chapter>    <chapter id="fbdev"> diff --git a/Documentation/IRQ-domain.txt b/Documentation/IRQ-domain.txt new file mode 100644 index 00000000000..27dcaabfb4d --- /dev/null +++ b/Documentation/IRQ-domain.txt @@ -0,0 +1,117 @@ +irq_domain interrupt number mapping library + +The current design of the Linux kernel uses a single large number +space where each separate IRQ source is assigned a different number. +This is simple when there is only one interrupt controller, but in +systems with multiple interrupt controllers the kernel must ensure +that each one gets assigned non-overlapping allocations of Linux +IRQ numbers. + +The irq_alloc_desc*() and irq_free_desc*() APIs provide allocation of +irq numbers, but they don't provide any support for reverse mapping of +the controller-local IRQ (hwirq) number into the Linux IRQ number +space. + +The irq_domain library adds mapping between hwirq and IRQ numbers on +top of the irq_alloc_desc*() API.  An irq_domain to manage mapping is +preferred over interrupt controller drivers open coding their own +reverse mapping scheme. + +irq_domain also implements translation from Device Tree interrupt +specifiers to hwirq numbers, and can be easily extended to support +other IRQ topology data sources. + +=== irq_domain usage === +An interrupt controller driver creates and registers an irq_domain by +calling one of the irq_domain_add_*() functions (each mapping method +has a different allocator function, more on that later).  The function +will return a pointer to the irq_domain on success.  The caller must +provide the allocator function with an irq_domain_ops structure with +the .map callback populated as a minimum. + +In most cases, the irq_domain will begin empty without any mappings +between hwirq and IRQ numbers.  Mappings are added to the irq_domain +by calling irq_create_mapping() which accepts the irq_domain and a +hwirq number as arguments.  If a mapping for the hwirq doesn't already +exist then it will allocate a new Linux irq_desc, associate it with +the hwirq, and call the .map() callback so the driver can perform any +required hardware setup. + +When an interrupt is received, irq_find_mapping() function should +be used to find the Linux IRQ number from the hwirq number. + +If the driver has the Linux IRQ number or the irq_data pointer, and +needs to know the associated hwirq number (such as in the irq_chip +callbacks) then it can be directly obtained from irq_data->hwirq. + +=== Types of irq_domain mappings === +There are several mechanisms available for reverse mapping from hwirq +to Linux irq, and each mechanism uses a different allocation function. +Which reverse map type should be used depends on the use case.  Each +of the reverse map types are described below: + +==== Linear ==== +irq_domain_add_linear() + +The linear reverse map maintains a fixed size table indexed by the +hwirq number.  When a hwirq is mapped, an irq_desc is allocated for +the hwirq, and the IRQ number is stored in the table. + +The Linear map is a good choice when the maximum number of hwirqs is +fixed and a relatively small number (~ < 256).  The advantages of this +map are fixed time lookup for IRQ numbers, and irq_descs are only +allocated for in-use IRQs.  The disadvantage is that the table must be +as large as the largest possible hwirq number. + +The majority of drivers should use the linear map. + +==== Tree ==== +irq_domain_add_tree() + +The irq_domain maintains a radix tree map from hwirq numbers to Linux +IRQs.  When an hwirq is mapped, an irq_desc is allocated and the +hwirq is used as the lookup key for the radix tree. + +The tree map is a good choice if the hwirq number can be very large +since it doesn't need to allocate a table as large as the largest +hwirq number.  The disadvantage is that hwirq to IRQ number lookup is +dependent on how many entries are in the table. + +Very few drivers should need this mapping.  At the moment, powerpc +iseries is the only user. + +==== No Map ===- +irq_domain_add_nomap() + +The No Map mapping is to be used when the hwirq number is +programmable in the hardware.  In this case it is best to program the +Linux IRQ number into the hardware itself so that no mapping is +required.  Calling irq_create_direct_mapping() will allocate a Linux +IRQ number and call the .map() callback so that driver can program the +Linux IRQ number into the hardware. + +Most drivers cannot use this mapping. + +==== Legacy ==== +irq_domain_add_legacy() +irq_domain_add_legacy_isa() + +The Legacy mapping is a special case for drivers that already have a +range of irq_descs allocated for the hwirqs.  It is used when the +driver cannot be immediately converted to use the linear mapping.  For +example, many embedded system board support files use a set of #defines +for IRQ numbers that are passed to struct device registrations.  In that +case the Linux IRQ numbers cannot be dynamically assigned and the legacy +mapping should be used. + +The legacy map assumes a contiguous range of IRQ numbers has already +been allocated for the controller and that the IRQ number can be +calculated by adding a fixed offset to the hwirq number, and +visa-versa.  The disadvantage is that it requires the interrupt +controller to manage IRQ allocations and it requires an irq_desc to be +allocated for every hwirq, even if it is unused. + +The legacy map should only be used if fixed IRQ mappings must be +supported.  For example, ISA controllers would use the legacy map for +mapping Linux IRQs 0-15 so that existing ISA drivers get the correct IRQ +numbers. diff --git a/Documentation/input/event-codes.txt b/Documentation/input/event-codes.txt index 23fcb05175b..53305bd0818 100644 --- a/Documentation/input/event-codes.txt +++ b/Documentation/input/event-codes.txt @@ -17,11 +17,11 @@ reports supported by a device are also provided by sysfs in  class/input/event*/device/capabilities/, and the properties of a device are  provided in class/input/event*/device/properties. -Types: -========== -Types are groupings of codes under a logical input construct. Each type has a -set of applicable codes to be used in generating events. See the Codes section -for details on valid codes for each type. +Event types: +=========== +Event types are groupings of codes under a logical input construct. Each +type has a set of applicable codes to be used in generating events. See the +Codes section for details on valid codes for each type.  * EV_SYN:    - Used as markers to separate events. Events may be separated in time or in @@ -63,9 +63,9 @@ for details on valid codes for each type.  * EV_FF_STATUS:    - Used to receive force feedback device status. -Codes: -========== -Codes define the precise type of event. +Event codes: +=========== +Event codes define the precise type of event.  EV_SYN:  ---------- @@ -220,6 +220,56 @@ EV_PWR:  EV_PWR events are a special type of event used specifically for power  mangement. Its usage is not well defined. To be addressed later. +Device properties: +================= +Normally, userspace sets up an input device based on the data it emits, +i.e., the event types. In the case of two devices emitting the same event +types, additional information can be provided in the form of device +properties. + +INPUT_PROP_DIRECT + INPUT_PROP_POINTER: +-------------------------------------- +The INPUT_PROP_DIRECT property indicates that device coordinates should be +directly mapped to screen coordinates (not taking into account trivial +transformations, such as scaling, flipping and rotating). Non-direct input +devices require non-trivial transformation, such as absolute to relative +transformation for touchpads. Typical direct input devices: touchscreens, +drawing tablets; non-direct devices: touchpads, mice. + +The INPUT_PROP_POINTER property indicates that the device is not transposed +on the screen and thus requires use of an on-screen pointer to trace user's +movements.  Typical pointer devices: touchpads, tablets, mice; non-pointer +device: touchscreen. + +If neither INPUT_PROP_DIRECT or INPUT_PROP_POINTER are set, the property is +considered undefined and the device type should be deduced in the +traditional way, using emitted event types. + +INPUT_PROP_BUTTONPAD: +-------------------- +For touchpads where the button is placed beneath the surface, such that +pressing down on the pad causes a button click, this property should be +set. Common in clickpad notebooks and macbooks from 2009 and onwards. + +Originally, the buttonpad property was coded into the bcm5974 driver +version field under the name integrated button. For backwards +compatibility, both methods need to be checked in userspace. + +INPUT_PROP_SEMI_MT: +------------------ +Some touchpads, most common between 2008 and 2011, can detect the presence +of multiple contacts without resolving the individual positions; only the +number of contacts and a rectangular shape is known. For such +touchpads, the semi-mt property should be set. + +Depending on the device, the rectangle may enclose all touches, like a +bounding box, or just some of them, for instance the two most recent +touches. The diversity makes the rectangle of limited use, but some +gestures can normally be extracted from it. + +If INPUT_PROP_SEMI_MT is not set, the device is assumed to be a true MT +device. +  Guidelines:  ==========  The guidelines below ensure proper single-touch and multi-finger functionality. @@ -240,6 +290,8 @@ used to report when a touch is active on the screen.  BTN_{MOUSE,LEFT,MIDDLE,RIGHT} must not be reported as the result of touch  contact. BTN_TOOL_<name> events should be reported where possible. +For new hardware, INPUT_PROP_DIRECT should be set. +  Trackpads:  ----------  Legacy trackpads that only provide relative position information must report @@ -250,6 +302,8 @@ location of the touch. BTN_TOUCH should be used to report when a touch is active  on the trackpad. Where multi-finger support is available, BTN_TOOL_<name> should  be used to report the number of touches active on the trackpad. +For new hardware, INPUT_PROP_POINTER should be set. +  Tablets:  ----------  BTN_TOOL_<name> events must be reported when a stylus or other tool is active on @@ -260,3 +314,5 @@ button may be used for buttons on the tablet except BTN_{MOUSE,LEFT}.  BTN_{0,1,2,etc} are good generic codes for unlabeled buttons. Do not use  meaningful buttons, like BTN_FORWARD, unless the button is labeled for that  purpose on the device. + +For new hardware, both INPUT_PROP_DIRECT and INPUT_PROP_POINTER should be set. diff --git a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt index 8c20fbd8b42..6d78841fd41 100644 --- a/Documentation/sysctl/kernel.txt +++ b/Documentation/sysctl/kernel.txt @@ -601,6 +601,8 @@ can be ORed together:          instead of using the one provided by the hardware.   512 - A kernel warning has occurred.  1024 - A module from drivers/staging was loaded. +2048 - The system is working around a severe firmware bug. +4096 - An out-of-tree module has been loaded.  ============================================================== diff --git a/MAINTAINERS b/MAINTAINERS index a1fce9a3ab2..57dd0f56cd3 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -159,7 +159,7 @@ S:	Maintained  F:	drivers/net/ethernet/realtek/r8169.c  8250/16?50 (AND CLONE UARTS) SERIAL DRIVER -M:	Greg Kroah-Hartman <gregkh@suse.de> +M:	Greg Kroah-Hartman <gregkh@linuxfoundation.org>  L:	linux-serial@vger.kernel.org  W:	http://serial.sourceforge.net  S:	Maintained @@ -789,12 +789,6 @@ F:	arch/arm/mach-mx*/  F:	arch/arm/mach-imx/  F:	arch/arm/plat-mxc/ -ARM/FREESCALE IMX51 -M:	Amit Kucheria <amit.kucheria@canonical.com> -L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) -S:	Maintained -F:	arch/arm/mach-mx5/ -  ARM/FREESCALE IMX6  M:	Shawn Guo <shawn.guo@linaro.org>  L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) @@ -1783,9 +1777,9 @@ X:	net/wireless/wext*  CHAR and MISC DRIVERS  M:	Arnd Bergmann <arnd@arndb.de> -M:	Greg Kroah-Hartman <greg@kroah.com> +M:	Greg Kroah-Hartman <gregkh@linuxfoundation.org>  T:	git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc.git -S:	Maintained +S:	Supported  F:	drivers/char/*  F:	drivers/misc/* @@ -2287,7 +2281,7 @@ F:	drivers/acpi/dock.c  DOCUMENTATION  M:	Randy Dunlap <rdunlap@xenotime.net>  L:	linux-doc@vger.kernel.org -T:	quilt http://userweb.kernel.org/~rdunlap/kernel-doc-patches/current/ +T:	quilt http://xenotime.net/kernel-doc-patches/current/  S:	Maintained  F:	Documentation/ @@ -2320,7 +2314,7 @@ F:	lib/lru_cache.c  F:	Documentation/blockdev/drbd/  DRIVER CORE, KOBJECTS, DEBUGFS AND SYSFS -M:	Greg Kroah-Hartman <gregkh@suse.de> +M:	Greg Kroah-Hartman <gregkh@linuxfoundation.org>  T:	git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core-2.6.git  S:	Supported  F:	Documentation/kobject.txt @@ -3324,6 +3318,12 @@ S:	Maintained  F:	net/ieee802154/  F:	drivers/ieee802154/ +IIO SUBSYSTEM AND DRIVERS +M:	Jonathan Cameron <jic23@cam.ac.uk> +L:	linux-iio@vger.kernel.org +S:	Maintained +F:	drivers/staging/iio/ +  IKANOS/ADI EAGLE ADSL USB DRIVER  M:	Matthieu Castet <castet.matthieu@free.fr>  M:	Stanislaw Gruszka <stf_xl@wp.pl> @@ -3640,6 +3640,15 @@ S:	Maintained  T:	git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git irq/core  F:	kernel/irq/ +IRQ DOMAINS (IRQ NUMBER MAPPING LIBRARY) +M:	Benjamin Herrenschmidt <benh@kernel.crashing.org> +M:	Grant Likely <grant.likely@secretlab.ca> +T:	git git://git.secretlab.ca/git/linux-2.6.git irqdomain/next +S:	Maintained +F:	Documentation/IRQ-domain.txt +F:	include/linux/irqdomain.h +F:	kernel/irq/irqdomain.c +  ISAPNP  M:	Jaroslav Kysela <perex@perex.cz>  S:	Maintained @@ -3992,11 +4001,11 @@ M:	Rusty Russell <rusty@rustcorp.com.au>  L:	lguest@lists.ozlabs.org  W:	http://lguest.ozlabs.org/  S:	Odd Fixes -F:	Documentation/virtual/lguest/ +F:	arch/x86/include/asm/lguest*.h  F:	arch/x86/lguest/  F:	drivers/lguest/  F:	include/linux/lguest*.h -F:	arch/x86/include/asm/lguest*.h +F:	tools/lguest/  LINUX FOR IBM pSERIES (RS/6000)  M:	Paul Mackerras <paulus@au.ibm.com> @@ -4136,7 +4145,7 @@ L:	linux-ntfs-dev@lists.sourceforge.net  W:	http://www.linux-ntfs.org/content/view/19/37/  S:	Maintained  F:	Documentation/ldm.txt -F:	fs/partitions/ldm.* +F:	block/partitions/ldm.*  LogFS  M:	Joern Engel <joern@logfs.org> @@ -5633,7 +5642,7 @@ W:	http://www.ibm.com/developerworks/linux/linux390/  S:	Supported  F:	arch/s390/  F:	drivers/s390/ -F:	fs/partitions/ibm.c +F:	block/partitions/ibm.c  F:	Documentation/s390/  F:	Documentation/DocBook/s390* @@ -6276,15 +6285,15 @@ S:	Maintained  F:	arch/alpha/kernel/srm_env.c  STABLE BRANCH -M:	Greg Kroah-Hartman <greg@kroah.com> +M:	Greg Kroah-Hartman <gregkh@linuxfoundation.org>  L:	stable@vger.kernel.org -S:	Maintained +S:	Supported  STAGING SUBSYSTEM -M:	Greg Kroah-Hartman <gregkh@suse.de> +M:	Greg Kroah-Hartman <gregkh@linuxfoundation.org>  T:	git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging.git  L:	devel@driverdev.osuosl.org -S:	Maintained +S:	Supported  F:	drivers/staging/  STAGING - AGERE HERMES II and II.5 WIRELESS DRIVERS @@ -6396,11 +6405,6 @@ M:	Omar Ramirez Luna <omar.ramirez@ti.com>  S:	Odd Fixes  F:	drivers/staging/tidspbridge/ -STAGING - TRIDENT TVMASTER TMxxxx USB VIDEO CAPTURE DRIVERS -L:	linux-media@vger.kernel.org -S:	Odd Fixes -F:	drivers/staging/tm6000/ -  STAGING - USB ENE SM/MS CARD READER DRIVER  M:	Al Cho <acho@novell.com>  S:	Odd Fixes @@ -6669,8 +6673,8 @@ S:	Maintained  K:	^Subject:.*(?i)trivial  TTY LAYER -M:	Greg Kroah-Hartman <gregkh@suse.de> -S:	Maintained +M:	Greg Kroah-Hartman <gregkh@linuxfoundation.org> +S:	Supported  T:	git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty-2.6.git  F:	drivers/tty/  F:	drivers/tty/serial/serial_core.c @@ -6958,7 +6962,7 @@ S:	Maintained  F:	drivers/usb/serial/digi_acceleport.c  USB SERIAL DRIVER -M:	Greg Kroah-Hartman <gregkh@suse.de> +M:	Greg Kroah-Hartman <gregkh@linuxfoundation.org>  L:	linux-usb@vger.kernel.org  S:	Supported  F:	Documentation/usb/usb-serial.txt @@ -6973,9 +6977,8 @@ S:	Maintained  F:	drivers/usb/serial/empeg.c  USB SERIAL KEYSPAN DRIVER -M:	Greg Kroah-Hartman <greg@kroah.com> +M:	Greg Kroah-Hartman <gregkh@linuxfoundation.org>  L:	linux-usb@vger.kernel.org -W:	http://www.kroah.com/linux/  S:	Maintained  F:	drivers/usb/serial/*keyspan* @@ -7003,7 +7006,7 @@ F:	Documentation/video4linux/sn9c102.txt  F:	drivers/media/video/sn9c102/  USB SUBSYSTEM -M:	Greg Kroah-Hartman <gregkh@suse.de> +M:	Greg Kroah-Hartman <gregkh@linuxfoundation.org>  L:	linux-usb@vger.kernel.org  W:	http://www.linux-usb.org  T:	git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6.git @@ -7090,7 +7093,7 @@ F:	fs/hppfs/  USERSPACE I/O (UIO)  M:	"Hans J. Koch" <hjk@hansjkoch.de> -M:	Greg Kroah-Hartman <gregkh@suse.de> +M:	Greg Kroah-Hartman <gregkh@linuxfoundation.org>  S:	Maintained  F:	Documentation/DocBook/uio-howto.tmpl  F:	drivers/uio/ @@ -1,7 +1,7 @@  VERSION = 3  PATCHLEVEL = 3  SUBLEVEL = 0 -EXTRAVERSION = -rc2 +EXTRAVERSION = -rc3  NAME = Saber-toothed Squirrel  # *DOCUMENTATION* diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c index c47d6199b78..f0783be1735 100644 --- a/arch/arm/common/gic.c +++ b/arch/arm/common/gic.c @@ -51,7 +51,6 @@ union gic_base {  };  struct gic_chip_data { -	unsigned int irq_offset;  	union gic_base dist_base;  	union gic_base cpu_base;  #ifdef CONFIG_CPU_PM @@ -61,9 +60,7 @@ struct gic_chip_data {  	u32 __percpu *saved_ppi_enable;  	u32 __percpu *saved_ppi_conf;  #endif -#ifdef CONFIG_IRQ_DOMAIN -	struct irq_domain domain; -#endif +	struct irq_domain *domain;  	unsigned int gic_irqs;  #ifdef CONFIG_GIC_NON_BANKED  	void __iomem *(*get_base)(union gic_base *); @@ -282,7 +279,7 @@ asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs)  		irqnr = irqstat & ~0x1c00;  		if (likely(irqnr > 15 && irqnr < 1021)) { -			irqnr = irq_domain_to_irq(&gic->domain, irqnr); +			irqnr = irq_find_mapping(gic->domain, irqnr);  			handle_IRQ(irqnr, regs);  			continue;  		} @@ -314,8 +311,8 @@ static void gic_handle_cascade_irq(unsigned int irq, struct irq_desc *desc)  	if (gic_irq == 1023)  		goto out; -	cascade_irq = irq_domain_to_irq(&chip_data->domain, gic_irq); -	if (unlikely(gic_irq < 32 || gic_irq > 1020 || cascade_irq >= NR_IRQS)) +	cascade_irq = irq_find_mapping(chip_data->domain, gic_irq); +	if (unlikely(gic_irq < 32 || gic_irq > 1020))  		do_bad_IRQ(cascade_irq, desc);  	else  		generic_handle_irq(cascade_irq); @@ -348,10 +345,9 @@ void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq)  static void __init gic_dist_init(struct gic_chip_data *gic)  { -	unsigned int i, irq; +	unsigned int i;  	u32 cpumask;  	unsigned int gic_irqs = gic->gic_irqs; -	struct irq_domain *domain = &gic->domain;  	void __iomem *base = gic_data_dist_base(gic);  	u32 cpu = cpu_logical_map(smp_processor_id()); @@ -386,23 +382,6 @@ static void __init gic_dist_init(struct gic_chip_data *gic)  	for (i = 32; i < gic_irqs; i += 32)  		writel_relaxed(0xffffffff, base + GIC_DIST_ENABLE_CLEAR + i * 4 / 32); -	/* -	 * Setup the Linux IRQ subsystem. -	 */ -	irq_domain_for_each_irq(domain, i, irq) { -		if (i < 32) { -			irq_set_percpu_devid(irq); -			irq_set_chip_and_handler(irq, &gic_chip, -						 handle_percpu_devid_irq); -			set_irq_flags(irq, IRQF_VALID | IRQF_NOAUTOEN); -		} else { -			irq_set_chip_and_handler(irq, &gic_chip, -						 handle_fasteoi_irq); -			set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); -		} -		irq_set_chip_data(irq, gic); -	} -  	writel_relaxed(1, base + GIC_DIST_CTRL);  } @@ -618,11 +597,27 @@ static void __init gic_pm_init(struct gic_chip_data *gic)  }  #endif -#ifdef CONFIG_OF -static int gic_irq_domain_dt_translate(struct irq_domain *d, -				       struct device_node *controller, -				       const u32 *intspec, unsigned int intsize, -				       unsigned long *out_hwirq, unsigned int *out_type) +static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq, +				irq_hw_number_t hw) +{ +	if (hw < 32) { +		irq_set_percpu_devid(irq); +		irq_set_chip_and_handler(irq, &gic_chip, +					 handle_percpu_devid_irq); +		set_irq_flags(irq, IRQF_VALID | IRQF_NOAUTOEN); +	} else { +		irq_set_chip_and_handler(irq, &gic_chip, +					 handle_fasteoi_irq); +		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); +	} +	irq_set_chip_data(irq, d->host_data); +	return 0; +} + +static int gic_irq_domain_xlate(struct irq_domain *d, +				struct device_node *controller, +				const u32 *intspec, unsigned int intsize, +				unsigned long *out_hwirq, unsigned int *out_type)  {  	if (d->of_node != controller)  		return -EINVAL; @@ -639,26 +634,23 @@ static int gic_irq_domain_dt_translate(struct irq_domain *d,  	*out_type = intspec[2] & IRQ_TYPE_SENSE_MASK;  	return 0;  } -#endif  const struct irq_domain_ops gic_irq_domain_ops = { -#ifdef CONFIG_OF -	.dt_translate = gic_irq_domain_dt_translate, -#endif +	.map = gic_irq_domain_map, +	.xlate = gic_irq_domain_xlate,  };  void __init gic_init_bases(unsigned int gic_nr, int irq_start,  			   void __iomem *dist_base, void __iomem *cpu_base, -			   u32 percpu_offset) +			   u32 percpu_offset, struct device_node *node)  { +	irq_hw_number_t hwirq_base;  	struct gic_chip_data *gic; -	struct irq_domain *domain; -	int gic_irqs; +	int gic_irqs, irq_base;  	BUG_ON(gic_nr >= MAX_GIC_NR);  	gic = &gic_data[gic_nr]; -	domain = &gic->domain;  #ifdef CONFIG_GIC_NON_BANKED  	if (percpu_offset) { /* Frankein-GIC without banked registers... */  		unsigned int cpu; @@ -694,10 +686,10 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start,  	 * For primary GICs, skip over SGIs.  	 * For secondary GICs, skip over PPIs, too.  	 */ -	domain->hwirq_base = 32; +	hwirq_base = 32;  	if (gic_nr == 0) {  		if ((irq_start & 31) > 0) { -			domain->hwirq_base = 16; +			hwirq_base = 16;  			if (irq_start != -1)  				irq_start = (irq_start & ~31) + 16;  		} @@ -713,17 +705,17 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start,  		gic_irqs = 1020;  	gic->gic_irqs = gic_irqs; -	domain->nr_irq = gic_irqs - domain->hwirq_base; -	domain->irq_base = irq_alloc_descs(irq_start, 16, domain->nr_irq, -					   numa_node_id()); -	if (IS_ERR_VALUE(domain->irq_base)) { +	gic_irqs -= hwirq_base; /* calculate # of irqs to allocate */ +	irq_base = irq_alloc_descs(irq_start, 16, gic_irqs, numa_node_id()); +	if (IS_ERR_VALUE(irq_base)) {  		WARN(1, "Cannot allocate irq_descs @ IRQ%d, assuming pre-allocated\n",  		     irq_start); -		domain->irq_base = irq_start; +		irq_base = irq_start;  	} -	domain->priv = gic; -	domain->ops = &gic_irq_domain_ops; -	irq_domain_add(domain); +	gic->domain = irq_domain_add_legacy(node, gic_irqs, irq_base, +				    hwirq_base, &gic_irq_domain_ops, gic); +	if (WARN_ON(!gic->domain)) +		return;  	gic_chip.flags |= gic_arch_extn.flags;  	gic_dist_init(gic); @@ -768,7 +760,6 @@ int __init gic_of_init(struct device_node *node, struct device_node *parent)  	void __iomem *dist_base;  	u32 percpu_offset;  	int irq; -	struct irq_domain *domain = &gic_data[gic_cnt].domain;  	if (WARN_ON(!node))  		return -ENODEV; @@ -782,9 +773,7 @@ int __init gic_of_init(struct device_node *node, struct device_node *parent)  	if (of_property_read_u32(node, "cpu-offset", &percpu_offset))  		percpu_offset = 0; -	domain->of_node = of_node_get(node); - -	gic_init_bases(gic_cnt, -1, dist_base, cpu_base, percpu_offset); +	gic_init_bases(gic_cnt, -1, dist_base, cpu_base, percpu_offset, node);  	if (parent) {  		irq = irq_of_parse_and_map(node, 0); diff --git a/arch/arm/common/vic.c b/arch/arm/common/vic.c index dcb004a804c..7a66311f306 100644 --- a/arch/arm/common/vic.c +++ b/arch/arm/common/vic.c @@ -56,7 +56,7 @@ struct vic_device {  	u32		int_enable;  	u32		soft_int;  	u32		protect; -	struct irq_domain domain; +	struct irq_domain *domain;  };  /* we cannot allocate memory when VICs are initially registered */ @@ -192,14 +192,8 @@ static void __init vic_register(void __iomem *base, unsigned int irq,  	v->resume_sources = resume_sources;  	v->irq = irq;  	vic_id++; - -	v->domain.irq_base = irq; -	v->domain.nr_irq = 32; -#ifdef CONFIG_OF_IRQ -	v->domain.of_node = of_node_get(node); -#endif /* CONFIG_OF */ -	v->domain.ops = &irq_domain_simple_ops; -	irq_domain_add(&v->domain); +	v->domain = irq_domain_add_legacy(node, 32, irq, 0, +					  &irq_domain_simple_ops, v);  }  static void vic_ack_irq(struct irq_data *d) @@ -348,7 +342,7 @@ static void __init vic_init_st(void __iomem *base, unsigned int irq_start,  	vic_register(base, irq_start, 0, node);  } -static void __init __vic_init(void __iomem *base, unsigned int irq_start, +void __init __vic_init(void __iomem *base, unsigned int irq_start,  			      u32 vic_sources, u32 resume_sources,  			      struct device_node *node)  { @@ -444,7 +438,7 @@ static int handle_one_vic(struct vic_device *vic, struct pt_regs *regs)  	stat = readl_relaxed(vic->base + VIC_IRQ_STATUS);  	while (stat) {  		irq = ffs(stat) - 1; -		handle_IRQ(irq_domain_to_irq(&vic->domain, irq), regs); +		handle_IRQ(irq_find_mapping(vic->domain, irq), regs);  		stat &= ~(1 << irq);  		handled = 1;  	} diff --git a/arch/arm/include/asm/hardware/gic.h b/arch/arm/include/asm/hardware/gic.h index 4bdfe001869..4b1ce6cd477 100644 --- a/arch/arm/include/asm/hardware/gic.h +++ b/arch/arm/include/asm/hardware/gic.h @@ -39,7 +39,7 @@ struct device_node;  extern struct irq_chip gic_arch_extn;  void gic_init_bases(unsigned int, int, void __iomem *, void __iomem *, -		    u32 offset); +		    u32 offset, struct device_node *);  int gic_of_init(struct device_node *node, struct device_node *parent);  void gic_secondary_init(unsigned int);  void gic_handle_irq(struct pt_regs *regs); @@ -49,7 +49,7 @@ void gic_raise_softirq(const struct cpumask *mask, unsigned int irq);  static inline void gic_init(unsigned int nr, int start,  			    void __iomem *dist , void __iomem *cpu)  { -	gic_init_bases(nr, start, dist, cpu, 0); +	gic_init_bases(nr, start, dist, cpu, 0, NULL);  }  #endif diff --git a/arch/arm/include/asm/hardware/vic.h b/arch/arm/include/asm/hardware/vic.h index f42ebd61959..e14af1a1a32 100644 --- a/arch/arm/include/asm/hardware/vic.h +++ b/arch/arm/include/asm/hardware/vic.h @@ -47,6 +47,8 @@  struct device_node;  struct pt_regs; +void __vic_init(void __iomem *base, unsigned int irq_start, u32 vic_sources, +		u32 resume_sources, struct device_node *node);  void vic_init(void __iomem *base, unsigned int irq_start, u32 vic_sources, u32 resume_sources);  int vic_of_init(struct device_node *node, struct device_node *parent);  void vic_handle_irq(struct pt_regs *regs); diff --git a/arch/arm/include/asm/tlb.h b/arch/arm/include/asm/tlb.h index 5d3ed7e3856..314d4664eae 100644 --- a/arch/arm/include/asm/tlb.h +++ b/arch/arm/include/asm/tlb.h @@ -198,7 +198,15 @@ static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte,  	unsigned long addr)  {  	pgtable_page_dtor(pte); -	tlb_add_flush(tlb, addr); + +	/* +	 * With the classic ARM MMU, a pte page has two corresponding pmd +	 * entries, each covering 1MB. +	 */ +	addr &= PMD_MASK; +	tlb_add_flush(tlb, addr + SZ_1M - PAGE_SIZE); +	tlb_add_flush(tlb, addr + SZ_1M); +  	tlb_remove_page(tlb, pte);  } diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index 3a456c6c700..be16a48007b 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -790,7 +790,7 @@ __kuser_cmpxchg64:				@ 0xffff0f60  	smp_dmb	arm  	rsbs	r0, r3, #0			@ set returned val and C flag  	ldmfd	sp!, {r4, r5, r6, r7} -	bx	lr +	usr_ret	lr  #elif !defined(CONFIG_SMP) diff --git a/arch/arm/kernel/perf_event_v7.c b/arch/arm/kernel/perf_event_v7.c index 460bbbb6b88..6933244c68f 100644 --- a/arch/arm/kernel/perf_event_v7.c +++ b/arch/arm/kernel/perf_event_v7.c @@ -469,6 +469,20 @@ static const unsigned armv7_a5_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]  			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,  		},  	}, +	[C(NODE)] = { +		[C(OP_READ)] = { +			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED, +			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED, +		}, +		[C(OP_WRITE)] = { +			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED, +			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED, +		}, +		[C(OP_PREFETCH)] = { +			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED, +			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED, +		}, +	},  };  /* @@ -579,6 +593,20 @@ static const unsigned armv7_a15_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]  			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,  		},  	}, +	[C(NODE)] = { +		[C(OP_READ)] = { +			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED, +			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED, +		}, +		[C(OP_WRITE)] = { +			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED, +			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED, +		}, +		[C(OP_PREFETCH)] = { +			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED, +			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED, +		}, +	},  };  /* diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c index e1d5e1929fb..e33870ff0ac 100644 --- a/arch/arm/kernel/ptrace.c +++ b/arch/arm/kernel/ptrace.c @@ -699,10 +699,13 @@ static int vfp_set(struct task_struct *target,  {  	int ret;  	struct thread_info *thread = task_thread_info(target); -	struct vfp_hard_struct new_vfp = thread->vfpstate.hard; +	struct vfp_hard_struct new_vfp;  	const size_t user_fpregs_offset = offsetof(struct user_vfp, fpregs);  	const size_t user_fpscr_offset = offsetof(struct user_vfp, fpscr); +	vfp_sync_hwstate(thread); +	new_vfp = thread->vfpstate.hard; +  	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,  				  &new_vfp.fpregs,  				  user_fpregs_offset, @@ -723,9 +726,8 @@ static int vfp_set(struct task_struct *target,  	if (ret)  		return ret; -	vfp_sync_hwstate(thread); -	thread->vfpstate.hard = new_vfp;  	vfp_flush_hwstate(thread); +	thread->vfpstate.hard = new_vfp;  	return 0;  } diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c index 0340224cf73..9e617bd4a14 100644 --- a/arch/arm/kernel/signal.c +++ b/arch/arm/kernel/signal.c @@ -227,6 +227,8 @@ static int restore_vfp_context(struct vfp_sigframe __user *frame)  	if (magic != VFP_MAGIC || size != VFP_STORAGE_SIZE)  		return -EINVAL; +	vfp_flush_hwstate(thread); +  	/*  	 * Copy the floating point registers. There can be unused  	 * registers see asm/hwcap.h for details. @@ -251,9 +253,6 @@ static int restore_vfp_context(struct vfp_sigframe __user *frame)  	__get_user_error(h->fpinst, &frame->ufp_exc.fpinst, err);  	__get_user_error(h->fpinst2, &frame->ufp_exc.fpinst2, err); -	if (!err) -		vfp_flush_hwstate(thread); -  	return err ? -EFAULT : 0;  } diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index 99a57270250..f84dfe67724 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c @@ -266,6 +266,7 @@ void die(const char *str, struct pt_regs *regs, int err)  {  	struct thread_info *thread = current_thread_info();  	int ret; +	enum bug_trap_type bug_type = BUG_TRAP_TYPE_NONE;  	oops_enter(); @@ -273,7 +274,9 @@ void die(const char *str, struct pt_regs *regs, int err)  	console_verbose();  	bust_spinlocks(1);  	if (!user_mode(regs)) -		report_bug(regs->ARM_pc, regs); +		bug_type = report_bug(regs->ARM_pc, regs); +	if (bug_type != BUG_TRAP_TYPE_NONE) +		str = "Oops - BUG";  	ret = __die(str, err, thread, regs);  	if (regs && kexec_should_crash(thread->task)) diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S index 1e19691e040..43a31fb0631 100644 --- a/arch/arm/kernel/vmlinux.lds.S +++ b/arch/arm/kernel/vmlinux.lds.S @@ -10,6 +10,7 @@  #include <asm/page.h>  #define PROC_INFO							\ +	. = ALIGN(4);							\  	VMLINUX_SYMBOL(__proc_info_begin) = .;				\  	*(.proc.info.init)						\  	VMLINUX_SYMBOL(__proc_info_end) = .; diff --git a/arch/arm/mach-bcmring/arch.c b/arch/arm/mach-bcmring/arch.c index 9e5e7552498..45c97b1ee9b 100644 --- a/arch/arm/mach-bcmring/arch.c +++ b/arch/arm/mach-bcmring/arch.c @@ -194,6 +194,6 @@ MACHINE_START(BCMRING, "BCMRING")  	.init_early = bcmring_init_early,  	.init_irq = bcmring_init_irq,  	.timer = &bcmring_timer, -	.init_machine = bcmring_init_machine +	.init_machine = bcmring_init_machine,  	.restart = bcmring_restart,  MACHINE_END diff --git a/arch/arm/mach-bcmring/dma.c b/arch/arm/mach-bcmring/dma.c index 1a1a27dd565..1024396797e 100644 --- a/arch/arm/mach-bcmring/dma.c +++ b/arch/arm/mach-bcmring/dma.c @@ -33,17 +33,11 @@  #include <mach/timer.h> -#include <linux/mm.h>  #include <linux/pfn.h>  #include <linux/atomic.h>  #include <linux/sched.h>  #include <mach/dma.h> -/* I don't quite understand why dc4 fails when this is set to 1 and DMA is enabled */ -/* especially since dc4 doesn't use kmalloc'd memory. */ - -#define ALLOW_MAP_OF_KMALLOC_MEMORY 0 -  /* ---- Public Variables ------------------------------------------------- */  /* ---- Private Constants and Types -------------------------------------- */ @@ -53,24 +47,12 @@  #define CONTROLLER_FROM_HANDLE(handle)    (((handle) >> 4) & 0x0f)  #define CHANNEL_FROM_HANDLE(handle)       ((handle) & 0x0f) -#define DMA_MAP_DEBUG   0 - -#if DMA_MAP_DEBUG -#   define  DMA_MAP_PRINT(fmt, args...)   printk("%s: " fmt, __func__,  ## args) -#else -#   define  DMA_MAP_PRINT(fmt, args...) -#endif  /* ---- Private Variables ------------------------------------------------ */  static DMA_Global_t gDMA;  static struct proc_dir_entry *gDmaDir; -static atomic_t gDmaStatMemTypeKmalloc = ATOMIC_INIT(0); -static atomic_t gDmaStatMemTypeVmalloc = ATOMIC_INIT(0); -static atomic_t gDmaStatMemTypeUser = ATOMIC_INIT(0); -static atomic_t gDmaStatMemTypeCoherent = ATOMIC_INIT(0); -  #include "dma_device.c"  /* ---- Private Function Prototypes -------------------------------------- */ @@ -79,34 +61,6 @@ static atomic_t gDmaStatMemTypeCoherent = ATOMIC_INIT(0);  /****************************************************************************/  /** -*   Displays information for /proc/dma/mem-type -*/ -/****************************************************************************/ - -static int dma_proc_read_mem_type(char *buf, char **start, off_t offset, -				  int count, int *eof, void *data) -{ -	int len = 0; - -	len += sprintf(buf + len, "dma_map_mem statistics\n"); -	len += -	    sprintf(buf + len, "coherent: %d\n", -		    atomic_read(&gDmaStatMemTypeCoherent)); -	len += -	    sprintf(buf + len, "kmalloc:  %d\n", -		    atomic_read(&gDmaStatMemTypeKmalloc)); -	len += -	    sprintf(buf + len, "vmalloc:  %d\n", -		    atomic_read(&gDmaStatMemTypeVmalloc)); -	len += -	    sprintf(buf + len, "user:     %d\n", -		    atomic_read(&gDmaStatMemTypeUser)); - -	return len; -} - -/****************************************************************************/ -/**  *   Displays information for /proc/dma/channels  */  /****************************************************************************/ @@ -846,8 +800,6 @@ int dma_init(void)  				       dma_proc_read_channels, NULL);  		create_proc_read_entry("devices", 0, gDmaDir,  				       dma_proc_read_devices, NULL); -		create_proc_read_entry("mem-type", 0, gDmaDir, -				       dma_proc_read_mem_type, NULL);  	}  out: @@ -1565,767 +1517,3 @@ int dma_set_device_handler(DMA_Device_t dev,	/* Device to set the callback for.  }  EXPORT_SYMBOL(dma_set_device_handler); - -/****************************************************************************/ -/** -*   Initializes a memory mapping structure -*/ -/****************************************************************************/ - -int dma_init_mem_map(DMA_MemMap_t *memMap) -{ -	memset(memMap, 0, sizeof(*memMap)); - -	sema_init(&memMap->lock, 1); - -	return 0; -} - -EXPORT_SYMBOL(dma_init_mem_map); - -/****************************************************************************/ -/** -*   Releases any memory currently being held by a memory mapping structure. -*/ -/****************************************************************************/ - -int dma_term_mem_map(DMA_MemMap_t *memMap) -{ -	down(&memMap->lock);	/* Just being paranoid */ - -	/* Free up any allocated memory */ - -	up(&memMap->lock); -	memset(memMap, 0, sizeof(*memMap)); - -	return 0; -} - -EXPORT_SYMBOL(dma_term_mem_map); - -/****************************************************************************/ -/** -*   Looks at a memory address and categorizes it. -* -*   @return One of the values from the DMA_MemType_t enumeration. -*/ -/****************************************************************************/ - -DMA_MemType_t dma_mem_type(void *addr) -{ -	unsigned long addrVal = (unsigned long)addr; - -	if (addrVal >= CONSISTENT_BASE) { -		/* NOTE: DMA virtual memory space starts at 0xFFxxxxxx */ - -		/* dma_alloc_xxx pages are physically and virtually contiguous */ - -		return DMA_MEM_TYPE_DMA; -	} - -	/* Technically, we could add one more classification. Addresses between VMALLOC_END */ -	/* and the beginning of the DMA virtual address could be considered to be I/O space. */ -	/* Right now, nobody cares about this particular classification, so we ignore it. */ - -	if (is_vmalloc_addr(addr)) { -		/* Address comes from the vmalloc'd region. Pages are virtually */ -		/* contiguous but NOT physically contiguous */ - -		return DMA_MEM_TYPE_VMALLOC; -	} - -	if (addrVal >= PAGE_OFFSET) { -		/* PAGE_OFFSET is typically 0xC0000000 */ - -		/* kmalloc'd pages are physically contiguous */ - -		return DMA_MEM_TYPE_KMALLOC; -	} - -	return DMA_MEM_TYPE_USER; -} - -EXPORT_SYMBOL(dma_mem_type); - -/****************************************************************************/ -/** -*   Looks at a memory address and determines if we support DMA'ing to/from -*   that type of memory. -* -*   @return boolean - -*               return value != 0 means dma supported -*               return value == 0 means dma not supported -*/ -/****************************************************************************/ - -int dma_mem_supports_dma(void *addr) -{ -	DMA_MemType_t memType = dma_mem_type(addr); - -	return (memType == DMA_MEM_TYPE_DMA) -#if ALLOW_MAP_OF_KMALLOC_MEMORY -	    || (memType == DMA_MEM_TYPE_KMALLOC) -#endif -	    || (memType == DMA_MEM_TYPE_USER); -} - -EXPORT_SYMBOL(dma_mem_supports_dma); - -/****************************************************************************/ -/** -*   Maps in a memory region such that it can be used for performing a DMA. -* -*   @return -*/ -/****************************************************************************/ - -int dma_map_start(DMA_MemMap_t *memMap,	/* Stores state information about the map */ -		  enum dma_data_direction dir	/* Direction that the mapping will be going */ -    ) { -	int rc; - -	down(&memMap->lock); - -	DMA_MAP_PRINT("memMap: %p\n", memMap); - -	if (memMap->inUse) { -		printk(KERN_ERR "%s: memory map %p is already being used\n", -		       __func__, memMap); -		rc = -EBUSY; -		goto out; -	} - -	memMap->inUse = 1; -	memMap->dir = dir; -	memMap->numRegionsUsed = 0; - -	rc = 0; - -out: - -	DMA_MAP_PRINT("returning %d", rc); - -	up(&memMap->lock); - -	return rc; -} - -EXPORT_SYMBOL(dma_map_start); - -/****************************************************************************/ -/** -*   Adds a segment of memory to a memory map. Each segment is both -*   physically and virtually contiguous. -* -*   @return     0 on success, error code otherwise. -*/ -/****************************************************************************/ - -static int dma_map_add_segment(DMA_MemMap_t *memMap,	/* Stores state information about the map */ -			       DMA_Region_t *region,	/* Region that the segment belongs to */ -			       void *virtAddr,	/* Virtual address of the segment being added */ -			       dma_addr_t physAddr,	/* Physical address of the segment being added */ -			       size_t numBytes	/* Number of bytes of the segment being added */ -    ) { -	DMA_Segment_t *segment; - -	DMA_MAP_PRINT("memMap:%p va:%p pa:0x%x #:%d\n", memMap, virtAddr, -		      physAddr, numBytes); - -	/* Sanity check */ - -	if (((unsigned long)virtAddr < (unsigned long)region->virtAddr) -	    || (((unsigned long)virtAddr + numBytes)) > -	    ((unsigned long)region->virtAddr + region->numBytes)) { -		printk(KERN_ERR -		       "%s: virtAddr %p is outside region @ %p len: %d\n", -		       __func__, virtAddr, region->virtAddr, region->numBytes); -		return -EINVAL; -	} - -	if (region->numSegmentsUsed > 0) { -		/* Check to see if this segment is physically contiguous with the previous one */ - -		segment = ®ion->segment[region->numSegmentsUsed - 1]; - -		if ((segment->physAddr + segment->numBytes) == physAddr) { -			/* It is - just add on to the end */ - -			DMA_MAP_PRINT("appending %d bytes to last segment\n", -				      numBytes); - -			segment->numBytes += numBytes; - -			return 0; -		} -	} - -	/* Reallocate to hold more segments, if required. */ - -	if (region->numSegmentsUsed >= region->numSegmentsAllocated) { -		DMA_Segment_t *newSegment; -		size_t oldSize = -		    region->numSegmentsAllocated * sizeof(*newSegment); -		int newAlloc = region->numSegmentsAllocated + 4; -		size_t newSize = newAlloc * sizeof(*newSegment); - -		newSegment = kmalloc(newSize, GFP_KERNEL); -		if (newSegment == NULL) { -			return -ENOMEM; -		} -		memcpy(newSegment, region->segment, oldSize); -		memset(&((uint8_t *) newSegment)[oldSize], 0, -		       newSize - oldSize); -		kfree(region->segment); - -		region->numSegmentsAllocated = newAlloc; -		region->segment = newSegment; -	} - -	segment = ®ion->segment[region->numSegmentsUsed]; -	region->numSegmentsUsed++; - -	segment->virtAddr = virtAddr; -	segment->physAddr = physAddr; -	segment->numBytes = numBytes; - -	DMA_MAP_PRINT("returning success\n"); - -	return 0; -} - -/****************************************************************************/ -/** -*   Adds a region of memory to a memory map. Each region is virtually -*   contiguous, but not necessarily physically contiguous. -* -*   @return     0 on success, error code otherwise. -*/ -/****************************************************************************/ - -int dma_map_add_region(DMA_MemMap_t *memMap,	/* Stores state information about the map */ -		       void *mem,	/* Virtual address that we want to get a map of */ -		       size_t numBytes	/* Number of bytes being mapped */ -    ) { -	unsigned long addr = (unsigned long)mem; -	unsigned int offset; -	int rc = 0; -	DMA_Region_t *region; -	dma_addr_t physAddr; - -	down(&memMap->lock); - -	DMA_MAP_PRINT("memMap:%p va:%p #:%d\n", memMap, mem, numBytes); - -	if (!memMap->inUse) { -		printk(KERN_ERR "%s: Make sure you call dma_map_start first\n", -		       __func__); -		rc = -EINVAL; -		goto out; -	} - -	/* Reallocate to hold more regions. */ - -	if (memMap->numRegionsUsed >= memMap->numRegionsAllocated) { -		DMA_Region_t *newRegion; -		size_t oldSize = -		    memMap->numRegionsAllocated * sizeof(*newRegion); -		int newAlloc = memMap->numRegionsAllocated + 4; -		size_t newSize = newAlloc * sizeof(*newRegion); - -		newRegion = kmalloc(newSize, GFP_KERNEL); -		if (newRegion == NULL) { -			rc = -ENOMEM; -			goto out; -		} -		memcpy(newRegion, memMap->region, oldSize); -		memset(&((uint8_t *) newRegion)[oldSize], 0, newSize - oldSize); - -		kfree(memMap->region); - -		memMap->numRegionsAllocated = newAlloc; -		memMap->region = newRegion; -	} - -	region = &memMap->region[memMap->numRegionsUsed]; -	memMap->numRegionsUsed++; - -	offset = addr & ~PAGE_MASK; - -	region->memType = dma_mem_type(mem); -	region->virtAddr = mem; -	region->numBytes = numBytes; -	region->numSegmentsUsed = 0; -	region->numLockedPages = 0; -	region->lockedPages = NULL; - -	switch (region->memType) { -	case DMA_MEM_TYPE_VMALLOC: -		{ -			atomic_inc(&gDmaStatMemTypeVmalloc); - -			/* printk(KERN_ERR "%s: vmalloc'd pages are not supported\n", __func__); */ - -			/* vmalloc'd pages are not physically contiguous */ - -			rc = -EINVAL; -			break; -		} - -	case DMA_MEM_TYPE_KMALLOC: -		{ -			atomic_inc(&gDmaStatMemTypeKmalloc); - -			/* kmalloc'd pages are physically contiguous, so they'll have exactly */ -			/* one segment */ - -#if ALLOW_MAP_OF_KMALLOC_MEMORY -			physAddr = -			    dma_map_single(NULL, mem, numBytes, memMap->dir); -			rc = dma_map_add_segment(memMap, region, mem, physAddr, -						 numBytes); -#else -			rc = -EINVAL; -#endif -			break; -		} - -	case DMA_MEM_TYPE_DMA: -		{ -			/* dma_alloc_xxx pages are physically contiguous */ - -			atomic_inc(&gDmaStatMemTypeCoherent); - -			physAddr = (vmalloc_to_pfn(mem) << PAGE_SHIFT) + offset; - -			dma_sync_single_for_cpu(NULL, physAddr, numBytes, -						memMap->dir); -			rc = dma_map_add_segment(memMap, region, mem, physAddr, -						 numBytes); -			break; -		} - -	case DMA_MEM_TYPE_USER: -		{ -			size_t firstPageOffset; -			size_t firstPageSize; -			struct page **pages; -			struct task_struct *userTask; - -			atomic_inc(&gDmaStatMemTypeUser); - -#if 1 -			/* If the pages are user pages, then the dma_mem_map_set_user_task function */ -			/* must have been previously called. */ - -			if (memMap->userTask == NULL) { -				printk(KERN_ERR -				       "%s: must call dma_mem_map_set_user_task when using user-mode memory\n", -				       __func__); -				return -EINVAL; -			} - -			/* User pages need to be locked. */ - -			firstPageOffset = -			    (unsigned long)region->virtAddr & (PAGE_SIZE - 1); -			firstPageSize = PAGE_SIZE - firstPageOffset; - -			region->numLockedPages = (firstPageOffset -						  + region->numBytes + -						  PAGE_SIZE - 1) / PAGE_SIZE; -			pages = -			    kmalloc(region->numLockedPages * -				    sizeof(struct page *), GFP_KERNEL); - -			if (pages == NULL) { -				region->numLockedPages = 0; -				return -ENOMEM; -			} - -			userTask = memMap->userTask; - -			down_read(&userTask->mm->mmap_sem); -			rc = get_user_pages(userTask,	/* task */ -					    userTask->mm,	/* mm */ -					    (unsigned long)region->virtAddr,	/* start */ -					    region->numLockedPages,	/* len */ -					    memMap->dir == DMA_FROM_DEVICE,	/* write */ -					    0,	/* force */ -					    pages,	/* pages (array of pointers to page) */ -					    NULL);	/* vmas */ -			up_read(&userTask->mm->mmap_sem); - -			if (rc != region->numLockedPages) { -				kfree(pages); -				region->numLockedPages = 0; - -				if (rc >= 0) { -					rc = -EINVAL; -				} -			} else { -				uint8_t *virtAddr = region->virtAddr; -				size_t bytesRemaining; -				int pageIdx; - -				rc = 0;	/* Since get_user_pages returns +ve number */ - -				region->lockedPages = pages; - -				/* We've locked the user pages. Now we need to walk them and figure */ -				/* out the physical addresses. */ - -				/* The first page may be partial */ - -				dma_map_add_segment(memMap, -						    region, -						    virtAddr, -						    PFN_PHYS(page_to_pfn -							     (pages[0])) + -						    firstPageOffset, -						    firstPageSize); - -				virtAddr += firstPageSize; -				bytesRemaining = -				    region->numBytes - firstPageSize; - -				for (pageIdx = 1; -				     pageIdx < region->numLockedPages; -				     pageIdx++) { -					size_t bytesThisPage = -					    (bytesRemaining > -					     PAGE_SIZE ? PAGE_SIZE : -					     bytesRemaining); - -					DMA_MAP_PRINT -					    ("pageIdx:%d pages[pageIdx]=%p pfn=%u phys=%u\n", -					     pageIdx, pages[pageIdx], -					     page_to_pfn(pages[pageIdx]), -					     PFN_PHYS(page_to_pfn -						      (pages[pageIdx]))); - -					dma_map_add_segment(memMap, -							    region, -							    virtAddr, -							    PFN_PHYS(page_to_pfn -								     (pages -								      [pageIdx])), -							    bytesThisPage); - -					virtAddr += bytesThisPage; -					bytesRemaining -= bytesThisPage; -				} -			} -#else -			printk(KERN_ERR -			       "%s: User mode pages are not yet supported\n", -			       __func__); - -			/* user pages are not physically contiguous */ - -			rc = -EINVAL; -#endif -			break; -		} - -	default: -		{ -			printk(KERN_ERR "%s: Unsupported memory type: %d\n", -			       __func__, region->memType); - -			rc = -EINVAL; -			break; -		} -	} - -	if (rc != 0) { -		memMap->numRegionsUsed--; -	} - -out: - -	DMA_MAP_PRINT("returning %d\n", rc); - -	up(&memMap->lock); - -	return rc; -} - -EXPORT_SYMBOL(dma_map_add_segment); - -/****************************************************************************/ -/** -*   Maps in a memory region such that it can be used for performing a DMA. -* -*   @return     0 on success, error code otherwise. -*/ -/****************************************************************************/ - -int dma_map_mem(DMA_MemMap_t *memMap,	/* Stores state information about the map */ -		void *mem,	/* Virtual address that we want to get a map of */ -		size_t numBytes,	/* Number of bytes being mapped */ -		enum dma_data_direction dir	/* Direction that the mapping will be going */ -    ) { -	int rc; - -	rc = dma_map_start(memMap, dir); -	if (rc == 0) { -		rc = dma_map_add_region(memMap, mem, numBytes); -		if (rc < 0) { -			/* Since the add fails, this function will fail, and the caller won't */ -			/* call unmap, so we need to do it here. */ - -			dma_unmap(memMap, 0); -		} -	} - -	return rc; -} - -EXPORT_SYMBOL(dma_map_mem); - -/****************************************************************************/ -/** -*   Setup a descriptor ring for a given memory map. -* -*   It is assumed that the descriptor ring has already been initialized, and -*   this routine will only reallocate a new descriptor ring if the existing -*   one is too small. -* -*   @return     0 on success, error code otherwise. -*/ -/****************************************************************************/ - -int dma_map_create_descriptor_ring(DMA_Device_t dev,	/* DMA device (where the ring is stored) */ -				   DMA_MemMap_t *memMap,	/* Memory map that will be used */ -				   dma_addr_t devPhysAddr	/* Physical address of device */ -    ) { -	int rc; -	int numDescriptors; -	DMA_DeviceAttribute_t *devAttr; -	DMA_Region_t *region; -	DMA_Segment_t *segment; -	dma_addr_t srcPhysAddr; -	dma_addr_t dstPhysAddr; -	int regionIdx; -	int segmentIdx; - -	devAttr = &DMA_gDeviceAttribute[dev]; - -	down(&memMap->lock); - -	/* Figure out how many descriptors we need */ - -	numDescriptors = 0; -	for (regionIdx = 0; regionIdx < memMap->numRegionsUsed; regionIdx++) { -		region = &memMap->region[regionIdx]; - -		for (segmentIdx = 0; segmentIdx < region->numSegmentsUsed; -		     segmentIdx++) { -			segment = ®ion->segment[segmentIdx]; - -			if (memMap->dir == DMA_TO_DEVICE) { -				srcPhysAddr = segment->physAddr; -				dstPhysAddr = devPhysAddr; -			} else { -				srcPhysAddr = devPhysAddr; -				dstPhysAddr = segment->physAddr; -			} - -			rc = -			     dma_calculate_descriptor_count(dev, srcPhysAddr, -							    dstPhysAddr, -							    segment-> -							    numBytes); -			if (rc < 0) { -				printk(KERN_ERR -				       "%s: dma_calculate_descriptor_count failed: %d\n", -				       __func__, rc); -				goto out; -			} -			numDescriptors += rc; -		} -	} - -	/* Adjust the size of the ring, if it isn't big enough */ - -	if (numDescriptors > devAttr->ring.descriptorsAllocated) { -		dma_free_descriptor_ring(&devAttr->ring); -		rc = -		     dma_alloc_descriptor_ring(&devAttr->ring, -					       numDescriptors); -		if (rc < 0) { -			printk(KERN_ERR -			       "%s: dma_alloc_descriptor_ring failed: %d\n", -			       __func__, rc); -			goto out; -		} -	} else { -		rc = -		     dma_init_descriptor_ring(&devAttr->ring, -					      numDescriptors); -		if (rc < 0) { -			printk(KERN_ERR -			       "%s: dma_init_descriptor_ring failed: %d\n", -			       __func__, rc); -			goto out; -		} -	} - -	/* Populate the descriptors */ - -	for (regionIdx = 0; regionIdx < memMap->numRegionsUsed; regionIdx++) { -		region = &memMap->region[regionIdx]; - -		for (segmentIdx = 0; segmentIdx < region->numSegmentsUsed; -		     segmentIdx++) { -			segment = ®ion->segment[segmentIdx]; - -			if (memMap->dir == DMA_TO_DEVICE) { -				srcPhysAddr = segment->physAddr; -				dstPhysAddr = devPhysAddr; -			} else { -				srcPhysAddr = devPhysAddr; -				dstPhysAddr = segment->physAddr; -			} - -			rc = -			     dma_add_descriptors(&devAttr->ring, dev, -						 srcPhysAddr, dstPhysAddr, -						 segment->numBytes); -			if (rc < 0) { -				printk(KERN_ERR -				       "%s: dma_add_descriptors failed: %d\n", -				       __func__, rc); -				goto out; -			} -		} -	} - -	rc = 0; - -out: - -	up(&memMap->lock); -	return rc; -} - -EXPORT_SYMBOL(dma_map_create_descriptor_ring); - -/****************************************************************************/ -/** -*   Maps in a memory region such that it can be used for performing a DMA. -* -*   @return -*/ -/****************************************************************************/ - -int dma_unmap(DMA_MemMap_t *memMap,	/* Stores state information about the map */ -	      int dirtied	/* non-zero if any of the pages were modified */ -    ) { - -	int rc = 0; -	int regionIdx; -	int segmentIdx; -	DMA_Region_t *region; -	DMA_Segment_t *segment; - -	down(&memMap->lock); - -	for (regionIdx = 0; regionIdx < memMap->numRegionsUsed; regionIdx++) { -		region = &memMap->region[regionIdx]; - -		for (segmentIdx = 0; segmentIdx < region->numSegmentsUsed; -		     segmentIdx++) { -			segment = ®ion->segment[segmentIdx]; - -			switch (region->memType) { -			case DMA_MEM_TYPE_VMALLOC: -				{ -					printk(KERN_ERR -					       "%s: vmalloc'd pages are not yet supported\n", -					       __func__); -					rc = -EINVAL; -					goto out; -				} - -			case DMA_MEM_TYPE_KMALLOC: -				{ -#if ALLOW_MAP_OF_KMALLOC_MEMORY -					dma_unmap_single(NULL, -							 segment->physAddr, -							 segment->numBytes, -							 memMap->dir); -#endif -					break; -				} - -			case DMA_MEM_TYPE_DMA: -				{ -					dma_sync_single_for_cpu(NULL, -								segment-> -								physAddr, -								segment-> -								numBytes, -								memMap->dir); -					break; -				} - -			case DMA_MEM_TYPE_USER: -				{ -					/* Nothing to do here. */ - -					break; -				} - -			default: -				{ -					printk(KERN_ERR -					       "%s: Unsupported memory type: %d\n", -					       __func__, region->memType); -					rc = -EINVAL; -					goto out; -				} -			} - -			segment->virtAddr = NULL; -			segment->physAddr = 0; -			segment->numBytes = 0; -		} - -		if (region->numLockedPages > 0) { -			int pageIdx; - -			/* Some user pages were locked. We need to go and unlock them now. */ - -			for (pageIdx = 0; pageIdx < region->numLockedPages; -			     pageIdx++) { -				struct page *page = -				    region->lockedPages[pageIdx]; - -				if (memMap->dir == DMA_FROM_DEVICE) { -					SetPageDirty(page); -				} -				page_cache_release(page); -			} -			kfree(region->lockedPages); -			region->numLockedPages = 0; -			region->lockedPages = NULL; -		} - -		region->memType = DMA_MEM_TYPE_NONE; -		region->virtAddr = NULL; -		region->numBytes = 0; -		region->numSegmentsUsed = 0; -	} -	memMap->userTask = NULL; -	memMap->numRegionsUsed = 0; -	memMap->inUse = 0; - -out: -	up(&memMap->lock); - -	return rc; -} - -EXPORT_SYMBOL(dma_unmap); diff --git a/arch/arm/mach-bcmring/include/mach/dma.h b/arch/arm/mach-bcmring/include/mach/dma.h index 1f2c5319c05..72543781207 100644 --- a/arch/arm/mach-bcmring/include/mach/dma.h +++ b/arch/arm/mach-bcmring/include/mach/dma.h @@ -26,15 +26,9 @@  /* ---- Include Files ---------------------------------------------------- */  #include <linux/kernel.h> -#include <linux/wait.h>  #include <linux/semaphore.h>  #include <csp/dmacHw.h>  #include <mach/timer.h> -#include <linux/scatterlist.h> -#include <linux/dma-mapping.h> -#include <linux/mm.h> -#include <linux/vmalloc.h> -#include <linux/pagemap.h>  /* ---- Constants and Types ---------------------------------------------- */ @@ -113,78 +107,6 @@ typedef struct {  /****************************************************************************  * -*   The DMA_MemType_t and DMA_MemMap_t are helper structures used to setup -*   DMA chains from a variety of memory sources. -* -*****************************************************************************/ - -#define DMA_MEM_MAP_MIN_SIZE    4096	/* Pages less than this size are better */ -					/* off not being DMA'd. */ - -typedef enum { -	DMA_MEM_TYPE_NONE,	/* Not a valid setting */ -	DMA_MEM_TYPE_VMALLOC,	/* Memory came from vmalloc call */ -	DMA_MEM_TYPE_KMALLOC,	/* Memory came from kmalloc call */ -	DMA_MEM_TYPE_DMA,	/* Memory came from dma_alloc_xxx call */ -	DMA_MEM_TYPE_USER,	/* Memory came from user space. */ - -} DMA_MemType_t; - -/* A segment represents a physically and virtually contiguous chunk of memory. */ -/* i.e. each segment can be DMA'd */ -/* A user of the DMA code will add memory regions. Each region may need to be */ -/* represented by one or more segments. */ - -typedef struct { -	void *virtAddr;		/* Virtual address used for this segment */ -	dma_addr_t physAddr;	/* Physical address this segment maps to */ -	size_t numBytes;	/* Size of the segment, in bytes */ - -} DMA_Segment_t; - -/* A region represents a virtually contiguous chunk of memory, which may be */ -/* made up of multiple segments. */ - -typedef struct { -	DMA_MemType_t memType; -	void *virtAddr; -	size_t numBytes; - -	/* Each region (virtually contiguous) consists of one or more segments. Each */ -	/* segment is virtually and physically contiguous. */ - -	int numSegmentsUsed; -	int numSegmentsAllocated; -	DMA_Segment_t *segment; - -	/* When a region corresponds to user memory, we need to lock all of the pages */ -	/* down before we can figure out the physical addresses. The lockedPage array contains */ -	/* the pages that were locked, and which subsequently need to be unlocked once the */ -	/* memory is unmapped. */ - -	unsigned numLockedPages; -	struct page **lockedPages; - -} DMA_Region_t; - -typedef struct { -	int inUse;		/* Is this mapping currently being used? */ -	struct semaphore lock;	/* Acquired when using this structure */ -	enum dma_data_direction dir;	/* Direction this transfer is intended for */ - -	/* In the event that we're mapping user memory, we need to know which task */ -	/* the memory is for, so that we can obtain the correct mm locks. */ - -	struct task_struct *userTask; - -	int numRegionsUsed; -	int numRegionsAllocated; -	DMA_Region_t *region; - -} DMA_MemMap_t; - -/**************************************************************************** -*  *   The DMA_DeviceAttribute_t contains information which describes a  *   particular DMA device (or peripheral).  * @@ -570,124 +492,6 @@ int dma_alloc_double_dst_descriptors(DMA_Handle_t handle,	/* DMA Handle */  /****************************************************************************/  /** -*   Initializes a DMA_MemMap_t data structure -*/ -/****************************************************************************/ - -int dma_init_mem_map(DMA_MemMap_t *memMap	/* Stores state information about the map */ -    ); - -/****************************************************************************/ -/** -*   Releases any memory currently being held by a memory mapping structure. -*/ -/****************************************************************************/ - -int dma_term_mem_map(DMA_MemMap_t *memMap	/* Stores state information about the map */ -    ); - -/****************************************************************************/ -/** -*   Looks at a memory address and categorizes it. -* -*   @return One of the values from the DMA_MemType_t enumeration. -*/ -/****************************************************************************/ - -DMA_MemType_t dma_mem_type(void *addr); - -/****************************************************************************/ -/** -*   Sets the process (aka userTask) associated with a mem map. This is -*   required if user-mode segments will be added to the mapping. -*/ -/****************************************************************************/ - -static inline void dma_mem_map_set_user_task(DMA_MemMap_t *memMap, -					     struct task_struct *task) -{ -	memMap->userTask = task; -} - -/****************************************************************************/ -/** -*   Looks at a memory address and determines if we support DMA'ing to/from -*   that type of memory. -* -*   @return boolean - -*               return value != 0 means dma supported -*               return value == 0 means dma not supported -*/ -/****************************************************************************/ - -int dma_mem_supports_dma(void *addr); - -/****************************************************************************/ -/** -*   Initializes a memory map for use. Since this function acquires a -*   sempaphore within the memory map, it is VERY important that dma_unmap -*   be called when you're finished using the map. -*/ -/****************************************************************************/ - -int dma_map_start(DMA_MemMap_t *memMap,	/* Stores state information about the map */ -		  enum dma_data_direction dir	/* Direction that the mapping will be going */ -    ); - -/****************************************************************************/ -/** -*   Adds a segment of memory to a memory map. -* -*   @return     0 on success, error code otherwise. -*/ -/****************************************************************************/ - -int dma_map_add_region(DMA_MemMap_t *memMap,	/* Stores state information about the map */ -		       void *mem,	/* Virtual address that we want to get a map of */ -		       size_t numBytes	/* Number of bytes being mapped */ -    ); - -/****************************************************************************/ -/** -*   Creates a descriptor ring from a memory mapping. -* -*   @return 0 on success, error code otherwise. -*/ -/****************************************************************************/ - -int dma_map_create_descriptor_ring(DMA_Device_t dev,	/* DMA device (where the ring is stored) */ -				   DMA_MemMap_t *memMap,	/* Memory map that will be used */ -				   dma_addr_t devPhysAddr	/* Physical address of device */ -    ); - -/****************************************************************************/ -/** -*   Maps in a memory region such that it can be used for performing a DMA. -* -*   @return -*/ -/****************************************************************************/ - -int dma_map_mem(DMA_MemMap_t *memMap,	/* Stores state information about the map */ -		void *addr,	/* Virtual address that we want to get a map of */ -		size_t count,	/* Number of bytes being mapped */ -		enum dma_data_direction dir	/* Direction that the mapping will be going */ -    ); - -/****************************************************************************/ -/** -*   Maps in a memory region such that it can be used for performing a DMA. -* -*   @return -*/ -/****************************************************************************/ - -int dma_unmap(DMA_MemMap_t *memMap,	/* Stores state information about the map */ -	      int dirtied	/* non-zero if any of the pages were modified */ -    ); - -/****************************************************************************/ -/**  *   Initiates a transfer when the descriptors have already been setup.  *  *   This is a special case, and normally, the dma_transfer_xxx functions should diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c index 6b22b543a83..d5088900af6 100644 --- a/arch/arm/mach-davinci/board-da850-evm.c +++ b/arch/arm/mach-davinci/board-da850-evm.c @@ -44,7 +44,7 @@  #include <mach/aemif.h>  #include <mach/spi.h> -#define DA850_EVM_PHY_ID		"0:00" +#define DA850_EVM_PHY_ID		"davinci_mdio-0:00"  #define DA850_LCD_PWR_PIN		GPIO_TO_PIN(2, 8)  #define DA850_LCD_BL_PIN		GPIO_TO_PIN(2, 15) diff --git a/arch/arm/mach-davinci/board-dm365-evm.c b/arch/arm/mach-davinci/board-dm365-evm.c index 346e1de2f5a..849311d3cb7 100644 --- a/arch/arm/mach-davinci/board-dm365-evm.c +++ b/arch/arm/mach-davinci/board-dm365-evm.c @@ -54,7 +54,7 @@ static inline int have_tvp7002(void)  	return 0;  } -#define DM365_EVM_PHY_ID		"0:01" +#define DM365_EVM_PHY_ID		"davinci_mdio-0:01"  /*   * A MAX-II CPLD is used for various board control functions.   */ diff --git a/arch/arm/mach-davinci/board-dm644x-evm.c b/arch/arm/mach-davinci/board-dm644x-evm.c index a64b49cfedc..1247ecdcf75 100644 --- a/arch/arm/mach-davinci/board-dm644x-evm.c +++ b/arch/arm/mach-davinci/board-dm644x-evm.c @@ -40,7 +40,7 @@  #include <mach/usb.h>  #include <mach/aemif.h> -#define DM644X_EVM_PHY_ID		"0:01" +#define DM644X_EVM_PHY_ID		"davinci_mdio-0:01"  #define LXT971_PHY_ID	(0x001378e2)  #define LXT971_PHY_MASK	(0xfffffff0) diff --git a/arch/arm/mach-davinci/board-dm646x-evm.c b/arch/arm/mach-davinci/board-dm646x-evm.c index 64017558860..872ac69fa04 100644 --- a/arch/arm/mach-davinci/board-dm646x-evm.c +++ b/arch/arm/mach-davinci/board-dm646x-evm.c @@ -736,7 +736,7 @@ static struct davinci_uart_config uart_config __initdata = {  	.enabled_uarts = (1 << 0),  }; -#define DM646X_EVM_PHY_ID		"0:01" +#define DM646X_EVM_PHY_ID		"davinci_mdio-0:01"  /*   * The following EDMA channels/slots are not being used by drivers (for   * example: Timer, GPIO, UART events etc) on dm646x, hence they are being diff --git a/arch/arm/mach-davinci/board-neuros-osd2.c b/arch/arm/mach-davinci/board-neuros-osd2.c index 6c4a16415d4..8d34f513d41 100644 --- a/arch/arm/mach-davinci/board-neuros-osd2.c +++ b/arch/arm/mach-davinci/board-neuros-osd2.c @@ -39,7 +39,7 @@  #include <mach/mmc.h>  #include <mach/usb.h> -#define NEUROS_OSD2_PHY_ID		"0:01" +#define NEUROS_OSD2_PHY_ID		"davinci_mdio-0:01"  #define LXT971_PHY_ID			0x001378e2  #define LXT971_PHY_MASK			0xfffffff0 diff --git a/arch/arm/mach-davinci/board-omapl138-hawk.c b/arch/arm/mach-davinci/board-omapl138-hawk.c index e7c0c7c5349..45e815760a2 100644 --- a/arch/arm/mach-davinci/board-omapl138-hawk.c +++ b/arch/arm/mach-davinci/board-omapl138-hawk.c @@ -21,7 +21,7 @@  #include <mach/da8xx.h>  #include <mach/mux.h> -#define HAWKBOARD_PHY_ID		"0:07" +#define HAWKBOARD_PHY_ID		"davinci_mdio-0:07"  #define DA850_HAWK_MMCSD_CD_PIN		GPIO_TO_PIN(3, 12)  #define DA850_HAWK_MMCSD_WP_PIN		GPIO_TO_PIN(3, 13) diff --git a/arch/arm/mach-davinci/board-sffsdr.c b/arch/arm/mach-davinci/board-sffsdr.c index 0b136a831c5..31da3c5b2ba 100644 --- a/arch/arm/mach-davinci/board-sffsdr.c +++ b/arch/arm/mach-davinci/board-sffsdr.c @@ -42,7 +42,7 @@  #include <mach/mux.h>  #include <mach/usb.h> -#define SFFSDR_PHY_ID		"0:01" +#define SFFSDR_PHY_ID		"davinci_mdio-0:01"  static struct mtd_partition davinci_sffsdr_nandflash_partition[] = {  	/* U-Boot Environment: Block 0  	 * UBL:                Block 1 diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c index 0ed7fdb64ef..992c4c41018 100644 --- a/arch/arm/mach-davinci/da850.c +++ b/arch/arm/mach-davinci/da850.c @@ -153,34 +153,6 @@ static struct clk pll1_sysclk3 = {  	.div_reg	= PLLDIV3,  }; -static struct clk pll1_sysclk4 = { -	.name		= "pll1_sysclk4", -	.parent		= &pll1_clk, -	.flags		= CLK_PLL, -	.div_reg	= PLLDIV4, -}; - -static struct clk pll1_sysclk5 = { -	.name		= "pll1_sysclk5", -	.parent		= &pll1_clk, -	.flags		= CLK_PLL, -	.div_reg	= PLLDIV5, -}; - -static struct clk pll1_sysclk6 = { -	.name		= "pll0_sysclk6", -	.parent		= &pll0_clk, -	.flags		= CLK_PLL, -	.div_reg	= PLLDIV6, -}; - -static struct clk pll1_sysclk7 = { -	.name		= "pll1_sysclk7", -	.parent		= &pll1_clk, -	.flags		= CLK_PLL, -	.div_reg	= PLLDIV7, -}; -  static struct clk i2c0_clk = {  	.name		= "i2c0",  	.parent		= &pll0_aux_clk, @@ -397,10 +369,6 @@ static struct clk_lookup da850_clks[] = {  	CLK(NULL,		"pll1_aux",	&pll1_aux_clk),  	CLK(NULL,		"pll1_sysclk2",	&pll1_sysclk2),  	CLK(NULL,		"pll1_sysclk3",	&pll1_sysclk3), -	CLK(NULL,		"pll1_sysclk4",	&pll1_sysclk4), -	CLK(NULL,		"pll1_sysclk5",	&pll1_sysclk5), -	CLK(NULL,		"pll1_sysclk6",	&pll1_sysclk6), -	CLK(NULL,		"pll1_sysclk7",	&pll1_sysclk7),  	CLK("i2c_davinci.1",	NULL,		&i2c0_clk),  	CLK(NULL,		"timer0",	&timerp64_0_clk),  	CLK("watchdog",		NULL,		&timerp64_1_clk), diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c index c59e1887100..6de298c5d2d 100644 --- a/arch/arm/mach-exynos/common.c +++ b/arch/arm/mach-exynos/common.c @@ -402,7 +402,7 @@ void __init exynos4_init_irq(void)  	gic_bank_offset = soc_is_exynos4412() ? 0x4000 : 0x8000;  	if (!of_have_populated_dt()) -		gic_init_bases(0, IRQ_PPI(0), S5P_VA_GIC_DIST, S5P_VA_GIC_CPU, gic_bank_offset); +		gic_init_bases(0, IRQ_PPI(0), S5P_VA_GIC_DIST, S5P_VA_GIC_CPU, gic_bank_offset, NULL);  #ifdef CONFIG_OF  	else  		of_irq_init(exynos4_dt_irq_match); diff --git a/arch/arm/mach-imx/imx51-dt.c b/arch/arm/mach-imx/imx51-dt.c index e6bad17b908..1e03ef42faa 100644 --- a/arch/arm/mach-imx/imx51-dt.c +++ b/arch/arm/mach-imx/imx51-dt.c @@ -47,7 +47,7 @@ static const struct of_dev_auxdata imx51_auxdata_lookup[] __initconst = {  static int __init imx51_tzic_add_irq_domain(struct device_node *np,  				struct device_node *interrupt_parent)  { -	irq_domain_add_simple(np, 0); +	irq_domain_add_legacy(np, 128, 0, 0, &irq_domain_simple_ops, NULL);  	return 0;  } @@ -57,7 +57,7 @@ static int __init imx51_gpio_add_irq_domain(struct device_node *np,  	static int gpio_irq_base = MXC_GPIO_IRQ_START + ARCH_NR_GPIOS;  	gpio_irq_base -= 32; -	irq_domain_add_simple(np, gpio_irq_base); +	irq_domain_add_legacy(np, 32, gpio_irq_base, 0, &irq_domain_simple_ops, NULL);  	return 0;  } diff --git a/arch/arm/mach-imx/imx53-dt.c b/arch/arm/mach-imx/imx53-dt.c index 05ebb3e6867..fd5be0f20fb 100644 --- a/arch/arm/mach-imx/imx53-dt.c +++ b/arch/arm/mach-imx/imx53-dt.c @@ -51,7 +51,7 @@ static const struct of_dev_auxdata imx53_auxdata_lookup[] __initconst = {  static int __init imx53_tzic_add_irq_domain(struct device_node *np,  				struct device_node *interrupt_parent)  { -	irq_domain_add_simple(np, 0); +	irq_domain_add_legacy(np, 128, 0, 0, &irq_domain_simple_ops, NULL);  	return 0;  } @@ -61,7 +61,7 @@ static int __init imx53_gpio_add_irq_domain(struct device_node *np,  	static int gpio_irq_base = MXC_GPIO_IRQ_START + ARCH_NR_GPIOS;  	gpio_irq_base -= 32; -	irq_domain_add_simple(np, gpio_irq_base); +	irq_domain_add_legacy(np, 32, gpio_irq_base, 0, &irq_domain_simple_ops, NULL);  	return 0;  } diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c index c2572810691..6075d4d62dd 100644 --- a/arch/arm/mach-imx/mach-imx6q.c +++ b/arch/arm/mach-imx/mach-imx6q.c @@ -97,7 +97,8 @@ static int __init imx6q_gpio_add_irq_domain(struct device_node *np,  	static int gpio_irq_base = MXC_GPIO_IRQ_START + ARCH_NR_GPIOS;  	gpio_irq_base -= 32; -	irq_domain_add_simple(np, gpio_irq_base); +	irq_domain_add_legacy(np, 32, gpio_irq_base, 0, &irq_domain_simple_ops, +			      NULL);  	return 0;  } diff --git a/arch/arm/mach-msm/board-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c index 0a113424632..962e7116975 100644 --- a/arch/arm/mach-msm/board-msm8x60.c +++ b/arch/arm/mach-msm/board-msm8x60.c @@ -80,12 +80,8 @@ static struct of_device_id msm_dt_gic_match[] __initdata = {  static void __init msm8x60_dt_init(void)  { -	struct device_node *node; - -	node = of_find_matching_node_by_address(NULL, msm_dt_gic_match, -			MSM8X60_QGIC_DIST_PHYS); -	if (node) -		irq_domain_add_simple(node, GIC_SPI_START); +	irq_domain_generate_simple(msm_dt_gic_match, MSM8X60_QGIC_DIST_PHYS, +				GIC_SPI_START);  	if (of_machine_is_compatible("qcom,msm8660-surf")) {  		printk(KERN_INFO "Init surf UART registers\n"); diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig index 41e6612ecba..d965da45160 100644 --- a/arch/arm/mach-omap2/Kconfig +++ b/arch/arm/mach-omap2/Kconfig @@ -213,13 +213,12 @@ config MACH_OMAP3_PANDORA  	depends on ARCH_OMAP3  	default y  	select OMAP_PACKAGE_CBB -	select REGULATOR_FIXED_VOLTAGE +	select REGULATOR_FIXED_VOLTAGE if REGULATOR  config MACH_OMAP3_TOUCHBOOK  	bool "OMAP3 Touch Book"  	depends on ARCH_OMAP3  	default y -	select BACKLIGHT_CLASS_DEVICE  config MACH_OMAP_3430SDP  	bool "OMAP 3430 SDP board" @@ -265,7 +264,7 @@ config MACH_OMAP_ZOOM2  	select SERIAL_8250  	select SERIAL_CORE_CONSOLE  	select SERIAL_8250_CONSOLE -	select REGULATOR_FIXED_VOLTAGE +	select REGULATOR_FIXED_VOLTAGE if REGULATOR  config MACH_OMAP_ZOOM3  	bool "OMAP3630 Zoom3 board" @@ -275,7 +274,7 @@ config MACH_OMAP_ZOOM3  	select SERIAL_8250  	select SERIAL_CORE_CONSOLE  	select SERIAL_8250_CONSOLE -	select REGULATOR_FIXED_VOLTAGE +	select REGULATOR_FIXED_VOLTAGE if REGULATOR  config MACH_CM_T35  	bool "CompuLab CM-T35/CM-T3730 modules" @@ -334,7 +333,7 @@ config MACH_OMAP_4430SDP  	depends on ARCH_OMAP4  	select OMAP_PACKAGE_CBL  	select OMAP_PACKAGE_CBS -	select REGULATOR_FIXED_VOLTAGE +	select REGULATOR_FIXED_VOLTAGE if REGULATOR  config MACH_OMAP4_PANDA  	bool "OMAP4 Panda Board" @@ -342,7 +341,7 @@ config MACH_OMAP4_PANDA  	depends on ARCH_OMAP4  	select OMAP_PACKAGE_CBL  	select OMAP_PACKAGE_CBS -	select REGULATOR_FIXED_VOLTAGE +	select REGULATOR_FIXED_VOLTAGE if REGULATOR  config OMAP3_EMU  	bool "OMAP3 debugging peripherals" diff --git a/arch/arm/mach-omap2/board-4430sdp.c b/arch/arm/mach-omap2/board-4430sdp.c index 39fba9df17f..4e9071589bf 100644 --- a/arch/arm/mach-omap2/board-4430sdp.c +++ b/arch/arm/mach-omap2/board-4430sdp.c @@ -52,8 +52,9 @@  #define ETH_KS8851_QUART		138  #define OMAP4_SFH7741_SENSOR_OUTPUT_GPIO	184  #define OMAP4_SFH7741_ENABLE_GPIO		188 -#define HDMI_GPIO_HPD 60 /* Hot plug pin for HDMI */ +#define HDMI_GPIO_CT_CP_HPD 60 /* HPD mode enable/disable */  #define HDMI_GPIO_LS_OE 41 /* Level shifter for HDMI */ +#define HDMI_GPIO_HPD  63 /* Hotplug detect */  #define DISPLAY_SEL_GPIO	59	/* LCD2/PicoDLP switch */  #define DLP_POWER_ON_GPIO	40 @@ -603,8 +604,9 @@ static void __init omap_sfh7741prox_init(void)  }  static struct gpio sdp4430_hdmi_gpios[] = { -	{ HDMI_GPIO_HPD,	GPIOF_OUT_INIT_HIGH,	"hdmi_gpio_hpd"   }, +	{ HDMI_GPIO_CT_CP_HPD, GPIOF_OUT_INIT_HIGH, "hdmi_gpio_ct_cp_hpd" },  	{ HDMI_GPIO_LS_OE,	GPIOF_OUT_INIT_HIGH,	"hdmi_gpio_ls_oe" }, +	{ HDMI_GPIO_HPD, GPIOF_DIR_IN, "hdmi_gpio_hpd" },  };  static int sdp4430_panel_enable_hdmi(struct omap_dss_device *dssdev) @@ -621,8 +623,7 @@ static int sdp4430_panel_enable_hdmi(struct omap_dss_device *dssdev)  static void sdp4430_panel_disable_hdmi(struct omap_dss_device *dssdev)  { -	gpio_free(HDMI_GPIO_LS_OE); -	gpio_free(HDMI_GPIO_HPD); +	gpio_free_array(sdp4430_hdmi_gpios, ARRAY_SIZE(sdp4430_hdmi_gpios));  }  static struct nokia_dsi_panel_data dsi1_panel = { @@ -738,6 +739,10 @@ static void sdp4430_lcd_init(void)  		pr_err("%s: Could not get lcd2_reset_gpio\n", __func__);  } +static struct omap_dss_hdmi_data sdp4430_hdmi_data = { +	.hpd_gpio = HDMI_GPIO_HPD, +}; +  static struct omap_dss_device sdp4430_hdmi_device = {  	.name = "hdmi",  	.driver_name = "hdmi_panel", @@ -745,6 +750,7 @@ static struct omap_dss_device sdp4430_hdmi_device = {  	.platform_enable = sdp4430_panel_enable_hdmi,  	.platform_disable = sdp4430_panel_disable_hdmi,  	.channel = OMAP_DSS_CHANNEL_DIGIT, +	.data = &sdp4430_hdmi_data,  };  static struct picodlp_panel_data sdp4430_picodlp_pdata = { @@ -808,7 +814,7 @@ static struct omap_dss_board_info sdp4430_dss_data = {  	.default_device	= &sdp4430_lcd_device,  }; -static void omap_4430sdp_display_init(void) +static void __init omap_4430sdp_display_init(void)  {  	int r; @@ -829,6 +835,10 @@ static void omap_4430sdp_display_init(void)  		omap_hdmi_init(OMAP_HDMI_SDA_SCL_EXTERNAL_PULLUP);  	else  		omap_hdmi_init(0); + +	omap_mux_init_gpio(HDMI_GPIO_LS_OE, OMAP_PIN_OUTPUT); +	omap_mux_init_gpio(HDMI_GPIO_CT_CP_HPD, OMAP_PIN_OUTPUT); +	omap_mux_init_gpio(HDMI_GPIO_HPD, OMAP_PIN_INPUT_PULLDOWN);  }  #ifdef CONFIG_OMAP_MUX @@ -841,7 +851,7 @@ static struct omap_board_mux board_mux[] __initdata = {  #define board_mux	NULL   #endif -static void omap4_sdp4430_wifi_mux_init(void) +static void __init omap4_sdp4430_wifi_mux_init(void)  {  	omap_mux_init_gpio(GPIO_WIFI_IRQ, OMAP_PIN_INPUT |  				OMAP_PIN_OFF_WAKEUPENABLE); @@ -868,12 +878,17 @@ static struct wl12xx_platform_data omap4_sdp4430_wlan_data __initdata = {  	.board_tcxo_clock = WL12XX_TCXOCLOCK_26,  }; -static void omap4_sdp4430_wifi_init(void) +static void __init omap4_sdp4430_wifi_init(void)  { +	int ret; +  	omap4_sdp4430_wifi_mux_init(); -	if (wl12xx_set_platform_data(&omap4_sdp4430_wlan_data)) -		pr_err("Error setting wl12xx data\n"); -	platform_device_register(&omap_vwlan_device); +	ret = wl12xx_set_platform_data(&omap4_sdp4430_wlan_data); +	if (ret) +		pr_err("Error setting wl12xx data: %d\n", ret); +	ret = platform_device_register(&omap_vwlan_device); +	if (ret) +		pr_err("Error registering wl12xx device: %d\n", ret);  }  static void __init omap_4430sdp_init(void) diff --git a/arch/arm/mach-omap2/board-generic.c b/arch/arm/mach-omap2/board-generic.c index d5875606048..00b1d024fa8 100644 --- a/arch/arm/mach-omap2/board-generic.c +++ b/arch/arm/mach-omap2/board-generic.c @@ -67,7 +67,7 @@ static void __init omap_generic_init(void)  {  	struct device_node *node = of_find_matching_node(NULL, intc_match);  	if (node) -		irq_domain_add_simple(node, 0); +		irq_domain_add_legacy(node, 32, 0, 0, &irq_domain_simple_ops, NULL);  	omap_sdrc_init(NULL, NULL); diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c index 003fe34c934..c775bead149 100644 --- a/arch/arm/mach-omap2/board-omap3evm.c +++ b/arch/arm/mach-omap2/board-omap3evm.c @@ -617,6 +617,21 @@ static struct gpio omap3_evm_ehci_gpios[] __initdata = {  	{ OMAP3_EVM_EHCI_SELECT, GPIOF_OUT_INIT_LOW,   "select EHCI port" },  }; +static void __init omap3_evm_wl12xx_init(void) +{ +#ifdef CONFIG_WL12XX_PLATFORM_DATA +	int ret; + +	/* WL12xx WLAN Init */ +	ret = wl12xx_set_platform_data(&omap3evm_wlan_data); +	if (ret) +		pr_err("error setting wl12xx data: %d\n", ret); +	ret = platform_device_register(&omap3evm_wlan_regulator); +	if (ret) +		pr_err("error registering wl12xx device: %d\n", ret); +#endif +} +  static void __init omap3_evm_init(void)  {  	omap3_evm_get_revision(); @@ -665,13 +680,7 @@ static void __init omap3_evm_init(void)  	omap_ads7846_init(1, OMAP3_EVM_TS_GPIO, 310, NULL);  	omap3evm_init_smsc911x();  	omap3_evm_display_init(); - -#ifdef CONFIG_WL12XX_PLATFORM_DATA -	/* WL12xx WLAN Init */ -	if (wl12xx_set_platform_data(&omap3evm_wlan_data)) -		pr_err("error setting wl12xx data\n"); -	platform_device_register(&omap3evm_wlan_regulator); -#endif +	omap3_evm_wl12xx_init();  }  MACHINE_START(OMAP3EVM, "OMAP3 EVM") diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c index 30ad40db2cf..28fc271f703 100644 --- a/arch/arm/mach-omap2/board-omap4panda.c +++ b/arch/arm/mach-omap2/board-omap4panda.c @@ -51,8 +51,9 @@  #define GPIO_HUB_NRESET		62  #define GPIO_WIFI_PMENA		43  #define GPIO_WIFI_IRQ		53 -#define HDMI_GPIO_HPD 60 /* Hot plug pin for HDMI */ +#define HDMI_GPIO_CT_CP_HPD 60 /* HPD mode enable/disable */  #define HDMI_GPIO_LS_OE 41 /* Level shifter for HDMI */ +#define HDMI_GPIO_HPD  63 /* Hotplug detect */  /* wl127x BT, FM, GPS connectivity chip */  static int wl1271_gpios[] = {46, -1, -1}; @@ -413,8 +414,9 @@ int __init omap4_panda_dvi_init(void)  }  static struct gpio panda_hdmi_gpios[] = { -	{ HDMI_GPIO_HPD,	GPIOF_OUT_INIT_HIGH, "hdmi_gpio_hpd"   }, +	{ HDMI_GPIO_CT_CP_HPD, GPIOF_OUT_INIT_HIGH, "hdmi_gpio_ct_cp_hpd" },  	{ HDMI_GPIO_LS_OE,	GPIOF_OUT_INIT_HIGH, "hdmi_gpio_ls_oe" }, +	{ HDMI_GPIO_HPD, GPIOF_DIR_IN, "hdmi_gpio_hpd" },  };  static int omap4_panda_panel_enable_hdmi(struct omap_dss_device *dssdev) @@ -431,10 +433,13 @@ static int omap4_panda_panel_enable_hdmi(struct omap_dss_device *dssdev)  static void omap4_panda_panel_disable_hdmi(struct omap_dss_device *dssdev)  { -	gpio_free(HDMI_GPIO_LS_OE); -	gpio_free(HDMI_GPIO_HPD); +	gpio_free_array(panda_hdmi_gpios, ARRAY_SIZE(panda_hdmi_gpios));  } +static struct omap_dss_hdmi_data omap4_panda_hdmi_data = { +	.hpd_gpio = HDMI_GPIO_HPD, +}; +  static struct omap_dss_device  omap4_panda_hdmi_device = {  	.name = "hdmi",  	.driver_name = "hdmi_panel", @@ -442,6 +447,7 @@ static struct omap_dss_device  omap4_panda_hdmi_device = {  	.platform_enable = omap4_panda_panel_enable_hdmi,  	.platform_disable = omap4_panda_panel_disable_hdmi,  	.channel = OMAP_DSS_CHANNEL_DIGIT, +	.data = &omap4_panda_hdmi_data,  };  static struct omap_dss_device *omap4_panda_dss_devices[] = { @@ -473,18 +479,24 @@ void omap4_panda_display_init(void)  		omap_hdmi_init(OMAP_HDMI_SDA_SCL_EXTERNAL_PULLUP);  	else  		omap_hdmi_init(0); + +	omap_mux_init_gpio(HDMI_GPIO_LS_OE, OMAP_PIN_OUTPUT); +	omap_mux_init_gpio(HDMI_GPIO_CT_CP_HPD, OMAP_PIN_OUTPUT); +	omap_mux_init_gpio(HDMI_GPIO_HPD, OMAP_PIN_INPUT_PULLDOWN);  }  static void __init omap4_panda_init(void)  {  	int package = OMAP_PACKAGE_CBS; +	int ret;  	if (omap_rev() == OMAP4430_REV_ES1_0)  		package = OMAP_PACKAGE_CBL;  	omap4_mux_init(board_mux, NULL, package); -	if (wl12xx_set_platform_data(&omap_panda_wlan_data)) -		pr_err("error setting wl12xx data\n"); +	ret = wl12xx_set_platform_data(&omap_panda_wlan_data); +	if (ret) +		pr_err("error setting wl12xx data: %d\n", ret);  	omap4_panda_i2c_init();  	platform_add_devices(panda_devices, ARRAY_SIZE(panda_devices)); diff --git a/arch/arm/mach-omap2/board-zoom-peripherals.c b/arch/arm/mach-omap2/board-zoom-peripherals.c index 8d7ce11cfea..c126461836a 100644 --- a/arch/arm/mach-omap2/board-zoom-peripherals.c +++ b/arch/arm/mach-omap2/board-zoom-peripherals.c @@ -296,8 +296,10 @@ static void enable_board_wakeup_source(void)  void __init zoom_peripherals_init(void)  { -	if (wl12xx_set_platform_data(&omap_zoom_wlan_data)) -		pr_err("error setting wl12xx data\n"); +	int ret = wl12xx_set_platform_data(&omap_zoom_wlan_data); + +	if (ret) +		pr_err("error setting wl12xx data: %d\n", ret);  	omap_i2c_init();  	platform_device_register(&omap_vwlan_device); diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c index 0b510ad01a0..283d11eae69 100644 --- a/arch/arm/mach-omap2/devices.c +++ b/arch/arm/mach-omap2/devices.c @@ -405,6 +405,7 @@ static int omap_mcspi_init(struct omap_hwmod *oh, void *unused)  			break;  	default:  			pr_err("Invalid McSPI Revision value\n"); +			kfree(pdata);  			return -EINVAL;  	} diff --git a/arch/arm/mach-omap2/display.c b/arch/arm/mach-omap2/display.c index 3c446d1a178..3677b1f58b8 100644 --- a/arch/arm/mach-omap2/display.c +++ b/arch/arm/mach-omap2/display.c @@ -103,12 +103,8 @@ static void omap4_hdmi_mux_pads(enum omap_hdmi_flags flags)  	u32 reg;  	u16 control_i2c_1; -	/* PAD0_HDMI_HPD_PAD1_HDMI_CEC */ -	omap_mux_init_signal("hdmi_hpd", -			OMAP_PIN_INPUT_PULLUP);  	omap_mux_init_signal("hdmi_cec",  			OMAP_PIN_INPUT_PULLUP); -	/* PAD0_HDMI_DDC_SCL_PAD1_HDMI_DDC_SDA */  	omap_mux_init_signal("hdmi_ddc_scl",  			OMAP_PIN_INPUT_PULLUP);  	omap_mux_init_signal("hdmi_ddc_sda", diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index 130034bf01d..dfffbbf4c00 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c @@ -528,7 +528,13 @@ int gpmc_cs_configure(int cs, int cmd, int wval)  	case GPMC_CONFIG_DEV_SIZE:  		regval  = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1); + +		/* clear 2 target bits */ +		regval &= ~GPMC_CONFIG1_DEVICESIZE(3); + +		/* set the proper value */  		regval |= GPMC_CONFIG1_DEVICESIZE(wval); +  		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval);  		break; diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c index bd844af13af..b40c2889529 100644 --- a/arch/arm/mach-omap2/hsmmc.c +++ b/arch/arm/mach-omap2/hsmmc.c @@ -175,14 +175,15 @@ static void hsmmc2_select_input_clk_src(struct omap_mmc_platform_data *mmc)  {  	u32 reg; -	if (mmc->slots[0].internal_clock) { -		reg = omap_ctrl_readl(control_devconf1_offset); +	reg = omap_ctrl_readl(control_devconf1_offset); +	if (mmc->slots[0].internal_clock)  		reg |= OMAP2_MMCSDIO2ADPCLKISEL; -		omap_ctrl_writel(reg, control_devconf1_offset); -	} +	else +		reg &= ~OMAP2_MMCSDIO2ADPCLKISEL; +	omap_ctrl_writel(reg, control_devconf1_offset);  } -static void hsmmc23_before_set_reg(struct device *dev, int slot, +static void hsmmc2_before_set_reg(struct device *dev, int slot,  				   int power_on, int vdd)  {  	struct omap_mmc_platform_data *mmc = dev->platform_data; @@ -292,8 +293,8 @@ static inline void omap_hsmmc_mux(struct omap_mmc_platform_data *mmc_controller,  	}  } -static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c, -					struct omap_mmc_platform_data *mmc) +static int omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c, +				 struct omap_mmc_platform_data *mmc)  {  	char *hc_name; @@ -407,14 +408,13 @@ static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c,  			c->caps &= ~MMC_CAP_8_BIT_DATA;  			c->caps |= MMC_CAP_4_BIT_DATA;  		} -		/* FALLTHROUGH */ -	case 3:  		if (mmc->slots[0].features & HSMMC_HAS_PBIAS) {  			/* off-chip level shifting, or none */ -			mmc->slots[0].before_set_reg = hsmmc23_before_set_reg; +			mmc->slots[0].before_set_reg = hsmmc2_before_set_reg;  			mmc->slots[0].after_set_reg = NULL;  		}  		break; +	case 3:  	case 4:  	case 5:  		mmc->slots[0].before_set_reg = NULL; @@ -430,7 +430,7 @@ static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c,  #define MAX_OMAP_MMC_HWMOD_NAME_LEN		16 -void __init omap_init_hsmmc(struct omap2_hsmmc_info *hsmmcinfo, int ctrl_nr) +void omap_init_hsmmc(struct omap2_hsmmc_info *hsmmcinfo, int ctrl_nr)  {  	struct omap_hwmod *oh;  	struct platform_device *pdev; @@ -487,7 +487,7 @@ done:  	kfree(mmc_data);  } -void __init omap2_hsmmc_init(struct omap2_hsmmc_info *controllers) +void omap2_hsmmc_init(struct omap2_hsmmc_info *controllers)  {  	u32 reg; diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c index 3f174d51f67..eb50c29fb64 100644 --- a/arch/arm/mach-omap2/io.c +++ b/arch/arm/mach-omap2/io.c @@ -388,7 +388,7 @@ static void __init omap_hwmod_init_postsetup(void)  	omap_pm_if_early_init();  } -#ifdef CONFIG_ARCH_OMAP2 +#ifdef CONFIG_SOC_OMAP2420  void __init omap2420_init_early(void)  {  	omap2_set_globals_242x(); @@ -400,7 +400,9 @@ void __init omap2420_init_early(void)  	omap_hwmod_init_postsetup();  	omap2420_clk_init();  } +#endif +#ifdef CONFIG_SOC_OMAP2430  void __init omap2430_init_early(void)  {  	omap2_set_globals_243x(); diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c index e1cc75d1a57..fb8bc9fa43b 100644 --- a/arch/arm/mach-omap2/mux.c +++ b/arch/arm/mach-omap2/mux.c @@ -100,8 +100,8 @@ void omap_mux_write_array(struct omap_mux_partition *partition,  static char *omap_mux_options; -static int __init _omap_mux_init_gpio(struct omap_mux_partition *partition, -				      int gpio, int val) +static int _omap_mux_init_gpio(struct omap_mux_partition *partition, +			       int gpio, int val)  {  	struct omap_mux_entry *e;  	struct omap_mux *gpio_mux = NULL; @@ -145,7 +145,7 @@ static int __init _omap_mux_init_gpio(struct omap_mux_partition *partition,  	return 0;  } -int __init omap_mux_init_gpio(int gpio, int val) +int omap_mux_init_gpio(int gpio, int val)  {  	struct omap_mux_partition *partition;  	int ret; @@ -159,9 +159,9 @@ int __init omap_mux_init_gpio(int gpio, int val)  	return -ENODEV;  } -static int __init _omap_mux_get_by_name(struct omap_mux_partition *partition, -					const char *muxname, -					struct omap_mux **found_mux) +static int _omap_mux_get_by_name(struct omap_mux_partition *partition, +				 const char *muxname, +				 struct omap_mux **found_mux)  {  	struct omap_mux *mux = NULL;  	struct omap_mux_entry *e; @@ -240,7 +240,7 @@ omap_mux_get_by_name(const char *muxname,  	return -ENODEV;  } -int __init omap_mux_init_signal(const char *muxname, int val) +int omap_mux_init_signal(const char *muxname, int val)  {  	struct omap_mux_partition *partition = NULL;  	struct omap_mux *mux = NULL; @@ -1094,8 +1094,8 @@ static void omap_mux_init_package(struct omap_mux *superset,  		omap_mux_package_init_balls(package_balls, superset);  } -static void omap_mux_init_signals(struct omap_mux_partition *partition, -				  struct omap_board_mux *board_mux) +static void __init omap_mux_init_signals(struct omap_mux_partition *partition, +					 struct omap_board_mux *board_mux)  {  	omap_mux_set_cmdline_signals();  	omap_mux_write_array(partition, board_mux); @@ -1109,8 +1109,8 @@ static void omap_mux_init_package(struct omap_mux *superset,  {  } -static void omap_mux_init_signals(struct omap_mux_partition *partition, -				  struct omap_board_mux *board_mux) +static void __init omap_mux_init_signals(struct omap_mux_partition *partition, +					 struct omap_board_mux *board_mux)  {  } diff --git a/arch/arm/mach-omap2/omap-headsmp.S b/arch/arm/mach-omap2/omap-headsmp.S index b13ef7ef5ef..503ac777a2b 100644 --- a/arch/arm/mach-omap2/omap-headsmp.S +++ b/arch/arm/mach-omap2/omap-headsmp.S @@ -18,6 +18,7 @@  #include <linux/linkage.h>  #include <linux/init.h> +	__CPUINIT  /*   * OMAP4 specific entry point for secondary CPU to jump from ROM   * code.  This routine also provides a holding flag into which diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index 5192cabb40e..eba6cd3816f 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -1517,8 +1517,8 @@ static int _enable(struct omap_hwmod *oh)  	if (oh->_state != _HWMOD_STATE_INITIALIZED &&  	    oh->_state != _HWMOD_STATE_IDLE &&  	    oh->_state != _HWMOD_STATE_DISABLED) { -		WARN(1, "omap_hwmod: %s: enabled state can only be entered " -		     "from initialized, idle, or disabled state\n", oh->name); +		WARN(1, "omap_hwmod: %s: enabled state can only be entered from initialized, idle, or disabled state\n", +			oh->name);  		return -EINVAL;  	} @@ -1600,8 +1600,8 @@ static int _idle(struct omap_hwmod *oh)  	pr_debug("omap_hwmod: %s: idling\n", oh->name);  	if (oh->_state != _HWMOD_STATE_ENABLED) { -		WARN(1, "omap_hwmod: %s: idle state can only be entered from " -		     "enabled state\n", oh->name); +		WARN(1, "omap_hwmod: %s: idle state can only be entered from enabled state\n", +			oh->name);  		return -EINVAL;  	} @@ -1682,8 +1682,8 @@ static int _shutdown(struct omap_hwmod *oh)  	if (oh->_state != _HWMOD_STATE_IDLE &&  	    oh->_state != _HWMOD_STATE_ENABLED) { -		WARN(1, "omap_hwmod: %s: disabled state can only be entered " -		     "from idle, or enabled state\n", oh->name); +		WARN(1, "omap_hwmod: %s: disabled state can only be entered from idle, or enabled state\n", +			oh->name);  		return -EINVAL;  	} @@ -2240,8 +2240,8 @@ void omap_hwmod_ocp_barrier(struct omap_hwmod *oh)  	BUG_ON(!oh);  	if (!oh->class->sysc || !oh->class->sysc->sysc_flags) { -		WARN(1, "omap_device: %s: OCP barrier impossible due to " -		      "device configuration\n", oh->name); +		WARN(1, "omap_device: %s: OCP barrier impossible due to device configuration\n", +			oh->name);  		return;  	} diff --git a/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c b/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c index c11273da5dc..f08e442af39 100644 --- a/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c @@ -56,27 +56,6 @@ struct omap_hwmod_class omap2_dss_hwmod_class = {  };  /* - * 'dispc' class - * display controller - */ - -static struct omap_hwmod_class_sysconfig omap2_dispc_sysc = { -	.rev_offs	= 0x0000, -	.sysc_offs	= 0x0010, -	.syss_offs	= 0x0014, -	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_MIDLEMODE | -			   SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE), -	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART | -			   MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART), -	.sysc_fields	= &omap_hwmod_sysc_type1, -}; - -struct omap_hwmod_class omap2_dispc_hwmod_class = { -	.name	= "dispc", -	.sysc	= &omap2_dispc_sysc, -}; - -/*   * 'rfbi' class   * remote frame buffer interface   */ diff --git a/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c b/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c index 177dee20fae..2a6729741b0 100644 --- a/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c @@ -28,6 +28,28 @@ struct omap_hwmod_dma_info omap2xxx_dss_sdma_chs[] = {  	{ .name = "dispc", .dma_req = 5 },  	{ .dma_req = -1 }  }; + +/* + * 'dispc' class + * display controller + */ + +static struct omap_hwmod_class_sysconfig omap2_dispc_sysc = { +	.rev_offs	= 0x0000, +	.sysc_offs	= 0x0010, +	.syss_offs	= 0x0014, +	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_MIDLEMODE | +			   SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE), +	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART | +			   MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART), +	.sysc_fields	= &omap_hwmod_sysc_type1, +}; + +struct omap_hwmod_class omap2_dispc_hwmod_class = { +	.name	= "dispc", +	.sysc	= &omap2_dispc_sysc, +}; +  /* OMAP2xxx Timer Common */  static struct omap_hwmod_class_sysconfig omap2xxx_timer_sysc = {  	.rev_offs	= 0x0000, diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c index 5324e8d93bc..3c8dd928628 100644 --- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c @@ -1480,6 +1480,28 @@ static struct omap_hwmod omap3xxx_dss_core_hwmod = {  	.masters_cnt	= ARRAY_SIZE(omap3xxx_dss_masters),  }; +/* + * 'dispc' class + * display controller + */ + +static struct omap_hwmod_class_sysconfig omap3_dispc_sysc = { +	.rev_offs	= 0x0000, +	.sysc_offs	= 0x0010, +	.syss_offs	= 0x0014, +	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_MIDLEMODE | +			   SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE | +			   SYSC_HAS_ENAWAKEUP), +	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART | +			   MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART), +	.sysc_fields	= &omap_hwmod_sysc_type1, +}; + +static struct omap_hwmod_class omap3_dispc_hwmod_class = { +	.name	= "dispc", +	.sysc	= &omap3_dispc_sysc, +}; +  /* l4_core -> dss_dispc */  static struct omap_hwmod_ocp_if omap3xxx_l4_core__dss_dispc = {  	.master		= &omap3xxx_l4_core_hwmod, @@ -1503,7 +1525,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_dss_dispc_slaves[] = {  static struct omap_hwmod omap3xxx_dss_dispc_hwmod = {  	.name		= "dss_dispc", -	.class		= &omap2_dispc_hwmod_class, +	.class		= &omap3_dispc_hwmod_class,  	.mpu_irqs	= omap2_dispc_irqs,  	.main_clk	= "dss1_alwon_fck",  	.prcm		= { @@ -3523,12 +3545,6 @@ static __initdata struct omap_hwmod *omap3xxx_hwmods[] = {  	&omap3xxx_uart2_hwmod,  	&omap3xxx_uart3_hwmod, -	/* dss class */ -	&omap3xxx_dss_dispc_hwmod, -	&omap3xxx_dss_dsi1_hwmod, -	&omap3xxx_dss_rfbi_hwmod, -	&omap3xxx_dss_venc_hwmod, -  	/* i2c class */  	&omap3xxx_i2c1_hwmod,  	&omap3xxx_i2c2_hwmod, @@ -3635,6 +3651,15 @@ static __initdata struct omap_hwmod *am35xx_hwmods[] = {  	NULL  }; +static __initdata struct omap_hwmod *omap3xxx_dss_hwmods[] = { +	/* dss class */ +	&omap3xxx_dss_dispc_hwmod, +	&omap3xxx_dss_dsi1_hwmod, +	&omap3xxx_dss_rfbi_hwmod, +	&omap3xxx_dss_venc_hwmod, +	NULL +}; +  int __init omap3xxx_hwmod_init(void)  {  	int r; @@ -3708,6 +3733,21 @@ int __init omap3xxx_hwmod_init(void)  	if (h)  		r = omap_hwmod_register(h); +	if (r < 0) +		return r; + +	/* +	 * DSS code presumes that dss_core hwmod is handled first, +	 * _before_ any other DSS related hwmods so register common +	 * DSS hwmods last to ensure that dss_core is already registered. +	 * Otherwise some change things may happen, for ex. if dispc +	 * is handled before dss_core and DSS is enabled in bootloader +	 * DIPSC will be reset with outputs enabled which sometimes leads +	 * to unrecoverable L3 error. +	 * XXX The long-term fix to this is to ensure modules are set up +	 * in dependency order in the hwmod core code. +	 */ +	r = omap_hwmod_register(omap3xxx_dss_hwmods);  	return r;  } diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c index f9f15108176..ef0524c10a8 100644 --- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c @@ -1031,6 +1031,7 @@ static struct omap_hwmod_dma_info omap44xx_dmic_sdma_reqs[] = {  static struct omap_hwmod_addr_space omap44xx_dmic_addrs[] = {  	{ +		.name		= "mpu",  		.pa_start	= 0x4012e000,  		.pa_end		= 0x4012e07f,  		.flags		= ADDR_TYPE_RT @@ -1049,6 +1050,7 @@ static struct omap_hwmod_ocp_if omap44xx_l4_abe__dmic = {  static struct omap_hwmod_addr_space omap44xx_dmic_dma_addrs[] = {  	{ +		.name		= "dma",  		.pa_start	= 0x4902e000,  		.pa_end		= 0x4902e07f,  		.flags		= ADDR_TYPE_RT diff --git a/arch/arm/mach-omap2/prm2xxx_3xxx.c b/arch/arm/mach-omap2/prm2xxx_3xxx.c index c1c4d86a79a..9ce765407ad 100644 --- a/arch/arm/mach-omap2/prm2xxx_3xxx.c +++ b/arch/arm/mach-omap2/prm2xxx_3xxx.c @@ -19,6 +19,7 @@  #include "common.h"  #include <plat/cpu.h>  #include <plat/prcm.h> +#include <plat/irqs.h>  #include "vp.h" diff --git a/arch/arm/mach-omap2/prm44xx.c b/arch/arm/mach-omap2/prm44xx.c index 33dd655e6aa..a1d6154dc12 100644 --- a/arch/arm/mach-omap2/prm44xx.c +++ b/arch/arm/mach-omap2/prm44xx.c @@ -19,6 +19,7 @@  #include "common.h"  #include <plat/cpu.h> +#include <plat/irqs.h>  #include <plat/prcm.h>  #include "vp.h" diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c index 247d89478f2..f590afc1f67 100644 --- a/arch/arm/mach-omap2/serial.c +++ b/arch/arm/mach-omap2/serial.c @@ -107,18 +107,18 @@ static void omap_uart_set_noidle(struct platform_device *pdev)  	omap_hwmod_set_slave_idlemode(od->hwmods[0], HWMOD_IDLEMODE_NO);  } -static void omap_uart_set_forceidle(struct platform_device *pdev) +static void omap_uart_set_smartidle(struct platform_device *pdev)  {  	struct omap_device *od = to_omap_device(pdev); -	omap_hwmod_set_slave_idlemode(od->hwmods[0], HWMOD_IDLEMODE_FORCE); +	omap_hwmod_set_slave_idlemode(od->hwmods[0], HWMOD_IDLEMODE_SMART);  }  #else  static void omap_uart_enable_wakeup(struct platform_device *pdev, bool enable)  {}  static void omap_uart_set_noidle(struct platform_device *pdev) {} -static void omap_uart_set_forceidle(struct platform_device *pdev) {} +static void omap_uart_set_smartidle(struct platform_device *pdev) {}  #endif /* CONFIG_PM */  #ifdef CONFIG_OMAP_MUX @@ -349,7 +349,7 @@ void __init omap_serial_init_port(struct omap_board_data *bdata,  	omap_up.uartclk = OMAP24XX_BASE_BAUD * 16;  	omap_up.flags = UPF_BOOT_AUTOCONF;  	omap_up.get_context_loss_count = omap_pm_get_dev_context_loss_count; -	omap_up.set_forceidle = omap_uart_set_forceidle; +	omap_up.set_forceidle = omap_uart_set_smartidle;  	omap_up.set_noidle = omap_uart_set_noidle;  	omap_up.enable_wakeup = omap_uart_enable_wakeup;  	omap_up.dma_rx_buf_size = info->dma_rx_buf_size; diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c index 9dd93453e56..7e755bb0ffc 100644 --- a/arch/arm/mach-omap2/smartreflex.c +++ b/arch/arm/mach-omap2/smartreflex.c @@ -897,7 +897,7 @@ static int __init omap_sr_probe(struct platform_device *pdev)  		ret = sr_late_init(sr_info);  		if (ret) {  			pr_warning("%s: Error in SR late init\n", __func__); -			return ret; +			goto err_iounmap;  		}  	} diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c index 6eeff0e0ae0..5c9acea9576 100644 --- a/arch/arm/mach-omap2/timer.c +++ b/arch/arm/mach-omap2/timer.c @@ -270,7 +270,7 @@ static struct clocksource clocksource_gpt = {  static u32 notrace dmtimer_read_sched_clock(void)  {  	if (clksrc.reserved) -		return __omap_dm_timer_read_counter(clksrc.io_base, 1); +		return __omap_dm_timer_read_counter(&clksrc, 1);  	return 0;  } diff --git a/arch/arm/mach-omap2/vc.c b/arch/arm/mach-omap2/vc.c index 031d116fbf1..175b7d86d86 100644 --- a/arch/arm/mach-omap2/vc.c +++ b/arch/arm/mach-omap2/vc.c @@ -247,7 +247,7 @@ static void __init omap4_vc_init_channel(struct voltagedomain *voltdm)   * omap_vc_i2c_init - initialize I2C interface to PMIC   * @voltdm: voltage domain containing VC data   * - * Use PMIC supplied seetings for I2C high-speed mode and + * Use PMIC supplied settings for I2C high-speed mode and   * master code (if set) and program the VC I2C configuration   * register.   * @@ -265,8 +265,8 @@ static void __init omap_vc_i2c_init(struct voltagedomain *voltdm)  	if (initialized) {  		if (voltdm->pmic->i2c_high_speed != i2c_high_speed) -			pr_warn("%s: I2C config for all channels must match.", -				__func__); +			pr_warn("%s: I2C config for vdd_%s does not match other channels (%u).", +				__func__, voltdm->name, i2c_high_speed);  		return;  	} @@ -292,9 +292,7 @@ void __init omap_vc_init_channel(struct voltagedomain *voltdm)  	u32 val;  	if (!voltdm->pmic || !voltdm->pmic->uv_to_vsel) { -		pr_err("%s: PMIC info requried to configure vc for" -			"vdd_%s not populated.Hence cannot initialize vc\n", -			__func__, voltdm->name); +		pr_err("%s: No PMIC info for vdd_%s\n", __func__, voltdm->name);  		return;  	} diff --git a/arch/arm/mach-omap2/vp.c b/arch/arm/mach-omap2/vp.c index 807391d84a9..0df88820978 100644 --- a/arch/arm/mach-omap2/vp.c +++ b/arch/arm/mach-omap2/vp.c @@ -41,6 +41,11 @@ void __init omap_vp_init(struct voltagedomain *voltdm)  	u32 val, sys_clk_rate, timeout, waittime;  	u32 vddmin, vddmax, vstepmin, vstepmax; +	if (!voltdm->pmic || !voltdm->pmic->uv_to_vsel) { +		pr_err("%s: No PMIC info for vdd_%s\n", __func__, voltdm->name); +		return; +	} +  	if (!voltdm->read || !voltdm->write) {  		pr_err("%s: No read/write API for accessing vdd_%s regs\n",  			__func__, voltdm->name); diff --git a/arch/arm/mach-prima2/irq.c b/arch/arm/mach-prima2/irq.c index d93ceef4a50..37c2de9b6f2 100644 --- a/arch/arm/mach-prima2/irq.c +++ b/arch/arm/mach-prima2/irq.c @@ -68,7 +68,7 @@ void __init sirfsoc_of_irq_init(void)  	if (!sirfsoc_intc_base)  		panic("unable to map intc cpu registers\n"); -	irq_domain_add_simple(np, 0); +	irq_domain_add_legacy(np, 32, 0, 0, &irq_domain_simple_ops, NULL);  	of_node_put(np); diff --git a/arch/arm/mach-shmobile/setup-sh7372.c b/arch/arm/mach-shmobile/setup-sh7372.c index 6fcf304d3cd..a83cf51fc09 100644 --- a/arch/arm/mach-shmobile/setup-sh7372.c +++ b/arch/arm/mach-shmobile/setup-sh7372.c @@ -662,6 +662,7 @@ static struct sh_dmae_pdata usb_dma0_platform_data = {  	.dmaor_is_32bit	= 1,  	.needs_tend_set	= 1,  	.no_dmars	= 1, +	.slave_only	= 1,  };  static struct resource sh7372_usb_dmae0_resources[] = { @@ -723,6 +724,7 @@ static struct sh_dmae_pdata usb_dma1_platform_data = {  	.dmaor_is_32bit	= 1,  	.needs_tend_set	= 1,  	.no_dmars	= 1, +	.slave_only	= 1,  };  static struct resource sh7372_usb_dmae1_resources[] = { diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c index 02b7b9303f3..008ce22b9a0 100644 --- a/arch/arm/mach-versatile/core.c +++ b/arch/arm/mach-versatile/core.c @@ -98,8 +98,11 @@ static const struct of_device_id sic_of_match[] __initconst = {  void __init versatile_init_irq(void)  { -	vic_init(VA_VIC_BASE, IRQ_VIC_START, ~0, 0); -	irq_domain_generate_simple(vic_of_match, VERSATILE_VIC_BASE, IRQ_VIC_START); +	struct device_node *np; + +	np = of_find_matching_node_by_address(NULL, vic_of_match, +					      VERSATILE_VIC_BASE); +	__vic_init(VA_VIC_BASE, IRQ_VIC_START, ~0, 0, np);  	writel(~0, VA_SIC_BASE + SIC_IRQ_ENABLE_CLEAR); diff --git a/arch/arm/mm/cache-v7.S b/arch/arm/mm/cache-v7.S index 07c4bc8ea0a..7a24d39661f 100644 --- a/arch/arm/mm/cache-v7.S +++ b/arch/arm/mm/cache-v7.S @@ -54,9 +54,15 @@ loop1:  	and	r1, r1, #7			@ mask of the bits for current cache only  	cmp	r1, #2				@ see what cache we have at this level  	blt	skip				@ skip if no cache, or just i-cache +#ifdef CONFIG_PREEMPT +	save_and_disable_irqs r9		@ make cssr&csidr read atomic +#endif  	mcr	p15, 2, r10, c0, c0, 0		@ select current cache level in cssr  	isb					@ isb to sych the new cssr&csidr  	mrc	p15, 1, r1, c0, c0, 0		@ read the new csidr +#ifdef CONFIG_PREEMPT +	restore_irqs_notrace r9 +#endif  	and	r2, r1, #7			@ extract the length of the cache lines  	add	r2, r2, #4			@ add 4 (line length offset)  	ldr	r4, =0x3ff diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c index ba159370fa5..80632e8d753 100644 --- a/arch/arm/mm/ioremap.c +++ b/arch/arm/mm/ioremap.c @@ -225,8 +225,7 @@ void __iomem * __arm_ioremap_pfn_caller(unsigned long pfn,  		if ((area->flags & VM_ARM_MTYPE_MASK) != VM_ARM_MTYPE(mtype))  			continue;  		if (__phys_to_pfn(area->phys_addr) > pfn || -		    __pfn_to_phys(pfn) + offset + size-1 > -		    area->phys_addr + area->size-1) +		    __pfn_to_phys(pfn) + size-1 > area->phys_addr + area->size-1)  			continue;  		/* we can drop the lock here as we know *area is static */  		read_unlock(&vmlist_lock); diff --git a/arch/avr32/Kconfig b/arch/avr32/Kconfig index 197e96f7040..3dea7231f63 100644 --- a/arch/avr32/Kconfig +++ b/arch/avr32/Kconfig @@ -8,6 +8,7 @@ config AVR32  	select HAVE_KPROBES  	select HAVE_GENERIC_HARDIRQS  	select GENERIC_IRQ_PROBE +	select GENERIC_ATOMIC64  	select HARDIRQS_SW_RESEND  	select GENERIC_IRQ_SHOW  	select ARCH_HAVE_NMI_SAFE_CMPXCHG diff --git a/arch/c6x/Kconfig b/arch/c6x/Kconfig index 26e67f0f005..3c64b2894c1 100644 --- a/arch/c6x/Kconfig +++ b/arch/c6x/Kconfig @@ -12,6 +12,7 @@ config TMS320C6X  	select HAVE_GENERIC_HARDIRQS  	select HAVE_MEMBLOCK  	select HAVE_SPARSE_IRQ +	select IRQ_DOMAIN  	select OF  	select OF_EARLY_FLATTREE diff --git a/arch/c6x/include/asm/irq.h b/arch/c6x/include/asm/irq.h index a6ae3c9d9c4..f13b78d5e1c 100644 --- a/arch/c6x/include/asm/irq.h +++ b/arch/c6x/include/asm/irq.h @@ -13,6 +13,7 @@  #ifndef _ASM_C6X_IRQ_H  #define _ASM_C6X_IRQ_H +#include <linux/irqdomain.h>  #include <linux/threads.h>  #include <linux/list.h>  #include <linux/radix-tree.h> @@ -41,253 +42,9 @@  /* This number is used when no interrupt has been assigned */  #define NO_IRQ		0 -/* This type is the placeholder for a hardware interrupt number. It has to - * be big enough to enclose whatever representation is used by a given - * platform. - */ -typedef unsigned long irq_hw_number_t; - -/* Interrupt controller "host" data structure. This could be defined as a - * irq domain controller. That is, it handles the mapping between hardware - * and virtual interrupt numbers for a given interrupt domain. The host - * structure is generally created by the PIC code for a given PIC instance - * (though a host can cover more than one PIC if they have a flat number - * model). It's the host callbacks that are responsible for setting the - * irq_chip on a given irq_desc after it's been mapped. - * - * The host code and data structures are fairly agnostic to the fact that - * we use an open firmware device-tree. We do have references to struct - * device_node in two places: in irq_find_host() to find the host matching - * a given interrupt controller node, and of course as an argument to its - * counterpart host->ops->match() callback. However, those are treated as - * generic pointers by the core and the fact that it's actually a device-node - * pointer is purely a convention between callers and implementation. This - * code could thus be used on other architectures by replacing those two - * by some sort of arch-specific void * "token" used to identify interrupt - * controllers. - */ -struct irq_host; -struct radix_tree_root; -struct device_node; - -/* Functions below are provided by the host and called whenever a new mapping - * is created or an old mapping is disposed. The host can then proceed to - * whatever internal data structures management is required. It also needs - * to setup the irq_desc when returning from map(). - */ -struct irq_host_ops { -	/* Match an interrupt controller device node to a host, returns -	 * 1 on a match -	 */ -	int (*match)(struct irq_host *h, struct device_node *node); - -	/* Create or update a mapping between a virtual irq number and a hw -	 * irq number. This is called only once for a given mapping. -	 */ -	int (*map)(struct irq_host *h, unsigned int virq, irq_hw_number_t hw); - -	/* Dispose of such a mapping */ -	void (*unmap)(struct irq_host *h, unsigned int virq); - -	/* Translate device-tree interrupt specifier from raw format coming -	 * from the firmware to a irq_hw_number_t (interrupt line number) and -	 * type (sense) that can be passed to set_irq_type(). In the absence -	 * of this callback, irq_create_of_mapping() and irq_of_parse_and_map() -	 * will return the hw number in the first cell and IRQ_TYPE_NONE for -	 * the type (which amount to keeping whatever default value the -	 * interrupt controller has for that line) -	 */ -	int (*xlate)(struct irq_host *h, struct device_node *ctrler, -		     const u32 *intspec, unsigned int intsize, -		     irq_hw_number_t *out_hwirq, unsigned int *out_type); -}; - -struct irq_host { -	struct list_head	link; - -	/* type of reverse mapping technique */ -	unsigned int		revmap_type; -#define IRQ_HOST_MAP_PRIORITY   0 /* core priority irqs, get irqs 1..15 */ -#define IRQ_HOST_MAP_NOMAP	1 /* no fast reverse mapping */ -#define IRQ_HOST_MAP_LINEAR	2 /* linear map of interrupts */ -#define IRQ_HOST_MAP_TREE	3 /* radix tree */ -	union { -		struct { -			unsigned int size; -			unsigned int *revmap; -		} linear; -		struct radix_tree_root tree; -	} revmap_data; -	struct irq_host_ops	*ops; -	void			*host_data; -	irq_hw_number_t		inval_irq; - -	/* Optional device node pointer */ -	struct device_node	*of_node; -}; -  struct irq_data;  extern irq_hw_number_t irqd_to_hwirq(struct irq_data *d);  extern irq_hw_number_t virq_to_hw(unsigned int virq); -extern bool virq_is_host(unsigned int virq, struct irq_host *host); - -/** - * irq_alloc_host - Allocate a new irq_host data structure - * @of_node: optional device-tree node of the interrupt controller - * @revmap_type: type of reverse mapping to use - * @revmap_arg: for IRQ_HOST_MAP_LINEAR linear only: size of the map - * @ops: map/unmap host callbacks - * @inval_irq: provide a hw number in that host space that is always invalid - * - * Allocates and initialize and irq_host structure. Note that in the case of - * IRQ_HOST_MAP_LEGACY, the map() callback will be called before this returns - * for all legacy interrupts except 0 (which is always the invalid irq for - * a legacy controller). For a IRQ_HOST_MAP_LINEAR, the map is allocated by - * this call as well. For a IRQ_HOST_MAP_TREE, the radix tree will be allocated - * later during boot automatically (the reverse mapping will use the slow path - * until that happens). - */ -extern struct irq_host *irq_alloc_host(struct device_node *of_node, -				       unsigned int revmap_type, -				       unsigned int revmap_arg, -				       struct irq_host_ops *ops, -				       irq_hw_number_t inval_irq); - - -/** - * irq_find_host - Locates a host for a given device node - * @node: device-tree node of the interrupt controller - */ -extern struct irq_host *irq_find_host(struct device_node *node); - - -/** - * irq_set_default_host - Set a "default" host - * @host: default host pointer - * - * For convenience, it's possible to set a "default" host that will be used - * whenever NULL is passed to irq_create_mapping(). It makes life easier for - * platforms that want to manipulate a few hard coded interrupt numbers that - * aren't properly represented in the device-tree. - */ -extern void irq_set_default_host(struct irq_host *host); - - -/** - * irq_set_virq_count - Set the maximum number of virt irqs - * @count: number of linux virtual irqs, capped with NR_IRQS - * - * This is mainly for use by platforms like iSeries who want to program - * the virtual irq number in the controller to avoid the reverse mapping - */ -extern void irq_set_virq_count(unsigned int count); - - -/** - * irq_create_mapping - Map a hardware interrupt into linux virq space - * @host: host owning this hardware interrupt or NULL for default host - * @hwirq: hardware irq number in that host space - * - * Only one mapping per hardware interrupt is permitted. Returns a linux - * virq number. - * If the sense/trigger is to be specified, set_irq_type() should be called - * on the number returned from that call. - */ -extern unsigned int irq_create_mapping(struct irq_host *host, -				       irq_hw_number_t hwirq); - - -/** - * irq_dispose_mapping - Unmap an interrupt - * @virq: linux virq number of the interrupt to unmap - */ -extern void irq_dispose_mapping(unsigned int virq); - -/** - * irq_find_mapping - Find a linux virq from an hw irq number. - * @host: host owning this hardware interrupt - * @hwirq: hardware irq number in that host space - * - * This is a slow path, for use by generic code. It's expected that an - * irq controller implementation directly calls the appropriate low level - * mapping function. - */ -extern unsigned int irq_find_mapping(struct irq_host *host, -				     irq_hw_number_t hwirq); - -/** - * irq_create_direct_mapping - Allocate a virq for direct mapping - * @host: host to allocate the virq for or NULL for default host - * - * This routine is used for irq controllers which can choose the hardware - * interrupt numbers they generate. In such a case it's simplest to use - * the linux virq as the hardware interrupt number. - */ -extern unsigned int irq_create_direct_mapping(struct irq_host *host); - -/** - * irq_radix_revmap_insert - Insert a hw irq to linux virq number mapping. - * @host: host owning this hardware interrupt - * @virq: linux irq number - * @hwirq: hardware irq number in that host space - * - * This is for use by irq controllers that use a radix tree reverse - * mapping for fast lookup. - */ -extern void irq_radix_revmap_insert(struct irq_host *host, unsigned int virq, -				    irq_hw_number_t hwirq); - -/** - * irq_radix_revmap_lookup - Find a linux virq from a hw irq number. - * @host: host owning this hardware interrupt - * @hwirq: hardware irq number in that host space - * - * This is a fast path, for use by irq controller code that uses radix tree - * revmaps - */ -extern unsigned int irq_radix_revmap_lookup(struct irq_host *host, -					    irq_hw_number_t hwirq); - -/** - * irq_linear_revmap - Find a linux virq from a hw irq number. - * @host: host owning this hardware interrupt - * @hwirq: hardware irq number in that host space - * - * This is a fast path, for use by irq controller code that uses linear - * revmaps. It does fallback to the slow path if the revmap doesn't exist - * yet and will create the revmap entry with appropriate locking - */ - -extern unsigned int irq_linear_revmap(struct irq_host *host, -				      irq_hw_number_t hwirq); - - - -/** - * irq_alloc_virt - Allocate virtual irq numbers - * @host: host owning these new virtual irqs - * @count: number of consecutive numbers to allocate - * @hint: pass a hint number, the allocator will try to use a 1:1 mapping - * - * This is a low level function that is used internally by irq_create_mapping() - * and that can be used by some irq controllers implementations for things - * like allocating ranges of numbers for MSIs. The revmaps are left untouched. - */ -extern unsigned int irq_alloc_virt(struct irq_host *host, -				   unsigned int count, -				   unsigned int hint); - -/** - * irq_free_virt - Free virtual irq numbers - * @virq: virtual irq number of the first interrupt to free - * @count: number of interrupts to free - * - * This function is the opposite of irq_alloc_virt. It will not clear reverse - * maps, this should be done previously by unmap'ing the interrupt. In fact, - * all interrupts covered by the range being freed should have been unmapped - * prior to calling this. - */ -extern void irq_free_virt(unsigned int virq, unsigned int count);  extern void __init init_pic_c64xplus(void); diff --git a/arch/c6x/kernel/irq.c b/arch/c6x/kernel/irq.c index 0929e4b2b24..d77bcfdf0d8 100644 --- a/arch/c6x/kernel/irq.c +++ b/arch/c6x/kernel/irq.c @@ -73,10 +73,10 @@ asmlinkage void c6x_do_IRQ(unsigned int prio, struct pt_regs *regs)  	set_irq_regs(old_regs);  } -static struct irq_host *core_host; +static struct irq_domain *core_domain; -static int core_host_map(struct irq_host *h, unsigned int virq, -			 irq_hw_number_t hw) +static int core_domain_map(struct irq_domain *h, unsigned int virq, +			   irq_hw_number_t hw)  {  	if (hw < 4 || hw >= NR_PRIORITY_IRQS)  		return -EINVAL; @@ -86,8 +86,9 @@ static int core_host_map(struct irq_host *h, unsigned int virq,  	return 0;  } -static struct irq_host_ops core_host_ops = { -	.map = core_host_map, +static const struct irq_domain_ops core_domain_ops = { +	.map = core_domain_map, +	.xlate = irq_domain_xlate_onecell,  };  void __init init_IRQ(void) @@ -100,10 +101,11 @@ void __init init_IRQ(void)  	np = of_find_compatible_node(NULL, NULL, "ti,c64x+core-pic");  	if (np != NULL) {  		/* create the core host */ -		core_host = irq_alloc_host(np, IRQ_HOST_MAP_PRIORITY, 0, -					   &core_host_ops, 0); -		if (core_host) -			irq_set_default_host(core_host); +		core_domain = irq_domain_add_legacy(np, NR_PRIORITY_IRQS, +						    0, 0, &core_domain_ops, +						    NULL); +		if (core_domain) +			irq_set_default_host(core_domain);  		of_node_put(np);  	} @@ -128,601 +130,15 @@ int arch_show_interrupts(struct seq_file *p, int prec)  	return 0;  } -/* - * IRQ controller and virtual interrupts - */ - -/* The main irq map itself is an array of NR_IRQ entries containing the - * associate host and irq number. An entry with a host of NULL is free. - * An entry can be allocated if it's free, the allocator always then sets - * hwirq first to the host's invalid irq number and then fills ops. - */ -struct irq_map_entry { -	irq_hw_number_t	hwirq; -	struct irq_host	*host; -}; - -static LIST_HEAD(irq_hosts); -static DEFINE_RAW_SPINLOCK(irq_big_lock); -static DEFINE_MUTEX(revmap_trees_mutex); -static struct irq_map_entry irq_map[NR_IRQS]; -static unsigned int irq_virq_count = NR_IRQS; -static struct irq_host *irq_default_host; -  irq_hw_number_t irqd_to_hwirq(struct irq_data *d)  { -	return irq_map[d->irq].hwirq; +	return d->hwirq;  }  EXPORT_SYMBOL_GPL(irqd_to_hwirq);  irq_hw_number_t virq_to_hw(unsigned int virq)  { -	return irq_map[virq].hwirq; +	struct irq_data *irq_data = irq_get_irq_data(virq); +	return WARN_ON(!irq_data) ? 0 : irq_data->hwirq;  }  EXPORT_SYMBOL_GPL(virq_to_hw); - -bool virq_is_host(unsigned int virq, struct irq_host *host) -{ -	return irq_map[virq].host == host; -} -EXPORT_SYMBOL_GPL(virq_is_host); - -static int default_irq_host_match(struct irq_host *h, struct device_node *np) -{ -	return h->of_node != NULL && h->of_node == np; -} - -struct irq_host *irq_alloc_host(struct device_node *of_node, -				unsigned int revmap_type, -				unsigned int revmap_arg, -				struct irq_host_ops *ops, -				irq_hw_number_t inval_irq) -{ -	struct irq_host *host; -	unsigned int size = sizeof(struct irq_host); -	unsigned int i; -	unsigned int *rmap; -	unsigned long flags; - -	/* Allocate structure and revmap table if using linear mapping */ -	if (revmap_type == IRQ_HOST_MAP_LINEAR) -		size += revmap_arg * sizeof(unsigned int); -	host = kzalloc(size, GFP_KERNEL); -	if (host == NULL) -		return NULL; - -	/* Fill structure */ -	host->revmap_type = revmap_type; -	host->inval_irq = inval_irq; -	host->ops = ops; -	host->of_node = of_node_get(of_node); - -	if (host->ops->match == NULL) -		host->ops->match = default_irq_host_match; - -	raw_spin_lock_irqsave(&irq_big_lock, flags); - -	/* Check for the priority controller. */ -	if (revmap_type == IRQ_HOST_MAP_PRIORITY) { -		if (irq_map[0].host != NULL) { -			raw_spin_unlock_irqrestore(&irq_big_lock, flags); -			of_node_put(host->of_node); -			kfree(host); -			return NULL; -		} -		irq_map[0].host = host; -	} - -	list_add(&host->link, &irq_hosts); -	raw_spin_unlock_irqrestore(&irq_big_lock, flags); - -	/* Additional setups per revmap type */ -	switch (revmap_type) { -	case IRQ_HOST_MAP_PRIORITY: -		/* 0 is always the invalid number for priority */ -		host->inval_irq = 0; -		/* setup us as the host for all priority interrupts */ -		for (i = 1; i < NR_PRIORITY_IRQS; i++) { -			irq_map[i].hwirq = i; -			smp_wmb(); -			irq_map[i].host = host; -			smp_wmb(); - -			ops->map(host, i, i); -		} -		break; -	case IRQ_HOST_MAP_LINEAR: -		rmap = (unsigned int *)(host + 1); -		for (i = 0; i < revmap_arg; i++) -			rmap[i] = NO_IRQ; -		host->revmap_data.linear.size = revmap_arg; -		smp_wmb(); -		host->revmap_data.linear.revmap = rmap; -		break; -	case IRQ_HOST_MAP_TREE: -		INIT_RADIX_TREE(&host->revmap_data.tree, GFP_KERNEL); -		break; -	default: -		break; -	} - -	pr_debug("irq: Allocated host of type %d @0x%p\n", revmap_type, host); - -	return host; -} - -struct irq_host *irq_find_host(struct device_node *node) -{ -	struct irq_host *h, *found = NULL; -	unsigned long flags; - -	/* We might want to match the legacy controller last since -	 * it might potentially be set to match all interrupts in -	 * the absence of a device node. This isn't a problem so far -	 * yet though... -	 */ -	raw_spin_lock_irqsave(&irq_big_lock, flags); -	list_for_each_entry(h, &irq_hosts, link) -		if (h->ops->match(h, node)) { -			found = h; -			break; -		} -	raw_spin_unlock_irqrestore(&irq_big_lock, flags); -	return found; -} -EXPORT_SYMBOL_GPL(irq_find_host); - -void irq_set_default_host(struct irq_host *host) -{ -	pr_debug("irq: Default host set to @0x%p\n", host); - -	irq_default_host = host; -} - -void irq_set_virq_count(unsigned int count) -{ -	pr_debug("irq: Trying to set virq count to %d\n", count); - -	BUG_ON(count < NR_PRIORITY_IRQS); -	if (count < NR_IRQS) -		irq_virq_count = count; -} - -static int irq_setup_virq(struct irq_host *host, unsigned int virq, -			    irq_hw_number_t hwirq) -{ -	int res; - -	res = irq_alloc_desc_at(virq, 0); -	if (res != virq) { -		pr_debug("irq: -> allocating desc failed\n"); -		goto error; -	} - -	/* map it */ -	smp_wmb(); -	irq_map[virq].hwirq = hwirq; -	smp_mb(); - -	if (host->ops->map(host, virq, hwirq)) { -		pr_debug("irq: -> mapping failed, freeing\n"); -		goto errdesc; -	} - -	irq_clear_status_flags(virq, IRQ_NOREQUEST); - -	return 0; - -errdesc: -	irq_free_descs(virq, 1); -error: -	irq_free_virt(virq, 1); -	return -1; -} - -unsigned int irq_create_direct_mapping(struct irq_host *host) -{ -	unsigned int virq; - -	if (host == NULL) -		host = irq_default_host; - -	BUG_ON(host == NULL); -	WARN_ON(host->revmap_type != IRQ_HOST_MAP_NOMAP); - -	virq = irq_alloc_virt(host, 1, 0); -	if (virq == NO_IRQ) { -		pr_debug("irq: create_direct virq allocation failed\n"); -		return NO_IRQ; -	} - -	pr_debug("irq: create_direct obtained virq %d\n", virq); - -	if (irq_setup_virq(host, virq, virq)) -		return NO_IRQ; - -	return virq; -} - -unsigned int irq_create_mapping(struct irq_host *host, -				irq_hw_number_t hwirq) -{ -	unsigned int virq, hint; - -	pr_debug("irq: irq_create_mapping(0x%p, 0x%lx)\n", host, hwirq); - -	/* Look for default host if nececssary */ -	if (host == NULL) -		host = irq_default_host; -	if (host == NULL) { -		printk(KERN_WARNING "irq_create_mapping called for" -		       " NULL host, hwirq=%lx\n", hwirq); -		WARN_ON(1); -		return NO_IRQ; -	} -	pr_debug("irq: -> using host @%p\n", host); - -	/* Check if mapping already exists */ -	virq = irq_find_mapping(host, hwirq); -	if (virq != NO_IRQ) { -		pr_debug("irq: -> existing mapping on virq %d\n", virq); -		return virq; -	} - -	/* Allocate a virtual interrupt number */ -	hint = hwirq % irq_virq_count; -	virq = irq_alloc_virt(host, 1, hint); -	if (virq == NO_IRQ) { -		pr_debug("irq: -> virq allocation failed\n"); -		return NO_IRQ; -	} - -	if (irq_setup_virq(host, virq, hwirq)) -		return NO_IRQ; - -	pr_debug("irq: irq %lu on host %s mapped to virtual irq %u\n", -		hwirq, host->of_node ? host->of_node->full_name : "null", virq); - -	return virq; -} -EXPORT_SYMBOL_GPL(irq_create_mapping); - -unsigned int irq_create_of_mapping(struct device_node *controller, -				   const u32 *intspec, unsigned int intsize) -{ -	struct irq_host *host; -	irq_hw_number_t hwirq; -	unsigned int type = IRQ_TYPE_NONE; -	unsigned int virq; - -	if (controller == NULL) -		host = irq_default_host; -	else -		host = irq_find_host(controller); -	if (host == NULL) { -		printk(KERN_WARNING "irq: no irq host found for %s !\n", -		       controller->full_name); -		return NO_IRQ; -	} - -	/* If host has no translation, then we assume interrupt line */ -	if (host->ops->xlate == NULL) -		hwirq = intspec[0]; -	else { -		if (host->ops->xlate(host, controller, intspec, intsize, -				     &hwirq, &type)) -			return NO_IRQ; -	} - -	/* Create mapping */ -	virq = irq_create_mapping(host, hwirq); -	if (virq == NO_IRQ) -		return virq; - -	/* Set type if specified and different than the current one */ -	if (type != IRQ_TYPE_NONE && -	    type != (irqd_get_trigger_type(irq_get_irq_data(virq)))) -		irq_set_irq_type(virq, type); -	return virq; -} -EXPORT_SYMBOL_GPL(irq_create_of_mapping); - -void irq_dispose_mapping(unsigned int virq) -{ -	struct irq_host *host; -	irq_hw_number_t hwirq; - -	if (virq == NO_IRQ) -		return; - -	/* Never unmap priority interrupts */ -	if (virq < NR_PRIORITY_IRQS) -		return; - -	host = irq_map[virq].host; -	if (WARN_ON(host == NULL)) -		return; - -	irq_set_status_flags(virq, IRQ_NOREQUEST); - -	/* remove chip and handler */ -	irq_set_chip_and_handler(virq, NULL, NULL); - -	/* Make sure it's completed */ -	synchronize_irq(virq); - -	/* Tell the PIC about it */ -	if (host->ops->unmap) -		host->ops->unmap(host, virq); -	smp_mb(); - -	/* Clear reverse map */ -	hwirq = irq_map[virq].hwirq; -	switch (host->revmap_type) { -	case IRQ_HOST_MAP_LINEAR: -		if (hwirq < host->revmap_data.linear.size) -			host->revmap_data.linear.revmap[hwirq] = NO_IRQ; -		break; -	case IRQ_HOST_MAP_TREE: -		mutex_lock(&revmap_trees_mutex); -		radix_tree_delete(&host->revmap_data.tree, hwirq); -		mutex_unlock(&revmap_trees_mutex); -		break; -	} - -	/* Destroy map */ -	smp_mb(); -	irq_map[virq].hwirq = host->inval_irq; - -	irq_free_descs(virq, 1); -	/* Free it */ -	irq_free_virt(virq, 1); -} -EXPORT_SYMBOL_GPL(irq_dispose_mapping); - -unsigned int irq_find_mapping(struct irq_host *host, -			      irq_hw_number_t hwirq) -{ -	unsigned int i; -	unsigned int hint = hwirq % irq_virq_count; - -	/* Look for default host if nececssary */ -	if (host == NULL) -		host = irq_default_host; -	if (host == NULL) -		return NO_IRQ; - -	/* Slow path does a linear search of the map */ -	i = hint; -	do  { -		if (irq_map[i].host == host && -		    irq_map[i].hwirq == hwirq) -			return i; -		i++; -		if (i >= irq_virq_count) -			i = 4; -	} while (i != hint); -	return NO_IRQ; -} -EXPORT_SYMBOL_GPL(irq_find_mapping); - -unsigned int irq_radix_revmap_lookup(struct irq_host *host, -				     irq_hw_number_t hwirq) -{ -	struct irq_map_entry *ptr; -	unsigned int virq; - -	if (WARN_ON_ONCE(host->revmap_type != IRQ_HOST_MAP_TREE)) -		return irq_find_mapping(host, hwirq); - -	/* -	 * The ptr returned references the static global irq_map. -	 * but freeing an irq can delete nodes along the path to -	 * do the lookup via call_rcu. -	 */ -	rcu_read_lock(); -	ptr = radix_tree_lookup(&host->revmap_data.tree, hwirq); -	rcu_read_unlock(); - -	/* -	 * If found in radix tree, then fine. -	 * Else fallback to linear lookup - this should not happen in practice -	 * as it means that we failed to insert the node in the radix tree. -	 */ -	if (ptr) -		virq = ptr - irq_map; -	else -		virq = irq_find_mapping(host, hwirq); - -	return virq; -} - -void irq_radix_revmap_insert(struct irq_host *host, unsigned int virq, -			     irq_hw_number_t hwirq) -{ -	if (WARN_ON(host->revmap_type != IRQ_HOST_MAP_TREE)) -		return; - -	if (virq != NO_IRQ) { -		mutex_lock(&revmap_trees_mutex); -		radix_tree_insert(&host->revmap_data.tree, hwirq, -				  &irq_map[virq]); -		mutex_unlock(&revmap_trees_mutex); -	} -} - -unsigned int irq_linear_revmap(struct irq_host *host, -			       irq_hw_number_t hwirq) -{ -	unsigned int *revmap; - -	if (WARN_ON_ONCE(host->revmap_type != IRQ_HOST_MAP_LINEAR)) -		return irq_find_mapping(host, hwirq); - -	/* Check revmap bounds */ -	if (unlikely(hwirq >= host->revmap_data.linear.size)) -		return irq_find_mapping(host, hwirq); - -	/* Check if revmap was allocated */ -	revmap = host->revmap_data.linear.revmap; -	if (unlikely(revmap == NULL)) -		return irq_find_mapping(host, hwirq); - -	/* Fill up revmap with slow path if no mapping found */ -	if (unlikely(revmap[hwirq] == NO_IRQ)) -		revmap[hwirq] = irq_find_mapping(host, hwirq); - -	return revmap[hwirq]; -} - -unsigned int irq_alloc_virt(struct irq_host *host, -			    unsigned int count, -			    unsigned int hint) -{ -	unsigned long flags; -	unsigned int i, j, found = NO_IRQ; - -	if (count == 0 || count > (irq_virq_count - NR_PRIORITY_IRQS)) -		return NO_IRQ; - -	raw_spin_lock_irqsave(&irq_big_lock, flags); - -	/* Use hint for 1 interrupt if any */ -	if (count == 1 && hint >= NR_PRIORITY_IRQS && -	    hint < irq_virq_count && irq_map[hint].host == NULL) { -		found = hint; -		goto hint_found; -	} - -	/* Look for count consecutive numbers in the allocatable -	 * (non-legacy) space -	 */ -	for (i = NR_PRIORITY_IRQS, j = 0; i < irq_virq_count; i++) { -		if (irq_map[i].host != NULL) -			j = 0; -		else -			j++; - -		if (j == count) { -			found = i - count + 1; -			break; -		} -	} -	if (found == NO_IRQ) { -		raw_spin_unlock_irqrestore(&irq_big_lock, flags); -		return NO_IRQ; -	} - hint_found: -	for (i = found; i < (found + count); i++) { -		irq_map[i].hwirq = host->inval_irq; -		smp_wmb(); -		irq_map[i].host = host; -	} -	raw_spin_unlock_irqrestore(&irq_big_lock, flags); -	return found; -} - -void irq_free_virt(unsigned int virq, unsigned int count) -{ -	unsigned long flags; -	unsigned int i; - -	WARN_ON(virq < NR_PRIORITY_IRQS); -	WARN_ON(count == 0 || (virq + count) > irq_virq_count); - -	if (virq < NR_PRIORITY_IRQS) { -		if (virq + count < NR_PRIORITY_IRQS) -			return; -		count  -= NR_PRIORITY_IRQS - virq; -		virq = NR_PRIORITY_IRQS; -	} - -	if (count > irq_virq_count || virq > irq_virq_count - count) { -		if (virq > irq_virq_count) -			return; -		count = irq_virq_count - virq; -	} - -	raw_spin_lock_irqsave(&irq_big_lock, flags); -	for (i = virq; i < (virq + count); i++) { -		struct irq_host *host; - -		host = irq_map[i].host; -		irq_map[i].hwirq = host->inval_irq; -		smp_wmb(); -		irq_map[i].host = NULL; -	} -	raw_spin_unlock_irqrestore(&irq_big_lock, flags); -} - -#ifdef CONFIG_VIRQ_DEBUG -static int virq_debug_show(struct seq_file *m, void *private) -{ -	unsigned long flags; -	struct irq_desc *desc; -	const char *p; -	static const char none[] = "none"; -	void *data; -	int i; - -	seq_printf(m, "%-5s  %-7s  %-15s  %-18s  %s\n", "virq", "hwirq", -		      "chip name", "chip data", "host name"); - -	for (i = 1; i < nr_irqs; i++) { -		desc = irq_to_desc(i); -		if (!desc) -			continue; - -		raw_spin_lock_irqsave(&desc->lock, flags); - -		if (desc->action && desc->action->handler) { -			struct irq_chip *chip; - -			seq_printf(m, "%5d  ", i); -			seq_printf(m, "0x%05lx  ", irq_map[i].hwirq); - -			chip = irq_desc_get_chip(desc); -			if (chip && chip->name) -				p = chip->name; -			else -				p = none; -			seq_printf(m, "%-15s  ", p); - -			data = irq_desc_get_chip_data(desc); -			seq_printf(m, "0x%16p  ", data); - -			if (irq_map[i].host && irq_map[i].host->of_node) -				p = irq_map[i].host->of_node->full_name; -			else -				p = none; -			seq_printf(m, "%s\n", p); -		} - -		raw_spin_unlock_irqrestore(&desc->lock, flags); -	} - -	return 0; -} - -static int virq_debug_open(struct inode *inode, struct file *file) -{ -	return single_open(file, virq_debug_show, inode->i_private); -} - -static const struct file_operations virq_debug_fops = { -	.open = virq_debug_open, -	.read = seq_read, -	.llseek = seq_lseek, -	.release = single_release, -}; - -static int __init irq_debugfs_init(void) -{ -	if (debugfs_create_file("virq_mapping", S_IRUGO, powerpc_debugfs_root, -				 NULL, &virq_debug_fops) == NULL) -		return -ENOMEM; - -	return 0; -} -device_initcall(irq_debugfs_init); -#endif /* CONFIG_VIRQ_DEBUG */ diff --git a/arch/c6x/platforms/megamod-pic.c b/arch/c6x/platforms/megamod-pic.c index 7c37a947fb1..c1c4e2ae3f8 100644 --- a/arch/c6x/platforms/megamod-pic.c +++ b/arch/c6x/platforms/megamod-pic.c @@ -48,7 +48,7 @@ struct megamod_regs {  };  struct megamod_pic { -	struct irq_host	*irqhost; +	struct irq_domain *irqhost;  	struct megamod_regs __iomem *regs;  	raw_spinlock_t lock; @@ -116,7 +116,7 @@ static void megamod_irq_cascade(unsigned int irq, struct irq_desc *desc)  	}  } -static int megamod_map(struct irq_host *h, unsigned int virq, +static int megamod_map(struct irq_domain *h, unsigned int virq,  		       irq_hw_number_t hw)  {  	struct megamod_pic *pic = h->host_data; @@ -136,21 +136,9 @@ static int megamod_map(struct irq_host *h, unsigned int virq,  	return 0;  } -static int megamod_xlate(struct irq_host *h, struct device_node *ct, -			 const u32 *intspec, unsigned int intsize, -			 irq_hw_number_t *out_hwirq, unsigned int *out_type) - -{ -	/* megamod intspecs must have 1 cell */ -	BUG_ON(intsize != 1); -	*out_hwirq = intspec[0]; -	*out_type = IRQ_TYPE_NONE; -	return 0; -} - -static struct irq_host_ops megamod_host_ops = { +static const struct irq_domain_ops megamod_domain_ops = {  	.map	= megamod_map, -	.xlate	= megamod_xlate, +	.xlate	= irq_domain_xlate_onecell,  };  static void __init set_megamod_mux(struct megamod_pic *pic, int src, int output) @@ -223,9 +211,8 @@ static struct megamod_pic * __init init_megamod_pic(struct device_node *np)  		return NULL;  	} -	pic->irqhost = irq_alloc_host(np, IRQ_HOST_MAP_LINEAR, -				      NR_COMBINERS * 32, &megamod_host_ops, -				      IRQ_UNMAPPED); +	pic->irqhost = irq_domain_add_linear(np, NR_COMBINERS * 32, +					     &megamod_domain_ops, pic);  	if (!pic->irqhost) {  		pr_err("%s: Could not alloc host.\n", np->full_name);  		goto error_free; diff --git a/arch/microblaze/Kconfig b/arch/microblaze/Kconfig index c8d6efb99db..11060fa87da 100644 --- a/arch/microblaze/Kconfig +++ b/arch/microblaze/Kconfig @@ -14,6 +14,7 @@ config MICROBLAZE  	select TRACING_SUPPORT  	select OF  	select OF_EARLY_FLATTREE +	select IRQ_DOMAIN  	select HAVE_GENERIC_HARDIRQS  	select GENERIC_IRQ_PROBE  	select GENERIC_IRQ_SHOW diff --git a/arch/microblaze/include/asm/hardirq.h b/arch/microblaze/include/asm/hardirq.h index cd1ac9aad56..fb3c05a0cbb 100644 --- a/arch/microblaze/include/asm/hardirq.h +++ b/arch/microblaze/include/asm/hardirq.h @@ -1,17 +1 @@ -/* - * Copyright (C) 2006 Atmark Techno, Inc. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ - -#ifndef _ASM_MICROBLAZE_HARDIRQ_H -#define _ASM_MICROBLAZE_HARDIRQ_H - -/* should be defined in each interrupt controller driver */ -extern unsigned int get_irq(struct pt_regs *regs); -  #include <asm-generic/hardirq.h> - -#endif /* _ASM_MICROBLAZE_HARDIRQ_H */ diff --git a/arch/microblaze/include/asm/irq.h b/arch/microblaze/include/asm/irq.h index a175132e449..bab3b1393ad 100644 --- a/arch/microblaze/include/asm/irq.h +++ b/arch/microblaze/include/asm/irq.h @@ -9,49 +9,13 @@  #ifndef _ASM_MICROBLAZE_IRQ_H  #define _ASM_MICROBLAZE_IRQ_H - -/* - * Linux IRQ# is currently offset by one to map to the hardware - * irq number. So hardware IRQ0 maps to Linux irq 1. - */ -#define NO_IRQ_OFFSET	1 -#define IRQ_OFFSET	NO_IRQ_OFFSET -#define NR_IRQS		(32 + IRQ_OFFSET) +#define NR_IRQS		(32 + 1)  #include <asm-generic/irq.h> -/* This type is the placeholder for a hardware interrupt number. It has to - * be big enough to enclose whatever representation is used by a given - * platform. - */ -typedef unsigned long irq_hw_number_t; - -extern unsigned int nr_irq; -  struct pt_regs;  extern void do_IRQ(struct pt_regs *regs); -/** FIXME - not implement - * irq_dispose_mapping - Unmap an interrupt - * @virq: linux virq number of the interrupt to unmap - */ -static inline void irq_dispose_mapping(unsigned int virq) -{ -	return; -} - -struct irq_host; - -/** - * irq_create_mapping - Map a hardware interrupt into linux virq space - * @host: host owning this hardware interrupt or NULL for default host - * @hwirq: hardware irq number in that host space - * - * Only one mapping per hardware interrupt is permitted. Returns a linux - * virq number. - * If the sense/trigger is to be specified, set_irq_type() should be called - * on the number returned from that call. - */ -extern unsigned int irq_create_mapping(struct irq_host *host, -					irq_hw_number_t hwirq); +/* should be defined in each interrupt controller driver */ +extern unsigned int get_irq(void);  #endif /* _ASM_MICROBLAZE_IRQ_H */ diff --git a/arch/microblaze/kernel/intc.c b/arch/microblaze/kernel/intc.c index 44b177e2ab1..ad120672cee 100644 --- a/arch/microblaze/kernel/intc.c +++ b/arch/microblaze/kernel/intc.c @@ -9,6 +9,7 @@   */  #include <linux/init.h> +#include <linux/irqdomain.h>  #include <linux/irq.h>  #include <asm/page.h>  #include <linux/io.h> @@ -25,8 +26,6 @@ static unsigned int intc_baseaddr;  #define INTC_BASE	intc_baseaddr  #endif -unsigned int nr_irq; -  /* No one else should require these constants, so define them locally here. */  #define ISR 0x00			/* Interrupt Status Register */  #define IPR 0x04			/* Interrupt Pending Register */ @@ -84,24 +83,45 @@ static struct irq_chip intc_dev = {  	.irq_mask_ack = intc_mask_ack,  }; -unsigned int get_irq(struct pt_regs *regs) +static struct irq_domain *root_domain; + +unsigned int get_irq(void)  { -	int irq; +	unsigned int hwirq, irq = -1; -	/* -	 * NOTE: This function is the one that needs to be improved in -	 * order to handle multiple interrupt controllers. It currently -	 * is hardcoded to check for interrupts only on the first INTC. -	 */ -	irq = in_be32(INTC_BASE + IVR) + NO_IRQ_OFFSET; -	pr_debug("get_irq: %d\n", irq); +	hwirq = in_be32(INTC_BASE + IVR); +	if (hwirq != -1U) +		irq = irq_find_mapping(root_domain, hwirq); + +	pr_debug("get_irq: hwirq=%d, irq=%d\n", hwirq, irq);  	return irq;  } +int xintc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw) +{ +	u32 intr_mask = (u32)d->host_data; + +	if (intr_mask & (1 << hw)) { +		irq_set_chip_and_handler_name(irq, &intc_dev, +						handle_edge_irq, "edge"); +		irq_clear_status_flags(irq, IRQ_LEVEL); +	} else { +		irq_set_chip_and_handler_name(irq, &intc_dev, +						handle_level_irq, "level"); +		irq_set_status_flags(irq, IRQ_LEVEL); +	} +	return 0; +} + +static const struct irq_domain_ops xintc_irq_domain_ops = { +	.xlate = irq_domain_xlate_onetwocell, +	.map = xintc_map, +}; +  void __init init_IRQ(void)  { -	u32 i, intr_mask; +	u32 nr_irq, intr_mask;  	struct device_node *intc = NULL;  #ifdef CONFIG_SELFMOD_INTC  	unsigned int intc_baseaddr = 0; @@ -146,16 +166,9 @@ void __init init_IRQ(void)  	/* Turn on the Master Enable. */  	out_be32(intc_baseaddr + MER, MER_HIE | MER_ME); -	for (i = IRQ_OFFSET; i < (nr_irq + IRQ_OFFSET); ++i) { -		if (intr_mask & (0x00000001 << (i - IRQ_OFFSET))) { -			irq_set_chip_and_handler_name(i, &intc_dev, -				handle_edge_irq, "edge"); -			irq_clear_status_flags(i, IRQ_LEVEL); -		} else { -			irq_set_chip_and_handler_name(i, &intc_dev, -				handle_level_irq, "level"); -			irq_set_status_flags(i, IRQ_LEVEL); -		} -		irq_get_irq_data(i)->hwirq = i - IRQ_OFFSET; -	} +	/* Yeah, okay, casting the intr_mask to a void* is butt-ugly, but I'm +	 * lazy and Michal can clean it up to something nicer when he tests +	 * and commits this patch.  ~~gcl */ +	root_domain = irq_domain_add_linear(intc, nr_irq, &xintc_irq_domain_ops, +							(void *)intr_mask);  } diff --git a/arch/microblaze/kernel/irq.c b/arch/microblaze/kernel/irq.c index bbebcae72c0..ace700afbfd 100644 --- a/arch/microblaze/kernel/irq.c +++ b/arch/microblaze/kernel/irq.c @@ -31,14 +31,13 @@ void __irq_entry do_IRQ(struct pt_regs *regs)  	trace_hardirqs_off();  	irq_enter(); -	irq = get_irq(regs); +	irq = get_irq();  next_irq:  	BUG_ON(!irq); -	/* Substract 1 because of get_irq */ -	generic_handle_irq(irq + IRQ_OFFSET - NO_IRQ_OFFSET); +	generic_handle_irq(irq); -	irq = get_irq(regs); -	if (irq) { +	irq = get_irq(); +	if (irq != -1U) {  		pr_debug("next irq: %d\n", irq);  		++concurrent_irq;  		goto next_irq; @@ -48,18 +47,3 @@ next_irq:  	set_irq_regs(old_regs);  	trace_hardirqs_on();  } - -/* MS: There is no any advance mapping mechanism. We are using simple 32bit -  intc without any cascades or any connection that's why mapping is 1:1 */ -unsigned int irq_create_mapping(struct irq_host *host, irq_hw_number_t hwirq) -{ -	return hwirq + IRQ_OFFSET; -} -EXPORT_SYMBOL_GPL(irq_create_mapping); - -unsigned int irq_create_of_mapping(struct device_node *controller, -				   const u32 *intspec, unsigned int intsize) -{ -	return intspec[0] + IRQ_OFFSET; -} -EXPORT_SYMBOL_GPL(irq_create_of_mapping); diff --git a/arch/microblaze/kernel/setup.c b/arch/microblaze/kernel/setup.c index d4fc1a97177..70e6d0b41ab 100644 --- a/arch/microblaze/kernel/setup.c +++ b/arch/microblaze/kernel/setup.c @@ -26,7 +26,6 @@  #include <linux/cache.h>  #include <linux/of_platform.h>  #include <linux/dma-mapping.h> -#include <linux/cpu.h>  #include <asm/cacheflush.h>  #include <asm/entry.h>  #include <asm/cpuinfo.h> @@ -52,8 +51,6 @@ void __init setup_arch(char **cmdline_p)  	unflatten_device_tree(); -	/* NOTE I think that this function is not necessary to call */ -	/* irq_early_init(); */  	setup_cpuinfo();  	microblaze_cache_init(); @@ -227,23 +224,5 @@ static int __init setup_bus_notifier(void)  	return 0;  } -arch_initcall(setup_bus_notifier); - -static DEFINE_PER_CPU(struct cpu, cpu_devices); - -static int __init topology_init(void) -{ -	int i, ret; - -	for_each_present_cpu(i) { -		struct cpu *c = &per_cpu(cpu_devices, i); -		ret = register_cpu(c, i); -		if (ret) -			printk(KERN_WARNING "topology_init: register_cpu %d " -						"failed (%d)\n", i, ret); -	} - -	return 0; -} -subsys_initcall(topology_init); +arch_initcall(setup_bus_notifier); diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index c4c1312473f..edbbae17e82 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -2327,6 +2327,7 @@ config USE_OF  	bool "Flattened Device Tree support"  	select OF  	select OF_EARLY_FLATTREE +	select IRQ_DOMAIN  	help  	  Include support for flattened device tree machine descriptions. @@ -2356,6 +2357,7 @@ config PCI  	depends on HW_HAS_PCI  	select PCI_DOMAINS  	select GENERIC_PCI_IOMAP +	select NO_GENERIC_PCI_IOPORT_MAP  	help  	  Find out whether you have a PCI motherboard. PCI is the name of a  	  bus system, i.e. the way the CPU talks to the other stuff inside diff --git a/arch/mips/include/asm/irq.h b/arch/mips/include/asm/irq.h index 2354c870a63..fb698dc09bc 100644 --- a/arch/mips/include/asm/irq.h +++ b/arch/mips/include/asm/irq.h @@ -11,15 +11,12 @@  #include <linux/linkage.h>  #include <linux/smp.h> +#include <linux/irqdomain.h>  #include <asm/mipsmtregs.h>  #include <irq.h> -static inline void irq_dispose_mapping(unsigned int virq) -{ -} -  #ifdef CONFIG_I8259  static inline int irq_canonicalize(int irq)  { diff --git a/arch/mips/kernel/prom.c b/arch/mips/kernel/prom.c index 6b8b4208481..558b5395795 100644 --- a/arch/mips/kernel/prom.c +++ b/arch/mips/kernel/prom.c @@ -60,20 +60,6 @@ void __init early_init_dt_setup_initrd_arch(unsigned long start,  }  #endif -/* - * irq_create_of_mapping - Hook to resolve OF irq specifier into a Linux irq# - * - * Currently the mapping mechanism is trivial; simple flat hwirq numbers are - * mapped 1:1 onto Linux irq numbers.  Cascaded irq controllers are not - * supported. - */ -unsigned int irq_create_of_mapping(struct device_node *controller, -				   const u32 *intspec, unsigned int intsize) -{ -	return intspec[0]; -} -EXPORT_SYMBOL_GPL(irq_create_of_mapping); -  void __init early_init_devtree(void *params)  {  	/* Setup flat device-tree pointer */ diff --git a/arch/mips/lib/iomap-pci.c b/arch/mips/lib/iomap-pci.c index 2635b1a9633..fd35daa4531 100644 --- a/arch/mips/lib/iomap-pci.c +++ b/arch/mips/lib/iomap-pci.c @@ -10,8 +10,8 @@  #include <linux/module.h>  #include <asm/io.h> -static void __iomem *ioport_map_pci(struct pci_dev *dev, -                                     unsigned long port, unsigned int nr) +void __iomem *__pci_ioport_map(struct pci_dev *dev, +			       unsigned long port, unsigned int nr)  {  	struct pci_controller *ctrl = dev->bus->sysdata;  	unsigned long base = ctrl->io_map_base; diff --git a/arch/openrisc/include/asm/prom.h b/arch/openrisc/include/asm/prom.h index e1f3fe26606..bbb34e5343a 100644 --- a/arch/openrisc/include/asm/prom.h +++ b/arch/openrisc/include/asm/prom.h @@ -24,6 +24,7 @@  #include <linux/types.h>  #include <asm/irq.h> +#include <linux/irqdomain.h>  #include <linux/atomic.h>  #include <linux/of_irq.h>  #include <linux/of_fdt.h> @@ -63,15 +64,6 @@ extern const void *of_get_mac_address(struct device_node *np);  struct pci_dev;  extern int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq); -/* This routine is here to provide compatibility with how powerpc - * handles IRQ mapping for OF device nodes.  We precompute and permanently - * register them in the platform_device objects, whereas powerpc computes them - * on request. - */ -static inline void irq_dispose_mapping(unsigned int virq) -{ -} -  #endif /* __ASSEMBLY__ */  #endif /* __KERNEL__ */  #endif /* _ASM_OPENRISC_PROM_H */ diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 1919634a9b3..303703d716f 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -135,6 +135,7 @@ config PPC  	select HAVE_GENERIC_HARDIRQS  	select HAVE_SPARSE_IRQ  	select IRQ_PER_CPU +	select IRQ_DOMAIN  	select GENERIC_IRQ_SHOW  	select GENERIC_IRQ_SHOW_LEVEL  	select IRQ_FORCED_THREADING diff --git a/arch/powerpc/include/asm/ehv_pic.h b/arch/powerpc/include/asm/ehv_pic.h index a9e1f4f796f..dc7d48e3ea9 100644 --- a/arch/powerpc/include/asm/ehv_pic.h +++ b/arch/powerpc/include/asm/ehv_pic.h @@ -25,7 +25,7 @@  struct ehv_pic {  	/* The remapper for this EHV_PIC */ -	struct irq_host	*irqhost; +	struct irq_domain	*irqhost;  	/* The "linux" controller struct */  	struct irq_chip	hc_irq; diff --git a/arch/powerpc/include/asm/i8259.h b/arch/powerpc/include/asm/i8259.h index 105ade297aa..c3fdfbd5a67 100644 --- a/arch/powerpc/include/asm/i8259.h +++ b/arch/powerpc/include/asm/i8259.h @@ -6,7 +6,7 @@  extern void i8259_init(struct device_node *node, unsigned long intack_addr);  extern unsigned int i8259_irq(void); -extern struct irq_host *i8259_get_host(void); +extern struct irq_domain *i8259_get_host(void);  #endif /* __KERNEL__ */  #endif /* _ASM_POWERPC_I8259_H */ diff --git a/arch/powerpc/include/asm/irq.h b/arch/powerpc/include/asm/irq.h index c0e1bc319e3..fe0b09dceb7 100644 --- a/arch/powerpc/include/asm/irq.h +++ b/arch/powerpc/include/asm/irq.h @@ -9,6 +9,7 @@   * 2 of the License, or (at your option) any later version.   */ +#include <linux/irqdomain.h>  #include <linux/threads.h>  #include <linux/list.h>  #include <linux/radix-tree.h> @@ -35,258 +36,12 @@ extern atomic_t ppc_n_lost_interrupts;  /* Total number of virq in the platform */  #define NR_IRQS		CONFIG_NR_IRQS -/* Number of irqs reserved for the legacy controller */ -#define NUM_ISA_INTERRUPTS	16 -  /* Same thing, used by the generic IRQ code */  #define NR_IRQS_LEGACY		NUM_ISA_INTERRUPTS -/* This type is the placeholder for a hardware interrupt number. It has to - * be big enough to enclose whatever representation is used by a given - * platform. - */ -typedef unsigned long irq_hw_number_t; - -/* Interrupt controller "host" data structure. This could be defined as a - * irq domain controller. That is, it handles the mapping between hardware - * and virtual interrupt numbers for a given interrupt domain. The host - * structure is generally created by the PIC code for a given PIC instance - * (though a host can cover more than one PIC if they have a flat number - * model). It's the host callbacks that are responsible for setting the - * irq_chip on a given irq_desc after it's been mapped. - * - * The host code and data structures are fairly agnostic to the fact that - * we use an open firmware device-tree. We do have references to struct - * device_node in two places: in irq_find_host() to find the host matching - * a given interrupt controller node, and of course as an argument to its - * counterpart host->ops->match() callback. However, those are treated as - * generic pointers by the core and the fact that it's actually a device-node - * pointer is purely a convention between callers and implementation. This - * code could thus be used on other architectures by replacing those two - * by some sort of arch-specific void * "token" used to identify interrupt - * controllers. - */ -struct irq_host; -struct radix_tree_root; - -/* Functions below are provided by the host and called whenever a new mapping - * is created or an old mapping is disposed. The host can then proceed to - * whatever internal data structures management is required. It also needs - * to setup the irq_desc when returning from map(). - */ -struct irq_host_ops { -	/* Match an interrupt controller device node to a host, returns -	 * 1 on a match -	 */ -	int (*match)(struct irq_host *h, struct device_node *node); - -	/* Create or update a mapping between a virtual irq number and a hw -	 * irq number. This is called only once for a given mapping. -	 */ -	int (*map)(struct irq_host *h, unsigned int virq, irq_hw_number_t hw); - -	/* Dispose of such a mapping */ -	void (*unmap)(struct irq_host *h, unsigned int virq); - -	/* Translate device-tree interrupt specifier from raw format coming -	 * from the firmware to a irq_hw_number_t (interrupt line number) and -	 * type (sense) that can be passed to set_irq_type(). In the absence -	 * of this callback, irq_create_of_mapping() and irq_of_parse_and_map() -	 * will return the hw number in the first cell and IRQ_TYPE_NONE for -	 * the type (which amount to keeping whatever default value the -	 * interrupt controller has for that line) -	 */ -	int (*xlate)(struct irq_host *h, struct device_node *ctrler, -		     const u32 *intspec, unsigned int intsize, -		     irq_hw_number_t *out_hwirq, unsigned int *out_type); -}; - -struct irq_host { -	struct list_head	link; - -	/* type of reverse mapping technique */ -	unsigned int		revmap_type; -#define IRQ_HOST_MAP_LEGACY     0 /* legacy 8259, gets irqs 1..15 */ -#define IRQ_HOST_MAP_NOMAP	1 /* no fast reverse mapping */ -#define IRQ_HOST_MAP_LINEAR	2 /* linear map of interrupts */ -#define IRQ_HOST_MAP_TREE	3 /* radix tree */ -	union { -		struct { -			unsigned int size; -			unsigned int *revmap; -		} linear; -		struct radix_tree_root tree; -	} revmap_data; -	struct irq_host_ops	*ops; -	void			*host_data; -	irq_hw_number_t		inval_irq; - -	/* Optional device node pointer */ -	struct device_node	*of_node; -}; -  struct irq_data;  extern irq_hw_number_t irqd_to_hwirq(struct irq_data *d);  extern irq_hw_number_t virq_to_hw(unsigned int virq); -extern bool virq_is_host(unsigned int virq, struct irq_host *host); - -/** - * irq_alloc_host - Allocate a new irq_host data structure - * @of_node: optional device-tree node of the interrupt controller - * @revmap_type: type of reverse mapping to use - * @revmap_arg: for IRQ_HOST_MAP_LINEAR linear only: size of the map - * @ops: map/unmap host callbacks - * @inval_irq: provide a hw number in that host space that is always invalid - * - * Allocates and initialize and irq_host structure. Note that in the case of - * IRQ_HOST_MAP_LEGACY, the map() callback will be called before this returns - * for all legacy interrupts except 0 (which is always the invalid irq for - * a legacy controller). For a IRQ_HOST_MAP_LINEAR, the map is allocated by - * this call as well. For a IRQ_HOST_MAP_TREE, the radix tree will be allocated - * later during boot automatically (the reverse mapping will use the slow path - * until that happens). - */ -extern struct irq_host *irq_alloc_host(struct device_node *of_node, -				       unsigned int revmap_type, -				       unsigned int revmap_arg, -				       struct irq_host_ops *ops, -				       irq_hw_number_t inval_irq); - - -/** - * irq_find_host - Locates a host for a given device node - * @node: device-tree node of the interrupt controller - */ -extern struct irq_host *irq_find_host(struct device_node *node); - - -/** - * irq_set_default_host - Set a "default" host - * @host: default host pointer - * - * For convenience, it's possible to set a "default" host that will be used - * whenever NULL is passed to irq_create_mapping(). It makes life easier for - * platforms that want to manipulate a few hard coded interrupt numbers that - * aren't properly represented in the device-tree. - */ -extern void irq_set_default_host(struct irq_host *host); - - -/** - * irq_set_virq_count - Set the maximum number of virt irqs - * @count: number of linux virtual irqs, capped with NR_IRQS - * - * This is mainly for use by platforms like iSeries who want to program - * the virtual irq number in the controller to avoid the reverse mapping - */ -extern void irq_set_virq_count(unsigned int count); - - -/** - * irq_create_mapping - Map a hardware interrupt into linux virq space - * @host: host owning this hardware interrupt or NULL for default host - * @hwirq: hardware irq number in that host space - * - * Only one mapping per hardware interrupt is permitted. Returns a linux - * virq number. - * If the sense/trigger is to be specified, set_irq_type() should be called - * on the number returned from that call. - */ -extern unsigned int irq_create_mapping(struct irq_host *host, -				       irq_hw_number_t hwirq); - - -/** - * irq_dispose_mapping - Unmap an interrupt - * @virq: linux virq number of the interrupt to unmap - */ -extern void irq_dispose_mapping(unsigned int virq); - -/** - * irq_find_mapping - Find a linux virq from an hw irq number. - * @host: host owning this hardware interrupt - * @hwirq: hardware irq number in that host space - * - * This is a slow path, for use by generic code. It's expected that an - * irq controller implementation directly calls the appropriate low level - * mapping function. - */ -extern unsigned int irq_find_mapping(struct irq_host *host, -				     irq_hw_number_t hwirq); - -/** - * irq_create_direct_mapping - Allocate a virq for direct mapping - * @host: host to allocate the virq for or NULL for default host - * - * This routine is used for irq controllers which can choose the hardware - * interrupt numbers they generate. In such a case it's simplest to use - * the linux virq as the hardware interrupt number. - */ -extern unsigned int irq_create_direct_mapping(struct irq_host *host); - -/** - * irq_radix_revmap_insert - Insert a hw irq to linux virq number mapping. - * @host: host owning this hardware interrupt - * @virq: linux irq number - * @hwirq: hardware irq number in that host space - * - * This is for use by irq controllers that use a radix tree reverse - * mapping for fast lookup. - */ -extern void irq_radix_revmap_insert(struct irq_host *host, unsigned int virq, -				    irq_hw_number_t hwirq); - -/** - * irq_radix_revmap_lookup - Find a linux virq from a hw irq number. - * @host: host owning this hardware interrupt - * @hwirq: hardware irq number in that host space - * - * This is a fast path, for use by irq controller code that uses radix tree - * revmaps - */ -extern unsigned int irq_radix_revmap_lookup(struct irq_host *host, -					    irq_hw_number_t hwirq); - -/** - * irq_linear_revmap - Find a linux virq from a hw irq number. - * @host: host owning this hardware interrupt - * @hwirq: hardware irq number in that host space - * - * This is a fast path, for use by irq controller code that uses linear - * revmaps. It does fallback to the slow path if the revmap doesn't exist - * yet and will create the revmap entry with appropriate locking - */ - -extern unsigned int irq_linear_revmap(struct irq_host *host, -				      irq_hw_number_t hwirq); - - - -/** - * irq_alloc_virt - Allocate virtual irq numbers - * @host: host owning these new virtual irqs - * @count: number of consecutive numbers to allocate - * @hint: pass a hint number, the allocator will try to use a 1:1 mapping - * - * This is a low level function that is used internally by irq_create_mapping() - * and that can be used by some irq controllers implementations for things - * like allocating ranges of numbers for MSIs. The revmaps are left untouched. - */ -extern unsigned int irq_alloc_virt(struct irq_host *host, -				   unsigned int count, -				   unsigned int hint); - -/** - * irq_free_virt - Free virtual irq numbers - * @virq: virtual irq number of the first interrupt to free - * @count: number of interrupts to free - * - * This function is the opposite of irq_alloc_virt. It will not clear reverse - * maps, this should be done previously by unmap'ing the interrupt. In fact, - * all interrupts covered by the range being freed should have been unmapped - * prior to calling this. - */ -extern void irq_free_virt(unsigned int virq, unsigned int count);  /**   * irq_early_init - Init irq remapping subsystem diff --git a/arch/powerpc/include/asm/mpic.h b/arch/powerpc/include/asm/mpic.h index 67b4d983723..a5b7c56237f 100644 --- a/arch/powerpc/include/asm/mpic.h +++ b/arch/powerpc/include/asm/mpic.h @@ -255,7 +255,7 @@ struct mpic  	struct device_node *node;  	/* The remapper for this MPIC */ -	struct irq_host		*irqhost; +	struct irq_domain	*irqhost;  	/* The "linux" controller struct */  	struct irq_chip		hc_irq; diff --git a/arch/powerpc/include/asm/xics.h b/arch/powerpc/include/asm/xics.h index c48de98ba94..4ae9a09c3b8 100644 --- a/arch/powerpc/include/asm/xics.h +++ b/arch/powerpc/include/asm/xics.h @@ -86,7 +86,7 @@ struct ics {  extern unsigned int xics_default_server;  extern unsigned int xics_default_distrib_server;  extern unsigned int xics_interrupt_server_size; -extern struct irq_host *xics_host; +extern struct irq_domain *xics_host;  struct xics_cppr {  	unsigned char stack[MAX_NUM_PRIORITIES]; diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index 701d4aceb4f..e3673ff6b7a 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c @@ -486,409 +486,19 @@ void do_softirq(void)  	local_irq_restore(flags);  } - -/* - * IRQ controller and virtual interrupts - */ - -/* The main irq map itself is an array of NR_IRQ entries containing the - * associate host and irq number. An entry with a host of NULL is free. - * An entry can be allocated if it's free, the allocator always then sets - * hwirq first to the host's invalid irq number and then fills ops. - */ -struct irq_map_entry { -	irq_hw_number_t	hwirq; -	struct irq_host	*host; -}; - -static LIST_HEAD(irq_hosts); -static DEFINE_RAW_SPINLOCK(irq_big_lock); -static DEFINE_MUTEX(revmap_trees_mutex); -static struct irq_map_entry irq_map[NR_IRQS]; -static unsigned int irq_virq_count = NR_IRQS; -static struct irq_host *irq_default_host; -  irq_hw_number_t irqd_to_hwirq(struct irq_data *d)  { -	return irq_map[d->irq].hwirq; +	return d->hwirq;  }  EXPORT_SYMBOL_GPL(irqd_to_hwirq);  irq_hw_number_t virq_to_hw(unsigned int virq)  { -	return irq_map[virq].hwirq; +	struct irq_data *irq_data = irq_get_irq_data(virq); +	return WARN_ON(!irq_data) ? 0 : irq_data->hwirq;  }  EXPORT_SYMBOL_GPL(virq_to_hw); -bool virq_is_host(unsigned int virq, struct irq_host *host) -{ -	return irq_map[virq].host == host; -} -EXPORT_SYMBOL_GPL(virq_is_host); - -static int default_irq_host_match(struct irq_host *h, struct device_node *np) -{ -	return h->of_node != NULL && h->of_node == np; -} - -struct irq_host *irq_alloc_host(struct device_node *of_node, -				unsigned int revmap_type, -				unsigned int revmap_arg, -				struct irq_host_ops *ops, -				irq_hw_number_t inval_irq) -{ -	struct irq_host *host; -	unsigned int size = sizeof(struct irq_host); -	unsigned int i; -	unsigned int *rmap; -	unsigned long flags; - -	/* Allocate structure and revmap table if using linear mapping */ -	if (revmap_type == IRQ_HOST_MAP_LINEAR) -		size += revmap_arg * sizeof(unsigned int); -	host = kzalloc(size, GFP_KERNEL); -	if (host == NULL) -		return NULL; - -	/* Fill structure */ -	host->revmap_type = revmap_type; -	host->inval_irq = inval_irq; -	host->ops = ops; -	host->of_node = of_node_get(of_node); - -	if (host->ops->match == NULL) -		host->ops->match = default_irq_host_match; - -	raw_spin_lock_irqsave(&irq_big_lock, flags); - -	/* If it's a legacy controller, check for duplicates and -	 * mark it as allocated (we use irq 0 host pointer for that -	 */ -	if (revmap_type == IRQ_HOST_MAP_LEGACY) { -		if (irq_map[0].host != NULL) { -			raw_spin_unlock_irqrestore(&irq_big_lock, flags); -			of_node_put(host->of_node); -			kfree(host); -			return NULL; -		} -		irq_map[0].host = host; -	} - -	list_add(&host->link, &irq_hosts); -	raw_spin_unlock_irqrestore(&irq_big_lock, flags); - -	/* Additional setups per revmap type */ -	switch(revmap_type) { -	case IRQ_HOST_MAP_LEGACY: -		/* 0 is always the invalid number for legacy */ -		host->inval_irq = 0; -		/* setup us as the host for all legacy interrupts */ -		for (i = 1; i < NUM_ISA_INTERRUPTS; i++) { -			irq_map[i].hwirq = i; -			smp_wmb(); -			irq_map[i].host = host; -			smp_wmb(); - -			/* Legacy flags are left to default at this point, -			 * one can then use irq_create_mapping() to -			 * explicitly change them -			 */ -			ops->map(host, i, i); - -			/* Clear norequest flags */ -			irq_clear_status_flags(i, IRQ_NOREQUEST); -		} -		break; -	case IRQ_HOST_MAP_LINEAR: -		rmap = (unsigned int *)(host + 1); -		for (i = 0; i < revmap_arg; i++) -			rmap[i] = NO_IRQ; -		host->revmap_data.linear.size = revmap_arg; -		smp_wmb(); -		host->revmap_data.linear.revmap = rmap; -		break; -	case IRQ_HOST_MAP_TREE: -		INIT_RADIX_TREE(&host->revmap_data.tree, GFP_KERNEL); -		break; -	default: -		break; -	} - -	pr_debug("irq: Allocated host of type %d @0x%p\n", revmap_type, host); - -	return host; -} - -struct irq_host *irq_find_host(struct device_node *node) -{ -	struct irq_host *h, *found = NULL; -	unsigned long flags; - -	/* We might want to match the legacy controller last since -	 * it might potentially be set to match all interrupts in -	 * the absence of a device node. This isn't a problem so far -	 * yet though... -	 */ -	raw_spin_lock_irqsave(&irq_big_lock, flags); -	list_for_each_entry(h, &irq_hosts, link) -		if (h->ops->match(h, node)) { -			found = h; -			break; -		} -	raw_spin_unlock_irqrestore(&irq_big_lock, flags); -	return found; -} -EXPORT_SYMBOL_GPL(irq_find_host); - -void irq_set_default_host(struct irq_host *host) -{ -	pr_debug("irq: Default host set to @0x%p\n", host); - -	irq_default_host = host; -} - -void irq_set_virq_count(unsigned int count) -{ -	pr_debug("irq: Trying to set virq count to %d\n", count); - -	BUG_ON(count < NUM_ISA_INTERRUPTS); -	if (count < NR_IRQS) -		irq_virq_count = count; -} - -static int irq_setup_virq(struct irq_host *host, unsigned int virq, -			    irq_hw_number_t hwirq) -{ -	int res; - -	res = irq_alloc_desc_at(virq, 0); -	if (res != virq) { -		pr_debug("irq: -> allocating desc failed\n"); -		goto error; -	} - -	/* map it */ -	smp_wmb(); -	irq_map[virq].hwirq = hwirq; -	smp_mb(); - -	if (host->ops->map(host, virq, hwirq)) { -		pr_debug("irq: -> mapping failed, freeing\n"); -		goto errdesc; -	} - -	irq_clear_status_flags(virq, IRQ_NOREQUEST); - -	return 0; - -errdesc: -	irq_free_descs(virq, 1); -error: -	irq_free_virt(virq, 1); -	return -1; -} - -unsigned int irq_create_direct_mapping(struct irq_host *host) -{ -	unsigned int virq; - -	if (host == NULL) -		host = irq_default_host; - -	BUG_ON(host == NULL); -	WARN_ON(host->revmap_type != IRQ_HOST_MAP_NOMAP); - -	virq = irq_alloc_virt(host, 1, 0); -	if (virq == NO_IRQ) { -		pr_debug("irq: create_direct virq allocation failed\n"); -		return NO_IRQ; -	} - -	pr_debug("irq: create_direct obtained virq %d\n", virq); - -	if (irq_setup_virq(host, virq, virq)) -		return NO_IRQ; - -	return virq; -} - -unsigned int irq_create_mapping(struct irq_host *host, -				irq_hw_number_t hwirq) -{ -	unsigned int virq, hint; - -	pr_debug("irq: irq_create_mapping(0x%p, 0x%lx)\n", host, hwirq); - -	/* Look for default host if nececssary */ -	if (host == NULL) -		host = irq_default_host; -	if (host == NULL) { -		printk(KERN_WARNING "irq_create_mapping called for" -		       " NULL host, hwirq=%lx\n", hwirq); -		WARN_ON(1); -		return NO_IRQ; -	} -	pr_debug("irq: -> using host @%p\n", host); - -	/* Check if mapping already exists */ -	virq = irq_find_mapping(host, hwirq); -	if (virq != NO_IRQ) { -		pr_debug("irq: -> existing mapping on virq %d\n", virq); -		return virq; -	} - -	/* Get a virtual interrupt number */ -	if (host->revmap_type == IRQ_HOST_MAP_LEGACY) { -		/* Handle legacy */ -		virq = (unsigned int)hwirq; -		if (virq == 0 || virq >= NUM_ISA_INTERRUPTS) -			return NO_IRQ; -		return virq; -	} else { -		/* Allocate a virtual interrupt number */ -		hint = hwirq % irq_virq_count; -		virq = irq_alloc_virt(host, 1, hint); -		if (virq == NO_IRQ) { -			pr_debug("irq: -> virq allocation failed\n"); -			return NO_IRQ; -		} -	} - -	if (irq_setup_virq(host, virq, hwirq)) -		return NO_IRQ; - -	pr_debug("irq: irq %lu on host %s mapped to virtual irq %u\n", -		hwirq, host->of_node ? host->of_node->full_name : "null", virq); - -	return virq; -} -EXPORT_SYMBOL_GPL(irq_create_mapping); - -unsigned int irq_create_of_mapping(struct device_node *controller, -				   const u32 *intspec, unsigned int intsize) -{ -	struct irq_host *host; -	irq_hw_number_t hwirq; -	unsigned int type = IRQ_TYPE_NONE; -	unsigned int virq; - -	if (controller == NULL) -		host = irq_default_host; -	else -		host = irq_find_host(controller); -	if (host == NULL) { -		printk(KERN_WARNING "irq: no irq host found for %s !\n", -		       controller->full_name); -		return NO_IRQ; -	} - -	/* If host has no translation, then we assume interrupt line */ -	if (host->ops->xlate == NULL) -		hwirq = intspec[0]; -	else { -		if (host->ops->xlate(host, controller, intspec, intsize, -				     &hwirq, &type)) -			return NO_IRQ; -	} - -	/* Create mapping */ -	virq = irq_create_mapping(host, hwirq); -	if (virq == NO_IRQ) -		return virq; - -	/* Set type if specified and different than the current one */ -	if (type != IRQ_TYPE_NONE && -	    type != (irqd_get_trigger_type(irq_get_irq_data(virq)))) -		irq_set_irq_type(virq, type); -	return virq; -} -EXPORT_SYMBOL_GPL(irq_create_of_mapping); - -void irq_dispose_mapping(unsigned int virq) -{ -	struct irq_host *host; -	irq_hw_number_t hwirq; - -	if (virq == NO_IRQ) -		return; - -	host = irq_map[virq].host; -	if (WARN_ON(host == NULL)) -		return; - -	/* Never unmap legacy interrupts */ -	if (host->revmap_type == IRQ_HOST_MAP_LEGACY) -		return; - -	irq_set_status_flags(virq, IRQ_NOREQUEST); - -	/* remove chip and handler */ -	irq_set_chip_and_handler(virq, NULL, NULL); - -	/* Make sure it's completed */ -	synchronize_irq(virq); - -	/* Tell the PIC about it */ -	if (host->ops->unmap) -		host->ops->unmap(host, virq); -	smp_mb(); - -	/* Clear reverse map */ -	hwirq = irq_map[virq].hwirq; -	switch(host->revmap_type) { -	case IRQ_HOST_MAP_LINEAR: -		if (hwirq < host->revmap_data.linear.size) -			host->revmap_data.linear.revmap[hwirq] = NO_IRQ; -		break; -	case IRQ_HOST_MAP_TREE: -		mutex_lock(&revmap_trees_mutex); -		radix_tree_delete(&host->revmap_data.tree, hwirq); -		mutex_unlock(&revmap_trees_mutex); -		break; -	} - -	/* Destroy map */ -	smp_mb(); -	irq_map[virq].hwirq = host->inval_irq; - -	irq_free_descs(virq, 1); -	/* Free it */ -	irq_free_virt(virq, 1); -} -EXPORT_SYMBOL_GPL(irq_dispose_mapping); - -unsigned int irq_find_mapping(struct irq_host *host, -			      irq_hw_number_t hwirq) -{ -	unsigned int i; -	unsigned int hint = hwirq % irq_virq_count; - -	/* Look for default host if nececssary */ -	if (host == NULL) -		host = irq_default_host; -	if (host == NULL) -		return NO_IRQ; - -	/* legacy -> bail early */ -	if (host->revmap_type == IRQ_HOST_MAP_LEGACY) -		return hwirq; - -	/* Slow path does a linear search of the map */ -	if (hint < NUM_ISA_INTERRUPTS) -		hint = NUM_ISA_INTERRUPTS; -	i = hint; -	do  { -		if (irq_map[i].host == host && -		    irq_map[i].hwirq == hwirq) -			return i; -		i++; -		if (i >= irq_virq_count) -			i = NUM_ISA_INTERRUPTS; -	} while(i != hint); -	return NO_IRQ; -} -EXPORT_SYMBOL_GPL(irq_find_mapping); -  #ifdef CONFIG_SMP  int irq_choose_cpu(const struct cpumask *mask)  { @@ -925,232 +535,11 @@ int irq_choose_cpu(const struct cpumask *mask)  }  #endif -unsigned int irq_radix_revmap_lookup(struct irq_host *host, -				     irq_hw_number_t hwirq) -{ -	struct irq_map_entry *ptr; -	unsigned int virq; - -	if (WARN_ON_ONCE(host->revmap_type != IRQ_HOST_MAP_TREE)) -		return irq_find_mapping(host, hwirq); - -	/* -	 * The ptr returned references the static global irq_map. -	 * but freeing an irq can delete nodes along the path to -	 * do the lookup via call_rcu. -	 */ -	rcu_read_lock(); -	ptr = radix_tree_lookup(&host->revmap_data.tree, hwirq); -	rcu_read_unlock(); - -	/* -	 * If found in radix tree, then fine. -	 * Else fallback to linear lookup - this should not happen in practice -	 * as it means that we failed to insert the node in the radix tree. -	 */ -	if (ptr) -		virq = ptr - irq_map; -	else -		virq = irq_find_mapping(host, hwirq); - -	return virq; -} - -void irq_radix_revmap_insert(struct irq_host *host, unsigned int virq, -			     irq_hw_number_t hwirq) -{ -	if (WARN_ON(host->revmap_type != IRQ_HOST_MAP_TREE)) -		return; - -	if (virq != NO_IRQ) { -		mutex_lock(&revmap_trees_mutex); -		radix_tree_insert(&host->revmap_data.tree, hwirq, -				  &irq_map[virq]); -		mutex_unlock(&revmap_trees_mutex); -	} -} - -unsigned int irq_linear_revmap(struct irq_host *host, -			       irq_hw_number_t hwirq) -{ -	unsigned int *revmap; - -	if (WARN_ON_ONCE(host->revmap_type != IRQ_HOST_MAP_LINEAR)) -		return irq_find_mapping(host, hwirq); - -	/* Check revmap bounds */ -	if (unlikely(hwirq >= host->revmap_data.linear.size)) -		return irq_find_mapping(host, hwirq); - -	/* Check if revmap was allocated */ -	revmap = host->revmap_data.linear.revmap; -	if (unlikely(revmap == NULL)) -		return irq_find_mapping(host, hwirq); - -	/* Fill up revmap with slow path if no mapping found */ -	if (unlikely(revmap[hwirq] == NO_IRQ)) -		revmap[hwirq] = irq_find_mapping(host, hwirq); - -	return revmap[hwirq]; -} - -unsigned int irq_alloc_virt(struct irq_host *host, -			    unsigned int count, -			    unsigned int hint) -{ -	unsigned long flags; -	unsigned int i, j, found = NO_IRQ; - -	if (count == 0 || count > (irq_virq_count - NUM_ISA_INTERRUPTS)) -		return NO_IRQ; - -	raw_spin_lock_irqsave(&irq_big_lock, flags); - -	/* Use hint for 1 interrupt if any */ -	if (count == 1 && hint >= NUM_ISA_INTERRUPTS && -	    hint < irq_virq_count && irq_map[hint].host == NULL) { -		found = hint; -		goto hint_found; -	} - -	/* Look for count consecutive numbers in the allocatable -	 * (non-legacy) space -	 */ -	for (i = NUM_ISA_INTERRUPTS, j = 0; i < irq_virq_count; i++) { -		if (irq_map[i].host != NULL) -			j = 0; -		else -			j++; - -		if (j == count) { -			found = i - count + 1; -			break; -		} -	} -	if (found == NO_IRQ) { -		raw_spin_unlock_irqrestore(&irq_big_lock, flags); -		return NO_IRQ; -	} - hint_found: -	for (i = found; i < (found + count); i++) { -		irq_map[i].hwirq = host->inval_irq; -		smp_wmb(); -		irq_map[i].host = host; -	} -	raw_spin_unlock_irqrestore(&irq_big_lock, flags); -	return found; -} - -void irq_free_virt(unsigned int virq, unsigned int count) -{ -	unsigned long flags; -	unsigned int i; - -	WARN_ON (virq < NUM_ISA_INTERRUPTS); -	WARN_ON (count == 0 || (virq + count) > irq_virq_count); - -	if (virq < NUM_ISA_INTERRUPTS) { -		if (virq + count < NUM_ISA_INTERRUPTS) -			return; -		count  =- NUM_ISA_INTERRUPTS - virq; -		virq = NUM_ISA_INTERRUPTS; -	} - -	if (count > irq_virq_count || virq > irq_virq_count - count) { -		if (virq > irq_virq_count) -			return; -		count = irq_virq_count - virq; -	} - -	raw_spin_lock_irqsave(&irq_big_lock, flags); -	for (i = virq; i < (virq + count); i++) { -		struct irq_host *host; - -		host = irq_map[i].host; -		irq_map[i].hwirq = host->inval_irq; -		smp_wmb(); -		irq_map[i].host = NULL; -	} -	raw_spin_unlock_irqrestore(&irq_big_lock, flags); -} -  int arch_early_irq_init(void)  {  	return 0;  } -#ifdef CONFIG_VIRQ_DEBUG -static int virq_debug_show(struct seq_file *m, void *private) -{ -	unsigned long flags; -	struct irq_desc *desc; -	const char *p; -	static const char none[] = "none"; -	void *data; -	int i; - -	seq_printf(m, "%-5s  %-7s  %-15s  %-18s  %s\n", "virq", "hwirq", -		      "chip name", "chip data", "host name"); - -	for (i = 1; i < nr_irqs; i++) { -		desc = irq_to_desc(i); -		if (!desc) -			continue; - -		raw_spin_lock_irqsave(&desc->lock, flags); - -		if (desc->action && desc->action->handler) { -			struct irq_chip *chip; - -			seq_printf(m, "%5d  ", i); -			seq_printf(m, "0x%05lx  ", irq_map[i].hwirq); - -			chip = irq_desc_get_chip(desc); -			if (chip && chip->name) -				p = chip->name; -			else -				p = none; -			seq_printf(m, "%-15s  ", p); - -			data = irq_desc_get_chip_data(desc); -			seq_printf(m, "0x%16p  ", data); - -			if (irq_map[i].host && irq_map[i].host->of_node) -				p = irq_map[i].host->of_node->full_name; -			else -				p = none; -			seq_printf(m, "%s\n", p); -		} - -		raw_spin_unlock_irqrestore(&desc->lock, flags); -	} - -	return 0; -} - -static int virq_debug_open(struct inode *inode, struct file *file) -{ -	return single_open(file, virq_debug_show, inode->i_private); -} - -static const struct file_operations virq_debug_fops = { -	.open = virq_debug_open, -	.read = seq_read, -	.llseek = seq_lseek, -	.release = single_release, -}; - -static int __init irq_debugfs_init(void) -{ -	if (debugfs_create_file("virq_mapping", S_IRUGO, powerpc_debugfs_root, -				 NULL, &virq_debug_fops) == NULL) -		return -ENOMEM; - -	return 0; -} -__initcall(irq_debugfs_init); -#endif /* CONFIG_VIRQ_DEBUG */ -  #ifdef CONFIG_PPC64  static int __init setup_noirqdistrib(char *str)  { diff --git a/arch/powerpc/platforms/512x/mpc5121_ads_cpld.c b/arch/powerpc/platforms/512x/mpc5121_ads_cpld.c index 9f09319352c..ca3a062ed1b 100644 --- a/arch/powerpc/platforms/512x/mpc5121_ads_cpld.c +++ b/arch/powerpc/platforms/512x/mpc5121_ads_cpld.c @@ -21,7 +21,7 @@  #include <asm/prom.h>  static struct device_node *cpld_pic_node; -static struct irq_host *cpld_pic_host; +static struct irq_domain *cpld_pic_host;  /*   * Bits to ignore in the misc_status register @@ -123,13 +123,13 @@ cpld_pic_cascade(unsigned int irq, struct irq_desc *desc)  }  static int -cpld_pic_host_match(struct irq_host *h, struct device_node *node) +cpld_pic_host_match(struct irq_domain *h, struct device_node *node)  {  	return cpld_pic_node == node;  }  static int -cpld_pic_host_map(struct irq_host *h, unsigned int virq, +cpld_pic_host_map(struct irq_domain *h, unsigned int virq,  			     irq_hw_number_t hw)  {  	irq_set_status_flags(virq, IRQ_LEVEL); @@ -137,8 +137,7 @@ cpld_pic_host_map(struct irq_host *h, unsigned int virq,  	return 0;  } -static struct -irq_host_ops cpld_pic_host_ops = { +static const struct irq_domain_ops cpld_pic_host_ops = {  	.match = cpld_pic_host_match,  	.map = cpld_pic_host_map,  }; @@ -191,8 +190,7 @@ mpc5121_ads_cpld_pic_init(void)  	cpld_pic_node = of_node_get(np); -	cpld_pic_host = -	    irq_alloc_host(np, IRQ_HOST_MAP_LINEAR, 16, &cpld_pic_host_ops, 16); +	cpld_pic_host = irq_domain_add_linear(np, 16, &cpld_pic_host_ops, NULL);  	if (!cpld_pic_host) {  		printk(KERN_ERR "CPLD PIC: failed to allocate irq host!\n");  		goto end; diff --git a/arch/powerpc/platforms/52xx/media5200.c b/arch/powerpc/platforms/52xx/media5200.c index 96f85e5e0cd..17d91b7da31 100644 --- a/arch/powerpc/platforms/52xx/media5200.c +++ b/arch/powerpc/platforms/52xx/media5200.c @@ -45,7 +45,7 @@ static struct of_device_id mpc5200_gpio_ids[] __initdata = {  struct media5200_irq {  	void __iomem *regs;  	spinlock_t lock; -	struct irq_host *irqhost; +	struct irq_domain *irqhost;  };  struct media5200_irq media5200_irq; @@ -112,7 +112,7 @@ void media5200_irq_cascade(unsigned int virq, struct irq_desc *desc)  	raw_spin_unlock(&desc->lock);  } -static int media5200_irq_map(struct irq_host *h, unsigned int virq, +static int media5200_irq_map(struct irq_domain *h, unsigned int virq,  			     irq_hw_number_t hw)  {  	pr_debug("%s: h=%p, virq=%i, hwirq=%i\n", __func__, h, virq, (int)hw); @@ -122,7 +122,7 @@ static int media5200_irq_map(struct irq_host *h, unsigned int virq,  	return 0;  } -static int media5200_irq_xlate(struct irq_host *h, struct device_node *ct, +static int media5200_irq_xlate(struct irq_domain *h, struct device_node *ct,  				 const u32 *intspec, unsigned int intsize,  				 irq_hw_number_t *out_hwirq,  				 unsigned int *out_flags) @@ -136,7 +136,7 @@ static int media5200_irq_xlate(struct irq_host *h, struct device_node *ct,  	return 0;  } -static struct irq_host_ops media5200_irq_ops = { +static const struct irq_domain_ops media5200_irq_ops = {  	.map = media5200_irq_map,  	.xlate = media5200_irq_xlate,  }; @@ -173,15 +173,12 @@ static void __init media5200_init_irq(void)  	spin_lock_init(&media5200_irq.lock); -	media5200_irq.irqhost = irq_alloc_host(fpga_np, IRQ_HOST_MAP_LINEAR, -					       MEDIA5200_NUM_IRQS, -					       &media5200_irq_ops, -1); +	media5200_irq.irqhost = irq_domain_add_linear(fpga_np, +			MEDIA5200_NUM_IRQS, &media5200_irq_ops, &media5200_irq);  	if (!media5200_irq.irqhost)  		goto out;  	pr_debug("%s: allocated irqhost\n", __func__); -	media5200_irq.irqhost->host_data = &media5200_irq; -  	irq_set_handler_data(cascade_virq, &media5200_irq);  	irq_set_chained_handler(cascade_virq, media5200_irq_cascade); diff --git a/arch/powerpc/platforms/52xx/mpc52xx_gpt.c b/arch/powerpc/platforms/52xx/mpc52xx_gpt.c index f94f06e5276..028470b9588 100644 --- a/arch/powerpc/platforms/52xx/mpc52xx_gpt.c +++ b/arch/powerpc/platforms/52xx/mpc52xx_gpt.c @@ -81,7 +81,7 @@ MODULE_LICENSE("GPL");   * @regs: virtual address of GPT registers   * @lock: spinlock to coordinate between different functions.   * @gc: gpio_chip instance structure; used when GPIO is enabled - * @irqhost: Pointer to irq_host instance; used when IRQ mode is supported + * @irqhost: Pointer to irq_domain instance; used when IRQ mode is supported   * @wdt_mode: only relevant for gpt0: bit 0 (MPC52xx_GPT_CAN_WDT) indicates   *   if the gpt may be used as wdt, bit 1 (MPC52xx_GPT_IS_WDT) indicates   *   if the timer is actively used as wdt which blocks gpt functions @@ -91,7 +91,7 @@ struct mpc52xx_gpt_priv {  	struct device *dev;  	struct mpc52xx_gpt __iomem *regs;  	spinlock_t lock; -	struct irq_host *irqhost; +	struct irq_domain *irqhost;  	u32 ipb_freq;  	u8 wdt_mode; @@ -204,7 +204,7 @@ void mpc52xx_gpt_irq_cascade(unsigned int virq, struct irq_desc *desc)  	}  } -static int mpc52xx_gpt_irq_map(struct irq_host *h, unsigned int virq, +static int mpc52xx_gpt_irq_map(struct irq_domain *h, unsigned int virq,  			       irq_hw_number_t hw)  {  	struct mpc52xx_gpt_priv *gpt = h->host_data; @@ -216,7 +216,7 @@ static int mpc52xx_gpt_irq_map(struct irq_host *h, unsigned int virq,  	return 0;  } -static int mpc52xx_gpt_irq_xlate(struct irq_host *h, struct device_node *ct, +static int mpc52xx_gpt_irq_xlate(struct irq_domain *h, struct device_node *ct,  				 const u32 *intspec, unsigned int intsize,  				 irq_hw_number_t *out_hwirq,  				 unsigned int *out_flags) @@ -236,7 +236,7 @@ static int mpc52xx_gpt_irq_xlate(struct irq_host *h, struct device_node *ct,  	return 0;  } -static struct irq_host_ops mpc52xx_gpt_irq_ops = { +static const struct irq_domain_ops mpc52xx_gpt_irq_ops = {  	.map = mpc52xx_gpt_irq_map,  	.xlate = mpc52xx_gpt_irq_xlate,  }; @@ -252,14 +252,12 @@ mpc52xx_gpt_irq_setup(struct mpc52xx_gpt_priv *gpt, struct device_node *node)  	if (!cascade_virq)  		return; -	gpt->irqhost = irq_alloc_host(node, IRQ_HOST_MAP_LINEAR, 1, -				      &mpc52xx_gpt_irq_ops, -1); +	gpt->irqhost = irq_domain_add_linear(node, 1, &mpc52xx_gpt_irq_ops, gpt);  	if (!gpt->irqhost) { -		dev_err(gpt->dev, "irq_alloc_host() failed\n"); +		dev_err(gpt->dev, "irq_domain_add_linear() failed\n");  		return;  	} -	gpt->irqhost->host_data = gpt;  	irq_set_handler_data(cascade_virq, gpt);  	irq_set_chained_handler(cascade_virq, mpc52xx_gpt_irq_cascade); diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pic.c b/arch/powerpc/platforms/52xx/mpc52xx_pic.c index 1a9a4957057..8520b58a5e9 100644 --- a/arch/powerpc/platforms/52xx/mpc52xx_pic.c +++ b/arch/powerpc/platforms/52xx/mpc52xx_pic.c @@ -132,7 +132,7 @@ static struct of_device_id mpc52xx_sdma_ids[] __initdata = {  static struct mpc52xx_intr __iomem *intr;  static struct mpc52xx_sdma __iomem *sdma; -static struct irq_host *mpc52xx_irqhost = NULL; +static struct irq_domain *mpc52xx_irqhost = NULL;  static unsigned char mpc52xx_map_senses[4] = {  	IRQ_TYPE_LEVEL_HIGH, @@ -301,7 +301,7 @@ static int mpc52xx_is_extirq(int l1, int l2)  /**   * mpc52xx_irqhost_xlate - translate virq# from device tree interrupts property   */ -static int mpc52xx_irqhost_xlate(struct irq_host *h, struct device_node *ct, +static int mpc52xx_irqhost_xlate(struct irq_domain *h, struct device_node *ct,  				 const u32 *intspec, unsigned int intsize,  				 irq_hw_number_t *out_hwirq,  				 unsigned int *out_flags) @@ -335,7 +335,7 @@ static int mpc52xx_irqhost_xlate(struct irq_host *h, struct device_node *ct,  /**   * mpc52xx_irqhost_map - Hook to map from virq to an irq_chip structure   */ -static int mpc52xx_irqhost_map(struct irq_host *h, unsigned int virq, +static int mpc52xx_irqhost_map(struct irq_domain *h, unsigned int virq,  			       irq_hw_number_t irq)  {  	int l1irq; @@ -384,7 +384,7 @@ static int mpc52xx_irqhost_map(struct irq_host *h, unsigned int virq,  	return 0;  } -static struct irq_host_ops mpc52xx_irqhost_ops = { +static const struct irq_domain_ops mpc52xx_irqhost_ops = {  	.xlate = mpc52xx_irqhost_xlate,  	.map = mpc52xx_irqhost_map,  }; @@ -444,9 +444,9 @@ void __init mpc52xx_init_irq(void)  	 * As last step, add an irq host to translate the real  	 * hw irq information provided by the ofw to linux virq  	 */ -	mpc52xx_irqhost = irq_alloc_host(picnode, IRQ_HOST_MAP_LINEAR, +	mpc52xx_irqhost = irq_domain_add_linear(picnode,  	                                 MPC52xx_IRQ_HIGHTESTHWIRQ, -	                                 &mpc52xx_irqhost_ops, -1); +	                                 &mpc52xx_irqhost_ops, NULL);  	if (!mpc52xx_irqhost)  		panic(__FILE__ ": Cannot allocate the IRQ host\n"); diff --git a/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c b/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c index 8ccf9ed62fe..328d221fd1c 100644 --- a/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c +++ b/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c @@ -29,7 +29,7 @@ static DEFINE_RAW_SPINLOCK(pci_pic_lock);  struct pq2ads_pci_pic {  	struct device_node *node; -	struct irq_host *host; +	struct irq_domain *host;  	struct {  		u32 stat; @@ -103,7 +103,7 @@ static void pq2ads_pci_irq_demux(unsigned int irq, struct irq_desc *desc)  	}  } -static int pci_pic_host_map(struct irq_host *h, unsigned int virq, +static int pci_pic_host_map(struct irq_domain *h, unsigned int virq,  			    irq_hw_number_t hw)  {  	irq_set_status_flags(virq, IRQ_LEVEL); @@ -112,14 +112,14 @@ static int pci_pic_host_map(struct irq_host *h, unsigned int virq,  	return 0;  } -static struct irq_host_ops pci_pic_host_ops = { +static const struct irq_domain_ops pci_pic_host_ops = {  	.map = pci_pic_host_map,  };  int __init pq2ads_pci_init_irq(void)  {  	struct pq2ads_pci_pic *priv; -	struct irq_host *host; +	struct irq_domain *host;  	struct device_node *np;  	int ret = -ENODEV;  	int irq; @@ -156,17 +156,13 @@ int __init pq2ads_pci_init_irq(void)  	out_be32(&priv->regs->mask, ~0);  	mb(); -	host = irq_alloc_host(np, IRQ_HOST_MAP_LINEAR, NUM_IRQS, -	                      &pci_pic_host_ops, NUM_IRQS); +	host = irq_domain_add_linear(np, NUM_IRQS, &pci_pic_host_ops, priv);  	if (!host) {  		ret = -ENOMEM;  		goto out_unmap_regs;  	} -	host->host_data = priv; -  	priv->host = host; -	host->host_data = priv;  	irq_set_handler_data(irq, priv);  	irq_set_chained_handler(irq, pq2ads_pci_irq_demux); diff --git a/arch/powerpc/platforms/85xx/socrates_fpga_pic.c b/arch/powerpc/platforms/85xx/socrates_fpga_pic.c index 12cb9bb2cc6..3bbbf748948 100644 --- a/arch/powerpc/platforms/85xx/socrates_fpga_pic.c +++ b/arch/powerpc/platforms/85xx/socrates_fpga_pic.c @@ -51,7 +51,7 @@ static struct socrates_fpga_irq_info fpga_irqs[SOCRATES_FPGA_NUM_IRQS] = {  static DEFINE_RAW_SPINLOCK(socrates_fpga_pic_lock);  static void __iomem *socrates_fpga_pic_iobase; -static struct irq_host *socrates_fpga_pic_irq_host; +static struct irq_domain *socrates_fpga_pic_irq_host;  static unsigned int socrates_fpga_irqs[3];  static inline uint32_t socrates_fpga_pic_read(int reg) @@ -227,7 +227,7 @@ static struct irq_chip socrates_fpga_pic_chip = {  	.irq_set_type	= socrates_fpga_pic_set_type,  }; -static int socrates_fpga_pic_host_map(struct irq_host *h, unsigned int virq, +static int socrates_fpga_pic_host_map(struct irq_domain *h, unsigned int virq,  		irq_hw_number_t hwirq)  {  	/* All interrupts are LEVEL sensitive */ @@ -238,7 +238,7 @@ static int socrates_fpga_pic_host_map(struct irq_host *h, unsigned int virq,  	return 0;  } -static int socrates_fpga_pic_host_xlate(struct irq_host *h, +static int socrates_fpga_pic_host_xlate(struct irq_domain *h,  		struct device_node *ct,	const u32 *intspec, unsigned int intsize,  		irq_hw_number_t *out_hwirq, unsigned int *out_flags)  { @@ -269,7 +269,7 @@ static int socrates_fpga_pic_host_xlate(struct irq_host *h,  	return 0;  } -static struct irq_host_ops socrates_fpga_pic_host_ops = { +static const struct irq_domain_ops socrates_fpga_pic_host_ops = {  	.map    = socrates_fpga_pic_host_map,  	.xlate  = socrates_fpga_pic_host_xlate,  }; @@ -279,10 +279,9 @@ void socrates_fpga_pic_init(struct device_node *pic)  	unsigned long flags;  	int i; -	/* Setup an irq_host structure */ -	socrates_fpga_pic_irq_host = irq_alloc_host(pic, IRQ_HOST_MAP_LINEAR, -			SOCRATES_FPGA_NUM_IRQS,	&socrates_fpga_pic_host_ops, -			SOCRATES_FPGA_NUM_IRQS); +	/* Setup an irq_domain structure */ +	socrates_fpga_pic_irq_host = irq_domain_add_linear(pic, +		    SOCRATES_FPGA_NUM_IRQS, &socrates_fpga_pic_host_ops, NULL);  	if (socrates_fpga_pic_irq_host == NULL) {  		pr_err("FPGA PIC: Unable to allocate host\n");  		return; diff --git a/arch/powerpc/platforms/86xx/gef_pic.c b/arch/powerpc/platforms/86xx/gef_pic.c index 94594e58594..af3fd697de8 100644 --- a/arch/powerpc/platforms/86xx/gef_pic.c +++ b/arch/powerpc/platforms/86xx/gef_pic.c @@ -50,7 +50,7 @@  static DEFINE_RAW_SPINLOCK(gef_pic_lock);  static void __iomem *gef_pic_irq_reg_base; -static struct irq_host *gef_pic_irq_host; +static struct irq_domain *gef_pic_irq_host;  static int gef_pic_cascade_irq;  /* @@ -153,7 +153,7 @@ static struct irq_chip gef_pic_chip = {  /* When an interrupt is being configured, this call allows some flexibilty   * in deciding which irq_chip structure is used   */ -static int gef_pic_host_map(struct irq_host *h, unsigned int virq, +static int gef_pic_host_map(struct irq_domain *h, unsigned int virq,  			  irq_hw_number_t hwirq)  {  	/* All interrupts are LEVEL sensitive */ @@ -163,7 +163,7 @@ static int gef_pic_host_map(struct irq_host *h, unsigned int virq,  	return 0;  } -static int gef_pic_host_xlate(struct irq_host *h, struct device_node *ct, +static int gef_pic_host_xlate(struct irq_domain *h, struct device_node *ct,  			    const u32 *intspec, unsigned int intsize,  			    irq_hw_number_t *out_hwirq, unsigned int *out_flags)  { @@ -177,7 +177,7 @@ static int gef_pic_host_xlate(struct irq_host *h, struct device_node *ct,  	return 0;  } -static struct irq_host_ops gef_pic_host_ops = { +static const struct irq_domain_ops gef_pic_host_ops = {  	.map	= gef_pic_host_map,  	.xlate	= gef_pic_host_xlate,  }; @@ -211,10 +211,9 @@ void __init gef_pic_init(struct device_node *np)  		return;  	} -	/* Setup an irq_host structure */ -	gef_pic_irq_host = irq_alloc_host(np, IRQ_HOST_MAP_LINEAR, -					  GEF_PIC_NUM_IRQS, -					  &gef_pic_host_ops, NO_IRQ); +	/* Setup an irq_domain structure */ +	gef_pic_irq_host = irq_domain_add_linear(np, GEF_PIC_NUM_IRQS, +					  &gef_pic_host_ops, NULL);  	if (gef_pic_irq_host == NULL)  		return; diff --git a/arch/powerpc/platforms/cell/axon_msi.c b/arch/powerpc/platforms/cell/axon_msi.c index 40a6e34793b..db360fc4cf0 100644 --- a/arch/powerpc/platforms/cell/axon_msi.c +++ b/arch/powerpc/platforms/cell/axon_msi.c @@ -67,7 +67,7 @@  struct axon_msic { -	struct irq_host *irq_host; +	struct irq_domain *irq_domain;  	__le32 *fifo_virt;  	dma_addr_t fifo_phys;  	dcr_host_t dcr_host; @@ -152,7 +152,7 @@ static void axon_msi_cascade(unsigned int irq, struct irq_desc *desc)  static struct axon_msic *find_msi_translator(struct pci_dev *dev)  { -	struct irq_host *irq_host; +	struct irq_domain *irq_domain;  	struct device_node *dn, *tmp;  	const phandle *ph;  	struct axon_msic *msic = NULL; @@ -184,14 +184,14 @@ static struct axon_msic *find_msi_translator(struct pci_dev *dev)  		goto out_error;  	} -	irq_host = irq_find_host(dn); -	if (!irq_host) { -		dev_dbg(&dev->dev, "axon_msi: no irq_host found for node %s\n", +	irq_domain = irq_find_host(dn); +	if (!irq_domain) { +		dev_dbg(&dev->dev, "axon_msi: no irq_domain found for node %s\n",  			dn->full_name);  		goto out_error;  	} -	msic = irq_host->host_data; +	msic = irq_domain->host_data;  out_error:  	of_node_put(dn); @@ -280,7 +280,7 @@ static int axon_msi_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)  	BUILD_BUG_ON(NR_IRQS > 65536);  	list_for_each_entry(entry, &dev->msi_list, list) { -		virq = irq_create_direct_mapping(msic->irq_host); +		virq = irq_create_direct_mapping(msic->irq_domain);  		if (virq == NO_IRQ) {  			dev_warn(&dev->dev,  				 "axon_msi: virq allocation failed!\n"); @@ -318,7 +318,7 @@ static struct irq_chip msic_irq_chip = {  	.name		= "AXON-MSI",  }; -static int msic_host_map(struct irq_host *h, unsigned int virq, +static int msic_host_map(struct irq_domain *h, unsigned int virq,  			 irq_hw_number_t hw)  {  	irq_set_chip_data(virq, h->host_data); @@ -327,7 +327,7 @@ static int msic_host_map(struct irq_host *h, unsigned int virq,  	return 0;  } -static struct irq_host_ops msic_host_ops = { +static const struct irq_domain_ops msic_host_ops = {  	.map	= msic_host_map,  }; @@ -337,7 +337,7 @@ static void axon_msi_shutdown(struct platform_device *device)  	u32 tmp;  	pr_devel("axon_msi: disabling %s\n", -		  msic->irq_host->of_node->full_name); +		  msic->irq_domain->of_node->full_name);  	tmp  = dcr_read(msic->dcr_host, MSIC_CTRL_REG);  	tmp &= ~MSIC_CTRL_ENABLE & ~MSIC_CTRL_IRQ_ENABLE;  	msic_dcr_write(msic, MSIC_CTRL_REG, tmp); @@ -392,16 +392,13 @@ static int axon_msi_probe(struct platform_device *device)  	}  	memset(msic->fifo_virt, 0xff, MSIC_FIFO_SIZE_BYTES); -	msic->irq_host = irq_alloc_host(dn, IRQ_HOST_MAP_NOMAP, -					NR_IRQS, &msic_host_ops, 0); -	if (!msic->irq_host) { -		printk(KERN_ERR "axon_msi: couldn't allocate irq_host for %s\n", +	msic->irq_domain = irq_domain_add_nomap(dn, &msic_host_ops, msic); +	if (!msic->irq_domain) { +		printk(KERN_ERR "axon_msi: couldn't allocate irq_domain for %s\n",  		       dn->full_name);  		goto out_free_fifo;  	} -	msic->irq_host->host_data = msic; -  	irq_set_handler_data(virq, msic);  	irq_set_chained_handler(virq, axon_msi_cascade);  	pr_devel("axon_msi: irq 0x%x setup for axon_msi\n", virq); diff --git a/arch/powerpc/platforms/cell/beat_interrupt.c b/arch/powerpc/platforms/cell/beat_interrupt.c index 55015e1f693..e5c3a2c6090 100644 --- a/arch/powerpc/platforms/cell/beat_interrupt.c +++ b/arch/powerpc/platforms/cell/beat_interrupt.c @@ -34,7 +34,7 @@ static DEFINE_RAW_SPINLOCK(beatic_irq_mask_lock);  static uint64_t	beatic_irq_mask_enable[(MAX_IRQS+255)/64];  static uint64_t	beatic_irq_mask_ack[(MAX_IRQS+255)/64]; -static struct irq_host *beatic_host; +static struct irq_domain *beatic_host;  /*   * In this implementation, "virq" == "IRQ plug number", @@ -122,7 +122,7 @@ static struct irq_chip beatic_pic = {   *   * Note that the number (virq) is already assigned at upper layer.   */ -static void beatic_pic_host_unmap(struct irq_host *h, unsigned int virq) +static void beatic_pic_host_unmap(struct irq_domain *h, unsigned int virq)  {  	beat_destruct_irq_plug(virq);  } @@ -133,7 +133,7 @@ static void beatic_pic_host_unmap(struct irq_host *h, unsigned int virq)   *   * Note that the number (virq) is already assigned at upper layer.   */ -static int beatic_pic_host_map(struct irq_host *h, unsigned int virq, +static int beatic_pic_host_map(struct irq_domain *h, unsigned int virq,  			       irq_hw_number_t hw)  {  	int64_t	err; @@ -154,7 +154,7 @@ static int beatic_pic_host_map(struct irq_host *h, unsigned int virq,   * Called from irq_create_of_mapping() only.   * Note: We have only 1 entry to translate.   */ -static int beatic_pic_host_xlate(struct irq_host *h, struct device_node *ct, +static int beatic_pic_host_xlate(struct irq_domain *h, struct device_node *ct,  				 const u32 *intspec, unsigned int intsize,  				 irq_hw_number_t *out_hwirq,  				 unsigned int *out_flags) @@ -166,13 +166,13 @@ static int beatic_pic_host_xlate(struct irq_host *h, struct device_node *ct,  	return 0;  } -static int beatic_pic_host_match(struct irq_host *h, struct device_node *np) +static int beatic_pic_host_match(struct irq_domain *h, struct device_node *np)  {  	/* Match all */  	return 1;  } -static struct irq_host_ops beatic_pic_host_ops = { +static const struct irq_domain_ops beatic_pic_host_ops = {  	.map = beatic_pic_host_map,  	.unmap = beatic_pic_host_unmap,  	.xlate = beatic_pic_host_xlate, @@ -239,9 +239,7 @@ void __init beatic_init_IRQ(void)  	ppc_md.get_irq = beatic_get_irq;  	/* Allocate an irq host */ -	beatic_host = irq_alloc_host(NULL, IRQ_HOST_MAP_NOMAP, 0, -				     &beatic_pic_host_ops, -					 0); +	beatic_host = irq_domain_add_nomap(NULL, &beatic_pic_host_ops, NULL);  	BUG_ON(beatic_host == NULL);  	irq_set_default_host(beatic_host);  } diff --git a/arch/powerpc/platforms/cell/interrupt.c b/arch/powerpc/platforms/cell/interrupt.c index 96a433dd2d6..2d42f3bb66d 100644 --- a/arch/powerpc/platforms/cell/interrupt.c +++ b/arch/powerpc/platforms/cell/interrupt.c @@ -56,7 +56,7 @@ struct iic {  static DEFINE_PER_CPU(struct iic, cpu_iic);  #define IIC_NODE_COUNT	2 -static struct irq_host *iic_host; +static struct irq_domain *iic_host;  /* Convert between "pending" bits and hw irq number */  static irq_hw_number_t iic_pending_to_hwnum(struct cbe_iic_pending_bits bits) @@ -186,7 +186,7 @@ void iic_message_pass(int cpu, int msg)  	out_be64(&per_cpu(cpu_iic, cpu).regs->generate, (0xf - msg) << 4);  } -struct irq_host *iic_get_irq_host(int node) +struct irq_domain *iic_get_irq_host(int node)  {  	return iic_host;  } @@ -222,13 +222,13 @@ void iic_request_IPIs(void)  #endif /* CONFIG_SMP */ -static int iic_host_match(struct irq_host *h, struct device_node *node) +static int iic_host_match(struct irq_domain *h, struct device_node *node)  {  	return of_device_is_compatible(node,  				    "IBM,CBEA-Internal-Interrupt-Controller");  } -static int iic_host_map(struct irq_host *h, unsigned int virq, +static int iic_host_map(struct irq_domain *h, unsigned int virq,  			irq_hw_number_t hw)  {  	switch (hw & IIC_IRQ_TYPE_MASK) { @@ -245,7 +245,7 @@ static int iic_host_map(struct irq_host *h, unsigned int virq,  	return 0;  } -static int iic_host_xlate(struct irq_host *h, struct device_node *ct, +static int iic_host_xlate(struct irq_domain *h, struct device_node *ct,  			   const u32 *intspec, unsigned int intsize,  			   irq_hw_number_t *out_hwirq, unsigned int *out_flags) @@ -285,7 +285,7 @@ static int iic_host_xlate(struct irq_host *h, struct device_node *ct,  	return 0;  } -static struct irq_host_ops iic_host_ops = { +static const struct irq_domain_ops iic_host_ops = {  	.match = iic_host_match,  	.map = iic_host_map,  	.xlate = iic_host_xlate, @@ -378,8 +378,8 @@ static int __init setup_iic(void)  void __init iic_init_IRQ(void)  {  	/* Setup an irq host data structure */ -	iic_host = irq_alloc_host(NULL, IRQ_HOST_MAP_LINEAR, IIC_SOURCE_COUNT, -				  &iic_host_ops, IIC_IRQ_INVALID); +	iic_host = irq_domain_add_linear(NULL, IIC_SOURCE_COUNT, &iic_host_ops, +					 NULL);  	BUG_ON(iic_host == NULL);  	irq_set_default_host(iic_host); diff --git a/arch/powerpc/platforms/cell/spider-pic.c b/arch/powerpc/platforms/cell/spider-pic.c index 442c28c00f8..d8b7cc8a66c 100644 --- a/arch/powerpc/platforms/cell/spider-pic.c +++ b/arch/powerpc/platforms/cell/spider-pic.c @@ -62,7 +62,7 @@ enum {  #define SPIDER_IRQ_INVALID	63  struct spider_pic { -	struct irq_host		*host; +	struct irq_domain		*host;  	void __iomem		*regs;  	unsigned int		node_id;  }; @@ -168,7 +168,7 @@ static struct irq_chip spider_pic = {  	.irq_set_type = spider_set_irq_type,  }; -static int spider_host_map(struct irq_host *h, unsigned int virq, +static int spider_host_map(struct irq_domain *h, unsigned int virq,  			irq_hw_number_t hw)  {  	irq_set_chip_data(virq, h->host_data); @@ -180,7 +180,7 @@ static int spider_host_map(struct irq_host *h, unsigned int virq,  	return 0;  } -static int spider_host_xlate(struct irq_host *h, struct device_node *ct, +static int spider_host_xlate(struct irq_domain *h, struct device_node *ct,  			   const u32 *intspec, unsigned int intsize,  			   irq_hw_number_t *out_hwirq, unsigned int *out_flags) @@ -194,7 +194,7 @@ static int spider_host_xlate(struct irq_host *h, struct device_node *ct,  	return 0;  } -static struct irq_host_ops spider_host_ops = { +static const struct irq_domain_ops spider_host_ops = {  	.map = spider_host_map,  	.xlate = spider_host_xlate,  }; @@ -299,12 +299,10 @@ static void __init spider_init_one(struct device_node *of_node, int chip,  		panic("spider_pic: can't map registers !");  	/* Allocate a host */ -	pic->host = irq_alloc_host(of_node, IRQ_HOST_MAP_LINEAR, -				   SPIDER_SRC_COUNT, &spider_host_ops, -				   SPIDER_IRQ_INVALID); +	pic->host = irq_domain_add_linear(of_node, SPIDER_SRC_COUNT, +					  &spider_host_ops, pic);  	if (pic->host == NULL)  		panic("spider_pic: can't allocate irq host !"); -	pic->host->host_data = pic;  	/* Go through all sources and disable them */  	for (i = 0; i < SPIDER_SRC_COUNT; i++) { diff --git a/arch/powerpc/platforms/embedded6xx/flipper-pic.c b/arch/powerpc/platforms/embedded6xx/flipper-pic.c index f61a2dd96b9..53d6eee0196 100644 --- a/arch/powerpc/platforms/embedded6xx/flipper-pic.c +++ b/arch/powerpc/platforms/embedded6xx/flipper-pic.c @@ -96,9 +96,9 @@ static struct irq_chip flipper_pic = {   *   */ -static struct irq_host *flipper_irq_host; +static struct irq_domain *flipper_irq_host; -static int flipper_pic_map(struct irq_host *h, unsigned int virq, +static int flipper_pic_map(struct irq_domain *h, unsigned int virq,  			   irq_hw_number_t hwirq)  {  	irq_set_chip_data(virq, h->host_data); @@ -107,13 +107,13 @@ static int flipper_pic_map(struct irq_host *h, unsigned int virq,  	return 0;  } -static int flipper_pic_match(struct irq_host *h, struct device_node *np) +static int flipper_pic_match(struct irq_domain *h, struct device_node *np)  {  	return 1;  } -static struct irq_host_ops flipper_irq_host_ops = { +static const struct irq_domain_ops flipper_irq_domain_ops = {  	.map = flipper_pic_map,  	.match = flipper_pic_match,  }; @@ -130,10 +130,10 @@ static void __flipper_quiesce(void __iomem *io_base)  	out_be32(io_base + FLIPPER_ICR, 0xffffffff);  } -struct irq_host * __init flipper_pic_init(struct device_node *np) +struct irq_domain * __init flipper_pic_init(struct device_node *np)  {  	struct device_node *pi; -	struct irq_host *irq_host = NULL; +	struct irq_domain *irq_domain = NULL;  	struct resource res;  	void __iomem *io_base;  	int retval; @@ -159,17 +159,15 @@ struct irq_host * __init flipper_pic_init(struct device_node *np)  	__flipper_quiesce(io_base); -	irq_host = irq_alloc_host(np, IRQ_HOST_MAP_LINEAR, FLIPPER_NR_IRQS, -				  &flipper_irq_host_ops, -1); -	if (!irq_host) { -		pr_err("failed to allocate irq_host\n"); +	irq_domain = irq_domain_add_linear(np, FLIPPER_NR_IRQS, +				  &flipper_irq_domain_ops, io_base); +	if (!irq_domain) { +		pr_err("failed to allocate irq_domain\n");  		return NULL;  	} -	irq_host->host_data = io_base; -  out: -	return irq_host; +	return irq_domain;  }  unsigned int flipper_pic_get_irq(void) diff --git a/arch/powerpc/platforms/embedded6xx/hlwd-pic.c b/arch/powerpc/platforms/embedded6xx/hlwd-pic.c index e4919170c6b..3006b5117ec 100644 --- a/arch/powerpc/platforms/embedded6xx/hlwd-pic.c +++ b/arch/powerpc/platforms/embedded6xx/hlwd-pic.c @@ -89,9 +89,9 @@ static struct irq_chip hlwd_pic = {   *   */ -static struct irq_host *hlwd_irq_host; +static struct irq_domain *hlwd_irq_host; -static int hlwd_pic_map(struct irq_host *h, unsigned int virq, +static int hlwd_pic_map(struct irq_domain *h, unsigned int virq,  			   irq_hw_number_t hwirq)  {  	irq_set_chip_data(virq, h->host_data); @@ -100,11 +100,11 @@ static int hlwd_pic_map(struct irq_host *h, unsigned int virq,  	return 0;  } -static struct irq_host_ops hlwd_irq_host_ops = { +static const struct irq_domain_ops hlwd_irq_domain_ops = {  	.map = hlwd_pic_map,  }; -static unsigned int __hlwd_pic_get_irq(struct irq_host *h) +static unsigned int __hlwd_pic_get_irq(struct irq_domain *h)  {  	void __iomem *io_base = h->host_data;  	int irq; @@ -123,14 +123,14 @@ static void hlwd_pic_irq_cascade(unsigned int cascade_virq,  				      struct irq_desc *desc)  {  	struct irq_chip *chip = irq_desc_get_chip(desc); -	struct irq_host *irq_host = irq_get_handler_data(cascade_virq); +	struct irq_domain *irq_domain = irq_get_handler_data(cascade_virq);  	unsigned int virq;  	raw_spin_lock(&desc->lock);  	chip->irq_mask(&desc->irq_data); /* IRQ_LEVEL */  	raw_spin_unlock(&desc->lock); -	virq = __hlwd_pic_get_irq(irq_host); +	virq = __hlwd_pic_get_irq(irq_domain);  	if (virq != NO_IRQ)  		generic_handle_irq(virq);  	else @@ -155,9 +155,9 @@ static void __hlwd_quiesce(void __iomem *io_base)  	out_be32(io_base + HW_BROADWAY_ICR, 0xffffffff);  } -struct irq_host *hlwd_pic_init(struct device_node *np) +struct irq_domain *hlwd_pic_init(struct device_node *np)  { -	struct irq_host *irq_host; +	struct irq_domain *irq_domain;  	struct resource res;  	void __iomem *io_base;  	int retval; @@ -177,15 +177,14 @@ struct irq_host *hlwd_pic_init(struct device_node *np)  	__hlwd_quiesce(io_base); -	irq_host = irq_alloc_host(np, IRQ_HOST_MAP_LINEAR, HLWD_NR_IRQS, -				  &hlwd_irq_host_ops, -1); -	if (!irq_host) { -		pr_err("failed to allocate irq_host\n"); +	irq_domain = irq_domain_add_linear(np, HLWD_NR_IRQS, +					   &hlwd_irq_domain_ops, io_base); +	if (!irq_domain) { +		pr_err("failed to allocate irq_domain\n");  		return NULL;  	} -	irq_host->host_data = io_base; -	return irq_host; +	return irq_domain;  }  unsigned int hlwd_pic_get_irq(void) @@ -200,7 +199,7 @@ unsigned int hlwd_pic_get_irq(void)  void hlwd_pic_probe(void)  { -	struct irq_host *host; +	struct irq_domain *host;  	struct device_node *np;  	const u32 *interrupts;  	int cascade_virq; diff --git a/arch/powerpc/platforms/iseries/irq.c b/arch/powerpc/platforms/iseries/irq.c index b2103453eb0..05ce5164caf 100644 --- a/arch/powerpc/platforms/iseries/irq.c +++ b/arch/powerpc/platforms/iseries/irq.c @@ -342,7 +342,7 @@ unsigned int iSeries_get_irq(void)  #ifdef CONFIG_PCI -static int iseries_irq_host_map(struct irq_host *h, unsigned int virq, +static int iseries_irq_host_map(struct irq_domain *h, unsigned int virq,  				irq_hw_number_t hw)  {  	irq_set_chip_and_handler(virq, &iseries_pic, handle_fasteoi_irq); @@ -350,13 +350,13 @@ static int iseries_irq_host_map(struct irq_host *h, unsigned int virq,  	return 0;  } -static int iseries_irq_host_match(struct irq_host *h, struct device_node *np) +static int iseries_irq_host_match(struct irq_domain *h, struct device_node *np)  {  	/* Match all */  	return 1;  } -static struct irq_host_ops iseries_irq_host_ops = { +static const struct irq_domain_ops iseries_irq_domain_ops = {  	.map = iseries_irq_host_map,  	.match = iseries_irq_host_match,  }; @@ -368,7 +368,7 @@ static struct irq_host_ops iseries_irq_host_ops = {  void __init iSeries_init_IRQ(void)  {  	/* Register PCI event handler and open an event path */ -	struct irq_host *host; +	struct irq_domain *host;  	int ret;  	/* @@ -380,8 +380,7 @@ void __init iSeries_init_IRQ(void)  	/* Create irq host. No need for a revmap since HV will give us  	 * back our virtual irq number  	 */ -	host = irq_alloc_host(NULL, IRQ_HOST_MAP_NOMAP, 0, -			      &iseries_irq_host_ops, 0); +	host = irq_domain_add_nomap(NULL, &iseries_irq_domain_ops, NULL);  	BUG_ON(host == NULL);  	irq_set_default_host(host); diff --git a/arch/powerpc/platforms/powermac/pic.c b/arch/powerpc/platforms/powermac/pic.c index 7761aabfc29..92afc382a49 100644 --- a/arch/powerpc/platforms/powermac/pic.c +++ b/arch/powerpc/platforms/powermac/pic.c @@ -61,7 +61,7 @@ static DEFINE_RAW_SPINLOCK(pmac_pic_lock);  static unsigned long ppc_lost_interrupts[NR_MASK_WORDS];  static unsigned long ppc_cached_irq_mask[NR_MASK_WORDS];  static int pmac_irq_cascade = -1; -static struct irq_host *pmac_pic_host; +static struct irq_domain *pmac_pic_host;  static void __pmac_retrigger(unsigned int irq_nr)  { @@ -268,13 +268,13 @@ static struct irqaction gatwick_cascade_action = {  	.name		= "cascade",  }; -static int pmac_pic_host_match(struct irq_host *h, struct device_node *node) +static int pmac_pic_host_match(struct irq_domain *h, struct device_node *node)  {  	/* We match all, we don't always have a node anyway */  	return 1;  } -static int pmac_pic_host_map(struct irq_host *h, unsigned int virq, +static int pmac_pic_host_map(struct irq_domain *h, unsigned int virq,  			     irq_hw_number_t hw)  {  	if (hw >= max_irqs) @@ -288,21 +288,10 @@ static int pmac_pic_host_map(struct irq_host *h, unsigned int virq,  	return 0;  } -static int pmac_pic_host_xlate(struct irq_host *h, struct device_node *ct, -			       const u32 *intspec, unsigned int intsize, -			       irq_hw_number_t *out_hwirq, -			       unsigned int *out_flags) - -{ -	*out_flags = IRQ_TYPE_NONE; -	*out_hwirq = *intspec; -	return 0; -} - -static struct irq_host_ops pmac_pic_host_ops = { +static const struct irq_domain_ops pmac_pic_host_ops = {  	.match = pmac_pic_host_match,  	.map = pmac_pic_host_map, -	.xlate = pmac_pic_host_xlate, +	.xlate = irq_domain_xlate_onecell,  };  static void __init pmac_pic_probe_oldstyle(void) @@ -352,9 +341,8 @@ static void __init pmac_pic_probe_oldstyle(void)  	/*  	 * Allocate an irq host  	 */ -	pmac_pic_host = irq_alloc_host(master, IRQ_HOST_MAP_LINEAR, max_irqs, -				       &pmac_pic_host_ops, -				       max_irqs); +	pmac_pic_host = irq_domain_add_linear(master, max_irqs, +					      &pmac_pic_host_ops, NULL);  	BUG_ON(pmac_pic_host == NULL);  	irq_set_default_host(pmac_pic_host); diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c index 44d769258eb..a81e5a88fbd 100644 --- a/arch/powerpc/platforms/powermac/smp.c +++ b/arch/powerpc/platforms/powermac/smp.c @@ -125,7 +125,7 @@ static volatile u32 __iomem *psurge_start;  static int psurge_type = PSURGE_NONE;  /* irq for secondary cpus to report */ -static struct irq_host *psurge_host; +static struct irq_domain *psurge_host;  int psurge_secondary_virq;  /* @@ -176,7 +176,7 @@ static void smp_psurge_cause_ipi(int cpu, unsigned long data)  	psurge_set_ipi(cpu);  } -static int psurge_host_map(struct irq_host *h, unsigned int virq, +static int psurge_host_map(struct irq_domain *h, unsigned int virq,  			 irq_hw_number_t hw)  {  	irq_set_chip_and_handler(virq, &dummy_irq_chip, handle_percpu_irq); @@ -184,7 +184,7 @@ static int psurge_host_map(struct irq_host *h, unsigned int virq,  	return 0;  } -struct irq_host_ops psurge_host_ops = { +static const struct irq_domain_ops psurge_host_ops = {  	.map	= psurge_host_map,  }; @@ -192,8 +192,7 @@ static int psurge_secondary_ipi_init(void)  {  	int rc = -ENOMEM; -	psurge_host = irq_alloc_host(NULL, IRQ_HOST_MAP_NOMAP, 0, -		&psurge_host_ops, 0); +	psurge_host = irq_domain_add_nomap(NULL, &psurge_host_ops, NULL);  	if (psurge_host)  		psurge_secondary_virq = irq_create_direct_mapping(psurge_host); diff --git a/arch/powerpc/platforms/ps3/interrupt.c b/arch/powerpc/platforms/ps3/interrupt.c index 617efa12a3a..2a4ff86cc21 100644 --- a/arch/powerpc/platforms/ps3/interrupt.c +++ b/arch/powerpc/platforms/ps3/interrupt.c @@ -667,7 +667,7 @@ static void __maybe_unused _dump_mask(struct ps3_private *pd,  static void dump_bmp(struct ps3_private* pd) {};  #endif /* defined(DEBUG) */ -static int ps3_host_map(struct irq_host *h, unsigned int virq, +static int ps3_host_map(struct irq_domain *h, unsigned int virq,  	irq_hw_number_t hwirq)  {  	DBG("%s:%d: hwirq %lu, virq %u\n", __func__, __LINE__, hwirq, @@ -678,13 +678,13 @@ static int ps3_host_map(struct irq_host *h, unsigned int virq,  	return 0;  } -static int ps3_host_match(struct irq_host *h, struct device_node *np) +static int ps3_host_match(struct irq_domain *h, struct device_node *np)  {  	/* Match all */  	return 1;  } -static struct irq_host_ops ps3_host_ops = { +static const struct irq_domain_ops ps3_host_ops = {  	.map = ps3_host_map,  	.match = ps3_host_match,  }; @@ -751,10 +751,9 @@ void __init ps3_init_IRQ(void)  {  	int result;  	unsigned cpu; -	struct irq_host *host; +	struct irq_domain *host; -	host = irq_alloc_host(NULL, IRQ_HOST_MAP_NOMAP, 0, &ps3_host_ops, -		PS3_INVALID_OUTLET); +	host = irq_domain_add_nomap(NULL, &ps3_host_ops, NULL);  	irq_set_default_host(host);  	irq_set_virq_count(PS3_PLUG_MAX + 1); diff --git a/arch/powerpc/platforms/wsp/opb_pic.c b/arch/powerpc/platforms/wsp/opb_pic.c index 19f353dfcd0..cb565bf9365 100644 --- a/arch/powerpc/platforms/wsp/opb_pic.c +++ b/arch/powerpc/platforms/wsp/opb_pic.c @@ -30,7 +30,7 @@  static int opb_index = 0;  struct opb_pic { -	struct irq_host *host; +	struct irq_domain *host;  	void *regs;  	int index;  	spinlock_t lock; @@ -179,7 +179,7 @@ static struct irq_chip opb_irq_chip = {  	.irq_set_type	= opb_set_irq_type  }; -static int opb_host_map(struct irq_host *host, unsigned int virq, +static int opb_host_map(struct irq_domain *host, unsigned int virq,  		irq_hw_number_t hwirq)  {  	struct opb_pic *opb; @@ -196,20 +196,9 @@ static int opb_host_map(struct irq_host *host, unsigned int virq,  	return 0;  } -static int opb_host_xlate(struct irq_host *host, struct device_node *dn, -		const u32 *intspec, unsigned int intsize, -		irq_hw_number_t *out_hwirq, unsigned int *out_type) -{ -	/* Interrupt size must == 2 */ -	BUG_ON(intsize != 2); -	*out_hwirq = intspec[0]; -	*out_type = intspec[1]; -	return 0; -} - -static struct irq_host_ops opb_host_ops = { +static const struct irq_domain_ops opb_host_ops = {  	.map = opb_host_map, -	.xlate = opb_host_xlate, +	.xlate = irq_domain_xlate_twocell,  };  irqreturn_t opb_irq_handler(int irq, void *private) @@ -263,13 +252,11 @@ struct opb_pic *opb_pic_init_one(struct device_node *dn)  		goto free_opb;  	} -	/* Allocate an irq host so that Linux knows that despite only +	/* Allocate an irq domain so that Linux knows that despite only  	 * having one interrupt to issue, we're the controller for multiple  	 * hardware IRQs, so later we can lookup their virtual IRQs. */ -	opb->host = irq_alloc_host(dn, IRQ_HOST_MAP_LINEAR, -			OPB_NR_IRQS, &opb_host_ops, -1); - +	opb->host = irq_domain_add_linear(dn, OPB_NR_IRQS, &opb_host_ops, opb);  	if (!opb->host) {  		printk(KERN_ERR "opb: Failed to allocate IRQ host!\n");  		goto free_regs; @@ -277,7 +264,6 @@ struct opb_pic *opb_pic_init_one(struct device_node *dn)  	opb->index = opb_index++;  	spin_lock_init(&opb->lock); -	opb->host->host_data = opb;  	/* Disable all interrupts by default */  	opb_out(opb, OPB_MLSASIER, 0); diff --git a/arch/powerpc/sysdev/cpm1.c b/arch/powerpc/sysdev/cpm1.c index 5d7d59a43c4..d4fa03f2b6a 100644 --- a/arch/powerpc/sysdev/cpm1.c +++ b/arch/powerpc/sysdev/cpm1.c @@ -54,7 +54,7 @@ cpm8xx_t __iomem *cpmp;  /* Pointer to comm processor space */  immap_t __iomem *mpc8xx_immr;  static cpic8xx_t __iomem *cpic_reg; -static struct irq_host *cpm_pic_host; +static struct irq_domain *cpm_pic_host;  static void cpm_mask_irq(struct irq_data *d)  { @@ -98,7 +98,7 @@ int cpm_get_irq(void)  	return irq_linear_revmap(cpm_pic_host, cpm_vec);  } -static int cpm_pic_host_map(struct irq_host *h, unsigned int virq, +static int cpm_pic_host_map(struct irq_domain *h, unsigned int virq,  			  irq_hw_number_t hw)  {  	pr_debug("cpm_pic_host_map(%d, 0x%lx)\n", virq, hw); @@ -123,7 +123,7 @@ static struct irqaction cpm_error_irqaction = {  	.name = "error",  }; -static struct irq_host_ops cpm_pic_host_ops = { +static const struct irq_domain_ops cpm_pic_host_ops = {  	.map = cpm_pic_host_map,  }; @@ -164,8 +164,7 @@ unsigned int cpm_pic_init(void)  	out_be32(&cpic_reg->cpic_cimr, 0); -	cpm_pic_host = irq_alloc_host(np, IRQ_HOST_MAP_LINEAR, -				      64, &cpm_pic_host_ops, 64); +	cpm_pic_host = irq_domain_add_linear(np, 64, &cpm_pic_host_ops, NULL);  	if (cpm_pic_host == NULL) {  		printk(KERN_ERR "CPM2 PIC: failed to allocate irq host!\n");  		sirq = NO_IRQ; diff --git a/arch/powerpc/sysdev/cpm2_pic.c b/arch/powerpc/sysdev/cpm2_pic.c index bcab50e2a9e..d3be961e2ae 100644 --- a/arch/powerpc/sysdev/cpm2_pic.c +++ b/arch/powerpc/sysdev/cpm2_pic.c @@ -50,7 +50,7 @@  static intctl_cpm2_t __iomem *cpm2_intctl; -static struct irq_host *cpm2_pic_host; +static struct irq_domain *cpm2_pic_host;  #define NR_MASK_WORDS   ((NR_IRQS + 31) / 32)  static unsigned long ppc_cached_irq_mask[NR_MASK_WORDS]; @@ -214,7 +214,7 @@ unsigned int cpm2_get_irq(void)  	return irq_linear_revmap(cpm2_pic_host, irq);  } -static int cpm2_pic_host_map(struct irq_host *h, unsigned int virq, +static int cpm2_pic_host_map(struct irq_domain *h, unsigned int virq,  			  irq_hw_number_t hw)  {  	pr_debug("cpm2_pic_host_map(%d, 0x%lx)\n", virq, hw); @@ -224,21 +224,9 @@ static int cpm2_pic_host_map(struct irq_host *h, unsigned int virq,  	return 0;  } -static int cpm2_pic_host_xlate(struct irq_host *h, struct device_node *ct, -			    const u32 *intspec, unsigned int intsize, -			    irq_hw_number_t *out_hwirq, unsigned int *out_flags) -{ -	*out_hwirq = intspec[0]; -	if (intsize > 1) -		*out_flags = intspec[1]; -	else -		*out_flags = IRQ_TYPE_NONE; -	return 0; -} - -static struct irq_host_ops cpm2_pic_host_ops = { +static const struct irq_domain_ops cpm2_pic_host_ops = {  	.map = cpm2_pic_host_map, -	.xlate = cpm2_pic_host_xlate, +	.xlate = irq_domain_xlate_onetwocell,  };  void cpm2_pic_init(struct device_node *node) @@ -275,8 +263,7 @@ void cpm2_pic_init(struct device_node *node)  	out_be32(&cpm2_intctl->ic_scprrl, 0x05309770);  	/* create a legacy host */ -	cpm2_pic_host = irq_alloc_host(node, IRQ_HOST_MAP_LINEAR, -				       64, &cpm2_pic_host_ops, 64); +	cpm2_pic_host = irq_domain_add_linear(node, 64, &cpm2_pic_host_ops, NULL);  	if (cpm2_pic_host == NULL) {  		printk(KERN_ERR "CPM2 PIC: failed to allocate irq host!\n");  		return; diff --git a/arch/powerpc/sysdev/ehv_pic.c b/arch/powerpc/sysdev/ehv_pic.c index b6731e4a664..6e0e1005227 100644 --- a/arch/powerpc/sysdev/ehv_pic.c +++ b/arch/powerpc/sysdev/ehv_pic.c @@ -182,13 +182,13 @@ unsigned int ehv_pic_get_irq(void)  	return irq_linear_revmap(global_ehv_pic->irqhost, irq);  } -static int ehv_pic_host_match(struct irq_host *h, struct device_node *node) +static int ehv_pic_host_match(struct irq_domain *h, struct device_node *node)  {  	/* Exact match, unless ehv_pic node is NULL */  	return h->of_node == NULL || h->of_node == node;  } -static int ehv_pic_host_map(struct irq_host *h, unsigned int virq, +static int ehv_pic_host_map(struct irq_domain *h, unsigned int virq,  			 irq_hw_number_t hw)  {  	struct ehv_pic *ehv_pic = h->host_data; @@ -217,7 +217,7 @@ static int ehv_pic_host_map(struct irq_host *h, unsigned int virq,  	return 0;  } -static int ehv_pic_host_xlate(struct irq_host *h, struct device_node *ct, +static int ehv_pic_host_xlate(struct irq_domain *h, struct device_node *ct,  			   const u32 *intspec, unsigned int intsize,  			   irq_hw_number_t *out_hwirq, unsigned int *out_flags) @@ -248,7 +248,7 @@ static int ehv_pic_host_xlate(struct irq_host *h, struct device_node *ct,  	return 0;  } -static struct irq_host_ops ehv_pic_host_ops = { +static const struct irq_domain_ops ehv_pic_host_ops = {  	.match = ehv_pic_host_match,  	.map = ehv_pic_host_map,  	.xlate = ehv_pic_host_xlate, @@ -275,9 +275,8 @@ void __init ehv_pic_init(void)  		return;  	} -	ehv_pic->irqhost = irq_alloc_host(np, IRQ_HOST_MAP_LINEAR, -		NR_EHV_PIC_INTS, &ehv_pic_host_ops, 0); - +	ehv_pic->irqhost = irq_domain_add_linear(np, NR_EHV_PIC_INTS, +						 &ehv_pic_host_ops, ehv_pic);  	if (!ehv_pic->irqhost) {  		of_node_put(np);  		kfree(ehv_pic); @@ -293,7 +292,6 @@ void __init ehv_pic_init(void)  		of_node_put(np2);  	} -	ehv_pic->irqhost->host_data = ehv_pic;  	ehv_pic->hc_irq = ehv_pic_irq_chip;  	ehv_pic->hc_irq.irq_set_affinity = ehv_pic_set_affinity;  	ehv_pic->coreint_flag = coreint_flag; diff --git a/arch/powerpc/sysdev/fsl_msi.c b/arch/powerpc/sysdev/fsl_msi.c index ecb5c1946d2..0c01debe963 100644 --- a/arch/powerpc/sysdev/fsl_msi.c +++ b/arch/powerpc/sysdev/fsl_msi.c @@ -60,7 +60,7 @@ static struct irq_chip fsl_msi_chip = {  	.name		= "FSL-MSI",  }; -static int fsl_msi_host_map(struct irq_host *h, unsigned int virq, +static int fsl_msi_host_map(struct irq_domain *h, unsigned int virq,  				irq_hw_number_t hw)  {  	struct fsl_msi *msi_data = h->host_data; @@ -74,7 +74,7 @@ static int fsl_msi_host_map(struct irq_host *h, unsigned int virq,  	return 0;  } -static struct irq_host_ops fsl_msi_host_ops = { +static const struct irq_domain_ops fsl_msi_host_ops = {  	.map = fsl_msi_host_map,  }; @@ -387,8 +387,8 @@ static int __devinit fsl_of_msi_probe(struct platform_device *dev)  	}  	platform_set_drvdata(dev, msi); -	msi->irqhost = irq_alloc_host(dev->dev.of_node, IRQ_HOST_MAP_LINEAR, -				      NR_MSI_IRQS, &fsl_msi_host_ops, 0); +	msi->irqhost = irq_domain_add_linear(dev->dev.of_node, +				      NR_MSI_IRQS, &fsl_msi_host_ops, msi);  	if (msi->irqhost == NULL) {  		dev_err(&dev->dev, "No memory for MSI irqhost\n"); @@ -420,8 +420,6 @@ static int __devinit fsl_of_msi_probe(struct platform_device *dev)  	msi->feature = features->fsl_pic_ip; -	msi->irqhost->host_data = msi; -  	/*  	 * Remember the phandle, so that we can match with any PCI nodes  	 * that have an "fsl,msi" property. diff --git a/arch/powerpc/sysdev/fsl_msi.h b/arch/powerpc/sysdev/fsl_msi.h index f6c646a5254..8225f8653f7 100644 --- a/arch/powerpc/sysdev/fsl_msi.h +++ b/arch/powerpc/sysdev/fsl_msi.h @@ -26,7 +26,7 @@  #define FSL_PIC_IP_VMPIC  0x00000003  struct fsl_msi { -	struct irq_host *irqhost; +	struct irq_domain *irqhost;  	unsigned long cascade_irq; diff --git a/arch/powerpc/sysdev/i8259.c b/arch/powerpc/sysdev/i8259.c index d18bb27e4df..997df6a7ab5 100644 --- a/arch/powerpc/sysdev/i8259.c +++ b/arch/powerpc/sysdev/i8259.c @@ -25,7 +25,7 @@ static unsigned char cached_8259[2] = { 0xff, 0xff };  static DEFINE_RAW_SPINLOCK(i8259_lock); -static struct irq_host *i8259_host; +static struct irq_domain *i8259_host;  /*   * Acknowledge the IRQ using either the PCI host bridge's interrupt @@ -163,12 +163,12 @@ static struct resource pic_edgectrl_iores = {  	.flags = IORESOURCE_BUSY,  }; -static int i8259_host_match(struct irq_host *h, struct device_node *node) +static int i8259_host_match(struct irq_domain *h, struct device_node *node)  {  	return h->of_node == NULL || h->of_node == node;  } -static int i8259_host_map(struct irq_host *h, unsigned int virq, +static int i8259_host_map(struct irq_domain *h, unsigned int virq,  			  irq_hw_number_t hw)  {  	pr_debug("i8259_host_map(%d, 0x%lx)\n", virq, hw); @@ -185,7 +185,7 @@ static int i8259_host_map(struct irq_host *h, unsigned int virq,  	return 0;  } -static int i8259_host_xlate(struct irq_host *h, struct device_node *ct, +static int i8259_host_xlate(struct irq_domain *h, struct device_node *ct,  			    const u32 *intspec, unsigned int intsize,  			    irq_hw_number_t *out_hwirq, unsigned int *out_flags)  { @@ -205,13 +205,13 @@ static int i8259_host_xlate(struct irq_host *h, struct device_node *ct,  	return 0;  } -static struct irq_host_ops i8259_host_ops = { +static struct irq_domain_ops i8259_host_ops = {  	.match = i8259_host_match,  	.map = i8259_host_map,  	.xlate = i8259_host_xlate,  }; -struct irq_host *i8259_get_host(void) +struct irq_domain *i8259_get_host(void)  {  	return i8259_host;  } @@ -263,8 +263,7 @@ void i8259_init(struct device_node *node, unsigned long intack_addr)  	raw_spin_unlock_irqrestore(&i8259_lock, flags);  	/* create a legacy host */ -	i8259_host = irq_alloc_host(node, IRQ_HOST_MAP_LEGACY, -				    0, &i8259_host_ops, 0); +	i8259_host = irq_domain_add_legacy_isa(node, &i8259_host_ops, NULL);  	if (i8259_host == NULL) {  		printk(KERN_ERR "i8259: failed to allocate irq host !\n");  		return; diff --git a/arch/powerpc/sysdev/ipic.c b/arch/powerpc/sysdev/ipic.c index 95da897f05a..b50f97811c2 100644 --- a/arch/powerpc/sysdev/ipic.c +++ b/arch/powerpc/sysdev/ipic.c @@ -672,13 +672,13 @@ static struct irq_chip ipic_edge_irq_chip = {  	.irq_set_type	= ipic_set_irq_type,  }; -static int ipic_host_match(struct irq_host *h, struct device_node *node) +static int ipic_host_match(struct irq_domain *h, struct device_node *node)  {  	/* Exact match, unless ipic node is NULL */  	return h->of_node == NULL || h->of_node == node;  } -static int ipic_host_map(struct irq_host *h, unsigned int virq, +static int ipic_host_map(struct irq_domain *h, unsigned int virq,  			 irq_hw_number_t hw)  {  	struct ipic *ipic = h->host_data; @@ -692,26 +692,10 @@ static int ipic_host_map(struct irq_host *h, unsigned int virq,  	return 0;  } -static int ipic_host_xlate(struct irq_host *h, struct device_node *ct, -			   const u32 *intspec, unsigned int intsize, -			   irq_hw_number_t *out_hwirq, unsigned int *out_flags) - -{ -	/* interrupt sense values coming from the device tree equal either -	 * LEVEL_LOW (low assertion) or EDGE_FALLING (high-to-low change) -	 */ -	*out_hwirq = intspec[0]; -	if (intsize > 1) -		*out_flags = intspec[1]; -	else -		*out_flags = IRQ_TYPE_NONE; -	return 0; -} - -static struct irq_host_ops ipic_host_ops = { +static struct irq_domain_ops ipic_host_ops = {  	.match	= ipic_host_match,  	.map	= ipic_host_map, -	.xlate	= ipic_host_xlate, +	.xlate	= irq_domain_xlate_onetwocell,  };  struct ipic * __init ipic_init(struct device_node *node, unsigned int flags) @@ -728,9 +712,8 @@ struct ipic * __init ipic_init(struct device_node *node, unsigned int flags)  	if (ipic == NULL)  		return NULL; -	ipic->irqhost = irq_alloc_host(node, IRQ_HOST_MAP_LINEAR, -				       NR_IPIC_INTS, -				       &ipic_host_ops, 0); +	ipic->irqhost = irq_domain_add_linear(node, NR_IPIC_INTS, +					      &ipic_host_ops, ipic);  	if (ipic->irqhost == NULL) {  		kfree(ipic);  		return NULL; @@ -738,8 +721,6 @@ struct ipic * __init ipic_init(struct device_node *node, unsigned int flags)  	ipic->regs = ioremap(res.start, resource_size(&res)); -	ipic->irqhost->host_data = ipic; -  	/* init hw */  	ipic_write(ipic->regs, IPIC_SICNR, 0x0); diff --git a/arch/powerpc/sysdev/ipic.h b/arch/powerpc/sysdev/ipic.h index 9391c57b0c5..90031d1282e 100644 --- a/arch/powerpc/sysdev/ipic.h +++ b/arch/powerpc/sysdev/ipic.h @@ -43,7 +43,7 @@ struct ipic {  	volatile u32 __iomem	*regs;  	/* The remapper for this IPIC */ -	struct irq_host		*irqhost; +	struct irq_domain		*irqhost;  };  struct ipic_info { diff --git a/arch/powerpc/sysdev/mpc8xx_pic.c b/arch/powerpc/sysdev/mpc8xx_pic.c index 2ca0a85fcce..d5f5416be31 100644 --- a/arch/powerpc/sysdev/mpc8xx_pic.c +++ b/arch/powerpc/sysdev/mpc8xx_pic.c @@ -17,7 +17,7 @@  extern int cpm_get_irq(struct pt_regs *regs); -static struct irq_host *mpc8xx_pic_host; +static struct irq_domain *mpc8xx_pic_host;  #define NR_MASK_WORDS   ((NR_IRQS + 31) / 32)  static unsigned long ppc_cached_irq_mask[NR_MASK_WORDS];  static sysconf8xx_t __iomem *siu_reg; @@ -110,7 +110,7 @@ unsigned int mpc8xx_get_irq(void)  } -static int mpc8xx_pic_host_map(struct irq_host *h, unsigned int virq, +static int mpc8xx_pic_host_map(struct irq_domain *h, unsigned int virq,  			  irq_hw_number_t hw)  {  	pr_debug("mpc8xx_pic_host_map(%d, 0x%lx)\n", virq, hw); @@ -121,7 +121,7 @@ static int mpc8xx_pic_host_map(struct irq_host *h, unsigned int virq,  } -static int mpc8xx_pic_host_xlate(struct irq_host *h, struct device_node *ct, +static int mpc8xx_pic_host_xlate(struct irq_domain *h, struct device_node *ct,  			    const u32 *intspec, unsigned int intsize,  			    irq_hw_number_t *out_hwirq, unsigned int *out_flags)  { @@ -142,7 +142,7 @@ static int mpc8xx_pic_host_xlate(struct irq_host *h, struct device_node *ct,  } -static struct irq_host_ops mpc8xx_pic_host_ops = { +static struct irq_domain_ops mpc8xx_pic_host_ops = {  	.map = mpc8xx_pic_host_map,  	.xlate = mpc8xx_pic_host_xlate,  }; @@ -171,8 +171,7 @@ int mpc8xx_pic_init(void)  		goto out;  	} -	mpc8xx_pic_host = irq_alloc_host(np, IRQ_HOST_MAP_LINEAR, -					 64, &mpc8xx_pic_host_ops, 64); +	mpc8xx_pic_host = irq_domain_add_linear(np, 64, &mpc8xx_pic_host_ops, NULL);  	if (mpc8xx_pic_host == NULL) {  		printk(KERN_ERR "MPC8xx PIC: failed to allocate irq host!\n");  		ret = -ENOMEM; diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index 4e9ccb1015d..c83a512fa17 100644 --- a/arch/powerpc/sysdev/mpic.c +++ b/arch/powerpc/sysdev/mpic.c @@ -965,13 +965,13 @@ static struct irq_chip mpic_irq_ht_chip = {  #endif /* CONFIG_MPIC_U3_HT_IRQS */ -static int mpic_host_match(struct irq_host *h, struct device_node *node) +static int mpic_host_match(struct irq_domain *h, struct device_node *node)  {  	/* Exact match, unless mpic node is NULL */  	return h->of_node == NULL || h->of_node == node;  } -static int mpic_host_map(struct irq_host *h, unsigned int virq, +static int mpic_host_map(struct irq_domain *h, unsigned int virq,  			 irq_hw_number_t hw)  {  	struct mpic *mpic = h->host_data; @@ -1041,7 +1041,7 @@ static int mpic_host_map(struct irq_host *h, unsigned int virq,  	return 0;  } -static int mpic_host_xlate(struct irq_host *h, struct device_node *ct, +static int mpic_host_xlate(struct irq_domain *h, struct device_node *ct,  			   const u32 *intspec, unsigned int intsize,  			   irq_hw_number_t *out_hwirq, unsigned int *out_flags) @@ -1121,13 +1121,13 @@ static void mpic_cascade(unsigned int irq, struct irq_desc *desc)  	BUG_ON(!(mpic->flags & MPIC_SECONDARY));  	virq = mpic_get_one_irq(mpic); -	if (virq != NO_IRQ) +	if (virq)  		generic_handle_irq(virq);  	chip->irq_eoi(&desc->irq_data);  } -static struct irq_host_ops mpic_host_ops = { +static struct irq_domain_ops mpic_host_ops = {  	.match = mpic_host_match,  	.map = mpic_host_map,  	.xlate = mpic_host_xlate, @@ -1345,10 +1345,9 @@ struct mpic * __init mpic_alloc(struct device_node *node,  	mpic->isu_shift = 1 + __ilog2(mpic->isu_size - 1);  	mpic->isu_mask = (1 << mpic->isu_shift) - 1; -	mpic->irqhost = irq_alloc_host(mpic->node, IRQ_HOST_MAP_LINEAR, +	mpic->irqhost = irq_domain_add_linear(mpic->node,  				       isu_size ? isu_size : mpic->num_sources, -				       &mpic_host_ops, -				       flags & MPIC_LARGE_VECTORS ? 2048 : 256); +				       &mpic_host_ops, mpic);  	/*  	 * FIXME: The code leaks the MPIC object and mappings here; this @@ -1357,8 +1356,6 @@ struct mpic * __init mpic_alloc(struct device_node *node,  	if (mpic->irqhost == NULL)  		return NULL; -	mpic->irqhost->host_data = mpic; -  	/* Display version */  	switch (greg_feature & MPIC_GREG_FEATURE_VERSION_MASK) {  	case 1: diff --git a/arch/powerpc/sysdev/mpic_msi.c b/arch/powerpc/sysdev/mpic_msi.c index 0f67cd79d48..0622aa91b18 100644 --- a/arch/powerpc/sysdev/mpic_msi.c +++ b/arch/powerpc/sysdev/mpic_msi.c @@ -32,7 +32,7 @@ void mpic_msi_reserve_hwirq(struct mpic *mpic, irq_hw_number_t hwirq)  static int mpic_msi_reserve_u3_hwirqs(struct mpic *mpic)  {  	irq_hw_number_t hwirq; -	struct irq_host_ops *ops = mpic->irqhost->ops; +	const struct irq_domain_ops *ops = mpic->irqhost->ops;  	struct device_node *np;  	int flags, index, i;  	struct of_irq oirq; diff --git a/arch/powerpc/sysdev/mv64x60_pic.c b/arch/powerpc/sysdev/mv64x60_pic.c index 14d130268e7..8848e99a83f 100644 --- a/arch/powerpc/sysdev/mv64x60_pic.c +++ b/arch/powerpc/sysdev/mv64x60_pic.c @@ -70,7 +70,7 @@ static u32 mv64x60_cached_low_mask;  static u32 mv64x60_cached_high_mask = MV64X60_HIGH_GPP_GROUPS;  static u32 mv64x60_cached_gpp_mask; -static struct irq_host *mv64x60_irq_host; +static struct irq_domain *mv64x60_irq_host;  /*   * mv64x60_chip_low functions @@ -208,7 +208,7 @@ static struct irq_chip *mv64x60_chips[] = {  	[MV64x60_LEVEL1_GPP]  = &mv64x60_chip_gpp,  }; -static int mv64x60_host_map(struct irq_host *h, unsigned int virq, +static int mv64x60_host_map(struct irq_domain *h, unsigned int virq,  			  irq_hw_number_t hwirq)  {  	int level1; @@ -223,7 +223,7 @@ static int mv64x60_host_map(struct irq_host *h, unsigned int virq,  	return 0;  } -static struct irq_host_ops mv64x60_host_ops = { +static struct irq_domain_ops mv64x60_host_ops = {  	.map   = mv64x60_host_map,  }; @@ -250,9 +250,8 @@ void __init mv64x60_init_irq(void)  	paddr = of_translate_address(np, reg);  	mv64x60_irq_reg_base = ioremap(paddr, reg[1]); -	mv64x60_irq_host = irq_alloc_host(np, IRQ_HOST_MAP_LINEAR, -					  MV64x60_NUM_IRQS, -					  &mv64x60_host_ops, MV64x60_NUM_IRQS); +	mv64x60_irq_host = irq_domain_add_linear(np, MV64x60_NUM_IRQS, +					  &mv64x60_host_ops, NULL);  	spin_lock_irqsave(&mv64x60_lock, flags);  	out_le32(mv64x60_gpp_reg_base + MV64x60_GPP_INTR_MASK, diff --git a/arch/powerpc/sysdev/qe_lib/qe_ic.c b/arch/powerpc/sysdev/qe_lib/qe_ic.c index 73034bd203c..2fba6ef2f95 100644 --- a/arch/powerpc/sysdev/qe_lib/qe_ic.c +++ b/arch/powerpc/sysdev/qe_lib/qe_ic.c @@ -245,13 +245,13 @@ static struct irq_chip qe_ic_irq_chip = {  	.irq_mask_ack = qe_ic_mask_irq,  }; -static int qe_ic_host_match(struct irq_host *h, struct device_node *node) +static int qe_ic_host_match(struct irq_domain *h, struct device_node *node)  {  	/* Exact match, unless qe_ic node is NULL */  	return h->of_node == NULL || h->of_node == node;  } -static int qe_ic_host_map(struct irq_host *h, unsigned int virq, +static int qe_ic_host_map(struct irq_domain *h, unsigned int virq,  			  irq_hw_number_t hw)  {  	struct qe_ic *qe_ic = h->host_data; @@ -272,23 +272,10 @@ static int qe_ic_host_map(struct irq_host *h, unsigned int virq,  	return 0;  } -static int qe_ic_host_xlate(struct irq_host *h, struct device_node *ct, -			    const u32 * intspec, unsigned int intsize, -			    irq_hw_number_t * out_hwirq, -			    unsigned int *out_flags) -{ -	*out_hwirq = intspec[0]; -	if (intsize > 1) -		*out_flags = intspec[1]; -	else -		*out_flags = IRQ_TYPE_NONE; -	return 0; -} - -static struct irq_host_ops qe_ic_host_ops = { +static struct irq_domain_ops qe_ic_host_ops = {  	.match = qe_ic_host_match,  	.map = qe_ic_host_map, -	.xlate = qe_ic_host_xlate, +	.xlate = irq_domain_xlate_onetwocell,  };  /* Return an interrupt vector or NO_IRQ if no interrupt is pending. */ @@ -339,8 +326,8 @@ void __init qe_ic_init(struct device_node *node, unsigned int flags,  	if (qe_ic == NULL)  		return; -	qe_ic->irqhost = irq_alloc_host(node, IRQ_HOST_MAP_LINEAR, -					NR_QE_IC_INTS, &qe_ic_host_ops, 0); +	qe_ic->irqhost = irq_domain_add_linear(node, NR_QE_IC_INTS, +					       &qe_ic_host_ops, qe_ic);  	if (qe_ic->irqhost == NULL) {  		kfree(qe_ic);  		return; @@ -348,7 +335,6 @@ void __init qe_ic_init(struct device_node *node, unsigned int flags,  	qe_ic->regs = ioremap(res.start, resource_size(&res)); -	qe_ic->irqhost->host_data = qe_ic;  	qe_ic->hc_irq = qe_ic_irq_chip;  	qe_ic->virq_high = irq_of_parse_and_map(node, 0); diff --git a/arch/powerpc/sysdev/qe_lib/qe_ic.h b/arch/powerpc/sysdev/qe_lib/qe_ic.h index c1361d005a8..c327872ed35 100644 --- a/arch/powerpc/sysdev/qe_lib/qe_ic.h +++ b/arch/powerpc/sysdev/qe_lib/qe_ic.h @@ -79,7 +79,7 @@ struct qe_ic {  	volatile u32 __iomem *regs;  	/* The remapper for this QEIC */ -	struct irq_host *irqhost; +	struct irq_domain *irqhost;  	/* The "linux" controller struct */  	struct irq_chip hc_irq; diff --git a/arch/powerpc/sysdev/tsi108_pci.c b/arch/powerpc/sysdev/tsi108_pci.c index 4d18658116e..188012c58f7 100644 --- a/arch/powerpc/sysdev/tsi108_pci.c +++ b/arch/powerpc/sysdev/tsi108_pci.c @@ -51,7 +51,7 @@  u32 tsi108_pci_cfg_base;  static u32 tsi108_pci_cfg_phys;  u32 tsi108_csr_vir_base; -static struct irq_host *pci_irq_host; +static struct irq_domain *pci_irq_host;  extern u32 get_vir_csrbase(void);  extern u32 tsi108_read_reg(u32 reg_offset); @@ -376,7 +376,7 @@ static struct irq_chip tsi108_pci_irq = {  	.irq_unmask = tsi108_pci_irq_unmask,  }; -static int pci_irq_host_xlate(struct irq_host *h, struct device_node *ct, +static int pci_irq_host_xlate(struct irq_domain *h, struct device_node *ct,  			    const u32 *intspec, unsigned int intsize,  			    irq_hw_number_t *out_hwirq, unsigned int *out_flags)  { @@ -385,7 +385,7 @@ static int pci_irq_host_xlate(struct irq_host *h, struct device_node *ct,  	return 0;  } -static int pci_irq_host_map(struct irq_host *h, unsigned int virq, +static int pci_irq_host_map(struct irq_domain *h, unsigned int virq,  			  irq_hw_number_t hw)  {	unsigned int irq;  	DBG("%s(%d, 0x%lx)\n", __func__, virq, hw); @@ -397,7 +397,7 @@ static int pci_irq_host_map(struct irq_host *h, unsigned int virq,  	return 0;  } -static struct irq_host_ops pci_irq_host_ops = { +static struct irq_domain_ops pci_irq_domain_ops = {  	.map = pci_irq_host_map,  	.xlate = pci_irq_host_xlate,  }; @@ -419,10 +419,9 @@ void __init tsi108_pci_int_init(struct device_node *node)  {  	DBG("Tsi108_pci_int_init: initializing PCI interrupts\n"); -	pci_irq_host = irq_alloc_host(node, IRQ_HOST_MAP_LEGACY, -				      0, &pci_irq_host_ops, 0); +	pci_irq_host = irq_domain_add_legacy_isa(node, &pci_irq_domain_ops, NULL);  	if (pci_irq_host == NULL) { -		printk(KERN_ERR "pci_irq_host: failed to allocate irq host !\n"); +		printk(KERN_ERR "pci_irq_host: failed to allocate irq domain!\n");  		return;  	} diff --git a/arch/powerpc/sysdev/uic.c b/arch/powerpc/sysdev/uic.c index 063c901b126..92033936a8f 100644 --- a/arch/powerpc/sysdev/uic.c +++ b/arch/powerpc/sysdev/uic.c @@ -49,7 +49,7 @@ struct uic {  	raw_spinlock_t lock;  	/* The remapper for this UIC */ -	struct irq_host	*irqhost; +	struct irq_domain	*irqhost;  };  static void uic_unmask_irq(struct irq_data *d) @@ -174,7 +174,7 @@ static struct irq_chip uic_irq_chip = {  	.irq_set_type	= uic_set_irq_type,  }; -static int uic_host_map(struct irq_host *h, unsigned int virq, +static int uic_host_map(struct irq_domain *h, unsigned int virq,  			irq_hw_number_t hw)  {  	struct uic *uic = h->host_data; @@ -190,21 +190,9 @@ static int uic_host_map(struct irq_host *h, unsigned int virq,  	return 0;  } -static int uic_host_xlate(struct irq_host *h, struct device_node *ct, -			  const u32 *intspec, unsigned int intsize, -			  irq_hw_number_t *out_hwirq, unsigned int *out_type) - -{ -	/* UIC intspecs must have 2 cells */ -	BUG_ON(intsize != 2); -	*out_hwirq = intspec[0]; -	*out_type = intspec[1]; -	return 0; -} - -static struct irq_host_ops uic_host_ops = { +static struct irq_domain_ops uic_host_ops = {  	.map	= uic_host_map, -	.xlate	= uic_host_xlate, +	.xlate	= irq_domain_xlate_twocell,  };  void uic_irq_cascade(unsigned int virq, struct irq_desc *desc) @@ -270,13 +258,11 @@ static struct uic * __init uic_init_one(struct device_node *node)  	}  	uic->dcrbase = *dcrreg; -	uic->irqhost = irq_alloc_host(node, IRQ_HOST_MAP_LINEAR, -				      NR_UIC_INTS, &uic_host_ops, -1); +	uic->irqhost = irq_domain_add_linear(node, NR_UIC_INTS, &uic_host_ops, +					     uic);  	if (! uic->irqhost)  		return NULL; /* FIXME: panic? */ -	uic->irqhost->host_data = uic; -  	/* Start with all interrupts disabled, level and non-critical */  	mtdcr(uic->dcrbase + UIC_ER, 0);  	mtdcr(uic->dcrbase + UIC_CR, 0); diff --git a/arch/powerpc/sysdev/xics/xics-common.c b/arch/powerpc/sysdev/xics/xics-common.c index d72eda6a4c0..ea5e204e345 100644 --- a/arch/powerpc/sysdev/xics/xics-common.c +++ b/arch/powerpc/sysdev/xics/xics-common.c @@ -40,7 +40,7 @@ unsigned int xics_interrupt_server_size		= 8;  DEFINE_PER_CPU(struct xics_cppr, xics_cppr); -struct irq_host *xics_host; +struct irq_domain *xics_host;  static LIST_HEAD(ics_list); @@ -212,16 +212,16 @@ void xics_migrate_irqs_away(void)  		/* We can't set affinity on ISA interrupts */  		if (virq < NUM_ISA_INTERRUPTS)  			continue; -		if (!virq_is_host(virq, xics_host)) -			continue; -		irq = (unsigned int)virq_to_hw(virq); -		/* We need to get IPIs still. */ -		if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS) -			continue;  		desc = irq_to_desc(virq);  		/* We only need to migrate enabled IRQS */  		if (!desc || !desc->action)  			continue; +		if (desc->irq_data.domain != xics_host) +			continue; +		irq = desc->irq_data.hwirq; +		/* We need to get IPIs still. */ +		if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS) +			continue;  		chip = irq_desc_get_chip(desc);  		if (!chip || !chip->irq_set_affinity)  			continue; @@ -301,7 +301,7 @@ int xics_get_irq_server(unsigned int virq, const struct cpumask *cpumask,  }  #endif /* CONFIG_SMP */ -static int xics_host_match(struct irq_host *h, struct device_node *node) +static int xics_host_match(struct irq_domain *h, struct device_node *node)  {  	struct ics *ics; @@ -323,7 +323,7 @@ static struct irq_chip xics_ipi_chip = {  	.irq_unmask = xics_ipi_unmask,  }; -static int xics_host_map(struct irq_host *h, unsigned int virq, +static int xics_host_map(struct irq_domain *h, unsigned int virq,  			 irq_hw_number_t hw)  {  	struct ics *ics; @@ -351,7 +351,7 @@ static int xics_host_map(struct irq_host *h, unsigned int virq,  	return -EINVAL;  } -static int xics_host_xlate(struct irq_host *h, struct device_node *ct, +static int xics_host_xlate(struct irq_domain *h, struct device_node *ct,  			   const u32 *intspec, unsigned int intsize,  			   irq_hw_number_t *out_hwirq, unsigned int *out_flags) @@ -366,7 +366,7 @@ static int xics_host_xlate(struct irq_host *h, struct device_node *ct,  	return 0;  } -static struct irq_host_ops xics_host_ops = { +static struct irq_domain_ops xics_host_ops = {  	.match = xics_host_match,  	.map = xics_host_map,  	.xlate = xics_host_xlate, @@ -374,8 +374,7 @@ static struct irq_host_ops xics_host_ops = {  static void __init xics_init_host(void)  { -	xics_host = irq_alloc_host(NULL, IRQ_HOST_MAP_TREE, 0, &xics_host_ops, -				   XICS_IRQ_SPURIOUS); +	xics_host = irq_domain_add_tree(NULL, &xics_host_ops, NULL);  	BUG_ON(xics_host == NULL);  	irq_set_default_host(xics_host);  } diff --git a/arch/powerpc/sysdev/xilinx_intc.c b/arch/powerpc/sysdev/xilinx_intc.c index 6183799754a..8d73c3c0bee 100644 --- a/arch/powerpc/sysdev/xilinx_intc.c +++ b/arch/powerpc/sysdev/xilinx_intc.c @@ -40,7 +40,7 @@  #define XINTC_IVR	24	/* Interrupt Vector */  #define XINTC_MER	28	/* Master Enable */ -static struct irq_host *master_irqhost; +static struct irq_domain *master_irqhost;  #define XILINX_INTC_MAXIRQS	(32) @@ -141,7 +141,7 @@ static struct irq_chip xilinx_intc_edge_irqchip = {  /**   * xilinx_intc_xlate - translate virq# from device tree interrupts property   */ -static int xilinx_intc_xlate(struct irq_host *h, struct device_node *ct, +static int xilinx_intc_xlate(struct irq_domain *h, struct device_node *ct,  				const u32 *intspec, unsigned int intsize,  				irq_hw_number_t *out_hwirq,  				unsigned int *out_flags) @@ -161,7 +161,7 @@ static int xilinx_intc_xlate(struct irq_host *h, struct device_node *ct,  	return 0;  } -static int xilinx_intc_map(struct irq_host *h, unsigned int virq, +static int xilinx_intc_map(struct irq_domain *h, unsigned int virq,  				  irq_hw_number_t irq)  {  	irq_set_chip_data(virq, h->host_data); @@ -177,15 +177,15 @@ static int xilinx_intc_map(struct irq_host *h, unsigned int virq,  	return 0;  } -static struct irq_host_ops xilinx_intc_ops = { +static struct irq_domain_ops xilinx_intc_ops = {  	.map = xilinx_intc_map,  	.xlate = xilinx_intc_xlate,  }; -struct irq_host * __init +struct irq_domain * __init  xilinx_intc_init(struct device_node *np)  { -	struct irq_host * irq; +	struct irq_domain * irq;  	void * regs;  	/* Find and map the intc registers */ @@ -200,12 +200,11 @@ xilinx_intc_init(struct device_node *np)  	out_be32(regs + XINTC_IAR, ~(u32) 0); /* Acknowledge pending irqs */  	out_be32(regs + XINTC_MER, 0x3UL); /* Turn on the Master Enable. */ -	/* Allocate and initialize an irq_host structure. */ -	irq = irq_alloc_host(np, IRQ_HOST_MAP_LINEAR, XILINX_INTC_MAXIRQS, -			     &xilinx_intc_ops, -1); +	/* Allocate and initialize an irq_domain structure. */ +	irq = irq_domain_add_linear(np, XILINX_INTC_MAXIRQS, &xilinx_intc_ops, +				    regs);  	if (!irq)  		panic(__FILE__ ": Cannot allocate IRQ host\n"); -	irq->host_data = regs;  	return irq;  } diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index 3c8db65c89e..713fb58ca50 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -859,6 +859,7 @@ config PCI  	depends on SYS_SUPPORTS_PCI  	select PCI_DOMAINS  	select GENERIC_PCI_IOMAP +	select NO_GENERIC_PCI_IOPORT_MAP  	help  	  Find out whether you have a PCI motherboard. PCI is the name of a  	  bus system, i.e. the way the CPU talks to the other stuff inside diff --git a/arch/sh/drivers/pci/pci.c b/arch/sh/drivers/pci/pci.c index 8f18dd090a6..1e7b0e2e764 100644 --- a/arch/sh/drivers/pci/pci.c +++ b/arch/sh/drivers/pci/pci.c @@ -356,8 +356,8 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,  #ifndef CONFIG_GENERIC_IOMAP -static void __iomem *ioport_map_pci(struct pci_dev *dev, -				    unsigned long port, unsigned int nr) +void __iomem *__pci_ioport_map(struct pci_dev *dev, +			       unsigned long port, unsigned int nr)  {  	struct pci_channel *chan = dev->sysdata; diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index 96657992a72..ca5580e4d81 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig @@ -33,6 +33,7 @@ config SPARC  config SPARC32  	def_bool !64BIT  	select GENERIC_ATOMIC64 +	select CLZ_TAB  config SPARC64  	def_bool 64BIT diff --git a/arch/sparc/include/asm/prom.h b/arch/sparc/include/asm/prom.h index edd3d3cde46..c2876511070 100644 --- a/arch/sparc/include/asm/prom.h +++ b/arch/sparc/include/asm/prom.h @@ -22,6 +22,7 @@  #include <linux/proc_fs.h>  #include <linux/mutex.h>  #include <linux/atomic.h> +#include <linux/irqdomain.h>  #define OF_ROOT_NODE_ADDR_CELLS_DEFAULT	2  #define OF_ROOT_NODE_SIZE_CELLS_DEFAULT	1 @@ -55,15 +56,6 @@ struct resource;  extern void __iomem *of_ioremap(struct resource *res, unsigned long offset, unsigned long size, char *name);  extern void of_iounmap(struct resource *res, void __iomem *base, unsigned long size); -/* These routines are here to provide compatibility with how powerpc - * handles IRQ mapping for OF device nodes.  We precompute and permanently - * register them in the platform_device objects, whereas powerpc computes them - * on request. - */ -static inline void irq_dispose_mapping(unsigned int virq) -{ -} -  extern struct device_node *of_console_device;  extern char *of_console_path;  extern char *of_console_options; diff --git a/arch/sparc/lib/divdi3.S b/arch/sparc/lib/divdi3.S index 681b3683da9..d74bc0925f2 100644 --- a/arch/sparc/lib/divdi3.S +++ b/arch/sparc/lib/divdi3.S @@ -17,23 +17,9 @@ along with GNU CC; see the file COPYING.  If not, write to  the Free Software Foundation, 59 Temple Place - Suite 330,  Boston, MA 02111-1307, USA.  */ -	.data -	.align 8 -	.globl	__clz_tab -__clz_tab: -	.byte	0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5 -	.byte	6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6 -	.byte	7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7 -	.byte	7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7 -	.byte	8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 -	.byte	8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 -	.byte	8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 -	.byte	8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 -	.size	 __clz_tab,256 -	.global .udiv -  	.text  	.align 4 +	.global .udiv  	.globl __divdi3  __divdi3:  	save %sp,-104,%sp diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 5bed94e189f..e0829a6a466 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -398,6 +398,7 @@ config X86_INTEL_CE  	select X86_REBOOTFIXUPS  	select OF  	select OF_EARLY_FLATTREE +	select IRQ_DOMAIN  	---help---  	  Select for the Intel CE media processor (CE4100) SOC.  	  This option compiles in support for the CE4100 SOC for settop @@ -2076,6 +2077,7 @@ config OLPC  	select GPIOLIB  	select OF  	select OF_PROMTREE +	select IRQ_DOMAIN  	---help---  	  Add support for detecting the unique features of the OLPC  	  XO hardware. diff --git a/arch/x86/include/asm/cmpxchg.h b/arch/x86/include/asm/cmpxchg.h index 0c9fa2745f1..b3b73326290 100644 --- a/arch/x86/include/asm/cmpxchg.h +++ b/arch/x86/include/asm/cmpxchg.h @@ -145,13 +145,13 @@ extern void __add_wrong_size(void)  #ifdef __HAVE_ARCH_CMPXCHG  #define cmpxchg(ptr, old, new)						\ -	__cmpxchg((ptr), (old), (new), sizeof(*ptr)) +	__cmpxchg(ptr, old, new, sizeof(*(ptr)))  #define sync_cmpxchg(ptr, old, new)					\ -	__sync_cmpxchg((ptr), (old), (new), sizeof(*ptr)) +	__sync_cmpxchg(ptr, old, new, sizeof(*(ptr)))  #define cmpxchg_local(ptr, old, new)					\ -	__cmpxchg_local((ptr), (old), (new), sizeof(*ptr)) +	__cmpxchg_local(ptr, old, new, sizeof(*(ptr)))  #endif  /* diff --git a/arch/x86/include/asm/i387.h b/arch/x86/include/asm/i387.h index 6919e936345..a29571821b9 100644 --- a/arch/x86/include/asm/i387.h +++ b/arch/x86/include/asm/i387.h @@ -29,7 +29,7 @@ extern unsigned int sig_xstate_size;  extern void fpu_init(void);  extern void mxcsr_feature_mask_init(void);  extern int init_fpu(struct task_struct *child); -extern asmlinkage void math_state_restore(void); +extern void math_state_restore(void);  extern void __math_state_restore(void);  extern int dump_fpu(struct pt_regs *, struct user_i387_struct *); @@ -307,9 +307,54 @@ static inline void __clear_fpu(struct task_struct *tsk)  	}  } +/* + * Were we in an interrupt that interrupted kernel mode? + * + * We can do a kernel_fpu_begin/end() pair *ONLY* if that + * pair does nothing at all: TS_USEDFPU must be clear (so + * that we don't try to save the FPU state), and TS must + * be set (so that the clts/stts pair does nothing that is + * visible in the interrupted kernel thread). + */ +static inline bool interrupted_kernel_fpu_idle(void) +{ +	return !(current_thread_info()->status & TS_USEDFPU) && +		(read_cr0() & X86_CR0_TS); +} + +/* + * Were we in user mode (or vm86 mode) when we were + * interrupted? + * + * Doing kernel_fpu_begin/end() is ok if we are running + * in an interrupt context from user mode - we'll just + * save the FPU state as required. + */ +static inline bool interrupted_user_mode(void) +{ +	struct pt_regs *regs = get_irq_regs(); +	return regs && user_mode_vm(regs); +} + +/* + * Can we use the FPU in kernel mode with the + * whole "kernel_fpu_begin/end()" sequence? + * + * It's always ok in process context (ie "not interrupt") + * but it is sometimes ok even from an irq. + */ +static inline bool irq_fpu_usable(void) +{ +	return !in_interrupt() || +		interrupted_user_mode() || +		interrupted_kernel_fpu_idle(); +} +  static inline void kernel_fpu_begin(void)  {  	struct thread_info *me = current_thread_info(); + +	WARN_ON_ONCE(!irq_fpu_usable());  	preempt_disable();  	if (me->status & TS_USEDFPU)  		__save_init_fpu(me->task); @@ -323,14 +368,6 @@ static inline void kernel_fpu_end(void)  	preempt_enable();  } -static inline bool irq_fpu_usable(void) -{ -	struct pt_regs *regs; - -	return !in_interrupt() || !(regs = get_irq_regs()) || \ -		user_mode(regs) || (read_cr0() & X86_CR0_TS); -} -  /*   * Some instructions like VIA's padlock instructions generate a spurious   * DNA fault but don't modify SSE registers. And these instructions @@ -367,6 +404,7 @@ static inline void irq_ts_restore(int TS_state)   */  static inline void save_init_fpu(struct task_struct *tsk)  { +	WARN_ON_ONCE(task_thread_info(tsk)->status & TS_USEDFPU);  	preempt_disable();  	__save_init_fpu(tsk);  	stts(); diff --git a/arch/x86/include/asm/irq_controller.h b/arch/x86/include/asm/irq_controller.h deleted file mode 100644 index 423bbbddf36..00000000000 --- a/arch/x86/include/asm/irq_controller.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef __IRQ_CONTROLLER__ -#define __IRQ_CONTROLLER__ - -struct irq_domain { -	int (*xlate)(struct irq_domain *h, const u32 *intspec, u32 intsize, -			u32 *out_hwirq, u32 *out_type); -	void *priv; -	struct device_node *controller; -	struct list_head l; -}; - -#endif diff --git a/arch/x86/include/asm/kvm_emulate.h b/arch/x86/include/asm/kvm_emulate.h index ab4092e3214..7b9cfc4878a 100644 --- a/arch/x86/include/asm/kvm_emulate.h +++ b/arch/x86/include/asm/kvm_emulate.h @@ -190,6 +190,9 @@ struct x86_emulate_ops {  	int (*intercept)(struct x86_emulate_ctxt *ctxt,  			 struct x86_instruction_info *info,  			 enum x86_intercept_stage stage); + +	bool (*get_cpuid)(struct x86_emulate_ctxt *ctxt, +			 u32 *eax, u32 *ebx, u32 *ecx, u32 *edx);  };  typedef u32 __attribute__((vector_size(16))) sse128_t; @@ -298,6 +301,19 @@ struct x86_emulate_ctxt {  #define X86EMUL_MODE_PROT     (X86EMUL_MODE_PROT16|X86EMUL_MODE_PROT32| \  			       X86EMUL_MODE_PROT64) +/* CPUID vendors */ +#define X86EMUL_CPUID_VENDOR_AuthenticAMD_ebx 0x68747541 +#define X86EMUL_CPUID_VENDOR_AuthenticAMD_ecx 0x444d4163 +#define X86EMUL_CPUID_VENDOR_AuthenticAMD_edx 0x69746e65 + +#define X86EMUL_CPUID_VENDOR_AMDisbetterI_ebx 0x69444d41 +#define X86EMUL_CPUID_VENDOR_AMDisbetterI_ecx 0x21726574 +#define X86EMUL_CPUID_VENDOR_AMDisbetterI_edx 0x74656273 + +#define X86EMUL_CPUID_VENDOR_GenuineIntel_ebx 0x756e6547 +#define X86EMUL_CPUID_VENDOR_GenuineIntel_ecx 0x6c65746e +#define X86EMUL_CPUID_VENDOR_GenuineIntel_edx 0x49656e69 +  enum x86_intercept_stage {  	X86_ICTP_NONE = 0,   /* Allow zero-init to not match anything */  	X86_ICPT_PRE_EXCEPT, diff --git a/arch/x86/include/asm/prom.h b/arch/x86/include/asm/prom.h index 644dd885f05..60bef663609 100644 --- a/arch/x86/include/asm/prom.h +++ b/arch/x86/include/asm/prom.h @@ -21,7 +21,6 @@  #include <asm/irq.h>  #include <linux/atomic.h>  #include <asm/setup.h> -#include <asm/irq_controller.h>  #ifdef CONFIG_OF  extern int of_ioapic; @@ -43,15 +42,6 @@ extern char cmd_line[COMMAND_LINE_SIZE];  #define pci_address_to_pio pci_address_to_pio  unsigned long pci_address_to_pio(phys_addr_t addr); -/** - * irq_dispose_mapping - Unmap an interrupt - * @virq: linux virq number of the interrupt to unmap - * - * FIXME: We really should implement proper virq handling like power, - * but that's going to be major surgery. - */ -static inline void irq_dispose_mapping(unsigned int virq) { } -  #define HAVE_ARCH_DEVTREE_FIXUPS  #endif /* __ASSEMBLY__ */ diff --git a/arch/x86/kernel/cpu/perf_event_intel_ds.c b/arch/x86/kernel/cpu/perf_event_intel_ds.c index 73da6b64f5b..d6bd49faa40 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_ds.c +++ b/arch/x86/kernel/cpu/perf_event_intel_ds.c @@ -439,7 +439,6 @@ void intel_pmu_pebs_enable(struct perf_event *event)  	hwc->config &= ~ARCH_PERFMON_EVENTSEL_INT;  	cpuc->pebs_enabled |= 1ULL << hwc->idx; -	WARN_ON_ONCE(cpuc->enabled);  	if (x86_pmu.intel_cap.pebs_trap && event->attr.precise_ip > 1)  		intel_pmu_lbr_enable(event); diff --git a/arch/x86/kernel/cpu/perf_event_intel_lbr.c b/arch/x86/kernel/cpu/perf_event_intel_lbr.c index 3fab3de3ce9..47a7e63bfe5 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_lbr.c +++ b/arch/x86/kernel/cpu/perf_event_intel_lbr.c @@ -72,8 +72,6 @@ void intel_pmu_lbr_enable(struct perf_event *event)  	if (!x86_pmu.lbr_nr)  		return; -	WARN_ON_ONCE(cpuc->enabled); -  	/*  	 * Reset the LBR stack if we changed task context to  	 * avoid data leaks. diff --git a/arch/x86/kernel/devicetree.c b/arch/x86/kernel/devicetree.c index 52821799a70..3ae2ced4a87 100644 --- a/arch/x86/kernel/devicetree.c +++ b/arch/x86/kernel/devicetree.c @@ -4,6 +4,7 @@  #include <linux/bootmem.h>  #include <linux/export.h>  #include <linux/io.h> +#include <linux/irqdomain.h>  #include <linux/interrupt.h>  #include <linux/list.h>  #include <linux/of.h> @@ -17,64 +18,14 @@  #include <linux/initrd.h>  #include <asm/hpet.h> -#include <asm/irq_controller.h>  #include <asm/apic.h>  #include <asm/pci_x86.h>  __initdata u64 initial_dtb;  char __initdata cmd_line[COMMAND_LINE_SIZE]; -static LIST_HEAD(irq_domains); -static DEFINE_RAW_SPINLOCK(big_irq_lock);  int __initdata of_ioapic; -#ifdef CONFIG_X86_IO_APIC -static void add_interrupt_host(struct irq_domain *ih) -{ -	unsigned long flags; - -	raw_spin_lock_irqsave(&big_irq_lock, flags); -	list_add(&ih->l, &irq_domains); -	raw_spin_unlock_irqrestore(&big_irq_lock, flags); -} -#endif - -static struct irq_domain *get_ih_from_node(struct device_node *controller) -{ -	struct irq_domain *ih, *found = NULL; -	unsigned long flags; - -	raw_spin_lock_irqsave(&big_irq_lock, flags); -	list_for_each_entry(ih, &irq_domains, l) { -		if (ih->controller ==  controller) { -			found = ih; -			break; -		} -	} -	raw_spin_unlock_irqrestore(&big_irq_lock, flags); -	return found; -} - -unsigned int irq_create_of_mapping(struct device_node *controller, -				   const u32 *intspec, unsigned int intsize) -{ -	struct irq_domain *ih; -	u32 virq, type; -	int ret; - -	ih = get_ih_from_node(controller); -	if (!ih) -		return 0; -	ret = ih->xlate(ih, intspec, intsize, &virq, &type); -	if (ret) -		return 0; -	if (type == IRQ_TYPE_NONE) -		return virq; -	irq_set_irq_type(virq, type); -	return virq; -} -EXPORT_SYMBOL_GPL(irq_create_of_mapping); -  unsigned long pci_address_to_pio(phys_addr_t address)  {  	/* @@ -354,36 +305,43 @@ static struct of_ioapic_type of_ioapic_type[] =  	},  }; -static int ioapic_xlate(struct irq_domain *id, const u32 *intspec, u32 intsize, -			u32 *out_hwirq, u32 *out_type) +static int ioapic_xlate(struct irq_domain *domain, +			struct device_node *controller, +			const u32 *intspec, u32 intsize, +			irq_hw_number_t *out_hwirq, u32 *out_type)  { -	struct mp_ioapic_gsi *gsi_cfg;  	struct io_apic_irq_attr attr;  	struct of_ioapic_type *it; -	u32 line, idx, type; +	u32 line, idx; +	int rc; -	if (intsize < 2) +	if (WARN_ON(intsize < 2))  		return -EINVAL; -	line = *intspec; -	idx = (u32) id->priv; -	gsi_cfg = mp_ioapic_gsi_routing(idx); -	*out_hwirq = line + gsi_cfg->gsi_base; - -	intspec++; -	type = *intspec; +	line = intspec[0]; -	if (type >= ARRAY_SIZE(of_ioapic_type)) +	if (intspec[1] >= ARRAY_SIZE(of_ioapic_type))  		return -EINVAL; -	it = of_ioapic_type + type; -	*out_type = it->out_type; +	it = &of_ioapic_type[intspec[1]]; +	idx = (u32) domain->host_data;  	set_io_apic_irq_attr(&attr, idx, line, it->trigger, it->polarity); -	return io_apic_setup_irq_pin_once(*out_hwirq, cpu_to_node(0), &attr); +	rc = io_apic_setup_irq_pin_once(irq_find_mapping(domain, line), +					cpu_to_node(0), &attr); +	if (rc) +		return rc; + +	*out_hwirq = line; +	*out_type = it->out_type; +	return 0;  } +const struct irq_domain_ops ioapic_irq_domain_ops = { +	.xlate = ioapic_xlate, +}; +  static void __init ioapic_add_ofnode(struct device_node *np)  {  	struct resource r; @@ -399,13 +357,14 @@ static void __init ioapic_add_ofnode(struct device_node *np)  	for (i = 0; i < nr_ioapics; i++) {  		if (r.start == mpc_ioapic_addr(i)) {  			struct irq_domain *id; +			struct mp_ioapic_gsi *gsi_cfg; + +			gsi_cfg = mp_ioapic_gsi_routing(i); -			id = kzalloc(sizeof(*id), GFP_KERNEL); +			id = irq_domain_add_legacy(np, 32, gsi_cfg->gsi_base, 0, +						   &ioapic_irq_domain_ops, +						   (void*)i);  			BUG_ON(!id); -			id->controller = np; -			id->xlate = ioapic_xlate; -			id->priv = (void *)i; -			add_interrupt_host(id);  			return;  		}  	} diff --git a/arch/x86/kernel/dumpstack.c b/arch/x86/kernel/dumpstack.c index 1aae78f775f..4025fe4f928 100644 --- a/arch/x86/kernel/dumpstack.c +++ b/arch/x86/kernel/dumpstack.c @@ -252,7 +252,8 @@ int __kprobes __die(const char *str, struct pt_regs *regs, long err)  	unsigned short ss;  	unsigned long sp;  #endif -	printk(KERN_EMERG "%s: %04lx [#%d] ", str, err & 0xffff, ++die_counter); +	printk(KERN_DEFAULT +	       "%s: %04lx [#%d] ", str, err & 0xffff, ++die_counter);  #ifdef CONFIG_PREEMPT  	printk("PREEMPT ");  #endif diff --git a/arch/x86/kernel/dumpstack_64.c b/arch/x86/kernel/dumpstack_64.c index 6d728d9284b..17107bd6e1f 100644 --- a/arch/x86/kernel/dumpstack_64.c +++ b/arch/x86/kernel/dumpstack_64.c @@ -129,7 +129,7 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,  	if (!stack) {  		if (regs)  			stack = (unsigned long *)regs->sp; -		else if (task && task != current) +		else if (task != current)  			stack = (unsigned long *)task->thread.sp;  		else  			stack = &dummy; @@ -269,11 +269,11 @@ void show_registers(struct pt_regs *regs)  		unsigned char c;  		u8 *ip; -		printk(KERN_EMERG "Stack:\n"); +		printk(KERN_DEFAULT "Stack:\n");  		show_stack_log_lvl(NULL, regs, (unsigned long *)sp, -				   0, KERN_EMERG); +				   0, KERN_DEFAULT); -		printk(KERN_EMERG "Code: "); +		printk(KERN_DEFAULT "Code: ");  		ip = (u8 *)regs->ip - code_prologue;  		if (ip < (u8 *)PAGE_OFFSET || probe_kernel_address(ip, c)) { diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c index 37a458b521a..d840e69a853 100644 --- a/arch/x86/kernel/reboot.c +++ b/arch/x86/kernel/reboot.c @@ -39,6 +39,14 @@ static int reboot_mode;  enum reboot_type reboot_type = BOOT_ACPI;  int reboot_force; +/* This variable is used privately to keep track of whether or not + * reboot_type is still set to its default value (i.e., reboot= hasn't + * been set on the command line).  This is needed so that we can + * suppress DMI scanning for reboot quirks.  Without it, it's + * impossible to override a faulty reboot quirk without recompiling. + */ +static int reboot_default = 1; +  #if defined(CONFIG_X86_32) && defined(CONFIG_SMP)  static int reboot_cpu = -1;  #endif @@ -67,6 +75,12 @@ bool port_cf9_safe = false;  static int __init reboot_setup(char *str)  {  	for (;;) { +		/* Having anything passed on the command line via +		 * reboot= will cause us to disable DMI checking +		 * below. +		 */ +		reboot_default = 0; +  		switch (*str) {  		case 'w':  			reboot_mode = 0x1234; @@ -295,14 +309,6 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = {  			DMI_MATCH(DMI_BOARD_NAME, "P4S800"),  		},  	}, -	{	/* Handle problems with rebooting on VersaLogic Menlow boards */ -		.callback = set_bios_reboot, -		.ident = "VersaLogic Menlow based board", -		.matches = { -			DMI_MATCH(DMI_BOARD_VENDOR, "VersaLogic Corporation"), -			DMI_MATCH(DMI_BOARD_NAME, "VersaLogic Menlow board"), -		}, -	},  	{ /* Handle reboot issue on Acer Aspire one */  		.callback = set_kbd_reboot,  		.ident = "Acer Aspire One A110", @@ -316,7 +322,12 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = {  static int __init reboot_init(void)  { -	dmi_check_system(reboot_dmi_table); +	/* Only do the DMI check if reboot_type hasn't been overridden +	 * on the command line +	 */ +	if (reboot_default) { +		dmi_check_system(reboot_dmi_table); +	}  	return 0;  }  core_initcall(reboot_init); @@ -465,7 +476,12 @@ static struct dmi_system_id __initdata pci_reboot_dmi_table[] = {  static int __init pci_reboot_init(void)  { -	dmi_check_system(pci_reboot_dmi_table); +	/* Only do the DMI check if reboot_type hasn't been overridden +	 * on the command line +	 */ +	if (reboot_default) { +		dmi_check_system(pci_reboot_dmi_table); +	}  	return 0;  }  core_initcall(pci_reboot_init); diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index 482ec3af206..8ba27dbc107 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c @@ -599,10 +599,10 @@ void __math_state_restore(void)   * Careful.. There are problems with IBM-designed IRQ13 behaviour.   * Don't touch unless you *really* know how it works.   * - * Must be called with kernel preemption disabled (in this case, - * local interrupts are disabled at the call-site in entry.S). + * Must be called with kernel preemption disabled (eg with local + * local interrupts as in the case of do_device_not_available).   */ -asmlinkage void math_state_restore(void) +void math_state_restore(void)  {  	struct thread_info *thread = current_thread_info();  	struct task_struct *tsk = thread->task; @@ -631,6 +631,7 @@ EXPORT_SYMBOL_GPL(math_state_restore);  dotraplinkage void __kprobes  do_device_not_available(struct pt_regs *regs, long error_code)  { +	WARN_ON_ONCE(!user_mode_vm(regs));  #ifdef CONFIG_MATH_EMULATION  	if (read_cr0() & X86_CR0_EM) {  		struct math_emu_info info = { }; diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index 05a562b8502..0982507b962 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -1891,6 +1891,51 @@ setup_syscalls_segments(struct x86_emulate_ctxt *ctxt,  	ss->p = 1;  } +static bool em_syscall_is_enabled(struct x86_emulate_ctxt *ctxt) +{ +	struct x86_emulate_ops *ops = ctxt->ops; +	u32 eax, ebx, ecx, edx; + +	/* +	 * syscall should always be enabled in longmode - so only become +	 * vendor specific (cpuid) if other modes are active... +	 */ +	if (ctxt->mode == X86EMUL_MODE_PROT64) +		return true; + +	eax = 0x00000000; +	ecx = 0x00000000; +	if (ops->get_cpuid(ctxt, &eax, &ebx, &ecx, &edx)) { +		/* +		 * Intel ("GenuineIntel") +		 * remark: Intel CPUs only support "syscall" in 64bit +		 * longmode. Also an 64bit guest with a +		 * 32bit compat-app running will #UD !! While this +		 * behaviour can be fixed (by emulating) into AMD +		 * response - CPUs of AMD can't behave like Intel. +		 */ +		if (ebx == X86EMUL_CPUID_VENDOR_GenuineIntel_ebx && +		    ecx == X86EMUL_CPUID_VENDOR_GenuineIntel_ecx && +		    edx == X86EMUL_CPUID_VENDOR_GenuineIntel_edx) +			return false; + +		/* AMD ("AuthenticAMD") */ +		if (ebx == X86EMUL_CPUID_VENDOR_AuthenticAMD_ebx && +		    ecx == X86EMUL_CPUID_VENDOR_AuthenticAMD_ecx && +		    edx == X86EMUL_CPUID_VENDOR_AuthenticAMD_edx) +			return true; + +		/* AMD ("AMDisbetter!") */ +		if (ebx == X86EMUL_CPUID_VENDOR_AMDisbetterI_ebx && +		    ecx == X86EMUL_CPUID_VENDOR_AMDisbetterI_ecx && +		    edx == X86EMUL_CPUID_VENDOR_AMDisbetterI_edx) +			return true; +	} + +	/* default: (not Intel, not AMD), apply Intel's stricter rules... */ +	return false; +} +  static int em_syscall(struct x86_emulate_ctxt *ctxt)  {  	struct x86_emulate_ops *ops = ctxt->ops; @@ -1904,9 +1949,15 @@ static int em_syscall(struct x86_emulate_ctxt *ctxt)  	    ctxt->mode == X86EMUL_MODE_VM86)  		return emulate_ud(ctxt); +	if (!(em_syscall_is_enabled(ctxt))) +		return emulate_ud(ctxt); +  	ops->get_msr(ctxt, MSR_EFER, &efer);  	setup_syscalls_segments(ctxt, &cs, &ss); +	if (!(efer & EFER_SCE)) +		return emulate_ud(ctxt); +  	ops->get_msr(ctxt, MSR_STAR, &msr_data);  	msr_data >>= 32;  	cs_sel = (u16)(msr_data & 0xfffc); diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 14d6cadc4ba..9cbfc069811 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -1495,6 +1495,8 @@ static void record_steal_time(struct kvm_vcpu *vcpu)  int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data)  { +	bool pr = false; +  	switch (msr) {  	case MSR_EFER:  		return set_efer(vcpu, data); @@ -1635,6 +1637,18 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data)  		pr_unimpl(vcpu, "unimplemented perfctr wrmsr: "  			"0x%x data 0x%llx\n", msr, data);  		break; +	case MSR_P6_PERFCTR0: +	case MSR_P6_PERFCTR1: +		pr = true; +	case MSR_P6_EVNTSEL0: +	case MSR_P6_EVNTSEL1: +		if (kvm_pmu_msr(vcpu, msr)) +			return kvm_pmu_set_msr(vcpu, msr, data); + +		if (pr || data != 0) +			pr_unimpl(vcpu, "disabled perfctr wrmsr: " +				"0x%x data 0x%llx\n", msr, data); +		break;  	case MSR_K7_CLK_CTL:  		/*  		 * Ignore all writes to this no longer documented MSR. @@ -1835,6 +1849,14 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata)  	case MSR_FAM10H_MMIO_CONF_BASE:  		data = 0;  		break; +	case MSR_P6_PERFCTR0: +	case MSR_P6_PERFCTR1: +	case MSR_P6_EVNTSEL0: +	case MSR_P6_EVNTSEL1: +		if (kvm_pmu_msr(vcpu, msr)) +			return kvm_pmu_get_msr(vcpu, msr, pdata); +		data = 0; +		break;  	case MSR_IA32_UCODE_REV:  		data = 0x100000000ULL;  		break; @@ -4180,6 +4202,28 @@ static int emulator_intercept(struct x86_emulate_ctxt *ctxt,  	return kvm_x86_ops->check_intercept(emul_to_vcpu(ctxt), info, stage);  } +static bool emulator_get_cpuid(struct x86_emulate_ctxt *ctxt, +			       u32 *eax, u32 *ebx, u32 *ecx, u32 *edx) +{ +	struct kvm_cpuid_entry2 *cpuid = NULL; + +	if (eax && ecx) +		cpuid = kvm_find_cpuid_entry(emul_to_vcpu(ctxt), +					    *eax, *ecx); + +	if (cpuid) { +		*eax = cpuid->eax; +		*ecx = cpuid->ecx; +		if (ebx) +			*ebx = cpuid->ebx; +		if (edx) +			*edx = cpuid->edx; +		return true; +	} + +	return false; +} +  static struct x86_emulate_ops emulate_ops = {  	.read_std            = kvm_read_guest_virt_system,  	.write_std           = kvm_write_guest_virt_system, @@ -4211,6 +4255,7 @@ static struct x86_emulate_ops emulate_ops = {  	.get_fpu             = emulator_get_fpu,  	.put_fpu             = emulator_put_fpu,  	.intercept           = emulator_intercept, +	.get_cpuid           = emulator_get_cpuid,  };  static void cache_all_regs(struct kvm_vcpu *vcpu) diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index 9d74824a708..f0b4caf85c1 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c @@ -673,7 +673,7 @@ no_context(struct pt_regs *regs, unsigned long error_code,  	stackend = end_of_stack(tsk);  	if (tsk != &init_task && *stackend != STACK_END_MAGIC) -		printk(KERN_ALERT "Thread overran stack, or stack corrupted\n"); +		printk(KERN_EMERG "Thread overran stack, or stack corrupted\n");  	tsk->thread.cr2		= address;  	tsk->thread.trap_no	= 14; @@ -684,7 +684,7 @@ no_context(struct pt_regs *regs, unsigned long error_code,  		sig = 0;  	/* Executive summary in case the body of the oops scrolled away */ -	printk(KERN_EMERG "CR2: %016lx\n", address); +	printk(KERN_DEFAULT "CR2: %016lx\n", address);  	oops_end(flags, regs, sig);  } diff --git a/arch/xtensa/include/asm/string.h b/arch/xtensa/include/asm/string.h index 5fb8c27cbef..405a8c49ff2 100644 --- a/arch/xtensa/include/asm/string.h +++ b/arch/xtensa/include/asm/string.h @@ -118,7 +118,4 @@ extern void *memmove(void *__dest, __const__ void *__src, size_t __n);  /* Don't build bcopy at all ...  */  #define __HAVE_ARCH_BCOPY -#define __HAVE_ARCH_MEMSCAN -#define memscan memchr -  #endif	/* _XTENSA_STRING_H */ diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c index fa8f2630944..75642a352a8 100644 --- a/block/blk-cgroup.c +++ b/block/blk-cgroup.c @@ -1659,7 +1659,7 @@ static void blkiocg_attach(struct cgroup_subsys *ss, struct cgroup *cgrp,  		ioc = get_task_io_context(task, GFP_ATOMIC, NUMA_NO_NODE);  		if (ioc) {  			ioc_cgroup_changed(ioc); -			put_io_context(ioc, NULL); +			put_io_context(ioc);  		}  	}  } diff --git a/block/blk-core.c b/block/blk-core.c index e6c05a97ee2..3a78b00edd7 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -642,7 +642,7 @@ static inline void blk_free_request(struct request_queue *q, struct request *rq)  	if (rq->cmd_flags & REQ_ELVPRIV) {  		elv_put_request(q, rq);  		if (rq->elv.icq) -			put_io_context(rq->elv.icq->ioc, q); +			put_io_context(rq->elv.icq->ioc);  	}  	mempool_free(rq, q->rq.rq_pool); @@ -872,13 +872,15 @@ retry:  	spin_unlock_irq(q->queue_lock);  	/* create icq if missing */ -	if (unlikely(et->icq_cache && !icq)) +	if ((rw_flags & REQ_ELVPRIV) && unlikely(et->icq_cache && !icq)) {  		icq = ioc_create_icq(q, gfp_mask); +		if (!icq) +			goto fail_icq; +	} -	/* rqs are guaranteed to have icq on elv_set_request() if requested */ -	if (likely(!et->icq_cache || icq)) -		rq = blk_alloc_request(q, icq, rw_flags, gfp_mask); +	rq = blk_alloc_request(q, icq, rw_flags, gfp_mask); +fail_icq:  	if (unlikely(!rq)) {  		/*  		 * Allocation failed presumably due to memory. Undo anything @@ -1210,7 +1212,6 @@ static bool bio_attempt_back_merge(struct request_queue *q, struct request *req,  	req->ioprio = ioprio_best(req->ioprio, bio_prio(bio));  	drive_stat_acct(req, 0); -	elv_bio_merged(q, req, bio);  	return true;  } @@ -1241,7 +1242,6 @@ static bool bio_attempt_front_merge(struct request_queue *q,  	req->ioprio = ioprio_best(req->ioprio, bio_prio(bio));  	drive_stat_acct(req, 0); -	elv_bio_merged(q, req, bio);  	return true;  } @@ -1255,13 +1255,12 @@ static bool bio_attempt_front_merge(struct request_queue *q,   * on %current's plugged list.  Returns %true if merge was successful,   * otherwise %false.   * - * This function is called without @q->queue_lock; however, elevator is - * accessed iff there already are requests on the plugged list which in - * turn guarantees validity of the elevator. - * - * Note that, on successful merge, elevator operation - * elevator_bio_merged_fn() will be called without queue lock.  Elevator - * must be ready for this. + * Plugging coalesces IOs from the same issuer for the same purpose without + * going through @q->queue_lock.  As such it's more of an issuing mechanism + * than scheduling, and the request, while may have elvpriv data, is not + * added on the elevator at this point.  In addition, we don't have + * reliable access to the elevator outside queue lock.  Only check basic + * merging parameters without querying the elevator.   */  static bool attempt_plug_merge(struct request_queue *q, struct bio *bio,  			       unsigned int *request_count) @@ -1280,10 +1279,10 @@ static bool attempt_plug_merge(struct request_queue *q, struct bio *bio,  		(*request_count)++; -		if (rq->q != q) +		if (rq->q != q || !blk_rq_merge_ok(rq, bio))  			continue; -		el_ret = elv_try_merge(rq, bio); +		el_ret = blk_try_merge(rq, bio);  		if (el_ret == ELEVATOR_BACK_MERGE) {  			ret = bio_attempt_back_merge(q, rq, bio);  			if (ret) @@ -1345,12 +1344,14 @@ void blk_queue_bio(struct request_queue *q, struct bio *bio)  	el_ret = elv_merge(q, &req, bio);  	if (el_ret == ELEVATOR_BACK_MERGE) {  		if (bio_attempt_back_merge(q, req, bio)) { +			elv_bio_merged(q, req, bio);  			if (!attempt_back_merge(q, req))  				elv_merged_request(q, req, el_ret);  			goto out_unlock;  		}  	} else if (el_ret == ELEVATOR_FRONT_MERGE) {  		if (bio_attempt_front_merge(q, req, bio)) { +			elv_bio_merged(q, req, bio);  			if (!attempt_front_merge(q, req))  				elv_merged_request(q, req, el_ret);  			goto out_unlock; diff --git a/block/blk-ioc.c b/block/blk-ioc.c index 27a06e00eae..8b782a63c29 100644 --- a/block/blk-ioc.c +++ b/block/blk-ioc.c @@ -29,21 +29,6 @@ void get_io_context(struct io_context *ioc)  }  EXPORT_SYMBOL(get_io_context); -/* - * Releasing ioc may nest into another put_io_context() leading to nested - * fast path release.  As the ioc's can't be the same, this is okay but - * makes lockdep whine.  Keep track of nesting and use it as subclass. - */ -#ifdef CONFIG_LOCKDEP -#define ioc_release_depth(q)		((q) ? (q)->ioc_release_depth : 0) -#define ioc_release_depth_inc(q)	(q)->ioc_release_depth++ -#define ioc_release_depth_dec(q)	(q)->ioc_release_depth-- -#else -#define ioc_release_depth(q)		0 -#define ioc_release_depth_inc(q)	do { } while (0) -#define ioc_release_depth_dec(q)	do { } while (0) -#endif -  static void icq_free_icq_rcu(struct rcu_head *head)  {  	struct io_cq *icq = container_of(head, struct io_cq, __rcu_head); @@ -75,11 +60,8 @@ static void ioc_exit_icq(struct io_cq *icq)  	if (rcu_dereference_raw(ioc->icq_hint) == icq)  		rcu_assign_pointer(ioc->icq_hint, NULL); -	if (et->ops.elevator_exit_icq_fn) { -		ioc_release_depth_inc(q); +	if (et->ops.elevator_exit_icq_fn)  		et->ops.elevator_exit_icq_fn(icq); -		ioc_release_depth_dec(q); -	}  	/*  	 * @icq->q might have gone away by the time RCU callback runs @@ -98,8 +80,15 @@ static void ioc_release_fn(struct work_struct *work)  	struct io_context *ioc = container_of(work, struct io_context,  					      release_work);  	struct request_queue *last_q = NULL; +	unsigned long flags; -	spin_lock_irq(&ioc->lock); +	/* +	 * Exiting icq may call into put_io_context() through elevator +	 * which will trigger lockdep warning.  The ioc's are guaranteed to +	 * be different, use a different locking subclass here.  Use +	 * irqsave variant as there's no spin_lock_irq_nested(). +	 */ +	spin_lock_irqsave_nested(&ioc->lock, flags, 1);  	while (!hlist_empty(&ioc->icq_list)) {  		struct io_cq *icq = hlist_entry(ioc->icq_list.first, @@ -121,15 +110,15 @@ static void ioc_release_fn(struct work_struct *work)  			 */  			if (last_q) {  				spin_unlock(last_q->queue_lock); -				spin_unlock_irq(&ioc->lock); +				spin_unlock_irqrestore(&ioc->lock, flags);  				blk_put_queue(last_q);  			} else { -				spin_unlock_irq(&ioc->lock); +				spin_unlock_irqrestore(&ioc->lock, flags);  			}  			last_q = this_q; -			spin_lock_irq(this_q->queue_lock); -			spin_lock(&ioc->lock); +			spin_lock_irqsave(this_q->queue_lock, flags); +			spin_lock_nested(&ioc->lock, 1);  			continue;  		}  		ioc_exit_icq(icq); @@ -137,10 +126,10 @@ static void ioc_release_fn(struct work_struct *work)  	if (last_q) {  		spin_unlock(last_q->queue_lock); -		spin_unlock_irq(&ioc->lock); +		spin_unlock_irqrestore(&ioc->lock, flags);  		blk_put_queue(last_q);  	} else { -		spin_unlock_irq(&ioc->lock); +		spin_unlock_irqrestore(&ioc->lock, flags);  	}  	kmem_cache_free(iocontext_cachep, ioc); @@ -149,79 +138,29 @@ static void ioc_release_fn(struct work_struct *work)  /**   * put_io_context - put a reference of io_context   * @ioc: io_context to put - * @locked_q: request_queue the caller is holding queue_lock of (hint)   *   * Decrement reference count of @ioc and release it if the count reaches - * zero.  If the caller is holding queue_lock of a queue, it can indicate - * that with @locked_q.  This is an optimization hint and the caller is - * allowed to pass in %NULL even when it's holding a queue_lock. + * zero.   */ -void put_io_context(struct io_context *ioc, struct request_queue *locked_q) +void put_io_context(struct io_context *ioc)  { -	struct request_queue *last_q = locked_q;  	unsigned long flags;  	if (ioc == NULL)  		return;  	BUG_ON(atomic_long_read(&ioc->refcount) <= 0); -	if (locked_q) -		lockdep_assert_held(locked_q->queue_lock); - -	if (!atomic_long_dec_and_test(&ioc->refcount)) -		return;  	/* -	 * Destroy @ioc.  This is a bit messy because icq's are chained -	 * from both ioc and queue, and ioc->lock nests inside queue_lock. -	 * The inner ioc->lock should be held to walk our icq_list and then -	 * for each icq the outer matching queue_lock should be grabbed. -	 * ie. We need to do reverse-order double lock dancing. -	 * -	 * Another twist is that we are often called with one of the -	 * matching queue_locks held as indicated by @locked_q, which -	 * prevents performing double-lock dance for other queues. -	 * -	 * So, we do it in two stages.  The fast path uses the queue_lock -	 * the caller is holding and, if other queues need to be accessed, -	 * uses trylock to avoid introducing locking dependency.  This can -	 * handle most cases, especially if @ioc was performing IO on only -	 * single device. -	 * -	 * If trylock doesn't cut it, we defer to @ioc->release_work which -	 * can do all the double-locking dancing. +	 * Releasing ioc requires reverse order double locking and we may +	 * already be holding a queue_lock.  Do it asynchronously from wq.  	 */ -	spin_lock_irqsave_nested(&ioc->lock, flags, -				 ioc_release_depth(locked_q)); - -	while (!hlist_empty(&ioc->icq_list)) { -		struct io_cq *icq = hlist_entry(ioc->icq_list.first, -						struct io_cq, ioc_node); -		struct request_queue *this_q = icq->q; - -		if (this_q != last_q) { -			if (last_q && last_q != locked_q) -				spin_unlock(last_q->queue_lock); -			last_q = NULL; - -			if (!spin_trylock(this_q->queue_lock)) -				break; -			last_q = this_q; -			continue; -		} -		ioc_exit_icq(icq); +	if (atomic_long_dec_and_test(&ioc->refcount)) { +		spin_lock_irqsave(&ioc->lock, flags); +		if (!hlist_empty(&ioc->icq_list)) +			schedule_work(&ioc->release_work); +		spin_unlock_irqrestore(&ioc->lock, flags);  	} - -	if (last_q && last_q != locked_q) -		spin_unlock(last_q->queue_lock); - -	spin_unlock_irqrestore(&ioc->lock, flags); - -	/* if no icq is left, we're done; otherwise, kick release_work */ -	if (hlist_empty(&ioc->icq_list)) -		kmem_cache_free(iocontext_cachep, ioc); -	else -		schedule_work(&ioc->release_work);  }  EXPORT_SYMBOL(put_io_context); @@ -236,7 +175,7 @@ void exit_io_context(struct task_struct *task)  	task_unlock(task);  	atomic_dec(&ioc->nr_tasks); -	put_io_context(ioc, NULL); +	put_io_context(ioc);  }  /** diff --git a/block/blk-merge.c b/block/blk-merge.c index cfcc37cb222..160035f5488 100644 --- a/block/blk-merge.c +++ b/block/blk-merge.c @@ -471,3 +471,40 @@ int blk_attempt_req_merge(struct request_queue *q, struct request *rq,  {  	return attempt_merge(q, rq, next);  } + +bool blk_rq_merge_ok(struct request *rq, struct bio *bio) +{ +	if (!rq_mergeable(rq)) +		return false; + +	/* don't merge file system requests and discard requests */ +	if ((bio->bi_rw & REQ_DISCARD) != (rq->bio->bi_rw & REQ_DISCARD)) +		return false; + +	/* don't merge discard requests and secure discard requests */ +	if ((bio->bi_rw & REQ_SECURE) != (rq->bio->bi_rw & REQ_SECURE)) +		return false; + +	/* different data direction or already started, don't merge */ +	if (bio_data_dir(bio) != rq_data_dir(rq)) +		return false; + +	/* must be same device and not a special request */ +	if (rq->rq_disk != bio->bi_bdev->bd_disk || rq->special) +		return false; + +	/* only merge integrity protected bio into ditto rq */ +	if (bio_integrity(bio) != blk_integrity_rq(rq)) +		return false; + +	return true; +} + +int blk_try_merge(struct request *rq, struct bio *bio) +{ +	if (blk_rq_pos(rq) + blk_rq_sectors(rq) == bio->bi_sector) +		return ELEVATOR_BACK_MERGE; +	else if (blk_rq_pos(rq) - bio_sectors(bio) == bio->bi_sector) +		return ELEVATOR_FRONT_MERGE; +	return ELEVATOR_NO_MERGE; +} diff --git a/block/blk.h b/block/blk.h index 7efd772336d..9c12f80882b 100644 --- a/block/blk.h +++ b/block/blk.h @@ -137,6 +137,8 @@ int blk_attempt_req_merge(struct request_queue *q, struct request *rq,  				struct request *next);  void blk_recalc_rq_segments(struct request *rq);  void blk_rq_set_mixed_merge(struct request *rq); +bool blk_rq_merge_ok(struct request *rq, struct bio *bio); +int blk_try_merge(struct request *rq, struct bio *bio);  void blk_queue_congestion_threshold(struct request_queue *q); diff --git a/block/bsg.c b/block/bsg.c index 4cf703fd98b..ff64ae3bace 100644 --- a/block/bsg.c +++ b/block/bsg.c @@ -983,7 +983,8 @@ void bsg_unregister_queue(struct request_queue *q)  	mutex_lock(&bsg_mutex);  	idr_remove(&bsg_minor_idr, bcd->minor); -	sysfs_remove_link(&q->kobj, "bsg"); +	if (q->kobj.sd) +		sysfs_remove_link(&q->kobj, "bsg");  	device_unregister(bcd->class_dev);  	bcd->class_dev = NULL;  	kref_put(&bcd->ref, bsg_kref_release_function); diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index ee55019066a..d0ba5053366 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -1699,18 +1699,11 @@ static int cfq_allow_merge(struct request_queue *q, struct request *rq,  	/*  	 * Lookup the cfqq that this bio will be queued with and allow -	 * merge only if rq is queued there.  This function can be called -	 * from plug merge without queue_lock.  In such cases, ioc of @rq -	 * and %current are guaranteed to be equal.  Avoid lookup which -	 * requires queue_lock by using @rq's cic. +	 * merge only if rq is queued there.  	 */ -	if (current->io_context == RQ_CIC(rq)->icq.ioc) { -		cic = RQ_CIC(rq); -	} else { -		cic = cfq_cic_lookup(cfqd, current->io_context); -		if (!cic) -			return false; -	} +	cic = cfq_cic_lookup(cfqd, current->io_context); +	if (!cic) +		return false;  	cfqq = cic_to_cfqq(cic, cfq_bio_sync(bio));  	return cfqq == RQ_CFQQ(rq); @@ -1794,7 +1787,7 @@ __cfq_slice_expired(struct cfq_data *cfqd, struct cfq_queue *cfqq,  		cfqd->active_queue = NULL;  	if (cfqd->active_cic) { -		put_io_context(cfqd->active_cic->icq.ioc, cfqd->queue); +		put_io_context(cfqd->active_cic->icq.ioc);  		cfqd->active_cic = NULL;  	}  } @@ -3117,17 +3110,18 @@ cfq_should_preempt(struct cfq_data *cfqd, struct cfq_queue *new_cfqq,   */  static void cfq_preempt_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq)  { +	enum wl_type_t old_type = cfqq_type(cfqd->active_queue); +  	cfq_log_cfqq(cfqd, cfqq, "preempt"); +	cfq_slice_expired(cfqd, 1);  	/*  	 * workload type is changed, don't save slice, otherwise preempt  	 * doesn't happen  	 */ -	if (cfqq_type(cfqd->active_queue) != cfqq_type(cfqq)) +	if (old_type != cfqq_type(cfqq))  		cfqq->cfqg->saved_workload_slice = 0; -	cfq_slice_expired(cfqd, 1); -  	/*  	 * Put the new queue at the front of the of the current list,  	 * so we know that it will be selected next. diff --git a/block/elevator.c b/block/elevator.c index 91e18f8af9b..f016855a46b 100644 --- a/block/elevator.c +++ b/block/elevator.c @@ -70,39 +70,9 @@ static int elv_iosched_allow_merge(struct request *rq, struct bio *bio)  /*   * can we safely merge with this request?   */ -int elv_rq_merge_ok(struct request *rq, struct bio *bio) +bool elv_rq_merge_ok(struct request *rq, struct bio *bio)  { -	if (!rq_mergeable(rq)) -		return 0; - -	/* -	 * Don't merge file system requests and discard requests -	 */ -	if ((bio->bi_rw & REQ_DISCARD) != (rq->bio->bi_rw & REQ_DISCARD)) -		return 0; - -	/* -	 * Don't merge discard requests and secure discard requests -	 */ -	if ((bio->bi_rw & REQ_SECURE) != (rq->bio->bi_rw & REQ_SECURE)) -		return 0; - -	/* -	 * different data direction or already started, don't merge -	 */ -	if (bio_data_dir(bio) != rq_data_dir(rq)) -		return 0; - -	/* -	 * must be same device and not a special request -	 */ -	if (rq->rq_disk != bio->bi_bdev->bd_disk || rq->special) -		return 0; - -	/* -	 * only merge integrity protected bio into ditto rq -	 */ -	if (bio_integrity(bio) != blk_integrity_rq(rq)) +	if (!blk_rq_merge_ok(rq, bio))  		return 0;  	if (!elv_iosched_allow_merge(rq, bio)) @@ -112,23 +82,6 @@ int elv_rq_merge_ok(struct request *rq, struct bio *bio)  }  EXPORT_SYMBOL(elv_rq_merge_ok); -int elv_try_merge(struct request *__rq, struct bio *bio) -{ -	int ret = ELEVATOR_NO_MERGE; - -	/* -	 * we can merge and sequence is ok, check if it's possible -	 */ -	if (elv_rq_merge_ok(__rq, bio)) { -		if (blk_rq_pos(__rq) + blk_rq_sectors(__rq) == bio->bi_sector) -			ret = ELEVATOR_BACK_MERGE; -		else if (blk_rq_pos(__rq) - bio_sectors(bio) == bio->bi_sector) -			ret = ELEVATOR_FRONT_MERGE; -	} - -	return ret; -} -  static struct elevator_type *elevator_find(const char *name)  {  	struct elevator_type *e; @@ -478,8 +431,8 @@ int elv_merge(struct request_queue *q, struct request **req, struct bio *bio)  	/*  	 * First try one-hit cache.  	 */ -	if (q->last_merge) { -		ret = elv_try_merge(q->last_merge, bio); +	if (q->last_merge && elv_rq_merge_ok(q->last_merge, bio)) { +		ret = blk_try_merge(q->last_merge, bio);  		if (ret != ELEVATOR_NO_MERGE) {  			*req = q->last_merge;  			return ret; diff --git a/crypto/sha512_generic.c b/crypto/sha512_generic.c index 88f160b77b1..f04af931a68 100644 --- a/crypto/sha512_generic.c +++ b/crypto/sha512_generic.c @@ -78,7 +78,7 @@ static inline void LOAD_OP(int I, u64 *W, const u8 *input)  static inline void BLEND_OP(int I, u64 *W)  { -	W[I % 16] += s1(W[(I-2) % 16]) + W[(I-7) % 16] + s0(W[(I-15) % 16]); +	W[I & 15] += s1(W[(I-2) & 15]) + W[(I-7) & 15] + s0(W[(I-15) & 15]);  }  static void @@ -89,46 +89,42 @@ sha512_transform(u64 *state, const u8 *input)  	int i;  	u64 W[16]; -	/* load the input */ -        for (i = 0; i < 16; i++) -                LOAD_OP(i, W, input); -  	/* load the state into our registers */  	a=state[0];   b=state[1];   c=state[2];   d=state[3];  	e=state[4];   f=state[5];   g=state[6];   h=state[7]; -#define SHA512_0_15(i, a, b, c, d, e, f, g, h)			\ -	t1 = h + e1(e) + Ch(e, f, g) + sha512_K[i] + W[i];	\ -	t2 = e0(a) + Maj(a, b, c);				\ -	d += t1;						\ -	h = t1 + t2 +	/* now iterate */ +	for (i=0; i<80; i+=8) { +		if (!(i & 8)) { +			int j; -#define SHA512_16_79(i, a, b, c, d, e, f, g, h)			\ -	BLEND_OP(i, W);						\ -	t1 = h + e1(e) + Ch(e, f, g) + sha512_K[i] + W[(i)%16];	\ -	t2 = e0(a) + Maj(a, b, c);				\ -	d += t1;						\ -	h = t1 + t2 +			if (i < 16) { +				/* load the input */ +				for (j = 0; j < 16; j++) +					LOAD_OP(i + j, W, input); +			} else { +				for (j = 0; j < 16; j++) { +					BLEND_OP(i + j, W); +				} +			} +		} -	for (i = 0; i < 16; i += 8) { -		SHA512_0_15(i, a, b, c, d, e, f, g, h); -		SHA512_0_15(i + 1, h, a, b, c, d, e, f, g); -		SHA512_0_15(i + 2, g, h, a, b, c, d, e, f); -		SHA512_0_15(i + 3, f, g, h, a, b, c, d, e); -		SHA512_0_15(i + 4, e, f, g, h, a, b, c, d); -		SHA512_0_15(i + 5, d, e, f, g, h, a, b, c); -		SHA512_0_15(i + 6, c, d, e, f, g, h, a, b); -		SHA512_0_15(i + 7, b, c, d, e, f, g, h, a); -	} -	for (i = 16; i < 80; i += 8) { -		SHA512_16_79(i, a, b, c, d, e, f, g, h); -		SHA512_16_79(i + 1, h, a, b, c, d, e, f, g); -		SHA512_16_79(i + 2, g, h, a, b, c, d, e, f); -		SHA512_16_79(i + 3, f, g, h, a, b, c, d, e); -		SHA512_16_79(i + 4, e, f, g, h, a, b, c, d); -		SHA512_16_79(i + 5, d, e, f, g, h, a, b, c); -		SHA512_16_79(i + 6, c, d, e, f, g, h, a, b); -		SHA512_16_79(i + 7, b, c, d, e, f, g, h, a); +		t1 = h + e1(e) + Ch(e,f,g) + sha512_K[i  ] + W[(i & 15)]; +		t2 = e0(a) + Maj(a,b,c);    d+=t1;    h=t1+t2; +		t1 = g + e1(d) + Ch(d,e,f) + sha512_K[i+1] + W[(i & 15) + 1]; +		t2 = e0(h) + Maj(h,a,b);    c+=t1;    g=t1+t2; +		t1 = f + e1(c) + Ch(c,d,e) + sha512_K[i+2] + W[(i & 15) + 2]; +		t2 = e0(g) + Maj(g,h,a);    b+=t1;    f=t1+t2; +		t1 = e + e1(b) + Ch(b,c,d) + sha512_K[i+3] + W[(i & 15) + 3]; +		t2 = e0(f) + Maj(f,g,h);    a+=t1;    e=t1+t2; +		t1 = d + e1(a) + Ch(a,b,c) + sha512_K[i+4] + W[(i & 15) + 4]; +		t2 = e0(e) + Maj(e,f,g);    h+=t1;    d=t1+t2; +		t1 = c + e1(h) + Ch(h,a,b) + sha512_K[i+5] + W[(i & 15) + 5]; +		t2 = e0(d) + Maj(d,e,f);    g+=t1;    c=t1+t2; +		t1 = b + e1(g) + Ch(g,h,a) + sha512_K[i+6] + W[(i & 15) + 6]; +		t2 = e0(c) + Maj(c,d,e);    f+=t1;    b=t1+t2; +		t1 = a + e1(f) + Ch(f,g,h) + sha512_K[i+7] + W[(i & 15) + 7]; +		t2 = e0(b) + Maj(b,c,d);    e+=t1;    a=t1+t2;  	}  	state[0] += a; state[1] += b; state[2] += c; state[3] += d; diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c index 2b805d7ef31..8ae05ce1850 100644 --- a/drivers/acpi/processor_driver.c +++ b/drivers/acpi/processor_driver.c @@ -586,13 +586,6 @@ static int __cpuinit acpi_processor_add(struct acpi_device *device)  	if (pr->flags.need_hotplug_init)  		return 0; -	/* -	 * Do not start hotplugged CPUs now, but when they -	 * are onlined the first time -	 */ -	if (pr->flags.need_hotplug_init) -		return 0; -  	result = acpi_processor_start(pr);  	if (result)  		goto err_remove_sysfs; diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c index db87e78d745..4dabf5077c4 100644 --- a/drivers/base/cpu.c +++ b/drivers/base/cpu.c @@ -208,6 +208,25 @@ static ssize_t print_cpus_offline(struct device *dev,  }  static DEVICE_ATTR(offline, 0444, print_cpus_offline, NULL); +static void cpu_device_release(struct device *dev) +{ +	/* +	 * This is an empty function to prevent the driver core from spitting a +	 * warning at us.  Yes, I know this is directly opposite of what the +	 * documentation for the driver core and kobjects say, and the author +	 * of this code has already been publically ridiculed for doing +	 * something as foolish as this.  However, at this point in time, it is +	 * the only way to handle the issue of statically allocated cpu +	 * devices.  The different architectures will have their cpu device +	 * code reworked to properly handle this in the near future, so this +	 * function will then be changed to correctly free up the memory held +	 * by the cpu device. +	 * +	 * Never copy this way of doing things, or you too will be made fun of +	 * on the linux-kerenl list, you have been warned. +	 */ +} +  /*   * register_cpu - Setup a sysfs device for a CPU.   * @cpu - cpu->hotpluggable field set to 1 will generate a control file in @@ -221,8 +240,10 @@ int __cpuinit register_cpu(struct cpu *cpu, int num)  	int error;  	cpu->node_id = cpu_to_node(num); +	memset(&cpu->dev, 0x00, sizeof(struct device));  	cpu->dev.id = num;  	cpu->dev.bus = &cpu_subsys; +	cpu->dev.release = cpu_device_release;  	error = device_register(&cpu->dev);  	if (!error && cpu->hotpluggable)  		register_cpu_control(cpu); diff --git a/drivers/base/memory.c b/drivers/base/memory.c index ed5de58c340..9e60dbe9fd9 100644 --- a/drivers/base/memory.c +++ b/drivers/base/memory.c @@ -572,19 +572,36 @@ static int init_memory_block(struct memory_block **memory,  }  static int add_memory_section(int nid, struct mem_section *section, +			struct memory_block **mem_p,  			unsigned long state, enum mem_add_context context)  { -	struct memory_block *mem; +	struct memory_block *mem = NULL; +	int scn_nr = __section_nr(section);  	int ret = 0;  	mutex_lock(&mem_sysfs_mutex); -	mem = find_memory_block(section); +	if (context == BOOT) { +		/* same memory block ? */ +		if (mem_p && *mem_p) +			if (scn_nr >= (*mem_p)->start_section_nr && +			    scn_nr <= (*mem_p)->end_section_nr) { +				mem = *mem_p; +				kobject_get(&mem->dev.kobj); +			} +	} else +		mem = find_memory_block(section); +  	if (mem) {  		mem->section_count++;  		kobject_put(&mem->dev.kobj); -	} else +	} else {  		ret = init_memory_block(&mem, section, state); +		/* store memory_block pointer for next loop */ +		if (!ret && context == BOOT) +			if (mem_p) +				*mem_p = mem; +	}  	if (!ret) {  		if (context == HOTPLUG && @@ -627,7 +644,7 @@ int remove_memory_block(unsigned long node_id, struct mem_section *section,   */  int register_new_memory(int nid, struct mem_section *section)  { -	return add_memory_section(nid, section, MEM_OFFLINE, HOTPLUG); +	return add_memory_section(nid, section, NULL, MEM_OFFLINE, HOTPLUG);  }  int unregister_memory_section(struct mem_section *section) @@ -647,6 +664,7 @@ int __init memory_dev_init(void)  	int ret;  	int err;  	unsigned long block_sz; +	struct memory_block *mem = NULL;  	ret = subsys_system_register(&memory_subsys, NULL);  	if (ret) @@ -662,7 +680,10 @@ int __init memory_dev_init(void)  	for (i = 0; i < NR_MEM_SECTIONS; i++) {  		if (!present_section_nr(i))  			continue; -		err = add_memory_section(0, __nr_to_section(i), MEM_ONLINE, +		/* don't need to reuse memory_block if only one per block */ +		err = add_memory_section(0, __nr_to_section(i), +				 (sections_per_block == 1) ? NULL : &mem, +					 MEM_ONLINE,  					 BOOT);  		if (!ret)  			ret = err; diff --git a/drivers/base/node.c b/drivers/base/node.c index 44f427a6611..90aa2a11a93 100644 --- a/drivers/base/node.c +++ b/drivers/base/node.c @@ -456,7 +456,15 @@ static int link_mem_sections(int nid)  		if (!present_section_nr(section_nr))  			continue;  		mem_sect = __nr_to_section(section_nr); + +		/* same memblock ? */ +		if (mem_blk) +			if ((section_nr >= mem_blk->start_section_nr) && +			    (section_nr <= mem_blk->end_section_nr)) +				continue; +  		mem_blk = find_memory_block_hinted(mem_sect, mem_blk); +  		ret = register_mem_sect_under_node(mem_blk, nid);  		if (!err)  			err = ret; diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c index febbc0a1222..ec31f7dd554 100644 --- a/drivers/bcma/main.c +++ b/drivers/bcma/main.c @@ -169,10 +169,8 @@ int bcma_bus_register(struct bcma_bus *bus)  	err = bcma_sprom_get(bus);  	if (err == -ENOENT) {  		pr_err("No SPROM available\n"); -	} else if (err) { +	} else if (err)  		pr_err("Failed to get SPROM: %d\n", err); -		return -ENOENT; -	}  	/* Register found cores */  	bcma_register_cores(bus); diff --git a/drivers/bcma/scan.c b/drivers/bcma/scan.c index cad99485768..3a2f672db9a 100644 --- a/drivers/bcma/scan.c +++ b/drivers/bcma/scan.c @@ -399,15 +399,18 @@ int bcma_bus_scan(struct bcma_bus *bus)  		core->bus = bus;  		err = bcma_get_next_core(bus, &eromptr, NULL, core_num, core); -		if (err == -ENODEV) { -			core_num++; -			continue; -		} else if (err == -ENXIO) -			continue; -		else if (err == -ESPIPE) -			break; -		else if (err < 0) +		if (err < 0) { +			kfree(core); +			if (err == -ENODEV) { +				core_num++; +				continue; +			} else if (err == -ENXIO) { +				continue; +			} else if (err == -ESPIPE) { +				break; +			}  			return err; +		}  		core->core_index = core_num++;  		bus->nr_cores++; diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 510fb10ec45..9baf11e8636 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -4368,8 +4368,14 @@ out_unreg_blkdev:  out_put_disk:  	while (dr--) {  		del_timer_sync(&motor_off_timer[dr]); -		if (disks[dr]->queue) +		if (disks[dr]->queue) {  			blk_cleanup_queue(disks[dr]->queue); +			/* +			 * put_disk() is not paired with add_disk() and +			 * will put queue reference one extra time. fix it. +			 */ +			disks[dr]->queue = NULL; +		}  		put_disk(disks[dr]);  	}  	return err; @@ -4579,6 +4585,15 @@ static void __exit floppy_module_exit(void)  			platform_device_unregister(&floppy_device[drive]);  		}  		blk_cleanup_queue(disks[drive]->queue); + +		/* +		 * These disks have not called add_disk().  Don't put down +		 * queue reference in put_disk(). +		 */ +		if (!(allowed_drive_mask & (1 << drive)) || +		    fdc_state[FDC(drive)].version == FDC_NONE) +			disks[drive]->queue = NULL; +  		put_disk(disks[drive]);  	} diff --git a/drivers/block/loop.c b/drivers/block/loop.c index f00257782fc..cd504353b27 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -356,14 +356,14 @@ lo_direct_splice_actor(struct pipe_inode_info *pipe, struct splice_desc *sd)  	return __splice_from_pipe(pipe, sd, lo_splice_actor);  } -static int +static ssize_t  do_lo_receive(struct loop_device *lo,  	      struct bio_vec *bvec, int bsize, loff_t pos)  {  	struct lo_read_data cookie;  	struct splice_desc sd;  	struct file *file; -	long retval; +	ssize_t retval;  	cookie.lo = lo;  	cookie.page = bvec->bv_page; @@ -379,26 +379,28 @@ do_lo_receive(struct loop_device *lo,  	file = lo->lo_backing_file;  	retval = splice_direct_to_actor(file, &sd, lo_direct_splice_actor); -	if (retval < 0) -		return retval; -	if (retval != bvec->bv_len) -		return -EIO; -	return 0; +	return retval;  }  static int  lo_receive(struct loop_device *lo, struct bio *bio, int bsize, loff_t pos)  {  	struct bio_vec *bvec; -	int i, ret = 0; +	ssize_t s; +	int i;  	bio_for_each_segment(bvec, bio, i) { -		ret = do_lo_receive(lo, bvec, bsize, pos); -		if (ret < 0) +		s = do_lo_receive(lo, bvec, bsize, pos); +		if (s < 0) +			return s; + +		if (s != bvec->bv_len) { +			zero_fill_bio(bio);  			break; +		}  		pos += bvec->bv_len;  	} -	return ret; +	return 0;  }  static int do_bio_filebacked(struct loop_device *lo, struct bio *bio) diff --git a/drivers/block/mtip32xx/mtip32xx.c b/drivers/block/mtip32xx/mtip32xx.c index b74eab70c3d..8eb81c96608 100644 --- a/drivers/block/mtip32xx/mtip32xx.c +++ b/drivers/block/mtip32xx/mtip32xx.c @@ -2068,8 +2068,6 @@ static int mtip_hw_ioctl(struct driver_data *dd, unsigned int cmd,   *	     when the read completes.   * @data     Callback data passed to the callback function   *	     when the read completes. - * @barrier  If non-zero, this command must be completed before - *	     issuing any other commands.   * @dir      Direction (read or write)   *   * return value @@ -2077,7 +2075,7 @@ static int mtip_hw_ioctl(struct driver_data *dd, unsigned int cmd,   */  static void mtip_hw_submit_io(struct driver_data *dd, sector_t start,  			      int nsect, int nents, int tag, void *callback, -			      void *data, int barrier, int dir) +			      void *data, int dir)  {  	struct host_to_dev_fis	*fis;  	struct mtip_port *port = dd->port; @@ -2108,8 +2106,6 @@ static void mtip_hw_submit_io(struct driver_data *dd, sector_t start,  	*((unsigned int *) &fis->lba_low) = (start & 0xFFFFFF);  	*((unsigned int *) &fis->lba_low_ex) = ((start >> 24) & 0xFFFFFF);  	fis->device	 = 1 << 6; -	if (barrier) -		fis->device |= FUA_BIT;  	fis->features    = nsect & 0xFF;  	fis->features_ex = (nsect >> 8) & 0xFF;  	fis->sect_count  = ((tag << 3) | (tag >> 5)); @@ -3087,7 +3083,6 @@ static void mtip_make_request(struct request_queue *queue, struct bio *bio)  				tag,  				bio_endio,  				bio, -				bio->bi_rw & REQ_FUA,  				bio_data_dir(bio));  	} else  		bio_io_error(bio); @@ -3187,6 +3182,10 @@ skip_create_disk:  	blk_queue_max_segments(dd->queue, MTIP_MAX_SG);  	blk_queue_physical_block_size(dd->queue, 4096);  	blk_queue_io_min(dd->queue, 4096); +	/* +	 * write back cache is not supported in the device. FUA depends on +	 * write back cache support, hence setting flush support to zero. +	 */  	blk_queue_flush(dd->queue, 0);  	/* Set the capacity of the device in 512 byte sectors. */ diff --git a/drivers/block/mtip32xx/mtip32xx.h b/drivers/block/mtip32xx/mtip32xx.h index 723d7c4946d..e0554a8f223 100644 --- a/drivers/block/mtip32xx/mtip32xx.h +++ b/drivers/block/mtip32xx/mtip32xx.h @@ -104,9 +104,6 @@  /* BAR number used to access the HBA registers. */  #define MTIP_ABAR		5 -/* Forced Unit Access Bit */ -#define FUA_BIT			0x80 -  #ifdef DEBUG   #define dbg_printk(format, arg...)	\  	printk(pr_fmt(format), ##arg); @@ -415,8 +412,6 @@ struct driver_data {  	atomic_t resumeflag; /* Atomic variable to track suspend/resume */ -	atomic_t eh_active; /* Flag for error handling tracking */ -  	struct task_struct *mtip_svc_handler; /* task_struct of svc thd */  }; diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index 3fd31dec8c9..a6278e7e61a 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -380,6 +380,7 @@ static int rbd_get_client(struct rbd_device *rbd_dev, const char *mon_addr,  	rbdc = __rbd_client_find(opt);  	if (rbdc) {  		ceph_destroy_options(opt); +		kfree(rbd_opts);  		/* using an existing client */  		kref_get(&rbdc->kref); @@ -406,15 +407,15 @@ done_err:  /*   * Destroy ceph client + * + * Caller must hold node_lock.   */  static void rbd_client_release(struct kref *kref)  {  	struct rbd_client *rbdc = container_of(kref, struct rbd_client, kref);  	dout("rbd_release_client %p\n", rbdc); -	spin_lock(&node_lock);  	list_del(&rbdc->node); -	spin_unlock(&node_lock);  	ceph_destroy_client(rbdc->client);  	kfree(rbdc->rbd_opts); @@ -427,7 +428,9 @@ static void rbd_client_release(struct kref *kref)   */  static void rbd_put_client(struct rbd_device *rbd_dev)  { +	spin_lock(&node_lock);  	kref_put(&rbd_dev->rbd_client->kref, rbd_client_release); +	spin_unlock(&node_lock);  	rbd_dev->rbd_client = NULL;  	rbd_dev->client = NULL;  } diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c index 55eaf474d32..d620b449574 100644 --- a/drivers/cdrom/cdrom.c +++ b/drivers/cdrom/cdrom.c @@ -286,8 +286,6 @@  /* used to tell the module to turn on full debugging messages */  static bool debug; -/* used to keep tray locked at all times */ -static int keeplocked;  /* default compatibility mode */  static bool autoclose=1;  static bool autoeject; @@ -1204,7 +1202,7 @@ void cdrom_release(struct cdrom_device_info *cdi, fmode_t mode)  		cdinfo(CD_CLOSE, "Use count for \"/dev/%s\" now zero\n", cdi->name);  		cdrom_dvd_rw_close_write(cdi); -		if ((cdo->capability & CDC_LOCK) && !keeplocked) { +		if ((cdo->capability & CDC_LOCK) && !cdi->keeplocked) {  			cdinfo(CD_CLOSE, "Unlocking door!\n");  			cdo->lock_door(cdi, 0);  		} @@ -1371,7 +1369,7 @@ static int cdrom_select_disc(struct cdrom_device_info *cdi, int slot)  	curslot = info->hdr.curslot;  	kfree(info); -	if (cdi->use_count > 1 || keeplocked) { +	if (cdi->use_count > 1 || cdi->keeplocked) {  		if (slot == CDSL_CURRENT) {  	    		return curslot;  		} else { @@ -2119,11 +2117,6 @@ static int cdrom_read_cdda_old(struct cdrom_device_info *cdi, __u8 __user *ubuf,  	if (!nr)  		return -ENOMEM; -	if (!access_ok(VERIFY_WRITE, ubuf, nframes * CD_FRAMESIZE_RAW)) { -		ret = -EFAULT; -		goto out; -	} -  	cgc.data_direction = CGC_DATA_READ;  	while (nframes > 0) {  		if (nr > nframes) @@ -2132,7 +2125,7 @@ static int cdrom_read_cdda_old(struct cdrom_device_info *cdi, __u8 __user *ubuf,  		ret = cdrom_read_block(cdi, &cgc, lba, nr, 1, CD_FRAMESIZE_RAW);  		if (ret)  			break; -		if (__copy_to_user(ubuf, cgc.buffer, CD_FRAMESIZE_RAW * nr)) { +		if (copy_to_user(ubuf, cgc.buffer, CD_FRAMESIZE_RAW * nr)) {  			ret = -EFAULT;  			break;  		} @@ -2140,7 +2133,6 @@ static int cdrom_read_cdda_old(struct cdrom_device_info *cdi, __u8 __user *ubuf,  		nframes -= nr;  		lba += nr;  	} -out:  	kfree(cgc.buffer);  	return ret;  } @@ -2295,7 +2287,7 @@ static int cdrom_ioctl_eject(struct cdrom_device_info *cdi)  	if (!CDROM_CAN(CDC_OPEN_TRAY))  		return -ENOSYS; -	if (cdi->use_count != 1 || keeplocked) +	if (cdi->use_count != 1 || cdi->keeplocked)  		return -EBUSY;  	if (CDROM_CAN(CDC_LOCK)) {  		int ret = cdi->ops->lock_door(cdi, 0); @@ -2322,7 +2314,7 @@ static int cdrom_ioctl_eject_sw(struct cdrom_device_info *cdi,  	if (!CDROM_CAN(CDC_OPEN_TRAY))  		return -ENOSYS; -	if (keeplocked) +	if (cdi->keeplocked)  		return -EBUSY;  	cdi->options &= ~(CDO_AUTO_CLOSE | CDO_AUTO_EJECT); @@ -2453,7 +2445,7 @@ static int cdrom_ioctl_lock_door(struct cdrom_device_info *cdi,  	if (!CDROM_CAN(CDC_LOCK))  		return -EDRIVE_CANT_DO_THIS; -	keeplocked = arg ? 1 : 0; +	cdi->keeplocked = arg ? 1 : 0;  	/*  	 * Don't unlock the door on multiple opens by default, but allow diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index 97f87b29b9f..f4aed5fc2cb 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c @@ -1343,7 +1343,7 @@ static int __init at_dma_probe(struct platform_device *pdev)  		tasklet_init(&atchan->tasklet, atc_tasklet,  				(unsigned long)atchan); -		atc_enable_irq(atchan); +		atc_enable_chan_irq(atdma, i);  	}  	/* set base routines */ @@ -1410,7 +1410,7 @@ static int __exit at_dma_remove(struct platform_device *pdev)  		struct at_dma_chan	*atchan = to_at_dma_chan(chan);  		/* Disable interrupts */ -		atc_disable_irq(atchan); +		atc_disable_chan_irq(atdma, chan->chan_id);  		tasklet_disable(&atchan->tasklet);  		tasklet_kill(&atchan->tasklet); diff --git a/drivers/dma/at_hdmac_regs.h b/drivers/dma/at_hdmac_regs.h index dcaedfc181c..a8d3277d60b 100644 --- a/drivers/dma/at_hdmac_regs.h +++ b/drivers/dma/at_hdmac_regs.h @@ -327,28 +327,27 @@ static void atc_dump_lli(struct at_dma_chan *atchan, struct at_lli *lli)  } -static void atc_setup_irq(struct at_dma_chan *atchan, int on) +static void atc_setup_irq(struct at_dma *atdma, int chan_id, int on)  { -	struct at_dma	*atdma = to_at_dma(atchan->chan_common.device); -	u32		ebci; +	u32 ebci;  	/* enable interrupts on buffer transfer completion & error */ -	ebci =    AT_DMA_BTC(atchan->chan_common.chan_id) -		| AT_DMA_ERR(atchan->chan_common.chan_id); +	ebci =    AT_DMA_BTC(chan_id) +		| AT_DMA_ERR(chan_id);  	if (on)  		dma_writel(atdma, EBCIER, ebci);  	else  		dma_writel(atdma, EBCIDR, ebci);  } -static inline void atc_enable_irq(struct at_dma_chan *atchan) +static void atc_enable_chan_irq(struct at_dma *atdma, int chan_id)  { -	atc_setup_irq(atchan, 1); +	atc_setup_irq(atdma, chan_id, 1);  } -static inline void atc_disable_irq(struct at_dma_chan *atchan) +static void atc_disable_chan_irq(struct at_dma *atdma, int chan_id)  { -	atc_setup_irq(atchan, 0); +	atc_setup_irq(atdma, chan_id, 0);  } diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c index 2b8661b54ea..24225f0fdcd 100644 --- a/drivers/dma/dmatest.c +++ b/drivers/dma/dmatest.c @@ -599,7 +599,7 @@ static int dmatest_add_channel(struct dma_chan *chan)  	}  	if (dma_has_cap(DMA_PQ, dma_dev->cap_mask)) {  		cnt = dmatest_add_threads(dtc, DMA_PQ); -		thread_count += cnt > 0 ?: 0; +		thread_count += cnt > 0 ? cnt : 0;  	}  	pr_info("dmatest: Started %u threads using %s\n", diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c index a8af379680c..8bc5acf36ee 100644 --- a/drivers/dma/imx-sdma.c +++ b/drivers/dma/imx-sdma.c @@ -1102,11 +1102,13 @@ static int sdma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,  	case DMA_SLAVE_CONFIG:  		if (dmaengine_cfg->direction == DMA_DEV_TO_MEM) {  			sdmac->per_address = dmaengine_cfg->src_addr; -			sdmac->watermark_level = dmaengine_cfg->src_maxburst; +			sdmac->watermark_level = dmaengine_cfg->src_maxburst * +						dmaengine_cfg->src_addr_width;  			sdmac->word_size = dmaengine_cfg->src_addr_width;  		} else {  			sdmac->per_address = dmaengine_cfg->dst_addr; -			sdmac->watermark_level = dmaengine_cfg->dst_maxburst; +			sdmac->watermark_level = dmaengine_cfg->dst_maxburst * +						dmaengine_cfg->dst_addr_width;  			sdmac->word_size = dmaengine_cfg->dst_addr_width;  		}  		sdmac->direction = dmaengine_cfg->direction; diff --git a/drivers/dma/shdma.c b/drivers/dma/shdma.c index 54043cd831c..812fd76e9c1 100644 --- a/drivers/dma/shdma.c +++ b/drivers/dma/shdma.c @@ -1262,7 +1262,8 @@ static int __init sh_dmae_probe(struct platform_device *pdev)  	INIT_LIST_HEAD(&shdev->common.channels); -	dma_cap_set(DMA_MEMCPY, shdev->common.cap_mask); +	if (!pdata->slave_only) +		dma_cap_set(DMA_MEMCPY, shdev->common.cap_mask);  	if (pdata->slave && pdata->slave_num)  		dma_cap_set(DMA_SLAVE, shdev->common.cap_mask); diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index 6628feaa762..7f5f0da726d 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c @@ -263,6 +263,7 @@ static inline struct fw_ohci *fw_ohci(struct fw_card *card)  static char ohci_driver_name[] = KBUILD_MODNAME;  #define PCI_DEVICE_ID_AGERE_FW643	0x5901 +#define PCI_DEVICE_ID_CREATIVE_SB1394	0x4001  #define PCI_DEVICE_ID_JMICRON_JMB38X_FW	0x2380  #define PCI_DEVICE_ID_TI_TSB12LV22	0x8009  #define PCI_DEVICE_ID_TI_TSB12LV26	0x8020 @@ -289,6 +290,9 @@ static const struct {  	{PCI_VENDOR_ID_ATT, PCI_DEVICE_ID_AGERE_FW643, 6,  		QUIRK_NO_MSI}, +	{PCI_VENDOR_ID_CREATIVE, PCI_DEVICE_ID_CREATIVE_SB1394, PCI_ANY_ID, +		QUIRK_RESET_PACKET}, +  	{PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB38X_FW, PCI_ANY_ID,  		QUIRK_NO_MSI}, @@ -299,7 +303,7 @@ static const struct {  		QUIRK_NO_MSI},  	{PCI_VENDOR_ID_RICOH, PCI_ANY_ID, PCI_ANY_ID, -		QUIRK_CYCLE_TIMER}, +		QUIRK_CYCLE_TIMER | QUIRK_NO_MSI},  	{PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_TSB12LV22, PCI_ANY_ID,  		QUIRK_CYCLE_TIMER | QUIRK_RESET_PACKET | QUIRK_NO_1394A}, diff --git a/drivers/gpio/gpio-lpc32xx.c b/drivers/gpio/gpio-lpc32xx.c index 5b6948081f8..ddfacc5ce56 100644 --- a/drivers/gpio/gpio-lpc32xx.c +++ b/drivers/gpio/gpio-lpc32xx.c @@ -96,7 +96,7 @@ static const char *gpio_p2_names[LPC32XX_GPIO_P2_MAX] = {  };  static const char *gpio_p3_names[LPC32XX_GPIO_P3_MAX] = { -	"gpi000", "gpio01", "gpio02", "gpio03", +	"gpio00", "gpio01", "gpio02", "gpio03",  	"gpio04", "gpio05"  }; diff --git a/drivers/gpio/gpio-ml-ioh.c b/drivers/gpio/gpio-ml-ioh.c index 03d6dd5dcb7..f0febe5b822 100644 --- a/drivers/gpio/gpio-ml-ioh.c +++ b/drivers/gpio/gpio-ml-ioh.c @@ -448,6 +448,7 @@ static int __devinit ioh_gpio_probe(struct pci_dev *pdev,  		chip->reg = chip->base;  		chip->ch = i;  		mutex_init(&chip->lock); +		spin_lock_init(&chip->spinlock);  		ioh_gpio_setup(chip, num_ports[i]);  		ret = gpiochip_add(&chip->gpio);  		if (ret) { diff --git a/drivers/gpio/gpio-mpc8xxx.c b/drivers/gpio/gpio-mpc8xxx.c index 5cd04b65c55..e6568c19c93 100644 --- a/drivers/gpio/gpio-mpc8xxx.c +++ b/drivers/gpio/gpio-mpc8xxx.c @@ -37,7 +37,7 @@ struct mpc8xxx_gpio_chip {  	 * open drain mode safely  	 */  	u32 data; -	struct irq_host *irq; +	struct irq_domain *irq;  	void *of_dev_id_data;  }; @@ -281,7 +281,7 @@ static struct irq_chip mpc8xxx_irq_chip = {  	.irq_set_type	= mpc8xxx_irq_set_type,  }; -static int mpc8xxx_gpio_irq_map(struct irq_host *h, unsigned int virq, +static int mpc8xxx_gpio_irq_map(struct irq_domain *h, unsigned int virq,  				irq_hw_number_t hw)  {  	struct mpc8xxx_gpio_chip *mpc8xxx_gc = h->host_data; @@ -296,24 +296,9 @@ static int mpc8xxx_gpio_irq_map(struct irq_host *h, unsigned int virq,  	return 0;  } -static int mpc8xxx_gpio_irq_xlate(struct irq_host *h, struct device_node *ct, -				  const u32 *intspec, unsigned int intsize, -				  irq_hw_number_t *out_hwirq, -				  unsigned int *out_flags) - -{ -	/* interrupt sense values coming from the device tree equal either -	 * EDGE_FALLING or EDGE_BOTH -	 */ -	*out_hwirq = intspec[0]; -	*out_flags = intspec[1]; - -	return 0; -} - -static struct irq_host_ops mpc8xxx_gpio_irq_ops = { +static struct irq_domain_ops mpc8xxx_gpio_irq_ops = {  	.map	= mpc8xxx_gpio_irq_map, -	.xlate	= mpc8xxx_gpio_irq_xlate, +	.xlate	= irq_domain_xlate_twocell,  };  static struct of_device_id mpc8xxx_gpio_ids[] __initdata = { @@ -364,9 +349,8 @@ static void __init mpc8xxx_add_controller(struct device_node *np)  	if (hwirq == NO_IRQ)  		goto skip_irq; -	mpc8xxx_gc->irq = -		irq_alloc_host(np, IRQ_HOST_MAP_LINEAR, MPC8XXX_GPIO_PINS, -			       &mpc8xxx_gpio_irq_ops, MPC8XXX_GPIO_PINS); +	mpc8xxx_gc->irq = irq_domain_add_linear(np, MPC8XXX_GPIO_PINS, +					&mpc8xxx_gpio_irq_ops, mpc8xxx_gc);  	if (!mpc8xxx_gc->irq)  		goto skip_irq; @@ -374,8 +358,6 @@ static void __init mpc8xxx_add_controller(struct device_node *np)  	if (id)  		mpc8xxx_gc->of_dev_id_data = id->data; -	mpc8xxx_gc->irq->host_data = mpc8xxx_gc; -  	/* ack and mask all irqs */  	out_be32(mm_gc->regs + GPIO_IER, 0xffffffff);  	out_be32(mm_gc->regs + GPIO_IMR, 0); diff --git a/drivers/gpio/gpio-pch.c b/drivers/gpio/gpio-pch.c index 68fa55e86eb..e8729cc2ba2 100644 --- a/drivers/gpio/gpio-pch.c +++ b/drivers/gpio/gpio-pch.c @@ -392,6 +392,7 @@ static int __devinit pch_gpio_probe(struct pci_dev *pdev,  	chip->reg = chip->base;  	pci_set_drvdata(pdev, chip);  	mutex_init(&chip->lock); +	spin_lock_init(&chip->spinlock);  	pch_gpio_setup(chip);  	ret = gpiochip_add(&chip->gpio);  	if (ret) { diff --git a/drivers/gpio/gpio-samsung.c b/drivers/gpio/gpio-samsung.c index a7661773c05..0a79a1167a2 100644 --- a/drivers/gpio/gpio-samsung.c +++ b/drivers/gpio/gpio-samsung.c @@ -2387,27 +2387,30 @@ static struct samsung_gpio_chip exynos4_gpios_3[] = {  };  #if defined(CONFIG_ARCH_EXYNOS4) && defined(CONFIG_OF) -static int exynos4_gpio_xlate(struct gpio_chip *gc, struct device_node *np, -			      const void *gpio_spec, u32 *flags) +static int exynos4_gpio_xlate(struct gpio_chip *gc, +			const struct of_phandle_args *gpiospec, u32 *flags)  { -	const __be32 *gpio = gpio_spec; -	const u32 n = be32_to_cpup(gpio); -	unsigned int pin = gc->base + be32_to_cpu(gpio[0]); +	unsigned int pin;  	if (WARN_ON(gc->of_gpio_n_cells < 4))  		return -EINVAL; -	if (n > gc->ngpio) +	if (WARN_ON(gpiospec->args_count < gc->of_gpio_n_cells))  		return -EINVAL; -	if (s3c_gpio_cfgpin(pin, S3C_GPIO_SFN(be32_to_cpu(gpio[1])))) +	if (gpiospec->args[0] > gc->ngpio) +		return -EINVAL; + +	pin = gc->base + gpiospec->args[0]; + +	if (s3c_gpio_cfgpin(pin, S3C_GPIO_SFN(gpiospec->args[1])))  		pr_warn("gpio_xlate: failed to set pin function\n"); -	if (s3c_gpio_setpull(pin, be32_to_cpu(gpio[2]))) +	if (s3c_gpio_setpull(pin, gpiospec->args[2]))  		pr_warn("gpio_xlate: failed to set pin pull up/down\n"); -	if (s5p_gpio_set_drvstr(pin, be32_to_cpu(gpio[3]))) +	if (s5p_gpio_set_drvstr(pin, gpiospec->args[3]))  		pr_warn("gpio_xlate: failed to set pin drive strength\n"); -	return n; +	return gpiospec->args[0];  }  static const struct of_device_id exynos4_gpio_dt_match[] __initdata = { diff --git a/drivers/gpu/drm/drm_ioc32.c b/drivers/gpu/drm/drm_ioc32.c index ddd70db45f7..637fcc3766c 100644 --- a/drivers/gpu/drm/drm_ioc32.c +++ b/drivers/gpu/drm/drm_ioc32.c @@ -315,7 +315,8 @@ static int compat_drm_getclient(struct file *file, unsigned int cmd,  	if (err)  		return err; -	if (__get_user(c32.auth, &client->auth) +	if (__get_user(c32.idx, &client->idx) +	    || __get_user(c32.auth, &client->auth)  	    || __get_user(c32.pid, &client->pid)  	    || __get_user(c32.uid, &client->uid)  	    || __get_user(c32.magic, &client->magic) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index b3b51c43dad..00fbff5ddd8 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1872,7 +1872,7 @@ static void intel_update_fbc(struct drm_device *dev)  	if (enable_fbc < 0) {  		DRM_DEBUG_KMS("fbc set to per-chip default\n");  		enable_fbc = 1; -		if (INTEL_INFO(dev)->gen <= 5) +		if (INTEL_INFO(dev)->gen <= 6)  			enable_fbc = 0;  	}  	if (!enable_fbc) { @@ -5307,6 +5307,7 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,  		}  	} +	pipeconf &= ~PIPECONF_INTERLACE_MASK;  	if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) {  		pipeconf |= PIPECONF_INTERLACE_W_FIELD_INDICATION;  		/* the chip adds 2 halflines automatically */ @@ -5317,7 +5318,7 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,  		adjusted_mode->crtc_vsync_end -= 1;  		adjusted_mode->crtc_vsync_start -= 1;  	} else -		pipeconf &= ~PIPECONF_INTERLACE_MASK; /* progressive */ +		pipeconf |= PIPECONF_PROGRESSIVE;  	I915_WRITE(HTOTAL(pipe),  		   (adjusted_mode->crtc_hdisplay - 1) | @@ -5902,6 +5903,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,  		}  	} +	pipeconf &= ~PIPECONF_INTERLACE_MASK;  	if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) {  		pipeconf |= PIPECONF_INTERLACE_W_FIELD_INDICATION;  		/* the chip adds 2 halflines automatically */ @@ -5912,7 +5914,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,  		adjusted_mode->crtc_vsync_end -= 1;  		adjusted_mode->crtc_vsync_start -= 1;  	} else -		pipeconf &= ~PIPECONF_INTERLACE_W_FIELD_INDICATION; /* progressive */ +		pipeconf |= PIPECONF_PROGRESSIVE;  	I915_WRITE(HTOTAL(pipe),  		   (adjusted_mode->crtc_hdisplay - 1) | diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index db3b461ad41..94f860cce3f 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -208,17 +208,8 @@ intel_dp_link_clock(uint8_t link_bw)   */  static int -intel_dp_link_required(struct intel_dp *intel_dp, int pixel_clock, int check_bpp) +intel_dp_link_required(int pixel_clock, int bpp)  { -	struct drm_crtc *crtc = intel_dp->base.base.crtc; -	struct intel_crtc *intel_crtc = to_intel_crtc(crtc); -	int bpp = 24; - -	if (check_bpp) -		bpp = check_bpp; -	else if (intel_crtc) -		bpp = intel_crtc->bpp; -  	return (pixel_clock * bpp + 9) / 10;  } @@ -245,12 +236,11 @@ intel_dp_mode_valid(struct drm_connector *connector,  			return MODE_PANEL;  	} -	mode_rate = intel_dp_link_required(intel_dp, mode->clock, 0); +	mode_rate = intel_dp_link_required(mode->clock, 24);  	max_rate = intel_dp_max_data_rate(max_link_clock, max_lanes);  	if (mode_rate > max_rate) { -			mode_rate = intel_dp_link_required(intel_dp, -							   mode->clock, 18); +			mode_rate = intel_dp_link_required(mode->clock, 18);  			if (mode_rate > max_rate)  				return MODE_CLOCK_HIGH;  			else @@ -683,7 +673,7 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,  	int lane_count, clock;  	int max_lane_count = intel_dp_max_lane_count(intel_dp);  	int max_clock = intel_dp_max_link_bw(intel_dp) == DP_LINK_BW_2_7 ? 1 : 0; -	int bpp = mode->private_flags & INTEL_MODE_DP_FORCE_6BPC ? 18 : 0; +	int bpp = mode->private_flags & INTEL_MODE_DP_FORCE_6BPC ? 18 : 24;  	static int bws[2] = { DP_LINK_BW_1_62, DP_LINK_BW_2_7 };  	if (is_edp(intel_dp) && intel_dp->panel_fixed_mode) { @@ -701,7 +691,7 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,  		for (clock = 0; clock <= max_clock; clock++) {  			int link_avail = intel_dp_max_data_rate(intel_dp_link_clock(bws[clock]), lane_count); -			if (intel_dp_link_required(intel_dp, mode->clock, bpp) +			if (intel_dp_link_required(mode->clock, bpp)  					<= link_avail) {  				intel_dp->link_bw = bws[clock];  				intel_dp->lane_count = lane_count; diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 798f6e1aa54..aa84832b0e1 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -694,6 +694,14 @@ static const struct dmi_system_id intel_no_lvds[] = {  	},  	{  		.callback = intel_no_lvds_dmi_callback, +                .ident = "AOpen i45GMx-I", +                .matches = { +                        DMI_MATCH(DMI_BOARD_VENDOR, "AOpen"), +                        DMI_MATCH(DMI_BOARD_NAME, "i45GMx-I"), +                }, +        }, +	{ +		.callback = intel_no_lvds_dmi_callback,  		.ident = "Aopen i945GTt-VFA",  		.matches = {  			DMI_MATCH(DMI_PRODUCT_VERSION, "AO00001JW"), diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.h b/drivers/gpu/drm/nouveau/nouveau_bios.h index 1e382ad5a2b..a37c31e358a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.h +++ b/drivers/gpu/drm/nouveau/nouveau_bios.h @@ -54,9 +54,10 @@ struct bit_entry {  int bit_table(struct drm_device *, u8 id, struct bit_entry *);  enum dcb_gpio_tag { -	DCB_GPIO_TVDAC0 = 0xc, +	DCB_GPIO_PANEL_POWER = 0x01, +	DCB_GPIO_TVDAC0 = 0x0c,  	DCB_GPIO_TVDAC1 = 0x2d, -	DCB_GPIO_PWM_FAN = 0x9, +	DCB_GPIO_PWM_FAN = 0x09,  	DCB_GPIO_FAN_SENSE = 0x3d,  	DCB_GPIO_UNUSED = 0xff  }; diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index 3cb52bc52b2..795a9e3c990 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -219,6 +219,16 @@ nouveau_display_init(struct drm_device *dev)  	if (ret)  		return ret; +	/* power on internal panel if it's not already.  the init tables of +	 * some vbios default this to off for some reason, causing the +	 * panel to not work after resume +	 */ +	if (nouveau_gpio_func_get(dev, DCB_GPIO_PANEL_POWER) == 0) { +		nouveau_gpio_func_set(dev, DCB_GPIO_PANEL_POWER, true); +		msleep(300); +	} + +	/* enable polling for external displays */  	drm_kms_helper_poll_enable(dev);  	/* enable hotplug interrupts */ diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.c b/drivers/gpu/drm/nouveau/nouveau_drv.c index e4a7cfe7898..81d7962e725 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.c +++ b/drivers/gpu/drm/nouveau/nouveau_drv.c @@ -124,7 +124,7 @@ MODULE_PARM_DESC(ctxfw, "Use external HUB/GPC ucode (fermi)\n");  int nouveau_ctxfw;  module_param_named(ctxfw, nouveau_ctxfw, int, 0400); -MODULE_PARM_DESC(ctxfw, "Santise DCB table according to MXM-SIS\n"); +MODULE_PARM_DESC(mxmdcb, "Santise DCB table according to MXM-SIS\n");  int nouveau_mxmdcb = 1;  module_param_named(mxmdcb, nouveau_mxmdcb, int, 0400); diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index 5f0bc57fdaa..7ce3fde4074 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c @@ -380,6 +380,25 @@ retry:  }  static int +validate_sync(struct nouveau_channel *chan, struct nouveau_bo *nvbo) +{ +	struct nouveau_fence *fence = NULL; +	int ret = 0; + +	spin_lock(&nvbo->bo.bdev->fence_lock); +	if (nvbo->bo.sync_obj) +		fence = nouveau_fence_ref(nvbo->bo.sync_obj); +	spin_unlock(&nvbo->bo.bdev->fence_lock); + +	if (fence) { +		ret = nouveau_fence_sync(fence, chan); +		nouveau_fence_unref(&fence); +	} + +	return ret; +} + +static int  validate_list(struct nouveau_channel *chan, struct list_head *list,  	      struct drm_nouveau_gem_pushbuf_bo *pbbo, uint64_t user_pbbo_ptr)  { @@ -393,7 +412,7 @@ validate_list(struct nouveau_channel *chan, struct list_head *list,  	list_for_each_entry(nvbo, list, entry) {  		struct drm_nouveau_gem_pushbuf_bo *b = &pbbo[nvbo->pbbo_index]; -		ret = nouveau_fence_sync(nvbo->bo.sync_obj, chan); +		ret = validate_sync(chan, nvbo);  		if (unlikely(ret)) {  			NV_ERROR(dev, "fail pre-validate sync\n");  			return ret; @@ -416,7 +435,7 @@ validate_list(struct nouveau_channel *chan, struct list_head *list,  			return ret;  		} -		ret = nouveau_fence_sync(nvbo->bo.sync_obj, chan); +		ret = validate_sync(chan, nvbo);  		if (unlikely(ret)) {  			NV_ERROR(dev, "fail post-validate sync\n");  			return ret; diff --git a/drivers/gpu/drm/nouveau/nouveau_mxm.c b/drivers/gpu/drm/nouveau/nouveau_mxm.c index 8bccddf4eff..e5a64f0f4cb 100644 --- a/drivers/gpu/drm/nouveau/nouveau_mxm.c +++ b/drivers/gpu/drm/nouveau/nouveau_mxm.c @@ -656,7 +656,16 @@ nouveau_mxm_init(struct drm_device *dev)  	if (mxm_shadow(dev, mxm[0])) {  		MXM_MSG(dev, "failed to locate valid SIS\n"); +#if 0 +		/* we should, perhaps, fall back to some kind of limited +		 * mode here if the x86 vbios hasn't already done the +		 * work for us (so we prevent loading with completely +		 * whacked vbios tables). +		 */  		return -EINVAL; +#else +		return 0; +#endif  	}  	MXM_MSG(dev, "MXMS Version %d.%d\n", diff --git a/drivers/gpu/drm/nouveau/nv50_pm.c b/drivers/gpu/drm/nouveau/nv50_pm.c index 03937212e9d..ec5481dfcd8 100644 --- a/drivers/gpu/drm/nouveau/nv50_pm.c +++ b/drivers/gpu/drm/nouveau/nv50_pm.c @@ -495,9 +495,9 @@ nv50_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl)  	struct drm_nouveau_private *dev_priv = dev->dev_private;  	struct nv50_pm_state *info;  	struct pll_lims pll; -	int ret = -EINVAL; +	int clk, ret = -EINVAL;  	int N, M, P1, P2; -	u32 clk, out; +	u32 out;  	if (dev_priv->chipset == 0xaa ||  	    dev_priv->chipset == 0xac) diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 891935271d3..742f17f009a 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -1184,7 +1184,7 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,  	WREG32(EVERGREEN_GRPH_ENABLE + radeon_crtc->crtc_offset, 1);  	WREG32(EVERGREEN_DESKTOP_HEIGHT + radeon_crtc->crtc_offset, -	       crtc->mode.vdisplay); +	       target_fb->height);  	x &= ~3;  	y &= ~1;  	WREG32(EVERGREEN_VIEWPORT_START + radeon_crtc->crtc_offset, @@ -1353,7 +1353,7 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc,  	WREG32(AVIVO_D1GRPH_ENABLE + radeon_crtc->crtc_offset, 1);  	WREG32(AVIVO_D1MODE_DESKTOP_HEIGHT + radeon_crtc->crtc_offset, -	       crtc->mode.vdisplay); +	       target_fb->height);  	x &= ~3;  	y &= ~1;  	WREG32(AVIVO_D1MODE_VIEWPORT_START + radeon_crtc->crtc_offset, diff --git a/drivers/gpu/drm/radeon/atombios_dp.c b/drivers/gpu/drm/radeon/atombios_dp.c index a71557ce01d..552b436451f 100644 --- a/drivers/gpu/drm/radeon/atombios_dp.c +++ b/drivers/gpu/drm/radeon/atombios_dp.c @@ -564,9 +564,21 @@ int radeon_dp_get_panel_mode(struct drm_encoder *encoder,  	    ENCODER_OBJECT_ID_NUTMEG)  		panel_mode = DP_PANEL_MODE_INTERNAL_DP1_MODE;  	else if (radeon_connector_encoder_get_dp_bridge_encoder_id(connector) == -		 ENCODER_OBJECT_ID_TRAVIS) -		panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE; -	else if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { +		 ENCODER_OBJECT_ID_TRAVIS) { +		u8 id[6]; +		int i; +		for (i = 0; i < 6; i++) +			id[i] = radeon_read_dpcd_reg(radeon_connector, 0x503 + i); +		if (id[0] == 0x73 && +		    id[1] == 0x69 && +		    id[2] == 0x76 && +		    id[3] == 0x61 && +		    id[4] == 0x72 && +		    id[5] == 0x54) +			panel_mode = DP_PANEL_MODE_INTERNAL_DP1_MODE; +		else +			panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE; +	} else if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {  		u8 tmp = radeon_read_dpcd_reg(radeon_connector, DP_EDP_CONFIGURATION_CAP);  		if (tmp & 1)  			panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE; diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index ae09fe82afb..9be353b894c 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -3191,6 +3191,7 @@ static int evergreen_startup(struct radeon_device *rdev)  	if (r) {  		DRM_ERROR("radeon: failed testing IB (%d).\n", r);  		rdev->accel_working = false; +		return r;  	}  	r = r600_audio_init(rdev); diff --git a/drivers/gpu/drm/radeon/r600_blit_kms.c b/drivers/gpu/drm/radeon/r600_blit_kms.c index d996f438113..accc032c103 100644 --- a/drivers/gpu/drm/radeon/r600_blit_kms.c +++ b/drivers/gpu/drm/radeon/r600_blit_kms.c @@ -468,27 +468,42 @@ set_default_state(struct radeon_device *rdev)  	radeon_ring_write(ring, sq_stack_resource_mgmt_2);  } +#define I2F_MAX_BITS 15 +#define I2F_MAX_INPUT  ((1 << I2F_MAX_BITS) - 1) +#define I2F_SHIFT (24 - I2F_MAX_BITS) + +/* + * Converts unsigned integer into 32-bit IEEE floating point representation. + * Conversion is not universal and only works for the range from 0 + * to 2^I2F_MAX_BITS-1. Currently we only use it with inputs between + * 0 and 16384 (inclusive), so I2F_MAX_BITS=15 is enough. If necessary, + * I2F_MAX_BITS can be increased, but that will add to the loop iterations + * and slow us down. Conversion is done by shifting the input and counting + * down until the first 1 reaches bit position 23. The resulting counter + * and the shifted input are, respectively, the exponent and the fraction. + * The sign is always zero. + */  static uint32_t i2f(uint32_t input)  {  	u32 result, i, exponent, fraction; -	if ((input & 0x3fff) == 0) -		result = 0; /* 0 is a special case */ +	WARN_ON_ONCE(input > I2F_MAX_INPUT); + +	if ((input & I2F_MAX_INPUT) == 0) +		result = 0;  	else { -		exponent = 140; /* exponent biased by 127; */ -		fraction = (input & 0x3fff) << 10; /* cheat and only -						      handle numbers below 2^^15 */ -		for (i = 0; i < 14; i++) { +		exponent = 126 + I2F_MAX_BITS; +		fraction = (input & I2F_MAX_INPUT) << I2F_SHIFT; + +		for (i = 0; i < I2F_MAX_BITS; i++) {  			if (fraction & 0x800000)  				break;  			else { -				fraction = fraction << 1; /* keep -							     shifting left until top bit = 1 */ +				fraction = fraction << 1;  				exponent = exponent - 1;  			}  		} -		result = exponent << 23 | (fraction & 0x7fffff); /* mask -								    off top bit; assumed 1 */ +		result = exponent << 23 | (fraction & 0x7fffff);  	}  	return result;  } diff --git a/drivers/gpu/drm/radeon/radeon_atpx_handler.c b/drivers/gpu/drm/radeon/radeon_atpx_handler.c index 13ac63ba607..98724fcb008 100644 --- a/drivers/gpu/drm/radeon/radeon_atpx_handler.c +++ b/drivers/gpu/drm/radeon/radeon_atpx_handler.c @@ -59,8 +59,9 @@ static int radeon_atrm_call(acpi_handle atrm_handle, uint8_t *bios,  	obj = (union acpi_object *)buffer.pointer;  	memcpy(bios+offset, obj->buffer.pointer, obj->buffer.length); +	len = obj->buffer.length;  	kfree(buffer.pointer); -	return obj->buffer.length; +	return len;  }  bool radeon_atrm_supported(struct pci_dev *pdev) diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index cec51a5b69d..49f7cb7e226 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -883,6 +883,8 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state)  	if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)  		return 0; +	drm_kms_helper_poll_disable(dev); +  	/* turn off display hw */  	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {  		drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF); @@ -972,6 +974,8 @@ int radeon_resume_kms(struct drm_device *dev)  	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {  		drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON);  	} + +	drm_kms_helper_poll_enable(dev);  	return 0;  } diff --git a/drivers/gpu/drm/radeon/radeon_i2c.c b/drivers/gpu/drm/radeon/radeon_i2c.c index e2a393ff0c4..98a8ad68010 100644 --- a/drivers/gpu/drm/radeon/radeon_i2c.c +++ b/drivers/gpu/drm/radeon/radeon_i2c.c @@ -958,6 +958,7 @@ struct radeon_i2c_chan *radeon_i2c_create_dp(struct drm_device *dev,  	i2c->rec = *rec;  	i2c->adapter.owner = THIS_MODULE;  	i2c->adapter.class = I2C_CLASS_DDC; +	i2c->adapter.dev.parent = &dev->pdev->dev;  	i2c->dev = dev;  	snprintf(i2c->adapter.name, sizeof(i2c->adapter.name),  		 "Radeon aux bus %s", name); diff --git a/drivers/hid/hid-hyperv.c b/drivers/hid/hid-hyperv.c index 0c33ae9cf0f..406632472c1 100644 --- a/drivers/hid/hid-hyperv.c +++ b/drivers/hid/hid-hyperv.c @@ -548,6 +548,7 @@ static int mousevsc_remove(struct hv_device *dev)  	struct mousevsc_dev *input_dev = hv_get_drvdata(dev);  	vmbus_close(dev->channel); +	hid_hw_stop(input_dev->hid_device);  	hid_destroy_device(input_dev->hid_device);  	mousevsc_free_device(input_dev); diff --git a/drivers/hid/hid-wacom.c b/drivers/hid/hid-wacom.c index b47e58b52d9..acab74cde72 100644 --- a/drivers/hid/hid-wacom.c +++ b/drivers/hid/hid-wacom.c @@ -531,7 +531,6 @@ static int wacom_probe(struct hid_device *hdev,  	wdata->battery.type = POWER_SUPPLY_TYPE_BATTERY;  	wdata->battery.use_for_apm = 0; -	power_supply_powers(&wdata->battery, &hdev->dev);  	ret = power_supply_register(&hdev->dev, &wdata->battery);  	if (ret) { @@ -540,6 +539,8 @@ static int wacom_probe(struct hid_device *hdev,  		goto err_battery;  	} +	power_supply_powers(&wdata->battery, &hdev->dev); +  	wdata->ac.properties = wacom_ac_props;  	wdata->ac.num_properties = ARRAY_SIZE(wacom_ac_props);  	wdata->ac.get_property = wacom_ac_get_property; @@ -547,14 +548,14 @@ static int wacom_probe(struct hid_device *hdev,  	wdata->ac.type = POWER_SUPPLY_TYPE_MAINS;  	wdata->ac.use_for_apm = 0; -	power_supply_powers(&wdata->battery, &hdev->dev); -  	ret = power_supply_register(&hdev->dev, &wdata->ac);  	if (ret) {  		hid_warn(hdev,  			 "can't create ac battery attribute, err: %d\n", ret);  		goto err_ac;  	} + +	power_supply_powers(&wdata->ac, &hdev->dev);  #endif  	return 0; diff --git a/drivers/hid/hid-wiimote-core.c b/drivers/hid/hid-wiimote-core.c index fc253b472f9..cac3589b1ed 100644 --- a/drivers/hid/hid-wiimote-core.c +++ b/drivers/hid/hid-wiimote-core.c @@ -1226,14 +1226,14 @@ static int wiimote_hid_probe(struct hid_device *hdev,  	wdata->battery.type = POWER_SUPPLY_TYPE_BATTERY;  	wdata->battery.use_for_apm = 0; -	power_supply_powers(&wdata->battery, &hdev->dev); -  	ret = power_supply_register(&wdata->hdev->dev, &wdata->battery);  	if (ret) {  		hid_err(hdev, "Cannot register battery device\n");  		goto err_battery;  	} +	power_supply_powers(&wdata->battery, &hdev->dev); +  	ret = wiimote_leds_create(wdata);  	if (ret)  		goto err_free; diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c index 7c297d305d5..b1ec0e2aeb5 100644 --- a/drivers/hid/usbhid/hiddev.c +++ b/drivers/hid/usbhid/hiddev.c @@ -922,11 +922,11 @@ void hiddev_disconnect(struct hid_device *hid)  	struct hiddev *hiddev = hid->hiddev;  	struct usbhid_device *usbhid = hid->driver_data; +	usb_deregister_dev(usbhid->intf, &hiddev_class); +  	mutex_lock(&hiddev->existancelock);  	hiddev->exist = 0; -	usb_deregister_dev(usbhid->intf, &hiddev_class); -  	if (hiddev->open) {  		mutex_unlock(&hiddev->existancelock);  		usbhid_close(hiddev->hid); diff --git a/drivers/hwmon/f75375s.c b/drivers/hwmon/f75375s.c index eedf574ab53..f609b5727ba 100644 --- a/drivers/hwmon/f75375s.c +++ b/drivers/hwmon/f75375s.c @@ -172,7 +172,7 @@ static inline void f75375_write8(struct i2c_client *client, u8 reg,  static inline void f75375_write16(struct i2c_client *client, u8 reg,  		u16 value)  { -	int err = i2c_smbus_write_byte_data(client, reg, (value << 8)); +	int err = i2c_smbus_write_byte_data(client, reg, (value >> 8));  	if (err)  		return;  	i2c_smbus_write_byte_data(client, reg + 1, (value & 0xFF)); @@ -200,9 +200,6 @@ static struct f75375_data *f75375_update_device(struct device *dev)  				f75375_read16(client, F75375_REG_FAN_MIN(nr));  			data->fan_target[nr] =  				f75375_read16(client, F75375_REG_FAN_EXP(nr)); -			data->pwm[nr] =	f75375_read8(client, -				F75375_REG_FAN_PWM_DUTY(nr)); -  		}  		for (nr = 0; nr < 4; nr++) {  			data->in_max[nr] = @@ -218,6 +215,8 @@ static struct f75375_data *f75375_update_device(struct device *dev)  	if (time_after(jiffies, data->last_updated + 2 * HZ)  		|| !data->valid) {  		for (nr = 0; nr < 2; nr++) { +			data->pwm[nr] =	f75375_read8(client, +				F75375_REG_FAN_PWM_DUTY(nr));  			/* assign MSB, therefore shift it by 8 bits */  			data->temp11[nr] =  				f75375_read8(client, F75375_REG_TEMP(nr)) << 8; @@ -369,7 +368,7 @@ static int set_pwm_enable_direct(struct i2c_client *client, int nr, int val)  			fanmode  |= (3 << FAN_CTRL_MODE(nr));  			break;  		case 2: /* AUTOMATIC*/ -			fanmode  |= (2 << FAN_CTRL_MODE(nr)); +			fanmode  |= (1 << FAN_CTRL_MODE(nr));  			break;  		case 3: /* fan speed */  			break; @@ -723,7 +722,7 @@ static void f75375_init(struct i2c_client *client, struct f75375_data *data,  			if (data->kind == f75387) {  				bool manu, duty; -				if (!(conf & (1 << F75387_FAN_CTRL_LINEAR(nr)))) +				if (!(mode & (1 << F75387_FAN_CTRL_LINEAR(nr))))  					data->pwm_mode[nr] = 1;  				manu = ((mode >> F75387_FAN_MANU_MODE(nr)) & 1); diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c index 2dfae7d7cc5..5276d1933db 100644 --- a/drivers/hwmon/w83627ehf.c +++ b/drivers/hwmon/w83627ehf.c @@ -1920,9 +1920,26 @@ w83627ehf_check_fan_inputs(const struct w83627ehf_sio_data *sio_data,  		fan4min = 0;  		fan5pin = 0;  	} else if (sio_data->kind == nct6776) { -		fan3pin = !(superio_inb(sio_data->sioreg, 0x24) & 0x40); -		fan4pin = !!(superio_inb(sio_data->sioreg, 0x1C) & 0x01); -		fan5pin = !!(superio_inb(sio_data->sioreg, 0x1C) & 0x02); +		bool gpok = superio_inb(sio_data->sioreg, 0x27) & 0x80; + +		superio_select(sio_data->sioreg, W83627EHF_LD_HWM); +		regval = superio_inb(sio_data->sioreg, SIO_REG_ENABLE); + +		if (regval & 0x80) +			fan3pin = gpok; +		else +			fan3pin = !(superio_inb(sio_data->sioreg, 0x24) & 0x40); + +		if (regval & 0x40) +			fan4pin = gpok; +		else +			fan4pin = !!(superio_inb(sio_data->sioreg, 0x1C) & 0x01); + +		if (regval & 0x20) +			fan5pin = gpok; +		else +			fan5pin = !!(superio_inb(sio_data->sioreg, 0x1C) & 0x02); +  		fan4min = fan4pin;  	} else if (sio_data->kind == w83667hg || sio_data->kind == w83667hg_b) {  		fan3pin = 1; @@ -2337,11 +2354,6 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev)  	for (i = 0; i < data->pwm_num; i++)  		data->pwm_enable_orig[i] = data->pwm_enable[i]; -	/* Read pwm data to save original values */ -	w83627ehf_update_pwm_common(dev, data); -	for (i = 0; i < data->pwm_num; i++) -		data->pwm_enable_orig[i] = data->pwm_enable[i]; -  	/* Register sysfs hooks */  	for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays); i++) {  		err = device_create_file(dev, &sda_sf3_arrays[i].dev_attr); diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index f713eac5504..801df6000e9 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -1018,7 +1018,7 @@ omap_i2c_probe(struct platform_device *pdev)  		goto err_release_region;  	} -	match = of_match_device(omap_i2c_of_match, &pdev->dev); +	match = of_match_device(of_match_ptr(omap_i2c_of_match), &pdev->dev);  	if (match) {  		u32 freq = 100000; /* default to 100000 Hz */ diff --git a/drivers/infiniband/core/ucma.c b/drivers/infiniband/core/ucma.c index b37b0c02a7b..5034a87cc72 100644 --- a/drivers/infiniband/core/ucma.c +++ b/drivers/infiniband/core/ucma.c @@ -808,9 +808,12 @@ static ssize_t ucma_accept(struct ucma_file *file, const char __user *inbuf,  		return PTR_ERR(ctx);  	if (cmd.conn_param.valid) { -		ctx->uid = cmd.uid;  		ucma_copy_conn_param(&conn_param, &cmd.conn_param); +		mutex_lock(&file->mut);  		ret = rdma_accept(ctx->cm_id, &conn_param); +		if (!ret) +			ctx->uid = cmd.uid; +		mutex_unlock(&file->mut);  	} else  		ret = rdma_accept(ctx->cm_id, NULL); diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c index b930da4c0c6..4d27e4c3fe3 100644 --- a/drivers/infiniband/core/uverbs_cmd.c +++ b/drivers/infiniband/core/uverbs_cmd.c @@ -1485,6 +1485,7 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,  		qp->event_handler = attr.event_handler;  		qp->qp_context	  = attr.qp_context;  		qp->qp_type	  = attr.qp_type; +		atomic_set(&qp->usecnt, 0);  		atomic_inc(&pd->usecnt);  		atomic_inc(&attr.send_cq->usecnt);  		if (attr.recv_cq) diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c index 602b1bd723a..575b78045aa 100644 --- a/drivers/infiniband/core/verbs.c +++ b/drivers/infiniband/core/verbs.c @@ -421,6 +421,7 @@ struct ib_qp *ib_create_qp(struct ib_pd *pd,  		qp->uobject    = NULL;  		qp->qp_type    = qp_init_attr->qp_type; +		atomic_set(&qp->usecnt, 0);  		if (qp_init_attr->qp_type == IB_QPT_XRC_TGT) {  			qp->event_handler = __ib_shared_qp_event_handler;  			qp->qp_context = qp; @@ -430,7 +431,6 @@ struct ib_qp *ib_create_qp(struct ib_pd *pd,  			qp->xrcd = qp_init_attr->xrcd;  			atomic_inc(&qp_init_attr->xrcd->usecnt);  			INIT_LIST_HEAD(&qp->open_list); -			atomic_set(&qp->usecnt, 0);  			real_qp = qp;  			qp = __ib_open_qp(real_qp, qp_init_attr->event_handler, diff --git a/drivers/infiniband/hw/ipath/ipath_fs.c b/drivers/infiniband/hw/ipath/ipath_fs.c index b7d4216db3c..a4de9d58e9b 100644 --- a/drivers/infiniband/hw/ipath/ipath_fs.c +++ b/drivers/infiniband/hw/ipath/ipath_fs.c @@ -89,7 +89,7 @@ static int create_file(const char *name, umode_t mode,  		error = ipathfs_mknod(parent->d_inode, *dentry,  				      mode, fops, data);  	else -		error = PTR_ERR(dentry); +		error = PTR_ERR(*dentry);  	mutex_unlock(&parent->d_inode->i_mutex);  	return error; diff --git a/drivers/infiniband/hw/mlx4/mad.c b/drivers/infiniband/hw/mlx4/mad.c index 95c94d8f025..259b0670b51 100644 --- a/drivers/infiniband/hw/mlx4/mad.c +++ b/drivers/infiniband/hw/mlx4/mad.c @@ -257,12 +257,9 @@ static int ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num,  			return IB_MAD_RESULT_SUCCESS;  		/* -		 * Don't process SMInfo queries or vendor-specific -		 * MADs -- the SMA can't handle them. +		 * Don't process SMInfo queries -- the SMA can't handle them.  		 */ -		if (in_mad->mad_hdr.attr_id == IB_SMP_ATTR_SM_INFO || -		    ((in_mad->mad_hdr.attr_id & IB_SMP_ATTR_VENDOR_MASK) == -		     IB_SMP_ATTR_VENDOR_MASK)) +		if (in_mad->mad_hdr.attr_id == IB_SMP_ATTR_SM_INFO)  			return IB_MAD_RESULT_SUCCESS;  	} else if (in_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_PERF_MGMT ||  		   in_mad->mad_hdr.mgmt_class == MLX4_IB_VENDOR_CLASS1   || diff --git a/drivers/infiniband/hw/nes/nes.c b/drivers/infiniband/hw/nes/nes.c index 7013da5e9ed..7140199f562 100644 --- a/drivers/infiniband/hw/nes/nes.c +++ b/drivers/infiniband/hw/nes/nes.c @@ -1,5 +1,5 @@  /* - * Copyright (c) 2006 - 2009 Intel Corporation.  All rights reserved. + * Copyright (c) 2006 - 2011 Intel Corporation.  All rights reserved.   * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved.   *   * This software is available to you under a choice of one of two diff --git a/drivers/infiniband/hw/nes/nes.h b/drivers/infiniband/hw/nes/nes.h index 568b4f11380..c438e4691b3 100644 --- a/drivers/infiniband/hw/nes/nes.h +++ b/drivers/infiniband/hw/nes/nes.h @@ -1,5 +1,5 @@  /* - * Copyright (c) 2006 - 2009 Intel Corporation.  All rights reserved. + * Copyright (c) 2006 - 2011 Intel Corporation.  All rights reserved.   * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved.   *   * This software is available to you under a choice of one of two diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c index 425065b36b8..a4972abedef 100644 --- a/drivers/infiniband/hw/nes/nes_cm.c +++ b/drivers/infiniband/hw/nes/nes_cm.c @@ -1,5 +1,5 @@  /* - * Copyright (c) 2006 - 2009 Intel Corporation.  All rights reserved. + * Copyright (c) 2006 - 2011 Intel Corporation.  All rights reserved.   *   * This software is available to you under a choice of one of two   * licenses.  You may choose to be licensed under the terms of the GNU @@ -233,6 +233,7 @@ static int send_mpa_reject(struct nes_cm_node *cm_node)  	u8 *start_ptr = &start_addr;  	u8 **start_buff = &start_ptr;  	u16 buff_len = 0; +	struct ietf_mpa_v1 *mpa_frame;  	skb = dev_alloc_skb(MAX_CM_BUFFER);  	if (!skb) { @@ -242,6 +243,8 @@ static int send_mpa_reject(struct nes_cm_node *cm_node)  	/* send an MPA reject frame */  	cm_build_mpa_frame(cm_node, start_buff, &buff_len, NULL, MPA_KEY_REPLY); +	mpa_frame = (struct ietf_mpa_v1 *)*start_buff; +	mpa_frame->flags |= IETF_MPA_FLAGS_REJECT;  	form_cm_frame(skb, cm_node, NULL, 0, *start_buff, buff_len, SET_ACK | SET_FIN);  	cm_node->state = NES_CM_STATE_FIN_WAIT1; @@ -1360,8 +1363,7 @@ static int nes_addr_resolve_neigh(struct nes_vnic *nesvnic, u32 dst_ip, int arpi  				if (!memcmp(nesadapter->arp_table[arpindex].mac_addr,  					    neigh->ha, ETH_ALEN)) {  					/* Mac address same as in nes_arp_table */ -					ip_rt_put(rt); -					return rc; +					goto out;  				}  				nes_manage_arp_cache(nesvnic->netdev, @@ -1377,6 +1379,8 @@ static int nes_addr_resolve_neigh(struct nes_vnic *nesvnic, u32 dst_ip, int arpi  			neigh_event_send(neigh, NULL);  		}  	} + +out:  	rcu_read_unlock();  	ip_rt_put(rt);  	return rc; diff --git a/drivers/infiniband/hw/nes/nes_cm.h b/drivers/infiniband/hw/nes/nes_cm.h index bdfa1fbb35f..4646e666608 100644 --- a/drivers/infiniband/hw/nes/nes_cm.h +++ b/drivers/infiniband/hw/nes/nes_cm.h @@ -1,5 +1,5 @@  /* - * Copyright (c) 2006 - 2009 Intel Corporation.  All rights reserved. + * Copyright (c) 2006 - 2011 Intel Corporation.  All rights reserved.   *   * This software is available to you under a choice of one of two   * licenses.  You may choose to be licensed under the terms of the GNU diff --git a/drivers/infiniband/hw/nes/nes_context.h b/drivers/infiniband/hw/nes/nes_context.h index b4393a16099..a69eef16d72 100644 --- a/drivers/infiniband/hw/nes/nes_context.h +++ b/drivers/infiniband/hw/nes/nes_context.h @@ -1,5 +1,5 @@  /* - * Copyright (c) 2006 - 2009 Intel Corporation.  All rights reserved. + * Copyright (c) 2006 - 2011 Intel Corporation.  All rights reserved.   *   * This software is available to you under a choice of one of two   * licenses.  You may choose to be licensed under the terms of the GNU diff --git a/drivers/infiniband/hw/nes/nes_hw.c b/drivers/infiniband/hw/nes/nes_hw.c index 055f4b545df..d42c9f435b1 100644 --- a/drivers/infiniband/hw/nes/nes_hw.c +++ b/drivers/infiniband/hw/nes/nes_hw.c @@ -1,5 +1,5 @@  /* - * Copyright (c) 2006 - 2009 Intel Corporation.  All rights reserved. + * Copyright (c) 2006 - 2011 Intel Corporation.  All rights reserved.   *   * This software is available to you under a choice of one of two   * licenses.  You may choose to be licensed under the terms of the GNU diff --git a/drivers/infiniband/hw/nes/nes_hw.h b/drivers/infiniband/hw/nes/nes_hw.h index 0b590e152c6..d748e4b31b8 100644 --- a/drivers/infiniband/hw/nes/nes_hw.h +++ b/drivers/infiniband/hw/nes/nes_hw.h @@ -1,5 +1,5 @@  /* -* Copyright (c) 2006 - 2009 Intel Corporation.  All rights reserved. +* Copyright (c) 2006 - 2011 Intel Corporation.  All rights reserved.  *  * This software is available to you under a choice of one of two  * licenses.  You may choose to be licensed under the terms of the GNU diff --git a/drivers/infiniband/hw/nes/nes_mgt.c b/drivers/infiniband/hw/nes/nes_mgt.c index b3b2a240c6e..3ba7be36945 100644 --- a/drivers/infiniband/hw/nes/nes_mgt.c +++ b/drivers/infiniband/hw/nes/nes_mgt.c @@ -1,5 +1,5 @@  /* - * Copyright (c) 2006 - 2009 Intel-NE, Inc.  All rights reserved. + * Copyright (c) 2006 - 2011 Intel-NE, Inc.  All rights reserved.   *   * This software is available to you under a choice of one of two   * licenses.  You may choose to be licensed under the terms of the GNU diff --git a/drivers/infiniband/hw/nes/nes_mgt.h b/drivers/infiniband/hw/nes/nes_mgt.h index 8c8af254555..4f7f701c4a8 100644 --- a/drivers/infiniband/hw/nes/nes_mgt.h +++ b/drivers/infiniband/hw/nes/nes_mgt.h @@ -1,5 +1,5 @@  /* -* Copyright (c) 2010 Intel-NE, Inc.  All rights reserved. +* Copyright (c) 2006 - 2011 Intel-NE, Inc.  All rights reserved.  *  * This software is available to you under a choice of one of two  * licenses.  You may choose to be licensed under the terms of the GNU diff --git a/drivers/infiniband/hw/nes/nes_nic.c b/drivers/infiniband/hw/nes/nes_nic.c index 4b3fa711a24..f3a3ecf8d09 100644 --- a/drivers/infiniband/hw/nes/nes_nic.c +++ b/drivers/infiniband/hw/nes/nes_nic.c @@ -1,5 +1,5 @@  /* - * Copyright (c) 2006 - 2009 Intel Corporation.  All rights reserved. + * Copyright (c) 2006 - 2011 Intel Corporation.  All rights reserved.   *   * This software is available to you under a choice of one of two   * licenses.  You may choose to be licensed under the terms of the GNU diff --git a/drivers/infiniband/hw/nes/nes_user.h b/drivers/infiniband/hw/nes/nes_user.h index 71e133ab209..4926de74448 100644 --- a/drivers/infiniband/hw/nes/nes_user.h +++ b/drivers/infiniband/hw/nes/nes_user.h @@ -1,5 +1,5 @@  /* - * Copyright (c) 2006 - 2009 Intel Corporation.  All rights reserved. + * Copyright (c) 2006 - 2011 Intel Corporation.  All rights reserved.   * Copyright (c) 2005 Topspin Communications.  All rights reserved.   * Copyright (c) 2005 Cisco Systems.  All rights reserved.   * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved. diff --git a/drivers/infiniband/hw/nes/nes_utils.c b/drivers/infiniband/hw/nes/nes_utils.c index 8b4c2ff5488..e98f4fc0b76 100644 --- a/drivers/infiniband/hw/nes/nes_utils.c +++ b/drivers/infiniband/hw/nes/nes_utils.c @@ -1,5 +1,5 @@  /* - * Copyright (c) 2006 - 2009 Intel Corporation.  All rights reserved. + * Copyright (c) 2006 - 2011 Intel Corporation.  All rights reserved.   *   * This software is available to you under a choice of one of two   * licenses.  You may choose to be licensed under the terms of the GNU diff --git a/drivers/infiniband/hw/nes/nes_verbs.c b/drivers/infiniband/hw/nes/nes_verbs.c index 5095bc41c6c..0927b5cc65d 100644 --- a/drivers/infiniband/hw/nes/nes_verbs.c +++ b/drivers/infiniband/hw/nes/nes_verbs.c @@ -1,5 +1,5 @@  /* - * Copyright (c) 2006 - 2009 Intel Corporation.  All rights reserved. + * Copyright (c) 2006 - 2011 Intel Corporation.  All rights reserved.   *   * This software is available to you under a choice of one of two   * licenses.  You may choose to be licensed under the terms of the GNU @@ -3428,6 +3428,8 @@ static int nes_post_send(struct ib_qp *ibqp, struct ib_send_wr *ib_wr,  					    NES_IWARP_SQ_FMR_WQE_LENGTH_LOW_IDX,  					    ib_wr->wr.fast_reg.length);  			set_wqe_32bit_value(wqe->wqe_words, +					    NES_IWARP_SQ_FMR_WQE_LENGTH_HIGH_IDX, 0); +			set_wqe_32bit_value(wqe->wqe_words,  					    NES_IWARP_SQ_FMR_WQE_MR_STAG_IDX,  					    ib_wr->wr.fast_reg.rkey);  			/* Set page size: */ @@ -3724,7 +3726,7 @@ static int nes_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry)  						entry->opcode = IB_WC_SEND;  						break;  					case NES_IWARP_SQ_OP_LOCINV: -						entry->opcode = IB_WR_LOCAL_INV; +						entry->opcode = IB_WC_LOCAL_INV;  						break;  					case NES_IWARP_SQ_OP_FAST_REG:  						entry->opcode = IB_WC_FAST_REG_MR; diff --git a/drivers/infiniband/hw/nes/nes_verbs.h b/drivers/infiniband/hw/nes/nes_verbs.h index fe6b6e92fa9..0eff7c44d76 100644 --- a/drivers/infiniband/hw/nes/nes_verbs.h +++ b/drivers/infiniband/hw/nes/nes_verbs.h @@ -1,5 +1,5 @@  /* - * Copyright (c) 2006 - 2009 Intel Corporation.  All rights reserved. + * Copyright (c) 2006 - 2011 Intel Corporation.  All rights reserved.   * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved.   *   * This software is available to you under a choice of one of two diff --git a/drivers/infiniband/hw/qib/qib_iba6120.c b/drivers/infiniband/hw/qib/qib_iba6120.c index 4f18e2d332d..d0c64d51481 100644 --- a/drivers/infiniband/hw/qib/qib_iba6120.c +++ b/drivers/infiniband/hw/qib/qib_iba6120.c @@ -2105,7 +2105,7 @@ static void alloc_dummy_hdrq(struct qib_devdata *dd)  	dd->cspec->dummy_hdrq = dma_alloc_coherent(&dd->pcidev->dev,  					dd->rcd[0]->rcvhdrq_size,  					&dd->cspec->dummy_hdrq_phys, -					GFP_KERNEL | __GFP_COMP); +					GFP_ATOMIC | __GFP_COMP);  	if (!dd->cspec->dummy_hdrq) {  		qib_devinfo(dd->pcidev, "Couldn't allocate dummy hdrq\n");  		/* fallback to just 0'ing */ diff --git a/drivers/infiniband/hw/qib/qib_pcie.c b/drivers/infiniband/hw/qib/qib_pcie.c index f695061d688..0fde788e110 100644 --- a/drivers/infiniband/hw/qib/qib_pcie.c +++ b/drivers/infiniband/hw/qib/qib_pcie.c @@ -560,7 +560,7 @@ static int qib_tune_pcie_coalesce(struct qib_devdata *dd)   * BIOS may not set PCIe bus-utilization parameters for best performance.   * Check and optionally adjust them to maximize our throughput.   */ -static int qib_pcie_caps = 0x51; +static int qib_pcie_caps;  module_param_named(pcie_caps, qib_pcie_caps, int, S_IRUGO);  MODULE_PARM_DESC(pcie_caps, "Max PCIe tuning: Payload (0..3), ReadReq (4..7)"); diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h index b3cc1e062b1..86df632ea61 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib.h +++ b/drivers/infiniband/ulp/ipoib/ipoib.h @@ -44,6 +44,7 @@  #include <linux/mutex.h>  #include <net/neighbour.h> +#include <net/sch_generic.h>  #include <linux/atomic.h> @@ -117,8 +118,9 @@ struct ipoib_header {  	u16	reserved;  }; -struct ipoib_pseudoheader { -	u8  hwaddr[INFINIBAND_ALEN]; +struct ipoib_cb { +	struct qdisc_skb_cb	qdisc_cb; +	u8			hwaddr[INFINIBAND_ALEN];  };  /* Used for all multicast joins (broadcast, IPv4 mcast and IPv6 mcast) */ diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index 3514ca05dee..3974c290b66 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -653,7 +653,7 @@ static void ipoib_path_lookup(struct sk_buff *skb, struct neighbour *n, struct n  }  static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev, -			     struct ipoib_pseudoheader *phdr) +			     struct ipoib_cb *cb)  {  	struct ipoib_dev_priv *priv = netdev_priv(dev);  	struct ipoib_path *path; @@ -661,17 +661,15 @@ static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev,  	spin_lock_irqsave(&priv->lock, flags); -	path = __path_find(dev, phdr->hwaddr + 4); +	path = __path_find(dev, cb->hwaddr + 4);  	if (!path || !path->valid) {  		int new_path = 0;  		if (!path) { -			path = path_rec_create(dev, phdr->hwaddr + 4); +			path = path_rec_create(dev, cb->hwaddr + 4);  			new_path = 1;  		}  		if (path) { -			/* put pseudoheader back on for next time */ -			skb_push(skb, sizeof *phdr);  			__skb_queue_tail(&path->queue, skb);  			if (!path->query && path_rec_start(dev, path)) { @@ -695,12 +693,10 @@ static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev,  			  be16_to_cpu(path->pathrec.dlid));  		spin_unlock_irqrestore(&priv->lock, flags); -		ipoib_send(dev, skb, path->ah, IPOIB_QPN(phdr->hwaddr)); +		ipoib_send(dev, skb, path->ah, IPOIB_QPN(cb->hwaddr));  		return;  	} else if ((path->query || !path_rec_start(dev, path)) &&  		   skb_queue_len(&path->queue) < IPOIB_MAX_PATH_REC_QUEUE) { -		/* put pseudoheader back on for next time */ -		skb_push(skb, sizeof *phdr);  		__skb_queue_tail(&path->queue, skb);  	} else {  		++dev->stats.tx_dropped; @@ -774,16 +770,14 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)  			dev_kfree_skb_any(skb);  		}  	} else { -		struct ipoib_pseudoheader *phdr = -			(struct ipoib_pseudoheader *) skb->data; -		skb_pull(skb, sizeof *phdr); +		struct ipoib_cb *cb = (struct ipoib_cb *) skb->cb; -		if (phdr->hwaddr[4] == 0xff) { +		if (cb->hwaddr[4] == 0xff) {  			/* Add in the P_Key for multicast*/ -			phdr->hwaddr[8] = (priv->pkey >> 8) & 0xff; -			phdr->hwaddr[9] = priv->pkey & 0xff; +			cb->hwaddr[8] = (priv->pkey >> 8) & 0xff; +			cb->hwaddr[9] = priv->pkey & 0xff; -			ipoib_mcast_send(dev, phdr->hwaddr + 4, skb); +			ipoib_mcast_send(dev, cb->hwaddr + 4, skb);  		} else {  			/* unicast GID -- should be ARP or RARP reply */ @@ -792,14 +786,14 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)  				ipoib_warn(priv, "Unicast, no %s: type %04x, QPN %06x %pI6\n",  					   skb_dst(skb) ? "neigh" : "dst",  					   be16_to_cpup((__be16 *) skb->data), -					   IPOIB_QPN(phdr->hwaddr), -					   phdr->hwaddr + 4); +					   IPOIB_QPN(cb->hwaddr), +					   cb->hwaddr + 4);  				dev_kfree_skb_any(skb);  				++dev->stats.tx_dropped;  				goto unlock;  			} -			unicast_arp_send(skb, dev, phdr); +			unicast_arp_send(skb, dev, cb);  		}  	}  unlock: @@ -825,8 +819,6 @@ static int ipoib_hard_header(struct sk_buff *skb,  			     const void *daddr, const void *saddr, unsigned len)  {  	struct ipoib_header *header; -	struct dst_entry *dst; -	struct neighbour *n;  	header = (struct ipoib_header *) skb_push(skb, sizeof *header); @@ -834,18 +826,13 @@ static int ipoib_hard_header(struct sk_buff *skb,  	header->reserved = 0;  	/* -	 * If we don't have a neighbour structure, stuff the -	 * destination address onto the front of the skb so we can -	 * figure out where to send the packet later. +	 * If we don't have a dst_entry structure, stuff the +	 * destination address into skb->cb so we can figure out where +	 * to send the packet later.  	 */ -	dst = skb_dst(skb); -	n = NULL; -	if (dst) -		n = dst_get_neighbour_noref_raw(dst); -	if ((!dst || !n) && daddr) { -		struct ipoib_pseudoheader *phdr = -			(struct ipoib_pseudoheader *) skb_push(skb, sizeof *phdr); -		memcpy(phdr->hwaddr, daddr, INFINIBAND_ALEN); +	if (!skb_dst(skb)) { +		struct ipoib_cb *cb = (struct ipoib_cb *) skb->cb; +		memcpy(cb->hwaddr, daddr, INFINIBAND_ALEN);  	}  	return 0; @@ -1021,11 +1008,7 @@ static void ipoib_setup(struct net_device *dev)  	dev->flags		|= IFF_BROADCAST | IFF_MULTICAST; -	/* -	 * We add in INFINIBAND_ALEN to allow for the destination -	 * address "pseudoheader" for skbs without neighbour struct. -	 */ -	dev->hard_header_len	 = IPOIB_ENCAP_LEN + INFINIBAND_ALEN; +	dev->hard_header_len	 = IPOIB_ENCAP_LEN;  	dev->addr_len		 = INFINIBAND_ALEN;  	dev->type		 = ARPHRD_INFINIBAND;  	dev->tx_queue_len	 = ipoib_sendq_size * 2; diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c index f7ff9dd66cd..20ebc6fd1bb 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c @@ -262,21 +262,13 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast,  	netif_tx_lock_bh(dev);  	while (!skb_queue_empty(&mcast->pkt_queue)) {  		struct sk_buff *skb = skb_dequeue(&mcast->pkt_queue); -		struct dst_entry *dst = skb_dst(skb); -		struct neighbour *n = NULL;  		netif_tx_unlock_bh(dev);  		skb->dev = dev; -		if (dst) -			n = dst_get_neighbour_noref_raw(dst); -		if (!dst || !n) { -			/* put pseudoheader back on for next time */ -			skb_push(skb, sizeof (struct ipoib_pseudoheader)); -		} -  		if (dev_queue_xmit(skb))  			ipoib_warn(priv, "dev_queue_xmit failed to requeue packet\n"); +  		netif_tx_lock_bh(dev);  	}  	netif_tx_unlock_bh(dev); diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c index cd5d05e22a7..2b73d43cd69 100644 --- a/drivers/infiniband/ulp/srpt/ib_srpt.c +++ b/drivers/infiniband/ulp/srpt/ib_srpt.c @@ -69,8 +69,8 @@ MODULE_LICENSE("Dual BSD/GPL");   */  static u64 srpt_service_guid; -static spinlock_t srpt_dev_lock;       /* Protects srpt_dev_list. */ -static struct list_head srpt_dev_list; /* List of srpt_device structures. */ +static DEFINE_SPINLOCK(srpt_dev_lock);	/* Protects srpt_dev_list. */ +static LIST_HEAD(srpt_dev_list);	/* List of srpt_device structures. */  static unsigned srp_max_req_size = DEFAULT_MAX_REQ_SIZE;  module_param(srp_max_req_size, int, 0444); @@ -687,6 +687,7 @@ err:  	while (--i >= 0)  		srpt_free_ioctx(sdev, ring[i], dma_size, dir);  	kfree(ring); +	ring = NULL;  out:  	return ring;  } @@ -2595,7 +2596,7 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id,  	}  	ch->sess = transport_init_session(); -	if (!ch->sess) { +	if (IS_ERR(ch->sess)) {  		rej->reason = __constant_cpu_to_be32(  				SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES);  		pr_debug("Failed to create session\n"); @@ -3264,8 +3265,7 @@ static void srpt_add_one(struct ib_device *device)  	for (i = 0; i < sdev->srq_size; ++i)  		srpt_post_recv(sdev, sdev->ioctx_ring[i]); -	WARN_ON(sdev->device->phys_port_cnt -		> sizeof(sdev->port)/sizeof(sdev->port[0])); +	WARN_ON(sdev->device->phys_port_cnt > ARRAY_SIZE(sdev->port));  	for (i = 1; i <= sdev->device->phys_port_cnt; i++) {  		sport = &sdev->port[i - 1]; @@ -4010,13 +4010,10 @@ static int __init srpt_init_module(void)  		goto out;  	} -	spin_lock_init(&srpt_dev_lock); -	INIT_LIST_HEAD(&srpt_dev_list); - -	ret = -ENODEV;  	srpt_target = target_fabric_configfs_init(THIS_MODULE, "srpt"); -	if (!srpt_target) { +	if (IS_ERR(srpt_target)) {  		printk(KERN_ERR "couldn't register\n"); +		ret = PTR_ERR(srpt_target);  		goto out;  	} diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.h b/drivers/infiniband/ulp/srpt/ib_srpt.h index b4b4bbcd7f1..61e52b83081 100644 --- a/drivers/infiniband/ulp/srpt/ib_srpt.h +++ b/drivers/infiniband/ulp/srpt/ib_srpt.h @@ -35,7 +35,6 @@  #ifndef IB_SRPT_H  #define IB_SRPT_H -#include <linux/version.h>  #include <linux/types.h>  #include <linux/list.h>  #include <linux/wait.h> diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index 76457d50bc3..afc166fcc3d 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -386,7 +386,7 @@ static ssize_t evdev_read(struct file *file, char __user *buffer,  	struct evdev_client *client = file->private_data;  	struct evdev *evdev = client->evdev;  	struct input_event event; -	int retval; +	int retval = 0;  	if (count < input_event_size())  		return -EINVAL; diff --git a/drivers/input/keyboard/twl4030_keypad.c b/drivers/input/keyboard/twl4030_keypad.c index a588578037e..67bec14e8b9 100644 --- a/drivers/input/keyboard/twl4030_keypad.c +++ b/drivers/input/keyboard/twl4030_keypad.c @@ -34,7 +34,6 @@  #include <linux/i2c/twl.h>  #include <linux/slab.h> -  /*   * The TWL4030 family chips include a keypad controller that supports   * up to an 8x8 switch matrix.  The controller can issue system wakeup @@ -302,7 +301,7 @@ static int __devinit twl4030_kp_program(struct twl4030_keypad *kp)  	if (twl4030_kpwrite_u8(kp, i, KEYP_DEB) < 0)  		return -EIO; -	/* Set timeout period to 100 ms */ +	/* Set timeout period to 200 ms */  	i = KEYP_PERIOD_US(200000, PTV_PRESCALER);  	if (twl4030_kpwrite_u8(kp, (i & 0xFF), KEYP_TIMEOUT_L) < 0)  		return -EIO; @@ -466,4 +465,3 @@ MODULE_AUTHOR("Texas Instruments");  MODULE_DESCRIPTION("TWL4030 Keypad Driver");  MODULE_LICENSE("GPL");  MODULE_ALIAS("platform:twl4030_keypad"); - diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index b4cfc6c8be8..5ec774d6c82 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h @@ -512,6 +512,13 @@ static const struct dmi_system_id __initconst i8042_dmi_reset_table[] = {  			DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 1720"),  		},  	}, +	{ +		/* Lenovo Ideapad U455 */ +		.matches = { +			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), +			DMI_MATCH(DMI_PRODUCT_NAME, "20046"), +		}, +	},  	{ }  }; diff --git a/drivers/input/serio/serio_raw.c b/drivers/input/serio/serio_raw.c index 8250299fd64..4494233d331 100644 --- a/drivers/input/serio/serio_raw.c +++ b/drivers/input/serio/serio_raw.c @@ -164,7 +164,8 @@ static ssize_t serio_raw_read(struct file *file, char __user *buffer,  	struct serio_raw_client *client = file->private_data;  	struct serio_raw *serio_raw = client->serio_raw;  	char uninitialized_var(c); -	ssize_t retval = 0; +	ssize_t read = 0; +	int retval;  	if (serio_raw->dead)  		return -ENODEV; @@ -180,13 +181,15 @@ static ssize_t serio_raw_read(struct file *file, char __user *buffer,  	if (serio_raw->dead)  		return -ENODEV; -	while (retval < count && serio_raw_fetch_byte(serio_raw, &c)) { -		if (put_user(c, buffer++)) -			return -EFAULT; -		retval++; +	while (read < count && serio_raw_fetch_byte(serio_raw, &c)) { +		if (put_user(c, buffer++)) { +			retval = -EFAULT; +			break; +		} +		read++;  	} -	return retval; +	return read ?: retval;  }  static ssize_t serio_raw_write(struct file *file, const char __user *buffer, diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index cce1f03b889..f75e0608be5 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c @@ -2863,6 +2863,9 @@ static unsigned device_dma_ops_init(void)  	for_each_pci_dev(pdev) {  		if (!check_device(&pdev->dev)) { + +			iommu_ignore_device(&pdev->dev); +  			unhandled += 1;  			continue;  		} diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu.c index 08a90b88e40..cee307e8660 100644 --- a/drivers/iommu/msm_iommu.c +++ b/drivers/iommu/msm_iommu.c @@ -482,23 +482,19 @@ static size_t msm_iommu_unmap(struct iommu_domain *domain, unsigned long va,  	priv = domain->priv; -	if (!priv) { -		ret = -ENODEV; +	if (!priv)  		goto fail; -	}  	fl_table = priv->pgtable;  	if (len != SZ_16M && len != SZ_1M &&  	    len != SZ_64K && len != SZ_4K) {  		pr_debug("Bad length: %d\n", len); -		ret = -EINVAL;  		goto fail;  	}  	if (!fl_table) {  		pr_debug("Null page table\n"); -		ret = -EINVAL;  		goto fail;  	} @@ -507,7 +503,6 @@ static size_t msm_iommu_unmap(struct iommu_domain *domain, unsigned long va,  	if (*fl_pte == 0) {  		pr_debug("First level PTE is 0\n"); -		ret = -ENODEV;  		goto fail;  	} diff --git a/drivers/isdn/i4l/isdn_net.c b/drivers/isdn/i4l/isdn_net.c index 2339d7396b9..802ab87a78b 100644 --- a/drivers/isdn/i4l/isdn_net.c +++ b/drivers/isdn/i4l/isdn_net.c @@ -1901,7 +1901,7 @@ static int isdn_net_header(struct sk_buff *skb, struct net_device *dev,  {  	isdn_net_local *lp = netdev_priv(dev);  	unsigned char *p; -	ushort len = 0; +	int len = 0;  	switch (lp->p_encap) {  		case ISDN_NET_ENCAP_ETHER: diff --git a/drivers/leds/leds-lm3530.c b/drivers/leds/leds-lm3530.c index 45e6878d737..e59c166a0ce 100644 --- a/drivers/leds/leds-lm3530.c +++ b/drivers/leds/leds-lm3530.c @@ -164,8 +164,8 @@ static int lm3530_init_registers(struct lm3530_data *drvdata)  	if (drvdata->mode == LM3530_BL_MODE_ALS) {  		if (pltfm->als_vmax == 0) { -			pltfm->als_vmin = als_vmin = 0; -			pltfm->als_vmin = als_vmax = LM3530_ALS_WINDOW_mV; +			pltfm->als_vmin = 0; +			pltfm->als_vmax = LM3530_ALS_WINDOW_mV;  		}  		als_vmin = pltfm->als_vmin; diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c index c2907d836e4..86cb7e5d83d 100644 --- a/drivers/md/dm-raid.c +++ b/drivers/md/dm-raid.c @@ -56,7 +56,8 @@ struct raid_dev {  struct raid_set {  	struct dm_target *ti; -	uint64_t print_flags; +	uint32_t bitmap_loaded; +	uint32_t print_flags;  	struct mddev md;  	struct raid_type *raid_type; @@ -1085,7 +1086,7 @@ static int raid_status(struct dm_target *ti, status_type_t type,  				raid_param_cnt += 2;  		} -		raid_param_cnt += (hweight64(rs->print_flags & ~DMPF_REBUILD) * 2); +		raid_param_cnt += (hweight32(rs->print_flags & ~DMPF_REBUILD) * 2);  		if (rs->print_flags & (DMPF_SYNC | DMPF_NOSYNC))  			raid_param_cnt--; @@ -1197,7 +1198,12 @@ static void raid_resume(struct dm_target *ti)  {  	struct raid_set *rs = ti->private; -	bitmap_load(&rs->md); +	if (!rs->bitmap_loaded) { +		bitmap_load(&rs->md); +		rs->bitmap_loaded = 1; +	} else +		md_wakeup_thread(rs->md.thread); +  	mddev_resume(&rs->md);  } diff --git a/drivers/md/md.c b/drivers/md/md.c index 9417ae2fa0b..ce88755baf4 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -7333,7 +7333,8 @@ void md_do_sync(struct mddev *mddev)  					printk(KERN_INFO  					       "md: checkpointing %s of %s.\n",  					       desc, mdname(mddev)); -					mddev->recovery_cp = mddev->curr_resync; +					mddev->recovery_cp = +						mddev->curr_resync_completed;  				}  			} else  				mddev->recovery_cp = MaxSector; @@ -7351,9 +7352,9 @@ void md_do_sync(struct mddev *mddev)  			rcu_read_unlock();  		}  	} + skip:  	set_bit(MD_CHANGE_DEVS, &mddev->flags); - skip:  	if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery)) {  		/* We completed so min/max setting can be forgotten if used. */  		if (test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index cd13e9f2f5e..1489c3540f9 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -200,7 +200,8 @@ config MENELAUS  config TWL4030_CORE  	bool "Texas Instruments TWL4030/TWL5030/TWL6030/TPS659x0 Support" -	depends on I2C=y && GENERIC_HARDIRQS && IRQ_DOMAIN +	depends on I2C=y && GENERIC_HARDIRQS +	select IRQ_DOMAIN  	help  	  Say yes here if you have TWL4030 / TWL6030 family chip on your board.  	  This core driver provides register access and IRQ handling diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c index e04e04ddc15..4970d43952d 100644 --- a/drivers/mfd/twl-core.c +++ b/drivers/mfd/twl-core.c @@ -149,7 +149,7 @@  #define TWL_MODULE_LAST TWL4030_MODULE_LAST -#define TWL4030_NR_IRQS    8 +#define TWL4030_NR_IRQS    34 /* core:8, power:8, gpio: 18 */  #define TWL6030_NR_IRQS    20  /* Base Address defns for twl4030_map[] */ @@ -263,8 +263,6 @@ struct twl_client {  static struct twl_client twl_modules[TWL_NUM_SLAVES]; -static struct irq_domain domain; -  /* mapping the module id to slave id and base address */  struct twl_mapping {  	unsigned char sid;	/* Slave ID */ @@ -1225,14 +1223,8 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)  	pdata->irq_base = status;  	pdata->irq_end = pdata->irq_base + nr_irqs; - -	domain.irq_base = pdata->irq_base; -	domain.nr_irq = nr_irqs; -#ifdef CONFIG_OF_IRQ -	domain.of_node = of_node_get(node); -	domain.ops = &irq_domain_simple_ops; -#endif -	irq_domain_add(&domain); +	irq_domain_add_legacy(node, nr_irqs, pdata->irq_base, 0, +			      &irq_domain_simple_ops, NULL);  	if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C) == 0) {  		dev_dbg(&client->dev, "can't talk I2C?\n"); @@ -1313,11 +1305,10 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)  		twl_i2c_write_u8(TWL4030_MODULE_INTBR, temp, REG_GPPUPDCTR1);  	} -#ifdef CONFIG_OF_DEVICE +	status = -ENODEV;  	if (node)  		status = of_platform_populate(node, NULL, NULL, &client->dev); -	else -#endif +	if (status)  		status = add_children(pdata, id->driver_data);  fail: diff --git a/drivers/mfd/twl4030-power.c b/drivers/mfd/twl4030-power.c index d905f517115..79ca33dfacc 100644 --- a/drivers/mfd/twl4030-power.c +++ b/drivers/mfd/twl4030-power.c @@ -124,7 +124,7 @@ static u8 res_config_addrs[] = {  	[RES_MAIN_REF]	= 0x94,  }; -static int __init twl4030_write_script_byte(u8 address, u8 byte) +static int __devinit twl4030_write_script_byte(u8 address, u8 byte)  {  	int err; @@ -138,7 +138,7 @@ out:  	return err;  } -static int __init twl4030_write_script_ins(u8 address, u16 pmb_message, +static int __devinit twl4030_write_script_ins(u8 address, u16 pmb_message,  					   u8 delay, u8 next)  {  	int err; @@ -158,7 +158,7 @@ out:  	return err;  } -static int __init twl4030_write_script(u8 address, struct twl4030_ins *script, +static int __devinit twl4030_write_script(u8 address, struct twl4030_ins *script,  				       int len)  {  	int err; @@ -183,7 +183,7 @@ static int __init twl4030_write_script(u8 address, struct twl4030_ins *script,  	return err;  } -static int __init twl4030_config_wakeup3_sequence(u8 address) +static int __devinit twl4030_config_wakeup3_sequence(u8 address)  {  	int err;  	u8 data; @@ -208,7 +208,7 @@ out:  	return err;  } -static int __init twl4030_config_wakeup12_sequence(u8 address) +static int __devinit twl4030_config_wakeup12_sequence(u8 address)  {  	int err = 0;  	u8 data; @@ -262,7 +262,7 @@ out:  	return err;  } -static int __init twl4030_config_sleep_sequence(u8 address) +static int __devinit twl4030_config_sleep_sequence(u8 address)  {  	int err; @@ -276,7 +276,7 @@ static int __init twl4030_config_sleep_sequence(u8 address)  	return err;  } -static int __init twl4030_config_warmreset_sequence(u8 address) +static int __devinit twl4030_config_warmreset_sequence(u8 address)  {  	int err;  	u8 rd_data; @@ -324,7 +324,7 @@ out:  	return err;  } -static int __init twl4030_configure_resource(struct twl4030_resconfig *rconfig) +static int __devinit twl4030_configure_resource(struct twl4030_resconfig *rconfig)  {  	int rconfig_addr;  	int err; @@ -416,7 +416,7 @@ static int __init twl4030_configure_resource(struct twl4030_resconfig *rconfig)  	return 0;  } -static int __init load_twl4030_script(struct twl4030_script *tscript, +static int __devinit load_twl4030_script(struct twl4030_script *tscript,  	       u8 address)  {  	int err; @@ -527,7 +527,7 @@ void twl4030_power_off(void)  		pr_err("TWL4030 Unable to power off\n");  } -void __init twl4030_power_init(struct twl4030_power_data *twl4030_scripts) +void __devinit twl4030_power_init(struct twl4030_power_data *twl4030_scripts)  {  	int err = 0;  	int i; diff --git a/drivers/mfd/twl6040-core.c b/drivers/mfd/twl6040-core.c index dda86293dc9..b2d8e512d3c 100644 --- a/drivers/mfd/twl6040-core.c +++ b/drivers/mfd/twl6040-core.c @@ -282,6 +282,7 @@ int twl6040_power(struct twl6040 *twl6040, int on)  		/* Default PLL configuration after power up */  		twl6040->pll = TWL6040_SYSCLK_SEL_LPPLL;  		twl6040->sysclk = 19200000; +		twl6040->mclk = 32768;  	} else {  		/* already powered-down */  		if (!twl6040->power_count) { @@ -305,6 +306,7 @@ int twl6040_power(struct twl6040 *twl6040, int on)  			twl6040_power_down(twl6040);  		}  		twl6040->sysclk = 0; +		twl6040->mclk = 0;  	}  out: @@ -324,23 +326,38 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id,  	hppllctl = twl6040_reg_read(twl6040, TWL6040_REG_HPPLLCTL);  	lppllctl = twl6040_reg_read(twl6040, TWL6040_REG_LPPLLCTL); +	/* Force full reconfiguration when switching between PLL */ +	if (pll_id != twl6040->pll) { +		twl6040->sysclk = 0; +		twl6040->mclk = 0; +	} +  	switch (pll_id) {  	case TWL6040_SYSCLK_SEL_LPPLL:  		/* low-power PLL divider */ -		switch (freq_out) { -		case 17640000: -			lppllctl |= TWL6040_LPLLFIN; -			break; -		case 19200000: -			lppllctl &= ~TWL6040_LPLLFIN; -			break; -		default: -			dev_err(twl6040->dev, -				"freq_out %d not supported\n", freq_out); -			ret = -EINVAL; -			goto pll_out; +		/* Change the sysclk configuration only if it has been canged */ +		if (twl6040->sysclk != freq_out) { +			switch (freq_out) { +			case 17640000: +				lppllctl |= TWL6040_LPLLFIN; +				break; +			case 19200000: +				lppllctl &= ~TWL6040_LPLLFIN; +				break; +			default: +				dev_err(twl6040->dev, +					"freq_out %d not supported\n", +					freq_out); +				ret = -EINVAL; +				goto pll_out; +			} +			twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, +					  lppllctl);  		} -		twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl); + +		/* The PLL in use has not been change, we can exit */ +		if (twl6040->pll == pll_id) +			break;  		switch (freq_in) {  		case 32768: @@ -371,48 +388,56 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id,  			goto pll_out;  		} -		hppllctl &= ~TWL6040_MCLK_MSK; +		if (twl6040->mclk != freq_in) { +			hppllctl &= ~TWL6040_MCLK_MSK; + +			switch (freq_in) { +			case 12000000: +				/* PLL enabled, active mode */ +				hppllctl |= TWL6040_MCLK_12000KHZ | +					    TWL6040_HPLLENA; +				break; +			case 19200000: +				/* +				* PLL disabled +				* (enable PLL if MCLK jitter quality +				*  doesn't meet specification) +				*/ +				hppllctl |= TWL6040_MCLK_19200KHZ; +				break; +			case 26000000: +				/* PLL enabled, active mode */ +				hppllctl |= TWL6040_MCLK_26000KHZ | +					    TWL6040_HPLLENA; +				break; +			case 38400000: +				/* PLL enabled, active mode */ +				hppllctl |= TWL6040_MCLK_38400KHZ | +					    TWL6040_HPLLENA; +				break; +			default: +				dev_err(twl6040->dev, +					"freq_in %d not supported\n", freq_in); +				ret = -EINVAL; +				goto pll_out; +			} -		switch (freq_in) { -		case 12000000: -			/* PLL enabled, active mode */ -			hppllctl |= TWL6040_MCLK_12000KHZ | -				    TWL6040_HPLLENA; -			break; -		case 19200000:  			/* -			 * PLL disabled -			 * (enable PLL if MCLK jitter quality -			 *  doesn't meet specification) +			 * enable clock slicer to ensure input waveform is +			 * square  			 */ -			hppllctl |= TWL6040_MCLK_19200KHZ; -			break; -		case 26000000: -			/* PLL enabled, active mode */ -			hppllctl |= TWL6040_MCLK_26000KHZ | -				    TWL6040_HPLLENA; -			break; -		case 38400000: -			/* PLL enabled, active mode */ -			hppllctl |= TWL6040_MCLK_38400KHZ | -				    TWL6040_HPLLENA; -			break; -		default: -			dev_err(twl6040->dev, -				"freq_in %d not supported\n", freq_in); -			ret = -EINVAL; -			goto pll_out; -		} +			hppllctl |= TWL6040_HPLLSQRENA; -		/* enable clock slicer to ensure input waveform is square */ -		hppllctl |= TWL6040_HPLLSQRENA; - -		twl6040_reg_write(twl6040, TWL6040_REG_HPPLLCTL, hppllctl); -		usleep_range(500, 700); -		lppllctl |= TWL6040_HPLLSEL; -		twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl); -		lppllctl &= ~TWL6040_LPLLENA; -		twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, lppllctl); +			twl6040_reg_write(twl6040, TWL6040_REG_HPPLLCTL, +					  hppllctl); +			usleep_range(500, 700); +			lppllctl |= TWL6040_HPLLSEL; +			twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, +					  lppllctl); +			lppllctl &= ~TWL6040_LPLLENA; +			twl6040_reg_write(twl6040, TWL6040_REG_LPPLLCTL, +					  lppllctl); +		}  		break;  	default:  		dev_err(twl6040->dev, "unknown pll id %d\n", pll_id); @@ -421,6 +446,7 @@ int twl6040_set_pll(struct twl6040 *twl6040, int pll_id,  	}  	twl6040->sysclk = freq_out; +	twl6040->mclk = freq_in;  	twl6040->pll = pll_id;  pll_out: diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 6a1a092db14..c7795096d43 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -2,24 +2,14 @@  # Misc strange devices  # -# This one has to live outside of the MISC_DEVICES conditional, -# because it may be selected by drivers/platform/x86/hp_accel. +menu "Misc devices" +  config SENSORS_LIS3LV02D  	tristate  	depends on INPUT  	select INPUT_POLLDEV  	default n -menuconfig MISC_DEVICES -	bool "Misc devices" -	---help--- -	  Say Y here to get to see options for device drivers from various -	  different categories. This option alone does not add any kernel code. - -	  If you say N, all options in this submenu will be skipped and disabled. - -if MISC_DEVICES -  config AD525X_DPOT  	tristate "Analog Devices Digital Potentiometers"  	depends on (I2C || SPI) && SYSFS @@ -516,5 +506,4 @@ source "drivers/misc/ti-st/Kconfig"  source "drivers/misc/lis3lv02d/Kconfig"  source "drivers/misc/carma/Kconfig"  source "drivers/misc/altera-stapl/Kconfig" - -endif # MISC_DEVICES +endmenu diff --git a/drivers/misc/c2port/c2port-duramar2150.c b/drivers/misc/c2port/c2port-duramar2150.c index 778fc3fdfb9..5484301d57d 100644 --- a/drivers/misc/c2port/c2port-duramar2150.c +++ b/drivers/misc/c2port/c2port-duramar2150.c @@ -15,6 +15,7 @@  #include <linux/module.h>  #include <linux/delay.h>  #include <linux/io.h> +#include <linux/ioport.h>  #include <linux/c2port.h>  #define DATA_PORT	0x325 diff --git a/drivers/misc/cb710/core.c b/drivers/misc/cb710/core.c index 68cd05b6d82..85cc7710193 100644 --- a/drivers/misc/cb710/core.c +++ b/drivers/misc/cb710/core.c @@ -245,6 +245,7 @@ static int __devinit cb710_probe(struct pci_dev *pdev,  	if (err)  		return err; +	spin_lock_init(&chip->irq_lock);  	chip->pdev = pdev;  	chip->iobase = pcim_iomap_table(pdev)[0]; diff --git a/drivers/misc/cs5535-mfgpt.c b/drivers/misc/cs5535-mfgpt.c index bc685bfc4c3..87a390de054 100644 --- a/drivers/misc/cs5535-mfgpt.c +++ b/drivers/misc/cs5535-mfgpt.c @@ -262,7 +262,7 @@ static void __init reset_all_timers(void)   * In other cases (such as with VSAless OpenFirmware), the system firmware   * leaves timers available for us to use.   */ -static int __init scan_timers(struct cs5535_mfgpt_chip *mfgpt) +static int __devinit scan_timers(struct cs5535_mfgpt_chip *mfgpt)  {  	struct cs5535_mfgpt_timer timer = { .chip = mfgpt };  	unsigned long flags; diff --git a/drivers/misc/lkdtm.c b/drivers/misc/lkdtm.c index 150cd7061b8..28adefe70f9 100644 --- a/drivers/misc/lkdtm.c +++ b/drivers/misc/lkdtm.c @@ -354,6 +354,7 @@ static void lkdtm_do_action(enum ctype which)  static void lkdtm_handler(void)  {  	unsigned long flags; +	bool do_it = false;  	spin_lock_irqsave(&count_lock, flags);  	count--; @@ -361,10 +362,13 @@ static void lkdtm_handler(void)  			cp_name_to_str(cpoint), cp_type_to_str(cptype), count);  	if (count == 0) { -		lkdtm_do_action(cptype); +		do_it = true;  		count = cpoint_count;  	}  	spin_unlock_irqrestore(&count_lock, flags); + +	if (do_it) +		lkdtm_do_action(cptype);  }  static int lkdtm_register_cpoint(enum cname which) diff --git a/drivers/misc/vmw_balloon.c b/drivers/misc/vmw_balloon.c index cd41d403c9d..cb56e270da1 100644 --- a/drivers/misc/vmw_balloon.c +++ b/drivers/misc/vmw_balloon.c @@ -314,7 +314,7 @@ static bool vmballoon_send_get_target(struct vmballoon *b, u32 *new_target)   * fear that guest will need it. Host may reject some pages, we need to   * check the return value and maybe submit a different page.   */ -static bool vmballoon_send_lock_page(struct vmballoon *b, unsigned long pfn, +static int vmballoon_send_lock_page(struct vmballoon *b, unsigned long pfn,  				     unsigned int *hv_status)  {  	unsigned long status, dummy; @@ -322,17 +322,17 @@ static bool vmballoon_send_lock_page(struct vmballoon *b, unsigned long pfn,  	pfn32 = (u32)pfn;  	if (pfn32 != pfn) -		return false; +		return -1;  	STATS_INC(b->stats.lock);  	*hv_status = status = VMWARE_BALLOON_CMD(LOCK, pfn, dummy);  	if (vmballoon_check_status(b, status)) -		return true; +		return 0;  	pr_debug("%s - ppn %lx, hv returns %ld\n", __func__, pfn, status);  	STATS_INC(b->stats.lock_fail); -	return false; +	return 1;  }  /* @@ -411,7 +411,7 @@ static int vmballoon_reserve_page(struct vmballoon *b, bool can_sleep)  	struct page *page;  	gfp_t flags;  	unsigned int hv_status; -	bool locked = false; +	int locked;  	flags = can_sleep ? VMW_PAGE_ALLOC_CANSLEEP : VMW_PAGE_ALLOC_NOSLEEP;  	do { @@ -431,7 +431,7 @@ static int vmballoon_reserve_page(struct vmballoon *b, bool can_sleep)  		/* inform monitor */  		locked = vmballoon_send_lock_page(b, page_to_pfn(page), &hv_status); -		if (!locked) { +		if (locked > 0) {  			STATS_INC(b->stats.refused_alloc);  			if (hv_status == VMW_BALLOON_ERROR_RESET || @@ -449,7 +449,7 @@ static int vmballoon_reserve_page(struct vmballoon *b, bool can_sleep)  			if (++b->n_refused_pages >= VMW_BALLOON_MAX_REFUSED)  				return -EIO;  		} -	} while (!locked); +	} while (locked != 0);  	/* track allocated page */  	list_add(&page->lru, &b->pages); diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index cf444b0ca2c..00fcbed1afd 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -477,7 +477,6 @@ config MMC_SDHI  config MMC_CB710  	tristate "ENE CB710 MMC/SD Interface support"  	depends on PCI -	select MISC_DEVICES  	select CB710_CORE  	help  	  This option enables support for MMC/SD part of ENE CB710/720 Flash diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index 6ae9ca01388..9a9ce71a71f 100644 --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c @@ -119,7 +119,7 @@ static int mtd_cls_suspend(struct device *dev, pm_message_t state)  {  	struct mtd_info *mtd = dev_get_drvdata(dev); -	return mtd_suspend(mtd); +	return mtd ? mtd_suspend(mtd) : 0;  }  static int mtd_cls_resume(struct device *dev) diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index 4dd056e2e16..35b4fb55dbd 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c @@ -161,6 +161,37 @@ static int atmel_nand_device_ready(struct mtd_info *mtd)                  !!host->board->rdy_pin_active_low;  } +/* + * Minimal-overhead PIO for data access. + */ +static void atmel_read_buf8(struct mtd_info *mtd, u8 *buf, int len) +{ +	struct nand_chip	*nand_chip = mtd->priv; + +	__raw_readsb(nand_chip->IO_ADDR_R, buf, len); +} + +static void atmel_read_buf16(struct mtd_info *mtd, u8 *buf, int len) +{ +	struct nand_chip	*nand_chip = mtd->priv; + +	__raw_readsw(nand_chip->IO_ADDR_R, buf, len / 2); +} + +static void atmel_write_buf8(struct mtd_info *mtd, const u8 *buf, int len) +{ +	struct nand_chip	*nand_chip = mtd->priv; + +	__raw_writesb(nand_chip->IO_ADDR_W, buf, len); +} + +static void atmel_write_buf16(struct mtd_info *mtd, const u8 *buf, int len) +{ +	struct nand_chip	*nand_chip = mtd->priv; + +	__raw_writesw(nand_chip->IO_ADDR_W, buf, len / 2); +} +  static void dma_complete_func(void *completion)  {  	complete(completion); @@ -235,27 +266,33 @@ err_buf:  static void atmel_read_buf(struct mtd_info *mtd, u8 *buf, int len)  {  	struct nand_chip *chip = mtd->priv; +	struct atmel_nand_host *host = chip->priv;  	if (use_dma && len > mtd->oobsize)  		/* only use DMA for bigger than oob size: better performances */  		if (atmel_nand_dma_op(mtd, buf, len, 1) == 0)  			return; -	/* if no DMA operation possible, use PIO */ -	memcpy_fromio(buf, chip->IO_ADDR_R, len); +	if (host->board->bus_width_16) +		atmel_read_buf16(mtd, buf, len); +	else +		atmel_read_buf8(mtd, buf, len);  }  static void atmel_write_buf(struct mtd_info *mtd, const u8 *buf, int len)  {  	struct nand_chip *chip = mtd->priv; +	struct atmel_nand_host *host = chip->priv;  	if (use_dma && len > mtd->oobsize)  		/* only use DMA for bigger than oob size: better performances */  		if (atmel_nand_dma_op(mtd, (void *)buf, len, 0) == 0)  			return; -	/* if no DMA operation possible, use PIO */ -	memcpy_toio(chip->IO_ADDR_W, buf, len); +	if (host->board->bus_width_16) +		atmel_write_buf16(mtd, buf, len); +	else +		atmel_write_buf8(mtd, buf, len);  }  /* diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c index 7f680420bfa..7db6555ed3b 100644 --- a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c +++ b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c @@ -69,17 +69,19 @@ static int clear_poll_bit(void __iomem *addr, u32 mask)   *  [1] enable the module.   *  [2] reset the module.   * - * In most of the cases, it's ok. But there is a hardware bug in the BCH block. + * In most of the cases, it's ok. + * But in MX23, there is a hardware bug in the BCH block (see erratum #2847).   * If you try to soft reset the BCH block, it becomes unusable until   * the next hard reset. This case occurs in the NAND boot mode. When the board   * boots by NAND, the ROM of the chip will initialize the BCH blocks itself.   * So If the driver tries to reset the BCH again, the BCH will not work anymore. - * You will see a DMA timeout in this case. + * You will see a DMA timeout in this case. The bug has been fixed + * in the following chips, such as MX28.   *   * To avoid this bug, just add a new parameter `just_enable` for   * the mxs_reset_block(), and rewrite it here.   */ -int gpmi_reset_block(void __iomem *reset_addr, bool just_enable) +static int gpmi_reset_block(void __iomem *reset_addr, bool just_enable)  {  	int ret;  	int timeout = 0x400; @@ -206,7 +208,15 @@ int bch_set_geometry(struct gpmi_nand_data *this)  	if (ret)  		goto err_out; -	ret = gpmi_reset_block(r->bch_regs, true); +	/* +	* Due to erratum #2847 of the MX23, the BCH cannot be soft reset on this +	* chip, otherwise it will lock up. So we skip resetting BCH on the MX23. +	* On the other hand, the MX28 needs the reset, because one case has been +	* seen where the BCH produced ECC errors constantly after 10000 +	* consecutive reboots. The latter case has not been seen on the MX23 yet, +	* still we don't know if it could happen there as well. +	*/ +	ret = gpmi_reset_block(r->bch_regs, GPMI_IS_MX23(this));  	if (ret)  		goto err_out; diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 35b4565050f..8a393f9e602 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -2588,7 +2588,7 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,  	instr->state = MTD_ERASING;  	while (len) { -		/* Heck if we have a bad block, we do not erase bad blocks! */ +		/* Check if we have a bad block, we do not erase bad blocks! */  		if (nand_block_checkbad(mtd, ((loff_t) page) <<  					chip->page_shift, 0, allowbbt)) {  			pr_warn("%s: attempt to erase a bad block at page 0x%08x\n", diff --git a/drivers/net/can/cc770/cc770.c b/drivers/net/can/cc770/cc770.c index 76689674764..c30f0e6f104 100644 --- a/drivers/net/can/cc770/cc770.c +++ b/drivers/net/can/cc770/cc770.c @@ -440,12 +440,14 @@ static netdev_tx_t cc770_start_xmit(struct sk_buff *skb, struct net_device *dev)  	for (i = 0; i < dlc; i++)  		cc770_write_reg(priv, msgobj[mo].data[i], cf->data[i]); +	/* Store echo skb before starting the transfer */ +	can_put_echo_skb(skb, dev, 0); +  	cc770_write_reg(priv, msgobj[mo].ctrl1,  			RMTPND_RES | TXRQST_SET | CPUUPD_RES | NEWDAT_UNC);  	stats->tx_bytes += dlc; -	can_put_echo_skb(skb, dev, 0);  	/*  	 * HM: We had some cases of repeated IRQs so make sure the diff --git a/drivers/net/can/cc770/cc770_isa.c b/drivers/net/can/cc770/cc770_isa.c index 4be5fe2c40a..9f3a25ccd66 100644 --- a/drivers/net/can/cc770/cc770_isa.c +++ b/drivers/net/can/cc770/cc770_isa.c @@ -110,6 +110,11 @@ MODULE_PARM_DESC(bcr, "Bus configuration register (default=0x40 [CBY])");  #define CC770_IOSIZE          0x20  #define CC770_IOSIZE_INDIRECT 0x02 +/* Spinlock for cc770_isa_port_write_reg_indirect + * and cc770_isa_port_read_reg_indirect + */ +static DEFINE_SPINLOCK(cc770_isa_port_lock); +  static struct platform_device *cc770_isa_devs[MAXDEV];  static u8 cc770_isa_mem_read_reg(const struct cc770_priv *priv, int reg) @@ -138,18 +143,27 @@ static u8 cc770_isa_port_read_reg_indirect(const struct cc770_priv *priv,  					     int reg)  {  	unsigned long base = (unsigned long)priv->reg_base; +	unsigned long flags; +	u8 val; +	spin_lock_irqsave(&cc770_isa_port_lock, flags);  	outb(reg, base); -	return inb(base + 1); +	val = inb(base + 1); +	spin_unlock_irqrestore(&cc770_isa_port_lock, flags); + +	return val;  }  static void cc770_isa_port_write_reg_indirect(const struct cc770_priv *priv,  						int reg, u8 val)  {  	unsigned long base = (unsigned long)priv->reg_base; +	unsigned long flags; +	spin_lock_irqsave(&cc770_isa_port_lock, flags);  	outb(reg, base);  	outb(val, base + 1); +	spin_unlock_irqrestore(&cc770_isa_port_lock, flags);  }  static int __devinit cc770_isa_probe(struct platform_device *pdev) diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index 7fd8089946f..96d235799ec 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c @@ -118,6 +118,9 @@  	(FLEXCAN_ESR_TWRN_INT | FLEXCAN_ESR_RWRN_INT | FLEXCAN_ESR_BOFF_INT)  #define FLEXCAN_ESR_ERR_ALL \  	(FLEXCAN_ESR_ERR_BUS | FLEXCAN_ESR_ERR_STATE) +#define FLEXCAN_ESR_ALL_INT \ +	(FLEXCAN_ESR_TWRN_INT | FLEXCAN_ESR_RWRN_INT | \ +	 FLEXCAN_ESR_BOFF_INT | FLEXCAN_ESR_ERR_INT)  /* FLEXCAN interrupt flag register (IFLAG) bits */  #define FLEXCAN_TX_BUF_ID		8 @@ -577,7 +580,9 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)  	reg_iflag1 = flexcan_read(®s->iflag1);  	reg_esr = flexcan_read(®s->esr); -	flexcan_write(FLEXCAN_ESR_ERR_INT, ®s->esr);	/* ACK err IRQ */ +	/* ACK all bus error and state change IRQ sources */ +	if (reg_esr & FLEXCAN_ESR_ALL_INT) +		flexcan_write(reg_esr & FLEXCAN_ESR_ALL_INT, ®s->esr);  	/*  	 * schedule NAPI in case of: diff --git a/drivers/net/can/pch_can.c b/drivers/net/can/pch_can.c index d11fbb2b95f..6edc25e0dd1 100644 --- a/drivers/net/can/pch_can.c +++ b/drivers/net/can/pch_can.c @@ -66,6 +66,7 @@  #define PCH_IF_CREQ_BUSY	BIT(15)  #define PCH_STATUS_INT		0x8000 +#define PCH_RP			0x00008000  #define PCH_REC			0x00007f00  #define PCH_TEC			0x000000ff @@ -527,7 +528,7 @@ static void pch_can_error(struct net_device *ndev, u32 status)  		priv->can.can_stats.error_passive++;  		state = CAN_STATE_ERROR_PASSIVE;  		cf->can_id |= CAN_ERR_CRTL; -		if (((errc & PCH_REC) >> 8) > 127) +		if (errc & PCH_RP)  			cf->data[1] |= CAN_ERR_CRTL_RX_PASSIVE;  		if ((errc & PCH_TEC) > 127)  			cf->data[1] |= CAN_ERR_CRTL_TX_PASSIVE; diff --git a/drivers/net/can/sja1000/peak_pci.c b/drivers/net/can/sja1000/peak_pci.c index 2c7f5036f57..214795945bc 100644 --- a/drivers/net/can/sja1000/peak_pci.c +++ b/drivers/net/can/sja1000/peak_pci.c @@ -39,9 +39,9 @@ MODULE_LICENSE("GPL v2");  #define DRV_NAME  "peak_pci"  struct peak_pci_chan { -	void __iomem *cfg_base;	     /* Common for all channels */ -	struct net_device *next_dev; /* Chain of network devices */ -	u16 icr_mask;		     /* Interrupt mask for fast ack */ +	void __iomem *cfg_base;		/* Common for all channels */ +	struct net_device *prev_dev;	/* Chain of network devices */ +	u16 icr_mask;			/* Interrupt mask for fast ack */  };  #define PEAK_PCI_CAN_CLOCK	(16000000 / 2) @@ -98,7 +98,7 @@ static int __devinit peak_pci_probe(struct pci_dev *pdev,  {  	struct sja1000_priv *priv;  	struct peak_pci_chan *chan; -	struct net_device *dev, *dev0 = NULL; +	struct net_device *dev;  	void __iomem *cfg_base, *reg_base;  	u16 sub_sys_id, icr;  	int i, err, channels; @@ -196,18 +196,14 @@ static int __devinit peak_pci_probe(struct pci_dev *pdev,  		}  		/* Create chain of SJA1000 devices */ -		if (i == 0) -			dev0 = dev; -		else -			chan->next_dev = dev; +		chan->prev_dev = pci_get_drvdata(pdev); +		pci_set_drvdata(pdev, dev);  		dev_info(&pdev->dev,  			 "%s at reg_base=0x%p cfg_base=0x%p irq=%d\n",  			 dev->name, priv->reg_base, chan->cfg_base, dev->irq);  	} -	pci_set_drvdata(pdev, dev0); -  	/* Enable interrupts */  	writew(icr, cfg_base + PITA_ICR + 2); @@ -217,12 +213,11 @@ failure_remove_channels:  	/* Disable interrupts */  	writew(0x0, cfg_base + PITA_ICR + 2); -	for (dev = dev0; dev; dev = chan->next_dev) { +	for (dev = pci_get_drvdata(pdev); dev; dev = chan->prev_dev) {  		unregister_sja1000dev(dev);  		free_sja1000dev(dev);  		priv = netdev_priv(dev);  		chan = priv->priv; -		dev = chan->next_dev;  	}  	pci_iounmap(pdev, reg_base); @@ -241,7 +236,7 @@ failure_disable_pci:  static void __devexit peak_pci_remove(struct pci_dev *pdev)  { -	struct net_device *dev = pci_get_drvdata(pdev); /* First device */ +	struct net_device *dev = pci_get_drvdata(pdev); /* Last device */  	struct sja1000_priv *priv = netdev_priv(dev);  	struct peak_pci_chan *chan = priv->priv;  	void __iomem *cfg_base = chan->cfg_base; @@ -255,7 +250,7 @@ static void __devexit peak_pci_remove(struct pci_dev *pdev)  		dev_info(&pdev->dev, "removing device %s\n", dev->name);  		unregister_sja1000dev(dev);  		free_sja1000dev(dev); -		dev = chan->next_dev; +		dev = chan->prev_dev;  		if (!dev)  			break;  		priv = netdev_priv(dev); diff --git a/drivers/net/can/ti_hecc.c b/drivers/net/can/ti_hecc.c index df809e3f130..5a2e1e3588a 100644 --- a/drivers/net/can/ti_hecc.c +++ b/drivers/net/can/ti_hecc.c @@ -745,9 +745,10 @@ static int ti_hecc_error(struct net_device *ndev, int int_status,  		}  	} -	netif_receive_skb(skb); +	netif_rx(skb);  	stats->rx_packets++;  	stats->rx_bytes += cf->can_dlc; +  	return 0;  } diff --git a/drivers/net/can/usb/ems_usb.c b/drivers/net/can/usb/ems_usb.c index 9697c14b8dc..7dae64d44e8 100644 --- a/drivers/net/can/usb/ems_usb.c +++ b/drivers/net/can/usb/ems_usb.c @@ -627,9 +627,6 @@ static int ems_usb_start(struct ems_usb *dev)  		err = usb_submit_urb(urb, GFP_KERNEL);  		if (err) { -			if (err == -ENODEV) -				netif_device_detach(dev->netdev); -  			usb_unanchor_urb(urb);  			usb_free_coherent(dev->udev, RX_BUFFER_SIZE, buf,  					  urb->transfer_dma); @@ -659,9 +656,6 @@ static int ems_usb_start(struct ems_usb *dev)  	err = usb_submit_urb(dev->intr_urb, GFP_KERNEL);  	if (err) { -		if (err == -ENODEV) -			netif_device_detach(dev->netdev); -  		dev_warn(netdev->dev.parent, "intr URB submit failed: %d\n",  			 err); @@ -692,9 +686,6 @@ static int ems_usb_start(struct ems_usb *dev)  	return 0;  failed: -	if (err == -ENODEV) -		netif_device_detach(dev->netdev); -  	dev_warn(netdev->dev.parent, "couldn't submit control: %d\n", err);  	return err; diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index 03f3935fd8c..7aee46983be 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c @@ -523,7 +523,6 @@ static void bnx2x_tpa_stop(struct bnx2x *bp, struct bnx2x_fastpath *fp,  		skb = build_skb(data);  	if (likely(skb)) { -  #ifdef BNX2X_STOP_ON_ERROR  		if (pad + len > fp->rx_buf_size) {  			BNX2X_ERR("skb_put is about to fail...  " @@ -557,7 +556,7 @@ static void bnx2x_tpa_stop(struct bnx2x *bp, struct bnx2x_fastpath *fp,  		return;  	} - +	kfree(new_data);  drop:  	/* drop the packet and keep the buffer in the bin */  	DP(NETIF_MSG_RX_STATUS, diff --git a/drivers/net/ethernet/brocade/bna/bnad_ethtool.c b/drivers/net/ethernet/brocade/bna/bnad_ethtool.c index 9b44ec8096b..803ea32aa99 100644 --- a/drivers/net/ethernet/brocade/bna/bnad_ethtool.c +++ b/drivers/net/ethernet/brocade/bna/bnad_ethtool.c @@ -946,7 +946,7 @@ bnad_get_flash_partition_by_offset(struct bnad *bnad, u32 offset,  	flash_attr = kzalloc(sizeof(struct bfa_flash_attr), GFP_KERNEL);  	if (!flash_attr) -		return -ENOMEM; +		return 0;  	fcomp.bnad = bnad;  	fcomp.comp_status = 0; @@ -958,7 +958,7 @@ bnad_get_flash_partition_by_offset(struct bnad *bnad, u32 offset,  	if (ret != BFA_STATUS_OK) {  		spin_unlock_irqrestore(&bnad->bna_lock, flags);  		kfree(flash_attr); -		goto out_err; +		return 0;  	}  	spin_unlock_irqrestore(&bnad->bna_lock, flags);  	wait_for_completion(&fcomp.comp); @@ -978,8 +978,6 @@ bnad_get_flash_partition_by_offset(struct bnad *bnad, u32 offset,  	}  	kfree(flash_attr);  	return flash_part; -out_err: -	return -EINVAL;  }  static int @@ -1006,7 +1004,7 @@ bnad_get_eeprom(struct net_device *netdev, struct ethtool_eeprom *eeprom,  	/* Query the flash partition based on the offset */  	flash_part = bnad_get_flash_partition_by_offset(bnad,  				eeprom->offset, &base_offset); -	if (flash_part <= 0) +	if (flash_part == 0)  		return -EFAULT;  	fcomp.bnad = bnad; @@ -1048,7 +1046,7 @@ bnad_set_eeprom(struct net_device *netdev, struct ethtool_eeprom *eeprom,  	/* Query the flash partition based on the offset */  	flash_part = bnad_get_flash_partition_by_offset(bnad,  				eeprom->offset, &base_offset); -	if (flash_part <= 0) +	if (flash_part == 0)  		return -EFAULT;  	fcomp.bnad = bnad; diff --git a/drivers/net/ethernet/emulex/benet/be_ethtool.c b/drivers/net/ethernet/emulex/benet/be_ethtool.c index 6db6b6ae5e9..802e5ddef8a 100644 --- a/drivers/net/ethernet/emulex/benet/be_ethtool.c +++ b/drivers/net/ethernet/emulex/benet/be_ethtool.c @@ -716,12 +716,8 @@ static int  be_do_flash(struct net_device *netdev, struct ethtool_flash *efl)  {  	struct be_adapter *adapter = netdev_priv(netdev); -	char file_name[ETHTOOL_FLASH_MAX_FILENAME]; -	file_name[ETHTOOL_FLASH_MAX_FILENAME - 1] = 0; -	strcpy(file_name, efl->data); - -	return be_load_fw(adapter, file_name); +	return be_load_fw(adapter, efl->data);  }  static int diff --git a/drivers/net/ethernet/freescale/fec.c b/drivers/net/ethernet/freescale/fec.c index 7b25e9cf13f..1c7aad8fa19 100644 --- a/drivers/net/ethernet/freescale/fec.c +++ b/drivers/net/ethernet/freescale/fec.c @@ -990,7 +990,7 @@ static int fec_enet_mii_probe(struct net_device *ndev)  		phy_id = 0;  	} -	snprintf(phy_name, MII_BUS_ID_SIZE, PHY_ID_FMT, mdio_bus_id, phy_id); +	snprintf(phy_name, sizeof(phy_name), PHY_ID_FMT, mdio_bus_id, phy_id);  	phy_dev = phy_connect(ndev, phy_name, &fec_enet_adjust_link, 0,  			      fep->phy_interface);  	if (IS_ERR(phy_dev)) { diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c b/drivers/net/ethernet/intel/e1000/e1000_main.c index 669ca3800c0..d94d64b5d69 100644 --- a/drivers/net/ethernet/intel/e1000/e1000_main.c +++ b/drivers/net/ethernet/intel/e1000/e1000_main.c @@ -4740,12 +4740,14 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake)  		e1000_setup_rctl(adapter);  		e1000_set_rx_mode(netdev); +		rctl = er32(RCTL); +  		/* turn on all-multi mode if wake on multicast is enabled */ -		if (wufc & E1000_WUFC_MC) { -			rctl = er32(RCTL); +		if (wufc & E1000_WUFC_MC)  			rctl |= E1000_RCTL_MPE; -			ew32(RCTL, rctl); -		} + +		/* enable receives in the hardware */ +		ew32(RCTL, rctl | E1000_RCTL_EN);  		if (hw->mac_type >= e1000_82540) {  			ctrl = er32(CTRL); diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index e91d73c8aa4..94be6c32fa7 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -5012,7 +5012,8 @@ static int igb_find_enabled_vfs(struct igb_adapter *adapter)  	vf_devfn = pdev->devfn + 0x80;  	pvfdev = pci_get_device(hw->vendor_id, device_id, NULL);  	while (pvfdev) { -		if (pvfdev->devfn == vf_devfn) +		if (pvfdev->devfn == vf_devfn && +		    (pvfdev->bus->number >= pdev->bus->number))  			vfs_found++;  		vf_devfn += vf_stride;  		pvfdev = pci_get_device(hw->vendor_id, diff --git a/drivers/net/ethernet/intel/igbvf/Makefile b/drivers/net/ethernet/intel/igbvf/Makefile index 0fa3db3dd8b..044b0ad5fcb 100644 --- a/drivers/net/ethernet/intel/igbvf/Makefile +++ b/drivers/net/ethernet/intel/igbvf/Makefile @@ -1,7 +1,7 @@  ################################################################################  #  # Intel(R) 82576 Virtual Function Linux driver -# Copyright(c) 2009 - 2010 Intel Corporation. +# Copyright(c) 2009 - 2012 Intel Corporation.  #  # This program is free software; you can redistribute it and/or modify it  # under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ethernet/intel/igbvf/defines.h b/drivers/net/ethernet/intel/igbvf/defines.h index 79f2604673f..33f40d3474a 100644 --- a/drivers/net/ethernet/intel/igbvf/defines.h +++ b/drivers/net/ethernet/intel/igbvf/defines.h @@ -1,7 +1,7 @@  /*******************************************************************************    Intel(R) 82576 Virtual Function Linux driver -  Copyright(c) 1999 - 2010 Intel Corporation. +  Copyright(c) 1999 - 2012 Intel Corporation.    This program is free software; you can redistribute it and/or modify it    under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ethernet/intel/igbvf/ethtool.c b/drivers/net/ethernet/intel/igbvf/ethtool.c index 2dba5344606..db7dce2351c 100644 --- a/drivers/net/ethernet/intel/igbvf/ethtool.c +++ b/drivers/net/ethernet/intel/igbvf/ethtool.c @@ -1,7 +1,7 @@  /*******************************************************************************    Intel(R) 82576 Virtual Function Linux driver -  Copyright(c) 2009 - 2010 Intel Corporation. +  Copyright(c) 2009 - 2012 Intel Corporation.    This program is free software; you can redistribute it and/or modify it    under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ethernet/intel/igbvf/igbvf.h b/drivers/net/ethernet/intel/igbvf/igbvf.h index fd4a7b780fd..2c6d87e4d3d 100644 --- a/drivers/net/ethernet/intel/igbvf/igbvf.h +++ b/drivers/net/ethernet/intel/igbvf/igbvf.h @@ -1,7 +1,7 @@  /*******************************************************************************    Intel(R) 82576 Virtual Function Linux driver -  Copyright(c) 2009 - 2010 Intel Corporation. +  Copyright(c) 2009 - 2012 Intel Corporation.    This program is free software; you can redistribute it and/or modify it    under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ethernet/intel/igbvf/mbx.c b/drivers/net/ethernet/intel/igbvf/mbx.c index 048aae248d0..b4b65bc9fc5 100644 --- a/drivers/net/ethernet/intel/igbvf/mbx.c +++ b/drivers/net/ethernet/intel/igbvf/mbx.c @@ -1,7 +1,7 @@  /*******************************************************************************    Intel(R) 82576 Virtual Function Linux driver -  Copyright(c) 2009 - 2010 Intel Corporation. +  Copyright(c) 2009 - 2012 Intel Corporation.    This program is free software; you can redistribute it and/or modify it    under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ethernet/intel/igbvf/mbx.h b/drivers/net/ethernet/intel/igbvf/mbx.h index c2883c45d47..24370bcb0e2 100644 --- a/drivers/net/ethernet/intel/igbvf/mbx.h +++ b/drivers/net/ethernet/intel/igbvf/mbx.h @@ -1,7 +1,7 @@  /*******************************************************************************    Intel(R) 82576 Virtual Function Linux driver -  Copyright(c) 1999 - 2010 Intel Corporation. +  Copyright(c) 1999 - 2012 Intel Corporation.    This program is free software; you can redistribute it and/or modify it    under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ethernet/intel/igbvf/netdev.c b/drivers/net/ethernet/intel/igbvf/netdev.c index a4b20c86575..4e9141cfe81 100644 --- a/drivers/net/ethernet/intel/igbvf/netdev.c +++ b/drivers/net/ethernet/intel/igbvf/netdev.c @@ -1,7 +1,7 @@  /*******************************************************************************    Intel(R) 82576 Virtual Function Linux driver -  Copyright(c) 2009 - 2010 Intel Corporation. +  Copyright(c) 2009 - 2012 Intel Corporation.    This program is free software; you can redistribute it and/or modify it    under the terms and conditions of the GNU General Public License, @@ -53,7 +53,7 @@ const char igbvf_driver_version[] = DRV_VERSION;  static const char igbvf_driver_string[] =  		  "Intel(R) Gigabit Virtual Function Network Driver";  static const char igbvf_copyright[] = -		  "Copyright (c) 2009 - 2011 Intel Corporation."; +		  "Copyright (c) 2009 - 2012 Intel Corporation.";  static int igbvf_poll(struct napi_struct *napi, int budget);  static void igbvf_reset(struct igbvf_adapter *); diff --git a/drivers/net/ethernet/intel/igbvf/regs.h b/drivers/net/ethernet/intel/igbvf/regs.h index 77e18d3d6b1..7dc6341715d 100644 --- a/drivers/net/ethernet/intel/igbvf/regs.h +++ b/drivers/net/ethernet/intel/igbvf/regs.h @@ -1,7 +1,7 @@  /*******************************************************************************    Intel(R) 82576 Virtual Function Linux driver -  Copyright(c) 2009 - 2010 Intel Corporation. +  Copyright(c) 2009 - 2012 Intel Corporation.    This program is free software; you can redistribute it and/or modify it    under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ethernet/intel/igbvf/vf.c b/drivers/net/ethernet/intel/igbvf/vf.c index af3822f9ea9..19551977b35 100644 --- a/drivers/net/ethernet/intel/igbvf/vf.c +++ b/drivers/net/ethernet/intel/igbvf/vf.c @@ -1,7 +1,7 @@  /*******************************************************************************    Intel(R) 82576 Virtual Function Linux driver -  Copyright(c) 2009 - 2010 Intel Corporation. +  Copyright(c) 2009 - 2012 Intel Corporation.    This program is free software; you can redistribute it and/or modify it    under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ethernet/intel/igbvf/vf.h b/drivers/net/ethernet/intel/igbvf/vf.h index d7ed58fcd9b..57db3c68dfc 100644 --- a/drivers/net/ethernet/intel/igbvf/vf.h +++ b/drivers/net/ethernet/intel/igbvf/vf.h @@ -1,7 +1,7 @@  /*******************************************************************************    Intel(R) 82576 Virtual Function Linux driver -  Copyright(c) 2009 - 2010 Intel Corporation. +  Copyright(c) 2009 - 2012 Intel Corporation.    This program is free software; you can redistribute it and/or modify it    under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ethernet/intel/ixgbe/Makefile b/drivers/net/ethernet/intel/ixgbe/Makefile index 7d7387fbdec..7a16177a12a 100644 --- a/drivers/net/ethernet/intel/ixgbe/Makefile +++ b/drivers/net/ethernet/intel/ixgbe/Makefile @@ -1,7 +1,7 @@  ################################################################################  #  # Intel 10 Gigabit PCI Express Linux driver -# Copyright(c) 1999 - 2010 Intel Corporation. +# Copyright(c) 1999 - 2012 Intel Corporation.  #  # This program is free software; you can redistribute it and/or modify it  # under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h index 258164d6d45..e6aeb64105a 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h @@ -1,7 +1,7 @@  /*******************************************************************************    Intel 10 Gigabit PCI Express Linux driver -  Copyright(c) 1999 - 2011 Intel Corporation. +  Copyright(c) 1999 - 2012 Intel Corporation.    This program is free software; you can redistribute it and/or modify it    under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c index ef2afefb0cd..b406c367b19 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c @@ -1,7 +1,7 @@  /*******************************************************************************    Intel 10 Gigabit PCI Express Linux driver -  Copyright(c) 1999 - 2011 Intel Corporation. +  Copyright(c) 1999 - 2012 Intel Corporation.    This program is free software; you can redistribute it and/or modify it    under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c index 772072147be..4e59083a3de 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c @@ -1,7 +1,7 @@  /*******************************************************************************    Intel 10 Gigabit PCI Express Linux driver -  Copyright(c) 1999 - 2011 Intel Corporation. +  Copyright(c) 1999 - 2012 Intel Corporation.    This program is free software; you can redistribute it and/or modify it    under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c index a3aa6333073..383b9413292 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c @@ -1,7 +1,7 @@  /*******************************************************************************    Intel 10 Gigabit PCI Express Linux driver -  Copyright(c) 1999 - 2011 Intel Corporation. +  Copyright(c) 1999 - 2012 Intel Corporation.    This program is free software; you can redistribute it and/or modify it    under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h index 863f9c1f145..2c834c46bba 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h @@ -1,7 +1,7 @@  /*******************************************************************************    Intel 10 Gigabit PCI Express Linux driver -  Copyright(c) 1999 - 2011 Intel Corporation. +  Copyright(c) 1999 - 2012 Intel Corporation.    This program is free software; you can redistribute it and/or modify it    under the terms and conditions of the GNU General Public License, @@ -75,7 +75,7 @@ s32 ixgbe_update_mc_addr_list_generic(struct ixgbe_hw *hw,  s32 ixgbe_enable_mc_generic(struct ixgbe_hw *hw);  s32 ixgbe_disable_mc_generic(struct ixgbe_hw *hw);  s32 ixgbe_enable_rx_dma_generic(struct ixgbe_hw *hw, u32 regval); -s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw, s32 packtetbuf_num); +s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw, s32 packetbuf_num);  s32 ixgbe_fc_autoneg(struct ixgbe_hw *hw);  s32 ixgbe_validate_mac_addr(u8 *mac_addr); diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb.c index 318caf4bf62..8bfaaee5ac5 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb.c @@ -1,7 +1,7 @@  /*******************************************************************************    Intel 10 Gigabit PCI Express Linux driver -  Copyright(c) 1999 - 2011 Intel Corporation. +  Copyright(c) 1999 - 2012 Intel Corporation.    This program is free software; you can redistribute it and/or modify it    under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb.h index e162775064d..24333b71816 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb.h @@ -1,7 +1,7 @@  /*******************************************************************************    Intel 10 Gigabit PCI Express Linux driver -  Copyright(c) 1999 - 2011 Intel Corporation. +  Copyright(c) 1999 - 2012 Intel Corporation.    This program is free software; you can redistribute it and/or modify it    under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82598.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82598.c index fcd0e479721..d3695edfcb8 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82598.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82598.c @@ -1,7 +1,7 @@  /*******************************************************************************    Intel 10 Gigabit PCI Express Linux driver -  Copyright(c) 1999 - 2011 Intel Corporation. +  Copyright(c) 1999 - 2012 Intel Corporation.    This program is free software; you can redistribute it and/or modify it    under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82598.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82598.h index 2f318935561..ba835708fca 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82598.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82598.h @@ -1,7 +1,7 @@  /*******************************************************************************    Intel 10 Gigabit PCI Express Linux driver -  Copyright(c) 1999 - 2011 Intel Corporation. +  Copyright(c) 1999 - 2012 Intel Corporation.    This program is free software; you can redistribute it and/or modify it    under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82599.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82599.c index 32cd97bc794..888a419dc3d 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82599.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82599.c @@ -1,7 +1,7 @@  /*******************************************************************************    Intel 10 Gigabit PCI Express Linux driver -  Copyright(c) 1999 - 2011 Intel Corporation. +  Copyright(c) 1999 - 2012 Intel Corporation.    This program is free software; you can redistribute it and/or modify it    under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82599.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82599.h index a59d5dc59d0..4dec47faeb0 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82599.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82599.h @@ -1,7 +1,7 @@  /*******************************************************************************    Intel 10 Gigabit PCI Express Linux driver -  Copyright(c) 1999 - 2011 Intel Corporation. +  Copyright(c) 1999 - 2012 Intel Corporation.    This program is free software; you can redistribute it and/or modify it    under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c index da31735311f..79a92fe987b 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c @@ -1,7 +1,7 @@  /*******************************************************************************    Intel 10 Gigabit PCI Express Linux driver -  Copyright(c) 1999 - 2011 Intel Corporation. +  Copyright(c) 1999 - 2012 Intel Corporation.    This program is free software; you can redistribute it and/or modify it    under the terms and conditions of the GNU General Public License, @@ -112,6 +112,8 @@ static u8 ixgbe_dcbnl_get_state(struct net_device *netdev)  static u8 ixgbe_dcbnl_set_state(struct net_device *netdev, u8 state)  {  	u8 err = 0; +	u8 prio_tc[MAX_USER_PRIORITY] = {0}; +	int i;  	struct ixgbe_adapter *adapter = netdev_priv(netdev);  	/* Fail command if not in CEE mode */ @@ -122,10 +124,15 @@ static u8 ixgbe_dcbnl_set_state(struct net_device *netdev, u8 state)  	if (!!state != !(adapter->flags & IXGBE_FLAG_DCB_ENABLED))  		return err; -	if (state > 0) +	if (state > 0) {  		err = ixgbe_setup_tc(netdev, adapter->dcb_cfg.num_tcs.pg_tcs); -	else +		ixgbe_dcb_unpack_map(&adapter->dcb_cfg, DCB_TX_CONFIG, prio_tc); +	} else {  		err = ixgbe_setup_tc(netdev, 0); +	} + +	for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) +		netdev_set_prio_tc_map(netdev, i, prio_tc[i]);  	return err;  } diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c index da7e580f517..a62975480e3 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c @@ -1,7 +1,7 @@  /*******************************************************************************    Intel 10 Gigabit PCI Express Linux driver -  Copyright(c) 1999 - 2011 Intel Corporation. +  Copyright(c) 1999 - 2012 Intel Corporation.    This program is free software; you can redistribute it and/or modify it    under the terms and conditions of the GNU General Public License, @@ -58,7 +58,7 @@ struct ixgbe_stats {  				sizeof(((struct rtnl_link_stats64 *)0)->m), \  				offsetof(struct rtnl_link_stats64, m) -static struct ixgbe_stats ixgbe_gstrings_stats[] = { +static const struct ixgbe_stats ixgbe_gstrings_stats[] = {  	{"rx_packets", IXGBE_NETDEV_STAT(rx_packets)},  	{"tx_packets", IXGBE_NETDEV_STAT(tx_packets)},  	{"rx_bytes", IXGBE_NETDEV_STAT(rx_bytes)}, @@ -120,19 +120,23 @@ static struct ixgbe_stats ixgbe_gstrings_stats[] = {  #endif /* IXGBE_FCOE */  }; -#define IXGBE_QUEUE_STATS_LEN \ -	((((struct ixgbe_adapter *)netdev_priv(netdev))->num_tx_queues + \ -	((struct ixgbe_adapter *)netdev_priv(netdev))->num_rx_queues) * \ +/* ixgbe allocates num_tx_queues and num_rx_queues symmetrically so + * we set the num_rx_queues to evaluate to num_tx_queues. This is + * used because we do not have a good way to get the max number of + * rx queues with CONFIG_RPS disabled. + */ +#define IXGBE_NUM_RX_QUEUES netdev->num_tx_queues + +#define IXGBE_QUEUE_STATS_LEN ( \ +	(netdev->num_tx_queues + IXGBE_NUM_RX_QUEUES) * \  	(sizeof(struct ixgbe_queue_stats) / sizeof(u64)))  #define IXGBE_GLOBAL_STATS_LEN ARRAY_SIZE(ixgbe_gstrings_stats)  #define IXGBE_PB_STATS_LEN ( \ -                 (((struct ixgbe_adapter *)netdev_priv(netdev))->flags & \ -                 IXGBE_FLAG_DCB_ENABLED) ? \ -                 (sizeof(((struct ixgbe_adapter *)0)->stats.pxonrxc) + \ -                  sizeof(((struct ixgbe_adapter *)0)->stats.pxontxc) + \ -                  sizeof(((struct ixgbe_adapter *)0)->stats.pxoffrxc) + \ -                  sizeof(((struct ixgbe_adapter *)0)->stats.pxofftxc)) \ -                  / sizeof(u64) : 0) +			(sizeof(((struct ixgbe_adapter *)0)->stats.pxonrxc) + \ +			 sizeof(((struct ixgbe_adapter *)0)->stats.pxontxc) + \ +			 sizeof(((struct ixgbe_adapter *)0)->stats.pxoffrxc) + \ +			 sizeof(((struct ixgbe_adapter *)0)->stats.pxofftxc)) \ +			/ sizeof(u64))  #define IXGBE_STATS_LEN (IXGBE_GLOBAL_STATS_LEN + \                           IXGBE_PB_STATS_LEN + \                           IXGBE_QUEUE_STATS_LEN) @@ -1078,8 +1082,15 @@ static void ixgbe_get_ethtool_stats(struct net_device *netdev,  		data[i] = (ixgbe_gstrings_stats[i].sizeof_stat ==  		           sizeof(u64)) ? *(u64 *)p : *(u32 *)p;  	} -	for (j = 0; j < adapter->num_tx_queues; j++) { +	for (j = 0; j < IXGBE_NUM_RX_QUEUES; j++) {  		ring = adapter->tx_ring[j]; +		if (!ring) { +			data[i] = 0; +			data[i+1] = 0; +			i += 2; +			continue; +		} +  		do {  			start = u64_stats_fetch_begin_bh(&ring->syncp);  			data[i]   = ring->stats.packets; @@ -1087,8 +1098,15 @@ static void ixgbe_get_ethtool_stats(struct net_device *netdev,  		} while (u64_stats_fetch_retry_bh(&ring->syncp, start));  		i += 2;  	} -	for (j = 0; j < adapter->num_rx_queues; j++) { +	for (j = 0; j < IXGBE_NUM_RX_QUEUES; j++) {  		ring = adapter->rx_ring[j]; +		if (!ring) { +			data[i] = 0; +			data[i+1] = 0; +			i += 2; +			continue; +		} +  		do {  			start = u64_stats_fetch_begin_bh(&ring->syncp);  			data[i]   = ring->stats.packets; @@ -1096,22 +1114,20 @@ static void ixgbe_get_ethtool_stats(struct net_device *netdev,  		} while (u64_stats_fetch_retry_bh(&ring->syncp, start));  		i += 2;  	} -	if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) { -		for (j = 0; j < MAX_TX_PACKET_BUFFERS; j++) { -			data[i++] = adapter->stats.pxontxc[j]; -			data[i++] = adapter->stats.pxofftxc[j]; -		} -		for (j = 0; j < MAX_RX_PACKET_BUFFERS; j++) { -			data[i++] = adapter->stats.pxonrxc[j]; -			data[i++] = adapter->stats.pxoffrxc[j]; -		} + +	for (j = 0; j < IXGBE_MAX_PACKET_BUFFERS; j++) { +		data[i++] = adapter->stats.pxontxc[j]; +		data[i++] = adapter->stats.pxofftxc[j]; +	} +	for (j = 0; j < IXGBE_MAX_PACKET_BUFFERS; j++) { +		data[i++] = adapter->stats.pxonrxc[j]; +		data[i++] = adapter->stats.pxoffrxc[j];  	}  }  static void ixgbe_get_strings(struct net_device *netdev, u32 stringset,                                u8 *data)  { -	struct ixgbe_adapter *adapter = netdev_priv(netdev);  	char *p = (char *)data;  	int i; @@ -1126,31 +1142,29 @@ static void ixgbe_get_strings(struct net_device *netdev, u32 stringset,  			       ETH_GSTRING_LEN);  			p += ETH_GSTRING_LEN;  		} -		for (i = 0; i < adapter->num_tx_queues; i++) { +		for (i = 0; i < netdev->num_tx_queues; i++) {  			sprintf(p, "tx_queue_%u_packets", i);  			p += ETH_GSTRING_LEN;  			sprintf(p, "tx_queue_%u_bytes", i);  			p += ETH_GSTRING_LEN;  		} -		for (i = 0; i < adapter->num_rx_queues; i++) { +		for (i = 0; i < IXGBE_NUM_RX_QUEUES; i++) {  			sprintf(p, "rx_queue_%u_packets", i);  			p += ETH_GSTRING_LEN;  			sprintf(p, "rx_queue_%u_bytes", i);  			p += ETH_GSTRING_LEN;  		} -		if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) { -			for (i = 0; i < MAX_TX_PACKET_BUFFERS; i++) { -				sprintf(p, "tx_pb_%u_pxon", i); -				p += ETH_GSTRING_LEN; -				sprintf(p, "tx_pb_%u_pxoff", i); -				p += ETH_GSTRING_LEN; -			} -			for (i = 0; i < MAX_RX_PACKET_BUFFERS; i++) { -				sprintf(p, "rx_pb_%u_pxon", i); -				p += ETH_GSTRING_LEN; -				sprintf(p, "rx_pb_%u_pxoff", i); -				p += ETH_GSTRING_LEN; -			} +		for (i = 0; i < IXGBE_MAX_PACKET_BUFFERS; i++) { +			sprintf(p, "tx_pb_%u_pxon", i); +			p += ETH_GSTRING_LEN; +			sprintf(p, "tx_pb_%u_pxoff", i); +			p += ETH_GSTRING_LEN; +		} +		for (i = 0; i < IXGBE_MAX_PACKET_BUFFERS; i++) { +			sprintf(p, "rx_pb_%u_pxon", i); +			p += ETH_GSTRING_LEN; +			sprintf(p, "rx_pb_%u_pxoff", i); +			p += ETH_GSTRING_LEN;  		}  		/* BUG_ON(p - data != IXGBE_STATS_LEN * ETH_GSTRING_LEN); */  		break; diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c index d18d6157dd2..4bc79424980 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c @@ -1,7 +1,7 @@  /*******************************************************************************    Intel 10 Gigabit PCI Express Linux driver -  Copyright(c) 1999 - 2011 Intel Corporation. +  Copyright(c) 1999 - 2012 Intel Corporation.    This program is free software; you can redistribute it and/or modify it    under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.h index 261fd62dda1..1dbed17c810 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.h @@ -1,7 +1,7 @@  /*******************************************************************************    Intel 10 Gigabit PCI Express Linux driver -  Copyright(c) 1999 - 2011 Intel Corporation. +  Copyright(c) 1999 - 2012 Intel Corporation.    This program is free software; you can redistribute it and/or modify it    under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 1ee5d0fbb90..3dc6cef5810 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -1,7 +1,7 @@  /*******************************************************************************    Intel 10 Gigabit PCI Express Linux driver -  Copyright(c) 1999 - 2011 Intel Corporation. +  Copyright(c) 1999 - 2012 Intel Corporation.    This program is free software; you can redistribute it and/or modify it    under the terms and conditions of the GNU General Public License, @@ -64,7 +64,7 @@ char ixgbe_default_device_descr[] =  	__stringify(BUILD) "-k"  const char ixgbe_driver_version[] = DRV_VERSION;  static const char ixgbe_copyright[] = -				"Copyright (c) 1999-2011 Intel Corporation."; +				"Copyright (c) 1999-2012 Intel Corporation.";  static const struct ixgbe_info *ixgbe_info_tbl[] = {  	[board_82598] = &ixgbe_82598_info, @@ -2633,22 +2633,22 @@ static void ixgbe_configure_rscctl(struct ixgbe_adapter *adapter,  	/*  	 * we must limit the number of descriptors so that the  	 * total size of max desc * buf_len is not greater -	 * than 65535 +	 * than 65536  	 */  	if (ring_is_ps_enabled(ring)) { -#if (MAX_SKB_FRAGS > 16) +#if (PAGE_SIZE < 8192)  		rscctrl |= IXGBE_RSCCTL_MAXDESC_16; -#elif (MAX_SKB_FRAGS > 8) +#elif (PAGE_SIZE < 16384)  		rscctrl |= IXGBE_RSCCTL_MAXDESC_8; -#elif (MAX_SKB_FRAGS > 4) +#elif (PAGE_SIZE < 32768)  		rscctrl |= IXGBE_RSCCTL_MAXDESC_4;  #else  		rscctrl |= IXGBE_RSCCTL_MAXDESC_1;  #endif  	} else { -		if (rx_buf_len < IXGBE_RXBUFFER_4K) +		if (rx_buf_len <= IXGBE_RXBUFFER_4K)  			rscctrl |= IXGBE_RSCCTL_MAXDESC_16; -		else if (rx_buf_len < IXGBE_RXBUFFER_8K) +		else if (rx_buf_len <= IXGBE_RXBUFFER_8K)  			rscctrl |= IXGBE_RSCCTL_MAXDESC_8;  		else  			rscctrl |= IXGBE_RSCCTL_MAXDESC_4; @@ -2830,7 +2830,7 @@ static void ixgbe_configure_virtualization(struct ixgbe_adapter *adapter)  	IXGBE_WRITE_REG(hw, IXGBE_VT_CTL, vmdctl | vt_reg_bits);  	vf_shift = adapter->num_vfs % 32; -	reg_offset = (adapter->num_vfs > 32) ? 1 : 0; +	reg_offset = (adapter->num_vfs >= 32) ? 1 : 0;  	/* Enable only the PF's pool for Tx/Rx */  	IXGBE_WRITE_REG(hw, IXGBE_VFRE(reg_offset), (1 << vf_shift)); @@ -4330,6 +4330,10 @@ static int ixgbe_set_num_queues(struct ixgbe_adapter *adapter)  	adapter->num_tx_queues = 1;  done: +	if ((adapter->netdev->reg_state == NETREG_UNREGISTERED) || +	    (adapter->netdev->reg_state == NETREG_UNREGISTERING)) +		return 0; +  	/* Notify the stack of the (possibly) reduced queue counts. */  	netif_set_real_num_tx_queues(adapter->netdev, adapter->num_tx_queues);  	return netif_set_real_num_rx_queues(adapter->netdev, diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.c index 3f725d48336..1f3e32b576a 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.c @@ -1,7 +1,7 @@  /*******************************************************************************    Intel 10 Gigabit PCI Express Linux driver -  Copyright(c) 1999 - 2011 Intel Corporation. +  Copyright(c) 1999 - 2012 Intel Corporation.    This program is free software; you can redistribute it and/or modify it    under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.h index b239bdac38d..310bdd96107 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.h @@ -1,7 +1,7 @@  /*******************************************************************************    Intel 10 Gigabit PCI Express Linux driver -  Copyright(c) 1999 - 2011 Intel Corporation. +  Copyright(c) 1999 - 2012 Intel Corporation.    This program is free software; you can redistribute it and/or modify it    under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c index 7cf1e1f56c6..b91773551a3 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c @@ -1,7 +1,7 @@  /*******************************************************************************    Intel 10 Gigabit PCI Express Linux driver -  Copyright(c) 1999 - 2011 Intel Corporation. +  Copyright(c) 1999 - 2012 Intel Corporation.    This program is free software; you can redistribute it and/or modify it    under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h index 197bdd13106..cc18165b4c0 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h @@ -1,7 +1,7 @@  /*******************************************************************************    Intel 10 Gigabit PCI Express Linux driver -  Copyright(c) 1999 - 2011 Intel Corporation. +  Copyright(c) 1999 - 2012 Intel Corporation.    This program is free software; you can redistribute it and/or modify it    under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c index cf6812dd143..b01ecb4d2bb 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c @@ -1,7 +1,7 @@  /*******************************************************************************    Intel 10 Gigabit PCI Express Linux driver -  Copyright(c) 1999 - 2011 Intel Corporation. +  Copyright(c) 1999 - 2012 Intel Corporation.    This program is free software; you can redistribute it and/or modify it    under the terms and conditions of the GNU General Public License, @@ -67,7 +67,8 @@ static int ixgbe_find_enabled_vfs(struct ixgbe_adapter *adapter)  	vf_devfn = pdev->devfn + 0x80;  	pvfdev = pci_get_device(IXGBE_INTEL_VENDOR_ID, device_id, NULL);  	while (pvfdev) { -		if (pvfdev->devfn == vf_devfn) +		if (pvfdev->devfn == vf_devfn && +		    (pvfdev->bus->number >= pdev->bus->number))  			vfs_found++;  		vf_devfn += 2;  		pvfdev = pci_get_device(IXGBE_INTEL_VENDOR_ID, @@ -646,6 +647,9 @@ static int ixgbe_rcv_msg_from_vf(struct ixgbe_adapter *adapter, u32 vf)  			ixgbe_ndo_set_vf_spoofchk(adapter->netdev, vf, false);  		retval = ixgbe_set_vf_macvlan(adapter, vf, index,  					      (unsigned char *)(&msgbuf[1])); +		if (retval == -ENOSPC) +			e_warn(drv, "VF %d has requested a MACVLAN filter " +				    "but there is no space for it\n", vf);  		break;  	default:  		e_err(drv, "Unhandled Msg %8.8x\n", msgbuf[0]); diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.h index e8badab0335..2ab38d5fda9 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.h @@ -1,7 +1,7 @@  /*******************************************************************************    Intel 10 Gigabit PCI Express Linux driver -  Copyright(c) 1999 - 2011 Intel Corporation. +  Copyright(c) 1999 - 2012 Intel Corporation.    This program is free software; you can redistribute it and/or modify it    under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h index 775602ef90e..9b95bef6097 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h @@ -1,7 +1,7 @@  /*******************************************************************************    Intel 10 Gigabit PCI Express Linux driver -  Copyright(c) 1999 - 2011 Intel Corporation. +  Copyright(c) 1999 - 2012 Intel Corporation.    This program is free software; you can redistribute it and/or modify it    under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c index 8cc5eccfd65..f838a2be8cf 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c @@ -1,7 +1,7 @@  /*******************************************************************************    Intel 10 Gigabit PCI Express Linux driver -  Copyright(c) 1999 - 2011 Intel Corporation. +  Copyright(c) 1999 - 2012 Intel Corporation.    This program is free software; you can redistribute it and/or modify it    under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ethernet/intel/ixgbevf/Makefile b/drivers/net/ethernet/intel/ixgbevf/Makefile index 1f35d229e71..4ce4c97ef5a 100644 --- a/drivers/net/ethernet/intel/ixgbevf/Makefile +++ b/drivers/net/ethernet/intel/ixgbevf/Makefile @@ -1,7 +1,7 @@  ################################################################################  #  # Intel 82599 Virtual Function driver -# Copyright(c) 1999 - 2010 Intel Corporation. +# Copyright(c) 1999 - 2012 Intel Corporation.  #  # This program is free software; you can redistribute it and/or modify it  # under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ethernet/intel/ixgbevf/defines.h b/drivers/net/ethernet/intel/ixgbevf/defines.h index 2eb89cb94a0..947b5c83073 100644 --- a/drivers/net/ethernet/intel/ixgbevf/defines.h +++ b/drivers/net/ethernet/intel/ixgbevf/defines.h @@ -1,7 +1,7 @@  /*******************************************************************************    Intel 82599 Virtual Function driver -  Copyright(c) 1999 - 2010 Intel Corporation. +  Copyright(c) 1999 - 2012 Intel Corporation.    This program is free software; you can redistribute it and/or modify it    under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ethernet/intel/ixgbevf/ethtool.c b/drivers/net/ethernet/intel/ixgbevf/ethtool.c index c8570031814..2bfe0d1d795 100644 --- a/drivers/net/ethernet/intel/ixgbevf/ethtool.c +++ b/drivers/net/ethernet/intel/ixgbevf/ethtool.c @@ -1,7 +1,7 @@  /*******************************************************************************    Intel 82599 Virtual Function driver -  Copyright(c) 1999 - 2009 Intel Corporation. +  Copyright(c) 1999 - 2012 Intel Corporation.    This program is free software; you can redistribute it and/or modify it    under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h b/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h index 9075c1d6103..dfed420a1bf 100644 --- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h +++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h @@ -1,7 +1,7 @@  /*******************************************************************************    Intel 82599 Virtual Function driver -  Copyright(c) 1999 - 2010 Intel Corporation. +  Copyright(c) 1999 - 2012 Intel Corporation.    This program is free software; you can redistribute it and/or modify it    under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c index bed411bada2..e51d552410a 100644 --- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c +++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c @@ -1,7 +1,7 @@  /*******************************************************************************    Intel 82599 Virtual Function driver -  Copyright(c) 1999 - 2010 Intel Corporation. +  Copyright(c) 1999 - 2012 Intel Corporation.    This program is free software; you can redistribute it and/or modify it    under the terms and conditions of the GNU General Public License, @@ -60,7 +60,7 @@ static const char ixgbevf_driver_string[] =  #define DRV_VERSION "2.2.0-k"  const char ixgbevf_driver_version[] = DRV_VERSION;  static char ixgbevf_copyright[] = -	"Copyright (c) 2009 - 2010 Intel Corporation."; +	"Copyright (c) 2009 - 2012 Intel Corporation.";  static const struct ixgbevf_info *ixgbevf_info_tbl[] = {  	[board_82599_vf] = &ixgbevf_82599_vf_info, @@ -935,7 +935,11 @@ static irqreturn_t ixgbevf_msix_mbx(int irq, void *data)  		if (msg & IXGBE_VT_MSGTYPE_NACK)  			pr_warn("Last Request of type %2.2x to PF Nacked\n",  				msg & 0xFF); -		goto out; +		/* +		 * Restore the PFSTS bit in case someone is polling for a +		 * return message from the PF +		 */ +		hw->mbx.v2p_mailbox |= IXGBE_VFMAILBOX_PFSTS;  	}  	/* @@ -945,7 +949,7 @@ static irqreturn_t ixgbevf_msix_mbx(int irq, void *data)  	 */  	if (got_ack)  		hw->mbx.v2p_mailbox |= IXGBE_VFMAILBOX_PFACK; -out: +  	return IRQ_HANDLED;  } diff --git a/drivers/net/ethernet/intel/ixgbevf/mbx.c b/drivers/net/ethernet/intel/ixgbevf/mbx.c index 13532d9ba72..9c955900fe6 100644 --- a/drivers/net/ethernet/intel/ixgbevf/mbx.c +++ b/drivers/net/ethernet/intel/ixgbevf/mbx.c @@ -1,7 +1,7 @@  /*******************************************************************************    Intel 82599 Virtual Function driver -  Copyright(c) 1999 - 2010 Intel Corporation. +  Copyright(c) 1999 - 2012 Intel Corporation.    This program is free software; you can redistribute it and/or modify it    under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ethernet/intel/ixgbevf/mbx.h b/drivers/net/ethernet/intel/ixgbevf/mbx.h index 9d38a94a348..cf9131c5c11 100644 --- a/drivers/net/ethernet/intel/ixgbevf/mbx.h +++ b/drivers/net/ethernet/intel/ixgbevf/mbx.h @@ -1,7 +1,7 @@  /*******************************************************************************    Intel 82599 Virtual Function driver -  Copyright(c) 1999 - 2010 Intel Corporation. +  Copyright(c) 1999 - 2012 Intel Corporation.    This program is free software; you can redistribute it and/or modify it    under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ethernet/intel/ixgbevf/regs.h b/drivers/net/ethernet/intel/ixgbevf/regs.h index 5e4d5e5cdf3..debd8c0e1f2 100644 --- a/drivers/net/ethernet/intel/ixgbevf/regs.h +++ b/drivers/net/ethernet/intel/ixgbevf/regs.h @@ -1,7 +1,7 @@  /*******************************************************************************    Intel 82599 Virtual Function driver -  Copyright(c) 1999 - 2010 Intel Corporation. +  Copyright(c) 1999 - 2012 Intel Corporation.    This program is free software; you can redistribute it and/or modify it    under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ethernet/intel/ixgbevf/vf.c b/drivers/net/ethernet/intel/ixgbevf/vf.c index d0138d7a31a..74be7411242 100644 --- a/drivers/net/ethernet/intel/ixgbevf/vf.c +++ b/drivers/net/ethernet/intel/ixgbevf/vf.c @@ -1,7 +1,7 @@  /*******************************************************************************    Intel 82599 Virtual Function driver -  Copyright(c) 1999 - 2010 Intel Corporation. +  Copyright(c) 1999 - 2012 Intel Corporation.    This program is free software; you can redistribute it and/or modify it    under the terms and conditions of the GNU General Public License, @@ -283,6 +283,17 @@ static s32 ixgbevf_set_rar_vf(struct ixgbe_hw *hw, u32 index, u8 *addr,  	return ret_val;  } +static void ixgbevf_write_msg_read_ack(struct ixgbe_hw *hw, +					u32 *msg, u16 size) +{ +	struct ixgbe_mbx_info *mbx = &hw->mbx; +	u32 retmsg[IXGBE_VFMAILBOX_SIZE]; +	s32 retval = mbx->ops.write_posted(hw, msg, size); + +	if (!retval) +		mbx->ops.read_posted(hw, retmsg, size); +} +  /**   *  ixgbevf_update_mc_addr_list_vf - Update Multicast addresses   *  @hw: pointer to the HW structure @@ -294,7 +305,6 @@ static s32 ixgbevf_update_mc_addr_list_vf(struct ixgbe_hw *hw,  					  struct net_device *netdev)  {  	struct netdev_hw_addr *ha; -	struct ixgbe_mbx_info *mbx = &hw->mbx;  	u32 msgbuf[IXGBE_VFMAILBOX_SIZE];  	u16 *vector_list = (u16 *)&msgbuf[1];  	u32 cnt, i; @@ -321,7 +331,7 @@ static s32 ixgbevf_update_mc_addr_list_vf(struct ixgbe_hw *hw,  		vector_list[i++] = ixgbevf_mta_vector(hw, ha->addr);  	} -	mbx->ops.write_posted(hw, msgbuf, IXGBE_VFMAILBOX_SIZE); +	ixgbevf_write_msg_read_ack(hw, msgbuf, IXGBE_VFMAILBOX_SIZE);  	return 0;  } @@ -336,7 +346,6 @@ static s32 ixgbevf_update_mc_addr_list_vf(struct ixgbe_hw *hw,  static s32 ixgbevf_set_vfta_vf(struct ixgbe_hw *hw, u32 vlan, u32 vind,  			       bool vlan_on)  { -	struct ixgbe_mbx_info *mbx = &hw->mbx;  	u32 msgbuf[2];  	msgbuf[0] = IXGBE_VF_SET_VLAN; @@ -344,7 +353,9 @@ static s32 ixgbevf_set_vfta_vf(struct ixgbe_hw *hw, u32 vlan, u32 vind,  	/* Setting the 8 bit field MSG INFO to TRUE indicates "add" */  	msgbuf[0] |= vlan_on << IXGBE_VT_MSGINFO_SHIFT; -	return mbx->ops.write_posted(hw, msgbuf, 2); +	ixgbevf_write_msg_read_ack(hw, msgbuf, 2); + +	return 0;  }  /** diff --git a/drivers/net/ethernet/intel/ixgbevf/vf.h b/drivers/net/ethernet/intel/ixgbevf/vf.h index d556619a921..25c951daee5 100644 --- a/drivers/net/ethernet/intel/ixgbevf/vf.h +++ b/drivers/net/ethernet/intel/ixgbevf/vf.h @@ -1,7 +1,7 @@  /*******************************************************************************    Intel 82599 Virtual Function driver -  Copyright(c) 1999 - 2010 Intel Corporation. +  Copyright(c) 1999 - 2012 Intel Corporation.    This program is free software; you can redistribute it and/or modify it    under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ethernet/marvell/skge.c b/drivers/net/ethernet/marvell/skge.c index edb9bda55d5..33947ac595c 100644 --- a/drivers/net/ethernet/marvell/skge.c +++ b/drivers/net/ethernet/marvell/skge.c @@ -931,20 +931,17 @@ static int skge_ring_alloc(struct skge_ring *ring, void *vaddr, u32 base)  }  /* Allocate and setup a new buffer for receiving */ -static int skge_rx_setup(struct pci_dev *pdev, -			 struct skge_element *e, -			 struct sk_buff *skb, unsigned int bufsize) +static void skge_rx_setup(struct skge_port *skge, struct skge_element *e, +			  struct sk_buff *skb, unsigned int bufsize)  {  	struct skge_rx_desc *rd = e->desc; -	dma_addr_t map; +	u64 map; -	map = pci_map_single(pdev, skb->data, bufsize, +	map = pci_map_single(skge->hw->pdev, skb->data, bufsize,  			     PCI_DMA_FROMDEVICE); -	if (pci_dma_mapping_error(pdev, map)) -		goto mapping_error; -	rd->dma_lo = lower_32_bits(map); -	rd->dma_hi = upper_32_bits(map); +	rd->dma_lo = map; +	rd->dma_hi = map >> 32;  	e->skb = skb;  	rd->csum1_start = ETH_HLEN;  	rd->csum2_start = ETH_HLEN; @@ -956,13 +953,6 @@ static int skge_rx_setup(struct pci_dev *pdev,  	rd->control = BMU_OWN | BMU_STF | BMU_IRQ_EOF | BMU_TCP_CHECK | bufsize;  	dma_unmap_addr_set(e, mapaddr, map);  	dma_unmap_len_set(e, maplen, bufsize); -	return 0; - -mapping_error: -	if (net_ratelimit()) -		dev_warn(&pdev->dev, "%s: rx mapping error\n", -			 skb->dev->name); -	return -EIO;  }  /* Resume receiving using existing skb, @@ -1024,11 +1014,7 @@ static int skge_rx_fill(struct net_device *dev)  			return -ENOMEM;  		skb_reserve(skb, NET_IP_ALIGN); -		if (skge_rx_setup(skge->hw->pdev, e, skb, skge->rx_buf_size)) { -			kfree_skb(skb); -			return -ENOMEM; -		} - +		skge_rx_setup(skge, e, skb, skge->rx_buf_size);  	} while ((e = e->next) != ring->start);  	ring->to_clean = ring->start; @@ -2743,7 +2729,7 @@ static netdev_tx_t skge_xmit_frame(struct sk_buff *skb,  	struct skge_tx_desc *td;  	int i;  	u32 control, len; -	dma_addr_t map; +	u64 map;  	if (skb_padto(skb, ETH_ZLEN))  		return NETDEV_TX_OK; @@ -2757,14 +2743,11 @@ static netdev_tx_t skge_xmit_frame(struct sk_buff *skb,  	e->skb = skb;  	len = skb_headlen(skb);  	map = pci_map_single(hw->pdev, skb->data, len, PCI_DMA_TODEVICE); -	if (pci_dma_mapping_error(hw->pdev, map)) -		goto mapping_error; -  	dma_unmap_addr_set(e, mapaddr, map);  	dma_unmap_len_set(e, maplen, len); -	td->dma_lo = lower_32_bits(map); -	td->dma_hi = upper_32_bits(map); +	td->dma_lo = map; +	td->dma_hi = map >> 32;  	if (skb->ip_summed == CHECKSUM_PARTIAL) {  		const int offset = skb_checksum_start_offset(skb); @@ -2795,16 +2778,14 @@ static netdev_tx_t skge_xmit_frame(struct sk_buff *skb,  			map = skb_frag_dma_map(&hw->pdev->dev, frag, 0,  					       skb_frag_size(frag), DMA_TO_DEVICE); -			if (dma_mapping_error(&hw->pdev->dev, map)) -				goto mapping_unwind;  			e = e->next;  			e->skb = skb;  			tf = e->desc;  			BUG_ON(tf->control & BMU_OWN); -			tf->dma_lo = lower_32_bits(map); -			tf->dma_hi = upper_32_bits(map); +			tf->dma_lo = map; +			tf->dma_hi = (u64) map >> 32;  			dma_unmap_addr_set(e, mapaddr, map);  			dma_unmap_len_set(e, maplen, skb_frag_size(frag)); @@ -2834,28 +2815,6 @@ static netdev_tx_t skge_xmit_frame(struct sk_buff *skb,  	}  	return NETDEV_TX_OK; - -mapping_unwind: -	/* unroll any pages that were already mapped.  */ -	if (e != skge->tx_ring.to_use) { -		struct skge_element *u; - -		for (u = skge->tx_ring.to_use->next; u != e; u = u->next) -			pci_unmap_page(hw->pdev, dma_unmap_addr(u, mapaddr), -				       dma_unmap_len(u, maplen), -				       PCI_DMA_TODEVICE); -		e = skge->tx_ring.to_use; -	} -	/* undo the mapping for the skb header */ -	pci_unmap_single(hw->pdev, dma_unmap_addr(e, mapaddr), -			 dma_unmap_len(e, maplen), -			 PCI_DMA_TODEVICE); -mapping_error: -	/* mapping error causes error message and packet to be discarded. */ -	if (net_ratelimit()) -		dev_warn(&hw->pdev->dev, "%s: tx mapping error\n", dev->name); -	dev_kfree_skb(skb); -	return NETDEV_TX_OK;  } @@ -3099,17 +3058,13 @@ static struct sk_buff *skge_rx_get(struct net_device *dev,  		if (!nskb)  			goto resubmit; -		if (unlikely(skge_rx_setup(skge->hw->pdev, e, nskb, skge->rx_buf_size))) { -			dev_kfree_skb(nskb); -			goto resubmit; -		} -  		pci_unmap_single(skge->hw->pdev,  				 dma_unmap_addr(e, mapaddr),  				 dma_unmap_len(e, maplen),  				 PCI_DMA_FROMDEVICE);  		skb = e->skb;  		prefetch(skb->data); +		skge_rx_setup(skge, e, nskb, skge->rx_buf_size);  	}  	skb_put(skb, len); diff --git a/drivers/net/ethernet/mellanox/mlx4/cmd.c b/drivers/net/ethernet/mellanox/mlx4/cmd.c index 405e6ac3faf..eaf09d4f02d 100644 --- a/drivers/net/ethernet/mellanox/mlx4/cmd.c +++ b/drivers/net/ethernet/mellanox/mlx4/cmd.c @@ -1616,12 +1616,12 @@ void mlx4_multi_func_cleanup(struct mlx4_dev *dev)  				kfree(priv->mfunc.master.slave_state[i].vlan_filter[port]);  		}  		kfree(priv->mfunc.master.slave_state); -		iounmap(priv->mfunc.comm); -		dma_free_coherent(&(dev->pdev->dev), PAGE_SIZE, -						     priv->mfunc.vhcr, -						     priv->mfunc.vhcr_dma); -		priv->mfunc.vhcr = NULL;  	} + +	iounmap(priv->mfunc.comm); +	dma_free_coherent(&(dev->pdev->dev), PAGE_SIZE, +		     priv->mfunc.vhcr, priv->mfunc.vhcr_dma); +	priv->mfunc.vhcr = NULL;  }  void mlx4_cmd_cleanup(struct mlx4_dev *dev) diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c index 467ae582487..149e60da0a3 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c @@ -892,7 +892,8 @@ void mlx4_en_free_resources(struct mlx4_en_priv *priv)  	for (i = 0; i < priv->rx_ring_num; i++) {  		if (priv->rx_ring[i].rx_info) -			mlx4_en_destroy_rx_ring(priv, &priv->rx_ring[i]); +			mlx4_en_destroy_rx_ring(priv, &priv->rx_ring[i], +				priv->prof->rx_ring_size, priv->stride);  		if (priv->rx_cq[i].buf)  			mlx4_en_destroy_cq(priv, &priv->rx_cq[i]);  	} diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ethernet/mellanox/mlx4/en_rx.c index 971d4b6b8df..d4ad8c226b5 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c @@ -168,8 +168,12 @@ static int mlx4_en_prepare_rx_desc(struct mlx4_en_priv *priv,  	return 0;  err: -	while (i--) +	while (i--) { +		dma_addr_t dma = be64_to_cpu(rx_desc->data[i].addr); +		pci_unmap_single(priv->mdev->pdev, dma, skb_frags[i].size, +				 PCI_DMA_FROMDEVICE);  		put_page(skb_frags[i].page); +	}  	return -ENOMEM;  } @@ -380,12 +384,12 @@ err_allocator:  }  void mlx4_en_destroy_rx_ring(struct mlx4_en_priv *priv, -			     struct mlx4_en_rx_ring *ring) +			     struct mlx4_en_rx_ring *ring, u32 size, u16 stride)  {  	struct mlx4_en_dev *mdev = priv->mdev;  	mlx4_en_unmap_buffer(&ring->wqres.buf); -	mlx4_free_hwq_res(mdev->dev, &ring->wqres, ring->buf_size + TXBB_SIZE); +	mlx4_free_hwq_res(mdev->dev, &ring->wqres, size * stride + TXBB_SIZE);  	vfree(ring->rx_info);  	ring->rx_info = NULL;  } diff --git a/drivers/net/ethernet/mellanox/mlx4/mcg.c b/drivers/net/ethernet/mellanox/mlx4/mcg.c index 0785d9b2a26..ca574d850b3 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mcg.c +++ b/drivers/net/ethernet/mellanox/mlx4/mcg.c @@ -136,7 +136,7 @@ static int new_steering_entry(struct mlx4_dev *dev, u8 port,  	u32 prot;  	int err; -	s_steer = &mlx4_priv(dev)->steer[0]; +	s_steer = &mlx4_priv(dev)->steer[port - 1];  	new_entry = kzalloc(sizeof *new_entry, GFP_KERNEL);  	if (!new_entry)  		return -ENOMEM; @@ -220,7 +220,7 @@ static int existing_steering_entry(struct mlx4_dev *dev, u8 port,  	struct mlx4_promisc_qp *pqp;  	struct mlx4_promisc_qp *dqp; -	s_steer = &mlx4_priv(dev)->steer[0]; +	s_steer = &mlx4_priv(dev)->steer[port - 1];  	pqp = get_promisc_qp(dev, 0, steer, qpn);  	if (!pqp) @@ -265,7 +265,7 @@ static bool check_duplicate_entry(struct mlx4_dev *dev, u8 port,  	struct mlx4_steer_index *tmp_entry, *entry = NULL;  	struct mlx4_promisc_qp *dqp, *tmp_dqp; -	s_steer = &mlx4_priv(dev)->steer[0]; +	s_steer = &mlx4_priv(dev)->steer[port - 1];  	/* if qp is not promisc, it cannot be duplicated */  	if (!get_promisc_qp(dev, 0, steer, qpn)) @@ -306,7 +306,7 @@ static bool can_remove_steering_entry(struct mlx4_dev *dev, u8 port,  	bool ret = false;  	int i; -	s_steer = &mlx4_priv(dev)->steer[0]; +	s_steer = &mlx4_priv(dev)->steer[port - 1];  	mailbox = mlx4_alloc_cmd_mailbox(dev);  	if (IS_ERR(mailbox)) @@ -361,7 +361,7 @@ static int add_promisc_qp(struct mlx4_dev *dev, u8 port,  	int err;  	struct mlx4_priv *priv = mlx4_priv(dev); -	s_steer = &mlx4_priv(dev)->steer[0]; +	s_steer = &mlx4_priv(dev)->steer[port - 1];  	mutex_lock(&priv->mcg_table.mutex); @@ -466,7 +466,7 @@ static int remove_promisc_qp(struct mlx4_dev *dev, u8 port,  	int loc, i;  	int err; -	s_steer = &mlx4_priv(dev)->steer[0]; +	s_steer = &mlx4_priv(dev)->steer[port - 1];  	mutex_lock(&priv->mcg_table.mutex);  	pqp = get_promisc_qp(dev, 0, steer, qpn); @@ -1004,7 +1004,7 @@ EXPORT_SYMBOL_GPL(mlx4_multicast_promisc_remove);  int mlx4_unicast_promisc_add(struct mlx4_dev *dev, u32 qpn, u8 port)  { -	if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER)) +	if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER))  		return 0;  	if (mlx4_is_mfunc(dev)) @@ -1016,7 +1016,7 @@ EXPORT_SYMBOL_GPL(mlx4_unicast_promisc_add);  int mlx4_unicast_promisc_remove(struct mlx4_dev *dev, u32 qpn, u8 port)  { -	if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER)) +	if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER))  		return 0;  	if (mlx4_is_mfunc(dev)) diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h index 35f08840813..d60335f3c47 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h @@ -528,7 +528,8 @@ int mlx4_en_create_rx_ring(struct mlx4_en_priv *priv,  			   struct mlx4_en_rx_ring *ring,  			   u32 size, u16 stride);  void mlx4_en_destroy_rx_ring(struct mlx4_en_priv *priv, -			     struct mlx4_en_rx_ring *ring); +			     struct mlx4_en_rx_ring *ring, +			     u32 size, u16 stride);  int mlx4_en_activate_rx_rings(struct mlx4_en_priv *priv);  void mlx4_en_deactivate_rx_ring(struct mlx4_en_priv *priv,  				struct mlx4_en_rx_ring *ring); diff --git a/drivers/net/ethernet/micrel/Kconfig b/drivers/net/ethernet/micrel/Kconfig index 1ea811cf515..fe42fc00d8d 100644 --- a/drivers/net/ethernet/micrel/Kconfig +++ b/drivers/net/ethernet/micrel/Kconfig @@ -42,7 +42,6 @@ config KS8851  	select NET_CORE  	select MII  	select CRC32 -	select MISC_DEVICES  	select EEPROM_93CX6  	---help---  	  SPI driver for Micrel KS8851 SPI attached network chip. diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index 813d41c4a84..87b65013177 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -38,6 +38,7 @@  #include <linux/pm_runtime.h>  #include <linux/slab.h>  #include <linux/ethtool.h> +#include <linux/if_vlan.h>  #include <linux/sh_eth.h>  #include "sh_eth.h" @@ -817,7 +818,8 @@ static int sh_eth_dev_init(struct net_device *ndev)  		sh_eth_write(ndev, 0, TRIMD);  	/* Recv frame limit set register */ -	sh_eth_write(ndev, RFLR_VALUE, RFLR); +	sh_eth_write(ndev, ndev->mtu + ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN, +		     RFLR);  	sh_eth_write(ndev, sh_eth_read(ndev, EESR), EESR);  	sh_eth_write(ndev, mdp->cd->eesipr_value, EESIPR); diff --git a/drivers/net/ethernet/renesas/sh_eth.h b/drivers/net/ethernet/renesas/sh_eth.h index 47877b13ffa..cdbd844662a 100644 --- a/drivers/net/ethernet/renesas/sh_eth.h +++ b/drivers/net/ethernet/renesas/sh_eth.h @@ -575,9 +575,6 @@ enum RPADIR_BIT {  	RPADIR_PADR = 0x0003f,  }; -/* RFLR */ -#define RFLR_VALUE 0x1000 -  /* FDR */  #define DEFAULT_FDR_INIT	0x00000707 diff --git a/drivers/net/ethernet/ti/davinci_emac.c b/drivers/net/ethernet/ti/davinci_emac.c index 794ac30a577..4fa0bcb25df 100644 --- a/drivers/net/ethernet/ti/davinci_emac.c +++ b/drivers/net/ethernet/ti/davinci_emac.c @@ -1600,8 +1600,9 @@ static int emac_dev_open(struct net_device *ndev)  		if (IS_ERR(priv->phydev)) {  			dev_err(emac_dev, "could not connect to phy %s\n",  				priv->phy_id); +			ret = PTR_ERR(priv->phydev);  			priv->phydev = NULL; -			return PTR_ERR(priv->phydev); +			return ret;  		}  		priv->link = 0; diff --git a/drivers/net/ethernet/ti/davinci_mdio.c b/drivers/net/ethernet/ti/davinci_mdio.c index ef7c9c17bff..af8b8fc39eb 100644 --- a/drivers/net/ethernet/ti/davinci_mdio.c +++ b/drivers/net/ethernet/ti/davinci_mdio.c @@ -318,9 +318,9 @@ static int __devinit davinci_mdio_probe(struct platform_device *pdev)  	data->clk = clk_get(dev, NULL);  	if (IS_ERR(data->clk)) { -		data->clk = NULL;  		dev_err(dev, "failed to get device clock\n");  		ret = PTR_ERR(data->clk); +		data->clk = NULL;  		goto bail_out;  	} diff --git a/drivers/net/ethernet/toshiba/Kconfig b/drivers/net/ethernet/toshiba/Kconfig index 05176470455..74acb5cf609 100644 --- a/drivers/net/ethernet/toshiba/Kconfig +++ b/drivers/net/ethernet/toshiba/Kconfig @@ -5,7 +5,7 @@  config NET_VENDOR_TOSHIBA  	bool "Toshiba devices"  	default y -	depends on PCI && (PPC_IBM_CELL_BLADE || PPC_CELLEB) || PPC_PS3 +	depends on PCI && (PPC_IBM_CELL_BLADE || PPC_CELLEB || MIPS) || PPC_PS3  	---help---  	  If you have a network (Ethernet) card belonging to this class, say Y  	  and read the Ethernet-HOWTO, available from diff --git a/drivers/net/ethernet/via/via-velocity.c b/drivers/net/ethernet/via/via-velocity.c index 4128d6b8cc2..cb35b14b73b 100644 --- a/drivers/net/ethernet/via/via-velocity.c +++ b/drivers/net/ethernet/via/via-velocity.c @@ -2491,9 +2491,6 @@ static int velocity_close(struct net_device *dev)  	if (dev->irq != 0)  		free_irq(dev->irq, dev); -	/* Power down the chip */ -	pci_set_power_state(vptr->pdev, PCI_D3hot); -  	velocity_free_rings(vptr);  	vptr->flags &= (~VELOCITY_FLAGS_OPENED); diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index 1a1ca6cfc74..466c58a7353 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c @@ -123,7 +123,7 @@ static int netvsc_close(struct net_device *net)  	struct hv_device *device_obj = net_device_ctx->device_ctx;  	int ret; -	netif_stop_queue(net); +	netif_tx_disable(net);  	ret = rndis_filter_close(device_obj);  	if (ret != 0) @@ -151,10 +151,10 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)  	int ret;  	unsigned int i, num_pages, npg_data; -	/* Add multipage for skb->data and additional one for RNDIS */ +	/* Add multipages for skb->data and additional 2 for RNDIS */  	npg_data = (((unsigned long)skb->data + skb_headlen(skb) - 1)  		>> PAGE_SHIFT) - ((unsigned long)skb->data >> PAGE_SHIFT) + 1; -	num_pages = skb_shinfo(skb)->nr_frags + npg_data + 1; +	num_pages = skb_shinfo(skb)->nr_frags + npg_data + 2;  	/* Allocate a netvsc packet based on # of frags. */  	packet = kzalloc(sizeof(struct hv_netvsc_packet) + @@ -173,8 +173,8 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)  				sizeof(struct hv_netvsc_packet) +  				    (num_pages * sizeof(struct hv_page_buffer)); -	/* Setup the rndis header */ -	packet->page_buf_cnt = num_pages; +	/* If the rndis msg goes beyond 1 page, we will add 1 later */ +	packet->page_buf_cnt = num_pages - 1;  	/* Initialize it from the skb */  	packet->total_data_buflen = skb->len; @@ -256,7 +256,7 @@ void netvsc_linkstatus_callback(struct hv_device *device_obj,  		schedule_delayed_work(&ndev_ctx->dwork, msecs_to_jiffies(20));  	} else {  		netif_carrier_off(net); -		netif_stop_queue(net); +		netif_tx_disable(net);  	}  } @@ -298,7 +298,7 @@ int netvsc_recv_callback(struct hv_device *device_obj,  	skb->ip_summed = CHECKSUM_NONE;  	net->stats.rx_packets++; -	net->stats.rx_bytes += skb->len; +	net->stats.rx_bytes += packet->total_data_buflen;  	/*  	 * Pass the skb back up. Network stack will deallocate the skb when it @@ -337,7 +337,7 @@ static int netvsc_change_mtu(struct net_device *ndev, int mtu)  	nvdev->start_remove = true;  	cancel_delayed_work_sync(&ndevctx->dwork); -	netif_stop_queue(ndev); +	netif_tx_disable(ndev);  	rndis_filter_device_remove(hdev);  	ndev->mtu = mtu; @@ -460,7 +460,7 @@ static int netvsc_remove(struct hv_device *dev)  	cancel_delayed_work_sync(&ndev_ctx->dwork);  	/* Stop outbound asap */ -	netif_stop_queue(net); +	netif_tx_disable(net);  	unregister_netdev(net); diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c index da181f9a49d..133b7fbf859 100644 --- a/drivers/net/hyperv/rndis_filter.c +++ b/drivers/net/hyperv/rndis_filter.c @@ -321,6 +321,25 @@ static void rndis_filter_receive_data(struct rndis_device *dev,  	data_offset = RNDIS_HEADER_SIZE + rndis_pkt->data_offset;  	pkt->total_data_buflen -= data_offset; + +	/* +	 * Make sure we got a valid RNDIS message, now total_data_buflen +	 * should be the data packet size plus the trailer padding size +	 */ +	if (pkt->total_data_buflen < rndis_pkt->data_len) { +		netdev_err(dev->net_dev->ndev, "rndis message buffer " +			   "overflow detected (got %u, min %u)" +			   "...dropping this message!\n", +			   pkt->total_data_buflen, rndis_pkt->data_len); +		return; +	} + +	/* +	 * Remove the rndis trailer padding from rndis packet message +	 * rndis_pkt->data_len tell us the real data length, we only copy +	 * the data packet to the stack, without the rndis trailer padding +	 */ +	pkt->total_data_buflen = rndis_pkt->data_len;  	pkt->data = (void *)((unsigned long)pkt->data + data_offset);  	pkt->is_data_pkt = true; @@ -778,6 +797,19 @@ int rndis_filter_send(struct hv_device *dev,  			(unsigned long)rndisMessage & (PAGE_SIZE-1);  	pkt->page_buf[0].len = rndisMessageSize; +	/* Add one page_buf if the rndis msg goes beyond page boundary */ +	if (pkt->page_buf[0].offset + rndisMessageSize > PAGE_SIZE) { +		int i; +		for (i = pkt->page_buf_cnt; i > 1; i--) +			pkt->page_buf[i] = pkt->page_buf[i-1]; +		pkt->page_buf_cnt++; +		pkt->page_buf[0].len = PAGE_SIZE - pkt->page_buf[0].offset; +		pkt->page_buf[1].pfn = virt_to_phys((void *)((ulong) +			rndisMessage + pkt->page_buf[0].len)) >> PAGE_SHIFT; +		pkt->page_buf[1].offset = 0; +		pkt->page_buf[1].len = rndisMessageSize - pkt->page_buf[0].len; +	} +  	/* Save the packet send completion and context */  	filterPacket->completion = pkt->completion.send.send_completion;  	filterPacket->completion_ctx = diff --git a/drivers/net/phy/mdio-gpio.c b/drivers/net/phy/mdio-gpio.c index 50e8e5e7446..7189adf54bd 100644 --- a/drivers/net/phy/mdio-gpio.c +++ b/drivers/net/phy/mdio-gpio.c @@ -255,13 +255,13 @@ static inline int __init mdio_ofgpio_init(void)  	return platform_driver_register(&mdio_ofgpio_driver);  } -static inline void __exit mdio_ofgpio_exit(void) +static inline void mdio_ofgpio_exit(void)  {  	platform_driver_unregister(&mdio_ofgpio_driver);  }  #else  static inline int __init mdio_ofgpio_init(void) { return 0; } -static inline void __exit mdio_ofgpio_exit(void) { } +static inline void mdio_ofgpio_exit(void) { }  #endif /* CONFIG_OF_GPIO */  static struct platform_driver mdio_gpio_driver = { diff --git a/drivers/net/tokenring/Kconfig b/drivers/net/tokenring/Kconfig index c7e0149d151..45550d42b36 100644 --- a/drivers/net/tokenring/Kconfig +++ b/drivers/net/tokenring/Kconfig @@ -7,7 +7,6 @@ menuconfig TR  	bool "Token Ring driver support"  	depends on NETDEVICES && !UML  	depends on (PCI || ISA || MCA || CCW || PCMCIA) -	select LLC  	help  	  Token Ring is IBM's way of communication on a local network; the  	  rest of the world uses Ethernet. To participate on a Token Ring @@ -20,6 +19,10 @@ menuconfig TR  if TR +config WANT_LLC +	def_bool y +	select LLC +  config PCMCIA_IBMTR  	tristate "IBM PCMCIA tokenring adapter support"  	depends on IBMTR!=y && PCMCIA diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index ee775957505..87db1ee1c29 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1037,13 +1037,16 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah)  	/*  	 * Workaround for early ACK timeouts, add an offset to match the -	 * initval's 64us ack timeout value. +	 * initval's 64us ack timeout value. Use 48us for the CTS timeout.  	 * This was initially only meant to work around an issue with delayed  	 * BA frames in some implementations, but it has been found to fix ACK  	 * timeout issues in other cases as well.  	 */ -	if (conf->channel && conf->channel->band == IEEE80211_BAND_2GHZ) +	if (conf->channel && conf->channel->band == IEEE80211_BAND_2GHZ) {  		acktimeout += 64 - sifstime - ah->slottime; +		ctstimeout += 48 - sifstime - ah->slottime; +	} +  	ath9k_hw_set_sifs_time(ah, sifstime);  	ath9k_hw_setslottime(ah, slottime); diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index abf943557de..53a005d288a 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -822,6 +822,11 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc,  		ARRAY_SIZE(ath9k_tpt_blink));  #endif +	INIT_WORK(&sc->hw_reset_work, ath_reset_work); +	INIT_WORK(&sc->hw_check_work, ath_hw_check); +	INIT_WORK(&sc->paprd_work, ath_paprd_calibrate); +	INIT_DELAYED_WORK(&sc->hw_pll_work, ath_hw_pll_work); +  	/* Register with mac80211 */  	error = ieee80211_register_hw(hw);  	if (error) @@ -840,10 +845,6 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc,  			goto error_world;  	} -	INIT_WORK(&sc->hw_reset_work, ath_reset_work); -	INIT_WORK(&sc->hw_check_work, ath_hw_check); -	INIT_WORK(&sc->paprd_work, ath_paprd_calibrate); -	INIT_DELAYED_WORK(&sc->hw_pll_work, ath_hw_pll_work);  	sc->last_rssi = ATH_RSSI_DUMMY_MARKER;  	ath_init_leds(sc); diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index b3c3798fe51..635b592ad96 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c @@ -694,7 +694,7 @@ static u8 ath_rc_get_highest_rix(struct ath_softc *sc,  		return rate;  	/* This should not happen */ -	WARN_ON(1); +	WARN_ON_ONCE(1);  	rate = ath_rc_priv->valid_rate_index[0]; diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 0e666fbe084..7e1a91af149 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -822,6 +822,14 @@ static bool ath9k_rx_accept(struct ath_common *common,  		(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_CRC | ATH9K_RXERR_MIC |  		 ATH9K_RXERR_KEYMISS)); +	/* +	 * Key miss events are only relevant for pairwise keys where the +	 * descriptor does contain a valid key index. This has been observed +	 * mostly with CCMP encryption. +	 */ +	if (rx_stats->rs_keyix == ATH9K_RXKEYIX_INVALID) +		rx_stats->rs_status &= ~ATH9K_RXERR_KEYMISS; +  	if (!rx_stats->rs_datalen)  		return false;          /* diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index c664c272655..63bbc60be28 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -91,6 +91,7 @@ static void iwlagn_tx_cmd_build_basic(struct iwl_priv *priv,  		tx_cmd->tid_tspec = qc[0] & 0xf;  		tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK;  	} else { +		tx_cmd->tid_tspec = IWL_TID_NON_QOS;  		if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ)  			tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;  		else @@ -620,7 +621,7 @@ int iwlagn_tx_agg_oper(struct iwl_priv *priv, struct ieee80211_vif *vif,  	sta_priv->lq_sta.lq.agg_params.agg_frame_cnt_limit =  		sta_priv->max_agg_bufsize; -	IWL_INFO(priv, "Tx aggregation enabled on ra = %pM tid = %d\n", +	IWL_DEBUG_HT(priv, "Tx aggregation enabled on ra = %pM tid = %d\n",  		 sta->addr, tid);  	return iwl_send_lq_cmd(priv, ctx, @@ -808,6 +809,8 @@ static void iwl_rx_reply_tx_agg(struct iwl_priv *priv,  	u32 status = le16_to_cpu(tx_resp->status.status);  	int i; +	WARN_ON(tid == IWL_TID_NON_QOS); +  	if (agg->wait_for_ba)  		IWL_DEBUG_TX_REPLY(priv,  			"got tx response w/o block-ack\n"); @@ -1035,10 +1038,13 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,  		}  		__skb_queue_head_init(&skbs); -		priv->tid_data[sta_id][tid].next_reclaimed = next_reclaimed; -		IWL_DEBUG_TX_REPLY(priv, "Next reclaimed packet:%d", -					  next_reclaimed); +		if (tid != IWL_TID_NON_QOS) { +			priv->tid_data[sta_id][tid].next_reclaimed = +				next_reclaimed; +			IWL_DEBUG_TX_REPLY(priv, "Next reclaimed packet:%d", +						  next_reclaimed); +		}  		/*we can free until ssn % q.n_bd not inclusive */  		WARN_ON(iwl_trans_reclaim(trans(priv), sta_id, tid, txq_id, diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 265de39d394..f822ac447c3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -815,6 +815,7 @@ struct iwl_qosparam_cmd {  #define	IWL_INVALID_STATION 	255  #define IWL_MAX_TID_COUNT	8 +#define IWL_TID_NON_QOS IWL_MAX_TID_COUNT  #define STA_FLG_TX_RATE_MSK		cpu_to_le32(1 << 2)  #define STA_FLG_PWR_SAVE_MSK		cpu_to_le32(1 << 8) diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c index 67d6e324e26..324d06dfb69 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c @@ -1262,6 +1262,7 @@ static int iwl_trans_pcie_reclaim(struct iwl_trans *trans, int sta_id, int tid,  	txq->time_stamp = jiffies;  	if (unlikely(txq_id >= IWLAGN_FIRST_AMPDU_QUEUE && +		     tid != IWL_TID_NON_QOS &&  		     txq_id != trans_pcie->agg_txq[sta_id][tid])) {  		/*  		 * FIXME: this is a uCode bug which need to be addressed, diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c index e05b417a3fa..1d0ec57a014 100644 --- a/drivers/net/wireless/mwifiex/init.c +++ b/drivers/net/wireless/mwifiex/init.c @@ -382,7 +382,8 @@ mwifiex_free_adapter(struct mwifiex_adapter *adapter)  	adapter->if_ops.cleanup_if(adapter); -	dev_kfree_skb_any(adapter->sleep_cfm); +	if (adapter->sleep_cfm) +		dev_kfree_skb_any(adapter->sleep_cfm);  }  /* diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c index 84be196188c..b728f54451e 100644 --- a/drivers/net/wireless/mwifiex/main.c +++ b/drivers/net/wireless/mwifiex/main.c @@ -822,7 +822,9 @@ int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem)  			continue;  		rtnl_lock(); -		mwifiex_del_virtual_intf(priv->wdev->wiphy, priv->netdev); +		if (priv->wdev && priv->netdev) +			mwifiex_del_virtual_intf(priv->wdev->wiphy, +						 priv->netdev);  		rtnl_unlock();  	} @@ -830,9 +832,11 @@ int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem)  	if (!priv)  		goto exit_remove; -	wiphy_unregister(priv->wdev->wiphy); -	wiphy_free(priv->wdev->wiphy); -	kfree(priv->wdev); +	if (priv->wdev) { +		wiphy_unregister(priv->wdev->wiphy); +		wiphy_free(priv->wdev->wiphy); +		kfree(priv->wdev); +	}  	mwifiex_terminate_workqueue(adapter); diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c index 470ca75ec25..b0fbf5d4fea 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c @@ -54,7 +54,7 @@ int mwifiex_copy_mcast_addr(struct mwifiex_multicast_list *mlist,  int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter)  {  	bool cancel_flag = false; -	int status = adapter->cmd_wait_q.status; +	int status;  	struct cmd_ctrl_node *cmd_queued;  	if (!adapter->cmd_queued) @@ -79,6 +79,8 @@ int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter)  		mwifiex_cancel_pending_ioctl(adapter);  		dev_dbg(adapter->dev, "cmd cancel\n");  	} + +	status = adapter->cmd_wait_q.status;  	adapter->cmd_wait_q.status = 0;  	return status; @@ -240,6 +242,8 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,  		if (!netif_queue_stopped(priv->netdev))  			mwifiex_stop_net_dev_queue(priv->netdev, adapter); +		if (netif_carrier_ok(priv->netdev)) +			netif_carrier_off(priv->netdev);  		/* Clear any past association response stored for  		 * application retrieval */ @@ -271,6 +275,8 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,  		if (!netif_queue_stopped(priv->netdev))  			mwifiex_stop_net_dev_queue(priv->netdev, adapter); +		if (netif_carrier_ok(priv->netdev)) +			netif_carrier_off(priv->netdev);  		if (!ret) {  			dev_dbg(adapter->dev, "info: network found in scan" diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 22a1a8fc6e0..7bef66def10 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -514,9 +514,9 @@ EXPORT_SYMBOL_GPL(rt2800_write_tx_data);  static int rt2800_agc_to_rssi(struct rt2x00_dev *rt2x00dev, u32 rxwi_w2)  { -	int rssi0 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI0); -	int rssi1 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI1); -	int rssi2 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI2); +	s8 rssi0 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI0); +	s8 rssi1 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI1); +	s8 rssi2 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI2);  	u16 eeprom;  	u8 offset0;  	u8 offset1; @@ -552,7 +552,7 @@ static int rt2800_agc_to_rssi(struct rt2x00_dev *rt2x00dev, u32 rxwi_w2)  	 * which gives less energy...  	 */  	rssi0 = max(rssi0, rssi1); -	return max(rssi0, rssi2); +	return (int)max(rssi0, rssi2);  }  void rt2800_process_rxwi(struct queue_entry *entry, diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index 0a70149df3f..98a574a4a46 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c @@ -866,6 +866,14 @@ static int fill_ctrlset(struct zd_mac *mac,  	ZD_ASSERT(frag_len <= 0xffff); +	/* +	 * Firmware computes the duration itself (for all frames except PSPoll) +	 * and needs the field set to 0 at input, otherwise firmware messes up +	 * duration_id and sets bits 14 and 15 on. +	 */ +	if (!ieee80211_is_pspoll(hdr->frame_control)) +		hdr->duration_id = 0; +  	txrate = ieee80211_get_tx_rate(mac->hw, info);  	cs->modulation = txrate->hw_value; diff --git a/drivers/of/platform.c b/drivers/of/platform.c index 63b3ec48c20..20fbebd49db 100644 --- a/drivers/of/platform.c +++ b/drivers/of/platform.c @@ -55,7 +55,7 @@ EXPORT_SYMBOL(of_find_device_by_node);  #include <asm/dcr.h>  #endif -#if !defined(CONFIG_SPARC) +#ifdef CONFIG_OF_ADDRESS  /*   * The following routines scan a subtree and registers a device for   * each applicable node. @@ -462,4 +462,4 @@ int of_platform_populate(struct device_node *root,  	of_node_put(root);  	return rc;  } -#endif /* !CONFIG_SPARC */ +#endif /* CONFIG_OF_ADDRESS */ diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 749c2a16012..1932029de48 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c @@ -1269,10 +1269,8 @@ static int pcmcia_bus_add(struct pcmcia_socket *skt)  static int pcmcia_bus_early_resume(struct pcmcia_socket *skt)  { -	if (!verify_cis_cache(skt)) { -		pcmcia_put_socket(skt); +	if (!verify_cis_cache(skt))  		return 0; -	}  	dev_dbg(&skt->dev, "cis mismatch - different card\n"); diff --git a/drivers/power/bq27x00_battery.c b/drivers/power/bq27x00_battery.c index 98bf5676318..1ed6ea0bad6 100644 --- a/drivers/power/bq27x00_battery.c +++ b/drivers/power/bq27x00_battery.c @@ -62,11 +62,10 @@  #define BQ27500_REG_SOC			0x2C  #define BQ27500_REG_DCAP		0x3C /* Design capacity */ -#define BQ27500_FLAG_DSG		BIT(0) /* Discharging */ +#define BQ27500_FLAG_DSC		BIT(0)  #define BQ27500_FLAG_SOCF		BIT(1) /* State-of-Charge threshold final */  #define BQ27500_FLAG_SOC1		BIT(2) /* State-of-Charge threshold 1 */ -#define BQ27500_FLAG_CHG		BIT(8) /* Charging */ -#define BQ27500_FLAG_FC			BIT(9) /* Fully charged */ +#define BQ27500_FLAG_FC			BIT(9)  #define BQ27000_RS			20 /* Resistor sense */ @@ -312,7 +311,7 @@ static void bq27x00_update(struct bq27x00_device_info *di)  	struct bq27x00_reg_cache cache = {0, };  	bool is_bq27500 = di->chip == BQ27500; -	cache.flags = bq27x00_read(di, BQ27x00_REG_FLAGS, is_bq27500); +	cache.flags = bq27x00_read(di, BQ27x00_REG_FLAGS, !is_bq27500);  	if (cache.flags >= 0) {  		if (!is_bq27500 && (cache.flags & BQ27000_FLAG_CI)) {  			dev_info(di->dev, "battery is not calibrated! ignoring capacity values\n"); @@ -401,14 +400,10 @@ static int bq27x00_battery_status(struct bq27x00_device_info *di,  	if (di->chip == BQ27500) {  		if (di->cache.flags & BQ27500_FLAG_FC)  			status = POWER_SUPPLY_STATUS_FULL; -		else if (di->cache.flags & BQ27500_FLAG_DSG) +		else if (di->cache.flags & BQ27500_FLAG_DSC)  			status = POWER_SUPPLY_STATUS_DISCHARGING; -		else if (di->cache.flags & BQ27500_FLAG_CHG) -			status = POWER_SUPPLY_STATUS_CHARGING; -		else if (power_supply_am_i_supplied(&di->bat)) -			status = POWER_SUPPLY_STATUS_NOT_CHARGING;  		else -			status = POWER_SUPPLY_STATUS_UNKNOWN; +			status = POWER_SUPPLY_STATUS_CHARGING;  	} else {  		if (di->cache.flags & BQ27000_FLAG_FC)  			status = POWER_SUPPLY_STATUS_FULL; diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c index 0378d019efa..88fd9710bda 100644 --- a/drivers/power/charger-manager.c +++ b/drivers/power/charger-manager.c @@ -974,10 +974,11 @@ static int __devexit charger_manager_remove(struct platform_device *pdev)  	return 0;  } -const struct platform_device_id charger_manager_id[] = { +static const struct platform_device_id charger_manager_id[] = {  	{ "charger-manager", 0 },  	{ },  }; +MODULE_DEVICE_TABLE(platform, charger_manager_id);  static int cm_suspend_prepare(struct device *dev)  { @@ -1069,4 +1070,3 @@ module_exit(charger_manager_cleanup);  MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>");  MODULE_DESCRIPTION("Charger Manager");  MODULE_LICENSE("GPL"); -MODULE_ALIAS("charger-manager"); diff --git a/drivers/power/lp8727_charger.c b/drivers/power/lp8727_charger.c index b15b575c070..c53dd1292f8 100644 --- a/drivers/power/lp8727_charger.c +++ b/drivers/power/lp8727_charger.c @@ -464,6 +464,7 @@ static int __devexit lp8727_remove(struct i2c_client *cl)  static const struct i2c_device_id lp8727_ids[] = {  	{"lp8727", 0}, +	{ }  };  static struct i2c_driver lp8727_driver = { diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 3f9a47ec67d..8293658e7cf 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -299,7 +299,7 @@ config SPI_S3C24XX_FIQ  config SPI_S3C64XX  	tristate "Samsung S3C64XX series type SPI" -	depends on (ARCH_S3C64XX || ARCH_S5P64X0) +	depends on (ARCH_S3C64XX || ARCH_S5P64X0 || ARCH_EXYNOS)  	select S3C64XX_DMA if ARCH_S3C64XX  	help  	  SPI driver for Samsung S3C64XX and newer SoCs. diff --git a/drivers/spi/spi-topcliff-pch.c b/drivers/spi/spi-topcliff-pch.c index 2a6429d8c36..10182eb5006 100644 --- a/drivers/spi/spi-topcliff-pch.c +++ b/drivers/spi/spi-topcliff-pch.c @@ -1720,7 +1720,7 @@ static int pch_spi_resume(struct pci_dev *pdev)  #endif -static struct pci_driver pch_spi_pcidev = { +static struct pci_driver pch_spi_pcidev_driver = {  	.name = "pch_spi",  	.id_table = pch_spi_pcidev_id,  	.probe = pch_spi_probe, @@ -1736,7 +1736,7 @@ static int __init pch_spi_init(void)  	if (ret)  		return ret; -	ret = pci_register_driver(&pch_spi_pcidev); +	ret = pci_register_driver(&pch_spi_pcidev_driver);  	if (ret)  		return ret; @@ -1746,7 +1746,7 @@ module_init(pch_spi_init);  static void __exit pch_spi_exit(void)  { -	pci_unregister_driver(&pch_spi_pcidev); +	pci_unregister_driver(&pch_spi_pcidev_driver);  	platform_driver_unregister(&pch_spi_pd_driver);  }  module_exit(pch_spi_exit); diff --git a/drivers/ssb/driver_pcicore.c b/drivers/ssb/driver_pcicore.c index 520e8286db2..49d209173f5 100644 --- a/drivers/ssb/driver_pcicore.c +++ b/drivers/ssb/driver_pcicore.c @@ -75,7 +75,7 @@ static u32 get_cfgspace_addr(struct ssb_pcicore *pc,  	u32 tmp;  	/* We do only have one cardbus device behind the bridge. */ -	if (pc->cardbusmode && (dev >= 1)) +	if (pc->cardbusmode && (dev > 1))  		goto out;  	if (bus == 0) { diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 21e2f4b87f1..9e634724978 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -60,8 +60,6 @@ source "drivers/staging/rts5139/Kconfig"  source "drivers/staging/frontier/Kconfig" -source "drivers/staging/pohmelfs/Kconfig" -  source "drivers/staging/phison/Kconfig"  source "drivers/staging/line6/Kconfig" @@ -120,8 +118,6 @@ source "drivers/staging/cptm1217/Kconfig"  source "drivers/staging/ste_rmi4/Kconfig" -source "drivers/staging/gma500/Kconfig" -  source "drivers/staging/mei/Kconfig"  source "drivers/staging/nvec/Kconfig" diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 7c5808d7212..943e1483075 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -22,7 +22,6 @@ obj-$(CONFIG_R8712U)		+= rtl8712/  obj-$(CONFIG_RTS_PSTOR)		+= rts_pstor/  obj-$(CONFIG_RTS5139)		+= rts5139/  obj-$(CONFIG_TRANZPORT)		+= frontier/ -obj-$(CONFIG_POHMELFS)		+= pohmelfs/  obj-$(CONFIG_IDE_PHISON)	+= phison/  obj-$(CONFIG_LINE6_USB)		+= line6/  obj-$(CONFIG_USB_SERIAL_QUATECH2)	+= serqt_usb2/ @@ -52,7 +51,6 @@ obj-$(CONFIG_FT1000)		+= ft1000/  obj-$(CONFIG_SPEAKUP)		+= speakup/  obj-$(CONFIG_TOUCHSCREEN_CLEARPAD_TM1217)	+= cptm1217/  obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4)	+= ste_rmi4/ -obj-$(CONFIG_DRM_PSB)		+= gma500/  obj-$(CONFIG_INTEL_MEI)		+= mei/  obj-$(CONFIG_MFD_NVEC)		+= nvec/  obj-$(CONFIG_DRM_OMAP)		+= omapdrm/ diff --git a/drivers/staging/android/Kconfig b/drivers/staging/android/Kconfig index becf711117e..fef3580ce8d 100644 --- a/drivers/staging/android/Kconfig +++ b/drivers/staging/android/Kconfig @@ -27,6 +27,7 @@ config ANDROID_LOGGER  config ANDROID_RAM_CONSOLE  	bool "Android RAM buffer console" +	depends on !S390 && !UML  	default n  config ANDROID_RAM_CONSOLE_ENABLE_VERBOSE @@ -99,10 +100,6 @@ config ANDROID_LOW_MEMORY_KILLER  	---help---  	  Register processes to be killed when memory is low -config ANDROID_PMEM -	bool "Android pmem allocator" -	depends on ARM -  source "drivers/staging/android/switch/Kconfig"  endif # if ANDROID diff --git a/drivers/staging/android/Makefile b/drivers/staging/android/Makefile index eaed1ff64f0..5fcc24ffdd5 100644 --- a/drivers/staging/android/Makefile +++ b/drivers/staging/android/Makefile @@ -5,5 +5,4 @@ obj-$(CONFIG_ANDROID_RAM_CONSOLE)	+= ram_console.o  obj-$(CONFIG_ANDROID_TIMED_OUTPUT)	+= timed_output.o  obj-$(CONFIG_ANDROID_TIMED_GPIO)	+= timed_gpio.o  obj-$(CONFIG_ANDROID_LOW_MEMORY_KILLER)	+= lowmemorykiller.o -obj-$(CONFIG_ANDROID_PMEM)		+= pmem.o  obj-$(CONFIG_ANDROID_SWITCH)		+= switch/ diff --git a/drivers/staging/android/android_pmem.h b/drivers/staging/android/android_pmem.h deleted file mode 100644 index f633621f5be..00000000000 --- a/drivers/staging/android/android_pmem.h +++ /dev/null @@ -1,93 +0,0 @@ -/* include/linux/android_pmem.h - * - * Copyright (C) 2007 Google, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * 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. - * - */ - -#ifndef _ANDROID_PMEM_H_ -#define _ANDROID_PMEM_H_ - -#define PMEM_IOCTL_MAGIC 'p' -#define PMEM_GET_PHYS		_IOW(PMEM_IOCTL_MAGIC, 1, unsigned int) -#define PMEM_MAP		_IOW(PMEM_IOCTL_MAGIC, 2, unsigned int) -#define PMEM_GET_SIZE		_IOW(PMEM_IOCTL_MAGIC, 3, unsigned int) -#define PMEM_UNMAP		_IOW(PMEM_IOCTL_MAGIC, 4, unsigned int) -/* This ioctl will allocate pmem space, backing the file, it will fail - * if the file already has an allocation, pass it the len as the argument - * to the ioctl */ -#define PMEM_ALLOCATE		_IOW(PMEM_IOCTL_MAGIC, 5, unsigned int) -/* This will connect a one pmem file to another, pass the file that is already - * backed in memory as the argument to the ioctl - */ -#define PMEM_CONNECT		_IOW(PMEM_IOCTL_MAGIC, 6, unsigned int) -/* Returns the total size of the pmem region it is sent to as a pmem_region - * struct (with offset set to 0).  - */ -#define PMEM_GET_TOTAL_SIZE	_IOW(PMEM_IOCTL_MAGIC, 7, unsigned int) -#define PMEM_CACHE_FLUSH	_IOW(PMEM_IOCTL_MAGIC, 8, unsigned int) - -struct android_pmem_platform_data -{ -	const char* name; -	/* starting physical address of memory region */ -	unsigned long start; -	/* size of memory region */ -	unsigned long size; -	/* set to indicate the region should not be managed with an allocator */ -	unsigned no_allocator; -	/* set to indicate maps of this region should be cached, if a mix of -	 * cached and uncached is desired, set this and open the device with -	 * O_SYNC to get an uncached region */ -	unsigned cached; -	/* The MSM7k has bits to enable a write buffer in the bus controller*/ -	unsigned buffered; -}; - -struct pmem_region { -	unsigned long offset; -	unsigned long len; -}; - -#ifdef CONFIG_ANDROID_PMEM -int is_pmem_file(struct file *file); -int get_pmem_file(int fd, unsigned long *start, unsigned long *vstart, -		  unsigned long *end, struct file **filp); -int get_pmem_user_addr(struct file *file, unsigned long *start, -		       unsigned long *end); -void put_pmem_file(struct file* file); -void flush_pmem_file(struct file *file, unsigned long start, unsigned long len); -int pmem_setup(struct android_pmem_platform_data *pdata, -	       long (*ioctl)(struct file *, unsigned int, unsigned long), -	       int (*release)(struct inode *, struct file *)); -int pmem_remap(struct pmem_region *region, struct file *file, -	       unsigned operation); - -#else -static inline int is_pmem_file(struct file *file) { return 0; } -static inline int get_pmem_file(int fd, unsigned long *start, -				unsigned long *vstart, unsigned long *end, -				struct file **filp) { return -ENOSYS; } -static inline int get_pmem_user_addr(struct file *file, unsigned long *start, -				     unsigned long *end) { return -ENOSYS; } -static inline void put_pmem_file(struct file* file) { return; } -static inline void flush_pmem_file(struct file *file, unsigned long start, -				   unsigned long len) { return; } -static inline int pmem_setup(struct android_pmem_platform_data *pdata, -	      long (*ioctl)(struct file *, unsigned int, unsigned long), -	      int (*release)(struct inode *, struct file *)) { return -ENOSYS; } - -static inline int pmem_remap(struct pmem_region *region, struct file *file, -			     unsigned operation) { return -ENOSYS; } -#endif - -#endif //_ANDROID_PPP_H_ - diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c index 7491801a661..f0b7e6605ab 100644 --- a/drivers/staging/android/binder.c +++ b/drivers/staging/android/binder.c @@ -38,6 +38,7 @@  static DEFINE_MUTEX(binder_lock);  static DEFINE_MUTEX(binder_deferred_lock); +static DEFINE_MUTEX(binder_mmap_lock);  static HLIST_HEAD(binder_procs);  static HLIST_HEAD(binder_deferred_list); @@ -632,6 +633,11 @@ static int binder_update_page_range(struct binder_proc *proc, int allocate,  	if (mm) {  		down_write(&mm->mmap_sem);  		vma = proc->vma; +		if (vma && mm != vma->vm_mm) { +			pr_err("binder: %d: vma mm and task mm mismatch\n", +				proc->pid); +			vma = NULL; +		}  	}  	if (allocate == 0) @@ -2759,7 +2765,6 @@ static void binder_vma_open(struct vm_area_struct *vma)  		     proc->pid, vma->vm_start, vma->vm_end,  		     (vma->vm_end - vma->vm_start) / SZ_1K, vma->vm_flags,  		     (unsigned long)pgprot_val(vma->vm_page_prot)); -	dump_stack();  }  static void binder_vma_close(struct vm_area_struct *vma) @@ -2803,6 +2808,7 @@ static int binder_mmap(struct file *filp, struct vm_area_struct *vma)  	}  	vma->vm_flags = (vma->vm_flags | VM_DONTCOPY) & ~VM_MAYWRITE; +	mutex_lock(&binder_mmap_lock);  	if (proc->buffer) {  		ret = -EBUSY;  		failure_string = "already mapped"; @@ -2817,6 +2823,7 @@ static int binder_mmap(struct file *filp, struct vm_area_struct *vma)  	}  	proc->buffer = area->addr;  	proc->user_buffer_offset = vma->vm_start - (uintptr_t)proc->buffer; +	mutex_unlock(&binder_mmap_lock);  #ifdef CONFIG_CPU_CACHE_VIPT  	if (cache_is_vipt_aliasing()) { @@ -2849,7 +2856,7 @@ static int binder_mmap(struct file *filp, struct vm_area_struct *vma)  	binder_insert_free_buffer(proc, buffer);  	proc->free_async_space = proc->buffer_size / 2;  	barrier(); -	proc->files = get_files_struct(current); +	proc->files = get_files_struct(proc->tsk);  	proc->vma = vma;  	/*printk(KERN_INFO "binder_mmap: %d %lx-%lx maps %p\n", @@ -2860,10 +2867,12 @@ err_alloc_small_buf_failed:  	kfree(proc->pages);  	proc->pages = NULL;  err_alloc_pages_failed: +	mutex_lock(&binder_mmap_lock);  	vfree(proc->buffer);  	proc->buffer = NULL;  err_get_vm_area_failed:  err_already_mapped: +	mutex_unlock(&binder_mmap_lock);  err_bad_arg:  	printk(KERN_ERR "binder_mmap: %d %lx-%lx %s failed %d\n",  	       proc->pid, vma->vm_start, vma->vm_end, failure_string, ret); diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c index 2d8d2b79610..efc7dc1f483 100644 --- a/drivers/staging/android/lowmemorykiller.c +++ b/drivers/staging/android/lowmemorykiller.c @@ -54,6 +54,7 @@ static size_t lowmem_minfree[6] = {  static int lowmem_minfree_size = 4;  static struct task_struct *lowmem_deathpending; +static unsigned long lowmem_deathpending_timeout;  #define lowmem_print(level, x...)			\  	do {						\ @@ -103,7 +104,8 @@ static int lowmem_shrink(struct shrinker *s, struct shrink_control *sc)  	 * Note: Currently you need CONFIG_PROFILING  	 * for this to work correctly.  	 */ -	if (lowmem_deathpending) +	if (lowmem_deathpending && +	    time_before_eq(jiffies, lowmem_deathpending_timeout))  		return 0;  	if (lowmem_adj_size < array_size) @@ -178,6 +180,7 @@ static int lowmem_shrink(struct shrinker *s, struct shrink_control *sc)  		 */  #ifdef CONFIG_PROFILING  		lowmem_deathpending = selected; +		lowmem_deathpending_timeout = jiffies + HZ;  		task_handoff_register(&task_nb);  #endif  		force_sig(SIGKILL, selected); diff --git a/drivers/staging/android/pmem.c b/drivers/staging/android/pmem.c deleted file mode 100644 index 7d97032c650..00000000000 --- a/drivers/staging/android/pmem.c +++ /dev/null @@ -1,1345 +0,0 @@ -/* pmem.c - * - * Copyright (C) 2007 Google, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * 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. - * - */ - -#include <linux/miscdevice.h> -#include <linux/platform_device.h> -#include <linux/fs.h> -#include <linux/file.h> -#include <linux/mm.h> -#include <linux/list.h> -#include <linux/mutex.h> -#include <linux/debugfs.h> -#include <linux/mempolicy.h> -#include <linux/sched.h> -#include <asm/io.h> -#include <asm/uaccess.h> -#include <asm/cacheflush.h> -#include "android_pmem.h" - -#define PMEM_MAX_DEVICES 10 -#define PMEM_MAX_ORDER 128 -#define PMEM_MIN_ALLOC PAGE_SIZE - -#define PMEM_DEBUG 1 - -/* indicates that a refernce to this file has been taken via get_pmem_file, - * the file should not be released until put_pmem_file is called */ -#define PMEM_FLAGS_BUSY 0x1 -/* indicates that this is a suballocation of a larger master range */ -#define PMEM_FLAGS_CONNECTED 0x1 << 1 -/* indicates this is a master and not a sub allocation and that it is mmaped */ -#define PMEM_FLAGS_MASTERMAP 0x1 << 2 -/* submap and unsubmap flags indicate: - * 00: subregion has never been mmaped - * 10: subregion has been mmaped, reference to the mm was taken - * 11: subretion has ben released, refernece to the mm still held - * 01: subretion has been released, reference to the mm has been released - */ -#define PMEM_FLAGS_SUBMAP 0x1 << 3 -#define PMEM_FLAGS_UNSUBMAP 0x1 << 4 - - -struct pmem_data { -	/* in alloc mode: an index into the bitmap -	 * in no_alloc mode: the size of the allocation */ -	int index; -	/* see flags above for descriptions */ -	unsigned int flags; -	/* protects this data field, if the mm_mmap sem will be held at the -	 * same time as this sem, the mm sem must be taken first (as this is -	 * the order for vma_open and vma_close ops */ -	struct rw_semaphore sem; -	/* info about the mmaping process */ -	struct vm_area_struct *vma; -	/* task struct of the mapping process */ -	struct task_struct *task; -	/* process id of teh mapping process */ -	pid_t pid; -	/* file descriptor of the master */ -	int master_fd; -	/* file struct of the master */ -	struct file *master_file; -	/* a list of currently available regions if this is a suballocation */ -	struct list_head region_list; -	/* a linked list of data so we can access them for debugging */ -	struct list_head list; -#if PMEM_DEBUG -	int ref; -#endif -}; - -struct pmem_bits { -	unsigned allocated:1;		/* 1 if allocated, 0 if free */ -	unsigned order:7;		/* size of the region in pmem space */ -}; - -struct pmem_region_node { -	struct pmem_region region; -	struct list_head list; -}; - -#define PMEM_DEBUG_MSGS 0 -#if PMEM_DEBUG_MSGS -#define DLOG(fmt,args...) \ -	do { printk(KERN_INFO "[%s:%s:%d] "fmt, __FILE__, __func__, __LINE__, \ -		    ##args); } \ -	while (0) -#else -#define DLOG(x...) do {} while (0) -#endif - -struct pmem_info { -	struct miscdevice dev; -	/* physical start address of the remaped pmem space */ -	unsigned long base; -	/* vitual start address of the remaped pmem space */ -	unsigned char __iomem *vbase; -	/* total size of the pmem space */ -	unsigned long size; -	/* number of entries in the pmem space */ -	unsigned long num_entries; -	/* pfn of the garbage page in memory */ -	unsigned long garbage_pfn; -	/* index of the garbage page in the pmem space */ -	int garbage_index; -	/* the bitmap for the region indicating which entries are allocated -	 * and which are free */ -	struct pmem_bits *bitmap; -	/* indicates the region should not be managed with an allocator */ -	unsigned no_allocator; -	/* indicates maps of this region should be cached, if a mix of -	 * cached and uncached is desired, set this and open the device with -	 * O_SYNC to get an uncached region */ -	unsigned cached; -	unsigned buffered; -	/* in no_allocator mode the first mapper gets the whole space and sets -	 * this flag */ -	unsigned allocated; -	/* for debugging, creates a list of pmem file structs, the -	 * data_list_lock should be taken before pmem_data->sem if both are -	 * needed */ -	struct mutex data_list_lock; -	struct list_head data_list; -	/* pmem_sem protects the bitmap array -	 * a write lock should be held when modifying entries in bitmap -	 * a read lock should be held when reading data from bits or -	 * dereferencing a pointer into bitmap -	 * -	 * pmem_data->sem protects the pmem data of a particular file -	 * Many of the function that require the pmem_data->sem have a non- -	 * locking version for when the caller is already holding that sem. -	 * -	 * IF YOU TAKE BOTH LOCKS TAKE THEM IN THIS ORDER: -	 * down(pmem_data->sem) => down(bitmap_sem) -	 */ -	struct rw_semaphore bitmap_sem; - -	long (*ioctl)(struct file *, unsigned int, unsigned long); -	int (*release)(struct inode *, struct file *); -}; - -static struct pmem_info pmem[PMEM_MAX_DEVICES]; -static int id_count; - -#define PMEM_IS_FREE(id, index) !(pmem[id].bitmap[index].allocated) -#define PMEM_ORDER(id, index) pmem[id].bitmap[index].order -#define PMEM_BUDDY_INDEX(id, index) (index ^ (1 << PMEM_ORDER(id, index))) -#define PMEM_NEXT_INDEX(id, index) (index + (1 << PMEM_ORDER(id, index))) -#define PMEM_OFFSET(index) (index * PMEM_MIN_ALLOC) -#define PMEM_START_ADDR(id, index) (PMEM_OFFSET(index) + pmem[id].base) -#define PMEM_LEN(id, index) ((1 << PMEM_ORDER(id, index)) * PMEM_MIN_ALLOC) -#define PMEM_END_ADDR(id, index) (PMEM_START_ADDR(id, index) + \ -	PMEM_LEN(id, index)) -#define PMEM_START_VADDR(id, index) (PMEM_OFFSET(id, index) + pmem[id].vbase) -#define PMEM_END_VADDR(id, index) (PMEM_START_VADDR(id, index) + \ -	PMEM_LEN(id, index)) -#define PMEM_REVOKED(data) (data->flags & PMEM_FLAGS_REVOKED) -#define PMEM_IS_PAGE_ALIGNED(addr) (!((addr) & (~PAGE_MASK))) -#define PMEM_IS_SUBMAP(data) ((data->flags & PMEM_FLAGS_SUBMAP) && \ -	(!(data->flags & PMEM_FLAGS_UNSUBMAP))) - -static int pmem_release(struct inode *, struct file *); -static int pmem_mmap(struct file *, struct vm_area_struct *); -static int pmem_open(struct inode *, struct file *); -static long pmem_ioctl(struct file *, unsigned int, unsigned long); - -struct file_operations pmem_fops = { -	.release = pmem_release, -	.mmap = pmem_mmap, -	.open = pmem_open, -	.unlocked_ioctl = pmem_ioctl, -}; - -static int get_id(struct file *file) -{ -	return MINOR(file->f_dentry->d_inode->i_rdev); -} - -int is_pmem_file(struct file *file) -{ -	int id; - -	if (unlikely(!file || !file->f_dentry || !file->f_dentry->d_inode)) -		return 0; -	id = get_id(file); -	if (unlikely(id >= PMEM_MAX_DEVICES)) -		return 0; -	if (unlikely(file->f_dentry->d_inode->i_rdev != -	     MKDEV(MISC_MAJOR, pmem[id].dev.minor))) -		return 0; -	return 1; -} - -static int has_allocation(struct file *file) -{ -	struct pmem_data *data; -	/* check is_pmem_file first if not accessed via pmem_file_ops */ - -	if (unlikely(!file->private_data)) -		return 0; -	data = (struct pmem_data *)file->private_data; -	if (unlikely(data->index < 0)) -		return 0; -	return 1; -} - -static int is_master_owner(struct file *file) -{ -	struct file *master_file; -	struct pmem_data *data; -	int put_needed, ret = 0; - -	if (!is_pmem_file(file) || !has_allocation(file)) -		return 0; -	data = (struct pmem_data *)file->private_data; -	if (PMEM_FLAGS_MASTERMAP & data->flags) -		return 1; -	master_file = fget_light(data->master_fd, &put_needed); -	if (master_file && data->master_file == master_file) -		ret = 1; -	fput_light(master_file, put_needed); -	return ret; -} - -static int pmem_free(int id, int index) -{ -	/* caller should hold the write lock on pmem_sem! */ -	int buddy, curr = index; -	DLOG("index %d\n", index); - -	if (pmem[id].no_allocator) { -		pmem[id].allocated = 0; -		return 0; -	} -	/* clean up the bitmap, merging any buddies */ -	pmem[id].bitmap[curr].allocated = 0; -	/* find a slots buddy Buddy# = Slot# ^ (1 << order) -	 * if the buddy is also free merge them -	 * repeat until the buddy is not free or end of the bitmap is reached -	 */ -	do { -		buddy = PMEM_BUDDY_INDEX(id, curr); -		if (PMEM_IS_FREE(id, buddy) && -				PMEM_ORDER(id, buddy) == PMEM_ORDER(id, curr)) { -			PMEM_ORDER(id, buddy)++; -			PMEM_ORDER(id, curr)++; -			curr = min(buddy, curr); -		} else { -			break; -		} -	} while (curr < pmem[id].num_entries); - -	return 0; -} - -static void pmem_revoke(struct file *file, struct pmem_data *data); - -static int pmem_release(struct inode *inode, struct file *file) -{ -	struct pmem_data *data = (struct pmem_data *)file->private_data; -	struct pmem_region_node *region_node; -	struct list_head *elt, *elt2; -	int id = get_id(file), ret = 0; - - -	mutex_lock(&pmem[id].data_list_lock); -	/* if this file is a master, revoke all the memory in the connected -	 *  files */ -	if (PMEM_FLAGS_MASTERMAP & data->flags) { -		struct pmem_data *sub_data; -		list_for_each(elt, &pmem[id].data_list) { -			sub_data = list_entry(elt, struct pmem_data, list); -			down_read(&sub_data->sem); -			if (PMEM_IS_SUBMAP(sub_data) && -			    file == sub_data->master_file) { -				up_read(&sub_data->sem); -				pmem_revoke(file, sub_data); -			}  else -				up_read(&sub_data->sem); -		} -	} -	list_del(&data->list); -	mutex_unlock(&pmem[id].data_list_lock); - - -	down_write(&data->sem); - -	/* if its not a conencted file and it has an allocation, free it */ -	if (!(PMEM_FLAGS_CONNECTED & data->flags) && has_allocation(file)) { -		down_write(&pmem[id].bitmap_sem); -		ret = pmem_free(id, data->index); -		up_write(&pmem[id].bitmap_sem); -	} - -	/* if this file is a submap (mapped, connected file), downref the -	 * task struct */ -	if (PMEM_FLAGS_SUBMAP & data->flags) -		if (data->task) { -			put_task_struct(data->task); -			data->task = NULL; -		} - -	file->private_data = NULL; - -	list_for_each_safe(elt, elt2, &data->region_list) { -		region_node = list_entry(elt, struct pmem_region_node, list); -		list_del(elt); -		kfree(region_node); -	} -	BUG_ON(!list_empty(&data->region_list)); - -	up_write(&data->sem); -	kfree(data); -	if (pmem[id].release) -		ret = pmem[id].release(inode, file); - -	return ret; -} - -static int pmem_open(struct inode *inode, struct file *file) -{ -	struct pmem_data *data; -	int id = get_id(file); -	int ret = 0; - -	DLOG("current %u file %p(%d)\n", current->pid, file, file_count(file)); -	/* setup file->private_data to indicate its unmapped */ -	/*  you can only open a pmem device one time */ -	if (file->private_data != NULL) -		return -1; -	data = kmalloc(sizeof(struct pmem_data), GFP_KERNEL); -	if (!data) { -		printk("pmem: unable to allocate memory for pmem metadata."); -		return -1; -	} -	data->flags = 0; -	data->index = -1; -	data->task = NULL; -	data->vma = NULL; -	data->pid = 0; -	data->master_file = NULL; -#if PMEM_DEBUG -	data->ref = 0; -#endif -	INIT_LIST_HEAD(&data->region_list); -	init_rwsem(&data->sem); - -	file->private_data = data; -	INIT_LIST_HEAD(&data->list); - -	mutex_lock(&pmem[id].data_list_lock); -	list_add(&data->list, &pmem[id].data_list); -	mutex_unlock(&pmem[id].data_list_lock); -	return ret; -} - -static unsigned long pmem_order(unsigned long len) -{ -	int i; - -	len = (len + PMEM_MIN_ALLOC - 1)/PMEM_MIN_ALLOC; -	len--; -	for (i = 0; i < sizeof(len)*8; i++) -		if (len >> i == 0) -			break; -	return i; -} - -static int pmem_allocate(int id, unsigned long len) -{ -	/* caller should hold the write lock on pmem_sem! */ -	/* return the corresponding pdata[] entry */ -	int curr = 0; -	int end = pmem[id].num_entries; -	int best_fit = -1; -	unsigned long order = pmem_order(len); - -	if (pmem[id].no_allocator) { -		DLOG("no allocator"); -		if ((len > pmem[id].size) || pmem[id].allocated) -			return -1; -		pmem[id].allocated = 1; -		return len; -	} - -	if (order > PMEM_MAX_ORDER) -		return -1; -	DLOG("order %lx\n", order); - -	/* look through the bitmap: -	 * 	if you find a free slot of the correct order use it -	 * 	otherwise, use the best fit (smallest with size > order) slot -	 */ -	while (curr < end) { -		if (PMEM_IS_FREE(id, curr)) { -			if (PMEM_ORDER(id, curr) == (unsigned char)order) { -				/* set the not free bit and clear others */ -				best_fit = curr; -				break; -			} -			if (PMEM_ORDER(id, curr) > (unsigned char)order && -			    (best_fit < 0 || -			     PMEM_ORDER(id, curr) < PMEM_ORDER(id, best_fit))) -				best_fit = curr; -		} -		curr = PMEM_NEXT_INDEX(id, curr); -	} - -	/* if best_fit < 0, there are no suitable slots, -	 * return an error -	 */ -	if (best_fit < 0) { -		printk("pmem: no space left to allocate!\n"); -		return -1; -	} - -	/* now partition the best fit: -	 * 	split the slot into 2 buddies of order - 1 -	 * 	repeat until the slot is of the correct order -	 */ -	while (PMEM_ORDER(id, best_fit) > (unsigned char)order) { -		int buddy; -		PMEM_ORDER(id, best_fit) -= 1; -		buddy = PMEM_BUDDY_INDEX(id, best_fit); -		PMEM_ORDER(id, buddy) = PMEM_ORDER(id, best_fit); -	} -	pmem[id].bitmap[best_fit].allocated = 1; -	return best_fit; -} - -static pgprot_t pmem_access_prot(struct file *file, pgprot_t vma_prot) -{ -	int id = get_id(file); -#ifdef pgprot_noncached -	if (pmem[id].cached == 0 || file->f_flags & O_SYNC) -		return pgprot_noncached(vma_prot); -#endif -#ifdef pgprot_ext_buffered -	else if (pmem[id].buffered) -		return pgprot_ext_buffered(vma_prot); -#endif -	return vma_prot; -} - -static unsigned long pmem_start_addr(int id, struct pmem_data *data) -{ -	if (pmem[id].no_allocator) -		return PMEM_START_ADDR(id, 0); -	else -		return PMEM_START_ADDR(id, data->index); - -} - -static void *pmem_start_vaddr(int id, struct pmem_data *data) -{ -	return pmem_start_addr(id, data) - pmem[id].base + pmem[id].vbase; -} - -static unsigned long pmem_len(int id, struct pmem_data *data) -{ -	if (pmem[id].no_allocator) -		return data->index; -	else -		return PMEM_LEN(id, data->index); -} - -static int pmem_map_garbage(int id, struct vm_area_struct *vma, -			    struct pmem_data *data, unsigned long offset, -			    unsigned long len) -{ -	int i, garbage_pages = len >> PAGE_SHIFT; - -	vma->vm_flags |= VM_IO | VM_RESERVED | VM_PFNMAP | VM_SHARED | VM_WRITE; -	for (i = 0; i < garbage_pages; i++) { -		if (vm_insert_pfn(vma, vma->vm_start + offset + (i * PAGE_SIZE), -		    pmem[id].garbage_pfn)) -			return -EAGAIN; -	} -	return 0; -} - -static int pmem_unmap_pfn_range(int id, struct vm_area_struct *vma, -				struct pmem_data *data, unsigned long offset, -				unsigned long len) -{ -	int garbage_pages; -	DLOG("unmap offset %lx len %lx\n", offset, len); - -	BUG_ON(!PMEM_IS_PAGE_ALIGNED(len)); - -	garbage_pages = len >> PAGE_SHIFT; -	zap_page_range(vma, vma->vm_start + offset, len, NULL); -	pmem_map_garbage(id, vma, data, offset, len); -	return 0; -} - -static int pmem_map_pfn_range(int id, struct vm_area_struct *vma, -			      struct pmem_data *data, unsigned long offset, -			      unsigned long len) -{ -	DLOG("map offset %lx len %lx\n", offset, len); -	BUG_ON(!PMEM_IS_PAGE_ALIGNED(vma->vm_start)); -	BUG_ON(!PMEM_IS_PAGE_ALIGNED(vma->vm_end)); -	BUG_ON(!PMEM_IS_PAGE_ALIGNED(len)); -	BUG_ON(!PMEM_IS_PAGE_ALIGNED(offset)); - -	if (io_remap_pfn_range(vma, vma->vm_start + offset, -		(pmem_start_addr(id, data) + offset) >> PAGE_SHIFT, -		len, vma->vm_page_prot)) { -		return -EAGAIN; -	} -	return 0; -} - -static int pmem_remap_pfn_range(int id, struct vm_area_struct *vma, -			      struct pmem_data *data, unsigned long offset, -			      unsigned long len) -{ -	/* hold the mm semp for the vma you are modifying when you call this */ -	BUG_ON(!vma); -	zap_page_range(vma, vma->vm_start + offset, len, NULL); -	return pmem_map_pfn_range(id, vma, data, offset, len); -} - -static void pmem_vma_open(struct vm_area_struct *vma) -{ -	struct file *file = vma->vm_file; -	struct pmem_data *data = file->private_data; -	int id = get_id(file); -	/* this should never be called as we don't support copying pmem -	 * ranges via fork */ -	BUG_ON(!has_allocation(file)); -	down_write(&data->sem); -	/* remap the garbage pages, forkers don't get access to the data */ -	pmem_unmap_pfn_range(id, vma, data, 0, vma->vm_start - vma->vm_end); -	up_write(&data->sem); -} - -static void pmem_vma_close(struct vm_area_struct *vma) -{ -	struct file *file = vma->vm_file; -	struct pmem_data *data = file->private_data; - -	DLOG("current %u ppid %u file %p count %d\n", current->pid, -	     current->parent->pid, file, file_count(file)); -	if (unlikely(!is_pmem_file(file) || !has_allocation(file))) { -		printk(KERN_WARNING "pmem: something is very wrong, you are " -		       "closing a vm backing an allocation that doesn't " -		       "exist!\n"); -		return; -	} -	down_write(&data->sem); -	if (data->vma == vma) { -		data->vma = NULL; -		if ((data->flags & PMEM_FLAGS_CONNECTED) && -		    (data->flags & PMEM_FLAGS_SUBMAP)) -			data->flags |= PMEM_FLAGS_UNSUBMAP; -	} -	/* the kernel is going to free this vma now anyway */ -	up_write(&data->sem); -} - -static struct vm_operations_struct vm_ops = { -	.open = pmem_vma_open, -	.close = pmem_vma_close, -}; - -static int pmem_mmap(struct file *file, struct vm_area_struct *vma) -{ -	struct pmem_data *data; -	int index; -	unsigned long vma_size =  vma->vm_end - vma->vm_start; -	int ret = 0, id = get_id(file); - -	if (vma->vm_pgoff || !PMEM_IS_PAGE_ALIGNED(vma_size)) { -#if PMEM_DEBUG -		printk(KERN_ERR "pmem: mmaps must be at offset zero, aligned" -				" and a multiple of pages_size.\n"); -#endif -		return -EINVAL; -	} - -	data = (struct pmem_data *)file->private_data; -	down_write(&data->sem); -	/* check this file isn't already mmaped, for submaps check this file -	 * has never been mmaped */ -	if ((data->flags & PMEM_FLAGS_SUBMAP) || -	    (data->flags & PMEM_FLAGS_UNSUBMAP)) { -#if PMEM_DEBUG -		printk(KERN_ERR "pmem: you can only mmap a pmem file once, " -		       "this file is already mmaped. %x\n", data->flags); -#endif -		ret = -EINVAL; -		goto error; -	} -	/* if file->private_data == unalloced, alloc*/ -	if (data && data->index == -1) { -		down_write(&pmem[id].bitmap_sem); -		index = pmem_allocate(id, vma->vm_end - vma->vm_start); -		up_write(&pmem[id].bitmap_sem); -		data->index = index; -	} -	/* either no space was available or an error occured */ -	if (!has_allocation(file)) { -		ret = -EINVAL; -		printk("pmem: could not find allocation for map.\n"); -		goto error; -	} - -	if (pmem_len(id, data) < vma_size) { -#if PMEM_DEBUG -		printk(KERN_WARNING "pmem: mmap size [%lu] does not match" -		       "size of backing region [%lu].\n", vma_size, -		       pmem_len(id, data)); -#endif -		ret = -EINVAL; -		goto error; -	} - -	vma->vm_pgoff = pmem_start_addr(id, data) >> PAGE_SHIFT; -	vma->vm_page_prot = pmem_access_prot(file, vma->vm_page_prot); - -	if (data->flags & PMEM_FLAGS_CONNECTED) { -		struct pmem_region_node *region_node; -		struct list_head *elt; -		if (pmem_map_garbage(id, vma, data, 0, vma_size)) { -			printk("pmem: mmap failed in kernel!\n"); -			ret = -EAGAIN; -			goto error; -		} -		list_for_each(elt, &data->region_list) { -			region_node = list_entry(elt, struct pmem_region_node, -						 list); -			DLOG("remapping file: %p %lx %lx\n", file, -				region_node->region.offset, -				region_node->region.len); -			if (pmem_remap_pfn_range(id, vma, data, -						 region_node->region.offset, -						 region_node->region.len)) { -				ret = -EAGAIN; -				goto error; -			} -		} -		data->flags |= PMEM_FLAGS_SUBMAP; -		get_task_struct(current->group_leader); -		data->task = current->group_leader; -		data->vma = vma; -#if PMEM_DEBUG -		data->pid = current->pid; -#endif -		DLOG("submmapped file %p vma %p pid %u\n", file, vma, -		     current->pid); -	} else { -		if (pmem_map_pfn_range(id, vma, data, 0, vma_size)) { -			printk(KERN_INFO "pmem: mmap failed in kernel!\n"); -			ret = -EAGAIN; -			goto error; -		} -		data->flags |= PMEM_FLAGS_MASTERMAP; -		data->pid = current->pid; -	} -	vma->vm_ops = &vm_ops; -error: -	up_write(&data->sem); -	return ret; -} - -/* the following are the api for accessing pmem regions by other drivers - * from inside the kernel */ -int get_pmem_user_addr(struct file *file, unsigned long *start, -		   unsigned long *len) -{ -	struct pmem_data *data; -	if (!is_pmem_file(file) || !has_allocation(file)) { -#if PMEM_DEBUG -		printk(KERN_INFO "pmem: requested pmem data from invalid" -				  "file.\n"); -#endif -		return -1; -	} -	data = (struct pmem_data *)file->private_data; -	down_read(&data->sem); -	if (data->vma) { -		*start = data->vma->vm_start; -		*len = data->vma->vm_end - data->vma->vm_start; -	} else { -		*start = 0; -		*len = 0; -	} -	up_read(&data->sem); -	return 0; -} - -int get_pmem_addr(struct file *file, unsigned long *start, -		  unsigned long *vstart, unsigned long *len) -{ -	struct pmem_data *data; -	int id; - -	if (!is_pmem_file(file) || !has_allocation(file)) { -		return -1; -	} - -	data = (struct pmem_data *)file->private_data; -	if (data->index == -1) { -#if PMEM_DEBUG -		printk(KERN_INFO "pmem: requested pmem data from file with no " -		       "allocation.\n"); -		return -1; -#endif -	} -	id = get_id(file); - -	down_read(&data->sem); -	*start = pmem_start_addr(id, data); -	*len = pmem_len(id, data); -	*vstart = (unsigned long)pmem_start_vaddr(id, data); -	up_read(&data->sem); -#if PMEM_DEBUG -	down_write(&data->sem); -	data->ref++; -	up_write(&data->sem); -#endif -	return 0; -} - -int get_pmem_file(int fd, unsigned long *start, unsigned long *vstart, -		  unsigned long *len, struct file **filp) -{ -	struct file *file; - -	file = fget(fd); -	if (unlikely(file == NULL)) { -		printk(KERN_INFO "pmem: requested data from file descriptor " -		       "that doesn't exist."); -		return -1; -	} - -	if (get_pmem_addr(file, start, vstart, len)) -		goto end; - -	if (filp) -		*filp = file; -	return 0; -end: -	fput(file); -	return -1; -} - -void put_pmem_file(struct file *file) -{ -	struct pmem_data *data; -	int id; - -	if (!is_pmem_file(file)) -		return; -	id = get_id(file); -	data = (struct pmem_data *)file->private_data; -#if PMEM_DEBUG -	down_write(&data->sem); -	if (data->ref == 0) { -		printk("pmem: pmem_put > pmem_get %s (pid %d)\n", -		       pmem[id].dev.name, data->pid); -		BUG(); -	} -	data->ref--; -	up_write(&data->sem); -#endif -	fput(file); -} - -void flush_pmem_file(struct file *file, unsigned long offset, unsigned long len) -{ -	struct pmem_data *data; -	int id; -	void *vaddr; -	struct pmem_region_node *region_node; -	struct list_head *elt; -	void *flush_start, *flush_end; - -	if (!is_pmem_file(file) || !has_allocation(file)) { -		return; -	} - -	id = get_id(file); -	data = (struct pmem_data *)file->private_data; -	if (!pmem[id].cached || file->f_flags & O_SYNC) -		return; - -	down_read(&data->sem); -	vaddr = pmem_start_vaddr(id, data); -	/* if this isn't a submmapped file, flush the whole thing */ -	if (unlikely(!(data->flags & PMEM_FLAGS_CONNECTED))) { -		dmac_flush_range(vaddr, vaddr + pmem_len(id, data)); -		goto end; -	} -	/* otherwise, flush the region of the file we are drawing */ -	list_for_each(elt, &data->region_list) { -		region_node = list_entry(elt, struct pmem_region_node, list); -		if ((offset >= region_node->region.offset) && -		    ((offset + len) <= (region_node->region.offset + -			region_node->region.len))) { -			flush_start = vaddr + region_node->region.offset; -			flush_end = flush_start + region_node->region.len; -			dmac_flush_range(flush_start, flush_end); -			break; -		} -	} -end: -	up_read(&data->sem); -} - -static int pmem_connect(unsigned long connect, struct file *file) -{ -	struct pmem_data *data = (struct pmem_data *)file->private_data; -	struct pmem_data *src_data; -	struct file *src_file; -	int ret = 0, put_needed; - -	down_write(&data->sem); -	/* retrieve the src file and check it is a pmem file with an alloc */ -	src_file = fget_light(connect, &put_needed); -	DLOG("connect %p to %p\n", file, src_file); -	if (!src_file) { -		printk("pmem: src file not found!\n"); -		ret = -EINVAL; -		goto err_no_file; -	} -	if (unlikely(!is_pmem_file(src_file) || !has_allocation(src_file))) { -		printk(KERN_INFO "pmem: src file is not a pmem file or has no " -		       "alloc!\n"); -		ret = -EINVAL; -		goto err_bad_file; -	} -	src_data = (struct pmem_data *)src_file->private_data; - -	if (has_allocation(file) && (data->index != src_data->index)) { -		printk("pmem: file is already mapped but doesn't match this" -		       " src_file!\n"); -		ret = -EINVAL; -		goto err_bad_file; -	} -	data->index = src_data->index; -	data->flags |= PMEM_FLAGS_CONNECTED; -	data->master_fd = connect; -	data->master_file = src_file; - -err_bad_file: -	fput_light(src_file, put_needed); -err_no_file: -	up_write(&data->sem); -	return ret; -} - -static void pmem_unlock_data_and_mm(struct pmem_data *data, -				    struct mm_struct *mm) -{ -	up_write(&data->sem); -	if (mm != NULL) { -		up_write(&mm->mmap_sem); -		mmput(mm); -	} -} - -static int pmem_lock_data_and_mm(struct file *file, struct pmem_data *data, -				 struct mm_struct **locked_mm) -{ -	int ret = 0; -	struct mm_struct *mm = NULL; -	*locked_mm = NULL; -lock_mm: -	down_read(&data->sem); -	if (PMEM_IS_SUBMAP(data)) { -		mm = get_task_mm(data->task); -		if (!mm) { -#if PMEM_DEBUG -			printk("pmem: can't remap task is gone!\n"); -#endif -			up_read(&data->sem); -			return -1; -		} -	} -	up_read(&data->sem); - -	if (mm) -		down_write(&mm->mmap_sem); - -	down_write(&data->sem); -	/* check that the file didn't get mmaped before we could take the -	 * data sem, this should be safe b/c you can only submap each file -	 * once */ -	if (PMEM_IS_SUBMAP(data) && !mm) { -		pmem_unlock_data_and_mm(data, mm); -		up_write(&data->sem); -		goto lock_mm; -	} -	/* now check that vma.mm is still there, it could have been -	 * deleted by vma_close before we could get the data->sem */ -	if ((data->flags & PMEM_FLAGS_UNSUBMAP) && (mm != NULL)) { -		/* might as well release this */ -		if (data->flags & PMEM_FLAGS_SUBMAP) { -			put_task_struct(data->task); -			data->task = NULL; -			/* lower the submap flag to show the mm is gone */ -			data->flags &= ~(PMEM_FLAGS_SUBMAP); -		} -		pmem_unlock_data_and_mm(data, mm); -		return -1; -	} -	*locked_mm = mm; -	return ret; -} - -int pmem_remap(struct pmem_region *region, struct file *file, -		      unsigned operation) -{ -	int ret; -	struct pmem_region_node *region_node; -	struct mm_struct *mm = NULL; -	struct list_head *elt, *elt2; -	int id = get_id(file); -	struct pmem_data *data = (struct pmem_data *)file->private_data; - -	/* pmem region must be aligned on a page boundry */ -	if (unlikely(!PMEM_IS_PAGE_ALIGNED(region->offset) || -		 !PMEM_IS_PAGE_ALIGNED(region->len))) { -#if PMEM_DEBUG -		printk("pmem: request for unaligned pmem suballocation " -		       "%lx %lx\n", region->offset, region->len); -#endif -		return -EINVAL; -	} - -	/* if userspace requests a region of len 0, there's nothing to do */ -	if (region->len == 0) -		return 0; - -	/* lock the mm and data */ -	ret = pmem_lock_data_and_mm(file, data, &mm); -	if (ret) -		return 0; - -	/* only the owner of the master file can remap the client fds -	 * that back in it */ -	if (!is_master_owner(file)) { -#if PMEM_DEBUG -		printk("pmem: remap requested from non-master process\n"); -#endif -		ret = -EINVAL; -		goto err; -	} - -	/* check that the requested range is within the src allocation */ -	if (unlikely((region->offset > pmem_len(id, data)) || -		     (region->len > pmem_len(id, data)) || -		     (region->offset + region->len > pmem_len(id, data)))) { -#if PMEM_DEBUG -		printk(KERN_INFO "pmem: suballoc doesn't fit in src_file!\n"); -#endif -		ret = -EINVAL; -		goto err; -	} - -	if (operation == PMEM_MAP) { -		region_node = kmalloc(sizeof(struct pmem_region_node), -			      GFP_KERNEL); -		if (!region_node) { -			ret = -ENOMEM; -#if PMEM_DEBUG -			printk(KERN_INFO "No space to allocate metadata!"); -#endif -			goto err; -		} -		region_node->region = *region; -		list_add(®ion_node->list, &data->region_list); -	} else if (operation == PMEM_UNMAP) { -		int found = 0; -		list_for_each_safe(elt, elt2, &data->region_list) { -			region_node = list_entry(elt, struct pmem_region_node, -				      list); -			if (region->len == 0 || -			    (region_node->region.offset == region->offset && -			    region_node->region.len == region->len)) { -				list_del(elt); -				kfree(region_node); -				found = 1; -			} -		} -		if (!found) { -#if PMEM_DEBUG -			printk("pmem: Unmap region does not map any mapped " -				"region!"); -#endif -			ret = -EINVAL; -			goto err; -		} -	} - -	if (data->vma && PMEM_IS_SUBMAP(data)) { -		if (operation == PMEM_MAP) -			ret = pmem_remap_pfn_range(id, data->vma, data, -						   region->offset, region->len); -		else if (operation == PMEM_UNMAP) -			ret = pmem_unmap_pfn_range(id, data->vma, data, -						   region->offset, region->len); -	} - -err: -	pmem_unlock_data_and_mm(data, mm); -	return ret; -} - -static void pmem_revoke(struct file *file, struct pmem_data *data) -{ -	struct pmem_region_node *region_node; -	struct list_head *elt, *elt2; -	struct mm_struct *mm = NULL; -	int id = get_id(file); -	int ret = 0; - -	data->master_file = NULL; -	ret = pmem_lock_data_and_mm(file, data, &mm); -	/* if lock_data_and_mm fails either the task that mapped the fd, or -	 * the vma that mapped it have already gone away, nothing more -	 * needs to be done */ -	if (ret) -		return; -	/* unmap everything */ -	/* delete the regions and region list nothing is mapped any more */ -	if (data->vma) -		list_for_each_safe(elt, elt2, &data->region_list) { -			region_node = list_entry(elt, struct pmem_region_node, -						 list); -			pmem_unmap_pfn_range(id, data->vma, data, -					     region_node->region.offset, -					     region_node->region.len); -			list_del(elt); -			kfree(region_node); -	} -	/* delete the master file */ -	pmem_unlock_data_and_mm(data, mm); -} - -static void pmem_get_size(struct pmem_region *region, struct file *file) -{ -	struct pmem_data *data = (struct pmem_data *)file->private_data; -	int id = get_id(file); - -	if (!has_allocation(file)) { -		region->offset = 0; -		region->len = 0; -		return; -	} else { -		region->offset = pmem_start_addr(id, data); -		region->len = pmem_len(id, data); -	} -	DLOG("offset %lx len %lx\n", region->offset, region->len); -} - - -static long pmem_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ -	struct pmem_data *data; -	int id = get_id(file); - -	switch (cmd) { -	case PMEM_GET_PHYS: -		{ -			struct pmem_region region; -			DLOG("get_phys\n"); -			if (!has_allocation(file)) { -				region.offset = 0; -				region.len = 0; -			} else { -				data = (struct pmem_data *)file->private_data; -				region.offset = pmem_start_addr(id, data); -				region.len = pmem_len(id, data); -			} -			printk(KERN_INFO "pmem: request for physical address of pmem region " -					"from process %d.\n", current->pid); -			if (copy_to_user((void __user *)arg, ®ion, -						sizeof(struct pmem_region))) -				return -EFAULT; -			break; -		} -	case PMEM_MAP: -		{ -			struct pmem_region region; -			if (copy_from_user(®ion, (void __user *)arg, -						sizeof(struct pmem_region))) -				return -EFAULT; -			data = (struct pmem_data *)file->private_data; -			return pmem_remap(®ion, file, PMEM_MAP); -		} -		break; -	case PMEM_UNMAP: -		{ -			struct pmem_region region; -			if (copy_from_user(®ion, (void __user *)arg, -						sizeof(struct pmem_region))) -				return -EFAULT; -			data = (struct pmem_data *)file->private_data; -			return pmem_remap(®ion, file, PMEM_UNMAP); -			break; -		} -	case PMEM_GET_SIZE: -		{ -			struct pmem_region region; -			DLOG("get_size\n"); -			pmem_get_size(®ion, file); -			if (copy_to_user((void __user *)arg, ®ion, -						sizeof(struct pmem_region))) -				return -EFAULT; -			break; -		} -	case PMEM_GET_TOTAL_SIZE: -		{ -			struct pmem_region region; -			DLOG("get total size\n"); -			region.offset = 0; -			get_id(file); -			region.len = pmem[id].size; -			if (copy_to_user((void __user *)arg, ®ion, -						sizeof(struct pmem_region))) -				return -EFAULT; -			break; -		} -	case PMEM_ALLOCATE: -		{ -			if (has_allocation(file)) -				return -EINVAL; -			data = (struct pmem_data *)file->private_data; -			data->index = pmem_allocate(id, arg); -			break; -		} -	case PMEM_CONNECT: -		DLOG("connect\n"); -		return pmem_connect(arg, file); -		break; -	case PMEM_CACHE_FLUSH: -		{ -			struct pmem_region region; -			DLOG("flush\n"); -			if (copy_from_user(®ion, (void __user *)arg, -					   sizeof(struct pmem_region))) -				return -EFAULT; -			flush_pmem_file(file, region.offset, region.len); -			break; -		} -	default: -		if (pmem[id].ioctl) -			return pmem[id].ioctl(file, cmd, arg); -		return -EINVAL; -	} -	return 0; -} - -#if PMEM_DEBUG -static ssize_t debug_open(struct inode *inode, struct file *file) -{ -	file->private_data = inode->i_private; -	return 0; -} - -static ssize_t debug_read(struct file *file, char __user *buf, size_t count, -			  loff_t *ppos) -{ -	struct list_head *elt, *elt2; -	struct pmem_data *data; -	struct pmem_region_node *region_node; -	int id = (int)file->private_data; -	const int debug_bufmax = 4096; -	static char buffer[4096]; -	int n = 0; - -	DLOG("debug open\n"); -	n = scnprintf(buffer, debug_bufmax, -		      "pid #: mapped regions (offset, len) (offset,len)...\n"); - -	mutex_lock(&pmem[id].data_list_lock); -	list_for_each(elt, &pmem[id].data_list) { -		data = list_entry(elt, struct pmem_data, list); -		down_read(&data->sem); -		n += scnprintf(buffer + n, debug_bufmax - n, "pid %u:", -				data->pid); -		list_for_each(elt2, &data->region_list) { -			region_node = list_entry(elt2, struct pmem_region_node, -				      list); -			n += scnprintf(buffer + n, debug_bufmax - n, -					"(%lx,%lx) ", -					region_node->region.offset, -					region_node->region.len); -		} -		n += scnprintf(buffer + n, debug_bufmax - n, "\n"); -		up_read(&data->sem); -	} -	mutex_unlock(&pmem[id].data_list_lock); - -	n++; -	buffer[n] = 0; -	return simple_read_from_buffer(buf, count, ppos, buffer, n); -} - -static struct file_operations debug_fops = { -	.read = debug_read, -	.open = debug_open, -}; -#endif - -#if 0 -static struct miscdevice pmem_dev = { -	.name = "pmem", -	.fops = &pmem_fops, -}; -#endif - -int pmem_setup(struct android_pmem_platform_data *pdata, -	       long (*ioctl)(struct file *, unsigned int, unsigned long), -	       int (*release)(struct inode *, struct file *)) -{ -	int err = 0; -	int i, index = 0; -	int id = id_count; -	id_count++; - -	pmem[id].no_allocator = pdata->no_allocator; -	pmem[id].cached = pdata->cached; -	pmem[id].buffered = pdata->buffered; -	pmem[id].base = pdata->start; -	pmem[id].size = pdata->size; -	pmem[id].ioctl = ioctl; -	pmem[id].release = release; -	init_rwsem(&pmem[id].bitmap_sem); -	mutex_init(&pmem[id].data_list_lock); -	INIT_LIST_HEAD(&pmem[id].data_list); -	pmem[id].dev.name = pdata->name; -	pmem[id].dev.minor = id; -	pmem[id].dev.fops = &pmem_fops; -	printk(KERN_INFO "%s: %d init\n", pdata->name, pdata->cached); - -	err = misc_register(&pmem[id].dev); -	if (err) { -		printk(KERN_ALERT "Unable to register pmem driver!\n"); -		goto err_cant_register_device; -	} -	pmem[id].num_entries = pmem[id].size / PMEM_MIN_ALLOC; - -	pmem[id].bitmap = kmalloc(pmem[id].num_entries * -				  sizeof(struct pmem_bits), GFP_KERNEL); -	if (!pmem[id].bitmap) -		goto err_no_mem_for_metadata; - -	memset(pmem[id].bitmap, 0, sizeof(struct pmem_bits) * -					  pmem[id].num_entries); - -	for (i = sizeof(pmem[id].num_entries) * 8 - 1; i >= 0; i--) { -		if ((pmem[id].num_entries) &  1<<i) { -			PMEM_ORDER(id, index) = i; -			index = PMEM_NEXT_INDEX(id, index); -		} -	} - -	if (pmem[id].cached) -		pmem[id].vbase = ioremap_cached(pmem[id].base, -						pmem[id].size); -#ifdef ioremap_ext_buffered -	else if (pmem[id].buffered) -		pmem[id].vbase = ioremap_ext_buffered(pmem[id].base, -						      pmem[id].size); -#endif -	else -		pmem[id].vbase = ioremap(pmem[id].base, pmem[id].size); - -	if (pmem[id].vbase == 0) -		goto error_cant_remap; - -	pmem[id].garbage_pfn = page_to_pfn(alloc_page(GFP_KERNEL)); -	if (pmem[id].no_allocator) -		pmem[id].allocated = 0; - -#if PMEM_DEBUG -	debugfs_create_file(pdata->name, S_IFREG | S_IRUGO, NULL, (void *)id, -			    &debug_fops); -#endif -	return 0; -error_cant_remap: -	kfree(pmem[id].bitmap); -err_no_mem_for_metadata: -	misc_deregister(&pmem[id].dev); -err_cant_register_device: -	return -1; -} - -static int pmem_probe(struct platform_device *pdev) -{ -	struct android_pmem_platform_data *pdata; - -	if (!pdev || !pdev->dev.platform_data) { -		printk(KERN_ALERT "Unable to probe pmem!\n"); -		return -1; -	} -	pdata = pdev->dev.platform_data; -	return pmem_setup(pdata, NULL, NULL); -} - - -static int pmem_remove(struct platform_device *pdev) -{ -	int id = pdev->id; -	__free_page(pfn_to_page(pmem[id].garbage_pfn)); -	misc_deregister(&pmem[id].dev); -	return 0; -} - -static struct platform_driver pmem_driver = { -	.probe = pmem_probe, -	.remove = pmem_remove, -	.driver = { .name = "android_pmem" } -}; - - -static int __init pmem_init(void) -{ -	return platform_driver_register(&pmem_driver); -} - -static void __exit pmem_exit(void) -{ -	platform_driver_unregister(&pmem_driver); -} - -module_init(pmem_init); -module_exit(pmem_exit); - diff --git a/drivers/staging/asus_oled/asus_oled.c b/drivers/staging/asus_oled/asus_oled.c index e77e4e0396c..1df9586f273 100644 --- a/drivers/staging/asus_oled/asus_oled.c +++ b/drivers/staging/asus_oled/asus_oled.c @@ -355,7 +355,14 @@ static void send_data(struct asus_oled_dev *odev)  static int append_values(struct asus_oled_dev *odev, uint8_t val, size_t count)  { -	while (count-- > 0 && val) { +	odev->last_val = val; + +	if (val == 0) { +		odev->buf_offs += count; +		return 0; +	} + +	while (count-- > 0) {  		size_t x = odev->buf_offs % odev->width;  		size_t y = odev->buf_offs / odev->width;  		size_t i; @@ -406,7 +413,6 @@ static int append_values(struct asus_oled_dev *odev, uint8_t val, size_t count)  			;  		} -		odev->last_val = val;  		odev->buf_offs++;  	} @@ -805,10 +811,9 @@ error:  static void __exit asus_oled_exit(void)  { +	usb_deregister(&oled_driver);  	class_remove_file(oled_class, &class_attr_version.attr);  	class_destroy(oled_class); - -	usb_deregister(&oled_driver);  }  module_init(asus_oled_init); diff --git a/drivers/staging/gma500/Kconfig b/drivers/staging/gma500/Kconfig deleted file mode 100644 index c7a2b3bc0a1..00000000000 --- a/drivers/staging/gma500/Kconfig +++ /dev/null @@ -1,33 +0,0 @@ -config DRM_PSB -	tristate "Intel GMA5/600 KMS Framebuffer" -	depends on DRM && PCI && X86 && BROKEN -	select FB_CFB_COPYAREA -        select FB_CFB_FILLRECT -        select FB_CFB_IMAGEBLIT -        select DRM_KMS_HELPER -        select DRM_TTM -	help -	  Say yes for an experimental 2D KMS framebuffer driver for the -	  Intel GMA500 ('Poulsbo') and other Intel IMG based graphics -	  devices. - -config DRM_PSB_MRST -	bool "Intel GMA600 support (Experimental)" -	depends on DRM_PSB -	help -	  Say yes to include support for GMA600 (Intel Moorestown/Oaktrail) -	  platforms with LVDS ports. HDMI and MIPI are not currently -	  supported. - -config DRM_PSB_MFLD -	bool "Intel Medfield support (Experimental)" -	depends on DRM_PSB -	help -	  Say yes to include support for Intel Medfield platforms with MIPI -	  interfaces. -	 -config DRM_PSB_CDV -	bool "Intel Cedarview support (Experimental)" -	depends on DRM_PSB -	help -	  Say yes to include support for Intel Cedarview platforms diff --git a/drivers/staging/gma500/Makefile b/drivers/staging/gma500/Makefile deleted file mode 100644 index c729868b1b1..00000000000 --- a/drivers/staging/gma500/Makefile +++ /dev/null @@ -1,52 +0,0 @@ -# -#	KMS driver for the GMA500 -# -ccflags-y += -Iinclude/drm - -psb_gfx-y += gem_glue.o \ -	  accel_2d.o \ -	  backlight.o \ -	  framebuffer.o \ -	  gem.o \ -	  gtt.o \ -	  intel_bios.o \ -	  intel_i2c.o \ -	  intel_opregion.o \ -	  mmu.o \ -	  power.o \ -	  psb_drv.o \ -	  psb_intel_display.o \ -	  psb_intel_lvds.o \ -	  psb_intel_modes.o \ -	  psb_intel_sdvo.o \ -	  psb_lid.o \ -	  psb_irq.o \ -	  psb_device.o \ -	  mid_bios.o - -psb_gfx-$(CONFIG_DRM_PSB_CDV) +=  cdv_device.o \ -	  cdv_intel_crt.o \ -	  cdv_intel_display.o \ -	  cdv_intel_hdmi.o \ -	  cdv_intel_lvds.o - -psb_gfx-$(CONFIG_DRM_PSB_MRST) += mrst_device.o \ -	  mrst_crtc.o \ -	  mrst_lvds.o \ -	  mrst_hdmi.o \ -	  mrst_hdmi_i2c.o - -psb_gfx-$(CONFIG_DRM_PSB_MFLD) += mdfld_device.o \ -	  mdfld_output.o \ -	  mdfld_pyr_cmd.o \ -	  mdfld_tmd_vid.o \ -	  mdfld_tpo_cmd.o \ -	  mdfld_tpo_vid.o \ -	  mdfld_dsi_pkg_sender.o \ -	  mdfld_dsi_dpi.o \ -	  mdfld_dsi_output.o \ -	  mdfld_dsi_dbi.o \ -	  mdfld_dsi_dbi_dpu.o \ -	  mdfld_intel_display.o - -obj-$(CONFIG_DRM_PSB) += psb_gfx.o diff --git a/drivers/staging/gma500/TODO b/drivers/staging/gma500/TODO deleted file mode 100644 index fc836158e74..00000000000 --- a/drivers/staging/gma500/TODO +++ /dev/null @@ -1,15 +0,0 @@ --	Sort out the power management side. Not important for Poulsbo but -	matters for Moorestown/Medfield --	Debug Oaktrail/Moorestown support (single pipe, no BIOS on mrst, -					some other differences) --	Add 2D acceleration via console and DRM --	Add scrolling acceleration using the GTT to do remapping on the main -	framebuffer. --	HDMI testing --	Oaktrail HDMI and other features --	Oaktrail MIPI --	Medfield needs a lot of further love - -As per kernel policy and the in the interest of the safety of various -kittens there is no support or plans to add hooks for the closed user space -stuff. diff --git a/drivers/staging/gma500/accel_2d.c b/drivers/staging/gma500/accel_2d.c deleted file mode 100644 index b8f78ebbb14..00000000000 --- a/drivers/staging/gma500/accel_2d.c +++ /dev/null @@ -1,414 +0,0 @@ -/************************************************************************** - * Copyright (c) 2007-2011, Intel Corporation. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - * Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to - * develop this driver. - * - **************************************************************************/ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/string.h> -#include <linux/mm.h> -#include <linux/tty.h> -#include <linux/slab.h> -#include <linux/delay.h> -#include <linux/fb.h> -#include <linux/init.h> -#include <linux/console.h> - -#include <drm/drmP.h> -#include <drm/drm.h> -#include <drm/drm_crtc.h> - -#include "psb_drv.h" -#include "psb_reg.h" -#include "framebuffer.h" - -/** - *	psb_spank		-	reset the 2D engine - *	@dev_priv: our PSB DRM device - * - *	Soft reset the graphics engine and then reload the necessary registers. - *	We use this at initialisation time but it will become relevant for - *	accelerated X later - */ -void psb_spank(struct drm_psb_private *dev_priv) -{ -	PSB_WSGX32(_PSB_CS_RESET_BIF_RESET | _PSB_CS_RESET_DPM_RESET | -		_PSB_CS_RESET_TA_RESET | _PSB_CS_RESET_USE_RESET | -		_PSB_CS_RESET_ISP_RESET | _PSB_CS_RESET_TSP_RESET | -		_PSB_CS_RESET_TWOD_RESET, PSB_CR_SOFT_RESET); -	PSB_RSGX32(PSB_CR_SOFT_RESET); - -	msleep(1); - -	PSB_WSGX32(0, PSB_CR_SOFT_RESET); -	wmb(); -	PSB_WSGX32(PSB_RSGX32(PSB_CR_BIF_CTRL) | _PSB_CB_CTRL_CLEAR_FAULT, -		   PSB_CR_BIF_CTRL); -	wmb(); -	(void) PSB_RSGX32(PSB_CR_BIF_CTRL); - -	msleep(1); -	PSB_WSGX32(PSB_RSGX32(PSB_CR_BIF_CTRL) & ~_PSB_CB_CTRL_CLEAR_FAULT, -		   PSB_CR_BIF_CTRL); -	(void) PSB_RSGX32(PSB_CR_BIF_CTRL); -	PSB_WSGX32(dev_priv->gtt.gatt_start, PSB_CR_BIF_TWOD_REQ_BASE); -} - -/** - *	psb2_2d_wait_available	-	wait for FIFO room - *	@dev_priv: our DRM device - *	@size: size (in dwords) of the command we want to issue - * - *	Wait until there is room to load the FIFO with our data. If the - *	device is not responding then reset it - */ -static int psb_2d_wait_available(struct drm_psb_private *dev_priv, -			  unsigned size) -{ -	uint32_t avail = PSB_RSGX32(PSB_CR_2D_SOCIF); -	unsigned long t = jiffies + HZ; - -	while (avail < size) { -		avail = PSB_RSGX32(PSB_CR_2D_SOCIF); -		if (time_after(jiffies, t)) { -			psb_spank(dev_priv); -			return -EIO; -		} -	} -	return 0; -} - -/** - *	psb_2d_submit		-	submit a 2D command - *	@dev_priv: our DRM device - *	@cmdbuf: command to issue - *	@size: length (in dwords) - * - *	Issue one or more 2D commands to the accelerator. This needs to be - *	serialized later when we add the GEM interfaces for acceleration - */ -static int psbfb_2d_submit(struct drm_psb_private *dev_priv, uint32_t *cmdbuf, -								unsigned size) -{ -	int ret = 0; -	int i; -	unsigned submit_size; -	unsigned long flags; - -	spin_lock_irqsave(&dev_priv->lock_2d, flags); -	while (size > 0) { -		submit_size = (size < 0x60) ? size : 0x60; -		size -= submit_size; -		ret = psb_2d_wait_available(dev_priv, submit_size); -		if (ret) -			break; - -		submit_size <<= 2; - -		for (i = 0; i < submit_size; i += 4) -			PSB_WSGX32(*cmdbuf++, PSB_SGX_2D_SLAVE_PORT + i); - -		(void)PSB_RSGX32(PSB_SGX_2D_SLAVE_PORT + i - 4); -	} -	spin_unlock_irqrestore(&dev_priv->lock_2d, flags); -	return ret; -} - - -/** - *	psb_accel_2d_copy_direction	-	compute blit order - *	@xdir: X direction of move - *	@ydir: Y direction of move - * - *	Compute the correct order setings to ensure that an overlapping blit - *	correctly copies all the pixels. - */ -static u32 psb_accel_2d_copy_direction(int xdir, int ydir) -{ -	if (xdir < 0) -		return (ydir < 0) ? PSB_2D_COPYORDER_BR2TL : -						PSB_2D_COPYORDER_TR2BL; -	else -		return (ydir < 0) ? PSB_2D_COPYORDER_BL2TR : -						PSB_2D_COPYORDER_TL2BR; -} - -/** - *	psb_accel_2d_copy		-	accelerated 2D copy - *	@dev_priv: our DRM device - *	@src_offset in bytes - *	@src_stride in bytes - *	@src_format psb 2D format defines - *	@dst_offset in bytes - *	@dst_stride in bytes - *	@dst_format psb 2D format defines - *	@src_x offset in pixels - *	@src_y offset in pixels - *	@dst_x offset in pixels - *	@dst_y offset in pixels - *	@size_x of the copied area - *	@size_y of the copied area - * - *	Format and issue a 2D accelerated copy command. - */ -static int psb_accel_2d_copy(struct drm_psb_private *dev_priv, -			     uint32_t src_offset, uint32_t src_stride, -			     uint32_t src_format, uint32_t dst_offset, -			     uint32_t dst_stride, uint32_t dst_format, -			     uint16_t src_x, uint16_t src_y, -			     uint16_t dst_x, uint16_t dst_y, -			     uint16_t size_x, uint16_t size_y) -{ -	uint32_t blit_cmd; -	uint32_t buffer[10]; -	uint32_t *buf; -	uint32_t direction; - -	buf = buffer; - -	direction = -	    psb_accel_2d_copy_direction(src_x - dst_x, src_y - dst_y); - -	if (direction == PSB_2D_COPYORDER_BR2TL || -	    direction == PSB_2D_COPYORDER_TR2BL) { -		src_x += size_x - 1; -		dst_x += size_x - 1; -	} -	if (direction == PSB_2D_COPYORDER_BR2TL || -	    direction == PSB_2D_COPYORDER_BL2TR) { -		src_y += size_y - 1; -		dst_y += size_y - 1; -	} - -	blit_cmd = -	    PSB_2D_BLIT_BH | -	    PSB_2D_ROT_NONE | -	    PSB_2D_DSTCK_DISABLE | -	    PSB_2D_SRCCK_DISABLE | -	    PSB_2D_USE_PAT | PSB_2D_ROP3_SRCCOPY | direction; - -	*buf++ = PSB_2D_FENCE_BH; -	*buf++ = -	    PSB_2D_DST_SURF_BH | dst_format | (dst_stride << -					       PSB_2D_DST_STRIDE_SHIFT); -	*buf++ = dst_offset; -	*buf++ = -	    PSB_2D_SRC_SURF_BH | src_format | (src_stride << -					       PSB_2D_SRC_STRIDE_SHIFT); -	*buf++ = src_offset; -	*buf++ = -	    PSB_2D_SRC_OFF_BH | (src_x << PSB_2D_SRCOFF_XSTART_SHIFT) | -	    (src_y << PSB_2D_SRCOFF_YSTART_SHIFT); -	*buf++ = blit_cmd; -	*buf++ = -	    (dst_x << PSB_2D_DST_XSTART_SHIFT) | (dst_y << -						  PSB_2D_DST_YSTART_SHIFT); -	*buf++ = -	    (size_x << PSB_2D_DST_XSIZE_SHIFT) | (size_y << -						  PSB_2D_DST_YSIZE_SHIFT); -	*buf++ = PSB_2D_FLUSH_BH; - -	return psbfb_2d_submit(dev_priv, buffer, buf - buffer); -} - -/** - *	psbfb_copyarea_accel	-	copyarea acceleration for /dev/fb - *	@info: our framebuffer - *	@a: copyarea parameters from the framebuffer core - * - *	Perform a 2D copy via the accelerator - */ -static void psbfb_copyarea_accel(struct fb_info *info, -				 const struct fb_copyarea *a) -{ -	struct psb_fbdev *fbdev = info->par; -	struct psb_framebuffer *psbfb = &fbdev->pfb; -	struct drm_device *dev = psbfb->base.dev; -	struct drm_framebuffer *fb = fbdev->psb_fb_helper.fb; -	struct drm_psb_private *dev_priv = dev->dev_private; -	uint32_t offset; -	uint32_t stride; -	uint32_t src_format; -	uint32_t dst_format; - -	if (!fb) -		return; - -	offset = psbfb->gtt->offset; -	stride = fb->pitches[0]; - -	switch (fb->depth) { -	case 8: -		src_format = PSB_2D_SRC_332RGB; -		dst_format = PSB_2D_DST_332RGB; -		break; -	case 15: -		src_format = PSB_2D_SRC_555RGB; -		dst_format = PSB_2D_DST_555RGB; -		break; -	case 16: -		src_format = PSB_2D_SRC_565RGB; -		dst_format = PSB_2D_DST_565RGB; -		break; -	case 24: -	case 32: -		/* this is wrong but since we don't do blending its okay */ -		src_format = PSB_2D_SRC_8888ARGB; -		dst_format = PSB_2D_DST_8888ARGB; -		break; -	default: -		/* software fallback */ -		cfb_copyarea(info, a); -		return; -	} - -	if (!gma_power_begin(dev, false)) { -		cfb_copyarea(info, a); -		return; -	} -	psb_accel_2d_copy(dev_priv, -			  offset, stride, src_format, -			  offset, stride, dst_format, -			  a->sx, a->sy, a->dx, a->dy, a->width, a->height); -	gma_power_end(dev); -} - -/** - *	psbfb_copyarea	-	2D copy interface - *	@info: our framebuffer - *	@region: region to copy - * - *	Copy an area of the framebuffer console either by the accelerator - *	or directly using the cfb helpers according to the request - */ -void psbfb_copyarea(struct fb_info *info, -			   const struct fb_copyarea *region) -{ -	if (unlikely(info->state != FBINFO_STATE_RUNNING)) -		return; - -	/* Avoid the 8 pixel erratum */ -	if (region->width == 8 || region->height == 8 || -		(info->flags & FBINFO_HWACCEL_DISABLED)) -		return cfb_copyarea(info, region); - -	psbfb_copyarea_accel(info, region); -} - -/** - *	psbfb_sync	-	synchronize 2D - *	@info: our framebuffer - * - *	Wait for the 2D engine to quiesce so that we can do CPU - *	access to the framebuffer again - */ -int psbfb_sync(struct fb_info *info) -{ -	struct psb_fbdev *fbdev = info->par; -	struct psb_framebuffer *psbfb = &fbdev->pfb; -	struct drm_device *dev = psbfb->base.dev; -	struct drm_psb_private *dev_priv = dev->dev_private; -	unsigned long _end = jiffies + DRM_HZ; -	int busy = 0; -	unsigned long flags; - -	spin_lock_irqsave(&dev_priv->lock_2d, flags); -	/* -	 * First idle the 2D engine. -	 */ - -	if ((PSB_RSGX32(PSB_CR_2D_SOCIF) == _PSB_C2_SOCIF_EMPTY) && -	    ((PSB_RSGX32(PSB_CR_2D_BLIT_STATUS) & _PSB_C2B_STATUS_BUSY) == 0)) -		goto out; - -	do { -		busy = (PSB_RSGX32(PSB_CR_2D_SOCIF) != _PSB_C2_SOCIF_EMPTY); -		cpu_relax(); -	} while (busy && !time_after_eq(jiffies, _end)); - -	if (busy) -		busy = (PSB_RSGX32(PSB_CR_2D_SOCIF) != _PSB_C2_SOCIF_EMPTY); -	if (busy) -		goto out; - -	do { -		busy = ((PSB_RSGX32(PSB_CR_2D_BLIT_STATUS) & -						_PSB_C2B_STATUS_BUSY) != 0); -		cpu_relax(); -	} while (busy && !time_after_eq(jiffies, _end)); -	if (busy) -		busy = ((PSB_RSGX32(PSB_CR_2D_BLIT_STATUS) & -					_PSB_C2B_STATUS_BUSY) != 0); - -out: -	spin_unlock_irqrestore(&dev_priv->lock_2d, flags); -	return (busy) ? -EBUSY : 0; -} - -int psb_accel_ioctl(struct drm_device *dev, void *data, struct drm_file *file) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; -	struct drm_psb_2d_op *op = data; -	u32 *op_ptr = &op->cmd[0]; -	int i; -	struct drm_gem_object *obj; -	struct gtt_range *gtt; -	int err = -EINVAL; - -	if (!dev_priv->ops->accel_2d) -		return -EOPNOTSUPP; -	if (op->size > PSB_2D_OP_BUFLEN) -		return -EINVAL; - -	/* The GEM object being used. We need to support separate src/dst/etc -	   in the end but for now keep them all the same */ -	obj = drm_gem_object_lookup(dev, file, op->src); -	if (obj == NULL) -		return -ENOENT; -	gtt = container_of(obj, struct gtt_range, gem); - -	if (psb_gtt_pin(gtt) < 0) -		goto bad_2; -	for (i = 0; i < op->size; i++, op_ptr++) { -		u32 r = *op_ptr & 0xF0000000; -		/* Fill in the GTT offsets for the command buffer */ -		if (r == PSB_2D_SRC_SURF_BH || -			r == PSB_2D_DST_SURF_BH || -			r == PSB_2D_MASK_SURF_BH || -			r == PSB_2D_PAT_SURF_BH) { -			i++; -			op_ptr++; -			if (i == op->size) -				goto bad; -			if (*op_ptr) -				goto bad; -			*op_ptr = gtt->offset; -			continue; -		} -	} -	psbfb_2d_submit(dev_priv, op->cmd, op->size); -	err = 0; -bad: -	psb_gtt_unpin(gtt); -bad_2: -	drm_gem_object_unreference(obj); -	return err; -} diff --git a/drivers/staging/gma500/backlight.c b/drivers/staging/gma500/backlight.c deleted file mode 100644 index 20793951fca..00000000000 --- a/drivers/staging/gma500/backlight.c +++ /dev/null @@ -1,49 +0,0 @@ -/* - * GMA500 Backlight Interface - * - * Copyright (c) 2009-2011, Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - * Authors: Eric Knopp - * - */ - -#include "psb_drv.h" -#include "psb_intel_reg.h" -#include "psb_intel_drv.h" -#include "intel_bios.h" -#include "power.h" - -int gma_backlight_init(struct drm_device *dev) -{ -#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE -	struct drm_psb_private *dev_priv = dev->dev_private; -	return dev_priv->ops->backlight_init(dev); -#else -	return 0; -#endif -} - -void gma_backlight_exit(struct drm_device *dev) -{ -#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE -	struct drm_psb_private *dev_priv = dev->dev_private; -	if (dev_priv->backlight_device) { -		dev_priv->backlight_device->props.brightness = 0; -		backlight_update_status(dev_priv->backlight_device); -		backlight_device_unregister(dev_priv->backlight_device); -	} -#endif -} diff --git a/drivers/staging/gma500/cdv_device.c b/drivers/staging/gma500/cdv_device.c deleted file mode 100644 index 8ec10caab13..00000000000 --- a/drivers/staging/gma500/cdv_device.c +++ /dev/null @@ -1,350 +0,0 @@ -/************************************************************************** - * Copyright (c) 2011, Intel Corporation. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - **************************************************************************/ - -#include <linux/backlight.h> -#include <drm/drmP.h> -#include <drm/drm.h> -#include "psb_drm.h" -#include "psb_drv.h" -#include "psb_reg.h" -#include "psb_intel_reg.h" -#include "intel_bios.h" -#include "cdv_device.h" - -#define VGA_SR_INDEX		0x3c4 -#define VGA_SR_DATA		0x3c5 - -static void cdv_disable_vga(struct drm_device *dev) -{ -	u8 sr1; -	u32 vga_reg; - -	vga_reg = VGACNTRL; - -	outb(1, VGA_SR_INDEX); -	sr1 = inb(VGA_SR_DATA); -	outb(sr1 | 1<<5, VGA_SR_DATA); -	udelay(300); - -	REG_WRITE(vga_reg, VGA_DISP_DISABLE); -	REG_READ(vga_reg); -} - -static int cdv_output_init(struct drm_device *dev) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; -	cdv_disable_vga(dev); - -	cdv_intel_crt_init(dev, &dev_priv->mode_dev); -	cdv_intel_lvds_init(dev, &dev_priv->mode_dev); - -	/* These bits indicate HDMI not SDVO on CDV, but we don't yet support -	   the HDMI interface */ -	if (REG_READ(SDVOB) & SDVO_DETECTED) -		cdv_hdmi_init(dev, &dev_priv->mode_dev, SDVOB); -	if (REG_READ(SDVOC) & SDVO_DETECTED) -		cdv_hdmi_init(dev, &dev_priv->mode_dev, SDVOC); -	return 0; -} - -#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE - -/* - *	Poulsbo Backlight Interfaces - */ - -#define BLC_PWM_PRECISION_FACTOR 100	/* 10000000 */ -#define BLC_PWM_FREQ_CALC_CONSTANT 32 -#define MHz 1000000 - -#define PSB_BLC_PWM_PRECISION_FACTOR    10 -#define PSB_BLC_MAX_PWM_REG_FREQ        0xFFFE -#define PSB_BLC_MIN_PWM_REG_FREQ        0x2 - -#define PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR (0xFFFE) -#define PSB_BACKLIGHT_PWM_CTL_SHIFT	(16) - -static int cdv_brightness; -static struct backlight_device *cdv_backlight_device; - -static int cdv_get_brightness(struct backlight_device *bd) -{ -	/* return locally cached var instead of HW read (due to DPST etc.) */ -	/* FIXME: ideally return actual value in case firmware fiddled with -	   it */ -	return cdv_brightness; -} - - -static int cdv_backlight_setup(struct drm_device *dev) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; -	unsigned long core_clock; -	/* u32 bl_max_freq; */ -	/* unsigned long value; */ -	u16 bl_max_freq; -	uint32_t value; -	uint32_t blc_pwm_precision_factor; - -	/* get bl_max_freq and pol from dev_priv*/ -	if (!dev_priv->lvds_bl) { -		dev_err(dev->dev, "Has no valid LVDS backlight info\n"); -		return -ENOENT; -	} -	bl_max_freq = dev_priv->lvds_bl->freq; -	blc_pwm_precision_factor = PSB_BLC_PWM_PRECISION_FACTOR; - -	core_clock = dev_priv->core_freq; - -	value = (core_clock * MHz) / BLC_PWM_FREQ_CALC_CONSTANT; -	value *= blc_pwm_precision_factor; -	value /= bl_max_freq; -	value /= blc_pwm_precision_factor; - -	if (value > (unsigned long long)PSB_BLC_MAX_PWM_REG_FREQ || -		 value < (unsigned long long)PSB_BLC_MIN_PWM_REG_FREQ) -				return -ERANGE; -	else { -		/* FIXME */ -	} -	return 0; -} - -static int cdv_set_brightness(struct backlight_device *bd) -{ -	int level = bd->props.brightness; - -	/* Percentage 1-100% being valid */ -	if (level < 1) -		level = 1; - -	/*cdv_intel_lvds_set_brightness(dev, level); FIXME */ -	cdv_brightness = level; -	return 0; -} - -static const struct backlight_ops cdv_ops = { -	.get_brightness = cdv_get_brightness, -	.update_status  = cdv_set_brightness, -}; - -static int cdv_backlight_init(struct drm_device *dev) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; -	int ret; -	struct backlight_properties props; - -	memset(&props, 0, sizeof(struct backlight_properties)); -	props.max_brightness = 100; -	props.type = BACKLIGHT_PLATFORM; - -	cdv_backlight_device = backlight_device_register("psb-bl", -					NULL, (void *)dev, &cdv_ops, &props); -	if (IS_ERR(cdv_backlight_device)) -		return PTR_ERR(cdv_backlight_device); - -	ret = cdv_backlight_setup(dev); -	if (ret < 0) { -		backlight_device_unregister(cdv_backlight_device); -		cdv_backlight_device = NULL; -		return ret; -	} -	cdv_backlight_device->props.brightness = 100; -	cdv_backlight_device->props.max_brightness = 100; -	backlight_update_status(cdv_backlight_device); -	dev_priv->backlight_device = cdv_backlight_device; -	return 0; -} - -#endif - -/* - *	Provide the Cedarview specific chip logic and low level methods - *	for power management - * - *	FIXME: we need to implement the apm/ospm base management bits - *	for this and the MID devices. - */ - -static inline u32 CDV_MSG_READ32(uint port, uint offset) -{ -	int mcr = (0x10<<24) | (port << 16) | (offset << 8); -	uint32_t ret_val = 0; -	struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0); -	pci_write_config_dword(pci_root, 0xD0, mcr); -	pci_read_config_dword(pci_root, 0xD4, &ret_val); -	pci_dev_put(pci_root); -	return ret_val; -} - -static inline void CDV_MSG_WRITE32(uint port, uint offset, u32 value) -{ -	int mcr = (0x11<<24) | (port << 16) | (offset << 8) | 0xF0; -	struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0); -	pci_write_config_dword(pci_root, 0xD4, value); -	pci_write_config_dword(pci_root, 0xD0, mcr); -	pci_dev_put(pci_root); -} - -#define PSB_APM_CMD			0x0 -#define PSB_APM_STS			0x04 -#define PSB_PM_SSC			0x20 -#define PSB_PM_SSS			0x30 -#define PSB_PWRGT_GFX_MASK		0x3 -#define CDV_PWRGT_DISPLAY_CNTR		0x000fc00c -#define CDV_PWRGT_DISPLAY_STS		0x000fc00c - -static void cdv_init_pm(struct drm_device *dev) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; -	u32 pwr_cnt; -	int i; - -	dev_priv->apm_base = CDV_MSG_READ32(PSB_PUNIT_PORT, -							PSB_APMBA) & 0xFFFF; -	dev_priv->ospm_base = CDV_MSG_READ32(PSB_PUNIT_PORT, -							PSB_OSPMBA) & 0xFFFF; - -	/* Force power on for now */ -	pwr_cnt = inl(dev_priv->apm_base + PSB_APM_CMD); -	pwr_cnt &= ~PSB_PWRGT_GFX_MASK; - -	outl(pwr_cnt, dev_priv->apm_base + PSB_APM_CMD); -	for (i = 0; i < 5; i++) { -		u32 pwr_sts = inl(dev_priv->apm_base + PSB_APM_STS); -		if ((pwr_sts & PSB_PWRGT_GFX_MASK) == 0) -			break; -		udelay(10); -	} -	pwr_cnt = inl(dev_priv->ospm_base + PSB_PM_SSC); -	pwr_cnt &= ~CDV_PWRGT_DISPLAY_CNTR; -	outl(pwr_cnt, dev_priv->ospm_base + PSB_PM_SSC); -	for (i = 0; i < 5; i++) { -		u32 pwr_sts = inl(dev_priv->ospm_base + PSB_PM_SSS); -		if ((pwr_sts & CDV_PWRGT_DISPLAY_STS) == 0) -			break; -		udelay(10); -	} -} - -/** - *	cdv_save_display_registers	-	save registers lost on suspend - *	@dev: our DRM device - * - *	Save the state we need in order to be able to restore the interface - *	upon resume from suspend - * - *	FIXME: review - */ -static int cdv_save_display_registers(struct drm_device *dev) -{ -	return 0; -} - -/** - *	cdv_restore_display_registers	-	restore lost register state - *	@dev: our DRM device - * - *	Restore register state that was lost during suspend and resume. - * - *	FIXME: review - */ -static int cdv_restore_display_registers(struct drm_device *dev) -{ -	return 0; -} - -static int cdv_power_down(struct drm_device *dev) -{ -	return 0; -} - -static int cdv_power_up(struct drm_device *dev) -{ -	return 0; -} - -/* FIXME ? - shared with Poulsbo */ -static void cdv_get_core_freq(struct drm_device *dev) -{ -	uint32_t clock; -	struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0); -	struct drm_psb_private *dev_priv = dev->dev_private; - -	pci_write_config_dword(pci_root, 0xD0, 0xD0050300); -	pci_read_config_dword(pci_root, 0xD4, &clock); -	pci_dev_put(pci_root); - -	switch (clock & 0x07) { -	case 0: -		dev_priv->core_freq = 100; -		break; -	case 1: -		dev_priv->core_freq = 133; -		break; -	case 2: -		dev_priv->core_freq = 150; -		break; -	case 3: -		dev_priv->core_freq = 178; -		break; -	case 4: -		dev_priv->core_freq = 200; -		break; -	case 5: -	case 6: -	case 7: -		dev_priv->core_freq = 266; -	default: -		dev_priv->core_freq = 0; -	} -} - -static int cdv_chip_setup(struct drm_device *dev) -{ -	cdv_get_core_freq(dev); -	gma_intel_opregion_init(dev); -	psb_intel_init_bios(dev); -	return 0; -} - -/* CDV is much like Poulsbo but has MID like SGX offsets and PM */ - -const struct psb_ops cdv_chip_ops = { -	.name = "Cedartrail", -	.accel_2d = 0, -	.pipes = 2, -	.sgx_offset = MRST_SGX_OFFSET, -	.chip_setup = cdv_chip_setup, - -	.crtc_helper = &cdv_intel_helper_funcs, -	.crtc_funcs = &cdv_intel_crtc_funcs, - -	.output_init = cdv_output_init, - -#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE -	.backlight_init = cdv_backlight_init, -#endif - -	.init_pm = cdv_init_pm, -	.save_regs = cdv_save_display_registers, -	.restore_regs = cdv_restore_display_registers, -	.power_down = cdv_power_down, -	.power_up = cdv_power_up, -}; diff --git a/drivers/staging/gma500/cdv_device.h b/drivers/staging/gma500/cdv_device.h deleted file mode 100644 index 2a88b7beb55..00000000000 --- a/drivers/staging/gma500/cdv_device.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright © 2011 Intel Corporation - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc.,  - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - */ - -extern const struct drm_crtc_helper_funcs cdv_intel_helper_funcs; -extern const struct drm_crtc_funcs cdv_intel_crtc_funcs; -extern void cdv_intel_crt_init(struct drm_device *dev, -			struct psb_intel_mode_device *mode_dev); -extern void cdv_intel_lvds_init(struct drm_device *dev, -			struct psb_intel_mode_device *mode_dev); -extern void cdv_hdmi_init(struct drm_device *dev, struct psb_intel_mode_device *mode_dev, -			int reg); -extern struct drm_display_mode *cdv_intel_crtc_mode_get(struct drm_device *dev, -					     struct drm_crtc *crtc); - -extern inline void cdv_intel_wait_for_vblank(struct drm_device *dev) -{ -	/* Wait for 20ms, i.e. one cycle at 50hz. */ -        /* FIXME: msleep ?? */ -	mdelay(20); -} - - diff --git a/drivers/staging/gma500/cdv_intel_crt.c b/drivers/staging/gma500/cdv_intel_crt.c deleted file mode 100644 index efda63b97b4..00000000000 --- a/drivers/staging/gma500/cdv_intel_crt.c +++ /dev/null @@ -1,326 +0,0 @@ -/* - * Copyright © 2006-2007 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Authors: - *	Eric Anholt <eric@anholt.net> - */ - -#include <linux/i2c.h> -#include <drm/drmP.h> - -#include "intel_bios.h" -#include "psb_drv.h" -#include "psb_intel_drv.h" -#include "psb_intel_reg.h" -#include "power.h" -#include <linux/pm_runtime.h> - - -static void cdv_intel_crt_dpms(struct drm_encoder *encoder, int mode) -{ -	struct drm_device *dev = encoder->dev; -	u32 temp, reg; -	reg = ADPA; - -	temp = REG_READ(reg); -	temp &= ~(ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE); -	temp &= ~ADPA_DAC_ENABLE; - -	switch (mode) { -	case DRM_MODE_DPMS_ON: -		temp |= ADPA_DAC_ENABLE; -		break; -	case DRM_MODE_DPMS_STANDBY: -		temp |= ADPA_DAC_ENABLE | ADPA_HSYNC_CNTL_DISABLE; -		break; -	case DRM_MODE_DPMS_SUSPEND: -		temp |= ADPA_DAC_ENABLE | ADPA_VSYNC_CNTL_DISABLE; -		break; -	case DRM_MODE_DPMS_OFF: -		temp |= ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE; -		break; -	} - -	REG_WRITE(reg, temp); -} - -static int cdv_intel_crt_mode_valid(struct drm_connector *connector, -				struct drm_display_mode *mode) -{ -	int max_clock = 0; -	if (mode->flags & DRM_MODE_FLAG_DBLSCAN) -		return MODE_NO_DBLESCAN; - -	/* The lowest clock for CDV is 20000KHz */ -	if (mode->clock < 20000) -		return MODE_CLOCK_LOW; - -	/* The max clock for CDV is 355 instead of 400 */ -	max_clock = 355000; -	if (mode->clock > max_clock) -		return MODE_CLOCK_HIGH; - -	if (mode->hdisplay > 1680 || mode->vdisplay > 1050) -		return MODE_PANEL; - -	return MODE_OK; -} - -static bool cdv_intel_crt_mode_fixup(struct drm_encoder *encoder, -				 struct drm_display_mode *mode, -				 struct drm_display_mode *adjusted_mode) -{ -	return true; -} - -static void cdv_intel_crt_mode_set(struct drm_encoder *encoder, -			       struct drm_display_mode *mode, -			       struct drm_display_mode *adjusted_mode) -{ - -	struct drm_device *dev = encoder->dev; -	struct drm_crtc *crtc = encoder->crtc; -	struct psb_intel_crtc *psb_intel_crtc = -					to_psb_intel_crtc(crtc); -	int dpll_md_reg; -	u32 adpa, dpll_md; -	u32 adpa_reg; - -	if (psb_intel_crtc->pipe == 0) -		dpll_md_reg = DPLL_A_MD; -	else -		dpll_md_reg = DPLL_B_MD; - -	adpa_reg = ADPA; - -	/* -	 * Disable separate mode multiplier used when cloning SDVO to CRT -	 * XXX this needs to be adjusted when we really are cloning -	 */ -	{ -		dpll_md = REG_READ(dpll_md_reg); -		REG_WRITE(dpll_md_reg, -			   dpll_md & ~DPLL_MD_UDI_MULTIPLIER_MASK); -	} - -	adpa = 0; -	if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) -		adpa |= ADPA_HSYNC_ACTIVE_HIGH; -	if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) -		adpa |= ADPA_VSYNC_ACTIVE_HIGH; - -	if (psb_intel_crtc->pipe == 0) -		adpa |= ADPA_PIPE_A_SELECT; -	else -		adpa |= ADPA_PIPE_B_SELECT; - -	REG_WRITE(adpa_reg, adpa); -} - - -/** - * Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect CRT presence. - * - * \return true if CRT is connected. - * \return false if CRT is disconnected. - */ -static bool cdv_intel_crt_detect_hotplug(struct drm_connector *connector, -								bool force) -{ -	struct drm_device *dev = connector->dev; -	u32 hotplug_en; -	int i, tries = 0, ret = false; -	u32 adpa_orig; - -	/* disable the DAC when doing the hotplug detection */ - -	adpa_orig = REG_READ(ADPA); - -	REG_WRITE(ADPA, adpa_orig & ~(ADPA_DAC_ENABLE)); - -	/* -	 * On a CDV thep, CRT detect sequence need to be done twice -	 * to get a reliable result. -	 */ -	tries = 2; - -	hotplug_en = REG_READ(PORT_HOTPLUG_EN); -	hotplug_en &= ~(CRT_HOTPLUG_DETECT_MASK); -	hotplug_en |= CRT_HOTPLUG_FORCE_DETECT; - -	hotplug_en |= CRT_HOTPLUG_ACTIVATION_PERIOD_64; -	hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50; - -	for (i = 0; i < tries ; i++) { -		unsigned long timeout; -		/* turn on the FORCE_DETECT */ -		REG_WRITE(PORT_HOTPLUG_EN, hotplug_en); -		timeout = jiffies + msecs_to_jiffies(1000); -		/* wait for FORCE_DETECT to go off */ -		do { -			if (!(REG_READ(PORT_HOTPLUG_EN) & -					CRT_HOTPLUG_FORCE_DETECT)) -				break; -			msleep(1); -		} while (time_after(timeout, jiffies)); -	} - -	if ((REG_READ(PORT_HOTPLUG_STAT) & CRT_HOTPLUG_MONITOR_MASK) != -	    CRT_HOTPLUG_MONITOR_NONE) -		ret = true; - -	/* Restore the saved ADPA */ -	REG_WRITE(ADPA, adpa_orig); -	return ret; -} - -static enum drm_connector_status cdv_intel_crt_detect( -				struct drm_connector *connector, bool force) -{ -	if (cdv_intel_crt_detect_hotplug(connector, force)) -		return connector_status_connected; -	else -		return connector_status_disconnected; -} - -static void cdv_intel_crt_destroy(struct drm_connector *connector) -{ -	struct psb_intel_output *intel_output = to_psb_intel_output(connector); - -	psb_intel_i2c_destroy(intel_output->ddc_bus); -	drm_sysfs_connector_remove(connector); -	drm_connector_cleanup(connector); -	kfree(connector); -} - -static int cdv_intel_crt_get_modes(struct drm_connector *connector) -{ -	struct psb_intel_output *intel_output = -				to_psb_intel_output(connector); -	return psb_intel_ddc_get_modes(intel_output); -} - -static int cdv_intel_crt_set_property(struct drm_connector *connector, -				  struct drm_property *property, -				  uint64_t value) -{ -	return 0; -} - -/* - * Routines for controlling stuff on the analog port - */ - -static const struct drm_encoder_helper_funcs cdv_intel_crt_helper_funcs = { -	.dpms = cdv_intel_crt_dpms, -	.mode_fixup = cdv_intel_crt_mode_fixup, -	.prepare = psb_intel_encoder_prepare, -	.commit = psb_intel_encoder_commit, -	.mode_set = cdv_intel_crt_mode_set, -}; - -static const struct drm_connector_funcs cdv_intel_crt_connector_funcs = { -	.dpms = drm_helper_connector_dpms, -	.detect = cdv_intel_crt_detect, -	.fill_modes = drm_helper_probe_single_connector_modes, -	.destroy = cdv_intel_crt_destroy, -	.set_property = cdv_intel_crt_set_property, -}; - -static const struct drm_connector_helper_funcs -				cdv_intel_crt_connector_helper_funcs = { -	.mode_valid = cdv_intel_crt_mode_valid, -	.get_modes = cdv_intel_crt_get_modes, -	.best_encoder = psb_intel_best_encoder, -}; - -static void cdv_intel_crt_enc_destroy(struct drm_encoder *encoder) -{ -	drm_encoder_cleanup(encoder); -} - -static const struct drm_encoder_funcs cdv_intel_crt_enc_funcs = { -	.destroy = cdv_intel_crt_enc_destroy, -}; - -void cdv_intel_crt_init(struct drm_device *dev, -			struct psb_intel_mode_device *mode_dev) -{ - -	struct psb_intel_output *psb_intel_output; -	struct drm_connector *connector; -	struct drm_encoder *encoder; - -	u32 i2c_reg; - -	psb_intel_output = kzalloc(sizeof(struct psb_intel_output), GFP_KERNEL); -	if (!psb_intel_output) -		return; - -	psb_intel_output->mode_dev = mode_dev; -	connector = &psb_intel_output->base; -	drm_connector_init(dev, connector, -		&cdv_intel_crt_connector_funcs, DRM_MODE_CONNECTOR_VGA); - -	encoder = &psb_intel_output->enc; -	drm_encoder_init(dev, encoder, -		&cdv_intel_crt_enc_funcs, DRM_MODE_ENCODER_DAC); - -	drm_mode_connector_attach_encoder(&psb_intel_output->base, -					  &psb_intel_output->enc); - -	/* Set up the DDC bus. */ -	i2c_reg = GPIOA; -	/* Remove the following code for CDV */ -	/* -	if (dev_priv->crt_ddc_bus != 0) -		i2c_reg = dev_priv->crt_ddc_bus; -	}*/ -	psb_intel_output->ddc_bus = psb_intel_i2c_create(dev, -						i2c_reg, "CRTDDC_A"); -	if (!psb_intel_output->ddc_bus) { -		dev_printk(KERN_ERR, &dev->pdev->dev, "DDC bus registration " -			   "failed.\n"); -		goto failed_ddc; -	} - -	psb_intel_output->type = INTEL_OUTPUT_ANALOG; -	/* -	psb_intel_output->clone_mask = (1 << INTEL_ANALOG_CLONE_BIT); -	psb_intel_output->crtc_mask = (1 << 0) | (1 << 1); -	*/ -	connector->interlace_allowed = 0; -	connector->doublescan_allowed = 0; - -	drm_encoder_helper_add(encoder, &cdv_intel_crt_helper_funcs); -	drm_connector_helper_add(connector, -					&cdv_intel_crt_connector_helper_funcs); - -	drm_sysfs_connector_add(connector); - -	return; -failed_ddc: -	drm_encoder_cleanup(&psb_intel_output->enc); -	drm_connector_cleanup(&psb_intel_output->base); -	kfree(psb_intel_output); -	return; -} diff --git a/drivers/staging/gma500/cdv_intel_display.c b/drivers/staging/gma500/cdv_intel_display.c deleted file mode 100644 index c63a32776a9..00000000000 --- a/drivers/staging/gma500/cdv_intel_display.c +++ /dev/null @@ -1,1508 +0,0 @@ -/* - * Copyright © 2006-2011 Intel Corporation - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - * Authors: - *	Eric Anholt <eric@anholt.net> - */ - -#include <linux/i2c.h> -#include <linux/pm_runtime.h> - -#include <drm/drmP.h> -#include "framebuffer.h" -#include "psb_drv.h" -#include "psb_intel_drv.h" -#include "psb_intel_reg.h" -#include "psb_intel_display.h" -#include "power.h" -#include "cdv_device.h" - - -struct cdv_intel_range_t { -	int min, max; -}; - -struct cdv_intel_p2_t { -	int dot_limit; -	int p2_slow, p2_fast; -}; - -struct cdv_intel_clock_t { -	/* given values */ -	int n; -	int m1, m2; -	int p1, p2; -	/* derived values */ -	int dot; -	int vco; -	int m; -	int p; -}; - -#define INTEL_P2_NUM		      2 - -struct cdv_intel_limit_t { -	struct cdv_intel_range_t dot, vco, n, m, m1, m2, p, p1; -	struct cdv_intel_p2_t p2; -}; - -#define CDV_LIMIT_SINGLE_LVDS_96	0 -#define CDV_LIMIT_SINGLE_LVDS_100	1 -#define CDV_LIMIT_DAC_HDMI_27		2 -#define CDV_LIMIT_DAC_HDMI_96		3 - -static const struct cdv_intel_limit_t cdv_intel_limits[] = { -	{			/* CDV_SIGNLE_LVDS_96MHz */ -	 .dot = {.min = 20000, .max = 115500}, -	 .vco = {.min = 1800000, .max = 3600000}, -	 .n = {.min = 2, .max = 6}, -	 .m = {.min = 60, .max = 160}, -	 .m1 = {.min = 0, .max = 0}, -	 .m2 = {.min = 58, .max = 158}, -	 .p = {.min = 28, .max = 140}, -	 .p1 = {.min = 2, .max = 10}, -	 .p2 = {.dot_limit = 200000, -		.p2_slow = 14, .p2_fast = 14}, -	 }, -	{			/* CDV_SINGLE_LVDS_100MHz */ -	 .dot = {.min = 20000, .max = 115500}, -	 .vco = {.min = 1800000, .max = 3600000}, -	 .n = {.min = 2, .max = 6}, -	 .m = {.min = 60, .max = 160}, -	 .m1 = {.min = 0, .max = 0}, -	 .m2 = {.min = 58, .max = 158}, -	 .p = {.min = 28, .max = 140}, -	 .p1 = {.min = 2, .max = 10}, -	 /* The single-channel range is 25-112Mhz, and dual-channel -	  * is 80-224Mhz.  Prefer single channel as much as possible. -	  */ -	 .p2 = {.dot_limit = 200000, .p2_slow = 14, .p2_fast = 14}, -	 }, -	{			/* CDV_DAC_HDMI_27MHz */ -	 .dot = {.min = 20000, .max = 400000}, -	 .vco = {.min = 1809000, .max = 3564000}, -	 .n = {.min = 1, .max = 1}, -	 .m = {.min = 67, .max = 132}, -	 .m1 = {.min = 0, .max = 0}, -	 .m2 = {.min = 65, .max = 130}, -	 .p = {.min = 5, .max = 90}, -	 .p1 = {.min = 1, .max = 9}, -	 .p2 = {.dot_limit = 225000, .p2_slow = 10, .p2_fast = 5}, -	 }, -	{			/* CDV_DAC_HDMI_96MHz */ -	 .dot = {.min = 20000, .max = 400000}, -	 .vco = {.min = 1800000, .max = 3600000}, -	 .n = {.min = 2, .max = 6}, -	 .m = {.min = 60, .max = 160}, -	 .m1 = {.min = 0, .max = 0}, -	 .m2 = {.min = 58, .max = 158}, -	 .p = {.min = 5, .max = 100}, -	 .p1 = {.min = 1, .max = 10}, -	 .p2 = {.dot_limit = 225000, .p2_slow = 10, .p2_fast = 5}, -	 }, -}; - -#define _wait_for(COND, MS, W) ({ \ -	unsigned long timeout__ = jiffies + msecs_to_jiffies(MS);	\ -	int ret__ = 0;							\ -	while (!(COND)) {						\ -		if (time_after(jiffies, timeout__)) {			\ -			ret__ = -ETIMEDOUT;				\ -			break;						\ -		}							\ -		if (W && !in_dbg_master())				\ -			msleep(W);					\ -	}								\ -	ret__;								\ -}) - -#define wait_for(COND, MS) _wait_for(COND, MS, 1) - - -static int cdv_sb_read(struct drm_device *dev, u32 reg, u32 *val) -{ -	int ret; - -	ret = wait_for((REG_READ(SB_PCKT) & SB_BUSY) == 0, 1000); -	if (ret) { -		DRM_ERROR("timeout waiting for SB to idle before read\n"); -		return ret; -	} - -	REG_WRITE(SB_ADDR, reg); -	REG_WRITE(SB_PCKT, -		   SET_FIELD(SB_OPCODE_READ, SB_OPCODE) | -		   SET_FIELD(SB_DEST_DPLL, SB_DEST) | -		   SET_FIELD(0xf, SB_BYTE_ENABLE)); - -	ret = wait_for((REG_READ(SB_PCKT) & SB_BUSY) == 0, 1000); -	if (ret) { -		DRM_ERROR("timeout waiting for SB to idle after read\n"); -		return ret; -	} - -	*val = REG_READ(SB_DATA); - -	return 0; -} - -static int cdv_sb_write(struct drm_device *dev, u32 reg, u32 val) -{ -	int ret; -	static bool dpio_debug = true; -	u32 temp; - -	if (dpio_debug) { -		if (cdv_sb_read(dev, reg, &temp) == 0) -			DRM_DEBUG_KMS("0x%08x: 0x%08x (before)\n", reg, temp); -		DRM_DEBUG_KMS("0x%08x: 0x%08x\n", reg, val); -	} - -	ret = wait_for((REG_READ(SB_PCKT) & SB_BUSY) == 0, 1000); -	if (ret) { -		DRM_ERROR("timeout waiting for SB to idle before write\n"); -		return ret; -	} - -	REG_WRITE(SB_ADDR, reg); -	REG_WRITE(SB_DATA, val); -	REG_WRITE(SB_PCKT, -		   SET_FIELD(SB_OPCODE_WRITE, SB_OPCODE) | -		   SET_FIELD(SB_DEST_DPLL, SB_DEST) | -		   SET_FIELD(0xf, SB_BYTE_ENABLE)); - -	ret = wait_for((REG_READ(SB_PCKT) & SB_BUSY) == 0, 1000); -	if (ret) { -		DRM_ERROR("timeout waiting for SB to idle after write\n"); -		return ret; -	} - -	if (dpio_debug) { -		if (cdv_sb_read(dev, reg, &temp) == 0) -			DRM_DEBUG_KMS("0x%08x: 0x%08x (after)\n", reg, temp); -	} - -	return 0; -} - -/* Reset the DPIO configuration register.  The BIOS does this at every - * mode set. - */ -static void cdv_sb_reset(struct drm_device *dev) -{ - -	REG_WRITE(DPIO_CFG, 0); -	REG_READ(DPIO_CFG); -	REG_WRITE(DPIO_CFG, DPIO_MODE_SELECT_0 | DPIO_CMN_RESET_N); -} - -/* Unlike most Intel display engines, on Cedarview the DPLL registers - * are behind this sideband bus.  They must be programmed while the - * DPLL reference clock is on in the DPLL control register, but before - * the DPLL is enabled in the DPLL control register. - */ -static int -cdv_dpll_set_clock_cdv(struct drm_device *dev, struct drm_crtc *crtc, -			       struct cdv_intel_clock_t *clock) -{ -	struct psb_intel_crtc *psb_crtc = -				to_psb_intel_crtc(crtc); -	int pipe = psb_crtc->pipe; -	u32 m, n_vco, p; -	int ret = 0; -	int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B; -	u32 ref_value; - -	cdv_sb_reset(dev); - -	if ((REG_READ(dpll_reg) & DPLL_SYNCLOCK_ENABLE) == 0) { -		DRM_ERROR("Attempting to set DPLL with refclk disabled\n"); -		return -EBUSY; -	} - -	/* Follow the BIOS and write the REF/SFR Register. Hardcoded value */ -	ref_value = 0x68A701; - -	cdv_sb_write(dev, SB_REF_SFR(pipe), ref_value); - -	/* We don't know what the other fields of these regs are, so -	 * leave them in place. -	 */ -	ret = cdv_sb_read(dev, SB_M(pipe), &m); -	if (ret) -		return ret; -	m &= ~SB_M_DIVIDER_MASK; -	m |= ((clock->m2) << SB_M_DIVIDER_SHIFT); -	ret = cdv_sb_write(dev, SB_M(pipe), m); -	if (ret) -		return ret; - -	ret = cdv_sb_read(dev, SB_N_VCO(pipe), &n_vco); -	if (ret) -		return ret; - -	/* Follow the BIOS to program the N_DIVIDER REG */ -	n_vco &= 0xFFFF; -	n_vco |= 0x107; -	n_vco &= ~(SB_N_VCO_SEL_MASK | -		   SB_N_DIVIDER_MASK | -		   SB_N_CB_TUNE_MASK); - -	n_vco |= ((clock->n) << SB_N_DIVIDER_SHIFT); - -	if (clock->vco < 2250000) { -		n_vco |= (2 << SB_N_CB_TUNE_SHIFT); -		n_vco |= (0 << SB_N_VCO_SEL_SHIFT); -	} else if (clock->vco < 2750000) { -		n_vco |= (1 << SB_N_CB_TUNE_SHIFT); -		n_vco |= (1 << SB_N_VCO_SEL_SHIFT); -	} else if (clock->vco < 3300000) { -		n_vco |= (0 << SB_N_CB_TUNE_SHIFT); -		n_vco |= (2 << SB_N_VCO_SEL_SHIFT); -	} else { -		n_vco |= (0 << SB_N_CB_TUNE_SHIFT); -		n_vco |= (3 << SB_N_VCO_SEL_SHIFT); -	} - -	ret = cdv_sb_write(dev, SB_N_VCO(pipe), n_vco); -	if (ret) -		return ret; - -	ret = cdv_sb_read(dev, SB_P(pipe), &p); -	if (ret) -		return ret; -	p &= ~(SB_P2_DIVIDER_MASK | SB_P1_DIVIDER_MASK); -	p |= SET_FIELD(clock->p1, SB_P1_DIVIDER); -	switch (clock->p2) { -	case 5: -		p |= SET_FIELD(SB_P2_5, SB_P2_DIVIDER); -		break; -	case 10: -		p |= SET_FIELD(SB_P2_10, SB_P2_DIVIDER); -		break; -	case 14: -		p |= SET_FIELD(SB_P2_14, SB_P2_DIVIDER); -		break; -	case 7: -		p |= SET_FIELD(SB_P2_7, SB_P2_DIVIDER); -		break; -	default: -		DRM_ERROR("Bad P2 clock: %d\n", clock->p2); -		return -EINVAL; -	} -	ret = cdv_sb_write(dev, SB_P(pipe), p); -	if (ret) -		return ret; - -	/* always Program the Lane Register for the Pipe A*/ -	if (pipe == 0) { -		/* Program the Lane0/1 for HDMI B */ -		u32 lane_reg, lane_value; - -		lane_reg = PSB_LANE0; -		cdv_sb_read(dev, lane_reg, &lane_value); -		lane_value &= ~(LANE_PLL_MASK); -		lane_value |= LANE_PLL_ENABLE; -		cdv_sb_write(dev, lane_reg, lane_value); - -		lane_reg = PSB_LANE1; -		cdv_sb_read(dev, lane_reg, &lane_value); -		lane_value &= ~(LANE_PLL_MASK); -		lane_value |= LANE_PLL_ENABLE; -		cdv_sb_write(dev, lane_reg, lane_value); - -		/* Program the Lane2/3 for HDMI C */ -		lane_reg = PSB_LANE2; -		cdv_sb_read(dev, lane_reg, &lane_value); -		lane_value &= ~(LANE_PLL_MASK); -		lane_value |= LANE_PLL_ENABLE; -		cdv_sb_write(dev, lane_reg, lane_value); - -		lane_reg = PSB_LANE3; -		cdv_sb_read(dev, lane_reg, &lane_value); -		lane_value &= ~(LANE_PLL_MASK); -		lane_value |= LANE_PLL_ENABLE; -		cdv_sb_write(dev, lane_reg, lane_value); -	} - -	return 0; -} - -/* - * Returns whether any output on the specified pipe is of the specified type - */ -bool cdv_intel_pipe_has_type(struct drm_crtc *crtc, int type) -{ -	struct drm_device *dev = crtc->dev; -	struct drm_mode_config *mode_config = &dev->mode_config; -	struct drm_connector *l_entry; - -	list_for_each_entry(l_entry, &mode_config->connector_list, head) { -		if (l_entry->encoder && l_entry->encoder->crtc == crtc) { -			struct psb_intel_output *psb_intel_output = -			    to_psb_intel_output(l_entry); -			if (psb_intel_output->type == type) -				return true; -		} -	} -	return false; -} - -static const struct cdv_intel_limit_t *cdv_intel_limit(struct drm_crtc *crtc, -							int refclk) -{ -	const struct cdv_intel_limit_t *limit; -	if (cdv_intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) { -		/* -		 * Now only single-channel LVDS is supported on CDV. If it is -		 * incorrect, please add the dual-channel LVDS. -		 */ -		if (refclk == 96000) -			limit = &cdv_intel_limits[CDV_LIMIT_SINGLE_LVDS_96]; -		else -			limit = &cdv_intel_limits[CDV_LIMIT_SINGLE_LVDS_100]; -	} else { -		if (refclk == 27000) -			limit = &cdv_intel_limits[CDV_LIMIT_DAC_HDMI_27]; -		else -			limit = &cdv_intel_limits[CDV_LIMIT_DAC_HDMI_96]; -	} -	return limit; -} - -/* m1 is reserved as 0 in CDV, n is a ring counter */ -static void cdv_intel_clock(struct drm_device *dev, -			int refclk, struct cdv_intel_clock_t *clock) -{ -	clock->m = clock->m2 + 2; -	clock->p = clock->p1 * clock->p2; -	clock->vco = (refclk * clock->m) / clock->n; -	clock->dot = clock->vco / clock->p; -} - - -#define INTELPllInvalid(s)   { /* ErrorF (s) */; return false; } -static bool cdv_intel_PLL_is_valid(struct drm_crtc *crtc, -				const struct cdv_intel_limit_t *limit, -			       struct cdv_intel_clock_t *clock) -{ -	if (clock->p1 < limit->p1.min || limit->p1.max < clock->p1) -		INTELPllInvalid("p1 out of range\n"); -	if (clock->p < limit->p.min || limit->p.max < clock->p) -		INTELPllInvalid("p out of range\n"); -	/* unnecessary to check the range of m(m1/M2)/n again */ -	if (clock->vco < limit->vco.min || limit->vco.max < clock->vco) -		INTELPllInvalid("vco out of range\n"); -	/* XXX: We may need to be checking "Dot clock" -	 * depending on the multiplier, connector, etc., -	 * rather than just a single range. -	 */ -	if (clock->dot < limit->dot.min || limit->dot.max < clock->dot) -		INTELPllInvalid("dot out of range\n"); - -	return true; -} - -static bool cdv_intel_find_best_PLL(struct drm_crtc *crtc, int target, -				int refclk, -				struct cdv_intel_clock_t *best_clock) -{ -	struct drm_device *dev = crtc->dev; -	struct cdv_intel_clock_t clock; -	const struct cdv_intel_limit_t *limit = cdv_intel_limit(crtc, refclk); -	int err = target; - - -	if (cdv_intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) && -	    (REG_READ(LVDS) & LVDS_PORT_EN) != 0) { -		/* -		 * For LVDS, if the panel is on, just rely on its current -		 * settings for dual-channel.  We haven't figured out how to -		 * reliably set up different single/dual channel state, if we -		 * even can. -		 */ -		if ((REG_READ(LVDS) & LVDS_CLKB_POWER_MASK) == -		    LVDS_CLKB_POWER_UP) -			clock.p2 = limit->p2.p2_fast; -		else -			clock.p2 = limit->p2.p2_slow; -	} else { -		if (target < limit->p2.dot_limit) -			clock.p2 = limit->p2.p2_slow; -		else -			clock.p2 = limit->p2.p2_fast; -	} - -	memset(best_clock, 0, sizeof(*best_clock)); -	clock.m1 = 0; -	/* m1 is reserved as 0 in CDV, n is a ring counter. -	   So skip the m1 loop */ -	for (clock.n = limit->n.min; clock.n <= limit->n.max; clock.n++) { -		for (clock.m2 = limit->m2.min; clock.m2 <= limit->m2.max; -					     clock.m2++) { -			for (clock.p1 = limit->p1.min; -					clock.p1 <= limit->p1.max; -					clock.p1++) { -				int this_err; - -				cdv_intel_clock(dev, refclk, &clock); - -				if (!cdv_intel_PLL_is_valid(crtc, -								limit, &clock)) -						continue; - -				this_err = abs(clock.dot - target); -				if (this_err < err) { -					*best_clock = clock; -					err = this_err; -				} -			} -		} -	} - -	return err != target; -} - -int cdv_intel_pipe_set_base(struct drm_crtc *crtc, -			    int x, int y, struct drm_framebuffer *old_fb) -{ -	struct drm_device *dev = crtc->dev; -	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); -	struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb); -	int pipe = psb_intel_crtc->pipe; -	unsigned long start, offset; -	int dspbase = (pipe == 0 ? DSPABASE : DSPBBASE); -	int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF); -	int dspstride = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE; -	int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; -	u32 dspcntr; -	int ret = 0; - -	if (!gma_power_begin(dev, true)) -		return 0; - -	/* no fb bound */ -	if (!crtc->fb) { -		dev_err(dev->dev, "No FB bound\n"); -		goto psb_intel_pipe_cleaner; -	} - - -	/* We are displaying this buffer, make sure it is actually loaded -	   into the GTT */ -	ret = psb_gtt_pin(psbfb->gtt); -	if (ret < 0) -		goto psb_intel_pipe_set_base_exit; -	start = psbfb->gtt->offset; -	offset = y * crtc->fb->pitches[0] + x * (crtc->fb->bits_per_pixel / 8); - -	REG_WRITE(dspstride, crtc->fb->pitches[0]); - -	dspcntr = REG_READ(dspcntr_reg); -	dspcntr &= ~DISPPLANE_PIXFORMAT_MASK; - -	switch (crtc->fb->bits_per_pixel) { -	case 8: -		dspcntr |= DISPPLANE_8BPP; -		break; -	case 16: -		if (crtc->fb->depth == 15) -			dspcntr |= DISPPLANE_15_16BPP; -		else -			dspcntr |= DISPPLANE_16BPP; -		break; -	case 24: -	case 32: -		dspcntr |= DISPPLANE_32BPP_NO_ALPHA; -		break; -	default: -		dev_err(dev->dev, "Unknown color depth\n"); -		ret = -EINVAL; -		goto psb_intel_pipe_set_base_exit; -	} -	REG_WRITE(dspcntr_reg, dspcntr); - -	dev_dbg(dev->dev, -		"Writing base %08lX %08lX %d %d\n", start, offset, x, y); - -	REG_WRITE(dspbase, offset); -	REG_READ(dspbase); -	REG_WRITE(dspsurf, start); -	REG_READ(dspsurf); - -psb_intel_pipe_cleaner: -	/* If there was a previous display we can now unpin it */ -	if (old_fb) -		psb_gtt_unpin(to_psb_fb(old_fb)->gtt); - -psb_intel_pipe_set_base_exit: -	gma_power_end(dev); -	return ret; -} - -/** - * Sets the power management mode of the pipe and plane. - * - * This code should probably grow support for turning the cursor off and back - * on appropriately at the same time as we're turning the pipe off/on. - */ -static void cdv_intel_crtc_dpms(struct drm_crtc *crtc, int mode) -{ -	struct drm_device *dev = crtc->dev; -	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); -	int pipe = psb_intel_crtc->pipe; -	int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B; -	int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; -	int dspbase_reg = (pipe == 0) ? DSPABASE : DSPBBASE; -	int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; -	u32 temp; -	bool enabled; - -	/* XXX: When our outputs are all unaware of DPMS modes other than off -	 * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC. -	 */ -	switch (mode) { -	case DRM_MODE_DPMS_ON: -	case DRM_MODE_DPMS_STANDBY: -	case DRM_MODE_DPMS_SUSPEND: -		/* Enable the DPLL */ -		temp = REG_READ(dpll_reg); -		if ((temp & DPLL_VCO_ENABLE) == 0) { -			REG_WRITE(dpll_reg, temp); -			REG_READ(dpll_reg); -			/* Wait for the clocks to stabilize. */ -			udelay(150); -			REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE); -			REG_READ(dpll_reg); -			/* Wait for the clocks to stabilize. */ -			udelay(150); -			REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE); -			REG_READ(dpll_reg); -			/* Wait for the clocks to stabilize. */ -			udelay(150); -		} - -		/* Jim Bish - switch plan and pipe per scott */ -		/* Enable the plane */ -		temp = REG_READ(dspcntr_reg); -		if ((temp & DISPLAY_PLANE_ENABLE) == 0) { -			REG_WRITE(dspcntr_reg, -				  temp | DISPLAY_PLANE_ENABLE); -			/* Flush the plane changes */ -			REG_WRITE(dspbase_reg, REG_READ(dspbase_reg)); -		} - -		udelay(150); - -		/* Enable the pipe */ -		temp = REG_READ(pipeconf_reg); -		if ((temp & PIPEACONF_ENABLE) == 0) -			REG_WRITE(pipeconf_reg, temp | PIPEACONF_ENABLE); - -		psb_intel_crtc_load_lut(crtc); - -		/* Give the overlay scaler a chance to enable -		 * if it's on this pipe */ -		/* psb_intel_crtc_dpms_video(crtc, true); TODO */ -		break; -	case DRM_MODE_DPMS_OFF: -		/* Give the overlay scaler a chance to disable -		 * if it's on this pipe */ -		/* psb_intel_crtc_dpms_video(crtc, FALSE); TODO */ - -		/* Disable the VGA plane that we never use */ -		REG_WRITE(VGACNTRL, VGA_DISP_DISABLE); - -		/* Jim Bish - changed pipe/plane here as well. */ - -		/* Wait for vblank for the disable to take effect */ -		cdv_intel_wait_for_vblank(dev); - -		/* Next, disable display pipes */ -		temp = REG_READ(pipeconf_reg); -		if ((temp & PIPEACONF_ENABLE) != 0) { -			REG_WRITE(pipeconf_reg, temp & ~PIPEACONF_ENABLE); -			REG_READ(pipeconf_reg); -		} - -		/* Wait for vblank for the disable to take effect. */ -		cdv_intel_wait_for_vblank(dev); - -		udelay(150); - -		/* Disable display plane */ -		temp = REG_READ(dspcntr_reg); -		if ((temp & DISPLAY_PLANE_ENABLE) != 0) { -			REG_WRITE(dspcntr_reg, -				  temp & ~DISPLAY_PLANE_ENABLE); -			/* Flush the plane changes */ -			REG_WRITE(dspbase_reg, REG_READ(dspbase_reg)); -			REG_READ(dspbase_reg); -		} - -		temp = REG_READ(dpll_reg); -		if ((temp & DPLL_VCO_ENABLE) != 0) { -			REG_WRITE(dpll_reg, temp & ~DPLL_VCO_ENABLE); -			REG_READ(dpll_reg); -		} - -		/* Wait for the clocks to turn off. */ -		udelay(150); -		break; -	} -	enabled = crtc->enabled && mode != DRM_MODE_DPMS_OFF; -	/*Set FIFO Watermarks*/ -	REG_WRITE(DSPARB, 0x3F3E); -} - -static void cdv_intel_crtc_prepare(struct drm_crtc *crtc) -{ -	struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; -	crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF); -} - -static void cdv_intel_crtc_commit(struct drm_crtc *crtc) -{ -	struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; -	crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON); -} - -void cdv_intel_encoder_prepare(struct drm_encoder *encoder) -{ -	struct drm_encoder_helper_funcs *encoder_funcs = -	    encoder->helper_private; -	/* lvds has its own version of prepare see cdv_intel_lvds_prepare */ -	encoder_funcs->dpms(encoder, DRM_MODE_DPMS_OFF); -} - -void cdv_intel_encoder_commit(struct drm_encoder *encoder) -{ -	struct drm_encoder_helper_funcs *encoder_funcs = -	    encoder->helper_private; -	/* lvds has its own version of commit see cdv_intel_lvds_commit */ -	encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON); -} - -static bool cdv_intel_crtc_mode_fixup(struct drm_crtc *crtc, -				  struct drm_display_mode *mode, -				  struct drm_display_mode *adjusted_mode) -{ -	return true; -} - - -/** - * Return the pipe currently connected to the panel fitter, - * or -1 if the panel fitter is not present or not in use - */ -static int cdv_intel_panel_fitter_pipe(struct drm_device *dev) -{ -	u32 pfit_control; - -	pfit_control = REG_READ(PFIT_CONTROL); - -	/* See if the panel fitter is in use */ -	if ((pfit_control & PFIT_ENABLE) == 0) -		return -1; -	return (pfit_control >> 29) & 0x3; -} - -static int cdv_intel_crtc_mode_set(struct drm_crtc *crtc, -			       struct drm_display_mode *mode, -			       struct drm_display_mode *adjusted_mode, -			       int x, int y, -			       struct drm_framebuffer *old_fb) -{ -	struct drm_device *dev = crtc->dev; -	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); -	int pipe = psb_intel_crtc->pipe; -	int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B; -	int dpll_md_reg = (psb_intel_crtc->pipe == 0) ? DPLL_A_MD : DPLL_B_MD; -	int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; -	int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; -	int htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B; -	int hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B; -	int hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B; -	int vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B; -	int vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B; -	int vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B; -	int dspsize_reg = (pipe == 0) ? DSPASIZE : DSPBSIZE; -	int dsppos_reg = (pipe == 0) ? DSPAPOS : DSPBPOS; -	int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC; -	int refclk; -	struct cdv_intel_clock_t clock; -	u32 dpll = 0, dspcntr, pipeconf; -	bool ok, is_sdvo = false, is_dvo = false; -	bool is_crt = false, is_lvds = false, is_tv = false; -	bool is_hdmi = false; -	struct drm_mode_config *mode_config = &dev->mode_config; -	struct drm_connector *connector; - -	list_for_each_entry(connector, &mode_config->connector_list, head) { -		struct psb_intel_output *psb_intel_output = -		    to_psb_intel_output(connector); - -		if (!connector->encoder -		    || connector->encoder->crtc != crtc) -			continue; - -		switch (psb_intel_output->type) { -		case INTEL_OUTPUT_LVDS: -			is_lvds = true; -			break; -		case INTEL_OUTPUT_SDVO: -			is_sdvo = true; -			break; -		case INTEL_OUTPUT_DVO: -			is_dvo = true; -			break; -		case INTEL_OUTPUT_TVOUT: -			is_tv = true; -			break; -		case INTEL_OUTPUT_ANALOG: -			is_crt = true; -			break; -		case INTEL_OUTPUT_HDMI: -			is_hdmi = true; -			break; -		} -	} - -	refclk = 96000; - -	/* Hack selection about ref clk for CRT */ -	/* Select 27MHz as the reference clk for HDMI */ -	if (is_crt || is_hdmi) -		refclk = 27000; - -	drm_mode_debug_printmodeline(adjusted_mode); - -	ok = cdv_intel_find_best_PLL(crtc, adjusted_mode->clock, refclk, -				 &clock); -	if (!ok) { -		dev_err(dev->dev, "Couldn't find PLL settings for mode!\n"); -		return 0; -	} - -	dpll = DPLL_VGA_MODE_DIS; -	if (is_tv) { -		/* XXX: just matching BIOS for now */ -/*	dpll |= PLL_REF_INPUT_TVCLKINBC; */ -		dpll |= 3; -	} -		dpll |= PLL_REF_INPUT_DREFCLK; - -	dpll |= DPLL_SYNCLOCK_ENABLE; -	dpll |= DPLL_VGA_MODE_DIS; -	if (is_lvds) -		dpll |= DPLLB_MODE_LVDS; -	else -		dpll |= DPLLB_MODE_DAC_SERIAL; -	/* dpll |= (2 << 11); */ - -	/* setup pipeconf */ -	pipeconf = REG_READ(pipeconf_reg); - -	/* Set up the display plane register */ -	dspcntr = DISPPLANE_GAMMA_ENABLE; - -	if (pipe == 0) -		dspcntr |= DISPPLANE_SEL_PIPE_A; -	else -		dspcntr |= DISPPLANE_SEL_PIPE_B; - -	dspcntr |= DISPLAY_PLANE_ENABLE; -	pipeconf |= PIPEACONF_ENABLE; - -	REG_WRITE(dpll_reg, dpll | DPLL_VGA_MODE_DIS | DPLL_SYNCLOCK_ENABLE); -	REG_READ(dpll_reg); - -	cdv_dpll_set_clock_cdv(dev, crtc, &clock); - -	udelay(150); - - -	/* The LVDS pin pair needs to be on before the DPLLs are enabled. -	 * This is an exception to the general rule that mode_set doesn't turn -	 * things on. -	 */ -	if (is_lvds) { -		u32 lvds = REG_READ(LVDS); - -		lvds |= -		    LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP | -		    LVDS_PIPEB_SELECT; -		/* Set the B0-B3 data pairs corresponding to -		 * whether we're going to -		 * set the DPLLs for dual-channel mode or not. -		 */ -		if (clock.p2 == 7) -			lvds |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP; -		else -			lvds &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP); - -		/* It would be nice to set 24 vs 18-bit mode (LVDS_A3_POWER_UP) -		 * appropriately here, but we need to look more -		 * thoroughly into how panels behave in the two modes. -		 */ - -		REG_WRITE(LVDS, lvds); -		REG_READ(LVDS); -	} - -	dpll |= DPLL_VCO_ENABLE; - -	/* Disable the panel fitter if it was on our pipe */ -	if (cdv_intel_panel_fitter_pipe(dev) == pipe) -		REG_WRITE(PFIT_CONTROL, 0); - -	DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B'); -	drm_mode_debug_printmodeline(mode); - -	REG_WRITE(dpll_reg, -		(REG_READ(dpll_reg) & ~DPLL_LOCK) | DPLL_VCO_ENABLE); -	REG_READ(dpll_reg); -	/* Wait for the clocks to stabilize. */ -	udelay(150); /* 42 usec w/o calibration, 110 with.  rounded up. */ - -	if (!(REG_READ(dpll_reg) & DPLL_LOCK)) { -		dev_err(dev->dev, "Failed to get DPLL lock\n"); -		return -EBUSY; -	} - -	{ -		int sdvo_pixel_multiply = adjusted_mode->clock / mode->clock; -		REG_WRITE(dpll_md_reg, (0 << DPLL_MD_UDI_DIVIDER_SHIFT) | ((sdvo_pixel_multiply - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT)); -	} - -	REG_WRITE(htot_reg, (adjusted_mode->crtc_hdisplay - 1) | -		  ((adjusted_mode->crtc_htotal - 1) << 16)); -	REG_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) | -		  ((adjusted_mode->crtc_hblank_end - 1) << 16)); -	REG_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - 1) | -		  ((adjusted_mode->crtc_hsync_end - 1) << 16)); -	REG_WRITE(vtot_reg, (adjusted_mode->crtc_vdisplay - 1) | -		  ((adjusted_mode->crtc_vtotal - 1) << 16)); -	REG_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - 1) | -		  ((adjusted_mode->crtc_vblank_end - 1) << 16)); -	REG_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - 1) | -		  ((adjusted_mode->crtc_vsync_end - 1) << 16)); -	/* pipesrc and dspsize control the size that is scaled from, -	 * which should always be the user's requested size. -	 */ -	REG_WRITE(dspsize_reg, -		  ((mode->vdisplay - 1) << 16) | (mode->hdisplay - 1)); -	REG_WRITE(dsppos_reg, 0); -	REG_WRITE(pipesrc_reg, -		  ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1)); -	REG_WRITE(pipeconf_reg, pipeconf); -	REG_READ(pipeconf_reg); - -	cdv_intel_wait_for_vblank(dev); - -	REG_WRITE(dspcntr_reg, dspcntr); - -	/* Flush the plane changes */ -	{ -		struct drm_crtc_helper_funcs *crtc_funcs = -		    crtc->helper_private; -		crtc_funcs->mode_set_base(crtc, x, y, old_fb); -	} - -	cdv_intel_wait_for_vblank(dev); - -	return 0; -} - -/** Loads the palette/gamma unit for the CRTC with the prepared values */ -void cdv_intel_crtc_load_lut(struct drm_crtc *crtc) -{ -	struct drm_device *dev = crtc->dev; -	struct drm_psb_private *dev_priv = -				(struct drm_psb_private *)dev->dev_private; -	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); -	int palreg = PALETTE_A; -	int i; - -	/* The clocks have to be on to load the palette. */ -	if (!crtc->enabled) -		return; - -	switch (psb_intel_crtc->pipe) { -	case 0: -		break; -	case 1: -		palreg = PALETTE_B; -		break; -	case 2: -		palreg = PALETTE_C; -		break; -	default: -		dev_err(dev->dev, "Illegal Pipe Number.\n"); -		return; -	} - -	if (gma_power_begin(dev, false)) { -		for (i = 0; i < 256; i++) { -			REG_WRITE(palreg + 4 * i, -				  ((psb_intel_crtc->lut_r[i] + -				  psb_intel_crtc->lut_adj[i]) << 16) | -				  ((psb_intel_crtc->lut_g[i] + -				  psb_intel_crtc->lut_adj[i]) << 8) | -				  (psb_intel_crtc->lut_b[i] + -				  psb_intel_crtc->lut_adj[i])); -		} -		gma_power_end(dev); -	} else { -		for (i = 0; i < 256; i++) { -			dev_priv->save_palette_a[i] = -				  ((psb_intel_crtc->lut_r[i] + -				  psb_intel_crtc->lut_adj[i]) << 16) | -				  ((psb_intel_crtc->lut_g[i] + -				  psb_intel_crtc->lut_adj[i]) << 8) | -				  (psb_intel_crtc->lut_b[i] + -				  psb_intel_crtc->lut_adj[i]); -		} - -	} -} - -/** - * Save HW states of giving crtc - */ -static void cdv_intel_crtc_save(struct drm_crtc *crtc) -{ -	struct drm_device *dev = crtc->dev; -	/* struct drm_psb_private *dev_priv = -			(struct drm_psb_private *)dev->dev_private; */ -	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); -	struct psb_intel_crtc_state *crtc_state = psb_intel_crtc->crtc_state; -	int pipeA = (psb_intel_crtc->pipe == 0); -	uint32_t paletteReg; -	int i; - -	if (!crtc_state) { -		dev_dbg(dev->dev, "No CRTC state found\n"); -		return; -	} - -	crtc_state->saveDSPCNTR = REG_READ(pipeA ? DSPACNTR : DSPBCNTR); -	crtc_state->savePIPECONF = REG_READ(pipeA ? PIPEACONF : PIPEBCONF); -	crtc_state->savePIPESRC = REG_READ(pipeA ? PIPEASRC : PIPEBSRC); -	crtc_state->saveFP0 = REG_READ(pipeA ? FPA0 : FPB0); -	crtc_state->saveFP1 = REG_READ(pipeA ? FPA1 : FPB1); -	crtc_state->saveDPLL = REG_READ(pipeA ? DPLL_A : DPLL_B); -	crtc_state->saveHTOTAL = REG_READ(pipeA ? HTOTAL_A : HTOTAL_B); -	crtc_state->saveHBLANK = REG_READ(pipeA ? HBLANK_A : HBLANK_B); -	crtc_state->saveHSYNC = REG_READ(pipeA ? HSYNC_A : HSYNC_B); -	crtc_state->saveVTOTAL = REG_READ(pipeA ? VTOTAL_A : VTOTAL_B); -	crtc_state->saveVBLANK = REG_READ(pipeA ? VBLANK_A : VBLANK_B); -	crtc_state->saveVSYNC = REG_READ(pipeA ? VSYNC_A : VSYNC_B); -	crtc_state->saveDSPSTRIDE = REG_READ(pipeA ? DSPASTRIDE : DSPBSTRIDE); - -	/*NOTE: DSPSIZE DSPPOS only for psb*/ -	crtc_state->saveDSPSIZE = REG_READ(pipeA ? DSPASIZE : DSPBSIZE); -	crtc_state->saveDSPPOS = REG_READ(pipeA ? DSPAPOS : DSPBPOS); - -	crtc_state->saveDSPBASE = REG_READ(pipeA ? DSPABASE : DSPBBASE); - -	DRM_DEBUG("(%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x)\n", -			crtc_state->saveDSPCNTR, -			crtc_state->savePIPECONF, -			crtc_state->savePIPESRC, -			crtc_state->saveFP0, -			crtc_state->saveFP1, -			crtc_state->saveDPLL, -			crtc_state->saveHTOTAL, -			crtc_state->saveHBLANK, -			crtc_state->saveHSYNC, -			crtc_state->saveVTOTAL, -			crtc_state->saveVBLANK, -			crtc_state->saveVSYNC, -			crtc_state->saveDSPSTRIDE, -			crtc_state->saveDSPSIZE, -			crtc_state->saveDSPPOS, -			crtc_state->saveDSPBASE -		); - -	paletteReg = pipeA ? PALETTE_A : PALETTE_B; -	for (i = 0; i < 256; ++i) -		crtc_state->savePalette[i] = REG_READ(paletteReg + (i << 2)); -} - -/** - * Restore HW states of giving crtc - */ -static void cdv_intel_crtc_restore(struct drm_crtc *crtc) -{ -	struct drm_device *dev = crtc->dev; -	/* struct drm_psb_private * dev_priv = -				(struct drm_psb_private *)dev->dev_private; */ -	struct psb_intel_crtc *psb_intel_crtc =  to_psb_intel_crtc(crtc); -	struct psb_intel_crtc_state *crtc_state = psb_intel_crtc->crtc_state; -	/* struct drm_crtc_helper_funcs * crtc_funcs = crtc->helper_private; */ -	int pipeA = (psb_intel_crtc->pipe == 0); -	uint32_t paletteReg; -	int i; - -	if (!crtc_state) { -		dev_dbg(dev->dev, "No crtc state\n"); -		return; -	} - -	DRM_DEBUG( -		"current:(%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x)\n", -		REG_READ(pipeA ? DSPACNTR : DSPBCNTR), -		REG_READ(pipeA ? PIPEACONF : PIPEBCONF), -		REG_READ(pipeA ? PIPEASRC : PIPEBSRC), -		REG_READ(pipeA ? FPA0 : FPB0), -		REG_READ(pipeA ? FPA1 : FPB1), -		REG_READ(pipeA ? DPLL_A : DPLL_B), -		REG_READ(pipeA ? HTOTAL_A : HTOTAL_B), -		REG_READ(pipeA ? HBLANK_A : HBLANK_B), -		REG_READ(pipeA ? HSYNC_A : HSYNC_B), -		REG_READ(pipeA ? VTOTAL_A : VTOTAL_B), -		REG_READ(pipeA ? VBLANK_A : VBLANK_B), -		REG_READ(pipeA ? VSYNC_A : VSYNC_B), -		REG_READ(pipeA ? DSPASTRIDE : DSPBSTRIDE), -		REG_READ(pipeA ? DSPASIZE : DSPBSIZE), -		REG_READ(pipeA ? DSPAPOS : DSPBPOS), -		REG_READ(pipeA ? DSPABASE : DSPBBASE) -		); - -	DRM_DEBUG( -		"saved: (%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x)\n", -		crtc_state->saveDSPCNTR, -		crtc_state->savePIPECONF, -		crtc_state->savePIPESRC, -		crtc_state->saveFP0, -		crtc_state->saveFP1, -		crtc_state->saveDPLL, -		crtc_state->saveHTOTAL, -		crtc_state->saveHBLANK, -		crtc_state->saveHSYNC, -		crtc_state->saveVTOTAL, -		crtc_state->saveVBLANK, -		crtc_state->saveVSYNC, -		crtc_state->saveDSPSTRIDE, -		crtc_state->saveDSPSIZE, -		crtc_state->saveDSPPOS, -		crtc_state->saveDSPBASE -		); - - -	if (crtc_state->saveDPLL & DPLL_VCO_ENABLE) { -		REG_WRITE(pipeA ? DPLL_A : DPLL_B, -			crtc_state->saveDPLL & ~DPLL_VCO_ENABLE); -		REG_READ(pipeA ? DPLL_A : DPLL_B); -		DRM_DEBUG("write dpll: %x\n", -				REG_READ(pipeA ? DPLL_A : DPLL_B)); -		udelay(150); -	} - -	REG_WRITE(pipeA ? FPA0 : FPB0, crtc_state->saveFP0); -	REG_READ(pipeA ? FPA0 : FPB0); - -	REG_WRITE(pipeA ? FPA1 : FPB1, crtc_state->saveFP1); -	REG_READ(pipeA ? FPA1 : FPB1); - -	REG_WRITE(pipeA ? DPLL_A : DPLL_B, crtc_state->saveDPLL); -	REG_READ(pipeA ? DPLL_A : DPLL_B); -	udelay(150); - -	REG_WRITE(pipeA ? HTOTAL_A : HTOTAL_B, crtc_state->saveHTOTAL); -	REG_WRITE(pipeA ? HBLANK_A : HBLANK_B, crtc_state->saveHBLANK); -	REG_WRITE(pipeA ? HSYNC_A : HSYNC_B, crtc_state->saveHSYNC); -	REG_WRITE(pipeA ? VTOTAL_A : VTOTAL_B, crtc_state->saveVTOTAL); -	REG_WRITE(pipeA ? VBLANK_A : VBLANK_B, crtc_state->saveVBLANK); -	REG_WRITE(pipeA ? VSYNC_A : VSYNC_B, crtc_state->saveVSYNC); -	REG_WRITE(pipeA ? DSPASTRIDE : DSPBSTRIDE, crtc_state->saveDSPSTRIDE); - -	REG_WRITE(pipeA ? DSPASIZE : DSPBSIZE, crtc_state->saveDSPSIZE); -	REG_WRITE(pipeA ? DSPAPOS : DSPBPOS, crtc_state->saveDSPPOS); - -	REG_WRITE(pipeA ? PIPEASRC : PIPEBSRC, crtc_state->savePIPESRC); -	REG_WRITE(pipeA ? DSPABASE : DSPBBASE, crtc_state->saveDSPBASE); -	REG_WRITE(pipeA ? PIPEACONF : PIPEBCONF, crtc_state->savePIPECONF); - -	cdv_intel_wait_for_vblank(dev); - -	REG_WRITE(pipeA ? DSPACNTR : DSPBCNTR, crtc_state->saveDSPCNTR); -	REG_WRITE(pipeA ? DSPABASE : DSPBBASE, crtc_state->saveDSPBASE); - -	cdv_intel_wait_for_vblank(dev); - -	paletteReg = pipeA ? PALETTE_A : PALETTE_B; -	for (i = 0; i < 256; ++i) -		REG_WRITE(paletteReg + (i << 2), crtc_state->savePalette[i]); -} - -static int cdv_intel_crtc_cursor_set(struct drm_crtc *crtc, -				 struct drm_file *file_priv, -				 uint32_t handle, -				 uint32_t width, uint32_t height) -{ -	struct drm_device *dev = crtc->dev; -	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); -	int pipe = psb_intel_crtc->pipe; -	uint32_t control = (pipe == 0) ? CURACNTR : CURBCNTR; -	uint32_t base = (pipe == 0) ? CURABASE : CURBBASE; -	uint32_t temp; -	size_t addr = 0; -	struct gtt_range *gt; -	struct drm_gem_object *obj; -	int ret; - -	/* if we want to turn of the cursor ignore width and height */ -	if (!handle) { -		/* turn off the cursor */ -		temp = CURSOR_MODE_DISABLE; - -		if (gma_power_begin(dev, false)) { -			REG_WRITE(control, temp); -			REG_WRITE(base, 0); -			gma_power_end(dev); -		} - -		/* unpin the old GEM object */ -		if (psb_intel_crtc->cursor_obj) { -			gt = container_of(psb_intel_crtc->cursor_obj, -							struct gtt_range, gem); -			psb_gtt_unpin(gt); -			drm_gem_object_unreference(psb_intel_crtc->cursor_obj); -			psb_intel_crtc->cursor_obj = NULL; -		} - -		return 0; -	} - -	/* Currently we only support 64x64 cursors */ -	if (width != 64 || height != 64) { -		dev_dbg(dev->dev, "we currently only support 64x64 cursors\n"); -		return -EINVAL; -	} - -	obj = drm_gem_object_lookup(dev, file_priv, handle); -	if (!obj) -		return -ENOENT; - -	if (obj->size < width * height * 4) { -		dev_dbg(dev->dev, "buffer is to small\n"); -		return -ENOMEM; -	} - -	gt = container_of(obj, struct gtt_range, gem); - -	/* Pin the memory into the GTT */ -	ret = psb_gtt_pin(gt); -	if (ret) { -		dev_err(dev->dev, "Can not pin down handle 0x%x\n", handle); -		return ret; -	} - -	addr = gt->offset;	/* Or resource.start ??? */ - -	psb_intel_crtc->cursor_addr = addr; - -	temp = 0; -	/* set the pipe for the cursor */ -	temp |= (pipe << 28); -	temp |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE; - -	if (gma_power_begin(dev, false)) { -		REG_WRITE(control, temp); -		REG_WRITE(base, addr); -		gma_power_end(dev); -	} - -	/* unpin the old GEM object */ -	if (psb_intel_crtc->cursor_obj) { -		gt = container_of(psb_intel_crtc->cursor_obj, -							struct gtt_range, gem); -		psb_gtt_unpin(gt); -		drm_gem_object_unreference(psb_intel_crtc->cursor_obj); -		psb_intel_crtc->cursor_obj = obj; -	} -	return 0; -} - -static int cdv_intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) -{ -	struct drm_device *dev = crtc->dev; -	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); -	int pipe = psb_intel_crtc->pipe; -	uint32_t temp = 0; -	uint32_t adder; - - -	if (x < 0) { -		temp |= (CURSOR_POS_SIGN << CURSOR_X_SHIFT); -		x = -x; -	} -	if (y < 0) { -		temp |= (CURSOR_POS_SIGN << CURSOR_Y_SHIFT); -		y = -y; -	} - -	temp |= ((x & CURSOR_POS_MASK) << CURSOR_X_SHIFT); -	temp |= ((y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT); - -	adder = psb_intel_crtc->cursor_addr; - -	if (gma_power_begin(dev, false)) { -		REG_WRITE((pipe == 0) ? CURAPOS : CURBPOS, temp); -		REG_WRITE((pipe == 0) ? CURABASE : CURBBASE, adder); -		gma_power_end(dev); -	} -	return 0; -} - -static void cdv_intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, -			 u16 *green, u16 *blue, uint32_t start, uint32_t size) -{ -	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); -	int i; -	int end = (start + size > 256) ? 256 : start + size; - -	for (i = start; i < end; i++) { -		psb_intel_crtc->lut_r[i] = red[i] >> 8; -		psb_intel_crtc->lut_g[i] = green[i] >> 8; -		psb_intel_crtc->lut_b[i] = blue[i] >> 8; -	} - -	cdv_intel_crtc_load_lut(crtc); -} - -static int cdv_crtc_set_config(struct drm_mode_set *set) -{ -	int ret = 0; -	struct drm_device *dev = set->crtc->dev; -	struct drm_psb_private *dev_priv = dev->dev_private; - -	if (!dev_priv->rpm_enabled) -		return drm_crtc_helper_set_config(set); - -	pm_runtime_forbid(&dev->pdev->dev); - -	ret = drm_crtc_helper_set_config(set); - -	pm_runtime_allow(&dev->pdev->dev); - -	return ret; -} - -/** Derive the pixel clock for the given refclk and divisors for 8xx chips. */ - -/* FIXME: why are we using this, should it be cdv_ in this tree ? */ - -static void i8xx_clock(int refclk, struct cdv_intel_clock_t *clock) -{ -	clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2); -	clock->p = clock->p1 * clock->p2; -	clock->vco = refclk * clock->m / (clock->n + 2); -	clock->dot = clock->vco / clock->p; -} - -/* Returns the clock of the currently programmed mode of the given pipe. */ -static int cdv_intel_crtc_clock_get(struct drm_device *dev, -				struct drm_crtc *crtc) -{ -	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); -	int pipe = psb_intel_crtc->pipe; -	u32 dpll; -	u32 fp; -	struct cdv_intel_clock_t clock; -	bool is_lvds; -	struct drm_psb_private *dev_priv = dev->dev_private; - -	if (gma_power_begin(dev, false)) { -		dpll = REG_READ((pipe == 0) ? DPLL_A : DPLL_B); -		if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0) -			fp = REG_READ((pipe == 0) ? FPA0 : FPB0); -		else -			fp = REG_READ((pipe == 0) ? FPA1 : FPB1); -		is_lvds = (pipe == 1) && (REG_READ(LVDS) & LVDS_PORT_EN); -		gma_power_end(dev); -	} else { -		dpll = (pipe == 0) ? -			dev_priv->saveDPLL_A : dev_priv->saveDPLL_B; - -		if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0) -			fp = (pipe == 0) ? -				dev_priv->saveFPA0 : -				dev_priv->saveFPB0; -		else -			fp = (pipe == 0) ? -				dev_priv->saveFPA1 : -				dev_priv->saveFPB1; - -		is_lvds = (pipe == 1) && (dev_priv->saveLVDS & LVDS_PORT_EN); -	} - -	clock.m1 = (fp & FP_M1_DIV_MASK) >> FP_M1_DIV_SHIFT; -	clock.m2 = (fp & FP_M2_DIV_MASK) >> FP_M2_DIV_SHIFT; -	clock.n = (fp & FP_N_DIV_MASK) >> FP_N_DIV_SHIFT; - -	if (is_lvds) { -		clock.p1 = -		    ffs((dpll & -			 DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS) >> -			DPLL_FPA01_P1_POST_DIV_SHIFT); -		if (clock.p1 == 0) { -			clock.p1 = 4; -			dev_err(dev->dev, "PLL %d\n", dpll); -		} -		clock.p2 = 14; - -		if ((dpll & PLL_REF_INPUT_MASK) == -		    PLLB_REF_INPUT_SPREADSPECTRUMIN) { -			/* XXX: might not be 66MHz */ -			i8xx_clock(66000, &clock); -		} else -			i8xx_clock(48000, &clock); -	} else { -		if (dpll & PLL_P1_DIVIDE_BY_TWO) -			clock.p1 = 2; -		else { -			clock.p1 = -			    ((dpll & -			      DPLL_FPA01_P1_POST_DIV_MASK_I830) >> -			     DPLL_FPA01_P1_POST_DIV_SHIFT) + 2; -		} -		if (dpll & PLL_P2_DIVIDE_BY_4) -			clock.p2 = 4; -		else -			clock.p2 = 2; - -		i8xx_clock(48000, &clock); -	} - -	/* XXX: It would be nice to validate the clocks, but we can't reuse -	 * i830PllIsValid() because it relies on the xf86_config connector -	 * configuration being accurate, which it isn't necessarily. -	 */ - -	return clock.dot; -} - -/** Returns the currently programmed mode of the given pipe. */ -struct drm_display_mode *cdv_intel_crtc_mode_get(struct drm_device *dev, -					     struct drm_crtc *crtc) -{ -	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); -	int pipe = psb_intel_crtc->pipe; -	struct drm_display_mode *mode; -	int htot; -	int hsync; -	int vtot; -	int vsync; -	struct drm_psb_private *dev_priv = dev->dev_private; - -	if (gma_power_begin(dev, false)) { -		htot = REG_READ((pipe == 0) ? HTOTAL_A : HTOTAL_B); -		hsync = REG_READ((pipe == 0) ? HSYNC_A : HSYNC_B); -		vtot = REG_READ((pipe == 0) ? VTOTAL_A : VTOTAL_B); -		vsync = REG_READ((pipe == 0) ? VSYNC_A : VSYNC_B); -		gma_power_end(dev); -	} else { -		htot = (pipe == 0) ? -			dev_priv->saveHTOTAL_A : dev_priv->saveHTOTAL_B; -		hsync = (pipe == 0) ? -			dev_priv->saveHSYNC_A : dev_priv->saveHSYNC_B; -		vtot = (pipe == 0) ? -			dev_priv->saveVTOTAL_A : dev_priv->saveVTOTAL_B; -		vsync = (pipe == 0) ? -			dev_priv->saveVSYNC_A : dev_priv->saveVSYNC_B; -	} - -	mode = kzalloc(sizeof(*mode), GFP_KERNEL); -	if (!mode) -		return NULL; - -	mode->clock = cdv_intel_crtc_clock_get(dev, crtc); -	mode->hdisplay = (htot & 0xffff) + 1; -	mode->htotal = ((htot & 0xffff0000) >> 16) + 1; -	mode->hsync_start = (hsync & 0xffff) + 1; -	mode->hsync_end = ((hsync & 0xffff0000) >> 16) + 1; -	mode->vdisplay = (vtot & 0xffff) + 1; -	mode->vtotal = ((vtot & 0xffff0000) >> 16) + 1; -	mode->vsync_start = (vsync & 0xffff) + 1; -	mode->vsync_end = ((vsync & 0xffff0000) >> 16) + 1; - -	drm_mode_set_name(mode); -	drm_mode_set_crtcinfo(mode, 0); - -	return mode; -} - -static void cdv_intel_crtc_destroy(struct drm_crtc *crtc) -{ -	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); - -	kfree(psb_intel_crtc->crtc_state); -	drm_crtc_cleanup(crtc); -	kfree(psb_intel_crtc); -} - -const struct drm_crtc_helper_funcs cdv_intel_helper_funcs = { -	.dpms = cdv_intel_crtc_dpms, -	.mode_fixup = cdv_intel_crtc_mode_fixup, -	.mode_set = cdv_intel_crtc_mode_set, -	.mode_set_base = cdv_intel_pipe_set_base, -	.prepare = cdv_intel_crtc_prepare, -	.commit = cdv_intel_crtc_commit, -}; - -const struct drm_crtc_funcs cdv_intel_crtc_funcs = { -	.save = cdv_intel_crtc_save, -	.restore = cdv_intel_crtc_restore, -	.cursor_set = cdv_intel_crtc_cursor_set, -	.cursor_move = cdv_intel_crtc_cursor_move, -	.gamma_set = cdv_intel_crtc_gamma_set, -	.set_config = cdv_crtc_set_config, -	.destroy = cdv_intel_crtc_destroy, -}; - -/* - * Set the default value of cursor control and base register - * to zero. This is a workaround for h/w defect on oaktrail - */ -void cdv_intel_cursor_init(struct drm_device *dev, int pipe) -{ -	uint32_t control; -	uint32_t base; - -	switch (pipe) { -	case 0: -		control = CURACNTR; -		base = CURABASE; -		break; -	case 1: -		control = CURBCNTR; -		base = CURBBASE; -		break; -	case 2: -		control = CURCCNTR; -		base = CURCBASE; -		break; -	default: -		return; -	} - -	REG_WRITE(control, 0); -	REG_WRITE(base, 0); -} - diff --git a/drivers/staging/gma500/cdv_intel_hdmi.c b/drivers/staging/gma500/cdv_intel_hdmi.c deleted file mode 100644 index cbca2b0c7d5..00000000000 --- a/drivers/staging/gma500/cdv_intel_hdmi.c +++ /dev/null @@ -1,376 +0,0 @@ -/* - * Copyright © 2006-2011 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Authors: - *	jim liu <jim.liu@intel.com> - * - * FIXME: - *	We should probably make this generic and share it with Medfield - */ - -#include <drm/drmP.h> -#include <drm/drm.h> -#include <drm/drm_crtc.h> -#include <drm/drm_edid.h> -#include "psb_intel_drv.h" -#include "psb_drv.h" -#include "psb_intel_reg.h" -#include <linux/pm_runtime.h> - -/* hdmi control bits */ -#define HDMI_NULL_PACKETS_DURING_VSYNC	(1 << 9) -#define HDMI_BORDER_ENABLE		(1 << 7) -#define HDMI_AUDIO_ENABLE		(1 << 6) -#define HDMI_VSYNC_ACTIVE_HIGH		(1 << 4) -#define HDMI_HSYNC_ACTIVE_HIGH		(1 << 3) -/* hdmi-b control bits */ -#define	HDMIB_PIPE_B_SELECT		(1 << 30) - - -struct mid_intel_hdmi_priv { -	u32 hdmi_reg; -	u32 save_HDMIB; -	bool has_hdmi_sink; -	bool has_hdmi_audio; -	/* Should set this when detect hotplug */ -	bool hdmi_device_connected; -	struct mdfld_hdmi_i2c *i2c_bus; -	struct i2c_adapter *hdmi_i2c_adapter;	/* for control functions */ -	struct drm_device *dev; -}; - -static void cdv_hdmi_mode_set(struct drm_encoder *encoder, -			struct drm_display_mode *mode, -			struct drm_display_mode *adjusted_mode) -{ -	struct drm_device *dev = encoder->dev; -	struct psb_intel_output *output = enc_to_psb_intel_output(encoder); -	struct mid_intel_hdmi_priv *hdmi_priv = output->dev_priv; -	u32 hdmib; -	struct drm_crtc *crtc = encoder->crtc; -	struct psb_intel_crtc *intel_crtc = to_psb_intel_crtc(crtc); - -	hdmib = (2 << 10); - -	if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) -		hdmib |= HDMI_VSYNC_ACTIVE_HIGH; -	if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) -		hdmib |= HDMI_HSYNC_ACTIVE_HIGH; - -	if (intel_crtc->pipe == 1) -		hdmib |= HDMIB_PIPE_B_SELECT; - -	if (hdmi_priv->has_hdmi_audio) { -		hdmib |= HDMI_AUDIO_ENABLE; -		hdmib |= HDMI_NULL_PACKETS_DURING_VSYNC; -	} - -	REG_WRITE(hdmi_priv->hdmi_reg, hdmib); -	REG_READ(hdmi_priv->hdmi_reg); -} - -static bool cdv_hdmi_mode_fixup(struct drm_encoder *encoder, -				  struct drm_display_mode *mode, -				  struct drm_display_mode *adjusted_mode) -{ -	return true; -} - -static void cdv_hdmi_dpms(struct drm_encoder *encoder, int mode) -{ -	struct drm_device *dev = encoder->dev; -	struct psb_intel_output *output = enc_to_psb_intel_output(encoder); -	struct mid_intel_hdmi_priv *hdmi_priv = output->dev_priv; -	u32 hdmib; - -	hdmib = REG_READ(hdmi_priv->hdmi_reg); - -	if (mode != DRM_MODE_DPMS_ON) -		REG_WRITE(hdmi_priv->hdmi_reg, hdmib & ~HDMIB_PORT_EN); -	else -		REG_WRITE(hdmi_priv->hdmi_reg, hdmib | HDMIB_PORT_EN); -	REG_READ(hdmi_priv->hdmi_reg); -} - -static void cdv_hdmi_save(struct drm_connector *connector) -{ -	struct drm_device *dev = connector->dev; -	struct psb_intel_output *output = to_psb_intel_output(connector); -	struct mid_intel_hdmi_priv *hdmi_priv = output->dev_priv; - -	hdmi_priv->save_HDMIB = REG_READ(hdmi_priv->hdmi_reg); -} - -static void cdv_hdmi_restore(struct drm_connector *connector) -{ -	struct drm_device *dev = connector->dev; -	struct psb_intel_output *output = to_psb_intel_output(connector); -	struct mid_intel_hdmi_priv *hdmi_priv = output->dev_priv; - -	REG_WRITE(hdmi_priv->hdmi_reg, hdmi_priv->save_HDMIB); -	REG_READ(hdmi_priv->hdmi_reg); -} - -static enum drm_connector_status cdv_hdmi_detect( -				struct drm_connector *connector, bool force) -{ -	struct psb_intel_output *psb_intel_output = -						to_psb_intel_output(connector); -	struct mid_intel_hdmi_priv *hdmi_priv = psb_intel_output->dev_priv; -	struct edid *edid = NULL; -	enum drm_connector_status status = connector_status_disconnected; - -	edid = drm_get_edid(&psb_intel_output->base, -			 psb_intel_output->hdmi_i2c_adapter); - -	hdmi_priv->has_hdmi_sink = false; -	hdmi_priv->has_hdmi_audio = false; -	if (edid) { -		if (edid->input & DRM_EDID_INPUT_DIGITAL) { -			status = connector_status_connected; -			hdmi_priv->has_hdmi_sink = -						drm_detect_hdmi_monitor(edid); -			hdmi_priv->has_hdmi_audio = -						drm_detect_monitor_audio(edid); -		} - -		psb_intel_output->base.display_info.raw_edid = NULL; -		kfree(edid); -	} -	return status; -} - -static int cdv_hdmi_set_property(struct drm_connector *connector, -				       struct drm_property *property, -				       uint64_t value) -{ -	struct drm_encoder *encoder = connector->encoder; - -	if (!strcmp(property->name, "scaling mode") && encoder) { -		struct psb_intel_crtc *crtc = to_psb_intel_crtc(encoder->crtc); -		bool centre; -		uint64_t curValue; - -		if (!crtc) -			return -1; - -		switch (value) { -		case DRM_MODE_SCALE_FULLSCREEN: -			break; -		case DRM_MODE_SCALE_NO_SCALE: -			break; -		case DRM_MODE_SCALE_ASPECT: -			break; -		default: -			return -1; -		} - -		if (drm_connector_property_get_value(connector, -							property, &curValue)) -			return -1; - -		if (curValue == value) -			return 0; - -		if (drm_connector_property_set_value(connector, -							property, value)) -			return -1; - -		centre = (curValue == DRM_MODE_SCALE_NO_SCALE) || -			(value == DRM_MODE_SCALE_NO_SCALE); - -		if (crtc->saved_mode.hdisplay != 0 && -		    crtc->saved_mode.vdisplay != 0) { -			if (centre) { -				if (!drm_crtc_helper_set_mode(encoder->crtc, &crtc->saved_mode, -					    encoder->crtc->x, encoder->crtc->y, encoder->crtc->fb)) -					return -1; -			} else { -				struct drm_encoder_helper_funcs *helpers -						    = encoder->helper_private; -				helpers->mode_set(encoder, &crtc->saved_mode, -					     &crtc->saved_adjusted_mode); -			} -		} -	} -	return 0; -} - -/* - * Return the list of HDMI DDC modes if available. - */ -static int cdv_hdmi_get_modes(struct drm_connector *connector) -{ -	struct psb_intel_output *psb_intel_output = -					to_psb_intel_output(connector); -	struct edid *edid = NULL; -	int ret = 0; - -	edid = drm_get_edid(&psb_intel_output->base, -			 psb_intel_output->hdmi_i2c_adapter); -	if (edid) { -		drm_mode_connector_update_edid_property(&psb_intel_output-> -							base, edid); -		ret = drm_add_edid_modes(&psb_intel_output->base, edid); -		kfree(edid); -	} -	return ret; -} - -static int cdv_hdmi_mode_valid(struct drm_connector *connector, -				 struct drm_display_mode *mode) -{ - -	if (mode->clock > 165000) -		return MODE_CLOCK_HIGH; -	if (mode->clock < 20000) -		return MODE_CLOCK_HIGH; - -	/* just in case */ -	if (mode->flags & DRM_MODE_FLAG_DBLSCAN) -		return MODE_NO_DBLESCAN; - -	/* just in case */ -	if (mode->flags & DRM_MODE_FLAG_INTERLACE) -		return MODE_NO_INTERLACE; - -	/* -	 * FIXME: for now we limit the size to 1680x1050 on CDV, otherwise it -	 * will go beyond the stolen memory size allocated to the framebuffer -	 */ -	if (mode->hdisplay > 1680) -		return MODE_PANEL; -	if (mode->vdisplay > 1050) -		return MODE_PANEL; -	return MODE_OK; -} - -static void cdv_hdmi_destroy(struct drm_connector *connector) -{ -	struct psb_intel_output *psb_intel_output = -					to_psb_intel_output(connector); - -	if (psb_intel_output->ddc_bus) -		psb_intel_i2c_destroy(psb_intel_output->ddc_bus); -	drm_sysfs_connector_remove(connector); -	drm_connector_cleanup(connector); -	kfree(connector); -} - -static const struct drm_encoder_helper_funcs cdv_hdmi_helper_funcs = { -	.dpms = cdv_hdmi_dpms, -	.mode_fixup = cdv_hdmi_mode_fixup, -	.prepare = psb_intel_encoder_prepare, -	.mode_set = cdv_hdmi_mode_set, -	.commit = psb_intel_encoder_commit, -}; - -static const struct drm_connector_helper_funcs -					cdv_hdmi_connector_helper_funcs = { -	.get_modes = cdv_hdmi_get_modes, -	.mode_valid = cdv_hdmi_mode_valid, -	.best_encoder = psb_intel_best_encoder, -}; - -static const struct drm_connector_funcs cdv_hdmi_connector_funcs = { -	.dpms = drm_helper_connector_dpms, -	.save = cdv_hdmi_save, -	.restore = cdv_hdmi_restore, -	.detect = cdv_hdmi_detect, -	.fill_modes = drm_helper_probe_single_connector_modes, -	.set_property = cdv_hdmi_set_property, -	.destroy = cdv_hdmi_destroy, -}; - -void cdv_hdmi_init(struct drm_device *dev, -			struct psb_intel_mode_device *mode_dev, int reg) -{ -	struct psb_intel_output *psb_intel_output; -	struct drm_connector *connector; -	struct drm_encoder *encoder; -	struct mid_intel_hdmi_priv *hdmi_priv; -	int ddc_bus; - -	psb_intel_output = kzalloc(sizeof(struct psb_intel_output) + -			       sizeof(struct mid_intel_hdmi_priv), GFP_KERNEL); -	if (!psb_intel_output) -		return; - -	hdmi_priv = (struct mid_intel_hdmi_priv *)(psb_intel_output + 1); -	psb_intel_output->mode_dev = mode_dev; -	connector = &psb_intel_output->base; -	encoder = &psb_intel_output->enc; -	drm_connector_init(dev, &psb_intel_output->base, -			   &cdv_hdmi_connector_funcs, -			   DRM_MODE_CONNECTOR_DVID); - -	drm_encoder_init(dev, &psb_intel_output->enc, &psb_intel_lvds_enc_funcs, -			 DRM_MODE_ENCODER_TMDS); - -	drm_mode_connector_attach_encoder(&psb_intel_output->base, -					  &psb_intel_output->enc); -	psb_intel_output->type = INTEL_OUTPUT_HDMI; -	hdmi_priv->hdmi_reg = reg; -	hdmi_priv->has_hdmi_sink = false; -	psb_intel_output->dev_priv = hdmi_priv; - -	drm_encoder_helper_add(encoder, &cdv_hdmi_helper_funcs); -	drm_connector_helper_add(connector, -				 &cdv_hdmi_connector_helper_funcs); -	connector->display_info.subpixel_order = SubPixelHorizontalRGB; -	connector->interlace_allowed = false; -	connector->doublescan_allowed = false; - -	drm_connector_attach_property(connector, -	    dev->mode_config.scaling_mode_property, DRM_MODE_SCALE_FULLSCREEN); - -	switch (reg) { -	case SDVOB: -		ddc_bus = GPIOE; -		break; -	case SDVOC: -		ddc_bus = GPIOD; -		break; -	default: -		DRM_ERROR("unknown reg 0x%x for HDMI\n", reg); -		goto failed_ddc; -		break; -	} - -	psb_intel_output->ddc_bus = psb_intel_i2c_create(dev, -				ddc_bus, (reg == SDVOB) ? "HDMIB" : "HDMIC"); - -	if (!psb_intel_output->ddc_bus) { -		dev_err(dev->dev, "No ddc adapter available!\n"); -		goto failed_ddc; -	} -	psb_intel_output->hdmi_i2c_adapter = -				&(psb_intel_output->ddc_bus->adapter); -	hdmi_priv->dev = dev; -	drm_sysfs_connector_add(connector); -	return; - -failed_ddc: -	drm_encoder_cleanup(&psb_intel_output->enc); -	drm_connector_cleanup(&psb_intel_output->base); -	kfree(psb_intel_output); -} diff --git a/drivers/staging/gma500/cdv_intel_lvds.c b/drivers/staging/gma500/cdv_intel_lvds.c deleted file mode 100644 index 988b2d0acf4..00000000000 --- a/drivers/staging/gma500/cdv_intel_lvds.c +++ /dev/null @@ -1,721 +0,0 @@ -/* - * Copyright © 2006-2011 Intel Corporation - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - * Authors: - *	Eric Anholt <eric@anholt.net> - *	Dave Airlie <airlied@linux.ie> - *	Jesse Barnes <jesse.barnes@intel.com> - */ - -#include <linux/i2c.h> -#include <linux/dmi.h> -#include <drm/drmP.h> - -#include "intel_bios.h" -#include "psb_drv.h" -#include "psb_intel_drv.h" -#include "psb_intel_reg.h" -#include "power.h" -#include <linux/pm_runtime.h> -#include "cdv_device.h" - -/** - * LVDS I2C backlight control macros - */ -#define BRIGHTNESS_MAX_LEVEL 100 -#define BRIGHTNESS_MASK 0xFF -#define BLC_I2C_TYPE	0x01 -#define BLC_PWM_TYPT	0x02 - -#define BLC_POLARITY_NORMAL 0 -#define BLC_POLARITY_INVERSE 1 - -#define PSB_BLC_MAX_PWM_REG_FREQ       (0xFFFE) -#define PSB_BLC_MIN_PWM_REG_FREQ	(0x2) -#define PSB_BLC_PWM_PRECISION_FACTOR	(10) -#define PSB_BACKLIGHT_PWM_CTL_SHIFT	(16) -#define PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR (0xFFFE) - -struct cdv_intel_lvds_priv { -	/** -	 * Saved LVDO output states -	 */ -	uint32_t savePP_ON; -	uint32_t savePP_OFF; -	uint32_t saveLVDS; -	uint32_t savePP_CONTROL; -	uint32_t savePP_CYCLE; -	uint32_t savePFIT_CONTROL; -	uint32_t savePFIT_PGM_RATIOS; -	uint32_t saveBLC_PWM_CTL; -}; - -/* - * Returns the maximum level of the backlight duty cycle field. - */ -static u32 cdv_intel_lvds_get_max_backlight(struct drm_device *dev) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; -	u32 retval; - -	if (gma_power_begin(dev, false)) { -		retval = ((REG_READ(BLC_PWM_CTL) & -			  BACKLIGHT_MODULATION_FREQ_MASK) >> -			  BACKLIGHT_MODULATION_FREQ_SHIFT) * 2; - -		gma_power_end(dev); -	} else -		retval = ((dev_priv->saveBLC_PWM_CTL & -			  BACKLIGHT_MODULATION_FREQ_MASK) >> -			  BACKLIGHT_MODULATION_FREQ_SHIFT) * 2; - -	return retval; -} - -/* - * Set LVDS backlight level by I2C command - */ -static int cdv_lvds_i2c_set_brightness(struct drm_device *dev, -					unsigned int level) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; -	struct psb_intel_i2c_chan *lvds_i2c_bus = dev_priv->lvds_i2c_bus; -	u8 out_buf[2]; -	unsigned int blc_i2c_brightness; - -	struct i2c_msg msgs[] = { -		{ -			.addr = lvds_i2c_bus->slave_addr, -			.flags = 0, -			.len = 2, -			.buf = out_buf, -		} -	}; - -	blc_i2c_brightness = BRIGHTNESS_MASK & ((unsigned int)level * -			     BRIGHTNESS_MASK / -			     BRIGHTNESS_MAX_LEVEL); - -	if (dev_priv->lvds_bl->pol == BLC_POLARITY_INVERSE) -		blc_i2c_brightness = BRIGHTNESS_MASK - blc_i2c_brightness; - -	out_buf[0] = dev_priv->lvds_bl->brightnesscmd; -	out_buf[1] = (u8)blc_i2c_brightness; - -	if (i2c_transfer(&lvds_i2c_bus->adapter, msgs, 1) == 1) -		return 0; - -	DRM_ERROR("I2C transfer error\n"); -	return -1; -} - - -static int cdv_lvds_pwm_set_brightness(struct drm_device *dev, int level) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; - -	u32 max_pwm_blc; -	u32 blc_pwm_duty_cycle; - -	max_pwm_blc = cdv_intel_lvds_get_max_backlight(dev); - -	/*BLC_PWM_CTL Should be initiated while backlight device init*/ -	BUG_ON((max_pwm_blc & PSB_BLC_MAX_PWM_REG_FREQ) == 0); - -	blc_pwm_duty_cycle = level * max_pwm_blc / BRIGHTNESS_MAX_LEVEL; - -	if (dev_priv->lvds_bl->pol == BLC_POLARITY_INVERSE) -		blc_pwm_duty_cycle = max_pwm_blc - blc_pwm_duty_cycle; - -	blc_pwm_duty_cycle &= PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR; -	REG_WRITE(BLC_PWM_CTL, -		  (max_pwm_blc << PSB_BACKLIGHT_PWM_CTL_SHIFT) | -		  (blc_pwm_duty_cycle)); - -	return 0; -} - -/* - * Set LVDS backlight level either by I2C or PWM - */ -void cdv_intel_lvds_set_brightness(struct drm_device *dev, int level) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; - -	if (!dev_priv->lvds_bl) { -		DRM_ERROR("NO LVDS Backlight Info\n"); -		return; -	} - -	if (dev_priv->lvds_bl->type == BLC_I2C_TYPE) -		cdv_lvds_i2c_set_brightness(dev, level); -	else -		cdv_lvds_pwm_set_brightness(dev, level); -} - -/** - * Sets the backlight level. - * - * level backlight level, from 0 to cdv_intel_lvds_get_max_backlight(). - */ -static void cdv_intel_lvds_set_backlight(struct drm_device *dev, int level) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; -	u32 blc_pwm_ctl; - -	if (gma_power_begin(dev, false)) { -		blc_pwm_ctl = -			REG_READ(BLC_PWM_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK; -		REG_WRITE(BLC_PWM_CTL, -				(blc_pwm_ctl | -				(level << BACKLIGHT_DUTY_CYCLE_SHIFT))); -		gma_power_end(dev); -	} else { -		blc_pwm_ctl = dev_priv->saveBLC_PWM_CTL & -				~BACKLIGHT_DUTY_CYCLE_MASK; -		dev_priv->saveBLC_PWM_CTL = (blc_pwm_ctl | -					(level << BACKLIGHT_DUTY_CYCLE_SHIFT)); -	} -} - -/** - * Sets the power state for the panel. - */ -static void cdv_intel_lvds_set_power(struct drm_device *dev, -				 struct psb_intel_output *output, bool on) -{ -	u32 pp_status; - -	if (!gma_power_begin(dev, true)) -		return; - -	if (on) { -		REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) | -			  POWER_TARGET_ON); -		do { -			pp_status = REG_READ(PP_STATUS); -		} while ((pp_status & PP_ON) == 0); - -		cdv_intel_lvds_set_backlight(dev, -					 output-> -					 mode_dev->backlight_duty_cycle); -	} else { -		cdv_intel_lvds_set_backlight(dev, 0); - -		REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) & -			  ~POWER_TARGET_ON); -		do { -			pp_status = REG_READ(PP_STATUS); -		} while (pp_status & PP_ON); -	} -	gma_power_end(dev); -} - -static void cdv_intel_lvds_encoder_dpms(struct drm_encoder *encoder, int mode) -{ -	struct drm_device *dev = encoder->dev; -	struct psb_intel_output *output = enc_to_psb_intel_output(encoder); -	if (mode == DRM_MODE_DPMS_ON) -		cdv_intel_lvds_set_power(dev, output, true); -	else -		cdv_intel_lvds_set_power(dev, output, false); -	/* XXX: We never power down the LVDS pairs. */ -} - -static void cdv_intel_lvds_save(struct drm_connector *connector) -{ -} - -static void cdv_intel_lvds_restore(struct drm_connector *connector) -{ -} - -int cdv_intel_lvds_mode_valid(struct drm_connector *connector, -				 struct drm_display_mode *mode) -{ -	struct psb_intel_output *psb_intel_output = -				to_psb_intel_output(connector); -	struct drm_display_mode *fixed_mode = -	    psb_intel_output->mode_dev->panel_fixed_mode; - -	/* just in case */ -	if (mode->flags & DRM_MODE_FLAG_DBLSCAN) -		return MODE_NO_DBLESCAN; - -	/* just in case */ -	if (mode->flags & DRM_MODE_FLAG_INTERLACE) -		return MODE_NO_INTERLACE; - -	if (fixed_mode) { -		if (mode->hdisplay > fixed_mode->hdisplay) -			return MODE_PANEL; -		if (mode->vdisplay > fixed_mode->vdisplay) -			return MODE_PANEL; -	} -	return MODE_OK; -} - -bool cdv_intel_lvds_mode_fixup(struct drm_encoder *encoder, -				  struct drm_display_mode *mode, -				  struct drm_display_mode *adjusted_mode) -{ -	struct psb_intel_mode_device *mode_dev = -	    enc_to_psb_intel_output(encoder)->mode_dev; -	struct drm_device *dev = encoder->dev; -	struct drm_encoder *tmp_encoder; -	struct drm_display_mode *panel_fixed_mode = mode_dev->panel_fixed_mode; - -	/* Should never happen!! */ -	list_for_each_entry(tmp_encoder, &dev->mode_config.encoder_list, -			    head) { -		if (tmp_encoder != encoder -		    && tmp_encoder->crtc == encoder->crtc) { -			printk(KERN_ERR "Can't enable LVDS and another " -			       "encoder on the same pipe\n"); -			return false; -		} -	} - -	/* -	 * If we have timings from the BIOS for the panel, put them in -	 * to the adjusted mode.  The CRTC will be set up for this mode, -	 * with the panel scaling set up to source from the H/VDisplay -	 * of the original mode. -	 */ -	if (panel_fixed_mode != NULL) { -		adjusted_mode->hdisplay = panel_fixed_mode->hdisplay; -		adjusted_mode->hsync_start = panel_fixed_mode->hsync_start; -		adjusted_mode->hsync_end = panel_fixed_mode->hsync_end; -		adjusted_mode->htotal = panel_fixed_mode->htotal; -		adjusted_mode->vdisplay = panel_fixed_mode->vdisplay; -		adjusted_mode->vsync_start = panel_fixed_mode->vsync_start; -		adjusted_mode->vsync_end = panel_fixed_mode->vsync_end; -		adjusted_mode->vtotal = panel_fixed_mode->vtotal; -		adjusted_mode->clock = panel_fixed_mode->clock; -		drm_mode_set_crtcinfo(adjusted_mode, -				      CRTC_INTERLACE_HALVE_V); -	} - -	/* -	 * XXX: It would be nice to support lower refresh rates on the -	 * panels to reduce power consumption, and perhaps match the -	 * user's requested refresh rate. -	 */ - -	return true; -} - -static void cdv_intel_lvds_prepare(struct drm_encoder *encoder) -{ -	struct drm_device *dev = encoder->dev; -	struct psb_intel_output *output = enc_to_psb_intel_output(encoder); -	struct psb_intel_mode_device *mode_dev = output->mode_dev; - -	if (!gma_power_begin(dev, true)) -		return; - -	mode_dev->saveBLC_PWM_CTL = REG_READ(BLC_PWM_CTL); -	mode_dev->backlight_duty_cycle = (mode_dev->saveBLC_PWM_CTL & -					  BACKLIGHT_DUTY_CYCLE_MASK); - -	cdv_intel_lvds_set_power(dev, output, false); - -	gma_power_end(dev); -} - -static void cdv_intel_lvds_commit(struct drm_encoder *encoder) -{ -	struct drm_device *dev = encoder->dev; -	struct psb_intel_output *output = enc_to_psb_intel_output(encoder); -	struct psb_intel_mode_device *mode_dev = output->mode_dev; - -	if (mode_dev->backlight_duty_cycle == 0) -		mode_dev->backlight_duty_cycle = -		    cdv_intel_lvds_get_max_backlight(dev); - -	cdv_intel_lvds_set_power(dev, output, true); -} - -static void cdv_intel_lvds_mode_set(struct drm_encoder *encoder, -				struct drm_display_mode *mode, -				struct drm_display_mode *adjusted_mode) -{ -	struct drm_device *dev = encoder->dev; -	struct drm_psb_private *dev_priv = dev->dev_private; -	u32 pfit_control; - -	/* -	 * The LVDS pin pair will already have been turned on in the -	 * cdv_intel_crtc_mode_set since it has a large impact on the DPLL -	 * settings. -	 */ - -	/* -	 * Enable automatic panel scaling so that non-native modes fill the -	 * screen.  Should be enabled before the pipe is enabled, according to -	 * register description and PRM. -	 */ -	if (mode->hdisplay != adjusted_mode->hdisplay || -	    mode->vdisplay != adjusted_mode->vdisplay) -		pfit_control = (PFIT_ENABLE | VERT_AUTO_SCALE | -				HORIZ_AUTO_SCALE | VERT_INTERP_BILINEAR | -				HORIZ_INTERP_BILINEAR); -	else -		pfit_control = 0; - -	if (dev_priv->lvds_dither) -		pfit_control |= PANEL_8TO6_DITHER_ENABLE; - -	REG_WRITE(PFIT_CONTROL, pfit_control); -} - -/** - * Detect the LVDS connection. - * - * This always returns CONNECTOR_STATUS_CONNECTED. - * This connector should only have - * been set up if the LVDS was actually connected anyway. - */ -static enum drm_connector_status cdv_intel_lvds_detect( -				struct drm_connector *connector, bool force) -{ -	return connector_status_connected; -} - -/** - * Return the list of DDC modes if available, or the BIOS fixed mode otherwise. - */ -static int cdv_intel_lvds_get_modes(struct drm_connector *connector) -{ -	struct drm_device *dev = connector->dev; -	struct psb_intel_output *psb_intel_output = -					to_psb_intel_output(connector); -	struct psb_intel_mode_device *mode_dev = -					psb_intel_output->mode_dev; -	int ret; - -	ret = psb_intel_ddc_get_modes(psb_intel_output); - -	if (ret) -		return ret; - -	/* Didn't get an EDID, so -	 * Set wide sync ranges so we get all modes -	 * handed to valid_mode for checking -	 */ -	connector->display_info.min_vfreq = 0; -	connector->display_info.max_vfreq = 200; -	connector->display_info.min_hfreq = 0; -	connector->display_info.max_hfreq = 200; -	if (mode_dev->panel_fixed_mode != NULL) { -		struct drm_display_mode *mode = -		    drm_mode_duplicate(dev, mode_dev->panel_fixed_mode); -		drm_mode_probed_add(connector, mode); -		return 1; -	} - -	return 0; -} - -/** - * cdv_intel_lvds_destroy - unregister and free LVDS structures - * @connector: connector to free - * - * Unregister the DDC bus for this connector then free the driver private - * structure. - */ -void cdv_intel_lvds_destroy(struct drm_connector *connector) -{ -	struct psb_intel_output *psb_intel_output = -					to_psb_intel_output(connector); - -	if (psb_intel_output->ddc_bus) -		psb_intel_i2c_destroy(psb_intel_output->ddc_bus); -	drm_sysfs_connector_remove(connector); -	drm_connector_cleanup(connector); -	kfree(connector); -} - -int cdv_intel_lvds_set_property(struct drm_connector *connector, -				       struct drm_property *property, -				       uint64_t value) -{ -	struct drm_encoder *encoder = connector->encoder; - -	if (!strcmp(property->name, "scaling mode") && encoder) { -		struct psb_intel_crtc *crtc = -					to_psb_intel_crtc(encoder->crtc); -		uint64_t curValue; - -		if (!crtc) -			return -1; - -		switch (value) { -		case DRM_MODE_SCALE_FULLSCREEN: -			break; -		case DRM_MODE_SCALE_NO_SCALE: -			break; -		case DRM_MODE_SCALE_ASPECT: -			break; -		default: -			return -1; -		} - -		if (drm_connector_property_get_value(connector, -						     property, -						     &curValue)) -			return -1; - -		if (curValue == value) -			return 0; - -		if (drm_connector_property_set_value(connector, -							property, -							value)) -			return -1; - -		if (crtc->saved_mode.hdisplay != 0 && -		    crtc->saved_mode.vdisplay != 0) { -			if (!drm_crtc_helper_set_mode(encoder->crtc, -						      &crtc->saved_mode, -						      encoder->crtc->x, -						      encoder->crtc->y, -						      encoder->crtc->fb)) -				return -1; -		} -	} else if (!strcmp(property->name, "backlight") && encoder) { -		if (drm_connector_property_set_value(connector, -							property, -							value)) -			return -1; -		else { -#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE -			struct drm_psb_private *dev_priv = -						encoder->dev->dev_private; -			struct backlight_device *bd = -						dev_priv->backlight_device; -			bd->props.brightness = value; -			backlight_update_status(bd); -#endif -		} -	} else if (!strcmp(property->name, "DPMS") && encoder) { -		struct drm_encoder_helper_funcs *helpers = -					encoder->helper_private; -		helpers->dpms(encoder, value); -	} -	return 0; -} - -static const struct drm_encoder_helper_funcs -					cdv_intel_lvds_helper_funcs = { -	.dpms = cdv_intel_lvds_encoder_dpms, -	.mode_fixup = cdv_intel_lvds_mode_fixup, -	.prepare = cdv_intel_lvds_prepare, -	.mode_set = cdv_intel_lvds_mode_set, -	.commit = cdv_intel_lvds_commit, -}; - -static const struct drm_connector_helper_funcs -				cdv_intel_lvds_connector_helper_funcs = { -	.get_modes = cdv_intel_lvds_get_modes, -	.mode_valid = cdv_intel_lvds_mode_valid, -	.best_encoder = psb_intel_best_encoder, -}; - -static const struct drm_connector_funcs cdv_intel_lvds_connector_funcs = { -	.dpms = drm_helper_connector_dpms, -	.save = cdv_intel_lvds_save, -	.restore = cdv_intel_lvds_restore, -	.detect = cdv_intel_lvds_detect, -	.fill_modes = drm_helper_probe_single_connector_modes, -	.set_property = cdv_intel_lvds_set_property, -	.destroy = cdv_intel_lvds_destroy, -}; - - -static void cdv_intel_lvds_enc_destroy(struct drm_encoder *encoder) -{ -	drm_encoder_cleanup(encoder); -} - -const struct drm_encoder_funcs cdv_intel_lvds_enc_funcs = { -	.destroy = cdv_intel_lvds_enc_destroy, -}; - -/** - * cdv_intel_lvds_init - setup LVDS connectors on this device - * @dev: drm device - * - * Create the connector, register the LVDS DDC bus, and try to figure out what - * modes we can display on the LVDS panel (if present). - */ -void cdv_intel_lvds_init(struct drm_device *dev, -		     struct psb_intel_mode_device *mode_dev) -{ -	struct psb_intel_output *psb_intel_output; -	struct cdv_intel_lvds_priv *lvds_priv; -	struct drm_connector *connector; -	struct drm_encoder *encoder; -	struct drm_display_mode *scan; -	struct drm_crtc *crtc; -	struct drm_psb_private *dev_priv = dev->dev_private; -	u32 lvds; -	int pipe; - -	psb_intel_output = kzalloc(sizeof(struct psb_intel_output) + -			sizeof(struct cdv_intel_lvds_priv), GFP_KERNEL); -	if (!psb_intel_output) -		return; - -	lvds_priv = (struct cdv_intel_lvds_priv *)(psb_intel_output + 1); - -	psb_intel_output->dev_priv = lvds_priv; - -	psb_intel_output->mode_dev = mode_dev; -	connector = &psb_intel_output->base; -	encoder = &psb_intel_output->enc; - - -	drm_connector_init(dev, &psb_intel_output->base, -			   &cdv_intel_lvds_connector_funcs, -			   DRM_MODE_CONNECTOR_LVDS); - -	drm_encoder_init(dev, &psb_intel_output->enc, -			 &cdv_intel_lvds_enc_funcs, -			 DRM_MODE_ENCODER_LVDS); - - -	drm_mode_connector_attach_encoder(&psb_intel_output->base, -					  &psb_intel_output->enc); -	psb_intel_output->type = INTEL_OUTPUT_LVDS; - -	drm_encoder_helper_add(encoder, &cdv_intel_lvds_helper_funcs); -	drm_connector_helper_add(connector, -				 &cdv_intel_lvds_connector_helper_funcs); -	connector->display_info.subpixel_order = SubPixelHorizontalRGB; -	connector->interlace_allowed = false; -	connector->doublescan_allowed = false; - -	/*Attach connector properties*/ -	drm_connector_attach_property(connector, -				      dev->mode_config.scaling_mode_property, -				      DRM_MODE_SCALE_FULLSCREEN); -	drm_connector_attach_property(connector, -				      dev_priv->backlight_property, -				      BRIGHTNESS_MAX_LEVEL); - -	/** -	 * Set up I2C bus -	 * FIXME: distroy i2c_bus when exit -	 */ -	psb_intel_output->i2c_bus = psb_intel_i2c_create(dev, -							 GPIOB, -							 "LVDSBLC_B"); -	if (!psb_intel_output->i2c_bus) { -		dev_printk(KERN_ERR, -			&dev->pdev->dev, "I2C bus registration failed.\n"); -		goto failed_blc_i2c; -	} -	psb_intel_output->i2c_bus->slave_addr = 0x2C; -	dev_priv->lvds_i2c_bus =  psb_intel_output->i2c_bus; - -	/* -	 * LVDS discovery: -	 * 1) check for EDID on DDC -	 * 2) check for VBT data -	 * 3) check to see if LVDS is already on -	 *    if none of the above, no panel -	 * 4) make sure lid is open -	 *    if closed, act like it's not there for now -	 */ - -	/* Set up the DDC bus. */ -	psb_intel_output->ddc_bus = psb_intel_i2c_create(dev, -							 GPIOC, -							 "LVDSDDC_C"); -	if (!psb_intel_output->ddc_bus) { -		dev_printk(KERN_ERR, &dev->pdev->dev, -			   "DDC bus registration " "failed.\n"); -		goto failed_ddc; -	} - -	/* -	 * Attempt to get the fixed panel mode from DDC.  Assume that the -	 * preferred mode is the right one. -	 */ -	psb_intel_ddc_get_modes(psb_intel_output); -	list_for_each_entry(scan, &connector->probed_modes, head) { -		if (scan->type & DRM_MODE_TYPE_PREFERRED) { -			mode_dev->panel_fixed_mode = -			    drm_mode_duplicate(dev, scan); -			goto out;	/* FIXME: check for quirks */ -		} -	} - -	/* Failed to get EDID, what about VBT? do we need this?*/ -	if (dev_priv->lfp_lvds_vbt_mode) { -		mode_dev->panel_fixed_mode = -			drm_mode_duplicate(dev, dev_priv->lfp_lvds_vbt_mode); -		if (mode_dev->panel_fixed_mode) { -			mode_dev->panel_fixed_mode->type |= -				DRM_MODE_TYPE_PREFERRED; -			goto out;	/* FIXME: check for quirks */ -		} -	} -	/* -	 * If we didn't get EDID, try checking if the panel is already turned -	 * on.	If so, assume that whatever is currently programmed is the -	 * correct mode. -	 */ -	lvds = REG_READ(LVDS); -	pipe = (lvds & LVDS_PIPEB_SELECT) ? 1 : 0; -	crtc = psb_intel_get_crtc_from_pipe(dev, pipe); - -	if (crtc && (lvds & LVDS_PORT_EN)) { -		mode_dev->panel_fixed_mode = -		    cdv_intel_crtc_mode_get(dev, crtc); -		if (mode_dev->panel_fixed_mode) { -			mode_dev->panel_fixed_mode->type |= -			    DRM_MODE_TYPE_PREFERRED; -			goto out;	/* FIXME: check for quirks */ -		} -	} - -	/* If we still don't have a mode after all that, give up. */ -	if (!mode_dev->panel_fixed_mode) { -		DRM_DEBUG -			("Found no modes on the lvds, ignoring the LVDS\n"); -		goto failed_find; -	} - -out: -	drm_sysfs_connector_add(connector); -	return; - -failed_find: -	printk(KERN_ERR "Failed find\n"); -	if (psb_intel_output->ddc_bus) -		psb_intel_i2c_destroy(psb_intel_output->ddc_bus); -failed_ddc: -	printk(KERN_ERR "Failed DDC\n"); -	if (psb_intel_output->i2c_bus) -		psb_intel_i2c_destroy(psb_intel_output->i2c_bus); -failed_blc_i2c: -	printk(KERN_ERR "Failed BLC\n"); -	drm_encoder_cleanup(encoder); -	drm_connector_cleanup(connector); -	kfree(connector); -} diff --git a/drivers/staging/gma500/displays/hdmi.h b/drivers/staging/gma500/displays/hdmi.h deleted file mode 100644 index d58ba9bd010..00000000000 --- a/drivers/staging/gma500/displays/hdmi.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c)  2010 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Authors: - * Thomas Eaton <thomas.g.eaton@intel.com> - * Scott Rowe <scott.m.rowe@intel.com> - */ - -#ifndef HDMI_H -#define HDMI_H - -extern void hdmi_init(struct drm_device *dev); - -#endif diff --git a/drivers/staging/gma500/displays/pyr_cmd.h b/drivers/staging/gma500/displays/pyr_cmd.h deleted file mode 100644 index 84bae5c8c55..00000000000 --- a/drivers/staging/gma500/displays/pyr_cmd.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c)  2010 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicensen - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Authors: - * Thomas Eaton <thomas.g.eaton@intel.com> - * Scott Rowe <scott.m.rowe@intel.com> - */ - -#ifndef PYR_CMD_H -#define PYR_CMD_H - -extern void pyr_cmd_init(struct drm_device *dev, struct panel_funcs *p_funcs); - -#endif - diff --git a/drivers/staging/gma500/displays/pyr_vid.h b/drivers/staging/gma500/displays/pyr_vid.h deleted file mode 100644 index ce98860fa68..00000000000 --- a/drivers/staging/gma500/displays/pyr_vid.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c)  2010 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicensen - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Authors: - * Thomas Eaton <thomas.g.eaton@intel.com> - * Scott Rowe <scott.m.rowe@intel.com> -*/ - -#ifndef PYR_VID_H -#define PYR_VID_H - -extern void pyr_vid_init(struct drm_device *dev, struct panel_funcs *p_funcs); -extern struct drm_display_mode *pyr_vid_get_config_mode(struct drm_device* dev); - -#endif diff --git a/drivers/staging/gma500/displays/tmd_cmd.h b/drivers/staging/gma500/displays/tmd_cmd.h deleted file mode 100644 index 641e85eedec..00000000000 --- a/drivers/staging/gma500/displays/tmd_cmd.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c)  2010 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicensen - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Authors: - * Thomas Eaton <thomas.g.eaton@intel.com> - * Scott Rowe <scott.m.rowe@intel.com> - */ - -#ifndef TMD_CMD_H -#define TMD_CMD_H - -extern void tmd_cmd_init(struct drm_device *dev, struct panel_funcs *p_funcs); -extern struct drm_display_mode *tmd_cmd_get_config_mode(struct drm_device *dev); - -#endif diff --git a/drivers/staging/gma500/displays/tmd_vid.h b/drivers/staging/gma500/displays/tmd_vid.h deleted file mode 100644 index 7a5fa3b935e..00000000000 --- a/drivers/staging/gma500/displays/tmd_vid.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c)  2010 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicensen - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Authors: - * Thomas Eaton <thomas.g.eaton@intel.com> - * Scott Rowe <scott.m.rowe@intel.com> -*/ - -#ifndef TMD_VID_H -#define TMD_VID_H - -extern void tmd_vid_init(struct drm_device *dev, struct panel_funcs *p_funcs); -extern struct drm_display_mode *tmd_vid_get_config_mode(struct drm_device *dev); - -#endif diff --git a/drivers/staging/gma500/displays/tpo_cmd.h b/drivers/staging/gma500/displays/tpo_cmd.h deleted file mode 100644 index 610552730d7..00000000000 --- a/drivers/staging/gma500/displays/tpo_cmd.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c)  2010 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicensen - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Authors: - * Thomas Eaton <thomas.g.eaton@intel.com> - * Scott Rowe <scott.m.rowe@intel.com> -*/ - -#ifndef TPO_CMD_H -#define TPO_CMD_H - -extern void tpo_cmd_init(struct drm_device *dev, struct panel_funcs *p_funcs); -/* extern struct drm_display_mode * */ -/* tpo_cmd_get_config_mode(struct drm_device *dev); */ - -#endif diff --git a/drivers/staging/gma500/displays/tpo_vid.h b/drivers/staging/gma500/displays/tpo_vid.h deleted file mode 100644 index c24f05722de..00000000000 --- a/drivers/staging/gma500/displays/tpo_vid.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c)  2010 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicensen - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Authors: - * Thomas Eaton <thomas.g.eaton@intel.com> - * Scott Rowe <scott.m.rowe@intel.com> - */ - -#ifndef TPO_VID_H -#define TPO_VID_H - -extern void tpo_vid_init(struct drm_device *dev, struct panel_funcs *p_funcs); - -#endif diff --git a/drivers/staging/gma500/framebuffer.c b/drivers/staging/gma500/framebuffer.c deleted file mode 100644 index b00761cba14..00000000000 --- a/drivers/staging/gma500/framebuffer.c +++ /dev/null @@ -1,856 +0,0 @@ -/************************************************************************** - * Copyright (c) 2007-2011, Intel Corporation. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - **************************************************************************/ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/string.h> -#include <linux/mm.h> -#include <linux/tty.h> -#include <linux/slab.h> -#include <linux/delay.h> -#include <linux/fb.h> -#include <linux/init.h> -#include <linux/console.h> - -#include <drm/drmP.h> -#include <drm/drm.h> -#include <drm/drm_crtc.h> -#include <drm/drm_fb_helper.h> - -#include "psb_drv.h" -#include "psb_intel_reg.h" -#include "psb_intel_drv.h" -#include "framebuffer.h" -#include "gtt.h" - -#include "mdfld_output.h" - -static void psb_user_framebuffer_destroy(struct drm_framebuffer *fb); -static int psb_user_framebuffer_create_handle(struct drm_framebuffer *fb, -					      struct drm_file *file_priv, -					      unsigned int *handle); - -static const struct drm_framebuffer_funcs psb_fb_funcs = { -	.destroy = psb_user_framebuffer_destroy, -	.create_handle = psb_user_framebuffer_create_handle, -}; - -#define CMAP_TOHW(_val, _width) ((((_val) << (_width)) + 0x7FFF - (_val)) >> 16) - -static int psbfb_setcolreg(unsigned regno, unsigned red, unsigned green, -			   unsigned blue, unsigned transp, -			   struct fb_info *info) -{ -	struct psb_fbdev *fbdev = info->par; -	struct drm_framebuffer *fb = fbdev->psb_fb_helper.fb; -	uint32_t v; - -	if (!fb) -		return -ENOMEM; - -	if (regno > 255) -		return 1; - -	red = CMAP_TOHW(red, info->var.red.length); -	blue = CMAP_TOHW(blue, info->var.blue.length); -	green = CMAP_TOHW(green, info->var.green.length); -	transp = CMAP_TOHW(transp, info->var.transp.length); - -	v = (red << info->var.red.offset) | -	    (green << info->var.green.offset) | -	    (blue << info->var.blue.offset) | -	    (transp << info->var.transp.offset); - -	if (regno < 16) { -		switch (fb->bits_per_pixel) { -		case 16: -			((uint32_t *) info->pseudo_palette)[regno] = v; -			break; -		case 24: -		case 32: -			((uint32_t *) info->pseudo_palette)[regno] = v; -			break; -		} -	} - -	return 0; -} - -static int psbfb_pan(struct fb_var_screeninfo *var, struct fb_info *info) -{ -	struct psb_fbdev *fbdev = info->par; -	struct psb_framebuffer *psbfb = &fbdev->pfb; -	struct drm_device *dev = psbfb->base.dev; - -	/* -	 *	We have to poke our nose in here. The core fb code assumes -	 *	panning is part of the hardware that can be invoked before -	 *	the actual fb is mapped. In our case that isn't quite true. -	 */ -	if (psbfb->gtt->npage) -        	psb_gtt_roll(dev, psbfb->gtt, var->yoffset); -	return 0; -} - -void psbfb_suspend(struct drm_device *dev) -{ -	struct drm_framebuffer *fb = 0; -	struct psb_framebuffer *psbfb = to_psb_fb(fb); - -	console_lock(); -	mutex_lock(&dev->mode_config.mutex); -	list_for_each_entry(fb, &dev->mode_config.fb_list, head) { -		struct fb_info *info = psbfb->fbdev; -		fb_set_suspend(info, 1); -		drm_fb_helper_blank(FB_BLANK_POWERDOWN, info); -	} -	mutex_unlock(&dev->mode_config.mutex); -	console_unlock(); -} - -void psbfb_resume(struct drm_device *dev) -{ -	struct drm_framebuffer *fb = 0; -	struct psb_framebuffer *psbfb = to_psb_fb(fb); - -	console_lock(); -	mutex_lock(&dev->mode_config.mutex); -	list_for_each_entry(fb, &dev->mode_config.fb_list, head) { -		struct fb_info *info = psbfb->fbdev; -		fb_set_suspend(info, 0); -		drm_fb_helper_blank(FB_BLANK_UNBLANK, info); -	} -	mutex_unlock(&dev->mode_config.mutex); -	console_unlock(); -	drm_helper_disable_unused_functions(dev); -} - -static int psbfb_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) -{ -	struct psb_framebuffer *psbfb = vma->vm_private_data; -	struct drm_device *dev = psbfb->base.dev; -	struct drm_psb_private *dev_priv = dev->dev_private; -	int page_num; -	int i; -	unsigned long address; -	int ret; -	unsigned long pfn; -	/* FIXME: assumes fb at stolen base which may not be true */ -	unsigned long phys_addr = (unsigned long)dev_priv->stolen_base; - -	page_num = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; -	address = (unsigned long)vmf->virtual_address; - -	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); - -	for (i = 0; i < page_num; i++) { -		pfn = (phys_addr >> PAGE_SHIFT); - -		ret = vm_insert_mixed(vma, address, pfn); -		if (unlikely((ret == -EBUSY) || (ret != 0 && i > 0))) -			break; -		else if (unlikely(ret != 0)) { -			ret = (ret == -ENOMEM) ? VM_FAULT_OOM : VM_FAULT_SIGBUS; -			return ret; -		} -		address += PAGE_SIZE; -		phys_addr += PAGE_SIZE; -	} -	return VM_FAULT_NOPAGE; -} - -static void psbfb_vm_open(struct vm_area_struct *vma) -{ -} - -static void psbfb_vm_close(struct vm_area_struct *vma) -{ -} - -static struct vm_operations_struct psbfb_vm_ops = { -	.fault	= psbfb_vm_fault, -	.open	= psbfb_vm_open, -	.close	= psbfb_vm_close -}; - -static int psbfb_mmap(struct fb_info *info, struct vm_area_struct *vma) -{ -	struct psb_fbdev *fbdev = info->par; -	struct psb_framebuffer *psbfb = &fbdev->pfb; - -	if (vma->vm_pgoff != 0) -		return -EINVAL; -	if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) -		return -EINVAL; - -	if (!psbfb->addr_space) -		psbfb->addr_space = vma->vm_file->f_mapping; -	/* -	 * If this is a GEM object then info->screen_base is the virtual -	 * kernel remapping of the object. FIXME: Review if this is -	 * suitable for our mmap work -	 */ -	vma->vm_ops = &psbfb_vm_ops; -	vma->vm_private_data = (void *)psbfb; -	vma->vm_flags |= VM_RESERVED | VM_IO | -					VM_MIXEDMAP | VM_DONTEXPAND; -	return 0; -} - -static int psbfb_ioctl(struct fb_info *info, unsigned int cmd, -						unsigned long arg) -{ -	return -ENOTTY; -} - -static struct fb_ops psbfb_ops = { -	.owner = THIS_MODULE, -	.fb_check_var = drm_fb_helper_check_var, -	.fb_set_par = drm_fb_helper_set_par, -	.fb_blank = drm_fb_helper_blank, -	.fb_setcolreg = psbfb_setcolreg, -	.fb_fillrect = cfb_fillrect, -	.fb_copyarea = psbfb_copyarea, -	.fb_imageblit = cfb_imageblit, -	.fb_mmap = psbfb_mmap, -	.fb_sync = psbfb_sync, -	.fb_ioctl = psbfb_ioctl, -}; - -static struct fb_ops psbfb_roll_ops = { -	.owner = THIS_MODULE, -	.fb_check_var = drm_fb_helper_check_var, -	.fb_set_par = drm_fb_helper_set_par, -	.fb_blank = drm_fb_helper_blank, -	.fb_setcolreg = psbfb_setcolreg, -	.fb_fillrect = cfb_fillrect, -	.fb_copyarea = cfb_copyarea, -	.fb_imageblit = cfb_imageblit, -	.fb_pan_display = psbfb_pan, -	.fb_mmap = psbfb_mmap, -	.fb_sync = psbfb_sync, -	.fb_ioctl = psbfb_ioctl, -}; - -static struct fb_ops psbfb_unaccel_ops = { -	.owner = THIS_MODULE, -	.fb_check_var = drm_fb_helper_check_var, -	.fb_set_par = drm_fb_helper_set_par, -	.fb_blank = drm_fb_helper_blank, -	.fb_setcolreg = psbfb_setcolreg, -	.fb_fillrect = cfb_fillrect, -	.fb_copyarea = cfb_copyarea, -	.fb_imageblit = cfb_imageblit, -	.fb_mmap = psbfb_mmap, -	.fb_ioctl = psbfb_ioctl, -}; - -/** - *	psb_framebuffer_init	-	initialize a framebuffer - *	@dev: our DRM device - *	@fb: framebuffer to set up - *	@mode_cmd: mode description - *	@gt: backing object - * - *	Configure and fill in the boilerplate for our frame buffer. Return - *	0 on success or an error code if we fail. - */ -static int psb_framebuffer_init(struct drm_device *dev, -					struct psb_framebuffer *fb, -					struct drm_mode_fb_cmd2 *mode_cmd, -					struct gtt_range *gt) -{ -	u32 bpp, depth; -	int ret; - -	drm_fb_get_bpp_depth(mode_cmd->pixel_format, &depth, &bpp); - -	if (mode_cmd->pitches[0] & 63) -		return -EINVAL; -	switch (bpp) { -	case 8: -	case 16: -	case 24: -	case 32: -		break; -	default: -		return -EINVAL; -	} -	ret = drm_framebuffer_init(dev, &fb->base, &psb_fb_funcs); -	if (ret) { -		dev_err(dev->dev, "framebuffer init failed: %d\n", ret); -		return ret; -	} -	drm_helper_mode_fill_fb_struct(&fb->base, mode_cmd); -	fb->gtt = gt; -	return 0; -} - -/** - *	psb_framebuffer_create	-	create a framebuffer backed by gt - *	@dev: our DRM device - *	@mode_cmd: the description of the requested mode - *	@gt: the backing object - * - *	Create a framebuffer object backed by the gt, and fill in the - *	boilerplate required - * - *	TODO: review object references - */ - -static struct drm_framebuffer *psb_framebuffer_create -			(struct drm_device *dev, -			 struct drm_mode_fb_cmd2 *mode_cmd, -			 struct gtt_range *gt) -{ -	struct psb_framebuffer *fb; -	int ret; - -	fb = kzalloc(sizeof(*fb), GFP_KERNEL); -	if (!fb) -		return ERR_PTR(-ENOMEM); - -	ret = psb_framebuffer_init(dev, fb, mode_cmd, gt); -	if (ret) { -		kfree(fb); -		return ERR_PTR(ret); -	} -	return &fb->base; -} - -/** - *	psbfb_alloc		-	allocate frame buffer memory - *	@dev: the DRM device - *	@aligned_size: space needed - *	@force: fall back to GEM buffers if need be - * - *	Allocate the frame buffer. In the usual case we get a GTT range that - *	is stolen memory backed and life is simple. If there isn't sufficient - *	stolen memory or the system has no stolen memory we allocate a range - *	and back it with a GEM object. - * - *	In this case the GEM object has no handle. - */ -static struct gtt_range *psbfb_alloc(struct drm_device *dev, -						int aligned_size, int force) -{ -	struct gtt_range *backing; -	/* Begin by trying to use stolen memory backing */ -	backing = psb_gtt_alloc_range(dev, aligned_size, "fb", 1); -	if (backing) { -		if (drm_gem_private_object_init(dev, -					&backing->gem, aligned_size) == 0) -			return backing; -		psb_gtt_free_range(dev, backing); -	} -	if (!force) -		return NULL; - -	/* Next try using GEM host memory */ -	backing = psb_gtt_alloc_range(dev, aligned_size, "fb(gem)", 0); -	if (backing == NULL) -		return NULL; - -	/* Now back it with an object */ -	if (drm_gem_object_init(dev, &backing->gem, aligned_size) != 0) { -		psb_gtt_free_range(dev, backing); -		return NULL; -	} -	return backing; -} - -/** - *	psbfb_create		-	create a framebuffer - *	@fbdev: the framebuffer device - *	@sizes: specification of the layout - * - *	Create a framebuffer to the specifications provided - */ -static int psbfb_create(struct psb_fbdev *fbdev, -				struct drm_fb_helper_surface_size *sizes) -{ -	struct drm_device *dev = fbdev->psb_fb_helper.dev; -	struct drm_psb_private *dev_priv = dev->dev_private; -	struct fb_info *info; -	struct drm_framebuffer *fb; -	struct psb_framebuffer *psbfb = &fbdev->pfb; -	struct drm_mode_fb_cmd2 mode_cmd; -	struct device *device = &dev->pdev->dev; -	int size; -	int ret; -	struct gtt_range *backing; -	int gtt_roll = 1; -	u32 bpp, depth; - -	mode_cmd.width = sizes->surface_width; -	mode_cmd.height = sizes->surface_height; -	bpp = sizes->surface_bpp; - -	/* No 24bit packed */ -	if (bpp == 24) -		bpp = 32; - -	/* Acceleration via the GTT requires pitch to be 4096 byte aligned  -	   (ie 1024 or 2048 pixels in normal use) */ -	mode_cmd.pitches[0] =  ALIGN(mode_cmd.width * ((bpp + 7) / 8), 4096); -	depth = sizes->surface_depth; - -	size = mode_cmd.pitches[0] * mode_cmd.height; -	size = ALIGN(size, PAGE_SIZE); - -	/* Allocate the framebuffer in the GTT with stolen page backing */ -	backing = psbfb_alloc(dev, size, 0); -	if (backing == NULL) { -		/* -		 *	We couldn't get the space we wanted, fall back to the -		 *	display engine requirement instead.  The HW requires -		 *	the pitch to be 64 byte aligned -		 */ - -		gtt_roll = 0;	/* Don't use GTT accelerated scrolling */ - -		mode_cmd.pitches[0] =  ALIGN(mode_cmd.width * ((bpp + 7) / 8), 64); -		depth = sizes->surface_depth; - -		size = mode_cmd.pitches[0] * mode_cmd.height; -		size = ALIGN(size, PAGE_SIZE); - -		/* Allocate the framebuffer in the GTT with stolen page -		   backing when there is room */ -		backing = psbfb_alloc(dev, size, 1); -		if (backing == NULL) -			return -ENOMEM; -	} - -	mutex_lock(&dev->struct_mutex); - -	info = framebuffer_alloc(0, device); -	if (!info) { -		ret = -ENOMEM; -		goto out_err1; -	} -	info->par = fbdev; - -	mode_cmd.pixel_format = drm_mode_legacy_fb_format(bpp, depth); - -	ret = psb_framebuffer_init(dev, psbfb, &mode_cmd, backing); -	if (ret) -		goto out_unref; - -	fb = &psbfb->base; -	psbfb->fbdev = info; - -	fbdev->psb_fb_helper.fb = fb; -	fbdev->psb_fb_helper.fbdev = info; - -	strcpy(info->fix.id, "psbfb"); - -	info->flags = FBINFO_DEFAULT; -	if (gtt_roll) {	/* GTT rolling seems best */ -		info->fbops = &psbfb_roll_ops; -		info->flags |= FBINFO_HWACCEL_YPAN; -        } -	else if (dev_priv->ops->accel_2d)	/* 2D engine */ -		info->fbops = &psbfb_ops; -	else	/* Software */ -		info->fbops = &psbfb_unaccel_ops; - -	ret = fb_alloc_cmap(&info->cmap, 256, 0); -	if (ret) { -		ret = -ENOMEM; -		goto out_unref; -	} - -	info->fix.smem_start = dev->mode_config.fb_base; -	info->fix.smem_len = size; -	info->fix.ywrapstep = gtt_roll; -	info->fix.ypanstep = gtt_roll; - -	if (backing->stolen) { -		/* Accessed stolen memory directly */ -		info->screen_base = (char *)dev_priv->vram_addr + -							backing->offset; -	} else { -		/* Pin the pages into the GTT and create a mapping to them */ -		psb_gtt_pin(backing); -		info->screen_base = vm_map_ram(backing->pages, backing->npage, -				-1, PAGE_KERNEL); -		if (info->screen_base == NULL) { -			psb_gtt_unpin(backing); -			ret = -ENOMEM; -			goto out_unref; -		} -		psbfb->vm_map = 1; -	} -	info->screen_size = size; - -	if (dev_priv->gtt.stolen_size) { -		info->apertures = alloc_apertures(1); -		if (!info->apertures) { -			ret = -ENOMEM; -			goto out_unref; -		} -		info->apertures->ranges[0].base = dev->mode_config.fb_base; -		info->apertures->ranges[0].size = dev_priv->gtt.stolen_size; -	} - -	drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth); -	drm_fb_helper_fill_var(info, &fbdev->psb_fb_helper, -				sizes->fb_width, sizes->fb_height); - -	info->fix.mmio_start = pci_resource_start(dev->pdev, 0); -	info->fix.mmio_len = pci_resource_len(dev->pdev, 0); - -	info->pixmap.size = 64 * 1024; -	info->pixmap.buf_align = 8; -	info->pixmap.access_align = 32; -	info->pixmap.flags = FB_PIXMAP_SYSTEM; -	info->pixmap.scan_align = 1; - -	dev_info(dev->dev, "allocated %dx%d fb\n", -					psbfb->base.width, psbfb->base.height); - -	mutex_unlock(&dev->struct_mutex); -	return 0; -out_unref: -	if (backing->stolen) -		psb_gtt_free_range(dev, backing); -	else { -		if (psbfb->vm_map) -			vm_unmap_ram(info->screen_base, backing->npage); -		drm_gem_object_unreference(&backing->gem); -	} -out_err1: -	mutex_unlock(&dev->struct_mutex); -	psb_gtt_free_range(dev, backing); -	return ret; -} - -/** - *	psb_user_framebuffer_create	-	create framebuffer - *	@dev: our DRM device - *	@filp: client file - *	@cmd: mode request - * - *	Create a new framebuffer backed by a userspace GEM object - */ -static struct drm_framebuffer *psb_user_framebuffer_create -			(struct drm_device *dev, struct drm_file *filp, -			 struct drm_mode_fb_cmd2 *cmd) -{ -	struct gtt_range *r; -	struct drm_gem_object *obj; - -	/* -	 *	Find the GEM object and thus the gtt range object that is -	 *	to back this space -	 */ -	obj = drm_gem_object_lookup(dev, filp, cmd->handles[0]); -	if (obj == NULL) -		return ERR_PTR(-ENOENT); - -	/* Let the core code do all the work */ -	r = container_of(obj, struct gtt_range, gem); -	return psb_framebuffer_create(dev, cmd, r); -} - -static void psbfb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, -							u16 blue, int regno) -{ -} - -static void psbfb_gamma_get(struct drm_crtc *crtc, u16 *red, -					u16 *green, u16 *blue, int regno) -{ -} - -static int psbfb_probe(struct drm_fb_helper *helper, -				struct drm_fb_helper_surface_size *sizes) -{ -	struct psb_fbdev *psb_fbdev = (struct psb_fbdev *)helper; -	int new_fb = 0; -	int ret; - -	if (!helper->fb) { -		ret = psbfb_create(psb_fbdev, sizes); -		if (ret) -			return ret; -		new_fb = 1; -	} -	return new_fb; -} - -struct drm_fb_helper_funcs psb_fb_helper_funcs = { -	.gamma_set = psbfb_gamma_set, -	.gamma_get = psbfb_gamma_get, -	.fb_probe = psbfb_probe, -}; - -int psb_fbdev_destroy(struct drm_device *dev, struct psb_fbdev *fbdev) -{ -	struct fb_info *info; -	struct psb_framebuffer *psbfb = &fbdev->pfb; - -	if (fbdev->psb_fb_helper.fbdev) { -		info = fbdev->psb_fb_helper.fbdev; - -		/* If this is our base framebuffer then kill any virtual map -		   for the framebuffer layer and unpin it */ -		if (psbfb->vm_map) { -			vm_unmap_ram(info->screen_base, psbfb->gtt->npage); -			psb_gtt_unpin(psbfb->gtt); -		} -		unregister_framebuffer(info); -		if (info->cmap.len) -			fb_dealloc_cmap(&info->cmap); -		framebuffer_release(info); -	} -	drm_fb_helper_fini(&fbdev->psb_fb_helper); -	drm_framebuffer_cleanup(&psbfb->base); - -	if (psbfb->gtt) -		drm_gem_object_unreference(&psbfb->gtt->gem); -	return 0; -} - -int psb_fbdev_init(struct drm_device *dev) -{ -	struct psb_fbdev *fbdev; -	struct drm_psb_private *dev_priv = dev->dev_private; - -	fbdev = kzalloc(sizeof(struct psb_fbdev), GFP_KERNEL); -	if (!fbdev) { -		dev_err(dev->dev, "no memory\n"); -		return -ENOMEM; -	} - -	dev_priv->fbdev = fbdev; -	fbdev->psb_fb_helper.funcs = &psb_fb_helper_funcs; - -	drm_fb_helper_init(dev, &fbdev->psb_fb_helper, dev_priv->ops->crtcs, -							INTELFB_CONN_LIMIT); - -	drm_fb_helper_single_add_all_connectors(&fbdev->psb_fb_helper); -	drm_fb_helper_initial_config(&fbdev->psb_fb_helper, 32); -	return 0; -} - -void psb_fbdev_fini(struct drm_device *dev) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; - -	if (!dev_priv->fbdev) -		return; - -	psb_fbdev_destroy(dev, dev_priv->fbdev); -	kfree(dev_priv->fbdev); -	dev_priv->fbdev = NULL; -} - -static void psbfb_output_poll_changed(struct drm_device *dev) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; -	struct psb_fbdev *fbdev = (struct psb_fbdev *)dev_priv->fbdev; -	drm_fb_helper_hotplug_event(&fbdev->psb_fb_helper); -} - -/** - *	psb_user_framebuffer_create_handle - add hamdle to a framebuffer - *	@fb: framebuffer - *	@file_priv: our DRM file - *	@handle: returned handle - * - *	Our framebuffer object is a GTT range which also contains a GEM - *	object. We need to turn it into a handle for userspace. GEM will do - *	the work for us - */ -static int psb_user_framebuffer_create_handle(struct drm_framebuffer *fb, -					      struct drm_file *file_priv, -					      unsigned int *handle) -{ -	struct psb_framebuffer *psbfb = to_psb_fb(fb); -	struct gtt_range *r = psbfb->gtt; -	return drm_gem_handle_create(file_priv, &r->gem, handle); -} - -/** - *	psb_user_framebuffer_destroy	-	destruct user created fb - *	@fb: framebuffer - * - *	User framebuffers are backed by GEM objects so all we have to do is - *	clean up a bit and drop the reference, GEM will handle the fallout - */ -static void psb_user_framebuffer_destroy(struct drm_framebuffer *fb) -{ -	struct psb_framebuffer *psbfb = to_psb_fb(fb); -	struct gtt_range *r = psbfb->gtt; -	struct drm_device *dev = fb->dev; -	struct drm_psb_private *dev_priv = dev->dev_private; -	struct psb_fbdev *fbdev = dev_priv->fbdev; -	struct drm_crtc *crtc; -	int reset = 0; - -	/* Should never get stolen memory for a user fb */ -	WARN_ON(r->stolen); - -	/* Check if we are erroneously live */ -	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) -		if (crtc->fb == fb) -			reset = 1; - -	if (reset) -		/* -		 * Now force a sane response before we permit the DRM CRTC -		 * layer to do stupid things like blank the display. Instead -		 * we reset this framebuffer as if the user had forced a reset. -		 * We must do this before the cleanup so that the DRM layer -		 * doesn't get a chance to stick its oar in where it isn't -		 * wanted. -		 */ -		drm_fb_helper_restore_fbdev_mode(&fbdev->psb_fb_helper); - -	/* Let DRM do its clean up */ -	drm_framebuffer_cleanup(fb); -	/*  We are no longer using the resource in GEM */ -	drm_gem_object_unreference_unlocked(&r->gem); -	kfree(fb); -} - -static const struct drm_mode_config_funcs psb_mode_funcs = { -	.fb_create = psb_user_framebuffer_create, -	.output_poll_changed = psbfb_output_poll_changed, -}; - -static int psb_create_backlight_property(struct drm_device *dev) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; -	struct drm_property *backlight; - -	if (dev_priv->backlight_property) -		return 0; - -	backlight = drm_property_create(dev, DRM_MODE_PROP_RANGE, -							"backlight", 2); -	backlight->values[0] = 0; -	backlight->values[1] = 100; - -	dev_priv->backlight_property = backlight; - -	return 0; -} - -static void psb_setup_outputs(struct drm_device *dev) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; -	struct drm_connector *connector; - -	drm_mode_create_scaling_mode_property(dev); -	psb_create_backlight_property(dev); - -	dev_priv->ops->output_init(dev); - -	list_for_each_entry(connector, &dev->mode_config.connector_list, -			    head) { -		struct psb_intel_output *psb_intel_output = -		    to_psb_intel_output(connector); -		struct drm_encoder *encoder = &psb_intel_output->enc; -		int crtc_mask = 0, clone_mask = 0; - -		/* valid crtcs */ -		switch (psb_intel_output->type) { -		case INTEL_OUTPUT_ANALOG: -			crtc_mask = (1 << 0); -			clone_mask = (1 << INTEL_OUTPUT_ANALOG); -			break; -		case INTEL_OUTPUT_SDVO: -			crtc_mask = ((1 << 0) | (1 << 1)); -			clone_mask = (1 << INTEL_OUTPUT_SDVO); -			break; -		case INTEL_OUTPUT_LVDS: -			if (IS_MRST(dev)) -				crtc_mask = (1 << 0); -			else -				crtc_mask = (1 << 1); -			clone_mask = (1 << INTEL_OUTPUT_LVDS); -			break; -		case INTEL_OUTPUT_MIPI: -			crtc_mask = (1 << 0); -			clone_mask = (1 << INTEL_OUTPUT_MIPI); -			break; -		case INTEL_OUTPUT_MIPI2: -			crtc_mask = (1 << 2); -			clone_mask = (1 << INTEL_OUTPUT_MIPI2); -			break; -		case INTEL_OUTPUT_HDMI: -		        /* HDMI on crtc 1 for SoC devices and crtc 0 for -                           Cedarview. HDMI on Poulsbo is only via external -			   logic */ -			if (IS_MFLD(dev) || IS_MRST(dev)) -				crtc_mask = (1 << 1); -			else -				crtc_mask = (1 << 0);	/* Cedarview */ -			clone_mask = (1 << INTEL_OUTPUT_HDMI); -			break; -		} -		encoder->possible_crtcs = crtc_mask; -		encoder->possible_clones = -		    psb_intel_connector_clones(dev, clone_mask); -	} -} - -void psb_modeset_init(struct drm_device *dev) -{ -	struct drm_psb_private *dev_priv = -	    (struct drm_psb_private *) dev->dev_private; -	struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev; -	int i; - -	drm_mode_config_init(dev); - -	dev->mode_config.min_width = 0; -	dev->mode_config.min_height = 0; - -	dev->mode_config.funcs = (void *) &psb_mode_funcs; - -	/* set memory base */ -	/* MRST and PSB should use BAR 2*/ -	pci_read_config_dword(dev->pdev, PSB_BSM, (u32 *) -					&(dev->mode_config.fb_base)); - -	/* num pipes is 2 for PSB but 1 for Mrst */ -	for (i = 0; i < dev_priv->num_pipe; i++) -		psb_intel_crtc_init(dev, i, mode_dev); - -	dev->mode_config.max_width = 2048; -	dev->mode_config.max_height = 2048; - -	psb_setup_outputs(dev); -} - -void psb_modeset_cleanup(struct drm_device *dev) -{ -	mutex_lock(&dev->struct_mutex); - -	drm_kms_helper_poll_fini(dev); -	psb_fbdev_fini(dev); -	drm_mode_config_cleanup(dev); - -	mutex_unlock(&dev->struct_mutex); -} diff --git a/drivers/staging/gma500/framebuffer.h b/drivers/staging/gma500/framebuffer.h deleted file mode 100644 index d1b2289447f..00000000000 --- a/drivers/staging/gma500/framebuffer.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2008-2011, Intel Corporation - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - * Authors: - *      Eric Anholt <eric@anholt.net> - * - */ - -#ifndef _FRAMEBUFFER_H_ -#define _FRAMEBUFFER_H_ - -#include <drm/drmP.h> -#include <drm/drm_fb_helper.h> - -#include "psb_drv.h" - -struct psb_framebuffer { -	struct drm_framebuffer base; -	struct address_space *addr_space; -	struct fb_info *fbdev; -	struct gtt_range *gtt; -	bool vm_map;		/* True if we must undo a vm_map_ram */ -}; - -struct psb_fbdev { -	struct drm_fb_helper psb_fb_helper; -	struct psb_framebuffer pfb; -}; - -#define to_psb_fb(x) container_of(x, struct psb_framebuffer, base) - -extern int psb_intel_connector_clones(struct drm_device *dev, int type_mask); - -#endif - diff --git a/drivers/staging/gma500/gem.c b/drivers/staging/gma500/gem.c deleted file mode 100644 index f6433c037d2..00000000000 --- a/drivers/staging/gma500/gem.c +++ /dev/null @@ -1,292 +0,0 @@ -/* - *  psb GEM interface - * - * Copyright (c) 2011, Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - * Authors: Alan Cox - * - * TODO: - *	-	we need to work out if the MMU is relevant (eg for - *		accelerated operations on a GEM object) - */ - -#include <drm/drmP.h> -#include <drm/drm.h> -#include "psb_drm.h" -#include "psb_drv.h" - -int psb_gem_init_object(struct drm_gem_object *obj) -{ -	return -EINVAL; -} - -void psb_gem_free_object(struct drm_gem_object *obj) -{ -	struct gtt_range *gtt = container_of(obj, struct gtt_range, gem); -	drm_gem_object_release_wrap(obj); -	/* This must occur last as it frees up the memory of the GEM object */ -	psb_gtt_free_range(obj->dev, gtt); -} - -int psb_gem_get_aperture(struct drm_device *dev, void *data, -				struct drm_file *file) -{ -	return -EINVAL; -} - -/** - *	psb_gem_dumb_map_gtt	-	buffer mapping for dumb interface - *	@file: our drm client file - *	@dev: drm device - *	@handle: GEM handle to the object (from dumb_create) - * - *	Do the necessary setup to allow the mapping of the frame buffer - *	into user memory. We don't have to do much here at the moment. - */ -int psb_gem_dumb_map_gtt(struct drm_file *file, struct drm_device *dev, -			 uint32_t handle, uint64_t *offset) -{ -	int ret = 0; -	struct drm_gem_object *obj; - -	if (!(dev->driver->driver_features & DRIVER_GEM)) -		return -ENODEV; - -	mutex_lock(&dev->struct_mutex); - -	/* GEM does all our handle to object mapping */ -	obj = drm_gem_object_lookup(dev, file, handle); -	if (obj == NULL) { -		ret = -ENOENT; -		goto unlock; -	} -	/* What validation is needed here ? */ - -	/* Make it mmapable */ -	if (!obj->map_list.map) { -		ret = gem_create_mmap_offset(obj); -		if (ret) -			goto out; -	} -	/* GEM should really work out the hash offsets for us */ -	*offset = (u64)obj->map_list.hash.key << PAGE_SHIFT; -out: -	drm_gem_object_unreference(obj); -unlock: -	mutex_unlock(&dev->struct_mutex); -	return ret; -} - -/** - *	psb_gem_create		-	create a mappable object - *	@file: the DRM file of the client - *	@dev: our device - *	@size: the size requested - *	@handlep: returned handle (opaque number) - * - *	Create a GEM object, fill in the boilerplate and attach a handle to - *	it so that userspace can speak about it. This does the core work - *	for the various methods that do/will create GEM objects for things - */ -static int psb_gem_create(struct drm_file *file, -	struct drm_device *dev, uint64_t size, uint32_t *handlep) -{ -	struct gtt_range *r; -	int ret; -	u32 handle; - -	size = roundup(size, PAGE_SIZE); - -	/* Allocate our object - for now a direct gtt range which is not -	   stolen memory backed */ -	r = psb_gtt_alloc_range(dev, size, "gem", 0); -	if (r == NULL) { -		dev_err(dev->dev, "no memory for %lld byte GEM object\n", size); -		return -ENOSPC; -	} -	/* Initialize the extra goodies GEM needs to do all the hard work */ -	if (drm_gem_object_init(dev, &r->gem, size) != 0) { -		psb_gtt_free_range(dev, r); -		/* GEM doesn't give an error code so use -ENOMEM */ -		dev_err(dev->dev, "GEM init failed for %lld\n", size); -		return -ENOMEM; -	} -	/* Give the object a handle so we can carry it more easily */ -	ret = drm_gem_handle_create(file, &r->gem, &handle); -	if (ret) { -		dev_err(dev->dev, "GEM handle failed for %p, %lld\n", -							&r->gem, size); -		drm_gem_object_release(&r->gem); -		psb_gtt_free_range(dev, r); -		return ret; -	} -	/* We have the initial and handle reference but need only one now */ -	drm_gem_object_unreference(&r->gem); -	*handlep = handle; -	return 0; -} - -/** - *	psb_gem_dumb_create	-	create a dumb buffer - *	@drm_file: our client file - *	@dev: our device - *	@args: the requested arguments copied from userspace - * - *	Allocate a buffer suitable for use for a frame buffer of the - *	form described by user space. Give userspace a handle by which - *	to reference it. - */ -int psb_gem_dumb_create(struct drm_file *file, struct drm_device *dev, -			struct drm_mode_create_dumb *args) -{ -	args->pitch = ALIGN(args->width * ((args->bpp + 7) / 8), 64); -	args->size = args->pitch * args->height; -	return psb_gem_create(file, dev, args->size, &args->handle); -} - -/** - *	psb_gem_dumb_destroy	-	destroy a dumb buffer - *	@file: client file - *	@dev: our DRM device - *	@handle: the object handle - * - *	Destroy a handle that was created via psb_gem_dumb_create, at least - *	we hope it was created that way. i915 seems to assume the caller - *	does the checking but that might be worth review ! FIXME - */ -int psb_gem_dumb_destroy(struct drm_file *file, struct drm_device *dev, -			uint32_t handle) -{ -	/* No special work needed, drop the reference and see what falls out */ -	return drm_gem_handle_delete(file, handle); -} - -/** - *	psb_gem_fault		-	pagefault handler for GEM objects - *	@vma: the VMA of the GEM object - *	@vmf: fault detail - * - *	Invoked when a fault occurs on an mmap of a GEM managed area. GEM - *	does most of the work for us including the actual map/unmap calls - *	but we need to do the actual page work. - * - *	This code eventually needs to handle faulting objects in and out - *	of the GTT and repacking it when we run out of space. We can put - *	that off for now and for our simple uses - * - *	The VMA was set up by GEM. In doing so it also ensured that the - *	vma->vm_private_data points to the GEM object that is backing this - *	mapping. - */ -int psb_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) -{ -	struct drm_gem_object *obj; -	struct gtt_range *r; -	int ret; -	unsigned long pfn; -	pgoff_t page_offset; -	struct drm_device *dev; -	struct drm_psb_private *dev_priv; - -	obj = vma->vm_private_data;	/* GEM object */ -	dev = obj->dev; -	dev_priv = dev->dev_private; - -	r = container_of(obj, struct gtt_range, gem);	/* Get the gtt range */ - -	/* Make sure we don't parallel update on a fault, nor move or remove -	   something from beneath our feet */ -	mutex_lock(&dev->struct_mutex); - -	/* For now the mmap pins the object and it stays pinned. As things -	   stand that will do us no harm */ -	if (r->mmapping == 0) { -		ret = psb_gtt_pin(r); -		if (ret < 0) { -			dev_err(dev->dev, "gma500: pin failed: %d\n", ret); -			goto fail; -		} -		r->mmapping = 1; -	} - -	/* Page relative to the VMA start - we must calculate this ourselves -	   because vmf->pgoff is the fake GEM offset */ -	page_offset = ((unsigned long) vmf->virtual_address - vma->vm_start) -				>> PAGE_SHIFT; - -	/* CPU view of the page, don't go via the GART for CPU writes */ -	if (r->stolen) -		pfn = (dev_priv->stolen_base + r->offset) >> PAGE_SHIFT; -	else -		pfn = page_to_pfn(r->pages[page_offset]); -	ret = vm_insert_pfn(vma, (unsigned long)vmf->virtual_address, pfn); - -fail: -	mutex_unlock(&dev->struct_mutex); -	switch (ret) { -	case 0: -	case -ERESTARTSYS: -	case -EINTR: -		return VM_FAULT_NOPAGE; -	case -ENOMEM: -		return VM_FAULT_OOM; -	default: -		return VM_FAULT_SIGBUS; -	} -} - -static int psb_gem_create_stolen(struct drm_file *file, struct drm_device *dev, -						int size, u32 *handle) -{ -	struct gtt_range *gtt = psb_gtt_alloc_range(dev, size, "gem", 1); -	if (gtt == NULL) -		return -ENOMEM; -	if (drm_gem_private_object_init(dev, >t->gem, size) != 0) -		goto free_gtt; -	if (drm_gem_handle_create(file, >t->gem, handle) == 0) -		return 0; -free_gtt: -	psb_gtt_free_range(dev, gtt); -	return -ENOMEM; -} - -/* - *	GEM interfaces for our specific client - */ -int psb_gem_create_ioctl(struct drm_device *dev, void *data, -					struct drm_file *file) -{ -	struct drm_psb_gem_create *args = data; -	int ret; -	if (args->flags & PSB_GEM_CREATE_STOLEN) { -		ret = psb_gem_create_stolen(file, dev, args->size, -							&args->handle); -		if (ret == 0) -			return 0; -		/* Fall throguh */ -		args->flags &= ~PSB_GEM_CREATE_STOLEN; -	} -	return psb_gem_create(file, dev, args->size, &args->handle); -} - -int psb_gem_mmap_ioctl(struct drm_device *dev, void *data, -					struct drm_file *file) -{ -	struct drm_psb_gem_mmap *args = data; -	return dev->driver->dumb_map_offset(file, dev, -						args->handle, &args->offset); -} - diff --git a/drivers/staging/gma500/gem_glue.c b/drivers/staging/gma500/gem_glue.c deleted file mode 100644 index daac1212065..00000000000 --- a/drivers/staging/gma500/gem_glue.c +++ /dev/null @@ -1,89 +0,0 @@ -/************************************************************************** - * Copyright (c) 2011, Intel Corporation. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - **************************************************************************/ - -#include <drm/drmP.h> -#include <drm/drm.h> - -void drm_gem_object_release_wrap(struct drm_gem_object *obj) -{ -	/* Remove the list map if one is present */ -	if (obj->map_list.map) { -		struct drm_gem_mm *mm = obj->dev->mm_private; -		struct drm_map_list *list = &obj->map_list; -		drm_ht_remove_item(&mm->offset_hash, &list->hash); -		drm_mm_put_block(list->file_offset_node); -		kfree(list->map); -		list->map = NULL; -	} -	drm_gem_object_release(obj); -} - -/** - *	gem_create_mmap_offset		-	invent an mmap offset - *	@obj: our object - * - *	Standard implementation of offset generation for mmap as is - *	duplicated in several drivers. This belongs in GEM. - */ -int gem_create_mmap_offset(struct drm_gem_object *obj) -{ -	struct drm_device *dev = obj->dev; -	struct drm_gem_mm *mm = dev->mm_private; -	struct drm_map_list *list; -	struct drm_local_map *map; -	int ret; - -	list = &obj->map_list; -	list->map = kzalloc(sizeof(struct drm_map_list), GFP_KERNEL); -	if (list->map == NULL) -		return -ENOMEM; -	map = list->map; -	map->type = _DRM_GEM; -	map->size = obj->size; -	map->handle = obj; - -	list->file_offset_node = drm_mm_search_free(&mm->offset_manager, -					obj->size / PAGE_SIZE, 0, 0); -	if (!list->file_offset_node) { -		dev_err(dev->dev, "failed to allocate offset for bo %d\n", -								obj->name); -		ret = -ENOSPC; -		goto free_it; -	} -	list->file_offset_node = drm_mm_get_block(list->file_offset_node, -					obj->size / PAGE_SIZE, 0); -	if (!list->file_offset_node) { -		ret = -ENOMEM; -		goto free_it; -	} -	list->hash.key = list->file_offset_node->start; -	ret = drm_ht_insert_item(&mm->offset_hash, &list->hash); -	if (ret) { -		dev_err(dev->dev, "failed to add to map hash\n"); -		goto free_mm; -	} -	return 0; - -free_mm: -	drm_mm_put_block(list->file_offset_node); -free_it: -	kfree(list->map); -	list->map = NULL; -	return ret; -} diff --git a/drivers/staging/gma500/gem_glue.h b/drivers/staging/gma500/gem_glue.h deleted file mode 100644 index ce5ce30f74d..00000000000 --- a/drivers/staging/gma500/gem_glue.h +++ /dev/null @@ -1,2 +0,0 @@ -extern void drm_gem_object_release_wrap(struct drm_gem_object *obj); -extern int gem_create_mmap_offset(struct drm_gem_object *obj); diff --git a/drivers/staging/gma500/gtt.c b/drivers/staging/gma500/gtt.c deleted file mode 100644 index e770bd190a5..00000000000 --- a/drivers/staging/gma500/gtt.c +++ /dev/null @@ -1,553 +0,0 @@ -/* - * Copyright (c) 2007, Intel Corporation. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - * Authors: Thomas Hellstrom <thomas-at-tungstengraphics.com> - *	    Alan Cox <alan@linux.intel.com> - */ - -#include <drm/drmP.h> -#include "psb_drv.h" - - -/* - *	GTT resource allocator - manage page mappings in GTT space - */ - -/** - *	psb_gtt_mask_pte	-	generate GTT pte entry - *	@pfn: page number to encode - *	@type: type of memory in the GTT - * - *	Set the GTT entry for the appropriate memory type. - */ -static inline uint32_t psb_gtt_mask_pte(uint32_t pfn, int type) -{ -	uint32_t mask = PSB_PTE_VALID; - -	if (type & PSB_MMU_CACHED_MEMORY) -		mask |= PSB_PTE_CACHED; -	if (type & PSB_MMU_RO_MEMORY) -		mask |= PSB_PTE_RO; -	if (type & PSB_MMU_WO_MEMORY) -		mask |= PSB_PTE_WO; - -	return (pfn << PAGE_SHIFT) | mask; -} - -/** - *	psb_gtt_entry		-	find the GTT entries for a gtt_range - *	@dev: our DRM device - *	@r: our GTT range - * - *	Given a gtt_range object return the GTT offset of the page table - *	entries for this gtt_range - */ -u32 *psb_gtt_entry(struct drm_device *dev, struct gtt_range *r) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; -	unsigned long offset; - -	offset = r->resource.start - dev_priv->gtt_mem->start; - -	return dev_priv->gtt_map + (offset >> PAGE_SHIFT); -} - -/** - *	psb_gtt_insert	-	put an object into the GTT - *	@dev: our DRM device - *	@r: our GTT range - * - *	Take our preallocated GTT range and insert the GEM object into - *	the GTT. This is protected via the gtt mutex which the caller - *	must hold. - */ -static int psb_gtt_insert(struct drm_device *dev, struct gtt_range *r) -{ -	u32 *gtt_slot, pte; -	struct page **pages; -	int i; - -	if (r->pages == NULL) { -		WARN_ON(1); -		return -EINVAL; -	} - -	WARN_ON(r->stolen);	/* refcount these maybe ? */ - -	gtt_slot = psb_gtt_entry(dev, r); -	pages = r->pages; - -	/* Make sure changes are visible to the GPU */ -	set_pages_array_uc(pages, r->npage); - -	/* Write our page entries into the GTT itself */ -	for (i = r->roll; i < r->npage; i++) { -		pte = psb_gtt_mask_pte(page_to_pfn(r->pages[i]), 0); -		iowrite32(pte, gtt_slot++); -	} -	for (i = 0; i < r->roll; i++) { -		pte = psb_gtt_mask_pte(page_to_pfn(r->pages[i]), 0); -		iowrite32(pte, gtt_slot++); -	} -	/* Make sure all the entries are set before we return */ -	ioread32(gtt_slot - 1); - -	return 0; -} - -/** - *	psb_gtt_remove	-	remove an object from the GTT - *	@dev: our DRM device - *	@r: our GTT range - * - *	Remove a preallocated GTT range from the GTT. Overwrite all the - *	page table entries with the dummy page. This is protected via the gtt - *	mutex which the caller must hold. - */ -static void psb_gtt_remove(struct drm_device *dev, struct gtt_range *r) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; -	u32 *gtt_slot, pte; -	int i; - -	WARN_ON(r->stolen); - -	gtt_slot = psb_gtt_entry(dev, r); -	pte = psb_gtt_mask_pte(page_to_pfn(dev_priv->scratch_page), 0); - -	for (i = 0; i < r->npage; i++) -		iowrite32(pte, gtt_slot++); -	ioread32(gtt_slot - 1); -	set_pages_array_wb(r->pages, r->npage); -} - -/** - *	psb_gtt_roll	-	set scrolling position - *	@dev: our DRM device - *	@r: the gtt mapping we are using - *	@roll: roll offset - * - *	Roll an existing pinned mapping by moving the pages through the GTT. - *	This allows us to implement hardware scrolling on the consoles without - *	a 2D engine - */ -void psb_gtt_roll(struct drm_device *dev, struct gtt_range *r, int roll) -{ -	u32 *gtt_slot, pte; -	int i; - -	if (roll >= r->npage) { -		WARN_ON(1); -		return; -	} - -	r->roll = roll; - -	/* Not currently in the GTT - no worry we will write the mapping at -	   the right position when it gets pinned */ -	if (!r->stolen && !r->in_gart) -		return; - -	gtt_slot = psb_gtt_entry(dev, r); - -	for (i = r->roll; i < r->npage; i++) { -		pte = psb_gtt_mask_pte(page_to_pfn(r->pages[i]), 0); -		iowrite32(pte, gtt_slot++); -	} -	for (i = 0; i < r->roll; i++) { -		pte = psb_gtt_mask_pte(page_to_pfn(r->pages[i]), 0); -		iowrite32(pte, gtt_slot++); -	} -	ioread32(gtt_slot - 1); -} - -/** - *	psb_gtt_attach_pages	-	attach and pin GEM pages - *	@gt: the gtt range - * - *	Pin and build an in kernel list of the pages that back our GEM object. - *	While we hold this the pages cannot be swapped out. This is protected - *	via the gtt mutex which the caller must hold. - */ -static int psb_gtt_attach_pages(struct gtt_range *gt) -{ -	struct inode *inode; -	struct address_space *mapping; -	int i; -	struct page *p; -	int pages = gt->gem.size / PAGE_SIZE; - -	WARN_ON(gt->pages); - -	/* This is the shared memory object that backs the GEM resource */ -	inode = gt->gem.filp->f_path.dentry->d_inode; -	mapping = inode->i_mapping; - -	gt->pages = kmalloc(pages * sizeof(struct page *), GFP_KERNEL); -	if (gt->pages == NULL) -		return -ENOMEM; -	gt->npage = pages; - -	for (i = 0; i < pages; i++) { -		/* FIXME: needs updating as per mail from Hugh Dickins */ -		p = read_cache_page_gfp(mapping, i, -					__GFP_COLD | GFP_KERNEL); -		if (IS_ERR(p)) -			goto err; -		gt->pages[i] = p; -	} -	return 0; - -err: -	while (i--) -		page_cache_release(gt->pages[i]); -	kfree(gt->pages); -	gt->pages = NULL; -	return PTR_ERR(p); -} - -/** - *	psb_gtt_detach_pages	-	attach and pin GEM pages - *	@gt: the gtt range - * - *	Undo the effect of psb_gtt_attach_pages. At this point the pages - *	must have been removed from the GTT as they could now be paged out - *	and move bus address. This is protected via the gtt mutex which the - *	caller must hold. - */ -static void psb_gtt_detach_pages(struct gtt_range *gt) -{ -	int i; -	for (i = 0; i < gt->npage; i++) { -		/* FIXME: do we need to force dirty */ -		set_page_dirty(gt->pages[i]); -		page_cache_release(gt->pages[i]); -	} -	kfree(gt->pages); -	gt->pages = NULL; -} - -/** - *	psb_gtt_pin		-	pin pages into the GTT - *	@gt: range to pin - * - *	Pin a set of pages into the GTT. The pins are refcounted so that - *	multiple pins need multiple unpins to undo. - * - *	Non GEM backed objects treat this as a no-op as they are always GTT - *	backed objects. - */ -int psb_gtt_pin(struct gtt_range *gt) -{ -	int ret = 0; -	struct drm_device *dev = gt->gem.dev; -	struct drm_psb_private *dev_priv = dev->dev_private; - -	mutex_lock(&dev_priv->gtt_mutex); - -	if (gt->in_gart == 0 && gt->stolen == 0) { -		ret = psb_gtt_attach_pages(gt); -		if (ret < 0) -			goto out; -		ret = psb_gtt_insert(dev, gt); -		if (ret < 0) { -			psb_gtt_detach_pages(gt); -			goto out; -		} -	} -	gt->in_gart++; -out: -	mutex_unlock(&dev_priv->gtt_mutex); -	return ret; -} - -/** - *	psb_gtt_unpin		-	Drop a GTT pin requirement - *	@gt: range to pin - * - *	Undoes the effect of psb_gtt_pin. On the last drop the GEM object - *	will be removed from the GTT which will also drop the page references - *	and allow the VM to clean up or page stuff. - * - *	Non GEM backed objects treat this as a no-op as they are always GTT - *	backed objects. - */ -void psb_gtt_unpin(struct gtt_range *gt) -{ -	struct drm_device *dev = gt->gem.dev; -	struct drm_psb_private *dev_priv = dev->dev_private; - -	mutex_lock(&dev_priv->gtt_mutex); - -	WARN_ON(!gt->in_gart); - -	gt->in_gart--; -	if (gt->in_gart == 0 && gt->stolen == 0) { -		psb_gtt_remove(dev, gt); -		psb_gtt_detach_pages(gt); -	} -	mutex_unlock(&dev_priv->gtt_mutex); -} - -/* - *	GTT resource allocator - allocate and manage GTT address space - */ - -/** - *	psb_gtt_alloc_range	-	allocate GTT address space - *	@dev: Our DRM device - *	@len: length (bytes) of address space required - *	@name: resource name - *	@backed: resource should be backed by stolen pages - * - *	Ask the kernel core to find us a suitable range of addresses - *	to use for a GTT mapping. - * - *	Returns a gtt_range structure describing the object, or NULL on - *	error. On successful return the resource is both allocated and marked - *	as in use. - */ -struct gtt_range *psb_gtt_alloc_range(struct drm_device *dev, int len, -						const char *name, int backed) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; -	struct gtt_range *gt; -	struct resource *r = dev_priv->gtt_mem; -	int ret; -	unsigned long start, end; - -	if (backed) { -		/* The start of the GTT is the stolen pages */ -		start = r->start; -		end = r->start + dev_priv->gtt.stolen_size - 1; -	} else { -		/* The rest we will use for GEM backed objects */ -		start = r->start + dev_priv->gtt.stolen_size; -		end = r->end; -	} - -	gt = kzalloc(sizeof(struct gtt_range), GFP_KERNEL); -	if (gt == NULL) -		return NULL; -	gt->resource.name = name; -	gt->stolen = backed; -	gt->in_gart = backed; -	gt->roll = 0; -	/* Ensure this is set for non GEM objects */ -	gt->gem.dev = dev; -	ret = allocate_resource(dev_priv->gtt_mem, >->resource, -				len, start, end, PAGE_SIZE, NULL, NULL); -	if (ret == 0) { -		gt->offset = gt->resource.start - r->start; -		return gt; -	} -	kfree(gt); -	return NULL; -} - -/** - *	psb_gtt_free_range	-	release GTT address space - *	@dev: our DRM device - *	@gt: a mapping created with psb_gtt_alloc_range - * - *	Release a resource that was allocated with psb_gtt_alloc_range. If the - *	object has been pinned by mmap users we clean this up here currently. - */ -void psb_gtt_free_range(struct drm_device *dev, struct gtt_range *gt) -{ -	/* Undo the mmap pin if we are destroying the object */ -	if (gt->mmapping) { -		psb_gtt_unpin(gt); -		gt->mmapping = 0; -	} -	WARN_ON(gt->in_gart && !gt->stolen); -	release_resource(>->resource); -	kfree(gt); -} - -void psb_gtt_alloc(struct drm_device *dev) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; -	init_rwsem(&dev_priv->gtt.sem); -} - -void psb_gtt_takedown(struct drm_device *dev) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; - -	if (dev_priv->gtt_map) { -		iounmap(dev_priv->gtt_map); -		dev_priv->gtt_map = NULL; -	} -	if (dev_priv->gtt_initialized) { -		pci_write_config_word(dev->pdev, PSB_GMCH_CTRL, -				      dev_priv->gmch_ctrl); -		PSB_WVDC32(dev_priv->pge_ctl, PSB_PGETBL_CTL); -		(void) PSB_RVDC32(PSB_PGETBL_CTL); -	} -	if (dev_priv->vram_addr) -		iounmap(dev_priv->gtt_map); -} - -int psb_gtt_init(struct drm_device *dev, int resume) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; -	unsigned gtt_pages; -	unsigned long stolen_size, vram_stolen_size; -	unsigned i, num_pages; -	unsigned pfn_base; -	uint32_t vram_pages; -	uint32_t dvmt_mode = 0; -	struct psb_gtt *pg; - -	int ret = 0; -	uint32_t pte; - -	mutex_init(&dev_priv->gtt_mutex); - -	psb_gtt_alloc(dev); -	pg = &dev_priv->gtt; - -	/* Enable the GTT */ -	pci_read_config_word(dev->pdev, PSB_GMCH_CTRL, &dev_priv->gmch_ctrl); -	pci_write_config_word(dev->pdev, PSB_GMCH_CTRL, -			      dev_priv->gmch_ctrl | _PSB_GMCH_ENABLED); - -	dev_priv->pge_ctl = PSB_RVDC32(PSB_PGETBL_CTL); -	PSB_WVDC32(dev_priv->pge_ctl | _PSB_PGETBL_ENABLED, PSB_PGETBL_CTL); -	(void) PSB_RVDC32(PSB_PGETBL_CTL); - -	/* The root resource we allocate address space from */ -	dev_priv->gtt_initialized = 1; - -	pg->gtt_phys_start = dev_priv->pge_ctl & PAGE_MASK; - -	/* -	 *	The video mmu has a hw bug when accessing 0x0D0000000. -	 *	Make gatt start at 0x0e000,0000. This doesn't actually -	 *	matter for us but may do if the video acceleration ever -	 *	gets opened up. -	 */ -	pg->mmu_gatt_start = 0xE0000000; - -	pg->gtt_start = pci_resource_start(dev->pdev, PSB_GTT_RESOURCE); -	gtt_pages = pci_resource_len(dev->pdev, PSB_GTT_RESOURCE) -								>> PAGE_SHIFT; -	/* Some CDV firmware doesn't report this currently. In which case the -	   system has 64 gtt pages */ -	if (pg->gtt_start == 0 || gtt_pages == 0) { -		dev_err(dev->dev, "GTT PCI BAR not initialized.\n"); -		gtt_pages = 64; -		pg->gtt_start = dev_priv->pge_ctl; -	} - -	pg->gatt_start = pci_resource_start(dev->pdev, PSB_GATT_RESOURCE); -	pg->gatt_pages = pci_resource_len(dev->pdev, PSB_GATT_RESOURCE) -								>> PAGE_SHIFT; -	dev_priv->gtt_mem = &dev->pdev->resource[PSB_GATT_RESOURCE]; - -	if (pg->gatt_pages == 0 || pg->gatt_start == 0) { -		static struct resource fudge;	/* Preferably peppermint */ -		/* This can occur on CDV SDV systems. Fudge it in this case. -		   We really don't care what imaginary space is being allocated -		   at this point */ -		dev_err(dev->dev, "GATT PCI BAR not initialized.\n"); -		pg->gatt_start = 0x40000000; -		pg->gatt_pages = (128 * 1024 * 1024) >> PAGE_SHIFT; -		/* This is a little confusing but in fact the GTT is providing -		   a view from the GPU into memory and not vice versa. As such -		   this is really allocating space that is not the same as the -		   CPU address space on CDV */ -		fudge.start = 0x40000000; -		fudge.end = 0x40000000 + 128 * 1024 * 1024 - 1; -		fudge.name = "fudge"; -		fudge.flags = IORESOURCE_MEM; -		dev_priv->gtt_mem = &fudge; -	} - -	pci_read_config_dword(dev->pdev, PSB_BSM, &dev_priv->stolen_base); -	vram_stolen_size = pg->gtt_phys_start - dev_priv->stolen_base -								- PAGE_SIZE; - -	stolen_size = vram_stolen_size; - -	printk(KERN_INFO "Stolen memory information\n"); -	printk(KERN_INFO "       base in RAM: 0x%x\n", dev_priv->stolen_base); -	printk(KERN_INFO "       size: %luK, calculated by (GTT RAM base) - (Stolen base), seems wrong\n", -		vram_stolen_size/1024); -	dvmt_mode = (dev_priv->gmch_ctrl >> 4) & 0x7; -	printk(KERN_INFO "      the correct size should be: %dM(dvmt mode=%d)\n", -		(dvmt_mode == 1) ? 1 : (2 << (dvmt_mode - 1)), dvmt_mode); - -	if (resume && (gtt_pages != pg->gtt_pages) && -	    (stolen_size != pg->stolen_size)) { -		dev_err(dev->dev, "GTT resume error.\n"); -		ret = -EINVAL; -		goto out_err; -	} - -	pg->gtt_pages = gtt_pages; -	pg->stolen_size = stolen_size; -	dev_priv->vram_stolen_size = vram_stolen_size; - -	/* -	 *	Map the GTT and the stolen memory area -	 */ -	dev_priv->gtt_map = ioremap_nocache(pg->gtt_phys_start, -						gtt_pages << PAGE_SHIFT); -	if (!dev_priv->gtt_map) { -		dev_err(dev->dev, "Failure to map gtt.\n"); -		ret = -ENOMEM; -		goto out_err; -	} - -	dev_priv->vram_addr = ioremap_wc(dev_priv->stolen_base, stolen_size); -	if (!dev_priv->vram_addr) { -		dev_err(dev->dev, "Failure to map stolen base.\n"); -		ret = -ENOMEM; -		goto out_err; -	} - -	/* -	 * Insert vram stolen pages into the GTT -	 */ - -	pfn_base = dev_priv->stolen_base >> PAGE_SHIFT; -	vram_pages = num_pages = vram_stolen_size >> PAGE_SHIFT; -	printk(KERN_INFO"Set up %d stolen pages starting at 0x%08x, GTT offset %dK\n", -		num_pages, pfn_base << PAGE_SHIFT, 0); -	for (i = 0; i < num_pages; ++i) { -		pte = psb_gtt_mask_pte(pfn_base + i, 0); -		iowrite32(pte, dev_priv->gtt_map + i); -	} - -	/* -	 * Init rest of GTT to the scratch page to avoid accidents or scribbles -	 */ - -	pfn_base = page_to_pfn(dev_priv->scratch_page); -	pte = psb_gtt_mask_pte(pfn_base, 0); -	for (; i < gtt_pages; ++i) -		iowrite32(pte, dev_priv->gtt_map + i); - -	(void) ioread32(dev_priv->gtt_map + i - 1); -	return 0; - -out_err: -	psb_gtt_takedown(dev); -	return ret; -} diff --git a/drivers/staging/gma500/gtt.h b/drivers/staging/gma500/gtt.h deleted file mode 100644 index aa1742387f5..00000000000 --- a/drivers/staging/gma500/gtt.h +++ /dev/null @@ -1,64 +0,0 @@ -/************************************************************************** - * Copyright (c) 2007-2008, Intel Corporation. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - **************************************************************************/ - -#ifndef _PSB_GTT_H_ -#define _PSB_GTT_H_ - -#include <drm/drmP.h> - -/* This wants cleaning up with respect to the psb_dev and un-needed stuff */ -struct psb_gtt { -	uint32_t gatt_start; -	uint32_t mmu_gatt_start; -	uint32_t gtt_start; -	uint32_t gtt_phys_start; -	unsigned gtt_pages; -	unsigned gatt_pages; -	unsigned long stolen_size; -	unsigned long vram_stolen_size; -	struct rw_semaphore sem; -}; - -/* Exported functions */ -extern int psb_gtt_init(struct drm_device *dev, int resume); -extern void psb_gtt_takedown(struct drm_device *dev); - -/* Each gtt_range describes an allocation in the GTT area */ -struct gtt_range { -	struct resource resource;	/* Resource for our allocation */ -	u32 offset;			/* GTT offset of our object */ -	struct drm_gem_object gem;	/* GEM high level stuff */ -	int in_gart;			/* Currently in the GART (ref ct) */ -	bool stolen;			/* Backed from stolen RAM */ -	bool mmapping;			/* Is mmappable */ -	struct page **pages;		/* Backing pages if present */ -	int npage;			/* Number of backing pages */ -	int roll;			/* Roll applied to the GTT entries */ -}; - -extern struct gtt_range *psb_gtt_alloc_range(struct drm_device *dev, int len, -						const char *name, int backed); -extern void psb_gtt_kref_put(struct gtt_range *gt); -extern void psb_gtt_free_range(struct drm_device *dev, struct gtt_range *gt); -extern int psb_gtt_pin(struct gtt_range *gt); -extern void psb_gtt_unpin(struct gtt_range *gt); -extern void psb_gtt_roll(struct drm_device *dev, -					struct gtt_range *gt, int roll); - -#endif diff --git a/drivers/staging/gma500/intel_bios.c b/drivers/staging/gma500/intel_bios.c deleted file mode 100644 index 096757f9bc8..00000000000 --- a/drivers/staging/gma500/intel_bios.c +++ /dev/null @@ -1,303 +0,0 @@ -/* - * Copyright (c) 2006 Intel Corporation - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - * Authors: - *    Eric Anholt <eric@anholt.net> - * - */ -#include <drm/drmP.h> -#include <drm/drm.h> -#include "psb_drm.h" -#include "psb_drv.h" -#include "psb_intel_drv.h" -#include "psb_intel_reg.h" -#include "intel_bios.h" - - -static void *find_section(struct bdb_header *bdb, int section_id) -{ -	u8 *base = (u8 *)bdb; -	int index = 0; -	u16 total, current_size; -	u8 current_id; - -	/* skip to first section */ -	index += bdb->header_size; -	total = bdb->bdb_size; - -	/* walk the sections looking for section_id */ -	while (index < total) { -		current_id = *(base + index); -		index++; -		current_size = *((u16 *)(base + index)); -		index += 2; -		if (current_id == section_id) -			return base + index; -		index += current_size; -	} - -	return NULL; -} - -static void fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode, -			struct lvds_dvo_timing *dvo_timing) -{ -	panel_fixed_mode->hdisplay = (dvo_timing->hactive_hi << 8) | -		dvo_timing->hactive_lo; -	panel_fixed_mode->hsync_start = panel_fixed_mode->hdisplay + -		((dvo_timing->hsync_off_hi << 8) | dvo_timing->hsync_off_lo); -	panel_fixed_mode->hsync_end = panel_fixed_mode->hsync_start + -		dvo_timing->hsync_pulse_width; -	panel_fixed_mode->htotal = panel_fixed_mode->hdisplay + -		((dvo_timing->hblank_hi << 8) | dvo_timing->hblank_lo); - -	panel_fixed_mode->vdisplay = (dvo_timing->vactive_hi << 8) | -		dvo_timing->vactive_lo; -	panel_fixed_mode->vsync_start = panel_fixed_mode->vdisplay + -		dvo_timing->vsync_off; -	panel_fixed_mode->vsync_end = panel_fixed_mode->vsync_start + -		dvo_timing->vsync_pulse_width; -	panel_fixed_mode->vtotal = panel_fixed_mode->vdisplay + -		((dvo_timing->vblank_hi << 8) | dvo_timing->vblank_lo); -	panel_fixed_mode->clock = dvo_timing->clock * 10; -	panel_fixed_mode->type = DRM_MODE_TYPE_PREFERRED; - -	/* Some VBTs have bogus h/vtotal values */ -	if (panel_fixed_mode->hsync_end > panel_fixed_mode->htotal) -		panel_fixed_mode->htotal = panel_fixed_mode->hsync_end + 1; -	if (panel_fixed_mode->vsync_end > panel_fixed_mode->vtotal) -		panel_fixed_mode->vtotal = panel_fixed_mode->vsync_end + 1; - -	drm_mode_set_name(panel_fixed_mode); -} - -static void parse_backlight_data(struct drm_psb_private *dev_priv, -				struct bdb_header *bdb) -{ -	struct bdb_lvds_backlight *vbt_lvds_bl = NULL; -	struct bdb_lvds_backlight *lvds_bl; -	u8 p_type = 0; -	void *bl_start = NULL; -	struct bdb_lvds_options *lvds_opts -				= find_section(bdb, BDB_LVDS_OPTIONS); - -	dev_priv->lvds_bl = NULL; - -	if (lvds_opts) -		p_type = lvds_opts->panel_type; -	else -		return; - -	bl_start = find_section(bdb, BDB_LVDS_BACKLIGHT); -	vbt_lvds_bl = (struct bdb_lvds_backlight *)(bl_start + 1) + p_type; - -	lvds_bl = kzalloc(sizeof(*vbt_lvds_bl), GFP_KERNEL); -	if (!lvds_bl) { -		dev_err(dev_priv->dev->dev, "out of memory for backlight data\n"); -		return; -	} -	memcpy(lvds_bl, vbt_lvds_bl, sizeof(*vbt_lvds_bl)); -	dev_priv->lvds_bl = lvds_bl; -} - -/* Try to find integrated panel data */ -static void parse_lfp_panel_data(struct drm_psb_private *dev_priv, -			    struct bdb_header *bdb) -{ -	struct bdb_lvds_options *lvds_options; -	struct bdb_lvds_lfp_data *lvds_lfp_data; -	struct bdb_lvds_lfp_data_entry *entry; -	struct lvds_dvo_timing *dvo_timing; -	struct drm_display_mode *panel_fixed_mode; - -	/* Defaults if we can't find VBT info */ -	dev_priv->lvds_dither = 0; -	dev_priv->lvds_vbt = 0; - -	lvds_options = find_section(bdb, BDB_LVDS_OPTIONS); -	if (!lvds_options) -		return; - -	dev_priv->lvds_dither = lvds_options->pixel_dither; -	if (lvds_options->panel_type == 0xff) -		return; - -	lvds_lfp_data = find_section(bdb, BDB_LVDS_LFP_DATA); -	if (!lvds_lfp_data) -		return; - - -	entry = &lvds_lfp_data->data[lvds_options->panel_type]; -	dvo_timing = &entry->dvo_timing; - -	panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), -				      GFP_KERNEL); -	if (panel_fixed_mode == NULL) { -		dev_err(dev_priv->dev->dev, "out of memory for fixed panel mode\n"); -		return; -	} - -	dev_priv->lvds_vbt = 1; -	fill_detail_timing_data(panel_fixed_mode, dvo_timing); - -	if (panel_fixed_mode->htotal > 0 && panel_fixed_mode->vtotal > 0) { -		dev_priv->lfp_lvds_vbt_mode = panel_fixed_mode; -		drm_mode_debug_printmodeline(panel_fixed_mode); -	} else { -		dev_dbg(dev_priv->dev->dev, "ignoring invalid LVDS VBT\n"); -		dev_priv->lvds_vbt = 0; -		kfree(panel_fixed_mode); -	} -	return; -} - -/* Try to find sdvo panel data */ -static void parse_sdvo_panel_data(struct drm_psb_private *dev_priv, -		      struct bdb_header *bdb) -{ -	struct bdb_sdvo_lvds_options *sdvo_lvds_options; -	struct lvds_dvo_timing *dvo_timing; -	struct drm_display_mode *panel_fixed_mode; - -	dev_priv->sdvo_lvds_vbt_mode = NULL; - -	sdvo_lvds_options = find_section(bdb, BDB_SDVO_LVDS_OPTIONS); -	if (!sdvo_lvds_options) -		return; - -	dvo_timing = find_section(bdb, BDB_SDVO_PANEL_DTDS); -	if (!dvo_timing) -		return; - -	panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), GFP_KERNEL); - -	if (!panel_fixed_mode) -		return; - -	fill_detail_timing_data(panel_fixed_mode, -			dvo_timing + sdvo_lvds_options->panel_type); - -	dev_priv->sdvo_lvds_vbt_mode = panel_fixed_mode; - -	return; -} - -static void parse_general_features(struct drm_psb_private *dev_priv, -		       struct bdb_header *bdb) -{ -	struct bdb_general_features *general; - -	/* Set sensible defaults in case we can't find the general block */ -	dev_priv->int_tv_support = 1; -	dev_priv->int_crt_support = 1; - -	general = find_section(bdb, BDB_GENERAL_FEATURES); -	if (general) { -		dev_priv->int_tv_support = general->int_tv_support; -		dev_priv->int_crt_support = general->int_crt_support; -		dev_priv->lvds_use_ssc = general->enable_ssc; - -		if (dev_priv->lvds_use_ssc) { -			dev_priv->lvds_ssc_freq -				= general->ssc_freq ? 100 : 96; -		} -	} -} - -/** - * psb_intel_init_bios - initialize VBIOS settings & find VBT - * @dev: DRM device - * - * Loads the Video BIOS and checks that the VBT exists.  Sets scratch registers - * to appropriate values. - * - * VBT existence is a sanity check that is relied on by other i830_bios.c code. - * Note that it would be better to use a BIOS call to get the VBT, as BIOSes may - * feed an updated VBT back through that, compared to what we'll fetch using - * this method of groping around in the BIOS data. - * - * Returns 0 on success, nonzero on failure. - */ -bool psb_intel_init_bios(struct drm_device *dev) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; -	struct pci_dev *pdev = dev->pdev; -	struct vbt_header *vbt = NULL; -	struct bdb_header *bdb; -	u8 __iomem *bios; -	size_t size; -	int i; - -	bios = pci_map_rom(pdev, &size); -	if (!bios) -		return -1; - -	/* Scour memory looking for the VBT signature */ -	for (i = 0; i + 4 < size; i++) { -		if (!memcmp(bios + i, "$VBT", 4)) { -			vbt = (struct vbt_header *)(bios + i); -			break; -		} -	} - -	if (!vbt) { -		dev_err(dev->dev, "VBT signature missing\n"); -		pci_unmap_rom(pdev, bios); -		return -1; -	} - -	bdb = (struct bdb_header *)(bios + i + vbt->bdb_offset); - -	/* Grab useful general definitions */ -	parse_general_features(dev_priv, bdb); -	parse_lfp_panel_data(dev_priv, bdb); -	parse_sdvo_panel_data(dev_priv, bdb); -	parse_backlight_data(dev_priv, bdb); - -	pci_unmap_rom(pdev, bios); - -	return 0; -} - -/** - * Destroy and free VBT data - */ -void psb_intel_destroy_bios(struct drm_device *dev) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; -	struct drm_display_mode *sdvo_lvds_vbt_mode = -				dev_priv->sdvo_lvds_vbt_mode; -	struct drm_display_mode *lfp_lvds_vbt_mode = -				dev_priv->lfp_lvds_vbt_mode; -	struct bdb_lvds_backlight *lvds_bl = -				dev_priv->lvds_bl; - -	/*free sdvo panel mode*/ -	if (sdvo_lvds_vbt_mode) { -		dev_priv->sdvo_lvds_vbt_mode = NULL; -		kfree(sdvo_lvds_vbt_mode); -	} - -	if (lfp_lvds_vbt_mode) { -		dev_priv->lfp_lvds_vbt_mode = NULL; -		kfree(lfp_lvds_vbt_mode); -	} - -	if (lvds_bl) { -		dev_priv->lvds_bl = NULL; -		kfree(lvds_bl); -	} -} diff --git a/drivers/staging/gma500/intel_bios.h b/drivers/staging/gma500/intel_bios.h deleted file mode 100644 index 70f1bf01818..00000000000 --- a/drivers/staging/gma500/intel_bios.h +++ /dev/null @@ -1,430 +0,0 @@ -/* - * Copyright (c) 2006 Intel Corporation - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - * Authors: - *    Eric Anholt <eric@anholt.net> - * - */ - -#ifndef _I830_BIOS_H_ -#define _I830_BIOS_H_ - -#include <drm/drmP.h> - -struct vbt_header { -	u8 signature[20];		/**< Always starts with 'VBT$' */ -	u16 version;			/**< decimal */ -	u16 header_size;		/**< in bytes */ -	u16 vbt_size;			/**< in bytes */ -	u8 vbt_checksum; -	u8 reserved0; -	u32 bdb_offset;			/**< from beginning of VBT */ -	u32 aim_offset[4];		/**< from beginning of VBT */ -} __attribute__((packed)); - - -struct bdb_header { -	u8 signature[16];		/**< Always 'BIOS_DATA_BLOCK' */ -	u16 version;			/**< decimal */ -	u16 header_size;		/**< in bytes */ -	u16 bdb_size;			/**< in bytes */ -}; - -/* strictly speaking, this is a "skip" block, but it has interesting info */ -struct vbios_data { -	u8 type; /* 0 == desktop, 1 == mobile */ -	u8 relstage; -	u8 chipset; -	u8 lvds_present:1; -	u8 tv_present:1; -	u8 rsvd2:6; /* finish byte */ -	u8 rsvd3[4]; -	u8 signon[155]; -	u8 copyright[61]; -	u16 code_segment; -	u8 dos_boot_mode; -	u8 bandwidth_percent; -	u8 rsvd4; /* popup memory size */ -	u8 resize_pci_bios; -	u8 rsvd5; /* is crt already on ddc2 */ -} __attribute__((packed)); - -/* - * There are several types of BIOS data blocks (BDBs), each block has - * an ID and size in the first 3 bytes (ID in first, size in next 2). - * Known types are listed below. - */ -#define BDB_GENERAL_FEATURES	  1 -#define BDB_GENERAL_DEFINITIONS	  2 -#define BDB_OLD_TOGGLE_LIST	  3 -#define BDB_MODE_SUPPORT_LIST	  4 -#define BDB_GENERIC_MODE_TABLE	  5 -#define BDB_EXT_MMIO_REGS	  6 -#define BDB_SWF_IO		  7 -#define BDB_SWF_MMIO		  8 -#define BDB_DOT_CLOCK_TABLE	  9 -#define BDB_MODE_REMOVAL_TABLE	 10 -#define BDB_CHILD_DEVICE_TABLE	 11 -#define BDB_DRIVER_FEATURES	 12 -#define BDB_DRIVER_PERSISTENCE	 13 -#define BDB_EXT_TABLE_PTRS	 14 -#define BDB_DOT_CLOCK_OVERRIDE	 15 -#define BDB_DISPLAY_SELECT	 16 -/* 17 rsvd */ -#define BDB_DRIVER_ROTATION	 18 -#define BDB_DISPLAY_REMOVE	 19 -#define BDB_OEM_CUSTOM		 20 -#define BDB_EFP_LIST		 21 /* workarounds for VGA hsync/vsync */ -#define BDB_SDVO_LVDS_OPTIONS	 22 -#define BDB_SDVO_PANEL_DTDS	 23 -#define BDB_SDVO_LVDS_PNP_IDS	 24 -#define BDB_SDVO_LVDS_POWER_SEQ	 25 -#define BDB_TV_OPTIONS		 26 -#define BDB_LVDS_OPTIONS	 40 -#define BDB_LVDS_LFP_DATA_PTRS	 41 -#define BDB_LVDS_LFP_DATA	 42 -#define BDB_LVDS_BACKLIGHT	 43 -#define BDB_LVDS_POWER		 44 -#define BDB_SKIP		254 /* VBIOS private block, ignore */ - -struct bdb_general_features { -	/* bits 1 */ -	u8 panel_fitting:2; -	u8 flexaim:1; -	u8 msg_enable:1; -	u8 clear_screen:3; -	u8 color_flip:1; - -	/* bits 2 */ -	u8 download_ext_vbt:1; -	u8 enable_ssc:1; -	u8 ssc_freq:1; -	u8 enable_lfp_on_override:1; -	u8 disable_ssc_ddt:1; -	u8 rsvd8:3; /* finish byte */ - -	/* bits 3 */ -	u8 disable_smooth_vision:1; -	u8 single_dvi:1; -	u8 rsvd9:6; /* finish byte */ - -	/* bits 4 */ -	u8 legacy_monitor_detect; - -	/* bits 5 */ -	u8 int_crt_support:1; -	u8 int_tv_support:1; -	u8 rsvd11:6; /* finish byte */ -} __attribute__((packed)); - -struct bdb_general_definitions { -	/* DDC GPIO */ -	u8 crt_ddc_gmbus_pin; - -	/* DPMS bits */ -	u8 dpms_acpi:1; -	u8 skip_boot_crt_detect:1; -	u8 dpms_aim:1; -	u8 rsvd1:5; /* finish byte */ - -	/* boot device bits */ -	u8 boot_display[2]; -	u8 child_dev_size; - -	/* device info */ -	u8 tv_or_lvds_info[33]; -	u8 dev1[33]; -	u8 dev2[33]; -	u8 dev3[33]; -	u8 dev4[33]; -	/* may be another device block here on some platforms */ -}; - -struct bdb_lvds_options { -	u8 panel_type; -	u8 rsvd1; -	/* LVDS capabilities, stored in a dword */ -	u8 pfit_mode:2; -	u8 pfit_text_mode_enhanced:1; -	u8 pfit_gfx_mode_enhanced:1; -	u8 pfit_ratio_auto:1; -	u8 pixel_dither:1; -	u8 lvds_edid:1; -	u8 rsvd2:1; -	u8 rsvd4; -} __attribute__((packed)); - -struct bdb_lvds_backlight { -	u8 type:2; -	u8 pol:1; -	u8 gpio:3; -	u8 gmbus:2; -	u16 freq; -	u8 minbrightness; -	u8 i2caddr; -	u8 brightnesscmd; -	/*FIXME: more...*/ -} __attribute__((packed)); - -/* LFP pointer table contains entries to the struct below */ -struct bdb_lvds_lfp_data_ptr { -	u16 fp_timing_offset; /* offsets are from start of bdb */ -	u8 fp_table_size; -	u16 dvo_timing_offset; -	u8 dvo_table_size; -	u16 panel_pnp_id_offset; -	u8 pnp_table_size; -} __attribute__((packed)); - -struct bdb_lvds_lfp_data_ptrs { -	u8 lvds_entries; /* followed by one or more lvds_data_ptr structs */ -	struct bdb_lvds_lfp_data_ptr ptr[16]; -} __attribute__((packed)); - -/* LFP data has 3 blocks per entry */ -struct lvds_fp_timing { -	u16 x_res; -	u16 y_res; -	u32 lvds_reg; -	u32 lvds_reg_val; -	u32 pp_on_reg; -	u32 pp_on_reg_val; -	u32 pp_off_reg; -	u32 pp_off_reg_val; -	u32 pp_cycle_reg; -	u32 pp_cycle_reg_val; -	u32 pfit_reg; -	u32 pfit_reg_val; -	u16 terminator; -} __attribute__((packed)); - -struct lvds_dvo_timing { -	u16 clock;		/**< In 10khz */ -	u8 hactive_lo; -	u8 hblank_lo; -	u8 hblank_hi:4; -	u8 hactive_hi:4; -	u8 vactive_lo; -	u8 vblank_lo; -	u8 vblank_hi:4; -	u8 vactive_hi:4; -	u8 hsync_off_lo; -	u8 hsync_pulse_width; -	u8 vsync_pulse_width:4; -	u8 vsync_off:4; -	u8 rsvd0:6; -	u8 hsync_off_hi:2; -	u8 h_image; -	u8 v_image; -	u8 max_hv; -	u8 h_border; -	u8 v_border; -	u8 rsvd1:3; -	u8 digital:2; -	u8 vsync_positive:1; -	u8 hsync_positive:1; -	u8 rsvd2:1; -} __attribute__((packed)); - -struct lvds_pnp_id { -	u16 mfg_name; -	u16 product_code; -	u32 serial; -	u8 mfg_week; -	u8 mfg_year; -} __attribute__((packed)); - -struct bdb_lvds_lfp_data_entry { -	struct lvds_fp_timing fp_timing; -	struct lvds_dvo_timing dvo_timing; -	struct lvds_pnp_id pnp_id; -} __attribute__((packed)); - -struct bdb_lvds_lfp_data { -	struct bdb_lvds_lfp_data_entry data[16]; -} __attribute__((packed)); - -struct aimdb_header { -	char signature[16]; -	char oem_device[20]; -	u16 aimdb_version; -	u16 aimdb_header_size; -	u16 aimdb_size; -} __attribute__((packed)); - -struct aimdb_block { -	u8 aimdb_id; -	u16 aimdb_size; -} __attribute__((packed)); - -struct vch_panel_data { -	u16 fp_timing_offset; -	u8 fp_timing_size; -	u16 dvo_timing_offset; -	u8 dvo_timing_size; -	u16 text_fitting_offset; -	u8 text_fitting_size; -	u16 graphics_fitting_offset; -	u8 graphics_fitting_size; -} __attribute__((packed)); - -struct vch_bdb_22 { -	struct aimdb_block aimdb_block; -	struct vch_panel_data panels[16]; -} __attribute__((packed)); - -struct bdb_sdvo_lvds_options { -	u8 panel_backlight; -	u8 h40_set_panel_type; -	u8 panel_type; -	u8 ssc_clk_freq; -	u16 als_low_trip; -	u16 als_high_trip; -	u8 sclalarcoeff_tab_row_num; -	u8 sclalarcoeff_tab_row_size; -	u8 coefficient[8]; -	u8 panel_misc_bits_1; -	u8 panel_misc_bits_2; -	u8 panel_misc_bits_3; -	u8 panel_misc_bits_4; -} __attribute__((packed)); - - -extern bool psb_intel_init_bios(struct drm_device *dev); -extern void psb_intel_destroy_bios(struct drm_device *dev); - -/* - * Driver<->VBIOS interaction occurs through scratch bits in - * GR18 & SWF*. - */ - -/* GR18 bits are set on display switch and hotkey events */ -#define GR18_DRIVER_SWITCH_EN	(1<<7) /* 0: VBIOS control, 1: driver control */ -#define GR18_HOTKEY_MASK	0x78 /* See also SWF4 15:0 */ -#define   GR18_HK_NONE		(0x0<<3) -#define   GR18_HK_LFP_STRETCH	(0x1<<3) -#define   GR18_HK_TOGGLE_DISP	(0x2<<3) -#define   GR18_HK_DISP_SWITCH	(0x4<<3) /* see SWF14 15:0 for what to enable */ -#define   GR18_HK_POPUP_DISABLED (0x6<<3) -#define   GR18_HK_POPUP_ENABLED	(0x7<<3) -#define   GR18_HK_PFIT		(0x8<<3) -#define   GR18_HK_APM_CHANGE	(0xa<<3) -#define   GR18_HK_MULTIPLE	(0xc<<3) -#define GR18_USER_INT_EN	(1<<2) -#define GR18_A0000_FLUSH_EN	(1<<1) -#define GR18_SMM_EN		(1<<0) - -/* Set by driver, cleared by VBIOS */ -#define SWF00_YRES_SHIFT	16 -#define SWF00_XRES_SHIFT	0 -#define SWF00_RES_MASK		0xffff - -/* Set by VBIOS at boot time and driver at runtime */ -#define SWF01_TV2_FORMAT_SHIFT	8 -#define SWF01_TV1_FORMAT_SHIFT	0 -#define SWF01_TV_FORMAT_MASK	0xffff - -#define SWF10_VBIOS_BLC_I2C_EN	(1<<29) -#define SWF10_GTT_OVERRIDE_EN	(1<<28) -#define SWF10_LFP_DPMS_OVR	(1<<27) /* override DPMS on display switch */ -#define SWF10_ACTIVE_TOGGLE_LIST_MASK (7<<24) -#define   SWF10_OLD_TOGGLE	0x0 -#define   SWF10_TOGGLE_LIST_1	0x1 -#define   SWF10_TOGGLE_LIST_2	0x2 -#define   SWF10_TOGGLE_LIST_3	0x3 -#define   SWF10_TOGGLE_LIST_4	0x4 -#define SWF10_PANNING_EN	(1<<23) -#define SWF10_DRIVER_LOADED	(1<<22) -#define SWF10_EXTENDED_DESKTOP	(1<<21) -#define SWF10_EXCLUSIVE_MODE	(1<<20) -#define SWF10_OVERLAY_EN	(1<<19) -#define SWF10_PLANEB_HOLDOFF	(1<<18) -#define SWF10_PLANEA_HOLDOFF	(1<<17) -#define SWF10_VGA_HOLDOFF	(1<<16) -#define SWF10_ACTIVE_DISP_MASK	0xffff -#define   SWF10_PIPEB_LFP2	(1<<15) -#define   SWF10_PIPEB_EFP2	(1<<14) -#define   SWF10_PIPEB_TV2	(1<<13) -#define   SWF10_PIPEB_CRT2	(1<<12) -#define   SWF10_PIPEB_LFP	(1<<11) -#define   SWF10_PIPEB_EFP	(1<<10) -#define   SWF10_PIPEB_TV	(1<<9) -#define   SWF10_PIPEB_CRT	(1<<8) -#define   SWF10_PIPEA_LFP2	(1<<7) -#define   SWF10_PIPEA_EFP2	(1<<6) -#define   SWF10_PIPEA_TV2	(1<<5) -#define   SWF10_PIPEA_CRT2	(1<<4) -#define   SWF10_PIPEA_LFP	(1<<3) -#define   SWF10_PIPEA_EFP	(1<<2) -#define   SWF10_PIPEA_TV	(1<<1) -#define   SWF10_PIPEA_CRT	(1<<0) - -#define SWF11_MEMORY_SIZE_SHIFT	16 -#define SWF11_SV_TEST_EN	(1<<15) -#define SWF11_IS_AGP		(1<<14) -#define SWF11_DISPLAY_HOLDOFF	(1<<13) -#define SWF11_DPMS_REDUCED	(1<<12) -#define SWF11_IS_VBE_MODE	(1<<11) -#define SWF11_PIPEB_ACCESS	(1<<10) /* 0 here means pipe a */ -#define SWF11_DPMS_MASK		0x07 -#define   SWF11_DPMS_OFF	(1<<2) -#define   SWF11_DPMS_SUSPEND	(1<<1) -#define   SWF11_DPMS_STANDBY	(1<<0) -#define   SWF11_DPMS_ON		0 - -#define SWF14_GFX_PFIT_EN	(1<<31) -#define SWF14_TEXT_PFIT_EN	(1<<30) -#define SWF14_LID_STATUS_CLOSED	(1<<29) /* 0 here means open */ -#define SWF14_POPUP_EN		(1<<28) -#define SWF14_DISPLAY_HOLDOFF	(1<<27) -#define SWF14_DISP_DETECT_EN	(1<<26) -#define SWF14_DOCKING_STATUS_DOCKED (1<<25) /* 0 here means undocked */ -#define SWF14_DRIVER_STATUS	(1<<24) -#define SWF14_OS_TYPE_WIN9X	(1<<23) -#define SWF14_OS_TYPE_WINNT	(1<<22) -/* 21:19 rsvd */ -#define SWF14_PM_TYPE_MASK	0x00070000 -#define   SWF14_PM_ACPI_VIDEO	(0x4 << 16) -#define   SWF14_PM_ACPI		(0x3 << 16) -#define   SWF14_PM_APM_12	(0x2 << 16) -#define   SWF14_PM_APM_11	(0x1 << 16) -#define SWF14_HK_REQUEST_MASK	0x0000ffff /* see GR18 6:3 for event type */ -	  /* if GR18 indicates a display switch */ -#define   SWF14_DS_PIPEB_LFP2_EN (1<<15) -#define   SWF14_DS_PIPEB_EFP2_EN (1<<14) -#define   SWF14_DS_PIPEB_TV2_EN  (1<<13) -#define   SWF14_DS_PIPEB_CRT2_EN (1<<12) -#define   SWF14_DS_PIPEB_LFP_EN  (1<<11) -#define   SWF14_DS_PIPEB_EFP_EN  (1<<10) -#define   SWF14_DS_PIPEB_TV_EN	 (1<<9) -#define   SWF14_DS_PIPEB_CRT_EN  (1<<8) -#define   SWF14_DS_PIPEA_LFP2_EN (1<<7) -#define   SWF14_DS_PIPEA_EFP2_EN (1<<6) -#define   SWF14_DS_PIPEA_TV2_EN  (1<<5) -#define   SWF14_DS_PIPEA_CRT2_EN (1<<4) -#define   SWF14_DS_PIPEA_LFP_EN  (1<<3) -#define   SWF14_DS_PIPEA_EFP_EN  (1<<2) -#define   SWF14_DS_PIPEA_TV_EN	 (1<<1) -#define   SWF14_DS_PIPEA_CRT_EN  (1<<0) -	  /* if GR18 indicates a panel fitting request */ -#define   SWF14_PFIT_EN		(1<<0) /* 0 means disable */ -	  /* if GR18 indicates an APM change request */ -#define   SWF14_APM_HIBERNATE	0x4 -#define   SWF14_APM_SUSPEND	0x3 -#define   SWF14_APM_STANDBY	0x1 -#define   SWF14_APM_RESTORE	0x0 - -#endif /* _I830_BIOS_H_ */ diff --git a/drivers/staging/gma500/intel_i2c.c b/drivers/staging/gma500/intel_i2c.c deleted file mode 100644 index 51cbf65268e..00000000000 --- a/drivers/staging/gma500/intel_i2c.c +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Copyright © 2006-2007 Intel Corporation - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - * Authors: - *	Eric Anholt <eric@anholt.net> - */ - -#include <linux/i2c.h> -#include <linux/i2c-algo-bit.h> -#include <linux/export.h> - -#include "psb_drv.h" -#include "psb_intel_reg.h" - -/* - * Intel GPIO access functions - */ - -#define I2C_RISEFALL_TIME 20 - -static int get_clock(void *data) -{ -	struct psb_intel_i2c_chan *chan = data; -	struct drm_device *dev = chan->drm_dev; -	u32 val; - -	val = REG_READ(chan->reg); -	return (val & GPIO_CLOCK_VAL_IN) != 0; -} - -static int get_data(void *data) -{ -	struct psb_intel_i2c_chan *chan = data; -	struct drm_device *dev = chan->drm_dev; -	u32 val; - -	val = REG_READ(chan->reg); -	return (val & GPIO_DATA_VAL_IN) != 0; -} - -static void set_clock(void *data, int state_high) -{ -	struct psb_intel_i2c_chan *chan = data; -	struct drm_device *dev = chan->drm_dev; -	u32 reserved = 0, clock_bits; - -	/* On most chips, these bits must be preserved in software. */ -	reserved = -		    REG_READ(chan->reg) & (GPIO_DATA_PULLUP_DISABLE | -					   GPIO_CLOCK_PULLUP_DISABLE); - -	if (state_high) -		clock_bits = GPIO_CLOCK_DIR_IN | GPIO_CLOCK_DIR_MASK; -	else -		clock_bits = GPIO_CLOCK_DIR_OUT | GPIO_CLOCK_DIR_MASK | -		    GPIO_CLOCK_VAL_MASK; -	REG_WRITE(chan->reg, reserved | clock_bits); -	udelay(I2C_RISEFALL_TIME);	/* wait for the line to change state */ -} - -static void set_data(void *data, int state_high) -{ -	struct psb_intel_i2c_chan *chan = data; -	struct drm_device *dev = chan->drm_dev; -	u32 reserved = 0, data_bits; - -	/* On most chips, these bits must be preserved in software. */ -	reserved = -		    REG_READ(chan->reg) & (GPIO_DATA_PULLUP_DISABLE | -					   GPIO_CLOCK_PULLUP_DISABLE); - -	if (state_high) -		data_bits = GPIO_DATA_DIR_IN | GPIO_DATA_DIR_MASK; -	else -		data_bits = -		    GPIO_DATA_DIR_OUT | GPIO_DATA_DIR_MASK | -		    GPIO_DATA_VAL_MASK; - -	REG_WRITE(chan->reg, reserved | data_bits); -	udelay(I2C_RISEFALL_TIME);	/* wait for the line to change state */ -} - -/** - * psb_intel_i2c_create - instantiate an Intel i2c bus using the specified GPIO reg - * @dev: DRM device - * @output: driver specific output device - * @reg: GPIO reg to use - * @name: name for this bus - * - * Creates and registers a new i2c bus with the Linux i2c layer, for use - * in output probing and control (e.g. DDC or SDVO control functions). - * - * Possible values for @reg include: - *   %GPIOA - *   %GPIOB - *   %GPIOC - *   %GPIOD - *   %GPIOE - *   %GPIOF - *   %GPIOG - *   %GPIOH - * see PRM for details on how these different busses are used. - */ -struct psb_intel_i2c_chan *psb_intel_i2c_create(struct drm_device *dev, -					const u32 reg, const char *name) -{ -	struct psb_intel_i2c_chan *chan; - -	chan = kzalloc(sizeof(struct psb_intel_i2c_chan), GFP_KERNEL); -	if (!chan) -		goto out_free; - -	chan->drm_dev = dev; -	chan->reg = reg; -	snprintf(chan->adapter.name, I2C_NAME_SIZE, "intel drm %s", name); -	chan->adapter.owner = THIS_MODULE; -	chan->adapter.algo_data = &chan->algo; -	chan->adapter.dev.parent = &dev->pdev->dev; -	chan->algo.setsda = set_data; -	chan->algo.setscl = set_clock; -	chan->algo.getsda = get_data; -	chan->algo.getscl = get_clock; -	chan->algo.udelay = 20; -	chan->algo.timeout = usecs_to_jiffies(2200); -	chan->algo.data = chan; - -	i2c_set_adapdata(&chan->adapter, chan); - -	if (i2c_bit_add_bus(&chan->adapter)) -		goto out_free; - -	/* JJJ:  raise SCL and SDA? */ -	set_data(chan, 1); -	set_clock(chan, 1); -	udelay(20); - -	return chan; - -out_free: -	kfree(chan); -	return NULL; -} - -/** - * psb_intel_i2c_destroy - unregister and free i2c bus resources - * @output: channel to free - * - * Unregister the adapter from the i2c layer, then free the structure. - */ -void psb_intel_i2c_destroy(struct psb_intel_i2c_chan *chan) -{ -	if (!chan) -		return; - -	i2c_del_adapter(&chan->adapter); -	kfree(chan); -} diff --git a/drivers/staging/gma500/intel_opregion.c b/drivers/staging/gma500/intel_opregion.c deleted file mode 100644 index d946bc1b17b..00000000000 --- a/drivers/staging/gma500/intel_opregion.c +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 2010 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * FIXME: resolve with the i915 version - */ - -#include "psb_drv.h" - -struct opregion_header { -	u8 signature[16]; -	u32 size; -	u32 opregion_ver; -	u8 bios_ver[32]; -	u8 vbios_ver[16]; -	u8 driver_ver[16]; -	u32 mboxes; -	u8 reserved[164]; -} __packed; - -struct opregion_apci { -	/*FIXME: add it later*/ -} __packed; - -struct opregion_swsci { -	/*FIXME: add it later*/ -} __packed; - -struct opregion_acpi { -	/*FIXME: add it later*/ -} __packed; - -int gma_intel_opregion_init(struct drm_device *dev) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; -	u32 opregion_phy; -	void *base; -	u32 *lid_state; - -	dev_priv->lid_state = NULL; - -	pci_read_config_dword(dev->pdev, 0xfc, &opregion_phy); -	if (opregion_phy == 0) -		return -ENOTSUPP; - -	base = ioremap(opregion_phy, 8*1024); -	if (!base) -		return -ENOMEM; - -	lid_state = base + 0x01ac; - -	dev_priv->lid_state = lid_state; -	dev_priv->lid_last_state = readl(lid_state); -	return 0; -} - -int gma_intel_opregion_exit(struct drm_device *dev) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; -	if (dev_priv->lid_state) -		iounmap(dev_priv->lid_state); -	return 0; -} diff --git a/drivers/staging/gma500/mdfld_device.c b/drivers/staging/gma500/mdfld_device.c deleted file mode 100644 index f47aeb7a203..00000000000 --- a/drivers/staging/gma500/mdfld_device.c +++ /dev/null @@ -1,714 +0,0 @@ -/************************************************************************** - * Copyright (c) 2011, Intel Corporation. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - **************************************************************************/ - -#include <linux/backlight.h> -#include <drm/drmP.h> -#include <drm/drm.h> -#include "psb_reg.h" -#include "psb_intel_reg.h" -#include "psb_drm.h" -#include "psb_drv.h" -#include "mdfld_output.h" -#include "mdfld_dsi_output.h" -#include "mid_bios.h" - -/* - *	Provide the Medfield specific backlight management - */ - -#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE - -static int mdfld_brightness; -struct backlight_device *mdfld_backlight_device; - -static int mfld_set_brightness(struct backlight_device *bd) -{ -	struct drm_device *dev = bl_get_data(mdfld_backlight_device); -	struct drm_psb_private *dev_priv = dev->dev_private; -	int level = bd->props.brightness; - -	/* Percentage 1-100% being valid */ -	if (level < 1) -		level = 1; - -	if (gma_power_begin(dev, 0)) { -		/* Calculate and set the brightness value */ -		u32 adjusted_level; - -		/* Adjust the backlight level with the percent in -		 * dev_priv->blc_adj2; -		 */ -		adjusted_level = level * dev_priv->blc_adj2; -		adjusted_level = adjusted_level / 100; -#if 0 -#ifndef CONFIG_MDFLD_DSI_DPU -		if(!(dev_priv->dsr_fb_update & MDFLD_DSR_MIPI_CONTROL) &&  -			(dev_priv->dbi_panel_on || dev_priv->dbi_panel_on2)){ -			mdfld_dsi_dbi_exit_dsr(dev,MDFLD_DSR_MIPI_CONTROL, 0, 0); -			dev_dbg(dev->dev, "Out of DSR before set brightness to %d.\n",adjusted_level); -		} -#endif -		mdfld_dsi_brightness_control(dev, 0, adjusted_level); - -		if ((dev_priv->dbi_panel_on2) || (dev_priv->dpi_panel_on2)) -			mdfld_dsi_brightness_control(dev, 2, adjusted_level); -#endif -		gma_power_end(dev); -	} -	mdfld_brightness = level; -	return 0; -} - -int psb_get_brightness(struct backlight_device *bd) -{ -	/* return locally cached var instead of HW read (due to DPST etc.) */ -	/* FIXME: ideally return actual value in case firmware fiddled with -	   it */ -	return mdfld_brightness; -} - -static const struct backlight_ops mfld_ops = { -	.get_brightness = psb_get_brightness, -	.update_status  = mfld_set_brightness, -}; - -static int mdfld_backlight_init(struct drm_device *dev) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; -	struct backlight_properties props; -	memset(&props, 0, sizeof(struct backlight_properties)); -	props.max_brightness = 100; -	props.type = BACKLIGHT_PLATFORM; - -	mdfld_backlight_device = backlight_device_register("mfld-bl", -					NULL, (void *)dev, &mfld_ops, &props); -					 -	if (IS_ERR(mdfld_backlight_device)) -		return PTR_ERR(mdfld_backlight_device); - -	dev_priv->blc_adj1 = 100; -	dev_priv->blc_adj2 = 100; -	mdfld_backlight_device->props.brightness = 100; -	mdfld_backlight_device->props.max_brightness = 100; -	backlight_update_status(mdfld_backlight_device); -	dev_priv->backlight_device = mdfld_backlight_device; -	return 0; -} - -#endif - -/* - *	Provide the Medfield specific chip logic and low level methods for - *	power management. - */ - -static void mdfld_init_pm(struct drm_device *dev) -{ -	/* No work needed here yet */ -} - -/** - * mdfld_save_display_registers	-	save registers for pipe - * @dev: our device - * @pipe: pipe to save - * - * Save the pipe state of the device before we power it off. Keep everything - * we need to put it back again - */ -static int mdfld_save_display_registers(struct drm_device *dev, int pipe) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; -	int i; - -	/* register */ -	u32 dpll_reg = MRST_DPLL_A; -	u32 fp_reg = MRST_FPA0; -	u32 pipeconf_reg = PIPEACONF; -	u32 htot_reg = HTOTAL_A; -	u32 hblank_reg = HBLANK_A; -	u32 hsync_reg = HSYNC_A; -	u32 vtot_reg = VTOTAL_A; -	u32 vblank_reg = VBLANK_A; -	u32 vsync_reg = VSYNC_A; -	u32 pipesrc_reg = PIPEASRC; -	u32 dspstride_reg = DSPASTRIDE; -	u32 dsplinoff_reg = DSPALINOFF; -	u32 dsptileoff_reg = DSPATILEOFF; -	u32 dspsize_reg = DSPASIZE; -	u32 dsppos_reg = DSPAPOS; -	u32 dspsurf_reg = DSPASURF; -	u32 mipi_reg = MIPI; -	u32 dspcntr_reg = DSPACNTR; -	u32 dspstatus_reg = PIPEASTAT; -	u32 palette_reg = PALETTE_A; - -	/* pointer to values */ -	u32 *dpll_val = &dev_priv->saveDPLL_A; -	u32 *fp_val = &dev_priv->saveFPA0; -	u32 *pipeconf_val = &dev_priv->savePIPEACONF; -	u32 *htot_val = &dev_priv->saveHTOTAL_A; -	u32 *hblank_val = &dev_priv->saveHBLANK_A; -	u32 *hsync_val = &dev_priv->saveHSYNC_A; -	u32 *vtot_val = &dev_priv->saveVTOTAL_A; -	u32 *vblank_val = &dev_priv->saveVBLANK_A; -	u32 *vsync_val = &dev_priv->saveVSYNC_A; -	u32 *pipesrc_val = &dev_priv->savePIPEASRC; -	u32 *dspstride_val = &dev_priv->saveDSPASTRIDE; -	u32 *dsplinoff_val = &dev_priv->saveDSPALINOFF; -	u32 *dsptileoff_val = &dev_priv->saveDSPATILEOFF; -	u32 *dspsize_val = &dev_priv->saveDSPASIZE; -	u32 *dsppos_val = &dev_priv->saveDSPAPOS; -	u32 *dspsurf_val = &dev_priv->saveDSPASURF; -	u32 *mipi_val = &dev_priv->saveMIPI; -	u32 *dspcntr_val = &dev_priv->saveDSPACNTR; -	u32 *dspstatus_val = &dev_priv->saveDSPASTATUS; -	u32 *palette_val = dev_priv->save_palette_a; - -	switch (pipe) { -	case 0: -		break; -	case 1: -		/* register */ -		dpll_reg = MDFLD_DPLL_B; -		fp_reg = MDFLD_DPLL_DIV0; -		pipeconf_reg = PIPEBCONF; -		htot_reg = HTOTAL_B; -		hblank_reg = HBLANK_B; -		hsync_reg = HSYNC_B; -		vtot_reg = VTOTAL_B; -		vblank_reg = VBLANK_B; -		vsync_reg = VSYNC_B; -		pipesrc_reg = PIPEBSRC; -		dspstride_reg = DSPBSTRIDE; -		dsplinoff_reg = DSPBLINOFF; -		dsptileoff_reg = DSPBTILEOFF; -		dspsize_reg = DSPBSIZE; -		dsppos_reg = DSPBPOS; -		dspsurf_reg = DSPBSURF; -		dspcntr_reg = DSPBCNTR; -		dspstatus_reg = PIPEBSTAT; -		palette_reg = PALETTE_B; - -		/* values */ -		dpll_val = &dev_priv->saveDPLL_B; -		fp_val = &dev_priv->saveFPB0; -		pipeconf_val = &dev_priv->savePIPEBCONF; -		htot_val = &dev_priv->saveHTOTAL_B; -		hblank_val = &dev_priv->saveHBLANK_B; -		hsync_val = &dev_priv->saveHSYNC_B; -		vtot_val = &dev_priv->saveVTOTAL_B; -		vblank_val = &dev_priv->saveVBLANK_B; -		vsync_val = &dev_priv->saveVSYNC_B; -		pipesrc_val = &dev_priv->savePIPEBSRC; -		dspstride_val = &dev_priv->saveDSPBSTRIDE; -		dsplinoff_val = &dev_priv->saveDSPBLINOFF; -		dsptileoff_val = &dev_priv->saveDSPBTILEOFF; -		dspsize_val = &dev_priv->saveDSPBSIZE; -		dsppos_val = &dev_priv->saveDSPBPOS; -		dspsurf_val = &dev_priv->saveDSPBSURF; -		dspcntr_val = &dev_priv->saveDSPBCNTR; -		dspstatus_val = &dev_priv->saveDSPBSTATUS; -		palette_val = dev_priv->save_palette_b; -		break; -	case 2: -		/* register */ -		pipeconf_reg = PIPECCONF; -		htot_reg = HTOTAL_C; -		hblank_reg = HBLANK_C; -		hsync_reg = HSYNC_C; -		vtot_reg = VTOTAL_C; -		vblank_reg = VBLANK_C; -		vsync_reg = VSYNC_C; -		pipesrc_reg = PIPECSRC; -		dspstride_reg = DSPCSTRIDE; -		dsplinoff_reg = DSPCLINOFF; -		dsptileoff_reg = DSPCTILEOFF; -		dspsize_reg = DSPCSIZE; -		dsppos_reg = DSPCPOS; -		dspsurf_reg = DSPCSURF; -		mipi_reg = MIPI_C; -		dspcntr_reg = DSPCCNTR; -		dspstatus_reg = PIPECSTAT; -		palette_reg = PALETTE_C; - -		/* pointer to values */ -		pipeconf_val = &dev_priv->savePIPECCONF; -		htot_val = &dev_priv->saveHTOTAL_C; -		hblank_val = &dev_priv->saveHBLANK_C; -		hsync_val = &dev_priv->saveHSYNC_C; -		vtot_val = &dev_priv->saveVTOTAL_C; -		vblank_val = &dev_priv->saveVBLANK_C; -		vsync_val = &dev_priv->saveVSYNC_C; -		pipesrc_val = &dev_priv->savePIPECSRC; -		dspstride_val = &dev_priv->saveDSPCSTRIDE; -		dsplinoff_val = &dev_priv->saveDSPCLINOFF; -		dsptileoff_val = &dev_priv->saveDSPCTILEOFF; -		dspsize_val = &dev_priv->saveDSPCSIZE; -		dsppos_val = &dev_priv->saveDSPCPOS; -		dspsurf_val = &dev_priv->saveDSPCSURF; -		mipi_val = &dev_priv->saveMIPI_C; -		dspcntr_val = &dev_priv->saveDSPCCNTR; -		dspstatus_val = &dev_priv->saveDSPCSTATUS; -		palette_val = dev_priv->save_palette_c; -		break; -	default: -		DRM_ERROR("%s, invalid pipe number.\n", __func__); -		return -EINVAL; -	} - -	/* Pipe & plane A info */ -	*dpll_val = PSB_RVDC32(dpll_reg); -	*fp_val = PSB_RVDC32(fp_reg); -	*pipeconf_val = PSB_RVDC32(pipeconf_reg); -	*htot_val = PSB_RVDC32(htot_reg); -	*hblank_val = PSB_RVDC32(hblank_reg); -	*hsync_val = PSB_RVDC32(hsync_reg); -	*vtot_val = PSB_RVDC32(vtot_reg); -	*vblank_val = PSB_RVDC32(vblank_reg); -	*vsync_val = PSB_RVDC32(vsync_reg); -	*pipesrc_val = PSB_RVDC32(pipesrc_reg); -	*dspstride_val = PSB_RVDC32(dspstride_reg); -	*dsplinoff_val = PSB_RVDC32(dsplinoff_reg); -	*dsptileoff_val = PSB_RVDC32(dsptileoff_reg); -	*dspsize_val = PSB_RVDC32(dspsize_reg); -	*dsppos_val = PSB_RVDC32(dsppos_reg); -	*dspsurf_val = PSB_RVDC32(dspsurf_reg); -	*dspcntr_val = PSB_RVDC32(dspcntr_reg); -	*dspstatus_val = PSB_RVDC32(dspstatus_reg); - -	/*save palette (gamma) */ -	for (i = 0; i < 256; i++) -		palette_val[i] = PSB_RVDC32(palette_reg + (i<<2)); - -	if (pipe == 1) { -		dev_priv->savePFIT_CONTROL = PSB_RVDC32(PFIT_CONTROL); -		dev_priv->savePFIT_PGM_RATIOS = PSB_RVDC32(PFIT_PGM_RATIOS); -		dev_priv->saveHDMIPHYMISCCTL = PSB_RVDC32(HDMIPHYMISCCTL); -		dev_priv->saveHDMIB_CONTROL = PSB_RVDC32(HDMIB_CONTROL); -		return 0; -	} -	*mipi_val = PSB_RVDC32(mipi_reg); -	return 0; -} - -/** - * mdfld_save_cursor_overlay_registers	-	save cursor overlay info - * @dev: our device - * - * Save the cursor and overlay register state - */ -static int mdfld_save_cursor_overlay_registers(struct drm_device *dev) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; - -	/* Save cursor regs */ -	dev_priv->saveDSPACURSOR_CTRL = PSB_RVDC32(CURACNTR); -	dev_priv->saveDSPACURSOR_BASE = PSB_RVDC32(CURABASE); -	dev_priv->saveDSPACURSOR_POS = PSB_RVDC32(CURAPOS); - -	dev_priv->saveDSPBCURSOR_CTRL = PSB_RVDC32(CURBCNTR); -	dev_priv->saveDSPBCURSOR_BASE = PSB_RVDC32(CURBBASE); -	dev_priv->saveDSPBCURSOR_POS = PSB_RVDC32(CURBPOS); - -	dev_priv->saveDSPCCURSOR_CTRL = PSB_RVDC32(CURCCNTR); -	dev_priv->saveDSPCCURSOR_BASE = PSB_RVDC32(CURCBASE); -	dev_priv->saveDSPCCURSOR_POS = PSB_RVDC32(CURCPOS); - -	/* HW overlay */ -	dev_priv->saveOV_OVADD = PSB_RVDC32(OV_OVADD); -	dev_priv->saveOV_OGAMC0 = PSB_RVDC32(OV_OGAMC0); -	dev_priv->saveOV_OGAMC1 = PSB_RVDC32(OV_OGAMC1); -	dev_priv->saveOV_OGAMC2 = PSB_RVDC32(OV_OGAMC2); -	dev_priv->saveOV_OGAMC3 = PSB_RVDC32(OV_OGAMC3); -	dev_priv->saveOV_OGAMC4 = PSB_RVDC32(OV_OGAMC4); -	dev_priv->saveOV_OGAMC5 = PSB_RVDC32(OV_OGAMC5); - -	dev_priv->saveOV_OVADD_C = PSB_RVDC32(OV_OVADD + OV_C_OFFSET); -	dev_priv->saveOV_OGAMC0_C = PSB_RVDC32(OV_OGAMC0 + OV_C_OFFSET); -	dev_priv->saveOV_OGAMC1_C = PSB_RVDC32(OV_OGAMC1 + OV_C_OFFSET); -	dev_priv->saveOV_OGAMC2_C = PSB_RVDC32(OV_OGAMC2 + OV_C_OFFSET); -	dev_priv->saveOV_OGAMC3_C = PSB_RVDC32(OV_OGAMC3 + OV_C_OFFSET); -	dev_priv->saveOV_OGAMC4_C = PSB_RVDC32(OV_OGAMC4 + OV_C_OFFSET); -	dev_priv->saveOV_OGAMC5_C = PSB_RVDC32(OV_OGAMC5 + OV_C_OFFSET); - -	return 0; -} -/* - * mdfld_restore_display_registers	-	restore the state of a pipe - * @dev: our device - * @pipe: the pipe to restore - * - * Restore the state of a pipe to that which was saved by the register save - * functions. - */ -static int mdfld_restore_display_registers(struct drm_device *dev, int pipe) -{ -	/* To get  panel out of ULPS mode */ -	struct drm_psb_private *dev_priv = dev->dev_private; -	struct mdfld_dsi_config *dsi_config = NULL; -	u32 i = 0; -	u32 dpll = 0; -	u32 timeout = 0; -	u32 reg_offset = 0; - -	/* register */ -	u32 dpll_reg = MRST_DPLL_A; -	u32 fp_reg = MRST_FPA0; -	u32 pipeconf_reg = PIPEACONF; -	u32 htot_reg = HTOTAL_A; -	u32 hblank_reg = HBLANK_A; -	u32 hsync_reg = HSYNC_A; -	u32 vtot_reg = VTOTAL_A; -	u32 vblank_reg = VBLANK_A; -	u32 vsync_reg = VSYNC_A; -	u32 pipesrc_reg = PIPEASRC; -	u32 dspstride_reg = DSPASTRIDE; -	u32 dsplinoff_reg = DSPALINOFF; -	u32 dsptileoff_reg = DSPATILEOFF; -	u32 dspsize_reg = DSPASIZE; -	u32 dsppos_reg = DSPAPOS; -	u32 dspsurf_reg = DSPASURF; -	u32 dspstatus_reg = PIPEASTAT; -	u32 mipi_reg = MIPI; -	u32 dspcntr_reg = DSPACNTR; -	u32 palette_reg = PALETTE_A; - -	/* values */ -	u32 dpll_val = dev_priv->saveDPLL_A & ~DPLL_VCO_ENABLE; -	u32 fp_val = dev_priv->saveFPA0; -	u32 pipeconf_val = dev_priv->savePIPEACONF; -	u32 htot_val = dev_priv->saveHTOTAL_A; -	u32 hblank_val = dev_priv->saveHBLANK_A; -	u32 hsync_val = dev_priv->saveHSYNC_A; -	u32 vtot_val = dev_priv->saveVTOTAL_A; -	u32 vblank_val = dev_priv->saveVBLANK_A; -	u32 vsync_val = dev_priv->saveVSYNC_A; -	u32 pipesrc_val = dev_priv->savePIPEASRC; -	u32 dspstride_val = dev_priv->saveDSPASTRIDE; -	u32 dsplinoff_val = dev_priv->saveDSPALINOFF; -	u32 dsptileoff_val = dev_priv->saveDSPATILEOFF; -	u32 dspsize_val = dev_priv->saveDSPASIZE; -	u32 dsppos_val = dev_priv->saveDSPAPOS; -	u32 dspsurf_val = dev_priv->saveDSPASURF; -	u32 dspstatus_val = dev_priv->saveDSPASTATUS; -	u32 mipi_val = dev_priv->saveMIPI; -	u32 dspcntr_val = dev_priv->saveDSPACNTR; -	u32 *palette_val = dev_priv->save_palette_a; - -	switch (pipe) { -	case 0: -		dsi_config = dev_priv->dsi_configs[0]; -		break; -	case 1: -		/* register */ -		dpll_reg = MDFLD_DPLL_B; -		fp_reg = MDFLD_DPLL_DIV0; -		pipeconf_reg = PIPEBCONF; -		htot_reg = HTOTAL_B; -		hblank_reg = HBLANK_B; -		hsync_reg = HSYNC_B; -		vtot_reg = VTOTAL_B; -		vblank_reg = VBLANK_B; -		vsync_reg = VSYNC_B; -		pipesrc_reg = PIPEBSRC; -		dspstride_reg = DSPBSTRIDE; -		dsplinoff_reg = DSPBLINOFF; -		dsptileoff_reg = DSPBTILEOFF; -		dspsize_reg = DSPBSIZE; -		dsppos_reg = DSPBPOS; -		dspsurf_reg = DSPBSURF; -		dspcntr_reg = DSPBCNTR; -		palette_reg = PALETTE_B; -		dspstatus_reg = PIPEBSTAT; - -		/* values */ -		dpll_val = dev_priv->saveDPLL_B & ~DPLL_VCO_ENABLE; -		fp_val = dev_priv->saveFPB0; -		pipeconf_val = dev_priv->savePIPEBCONF; -		htot_val = dev_priv->saveHTOTAL_B; -		hblank_val = dev_priv->saveHBLANK_B; -		hsync_val = dev_priv->saveHSYNC_B; -		vtot_val = dev_priv->saveVTOTAL_B; -		vblank_val = dev_priv->saveVBLANK_B; -		vsync_val = dev_priv->saveVSYNC_B; -		pipesrc_val = dev_priv->savePIPEBSRC; -		dspstride_val = dev_priv->saveDSPBSTRIDE; -		dsplinoff_val = dev_priv->saveDSPBLINOFF; -		dsptileoff_val = dev_priv->saveDSPBTILEOFF; -		dspsize_val = dev_priv->saveDSPBSIZE; -		dsppos_val = dev_priv->saveDSPBPOS; -		dspsurf_val = dev_priv->saveDSPBSURF; -		dspcntr_val = dev_priv->saveDSPBCNTR; -		dspstatus_val = dev_priv->saveDSPBSTATUS; -		palette_val = dev_priv->save_palette_b; -		break; -	case 2: -		reg_offset = MIPIC_REG_OFFSET; - -		/* register */ -		pipeconf_reg = PIPECCONF; -		htot_reg = HTOTAL_C; -		hblank_reg = HBLANK_C; -		hsync_reg = HSYNC_C; -		vtot_reg = VTOTAL_C; -		vblank_reg = VBLANK_C; -		vsync_reg = VSYNC_C; -		pipesrc_reg = PIPECSRC; -		dspstride_reg = DSPCSTRIDE; -		dsplinoff_reg = DSPCLINOFF; -		dsptileoff_reg = DSPCTILEOFF; -		dspsize_reg = DSPCSIZE; -		dsppos_reg = DSPCPOS; -		dspsurf_reg = DSPCSURF; -		mipi_reg = MIPI_C; -		dspcntr_reg = DSPCCNTR; -		palette_reg = PALETTE_C; -		dspstatus_reg = PIPECSTAT; - -		/* values */ -		pipeconf_val = dev_priv->savePIPECCONF; -		htot_val = dev_priv->saveHTOTAL_C; -		hblank_val = dev_priv->saveHBLANK_C; -		hsync_val = dev_priv->saveHSYNC_C; -		vtot_val = dev_priv->saveVTOTAL_C; -		vblank_val = dev_priv->saveVBLANK_C; -		vsync_val = dev_priv->saveVSYNC_C; -		pipesrc_val = dev_priv->savePIPECSRC; -		dspstride_val = dev_priv->saveDSPCSTRIDE; -		dsplinoff_val = dev_priv->saveDSPCLINOFF; -		dsptileoff_val = dev_priv->saveDSPCTILEOFF; -		dspsize_val = dev_priv->saveDSPCSIZE; -		dsppos_val = dev_priv->saveDSPCPOS; -		dspsurf_val = dev_priv->saveDSPCSURF; -		dspstatus_val = dev_priv->saveDSPCSTATUS; -		mipi_val = dev_priv->saveMIPI_C; -		dspcntr_val = dev_priv->saveDSPCCNTR; -		palette_val = dev_priv->save_palette_c; - -		dsi_config = dev_priv->dsi_configs[1]; -		break; -	default: -		DRM_ERROR("%s, invalid pipe number.\n", __func__); -		return -EINVAL; -	} - -	/* Make sure VGA plane is off. it initializes to on after reset!*/ -	PSB_WVDC32(0x80000000, VGACNTRL); -	if (pipe == 1) { -		PSB_WVDC32(dpll_val & ~DPLL_VCO_ENABLE, dpll_reg); -		PSB_RVDC32(dpll_reg); - -		PSB_WVDC32(fp_val, fp_reg); -	} else { -		dpll = PSB_RVDC32(dpll_reg); - -		if (!(dpll & DPLL_VCO_ENABLE)) { - -			/* When ungating power of DPLL, needs to wait 0.5us before enable the VCO */ -			if (dpll & MDFLD_PWR_GATE_EN) { -				dpll &= ~MDFLD_PWR_GATE_EN; -				PSB_WVDC32(dpll, dpll_reg); -				udelay(500);	/* FIXME: 1 ? */ -			} - -			PSB_WVDC32(fp_val, fp_reg); -			PSB_WVDC32(dpll_val, dpll_reg); -			/* FIXME_MDFLD PO - change 500 to 1 after PO */ -			udelay(500); - -			dpll_val |= DPLL_VCO_ENABLE; -			PSB_WVDC32(dpll_val, dpll_reg); -			PSB_RVDC32(dpll_reg); - -			/* wait for DSI PLL to lock */ -			while ((timeout < 20000) && !(PSB_RVDC32(pipeconf_reg) & PIPECONF_DSIPLL_LOCK)) { -				udelay(150); -				timeout++; -			} - -			if (timeout == 20000) { -				DRM_ERROR("%s, can't lock DSIPLL.\n", -							__func__); -				return -EINVAL; -			} -		} -	} -	/* Restore mode */ -	PSB_WVDC32(htot_val, htot_reg); -	PSB_WVDC32(hblank_val, hblank_reg); -	PSB_WVDC32(hsync_val, hsync_reg); -	PSB_WVDC32(vtot_val, vtot_reg); -	PSB_WVDC32(vblank_val, vblank_reg); -	PSB_WVDC32(vsync_val, vsync_reg); -	PSB_WVDC32(pipesrc_val, pipesrc_reg); -	PSB_WVDC32(dspstatus_val, dspstatus_reg); - -	/* Set up the plane */ -	PSB_WVDC32(dspstride_val, dspstride_reg); -	PSB_WVDC32(dsplinoff_val, dsplinoff_reg); -	PSB_WVDC32(dsptileoff_val, dsptileoff_reg); -	PSB_WVDC32(dspsize_val, dspsize_reg); -	PSB_WVDC32(dsppos_val, dsppos_reg); -	PSB_WVDC32(dspsurf_val, dspsurf_reg); - -	if (pipe == 1) { -		PSB_WVDC32(dev_priv->savePFIT_CONTROL, PFIT_CONTROL); -		PSB_WVDC32(dev_priv->savePFIT_PGM_RATIOS, PFIT_PGM_RATIOS); -		PSB_WVDC32(dev_priv->saveHDMIPHYMISCCTL, HDMIPHYMISCCTL); -		PSB_WVDC32(dev_priv->saveHDMIB_CONTROL, HDMIB_CONTROL); - -	} else { -		/* Set up pipe related registers */ -		PSB_WVDC32(mipi_val, mipi_reg); -		/* Setup MIPI adapter + MIPI IP registers */ -		mdfld_dsi_controller_init(dsi_config, pipe); -		msleep(20); -	} -	/* Enable the plane */ -	PSB_WVDC32(dspcntr_val, dspcntr_reg); -	msleep(20); -	/* Enable the pipe */ -	PSB_WVDC32(pipeconf_val, pipeconf_reg); - -	for (i = 0; i < 256; i++) -		PSB_WVDC32(palette_val[i], palette_reg + (i<<2)); -	if (pipe == 1) -		return 0; -	if (!mdfld_panel_dpi(dev)) -		mdfld_enable_te(dev, pipe); -	return 0; -} - -/** - * mdfld_restore_cursor_overlay_registers	-	restore cursor - * @dev: our device - * - * Restore the cursor and overlay state that was saved earlier - */ -static int mdfld_restore_cursor_overlay_registers(struct drm_device *dev) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; - -	/* Enable Cursor A */ -	PSB_WVDC32(dev_priv->saveDSPACURSOR_CTRL, CURACNTR); -	PSB_WVDC32(dev_priv->saveDSPACURSOR_POS, CURAPOS); -	PSB_WVDC32(dev_priv->saveDSPACURSOR_BASE, CURABASE); - -	PSB_WVDC32(dev_priv->saveDSPBCURSOR_CTRL, CURBCNTR); -	PSB_WVDC32(dev_priv->saveDSPBCURSOR_POS, CURBPOS); -	PSB_WVDC32(dev_priv->saveDSPBCURSOR_BASE, CURBBASE); - -	PSB_WVDC32(dev_priv->saveDSPCCURSOR_CTRL, CURCCNTR); -	PSB_WVDC32(dev_priv->saveDSPCCURSOR_POS, CURCPOS); -	PSB_WVDC32(dev_priv->saveDSPCCURSOR_BASE, CURCBASE); - -	/* Restore HW overlay */ -	PSB_WVDC32(dev_priv->saveOV_OVADD, OV_OVADD); -	PSB_WVDC32(dev_priv->saveOV_OGAMC0, OV_OGAMC0); -	PSB_WVDC32(dev_priv->saveOV_OGAMC1, OV_OGAMC1); -	PSB_WVDC32(dev_priv->saveOV_OGAMC2, OV_OGAMC2); -	PSB_WVDC32(dev_priv->saveOV_OGAMC3, OV_OGAMC3); -	PSB_WVDC32(dev_priv->saveOV_OGAMC4, OV_OGAMC4); -	PSB_WVDC32(dev_priv->saveOV_OGAMC5, OV_OGAMC5); - -	PSB_WVDC32(dev_priv->saveOV_OVADD_C, OV_OVADD + OV_C_OFFSET); -	PSB_WVDC32(dev_priv->saveOV_OGAMC0_C, OV_OGAMC0 + OV_C_OFFSET); -	PSB_WVDC32(dev_priv->saveOV_OGAMC1_C, OV_OGAMC1 + OV_C_OFFSET); -	PSB_WVDC32(dev_priv->saveOV_OGAMC2_C, OV_OGAMC2 + OV_C_OFFSET); -	PSB_WVDC32(dev_priv->saveOV_OGAMC3_C, OV_OGAMC3 + OV_C_OFFSET); -	PSB_WVDC32(dev_priv->saveOV_OGAMC4_C, OV_OGAMC4 + OV_C_OFFSET); -	PSB_WVDC32(dev_priv->saveOV_OGAMC5_C, OV_OGAMC5 + OV_C_OFFSET); - -	return 0; -} - -/** - *	mdfld_save_display_registers	-	save registers lost on suspend - *	@dev: our DRM device - * - *	Save the state we need in order to be able to restore the interface - *	upon resume from suspend - */ -static int mdfld_save_registers(struct drm_device *dev) -{ -	/* FIXME: We need to shut down panels here if using them -	   and once the right bits are merged */ -	mdfld_save_cursor_overlay_registers(dev); -	mdfld_save_display_registers(dev, 0); -	mdfld_save_display_registers(dev, 0); -	mdfld_save_display_registers(dev, 2); -	mdfld_save_display_registers(dev, 1); -	mdfld_disable_crtc(dev, 0); -	mdfld_disable_crtc(dev, 2); -	mdfld_disable_crtc(dev, 1); -	return 0; -} - -/** - *	mdfld_restore_display_registers	-	restore lost register state - *	@dev: our DRM device - * - *	Restore register state that was lost during suspend and resume. - */ -static int mdfld_restore_registers(struct drm_device *dev) -{ -	mdfld_restore_display_registers(dev, 1); -	mdfld_restore_display_registers(dev, 0); -	mdfld_restore_display_registers(dev, 2); -	mdfld_restore_cursor_overlay_registers(dev); -	return 0; -} - -static int mdfld_power_down(struct drm_device *dev) -{ -	/* FIXME */ -	return 0; -} - -static int mdfld_power_up(struct drm_device *dev) -{ -	/* FIXME */ -	return 0; -} - -const struct psb_ops mdfld_chip_ops = { -	.name = "Medfield", -	.accel_2d = 0, -	.pipes = 3, -	.crtcs = 2, -	.sgx_offset = MRST_SGX_OFFSET, - -	.chip_setup = mid_chip_setup, - -	.crtc_helper = &mdfld_helper_funcs, -	.crtc_funcs = &mdfld_intel_crtc_funcs, - -	.output_init = mdfld_output_init, - -#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE -	.backlight_init = mdfld_backlight_init, -#endif - -	.init_pm = mdfld_init_pm, -	.save_regs = mdfld_save_registers, -	.restore_regs = mdfld_restore_registers, -	.power_down = mdfld_power_down, -	.power_up = mdfld_power_up, -}; - diff --git a/drivers/staging/gma500/mdfld_dsi_dbi.c b/drivers/staging/gma500/mdfld_dsi_dbi.c deleted file mode 100644 index fd211f3467c..00000000000 --- a/drivers/staging/gma500/mdfld_dsi_dbi.c +++ /dev/null @@ -1,761 +0,0 @@ -/* - * Copyright © 2010 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Authors: - *  jim liu <jim.liu@intel.com> - *  Jackie Li<yaodong.li@intel.com> - */ - -#include "mdfld_dsi_dbi.h" -#include "mdfld_dsi_dbi_dpu.h" -#include "mdfld_dsi_pkg_sender.h" - -#include "power.h" -#include <linux/pm_runtime.h> - -int enable_gfx_rtpm; - -extern struct drm_device *gpDrmDevice; -extern int gfxrtdelay; -int enter_dsr; -struct mdfld_dsi_dbi_output *gdbi_output; -extern bool gbgfxsuspended; -extern int enable_gfx_rtpm; -extern int gfxrtdelay; - -#define MDFLD_DSR_MAX_IDLE_COUNT	2 - -/* - * set refreshing area - */ -int mdfld_dsi_dbi_update_area(struct mdfld_dsi_dbi_output *dbi_output, -				u16 x1, u16 y1, u16 x2, u16 y2) -{ -	struct mdfld_dsi_pkg_sender *sender = -		mdfld_dsi_encoder_get_pkg_sender(&dbi_output->base); -	u8 param[4]; -	u8 cmd; -	int err; - -	if (!sender) { -		WARN_ON(1); -		return -EINVAL; -	} - -	/* Set column */ -	cmd = DCS_SET_COLUMN_ADDRESS; -	param[0] = x1 >> 8; -	param[1] = x1; -	param[2] = x2 >> 8; -	param[3] = x2; - -	err = mdfld_dsi_send_dcs(sender, -				 cmd, -				 param, -				 4, -				 CMD_DATA_SRC_SYSTEM_MEM, -				 MDFLD_DSI_QUEUE_PACKAGE); -	if (err) { -		dev_err(sender->dev->dev, "DCS 0x%x sent failed\n", cmd); -		goto err_out; -	} - -	/* Set page */ -	cmd = DCS_SET_PAGE_ADDRESS; -	param[0] = y1 >> 8; -	param[1] = y1; -	param[2] = y2 >> 8; -	param[3] = y2; - -	err = mdfld_dsi_send_dcs(sender, -				 cmd, -				 param, -				 4, -				 CMD_DATA_SRC_SYSTEM_MEM, -				 MDFLD_DSI_QUEUE_PACKAGE); -	if (err) { -		dev_err(sender->dev->dev, "DCS 0x%x sent failed\n", cmd); -		goto err_out; -	} - -	/*update screen*/ -	err = mdfld_dsi_send_dcs(sender, -				 write_mem_start, -				 NULL, -				 0, -				 CMD_DATA_SRC_PIPE, -				 MDFLD_DSI_QUEUE_PACKAGE); -	if (err) { -		dev_err(sender->dev->dev, "DCS 0x%x sent failed\n", cmd); -		goto err_out; -	} -	mdfld_dsi_cmds_kick_out(sender); -err_out: -	return err; -} - -/* - * set panel's power state - */ -int mdfld_dsi_dbi_update_power(struct mdfld_dsi_dbi_output *dbi_output, -								int mode) -{ -	struct drm_device *dev = dbi_output->dev; -	struct mdfld_dsi_pkg_sender *sender = -		mdfld_dsi_encoder_get_pkg_sender(&dbi_output->base); -	u8 param = 0; -	u32 err = 0; - -	if (!sender) { -		WARN_ON(1); -		return -EINVAL; -	} - -	if (mode == DRM_MODE_DPMS_ON) { -		/* Exit sleep mode */ -		err = mdfld_dsi_send_dcs(sender, -					 DCS_EXIT_SLEEP_MODE, -					 NULL, -					 0, -					 CMD_DATA_SRC_SYSTEM_MEM, -					 MDFLD_DSI_QUEUE_PACKAGE); -		if (err) { -			dev_err(dev->dev, "DCS 0x%x sent failed\n", -						DCS_EXIT_SLEEP_MODE); -			goto power_err; -		} - -		/* Set display on */ -		err = mdfld_dsi_send_dcs(sender, -					 DCS_SET_DISPLAY_ON, -					 NULL, -					 0, -					 CMD_DATA_SRC_SYSTEM_MEM, -					 MDFLD_DSI_QUEUE_PACKAGE); -		if (err) { -			dev_err(dev->dev, "DCS 0x%x sent failed\n", -							DCS_SET_DISPLAY_ON); -			goto power_err; -		} - -		/* set tear effect on */ -		err = mdfld_dsi_send_dcs(sender, -					 DCS_SET_TEAR_ON, -					 ¶m, -					 1, -					 CMD_DATA_SRC_SYSTEM_MEM, -					 MDFLD_DSI_QUEUE_PACKAGE); -		if (err) { -			dev_err(dev->dev, "DCS 0x%x sent failed\n", -							set_tear_on); -			goto power_err; -		} - -		/** -		 * FIXME: remove this later -		 */ -		err = mdfld_dsi_send_dcs(sender, -					 DCS_WRITE_MEM_START, -					 NULL, -					 0, -					 CMD_DATA_SRC_PIPE, -					 MDFLD_DSI_QUEUE_PACKAGE); -		if (err) { -			dev_err(dev->dev, "DCS 0x%x sent failed\n", -						DCS_WRITE_MEM_START); -			goto power_err; -		} -	} else { -		/* Set tear effect off */ -		err = mdfld_dsi_send_dcs(sender, -					 DCS_SET_TEAR_OFF, -					 NULL, -					 0, -					 CMD_DATA_SRC_SYSTEM_MEM, -					 MDFLD_DSI_QUEUE_PACKAGE); -		if (err) { -			dev_err(dev->dev, "DCS 0x%x sent failed\n", -							DCS_SET_TEAR_OFF); -			goto power_err; -		} - -		/* Turn display off */ -		err = mdfld_dsi_send_dcs(sender, -					 DCS_SET_DISPLAY_OFF, -					 NULL, -					 0, -					 CMD_DATA_SRC_SYSTEM_MEM, -					 MDFLD_DSI_QUEUE_PACKAGE); -		if (err) { -			dev_err(dev->dev, "DCS 0x%x sent failed\n", -						DCS_SET_DISPLAY_OFF); -			goto power_err; -		} - -		/* Now enter sleep mode */ -		err = mdfld_dsi_send_dcs(sender, -					 DCS_ENTER_SLEEP_MODE, -					 NULL, -					 0, -					 CMD_DATA_SRC_SYSTEM_MEM, -					 MDFLD_DSI_QUEUE_PACKAGE); -		if (err) { -			dev_err(dev->dev, "DCS 0x%x sent failed\n", -							DCS_ENTER_SLEEP_MODE); -			goto power_err; -		} -	} -	mdfld_dsi_cmds_kick_out(sender); -power_err: -	return err; -} - -/* - * send a generic DCS command with a parameter list - */ -int mdfld_dsi_dbi_send_dcs(struct mdfld_dsi_dbi_output *dbi_output, -			u8 dcs,  u8 *param, u32 num, u8 data_src) -{ -	struct mdfld_dsi_pkg_sender *sender = -		mdfld_dsi_encoder_get_pkg_sender(&dbi_output->base); -	int ret; - -	if (!sender) { -		WARN_ON(1); -		return -EINVAL; -	} - -	ret = mdfld_dsi_send_dcs(sender, -				 dcs, -				 param, -				 num, -				 data_src, -				 MDFLD_DSI_SEND_PACKAGE); - -	return ret; -} - -/* - * Enter DSR - */ -void mdfld_dsi_dbi_enter_dsr(struct mdfld_dsi_dbi_output *dbi_output, int pipe) -{ -	u32 reg_val; -	struct drm_device *dev = dbi_output->dev; -	struct drm_psb_private *dev_priv = dev->dev_private; -	struct drm_crtc *crtc = dbi_output->base.base.crtc; -	struct psb_intel_crtc *psb_crtc = (crtc) ? -					to_psb_intel_crtc(crtc) : NULL; -	u32 dpll_reg = MRST_DPLL_A; -	u32 pipeconf_reg = PIPEACONF; -	u32 dspcntr_reg = DSPACNTR; - -	if (!dbi_output) -		return; - -	/* FIXME check if can go */ -	dev_priv->is_in_idle = true; - -	gdbi_output = dbi_output; -	if ((dbi_output->mode_flags & MODE_SETTING_ON_GOING) || -		(psb_crtc && psb_crtc->mode_flags & MODE_SETTING_ON_GOING)) -		return; - -	if (pipe == 2) { -		dpll_reg = MRST_DPLL_A; -		pipeconf_reg = PIPECCONF; -		dspcntr_reg = DSPCCNTR; -	} - -	if (!gma_power_begin(dev, true)) { -		dev_err(dev->dev, "hw begin failed\n"); -		return; -	} -	/* Disable te interrupts */ -	mdfld_disable_te(dev, pipe); - -	/* Disable plane */ -	reg_val = REG_READ(dspcntr_reg); -	if (!(reg_val & DISPLAY_PLANE_ENABLE)) { -		REG_WRITE(dspcntr_reg, reg_val & ~DISPLAY_PLANE_ENABLE); -		REG_READ(dspcntr_reg); -	} - -	/* Disable pipe */ -	reg_val = REG_READ(pipeconf_reg); -	if (!(reg_val & DISPLAY_PLANE_ENABLE)) { -		reg_val &= ~DISPLAY_PLANE_ENABLE; -		reg_val |= (PIPECONF_PLANE_OFF | PIPECONF_CURSOR_OFF); -		REG_WRITE(pipeconf_reg, reg_val); -		REG_READ(pipeconf_reg); -		mdfldWaitForPipeDisable(dev, pipe); -	} - -	/* Disable DPLL */ -	reg_val = REG_READ(dpll_reg); -	if (!(reg_val & DPLL_VCO_ENABLE)) { -		reg_val &= ~DPLL_VCO_ENABLE; -		REG_WRITE(dpll_reg, reg_val); -		REG_READ(dpll_reg); -		udelay(500); -	} - -	gma_power_end(dev); -	dbi_output->mode_flags |= MODE_SETTING_IN_DSR; -	if (pipe == 2) { -		enter_dsr = 1; -		/* pm_schedule_suspend(&dev->pdev->dev, gfxrtdelay); */ -	} -} - -static void mdfld_dbi_output_exit_dsr(struct mdfld_dsi_dbi_output *dbi_output, -			int pipe) -{ -	struct drm_device *dev = dbi_output->dev; -	struct drm_crtc *crtc = dbi_output->base.base.crtc; -	struct psb_intel_crtc *psb_crtc = (crtc) ? -					to_psb_intel_crtc(crtc) : NULL; -	u32 reg_val; -	u32 dpll_reg = MRST_DPLL_A; -	u32 pipeconf_reg = PIPEACONF; -	u32 dspcntr_reg = DSPACNTR; -	u32 reg_offset = 0; - -	/*if mode setting on-going, back off*/ -	if ((dbi_output->mode_flags & MODE_SETTING_ON_GOING) || -		(psb_crtc && psb_crtc->mode_flags & MODE_SETTING_ON_GOING)) -		return; - -	if (pipe == 2) { -		dpll_reg = MRST_DPLL_A; -		pipeconf_reg = PIPECCONF; -		dspcntr_reg = DSPCCNTR; -		reg_offset = MIPIC_REG_OFFSET; -	} - -	if (!gma_power_begin(dev, true)) { -		dev_err(dev->dev, "hw begin failed\n"); -		return; -	} - -	/* Enable DPLL */ -	reg_val = REG_READ(dpll_reg); -	if (!(reg_val & DPLL_VCO_ENABLE)) { -		if (reg_val & MDFLD_PWR_GATE_EN) { -			reg_val &= ~MDFLD_PWR_GATE_EN; -			REG_WRITE(dpll_reg, reg_val); -			REG_READ(dpll_reg); -			udelay(500); -		} - -		reg_val |= DPLL_VCO_ENABLE; -		REG_WRITE(dpll_reg, reg_val); -		REG_READ(dpll_reg); -		udelay(500); - -		/* Add timeout */ -		while (!(REG_READ(pipeconf_reg) & PIPECONF_DSIPLL_LOCK)) -			cpu_relax(); -	} - -	/* Enable pipe */ -	reg_val = REG_READ(pipeconf_reg); -	if (!(reg_val & PIPEACONF_ENABLE)) { -		reg_val |= PIPEACONF_ENABLE; -		REG_WRITE(pipeconf_reg, reg_val); -		REG_READ(pipeconf_reg); -		udelay(500); -		mdfldWaitForPipeEnable(dev, pipe); -	} - -	/* Enable plane */ -	reg_val = REG_READ(dspcntr_reg); -	if (!(reg_val & DISPLAY_PLANE_ENABLE)) { -		reg_val |= DISPLAY_PLANE_ENABLE; -		REG_WRITE(dspcntr_reg, reg_val); -		REG_READ(dspcntr_reg); -		udelay(500); -	} - -	/* Enable TE interrupt on this pipe */ -	mdfld_enable_te(dev, pipe); -	gma_power_end(dev); - -	/*clean IN_DSR flag*/ -	dbi_output->mode_flags &= ~MODE_SETTING_IN_DSR; -} - -/* - * Exit from DSR - */ -void mdfld_dsi_dbi_exit_dsr(struct drm_device *dev, u32 update_src) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; -	struct mdfld_dbi_dsr_info *dsr_info = dev_priv->dbi_dsr_info; -	struct mdfld_dsi_dbi_output **dbi_output; -	int i; -	int pipe; - -	/* FIXME can go ? */ -	dev_priv->is_in_idle = false; -	dbi_output = dsr_info->dbi_outputs; - -#ifdef CONFIG_PM_RUNTIME -	 if (!enable_gfx_rtpm) { -/*                pm_runtime_allow(&gpDrmDevice->pdev->dev); */ -/*		schedule_delayed_work(&rtpm_work, 30 * 1000);*/ /* FIXME: HZ ? */ -	} -#endif - -	/* For each output, exit dsr */ -	for (i = 0; i < dsr_info->dbi_output_num; i++) { -		/* If panel has been turned off, skip */ -		if (!dbi_output[i] || !dbi_output[i]->dbi_panel_on) -			continue; -		pipe = dbi_output[i]->channel_num ? 2 : 0; -		enter_dsr = 0; -		mdfld_dbi_output_exit_dsr(dbi_output[i], pipe); -	} -	dev_priv->dsr_fb_update |= update_src; -} - -static bool mdfld_dbi_is_in_dsr(struct drm_device *dev) -{ -	if (REG_READ(MRST_DPLL_A) & DPLL_VCO_ENABLE) -		return false; -	if ((REG_READ(PIPEACONF) & PIPEACONF_ENABLE) || -	   (REG_READ(PIPECCONF) & PIPEACONF_ENABLE)) -		return false; -	if ((REG_READ(DSPACNTR) & DISPLAY_PLANE_ENABLE) || -	   (REG_READ(DSPCCNTR) & DISPLAY_PLANE_ENABLE)) -		return false; - -	return true; -} - -/* Periodically update dbi panel */ -void mdfld_dbi_update_panel(struct drm_device *dev, int pipe) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; -	struct mdfld_dbi_dsr_info *dsr_info = dev_priv->dbi_dsr_info; -	struct mdfld_dsi_dbi_output **dbi_outputs; -	struct mdfld_dsi_dbi_output *dbi_output; -	int i; -	int can_enter_dsr = 0; -	u32 damage_mask; - -	dbi_outputs = dsr_info->dbi_outputs; -	dbi_output = pipe ? dbi_outputs[1] : dbi_outputs[0]; - -	if (!dbi_output) -		return; - -	if (pipe == 0) -		damage_mask = dev_priv->dsr_fb_update & MDFLD_DSR_DAMAGE_MASK_0; -	else if (pipe == 2) -		damage_mask = dev_priv->dsr_fb_update & MDFLD_DSR_DAMAGE_MASK_2; -	else -		return; - -	/* If FB is damaged and panel is on update on-panel FB */ -	if (damage_mask && dbi_output->dbi_panel_on) { -		dbi_output->dsr_fb_update_done = false; - -		if (dbi_output->p_funcs->update_fb) -			dbi_output->p_funcs->update_fb(dbi_output, pipe); - -		if (dev_priv->dsr_enable && dbi_output->dsr_fb_update_done) -			dev_priv->dsr_fb_update &= ~damage_mask; - -		/*clean IN_DSR flag*/ -		dbi_output->mode_flags &= ~MODE_SETTING_IN_DSR; - -		dbi_output->dsr_idle_count = 0; -	} else { -		dbi_output->dsr_idle_count++; -	} - -	switch (dsr_info->dbi_output_num) { -	case 1: -		if (dbi_output->dsr_idle_count > MDFLD_DSR_MAX_IDLE_COUNT) -			can_enter_dsr = 1; -		break; -	case 2: -		if (dbi_outputs[0]->dsr_idle_count > MDFLD_DSR_MAX_IDLE_COUNT -		   && dbi_outputs[1]->dsr_idle_count > MDFLD_DSR_MAX_IDLE_COUNT) -			can_enter_dsr = 1; -		break; -	default: -		DRM_ERROR("Wrong DBI output number\n"); -	} - -	/* Try to enter DSR */ -	if (can_enter_dsr) { -		for (i = 0; i < dsr_info->dbi_output_num; i++) { -			if (!mdfld_dbi_is_in_dsr(dev) && dbi_outputs[i] && -			   !(dbi_outputs[i]->mode_flags & MODE_SETTING_ON_GOING)) { -				mdfld_dsi_dbi_enter_dsr(dbi_outputs[i], -					dbi_outputs[i]->channel_num ? 2 : 0); -#if 0 -				enter_dsr = 1; -				pr_err("%s: enter_dsr = 1\n", __func__); -#endif -			} -		} -	/*schedule rpm suspend after gfxrtdelay*/ -#ifdef CONFIG_GFX_RTPM -		if (!dev_priv->rpm_enabled -			|| !enter_dsr -	/*		|| (REG_READ(HDMIB_CONTROL) & HDMIB_PORT_EN) */ -			|| pm_schedule_suspend(&dev->pdev->dev, gfxrtdelay)) -			dev_warn(dev->dev, -				"Runtime PM schedule suspend failed, rpm %d\n", -					dev_priv->rpm_enabled); -#endif -	} -} - -int mdfld_dbi_dsr_init(struct drm_device *dev) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; -	struct mdfld_dbi_dsr_info *dsr_info = dev_priv->dbi_dsr_info; - -	if (!dsr_info || IS_ERR(dsr_info)) { -		dsr_info = kzalloc(sizeof(struct mdfld_dbi_dsr_info), -								GFP_KERNEL); -		if (!dsr_info) { -			dev_err(dev->dev, "No memory\n"); -			return -ENOMEM; -		} -		dev_priv->dbi_dsr_info = dsr_info; -	} -	return 0; -} - -void mdfld_dbi_dsr_exit(struct drm_device *dev) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; -	struct mdfld_dbi_dsr_info *dsr_info = dev_priv->dbi_dsr_info; - -	if (dsr_info) { -		kfree(dsr_info); -		dev_priv->dbi_dsr_info = NULL; -	} -} - -void mdfld_dsi_controller_dbi_init(struct mdfld_dsi_config *dsi_config, -								int pipe) -{ -	struct drm_device *dev = dsi_config->dev; -	u32 reg_offset = pipe ? MIPIC_REG_OFFSET : 0; -	int lane_count = dsi_config->lane_count; -	u32 val = 0; - -	dev_dbg(dev->dev, "Init DBI interface on pipe %d...\n", pipe); - -	/* Un-ready device */ -	REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000000); - -	/* Init dsi adapter before kicking off */ -	REG_WRITE((MIPIA_CONTROL_REG + reg_offset), 0x00000018); - -	/* TODO: figure out how to setup these registers */ -	REG_WRITE((MIPIA_DPHY_PARAM_REG + reg_offset), 0x150c3408); -	REG_WRITE((MIPIA_CLK_LANE_SWITCH_TIME_CNT_REG + reg_offset), -							0x000a0014); -	REG_WRITE((MIPIA_DBI_BW_CTRL_REG + reg_offset), 0x00000400); -	REG_WRITE((MIPIA_DBI_FIFO_THROTTLE_REG + reg_offset), 0x00000001); -	REG_WRITE((MIPIA_HS_LS_DBI_ENABLE_REG + reg_offset), 0x00000000); - -	/* Enable all interrupts */ -	REG_WRITE((MIPIA_INTR_EN_REG + reg_offset), 0xffffffff); -	/* Max value: 20 clock cycles of txclkesc */ -	REG_WRITE((MIPIA_TURN_AROUND_TIMEOUT_REG + reg_offset), 0x0000001f); -	/* Min 21 txclkesc, max: ffffh */ -	REG_WRITE((MIPIA_DEVICE_RESET_TIMER_REG + reg_offset), 0x0000ffff); -	/* Min: 7d0 max: 4e20 */ -	REG_WRITE((MIPIA_INIT_COUNT_REG + reg_offset), 0x00000fa0); - -	/* Set up func_prg */ -	val |= lane_count; -	val |= (dsi_config->channel_num << DSI_DBI_VIRT_CHANNEL_OFFSET); -	val |= DSI_DBI_COLOR_FORMAT_OPTION2; -	REG_WRITE((MIPIA_DSI_FUNC_PRG_REG + reg_offset), val); - -	REG_WRITE((MIPIA_HS_TX_TIMEOUT_REG + reg_offset), 0x3fffff); -	REG_WRITE((MIPIA_LP_RX_TIMEOUT_REG + reg_offset), 0xffff); - -	/* De-assert dbi_stall when half of DBI FIFO is empty */ -	/* REG_WRITE((MIPIA_DBI_FIFO_THROTTLE_REG + reg_offset), 0x00000000); */ - -	REG_WRITE((MIPIA_HIGH_LOW_SWITCH_COUNT_REG + reg_offset), 0x46); -	REG_WRITE((MIPIA_EOT_DISABLE_REG + reg_offset), 0x00000000); -	REG_WRITE((MIPIA_LP_BYTECLK_REG + reg_offset), 0x00000004); -	REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000001); -} - -#if 0 -/*DBI encoder helper funcs*/ -static const struct drm_encoder_helper_funcs mdfld_dsi_dbi_helper_funcs = { -	.dpms = mdfld_dsi_dbi_dpms, -	.mode_fixup = mdfld_dsi_dbi_mode_fixup, -	.prepare = mdfld_dsi_dbi_prepare, -	.mode_set = mdfld_dsi_dbi_mode_set, -	.commit = mdfld_dsi_dbi_commit, -}; - -/*DBI encoder funcs*/ -static const struct drm_encoder_funcs mdfld_dsi_dbi_encoder_funcs = { -	.destroy = drm_encoder_cleanup, -}; - -#endif - -/* - * Init DSI DBI encoder. - * Allocate an mdfld_dsi_encoder and attach it to given @dsi_connector - * return pointer of newly allocated DBI encoder, NULL on error - */ -struct mdfld_dsi_encoder *mdfld_dsi_dbi_init(struct drm_device *dev, -				struct mdfld_dsi_connector *dsi_connector, -				struct panel_funcs *p_funcs) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; -	struct mdfld_dsi_dbi_output *dbi_output = NULL; -	struct mdfld_dsi_config *dsi_config; -	struct drm_connector *connector = NULL; -	struct drm_encoder *encoder = NULL; -	struct drm_display_mode *fixed_mode = NULL; -	struct psb_gtt *pg = dev_priv ? (&dev_priv->gtt) : NULL; -	struct mdfld_dbi_dpu_info *dpu_info = dev_priv ? (dev_priv->dbi_dpu_info) : NULL; -	struct mdfld_dbi_dsr_info *dsr_info = dev_priv ? (dev_priv->dbi_dsr_info) : NULL; -	u32 data = 0; -	int pipe; -	int ret; - -	if (!pg || !dsi_connector || !p_funcs) { -		WARN_ON(1); -		return NULL; -	} - -	dsi_config = mdfld_dsi_get_config(dsi_connector); -	pipe = dsi_connector->pipe; - -	/*panel hard-reset*/ -	if (p_funcs->reset) { -		ret = p_funcs->reset(pipe); -		if (ret) { -			DRM_ERROR("Panel %d hard-reset failed\n", pipe); -			return NULL; -		} -	} -	/* Panel drvIC init */ -	if (p_funcs->drv_ic_init) -		p_funcs->drv_ic_init(dsi_config, pipe); - -	/* Panel power mode detect */ -	ret = mdfld_dsi_get_power_mode(dsi_config, -				       &data, -				       MDFLD_DSI_HS_TRANSMISSION); -	if (ret) { -		DRM_ERROR("Panel %d get power mode failed\n", pipe); -		dsi_connector->status = connector_status_disconnected; -	} else { -		DRM_INFO("pipe %d power mode 0x%x\n", pipe, data); -		dsi_connector->status = connector_status_connected; -	} - -	/*TODO: get panel info from DDB*/ - -	dbi_output = kzalloc(sizeof(struct mdfld_dsi_dbi_output), GFP_KERNEL); -	if (!dbi_output) { -		dev_err(dev->dev, "No memory\n"); -		return NULL; -	} - -	if (dsi_connector->pipe == 0) { -		dbi_output->channel_num = 0; -		dev_priv->dbi_output = dbi_output; -	} else if (dsi_connector->pipe == 2) { -		dbi_output->channel_num = 1; -		dev_priv->dbi_output2 = dbi_output; -	} else { -		dev_err(dev->dev, "only support 2 DSI outputs\n"); -		goto out_err1; -	} - -	dbi_output->dev = dev; -	dbi_output->p_funcs = p_funcs; -	fixed_mode = dsi_config->fixed_mode; -	dbi_output->panel_fixed_mode = fixed_mode; - -	/* Create drm encoder object */ -	connector = &dsi_connector->base.base; -	encoder = &dbi_output->base.base; -	/* Review this if we ever get MIPI-HDMI bridges or similar */ -	drm_encoder_init(dev, -			encoder, -			p_funcs->encoder_funcs, -			DRM_MODE_ENCODER_LVDS); -	drm_encoder_helper_add(encoder, p_funcs->encoder_helper_funcs); - -	/* Attach to given connector */ -	drm_mode_connector_attach_encoder(connector, encoder); - -	/* Set possible CRTCs and clones */ -	if (dsi_connector->pipe) { -		encoder->possible_crtcs = (1 << 2); -		encoder->possible_clones = (1 << 1); -	} else { -		encoder->possible_crtcs = (1 << 0); -		encoder->possible_clones = (1 << 0); -	} - -	dev_priv->dsr_fb_update = 0; -	dev_priv->dsr_enable = false; -	dev_priv->exit_idle = mdfld_dsi_dbi_exit_dsr; - -	dbi_output->first_boot = true; -	dbi_output->mode_flags = MODE_SETTING_IN_ENCODER; - -	/* Add this output to dpu_info if in DPU mode */ -	if (dpu_info && dsi_connector->status == connector_status_connected) { -		if (dsi_connector->pipe == 0) -			dpu_info->dbi_outputs[0] = dbi_output; -		else -			dpu_info->dbi_outputs[1] = dbi_output; - -		dpu_info->dbi_output_num++; -	} else if (dsi_connector->status == connector_status_connected) { -		/* Add this output to dsr_info if not */ -		if (dsi_connector->pipe == 0) -			dsr_info->dbi_outputs[0] = dbi_output; -		else -			dsr_info->dbi_outputs[1] = dbi_output; - -		dsr_info->dbi_output_num++; -	} -	return &dbi_output->base; -out_err1: -	kfree(dbi_output); -	return NULL; -} diff --git a/drivers/staging/gma500/mdfld_dsi_dbi.h b/drivers/staging/gma500/mdfld_dsi_dbi.h deleted file mode 100644 index f0fa986fd93..00000000000 --- a/drivers/staging/gma500/mdfld_dsi_dbi.h +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Copyright © 2010 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Authors: - * jim liu <jim.liu@intel.com> - * Jackie Li<yaodong.li@intel.com> - */ - -#ifndef __MDFLD_DSI_DBI_H__ -#define __MDFLD_DSI_DBI_H__ - -#include <linux/backlight.h> -#include <drm/drmP.h> -#include <drm/drm.h> -#include <drm/drm_crtc.h> -#include <drm/drm_edid.h> - -#include "psb_drv.h" -#include "psb_intel_drv.h" -#include "psb_intel_reg.h" -#include "power.h" - -#include "mdfld_dsi_output.h" -#include "mdfld_output.h" - -/* - * DBI encoder which inherits from mdfld_dsi_encoder - */ -struct mdfld_dsi_dbi_output { -	struct mdfld_dsi_encoder base; -	struct drm_display_mode *panel_fixed_mode; -	u8 last_cmd; -	u8 lane_count; -	u8 channel_num; -	struct drm_device *dev; - -	/* Backlight operations */ - -	/* DSR timer */ -	u32 dsr_idle_count; -	bool dsr_fb_update_done; - -	/* Mode setting flags */ -	u32 mode_flags; - -	/* Panel status */ -	bool dbi_panel_on; -	bool first_boot; -	struct panel_funcs *p_funcs; - -	/* DPU */ -	u32 *dbi_cb_addr; -	u32 dbi_cb_phy; -	spinlock_t cb_lock; -	u32 cb_write; -}; - -#define MDFLD_DSI_DBI_OUTPUT(dsi_encoder) \ -	container_of(dsi_encoder, struct mdfld_dsi_dbi_output, base) - -struct mdfld_dbi_dsr_info { -	int dbi_output_num; -	struct mdfld_dsi_dbi_output *dbi_outputs[2]; - -	u32 dsr_idle_count; -}; - -#define DBI_CB_TIMEOUT_COUNT	0xffff - -/* Offsets */ -#define CMD_MEM_ADDR_OFFSET	0 - -#define CMD_DATA_SRC_SYSTEM_MEM	0 -#define CMD_DATA_SRC_PIPE	1 - -static inline int mdfld_dsi_dbi_fifo_ready(struct mdfld_dsi_dbi_output *dbi_output) -{ -	struct drm_device *dev = dbi_output->dev; -	u32 retry = DBI_CB_TIMEOUT_COUNT; -	int reg_offset = (dbi_output->channel_num == 1) ? MIPIC_REG_OFFSET : 0; -	int ret = 0; - -	/* Query the dbi fifo status*/ -	while (retry--) { -		if (REG_READ(MIPIA_GEN_FIFO_STAT_REG + reg_offset) & (1 << 27)) -			break; -	} - -	if (!retry) { -		DRM_ERROR("Timeout waiting for DBI FIFO empty\n"); -		ret = -EAGAIN; -	} -	return ret; -} - -static inline int mdfld_dsi_dbi_cmd_sent(struct mdfld_dsi_dbi_output *dbi_output) -{ -	struct drm_device *dev = dbi_output->dev; -	u32 retry = DBI_CB_TIMEOUT_COUNT; -	int reg_offset = (dbi_output->channel_num == 1) ? MIPIC_REG_OFFSET : 0; -	int ret = 0; - -	/* Query the command execution status */ -	while (retry--) -		if (!(REG_READ(MIPIA_CMD_ADD_REG + reg_offset) & (1 << 0))) -			break; - -	if (!retry) { -		DRM_ERROR("Timeout waiting for DBI command status\n"); -		ret = -EAGAIN; -	} - -	return ret; -} - -static inline int mdfld_dsi_dbi_cb_ready(struct mdfld_dsi_dbi_output *dbi_output) -{ -	int ret = 0; - -	/* Query the command execution status*/ -	ret = mdfld_dsi_dbi_cmd_sent(dbi_output); -	if (ret) { -		DRM_ERROR("Peripheral is busy\n"); -		ret = -EAGAIN; -	} -	/* Query the dbi fifo status*/ -	ret = mdfld_dsi_dbi_fifo_ready(dbi_output); -	if (ret) { -		DRM_ERROR("DBI FIFO is not empty\n"); -		ret = -EAGAIN; -	} -	return ret; -} - -extern void mdfld_dsi_dbi_output_init(struct drm_device *dev, -			struct psb_intel_mode_device *mode_dev, int pipe); -extern void mdfld_dsi_dbi_exit_dsr(struct drm_device *dev, u32 update_src); -extern void mdfld_dsi_dbi_enter_dsr(struct mdfld_dsi_dbi_output *dbi_output, -			int pipe); -extern int mdfld_dbi_dsr_init(struct drm_device *dev); -extern void mdfld_dbi_dsr_exit(struct drm_device *dev); -extern struct mdfld_dsi_encoder *mdfld_dsi_dbi_init(struct drm_device *dev, -			struct mdfld_dsi_connector *dsi_connector, -			struct panel_funcs *p_funcs); -extern int mdfld_dsi_dbi_send_dcs(struct mdfld_dsi_dbi_output *dbi_output, -			u8 dcs, u8 *param, u32 num, u8 data_src); -extern int mdfld_dsi_dbi_update_area(struct mdfld_dsi_dbi_output *dbi_output, -			u16 x1, u16 y1, u16 x2, u16 y2); -extern int mdfld_dsi_dbi_update_power(struct mdfld_dsi_dbi_output *dbi_output, -			int mode); -extern void mdfld_dsi_controller_dbi_init(struct mdfld_dsi_config *dsi_config, -			int pipe); - -#endif /*__MDFLD_DSI_DBI_H__*/ diff --git a/drivers/staging/gma500/mdfld_dsi_dbi_dpu.c b/drivers/staging/gma500/mdfld_dsi_dbi_dpu.c deleted file mode 100644 index a4e2ff442b1..00000000000 --- a/drivers/staging/gma500/mdfld_dsi_dbi_dpu.c +++ /dev/null @@ -1,778 +0,0 @@ -/* - * Copyright © 2010-2011 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Authors: - * Jim Liu <jim.liu@intel.com> - * Jackie Li<yaodong.li@intel.com> - */ - -#include "mdfld_dsi_dbi_dpu.h" -#include "mdfld_dsi_dbi.h" - -/* - * NOTE: all mdlfd_x_damage funcs should be called by holding dpu_update_lock - */ - -static int mdfld_cursor_damage(struct mdfld_dbi_dpu_info *dpu_info, -			   mdfld_plane_t plane, -			   struct psb_drm_dpu_rect *damaged_rect) -{ -	int x, y; -	int new_x, new_y; -	struct psb_drm_dpu_rect *rect; -	struct psb_drm_dpu_rect *pipe_rect; -	int cursor_size; -	struct mdfld_cursor_info *cursor; -	mdfld_plane_t fb_plane; - -	if (plane == MDFLD_CURSORA) { -		cursor = &dpu_info->cursors[0]; -		x = dpu_info->cursors[0].x; -		y = dpu_info->cursors[0].y; -		cursor_size = dpu_info->cursors[0].size; -		pipe_rect = &dpu_info->damage_pipea; -		fb_plane = MDFLD_PLANEA; -	} else { -		cursor = &dpu_info->cursors[1]; -		x = dpu_info->cursors[1].x; -		y = dpu_info->cursors[1].y; -		cursor_size = dpu_info->cursors[1].size; -		pipe_rect = &dpu_info->damage_pipec; -		fb_plane = MDFLD_PLANEC; -	} -	new_x = damaged_rect->x; -	new_y = damaged_rect->y; - -	if (x == new_x && y == new_y) -		return 0; - -	rect = &dpu_info->damaged_rects[plane]; -	/* Move to right */ -	if (new_x >= x) { -		if (new_y > y) { -			rect->x = x; -			rect->y = y; -			rect->width = (new_x + cursor_size) - x; -			rect->height = (new_y + cursor_size) - y; -			goto cursor_out; -		} else { -			rect->x = x; -			rect->y = new_y; -			rect->width = (new_x + cursor_size) - x; -			rect->height = (y - new_y); -			goto cursor_out; -		} -	} else { -		if (new_y > y) { -			rect->x = new_x; -			rect->y = y; -			rect->width = (x + cursor_size) - new_x; -			rect->height = new_y - y; -			goto cursor_out; -		} else { -			rect->x = new_x; -			rect->y = new_y; -			rect->width = (x + cursor_size) - new_x; -			rect->height = (y + cursor_size) - new_y; -		} -	} -cursor_out: -	if (new_x < 0) -		cursor->x = 0; -	else if (new_x > 864) -		cursor->x = 864; -	else -		cursor->x = new_x; - -	if (new_y < 0) -		cursor->y = 0; -	else if (new_y > 480) -		cursor->y = 480; -	else -		cursor->y = new_y; - -	/* -	 * FIXME: this is a workaround for cursor plane update, -	 * remove it later! -	 */ -	rect->x = 0; -	rect->y = 0; -	rect->width = 864; -	rect->height = 480; - -	mdfld_check_boundary(dpu_info, rect); -	mdfld_dpu_region_extent(pipe_rect, rect); - -	/* Update pending status of dpu_info */ -	dpu_info->pending |= (1 << plane); -	/* Update fb panel as well */ -	dpu_info->pending |= (1 << fb_plane); -	return 0; -} - -static int mdfld_fb_damage(struct mdfld_dbi_dpu_info *dpu_info, -				   mdfld_plane_t plane, -				   struct psb_drm_dpu_rect *damaged_rect) -{ -	struct psb_drm_dpu_rect *rect; - -	if (plane == MDFLD_PLANEA) -		rect = &dpu_info->damage_pipea; -	else -		rect = &dpu_info->damage_pipec; - -	mdfld_check_boundary(dpu_info, damaged_rect); - -	/* Add fb damage area to this pipe */ -	mdfld_dpu_region_extent(rect, damaged_rect); - -	/* Update pending status of dpu_info */ -	dpu_info->pending |= (1 << plane); -	return 0; -} - -/* Do nothing here, right now */ -static int mdfld_overlay_damage(struct mdfld_dbi_dpu_info *dpu_info, -				mdfld_plane_t plane, -				struct psb_drm_dpu_rect *damaged_rect) -{ -	return 0; -} - -int mdfld_dbi_dpu_report_damage(struct drm_device *dev, -				mdfld_plane_t plane, -				struct psb_drm_dpu_rect *rect) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; -	struct mdfld_dbi_dpu_info *dpu_info = dev_priv->dbi_dpu_info; -	int ret = 0; - -	/* DPU not in use, no damage reporting needed */ -	if (dpu_info == NULL) -		return 0; - -	spin_lock(&dpu_info->dpu_update_lock); - -	switch (plane) { -	case MDFLD_PLANEA: -	case MDFLD_PLANEC: -		mdfld_fb_damage(dpu_info, plane, rect); -		break; -	case MDFLD_CURSORA: -	case MDFLD_CURSORC: -		mdfld_cursor_damage(dpu_info, plane, rect); -		break; -	case MDFLD_OVERLAYA: -	case MDFLD_OVERLAYC: -		mdfld_overlay_damage(dpu_info, plane, rect); -		break; -	default: -		DRM_ERROR("Invalid plane type %d\n", plane); -		ret = -EINVAL; -	} -	spin_unlock(&dpu_info->dpu_update_lock); -	return ret; -} - -int mdfld_dbi_dpu_report_fullscreen_damage(struct drm_device *dev) -{ -	struct drm_psb_private *dev_priv; -	struct mdfld_dbi_dpu_info *dpu_info; -	struct mdfld_dsi_config  *dsi_config; -	struct psb_drm_dpu_rect rect; -	int i; - -	if (!dev) { -		DRM_ERROR("Invalid parameter\n"); -		return -EINVAL; -	} - -	dev_priv = dev->dev_private; -	dpu_info = dev_priv->dbi_dpu_info; - -	/* This is fine - we may be in non DPU mode */ -	if (!dpu_info) -		return -EINVAL; - -	for (i = 0; i < dpu_info->dbi_output_num; i++) { -		dsi_config = dev_priv->dsi_configs[i]; -		if (dsi_config) { -			rect.x = rect.y = 0; -			rect.width = dsi_config->fixed_mode->hdisplay; -			rect.height = dsi_config->fixed_mode->vdisplay; -			mdfld_dbi_dpu_report_damage(dev, -				    i ? (MDFLD_PLANEC) : (MDFLD_PLANEA), -				    &rect); -		} -	} -	/* Exit DSR state */ -	mdfld_dpu_exit_dsr(dev); -	return 0; -} - -int mdfld_dsi_dbi_dsr_off(struct drm_device *dev, -					struct psb_drm_dpu_rect *rect) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; -	struct mdfld_dbi_dpu_info *dpu_info = dev_priv->dbi_dpu_info; - -	mdfld_dbi_dpu_report_damage(dev, MDFLD_PLANEA, rect); - -	/* If dual display mode */ -	if (dpu_info->dbi_output_num == 2) -		mdfld_dbi_dpu_report_damage(dev, MDFLD_PLANEC, rect); - -	/* Force dsi to exit DSR mode */ -	mdfld_dpu_exit_dsr(dev); -	return 0; -} - -static void mdfld_dpu_cursor_plane_flush(struct mdfld_dbi_dpu_info *dpu_info, -						 mdfld_plane_t plane) -{ -	struct drm_device *dev = dpu_info->dev; -	u32 curpos_reg = CURAPOS; -	u32 curbase_reg = CURABASE; -	u32 curcntr_reg = CURACNTR; -	struct mdfld_cursor_info *cursor = &dpu_info->cursors[0]; - -	if (plane == MDFLD_CURSORC) { -		curpos_reg = CURCPOS; -		curbase_reg = CURCBASE; -		curcntr_reg = CURCCNTR; -		cursor = &dpu_info->cursors[1]; -	} - -	REG_WRITE(curcntr_reg, REG_READ(curcntr_reg)); -	REG_WRITE(curpos_reg, -		(((cursor->x & CURSOR_POS_MASK) << CURSOR_X_SHIFT) | -		((cursor->y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT))); -	REG_WRITE(curbase_reg, REG_READ(curbase_reg)); -} - -static void mdfld_dpu_fb_plane_flush(struct mdfld_dbi_dpu_info *dpu_info, -						 mdfld_plane_t plane) -{ -	u32 pipesrc_reg = PIPEASRC; -	u32 dspsize_reg = DSPASIZE; -	u32 dspoff_reg = DSPALINOFF; -	u32 dspsurf_reg = DSPASURF; -	u32 dspstride_reg = DSPASTRIDE; -	u32 stride; -	struct psb_drm_dpu_rect *rect = &dpu_info->damage_pipea; -	struct drm_device *dev = dpu_info->dev; - -	if (plane == MDFLD_PLANEC) { -		pipesrc_reg = PIPECSRC; -		dspsize_reg = DSPCSIZE; -		dspoff_reg = DSPCLINOFF; -		dspsurf_reg = DSPCSURF; -		dspstride_reg = DSPCSTRIDE; -		rect = &dpu_info->damage_pipec; -	} - -	stride = REG_READ(dspstride_reg); -	/* FIXME: should I do the pipe src update here? */ -	REG_WRITE(pipesrc_reg, ((rect->width - 1) << 16) | (rect->height - 1)); -	/* Flush plane */ -	REG_WRITE(dspsize_reg, ((rect->height - 1) << 16) | (rect->width - 1)); -	REG_WRITE(dspoff_reg, ((rect->x * 4) + (rect->y * stride))); -	REG_WRITE(dspsurf_reg, REG_READ(dspsurf_reg)); - -	/* -	 * TODO: wait for flip finished and restore the pipesrc reg, -	 * or cursor will be show at a wrong position -	 */ -} - -static void mdfld_dpu_overlay_plane_flush(struct mdfld_dbi_dpu_info *dpu_info, -						  mdfld_plane_t plane) -{ -} - -/* - * TODO: we are still in dbi normal mode now, we will try to use partial - * mode later. - */ -static int mdfld_dbi_prepare_cb(struct mdfld_dsi_dbi_output *dbi_output, -				struct mdfld_dbi_dpu_info *dpu_info, int pipe) -{ -	u8 *cb_addr = (u8 *)dbi_output->dbi_cb_addr; -	u32 *index; -	struct psb_drm_dpu_rect *rect = pipe ? -		(&dpu_info->damage_pipec) : (&dpu_info->damage_pipea); - -	/* FIXME: lock command buffer, this may lead to a deadlock, -	   as we already hold the dpu_update_lock */ -	if (!spin_trylock(&dbi_output->cb_lock)) { -		DRM_ERROR("lock command buffer failed, try again\n"); -		return -EAGAIN; -	} - -	index = &dbi_output->cb_write; - -	if (*index) { -		DRM_ERROR("DBI command buffer unclean\n"); -		return -EAGAIN; -	} - -	/* Column address */ -	*(cb_addr + ((*index)++)) = set_column_address; -	*(cb_addr + ((*index)++)) = rect->x >> 8; -	*(cb_addr + ((*index)++)) = rect->x; -	*(cb_addr + ((*index)++)) = (rect->x + rect->width - 1) >> 8; -	*(cb_addr + ((*index)++)) = (rect->x + rect->width - 1); - -	*index = 8; - -	/* Page address */ -	*(cb_addr + ((*index)++)) = set_page_addr; -	*(cb_addr + ((*index)++)) = rect->y >> 8; -	*(cb_addr + ((*index)++)) = rect->y; -	*(cb_addr + ((*index)++)) = (rect->y + rect->height - 1) >> 8; -	*(cb_addr + ((*index)++)) = (rect->y + rect->height - 1); - -	*index = 16; - -	/*write memory*/ -	*(cb_addr + ((*index)++)) = write_mem_start; - -	return 0; -} - -static int mdfld_dbi_flush_cb(struct mdfld_dsi_dbi_output *dbi_output, int pipe) -{ -	u32 cmd_phy = dbi_output->dbi_cb_phy; -	u32 *index = &dbi_output->cb_write; -	int reg_offset = pipe ? MIPIC_REG_OFFSET : 0; -	struct drm_device *dev = dbi_output->dev; - -	if (*index == 0 || !dbi_output) -		return 0; - -	REG_WRITE((MIPIA_CMD_LEN_REG + reg_offset), 0x010505); -	REG_WRITE((MIPIA_CMD_ADD_REG + reg_offset), cmd_phy | 3); - -	*index = 0; - -	/* FIXME: unlock command buffer */ -	spin_unlock(&dbi_output->cb_lock); -	return 0; -} - -static int mdfld_dpu_update_pipe(struct mdfld_dsi_dbi_output *dbi_output, -				 struct mdfld_dbi_dpu_info *dpu_info, int pipe) -{ -	struct drm_device *dev =  dbi_output->dev; -	struct drm_psb_private *dev_priv = dev->dev_private; -	mdfld_plane_t cursor_plane = MDFLD_CURSORA; -	mdfld_plane_t fb_plane = MDFLD_PLANEA; -	mdfld_plane_t overlay_plane = MDFLD_OVERLAYA; -	int ret = 0; -	u32 plane_mask = MDFLD_PIPEA_PLANE_MASK; - -	/* Damaged rects on this pipe */ -	if (pipe) { -		cursor_plane = MDFLD_CURSORC; -		fb_plane = MDFLD_PLANEC; -		overlay_plane = MDFLD_OVERLAYC; -		plane_mask = MDFLD_PIPEC_PLANE_MASK; -	} - -	/*update cursor which assigned to @pipe*/ -	if (dpu_info->pending & (1 << cursor_plane)) -		mdfld_dpu_cursor_plane_flush(dpu_info, cursor_plane); - -	/*update fb which assigned to @pipe*/ -	if (dpu_info->pending & (1 << fb_plane)) -		mdfld_dpu_fb_plane_flush(dpu_info, fb_plane); - -	/* TODO: update overlay */ -	if (dpu_info->pending & (1 << overlay_plane)) -		mdfld_dpu_overlay_plane_flush(dpu_info, overlay_plane); - -	/* Flush damage area to panel fb */ -	if (dpu_info->pending & plane_mask) { -		ret = mdfld_dbi_prepare_cb(dbi_output, dpu_info, pipe); -		/* -		 * TODO: remove b_dsr_enable later, -		 * added it so that text console could boot smoothly -		 */ -		/* Clean pending flags on this pipe */ -		if (!ret && dev_priv->dsr_enable) { -			dpu_info->pending &= ~plane_mask; -			/* Reset overlay pipe damage rect */ -			mdfld_dpu_init_damage(dpu_info, pipe); -		} -	} -	return ret; -} - -static int mdfld_dpu_update_fb(struct drm_device *dev) -{ -	struct drm_crtc *crtc; -	struct psb_intel_crtc *psb_crtc; -	struct mdfld_dsi_dbi_output **dbi_output; -	struct drm_psb_private *dev_priv = dev->dev_private; -	struct mdfld_dbi_dpu_info *dpu_info = dev_priv->dbi_dpu_info; -	bool pipe_updated[2]; -	unsigned long irq_flags; -	u32 dpll_reg = MRST_DPLL_A; -	u32 dspcntr_reg = DSPACNTR; -	u32 pipeconf_reg = PIPEACONF; -	u32 dsplinoff_reg = DSPALINOFF; -	u32 dspsurf_reg = DSPASURF; -	u32 mipi_state_reg = MIPIA_INTR_STAT_REG; -	u32 reg_offset = 0; -	int pipe; -	int i; -	int ret; - -	dbi_output = dpu_info->dbi_outputs; -	pipe_updated[0] = pipe_updated[1] = false; - -	if (!gma_power_begin(dev, true)) -		return -EAGAIN; - -	/* Try to prevent any new damage reports */ -	if (!spin_trylock_irqsave(&dpu_info->dpu_update_lock, irq_flags)) -		return -EAGAIN; - -	for (i = 0; i < dpu_info->dbi_output_num; i++) { -		crtc = dbi_output[i]->base.base.crtc; -		psb_crtc = (crtc) ? to_psb_intel_crtc(crtc) : NULL; - -		pipe = dbi_output[i]->channel_num ? 2 : 0; - -		if (pipe == 2) { -			dspcntr_reg = DSPCCNTR; -			pipeconf_reg = PIPECCONF; -			dsplinoff_reg = DSPCLINOFF; -			dspsurf_reg = DSPCSURF; -			reg_offset = MIPIC_REG_OFFSET; -		} - -		if (!(REG_READ((MIPIA_GEN_FIFO_STAT_REG + reg_offset)) -							& (1 << 27)) || -			!(REG_READ(dpll_reg) & DPLL_VCO_ENABLE) || -			!(REG_READ(dspcntr_reg) & DISPLAY_PLANE_ENABLE) || -			!(REG_READ(pipeconf_reg) & DISPLAY_PLANE_ENABLE)) { -			dev_err(dev->dev, -				"DBI FIFO is busy, DSI %d state %x\n", -				pipe, -				REG_READ(mipi_state_reg + reg_offset)); -			continue; -		} - -		/* -		 *	If DBI output is in a exclusive state then the pipe -		 *	change won't be updated -		 */ -		if (dbi_output[i]->dbi_panel_on && -		   !(dbi_output[i]->mode_flags & MODE_SETTING_ON_GOING) && -		   !(psb_crtc && -			psb_crtc->mode_flags & MODE_SETTING_ON_GOING) && -		   !(dbi_output[i]->mode_flags & MODE_SETTING_IN_DSR)) { -			ret = mdfld_dpu_update_pipe(dbi_output[i], -				dpu_info, dbi_output[i]->channel_num ? 2 : 0); -			if (!ret) -				pipe_updated[i] = true; -		} -	} - -	for (i = 0; i < dpu_info->dbi_output_num; i++) -		if (pipe_updated[i]) -			mdfld_dbi_flush_cb(dbi_output[i], -				dbi_output[i]->channel_num ? 2 : 0); - -	spin_unlock_irqrestore(&dpu_info->dpu_update_lock, irq_flags); -	gma_power_end(dev); -	return 0; -} - -static int __mdfld_dbi_exit_dsr(struct mdfld_dsi_dbi_output *dbi_output, -								int pipe) -{ -	struct drm_device *dev = dbi_output->dev; -	struct drm_crtc *crtc = dbi_output->base.base.crtc; -	struct psb_intel_crtc *psb_crtc = (crtc) ? to_psb_intel_crtc(crtc) -								: NULL; -	u32 reg_val; -	u32 dpll_reg = MRST_DPLL_A; -	u32 pipeconf_reg = PIPEACONF; -	u32 dspcntr_reg = DSPACNTR; -	u32 dspbase_reg = DSPABASE; -	u32 dspsurf_reg = DSPASURF; -	u32 reg_offset = 0; - -	if (!dbi_output) -		return 0; - -	/* If mode setting on-going, back off */ -	if ((dbi_output->mode_flags & MODE_SETTING_ON_GOING) || -		(psb_crtc && psb_crtc->mode_flags & MODE_SETTING_ON_GOING)) -		return -EAGAIN; - -	if (pipe == 2) { -		dpll_reg = MRST_DPLL_A; -		pipeconf_reg = PIPECCONF; -		dspcntr_reg = DSPCCNTR; -		dspbase_reg = MDFLD_DSPCBASE; -		dspsurf_reg = DSPCSURF; - -		reg_offset = MIPIC_REG_OFFSET; -	} - -	if (!gma_power_begin(dev, true)) -		return -EAGAIN; - -	/* Enable DPLL */ -	reg_val = REG_READ(dpll_reg); -	if (!(reg_val & DPLL_VCO_ENABLE)) { - -		if (reg_val & MDFLD_PWR_GATE_EN) { -			reg_val &= ~MDFLD_PWR_GATE_EN; -			REG_WRITE(dpll_reg, reg_val); -			REG_READ(dpll_reg); -			udelay(500); -		} - -		reg_val |= DPLL_VCO_ENABLE; -		REG_WRITE(dpll_reg, reg_val); -		REG_READ(dpll_reg); -		udelay(500); - -		/* FIXME: add timeout */ -		while (!(REG_READ(pipeconf_reg) & PIPECONF_DSIPLL_LOCK)) -			cpu_relax(); -	} - -	/* Enable pipe */ -	reg_val = REG_READ(pipeconf_reg); -	if (!(reg_val & PIPEACONF_ENABLE)) { -		reg_val |= PIPEACONF_ENABLE; -		REG_WRITE(pipeconf_reg, reg_val); -		REG_READ(pipeconf_reg); -		udelay(500); -		mdfldWaitForPipeEnable(dev, pipe); -	} - -	/* Enable plane */ -	reg_val = REG_READ(dspcntr_reg); -	if (!(reg_val & DISPLAY_PLANE_ENABLE)) { -		reg_val |= DISPLAY_PLANE_ENABLE; -		REG_WRITE(dspcntr_reg, reg_val); -		REG_READ(dspcntr_reg); -		udelay(500); -	} - -	gma_power_end(dev); - -	/* Clean IN_DSR flag */ -	dbi_output->mode_flags &= ~MODE_SETTING_IN_DSR; - -	return 0; -} - -int mdfld_dpu_exit_dsr(struct drm_device *dev) -{ -	struct mdfld_dsi_dbi_output **dbi_output; -	struct drm_psb_private *dev_priv = dev->dev_private; -	struct mdfld_dbi_dpu_info *dpu_info = dev_priv->dbi_dpu_info; -	int i; -	int pipe; - -	dbi_output = dpu_info->dbi_outputs; - -	for (i = 0; i < dpu_info->dbi_output_num; i++) { -		/* If this output is not in DSR mode, don't call exit dsr */ -		if (dbi_output[i]->mode_flags & MODE_SETTING_IN_DSR) -			__mdfld_dbi_exit_dsr(dbi_output[i], -					dbi_output[i]->channel_num ? 2 : 0); -	} - -	/* Enable TE interrupt */ -	for (i = 0; i < dpu_info->dbi_output_num; i++) { -		/* If this output is not in DSR mode, don't call exit dsr */ -		pipe = dbi_output[i]->channel_num ? 2 : 0; -		if (dbi_output[i]->dbi_panel_on && pipe) { -			mdfld_disable_te(dev, 0); -			mdfld_enable_te(dev, 2); -		} else if (dbi_output[i]->dbi_panel_on && !pipe) { -			mdfld_disable_te(dev, 2); -			mdfld_enable_te(dev, 0); -		} -	} -	return 0; -} - -static int mdfld_dpu_enter_dsr(struct drm_device *dev) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; -	struct mdfld_dbi_dpu_info *dpu_info = dev_priv->dbi_dpu_info; -	struct mdfld_dsi_dbi_output **dbi_output; -	int i; - -	dbi_output = dpu_info->dbi_outputs; - -	for (i = 0; i < dpu_info->dbi_output_num; i++) { -		/* If output is off or already in DSR state, don't re-enter */ -		if (dbi_output[i]->dbi_panel_on && -		   !(dbi_output[i]->mode_flags & MODE_SETTING_IN_DSR)) { -			mdfld_dsi_dbi_enter_dsr(dbi_output[i], -				dbi_output[i]->channel_num ? 2 : 0); -		} -	} - -	return 0; -} - -static void mdfld_dbi_dpu_timer_func(unsigned long data) -{ -	struct drm_device *dev = (struct drm_device *)data; -	struct drm_psb_private *dev_priv = dev->dev_private; -	struct mdfld_dbi_dpu_info *dpu_info = dev_priv->dbi_dpu_info; -	struct timer_list *dpu_timer = &dpu_info->dpu_timer; -	unsigned long flags; - -	if (dpu_info->pending) { -		dpu_info->idle_count = 0; -		/* Update panel fb with damaged area */ -		mdfld_dpu_update_fb(dev); -	} else { -		dpu_info->idle_count++; -	} - -	if (dpu_info->idle_count >= MDFLD_MAX_IDLE_COUNT) { -		mdfld_dpu_enter_dsr(dev); -		/* Stop timer by return */ -		return; -	} - -	spin_lock_irqsave(&dpu_info->dpu_timer_lock, flags); -	if (!timer_pending(dpu_timer)) { -		dpu_timer->expires = jiffies + MDFLD_DSR_DELAY; -		add_timer(dpu_timer); -	} -	spin_unlock_irqrestore(&dpu_info->dpu_timer_lock, flags); -} - -void mdfld_dpu_update_panel(struct drm_device *dev) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; -	struct mdfld_dbi_dpu_info *dpu_info = dev_priv->dbi_dpu_info; - -	if (dpu_info->pending) { -		dpu_info->idle_count = 0; - -		/*update panel fb with damaged area*/ -		mdfld_dpu_update_fb(dev); -	} else { -		dpu_info->idle_count++; -	} - -	if (dpu_info->idle_count >= MDFLD_MAX_IDLE_COUNT) { -		/*enter dsr*/ -		mdfld_dpu_enter_dsr(dev); -	} -} - -static int mdfld_dbi_dpu_timer_init(struct drm_device *dev, -				struct mdfld_dbi_dpu_info *dpu_info) -{ -	struct timer_list *dpu_timer = &dpu_info->dpu_timer; -	unsigned long flags; - -	spin_lock_init(&dpu_info->dpu_timer_lock); -	spin_lock_irqsave(&dpu_info->dpu_timer_lock, flags); - -	init_timer(dpu_timer); - -	dpu_timer->data = (unsigned long)dev; -	dpu_timer->function = mdfld_dbi_dpu_timer_func; -	dpu_timer->expires = jiffies + MDFLD_DSR_DELAY; - -	spin_unlock_irqrestore(&dpu_info->dpu_timer_lock, flags); - -	return 0; -} - -void mdfld_dbi_dpu_timer_start(struct mdfld_dbi_dpu_info *dpu_info) -{ -	struct timer_list *dpu_timer = &dpu_info->dpu_timer; -	unsigned long flags; - -	spin_lock_irqsave(&dpu_info->dpu_timer_lock, flags); -	if (!timer_pending(dpu_timer)) { -		dpu_timer->expires = jiffies + MDFLD_DSR_DELAY; -		add_timer(dpu_timer); -	} -	spin_unlock_irqrestore(&dpu_info->dpu_timer_lock, flags); -} - -int mdfld_dbi_dpu_init(struct drm_device *dev) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; -	struct mdfld_dbi_dpu_info *dpu_info = dev_priv->dbi_dpu_info; - -	if (!dpu_info || IS_ERR(dpu_info)) { -		dpu_info = kzalloc(sizeof(struct mdfld_dbi_dpu_info), -								GFP_KERNEL); -		if (!dpu_info) { -			DRM_ERROR("No memory\n"); -			return -ENOMEM; -		} -		dev_priv->dbi_dpu_info = dpu_info; -	} - -	dpu_info->dev = dev; - -	dpu_info->cursors[0].size = MDFLD_CURSOR_SIZE; -	dpu_info->cursors[1].size = MDFLD_CURSOR_SIZE; - -	/*init dpu_update_lock*/ -	spin_lock_init(&dpu_info->dpu_update_lock); - -	/*init dpu refresh timer*/ -	mdfld_dbi_dpu_timer_init(dev, dpu_info); - -	/*init pipe damage area*/ -	mdfld_dpu_init_damage(dpu_info, 0); -	mdfld_dpu_init_damage(dpu_info, 2); - -	return 0; -} - -void mdfld_dbi_dpu_exit(struct drm_device *dev) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; -	struct mdfld_dbi_dpu_info *dpu_info = dev_priv->dbi_dpu_info; - -	if (!dpu_info) -		return; - -	del_timer_sync(&dpu_info->dpu_timer); -	kfree(dpu_info); -	dev_priv->dbi_dpu_info = NULL; -} - - diff --git a/drivers/staging/gma500/mdfld_dsi_dbi_dpu.h b/drivers/staging/gma500/mdfld_dsi_dbi_dpu.h deleted file mode 100644 index 42367ed48c0..00000000000 --- a/drivers/staging/gma500/mdfld_dsi_dbi_dpu.h +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright © 2010 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Authors: - * jim liu <jim.liu@intel.com> - * Jackie Li<yaodong.li@intel.com> - */ - -#ifndef __MDFLD_DSI_DBI_DPU_H__ -#define __MDFLD_DSI_DBI_DPU_H__ - -#include "mdfld_dsi_dbi.h" - -typedef enum { -	MDFLD_PLANEA, -	MDFLD_PLANEC, -	MDFLD_CURSORA, -	MDFLD_CURSORC, -	MDFLD_OVERLAYA, -	MDFLD_OVERLAYC, -	MDFLD_PLANE_NUM, -} mdfld_plane_t; - -#define MDFLD_PIPEA_PLANE_MASK	0x15 -#define MDFLD_PIPEC_PLANE_MASK	0x2A - -struct mdfld_cursor_info { -	int x, y; -	int size; -}; - -#define MDFLD_CURSOR_SIZE	64 - -/* - * enter DSR mode if screen has no update for 2 frames. - */ -#define MDFLD_MAX_IDLE_COUNT	2 - -struct mdfld_dbi_dpu_info { -	struct drm_device *dev; -	/* Lock */ -	spinlock_t dpu_update_lock; - -	/* Cursor postion */ -	struct mdfld_cursor_info cursors[2]; - -	/* Damaged area for each plane */ -	struct psb_drm_dpu_rect damaged_rects[MDFLD_PLANE_NUM]; - -	/* Final damaged area */ -	struct psb_drm_dpu_rect damage_pipea; -	struct psb_drm_dpu_rect damage_pipec; - -	/* Pending */ -	u32 pending; - -	/* DPU timer */ -	struct timer_list dpu_timer; -	spinlock_t dpu_timer_lock; - -	/* DPU idle count */ -	u32 idle_count; - -	/* DSI outputs */ -	struct mdfld_dsi_dbi_output *dbi_outputs[2]; -	int dbi_output_num; -}; - -static inline int mdfld_dpu_region_extent(struct psb_drm_dpu_rect *origin, -			 struct psb_drm_dpu_rect *rect) -{ -	int x1, y1, x2, y2; - -	x1 = origin->x + origin->width; -	y1 = origin->y + origin->height; - -	x2 = rect->x + rect->width; -	y2 = rect->y + rect->height; - -	origin->x = min(origin->x, rect->x); -	origin->y = min(origin->y, rect->y); -	origin->width = max(x1, x2) - origin->x; -	origin->height = max(y1, y2) - origin->y; - -	return 0; -} - -static inline void mdfld_check_boundary(struct mdfld_dbi_dpu_info *dpu_info, -				struct psb_drm_dpu_rect *rect) -{ -	if (rect->x < 0) -		rect->x = 0; -	if (rect->y < 0) -		rect->y = 0; - -	if (rect->x + rect->width > 864) -		rect->width = 864 - rect->x; -	if (rect->y + rect->height > 480) -		rect->height = 480 - rect->height; - -	if (!rect->width) -		rect->width = 1; -	if (!rect->height) -		rect->height = 1; -} - -static inline void mdfld_dpu_init_damage(struct mdfld_dbi_dpu_info *dpu_info, -				int pipe) -{ -	struct psb_drm_dpu_rect *rect; - -	if (pipe == 0) -		rect = &dpu_info->damage_pipea; -	else -		rect = &dpu_info->damage_pipec; - -	rect->x = 864; -	rect->y = 480; -	rect->width = -864; -	rect->height = -480; -} - -extern int mdfld_dsi_dbi_dsr_off(struct drm_device *dev, -				struct psb_drm_dpu_rect *rect); -extern int mdfld_dbi_dpu_report_damage(struct drm_device *dev, -				mdfld_plane_t plane, -				struct psb_drm_dpu_rect *rect); -extern int mdfld_dbi_dpu_report_fullscreen_damage(struct drm_device *dev); -extern int mdfld_dpu_exit_dsr(struct drm_device *dev); -extern void mdfld_dbi_dpu_timer_start(struct mdfld_dbi_dpu_info *dpu_info); -extern int mdfld_dbi_dpu_init(struct drm_device *dev); -extern void mdfld_dbi_dpu_exit(struct drm_device *dev); -extern void mdfld_dpu_update_panel(struct drm_device *dev); - -#endif /*__MDFLD_DSI_DBI_DPU_H__*/ diff --git a/drivers/staging/gma500/mdfld_dsi_dpi.c b/drivers/staging/gma500/mdfld_dsi_dpi.c deleted file mode 100644 index e685f1217ba..00000000000 --- a/drivers/staging/gma500/mdfld_dsi_dpi.c +++ /dev/null @@ -1,805 +0,0 @@ -/* - * Copyright © 2010 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Authors: - * jim liu <jim.liu@intel.com> - * Jackie Li<yaodong.li@intel.com> - */ - -#include "mdfld_dsi_dpi.h" -#include "mdfld_output.h" -#include "mdfld_dsi_pkg_sender.h" - - -static void mdfld_wait_for_HS_DATA_FIFO(struct drm_device *dev, u32 pipe) -{ -	u32 gen_fifo_stat_reg = MIPIA_GEN_FIFO_STAT_REG; -	int timeout = 0; - -	if (pipe == 2) -		gen_fifo_stat_reg += MIPIC_REG_OFFSET; - -	udelay(500); - -	/* This will time out after approximately 2+ seconds */ -	while ((timeout < 20000) && (REG_READ(gen_fifo_stat_reg) & DSI_FIFO_GEN_HS_DATA_FULL)) { -		udelay(100); -		timeout++; -	} - -	if (timeout == 20000) -		dev_warn(dev->dev, "MIPI: HS Data FIFO was never cleared!\n"); -} - -static void mdfld_wait_for_HS_CTRL_FIFO(struct drm_device *dev, u32 pipe) -{ -	u32 gen_fifo_stat_reg = MIPIA_GEN_FIFO_STAT_REG; -	int timeout = 0; - -	if (pipe == 2) -		gen_fifo_stat_reg += MIPIC_REG_OFFSET; - -	udelay(500); - -	/* This will time out after approximately 2+ seconds */ -	while ((timeout < 20000) && (REG_READ(gen_fifo_stat_reg) & DSI_FIFO_GEN_HS_CTRL_FULL)) { -		udelay(100); -		timeout++; -	} -	if (timeout == 20000) -		dev_warn(dev->dev, "MIPI: HS CMD FIFO was never cleared!\n"); -} - -static void mdfld_wait_for_DPI_CTRL_FIFO(struct drm_device *dev, u32 pipe) -{ -	u32 gen_fifo_stat_reg = MIPIA_GEN_FIFO_STAT_REG; -        int timeout = 0; - -	if (pipe == 2) -		gen_fifo_stat_reg += MIPIC_REG_OFFSET; - -        udelay(500); - -        /* This will time out after approximately 2+ seconds */ -        while ((timeout < 20000) && ((REG_READ(gen_fifo_stat_reg) & DPI_FIFO_EMPTY) -                                                        != DPI_FIFO_EMPTY)) { -                udelay(100); -                timeout++; -        } - -        if (timeout == 20000) -                dev_warn(dev->dev, "MIPI: DPI FIFO was never cleared!\n"); -} - -static void mdfld_wait_for_SPL_PKG_SENT(struct drm_device *dev, u32 pipe) -{ -	u32 intr_stat_reg = MIPIA_INTR_STAT_REG; -	int timeout = 0; - -	if (pipe == 2) -		intr_stat_reg += MIPIC_REG_OFFSET; - -        udelay(500); - -        /* This will time out after approximately 2+ seconds */ -        while ((timeout < 20000) && (!(REG_READ(intr_stat_reg) & DSI_INTR_STATE_SPL_PKG_SENT))) { -                udelay(100); -                timeout++; -        } - -        if (timeout == 20000) -                dev_warn(dev->dev, "MIPI: SPL_PKT_SENT_INTERRUPT was not sent successfully!\n"); -} - - -/* ************************************************************************* *\ - * FUNCTION: mdfld_dsi_tpo_ic_init - * - * DESCRIPTION:  This function is called only by mrst_dsi_mode_set and - *               restore_display_registers.  since this function does not - *               acquire the mutex, it is important that the calling function - *               does! -\* ************************************************************************* */ -void mdfld_dsi_tpo_ic_init(struct mdfld_dsi_config *dsi_config, u32 pipe) -{ -	struct drm_device *dev = dsi_config->dev; -	u32 dcsChannelNumber = dsi_config->channel_num; -	u32 gen_data_reg = MIPIA_HS_GEN_DATA_REG;  -	u32 gen_ctrl_reg = MIPIA_HS_GEN_CTRL_REG; -	u32 gen_ctrl_val = GEN_LONG_WRITE; - -	if (pipe == 2) { -		gen_data_reg = HS_GEN_DATA_REG + MIPIC_REG_OFFSET;  -		gen_ctrl_reg = HS_GEN_CTRL_REG + MIPIC_REG_OFFSET; -	} - -	gen_ctrl_val |= dcsChannelNumber << DCS_CHANNEL_NUMBER_POS; - -	/* Flip page order */ -	mdfld_wait_for_HS_DATA_FIFO(dev, pipe); -	REG_WRITE(gen_data_reg, 0x00008036); -	mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); -	REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x02 << WORD_COUNTS_POS)); - -	/* 0xF0 */ -	mdfld_wait_for_HS_DATA_FIFO(dev, pipe); -	REG_WRITE(gen_data_reg, 0x005a5af0); -	mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); -	REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS)); - -	/* Write protection key */ -	mdfld_wait_for_HS_DATA_FIFO(dev, pipe); -	REG_WRITE(gen_data_reg, 0x005a5af1); -	mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); -	REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS)); - -	/* 0xFC */ -	mdfld_wait_for_HS_DATA_FIFO(dev, pipe); -	REG_WRITE(gen_data_reg, 0x005a5afc); -	mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); -	REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS)); - -	/* 0xB7 */ -	mdfld_wait_for_HS_DATA_FIFO(dev, pipe); -	REG_WRITE(gen_data_reg, 0x770000b7); -	mdfld_wait_for_HS_DATA_FIFO(dev, pipe); -	REG_WRITE(gen_data_reg, 0x00000044); -	mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); -	REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x05 << WORD_COUNTS_POS)); - -	/* 0xB6 */ -	mdfld_wait_for_HS_DATA_FIFO(dev, pipe); -	REG_WRITE(gen_data_reg, 0x000a0ab6); -	mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); -	REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS)); - -	/* 0xF2 */ -	mdfld_wait_for_HS_DATA_FIFO(dev, pipe); -	REG_WRITE(gen_data_reg, 0x081010f2); -	mdfld_wait_for_HS_DATA_FIFO(dev, pipe); -	REG_WRITE(gen_data_reg, 0x4a070708); -	mdfld_wait_for_HS_DATA_FIFO(dev, pipe); -	REG_WRITE(gen_data_reg, 0x000000c5); -	mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); -	REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x09 << WORD_COUNTS_POS)); - -	/* 0xF8 */ -	mdfld_wait_for_HS_DATA_FIFO(dev, pipe); -	REG_WRITE(gen_data_reg, 0x024003f8); -	mdfld_wait_for_HS_DATA_FIFO(dev, pipe); -	REG_WRITE(gen_data_reg, 0x01030a04); -	mdfld_wait_for_HS_DATA_FIFO(dev, pipe); -	REG_WRITE(gen_data_reg, 0x0e020220); -	mdfld_wait_for_HS_DATA_FIFO(dev, pipe); -	REG_WRITE(gen_data_reg, 0x00000004); -	mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); -	REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x0d << WORD_COUNTS_POS)); - -	/* 0xE2 */ -	mdfld_wait_for_HS_DATA_FIFO(dev, pipe); -	REG_WRITE(gen_data_reg, 0x398fc3e2); -	mdfld_wait_for_HS_DATA_FIFO(dev, pipe); -	REG_WRITE(gen_data_reg, 0x0000916f); -	mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); -	REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x06 << WORD_COUNTS_POS)); - -	/* 0xB0 */ -	mdfld_wait_for_HS_DATA_FIFO(dev, pipe); -	REG_WRITE(gen_data_reg, 0x000000b0); -	mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); -	REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x02 << WORD_COUNTS_POS)); - -	/* 0xF4 */ -	mdfld_wait_for_HS_DATA_FIFO(dev, pipe); -	REG_WRITE(gen_data_reg, 0x240242f4); -	mdfld_wait_for_HS_DATA_FIFO(dev, pipe); -	REG_WRITE(gen_data_reg, 0x78ee2002); -	mdfld_wait_for_HS_DATA_FIFO(dev, pipe); -	REG_WRITE(gen_data_reg, 0x2a071050); -	mdfld_wait_for_HS_DATA_FIFO(dev, pipe); -	REG_WRITE(gen_data_reg, 0x507fee10); -	mdfld_wait_for_HS_DATA_FIFO(dev, pipe); -	REG_WRITE(gen_data_reg, 0x10300710); -	mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); -	REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x14 << WORD_COUNTS_POS)); - -	/* 0xBA */ -	mdfld_wait_for_HS_DATA_FIFO(dev, pipe); -	REG_WRITE(gen_data_reg, 0x19fe07ba); -	mdfld_wait_for_HS_DATA_FIFO(dev, pipe); -	REG_WRITE(gen_data_reg, 0x101c0a31); -	mdfld_wait_for_HS_DATA_FIFO(dev, pipe); -	REG_WRITE(gen_data_reg, 0x00000010); -	mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); -	REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x09 << WORD_COUNTS_POS)); - -	/* 0xBB */ -	mdfld_wait_for_HS_DATA_FIFO(dev, pipe); -	REG_WRITE(gen_data_reg, 0x28ff07bb); -	mdfld_wait_for_HS_DATA_FIFO(dev, pipe); -	REG_WRITE(gen_data_reg, 0x24280a31); -	mdfld_wait_for_HS_DATA_FIFO(dev, pipe); -	REG_WRITE(gen_data_reg, 0x00000034); -	mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); -	REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x09 << WORD_COUNTS_POS)); - -	/* 0xFB */ -	mdfld_wait_for_HS_DATA_FIFO(dev, pipe); -	REG_WRITE(gen_data_reg, 0x535d05fb); -	mdfld_wait_for_HS_DATA_FIFO(dev, pipe); -	REG_WRITE(gen_data_reg, 0x1b1a2130); -	mdfld_wait_for_HS_DATA_FIFO(dev, pipe); -	REG_WRITE(gen_data_reg, 0x221e180e); -	mdfld_wait_for_HS_DATA_FIFO(dev, pipe); -	REG_WRITE(gen_data_reg, 0x131d2120); -	mdfld_wait_for_HS_DATA_FIFO(dev, pipe); -	REG_WRITE(gen_data_reg, 0x535d0508); -	mdfld_wait_for_HS_DATA_FIFO(dev, pipe); -	REG_WRITE(gen_data_reg, 0x1c1a2131); -	mdfld_wait_for_HS_DATA_FIFO(dev, pipe); -	REG_WRITE(gen_data_reg, 0x231f160d); -	mdfld_wait_for_HS_DATA_FIFO(dev, pipe); -	REG_WRITE(gen_data_reg, 0x111b2220); -	mdfld_wait_for_HS_DATA_FIFO(dev, pipe); -	REG_WRITE(gen_data_reg, 0x535c2008); -	mdfld_wait_for_HS_DATA_FIFO(dev, pipe); -	REG_WRITE(gen_data_reg, 0x1f1d2433); -	mdfld_wait_for_HS_DATA_FIFO(dev, pipe); -	REG_WRITE(gen_data_reg, 0x2c251a10); -	mdfld_wait_for_HS_DATA_FIFO(dev, pipe); -	REG_WRITE(gen_data_reg, 0x2c34372d); -	mdfld_wait_for_HS_DATA_FIFO(dev, pipe); -	REG_WRITE(gen_data_reg, 0x00000023); -	mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); -	REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x31 << WORD_COUNTS_POS)); - -	/* 0xFA */ -	mdfld_wait_for_HS_DATA_FIFO(dev, pipe); -	REG_WRITE(gen_data_reg, 0x525c0bfa); -	mdfld_wait_for_HS_DATA_FIFO(dev, pipe); -	REG_WRITE(gen_data_reg, 0x1c1c232f); -	mdfld_wait_for_HS_DATA_FIFO(dev, pipe); -	REG_WRITE(gen_data_reg, 0x2623190e); -	mdfld_wait_for_HS_DATA_FIFO(dev, pipe); -	REG_WRITE(gen_data_reg, 0x18212625); -	mdfld_wait_for_HS_DATA_FIFO(dev, pipe); -	REG_WRITE(gen_data_reg, 0x545d0d0e); -	mdfld_wait_for_HS_DATA_FIFO(dev, pipe); -	REG_WRITE(gen_data_reg, 0x1e1d2333); -	mdfld_wait_for_HS_DATA_FIFO(dev, pipe); -	REG_WRITE(gen_data_reg, 0x26231a10); -	mdfld_wait_for_HS_DATA_FIFO(dev, pipe); -	REG_WRITE(gen_data_reg, 0x1a222725); -	mdfld_wait_for_HS_DATA_FIFO(dev, pipe); -	REG_WRITE(gen_data_reg, 0x545d280f); -	mdfld_wait_for_HS_DATA_FIFO(dev, pipe); -	REG_WRITE(gen_data_reg, 0x21202635); -	mdfld_wait_for_HS_DATA_FIFO(dev, pipe); -	REG_WRITE(gen_data_reg, 0x31292013); -	mdfld_wait_for_HS_DATA_FIFO(dev, pipe); -	REG_WRITE(gen_data_reg, 0x31393d33); -	mdfld_wait_for_HS_DATA_FIFO(dev, pipe); -	REG_WRITE(gen_data_reg, 0x00000029); -	mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); -	REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x31 << WORD_COUNTS_POS)); - -	/* Set DM */ -	mdfld_wait_for_HS_DATA_FIFO(dev, pipe); -	REG_WRITE(gen_data_reg, 0x000100f7); -	mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); -	REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS)); -} - -static u16 mdfld_dsi_dpi_to_byte_clock_count(int pixel_clock_count, -						int num_lane, int bpp) -{ -	return (u16)((pixel_clock_count * bpp) / (num_lane * 8));  -} - -/* - * Calculate the dpi time basing on a given drm mode @mode - * return 0 on success. - * FIXME: I was using proposed mode value for calculation, may need to  - * use crtc mode values later  - */ -int mdfld_dsi_dpi_timing_calculation(struct drm_display_mode *mode,  -			struct mdfld_dsi_dpi_timing *dpi_timing, -			int num_lane, int bpp) -{ -	int pclk_hsync, pclk_hfp, pclk_hbp, pclk_hactive; -	int pclk_vsync, pclk_vfp, pclk_vbp, pclk_vactive; -	 -	if(!mode || !dpi_timing) { -		DRM_ERROR("Invalid parameter\n"); -		return -EINVAL; -	} -	 -	pclk_hactive = mode->hdisplay; -	pclk_hfp = mode->hsync_start - mode->hdisplay; -	pclk_hsync = mode->hsync_end - mode->hsync_start; -	pclk_hbp = mode->htotal - mode->hsync_end; -	 -	pclk_vactive = mode->vdisplay; -	pclk_vfp = mode->vsync_start - mode->vdisplay; -	pclk_vsync = mode->vsync_end - mode->vsync_start; -	pclk_vbp = mode->vtotal - mode->vsync_end; - -	/* -	 * byte clock counts were calculated by following formula -	 * bclock_count = pclk_count * bpp / num_lane / 8 -	 */ -	dpi_timing->hsync_count = mdfld_dsi_dpi_to_byte_clock_count(pclk_hsync, num_lane, bpp); -	dpi_timing->hbp_count = mdfld_dsi_dpi_to_byte_clock_count(pclk_hbp, num_lane, bpp); -	dpi_timing->hfp_count = mdfld_dsi_dpi_to_byte_clock_count(pclk_hfp, num_lane, bpp); -	dpi_timing->hactive_count = mdfld_dsi_dpi_to_byte_clock_count(pclk_hactive, num_lane, bpp); -	dpi_timing->vsync_count = mdfld_dsi_dpi_to_byte_clock_count(pclk_vsync, num_lane, bpp); -	dpi_timing->vbp_count = mdfld_dsi_dpi_to_byte_clock_count(pclk_vbp, num_lane, bpp); -	dpi_timing->vfp_count = mdfld_dsi_dpi_to_byte_clock_count(pclk_vfp, num_lane, bpp); - -	return 0;  -} - -void mdfld_dsi_dpi_controller_init(struct mdfld_dsi_config *dsi_config, int pipe) -{ -	struct drm_device *dev = dsi_config->dev; -	u32 reg_offset = pipe ? MIPIC_REG_OFFSET : 0; -	int lane_count = dsi_config->lane_count; -	struct mdfld_dsi_dpi_timing dpi_timing; -	struct drm_display_mode *mode = dsi_config->mode; -	u32 val = 0; -	 -	/*un-ready device*/ -	REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000000); -	 -	/*init dsi adapter before kicking off*/ -	REG_WRITE((MIPIA_CONTROL_REG + reg_offset), 0x00000018); -	 -	/*enable all interrupts*/ -	REG_WRITE((MIPIA_INTR_EN_REG + reg_offset), 0xffffffff); -	 - -	/*set up func_prg*/ -	val |= lane_count; -	val |= dsi_config->channel_num << DSI_DPI_VIRT_CHANNEL_OFFSET; -		 -	switch(dsi_config->bpp) { -	case 16: -		val |= DSI_DPI_COLOR_FORMAT_RGB565; -		break; -	case 18: -		val |= DSI_DPI_COLOR_FORMAT_RGB666; -		break; -	case 24: -		val |= DSI_DPI_COLOR_FORMAT_RGB888; -		break; -	default: -		DRM_ERROR("unsupported color format, bpp = %d\n", dsi_config->bpp); -	} -	REG_WRITE((MIPIA_DSI_FUNC_PRG_REG + reg_offset), val); -	 -	REG_WRITE((MIPIA_HS_TX_TIMEOUT_REG + reg_offset),  -			(mode->vtotal * mode->htotal * dsi_config->bpp / (8 * lane_count)) & DSI_HS_TX_TIMEOUT_MASK); -	REG_WRITE((MIPIA_LP_RX_TIMEOUT_REG + reg_offset), 0xffff & DSI_LP_RX_TIMEOUT_MASK); -	 -	/*max value: 20 clock cycles of txclkesc*/ -	REG_WRITE((MIPIA_TURN_AROUND_TIMEOUT_REG + reg_offset), 0x14 & DSI_TURN_AROUND_TIMEOUT_MASK); -	 -	/*min 21 txclkesc, max: ffffh*/ -	REG_WRITE((MIPIA_DEVICE_RESET_TIMER_REG + reg_offset), 0xffff & DSI_RESET_TIMER_MASK); - -	REG_WRITE((MIPIA_DPI_RESOLUTION_REG + reg_offset), mode->vdisplay << 16 | mode->hdisplay); -	 -	/*set DPI timing registers*/ -	mdfld_dsi_dpi_timing_calculation(mode, &dpi_timing, dsi_config->lane_count, dsi_config->bpp); -	 -	REG_WRITE((MIPIA_HSYNC_COUNT_REG + reg_offset), dpi_timing.hsync_count & DSI_DPI_TIMING_MASK); -	REG_WRITE((MIPIA_HBP_COUNT_REG + reg_offset), dpi_timing.hbp_count & DSI_DPI_TIMING_MASK); -	REG_WRITE((MIPIA_HFP_COUNT_REG + reg_offset), dpi_timing.hfp_count & DSI_DPI_TIMING_MASK); -	REG_WRITE((MIPIA_HACTIVE_COUNT_REG + reg_offset), dpi_timing.hactive_count & DSI_DPI_TIMING_MASK); -	REG_WRITE((MIPIA_VSYNC_COUNT_REG + reg_offset), dpi_timing.vsync_count & DSI_DPI_TIMING_MASK); -	REG_WRITE((MIPIA_VBP_COUNT_REG + reg_offset), dpi_timing.vbp_count & DSI_DPI_TIMING_MASK); -	REG_WRITE((MIPIA_VFP_COUNT_REG + reg_offset), dpi_timing.vfp_count & DSI_DPI_TIMING_MASK); -	 -	REG_WRITE((MIPIA_HIGH_LOW_SWITCH_COUNT_REG + reg_offset), 0x46); -	 -	/*min: 7d0 max: 4e20*/ -	REG_WRITE((MIPIA_INIT_COUNT_REG + reg_offset), 0x000007d0); -	 -	/*set up video mode*/ -	val = 0; -	val = dsi_config->video_mode | DSI_DPI_COMPLETE_LAST_LINE; -	REG_WRITE((MIPIA_VIDEO_MODE_FORMAT_REG + reg_offset), val); -	 -	REG_WRITE((MIPIA_EOT_DISABLE_REG + reg_offset), 0x00000000); -	 -	REG_WRITE((MIPIA_LP_BYTECLK_REG + reg_offset), 0x00000004); -	 -	/*TODO: figure out how to setup these registers*/ -	REG_WRITE((MIPIA_DPHY_PARAM_REG + reg_offset), 0x150c3408); -	 -	REG_WRITE((MIPIA_CLK_LANE_SWITCH_TIME_CNT_REG + reg_offset), (0xa << 16) | 0x14); -	/*set device ready*/ -	REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000001); -} - -void mdfld_dsi_dpi_turn_on(struct mdfld_dsi_dpi_output *output, int pipe) -{ -	struct drm_device *dev = output->dev; -	u32 reg_offset = 0; -	 -	if(output->panel_on)  -		return; -		 -	if(pipe)  -		reg_offset = MIPIC_REG_OFFSET; - -	/* clear special packet sent bit */ -	if(REG_READ(MIPIA_INTR_STAT_REG + reg_offset) & DSI_INTR_STATE_SPL_PKG_SENT) { -		REG_WRITE((MIPIA_INTR_STAT_REG + reg_offset), DSI_INTR_STATE_SPL_PKG_SENT); -	} -		 -	/*send turn on package*/ -	REG_WRITE((MIPIA_DPI_CONTROL_REG + reg_offset), DSI_DPI_CTRL_HS_TURN_ON); -	 -	/*wait for SPL_PKG_SENT interrupt*/ -	mdfld_wait_for_SPL_PKG_SENT(dev, pipe); -	 -	if(REG_READ(MIPIA_INTR_STAT_REG + reg_offset) & DSI_INTR_STATE_SPL_PKG_SENT) { -		REG_WRITE((MIPIA_INTR_STAT_REG + reg_offset), DSI_INTR_STATE_SPL_PKG_SENT); -	} - -	output->panel_on = 1; - -	/* FIXME the following is disabled to WA the X slow start issue for TMD panel */ -	/* if(pipe == 2) */ -	/* 	dev_priv->dpi_panel_on2 = true; */ -	/* else if (pipe == 0) */ -	/* 	dev_priv->dpi_panel_on = true; */ -} - -static void mdfld_dsi_dpi_shut_down(struct mdfld_dsi_dpi_output *output, int pipe) -{ -	struct drm_device *dev = output->dev; -	u32 reg_offset = 0; -	 -	/*if output is on, or mode setting didn't happen, ignore this*/ -	if((!output->panel_on) || output->first_boot) { -		output->first_boot = 0;  -		return; -	} -	 -	if(pipe) -		reg_offset = MIPIC_REG_OFFSET; - -	/* Wait for dpi fifo to empty */ -	mdfld_wait_for_DPI_CTRL_FIFO(dev, pipe); - -	/* Clear the special packet interrupt bit if set */ -	if(REG_READ(MIPIA_INTR_STAT_REG + reg_offset) & DSI_INTR_STATE_SPL_PKG_SENT) { -		REG_WRITE((MIPIA_INTR_STAT_REG + reg_offset), DSI_INTR_STATE_SPL_PKG_SENT); -	} -	 -	if(REG_READ(MIPIA_DPI_CONTROL_REG + reg_offset) == DSI_DPI_CTRL_HS_SHUTDOWN) { -		dev_warn(dev->dev, "try to send the same package again, abort!"); -		goto shutdown_out; -	} -	 -	REG_WRITE((MIPIA_DPI_CONTROL_REG + reg_offset), DSI_DPI_CTRL_HS_SHUTDOWN); - -shutdown_out: -	output->panel_on = 0; -	output->first_boot = 0; - -	/* FIXME the following is disabled to WA the X slow start issue for TMD panel */ -	/* if(pipe == 2) */ -	/* 	dev_priv->dpi_panel_on2 = false; */ -	/* else if (pipe == 0) */ -	/* 	dev_priv->dpi_panel_on = false;	 */ -	/* #ifdef CONFIG_PM_RUNTIME*/  -	/*	if (drm_psb_ospm && !enable_gfx_rtpm) { */ -	/*		pm_runtime_allow(&gpDrmDevice->pdev->dev); */ -	/*	schedule_delayed_work(&dev_priv->rtpm_work, 30 * 1000); */ -	/* } */ -	/*if (enable_gfx_rtpm) */ -	/*		pm_schedule_suspend(&dev->pdev->dev, gfxrtdelay); */ -	/* #endif */ -} - -void mdfld_dsi_dpi_set_power(struct drm_encoder *encoder, bool on) -{ -	struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder); -	struct mdfld_dsi_dpi_output *dpi_output = MDFLD_DSI_DPI_OUTPUT(dsi_encoder); -	struct mdfld_dsi_config *dsi_config = mdfld_dsi_encoder_get_config(dsi_encoder); -	int pipe = mdfld_dsi_encoder_get_pipe(dsi_encoder); -	struct drm_device *dev = dsi_config->dev; -	struct drm_psb_private *dev_priv = dev->dev_private; -	u32 mipi_reg = MIPI; -	u32 pipeconf_reg = PIPEACONF; -	 -	if(pipe) { -		mipi_reg = MIPI_C; -		pipeconf_reg = PIPECCONF; -	} -	 -	/* Start up display island if it was shutdown */ -	if (!gma_power_begin(dev, true)) -		return; - -	if(on) { -		if (mdfld_get_panel_type(dev, pipe) == TMD_VID){ - 			mdfld_dsi_dpi_turn_on(dpi_output, pipe); - 		} else { -			/* Enable mipi port */ -			REG_WRITE(mipi_reg, (REG_READ(mipi_reg) | (1 << 31))); -			REG_READ(mipi_reg); - -			mdfld_dsi_dpi_turn_on(dpi_output, pipe); -			mdfld_dsi_tpo_ic_init(dsi_config, pipe); -		} - -		if(pipe == 2) { -			dev_priv->dpi_panel_on2 = true; -		} -		else { -			dev_priv->dpi_panel_on  = true; -		} - -	} else { - 		if (mdfld_get_panel_type(dev, pipe) == TMD_VID) { - 			mdfld_dsi_dpi_shut_down(dpi_output, pipe); - 		} else { -			mdfld_dsi_dpi_shut_down(dpi_output, pipe); -			/* Disable mipi port */ -			REG_WRITE(mipi_reg, (REG_READ(mipi_reg) & ~(1<<31))); -			REG_READ(mipi_reg); -		} - -		if(pipe == 2) -			dev_priv->dpi_panel_on2 = false; -		else -			dev_priv->dpi_panel_on  = false; -	} -	gma_power_end(dev); -} - -void mdfld_dsi_dpi_dpms(struct drm_encoder *encoder, int mode) -{ -	dev_dbg(encoder->dev->dev, "DPMS %s\n", -			(mode == DRM_MODE_DPMS_ON ? "on":"off")); - -	if (mode == DRM_MODE_DPMS_ON) -		mdfld_dsi_dpi_set_power(encoder, true); -	else { -		mdfld_dsi_dpi_set_power(encoder, false); -#if 0 /* FIXME */ -#ifdef CONFIG_PM_RUNTIME -		if (enable_gfx_rtpm) -			pm_schedule_suspend(&gpDrmDevice->pdev->dev, gfxrtdelay); -#endif -#endif -	} -} - -bool mdfld_dsi_dpi_mode_fixup(struct drm_encoder *encoder, -				     struct drm_display_mode *mode, -				     struct drm_display_mode *adjusted_mode) -{ -	struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder); -	struct mdfld_dsi_config *dsi_config = mdfld_dsi_encoder_get_config(dsi_encoder); -	struct drm_display_mode *fixed_mode = dsi_config->fixed_mode; - -	if(fixed_mode) { -		adjusted_mode->hdisplay = fixed_mode->hdisplay; -		adjusted_mode->hsync_start = fixed_mode->hsync_start; -		adjusted_mode->hsync_end = fixed_mode->hsync_end; -		adjusted_mode->htotal = fixed_mode->htotal; -		adjusted_mode->vdisplay = fixed_mode->vdisplay; -		adjusted_mode->vsync_start = fixed_mode->vsync_start; -		adjusted_mode->vsync_end = fixed_mode->vsync_end; -		adjusted_mode->vtotal = fixed_mode->vtotal; -		adjusted_mode->clock = fixed_mode->clock; -		drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V); -	} -	 -	return true; -} - -void mdfld_dsi_dpi_prepare(struct drm_encoder *encoder)  -{ -	mdfld_dsi_dpi_set_power(encoder, false); -} - -void mdfld_dsi_dpi_commit(struct drm_encoder *encoder)  -{ -	mdfld_dsi_dpi_set_power(encoder, true); -} - -void mdfld_dsi_dpi_mode_set(struct drm_encoder *encoder, -				   struct drm_display_mode *mode, -				   struct drm_display_mode *adjusted_mode) -{ -	struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder); -	struct mdfld_dsi_dpi_output *dpi_output = MDFLD_DSI_DPI_OUTPUT(dsi_encoder); -	struct mdfld_dsi_config *dsi_config = mdfld_dsi_encoder_get_config(dsi_encoder); -	struct drm_device *dev = dsi_config->dev; -	struct drm_psb_private *dev_priv = dev->dev_private; -	int pipe = mdfld_dsi_encoder_get_pipe(dsi_encoder); -	 -	u32 pipeconf_reg = PIPEACONF; -	u32 dspcntr_reg = DSPACNTR; -	u32 mipi_reg = MIPI; -	u32 reg_offset = 0; -	 -	u32 pipeconf = dev_priv->pipeconf; -	u32 dspcntr = dev_priv->dspcntr; -	u32 mipi = MIPI_PORT_EN | PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX; -	 -	dev_dbg(dev->dev, "set mode %dx%d on pipe %d\n", -				mode->hdisplay, mode->vdisplay, pipe); - -	if(pipe) { -		pipeconf_reg = PIPECCONF; -		dspcntr_reg = DSPCCNTR; -		mipi_reg = MIPI_C; -		reg_offset = MIPIC_REG_OFFSET; -	} else { -		mipi |= 2; -	} -	 -	if (!gma_power_begin(dev, true)) -		return; - -	/* Set up mipi port FIXME: do at init time */ -	REG_WRITE(mipi_reg, mipi); -	REG_READ(mipi_reg); - -	/* Set up DSI controller DPI interface */ -	mdfld_dsi_dpi_controller_init(dsi_config, pipe); - -	if (mdfld_get_panel_type(dev, pipe) != TMD_VID) { -		/* Turn on DPI interface */ -		mdfld_dsi_dpi_turn_on(dpi_output, pipe); -	} -	 -	/* Set up pipe */ -	REG_WRITE(pipeconf_reg, pipeconf); -	REG_READ(pipeconf_reg); -	 -	/* Set up display plane */ -	REG_WRITE(dspcntr_reg, dspcntr); -	REG_READ(dspcntr_reg); -	 -	msleep(20); /* FIXME: this should wait for vblank */ -	 -	dev_dbg(dev->dev, "State %x, power %d\n", -		REG_READ(MIPIA_INTR_STAT_REG + reg_offset), -		dpi_output->panel_on); - -	if (mdfld_get_panel_type(dev, pipe) != TMD_VID) { -		/* Init driver ic */ -		mdfld_dsi_tpo_ic_init(dsi_config, pipe); -		/* Init backlight */ -		mdfld_dsi_brightness_init(dsi_config, pipe); -	} -	gma_power_end(dev); -} - - -/* - * Init DSI DPI encoder.  - * Allocate an mdfld_dsi_encoder and attach it to given @dsi_connector - * return pointer of newly allocated DPI encoder, NULL on error - */  -struct mdfld_dsi_encoder *mdfld_dsi_dpi_init(struct drm_device *dev,  -				struct mdfld_dsi_connector *dsi_connector, -				struct panel_funcs *p_funcs) -{ -	struct mdfld_dsi_dpi_output *dpi_output = NULL; -	struct mdfld_dsi_config *dsi_config; -	struct drm_connector *connector = NULL; -	struct drm_encoder *encoder = NULL; -	struct drm_display_mode *fixed_mode = NULL; -	int pipe; -	u32 data; -	int ret; - -	if (!dsi_connector || !p_funcs) { -		WARN_ON(1); -		return NULL; -	} - -	dsi_config = mdfld_dsi_get_config(dsi_connector); -	pipe = dsi_connector->pipe; - -	/* Panel hard-reset */ -	if (p_funcs->reset) { -		ret = p_funcs->reset(pipe); -		if (ret) { -			DRM_ERROR("Panel %d hard-reset failed\n", pipe); -			return NULL; -		} -	} - -	/* Panel drvIC init */ -	if (p_funcs->drv_ic_init) -		p_funcs->drv_ic_init(dsi_config, pipe); - -	/* Panel power mode detect */ -	ret = mdfld_dsi_get_power_mode(dsi_config, -					&data, -					MDFLD_DSI_LP_TRANSMISSION); -	if (ret) { -		DRM_ERROR("Panel %d get power mode failed\n", pipe); -		dsi_connector->status = connector_status_disconnected; -	} else { -		DRM_INFO("pipe %d power mode 0x%x\n", pipe, data); -		dsi_connector->status = connector_status_connected; -	} - -	dpi_output = kzalloc(sizeof(struct mdfld_dsi_dpi_output), GFP_KERNEL); -	if(!dpi_output) { -		dev_err(dev->dev, "No memory for dsi_dpi_output\n"); -		return NULL; -	} - -	if(dsi_connector->pipe)  -		dpi_output->panel_on = 0; -	else -		dpi_output->panel_on = 0; -	 -	dpi_output->dev = dev; -	dpi_output->p_funcs = p_funcs; -	dpi_output->first_boot = 1; -	 -	/* Get fixed mode */ -	dsi_config = mdfld_dsi_get_config(dsi_connector); -	fixed_mode = dsi_config->fixed_mode; -	 -	/* Create drm encoder object */ -	connector = &dsi_connector->base.base; -	encoder = &dpi_output->base.base; -	/* -	 * On existing hardware this will be a panel of some form, -	 * if future devices also have HDMI bridges this will need -	 * revisiting -	 */ -	drm_encoder_init(dev, -			encoder, -			p_funcs->encoder_funcs, -			DRM_MODE_ENCODER_LVDS); -	drm_encoder_helper_add(encoder, -				p_funcs->encoder_helper_funcs); -	 -	/* Attach to given connector */ -	drm_mode_connector_attach_encoder(connector, encoder); -	 -	/* Set possible crtcs and clones */ -	if(dsi_connector->pipe) { -		encoder->possible_crtcs = (1 << 2); -		encoder->possible_clones = (1 << 1); -	} else { -		encoder->possible_crtcs = (1 << 0); -		encoder->possible_clones = (1 << 0); -	} -	return &dpi_output->base; -} - diff --git a/drivers/staging/gma500/mdfld_dsi_dpi.h b/drivers/staging/gma500/mdfld_dsi_dpi.h deleted file mode 100644 index ed92d45ee74..00000000000 --- a/drivers/staging/gma500/mdfld_dsi_dpi.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright © 2010 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Authors: - * jim liu <jim.liu@intel.com> - * Jackie Li<yaodong.li@intel.com> - */ - -#ifndef __MDFLD_DSI_DPI_H__ -#define __MDFLD_DSI_DPI_H__ - -#include "mdfld_dsi_output.h" -#include "mdfld_output.h" - -struct mdfld_dsi_dpi_timing { -	u16 hsync_count; -	u16 hbp_count; -	u16 hfp_count; -	u16 hactive_count; -	u16 vsync_count; -	u16 vbp_count; -	u16 vfp_count; -}; - -struct mdfld_dsi_dpi_output { -	struct mdfld_dsi_encoder base; -	struct drm_device *dev; - -	int panel_on; -	int first_boot; - -	struct panel_funcs *p_funcs; -}; - -#define MDFLD_DSI_DPI_OUTPUT(dsi_encoder) \ -	container_of(dsi_encoder, struct mdfld_dsi_dpi_output, base) - -extern int mdfld_dsi_dpi_timing_calculation(struct drm_display_mode *mode, -			struct mdfld_dsi_dpi_timing *dpi_timing, -			int num_lane, int bpp); -extern struct mdfld_dsi_encoder *mdfld_dsi_dpi_init(struct drm_device *dev, -			struct mdfld_dsi_connector *dsi_connector, -			struct panel_funcs *p_funcs); - -/* Medfield DPI helper functions */ -extern void mdfld_dsi_dpi_dpms(struct drm_encoder *encoder, int mode); -extern bool mdfld_dsi_dpi_mode_fixup(struct drm_encoder *encoder, -			struct drm_display_mode *mode, -			struct drm_display_mode *adjusted_mode); -extern void mdfld_dsi_dpi_prepare(struct drm_encoder *encoder); -extern void mdfld_dsi_dpi_commit(struct drm_encoder *encoder); -extern void mdfld_dsi_dpi_mode_set(struct drm_encoder *encoder, -			struct drm_display_mode *mode, -			struct drm_display_mode *adjusted_mode); -extern void mdfld_dsi_dpi_turn_on(struct mdfld_dsi_dpi_output *output, -			int pipe); -extern void mdfld_dsi_dpi_controller_init(struct mdfld_dsi_config *si_config, -			int pipe); -#endif /*__MDFLD_DSI_DPI_H__*/ diff --git a/drivers/staging/gma500/mdfld_dsi_output.c b/drivers/staging/gma500/mdfld_dsi_output.c deleted file mode 100644 index 3f979db2c3a..00000000000 --- a/drivers/staging/gma500/mdfld_dsi_output.c +++ /dev/null @@ -1,1014 +0,0 @@ -/* - * Copyright © 2010 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Authors: - * jim liu <jim.liu@intel.com> - * Jackie Li<yaodong.li@intel.com> - */ - -#include "mdfld_dsi_output.h" -#include "mdfld_dsi_dbi.h" -#include "mdfld_dsi_dpi.h" -#include "mdfld_output.h" -#include <asm/intel_scu_ipc.h> -#include "mdfld_dsi_pkg_sender.h" -#include <linux/pm_runtime.h> -#include <linux/moduleparam.h> - -#define MDFLD_DSI_BRIGHTNESS_MAX_LEVEL 100 - -static int CABC_control = 1; -static int LABC_control = 1; - -module_param (CABC_control, int, 0644); -module_param (LABC_control, int, 0644); - -/** - * make these MCS command global  - * we don't need 'movl' everytime we send them. - * FIXME: these datas were provided by OEM, we should get them from GCT. - **/ -static u32 mdfld_dbi_mcs_hysteresis[] = { -	0x42000f57, 0x8c006400, 0xff00bf00, 0xffffffff, -	0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, -	0x38000aff, 0x82005000, 0xff00ab00, 0xffffffff, -	0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, -	0x000000ff, -}; - -static u32 mdfld_dbi_mcs_display_profile[] = { -	0x50281450, 0x0000c882, 0x00000000, 0x00000000, -	0x00000000, -}; - -static u32 mdfld_dbi_mcs_kbbc_profile[] = { -	0x00ffcc60, 0x00000000, 0x00000000, 0x00000000, -};  -	 -static u32 mdfld_dbi_mcs_gamma_profile[] = { -	0x81111158, 0x88888888, 0x88888888, -};  - -/* - * write hysteresis values. - */ -static void mdfld_dsi_write_hysteresis (struct mdfld_dsi_config *dsi_config, -                                                                int pipe) -{ -	struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_get_pkg_sender(dsi_config); - -	if(!sender) { -	        WARN_ON(1); -		return; -	} -	mdfld_dsi_send_mcs_long_hs(sender, -				   mdfld_dbi_mcs_hysteresis, -				   17, -				   MDFLD_DSI_SEND_PACKAGE); -} - -/* - * write display profile values. - */ -static void mdfld_dsi_write_display_profile(struct mdfld_dsi_config *dsi_config, int pipe) -{ -	struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_get_pkg_sender(dsi_config); - -	if(!sender) { -	        WARN_ON(1); -		return; -        } -	mdfld_dsi_send_mcs_long_hs(sender, -				   mdfld_dbi_mcs_display_profile, -				   5, -				   MDFLD_DSI_SEND_PACKAGE); -} - -/* - * write KBBC profile values. - */ -static void mdfld_dsi_write_kbbc_profile (struct mdfld_dsi_config * dsi_config, int pipe) -{ -	struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_get_pkg_sender(dsi_config); - -	if(!sender) { -	        WARN_ON(1); -		return; -        } -	mdfld_dsi_send_mcs_long_hs(sender, -				   mdfld_dbi_mcs_kbbc_profile, -				   4, -				   MDFLD_DSI_SEND_PACKAGE); -} - -/* - * write gamma setting. - */ -static void mdfld_dsi_write_gamma_setting (struct mdfld_dsi_config *dsi_config, int pipe) -{ -	struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_get_pkg_sender(dsi_config); - -	if(!sender) { -	        WARN_ON(1); -		return; -	} -	mdfld_dsi_send_mcs_long_hs(sender, -				   mdfld_dbi_mcs_gamma_profile, -				   3, -				   MDFLD_DSI_SEND_PACKAGE); -} - -/* - * Check and see if the generic control or data buffer is empty and ready. - */ -void mdfld_dsi_gen_fifo_ready (struct drm_device *dev, u32 gen_fifo_stat_reg, u32 fifo_stat) -{ -	u32 GEN_BF_time_out_count = 0; -	 -	/* Check MIPI Adatper command registers */ -	for (GEN_BF_time_out_count = 0; GEN_BF_time_out_count < GEN_FB_TIME_OUT; GEN_BF_time_out_count++) -	{ -		if ((REG_READ(gen_fifo_stat_reg) & fifo_stat) == fifo_stat) -			break; -		udelay (100); -	} - -	if (GEN_BF_time_out_count == GEN_FB_TIME_OUT) -		dev_err(dev->dev, -        "mdfld_dsi_gen_fifo_ready, Timeout. gen_fifo_stat_reg = 0x%x. \n", -                                                gen_fifo_stat_reg); -} - -/* - * Manage the DSI MIPI keyboard and display brightness. - * FIXME: this is exported to OSPM code. should work out an specific  - * display interface to OSPM.  - */ -void mdfld_dsi_brightness_init(struct mdfld_dsi_config *dsi_config, int pipe) -{ -	struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_get_pkg_sender(dsi_config); -	struct drm_device *dev = sender->dev; -	struct drm_psb_private *dev_priv = dev->dev_private; -	u32 gen_ctrl_val; -	 -	if(!sender) { -	        WARN_ON(1); -	        return; -	} -	/* Set default display backlight value to 85% (0xd8)*/ -	mdfld_dsi_send_mcs_short_hs(sender, -				    write_display_brightness, -				    0xd8, -				    1, -				    MDFLD_DSI_SEND_PACKAGE); - -	/* Set minimum brightness setting of CABC function to 20% (0x33)*/ -	mdfld_dsi_send_mcs_short_hs(sender, -				    write_cabc_min_bright, -				    0x33, -				    1, -				    MDFLD_DSI_SEND_PACKAGE); - -	mdfld_dsi_write_hysteresis(dsi_config, pipe); -	mdfld_dsi_write_display_profile (dsi_config, pipe); -	mdfld_dsi_write_kbbc_profile (dsi_config, pipe); -	mdfld_dsi_write_gamma_setting (dsi_config, pipe); - -	/* Enable backlight or/and LABC */ -	gen_ctrl_val = BRIGHT_CNTL_BLOCK_ON | DISPLAY_DIMMING_ON| BACKLIGHT_ON; -	if (LABC_control == 1 || CABC_control == 1) -		gen_ctrl_val |= DISPLAY_DIMMING_ON| DISPLAY_BRIGHTNESS_AUTO | GAMMA_AUTO; - -	if (LABC_control == 1) -		gen_ctrl_val |= AMBIENT_LIGHT_SENSE_ON; - -	dev_priv->mipi_ctrl_display = gen_ctrl_val; - -	mdfld_dsi_send_mcs_short_hs(sender, -				    write_ctrl_display, -				    (u8)gen_ctrl_val, -				    1, -				    MDFLD_DSI_SEND_PACKAGE); - -	if (CABC_control == 0) -		return; -	mdfld_dsi_send_mcs_short_hs(sender, -				    write_ctrl_cabc, -				    UI_IMAGE, -				    1, -				    MDFLD_DSI_SEND_PACKAGE); -} - -/* - * Manage the mipi display brightness. - * TODO: refine this interface later - */ -void mdfld_dsi_brightness_control(struct drm_device *dev, int pipe, int level) -{ -	struct mdfld_dsi_pkg_sender *sender; -	struct drm_psb_private *dev_priv; -	struct mdfld_dsi_config *dsi_config; -	u32 gen_ctrl_val; -	int p_type;	 -	 -	if (!dev || (pipe != 0 && pipe != 2)) { -		dev_err(dev->dev, "Invalid parameter\n"); -		return; -	} - -	p_type = mdfld_get_panel_type(dev, 0); - -	dev_priv = dev->dev_private; - -	if(pipe) -		dsi_config = dev_priv->dsi_configs[1]; -	else -		dsi_config = dev_priv->dsi_configs[0]; - -	sender = mdfld_dsi_get_pkg_sender(dsi_config); - -	if(!sender) { -	        WARN_ON(1); -		return; -	} - -	gen_ctrl_val = ((level * 0xff) / MDFLD_DSI_BRIGHTNESS_MAX_LEVEL) & 0xff; - -	dev_dbg(dev->dev, -                "pipe = %d, gen_ctrl_val = %d.  \n", pipe, gen_ctrl_val); -	 -	if(p_type == TMD_VID || p_type == TMD_CMD){ -		/* Set display backlight value */ -		mdfld_dsi_send_mcs_short_hs(sender,  -					tmd_write_display_brightness,  -					(u8)gen_ctrl_val,  -	                                 1,  -	                        	MDFLD_DSI_SEND_PACKAGE);		 -	} else {			 -		/* Set display backlight value */ -		mdfld_dsi_send_mcs_short_hs(sender, -				    write_display_brightness, -				    (u8)gen_ctrl_val, -                                    1, -                                    MDFLD_DSI_SEND_PACKAGE); - - -		/* Enable backlight control */ -		if (level == 0) -			gen_ctrl_val = 0; -		else  -			gen_ctrl_val = dev_priv->mipi_ctrl_display; - -		mdfld_dsi_send_mcs_short_hs(sender, -                                    write_ctrl_display, -                                   (u8)gen_ctrl_val, -                                   1, -                                   MDFLD_DSI_SEND_PACKAGE); -	} -} - -/* - * shut down DSI controller - */  -void mdfld_dsi_controller_shutdown(struct mdfld_dsi_config * dsi_config, int pipe) -{ -	struct drm_device * dev; -	u32 reg_offset = pipe ? MIPIC_REG_OFFSET : 0; -	int retry = 100; -	 -	if (!dsi_config) { -	        WARN_ON(1); -		return; -	} -	 -	dev = dsi_config->dev; -	 -	if (!gma_power_begin(dev, true)) { -		dev_err(dev->dev, "hw begin failed\n"); -		return; -	} -		 -	if(!(REG_READ(MIPIA_DEVICE_READY_REG + reg_offset) &  DSI_DEVICE_READY))  -		goto shutdown_out; -	 -	/* Send shut down package, clean packet send bit first */ -	if(REG_READ(MIPIA_INTR_STAT_REG + reg_offset) & DSI_INTR_STATE_SPL_PKG_SENT) { -		REG_WRITE((MIPIA_INTR_STAT_REG + reg_offset),  -				(REG_READ(MIPIA_INTR_STAT_REG + reg_offset) | DSI_INTR_STATE_SPL_PKG_SENT)); -	} -	 -	/*send shut down package in HS*/ -	REG_WRITE((MIPIA_DPI_CONTROL_REG + reg_offset), DSI_DPI_CTRL_HS_SHUTDOWN); -	 -	 -	/* -	 * make sure shut down is sent. -	 * FIXME: add max retry counter -	 */ -	while(!(REG_READ(MIPIA_INTR_STAT_REG + reg_offset) & DSI_INTR_STATE_SPL_PKG_SENT)) { -		retry--; -		 -		if(!retry) { -			dev_err(dev->dev, "timeout\n"); -			break; -		} -	} -	 -	/*sleep 1 ms to ensure shutdown finished*/ -	msleep(100); -	 -	/*un-ready device*/ -	REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), -			   (REG_READ(MIPIA_DEVICE_READY_REG + reg_offset) & ~DSI_DEVICE_READY)); - -shutdown_out:			    -	gma_power_end(dev); -} - -void mdfld_dsi_controller_startup(struct mdfld_dsi_config * dsi_config, int pipe) -{ -	struct drm_device * dev; -	u32 reg_offset = pipe ? MIPIC_REG_OFFSET : 0; -	int retry = 100; -	 -	 -	if (!dsi_config) { -		WARN_ON(1); -		return; -	} -	 -	dev = dsi_config->dev; -	dev_dbg(dev->dev, "starting up DSI controller on pipe %d...\n", pipe); -	 -	if (!gma_power_begin(dev, true)) { -		dev_err(dev->dev, "hw begin failed\n"); -		return; -	} -	 -	if((REG_READ(MIPIA_DEVICE_READY_REG + reg_offset) & DSI_DEVICE_READY))  -		goto startup_out; -	 -	/*if config DPI, turn on DPI interface*/ -	if(dsi_config->type == MDFLD_DSI_ENCODER_DPI) { -		if(REG_READ(MIPIA_INTR_STAT_REG + reg_offset) & DSI_INTR_STATE_SPL_PKG_SENT) { -			REG_WRITE((MIPIA_INTR_STAT_REG + reg_offset), DSI_INTR_STATE_SPL_PKG_SENT); -		} -		 -		REG_WRITE((MIPIA_DPI_CONTROL_REG + reg_offset), DSI_DPI_CTRL_HS_TURN_ON); -		 -		/* -		 * make sure shut down is sent. -		 * FIXME: add max retry counter -		 */ -		while(!(REG_READ(MIPIA_INTR_STAT_REG + reg_offset) & DSI_INTR_STATE_SPL_PKG_SENT)) { -			retry--; -			if(!retry) { -				dev_err(dev->dev, "timeout\n"); -				break; -			} -		} -		 -		msleep(100); -	} -	 -	/*set device ready*/ -	REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), -			   (REG_READ(MIPIA_DEVICE_READY_REG + reg_offset) | DSI_DEVICE_READY)); - -startup_out:	 -	gma_power_end(dev); -} - - -static int mdfld_dsi_get_panel_status(struct mdfld_dsi_config *dsi_config, -					u8 dcs, -					u32 *data, -					u8 transmission) -{ -	struct mdfld_dsi_pkg_sender *sender -		= mdfld_dsi_get_pkg_sender(dsi_config); - -	if (!sender || !data) { -		DRM_ERROR("Invalid parameter\n"); -		return -EINVAL; -	} - -	if (transmission == MDFLD_DSI_HS_TRANSMISSION) -		return mdfld_dsi_read_mcs_hs(sender, dcs, data, 1); -	else if (transmission == MDFLD_DSI_LP_TRANSMISSION) -		return mdfld_dsi_read_mcs_lp(sender, dcs, data, 1); -	else -		return -EINVAL; -} - -int mdfld_dsi_get_power_mode(struct mdfld_dsi_config *dsi_config, -				u32 *mode, -				u8 transmission) -{ -	if (!dsi_config || !mode) { -		DRM_ERROR("Invalid parameter\n"); -		return -EINVAL; -	} - -	return mdfld_dsi_get_panel_status(dsi_config, 0x0a, mode, transmission); -} - -int mdfld_dsi_get_diagnostic_result(struct mdfld_dsi_config *dsi_config, -					u32 *result, -					u8 transmission) -{ -	if (!dsi_config || !result) { -		DRM_ERROR("Invalid parameter\n"); -		return -EINVAL; -	} - -	return mdfld_dsi_get_panel_status(dsi_config, 0x0f, result, -					  transmission); -} - -/* - * NOTE: this function was used by OSPM. - * TODO: will be removed later, should work out display interfaces for OSPM - */ -void mdfld_dsi_controller_init(struct mdfld_dsi_config * dsi_config, int pipe) -{ -	if(!dsi_config || ((pipe != 0) && (pipe != 2))) { -	        WARN_ON(1); -		return; -	} - -	if(dsi_config->type) -		mdfld_dsi_dpi_controller_init(dsi_config, pipe); -	else -		mdfld_dsi_controller_dbi_init(dsi_config, pipe); -} - -static void mdfld_dsi_connector_save(struct drm_connector * connector) -{ -} - -static void mdfld_dsi_connector_restore(struct drm_connector * connector) -{ -} - -static enum drm_connector_status mdfld_dsi_connector_detect(struct drm_connector * connector, bool force) -{ -	struct psb_intel_output *psb_output -					= to_psb_intel_output(connector); -	struct mdfld_dsi_connector *dsi_connector -	                                = MDFLD_DSI_CONNECTOR(psb_output); -	return dsi_connector->status; -} - -static int mdfld_dsi_connector_set_property(struct drm_connector *connector, -					struct drm_property *property, -					uint64_t value) -{ -	struct drm_encoder *encoder = connector->encoder; - -	if (!strcmp(property->name, "scaling mode") && encoder) { -		struct psb_intel_crtc * psb_crtc = to_psb_intel_crtc(encoder->crtc); -		bool bTransitionFromToCentered; -		uint64_t curValue; - -		if (!psb_crtc) -			goto set_prop_error; - -		switch (value) { -		case DRM_MODE_SCALE_FULLSCREEN: -			break; -		case DRM_MODE_SCALE_NO_SCALE: -			break; -		case DRM_MODE_SCALE_ASPECT: -			break; -		default: -			goto set_prop_error; -		} - -		if (drm_connector_property_get_value(connector, property, &curValue)) -			goto set_prop_error; - -		if (curValue == value) -			goto set_prop_done; - -		if (drm_connector_property_set_value(connector, property, value)) -			goto set_prop_error; - -		bTransitionFromToCentered = (curValue == DRM_MODE_SCALE_NO_SCALE) || -			(value == DRM_MODE_SCALE_NO_SCALE); - -		if (psb_crtc->saved_mode.hdisplay != 0 && -		    psb_crtc->saved_mode.vdisplay != 0) { -			if (bTransitionFromToCentered) { -				if (!drm_crtc_helper_set_mode(encoder->crtc, &psb_crtc->saved_mode, -					    encoder->crtc->x, encoder->crtc->y, encoder->crtc->fb)) -					goto set_prop_error; -			} else { -				struct drm_encoder_helper_funcs *pEncHFuncs  = encoder->helper_private; -				pEncHFuncs->mode_set(encoder, &psb_crtc->saved_mode, -						     &psb_crtc->saved_adjusted_mode); -			} -		} -#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE -	} else if (!strcmp(property->name, "backlight") && encoder) { -		struct drm_psb_private *dev_priv = encoder->dev->dev_private; -		struct backlight_device *psb_bd = dev_priv->backlight_device; -		dev_dbg(encoder->dev->dev, "backlight level = %d\n", (int)value); -		if (drm_connector_property_set_value(connector, property, value)) -			goto set_prop_error; -		else { -			dev_dbg(encoder->dev->dev, -			                "set brightness to %d", (int)value); -			if (psb_bd) { -				psb_bd->props.brightness = value; -				backlight_update_status(psb_bd); -			} -		} -#endif -	} -set_prop_done: -    return 0; -set_prop_error: -    return -1; -} - -static void mdfld_dsi_connector_destroy(struct drm_connector *connector) -{ -	struct psb_intel_output * psb_output = to_psb_intel_output(connector); -	struct mdfld_dsi_connector * dsi_connector = MDFLD_DSI_CONNECTOR(psb_output); -	struct mdfld_dsi_pkg_sender * sender; -	 -	if(!dsi_connector) -	        return; -	 -	drm_sysfs_connector_remove(connector); -	drm_connector_cleanup(connector); -	 -	sender = dsi_connector->pkg_sender; - -	mdfld_dsi_pkg_sender_destroy(sender); - -	kfree(dsi_connector); -} - -static int mdfld_dsi_connector_get_modes(struct drm_connector * connector) -{ -	struct psb_intel_output * psb_output = to_psb_intel_output(connector); -	struct mdfld_dsi_connector * dsi_connector = MDFLD_DSI_CONNECTOR(psb_output); -	struct mdfld_dsi_config * dsi_config = mdfld_dsi_get_config(dsi_connector); -	struct drm_display_mode * fixed_mode = dsi_config->fixed_mode; -	struct drm_display_mode * dup_mode = NULL; -	struct drm_device * dev = connector->dev; -	 -	connector->display_info.min_vfreq = 0; -	connector->display_info.max_vfreq = 200; -	connector->display_info.min_hfreq = 0; -	connector->display_info.max_hfreq = 200; - -	if(fixed_mode) { -		dev_dbg(dev->dev, "fixed_mode %dx%d\n", -		        fixed_mode->hdisplay, fixed_mode->vdisplay); -		 -		dup_mode = drm_mode_duplicate(dev, fixed_mode); -		drm_mode_probed_add(connector, dup_mode); -		return 1; -	} -	dev_err(dev->dev, "Didn't get any modes!\n"); -	return 0; -} - -static int mdfld_dsi_connector_mode_valid(struct drm_connector * connector, struct drm_display_mode * mode) -{ -	struct psb_intel_output * psb_output = to_psb_intel_output(connector); -	struct mdfld_dsi_connector * dsi_connector = MDFLD_DSI_CONNECTOR(psb_output); -	struct mdfld_dsi_config * dsi_config = mdfld_dsi_get_config(dsi_connector); -	struct drm_display_mode * fixed_mode = dsi_config->fixed_mode; - -	dev_dbg(connector->dev->dev, "mode %p, fixed mode %p\n", -	                                                mode, fixed_mode); - -	if(mode->flags & DRM_MODE_FLAG_DBLSCAN)  -		return MODE_NO_DBLESCAN; - -	if(mode->flags & DRM_MODE_FLAG_INTERLACE) -		return MODE_NO_INTERLACE; - -	/** -	 * FIXME: current DC has no fitting unit, reject any mode setting request -	 * will figure out a way to do up-scaling(pannel fitting) later.   -	 **/ -	if(fixed_mode) { -		if(mode->hdisplay != fixed_mode->hdisplay) -			return MODE_PANEL; - -		if(mode->vdisplay != fixed_mode->vdisplay) -			return MODE_PANEL; -	} -	dev_dbg(connector->dev->dev, "mode ok\n"); - -	return MODE_OK; -} - -static void mdfld_dsi_connector_dpms(struct drm_connector *connector, int mode) -{ -#ifdef CONFIG_PM_RUNTIME -	struct drm_device * dev = connector->dev; -	struct drm_psb_private * dev_priv = dev->dev_private; -	bool panel_on, panel_on2; -#endif -	/* First, execute DPMS */ -	drm_helper_connector_dpms(connector, mode); - -#ifdef CONFIG_PM_RUNTIME -	if(mdfld_panel_dpi(dev)) { -		/* DPI panel */ -		panel_on = dev_priv->dpi_panel_on; -		panel_on2 = dev_priv->dpi_panel_on2; -	} else { -		/* DBI panel */ -		panel_on = dev_priv->dbi_panel_on; -		panel_on2 = dev_priv->dbi_panel_on2; -	} - -	/* Then check all display panels + monitors status */ -	/* Make sure that the Display (B) sub-system status isn't i3 when -	 * R/W the DC register, otherwise "Fabric error" issue would occur -	 * during S0i3 state. */ -	if(!panel_on && !panel_on2 && !(REG_READ(HDMIB_CONTROL) -	                                        & HDMIB_PORT_EN)) { -		/* Request rpm idle */ -		if(dev_priv->rpm_enabled) -			pm_request_idle(&dev->pdev->dev); -	} -	/* -	 * if rpm wasn't enabled yet, try to allow it -	 * FIXME: won't enable rpm for DPI since DPI -	 * CRTC setting is a little messy now. -	 * Enable it later! -	 */ -#if 0 -	if(!dev_priv->rpm_enabled && !mdfld_panel_dpi(dev)) -		ospm_runtime_pm_allow(dev); -#endif -#endif -} - -static struct drm_encoder *mdfld_dsi_connector_best_encoder( -                                        struct drm_connector *connector)  -{ -	struct psb_intel_output * psb_output = to_psb_intel_output(connector); -	struct mdfld_dsi_connector * dsi_connector = MDFLD_DSI_CONNECTOR(psb_output); -	struct mdfld_dsi_config * dsi_config = mdfld_dsi_get_config(dsi_connector); -	struct mdfld_dsi_encoder * encoder = NULL; -	 -	if(dsi_config->type == MDFLD_DSI_ENCODER_DBI)  -		encoder = dsi_config->encoders[MDFLD_DSI_ENCODER_DBI]; -	else if (dsi_config->type == MDFLD_DSI_ENCODER_DPI)  -		encoder = dsi_config->encoders[MDFLD_DSI_ENCODER_DPI]; -	 -	dev_dbg(connector->dev->dev, "get encoder %p\n", encoder); -	 -	if(!encoder) { -		dev_err(connector->dev->dev, -                        "Invalid encoder for type %d\n", dsi_config->type); -		return NULL; -	} -	dsi_config->encoder = encoder;	 -	return &encoder->base;	 -} - -/* DSI connector funcs */ -static const struct drm_connector_funcs mdfld_dsi_connector_funcs = { -	.dpms = /*drm_helper_connector_dpms*/mdfld_dsi_connector_dpms, -	.save = mdfld_dsi_connector_save, -	.restore = mdfld_dsi_connector_restore, -	.detect = mdfld_dsi_connector_detect, -	.fill_modes = drm_helper_probe_single_connector_modes, -	.set_property = mdfld_dsi_connector_set_property, -	.destroy = mdfld_dsi_connector_destroy, -}; - -/* DSI connector helper funcs */ -static const struct drm_connector_helper_funcs mdfld_dsi_connector_helper_funcs = { -	.get_modes = mdfld_dsi_connector_get_modes, -	.mode_valid = mdfld_dsi_connector_mode_valid, -	.best_encoder = mdfld_dsi_connector_best_encoder, -}; - -static int mdfld_dsi_get_default_config(struct drm_device * dev,  -										struct mdfld_dsi_config * config, int pipe) -{ -	if(!dev || !config) { -	        WARN_ON(1); -		return -EINVAL; -	} -	 -	config->bpp = 24; -	config->type = mdfld_panel_dpi(dev); -	config->lane_count = 2; -	config->channel_num = 0; -	/*NOTE: video mode is ignored when type is MDFLD_DSI_ENCODER_DBI*/ -	if (mdfld_get_panel_type(dev, pipe) == TMD_VID) { -		config->video_mode = MDFLD_DSI_VIDEO_NON_BURST_MODE_SYNC_PULSE; -	} else { -		config->video_mode = MDFLD_DSI_VIDEO_BURST_MODE; -	} -	 -	return 0; -} - -/* - * Returns the panel fixed mode from configuration.  - */ -struct drm_display_mode * -mdfld_dsi_get_configuration_mode(struct mdfld_dsi_config * dsi_config, int pipe) -{ -	struct drm_device *dev = dsi_config->dev; -	struct drm_display_mode *mode; -	struct drm_psb_private *dev_priv = dev->dev_private; -	struct mrst_timing_info *ti = &dev_priv->gct_data.DTD; -	bool use_gct = false; - -	mode = kzalloc(sizeof(*mode), GFP_KERNEL); -	if (!mode) { -	        dev_err(dev->dev, "Out of memory for mode\n"); -		return NULL; -        } -	if (use_gct) { -		dev_dbg(dev->dev, "gct find MIPI panel.\n"); - -		mode->hdisplay = (ti->hactive_hi << 8) | ti->hactive_lo; -		mode->vdisplay = (ti->vactive_hi << 8) | ti->vactive_lo; -		mode->hsync_start = mode->hdisplay + \ -				((ti->hsync_offset_hi << 8) | \ -				ti->hsync_offset_lo); -		mode->hsync_end = mode->hsync_start + \ -				((ti->hsync_pulse_width_hi << 8) | \ -				ti->hsync_pulse_width_lo); -		mode->htotal = mode->hdisplay + ((ti->hblank_hi << 8) | \ -								ti->hblank_lo); -		mode->vsync_start = \ -			mode->vdisplay + ((ti->vsync_offset_hi << 8) | \ -						ti->vsync_offset_lo); -		mode->vsync_end = \ -			mode->vsync_start + ((ti->vsync_pulse_width_hi << 8) | \ -						ti->vsync_pulse_width_lo); -		mode->vtotal = mode->vdisplay + \ -				((ti->vblank_hi << 8) | ti->vblank_lo); -		mode->clock = ti->pixel_clock * 10; -	} else { -		if(dsi_config->type == MDFLD_DSI_ENCODER_DPI) {  -			if (mdfld_get_panel_type(dev, pipe) == TMD_VID) { -				mode->hdisplay = 480; -				mode->vdisplay = 854; -				mode->hsync_start = 487; -				mode->hsync_end = 490; -				mode->htotal = 499; -				mode->vsync_start = 861; -				mode->vsync_end = 865; -				mode->vtotal = 873; -				mode->clock = 33264; -			} else { -				mode->hdisplay = 864; -				mode->vdisplay = 480; -				mode->hsync_start = 873; -				mode->hsync_end = 876; -				mode->htotal = 887; -				mode->vsync_start = 487; -				mode->vsync_end = 490; -				mode->vtotal = 499; -				mode->clock = 33264; -			} -		} else if(dsi_config->type == MDFLD_DSI_ENCODER_DBI) { -			mode->hdisplay = 864; -			mode->vdisplay = 480; -			mode->hsync_start = 872; -			mode->hsync_end = 876; -			mode->htotal = 884; -			mode->vsync_start = 482; -			mode->vsync_end = 494; -			mode->vtotal = 486; -			mode->clock = 25777; -			 -		} -	} - -	drm_mode_set_name(mode); -	drm_mode_set_crtcinfo(mode, 0); -	 -	mode->type |= DRM_MODE_TYPE_PREFERRED; - -	return mode; -} - -int mdfld_dsi_panel_reset(int pipe) -{ -	unsigned gpio; -	int ret = 0; - -	switch (pipe) { -	case 0: -		gpio = 128; -		break; -	case 2: -		gpio = 34; -		break; -	default: -		DRM_ERROR("Invalid output\n"); -		return -EINVAL; -	} - -	ret = gpio_request(gpio, "gfx"); -	if (ret) { -		DRM_ERROR("gpio_rqueset failed\n"); -		return ret; -	} - -	ret = gpio_direction_output(gpio, 1); -	if (ret) { -		DRM_ERROR("gpio_direction_output failed\n"); -		goto gpio_error; -	} - -	gpio_get_value(128); - -gpio_error: -	if (gpio_is_valid(gpio)) -		gpio_free(gpio); - -	return ret; -} - -/* - * MIPI output init - * @dev drm device - * @pipe pipe number. 0 or 2 - * @config  - *  - * Do the initialization of a MIPI output, including create DRM mode objects - * initialization of DSI output on @pipe  - */ -void mdfld_dsi_output_init(struct drm_device *dev, -			   int pipe,  -			   struct mdfld_dsi_config *config, -			   struct panel_funcs* p_cmd_funcs, -			   struct panel_funcs* p_vid_funcs) -{ -	struct mdfld_dsi_config * dsi_config; -	struct mdfld_dsi_connector * dsi_connector; -	struct psb_intel_output * psb_output; -	struct drm_connector * connector; -	struct mdfld_dsi_encoder * encoder; -	struct drm_psb_private * dev_priv = dev->dev_private; -	struct panel_info dsi_panel_info; -	u32 width_mm, height_mm; - -	dev_dbg(dev->dev, "init DSI output on pipe %d\n", pipe); -	 -	if(!dev || ((pipe != 0) && (pipe != 2))) { -	        WARN_ON(1); -		return; -	} -	 -	/*create a new connetor*/ -	dsi_connector = kzalloc(sizeof(struct mdfld_dsi_connector), GFP_KERNEL); -	if(!dsi_connector) { -		DRM_ERROR("No memory"); -		return; -	} -	 -	dsi_connector->pipe =  pipe; -	 -	/*set DSI config*/ -	if(config) {  -		dsi_config = config; -	} else { -		dsi_config = kzalloc(sizeof(struct mdfld_dsi_config), GFP_KERNEL); -		if(!dsi_config) { -			dev_err(dev->dev, -			        "cannot allocate memory for DSI config\n"); -			goto dsi_init_err0; -		} -		 -		mdfld_dsi_get_default_config(dev, dsi_config, pipe); -	} -	 -	dsi_connector->private = dsi_config; -	 -	dsi_config->changed = 1; -	dsi_config->dev = dev; -	 -	/* Init fixed mode basing on DSI config type */ -	if(dsi_config->type == MDFLD_DSI_ENCODER_DBI) { -		dsi_config->fixed_mode = p_cmd_funcs->get_config_mode(dev); -		if(p_cmd_funcs->get_panel_info(dev, pipe, &dsi_panel_info)) -			goto dsi_init_err0; -	} else if(dsi_config->type == MDFLD_DSI_ENCODER_DPI) { -		dsi_config->fixed_mode = p_vid_funcs->get_config_mode(dev); -		if(p_vid_funcs->get_panel_info(dev, pipe, &dsi_panel_info)) -			goto dsi_init_err0; -	} - -	width_mm = dsi_panel_info.width_mm; -	height_mm = dsi_panel_info.height_mm; - -	dsi_config->mode = dsi_config->fixed_mode; -	dsi_config->connector = dsi_connector; -	 -	if(!dsi_config->fixed_mode) { -		dev_err(dev->dev, "No pannel fixed mode was found\n"); -		goto dsi_init_err0; -	} -	 -	if(pipe && dev_priv->dsi_configs[0]) { -		dsi_config->dvr_ic_inited = 0; -		dev_priv->dsi_configs[1] = dsi_config; -	} else if(pipe == 0) { -		dsi_config->dvr_ic_inited = 1; -		dev_priv->dsi_configs[0] = dsi_config; -	} else { -		dev_err(dev->dev, "Trying to init MIPI1 before MIPI0\n"); -		goto dsi_init_err0; -	} - -	/*init drm connector object*/ -	psb_output = &dsi_connector->base; -	 -	psb_output->type = (pipe == 0) ? INTEL_OUTPUT_MIPI : INTEL_OUTPUT_MIPI2; - -	connector = &psb_output->base; -	/* Revisit type if MIPI/HDMI bridges ever appear on Medfield */ -	drm_connector_init(dev, connector, &mdfld_dsi_connector_funcs, -						DRM_MODE_CONNECTOR_LVDS); -	drm_connector_helper_add(connector, &mdfld_dsi_connector_helper_funcs); -	 -	connector->display_info.subpixel_order = SubPixelHorizontalRGB; -	connector->display_info.width_mm = width_mm; -	connector->display_info.height_mm = height_mm; -	connector->interlace_allowed = false; -	connector->doublescan_allowed = false; -	 -	/* Attach properties */ -	drm_connector_attach_property(connector, dev->mode_config.scaling_mode_property, DRM_MODE_SCALE_FULLSCREEN); -	drm_connector_attach_property(connector, dev_priv->backlight_property, MDFLD_DSI_BRIGHTNESS_MAX_LEVEL); - -	/* Init DSI package sender on this output */ -	if (mdfld_dsi_pkg_sender_init(dsi_connector, pipe)) { -		DRM_ERROR("Package Sender initialization failed on pipe %d\n", pipe); -		goto dsi_init_err0; -	} - -	/* Init DBI & DPI encoders */ -	if (p_cmd_funcs) { -		encoder = mdfld_dsi_dbi_init(dev, dsi_connector, p_cmd_funcs); -		if(!encoder) { -			dev_err(dev->dev, "Create DBI encoder failed\n"); -			goto dsi_init_err1; -		} -		encoder->private = dsi_config; -		dsi_config->encoders[MDFLD_DSI_ENCODER_DBI] = encoder; -	} -	 -	if(p_vid_funcs) { -		encoder = mdfld_dsi_dpi_init(dev, dsi_connector, p_vid_funcs); -		if(!encoder) { -			dev_err(dev->dev, "Create DPI encoder failed\n"); -			goto dsi_init_err1; -		} -		encoder->private = dsi_config; -		dsi_config->encoders[MDFLD_DSI_ENCODER_DPI] = encoder; -	} -	 -	drm_sysfs_connector_add(connector); -	return; -	 -	/*TODO: add code to destroy outputs on error*/ -dsi_init_err1: -	/*destroy sender*/ -	mdfld_dsi_pkg_sender_destroy(dsi_connector->pkg_sender); - -	drm_connector_cleanup(connector); -	kfree(dsi_config->fixed_mode); -	kfree(dsi_config); -dsi_init_err0: -	kfree(dsi_connector); -} diff --git a/drivers/staging/gma500/mdfld_dsi_output.h b/drivers/staging/gma500/mdfld_dsi_output.h deleted file mode 100644 index 4699267efd6..00000000000 --- a/drivers/staging/gma500/mdfld_dsi_output.h +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright © 2010 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Authors: - * jim liu <jim.liu@intel.com> - * Jackie Li<yaodong.li@intel.com> - */ - -#ifndef __MDFLD_DSI_OUTPUT_H__ -#define __MDFLD_DSI_OUTPUT_H__ - -#include <linux/backlight.h> -#include <drm/drmP.h> -#include <drm/drm.h> -#include <drm/drm_crtc.h> -#include <drm/drm_edid.h> - -#include "psb_drv.h" -#include "psb_intel_drv.h" -#include "psb_intel_reg.h" -#include "power.h" -#include "mdfld_output.h" - -#include <asm/mrst.h> - - -static inline struct mdfld_dsi_config * -	mdfld_dsi_get_config(struct mdfld_dsi_connector *connector) -{ -	if (!connector) -		return NULL; -	return (struct mdfld_dsi_config *)connector->private; -} - -static inline void *mdfld_dsi_get_pkg_sender(struct mdfld_dsi_config *config) -{ -	struct mdfld_dsi_connector *dsi_connector; - -	if (!config) -		return NULL; - -	dsi_connector = config->connector; - -	if (!dsi_connector) -		return NULL; - -	return dsi_connector->pkg_sender; -} - -static inline struct mdfld_dsi_config * -	mdfld_dsi_encoder_get_config(struct mdfld_dsi_encoder *encoder) -{ -	if (!encoder) -		return NULL; -	return (struct mdfld_dsi_config *)encoder->private; -} - -static inline struct mdfld_dsi_connector * -	mdfld_dsi_encoder_get_connector(struct mdfld_dsi_encoder *encoder) -{ -	struct mdfld_dsi_config *config; - -	if (!encoder) -		return NULL; - -	config = mdfld_dsi_encoder_get_config(encoder); -	if (!config) -		return NULL; - -	return config->connector; -} - -static inline void *mdfld_dsi_encoder_get_pkg_sender( -	struct mdfld_dsi_encoder *encoder) -{ -	struct mdfld_dsi_config *dsi_config; - -	dsi_config = mdfld_dsi_encoder_get_config(encoder); -	if (!dsi_config) -		return NULL; - -	return mdfld_dsi_get_pkg_sender(dsi_config); -} - -static inline int mdfld_dsi_encoder_get_pipe(struct mdfld_dsi_encoder *encoder) -{ -	struct mdfld_dsi_connector *connector; - -	if (!encoder) -		return -1; - -	connector = mdfld_dsi_encoder_get_connector(encoder); -	if (!connector) -		return -1; - -	return connector->pipe; -} - -extern void mdfld_dsi_gen_fifo_ready(struct drm_device *dev, -				u32 gen_fifo_stat_reg, u32 fifo_stat); -extern void mdfld_dsi_brightness_init(struct mdfld_dsi_config *dsi_config, -				int pipe); -extern void mdfld_dsi_brightness_control(struct drm_device *dev, int pipe, -				int level); -extern void mdfld_dsi_output_init(struct drm_device *dev, int pipe, -				struct mdfld_dsi_config *config, -				struct panel_funcs *p_cmd_funcs, -				struct panel_funcs *p_vid_funcs); -extern void mdfld_dsi_controller_init(struct mdfld_dsi_config *dsi_config, -				int pipe); -extern int mdfld_dsi_get_power_mode(struct mdfld_dsi_config *dsi_config, -				u32 *mode, -				u8 transmission); -extern int mdfld_dsi_get_diagnostic_result(struct mdfld_dsi_config *dsi_config, -				u32 *result, -				u8 transmission); -extern int mdfld_dsi_panel_reset(int pipe); - -#endif /*__MDFLD_DSI_OUTPUT_H__*/ diff --git a/drivers/staging/gma500/mdfld_dsi_pkg_sender.c b/drivers/staging/gma500/mdfld_dsi_pkg_sender.c deleted file mode 100644 index 9b96a5c9abc..00000000000 --- a/drivers/staging/gma500/mdfld_dsi_pkg_sender.c +++ /dev/null @@ -1,1484 +0,0 @@ -/* - * Copyright © 2010 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Authors: - * Jackie Li<yaodong.li@intel.com> - */ - -#include <linux/freezer.h> - -#include "mdfld_dsi_output.h" -#include "mdfld_dsi_pkg_sender.h" -#include "mdfld_dsi_dbi.h" -#include "mdfld_dsi_dpi.h" - -#define MDFLD_DSI_DBI_FIFO_TIMEOUT		100 -#define MDFLD_DSI_MAX_RETURN_PACKET_SIZE	512 -#define MDFLD_DSI_READ_MAX_COUNT		5000 - -static const char * const dsi_errors[] = { -	"RX SOT Error", -	"RX SOT Sync Error", -	"RX EOT Sync Error", -	"RX Escape Mode Entry Error", -	"RX LP TX Sync Error", -	"RX HS Receive Timeout Error", -	"RX False Control Error", -	"RX ECC Single Bit Error", -	"RX ECC Multibit Error", -	"RX Checksum Error", -	"RX DSI Data Type Not Recognised", -	"RX DSI VC ID Invalid", -	"TX False Control Error", -	"TX ECC Single Bit Error", -	"TX ECC Multibit Error", -	"TX Checksum Error", -	"TX DSI Data Type Not Recognised", -	"TX DSI VC ID invalid", -	"High Contention", -	"Low contention", -	"DPI FIFO Under run", -	"HS TX Timeout", -	"LP RX Timeout", -	"Turn Around ACK Timeout", -	"ACK With No Error", -	"RX Invalid TX Length", -	"RX Prot Violation", -	"HS Generic Write FIFO Full", -	"LP Generic Write FIFO Full", -	"Generic Read Data Avail", -	"Special Packet Sent", -	"Tearing Effect", -}; - -static int wait_for_gen_fifo_empty(struct mdfld_dsi_pkg_sender *sender, -								u32 mask) -{ -	struct drm_device *dev = sender->dev; -	u32 gen_fifo_stat_reg = sender->mipi_gen_fifo_stat_reg; -	int retry = 0xffff; - -	while (retry--) { -		if ((mask & REG_READ(gen_fifo_stat_reg)) == mask) -			return 0; -		udelay(100); -	} -	dev_err(dev->dev, "fifo is NOT empty 0x%08x\n", -					REG_READ(gen_fifo_stat_reg)); -	return -EIO; -} - -static int wait_for_all_fifos_empty(struct mdfld_dsi_pkg_sender *sender) -{ -	return wait_for_gen_fifo_empty(sender, (1 << 2) | (1 << 10) | (1 << 18) -		| (1 << 26) | (1 << 27) | (1 << 28)); -} - -static int wait_for_lp_fifos_empty(struct mdfld_dsi_pkg_sender *sender) -{ -	return wait_for_gen_fifo_empty(sender, (1 << 10) | (1 << 26)); -} - -static int wait_for_hs_fifos_empty(struct mdfld_dsi_pkg_sender *sender) -{ -	return wait_for_gen_fifo_empty(sender, (1 << 2) | (1 << 18)); -} - -static int wait_for_dbi_fifo_empty(struct mdfld_dsi_pkg_sender *sender) -{ -	return wait_for_gen_fifo_empty(sender, (1 << 27)); -} - -static int handle_dsi_error(struct mdfld_dsi_pkg_sender *sender, u32 mask) -{ -	u32 intr_stat_reg = sender->mipi_intr_stat_reg; -	struct drm_device *dev = sender->dev; - -	switch (mask) { -	case (1 << 0): -	case (1 << 1): -	case (1 << 2): -	case (1 << 3): -	case (1 << 4): -	case (1 << 5): -	case (1 << 6): -	case (1 << 7): -	case (1 << 8): -	case (1 << 9): -	case (1 << 10): -	case (1 << 11): -	case (1 << 12): -	case (1 << 13): -		break; -	case (1 << 14): -		/*wait for all fifo empty*/ -		/*wait_for_all_fifos_empty(sender)*/; -		break; -	case (1 << 15): -		break; -	case (1 << 16): -		break; -	case (1 << 17): -		break; -	case (1 << 18): -	case (1 << 19): -		/*wait for contention recovery time*/ -		/*mdelay(10);*/ -		/*wait for all fifo empty*/ -		if (0) -			wait_for_all_fifos_empty(sender); -		break; -	case (1 << 20): -		break; -	case (1 << 21): -		/*wait for all fifo empty*/ -		/*wait_for_all_fifos_empty(sender);*/ -		break; -	case (1 << 22): -		break; -	case (1 << 23): -	case (1 << 24): -	case (1 << 25): -	case (1 << 26): -	case (1 << 27): -		/* HS Gen fifo full */ -		REG_WRITE(intr_stat_reg, mask); -		wait_for_hs_fifos_empty(sender); -		break; -	case (1 << 28): -		/* LP Gen fifo full\n */ -		REG_WRITE(intr_stat_reg, mask); -		wait_for_lp_fifos_empty(sender); -		break; -	case (1 << 29): -	case (1 << 30): -	case (1 << 31): -		break; -	} - -	if (mask & REG_READ(intr_stat_reg)) -		dev_warn(dev->dev, "Cannot clean interrupt 0x%08x\n", mask); - -	return 0; -} - -static int dsi_error_handler(struct mdfld_dsi_pkg_sender *sender) -{ -	struct drm_device *dev = sender->dev; -	u32 intr_stat_reg = sender->mipi_intr_stat_reg; -	u32 mask; -	u32 intr_stat; -	int i; -	int err = 0; - -	intr_stat = REG_READ(intr_stat_reg); - -	for (i = 0; i < 32; i++) { -		mask = (0x00000001UL) << i; -		if (intr_stat & mask) { -			dev_dbg(dev->dev, "[DSI]: %s\n", dsi_errors[i]); -			err = handle_dsi_error(sender, mask); -			if (err) -				dev_err(dev->dev, "Cannot handle error\n"); -		} -	} -	return err; -} - -static inline int dbi_cmd_sent(struct mdfld_dsi_pkg_sender *sender) -{ -	struct drm_device *dev = sender->dev; -	u32 retry = 0xffff; -	u32 dbi_cmd_addr_reg = sender->mipi_cmd_addr_reg; - -	/* Query the command execution status */ -	while (retry--) { -		if (!(REG_READ(dbi_cmd_addr_reg) & (1 << 0))) -			break; -	} - -	if (!retry) { -		dev_err(dev->dev, "Timeout waiting for DBI Command status\n"); -		return -EAGAIN; -	} -	return 0; -} - -/* - * NOTE: this interface is abandoned expect for write_mem_start DCS - * other DCS are sent via generic pkg interfaces - */ -static int send_dcs_pkg(struct mdfld_dsi_pkg_sender *sender, -			struct mdfld_dsi_pkg *pkg) -{ -	struct drm_device *dev = sender->dev; -	struct mdfld_dsi_dcs_pkg *dcs_pkg = &pkg->pkg.dcs_pkg; -	u32 dbi_cmd_len_reg = sender->mipi_cmd_len_reg; -	u32 dbi_cmd_addr_reg = sender->mipi_cmd_addr_reg; -	u32 cb_phy = sender->dbi_cb_phy; -	u32 index = 0; -	u8 *cb = (u8 *)sender->dbi_cb_addr; -	int i; -	int ret; - -	if (!sender->dbi_pkg_support) { -		dev_err(dev->dev, "Trying to send DCS on a non DBI output, abort!\n"); -		return -ENOTSUPP; -	} - -	/*wait for DBI fifo empty*/ -	wait_for_dbi_fifo_empty(sender); - -	*(cb + (index++)) = dcs_pkg->cmd; -	if (dcs_pkg->param_num) { -		for (i = 0; i < dcs_pkg->param_num; i++) -			*(cb + (index++)) = *(dcs_pkg->param + i); -	} - -	REG_WRITE(dbi_cmd_len_reg, (1 + dcs_pkg->param_num)); -	REG_WRITE(dbi_cmd_addr_reg, -		(cb_phy << CMD_MEM_ADDR_OFFSET) -		| (1 << 0) -		| ((dcs_pkg->data_src == CMD_DATA_SRC_PIPE) ? (1 << 1) : 0)); - -	ret = dbi_cmd_sent(sender); -	if (ret) { -		dev_err(dev->dev, "command 0x%x not complete\n", dcs_pkg->cmd); -		return -EAGAIN; -	} -	return 0; -} - -static int __send_short_pkg(struct mdfld_dsi_pkg_sender *sender, -				struct mdfld_dsi_pkg *pkg) -{ -	struct drm_device *dev = sender->dev; -	u32 hs_gen_ctrl_reg = sender->mipi_hs_gen_ctrl_reg; -	u32 lp_gen_ctrl_reg = sender->mipi_lp_gen_ctrl_reg; -	u32 gen_ctrl_val = 0; -	struct mdfld_dsi_gen_short_pkg *short_pkg = &pkg->pkg.short_pkg; - -	gen_ctrl_val |= short_pkg->cmd << MCS_COMMANDS_POS; -	gen_ctrl_val |= 0 << DCS_CHANNEL_NUMBER_POS; -	gen_ctrl_val |= pkg->pkg_type; -	gen_ctrl_val |= short_pkg->param << MCS_PARAMETER_POS; - -	if (pkg->transmission_type == MDFLD_DSI_HS_TRANSMISSION) { -		/* wait for hs fifo empty */ -		/* wait_for_hs_fifos_empty(sender); */ -		/* Send pkg */ -		REG_WRITE(hs_gen_ctrl_reg, gen_ctrl_val); -	} else if (pkg->transmission_type == MDFLD_DSI_LP_TRANSMISSION) { -		/* wait_for_lp_fifos_empty(sender); */ -		/* Send pkg*/ -		REG_WRITE(lp_gen_ctrl_reg, gen_ctrl_val); -	} else { -		dev_err(dev->dev, "Unknown transmission type %d\n", -							pkg->transmission_type); -		return -EINVAL; -	} - -	return 0; -} - -static int __send_long_pkg(struct mdfld_dsi_pkg_sender *sender, -				struct mdfld_dsi_pkg *pkg) -{ -	struct drm_device *dev = sender->dev; -	u32 hs_gen_ctrl_reg = sender->mipi_hs_gen_ctrl_reg; -	u32 hs_gen_data_reg = sender->mipi_hs_gen_data_reg; -	u32 lp_gen_ctrl_reg = sender->mipi_lp_gen_ctrl_reg; -	u32 lp_gen_data_reg = sender->mipi_lp_gen_data_reg; -	u32 gen_ctrl_val = 0; -	u32 *dp; -	int i; -	struct mdfld_dsi_gen_long_pkg *long_pkg = &pkg->pkg.long_pkg; - -	dp = long_pkg->data; - -	/* -	 * Set up word count for long pkg -	 * FIXME: double check word count field. -	 * currently, using the byte counts of the payload as the word count. -	 * ------------------------------------------------------------ -	 * | DI |   WC   | ECC|         PAYLOAD              |CHECKSUM| -	 * ------------------------------------------------------------ -	 */ -	gen_ctrl_val |= (long_pkg->len << 2) << WORD_COUNTS_POS; -	gen_ctrl_val |= 0 << DCS_CHANNEL_NUMBER_POS; -	gen_ctrl_val |= pkg->pkg_type; - -	if (pkg->transmission_type == MDFLD_DSI_HS_TRANSMISSION) { -		/* Wait for hs ctrl and data fifos to be empty */ -		/* wait_for_hs_fifos_empty(sender); */ -		for (i = 0; i < long_pkg->len; i++) -			REG_WRITE(hs_gen_data_reg, *(dp + i)); -		REG_WRITE(hs_gen_ctrl_reg, gen_ctrl_val); -	} else if (pkg->transmission_type == MDFLD_DSI_LP_TRANSMISSION) { -		/* wait_for_lp_fifos_empty(sender); */ -		for (i = 0; i < long_pkg->len; i++) -			REG_WRITE(lp_gen_data_reg, *(dp + i)); -		REG_WRITE(lp_gen_ctrl_reg, gen_ctrl_val); -	} else { -		dev_err(dev->dev, "Unknown transmission type %d\n", -						pkg->transmission_type); -		return -EINVAL; -	} - -	return 0; - -} - -static int send_mcs_short_pkg(struct mdfld_dsi_pkg_sender *sender, -				struct mdfld_dsi_pkg *pkg) -{ -	return __send_short_pkg(sender, pkg); -} - -static int send_mcs_long_pkg(struct mdfld_dsi_pkg_sender *sender, -				struct mdfld_dsi_pkg *pkg) -{ -	return __send_long_pkg(sender, pkg); -} - -static int send_gen_short_pkg(struct mdfld_dsi_pkg_sender *sender, -				struct mdfld_dsi_pkg *pkg) -{ -	return __send_short_pkg(sender, pkg); -} - -static int send_gen_long_pkg(struct mdfld_dsi_pkg_sender *sender, -				struct mdfld_dsi_pkg *pkg) -{ -	return __send_long_pkg(sender, pkg); -} - -static int send_pkg_prepare(struct mdfld_dsi_pkg_sender *sender, -				struct mdfld_dsi_pkg *pkg) -{ -	u8 cmd; -	u8 *data; - -	switch (pkg->pkg_type) { -	case MDFLD_DSI_PKG_DCS: -		cmd = pkg->pkg.dcs_pkg.cmd; -		break; -	case MDFLD_DSI_PKG_MCS_SHORT_WRITE_0: -	case MDFLD_DSI_PKG_MCS_SHORT_WRITE_1: -		cmd = pkg->pkg.short_pkg.cmd; -		break; -	case MDFLD_DSI_PKG_MCS_LONG_WRITE: -		data = (u8 *)pkg->pkg.long_pkg.data; -		cmd = *data; -		break; -	default: -		return 0; -	} - -	/* This prevents other package sending while doing msleep */ -	sender->status = MDFLD_DSI_PKG_SENDER_BUSY; - -	/* Check panel mode v.s. sending command */ -	if ((sender->panel_mode & MDFLD_DSI_PANEL_MODE_SLEEP) && -		cmd != exit_sleep_mode) { -		dev_err(sender->dev->dev, -				"sending 0x%x when panel sleep in\n", cmd); -		sender->status = MDFLD_DSI_PKG_SENDER_FREE; -		return -EINVAL; -	} - -	/* Wait for 120 milliseconds in case exit_sleep_mode just be sent */ -	if (cmd == DCS_ENTER_SLEEP_MODE) { - 		/*TODO: replace it with msleep later*/ -		mdelay(120); -	} -	return 0; -} - -static int send_pkg_done(struct mdfld_dsi_pkg_sender *sender, -				struct mdfld_dsi_pkg *pkg) -{ -	u8 cmd; -	u8 *data; - -	switch (pkg->pkg_type) { -	case MDFLD_DSI_PKG_DCS: -		cmd = pkg->pkg.dcs_pkg.cmd; -		break; -	case MDFLD_DSI_PKG_MCS_SHORT_WRITE_0: -	case MDFLD_DSI_PKG_MCS_SHORT_WRITE_1: -		cmd = pkg->pkg.short_pkg.cmd; -		break; -	case MDFLD_DSI_PKG_MCS_LONG_WRITE: -		data = (u8 *)pkg->pkg.long_pkg.data; -		cmd = *data; -		break; -	default: -		return 0; -	} - -	/* Update panel status */ -	if (cmd == DCS_ENTER_SLEEP_MODE) { -		sender->panel_mode |= MDFLD_DSI_PANEL_MODE_SLEEP; -		/*TODO: replace it with msleep later*/ -		mdelay(120); -	} else if (cmd == DCS_EXIT_SLEEP_MODE) { -		sender->panel_mode &= ~MDFLD_DSI_PANEL_MODE_SLEEP; -		/*TODO: replace it with msleep later*/ -		mdelay(120); -	} else if (unlikely(cmd == DCS_SOFT_RESET)) { -		/*TODO: replace it with msleep later*/ -		mdelay(5); - 	} -	sender->status = MDFLD_DSI_PKG_SENDER_FREE; -	return 0; - -} - -static int do_send_pkg(struct mdfld_dsi_pkg_sender *sender, -			struct mdfld_dsi_pkg *pkg) -{ -	int ret; - -	if (sender->status == MDFLD_DSI_PKG_SENDER_BUSY) { -		dev_err(sender->dev->dev, "sender is busy\n"); -		return -EAGAIN; -	} - -	ret = send_pkg_prepare(sender, pkg); -	if (ret) { -		dev_err(sender->dev->dev, "send_pkg_prepare error\n"); -		return ret; -	} - -	switch (pkg->pkg_type) { -	case MDFLD_DSI_PKG_DCS: -		ret = send_dcs_pkg(sender, pkg); -		break; -	case MDFLD_DSI_PKG_GEN_SHORT_WRITE_0: -	case MDFLD_DSI_PKG_GEN_SHORT_WRITE_1: -	case MDFLD_DSI_PKG_GEN_SHORT_WRITE_2: -	case MDFLD_DSI_PKG_GEN_READ_0: -	case MDFLD_DSI_PKG_GEN_READ_1: -	case MDFLD_DSI_PKG_GEN_READ_2: -		ret = send_gen_short_pkg(sender, pkg); -		break; -	case MDFLD_DSI_PKG_GEN_LONG_WRITE: -		ret = send_gen_long_pkg(sender, pkg); -		break; -	case MDFLD_DSI_PKG_MCS_SHORT_WRITE_0: -	case MDFLD_DSI_PKG_MCS_SHORT_WRITE_1: -	case MDFLD_DSI_PKG_MCS_READ: -		ret = send_mcs_short_pkg(sender, pkg); -		break; -	case MDFLD_DSI_PKG_MCS_LONG_WRITE: -		ret = send_mcs_long_pkg(sender, pkg); -		break; -	default: -		dev_err(sender->dev->dev, "Invalid pkg type 0x%x\n", -							pkg->pkg_type); -		ret = -EINVAL; -	} -	send_pkg_done(sender, pkg); -	return ret; -} - -static int send_pkg(struct mdfld_dsi_pkg_sender *sender, -			struct mdfld_dsi_pkg *pkg) -{ -	int err ; - -	/* Handle DSI error */ -	err = dsi_error_handler(sender); -	if (err) { -		dev_err(sender->dev->dev, "Error handling failed\n"); -		err = -EAGAIN; -		goto send_pkg_err; -	} - -	/* Send pkg */ -	err = do_send_pkg(sender, pkg); -	if (err) { -		dev_err(sender->dev->dev, "sent pkg failed\n"); -		err = -EAGAIN; -		goto send_pkg_err; -	} - -	/* FIXME: should I query complete and fifo empty here? */ -send_pkg_err: -	return err; -} - -static struct mdfld_dsi_pkg *pkg_sender_get_pkg_locked( -					struct mdfld_dsi_pkg_sender *sender) -{ -	struct mdfld_dsi_pkg *pkg; - -	if (list_empty(&sender->free_list)) { -		dev_err(sender->dev->dev, "No free pkg left\n"); -		return NULL; -	} -	pkg = list_first_entry(&sender->free_list, struct mdfld_dsi_pkg, entry); -	/* Detach from free list */ -	list_del_init(&pkg->entry); -	return pkg; -} - -static void pkg_sender_put_pkg_locked(struct mdfld_dsi_pkg_sender *sender, -					struct mdfld_dsi_pkg *pkg) -{ -	memset(pkg, 0, sizeof(struct mdfld_dsi_pkg)); -	INIT_LIST_HEAD(&pkg->entry); -	list_add_tail(&pkg->entry, &sender->free_list); -} - -static int mdfld_dbi_cb_init(struct mdfld_dsi_pkg_sender *sender, -					struct psb_gtt *pg, int pipe) -{ -	unsigned long phys; -	void *virt_addr = NULL; - -	switch (pipe) { -	case 0: -		/* FIXME: Doesn't this collide with stolen space ? */ -		phys = pg->gtt_phys_start - 0x1000; -		break; -	case 2: -		phys = pg->gtt_phys_start - 0x800; -		break; -	default: -		dev_err(sender->dev->dev, "Unsupported channel %d\n", pipe); -		return -EINVAL; -	} - -	virt_addr = ioremap_nocache(phys, 0x800); -	if (!virt_addr) { -		dev_err(sender->dev->dev, "Map DBI command buffer error\n"); -		return -ENOMEM; -	} -	sender->dbi_cb_phy = phys; -	sender->dbi_cb_addr = virt_addr; -	return 0; -} - -static void mdfld_dbi_cb_destroy(struct mdfld_dsi_pkg_sender *sender) -{ -	if (sender && sender->dbi_cb_addr) -		iounmap(sender->dbi_cb_addr); -} - -static void pkg_sender_queue_pkg(struct mdfld_dsi_pkg_sender *sender, -					struct mdfld_dsi_pkg *pkg, -					int delay) -{ -	unsigned long flags; - -	spin_lock_irqsave(&sender->lock, flags); - -	if (!delay) { -		send_pkg(sender, pkg); -		pkg_sender_put_pkg_locked(sender, pkg); -	} else { -		/* Queue it */ -		list_add_tail(&pkg->entry, &sender->pkg_list); -	} -	spin_unlock_irqrestore(&sender->lock, flags); -} - -static void process_pkg_list(struct mdfld_dsi_pkg_sender *sender) -{ -	struct mdfld_dsi_pkg *pkg; -	unsigned long flags; - -	spin_lock_irqsave(&sender->lock, flags); - -	while (!list_empty(&sender->pkg_list)) { -		pkg = list_first_entry(&sender->pkg_list, -					struct mdfld_dsi_pkg, entry); -		send_pkg(sender, pkg); -		list_del_init(&pkg->entry); -		pkg_sender_put_pkg_locked(sender, pkg); -	} - -	spin_unlock_irqrestore(&sender->lock, flags); -} - -static int mdfld_dsi_send_mcs_long(struct mdfld_dsi_pkg_sender *sender, -	u32 *data, u32 len, u8 transmission, int delay) -{ -	struct mdfld_dsi_pkg *pkg; -	unsigned long flags; - -	spin_lock_irqsave(&sender->lock, flags); -	pkg = pkg_sender_get_pkg_locked(sender); -	spin_unlock_irqrestore(&sender->lock, flags); - -	if (!pkg) { -		dev_err(sender->dev->dev, "No memory\n"); -		return -ENOMEM; -	} -	pkg->pkg_type = MDFLD_DSI_PKG_MCS_LONG_WRITE; -	pkg->transmission_type = transmission; -	pkg->pkg.long_pkg.data = data; -	pkg->pkg.long_pkg.len = len; -	INIT_LIST_HEAD(&pkg->entry); - -	pkg_sender_queue_pkg(sender, pkg, delay); -	return 0; -} - -static int mdfld_dsi_send_mcs_short(struct mdfld_dsi_pkg_sender *sender, -					u8 cmd, u8 param, u8 param_num, -					u8 transmission, -					int delay) -{ -	struct mdfld_dsi_pkg *pkg; -	unsigned long flags; - -	spin_lock_irqsave(&sender->lock, flags); -	pkg = pkg_sender_get_pkg_locked(sender); -	spin_unlock_irqrestore(&sender->lock, flags); - -	if (!pkg) { -		dev_err(sender->dev->dev, "No memory\n"); -		return -ENOMEM; -	} - -	if (param_num) { -		pkg->pkg_type = MDFLD_DSI_PKG_MCS_SHORT_WRITE_1; -		pkg->pkg.short_pkg.param = param; -	} else { -		pkg->pkg_type = MDFLD_DSI_PKG_MCS_SHORT_WRITE_0; -		pkg->pkg.short_pkg.param = 0; -	} -	pkg->transmission_type = transmission; -	pkg->pkg.short_pkg.cmd = cmd; -	INIT_LIST_HEAD(&pkg->entry); - -	pkg_sender_queue_pkg(sender, pkg, delay); -	return 0; -} - -static int mdfld_dsi_send_gen_short(struct mdfld_dsi_pkg_sender *sender, -					u8 param0, u8 param1, u8 param_num, -					u8 transmission, -					int delay) -{ -	struct mdfld_dsi_pkg *pkg; -	unsigned long flags; - -	spin_lock_irqsave(&sender->lock, flags); -	pkg = pkg_sender_get_pkg_locked(sender); -	spin_unlock_irqrestore(&sender->lock, flags); - -	if (!pkg) { -		dev_err(sender->dev->dev, "No pkg memory\n"); -		return -ENOMEM; -	} - -	switch (param_num) { -	case 0: -		pkg->pkg_type = MDFLD_DSI_PKG_GEN_SHORT_WRITE_0; -		pkg->pkg.short_pkg.cmd = 0; -		pkg->pkg.short_pkg.param = 0; -		break; -	case 1: -		pkg->pkg_type = MDFLD_DSI_PKG_GEN_SHORT_WRITE_1; -		pkg->pkg.short_pkg.cmd = param0; -		pkg->pkg.short_pkg.param = 0; -		break; -	case 2: -		pkg->pkg_type = MDFLD_DSI_PKG_GEN_SHORT_WRITE_2; -		pkg->pkg.short_pkg.cmd = param0; -		pkg->pkg.short_pkg.param = param1; -		break; -	} - -	pkg->transmission_type = transmission; -	INIT_LIST_HEAD(&pkg->entry); - -	pkg_sender_queue_pkg(sender, pkg, delay); -	return 0; -} - -static int mdfld_dsi_send_gen_long(struct mdfld_dsi_pkg_sender *sender, -				u32 *data, u32 len, u8 transmission, int delay) -{ -	struct mdfld_dsi_pkg *pkg; -	unsigned long flags; - -	spin_lock_irqsave(&sender->lock, flags); -	pkg = pkg_sender_get_pkg_locked(sender); -	spin_unlock_irqrestore(&sender->lock, flags); - -	if (!pkg) { -		dev_err(sender->dev->dev, "No pkg memory\n"); -		return -ENOMEM; -	} - -	pkg->pkg_type = MDFLD_DSI_PKG_GEN_LONG_WRITE; -	pkg->transmission_type = transmission; -	pkg->pkg.long_pkg.data = data; -	pkg->pkg.long_pkg.len = len; - -	INIT_LIST_HEAD(&pkg->entry); - -	pkg_sender_queue_pkg(sender, pkg, delay); - -	return 0; -} - -static int __read_panel_data(struct mdfld_dsi_pkg_sender *sender, -				struct mdfld_dsi_pkg *pkg, -				u32 *data, -				u16 len) -{ -	unsigned long flags; -	struct drm_device *dev = sender->dev; -	int i; -	u32 gen_data_reg; -	int retry = MDFLD_DSI_READ_MAX_COUNT; -	u8 transmission = pkg->transmission_type; - -	/* -	 * do reading. -	 * 0) send out generic read request -	 * 1) polling read data avail interrupt -	 * 2) read data -	 */ -	spin_lock_irqsave(&sender->lock, flags); - -	REG_WRITE(sender->mipi_intr_stat_reg, 1 << 29); - -	if ((REG_READ(sender->mipi_intr_stat_reg) & (1 << 29))) -		DRM_ERROR("Can NOT clean read data valid interrupt\n"); - -	/*send out read request*/ -	send_pkg(sender, pkg); - -	pkg_sender_put_pkg_locked(sender, pkg); - -	/*polling read data avail interrupt*/ -	while (retry && !(REG_READ(sender->mipi_intr_stat_reg) & (1 << 29))) { -		udelay(100); -		retry--; -	} - -	if (!retry) { -		spin_unlock_irqrestore(&sender->lock, flags); -		return -ETIMEDOUT; -	} - -	REG_WRITE(sender->mipi_intr_stat_reg, (1 << 29)); - -	/*read data*/ -	if (transmission == MDFLD_DSI_HS_TRANSMISSION) -		gen_data_reg = sender->mipi_hs_gen_data_reg; -	else if (transmission == MDFLD_DSI_LP_TRANSMISSION) -		gen_data_reg = sender->mipi_lp_gen_data_reg; -	else { -		DRM_ERROR("Unknown transmission"); -		spin_unlock_irqrestore(&sender->lock, flags); -		return -EINVAL; -	} - -	for (i=0; i<len; i++) -		*(data + i) = REG_READ(gen_data_reg); - - 	spin_unlock_irqrestore(&sender->lock, flags); -  -	return 0; -} - -static int mdfld_dsi_read_gen(struct mdfld_dsi_pkg_sender *sender, -				u8 param0, -				u8 param1, -				u8 param_num, -				u32 *data, -				u16 len, -				u8 transmission) -{ -	struct mdfld_dsi_pkg *pkg; -	unsigned long flags; - -	spin_lock_irqsave(&sender->lock, flags); - -	pkg = pkg_sender_get_pkg_locked(sender); - -	spin_unlock_irqrestore(&sender->lock,flags); - -	if (!pkg) { -		dev_err(sender->dev->dev, "No pkg memory\n"); -		return -ENOMEM; -	} - -	switch (param_num) { -	case 0: -		pkg->pkg_type = MDFLD_DSI_PKG_GEN_READ_0; -		pkg->pkg.short_pkg.cmd = 0; -		pkg->pkg.short_pkg.param = 0; -		break; -	case 1: -		pkg->pkg_type = MDFLD_DSI_PKG_GEN_READ_1; -		pkg->pkg.short_pkg.cmd = param0; -		pkg->pkg.short_pkg.param = 0; -		break; - 	case 2: -		pkg->pkg_type = MDFLD_DSI_PKG_GEN_READ_2; -		pkg->pkg.short_pkg.cmd = param0; -		pkg->pkg.short_pkg.param = param1; -		break; -	} - -	pkg->transmission_type = transmission; - -	INIT_LIST_HEAD(&pkg->entry); - -	return __read_panel_data(sender, pkg, data, len); -} -  -static int mdfld_dsi_read_mcs(struct mdfld_dsi_pkg_sender *sender, -				u8 cmd, -				u32 *data, -				u16 len, -				u8 transmission) -{ -	struct mdfld_dsi_pkg *pkg; -	unsigned long flags; - -	spin_lock_irqsave(&sender->lock, flags); - -	pkg = pkg_sender_get_pkg_locked(sender); - - 	spin_unlock_irqrestore(&sender->lock, flags); -  - 	if (!pkg) { -		dev_err(sender->dev->dev, "No pkg memory\n"); - 		return -ENOMEM; -	} - -	pkg->pkg_type = MDFLD_DSI_PKG_MCS_READ; -	pkg->pkg.short_pkg.cmd = cmd; -	pkg->pkg.short_pkg.param = 0; - -	pkg->transmission_type = transmission; -  -	INIT_LIST_HEAD(&pkg->entry); - -	return __read_panel_data(sender, pkg, data, len); -} - -void dsi_controller_dbi_init(struct mdfld_dsi_config * dsi_config, int pipe) -{ -	struct drm_device * dev = dsi_config->dev; -	u32 reg_offset = pipe ? MIPIC_REG_OFFSET : 0; -	int lane_count = dsi_config->lane_count; -	u32 val = 0; - -	/*un-ready device*/ -	REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000000); - -	/*init dsi adapter before kicking off*/ -	REG_WRITE((MIPIA_CONTROL_REG + reg_offset), 0x00000018); - -	/*TODO: figure out how to setup these registers*/ -	REG_WRITE((MIPIA_DPHY_PARAM_REG + reg_offset), 0x150c3408); -	REG_WRITE((MIPIA_CLK_LANE_SWITCH_TIME_CNT_REG + reg_offset), 0x000a0014); -	REG_WRITE((MIPIA_DBI_BW_CTRL_REG + reg_offset), 0x00000400); -	REG_WRITE((MIPIA_DBI_FIFO_THROTTLE_REG + reg_offset), 0x00000001); -	REG_WRITE((MIPIA_HS_LS_DBI_ENABLE_REG + reg_offset), 0x00000000); - -	/*enable all interrupts*/ -	REG_WRITE((MIPIA_INTR_EN_REG + reg_offset), 0xffffffff); -	/*max value: 20 clock cycles of txclkesc*/ -	REG_WRITE((MIPIA_TURN_AROUND_TIMEOUT_REG + reg_offset), 0x0000001f); -	/*min 21 txclkesc, max: ffffh*/ -	REG_WRITE((MIPIA_DEVICE_RESET_TIMER_REG + reg_offset), 0x0000ffff); -	/*min: 7d0 max: 4e20*/ -	REG_WRITE((MIPIA_INIT_COUNT_REG + reg_offset), 0x00000fa0); - -	/*set up max return packet size*/ -	REG_WRITE((MIPIA_MAX_RETURN_PACK_SIZE_REG + reg_offset), -			MDFLD_DSI_MAX_RETURN_PACKET_SIZE); - -	/*set up func_prg*/ -	val |= lane_count; -	val |= (dsi_config->channel_num << DSI_DBI_VIRT_CHANNEL_OFFSET); -	val |= DSI_DBI_COLOR_FORMAT_OPTION2; -	REG_WRITE((MIPIA_DSI_FUNC_PRG_REG + reg_offset), val); - -	REG_WRITE((MIPIA_HS_TX_TIMEOUT_REG + reg_offset), 0x3fffff); -	REG_WRITE((MIPIA_LP_RX_TIMEOUT_REG + reg_offset), 0xffff); - -	REG_WRITE((MIPIA_HIGH_LOW_SWITCH_COUNT_REG + reg_offset), 0x46); -	REG_WRITE((MIPIA_EOT_DISABLE_REG + reg_offset), 0x00000000); -	REG_WRITE((MIPIA_LP_BYTECLK_REG + reg_offset), 0x00000004); -	REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000001); -} - -void dsi_controller_dpi_init(struct mdfld_dsi_config * dsi_config, int pipe) -{ -	struct drm_device * dev = dsi_config->dev; -	u32 reg_offset = pipe ? MIPIC_REG_OFFSET : 0; -	int lane_count = dsi_config->lane_count; -	struct mdfld_dsi_dpi_timing dpi_timing; -	struct drm_display_mode * mode = dsi_config->mode; -	u32 val = 0; - -	/*un-ready device*/ -	REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000000); - -	/*init dsi adapter before kicking off*/ -	REG_WRITE((MIPIA_CONTROL_REG + reg_offset), 0x00000018); - -	/*enable all interrupts*/ -	REG_WRITE((MIPIA_INTR_EN_REG + reg_offset), 0xffffffff); - -	/*set up func_prg*/ -	val |= lane_count; -	val |= dsi_config->channel_num << DSI_DPI_VIRT_CHANNEL_OFFSET; - -	switch(dsi_config->bpp) { -	case 16: -		val |= DSI_DPI_COLOR_FORMAT_RGB565; -		break; -	case 18: -		val |= DSI_DPI_COLOR_FORMAT_RGB666; -		break; -	case 24: -		val |= DSI_DPI_COLOR_FORMAT_RGB888; -		break; -	default: -		DRM_ERROR("unsupported color format, bpp = %d\n", dsi_config->bpp); -	} - -	REG_WRITE((MIPIA_DSI_FUNC_PRG_REG + reg_offset), val); - -	REG_WRITE((MIPIA_HS_TX_TIMEOUT_REG + reg_offset), -			(mode->vtotal * mode->htotal * dsi_config->bpp / (8 * lane_count)) & DSI_HS_TX_TIMEOUT_MASK); -	REG_WRITE((MIPIA_LP_RX_TIMEOUT_REG + reg_offset), 0xffff & DSI_LP_RX_TIMEOUT_MASK); - -	/*max value: 20 clock cycles of txclkesc*/ -	REG_WRITE((MIPIA_TURN_AROUND_TIMEOUT_REG + reg_offset), 0x14 & DSI_TURN_AROUND_TIMEOUT_MASK); - -	/*min 21 txclkesc, max: ffffh*/ -	REG_WRITE((MIPIA_DEVICE_RESET_TIMER_REG + reg_offset), 0xffff & DSI_RESET_TIMER_MASK); - -	REG_WRITE((MIPIA_DPI_RESOLUTION_REG + reg_offset), mode->vdisplay << 16 | mode->hdisplay); - -	/*set DPI timing registers*/ -	mdfld_dsi_dpi_timing_calculation(mode, &dpi_timing, dsi_config->lane_count, dsi_config->bpp); - -	REG_WRITE((MIPIA_HSYNC_COUNT_REG + reg_offset), dpi_timing.hsync_count & DSI_DPI_TIMING_MASK); -	REG_WRITE((MIPIA_HBP_COUNT_REG + reg_offset), dpi_timing.hbp_count & DSI_DPI_TIMING_MASK); -	REG_WRITE((MIPIA_HFP_COUNT_REG + reg_offset), dpi_timing.hfp_count & DSI_DPI_TIMING_MASK); -	REG_WRITE((MIPIA_HACTIVE_COUNT_REG + reg_offset), dpi_timing.hactive_count & DSI_DPI_TIMING_MASK); -	REG_WRITE((MIPIA_VSYNC_COUNT_REG + reg_offset), dpi_timing.vsync_count & DSI_DPI_TIMING_MASK); -	REG_WRITE((MIPIA_VBP_COUNT_REG + reg_offset), dpi_timing.vbp_count & DSI_DPI_TIMING_MASK); -	REG_WRITE((MIPIA_VFP_COUNT_REG + reg_offset), dpi_timing.vfp_count & DSI_DPI_TIMING_MASK); - -	REG_WRITE((MIPIA_HIGH_LOW_SWITCH_COUNT_REG + reg_offset), 0x46); - -	/*min: 7d0 max: 4e20*/ -	REG_WRITE((MIPIA_INIT_COUNT_REG + reg_offset), 0x000007d0); - -	/*set up video mode*/ -	val = dsi_config->video_mode | DSI_DPI_COMPLETE_LAST_LINE; -	REG_WRITE((MIPIA_VIDEO_MODE_FORMAT_REG + reg_offset), val); - -	REG_WRITE((MIPIA_EOT_DISABLE_REG + reg_offset), 0x00000000); - -	REG_WRITE((MIPIA_LP_BYTECLK_REG + reg_offset), 0x00000004); - -	/*TODO: figure out how to setup these registers*/ -	REG_WRITE((MIPIA_DPHY_PARAM_REG + reg_offset), 0x150c3408); - -	REG_WRITE((MIPIA_CLK_LANE_SWITCH_TIME_CNT_REG + reg_offset), (0xa << 16) | 0x14); - -	/*set device ready*/ -	REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000001); -} - -static void dsi_controller_init(struct mdfld_dsi_config * dsi_config, int pipe) -{ -	if (!dsi_config || ((pipe != 0) && (pipe != 2))) { -		DRM_ERROR("Invalid parameters\n"); -		return; -	} - -	if (dsi_config->type == MDFLD_DSI_ENCODER_DPI) -		dsi_controller_dpi_init(dsi_config, pipe); -	else if (dsi_config->type == MDFLD_DSI_ENCODER_DBI) -		dsi_controller_dbi_init(dsi_config, pipe); -	else -		DRM_ERROR("Bad DSI encoder type\n"); -} - -void mdfld_dsi_cmds_kick_out(struct mdfld_dsi_pkg_sender *sender) -{ -	process_pkg_list(sender); -} - -int mdfld_dsi_send_dcs(struct mdfld_dsi_pkg_sender *sender, -			u8 dcs, u8 *param, u32 param_num, u8 data_src, -			int delay) -{ -	struct mdfld_dsi_pkg *pkg; -	u32 cb_phy = sender->dbi_cb_phy; -	struct drm_device *dev = sender->dev; -	u32 index = 0; -	u8 *cb = (u8 *)sender->dbi_cb_addr; -	unsigned long flags; -	int retry; -	u8 *dst = NULL; -	u32 len; - -	if (!sender) { -		WARN_ON(1); -		return -EINVAL; -	} - -	if (!sender->dbi_pkg_support) { -		dev_err(dev->dev, "No DBI pkg sending on this sender\n"); -		return -ENOTSUPP; -	} - -	if (param_num > MDFLD_MAX_DCS_PARAM) { -		dev_err(dev->dev, "Sender only supports up to %d DCS params\n", -							MDFLD_MAX_DCS_PARAM); -		return -EINVAL; -	} - -	/* -	 * If dcs is write_mem_start, send it directly using DSI adapter -	 * interface -	 */ -	if (dcs == DCS_WRITE_MEM_START) { -		if (!spin_trylock(&sender->lock)) -			return -EAGAIN; - -		/* -		 * query whether DBI FIFO is empty, -		 * if not wait it becoming empty -		 */ -		retry = MDFLD_DSI_DBI_FIFO_TIMEOUT; -		while (retry && -		    !(REG_READ(sender->mipi_gen_fifo_stat_reg) & (1 << 27))) { -			udelay(500); -			retry--; -		} - -		/* If DBI FIFO timeout, drop this frame */ -		if (!retry) { -			spin_unlock(&sender->lock); -			return 0; -		} - -		*(cb + (index++)) = write_mem_start; - -		REG_WRITE(sender->mipi_cmd_len_reg, 1); -		REG_WRITE(sender->mipi_cmd_addr_reg, -					cb_phy | (1 << 0) | (1 << 1)); - -		retry = MDFLD_DSI_DBI_FIFO_TIMEOUT; -		while (retry && -			(REG_READ(sender->mipi_cmd_addr_reg) & (1 << 0))) { -			udelay(1); -			retry--; -		} - -		spin_unlock(&sender->lock); -		return 0; -	} - -	/* Get a free pkg */ -	spin_lock_irqsave(&sender->lock, flags); -	pkg = pkg_sender_get_pkg_locked(sender); -	spin_unlock_irqrestore(&sender->lock, flags); - -	if (!pkg) { -		dev_err(dev->dev, "No packages memory\n"); -		return -ENOMEM; -	} - -	dst = pkg->pkg.dcs_pkg.param; -	memcpy(dst, param, param_num); - -	pkg->pkg_type = MDFLD_DSI_PKG_DCS; -	pkg->transmission_type = MDFLD_DSI_DCS; -	pkg->pkg.dcs_pkg.cmd = dcs; -	pkg->pkg.dcs_pkg.param_num = param_num; -	pkg->pkg.dcs_pkg.data_src = data_src; - -	INIT_LIST_HEAD(&pkg->entry); - -	if (param_num == 0) -		return mdfld_dsi_send_mcs_short_hs(sender, dcs, 0, 0, delay); -	else if (param_num == 1) -		return mdfld_dsi_send_mcs_short_hs(sender, dcs, -							param[0], 1, delay); -	else if (param_num > 1) { -		len = (param_num + 1) / 4; -		if ((param_num + 1) % 4) -			len++; -		return mdfld_dsi_send_mcs_long_hs(sender, -				(u32 *)&pkg->pkg.dcs_pkg, len, delay); -	} -	return 0; -} - -int mdfld_dsi_send_mcs_short_hs(struct mdfld_dsi_pkg_sender *sender, -				u8 cmd, u8 param, u8 param_num, int delay) -{ -	if (!sender) { -		WARN_ON(1); -		return -EINVAL; -	} -	return mdfld_dsi_send_mcs_short(sender, cmd, param, param_num, -					MDFLD_DSI_HS_TRANSMISSION, delay); -} - -int mdfld_dsi_send_mcs_short_lp(struct mdfld_dsi_pkg_sender *sender, -				u8 cmd, u8 param, u8 param_num, int delay) -{ -	if (!sender) { -		WARN_ON(1); -		return -EINVAL; -	} -	return mdfld_dsi_send_mcs_short(sender, cmd, param, param_num, -					MDFLD_DSI_LP_TRANSMISSION, delay); -} - -int mdfld_dsi_send_mcs_long_hs(struct mdfld_dsi_pkg_sender *sender, -				u32 *data, -				u32 len, -				int delay) -{ -	if (!sender || !data || !len) { -		DRM_ERROR("Invalid parameters\n"); -		return -EINVAL; -	} -	return mdfld_dsi_send_mcs_long(sender, data, len, -					MDFLD_DSI_HS_TRANSMISSION, delay); -} - -int mdfld_dsi_send_mcs_long_lp(struct mdfld_dsi_pkg_sender *sender, -				u32 *data, -				u32 len, -				int delay) -{ -	if (!sender || !data || !len) { -		WARN_ON(1); -		return -EINVAL; -	} -	return mdfld_dsi_send_mcs_long(sender, data, len, -				MDFLD_DSI_LP_TRANSMISSION, delay); -} - -int mdfld_dsi_send_gen_short_hs(struct mdfld_dsi_pkg_sender *sender, -				u8 param0, u8 param1, u8 param_num, int delay) -{ -	if (!sender) { -		WARN_ON(1); -		return -EINVAL; -	} -	return mdfld_dsi_send_gen_short(sender, param0, param1, param_num, -					MDFLD_DSI_HS_TRANSMISSION, delay); -} - -int mdfld_dsi_send_gen_short_lp(struct mdfld_dsi_pkg_sender *sender, -				u8 param0, u8 param1, u8 param_num, int delay) -{ -	if (!sender || param_num < 0 || param_num > 2) { -		WARN_ON(1); -		return -EINVAL; -	} -	return mdfld_dsi_send_gen_short(sender, param0, param1, param_num, -					MDFLD_DSI_LP_TRANSMISSION, delay); -} - -int mdfld_dsi_send_gen_long_hs(struct mdfld_dsi_pkg_sender *sender, -				u32 *data, -				u32 len, -				int delay) -{ -	if (!sender || !data || !len) { -		WARN_ON(1); -		return -EINVAL; -	} -	return mdfld_dsi_send_gen_long(sender, data, len, -					MDFLD_DSI_HS_TRANSMISSION, delay); -} - -int mdfld_dsi_send_gen_long_lp(struct mdfld_dsi_pkg_sender *sender, -				u32 *data, -				u32 len, -				int delay) -{ -	if (!sender || !data || !len) { -		WARN_ON(1); -		return -EINVAL; -	} -	return mdfld_dsi_send_gen_long(sender, data, len, -					MDFLD_DSI_LP_TRANSMISSION, delay); -} - -int mdfld_dsi_read_gen_hs(struct mdfld_dsi_pkg_sender *sender, -			u8 param0, -			u8 param1, -			u8 param_num, -			u32 *data, -			u16 len) -{ -	if (!sender || !data || param_num < 0 || param_num > 2 -		|| !data || !len) { -		DRM_ERROR("Invalid parameters\n"); -		return -EINVAL; -	} - -	return mdfld_dsi_read_gen(sender, param0, param1, param_num, -				data, len, MDFLD_DSI_HS_TRANSMISSION); - -} - -int mdfld_dsi_read_gen_lp(struct mdfld_dsi_pkg_sender *sender, -			u8 param0, -			u8 param1, -			u8 param_num, -			u32 *data, -			u16 len) -{ -	if (!sender || !data || param_num < 0 || param_num > 2 -		|| !data || !len) { -		DRM_ERROR("Invalid parameters\n"); -		return -EINVAL; -	} - -	return mdfld_dsi_read_gen(sender, param0, param1, param_num, -				data, len, MDFLD_DSI_LP_TRANSMISSION); -} - -int mdfld_dsi_read_mcs_hs(struct mdfld_dsi_pkg_sender *sender, -			u8 cmd, -			u32 *data, -			u16 len) -{ -	if (!sender || !data || !len) { -		DRM_ERROR("Invalid parameters\n"); -		return -EINVAL; -	} - -	return mdfld_dsi_read_mcs(sender, cmd, data, len, -				MDFLD_DSI_HS_TRANSMISSION); -} - -int mdfld_dsi_read_mcs_lp(struct mdfld_dsi_pkg_sender *sender, -			u8 cmd, -			u32 *data, -			u16 len) -{ -	if (!sender || !data || !len) { -		WARN_ON(1); -		return -EINVAL; -	} - -	return mdfld_dsi_read_mcs(sender, cmd, data, len, -				MDFLD_DSI_LP_TRANSMISSION); -} -  -int mdfld_dsi_pkg_sender_init(struct mdfld_dsi_connector *dsi_connector, -								int pipe) -{ -	int ret; -	struct mdfld_dsi_pkg_sender *pkg_sender; -	struct mdfld_dsi_config *dsi_config = -					mdfld_dsi_get_config(dsi_connector); -	struct drm_device *dev = dsi_config->dev; -	struct drm_psb_private *dev_priv = dev->dev_private; -	struct psb_gtt *pg = &dev_priv->gtt; -	int i; -	struct mdfld_dsi_pkg *pkg, *tmp; -	u32 mipi_val = 0; - -	if (!dsi_connector) { -		WARN_ON(1); -		return -EINVAL; -	} - -	pkg_sender = dsi_connector->pkg_sender; - -	if (!pkg_sender || IS_ERR(pkg_sender)) { -		pkg_sender = kzalloc(sizeof(struct mdfld_dsi_pkg_sender), -								GFP_KERNEL); -		if (!pkg_sender) { -			dev_err(dev->dev, "Create DSI pkg sender failed\n"); -			return -ENOMEM; -		} - -		dsi_connector->pkg_sender = (void *)pkg_sender; -	} - -	pkg_sender->dev = dev; -	pkg_sender->dsi_connector = dsi_connector; -	pkg_sender->pipe = pipe; -	pkg_sender->pkg_num = 0; -	pkg_sender->panel_mode = 0; -	pkg_sender->status = MDFLD_DSI_PKG_SENDER_FREE; - -	/* Init dbi command buffer*/ - -	if (dsi_config->type == MDFLD_DSI_ENCODER_DBI) { -		pkg_sender->dbi_pkg_support = 1; -		ret = mdfld_dbi_cb_init(pkg_sender, pg, pipe); -		if (ret) { -			dev_err(dev->dev, "DBI command buffer map failed\n"); -			goto mapping_err; -		} -	} - -	/* Init regs */ -	if (pipe == 0) { -		pkg_sender->dpll_reg = MRST_DPLL_A; -		pkg_sender->dspcntr_reg = DSPACNTR; -		pkg_sender->pipeconf_reg = PIPEACONF; -		pkg_sender->dsplinoff_reg = DSPALINOFF; -		pkg_sender->dspsurf_reg = DSPASURF; -		pkg_sender->pipestat_reg = PIPEASTAT; - -		pkg_sender->mipi_intr_stat_reg = MIPIA_INTR_STAT_REG; -		pkg_sender->mipi_lp_gen_data_reg = MIPIA_LP_GEN_DATA_REG; -		pkg_sender->mipi_hs_gen_data_reg = MIPIA_HS_GEN_DATA_REG; -		pkg_sender->mipi_lp_gen_ctrl_reg = MIPIA_LP_GEN_CTRL_REG; -		pkg_sender->mipi_hs_gen_ctrl_reg = MIPIA_HS_GEN_CTRL_REG; -		pkg_sender->mipi_gen_fifo_stat_reg = MIPIA_GEN_FIFO_STAT_REG; -		pkg_sender->mipi_data_addr_reg = MIPIA_DATA_ADD_REG; -		pkg_sender->mipi_data_len_reg = MIPIA_DATA_LEN_REG; -		pkg_sender->mipi_cmd_addr_reg = MIPIA_CMD_ADD_REG; -		pkg_sender->mipi_cmd_len_reg = MIPIA_CMD_LEN_REG; -	} else if (pipe == 2) { -		pkg_sender->dpll_reg = MRST_DPLL_A; -		pkg_sender->dspcntr_reg = DSPCCNTR; -		pkg_sender->pipeconf_reg = PIPECCONF; -		pkg_sender->dsplinoff_reg = DSPCLINOFF; -		pkg_sender->dspsurf_reg = DSPCSURF; -		pkg_sender->pipestat_reg = PIPECSTAT; - -		pkg_sender->mipi_intr_stat_reg = -				MIPIA_INTR_STAT_REG + MIPIC_REG_OFFSET; -		pkg_sender->mipi_lp_gen_data_reg = -				MIPIA_LP_GEN_DATA_REG + MIPIC_REG_OFFSET; -		pkg_sender->mipi_hs_gen_data_reg = -				MIPIA_HS_GEN_DATA_REG + MIPIC_REG_OFFSET; -		pkg_sender->mipi_lp_gen_ctrl_reg = -				MIPIA_LP_GEN_CTRL_REG + MIPIC_REG_OFFSET; -		pkg_sender->mipi_hs_gen_ctrl_reg = -				MIPIA_HS_GEN_CTRL_REG + MIPIC_REG_OFFSET; -		pkg_sender->mipi_gen_fifo_stat_reg = -				MIPIA_GEN_FIFO_STAT_REG + MIPIC_REG_OFFSET; -		pkg_sender->mipi_data_addr_reg = -				MIPIA_DATA_ADD_REG + MIPIC_REG_OFFSET; -		pkg_sender->mipi_data_len_reg = -				MIPIA_DATA_LEN_REG + MIPIC_REG_OFFSET; -		pkg_sender->mipi_cmd_addr_reg = -				MIPIA_CMD_ADD_REG + MIPIC_REG_OFFSET; -		pkg_sender->mipi_cmd_len_reg = -				MIPIA_CMD_LEN_REG + MIPIC_REG_OFFSET; -	} - -	/* Init pkg list */ -	INIT_LIST_HEAD(&pkg_sender->pkg_list); -	INIT_LIST_HEAD(&pkg_sender->free_list); - -	spin_lock_init(&pkg_sender->lock); - -	/* Allocate free pkg pool */ -	for (i = 0; i < MDFLD_MAX_PKG_NUM; i++) { -		pkg = kzalloc(sizeof(struct mdfld_dsi_pkg), GFP_KERNEL); -		if (!pkg) { -			dev_err(dev->dev, "Out of memory allocating pkg pool"); -			ret = -ENOMEM; -			goto pkg_alloc_err; -		} -		INIT_LIST_HEAD(&pkg->entry); -		list_add_tail(&pkg->entry, &pkg_sender->free_list); -	} - -	/* -	 * For video mode, don't enable DPI timing output here, -	 * will init the DPI timing output during mode setting. -	 */ -	if (dsi_config->type == MDFLD_DSI_ENCODER_DPI) -		mipi_val = PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX; -	else if (dsi_config->type == MDFLD_DSI_ENCODER_DBI) -		mipi_val = PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX -			| TE_TRIGGER_GPIO_PIN; -	else -		DRM_ERROR("Bad DSI encoder type\n"); - -	if (pipe == 0) { -		mipi_val |= 0x2; -		REG_WRITE(MIPI, mipi_val); -		REG_READ(MIPI); -	} else if (pipe == 2) { -		REG_WRITE(MIPI_C, mipi_val); -		REG_READ(MIPI_C); -	} - -	/*do dsi controller init*/ -	dsi_controller_init(dsi_config, pipe); -	 -	return 0; - -pkg_alloc_err: -	list_for_each_entry_safe(pkg, tmp, &pkg_sender->free_list, entry) { -		list_del(&pkg->entry); -		kfree(pkg); -	} - -	/* Free mapped command buffer */ -	mdfld_dbi_cb_destroy(pkg_sender); -mapping_err: -	kfree(pkg_sender); -	dsi_connector->pkg_sender = NULL; -	return ret; -} - -void mdfld_dsi_pkg_sender_destroy(struct mdfld_dsi_pkg_sender *sender) -{ -	struct mdfld_dsi_pkg *pkg, *tmp; - -	if (!sender || IS_ERR(sender)) -		return; - -	/* Free pkg pool */ -	list_for_each_entry_safe(pkg, tmp, &sender->free_list, entry) { -		list_del(&pkg->entry); -		kfree(pkg); -	} -	/* Free pkg list */ -	list_for_each_entry_safe(pkg, tmp, &sender->pkg_list, entry) { -		list_del(&pkg->entry); -		kfree(pkg); -	} -	mdfld_dbi_cb_destroy(sender);	/* free mapped command buffer */ -	kfree(sender); -} diff --git a/drivers/staging/gma500/mdfld_dsi_pkg_sender.h b/drivers/staging/gma500/mdfld_dsi_pkg_sender.h deleted file mode 100644 index f24abc70068..00000000000 --- a/drivers/staging/gma500/mdfld_dsi_pkg_sender.h +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Copyright © 2010 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Authors: - * Jackie Li<yaodong.li@intel.com> - */ -#ifndef __MDFLD_DSI_PKG_SENDER_H__ -#define __MDFLD_DSI_PKG_SENDER_H__ - -#include <linux/kthread.h> - -#define MDFLD_MAX_DCS_PARAM	8 -#define MDFLD_MAX_PKG_NUM	2048 - -enum { -	MDFLD_DSI_PKG_DCS, -	MDFLD_DSI_PKG_GEN_SHORT_WRITE_0 = 0x03, -	MDFLD_DSI_PKG_GEN_SHORT_WRITE_1 = 0x13, -	MDFLD_DSI_PKG_GEN_SHORT_WRITE_2 = 0x23, -	MDFLD_DSI_PKG_GEN_READ_0 = 0x04, -	MDFLD_DSI_PKG_GEN_READ_1 = 0x14, -	MDFLD_DSI_PKG_GEN_READ_2 = 0x24, -	MDFLD_DSI_PKG_GEN_LONG_WRITE = 0x29, -	MDFLD_DSI_PKG_MCS_SHORT_WRITE_0 = 0x05, -	MDFLD_DSI_PKG_MCS_SHORT_WRITE_1 = 0x15, -	MDFLD_DSI_PKG_MCS_READ = 0x06, -	MDFLD_DSI_PKG_MCS_LONG_WRITE = 0x39, -}; - -enum { -	MDFLD_DSI_LP_TRANSMISSION, -	MDFLD_DSI_HS_TRANSMISSION, -	MDFLD_DSI_DCS, -}; - -enum { -	MDFLD_DSI_PANEL_MODE_SLEEP = 0x1, -}; - -enum { -	MDFLD_DSI_PKG_SENDER_FREE = 0x0, -	MDFLD_DSI_PKG_SENDER_BUSY = 0x1, -}; - -enum { -	MDFLD_DSI_SEND_PACKAGE, -	MDFLD_DSI_QUEUE_PACKAGE, -}; - -struct mdfld_dsi_gen_short_pkg { -	u8 cmd; -	u8 param; -}; - -struct mdfld_dsi_gen_long_pkg { -	u32 *data; -	u32 len; -}; - -struct mdfld_dsi_dcs_pkg { -	u8 cmd; -	u8 param[MDFLD_MAX_DCS_PARAM]; -	u32 param_num; -	u8 data_src; -}; - -struct mdfld_dsi_pkg { -	u8 pkg_type; -	u8 transmission_type; - -	union { -		struct mdfld_dsi_gen_short_pkg short_pkg; -		struct mdfld_dsi_gen_long_pkg long_pkg; -		struct mdfld_dsi_dcs_pkg dcs_pkg; -	} pkg; - -	struct list_head entry; -}; - -struct mdfld_dsi_pkg_sender { -	struct drm_device *dev; -	struct mdfld_dsi_connector *dsi_connector; -	u32 status; - -	u32 panel_mode; - -	int pipe; - -	spinlock_t lock; -	struct list_head pkg_list; -	struct list_head free_list; - -	u32 pkg_num; - -	int dbi_pkg_support; - -	u32 dbi_cb_phy; -	void *dbi_cb_addr; - -	/* Registers */ -	u32 dpll_reg; -	u32 dspcntr_reg; -	u32 pipeconf_reg; -	u32 pipestat_reg; -	u32 dsplinoff_reg; -	u32 dspsurf_reg; - -	u32 mipi_intr_stat_reg; -	u32 mipi_lp_gen_data_reg; -	u32 mipi_hs_gen_data_reg; -	u32 mipi_lp_gen_ctrl_reg; -	u32 mipi_hs_gen_ctrl_reg; -	u32 mipi_gen_fifo_stat_reg; -	u32 mipi_data_addr_reg; -	u32 mipi_data_len_reg; -	u32 mipi_cmd_addr_reg; -	u32 mipi_cmd_len_reg; -}; - -/* DCS definitions */ -#define DCS_SOFT_RESET			0x01 -#define DCS_ENTER_SLEEP_MODE		0x10 -#define DCS_EXIT_SLEEP_MODE		0x11 -#define DCS_SET_DISPLAY_OFF		0x28 -#define DCS_SET_DISPLAY_ON		0x29 -#define DCS_SET_COLUMN_ADDRESS		0x2a -#define DCS_SET_PAGE_ADDRESS		0x2b -#define DCS_WRITE_MEM_START		0x2c -#define DCS_SET_TEAR_OFF		0x34 -#define DCS_SET_TEAR_ON 		0x35 - -extern int mdfld_dsi_pkg_sender_init(struct mdfld_dsi_connector *dsi_connector, -			int pipe); -extern void mdfld_dsi_pkg_sender_destroy(struct mdfld_dsi_pkg_sender *sender); -extern int mdfld_dsi_send_dcs(struct mdfld_dsi_pkg_sender *sender, u8 dcs, -			u8 *param, u32 param_num, u8 data_src, int delay); -extern int mdfld_dsi_send_mcs_short_hs(struct mdfld_dsi_pkg_sender *sender, -			u8 cmd, u8 param, u8 param_num, int delay); -extern int mdfld_dsi_send_mcs_short_lp(struct mdfld_dsi_pkg_sender *sender, -			u8 cmd, u8 param, u8 param_num, int delay); -extern int mdfld_dsi_send_mcs_long_hs(struct mdfld_dsi_pkg_sender *sender, -			u32 *data, u32 len, int delay); -extern int mdfld_dsi_send_mcs_long_lp(struct mdfld_dsi_pkg_sender *sender, -			u32 *data, u32 len, int delay); -extern int mdfld_dsi_send_gen_short_hs(struct mdfld_dsi_pkg_sender *sender, -			u8 param0, u8 param1, u8 param_num, int delay); -extern int mdfld_dsi_send_gen_short_lp(struct mdfld_dsi_pkg_sender *sender, -			u8 param0, u8 param1, u8 param_num, int delay); -extern int mdfld_dsi_send_gen_long_hs(struct mdfld_dsi_pkg_sender *sender, -			u32 *data, u32 len, int delay); -extern int mdfld_dsi_send_gen_long_lp(struct mdfld_dsi_pkg_sender *sender, -			u32 *data, u32 len, int delay); - -extern int mdfld_dsi_read_gen_hs(struct mdfld_dsi_pkg_sender *sender, -			u8 param0, u8 param1, u8 param_num, u32 *data, u16 len); -extern int mdfld_dsi_read_gen_lp(struct mdfld_dsi_pkg_sender *sender, -			u8 param0, u8 param1, u8 param_num, u32 *data, u16 len); -extern int mdfld_dsi_read_mcs_hs(struct mdfld_dsi_pkg_sender *sender, -			u8 cmd, u32 *data, u16 len); -extern int mdfld_dsi_read_mcs_lp(struct mdfld_dsi_pkg_sender *sender, -			u8 cmd, u32 *data, u16 len); - -extern void mdfld_dsi_cmds_kick_out(struct mdfld_dsi_pkg_sender *sender); - -#endif /* __MDFLD_DSI_PKG_SENDER_H__ */ diff --git a/drivers/staging/gma500/mdfld_intel_display.c b/drivers/staging/gma500/mdfld_intel_display.c deleted file mode 100644 index 0b37b7b6b02..00000000000 --- a/drivers/staging/gma500/mdfld_intel_display.c +++ /dev/null @@ -1,1404 +0,0 @@ -/* - * Copyright © 2006-2011 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Authors: - *	Eric Anholt <eric@anholt.net> - */ - -#include "framebuffer.h" -#include "psb_intel_display.h" -#include "mdfld_dsi_dbi.h" -#include "mdfld_dsi_dpi.h" -#include "mdfld_dsi_dbi_dpu.h" - -#include <linux/pm_runtime.h> - -#ifdef MIN -#undef MIN -#endif - -#define MIN(x, y) (((x) < (y)) ? (x) : (y)) - -/* Hardcoded currently */ -static int ksel = KSEL_CRYSTAL_19; - -extern void mdfld_save_display(struct drm_device *dev); -extern bool gbgfxsuspended; - -struct psb_intel_range_t { -	int min, max; -}; - -struct mdfld_limit_t { -	struct psb_intel_range_t dot, m, p1; -}; - -struct mdfld_intel_clock_t { -	/* given values */ -	int n; -	int m1, m2; -	int p1, p2; -	/* derived values */ -	int dot; -	int vco; -	int m; -	int p; -}; - - - -#define COUNT_MAX 0x10000000 - -void mdfldWaitForPipeDisable(struct drm_device *dev, int pipe) -{ -	int count, temp; -	u32 pipeconf_reg = PIPEACONF; -	 -	switch (pipe) { -	case 0: -		break; -	case 1: -		pipeconf_reg = PIPEBCONF; -		break; -	case 2: -		pipeconf_reg = PIPECCONF; -		break; -	default: -		DRM_ERROR("Illegal Pipe Number. \n"); -		return; -	} - -	/* FIXME JLIU7_PO */ -	psb_intel_wait_for_vblank(dev); -	return; - -	/* Wait for for the pipe disable to take effect. */ -	for (count = 0; count < COUNT_MAX; count++) { -		temp = REG_READ(pipeconf_reg); -		if ((temp & PIPEACONF_PIPE_STATE) == 0) -			break; -	} -} - -void mdfldWaitForPipeEnable(struct drm_device *dev, int pipe) -{ -	int count, temp; -	u32 pipeconf_reg = PIPEACONF; -	 -	switch (pipe) { -	case 0: -		break; -	case 1: -		pipeconf_reg = PIPEBCONF; -		break; -	case 2: -		pipeconf_reg = PIPECCONF; -		break; -	default: -		dev_err(dev->dev, "Illegal Pipe Number.\n"); -		return; -	} - -	/* FIXME JLIU7_PO */ -	psb_intel_wait_for_vblank(dev); -	return; - -	/* Wait for for the pipe enable to take effect. */ -	for (count = 0; count < COUNT_MAX; count++) { -		temp = REG_READ(pipeconf_reg); -		if ((temp & PIPEACONF_PIPE_STATE) == 1) -			break; -	} -} - - -static int mdfld_intel_crtc_cursor_set(struct drm_crtc *crtc, -				 struct drm_file *file_priv, -				 uint32_t handle, -				 uint32_t width, uint32_t height) -{ -	struct drm_device *dev = crtc->dev; -	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); -	int pipe = psb_intel_crtc->pipe; -	uint32_t control = CURACNTR; -	uint32_t base = CURABASE; -	uint32_t temp; -	size_t addr = 0; -	struct gtt_range *gt; -	struct drm_gem_object *obj; -	int ret; - -	switch (pipe) { -	case 0: -		break; -	case 1: -		control = CURBCNTR; -		base = CURBBASE; -		break; -	case 2: -		control = CURCCNTR; -		base = CURCBASE; -		break; -	default: -		dev_err(dev->dev, "Illegal Pipe Number. \n"); -		return -EINVAL; -	} -	 -#if 1 /* FIXME_JLIU7 can't enalbe cursorB/C HW issue. need to remove after HW fix */ -	if (pipe != 0) -		return 0; -#endif  -	/* if we want to turn of the cursor ignore width and height */ -	if (!handle) { -		dev_dbg(dev->dev, "cursor off\n"); -		/* turn off the cursor */ -		temp = 0; -		temp |= CURSOR_MODE_DISABLE; - -		if (gma_power_begin(dev, true)) { -			REG_WRITE(control, temp); -			REG_WRITE(base, 0); -			gma_power_end(dev); -		} -		/* Unpin the old GEM object */ -		if (psb_intel_crtc->cursor_obj) { -			gt = container_of(psb_intel_crtc->cursor_obj, -							struct gtt_range, gem); -			psb_gtt_unpin(gt); -			drm_gem_object_unreference(psb_intel_crtc->cursor_obj); -			psb_intel_crtc->cursor_obj = NULL; -		} -		return 0; -	} - -	/* Currently we only support 64x64 cursors */ -	if (width != 64 || height != 64) { -		DRM_ERROR("we currently only support 64x64 cursors\n"); -		return -EINVAL; -	} - -	obj = drm_gem_object_lookup(dev, file_priv, handle); -	if (!obj) -		return -ENOENT; - -	if (obj->size < width * height * 4) { -		dev_dbg(dev->dev, "buffer is to small\n"); -		return -ENOMEM; -	} - -	gt = container_of(obj, struct gtt_range, gem); - -	/* Pin the memory into the GTT */ -	ret = psb_gtt_pin(gt); -	if (ret) { -		dev_err(dev->dev, "Can not pin down handle 0x%x\n", handle); -		return ret; -	} - - -	addr = gt->offset;	/* Or resource.start ??? */ - -	psb_intel_crtc->cursor_addr = addr; - -	temp = 0; -	/* set the pipe for the cursor */ -	temp |= (pipe << 28); -	temp |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE; - -	if (gma_power_begin(dev, true)) { -		REG_WRITE(control, temp); -		REG_WRITE(base, addr); -		gma_power_end(dev); -	} -	/* unpin the old GEM object */ -	if (psb_intel_crtc->cursor_obj) { -		gt = container_of(psb_intel_crtc->cursor_obj, -							struct gtt_range, gem); -		psb_gtt_unpin(gt); -		drm_gem_object_unreference(psb_intel_crtc->cursor_obj); -		psb_intel_crtc->cursor_obj = obj; -	} -	return 0; -} - -static int mdfld_intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) -{ -	struct drm_device *dev = crtc->dev; -	struct drm_psb_private * dev_priv = (struct drm_psb_private *)dev->dev_private; -	struct mdfld_dbi_dpu_info *dpu_info = dev_priv->dbi_dpu_info; -	struct psb_drm_dpu_rect rect; -	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); -	int pipe = psb_intel_crtc->pipe; -	uint32_t pos = CURAPOS; -	uint32_t base = CURABASE; -	uint32_t temp = 0; -	uint32_t addr; - -	switch (pipe) { -	case 0: -		if (dpu_info) { -			rect.x = x; -			rect.y = y; -		 -			mdfld_dbi_dpu_report_damage(dev, MDFLD_CURSORA, &rect); -			mdfld_dpu_exit_dsr(dev); -		} else if (!(dev_priv->dsr_fb_update & MDFLD_DSR_CURSOR_0)) -			mdfld_dsi_dbi_exit_dsr(dev, MDFLD_DSR_CURSOR_0); -		break; -	case 1: -		pos = CURBPOS; -		base = CURBBASE; -		break; -	case 2: -		if (dpu_info) { -			mdfld_dbi_dpu_report_damage(dev, MDFLD_CURSORC, &rect); -			mdfld_dpu_exit_dsr(dev); -		} else if (!(dev_priv->dsr_fb_update & MDFLD_DSR_CURSOR_2)) -			mdfld_dsi_dbi_exit_dsr(dev, MDFLD_DSR_CURSOR_2); -		pos = CURCPOS; -		base = CURCBASE; -		break; -	default: -		DRM_ERROR("Illegal Pipe Number. \n"); -		return -EINVAL; -	} -		 -#if 1 /* FIXME_JLIU7 can't enable cursorB/C HW issue. need to remove after HW fix */ -	if (pipe != 0) -		return 0; -#endif  -	if (x < 0) { -		temp |= (CURSOR_POS_SIGN << CURSOR_X_SHIFT); -		x = -x; -	} -	if (y < 0) { -		temp |= (CURSOR_POS_SIGN << CURSOR_Y_SHIFT); -		y = -y; -	} - -	temp |= ((x & CURSOR_POS_MASK) << CURSOR_X_SHIFT); -	temp |= ((y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT); - -	addr = psb_intel_crtc->cursor_addr; - -	if (gma_power_begin(dev, true)) { -		REG_WRITE(pos, temp); -		REG_WRITE(base, addr); -		gma_power_end(dev); -	} - -	return 0; -} - -const struct drm_crtc_funcs mdfld_intel_crtc_funcs = { -	.cursor_set = mdfld_intel_crtc_cursor_set, -	.cursor_move = mdfld_intel_crtc_cursor_move, -	.gamma_set = psb_intel_crtc_gamma_set, -	.set_config = drm_crtc_helper_set_config, -	.destroy = psb_intel_crtc_destroy, -}; - -static struct drm_device globle_dev; - -void mdfld__intel_plane_set_alpha(int enable) -{ -	struct drm_device *dev = &globle_dev; -	int dspcntr_reg = DSPACNTR; -	u32 dspcntr; - -	dspcntr = REG_READ(dspcntr_reg); - -	if (enable) { -		dspcntr &= ~DISPPLANE_32BPP_NO_ALPHA; -		dspcntr |= DISPPLANE_32BPP; -	} else { -		dspcntr &= ~DISPPLANE_32BPP; -		dspcntr |= DISPPLANE_32BPP_NO_ALPHA; -	} - -	REG_WRITE(dspcntr_reg, dspcntr); -} - -int mdfld__intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, struct drm_framebuffer *old_fb) -{ -	struct drm_device *dev = crtc->dev; -	/* struct drm_i915_master_private *master_priv; */ -	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); -	struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb); -	int pipe = psb_intel_crtc->pipe; -	unsigned long start, offset; -	int dsplinoff = DSPALINOFF; -	int dspsurf = DSPASURF; -	int dspstride = DSPASTRIDE; -	int dspcntr_reg = DSPACNTR; -	u32 dspcntr; -	int ret = 0; - -	memcpy(&globle_dev, dev, sizeof(struct drm_device)); - -	if (!gma_power_begin(dev, true)) -		return 0; - -	/* no fb bound */ -	if (!crtc->fb) { -		dev_err(dev->dev, "No FB bound\n"); -		goto psb_intel_pipe_cleaner; -	} - -	switch (pipe) { -	case 0: -		dsplinoff = DSPALINOFF; -		break; -	case 1: -		dsplinoff = DSPBLINOFF; -		dspsurf = DSPBSURF; -		dspstride = DSPBSTRIDE; -		dspcntr_reg = DSPBCNTR; -		break; -	case 2: -		dsplinoff = DSPCLINOFF; -		dspsurf = DSPCSURF; -		dspstride = DSPCSTRIDE; -		dspcntr_reg = DSPCCNTR; -		break; -	default: -		dev_err(dev->dev, "Illegal Pipe Number.\n"); -		return -EINVAL; -	} - -	ret = psb_gtt_pin(psbfb->gtt); -	if (ret < 0) -	        goto psb_intel_pipe_set_base_exit; - -	start = psbfb->gtt->offset; -	offset = y * crtc->fb->pitches[0] + x * (crtc->fb->bits_per_pixel / 8); - -	REG_WRITE(dspstride, crtc->fb->pitches[0]); -	dspcntr = REG_READ(dspcntr_reg); -	dspcntr &= ~DISPPLANE_PIXFORMAT_MASK; - -	switch (crtc->fb->bits_per_pixel) { -	case 8: -		dspcntr |= DISPPLANE_8BPP; -		break; -	case 16: -		if (crtc->fb->depth == 15) -			dspcntr |= DISPPLANE_15_16BPP; -		else -			dspcntr |= DISPPLANE_16BPP; -		break; -	case 24: -	case 32: -		dspcntr |= DISPPLANE_32BPP_NO_ALPHA; -		break; -	default: -		dev_err(dev->dev, "Unknown color depth\n"); -		ret = -EINVAL; -		goto psb_intel_pipe_set_base_exit; -	} -	REG_WRITE(dspcntr_reg, dspcntr); - -	dev_dbg(dev->dev, "Writing base %08lX %08lX %d %d\n", -	                                        start, offset, x, y); - -	REG_WRITE(dsplinoff, offset); -	REG_READ(dsplinoff); -	REG_WRITE(dspsurf, start); -	REG_READ(dspsurf); - -psb_intel_pipe_cleaner: -	/* If there was a previous display we can now unpin it */ -	if (old_fb) -		psb_gtt_unpin(to_psb_fb(old_fb)->gtt); - -psb_intel_pipe_set_base_exit: -	gma_power_end(dev); -	return ret; -} - -/** - * Disable the pipe, plane and pll. - * - */ -void mdfld_disable_crtc (struct drm_device *dev, int pipe) -{ -	int dpll_reg = MRST_DPLL_A; -	int dspcntr_reg = DSPACNTR; -	int dspbase_reg = MRST_DSPABASE; -	int pipeconf_reg = PIPEACONF; -	u32 gen_fifo_stat_reg = GEN_FIFO_STAT_REG; -	u32 temp; - -	switch (pipe) { -	case 0: -		break; -	case 1: -		dpll_reg = MDFLD_DPLL_B; -		dspcntr_reg = DSPBCNTR; -		dspbase_reg = DSPBSURF; -		pipeconf_reg = PIPEBCONF; -		break; -	case 2: -		dpll_reg = MRST_DPLL_A; -		dspcntr_reg = DSPCCNTR; -		dspbase_reg = MDFLD_DSPCBASE; -		pipeconf_reg = PIPECCONF; -		gen_fifo_stat_reg = GEN_FIFO_STAT_REG + MIPIC_REG_OFFSET; -		break; -	default: -		dev_err(dev->dev, "Illegal Pipe Number. \n"); -		return; -	} - -	if (pipe != 1) -		mdfld_dsi_gen_fifo_ready (dev, gen_fifo_stat_reg, HS_CTRL_FIFO_EMPTY | HS_DATA_FIFO_EMPTY); - -	/* Disable display plane */ -	temp = REG_READ(dspcntr_reg); -	if ((temp & DISPLAY_PLANE_ENABLE) != 0) { -		REG_WRITE(dspcntr_reg, -			  temp & ~DISPLAY_PLANE_ENABLE); -		/* Flush the plane changes */ -		REG_WRITE(dspbase_reg, REG_READ(dspbase_reg)); -		REG_READ(dspbase_reg); -	} - -	/* FIXME_JLIU7 MDFLD_PO revisit */ -	/* Wait for vblank for the disable to take effect */ -/* MDFLD_PO_JLIU7		psb_intel_wait_for_vblank(dev); */ - -	/* Next, disable display pipes */ -	temp = REG_READ(pipeconf_reg); -	if ((temp & PIPEACONF_ENABLE) != 0) { -		temp &= ~PIPEACONF_ENABLE; -		temp |= PIPECONF_PLANE_OFF | PIPECONF_CURSOR_OFF; -		REG_WRITE(pipeconf_reg, temp); -		REG_READ(pipeconf_reg); - -		/* Wait for for the pipe disable to take effect. */ -		mdfldWaitForPipeDisable(dev, pipe); -	} - -	temp = REG_READ(dpll_reg); -	if (temp & DPLL_VCO_ENABLE) { -		if (((pipe != 1) && !((REG_READ(PIPEACONF) | REG_READ(PIPECCONF)) & PIPEACONF_ENABLE)) -				|| (pipe == 1)){ -			temp &= ~(DPLL_VCO_ENABLE); -			REG_WRITE(dpll_reg, temp); -			REG_READ(dpll_reg); -			/* Wait for the clocks to turn off. */ -			/* FIXME_MDFLD PO may need more delay */ -			udelay(500); - -			if (!(temp & MDFLD_PWR_GATE_EN)) { -				/* gating power of DPLL */ -				REG_WRITE(dpll_reg, temp | MDFLD_PWR_GATE_EN); -				/* FIXME_MDFLD PO - change 500 to 1 after PO */ -				udelay(5000); -			} -		} -	} - -} - -/** - * Sets the power management mode of the pipe and plane. - * - * This code should probably grow support for turning the cursor off and back - * on appropriately at the same time as we're turning the pipe off/on. - */ -static void mdfld_crtc_dpms(struct drm_crtc *crtc, int mode) -{ -	struct drm_device *dev = crtc->dev; -	struct drm_psb_private *dev_priv = dev->dev_private; -	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); -	int pipe = psb_intel_crtc->pipe; -	int dpll_reg = MRST_DPLL_A; -	int dspcntr_reg = DSPACNTR; -	int dspbase_reg = MRST_DSPABASE; -	int pipeconf_reg = PIPEACONF; -	u32 pipestat_reg = PIPEASTAT; -	u32 gen_fifo_stat_reg = GEN_FIFO_STAT_REG; -	u32 pipeconf = dev_priv->pipeconf; -	u32 dspcntr = dev_priv->dspcntr; -	u32 mipi_enable_reg = MIPIA_DEVICE_READY_REG; -	u32 temp; -	bool enabled; -	int timeout = 0; - -	if (!gma_power_begin(dev, true)) -		return; - -	 /* Ignore if system is already in DSR and in suspended state. */ -	if(/*gbgfxsuspended */0 && dev_priv->dispstatus == false && mode == 3){ -	    if(dev_priv->rpm_enabled && pipe == 1){ -	//          dev_priv->is_mipi_on = false; -	          pm_request_idle(&dev->pdev->dev); -	    } -	    return; -	}else if(mode == 0) { -		//do not need to set gbdispstatus=true in crtc. -		//this will be set in encoder such as mdfld_dsi_dbi_dpms -	    //gbdispstatus = true; -	} - -/* FIXME_JLIU7 MDFLD_PO replaced w/ the following function */ -/* mdfld_dbi_dpms (struct drm_device *dev, int pipe, bool enabled) */ - -	switch (pipe) { -	case 0: -		break; -	case 1: -		dpll_reg = DPLL_B; -		dspcntr_reg = DSPBCNTR; -		dspbase_reg = MRST_DSPBBASE; -		pipeconf_reg = PIPEBCONF; -		pipeconf = dev_priv->pipeconf1; -		dspcntr = dev_priv->dspcntr1; -		dpll_reg = MDFLD_DPLL_B; -		break; -	case 2: -		dpll_reg = MRST_DPLL_A; -		dspcntr_reg = DSPCCNTR; -		dspbase_reg = MDFLD_DSPCBASE; -		pipeconf_reg = PIPECCONF; -		pipestat_reg = PIPECSTAT; -		pipeconf = dev_priv->pipeconf2; -		dspcntr = dev_priv->dspcntr2; -		gen_fifo_stat_reg = GEN_FIFO_STAT_REG + MIPIC_REG_OFFSET; -		mipi_enable_reg = MIPIA_DEVICE_READY_REG + MIPIC_REG_OFFSET; -		break; -	default: -		dev_err(dev->dev, "Illegal Pipe Number.\n"); -		return; -	} - -	/* XXX: When our outputs are all unaware of DPMS modes other than off -	 * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC. -	 */ -	switch (mode) { -	case DRM_MODE_DPMS_ON: -	case DRM_MODE_DPMS_STANDBY: -	case DRM_MODE_DPMS_SUSPEND: -		/* Enable the DPLL */ -		temp = REG_READ(dpll_reg); - -		if ((temp & DPLL_VCO_ENABLE) == 0) { -			/* When ungating power of DPLL, needs to wait 0.5us before enable the VCO */ -			if (temp & MDFLD_PWR_GATE_EN) { -				temp &= ~MDFLD_PWR_GATE_EN; -				REG_WRITE(dpll_reg, temp); -				/* FIXME_MDFLD PO - change 500 to 1 after PO */ -				udelay(500); -			} - -			REG_WRITE(dpll_reg, temp); -			REG_READ(dpll_reg); -			/* FIXME_MDFLD PO - change 500 to 1 after PO */ -			udelay(500); -			 -			REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE); -			REG_READ(dpll_reg); - -			/** -			 * wait for DSI PLL to lock -			 * NOTE: only need to poll status of pipe 0 and pipe 1, -			 * since both MIPI pipes share the same PLL. -			 */ -			while ((pipe != 2) && (timeout < 20000) && !(REG_READ(pipeconf_reg) & PIPECONF_DSIPLL_LOCK)) { -				udelay(150); -				timeout ++; -			} -		} - -		/* Enable the plane */ -		temp = REG_READ(dspcntr_reg); -		if ((temp & DISPLAY_PLANE_ENABLE) == 0) { -			REG_WRITE(dspcntr_reg, -				temp | DISPLAY_PLANE_ENABLE); -			/* Flush the plane changes */ -			REG_WRITE(dspbase_reg, REG_READ(dspbase_reg)); -		} - -		/* Enable the pipe */ -		temp = REG_READ(pipeconf_reg); -		if ((temp & PIPEACONF_ENABLE) == 0) { -			REG_WRITE(pipeconf_reg, pipeconf); - -			/* Wait for for the pipe enable to take effect. */ -			mdfldWaitForPipeEnable(dev, pipe); -		} - -		/*workaround for sighting 3741701 Random X blank display*/ -		/*perform w/a in video mode only on pipe A or C*/ -		if ((pipe == 0 || pipe == 2) && -			(mdfld_panel_dpi(dev) == true)) { -			REG_WRITE(pipestat_reg, REG_READ(pipestat_reg)); -			msleep(100); -			if(PIPE_VBLANK_STATUS & REG_READ(pipestat_reg)) { -				printk(KERN_ALERT "OK"); -			} else { -				printk(KERN_ALERT "STUCK!!!!"); -				/*shutdown controller*/ -				temp = REG_READ(dspcntr_reg); -				REG_WRITE(dspcntr_reg, temp & ~DISPLAY_PLANE_ENABLE); -				REG_WRITE(dspbase_reg, REG_READ(dspbase_reg)); -				/*mdfld_dsi_dpi_shut_down(dev, pipe);*/ -				REG_WRITE(0xb048, 1); -				msleep(100); -				temp = REG_READ(pipeconf_reg); -				temp &= ~PIPEACONF_ENABLE; -				REG_WRITE(pipeconf_reg, temp); -				msleep(100); /*wait for pipe disable*/ -			/*printk(KERN_ALERT "70008 is %x\n", REG_READ(0x70008)); -			printk(KERN_ALERT "b074 is %x\n", REG_READ(0xb074));*/ -				REG_WRITE(mipi_enable_reg, 0); -				msleep(100); -			printk(KERN_ALERT "70008 is %x\n", REG_READ(0x70008)); -			printk(KERN_ALERT "b074 is %x\n", REG_READ(0xb074)); -				REG_WRITE(0xb004, REG_READ(0xb004)); -				/* try to bring the controller back up again*/ -				REG_WRITE(mipi_enable_reg, 1); -				temp = REG_READ(dspcntr_reg); -				REG_WRITE(dspcntr_reg, temp | DISPLAY_PLANE_ENABLE); -				REG_WRITE(dspbase_reg, REG_READ(dspbase_reg)); -				/*mdfld_dsi_dpi_turn_on(dev, pipe);*/ -				REG_WRITE(0xb048, 2); -				msleep(100); -				temp = REG_READ(pipeconf_reg); -				temp |= PIPEACONF_ENABLE; -				REG_WRITE(pipeconf_reg, temp); -			} -		} - -		psb_intel_crtc_load_lut(crtc); - -		/* Give the overlay scaler a chance to enable -		   if it's on this pipe */ -		/* psb_intel_crtc_dpms_video(crtc, true); TODO */ - -		break; -	case DRM_MODE_DPMS_OFF: -		/* Give the overlay scaler a chance to disable -		 * if it's on this pipe */ -		/* psb_intel_crtc_dpms_video(crtc, FALSE); TODO */ -		if (pipe != 1) -			mdfld_dsi_gen_fifo_ready (dev, gen_fifo_stat_reg, HS_CTRL_FIFO_EMPTY | HS_DATA_FIFO_EMPTY); - -		/* Disable the VGA plane that we never use */ -		REG_WRITE(VGACNTRL, VGA_DISP_DISABLE); - -		/* Disable display plane */ -		temp = REG_READ(dspcntr_reg); -		if ((temp & DISPLAY_PLANE_ENABLE) != 0) { -			REG_WRITE(dspcntr_reg, -				  temp & ~DISPLAY_PLANE_ENABLE); -			/* Flush the plane changes */ -			REG_WRITE(dspbase_reg, REG_READ(dspbase_reg)); -			REG_READ(dspbase_reg); -		} - -		/* FIXME_JLIU7 MDFLD_PO revisit */ -		/* Wait for vblank for the disable to take effect */ -// MDFLD_PO_JLIU7		psb_intel_wait_for_vblank(dev); - -		/* Next, disable display pipes */ -		temp = REG_READ(pipeconf_reg); -		if ((temp & PIPEACONF_ENABLE) != 0) { -			temp &= ~PIPEACONF_ENABLE; -			temp |= PIPECONF_PLANE_OFF | PIPECONF_CURSOR_OFF; -			REG_WRITE(pipeconf_reg, temp); -//			REG_WRITE(pipeconf_reg, 0); -			REG_READ(pipeconf_reg); - -			/* Wait for for the pipe disable to take effect. */ -			mdfldWaitForPipeDisable(dev, pipe); -		} - -		temp = REG_READ(dpll_reg); -		if (temp & DPLL_VCO_ENABLE) { -			if (((pipe != 1) && !((REG_READ(PIPEACONF) | REG_READ(PIPECCONF)) & PIPEACONF_ENABLE)) -					|| (pipe == 1)){ -				temp &= ~(DPLL_VCO_ENABLE); -				REG_WRITE(dpll_reg, temp); -				REG_READ(dpll_reg); -				/* Wait for the clocks to turn off. */ -				/* FIXME_MDFLD PO may need more delay */ -				udelay(500); -#if 0 /* MDFLD_PO_JLIU7 */	 -		if (!(temp & MDFLD_PWR_GATE_EN)) { -			/* gating power of DPLL */ -			REG_WRITE(dpll_reg, temp | MDFLD_PWR_GATE_EN); -			/* FIXME_MDFLD PO - change 500 to 1 after PO */ -			udelay(5000); -		} -#endif  /* MDFLD_PO_JLIU7 */	 -			} -		} -		break; -	} - -	enabled = crtc->enabled && mode != DRM_MODE_DPMS_OFF; - -#if 0				/* JB: Add vblank support later */ -	if (enabled) -		dev_priv->vblank_pipe |= (1 << pipe); -	else -		dev_priv->vblank_pipe &= ~(1 << pipe); -#endif - -	gma_power_end(dev); -} - - -#define MDFLD_LIMT_DPLL_19	    0 -#define MDFLD_LIMT_DPLL_25	    1 -#define MDFLD_LIMT_DPLL_83	    2 -#define MDFLD_LIMT_DPLL_100	    3 -#define MDFLD_LIMT_DSIPLL_19	    4 -#define MDFLD_LIMT_DSIPLL_25	    5 -#define MDFLD_LIMT_DSIPLL_83	    6 -#define MDFLD_LIMT_DSIPLL_100	    7 - -#define MDFLD_DOT_MIN		  19750  /* FIXME_MDFLD JLIU7 need to find out  min & max for MDFLD */ -#define MDFLD_DOT_MAX		  120000 -#define MDFLD_DPLL_M_MIN_19	    113 -#define MDFLD_DPLL_M_MAX_19	    155 -#define MDFLD_DPLL_P1_MIN_19	    2 -#define MDFLD_DPLL_P1_MAX_19	    10 -#define MDFLD_DPLL_M_MIN_25	    101 -#define MDFLD_DPLL_M_MAX_25	    130 -#define MDFLD_DPLL_P1_MIN_25	    2 -#define MDFLD_DPLL_P1_MAX_25	    10 -#define MDFLD_DPLL_M_MIN_83	    64 -#define MDFLD_DPLL_M_MAX_83	    64 -#define MDFLD_DPLL_P1_MIN_83	    2 -#define MDFLD_DPLL_P1_MAX_83	    2 -#define MDFLD_DPLL_M_MIN_100	    64 -#define MDFLD_DPLL_M_MAX_100	    64 -#define MDFLD_DPLL_P1_MIN_100	    2 -#define MDFLD_DPLL_P1_MAX_100	    2 -#define MDFLD_DSIPLL_M_MIN_19	    131 -#define MDFLD_DSIPLL_M_MAX_19	    175 -#define MDFLD_DSIPLL_P1_MIN_19	    3 -#define MDFLD_DSIPLL_P1_MAX_19	    8 -#define MDFLD_DSIPLL_M_MIN_25	    97 -#define MDFLD_DSIPLL_M_MAX_25	    140 -#define MDFLD_DSIPLL_P1_MIN_25	    3 -#define MDFLD_DSIPLL_P1_MAX_25	    9 -#define MDFLD_DSIPLL_M_MIN_83	    33 -#define MDFLD_DSIPLL_M_MAX_83	    92 -#define MDFLD_DSIPLL_P1_MIN_83	    2 -#define MDFLD_DSIPLL_P1_MAX_83	    3 -#define MDFLD_DSIPLL_M_MIN_100	    97 -#define MDFLD_DSIPLL_M_MAX_100	    140 -#define MDFLD_DSIPLL_P1_MIN_100	    3 -#define MDFLD_DSIPLL_P1_MAX_100	    9 - -static const struct mdfld_limit_t mdfld_limits[] = { -	{			/* MDFLD_LIMT_DPLL_19 */ -	 .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX}, -	 .m = {.min = MDFLD_DPLL_M_MIN_19, .max = MDFLD_DPLL_M_MAX_19}, -	 .p1 = {.min = MDFLD_DPLL_P1_MIN_19, .max = MDFLD_DPLL_P1_MAX_19}, -	 }, -	{			/* MDFLD_LIMT_DPLL_25 */ -	 .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX}, -	 .m = {.min = MDFLD_DPLL_M_MIN_25, .max = MDFLD_DPLL_M_MAX_25}, -	 .p1 = {.min = MDFLD_DPLL_P1_MIN_25, .max = MDFLD_DPLL_P1_MAX_25}, -	 }, -	{			/* MDFLD_LIMT_DPLL_83 */ -	 .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX}, -	 .m = {.min = MDFLD_DPLL_M_MIN_83, .max = MDFLD_DPLL_M_MAX_83}, -	 .p1 = {.min = MDFLD_DPLL_P1_MIN_83, .max = MDFLD_DPLL_P1_MAX_83}, -	 }, -	{			/* MDFLD_LIMT_DPLL_100 */ -	 .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX}, -	 .m = {.min = MDFLD_DPLL_M_MIN_100, .max = MDFLD_DPLL_M_MAX_100}, -	 .p1 = {.min = MDFLD_DPLL_P1_MIN_100, .max = MDFLD_DPLL_P1_MAX_100}, -	 }, -	{			/* MDFLD_LIMT_DSIPLL_19 */ -	 .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX}, -	 .m = {.min = MDFLD_DSIPLL_M_MIN_19, .max = MDFLD_DSIPLL_M_MAX_19}, -	 .p1 = {.min = MDFLD_DSIPLL_P1_MIN_19, .max = MDFLD_DSIPLL_P1_MAX_19}, -	 }, -	{			/* MDFLD_LIMT_DSIPLL_25 */ -	 .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX}, -	 .m = {.min = MDFLD_DSIPLL_M_MIN_25, .max = MDFLD_DSIPLL_M_MAX_25}, -	 .p1 = {.min = MDFLD_DSIPLL_P1_MIN_25, .max = MDFLD_DSIPLL_P1_MAX_25}, -	 }, -	{			/* MDFLD_LIMT_DSIPLL_83 */ -	 .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX}, -	 .m = {.min = MDFLD_DSIPLL_M_MIN_83, .max = MDFLD_DSIPLL_M_MAX_83}, -	 .p1 = {.min = MDFLD_DSIPLL_P1_MIN_83, .max = MDFLD_DSIPLL_P1_MAX_83}, -	 }, -	{			/* MDFLD_LIMT_DSIPLL_100 */ -	 .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX}, -	 .m = {.min = MDFLD_DSIPLL_M_MIN_100, .max = MDFLD_DSIPLL_M_MAX_100}, -	 .p1 = {.min = MDFLD_DSIPLL_P1_MIN_100, .max = MDFLD_DSIPLL_P1_MAX_100}, -	 }, -}; - -#define MDFLD_M_MIN	    21 -#define MDFLD_M_MAX	    180 -static const u32 mdfld_m_converts[] = { -/* M configuration table from 9-bit LFSR table */ -	224, 368, 440, 220, 366, 439, 219, 365, 182, 347, /* 21 - 30 */ -	173, 342, 171, 85, 298, 149, 74, 37, 18, 265,   /* 31 - 40 */ -	388, 194, 353, 432, 216, 108, 310, 155, 333, 166, /* 41 - 50 */ -	83, 41, 276, 138, 325, 162, 337, 168, 340, 170, /* 51 - 60 */ -	341, 426, 469, 234, 373, 442, 221, 110, 311, 411, /* 61 - 70 */ -	461, 486, 243, 377, 188, 350, 175, 343, 427, 213, /* 71 - 80 */ -	106, 53, 282, 397, 354, 227, 113, 56, 284, 142, /* 81 - 90 */ -	71, 35, 273, 136, 324, 418, 465, 488, 500, 506, /* 91 - 100 */ -	253, 126, 63, 287, 399, 455, 483, 241, 376, 444, /* 101 - 110 */ -	478, 495, 503, 251, 381, 446, 479, 239, 375, 443, /* 111 - 120 */ -	477, 238, 119, 315, 157, 78, 295, 147, 329, 420, /* 121 - 130 */ -	210, 105, 308, 154, 77, 38, 275, 137, 68, 290, /* 131 - 140 */ -	145, 328, 164, 82, 297, 404, 458, 485, 498, 249, /* 141 - 150 */ -	380, 190, 351, 431, 471, 235, 117, 314, 413, 206, /* 151 - 160 */ -	103, 51, 25, 12, 262, 387, 193, 96, 48, 280, /* 161 - 170 */ -	396, 198, 99, 305, 152, 76, 294, 403, 457, 228, /* 171 - 180 */ -}; - -static const struct mdfld_limit_t *mdfld_limit(struct drm_crtc *crtc) -{ -	const struct mdfld_limit_t *limit = NULL; -	struct drm_device *dev = crtc->dev; -	struct drm_psb_private *dev_priv = dev->dev_private; - -	if (psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_MIPI) -	    || psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_MIPI2)) { -		if ((ksel == KSEL_CRYSTAL_19) || (ksel == KSEL_BYPASS_19)) -			limit = &mdfld_limits[MDFLD_LIMT_DSIPLL_19]; -		else if (ksel == KSEL_BYPASS_25)  -			limit = &mdfld_limits[MDFLD_LIMT_DSIPLL_25]; -		else if ((ksel == KSEL_BYPASS_83_100) && (dev_priv->core_freq == 166)) -			limit = &mdfld_limits[MDFLD_LIMT_DSIPLL_83]; -		else if ((ksel == KSEL_BYPASS_83_100) && -			 (dev_priv->core_freq == 100 || dev_priv->core_freq == 200)) -			limit = &mdfld_limits[MDFLD_LIMT_DSIPLL_100]; -	} else if (psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI)) { -		if ((ksel == KSEL_CRYSTAL_19) || (ksel == KSEL_BYPASS_19)) -			limit = &mdfld_limits[MDFLD_LIMT_DPLL_19]; -		else if (ksel == KSEL_BYPASS_25)  -			limit = &mdfld_limits[MDFLD_LIMT_DPLL_25]; -		else if ((ksel == KSEL_BYPASS_83_100) && (dev_priv->core_freq == 166)) -			limit = &mdfld_limits[MDFLD_LIMT_DPLL_83]; -		else if ((ksel == KSEL_BYPASS_83_100) && -			 (dev_priv->core_freq == 100 || dev_priv->core_freq == 200)) -			limit = &mdfld_limits[MDFLD_LIMT_DPLL_100]; -	} else { -		limit = NULL; -		dev_err(dev->dev, "mdfld_limit Wrong display type.\n"); -	} - -	return limit; -} - -/** Derive the pixel clock for the given refclk and divisors for 8xx chips. */ -static void mdfld_clock(int refclk, struct mdfld_intel_clock_t *clock) -{ -	clock->dot = (refclk * clock->m) / clock->p1; -} - -/** - * Returns a set of divisors for the desired target clock with the given refclk, - * or FALSE.  Divisor values are the actual divisors for - */ -static bool -mdfldFindBestPLL(struct drm_crtc *crtc, int target, int refclk, -		struct mdfld_intel_clock_t *best_clock) -{ -	struct mdfld_intel_clock_t clock; -	const struct mdfld_limit_t *limit = mdfld_limit(crtc); -	int err = target; - -	memset(best_clock, 0, sizeof(*best_clock)); - -	for (clock.m = limit->m.min; clock.m <= limit->m.max; clock.m++) { -		for (clock.p1 = limit->p1.min; clock.p1 <= limit->p1.max; -		     clock.p1++) { -			int this_err; - -			mdfld_clock(refclk, &clock); - -			this_err = abs(clock.dot - target); -			if (this_err < err) { -				*best_clock = clock; -				err = this_err; -			} -		} -	} -	return err != target; -} - -/** - * Return the pipe currently connected to the panel fitter, - * or -1 if the panel fitter is not present or not in use - */ -static int mdfld_panel_fitter_pipe(struct drm_device *dev) -{ -	u32 pfit_control; - -	pfit_control = REG_READ(PFIT_CONTROL); - -	/* See if the panel fitter is in use */ -	if ((pfit_control & PFIT_ENABLE) == 0) -		return -1; -	return (pfit_control >> 29) & 3; -} - -static int mdfld_crtc_mode_set(struct drm_crtc *crtc, -			      struct drm_display_mode *mode, -			      struct drm_display_mode *adjusted_mode, -			      int x, int y, -			      struct drm_framebuffer *old_fb) -{ -	struct drm_device *dev = crtc->dev; -	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); -	struct drm_psb_private *dev_priv = dev->dev_private; -	int pipe = psb_intel_crtc->pipe; -	int fp_reg = MRST_FPA0; -	int dpll_reg = MRST_DPLL_A; -	int dspcntr_reg = DSPACNTR; -	int pipeconf_reg = PIPEACONF; -	int htot_reg = HTOTAL_A; -	int hblank_reg = HBLANK_A; -	int hsync_reg = HSYNC_A; -	int vtot_reg = VTOTAL_A; -	int vblank_reg = VBLANK_A; -	int vsync_reg = VSYNC_A; -	int dspsize_reg = DSPASIZE;  -	int dsppos_reg = DSPAPOS;  -	int pipesrc_reg = PIPEASRC; -	u32 *pipeconf = &dev_priv->pipeconf; -	u32 *dspcntr = &dev_priv->dspcntr; -	int refclk = 0; -	int clk_n = 0, clk_p2 = 0, clk_byte = 1, clk = 0, m_conv = 0, clk_tmp = 0; -	struct mdfld_intel_clock_t clock; -	bool ok; -	u32 dpll = 0, fp = 0; -	bool is_crt = false, is_lvds = false, is_tv = false; -	bool is_mipi = false, is_mipi2 = false, is_hdmi = false; -	struct drm_mode_config *mode_config = &dev->mode_config; -	struct psb_intel_output *psb_intel_output = NULL; -	uint64_t scalingType = DRM_MODE_SCALE_FULLSCREEN; -	struct drm_encoder *encoder; -	struct drm_connector *connector; -	int timeout = 0; - -	dev_dbg(dev->dev, "pipe = 0x%x \n", pipe); - -	switch (pipe) { -	case 0: -		break; -	case 1: -		fp_reg = FPB0; -		dpll_reg = DPLL_B; -		dspcntr_reg = DSPBCNTR; -		pipeconf_reg = PIPEBCONF; -		htot_reg = HTOTAL_B; -		hblank_reg = HBLANK_B; -		hsync_reg = HSYNC_B; -		vtot_reg = VTOTAL_B; -		vblank_reg = VBLANK_B; -		vsync_reg = VSYNC_B; -		dspsize_reg = DSPBSIZE;  -		dsppos_reg = DSPBPOS;  -		pipesrc_reg = PIPEBSRC; -		pipeconf = &dev_priv->pipeconf1; -		dspcntr = &dev_priv->dspcntr1; -		fp_reg = MDFLD_DPLL_DIV0; -		dpll_reg = MDFLD_DPLL_B; -		break; -	case 2: -		dpll_reg = MRST_DPLL_A; -		dspcntr_reg = DSPCCNTR; -		pipeconf_reg = PIPECCONF; -		htot_reg = HTOTAL_C; -		hblank_reg = HBLANK_C; -		hsync_reg = HSYNC_C; -		vtot_reg = VTOTAL_C; -		vblank_reg = VBLANK_C; -		vsync_reg = VSYNC_C; -		dspsize_reg = DSPCSIZE;  -		dsppos_reg = DSPCPOS;  -		pipesrc_reg = PIPECSRC; -		pipeconf = &dev_priv->pipeconf2; -		dspcntr = &dev_priv->dspcntr2; -		break; -	default: -		DRM_ERROR("Illegal Pipe Number. \n"); -		return 0; -	} - -	dev_dbg(dev->dev, "adjusted_hdisplay = %d\n", -		 adjusted_mode->hdisplay); -	dev_dbg(dev->dev, "adjusted_vdisplay = %d\n", -		 adjusted_mode->vdisplay); -	dev_dbg(dev->dev, "adjusted_hsync_start = %d\n", -		 adjusted_mode->hsync_start); -	dev_dbg(dev->dev, "adjusted_hsync_end = %d\n", -		 adjusted_mode->hsync_end); -	dev_dbg(dev->dev, "adjusted_htotal = %d\n", -		 adjusted_mode->htotal); -	dev_dbg(dev->dev, "adjusted_vsync_start = %d\n", -		 adjusted_mode->vsync_start); -	dev_dbg(dev->dev, "adjusted_vsync_end = %d\n", -		 adjusted_mode->vsync_end); -	dev_dbg(dev->dev, "adjusted_vtotal = %d\n", -		 adjusted_mode->vtotal); -	dev_dbg(dev->dev, "adjusted_clock = %d\n", -		 adjusted_mode->clock); -	dev_dbg(dev->dev, "hdisplay = %d\n", -		 mode->hdisplay); -	dev_dbg(dev->dev, "vdisplay = %d\n", -		 mode->vdisplay); - -	if (!gma_power_begin(dev, true)) -		return 0; - -	memcpy(&psb_intel_crtc->saved_mode, mode, sizeof(struct drm_display_mode)); -	memcpy(&psb_intel_crtc->saved_adjusted_mode, adjusted_mode, sizeof(struct drm_display_mode)); - -	list_for_each_entry(connector, &mode_config->connector_list, head) { -			 -		encoder = connector->encoder; -		 -		if(!encoder) -			continue; - -		if (encoder->crtc != crtc) -			continue; - -		psb_intel_output = to_psb_intel_output(connector); -		 -		dev_dbg(dev->dev, "output->type = 0x%x \n", psb_intel_output->type); - -		switch (psb_intel_output->type) { -		case INTEL_OUTPUT_LVDS: -			is_lvds = true; -			break; -		case INTEL_OUTPUT_TVOUT: -			is_tv = true; -			break; -		case INTEL_OUTPUT_ANALOG: -			is_crt = true; -			break; -		case INTEL_OUTPUT_MIPI: -			is_mipi = true; -			break; -		case INTEL_OUTPUT_MIPI2: -			is_mipi2 = true; -			break; -		case INTEL_OUTPUT_HDMI: -			is_hdmi = true; -			break; -		} -	} - -	/* Disable the VGA plane that we never use */ -	REG_WRITE(VGACNTRL, VGA_DISP_DISABLE); - -	/* Disable the panel fitter if it was on our pipe */ -	if (mdfld_panel_fitter_pipe(dev) == pipe) -		REG_WRITE(PFIT_CONTROL, 0); - -	/* pipesrc and dspsize control the size that is scaled from, -	 * which should always be the user's requested size. -	 */ -	if (pipe == 1) { -		/* FIXME: To make HDMI display with 864x480 (TPO), 480x864 (PYR) or 480x854 (TMD), set the sprite -		 * width/height and souce image size registers with the adjusted mode for pipe B. */ - -		/* The defined sprite rectangle must always be completely contained within the displayable -		 * area of the screen image (frame buffer). */ -		REG_WRITE(dspsize_reg, ((MIN(mode->crtc_vdisplay, adjusted_mode->crtc_vdisplay) - 1) << 16) -				| (MIN(mode->crtc_hdisplay, adjusted_mode->crtc_hdisplay) - 1)); -		/* Set the CRTC with encoder mode. */ -		REG_WRITE(pipesrc_reg, ((mode->crtc_hdisplay - 1) << 16) -				 | (mode->crtc_vdisplay - 1)); -	} else { -		REG_WRITE(dspsize_reg, ((mode->crtc_vdisplay - 1) << 16) | (mode->crtc_hdisplay - 1)); -		REG_WRITE(pipesrc_reg, ((mode->crtc_hdisplay - 1) << 16) | (mode->crtc_vdisplay - 1)); -	} - -	REG_WRITE(dsppos_reg, 0); - -	if (psb_intel_output) -		drm_connector_property_get_value(&psb_intel_output->base, -			dev->mode_config.scaling_mode_property, &scalingType); - -	if (scalingType == DRM_MODE_SCALE_NO_SCALE) { -		/* -		 *	Medfield doesn't have register support for centering so -		 *	we need to mess with the h/vblank and h/vsync start and -		 *	ends to get central -		 */ -		int offsetX = 0, offsetY = 0; - -		offsetX = (adjusted_mode->crtc_hdisplay - mode->crtc_hdisplay) / 2; -		offsetY = (adjusted_mode->crtc_vdisplay - mode->crtc_vdisplay) / 2; - -		REG_WRITE(htot_reg, (mode->crtc_hdisplay - 1) | -			((adjusted_mode->crtc_htotal - 1) << 16)); -		REG_WRITE(vtot_reg, (mode->crtc_vdisplay - 1) | -			((adjusted_mode->crtc_vtotal - 1) << 16)); -		REG_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - offsetX - 1) | -			((adjusted_mode->crtc_hblank_end - offsetX - 1) << 16)); -		REG_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - offsetX - 1) | -			((adjusted_mode->crtc_hsync_end - offsetX - 1) << 16)); -		REG_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - offsetY - 1) | -			((adjusted_mode->crtc_vblank_end - offsetY - 1) << 16)); -		REG_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - offsetY - 1) | -			((adjusted_mode->crtc_vsync_end - offsetY - 1) << 16)); -	} else { -		REG_WRITE(htot_reg, (adjusted_mode->crtc_hdisplay - 1) | -			((adjusted_mode->crtc_htotal - 1) << 16)); -		REG_WRITE(vtot_reg, (adjusted_mode->crtc_vdisplay - 1) | -			((adjusted_mode->crtc_vtotal - 1) << 16)); -		REG_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) | -			((adjusted_mode->crtc_hblank_end - 1) << 16)); -		REG_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - 1) | -			((adjusted_mode->crtc_hsync_end - 1) << 16)); -		REG_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - 1) | -			((adjusted_mode->crtc_vblank_end - 1) << 16)); -		REG_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - 1) | -			((adjusted_mode->crtc_vsync_end - 1) << 16)); -	} - -	/* Flush the plane changes */ -	{ -		struct drm_crtc_helper_funcs *crtc_funcs = -		    crtc->helper_private; -		crtc_funcs->mode_set_base(crtc, x, y, old_fb); -	} - -	/* setup pipeconf */ -	*pipeconf = PIPEACONF_ENABLE; /* FIXME_JLIU7 REG_READ(pipeconf_reg); */ - -	/* Set up the display plane register */ - 	*dspcntr = REG_READ(dspcntr_reg); -	*dspcntr |= pipe << DISPPLANE_SEL_PIPE_POS; -	*dspcntr |= DISPLAY_PLANE_ENABLE; -/* MDFLD_PO_JLIU7	dspcntr |= DISPPLANE_BOTTOM; */ -/* MDFLD_PO_JLIU7	dspcntr |= DISPPLANE_GAMMA_ENABLE; */ - -	if (is_mipi2) -	{ -		goto mrst_crtc_mode_set_exit; -	} -/* FIXME JLIU7 Add MDFLD HDMI supports */ -/* FIXME_MDFLD JLIU7 DSIPLL clock *= 8? */ -/* FIXME_MDFLD JLIU7 need to revist for dual MIPI supports */ -	clk = adjusted_mode->clock; - -	if (is_hdmi) { -		if ((ksel == KSEL_CRYSTAL_19) || (ksel == KSEL_BYPASS_19)) -		{ -			refclk = 19200; - -			if (is_mipi || is_mipi2) -			{ -				clk_n = 1, clk_p2 = 8; -			} else if (is_hdmi) { -				clk_n = 1, clk_p2 = 10; -			} -		} else if (ksel == KSEL_BYPASS_25) {  -			refclk = 25000; - -			if (is_mipi || is_mipi2) -			{ -				clk_n = 1, clk_p2 = 8; -			} else if (is_hdmi) { -				clk_n = 1, clk_p2 = 10; -			} -		} else if ((ksel == KSEL_BYPASS_83_100) && (dev_priv->core_freq == 166)) { -			refclk = 83000; - -			if (is_mipi || is_mipi2) -			{ -				clk_n = 4, clk_p2 = 8; -			} else if (is_hdmi) { -				clk_n = 4, clk_p2 = 10; -			} -		} else if ((ksel == KSEL_BYPASS_83_100) && -			   (dev_priv->core_freq == 100 || dev_priv->core_freq == 200)) { -			refclk = 100000; -			if (is_mipi || is_mipi2) -			{ -				clk_n = 4, clk_p2 = 8; -			} else if (is_hdmi) { -				clk_n = 4, clk_p2 = 10; -			} -		} - -		if (is_mipi) -			clk_byte = dev_priv->bpp / 8; -		else if (is_mipi2) -			clk_byte = dev_priv->bpp2 / 8; -	 -		clk_tmp = clk * clk_n * clk_p2 * clk_byte; - -		dev_dbg(dev->dev, "clk = %d, clk_n = %d, clk_p2 = %d. \n", clk, clk_n, clk_p2); -		dev_dbg(dev->dev, "adjusted_mode->clock = %d, clk_tmp = %d. \n", adjusted_mode->clock, clk_tmp); - -		ok = mdfldFindBestPLL(crtc, clk_tmp, refclk, &clock); - -		if (!ok) { -			dev_err(dev->dev,  -			   "mdfldFindBestPLL fail in mdfld_crtc_mode_set. \n"); -		} else { -			m_conv = mdfld_m_converts[(clock.m - MDFLD_M_MIN)]; - -			dev_dbg(dev->dev, "dot clock = %d," -				 "m = %d, p1 = %d, m_conv = %d. \n", clock.dot, clock.m, -				 clock.p1, m_conv); -		} - -		dpll = REG_READ(dpll_reg); - -		if (dpll & DPLL_VCO_ENABLE) { -			dpll &= ~DPLL_VCO_ENABLE; -			REG_WRITE(dpll_reg, dpll); -			REG_READ(dpll_reg); - -			/* FIXME jliu7 check the DPLL lock bit PIPEACONF[29] */ -			/* FIXME_MDFLD PO - change 500 to 1 after PO */ -			udelay(500); - -			/* reset M1, N1 & P1 */ -			REG_WRITE(fp_reg, 0); -			dpll &= ~MDFLD_P1_MASK; -			REG_WRITE(dpll_reg, dpll); -			/* FIXME_MDFLD PO - change 500 to 1 after PO */ -			udelay(500); -		} - -		/* When ungating power of DPLL, needs to wait 0.5us before enable the VCO */ -		if (dpll & MDFLD_PWR_GATE_EN) { -			dpll &= ~MDFLD_PWR_GATE_EN; -			REG_WRITE(dpll_reg, dpll); -			/* FIXME_MDFLD PO - change 500 to 1 after PO */ -			udelay(500); -		}	 - -		dpll = 0;  - -#if 0 /* FIXME revisit later */ -		if ((ksel == KSEL_CRYSTAL_19) || (ksel == KSEL_BYPASS_19) || (ksel == KSEL_BYPASS_25)) { -			dpll &= ~MDFLD_INPUT_REF_SEL;	 -		} else if (ksel == KSEL_BYPASS_83_100) {  -			dpll |= MDFLD_INPUT_REF_SEL;	 -		} -#endif /* FIXME revisit later */ - -		if (is_hdmi) -			dpll |= MDFLD_VCO_SEL;	 - -		fp = (clk_n / 2) << 16; -		fp |= m_conv;  - -		/* compute bitmask from p1 value */ -		dpll |= (1 << (clock.p1 - 2)) << 17; - -#if 0 /* 1080p30 & 720p */ -        	dpll = 0x00050000; -        	fp = 0x000001be; -#endif  -#if 0 /* 480p */ -        	dpll = 0x02010000; -        	fp = 0x000000d2; -#endif  -	} else { -#if 0 /*DBI_TPO_480x864*/ -		dpll = 0x00020000; -		fp = 0x00000156;  -#endif /* DBI_TPO_480x864 */ /* get from spec. */ - -        	dpll = 0x00800000; -	        fp = 0x000000c1; -} - -	REG_WRITE(fp_reg, fp); -	REG_WRITE(dpll_reg, dpll); -	/* FIXME_MDFLD PO - change 500 to 1 after PO */ -	udelay(500); - -	dpll |= DPLL_VCO_ENABLE; -	REG_WRITE(dpll_reg, dpll); -	REG_READ(dpll_reg); - -	/* wait for DSI PLL to lock */ -	while ((timeout < 20000) && !(REG_READ(pipeconf_reg) & PIPECONF_DSIPLL_LOCK)) { -		udelay(150); -		timeout ++; -	} - -	if (is_mipi) -		goto mrst_crtc_mode_set_exit; - -	dev_dbg(dev->dev, "is_mipi = 0x%x \n", is_mipi); - -	REG_WRITE(pipeconf_reg, *pipeconf); -	REG_READ(pipeconf_reg); - -	/* Wait for for the pipe enable to take effect. */ -//FIXME_JLIU7 HDMI	mrstWaitForPipeEnable(dev); - -	REG_WRITE(dspcntr_reg, *dspcntr); -	psb_intel_wait_for_vblank(dev); - -mrst_crtc_mode_set_exit: - -	gma_power_end(dev); - -	return 0; -} - -static void mdfld_crtc_prepare(struct drm_crtc *crtc) -{ -	struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; -	crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF); -} - -static void mdfld_crtc_commit(struct drm_crtc *crtc) -{ -	struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; -	crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON); -} - -static bool mdfld_crtc_mode_fixup(struct drm_crtc *crtc, -				  struct drm_display_mode *mode, -				  struct drm_display_mode *adjusted_mode) -{ -	return true; -} - -const struct drm_crtc_helper_funcs mdfld_helper_funcs = { -	.dpms = mdfld_crtc_dpms, -	.mode_fixup = mdfld_crtc_mode_fixup, -	.mode_set = mdfld_crtc_mode_set, -	.mode_set_base = mdfld__intel_pipe_set_base, -	.prepare = mdfld_crtc_prepare, -	.commit = mdfld_crtc_commit, -}; diff --git a/drivers/staging/gma500/mdfld_msic.h b/drivers/staging/gma500/mdfld_msic.h deleted file mode 100644 index a7ad6547249..00000000000 --- a/drivers/staging/gma500/mdfld_msic.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright © 2010 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Authors: - *	Jim Liu <jim.liu@intel.com> - */ - -#define MSIC_PCI_DEVICE_ID	0x831 - -int msic_regsiter_driver(void); -int msic_unregister_driver(void); -extern void hpd_notify_um(void); diff --git a/drivers/staging/gma500/mdfld_output.c b/drivers/staging/gma500/mdfld_output.c deleted file mode 100644 index eabf53d58f9..00000000000 --- a/drivers/staging/gma500/mdfld_output.c +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (c)  2010 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicensen - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Authors: - * Thomas Eaton <thomas.g.eaton@intel.com> - * Scott Rowe <scott.m.rowe@intel.com> -*/ - -#include <linux/init.h> -#include <linux/moduleparam.h> -#include "mdfld_dsi_dbi.h" -#include "mdfld_dsi_dpi.h" -#include "mdfld_dsi_output.h" -#include "mdfld_output.h" -#include "mdfld_dsi_dbi_dpu.h" - -#include "displays/tpo_cmd.h" -#include "displays/tpo_vid.h" -#include "displays/tmd_cmd.h" -#include "displays/tmd_vid.h" -#include "displays/pyr_cmd.h" -#include "displays/pyr_vid.h" -/* #include "displays/hdmi.h" */ - -static int mdfld_dual_mipi; -static int mdfld_hdmi; -static int mdfld_dpu; - -module_param(mdfld_dual_mipi, int, 0600); -MODULE_PARM_DESC(mdfld_dual_mipi, "Enable dual MIPI configuration"); -module_param(mdfld_hdmi, int, 0600); -MODULE_PARM_DESC(mdfld_hdmi, "Enable Medfield HDMI"); -module_param(mdfld_dpu, int, 0600); -MODULE_PARM_DESC(mdfld_dpu, "Enable Medfield DPU"); - -/* For now a single type per device is all we cope with */ -int mdfld_get_panel_type(struct drm_device *dev, int pipe) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; -	return dev_priv->panel_id; -} - -int mdfld_panel_dpi(struct drm_device *dev) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; - -	switch (dev_priv->panel_id) { -	case TMD_VID: -	case TPO_VID: -	case PYR_VID: -		return true; -	case TMD_CMD: -	case TPO_CMD: -	case PYR_CMD: -	default: -		return false; -	} -} - -static int init_panel(struct drm_device *dev, int mipi_pipe, int p_type) -{ -	struct panel_funcs *p_cmd_funcs; -	struct panel_funcs *p_vid_funcs; - -	/* Oh boy ... FIXME */ -	p_cmd_funcs = kzalloc(sizeof(struct panel_funcs), GFP_KERNEL); -	if (p_cmd_funcs == NULL) -		return -ENODEV; -	p_vid_funcs = kzalloc(sizeof(struct panel_funcs), GFP_KERNEL); -	if (p_vid_funcs == NULL) { -		kfree(p_cmd_funcs); -		return -ENODEV; -	} - -	switch (p_type) { -	case TPO_CMD: -		tpo_cmd_init(dev, p_cmd_funcs); -		mdfld_dsi_output_init(dev, mipi_pipe, NULL, p_cmd_funcs, NULL); -		break; -	case TPO_VID: -		tpo_vid_init(dev, p_vid_funcs); -		mdfld_dsi_output_init(dev, mipi_pipe, NULL, NULL, p_vid_funcs); -		break; -	case TMD_CMD: -		/*tmd_cmd_init(dev, p_cmd_funcs); */ -		mdfld_dsi_output_init(dev, mipi_pipe, NULL, p_cmd_funcs, NULL); -		break; -	case TMD_VID: -		tmd_vid_init(dev, p_vid_funcs); -		mdfld_dsi_output_init(dev, mipi_pipe, NULL, NULL, p_vid_funcs); -		break; -	case PYR_CMD: -		pyr_cmd_init(dev, p_cmd_funcs); -		mdfld_dsi_output_init(dev, mipi_pipe, NULL, p_cmd_funcs, NULL); -		break; -	case PYR_VID: -		mdfld_dsi_output_init(dev, mipi_pipe, NULL, NULL, p_vid_funcs); -		break; -	case TPO:	/* TPO panel supports both cmd & vid interfaces */ -		tpo_cmd_init(dev, p_cmd_funcs); -		tpo_vid_init(dev, p_vid_funcs); -		mdfld_dsi_output_init(dev, mipi_pipe, NULL, p_cmd_funcs, -				      p_vid_funcs); -		break; -	case TMD: -		break; -	case PYR: -		break; -#if 0 -	case HDMI: -		dev_dbg(dev->dev, "Initializing HDMI"); -		mdfld_hdmi_init(dev, &dev_priv->mode_dev); -		break; -#endif -	default: -		dev_err(dev->dev, "Unsupported interface %d", p_type); -		return -ENODEV; -	} -	return 0; -} - -int mdfld_output_init(struct drm_device *dev) -{ -	int type; - -	/* MIPI panel 1 */ -	type = mdfld_get_panel_type(dev, 0); -	dev_info(dev->dev, "panel 1: type is %d\n", type); -	init_panel(dev, 0, type); - -	if (mdfld_dual_mipi) { -		/* MIPI panel 2 */ -		type = mdfld_get_panel_type(dev, 2); -		dev_info(dev->dev, "panel 2: type is %d\n", type); -		init_panel(dev, 2, type); -	} -	if (mdfld_hdmi) -		/* HDMI panel */ -		init_panel(dev, 0, HDMI); -	return 0; -} - -void mdfld_output_setup(struct drm_device *dev) -{ -	/* FIXME: this is not the right place for this stuff ! */ -	if (IS_MFLD(dev)) { -		if (mdfld_dpu) -			mdfld_dbi_dpu_init(dev); -		else -			mdfld_dbi_dsr_init(dev); -	} -} diff --git a/drivers/staging/gma500/mdfld_output.h b/drivers/staging/gma500/mdfld_output.h deleted file mode 100644 index daf33e7df9d..00000000000 --- a/drivers/staging/gma500/mdfld_output.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c)  2010 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicensen - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Authors: - * Thomas Eaton <thomas.g.eaton@intel.com> - * Scott Rowe <scott.m.rowe@intel.com> -*/ - -#ifndef MDFLD_OUTPUT_H -#define MDFLD_OUTPUT_H - -int mdfld_output_init(struct drm_device *dev); -int mdfld_panel_dpi(struct drm_device *dev); -int mdfld_get_panel_type(struct drm_device *dev, int pipe); -void mdfld_disable_crtc (struct drm_device *dev, int pipe); - -extern const struct drm_crtc_helper_funcs mdfld_helper_funcs; -extern const struct drm_crtc_funcs mdfld_intel_crtc_funcs; - -extern void mdfld_output_setup(struct drm_device *dev); - -#endif diff --git a/drivers/staging/gma500/mdfld_pyr_cmd.c b/drivers/staging/gma500/mdfld_pyr_cmd.c deleted file mode 100644 index 523f2d8fe4f..00000000000 --- a/drivers/staging/gma500/mdfld_pyr_cmd.c +++ /dev/null @@ -1,558 +0,0 @@ -/* - * Copyright (c)  2010 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicensen - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Authors: - * Thomas Eaton <thomas.g.eaton@intel.com> - * Scott Rowe <scott.m.rowe@intel.com> -*/ - -#include "mdfld_dsi_dbi.h" -#include "mdfld_dsi_dpi.h" -#include "mdfld_dsi_output.h" -#include "mdfld_output.h" -#include "mdfld_dsi_dbi_dpu.h" -#include "mdfld_dsi_pkg_sender.h" - -#include "displays/pyr_cmd.h" - -static struct drm_display_mode *pyr_cmd_get_config_mode(struct drm_device *dev) -{ -	struct drm_display_mode *mode; - -	mode = kzalloc(sizeof(*mode), GFP_KERNEL); -	if (!mode) { -		dev_err(dev->dev, "Out of memory\n"); -		return NULL; -	} - -	dev_dbg(dev->dev, "hdisplay is %d\n", mode->hdisplay); -	dev_dbg(dev->dev, "vdisplay is %d\n", mode->vdisplay); -	dev_dbg(dev->dev, "HSS is %d\n", mode->hsync_start); -	dev_dbg(dev->dev, "HSE is %d\n", mode->hsync_end); -	dev_dbg(dev->dev, "htotal is %d\n", mode->htotal); -	dev_dbg(dev->dev, "VSS is %d\n", mode->vsync_start); -	dev_dbg(dev->dev, "VSE is %d\n", mode->vsync_end); -	dev_dbg(dev->dev, "vtotal is %d\n", mode->vtotal); -	dev_dbg(dev->dev, "clock is %d\n", mode->clock); - -	mode->hdisplay = 480; -	mode->vdisplay = 864; -	mode->hsync_start = 487; -	mode->hsync_end = 490; -	mode->htotal = 499; -	mode->vsync_start = 874; -	mode->vsync_end = 878; -	mode->vtotal = 886; -	mode->clock = 25777; - -	drm_mode_set_name(mode); -	drm_mode_set_crtcinfo(mode, 0); - -	mode->type |= DRM_MODE_TYPE_PREFERRED; - -	return mode; -} - -static bool pyr_dsi_dbi_mode_fixup(struct drm_encoder *encoder, -				struct drm_display_mode *mode, -				struct drm_display_mode *adjusted_mode) -{ -	struct drm_device *dev = encoder->dev; -	struct drm_display_mode *fixed_mode = pyr_cmd_get_config_mode(dev); - -	if (fixed_mode) { -		adjusted_mode->hdisplay = fixed_mode->hdisplay; -		adjusted_mode->hsync_start = fixed_mode->hsync_start; -		adjusted_mode->hsync_end = fixed_mode->hsync_end; -		adjusted_mode->htotal = fixed_mode->htotal; -		adjusted_mode->vdisplay = fixed_mode->vdisplay; -		adjusted_mode->vsync_start = fixed_mode->vsync_start; -		adjusted_mode->vsync_end = fixed_mode->vsync_end; -		adjusted_mode->vtotal = fixed_mode->vtotal; -		adjusted_mode->clock = fixed_mode->clock; -		drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V); -		kfree(fixed_mode); -	} -	return true; -} - -static void pyr_dsi_dbi_set_power(struct drm_encoder *encoder, bool on) -{ -	int ret = 0; -	struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder); -	struct mdfld_dsi_dbi_output *dbi_output = -				MDFLD_DSI_DBI_OUTPUT(dsi_encoder); -	struct drm_device *dev = encoder->dev; -	struct drm_psb_private *dev_priv = dev->dev_private; -	u32 reg_offset = 0; -	int pipe = (dbi_output->channel_num == 0) ? 0 : 2; - -	dev_dbg(dev->dev, "pipe %d : %s, panel on: %s\n", pipe, -			on ? "On" : "Off", -			dbi_output->dbi_panel_on ? "True" : "False"); - -	if (pipe == 2) { -		if (on) -			dev_priv->dual_mipi = true; -		else -			dev_priv->dual_mipi = false; - -		reg_offset = MIPIC_REG_OFFSET; -	} else { -		if (!on) -			dev_priv->dual_mipi = false; -	} - -	if (!gma_power_begin(dev, true)) { -		dev_err(dev->dev, "hw begin failed\n"); -		return; -	} - - -	if (on) { -		if (dbi_output->dbi_panel_on) -			goto out_err; - -		ret = mdfld_dsi_dbi_update_power(dbi_output, DRM_MODE_DPMS_ON); -		if (ret) { -			dev_err(dev->dev, "power on error\n"); -			goto out_err; -		} - -		dbi_output->dbi_panel_on = true; - -		if (pipe == 2) { -			dev_priv->dbi_panel_on2 = true; -		} else { -			dev_priv->dbi_panel_on = true; -			mdfld_enable_te(dev, 0); -		} -	} else { -		if (!dbi_output->dbi_panel_on && !dbi_output->first_boot) -			goto out_err; - -		dbi_output->dbi_panel_on = false; -		dbi_output->first_boot = false; - -		if (pipe == 2) { -			dev_priv->dbi_panel_on2 = false; -			mdfld_disable_te(dev, 2); -		} else { -			dev_priv->dbi_panel_on = false; -			mdfld_disable_te(dev, 0); - -			if (dev_priv->dbi_panel_on2) -				mdfld_enable_te(dev, 2); -		} - -		ret = mdfld_dsi_dbi_update_power(dbi_output, DRM_MODE_DPMS_OFF); -		if (ret) { -			dev_err(dev->dev, "power on error\n"); -			goto out_err; -		} -	} - -out_err: -	gma_power_end(dev); - -	if (ret) -		dev_err(dev->dev, "failed\n"); -} - -static void pyr_dsi_controller_dbi_init(struct mdfld_dsi_config *dsi_config, -								int pipe) -{ -	struct drm_device *dev = dsi_config->dev; -	u32 reg_offset = pipe ? MIPIC_REG_OFFSET : 0; -	int lane_count = dsi_config->lane_count; -	u32 val = 0; - -	dev_dbg(dev->dev, "Init DBI interface on pipe %d...\n", pipe); - -	/* Un-ready device */ -	REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000000); - -	/* Init dsi adapter before kicking off */ -	REG_WRITE((MIPIA_CONTROL_REG + reg_offset), 0x00000018); - -	/* TODO: figure out how to setup these registers */ -	REG_WRITE((MIPIA_DPHY_PARAM_REG + reg_offset), 0x150c600F); -	REG_WRITE((MIPIA_CLK_LANE_SWITCH_TIME_CNT_REG + reg_offset), -								0x000a0014); -	REG_WRITE((MIPIA_DBI_BW_CTRL_REG + reg_offset), 0x00000400); -	REG_WRITE((MIPIA_HS_LS_DBI_ENABLE_REG + reg_offset), 0x00000000); - -	/* Enable all interrupts */ -	REG_WRITE((MIPIA_INTR_EN_REG + reg_offset), 0xffffffff); -	/* Max value: 20 clock cycles of txclkesc */ -	REG_WRITE((MIPIA_TURN_AROUND_TIMEOUT_REG + reg_offset), 0x0000001f); -	/* Min 21 txclkesc, max: ffffh */ -	REG_WRITE((MIPIA_DEVICE_RESET_TIMER_REG + reg_offset), 0x0000ffff); -	/* Min: 7d0 max: 4e20 */ -	REG_WRITE((MIPIA_INIT_COUNT_REG + reg_offset), 0x00000fa0); - -	/* Set up func_prg */ -	val |= lane_count; -	val |= (dsi_config->channel_num << DSI_DBI_VIRT_CHANNEL_OFFSET); -	val |= DSI_DBI_COLOR_FORMAT_OPTION2; -	REG_WRITE((MIPIA_DSI_FUNC_PRG_REG + reg_offset), val); - -	REG_WRITE((MIPIA_HS_TX_TIMEOUT_REG + reg_offset), 0x3fffff); -	REG_WRITE((MIPIA_LP_RX_TIMEOUT_REG + reg_offset), 0xffff); - -	/* De-assert dbi_stall when half of DBI FIFO is empty */ -	/* REG_WRITE((MIPIA_DBI_FIFO_THROTTLE_REG + reg_offset), 0x00000000); */ - -	REG_WRITE((MIPIA_HIGH_LOW_SWITCH_COUNT_REG + reg_offset), 0x46); -	REG_WRITE((MIPIA_EOT_DISABLE_REG + reg_offset), 0x00000002); -	REG_WRITE((MIPIA_LP_BYTECLK_REG + reg_offset), 0x00000004); -	REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000001); -} - -static void pyr_dsi_dbi_mode_set(struct drm_encoder *encoder, -				struct drm_display_mode *mode, -				struct drm_display_mode *adjusted_mode) -{ -	int ret = 0; -	struct drm_device *dev = encoder->dev; -	struct drm_psb_private *dev_priv = dev->dev_private; -	struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder); -	struct mdfld_dsi_dbi_output *dsi_output = -					MDFLD_DSI_DBI_OUTPUT(dsi_encoder); -	struct mdfld_dsi_config *dsi_config = -				mdfld_dsi_encoder_get_config(dsi_encoder); -	struct mdfld_dsi_connector *dsi_connector = dsi_config->connector; -	int pipe = dsi_connector->pipe; -	u8 param = 0; - -	/* Regs */ -	u32 mipi_reg = MIPI; -	u32 dspcntr_reg = DSPACNTR; -	u32 pipeconf_reg = PIPEACONF; -	u32 reg_offset = 0; - -	/* Values */ -	u32 dspcntr_val = dev_priv->dspcntr; -	u32 pipeconf_val = dev_priv->pipeconf; -	u32 h_active_area = mode->hdisplay; -	u32 v_active_area = mode->vdisplay; -	u32 mipi_val = (PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX | -							TE_TRIGGER_GPIO_PIN); - -	dev_dbg(dev->dev, "mipi_val =0x%x\n", mipi_val); - -	dev_dbg(dev->dev, "type %s\n", (pipe == 2) ? "MIPI2" : "MIPI"); -	dev_dbg(dev->dev, "h %d v %d\n", mode->hdisplay, mode->vdisplay); - -	if (pipe == 2) { -		mipi_reg = MIPI_C; -		dspcntr_reg = DSPCCNTR; -		pipeconf_reg = PIPECCONF; - -		reg_offset = MIPIC_REG_OFFSET; - -		dspcntr_val = dev_priv->dspcntr2; -		pipeconf_val = dev_priv->pipeconf2; -	} else { -		mipi_val |= 0x2; /* Two lanes for port A and C respectively */ -	} - -	if (!gma_power_begin(dev, true)) { -		dev_err(dev->dev, "hw begin failed\n"); -		return; -	} - -	/* Set up pipe related registers */ -	REG_WRITE(mipi_reg, mipi_val); -	REG_READ(mipi_reg); - -	pyr_dsi_controller_dbi_init(dsi_config, pipe); - -	msleep(20); - -	REG_WRITE(dspcntr_reg, dspcntr_val); -	REG_READ(dspcntr_reg); - -	/* 20ms delay before sending exit_sleep_mode */ -	msleep(20); - -	/* Send exit_sleep_mode DCS */ -	ret = mdfld_dsi_dbi_send_dcs(dsi_output, exit_sleep_mode, NULL, -						0, CMD_DATA_SRC_SYSTEM_MEM); -	if (ret) { -		dev_err(dev->dev, "sent exit_sleep_mode faild\n"); -		goto out_err; -	} - -	/*send set_tear_on DCS*/ -	ret = mdfld_dsi_dbi_send_dcs(dsi_output, set_tear_on, -					¶m, 1, CMD_DATA_SRC_SYSTEM_MEM); -	if (ret) { -		dev_err(dev->dev, "%s - sent set_tear_on faild\n", __func__); -		goto out_err; -	} - -	/* Do some init stuff */ -	mdfld_dsi_brightness_init(dsi_config, pipe); -	mdfld_dsi_gen_fifo_ready(dev, (MIPIA_GEN_FIFO_STAT_REG + reg_offset), -				HS_CTRL_FIFO_EMPTY | HS_DATA_FIFO_EMPTY); - -	REG_WRITE(pipeconf_reg, pipeconf_val | PIPEACONF_DSR); -	REG_READ(pipeconf_reg); - -	/* TODO: this looks ugly, try to move it to CRTC mode setting */ -	if (pipe == 2) -		dev_priv->pipeconf2 |= PIPEACONF_DSR; -	else -		dev_priv->pipeconf |= PIPEACONF_DSR; - -	dev_dbg(dev->dev, "pipeconf %x\n",  REG_READ(pipeconf_reg)); - -	ret = mdfld_dsi_dbi_update_area(dsi_output, 0, 0, -				h_active_area - 1, v_active_area - 1); -	if (ret) { -		dev_err(dev->dev, "update area failed\n"); -		goto out_err; -	} - -out_err: -	gma_power_end(dev); - -	if (ret) -		dev_err(dev->dev, "mode set failed\n"); -	else -		dev_dbg(dev->dev, "mode set done successfully\n"); -} - -static void pyr_dsi_dbi_prepare(struct drm_encoder *encoder) -{ -	struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder); -	struct mdfld_dsi_dbi_output *dbi_output = -					MDFLD_DSI_DBI_OUTPUT(dsi_encoder); - -	dbi_output->mode_flags |= MODE_SETTING_IN_ENCODER; -	dbi_output->mode_flags &= ~MODE_SETTING_ENCODER_DONE; - -	pyr_dsi_dbi_set_power(encoder, false); -} - -static void pyr_dsi_dbi_commit(struct drm_encoder *encoder) -{ -	struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder); -	struct mdfld_dsi_dbi_output *dbi_output = -					MDFLD_DSI_DBI_OUTPUT(dsi_encoder); -	struct drm_device *dev = dbi_output->dev; -	struct drm_psb_private *dev_priv = dev->dev_private; -	struct psb_drm_dpu_rect rect; - -	pyr_dsi_dbi_set_power(encoder, true); - -	dbi_output->mode_flags &= ~MODE_SETTING_IN_ENCODER; - -	rect.x = rect.y = 0; -	rect.width = 864; -	rect.height = 480; - -	if (dbi_output->channel_num == 1) { -		dev_priv->dsr_fb_update |= MDFLD_DSR_2D_3D_2; -		/* If DPU enabled report a fullscreen damage */ -		mdfld_dbi_dpu_report_damage(dev, MDFLD_PLANEC, &rect); -	} else { -		dev_priv->dsr_fb_update |= MDFLD_DSR_2D_3D_0; -		mdfld_dbi_dpu_report_damage(dev, MDFLD_PLANEA, &rect); -	} -	dbi_output->mode_flags |= MODE_SETTING_ENCODER_DONE; -} - -static void pyr_dsi_dbi_dpms(struct drm_encoder *encoder, int mode) -{ -	struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder); -	struct mdfld_dsi_dbi_output *dbi_output = -					MDFLD_DSI_DBI_OUTPUT(dsi_encoder); -	struct drm_device *dev = dbi_output->dev; - -	dev_dbg(dev->dev, "%s\n",  (mode == DRM_MODE_DPMS_ON ? "on" : "off")); - -	if (mode == DRM_MODE_DPMS_ON) -		pyr_dsi_dbi_set_power(encoder, true); -	else -		pyr_dsi_dbi_set_power(encoder, false); -} - -/* - * Update the DBI MIPI Panel Frame Buffer. - */ -static void pyr_dsi_dbi_update_fb(struct mdfld_dsi_dbi_output *dbi_output, -								int pipe) -{ -	struct mdfld_dsi_pkg_sender *sender = -		mdfld_dsi_encoder_get_pkg_sender(&dbi_output->base); -	struct drm_device *dev = dbi_output->dev; -	struct drm_crtc *crtc = dbi_output->base.base.crtc; -	struct psb_intel_crtc *psb_crtc = (crtc) ? -				to_psb_intel_crtc(crtc) : NULL; - -	u32 dpll_reg = MRST_DPLL_A; -	u32 dspcntr_reg = DSPACNTR; -	u32 pipeconf_reg = PIPEACONF; -	u32 dsplinoff_reg = DSPALINOFF; -	u32 dspsurf_reg = DSPASURF; -	u32 hs_gen_ctrl_reg = HS_GEN_CTRL_REG; -	u32 gen_fifo_stat_reg = GEN_FIFO_STAT_REG; -	u32 reg_offset = 0; - -	u32 intr_status; -	u32 fifo_stat_reg_val; -	u32 dpll_reg_val; -	u32 dspcntr_reg_val; -	u32 pipeconf_reg_val; - -	/* If mode setting on-going, back off */ -	if ((dbi_output->mode_flags & MODE_SETTING_ON_GOING) || -		(psb_crtc && psb_crtc->mode_flags & MODE_SETTING_ON_GOING) || -		!(dbi_output->mode_flags & MODE_SETTING_ENCODER_DONE)) -		return; - -	/* -	 * Look for errors here.  In particular we're checking for whatever -	 * error status might have appeared during the last frame transmit -	 * (memory write). -	 * -	 * Normally, the bits we're testing here would be set infrequently, -	 * if at all.  However, one panel (at least) returns at least one -	 * error bit on most frames.  So we've disabled the kernel message -	 * for now. -	 * -	 * Still clear whatever error bits are set, except don't clear the -	 * ones that would make the Penwell DSI controller reset if we -	 * cleared them. -	 */ -	intr_status = REG_READ(INTR_STAT_REG); -	if ((intr_status & 0x26FFFFFF) != 0) { -		/* dev_err(dev->dev, "DSI status: 0x%08X\n", intr_status); */ -		intr_status &= 0x26F3FFFF; -		REG_WRITE(INTR_STAT_REG, intr_status); -	} - -	if (pipe == 2) { -		dspcntr_reg = DSPCCNTR; -		pipeconf_reg = PIPECCONF; -		dsplinoff_reg = DSPCLINOFF; -		dspsurf_reg = DSPCSURF; - -		hs_gen_ctrl_reg = HS_GEN_CTRL_REG + MIPIC_REG_OFFSET; -		gen_fifo_stat_reg = GEN_FIFO_STAT_REG + MIPIC_REG_OFFSET, - -		reg_offset = MIPIC_REG_OFFSET; -	} - -	if (!gma_power_begin(dev, true)) { -		dev_err(dev->dev, "hw begin failed\n"); -		return; -	} - -	fifo_stat_reg_val = REG_READ(MIPIA_GEN_FIFO_STAT_REG + reg_offset); -	dpll_reg_val = REG_READ(dpll_reg); -	dspcntr_reg_val = REG_READ(dspcntr_reg); -	pipeconf_reg_val = REG_READ(pipeconf_reg); - -	if (!(fifo_stat_reg_val & (1 << 27)) || -		(dpll_reg_val & DPLL_VCO_ENABLE) || -		!(dspcntr_reg_val & DISPLAY_PLANE_ENABLE) || -		!(pipeconf_reg_val & DISPLAY_PLANE_ENABLE)) { -		goto update_fb_out0; -	} - -	/* Refresh plane changes */ -	REG_WRITE(dsplinoff_reg, REG_READ(dsplinoff_reg)); -	REG_WRITE(dspsurf_reg, REG_READ(dspsurf_reg)); -	REG_READ(dspsurf_reg); - -	mdfld_dsi_send_dcs(sender, -			   write_mem_start, -			   NULL, -			   0, -			   CMD_DATA_SRC_PIPE, -			   MDFLD_DSI_SEND_PACKAGE); - -	/* -	 * The idea here is to transmit a Generic Read command after the -	 * Write Memory Start/Continue commands finish.  This asks for -	 * the panel to return an "ACK No Errors," or (if it has errors -	 * to report) an Error Report.  This allows us to monitor the -	 * panel's perception of the health of the DSI. -	 */ -	mdfld_dsi_gen_fifo_ready(dev, gen_fifo_stat_reg, -				HS_CTRL_FIFO_EMPTY | HS_DATA_FIFO_EMPTY); -	REG_WRITE(hs_gen_ctrl_reg, (1 << WORD_COUNTS_POS) | GEN_READ_0); - -	dbi_output->dsr_fb_update_done = true; -update_fb_out0: -	gma_power_end(dev); -} - -/* - * TODO: will be removed later, should work out display interfaces for power - */ -void pyr_dsi_adapter_init(struct mdfld_dsi_config *dsi_config, int pipe) -{ -	if (!dsi_config || (pipe != 0 && pipe != 2)) { -		WARN_ON(1); -		return; -	} -	pyr_dsi_controller_dbi_init(dsi_config, pipe); -} - -static int pyr_cmd_get_panel_info(struct drm_device *dev, int pipe, -							struct panel_info *pi) -{ -	if (!dev || !pi) -		return -EINVAL; - -	pi->width_mm = PYR_PANEL_WIDTH; -	pi->height_mm = PYR_PANEL_HEIGHT; - -	return 0; -} - -/* PYR DBI encoder helper funcs */ -static const struct drm_encoder_helper_funcs pyr_dsi_dbi_helper_funcs = { -	.dpms = pyr_dsi_dbi_dpms, -	.mode_fixup = pyr_dsi_dbi_mode_fixup, -	.prepare = pyr_dsi_dbi_prepare, -	.mode_set = pyr_dsi_dbi_mode_set, -	.commit = pyr_dsi_dbi_commit, -}; - -/* PYR DBI encoder funcs */ -static const struct drm_encoder_funcs mdfld_dsi_dbi_encoder_funcs = { -	.destroy = drm_encoder_cleanup, -}; - -void pyr_cmd_init(struct drm_device *dev, struct panel_funcs *p_funcs) -{ -	p_funcs->encoder_funcs = &mdfld_dsi_dbi_encoder_funcs; -	p_funcs->encoder_helper_funcs = &pyr_dsi_dbi_helper_funcs; -	p_funcs->get_config_mode = &pyr_cmd_get_config_mode; -	p_funcs->update_fb = pyr_dsi_dbi_update_fb; -	p_funcs->get_panel_info = pyr_cmd_get_panel_info; -} diff --git a/drivers/staging/gma500/mdfld_tmd_vid.c b/drivers/staging/gma500/mdfld_tmd_vid.c deleted file mode 100644 index affdc09c676..00000000000 --- a/drivers/staging/gma500/mdfld_tmd_vid.c +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright © 2010 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Authors: - * Jim Liu <jim.liu@intel.com> - * Jackie Li<yaodong.li@intel.com> - * Gideon Eaton <eaton. - * Scott Rowe <scott.m.rowe@intel.com> - */ - -#include "mdfld_dsi_dbi.h" -#include "mdfld_dsi_dpi.h" -#include "mdfld_dsi_output.h" -#include "mdfld_output.h" - -#include "mdfld_dsi_pkg_sender.h" - -#include "displays/tmd_vid.h" - -/* FIXME: static ? */ -struct drm_display_mode *tmd_vid_get_config_mode(struct drm_device *dev) -{ -	struct drm_display_mode *mode; -	struct drm_psb_private *dev_priv = dev->dev_private; -	struct mrst_timing_info *ti = &dev_priv->gct_data.DTD; -	bool use_gct = false; /*Disable GCT for now*/ - -	mode = kzalloc(sizeof(*mode), GFP_KERNEL); -	if (!mode) { -		dev_err(dev->dev, "Out of memory\n"); -		return NULL; -	} - -	if (use_gct) { -		dev_dbg(dev->dev, "gct find MIPI panel.\n"); - -		mode->hdisplay = (ti->hactive_hi << 8) | ti->hactive_lo; -		mode->vdisplay = (ti->vactive_hi << 8) | ti->vactive_lo; -		mode->hsync_start = mode->hdisplay + -				((ti->hsync_offset_hi << 8) | -				ti->hsync_offset_lo); -		mode->hsync_end = mode->hsync_start + -				((ti->hsync_pulse_width_hi << 8) | -				ti->hsync_pulse_width_lo); -		mode->htotal = mode->hdisplay + ((ti->hblank_hi << 8) | -								ti->hblank_lo); -		mode->vsync_start = \ -			mode->vdisplay + ((ti->vsync_offset_hi << 8) | -						ti->vsync_offset_lo); -		mode->vsync_end = \ -			mode->vsync_start + ((ti->vsync_pulse_width_hi << 8) | \ -						ti->vsync_pulse_width_lo); -		mode->vtotal = mode->vdisplay + -				((ti->vblank_hi << 8) | ti->vblank_lo); -		mode->clock = ti->pixel_clock * 10; - -		dev_dbg(dev->dev, "hdisplay is %d\n", mode->hdisplay); -		dev_dbg(dev->dev, "vdisplay is %d\n", mode->vdisplay); -		dev_dbg(dev->dev, "HSS is %d\n", mode->hsync_start); -		dev_dbg(dev->dev, "HSE is %d\n", mode->hsync_end); -		dev_dbg(dev->dev, "htotal is %d\n", mode->htotal); -		dev_dbg(dev->dev, "VSS is %d\n", mode->vsync_start); -		dev_dbg(dev->dev, "VSE is %d\n", mode->vsync_end); -		dev_dbg(dev->dev, "vtotal is %d\n", mode->vtotal); -		dev_dbg(dev->dev, "clock is %d\n", mode->clock); -	} else { -		mode->hdisplay = 480; -		mode->vdisplay = 854; -		mode->hsync_start = 487; -		mode->hsync_end = 490; -		mode->htotal = 499; -		mode->vsync_start = 861; -		mode->vsync_end = 865; -		mode->vtotal = 873; -		mode->clock = 33264; -	} -	drm_mode_set_name(mode); -	drm_mode_set_crtcinfo(mode, 0); - -	mode->type |= DRM_MODE_TYPE_PREFERRED; - -	return mode; -} - -static int tmd_vid_get_panel_info(struct drm_device *dev, -				int pipe, -				struct panel_info *pi) -{ -	if (!dev || !pi) -		return -EINVAL; - -	pi->width_mm = TMD_PANEL_WIDTH; -	pi->height_mm = TMD_PANEL_HEIGHT; - -	return 0; -} - -/* - *	mdfld_init_TMD_MIPI	-	initialise a TMD interface - *	@dsi_config: configuration - *	@pipe: pipe to configure - * - *	This function is called only by mrst_dsi_mode_set and - *	restore_display_registers.  since this function does not - *	acquire the mutex, it is important that the calling function - *	does! - */ - - -static void mdfld_dsi_tmd_drv_ic_init(struct mdfld_dsi_config *dsi_config, -				      int pipe) -{ -	static u32 tmd_cmd_mcap_off[] = {0x000000b2}; -	static u32 tmd_cmd_enable_lane_switch[] = {0x000101ef}; -	static u32 tmd_cmd_set_lane_num[] = {0x006360ef}; -	static u32 tmd_cmd_pushing_clock0[] = {0x00cc2fef}; -	static u32 tmd_cmd_pushing_clock1[] = {0x00dd6eef}; -	static u32 tmd_cmd_set_mode[] = {0x000000b3}; -	static u32 tmd_cmd_set_sync_pulse_mode[] = {0x000961ef}; -	static u32 tmd_cmd_set_column[] = {0x0100002a, 0x000000df}; -	static u32 tmd_cmd_set_page[] = {0x0300002b, 0x00000055}; -	static u32 tmd_cmd_set_video_mode[] = {0x00000153}; -	/*no auto_bl,need add in furture*/ -	static u32 tmd_cmd_enable_backlight[] = {0x00005ab4}; -	static u32 tmd_cmd_set_backlight_dimming[] = {0x00000ebd}; - -	struct mdfld_dsi_pkg_sender *sender -			= mdfld_dsi_get_pkg_sender(dsi_config); - -	DRM_INFO("Enter mdfld init TMD MIPI display.\n"); - -	if (!sender) { -		DRM_ERROR("Cannot get sender\n"); -		return; -	} - -	if (dsi_config->dvr_ic_inited) -		return; - -	msleep(3); - -	mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_mcap_off, 1, 0); -	mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_enable_lane_switch, 1, 0); -	mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_set_lane_num, 1, 0); -	mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_pushing_clock0, 1, 0); -	mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_pushing_clock1, 1, 0); -	mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_set_mode, 1, 0); -	mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_set_sync_pulse_mode, 1, 0); -	mdfld_dsi_send_mcs_long_lp(sender, tmd_cmd_set_column, 2, 0); -	mdfld_dsi_send_mcs_long_lp(sender, tmd_cmd_set_page, 2, 0); -	mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_set_video_mode, 1, 0); -	mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_enable_backlight, 1, 0); -	mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_set_backlight_dimming, 1, 0); - -	dsi_config->dvr_ic_inited = 1; -} - -/* TMD DPI encoder helper funcs */ -static const struct drm_encoder_helper_funcs -					mdfld_tpo_dpi_encoder_helper_funcs = { -	.dpms = mdfld_dsi_dpi_dpms, -	.mode_fixup = mdfld_dsi_dpi_mode_fixup, -	.prepare = mdfld_dsi_dpi_prepare, -	.mode_set = mdfld_dsi_dpi_mode_set, -	.commit = mdfld_dsi_dpi_commit, -}; - -/* TMD DPI encoder funcs */ -static const struct drm_encoder_funcs mdfld_tpo_dpi_encoder_funcs = { -	.destroy = drm_encoder_cleanup, -}; - -void tmd_vid_init(struct drm_device *dev, struct panel_funcs *p_funcs) -{ -	if (!dev || !p_funcs) { -		dev_err(dev->dev, "Invalid parameters\n"); -		return; -	} - -	p_funcs->encoder_funcs = &mdfld_tpo_dpi_encoder_funcs; -	p_funcs->encoder_helper_funcs = &mdfld_tpo_dpi_encoder_helper_funcs; -	p_funcs->get_config_mode = &tmd_vid_get_config_mode; -	p_funcs->update_fb = NULL; -	p_funcs->get_panel_info = tmd_vid_get_panel_info; -	p_funcs->reset = mdfld_dsi_panel_reset; -	p_funcs->drv_ic_init = mdfld_dsi_tmd_drv_ic_init; -} diff --git a/drivers/staging/gma500/mdfld_tpo_cmd.c b/drivers/staging/gma500/mdfld_tpo_cmd.c deleted file mode 100644 index c7f7c9c19bc..00000000000 --- a/drivers/staging/gma500/mdfld_tpo_cmd.c +++ /dev/null @@ -1,509 +0,0 @@ -/* - * Copyright (c)  2010 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicensen - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Authors: - * Thomas Eaton <thomas.g.eaton@intel.com> - * Scott Rowe <scott.m.rowe@intel.com> - */ - -#include "mdfld_dsi_dbi.h" -#include "mdfld_dsi_dpi.h" -#include "mdfld_dsi_output.h" -#include "mdfld_output.h" -#include "mdfld_dsi_dbi_dpu.h" -#include "mdfld_dsi_pkg_sender.h" - -#include "displays/tpo_cmd.h" - -static struct drm_display_mode *tpo_cmd_get_config_mode(struct drm_device *dev) -{ -	struct drm_display_mode *mode; -	struct drm_psb_private *dev_priv = dev->dev_private; -	struct mrst_timing_info *ti = &dev_priv->gct_data.DTD; -	bool use_gct = false; - -	mode = kzalloc(sizeof(*mode), GFP_KERNEL); -	if (!mode) -		return NULL; - -	if (use_gct) { -		dev_dbg(dev->dev, "gct find MIPI panel.\n"); - -		mode->hdisplay = (ti->hactive_hi << 8) | ti->hactive_lo; -		mode->vdisplay = (ti->vactive_hi << 8) | ti->vactive_lo; -		mode->hsync_start = mode->hdisplay + \ -				((ti->hsync_offset_hi << 8) | \ -				ti->hsync_offset_lo); -		mode->hsync_end = mode->hsync_start + \ -				((ti->hsync_pulse_width_hi << 8) | \ -				ti->hsync_pulse_width_lo); -		mode->htotal = mode->hdisplay + ((ti->hblank_hi << 8) | \ -								ti->hblank_lo); -		mode->vsync_start = \ -			mode->vdisplay + ((ti->vsync_offset_hi << 8) | \ -						ti->vsync_offset_lo); -		mode->vsync_end = \ -			mode->vsync_start + ((ti->vsync_pulse_width_hi << 8) | \ -						ti->vsync_pulse_width_lo); -		mode->vtotal = mode->vdisplay + \ -				((ti->vblank_hi << 8) | ti->vblank_lo); -		mode->clock = ti->pixel_clock * 10; - -		dev_dbg(dev->dev, "hdisplay is %d\n", mode->hdisplay); -		dev_dbg(dev->dev, "vdisplay is %d\n", mode->vdisplay); -		dev_dbg(dev->dev, "HSS is %d\n", mode->hsync_start); -		dev_dbg(dev->dev, "HSE is %d\n", mode->hsync_end); -		dev_dbg(dev->dev, "htotal is %d\n", mode->htotal); -		dev_dbg(dev->dev, "VSS is %d\n", mode->vsync_start); -		dev_dbg(dev->dev, "VSE is %d\n", mode->vsync_end); -		dev_dbg(dev->dev, "vtotal is %d\n", mode->vtotal); -		dev_dbg(dev->dev, "clock is %d\n", mode->clock); -	} else { -		mode->hdisplay = 864; -		mode->vdisplay = 480; -		mode->hsync_start = 872; -		mode->hsync_end = 876; -		mode->htotal = 884; -		mode->vsync_start = 482; -		mode->vsync_end = 494; -		mode->vtotal = 486; -		mode->clock = 25777; -	} - -	drm_mode_set_name(mode); -	drm_mode_set_crtcinfo(mode, 0); - -	mode->type |= DRM_MODE_TYPE_PREFERRED; - -	return mode; -} - -static bool mdfld_dsi_dbi_mode_fixup(struct drm_encoder *encoder, -				     struct drm_display_mode *mode, -				     struct drm_display_mode *adjusted_mode) -{ -	struct drm_device *dev = encoder->dev; -	struct drm_display_mode *fixed_mode = tpo_cmd_get_config_mode(dev); - -	if (fixed_mode) { -		adjusted_mode->hdisplay = fixed_mode->hdisplay; -		adjusted_mode->hsync_start = fixed_mode->hsync_start; -		adjusted_mode->hsync_end = fixed_mode->hsync_end; -		adjusted_mode->htotal = fixed_mode->htotal; -		adjusted_mode->vdisplay = fixed_mode->vdisplay; -		adjusted_mode->vsync_start = fixed_mode->vsync_start; -		adjusted_mode->vsync_end = fixed_mode->vsync_end; -		adjusted_mode->vtotal = fixed_mode->vtotal; -		adjusted_mode->clock = fixed_mode->clock; -		drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V); -		kfree(fixed_mode); -	} -	return true; -} - -static void mdfld_dsi_dbi_set_power(struct drm_encoder *encoder, bool on) -{ -	int ret = 0; -	struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder); -	struct mdfld_dsi_dbi_output *dbi_output = -				MDFLD_DSI_DBI_OUTPUT(dsi_encoder); -	struct mdfld_dsi_config *dsi_config = -		mdfld_dsi_encoder_get_config(dsi_encoder); -	struct mdfld_dsi_pkg_sender *sender = -		mdfld_dsi_encoder_get_pkg_sender(dsi_encoder); -	struct drm_device *dev = encoder->dev; -	struct drm_psb_private *dev_priv = dev->dev_private; -	u32 reg_offset = 0; -	int pipe = (dbi_output->channel_num == 0) ? 0 : 2; -	u32 data = 0; - -	dev_dbg(dev->dev, "pipe %d : %s, panel on: %s\n", -			pipe, on ? "On" : "Off", -			dbi_output->dbi_panel_on ? "True" : "False"); - -	if (pipe == 2) { -		if (on) -			dev_priv->dual_mipi = true; -		else -			dev_priv->dual_mipi = false; -		reg_offset = MIPIC_REG_OFFSET; -	} else { -		if (!on) -			dev_priv->dual_mipi = false; -	} - -	if (!gma_power_begin(dev, true)) { -		dev_err(dev->dev, "hw begin failed\n"); -		return; -	} - -	if (on) { -		if (dbi_output->dbi_panel_on) -			goto out_err; - -		ret = mdfld_dsi_dbi_update_power(dbi_output, DRM_MODE_DPMS_ON); -		if (ret) { -			dev_err(dev->dev, "power on error\n"); -			goto out_err; -		} - -		dbi_output->dbi_panel_on = true; - -		if (pipe == 2) -			dev_priv->dbi_panel_on2 = true; -		else -			dev_priv->dbi_panel_on = true; -		mdfld_enable_te(dev, pipe); -	} else { -		if (!dbi_output->dbi_panel_on && !dbi_output->first_boot) -			goto out_err; - -		dbi_output->dbi_panel_on = false; -		dbi_output->first_boot = false; - -		if (pipe == 2) -			dev_priv->dbi_panel_on2 = false; -		else -			dev_priv->dbi_panel_on = false; - -		mdfld_disable_te(dev, pipe); - -		ret = mdfld_dsi_dbi_update_power(dbi_output, DRM_MODE_DPMS_OFF); -		if (ret) { -			dev_err(dev->dev, "power on error\n"); -			goto out_err; -		} -	} - -	/* -	 * FIXME: this is a WA for TPO panel crash on DPMS on & off around -	 * 83 times. the root cause of this issue is that Booster in -	 * drvIC crashed. Add this WA so that we can resume the driver IC -	 * once we found that booster has a fault -	 */ -	mdfld_dsi_get_power_mode(dsi_config, -				&data, -				MDFLD_DSI_HS_TRANSMISSION); - -	if (on && data && !(data & (1 << 7))) { -		/* Soft reset */ -		mdfld_dsi_send_dcs(sender, -				   DCS_SOFT_RESET, -				   NULL, -				   0, -				   CMD_DATA_SRC_PIPE, -				   MDFLD_DSI_SEND_PACKAGE); - -		/* Init drvIC */ -		if (dbi_output->p_funcs->drv_ic_init) -			dbi_output->p_funcs->drv_ic_init(dsi_config, -							 pipe); -	} -  -out_err: -	gma_power_end(dev); -	if (ret) -		dev_err(dev->dev, "failed\n"); -} - - -static void mdfld_dsi_dbi_mode_set(struct drm_encoder *encoder, -				   struct drm_display_mode *mode, -				   struct drm_display_mode *adjusted_mode) -{ -	int ret = 0; -	struct drm_device *dev = encoder->dev; -	struct drm_psb_private *dev_priv = dev->dev_private; -	struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder); -	struct mdfld_dsi_dbi_output *dsi_output = -					MDFLD_DSI_DBI_OUTPUT(dsi_encoder); -	struct mdfld_dsi_config *dsi_config = -				mdfld_dsi_encoder_get_config(dsi_encoder); -	struct mdfld_dsi_connector *dsi_connector = dsi_config->connector; -	int pipe = dsi_connector->pipe; -	u8 param = 0; - -	/* Regs */ -	u32 mipi_reg = MIPI; -	u32 dspcntr_reg = DSPACNTR; -	u32 pipeconf_reg = PIPEACONF; -	u32 reg_offset = 0; - -	/* Values */ -	u32 dspcntr_val = dev_priv->dspcntr; -	u32 pipeconf_val = dev_priv->pipeconf; -	u32 h_active_area = mode->hdisplay; -	u32 v_active_area = mode->vdisplay; -	u32 mipi_val; - -	mipi_val = (PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX | -						TE_TRIGGER_GPIO_PIN); - -	dev_dbg(dev->dev, "mipi_val =0x%x\n", mipi_val); - -	dev_dbg(dev->dev, "type %s\n", (pipe == 2) ? "MIPI2" : "MIPI"); -	dev_dbg(dev->dev, "h %d v %d\n", mode->hdisplay, mode->vdisplay); - -	if (pipe == 2) { -		mipi_reg = MIPI_C; -		dspcntr_reg = DSPCCNTR; -		pipeconf_reg = PIPECCONF; - -		reg_offset = MIPIC_REG_OFFSET; - -		dspcntr_val = dev_priv->dspcntr2; -		pipeconf_val = dev_priv->pipeconf2; -	} else { -		mipi_val |= 0x2; /*two lanes for port A and C respectively*/ -	} - -	if (!gma_power_begin(dev, true)) { -		dev_err(dev->dev, "hw begin failed\n"); -		return; -	} - -	REG_WRITE(dspcntr_reg, dspcntr_val); -	REG_READ(dspcntr_reg); - -	/* 20ms delay before sending exit_sleep_mode */ -	msleep(20); - -	/* Send exit_sleep_mode DCS */ -	ret = mdfld_dsi_dbi_send_dcs(dsi_output, DCS_EXIT_SLEEP_MODE, -					NULL, 0, CMD_DATA_SRC_SYSTEM_MEM); -	if (ret) { -		dev_err(dev->dev, "sent exit_sleep_mode faild\n"); -		goto out_err; -	} - -	/* Send set_tear_on DCS */ -	ret = mdfld_dsi_dbi_send_dcs(dsi_output, DCS_SET_TEAR_ON, -					¶m, 1, CMD_DATA_SRC_SYSTEM_MEM); -	if (ret) { -		dev_err(dev->dev, "%s - sent set_tear_on faild\n", __func__); -		goto out_err; -	} - -	/* Do some init stuff */ -	REG_WRITE(pipeconf_reg, pipeconf_val | PIPEACONF_DSR); -	REG_READ(pipeconf_reg); - -	/* TODO: this looks ugly, try to move it to CRTC mode setting*/ -	if (pipe == 2) -		dev_priv->pipeconf2 |= PIPEACONF_DSR; -	else -		dev_priv->pipeconf |= PIPEACONF_DSR; - -	dev_dbg(dev->dev, "pipeconf %x\n",  REG_READ(pipeconf_reg)); - -	ret = mdfld_dsi_dbi_update_area(dsi_output, 0, 0, -				h_active_area - 1, v_active_area - 1); -	if (ret) { -		dev_err(dev->dev, "update area failed\n"); -		goto out_err; -	} - -out_err: -	gma_power_end(dev); - -	if (ret) -		dev_err(dev->dev, "mode set failed\n"); -} - -static void mdfld_dsi_dbi_prepare(struct drm_encoder *encoder) -{ -	struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder); -	struct mdfld_dsi_dbi_output *dbi_output -				= MDFLD_DSI_DBI_OUTPUT(dsi_encoder); - -	dbi_output->mode_flags |= MODE_SETTING_IN_ENCODER; -	dbi_output->mode_flags &= ~MODE_SETTING_ENCODER_DONE; - -	mdfld_dsi_dbi_set_power(encoder, false); -} - -static void mdfld_dsi_dbi_commit(struct drm_encoder *encoder) -{ -	struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder); -	struct mdfld_dsi_dbi_output *dbi_output = -					MDFLD_DSI_DBI_OUTPUT(dsi_encoder); -	struct drm_device *dev = dbi_output->dev; -	struct drm_psb_private *dev_priv = dev->dev_private; -	struct psb_drm_dpu_rect rect; - -	mdfld_dsi_dbi_set_power(encoder, true); -	dbi_output->mode_flags &= ~MODE_SETTING_IN_ENCODER; - -	rect.x = rect.y = 0; -	rect.width = 864; -	rect.height = 480; - -	if (dbi_output->channel_num == 1) { -		dev_priv->dsr_fb_update |= MDFLD_DSR_2D_3D_2; -		/*if dpu enabled report a fullscreen damage*/ -		mdfld_dbi_dpu_report_damage(dev, MDFLD_PLANEC, &rect); -	} else { -		dev_priv->dsr_fb_update |= MDFLD_DSR_2D_3D_0; -		mdfld_dbi_dpu_report_damage(dev, MDFLD_PLANEA, &rect); -	} -	dbi_output->mode_flags |= MODE_SETTING_ENCODER_DONE; -} - -static void mdfld_dsi_dbi_dpms(struct drm_encoder *encoder, int mode) -{ -	struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder); -	struct mdfld_dsi_dbi_output *dbi_output -				= MDFLD_DSI_DBI_OUTPUT(dsi_encoder); -	struct drm_device *dev = dbi_output->dev; -	struct drm_psb_private *dev_priv = dev->dev_private; -	static bool bdispoff; - -	dev_dbg(dev->dev, "%s\n", (mode == DRM_MODE_DPMS_ON ? "on" : "off")); - -	if (mode == DRM_MODE_DPMS_ON) { -		/* -		 * FIXME: in case I am wrong! -		 * we don't need to exit dsr here to wake up plane/pipe/pll -		 * if everything goes right, hw_begin will resume them all -		 * during set_power. -		 */ -		if (bdispoff /* FIXME && gbgfxsuspended */) { -			mdfld_dsi_dbi_exit_dsr(dev, MDFLD_DSR_2D_3D); -			bdispoff = false; -			dev_priv->dispstatus = true; -		} - -		mdfld_dsi_dbi_set_power(encoder, true); -		/* FIXME if (gbgfxsuspended) -			gbgfxsuspended = false; */ -	} else { -		/* -		 * I am not sure whether this is the perfect place to -		 * turn rpm on since we still have a lot of CRTC turnning -		 * on work to do. -		 */ -		bdispoff = true; -		dev_priv->dispstatus = false; -		mdfld_dsi_dbi_set_power(encoder, false); -	} -} - - -/* - * Update the DBI MIPI Panel Frame Buffer. - */ -static void mdfld_dsi_dbi_update_fb(struct mdfld_dsi_dbi_output *dbi_output, -								int pipe) -{ -	struct mdfld_dsi_pkg_sender *sender = -		mdfld_dsi_encoder_get_pkg_sender(&dbi_output->base); -	struct drm_device *dev = dbi_output->dev; -	struct drm_crtc *crtc = dbi_output->base.base.crtc; -	struct psb_intel_crtc *psb_crtc = (crtc) ? -					to_psb_intel_crtc(crtc) : NULL; -	u32 dpll_reg = MRST_DPLL_A; -	u32 dspcntr_reg = DSPACNTR; -	u32 pipeconf_reg = PIPEACONF; -	u32 dsplinoff_reg = DSPALINOFF; -	u32 dspsurf_reg = DSPASURF; -	u32 reg_offset = 0; - -	/* If mode setting on-going, back off */ -	if ((dbi_output->mode_flags & MODE_SETTING_ON_GOING) || -		(psb_crtc && psb_crtc->mode_flags & MODE_SETTING_ON_GOING) || -		!(dbi_output->mode_flags & MODE_SETTING_ENCODER_DONE)) -		return; - -	if (pipe == 2) { -		dspcntr_reg = DSPCCNTR; -		pipeconf_reg = PIPECCONF; -		dsplinoff_reg = DSPCLINOFF; -		dspsurf_reg = DSPCSURF; -		reg_offset = MIPIC_REG_OFFSET; -	} - -	if (!gma_power_begin(dev, true)) { -		dev_err(dev->dev, "hw begin failed\n"); -		return; -	} - -	/* Check DBI FIFO status */ -	if (!(REG_READ(dpll_reg) & DPLL_VCO_ENABLE) || -	   !(REG_READ(dspcntr_reg) & DISPLAY_PLANE_ENABLE) || -	   !(REG_READ(pipeconf_reg) & DISPLAY_PLANE_ENABLE)) -		goto update_fb_out0; - -	/* Refresh plane changes */ -	REG_WRITE(dsplinoff_reg, REG_READ(dsplinoff_reg)); -	REG_WRITE(dspsurf_reg, REG_READ(dspsurf_reg)); -	REG_READ(dspsurf_reg); - -	mdfld_dsi_send_dcs(sender, -			   DCS_WRITE_MEM_START, -			   NULL, -			   0, -			   CMD_DATA_SRC_PIPE, -			   MDFLD_DSI_SEND_PACKAGE); - -	dbi_output->dsr_fb_update_done = true; -update_fb_out0: -	gma_power_end(dev); -} - -static int tpo_cmd_get_panel_info(struct drm_device *dev, -				int pipe, -				struct panel_info *pi) -{ -	if (!dev || !pi) -		return -EINVAL; - -	pi->width_mm = TPO_PANEL_WIDTH; -	pi->height_mm = TPO_PANEL_HEIGHT; - -	return 0; -} - - -/* TPO DBI encoder helper funcs */ -static const struct drm_encoder_helper_funcs mdfld_dsi_dbi_helper_funcs = { -	.dpms = mdfld_dsi_dbi_dpms, -	.mode_fixup = mdfld_dsi_dbi_mode_fixup, -	.prepare = mdfld_dsi_dbi_prepare, -	.mode_set = mdfld_dsi_dbi_mode_set, -	.commit = mdfld_dsi_dbi_commit, -}; - -/* TPO DBI encoder funcs */ -static const struct drm_encoder_funcs mdfld_dsi_dbi_encoder_funcs = { -	.destroy = drm_encoder_cleanup, -}; - -void tpo_cmd_init(struct drm_device *dev, struct panel_funcs *p_funcs) -{ -	p_funcs->encoder_funcs = &mdfld_dsi_dbi_encoder_funcs; -	p_funcs->encoder_helper_funcs = &mdfld_dsi_dbi_helper_funcs; -	p_funcs->get_config_mode = &tpo_cmd_get_config_mode; -	p_funcs->update_fb = mdfld_dsi_dbi_update_fb; -	p_funcs->get_panel_info = tpo_cmd_get_panel_info; -	p_funcs->reset = mdfld_dsi_panel_reset; -	p_funcs->drv_ic_init = mdfld_dsi_brightness_init; -} diff --git a/drivers/staging/gma500/mdfld_tpo_vid.c b/drivers/staging/gma500/mdfld_tpo_vid.c deleted file mode 100644 index 95490175176..00000000000 --- a/drivers/staging/gma500/mdfld_tpo_vid.c +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright © 2010 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Authors: - * jim liu <jim.liu@intel.com> - * Jackie Li<yaodong.li@intel.com> - */ - -#include "mdfld_dsi_dbi.h" -#include "mdfld_dsi_dpi.h" -#include "mdfld_dsi_output.h" -#include "mdfld_output.h" - -#include "mdfld_dsi_pkg_sender.h" - -#include "displays/tpo_vid.h" - -static struct drm_display_mode *tpo_vid_get_config_mode(struct drm_device *dev) -{ -	struct drm_display_mode *mode; -	struct drm_psb_private *dev_priv = dev->dev_private; -	struct mrst_timing_info *ti = &dev_priv->gct_data.DTD; -	bool use_gct = false; - -	mode = kzalloc(sizeof(*mode), GFP_KERNEL); -	if (!mode) { -		dev_err(dev->dev, "out of memory\n"); -		return NULL; -	} - -	if (use_gct) { -		mode->hdisplay = (ti->hactive_hi << 8) | ti->hactive_lo; -		mode->vdisplay = (ti->vactive_hi << 8) | ti->vactive_lo; -		mode->hsync_start = mode->hdisplay + \ -				((ti->hsync_offset_hi << 8) | \ -				ti->hsync_offset_lo); -		mode->hsync_end = mode->hsync_start + \ -				((ti->hsync_pulse_width_hi << 8) | \ -				ti->hsync_pulse_width_lo); -		mode->htotal = mode->hdisplay + ((ti->hblank_hi << 8) | \ -								ti->hblank_lo); -		mode->vsync_start = \ -			mode->vdisplay + ((ti->vsync_offset_hi << 8) | \ -						ti->vsync_offset_lo); -		mode->vsync_end = \ -			mode->vsync_start + ((ti->vsync_pulse_width_hi << 8) | \ -						ti->vsync_pulse_width_lo); -		mode->vtotal = mode->vdisplay + \ -				((ti->vblank_hi << 8) | ti->vblank_lo); -		mode->clock = ti->pixel_clock * 10; - -		dev_dbg(dev->dev, "hdisplay is %d\n", mode->hdisplay); -		dev_dbg(dev->dev, "vdisplay is %d\n", mode->vdisplay); -		dev_dbg(dev->dev, "HSS is %d\n", mode->hsync_start); -		dev_dbg(dev->dev, "HSE is %d\n", mode->hsync_end); -		dev_dbg(dev->dev, "htotal is %d\n", mode->htotal); -		dev_dbg(dev->dev, "VSS is %d\n", mode->vsync_start); -		dev_dbg(dev->dev, "VSE is %d\n", mode->vsync_end); -		dev_dbg(dev->dev, "vtotal is %d\n", mode->vtotal); -		dev_dbg(dev->dev, "clock is %d\n", mode->clock); -	} else { -		mode->hdisplay = 864; -		mode->vdisplay = 480; -		mode->hsync_start = 873; -		mode->hsync_end = 876; -		mode->htotal = 887; -		mode->vsync_start = 487; -		mode->vsync_end = 490; -		mode->vtotal = 499; -		mode->clock = 33264; -	} - -	drm_mode_set_name(mode); -	drm_mode_set_crtcinfo(mode, 0); - -	mode->type |= DRM_MODE_TYPE_PREFERRED; - -	return mode; -} - -static int tpo_vid_get_panel_info(struct drm_device *dev, -				int pipe, -				struct panel_info *pi) -{ -	if (!dev || !pi) -		return -EINVAL; - -	pi->width_mm = TPO_PANEL_WIDTH; -	pi->height_mm = TPO_PANEL_HEIGHT; - -	return 0; -} - -/*TPO DPI encoder helper funcs*/ -static const struct drm_encoder_helper_funcs -					mdfld_tpo_dpi_encoder_helper_funcs = { -	.dpms = mdfld_dsi_dpi_dpms, -	.mode_fixup = mdfld_dsi_dpi_mode_fixup, -	.prepare = mdfld_dsi_dpi_prepare, -	.mode_set = mdfld_dsi_dpi_mode_set, -	.commit = mdfld_dsi_dpi_commit, -}; - -/*TPO DPI encoder funcs*/ -static const struct drm_encoder_funcs mdfld_tpo_dpi_encoder_funcs = { -	.destroy = drm_encoder_cleanup, -}; - -void tpo_vid_init(struct drm_device *dev, struct panel_funcs *p_funcs) -{ -	if (!dev || !p_funcs) { -		dev_err(dev->dev, "tpo_vid_init: Invalid parameters\n"); -		return; -	} - -	p_funcs->encoder_funcs = &mdfld_tpo_dpi_encoder_funcs; -	p_funcs->encoder_helper_funcs = &mdfld_tpo_dpi_encoder_helper_funcs; -	p_funcs->get_config_mode = &tpo_vid_get_config_mode; -	p_funcs->update_fb = NULL; -	p_funcs->get_panel_info = tpo_vid_get_panel_info; -} diff --git a/drivers/staging/gma500/medfield.h b/drivers/staging/gma500/medfield.h deleted file mode 100644 index 09e9687431f..00000000000 --- a/drivers/staging/gma500/medfield.h +++ /dev/null @@ -1,268 +0,0 @@ -/* - * Copyright © 2011 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -/* Medfield DSI controller registers */ - -#define MIPIA_DEVICE_READY_REG				0xb000 -#define MIPIA_INTR_STAT_REG				0xb004 -#define MIPIA_INTR_EN_REG				0xb008 -#define MIPIA_DSI_FUNC_PRG_REG				0xb00c -#define MIPIA_HS_TX_TIMEOUT_REG				0xb010 -#define MIPIA_LP_RX_TIMEOUT_REG				0xb014 -#define MIPIA_TURN_AROUND_TIMEOUT_REG			0xb018 -#define MIPIA_DEVICE_RESET_TIMER_REG			0xb01c -#define MIPIA_DPI_RESOLUTION_REG			0xb020 -#define MIPIA_DBI_FIFO_THROTTLE_REG			0xb024 -#define MIPIA_HSYNC_COUNT_REG				0xb028 -#define MIPIA_HBP_COUNT_REG				0xb02c -#define MIPIA_HFP_COUNT_REG				0xb030 -#define MIPIA_HACTIVE_COUNT_REG				0xb034 -#define MIPIA_VSYNC_COUNT_REG				0xb038 -#define MIPIA_VBP_COUNT_REG				0xb03c -#define MIPIA_VFP_COUNT_REG				0xb040 -#define MIPIA_HIGH_LOW_SWITCH_COUNT_REG			0xb044 -#define MIPIA_DPI_CONTROL_REG				0xb048 -#define MIPIA_DPI_DATA_REG				0xb04c -#define MIPIA_INIT_COUNT_REG				0xb050 -#define MIPIA_MAX_RETURN_PACK_SIZE_REG			0xb054 -#define MIPIA_VIDEO_MODE_FORMAT_REG			0xb058 -#define MIPIA_EOT_DISABLE_REG				0xb05c -#define MIPIA_LP_BYTECLK_REG				0xb060 -#define MIPIA_LP_GEN_DATA_REG				0xb064 -#define MIPIA_HS_GEN_DATA_REG				0xb068 -#define MIPIA_LP_GEN_CTRL_REG				0xb06c -#define MIPIA_HS_GEN_CTRL_REG				0xb070 -#define MIPIA_GEN_FIFO_STAT_REG				0xb074 -#define MIPIA_HS_LS_DBI_ENABLE_REG			0xb078 -#define MIPIA_DPHY_PARAM_REG				0xb080 -#define MIPIA_DBI_BW_CTRL_REG				0xb084 -#define MIPIA_CLK_LANE_SWITCH_TIME_CNT_REG		0xb088 - -#define DSI_DEVICE_READY				(0x1) -#define DSI_POWER_STATE_ULPS_ENTER			(0x2 << 1) -#define DSI_POWER_STATE_ULPS_EXIT			(0x1 << 1) -#define DSI_POWER_STATE_ULPS_OFFSET			(0x1) - - -#define DSI_ONE_DATA_LANE				(0x1) -#define DSI_TWO_DATA_LANE				(0x2) -#define DSI_THREE_DATA_LANE				(0X3) -#define DSI_FOUR_DATA_LANE				(0x4) -#define DSI_DPI_VIRT_CHANNEL_OFFSET			(0x3) -#define DSI_DBI_VIRT_CHANNEL_OFFSET			(0x5) -#define DSI_DPI_COLOR_FORMAT_RGB565			(0x01 << 7) -#define DSI_DPI_COLOR_FORMAT_RGB666			(0x02 << 7) -#define DSI_DPI_COLOR_FORMAT_RGB666_UNPACK		(0x03 << 7) -#define DSI_DPI_COLOR_FORMAT_RGB888			(0x04 << 7) -#define DSI_DBI_COLOR_FORMAT_OPTION2			(0x05 << 13) - -#define DSI_INTR_STATE_RXSOTERROR			1 - -#define DSI_INTR_STATE_SPL_PKG_SENT			(1 << 30) -#define DSI_INTR_STATE_TE				(1 << 31) - -#define DSI_HS_TX_TIMEOUT_MASK				(0xffffff) - -#define DSI_LP_RX_TIMEOUT_MASK				(0xffffff) - -#define DSI_TURN_AROUND_TIMEOUT_MASK			(0x3f) - -#define DSI_RESET_TIMER_MASK				(0xffff) - -#define DSI_DBI_FIFO_WM_HALF				(0x0) -#define DSI_DBI_FIFO_WM_QUARTER				(0x1) -#define DSI_DBI_FIFO_WM_LOW				(0x2) - -#define DSI_DPI_TIMING_MASK				(0xffff) - -#define DSI_INIT_TIMER_MASK				(0xffff) - -#define DSI_DBI_RETURN_PACK_SIZE_MASK			(0x3ff) - -#define DSI_LP_BYTECLK_MASK				(0x0ffff) - -#define DSI_HS_CTRL_GEN_SHORT_W0			(0x03) -#define DSI_HS_CTRL_GEN_SHORT_W1			(0x13) -#define DSI_HS_CTRL_GEN_SHORT_W2			(0x23) -#define DSI_HS_CTRL_GEN_R0				(0x04) -#define DSI_HS_CTRL_GEN_R1				(0x14) -#define DSI_HS_CTRL_GEN_R2				(0x24) -#define DSI_HS_CTRL_GEN_LONG_W				(0x29) -#define DSI_HS_CTRL_MCS_SHORT_W0			(0x05) -#define DSI_HS_CTRL_MCS_SHORT_W1			(0x15) -#define DSI_HS_CTRL_MCS_R0				(0x06) -#define DSI_HS_CTRL_MCS_LONG_W				(0x39) -#define DSI_HS_CTRL_VC_OFFSET				(0x06) -#define DSI_HS_CTRL_WC_OFFSET				(0x08) - -#define	DSI_FIFO_GEN_HS_DATA_FULL			(1 << 0) -#define DSI_FIFO_GEN_HS_DATA_HALF_EMPTY			(1 << 1) -#define DSI_FIFO_GEN_HS_DATA_EMPTY			(1 << 2) -#define DSI_FIFO_GEN_LP_DATA_FULL			(1 << 8) -#define DSI_FIFO_GEN_LP_DATA_HALF_EMPTY			(1 << 9) -#define DSI_FIFO_GEN_LP_DATA_EMPTY			(1 << 10) -#define DSI_FIFO_GEN_HS_CTRL_FULL			(1 << 16) -#define DSI_FIFO_GEN_HS_CTRL_HALF_EMPTY			(1 << 17) -#define DSI_FIFO_GEN_HS_CTRL_EMPTY			(1 << 18) -#define DSI_FIFO_GEN_LP_CTRL_FULL			(1 << 24) -#define DSI_FIFO_GEN_LP_CTRL_HALF_EMPTY			(1 << 25) -#define DSI_FIFO_GEN_LP_CTRL_EMPTY			(1 << 26) -#define DSI_FIFO_DBI_EMPTY				(1 << 27) -#define DSI_FIFO_DPI_EMPTY				(1 << 28) - -#define DSI_DBI_HS_LP_SWITCH_MASK			(0x1) - -#define DSI_HS_LP_SWITCH_COUNTER_OFFSET			(0x0) -#define DSI_LP_HS_SWITCH_COUNTER_OFFSET			(0x16) - -#define DSI_DPI_CTRL_HS_SHUTDOWN			(0x00000001) -#define DSI_DPI_CTRL_HS_TURN_ON				(0x00000002) - -/* Medfield DSI adapter registers */ -#define MIPIA_CONTROL_REG				0xb104 -#define MIPIA_DATA_ADD_REG				0xb108 -#define MIPIA_DATA_LEN_REG				0xb10c -#define MIPIA_CMD_ADD_REG				0xb110 -#define MIPIA_CMD_LEN_REG				0xb114 - -/*dsi power modes*/ -#define DSI_POWER_MODE_DISPLAY_ON	(1 << 2) -#define DSI_POWER_MODE_NORMAL_ON	(1 << 3) -#define DSI_POWER_MODE_SLEEP_OUT	(1 << 4) -#define DSI_POWER_MODE_PARTIAL_ON	(1 << 5) -#define DSI_POWER_MODE_IDLE_ON		(1 << 6) - -enum { -	MDFLD_DSI_ENCODER_DBI = 0, -	MDFLD_DSI_ENCODER_DPI, -}; - -enum { -	MDFLD_DSI_VIDEO_NON_BURST_MODE_SYNC_PULSE = 1, -	MDFLD_DSI_VIDEO_NON_BURST_MODE_SYNC_EVENTS = 2, -	MDFLD_DSI_VIDEO_BURST_MODE = 3, -}; - -#define DSI_DPI_COMPLETE_LAST_LINE			(1 << 2) -#define DSI_DPI_DISABLE_BTA				(1 << 3) -/* Panel types */ -enum { -	TPO_CMD, -	TPO_VID, -	TMD_CMD, -	TMD_VID, -	PYR_CMD, -	PYR_VID, -	TPO, -	TMD, -	PYR, -	HDMI, -	GCT_DETECT -}; - -/* Junk that belongs elsewhere */ -#define TPO_PANEL_WIDTH		84 -#define TPO_PANEL_HEIGHT	46 -#define TMD_PANEL_WIDTH		39 -#define TMD_PANEL_HEIGHT	71 -#define PYR_PANEL_WIDTH		53 -#define PYR_PANEL_HEIGHT	95 - -/* Panel interface */ -struct panel_info { -	u32 width_mm; -	u32 height_mm; -}; - -struct mdfld_dsi_dbi_output; - -struct mdfld_dsi_connector_state { -	u32 mipi_ctrl_reg; -}; - -struct mdfld_dsi_encoder_state { - -}; - -struct mdfld_dsi_connector { -	/* -	 * This is ugly, but I have to use connector in it! :-( -	 * FIXME: use drm_connector instead. -	 */ -	struct psb_intel_output base; - -	int pipe; -	void *private; -	void *pkg_sender; - -	/* Connection status */ -	enum drm_connector_status status; -}; - -struct mdfld_dsi_encoder { -	struct drm_encoder base; -	void *private; -}; - -/* - * DSI config, consists of one DSI connector, two DSI encoders. - * DRM will pick up on DSI encoder basing on differents configs. - */ -struct mdfld_dsi_config { -	struct drm_device *dev; -	struct drm_display_mode *fixed_mode; -	struct drm_display_mode *mode; - -	struct mdfld_dsi_connector *connector; -	struct mdfld_dsi_encoder *encoders[DRM_CONNECTOR_MAX_ENCODER]; -	struct mdfld_dsi_encoder *encoder; - -	int changed; - -	int bpp; -	int type; -	int lane_count; -	/*Virtual channel number for this encoder*/ -	int channel_num; -	/*video mode configure*/ -	int video_mode; - -	int dvr_ic_inited; -}; - -#define MDFLD_DSI_CONNECTOR(psb_output) \ -		(container_of(psb_output, struct mdfld_dsi_connector, base)) - -#define MDFLD_DSI_ENCODER(encoder) \ -		(container_of(encoder, struct mdfld_dsi_encoder, base)) - -struct panel_funcs { -	const struct drm_encoder_funcs *encoder_funcs; -	const struct drm_encoder_helper_funcs *encoder_helper_funcs; -	struct drm_display_mode *(*get_config_mode) (struct drm_device *); -	void (*update_fb) (struct mdfld_dsi_dbi_output *, int); -	int (*get_panel_info) (struct drm_device *, int, struct panel_info *); -	int (*reset)(int pipe); -	void (*drv_ic_init)(struct mdfld_dsi_config *dsi_config, int pipe); -}; - diff --git a/drivers/staging/gma500/mid_bios.c b/drivers/staging/gma500/mid_bios.c deleted file mode 100644 index ee3c0368e32..00000000000 --- a/drivers/staging/gma500/mid_bios.c +++ /dev/null @@ -1,270 +0,0 @@ -/************************************************************************** - * Copyright (c) 2011, Intel Corporation. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - **************************************************************************/ - -/* TODO - * - Split functions by vbt type - * - Make them all take drm_device - * - Check ioremap failures - */ - -#include <linux/moduleparam.h> -#include <drm/drmP.h> -#include <drm/drm.h> -#include "psb_drm.h" -#include "psb_drv.h" -#include "mid_bios.h" -#include "mdfld_output.h" - -static int panel_id = GCT_DETECT; -module_param_named(panel_id, panel_id, int, 0600); -MODULE_PARM_DESC(panel_id, "Panel Identifier"); - - -static void mid_get_fuse_settings(struct drm_device *dev) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; -	struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0); -	uint32_t fuse_value = 0; -	uint32_t fuse_value_tmp = 0; - -#define FB_REG06 0xD0810600 -#define FB_MIPI_DISABLE  (1 << 11) -#define FB_REG09 0xD0810900 -#define FB_REG09 0xD0810900 -#define FB_SKU_MASK  0x7000 -#define FB_SKU_SHIFT 12 -#define FB_SKU_100 0 -#define FB_SKU_100L 1 -#define FB_SKU_83 2 -	pci_write_config_dword(pci_root, 0xD0, FB_REG06); -	pci_read_config_dword(pci_root, 0xD4, &fuse_value); - -	/* FB_MIPI_DISABLE doesn't mean LVDS on with Medfield */ -	if (IS_MRST(dev)) -		dev_priv->iLVDS_enable = fuse_value & FB_MIPI_DISABLE; - -	DRM_INFO("internal display is %s\n", -		 dev_priv->iLVDS_enable ? "LVDS display" : "MIPI display"); - -	 /* Prevent runtime suspend at start*/ -	 if (dev_priv->iLVDS_enable) { -		dev_priv->is_lvds_on = true; -		dev_priv->is_mipi_on = false; -	} else { -		dev_priv->is_mipi_on = true; -		dev_priv->is_lvds_on = false; -	} - -	dev_priv->video_device_fuse = fuse_value; - -	pci_write_config_dword(pci_root, 0xD0, FB_REG09); -	pci_read_config_dword(pci_root, 0xD4, &fuse_value); - -	dev_dbg(dev->dev, "SKU values is 0x%x.\n", fuse_value); -	fuse_value_tmp = (fuse_value & FB_SKU_MASK) >> FB_SKU_SHIFT; - -	dev_priv->fuse_reg_value = fuse_value; - -	switch (fuse_value_tmp) { -	case FB_SKU_100: -		dev_priv->core_freq = 200; -		break; -	case FB_SKU_100L: -		dev_priv->core_freq = 100; -		break; -	case FB_SKU_83: -		dev_priv->core_freq = 166; -		break; -	default: -		dev_warn(dev->dev, "Invalid SKU values, SKU value = 0x%08x\n", -								fuse_value_tmp); -		dev_priv->core_freq = 0; -	} -	dev_dbg(dev->dev, "LNC core clk is %dMHz.\n", dev_priv->core_freq); -	pci_dev_put(pci_root); -} - -/* - *	Get the revison ID, B0:D2:F0;0x08 - */ -static void mid_get_pci_revID(struct drm_psb_private *dev_priv) -{ -	uint32_t platform_rev_id = 0; -	struct pci_dev *pci_gfx_root = pci_get_bus_and_slot(0, PCI_DEVFN(2, 0)); - -	pci_read_config_dword(pci_gfx_root, 0x08, &platform_rev_id); -	dev_priv->platform_rev_id = (uint8_t) platform_rev_id; -	pci_dev_put(pci_gfx_root); -	dev_dbg(dev_priv->dev->dev, "platform_rev_id is %x\n", -					dev_priv->platform_rev_id); -} - -static void mid_get_vbt_data(struct drm_psb_private *dev_priv) -{ -	struct drm_device *dev = dev_priv->dev; -	struct mrst_vbt *vbt = &dev_priv->vbt_data; -	u32 addr; -	u16 new_size; -	u8 *vbt_virtual; -	u8 bpi; -	u8 number_desc = 0; -	struct mrst_timing_info *dp_ti = &dev_priv->gct_data.DTD; -	struct gct_r10_timing_info ti; -	void *pGCT; -	struct pci_dev *pci_gfx_root = pci_get_bus_and_slot(0, PCI_DEVFN(2, 0)); - -	/* Get the address of the platform config vbt, B0:D2:F0;0xFC */ -	pci_read_config_dword(pci_gfx_root, 0xFC, &addr); -	pci_dev_put(pci_gfx_root); - -	dev_dbg(dev->dev, "drm platform config address is %x\n", addr); - -	/* check for platform config address == 0. */ -	/* this means fw doesn't support vbt */ - -	if (addr == 0) { -		vbt->size = 0; -		return; -	} - -	/* get the virtual address of the vbt */ -	vbt_virtual = ioremap(addr, sizeof(*vbt)); - -	memcpy(vbt, vbt_virtual, sizeof(*vbt)); -	iounmap(vbt_virtual); /* Free virtual address space */ - -	dev_dbg(dev->dev, "GCT revision is %x\n", vbt->revision); - -	switch (vbt->revision) { -	case 0: -		vbt->mrst_gct = ioremap(addr + sizeof(*vbt) - 4, -					vbt->size - sizeof(*vbt) + 4); -		pGCT = vbt->mrst_gct; -		bpi = ((struct mrst_gct_v1 *)pGCT)->PD.BootPanelIndex; -		dev_priv->gct_data.bpi = bpi; -		dev_priv->gct_data.pt = -			((struct mrst_gct_v1 *)pGCT)->PD.PanelType; -		memcpy(&dev_priv->gct_data.DTD, -			&((struct mrst_gct_v1 *)pGCT)->panel[bpi].DTD, -				sizeof(struct mrst_timing_info)); -		dev_priv->gct_data.Panel_Port_Control = -		  ((struct mrst_gct_v1 *)pGCT)->panel[bpi].Panel_Port_Control; -		dev_priv->gct_data.Panel_MIPI_Display_Descriptor = -			((struct mrst_gct_v1 *)pGCT)->panel[bpi].Panel_MIPI_Display_Descriptor; -		break; -	case 1: -		vbt->mrst_gct = ioremap(addr + sizeof(*vbt) - 4, -					vbt->size - sizeof(*vbt) + 4); -		pGCT = vbt->mrst_gct; -		bpi = ((struct mrst_gct_v2 *)pGCT)->PD.BootPanelIndex; -		dev_priv->gct_data.bpi = bpi; -		dev_priv->gct_data.pt = -			((struct mrst_gct_v2 *)pGCT)->PD.PanelType; -		memcpy(&dev_priv->gct_data.DTD, -			&((struct mrst_gct_v2 *)pGCT)->panel[bpi].DTD, -				sizeof(struct mrst_timing_info)); -		dev_priv->gct_data.Panel_Port_Control = -		  ((struct mrst_gct_v2 *)pGCT)->panel[bpi].Panel_Port_Control; -		dev_priv->gct_data.Panel_MIPI_Display_Descriptor = -			((struct mrst_gct_v2 *)pGCT)->panel[bpi].Panel_MIPI_Display_Descriptor; -		break; -	case 0x10: -		/*header definition changed from rev 01 (v2) to rev 10h. */ -		/*so, some values have changed location*/ -		new_size = vbt->checksum; /*checksum contains lo size byte*/ -		/*LSB of mrst_gct contains hi size byte*/ -		new_size |= ((0xff & (unsigned int)vbt->mrst_gct)) << 8; - -		vbt->checksum = vbt->size; /*size contains the checksum*/ -		if (new_size > 0xff) -			vbt->size = 0xff; /*restrict size to 255*/ -		else -			vbt->size = new_size; - -		/* number of descriptors defined in the GCT */ -		number_desc = ((0xff00 & (unsigned int)vbt->mrst_gct)) >> 8; -		bpi = ((0xff0000 & (unsigned int)vbt->mrst_gct)) >> 16; -		vbt->mrst_gct = ioremap(addr + GCT_R10_HEADER_SIZE, -				GCT_R10_DISPLAY_DESC_SIZE * number_desc); -		pGCT = vbt->mrst_gct; -		pGCT = (u8 *)pGCT + (bpi*GCT_R10_DISPLAY_DESC_SIZE); -		dev_priv->gct_data.bpi = bpi; /*save boot panel id*/ - -		/*copy the GCT display timings into a temp structure*/ -		memcpy(&ti, pGCT, sizeof(struct gct_r10_timing_info)); - -		/*now copy the temp struct into the dev_priv->gct_data*/ -		dp_ti->pixel_clock = ti.pixel_clock; -		dp_ti->hactive_hi = ti.hactive_hi; -		dp_ti->hactive_lo = ti.hactive_lo; -		dp_ti->hblank_hi = ti.hblank_hi; -		dp_ti->hblank_lo = ti.hblank_lo; -		dp_ti->hsync_offset_hi = ti.hsync_offset_hi; -		dp_ti->hsync_offset_lo = ti.hsync_offset_lo; -		dp_ti->hsync_pulse_width_hi = ti.hsync_pulse_width_hi; -		dp_ti->hsync_pulse_width_lo = ti.hsync_pulse_width_lo; -		dp_ti->vactive_hi = ti.vactive_hi; -		dp_ti->vactive_lo = ti.vactive_lo; -		dp_ti->vblank_hi = ti.vblank_hi; -		dp_ti->vblank_lo = ti.vblank_lo; -		dp_ti->vsync_offset_hi = ti.vsync_offset_hi; -		dp_ti->vsync_offset_lo = ti.vsync_offset_lo; -		dp_ti->vsync_pulse_width_hi = ti.vsync_pulse_width_hi; -		dp_ti->vsync_pulse_width_lo = ti.vsync_pulse_width_lo; - -		/* Move the MIPI_Display_Descriptor data from GCT to dev priv */ -		dev_priv->gct_data.Panel_MIPI_Display_Descriptor = -							*((u8 *)pGCT + 0x0d); -		dev_priv->gct_data.Panel_MIPI_Display_Descriptor |= -						(*((u8 *)pGCT + 0x0e)) << 8; -		break; -	default: -		dev_err(dev->dev, "Unknown revision of GCT!\n"); -		vbt->size = 0; -	} -	if (IS_MFLD(dev_priv->dev)) { -		if (panel_id == GCT_DETECT) { -			if (dev_priv->gct_data.bpi == 2) { -				dev_info(dev->dev, "[GFX] PYR Panel Detected\n"); -				dev_priv->panel_id = PYR_CMD; -				panel_id = PYR_CMD; -			} else if (dev_priv->gct_data.bpi == 0) { -				dev_info(dev->dev, "[GFX] TMD Panel Detected.\n"); -				dev_priv->panel_id = TMD_VID; -				panel_id = TMD_VID; -			} else { -				dev_info(dev->dev, "[GFX] Default Panel (TPO)\n"); -				dev_priv->panel_id = TPO_CMD; -				panel_id = TPO_CMD; -			} -		} else { -			dev_info(dev->dev, "[GFX] Panel Parameter Passed in through cmd line\n"); -			dev_priv->panel_id = panel_id; -		} -	} -} - -int mid_chip_setup(struct drm_device *dev) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; -	mid_get_fuse_settings(dev); -	mid_get_vbt_data(dev_priv); -	mid_get_pci_revID(dev_priv); -	return 0; -} diff --git a/drivers/staging/gma500/mid_bios.h b/drivers/staging/gma500/mid_bios.h deleted file mode 100644 index 00e7d564b7e..00000000000 --- a/drivers/staging/gma500/mid_bios.h +++ /dev/null @@ -1,21 +0,0 @@ -/************************************************************************** - * Copyright (c) 2011, Intel Corporation. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - **************************************************************************/ - -extern int mid_chip_setup(struct drm_device *dev); - diff --git a/drivers/staging/gma500/mmu.c b/drivers/staging/gma500/mmu.c deleted file mode 100644 index c904d73b1de..00000000000 --- a/drivers/staging/gma500/mmu.c +++ /dev/null @@ -1,858 +0,0 @@ -/************************************************************************** - * Copyright (c) 2007, Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - **************************************************************************/ -#include <drm/drmP.h> -#include "psb_drv.h" -#include "psb_reg.h" - -/* - * Code for the SGX MMU: - */ - -/* - * clflush on one processor only: - * clflush should apparently flush the cache line on all processors in an - * SMP system. - */ - -/* - * kmap atomic: - * The usage of the slots must be completely encapsulated within a spinlock, and - * no other functions that may be using the locks for other purposed may be - * called from within the locked region. - * Since the slots are per processor, this will guarantee that we are the only - * user. - */ - -/* - * TODO: Inserting ptes from an interrupt handler: - * This may be desirable for some SGX functionality where the GPU can fault in - * needed pages. For that, we need to make an atomic insert_pages function, that - * may fail. - * If it fails, the caller need to insert the page using a workqueue function, - * but on average it should be fast. - */ - -struct psb_mmu_driver { -	/* protects driver- and pd structures. Always take in read mode -	 * before taking the page table spinlock. -	 */ -	struct rw_semaphore sem; - -	/* protects page tables, directory tables and pt tables. -	 * and pt structures. -	 */ -	spinlock_t lock; - -	atomic_t needs_tlbflush; - -	uint8_t __iomem *register_map; -	struct psb_mmu_pd *default_pd; -	/*uint32_t bif_ctrl;*/ -	int has_clflush; -	int clflush_add; -	unsigned long clflush_mask; - -	struct drm_psb_private *dev_priv; -}; - -struct psb_mmu_pd; - -struct psb_mmu_pt { -	struct psb_mmu_pd *pd; -	uint32_t index; -	uint32_t count; -	struct page *p; -	uint32_t *v; -}; - -struct psb_mmu_pd { -	struct psb_mmu_driver *driver; -	int hw_context; -	struct psb_mmu_pt **tables; -	struct page *p; -	struct page *dummy_pt; -	struct page *dummy_page; -	uint32_t pd_mask; -	uint32_t invalid_pde; -	uint32_t invalid_pte; -}; - -static inline uint32_t psb_mmu_pt_index(uint32_t offset) -{ -	return (offset >> PSB_PTE_SHIFT) & 0x3FF; -} - -static inline uint32_t psb_mmu_pd_index(uint32_t offset) -{ -	return offset >> PSB_PDE_SHIFT; -} - -static inline void psb_clflush(void *addr) -{ -	__asm__ __volatile__("clflush (%0)\n" : : "r"(addr) : "memory"); -} - -static inline void psb_mmu_clflush(struct psb_mmu_driver *driver, -				   void *addr) -{ -	if (!driver->has_clflush) -		return; - -	mb(); -	psb_clflush(addr); -	mb(); -} - -static void psb_page_clflush(struct psb_mmu_driver *driver, struct page* page) -{ -	uint32_t clflush_add = driver->clflush_add >> PAGE_SHIFT; -	uint32_t clflush_count = PAGE_SIZE / clflush_add; -	int i; -	uint8_t *clf; - -	clf = kmap_atomic(page, KM_USER0); -	mb(); -	for (i = 0; i < clflush_count; ++i) { -		psb_clflush(clf); -		clf += clflush_add; -	} -	mb(); -	kunmap_atomic(clf, KM_USER0); -} - -static void psb_pages_clflush(struct psb_mmu_driver *driver, -				struct page *page[], unsigned long num_pages) -{ -	int i; - -	if (!driver->has_clflush) -		return ; - -	for (i = 0; i < num_pages; i++) -		psb_page_clflush(driver, *page++); -} - -static void psb_mmu_flush_pd_locked(struct psb_mmu_driver *driver, -				    int force) -{ -	atomic_set(&driver->needs_tlbflush, 0); -} - -static void psb_mmu_flush_pd(struct psb_mmu_driver *driver, int force) -{ -	down_write(&driver->sem); -	psb_mmu_flush_pd_locked(driver, force); -	up_write(&driver->sem); -} - -void psb_mmu_flush(struct psb_mmu_driver *driver, int rc_prot) -{ -	if (rc_prot) -		down_write(&driver->sem); -	if (rc_prot) -		up_write(&driver->sem); -} - -void psb_mmu_set_pd_context(struct psb_mmu_pd *pd, int hw_context) -{ -	/*ttm_tt_cache_flush(&pd->p, 1);*/ -	psb_pages_clflush(pd->driver, &pd->p, 1); -	down_write(&pd->driver->sem); -	wmb(); -	psb_mmu_flush_pd_locked(pd->driver, 1); -	pd->hw_context = hw_context; -	up_write(&pd->driver->sem); - -} - -static inline unsigned long psb_pd_addr_end(unsigned long addr, -					    unsigned long end) -{ - -	addr = (addr + PSB_PDE_MASK + 1) & ~PSB_PDE_MASK; -	return (addr < end) ? addr : end; -} - -static inline uint32_t psb_mmu_mask_pte(uint32_t pfn, int type) -{ -	uint32_t mask = PSB_PTE_VALID; - -	if (type & PSB_MMU_CACHED_MEMORY) -		mask |= PSB_PTE_CACHED; -	if (type & PSB_MMU_RO_MEMORY) -		mask |= PSB_PTE_RO; -	if (type & PSB_MMU_WO_MEMORY) -		mask |= PSB_PTE_WO; - -	return (pfn << PAGE_SHIFT) | mask; -} - -struct psb_mmu_pd *psb_mmu_alloc_pd(struct psb_mmu_driver *driver, -				    int trap_pagefaults, int invalid_type) -{ -	struct psb_mmu_pd *pd = kmalloc(sizeof(*pd), GFP_KERNEL); -	uint32_t *v; -	int i; - -	if (!pd) -		return NULL; - -	pd->p = alloc_page(GFP_DMA32); -	if (!pd->p) -		goto out_err1; -	pd->dummy_pt = alloc_page(GFP_DMA32); -	if (!pd->dummy_pt) -		goto out_err2; -	pd->dummy_page = alloc_page(GFP_DMA32); -	if (!pd->dummy_page) -		goto out_err3; - -	if (!trap_pagefaults) { -		pd->invalid_pde = -		    psb_mmu_mask_pte(page_to_pfn(pd->dummy_pt), -				     invalid_type); -		pd->invalid_pte = -		    psb_mmu_mask_pte(page_to_pfn(pd->dummy_page), -				     invalid_type); -	} else { -		pd->invalid_pde = 0; -		pd->invalid_pte = 0; -	} - -	v = kmap(pd->dummy_pt); -	for (i = 0; i < (PAGE_SIZE / sizeof(uint32_t)); ++i) -		v[i] = pd->invalid_pte; - -	kunmap(pd->dummy_pt); - -	v = kmap(pd->p); -	for (i = 0; i < (PAGE_SIZE / sizeof(uint32_t)); ++i) -		v[i] = pd->invalid_pde; - -	kunmap(pd->p); - -	clear_page(kmap(pd->dummy_page)); -	kunmap(pd->dummy_page); - -	pd->tables = vmalloc_user(sizeof(struct psb_mmu_pt *) * 1024); -	if (!pd->tables) -		goto out_err4; - -	pd->hw_context = -1; -	pd->pd_mask = PSB_PTE_VALID; -	pd->driver = driver; - -	return pd; - -out_err4: -	__free_page(pd->dummy_page); -out_err3: -	__free_page(pd->dummy_pt); -out_err2: -	__free_page(pd->p); -out_err1: -	kfree(pd); -	return NULL; -} - -void psb_mmu_free_pt(struct psb_mmu_pt *pt) -{ -	__free_page(pt->p); -	kfree(pt); -} - -void psb_mmu_free_pagedir(struct psb_mmu_pd *pd) -{ -	struct psb_mmu_driver *driver = pd->driver; -	struct psb_mmu_pt *pt; -	int i; - -	down_write(&driver->sem); -	if (pd->hw_context != -1) -		psb_mmu_flush_pd_locked(driver, 1); - -	/* Should take the spinlock here, but we don't need to do that -	   since we have the semaphore in write mode. */ - -	for (i = 0; i < 1024; ++i) { -		pt = pd->tables[i]; -		if (pt) -			psb_mmu_free_pt(pt); -	} - -	vfree(pd->tables); -	__free_page(pd->dummy_page); -	__free_page(pd->dummy_pt); -	__free_page(pd->p); -	kfree(pd); -	up_write(&driver->sem); -} - -static struct psb_mmu_pt *psb_mmu_alloc_pt(struct psb_mmu_pd *pd) -{ -	struct psb_mmu_pt *pt = kmalloc(sizeof(*pt), GFP_KERNEL); -	void *v; -	uint32_t clflush_add = pd->driver->clflush_add >> PAGE_SHIFT; -	uint32_t clflush_count = PAGE_SIZE / clflush_add; -	spinlock_t *lock = &pd->driver->lock; -	uint8_t *clf; -	uint32_t *ptes; -	int i; - -	if (!pt) -		return NULL; - -	pt->p = alloc_page(GFP_DMA32); -	if (!pt->p) { -		kfree(pt); -		return NULL; -	} - -	spin_lock(lock); - -	v = kmap_atomic(pt->p, KM_USER0); -	clf = (uint8_t *) v; -	ptes = (uint32_t *) v; -	for (i = 0; i < (PAGE_SIZE / sizeof(uint32_t)); ++i) -		*ptes++ = pd->invalid_pte; - - -	if (pd->driver->has_clflush && pd->hw_context != -1) { -		mb(); -		for (i = 0; i < clflush_count; ++i) { -			psb_clflush(clf); -			clf += clflush_add; -		} -		mb(); -	} - -	kunmap_atomic(v, KM_USER0); -	spin_unlock(lock); - -	pt->count = 0; -	pt->pd = pd; -	pt->index = 0; - -	return pt; -} - -struct psb_mmu_pt *psb_mmu_pt_alloc_map_lock(struct psb_mmu_pd *pd, -					     unsigned long addr) -{ -	uint32_t index = psb_mmu_pd_index(addr); -	struct psb_mmu_pt *pt; -	uint32_t *v; -	spinlock_t *lock = &pd->driver->lock; - -	spin_lock(lock); -	pt = pd->tables[index]; -	while (!pt) { -		spin_unlock(lock); -		pt = psb_mmu_alloc_pt(pd); -		if (!pt) -			return NULL; -		spin_lock(lock); - -		if (pd->tables[index]) { -			spin_unlock(lock); -			psb_mmu_free_pt(pt); -			spin_lock(lock); -			pt = pd->tables[index]; -			continue; -		} - -		v = kmap_atomic(pd->p, KM_USER0); -		pd->tables[index] = pt; -		v[index] = (page_to_pfn(pt->p) << 12) | pd->pd_mask; -		pt->index = index; -		kunmap_atomic((void *) v, KM_USER0); - -		if (pd->hw_context != -1) { -			psb_mmu_clflush(pd->driver, (void *) &v[index]); -			atomic_set(&pd->driver->needs_tlbflush, 1); -		} -	} -	pt->v = kmap_atomic(pt->p, KM_USER0); -	return pt; -} - -static struct psb_mmu_pt *psb_mmu_pt_map_lock(struct psb_mmu_pd *pd, -					      unsigned long addr) -{ -	uint32_t index = psb_mmu_pd_index(addr); -	struct psb_mmu_pt *pt; -	spinlock_t *lock = &pd->driver->lock; - -	spin_lock(lock); -	pt = pd->tables[index]; -	if (!pt) { -		spin_unlock(lock); -		return NULL; -	} -	pt->v = kmap_atomic(pt->p, KM_USER0); -	return pt; -} - -static void psb_mmu_pt_unmap_unlock(struct psb_mmu_pt *pt) -{ -	struct psb_mmu_pd *pd = pt->pd; -	uint32_t *v; - -	kunmap_atomic(pt->v, KM_USER0); -	if (pt->count == 0) { -		v = kmap_atomic(pd->p, KM_USER0); -		v[pt->index] = pd->invalid_pde; -		pd->tables[pt->index] = NULL; - -		if (pd->hw_context != -1) { -			psb_mmu_clflush(pd->driver, -					(void *) &v[pt->index]); -			atomic_set(&pd->driver->needs_tlbflush, 1); -		} -		kunmap_atomic(pt->v, KM_USER0); -		spin_unlock(&pd->driver->lock); -		psb_mmu_free_pt(pt); -		return; -	} -	spin_unlock(&pd->driver->lock); -} - -static inline void psb_mmu_set_pte(struct psb_mmu_pt *pt, -				   unsigned long addr, uint32_t pte) -{ -	pt->v[psb_mmu_pt_index(addr)] = pte; -} - -static inline void psb_mmu_invalidate_pte(struct psb_mmu_pt *pt, -					  unsigned long addr) -{ -	pt->v[psb_mmu_pt_index(addr)] = pt->pd->invalid_pte; -} - - -void psb_mmu_mirror_gtt(struct psb_mmu_pd *pd, -			uint32_t mmu_offset, uint32_t gtt_start, -			uint32_t gtt_pages) -{ -	uint32_t *v; -	uint32_t start = psb_mmu_pd_index(mmu_offset); -	struct psb_mmu_driver *driver = pd->driver; -	int num_pages = gtt_pages; - -	down_read(&driver->sem); -	spin_lock(&driver->lock); - -	v = kmap_atomic(pd->p, KM_USER0); -	v += start; - -	while (gtt_pages--) { -		*v++ = gtt_start | pd->pd_mask; -		gtt_start += PAGE_SIZE; -	} - -	/*ttm_tt_cache_flush(&pd->p, num_pages);*/ -	psb_pages_clflush(pd->driver, &pd->p, num_pages); -	kunmap_atomic(v, KM_USER0); -	spin_unlock(&driver->lock); - -	if (pd->hw_context != -1) -		atomic_set(&pd->driver->needs_tlbflush, 1); - -	up_read(&pd->driver->sem); -	psb_mmu_flush_pd(pd->driver, 0); -} - -struct psb_mmu_pd *psb_mmu_get_default_pd(struct psb_mmu_driver *driver) -{ -	struct psb_mmu_pd *pd; - -	/* down_read(&driver->sem); */ -	pd = driver->default_pd; -	/* up_read(&driver->sem); */ - -	return pd; -} - -/* Returns the physical address of the PD shared by sgx/msvdx */ -uint32_t psb_get_default_pd_addr(struct psb_mmu_driver *driver) -{ -	struct psb_mmu_pd *pd; - -	pd = psb_mmu_get_default_pd(driver); -	return page_to_pfn(pd->p) << PAGE_SHIFT; -} - -void psb_mmu_driver_takedown(struct psb_mmu_driver *driver) -{ -	psb_mmu_free_pagedir(driver->default_pd); -	kfree(driver); -} - -struct psb_mmu_driver *psb_mmu_driver_init(uint8_t __iomem * registers, -					int trap_pagefaults, -					int invalid_type, -					struct drm_psb_private *dev_priv) -{ -	struct psb_mmu_driver *driver; - -	driver = kmalloc(sizeof(*driver), GFP_KERNEL); - -	if (!driver) -		return NULL; -	driver->dev_priv = dev_priv; - -	driver->default_pd = psb_mmu_alloc_pd(driver, trap_pagefaults, -					      invalid_type); -	if (!driver->default_pd) -		goto out_err1; - -	spin_lock_init(&driver->lock); -	init_rwsem(&driver->sem); -	down_write(&driver->sem); -	driver->register_map = registers; -	atomic_set(&driver->needs_tlbflush, 1); - -	driver->has_clflush = 0; - -	if (boot_cpu_has(X86_FEATURE_CLFLSH)) { -		uint32_t tfms, misc, cap0, cap4, clflush_size; - -		/* -		 * clflush size is determined at kernel setup for x86_64 -		 *  but not for i386. We have to do it here. -		 */ - -		cpuid(0x00000001, &tfms, &misc, &cap0, &cap4); -		clflush_size = ((misc >> 8) & 0xff) * 8; -		driver->has_clflush = 1; -		driver->clflush_add = -		    PAGE_SIZE * clflush_size / sizeof(uint32_t); -		driver->clflush_mask = driver->clflush_add - 1; -		driver->clflush_mask = ~driver->clflush_mask; -	} - -	up_write(&driver->sem); -	return driver; - -out_err1: -	kfree(driver); -	return NULL; -} - -static void psb_mmu_flush_ptes(struct psb_mmu_pd *pd, -			       unsigned long address, uint32_t num_pages, -			       uint32_t desired_tile_stride, -			       uint32_t hw_tile_stride) -{ -	struct psb_mmu_pt *pt; -	uint32_t rows = 1; -	uint32_t i; -	unsigned long addr; -	unsigned long end; -	unsigned long next; -	unsigned long add; -	unsigned long row_add; -	unsigned long clflush_add = pd->driver->clflush_add; -	unsigned long clflush_mask = pd->driver->clflush_mask; - -	if (!pd->driver->has_clflush) { -		/*ttm_tt_cache_flush(&pd->p, num_pages);*/ -		psb_pages_clflush(pd->driver, &pd->p, num_pages); -		return; -	} - -	if (hw_tile_stride) -		rows = num_pages / desired_tile_stride; -	else -		desired_tile_stride = num_pages; - -	add = desired_tile_stride << PAGE_SHIFT; -	row_add = hw_tile_stride << PAGE_SHIFT; -	mb(); -	for (i = 0; i < rows; ++i) { - -		addr = address; -		end = addr + add; - -		do { -			next = psb_pd_addr_end(addr, end); -			pt = psb_mmu_pt_map_lock(pd, addr); -			if (!pt) -				continue; -			do { -				psb_clflush(&pt->v -					    [psb_mmu_pt_index(addr)]); -			} while (addr += -				 clflush_add, -				 (addr & clflush_mask) < next); - -			psb_mmu_pt_unmap_unlock(pt); -		} while (addr = next, next != end); -		address += row_add; -	} -	mb(); -} - -void psb_mmu_remove_pfn_sequence(struct psb_mmu_pd *pd, -				 unsigned long address, uint32_t num_pages) -{ -	struct psb_mmu_pt *pt; -	unsigned long addr; -	unsigned long end; -	unsigned long next; -	unsigned long f_address = address; - -	down_read(&pd->driver->sem); - -	addr = address; -	end = addr + (num_pages << PAGE_SHIFT); - -	do { -		next = psb_pd_addr_end(addr, end); -		pt = psb_mmu_pt_alloc_map_lock(pd, addr); -		if (!pt) -			goto out; -		do { -			psb_mmu_invalidate_pte(pt, addr); -			--pt->count; -		} while (addr += PAGE_SIZE, addr < next); -		psb_mmu_pt_unmap_unlock(pt); - -	} while (addr = next, next != end); - -out: -	if (pd->hw_context != -1) -		psb_mmu_flush_ptes(pd, f_address, num_pages, 1, 1); - -	up_read(&pd->driver->sem); - -	if (pd->hw_context != -1) -		psb_mmu_flush(pd->driver, 0); - -	return; -} - -void psb_mmu_remove_pages(struct psb_mmu_pd *pd, unsigned long address, -			  uint32_t num_pages, uint32_t desired_tile_stride, -			  uint32_t hw_tile_stride) -{ -	struct psb_mmu_pt *pt; -	uint32_t rows = 1; -	uint32_t i; -	unsigned long addr; -	unsigned long end; -	unsigned long next; -	unsigned long add; -	unsigned long row_add; -	unsigned long f_address = address; - -	if (hw_tile_stride) -		rows = num_pages / desired_tile_stride; -	else -		desired_tile_stride = num_pages; - -	add = desired_tile_stride << PAGE_SHIFT; -	row_add = hw_tile_stride << PAGE_SHIFT; - -	/* down_read(&pd->driver->sem); */ - -	/* Make sure we only need to flush this processor's cache */ - -	for (i = 0; i < rows; ++i) { - -		addr = address; -		end = addr + add; - -		do { -			next = psb_pd_addr_end(addr, end); -			pt = psb_mmu_pt_map_lock(pd, addr); -			if (!pt) -				continue; -			do { -				psb_mmu_invalidate_pte(pt, addr); -				--pt->count; - -			} while (addr += PAGE_SIZE, addr < next); -			psb_mmu_pt_unmap_unlock(pt); - -		} while (addr = next, next != end); -		address += row_add; -	} -	if (pd->hw_context != -1) -		psb_mmu_flush_ptes(pd, f_address, num_pages, -				   desired_tile_stride, hw_tile_stride); - -	/* up_read(&pd->driver->sem); */ - -	if (pd->hw_context != -1) -		psb_mmu_flush(pd->driver, 0); -} - -int psb_mmu_insert_pfn_sequence(struct psb_mmu_pd *pd, uint32_t start_pfn, -				unsigned long address, uint32_t num_pages, -				int type) -{ -	struct psb_mmu_pt *pt; -	uint32_t pte; -	unsigned long addr; -	unsigned long end; -	unsigned long next; -	unsigned long f_address = address; -	int ret = 0; - -	down_read(&pd->driver->sem); - -	addr = address; -	end = addr + (num_pages << PAGE_SHIFT); - -	do { -		next = psb_pd_addr_end(addr, end); -		pt = psb_mmu_pt_alloc_map_lock(pd, addr); -		if (!pt) { -			ret = -ENOMEM; -			goto out; -		} -		do { -			pte = psb_mmu_mask_pte(start_pfn++, type); -			psb_mmu_set_pte(pt, addr, pte); -			pt->count++; -		} while (addr += PAGE_SIZE, addr < next); -		psb_mmu_pt_unmap_unlock(pt); - -	} while (addr = next, next != end); - -out: -	if (pd->hw_context != -1) -		psb_mmu_flush_ptes(pd, f_address, num_pages, 1, 1); - -	up_read(&pd->driver->sem); - -	if (pd->hw_context != -1) -		psb_mmu_flush(pd->driver, 1); - -	return ret; -} - -int psb_mmu_insert_pages(struct psb_mmu_pd *pd, struct page **pages, -			 unsigned long address, uint32_t num_pages, -			 uint32_t desired_tile_stride, -			 uint32_t hw_tile_stride, int type) -{ -	struct psb_mmu_pt *pt; -	uint32_t rows = 1; -	uint32_t i; -	uint32_t pte; -	unsigned long addr; -	unsigned long end; -	unsigned long next; -	unsigned long add; -	unsigned long row_add; -	unsigned long f_address = address; -	int ret = 0; - -	if (hw_tile_stride) { -		if (num_pages % desired_tile_stride != 0) -			return -EINVAL; -		rows = num_pages / desired_tile_stride; -	} else { -		desired_tile_stride = num_pages; -	} - -	add = desired_tile_stride << PAGE_SHIFT; -	row_add = hw_tile_stride << PAGE_SHIFT; - -	down_read(&pd->driver->sem); - -	for (i = 0; i < rows; ++i) { - -		addr = address; -		end = addr + add; - -		do { -			next = psb_pd_addr_end(addr, end); -			pt = psb_mmu_pt_alloc_map_lock(pd, addr); -			if (!pt) { -				ret = -ENOMEM; -				goto out; -			} -			do { -				pte = -				    psb_mmu_mask_pte(page_to_pfn(*pages++), -						     type); -				psb_mmu_set_pte(pt, addr, pte); -				pt->count++; -			} while (addr += PAGE_SIZE, addr < next); -			psb_mmu_pt_unmap_unlock(pt); - -		} while (addr = next, next != end); - -		address += row_add; -	} -out: -	if (pd->hw_context != -1) -		psb_mmu_flush_ptes(pd, f_address, num_pages, -				   desired_tile_stride, hw_tile_stride); - -	up_read(&pd->driver->sem); - -	if (pd->hw_context != -1) -		psb_mmu_flush(pd->driver, 1); - -	return ret; -} - -int psb_mmu_virtual_to_pfn(struct psb_mmu_pd *pd, uint32_t virtual, -			   unsigned long *pfn) -{ -	int ret; -	struct psb_mmu_pt *pt; -	uint32_t tmp; -	spinlock_t *lock = &pd->driver->lock; - -	down_read(&pd->driver->sem); -	pt = psb_mmu_pt_map_lock(pd, virtual); -	if (!pt) { -		uint32_t *v; - -		spin_lock(lock); -		v = kmap_atomic(pd->p, KM_USER0); -		tmp = v[psb_mmu_pd_index(virtual)]; -		kunmap_atomic(v, KM_USER0); -		spin_unlock(lock); - -		if (tmp != pd->invalid_pde || !(tmp & PSB_PTE_VALID) || -		    !(pd->invalid_pte & PSB_PTE_VALID)) { -			ret = -EINVAL; -			goto out; -		} -		ret = 0; -		*pfn = pd->invalid_pte >> PAGE_SHIFT; -		goto out; -	} -	tmp = pt->v[psb_mmu_pt_index(virtual)]; -	if (!(tmp & PSB_PTE_VALID)) { -		ret = -EINVAL; -	} else { -		ret = 0; -		*pfn = tmp >> PAGE_SHIFT; -	} -	psb_mmu_pt_unmap_unlock(pt); -out: -	up_read(&pd->driver->sem); -	return ret; -} diff --git a/drivers/staging/gma500/mrst.h b/drivers/staging/gma500/mrst.h deleted file mode 100644 index b563dbc7310..00000000000 --- a/drivers/staging/gma500/mrst.h +++ /dev/null @@ -1,252 +0,0 @@ -/************************************************************************** - * Copyright (c) 2007-2011, Intel Corporation. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - **************************************************************************/ - -/* MID device specific descriptors */ - -struct mrst_vbt { -	s8 signature[4];	/*4 bytes,"$GCT" */ -	u8 revision; -	u8 size; -	u8 checksum; -	void *mrst_gct; -} __packed; - -struct mrst_timing_info { -	u16 pixel_clock; -	u8 hactive_lo; -	u8 hblank_lo; -	u8 hblank_hi:4; -	u8 hactive_hi:4; -	u8 vactive_lo; -	u8 vblank_lo; -	u8 vblank_hi:4; -	u8 vactive_hi:4; -	u8 hsync_offset_lo; -	u8 hsync_pulse_width_lo; -	u8 vsync_pulse_width_lo:4; -	u8 vsync_offset_lo:4; -	u8 vsync_pulse_width_hi:2; -	u8 vsync_offset_hi:2; -	u8 hsync_pulse_width_hi:2; -	u8 hsync_offset_hi:2; -	u8 width_mm_lo; -	u8 height_mm_lo; -	u8 height_mm_hi:4; -	u8 width_mm_hi:4; -	u8 hborder; -	u8 vborder; -	u8 unknown0:1; -	u8 hsync_positive:1; -	u8 vsync_positive:1; -	u8 separate_sync:2; -	u8 stereo:1; -	u8 unknown6:1; -	u8 interlaced:1; -} __packed; - -struct gct_r10_timing_info { -	u16 pixel_clock; -	u32 hactive_lo:8; -	u32 hactive_hi:4; -	u32 hblank_lo:8; -	u32 hblank_hi:4; -	u32 hsync_offset_lo:8; -	u16 hsync_offset_hi:2; -	u16 hsync_pulse_width_lo:8; -	u16 hsync_pulse_width_hi:2; -	u16 hsync_positive:1; -	u16 rsvd_1:3; -	u8  vactive_lo:8; -	u16 vactive_hi:4; -	u16 vblank_lo:8; -	u16 vblank_hi:4; -	u16 vsync_offset_lo:4; -	u16 vsync_offset_hi:2; -	u16 vsync_pulse_width_lo:4; -	u16 vsync_pulse_width_hi:2; -	u16 vsync_positive:1; -	u16 rsvd_2:3; -} __packed; - -struct mrst_panel_descriptor_v1 { -	u32 Panel_Port_Control; /* 1 dword, Register 0x61180 if LVDS */ -				/* 0x61190 if MIPI */ -	u32 Panel_Power_On_Sequencing;/*1 dword,Register 0x61208,*/ -	u32 Panel_Power_Off_Sequencing;/*1 dword,Register 0x6120C,*/ -	u32 Panel_Power_Cycle_Delay_and_Reference_Divisor;/* 1 dword */ -						/* Register 0x61210 */ -	struct mrst_timing_info DTD;/*18 bytes, Standard definition */ -	u16 Panel_Backlight_Inverter_Descriptor;/* 16 bits, as follows */ -				/* Bit 0, Frequency, 15 bits,0 - 32767Hz */ -			/* Bit 15, Polarity, 1 bit, 0: Normal, 1: Inverted */ -	u16 Panel_MIPI_Display_Descriptor; -			/*16 bits, Defined as follows: */ -			/* if MIPI, 0x0000 if LVDS */ -			/* Bit 0, Type, 2 bits, */ -			/* 0: Type-1, */ -			/* 1: Type-2, */ -			/* 2: Type-3, */ -			/* 3: Type-4 */ -			/* Bit 2, Pixel Format, 4 bits */ -			/* Bit0: 16bpp (not supported in LNC), */ -			/* Bit1: 18bpp loosely packed, */ -			/* Bit2: 18bpp packed, */ -			/* Bit3: 24bpp */ -			/* Bit 6, Reserved, 2 bits, 00b */ -			/* Bit 8, Minimum Supported Frame Rate, 6 bits, 0 - 63Hz */ -			/* Bit 14, Reserved, 2 bits, 00b */ -} __packed; - -struct mrst_panel_descriptor_v2 { -	u32 Panel_Port_Control; /* 1 dword, Register 0x61180 if LVDS */ -				/* 0x61190 if MIPI */ -	u32 Panel_Power_On_Sequencing;/*1 dword,Register 0x61208,*/ -	u32 Panel_Power_Off_Sequencing;/*1 dword,Register 0x6120C,*/ -	u8 Panel_Power_Cycle_Delay_and_Reference_Divisor;/* 1 byte */ -						/* Register 0x61210 */ -	struct mrst_timing_info DTD;/*18 bytes, Standard definition */ -	u16 Panel_Backlight_Inverter_Descriptor;/*16 bits, as follows*/ -				/*Bit 0, Frequency, 16 bits, 0 - 32767Hz*/ -	u8 Panel_Initial_Brightness;/* [7:0] 0 - 100% */ -			/*Bit 7, Polarity, 1 bit,0: Normal, 1: Inverted*/ -	u16 Panel_MIPI_Display_Descriptor; -			/*16 bits, Defined as follows: */ -			/* if MIPI, 0x0000 if LVDS */ -			/* Bit 0, Type, 2 bits, */ -			/* 0: Type-1, */ -			/* 1: Type-2, */ -			/* 2: Type-3, */ -			/* 3: Type-4 */ -			/* Bit 2, Pixel Format, 4 bits */ -			/* Bit0: 16bpp (not supported in LNC), */ -			/* Bit1: 18bpp loosely packed, */ -			/* Bit2: 18bpp packed, */ -			/* Bit3: 24bpp */ -			/* Bit 6, Reserved, 2 bits, 00b */ -			/* Bit 8, Minimum Supported Frame Rate, 6 bits, 0 - 63Hz */ -			/* Bit 14, Reserved, 2 bits, 00b */ -} __packed; - -union mrst_panel_rx { -	struct { -		u16 NumberOfLanes:2; /*Num of Lanes, 2 bits,0 = 1 lane,*/ -			/* 1 = 2 lanes, 2 = 3 lanes, 3 = 4 lanes. */ -		u16 MaxLaneFreq:3; /* 0: 100MHz, 1: 200MHz, 2: 300MHz, */ -		/*3: 400MHz, 4: 500MHz, 5: 600MHz, 6: 700MHz, 7: 800MHz.*/ -		u16 SupportedVideoTransferMode:2; /*0: Non-burst only */ -					/* 1: Burst and non-burst */ -					/* 2/3: Reserved */ -		u16 HSClkBehavior:1; /*0: Continuous, 1: Non-continuous*/ -		u16 DuoDisplaySupport:1; /*1 bit,0: No, 1: Yes*/ -		u16 ECC_ChecksumCapabilities:1;/*1 bit,0: No, 1: Yes*/ -		u16 BidirectionalCommunication:1;/*1 bit,0: No, 1: Yes */ -		u16 Rsvd:5;/*5 bits,00000b */ -	} panelrx; -	u16 panel_receiver; -} __packed; - -struct mrst_gct_v1 { -	union { /*8 bits,Defined as follows: */ -		struct { -			u8 PanelType:4; /*4 bits, Bit field for panels*/ -					/* 0 - 3: 0 = LVDS, 1 = MIPI*/ -					/*2 bits,Specifies which of the*/ -			u8 BootPanelIndex:2; -					/* 4 panels to use by default*/ -			u8 BootMIPI_DSI_RxIndex:2;/*Specifies which of*/ -					/* the 4 MIPI DSI receivers to use*/ -		} PD; -		u8 PanelDescriptor; -	}; -	struct mrst_panel_descriptor_v1 panel[4];/*panel descrs,38 bytes each*/ -	union mrst_panel_rx panelrx[4]; /* panel receivers*/ -} __packed; - -struct mrst_gct_v2 { -	union { /*8 bits,Defined as follows: */ -		struct { -			u8 PanelType:4; /*4 bits, Bit field for panels*/ -					/* 0 - 3: 0 = LVDS, 1 = MIPI*/ -					/*2 bits,Specifies which of the*/ -			u8 BootPanelIndex:2; -					/* 4 panels to use by default*/ -			u8 BootMIPI_DSI_RxIndex:2;/*Specifies which of*/ -					/* the 4 MIPI DSI receivers to use*/ -		} PD; -		u8 PanelDescriptor; -	}; -	struct mrst_panel_descriptor_v2 panel[4];/*panel descrs,38 bytes each*/ -	union mrst_panel_rx panelrx[4]; /* panel receivers*/ -} __packed; - -struct mrst_gct_data { -	u8 bpi; /* boot panel index, number of panel used during boot */ -	u8 pt; /* panel type, 4 bit field, 0=lvds, 1=mipi */ -	struct mrst_timing_info DTD; /* timing info for the selected panel */ -	u32 Panel_Port_Control; -	u32 PP_On_Sequencing;/*1 dword,Register 0x61208,*/ -	u32 PP_Off_Sequencing;/*1 dword,Register 0x6120C,*/ -	u32 PP_Cycle_Delay; -	u16 Panel_Backlight_Inverter_Descriptor; -	u16 Panel_MIPI_Display_Descriptor; -} __packed; - -#define MODE_SETTING_IN_CRTC		0x1 -#define MODE_SETTING_IN_ENCODER		0x2 -#define MODE_SETTING_ON_GOING		0x3 -#define MODE_SETTING_IN_DSR		0x4 -#define MODE_SETTING_ENCODER_DONE	0x8 - -#define GCT_R10_HEADER_SIZE		16 -#define GCT_R10_DISPLAY_DESC_SIZE	28 - -/* - *	Moorestown HDMI interfaces - */ - -struct mrst_hdmi_dev { -	struct pci_dev *dev; -	void __iomem *regs; -	unsigned int mmio, mmio_len; -	int dpms_mode; -	struct hdmi_i2c_dev *i2c_dev; - -	/* register state */ -	u32 saveDPLL_CTRL; -	u32 saveDPLL_DIV_CTRL; -	u32 saveDPLL_ADJUST; -	u32 saveDPLL_UPDATE; -	u32 saveDPLL_CLK_ENABLE; -	u32 savePCH_HTOTAL_B; -	u32 savePCH_HBLANK_B; -	u32 savePCH_HSYNC_B; -	u32 savePCH_VTOTAL_B; -	u32 savePCH_VBLANK_B; -	u32 savePCH_VSYNC_B; -	u32 savePCH_PIPEBCONF; -	u32 savePCH_PIPEBSRC; -}; - -extern void mrst_hdmi_setup(struct drm_device *dev); -extern void mrst_hdmi_teardown(struct drm_device *dev); -extern int  mrst_hdmi_i2c_init(struct pci_dev *dev); -extern void mrst_hdmi_i2c_exit(struct pci_dev *dev); -extern void mrst_hdmi_save(struct drm_device *dev); -extern void mrst_hdmi_restore(struct drm_device *dev); -extern void mrst_hdmi_init(struct drm_device *dev, struct psb_intel_mode_device *mode_dev); diff --git a/drivers/staging/gma500/mrst_crtc.c b/drivers/staging/gma500/mrst_crtc.c deleted file mode 100644 index 980837e37d8..00000000000 --- a/drivers/staging/gma500/mrst_crtc.c +++ /dev/null @@ -1,604 +0,0 @@ -/* - * Copyright © 2009 Intel Corporation - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include <linux/i2c.h> -#include <linux/pm_runtime.h> - -#include <drm/drmP.h> -#include "framebuffer.h" -#include "psb_drv.h" -#include "psb_intel_drv.h" -#include "psb_intel_reg.h" -#include "psb_intel_display.h" -#include "power.h" - -struct psb_intel_range_t { -	int min, max; -}; - -struct mrst_limit_t { -	struct psb_intel_range_t dot, m, p1; -}; - -struct mrst_clock_t { -	/* derived values */ -	int dot; -	int m; -	int p1; -}; - -#define MRST_LIMIT_LVDS_100L	    0 -#define MRST_LIMIT_LVDS_83	    1 -#define MRST_LIMIT_LVDS_100	    2 - -#define MRST_DOT_MIN		  19750 -#define MRST_DOT_MAX		  120000 -#define MRST_M_MIN_100L		    20 -#define MRST_M_MIN_100		    10 -#define MRST_M_MIN_83		    12 -#define MRST_M_MAX_100L		    34 -#define MRST_M_MAX_100		    17 -#define MRST_M_MAX_83		    20 -#define MRST_P1_MIN		    2 -#define MRST_P1_MAX_0		    7 -#define MRST_P1_MAX_1		    8 - -static const struct mrst_limit_t mrst_limits[] = { -	{			/* MRST_LIMIT_LVDS_100L */ -	 .dot = {.min = MRST_DOT_MIN, .max = MRST_DOT_MAX}, -	 .m = {.min = MRST_M_MIN_100L, .max = MRST_M_MAX_100L}, -	 .p1 = {.min = MRST_P1_MIN, .max = MRST_P1_MAX_1}, -	 }, -	{			/* MRST_LIMIT_LVDS_83L */ -	 .dot = {.min = MRST_DOT_MIN, .max = MRST_DOT_MAX}, -	 .m = {.min = MRST_M_MIN_83, .max = MRST_M_MAX_83}, -	 .p1 = {.min = MRST_P1_MIN, .max = MRST_P1_MAX_0}, -	 }, -	{			/* MRST_LIMIT_LVDS_100 */ -	 .dot = {.min = MRST_DOT_MIN, .max = MRST_DOT_MAX}, -	 .m = {.min = MRST_M_MIN_100, .max = MRST_M_MAX_100}, -	 .p1 = {.min = MRST_P1_MIN, .max = MRST_P1_MAX_1}, -	 }, -}; - -#define MRST_M_MIN	    10 -static const u32 mrst_m_converts[] = { -	0x2B, 0x15, 0x2A, 0x35, 0x1A, 0x0D, 0x26, 0x33, 0x19, 0x2C, -	0x36, 0x3B, 0x1D, 0x2E, 0x37, 0x1B, 0x2D, 0x16, 0x0B, 0x25, -	0x12, 0x09, 0x24, 0x32, 0x39, 0x1c, -}; - -static const struct mrst_limit_t *mrst_limit(struct drm_crtc *crtc) -{ -	const struct mrst_limit_t *limit = NULL; -	struct drm_device *dev = crtc->dev; -	struct drm_psb_private *dev_priv = dev->dev_private; - -	if (psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) -	    || psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_MIPI)) { -		switch (dev_priv->core_freq) { -		case 100: -			limit = &mrst_limits[MRST_LIMIT_LVDS_100L]; -			break; -		case 166: -			limit = &mrst_limits[MRST_LIMIT_LVDS_83]; -			break; -		case 200: -			limit = &mrst_limits[MRST_LIMIT_LVDS_100]; -			break; -		} -	} else { -		limit = NULL; -		dev_err(dev->dev, "mrst_limit Wrong display type.\n"); -	} - -	return limit; -} - -/** Derive the pixel clock for the given refclk and divisors for 8xx chips. */ -static void mrst_clock(int refclk, struct mrst_clock_t *clock) -{ -	clock->dot = (refclk * clock->m) / (14 * clock->p1); -} - -void mrstPrintPll(char *prefix, struct mrst_clock_t *clock) -{ -	pr_debug("%s: dotclock = %d,  m = %d, p1 = %d.\n", -	     prefix, clock->dot, clock->m, clock->p1); -} - -/** - * Returns a set of divisors for the desired target clock with the given refclk, - * or FALSE.  Divisor values are the actual divisors for - */ -static bool -mrstFindBestPLL(struct drm_crtc *crtc, int target, int refclk, -		struct mrst_clock_t *best_clock) -{ -	struct mrst_clock_t clock; -	const struct mrst_limit_t *limit = mrst_limit(crtc); -	int err = target; - -	memset(best_clock, 0, sizeof(*best_clock)); - -	for (clock.m = limit->m.min; clock.m <= limit->m.max; clock.m++) { -		for (clock.p1 = limit->p1.min; clock.p1 <= limit->p1.max; -		     clock.p1++) { -			int this_err; - -			mrst_clock(refclk, &clock); - -			this_err = abs(clock.dot - target); -			if (this_err < err) { -				*best_clock = clock; -				err = this_err; -			} -		} -	} -	dev_dbg(crtc->dev->dev, "mrstFindBestPLL err = %d.\n", err); -	return err != target; -} - -/** - * Sets the power management mode of the pipe and plane. - * - * This code should probably grow support for turning the cursor off and back - * on appropriately at the same time as we're turning the pipe off/on. - */ -static void mrst_crtc_dpms(struct drm_crtc *crtc, int mode) -{ -	struct drm_device *dev = crtc->dev; -	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); -	int pipe = psb_intel_crtc->pipe; -	int dpll_reg = (pipe == 0) ? MRST_DPLL_A : DPLL_B; -	int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; -	int dspbase_reg = (pipe == 0) ? MRST_DSPABASE : DSPBBASE; -	int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; -	u32 temp; -	bool enabled; - -	if (!gma_power_begin(dev, true)) -		return; - -	/* XXX: When our outputs are all unaware of DPMS modes other than off -	 * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC. -	 */ -	switch (mode) { -	case DRM_MODE_DPMS_ON: -	case DRM_MODE_DPMS_STANDBY: -	case DRM_MODE_DPMS_SUSPEND: -		/* Enable the DPLL */ -		temp = REG_READ(dpll_reg); -		if ((temp & DPLL_VCO_ENABLE) == 0) { -			REG_WRITE(dpll_reg, temp); -			REG_READ(dpll_reg); -			/* Wait for the clocks to stabilize. */ -			udelay(150); -			REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE); -			REG_READ(dpll_reg); -			/* Wait for the clocks to stabilize. */ -			udelay(150); -			REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE); -			REG_READ(dpll_reg); -			/* Wait for the clocks to stabilize. */ -			udelay(150); -		} -		/* Enable the pipe */ -		temp = REG_READ(pipeconf_reg); -		if ((temp & PIPEACONF_ENABLE) == 0) -			REG_WRITE(pipeconf_reg, temp | PIPEACONF_ENABLE); -		/* Enable the plane */ -		temp = REG_READ(dspcntr_reg); -		if ((temp & DISPLAY_PLANE_ENABLE) == 0) { -			REG_WRITE(dspcntr_reg, -				  temp | DISPLAY_PLANE_ENABLE); -			/* Flush the plane changes */ -			REG_WRITE(dspbase_reg, REG_READ(dspbase_reg)); -		} - -		psb_intel_crtc_load_lut(crtc); - -		/* Give the overlay scaler a chance to enable -		   if it's on this pipe */ -		/* psb_intel_crtc_dpms_video(crtc, true); TODO */ -		break; -	case DRM_MODE_DPMS_OFF: -		/* Give the overlay scaler a chance to disable -		 * if it's on this pipe */ -		/* psb_intel_crtc_dpms_video(crtc, FALSE); TODO */ - -		/* Disable the VGA plane that we never use */ -		REG_WRITE(VGACNTRL, VGA_DISP_DISABLE); -		/* Disable display plane */ -		temp = REG_READ(dspcntr_reg); -		if ((temp & DISPLAY_PLANE_ENABLE) != 0) { -			REG_WRITE(dspcntr_reg, -				  temp & ~DISPLAY_PLANE_ENABLE); -			/* Flush the plane changes */ -			REG_WRITE(dspbase_reg, REG_READ(dspbase_reg)); -			REG_READ(dspbase_reg); -		} - -		/* Next, disable display pipes */ -		temp = REG_READ(pipeconf_reg); -		if ((temp & PIPEACONF_ENABLE) != 0) { -			REG_WRITE(pipeconf_reg, temp & ~PIPEACONF_ENABLE); -			REG_READ(pipeconf_reg); -		} -		/* Wait for for the pipe disable to take effect. */ -		psb_intel_wait_for_vblank(dev); - -		temp = REG_READ(dpll_reg); -		if ((temp & DPLL_VCO_ENABLE) != 0) { -			REG_WRITE(dpll_reg, temp & ~DPLL_VCO_ENABLE); -			REG_READ(dpll_reg); -		} - -		/* Wait for the clocks to turn off. */ -		udelay(150); -		break; -	} - -	enabled = crtc->enabled && mode != DRM_MODE_DPMS_OFF; - -	/*Set FIFO Watermarks*/ -	REG_WRITE(DSPARB, 0x3FFF); -	REG_WRITE(DSPFW1, 0x3F88080A); -	REG_WRITE(DSPFW2, 0x0b060808); -	REG_WRITE(DSPFW3, 0x0); -	REG_WRITE(DSPFW4, 0x08030404); -	REG_WRITE(DSPFW5, 0x04040404); -	REG_WRITE(DSPFW6, 0x78); -	REG_WRITE(0x70400, REG_READ(0x70400) | 0x4000); -	/* Must write Bit 14 of the Chicken Bit Register */ - -	gma_power_end(dev); -} - -/** - * Return the pipe currently connected to the panel fitter, - * or -1 if the panel fitter is not present or not in use - */ -static int mrst_panel_fitter_pipe(struct drm_device *dev) -{ -	u32 pfit_control; - -	pfit_control = REG_READ(PFIT_CONTROL); - -	/* See if the panel fitter is in use */ -	if ((pfit_control & PFIT_ENABLE) == 0) -		return -1; -	return (pfit_control >> 29) & 3; -} - -static int mrst_crtc_mode_set(struct drm_crtc *crtc, -			      struct drm_display_mode *mode, -			      struct drm_display_mode *adjusted_mode, -			      int x, int y, -			      struct drm_framebuffer *old_fb) -{ -	struct drm_device *dev = crtc->dev; -	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); -	struct drm_psb_private *dev_priv = dev->dev_private; -	int pipe = psb_intel_crtc->pipe; -	int fp_reg = (pipe == 0) ? MRST_FPA0 : FPB0; -	int dpll_reg = (pipe == 0) ? MRST_DPLL_A : DPLL_B; -	int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; -	int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; -	int htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B; -	int hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B; -	int hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B; -	int vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B; -	int vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B; -	int vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B; -	int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC; -	int refclk = 0; -	struct mrst_clock_t clock; -	u32 dpll = 0, fp = 0, dspcntr, pipeconf; -	bool ok, is_sdvo = false; -	bool is_crt = false, is_lvds = false, is_tv = false; -	bool is_mipi = false; -	struct drm_mode_config *mode_config = &dev->mode_config; -	struct psb_intel_output *psb_intel_output = NULL; -	uint64_t scalingType = DRM_MODE_SCALE_FULLSCREEN; -	struct drm_encoder *encoder; - -	if (!gma_power_begin(dev, true)) -		return 0; - -	memcpy(&psb_intel_crtc->saved_mode, -		mode, -		sizeof(struct drm_display_mode)); -	memcpy(&psb_intel_crtc->saved_adjusted_mode, -		adjusted_mode, -		sizeof(struct drm_display_mode)); - -	list_for_each_entry(encoder, &mode_config->encoder_list, head) { - -		if (encoder->crtc != crtc) -			continue; - -		psb_intel_output = enc_to_psb_intel_output(encoder); -		switch (psb_intel_output->type) { -		case INTEL_OUTPUT_LVDS: -			is_lvds = true; -			break; -		case INTEL_OUTPUT_SDVO: -			is_sdvo = true; -			break; -		case INTEL_OUTPUT_TVOUT: -			is_tv = true; -			break; -		case INTEL_OUTPUT_ANALOG: -			is_crt = true; -			break; -		case INTEL_OUTPUT_MIPI: -			is_mipi = true; -			break; -		} -	} - -	/* Disable the VGA plane that we never use */ -	REG_WRITE(VGACNTRL, VGA_DISP_DISABLE); - -	/* Disable the panel fitter if it was on our pipe */ -	if (mrst_panel_fitter_pipe(dev) == pipe) -		REG_WRITE(PFIT_CONTROL, 0); - -	REG_WRITE(pipesrc_reg, -		  ((mode->crtc_hdisplay - 1) << 16) | -		  (mode->crtc_vdisplay - 1)); - -	if (psb_intel_output) -		drm_connector_property_get_value(&psb_intel_output->base, -			dev->mode_config.scaling_mode_property, &scalingType); - -	if (scalingType == DRM_MODE_SCALE_NO_SCALE) { -		/* Moorestown doesn't have register support for centering so -		 * we need to mess with the h/vblank and h/vsync start and -		 * ends to get centering */ -		int offsetX = 0, offsetY = 0; - -		offsetX = (adjusted_mode->crtc_hdisplay - -			   mode->crtc_hdisplay) / 2; -		offsetY = (adjusted_mode->crtc_vdisplay - -			   mode->crtc_vdisplay) / 2; - -		REG_WRITE(htot_reg, (mode->crtc_hdisplay - 1) | -			((adjusted_mode->crtc_htotal - 1) << 16)); -		REG_WRITE(vtot_reg, (mode->crtc_vdisplay - 1) | -			((adjusted_mode->crtc_vtotal - 1) << 16)); -		REG_WRITE(hblank_reg, -			(adjusted_mode->crtc_hblank_start - offsetX - 1) | -			((adjusted_mode->crtc_hblank_end - offsetX - 1) << 16)); -		REG_WRITE(hsync_reg, -			(adjusted_mode->crtc_hsync_start - offsetX - 1) | -			((adjusted_mode->crtc_hsync_end - offsetX - 1) << 16)); -		REG_WRITE(vblank_reg, -			(adjusted_mode->crtc_vblank_start - offsetY - 1) | -			((adjusted_mode->crtc_vblank_end - offsetY - 1) << 16)); -		REG_WRITE(vsync_reg, -			(adjusted_mode->crtc_vsync_start - offsetY - 1) | -			((adjusted_mode->crtc_vsync_end - offsetY - 1) << 16)); -	} else { -		REG_WRITE(htot_reg, (adjusted_mode->crtc_hdisplay - 1) | -			((adjusted_mode->crtc_htotal - 1) << 16)); -		REG_WRITE(vtot_reg, (adjusted_mode->crtc_vdisplay - 1) | -			((adjusted_mode->crtc_vtotal - 1) << 16)); -		REG_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) | -			((adjusted_mode->crtc_hblank_end - 1) << 16)); -		REG_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - 1) | -			((adjusted_mode->crtc_hsync_end - 1) << 16)); -		REG_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - 1) | -			((adjusted_mode->crtc_vblank_end - 1) << 16)); -		REG_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - 1) | -			((adjusted_mode->crtc_vsync_end - 1) << 16)); -	} - -	/* Flush the plane changes */ -	{ -		struct drm_crtc_helper_funcs *crtc_funcs = -		    crtc->helper_private; -		crtc_funcs->mode_set_base(crtc, x, y, old_fb); -	} - -	/* setup pipeconf */ -	pipeconf = REG_READ(pipeconf_reg); - -	/* Set up the display plane register */ -	dspcntr = REG_READ(dspcntr_reg); -	dspcntr |= DISPPLANE_GAMMA_ENABLE; - -	if (pipe == 0) -		dspcntr |= DISPPLANE_SEL_PIPE_A; -	else -		dspcntr |= DISPPLANE_SEL_PIPE_B; - -	dev_priv->dspcntr = dspcntr |= DISPLAY_PLANE_ENABLE; -	dev_priv->pipeconf = pipeconf |= PIPEACONF_ENABLE; - -	if (is_mipi) -		goto mrst_crtc_mode_set_exit; - -	refclk = dev_priv->core_freq * 1000; - -	dpll = 0;		/*BIT16 = 0 for 100MHz reference */ - -	ok = mrstFindBestPLL(crtc, adjusted_mode->clock, refclk, &clock); - -	if (!ok) { -		dev_dbg(dev->dev, "mrstFindBestPLL fail in mrst_crtc_mode_set.\n"); -	} else { -		dev_dbg(dev->dev, "mrst_crtc_mode_set pixel clock = %d," -			 "m = %x, p1 = %x.\n", clock.dot, clock.m, -			 clock.p1); -	} - -	fp = mrst_m_converts[(clock.m - MRST_M_MIN)] << 8; - -	dpll |= DPLL_VGA_MODE_DIS; - - -	dpll |= DPLL_VCO_ENABLE; - -	if (is_lvds) -		dpll |= DPLLA_MODE_LVDS; -	else -		dpll |= DPLLB_MODE_DAC_SERIAL; - -	if (is_sdvo) { -		int sdvo_pixel_multiply = -		    adjusted_mode->clock / mode->clock; - -		dpll |= DPLL_DVO_HIGH_SPEED; -		dpll |= -		    (sdvo_pixel_multiply - -		     1) << SDVO_MULTIPLIER_SHIFT_HIRES; -	} - - -	/* compute bitmask from p1 value */ -	dpll |= (1 << (clock.p1 - 2)) << 17; - -	dpll |= DPLL_VCO_ENABLE; - -	mrstPrintPll("chosen", &clock); - -	if (dpll & DPLL_VCO_ENABLE) { -		REG_WRITE(fp_reg, fp); -		REG_WRITE(dpll_reg, dpll & ~DPLL_VCO_ENABLE); -		REG_READ(dpll_reg); -		/* Check the DPLLA lock bit PIPEACONF[29] */ -		udelay(150); -	} - -	REG_WRITE(fp_reg, fp); -	REG_WRITE(dpll_reg, dpll); -	REG_READ(dpll_reg); -	/* Wait for the clocks to stabilize. */ -	udelay(150); - -	/* write it again -- the BIOS does, after all */ -	REG_WRITE(dpll_reg, dpll); -	REG_READ(dpll_reg); -	/* Wait for the clocks to stabilize. */ -	udelay(150); - -	REG_WRITE(pipeconf_reg, pipeconf); -	REG_READ(pipeconf_reg); -	psb_intel_wait_for_vblank(dev); - -	REG_WRITE(dspcntr_reg, dspcntr); -	psb_intel_wait_for_vblank(dev); - -mrst_crtc_mode_set_exit: -	gma_power_end(dev); -	return 0; -} - -static bool mrst_crtc_mode_fixup(struct drm_crtc *crtc, -				  struct drm_display_mode *mode, -				  struct drm_display_mode *adjusted_mode) -{ -	return true; -} - -int mrst_pipe_set_base(struct drm_crtc *crtc, -			    int x, int y, struct drm_framebuffer *old_fb) -{ -	struct drm_device *dev = crtc->dev; -	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); -	struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb); -	int pipe = psb_intel_crtc->pipe; -	unsigned long start, offset; - -	int dspbase = (pipe == 0 ? DSPALINOFF : DSPBBASE); -	int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF); -	int dspstride = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE; -	int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; -	u32 dspcntr; -	int ret = 0; - -	/* no fb bound */ -	if (!crtc->fb) { -		dev_dbg(dev->dev, "No FB bound\n"); -		return 0; -	} - -	if (!gma_power_begin(dev, true)) -		return 0; - -	start = psbfb->gtt->offset; -	offset = y * crtc->fb->pitches[0] + x * (crtc->fb->bits_per_pixel / 8); - -	REG_WRITE(dspstride, crtc->fb->pitches[0]); - -	dspcntr = REG_READ(dspcntr_reg); -	dspcntr &= ~DISPPLANE_PIXFORMAT_MASK; - -	switch (crtc->fb->bits_per_pixel) { -	case 8: -		dspcntr |= DISPPLANE_8BPP; -		break; -	case 16: -		if (crtc->fb->depth == 15) -			dspcntr |= DISPPLANE_15_16BPP; -		else -			dspcntr |= DISPPLANE_16BPP; -		break; -	case 24: -	case 32: -		dspcntr |= DISPPLANE_32BPP_NO_ALPHA; -		break; -	default: -		dev_err(dev->dev, "Unknown color depth\n"); -		ret = -EINVAL; -		goto pipe_set_base_exit; -	} -	REG_WRITE(dspcntr_reg, dspcntr); - -	REG_WRITE(dspbase, offset); -	REG_READ(dspbase); -	REG_WRITE(dspsurf, start); -	REG_READ(dspsurf); - -pipe_set_base_exit: -	gma_power_end(dev); -	return ret; -} - -static void mrst_crtc_prepare(struct drm_crtc *crtc) -{ -	struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; -	crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF); -} - -static void mrst_crtc_commit(struct drm_crtc *crtc) -{ -	struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; -	crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON); -} - -const struct drm_crtc_helper_funcs mrst_helper_funcs = { -	.dpms = mrst_crtc_dpms, -	.mode_fixup = mrst_crtc_mode_fixup, -	.mode_set = mrst_crtc_mode_set, -	.mode_set_base = mrst_pipe_set_base, -	.prepare = mrst_crtc_prepare, -	.commit = mrst_crtc_commit, -}; - diff --git a/drivers/staging/gma500/mrst_device.c b/drivers/staging/gma500/mrst_device.c deleted file mode 100644 index 6707fafbfa1..00000000000 --- a/drivers/staging/gma500/mrst_device.c +++ /dev/null @@ -1,634 +0,0 @@ -/************************************************************************** - * Copyright (c) 2011, Intel Corporation. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - **************************************************************************/ - -#include <linux/backlight.h> -#include <linux/module.h> -#include <linux/dmi.h> -#include <drm/drmP.h> -#include <drm/drm.h> -#include "psb_drm.h" -#include "psb_drv.h" -#include "psb_reg.h" -#include "psb_intel_reg.h" -#include <asm/mrst.h> -#include <asm/intel_scu_ipc.h> -#include "mid_bios.h" - -static int devtype; - -module_param_named(type, devtype, int, 0600); -MODULE_PARM_DESC(type, "Moorestown/Oaktrail device type"); - -#define DEVICE_MOORESTOWN		1 -#define DEVICE_OAKTRAIL			2 -#define DEVICE_MOORESTOWN_MM		3 - -static int mrst_device_ident(struct drm_device *dev) -{ -	/* User forced */ -	if (devtype) -		return devtype; -	if (dmi_match(DMI_PRODUCT_NAME, "OakTrail") || -		dmi_match(DMI_PRODUCT_NAME, "OakTrail platform")) -		return DEVICE_OAKTRAIL; -#if defined(CONFIG_X86_MRST) -	if (dmi_match(DMI_PRODUCT_NAME, "MM") || -		dmi_match(DMI_PRODUCT_NAME, "MM 10")) -		return DEVICE_MOORESTOWN_MM; -	if (mrst_identify_cpu()) -		return DEVICE_MOORESTOWN; -#endif -	return DEVICE_OAKTRAIL; -} - - -/* IPC message and command defines used to enable/disable mipi panel voltages */ -#define IPC_MSG_PANEL_ON_OFF    0xE9 -#define IPC_CMD_PANEL_ON        1 -#define IPC_CMD_PANEL_OFF       0 - -static int mrst_output_init(struct drm_device *dev) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; -	if (dev_priv->iLVDS_enable) -		mrst_lvds_init(dev, &dev_priv->mode_dev); -	else -		dev_err(dev->dev, "DSI is not supported\n"); -	if (dev_priv->hdmi_priv) -		mrst_hdmi_init(dev, &dev_priv->mode_dev); -	return 0; -} - -/* - *	Provide the low level interfaces for the Moorestown backlight - */ - -#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE - -#define MRST_BLC_MAX_PWM_REG_FREQ	    0xFFFF -#define BLC_PWM_PRECISION_FACTOR 100	/* 10000000 */ -#define BLC_PWM_FREQ_CALC_CONSTANT 32 -#define MHz 1000000 -#define BLC_ADJUSTMENT_MAX 100 - -static struct backlight_device *mrst_backlight_device; -static int mrst_brightness; - -static int mrst_set_brightness(struct backlight_device *bd) -{ -	struct drm_device *dev = bl_get_data(mrst_backlight_device); -	struct drm_psb_private *dev_priv = dev->dev_private; -	int level = bd->props.brightness; -	u32 blc_pwm_ctl; -	u32 max_pwm_blc; - -	/* Percentage 1-100% being valid */ -	if (level < 1) -		level = 1; - -	if (gma_power_begin(dev, 0)) { -		/* Calculate and set the brightness value */ -		max_pwm_blc = REG_READ(BLC_PWM_CTL) >> 16; -		blc_pwm_ctl = level * max_pwm_blc / 100; - -		/* Adjust the backlight level with the percent in -		 * dev_priv->blc_adj1; -		 */ -		blc_pwm_ctl = blc_pwm_ctl * dev_priv->blc_adj1; -		blc_pwm_ctl = blc_pwm_ctl / 100; - -		/* Adjust the backlight level with the percent in -		 * dev_priv->blc_adj2; -		 */ -		blc_pwm_ctl = blc_pwm_ctl * dev_priv->blc_adj2; -		blc_pwm_ctl = blc_pwm_ctl / 100; - -		/* force PWM bit on */ -		REG_WRITE(BLC_PWM_CTL2, (0x80000000 | REG_READ(BLC_PWM_CTL2))); -		REG_WRITE(BLC_PWM_CTL, (max_pwm_blc << 16) | blc_pwm_ctl); -		gma_power_end(dev); -	} -	mrst_brightness = level; -	return 0; -} - -static int mrst_get_brightness(struct backlight_device *bd) -{ -	/* return locally cached var instead of HW read (due to DPST etc.) */ -	/* FIXME: ideally return actual value in case firmware fiddled with -	   it */ -	return mrst_brightness; -} - -static int device_backlight_init(struct drm_device *dev) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; -	unsigned long core_clock; -	u16 bl_max_freq; -	uint32_t value; -	uint32_t blc_pwm_precision_factor; - -	dev_priv->blc_adj1 = BLC_ADJUSTMENT_MAX; -	dev_priv->blc_adj2 = BLC_ADJUSTMENT_MAX; -	bl_max_freq = 256; -	/* this needs to be set elsewhere */ -	blc_pwm_precision_factor = BLC_PWM_PRECISION_FACTOR; - -	core_clock = dev_priv->core_freq; - -	value = (core_clock * MHz) / BLC_PWM_FREQ_CALC_CONSTANT; -	value *= blc_pwm_precision_factor; -	value /= bl_max_freq; -	value /= blc_pwm_precision_factor; - -	if (value > (unsigned long long)MRST_BLC_MAX_PWM_REG_FREQ) -			return -ERANGE; - -	if (gma_power_begin(dev, false)) { -		REG_WRITE(BLC_PWM_CTL2, (0x80000000 | REG_READ(BLC_PWM_CTL2))); -		REG_WRITE(BLC_PWM_CTL, value | (value << 16)); -		gma_power_end(dev); -	} -	return 0; -} - -static const struct backlight_ops mrst_ops = { -	.get_brightness = mrst_get_brightness, -	.update_status  = mrst_set_brightness, -}; - -int mrst_backlight_init(struct drm_device *dev) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; -	int ret; -	struct backlight_properties props; - -	memset(&props, 0, sizeof(struct backlight_properties)); -	props.max_brightness = 100; -	props.type = BACKLIGHT_PLATFORM; - -	mrst_backlight_device = backlight_device_register("mrst-bl", -					NULL, (void *)dev, &mrst_ops, &props); - -	if (IS_ERR(mrst_backlight_device)) -		return PTR_ERR(mrst_backlight_device); - -	ret = device_backlight_init(dev); -	if (ret < 0) { -		backlight_device_unregister(mrst_backlight_device); -		return ret; -	} -	mrst_backlight_device->props.brightness = 100; -	mrst_backlight_device->props.max_brightness = 100; -	backlight_update_status(mrst_backlight_device); -	dev_priv->backlight_device = mrst_backlight_device; -	return 0; -} - -#endif - -/* - *	Provide the Moorestown specific chip logic and low level methods - *	for power management - */ - -static void mrst_init_pm(struct drm_device *dev) -{ -} - -/** - *	mrst_save_display_registers	-	save registers lost on suspend - *	@dev: our DRM device - * - *	Save the state we need in order to be able to restore the interface - *	upon resume from suspend - */ -static int mrst_save_display_registers(struct drm_device *dev) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; -	int i; -	u32 pp_stat; - -	/* Display arbitration control + watermarks */ -	dev_priv->saveDSPARB = PSB_RVDC32(DSPARB); -	dev_priv->saveDSPFW1 = PSB_RVDC32(DSPFW1); -	dev_priv->saveDSPFW2 = PSB_RVDC32(DSPFW2); -	dev_priv->saveDSPFW3 = PSB_RVDC32(DSPFW3); -	dev_priv->saveDSPFW4 = PSB_RVDC32(DSPFW4); -	dev_priv->saveDSPFW5 = PSB_RVDC32(DSPFW5); -	dev_priv->saveDSPFW6 = PSB_RVDC32(DSPFW6); -	dev_priv->saveCHICKENBIT = PSB_RVDC32(DSPCHICKENBIT); - -	/* Pipe & plane A info */ -	dev_priv->savePIPEACONF = PSB_RVDC32(PIPEACONF); -	dev_priv->savePIPEASRC = PSB_RVDC32(PIPEASRC); -	dev_priv->saveFPA0 = PSB_RVDC32(MRST_FPA0); -	dev_priv->saveFPA1 = PSB_RVDC32(MRST_FPA1); -	dev_priv->saveDPLL_A = PSB_RVDC32(MRST_DPLL_A); -	dev_priv->saveHTOTAL_A = PSB_RVDC32(HTOTAL_A); -	dev_priv->saveHBLANK_A = PSB_RVDC32(HBLANK_A); -	dev_priv->saveHSYNC_A = PSB_RVDC32(HSYNC_A); -	dev_priv->saveVTOTAL_A = PSB_RVDC32(VTOTAL_A); -	dev_priv->saveVBLANK_A = PSB_RVDC32(VBLANK_A); -	dev_priv->saveVSYNC_A = PSB_RVDC32(VSYNC_A); -	dev_priv->saveBCLRPAT_A = PSB_RVDC32(BCLRPAT_A); -	dev_priv->saveDSPACNTR = PSB_RVDC32(DSPACNTR); -	dev_priv->saveDSPASTRIDE = PSB_RVDC32(DSPASTRIDE); -	dev_priv->saveDSPAADDR = PSB_RVDC32(DSPABASE); -	dev_priv->saveDSPASURF = PSB_RVDC32(DSPASURF); -	dev_priv->saveDSPALINOFF = PSB_RVDC32(DSPALINOFF); -	dev_priv->saveDSPATILEOFF = PSB_RVDC32(DSPATILEOFF); - -	/* Save cursor regs */ -	dev_priv->saveDSPACURSOR_CTRL = PSB_RVDC32(CURACNTR); -	dev_priv->saveDSPACURSOR_BASE = PSB_RVDC32(CURABASE); -	dev_priv->saveDSPACURSOR_POS = PSB_RVDC32(CURAPOS); - -	/* Save palette (gamma) */ -	for (i = 0; i < 256; i++) -		dev_priv->save_palette_a[i] = PSB_RVDC32(PALETTE_A + (i << 2)); - -	if (dev_priv->hdmi_priv) -		mrst_hdmi_save(dev); - -	/* Save performance state */ -	dev_priv->savePERF_MODE = PSB_RVDC32(MRST_PERF_MODE); - -	/* LVDS state */ -	dev_priv->savePP_CONTROL = PSB_RVDC32(PP_CONTROL); -	dev_priv->savePFIT_PGM_RATIOS = PSB_RVDC32(PFIT_PGM_RATIOS); -	dev_priv->savePFIT_AUTO_RATIOS = PSB_RVDC32(PFIT_AUTO_RATIOS); -	dev_priv->saveBLC_PWM_CTL = PSB_RVDC32(BLC_PWM_CTL); -	dev_priv->saveBLC_PWM_CTL2 = PSB_RVDC32(BLC_PWM_CTL2); -	dev_priv->saveLVDS = PSB_RVDC32(LVDS); -	dev_priv->savePFIT_CONTROL = PSB_RVDC32(PFIT_CONTROL); -	dev_priv->savePP_ON_DELAYS = PSB_RVDC32(LVDSPP_ON); -	dev_priv->savePP_OFF_DELAYS = PSB_RVDC32(LVDSPP_OFF); -	dev_priv->savePP_DIVISOR = PSB_RVDC32(PP_CYCLE); - -	/* HW overlay */ -	dev_priv->saveOV_OVADD = PSB_RVDC32(OV_OVADD); -	dev_priv->saveOV_OGAMC0 = PSB_RVDC32(OV_OGAMC0); -	dev_priv->saveOV_OGAMC1 = PSB_RVDC32(OV_OGAMC1); -	dev_priv->saveOV_OGAMC2 = PSB_RVDC32(OV_OGAMC2); -	dev_priv->saveOV_OGAMC3 = PSB_RVDC32(OV_OGAMC3); -	dev_priv->saveOV_OGAMC4 = PSB_RVDC32(OV_OGAMC4); -	dev_priv->saveOV_OGAMC5 = PSB_RVDC32(OV_OGAMC5); - -	/* DPST registers */ -	dev_priv->saveHISTOGRAM_INT_CONTROL_REG = -					PSB_RVDC32(HISTOGRAM_INT_CONTROL); -	dev_priv->saveHISTOGRAM_LOGIC_CONTROL_REG = -					PSB_RVDC32(HISTOGRAM_LOGIC_CONTROL); -	dev_priv->savePWM_CONTROL_LOGIC = PSB_RVDC32(PWM_CONTROL_LOGIC); - -	if (dev_priv->iLVDS_enable) { -		/* Shut down the panel */ -		PSB_WVDC32(0, PP_CONTROL); - -		do { -			pp_stat = PSB_RVDC32(PP_STATUS); -		} while (pp_stat & 0x80000000); - -		/* Turn off the plane */ -		PSB_WVDC32(0x58000000, DSPACNTR); -		/* Trigger the plane disable */ -		PSB_WVDC32(0, DSPASURF); - -		/* Wait ~4 ticks */ -		msleep(4); - -		/* Turn off pipe */ -		PSB_WVDC32(0x0, PIPEACONF); -		/* Wait ~8 ticks */ -		msleep(8); - -		/* Turn off PLLs */ -		PSB_WVDC32(0, MRST_DPLL_A); -	} -	return 0; -} - -/** - *	mrst_restore_display_registers	-	restore lost register state - *	@dev: our DRM device - * - *	Restore register state that was lost during suspend and resume. - */ -static int mrst_restore_display_registers(struct drm_device *dev) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; -	u32 pp_stat; -	int i; - -	/* Display arbitration + watermarks */ -	PSB_WVDC32(dev_priv->saveDSPARB, DSPARB); -	PSB_WVDC32(dev_priv->saveDSPFW1, DSPFW1); -	PSB_WVDC32(dev_priv->saveDSPFW2, DSPFW2); -	PSB_WVDC32(dev_priv->saveDSPFW3, DSPFW3); -	PSB_WVDC32(dev_priv->saveDSPFW4, DSPFW4); -	PSB_WVDC32(dev_priv->saveDSPFW5, DSPFW5); -	PSB_WVDC32(dev_priv->saveDSPFW6, DSPFW6); -	PSB_WVDC32(dev_priv->saveCHICKENBIT, DSPCHICKENBIT); - -	/* Make sure VGA plane is off. it initializes to on after reset!*/ -	PSB_WVDC32(0x80000000, VGACNTRL); - -	/* set the plls */ -	PSB_WVDC32(dev_priv->saveFPA0, MRST_FPA0); -	PSB_WVDC32(dev_priv->saveFPA1, MRST_FPA1); - -	/* Actually enable it */ -	PSB_WVDC32(dev_priv->saveDPLL_A, MRST_DPLL_A); -	DRM_UDELAY(150); - -	/* Restore mode */ -	PSB_WVDC32(dev_priv->saveHTOTAL_A, HTOTAL_A); -	PSB_WVDC32(dev_priv->saveHBLANK_A, HBLANK_A); -	PSB_WVDC32(dev_priv->saveHSYNC_A, HSYNC_A); -	PSB_WVDC32(dev_priv->saveVTOTAL_A, VTOTAL_A); -	PSB_WVDC32(dev_priv->saveVBLANK_A, VBLANK_A); -	PSB_WVDC32(dev_priv->saveVSYNC_A, VSYNC_A); -	PSB_WVDC32(dev_priv->savePIPEASRC, PIPEASRC); -	PSB_WVDC32(dev_priv->saveBCLRPAT_A, BCLRPAT_A); - -	/* Restore performance mode*/ -	PSB_WVDC32(dev_priv->savePERF_MODE, MRST_PERF_MODE); - -	/* Enable the pipe*/ -	if (dev_priv->iLVDS_enable) -		PSB_WVDC32(dev_priv->savePIPEACONF, PIPEACONF); - -	/* Set up the plane*/ -	PSB_WVDC32(dev_priv->saveDSPALINOFF, DSPALINOFF); -	PSB_WVDC32(dev_priv->saveDSPASTRIDE, DSPASTRIDE); -	PSB_WVDC32(dev_priv->saveDSPATILEOFF, DSPATILEOFF); - -	/* Enable the plane */ -	PSB_WVDC32(dev_priv->saveDSPACNTR, DSPACNTR); -	PSB_WVDC32(dev_priv->saveDSPASURF, DSPASURF); - -	/* Enable Cursor A */ -	PSB_WVDC32(dev_priv->saveDSPACURSOR_CTRL, CURACNTR); -	PSB_WVDC32(dev_priv->saveDSPACURSOR_POS, CURAPOS); -	PSB_WVDC32(dev_priv->saveDSPACURSOR_BASE, CURABASE); - -	/* Restore palette (gamma) */ -	for (i = 0; i < 256; i++) -		PSB_WVDC32(dev_priv->save_palette_a[i], PALETTE_A + (i << 2)); - -	if (dev_priv->hdmi_priv) -		mrst_hdmi_restore(dev); - -	if (dev_priv->iLVDS_enable) { -		PSB_WVDC32(dev_priv->saveBLC_PWM_CTL2, BLC_PWM_CTL2); -		PSB_WVDC32(dev_priv->saveLVDS, LVDS); /*port 61180h*/ -		PSB_WVDC32(dev_priv->savePFIT_CONTROL, PFIT_CONTROL); -		PSB_WVDC32(dev_priv->savePFIT_PGM_RATIOS, PFIT_PGM_RATIOS); -		PSB_WVDC32(dev_priv->savePFIT_AUTO_RATIOS, PFIT_AUTO_RATIOS); -		PSB_WVDC32(dev_priv->saveBLC_PWM_CTL, BLC_PWM_CTL); -		PSB_WVDC32(dev_priv->savePP_ON_DELAYS, LVDSPP_ON); -		PSB_WVDC32(dev_priv->savePP_OFF_DELAYS, LVDSPP_OFF); -		PSB_WVDC32(dev_priv->savePP_DIVISOR, PP_CYCLE); -		PSB_WVDC32(dev_priv->savePP_CONTROL, PP_CONTROL); -	} - -	/* Wait for cycle delay */ -	do { -		pp_stat = PSB_RVDC32(PP_STATUS); -	} while (pp_stat & 0x08000000); - -	/* Wait for panel power up */ -	do { -		pp_stat = PSB_RVDC32(PP_STATUS); -	} while (pp_stat & 0x10000000); - -	/* Restore HW overlay */ -	PSB_WVDC32(dev_priv->saveOV_OVADD, OV_OVADD); -	PSB_WVDC32(dev_priv->saveOV_OGAMC0, OV_OGAMC0); -	PSB_WVDC32(dev_priv->saveOV_OGAMC1, OV_OGAMC1); -	PSB_WVDC32(dev_priv->saveOV_OGAMC2, OV_OGAMC2); -	PSB_WVDC32(dev_priv->saveOV_OGAMC3, OV_OGAMC3); -	PSB_WVDC32(dev_priv->saveOV_OGAMC4, OV_OGAMC4); -	PSB_WVDC32(dev_priv->saveOV_OGAMC5, OV_OGAMC5); - -	/* DPST registers */ -	PSB_WVDC32(dev_priv->saveHISTOGRAM_INT_CONTROL_REG, -						HISTOGRAM_INT_CONTROL); -	PSB_WVDC32(dev_priv->saveHISTOGRAM_LOGIC_CONTROL_REG, -						HISTOGRAM_LOGIC_CONTROL); -	PSB_WVDC32(dev_priv->savePWM_CONTROL_LOGIC, PWM_CONTROL_LOGIC); - -	return 0; -} - -/** - *	mrst_power_down	-	power down the display island - *	@dev: our DRM device - * - *	Power down the display interface of our device - */ -static int mrst_power_down(struct drm_device *dev) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; -	u32 pwr_mask ; -	u32 pwr_sts; - -	pwr_mask = PSB_PWRGT_DISPLAY_MASK; -	outl(pwr_mask, dev_priv->ospm_base + PSB_PM_SSC); - -	while (true) { -		pwr_sts = inl(dev_priv->ospm_base + PSB_PM_SSS); -		if ((pwr_sts & pwr_mask) == pwr_mask) -			break; -		else -			udelay(10); -	} -	return 0; -} - -/* - * mrst_power_up - * - * Restore power to the specified island(s) (powergating) - */ -static int mrst_power_up(struct drm_device *dev) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; -	u32 pwr_mask = PSB_PWRGT_DISPLAY_MASK; -	u32 pwr_sts, pwr_cnt; - -	pwr_cnt = inl(dev_priv->ospm_base + PSB_PM_SSC); -	pwr_cnt &= ~pwr_mask; -	outl(pwr_cnt, (dev_priv->ospm_base + PSB_PM_SSC)); - -	while (true) { -		pwr_sts = inl(dev_priv->ospm_base + PSB_PM_SSS); -		if ((pwr_sts & pwr_mask) == 0) -			break; -		else -			udelay(10); -	} -	return 0; -} - -#if defined(CONFIG_X86_MRST) -static void mrst_lvds_cache_bl(struct drm_device *dev) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; - -	intel_scu_ipc_ioread8(0x28, &(dev_priv->saveBKLTCNT)); -	intel_scu_ipc_ioread8(0x29, &(dev_priv->saveBKLTREQ)); -	intel_scu_ipc_ioread8(0x2A, &(dev_priv->saveBKLTBRTL)); -} - -static void mrst_mm_bl_power(struct drm_device *dev, bool on) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; - -	if (on) { -		intel_scu_ipc_iowrite8(0x2A, dev_priv->saveBKLTBRTL); -		intel_scu_ipc_iowrite8(0x28, dev_priv->saveBKLTCNT); -		intel_scu_ipc_iowrite8(0x29, dev_priv->saveBKLTREQ); -	} else { -		intel_scu_ipc_iowrite8(0x2A, 0); -		intel_scu_ipc_iowrite8(0x28, 0); -		intel_scu_ipc_iowrite8(0x29, 0); -	} -} - -static const struct psb_ops mrst_mm_chip_ops = { -	.name = "Moorestown MM ", -	.accel_2d = 1, -	.pipes = 1, -	.crtcs = 1, -	.sgx_offset = MRST_SGX_OFFSET, - -	.crtc_helper = &mrst_helper_funcs, -	.crtc_funcs = &psb_intel_crtc_funcs, - -	.output_init = mrst_output_init, - -	.lvds_bl_power = mrst_mm_bl_power, -#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE -	.backlight_init = mrst_backlight_init, -#endif - -	.init_pm = mrst_init_pm, -	.save_regs = mrst_save_display_registers, -	.restore_regs = mrst_restore_display_registers, -	.power_down = mrst_power_down, -	.power_up = mrst_power_up, - -	.i2c_bus = 0, -}; - -#endif - -static void oaktrail_teardown(struct drm_device *dev) -{ -	mrst_hdmi_teardown(dev); -} - -static const struct psb_ops oaktrail_chip_ops = { -	.name = "Oaktrail", -	.accel_2d = 1, -	.pipes = 2, -	.crtcs = 2, -	.sgx_offset = MRST_SGX_OFFSET, - -	.chip_setup = mid_chip_setup, -	.chip_teardown = oaktrail_teardown, -	.crtc_helper = &mrst_helper_funcs, -	.crtc_funcs = &psb_intel_crtc_funcs, - -	.output_init = mrst_output_init, - -#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE -	.backlight_init = mrst_backlight_init, -#endif - -	.init_pm = mrst_init_pm, -	.save_regs = mrst_save_display_registers, -	.restore_regs = mrst_restore_display_registers, -	.power_down = mrst_power_down, -	.power_up = mrst_power_up, - -	.i2c_bus = 1, -}; - -/** - *	mrst_chip_setup		-	perform the initial chip init - *	@dev: Our drm_device - * - *	Figure out which incarnation we are and then scan the firmware for - *	tables and information. - */ -static int mrst_chip_setup(struct drm_device *dev) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; - -	switch (mrst_device_ident(dev)) { -	case DEVICE_OAKTRAIL: -		/* Dual CRTC, PC compatible, HDMI, I2C #2 */ -		dev_priv->ops = &oaktrail_chip_ops; -		mrst_hdmi_setup(dev); -		return mid_chip_setup(dev); -#if defined(CONFIG_X86_MRST) -	case DEVICE_MOORESTOWN_MM: -		/* Single CRTC, No HDMI, I2C #0, BL control */ -		mrst_lvds_cache_bl(dev); -		dev_priv->ops = &mrst_mm_chip_ops; -		return mid_chip_setup(dev); -	case DEVICE_MOORESTOWN: -		/* Dual CRTC, No HDMI(?), I2C #1 */ -		return mid_chip_setup(dev); -#endif -	default: -		dev_err(dev->dev, "unsupported device type.\n"); -		return -ENODEV; -	} -} - -const struct psb_ops mrst_chip_ops = { -	.name = "Moorestown", -	.accel_2d = 1, -	.pipes = 2, -	.crtcs = 2, -	.sgx_offset = MRST_SGX_OFFSET, - -	.chip_setup = mrst_chip_setup, -	.crtc_helper = &mrst_helper_funcs, -	.crtc_funcs = &psb_intel_crtc_funcs, - -	.output_init = mrst_output_init, - -#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE -	.backlight_init = mrst_backlight_init, -#endif - -	.init_pm = mrst_init_pm, -	.save_regs = mrst_save_display_registers, -	.restore_regs = mrst_restore_display_registers, -	.power_down = mrst_power_down, -	.power_up = mrst_power_up, - -	.i2c_bus = 2, -}; - diff --git a/drivers/staging/gma500/mrst_hdmi.c b/drivers/staging/gma500/mrst_hdmi.c deleted file mode 100644 index e66607eb3d3..00000000000 --- a/drivers/staging/gma500/mrst_hdmi.c +++ /dev/null @@ -1,852 +0,0 @@ -/* - * Copyright © 2010 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Authors: - *	Li Peng <peng.li@intel.com> - */ - -#include <drm/drmP.h> -#include <drm/drm.h> -#include "psb_intel_drv.h" -#include "psb_intel_reg.h" -#include "psb_drv.h" - -#define HDMI_READ(reg)		readl(hdmi_dev->regs + (reg)) -#define HDMI_WRITE(reg, val)	writel(val, hdmi_dev->regs + (reg)) - -#define HDMI_HCR	0x1000 -#define HCR_ENABLE_HDCP		(1 << 5) -#define HCR_ENABLE_AUDIO	(1 << 2) -#define HCR_ENABLE_PIXEL	(1 << 1) -#define HCR_ENABLE_TMDS		(1 << 0) - -#define HDMI_HICR	0x1004 -#define HDMI_HSR	0x1008 -#define HDMI_HISR	0x100C -#define HDMI_DETECT_HDP		(1 << 0) - -#define HDMI_VIDEO_REG	0x3000 -#define HDMI_UNIT_EN		(1 << 7) -#define HDMI_MODE_OUTPUT	(1 << 0) -#define HDMI_HBLANK_A	0x3100 - -#define HDMI_AUDIO_CTRL	0x4000 -#define HDMI_ENABLE_AUDIO	(1 << 0) - -#define PCH_HTOTAL_B	0x3100 -#define PCH_HBLANK_B	0x3104 -#define PCH_HSYNC_B	0x3108 -#define PCH_VTOTAL_B	0x310C -#define PCH_VBLANK_B	0x3110 -#define PCH_VSYNC_B	0x3114 -#define PCH_PIPEBSRC	0x311C - -#define PCH_PIPEB_DSL	0x3800 -#define PCH_PIPEB_SLC	0x3804 -#define PCH_PIPEBCONF	0x3808 -#define PCH_PIPEBSTAT	0x3824 - -#define CDVO_DFT	0x5000 -#define CDVO_SLEWRATE	0x5004 -#define CDVO_STRENGTH	0x5008 -#define CDVO_RCOMP	0x500C - -#define DPLL_CTRL       0x6000 -#define DPLL_PDIV_SHIFT		16 -#define DPLL_PDIV_MASK		(0xf << 16) -#define DPLL_PWRDN		(1 << 4) -#define DPLL_RESET		(1 << 3) -#define DPLL_FASTEN		(1 << 2) -#define DPLL_ENSTAT		(1 << 1) -#define DPLL_DITHEN		(1 << 0) - -#define DPLL_DIV_CTRL   0x6004 -#define DPLL_CLKF_MASK		0xffffffc0 -#define DPLL_CLKR_MASK		(0x3f) - -#define DPLL_CLK_ENABLE 0x6008 -#define DPLL_EN_DISP		(1 << 31) -#define DPLL_SEL_HDMI		(1 << 8) -#define DPLL_EN_HDMI		(1 << 1) -#define DPLL_EN_VGA		(1 << 0) - -#define DPLL_ADJUST     0x600C -#define DPLL_STATUS     0x6010 -#define DPLL_UPDATE     0x6014 -#define DPLL_DFT        0x6020 - -struct intel_range { -	int	min, max; -}; - -struct mrst_hdmi_limit { -	struct intel_range vco, np, nr, nf; -}; - -struct mrst_hdmi_clock { -	int np; -	int nr; -	int nf; -	int dot; -}; - -#define VCO_MIN		320000 -#define VCO_MAX		1650000 -#define	NP_MIN		1 -#define	NP_MAX		15 -#define	NR_MIN		1 -#define	NR_MAX		64 -#define NF_MIN		2 -#define NF_MAX		4095 - -static const struct mrst_hdmi_limit mrst_hdmi_limit = { -	.vco = { .min = VCO_MIN,		.max = VCO_MAX }, -	.np  = { .min = NP_MIN,			.max = NP_MAX  }, -	.nr  = { .min = NR_MIN,			.max = NR_MAX  }, -	.nf  = { .min = NF_MIN,			.max = NF_MAX  }, -}; - -static void wait_for_vblank(struct drm_device *dev) -{ -	/* FIXME: Can we do this as a sleep ? */ -	/* Wait for 20ms, i.e. one cycle at 50hz. */ -	mdelay(20); -} - -static void scu_busy_loop(void *scu_base) -{ -	u32 status = 0; -	u32 loop_count = 0; - -	status = readl(scu_base + 0x04); -	while (status & 1) { -		udelay(1); /* scu processing time is in few u secods */ -		status = readl(scu_base + 0x04); -		loop_count++; -		/* break if scu doesn't reset busy bit after huge retry */ -		if (loop_count > 1000) { -			DRM_DEBUG_KMS("SCU IPC timed out"); -			return; -		} -	} -} - -static void mrst_hdmi_reset(struct drm_device *dev) -{ -	void *base; -	/* FIXME: at least make these defines */ -	unsigned int scu_ipc_mmio = 0xff11c000; -	int scu_len = 1024; - -	base = ioremap((resource_size_t)scu_ipc_mmio, scu_len); -	if (base == NULL) { -		DRM_ERROR("failed to map SCU mmio\n"); -		return; -	} - -	/* scu ipc: assert hdmi controller reset */ -	writel(0xff11d118, base + 0x0c); -	writel(0x7fffffdf, base + 0x80); -	writel(0x42005, base + 0x0); -	scu_busy_loop(base); - -	/* scu ipc: de-assert hdmi controller reset */ -	writel(0xff11d118, base + 0x0c); -	writel(0x7fffffff, base + 0x80); -	writel(0x42005, base + 0x0); -	scu_busy_loop(base); - -	iounmap(base); -} - -static void mrst_hdmi_audio_enable(struct drm_device *dev) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; -	struct mrst_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv; - -	HDMI_WRITE(HDMI_HCR, 0x67); -	HDMI_READ(HDMI_HCR); - -	HDMI_WRITE(0x51a8, 0x10); -	HDMI_READ(0x51a8); - -	HDMI_WRITE(HDMI_AUDIO_CTRL, 0x1); -	HDMI_READ(HDMI_AUDIO_CTRL); -} - -static void mrst_hdmi_audio_disable(struct drm_device *dev) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; -	struct mrst_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv; - -	HDMI_WRITE(0x51a8, 0x0); -	HDMI_READ(0x51a8); - -	HDMI_WRITE(HDMI_AUDIO_CTRL, 0x0); -	HDMI_READ(HDMI_AUDIO_CTRL); - -	HDMI_WRITE(HDMI_HCR, 0x47); -	HDMI_READ(HDMI_HCR); -} - -void mrst_crtc_hdmi_dpms(struct drm_crtc *crtc, int mode) -{ -	struct drm_device *dev = crtc->dev; -	u32 temp; - -	switch (mode) { -	case DRM_MODE_DPMS_OFF: -		/* Disable VGACNTRL */ -		REG_WRITE(VGACNTRL, 0x80000000); - -		/* Disable plane */ -		temp = REG_READ(DSPBCNTR); -		if ((temp & DISPLAY_PLANE_ENABLE) != 0) { -			REG_WRITE(DSPBCNTR, temp & ~DISPLAY_PLANE_ENABLE); -			REG_READ(DSPBCNTR); -			/* Flush the plane changes */ -			REG_WRITE(DSPBSURF, REG_READ(DSPBSURF)); -			REG_READ(DSPBSURF); -		} - -		/* Disable pipe B */ -		temp = REG_READ(PIPEBCONF); -		if ((temp & PIPEACONF_ENABLE) != 0) { -			REG_WRITE(PIPEBCONF, temp & ~PIPEACONF_ENABLE); -			REG_READ(PIPEBCONF); -		} - -		/* Disable LNW Pipes, etc */ -		temp = REG_READ(PCH_PIPEBCONF); -		if ((temp & PIPEACONF_ENABLE) != 0) { -			REG_WRITE(PCH_PIPEBCONF, temp & ~PIPEACONF_ENABLE); -			REG_READ(PCH_PIPEBCONF); -		} -		/* wait for pipe off */ -		udelay(150); -		/* Disable dpll */ -		temp = REG_READ(DPLL_CTRL); -		if ((temp & DPLL_PWRDN) == 0) { -			REG_WRITE(DPLL_CTRL, temp | (DPLL_PWRDN | DPLL_RESET)); -			REG_WRITE(DPLL_STATUS, 0x1); -		} -		/* wait for dpll off */ -		udelay(150); -		break; -	case DRM_MODE_DPMS_ON: -	case DRM_MODE_DPMS_STANDBY: -	case DRM_MODE_DPMS_SUSPEND: -		/* Enable dpll */ -		temp = REG_READ(DPLL_CTRL); -		if ((temp & DPLL_PWRDN) != 0) { -			REG_WRITE(DPLL_CTRL, temp & ~(DPLL_PWRDN | DPLL_RESET)); -			temp = REG_READ(DPLL_CLK_ENABLE); -			REG_WRITE(DPLL_CLK_ENABLE, temp | DPLL_EN_DISP | DPLL_SEL_HDMI | DPLL_EN_HDMI); -			REG_READ(DPLL_CLK_ENABLE); -		} -		/* wait for dpll warm up */ -		udelay(150); - -		/* Enable pipe B */ -		temp = REG_READ(PIPEBCONF); -		if ((temp & PIPEACONF_ENABLE) == 0) { -			REG_WRITE(PIPEBCONF, temp | PIPEACONF_ENABLE); -			REG_READ(PIPEBCONF); -		} - -		/* Enable LNW Pipe B */ -		temp = REG_READ(PCH_PIPEBCONF); -		if ((temp & PIPEACONF_ENABLE) == 0) { -			REG_WRITE(PCH_PIPEBCONF, temp | PIPEACONF_ENABLE); -			REG_READ(PCH_PIPEBCONF); -		} -		wait_for_vblank(dev); - -		/* Enable plane */ -		temp = REG_READ(DSPBCNTR); -		if ((temp & DISPLAY_PLANE_ENABLE) == 0) { -			REG_WRITE(DSPBCNTR, temp | DISPLAY_PLANE_ENABLE); -			/* Flush the plane changes */ -			REG_WRITE(DSPBSURF, REG_READ(DSPBSURF)); -			REG_READ(DSPBSURF); -		} -		psb_intel_crtc_load_lut(crtc); -	} -	/* DSPARB */ -	REG_WRITE(DSPARB, 0x00003fbf); -	/* FW1 */ -	REG_WRITE(0x70034, 0x3f880a0a); -	/* FW2 */ -	REG_WRITE(0x70038, 0x0b060808); -	/* FW4 */ -	REG_WRITE(0x70050, 0x08030404); -	/* FW5 */ -	REG_WRITE(0x70054, 0x04040404); -	/* LNC Chicken Bits */ -	REG_WRITE(0x70400, 0x4000); -} - - -static void mrst_hdmi_dpms(struct drm_encoder *encoder, int mode) -{ -	static int dpms_mode = -1; - -	struct drm_device *dev = encoder->dev; -	struct drm_psb_private *dev_priv = dev->dev_private; -	struct mrst_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv; -	u32 temp; - -	if (dpms_mode == mode) -		return; - -	if (mode != DRM_MODE_DPMS_ON) -		temp = 0x0; -	else -		temp = 0x99; - -	dpms_mode = mode; -	HDMI_WRITE(HDMI_VIDEO_REG, temp); -} - -static unsigned int htotal_calculate(struct drm_display_mode *mode) -{ -	u32 htotal, new_crtc_htotal; - -	htotal = (mode->crtc_hdisplay - 1) | ((mode->crtc_htotal - 1) << 16); - -	/* -	 * 1024 x 768  new_crtc_htotal = 0x1024; -	 * 1280 x 1024 new_crtc_htotal = 0x0c34; -	 */ -	new_crtc_htotal = (mode->crtc_htotal - 1) * 200 * 1000 / mode->clock; - -	return (mode->crtc_hdisplay - 1) | (new_crtc_htotal << 16); -} - -static void mrst_hdmi_find_dpll(struct drm_crtc *crtc, int target, -				int refclk, struct mrst_hdmi_clock *best_clock) -{ -	int np_min, np_max, nr_min, nr_max; -	int np, nr, nf; - -	np_min = DIV_ROUND_UP(mrst_hdmi_limit.vco.min, target * 10); -	np_max = mrst_hdmi_limit.vco.max / (target * 10); -	if (np_min < mrst_hdmi_limit.np.min) -		np_min = mrst_hdmi_limit.np.min; -	if (np_max > mrst_hdmi_limit.np.max) -		np_max = mrst_hdmi_limit.np.max; - -	nr_min = DIV_ROUND_UP((refclk * 1000), (target * 10 * np_max)); -	nr_max = DIV_ROUND_UP((refclk * 1000), (target * 10 * np_min)); -	if (nr_min < mrst_hdmi_limit.nr.min) -		nr_min = mrst_hdmi_limit.nr.min; -	if (nr_max > mrst_hdmi_limit.nr.max) -		nr_max = mrst_hdmi_limit.nr.max; - -	np = DIV_ROUND_UP((refclk * 1000), (target * 10 * nr_max)); -	nr = DIV_ROUND_UP((refclk * 1000), (target * 10 * np)); -	nf = DIV_ROUND_CLOSEST((target * 10 * np * nr), refclk); -	DRM_DEBUG_KMS("np, nr, nf %d %d %d\n", np, nr, nf); - -	/* -	 * 1024 x 768  np = 1; nr = 0x26; nf = 0x0fd8000; -	 * 1280 x 1024 np = 1; nr = 0x17; nf = 0x1034000; -	 */ -	best_clock->np = np; -	best_clock->nr = nr - 1; -	best_clock->nf = (nf << 14); -} - -int mrst_crtc_hdmi_mode_set(struct drm_crtc *crtc, -			    struct drm_display_mode *mode, -			    struct drm_display_mode *adjusted_mode, -			    int x, int y, -			    struct drm_framebuffer *old_fb) -{ -	struct drm_device *dev = crtc->dev; -	struct drm_psb_private *dev_priv = dev->dev_private; -	struct mrst_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv; -	int pipe = 1; -	int htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B; -	int hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B; -	int hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B; -	int vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B; -	int vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B; -	int vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B; -	int dspsize_reg = (pipe == 0) ? DSPASIZE : DSPBSIZE; -	int dsppos_reg = (pipe == 0) ? DSPAPOS : DSPBPOS; -	int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC; -	int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; -	int refclk; -	struct mrst_hdmi_clock clock; -	u32 dspcntr, pipeconf, dpll, temp; -	int dspcntr_reg = DSPBCNTR; - -	/* Disable the VGA plane that we never use */ -	REG_WRITE(VGACNTRL, VGA_DISP_DISABLE); - -	/* XXX: Disable the panel fitter if it was on our pipe */ - -	/* Disable dpll if necessary */ -	dpll = REG_READ(DPLL_CTRL); -	if ((dpll & DPLL_PWRDN) == 0) { -		REG_WRITE(DPLL_CTRL, dpll | (DPLL_PWRDN | DPLL_RESET)); -		REG_WRITE(DPLL_DIV_CTRL, 0x00000000); -		REG_WRITE(DPLL_STATUS, 0x1); -	} -	udelay(150); - -	/* reset controller: FIXME - can we sort out the ioremap mess ? */ -	iounmap(hdmi_dev->regs); -	mrst_hdmi_reset(dev); - -	/* program and enable dpll */ -	refclk = 25000; -	mrst_hdmi_find_dpll(crtc, adjusted_mode->clock, refclk, &clock); - -	/* Setting DPLL */ -	dpll = REG_READ(DPLL_CTRL); -	dpll &= ~DPLL_PDIV_MASK; -	dpll &= ~(DPLL_PWRDN | DPLL_RESET); -	REG_WRITE(DPLL_CTRL, 0x00000008); -	REG_WRITE(DPLL_DIV_CTRL, ((clock.nf << 6) | clock.nr)); -	REG_WRITE(DPLL_ADJUST, ((clock.nf >> 14) - 1)); -	REG_WRITE(DPLL_CTRL, (dpll | (clock.np << DPLL_PDIV_SHIFT) | DPLL_ENSTAT | DPLL_DITHEN)); -	REG_WRITE(DPLL_UPDATE, 0x80000000); -	REG_WRITE(DPLL_CLK_ENABLE, 0x80050102); -	udelay(150); - -	hdmi_dev->regs = ioremap(hdmi_dev->mmio, hdmi_dev->mmio_len); -	if (hdmi_dev->regs == NULL) { -		DRM_ERROR("failed to do hdmi mmio mapping\n"); -		return -ENOMEM; -	} - -	/* configure HDMI */ -	HDMI_WRITE(0x1004, 0x1fd); -	HDMI_WRITE(0x2000, 0x1); -	HDMI_WRITE(0x2008, 0x0); -	HDMI_WRITE(0x3130, 0x8); -	HDMI_WRITE(0x101c, 0x1800810); - -	temp = htotal_calculate(adjusted_mode); -	REG_WRITE(htot_reg, temp); -	REG_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) | ((adjusted_mode->crtc_hblank_end - 1) << 16)); -	REG_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - 1) | ((adjusted_mode->crtc_hsync_end - 1) << 16)); -	REG_WRITE(vtot_reg, (adjusted_mode->crtc_vdisplay - 1) | ((adjusted_mode->crtc_vtotal - 1) << 16)); -	REG_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - 1) | ((adjusted_mode->crtc_vblank_end - 1) << 16)); -	REG_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - 1) | ((adjusted_mode->crtc_vsync_end - 1) << 16)); -	REG_WRITE(pipesrc_reg, -		((mode->crtc_hdisplay - 1) << 16) |  (mode->crtc_vdisplay - 1)); - -	REG_WRITE(PCH_HTOTAL_B, (adjusted_mode->crtc_hdisplay - 1) | ((adjusted_mode->crtc_htotal - 1) << 16)); -	REG_WRITE(PCH_HBLANK_B, (adjusted_mode->crtc_hblank_start - 1) | ((adjusted_mode->crtc_hblank_end - 1) << 16)); -	REG_WRITE(PCH_HSYNC_B, (adjusted_mode->crtc_hsync_start - 1) | ((adjusted_mode->crtc_hsync_end - 1) << 16)); -	REG_WRITE(PCH_VTOTAL_B, (adjusted_mode->crtc_vdisplay - 1) | ((adjusted_mode->crtc_vtotal - 1) << 16)); -	REG_WRITE(PCH_VBLANK_B, (adjusted_mode->crtc_vblank_start - 1) | ((adjusted_mode->crtc_vblank_end - 1) << 16)); -	REG_WRITE(PCH_VSYNC_B, (adjusted_mode->crtc_vsync_start - 1) | ((adjusted_mode->crtc_vsync_end - 1) << 16)); -	REG_WRITE(PCH_PIPEBSRC, -		((mode->crtc_hdisplay - 1) << 16) |  (mode->crtc_vdisplay - 1)); - -	temp = adjusted_mode->crtc_hblank_end - adjusted_mode->crtc_hblank_start; -	HDMI_WRITE(HDMI_HBLANK_A, ((adjusted_mode->crtc_hdisplay - 1) << 16) |  temp); - -	REG_WRITE(dspsize_reg, -			((mode->vdisplay - 1) << 16) | (mode->hdisplay - 1)); -	REG_WRITE(dsppos_reg, 0); - -	/* Flush the plane changes */ -	{ -		struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; -		crtc_funcs->mode_set_base(crtc, x, y, old_fb); -	} - -	/* Set up the display plane register */ -	dspcntr = REG_READ(dspcntr_reg); -	dspcntr |= DISPPLANE_GAMMA_ENABLE; -	dspcntr |= DISPPLANE_SEL_PIPE_B; -	dspcntr |= DISPLAY_PLANE_ENABLE; - -	/* setup pipeconf */ -	pipeconf = REG_READ(pipeconf_reg); -	pipeconf |= PIPEACONF_ENABLE; - -	REG_WRITE(pipeconf_reg, pipeconf); -	REG_READ(pipeconf_reg); - -	REG_WRITE(PCH_PIPEBCONF, pipeconf); -	REG_READ(PCH_PIPEBCONF); -	wait_for_vblank(dev); - -	REG_WRITE(dspcntr_reg, dspcntr); -	wait_for_vblank(dev); - -	return 0; -} - -static int mrst_hdmi_mode_valid(struct drm_connector *connector, -				struct drm_display_mode *mode) -{ -	if (mode->clock > 165000) -		return MODE_CLOCK_HIGH; -	if (mode->clock < 20000) -		return MODE_CLOCK_LOW; - -	if (mode->flags & DRM_MODE_FLAG_DBLSCAN) -		return MODE_NO_DBLESCAN; - -	return MODE_OK; -} - -static bool mrst_hdmi_mode_fixup(struct drm_encoder *encoder, -				 struct drm_display_mode *mode, -				 struct drm_display_mode *adjusted_mode) -{ -	return true; -} - -static enum drm_connector_status -mrst_hdmi_detect(struct drm_connector *connector, bool force) -{ -	enum drm_connector_status status; -	struct drm_device *dev = connector->dev; -	struct drm_psb_private *dev_priv = dev->dev_private; -	struct mrst_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv; -	u32 temp; - -	temp = HDMI_READ(HDMI_HSR); -	DRM_DEBUG_KMS("HDMI_HSR %x\n", temp); - -	if ((temp & HDMI_DETECT_HDP) != 0) -		status = connector_status_connected; -	else -		status = connector_status_disconnected; - -	return status; -} - -static const unsigned char raw_edid[] = { -	0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x10, 0xac, 0x2f, 0xa0, -	0x53, 0x55, 0x33, 0x30, 0x16, 0x13, 0x01, 0x03, 0x0e, 0x3a, 0x24, 0x78, -	0xea, 0xe9, 0xf5, 0xac, 0x51, 0x30, 0xb4, 0x25, 0x11, 0x50, 0x54, 0xa5, -	0x4b, 0x00, 0x81, 0x80, 0xa9, 0x40, 0x71, 0x4f, 0xb3, 0x00, 0x01, 0x01, -	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x28, 0x3c, 0x80, 0xa0, 0x70, 0xb0, -	0x23, 0x40, 0x30, 0x20, 0x36, 0x00, 0x46, 0x6c, 0x21, 0x00, 0x00, 0x1a, -	0x00, 0x00, 0x00, 0xff, 0x00, 0x47, 0x4e, 0x37, 0x32, 0x31, 0x39, 0x35, -	0x52, 0x30, 0x33, 0x55, 0x53, 0x0a, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x44, -	0x45, 0x4c, 0x4c, 0x20, 0x32, 0x37, 0x30, 0x39, 0x57, 0x0a, 0x20, 0x20, -	0x00, 0x00, 0x00, 0xfd, 0x00, 0x38, 0x4c, 0x1e, 0x53, 0x11, 0x00, 0x0a, -	0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x8d -}; - -static int mrst_hdmi_get_modes(struct drm_connector *connector) -{ -	struct drm_device *dev = connector->dev; -	struct drm_psb_private *dev_priv = dev->dev_private; -	struct i2c_adapter *i2c_adap; -	struct edid *edid; -	struct drm_display_mode *mode, *t; -	int i = 0, ret = 0; - -	i2c_adap = i2c_get_adapter(3); -	if (i2c_adap == NULL) { -		DRM_ERROR("No ddc adapter available!\n"); -		edid = (struct edid *)raw_edid; -	} else { -		edid = (struct edid *)raw_edid; -		/* FIXME ? edid = drm_get_edid(connector, i2c_adap); */ -	} - -	if (edid) { -		drm_mode_connector_update_edid_property(connector, edid); -		ret = drm_add_edid_modes(connector, edid); -		connector->display_info.raw_edid = NULL; -	} - -	/* -	 * prune modes that require frame buffer bigger than stolen mem -	 */ -	list_for_each_entry_safe(mode, t, &connector->probed_modes, head) { -		if ((mode->hdisplay * mode->vdisplay * 4) >= dev_priv->vram_stolen_size) { -			i++; -			drm_mode_remove(connector, mode); -		} -	} -	return ret - i; -} - -static void mrst_hdmi_mode_set(struct drm_encoder *encoder, -			       struct drm_display_mode *mode, -			       struct drm_display_mode *adjusted_mode) -{ -	struct drm_device *dev = encoder->dev; - -	mrst_hdmi_audio_enable(dev); -	return; -} - -static void mrst_hdmi_destroy(struct drm_connector *connector) -{ -	return; -} - -static const struct drm_encoder_helper_funcs mrst_hdmi_helper_funcs = { -	.dpms = mrst_hdmi_dpms, -	.mode_fixup = mrst_hdmi_mode_fixup, -	.prepare = psb_intel_encoder_prepare, -	.mode_set = mrst_hdmi_mode_set, -	.commit = psb_intel_encoder_commit, -}; - -static const struct drm_connector_helper_funcs -					mrst_hdmi_connector_helper_funcs = { -	.get_modes = mrst_hdmi_get_modes, -	.mode_valid = mrst_hdmi_mode_valid, -	.best_encoder = psb_intel_best_encoder, -}; - -static const struct drm_connector_funcs mrst_hdmi_connector_funcs = { -	.dpms = drm_helper_connector_dpms, -	.detect = mrst_hdmi_detect, -	.fill_modes = drm_helper_probe_single_connector_modes, -	.destroy = mrst_hdmi_destroy, -}; - -static void mrst_hdmi_enc_destroy(struct drm_encoder *encoder) -{ -	drm_encoder_cleanup(encoder); -} - -static const struct drm_encoder_funcs mrst_hdmi_enc_funcs = { -	.destroy = mrst_hdmi_enc_destroy, -}; - -void mrst_hdmi_init(struct drm_device *dev, -					struct psb_intel_mode_device *mode_dev) -{ -	struct psb_intel_output *psb_intel_output; -	struct drm_connector *connector; -	struct drm_encoder *encoder; - -	psb_intel_output = kzalloc(sizeof(struct psb_intel_output), GFP_KERNEL); -	if (!psb_intel_output) -		return; - -	psb_intel_output->mode_dev = mode_dev; -	connector = &psb_intel_output->base; -	encoder = &psb_intel_output->enc; -	drm_connector_init(dev, &psb_intel_output->base, -			   &mrst_hdmi_connector_funcs, -			   DRM_MODE_CONNECTOR_DVID); - -	drm_encoder_init(dev, &psb_intel_output->enc, -			 &mrst_hdmi_enc_funcs, -			 DRM_MODE_ENCODER_TMDS); - -	drm_mode_connector_attach_encoder(&psb_intel_output->base, -					  &psb_intel_output->enc); - -	psb_intel_output->type = INTEL_OUTPUT_HDMI; -	drm_encoder_helper_add(encoder, &mrst_hdmi_helper_funcs); -	drm_connector_helper_add(connector, &mrst_hdmi_connector_helper_funcs); - -	connector->display_info.subpixel_order = SubPixelHorizontalRGB; -	connector->interlace_allowed = false; -	connector->doublescan_allowed = false; -	drm_sysfs_connector_add(connector); - -	return; -} - -static DEFINE_PCI_DEVICE_TABLE(hdmi_ids) = { -	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x080d) }, -	{} -}; - -void mrst_hdmi_setup(struct drm_device *dev) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; -	struct pci_dev *pdev; -	struct mrst_hdmi_dev *hdmi_dev; -	int ret; - -	pdev = pci_get_device(PCI_VENDOR_ID_INTEL, 0x080d, NULL); -	if (!pdev) -		return; - -	hdmi_dev = kzalloc(sizeof(struct mrst_hdmi_dev), GFP_KERNEL); -	if (!hdmi_dev) { -		dev_err(dev->dev, "failed to allocate memory\n"); -		goto out; -	} - - -	ret = pci_enable_device(pdev); -	if (ret) { -		dev_err(dev->dev, "failed to enable hdmi controller\n"); -		goto free; -	} - -	hdmi_dev->mmio = pci_resource_start(pdev, 0); -	hdmi_dev->mmio_len = pci_resource_len(pdev, 0); -	hdmi_dev->regs = ioremap(hdmi_dev->mmio, hdmi_dev->mmio_len); -	if (!hdmi_dev->regs) { -		dev_err(dev->dev, "failed to map hdmi mmio\n"); -		goto free; -	} - -	hdmi_dev->dev = pdev; -	pci_set_drvdata(pdev, hdmi_dev); - -	/* Initialize i2c controller */ -	ret = mrst_hdmi_i2c_init(hdmi_dev->dev); -	if (ret) -		dev_err(dev->dev, "HDMI I2C initialization failed\n"); - -	dev_priv->hdmi_priv = hdmi_dev; -	mrst_hdmi_audio_disable(dev); -	return; - -free: -	kfree(hdmi_dev); -out: -	return; -} - -void mrst_hdmi_teardown(struct drm_device *dev) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; -	struct mrst_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv; -	struct pci_dev *pdev; - -	if (hdmi_dev) { -		pdev = hdmi_dev->dev; -		pci_set_drvdata(pdev, NULL); -		mrst_hdmi_i2c_exit(pdev); -		iounmap(hdmi_dev->regs); -		kfree(hdmi_dev); -		pci_dev_put(pdev); -	} -} - -/* save HDMI register state */ -void mrst_hdmi_save(struct drm_device *dev) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; -	struct mrst_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv; -	int i; - -	/* dpll */ -	hdmi_dev->saveDPLL_CTRL = PSB_RVDC32(DPLL_CTRL); -	hdmi_dev->saveDPLL_DIV_CTRL = PSB_RVDC32(DPLL_DIV_CTRL); -	hdmi_dev->saveDPLL_ADJUST = PSB_RVDC32(DPLL_ADJUST); -	hdmi_dev->saveDPLL_UPDATE = PSB_RVDC32(DPLL_UPDATE); -	hdmi_dev->saveDPLL_CLK_ENABLE = PSB_RVDC32(DPLL_CLK_ENABLE); - -	/* pipe B */ -	dev_priv->savePIPEBCONF = PSB_RVDC32(PIPEBCONF); -	dev_priv->savePIPEBSRC  = PSB_RVDC32(PIPEBSRC); -	dev_priv->saveHTOTAL_B  = PSB_RVDC32(HTOTAL_B); -	dev_priv->saveHBLANK_B  = PSB_RVDC32(HBLANK_B); -	dev_priv->saveHSYNC_B   = PSB_RVDC32(HSYNC_B); -	dev_priv->saveVTOTAL_B  = PSB_RVDC32(VTOTAL_B); -	dev_priv->saveVBLANK_B  = PSB_RVDC32(VBLANK_B); -	dev_priv->saveVSYNC_B   = PSB_RVDC32(VSYNC_B); - -	hdmi_dev->savePCH_PIPEBCONF = PSB_RVDC32(PCH_PIPEBCONF); -	hdmi_dev->savePCH_PIPEBSRC = PSB_RVDC32(PCH_PIPEBSRC); -	hdmi_dev->savePCH_HTOTAL_B = PSB_RVDC32(PCH_HTOTAL_B); -	hdmi_dev->savePCH_HBLANK_B = PSB_RVDC32(PCH_HBLANK_B); -	hdmi_dev->savePCH_HSYNC_B  = PSB_RVDC32(PCH_HSYNC_B); -	hdmi_dev->savePCH_VTOTAL_B = PSB_RVDC32(PCH_VTOTAL_B); -	hdmi_dev->savePCH_VBLANK_B = PSB_RVDC32(PCH_VBLANK_B); -	hdmi_dev->savePCH_VSYNC_B  = PSB_RVDC32(PCH_VSYNC_B); - -	/* plane */ -	dev_priv->saveDSPBCNTR = PSB_RVDC32(DSPBCNTR); -	dev_priv->saveDSPBSTRIDE = PSB_RVDC32(DSPBSTRIDE); -	dev_priv->saveDSPBADDR = PSB_RVDC32(DSPBBASE); -	dev_priv->saveDSPBSURF = PSB_RVDC32(DSPBSURF); -	dev_priv->saveDSPBLINOFF = PSB_RVDC32(DSPBLINOFF); -	dev_priv->saveDSPBTILEOFF = PSB_RVDC32(DSPBTILEOFF); - -	/* cursor B */ -	dev_priv->saveDSPBCURSOR_CTRL = PSB_RVDC32(CURBCNTR); -	dev_priv->saveDSPBCURSOR_BASE = PSB_RVDC32(CURBBASE); -	dev_priv->saveDSPBCURSOR_POS = PSB_RVDC32(CURBPOS); - -	/* save palette */ -	for (i = 0; i < 256; i++) -		dev_priv->save_palette_b[i] = PSB_RVDC32(PALETTE_B + (i << 2)); -} - -/* restore HDMI register state */ -void mrst_hdmi_restore(struct drm_device *dev) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; -	struct mrst_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv; -	int i; - -	/* dpll */ -	PSB_WVDC32(hdmi_dev->saveDPLL_CTRL, DPLL_CTRL); -	PSB_WVDC32(hdmi_dev->saveDPLL_DIV_CTRL, DPLL_DIV_CTRL); -	PSB_WVDC32(hdmi_dev->saveDPLL_ADJUST, DPLL_ADJUST); -	PSB_WVDC32(hdmi_dev->saveDPLL_UPDATE, DPLL_UPDATE); -	PSB_WVDC32(hdmi_dev->saveDPLL_CLK_ENABLE, DPLL_CLK_ENABLE); -	DRM_UDELAY(150); - -	/* pipe */ -	PSB_WVDC32(dev_priv->savePIPEBSRC, PIPEBSRC); -	PSB_WVDC32(dev_priv->saveHTOTAL_B, HTOTAL_B); -	PSB_WVDC32(dev_priv->saveHBLANK_B, HBLANK_B); -	PSB_WVDC32(dev_priv->saveHSYNC_B,  HSYNC_B); -	PSB_WVDC32(dev_priv->saveVTOTAL_B, VTOTAL_B); -	PSB_WVDC32(dev_priv->saveVBLANK_B, VBLANK_B); -	PSB_WVDC32(dev_priv->saveVSYNC_B,  VSYNC_B); - -	PSB_WVDC32(hdmi_dev->savePCH_PIPEBSRC, PCH_PIPEBSRC); -	PSB_WVDC32(hdmi_dev->savePCH_HTOTAL_B, PCH_HTOTAL_B); -	PSB_WVDC32(hdmi_dev->savePCH_HBLANK_B, PCH_HBLANK_B); -	PSB_WVDC32(hdmi_dev->savePCH_HSYNC_B,  PCH_HSYNC_B); -	PSB_WVDC32(hdmi_dev->savePCH_VTOTAL_B, PCH_VTOTAL_B); -	PSB_WVDC32(hdmi_dev->savePCH_VBLANK_B, PCH_VBLANK_B); -	PSB_WVDC32(hdmi_dev->savePCH_VSYNC_B,  PCH_VSYNC_B); - -	PSB_WVDC32(dev_priv->savePIPEBCONF, PIPEBCONF); -	PSB_WVDC32(hdmi_dev->savePCH_PIPEBCONF, PCH_PIPEBCONF); - -	/* plane */ -	PSB_WVDC32(dev_priv->saveDSPBLINOFF, DSPBLINOFF); -	PSB_WVDC32(dev_priv->saveDSPBSTRIDE, DSPBSTRIDE); -	PSB_WVDC32(dev_priv->saveDSPBTILEOFF, DSPBTILEOFF); -	PSB_WVDC32(dev_priv->saveDSPBCNTR, DSPBCNTR); -	PSB_WVDC32(dev_priv->saveDSPBSURF, DSPBSURF); - -	/* cursor B */ -	PSB_WVDC32(dev_priv->saveDSPBCURSOR_CTRL, CURBCNTR); -	PSB_WVDC32(dev_priv->saveDSPBCURSOR_POS, CURBPOS); -	PSB_WVDC32(dev_priv->saveDSPBCURSOR_BASE, CURBBASE); - -	/* restore palette */ -	for (i = 0; i < 256; i++) -		PSB_WVDC32(dev_priv->save_palette_b[i], PALETTE_B + (i << 2)); -} diff --git a/drivers/staging/gma500/mrst_hdmi_i2c.c b/drivers/staging/gma500/mrst_hdmi_i2c.c deleted file mode 100644 index 36e7edc4d14..00000000000 --- a/drivers/staging/gma500/mrst_hdmi_i2c.c +++ /dev/null @@ -1,328 +0,0 @@ -/* - * Copyright © 2010 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Authors: - *	Li Peng <peng.li@intel.com> - */ - -#include <linux/mutex.h> -#include <linux/pci.h> -#include <linux/i2c.h> -#include <linux/interrupt.h> -#include <linux/delay.h> -#include <linux/export.h> -#include "psb_drv.h" - -#define HDMI_READ(reg)		readl(hdmi_dev->regs + (reg)) -#define HDMI_WRITE(reg, val)	writel(val, hdmi_dev->regs + (reg)) - -#define HDMI_HCR	0x1000 -#define HCR_DETECT_HDP		(1 << 6) -#define HCR_ENABLE_HDCP		(1 << 5) -#define HCR_ENABLE_AUDIO	(1 << 2) -#define HCR_ENABLE_PIXEL	(1 << 1) -#define HCR_ENABLE_TMDS		(1 << 0) -#define HDMI_HICR	0x1004 -#define HDMI_INTR_I2C_ERROR	(1 << 4) -#define HDMI_INTR_I2C_FULL	(1 << 3) -#define HDMI_INTR_I2C_DONE	(1 << 2) -#define HDMI_INTR_HPD		(1 << 0) -#define HDMI_HSR	0x1008 -#define HDMI_HISR	0x100C -#define HDMI_HI2CRDB0	0x1200 -#define HDMI_HI2CHCR	0x1240 -#define HI2C_HDCP_WRITE		(0 << 2) -#define HI2C_HDCP_RI_READ	(1 << 2) -#define HI2C_HDCP_READ		(2 << 2) -#define HI2C_EDID_READ		(3 << 2) -#define HI2C_READ_CONTINUE	(1 << 1) -#define HI2C_ENABLE_TRANSACTION	(1 << 0) - -#define HDMI_ICRH	0x1100 -#define HDMI_HI2CTDR0	0x1244 -#define HDMI_HI2CTDR1	0x1248 - -#define I2C_STAT_INIT		0 -#define I2C_READ_DONE		1 -#define I2C_TRANSACTION_DONE	2 - -struct hdmi_i2c_dev { -	struct i2c_adapter *adap; -	struct mutex i2c_lock; -	struct completion complete; -	int status; -	struct i2c_msg *msg; -	int buf_offset; -}; - -static void hdmi_i2c_irq_enable(struct mrst_hdmi_dev *hdmi_dev) -{ -	u32 temp; - -	temp = HDMI_READ(HDMI_HICR); -	temp |= (HDMI_INTR_I2C_ERROR | HDMI_INTR_I2C_FULL | HDMI_INTR_I2C_DONE); -	HDMI_WRITE(HDMI_HICR, temp); -	HDMI_READ(HDMI_HICR); -} - -static void hdmi_i2c_irq_disable(struct mrst_hdmi_dev *hdmi_dev) -{ -	HDMI_WRITE(HDMI_HICR, 0x0); -	HDMI_READ(HDMI_HICR); -} - -static int xfer_read(struct i2c_adapter *adap, struct i2c_msg *pmsg) -{ -	struct mrst_hdmi_dev *hdmi_dev = i2c_get_adapdata(adap); -	struct hdmi_i2c_dev *i2c_dev = hdmi_dev->i2c_dev; -	u32 temp; - -	i2c_dev->status = I2C_STAT_INIT; -	i2c_dev->msg = pmsg; -	i2c_dev->buf_offset = 0; -	INIT_COMPLETION(i2c_dev->complete); - -	/* Enable I2C transaction */ -	temp = ((pmsg->len) << 20) | HI2C_EDID_READ | HI2C_ENABLE_TRANSACTION; -	HDMI_WRITE(HDMI_HI2CHCR, temp); -	HDMI_READ(HDMI_HI2CHCR); - -	while (i2c_dev->status != I2C_TRANSACTION_DONE) -		wait_for_completion_interruptible_timeout(&i2c_dev->complete, -								10 * HZ); - -	return 0; -} - -static int xfer_write(struct i2c_adapter *adap, struct i2c_msg *pmsg) -{ -	/* -	 * XXX: i2c write seems isn't useful for EDID probe, don't do anything -	 */ -	return 0; -} - -static int mrst_hdmi_i2c_access(struct i2c_adapter *adap, -				struct i2c_msg *pmsg, -				int num) -{ -	struct mrst_hdmi_dev *hdmi_dev = i2c_get_adapdata(adap); -	struct hdmi_i2c_dev *i2c_dev = hdmi_dev->i2c_dev; -	int i, err = 0; - -	mutex_lock(&i2c_dev->i2c_lock); - -	/* Enable i2c unit */ -	HDMI_WRITE(HDMI_ICRH, 0x00008760); - -	/* Enable irq */ -	hdmi_i2c_irq_enable(hdmi_dev); -	for (i = 0; i < num; i++) { -		if (pmsg->len && pmsg->buf) { -			if (pmsg->flags & I2C_M_RD) -				err = xfer_read(adap, pmsg); -			else -				err = xfer_write(adap, pmsg); -		} -		pmsg++;         /* next message */ -	} - -	/* Disable irq */ -	hdmi_i2c_irq_disable(hdmi_dev); - -	mutex_unlock(&i2c_dev->i2c_lock); - -	return i; -} - -static u32 mrst_hdmi_i2c_func(struct i2c_adapter *adapter) -{ -	return I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR; -} - -static const struct i2c_algorithm mrst_hdmi_i2c_algorithm = { -	.master_xfer	= mrst_hdmi_i2c_access, -	.functionality  = mrst_hdmi_i2c_func, -}; - -static struct i2c_adapter mrst_hdmi_i2c_adapter = { -	.name		= "mrst_hdmi_i2c", -	.nr		= 3, -	.owner		= THIS_MODULE, -	.class		= I2C_CLASS_DDC, -	.algo		= &mrst_hdmi_i2c_algorithm, -}; - -static void hdmi_i2c_read(struct mrst_hdmi_dev *hdmi_dev) -{ -	struct hdmi_i2c_dev *i2c_dev = hdmi_dev->i2c_dev; -	struct i2c_msg *msg = i2c_dev->msg; -	u8 *buf = msg->buf; -	u32 temp; -	int i, offset; - -	offset = i2c_dev->buf_offset; -	for (i = 0; i < 0x10; i++) { -		temp = HDMI_READ(HDMI_HI2CRDB0 + (i * 4)); -		memcpy(buf + (offset + i * 4), &temp, 4); -	} -	i2c_dev->buf_offset += (0x10 * 4); - -	/* clearing read buffer full intr */ -	temp = HDMI_READ(HDMI_HISR); -	HDMI_WRITE(HDMI_HISR, temp | HDMI_INTR_I2C_FULL); -	HDMI_READ(HDMI_HISR); - -	/* continue read transaction */ -	temp = HDMI_READ(HDMI_HI2CHCR); -	HDMI_WRITE(HDMI_HI2CHCR, temp | HI2C_READ_CONTINUE); -	HDMI_READ(HDMI_HI2CHCR); - -	i2c_dev->status = I2C_READ_DONE; -	return; -} - -static void hdmi_i2c_transaction_done(struct mrst_hdmi_dev *hdmi_dev) -{ -	struct hdmi_i2c_dev *i2c_dev = hdmi_dev->i2c_dev; -	u32 temp; - -	/* clear transaction done intr */ -	temp = HDMI_READ(HDMI_HISR); -	HDMI_WRITE(HDMI_HISR, temp | HDMI_INTR_I2C_DONE); -	HDMI_READ(HDMI_HISR); - - -	temp = HDMI_READ(HDMI_HI2CHCR); -	HDMI_WRITE(HDMI_HI2CHCR, temp & ~HI2C_ENABLE_TRANSACTION); -	HDMI_READ(HDMI_HI2CHCR); - -	i2c_dev->status = I2C_TRANSACTION_DONE; -	return; -} - -static irqreturn_t mrst_hdmi_i2c_handler(int this_irq, void *dev) -{ -	struct mrst_hdmi_dev *hdmi_dev = dev; -	struct hdmi_i2c_dev *i2c_dev = hdmi_dev->i2c_dev; -	u32 stat; - -	stat = HDMI_READ(HDMI_HISR); - -	if (stat & HDMI_INTR_HPD) { -		HDMI_WRITE(HDMI_HISR, stat | HDMI_INTR_HPD); -		HDMI_READ(HDMI_HISR); -	} - -	if (stat & HDMI_INTR_I2C_FULL) -		hdmi_i2c_read(hdmi_dev); - -	if (stat & HDMI_INTR_I2C_DONE) -		hdmi_i2c_transaction_done(hdmi_dev); - -	complete(&i2c_dev->complete); - -	return IRQ_HANDLED; -} - -/* - * choose alternate function 2 of GPIO pin 52, 53, - * which is used by HDMI I2C logic - */ -static void mrst_hdmi_i2c_gpio_fix(void) -{ -	void *base; -	unsigned int gpio_base = 0xff12c000; -	int gpio_len = 0x1000; -	u32 temp; - -	base = ioremap((resource_size_t)gpio_base, gpio_len); -	if (base == NULL) { -		DRM_ERROR("gpio ioremap fail\n"); -		return; -	} - -	temp = readl(base + 0x44); -	DRM_DEBUG_DRIVER("old gpio val %x\n", temp); -	writel((temp | 0x00000a00), (base +  0x44)); -	temp = readl(base + 0x44); -	DRM_DEBUG_DRIVER("new gpio val %x\n", temp); - -	iounmap(base); -} - -int mrst_hdmi_i2c_init(struct pci_dev *dev) -{ -	struct mrst_hdmi_dev *hdmi_dev; -	struct hdmi_i2c_dev *i2c_dev; -	int ret; - -	hdmi_dev = pci_get_drvdata(dev); - -	i2c_dev = kzalloc(sizeof(struct hdmi_i2c_dev), GFP_KERNEL); -	if (i2c_dev == NULL) { -		DRM_ERROR("Can't allocate interface\n"); -		ret = -ENOMEM; -		goto exit; -	} - -	i2c_dev->adap = &mrst_hdmi_i2c_adapter; -	i2c_dev->status = I2C_STAT_INIT; -	init_completion(&i2c_dev->complete); -	mutex_init(&i2c_dev->i2c_lock); -	i2c_set_adapdata(&mrst_hdmi_i2c_adapter, hdmi_dev); -	hdmi_dev->i2c_dev = i2c_dev; - -	/* Enable HDMI I2C function on gpio */ -	mrst_hdmi_i2c_gpio_fix(); - -	/* request irq */ -	ret = request_irq(dev->irq, mrst_hdmi_i2c_handler, IRQF_SHARED, -			  mrst_hdmi_i2c_adapter.name, hdmi_dev); -	if (ret) { -		DRM_ERROR("Failed to request IRQ for I2C controller\n"); -		goto err; -	} - -	/* Adapter registration */ -	ret = i2c_add_numbered_adapter(&mrst_hdmi_i2c_adapter); -	return ret; - -err: -	kfree(i2c_dev); -exit: -	return ret; -} - -void mrst_hdmi_i2c_exit(struct pci_dev *dev) -{ -	struct mrst_hdmi_dev *hdmi_dev; -	struct hdmi_i2c_dev *i2c_dev; - -	hdmi_dev = pci_get_drvdata(dev); -	if (i2c_del_adapter(&mrst_hdmi_i2c_adapter)) -		DRM_DEBUG_DRIVER("Failed to delete hdmi-i2c adapter\n"); - -	i2c_dev = hdmi_dev->i2c_dev; -	kfree(i2c_dev); -	free_irq(dev->irq, hdmi_dev); -} diff --git a/drivers/staging/gma500/mrst_lvds.c b/drivers/staging/gma500/mrst_lvds.c deleted file mode 100644 index e7999a2a379..00000000000 --- a/drivers/staging/gma500/mrst_lvds.c +++ /dev/null @@ -1,407 +0,0 @@ -/* - * Copyright © 2006-2009 Intel Corporation - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - * Authors: - *	Eric Anholt <eric@anholt.net> - *	Dave Airlie <airlied@linux.ie> - *	Jesse Barnes <jesse.barnes@intel.com> - */ - -#include <linux/i2c.h> -#include <drm/drmP.h> -#include <asm/mrst.h> - -#include "intel_bios.h" -#include "psb_drv.h" -#include "psb_intel_drv.h" -#include "psb_intel_reg.h" -#include "power.h" -#include <linux/pm_runtime.h> - -/* The max/min PWM frequency in BPCR[31:17] - */ -/* The smallest number is 1 (not 0) that can fit in the - * 15-bit field of the and then*/ -/* shifts to the left by one bit to get the actual 16-bit - * value that the 15-bits correspond to.*/ -#define MRST_BLC_MAX_PWM_REG_FREQ	    0xFFFF -#define BRIGHTNESS_MAX_LEVEL 100 - -/** - * Sets the power state for the panel. - */ -static void mrst_lvds_set_power(struct drm_device *dev, -				struct psb_intel_output *output, bool on) -{ -	u32 pp_status; -	struct drm_psb_private *dev_priv = dev->dev_private; - -	if (!gma_power_begin(dev, true)) -		return; - -	if (on) { -		REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) | -			  POWER_TARGET_ON); -		do { -			pp_status = REG_READ(PP_STATUS); -		} while ((pp_status & (PP_ON | PP_READY)) == PP_READY); -		dev_priv->is_lvds_on = true; -		if (dev_priv->ops->lvds_bl_power) -			dev_priv->ops->lvds_bl_power(dev, true); -	} else { -		if (dev_priv->ops->lvds_bl_power) -			dev_priv->ops->lvds_bl_power(dev, false); -		REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) & -			  ~POWER_TARGET_ON); -		do { -			pp_status = REG_READ(PP_STATUS); -		} while (pp_status & PP_ON); -		dev_priv->is_lvds_on = false; -		pm_request_idle(&dev->pdev->dev); -	} -	gma_power_end(dev); -} - -static void mrst_lvds_dpms(struct drm_encoder *encoder, int mode) -{ -	struct drm_device *dev = encoder->dev; -	struct psb_intel_output *output = enc_to_psb_intel_output(encoder); - -	if (mode == DRM_MODE_DPMS_ON) -		mrst_lvds_set_power(dev, output, true); -	else -		mrst_lvds_set_power(dev, output, false); - -	/* XXX: We never power down the LVDS pairs. */ -} - -static void mrst_lvds_mode_set(struct drm_encoder *encoder, -			       struct drm_display_mode *mode, -			       struct drm_display_mode *adjusted_mode) -{ -	struct psb_intel_mode_device *mode_dev = -				enc_to_psb_intel_output(encoder)->mode_dev; -	struct drm_device *dev = encoder->dev; -	struct drm_psb_private *dev_priv = dev->dev_private; -	u32 lvds_port; -	uint64_t v = DRM_MODE_SCALE_FULLSCREEN; - -	if (!gma_power_begin(dev, true)) -		return; - -	/* -	 * The LVDS pin pair will already have been turned on in the -	 * psb_intel_crtc_mode_set since it has a large impact on the DPLL -	 * settings. -	 */ -	lvds_port = (REG_READ(LVDS) & -		    (~LVDS_PIPEB_SELECT)) | -		    LVDS_PORT_EN | -		    LVDS_BORDER_EN; - -	/* If the firmware says dither on Moorestown, or the BIOS does -	   on Oaktrail then enable dithering */ -	if (mode_dev->panel_wants_dither || dev_priv->lvds_dither) -		lvds_port |= MRST_PANEL_8TO6_DITHER_ENABLE; - -	REG_WRITE(LVDS, lvds_port); - -	drm_connector_property_get_value( -		&enc_to_psb_intel_output(encoder)->base, -		dev->mode_config.scaling_mode_property, -		&v); - -	if (v == DRM_MODE_SCALE_NO_SCALE) -		REG_WRITE(PFIT_CONTROL, 0); -	else if (v == DRM_MODE_SCALE_ASPECT) { -		if ((mode->vdisplay != adjusted_mode->crtc_vdisplay) || -		    (mode->hdisplay != adjusted_mode->crtc_hdisplay)) { -			if ((adjusted_mode->crtc_hdisplay * mode->vdisplay) == -			    (mode->hdisplay * adjusted_mode->crtc_vdisplay)) -				REG_WRITE(PFIT_CONTROL, PFIT_ENABLE); -			else if ((adjusted_mode->crtc_hdisplay * -				mode->vdisplay) > (mode->hdisplay * -				adjusted_mode->crtc_vdisplay)) -				REG_WRITE(PFIT_CONTROL, PFIT_ENABLE | -					  PFIT_SCALING_MODE_PILLARBOX); -			else -				REG_WRITE(PFIT_CONTROL, PFIT_ENABLE | -					  PFIT_SCALING_MODE_LETTERBOX); -		} else -			REG_WRITE(PFIT_CONTROL, PFIT_ENABLE); -	} else /*(v == DRM_MODE_SCALE_FULLSCREEN)*/ -		REG_WRITE(PFIT_CONTROL, PFIT_ENABLE); - -	gma_power_end(dev); -} - -static void mrst_lvds_prepare(struct drm_encoder *encoder) -{ -	struct drm_device *dev = encoder->dev; -	struct psb_intel_output *output = enc_to_psb_intel_output(encoder); -	struct psb_intel_mode_device *mode_dev = output->mode_dev; - -	if (!gma_power_begin(dev, true)) -		return; - -	mode_dev->saveBLC_PWM_CTL = REG_READ(BLC_PWM_CTL); -	mode_dev->backlight_duty_cycle = (mode_dev->saveBLC_PWM_CTL & -					  BACKLIGHT_DUTY_CYCLE_MASK); -	mrst_lvds_set_power(dev, output, false); -	gma_power_end(dev); -} - -static u32 mrst_lvds_get_max_backlight(struct drm_device *dev) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; -	u32 ret; - -	if (gma_power_begin(dev, false)) { -		ret = ((REG_READ(BLC_PWM_CTL) & -			  BACKLIGHT_MODULATION_FREQ_MASK) >> -			  BACKLIGHT_MODULATION_FREQ_SHIFT) * 2; - -		gma_power_end(dev); -	} else -		ret = ((dev_priv->saveBLC_PWM_CTL & -			  BACKLIGHT_MODULATION_FREQ_MASK) >> -			  BACKLIGHT_MODULATION_FREQ_SHIFT) * 2; - -	return ret; -} - -static void mrst_lvds_commit(struct drm_encoder *encoder) -{ -	struct drm_device *dev = encoder->dev; -	struct psb_intel_output *output = enc_to_psb_intel_output(encoder); -	struct psb_intel_mode_device *mode_dev = output->mode_dev; - -	if (mode_dev->backlight_duty_cycle == 0) -		mode_dev->backlight_duty_cycle = -					mrst_lvds_get_max_backlight(dev); -	mrst_lvds_set_power(dev, output, true); -} - -static const struct drm_encoder_helper_funcs mrst_lvds_helper_funcs = { -	.dpms = mrst_lvds_dpms, -	.mode_fixup = psb_intel_lvds_mode_fixup, -	.prepare = mrst_lvds_prepare, -	.mode_set = mrst_lvds_mode_set, -	.commit = mrst_lvds_commit, -}; - -static struct drm_display_mode lvds_configuration_modes[] = { -	/* hard coded fixed mode for TPO LTPS LPJ040K001A */ -	{ DRM_MODE("800x480",  DRM_MODE_TYPE_DRIVER, 33264, 800, 836, -		   846, 1056, 0, 480, 489, 491, 525, 0, 0) }, -	/* hard coded fixed mode for LVDS 800x480 */ -	{ DRM_MODE("800x480",  DRM_MODE_TYPE_DRIVER, 30994, 800, 801, -		   802, 1024, 0, 480, 481, 482, 525, 0, 0) }, -	/* hard coded fixed mode for Samsung 480wsvga LVDS 1024x600@75 */ -	{ DRM_MODE("1024x600", DRM_MODE_TYPE_DRIVER, 53990, 1024, 1072, -		   1104, 1184, 0, 600, 603, 604, 608, 0, 0) }, -	/* hard coded fixed mode for Samsung 480wsvga LVDS 1024x600@75 */ -	{ DRM_MODE("1024x600", DRM_MODE_TYPE_DRIVER, 53990, 1024, 1104, -		   1136, 1184, 0, 600, 603, 604, 608, 0, 0) }, -	/* hard coded fixed mode for Sharp wsvga LVDS 1024x600 */ -	{ DRM_MODE("1024x600", DRM_MODE_TYPE_DRIVER, 48885, 1024, 1124, -		   1204, 1312, 0, 600, 607, 610, 621, 0, 0) }, -	/* hard coded fixed mode for LVDS 1024x768 */ -	{ DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 65000, 1024, 1048, -		   1184, 1344, 0, 768, 771, 777, 806, 0, 0) }, -	/* hard coded fixed mode for LVDS 1366x768 */ -	{ DRM_MODE("1366x768", DRM_MODE_TYPE_DRIVER, 77500, 1366, 1430, -		   1558, 1664, 0, 768, 769, 770, 776, 0, 0) }, -}; - -/* Returns the panel fixed mode from configuration. */ - -static struct drm_display_mode * -mrst_lvds_get_configuration_mode(struct drm_device *dev) -{ -	struct drm_display_mode *mode = NULL; -	struct drm_psb_private *dev_priv = dev->dev_private; -	struct mrst_timing_info *ti = &dev_priv->gct_data.DTD; - -	if (dev_priv->vbt_data.size != 0x00) { /*if non-zero, then use vbt*/ -		mode = kzalloc(sizeof(*mode), GFP_KERNEL); -		if (!mode) -			return NULL; - -		mode->hdisplay = (ti->hactive_hi << 8) | ti->hactive_lo; -		mode->vdisplay = (ti->vactive_hi << 8) | ti->vactive_lo; -		mode->hsync_start = mode->hdisplay + \ -				((ti->hsync_offset_hi << 8) | \ -				ti->hsync_offset_lo); -		mode->hsync_end = mode->hsync_start + \ -				((ti->hsync_pulse_width_hi << 8) | \ -				ti->hsync_pulse_width_lo); -		mode->htotal = mode->hdisplay + ((ti->hblank_hi << 8) | \ -							ti->hblank_lo); -		mode->vsync_start = \ -			mode->vdisplay + ((ti->vsync_offset_hi << 4) | \ -						ti->vsync_offset_lo); -		mode->vsync_end = \ -			mode->vsync_start + ((ti->vsync_pulse_width_hi << 4) | \ -						ti->vsync_pulse_width_lo); -		mode->vtotal = mode->vdisplay + \ -				((ti->vblank_hi << 8) | ti->vblank_lo); -		mode->clock = ti->pixel_clock * 10; -#if 0 -		printk(KERN_INFO "hdisplay is %d\n", mode->hdisplay); -		printk(KERN_INFO "vdisplay is %d\n", mode->vdisplay); -		printk(KERN_INFO "HSS is %d\n", mode->hsync_start); -		printk(KERN_INFO "HSE is %d\n", mode->hsync_end); -		printk(KERN_INFO "htotal is %d\n", mode->htotal); -		printk(KERN_INFO "VSS is %d\n", mode->vsync_start); -		printk(KERN_INFO "VSE is %d\n", mode->vsync_end); -		printk(KERN_INFO "vtotal is %d\n", mode->vtotal); -		printk(KERN_INFO "clock is %d\n", mode->clock); -#endif -	} else -		mode = drm_mode_duplicate(dev, &lvds_configuration_modes[2]); - -	drm_mode_set_name(mode); -	drm_mode_set_crtcinfo(mode, 0); - -	return mode; -} - -/** - * mrst_lvds_init - setup LVDS connectors on this device - * @dev: drm device - * - * Create the connector, register the LVDS DDC bus, and try to figure out what - * modes we can display on the LVDS panel (if present). - */ -void mrst_lvds_init(struct drm_device *dev, -		    struct psb_intel_mode_device *mode_dev) -{ -	struct psb_intel_output *psb_intel_output; -	struct drm_connector *connector; -	struct drm_encoder *encoder; -	struct drm_psb_private *dev_priv = -				(struct drm_psb_private *) dev->dev_private; -	struct edid *edid; -	int ret = 0; -	struct i2c_adapter *i2c_adap; -	struct drm_display_mode *scan;	/* *modes, *bios_mode; */ - -	psb_intel_output = kzalloc(sizeof(struct psb_intel_output), GFP_KERNEL); -	if (!psb_intel_output) -		return; - -	psb_intel_output->mode_dev = mode_dev; -	connector = &psb_intel_output->base; -	encoder = &psb_intel_output->enc; -	dev_priv->is_lvds_on = true; -	drm_connector_init(dev, &psb_intel_output->base, -			   &psb_intel_lvds_connector_funcs, -			   DRM_MODE_CONNECTOR_LVDS); - -	drm_encoder_init(dev, &psb_intel_output->enc, &psb_intel_lvds_enc_funcs, -			 DRM_MODE_ENCODER_LVDS); - -	drm_mode_connector_attach_encoder(&psb_intel_output->base, -					  &psb_intel_output->enc); -	psb_intel_output->type = INTEL_OUTPUT_LVDS; - -	drm_encoder_helper_add(encoder, &mrst_lvds_helper_funcs); -	drm_connector_helper_add(connector, -				 &psb_intel_lvds_connector_helper_funcs); -	connector->display_info.subpixel_order = SubPixelHorizontalRGB; -	connector->interlace_allowed = false; -	connector->doublescan_allowed = false; - -	drm_connector_attach_property(connector, -					dev->mode_config.scaling_mode_property, -					DRM_MODE_SCALE_FULLSCREEN); -	drm_connector_attach_property(connector, -					dev_priv->backlight_property, -					BRIGHTNESS_MAX_LEVEL); - -	mode_dev->panel_wants_dither = false; -	if (dev_priv->vbt_data.size != 0x00) -		mode_dev->panel_wants_dither = (dev_priv->gct_data. -			Panel_Port_Control & MRST_PANEL_8TO6_DITHER_ENABLE); - -	/* -	 * LVDS discovery: -	 * 1) check for EDID on DDC -	 * 2) check for VBT data -	 * 3) check to see if LVDS is already on -	 *    if none of the above, no panel -	 * 4) make sure lid is open -	 *    if closed, act like it's not there for now -	 */ - -	i2c_adap = i2c_get_adapter(dev_priv->ops->i2c_bus); - -	if (i2c_adap == NULL) -		dev_err(dev->dev, "No ddc adapter available!\n"); -	/* -	 * Attempt to get the fixed panel mode from DDC.  Assume that the -	 * preferred mode is the right one. -	 */ -	if (i2c_adap) { -		edid = drm_get_edid(connector, i2c_adap); -		if (edid) { -			drm_mode_connector_update_edid_property(connector, -									edid); -			ret = drm_add_edid_modes(connector, edid); -			kfree(edid); -		} - -		list_for_each_entry(scan, &connector->probed_modes, head) { -			if (scan->type & DRM_MODE_TYPE_PREFERRED) { -				mode_dev->panel_fixed_mode = -				    drm_mode_duplicate(dev, scan); -				goto out;	/* FIXME: check for quirks */ -			} -		} -	} -	/* -	 * If we didn't get EDID, try geting panel timing -	 * from configuration data -	 */ -	mode_dev->panel_fixed_mode = mrst_lvds_get_configuration_mode(dev); - -	if (mode_dev->panel_fixed_mode) { -		mode_dev->panel_fixed_mode->type |= DRM_MODE_TYPE_PREFERRED; -		goto out;	/* FIXME: check for quirks */ -	} - -	/* If we still don't have a mode after all that, give up. */ -	if (!mode_dev->panel_fixed_mode) { -		dev_err(dev->dev, "Found no modes on the lvds, ignoring the LVDS\n"); -		goto failed_find; -	} - -out: -	drm_sysfs_connector_add(connector); -	return; - -failed_find: -	dev_dbg(dev->dev, "No LVDS modes found, disabling.\n"); -	if (psb_intel_output->ddc_bus) -		psb_intel_i2c_destroy(psb_intel_output->ddc_bus); - -/* failed_ddc: */ - -	drm_encoder_cleanup(encoder); -	drm_connector_cleanup(connector); -	kfree(connector); -} - diff --git a/drivers/staging/gma500/power.c b/drivers/staging/gma500/power.c deleted file mode 100644 index 40825703833..00000000000 --- a/drivers/staging/gma500/power.c +++ /dev/null @@ -1,318 +0,0 @@ -/************************************************************************** - * Copyright (c) 2009-2011, Intel Corporation. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * Authors: - *    Benjamin Defnet <benjamin.r.defnet@intel.com> - *    Rajesh Poornachandran <rajesh.poornachandran@intel.com> - * Massively reworked - *    Alan Cox <alan@linux.intel.com> - */ - -#include "power.h" -#include "psb_drv.h" -#include "psb_reg.h" -#include "psb_intel_reg.h" -#include <linux/mutex.h> -#include <linux/pm_runtime.h> - -static struct mutex power_mutex;	/* Serialize power ops */ -static spinlock_t power_ctrl_lock;	/* Serialize power claim */ - -/** - *	gma_power_init		-	initialise power manager - *	@dev: our device - * - *	Set up for power management tracking of our hardware. - */ -void gma_power_init(struct drm_device *dev) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; - -	/* FIXME: Move APM/OSPM base into relevant device code */ -	dev_priv->apm_base = dev_priv->apm_reg & 0xffff; -	dev_priv->ospm_base &= 0xffff; - -	dev_priv->display_power = true;	/* We start active */ -	dev_priv->display_count = 0;	/* Currently no users */ -	dev_priv->suspended = false;	/* And not suspended */ -	spin_lock_init(&power_ctrl_lock); -	mutex_init(&power_mutex); - -	dev_priv->ops->init_pm(dev); -} - -/** - *	gma_power_uninit	-	end power manager - *	@dev: device to end for - * - *	Undo the effects of gma_power_init - */ -void gma_power_uninit(struct drm_device *dev) -{ -	pm_runtime_disable(&dev->pdev->dev); -	pm_runtime_set_suspended(&dev->pdev->dev); -} - -/** - *	gma_suspend_display	-	suspend the display logic - *	@dev: our DRM device - * - *	Suspend the display logic of the graphics interface - */ -static void gma_suspend_display(struct drm_device *dev) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; - -	if (!dev_priv->display_power) -		return; -	dev_priv->ops->save_regs(dev); -	dev_priv->ops->power_down(dev); -	dev_priv->display_power = false; -} - -/** - *	gma_resume_display	-	resume display side logic - * - *	Resume the display hardware restoring state and enabling - *	as necessary. - */ -static void gma_resume_display(struct pci_dev *pdev) -{ -	struct drm_device *dev = pci_get_drvdata(pdev); -	struct drm_psb_private *dev_priv = dev->dev_private; - -	if (dev_priv->display_power) -		return; - -	/* turn on the display power island */ -	dev_priv->ops->power_up(dev); -	dev_priv->suspended = false; -	dev_priv->display_power = true; - -	PSB_WVDC32(dev_priv->pge_ctl | _PSB_PGETBL_ENABLED, PSB_PGETBL_CTL); -	pci_write_config_word(pdev, PSB_GMCH_CTRL, -			dev_priv->gmch_ctrl | _PSB_GMCH_ENABLED); -	dev_priv->ops->restore_regs(dev); -} - -/** - *	gma_suspend_pci		-	suspend PCI side - *	@pdev: PCI device - * - *	Perform the suspend processing on our PCI device state - */ -static void gma_suspend_pci(struct pci_dev *pdev) -{ -	struct drm_device *dev = pci_get_drvdata(pdev); -	struct drm_psb_private *dev_priv = dev->dev_private; -	int bsm, vbt; - -	if (dev_priv->suspended) -		return; - -	pci_save_state(pdev); -	pci_read_config_dword(pdev, 0x5C, &bsm); -	dev_priv->saveBSM = bsm; -	pci_read_config_dword(pdev, 0xFC, &vbt); -	dev_priv->saveVBT = vbt; -	pci_read_config_dword(pdev, PSB_PCIx_MSI_ADDR_LOC, &dev_priv->msi_addr); -	pci_read_config_dword(pdev, PSB_PCIx_MSI_DATA_LOC, &dev_priv->msi_data); - -	pci_disable_device(pdev); -	pci_set_power_state(pdev, PCI_D3hot); - -	dev_priv->suspended = true; -} - -/** - *	gma_resume_pci		-	resume helper - *	@dev: our PCI device - * - *	Perform the resume processing on our PCI device state - rewrite - *	register state and re-enable the PCI device - */ -static bool gma_resume_pci(struct pci_dev *pdev) -{ -	struct drm_device *dev = pci_get_drvdata(pdev); -	struct drm_psb_private *dev_priv = dev->dev_private; -	int ret; - -	if (!dev_priv->suspended) -		return true; - -	pci_set_power_state(pdev, PCI_D0); -	pci_restore_state(pdev); -	pci_write_config_dword(pdev, 0x5c, dev_priv->saveBSM); -	pci_write_config_dword(pdev, 0xFC, dev_priv->saveVBT); -	/* restoring MSI address and data in PCIx space */ -	pci_write_config_dword(pdev, PSB_PCIx_MSI_ADDR_LOC, dev_priv->msi_addr); -	pci_write_config_dword(pdev, PSB_PCIx_MSI_DATA_LOC, dev_priv->msi_data); -	ret = pci_enable_device(pdev); - -	if (ret != 0) -		dev_err(&pdev->dev, "pci_enable failed: %d\n", ret); -	else -		dev_priv->suspended = false; -	return !dev_priv->suspended; -} - -/** - *	gma_power_suspend		-	bus callback for suspend - *	@pdev: our PCI device - *	@state: suspend type - * - *	Called back by the PCI layer during a suspend of the system. We - *	perform the necessary shut down steps and save enough state that - *	we can undo this when resume is called. - */ -int gma_power_suspend(struct device *_dev) -{ -	struct pci_dev *pdev = container_of(_dev, struct pci_dev, dev); -	struct drm_device *dev = pci_get_drvdata(pdev); -	struct drm_psb_private *dev_priv = dev->dev_private; - -	mutex_lock(&power_mutex); -	if (!dev_priv->suspended) { -		if (dev_priv->display_count) { -			mutex_unlock(&power_mutex); -			return -EBUSY; -		} -		psb_irq_uninstall(dev); -		gma_suspend_display(dev); -		gma_suspend_pci(pdev); -	} -	mutex_unlock(&power_mutex); -	return 0; -} - -/** - *	gma_power_resume		-	resume power - *	@pdev: PCI device - * - *	Resume the PCI side of the graphics and then the displays - */ -int gma_power_resume(struct device *_dev) -{ -	struct pci_dev *pdev = container_of(_dev, struct pci_dev, dev); -	struct drm_device *dev = pci_get_drvdata(pdev); - -	mutex_lock(&power_mutex); -	gma_resume_pci(pdev); -	gma_resume_display(pdev); -	psb_irq_preinstall(dev); -	psb_irq_postinstall(dev); -	mutex_unlock(&power_mutex); -	return 0; -} - -/** - *	gma_power_is_on		-	returne true if power is on - *	@dev: our DRM device - * - *	Returns true if the display island power is on at this moment - */ -bool gma_power_is_on(struct drm_device *dev) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; -	return dev_priv->display_power; -} - -/** - *	gma_power_begin		-	begin requiring power - *	@dev: our DRM device - *	@force_on: true to force power on - * - *	Begin an action that requires the display power island is enabled. - *	We refcount the islands. - */ -bool gma_power_begin(struct drm_device *dev, bool force_on) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; -	int ret; -	unsigned long flags; - -	spin_lock_irqsave(&power_ctrl_lock, flags); -	/* Power already on ? */ -	if (dev_priv->display_power) { -		dev_priv->display_count++; -		pm_runtime_get(&dev->pdev->dev); -		spin_unlock_irqrestore(&power_ctrl_lock, flags); -		return true; -	} -	if (force_on == false) -		goto out_false; - -	/* Ok power up needed */ -	ret = gma_resume_pci(dev->pdev); -	if (ret == 0) { -		/* FIXME: we want to defer this for Medfield/Oaktrail */ -		gma_resume_display(dev->pdev); -		psb_irq_preinstall(dev); -		psb_irq_postinstall(dev); -		pm_runtime_get(&dev->pdev->dev); -		dev_priv->display_count++; -		spin_unlock_irqrestore(&power_ctrl_lock, flags); -		return true; -	} -out_false: -	spin_unlock_irqrestore(&power_ctrl_lock, flags); -	return false; -} - -/** - *	gma_power_end		-	end use of power - *	@dev: Our DRM device - * - *	Indicate that one of our gma_power_begin() requested periods when - *	the diplay island power is needed has completed. - */ -void gma_power_end(struct drm_device *dev) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; -	unsigned long flags; -	spin_lock_irqsave(&power_ctrl_lock, flags); -	dev_priv->display_count--; -	WARN_ON(dev_priv->display_count < 0); -	spin_unlock_irqrestore(&power_ctrl_lock, flags); -	pm_runtime_put(&dev->pdev->dev); -} - -int psb_runtime_suspend(struct device *dev) -{ -	return gma_power_suspend(dev); -} - -int psb_runtime_resume(struct device *dev) -{ -	return gma_power_resume(dev);; -} - -int psb_runtime_idle(struct device *dev) -{ -	struct drm_device *drmdev = pci_get_drvdata(to_pci_dev(dev)); -	struct drm_psb_private *dev_priv = drmdev->dev_private; -	if (dev_priv->display_count) -		return 0; -	else -		return 1; -} diff --git a/drivers/staging/gma500/power.h b/drivers/staging/gma500/power.h deleted file mode 100644 index 1969d2ecb32..00000000000 --- a/drivers/staging/gma500/power.h +++ /dev/null @@ -1,67 +0,0 @@ -/************************************************************************** - * Copyright (c) 2009-2011, Intel Corporation. - * All Rights Reserved. - - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * Authors: - *    Benjamin Defnet <benjamin.r.defnet@intel.com> - *    Rajesh Poornachandran <rajesh.poornachandran@intel.com> - * Massively reworked - *    Alan Cox <alan@linux.intel.com> - */ -#ifndef _PSB_POWERMGMT_H_ -#define _PSB_POWERMGMT_H_ - -#include <linux/pci.h> -#include <drm/drmP.h> - -void gma_power_init(struct drm_device *dev); -void gma_power_uninit(struct drm_device *dev); - -/* - * The kernel bus power management  will call these functions - */ -int gma_power_suspend(struct device *dev); -int gma_power_resume(struct device *dev); - -/* - * These are the functions the driver should use to wrap all hw access - * (i.e. register reads and writes) - */ -bool gma_power_begin(struct drm_device *dev, bool force); -void gma_power_end(struct drm_device *dev); - -/* - * Use this function to do an instantaneous check for if the hw is on. - * Only use this in cases where you know the mutex is already held such - * as in irq install/uninstall and you need to - * prevent a deadlock situation.  Otherwise use gma_power_begin(). - */ -bool gma_power_is_on(struct drm_device *dev); - -/* - * GFX-Runtime PM callbacks - */ -int psb_runtime_suspend(struct device *dev); -int psb_runtime_resume(struct device *dev); -int psb_runtime_idle(struct device *dev); - -#endif /*_PSB_POWERMGMT_H_*/ diff --git a/drivers/staging/gma500/psb_device.c b/drivers/staging/gma500/psb_device.c deleted file mode 100644 index b97aa78519f..00000000000 --- a/drivers/staging/gma500/psb_device.c +++ /dev/null @@ -1,321 +0,0 @@ -/************************************************************************** - * Copyright (c) 2011, Intel Corporation. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - **************************************************************************/ - -#include <linux/backlight.h> -#include <drm/drmP.h> -#include <drm/drm.h> -#include "psb_drm.h" -#include "psb_drv.h" -#include "psb_reg.h" -#include "psb_intel_reg.h" -#include "intel_bios.h" - - -static int psb_output_init(struct drm_device *dev) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; -	psb_intel_lvds_init(dev, &dev_priv->mode_dev); -	psb_intel_sdvo_init(dev, SDVOB); -	return 0; -} - -#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE - -/* - *	Poulsbo Backlight Interfaces - */ - -#define BLC_PWM_PRECISION_FACTOR 100	/* 10000000 */ -#define BLC_PWM_FREQ_CALC_CONSTANT 32 -#define MHz 1000000 - -#define PSB_BLC_PWM_PRECISION_FACTOR    10 -#define PSB_BLC_MAX_PWM_REG_FREQ        0xFFFE -#define PSB_BLC_MIN_PWM_REG_FREQ        0x2 - -#define PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR (0xFFFE) -#define PSB_BACKLIGHT_PWM_CTL_SHIFT	(16) - -static int psb_brightness; -static struct backlight_device *psb_backlight_device; - -static int psb_get_brightness(struct backlight_device *bd) -{ -	/* return locally cached var instead of HW read (due to DPST etc.) */ -	/* FIXME: ideally return actual value in case firmware fiddled with -	   it */ -	return psb_brightness; -} - - -static int psb_backlight_setup(struct drm_device *dev) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; -	unsigned long core_clock; -	/* u32 bl_max_freq; */ -	/* unsigned long value; */ -	u16 bl_max_freq; -	uint32_t value; -	uint32_t blc_pwm_precision_factor; - -	/* get bl_max_freq and pol from dev_priv*/ -	if (!dev_priv->lvds_bl) { -		dev_err(dev->dev, "Has no valid LVDS backlight info\n"); -		return -ENOENT; -	} -	bl_max_freq = dev_priv->lvds_bl->freq; -	blc_pwm_precision_factor = PSB_BLC_PWM_PRECISION_FACTOR; - -	core_clock = dev_priv->core_freq; - -	value = (core_clock * MHz) / BLC_PWM_FREQ_CALC_CONSTANT; -	value *= blc_pwm_precision_factor; -	value /= bl_max_freq; -	value /= blc_pwm_precision_factor; - -	if (value > (unsigned long long)PSB_BLC_MAX_PWM_REG_FREQ || -		 value < (unsigned long long)PSB_BLC_MIN_PWM_REG_FREQ) -				return -ERANGE; -	else { -		value &= PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR; -		REG_WRITE(BLC_PWM_CTL, -			(value << PSB_BACKLIGHT_PWM_CTL_SHIFT) | (value)); -	} -	return 0; -} - -static int psb_set_brightness(struct backlight_device *bd) -{ -	struct drm_device *dev = bl_get_data(psb_backlight_device); -	int level = bd->props.brightness; - -	/* Percentage 1-100% being valid */ -	if (level < 1) -		level = 1; - -	psb_intel_lvds_set_brightness(dev, level); -	psb_brightness = level; -	return 0; -} - -static const struct backlight_ops psb_ops = { -	.get_brightness = psb_get_brightness, -	.update_status  = psb_set_brightness, -}; - -static int psb_backlight_init(struct drm_device *dev) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; -	int ret; -	struct backlight_properties props; - -	memset(&props, 0, sizeof(struct backlight_properties)); -	props.max_brightness = 100; -	props.type = BACKLIGHT_PLATFORM; - -	psb_backlight_device = backlight_device_register("psb-bl", -					NULL, (void *)dev, &psb_ops, &props); -	if (IS_ERR(psb_backlight_device)) -		return PTR_ERR(psb_backlight_device); - -	ret = psb_backlight_setup(dev); -	if (ret < 0) { -		backlight_device_unregister(psb_backlight_device); -		psb_backlight_device = NULL; -		return ret; -	} -	psb_backlight_device->props.brightness = 100; -	psb_backlight_device->props.max_brightness = 100; -	backlight_update_status(psb_backlight_device); -	dev_priv->backlight_device = psb_backlight_device; -	return 0; -} - -#endif - -/* - *	Provide the Poulsbo specific chip logic and low level methods - *	for power management - */ - -static void psb_init_pm(struct drm_device *dev) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; - -	u32 gating = PSB_RSGX32(PSB_CR_CLKGATECTL); -	gating &= ~3;	/* Disable 2D clock gating */ -	gating |= 1; -	PSB_WSGX32(gating, PSB_CR_CLKGATECTL); -	PSB_RSGX32(PSB_CR_CLKGATECTL); -} - -/** - *	psb_save_display_registers	-	save registers lost on suspend - *	@dev: our DRM device - * - *	Save the state we need in order to be able to restore the interface - *	upon resume from suspend - */ -static int psb_save_display_registers(struct drm_device *dev) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; -	struct drm_crtc *crtc; -	struct drm_connector *connector; - -	/* Display arbitration control + watermarks */ -	dev_priv->saveDSPARB = PSB_RVDC32(DSPARB); -	dev_priv->saveDSPFW1 = PSB_RVDC32(DSPFW1); -	dev_priv->saveDSPFW2 = PSB_RVDC32(DSPFW2); -	dev_priv->saveDSPFW3 = PSB_RVDC32(DSPFW3); -	dev_priv->saveDSPFW4 = PSB_RVDC32(DSPFW4); -	dev_priv->saveDSPFW5 = PSB_RVDC32(DSPFW5); -	dev_priv->saveDSPFW6 = PSB_RVDC32(DSPFW6); -	dev_priv->saveCHICKENBIT = PSB_RVDC32(DSPCHICKENBIT); - -	/* Save crtc and output state */ -	mutex_lock(&dev->mode_config.mutex); -	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { -		if (drm_helper_crtc_in_use(crtc)) -			crtc->funcs->save(crtc); -	} - -	list_for_each_entry(connector, &dev->mode_config.connector_list, head) -		connector->funcs->save(connector); - -	mutex_unlock(&dev->mode_config.mutex); -	return 0; -} - -/** - *	psb_restore_display_registers	-	restore lost register state - *	@dev: our DRM device - * - *	Restore register state that was lost during suspend and resume. - */ -static int psb_restore_display_registers(struct drm_device *dev) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; -	struct drm_crtc *crtc; -	struct drm_connector *connector; - -	/* Display arbitration + watermarks */ -	PSB_WVDC32(dev_priv->saveDSPARB, DSPARB); -	PSB_WVDC32(dev_priv->saveDSPFW1, DSPFW1); -	PSB_WVDC32(dev_priv->saveDSPFW2, DSPFW2); -	PSB_WVDC32(dev_priv->saveDSPFW3, DSPFW3); -	PSB_WVDC32(dev_priv->saveDSPFW4, DSPFW4); -	PSB_WVDC32(dev_priv->saveDSPFW5, DSPFW5); -	PSB_WVDC32(dev_priv->saveDSPFW6, DSPFW6); -	PSB_WVDC32(dev_priv->saveCHICKENBIT, DSPCHICKENBIT); - -	/*make sure VGA plane is off. it initializes to on after reset!*/ -	PSB_WVDC32(0x80000000, VGACNTRL); - -	mutex_lock(&dev->mode_config.mutex); -	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) -		if (drm_helper_crtc_in_use(crtc)) -			crtc->funcs->restore(crtc); - -	list_for_each_entry(connector, &dev->mode_config.connector_list, head) -		connector->funcs->restore(connector); - -	mutex_unlock(&dev->mode_config.mutex); -	return 0; -} - -static int psb_power_down(struct drm_device *dev) -{ -	return 0; -} - -static int psb_power_up(struct drm_device *dev) -{ -	return 0; -} - -static void psb_get_core_freq(struct drm_device *dev) -{ -	uint32_t clock; -	struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0); -	struct drm_psb_private *dev_priv = dev->dev_private; - -	/*pci_write_config_dword(pci_root, 0xD4, 0x00C32004);*/ -	/*pci_write_config_dword(pci_root, 0xD0, 0xE0033000);*/ - -	pci_write_config_dword(pci_root, 0xD0, 0xD0050300); -	pci_read_config_dword(pci_root, 0xD4, &clock); -	pci_dev_put(pci_root); - -	switch (clock & 0x07) { -	case 0: -		dev_priv->core_freq = 100; -		break; -	case 1: -		dev_priv->core_freq = 133; -		break; -	case 2: -		dev_priv->core_freq = 150; -		break; -	case 3: -		dev_priv->core_freq = 178; -		break; -	case 4: -		dev_priv->core_freq = 200; -		break; -	case 5: -	case 6: -	case 7: -		dev_priv->core_freq = 266; -	default: -		dev_priv->core_freq = 0; -	} -} - -static int psb_chip_setup(struct drm_device *dev) -{ -	psb_get_core_freq(dev); -	gma_intel_opregion_init(dev); -	psb_intel_init_bios(dev); -	return 0; -} - -const struct psb_ops psb_chip_ops = { -	.name = "Poulsbo", -	.accel_2d = 1, -	.pipes = 2, -	.crtcs = 2, -	.sgx_offset = PSB_SGX_OFFSET, -	.chip_setup = psb_chip_setup, - -	.crtc_helper = &psb_intel_helper_funcs, -	.crtc_funcs = &psb_intel_crtc_funcs, - -	.output_init = psb_output_init, - -#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE -	.backlight_init = psb_backlight_init, -#endif - -	.init_pm = psb_init_pm, -	.save_regs = psb_save_display_registers, -	.restore_regs = psb_restore_display_registers, -	.power_down = psb_power_down, -	.power_up = psb_power_up, -}; - diff --git a/drivers/staging/gma500/psb_drm.h b/drivers/staging/gma500/psb_drm.h deleted file mode 100644 index 0da84683568..00000000000 --- a/drivers/staging/gma500/psb_drm.h +++ /dev/null @@ -1,219 +0,0 @@ -/************************************************************************** - * Copyright (c) 2007-2011, Intel Corporation. - * All Rights Reserved. - * Copyright (c) 2008, Tungsten Graphics Inc.  Cedar Park, TX., USA. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - **************************************************************************/ - -#ifndef _PSB_DRM_H_ -#define _PSB_DRM_H_ - -#define PSB_NUM_PIPE 3 - -#define PSB_GPU_ACCESS_READ         (1ULL << 32) -#define PSB_GPU_ACCESS_WRITE        (1ULL << 33) -#define PSB_GPU_ACCESS_MASK         (PSB_GPU_ACCESS_READ | PSB_GPU_ACCESS_WRITE) - -#define PSB_BO_FLAG_COMMAND         (1ULL << 52) - -/* - * Feedback components: - */ - -struct drm_psb_sizes_arg { -	u32 ta_mem_size; -	u32 mmu_size; -	u32 pds_size; -	u32 rastgeom_size; -	u32 tt_size; -	u32 vram_size; -}; - -struct drm_psb_dpst_lut_arg { -	uint8_t lut[256]; -	int output_id; -}; - -#define PSB_DC_CRTC_SAVE 0x01 -#define PSB_DC_CRTC_RESTORE 0x02 -#define PSB_DC_OUTPUT_SAVE 0x04 -#define PSB_DC_OUTPUT_RESTORE 0x08 -#define PSB_DC_CRTC_MASK 0x03 -#define PSB_DC_OUTPUT_MASK 0x0C - -struct drm_psb_dc_state_arg { -	u32 flags; -	u32 obj_id; -}; - -struct drm_psb_mode_operation_arg { -	u32 obj_id; -	u16 operation; -	struct drm_mode_modeinfo mode; -	void *data; -}; - -struct drm_psb_stolen_memory_arg { -	u32 base; -	u32 size; -}; - -/*Display Register Bits*/ -#define REGRWBITS_PFIT_CONTROLS			(1 << 0) -#define REGRWBITS_PFIT_AUTOSCALE_RATIOS		(1 << 1) -#define REGRWBITS_PFIT_PROGRAMMED_SCALE_RATIOS	(1 << 2) -#define REGRWBITS_PIPEASRC			(1 << 3) -#define REGRWBITS_PIPEBSRC			(1 << 4) -#define REGRWBITS_VTOTAL_A			(1 << 5) -#define REGRWBITS_VTOTAL_B			(1 << 6) -#define REGRWBITS_DSPACNTR	(1 << 8) -#define REGRWBITS_DSPBCNTR	(1 << 9) -#define REGRWBITS_DSPCCNTR	(1 << 10) - -/*Overlay Register Bits*/ -#define OV_REGRWBITS_OVADD			(1 << 0) -#define OV_REGRWBITS_OGAM_ALL			(1 << 1) - -#define OVC_REGRWBITS_OVADD                  (1 << 2) -#define OVC_REGRWBITS_OGAM_ALL			(1 << 3) - -struct drm_psb_register_rw_arg { -	u32 b_force_hw_on; - -	u32 display_read_mask; -	u32 display_write_mask; - -	struct { -		u32 pfit_controls; -		u32 pfit_autoscale_ratios; -		u32 pfit_programmed_scale_ratios; -		u32 pipeasrc; -		u32 pipebsrc; -		u32 vtotal_a; -		u32 vtotal_b; -	} display; - -	u32 overlay_read_mask; -	u32 overlay_write_mask; - -	struct { -		u32 OVADD; -		u32 OGAMC0; -		u32 OGAMC1; -		u32 OGAMC2; -		u32 OGAMC3; -		u32 OGAMC4; -		u32 OGAMC5; -		u32 IEP_ENABLED; -		u32 IEP_BLE_MINMAX; -		u32 IEP_BSSCC_CONTROL; -		u32 b_wait_vblank; -	} overlay; - -	u32 sprite_enable_mask; -	u32 sprite_disable_mask; - -	struct { -		u32 dspa_control; -		u32 dspa_key_value; -		u32 dspa_key_mask; -		u32 dspc_control; -		u32 dspc_stride; -		u32 dspc_position; -		u32 dspc_linear_offset; -		u32 dspc_size; -		u32 dspc_surface; -	} sprite; - -	u32 subpicture_enable_mask; -	u32 subpicture_disable_mask; -}; - -/* Controlling the kernel modesetting buffers */ - -#define DRM_PSB_SIZES           0x07 -#define DRM_PSB_FUSE_REG	0x08 -#define DRM_PSB_DC_STATE	0x0A -#define DRM_PSB_ADB		0x0B -#define DRM_PSB_MODE_OPERATION	0x0C -#define DRM_PSB_STOLEN_MEMORY	0x0D -#define DRM_PSB_REGISTER_RW	0x0E - -/* - * NOTE: Add new commands here, but increment - * the values below and increment their - * corresponding defines where they're - * defined elsewhere. - */ - -#define DRM_PSB_GEM_CREATE	0x10 -#define DRM_PSB_2D_OP		0x11 -#define DRM_PSB_GEM_MMAP	0x12 -#define DRM_PSB_DPST		0x1B -#define DRM_PSB_GAMMA		0x1C -#define DRM_PSB_DPST_BL		0x1D -#define DRM_PSB_GET_PIPE_FROM_CRTC_ID 0x1F - -#define PSB_MODE_OPERATION_MODE_VALID	0x01 -#define PSB_MODE_OPERATION_SET_DC_BASE  0x02 - -struct drm_psb_get_pipe_from_crtc_id_arg { -	/** ID of CRTC being requested **/ -	u32 crtc_id; - -	/** pipe of requested CRTC **/ -	u32 pipe; -}; - -/* FIXME: move this into a medfield header once we are sure it isn't needed for an -   ioctl  */ -struct psb_drm_dpu_rect {   -	int x, y;              -	int width, height;     -};   - -struct drm_psb_gem_create { -	__u64 size; -	__u32 handle; -	__u32 flags; -#define PSB_GEM_CREATE_STOLEN		1	/* Stolen memory can be used */ -}; - -#define PSB_2D_OP_BUFLEN		16 - -struct drm_psb_2d_op { -	__u32 src;		/* Handles, only src supported right now */ -	__u32 dst; -	__u32 mask; -	__u32 pat; -	__u32 size;		/* In dwords of command */ -	__u32 spare;		/* And bumps array to u64 align */ -	__u32 cmd[PSB_2D_OP_BUFLEN]; -}; - -struct drm_psb_gem_mmap { -	__u32 handle; -	__u32 pad; -	/** -	 * Fake offset to use for subsequent mmap call -	 * -	 * This is a fixed-size type for 32/64 compatibility. -	 */ -	__u64 offset; -}; - -#endif diff --git a/drivers/staging/gma500/psb_drv.c b/drivers/staging/gma500/psb_drv.c deleted file mode 100644 index 95816808f86..00000000000 --- a/drivers/staging/gma500/psb_drv.c +++ /dev/null @@ -1,1230 +0,0 @@ -/************************************************************************** - * Copyright (c) 2007-2011, Intel Corporation. - * All Rights Reserved. - * Copyright (c) 2008, Tungsten Graphics, Inc. Cedar Park, TX., USA. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - **************************************************************************/ - -#include <drm/drmP.h> -#include <drm/drm.h> -#include "psb_drm.h" -#include "psb_drv.h" -#include "framebuffer.h" -#include "psb_reg.h" -#include "psb_intel_reg.h" -#include "intel_bios.h" -#include "mid_bios.h" -#include "mdfld_dsi_dbi.h" -#include <drm/drm_pciids.h> -#include "power.h" -#include <linux/cpu.h> -#include <linux/notifier.h> -#include <linux/spinlock.h> -#include <linux/pm_runtime.h> -#include <linux/module.h> -#include <acpi/video.h> - -static int drm_psb_trap_pagefaults; - -int drm_psb_no_fb; - -static int psb_probe(struct pci_dev *pdev, const struct pci_device_id *ent); - -MODULE_PARM_DESC(no_fb, "Disable FBdev"); -MODULE_PARM_DESC(trap_pagefaults, "Error and reset on MMU pagefaults"); -module_param_named(no_fb, drm_psb_no_fb, int, 0600); -module_param_named(trap_pagefaults, drm_psb_trap_pagefaults, int, 0600); - - -static DEFINE_PCI_DEVICE_TABLE(pciidlist) = { -	{ 0x8086, 0x8108, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &psb_chip_ops }, -	{ 0x8086, 0x8109, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &psb_chip_ops }, -#if defined(CONFIG_DRM_PSB_MRST) -	{ 0x8086, 0x4100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops}, -	{ 0x8086, 0x4101, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops}, -	{ 0x8086, 0x4102, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops}, -	{ 0x8086, 0x4103, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops}, -	{ 0x8086, 0x4104, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops}, -	{ 0x8086, 0x4105, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops}, -	{ 0x8086, 0x4106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops}, -	{ 0x8086, 0x4107, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops}, -#endif -#if defined(CONFIG_DRM_PSB_MFLD) -	{ 0x8086, 0x0130, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops}, -	{ 0x8086, 0x0131, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops}, -	{ 0x8086, 0x0132, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops}, -	{ 0x8086, 0x0133, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops}, -	{ 0x8086, 0x0134, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops}, -	{ 0x8086, 0x0135, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops}, -	{ 0x8086, 0x0136, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops}, -	{ 0x8086, 0x0137, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops}, -#endif -#if defined(CONFIG_DRM_PSB_CDV) -	{ 0x8086, 0x0be0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops}, -	{ 0x8086, 0x0be1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops}, -	{ 0x8086, 0x0be2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops}, -	{ 0x8086, 0x0be3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops}, -	{ 0x8086, 0x0be4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops}, -	{ 0x8086, 0x0be5, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops}, -	{ 0x8086, 0x0be6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops}, -	{ 0x8086, 0x0be7, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops}, -#endif -	{ 0, 0, 0} -}; -MODULE_DEVICE_TABLE(pci, pciidlist); - -/* - * Standard IOCTLs. - */ - -#define DRM_IOCTL_PSB_SIZES	\ -		DRM_IOR(DRM_PSB_SIZES + DRM_COMMAND_BASE, \ -			struct drm_psb_sizes_arg) -#define DRM_IOCTL_PSB_FUSE_REG	\ -		DRM_IOWR(DRM_PSB_FUSE_REG + DRM_COMMAND_BASE, uint32_t) -#define DRM_IOCTL_PSB_DC_STATE	\ -		DRM_IOW(DRM_PSB_DC_STATE + DRM_COMMAND_BASE, \ -			struct drm_psb_dc_state_arg) -#define DRM_IOCTL_PSB_ADB	\ -		DRM_IOWR(DRM_PSB_ADB + DRM_COMMAND_BASE, uint32_t) -#define DRM_IOCTL_PSB_MODE_OPERATION	\ -		DRM_IOWR(DRM_PSB_MODE_OPERATION + DRM_COMMAND_BASE, \ -			 struct drm_psb_mode_operation_arg) -#define DRM_IOCTL_PSB_STOLEN_MEMORY	\ -		DRM_IOWR(DRM_PSB_STOLEN_MEMORY + DRM_COMMAND_BASE, \ -			 struct drm_psb_stolen_memory_arg) -#define DRM_IOCTL_PSB_REGISTER_RW	\ -		DRM_IOWR(DRM_PSB_REGISTER_RW + DRM_COMMAND_BASE, \ -			 struct drm_psb_register_rw_arg) -#define DRM_IOCTL_PSB_DPST	\ -		DRM_IOWR(DRM_PSB_DPST + DRM_COMMAND_BASE, \ -			 uint32_t) -#define DRM_IOCTL_PSB_GAMMA	\ -		DRM_IOWR(DRM_PSB_GAMMA + DRM_COMMAND_BASE, \ -			 struct drm_psb_dpst_lut_arg) -#define DRM_IOCTL_PSB_DPST_BL	\ -		DRM_IOWR(DRM_PSB_DPST_BL + DRM_COMMAND_BASE, \ -			 uint32_t) -#define DRM_IOCTL_PSB_GET_PIPE_FROM_CRTC_ID	\ -		DRM_IOWR(DRM_PSB_GET_PIPE_FROM_CRTC_ID + DRM_COMMAND_BASE, \ -			 struct drm_psb_get_pipe_from_crtc_id_arg) -#define DRM_IOCTL_PSB_GEM_CREATE	\ -		DRM_IOWR(DRM_PSB_GEM_CREATE + DRM_COMMAND_BASE, \ -			 struct drm_psb_gem_create) -#define DRM_IOCTL_PSB_2D_OP	\ -		DRM_IOW(DRM_PSB_2D_OP + DRM_COMMAND_BASE, \ -			 struct drm_psb_2d_op) -#define DRM_IOCTL_PSB_GEM_MMAP	\ -		DRM_IOWR(DRM_PSB_GEM_MMAP + DRM_COMMAND_BASE, \ -			 struct drm_psb_gem_mmap) - -static int psb_sizes_ioctl(struct drm_device *dev, void *data, -			   struct drm_file *file_priv); -static int psb_dc_state_ioctl(struct drm_device *dev, void * data, -			      struct drm_file *file_priv); -static int psb_adb_ioctl(struct drm_device *dev, void *data, -			 struct drm_file *file_priv); -static int psb_mode_operation_ioctl(struct drm_device *dev, void *data, -				    struct drm_file *file_priv); -static int psb_stolen_memory_ioctl(struct drm_device *dev, void *data, -				   struct drm_file *file_priv); -static int psb_register_rw_ioctl(struct drm_device *dev, void *data, -				 struct drm_file *file_priv); -static int psb_dpst_ioctl(struct drm_device *dev, void *data, -			  struct drm_file *file_priv); -static int psb_gamma_ioctl(struct drm_device *dev, void *data, -			   struct drm_file *file_priv); -static int psb_dpst_bl_ioctl(struct drm_device *dev, void *data, -			     struct drm_file *file_priv); - -#define PSB_IOCTL_DEF(ioctl, func, flags) \ -	[DRM_IOCTL_NR(ioctl) - DRM_COMMAND_BASE] = {ioctl, flags, func} - -static struct drm_ioctl_desc psb_ioctls[] = { -	PSB_IOCTL_DEF(DRM_IOCTL_PSB_SIZES, psb_sizes_ioctl, DRM_AUTH), -	PSB_IOCTL_DEF(DRM_IOCTL_PSB_DC_STATE, psb_dc_state_ioctl, DRM_AUTH), -	PSB_IOCTL_DEF(DRM_IOCTL_PSB_ADB, psb_adb_ioctl, DRM_AUTH), -	PSB_IOCTL_DEF(DRM_IOCTL_PSB_MODE_OPERATION, psb_mode_operation_ioctl, -		      DRM_AUTH), -	PSB_IOCTL_DEF(DRM_IOCTL_PSB_STOLEN_MEMORY, psb_stolen_memory_ioctl, -		      DRM_AUTH), -	PSB_IOCTL_DEF(DRM_IOCTL_PSB_REGISTER_RW, psb_register_rw_ioctl, -		      DRM_AUTH), -	PSB_IOCTL_DEF(DRM_IOCTL_PSB_DPST, psb_dpst_ioctl, DRM_AUTH), -	PSB_IOCTL_DEF(DRM_IOCTL_PSB_GAMMA, psb_gamma_ioctl, DRM_AUTH), -	PSB_IOCTL_DEF(DRM_IOCTL_PSB_DPST_BL, psb_dpst_bl_ioctl, DRM_AUTH), -	PSB_IOCTL_DEF(DRM_IOCTL_PSB_GET_PIPE_FROM_CRTC_ID, -					psb_intel_get_pipe_from_crtc_id, 0), -	PSB_IOCTL_DEF(DRM_IOCTL_PSB_GEM_CREATE, psb_gem_create_ioctl, -						DRM_UNLOCKED | DRM_AUTH), -	PSB_IOCTL_DEF(DRM_IOCTL_PSB_2D_OP, psb_accel_ioctl, -						DRM_UNLOCKED| DRM_AUTH), -	PSB_IOCTL_DEF(DRM_IOCTL_PSB_GEM_MMAP, psb_gem_mmap_ioctl, -						DRM_UNLOCKED | DRM_AUTH), -}; - -static void psb_lastclose(struct drm_device *dev) -{ -	return; -} - -static void psb_do_takedown(struct drm_device *dev) -{ -} - -static int psb_do_init(struct drm_device *dev) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; -	struct psb_gtt *pg = &dev_priv->gtt; - -	uint32_t stolen_gtt; - -	int ret = -ENOMEM; - -	if (pg->mmu_gatt_start & 0x0FFFFFFF) { -		dev_err(dev->dev, "Gatt must be 256M aligned. This is a bug.\n"); -		ret = -EINVAL; -		goto out_err; -	} - - -	stolen_gtt = (pg->stolen_size >> PAGE_SHIFT) * 4; -	stolen_gtt = (stolen_gtt + PAGE_SIZE - 1) >> PAGE_SHIFT; -	stolen_gtt = -	    (stolen_gtt < pg->gtt_pages) ? stolen_gtt : pg->gtt_pages; - -	dev_priv->gatt_free_offset = pg->mmu_gatt_start + -	    (stolen_gtt << PAGE_SHIFT) * 1024; - -	if (1 || drm_debug) { -		uint32_t core_id = PSB_RSGX32(PSB_CR_CORE_ID); -		uint32_t core_rev = PSB_RSGX32(PSB_CR_CORE_REVISION); -		DRM_INFO("SGX core id = 0x%08x\n", core_id); -		DRM_INFO("SGX core rev major = 0x%02x, minor = 0x%02x\n", -			 (core_rev & _PSB_CC_REVISION_MAJOR_MASK) >> -			 _PSB_CC_REVISION_MAJOR_SHIFT, -			 (core_rev & _PSB_CC_REVISION_MINOR_MASK) >> -			 _PSB_CC_REVISION_MINOR_SHIFT); -		DRM_INFO -		    ("SGX core rev maintenance = 0x%02x, designer = 0x%02x\n", -		     (core_rev & _PSB_CC_REVISION_MAINTENANCE_MASK) >> -		     _PSB_CC_REVISION_MAINTENANCE_SHIFT, -		     (core_rev & _PSB_CC_REVISION_DESIGNER_MASK) >> -		     _PSB_CC_REVISION_DESIGNER_SHIFT); -	} - - -	spin_lock_init(&dev_priv->irqmask_lock); -	spin_lock_init(&dev_priv->lock_2d); - -	PSB_WSGX32(0x00000000, PSB_CR_BIF_BANK0); -	PSB_WSGX32(0x00000000, PSB_CR_BIF_BANK1); -	PSB_RSGX32(PSB_CR_BIF_BANK1); -	PSB_WSGX32(PSB_RSGX32(PSB_CR_BIF_CTRL) | _PSB_MMU_ER_MASK, -							PSB_CR_BIF_CTRL); -	psb_spank(dev_priv); - -	/* mmu_gatt ?? */ -	PSB_WSGX32(pg->gatt_start, PSB_CR_BIF_TWOD_REQ_BASE); -	return 0; -out_err: -	psb_do_takedown(dev); -	return ret; -} - -static int psb_driver_unload(struct drm_device *dev) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; - -	/* Kill vblank etc here */ - -	gma_backlight_exit(dev); - -	if (drm_psb_no_fb == 0) -		psb_modeset_cleanup(dev); - -	if (dev_priv) { -		psb_lid_timer_takedown(dev_priv); -		gma_intel_opregion_exit(dev); - -		if (dev_priv->ops->chip_teardown) -			dev_priv->ops->chip_teardown(dev); -		psb_do_takedown(dev); - - -		if (dev_priv->pf_pd) { -			psb_mmu_free_pagedir(dev_priv->pf_pd); -			dev_priv->pf_pd = NULL; -		} -		if (dev_priv->mmu) { -			struct psb_gtt *pg = &dev_priv->gtt; - -			down_read(&pg->sem); -			psb_mmu_remove_pfn_sequence( -				psb_mmu_get_default_pd -				(dev_priv->mmu), -				pg->mmu_gatt_start, -				dev_priv->vram_stolen_size >> PAGE_SHIFT); -			up_read(&pg->sem); -			psb_mmu_driver_takedown(dev_priv->mmu); -			dev_priv->mmu = NULL; -		} -		psb_gtt_takedown(dev); -		if (dev_priv->scratch_page) { -			__free_page(dev_priv->scratch_page); -			dev_priv->scratch_page = NULL; -		} -		if (dev_priv->vdc_reg) { -			iounmap(dev_priv->vdc_reg); -			dev_priv->vdc_reg = NULL; -		} -		if (dev_priv->sgx_reg) { -			iounmap(dev_priv->sgx_reg); -			dev_priv->sgx_reg = NULL; -		} - -		kfree(dev_priv); -		dev->dev_private = NULL; - -		/*destroy VBT data*/ -		psb_intel_destroy_bios(dev); -	} - -	gma_power_uninit(dev); - -	return 0; -} - - -static int psb_driver_load(struct drm_device *dev, unsigned long chipset) -{ -	struct drm_psb_private *dev_priv; -	unsigned long resource_start; -	struct psb_gtt *pg; -	unsigned long irqflags; -	int ret = -ENOMEM; -	uint32_t tt_pages; -	struct drm_connector *connector; -	struct psb_intel_output *psb_intel_output; - -	dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL); -	if (dev_priv == NULL) -		return -ENOMEM; - -	dev_priv->ops = (struct psb_ops *)chipset; -	dev_priv->dev = dev; -	dev->dev_private = (void *) dev_priv; - -	if (!IS_PSB(dev)) { -		if (pci_enable_msi(dev->pdev)) -			dev_warn(dev->dev, "Enabling MSI failed!\n"); -	} - -	dev_priv->num_pipe = dev_priv->ops->pipes; - -	resource_start = pci_resource_start(dev->pdev, PSB_MMIO_RESOURCE); - -	dev_priv->vdc_reg = -	    ioremap(resource_start + PSB_VDC_OFFSET, PSB_VDC_SIZE); -	if (!dev_priv->vdc_reg) -		goto out_err; - -	dev_priv->sgx_reg = ioremap(resource_start + dev_priv->ops->sgx_offset, -							PSB_SGX_SIZE); -	if (!dev_priv->sgx_reg) -		goto out_err; - -	ret = dev_priv->ops->chip_setup(dev); -	if (ret) -		goto out_err; - -	/* Init OSPM support */ -	gma_power_init(dev); - -	ret = -ENOMEM; - -	dev_priv->scratch_page = alloc_page(GFP_DMA32 | __GFP_ZERO); -	if (!dev_priv->scratch_page) -		goto out_err; - -	set_pages_uc(dev_priv->scratch_page, 1); - -	ret = psb_gtt_init(dev, 0); -	if (ret) -		goto out_err; - -	dev_priv->mmu = psb_mmu_driver_init((void *)0, -					drm_psb_trap_pagefaults, 0, -					dev_priv); -	if (!dev_priv->mmu) -		goto out_err; - -	pg = &dev_priv->gtt; - -	tt_pages = (pg->gatt_pages < PSB_TT_PRIV0_PLIMIT) ? -		(pg->gatt_pages) : PSB_TT_PRIV0_PLIMIT; - - -	dev_priv->pf_pd = psb_mmu_alloc_pd(dev_priv->mmu, 1, 0); -	if (!dev_priv->pf_pd) -		goto out_err; - -	psb_mmu_set_pd_context(psb_mmu_get_default_pd(dev_priv->mmu), 0); -	psb_mmu_set_pd_context(dev_priv->pf_pd, 1); - -	ret = psb_do_init(dev); -	if (ret) -		return ret; - -	PSB_WSGX32(0x20000000, PSB_CR_PDS_EXEC_BASE); -	PSB_WSGX32(0x30000000, PSB_CR_BIF_3D_REQ_BASE); - -/*	igd_opregion_init(&dev_priv->opregion_dev); */ -	acpi_video_register(); -	if (dev_priv->lid_state) -		psb_lid_timer_init(dev_priv); - -	ret = drm_vblank_init(dev, dev_priv->num_pipe); -	if (ret) -		goto out_err; - -	/* -	 * Install interrupt handlers prior to powering off SGX or else we will -	 * crash. -	 */ -	dev_priv->vdc_irq_mask = 0; -	dev_priv->pipestat[0] = 0; -	dev_priv->pipestat[1] = 0; -	dev_priv->pipestat[2] = 0; -	spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags); -	PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM); -	PSB_WVDC32(0x00000000, PSB_INT_ENABLE_R); -	PSB_WVDC32(0xFFFFFFFF, PSB_INT_MASK_R); -	spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); -	if (IS_PSB(dev) && drm_core_check_feature(dev, DRIVER_MODESET)) -		drm_irq_install(dev); - -	dev->vblank_disable_allowed = 1; - -	dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */ - -	dev->driver->get_vblank_counter = psb_get_vblank_counter; - -#if defined(CONFIG_DRM_PSB_MFLD) -	/* FIXME: this is not the right place for this stuff ! */ -	mdfld_output_setup(dev); -#endif -	if (drm_psb_no_fb == 0) { -		psb_modeset_init(dev); -		psb_fbdev_init(dev); -		drm_kms_helper_poll_init(dev); -	} - -	/* Only add backlight support if we have LVDS output */ -	list_for_each_entry(connector, &dev->mode_config.connector_list, -			    head) { -		psb_intel_output = to_psb_intel_output(connector); - -		switch (psb_intel_output->type) { -		case INTEL_OUTPUT_LVDS: -		case INTEL_OUTPUT_MIPI: -			ret = gma_backlight_init(dev); -			break; -		} -	} - -	if (ret) -		return ret; - -	/* Enable runtime pm at last */ -	pm_runtime_set_active(&dev->pdev->dev); -	return 0; -out_err: -	psb_driver_unload(dev); -	return ret; -} - -int psb_driver_device_is_agp(struct drm_device *dev) -{ -	return 0; -} - - -static int psb_sizes_ioctl(struct drm_device *dev, void *data, -			   struct drm_file *file_priv) -{ -	struct drm_psb_private *dev_priv = psb_priv(dev); -	struct drm_psb_sizes_arg *arg = data; - -	*arg = dev_priv->sizes; -	return 0; -} - -static int psb_dc_state_ioctl(struct drm_device *dev, void *data, -				struct drm_file *file_priv) -{ -	uint32_t flags; -	uint32_t obj_id; -	struct drm_mode_object *obj; -	struct drm_connector *connector; -	struct drm_crtc *crtc; -	struct drm_psb_dc_state_arg *arg = data; - - -	/* Double check MRST case */ -	if (IS_MRST(dev) || IS_MFLD(dev)) -		return -EOPNOTSUPP; - -	flags = arg->flags; -	obj_id = arg->obj_id; - -	if (flags & PSB_DC_CRTC_MASK) { -		obj = drm_mode_object_find(dev, obj_id, -				DRM_MODE_OBJECT_CRTC); -		if (!obj) { -			dev_dbg(dev->dev, "Invalid CRTC object.\n"); -			return -EINVAL; -		} - -		crtc = obj_to_crtc(obj); - -		mutex_lock(&dev->mode_config.mutex); -		if (drm_helper_crtc_in_use(crtc)) { -			if (flags & PSB_DC_CRTC_SAVE) -				crtc->funcs->save(crtc); -			else -				crtc->funcs->restore(crtc); -		} -		mutex_unlock(&dev->mode_config.mutex); - -		return 0; -	} else if (flags & PSB_DC_OUTPUT_MASK) { -		obj = drm_mode_object_find(dev, obj_id, -				DRM_MODE_OBJECT_CONNECTOR); -		if (!obj) { -			dev_dbg(dev->dev, "Invalid connector id.\n"); -			return -EINVAL; -		} - -		connector = obj_to_connector(obj); -		if (flags & PSB_DC_OUTPUT_SAVE) -			connector->funcs->save(connector); -		else -			connector->funcs->restore(connector); - -		return 0; -	} -	return -EINVAL; -} - -static inline void get_brightness(struct backlight_device *bd) -{ -#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE -	if (bd) { -		bd->props.brightness = bd->ops->get_brightness(bd); -		backlight_update_status(bd); -	} -#endif -} - -static int psb_dpst_bl_ioctl(struct drm_device *dev, void *data, -		       struct drm_file *file_priv) -{ -	struct drm_psb_private *dev_priv = psb_priv(dev); -	uint32_t *arg = data; - -	dev_priv->blc_adj2 = *arg; -	get_brightness(dev_priv->backlight_device); -	return 0; -} - -static int psb_adb_ioctl(struct drm_device *dev, void *data, -			struct drm_file *file_priv) -{ -	struct drm_psb_private *dev_priv = psb_priv(dev); -	uint32_t *arg = data; - -	dev_priv->blc_adj1 = *arg; -	get_brightness(dev_priv->backlight_device); -	return 0; -} - -/* return the current mode to the dpst module */ -static int psb_dpst_ioctl(struct drm_device *dev, void *data, -			  struct drm_file *file_priv) -{ -	struct drm_psb_private *dev_priv = psb_priv(dev); -	uint32_t *arg = data; -	uint32_t x; -	uint32_t y; -	uint32_t reg; - -	if (!gma_power_begin(dev, 0)) -		return -EIO; - -	reg = PSB_RVDC32(PIPEASRC); - -	gma_power_end(dev); - -	/* horizontal is the left 16 bits */ -	x = reg >> 16; -	/* vertical is the right 16 bits */ -	y = reg & 0x0000ffff; - -	/* the values are the image size minus one */ -	x++; -	y++; - -	*arg = (x << 16) | y; - -	return 0; -} -static int psb_gamma_ioctl(struct drm_device *dev, void *data, -			   struct drm_file *file_priv) -{ -	struct drm_psb_dpst_lut_arg *lut_arg = data; -	struct drm_mode_object *obj; -	struct drm_crtc *crtc; -	struct drm_connector *connector; -	struct psb_intel_crtc *psb_intel_crtc; -	int i = 0; -	int32_t obj_id; - -	obj_id = lut_arg->output_id; -	obj = drm_mode_object_find(dev, obj_id, DRM_MODE_OBJECT_CONNECTOR); -	if (!obj) { -		dev_dbg(dev->dev, "Invalid Connector object.\n"); -		return -EINVAL; -	} - -	connector = obj_to_connector(obj); -	crtc = connector->encoder->crtc; -	psb_intel_crtc = to_psb_intel_crtc(crtc); - -	for (i = 0; i < 256; i++) -		psb_intel_crtc->lut_adj[i] = lut_arg->lut[i]; - -	psb_intel_crtc_load_lut(crtc); - -	return 0; -} - -static int psb_mode_operation_ioctl(struct drm_device *dev, void *data, -				struct drm_file *file_priv) -{ -	uint32_t obj_id; -	uint16_t op; -	struct drm_mode_modeinfo *umode; -	struct drm_display_mode *mode = NULL; -	struct drm_psb_mode_operation_arg *arg; -	struct drm_mode_object *obj; -	struct drm_connector *connector; -	struct drm_framebuffer *drm_fb; -	struct psb_framebuffer *psb_fb; -	struct drm_connector_helper_funcs *connector_funcs; -	int ret = 0; -	int resp = MODE_OK; -	struct drm_psb_private *dev_priv = psb_priv(dev); - -	arg = (struct drm_psb_mode_operation_arg *)data; -	obj_id = arg->obj_id; -	op = arg->operation; - -	switch (op) { -	case PSB_MODE_OPERATION_SET_DC_BASE: -		obj = drm_mode_object_find(dev, obj_id, DRM_MODE_OBJECT_FB); -		if (!obj) { -			dev_dbg(dev->dev, "Invalid FB id %d\n", obj_id); -			return -EINVAL; -		} - -		drm_fb = obj_to_fb(obj); -		psb_fb = to_psb_fb(drm_fb); - -		if (gma_power_begin(dev, 0)) { -			REG_WRITE(DSPASURF, psb_fb->gtt->offset); -			REG_READ(DSPASURF); -			gma_power_end(dev); -		} else { -			dev_priv->saveDSPASURF = psb_fb->gtt->offset; -		} - -		return 0; -	case PSB_MODE_OPERATION_MODE_VALID: -		umode = &arg->mode; - -		mutex_lock(&dev->mode_config.mutex); - -		obj = drm_mode_object_find(dev, obj_id, -					DRM_MODE_OBJECT_CONNECTOR); -		if (!obj) { -			ret = -EINVAL; -			goto mode_op_out; -		} - -		connector = obj_to_connector(obj); - -		mode = drm_mode_create(dev); -		if (!mode) { -			ret = -ENOMEM; -			goto mode_op_out; -		} - -		/* drm_crtc_convert_umode(mode, umode); */ -		{ -			mode->clock = umode->clock; -			mode->hdisplay = umode->hdisplay; -			mode->hsync_start = umode->hsync_start; -			mode->hsync_end = umode->hsync_end; -			mode->htotal = umode->htotal; -			mode->hskew = umode->hskew; -			mode->vdisplay = umode->vdisplay; -			mode->vsync_start = umode->vsync_start; -			mode->vsync_end = umode->vsync_end; -			mode->vtotal = umode->vtotal; -			mode->vscan = umode->vscan; -			mode->vrefresh = umode->vrefresh; -			mode->flags = umode->flags; -			mode->type = umode->type; -			strncpy(mode->name, umode->name, DRM_DISPLAY_MODE_LEN); -			mode->name[DRM_DISPLAY_MODE_LEN-1] = 0; -		} - -		connector_funcs = (struct drm_connector_helper_funcs *) -				   connector->helper_private; - -		if (connector_funcs->mode_valid) { -			resp = connector_funcs->mode_valid(connector, mode); -			arg->data = (void *)resp; -		} - -		/*do some clean up work*/ -		if (mode) -			drm_mode_destroy(dev, mode); -mode_op_out: -		mutex_unlock(&dev->mode_config.mutex); -		return ret; - -	default: -		dev_dbg(dev->dev, "Unsupported psb mode operation\n"); -		return -EOPNOTSUPP; -	} - -	return 0; -} - -static int psb_stolen_memory_ioctl(struct drm_device *dev, void *data, -				   struct drm_file *file_priv) -{ -	struct drm_psb_private *dev_priv = psb_priv(dev); -	struct drm_psb_stolen_memory_arg *arg = data; - -	arg->base = dev_priv->stolen_base; -	arg->size = dev_priv->vram_stolen_size; - -	return 0; -} - -/* FIXME: needs Medfield changes */ -static int psb_register_rw_ioctl(struct drm_device *dev, void *data, -				 struct drm_file *file_priv) -{ -	struct drm_psb_private *dev_priv = psb_priv(dev); -	struct drm_psb_register_rw_arg *arg = data; -	bool usage = arg->b_force_hw_on ? true : false; - -	if (arg->display_write_mask != 0) { -		if (gma_power_begin(dev, usage)) { -			if (arg->display_write_mask & REGRWBITS_PFIT_CONTROLS) -				PSB_WVDC32(arg->display.pfit_controls, -					   PFIT_CONTROL); -			if (arg->display_write_mask & -			    REGRWBITS_PFIT_AUTOSCALE_RATIOS) -				PSB_WVDC32(arg->display.pfit_autoscale_ratios, -					   PFIT_AUTO_RATIOS); -			if (arg->display_write_mask & -			    REGRWBITS_PFIT_PROGRAMMED_SCALE_RATIOS) -				PSB_WVDC32( -				   arg->display.pfit_programmed_scale_ratios, -				   PFIT_PGM_RATIOS); -			if (arg->display_write_mask & REGRWBITS_PIPEASRC) -				PSB_WVDC32(arg->display.pipeasrc, -					   PIPEASRC); -			if (arg->display_write_mask & REGRWBITS_PIPEBSRC) -				PSB_WVDC32(arg->display.pipebsrc, -					   PIPEBSRC); -			if (arg->display_write_mask & REGRWBITS_VTOTAL_A) -				PSB_WVDC32(arg->display.vtotal_a, -					   VTOTAL_A); -			if (arg->display_write_mask & REGRWBITS_VTOTAL_B) -				PSB_WVDC32(arg->display.vtotal_b, -					   VTOTAL_B); -			gma_power_end(dev); -		} else { -			if (arg->display_write_mask & REGRWBITS_PFIT_CONTROLS) -				dev_priv->savePFIT_CONTROL = -						arg->display.pfit_controls; -			if (arg->display_write_mask & -			    REGRWBITS_PFIT_AUTOSCALE_RATIOS) -				dev_priv->savePFIT_AUTO_RATIOS = -					arg->display.pfit_autoscale_ratios; -			if (arg->display_write_mask & -			    REGRWBITS_PFIT_PROGRAMMED_SCALE_RATIOS) -				dev_priv->savePFIT_PGM_RATIOS = -				   arg->display.pfit_programmed_scale_ratios; -			if (arg->display_write_mask & REGRWBITS_PIPEASRC) -				dev_priv->savePIPEASRC = arg->display.pipeasrc; -			if (arg->display_write_mask & REGRWBITS_PIPEBSRC) -				dev_priv->savePIPEBSRC = arg->display.pipebsrc; -			if (arg->display_write_mask & REGRWBITS_VTOTAL_A) -				dev_priv->saveVTOTAL_A = arg->display.vtotal_a; -			if (arg->display_write_mask & REGRWBITS_VTOTAL_B) -				dev_priv->saveVTOTAL_B = arg->display.vtotal_b; -		} -	} - -	if (arg->display_read_mask != 0) { -		if (gma_power_begin(dev, usage)) { -			if (arg->display_read_mask & -			    REGRWBITS_PFIT_CONTROLS) -				arg->display.pfit_controls = -						PSB_RVDC32(PFIT_CONTROL); -			if (arg->display_read_mask & -			    REGRWBITS_PFIT_AUTOSCALE_RATIOS) -				arg->display.pfit_autoscale_ratios = -						PSB_RVDC32(PFIT_AUTO_RATIOS); -			if (arg->display_read_mask & -			    REGRWBITS_PFIT_PROGRAMMED_SCALE_RATIOS) -				arg->display.pfit_programmed_scale_ratios = -						PSB_RVDC32(PFIT_PGM_RATIOS); -			if (arg->display_read_mask & REGRWBITS_PIPEASRC) -				arg->display.pipeasrc = PSB_RVDC32(PIPEASRC); -			if (arg->display_read_mask & REGRWBITS_PIPEBSRC) -				arg->display.pipebsrc = PSB_RVDC32(PIPEBSRC); -			if (arg->display_read_mask & REGRWBITS_VTOTAL_A) -				arg->display.vtotal_a = PSB_RVDC32(VTOTAL_A); -			if (arg->display_read_mask & REGRWBITS_VTOTAL_B) -				arg->display.vtotal_b = PSB_RVDC32(VTOTAL_B); -			gma_power_end(dev); -		} else { -			if (arg->display_read_mask & -			    REGRWBITS_PFIT_CONTROLS) -				arg->display.pfit_controls = -						dev_priv->savePFIT_CONTROL; -			if (arg->display_read_mask & -			    REGRWBITS_PFIT_AUTOSCALE_RATIOS) -				arg->display.pfit_autoscale_ratios = -						dev_priv->savePFIT_AUTO_RATIOS; -			if (arg->display_read_mask & -			    REGRWBITS_PFIT_PROGRAMMED_SCALE_RATIOS) -				arg->display.pfit_programmed_scale_ratios = -						dev_priv->savePFIT_PGM_RATIOS; -			if (arg->display_read_mask & REGRWBITS_PIPEASRC) -				arg->display.pipeasrc = dev_priv->savePIPEASRC; -			if (arg->display_read_mask & REGRWBITS_PIPEBSRC) -				arg->display.pipebsrc = dev_priv->savePIPEBSRC; -			if (arg->display_read_mask & REGRWBITS_VTOTAL_A) -				arg->display.vtotal_a = dev_priv->saveVTOTAL_A; -			if (arg->display_read_mask & REGRWBITS_VTOTAL_B) -				arg->display.vtotal_b = dev_priv->saveVTOTAL_B; -		} -	} - -	if (arg->overlay_write_mask != 0) { -		if (gma_power_begin(dev, usage)) { -			if (arg->overlay_write_mask & OV_REGRWBITS_OGAM_ALL) { -				PSB_WVDC32(arg->overlay.OGAMC5, OV_OGAMC5); -				PSB_WVDC32(arg->overlay.OGAMC4, OV_OGAMC4); -				PSB_WVDC32(arg->overlay.OGAMC3, OV_OGAMC3); -				PSB_WVDC32(arg->overlay.OGAMC2, OV_OGAMC2); -				PSB_WVDC32(arg->overlay.OGAMC1, OV_OGAMC1); -				PSB_WVDC32(arg->overlay.OGAMC0, OV_OGAMC0); -			} -			if (arg->overlay_write_mask & OVC_REGRWBITS_OGAM_ALL) { -				PSB_WVDC32(arg->overlay.OGAMC5, OVC_OGAMC5); -				PSB_WVDC32(arg->overlay.OGAMC4, OVC_OGAMC4); -				PSB_WVDC32(arg->overlay.OGAMC3, OVC_OGAMC3); -				PSB_WVDC32(arg->overlay.OGAMC2, OVC_OGAMC2); -				PSB_WVDC32(arg->overlay.OGAMC1, OVC_OGAMC1); -				PSB_WVDC32(arg->overlay.OGAMC0, OVC_OGAMC0); -			} - -			if (arg->overlay_write_mask & OV_REGRWBITS_OVADD) { -				PSB_WVDC32(arg->overlay.OVADD, OV_OVADD); - -				if (arg->overlay.b_wait_vblank) { -					/* Wait for 20ms.*/ -					unsigned long vblank_timeout = jiffies -								+ HZ/50; -					uint32_t temp; -					while (time_before_eq(jiffies, -							vblank_timeout)) { -						temp = PSB_RVDC32(OV_DOVASTA); -						if ((temp & (0x1 << 31)) != 0) -							break; -						cpu_relax(); -					} -				} -			} -			if (arg->overlay_write_mask & OVC_REGRWBITS_OVADD) { -				PSB_WVDC32(arg->overlay.OVADD, OVC_OVADD); -				if (arg->overlay.b_wait_vblank) { -					/* Wait for 20ms.*/ -					unsigned long vblank_timeout = -							jiffies + HZ/50; -					uint32_t temp; -					while (time_before_eq(jiffies, -							vblank_timeout)) { -						temp = PSB_RVDC32(OVC_DOVCSTA); -						if ((temp & (0x1 << 31)) != 0) -							break; -						cpu_relax(); -					} -				} -			} -			gma_power_end(dev); -		} else { -			if (arg->overlay_write_mask & OV_REGRWBITS_OGAM_ALL) { -				dev_priv->saveOV_OGAMC5 = arg->overlay.OGAMC5; -				dev_priv->saveOV_OGAMC4 = arg->overlay.OGAMC4; -				dev_priv->saveOV_OGAMC3 = arg->overlay.OGAMC3; -				dev_priv->saveOV_OGAMC2 = arg->overlay.OGAMC2; -				dev_priv->saveOV_OGAMC1 = arg->overlay.OGAMC1; -				dev_priv->saveOV_OGAMC0 = arg->overlay.OGAMC0; -			} -			if (arg->overlay_write_mask & OVC_REGRWBITS_OGAM_ALL) { -				dev_priv->saveOVC_OGAMC5 = arg->overlay.OGAMC5; -				dev_priv->saveOVC_OGAMC4 = arg->overlay.OGAMC4; -				dev_priv->saveOVC_OGAMC3 = arg->overlay.OGAMC3; -				dev_priv->saveOVC_OGAMC2 = arg->overlay.OGAMC2; -				dev_priv->saveOVC_OGAMC1 = arg->overlay.OGAMC1; -				dev_priv->saveOVC_OGAMC0 = arg->overlay.OGAMC0; -			} -			if (arg->overlay_write_mask & OV_REGRWBITS_OVADD) -				dev_priv->saveOV_OVADD = arg->overlay.OVADD; -			if (arg->overlay_write_mask & OVC_REGRWBITS_OVADD) -				dev_priv->saveOVC_OVADD = arg->overlay.OVADD; -		} -	} - -	if (arg->overlay_read_mask != 0) { -		if (gma_power_begin(dev, usage)) { -			if (arg->overlay_read_mask & OV_REGRWBITS_OGAM_ALL) { -				arg->overlay.OGAMC5 = PSB_RVDC32(OV_OGAMC5); -				arg->overlay.OGAMC4 = PSB_RVDC32(OV_OGAMC4); -				arg->overlay.OGAMC3 = PSB_RVDC32(OV_OGAMC3); -				arg->overlay.OGAMC2 = PSB_RVDC32(OV_OGAMC2); -				arg->overlay.OGAMC1 = PSB_RVDC32(OV_OGAMC1); -				arg->overlay.OGAMC0 = PSB_RVDC32(OV_OGAMC0); -			} -			if (arg->overlay_read_mask & OVC_REGRWBITS_OGAM_ALL) { -				arg->overlay.OGAMC5 = PSB_RVDC32(OVC_OGAMC5); -				arg->overlay.OGAMC4 = PSB_RVDC32(OVC_OGAMC4); -				arg->overlay.OGAMC3 = PSB_RVDC32(OVC_OGAMC3); -				arg->overlay.OGAMC2 = PSB_RVDC32(OVC_OGAMC2); -				arg->overlay.OGAMC1 = PSB_RVDC32(OVC_OGAMC1); -				arg->overlay.OGAMC0 = PSB_RVDC32(OVC_OGAMC0); -			} -			if (arg->overlay_read_mask & OV_REGRWBITS_OVADD) -				arg->overlay.OVADD = PSB_RVDC32(OV_OVADD); -			if (arg->overlay_read_mask & OVC_REGRWBITS_OVADD) -				arg->overlay.OVADD = PSB_RVDC32(OVC_OVADD); -			gma_power_end(dev); -		} else { -			if (arg->overlay_read_mask & OV_REGRWBITS_OGAM_ALL) { -				arg->overlay.OGAMC5 = dev_priv->saveOV_OGAMC5; -				arg->overlay.OGAMC4 = dev_priv->saveOV_OGAMC4; -				arg->overlay.OGAMC3 = dev_priv->saveOV_OGAMC3; -				arg->overlay.OGAMC2 = dev_priv->saveOV_OGAMC2; -				arg->overlay.OGAMC1 = dev_priv->saveOV_OGAMC1; -				arg->overlay.OGAMC0 = dev_priv->saveOV_OGAMC0; -			} -			if (arg->overlay_read_mask & OVC_REGRWBITS_OGAM_ALL) { -				arg->overlay.OGAMC5 = dev_priv->saveOVC_OGAMC5; -				arg->overlay.OGAMC4 = dev_priv->saveOVC_OGAMC4; -				arg->overlay.OGAMC3 = dev_priv->saveOVC_OGAMC3; -				arg->overlay.OGAMC2 = dev_priv->saveOVC_OGAMC2; -				arg->overlay.OGAMC1 = dev_priv->saveOVC_OGAMC1; -				arg->overlay.OGAMC0 = dev_priv->saveOVC_OGAMC0; -			} -			if (arg->overlay_read_mask & OV_REGRWBITS_OVADD) -				arg->overlay.OVADD = dev_priv->saveOV_OVADD; -			if (arg->overlay_read_mask & OVC_REGRWBITS_OVADD) -				arg->overlay.OVADD = dev_priv->saveOVC_OVADD; -		} -	} - -	if (arg->sprite_enable_mask != 0) { -		if (gma_power_begin(dev, usage)) { -			PSB_WVDC32(0x1F3E, DSPARB); -			PSB_WVDC32(arg->sprite.dspa_control -					| PSB_RVDC32(DSPACNTR), DSPACNTR); -			PSB_WVDC32(arg->sprite.dspa_key_value, DSPAKEYVAL); -			PSB_WVDC32(arg->sprite.dspa_key_mask, DSPAKEYMASK); -			PSB_WVDC32(PSB_RVDC32(DSPASURF), DSPASURF); -			PSB_RVDC32(DSPASURF); -			PSB_WVDC32(arg->sprite.dspc_control, DSPCCNTR); -			PSB_WVDC32(arg->sprite.dspc_stride, DSPCSTRIDE); -			PSB_WVDC32(arg->sprite.dspc_position, DSPCPOS); -			PSB_WVDC32(arg->sprite.dspc_linear_offset, DSPCLINOFF); -			PSB_WVDC32(arg->sprite.dspc_size, DSPCSIZE); -			PSB_WVDC32(arg->sprite.dspc_surface, DSPCSURF); -			PSB_RVDC32(DSPCSURF); -			gma_power_end(dev); -		} -	} - -	if (arg->sprite_disable_mask != 0) { -		if (gma_power_begin(dev, usage)) { -			PSB_WVDC32(0x3F3E, DSPARB); -			PSB_WVDC32(0x0, DSPCCNTR); -			PSB_WVDC32(arg->sprite.dspc_surface, DSPCSURF); -			PSB_RVDC32(DSPCSURF); -			gma_power_end(dev); -		} -	} - -	if (arg->subpicture_enable_mask != 0) { -		if (gma_power_begin(dev, usage)) { -			uint32_t temp; -			if (arg->subpicture_enable_mask & REGRWBITS_DSPACNTR) { -				temp =  PSB_RVDC32(DSPACNTR); -				temp &= ~DISPPLANE_PIXFORMAT_MASK; -				temp &= ~DISPPLANE_BOTTOM; -				temp |= DISPPLANE_32BPP; -				PSB_WVDC32(temp, DSPACNTR); - -				temp =  PSB_RVDC32(DSPABASE); -				PSB_WVDC32(temp, DSPABASE); -				PSB_RVDC32(DSPABASE); -				temp =  PSB_RVDC32(DSPASURF); -				PSB_WVDC32(temp, DSPASURF); -				PSB_RVDC32(DSPASURF); -			} -			if (arg->subpicture_enable_mask & REGRWBITS_DSPBCNTR) { -				temp =  PSB_RVDC32(DSPBCNTR); -				temp &= ~DISPPLANE_PIXFORMAT_MASK; -				temp &= ~DISPPLANE_BOTTOM; -				temp |= DISPPLANE_32BPP; -				PSB_WVDC32(temp, DSPBCNTR); - -				temp =  PSB_RVDC32(DSPBBASE); -				PSB_WVDC32(temp, DSPBBASE); -				PSB_RVDC32(DSPBBASE); -				temp =  PSB_RVDC32(DSPBSURF); -				PSB_WVDC32(temp, DSPBSURF); -				PSB_RVDC32(DSPBSURF); -			} -			if (arg->subpicture_enable_mask & REGRWBITS_DSPCCNTR) { -				temp =  PSB_RVDC32(DSPCCNTR); -				temp &= ~DISPPLANE_PIXFORMAT_MASK; -				temp &= ~DISPPLANE_BOTTOM; -				temp |= DISPPLANE_32BPP; -				PSB_WVDC32(temp, DSPCCNTR); - -				temp =  PSB_RVDC32(DSPCBASE); -				PSB_WVDC32(temp, DSPCBASE); -				PSB_RVDC32(DSPCBASE); -				temp =  PSB_RVDC32(DSPCSURF); -				PSB_WVDC32(temp, DSPCSURF); -				PSB_RVDC32(DSPCSURF); -			} -			gma_power_end(dev); -		} -	} - -	if (arg->subpicture_disable_mask != 0) { -		if (gma_power_begin(dev, usage)) { -			uint32_t temp; -			if (arg->subpicture_disable_mask & REGRWBITS_DSPACNTR) { -				temp =  PSB_RVDC32(DSPACNTR); -				temp &= ~DISPPLANE_PIXFORMAT_MASK; -				temp |= DISPPLANE_32BPP_NO_ALPHA; -				PSB_WVDC32(temp, DSPACNTR); - -				temp =  PSB_RVDC32(DSPABASE); -				PSB_WVDC32(temp, DSPABASE); -				PSB_RVDC32(DSPABASE); -				temp =  PSB_RVDC32(DSPASURF); -				PSB_WVDC32(temp, DSPASURF); -				PSB_RVDC32(DSPASURF); -			} -			if (arg->subpicture_disable_mask & REGRWBITS_DSPBCNTR) { -				temp =  PSB_RVDC32(DSPBCNTR); -				temp &= ~DISPPLANE_PIXFORMAT_MASK; -				temp |= DISPPLANE_32BPP_NO_ALPHA; -				PSB_WVDC32(temp, DSPBCNTR); - -				temp =  PSB_RVDC32(DSPBBASE); -				PSB_WVDC32(temp, DSPBBASE); -				PSB_RVDC32(DSPBBASE); -				temp =  PSB_RVDC32(DSPBSURF); -				PSB_WVDC32(temp, DSPBSURF); -				PSB_RVDC32(DSPBSURF); -			} -			if (arg->subpicture_disable_mask & REGRWBITS_DSPCCNTR) { -				temp =  PSB_RVDC32(DSPCCNTR); -				temp &= ~DISPPLANE_PIXFORMAT_MASK; -				temp |= DISPPLANE_32BPP_NO_ALPHA; -				PSB_WVDC32(temp, DSPCCNTR); - -				temp =  PSB_RVDC32(DSPCBASE); -				PSB_WVDC32(temp, DSPCBASE); -				PSB_RVDC32(DSPCBASE); -				temp =  PSB_RVDC32(DSPCSURF); -				PSB_WVDC32(temp, DSPCSURF); -				PSB_RVDC32(DSPCSURF); -			} -			gma_power_end(dev); -		} -	} - -	return 0; -} - -static int psb_driver_open(struct drm_device *dev, struct drm_file *priv) -{ -	return 0; -} - -static void psb_driver_close(struct drm_device *dev, struct drm_file *priv) -{ -} - -static long psb_unlocked_ioctl(struct file *filp, unsigned int cmd, -			       unsigned long arg) -{ -	struct drm_file *file_priv = filp->private_data; -	struct drm_device *dev = file_priv->minor->dev; -	int ret; -	 -	pm_runtime_forbid(dev->dev); -	ret = drm_ioctl(filp, cmd, arg); -	pm_runtime_allow(dev->dev); -	return ret; -	/* FIXME: do we need to wrap the other side of this */ -} - - -/* When a client dies: - *    - Check for and clean up flipped page state - */ -void psb_driver_preclose(struct drm_device *dev, struct drm_file *priv) -{ -} - -static void psb_remove(struct pci_dev *pdev) -{ -	struct drm_device *dev = pci_get_drvdata(pdev); -	drm_put_dev(dev); -} - -static const struct dev_pm_ops psb_pm_ops = { -	.suspend = gma_power_suspend, -	.resume = gma_power_resume, -	.freeze = gma_power_suspend, -	.thaw = gma_power_resume, -	.poweroff = gma_power_suspend, -	.restore = gma_power_resume, -	.runtime_suspend = psb_runtime_suspend, -	.runtime_resume = psb_runtime_resume, -	.runtime_idle = psb_runtime_idle, -}; - -static struct vm_operations_struct psb_gem_vm_ops = { -	.fault = psb_gem_fault, -	.open = drm_gem_vm_open, -	.close = drm_gem_vm_close, -}; - -static const struct file_operations gma500_driver_fops = { -	.owner = THIS_MODULE, -	.open = drm_open, -	.release = drm_release, -	.unlocked_ioctl = psb_unlocked_ioctl, -	.mmap = drm_gem_mmap, -	.poll = drm_poll, -	.fasync = drm_fasync, -	.read = drm_read, -}; - -static struct drm_driver driver = { -	.driver_features = DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | \ -			   DRIVER_IRQ_VBL | DRIVER_MODESET | DRIVER_GEM , -	.load = psb_driver_load, -	.unload = psb_driver_unload, - -	.ioctls = psb_ioctls, -	.num_ioctls = DRM_ARRAY_SIZE(psb_ioctls), -	.device_is_agp = psb_driver_device_is_agp, -	.irq_preinstall = psb_irq_preinstall, -	.irq_postinstall = psb_irq_postinstall, -	.irq_uninstall = psb_irq_uninstall, -	.irq_handler = psb_irq_handler, -	.enable_vblank = psb_enable_vblank, -	.disable_vblank = psb_disable_vblank, -	.get_vblank_counter = psb_get_vblank_counter, -	.lastclose = psb_lastclose, -	.open = psb_driver_open, -	.preclose = psb_driver_preclose, -	.postclose = psb_driver_close, -	.reclaim_buffers = drm_core_reclaim_buffers, - -	.gem_init_object = psb_gem_init_object, -	.gem_free_object = psb_gem_free_object, -	.gem_vm_ops = &psb_gem_vm_ops, -	.dumb_create = psb_gem_dumb_create, -	.dumb_map_offset = psb_gem_dumb_map_gtt, -	.dumb_destroy = psb_gem_dumb_destroy, -	.fops = &gma500_driver_fops, -	.name = DRIVER_NAME, -	.desc = DRIVER_DESC, -	.date = PSB_DRM_DRIVER_DATE, -	.major = PSB_DRM_DRIVER_MAJOR, -	.minor = PSB_DRM_DRIVER_MINOR, -	.patchlevel = PSB_DRM_DRIVER_PATCHLEVEL -}; - -static struct pci_driver psb_pci_driver = { -	.name = DRIVER_NAME, -	.id_table = pciidlist, -	.probe = psb_probe, -	.remove = psb_remove, -	.driver.pm = &psb_pm_ops, -}; - -static int psb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) -{ -	return drm_get_pci_dev(pdev, ent, &driver); -} - -static int __init psb_init(void) -{ -	return drm_pci_init(&driver, &psb_pci_driver); -} - -static void __exit psb_exit(void) -{ -	drm_pci_exit(&driver, &psb_pci_driver); -} - -late_initcall(psb_init); -module_exit(psb_exit); - -MODULE_AUTHOR("Alan Cox <alan@linux.intel.com> and others"); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE("GPL"); diff --git a/drivers/staging/gma500/psb_drv.h b/drivers/staging/gma500/psb_drv.h deleted file mode 100644 index 11d963a055b..00000000000 --- a/drivers/staging/gma500/psb_drv.h +++ /dev/null @@ -1,952 +0,0 @@ -/************************************************************************** - * Copyright (c) 2007-2011, Intel Corporation. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - **************************************************************************/ - -#ifndef _PSB_DRV_H_ -#define _PSB_DRV_H_ - -#include <linux/kref.h> - -#include <drm/drmP.h> -#include "drm_global.h" -#include "gem_glue.h" -#include "psb_drm.h" -#include "psb_reg.h" -#include "psb_intel_drv.h" -#include "gtt.h" -#include "power.h" -#include "mrst.h" -#include "medfield.h" - -/* Append new drm mode definition here, align with libdrm definition */ -#define DRM_MODE_SCALE_NO_SCALE   	2 - -enum { -	CHIP_PSB_8108 = 0,		/* Poulsbo */ -	CHIP_PSB_8109 = 1,		/* Poulsbo */ -	CHIP_MRST_4100 = 2,		/* Moorestown/Oaktrail */ -	CHIP_MFLD_0130 = 3,		/* Medfield */ -}; - -#define IS_PSB(dev) (((dev)->pci_device & 0xfffe) == 0x8108) -#define IS_MRST(dev) (((dev)->pci_device & 0xfffc) == 0x4100) -#define IS_MFLD(dev) (((dev)->pci_device & 0xfff8) == 0x0130) - -/* - * Driver definitions - */ - -#define DRIVER_NAME "gma500" -#define DRIVER_DESC "DRM driver for the Intel GMA500" - -#define PSB_DRM_DRIVER_DATE "2011-06-06" -#define PSB_DRM_DRIVER_MAJOR 1 -#define PSB_DRM_DRIVER_MINOR 0 -#define PSB_DRM_DRIVER_PATCHLEVEL 0 - -/* - *	Hardware offsets - */ -#define PSB_VDC_OFFSET		 0x00000000 -#define PSB_VDC_SIZE		 0x000080000 -#define MRST_MMIO_SIZE		 0x0000C0000 -#define MDFLD_MMIO_SIZE          0x000100000 -#define PSB_SGX_SIZE		 0x8000 -#define PSB_SGX_OFFSET		 0x00040000 -#define MRST_SGX_OFFSET		 0x00080000 -/* - *	PCI resource identifiers - */ -#define PSB_MMIO_RESOURCE	 0 -#define PSB_GATT_RESOURCE	 2 -#define PSB_GTT_RESOURCE	 3 -/* - *	PCI configuration - */ -#define PSB_GMCH_CTRL		 0x52 -#define PSB_BSM			 0x5C -#define _PSB_GMCH_ENABLED	 0x4 -#define PSB_PGETBL_CTL		 0x2020 -#define _PSB_PGETBL_ENABLED	 0x00000001 -#define PSB_SGX_2D_SLAVE_PORT	 0x4000 - -/* To get rid of */ -#define PSB_TT_PRIV0_LIMIT	 (256*1024*1024) -#define PSB_TT_PRIV0_PLIMIT	 (PSB_TT_PRIV0_LIMIT >> PAGE_SHIFT) - -/* - *	SGX side MMU definitions (these can probably go) - */ - -/* - *	Flags for external memory type field. - */ -#define PSB_MMU_CACHED_MEMORY	  0x0001	/* Bind to MMU only */ -#define PSB_MMU_RO_MEMORY	  0x0002	/* MMU RO memory */ -#define PSB_MMU_WO_MEMORY	  0x0004	/* MMU WO memory */ -/* - *	PTE's and PDE's - */ -#define PSB_PDE_MASK		  0x003FFFFF -#define PSB_PDE_SHIFT		  22 -#define PSB_PTE_SHIFT		  12 -/* - *	Cache control - */ -#define PSB_PTE_VALID		  0x0001	/* PTE / PDE valid */ -#define PSB_PTE_WO		  0x0002	/* Write only */ -#define PSB_PTE_RO		  0x0004	/* Read only */ -#define PSB_PTE_CACHED		  0x0008	/* CPU cache coherent */ - -/* - *	VDC registers and bits - */ -#define PSB_MSVDX_CLOCKGATING	  0x2064 -#define PSB_TOPAZ_CLOCKGATING	  0x2068 -#define PSB_HWSTAM		  0x2098 -#define PSB_INSTPM		  0x20C0 -#define PSB_INT_IDENTITY_R        0x20A4 -#define _MDFLD_PIPEC_EVENT_FLAG   (1<<2) -#define _MDFLD_PIPEC_VBLANK_FLAG  (1<<3) -#define _PSB_DPST_PIPEB_FLAG      (1<<4) -#define _MDFLD_PIPEB_EVENT_FLAG   (1<<4) -#define _PSB_VSYNC_PIPEB_FLAG	  (1<<5) -#define _PSB_DPST_PIPEA_FLAG      (1<<6) -#define _PSB_PIPEA_EVENT_FLAG     (1<<6) -#define _PSB_VSYNC_PIPEA_FLAG	  (1<<7) -#define _MDFLD_MIPIA_FLAG	  (1<<16) -#define _MDFLD_MIPIC_FLAG	  (1<<17) -#define _PSB_IRQ_SGX_FLAG	  (1<<18) -#define _PSB_IRQ_MSVDX_FLAG	  (1<<19) -#define _LNC_IRQ_TOPAZ_FLAG	  (1<<20) - -#define _PSB_PIPE_EVENT_FLAG	(_PSB_VSYNC_PIPEA_FLAG | \ -				 _PSB_VSYNC_PIPEB_FLAG) - -/* This flag includes all the display IRQ bits excepts the vblank irqs. */ -#define _MDFLD_DISP_ALL_IRQ_FLAG (_MDFLD_PIPEC_EVENT_FLAG | \ -				  _MDFLD_PIPEB_EVENT_FLAG | \ -				  _PSB_PIPEA_EVENT_FLAG | \ -				  _PSB_VSYNC_PIPEA_FLAG | \ -				  _MDFLD_MIPIA_FLAG | \ -				  _MDFLD_MIPIC_FLAG) -#define PSB_INT_IDENTITY_R	  0x20A4 -#define PSB_INT_MASK_R		  0x20A8 -#define PSB_INT_ENABLE_R	  0x20A0 - -#define _PSB_MMU_ER_MASK      0x0001FF00 -#define _PSB_MMU_ER_HOST      (1 << 16) -#define GPIOA			0x5010 -#define GPIOB			0x5014 -#define GPIOC			0x5018 -#define GPIOD			0x501c -#define GPIOE			0x5020 -#define GPIOF			0x5024 -#define GPIOG			0x5028 -#define GPIOH			0x502c -#define GPIO_CLOCK_DIR_MASK		(1 << 0) -#define GPIO_CLOCK_DIR_IN		(0 << 1) -#define GPIO_CLOCK_DIR_OUT		(1 << 1) -#define GPIO_CLOCK_VAL_MASK		(1 << 2) -#define GPIO_CLOCK_VAL_OUT		(1 << 3) -#define GPIO_CLOCK_VAL_IN		(1 << 4) -#define GPIO_CLOCK_PULLUP_DISABLE	(1 << 5) -#define GPIO_DATA_DIR_MASK		(1 << 8) -#define GPIO_DATA_DIR_IN		(0 << 9) -#define GPIO_DATA_DIR_OUT		(1 << 9) -#define GPIO_DATA_VAL_MASK		(1 << 10) -#define GPIO_DATA_VAL_OUT		(1 << 11) -#define GPIO_DATA_VAL_IN		(1 << 12) -#define GPIO_DATA_PULLUP_DISABLE	(1 << 13) - -#define VCLK_DIVISOR_VGA0   0x6000 -#define VCLK_DIVISOR_VGA1   0x6004 -#define VCLK_POST_DIV	    0x6010 - -#define PSB_COMM_2D (PSB_ENGINE_2D << 4) -#define PSB_COMM_3D (PSB_ENGINE_3D << 4) -#define PSB_COMM_TA (PSB_ENGINE_TA << 4) -#define PSB_COMM_HP (PSB_ENGINE_HP << 4) -#define PSB_COMM_USER_IRQ (1024 >> 2) -#define PSB_COMM_USER_IRQ_LOST (PSB_COMM_USER_IRQ + 1) -#define PSB_COMM_FW (2048 >> 2) - -#define PSB_UIRQ_VISTEST	       1 -#define PSB_UIRQ_OOM_REPLY	       2 -#define PSB_UIRQ_FIRE_TA_REPLY	       3 -#define PSB_UIRQ_FIRE_RASTER_REPLY     4 - -#define PSB_2D_SIZE (256*1024*1024) -#define PSB_MAX_RELOC_PAGES 1024 - -#define PSB_LOW_REG_OFFS 0x0204 -#define PSB_HIGH_REG_OFFS 0x0600 - -#define PSB_NUM_VBLANKS 2 - - -#define PSB_2D_SIZE (256*1024*1024) -#define PSB_MAX_RELOC_PAGES 1024 - -#define PSB_LOW_REG_OFFS 0x0204 -#define PSB_HIGH_REG_OFFS 0x0600 - -#define PSB_NUM_VBLANKS 2 -#define PSB_WATCHDOG_DELAY (DRM_HZ * 2) -#define PSB_LID_DELAY (DRM_HZ / 10) - -#define MDFLD_PNW_B0 0x04 -#define MDFLD_PNW_C0 0x08 - -#define MDFLD_DSR_2D_3D_0 	(1 << 0) -#define MDFLD_DSR_2D_3D_2 	(1 << 1) -#define MDFLD_DSR_CURSOR_0 	(1 << 2) -#define MDFLD_DSR_CURSOR_2	(1 << 3) -#define MDFLD_DSR_OVERLAY_0 	(1 << 4) -#define MDFLD_DSR_OVERLAY_2 	(1 << 5) -#define MDFLD_DSR_MIPI_CONTROL	(1 << 6) -#define MDFLD_DSR_DAMAGE_MASK_0	((1 << 0) | (1 << 2) | (1 << 4)) -#define MDFLD_DSR_DAMAGE_MASK_2	((1 << 1) | (1 << 3) | (1 << 5)) -#define MDFLD_DSR_2D_3D 	(MDFLD_DSR_2D_3D_0 | MDFLD_DSR_2D_3D_2) - -#define MDFLD_DSR_RR		45 -#define MDFLD_DPU_ENABLE 	(1 << 31) -#define MDFLD_DSR_FULLSCREEN 	(1 << 30) -#define MDFLD_DSR_DELAY		(DRM_HZ / MDFLD_DSR_RR) - -#define PSB_PWR_STATE_ON		1 -#define PSB_PWR_STATE_OFF		2 - -#define PSB_PMPOLICY_NOPM		0 -#define PSB_PMPOLICY_CLOCKGATING	1 -#define PSB_PMPOLICY_POWERDOWN		2 - -#define PSB_PMSTATE_POWERUP		0 -#define PSB_PMSTATE_CLOCKGATED		1 -#define PSB_PMSTATE_POWERDOWN		2 -#define PSB_PCIx_MSI_ADDR_LOC		0x94 -#define PSB_PCIx_MSI_DATA_LOC		0x98 - -/* Medfield crystal settings */ -#define KSEL_CRYSTAL_19 1 -#define KSEL_BYPASS_19 5 -#define KSEL_BYPASS_25 6 -#define KSEL_BYPASS_83_100 7 - -struct opregion_header; -struct opregion_acpi; -struct opregion_swsci; -struct opregion_asle; - -struct psb_intel_opregion { -	struct opregion_header *header; -	struct opregion_acpi *acpi; -	struct opregion_swsci *swsci; -	struct opregion_asle *asle; -	int enabled; -}; - -struct psb_ops; - -struct drm_psb_private { -	struct drm_device *dev; -	const struct psb_ops *ops; - -	struct psb_gtt gtt; - -	/* GTT Memory manager */ -	struct psb_gtt_mm *gtt_mm; -	struct page *scratch_page; -	u32 *gtt_map; -	uint32_t stolen_base; -	void *vram_addr; -	unsigned long vram_stolen_size; -	int gtt_initialized; -	u16 gmch_ctrl;		/* Saved GTT setup */ -	u32 pge_ctl; - -	struct mutex gtt_mutex; -	struct resource *gtt_mem;	/* Our PCI resource */ - -	struct psb_mmu_driver *mmu; -	struct psb_mmu_pd *pf_pd; - -	/* -	 * Register base -	 */ - -	uint8_t *sgx_reg; -	uint8_t *vdc_reg; -	uint32_t gatt_free_offset; - -	/* -	 * Fencing / irq. -	 */ - -	uint32_t vdc_irq_mask; -	uint32_t pipestat[PSB_NUM_PIPE]; - -	spinlock_t irqmask_lock; - -	/* -	 * Power -	 */ - -	bool suspended; -	bool display_power; -	int display_count; - -	/* -	 * Modesetting -	 */ -	struct psb_intel_mode_device mode_dev; - -	struct drm_crtc *plane_to_crtc_mapping[PSB_NUM_PIPE]; -	struct drm_crtc *pipe_to_crtc_mapping[PSB_NUM_PIPE]; -	uint32_t num_pipe; - -	/* -	 * OSPM info (Power management base) (can go ?) -	 */ -	uint32_t ospm_base; - -	/* -	 * Sizes info -	 */ - -	struct drm_psb_sizes_arg sizes; - -	u32 fuse_reg_value; -	u32 video_device_fuse; - -	/* PCI revision ID for B0:D2:F0 */ -	uint8_t platform_rev_id; - -	/* -	 * LVDS info -	 */ -	int backlight_duty_cycle;	/* restore backlight to this value */ -	bool panel_wants_dither; -	struct drm_display_mode *panel_fixed_mode; -	struct drm_display_mode *lfp_lvds_vbt_mode; -	struct drm_display_mode *sdvo_lvds_vbt_mode; - -	struct bdb_lvds_backlight *lvds_bl; /* LVDS backlight info from VBT */ -	struct psb_intel_i2c_chan *lvds_i2c_bus; - -	/* Feature bits from the VBIOS */ -	unsigned int int_tv_support:1; -	unsigned int lvds_dither:1; -	unsigned int lvds_vbt:1; -	unsigned int int_crt_support:1; -	unsigned int lvds_use_ssc:1; -	int lvds_ssc_freq; -	bool is_lvds_on; -	bool is_mipi_on; -	u32 mipi_ctrl_display; - -	unsigned int core_freq; -	uint32_t iLVDS_enable; - -	/* Runtime PM state */ -	int rpm_enabled; - -	/* MID specific */ -	struct mrst_vbt vbt_data; -	struct mrst_gct_data gct_data; - -	/* MIPI Panel type etc */ -	int panel_id; -	bool dual_mipi;		/* dual display - DPI & DBI */ -	bool dpi_panel_on;	/* The DPI panel power is on */ -	bool dpi_panel_on2;	/* The DPI panel power is on */ -	bool dbi_panel_on;	/* The DBI panel power is on */ -	bool dbi_panel_on2;	/* The DBI panel power is on */ -	u32 dsr_fb_update;	/* DSR FB update counter */ - -	/* Moorestown HDMI state */ -	struct mrst_hdmi_dev *hdmi_priv; - -	/* Moorestown pipe config register value cache */ -	uint32_t pipeconf; -	uint32_t pipeconf1; -	uint32_t pipeconf2; - -	/* Moorestown plane control register value cache */ -	uint32_t dspcntr; -	uint32_t dspcntr1; -	uint32_t dspcntr2; - -	/* Moorestown MM backlight cache */ -	uint8_t saveBKLTCNT; -	uint8_t saveBKLTREQ; -	uint8_t saveBKLTBRTL; - -	/* -	 * Register state -	 */ -	uint32_t saveDSPACNTR; -	uint32_t saveDSPBCNTR; -	uint32_t savePIPEACONF; -	uint32_t savePIPEBCONF; -	uint32_t savePIPEASRC; -	uint32_t savePIPEBSRC; -	uint32_t saveFPA0; -	uint32_t saveFPA1; -	uint32_t saveDPLL_A; -	uint32_t saveDPLL_A_MD; -	uint32_t saveHTOTAL_A; -	uint32_t saveHBLANK_A; -	uint32_t saveHSYNC_A; -	uint32_t saveVTOTAL_A; -	uint32_t saveVBLANK_A; -	uint32_t saveVSYNC_A; -	uint32_t saveDSPASTRIDE; -	uint32_t saveDSPASIZE; -	uint32_t saveDSPAPOS; -	uint32_t saveDSPABASE; -	uint32_t saveDSPASURF; -	uint32_t saveDSPASTATUS; -	uint32_t saveFPB0; -	uint32_t saveFPB1; -	uint32_t saveDPLL_B; -	uint32_t saveDPLL_B_MD; -	uint32_t saveHTOTAL_B; -	uint32_t saveHBLANK_B; -	uint32_t saveHSYNC_B; -	uint32_t saveVTOTAL_B; -	uint32_t saveVBLANK_B; -	uint32_t saveVSYNC_B; -	uint32_t saveDSPBSTRIDE; -	uint32_t saveDSPBSIZE; -	uint32_t saveDSPBPOS; -	uint32_t saveDSPBBASE; -	uint32_t saveDSPBSURF; -	uint32_t saveDSPBSTATUS; -	uint32_t saveVCLK_DIVISOR_VGA0; -	uint32_t saveVCLK_DIVISOR_VGA1; -	uint32_t saveVCLK_POST_DIV; -	uint32_t saveVGACNTRL; -	uint32_t saveADPA; -	uint32_t saveLVDS; -	uint32_t saveDVOA; -	uint32_t saveDVOB; -	uint32_t saveDVOC; -	uint32_t savePP_ON; -	uint32_t savePP_OFF; -	uint32_t savePP_CONTROL; -	uint32_t savePP_CYCLE; -	uint32_t savePFIT_CONTROL; -	uint32_t savePaletteA[256]; -	uint32_t savePaletteB[256]; -	uint32_t saveBLC_PWM_CTL2; -	uint32_t saveBLC_PWM_CTL; -	uint32_t saveCLOCKGATING; -	uint32_t saveDSPARB; -	uint32_t saveDSPATILEOFF; -	uint32_t saveDSPBTILEOFF; -	uint32_t saveDSPAADDR; -	uint32_t saveDSPBADDR; -	uint32_t savePFIT_AUTO_RATIOS; -	uint32_t savePFIT_PGM_RATIOS; -	uint32_t savePP_ON_DELAYS; -	uint32_t savePP_OFF_DELAYS; -	uint32_t savePP_DIVISOR; -	uint32_t saveBSM; -	uint32_t saveVBT; -	uint32_t saveBCLRPAT_A; -	uint32_t saveBCLRPAT_B; -	uint32_t saveDSPALINOFF; -	uint32_t saveDSPBLINOFF; -	uint32_t savePERF_MODE; -	uint32_t saveDSPFW1; -	uint32_t saveDSPFW2; -	uint32_t saveDSPFW3; -	uint32_t saveDSPFW4; -	uint32_t saveDSPFW5; -	uint32_t saveDSPFW6; -	uint32_t saveCHICKENBIT; -	uint32_t saveDSPACURSOR_CTRL; -	uint32_t saveDSPBCURSOR_CTRL; -	uint32_t saveDSPACURSOR_BASE; -	uint32_t saveDSPBCURSOR_BASE; -	uint32_t saveDSPACURSOR_POS; -	uint32_t saveDSPBCURSOR_POS; -	uint32_t save_palette_a[256]; -	uint32_t save_palette_b[256]; -	uint32_t saveOV_OVADD; -	uint32_t saveOV_OGAMC0; -	uint32_t saveOV_OGAMC1; -	uint32_t saveOV_OGAMC2; -	uint32_t saveOV_OGAMC3; -	uint32_t saveOV_OGAMC4; -	uint32_t saveOV_OGAMC5; -	uint32_t saveOVC_OVADD; -	uint32_t saveOVC_OGAMC0; -	uint32_t saveOVC_OGAMC1; -	uint32_t saveOVC_OGAMC2; -	uint32_t saveOVC_OGAMC3; -	uint32_t saveOVC_OGAMC4; -	uint32_t saveOVC_OGAMC5; - -	/* MSI reg save */ -	uint32_t msi_addr; -	uint32_t msi_data; - -	/* Medfield specific register save state */ -	uint32_t saveHDMIPHYMISCCTL; -	uint32_t saveHDMIB_CONTROL; -	uint32_t saveDSPCCNTR; -	uint32_t savePIPECCONF; -	uint32_t savePIPECSRC; -	uint32_t saveHTOTAL_C; -	uint32_t saveHBLANK_C; -	uint32_t saveHSYNC_C; -	uint32_t saveVTOTAL_C; -	uint32_t saveVBLANK_C; -	uint32_t saveVSYNC_C; -	uint32_t saveDSPCSTRIDE; -	uint32_t saveDSPCSIZE; -	uint32_t saveDSPCPOS; -	uint32_t saveDSPCSURF; -	uint32_t saveDSPCSTATUS; -	uint32_t saveDSPCLINOFF; -	uint32_t saveDSPCTILEOFF; -	uint32_t saveDSPCCURSOR_CTRL; -	uint32_t saveDSPCCURSOR_BASE; -	uint32_t saveDSPCCURSOR_POS; -	uint32_t save_palette_c[256]; -	uint32_t saveOV_OVADD_C; -	uint32_t saveOV_OGAMC0_C; -	uint32_t saveOV_OGAMC1_C; -	uint32_t saveOV_OGAMC2_C; -	uint32_t saveOV_OGAMC3_C; -	uint32_t saveOV_OGAMC4_C; -	uint32_t saveOV_OGAMC5_C; - -	/* DSI register save */ -	uint32_t saveDEVICE_READY_REG; -	uint32_t saveINTR_EN_REG; -	uint32_t saveDSI_FUNC_PRG_REG; -	uint32_t saveHS_TX_TIMEOUT_REG; -	uint32_t saveLP_RX_TIMEOUT_REG; -	uint32_t saveTURN_AROUND_TIMEOUT_REG; -	uint32_t saveDEVICE_RESET_REG; -	uint32_t saveDPI_RESOLUTION_REG; -	uint32_t saveHORIZ_SYNC_PAD_COUNT_REG; -	uint32_t saveHORIZ_BACK_PORCH_COUNT_REG; -	uint32_t saveHORIZ_FRONT_PORCH_COUNT_REG; -	uint32_t saveHORIZ_ACTIVE_AREA_COUNT_REG; -	uint32_t saveVERT_SYNC_PAD_COUNT_REG; -	uint32_t saveVERT_BACK_PORCH_COUNT_REG; -	uint32_t saveVERT_FRONT_PORCH_COUNT_REG; -	uint32_t saveHIGH_LOW_SWITCH_COUNT_REG; -	uint32_t saveINIT_COUNT_REG; -	uint32_t saveMAX_RET_PAK_REG; -	uint32_t saveVIDEO_FMT_REG; -	uint32_t saveEOT_DISABLE_REG; -	uint32_t saveLP_BYTECLK_REG; -	uint32_t saveHS_LS_DBI_ENABLE_REG; -	uint32_t saveTXCLKESC_REG; -	uint32_t saveDPHY_PARAM_REG; -	uint32_t saveMIPI_CONTROL_REG; -	uint32_t saveMIPI; -	uint32_t saveMIPI_C; - -	/* DPST register save */ -	uint32_t saveHISTOGRAM_INT_CONTROL_REG; -	uint32_t saveHISTOGRAM_LOGIC_CONTROL_REG; -	uint32_t savePWM_CONTROL_LOGIC; - -	/* -	 * DSI info.  -	 */ -	void * dbi_dsr_info;	 -	void * dbi_dpu_info; -	void * dsi_configs[2]; -	/* -	 * LID-Switch -	 */ -	spinlock_t lid_lock; -	struct timer_list lid_timer; -	struct psb_intel_opregion opregion; -	u32 *lid_state; -	u32 lid_last_state; - -	/* -	 * Watchdog -	 */ - -	uint32_t apm_reg; -	uint16_t apm_base; - -	/* -	 * Used for modifying backlight from -	 * xrandr -- consider removing and using HAL instead -	 */ -	struct backlight_device *backlight_device; -	struct drm_property *backlight_property; -	uint32_t blc_adj1; -	uint32_t blc_adj2; - -	void *fbdev; -	/* DPST state */ -	uint32_t dsr_idle_count; -	bool is_in_idle; -	bool dsr_enable; -	void (*exit_idle)(struct drm_device *dev, u32 update_src); - -	/* 2D acceleration */ -	spinlock_t lock_2d; - -	/* FIXME: Arrays anyone ? */ -	struct mdfld_dsi_encoder *encoder0;	 -	struct mdfld_dsi_encoder *encoder2;	 -	struct mdfld_dsi_dbi_output * dbi_output; -	struct mdfld_dsi_dbi_output * dbi_output2; -	u32 bpp; -	u32 bpp2; -	 -	bool dispstatus; -}; - - -/* - *	Operations for each board type - */ -  -struct psb_ops { -	const char *name; -	unsigned int accel_2d:1; -	int pipes;		/* Number of output pipes */ -	int crtcs;		/* Number of CRTCs */ -	int sgx_offset;		/* Base offset of SGX device */ - -	/* Sub functions */ -	struct drm_crtc_helper_funcs const *crtc_helper; -	struct drm_crtc_funcs const *crtc_funcs; - -	/* Setup hooks */ -	int (*chip_setup)(struct drm_device *dev); -	void (*chip_teardown)(struct drm_device *dev); - -	/* Display management hooks */ -	int (*output_init)(struct drm_device *dev); -	/* Power management hooks */ -	void (*init_pm)(struct drm_device *dev); -	int (*save_regs)(struct drm_device *dev); -	int (*restore_regs)(struct drm_device *dev); -	int (*power_up)(struct drm_device *dev); -	int (*power_down)(struct drm_device *dev); - -	void (*lvds_bl_power)(struct drm_device *dev, bool on); -#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE -	/* Backlight */ -	int (*backlight_init)(struct drm_device *dev); -#endif -	int i2c_bus;		/* I2C bus identifier for Moorestown */ -}; - - - -struct psb_mmu_driver; - -extern int drm_crtc_probe_output_modes(struct drm_device *dev, int, int); -extern int drm_pick_crtcs(struct drm_device *dev); - -static inline struct drm_psb_private *psb_priv(struct drm_device *dev) -{ -	return (struct drm_psb_private *) dev->dev_private; -} - -/* - * MMU stuff. - */ - -extern struct psb_mmu_driver *psb_mmu_driver_init(uint8_t __iomem * registers, -					int trap_pagefaults, -					int invalid_type, -					struct drm_psb_private *dev_priv); -extern void psb_mmu_driver_takedown(struct psb_mmu_driver *driver); -extern struct psb_mmu_pd *psb_mmu_get_default_pd(struct psb_mmu_driver -						 *driver); -extern void psb_mmu_mirror_gtt(struct psb_mmu_pd *pd, uint32_t mmu_offset, -			       uint32_t gtt_start, uint32_t gtt_pages); -extern struct psb_mmu_pd *psb_mmu_alloc_pd(struct psb_mmu_driver *driver, -					   int trap_pagefaults, -					   int invalid_type); -extern void psb_mmu_free_pagedir(struct psb_mmu_pd *pd); -extern void psb_mmu_flush(struct psb_mmu_driver *driver, int rc_prot); -extern void psb_mmu_remove_pfn_sequence(struct psb_mmu_pd *pd, -					unsigned long address, -					uint32_t num_pages); -extern int psb_mmu_insert_pfn_sequence(struct psb_mmu_pd *pd, -				       uint32_t start_pfn, -				       unsigned long address, -				       uint32_t num_pages, int type); -extern int psb_mmu_virtual_to_pfn(struct psb_mmu_pd *pd, uint32_t virtual, -				  unsigned long *pfn); - -/* - * Enable / disable MMU for different requestors. - */ - - -extern void psb_mmu_set_pd_context(struct psb_mmu_pd *pd, int hw_context); -extern int psb_mmu_insert_pages(struct psb_mmu_pd *pd, struct page **pages, -				unsigned long address, uint32_t num_pages, -				uint32_t desired_tile_stride, -				uint32_t hw_tile_stride, int type); -extern void psb_mmu_remove_pages(struct psb_mmu_pd *pd, -				 unsigned long address, uint32_t num_pages, -				 uint32_t desired_tile_stride, -				 uint32_t hw_tile_stride); -/* - *psb_irq.c - */ - -extern irqreturn_t psb_irq_handler(DRM_IRQ_ARGS); -extern int psb_irq_enable_dpst(struct drm_device *dev); -extern int psb_irq_disable_dpst(struct drm_device *dev); -extern void psb_irq_preinstall(struct drm_device *dev); -extern int psb_irq_postinstall(struct drm_device *dev); -extern void psb_irq_uninstall(struct drm_device *dev); -extern void psb_irq_turn_on_dpst(struct drm_device *dev); -extern void psb_irq_turn_off_dpst(struct drm_device *dev); - -extern void psb_irq_uninstall_islands(struct drm_device *dev, int hw_islands); -extern int psb_vblank_wait2(struct drm_device *dev, unsigned int *sequence); -extern int psb_vblank_wait(struct drm_device *dev, unsigned int *sequence); -extern int psb_enable_vblank(struct drm_device *dev, int crtc); -extern void psb_disable_vblank(struct drm_device *dev, int crtc); -void -psb_enable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask); - -void -psb_disable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask); - -extern u32 psb_get_vblank_counter(struct drm_device *dev, int crtc); - -extern int mdfld_enable_te(struct drm_device *dev, int pipe); -extern void mdfld_disable_te(struct drm_device *dev, int pipe); - -/* - * intel_opregion.c - */ -extern int gma_intel_opregion_init(struct drm_device *dev); -extern int gma_intel_opregion_exit(struct drm_device *dev); - -/* - * framebuffer.c - */ -extern int psbfb_probed(struct drm_device *dev); -extern int psbfb_remove(struct drm_device *dev, -			struct drm_framebuffer *fb); -/* - * accel_2d.c - */ -extern void psbfb_copyarea(struct fb_info *info, -					const struct fb_copyarea *region); -extern int psbfb_sync(struct fb_info *info); -extern void psb_spank(struct drm_psb_private *dev_priv); -extern int psb_accel_ioctl(struct drm_device *dev, void *data, -							struct drm_file *file); - -/* - * psb_reset.c - */ - -extern void psb_lid_timer_init(struct drm_psb_private *dev_priv); -extern void psb_lid_timer_takedown(struct drm_psb_private *dev_priv); -extern void psb_print_pagefault(struct drm_psb_private *dev_priv); - -/* modesetting */ -extern void psb_modeset_init(struct drm_device *dev); -extern void psb_modeset_cleanup(struct drm_device *dev); -extern int psb_fbdev_init(struct drm_device *dev); - -/* backlight.c */ -int gma_backlight_init(struct drm_device *dev); -void gma_backlight_exit(struct drm_device *dev); - -/* mrst_crtc.c */ -extern const struct drm_crtc_helper_funcs mrst_helper_funcs; - -/* mrst_lvds.c */ -extern void mrst_lvds_init(struct drm_device *dev, -		    struct psb_intel_mode_device *mode_dev); - -/* psb_intel_display.c */ -extern const struct drm_crtc_helper_funcs psb_intel_helper_funcs; -extern const struct drm_crtc_funcs psb_intel_crtc_funcs; - -/* psb_intel_lvds.c */ -extern const struct drm_connector_helper_funcs -					psb_intel_lvds_connector_helper_funcs; -extern const struct drm_connector_funcs psb_intel_lvds_connector_funcs; - -/* gem.c */ -extern int psb_gem_init_object(struct drm_gem_object *obj); -extern void psb_gem_free_object(struct drm_gem_object *obj); -extern int psb_gem_get_aperture(struct drm_device *dev, void *data, -			struct drm_file *file); -extern int psb_gem_dumb_create(struct drm_file *file, struct drm_device *dev, -			struct drm_mode_create_dumb *args); -extern int psb_gem_dumb_destroy(struct drm_file *file, struct drm_device *dev, -			uint32_t handle); -extern int psb_gem_dumb_map_gtt(struct drm_file *file, struct drm_device *dev, -			uint32_t handle, uint64_t *offset); -extern int psb_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf); -extern int psb_gem_create_ioctl(struct drm_device *dev, void *data, -			struct drm_file *file); -extern int psb_gem_mmap_ioctl(struct drm_device *dev, void *data, -					struct drm_file *file); - -/* psb_device.c */ -extern const struct psb_ops psb_chip_ops; - -/* mrst_device.c */ -extern const struct psb_ops mrst_chip_ops; - -/* mdfld_device.c */ -extern const struct psb_ops mdfld_chip_ops; - -/* cdv_device.c */ -extern const struct psb_ops cdv_chip_ops; - -/* - * Debug print bits setting - */ -#define PSB_D_GENERAL (1 << 0) -#define PSB_D_INIT    (1 << 1) -#define PSB_D_IRQ     (1 << 2) -#define PSB_D_ENTRY   (1 << 3) -/* debug the get H/V BP/FP count */ -#define PSB_D_HV      (1 << 4) -#define PSB_D_DBI_BF  (1 << 5) -#define PSB_D_PM      (1 << 6) -#define PSB_D_RENDER  (1 << 7) -#define PSB_D_REG     (1 << 8) -#define PSB_D_MSVDX   (1 << 9) -#define PSB_D_TOPAZ   (1 << 10) - -extern int drm_psb_no_fb; -extern int drm_idle_check_interval; - -/* - *	Utilities - */ - -static inline u32 MRST_MSG_READ32(uint port, uint offset) -{ -	int mcr = (0xD0<<24) | (port << 16) | (offset << 8); -	uint32_t ret_val = 0; -	struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0); -	pci_write_config_dword(pci_root, 0xD0, mcr); -	pci_read_config_dword(pci_root, 0xD4, &ret_val); -	pci_dev_put(pci_root); -	return ret_val; -} -static inline void MRST_MSG_WRITE32(uint port, uint offset, u32 value) -{ -	int mcr = (0xE0<<24) | (port << 16) | (offset << 8) | 0xF0; -	struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0); -	pci_write_config_dword(pci_root, 0xD4, value); -	pci_write_config_dword(pci_root, 0xD0, mcr); -	pci_dev_put(pci_root); -} -static inline u32 MDFLD_MSG_READ32(uint port, uint offset) -{ -	int mcr = (0x10<<24) | (port << 16) | (offset << 8); -	uint32_t ret_val = 0; -	struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0); -	pci_write_config_dword(pci_root, 0xD0, mcr); -	pci_read_config_dword(pci_root, 0xD4, &ret_val); -	pci_dev_put(pci_root); -	return ret_val; -} -static inline void MDFLD_MSG_WRITE32(uint port, uint offset, u32 value) -{ -	int mcr = (0x11<<24) | (port << 16) | (offset << 8) | 0xF0; -	struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0); -	pci_write_config_dword(pci_root, 0xD4, value); -	pci_write_config_dword(pci_root, 0xD0, mcr); -	pci_dev_put(pci_root); -} - -static inline uint32_t REGISTER_READ(struct drm_device *dev, uint32_t reg) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; -	return ioread32(dev_priv->vdc_reg + reg); -} - -#define REG_READ(reg)	       REGISTER_READ(dev, (reg)) - -static inline void REGISTER_WRITE(struct drm_device *dev, uint32_t reg, -				      uint32_t val) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; -	iowrite32((val), dev_priv->vdc_reg + (reg)); -} - -#define REG_WRITE(reg, val)	REGISTER_WRITE(dev, (reg), (val)) - -static inline void REGISTER_WRITE16(struct drm_device *dev, -					uint32_t reg, uint32_t val) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; -	iowrite16((val), dev_priv->vdc_reg + (reg)); -} - -#define REG_WRITE16(reg, val)	  REGISTER_WRITE16(dev, (reg), (val)) - -static inline void REGISTER_WRITE8(struct drm_device *dev, -				       uint32_t reg, uint32_t val) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; -	iowrite8((val), dev_priv->vdc_reg + (reg)); -} - -#define REG_WRITE8(reg, val)		REGISTER_WRITE8(dev, (reg), (val)) - -#define PSB_WVDC32(_val, _offs)		iowrite32(_val, dev_priv->vdc_reg + (_offs)) -#define PSB_RVDC32(_offs)		ioread32(dev_priv->vdc_reg + (_offs)) - -/* #define TRAP_SGX_PM_FAULT 1 */ -#ifdef TRAP_SGX_PM_FAULT -#define PSB_RSGX32(_offs)						\ -({									\ -	if (inl(dev_priv->apm_base + PSB_APM_STS) & 0x3) {		\ -		printk(KERN_ERR						\ -			"access sgx when it's off!! (READ) %s, %d\n",	\ -	       __FILE__, __LINE__);					\ -		melay(1000);						\ -	}								\ -	ioread32(dev_priv->sgx_reg + (_offs));				\ -}) -#else -#define PSB_RSGX32(_offs)		ioread32(dev_priv->sgx_reg + (_offs)) -#endif -#define PSB_WSGX32(_val, _offs)		iowrite32(_val, dev_priv->sgx_reg + (_offs)) - -#define MSVDX_REG_DUMP 0 - -#define PSB_WMSVDX32(_val, _offs)	iowrite32(_val, dev_priv->msvdx_reg + (_offs)) -#define PSB_RMSVDX32(_offs)		ioread32(dev_priv->msvdx_reg + (_offs)) - -#endif diff --git a/drivers/staging/gma500/psb_intel_display.c b/drivers/staging/gma500/psb_intel_display.c deleted file mode 100644 index 85659613ae6..00000000000 --- a/drivers/staging/gma500/psb_intel_display.c +++ /dev/null @@ -1,1429 +0,0 @@ -/* - * Copyright © 2006-2011 Intel Corporation - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - * Authors: - *	Eric Anholt <eric@anholt.net> - */ - -#include <linux/i2c.h> -#include <linux/pm_runtime.h> - -#include <drm/drmP.h> -#include "framebuffer.h" -#include "psb_drv.h" -#include "psb_intel_drv.h" -#include "psb_intel_reg.h" -#include "psb_intel_display.h" -#include "power.h" - -#include "mdfld_output.h" - -struct psb_intel_clock_t { -	/* given values */ -	int n; -	int m1, m2; -	int p1, p2; -	/* derived values */ -	int dot; -	int vco; -	int m; -	int p; -}; - -struct psb_intel_range_t { -	int min, max; -}; - -struct psb_intel_p2_t { -	int dot_limit; -	int p2_slow, p2_fast; -}; - -#define INTEL_P2_NUM		      2 - -struct psb_intel_limit_t { -	struct psb_intel_range_t dot, vco, n, m, m1, m2, p, p1; -	struct psb_intel_p2_t p2; -}; - -#define I8XX_DOT_MIN		  25000 -#define I8XX_DOT_MAX		 350000 -#define I8XX_VCO_MIN		 930000 -#define I8XX_VCO_MAX		1400000 -#define I8XX_N_MIN		      3 -#define I8XX_N_MAX		     16 -#define I8XX_M_MIN		     96 -#define I8XX_M_MAX		    140 -#define I8XX_M1_MIN		     18 -#define I8XX_M1_MAX		     26 -#define I8XX_M2_MIN		      6 -#define I8XX_M2_MAX		     16 -#define I8XX_P_MIN		      4 -#define I8XX_P_MAX		    128 -#define I8XX_P1_MIN		      2 -#define I8XX_P1_MAX		     33 -#define I8XX_P1_LVDS_MIN	      1 -#define I8XX_P1_LVDS_MAX	      6 -#define I8XX_P2_SLOW		      4 -#define I8XX_P2_FAST		      2 -#define I8XX_P2_LVDS_SLOW	      14 -#define I8XX_P2_LVDS_FAST	      14	/* No fast option */ -#define I8XX_P2_SLOW_LIMIT	 165000 - -#define I9XX_DOT_MIN		  20000 -#define I9XX_DOT_MAX		 400000 -#define I9XX_VCO_MIN		1400000 -#define I9XX_VCO_MAX		2800000 -#define I9XX_N_MIN		      3 -#define I9XX_N_MAX		      8 -#define I9XX_M_MIN		     70 -#define I9XX_M_MAX		    120 -#define I9XX_M1_MIN		     10 -#define I9XX_M1_MAX		     20 -#define I9XX_M2_MIN		      5 -#define I9XX_M2_MAX		      9 -#define I9XX_P_SDVO_DAC_MIN	      5 -#define I9XX_P_SDVO_DAC_MAX	     80 -#define I9XX_P_LVDS_MIN		      7 -#define I9XX_P_LVDS_MAX		     98 -#define I9XX_P1_MIN		      1 -#define I9XX_P1_MAX		      8 -#define I9XX_P2_SDVO_DAC_SLOW		     10 -#define I9XX_P2_SDVO_DAC_FAST		      5 -#define I9XX_P2_SDVO_DAC_SLOW_LIMIT	 200000 -#define I9XX_P2_LVDS_SLOW		     14 -#define I9XX_P2_LVDS_FAST		      7 -#define I9XX_P2_LVDS_SLOW_LIMIT		 112000 - -#define INTEL_LIMIT_I8XX_DVO_DAC    0 -#define INTEL_LIMIT_I8XX_LVDS	    1 -#define INTEL_LIMIT_I9XX_SDVO_DAC   2 -#define INTEL_LIMIT_I9XX_LVDS	    3 - -static const struct psb_intel_limit_t psb_intel_limits[] = { -	{			/* INTEL_LIMIT_I8XX_DVO_DAC */ -	 .dot = {.min = I8XX_DOT_MIN, .max = I8XX_DOT_MAX}, -	 .vco = {.min = I8XX_VCO_MIN, .max = I8XX_VCO_MAX}, -	 .n = {.min = I8XX_N_MIN, .max = I8XX_N_MAX}, -	 .m = {.min = I8XX_M_MIN, .max = I8XX_M_MAX}, -	 .m1 = {.min = I8XX_M1_MIN, .max = I8XX_M1_MAX}, -	 .m2 = {.min = I8XX_M2_MIN, .max = I8XX_M2_MAX}, -	 .p = {.min = I8XX_P_MIN, .max = I8XX_P_MAX}, -	 .p1 = {.min = I8XX_P1_MIN, .max = I8XX_P1_MAX}, -	 .p2 = {.dot_limit = I8XX_P2_SLOW_LIMIT, -		.p2_slow = I8XX_P2_SLOW, .p2_fast = I8XX_P2_FAST}, -	 }, -	{			/* INTEL_LIMIT_I8XX_LVDS */ -	 .dot = {.min = I8XX_DOT_MIN, .max = I8XX_DOT_MAX}, -	 .vco = {.min = I8XX_VCO_MIN, .max = I8XX_VCO_MAX}, -	 .n = {.min = I8XX_N_MIN, .max = I8XX_N_MAX}, -	 .m = {.min = I8XX_M_MIN, .max = I8XX_M_MAX}, -	 .m1 = {.min = I8XX_M1_MIN, .max = I8XX_M1_MAX}, -	 .m2 = {.min = I8XX_M2_MIN, .max = I8XX_M2_MAX}, -	 .p = {.min = I8XX_P_MIN, .max = I8XX_P_MAX}, -	 .p1 = {.min = I8XX_P1_LVDS_MIN, .max = I8XX_P1_LVDS_MAX}, -	 .p2 = {.dot_limit = I8XX_P2_SLOW_LIMIT, -		.p2_slow = I8XX_P2_LVDS_SLOW, .p2_fast = I8XX_P2_LVDS_FAST}, -	 }, -	{			/* INTEL_LIMIT_I9XX_SDVO_DAC */ -	 .dot = {.min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX}, -	 .vco = {.min = I9XX_VCO_MIN, .max = I9XX_VCO_MAX}, -	 .n = {.min = I9XX_N_MIN, .max = I9XX_N_MAX}, -	 .m = {.min = I9XX_M_MIN, .max = I9XX_M_MAX}, -	 .m1 = {.min = I9XX_M1_MIN, .max = I9XX_M1_MAX}, -	 .m2 = {.min = I9XX_M2_MIN, .max = I9XX_M2_MAX}, -	 .p = {.min = I9XX_P_SDVO_DAC_MIN, .max = I9XX_P_SDVO_DAC_MAX}, -	 .p1 = {.min = I9XX_P1_MIN, .max = I9XX_P1_MAX}, -	 .p2 = {.dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT, -		.p2_slow = I9XX_P2_SDVO_DAC_SLOW, .p2_fast = -		I9XX_P2_SDVO_DAC_FAST}, -	 }, -	{			/* INTEL_LIMIT_I9XX_LVDS */ -	 .dot = {.min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX}, -	 .vco = {.min = I9XX_VCO_MIN, .max = I9XX_VCO_MAX}, -	 .n = {.min = I9XX_N_MIN, .max = I9XX_N_MAX}, -	 .m = {.min = I9XX_M_MIN, .max = I9XX_M_MAX}, -	 .m1 = {.min = I9XX_M1_MIN, .max = I9XX_M1_MAX}, -	 .m2 = {.min = I9XX_M2_MIN, .max = I9XX_M2_MAX}, -	 .p = {.min = I9XX_P_LVDS_MIN, .max = I9XX_P_LVDS_MAX}, -	 .p1 = {.min = I9XX_P1_MIN, .max = I9XX_P1_MAX}, -	 /* The single-channel range is 25-112Mhz, and dual-channel -	  * is 80-224Mhz.  Prefer single channel as much as possible. -	  */ -	 .p2 = {.dot_limit = I9XX_P2_LVDS_SLOW_LIMIT, -		.p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_FAST}, -	 }, -}; - -static const struct psb_intel_limit_t *psb_intel_limit(struct drm_crtc *crtc) -{ -	const struct psb_intel_limit_t *limit; - -	if (psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) -		limit = &psb_intel_limits[INTEL_LIMIT_I9XX_LVDS]; -	else -		limit = &psb_intel_limits[INTEL_LIMIT_I9XX_SDVO_DAC]; -	return limit; -} - -/** Derive the pixel clock for the given refclk and divisors for 8xx chips. */ - -static void i8xx_clock(int refclk, struct psb_intel_clock_t *clock) -{ -	clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2); -	clock->p = clock->p1 * clock->p2; -	clock->vco = refclk * clock->m / (clock->n + 2); -	clock->dot = clock->vco / clock->p; -} - -/** Derive the pixel clock for the given refclk and divisors for 9xx chips. */ - -static void i9xx_clock(int refclk, struct psb_intel_clock_t *clock) -{ -	clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2); -	clock->p = clock->p1 * clock->p2; -	clock->vco = refclk * clock->m / (clock->n + 2); -	clock->dot = clock->vco / clock->p; -} - -static void psb_intel_clock(struct drm_device *dev, int refclk, -			struct psb_intel_clock_t *clock) -{ -	return i9xx_clock(refclk, clock); -} - -/** - * Returns whether any output on the specified pipe is of the specified type - */ -bool psb_intel_pipe_has_type(struct drm_crtc *crtc, int type) -{ -	struct drm_device *dev = crtc->dev; -	struct drm_mode_config *mode_config = &dev->mode_config; -	struct drm_connector *l_entry; - -	list_for_each_entry(l_entry, &mode_config->connector_list, head) { -		if (l_entry->encoder && l_entry->encoder->crtc == crtc) { -			struct psb_intel_output *psb_intel_output = -			    to_psb_intel_output(l_entry); -			if (psb_intel_output->type == type) -				return true; -		} -	} -	return false; -} - -#define INTELPllInvalid(s)   { /* ErrorF (s) */; return false; } -/** - * Returns whether the given set of divisors are valid for a given refclk with - * the given connectors. - */ - -static bool psb_intel_PLL_is_valid(struct drm_crtc *crtc, -			       struct psb_intel_clock_t *clock) -{ -	const struct psb_intel_limit_t *limit = psb_intel_limit(crtc); - -	if (clock->p1 < limit->p1.min || limit->p1.max < clock->p1) -		INTELPllInvalid("p1 out of range\n"); -	if (clock->p < limit->p.min || limit->p.max < clock->p) -		INTELPllInvalid("p out of range\n"); -	if (clock->m2 < limit->m2.min || limit->m2.max < clock->m2) -		INTELPllInvalid("m2 out of range\n"); -	if (clock->m1 < limit->m1.min || limit->m1.max < clock->m1) -		INTELPllInvalid("m1 out of range\n"); -	if (clock->m1 <= clock->m2) -		INTELPllInvalid("m1 <= m2\n"); -	if (clock->m < limit->m.min || limit->m.max < clock->m) -		INTELPllInvalid("m out of range\n"); -	if (clock->n < limit->n.min || limit->n.max < clock->n) -		INTELPllInvalid("n out of range\n"); -	if (clock->vco < limit->vco.min || limit->vco.max < clock->vco) -		INTELPllInvalid("vco out of range\n"); -	/* XXX: We may need to be checking "Dot clock" -	 * depending on the multiplier, connector, etc., -	 * rather than just a single range. -	 */ -	if (clock->dot < limit->dot.min || limit->dot.max < clock->dot) -		INTELPllInvalid("dot out of range\n"); - -	return true; -} - -/** - * Returns a set of divisors for the desired target clock with the given - * refclk, or FALSE.  The returned values represent the clock equation: - * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2. - */ -static bool psb_intel_find_best_PLL(struct drm_crtc *crtc, int target, -				int refclk, -				struct psb_intel_clock_t *best_clock) -{ -	struct drm_device *dev = crtc->dev; -	struct psb_intel_clock_t clock; -	const struct psb_intel_limit_t *limit = psb_intel_limit(crtc); -	int err = target; - -	if (psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) && -	    (REG_READ(LVDS) & LVDS_PORT_EN) != 0) { -		/* -		 * For LVDS, if the panel is on, just rely on its current -		 * settings for dual-channel.  We haven't figured out how to -		 * reliably set up different single/dual channel state, if we -		 * even can. -		 */ -		if ((REG_READ(LVDS) & LVDS_CLKB_POWER_MASK) == -		    LVDS_CLKB_POWER_UP) -			clock.p2 = limit->p2.p2_fast; -		else -			clock.p2 = limit->p2.p2_slow; -	} else { -		if (target < limit->p2.dot_limit) -			clock.p2 = limit->p2.p2_slow; -		else -			clock.p2 = limit->p2.p2_fast; -	} - -	memset(best_clock, 0, sizeof(*best_clock)); - -	for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max; -	     clock.m1++) { -		for (clock.m2 = limit->m2.min; -		     clock.m2 < clock.m1 && clock.m2 <= limit->m2.max; -		     clock.m2++) { -			for (clock.n = limit->n.min; -			     clock.n <= limit->n.max; clock.n++) { -				for (clock.p1 = limit->p1.min; -				     clock.p1 <= limit->p1.max; -				     clock.p1++) { -					int this_err; - -					psb_intel_clock(dev, refclk, &clock); - -					if (!psb_intel_PLL_is_valid -					    (crtc, &clock)) -						continue; - -					this_err = abs(clock.dot - target); -					if (this_err < err) { -						*best_clock = clock; -						err = this_err; -					} -				} -			} -		} -	} - -	return err != target; -} - -void psb_intel_wait_for_vblank(struct drm_device *dev) -{ -	/* Wait for 20ms, i.e. one cycle at 50hz. */ -	mdelay(20); -} - -int psb_intel_pipe_set_base(struct drm_crtc *crtc, -			    int x, int y, struct drm_framebuffer *old_fb) -{ -	struct drm_device *dev = crtc->dev; -	/* struct drm_i915_master_private *master_priv; */ -	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); -	struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb); -	int pipe = psb_intel_crtc->pipe; -	unsigned long start, offset; -	int dspbase = (pipe == 0 ? DSPABASE : DSPBBASE); -	int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF); -	int dspstride = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE; -	int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; -	u32 dspcntr; -	int ret = 0; - -	if (!gma_power_begin(dev, true)) -		return 0; - -	/* no fb bound */ -	if (!crtc->fb) { -		dev_dbg(dev->dev, "No FB bound\n"); -		goto psb_intel_pipe_cleaner; -	} - -	/* We are displaying this buffer, make sure it is actually loaded -	   into the GTT */ -	ret = psb_gtt_pin(psbfb->gtt); -	if (ret < 0) -		goto psb_intel_pipe_set_base_exit; -	start = psbfb->gtt->offset; - -	offset = y * crtc->fb->pitches[0] + x * (crtc->fb->bits_per_pixel / 8); - -	REG_WRITE(dspstride, crtc->fb->pitches[0]); - -	dspcntr = REG_READ(dspcntr_reg); -	dspcntr &= ~DISPPLANE_PIXFORMAT_MASK; - -	switch (crtc->fb->bits_per_pixel) { -	case 8: -		dspcntr |= DISPPLANE_8BPP; -		break; -	case 16: -		if (crtc->fb->depth == 15) -			dspcntr |= DISPPLANE_15_16BPP; -		else -			dspcntr |= DISPPLANE_16BPP; -		break; -	case 24: -	case 32: -		dspcntr |= DISPPLANE_32BPP_NO_ALPHA; -		break; -	default: -		dev_err(dev->dev, "Unknown color depth\n"); -		ret = -EINVAL; -		psb_gtt_unpin(psbfb->gtt); -		goto psb_intel_pipe_set_base_exit; -	} -	REG_WRITE(dspcntr_reg, dspcntr); - - -	if (0 /* FIXMEAC - check what PSB needs */) { -		REG_WRITE(dspbase, offset); -		REG_READ(dspbase); -		REG_WRITE(dspsurf, start); -		REG_READ(dspsurf); -	} else { -		REG_WRITE(dspbase, start + offset); -		REG_READ(dspbase); -	} - -psb_intel_pipe_cleaner: -	/* If there was a previous display we can now unpin it */ -	if (old_fb) -		psb_gtt_unpin(to_psb_fb(old_fb)->gtt); - -psb_intel_pipe_set_base_exit: -	gma_power_end(dev); -	return ret; -} - -/** - * Sets the power management mode of the pipe and plane. - * - * This code should probably grow support for turning the cursor off and back - * on appropriately at the same time as we're turning the pipe off/on. - */ -static void psb_intel_crtc_dpms(struct drm_crtc *crtc, int mode) -{ -	struct drm_device *dev = crtc->dev; -	/* struct drm_i915_master_private *master_priv; */ -	/* struct drm_i915_private *dev_priv = dev->dev_private; */ -	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); -	int pipe = psb_intel_crtc->pipe; -	int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B; -	int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; -	int dspbase_reg = (pipe == 0) ? DSPABASE : DSPBBASE; -	int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; -	u32 temp; -	bool enabled; - -	/* XXX: When our outputs are all unaware of DPMS modes other than off -	 * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC. -	 */ -	switch (mode) { -	case DRM_MODE_DPMS_ON: -	case DRM_MODE_DPMS_STANDBY: -	case DRM_MODE_DPMS_SUSPEND: -		/* Enable the DPLL */ -		temp = REG_READ(dpll_reg); -		if ((temp & DPLL_VCO_ENABLE) == 0) { -			REG_WRITE(dpll_reg, temp); -			REG_READ(dpll_reg); -			/* Wait for the clocks to stabilize. */ -			udelay(150); -			REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE); -			REG_READ(dpll_reg); -			/* Wait for the clocks to stabilize. */ -			udelay(150); -			REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE); -			REG_READ(dpll_reg); -			/* Wait for the clocks to stabilize. */ -			udelay(150); -		} - -		/* Enable the pipe */ -		temp = REG_READ(pipeconf_reg); -		if ((temp & PIPEACONF_ENABLE) == 0) -			REG_WRITE(pipeconf_reg, temp | PIPEACONF_ENABLE); - -		/* Enable the plane */ -		temp = REG_READ(dspcntr_reg); -		if ((temp & DISPLAY_PLANE_ENABLE) == 0) { -			REG_WRITE(dspcntr_reg, -				  temp | DISPLAY_PLANE_ENABLE); -			/* Flush the plane changes */ -			REG_WRITE(dspbase_reg, REG_READ(dspbase_reg)); -		} - -		psb_intel_crtc_load_lut(crtc); - -		/* Give the overlay scaler a chance to enable -		 * if it's on this pipe */ -		/* psb_intel_crtc_dpms_video(crtc, true); TODO */ -		break; -	case DRM_MODE_DPMS_OFF: -		/* Give the overlay scaler a chance to disable -		 * if it's on this pipe */ -		/* psb_intel_crtc_dpms_video(crtc, FALSE); TODO */ - -		/* Disable the VGA plane that we never use */ -		REG_WRITE(VGACNTRL, VGA_DISP_DISABLE); - -		/* Disable display plane */ -		temp = REG_READ(dspcntr_reg); -		if ((temp & DISPLAY_PLANE_ENABLE) != 0) { -			REG_WRITE(dspcntr_reg, -				  temp & ~DISPLAY_PLANE_ENABLE); -			/* Flush the plane changes */ -			REG_WRITE(dspbase_reg, REG_READ(dspbase_reg)); -			REG_READ(dspbase_reg); -		} - -		/* Next, disable display pipes */ -		temp = REG_READ(pipeconf_reg); -		if ((temp & PIPEACONF_ENABLE) != 0) { -			REG_WRITE(pipeconf_reg, temp & ~PIPEACONF_ENABLE); -			REG_READ(pipeconf_reg); -		} - -		/* Wait for vblank for the disable to take effect. */ -		psb_intel_wait_for_vblank(dev); - -		temp = REG_READ(dpll_reg); -		if ((temp & DPLL_VCO_ENABLE) != 0) { -			REG_WRITE(dpll_reg, temp & ~DPLL_VCO_ENABLE); -			REG_READ(dpll_reg); -		} - -		/* Wait for the clocks to turn off. */ -		udelay(150); -		break; -	} - -	enabled = crtc->enabled && mode != DRM_MODE_DPMS_OFF; - -	/*Set FIFO Watermarks*/ -	REG_WRITE(DSPARB, 0x3F3E); -} - -static void psb_intel_crtc_prepare(struct drm_crtc *crtc) -{ -	struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; -	crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF); -} - -static void psb_intel_crtc_commit(struct drm_crtc *crtc) -{ -	struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; -	crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON); -} - -void psb_intel_encoder_prepare(struct drm_encoder *encoder) -{ -	struct drm_encoder_helper_funcs *encoder_funcs = -	    encoder->helper_private; -	/* lvds has its own version of prepare see psb_intel_lvds_prepare */ -	encoder_funcs->dpms(encoder, DRM_MODE_DPMS_OFF); -} - -void psb_intel_encoder_commit(struct drm_encoder *encoder) -{ -	struct drm_encoder_helper_funcs *encoder_funcs = -	    encoder->helper_private; -	/* lvds has its own version of commit see psb_intel_lvds_commit */ -	encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON); -} - -static bool psb_intel_crtc_mode_fixup(struct drm_crtc *crtc, -				  struct drm_display_mode *mode, -				  struct drm_display_mode *adjusted_mode) -{ -	return true; -} - - -/** - * Return the pipe currently connected to the panel fitter, - * or -1 if the panel fitter is not present or not in use - */ -static int psb_intel_panel_fitter_pipe(struct drm_device *dev) -{ -	u32 pfit_control; - -	pfit_control = REG_READ(PFIT_CONTROL); - -	/* See if the panel fitter is in use */ -	if ((pfit_control & PFIT_ENABLE) == 0) -		return -1; -	/* Must be on PIPE 1 for PSB */ -	return 1; -} - -static int psb_intel_crtc_mode_set(struct drm_crtc *crtc, -			       struct drm_display_mode *mode, -			       struct drm_display_mode *adjusted_mode, -			       int x, int y, -			       struct drm_framebuffer *old_fb) -{ -	struct drm_device *dev = crtc->dev; -	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); -	struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; -	int pipe = psb_intel_crtc->pipe; -	int fp_reg = (pipe == 0) ? FPA0 : FPB0; -	int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B; -	int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; -	int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; -	int htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B; -	int hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B; -	int hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B; -	int vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B; -	int vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B; -	int vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B; -	int dspsize_reg = (pipe == 0) ? DSPASIZE : DSPBSIZE; -	int dsppos_reg = (pipe == 0) ? DSPAPOS : DSPBPOS; -	int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC; -	int refclk; -	struct psb_intel_clock_t clock; -	u32 dpll = 0, fp = 0, dspcntr, pipeconf; -	bool ok, is_sdvo = false, is_dvo = false; -	bool is_crt = false, is_lvds = false, is_tv = false; -	struct drm_mode_config *mode_config = &dev->mode_config; -	struct drm_connector *connector; - -	/* No scan out no play */ -	if (crtc->fb == NULL) { -		crtc_funcs->mode_set_base(crtc, x, y, old_fb); -		return 0; -	} - -	list_for_each_entry(connector, &mode_config->connector_list, head) { -		struct psb_intel_output *psb_intel_output = -		    to_psb_intel_output(connector); - -		if (!connector->encoder -		    || connector->encoder->crtc != crtc) -			continue; - -		switch (psb_intel_output->type) { -		case INTEL_OUTPUT_LVDS: -			is_lvds = true; -			break; -		case INTEL_OUTPUT_SDVO: -			is_sdvo = true; -			break; -		case INTEL_OUTPUT_DVO: -			is_dvo = true; -			break; -		case INTEL_OUTPUT_TVOUT: -			is_tv = true; -			break; -		case INTEL_OUTPUT_ANALOG: -			is_crt = true; -			break; -		} -	} - -	refclk = 96000; - -	ok = psb_intel_find_best_PLL(crtc, adjusted_mode->clock, refclk, -				 &clock); -	if (!ok) { -		dev_err(dev->dev, "Couldn't find PLL settings for mode!\n"); -		return 0; -	} - -	fp = clock.n << 16 | clock.m1 << 8 | clock.m2; - -	dpll = DPLL_VGA_MODE_DIS; -	if (is_lvds) { -		dpll |= DPLLB_MODE_LVDS; -		dpll |= DPLL_DVO_HIGH_SPEED; -	} else -		dpll |= DPLLB_MODE_DAC_SERIAL; -	if (is_sdvo) { -		int sdvo_pixel_multiply = -			    adjusted_mode->clock / mode->clock; -		dpll |= DPLL_DVO_HIGH_SPEED; -		dpll |= -		    (sdvo_pixel_multiply - 1) << SDVO_MULTIPLIER_SHIFT_HIRES; -	} - -	/* compute bitmask from p1 value */ -	dpll |= (1 << (clock.p1 - 1)) << 16; -	switch (clock.p2) { -	case 5: -		dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_5; -		break; -	case 7: -		dpll |= DPLLB_LVDS_P2_CLOCK_DIV_7; -		break; -	case 10: -		dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_10; -		break; -	case 14: -		dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14; -		break; -	} - -	if (is_tv) { -		/* XXX: just matching BIOS for now */ -/*	dpll |= PLL_REF_INPUT_TVCLKINBC; */ -		dpll |= 3; -	} -	dpll |= PLL_REF_INPUT_DREFCLK; - -	/* setup pipeconf */ -	pipeconf = REG_READ(pipeconf_reg); - -	/* Set up the display plane register */ -	dspcntr = DISPPLANE_GAMMA_ENABLE; - -	if (pipe == 0) -		dspcntr |= DISPPLANE_SEL_PIPE_A; -	else -		dspcntr |= DISPPLANE_SEL_PIPE_B; - -	dspcntr |= DISPLAY_PLANE_ENABLE; -	pipeconf |= PIPEACONF_ENABLE; -	dpll |= DPLL_VCO_ENABLE; - - -	/* Disable the panel fitter if it was on our pipe */ -	if (psb_intel_panel_fitter_pipe(dev) == pipe) -		REG_WRITE(PFIT_CONTROL, 0); - -	drm_mode_debug_printmodeline(mode); - -	if (dpll & DPLL_VCO_ENABLE) { -		REG_WRITE(fp_reg, fp); -		REG_WRITE(dpll_reg, dpll & ~DPLL_VCO_ENABLE); -		REG_READ(dpll_reg); -		udelay(150); -	} - -	/* The LVDS pin pair needs to be on before the DPLLs are enabled. -	 * This is an exception to the general rule that mode_set doesn't turn -	 * things on. -	 */ -	if (is_lvds) { -		u32 lvds = REG_READ(LVDS); - -		lvds &= ~LVDS_PIPEB_SELECT; -		if (pipe == 1) -			lvds |= LVDS_PIPEB_SELECT; - -		lvds |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP; -		/* Set the B0-B3 data pairs corresponding to -		 * whether we're going to -		 * set the DPLLs for dual-channel mode or not. -		 */ -		lvds &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP); -		if (clock.p2 == 7) -			lvds |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP; - -		/* It would be nice to set 24 vs 18-bit mode (LVDS_A3_POWER_UP) -		 * appropriately here, but we need to look more -		 * thoroughly into how panels behave in the two modes. -		 */ - -		REG_WRITE(LVDS, lvds); -		REG_READ(LVDS); -	} - -	REG_WRITE(fp_reg, fp); -	REG_WRITE(dpll_reg, dpll); -	REG_READ(dpll_reg); -	/* Wait for the clocks to stabilize. */ -	udelay(150); - -	/* write it again -- the BIOS does, after all */ -	REG_WRITE(dpll_reg, dpll); - -	REG_READ(dpll_reg); -	/* Wait for the clocks to stabilize. */ -	udelay(150); - -	REG_WRITE(htot_reg, (adjusted_mode->crtc_hdisplay - 1) | -		  ((adjusted_mode->crtc_htotal - 1) << 16)); -	REG_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) | -		  ((adjusted_mode->crtc_hblank_end - 1) << 16)); -	REG_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - 1) | -		  ((adjusted_mode->crtc_hsync_end - 1) << 16)); -	REG_WRITE(vtot_reg, (adjusted_mode->crtc_vdisplay - 1) | -		  ((adjusted_mode->crtc_vtotal - 1) << 16)); -	REG_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - 1) | -		  ((adjusted_mode->crtc_vblank_end - 1) << 16)); -	REG_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - 1) | -		  ((adjusted_mode->crtc_vsync_end - 1) << 16)); -	/* pipesrc and dspsize control the size that is scaled from, -	 * which should always be the user's requested size. -	 */ -	REG_WRITE(dspsize_reg, -		  ((mode->vdisplay - 1) << 16) | (mode->hdisplay - 1)); -	REG_WRITE(dsppos_reg, 0); -	REG_WRITE(pipesrc_reg, -		  ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1)); -	REG_WRITE(pipeconf_reg, pipeconf); -	REG_READ(pipeconf_reg); - -	psb_intel_wait_for_vblank(dev); - -	REG_WRITE(dspcntr_reg, dspcntr); - -	/* Flush the plane changes */ -	crtc_funcs->mode_set_base(crtc, x, y, old_fb); - -	psb_intel_wait_for_vblank(dev); - -	return 0; -} - -/** Loads the palette/gamma unit for the CRTC with the prepared values */ -void psb_intel_crtc_load_lut(struct drm_crtc *crtc) -{ -	struct drm_device *dev = crtc->dev; -	struct drm_psb_private *dev_priv = -				(struct drm_psb_private *)dev->dev_private; -	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); -	int palreg = PALETTE_A; -	int i; - -	/* The clocks have to be on to load the palette. */ -	if (!crtc->enabled) -		return; - -	switch (psb_intel_crtc->pipe) { -	case 0: -		break; -	case 1: -		palreg = PALETTE_B; -		break; -	case 2: -		palreg = PALETTE_C; -		break; -	default: -		dev_err(dev->dev, "Illegal Pipe Number.\n"); -		return; -	} - -	if (gma_power_begin(dev, false)) { -		for (i = 0; i < 256; i++) { -			REG_WRITE(palreg + 4 * i, -				  ((psb_intel_crtc->lut_r[i] + -				  psb_intel_crtc->lut_adj[i]) << 16) | -				  ((psb_intel_crtc->lut_g[i] + -				  psb_intel_crtc->lut_adj[i]) << 8) | -				  (psb_intel_crtc->lut_b[i] + -				  psb_intel_crtc->lut_adj[i])); -		} -		gma_power_end(dev); -	} else { -		for (i = 0; i < 256; i++) { -			dev_priv->save_palette_a[i] = -				  ((psb_intel_crtc->lut_r[i] + -				  psb_intel_crtc->lut_adj[i]) << 16) | -				  ((psb_intel_crtc->lut_g[i] + -				  psb_intel_crtc->lut_adj[i]) << 8) | -				  (psb_intel_crtc->lut_b[i] + -				  psb_intel_crtc->lut_adj[i]); -		} - -	} -} - -/** - * Save HW states of giving crtc - */ -static void psb_intel_crtc_save(struct drm_crtc *crtc) -{ -	struct drm_device *dev = crtc->dev; -	/* struct drm_psb_private *dev_priv = -			(struct drm_psb_private *)dev->dev_private; */ -	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); -	struct psb_intel_crtc_state *crtc_state = psb_intel_crtc->crtc_state; -	int pipeA = (psb_intel_crtc->pipe == 0); -	uint32_t paletteReg; -	int i; - -	if (!crtc_state) { -		dev_err(dev->dev, "No CRTC state found\n"); -		return; -	} - -	crtc_state->saveDSPCNTR = REG_READ(pipeA ? DSPACNTR : DSPBCNTR); -	crtc_state->savePIPECONF = REG_READ(pipeA ? PIPEACONF : PIPEBCONF); -	crtc_state->savePIPESRC = REG_READ(pipeA ? PIPEASRC : PIPEBSRC); -	crtc_state->saveFP0 = REG_READ(pipeA ? FPA0 : FPB0); -	crtc_state->saveFP1 = REG_READ(pipeA ? FPA1 : FPB1); -	crtc_state->saveDPLL = REG_READ(pipeA ? DPLL_A : DPLL_B); -	crtc_state->saveHTOTAL = REG_READ(pipeA ? HTOTAL_A : HTOTAL_B); -	crtc_state->saveHBLANK = REG_READ(pipeA ? HBLANK_A : HBLANK_B); -	crtc_state->saveHSYNC = REG_READ(pipeA ? HSYNC_A : HSYNC_B); -	crtc_state->saveVTOTAL = REG_READ(pipeA ? VTOTAL_A : VTOTAL_B); -	crtc_state->saveVBLANK = REG_READ(pipeA ? VBLANK_A : VBLANK_B); -	crtc_state->saveVSYNC = REG_READ(pipeA ? VSYNC_A : VSYNC_B); -	crtc_state->saveDSPSTRIDE = REG_READ(pipeA ? DSPASTRIDE : DSPBSTRIDE); - -	/*NOTE: DSPSIZE DSPPOS only for psb*/ -	crtc_state->saveDSPSIZE = REG_READ(pipeA ? DSPASIZE : DSPBSIZE); -	crtc_state->saveDSPPOS = REG_READ(pipeA ? DSPAPOS : DSPBPOS); - -	crtc_state->saveDSPBASE = REG_READ(pipeA ? DSPABASE : DSPBBASE); - -	paletteReg = pipeA ? PALETTE_A : PALETTE_B; -	for (i = 0; i < 256; ++i) -		crtc_state->savePalette[i] = REG_READ(paletteReg + (i << 2)); -} - -/** - * Restore HW states of giving crtc - */ -static void psb_intel_crtc_restore(struct drm_crtc *crtc) -{ -	struct drm_device *dev = crtc->dev; -	/* struct drm_psb_private * dev_priv = -				(struct drm_psb_private *)dev->dev_private; */ -	struct psb_intel_crtc *psb_intel_crtc =  to_psb_intel_crtc(crtc); -	struct psb_intel_crtc_state *crtc_state = psb_intel_crtc->crtc_state; -	/* struct drm_crtc_helper_funcs * crtc_funcs = crtc->helper_private; */ -	int pipeA = (psb_intel_crtc->pipe == 0); -	uint32_t paletteReg; -	int i; - -	if (!crtc_state) { -		dev_err(dev->dev, "No crtc state\n"); -		return; -	} - -	if (crtc_state->saveDPLL & DPLL_VCO_ENABLE) { -		REG_WRITE(pipeA ? DPLL_A : DPLL_B, -			crtc_state->saveDPLL & ~DPLL_VCO_ENABLE); -		REG_READ(pipeA ? DPLL_A : DPLL_B); -		udelay(150); -	} - -	REG_WRITE(pipeA ? FPA0 : FPB0, crtc_state->saveFP0); -	REG_READ(pipeA ? FPA0 : FPB0); - -	REG_WRITE(pipeA ? FPA1 : FPB1, crtc_state->saveFP1); -	REG_READ(pipeA ? FPA1 : FPB1); - -	REG_WRITE(pipeA ? DPLL_A : DPLL_B, crtc_state->saveDPLL); -	REG_READ(pipeA ? DPLL_A : DPLL_B); -	udelay(150); - -	REG_WRITE(pipeA ? HTOTAL_A : HTOTAL_B, crtc_state->saveHTOTAL); -	REG_WRITE(pipeA ? HBLANK_A : HBLANK_B, crtc_state->saveHBLANK); -	REG_WRITE(pipeA ? HSYNC_A : HSYNC_B, crtc_state->saveHSYNC); -	REG_WRITE(pipeA ? VTOTAL_A : VTOTAL_B, crtc_state->saveVTOTAL); -	REG_WRITE(pipeA ? VBLANK_A : VBLANK_B, crtc_state->saveVBLANK); -	REG_WRITE(pipeA ? VSYNC_A : VSYNC_B, crtc_state->saveVSYNC); -	REG_WRITE(pipeA ? DSPASTRIDE : DSPBSTRIDE, crtc_state->saveDSPSTRIDE); - -	REG_WRITE(pipeA ? DSPASIZE : DSPBSIZE, crtc_state->saveDSPSIZE); -	REG_WRITE(pipeA ? DSPAPOS : DSPBPOS, crtc_state->saveDSPPOS); - -	REG_WRITE(pipeA ? PIPEASRC : PIPEBSRC, crtc_state->savePIPESRC); -	REG_WRITE(pipeA ? DSPABASE : DSPBBASE, crtc_state->saveDSPBASE); -	REG_WRITE(pipeA ? PIPEACONF : PIPEBCONF, crtc_state->savePIPECONF); - -	psb_intel_wait_for_vblank(dev); - -	REG_WRITE(pipeA ? DSPACNTR : DSPBCNTR, crtc_state->saveDSPCNTR); -	REG_WRITE(pipeA ? DSPABASE : DSPBBASE, crtc_state->saveDSPBASE); - -	psb_intel_wait_for_vblank(dev); - -	paletteReg = pipeA ? PALETTE_A : PALETTE_B; -	for (i = 0; i < 256; ++i) -		REG_WRITE(paletteReg + (i << 2), crtc_state->savePalette[i]); -} - -static int psb_intel_crtc_cursor_set(struct drm_crtc *crtc, -				 struct drm_file *file_priv, -				 uint32_t handle, -				 uint32_t width, uint32_t height) -{ -	struct drm_device *dev = crtc->dev; -	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); -	int pipe = psb_intel_crtc->pipe; -	uint32_t control = (pipe == 0) ? CURACNTR : CURBCNTR; -	uint32_t base = (pipe == 0) ? CURABASE : CURBBASE; -	uint32_t temp; -	size_t addr = 0; -	struct gtt_range *gt; -	struct drm_gem_object *obj; -	int ret; - -	/* if we want to turn of the cursor ignore width and height */ -	if (!handle) { -		/* turn off the cursor */ -		temp = CURSOR_MODE_DISABLE; - -		if (gma_power_begin(dev, false)) { -			REG_WRITE(control, temp); -			REG_WRITE(base, 0); -			gma_power_end(dev); -		} - -		/* Unpin the old GEM object */ -		if (psb_intel_crtc->cursor_obj) { -			gt = container_of(psb_intel_crtc->cursor_obj, -							struct gtt_range, gem); -			psb_gtt_unpin(gt); -			drm_gem_object_unreference(psb_intel_crtc->cursor_obj); -			psb_intel_crtc->cursor_obj = NULL; -		} - -		return 0; -	} - -	/* Currently we only support 64x64 cursors */ -	if (width != 64 || height != 64) { -		dev_dbg(dev->dev, "we currently only support 64x64 cursors\n"); -		return -EINVAL; -	} - -	obj = drm_gem_object_lookup(dev, file_priv, handle); -	if (!obj) -		return -ENOENT; - -	if (obj->size < width * height * 4) { -		dev_dbg(dev->dev, "buffer is to small\n"); -		return -ENOMEM; -	} - -	gt = container_of(obj, struct gtt_range, gem); - -	/* Pin the memory into the GTT */ -	ret = psb_gtt_pin(gt); -	if (ret) { -		dev_err(dev->dev, "Can not pin down handle 0x%x\n", handle); -		return ret; -	} - - -	addr = gt->offset;	/* Or resource.start ??? */ - -	psb_intel_crtc->cursor_addr = addr; - -	temp = 0; -	/* set the pipe for the cursor */ -	temp |= (pipe << 28); -	temp |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE; - -	if (gma_power_begin(dev, false)) { -		REG_WRITE(control, temp); -		REG_WRITE(base, addr); -		gma_power_end(dev); -	} - -	/* unpin the old bo */ -	if (psb_intel_crtc->cursor_obj) { -		gt = container_of(psb_intel_crtc->cursor_obj, -							struct gtt_range, gem); -		psb_gtt_unpin(gt); -		drm_gem_object_unreference(psb_intel_crtc->cursor_obj); -		psb_intel_crtc->cursor_obj = obj; -	} -	return 0; -} - -static int psb_intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) -{ -	struct drm_device *dev = crtc->dev; -	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); -	int pipe = psb_intel_crtc->pipe; -	uint32_t temp = 0; -	uint32_t addr; - - -	if (x < 0) { -		temp |= (CURSOR_POS_SIGN << CURSOR_X_SHIFT); -		x = -x; -	} -	if (y < 0) { -		temp |= (CURSOR_POS_SIGN << CURSOR_Y_SHIFT); -		y = -y; -	} - -	temp |= ((x & CURSOR_POS_MASK) << CURSOR_X_SHIFT); -	temp |= ((y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT); - -	addr = psb_intel_crtc->cursor_addr; - -	if (gma_power_begin(dev, false)) { -		REG_WRITE((pipe == 0) ? CURAPOS : CURBPOS, temp); -		REG_WRITE((pipe == 0) ? CURABASE : CURBBASE, addr); -		gma_power_end(dev); -	} -	return 0; -} - -void psb_intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, -			 u16 *green, u16 *blue, uint32_t type, uint32_t size) -{ -	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); -	int i; - -	if (size != 256) -		return; - -	for (i = 0; i < 256; i++) { -		psb_intel_crtc->lut_r[i] = red[i] >> 8; -		psb_intel_crtc->lut_g[i] = green[i] >> 8; -		psb_intel_crtc->lut_b[i] = blue[i] >> 8; -	} - -	psb_intel_crtc_load_lut(crtc); -} - -static int psb_crtc_set_config(struct drm_mode_set *set) -{ -	int ret; -	struct drm_device *dev = set->crtc->dev; - -	pm_runtime_forbid(&dev->pdev->dev); -	ret = drm_crtc_helper_set_config(set); -	pm_runtime_allow(&dev->pdev->dev); -	return ret; -} - -/* Returns the clock of the currently programmed mode of the given pipe. */ -static int psb_intel_crtc_clock_get(struct drm_device *dev, -				struct drm_crtc *crtc) -{ -	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); -	int pipe = psb_intel_crtc->pipe; -	u32 dpll; -	u32 fp; -	struct psb_intel_clock_t clock; -	bool is_lvds; -	struct drm_psb_private *dev_priv = dev->dev_private; - -	if (gma_power_begin(dev, false)) { -		dpll = REG_READ((pipe == 0) ? DPLL_A : DPLL_B); -		if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0) -			fp = REG_READ((pipe == 0) ? FPA0 : FPB0); -		else -			fp = REG_READ((pipe == 0) ? FPA1 : FPB1); -		is_lvds = (pipe == 1) && (REG_READ(LVDS) & LVDS_PORT_EN); -		gma_power_end(dev); -	} else { -		dpll = (pipe == 0) ? -			dev_priv->saveDPLL_A : dev_priv->saveDPLL_B; - -		if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0) -			fp = (pipe == 0) ? -				dev_priv->saveFPA0 : -				dev_priv->saveFPB0; -		else -			fp = (pipe == 0) ? -				dev_priv->saveFPA1 : -				dev_priv->saveFPB1; - -		is_lvds = (pipe == 1) && (dev_priv->saveLVDS & LVDS_PORT_EN); -	} - -	clock.m1 = (fp & FP_M1_DIV_MASK) >> FP_M1_DIV_SHIFT; -	clock.m2 = (fp & FP_M2_DIV_MASK) >> FP_M2_DIV_SHIFT; -	clock.n = (fp & FP_N_DIV_MASK) >> FP_N_DIV_SHIFT; - -	if (is_lvds) { -		clock.p1 = -		    ffs((dpll & -			 DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS) >> -			DPLL_FPA01_P1_POST_DIV_SHIFT); -		clock.p2 = 14; - -		if ((dpll & PLL_REF_INPUT_MASK) == -		    PLLB_REF_INPUT_SPREADSPECTRUMIN) { -			/* XXX: might not be 66MHz */ -			i8xx_clock(66000, &clock); -		} else -			i8xx_clock(48000, &clock); -	} else { -		if (dpll & PLL_P1_DIVIDE_BY_TWO) -			clock.p1 = 2; -		else { -			clock.p1 = -			    ((dpll & -			      DPLL_FPA01_P1_POST_DIV_MASK_I830) >> -			     DPLL_FPA01_P1_POST_DIV_SHIFT) + 2; -		} -		if (dpll & PLL_P2_DIVIDE_BY_4) -			clock.p2 = 4; -		else -			clock.p2 = 2; - -		i8xx_clock(48000, &clock); -	} - -	/* XXX: It would be nice to validate the clocks, but we can't reuse -	 * i830PllIsValid() because it relies on the xf86_config connector -	 * configuration being accurate, which it isn't necessarily. -	 */ - -	return clock.dot; -} - -/** Returns the currently programmed mode of the given pipe. */ -struct drm_display_mode *psb_intel_crtc_mode_get(struct drm_device *dev, -					     struct drm_crtc *crtc) -{ -	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); -	int pipe = psb_intel_crtc->pipe; -	struct drm_display_mode *mode; -	int htot; -	int hsync; -	int vtot; -	int vsync; -	struct drm_psb_private *dev_priv = dev->dev_private; - -	if (gma_power_begin(dev, false)) { -		htot = REG_READ((pipe == 0) ? HTOTAL_A : HTOTAL_B); -		hsync = REG_READ((pipe == 0) ? HSYNC_A : HSYNC_B); -		vtot = REG_READ((pipe == 0) ? VTOTAL_A : VTOTAL_B); -		vsync = REG_READ((pipe == 0) ? VSYNC_A : VSYNC_B); -		gma_power_end(dev); -	} else { -		htot = (pipe == 0) ? -			dev_priv->saveHTOTAL_A : dev_priv->saveHTOTAL_B; -		hsync = (pipe == 0) ? -			dev_priv->saveHSYNC_A : dev_priv->saveHSYNC_B; -		vtot = (pipe == 0) ? -			dev_priv->saveVTOTAL_A : dev_priv->saveVTOTAL_B; -		vsync = (pipe == 0) ? -			dev_priv->saveVSYNC_A : dev_priv->saveVSYNC_B; -	} - -	mode = kzalloc(sizeof(*mode), GFP_KERNEL); -	if (!mode) -		return NULL; - -	mode->clock = psb_intel_crtc_clock_get(dev, crtc); -	mode->hdisplay = (htot & 0xffff) + 1; -	mode->htotal = ((htot & 0xffff0000) >> 16) + 1; -	mode->hsync_start = (hsync & 0xffff) + 1; -	mode->hsync_end = ((hsync & 0xffff0000) >> 16) + 1; -	mode->vdisplay = (vtot & 0xffff) + 1; -	mode->vtotal = ((vtot & 0xffff0000) >> 16) + 1; -	mode->vsync_start = (vsync & 0xffff) + 1; -	mode->vsync_end = ((vsync & 0xffff0000) >> 16) + 1; - -	drm_mode_set_name(mode); -	drm_mode_set_crtcinfo(mode, 0); - -	return mode; -} - -void psb_intel_crtc_destroy(struct drm_crtc *crtc) -{ -	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); -	struct gtt_range *gt; - -	/* Unpin the old GEM object */ -	if (psb_intel_crtc->cursor_obj) { -		gt = container_of(psb_intel_crtc->cursor_obj, -						struct gtt_range, gem); -		psb_gtt_unpin(gt); -		drm_gem_object_unreference(psb_intel_crtc->cursor_obj); -		psb_intel_crtc->cursor_obj = NULL; -	} -	kfree(psb_intel_crtc->crtc_state); -	drm_crtc_cleanup(crtc); -	kfree(psb_intel_crtc); -} - -const struct drm_crtc_helper_funcs psb_intel_helper_funcs = { -	.dpms = psb_intel_crtc_dpms, -	.mode_fixup = psb_intel_crtc_mode_fixup, -	.mode_set = psb_intel_crtc_mode_set, -	.mode_set_base = psb_intel_pipe_set_base, -	.prepare = psb_intel_crtc_prepare, -	.commit = psb_intel_crtc_commit, -}; - -const struct drm_crtc_funcs psb_intel_crtc_funcs = { -	.save = psb_intel_crtc_save, -	.restore = psb_intel_crtc_restore, -	.cursor_set = psb_intel_crtc_cursor_set, -	.cursor_move = psb_intel_crtc_cursor_move, -	.gamma_set = psb_intel_crtc_gamma_set, -	.set_config = psb_crtc_set_config, -	.destroy = psb_intel_crtc_destroy, -}; - -/* - * Set the default value of cursor control and base register - * to zero. This is a workaround for h/w defect on Oaktrail - */ -static void psb_intel_cursor_init(struct drm_device *dev, int pipe) -{ -	u32 control[3] = { CURACNTR, CURBCNTR, CURCCNTR }; -	u32 base[3] = { CURABASE, CURBBASE, CURCBASE }; - -	REG_WRITE(control[pipe], 0); -	REG_WRITE(base[pipe], 0); -} - -void psb_intel_crtc_init(struct drm_device *dev, int pipe, -		     struct psb_intel_mode_device *mode_dev) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; -	struct psb_intel_crtc *psb_intel_crtc; -	int i; -	uint16_t *r_base, *g_base, *b_base; - -	/* We allocate a extra array of drm_connector pointers -	 * for fbdev after the crtc */ -	psb_intel_crtc = -	    kzalloc(sizeof(struct psb_intel_crtc) + -		    (INTELFB_CONN_LIMIT * sizeof(struct drm_connector *)), -		    GFP_KERNEL); -	if (psb_intel_crtc == NULL) -		return; - -	psb_intel_crtc->crtc_state = -		kzalloc(sizeof(struct psb_intel_crtc_state), GFP_KERNEL); -	if (!psb_intel_crtc->crtc_state) { -		dev_err(dev->dev, "Crtc state error: No memory\n"); -		kfree(psb_intel_crtc); -		return; -	} - -	/* Set the CRTC operations from the chip specific data */ -	drm_crtc_init(dev, &psb_intel_crtc->base, dev_priv->ops->crtc_funcs); - -	drm_mode_crtc_set_gamma_size(&psb_intel_crtc->base, 256); -	psb_intel_crtc->pipe = pipe; -	psb_intel_crtc->plane = pipe; - -	r_base = psb_intel_crtc->base.gamma_store; -	g_base = r_base + 256; -	b_base = g_base + 256; -	for (i = 0; i < 256; i++) { -		psb_intel_crtc->lut_r[i] = i; -		psb_intel_crtc->lut_g[i] = i; -		psb_intel_crtc->lut_b[i] = i; -		r_base[i] = i << 8; -		g_base[i] = i << 8; -		b_base[i] = i << 8; - -		psb_intel_crtc->lut_adj[i] = 0; -	} - -	psb_intel_crtc->mode_dev = mode_dev; -	psb_intel_crtc->cursor_addr = 0; - -	drm_crtc_helper_add(&psb_intel_crtc->base, -						dev_priv->ops->crtc_helper); - -	/* Setup the array of drm_connector pointer array */ -	psb_intel_crtc->mode_set.crtc = &psb_intel_crtc->base; -	BUG_ON(pipe >= ARRAY_SIZE(dev_priv->plane_to_crtc_mapping) || -	       dev_priv->plane_to_crtc_mapping[psb_intel_crtc->plane] != NULL); -	dev_priv->plane_to_crtc_mapping[psb_intel_crtc->plane] = -							&psb_intel_crtc->base; -	dev_priv->pipe_to_crtc_mapping[psb_intel_crtc->pipe] = -							&psb_intel_crtc->base; -	psb_intel_crtc->mode_set.connectors = -	    (struct drm_connector **) (psb_intel_crtc + 1); -	psb_intel_crtc->mode_set.num_connectors = 0; -	psb_intel_cursor_init(dev, pipe); -} - -int psb_intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data, -				struct drm_file *file_priv) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; -	struct drm_psb_get_pipe_from_crtc_id_arg *pipe_from_crtc_id = data; -	struct drm_mode_object *drmmode_obj; -	struct psb_intel_crtc *crtc; - -	if (!dev_priv) { -		dev_err(dev->dev, "called with no initialization\n"); -		return -EINVAL; -	} - -	drmmode_obj = drm_mode_object_find(dev, pipe_from_crtc_id->crtc_id, -			DRM_MODE_OBJECT_CRTC); - -	if (!drmmode_obj) { -		dev_err(dev->dev, "no such CRTC id\n"); -		return -EINVAL; -	} - -	crtc = to_psb_intel_crtc(obj_to_crtc(drmmode_obj)); -	pipe_from_crtc_id->pipe = crtc->pipe; - -	return 0; -} - -struct drm_crtc *psb_intel_get_crtc_from_pipe(struct drm_device *dev, int pipe) -{ -	struct drm_crtc *crtc = NULL; - -	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { -		struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); -		if (psb_intel_crtc->pipe == pipe) -			break; -	} -	return crtc; -} - -int psb_intel_connector_clones(struct drm_device *dev, int type_mask) -{ -	int index_mask = 0; -	struct drm_connector *connector; -	int entry = 0; - -	list_for_each_entry(connector, &dev->mode_config.connector_list, -			    head) { -		struct psb_intel_output *psb_intel_output = -		    to_psb_intel_output(connector); -		if (type_mask & (1 << psb_intel_output->type)) -			index_mask |= (1 << entry); -		entry++; -	} -	return index_mask; -} - - -void psb_intel_modeset_cleanup(struct drm_device *dev) -{ -	drm_mode_config_cleanup(dev); -} - - -/* current intel driver doesn't take advantage of encoders -   always give back the encoder for the connector -*/ -struct drm_encoder *psb_intel_best_encoder(struct drm_connector *connector) -{ -	struct psb_intel_output *psb_intel_output = -					to_psb_intel_output(connector); - -	return &psb_intel_output->enc; -} - diff --git a/drivers/staging/gma500/psb_intel_display.h b/drivers/staging/gma500/psb_intel_display.h deleted file mode 100644 index 535b49a5e40..00000000000 --- a/drivers/staging/gma500/psb_intel_display.h +++ /dev/null @@ -1,28 +0,0 @@ -/* copyright (c) 2008, Intel Corporation - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - * Authors: - * Eric Anholt <eric@anholt.net> - */ - -#ifndef _INTEL_DISPLAY_H_ -#define _INTEL_DISPLAY_H_ - -bool psb_intel_pipe_has_type(struct drm_crtc *crtc, int type); -void psb_intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, -			 u16 *green, u16 *blue, uint32_t type, uint32_t size); -void psb_intel_crtc_destroy(struct drm_crtc *crtc); - -#endif diff --git a/drivers/staging/gma500/psb_intel_drv.h b/drivers/staging/gma500/psb_intel_drv.h deleted file mode 100644 index 36b554b5c33..00000000000 --- a/drivers/staging/gma500/psb_intel_drv.h +++ /dev/null @@ -1,230 +0,0 @@ -/* - * Copyright (c) 2009-2011, Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#ifndef __INTEL_DRV_H__ -#define __INTEL_DRV_H__ - -#include <linux/i2c.h> -#include <linux/i2c-algo-bit.h> -#include <drm/drm_crtc.h> -#include <drm/drm_crtc_helper.h> -#include <linux/gpio.h> - -/* - * Display related stuff - */ - -/* store information about an Ixxx DVO */ -/* The i830->i865 use multiple DVOs with multiple i2cs */ -/* the i915, i945 have a single sDVO i2c bus - which is different */ -#define MAX_OUTPUTS 6 -/* maximum connectors per crtcs in the mode set */ -#define INTELFB_CONN_LIMIT 4 - -#define INTEL_I2C_BUS_DVO 1 -#define INTEL_I2C_BUS_SDVO 2 - -/* these are outputs from the chip - integrated only - * external chips are via DVO or SDVO output */ -#define INTEL_OUTPUT_UNUSED 0 -#define INTEL_OUTPUT_ANALOG 1 -#define INTEL_OUTPUT_DVO 2 -#define INTEL_OUTPUT_SDVO 3 -#define INTEL_OUTPUT_LVDS 4 -#define INTEL_OUTPUT_TVOUT 5 -#define INTEL_OUTPUT_HDMI 6 -#define INTEL_OUTPUT_MIPI 7 -#define INTEL_OUTPUT_MIPI2 8 - -#define INTEL_DVO_CHIP_NONE 0 -#define INTEL_DVO_CHIP_LVDS 1 -#define INTEL_DVO_CHIP_TMDS 2 -#define INTEL_DVO_CHIP_TVOUT 4 - -/* - * Hold information useally put on the device driver privates here, - * since it needs to be shared across multiple of devices drivers privates. - */ -struct psb_intel_mode_device { - -	/* -	 * Abstracted memory manager operations -	 */ -	 size_t(*bo_offset) (struct drm_device *dev, void *bo); - -	/* -	 * Cursor (Can go ?) -	 */ -	int cursor_needs_physical; - -	/* -	 * LVDS info -	 */ -	int backlight_duty_cycle;	/* restore backlight to this value */ -	bool panel_wants_dither; -	struct drm_display_mode *panel_fixed_mode; -	struct drm_display_mode *panel_fixed_mode2; -	struct drm_display_mode *vbt_mode;	/* if any */ - -	uint32_t saveBLC_PWM_CTL; -}; - -struct psb_intel_i2c_chan { -	/* for getting at dev. private (mmio etc.) */ -	struct drm_device *drm_dev; -	u32 reg;		/* GPIO reg */ -	struct i2c_adapter adapter; -	struct i2c_algo_bit_data algo; -	u8 slave_addr; -}; - -struct psb_intel_output { -	struct drm_connector base; - -	struct drm_encoder enc; -	int type; - -	struct psb_intel_i2c_chan *i2c_bus;	/* for control functions */ -	struct psb_intel_i2c_chan *ddc_bus;	/* for DDC only stuff */ -	bool load_detect_temp; -	void *dev_priv; - -	struct psb_intel_mode_device *mode_dev; -	struct i2c_adapter *hdmi_i2c_adapter;	/* for control functions */ -}; - -struct psb_intel_crtc_state { -	uint32_t saveDSPCNTR; -	uint32_t savePIPECONF; -	uint32_t savePIPESRC; -	uint32_t saveDPLL; -	uint32_t saveFP0; -	uint32_t saveFP1; -	uint32_t saveHTOTAL; -	uint32_t saveHBLANK; -	uint32_t saveHSYNC; -	uint32_t saveVTOTAL; -	uint32_t saveVBLANK; -	uint32_t saveVSYNC; -	uint32_t saveDSPSTRIDE; -	uint32_t saveDSPSIZE; -	uint32_t saveDSPPOS; -	uint32_t saveDSPBASE; -	uint32_t savePalette[256]; -}; - -struct psb_intel_crtc { -	struct drm_crtc base; -	int pipe; -	int plane; -	uint32_t cursor_addr; -	u8 lut_r[256], lut_g[256], lut_b[256]; -	u8 lut_adj[256]; -	struct psb_intel_framebuffer *fbdev_fb; -	/* a mode_set for fbdev users on this crtc */ -	struct drm_mode_set mode_set; - -	/* GEM object that holds our cursor */ -	struct drm_gem_object *cursor_obj; - -	struct drm_display_mode saved_mode; -	struct drm_display_mode saved_adjusted_mode; - -	struct psb_intel_mode_device *mode_dev; - -	/*crtc mode setting flags*/ -	u32 mode_flags; - -	/* Saved Crtc HW states */ -	struct psb_intel_crtc_state *crtc_state; -}; - -#define to_psb_intel_crtc(x)	\ -		container_of(x, struct psb_intel_crtc, base) -#define to_psb_intel_output(x)	\ -		container_of(x, struct psb_intel_output, base) -#define enc_to_psb_intel_output(x)	\ -		container_of(x, struct psb_intel_output, enc) -#define to_psb_intel_framebuffer(x)	\ -		container_of(x, struct psb_intel_framebuffer, base) - -struct psb_intel_i2c_chan *psb_intel_i2c_create(struct drm_device *dev, -					const u32 reg, const char *name); -void psb_intel_i2c_destroy(struct psb_intel_i2c_chan *chan); -int psb_intel_ddc_get_modes(struct psb_intel_output *psb_intel_output); -extern bool psb_intel_ddc_probe(struct psb_intel_output *psb_intel_output); - -extern void psb_intel_crtc_init(struct drm_device *dev, int pipe, -			    struct psb_intel_mode_device *mode_dev); -extern void psb_intel_crt_init(struct drm_device *dev); -extern void psb_intel_sdvo_init(struct drm_device *dev, int output_device); -extern void psb_intel_dvo_init(struct drm_device *dev); -extern void psb_intel_tv_init(struct drm_device *dev); -extern void psb_intel_lvds_init(struct drm_device *dev, -			    struct psb_intel_mode_device *mode_dev); -extern void psb_intel_lvds_set_brightness(struct drm_device *dev, int level); -extern void mrst_lvds_init(struct drm_device *dev, -			   struct psb_intel_mode_device *mode_dev); -extern void mrst_wait_for_INTR_PKT_SENT(struct drm_device *dev); -extern void mrst_dsi_init(struct drm_device *dev, -			   struct psb_intel_mode_device *mode_dev); -extern void mid_dsi_init(struct drm_device *dev, -		    struct psb_intel_mode_device *mode_dev, int dsi_num); - -extern void psb_intel_crtc_load_lut(struct drm_crtc *crtc); -extern void psb_intel_encoder_prepare(struct drm_encoder *encoder); -extern void psb_intel_encoder_commit(struct drm_encoder *encoder); - -extern struct drm_encoder *psb_intel_best_encoder(struct drm_connector -					      *connector); - -extern struct drm_display_mode *psb_intel_crtc_mode_get(struct drm_device *dev, -						    struct drm_crtc *crtc); -extern void psb_intel_wait_for_vblank(struct drm_device *dev); -extern int psb_intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data, -				struct drm_file *file_priv); -extern struct drm_crtc *psb_intel_get_crtc_from_pipe(struct drm_device *dev, -						 int pipe); -extern struct drm_connector *psb_intel_sdvo_find(struct drm_device *dev, -					     int sdvoB); -extern int psb_intel_sdvo_supports_hotplug(struct drm_connector *connector); -extern void psb_intel_sdvo_set_hotplug(struct drm_connector *connector, -				   int enable); -extern int intelfb_probe(struct drm_device *dev); -extern int intelfb_remove(struct drm_device *dev, -			  struct drm_framebuffer *fb); -extern struct drm_framebuffer *psb_intel_framebuffer_create(struct drm_device -							*dev, struct -							drm_mode_fb_cmd -							*mode_cmd, -							void *mm_private); -extern bool psb_intel_lvds_mode_fixup(struct drm_encoder *encoder, -				      struct drm_display_mode *mode, -				      struct drm_display_mode *adjusted_mode); -extern int psb_intel_lvds_mode_valid(struct drm_connector *connector, -				     struct drm_display_mode *mode); -extern int psb_intel_lvds_set_property(struct drm_connector *connector, -					struct drm_property *property, -					uint64_t value); -extern void psb_intel_lvds_destroy(struct drm_connector *connector); -extern const struct drm_encoder_funcs psb_intel_lvds_enc_funcs; - -extern void mdfldWaitForPipeDisable(struct drm_device *dev, int pipe); -extern void mdfldWaitForPipeEnable(struct drm_device *dev, int pipe); - -#endif				/* __INTEL_DRV_H__ */ diff --git a/drivers/staging/gma500/psb_intel_lvds.c b/drivers/staging/gma500/psb_intel_lvds.c deleted file mode 100644 index 21022e1a977..00000000000 --- a/drivers/staging/gma500/psb_intel_lvds.c +++ /dev/null @@ -1,854 +0,0 @@ -/* - * Copyright © 2006-2007 Intel Corporation - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - * Authors: - *	Eric Anholt <eric@anholt.net> - *	Dave Airlie <airlied@linux.ie> - *	Jesse Barnes <jesse.barnes@intel.com> - */ - -#include <linux/i2c.h> -#include <drm/drmP.h> - -#include "intel_bios.h" -#include "psb_drv.h" -#include "psb_intel_drv.h" -#include "psb_intel_reg.h" -#include "power.h" -#include <linux/pm_runtime.h> - -/* - * LVDS I2C backlight control macros - */ -#define BRIGHTNESS_MAX_LEVEL 100 -#define BRIGHTNESS_MASK 0xFF -#define BLC_I2C_TYPE	0x01 -#define BLC_PWM_TYPT	0x02 - -#define BLC_POLARITY_NORMAL 0 -#define BLC_POLARITY_INVERSE 1 - -#define PSB_BLC_MAX_PWM_REG_FREQ       (0xFFFE) -#define PSB_BLC_MIN_PWM_REG_FREQ	(0x2) -#define PSB_BLC_PWM_PRECISION_FACTOR	(10) -#define PSB_BACKLIGHT_PWM_CTL_SHIFT	(16) -#define PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR (0xFFFE) - -struct psb_intel_lvds_priv { -	/* -	 * Saved LVDO output states -	 */ -	uint32_t savePP_ON; -	uint32_t savePP_OFF; -	uint32_t saveLVDS; -	uint32_t savePP_CONTROL; -	uint32_t savePP_CYCLE; -	uint32_t savePFIT_CONTROL; -	uint32_t savePFIT_PGM_RATIOS; -	uint32_t saveBLC_PWM_CTL; -}; - - -/* - * Returns the maximum level of the backlight duty cycle field. - */ -static u32 psb_intel_lvds_get_max_backlight(struct drm_device *dev) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; -	u32 ret; - -	if (gma_power_begin(dev, false)) { -		ret = REG_READ(BLC_PWM_CTL); -		gma_power_end(dev); -	} else /* Powered off, use the saved value */ -		ret = dev_priv->saveBLC_PWM_CTL; - -	/* Top 15bits hold the frequency mask */ -	ret = (ret &  BACKLIGHT_MODULATION_FREQ_MASK) >> -					BACKLIGHT_MODULATION_FREQ_SHIFT; - -        ret *= 2;	/* Return a 16bit range as needed for setting */ -        if (ret == 0) -                dev_err(dev->dev, "BL bug: Reg %08x save %08X\n", -                        REG_READ(BLC_PWM_CTL), dev_priv->saveBLC_PWM_CTL); -	return ret; -} - -/* - * Set LVDS backlight level by I2C command - * - * FIXME: at some point we need to both track this for PM and also - * disable runtime pm on MRST if the brightness is nil (ie blanked) - */ -static int psb_lvds_i2c_set_brightness(struct drm_device *dev, -					unsigned int level) -{ -	struct drm_psb_private *dev_priv = -		(struct drm_psb_private *)dev->dev_private; - -	struct psb_intel_i2c_chan *lvds_i2c_bus = dev_priv->lvds_i2c_bus; -	u8 out_buf[2]; -	unsigned int blc_i2c_brightness; - -	struct i2c_msg msgs[] = { -		{ -			.addr = lvds_i2c_bus->slave_addr, -			.flags = 0, -			.len = 2, -			.buf = out_buf, -		} -	}; - -	blc_i2c_brightness = BRIGHTNESS_MASK & ((unsigned int)level * -			     BRIGHTNESS_MASK / -			     BRIGHTNESS_MAX_LEVEL); - -	if (dev_priv->lvds_bl->pol == BLC_POLARITY_INVERSE) -		blc_i2c_brightness = BRIGHTNESS_MASK - blc_i2c_brightness; - -	out_buf[0] = dev_priv->lvds_bl->brightnesscmd; -	out_buf[1] = (u8)blc_i2c_brightness; - -	if (i2c_transfer(&lvds_i2c_bus->adapter, msgs, 1) == 1) { -		dev_dbg(dev->dev, "I2C set brightness.(command, value) (%d, %d)\n", -			dev_priv->lvds_bl->brightnesscmd, -			blc_i2c_brightness); -		return 0; -	} - -	dev_err(dev->dev, "I2C transfer error\n"); -	return -1; -} - - -static int psb_lvds_pwm_set_brightness(struct drm_device *dev, int level) -{ -	struct drm_psb_private *dev_priv = -			(struct drm_psb_private *)dev->dev_private; - -	u32 max_pwm_blc; -	u32 blc_pwm_duty_cycle; - -	max_pwm_blc = psb_intel_lvds_get_max_backlight(dev); - -	/*BLC_PWM_CTL Should be initiated while backlight device init*/ -	BUG_ON(max_pwm_blc == 0); - -	blc_pwm_duty_cycle = level * max_pwm_blc / BRIGHTNESS_MAX_LEVEL; - -	if (dev_priv->lvds_bl->pol == BLC_POLARITY_INVERSE) -		blc_pwm_duty_cycle = max_pwm_blc - blc_pwm_duty_cycle; - -	blc_pwm_duty_cycle &= PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR; -	REG_WRITE(BLC_PWM_CTL, -		  (max_pwm_blc << PSB_BACKLIGHT_PWM_CTL_SHIFT) | -		  (blc_pwm_duty_cycle)); - -        dev_info(dev->dev, "Backlight lvds set brightness %08x\n", -		  (max_pwm_blc << PSB_BACKLIGHT_PWM_CTL_SHIFT) | -		  (blc_pwm_duty_cycle)); - -	return 0; -} - -/* - * Set LVDS backlight level either by I2C or PWM - */ -void psb_intel_lvds_set_brightness(struct drm_device *dev, int level) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; - -	dev_dbg(dev->dev, "backlight level is %d\n", level); - -	if (!dev_priv->lvds_bl) { -		dev_err(dev->dev, "NO LVDS backlight info\n"); -		return; -	} - -	if (dev_priv->lvds_bl->type == BLC_I2C_TYPE) -		psb_lvds_i2c_set_brightness(dev, level); -	else -		psb_lvds_pwm_set_brightness(dev, level); -} - -/* - * Sets the backlight level. - * - * level: backlight level, from 0 to psb_intel_lvds_get_max_backlight(). - */ -static void psb_intel_lvds_set_backlight(struct drm_device *dev, int level) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; -	u32 blc_pwm_ctl; - -	if (gma_power_begin(dev, false)) { -		blc_pwm_ctl = REG_READ(BLC_PWM_CTL); -		blc_pwm_ctl &= ~BACKLIGHT_DUTY_CYCLE_MASK; -		REG_WRITE(BLC_PWM_CTL, -				(blc_pwm_ctl | -				(level << BACKLIGHT_DUTY_CYCLE_SHIFT))); -		dev_priv->saveBLC_PWM_CTL = (blc_pwm_ctl | -					(level << BACKLIGHT_DUTY_CYCLE_SHIFT)); -		gma_power_end(dev); -	} else { -		blc_pwm_ctl = dev_priv->saveBLC_PWM_CTL & -				~BACKLIGHT_DUTY_CYCLE_MASK; -		dev_priv->saveBLC_PWM_CTL = (blc_pwm_ctl | -					(level << BACKLIGHT_DUTY_CYCLE_SHIFT)); -	} -} - -/* - * Sets the power state for the panel. - */ -static void psb_intel_lvds_set_power(struct drm_device *dev, -				 struct psb_intel_output *output, bool on) -{ -	u32 pp_status; - -	if (!gma_power_begin(dev, true)) { -	        dev_err(dev->dev, "set power, chip off!\n"); -		return; -        } -         -	if (on) { -		REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) | -			  POWER_TARGET_ON); -		do { -			pp_status = REG_READ(PP_STATUS); -		} while ((pp_status & PP_ON) == 0); - -		psb_intel_lvds_set_backlight(dev, -					 output-> -					 mode_dev->backlight_duty_cycle); -	} else { -		psb_intel_lvds_set_backlight(dev, 0); - -		REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) & -			  ~POWER_TARGET_ON); -		do { -			pp_status = REG_READ(PP_STATUS); -		} while (pp_status & PP_ON); -	} - -	gma_power_end(dev); -} - -static void psb_intel_lvds_encoder_dpms(struct drm_encoder *encoder, int mode) -{ -	struct drm_device *dev = encoder->dev; -	struct psb_intel_output *output = enc_to_psb_intel_output(encoder); - -	if (mode == DRM_MODE_DPMS_ON) -		psb_intel_lvds_set_power(dev, output, true); -	else -		psb_intel_lvds_set_power(dev, output, false); - -	/* XXX: We never power down the LVDS pairs. */ -} - -static void psb_intel_lvds_save(struct drm_connector *connector) -{ -	struct drm_device *dev = connector->dev; -	struct drm_psb_private *dev_priv = -		(struct drm_psb_private *)dev->dev_private; -	struct psb_intel_output *psb_intel_output = -		to_psb_intel_output(connector); -	struct psb_intel_lvds_priv *lvds_priv = -		(struct psb_intel_lvds_priv *)psb_intel_output->dev_priv; - -	lvds_priv->savePP_ON = REG_READ(LVDSPP_ON); -	lvds_priv->savePP_OFF = REG_READ(LVDSPP_OFF); -	lvds_priv->saveLVDS = REG_READ(LVDS); -	lvds_priv->savePP_CONTROL = REG_READ(PP_CONTROL); -	lvds_priv->savePP_CYCLE = REG_READ(PP_CYCLE); -	/*lvds_priv->savePP_DIVISOR = REG_READ(PP_DIVISOR);*/ -	lvds_priv->saveBLC_PWM_CTL = REG_READ(BLC_PWM_CTL); -	lvds_priv->savePFIT_CONTROL = REG_READ(PFIT_CONTROL); -	lvds_priv->savePFIT_PGM_RATIOS = REG_READ(PFIT_PGM_RATIOS); - -	/*TODO: move backlight_duty_cycle to psb_intel_lvds_priv*/ -	dev_priv->backlight_duty_cycle = (dev_priv->saveBLC_PWM_CTL & -						BACKLIGHT_DUTY_CYCLE_MASK); - -	/* -	 * If the light is off at server startup, -	 * just make it full brightness -	 */ -	if (dev_priv->backlight_duty_cycle == 0) -		dev_priv->backlight_duty_cycle = -		psb_intel_lvds_get_max_backlight(dev); - -	dev_dbg(dev->dev, "(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n", -			lvds_priv->savePP_ON, -			lvds_priv->savePP_OFF, -			lvds_priv->saveLVDS, -			lvds_priv->savePP_CONTROL, -			lvds_priv->savePP_CYCLE, -			lvds_priv->saveBLC_PWM_CTL); -} - -static void psb_intel_lvds_restore(struct drm_connector *connector) -{ -	struct drm_device *dev = connector->dev; -	u32 pp_status; -	struct psb_intel_output *psb_intel_output = -					to_psb_intel_output(connector); -	struct psb_intel_lvds_priv *lvds_priv = -		(struct psb_intel_lvds_priv *)psb_intel_output->dev_priv; - -	dev_dbg(dev->dev, "(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n", -			lvds_priv->savePP_ON, -			lvds_priv->savePP_OFF, -			lvds_priv->saveLVDS, -			lvds_priv->savePP_CONTROL, -			lvds_priv->savePP_CYCLE, -			lvds_priv->saveBLC_PWM_CTL); - -	REG_WRITE(BLC_PWM_CTL, lvds_priv->saveBLC_PWM_CTL); -	REG_WRITE(PFIT_CONTROL, lvds_priv->savePFIT_CONTROL); -	REG_WRITE(PFIT_PGM_RATIOS, lvds_priv->savePFIT_PGM_RATIOS); -	REG_WRITE(LVDSPP_ON, lvds_priv->savePP_ON); -	REG_WRITE(LVDSPP_OFF, lvds_priv->savePP_OFF); -	/*REG_WRITE(PP_DIVISOR, lvds_priv->savePP_DIVISOR);*/ -	REG_WRITE(PP_CYCLE, lvds_priv->savePP_CYCLE); -	REG_WRITE(PP_CONTROL, lvds_priv->savePP_CONTROL); -	REG_WRITE(LVDS, lvds_priv->saveLVDS); - -	if (lvds_priv->savePP_CONTROL & POWER_TARGET_ON) { -		REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) | -			POWER_TARGET_ON); -		do { -			pp_status = REG_READ(PP_STATUS); -		} while ((pp_status & PP_ON) == 0); -	} else { -		REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) & -			~POWER_TARGET_ON); -		do { -			pp_status = REG_READ(PP_STATUS); -		} while (pp_status & PP_ON); -	} -} - -int psb_intel_lvds_mode_valid(struct drm_connector *connector, -				 struct drm_display_mode *mode) -{ -	struct psb_intel_output *psb_intel_output = -				to_psb_intel_output(connector); -	struct drm_display_mode *fixed_mode = -	    psb_intel_output->mode_dev->panel_fixed_mode; - -	if (psb_intel_output->type == INTEL_OUTPUT_MIPI2) -		fixed_mode = psb_intel_output->mode_dev->panel_fixed_mode2; - -	/* just in case */ -	if (mode->flags & DRM_MODE_FLAG_DBLSCAN) -		return MODE_NO_DBLESCAN; - -	/* just in case */ -	if (mode->flags & DRM_MODE_FLAG_INTERLACE) -		return MODE_NO_INTERLACE; - -	if (fixed_mode) { -		if (mode->hdisplay > fixed_mode->hdisplay) -			return MODE_PANEL; -		if (mode->vdisplay > fixed_mode->vdisplay) -			return MODE_PANEL; -	} -	return MODE_OK; -} - -bool psb_intel_lvds_mode_fixup(struct drm_encoder *encoder, -				  struct drm_display_mode *mode, -				  struct drm_display_mode *adjusted_mode) -{ -	struct psb_intel_mode_device *mode_dev = -	    enc_to_psb_intel_output(encoder)->mode_dev; -	struct drm_device *dev = encoder->dev; -	struct psb_intel_crtc *psb_intel_crtc = -				to_psb_intel_crtc(encoder->crtc); -	struct drm_encoder *tmp_encoder; -	struct drm_display_mode *panel_fixed_mode = mode_dev->panel_fixed_mode; -	struct psb_intel_output *psb_intel_output = -					enc_to_psb_intel_output(encoder); - -	if (psb_intel_output->type == INTEL_OUTPUT_MIPI2) -		panel_fixed_mode = mode_dev->panel_fixed_mode2; - -	/* PSB requires the LVDS is on pipe B, MRST has only one pipe anyway */ -	if (!IS_MRST(dev) && psb_intel_crtc->pipe == 0) { -		printk(KERN_ERR "Can't support LVDS on pipe A\n"); -		return false; -	} -	if (IS_MRST(dev) && psb_intel_crtc->pipe != 0) { -		printk(KERN_ERR "Must use PIPE A\n"); -		return false; -	} -	/* Should never happen!! */ -	list_for_each_entry(tmp_encoder, &dev->mode_config.encoder_list, -			    head) { -		if (tmp_encoder != encoder -		    && tmp_encoder->crtc == encoder->crtc) { -			printk(KERN_ERR "Can't enable LVDS and another " -			       "encoder on the same pipe\n"); -			return false; -		} -	} - -	/* -	 * If we have timings from the BIOS for the panel, put them in -	 * to the adjusted mode.  The CRTC will be set up for this mode, -	 * with the panel scaling set up to source from the H/VDisplay -	 * of the original mode. -	 */ -	if (panel_fixed_mode != NULL) { -		adjusted_mode->hdisplay = panel_fixed_mode->hdisplay; -		adjusted_mode->hsync_start = panel_fixed_mode->hsync_start; -		adjusted_mode->hsync_end = panel_fixed_mode->hsync_end; -		adjusted_mode->htotal = panel_fixed_mode->htotal; -		adjusted_mode->vdisplay = panel_fixed_mode->vdisplay; -		adjusted_mode->vsync_start = panel_fixed_mode->vsync_start; -		adjusted_mode->vsync_end = panel_fixed_mode->vsync_end; -		adjusted_mode->vtotal = panel_fixed_mode->vtotal; -		adjusted_mode->clock = panel_fixed_mode->clock; -		drm_mode_set_crtcinfo(adjusted_mode, -				      CRTC_INTERLACE_HALVE_V); -	} - -	/* -	 * XXX: It would be nice to support lower refresh rates on the -	 * panels to reduce power consumption, and perhaps match the -	 * user's requested refresh rate. -	 */ - -	return true; -} - -static void psb_intel_lvds_prepare(struct drm_encoder *encoder) -{ -	struct drm_device *dev = encoder->dev; -	struct psb_intel_output *output = enc_to_psb_intel_output(encoder); -	struct psb_intel_mode_device *mode_dev = output->mode_dev; - -	if (!gma_power_begin(dev, true)) -		return; - -	mode_dev->saveBLC_PWM_CTL = REG_READ(BLC_PWM_CTL); -	mode_dev->backlight_duty_cycle = (mode_dev->saveBLC_PWM_CTL & -					  BACKLIGHT_DUTY_CYCLE_MASK); - -	psb_intel_lvds_set_power(dev, output, false); - -	gma_power_end(dev); -} - -static void psb_intel_lvds_commit(struct drm_encoder *encoder) -{ -	struct drm_device *dev = encoder->dev; -	struct psb_intel_output *output = enc_to_psb_intel_output(encoder); -	struct psb_intel_mode_device *mode_dev = output->mode_dev; - -	if (mode_dev->backlight_duty_cycle == 0) -		mode_dev->backlight_duty_cycle = -		    psb_intel_lvds_get_max_backlight(dev); - -	psb_intel_lvds_set_power(dev, output, true); -} - -static void psb_intel_lvds_mode_set(struct drm_encoder *encoder, -				struct drm_display_mode *mode, -				struct drm_display_mode *adjusted_mode) -{ -	struct drm_device *dev = encoder->dev; -	struct drm_psb_private *dev_priv = dev->dev_private; -	u32 pfit_control; - -	/* -	 * The LVDS pin pair will already have been turned on in the -	 * psb_intel_crtc_mode_set since it has a large impact on the DPLL -	 * settings. -	 */ - -	/* -	 * Enable automatic panel scaling so that non-native modes fill the -	 * screen.  Should be enabled before the pipe is enabled, according to -	 * register description and PRM. -	 */ -	if (mode->hdisplay != adjusted_mode->hdisplay || -	    mode->vdisplay != adjusted_mode->vdisplay) -		pfit_control = (PFIT_ENABLE | VERT_AUTO_SCALE | -				HORIZ_AUTO_SCALE | VERT_INTERP_BILINEAR | -				HORIZ_INTERP_BILINEAR); -	else -		pfit_control = 0; - -	if (dev_priv->lvds_dither) -		pfit_control |= PANEL_8TO6_DITHER_ENABLE; - -	REG_WRITE(PFIT_CONTROL, pfit_control); -} - -/* - * Detect the LVDS connection. - * - * This always returns CONNECTOR_STATUS_CONNECTED. - * This connector should only have - * been set up if the LVDS was actually connected anyway. - */ -static enum drm_connector_status psb_intel_lvds_detect(struct drm_connector -						   *connector, bool force) -{ -	return connector_status_connected; -} - -/* - * Return the list of DDC modes if available, or the BIOS fixed mode otherwise. - */ -static int psb_intel_lvds_get_modes(struct drm_connector *connector) -{ -	struct drm_device *dev = connector->dev; -	struct psb_intel_output *psb_intel_output = -					to_psb_intel_output(connector); -	struct psb_intel_mode_device *mode_dev = -					psb_intel_output->mode_dev; -	int ret = 0; - -	if (!IS_MRST(dev)) -		ret = psb_intel_ddc_get_modes(psb_intel_output); - -	if (ret) -		return ret; - -	/* Didn't get an EDID, so -	 * Set wide sync ranges so we get all modes -	 * handed to valid_mode for checking -	 */ -	connector->display_info.min_vfreq = 0; -	connector->display_info.max_vfreq = 200; -	connector->display_info.min_hfreq = 0; -	connector->display_info.max_hfreq = 200; - -	if (mode_dev->panel_fixed_mode != NULL) { -		struct drm_display_mode *mode = -		    drm_mode_duplicate(dev, mode_dev->panel_fixed_mode); -		drm_mode_probed_add(connector, mode); -		return 1; -	} - -	return 0; -} - -/** - * psb_intel_lvds_destroy - unregister and free LVDS structures - * @connector: connector to free - * - * Unregister the DDC bus for this connector then free the driver private - * structure. - */ -void psb_intel_lvds_destroy(struct drm_connector *connector) -{ -	struct psb_intel_output *psb_intel_output = -					to_psb_intel_output(connector); - -	if (psb_intel_output->ddc_bus) -		psb_intel_i2c_destroy(psb_intel_output->ddc_bus); -	drm_sysfs_connector_remove(connector); -	drm_connector_cleanup(connector); -	kfree(connector); -} - -int psb_intel_lvds_set_property(struct drm_connector *connector, -				       struct drm_property *property, -				       uint64_t value) -{ -	struct drm_encoder *encoder = connector->encoder; - -	if (!encoder) -		return -1; - -	if (!strcmp(property->name, "scaling mode")) { -		struct psb_intel_crtc *crtc = -					to_psb_intel_crtc(encoder->crtc); -		uint64_t curval; - -		if (!crtc) -			goto set_prop_error; - -		switch (value) { -		case DRM_MODE_SCALE_FULLSCREEN: -			break; -		case DRM_MODE_SCALE_NO_SCALE: -			break; -		case DRM_MODE_SCALE_ASPECT: -			break; -		default: -			goto set_prop_error; -		} - -		if (drm_connector_property_get_value(connector, -						     property, -						     &curval)) -			goto set_prop_error; - -		if (curval == value) -			goto set_prop_done; - -		if (drm_connector_property_set_value(connector, -							property, -							value)) -			goto set_prop_error; - -		if (crtc->saved_mode.hdisplay != 0 && -		    crtc->saved_mode.vdisplay != 0) { -			if (!drm_crtc_helper_set_mode(encoder->crtc, -						      &crtc->saved_mode, -						      encoder->crtc->x, -						      encoder->crtc->y, -						      encoder->crtc->fb)) -				goto set_prop_error; -		} -	} else if (!strcmp(property->name, "backlight")) { -		if (drm_connector_property_set_value(connector, -							property, -							value)) -			goto set_prop_error; -		else { -#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE -			struct drm_psb_private *devp = -						encoder->dev->dev_private; -			struct backlight_device *bd = devp->backlight_device; -			if (bd) { -				bd->props.brightness = value; -				backlight_update_status(bd); -			} -#endif -		} -	} else if (!strcmp(property->name, "DPMS")) { -		struct drm_encoder_helper_funcs *hfuncs -						= encoder->helper_private; -		hfuncs->dpms(encoder, value); -	} - -set_prop_done: -	return 0; -set_prop_error: -	return -1; -} - -static const struct drm_encoder_helper_funcs psb_intel_lvds_helper_funcs = { -	.dpms = psb_intel_lvds_encoder_dpms, -	.mode_fixup = psb_intel_lvds_mode_fixup, -	.prepare = psb_intel_lvds_prepare, -	.mode_set = psb_intel_lvds_mode_set, -	.commit = psb_intel_lvds_commit, -}; - -const struct drm_connector_helper_funcs -				psb_intel_lvds_connector_helper_funcs = { -	.get_modes = psb_intel_lvds_get_modes, -	.mode_valid = psb_intel_lvds_mode_valid, -	.best_encoder = psb_intel_best_encoder, -}; - -const struct drm_connector_funcs psb_intel_lvds_connector_funcs = { -	.dpms = drm_helper_connector_dpms, -	.save = psb_intel_lvds_save, -	.restore = psb_intel_lvds_restore, -	.detect = psb_intel_lvds_detect, -	.fill_modes = drm_helper_probe_single_connector_modes, -	.set_property = psb_intel_lvds_set_property, -	.destroy = psb_intel_lvds_destroy, -}; - - -static void psb_intel_lvds_enc_destroy(struct drm_encoder *encoder) -{ -	drm_encoder_cleanup(encoder); -} - -const struct drm_encoder_funcs psb_intel_lvds_enc_funcs = { -	.destroy = psb_intel_lvds_enc_destroy, -}; - - - -/** - * psb_intel_lvds_init - setup LVDS connectors on this device - * @dev: drm device - * - * Create the connector, register the LVDS DDC bus, and try to figure out what - * modes we can display on the LVDS panel (if present). - */ -void psb_intel_lvds_init(struct drm_device *dev, -		     struct psb_intel_mode_device *mode_dev) -{ -	struct psb_intel_output *psb_intel_output; -	struct psb_intel_lvds_priv *lvds_priv; -	struct drm_connector *connector; -	struct drm_encoder *encoder; -	struct drm_display_mode *scan;	/* *modes, *bios_mode; */ -	struct drm_crtc *crtc; -	struct drm_psb_private *dev_priv = dev->dev_private; -	u32 lvds; -	int pipe; - -	psb_intel_output = kzalloc(sizeof(struct psb_intel_output), GFP_KERNEL); -	if (!psb_intel_output) -		return; - -	lvds_priv = kzalloc(sizeof(struct psb_intel_lvds_priv), GFP_KERNEL); -	if (!lvds_priv) { -		kfree(psb_intel_output); -		dev_err(dev->dev, "LVDS private allocation error\n"); -		return; -	} - -	psb_intel_output->dev_priv = lvds_priv; -	psb_intel_output->mode_dev = mode_dev; - -	connector = &psb_intel_output->base; -	encoder = &psb_intel_output->enc; -	drm_connector_init(dev, &psb_intel_output->base, -			   &psb_intel_lvds_connector_funcs, -			   DRM_MODE_CONNECTOR_LVDS); - -	drm_encoder_init(dev, &psb_intel_output->enc, -			 &psb_intel_lvds_enc_funcs, -			 DRM_MODE_ENCODER_LVDS); - -	drm_mode_connector_attach_encoder(&psb_intel_output->base, -					  &psb_intel_output->enc); -	psb_intel_output->type = INTEL_OUTPUT_LVDS; - -	drm_encoder_helper_add(encoder, &psb_intel_lvds_helper_funcs); -	drm_connector_helper_add(connector, -				 &psb_intel_lvds_connector_helper_funcs); -	connector->display_info.subpixel_order = SubPixelHorizontalRGB; -	connector->interlace_allowed = false; -	connector->doublescan_allowed = false; - -	/*Attach connector properties*/ -	drm_connector_attach_property(connector, -				      dev->mode_config.scaling_mode_property, -				      DRM_MODE_SCALE_FULLSCREEN); -	drm_connector_attach_property(connector, -				      dev_priv->backlight_property, -				      BRIGHTNESS_MAX_LEVEL); - -	/* -	 * Set up I2C bus -	 * FIXME: distroy i2c_bus when exit -	 */ -	psb_intel_output->i2c_bus = psb_intel_i2c_create(dev, -							 GPIOB, -							 "LVDSBLC_B"); -	if (!psb_intel_output->i2c_bus) { -		dev_printk(KERN_ERR, -			&dev->pdev->dev, "I2C bus registration failed.\n"); -		goto failed_blc_i2c; -	} -	psb_intel_output->i2c_bus->slave_addr = 0x2C; -	dev_priv->lvds_i2c_bus =  psb_intel_output->i2c_bus; - -	/* -	 * LVDS discovery: -	 * 1) check for EDID on DDC -	 * 2) check for VBT data -	 * 3) check to see if LVDS is already on -	 *    if none of the above, no panel -	 * 4) make sure lid is open -	 *    if closed, act like it's not there for now -	 */ - -	/* Set up the DDC bus. */ -	psb_intel_output->ddc_bus = psb_intel_i2c_create(dev, -							 GPIOC, -							 "LVDSDDC_C"); -	if (!psb_intel_output->ddc_bus) { -		dev_printk(KERN_ERR, &dev->pdev->dev, -			   "DDC bus registration " "failed.\n"); -		goto failed_ddc; -	} - -	/* -	 * Attempt to get the fixed panel mode from DDC.  Assume that the -	 * preferred mode is the right one. -	 */ -	psb_intel_ddc_get_modes(psb_intel_output); -	list_for_each_entry(scan, &connector->probed_modes, head) { -		if (scan->type & DRM_MODE_TYPE_PREFERRED) { -			mode_dev->panel_fixed_mode = -			    drm_mode_duplicate(dev, scan); -			goto out;	/* FIXME: check for quirks */ -		} -	} - -	/* Failed to get EDID, what about VBT? do we need this? */ -	if (mode_dev->vbt_mode) -		mode_dev->panel_fixed_mode = -		    drm_mode_duplicate(dev, mode_dev->vbt_mode); - -	if (!mode_dev->panel_fixed_mode) -		if (dev_priv->lfp_lvds_vbt_mode) -			mode_dev->panel_fixed_mode = -				drm_mode_duplicate(dev, -					dev_priv->lfp_lvds_vbt_mode); - -	/* -	 * If we didn't get EDID, try checking if the panel is already turned -	 * on.	If so, assume that whatever is currently programmed is the -	 * correct mode. -	 */ -	lvds = REG_READ(LVDS); -	pipe = (lvds & LVDS_PIPEB_SELECT) ? 1 : 0; -	crtc = psb_intel_get_crtc_from_pipe(dev, pipe); - -	if (crtc && (lvds & LVDS_PORT_EN)) { -		mode_dev->panel_fixed_mode = -		    psb_intel_crtc_mode_get(dev, crtc); -		if (mode_dev->panel_fixed_mode) { -			mode_dev->panel_fixed_mode->type |= -			    DRM_MODE_TYPE_PREFERRED; -			goto out;	/* FIXME: check for quirks */ -		} -	} - -	/* If we still don't have a mode after all that, give up. */ -	if (!mode_dev->panel_fixed_mode) { -		dev_err(dev->dev, "Found no modes on the lvds, ignoring the LVDS\n"); -		goto failed_find; -	} - -	/* -	 * Blacklist machines with BIOSes that list an LVDS panel without -	 * actually having one. -	 */ -out: -	drm_sysfs_connector_add(connector); -	return; - -failed_find: -	if (psb_intel_output->ddc_bus) -		psb_intel_i2c_destroy(psb_intel_output->ddc_bus); -failed_ddc: -	if (psb_intel_output->i2c_bus) -		psb_intel_i2c_destroy(psb_intel_output->i2c_bus); -failed_blc_i2c: -	drm_encoder_cleanup(encoder); -	drm_connector_cleanup(connector); -	kfree(connector); -} - diff --git a/drivers/staging/gma500/psb_intel_modes.c b/drivers/staging/gma500/psb_intel_modes.c deleted file mode 100644 index bde1aff9619..00000000000 --- a/drivers/staging/gma500/psb_intel_modes.c +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2007 Intel Corporation - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - * Authers: Jesse Barnes <jesse.barnes@intel.com> - */ - -#include <linux/i2c.h> -#include <linux/fb.h> -#include <drm/drmP.h> -#include "psb_intel_drv.h" - -/** - * psb_intel_ddc_probe - * - */ -bool psb_intel_ddc_probe(struct psb_intel_output *psb_intel_output) -{ -	u8 out_buf[] = { 0x0, 0x0 }; -	u8 buf[2]; -	int ret; -	struct i2c_msg msgs[] = { -		{ -		 .addr = 0x50, -		 .flags = 0, -		 .len = 1, -		 .buf = out_buf, -		 }, -		{ -		 .addr = 0x50, -		 .flags = I2C_M_RD, -		 .len = 1, -		 .buf = buf, -		 } -	}; - -	ret = i2c_transfer(&psb_intel_output->ddc_bus->adapter, msgs, 2); -	if (ret == 2) -		return true; - -	return false; -} - -/** - * psb_intel_ddc_get_modes - get modelist from monitor - * @connector: DRM connector device to use - * - * Fetch the EDID information from @connector using the DDC bus. - */ -int psb_intel_ddc_get_modes(struct psb_intel_output *psb_intel_output) -{ -	struct edid *edid; -	int ret = 0; - -	edid = -	    drm_get_edid(&psb_intel_output->base, -			 &psb_intel_output->ddc_bus->adapter); -	if (edid) { -		drm_mode_connector_update_edid_property(&psb_intel_output-> -							base, edid); -		ret = drm_add_edid_modes(&psb_intel_output->base, edid); -		kfree(edid); -	} -	return ret; -} diff --git a/drivers/staging/gma500/psb_intel_reg.h b/drivers/staging/gma500/psb_intel_reg.h deleted file mode 100644 index 1ac16aa791c..00000000000 --- a/drivers/staging/gma500/psb_intel_reg.h +++ /dev/null @@ -1,1235 +0,0 @@ -/* - * Copyright (c) 2009, Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - */ -#ifndef __PSB_INTEL_REG_H__ -#define __PSB_INTEL_REG_H__ - -#define BLC_PWM_CTL		0x61254 -#define BLC_PWM_CTL2		0x61250 -#define BLC_PWM_CTL_C		0x62254 -#define BLC_PWM_CTL2_C		0x62250 -#define BACKLIGHT_MODULATION_FREQ_SHIFT		(17) -/* - * This is the most significant 15 bits of the number of backlight cycles in a - * complete cycle of the modulated backlight control. - * - * The actual value is this field multiplied by two. - */ -#define BACKLIGHT_MODULATION_FREQ_MASK	(0x7fff << 17) -#define BLM_LEGACY_MODE			(1 << 16) -/* - * This is the number of cycles out of the backlight modulation cycle for which - * the backlight is on. - * - * This field must be no greater than the number of cycles in the complete - * backlight modulation cycle. - */ -#define BACKLIGHT_DUTY_CYCLE_SHIFT	(0) -#define BACKLIGHT_DUTY_CYCLE_MASK	(0xffff) - -#define I915_GCFGC			0xf0 -#define I915_LOW_FREQUENCY_ENABLE	(1 << 7) -#define I915_DISPLAY_CLOCK_190_200_MHZ	(0 << 4) -#define I915_DISPLAY_CLOCK_333_MHZ	(4 << 4) -#define I915_DISPLAY_CLOCK_MASK		(7 << 4) - -#define I855_HPLLCC			0xc0 -#define I855_CLOCK_CONTROL_MASK		(3 << 0) -#define I855_CLOCK_133_200		(0 << 0) -#define I855_CLOCK_100_200		(1 << 0) -#define I855_CLOCK_100_133		(2 << 0) -#define I855_CLOCK_166_250		(3 << 0) - -/* I830 CRTC registers */ -#define HTOTAL_A		0x60000 -#define HBLANK_A		0x60004 -#define HSYNC_A			0x60008 -#define VTOTAL_A		0x6000c -#define VBLANK_A		0x60010 -#define VSYNC_A			0x60014 -#define PIPEASRC		0x6001c -#define BCLRPAT_A		0x60020 -#define VSYNCSHIFT_A		0x60028 - -#define HTOTAL_B		0x61000 -#define HBLANK_B		0x61004 -#define HSYNC_B			0x61008 -#define VTOTAL_B		0x6100c -#define VBLANK_B		0x61010 -#define VSYNC_B			0x61014 -#define PIPEBSRC		0x6101c -#define BCLRPAT_B		0x61020 -#define VSYNCSHIFT_B		0x61028 - -#define HTOTAL_C		0x62000 -#define HBLANK_C		0x62004 -#define HSYNC_C			0x62008 -#define VTOTAL_C		0x6200c -#define VBLANK_C		0x62010 -#define VSYNC_C			0x62014 -#define PIPECSRC		0x6201c -#define BCLRPAT_C		0x62020 -#define VSYNCSHIFT_C		0x62028 - -#define PP_STATUS		0x61200 -# define PP_ON				(1 << 31) -/* - * Indicates that all dependencies of the panel are on: - * - * - PLL enabled - * - pipe enabled - * - LVDS/DVOB/DVOC on - */ -#define PP_READY			(1 << 30) -#define PP_SEQUENCE_NONE		(0 << 28) -#define PP_SEQUENCE_ON			(1 << 28) -#define PP_SEQUENCE_OFF			(2 << 28) -#define PP_SEQUENCE_MASK		0x30000000 -#define PP_CONTROL		0x61204 -#define POWER_TARGET_ON			(1 << 0) - -#define LVDSPP_ON		0x61208 -#define LVDSPP_OFF		0x6120c -#define PP_CYCLE		0x61210 - -#define PFIT_CONTROL		0x61230 -#define PFIT_ENABLE			(1 << 31) -#define PFIT_PIPE_MASK			(3 << 29) -#define PFIT_PIPE_SHIFT			29 -#define PFIT_SCALING_MODE_PILLARBOX	(1 << 27) -#define PFIT_SCALING_MODE_LETTERBOX	(3 << 26) -#define VERT_INTERP_DISABLE		(0 << 10) -#define VERT_INTERP_BILINEAR		(1 << 10) -#define VERT_INTERP_MASK		(3 << 10) -#define VERT_AUTO_SCALE			(1 << 9) -#define HORIZ_INTERP_DISABLE		(0 << 6) -#define HORIZ_INTERP_BILINEAR		(1 << 6) -#define HORIZ_INTERP_MASK		(3 << 6) -#define HORIZ_AUTO_SCALE		(1 << 5) -#define PANEL_8TO6_DITHER_ENABLE	(1 << 3) - -#define PFIT_PGM_RATIOS		0x61234 -#define PFIT_VERT_SCALE_MASK			0xfff00000 -#define PFIT_HORIZ_SCALE_MASK			0x0000fff0 - -#define PFIT_AUTO_RATIOS	0x61238 - -#define DPLL_A			0x06014 -#define DPLL_B			0x06018 -#define DPLL_VCO_ENABLE			(1 << 31) -#define DPLL_DVO_HIGH_SPEED		(1 << 30) -#define DPLL_SYNCLOCK_ENABLE		(1 << 29) -#define DPLL_VGA_MODE_DIS		(1 << 28) -#define DPLLB_MODE_DAC_SERIAL		(1 << 26)	/* i915 */ -#define DPLLB_MODE_LVDS			(2 << 26)	/* i915 */ -#define DPLL_MODE_MASK			(3 << 26) -#define DPLL_DAC_SERIAL_P2_CLOCK_DIV_10	(0 << 24)	/* i915 */ -#define DPLL_DAC_SERIAL_P2_CLOCK_DIV_5	(1 << 24)	/* i915 */ -#define DPLLB_LVDS_P2_CLOCK_DIV_14	(0 << 24)	/* i915 */ -#define DPLLB_LVDS_P2_CLOCK_DIV_7	(1 << 24)	/* i915 */ -#define DPLL_P2_CLOCK_DIV_MASK		0x03000000	/* i915 */ -#define DPLL_FPA01_P1_POST_DIV_MASK	0x00ff0000	/* i915 */ -#define DPLL_LOCK			(1 << 15)	/* CDV */ - -/* - *  The i830 generation, in DAC/serial mode, defines p1 as two plus this - * bitfield, or just 2 if PLL_P1_DIVIDE_BY_TWO is set. - */ -# define DPLL_FPA01_P1_POST_DIV_MASK_I830	0x001f0000 -/* - * The i830 generation, in LVDS mode, defines P1 as the bit number set within - * this field (only one bit may be set). - */ -#define DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS	0x003f0000 -#define DPLL_FPA01_P1_POST_DIV_SHIFT	16 -#define PLL_P2_DIVIDE_BY_4		(1 << 23)	/* i830, required -							 * in DVO non-gang */ -# define PLL_P1_DIVIDE_BY_TWO		(1 << 21)	/* i830 */ -#define PLL_REF_INPUT_DREFCLK		(0 << 13) -#define PLL_REF_INPUT_TVCLKINA		(1 << 13)	/* i830 */ -#define PLL_REF_INPUT_TVCLKINBC		(2 << 13)	/* SDVO -								 * TVCLKIN */ -#define PLLB_REF_INPUT_SPREADSPECTRUMIN	(3 << 13) -#define PLL_REF_INPUT_MASK		(3 << 13) -#define PLL_LOAD_PULSE_PHASE_SHIFT	9 -/* - * Parallel to Serial Load Pulse phase selection. - * Selects the phase for the 10X DPLL clock for the PCIe - * digital display port. The range is 4 to 13; 10 or more - * is just a flip delay. The default is 6 - */ -#define PLL_LOAD_PULSE_PHASE_MASK	(0xf << PLL_LOAD_PULSE_PHASE_SHIFT) -#define DISPLAY_RATE_SELECT_FPA1	(1 << 8) - -/* - * SDVO multiplier for 945G/GM. Not used on 965. - * - * DPLL_MD_UDI_MULTIPLIER_MASK - */ -#define SDVO_MULTIPLIER_MASK		0x000000ff -#define SDVO_MULTIPLIER_SHIFT_HIRES	4 -#define SDVO_MULTIPLIER_SHIFT_VGA	0 - -/* - * PLL_MD - */ -/* Pipe A SDVO/UDI clock multiplier/divider register for G965. */ -#define DPLL_A_MD		0x0601c -/* Pipe B SDVO/UDI clock multiplier/divider register for G965. */ -#define DPLL_B_MD		0x06020 -/* - * UDI pixel divider, controlling how many pixels are stuffed into a packet. - * - * Value is pixels minus 1.  Must be set to 1 pixel for SDVO. - */ -#define DPLL_MD_UDI_DIVIDER_MASK	0x3f000000 -#define DPLL_MD_UDI_DIVIDER_SHIFT	24 -/* UDI pixel divider for VGA, same as DPLL_MD_UDI_DIVIDER_MASK. */ -#define DPLL_MD_VGA_UDI_DIVIDER_MASK	0x003f0000 -#define DPLL_MD_VGA_UDI_DIVIDER_SHIFT	16 -/* - * SDVO/UDI pixel multiplier. - * - * SDVO requires that the bus clock rate be between 1 and 2 Ghz, and the bus - * clock rate is 10 times the DPLL clock.  At low resolution/refresh rate - * modes, the bus rate would be below the limits, so SDVO allows for stuffing - * dummy bytes in the datastream at an increased clock rate, with both sides of - * the link knowing how many bytes are fill. - * - * So, for a mode with a dotclock of 65Mhz, we would want to double the clock - * rate to 130Mhz to get a bus rate of 1.30Ghz.  The DPLL clock rate would be - * set to 130Mhz, and the SDVO multiplier set to 2x in this register and - * through an SDVO command. - * - * This register field has values of multiplication factor minus 1, with - * a maximum multiplier of 5 for SDVO. - */ -#define DPLL_MD_UDI_MULTIPLIER_MASK	0x00003f00 -#define DPLL_MD_UDI_MULTIPLIER_SHIFT	8 -/* - * SDVO/UDI pixel multiplier for VGA, same as DPLL_MD_UDI_MULTIPLIER_MASK. - * This best be set to the default value (3) or the CRT won't work. No, - * I don't entirely understand what this does... - */ -#define DPLL_MD_VGA_UDI_MULTIPLIER_MASK	0x0000003f -#define DPLL_MD_VGA_UDI_MULTIPLIER_SHIFT 0 - -#define DPLL_TEST		0x606c -#define DPLLB_TEST_SDVO_DIV_1		(0 << 22) -#define DPLLB_TEST_SDVO_DIV_2		(1 << 22) -#define DPLLB_TEST_SDVO_DIV_4		(2 << 22) -#define DPLLB_TEST_SDVO_DIV_MASK	(3 << 22) -#define DPLLB_TEST_N_BYPASS		(1 << 19) -#define DPLLB_TEST_M_BYPASS		(1 << 18) -#define DPLLB_INPUT_BUFFER_ENABLE	(1 << 16) -#define DPLLA_TEST_N_BYPASS		(1 << 3) -#define DPLLA_TEST_M_BYPASS		(1 << 2) -#define DPLLA_INPUT_BUFFER_ENABLE	(1 << 0) - -#define ADPA			0x61100 -#define ADPA_DAC_ENABLE			(1 << 31) -#define ADPA_DAC_DISABLE		0 -#define ADPA_PIPE_SELECT_MASK		(1 << 30) -#define ADPA_PIPE_A_SELECT		0 -#define ADPA_PIPE_B_SELECT		(1 << 30) -#define ADPA_USE_VGA_HVPOLARITY		(1 << 15) -#define ADPA_SETS_HVPOLARITY		0 -#define ADPA_VSYNC_CNTL_DISABLE		(1 << 11) -#define ADPA_VSYNC_CNTL_ENABLE		0 -#define ADPA_HSYNC_CNTL_DISABLE		(1 << 10) -#define ADPA_HSYNC_CNTL_ENABLE		0 -#define ADPA_VSYNC_ACTIVE_HIGH		(1 << 4) -#define ADPA_VSYNC_ACTIVE_LOW		0 -#define ADPA_HSYNC_ACTIVE_HIGH		(1 << 3) -#define ADPA_HSYNC_ACTIVE_LOW		0 - -#define FPA0			0x06040 -#define FPA1			0x06044 -#define FPB0			0x06048 -#define FPB1			0x0604c -#define FP_N_DIV_MASK			0x003f0000 -#define FP_N_DIV_SHIFT			16 -#define FP_M1_DIV_MASK			0x00003f00 -#define FP_M1_DIV_SHIFT			8 -#define FP_M2_DIV_MASK			0x0000003f -#define FP_M2_DIV_SHIFT			0 - -#define PORT_HOTPLUG_EN		0x61110 -#define SDVOB_HOTPLUG_INT_EN		(1 << 26) -#define SDVOC_HOTPLUG_INT_EN		(1 << 25) -#define TV_HOTPLUG_INT_EN		(1 << 18) -#define CRT_HOTPLUG_INT_EN		(1 << 9) -#define CRT_HOTPLUG_FORCE_DETECT	(1 << 3) -/* CDV.. */ -#define CRT_HOTPLUG_ACTIVATION_PERIOD_64	(1 << 8) -#define CRT_HOTPLUG_DAC_ON_TIME_2M		(0 << 7) -#define CRT_HOTPLUG_DAC_ON_TIME_4M		(1 << 7) -#define CRT_HOTPLUG_VOLTAGE_COMPARE_40		(0 << 5) -#define CRT_HOTPLUG_VOLTAGE_COMPARE_50		(1 << 5) -#define CRT_HOTPLUG_VOLTAGE_COMPARE_60		(2 << 5) -#define CRT_HOTPLUG_VOLTAGE_COMPARE_70		(3 << 5) -#define CRT_HOTPLUG_VOLTAGE_COMPARE_MASK	(3 << 5) -#define CRT_HOTPLUG_DETECT_DELAY_1G		(0 << 4) -#define CRT_HOTPLUG_DETECT_DELAY_2G		(1 << 4) -#define CRT_HOTPLUG_DETECT_VOLTAGE_325MV	(0 << 2) -#define CRT_HOTPLUG_DETECT_VOLTAGE_475MV	(1 << 2) -#define CRT_HOTPLUG_DETECT_MASK			0x000000F8 - -#define PORT_HOTPLUG_STAT	0x61114 -#define CRT_HOTPLUG_INT_STATUS		(1 << 11) -#define TV_HOTPLUG_INT_STATUS		(1 << 10) -#define CRT_HOTPLUG_MONITOR_MASK	(3 << 8) -#define CRT_HOTPLUG_MONITOR_COLOR	(3 << 8) -#define CRT_HOTPLUG_MONITOR_MONO	(2 << 8) -#define CRT_HOTPLUG_MONITOR_NONE	(0 << 8) -#define SDVOC_HOTPLUG_INT_STATUS	(1 << 7) -#define SDVOB_HOTPLUG_INT_STATUS	(1 << 6) - -#define SDVOB			0x61140 -#define SDVOC			0x61160 -#define SDVO_ENABLE			(1 << 31) -#define SDVO_PIPE_B_SELECT		(1 << 30) -#define SDVO_STALL_SELECT		(1 << 29) -#define SDVO_INTERRUPT_ENABLE		(1 << 26) - -/** - * 915G/GM SDVO pixel multiplier. - * - * Programmed value is multiplier - 1, up to 5x. - * - * DPLL_MD_UDI_MULTIPLIER_MASK - */ -#define SDVO_PORT_MULTIPLY_MASK		(7 << 23) -#define SDVO_PORT_MULTIPLY_SHIFT	23 -#define SDVO_PHASE_SELECT_MASK		(15 << 19) -#define SDVO_PHASE_SELECT_DEFAULT	(6 << 19) -#define SDVO_CLOCK_OUTPUT_INVERT	(1 << 18) -#define SDVOC_GANG_MODE			(1 << 16) -#define SDVO_BORDER_ENABLE		(1 << 7) -#define SDVOB_PCIE_CONCURRENCY		(1 << 3) -#define SDVO_DETECTED			(1 << 2) -/* Bits to be preserved when writing */ -#define SDVOB_PRESERVE_MASK		((1 << 17) | (1 << 16) | (1 << 14)) -#define SDVOC_PRESERVE_MASK		(1 << 17) - -/* - * This register controls the LVDS output enable, pipe selection, and data - * format selection. - * - * All of the clock/data pairs are force powered down by power sequencing. - */ -#define LVDS			0x61180 -/* - * Enables the LVDS port.  This bit must be set before DPLLs are enabled, as - * the DPLL semantics change when the LVDS is assigned to that pipe. - */ -#define LVDS_PORT_EN			(1 << 31) -/* Selects pipe B for LVDS data.  Must be set on pre-965. */ -#define LVDS_PIPEB_SELECT		(1 << 30) - -/* Turns on border drawing to allow centered display. */ -#define LVDS_BORDER_EN			(1 << 15) - -/* - * Enables the A0-A2 data pairs and CLKA, containing 18 bits of color data per - * pixel. - */ -#define LVDS_A0A2_CLKA_POWER_MASK	(3 << 8) -#define LVDS_A0A2_CLKA_POWER_DOWN	(0 << 8) -#define LVDS_A0A2_CLKA_POWER_UP		(3 << 8) -/* - * Controls the A3 data pair, which contains the additional LSBs for 24 bit - * mode.  Only enabled if LVDS_A0A2_CLKA_POWER_UP also indicates it should be - * on. - */ -#define LVDS_A3_POWER_MASK		(3 << 6) -#define LVDS_A3_POWER_DOWN		(0 << 6) -#define LVDS_A3_POWER_UP		(3 << 6) -/* - * Controls the CLKB pair.  This should only be set when LVDS_B0B3_POWER_UP - * is set. - */ -#define LVDS_CLKB_POWER_MASK		(3 << 4) -#define LVDS_CLKB_POWER_DOWN		(0 << 4) -#define LVDS_CLKB_POWER_UP		(3 << 4) -/* - * Controls the B0-B3 data pairs.  This must be set to match the DPLL p2 - * setting for whether we are in dual-channel mode.  The B3 pair will - * additionally only be powered up when LVDS_A3_POWER_UP is set. - */ -#define LVDS_B0B3_POWER_MASK		(3 << 2) -#define LVDS_B0B3_POWER_DOWN		(0 << 2) -#define LVDS_B0B3_POWER_UP		(3 << 2) - -#define PIPEACONF		0x70008 -#define PIPEACONF_ENABLE		(1 << 31) -#define PIPEACONF_DISABLE		0 -#define PIPEACONF_DOUBLE_WIDE		(1 << 30) -#define PIPECONF_ACTIVE			(1 << 30) -#define I965_PIPECONF_ACTIVE		(1 << 30) -#define PIPECONF_DSIPLL_LOCK		(1 << 29) -#define PIPEACONF_SINGLE_WIDE		0 -#define PIPEACONF_PIPE_UNLOCKED		0 -#define PIPEACONF_DSR			(1 << 26) -#define PIPEACONF_PIPE_LOCKED		(1 << 25) -#define PIPEACONF_PALETTE		0 -#define PIPECONF_FORCE_BORDER		(1 << 25) -#define PIPEACONF_GAMMA			(1 << 24) -#define PIPECONF_PROGRESSIVE		(0 << 21) -#define PIPECONF_INTERLACE_W_FIELD_INDICATION	(6 << 21) -#define PIPECONF_INTERLACE_FIELD_0_ONLY		(7 << 21) -#define PIPECONF_PLANE_OFF		(1 << 19) -#define PIPECONF_CURSOR_OFF		(1 << 18) - -#define PIPEBCONF		0x71008 -#define PIPEBCONF_ENABLE		(1 << 31) -#define PIPEBCONF_DISABLE		0 -#define PIPEBCONF_DOUBLE_WIDE		(1 << 30) -#define PIPEBCONF_DISABLE		0 -#define PIPEBCONF_GAMMA			(1 << 24) -#define PIPEBCONF_PALETTE		0 - -#define PIPECCONF		0x72008 - -#define PIPEBGCMAXRED		0x71010 -#define PIPEBGCMAXGREEN		0x71014 -#define PIPEBGCMAXBLUE		0x71018 - -#define PIPEASTAT		0x70024 -#define PIPEBSTAT		0x71024 -#define PIPECSTAT		0x72024 -#define PIPE_VBLANK_INTERRUPT_STATUS		(1UL << 1) -#define PIPE_START_VBLANK_INTERRUPT_STATUS	(1UL << 2) -#define PIPE_VBLANK_CLEAR			(1 << 1) -#define PIPE_VBLANK_STATUS			(1 << 1) -#define PIPE_TE_STATUS				(1UL << 6) -#define PIPE_DPST_EVENT_STATUS			(1UL << 7) -#define PIPE_VSYNC_CLEAR			(1UL << 9) -#define PIPE_VSYNC_STATUS			(1UL << 9) -#define PIPE_HDMI_AUDIO_UNDERRUN_STATUS		(1UL << 10) -#define PIPE_HDMI_AUDIO_BUFFER_DONE_STATUS	(1UL << 11) -#define PIPE_VBLANK_INTERRUPT_ENABLE		(1UL << 17) -#define PIPE_START_VBLANK_INTERRUPT_ENABLE	(1UL << 18) -#define PIPE_TE_ENABLE				(1UL << 22) -#define PIPE_DPST_EVENT_ENABLE			(1UL << 23) -#define PIPE_VSYNC_ENABL			(1UL << 25) -#define PIPE_HDMI_AUDIO_UNDERRUN		(1UL << 26) -#define PIPE_HDMI_AUDIO_BUFFER_DONE		(1UL << 27) -#define PIPE_HDMI_AUDIO_INT_MASK		(PIPE_HDMI_AUDIO_UNDERRUN | \ -						PIPE_HDMI_AUDIO_BUFFER_DONE) -#define PIPE_EVENT_MASK ((1 << 29)|(1 << 28)|(1 << 27)|(1 << 26)|(1 << 24)|(1 << 23)|(1 << 22)|(1 << 21)|(1 << 20)|(1 << 16)) -#define PIPE_VBLANK_MASK ((1 << 25)|(1 << 24)|(1 << 18)|(1 << 17)) -#define HISTOGRAM_INT_CONTROL		0x61268 -#define HISTOGRAM_BIN_DATA		0X61264 -#define HISTOGRAM_LOGIC_CONTROL		0x61260 -#define PWM_CONTROL_LOGIC		0x61250 -#define PIPE_HOTPLUG_INTERRUPT_STATUS		(1UL << 10) -#define HISTOGRAM_INTERRUPT_ENABLE		(1UL << 31) -#define HISTOGRAM_LOGIC_ENABLE			(1UL << 31) -#define PWM_LOGIC_ENABLE			(1UL << 31) -#define PWM_PHASEIN_ENABLE			(1UL << 25) -#define PWM_PHASEIN_INT_ENABLE			(1UL << 24) -#define PWM_PHASEIN_VB_COUNT			0x00001f00 -#define PWM_PHASEIN_INC				0x0000001f -#define HISTOGRAM_INT_CTRL_CLEAR		(1UL << 30) -#define DPST_YUV_LUMA_MODE			0 - -struct dpst_ie_histogram_control { -	union { -		uint32_t data; -		struct { -			uint32_t bin_reg_index:7; -			uint32_t reserved:4; -			uint32_t bin_reg_func_select:1; -			uint32_t sync_to_phase_in:1; -			uint32_t alt_enhancement_mode:2; -			uint32_t reserved1:1; -			uint32_t sync_to_phase_in_count:8; -			uint32_t histogram_mode_select:1; -			uint32_t reserved2:4; -			uint32_t ie_pipe_assignment:1; -			uint32_t ie_mode_table_enabled:1; -			uint32_t ie_histogram_enable:1; -		}; -	}; -}; - -struct dpst_guardband { -	union { -		uint32_t data; -		struct { -			uint32_t guardband:22; -			uint32_t guardband_interrupt_delay:8; -			uint32_t interrupt_status:1; -			uint32_t interrupt_enable:1; -		}; -	}; -}; - -#define PIPEAFRAMEHIGH		0x70040 -#define PIPEAFRAMEPIXEL		0x70044 -#define PIPEBFRAMEHIGH		0x71040 -#define PIPEBFRAMEPIXEL		0x71044 -#define PIPECFRAMEHIGH		0x72040 -#define PIPECFRAMEPIXEL		0x72044 -#define PIPE_FRAME_HIGH_MASK	0x0000ffff -#define PIPE_FRAME_HIGH_SHIFT	0 -#define PIPE_FRAME_LOW_MASK	0xff000000 -#define PIPE_FRAME_LOW_SHIFT	24 -#define PIPE_PIXEL_MASK		0x00ffffff -#define PIPE_PIXEL_SHIFT	0 - -#define DSPARB			0x70030 -#define DSPFW1			0x70034 -#define DSPFW2			0x70038 -#define DSPFW3			0x7003c -#define DSPFW4			0x70050 -#define DSPFW5			0x70054 -#define DSPFW6			0x70058 -#define DSPCHICKENBIT		0x70400 -#define DSPACNTR		0x70180 -#define DSPBCNTR		0x71180 -#define DSPCCNTR		0x72180 -#define DISPLAY_PLANE_ENABLE			(1 << 31) -#define DISPLAY_PLANE_DISABLE			0 -#define DISPPLANE_GAMMA_ENABLE			(1 << 30) -#define DISPPLANE_GAMMA_DISABLE			0 -#define DISPPLANE_PIXFORMAT_MASK		(0xf << 26) -#define DISPPLANE_8BPP				(0x2 << 26) -#define DISPPLANE_15_16BPP			(0x4 << 26) -#define DISPPLANE_16BPP				(0x5 << 26) -#define DISPPLANE_32BPP_NO_ALPHA		(0x6 << 26) -#define DISPPLANE_32BPP				(0x7 << 26) -#define DISPPLANE_STEREO_ENABLE			(1 << 25) -#define DISPPLANE_STEREO_DISABLE		0 -#define DISPPLANE_SEL_PIPE_MASK			(1 << 24) -#define DISPPLANE_SEL_PIPE_POS			24 -#define DISPPLANE_SEL_PIPE_A			0 -#define DISPPLANE_SEL_PIPE_B			(1 << 24) -#define DISPPLANE_SRC_KEY_ENABLE		(1 << 22) -#define DISPPLANE_SRC_KEY_DISABLE		0 -#define DISPPLANE_LINE_DOUBLE			(1 << 20) -#define DISPPLANE_NO_LINE_DOUBLE		0 -#define DISPPLANE_STEREO_POLARITY_FIRST		0 -#define DISPPLANE_STEREO_POLARITY_SECOND	(1 << 18) -/* plane B only */ -#define DISPPLANE_ALPHA_TRANS_ENABLE		(1 << 15) -#define DISPPLANE_ALPHA_TRANS_DISABLE		0 -#define DISPPLANE_SPRITE_ABOVE_DISPLAYA		0 -#define DISPPLANE_SPRITE_ABOVE_OVERLAY		(1) -#define DISPPLANE_BOTTOM			(4) - -#define DSPABASE		0x70184 -#define DSPALINOFF		0x70184 -#define DSPASTRIDE		0x70188 - -#define DSPBBASE		0x71184 -#define DSPBLINOFF		0X71184 -#define DSPBADDR		DSPBBASE -#define DSPBSTRIDE		0x71188 - -#define DSPCBASE		0x72184 -#define DSPCLINOFF		0x72184 -#define DSPCSTRIDE		0x72188 - -#define DSPAKEYVAL		0x70194 -#define DSPAKEYMASK		0x70198 - -#define DSPAPOS			0x7018C	/* reserved */ -#define DSPASIZE		0x70190 -#define DSPBPOS			0x7118C -#define DSPBSIZE		0x71190 -#define DSPCPOS			0x7218C -#define DSPCSIZE		0x72190 - -#define DSPASURF		0x7019C -#define DSPATILEOFF		0x701A4 - -#define DSPBSURF		0x7119C -#define DSPBTILEOFF		0x711A4 - -#define DSPCSURF		0x7219C -#define DSPCTILEOFF		0x721A4 -#define DSPCKEYMAXVAL		0x721A0 -#define DSPCKEYMINVAL		0x72194 -#define DSPCKEYMSK		0x72198 - -#define VGACNTRL		0x71400 -#define VGA_DISP_DISABLE		(1 << 31) -#define VGA_2X_MODE			(1 << 30) -#define VGA_PIPE_B_SELECT		(1 << 29) - -/* - * Overlay registers - */ -#define OV_C_OFFSET		0x08000 -#define OV_OVADD		0x30000 -#define OV_DOVASTA		0x30008 -# define OV_PIPE_SELECT			((1 << 6)|(1 << 7)) -# define OV_PIPE_SELECT_POS		6 -# define OV_PIPE_A			0 -# define OV_PIPE_C			1 -#define OV_OGAMC5		0x30010 -#define OV_OGAMC4		0x30014 -#define OV_OGAMC3		0x30018 -#define OV_OGAMC2		0x3001C -#define OV_OGAMC1		0x30020 -#define OV_OGAMC0		0x30024 -#define OVC_OVADD		0x38000 -#define OVC_DOVCSTA		0x38008 -#define OVC_OGAMC5		0x38010 -#define OVC_OGAMC4		0x38014 -#define OVC_OGAMC3		0x38018 -#define OVC_OGAMC2		0x3801C -#define OVC_OGAMC1		0x38020 -#define OVC_OGAMC0		0x38024 - -/* - * Some BIOS scratch area registers.  The 845 (and 830?) store the amount - * of video memory available to the BIOS in SWF1. - */ -#define SWF0			0x71410 -#define SWF1			0x71414 -#define SWF2			0x71418 -#define SWF3			0x7141c -#define SWF4			0x71420 -#define SWF5			0x71424 -#define SWF6			0x71428 - -/* - * 855 scratch registers. - */ -#define SWF00			0x70410 -#define SWF01			0x70414 -#define SWF02			0x70418 -#define SWF03			0x7041c -#define SWF04			0x70420 -#define SWF05			0x70424 -#define SWF06			0x70428 - -#define SWF10			SWF0 -#define SWF11			SWF1 -#define SWF12			SWF2 -#define SWF13			SWF3 -#define SWF14			SWF4 -#define SWF15			SWF5 -#define SWF16			SWF6 - -#define SWF30			0x72414 -#define SWF31			0x72418 -#define SWF32			0x7241c - - -/* - * Palette registers - */ -#define PALETTE_A		0x0a000 -#define PALETTE_B		0x0a800 -#define PALETTE_C		0x0ac00 - -/* Cursor A & B regs */ -#define CURACNTR		0x70080 -#define CURSOR_MODE_DISABLE		0x00 -#define CURSOR_MODE_64_32B_AX		0x07 -#define CURSOR_MODE_64_ARGB_AX		((1 << 5) | CURSOR_MODE_64_32B_AX) -#define MCURSOR_GAMMA_ENABLE		(1 << 26) -#define CURABASE		0x70084 -#define CURAPOS			0x70088 -#define CURSOR_POS_MASK			0x007FF -#define CURSOR_POS_SIGN			0x8000 -#define CURSOR_X_SHIFT			0 -#define CURSOR_Y_SHIFT			16 -#define CURBCNTR		0x700c0 -#define CURBBASE		0x700c4 -#define CURBPOS			0x700c8 -#define CURCCNTR		0x700e0 -#define CURCBASE		0x700e4 -#define CURCPOS			0x700e8 - -/* - * Interrupt Registers - */ -#define IER			0x020a0 -#define IIR			0x020a4 -#define IMR			0x020a8 -#define ISR			0x020ac - -/* - * MOORESTOWN delta registers - */ -#define MRST_DPLL_A		0x0f014 -#define MDFLD_DPLL_B		0x0f018 -#define MDFLD_INPUT_REF_SEL		(1 << 14) -#define MDFLD_VCO_SEL			(1 << 16) -#define DPLLA_MODE_LVDS			(2 << 26)	/* mrst */ -#define MDFLD_PLL_LATCHEN		(1 << 28) -#define MDFLD_PWR_GATE_EN		(1 << 30) -#define MDFLD_P1_MASK			(0x1FF << 17) -#define MRST_FPA0		0x0f040 -#define MRST_FPA1		0x0f044 -#define MDFLD_DPLL_DIV0		0x0f048 -#define MDFLD_DPLL_DIV1		0x0f04c -#define MRST_PERF_MODE		0x020f4 - -/* - * MEDFIELD HDMI registers - */ -#define HDMIPHYMISCCTL		0x61134 -#define HDMI_PHY_POWER_DOWN		0x7f -#define HDMIB_CONTROL		0x61140 -#define HDMIB_PORT_EN			(1 << 31) -#define HDMIB_PIPE_B_SELECT		(1 << 30) -#define HDMIB_NULL_PACKET		(1 << 9) -#define HDMIB_HDCP_PORT			(1 << 5) - -/* #define LVDS			0x61180 */ -#define MRST_PANEL_8TO6_DITHER_ENABLE	(1 << 25) -#define MRST_PANEL_24_DOT_1_FORMAT	(1 << 24) -#define LVDS_A3_POWER_UP_0_OUTPUT	(1 << 6) - -#define MIPI			0x61190 -#define MIPI_C			0x62190 -#define MIPI_PORT_EN			(1 << 31) -/* Turns on border drawing to allow centered display. */ -#define SEL_FLOPPED_HSTX		(1 << 23) -#define PASS_FROM_SPHY_TO_AFE		(1 << 16) -#define MIPI_BORDER_EN			(1 << 15) -#define MIPIA_3LANE_MIPIC_1LANE		0x1 -#define MIPIA_2LANE_MIPIC_2LANE		0x2 -#define TE_TRIGGER_DSI_PROTOCOL		(1 << 2) -#define TE_TRIGGER_GPIO_PIN		(1 << 3) -#define MIPI_TE_COUNT		0x61194 - -/* #define PP_CONTROL	0x61204 */ -#define POWER_DOWN_ON_RESET		(1 << 1) - -/* #define PFIT_CONTROL	0x61230 */ -#define PFIT_PIPE_SELECT		(3 << 29) -#define PFIT_PIPE_SELECT_SHIFT		(29) - -/* #define BLC_PWM_CTL		0x61254 */ -#define MRST_BACKLIGHT_MODULATION_FREQ_SHIFT	(16) -#define MRST_BACKLIGHT_MODULATION_FREQ_MASK	(0xffff << 16) - -/* #define PIPEACONF 0x70008 */ -#define PIPEACONF_PIPE_STATE		(1 << 30) -/* #define DSPACNTR		0x70180 */ - -#define MRST_DSPABASE		0x7019c -#define MRST_DSPBBASE		0x7119c -#define MDFLD_DSPCBASE		0x7219c - -/* - * Moorestown registers. - */ - -/* - *	MIPI IP registers - */ -#define MIPIC_REG_OFFSET		0x800 - -#define DEVICE_READY_REG		0xb000 -#define LP_OUTPUT_HOLD				(1 << 16) -#define EXIT_ULPS_DEV_READY			0x3 -#define LP_OUTPUT_HOLD_RELEASE			0x810000 -# define ENTERING_ULPS				(2 << 1) -# define EXITING_ULPS				(1 << 1) -# define ULPS_MASK				(3 << 1) -# define BUS_POSSESSION				(1 << 3) -#define INTR_STAT_REG			0xb004 -#define RX_SOT_ERROR				(1 << 0) -#define RX_SOT_SYNC_ERROR			(1 << 1) -#define RX_ESCAPE_MODE_ENTRY_ERROR		(1 << 3) -#define RX_LP_TX_SYNC_ERROR			(1 << 4) -#define RX_HS_RECEIVE_TIMEOUT_ERROR		(1 << 5) -#define RX_FALSE_CONTROL_ERROR			(1 << 6) -#define RX_ECC_SINGLE_BIT_ERROR			(1 << 7) -#define RX_ECC_MULTI_BIT_ERROR			(1 << 8) -#define RX_CHECKSUM_ERROR			(1 << 9) -#define RX_DSI_DATA_TYPE_NOT_RECOGNIZED		(1 << 10) -#define RX_DSI_VC_ID_INVALID			(1 << 11) -#define TX_FALSE_CONTROL_ERROR			(1 << 12) -#define TX_ECC_SINGLE_BIT_ERROR			(1 << 13) -#define TX_ECC_MULTI_BIT_ERROR			(1 << 14) -#define TX_CHECKSUM_ERROR			(1 << 15) -#define TX_DSI_DATA_TYPE_NOT_RECOGNIZED		(1 << 16) -#define TX_DSI_VC_ID_INVALID			(1 << 17) -#define HIGH_CONTENTION				(1 << 18) -#define LOW_CONTENTION				(1 << 19) -#define DPI_FIFO_UNDER_RUN			(1 << 20) -#define HS_TX_TIMEOUT				(1 << 21) -#define LP_RX_TIMEOUT				(1 << 22) -#define TURN_AROUND_ACK_TIMEOUT			(1 << 23) -#define ACK_WITH_NO_ERROR			(1 << 24) -#define HS_GENERIC_WR_FIFO_FULL			(1 << 27) -#define LP_GENERIC_WR_FIFO_FULL			(1 << 28) -#define SPL_PKT_SENT				(1 << 30) -#define INTR_EN_REG			0xb008 -#define DSI_FUNC_PRG_REG		0xb00c -#define DPI_CHANNEL_NUMBER_POS			0x03 -#define DBI_CHANNEL_NUMBER_POS			0x05 -#define FMT_DPI_POS				0x07 -#define FMT_DBI_POS				0x0A -#define DBI_DATA_WIDTH_POS			0x0D - -/* DPI PIXEL FORMATS */ -#define RGB_565_FMT				0x01	/* RGB 565 FORMAT */ -#define RGB_666_FMT				0x02	/* RGB 666 FORMAT */ -#define LRGB_666_FMT				0x03	/* RGB LOOSELY PACKED -							 * 666 FORMAT -							 */ -#define RGB_888_FMT				0x04	/* RGB 888 FORMAT */ -#define VIRTUAL_CHANNEL_NUMBER_0		0x00	/* Virtual channel 0 */ -#define VIRTUAL_CHANNEL_NUMBER_1		0x01	/* Virtual channel 1 */ -#define VIRTUAL_CHANNEL_NUMBER_2		0x02	/* Virtual channel 2 */ -#define VIRTUAL_CHANNEL_NUMBER_3		0x03	/* Virtual channel 3 */ - -#define DBI_NOT_SUPPORTED			0x00	/* command mode -							 * is not supported -							 */ -#define DBI_DATA_WIDTH_16BIT			0x01	/* 16 bit data */ -#define DBI_DATA_WIDTH_9BIT			0x02	/* 9 bit data */ -#define DBI_DATA_WIDTH_8BIT			0x03	/* 8 bit data */ -#define DBI_DATA_WIDTH_OPT1			0x04	/* option 1 */ -#define DBI_DATA_WIDTH_OPT2			0x05	/* option 2 */ - -#define HS_TX_TIMEOUT_REG		0xb010 -#define LP_RX_TIMEOUT_REG		0xb014 -#define TURN_AROUND_TIMEOUT_REG		0xb018 -#define DEVICE_RESET_REG		0xb01C -#define DPI_RESOLUTION_REG		0xb020 -#define RES_V_POS				0x10 -#define DBI_RESOLUTION_REG		0xb024 /* Reserved for MDFLD */ -#define HORIZ_SYNC_PAD_COUNT_REG	0xb028 -#define HORIZ_BACK_PORCH_COUNT_REG	0xb02C -#define HORIZ_FRONT_PORCH_COUNT_REG	0xb030 -#define HORIZ_ACTIVE_AREA_COUNT_REG	0xb034 -#define VERT_SYNC_PAD_COUNT_REG		0xb038 -#define VERT_BACK_PORCH_COUNT_REG	0xb03c -#define VERT_FRONT_PORCH_COUNT_REG	0xb040 -#define HIGH_LOW_SWITCH_COUNT_REG	0xb044 -#define DPI_CONTROL_REG			0xb048 -#define DPI_SHUT_DOWN				(1 << 0) -#define DPI_TURN_ON				(1 << 1) -#define DPI_COLOR_MODE_ON			(1 << 2) -#define DPI_COLOR_MODE_OFF			(1 << 3) -#define DPI_BACK_LIGHT_ON			(1 << 4) -#define DPI_BACK_LIGHT_OFF			(1 << 5) -#define DPI_LP					(1 << 6) -#define DPI_DATA_REG			0xb04c -#define DPI_BACK_LIGHT_ON_DATA			0x07 -#define DPI_BACK_LIGHT_OFF_DATA			0x17 -#define INIT_COUNT_REG			0xb050 -#define MAX_RET_PAK_REG			0xb054 -#define VIDEO_FMT_REG			0xb058 -#define COMPLETE_LAST_PCKT			(1 << 2) -#define EOT_DISABLE_REG			0xb05c -#define ENABLE_CLOCK_STOPPING			(1 << 1) -#define LP_BYTECLK_REG			0xb060 -#define LP_GEN_DATA_REG			0xb064 -#define HS_GEN_DATA_REG			0xb068 -#define LP_GEN_CTRL_REG			0xb06C -#define HS_GEN_CTRL_REG			0xb070 -#define DCS_CHANNEL_NUMBER_POS		0x6 -#define MCS_COMMANDS_POS		0x8 -#define WORD_COUNTS_POS			0x8 -#define MCS_PARAMETER_POS			0x10 -#define GEN_FIFO_STAT_REG		0xb074 -#define HS_DATA_FIFO_FULL			(1 << 0) -#define HS_DATA_FIFO_HALF_EMPTY			(1 << 1) -#define HS_DATA_FIFO_EMPTY			(1 << 2) -#define LP_DATA_FIFO_FULL			(1 << 8) -#define LP_DATA_FIFO_HALF_EMPTY			(1 << 9) -#define LP_DATA_FIFO_EMPTY			(1 << 10) -#define HS_CTRL_FIFO_FULL			(1 << 16) -#define HS_CTRL_FIFO_HALF_EMPTY			(1 << 17) -#define HS_CTRL_FIFO_EMPTY			(1 << 18) -#define LP_CTRL_FIFO_FULL			(1 << 24) -#define LP_CTRL_FIFO_HALF_EMPTY			(1 << 25) -#define LP_CTRL_FIFO_EMPTY			(1 << 26) -#define DBI_FIFO_EMPTY				(1 << 27) -#define DPI_FIFO_EMPTY				(1 << 28) -#define HS_LS_DBI_ENABLE_REG		0xb078 -#define TXCLKESC_REG			0xb07c -#define DPHY_PARAM_REG			0xb080 -#define DBI_BW_CTRL_REG			0xb084 -#define CLK_LANE_SWT_REG		0xb088 - -/* - * MIPI Adapter registers - */ -#define MIPI_CONTROL_REG		0xb104 -#define MIPI_2X_CLOCK_BITS			((1 << 0) | (1 << 1)) -#define MIPI_DATA_ADDRESS_REG		0xb108 -#define MIPI_DATA_LENGTH_REG		0xb10C -#define MIPI_COMMAND_ADDRESS_REG	0xb110 -#define MIPI_COMMAND_LENGTH_REG		0xb114 -#define MIPI_READ_DATA_RETURN_REG0	0xb118 -#define MIPI_READ_DATA_RETURN_REG1	0xb11C -#define MIPI_READ_DATA_RETURN_REG2	0xb120 -#define MIPI_READ_DATA_RETURN_REG3	0xb124 -#define MIPI_READ_DATA_RETURN_REG4	0xb128 -#define MIPI_READ_DATA_RETURN_REG5	0xb12C -#define MIPI_READ_DATA_RETURN_REG6	0xb130 -#define MIPI_READ_DATA_RETURN_REG7	0xb134 -#define MIPI_READ_DATA_VALID_REG	0xb138 - -/* DBI COMMANDS */ -#define soft_reset			0x01 -/* - *	The display module performs a software reset. - *	Registers are written with their SW Reset default values. - */ -#define get_power_mode			0x0a -/* - *	The display module returns the current power mode - */ -#define get_address_mode		0x0b -/* - *	The display module returns the current status. - */ -#define get_pixel_format		0x0c -/* - *	This command gets the pixel format for the RGB image data - *	used by the interface. - */ -#define get_display_mode		0x0d -/* - *	The display module returns the Display Image Mode status. - */ -#define get_signal_mode			0x0e -/* - *	The display module returns the Display Signal Mode. - */ -#define get_diagnostic_result		0x0f -/* - *	The display module returns the self-diagnostic results following - *	a Sleep Out command. - */ -#define enter_sleep_mode		0x10 -/* - *	This command causes the display module to enter the Sleep mode. - *	In this mode, all unnecessary blocks inside the display module are - *	disabled except interface communication. This is the lowest power - *	mode the display module supports. - */ -#define exit_sleep_mode			0x11 -/* - *	This command causes the display module to exit Sleep mode. - *	All blocks inside the display module are enabled. - */ -#define enter_partial_mode		0x12 -/* - *	This command causes the display module to enter the Partial Display - *	Mode. The Partial Display Mode window is described by the - *	set_partial_area command. - */ -#define enter_normal_mode		0x13 -/* - *	This command causes the display module to enter the Normal mode. - *	Normal Mode is defined as Partial Display mode and Scroll mode are off - */ -#define exit_invert_mode		0x20 -/* - *	This command causes the display module to stop inverting the image - *	data on the display device. The frame memory contents remain unchanged. - *	No status bits are changed. - */ -#define enter_invert_mode		0x21 -/* - *	This command causes the display module to invert the image data only on - *	the display device. The frame memory contents remain unchanged. - *	No status bits are changed. - */ -#define set_gamma_curve			0x26 -/* - *	This command selects the desired gamma curve for the display device. - *	Four fixed gamma curves are defined in section DCS spec. - */ -#define set_display_off			0x28 -/* ************************************************************************* *\ -This command causes the display module to stop displaying the image data -on the display device. The frame memory contents remain unchanged. -No status bits are changed. -\* ************************************************************************* */ -#define set_display_on			0x29 -/* ************************************************************************* *\ -This command causes the display module to start displaying the image data -on the display device. The frame memory contents remain unchanged. -No status bits are changed. -\* ************************************************************************* */ -#define set_column_address		0x2a -/* - *	This command defines the column extent of the frame memory accessed by - *	the hostprocessor with the read_memory_continue and - *	write_memory_continue commands. - *	No status bits are changed. - */ -#define set_page_addr			0x2b -/* - *	This command defines the page extent of the frame memory accessed by - *	the host processor with the write_memory_continue and - *	read_memory_continue command. - *	No status bits are changed. - */ -#define write_mem_start			0x2c -/* - *	This command transfers image data from the host processor to the - *	display modules frame memory starting at the pixel location specified - *	by preceding set_column_address and set_page_address commands. - */ -#define set_partial_area		0x30 -/* - *	This command defines the Partial Display mode s display area. - *	There are two parameters associated with this command, the first - *	defines the Start Row (SR) and the second the End Row (ER). SR and ER - *	refer to the Frame Memory Line Pointer. - */ -#define set_scroll_area			0x33 -/* - *	This command defines the display modules Vertical Scrolling Area. - */ -#define set_tear_off			0x34 -/* - *	This command turns off the display modules Tearing Effect output - *	signal on the TE signal line. - */ -#define set_tear_on			0x35 -/* - *	This command turns on the display modules Tearing Effect output signal - *	on the TE signal line. - */ -#define set_address_mode		0x36 -/* - *	This command sets the data order for transfers from the host processor - *	to display modules frame memory,bits B[7:5] and B3, and from the - *	display modules frame memory to the display device, bits B[2:0] and B4. - */ -#define set_scroll_start		0x37 -/* - *	This command sets the start of the vertical scrolling area in the frame - *	memory. The vertical scrolling area is fully defined when this command - *	is used with the set_scroll_area command The set_scroll_start command - *	has one parameter, the Vertical Scroll Pointer. The VSP defines the - *	line in the frame memory that is written to the display device as the - *	first line of the vertical scroll area. - */ -#define exit_idle_mode			0x38 -/* - *	This command causes the display module to exit Idle mode. - */ -#define enter_idle_mode			0x39 -/* - *	This command causes the display module to enter Idle Mode. - *	In Idle Mode, color expression is reduced. Colors are shown on the - *	display device using the MSB of each of the R, G and B color - *	components in the frame memory - */ -#define set_pixel_format		0x3a -/* - *	This command sets the pixel format for the RGB image data used by the - *	interface. - *	Bits D[6:4]  DPI Pixel Format Definition - *	Bits D[2:0]  DBI Pixel Format Definition - *	Bits D7 and D3 are not used. - */ -#define DCS_PIXEL_FORMAT_3bpp		0x1 -#define DCS_PIXEL_FORMAT_8bpp		0x2 -#define DCS_PIXEL_FORMAT_12bpp		0x3 -#define DCS_PIXEL_FORMAT_16bpp		0x5 -#define DCS_PIXEL_FORMAT_18bpp		0x6 -#define DCS_PIXEL_FORMAT_24bpp		0x7 - -#define write_mem_cont			0x3c - -/* - *	This command transfers image data from the host processor to the - *	display module's frame memory continuing from the pixel location - *	following the previous write_memory_continue or write_memory_start - *	command. - */ -#define set_tear_scanline		0x44 -/* - *	This command turns on the display modules Tearing Effect output signal - *	on the TE signal line when the display module reaches line N. - */ -#define get_scanline			0x45 -/* - *	The display module returns the current scanline, N, used to update the - *	 display device. The total number of scanlines on a display device is - *	defined as VSYNC + VBP + VACT + VFP.The first scanline is defined as - *	the first line of V Sync and is denoted as Line 0. - *	When in Sleep Mode, the value returned by get_scanline is undefined. - */ - -/* MCS or Generic COMMANDS */ -/* MCS/generic data type */ -#define GEN_SHORT_WRITE_0	0x03  /* generic short write, no parameters */ -#define GEN_SHORT_WRITE_1	0x13  /* generic short write, 1 parameters */ -#define GEN_SHORT_WRITE_2	0x23  /* generic short write, 2 parameters */ -#define GEN_READ_0		0x04  /* generic read, no parameters */ -#define GEN_READ_1		0x14  /* generic read, 1 parameters */ -#define GEN_READ_2		0x24  /* generic read, 2 parameters */ -#define GEN_LONG_WRITE		0x29  /* generic long write */ -#define MCS_SHORT_WRITE_0	0x05  /* MCS short write, no parameters */ -#define MCS_SHORT_WRITE_1	0x15  /* MCS short write, 1 parameters */ -#define MCS_READ		0x06  /* MCS read, no parameters */ -#define MCS_LONG_WRITE		0x39  /* MCS long write */ -/* MCS/generic commands */ -/* TPO MCS */ -#define write_display_profile		0x50 -#define write_display_brightness	0x51 -#define write_ctrl_display		0x53 -#define write_ctrl_cabc			0x55 -  #define UI_IMAGE		0x01 -  #define STILL_IMAGE		0x02 -  #define MOVING_IMAGE		0x03 -#define write_hysteresis		0x57 -#define write_gamma_setting		0x58 -#define write_cabc_min_bright		0x5e -#define write_kbbc_profile		0x60 -/* TMD MCS */ -#define tmd_write_display_brightness 0x8c - -/* - *	This command is used to control ambient light, panel backlight - *	brightness and gamma settings. - */ -#define BRIGHT_CNTL_BLOCK_ON	(1 << 5) -#define AMBIENT_LIGHT_SENSE_ON	(1 << 4) -#define DISPLAY_DIMMING_ON	(1 << 3) -#define BACKLIGHT_ON		(1 << 2) -#define DISPLAY_BRIGHTNESS_AUTO	(1 << 1) -#define GAMMA_AUTO		(1 << 0) - -/* DCS Interface Pixel Formats */ -#define DCS_PIXEL_FORMAT_3BPP	0x1 -#define DCS_PIXEL_FORMAT_8BPP	0x2 -#define DCS_PIXEL_FORMAT_12BPP	0x3 -#define DCS_PIXEL_FORMAT_16BPP	0x5 -#define DCS_PIXEL_FORMAT_18BPP	0x6 -#define DCS_PIXEL_FORMAT_24BPP	0x7 -/* ONE PARAMETER READ DATA */ -#define addr_mode_data		0xfc -#define diag_res_data		0x00 -#define disp_mode_data		0x23 -#define pxl_fmt_data		0x77 -#define pwr_mode_data		0x74 -#define sig_mode_data		0x00 -/* TWO PARAMETERS READ DATA */ -#define scanline_data1		0xff -#define scanline_data2		0xff -#define NON_BURST_MODE_SYNC_PULSE	0x01	/* Non Burst Mode -						 * with Sync Pulse -						 */ -#define NON_BURST_MODE_SYNC_EVENTS	0x02	/* Non Burst Mode -						 * with Sync events -						 */ -#define BURST_MODE			0x03	/* Burst Mode */ -#define DBI_COMMAND_BUFFER_SIZE		0x240   /* 0x32 */    /* 0x120 */ -						/* Allocate at least -						 * 0x100 Byte with 32 -						 * byte alignment -						 */ -#define DBI_DATA_BUFFER_SIZE		0x120	/* Allocate at least -						 * 0x100 Byte with 32 -						 * byte alignment -						 */ -#define DBI_CB_TIME_OUT			0xFFFF - -#define GEN_FB_TIME_OUT			2000 - -#define SKU_83				0x01 -#define SKU_100				0x02 -#define SKU_100L			0x04 -#define SKU_BYPASS			0x08 - -/* Some handy macros for playing with bitfields. */ -#define PSB_MASK(high, low) (((1<<((high)-(low)+1))-1)<<(low)) -#define SET_FIELD(value, field) (((value) << field ## _SHIFT) & field ## _MASK) -#define GET_FIELD(word, field) (((word)  & field ## _MASK) >> field ## _SHIFT) - -#define _PIPE(pipe, a, b) ((a) + (pipe)*((b)-(a))) - -/* PCI config space */ - -#define SB_PCKT         0x02100 /* cedarview */ -# define SB_OPCODE_MASK                         PSB_MASK(31, 16) -# define SB_OPCODE_SHIFT                        16 -# define SB_OPCODE_READ                         0 -# define SB_OPCODE_WRITE                        1 -# define SB_DEST_MASK                           PSB_MASK(15, 8) -# define SB_DEST_SHIFT                          8 -# define SB_DEST_DPLL                           0x88 -# define SB_BYTE_ENABLE_MASK                    PSB_MASK(7, 4) -# define SB_BYTE_ENABLE_SHIFT                   4 -# define SB_BUSY                                (1 << 0) - - -/* 32-bit value read/written from the DPIO reg. */ -#define SB_DATA		0x02104 /* cedarview */ -/* 32-bit address of the DPIO reg to be read/written. */ -#define SB_ADDR		0x02108 /* cedarview */ -#define DPIO_CFG	0x02110 /* cedarview */ -# define DPIO_MODE_SELECT_1			(1 << 3) -# define DPIO_MODE_SELECT_0			(1 << 2) -# define DPIO_SFR_BYPASS			(1 << 1) -/* reset is active low */ -# define DPIO_CMN_RESET_N			(1 << 0) - -/* Cedarview sideband registers */ -#define _SB_M_A			0x8008 -#define _SB_M_B			0x8028 -#define SB_M(pipe) _PIPE(pipe, _SB_M_A, _SB_M_B) -# define SB_M_DIVIDER_MASK			(0xFF << 24) -# define SB_M_DIVIDER_SHIFT			24 - -#define _SB_N_VCO_A		0x8014 -#define _SB_N_VCO_B		0x8034 -#define SB_N_VCO(pipe) _PIPE(pipe, _SB_N_VCO_A, _SB_N_VCO_B) -#define SB_N_VCO_SEL_MASK			PSB_MASK(31, 30) -#define SB_N_VCO_SEL_SHIFT			30 -#define SB_N_DIVIDER_MASK			PSB_MASK(29, 26) -#define SB_N_DIVIDER_SHIFT			26 -#define SB_N_CB_TUNE_MASK			PSB_MASK(25, 24) -#define SB_N_CB_TUNE_SHIFT			24 - -#define _SB_REF_A		0x8018 -#define _SB_REF_B		0x8038 -#define SB_REF_SFR(pipe)	_PIPE(pipe, _SB_REF_A, _SB_REF_B) - -#define _SB_P_A			0x801c -#define _SB_P_B			0x803c -#define SB_P(pipe) _PIPE(pipe, _SB_P_A, _SB_P_B) -#define SB_P2_DIVIDER_MASK			PSB_MASK(31, 30) -#define SB_P2_DIVIDER_SHIFT			30 -#define SB_P2_10				0 /* HDMI, DP, DAC */ -#define SB_P2_5				1 /* DAC */ -#define SB_P2_14				2 /* LVDS single */ -#define SB_P2_7				3 /* LVDS double */ -#define SB_P1_DIVIDER_MASK			PSB_MASK(15, 12) -#define SB_P1_DIVIDER_SHIFT			12 - -#define PSB_LANE0		0x120 -#define PSB_LANE1		0x220 -#define PSB_LANE2		0x2320 -#define PSB_LANE3		0x2420 - -#define LANE_PLL_MASK		(0x7 << 20) -#define LANE_PLL_ENABLE		(0x3 << 20) - - -#endif diff --git a/drivers/staging/gma500/psb_intel_sdvo.c b/drivers/staging/gma500/psb_intel_sdvo.c deleted file mode 100644 index a4bad1af4b7..00000000000 --- a/drivers/staging/gma500/psb_intel_sdvo.c +++ /dev/null @@ -1,1293 +0,0 @@ -/* - * Copyright (c) 2006-2007 Intel Corporation - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - * Authors: - *	Eric Anholt <eric@anholt.net> - */ - -#include <linux/i2c.h> -#include <linux/delay.h> -/* #include <drm/drm_crtc.h> */ -#include <drm/drmP.h> -#include "psb_drv.h" -#include "psb_intel_drv.h" -#include "psb_intel_reg.h" -#include "psb_intel_sdvo_regs.h" - -struct psb_intel_sdvo_priv { -	struct psb_intel_i2c_chan *i2c_bus; -	int slaveaddr; -	int output_device; - -	u16 active_outputs; - -	struct psb_intel_sdvo_caps caps; -	int pixel_clock_min, pixel_clock_max; - -	int save_sdvo_mult; -	u16 save_active_outputs; -	struct psb_intel_sdvo_dtd save_input_dtd_1, save_input_dtd_2; -	struct psb_intel_sdvo_dtd save_output_dtd[16]; -	u32 save_SDVOX; -	u8 in_out_map[4]; - -	u8 by_input_wiring; -	u32 active_device; -}; - -/** - * Writes the SDVOB or SDVOC with the given value, but always writes both - * SDVOB and SDVOC to work around apparent hardware issues (according to - * comments in the BIOS). - */ -void psb_intel_sdvo_write_sdvox(struct psb_intel_output *psb_intel_output, -				u32 val) -{ -	struct drm_device *dev = psb_intel_output->base.dev; -	struct psb_intel_sdvo_priv *sdvo_priv = psb_intel_output->dev_priv; -	u32 bval = val, cval = val; -	int i; - -	if (sdvo_priv->output_device == SDVOB) -		cval = REG_READ(SDVOC); -	else -		bval = REG_READ(SDVOB); -	/* -	 * Write the registers twice for luck. Sometimes, -	 * writing them only once doesn't appear to 'stick'. -	 * The BIOS does this too. Yay, magic -	 */ -	for (i = 0; i < 2; i++) { -		REG_WRITE(SDVOB, bval); -		REG_READ(SDVOB); -		REG_WRITE(SDVOC, cval); -		REG_READ(SDVOC); -	} -} - -static bool psb_intel_sdvo_read_byte( -				struct psb_intel_output *psb_intel_output, -				u8 addr, u8 *ch) -{ -	struct psb_intel_sdvo_priv *sdvo_priv = psb_intel_output->dev_priv; -	u8 out_buf[2]; -	u8 buf[2]; -	int ret; - -	struct i2c_msg msgs[] = { -		{ -		 .addr = sdvo_priv->i2c_bus->slave_addr, -		 .flags = 0, -		 .len = 1, -		 .buf = out_buf, -		 }, -		{ -		 .addr = sdvo_priv->i2c_bus->slave_addr, -		 .flags = I2C_M_RD, -		 .len = 1, -		 .buf = buf, -		 } -	}; - -	out_buf[0] = addr; -	out_buf[1] = 0; - -	ret = i2c_transfer(&sdvo_priv->i2c_bus->adapter, msgs, 2); -	if (ret == 2) { -		*ch = buf[0]; -		return true; -	} - -	return false; -} - -static bool psb_intel_sdvo_write_byte( -			struct psb_intel_output *psb_intel_output, -			int addr, u8 ch) -{ -	u8 out_buf[2]; -	struct i2c_msg msgs[] = { -		{ -		 .addr = psb_intel_output->i2c_bus->slave_addr, -		 .flags = 0, -		 .len = 2, -		 .buf = out_buf, -		 } -	}; - -	out_buf[0] = addr; -	out_buf[1] = ch; - -	if (i2c_transfer(&psb_intel_output->i2c_bus->adapter, msgs, 1) == 1) -		return true; -	return false; -} - -#define SDVO_CMD_NAME_ENTRY(cmd) {cmd, #cmd} -/** Mapping of command numbers to names, for debug output */ -static const struct _sdvo_cmd_name { -	u8 cmd; -	char *name; -} sdvo_cmd_names[] = { -SDVO_CMD_NAME_ENTRY(SDVO_CMD_RESET), -	    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_DEVICE_CAPS), -	    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_FIRMWARE_REV), -	    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_TRAINED_INPUTS), -	    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ACTIVE_OUTPUTS), -	    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_ACTIVE_OUTPUTS), -	    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_IN_OUT_MAP), -	    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_IN_OUT_MAP), -	    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ATTACHED_DISPLAYS), -	    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HOT_PLUG_SUPPORT), -	    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_ACTIVE_HOT_PLUG), -	    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ACTIVE_HOT_PLUG), -	    SDVO_CMD_NAME_ENTRY -	    (SDVO_CMD_GET_INTERRUPT_EVENT_SOURCE), -	    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TARGET_INPUT), -	    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TARGET_OUTPUT), -	    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INPUT_TIMINGS_PART1), -	    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INPUT_TIMINGS_PART2), -	    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_INPUT_TIMINGS_PART1), -	    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_INPUT_TIMINGS_PART2), -	    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_INPUT_TIMINGS_PART1), -	    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_OUTPUT_TIMINGS_PART1), -	    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_OUTPUT_TIMINGS_PART2), -	    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OUTPUT_TIMINGS_PART1), -	    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OUTPUT_TIMINGS_PART2), -	    SDVO_CMD_NAME_ENTRY -	    (SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING), -	    SDVO_CMD_NAME_ENTRY -	    (SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1), -	    SDVO_CMD_NAME_ENTRY -	    (SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2), -	    SDVO_CMD_NAME_ENTRY -	    (SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE), -	    SDVO_CMD_NAME_ENTRY -	    (SDVO_CMD_GET_OUTPUT_PIXEL_CLOCK_RANGE), -	    SDVO_CMD_NAME_ENTRY -	    (SDVO_CMD_GET_SUPPORTED_CLOCK_RATE_MULTS), -	    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_CLOCK_RATE_MULT), -	    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_CLOCK_RATE_MULT), -	    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPPORTED_TV_FORMATS), -	    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_TV_FORMAT), -	    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TV_FORMAT), -	    SDVO_CMD_NAME_ENTRY -	    (SDVO_CMD_SET_TV_RESOLUTION_SUPPORT), -	    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_CONTROL_BUS_SWITCH),}; - -#define SDVO_NAME(dev_priv) \ -		 ((dev_priv)->output_device == SDVOB ? "SDVOB" : "SDVOC") -#define SDVO_PRIV(output)   ((struct psb_intel_sdvo_priv *) (output)->dev_priv) - -static void psb_intel_sdvo_write_cmd(struct psb_intel_output *psb_intel_output, -				     u8 cmd, -				     void *args, -				     int args_len) -{ -	struct psb_intel_sdvo_priv *sdvo_priv = psb_intel_output->dev_priv; -	int i; - -	if (0) { -		printk(KERN_DEBUG "%s: W: %02X ", SDVO_NAME(sdvo_priv), cmd); -		for (i = 0; i < args_len; i++) -			printk(KERN_CONT "%02X ", ((u8 *) args)[i]); -		for (; i < 8; i++) -			printk(KERN_CONT "   "); -		for (i = 0; -		     i < -		     sizeof(sdvo_cmd_names) / sizeof(sdvo_cmd_names[0]); -		     i++) { -			if (cmd == sdvo_cmd_names[i].cmd) { -				printk(KERN_CONT -					"(%s)", sdvo_cmd_names[i].name); -				break; -			} -		} -		if (i == -		    sizeof(sdvo_cmd_names) / sizeof(sdvo_cmd_names[0])) -			printk(KERN_CONT "(%02X)", cmd); -		printk(KERN_CONT "\n"); -	} - -	for (i = 0; i < args_len; i++) { -		psb_intel_sdvo_write_byte(psb_intel_output, -					SDVO_I2C_ARG_0 - i, -					((u8 *) args)[i]); -	} - -	psb_intel_sdvo_write_byte(psb_intel_output, SDVO_I2C_OPCODE, cmd); -} - -static const char *const cmd_status_names[] = { -	"Power on", -	"Success", -	"Not supported", -	"Invalid arg", -	"Pending", -	"Target not specified", -	"Scaling not supported" -}; - -static u8 psb_intel_sdvo_read_response( -				struct psb_intel_output *psb_intel_output, -				void *response, int response_len) -{ -	struct psb_intel_sdvo_priv *sdvo_priv = psb_intel_output->dev_priv; -	int i; -	u8 status; -	u8 retry = 50; - -	while (retry--) { -		/* Read the command response */ -		for (i = 0; i < response_len; i++) { -			psb_intel_sdvo_read_byte(psb_intel_output, -					     SDVO_I2C_RETURN_0 + i, -					     &((u8 *) response)[i]); -		} - -		/* read the return status */ -		psb_intel_sdvo_read_byte(psb_intel_output, -					 SDVO_I2C_CMD_STATUS, -					 &status); - -		if (0) { -			pr_debug("%s: R: ", SDVO_NAME(sdvo_priv)); -			for (i = 0; i < response_len; i++) -				printk(KERN_CONT "%02X ", ((u8 *) response)[i]); -			for (; i < 8; i++) -				printk("   "); -			if (status <= SDVO_CMD_STATUS_SCALING_NOT_SUPP) -				printk(KERN_CONT "(%s)", -					 cmd_status_names[status]); -			else -				printk(KERN_CONT "(??? %d)", status); -			printk(KERN_CONT "\n"); -		} - -		if (status != SDVO_CMD_STATUS_PENDING) -			return status; - -		mdelay(50); -	} - -	return status; -} - -int psb_intel_sdvo_get_pixel_multiplier(struct drm_display_mode *mode) -{ -	if (mode->clock >= 100000) -		return 1; -	else if (mode->clock >= 50000) -		return 2; -	else -		return 4; -} - -/** - * Don't check status code from this as it switches the bus back to the - * SDVO chips which defeats the purpose of doing a bus switch in the first - * place. - */ -void psb_intel_sdvo_set_control_bus_switch( -				struct psb_intel_output *psb_intel_output, -				u8 target) -{ -	psb_intel_sdvo_write_cmd(psb_intel_output, -				 SDVO_CMD_SET_CONTROL_BUS_SWITCH, -				 &target, -				 1); -} - -static bool psb_intel_sdvo_set_target_input( -				struct psb_intel_output *psb_intel_output, -				bool target_0, bool target_1) -{ -	struct psb_intel_sdvo_set_target_input_args targets = { 0 }; -	u8 status; - -	if (target_0 && target_1) -		return SDVO_CMD_STATUS_NOTSUPP; - -	if (target_1) -		targets.target_1 = 1; - -	psb_intel_sdvo_write_cmd(psb_intel_output, SDVO_CMD_SET_TARGET_INPUT, -			     &targets, sizeof(targets)); - -	status = psb_intel_sdvo_read_response(psb_intel_output, NULL, 0); - -	return status == SDVO_CMD_STATUS_SUCCESS; -} - -/** - * Return whether each input is trained. - * - * This function is making an assumption about the layout of the response, - * which should be checked against the docs. - */ -static bool psb_intel_sdvo_get_trained_inputs(struct psb_intel_output -					  *psb_intel_output, bool *input_1, -					  bool *input_2) -{ -	struct psb_intel_sdvo_get_trained_inputs_response response; -	u8 status; - -	psb_intel_sdvo_write_cmd(psb_intel_output, SDVO_CMD_GET_TRAINED_INPUTS, -			     NULL, 0); -	status = -	    psb_intel_sdvo_read_response(psb_intel_output, &response, -				     sizeof(response)); -	if (status != SDVO_CMD_STATUS_SUCCESS) -		return false; - -	*input_1 = response.input0_trained; -	*input_2 = response.input1_trained; -	return true; -} - -static bool psb_intel_sdvo_get_active_outputs(struct psb_intel_output -					  *psb_intel_output, u16 *outputs) -{ -	u8 status; - -	psb_intel_sdvo_write_cmd(psb_intel_output, SDVO_CMD_GET_ACTIVE_OUTPUTS, -			     NULL, 0); -	status = -	    psb_intel_sdvo_read_response(psb_intel_output, outputs, -				     sizeof(*outputs)); - -	return status == SDVO_CMD_STATUS_SUCCESS; -} - -static bool psb_intel_sdvo_set_active_outputs(struct psb_intel_output -					  *psb_intel_output, u16 outputs) -{ -	u8 status; - -	psb_intel_sdvo_write_cmd(psb_intel_output, SDVO_CMD_SET_ACTIVE_OUTPUTS, -			     &outputs, sizeof(outputs)); -	status = psb_intel_sdvo_read_response(psb_intel_output, NULL, 0); -	return status == SDVO_CMD_STATUS_SUCCESS; -} - -static bool psb_intel_sdvo_set_encoder_power_state(struct psb_intel_output -					       *psb_intel_output, int mode) -{ -	u8 status, state = SDVO_ENCODER_STATE_ON; - -	switch (mode) { -	case DRM_MODE_DPMS_ON: -		state = SDVO_ENCODER_STATE_ON; -		break; -	case DRM_MODE_DPMS_STANDBY: -		state = SDVO_ENCODER_STATE_STANDBY; -		break; -	case DRM_MODE_DPMS_SUSPEND: -		state = SDVO_ENCODER_STATE_SUSPEND; -		break; -	case DRM_MODE_DPMS_OFF: -		state = SDVO_ENCODER_STATE_OFF; -		break; -	} - -	psb_intel_sdvo_write_cmd(psb_intel_output, -			     SDVO_CMD_SET_ENCODER_POWER_STATE, &state, -			     sizeof(state)); -	status = psb_intel_sdvo_read_response(psb_intel_output, NULL, 0); - -	return status == SDVO_CMD_STATUS_SUCCESS; -} - -static bool psb_intel_sdvo_get_input_pixel_clock_range(struct psb_intel_output -						   *psb_intel_output, -						   int *clock_min, -						   int *clock_max) -{ -	struct psb_intel_sdvo_pixel_clock_range clocks; -	u8 status; - -	psb_intel_sdvo_write_cmd(psb_intel_output, -			     SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE, NULL, -			     0); - -	status = -	    psb_intel_sdvo_read_response(psb_intel_output, &clocks, -				     sizeof(clocks)); - -	if (status != SDVO_CMD_STATUS_SUCCESS) -		return false; - -	/* Convert the values from units of 10 kHz to kHz. */ -	*clock_min = clocks.min * 10; -	*clock_max = clocks.max * 10; - -	return true; -} - -static bool psb_intel_sdvo_set_target_output( -				struct psb_intel_output *psb_intel_output, -				u16 outputs) -{ -	u8 status; - -	psb_intel_sdvo_write_cmd(psb_intel_output, SDVO_CMD_SET_TARGET_OUTPUT, -			     &outputs, sizeof(outputs)); - -	status = psb_intel_sdvo_read_response(psb_intel_output, NULL, 0); -	return status == SDVO_CMD_STATUS_SUCCESS; -} - -static bool psb_intel_sdvo_get_timing(struct psb_intel_output *psb_intel_output, -				  u8 cmd, struct psb_intel_sdvo_dtd *dtd) -{ -	u8 status; - -	psb_intel_sdvo_write_cmd(psb_intel_output, cmd, NULL, 0); -	status = psb_intel_sdvo_read_response(psb_intel_output, &dtd->part1, -					  sizeof(dtd->part1)); -	if (status != SDVO_CMD_STATUS_SUCCESS) -		return false; - -	psb_intel_sdvo_write_cmd(psb_intel_output, cmd + 1, NULL, 0); -	status = psb_intel_sdvo_read_response(psb_intel_output, &dtd->part2, -					  sizeof(dtd->part2)); -	if (status != SDVO_CMD_STATUS_SUCCESS) -		return false; - -	return true; -} - -static bool psb_intel_sdvo_get_input_timing( -				struct psb_intel_output *psb_intel_output, -				struct psb_intel_sdvo_dtd *dtd) -{ -	return psb_intel_sdvo_get_timing(psb_intel_output, -				     SDVO_CMD_GET_INPUT_TIMINGS_PART1, -				     dtd); -} - -static bool psb_intel_sdvo_set_timing( -				struct psb_intel_output *psb_intel_output, -				u8 cmd, -				struct psb_intel_sdvo_dtd *dtd) -{ -	u8 status; - -	psb_intel_sdvo_write_cmd(psb_intel_output, cmd, &dtd->part1, -			     sizeof(dtd->part1)); -	status = psb_intel_sdvo_read_response(psb_intel_output, NULL, 0); -	if (status != SDVO_CMD_STATUS_SUCCESS) -		return false; - -	psb_intel_sdvo_write_cmd(psb_intel_output, cmd + 1, &dtd->part2, -			     sizeof(dtd->part2)); -	status = psb_intel_sdvo_read_response(psb_intel_output, NULL, 0); -	if (status != SDVO_CMD_STATUS_SUCCESS) -		return false; - -	return true; -} - -static bool psb_intel_sdvo_set_input_timing( -				struct psb_intel_output *psb_intel_output, -				struct psb_intel_sdvo_dtd *dtd) -{ -	return psb_intel_sdvo_set_timing(psb_intel_output, -				     SDVO_CMD_SET_INPUT_TIMINGS_PART1, -				     dtd); -} - -static bool psb_intel_sdvo_set_output_timing( -				struct psb_intel_output *psb_intel_output, -				struct psb_intel_sdvo_dtd *dtd) -{ -	return psb_intel_sdvo_set_timing(psb_intel_output, -				     SDVO_CMD_SET_OUTPUT_TIMINGS_PART1, -				     dtd); -} - -static int psb_intel_sdvo_get_clock_rate_mult(struct psb_intel_output -						*psb_intel_output) -{ -	u8 response, status; - -	psb_intel_sdvo_write_cmd(psb_intel_output, -				 SDVO_CMD_GET_CLOCK_RATE_MULT, -				 NULL, -				 0); - -	status = psb_intel_sdvo_read_response(psb_intel_output, &response, 1); - -	if (status != SDVO_CMD_STATUS_SUCCESS) { -		DRM_DEBUG("Couldn't get SDVO clock rate multiplier\n"); -		return SDVO_CLOCK_RATE_MULT_1X; -	} else { -		DRM_DEBUG("Current clock rate multiplier: %d\n", response); -	} - -	return response; -} - -static bool psb_intel_sdvo_set_clock_rate_mult(struct psb_intel_output -						*psb_intel_output, u8 val) -{ -	u8 status; - -	psb_intel_sdvo_write_cmd(psb_intel_output, -				SDVO_CMD_SET_CLOCK_RATE_MULT, -				&val, -				1); - -	status = psb_intel_sdvo_read_response(psb_intel_output, NULL, 0); -	if (status != SDVO_CMD_STATUS_SUCCESS) -		return false; - -	return true; -} - -static bool psb_sdvo_set_current_inoutmap(struct psb_intel_output *output, -					  u32 in0outputmask, -					  u32 in1outputmask) -{ -	u8 byArgs[4]; -	u8 status; -	int i; -	struct psb_intel_sdvo_priv *sdvo_priv = output->dev_priv; - -	/* Make all fields of the  args/ret to zero */ -	memset(byArgs, 0, sizeof(byArgs)); - -	/* Fill up the argument values; */ -	byArgs[0] = (u8) (in0outputmask & 0xFF); -	byArgs[1] = (u8) ((in0outputmask >> 8) & 0xFF); -	byArgs[2] = (u8) (in1outputmask & 0xFF); -	byArgs[3] = (u8) ((in1outputmask >> 8) & 0xFF); - - -	/*save inoutmap arg here*/ -	for (i = 0; i < 4; i++) -		sdvo_priv->in_out_map[i] = byArgs[0]; - -	psb_intel_sdvo_write_cmd(output, SDVO_CMD_SET_IN_OUT_MAP, byArgs, 4); -	status = psb_intel_sdvo_read_response(output, NULL, 0); - -	if (status != SDVO_CMD_STATUS_SUCCESS) -		return false; -	return true; -} - - -static void psb_intel_sdvo_set_iomap(struct psb_intel_output *output) -{ -	u32 dwCurrentSDVOIn0 = 0; -	u32 dwCurrentSDVOIn1 = 0; -	u32 dwDevMask = 0; - - -	struct psb_intel_sdvo_priv *sdvo_priv = output->dev_priv; - -	/* Please DO NOT change the following code. */ -	/* SDVOB_IN0 or SDVOB_IN1 ==> sdvo_in0 */ -	/* SDVOC_IN0 or SDVOC_IN1 ==> sdvo_in1 */ -	if (sdvo_priv->by_input_wiring & (SDVOB_IN0 | SDVOC_IN0)) { -		switch (sdvo_priv->active_device) { -		case SDVO_DEVICE_LVDS: -			dwDevMask = SDVO_OUTPUT_LVDS0 | SDVO_OUTPUT_LVDS1; -			break; -		case SDVO_DEVICE_TMDS: -			dwDevMask = SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1; -			break; -		case SDVO_DEVICE_TV: -			dwDevMask = -			SDVO_OUTPUT_YPRPB0 | SDVO_OUTPUT_SVID0 | -			SDVO_OUTPUT_CVBS0 | SDVO_OUTPUT_YPRPB1 | -			SDVO_OUTPUT_SVID1 | SDVO_OUTPUT_CVBS1 | -			SDVO_OUTPUT_SCART0 | SDVO_OUTPUT_SCART1; -			break; -		case SDVO_DEVICE_CRT: -			dwDevMask = SDVO_OUTPUT_RGB0 | SDVO_OUTPUT_RGB1; -			break; -		} -		dwCurrentSDVOIn0 = (sdvo_priv->active_outputs & dwDevMask); -	} else if (sdvo_priv->by_input_wiring & (SDVOB_IN1 | SDVOC_IN1)) { -		switch (sdvo_priv->active_device) { -		case SDVO_DEVICE_LVDS: -			dwDevMask = SDVO_OUTPUT_LVDS0 | SDVO_OUTPUT_LVDS1; -			break; -		case SDVO_DEVICE_TMDS: -			dwDevMask = SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1; -			break; -		case SDVO_DEVICE_TV: -			dwDevMask = -			SDVO_OUTPUT_YPRPB0 | SDVO_OUTPUT_SVID0 | -			SDVO_OUTPUT_CVBS0 | SDVO_OUTPUT_YPRPB1 | -			SDVO_OUTPUT_SVID1 | SDVO_OUTPUT_CVBS1 | -			SDVO_OUTPUT_SCART0 | SDVO_OUTPUT_SCART1; -			break; -		case SDVO_DEVICE_CRT: -			dwDevMask = SDVO_OUTPUT_RGB0 | SDVO_OUTPUT_RGB1; -			break; -		} -		dwCurrentSDVOIn1 = (sdvo_priv->active_outputs & dwDevMask); -	} - -	psb_sdvo_set_current_inoutmap(output, dwCurrentSDVOIn0, -					  dwCurrentSDVOIn1); -} - - -static bool psb_intel_sdvo_mode_fixup(struct drm_encoder *encoder, -				  struct drm_display_mode *mode, -				  struct drm_display_mode *adjusted_mode) -{ -	/* Make the CRTC code factor in the SDVO pixel multiplier.  The SDVO -	 * device will be told of the multiplier during mode_set. -	 */ -	adjusted_mode->clock *= psb_intel_sdvo_get_pixel_multiplier(mode); -	return true; -} - -static void psb_intel_sdvo_mode_set(struct drm_encoder *encoder, -				struct drm_display_mode *mode, -				struct drm_display_mode *adjusted_mode) -{ -	struct drm_device *dev = encoder->dev; -	struct drm_crtc *crtc = encoder->crtc; -	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); -	struct psb_intel_output *psb_intel_output = -					enc_to_psb_intel_output(encoder); -	struct psb_intel_sdvo_priv *sdvo_priv = psb_intel_output->dev_priv; -	u16 width, height; -	u16 h_blank_len, h_sync_len, v_blank_len, v_sync_len; -	u16 h_sync_offset, v_sync_offset; -	u32 sdvox; -	struct psb_intel_sdvo_dtd output_dtd; -	int sdvo_pixel_multiply; - -	if (!mode) -		return; - -	psb_intel_sdvo_set_target_output(psb_intel_output, 0); - -	width = mode->crtc_hdisplay; -	height = mode->crtc_vdisplay; - -	/* do some mode translations */ -	h_blank_len = mode->crtc_hblank_end - mode->crtc_hblank_start; -	h_sync_len = mode->crtc_hsync_end - mode->crtc_hsync_start; - -	v_blank_len = mode->crtc_vblank_end - mode->crtc_vblank_start; -	v_sync_len = mode->crtc_vsync_end - mode->crtc_vsync_start; - -	h_sync_offset = mode->crtc_hsync_start - mode->crtc_hblank_start; -	v_sync_offset = mode->crtc_vsync_start - mode->crtc_vblank_start; - -	output_dtd.part1.clock = mode->clock / 10; -	output_dtd.part1.h_active = width & 0xff; -	output_dtd.part1.h_blank = h_blank_len & 0xff; -	output_dtd.part1.h_high = (((width >> 8) & 0xf) << 4) | -	    ((h_blank_len >> 8) & 0xf); -	output_dtd.part1.v_active = height & 0xff; -	output_dtd.part1.v_blank = v_blank_len & 0xff; -	output_dtd.part1.v_high = (((height >> 8) & 0xf) << 4) | -	    ((v_blank_len >> 8) & 0xf); - -	output_dtd.part2.h_sync_off = h_sync_offset; -	output_dtd.part2.h_sync_width = h_sync_len & 0xff; -	output_dtd.part2.v_sync_off_width = (v_sync_offset & 0xf) << 4 | -	    (v_sync_len & 0xf); -	output_dtd.part2.sync_off_width_high = -	    ((h_sync_offset & 0x300) >> 2) | ((h_sync_len & 0x300) >> 4) | -	    ((v_sync_offset & 0x30) >> 2) | ((v_sync_len & 0x30) >> 4); - -	output_dtd.part2.dtd_flags = 0x18; -	if (mode->flags & DRM_MODE_FLAG_PHSYNC) -		output_dtd.part2.dtd_flags |= 0x2; -	if (mode->flags & DRM_MODE_FLAG_PVSYNC) -		output_dtd.part2.dtd_flags |= 0x4; - -	output_dtd.part2.sdvo_flags = 0; -	output_dtd.part2.v_sync_off_high = v_sync_offset & 0xc0; -	output_dtd.part2.reserved = 0; - -	/* Set the output timing to the screen */ -	psb_intel_sdvo_set_target_output(psb_intel_output, -				     sdvo_priv->active_outputs); - -	/* Set the input timing to the screen. Assume always input 0. */ -	psb_intel_sdvo_set_target_input(psb_intel_output, true, false); - -	psb_intel_sdvo_set_output_timing(psb_intel_output, &output_dtd); - -	/* We would like to use i830_sdvo_create_preferred_input_timing() to -	 * provide the device with a timing it can support, if it supports that -	 * feature.  However, presumably we would need to adjust the CRTC to -	 * output the preferred timing, and we don't support that currently. -	 */ -	psb_intel_sdvo_set_input_timing(psb_intel_output, &output_dtd); - -	switch (psb_intel_sdvo_get_pixel_multiplier(mode)) { -	case 1: -		psb_intel_sdvo_set_clock_rate_mult(psb_intel_output, -					       SDVO_CLOCK_RATE_MULT_1X); -		break; -	case 2: -		psb_intel_sdvo_set_clock_rate_mult(psb_intel_output, -					       SDVO_CLOCK_RATE_MULT_2X); -		break; -	case 4: -		psb_intel_sdvo_set_clock_rate_mult(psb_intel_output, -					       SDVO_CLOCK_RATE_MULT_4X); -		break; -	} - -	/* Set the SDVO control regs. */ -	sdvox = REG_READ(sdvo_priv->output_device); -	switch (sdvo_priv->output_device) { -	case SDVOB: -		sdvox &= SDVOB_PRESERVE_MASK; -		break; -	case SDVOC: -		sdvox &= SDVOC_PRESERVE_MASK; -		break; -	} -	sdvox |= (9 << 19) | SDVO_BORDER_ENABLE; -	if (psb_intel_crtc->pipe == 1) -		sdvox |= SDVO_PIPE_B_SELECT; - -	sdvo_pixel_multiply = psb_intel_sdvo_get_pixel_multiplier(mode); - -	psb_intel_sdvo_write_sdvox(psb_intel_output, sdvox); - -	 psb_intel_sdvo_set_iomap(psb_intel_output); -} - -static void psb_intel_sdvo_dpms(struct drm_encoder *encoder, int mode) -{ -	struct drm_device *dev = encoder->dev; -	struct psb_intel_output *psb_intel_output = -					enc_to_psb_intel_output(encoder); -	struct psb_intel_sdvo_priv *sdvo_priv = psb_intel_output->dev_priv; -	u32 temp; - -	if (mode != DRM_MODE_DPMS_ON) { -		psb_intel_sdvo_set_active_outputs(psb_intel_output, 0); -		if (0) -			psb_intel_sdvo_set_encoder_power_state( -							psb_intel_output, -							mode); - -		if (mode == DRM_MODE_DPMS_OFF) { -			temp = REG_READ(sdvo_priv->output_device); -			if ((temp & SDVO_ENABLE) != 0) { -				psb_intel_sdvo_write_sdvox(psb_intel_output, -						       temp & -						       ~SDVO_ENABLE); -			} -		} -	} else { -		bool input1, input2; -		int i; -		u8 status; - -		temp = REG_READ(sdvo_priv->output_device); -		if ((temp & SDVO_ENABLE) == 0) -			psb_intel_sdvo_write_sdvox(psb_intel_output, -					       temp | SDVO_ENABLE); -		for (i = 0; i < 2; i++) -			psb_intel_wait_for_vblank(dev); - -		status = -		    psb_intel_sdvo_get_trained_inputs(psb_intel_output, -							&input1, -							&input2); - - -		/* Warn if the device reported failure to sync. -		 * A lot of SDVO devices fail to notify of sync, but it's -		 * a given it the status is a success, we succeeded. -		 */ -		if (status == SDVO_CMD_STATUS_SUCCESS && !input1) { -			DRM_DEBUG -			    ("First %s output reported failure to sync\n", -			     SDVO_NAME(sdvo_priv)); -		} - -		if (0) -			psb_intel_sdvo_set_encoder_power_state( -							psb_intel_output, -							mode); -		psb_intel_sdvo_set_active_outputs(psb_intel_output, -					      sdvo_priv->active_outputs); -	} -	return; -} - -static void psb_intel_sdvo_save(struct drm_connector *connector) -{ -	struct drm_device *dev = connector->dev; -	struct psb_intel_output *psb_intel_output = -					to_psb_intel_output(connector); -	struct psb_intel_sdvo_priv *sdvo_priv = psb_intel_output->dev_priv; -	/*int o;*/ - -	sdvo_priv->save_sdvo_mult = -	    psb_intel_sdvo_get_clock_rate_mult(psb_intel_output); -	psb_intel_sdvo_get_active_outputs(psb_intel_output, -				      &sdvo_priv->save_active_outputs); - -	if (sdvo_priv->caps.sdvo_inputs_mask & 0x1) { -		psb_intel_sdvo_set_target_input(psb_intel_output, -						true, -						false); -		psb_intel_sdvo_get_input_timing(psb_intel_output, -					    &sdvo_priv->save_input_dtd_1); -	} - -	if (sdvo_priv->caps.sdvo_inputs_mask & 0x2) { -		psb_intel_sdvo_set_target_input(psb_intel_output, -						false, -						true); -		psb_intel_sdvo_get_input_timing(psb_intel_output, -					    &sdvo_priv->save_input_dtd_2); -	} -	sdvo_priv->save_SDVOX = REG_READ(sdvo_priv->output_device); - -	/*TODO: save the in_out_map state*/ -} - -static void psb_intel_sdvo_restore(struct drm_connector *connector) -{ -	struct drm_device *dev = connector->dev; -	struct psb_intel_output *psb_intel_output = -					to_psb_intel_output(connector); -	struct psb_intel_sdvo_priv *sdvo_priv = psb_intel_output->dev_priv; -	/*int o;*/ -	int i; -	bool input1, input2; -	u8 status; - -	psb_intel_sdvo_set_active_outputs(psb_intel_output, 0); - -	if (sdvo_priv->caps.sdvo_inputs_mask & 0x1) { -		psb_intel_sdvo_set_target_input(psb_intel_output, true, false); -		psb_intel_sdvo_set_input_timing(psb_intel_output, -					    &sdvo_priv->save_input_dtd_1); -	} - -	if (sdvo_priv->caps.sdvo_inputs_mask & 0x2) { -		psb_intel_sdvo_set_target_input(psb_intel_output, false, true); -		psb_intel_sdvo_set_input_timing(psb_intel_output, -					    &sdvo_priv->save_input_dtd_2); -	} - -	psb_intel_sdvo_set_clock_rate_mult(psb_intel_output, -				       sdvo_priv->save_sdvo_mult); - -	REG_WRITE(sdvo_priv->output_device, sdvo_priv->save_SDVOX); - -	if (sdvo_priv->save_SDVOX & SDVO_ENABLE) { -		for (i = 0; i < 2; i++) -			psb_intel_wait_for_vblank(dev); -		status = -		    psb_intel_sdvo_get_trained_inputs(psb_intel_output, -							&input1, -							&input2); -		if (status == SDVO_CMD_STATUS_SUCCESS && !input1) -			DRM_DEBUG -			    ("First %s output reported failure to sync\n", -			     SDVO_NAME(sdvo_priv)); -	} - -	psb_intel_sdvo_set_active_outputs(psb_intel_output, -				      sdvo_priv->save_active_outputs); - -	/*TODO: restore in_out_map*/ -	psb_intel_sdvo_write_cmd(psb_intel_output, -				 SDVO_CMD_SET_IN_OUT_MAP, -				 sdvo_priv->in_out_map, -				 4); - -	psb_intel_sdvo_read_response(psb_intel_output, NULL, 0); -} - -static int psb_intel_sdvo_mode_valid(struct drm_connector *connector, -				 struct drm_display_mode *mode) -{ -	struct psb_intel_output *psb_intel_output = -				to_psb_intel_output(connector); -	struct psb_intel_sdvo_priv *sdvo_priv = psb_intel_output->dev_priv; - -	if (mode->flags & DRM_MODE_FLAG_DBLSCAN) -		return MODE_NO_DBLESCAN; - -	if (sdvo_priv->pixel_clock_min > mode->clock) -		return MODE_CLOCK_LOW; - -	if (sdvo_priv->pixel_clock_max < mode->clock) -		return MODE_CLOCK_HIGH; - -	return MODE_OK; -} - -static bool psb_intel_sdvo_get_capabilities( -				struct psb_intel_output *psb_intel_output, -				struct psb_intel_sdvo_caps *caps) -{ -	u8 status; - -	psb_intel_sdvo_write_cmd(psb_intel_output, -				 SDVO_CMD_GET_DEVICE_CAPS, -				 NULL, -				 0); -	status = psb_intel_sdvo_read_response(psb_intel_output, -						caps, -						sizeof(*caps)); -	if (status != SDVO_CMD_STATUS_SUCCESS) -		return false; - -	return true; -} - -struct drm_connector *psb_intel_sdvo_find(struct drm_device *dev, int sdvoB) -{ -	struct drm_connector *connector = NULL; -	struct psb_intel_output *iout = NULL; -	struct psb_intel_sdvo_priv *sdvo; - -	/* find the sdvo connector */ -	list_for_each_entry(connector, &dev->mode_config.connector_list, -			    head) { -		iout = to_psb_intel_output(connector); - -		if (iout->type != INTEL_OUTPUT_SDVO) -			continue; - -		sdvo = iout->dev_priv; - -		if (sdvo->output_device == SDVOB && sdvoB) -			return connector; - -		if (sdvo->output_device == SDVOC && !sdvoB) -			return connector; - -	} - -	return NULL; -} - -int psb_intel_sdvo_supports_hotplug(struct drm_connector *connector) -{ -	u8 response[2]; -	u8 status; -	struct psb_intel_output *psb_intel_output; - -	if (!connector) -		return 0; - -	psb_intel_output = to_psb_intel_output(connector); - -	psb_intel_sdvo_write_cmd(psb_intel_output, -				 SDVO_CMD_GET_HOT_PLUG_SUPPORT, -				 NULL, -				 0); -	status = psb_intel_sdvo_read_response(psb_intel_output, -						&response, -						2); - -	if (response[0] != 0) -		return 1; - -	return 0; -} - -void psb_intel_sdvo_set_hotplug(struct drm_connector *connector, int on) -{ -	u8 response[2]; -	u8 status; -	struct psb_intel_output *psb_intel_output = -					to_psb_intel_output(connector); - -	psb_intel_sdvo_write_cmd(psb_intel_output, -				 SDVO_CMD_GET_ACTIVE_HOT_PLUG, -				 NULL, -				 0); -	psb_intel_sdvo_read_response(psb_intel_output, &response, 2); - -	if (on) { -		psb_intel_sdvo_write_cmd(psb_intel_output, -				     SDVO_CMD_GET_HOT_PLUG_SUPPORT, NULL, -				     0); -		status = psb_intel_sdvo_read_response(psb_intel_output, -						      &response, -						      2); - -		psb_intel_sdvo_write_cmd(psb_intel_output, -				     SDVO_CMD_SET_ACTIVE_HOT_PLUG, -				     &response, 2); -	} else { -		response[0] = 0; -		response[1] = 0; -		psb_intel_sdvo_write_cmd(psb_intel_output, -				     SDVO_CMD_SET_ACTIVE_HOT_PLUG, -				     &response, 2); -	} - -	psb_intel_sdvo_write_cmd(psb_intel_output, -				 SDVO_CMD_GET_ACTIVE_HOT_PLUG, -				 NULL, -				 0); -	psb_intel_sdvo_read_response(psb_intel_output, &response, 2); -} - -static enum drm_connector_status psb_intel_sdvo_detect(struct drm_connector -						   *connector, bool force) -{ -	u8 response[2]; -	u8 status; -	struct psb_intel_output *psb_intel_output = -					to_psb_intel_output(connector); - -	psb_intel_sdvo_write_cmd(psb_intel_output, -				 SDVO_CMD_GET_ATTACHED_DISPLAYS, -				 NULL, -				 0); -	status = psb_intel_sdvo_read_response(psb_intel_output, &response, 2); - -	DRM_DEBUG("SDVO response %d %d\n", response[0], response[1]); -	if ((response[0] != 0) || (response[1] != 0)) -		return connector_status_connected; -	else -		return connector_status_disconnected; -} - -static int psb_intel_sdvo_get_modes(struct drm_connector *connector) -{ -	struct psb_intel_output *psb_intel_output = -					to_psb_intel_output(connector); - -	/* set the bus switch and get the modes */ -	psb_intel_sdvo_set_control_bus_switch(psb_intel_output, -					  SDVO_CONTROL_BUS_DDC2); -	psb_intel_ddc_get_modes(psb_intel_output); - -	if (list_empty(&connector->probed_modes)) -		return 0; -	return 1; -} - -static void psb_intel_sdvo_destroy(struct drm_connector *connector) -{ -	struct psb_intel_output *psb_intel_output = -				to_psb_intel_output(connector); - -	if (psb_intel_output->i2c_bus) -		psb_intel_i2c_destroy(psb_intel_output->i2c_bus); -	drm_sysfs_connector_remove(connector); -	drm_connector_cleanup(connector); -	kfree(psb_intel_output); -} - -static const struct drm_encoder_helper_funcs psb_intel_sdvo_helper_funcs = { -	.dpms = psb_intel_sdvo_dpms, -	.mode_fixup = psb_intel_sdvo_mode_fixup, -	.prepare = psb_intel_encoder_prepare, -	.mode_set = psb_intel_sdvo_mode_set, -	.commit = psb_intel_encoder_commit, -}; - -static const struct drm_connector_funcs psb_intel_sdvo_connector_funcs = { -	.dpms = drm_helper_connector_dpms, -	.save = psb_intel_sdvo_save, -	.restore = psb_intel_sdvo_restore, -	.detect = psb_intel_sdvo_detect, -	.fill_modes = drm_helper_probe_single_connector_modes, -	.destroy = psb_intel_sdvo_destroy, -}; - -static const struct drm_connector_helper_funcs -				psb_intel_sdvo_connector_helper_funcs = { -	.get_modes = psb_intel_sdvo_get_modes, -	.mode_valid = psb_intel_sdvo_mode_valid, -	.best_encoder = psb_intel_best_encoder, -}; - -void psb_intel_sdvo_enc_destroy(struct drm_encoder *encoder) -{ -	drm_encoder_cleanup(encoder); -} - -static const struct drm_encoder_funcs psb_intel_sdvo_enc_funcs = { -	.destroy = psb_intel_sdvo_enc_destroy, -}; - - -void psb_intel_sdvo_init(struct drm_device *dev, int output_device) -{ -	struct drm_connector *connector; -	struct psb_intel_output *psb_intel_output; -	struct psb_intel_sdvo_priv *sdvo_priv; -	struct psb_intel_i2c_chan *i2cbus = NULL; -	int connector_type; -	u8 ch[0x40]; -	int i; -	int encoder_type, output_id; - -	psb_intel_output = -	    kcalloc(sizeof(struct psb_intel_output) + -		    sizeof(struct psb_intel_sdvo_priv), 1, GFP_KERNEL); -	if (!psb_intel_output) -		return; - -	connector = &psb_intel_output->base; - -	drm_connector_init(dev, connector, &psb_intel_sdvo_connector_funcs, -			   DRM_MODE_CONNECTOR_Unknown); -	drm_connector_helper_add(connector, -				 &psb_intel_sdvo_connector_helper_funcs); -	sdvo_priv = (struct psb_intel_sdvo_priv *) (psb_intel_output + 1); -	psb_intel_output->type = INTEL_OUTPUT_SDVO; - -	connector->interlace_allowed = 0; -	connector->doublescan_allowed = 0; - -	/* setup the DDC bus. */ -	if (output_device == SDVOB) -		i2cbus = -		    psb_intel_i2c_create(dev, GPIOE, "SDVOCTRL_E for SDVOB"); -	else -		i2cbus = -		    psb_intel_i2c_create(dev, GPIOE, "SDVOCTRL_E for SDVOC"); - -	if (!i2cbus) -		goto err_connector; - -	sdvo_priv->i2c_bus = i2cbus; - -	if (output_device == SDVOB) { -		output_id = 1; -		sdvo_priv->by_input_wiring = SDVOB_IN0; -		sdvo_priv->i2c_bus->slave_addr = 0x38; -	} else { -		output_id = 2; -		sdvo_priv->i2c_bus->slave_addr = 0x39; -	} - -	sdvo_priv->output_device = output_device; -	psb_intel_output->i2c_bus = i2cbus; -	psb_intel_output->dev_priv = sdvo_priv; - - -	/* Read the regs to test if we can talk to the device */ -	for (i = 0; i < 0x40; i++) { -		if (!psb_intel_sdvo_read_byte(psb_intel_output, i, &ch[i])) { -			dev_dbg(dev->dev, "No SDVO device found on SDVO%c\n", -				  output_device == SDVOB ? 'B' : 'C'); -			goto err_i2c; -		} -	} - -	psb_intel_sdvo_get_capabilities(psb_intel_output, &sdvo_priv->caps); - -	memset(&sdvo_priv->active_outputs, 0, -	       sizeof(sdvo_priv->active_outputs)); - -	/* TODO, CVBS, SVID, YPRPB & SCART outputs. */ -	if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_RGB0) { -		sdvo_priv->active_outputs = SDVO_OUTPUT_RGB0; -		sdvo_priv->active_device = SDVO_DEVICE_CRT; -		connector->display_info.subpixel_order = -		    SubPixelHorizontalRGB; -		encoder_type = DRM_MODE_ENCODER_DAC; -		connector_type = DRM_MODE_CONNECTOR_VGA; -	} else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_RGB1) { -		sdvo_priv->active_outputs = SDVO_OUTPUT_RGB1; -		sdvo_priv->active_outputs = SDVO_DEVICE_CRT; -		connector->display_info.subpixel_order = -		    SubPixelHorizontalRGB; -		encoder_type = DRM_MODE_ENCODER_DAC; -		connector_type = DRM_MODE_CONNECTOR_VGA; -	} else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_TMDS0) { -		sdvo_priv->active_outputs = SDVO_OUTPUT_TMDS0; -		sdvo_priv->active_device = SDVO_DEVICE_TMDS; -		connector->display_info.subpixel_order = -		    SubPixelHorizontalRGB; -		encoder_type = DRM_MODE_ENCODER_TMDS; -		connector_type = DRM_MODE_CONNECTOR_DVID; -	} else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_TMDS1) { -		sdvo_priv->active_outputs = SDVO_OUTPUT_TMDS1; -		sdvo_priv->active_device = SDVO_DEVICE_TMDS; -		connector->display_info.subpixel_order = -		    SubPixelHorizontalRGB; -		encoder_type = DRM_MODE_ENCODER_TMDS; -		connector_type = DRM_MODE_CONNECTOR_DVID; -	} else { -		unsigned char bytes[2]; - -		memcpy(bytes, &sdvo_priv->caps.output_flags, 2); -		dev_dbg(dev->dev, "%s: No active RGB or TMDS outputs (0x%02x%02x)\n", -		     SDVO_NAME(sdvo_priv), bytes[0], bytes[1]); -		goto err_i2c; -	} - -	drm_encoder_init(dev, &psb_intel_output->enc, &psb_intel_sdvo_enc_funcs, -			 encoder_type); -	drm_encoder_helper_add(&psb_intel_output->enc, -			       &psb_intel_sdvo_helper_funcs); -	connector->connector_type = connector_type; - -	drm_mode_connector_attach_encoder(&psb_intel_output->base, -					  &psb_intel_output->enc); -	drm_sysfs_connector_add(connector); - -	/* Set the input timing to the screen. Assume always input 0. */ -	psb_intel_sdvo_set_target_input(psb_intel_output, true, false); - -	psb_intel_sdvo_get_input_pixel_clock_range(psb_intel_output, -					       &sdvo_priv->pixel_clock_min, -					       &sdvo_priv-> -					       pixel_clock_max); - - -	dev_dbg(dev->dev, "%s device VID/DID: %02X:%02X.%02X, " -		  "clock range %dMHz - %dMHz, " -		  "input 1: %c, input 2: %c, " -		  "output 1: %c, output 2: %c\n", -		  SDVO_NAME(sdvo_priv), -		  sdvo_priv->caps.vendor_id, sdvo_priv->caps.device_id, -		  sdvo_priv->caps.device_rev_id, -		  sdvo_priv->pixel_clock_min / 1000, -		  sdvo_priv->pixel_clock_max / 1000, -		  (sdvo_priv->caps.sdvo_inputs_mask & 0x1) ? 'Y' : 'N', -		  (sdvo_priv->caps.sdvo_inputs_mask & 0x2) ? 'Y' : 'N', -		  /* check currently supported outputs */ -		  sdvo_priv->caps.output_flags & -		  (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_RGB0) ? 'Y' : 'N', -		  sdvo_priv->caps.output_flags & -		  (SDVO_OUTPUT_TMDS1 | SDVO_OUTPUT_RGB1) ? 'Y' : 'N'); - -	psb_intel_output->ddc_bus = i2cbus; - -	return; - -err_i2c: -	psb_intel_i2c_destroy(psb_intel_output->i2c_bus); -err_connector: -	drm_connector_cleanup(connector); -	kfree(psb_intel_output); - -	return; -} diff --git a/drivers/staging/gma500/psb_intel_sdvo_regs.h b/drivers/staging/gma500/psb_intel_sdvo_regs.h deleted file mode 100644 index 96862ea65ab..00000000000 --- a/drivers/staging/gma500/psb_intel_sdvo_regs.h +++ /dev/null @@ -1,338 +0,0 @@ -/* - * SDVO command definitions and structures. - * - * Copyright (c) 2008, Intel Corporation - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - * Authors: - *	Eric Anholt <eric@anholt.net> - */ - -#define SDVO_OUTPUT_FIRST   (0) -#define SDVO_OUTPUT_TMDS0   (1 << 0) -#define SDVO_OUTPUT_RGB0    (1 << 1) -#define SDVO_OUTPUT_CVBS0   (1 << 2) -#define SDVO_OUTPUT_SVID0   (1 << 3) -#define SDVO_OUTPUT_YPRPB0  (1 << 4) -#define SDVO_OUTPUT_SCART0  (1 << 5) -#define SDVO_OUTPUT_LVDS0   (1 << 6) -#define SDVO_OUTPUT_TMDS1   (1 << 8) -#define SDVO_OUTPUT_RGB1    (1 << 9) -#define SDVO_OUTPUT_CVBS1   (1 << 10) -#define SDVO_OUTPUT_SVID1   (1 << 11) -#define SDVO_OUTPUT_YPRPB1  (1 << 12) -#define SDVO_OUTPUT_SCART1  (1 << 13) -#define SDVO_OUTPUT_LVDS1   (1 << 14) -#define SDVO_OUTPUT_LAST    (14) - -struct psb_intel_sdvo_caps { -	u8 vendor_id; -	u8 device_id; -	u8 device_rev_id; -	u8 sdvo_version_major; -	u8 sdvo_version_minor; -	unsigned int sdvo_inputs_mask:2; -	unsigned int smooth_scaling:1; -	unsigned int sharp_scaling:1; -	unsigned int up_scaling:1; -	unsigned int down_scaling:1; -	unsigned int stall_support:1; -	unsigned int pad:1; -	u16 output_flags; -} __packed; - -/** This matches the EDID DTD structure, more or less */ -struct psb_intel_sdvo_dtd { -	struct { -		u16 clock;	/**< pixel clock, in 10kHz units */ -		u8 h_active;	/**< lower 8 bits (pixels) */ -		u8 h_blank;	/**< lower 8 bits (pixels) */ -		u8 h_high;	/**< upper 4 bits each h_active, h_blank */ -		u8 v_active;	/**< lower 8 bits (lines) */ -		u8 v_blank;	/**< lower 8 bits (lines) */ -		u8 v_high;	/**< upper 4 bits each v_active, v_blank */ -	} part1; - -	struct { -		u8 h_sync_off; -			/**< lower 8 bits, from hblank start */ -		u8 h_sync_width;/**< lower 8 bits (pixels) */ -	/** lower 4 bits each vsync offset, vsync width */ -		u8 v_sync_off_width; -	/** -	 * 2 high bits of hsync offset, 2 high bits of hsync width, -	 * bits 4-5 of vsync offset, and 2 high bits of vsync width. -	 */ -		u8 sync_off_width_high; -		u8 dtd_flags; -		u8 sdvo_flags; -	/** bits 6-7 of vsync offset at bits 6-7 */ -		u8 v_sync_off_high; -		u8 reserved; -	} part2; -} __packed; - -struct psb_intel_sdvo_pixel_clock_range { -	u16 min;		/**< pixel clock, in 10kHz units */ -	u16 max;		/**< pixel clock, in 10kHz units */ -} __packed; - -struct psb_intel_sdvo_preferred_input_timing_args { -	u16 clock; -	u16 width; -	u16 height; -} __packed; - -/* I2C registers for SDVO */ -#define SDVO_I2C_ARG_0				0x07 -#define SDVO_I2C_ARG_1				0x06 -#define SDVO_I2C_ARG_2				0x05 -#define SDVO_I2C_ARG_3				0x04 -#define SDVO_I2C_ARG_4				0x03 -#define SDVO_I2C_ARG_5				0x02 -#define SDVO_I2C_ARG_6				0x01 -#define SDVO_I2C_ARG_7				0x00 -#define SDVO_I2C_OPCODE				0x08 -#define SDVO_I2C_CMD_STATUS			0x09 -#define SDVO_I2C_RETURN_0			0x0a -#define SDVO_I2C_RETURN_1			0x0b -#define SDVO_I2C_RETURN_2			0x0c -#define SDVO_I2C_RETURN_3			0x0d -#define SDVO_I2C_RETURN_4			0x0e -#define SDVO_I2C_RETURN_5			0x0f -#define SDVO_I2C_RETURN_6			0x10 -#define SDVO_I2C_RETURN_7			0x11 -#define SDVO_I2C_VENDOR_BEGIN			0x20 - -/* Status results */ -#define SDVO_CMD_STATUS_POWER_ON		0x0 -#define SDVO_CMD_STATUS_SUCCESS			0x1 -#define SDVO_CMD_STATUS_NOTSUPP			0x2 -#define SDVO_CMD_STATUS_INVALID_ARG		0x3 -#define SDVO_CMD_STATUS_PENDING			0x4 -#define SDVO_CMD_STATUS_TARGET_NOT_SPECIFIED	0x5 -#define SDVO_CMD_STATUS_SCALING_NOT_SUPP	0x6 - -/* SDVO commands, argument/result registers */ - -#define SDVO_CMD_RESET					0x01 - -/** Returns a struct psb_intel_sdvo_caps */ -#define SDVO_CMD_GET_DEVICE_CAPS			0x02 - -#define SDVO_CMD_GET_FIRMWARE_REV			0x86 -# define SDVO_DEVICE_FIRMWARE_MINOR			SDVO_I2C_RETURN_0 -# define SDVO_DEVICE_FIRMWARE_MAJOR			SDVO_I2C_RETURN_1 -# define SDVO_DEVICE_FIRMWARE_PATCH			SDVO_I2C_RETURN_2 - -/** - * Reports which inputs are trained (managed to sync). - * - * Devices must have trained within 2 vsyncs of a mode change. - */ -#define SDVO_CMD_GET_TRAINED_INPUTS			0x03 -struct psb_intel_sdvo_get_trained_inputs_response { -	unsigned int input0_trained:1; -	unsigned int input1_trained:1; -	unsigned int pad:6; -} __packed; - -/** Returns a struct psb_intel_sdvo_output_flags of active outputs. */ -#define SDVO_CMD_GET_ACTIVE_OUTPUTS			0x04 - -/** - * Sets the current set of active outputs. - * - * Takes a struct psb_intel_sdvo_output_flags. - * Must be preceded by a SET_IN_OUT_MAP - * on multi-output devices. - */ -#define SDVO_CMD_SET_ACTIVE_OUTPUTS			0x05 - -/** - * Returns the current mapping of SDVO inputs to outputs on the device. - * - * Returns two struct psb_intel_sdvo_output_flags structures. - */ -#define SDVO_CMD_GET_IN_OUT_MAP				0x06 - -/** - * Sets the current mapping of SDVO inputs to outputs on the device. - * - * Takes two struct i380_sdvo_output_flags structures. - */ -#define SDVO_CMD_SET_IN_OUT_MAP				0x07 - -/** - * Returns a struct psb_intel_sdvo_output_flags of attached displays. - */ -#define SDVO_CMD_GET_ATTACHED_DISPLAYS			0x0b - -/** - * Returns a struct psb_intel_sdvo_ouptut_flags of displays supporting hot plugging. - */ -#define SDVO_CMD_GET_HOT_PLUG_SUPPORT			0x0c - -/** - * Takes a struct psb_intel_sdvo_output_flags. - */ -#define SDVO_CMD_SET_ACTIVE_HOT_PLUG			0x0d - -/** - * Returns a struct psb_intel_sdvo_output_flags of displays with hot plug - * interrupts enabled. - */ -#define SDVO_CMD_GET_ACTIVE_HOT_PLUG			0x0e - -#define SDVO_CMD_GET_INTERRUPT_EVENT_SOURCE		0x0f -struct psb_intel_sdvo_get_interrupt_event_source_response { -	u16 interrupt_status; -	unsigned int ambient_light_interrupt:1; -	unsigned int pad:7; -} __packed; - -/** - * Selects which input is affected by future input commands. - * - * Commands affected include SET_INPUT_TIMINGS_PART[12], - * GET_INPUT_TIMINGS_PART[12], GET_PREFERRED_INPUT_TIMINGS_PART[12], - * GET_INPUT_PIXEL_CLOCK_RANGE, and CREATE_PREFERRED_INPUT_TIMINGS. - */ -#define SDVO_CMD_SET_TARGET_INPUT			0x10 -struct psb_intel_sdvo_set_target_input_args { -	unsigned int target_1:1; -	unsigned int pad:7; -} __packed; - -/** - * Takes a struct psb_intel_sdvo_output_flags of which outputs are targeted by - * future output commands. - * - * Affected commands inclue SET_OUTPUT_TIMINGS_PART[12], - * GET_OUTPUT_TIMINGS_PART[12], and GET_OUTPUT_PIXEL_CLOCK_RANGE. - */ -#define SDVO_CMD_SET_TARGET_OUTPUT			0x11 - -#define SDVO_CMD_GET_INPUT_TIMINGS_PART1		0x12 -#define SDVO_CMD_GET_INPUT_TIMINGS_PART2		0x13 -#define SDVO_CMD_SET_INPUT_TIMINGS_PART1		0x14 -#define SDVO_CMD_SET_INPUT_TIMINGS_PART2		0x15 -#define SDVO_CMD_SET_OUTPUT_TIMINGS_PART1		0x16 -#define SDVO_CMD_SET_OUTPUT_TIMINGS_PART2		0x17 -#define SDVO_CMD_GET_OUTPUT_TIMINGS_PART1		0x18 -#define SDVO_CMD_GET_OUTPUT_TIMINGS_PART2		0x19 -/* Part 1 */ -# define SDVO_DTD_CLOCK_LOW				SDVO_I2C_ARG_0 -# define SDVO_DTD_CLOCK_HIGH				SDVO_I2C_ARG_1 -# define SDVO_DTD_H_ACTIVE				SDVO_I2C_ARG_2 -# define SDVO_DTD_H_BLANK				SDVO_I2C_ARG_3 -# define SDVO_DTD_H_HIGH				SDVO_I2C_ARG_4 -# define SDVO_DTD_V_ACTIVE				SDVO_I2C_ARG_5 -# define SDVO_DTD_V_BLANK				SDVO_I2C_ARG_6 -# define SDVO_DTD_V_HIGH				SDVO_I2C_ARG_7 -/* Part 2 */ -# define SDVO_DTD_HSYNC_OFF				SDVO_I2C_ARG_0 -# define SDVO_DTD_HSYNC_WIDTH				SDVO_I2C_ARG_1 -# define SDVO_DTD_VSYNC_OFF_WIDTH			SDVO_I2C_ARG_2 -# define SDVO_DTD_SYNC_OFF_WIDTH_HIGH			SDVO_I2C_ARG_3 -# define SDVO_DTD_DTD_FLAGS				SDVO_I2C_ARG_4 -# define SDVO_DTD_DTD_FLAG_INTERLACED				(1 << 7) -# define SDVO_DTD_DTD_FLAG_STEREO_MASK				(3 << 5) -# define SDVO_DTD_DTD_FLAG_INPUT_MASK				(3 << 3) -# define SDVO_DTD_DTD_FLAG_SYNC_MASK				(3 << 1) -# define SDVO_DTD_SDVO_FLAS				SDVO_I2C_ARG_5 -# define SDVO_DTD_SDVO_FLAG_STALL				(1 << 7) -# define SDVO_DTD_SDVO_FLAG_CENTERED				(0 << 6) -# define SDVO_DTD_SDVO_FLAG_UPPER_LEFT				(1 << 6) -# define SDVO_DTD_SDVO_FLAG_SCALING_MASK			(3 << 4) -# define SDVO_DTD_SDVO_FLAG_SCALING_NONE			(0 << 4) -# define SDVO_DTD_SDVO_FLAG_SCALING_SHARP			(1 << 4) -# define SDVO_DTD_SDVO_FLAG_SCALING_SMOOTH			(2 << 4) -# define SDVO_DTD_VSYNC_OFF_HIGH			SDVO_I2C_ARG_6 - -/** - * Generates a DTD based on the given width, height, and flags. - * - * This will be supported by any device supporting scaling or interlaced - * modes. - */ -#define SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING		0x1a -# define SDVO_PREFERRED_INPUT_TIMING_CLOCK_LOW		SDVO_I2C_ARG_0 -# define SDVO_PREFERRED_INPUT_TIMING_CLOCK_HIGH		SDVO_I2C_ARG_1 -# define SDVO_PREFERRED_INPUT_TIMING_WIDTH_LOW		SDVO_I2C_ARG_2 -# define SDVO_PREFERRED_INPUT_TIMING_WIDTH_HIGH		SDVO_I2C_ARG_3 -# define SDVO_PREFERRED_INPUT_TIMING_HEIGHT_LOW		SDVO_I2C_ARG_4 -# define SDVO_PREFERRED_INPUT_TIMING_HEIGHT_HIGH	SDVO_I2C_ARG_5 -# define SDVO_PREFERRED_INPUT_TIMING_FLAGS		SDVO_I2C_ARG_6 -# define SDVO_PREFERRED_INPUT_TIMING_FLAGS_INTERLACED		(1 << 0) -# define SDVO_PREFERRED_INPUT_TIMING_FLAGS_SCALED		(1 << 1) - -#define SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1	0x1b -#define SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2	0x1c - -/** Returns a struct psb_intel_sdvo_pixel_clock_range */ -#define SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE		0x1d -/** Returns a struct psb_intel_sdvo_pixel_clock_range */ -#define SDVO_CMD_GET_OUTPUT_PIXEL_CLOCK_RANGE		0x1e - -/** Returns a byte bitfield containing SDVO_CLOCK_RATE_MULT_* flags */ -#define SDVO_CMD_GET_SUPPORTED_CLOCK_RATE_MULTS		0x1f - -/** Returns a byte containing a SDVO_CLOCK_RATE_MULT_* flag */ -#define SDVO_CMD_GET_CLOCK_RATE_MULT			0x20 -/** Takes a byte containing a SDVO_CLOCK_RATE_MULT_* flag */ -#define SDVO_CMD_SET_CLOCK_RATE_MULT			0x21 -# define SDVO_CLOCK_RATE_MULT_1X				(1 << 0) -# define SDVO_CLOCK_RATE_MULT_2X				(1 << 1) -# define SDVO_CLOCK_RATE_MULT_4X				(1 << 3) - -#define SDVO_CMD_GET_SUPPORTED_TV_FORMATS		0x27 - -#define SDVO_CMD_GET_TV_FORMAT				0x28 - -#define SDVO_CMD_SET_TV_FORMAT				0x29 - -#define SDVO_CMD_GET_SUPPORTED_POWER_STATES		0x2a -#define SDVO_CMD_GET_ENCODER_POWER_STATE		0x2b -#define SDVO_CMD_SET_ENCODER_POWER_STATE		0x2c -# define SDVO_ENCODER_STATE_ON					(1 << 0) -# define SDVO_ENCODER_STATE_STANDBY				(1 << 1) -# define SDVO_ENCODER_STATE_SUSPEND				(1 << 2) -# define SDVO_ENCODER_STATE_OFF					(1 << 3) - -#define SDVO_CMD_SET_TV_RESOLUTION_SUPPORT		0x93 - -#define SDVO_CMD_SET_CONTROL_BUS_SWITCH			0x7a -# define SDVO_CONTROL_BUS_PROM				0x0 -# define SDVO_CONTROL_BUS_DDC1				0x1 -# define SDVO_CONTROL_BUS_DDC2				0x2 -# define SDVO_CONTROL_BUS_DDC3				0x3 - -/* SDVO Bus & SDVO Inputs wiring details*/ -/* Bit 0: Is SDVOB connected to In0 (1 = yes, 0 = no*/ -/* Bit 1: Is SDVOB connected to In1 (1 = yes, 0 = no*/ -/* Bit 2: Is SDVOC connected to In0 (1 = yes, 0 = no*/ -/* Bit 3: Is SDVOC connected to In1 (1 = yes, 0 = no*/ -#define SDVOB_IN0 0x01 -#define SDVOB_IN1 0x02 -#define SDVOC_IN0 0x04 -#define SDVOC_IN1 0x08 - -#define SDVO_DEVICE_NONE 0x00 -#define        SDVO_DEVICE_CRT 0x01 -#define        SDVO_DEVICE_TV 0x02 -#define        SDVO_DEVICE_LVDS 0x04 -#define        SDVO_DEVICE_TMDS 0x08 - diff --git a/drivers/staging/gma500/psb_irq.c b/drivers/staging/gma500/psb_irq.c deleted file mode 100644 index 36dd63044b0..00000000000 --- a/drivers/staging/gma500/psb_irq.c +++ /dev/null @@ -1,627 +0,0 @@ -/************************************************************************** - * Copyright (c) 2007, Intel Corporation. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - * Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to - * develop this driver. - * - **************************************************************************/ -/* - */ - -#include <drm/drmP.h> -#include "psb_drv.h" -#include "psb_reg.h" -#include "psb_intel_reg.h" -#include "power.h" -#include "mdfld_output.h" - -/* - * inline functions - */ - -static inline u32 -psb_pipestat(int pipe) -{ -	if (pipe == 0) -		return PIPEASTAT; -	if (pipe == 1) -		return PIPEBSTAT; -	if (pipe == 2) -		return PIPECSTAT; -	BUG(); -} - -static inline u32 -mid_pipe_event(int pipe) -{ -	if (pipe == 0) -		return _PSB_PIPEA_EVENT_FLAG; -	if (pipe == 1) -		return _MDFLD_PIPEB_EVENT_FLAG; -	if (pipe == 2) -		return _MDFLD_PIPEC_EVENT_FLAG; -	BUG(); -} - -static inline u32 -mid_pipe_vsync(int pipe) -{ -	if (pipe == 0) -		return _PSB_VSYNC_PIPEA_FLAG; -	if (pipe == 1) -		return _PSB_VSYNC_PIPEB_FLAG; -	if (pipe == 2) -		return _MDFLD_PIPEC_VBLANK_FLAG; -	BUG(); -} - -static inline u32 -mid_pipeconf(int pipe) -{ -	if (pipe == 0) -		return PIPEACONF; -	if (pipe == 1) -		return PIPEBCONF; -	if (pipe == 2) -		return PIPECCONF; -	BUG(); -} - -void -psb_enable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask) -{ -	if ((dev_priv->pipestat[pipe] & mask) != mask) { -		u32 reg = psb_pipestat(pipe); -		dev_priv->pipestat[pipe] |= mask; -		/* Enable the interrupt, clear any pending status */ -		if (gma_power_begin(dev_priv->dev, false)) { -			u32 writeVal = PSB_RVDC32(reg); -			writeVal |= (mask | (mask >> 16)); -			PSB_WVDC32(writeVal, reg); -			(void) PSB_RVDC32(reg); -			gma_power_end(dev_priv->dev); -		} -	} -} - -void -psb_disable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask) -{ -	if ((dev_priv->pipestat[pipe] & mask) != 0) { -		u32 reg = psb_pipestat(pipe); -		dev_priv->pipestat[pipe] &= ~mask; -		if (gma_power_begin(dev_priv->dev, false)) { -			u32 writeVal = PSB_RVDC32(reg); -			writeVal &= ~mask; -			PSB_WVDC32(writeVal, reg); -			(void) PSB_RVDC32(reg); -			gma_power_end(dev_priv->dev); -		} -	} -} - -void mid_enable_pipe_event(struct drm_psb_private *dev_priv, int pipe) -{ -	if (gma_power_begin(dev_priv->dev, false)) { -		u32 pipe_event = mid_pipe_event(pipe); -		dev_priv->vdc_irq_mask |= pipe_event; -		PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R); -		PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R); -		gma_power_end(dev_priv->dev); -	} -} - -void mid_disable_pipe_event(struct drm_psb_private *dev_priv, int pipe) -{ -	if (dev_priv->pipestat[pipe] == 0) { -		if (gma_power_begin(dev_priv->dev, false)) { -			u32 pipe_event = mid_pipe_event(pipe); -			dev_priv->vdc_irq_mask &= ~pipe_event; -			PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R); -			PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R); -			gma_power_end(dev_priv->dev); -		} -	} -} - -/** - * Display controller interrupt handler for pipe event. - * - */ -static void mid_pipe_event_handler(struct drm_device *dev, int pipe) -{ -	struct drm_psb_private *dev_priv = -	    (struct drm_psb_private *) dev->dev_private; - -	uint32_t pipe_stat_val = 0; -	uint32_t pipe_stat_reg = psb_pipestat(pipe); -	uint32_t pipe_enable = dev_priv->pipestat[pipe]; -	uint32_t pipe_status = dev_priv->pipestat[pipe] >> 16; -	uint32_t pipe_clear; -	uint32_t i = 0; - -	spin_lock(&dev_priv->irqmask_lock); - -	pipe_stat_val = PSB_RVDC32(pipe_stat_reg); -	pipe_stat_val &= pipe_enable | pipe_status; -	pipe_stat_val &= pipe_stat_val >> 16; - -	spin_unlock(&dev_priv->irqmask_lock); - -	/* Clear the 2nd level interrupt status bits -	 * Sometimes the bits are very sticky so we repeat until they unstick */ -	for (i = 0; i < 0xffff; i++) { -		PSB_WVDC32(PSB_RVDC32(pipe_stat_reg), pipe_stat_reg); -		pipe_clear = PSB_RVDC32(pipe_stat_reg) & pipe_status; - -		if (pipe_clear == 0) -			break; -	} - -	if (pipe_clear) -		dev_err(dev->dev, -		"%s, can't clear status bits for pipe %d, its value = 0x%x.\n", -		__func__, pipe, PSB_RVDC32(pipe_stat_reg)); - -	if (pipe_stat_val & PIPE_VBLANK_STATUS) -		drm_handle_vblank(dev, pipe); - -	if (pipe_stat_val & PIPE_TE_STATUS) -		drm_handle_vblank(dev, pipe); -} - -/* - * Display controller interrupt handler. - */ -static void psb_vdc_interrupt(struct drm_device *dev, uint32_t vdc_stat) -{ -	if (vdc_stat & _PSB_VSYNC_PIPEA_FLAG) -		mid_pipe_event_handler(dev, 0); - -	if (vdc_stat & _PSB_VSYNC_PIPEB_FLAG) -		mid_pipe_event_handler(dev, 1); -} - -irqreturn_t psb_irq_handler(DRM_IRQ_ARGS) -{ -	struct drm_device *dev = (struct drm_device *) arg; -	struct drm_psb_private *dev_priv = -	    (struct drm_psb_private *) dev->dev_private; - -	uint32_t vdc_stat, dsp_int = 0, sgx_int = 0; -	int handled = 0; - -	spin_lock(&dev_priv->irqmask_lock); - -	vdc_stat = PSB_RVDC32(PSB_INT_IDENTITY_R); - -	if (vdc_stat & _PSB_PIPE_EVENT_FLAG) -		dsp_int = 1; - -	/* FIXME: Handle Medfield -	if (vdc_stat & _MDFLD_DISP_ALL_IRQ_FLAG) -		dsp_int = 1; -	*/ - -	if (vdc_stat & _PSB_IRQ_SGX_FLAG) -		sgx_int = 1; - -	vdc_stat &= dev_priv->vdc_irq_mask; -	spin_unlock(&dev_priv->irqmask_lock); - -	if (dsp_int && gma_power_is_on(dev)) { -		psb_vdc_interrupt(dev, vdc_stat); -		handled = 1; -	} - -	if (sgx_int) { -		/* Not expected - we have it masked, shut it up */ -		u32 s, s2; -		s = PSB_RSGX32(PSB_CR_EVENT_STATUS); -		s2 = PSB_RSGX32(PSB_CR_EVENT_STATUS2); -		PSB_WSGX32(s, PSB_CR_EVENT_HOST_CLEAR); -		PSB_WSGX32(s2, PSB_CR_EVENT_HOST_CLEAR2); -		/* if s & _PSB_CE_TWOD_COMPLETE we have 2D done but -		   we may as well poll even if we add that ! */ -		handled = 1; -	} - -	PSB_WVDC32(vdc_stat, PSB_INT_IDENTITY_R); -	(void) PSB_RVDC32(PSB_INT_IDENTITY_R); -	DRM_READMEMORYBARRIER(); - -	if (!handled) -		return IRQ_NONE; - -	return IRQ_HANDLED; -} - -void psb_irq_preinstall(struct drm_device *dev) -{ -	struct drm_psb_private *dev_priv = -	    (struct drm_psb_private *) dev->dev_private; -	unsigned long irqflags; - -	spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags); - -	if (gma_power_is_on(dev)) -		PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM); -	if (dev->vblank_enabled[0]) -		dev_priv->vdc_irq_mask |= _PSB_VSYNC_PIPEA_FLAG; -	if (dev->vblank_enabled[1]) -		dev_priv->vdc_irq_mask |= _PSB_VSYNC_PIPEB_FLAG; - -	/* FIXME: Handle Medfield irq mask -	if (dev->vblank_enabled[1]) -		dev_priv->vdc_irq_mask |= _MDFLD_PIPEB_EVENT_FLAG; -	if (dev->vblank_enabled[2]) -		dev_priv->vdc_irq_mask |= _MDFLD_PIPEC_EVENT_FLAG; -	*/ - -	/* This register is safe even if display island is off */ -	PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R); -	spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); -} - -int psb_irq_postinstall(struct drm_device *dev) -{ -	struct drm_psb_private *dev_priv = -	    (struct drm_psb_private *) dev->dev_private; -	unsigned long irqflags; - -	spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags); - -	/* This register is safe even if display island is off */ -	PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R); -	PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM); - -	if (dev->vblank_enabled[0]) -		psb_enable_pipestat(dev_priv, 0, PIPE_VBLANK_INTERRUPT_ENABLE); -	else -		psb_disable_pipestat(dev_priv, 0, PIPE_VBLANK_INTERRUPT_ENABLE); - -	if (dev->vblank_enabled[1]) -		psb_enable_pipestat(dev_priv, 1, PIPE_VBLANK_INTERRUPT_ENABLE); -	else -		psb_disable_pipestat(dev_priv, 1, PIPE_VBLANK_INTERRUPT_ENABLE); - -	if (dev->vblank_enabled[2]) -		psb_enable_pipestat(dev_priv, 2, PIPE_VBLANK_INTERRUPT_ENABLE); -	else -		psb_disable_pipestat(dev_priv, 2, PIPE_VBLANK_INTERRUPT_ENABLE); - -	spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); -	return 0; -} - -void psb_irq_uninstall(struct drm_device *dev) -{ -	struct drm_psb_private *dev_priv = -	    (struct drm_psb_private *) dev->dev_private; -	unsigned long irqflags; - -	spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags); - -	PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM); - -	if (dev->vblank_enabled[0]) -		psb_disable_pipestat(dev_priv, 0, PIPE_VBLANK_INTERRUPT_ENABLE); - -	if (dev->vblank_enabled[1]) -		psb_disable_pipestat(dev_priv, 1, PIPE_VBLANK_INTERRUPT_ENABLE); - -	if (dev->vblank_enabled[2]) -		psb_disable_pipestat(dev_priv, 2, PIPE_VBLANK_INTERRUPT_ENABLE); - -	dev_priv->vdc_irq_mask &= _PSB_IRQ_SGX_FLAG | -				  _PSB_IRQ_MSVDX_FLAG | -				  _LNC_IRQ_TOPAZ_FLAG; - -	/* These two registers are safe even if display island is off */ -	PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R); -	PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R); - -	wmb(); - -	/* This register is safe even if display island is off */ -	PSB_WVDC32(PSB_RVDC32(PSB_INT_IDENTITY_R), PSB_INT_IDENTITY_R); -	spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); -} - -void psb_irq_turn_on_dpst(struct drm_device *dev) -{ -	struct drm_psb_private *dev_priv = -		(struct drm_psb_private *) dev->dev_private; -	u32 hist_reg; -	u32 pwm_reg; - -	if (gma_power_begin(dev, false)) { -		PSB_WVDC32(1 << 31, HISTOGRAM_LOGIC_CONTROL); -		hist_reg = PSB_RVDC32(HISTOGRAM_LOGIC_CONTROL); -		PSB_WVDC32(1 << 31, HISTOGRAM_INT_CONTROL); -		hist_reg = PSB_RVDC32(HISTOGRAM_INT_CONTROL); - -		PSB_WVDC32(0x80010100, PWM_CONTROL_LOGIC); -		pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC); -		PSB_WVDC32(pwm_reg | PWM_PHASEIN_ENABLE -						| PWM_PHASEIN_INT_ENABLE, -							   PWM_CONTROL_LOGIC); -		pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC); - -		psb_enable_pipestat(dev_priv, 0, PIPE_DPST_EVENT_ENABLE); - -		hist_reg = PSB_RVDC32(HISTOGRAM_INT_CONTROL); -		PSB_WVDC32(hist_reg | HISTOGRAM_INT_CTRL_CLEAR, -							HISTOGRAM_INT_CONTROL); -		pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC); -		PSB_WVDC32(pwm_reg | 0x80010100 | PWM_PHASEIN_ENABLE, -							PWM_CONTROL_LOGIC); - -		gma_power_end(dev); -	} -} - -int psb_irq_enable_dpst(struct drm_device *dev) -{ -	struct drm_psb_private *dev_priv = -		(struct drm_psb_private *) dev->dev_private; -	unsigned long irqflags; - -	spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags); - -	/* enable DPST */ -	mid_enable_pipe_event(dev_priv, 0); -	psb_irq_turn_on_dpst(dev); - -	spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); -	return 0; -} - -void psb_irq_turn_off_dpst(struct drm_device *dev) -{ -	struct drm_psb_private *dev_priv = -	    (struct drm_psb_private *) dev->dev_private; -	u32 hist_reg; -	u32 pwm_reg; - -	if (gma_power_begin(dev, false)) { -		PSB_WVDC32(0x00000000, HISTOGRAM_INT_CONTROL); -		hist_reg = PSB_RVDC32(HISTOGRAM_INT_CONTROL); - -		psb_disable_pipestat(dev_priv, 0, PIPE_DPST_EVENT_ENABLE); - -		pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC); -		PSB_WVDC32(pwm_reg & !(PWM_PHASEIN_INT_ENABLE), -							PWM_CONTROL_LOGIC); -		pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC); - -		gma_power_end(dev); -	} -} - -int psb_irq_disable_dpst(struct drm_device *dev) -{ -	struct drm_psb_private *dev_priv = -	    (struct drm_psb_private *) dev->dev_private; -	unsigned long irqflags; - -	spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags); - -	mid_disable_pipe_event(dev_priv, 0); -	psb_irq_turn_off_dpst(dev); - -	spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); - -	return 0; -} - -#ifdef PSB_FIXME -static int psb_vblank_do_wait(struct drm_device *dev, -			      unsigned int *sequence, atomic_t *counter) -{ -	unsigned int cur_vblank; -	int ret = 0; -	DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ, -		    (((cur_vblank = atomic_read(counter)) -		      - *sequence) <= (1 << 23))); -	*sequence = cur_vblank; - -	return ret; -} -#endif - -/* - * It is used to enable VBLANK interrupt - */ -int psb_enable_vblank(struct drm_device *dev, int pipe) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; -	unsigned long irqflags; -	uint32_t reg_val = 0; -	uint32_t pipeconf_reg = mid_pipeconf(pipe); - -#if defined(CONFIG_DRM_PSB_MFLD) -	/* Medfield is different - we should perhaps extract out vblank -	   and blacklight etc ops */ -	if (IS_MFLD(dev) && !mdfld_panel_dpi(dev)) -		return mdfld_enable_te(dev, pipe); -#endif -	if (gma_power_begin(dev, false)) { -		reg_val = REG_READ(pipeconf_reg); -		gma_power_end(dev); -	} - -	if (!(reg_val & PIPEACONF_ENABLE)) -		return -EINVAL; - -	spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags); - -	if (pipe == 0) -		dev_priv->vdc_irq_mask |= _PSB_VSYNC_PIPEA_FLAG; -	else if (pipe == 1) -		dev_priv->vdc_irq_mask |= _PSB_VSYNC_PIPEB_FLAG; - -	PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R); -	PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R); -	psb_enable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_ENABLE); - -	spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); - -	return 0; -} - -/* - * It is used to disable VBLANK interrupt - */ -void psb_disable_vblank(struct drm_device *dev, int pipe) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; -	unsigned long irqflags; - -#if defined(CONFIG_DRM_PSB_MFLD) -	if (IS_MFLD(dev) && !mdfld_panel_dpi(dev)) -		mdfld_disable_te(dev, pipe); -#endif -	spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags); - -	if (pipe == 0) -		dev_priv->vdc_irq_mask &= ~_PSB_VSYNC_PIPEA_FLAG; -	else if (pipe == 1) -		dev_priv->vdc_irq_mask &= ~_PSB_VSYNC_PIPEB_FLAG; - -	PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R); -	PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R); -	psb_disable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_ENABLE); - -	spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); -} - -/** - *	mdfld_enable_te		-	enable TE events - *	@dev: our DRM device - *	@pipe: which pipe to work on - * - *	Enable TE events on a Medfield display pipe. Medfield specific. - */ -int mdfld_enable_te(struct drm_device *dev, int pipe) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; -	unsigned long flags; -	uint32_t reg_val = 0; -	uint32_t pipeconf_reg = mid_pipeconf(pipe); - -	if (gma_power_begin(dev, false)) { -		reg_val = REG_READ(pipeconf_reg); -		gma_power_end(dev); -	} - -	if (!(reg_val & PIPEACONF_ENABLE)) -		return -EINVAL; - -	spin_lock_irqsave(&dev_priv->irqmask_lock, flags); - -	mid_enable_pipe_event(dev_priv, pipe); -	psb_enable_pipestat(dev_priv, pipe, PIPE_TE_ENABLE); - -	spin_unlock_irqrestore(&dev_priv->irqmask_lock, flags); - -	return 0; -} - -/** - *	mdfld_disable_te		-	disable TE events - *	@dev: our DRM device - *	@pipe: which pipe to work on - * - *	Disable TE events on a Medfield display pipe. Medfield specific. - */ -void mdfld_disable_te(struct drm_device *dev, int pipe) -{ -	struct drm_psb_private *dev_priv = dev->dev_private; -	unsigned long flags; - -	spin_lock_irqsave(&dev_priv->irqmask_lock, flags); - -	mid_disable_pipe_event(dev_priv, pipe); -	psb_disable_pipestat(dev_priv, pipe, PIPE_TE_ENABLE); - -	spin_unlock_irqrestore(&dev_priv->irqmask_lock, flags); -} - -/* Called from drm generic code, passed a 'crtc', which - * we use as a pipe index - */ -u32 psb_get_vblank_counter(struct drm_device *dev, int pipe) -{ -	uint32_t high_frame = PIPEAFRAMEHIGH; -	uint32_t low_frame = PIPEAFRAMEPIXEL; -	uint32_t pipeconf_reg = PIPEACONF; -	uint32_t reg_val = 0; -	uint32_t high1 = 0, high2 = 0, low = 0, count = 0; - -	switch (pipe) { -	case 0: -		break; -	case 1: -		high_frame = PIPEBFRAMEHIGH; -		low_frame = PIPEBFRAMEPIXEL; -		pipeconf_reg = PIPEBCONF; -		break; -	case 2: -		high_frame = PIPECFRAMEHIGH; -		low_frame = PIPECFRAMEPIXEL; -		pipeconf_reg = PIPECCONF; -		break; -	default: -		dev_err(dev->dev, "%s, invalid pipe.\n", __func__); -		return 0; -	} - -	if (!gma_power_begin(dev, false)) -		return 0; - -	reg_val = REG_READ(pipeconf_reg); - -	if (!(reg_val & PIPEACONF_ENABLE)) { -		dev_err(dev->dev, "trying to get vblank count for disabled pipe %d\n", -								pipe); -		goto psb_get_vblank_counter_exit; -	} - -	/* -	 * High & low register fields aren't synchronized, so make sure -	 * we get a low value that's stable across two reads of the high -	 * register. -	 */ -	do { -		high1 = ((REG_READ(high_frame) & PIPE_FRAME_HIGH_MASK) >> -			 PIPE_FRAME_HIGH_SHIFT); -		low =  ((REG_READ(low_frame) & PIPE_FRAME_LOW_MASK) >> -			PIPE_FRAME_LOW_SHIFT); -		high2 = ((REG_READ(high_frame) & PIPE_FRAME_HIGH_MASK) >> -			 PIPE_FRAME_HIGH_SHIFT); -	} while (high1 != high2); - -	count = (high1 << 8) | low; - -psb_get_vblank_counter_exit: - -	gma_power_end(dev); - -	return count; -} - diff --git a/drivers/staging/gma500/psb_irq.h b/drivers/staging/gma500/psb_irq.h deleted file mode 100644 index 216fda38b57..00000000000 --- a/drivers/staging/gma500/psb_irq.h +++ /dev/null @@ -1,45 +0,0 @@ -/************************************************************************** - * Copyright (c) 2009-2011, Intel Corporation. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - * Authors: - *    Benjamin Defnet <benjamin.r.defnet@intel.com> - *    Rajesh Poornachandran <rajesh.poornachandran@intel.com> - * - **************************************************************************/ - -#ifndef _SYSIRQ_H_ -#define _SYSIRQ_H_ - -#include <drm/drmP.h> - -bool sysirq_init(struct drm_device *dev); -void sysirq_uninit(struct drm_device *dev); - -void psb_irq_preinstall(struct drm_device *dev); -int  psb_irq_postinstall(struct drm_device *dev); -void psb_irq_uninstall(struct drm_device *dev); -irqreturn_t psb_irq_handler(DRM_IRQ_ARGS); - -int psb_irq_enable_dpst(struct drm_device *dev); -int psb_irq_disable_dpst(struct drm_device *dev); -void psb_irq_turn_on_dpst(struct drm_device *dev); -void psb_irq_turn_off_dpst(struct drm_device *dev); -int  psb_enable_vblank(struct drm_device *dev, int pipe); -void psb_disable_vblank(struct drm_device *dev, int pipe); -u32  psb_get_vblank_counter(struct drm_device *dev, int pipe); - -#endif /* _SYSIRQ_H_ */ diff --git a/drivers/staging/gma500/psb_lid.c b/drivers/staging/gma500/psb_lid.c deleted file mode 100644 index b867aabe6bf..00000000000 --- a/drivers/staging/gma500/psb_lid.c +++ /dev/null @@ -1,88 +0,0 @@ -/************************************************************************** - * Copyright (c) 2007, Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - * Authors: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com> - **************************************************************************/ - -#include <drm/drmP.h> -#include "psb_drv.h" -#include "psb_reg.h" -#include "psb_intel_reg.h" -#include <linux/spinlock.h> - -static void psb_lid_timer_func(unsigned long data) -{ -	struct drm_psb_private * dev_priv = (struct drm_psb_private *)data; -	struct drm_device *dev = (struct drm_device *)dev_priv->dev; -	struct timer_list *lid_timer = &dev_priv->lid_timer; -	unsigned long irq_flags; -	u32 *lid_state = dev_priv->lid_state; -	u32 pp_status; - -	if (readl(lid_state) == dev_priv->lid_last_state) -		goto lid_timer_schedule; - -	if ((readl(lid_state)) & 0x01) { -		/*lid state is open*/ -		REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) | POWER_TARGET_ON); -		do { -			pp_status = REG_READ(PP_STATUS); -		} while ((pp_status & PP_ON) == 0); - -		/*FIXME: should be backlight level before*/ -		psb_intel_lvds_set_brightness(dev, 100); -	} else { -		psb_intel_lvds_set_brightness(dev, 0); - -		REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) & ~POWER_TARGET_ON); -		do { -			pp_status = REG_READ(PP_STATUS); -		} while ((pp_status & PP_ON) == 0); -	} -	dev_priv->lid_last_state =  readl(lid_state); - -lid_timer_schedule: -	spin_lock_irqsave(&dev_priv->lid_lock, irq_flags); -	if (!timer_pending(lid_timer)) { -		lid_timer->expires = jiffies + PSB_LID_DELAY; -		add_timer(lid_timer); -	} -	spin_unlock_irqrestore(&dev_priv->lid_lock, irq_flags); -} - -void psb_lid_timer_init(struct drm_psb_private *dev_priv) -{ -	struct timer_list *lid_timer = &dev_priv->lid_timer; -	unsigned long irq_flags; - -	spin_lock_init(&dev_priv->lid_lock); -	spin_lock_irqsave(&dev_priv->lid_lock, irq_flags); - -	init_timer(lid_timer); - -	lid_timer->data = (unsigned long)dev_priv; -	lid_timer->function = psb_lid_timer_func; -	lid_timer->expires = jiffies + PSB_LID_DELAY; - -	add_timer(lid_timer); -	spin_unlock_irqrestore(&dev_priv->lid_lock, irq_flags); -} - -void psb_lid_timer_takedown(struct drm_psb_private *dev_priv) -{ -	del_timer_sync(&dev_priv->lid_timer); -} - diff --git a/drivers/staging/gma500/psb_reg.h b/drivers/staging/gma500/psb_reg.h deleted file mode 100644 index b81c7c1e9c2..00000000000 --- a/drivers/staging/gma500/psb_reg.h +++ /dev/null @@ -1,582 +0,0 @@ -/************************************************************************** - * - * Copyright (c) (2005-2007) Imagination Technologies Limited. - * Copyright (c) 2007, Intel Corporation. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.. - * - **************************************************************************/ - -#ifndef _PSB_REG_H_ -#define _PSB_REG_H_ - -#define PSB_CR_CLKGATECTL		0x0000 -#define _PSB_C_CLKGATECTL_AUTO_MAN_REG		(1 << 24) -#define _PSB_C_CLKGATECTL_USE_CLKG_SHIFT	(20) -#define _PSB_C_CLKGATECTL_USE_CLKG_MASK		(0x3 << 20) -#define _PSB_C_CLKGATECTL_DPM_CLKG_SHIFT	(16) -#define _PSB_C_CLKGATECTL_DPM_CLKG_MASK		(0x3 << 16) -#define _PSB_C_CLKGATECTL_TA_CLKG_SHIFT		(12) -#define _PSB_C_CLKGATECTL_TA_CLKG_MASK		(0x3 << 12) -#define _PSB_C_CLKGATECTL_TSP_CLKG_SHIFT	(8) -#define _PSB_C_CLKGATECTL_TSP_CLKG_MASK		(0x3 << 8) -#define _PSB_C_CLKGATECTL_ISP_CLKG_SHIFT	(4) -#define _PSB_C_CLKGATECTL_ISP_CLKG_MASK		(0x3 << 4) -#define _PSB_C_CLKGATECTL_2D_CLKG_SHIFT		(0) -#define _PSB_C_CLKGATECTL_2D_CLKG_MASK		(0x3 << 0) -#define _PSB_C_CLKGATECTL_CLKG_ENABLED		(0) -#define _PSB_C_CLKGATECTL_CLKG_DISABLED		(1) -#define _PSB_C_CLKGATECTL_CLKG_AUTO		(2) - -#define PSB_CR_CORE_ID			0x0010 -#define _PSB_CC_ID_ID_SHIFT			(16) -#define _PSB_CC_ID_ID_MASK			(0xFFFF << 16) -#define _PSB_CC_ID_CONFIG_SHIFT			(0) -#define _PSB_CC_ID_CONFIG_MASK			(0xFFFF << 0) - -#define PSB_CR_CORE_REVISION		0x0014 -#define _PSB_CC_REVISION_DESIGNER_SHIFT		(24) -#define _PSB_CC_REVISION_DESIGNER_MASK		(0xFF << 24) -#define _PSB_CC_REVISION_MAJOR_SHIFT		(16) -#define _PSB_CC_REVISION_MAJOR_MASK		(0xFF << 16) -#define _PSB_CC_REVISION_MINOR_SHIFT		(8) -#define _PSB_CC_REVISION_MINOR_MASK		(0xFF << 8) -#define _PSB_CC_REVISION_MAINTENANCE_SHIFT	(0) -#define _PSB_CC_REVISION_MAINTENANCE_MASK	(0xFF << 0) - -#define PSB_CR_DESIGNER_REV_FIELD1	0x0018 - -#define PSB_CR_SOFT_RESET		0x0080 -#define _PSB_CS_RESET_TSP_RESET		(1 << 6) -#define _PSB_CS_RESET_ISP_RESET		(1 << 5) -#define _PSB_CS_RESET_USE_RESET		(1 << 4) -#define _PSB_CS_RESET_TA_RESET		(1 << 3) -#define _PSB_CS_RESET_DPM_RESET		(1 << 2) -#define _PSB_CS_RESET_TWOD_RESET	(1 << 1) -#define _PSB_CS_RESET_BIF_RESET			(1 << 0) - -#define PSB_CR_DESIGNER_REV_FIELD2	0x001C - -#define PSB_CR_EVENT_HOST_ENABLE2	0x0110 - -#define PSB_CR_EVENT_STATUS2		0x0118 - -#define PSB_CR_EVENT_HOST_CLEAR2	0x0114 -#define _PSB_CE2_BIF_REQUESTER_FAULT		(1 << 4) - -#define PSB_CR_EVENT_STATUS		0x012C - -#define PSB_CR_EVENT_HOST_ENABLE	0x0130 - -#define PSB_CR_EVENT_HOST_CLEAR		0x0134 -#define _PSB_CE_MASTER_INTERRUPT		(1 << 31) -#define _PSB_CE_TA_DPM_FAULT			(1 << 28) -#define _PSB_CE_TWOD_COMPLETE			(1 << 27) -#define _PSB_CE_DPM_OUT_OF_MEMORY_ZLS		(1 << 25) -#define _PSB_CE_DPM_TA_MEM_FREE			(1 << 24) -#define _PSB_CE_PIXELBE_END_RENDER		(1 << 18) -#define _PSB_CE_SW_EVENT			(1 << 14) -#define _PSB_CE_TA_FINISHED			(1 << 13) -#define _PSB_CE_TA_TERMINATE			(1 << 12) -#define _PSB_CE_DPM_REACHED_MEM_THRESH		(1 << 3) -#define _PSB_CE_DPM_OUT_OF_MEMORY_GBL		(1 << 2) -#define _PSB_CE_DPM_OUT_OF_MEMORY_MT		(1 << 1) -#define _PSB_CE_DPM_3D_MEM_FREE			(1 << 0) - - -#define PSB_USE_OFFSET_MASK		0x0007FFFF -#define PSB_USE_OFFSET_SIZE		(PSB_USE_OFFSET_MASK + 1) -#define PSB_CR_USE_CODE_BASE0		0x0A0C -#define PSB_CR_USE_CODE_BASE1		0x0A10 -#define PSB_CR_USE_CODE_BASE2		0x0A14 -#define PSB_CR_USE_CODE_BASE3		0x0A18 -#define PSB_CR_USE_CODE_BASE4		0x0A1C -#define PSB_CR_USE_CODE_BASE5		0x0A20 -#define PSB_CR_USE_CODE_BASE6		0x0A24 -#define PSB_CR_USE_CODE_BASE7		0x0A28 -#define PSB_CR_USE_CODE_BASE8		0x0A2C -#define PSB_CR_USE_CODE_BASE9		0x0A30 -#define PSB_CR_USE_CODE_BASE10		0x0A34 -#define PSB_CR_USE_CODE_BASE11		0x0A38 -#define PSB_CR_USE_CODE_BASE12		0x0A3C -#define PSB_CR_USE_CODE_BASE13		0x0A40 -#define PSB_CR_USE_CODE_BASE14		0x0A44 -#define PSB_CR_USE_CODE_BASE15		0x0A48 -#define PSB_CR_USE_CODE_BASE(_i)	(0x0A0C + ((_i) << 2)) -#define _PSB_CUC_BASE_DM_SHIFT			(25) -#define _PSB_CUC_BASE_DM_MASK			(0x3 << 25) -#define _PSB_CUC_BASE_ADDR_SHIFT		(0)	/* 1024-bit aligned address? */ -#define _PSB_CUC_BASE_ADDR_ALIGNSHIFT		(7) -#define _PSB_CUC_BASE_ADDR_MASK			(0x1FFFFFF << 0) -#define _PSB_CUC_DM_VERTEX			(0) -#define _PSB_CUC_DM_PIXEL			(1) -#define _PSB_CUC_DM_RESERVED			(2) -#define _PSB_CUC_DM_EDM				(3) - -#define PSB_CR_PDS_EXEC_BASE		0x0AB8 -#define _PSB_CR_PDS_EXEC_BASE_ADDR_SHIFT	(20)	/* 1MB aligned address */ -#define _PSB_CR_PDS_EXEC_BASE_ADDR_ALIGNSHIFT	(20) - -#define PSB_CR_EVENT_KICKER		0x0AC4 -#define _PSB_CE_KICKER_ADDRESS_SHIFT		(4)	/* 128-bit aligned address */ - -#define PSB_CR_EVENT_KICK		0x0AC8 -#define _PSB_CE_KICK_NOW			(1 << 0) - -#define PSB_CR_BIF_DIR_LIST_BASE1	0x0C38 - -#define PSB_CR_BIF_CTRL			0x0C00 -#define _PSB_CB_CTRL_CLEAR_FAULT		(1 << 4) -#define _PSB_CB_CTRL_INVALDC			(1 << 3) -#define _PSB_CB_CTRL_FLUSH			(1 << 2) - -#define PSB_CR_BIF_INT_STAT		0x0C04 - -#define PSB_CR_BIF_FAULT		0x0C08 -#define _PSB_CBI_STAT_PF_N_RW			(1 << 14) -#define _PSB_CBI_STAT_FAULT_SHIFT		(0) -#define _PSB_CBI_STAT_FAULT_MASK		(0x3FFF << 0) -#define _PSB_CBI_STAT_FAULT_CACHE		(1 << 1) -#define _PSB_CBI_STAT_FAULT_TA			(1 << 2) -#define _PSB_CBI_STAT_FAULT_VDM			(1 << 3) -#define _PSB_CBI_STAT_FAULT_2D			(1 << 4) -#define _PSB_CBI_STAT_FAULT_PBE			(1 << 5) -#define _PSB_CBI_STAT_FAULT_TSP			(1 << 6) -#define _PSB_CBI_STAT_FAULT_ISP			(1 << 7) -#define _PSB_CBI_STAT_FAULT_USSEPDS		(1 << 8) -#define _PSB_CBI_STAT_FAULT_HOST		(1 << 9) - -#define PSB_CR_BIF_BANK0		0x0C78 -#define PSB_CR_BIF_BANK1		0x0C7C -#define PSB_CR_BIF_DIR_LIST_BASE0	0x0C84 -#define PSB_CR_BIF_TWOD_REQ_BASE	0x0C88 -#define PSB_CR_BIF_3D_REQ_BASE		0x0CAC - -#define PSB_CR_2D_SOCIF			0x0E18 -#define _PSB_C2_SOCIF_FREESPACE_SHIFT		(0) -#define _PSB_C2_SOCIF_FREESPACE_MASK		(0xFF << 0) -#define _PSB_C2_SOCIF_EMPTY			(0x80 << 0) - -#define PSB_CR_2D_BLIT_STATUS		0x0E04 -#define _PSB_C2B_STATUS_BUSY			(1 << 24) -#define _PSB_C2B_STATUS_COMPLETE_SHIFT		(0) -#define _PSB_C2B_STATUS_COMPLETE_MASK		(0xFFFFFF << 0) - -/* - * 2D defs. - */ - -/* - * 2D Slave Port Data : Block Header's Object Type - */ - -#define	PSB_2D_CLIP_BH			(0x00000000) -#define	PSB_2D_PAT_BH			(0x10000000) -#define	PSB_2D_CTRL_BH			(0x20000000) -#define	PSB_2D_SRC_OFF_BH		(0x30000000) -#define	PSB_2D_MASK_OFF_BH		(0x40000000) -#define	PSB_2D_RESERVED1_BH		(0x50000000) -#define	PSB_2D_RESERVED2_BH		(0x60000000) -#define	PSB_2D_FENCE_BH			(0x70000000) -#define	PSB_2D_BLIT_BH			(0x80000000) -#define	PSB_2D_SRC_SURF_BH		(0x90000000) -#define	PSB_2D_DST_SURF_BH		(0xA0000000) -#define	PSB_2D_PAT_SURF_BH		(0xB0000000) -#define	PSB_2D_SRC_PAL_BH		(0xC0000000) -#define	PSB_2D_PAT_PAL_BH		(0xD0000000) -#define	PSB_2D_MASK_SURF_BH		(0xE0000000) -#define	PSB_2D_FLUSH_BH			(0xF0000000) - -/* - * Clip Definition block (PSB_2D_CLIP_BH) - */ -#define PSB_2D_CLIPCOUNT_MAX		(1) -#define PSB_2D_CLIPCOUNT_MASK		(0x00000000) -#define PSB_2D_CLIPCOUNT_CLRMASK	(0xFFFFFFFF) -#define PSB_2D_CLIPCOUNT_SHIFT		(0) -/* clip rectangle min & max */ -#define PSB_2D_CLIP_XMAX_MASK		(0x00FFF000) -#define PSB_2D_CLIP_XMAX_CLRMASK	(0xFF000FFF) -#define PSB_2D_CLIP_XMAX_SHIFT		(12) -#define PSB_2D_CLIP_XMIN_MASK		(0x00000FFF) -#define PSB_2D_CLIP_XMIN_CLRMASK	(0x00FFF000) -#define PSB_2D_CLIP_XMIN_SHIFT		(0) -/* clip rectangle offset */ -#define PSB_2D_CLIP_YMAX_MASK		(0x00FFF000) -#define PSB_2D_CLIP_YMAX_CLRMASK	(0xFF000FFF) -#define PSB_2D_CLIP_YMAX_SHIFT		(12) -#define PSB_2D_CLIP_YMIN_MASK		(0x00000FFF) -#define PSB_2D_CLIP_YMIN_CLRMASK	(0x00FFF000) -#define PSB_2D_CLIP_YMIN_SHIFT		(0) - -/* - * Pattern Control (PSB_2D_PAT_BH) - */ -#define PSB_2D_PAT_HEIGHT_MASK		(0x0000001F) -#define PSB_2D_PAT_HEIGHT_SHIFT		(0) -#define PSB_2D_PAT_WIDTH_MASK		(0x000003E0) -#define PSB_2D_PAT_WIDTH_SHIFT		(5) -#define PSB_2D_PAT_YSTART_MASK		(0x00007C00) -#define PSB_2D_PAT_YSTART_SHIFT		(10) -#define PSB_2D_PAT_XSTART_MASK		(0x000F8000) -#define PSB_2D_PAT_XSTART_SHIFT		(15) - -/* - * 2D Control block (PSB_2D_CTRL_BH) - */ -/* Present Flags */ -#define PSB_2D_SRCCK_CTRL		(0x00000001) -#define PSB_2D_DSTCK_CTRL		(0x00000002) -#define PSB_2D_ALPHA_CTRL		(0x00000004) -/* Colour Key Colour (SRC/DST)*/ -#define PSB_2D_CK_COL_MASK		(0xFFFFFFFF) -#define PSB_2D_CK_COL_CLRMASK		(0x00000000) -#define PSB_2D_CK_COL_SHIFT		(0) -/* Colour Key Mask (SRC/DST)*/ -#define PSB_2D_CK_MASK_MASK		(0xFFFFFFFF) -#define PSB_2D_CK_MASK_CLRMASK		(0x00000000) -#define PSB_2D_CK_MASK_SHIFT		(0) -/* Alpha Control (Alpha/RGB)*/ -#define PSB_2D_GBLALPHA_MASK		(0x000FF000) -#define PSB_2D_GBLALPHA_CLRMASK		(0xFFF00FFF) -#define PSB_2D_GBLALPHA_SHIFT		(12) -#define PSB_2D_SRCALPHA_OP_MASK		(0x00700000) -#define PSB_2D_SRCALPHA_OP_CLRMASK	(0xFF8FFFFF) -#define PSB_2D_SRCALPHA_OP_SHIFT	(20) -#define PSB_2D_SRCALPHA_OP_ONE		(0x00000000) -#define PSB_2D_SRCALPHA_OP_SRC		(0x00100000) -#define PSB_2D_SRCALPHA_OP_DST		(0x00200000) -#define PSB_2D_SRCALPHA_OP_SG		(0x00300000) -#define PSB_2D_SRCALPHA_OP_DG		(0x00400000) -#define PSB_2D_SRCALPHA_OP_GBL		(0x00500000) -#define PSB_2D_SRCALPHA_OP_ZERO		(0x00600000) -#define PSB_2D_SRCALPHA_INVERT		(0x00800000) -#define PSB_2D_SRCALPHA_INVERT_CLR	(0xFF7FFFFF) -#define PSB_2D_DSTALPHA_OP_MASK		(0x07000000) -#define PSB_2D_DSTALPHA_OP_CLRMASK	(0xF8FFFFFF) -#define PSB_2D_DSTALPHA_OP_SHIFT	(24) -#define PSB_2D_DSTALPHA_OP_ONE		(0x00000000) -#define PSB_2D_DSTALPHA_OP_SRC		(0x01000000) -#define PSB_2D_DSTALPHA_OP_DST		(0x02000000) -#define PSB_2D_DSTALPHA_OP_SG		(0x03000000) -#define PSB_2D_DSTALPHA_OP_DG		(0x04000000) -#define PSB_2D_DSTALPHA_OP_GBL		(0x05000000) -#define PSB_2D_DSTALPHA_OP_ZERO		(0x06000000) -#define PSB_2D_DSTALPHA_INVERT		(0x08000000) -#define PSB_2D_DSTALPHA_INVERT_CLR	(0xF7FFFFFF) - -#define PSB_2D_PRE_MULTIPLICATION_ENABLE	(0x10000000) -#define PSB_2D_PRE_MULTIPLICATION_CLRMASK	(0xEFFFFFFF) -#define PSB_2D_ZERO_SOURCE_ALPHA_ENABLE		(0x20000000) -#define PSB_2D_ZERO_SOURCE_ALPHA_CLRMASK	(0xDFFFFFFF) - -/* - *Source Offset (PSB_2D_SRC_OFF_BH) - */ -#define PSB_2D_SRCOFF_XSTART_MASK	((0x00000FFF) << 12) -#define PSB_2D_SRCOFF_XSTART_SHIFT	(12) -#define PSB_2D_SRCOFF_YSTART_MASK	(0x00000FFF) -#define PSB_2D_SRCOFF_YSTART_SHIFT	(0) - -/* - * Mask Offset (PSB_2D_MASK_OFF_BH) - */ -#define PSB_2D_MASKOFF_XSTART_MASK	((0x00000FFF) << 12) -#define PSB_2D_MASKOFF_XSTART_SHIFT	(12) -#define PSB_2D_MASKOFF_YSTART_MASK	(0x00000FFF) -#define PSB_2D_MASKOFF_YSTART_SHIFT	(0) - -/* - * 2D Fence (see PSB_2D_FENCE_BH): bits 0:27 are ignored - */ - -/* - *Blit Rectangle (PSB_2D_BLIT_BH) - */ - -#define PSB_2D_ROT_MASK			(3 << 25) -#define PSB_2D_ROT_CLRMASK		(~PSB_2D_ROT_MASK) -#define PSB_2D_ROT_NONE			(0 << 25) -#define PSB_2D_ROT_90DEGS		(1 << 25) -#define PSB_2D_ROT_180DEGS		(2 << 25) -#define PSB_2D_ROT_270DEGS		(3 << 25) - -#define PSB_2D_COPYORDER_MASK		(3 << 23) -#define PSB_2D_COPYORDER_CLRMASK	(~PSB_2D_COPYORDER_MASK) -#define PSB_2D_COPYORDER_TL2BR		(0 << 23) -#define PSB_2D_COPYORDER_BR2TL		(1 << 23) -#define PSB_2D_COPYORDER_TR2BL		(2 << 23) -#define PSB_2D_COPYORDER_BL2TR		(3 << 23) - -#define PSB_2D_DSTCK_CLRMASK		(0xFF9FFFFF) -#define PSB_2D_DSTCK_DISABLE		(0x00000000) -#define PSB_2D_DSTCK_PASS		(0x00200000) -#define PSB_2D_DSTCK_REJECT		(0x00400000) - -#define PSB_2D_SRCCK_CLRMASK		(0xFFE7FFFF) -#define PSB_2D_SRCCK_DISABLE		(0x00000000) -#define PSB_2D_SRCCK_PASS		(0x00080000) -#define PSB_2D_SRCCK_REJECT		(0x00100000) - -#define PSB_2D_CLIP_ENABLE		(0x00040000) - -#define PSB_2D_ALPHA_ENABLE		(0x00020000) - -#define PSB_2D_PAT_CLRMASK		(0xFFFEFFFF) -#define PSB_2D_PAT_MASK			(0x00010000) -#define PSB_2D_USE_PAT			(0x00010000) -#define PSB_2D_USE_FILL			(0x00000000) -/* - * Tungsten Graphics note on rop codes: If rop A and rop B are - * identical, the mask surface will not be read and need not be - * set up. - */ - -#define PSB_2D_ROP3B_MASK		(0x0000FF00) -#define PSB_2D_ROP3B_CLRMASK		(0xFFFF00FF) -#define PSB_2D_ROP3B_SHIFT		(8) -/* rop code A */ -#define PSB_2D_ROP3A_MASK		(0x000000FF) -#define PSB_2D_ROP3A_CLRMASK		(0xFFFFFF00) -#define PSB_2D_ROP3A_SHIFT		(0) - -#define PSB_2D_ROP4_MASK		(0x0000FFFF) -/* - *	DWORD0:	(Only pass if Pattern control == Use Fill Colour) - *	Fill Colour RGBA8888 - */ -#define PSB_2D_FILLCOLOUR_MASK		(0xFFFFFFFF) -#define PSB_2D_FILLCOLOUR_SHIFT		(0) -/* - *	DWORD1: (Always Present) - *	X Start (Dest) - *	Y Start (Dest) - */ -#define PSB_2D_DST_XSTART_MASK		(0x00FFF000) -#define PSB_2D_DST_XSTART_CLRMASK	(0xFF000FFF) -#define PSB_2D_DST_XSTART_SHIFT		(12) -#define PSB_2D_DST_YSTART_MASK		(0x00000FFF) -#define PSB_2D_DST_YSTART_CLRMASK	(0xFFFFF000) -#define PSB_2D_DST_YSTART_SHIFT		(0) -/* - *	DWORD2: (Always Present) - *	X Size (Dest) - *	Y Size (Dest) - */ -#define PSB_2D_DST_XSIZE_MASK		(0x00FFF000) -#define PSB_2D_DST_XSIZE_CLRMASK	(0xFF000FFF) -#define PSB_2D_DST_XSIZE_SHIFT		(12) -#define PSB_2D_DST_YSIZE_MASK		(0x00000FFF) -#define PSB_2D_DST_YSIZE_CLRMASK	(0xFFFFF000) -#define PSB_2D_DST_YSIZE_SHIFT		(0) - -/* - * Source Surface (PSB_2D_SRC_SURF_BH) - */ -/* - * WORD 0 - */ - -#define PSB_2D_SRC_FORMAT_MASK		(0x00078000) -#define PSB_2D_SRC_1_PAL		(0x00000000) -#define PSB_2D_SRC_2_PAL		(0x00008000) -#define PSB_2D_SRC_4_PAL		(0x00010000) -#define PSB_2D_SRC_8_PAL		(0x00018000) -#define PSB_2D_SRC_8_ALPHA		(0x00020000) -#define PSB_2D_SRC_4_ALPHA		(0x00028000) -#define PSB_2D_SRC_332RGB		(0x00030000) -#define PSB_2D_SRC_4444ARGB		(0x00038000) -#define PSB_2D_SRC_555RGB		(0x00040000) -#define PSB_2D_SRC_1555ARGB		(0x00048000) -#define PSB_2D_SRC_565RGB		(0x00050000) -#define PSB_2D_SRC_0888ARGB		(0x00058000) -#define PSB_2D_SRC_8888ARGB		(0x00060000) -#define PSB_2D_SRC_8888UYVY		(0x00068000) -#define PSB_2D_SRC_RESERVED		(0x00070000) -#define PSB_2D_SRC_1555ARGB_LOOKUP	(0x00078000) - - -#define PSB_2D_SRC_STRIDE_MASK		(0x00007FFF) -#define PSB_2D_SRC_STRIDE_CLRMASK	(0xFFFF8000) -#define PSB_2D_SRC_STRIDE_SHIFT		(0) -/* - *  WORD 1 - Base Address - */ -#define PSB_2D_SRC_ADDR_MASK		(0x0FFFFFFC) -#define PSB_2D_SRC_ADDR_CLRMASK		(0x00000003) -#define PSB_2D_SRC_ADDR_SHIFT		(2) -#define PSB_2D_SRC_ADDR_ALIGNSHIFT	(2) - -/* - * Pattern Surface (PSB_2D_PAT_SURF_BH) - */ -/* - *  WORD 0 - */ - -#define PSB_2D_PAT_FORMAT_MASK		(0x00078000) -#define PSB_2D_PAT_1_PAL		(0x00000000) -#define PSB_2D_PAT_2_PAL		(0x00008000) -#define PSB_2D_PAT_4_PAL		(0x00010000) -#define PSB_2D_PAT_8_PAL		(0x00018000) -#define PSB_2D_PAT_8_ALPHA		(0x00020000) -#define PSB_2D_PAT_4_ALPHA		(0x00028000) -#define PSB_2D_PAT_332RGB		(0x00030000) -#define PSB_2D_PAT_4444ARGB		(0x00038000) -#define PSB_2D_PAT_555RGB		(0x00040000) -#define PSB_2D_PAT_1555ARGB		(0x00048000) -#define PSB_2D_PAT_565RGB		(0x00050000) -#define PSB_2D_PAT_0888ARGB		(0x00058000) -#define PSB_2D_PAT_8888ARGB		(0x00060000) - -#define PSB_2D_PAT_STRIDE_MASK		(0x00007FFF) -#define PSB_2D_PAT_STRIDE_CLRMASK	(0xFFFF8000) -#define PSB_2D_PAT_STRIDE_SHIFT		(0) -/* - *  WORD 1 - Base Address - */ -#define PSB_2D_PAT_ADDR_MASK		(0x0FFFFFFC) -#define PSB_2D_PAT_ADDR_CLRMASK		(0x00000003) -#define PSB_2D_PAT_ADDR_SHIFT		(2) -#define PSB_2D_PAT_ADDR_ALIGNSHIFT	(2) - -/* - * Destination Surface (PSB_2D_DST_SURF_BH) - */ -/* - * WORD 0 - */ - -#define PSB_2D_DST_FORMAT_MASK		(0x00078000) -#define PSB_2D_DST_332RGB		(0x00030000) -#define PSB_2D_DST_4444ARGB		(0x00038000) -#define PSB_2D_DST_555RGB		(0x00040000) -#define PSB_2D_DST_1555ARGB		(0x00048000) -#define PSB_2D_DST_565RGB		(0x00050000) -#define PSB_2D_DST_0888ARGB		(0x00058000) -#define PSB_2D_DST_8888ARGB		(0x00060000) -#define PSB_2D_DST_8888AYUV		(0x00070000) - -#define PSB_2D_DST_STRIDE_MASK		(0x00007FFF) -#define PSB_2D_DST_STRIDE_CLRMASK	(0xFFFF8000) -#define PSB_2D_DST_STRIDE_SHIFT		(0) -/* - * WORD 1 - Base Address - */ -#define PSB_2D_DST_ADDR_MASK		(0x0FFFFFFC) -#define PSB_2D_DST_ADDR_CLRMASK		(0x00000003) -#define PSB_2D_DST_ADDR_SHIFT		(2) -#define PSB_2D_DST_ADDR_ALIGNSHIFT	(2) - -/* - * Mask Surface (PSB_2D_MASK_SURF_BH) - */ -/* - * WORD 0 - */ -#define PSB_2D_MASK_STRIDE_MASK		(0x00007FFF) -#define PSB_2D_MASK_STRIDE_CLRMASK	(0xFFFF8000) -#define PSB_2D_MASK_STRIDE_SHIFT	(0) -/* - *  WORD 1 - Base Address - */ -#define PSB_2D_MASK_ADDR_MASK		(0x0FFFFFFC) -#define PSB_2D_MASK_ADDR_CLRMASK	(0x00000003) -#define PSB_2D_MASK_ADDR_SHIFT		(2) -#define PSB_2D_MASK_ADDR_ALIGNSHIFT	(2) - -/* - * Source Palette (PSB_2D_SRC_PAL_BH) - */ - -#define PSB_2D_SRCPAL_ADDR_SHIFT	(0) -#define PSB_2D_SRCPAL_ADDR_CLRMASK	(0xF0000007) -#define PSB_2D_SRCPAL_ADDR_MASK		(0x0FFFFFF8) -#define PSB_2D_SRCPAL_BYTEALIGN		(1024) - -/* - * Pattern Palette (PSB_2D_PAT_PAL_BH) - */ - -#define PSB_2D_PATPAL_ADDR_SHIFT	(0) -#define PSB_2D_PATPAL_ADDR_CLRMASK	(0xF0000007) -#define PSB_2D_PATPAL_ADDR_MASK		(0x0FFFFFF8) -#define PSB_2D_PATPAL_BYTEALIGN		(1024) - -/* - * Rop3 Codes (2 LS bytes) - */ - -#define PSB_2D_ROP3_SRCCOPY		(0xCCCC) -#define PSB_2D_ROP3_PATCOPY		(0xF0F0) -#define PSB_2D_ROP3_WHITENESS		(0xFFFF) -#define PSB_2D_ROP3_BLACKNESS		(0x0000) -#define PSB_2D_ROP3_SRC			(0xCC) -#define PSB_2D_ROP3_PAT			(0xF0) -#define PSB_2D_ROP3_DST			(0xAA) - -/* - * Sizes. - */ - -#define PSB_SCENE_HW_COOKIE_SIZE	16 -#define PSB_TA_MEM_HW_COOKIE_SIZE	16 - -/* - * Scene stuff. - */ - -#define PSB_NUM_HW_SCENES		2 - -/* - * Scheduler completion actions. - */ - -#define PSB_RASTER_BLOCK		0 -#define PSB_RASTER			1 -#define PSB_RETURN			2 -#define PSB_TA				3 - -/* Power management */ -#define PSB_PUNIT_PORT			0x04 -#define PSB_OSPMBA			0x78 -#define PSB_APMBA			0x7a -#define PSB_APM_CMD			0x0 -#define PSB_APM_STS			0x04 -#define PSB_PWRGT_VID_ENC_MASK		0x30 -#define PSB_PWRGT_VID_DEC_MASK		0xc -#define PSB_PWRGT_GL3_MASK		0xc0 - -#define PSB_PM_SSC			0x20 -#define PSB_PM_SSS			0x30 -#define PSB_PWRGT_DISPLAY_MASK		0xc /*on a different BA than video/gfx*/ -#define MDFLD_PWRGT_DISPLAY_A_CNTR	0x0000000c -#define MDFLD_PWRGT_DISPLAY_B_CNTR	0x0000c000 -#define MDFLD_PWRGT_DISPLAY_C_CNTR	0x00030000 -#define MDFLD_PWRGT_DISP_MIPI_CNTR	0x000c0000 -#define MDFLD_PWRGT_DISPLAY_CNTR    (MDFLD_PWRGT_DISPLAY_A_CNTR | MDFLD_PWRGT_DISPLAY_B_CNTR | MDFLD_PWRGT_DISPLAY_C_CNTR | MDFLD_PWRGT_DISP_MIPI_CNTR) /* 0x000fc00c */ -/* Display SSS register bits are different in A0 vs. B0 */ -#define PSB_PWRGT_GFX_MASK		0x3 -#define MDFLD_PWRGT_DISPLAY_A_STS	0x000000c0 -#define MDFLD_PWRGT_DISPLAY_B_STS	0x00000300 -#define MDFLD_PWRGT_DISPLAY_C_STS	0x00000c00 -#define PSB_PWRGT_GFX_MASK_B0		0xc3 -#define MDFLD_PWRGT_DISPLAY_A_STS_B0	0x0000000c -#define MDFLD_PWRGT_DISPLAY_B_STS_B0	0x0000c000 -#define MDFLD_PWRGT_DISPLAY_C_STS_B0	0x00030000 -#define MDFLD_PWRGT_DISP_MIPI_STS	0x000c0000 -#define MDFLD_PWRGT_DISPLAY_STS_A0    (MDFLD_PWRGT_DISPLAY_A_STS | MDFLD_PWRGT_DISPLAY_B_STS | MDFLD_PWRGT_DISPLAY_C_STS | MDFLD_PWRGT_DISP_MIPI_STS) /* 0x000fc00c */ -#define MDFLD_PWRGT_DISPLAY_STS_B0    (MDFLD_PWRGT_DISPLAY_A_STS_B0 | MDFLD_PWRGT_DISPLAY_B_STS_B0 | MDFLD_PWRGT_DISPLAY_C_STS_B0 | MDFLD_PWRGT_DISP_MIPI_STS) /* 0x000fc00c */ -#endif diff --git a/drivers/staging/media/go7007/go7007-usb.c b/drivers/staging/media/go7007/go7007-usb.c index 70e006b50f2..5443e25086e 100644 --- a/drivers/staging/media/go7007/go7007-usb.c +++ b/drivers/staging/media/go7007/go7007-usb.c @@ -1279,3 +1279,4 @@ static struct usb_driver go7007_usb_driver = {  };  module_usb_driver(go7007_usb_driver); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/omapdrm/Makefile b/drivers/staging/omapdrm/Makefile index 592cf69020c..d9cdc120d12 100644 --- a/drivers/staging/omapdrm/Makefile +++ b/drivers/staging/omapdrm/Makefile @@ -7,6 +7,7 @@ ccflags-y := -Iinclude/drm -Werror  omapdrm-y := omap_drv.o \  	omap_debugfs.o \  	omap_crtc.o \ +	omap_plane.o \  	omap_encoder.o \  	omap_connector.o \  	omap_fb.o \ diff --git a/drivers/staging/omapdrm/omap_crtc.c b/drivers/staging/omapdrm/omap_crtc.c index cffdf5e1239..17ca163e589 100644 --- a/drivers/staging/omapdrm/omap_crtc.c +++ b/drivers/staging/omapdrm/omap_crtc.c @@ -27,196 +27,95 @@  struct omap_crtc {  	struct drm_crtc base; -	struct omap_overlay *ovl; -	struct omap_overlay_info info; +	struct drm_plane *plane; +	const char *name;  	int id; -	/* if there is a pending flip, this will be non-null: */ +	/* if there is a pending flip, these will be non-null: */  	struct drm_pending_vblank_event *event; +	struct drm_framebuffer *old_fb;  }; -/* push changes down to dss2 */ -static int commit(struct drm_crtc *crtc) -{ -	struct drm_device *dev = crtc->dev; -	struct omap_crtc *omap_crtc = to_omap_crtc(crtc); -	struct omap_overlay *ovl = omap_crtc->ovl; -	struct omap_overlay_info *info = &omap_crtc->info; -	int ret; - -	DBG("%s", omap_crtc->ovl->name); -	DBG("%dx%d -> %dx%d (%d)", info->width, info->height, info->out_width, -			info->out_height, info->screen_width); -	DBG("%d,%d %08x", info->pos_x, info->pos_y, info->paddr); - -	/* NOTE: do we want to do this at all here, or just wait -	 * for dpms(ON) since other CRTC's may not have their mode -	 * set yet, so fb dimensions may still change.. -	 */ -	ret = ovl->set_overlay_info(ovl, info); -	if (ret) { -		dev_err(dev->dev, "could not set overlay info\n"); -		return ret; -	} - -	/* our encoder doesn't necessarily get a commit() after this, in -	 * particular in the dpms() and mode_set_base() cases, so force the -	 * manager to update: -	 * -	 * could this be in the encoder somehow? -	 */ -	if (ovl->manager) { -		ret = ovl->manager->apply(ovl->manager); -		if (ret) { -			dev_err(dev->dev, "could not apply settings\n"); -			return ret; -		} -	} - -	if (info->enabled) { -		omap_framebuffer_flush(crtc->fb, crtc->x, crtc->y, -				crtc->fb->width, crtc->fb->height); -	} - -	return 0; -} - -/* update parameters that are dependent on the framebuffer dimensions and - * position within the fb that this crtc scans out from. This is called - * when framebuffer dimensions or x,y base may have changed, either due - * to our mode, or a change in another crtc that is scanning out of the - * same fb. - */ -static void update_scanout(struct drm_crtc *crtc) -{ -	struct omap_crtc *omap_crtc = to_omap_crtc(crtc); -	dma_addr_t paddr; -	unsigned int screen_width; - -	omap_framebuffer_get_buffer(crtc->fb, crtc->x, crtc->y, -			NULL, &paddr, &screen_width); - -	DBG("%s: %d,%d: %08x (%d)", omap_crtc->ovl->name, -			crtc->x, crtc->y, (u32)paddr, screen_width); - -	omap_crtc->info.paddr = paddr; -	omap_crtc->info.screen_width = screen_width; -} -  static void omap_crtc_gamma_set(struct drm_crtc *crtc,  		u16 *red, u16 *green, u16 *blue, uint32_t start, uint32_t size)  { -	struct omap_crtc *omap_crtc = to_omap_crtc(crtc); -	DBG("%s", omap_crtc->ovl->name); +	/* not supported.. at least not yet */  }  static void omap_crtc_destroy(struct drm_crtc *crtc)  {  	struct omap_crtc *omap_crtc = to_omap_crtc(crtc); -	DBG("%s", omap_crtc->ovl->name); +	omap_crtc->plane->funcs->destroy(omap_crtc->plane);  	drm_crtc_cleanup(crtc);  	kfree(omap_crtc);  }  static void omap_crtc_dpms(struct drm_crtc *crtc, int mode)  { +	struct omap_drm_private *priv = crtc->dev->dev_private;  	struct omap_crtc *omap_crtc = to_omap_crtc(crtc); +	int i; -	DBG("%s: %d", omap_crtc->ovl->name, mode); +	WARN_ON(omap_plane_dpms(omap_crtc->plane, mode)); -	if (mode == DRM_MODE_DPMS_ON) { -		update_scanout(crtc); -		omap_crtc->info.enabled = true; -	} else { -		omap_crtc->info.enabled = false; +	for (i = 0; i < priv->num_planes; i++) { +		struct drm_plane *plane = priv->planes[i]; +		if (plane->crtc == crtc) +			WARN_ON(omap_plane_dpms(plane, mode));  	} - -	WARN_ON(commit(crtc));  }  static bool omap_crtc_mode_fixup(struct drm_crtc *crtc, -				  struct drm_display_mode *mode, -				  struct drm_display_mode *adjusted_mode) +		struct drm_display_mode *mode, +		struct drm_display_mode *adjusted_mode)  { -	struct omap_crtc *omap_crtc = to_omap_crtc(crtc); -	DBG("%s", omap_crtc->ovl->name);  	return true;  }  static int omap_crtc_mode_set(struct drm_crtc *crtc, -			       struct drm_display_mode *mode, -			       struct drm_display_mode *adjusted_mode, -			       int x, int y, -			       struct drm_framebuffer *old_fb) +		struct drm_display_mode *mode, +		struct drm_display_mode *adjusted_mode, +		int x, int y, +		struct drm_framebuffer *old_fb)  {  	struct omap_crtc *omap_crtc = to_omap_crtc(crtc); +	struct drm_plane *plane = omap_crtc->plane; -	DBG("%s: %d,%d: %dx%d", omap_crtc->ovl->name, x, y, -			mode->hdisplay, mode->vdisplay); - -	/* just use adjusted mode */ -	mode = adjusted_mode; - -	omap_crtc->info.width = mode->hdisplay; -	omap_crtc->info.height = mode->vdisplay; -	omap_crtc->info.out_width = mode->hdisplay; -	omap_crtc->info.out_height = mode->vdisplay; -	omap_crtc->info.color_mode = OMAP_DSS_COLOR_RGB24U; -	omap_crtc->info.rotation_type = OMAP_DSS_ROT_DMA; -	omap_crtc->info.rotation = OMAP_DSS_ROT_0; -	omap_crtc->info.global_alpha = 0xff; -	omap_crtc->info.mirror = 0; -	omap_crtc->info.mirror = 0; -	omap_crtc->info.pos_x = 0; -	omap_crtc->info.pos_y = 0; -#if 0 /* re-enable when these are available in DSS2 driver */ -	omap_crtc->info.zorder = 3;        /* GUI in the front, video behind */ -	omap_crtc->info.min_x_decim = 1; -	omap_crtc->info.max_x_decim = 1; -	omap_crtc->info.min_y_decim = 1; -	omap_crtc->info.max_y_decim = 1; -#endif - -	update_scanout(crtc); - -	return 0; +	return omap_plane_mode_set(plane, crtc, crtc->fb, +			0, 0, mode->hdisplay, mode->vdisplay, +			x << 16, y << 16, +			mode->hdisplay << 16, mode->vdisplay << 16);  }  static void omap_crtc_prepare(struct drm_crtc *crtc)  {  	struct omap_crtc *omap_crtc = to_omap_crtc(crtc); -	struct omap_overlay *ovl = omap_crtc->ovl; - -	DBG("%s", omap_crtc->ovl->name); - -	ovl->get_overlay_info(ovl, &omap_crtc->info); - +	DBG("%s", omap_crtc->name);  	omap_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);  }  static void omap_crtc_commit(struct drm_crtc *crtc)  {  	struct omap_crtc *omap_crtc = to_omap_crtc(crtc); -	DBG("%s", omap_crtc->ovl->name); +	DBG("%s", omap_crtc->name);  	omap_crtc_dpms(crtc, DRM_MODE_DPMS_ON);  }  static int omap_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, -		    struct drm_framebuffer *old_fb) +		struct drm_framebuffer *old_fb)  {  	struct omap_crtc *omap_crtc = to_omap_crtc(crtc); +	struct drm_plane *plane = omap_crtc->plane; +	struct drm_display_mode *mode = &crtc->mode; -	DBG("%s %d,%d: fb=%p", omap_crtc->ovl->name, x, y, old_fb); - -	update_scanout(crtc); - -	return commit(crtc); +	return plane->funcs->update_plane(plane, crtc, crtc->fb, +			0, 0, mode->hdisplay, mode->vdisplay, +			x << 16, y << 16, +			mode->hdisplay << 16, mode->vdisplay << 16);  }  static void omap_crtc_load_lut(struct drm_crtc *crtc)  { -	struct omap_crtc *omap_crtc = to_omap_crtc(crtc); -	DBG("%s", omap_crtc->ovl->name);  }  static void page_flip_cb(void *arg) @@ -225,15 +124,16 @@ static void page_flip_cb(void *arg)  	struct drm_device *dev = crtc->dev;  	struct omap_crtc *omap_crtc = to_omap_crtc(crtc);  	struct drm_pending_vblank_event *event = omap_crtc->event; +	struct drm_framebuffer *old_fb = omap_crtc->old_fb;  	struct timeval now;  	unsigned long flags;  	WARN_ON(!event);  	omap_crtc->event = NULL; +	omap_crtc->old_fb = NULL; -	update_scanout(crtc); -	WARN_ON(commit(crtc)); +	omap_crtc_mode_set_base(crtc, crtc->x, crtc->y, old_fb);  	/* wakeup userspace */  	/* TODO: this should happen *after* flip in vsync IRQ handler */ @@ -264,10 +164,11 @@ static int omap_crtc_page_flip_locked(struct drm_crtc *crtc,  		return -EINVAL;  	} -	crtc->fb = fb; +	omap_crtc->old_fb = crtc->fb;  	omap_crtc->event = event; +	crtc->fb = fb; -	omap_gem_op_async(omap_framebuffer_bo(fb), OMAP_GEM_READ, +	omap_gem_op_async(omap_framebuffer_bo(fb, 0), OMAP_GEM_READ,  			page_flip_cb, crtc);  	return 0; @@ -290,12 +191,6 @@ static const struct drm_crtc_helper_funcs omap_crtc_helper_funcs = {  	.load_lut = omap_crtc_load_lut,  }; -struct omap_overlay *omap_crtc_get_overlay(struct drm_crtc *crtc) -{ -	struct omap_crtc *omap_crtc = to_omap_crtc(crtc); -	return omap_crtc->ovl; -} -  /* initialize crtc */  struct drm_crtc *omap_crtc_init(struct drm_device *dev,  		struct omap_overlay *ovl, int id) @@ -310,9 +205,13 @@ struct drm_crtc *omap_crtc_init(struct drm_device *dev,  		goto fail;  	} -	omap_crtc->ovl = ovl; -	omap_crtc->id = id;  	crtc = &omap_crtc->base; + +	omap_crtc->plane = omap_plane_init(dev, ovl, (1 << id), true); +	omap_crtc->plane->crtc = crtc; +	omap_crtc->name = ovl->name; +	omap_crtc->id = id; +  	drm_crtc_init(dev, crtc, &omap_crtc_funcs);  	drm_crtc_helper_add(crtc, &omap_crtc_helper_funcs); diff --git a/drivers/staging/omapdrm/omap_drv.c b/drivers/staging/omapdrm/omap_drv.c index 602aa2dd49c..3bbea9aac40 100644 --- a/drivers/staging/omapdrm/omap_drv.c +++ b/drivers/staging/omapdrm/omap_drv.c @@ -204,12 +204,6 @@ static int create_crtc(struct drm_device *dev, struct omap_overlay *ovl,  	struct omap_overlay_manager *mgr = NULL;  	struct drm_crtc *crtc; -	if (ovl->manager) { -		DBG("disconnecting %s from %s", ovl->name, -					ovl->manager->name); -		ovl->unset_manager(ovl); -	} -  	/* find next best connector, ones with detected connection first  	 */  	while (*j < priv->num_connectors && !mgr) { @@ -245,11 +239,6 @@ static int create_crtc(struct drm_device *dev, struct omap_overlay *ovl,  		(*j)++;  	} -	if (mgr) { -		DBG("connecting %s to %s", ovl->name, mgr->name); -		ovl->set_manager(ovl, mgr); -	} -  	crtc = omap_crtc_init(dev, ovl, priv->num_crtcs);  	if (!crtc) { @@ -265,6 +254,26 @@ static int create_crtc(struct drm_device *dev, struct omap_overlay *ovl,  	return 0;  } +static int create_plane(struct drm_device *dev, struct omap_overlay *ovl, +		unsigned int possible_crtcs) +{ +	struct omap_drm_private *priv = dev->dev_private; +	struct drm_plane *plane = +			omap_plane_init(dev, ovl, possible_crtcs, false); + +	if (!plane) { +		dev_err(dev->dev, "could not create plane: %s\n", +				ovl->name); +		return -ENOMEM; +	} + +	BUG_ON(priv->num_planes >= ARRAY_SIZE(priv->planes)); + +	priv->planes[priv->num_planes++] = plane; + +	return 0; +} +  static int match_dev_name(struct omap_dss_device *dssdev, void *data)  {  	return !strcmp(dssdev->name, data); @@ -332,6 +341,12 @@ static int omap_modeset_init(struct drm_device *dev)  				omap_dss_get_overlay(kms_pdata->ovl_ids[i]);  			create_crtc(dev, ovl, &j, connected_connectors);  		} + +		for (i = 0; i < kms_pdata->pln_cnt; i++) { +			struct omap_overlay *ovl = +				omap_dss_get_overlay(kms_pdata->pln_ids[i]); +			create_plane(dev, ovl, (1 << priv->num_crtcs) - 1); +		}  	} else {  		/* otherwise just grab up to CONFIG_DRM_OMAP_NUM_CRTCS and try  		 * to make educated guesses about everything else @@ -353,6 +368,12 @@ static int omap_modeset_init(struct drm_device *dev)  			create_crtc(dev, omap_dss_get_overlay(i),  					&j, connected_connectors);  		} + +		/* use any remaining overlays as drm planes */ +		for (; i < omap_dss_get_num_overlays(); i++) { +			struct omap_overlay *ovl = omap_dss_get_overlay(i); +			create_plane(dev, ovl, (1 << priv->num_crtcs) - 1); +		}  	}  	/* for now keep the mapping of CRTCs and encoders static.. */ @@ -361,15 +382,7 @@ static int omap_modeset_init(struct drm_device *dev)  		struct omap_overlay_manager *mgr =  				omap_encoder_get_manager(encoder); -		encoder->possible_crtcs = 0; - -		for (j = 0; j < priv->num_crtcs; j++) { -			struct omap_overlay *ovl = -					omap_crtc_get_overlay(priv->crtcs[j]); -			if (ovl->manager == mgr) { -				encoder->possible_crtcs |= (1 << j); -			} -		} +		encoder->possible_crtcs = (1 << priv->num_crtcs) - 1;  		DBG("%s: possible_crtcs=%08x", mgr->name,  					encoder->possible_crtcs); @@ -377,8 +390,8 @@ static int omap_modeset_init(struct drm_device *dev)  	dump_video_chains(); -	dev->mode_config.min_width = 256; -	dev->mode_config.min_height = 256; +	dev->mode_config.min_width = 32; +	dev->mode_config.min_height = 32;  	/* note: eventually will need some cpu_is_omapXYZ() type stuff here  	 * to fill in these limits properly on different OMAP generations.. @@ -708,6 +721,18 @@ static struct vm_operations_struct omap_gem_vm_ops = {  	.close = drm_gem_vm_close,  }; +static const struct file_operations omapdriver_fops = { +		.owner = THIS_MODULE, +		.open = drm_open, +		.unlocked_ioctl = drm_ioctl, +		.release = drm_release, +		.mmap = omap_gem_mmap, +		.poll = drm_poll, +		.fasync = drm_fasync, +		.read = drm_read, +		.llseek = noop_llseek, +}; +  static struct drm_driver omap_drm_driver = {  		.driver_features =  				DRIVER_HAVE_IRQ | DRIVER_MODESET | DRIVER_GEM, @@ -738,17 +763,7 @@ static struct drm_driver omap_drm_driver = {  		.dumb_destroy = omap_gem_dumb_destroy,  		.ioctls = ioctls,  		.num_ioctls = DRM_OMAP_NUM_IOCTLS, -		.fops = { -				.owner = THIS_MODULE, -				.open = drm_open, -				.unlocked_ioctl = drm_ioctl, -				.release = drm_release, -				.mmap = omap_gem_mmap, -				.poll = drm_poll, -				.fasync = drm_fasync, -				.read = drm_read, -				.llseek = noop_llseek, -		}, +		.fops = &omapdriver_fops,  		.name = DRIVER_NAME,  		.desc = DRIVER_DESC,  		.date = DRIVER_DATE, diff --git a/drivers/staging/omapdrm/omap_drv.h b/drivers/staging/omapdrm/omap_drv.h index 76c42515ecc..61fe022dda5 100644 --- a/drivers/staging/omapdrm/omap_drv.h +++ b/drivers/staging/omapdrm/omap_drv.h @@ -24,6 +24,7 @@  #include <linux/module.h>  #include <linux/types.h>  #include <drm/drmP.h> +#include <drm/drm_crtc_helper.h>  #include "omap_drm.h"  #include "omap_priv.h" @@ -41,6 +42,8 @@  struct omap_drm_private {  	unsigned int num_crtcs;  	struct drm_crtc *crtcs[8]; +	unsigned int num_planes; +	struct drm_plane *planes[8];  	unsigned int num_encoders;  	struct drm_encoder *encoders[8];  	unsigned int num_connectors; @@ -61,7 +64,17 @@ void omap_fbdev_free(struct drm_device *dev);  struct drm_crtc *omap_crtc_init(struct drm_device *dev,  		struct omap_overlay *ovl, int id); -struct omap_overlay *omap_crtc_get_overlay(struct drm_crtc *crtc); + +struct drm_plane *omap_plane_init(struct drm_device *dev, +		struct omap_overlay *ovl, unsigned int possible_crtcs, +		bool priv); +int omap_plane_dpms(struct drm_plane *plane, int mode); +int omap_plane_mode_set(struct drm_plane *plane, +		struct drm_crtc *crtc, struct drm_framebuffer *fb, +		int crtc_x, int crtc_y, +		unsigned int crtc_w, unsigned int crtc_h, +		uint32_t src_x, uint32_t src_y, +		uint32_t src_w, uint32_t src_h);  struct drm_encoder *omap_encoder_init(struct drm_device *dev,  		struct omap_overlay_manager *mgr); @@ -80,12 +93,14 @@ void omap_connector_flush(struct drm_connector *connector,  		int x, int y, int w, int h);  struct drm_framebuffer *omap_framebuffer_create(struct drm_device *dev, -		struct drm_file *file, struct drm_mode_fb_cmd *mode_cmd); +		struct drm_file *file, struct drm_mode_fb_cmd2 *mode_cmd);  struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev, -		struct drm_mode_fb_cmd *mode_cmd, struct drm_gem_object *bo); -struct drm_gem_object *omap_framebuffer_bo(struct drm_framebuffer *fb); -int omap_framebuffer_get_buffer(struct drm_framebuffer *fb, int x, int y, -		void **vaddr, dma_addr_t *paddr, unsigned int *screen_width); +		struct drm_mode_fb_cmd2 *mode_cmd, struct drm_gem_object **bos); +struct drm_gem_object *omap_framebuffer_bo(struct drm_framebuffer *fb, int p); +int omap_framebuffer_pin(struct drm_framebuffer *fb); +void omap_framebuffer_unpin(struct drm_framebuffer *fb); +void omap_framebuffer_update_scanout(struct drm_framebuffer *fb, int x, int y, +		struct omap_overlay_info *info);  struct drm_connector *omap_framebuffer_get_next_connector(  		struct drm_framebuffer *fb, struct drm_connector *from);  void omap_framebuffer_flush(struct drm_framebuffer *fb, @@ -132,4 +147,29 @@ static inline int align_pitch(int pitch, int width, int bpp)  	return ALIGN(pitch, 8 * bytespp);  } +/* should these be made into common util helpers? + */ + +static inline int objects_lookup(struct drm_device *dev, +		struct drm_file *filp, uint32_t pixel_format, +		struct drm_gem_object **bos, uint32_t *handles) +{ +	int i, n = drm_format_num_planes(pixel_format); + +	for (i = 0; i < n; i++) { +		bos[i] = drm_gem_object_lookup(dev, filp, handles[i]); +		if (!bos[i]) { +			goto fail; +		} +	} + +	return 0; + +fail: +	while (--i > 0) { +		drm_gem_object_unreference_unlocked(bos[i]); +	} +	return -ENOENT; +} +  #endif /* __OMAP_DRV_H__ */ diff --git a/drivers/staging/omapdrm/omap_fb.c b/drivers/staging/omapdrm/omap_fb.c index 0b50c5b3b56..d021a7ec58d 100644 --- a/drivers/staging/omapdrm/omap_fb.c +++ b/drivers/staging/omapdrm/omap_fb.c @@ -22,18 +22,57 @@  #include "drm_crtc.h"  #include "drm_crtc_helper.h" -  /*   * framebuffer funcs   */ +/* per-format info: */ +struct format { +	enum omap_color_mode dss_format; +	uint32_t pixel_format; +	struct { +		int stride_bpp;           /* this times width is stride */ +		int sub_y;                /* sub-sample in y dimension */ +	} planes[4]; +	bool yuv; +}; + +static const struct format formats[] = { +	/* 16bpp [A]RGB: */ +	{ OMAP_DSS_COLOR_RGB16,       DRM_FORMAT_RGB565,   {{2, 1}}, false }, /* RGB16-565 */ +	{ OMAP_DSS_COLOR_RGB12U,      DRM_FORMAT_RGBX4444, {{2, 1}}, false }, /* RGB12x-4444 */ +	{ OMAP_DSS_COLOR_RGBX16,      DRM_FORMAT_XRGB4444, {{2, 1}}, false }, /* xRGB12-4444 */ +	{ OMAP_DSS_COLOR_RGBA16,      DRM_FORMAT_RGBA4444, {{2, 1}}, false }, /* RGBA12-4444 */ +	{ OMAP_DSS_COLOR_ARGB16,      DRM_FORMAT_ARGB4444, {{2, 1}}, false }, /* ARGB16-4444 */ +	{ OMAP_DSS_COLOR_XRGB16_1555, DRM_FORMAT_XRGB1555, {{2, 1}}, false }, /* xRGB15-1555 */ +	{ OMAP_DSS_COLOR_ARGB16_1555, DRM_FORMAT_ARGB1555, {{2, 1}}, false }, /* ARGB16-1555 */ +	/* 24bpp RGB: */ +	{ OMAP_DSS_COLOR_RGB24P,      DRM_FORMAT_RGB888,   {{3, 1}}, false }, /* RGB24-888 */ +	/* 32bpp [A]RGB: */ +	{ OMAP_DSS_COLOR_RGBX32,      DRM_FORMAT_RGBX8888, {{4, 1}}, false }, /* RGBx24-8888 */ +	{ OMAP_DSS_COLOR_RGB24U,      DRM_FORMAT_XRGB8888, {{4, 1}}, false }, /* xRGB24-8888 */ +	{ OMAP_DSS_COLOR_RGBA32,      DRM_FORMAT_RGBA8888, {{4, 1}}, false }, /* RGBA32-8888 */ +	{ OMAP_DSS_COLOR_ARGB32,      DRM_FORMAT_ARGB8888, {{4, 1}}, false }, /* ARGB32-8888 */ +	/* YUV: */ +	{ OMAP_DSS_COLOR_NV12,        DRM_FORMAT_NV12,     {{1, 1}, {1, 2}}, true }, +	{ OMAP_DSS_COLOR_YUV2,        DRM_FORMAT_YUYV,     {{2, 1}}, true }, +	{ OMAP_DSS_COLOR_UYVY,        DRM_FORMAT_UYVY,     {{2, 1}}, true }, +}; + +/* per-plane info for the fb: */ +struct plane { +	struct drm_gem_object *bo; +	uint32_t pitch; +	uint32_t offset; +	dma_addr_t paddr; +}; +  #define to_omap_framebuffer(x) container_of(x, struct omap_framebuffer, base)  struct omap_framebuffer {  	struct drm_framebuffer base; -	struct drm_gem_object *bo; -	int size; -	dma_addr_t paddr; +	const struct format *format; +	struct plane planes[4];  };  static int omap_framebuffer_create_handle(struct drm_framebuffer *fb, @@ -41,22 +80,23 @@ static int omap_framebuffer_create_handle(struct drm_framebuffer *fb,  		unsigned int *handle)  {  	struct omap_framebuffer *omap_fb = to_omap_framebuffer(fb); -    return drm_gem_handle_create(file_priv, omap_fb->bo, handle); +	return drm_gem_handle_create(file_priv, +			omap_fb->planes[0].bo, handle);  }  static void omap_framebuffer_destroy(struct drm_framebuffer *fb)  { -	struct drm_device *dev = fb->dev;  	struct omap_framebuffer *omap_fb = to_omap_framebuffer(fb); +	int i, n = drm_format_num_planes(omap_fb->format->pixel_format);  	DBG("destroy: FB ID: %d (%p)", fb->base.id, fb);  	drm_framebuffer_cleanup(fb); -	if (omap_fb->bo) { -		if (omap_fb->paddr && omap_gem_put_paddr(omap_fb->bo)) -			dev_err(dev->dev, "could not unmap!\n"); -		drm_gem_object_unreference_unlocked(omap_fb->bo); +	for (i = 0; i < n; i++) { +		struct plane *plane = &omap_fb->planes[i]; +		if (plane->bo) +			drm_gem_object_unreference_unlocked(plane->bo);  	}  	kfree(omap_fb); @@ -83,37 +123,76 @@ static const struct drm_framebuffer_funcs omap_framebuffer_funcs = {  	.dirty = omap_framebuffer_dirty,  }; -/* returns the buffer size */ -int omap_framebuffer_get_buffer(struct drm_framebuffer *fb, int x, int y, -		void **vaddr, dma_addr_t *paddr, unsigned int *screen_width) +/* pins buffer in preparation for scanout */ +int omap_framebuffer_pin(struct drm_framebuffer *fb)  {  	struct omap_framebuffer *omap_fb = to_omap_framebuffer(fb); -	int bpp = fb->bits_per_pixel / 8; -	unsigned long offset; +	int ret, i, n = drm_format_num_planes(omap_fb->format->pixel_format); -	offset = (x * bpp) + (y * fb->pitch); +	for (i = 0; i < n; i++) { +		struct plane *plane = &omap_fb->planes[i]; +		ret = omap_gem_get_paddr(plane->bo, &plane->paddr, true); +		if (ret) +			goto fail; +	} + +	return 0; -	if (vaddr) { -		void *bo_vaddr = omap_gem_vaddr(omap_fb->bo); -		/* note: we can only count on having a vaddr for buffers that -		 * are allocated physically contiguously to begin with (ie. -		 * dma_alloc_coherent()).  But this should be ok because it -		 * is only used by legacy fbdev -		 */ -		BUG_ON(IS_ERR_OR_NULL(bo_vaddr)); -		*vaddr = bo_vaddr + offset; +fail: +	while (--i > 0) { +		struct plane *plane = &omap_fb->planes[i]; +		omap_gem_put_paddr(plane->bo);  	} +	return ret; +} + +/* releases buffer when done with scanout */ +void omap_framebuffer_unpin(struct drm_framebuffer *fb) +{ +	struct omap_framebuffer *omap_fb = to_omap_framebuffer(fb); +	int i, n = drm_format_num_planes(omap_fb->format->pixel_format); + +	for (i = 0; i < n; i++) { +		struct plane *plane = &omap_fb->planes[i]; +		omap_gem_put_paddr(plane->bo); +	} +} -	*paddr = omap_fb->paddr + offset; -	*screen_width = fb->pitch / bpp; +/* update ovl info for scanout, handles cases of multi-planar fb's, etc. + */ +void omap_framebuffer_update_scanout(struct drm_framebuffer *fb, int x, int y, +		struct omap_overlay_info *info) +{ +	struct omap_framebuffer *omap_fb = to_omap_framebuffer(fb); +	const struct format *format = omap_fb->format; +	struct plane *plane = &omap_fb->planes[0]; +	unsigned int offset; -	return omap_fb->size - offset; +	offset = plane->offset + +			(x * format->planes[0].stride_bpp) + +			(y * plane->pitch / format->planes[0].sub_y); + +	info->color_mode   = format->dss_format; +	info->paddr        = plane->paddr + offset; +	info->screen_width = plane->pitch / format->planes[0].stride_bpp; + +	if (format->dss_format == OMAP_DSS_COLOR_NV12) { +		plane = &omap_fb->planes[1]; +		offset = plane->offset + +				(x * format->planes[1].stride_bpp) + +				(y * plane->pitch / format->planes[1].sub_y); +		info->p_uv_addr = plane->paddr + offset; +	} else { +		info->p_uv_addr = 0; +	}  } -struct drm_gem_object *omap_framebuffer_bo(struct drm_framebuffer *fb) +struct drm_gem_object *omap_framebuffer_bo(struct drm_framebuffer *fb, int p)  {  	struct omap_framebuffer *omap_fb = to_omap_framebuffer(fb); -	return omap_fb->bo; +	if (p >= drm_format_num_planes(omap_fb->format->pixel_format)) +		return NULL; +	return omap_fb->planes[p].bo;  }  /* iterate thru all the connectors, returning ones that are attached @@ -171,39 +250,57 @@ void omap_framebuffer_flush(struct drm_framebuffer *fb,  }  struct drm_framebuffer *omap_framebuffer_create(struct drm_device *dev, -		struct drm_file *file, struct drm_mode_fb_cmd *mode_cmd) +		struct drm_file *file, struct drm_mode_fb_cmd2 *mode_cmd)  { -	struct drm_gem_object *bo; +	struct drm_gem_object *bos[4];  	struct drm_framebuffer *fb; -	bo = drm_gem_object_lookup(dev, file, mode_cmd->handle); -	if (!bo) { -		return ERR_PTR(-ENOENT); -	} -	fb = omap_framebuffer_init(dev, mode_cmd, bo); -	if (!fb) { -		return ERR_PTR(-ENOMEM); +	int ret; + +	ret = objects_lookup(dev, file, mode_cmd->pixel_format, +			bos, mode_cmd->handles); +	if (ret) +		return ERR_PTR(ret); + +	fb = omap_framebuffer_init(dev, mode_cmd, bos); +	if (IS_ERR(fb)) { +		int i, n = drm_format_num_planes(mode_cmd->pixel_format); +		for (i = 0; i < n; i++) +			drm_gem_object_unreference_unlocked(bos[i]); +		return fb;  	}  	return fb;  }  struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev, -		struct drm_mode_fb_cmd *mode_cmd, struct drm_gem_object *bo) +		struct drm_mode_fb_cmd2 *mode_cmd, struct drm_gem_object **bos)  {  	struct omap_framebuffer *omap_fb;  	struct drm_framebuffer *fb = NULL; -	int size, ret; +	const struct format *format = NULL; +	int ret, i, n = drm_format_num_planes(mode_cmd->pixel_format); -	DBG("create framebuffer: dev=%p, mode_cmd=%p (%dx%d@%d)", +	DBG("create framebuffer: dev=%p, mode_cmd=%p (%dx%d@%4.4s)",  			dev, mode_cmd, mode_cmd->width, mode_cmd->height, -			mode_cmd->bpp); +			(char *)&mode_cmd->pixel_format); -	/* in case someone tries to feed us a completely bogus stride: */ -	mode_cmd->pitch = align_pitch(mode_cmd->pitch, -			mode_cmd->width, mode_cmd->bpp); +	for (i = 0; i < ARRAY_SIZE(formats); i++) { +		if (formats[i].pixel_format == mode_cmd->pixel_format) { +			format = &formats[i]; +			break; +		} +	} + +	if (!format) { +		dev_err(dev->dev, "unsupported pixel format: %4.4s\n", +				(char *)&mode_cmd->pixel_format); +		ret = -EINVAL; +		goto fail; +	}  	omap_fb = kzalloc(sizeof(*omap_fb), GFP_KERNEL);  	if (!omap_fb) {  		dev_err(dev->dev, "could not allocate fb\n"); +		ret = -ENOMEM;  		goto fail;  	} @@ -216,19 +313,32 @@ struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev,  	DBG("create: FB ID: %d (%p)", fb->base.id, fb); -	size = PAGE_ALIGN(mode_cmd->pitch * mode_cmd->height); +	omap_fb->format = format; -	if (size > bo->size) { -		dev_err(dev->dev, "provided buffer object is too small!\n"); -		goto fail; -	} +	for (i = 0; i < n; i++) { +		struct plane *plane = &omap_fb->planes[i]; +		int size, pitch = mode_cmd->pitches[i]; -	omap_fb->bo = bo; -	omap_fb->size = size; +		if (pitch < (mode_cmd->width * format->planes[i].stride_bpp)) { +			dev_err(dev->dev, "provided buffer pitch is too small! %d < %d\n", +					pitch, mode_cmd->width * format->planes[i].stride_bpp); +			ret = -EINVAL; +			goto fail; +		} -	if (omap_gem_get_paddr(bo, &omap_fb->paddr, true)) { -		dev_err(dev->dev, "could not map (paddr)!\n"); -		goto fail; +		size = pitch * mode_cmd->height / format->planes[i].sub_y; + +		if (size > (bos[i]->size - mode_cmd->offsets[i])) { +			dev_err(dev->dev, "provided buffer object is too small! %d < %d\n", +					bos[i]->size - mode_cmd->offsets[i], size); +			ret = -EINVAL; +			goto fail; +		} + +		plane->bo     = bos[i]; +		plane->offset = mode_cmd->offsets[i]; +		plane->pitch  = mode_cmd->pitches[i]; +		plane->paddr  = pitch;  	}  	drm_helper_mode_fill_fb_struct(fb, mode_cmd); @@ -239,5 +349,5 @@ fail:  	if (fb) {  		omap_framebuffer_destroy(fb);  	} -	return NULL; +	return ERR_PTR(ret);  } diff --git a/drivers/staging/omapdrm/omap_fbdev.c b/drivers/staging/omapdrm/omap_fbdev.c index 093ae2f87b2..96940bbfc6f 100644 --- a/drivers/staging/omapdrm/omap_fbdev.c +++ b/drivers/staging/omapdrm/omap_fbdev.c @@ -129,10 +129,8 @@ static int omap_fbdev_create(struct drm_fb_helper *helper,  	struct drm_framebuffer *fb = NULL;  	union omap_gem_size gsize;  	struct fb_info *fbi = NULL; -	struct drm_mode_fb_cmd mode_cmd = {0}; +	struct drm_mode_fb_cmd2 mode_cmd = {0};  	dma_addr_t paddr; -	void __iomem *vaddr; -	int size, screen_width;  	int ret;  	/* only doing ARGB32 since this is what is needed to alpha-blend @@ -145,36 +143,56 @@ static int omap_fbdev_create(struct drm_fb_helper *helper,  			sizes->surface_height, sizes->surface_bpp,  			sizes->fb_width, sizes->fb_height); +	mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, +			sizes->surface_depth); +  	mode_cmd.width = sizes->surface_width;  	mode_cmd.height = sizes->surface_height; -	mode_cmd.bpp = sizes->surface_bpp; -	mode_cmd.depth = sizes->surface_depth; - -	mode_cmd.pitch = align_pitch( -			mode_cmd.width * ((mode_cmd.bpp + 7) / 8), -			mode_cmd.width, mode_cmd.bpp); +	mode_cmd.pitches[0] = align_pitch( +			mode_cmd.width * ((sizes->surface_bpp + 7) / 8), +			mode_cmd.width, sizes->surface_bpp);  	fbdev->ywrap_enabled = priv->has_dmm && ywrap_enabled;  	if (fbdev->ywrap_enabled) {  		/* need to align pitch to page size if using DMM scrolling */ -		mode_cmd.pitch = ALIGN(mode_cmd.pitch, PAGE_SIZE); +		mode_cmd.pitches[0] = ALIGN(mode_cmd.pitches[0], PAGE_SIZE);  	}  	/* allocate backing bo */  	gsize = (union omap_gem_size){ -		.bytes = PAGE_ALIGN(mode_cmd.pitch * mode_cmd.height), +		.bytes = PAGE_ALIGN(mode_cmd.pitches[0] * mode_cmd.height),  	};  	DBG("allocating %d bytes for fb %d", gsize.bytes, dev->primary->index);  	fbdev->bo = omap_gem_new(dev, gsize, OMAP_BO_SCANOUT | OMAP_BO_WC);  	if (!fbdev->bo) {  		dev_err(dev->dev, "failed to allocate buffer object\n"); +		ret = -ENOMEM;  		goto fail;  	} -	fb = omap_framebuffer_init(dev, &mode_cmd, fbdev->bo); -	if (!fb) { +	fb = omap_framebuffer_init(dev, &mode_cmd, &fbdev->bo); +	if (IS_ERR(fb)) {  		dev_err(dev->dev, "failed to allocate fb\n"); +		/* note: if fb creation failed, we can't rely on fb destroy +		 * to unref the bo: +		 */ +		drm_gem_object_unreference(fbdev->bo); +		ret = PTR_ERR(fb); +		goto fail; +	} + +	/* note: this keeps the bo pinned.. which is perhaps not ideal, +	 * but is needed as long as we use fb_mmap() to mmap to userspace +	 * (since this happens using fix.smem_start).  Possibly we could +	 * implement our own mmap using GEM mmap support to avoid this +	 * (non-tiled buffer doesn't need to be pinned for fbcon to write +	 * to it).  Then we just need to be sure that we are able to re- +	 * pin it in case of an opps. +	 */ +	ret = omap_gem_get_paddr(fbdev->bo, &paddr, true); +	if (ret) { +		dev_err(dev->dev, "could not map (paddr)!\n");  		ret = -ENOMEM;  		goto fail;  	} @@ -206,18 +224,15 @@ static int omap_fbdev_create(struct drm_fb_helper *helper,  		goto fail_unlock;  	} -	drm_fb_helper_fill_fix(fbi, fb->pitch, fb->depth); +	drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->depth);  	drm_fb_helper_fill_var(fbi, helper, sizes->fb_width, sizes->fb_height); -	size = omap_framebuffer_get_buffer(fb, 0, 0, -			&vaddr, &paddr, &screen_width); -  	dev->mode_config.fb_base = paddr; -	fbi->screen_base = vaddr; -	fbi->screen_size = size; +	fbi->screen_base = omap_gem_vaddr(fbdev->bo); +	fbi->screen_size = fbdev->bo->size;  	fbi->fix.smem_start = paddr; -	fbi->fix.smem_len = size; +	fbi->fix.smem_len = fbdev->bo->size;  	/* if we have DMM, then we can use it for scrolling by just  	 * shuffling pages around in DMM rather than doing sw blit. @@ -362,11 +377,11 @@ void omap_fbdev_free(struct drm_device *dev)  	fbdev = to_omap_fbdev(priv->fbdev); -	kfree(fbdev); -  	/* this will free the backing object */  	if (fbdev->fb)  		fbdev->fb->funcs->destroy(fbdev->fb); +	kfree(fbdev); +  	priv->fbdev = NULL;  } diff --git a/drivers/staging/omapdrm/omap_gem.c b/drivers/staging/omapdrm/omap_gem.c index e0ebd1d139f..b7d6f886c5c 100644 --- a/drivers/staging/omapdrm/omap_gem.c +++ b/drivers/staging/omapdrm/omap_gem.c @@ -116,6 +116,9 @@ struct omap_gem_object {  	} *sync;  }; +static int get_pages(struct drm_gem_object *obj, struct page ***pages); +static uint64_t mmap_offset(struct drm_gem_object *obj); +  /* To deal with userspace mmap'ings of 2d tiled buffers, which (a) are   * not necessarily pinned in TILER all the time, and (b) when they are   * they are not necessarily page aligned, we reserve one or more small @@ -149,7 +152,7 @@ static void evict_entry(struct drm_gem_object *obj,  {  	if (obj->dev->dev_mapping) {  		size_t size = PAGE_SIZE * usergart[fmt].height; -		loff_t off = omap_gem_mmap_offset(obj) + +		loff_t off = mmap_offset(obj) +  				(entry->obj_pgoff << PAGE_SHIFT);  		unmap_mapping_range(obj->dev->dev_mapping, off, size, 1);  	} @@ -189,8 +192,6 @@ static inline bool is_shmem(struct drm_gem_object *obj)  	return obj->filp != NULL;  } -static int get_pages(struct drm_gem_object *obj, struct page ***pages); -  static DEFINE_SPINLOCK(sync_lock);  /** ensure backing pages are allocated */ @@ -251,7 +252,7 @@ static void omap_gem_detach_pages(struct drm_gem_object *obj)  }  /** get mmap offset */ -uint64_t omap_gem_mmap_offset(struct drm_gem_object *obj) +static uint64_t mmap_offset(struct drm_gem_object *obj)  {  	if (!obj->map_list.map) {  		/* Make it mmapable */ @@ -267,6 +268,15 @@ uint64_t omap_gem_mmap_offset(struct drm_gem_object *obj)  	return (uint64_t)obj->map_list.hash.key << PAGE_SHIFT;  } +uint64_t omap_gem_mmap_offset(struct drm_gem_object *obj) +{ +	uint64_t offset; +	mutex_lock(&obj->dev->struct_mutex); +	offset = mmap_offset(obj); +	mutex_unlock(&obj->dev->struct_mutex); +	return offset; +} +  /** get mmap size */  size_t omap_gem_mmap_size(struct drm_gem_object *obj)  { @@ -1034,6 +1044,11 @@ void omap_gem_free_object(struct drm_gem_object *obj)  		drm_gem_free_mmap_offset(obj);  	} +	/* this means the object is still pinned.. which really should +	 * not happen.  I think.. +	 */ +	WARN_ON(omap_obj->paddr_cnt > 0); +  	/* don't free externally allocated backing memory */  	if (!(omap_obj->flags & OMAP_BO_EXT_MEM)) {  		if (omap_obj->pages) { diff --git a/drivers/staging/omapdrm/omap_plane.c b/drivers/staging/omapdrm/omap_plane.c new file mode 100644 index 00000000000..97909124a1f --- /dev/null +++ b/drivers/staging/omapdrm/omap_plane.c @@ -0,0 +1,344 @@ +/* + * drivers/staging/omapdrm/omap_plane.c + * + * Copyright (C) 2011 Texas Instruments + * Author: Rob Clark <rob.clark@linaro.org> + * + * 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, see <http://www.gnu.org/licenses/>. + */ + +#include "omap_drv.h" + +/* some hackery because omapdss has an 'enum omap_plane' (which would be + * better named omap_plane_id).. and compiler seems unhappy about having + * both a 'struct omap_plane' and 'enum omap_plane' + */ +#define omap_plane _omap_plane + +/* + * plane funcs + */ + +#define to_omap_plane(x) container_of(x, struct omap_plane, base) + +struct omap_plane { +	struct drm_plane base; +	struct omap_overlay *ovl; +	struct omap_overlay_info info; + +	/* Source values, converted to integers because we don't support +	 * fractional positions: +	 */ +	unsigned int src_x, src_y; + +	/* last fb that we pinned: */ +	struct drm_framebuffer *pinned_fb; +}; + + +/* push changes down to dss2 */ +static int commit(struct drm_plane *plane) +{ +	struct drm_device *dev = plane->dev; +	struct omap_plane *omap_plane = to_omap_plane(plane); +	struct omap_overlay *ovl = omap_plane->ovl; +	struct omap_overlay_info *info = &omap_plane->info; +	int ret; + +	DBG("%s", ovl->name); +	DBG("%dx%d -> %dx%d (%d)", info->width, info->height, info->out_width, +			info->out_height, info->screen_width); +	DBG("%d,%d %08x %08x", info->pos_x, info->pos_y, +			info->paddr, info->p_uv_addr); + +	/* NOTE: do we want to do this at all here, or just wait +	 * for dpms(ON) since other CRTC's may not have their mode +	 * set yet, so fb dimensions may still change.. +	 */ +	ret = ovl->set_overlay_info(ovl, info); +	if (ret) { +		dev_err(dev->dev, "could not set overlay info\n"); +		return ret; +	} + +	/* our encoder doesn't necessarily get a commit() after this, in +	 * particular in the dpms() and mode_set_base() cases, so force the +	 * manager to update: +	 * +	 * could this be in the encoder somehow? +	 */ +	if (ovl->manager) { +		ret = ovl->manager->apply(ovl->manager); +		if (ret) { +			dev_err(dev->dev, "could not apply settings\n"); +			return ret; +		} +	} + +	if (ovl->is_enabled(ovl)) { +		omap_framebuffer_flush(plane->fb, info->pos_x, info->pos_y, +				info->out_width, info->out_height); +	} + +	return 0; +} + +/* when CRTC that we are attached to has potentially changed, this checks + * if we are attached to proper manager, and if necessary updates. + */ +static void update_manager(struct drm_plane *plane) +{ +	struct omap_drm_private *priv = plane->dev->dev_private; +	struct omap_plane *omap_plane = to_omap_plane(plane); +	struct omap_overlay *ovl = omap_plane->ovl; +	struct omap_overlay_manager *mgr = NULL; +	int i; + +	if (plane->crtc) { +		for (i = 0; i < priv->num_encoders; i++) { +			struct drm_encoder *encoder = priv->encoders[i]; +			if (encoder->crtc == plane->crtc) { +				mgr = omap_encoder_get_manager(encoder); +				break; +			} +		} +	} + +	if (ovl->manager != mgr) { +		bool enabled = ovl->is_enabled(ovl); + +		/* don't switch things around with enabled overlays: */ +		if (enabled) +			omap_plane_dpms(plane, DRM_MODE_DPMS_OFF); + +		if (ovl->manager) { +			DBG("disconnecting %s from %s", ovl->name, +					ovl->manager->name); +			ovl->unset_manager(ovl); +		} + +		if (mgr) { +			DBG("connecting %s to %s", ovl->name, mgr->name); +			ovl->set_manager(ovl, mgr); +		} + +		if (enabled && mgr) +			omap_plane_dpms(plane, DRM_MODE_DPMS_ON); +	} +} + +/* update which fb (if any) is pinned for scanout */ +static int update_pin(struct drm_plane *plane, struct drm_framebuffer *fb) +{ +	struct omap_plane *omap_plane = to_omap_plane(plane); +	int ret = 0; + +	if (omap_plane->pinned_fb != fb) { +		if (omap_plane->pinned_fb) +			omap_framebuffer_unpin(omap_plane->pinned_fb); +		omap_plane->pinned_fb = fb; +		if (fb) +			ret = omap_framebuffer_pin(fb); +	} + +	return ret; +} + +/* update parameters that are dependent on the framebuffer dimensions and + * position within the fb that this plane scans out from. This is called + * when framebuffer or x,y base may have changed. + */ +static void update_scanout(struct drm_plane *plane) +{ +	struct omap_plane *omap_plane = to_omap_plane(plane); +	struct omap_overlay_info *info = &omap_plane->info; +	int ret; + +	ret = update_pin(plane, plane->fb); +	if (ret) { +		dev_err(plane->dev->dev, +			"could not pin fb: %d\n", ret); +		omap_plane_dpms(plane, DRM_MODE_DPMS_OFF); +		return; +	} + +	omap_framebuffer_update_scanout(plane->fb, +			omap_plane->src_x, omap_plane->src_y, info); + +	DBG("%s: %d,%d: %08x %08x (%d)", omap_plane->ovl->name, +			omap_plane->src_x, omap_plane->src_y, +			(u32)info->paddr, (u32)info->p_uv_addr, +			info->screen_width); +} + +int omap_plane_mode_set(struct drm_plane *plane, +		struct drm_crtc *crtc, struct drm_framebuffer *fb, +		int crtc_x, int crtc_y, +		unsigned int crtc_w, unsigned int crtc_h, +		uint32_t src_x, uint32_t src_y, +		uint32_t src_w, uint32_t src_h) +{ +	struct omap_plane *omap_plane = to_omap_plane(plane); + +	/* src values are in Q16 fixed point, convert to integer: */ +	src_x = src_x >> 16; +	src_y = src_y >> 16; +	src_w = src_w >> 16; +	src_h = src_h >> 16; + +	omap_plane->info.pos_x = crtc_x; +	omap_plane->info.pos_y = crtc_y; +	omap_plane->info.out_width = crtc_w; +	omap_plane->info.out_height = crtc_h; +	omap_plane->info.width = src_w; +	omap_plane->info.height = src_h; +	omap_plane->src_x = src_x; +	omap_plane->src_y = src_y; + +	/* note: this is done after this fxn returns.. but if we need +	 * to do a commit/update_scanout, etc before this returns we +	 * need the current value. +	 */ +	plane->fb = fb; +	plane->crtc = crtc; + +	update_scanout(plane); +	update_manager(plane); + +	return 0; +} + +static int omap_plane_update(struct drm_plane *plane, +		struct drm_crtc *crtc, struct drm_framebuffer *fb, +		int crtc_x, int crtc_y, +		unsigned int crtc_w, unsigned int crtc_h, +		uint32_t src_x, uint32_t src_y, +		uint32_t src_w, uint32_t src_h) +{ +	omap_plane_mode_set(plane, crtc, fb, crtc_x, crtc_y, crtc_w, crtc_h, +			src_x, src_y, src_w, src_h); +	return omap_plane_dpms(plane, DRM_MODE_DPMS_ON); +} + +static int omap_plane_disable(struct drm_plane *plane) +{ +	return omap_plane_dpms(plane, DRM_MODE_DPMS_OFF); +} + +static void omap_plane_destroy(struct drm_plane *plane) +{ +	struct omap_plane *omap_plane = to_omap_plane(plane); +	DBG("%s", omap_plane->ovl->name); +	omap_plane_disable(plane); +	drm_plane_cleanup(plane); +	kfree(omap_plane); +} + +int omap_plane_dpms(struct drm_plane *plane, int mode) +{ +	struct omap_plane *omap_plane = to_omap_plane(plane); +	struct omap_overlay *ovl = omap_plane->ovl; +	int r; + +	DBG("%s: %d", omap_plane->ovl->name, mode); + +	if (mode == DRM_MODE_DPMS_ON) { +		update_scanout(plane); +		r = commit(plane); +		if (!r) +			r = ovl->enable(ovl); +	} else { +		r = ovl->disable(ovl); +		update_pin(plane, NULL); +	} + +	return r; +} + +static const struct drm_plane_funcs omap_plane_funcs = { +		.update_plane = omap_plane_update, +		.disable_plane = omap_plane_disable, +		.destroy = omap_plane_destroy, +}; + +static const uint32_t formats[] = { +		DRM_FORMAT_RGB565, +		DRM_FORMAT_RGBX4444, +		DRM_FORMAT_XRGB4444, +		DRM_FORMAT_RGBA4444, +		DRM_FORMAT_ABGR4444, +		DRM_FORMAT_XRGB1555, +		DRM_FORMAT_ARGB1555, +		DRM_FORMAT_RGB888, +		DRM_FORMAT_RGBX8888, +		DRM_FORMAT_XRGB8888, +		DRM_FORMAT_RGBA8888, +		DRM_FORMAT_ARGB8888, +		DRM_FORMAT_NV12, +		DRM_FORMAT_YUYV, +		DRM_FORMAT_UYVY, +}; + +/* initialize plane */ +struct drm_plane *omap_plane_init(struct drm_device *dev, +		struct omap_overlay *ovl, unsigned int possible_crtcs, +		bool priv) +{ +	struct drm_plane *plane = NULL; +	struct omap_plane *omap_plane; + +	DBG("%s: possible_crtcs=%08x, priv=%d", ovl->name, +			possible_crtcs, priv); + +	omap_plane = kzalloc(sizeof(*omap_plane), GFP_KERNEL); +	if (!omap_plane) { +		dev_err(dev->dev, "could not allocate plane\n"); +		goto fail; +	} + +	omap_plane->ovl = ovl; +	plane = &omap_plane->base; + +	drm_plane_init(dev, plane, possible_crtcs, &omap_plane_funcs, +			formats, ARRAY_SIZE(formats), priv); + +	/* get our starting configuration, set defaults for parameters +	 * we don't currently use, etc: +	 */ +	ovl->get_overlay_info(ovl, &omap_plane->info); +	omap_plane->info.rotation_type = OMAP_DSS_ROT_DMA; +	omap_plane->info.rotation = OMAP_DSS_ROT_0; +	omap_plane->info.global_alpha = 0xff; +	omap_plane->info.mirror = 0; +	omap_plane->info.mirror = 0; + +	/* Set defaults depending on whether we are a CRTC or overlay +	 * layer. +	 * TODO add ioctl to give userspace an API to change this.. this +	 * will come in a subsequent patch. +	 */ +	if (priv) +		omap_plane->info.zorder = 0; +	else +		omap_plane->info.zorder = 1; + +	update_manager(plane); + +	return plane; + +fail: +	if (plane) { +		omap_plane_destroy(plane); +	} +	return NULL; +} diff --git a/drivers/staging/omapdrm/omap_priv.h b/drivers/staging/omapdrm/omap_priv.h index c324709aa9a..ef644144714 100644 --- a/drivers/staging/omapdrm/omap_priv.h +++ b/drivers/staging/omapdrm/omap_priv.h @@ -27,14 +27,22 @@   * pipes/overlays/CRTCs are used.. if this is not provided, then instead the   * first CONFIG_DRM_OMAP_NUM_CRTCS are used, and they are each connected to   * one manager, with priority given to managers that are connected to - * detected devices.  This should be a good default behavior for most cases, - * but yet there still might be times when you wish to do something different. + * detected devices.  Remaining overlays are used as video planes.  This + * should be a good default behavior for most cases, but yet there still + * might be times when you wish to do something different.   */  struct omap_kms_platform_data { +	/* overlays to use as CRTCs: */  	int ovl_cnt;  	const int *ovl_ids; + +	/* overlays to use as video planes: */ +	int pln_cnt; +	const int *pln_ids; +  	int mgr_cnt;  	const int *mgr_ids; +  	int dev_cnt;  	const char **dev_names;  }; diff --git a/drivers/staging/pohmelfs/Kconfig b/drivers/staging/pohmelfs/Kconfig deleted file mode 100644 index 8d53b1a1e71..00000000000 --- a/drivers/staging/pohmelfs/Kconfig +++ /dev/null @@ -1,20 +0,0 @@ -config POHMELFS -	tristate "POHMELFS filesystem support" -	depends on NET -	select CONNECTOR -	select CRYPTO -	select CRYPTO_BLKCIPHER -	select CRYPTO_HMAC -	help -	  POHMELFS stands for Parallel Optimized Host Message Exchange Layered -	  File System.  This is a network filesystem which supports coherent -	  caching of data and metadata on clients. - -config POHMELFS_DEBUG -	bool "POHMELFS debugging" -	depends on POHMELFS -	default n -	help -	  Turns on excessive POHMELFS debugging facilities. -	  You usually do not want to slow things down noticeably and get really -	  lots of kernel messages in syslog. diff --git a/drivers/staging/pohmelfs/Makefile b/drivers/staging/pohmelfs/Makefile deleted file mode 100644 index 196561ca26b..00000000000 --- a/drivers/staging/pohmelfs/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -obj-$(CONFIG_POHMELFS)	+= pohmelfs.o - -pohmelfs-y := inode.o config.o dir.o net.o path_entry.o trans.o crypto.o lock.o mcache.o diff --git a/drivers/staging/pohmelfs/config.c b/drivers/staging/pohmelfs/config.c deleted file mode 100644 index b6c42cb0d1c..00000000000 --- a/drivers/staging/pohmelfs/config.c +++ /dev/null @@ -1,611 +0,0 @@ -/* - * 2007+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net> - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU General Public License for more details. - */ - -#include <linux/kernel.h> -#include <linux/connector.h> -#include <linux/crypto.h> -#include <linux/list.h> -#include <linux/mutex.h> -#include <linux/string.h> -#include <linux/in.h> -#include <linux/slab.h> - -#include "netfs.h" - -/* - * Global configuration list. - * Each client can be asked to get one of them. - * - * Allows to provide remote server address (ipv4/v6/whatever), port - * and so on via kernel connector. - */ - -static struct cb_id pohmelfs_cn_id = {.idx = POHMELFS_CN_IDX, .val = POHMELFS_CN_VAL}; -static LIST_HEAD(pohmelfs_config_list); -static DEFINE_MUTEX(pohmelfs_config_lock); - -static inline int pohmelfs_config_eql(struct pohmelfs_ctl *sc, struct pohmelfs_ctl *ctl) -{ -	if (sc->idx == ctl->idx && sc->type == ctl->type && -			sc->proto == ctl->proto && -			sc->addrlen == ctl->addrlen && -			!memcmp(&sc->addr, &ctl->addr, ctl->addrlen)) -		return 1; - -	return 0; -} - -static struct pohmelfs_config_group *pohmelfs_find_config_group(unsigned int idx) -{ -	struct pohmelfs_config_group *g, *group = NULL; - -	list_for_each_entry(g, &pohmelfs_config_list, group_entry) { -		if (g->idx == idx) { -			group = g; -			break; -		} -	} - -	return group; -} - -static struct pohmelfs_config_group *pohmelfs_find_create_config_group(unsigned int idx) -{ -	struct pohmelfs_config_group *g; - -	g = pohmelfs_find_config_group(idx); -	if (g) -		return g; - -	g = kzalloc(sizeof(struct pohmelfs_config_group), GFP_KERNEL); -	if (!g) -		return NULL; - -	INIT_LIST_HEAD(&g->config_list); -	g->idx = idx; -	g->num_entry = 0; - -	list_add_tail(&g->group_entry, &pohmelfs_config_list); - -	return g; -} - -static inline void pohmelfs_insert_config_entry(struct pohmelfs_sb *psb, struct pohmelfs_config *dst) -{ -	struct pohmelfs_config *tmp; - -	INIT_LIST_HEAD(&dst->config_entry); - -	list_for_each_entry(tmp, &psb->state_list, config_entry) { -		if (dst->state.ctl.prio > tmp->state.ctl.prio) -			list_add_tail(&dst->config_entry, &tmp->config_entry); -	} -	if (list_empty(&dst->config_entry)) -		list_add_tail(&dst->config_entry, &psb->state_list); -} - -static int pohmelfs_move_config_entry(struct pohmelfs_sb *psb, -		struct pohmelfs_config *dst, struct pohmelfs_config *new) -{ -	if ((dst->state.ctl.prio == new->state.ctl.prio) && -		(dst->state.ctl.perm == new->state.ctl.perm)) -		return 0; - -	dprintk("%s: dst: prio: %d, perm: %x, new: prio: %d, perm: %d.\n", -			__func__, dst->state.ctl.prio, dst->state.ctl.perm, -			new->state.ctl.prio, new->state.ctl.perm); -	dst->state.ctl.prio = new->state.ctl.prio; -	dst->state.ctl.perm = new->state.ctl.perm; - -	list_del_init(&dst->config_entry); -	pohmelfs_insert_config_entry(psb, dst); -	return 0; -} - -/* - * pohmelfs_copy_config() is used to copy new state configs from the - * config group (controlled by the netlink messages) into the superblock. - * This happens either at startup time where no transactions can access - * the list of the configs (and thus list of the network states), or at - * run-time, where it is protected by the psb->state_lock. - */ -int pohmelfs_copy_config(struct pohmelfs_sb *psb) -{ -	struct pohmelfs_config_group *g; -	struct pohmelfs_config *c, *dst; -	int err = -ENODEV; - -	mutex_lock(&pohmelfs_config_lock); - -	g = pohmelfs_find_config_group(psb->idx); -	if (!g) -		goto out_unlock; - -	/* -	 * Run over all entries in given config group and try to create and -	 * initialize those, which do not exist in superblock list. -	 * Skip all existing entries. -	 */ - -	list_for_each_entry(c, &g->config_list, config_entry) { -		err = 0; -		list_for_each_entry(dst, &psb->state_list, config_entry) { -			if (pohmelfs_config_eql(&dst->state.ctl, &c->state.ctl)) { -				err = pohmelfs_move_config_entry(psb, dst, c); -				if (!err) -					err = -EEXIST; -				break; -			} -		} - -		if (err) -			continue; - -		dst = kzalloc(sizeof(struct pohmelfs_config), GFP_KERNEL); -		if (!dst) { -			err = -ENOMEM; -			break; -		} - -		memcpy(&dst->state.ctl, &c->state.ctl, sizeof(struct pohmelfs_ctl)); - -		pohmelfs_insert_config_entry(psb, dst); - -		err = pohmelfs_state_init_one(psb, dst); -		if (err) { -			list_del(&dst->config_entry); -			kfree(dst); -		} - -		err = 0; -	} - -out_unlock: -	mutex_unlock(&pohmelfs_config_lock); - -	return err; -} - -int pohmelfs_copy_crypto(struct pohmelfs_sb *psb) -{ -	struct pohmelfs_config_group *g; -	int err = -ENOENT; - -	mutex_lock(&pohmelfs_config_lock); -	g = pohmelfs_find_config_group(psb->idx); -	if (!g) -		goto err_out_exit; - -	if (g->hash_string) { -		err = -ENOMEM; -		psb->hash_string = kstrdup(g->hash_string, GFP_KERNEL); -		if (!psb->hash_string) -			goto err_out_exit; -		psb->hash_strlen = g->hash_strlen; -	} - -	if (g->cipher_string) { -		psb->cipher_string = kstrdup(g->cipher_string, GFP_KERNEL); -		if (!psb->cipher_string) -			goto err_out_free_hash_string; -		psb->cipher_strlen = g->cipher_strlen; -	} - -	if (g->hash_keysize) { -		psb->hash_key = kmemdup(g->hash_key, g->hash_keysize, -					GFP_KERNEL); -		if (!psb->hash_key) -			goto err_out_free_cipher_string; -		psb->hash_keysize = g->hash_keysize; -	} - -	if (g->cipher_keysize) { -		psb->cipher_key = kmemdup(g->cipher_key, g->cipher_keysize, -					  GFP_KERNEL); -		if (!psb->cipher_key) -			goto err_out_free_hash; -		psb->cipher_keysize = g->cipher_keysize; -	} - -	mutex_unlock(&pohmelfs_config_lock); - -	return 0; - -err_out_free_hash: -	kfree(psb->hash_key); -err_out_free_cipher_string: -	kfree(psb->cipher_string); -err_out_free_hash_string: -	kfree(psb->hash_string); -err_out_exit: -	mutex_unlock(&pohmelfs_config_lock); -	return err; -} - -static int pohmelfs_send_reply(int err, int msg_num, int action, struct cn_msg *msg, struct pohmelfs_ctl *ctl) -{ -	struct pohmelfs_cn_ack *ack; - -	ack = kzalloc(sizeof(struct pohmelfs_cn_ack), GFP_KERNEL); -	if (!ack) -		return -ENOMEM; - -	memcpy(&ack->msg, msg, sizeof(struct cn_msg)); - -	if (action == POHMELFS_CTLINFO_ACK) -		memcpy(&ack->ctl, ctl, sizeof(struct pohmelfs_ctl)); - -	ack->msg.len = sizeof(struct pohmelfs_cn_ack) - sizeof(struct cn_msg); -	ack->msg.ack = msg->ack + 1; -	ack->error = err; -	ack->msg_num = msg_num; - -	cn_netlink_send(&ack->msg, 0, GFP_KERNEL); -	kfree(ack); -	return 0; -} - -static int pohmelfs_cn_disp(struct cn_msg *msg) -{ -	struct pohmelfs_config_group *g; -	struct pohmelfs_ctl *ctl = (struct pohmelfs_ctl *)msg->data; -	struct pohmelfs_config *c, *tmp; -	int err = 0, i = 1; - -	if (msg->len != sizeof(struct pohmelfs_ctl)) -		return -EBADMSG; - -	mutex_lock(&pohmelfs_config_lock); - -	g = pohmelfs_find_config_group(ctl->idx); -	if (!g) { -		pohmelfs_send_reply(err, 0, POHMELFS_NOINFO_ACK, msg, NULL); -		goto out_unlock; -	} - -	list_for_each_entry_safe(c, tmp, &g->config_list, config_entry) { -		struct pohmelfs_ctl *sc = &c->state.ctl; -		if (pohmelfs_send_reply(err, g->num_entry - i, POHMELFS_CTLINFO_ACK, msg, sc)) { -			err = -ENOMEM; -			goto out_unlock; -		} -		i += 1; -	} - - out_unlock: -	mutex_unlock(&pohmelfs_config_lock); -	return err; -} - -static int pohmelfs_cn_dump(struct cn_msg *msg) -{ -	struct pohmelfs_config_group *g; -	struct pohmelfs_config *c, *tmp; -	int err = 0, i = 1; -	int total_msg = 0; - -	if (msg->len != sizeof(struct pohmelfs_ctl)) -		return -EBADMSG; - -	mutex_lock(&pohmelfs_config_lock); - -	list_for_each_entry(g, &pohmelfs_config_list, group_entry) -		total_msg += g->num_entry; -	if (total_msg == 0) { -		if (pohmelfs_send_reply(err, 0, POHMELFS_NOINFO_ACK, msg, NULL)) -			err = -ENOMEM; -		goto out_unlock; -	} - -	list_for_each_entry(g, &pohmelfs_config_list, group_entry) { -		list_for_each_entry_safe(c, tmp, &g->config_list, -					 config_entry) { -			struct pohmelfs_ctl *sc = &c->state.ctl; -			if (pohmelfs_send_reply(err, total_msg - i, -						POHMELFS_CTLINFO_ACK, msg, -						sc)) { -				err = -ENOMEM; -				goto out_unlock; -			} -			i += 1; -		} -	} - -out_unlock: -	mutex_unlock(&pohmelfs_config_lock); -	return err; -} - -static int pohmelfs_cn_flush(struct cn_msg *msg) -{ -	struct pohmelfs_config_group *g; -	struct pohmelfs_ctl *ctl = (struct pohmelfs_ctl *)msg->data; -	struct pohmelfs_config *c, *tmp; -	int err = 0; - -	if (msg->len != sizeof(struct pohmelfs_ctl)) -		return -EBADMSG; - -	mutex_lock(&pohmelfs_config_lock); - -	if (ctl->idx != POHMELFS_NULL_IDX) { -		g = pohmelfs_find_config_group(ctl->idx); - -		if (!g) -			goto out_unlock; - -		list_for_each_entry_safe(c, tmp, &g->config_list, config_entry) { -			list_del(&c->config_entry); -			g->num_entry--; -			kfree(c); -		} -	} else { -		list_for_each_entry(g, &pohmelfs_config_list, group_entry) { -			list_for_each_entry_safe(c, tmp, &g->config_list, -						 config_entry) { -				list_del(&c->config_entry); -				g->num_entry--; -				kfree(c); -			} -		} -	} - -out_unlock: -	mutex_unlock(&pohmelfs_config_lock); -	pohmelfs_cn_dump(msg); - -	return err; -} - -static int pohmelfs_modify_config(struct pohmelfs_ctl *old, struct pohmelfs_ctl *new) -{ -	old->perm = new->perm; -	old->prio = new->prio; -	return 0; -} - -static int pohmelfs_cn_ctl(struct cn_msg *msg, int action) -{ -	struct pohmelfs_config_group *g; -	struct pohmelfs_ctl *ctl = (struct pohmelfs_ctl *)msg->data; -	struct pohmelfs_config *c, *tmp; -	int err = 0; - -	if (msg->len != sizeof(struct pohmelfs_ctl)) -		return -EBADMSG; - -	mutex_lock(&pohmelfs_config_lock); - -	g = pohmelfs_find_create_config_group(ctl->idx); -	if (!g) { -		err = -ENOMEM; -		goto out_unlock; -	} - -	list_for_each_entry_safe(c, tmp, &g->config_list, config_entry) { -		struct pohmelfs_ctl *sc = &c->state.ctl; - -		if (pohmelfs_config_eql(sc, ctl)) { -			if (action == POHMELFS_FLAGS_ADD) { -				err = -EEXIST; -				goto out_unlock; -			} else if (action == POHMELFS_FLAGS_DEL) { -				list_del(&c->config_entry); -				g->num_entry--; -				kfree(c); -				goto out_unlock; -			} else if (action == POHMELFS_FLAGS_MODIFY) { -				err = pohmelfs_modify_config(sc, ctl); -				goto out_unlock; -			} else { -				err = -EEXIST; -				goto out_unlock; -			} -		} -	} -	if (action == POHMELFS_FLAGS_DEL) { -		err = -EBADMSG; -		goto out_unlock; -	} - -	c = kzalloc(sizeof(struct pohmelfs_config), GFP_KERNEL); -	if (!c) { -		err = -ENOMEM; -		goto out_unlock; -	} -	memcpy(&c->state.ctl, ctl, sizeof(struct pohmelfs_ctl)); -	g->num_entry++; - -	list_add_tail(&c->config_entry, &g->config_list); - - out_unlock: -	mutex_unlock(&pohmelfs_config_lock); -	if (pohmelfs_send_reply(err, 0, POHMELFS_NOINFO_ACK, msg, NULL)) -		err = -ENOMEM; - -	return err; -} - -static int pohmelfs_crypto_hash_init(struct pohmelfs_config_group *g, struct pohmelfs_crypto *c) -{ -	char *algo = (char *)c->data; -	u8 *key = (u8 *)(algo + c->strlen); - -	if (g->hash_string) -		return -EEXIST; - -	g->hash_string = kstrdup(algo, GFP_KERNEL); -	if (!g->hash_string) -		return -ENOMEM; -	g->hash_strlen = c->strlen; -	g->hash_keysize = c->keysize; - -	g->hash_key = kmemdup(key, c->keysize, GFP_KERNEL); -	if (!g->hash_key) { -		kfree(g->hash_string); -		return -ENOMEM; -	} - -	return 0; -} - -static int pohmelfs_crypto_cipher_init(struct pohmelfs_config_group *g, struct pohmelfs_crypto *c) -{ -	char *algo = (char *)c->data; -	u8 *key = (u8 *)(algo + c->strlen); - -	if (g->cipher_string) -		return -EEXIST; - -	g->cipher_string = kstrdup(algo, GFP_KERNEL); -	if (!g->cipher_string) -		return -ENOMEM; -	g->cipher_strlen = c->strlen; -	g->cipher_keysize = c->keysize; - -	g->cipher_key = kmemdup(key, c->keysize, GFP_KERNEL); -	if (!g->cipher_key) { -		kfree(g->cipher_string); -		return -ENOMEM; -	} - -	return 0; -} - -static int pohmelfs_cn_crypto(struct cn_msg *msg) -{ -	struct pohmelfs_crypto *crypto = (struct pohmelfs_crypto *)msg->data; -	struct pohmelfs_config_group *g; -	int err = 0; - -	dprintk("%s: idx: %u, strlen: %u, type: %u, keysize: %u, algo: %s.\n", -			__func__, crypto->idx, crypto->strlen, crypto->type, -			crypto->keysize, (char *)crypto->data); - -	mutex_lock(&pohmelfs_config_lock); -	g = pohmelfs_find_create_config_group(crypto->idx); -	if (!g) { -		err = -ENOMEM; -		goto out_unlock; -	} - -	switch (crypto->type) { -	case POHMELFS_CRYPTO_HASH: -			err = pohmelfs_crypto_hash_init(g, crypto); -			break; -	case POHMELFS_CRYPTO_CIPHER: -			err = pohmelfs_crypto_cipher_init(g, crypto); -			break; -	default: -			err = -ENOTSUPP; -			break; -	} - -out_unlock: -	mutex_unlock(&pohmelfs_config_lock); -	if (pohmelfs_send_reply(err, 0, POHMELFS_NOINFO_ACK, msg, NULL)) -		err = -ENOMEM; - -	return err; -} - -static void pohmelfs_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp) -{ -	int err; - -	if (!cap_raised(current_cap(), CAP_SYS_ADMIN)) -		return; - -	switch (msg->flags) { -	case POHMELFS_FLAGS_ADD: -	case POHMELFS_FLAGS_DEL: -	case POHMELFS_FLAGS_MODIFY: -			err = pohmelfs_cn_ctl(msg, msg->flags); -			break; -	case POHMELFS_FLAGS_FLUSH: -			err = pohmelfs_cn_flush(msg); -			break; -	case POHMELFS_FLAGS_SHOW: -			err = pohmelfs_cn_disp(msg); -			break; -	case POHMELFS_FLAGS_DUMP: -			err = pohmelfs_cn_dump(msg); -			break; -	case POHMELFS_FLAGS_CRYPTO: -			err = pohmelfs_cn_crypto(msg); -			break; -	default: -			err = -ENOSYS; -			break; -	} -} - -int pohmelfs_config_check(struct pohmelfs_config *config, int idx) -{ -	struct pohmelfs_ctl *ctl = &config->state.ctl; -	struct pohmelfs_config *tmp; -	int err = -ENOENT; -	struct pohmelfs_ctl *sc; -	struct pohmelfs_config_group *g; - -	mutex_lock(&pohmelfs_config_lock); - -	g = pohmelfs_find_config_group(ctl->idx); -	if (g) { -		list_for_each_entry(tmp, &g->config_list, config_entry) { -			sc = &tmp->state.ctl; - -			if (pohmelfs_config_eql(sc, ctl)) { -				err = 0; -				break; -			} -		} -	} - -	mutex_unlock(&pohmelfs_config_lock); - -	return err; -} - -int __init pohmelfs_config_init(void) -{ -	/* XXX remove (void *) cast when vanilla connector got synced */ -	return cn_add_callback(&pohmelfs_cn_id, "pohmelfs", (void *)pohmelfs_cn_callback); -} - -void pohmelfs_config_exit(void) -{ -	struct pohmelfs_config *c, *tmp; -	struct pohmelfs_config_group *g, *gtmp; - -	cn_del_callback(&pohmelfs_cn_id); - -	mutex_lock(&pohmelfs_config_lock); -	list_for_each_entry_safe(g, gtmp, &pohmelfs_config_list, group_entry) { -		list_for_each_entry_safe(c, tmp, &g->config_list, config_entry) { -			list_del(&c->config_entry); -			kfree(c); -		} - -		list_del(&g->group_entry); - -		kfree(g->hash_string); - -		kfree(g->cipher_string); - -		kfree(g); -	} -	mutex_unlock(&pohmelfs_config_lock); -} diff --git a/drivers/staging/pohmelfs/crypto.c b/drivers/staging/pohmelfs/crypto.c deleted file mode 100644 index ad92771dce5..00000000000 --- a/drivers/staging/pohmelfs/crypto.c +++ /dev/null @@ -1,878 +0,0 @@ -/* - * 2007+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net> - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU General Public License for more details. - */ - -#include <linux/crypto.h> -#include <linux/highmem.h> -#include <linux/kthread.h> -#include <linux/pagemap.h> -#include <linux/scatterlist.h> -#include <linux/slab.h> - -#include "netfs.h" - -static struct crypto_hash *pohmelfs_init_hash(struct pohmelfs_sb *psb) -{ -	int err; -	struct crypto_hash *hash; - -	hash = crypto_alloc_hash(psb->hash_string, 0, CRYPTO_ALG_ASYNC); -	if (IS_ERR(hash)) { -		err = PTR_ERR(hash); -		dprintk("%s: idx: %u: failed to allocate hash '%s', err: %d.\n", -				__func__, psb->idx, psb->hash_string, err); -		goto err_out_exit; -	} - -	psb->crypto_attached_size = crypto_hash_digestsize(hash); - -	if (!psb->hash_keysize) -		return hash; - -	err = crypto_hash_setkey(hash, psb->hash_key, psb->hash_keysize); -	if (err) { -		dprintk("%s: idx: %u: failed to set key for hash '%s', err: %d.\n", -				__func__, psb->idx, psb->hash_string, err); -		goto err_out_free; -	} - -	return hash; - -err_out_free: -	crypto_free_hash(hash); -err_out_exit: -	return ERR_PTR(err); -} - -static struct crypto_ablkcipher *pohmelfs_init_cipher(struct pohmelfs_sb *psb) -{ -	int err = -EINVAL; -	struct crypto_ablkcipher *cipher; - -	if (!psb->cipher_keysize) -		goto err_out_exit; - -	cipher = crypto_alloc_ablkcipher(psb->cipher_string, 0, 0); -	if (IS_ERR(cipher)) { -		err = PTR_ERR(cipher); -		dprintk("%s: idx: %u: failed to allocate cipher '%s', err: %d.\n", -				__func__, psb->idx, psb->cipher_string, err); -		goto err_out_exit; -	} - -	crypto_ablkcipher_clear_flags(cipher, ~0); - -	err = crypto_ablkcipher_setkey(cipher, psb->cipher_key, psb->cipher_keysize); -	if (err) { -		dprintk("%s: idx: %u: failed to set key for cipher '%s', err: %d.\n", -				__func__, psb->idx, psb->cipher_string, err); -		goto err_out_free; -	} - -	return cipher; - -err_out_free: -	crypto_free_ablkcipher(cipher); -err_out_exit: -	return ERR_PTR(err); -} - -int pohmelfs_crypto_engine_init(struct pohmelfs_crypto_engine *e, struct pohmelfs_sb *psb) -{ -	int err; - -	e->page_num = 0; - -	e->size = PAGE_SIZE; -	e->data = kmalloc(e->size, GFP_KERNEL); -	if (!e->data) { -		err = -ENOMEM; -		goto err_out_exit; -	} - -	if (psb->hash_string) { -		e->hash = pohmelfs_init_hash(psb); -		if (IS_ERR(e->hash)) { -			err = PTR_ERR(e->hash); -			e->hash = NULL; -			goto err_out_free; -		} -	} - -	if (psb->cipher_string) { -		e->cipher = pohmelfs_init_cipher(psb); -		if (IS_ERR(e->cipher)) { -			err = PTR_ERR(e->cipher); -			e->cipher = NULL; -			goto err_out_free_hash; -		} -	} - -	return 0; - -err_out_free_hash: -	crypto_free_hash(e->hash); -err_out_free: -	kfree(e->data); -err_out_exit: -	return err; -} - -void pohmelfs_crypto_engine_exit(struct pohmelfs_crypto_engine *e) -{ -	crypto_free_hash(e->hash); -	crypto_free_ablkcipher(e->cipher); -	kfree(e->data); -} - -static void pohmelfs_crypto_complete(struct crypto_async_request *req, int err) -{ -	struct pohmelfs_crypto_completion *c = req->data; - -	if (err == -EINPROGRESS) -		return; - -	dprintk("%s: req: %p, err: %d.\n", __func__, req, err); -	c->error = err; -	complete(&c->complete); -} - -static int pohmelfs_crypto_process(struct ablkcipher_request *req, -		struct scatterlist *sg_dst, struct scatterlist *sg_src, -		void *iv, int enc, unsigned long timeout) -{ -	struct pohmelfs_crypto_completion complete; -	int err; - -	init_completion(&complete.complete); -	complete.error = -EINPROGRESS; - -	ablkcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, -					pohmelfs_crypto_complete, &complete); - -	ablkcipher_request_set_crypt(req, sg_src, sg_dst, sg_src->length, iv); - -	if (enc) -		err = crypto_ablkcipher_encrypt(req); -	else -		err = crypto_ablkcipher_decrypt(req); - -	switch (err) { -	case -EINPROGRESS: -	case -EBUSY: -		err = wait_for_completion_interruptible_timeout(&complete.complete, -					timeout); -		if (!err) -			err = -ETIMEDOUT; -		else if (err > 0) -			err = complete.error; -		break; -	default: -		break; -	} - -	return err; -} - -int pohmelfs_crypto_process_input_data(struct pohmelfs_crypto_engine *e, u64 cmd_iv, -		void *data, struct page *page, unsigned int size) -{ -	int err; -	struct scatterlist sg; - -	if (!e->cipher && !e->hash) -		return 0; - -	dprintk("%s: eng: %p, iv: %llx, data: %p, page: %p/%lu, size: %u.\n", -		__func__, e, cmd_iv, data, page, (page) ? page->index : 0, size); - -	if (data) { -		sg_init_one(&sg, data, size); -	} else { -		sg_init_table(&sg, 1); -		sg_set_page(&sg, page, size, 0); -	} - -	if (e->cipher) { -		struct ablkcipher_request *req = e->data + crypto_hash_digestsize(e->hash); -		u8 iv[32]; - -		memset(iv, 0, sizeof(iv)); -		memcpy(iv, &cmd_iv, sizeof(cmd_iv)); - -		ablkcipher_request_set_tfm(req, e->cipher); - -		err = pohmelfs_crypto_process(req, &sg, &sg, iv, 0, e->timeout); -		if (err) -			goto err_out_exit; -	} - -	if (e->hash) { -		struct hash_desc desc; -		void *dst = e->data + e->size/2; - -		desc.tfm = e->hash; -		desc.flags = 0; - -		err = crypto_hash_init(&desc); -		if (err) -			goto err_out_exit; - -		err = crypto_hash_update(&desc, &sg, size); -		if (err) -			goto err_out_exit; - -		err = crypto_hash_final(&desc, dst); -		if (err) -			goto err_out_exit; - -		err = !!memcmp(dst, e->data, crypto_hash_digestsize(e->hash)); - -		if (err) { -#ifdef CONFIG_POHMELFS_DEBUG -			unsigned int i; -			unsigned char *recv = e->data, *calc = dst; - -			dprintk("%s: eng: %p, hash: %p, cipher: %p: iv : %llx, hash mismatch (recv/calc): ", -					__func__, e, e->hash, e->cipher, cmd_iv); -			for (i = 0; i < crypto_hash_digestsize(e->hash); ++i) { -#if 0 -				dprintka("%02x ", recv[i]); -				if (recv[i] != calc[i]) { -					dprintka("| calc byte: %02x.\n", calc[i]); -					break; -				} -#else -				dprintka("%02x/%02x ", recv[i], calc[i]); -#endif -			} -			dprintk("\n"); -#endif -			goto err_out_exit; -		} else { -			dprintk("%s: eng: %p, hash: %p, cipher: %p: hashes matched.\n", -					__func__, e, e->hash, e->cipher); -		} -	} - -	dprintk("%s: eng: %p, size: %u, hash: %p, cipher: %p: completed.\n", -			__func__, e, e->size, e->hash, e->cipher); - -	return 0; - -err_out_exit: -	dprintk("%s: eng: %p, hash: %p, cipher: %p: err: %d.\n", -			__func__, e, e->hash, e->cipher, err); -	return err; -} - -static int pohmelfs_trans_iter(struct netfs_trans *t, struct pohmelfs_crypto_engine *e, -		int (*iterator) (struct pohmelfs_crypto_engine *e, -				  struct scatterlist *dst, -				  struct scatterlist *src)) -{ -	void *data = t->iovec.iov_base + sizeof(struct netfs_cmd) + t->psb->crypto_attached_size; -	unsigned int size = t->iovec.iov_len - sizeof(struct netfs_cmd) - t->psb->crypto_attached_size; -	struct netfs_cmd *cmd = data; -	unsigned int sz, pages = t->attached_pages, i, csize, cmd_cmd, dpage_idx; -	struct scatterlist sg_src, sg_dst; -	int err; - -	while (size) { -		cmd = data; -		cmd_cmd = __be16_to_cpu(cmd->cmd); -		csize = __be32_to_cpu(cmd->size); -		cmd->iv = __cpu_to_be64(e->iv); - -		if (cmd_cmd == NETFS_READ_PAGES || cmd_cmd == NETFS_READ_PAGE) -			csize = __be16_to_cpu(cmd->ext); - -		sz = csize + __be16_to_cpu(cmd->cpad) + sizeof(struct netfs_cmd); - -		dprintk("%s: size: %u, sz: %u, cmd_size: %u, cmd_cpad: %u.\n", -				__func__, size, sz, __be32_to_cpu(cmd->size), __be16_to_cpu(cmd->cpad)); - -		data += sz; -		size -= sz; - -		sg_init_one(&sg_src, cmd->data, sz - sizeof(struct netfs_cmd)); -		sg_init_one(&sg_dst, cmd->data, sz - sizeof(struct netfs_cmd)); - -		err = iterator(e, &sg_dst, &sg_src); -		if (err) -			return err; -	} - -	if (!pages) -		return 0; - -	dpage_idx = 0; -	for (i = 0; i < t->page_num; ++i) { -		struct page *page = t->pages[i]; -		struct page *dpage = e->pages[dpage_idx]; - -		if (!page) -			continue; - -		sg_init_table(&sg_src, 1); -		sg_init_table(&sg_dst, 1); -		sg_set_page(&sg_src, page, page_private(page), 0); -		sg_set_page(&sg_dst, dpage, page_private(page), 0); - -		err = iterator(e, &sg_dst, &sg_src); -		if (err) -			return err; - -		pages--; -		if (!pages) -			break; -		dpage_idx++; -	} - -	return 0; -} - -static int pohmelfs_encrypt_iterator(struct pohmelfs_crypto_engine *e, -		struct scatterlist *sg_dst, struct scatterlist *sg_src) -{ -	struct ablkcipher_request *req = e->data; -	u8 iv[32]; - -	memset(iv, 0, sizeof(iv)); - -	memcpy(iv, &e->iv, sizeof(e->iv)); - -	return pohmelfs_crypto_process(req, sg_dst, sg_src, iv, 1, e->timeout); -} - -static int pohmelfs_encrypt(struct pohmelfs_crypto_thread *tc) -{ -	struct netfs_trans *t = tc->trans; -	struct pohmelfs_crypto_engine *e = &tc->eng; -	struct ablkcipher_request *req = e->data; - -	memset(req, 0, sizeof(struct ablkcipher_request)); -	ablkcipher_request_set_tfm(req, e->cipher); - -	e->iv = pohmelfs_gen_iv(t); - -	return pohmelfs_trans_iter(t, e, pohmelfs_encrypt_iterator); -} - -static int pohmelfs_hash_iterator(struct pohmelfs_crypto_engine *e, -		struct scatterlist *sg_dst, struct scatterlist *sg_src) -{ -	return crypto_hash_update(e->data, sg_src, sg_src->length); -} - -static int pohmelfs_hash(struct pohmelfs_crypto_thread *tc) -{ -	struct pohmelfs_crypto_engine *e = &tc->eng; -	struct hash_desc *desc = e->data; -	unsigned char *dst = tc->trans->iovec.iov_base + sizeof(struct netfs_cmd); -	int err; - -	desc->tfm = e->hash; -	desc->flags = 0; - -	err = crypto_hash_init(desc); -	if (err) -		return err; - -	err = pohmelfs_trans_iter(tc->trans, e, pohmelfs_hash_iterator); -	if (err) -		return err; - -	err = crypto_hash_final(desc, dst); -	if (err) -		return err; - -	{ -		unsigned int i; -		dprintk("%s: ", __func__); -		for (i = 0; i < tc->psb->crypto_attached_size; ++i) -			dprintka("%02x ", dst[i]); -		dprintka("\n"); -	} - -	return 0; -} - -static void pohmelfs_crypto_pages_free(struct pohmelfs_crypto_engine *e) -{ -	unsigned int i; - -	for (i = 0; i < e->page_num; ++i) -		__free_page(e->pages[i]); -	kfree(e->pages); -} - -static int pohmelfs_crypto_pages_alloc(struct pohmelfs_crypto_engine *e, struct pohmelfs_sb *psb) -{ -	unsigned int i; - -	e->pages = kmalloc(psb->trans_max_pages * sizeof(struct page *), GFP_KERNEL); -	if (!e->pages) -		return -ENOMEM; - -	for (i = 0; i < psb->trans_max_pages; ++i) { -		e->pages[i] = alloc_page(GFP_KERNEL); -		if (!e->pages[i]) -			break; -	} - -	e->page_num = i; -	if (!e->page_num) -		goto err_out_free; - -	return 0; - -err_out_free: -	kfree(e->pages); -	return -ENOMEM; -} - -static void pohmelfs_sys_crypto_exit_one(struct pohmelfs_crypto_thread *t) -{ -	struct pohmelfs_sb *psb = t->psb; - -	if (t->thread) -		kthread_stop(t->thread); - -	mutex_lock(&psb->crypto_thread_lock); -	list_del(&t->thread_entry); -	psb->crypto_thread_num--; -	mutex_unlock(&psb->crypto_thread_lock); - -	pohmelfs_crypto_engine_exit(&t->eng); -	pohmelfs_crypto_pages_free(&t->eng); -	kfree(t); -} - -static int pohmelfs_crypto_finish(struct netfs_trans *t, struct pohmelfs_sb *psb, int err) -{ -	struct netfs_cmd *cmd = t->iovec.iov_base; -	netfs_convert_cmd(cmd); - -	if (likely(!err)) -		err = netfs_trans_finish_send(t, psb); - -	t->result = err; -	netfs_trans_put(t); - -	return err; -} - -void pohmelfs_crypto_thread_make_ready(struct pohmelfs_crypto_thread *th) -{ -	struct pohmelfs_sb *psb = th->psb; - -	th->page = NULL; -	th->trans = NULL; - -	mutex_lock(&psb->crypto_thread_lock); -	list_move_tail(&th->thread_entry, &psb->crypto_ready_list); -	mutex_unlock(&psb->crypto_thread_lock); -	wake_up(&psb->wait); -} - -static int pohmelfs_crypto_thread_trans(struct pohmelfs_crypto_thread *t) -{ -	struct netfs_trans *trans; -	int err = 0; - -	trans = t->trans; -	trans->eng = NULL; - -	if (t->eng.hash) { -		err = pohmelfs_hash(t); -		if (err) -			goto out_complete; -	} - -	if (t->eng.cipher) { -		err = pohmelfs_encrypt(t); -		if (err) -			goto out_complete; -		trans->eng = &t->eng; -	} - -out_complete: -	t->page = NULL; -	t->trans = NULL; - -	if (!trans->eng) -		pohmelfs_crypto_thread_make_ready(t); - -	pohmelfs_crypto_finish(trans, t->psb, err); -	return err; -} - -static int pohmelfs_crypto_thread_page(struct pohmelfs_crypto_thread *t) -{ -	struct pohmelfs_crypto_engine *e = &t->eng; -	struct page *page = t->page; -	int err; - -	WARN_ON(!PageChecked(page)); - -	err = pohmelfs_crypto_process_input_data(e, e->iv, NULL, page, t->size); -	if (!err) -		SetPageUptodate(page); -	else -		SetPageError(page); -	unlock_page(page); -	page_cache_release(page); - -	pohmelfs_crypto_thread_make_ready(t); - -	return err; -} - -static int pohmelfs_crypto_thread_func(void *data) -{ -	struct pohmelfs_crypto_thread *t = data; - -	while (!kthread_should_stop()) { -		wait_event_interruptible(t->wait, kthread_should_stop() || -				t->trans || t->page); - -		if (kthread_should_stop()) -			break; - -		if (!t->trans && !t->page) -			continue; - -		dprintk("%s: thread: %p, trans: %p, page: %p.\n", -				__func__, t, t->trans, t->page); - -		if (t->trans) -			pohmelfs_crypto_thread_trans(t); -		else if (t->page) -			pohmelfs_crypto_thread_page(t); -	} - -	return 0; -} - -static void pohmelfs_crypto_flush(struct pohmelfs_sb *psb, struct list_head *head) -{ -	while (!list_empty(head)) { -		struct pohmelfs_crypto_thread *t = NULL; - -		mutex_lock(&psb->crypto_thread_lock); -		if (!list_empty(head)) { -			t = list_first_entry(head, struct pohmelfs_crypto_thread, thread_entry); -			list_del_init(&t->thread_entry); -		} -		mutex_unlock(&psb->crypto_thread_lock); - -		if (t) -			pohmelfs_sys_crypto_exit_one(t); -	} -} - -static void pohmelfs_sys_crypto_exit(struct pohmelfs_sb *psb) -{ -	while (!list_empty(&psb->crypto_active_list) || !list_empty(&psb->crypto_ready_list)) { -		dprintk("%s: crypto_thread_num: %u.\n", __func__, psb->crypto_thread_num); -		pohmelfs_crypto_flush(psb, &psb->crypto_active_list); -		pohmelfs_crypto_flush(psb, &psb->crypto_ready_list); -	} -} - -static int pohmelfs_sys_crypto_init(struct pohmelfs_sb *psb) -{ -	unsigned int i; -	struct pohmelfs_crypto_thread *t; -	struct pohmelfs_config *c; -	struct netfs_state *st; -	int err; - -	list_for_each_entry(c, &psb->state_list, config_entry) { -		st = &c->state; - -		err = pohmelfs_crypto_engine_init(&st->eng, psb); -		if (err) -			goto err_out_exit; - -		dprintk("%s: st: %p, eng: %p, hash: %p, cipher: %p.\n", -				__func__, st, &st->eng, &st->eng.hash, &st->eng.cipher); -	} - -	for (i = 0; i < psb->crypto_thread_num; ++i) { -		err = -ENOMEM; -		t = kzalloc(sizeof(struct pohmelfs_crypto_thread), GFP_KERNEL); -		if (!t) -			goto err_out_free_state_engines; - -		init_waitqueue_head(&t->wait); - -		t->psb = psb; -		t->trans = NULL; -		t->eng.thread = t; - -		err = pohmelfs_crypto_engine_init(&t->eng, psb); -		if (err) -			goto err_out_free_state_engines; - -		err = pohmelfs_crypto_pages_alloc(&t->eng, psb); -		if (err) -			goto err_out_free; - -		t->thread = kthread_run(pohmelfs_crypto_thread_func, t, -				"pohmelfs-crypto-%d-%d", psb->idx, i); -		if (IS_ERR(t->thread)) { -			err = PTR_ERR(t->thread); -			t->thread = NULL; -			goto err_out_free; -		} - -		if (t->eng.cipher) -			psb->crypto_align_size = crypto_ablkcipher_blocksize(t->eng.cipher); - -		mutex_lock(&psb->crypto_thread_lock); -		list_add_tail(&t->thread_entry, &psb->crypto_ready_list); -		mutex_unlock(&psb->crypto_thread_lock); -	} - -	psb->crypto_thread_num = i; -	return 0; - -err_out_free: -	pohmelfs_sys_crypto_exit_one(t); -err_out_free_state_engines: -	list_for_each_entry(c, &psb->state_list, config_entry) { -		st = &c->state; -		pohmelfs_crypto_engine_exit(&st->eng); -	} -err_out_exit: -	pohmelfs_sys_crypto_exit(psb); -	return err; -} - -void pohmelfs_crypto_exit(struct pohmelfs_sb *psb) -{ -	pohmelfs_sys_crypto_exit(psb); - -	kfree(psb->hash_string); -	kfree(psb->cipher_string); -} - -static int pohmelfs_crypt_init_complete(struct page **pages, unsigned int page_num, -		void *private, int err) -{ -	struct pohmelfs_sb *psb = private; - -	psb->flags = -err; -	dprintk("%s: err: %d.\n", __func__, err); - -	wake_up(&psb->wait); - -	return err; -} - -static int pohmelfs_crypto_init_handshake(struct pohmelfs_sb *psb) -{ -	struct netfs_trans *t; -	struct netfs_crypto_capabilities *cap; -	struct netfs_cmd *cmd; -	char *str; -	int err = -ENOMEM, size; - -	size = sizeof(struct netfs_crypto_capabilities) + -		psb->cipher_strlen + psb->hash_strlen + 2; /* 0 bytes */ - -	t = netfs_trans_alloc(psb, size, 0, 0); -	if (!t) -		goto err_out_exit; - -	t->complete = pohmelfs_crypt_init_complete; -	t->private = psb; - -	cmd = netfs_trans_current(t); -	cap = (struct netfs_crypto_capabilities *)(cmd + 1); -	str = (char *)(cap + 1); - -	cmd->cmd = NETFS_CAPABILITIES; -	cmd->id = POHMELFS_CRYPTO_CAPABILITIES; -	cmd->size = size; -	cmd->start = 0; -	cmd->ext = 0; -	cmd->csize = 0; - -	netfs_convert_cmd(cmd); -	netfs_trans_update(cmd, t, size); - -	cap->hash_strlen = psb->hash_strlen; -	if (cap->hash_strlen) { -		sprintf(str, "%s", psb->hash_string); -		str += cap->hash_strlen; -	} - -	cap->cipher_strlen = psb->cipher_strlen; -	cap->cipher_keysize = psb->cipher_keysize; -	if (cap->cipher_strlen) -		sprintf(str, "%s", psb->cipher_string); - -	netfs_convert_crypto_capabilities(cap); - -	psb->flags = ~0; -	err = netfs_trans_finish(t, psb); -	if (err) -		goto err_out_exit; - -	err = wait_event_interruptible_timeout(psb->wait, (psb->flags != ~0), -			psb->wait_on_page_timeout); -	if (!err) -		err = -ETIMEDOUT; -	else if (err > 0) -		err = -psb->flags; - -	if (!err) -		psb->perform_crypto = 1; -	psb->flags = 0; - -	/* -	 * At this point NETFS_CAPABILITIES response command -	 * should setup superblock in a way, which is acceptable -	 * for both client and server, so if server refuses connection, -	 * it will send error in transaction response. -	 */ - -	if (err) -		goto err_out_exit; - -	return 0; - -err_out_exit: -	return err; -} - -int pohmelfs_crypto_init(struct pohmelfs_sb *psb) -{ -	int err; - -	if (!psb->cipher_string && !psb->hash_string) -		return 0; - -	err = pohmelfs_crypto_init_handshake(psb); -	if (err) -		return err; - -	err = pohmelfs_sys_crypto_init(psb); -	if (err) -		return err; - -	return 0; -} - -static int pohmelfs_crypto_thread_get(struct pohmelfs_sb *psb, -		int (*action)(struct pohmelfs_crypto_thread *t, void *data), void *data) -{ -	struct pohmelfs_crypto_thread *t = NULL; -	int err; - -	while (!t) { -		err = wait_event_interruptible_timeout(psb->wait, -				!list_empty(&psb->crypto_ready_list), -				psb->wait_on_page_timeout); - -		t = NULL; -		err = 0; -		mutex_lock(&psb->crypto_thread_lock); -		if (!list_empty(&psb->crypto_ready_list)) { -			t = list_entry(psb->crypto_ready_list.prev, -					struct pohmelfs_crypto_thread, -					thread_entry); - -			list_move_tail(&t->thread_entry, -					&psb->crypto_active_list); - -			action(t, data); -			wake_up(&t->wait); - -		} -		mutex_unlock(&psb->crypto_thread_lock); -	} - -	return err; -} - -static int pohmelfs_trans_crypt_action(struct pohmelfs_crypto_thread *t, void *data) -{ -	struct netfs_trans *trans = data; - -	netfs_trans_get(trans); -	t->trans = trans; - -	dprintk("%s: t: %p, gen: %u, thread: %p.\n", __func__, trans, trans->gen, t); -	return 0; -} - -int pohmelfs_trans_crypt(struct netfs_trans *trans, struct pohmelfs_sb *psb) -{ -	if ((!psb->hash_string && !psb->cipher_string) || !psb->perform_crypto) { -		netfs_trans_get(trans); -		return pohmelfs_crypto_finish(trans, psb, 0); -	} - -	return pohmelfs_crypto_thread_get(psb, pohmelfs_trans_crypt_action, trans); -} - -struct pohmelfs_crypto_input_action_data { -	struct page			*page; -	struct pohmelfs_crypto_engine	*e; -	u64				iv; -	unsigned int			size; -}; - -static int pohmelfs_crypt_input_page_action(struct pohmelfs_crypto_thread *t, void *data) -{ -	struct pohmelfs_crypto_input_action_data *act = data; - -	memcpy(t->eng.data, act->e->data, t->psb->crypto_attached_size); - -	t->size = act->size; -	t->eng.iv = act->iv; - -	t->page = act->page; -	return 0; -} - -int pohmelfs_crypto_process_input_page(struct pohmelfs_crypto_engine *e, -		struct page *page, unsigned int size, u64 iv) -{ -	struct inode *inode = page->mapping->host; -	struct pohmelfs_crypto_input_action_data act; -	int err = -ENOENT; - -	act.page = page; -	act.e = e; -	act.size = size; -	act.iv = iv; - -	err = pohmelfs_crypto_thread_get(POHMELFS_SB(inode->i_sb), -			pohmelfs_crypt_input_page_action, &act); -	if (err) -		goto err_out_exit; - -	return 0; - -err_out_exit: -	SetPageUptodate(page); -	page_cache_release(page); - -	return err; -} diff --git a/drivers/staging/pohmelfs/dir.c b/drivers/staging/pohmelfs/dir.c deleted file mode 100644 index 2ee4491b713..00000000000 --- a/drivers/staging/pohmelfs/dir.c +++ /dev/null @@ -1,1102 +0,0 @@ -/* - * 2007+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net> - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU General Public License for more details. - */ - -#include <linux/kernel.h> -#include <linux/fs.h> -#include <linux/jhash.h> -#include <linux/namei.h> -#include <linux/slab.h> -#include <linux/pagemap.h> - -#include "netfs.h" - -static int pohmelfs_cmp_hash(struct pohmelfs_name *n, u32 hash) -{ -	if (n->hash > hash) -		return -1; -	if (n->hash < hash) -		return 1; - -	return 0; -} - -static struct pohmelfs_name *pohmelfs_search_hash_unprecise(struct pohmelfs_inode *pi, u32 hash) -{ -	struct rb_node *n = pi->hash_root.rb_node; -	struct pohmelfs_name *tmp = NULL; -	int cmp; - -	while (n) { -		tmp = rb_entry(n, struct pohmelfs_name, hash_node); - -		cmp = pohmelfs_cmp_hash(tmp, hash); -		if (cmp < 0) -			n = n->rb_left; -		else if (cmp > 0) -			n = n->rb_right; -		else -			break; - -	} - -	return tmp; -} - -struct pohmelfs_name *pohmelfs_search_hash(struct pohmelfs_inode *pi, u32 hash) -{ -	struct pohmelfs_name *tmp; - -	tmp = pohmelfs_search_hash_unprecise(pi, hash); -	if (tmp && (tmp->hash == hash)) -		return tmp; - -	return NULL; -} - -static void __pohmelfs_name_del(struct pohmelfs_inode *parent, struct pohmelfs_name *node) -{ -	rb_erase(&node->hash_node, &parent->hash_root); -} - -/* - * Remove name cache entry from its caches and free it. - */ -static void pohmelfs_name_free(struct pohmelfs_inode *parent, struct pohmelfs_name *node) -{ -	__pohmelfs_name_del(parent, node); -	list_del(&node->sync_create_entry); -	kfree(node); -} - -static struct pohmelfs_name *pohmelfs_insert_hash(struct pohmelfs_inode *pi, -		struct pohmelfs_name *new) -{ -	struct rb_node **n = &pi->hash_root.rb_node, *parent = NULL; -	struct pohmelfs_name *ret = NULL, *tmp; -	int cmp; - -	while (*n) { -		parent = *n; - -		tmp = rb_entry(parent, struct pohmelfs_name, hash_node); - -		cmp = pohmelfs_cmp_hash(tmp, new->hash); -		if (cmp < 0) -			n = &parent->rb_left; -		else if (cmp > 0) -			n = &parent->rb_right; -		else { -			ret = tmp; -			break; -		} -	} - -	if (ret) { -		printk("%s: exist: parent: %llu, ino: %llu, hash: %x, len: %u, data: '%s', " -					"new: ino: %llu, hash: %x, len: %u, data: '%s'.\n", -				__func__, pi->ino, -				ret->ino, ret->hash, ret->len, ret->data, -				new->ino, new->hash, new->len, new->data); -		ret->ino = new->ino; -		return ret; -	} - -	rb_link_node(&new->hash_node, parent, n); -	rb_insert_color(&new->hash_node, &pi->hash_root); - -	return NULL; -} - -/* - * Free name cache for given inode. - */ -void pohmelfs_free_names(struct pohmelfs_inode *parent) -{ -	struct rb_node *rb_node; -	struct pohmelfs_name *n; - -	for (rb_node = rb_first(&parent->hash_root); rb_node;) { -		n = rb_entry(rb_node, struct pohmelfs_name, hash_node); -		rb_node = rb_next(rb_node); - -		pohmelfs_name_free(parent, n); -	} -} - -static void pohmelfs_fix_offset(struct pohmelfs_inode *parent, struct pohmelfs_name *node) -{ -	parent->total_len -= node->len; -} - -/* - * Free name cache entry helper. - */ -void pohmelfs_name_del(struct pohmelfs_inode *parent, struct pohmelfs_name *node) -{ -	pohmelfs_fix_offset(parent, node); -	pohmelfs_name_free(parent, node); -} - -/* - * Insert new name cache entry into all hash cache. - */ -static int pohmelfs_insert_name(struct pohmelfs_inode *parent, struct pohmelfs_name *n) -{ -	struct pohmelfs_name *name; - -	name = pohmelfs_insert_hash(parent, n); -	if (name) -		return -EEXIST; - -	parent->total_len += n->len; -	list_add_tail(&n->sync_create_entry, &parent->sync_create_list); - -	return 0; -} - -/* - * Allocate new name cache entry. - */ -static struct pohmelfs_name *pohmelfs_name_alloc(unsigned int len) -{ -	struct pohmelfs_name *n; - -	n = kzalloc(sizeof(struct pohmelfs_name) + len, GFP_KERNEL); -	if (!n) -		return NULL; - -	INIT_LIST_HEAD(&n->sync_create_entry); - -	n->data = (char *)(n+1); - -	return n; -} - -/* - * Add new name entry into directory's cache. - */ -static int pohmelfs_add_dir(struct pohmelfs_sb *psb, struct pohmelfs_inode *parent, -		struct pohmelfs_inode *npi, struct qstr *str, unsigned int mode, int link) -{ -	int err = -ENOMEM; -	struct pohmelfs_name *n; - -	n = pohmelfs_name_alloc(str->len + 1); -	if (!n) -		goto err_out_exit; - -	n->ino = npi->ino; -	n->mode = mode; -	n->len = str->len; -	n->hash = str->hash; -	sprintf(n->data, "%s", str->name); - -	mutex_lock(&parent->offset_lock); -	err = pohmelfs_insert_name(parent, n); -	mutex_unlock(&parent->offset_lock); - -	if (err) { -		if (err != -EEXIST) -			goto err_out_free; -		kfree(n); -	} - -	return 0; - -err_out_free: -	kfree(n); -err_out_exit: -	return err; -} - -/* - * Create new inode for given parameters (name, inode info, parent). - * This does not create object on the server, it will be synced there during writeback. - */ -struct pohmelfs_inode *pohmelfs_new_inode(struct pohmelfs_sb *psb, -		struct pohmelfs_inode *parent, struct qstr *str, -		struct netfs_inode_info *info, int link) -{ -	struct inode *new = NULL; -	struct pohmelfs_inode *npi; -	int err = -EEXIST; - -	dprintk("%s: creating inode: parent: %llu, ino: %llu, str: %p.\n", -			__func__, (parent) ? parent->ino : 0, info->ino, str); - -	err = -ENOMEM; -	new = iget_locked(psb->sb, info->ino); -	if (!new) -		goto err_out_exit; - -	npi = POHMELFS_I(new); -	npi->ino = info->ino; -	err = 0; - -	if (new->i_state & I_NEW) { -		dprintk("%s: filling VFS inode: %lu/%llu.\n", -				__func__, new->i_ino, info->ino); -		pohmelfs_fill_inode(new, info); - -		if (S_ISDIR(info->mode)) { -			struct qstr s; - -			s.name = "."; -			s.len = 1; -			s.hash = jhash(s.name, s.len, 0); - -			err = pohmelfs_add_dir(psb, npi, npi, &s, info->mode, 0); -			if (err) -				goto err_out_put; - -			s.name = ".."; -			s.len = 2; -			s.hash = jhash(s.name, s.len, 0); - -			err = pohmelfs_add_dir(psb, npi, (parent) ? parent : npi, &s, -					(parent) ? parent->vfs_inode.i_mode : npi->vfs_inode.i_mode, 0); -			if (err) -				goto err_out_put; -		} -	} - -	if (str) { -		if (parent) { -			err = pohmelfs_add_dir(psb, parent, npi, str, info->mode, link); - -			dprintk("%s: %s inserted name: '%s', new_offset: %llu, ino: %llu, parent: %llu.\n", -					__func__, (err) ? "unsuccessfully" : "successfully", -					str->name, parent->total_len, info->ino, parent->ino); - -			if (err && err != -EEXIST) -				goto err_out_put; -		} -	} - -	if (new->i_state & I_NEW) { -		if (parent) -			mark_inode_dirty(&parent->vfs_inode); -		mark_inode_dirty(new); -	} - -	set_bit(NETFS_INODE_OWNED, &npi->state); -	npi->lock_type = POHMELFS_WRITE_LOCK; -	unlock_new_inode(new); - -	return npi; - -err_out_put: -	printk("%s: putting inode: %p, npi: %p, error: %d.\n", __func__, new, npi, err); -	iput(new); -err_out_exit: -	return ERR_PTR(err); -} - -static int pohmelfs_remote_sync_complete(struct page **pages, unsigned int page_num, -		void *private, int err) -{ -	struct pohmelfs_inode *pi = private; -	struct pohmelfs_sb *psb = POHMELFS_SB(pi->vfs_inode.i_sb); - -	dprintk("%s: ino: %llu, err: %d.\n", __func__, pi->ino, err); - -	if (err) -		pi->error = err; -	wake_up(&psb->wait); -	pohmelfs_put_inode(pi); - -	return err; -} - -/* - * Receive directory content from the server. - * This should be only done for objects, which were not created locally, - * and which were not synced previously. - */ -static int pohmelfs_sync_remote_dir(struct pohmelfs_inode *pi) -{ -	struct inode *inode = &pi->vfs_inode; -	struct pohmelfs_sb *psb = POHMELFS_SB(inode->i_sb); -	long ret = psb->wait_on_page_timeout; -	int err; - -	dprintk("%s: dir: %llu, state: %lx: remote_synced: %d.\n", -		__func__, pi->ino, pi->state, test_bit(NETFS_INODE_REMOTE_SYNCED, &pi->state)); - -	if (test_bit(NETFS_INODE_REMOTE_DIR_SYNCED, &pi->state)) -		return 0; - -	if (!igrab(inode)) { -		err = -ENOENT; -		goto err_out_exit; -	} - -	err = pohmelfs_meta_command(pi, NETFS_READDIR, NETFS_TRANS_SINGLE_DST, -			pohmelfs_remote_sync_complete, pi, 0); -	if (err) -		goto err_out_exit; - -	pi->error = 0; -	ret = wait_event_interruptible_timeout(psb->wait, -			test_bit(NETFS_INODE_REMOTE_DIR_SYNCED, &pi->state) || pi->error, ret); -	dprintk("%s: awake dir: %llu, ret: %ld, err: %d.\n", __func__, pi->ino, ret, pi->error); -	if (ret <= 0) { -		err = ret; -		if (!err) -			err = -ETIMEDOUT; -		goto err_out_exit; -	} - -	if (pi->error) -		return pi->error; - -	return 0; - -err_out_exit: -	clear_bit(NETFS_INODE_REMOTE_SYNCED, &pi->state); - -	return err; -} - -static int pohmelfs_dir_open(struct inode *inode, struct file *file) -{ -	file->private_data = NULL; -	return 0; -} - -/* - * VFS readdir callback. Syncs directory content from server if needed, - * and provides direntry info to the userspace. - */ -static int pohmelfs_readdir(struct file *file, void *dirent, filldir_t filldir) -{ -	struct inode *inode = file->f_path.dentry->d_inode; -	struct pohmelfs_inode *pi = POHMELFS_I(inode); -	struct pohmelfs_name *n; -	struct rb_node *rb_node; -	int err = 0, mode; -	u64 len; - -	dprintk("%s: parent: %llu, fpos: %llu, hash: %08lx.\n", -			__func__, pi->ino, (u64)file->f_pos, -			(unsigned long)file->private_data); -#if 0 -	err = pohmelfs_data_lock(pi, 0, ~0, POHMELFS_READ_LOCK); -	if (err) -		return err; -#endif -	err = pohmelfs_sync_remote_dir(pi); -	if (err) -		return err; - -	if (file->private_data && (file->private_data == (void *)(unsigned long)file->f_pos)) -		return 0; - -	mutex_lock(&pi->offset_lock); -	n = pohmelfs_search_hash_unprecise(pi, (unsigned long)file->private_data); - -	while (n) { -		mode = (n->mode >> 12) & 15; - -		dprintk("%s: offset: %llu, parent ino: %llu, name: '%s', len: %u, ino: %llu, " -				"mode: %o/%o, fpos: %llu, hash: %08x.\n", -				__func__, file->f_pos, pi->ino, n->data, n->len, -				n->ino, n->mode, mode, file->f_pos, n->hash); - -		file->private_data = (void *)(unsigned long)n->hash; - -		len = n->len; -		err = filldir(dirent, n->data, n->len, file->f_pos, n->ino, mode); - -		if (err < 0) { -			dprintk("%s: err: %d.\n", __func__, err); -			err = 0; -			break; -		} - -		file->f_pos += len; - -		rb_node = rb_next(&n->hash_node); - -		if (!rb_node || (rb_node == &n->hash_node)) { -			file->private_data = (void *)(unsigned long)file->f_pos; -			break; -		} - -		n = rb_entry(rb_node, struct pohmelfs_name, hash_node); -	} -	mutex_unlock(&pi->offset_lock); - -	return err; -} - -static loff_t pohmelfs_dir_lseek(struct file *file, loff_t offset, int origin) -{ -	file->f_pos = offset; -	file->private_data = NULL; -	return offset; -} - -const struct file_operations pohmelfs_dir_fops = { -	.open = pohmelfs_dir_open, -	.read = generic_read_dir, -	.llseek = pohmelfs_dir_lseek, -	.readdir = pohmelfs_readdir, -}; - -/* - * Lookup single object on server. - */ -static int pohmelfs_lookup_single(struct pohmelfs_inode *parent, -		struct qstr *str, u64 ino) -{ -	struct pohmelfs_sb *psb = POHMELFS_SB(parent->vfs_inode.i_sb); -	long ret = msecs_to_jiffies(5000); -	int err; - -	set_bit(NETFS_COMMAND_PENDING, &parent->state); -	err = pohmelfs_meta_command_data(parent, parent->ino, NETFS_LOOKUP, -			(char *)str->name, NETFS_TRANS_SINGLE_DST, NULL, NULL, ino); -	if (err) -		goto err_out_exit; - -	err = 0; -	ret = wait_event_interruptible_timeout(psb->wait, -			!test_bit(NETFS_COMMAND_PENDING, &parent->state), ret); -	if (ret <= 0) { -		err = ret; -		if (!err) -			err = -ETIMEDOUT; -	} - -	if (err) -		goto err_out_exit; - -	return 0; - -err_out_exit: -	clear_bit(NETFS_COMMAND_PENDING, &parent->state); - -	printk("%s: failed: parent: %llu, ino: %llu, name: '%s', err: %d.\n", -			__func__, parent->ino, ino, str->name, err); - -	return err; -} - -/* - * VFS lookup callback. - * We first try to get inode number from local name cache, if we have one, - * then inode can be found in inode cache. If there is no inode or no object in - * local cache, try to lookup it on server. This only should be done for directories, - * which were not created locally, otherwise remote server does not know about dir at all, - * so no need to try to know that. - */ -struct dentry *pohmelfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) -{ -	struct pohmelfs_inode *parent = POHMELFS_I(dir); -	struct pohmelfs_name *n; -	struct inode *inode = NULL; -	unsigned long ino = 0; -	int err, lock_type = POHMELFS_READ_LOCK, need_lock = 1; -	struct qstr str = dentry->d_name; - -	if ((nd->intent.open.flags & O_ACCMODE) != O_RDONLY) -		lock_type = POHMELFS_WRITE_LOCK; - -	if (test_bit(NETFS_INODE_OWNED, &parent->state)) { -		if (lock_type == parent->lock_type) -			need_lock = 0; -		if ((lock_type == POHMELFS_READ_LOCK) && (parent->lock_type == POHMELFS_WRITE_LOCK)) -			need_lock = 0; -	} - -	if ((lock_type == POHMELFS_READ_LOCK) && !test_bit(NETFS_INODE_REMOTE_DIR_SYNCED, &parent->state)) -		need_lock = 1; - -	str.hash = jhash(dentry->d_name.name, dentry->d_name.len, 0); - -	mutex_lock(&parent->offset_lock); -	n = pohmelfs_search_hash(parent, str.hash); -	if (n) -		ino = n->ino; -	mutex_unlock(&parent->offset_lock); - -	dprintk("%s: start ino: %lu, inode: %p, name: '%s', hash: %x, parent_state: %lx, need_lock: %d.\n", -			__func__, ino, inode, str.name, str.hash, parent->state, need_lock); - -	if (ino) { -		inode = ilookup(dir->i_sb, ino); -		if (inode) -			goto out; -	} - -	dprintk("%s: no inode dir: %p, dir_ino: %llu, name: '%s', len: %u, dir_state: %lx, ino: %lu.\n", -			__func__, dir, parent->ino, -			str.name, str.len, parent->state, ino); - -	if (!ino) { -		if (!need_lock) -			goto out; -	} - -	err = pohmelfs_data_lock(parent, 0, ~0, lock_type); -	if (err) -		goto out; - -	err = pohmelfs_lookup_single(parent, &str, ino); -	if (err) -		goto out; - -	if (!ino) { -		mutex_lock(&parent->offset_lock); -		n = pohmelfs_search_hash(parent, str.hash); -		if (n) -			ino = n->ino; -		mutex_unlock(&parent->offset_lock); -	} - -	if (ino) { -		inode = ilookup(dir->i_sb, ino); -		dprintk("%s: second lookup ino: %lu, inode: %p, name: '%s', hash: %x.\n", -				__func__, ino, inode, str.name, str.hash); -		if (!inode) { -			dprintk("%s: No inode for ino: %lu, name: '%s', hash: %x.\n", -				__func__, ino, str.name, str.hash); -			/* return NULL; */ -			return ERR_PTR(-EACCES); -		} -	} else { -		printk("%s: No inode number : name: '%s', hash: %x.\n", -			__func__, str.name, str.hash); -	} -out: -	return d_splice_alias(inode, dentry); -} - -/* - * Create new object in local cache. Object will be synced to server - * during writeback for given inode. - */ -struct pohmelfs_inode *pohmelfs_create_entry_local(struct pohmelfs_sb *psb, -	struct pohmelfs_inode *parent, struct qstr *str, u64 start, umode_t mode) -{ -	struct pohmelfs_inode *npi; -	int err = -ENOMEM; -	struct netfs_inode_info info; - -	dprintk("%s: name: '%s', mode: %ho, start: %llu.\n", -			__func__, str->name, mode, start); - -	info.mode = mode; -	info.ino = start; - -	if (!start) -		info.ino = pohmelfs_new_ino(psb); - -	info.nlink = S_ISDIR(mode) ? 2 : 1; -	info.uid = current_fsuid(); -	info.gid = current_fsgid(); -	info.size = 0; -	info.blocksize = 512; -	info.blocks = 0; -	info.rdev = 0; -	info.version = 0; - -	npi = pohmelfs_new_inode(psb, parent, str, &info, !!start); -	if (IS_ERR(npi)) { -		err = PTR_ERR(npi); -		goto err_out_unlock; -	} - -	return npi; - -err_out_unlock: -	dprintk("%s: err: %d.\n", __func__, err); -	return ERR_PTR(err); -} - -/* - * Create local object and bind it to dentry. - */ -static int pohmelfs_create_entry(struct inode *dir, struct dentry *dentry, -				 u64 start, umode_t mode) -{ -	struct pohmelfs_sb *psb = POHMELFS_SB(dir->i_sb); -	struct pohmelfs_inode *npi, *parent; -	struct qstr str = dentry->d_name; -	int err; - -	parent = POHMELFS_I(dir); - -	err = pohmelfs_data_lock(parent, 0, ~0, POHMELFS_WRITE_LOCK); -	if (err) -		return err; - -	str.hash = jhash(dentry->d_name.name, dentry->d_name.len, 0); - -	npi = pohmelfs_create_entry_local(psb, parent, &str, start, mode); -	if (IS_ERR(npi)) -		return PTR_ERR(npi); - -	d_instantiate(dentry, &npi->vfs_inode); - -	dprintk("%s: parent: %llu, inode: %llu, name: '%s', parent_nlink: %d, nlink: %d.\n", -			__func__, parent->ino, npi->ino, dentry->d_name.name, -			(signed)dir->i_nlink, (signed)npi->vfs_inode.i_nlink); - -	return 0; -} - -/* - * VFS create and mkdir callbacks. - */ -static int pohmelfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, -		struct nameidata *nd) -{ -	return pohmelfs_create_entry(dir, dentry, 0, mode); -} - -static int pohmelfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) -{ -	int err; - -	inode_inc_link_count(dir); -	err = pohmelfs_create_entry(dir, dentry, 0, mode | S_IFDIR); -	if (err) -		inode_dec_link_count(dir); - -	return err; -} - -static int pohmelfs_remove_entry(struct inode *dir, struct dentry *dentry) -{ -	struct pohmelfs_sb *psb = POHMELFS_SB(dir->i_sb); -	struct inode *inode = dentry->d_inode; -	struct pohmelfs_inode *parent = POHMELFS_I(dir), *pi = POHMELFS_I(inode); -	struct pohmelfs_name *n; -	int err = -ENOENT; -	struct qstr str = dentry->d_name; - -	err = pohmelfs_data_lock(parent, 0, ~0, POHMELFS_WRITE_LOCK); -	if (err) -		return err; - -	str.hash = jhash(dentry->d_name.name, dentry->d_name.len, 0); - -	dprintk("%s: dir_ino: %llu, inode: %llu, name: '%s', nlink: %d.\n", -			__func__, parent->ino, pi->ino, -			str.name, (signed)inode->i_nlink); - -	BUG_ON(!inode); - -	mutex_lock(&parent->offset_lock); -	n = pohmelfs_search_hash(parent, str.hash); -	if (n) { -		pohmelfs_fix_offset(parent, n); -		if (test_bit(NETFS_INODE_REMOTE_SYNCED, &pi->state)) -			pohmelfs_remove_child(pi, n); - -		pohmelfs_name_free(parent, n); -		err = 0; -	} -	mutex_unlock(&parent->offset_lock); - -	if (!err) { -		psb->avail_size += inode->i_size; - -		pohmelfs_inode_del_inode(psb, pi); - -		mark_inode_dirty(dir); - -		inode->i_ctime = dir->i_ctime; -		if (inode->i_nlink) -			inode_dec_link_count(inode); -	} - -	return err; -} - -/* - * Unlink and rmdir VFS callbacks. - */ -static int pohmelfs_unlink(struct inode *dir, struct dentry *dentry) -{ -	return pohmelfs_remove_entry(dir, dentry); -} - -static int pohmelfs_rmdir(struct inode *dir, struct dentry *dentry) -{ -	int err; -	struct inode *inode = dentry->d_inode; - -	dprintk("%s: parent: %llu, inode: %llu, name: '%s', parent_nlink: %d, nlink: %d.\n", -			__func__, POHMELFS_I(dir)->ino, POHMELFS_I(inode)->ino, -			dentry->d_name.name, (signed)dir->i_nlink, (signed)inode->i_nlink); - -	err = pohmelfs_remove_entry(dir, dentry); -	if (!err) { -		inode_dec_link_count(dir); -		inode_dec_link_count(inode); -	} - -	return err; -} - -/* - * Link creation is synchronous. - * I'm lazy. - * Earth is somewhat round. - */ -static int pohmelfs_create_link(struct pohmelfs_inode *parent, struct qstr *obj, -		struct pohmelfs_inode *target, struct qstr *tstr) -{ -	struct super_block *sb = parent->vfs_inode.i_sb; -	struct pohmelfs_sb *psb = POHMELFS_SB(sb); -	struct netfs_cmd *cmd; -	struct netfs_trans *t; -	void *data; -	int err, parent_len, target_len = 0, cur_len, path_size = 0; - -	err = pohmelfs_data_lock(parent, 0, ~0, POHMELFS_WRITE_LOCK); -	if (err) -		return err; - -	err = sb->s_op->write_inode(&parent->vfs_inode, 0); -	if (err) -		goto err_out_exit; - -	if (tstr) -		target_len = tstr->len; - -	parent_len = pohmelfs_path_length(parent); -	if (target) -		target_len += pohmelfs_path_length(target); - -	if (parent_len < 0) { -		err = parent_len; -		goto err_out_exit; -	} - -	if (target_len < 0) { -		err = target_len; -		goto err_out_exit; -	} - -	t = netfs_trans_alloc(psb, parent_len + target_len + obj->len + 2, 0, 0); -	if (!t) { -		err = -ENOMEM; -		goto err_out_exit; -	} -	cur_len = netfs_trans_cur_len(t); - -	cmd = netfs_trans_current(t); -	if (IS_ERR(cmd)) { -		err = PTR_ERR(cmd); -		goto err_out_free; -	} - -	data = (void *)(cmd + 1); -	cur_len -= sizeof(struct netfs_cmd); - -	err = pohmelfs_construct_path_string(parent, data, parent_len); -	if (err > 0) { -		/* Do not place null-byte before the slash */ -		path_size = err - 1; -		cur_len -= path_size; - -		err = snprintf(data + path_size, cur_len, "/%s|", obj->name); - -		path_size += err; -		cur_len -= err; - -		cmd->ext = path_size - 1; /* No | symbol */ - -		if (target) { -			err = pohmelfs_construct_path_string(target, data + path_size, target_len); -			if (err > 0) { -				path_size += err; -				cur_len -= err; -			} -		} -	} - -	if (err < 0) -		goto err_out_free; - -	cmd->start = 0; - -	if (!target && tstr) { -		if (tstr->len > cur_len - 1) { -			err = -ENAMETOOLONG; -			goto err_out_free; -		} - -		err = snprintf(data + path_size, cur_len, "%s", tstr->name) + 1; /* 0-byte */ -		path_size += err; -		cur_len -= err; -		cmd->start = 1; -	} - -	dprintk("%s: parent: %llu, obj: '%s', target_inode: %llu, target_str: '%s', full: '%s'.\n", -			__func__, parent->ino, obj->name, (target) ? target->ino : 0, (tstr) ? tstr->name : NULL, -			(char *)data); - -	cmd->cmd = NETFS_LINK; -	cmd->size = path_size; -	cmd->id = parent->ino; - -	netfs_convert_cmd(cmd); - -	netfs_trans_update(cmd, t, path_size); - -	err = netfs_trans_finish(t, psb); -	if (err) -		goto err_out_exit; - -	return 0; - -err_out_free: -	t->result = err; -	netfs_trans_put(t); -err_out_exit: -	return err; -} - -/* - *  VFS hard and soft link callbacks. - */ -static int pohmelfs_link(struct dentry *old_dentry, struct inode *dir, -	struct dentry *dentry) -{ -	struct inode *inode = old_dentry->d_inode; -	struct pohmelfs_inode *pi = POHMELFS_I(inode); -	int err; -	struct qstr str = dentry->d_name; - -	str.hash = jhash(dentry->d_name.name, dentry->d_name.len, 0); - -	err = inode->i_sb->s_op->write_inode(inode, 0); -	if (err) -		return err; - -	err = pohmelfs_create_link(POHMELFS_I(dir), &str, pi, NULL); -	if (err) -		return err; - -	return pohmelfs_create_entry(dir, dentry, pi->ino, inode->i_mode); -} - -static int pohmelfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) -{ -	struct qstr sym_str; -	struct qstr str = dentry->d_name; -	struct inode *inode; -	int err; - -	str.hash = jhash(dentry->d_name.name, dentry->d_name.len, 0); - -	sym_str.name = symname; -	sym_str.len = strlen(symname); - -	err = pohmelfs_create_link(POHMELFS_I(dir), &str, NULL, &sym_str); -	if (err) -		goto err_out_exit; - -	err = pohmelfs_create_entry(dir, dentry, 0, S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO); -	if (err) -		goto err_out_exit; - -	inode = dentry->d_inode; - -	err = page_symlink(inode, symname, sym_str.len + 1); -	if (err) -		goto err_out_put; - -	return 0; - -err_out_put: -	iput(inode); -err_out_exit: -	return err; -} - -static int pohmelfs_send_rename(struct pohmelfs_inode *pi, struct pohmelfs_inode *parent, -		struct qstr *str) -{ -	int path_len, err, total_len = 0, inode_len, parent_len; -	char *path; -	struct netfs_trans *t; -	struct netfs_cmd *cmd; -	struct pohmelfs_sb *psb = POHMELFS_SB(pi->vfs_inode.i_sb); - -	parent_len = pohmelfs_path_length(parent); -	inode_len = pohmelfs_path_length(pi); - -	if (parent_len < 0 || inode_len < 0) -		return -EINVAL; - -	path_len = parent_len + inode_len + str->len + 3; - -	t = netfs_trans_alloc(psb, path_len, 0, 0); -	if (!t) -		return -ENOMEM; - -	cmd = netfs_trans_current(t); -	path = (char *)(cmd + 1); - -	err = pohmelfs_construct_path_string(pi, path, inode_len); -	if (err < 0) -		goto err_out_unlock; - -	cmd->ext = err; - -	path += err; -	total_len += err; -	path_len -= err; - -	*path = '|'; -	path++; -	total_len++; -	path_len--; - -	err = pohmelfs_construct_path_string(parent, path, parent_len); -	if (err < 0) -		goto err_out_unlock; - -	/* -	 * Do not place a null-byte before the final slash and the name. -	 */ -	err--; -	path += err; -	total_len += err; -	path_len -= err; - -	err = snprintf(path, path_len - 1, "/%s", str->name); - -	total_len += err + 1; /* 0 symbol */ -	path_len -= err + 1; - -	cmd->cmd = NETFS_RENAME; -	cmd->id = pi->ino; -	cmd->start = parent->ino; -	cmd->size = total_len; - -	netfs_convert_cmd(cmd); - -	netfs_trans_update(cmd, t, total_len); - -	return netfs_trans_finish(t, psb); - -err_out_unlock: -	netfs_trans_free(t); -	return err; -} - -static int pohmelfs_rename(struct inode *old_dir, struct dentry *old_dentry, -			struct inode *new_dir, struct dentry *new_dentry) -{ -	struct inode *inode = old_dentry->d_inode; -	struct pohmelfs_inode *old_parent, *pi, *new_parent; -	struct qstr str = new_dentry->d_name; -	struct pohmelfs_name *n; -	unsigned int old_hash; -	int err = -ENOENT; - -	pi = POHMELFS_I(inode); -	old_parent = POHMELFS_I(old_dir); - -	if (new_dir) -		new_dir->i_sb->s_op->write_inode(new_dir, 0); - -	old_hash = jhash(old_dentry->d_name.name, old_dentry->d_name.len, 0); -	str.hash = jhash(new_dentry->d_name.name, new_dentry->d_name.len, 0); - -	str.len = new_dentry->d_name.len; -	str.name = new_dentry->d_name.name; -	str.hash = jhash(new_dentry->d_name.name, new_dentry->d_name.len, 0); - -	if (new_dir) { -		new_parent = POHMELFS_I(new_dir); -		err = -ENOTEMPTY; - -		if (S_ISDIR(inode->i_mode) && -				new_parent->total_len <= 3) -			goto err_out_exit; -	} else { -		new_parent = old_parent; -	} - -	dprintk("%s: ino: %llu, parent: %llu, name: '%s' -> parent: %llu, name: '%s', i_size: %llu.\n", -			__func__, pi->ino, old_parent->ino, old_dentry->d_name.name, -			new_parent->ino, new_dentry->d_name.name, inode->i_size); - -	if (test_bit(NETFS_INODE_REMOTE_SYNCED, &pi->state) && -			test_bit(NETFS_INODE_OWNED, &pi->state)) { -		err = pohmelfs_send_rename(pi, new_parent, &str); -		if (err) -			goto err_out_exit; -	} - -	n = pohmelfs_name_alloc(str.len + 1); -	if (!n) -		goto err_out_exit; - -	mutex_lock(&new_parent->offset_lock); -	n->ino = pi->ino; -	n->mode = inode->i_mode; -	n->len = str.len; -	n->hash = str.hash; -	sprintf(n->data, "%s", str.name); - -	err = pohmelfs_insert_name(new_parent, n); -	mutex_unlock(&new_parent->offset_lock); - -	if (err) -		goto err_out_exit; - -	mutex_lock(&old_parent->offset_lock); -	n = pohmelfs_search_hash(old_parent, old_hash); -	if (n) -		pohmelfs_name_del(old_parent, n); -	mutex_unlock(&old_parent->offset_lock); - -	mark_inode_dirty(inode); -	mark_inode_dirty(&new_parent->vfs_inode); - -	WARN_ON_ONCE(list_empty(&inode->i_dentry)); - -	return 0; - -err_out_exit: - -	clear_bit(NETFS_INODE_REMOTE_SYNCED, &pi->state); - -	return err; -} - -/* - * POHMELFS directory inode operations. - */ -const struct inode_operations pohmelfs_dir_inode_ops = { -	.link		= pohmelfs_link, -	.symlink	= pohmelfs_symlink, -	.unlink		= pohmelfs_unlink, -	.mkdir		= pohmelfs_mkdir, -	.rmdir		= pohmelfs_rmdir, -	.create		= pohmelfs_create, -	.lookup 	= pohmelfs_lookup, -	.setattr	= pohmelfs_setattr, -	.rename		= pohmelfs_rename, -}; diff --git a/drivers/staging/pohmelfs/inode.c b/drivers/staging/pohmelfs/inode.c deleted file mode 100644 index 807e3f32411..00000000000 --- a/drivers/staging/pohmelfs/inode.c +++ /dev/null @@ -1,2055 +0,0 @@ -/* - * 2007+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net> - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU General Public License for more details. - */ - -#include <linux/module.h> -#include <linux/backing-dev.h> -#include <linux/crypto.h> -#include <linux/fs.h> -#include <linux/jhash.h> -#include <linux/hash.h> -#include <linux/ktime.h> -#include <linux/mm.h> -#include <linux/mount.h> -#include <linux/pagemap.h> -#include <linux/pagevec.h> -#include <linux/parser.h> -#include <linux/swap.h> -#include <linux/slab.h> -#include <linux/statfs.h> -#include <linux/writeback.h> -#include <linux/prefetch.h> - -#include "netfs.h" - -#define POHMELFS_MAGIC_NUM	0x504f482e - -static struct kmem_cache *pohmelfs_inode_cache; -static atomic_t psb_bdi_num = ATOMIC_INIT(0); - -/* - * Removes inode from all trees, drops local name cache and removes all queued - * requests for object removal. - */ -void pohmelfs_inode_del_inode(struct pohmelfs_sb *psb, struct pohmelfs_inode *pi) -{ -	mutex_lock(&pi->offset_lock); -	pohmelfs_free_names(pi); -	mutex_unlock(&pi->offset_lock); - -	dprintk("%s: deleted stuff in ino: %llu.\n", __func__, pi->ino); -} - -/* - * Sync inode to server. - * Returns zero in success and negative error value otherwise. - * It will gather path to root directory into structures containing - * creation mode, permissions and names, so that the whole path - * to given inode could be created using only single network command. - */ -int pohmelfs_write_inode_create(struct inode *inode, struct netfs_trans *trans) -{ -	struct pohmelfs_inode *pi = POHMELFS_I(inode); -	int err = -ENOMEM, size; -	struct netfs_cmd *cmd; -	void *data; -	int cur_len = netfs_trans_cur_len(trans); - -	if (unlikely(cur_len < 0)) -		return -ETOOSMALL; - -	cmd = netfs_trans_current(trans); -	cur_len -= sizeof(struct netfs_cmd); - -	data = (void *)(cmd + 1); - -	err = pohmelfs_construct_path_string(pi, data, cur_len); -	if (err < 0) -		goto err_out_exit; - -	size = err; - -	cmd->start = i_size_read(inode); -	cmd->cmd = NETFS_CREATE; -	cmd->size = size; -	cmd->id = pi->ino; -	cmd->ext = inode->i_mode; - -	netfs_convert_cmd(cmd); - -	netfs_trans_update(cmd, trans, size); - -	return 0; - -err_out_exit: -	printk("%s: completed ino: %llu, err: %d.\n", __func__, pi->ino, err); -	return err; -} - -static int pohmelfs_write_trans_complete(struct page **pages, unsigned int page_num, -		void *private, int err) -{ -	unsigned i; - -	dprintk("%s: pages: %lu-%lu, page_num: %u, err: %d.\n", -			__func__, pages[0]->index, pages[page_num-1]->index, -			page_num, err); - -	for (i = 0; i < page_num; i++) { -		struct page *page = pages[i]; - -		if (!page) -			continue; - -		end_page_writeback(page); - -		if (err < 0) { -			SetPageError(page); -			set_page_dirty(page); -		} - -		unlock_page(page); -		page_cache_release(page); - -		/* dprintk("%s: %3u/%u: page: %p.\n", __func__, i, page_num, page); */ -	} -	return err; -} - -static int pohmelfs_inode_has_dirty_pages(struct address_space *mapping, pgoff_t index) -{ -	int ret; -	struct page *page; - -	rcu_read_lock(); -	ret = radix_tree_gang_lookup_tag(&mapping->page_tree, -				(void **)&page, index, 1, PAGECACHE_TAG_DIRTY); -	rcu_read_unlock(); -	return ret; -} - -static int pohmelfs_writepages(struct address_space *mapping, struct writeback_control *wbc) -{ -	struct inode *inode = mapping->host; -	struct pohmelfs_inode *pi = POHMELFS_I(inode); -	struct pohmelfs_sb *psb = POHMELFS_SB(inode->i_sb); -	int err = 0; -	int done = 0; -	int nr_pages; -	pgoff_t index; -	pgoff_t end;		/* Inclusive */ -	int scanned = 0; -	int range_whole = 0; - -	if (wbc->range_cyclic) { -		index = mapping->writeback_index; /* Start from prev offset */ -		end = -1; -	} else { -		index = wbc->range_start >> PAGE_CACHE_SHIFT; -		end = wbc->range_end >> PAGE_CACHE_SHIFT; -		if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX) -			range_whole = 1; -		scanned = 1; -	} -retry: -	while (!done && (index <= end)) { -		unsigned int i = min(end - index, (pgoff_t)psb->trans_max_pages); -		int path_len; -		struct netfs_trans *trans; - -		err = pohmelfs_inode_has_dirty_pages(mapping, index); -		if (!err) -			break; - -		err = pohmelfs_path_length(pi); -		if (err < 0) -			break; - -		path_len = err; - -		if (path_len <= 2) { -			err = -ENOENT; -			break; -		} - -		trans = netfs_trans_alloc(psb, path_len, 0, i); -		if (!trans) { -			err = -ENOMEM; -			break; -		} -		trans->complete = &pohmelfs_write_trans_complete; - -		trans->page_num = nr_pages = find_get_pages_tag(mapping, &index, -				PAGECACHE_TAG_DIRTY, trans->page_num, -				trans->pages); - -		dprintk("%s: t: %p, nr_pages: %u, end: %lu, index: %lu, max: %u.\n", -				__func__, trans, nr_pages, end, index, trans->page_num); - -		if (!nr_pages) -			goto err_out_reset; - -		err = pohmelfs_write_inode_create(inode, trans); -		if (err) -			goto err_out_reset; - -		err = 0; -		scanned = 1; - -		for (i = 0; i < trans->page_num; i++) { -			struct page *page = trans->pages[i]; - -			lock_page(page); - -			if (unlikely(page->mapping != mapping)) -				goto out_continue; - -			if (!wbc->range_cyclic && page->index > end) { -				done = 1; -				goto out_continue; -			} - -			if (wbc->sync_mode != WB_SYNC_NONE) -				wait_on_page_writeback(page); - -			if (PageWriteback(page) || -			    !clear_page_dirty_for_io(page)) { -				dprintk("%s: not clear for io page: %p, writeback: %d.\n", -						__func__, page, PageWriteback(page)); -				goto out_continue; -			} - -			set_page_writeback(page); - -			trans->attached_size += page_private(page); -			trans->attached_pages++; -#if 0 -			dprintk("%s: %u/%u added trans: %p, gen: %u, page: %p, [High: %d], size: %lu, idx: %lu.\n", -					__func__, i, trans->page_num, trans, trans->gen, page, -					!!PageHighMem(page), page_private(page), page->index); -#endif -			wbc->nr_to_write--; - -			if (wbc->nr_to_write <= 0) -				done = 1; - -			continue; -out_continue: -			unlock_page(page); -			trans->pages[i] = NULL; -		} - -		err = netfs_trans_finish(trans, psb); -		if (err) -			break; - -		continue; - -err_out_reset: -		trans->result = err; -		netfs_trans_reset(trans); -		netfs_trans_put(trans); -		break; -	} - -	if (!scanned && !done) { -		/* -		 * We hit the last page and there is more work to be done: wrap -		 * back to the start of the file -		 */ -		scanned = 1; -		index = 0; -		goto retry; -	} - -	if (wbc->range_cyclic || (range_whole && wbc->nr_to_write > 0)) -		mapping->writeback_index = index; - -	return err; -} - -/* - * Inode writeback creation completion callback. - * Only invoked for just created inodes, which do not have pages attached, - * like dirs and empty files. - */ -static int pohmelfs_write_inode_complete(struct page **pages, unsigned int page_num, -		void *private, int err) -{ -	struct inode *inode = private; -	struct pohmelfs_inode *pi = POHMELFS_I(inode); - -	if (inode) { -		if (err) { -			mark_inode_dirty(inode); -			clear_bit(NETFS_INODE_REMOTE_SYNCED, &pi->state); -		} else { -			set_bit(NETFS_INODE_REMOTE_SYNCED, &pi->state); -		} - -		pohmelfs_put_inode(pi); -	} - -	return err; -} - -int pohmelfs_write_create_inode(struct pohmelfs_inode *pi) -{ -	struct netfs_trans *t; -	struct inode *inode = &pi->vfs_inode; -	struct pohmelfs_sb *psb = POHMELFS_SB(inode->i_sb); -	int err; - -	if (test_bit(NETFS_INODE_REMOTE_SYNCED, &pi->state)) -		return 0; - -	dprintk("%s: started ino: %llu.\n", __func__, pi->ino); - -	err = pohmelfs_path_length(pi); -	if (err < 0) -		goto err_out_exit; - -	t = netfs_trans_alloc(psb, err + 1, 0, 0); -	if (!t) { -		err = -ENOMEM; -		goto err_out_exit; -	} -	t->complete = pohmelfs_write_inode_complete; -	t->private = igrab(inode); -	if (!t->private) { -		err = -ENOENT; -		goto err_out_put; -	} - -	err = pohmelfs_write_inode_create(inode, t); -	if (err) -		goto err_out_put; - -	netfs_trans_finish(t, POHMELFS_SB(inode->i_sb)); - -	return 0; - -err_out_put: -	t->result = err; -	netfs_trans_put(t); -err_out_exit: -	return err; -} - -/* - * Sync all not-yet-created children in given directory to the server. - */ -static int pohmelfs_write_inode_create_children(struct inode *inode) -{ -	struct pohmelfs_inode *parent = POHMELFS_I(inode); -	struct super_block *sb = inode->i_sb; -	struct pohmelfs_name *n; - -	while (!list_empty(&parent->sync_create_list)) { -		n = NULL; -		mutex_lock(&parent->offset_lock); -		if (!list_empty(&parent->sync_create_list)) { -			n = list_first_entry(&parent->sync_create_list, -				struct pohmelfs_name, sync_create_entry); -			list_del_init(&n->sync_create_entry); -		} -		mutex_unlock(&parent->offset_lock); - -		if (!n) -			break; - -		inode = ilookup(sb, n->ino); - -		dprintk("%s: parent: %llu, ino: %llu, inode: %p.\n", -				__func__, parent->ino, n->ino, inode); - -		if (inode && (inode->i_state & I_DIRTY)) { -			struct pohmelfs_inode *pi = POHMELFS_I(inode); -			pohmelfs_write_create_inode(pi); -			/* pohmelfs_meta_command(pi, NETFS_INODE_INFO, 0, NULL, NULL, 0); */ -			iput(inode); -		} -	} - -	return 0; -} - -/* - * Removes given child from given inode on server. - */ -int pohmelfs_remove_child(struct pohmelfs_inode *pi, struct pohmelfs_name *n) -{ -	return pohmelfs_meta_command_data(pi, pi->ino, NETFS_REMOVE, NULL, 0, NULL, NULL, 0); -} - -/* - * Writeback for given inode. - */ -static int pohmelfs_write_inode(struct inode *inode, -				struct writeback_control *wbc) -{ -	struct pohmelfs_inode *pi = POHMELFS_I(inode); - -	pohmelfs_write_create_inode(pi); -	pohmelfs_write_inode_create_children(inode); - -	return 0; -} - -/* - * It is not exported, sorry... - */ -static inline wait_queue_head_t *page_waitqueue(struct page *page) -{ -	const struct zone *zone = page_zone(page); - -	return &zone->wait_table[hash_ptr(page, zone->wait_table_bits)]; -} - -static int pohmelfs_wait_on_page_locked(struct page *page) -{ -	struct pohmelfs_sb *psb = POHMELFS_SB(page->mapping->host->i_sb); -	long ret = psb->wait_on_page_timeout; -	DEFINE_WAIT_BIT(wait, &page->flags, PG_locked); -	int err = 0; - -	if (!PageLocked(page)) -		return 0; - -	for (;;) { -		prepare_to_wait(page_waitqueue(page), -				&wait.wait, TASK_INTERRUPTIBLE); - -		dprintk("%s: page: %p, locked: %d, uptodate: %d, error: %d, flags: %lx.\n", -				__func__, page, PageLocked(page), PageUptodate(page), -				PageError(page), page->flags); - -		if (!PageLocked(page)) -			break; - -		if (!signal_pending(current)) { -			ret = schedule_timeout(ret); -			if (!ret) -				break; -			continue; -		} -		ret = -ERESTARTSYS; -		break; -	} -	finish_wait(page_waitqueue(page), &wait.wait); - -	if (!ret) -		err = -ETIMEDOUT; - - -	if (!err) -		SetPageUptodate(page); - -	if (err) -		printk("%s: page: %p, uptodate: %d, locked: %d, err: %d.\n", -			__func__, page, PageUptodate(page), PageLocked(page), err); - -	return err; -} - -static int pohmelfs_read_page_complete(struct page **pages, unsigned int page_num, -		void *private, int err) -{ -	struct page *page = private; - -	if (PageChecked(page)) -		return err; - -	if (err < 0) { -		dprintk("%s: page: %p, err: %d.\n", __func__, page, err); -		SetPageError(page); -	} - -	unlock_page(page); - -	return err; -} - -/* - * Read a page from remote server. - * Function will wait until page is unlocked. - */ -static int pohmelfs_readpage(struct file *file, struct page *page) -{ -	struct inode *inode = page->mapping->host; -	struct pohmelfs_sb *psb = POHMELFS_SB(inode->i_sb); -	struct pohmelfs_inode *pi = POHMELFS_I(inode); -	struct netfs_trans *t; -	struct netfs_cmd *cmd; -	int err, path_len; -	void *data; -	u64 isize; - -	err = pohmelfs_data_lock(pi, page->index << PAGE_CACHE_SHIFT, -			PAGE_SIZE, POHMELFS_READ_LOCK); -	if (err) -		goto err_out_exit; - -	isize = i_size_read(inode); -	if (isize <= page->index << PAGE_CACHE_SHIFT) { -		SetPageUptodate(page); -		unlock_page(page); -		return 0; -	} - -	path_len = pohmelfs_path_length(pi); -	if (path_len < 0) { -		err = path_len; -		goto err_out_exit; -	} - -	t = netfs_trans_alloc(psb, path_len, NETFS_TRANS_SINGLE_DST, 0); -	if (!t) { -		err = -ENOMEM; -		goto err_out_exit; -	} - -	t->complete = pohmelfs_read_page_complete; -	t->private = page; - -	cmd = netfs_trans_current(t); -	data = (void *)(cmd + 1); - -	err = pohmelfs_construct_path_string(pi, data, path_len); -	if (err < 0) -		goto err_out_free; - -	path_len = err; - -	cmd->id = pi->ino; -	cmd->start = page->index; -	cmd->start <<= PAGE_CACHE_SHIFT; -	cmd->size = PAGE_CACHE_SIZE + path_len; -	cmd->cmd = NETFS_READ_PAGE; -	cmd->ext = path_len; - -	dprintk("%s: path: '%s', page: %p, ino: %llu, start: %llu, size: %lu.\n", -			__func__, (char *)data, page, pi->ino, cmd->start, PAGE_CACHE_SIZE); - -	netfs_convert_cmd(cmd); -	netfs_trans_update(cmd, t, path_len); - -	err = netfs_trans_finish(t, psb); -	if (err) -		goto err_out_return; - -	return pohmelfs_wait_on_page_locked(page); - -err_out_free: -	t->result = err; -	netfs_trans_put(t); -err_out_exit: -	SetPageError(page); -	if (PageLocked(page)) -		unlock_page(page); -err_out_return: -	printk("%s: page: %p, start: %lu, size: %lu, err: %d.\n", -		__func__, page, page->index << PAGE_CACHE_SHIFT, PAGE_CACHE_SIZE, err); - -	return err; -} - -/* - * Write begin/end magic. - * Allocates a page and writes inode if it was not synced to server before. - */ -static int pohmelfs_write_begin(struct file *file, struct address_space *mapping, -		loff_t pos, unsigned len, unsigned flags, -		struct page **pagep, void **fsdata) -{ -	struct inode *inode = mapping->host; -	struct page *page; -	pgoff_t index; -	unsigned start, end; -	int err; - -	*pagep = NULL; - -	index = pos >> PAGE_CACHE_SHIFT; -	start = pos & (PAGE_CACHE_SIZE - 1); -	end = start + len; - -	page = grab_cache_page(mapping, index); -#if 0 -	dprintk("%s: page: %p pos: %llu, len: %u, index: %lu, start: %u, end: %u, uptodate: %d.\n", -			__func__, page,	pos, len, index, start, end, PageUptodate(page)); -#endif -	if (!page) { -		err = -ENOMEM; -		goto err_out_exit; -	} - -	while (!PageUptodate(page)) { -		if (start && test_bit(NETFS_INODE_REMOTE_SYNCED, &POHMELFS_I(inode)->state)) { -			err = pohmelfs_readpage(file, page); -			if (err) -				goto err_out_exit; - -			lock_page(page); -			continue; -		} - -		if (len != PAGE_CACHE_SIZE) { -			void *kaddr = kmap_atomic(page, KM_USER0); - -			memset(kaddr + start, 0, PAGE_CACHE_SIZE - start); -			flush_dcache_page(page); -			kunmap_atomic(kaddr, KM_USER0); -		} -		SetPageUptodate(page); -	} - -	set_page_private(page, end); - -	*pagep = page; - -	return 0; - -err_out_exit: -	page_cache_release(page); -	*pagep = NULL; - -	return err; -} - -static int pohmelfs_write_end(struct file *file, struct address_space *mapping, -			loff_t pos, unsigned len, unsigned copied, -			struct page *page, void *fsdata) -{ -	struct inode *inode = mapping->host; - -	if (copied != len) { -		unsigned from = pos & (PAGE_CACHE_SIZE - 1); -		void *kaddr = kmap_atomic(page, KM_USER0); - -		memset(kaddr + from + copied, 0, len - copied); -		flush_dcache_page(page); -		kunmap_atomic(kaddr, KM_USER0); -	} - -	SetPageUptodate(page); -	set_page_dirty(page); -#if 0 -	dprintk("%s: page: %p [U: %d, D: %d, L: %d], pos: %llu, len: %u, copied: %u.\n", -			__func__, page, -			PageUptodate(page), PageDirty(page), PageLocked(page), -			pos, len, copied); -#endif -	flush_dcache_page(page); - -	unlock_page(page); -	page_cache_release(page); - -	if (pos + copied > inode->i_size) { -		struct pohmelfs_sb *psb = POHMELFS_SB(inode->i_sb); - -		psb->avail_size -= pos + copied - inode->i_size; - -		i_size_write(inode, pos + copied); -	} - -	return copied; -} - -static int pohmelfs_readpages_trans_complete(struct page **__pages, unsigned int page_num, -		void *private, int err) -{ -	struct pohmelfs_inode *pi = private; -	unsigned int i, num; -	struct page **pages, *page = (struct page *)__pages; -	loff_t index = page->index; - -	pages = kzalloc(sizeof(void *) * page_num, GFP_NOIO); -	if (!pages) -		return -ENOMEM; - -	num = find_get_pages_contig(pi->vfs_inode.i_mapping, index, page_num, pages); -	if (num <= 0) { -		err = num; -		goto err_out_free; -	} - -	for (i = 0; i < num; ++i) { -		page = pages[i]; - -		if (err) -			printk("%s: %u/%u: page: %p, index: %lu, uptodate: %d, locked: %d, err: %d.\n", -				__func__, i, num, page, page->index, -				PageUptodate(page), PageLocked(page), err); - -		if (!PageChecked(page)) { -			if (err < 0) -				SetPageError(page); -			unlock_page(page); -		} -		page_cache_release(page); -		page_cache_release(page); -	} - -err_out_free: -	kfree(pages); -	return err; -} - -static int pohmelfs_send_readpages(struct pohmelfs_inode *pi, struct page *first, unsigned int num) -{ -	struct netfs_trans *t; -	struct netfs_cmd *cmd; -	struct pohmelfs_sb *psb = POHMELFS_SB(pi->vfs_inode.i_sb); -	int err, path_len; -	void *data; - -	err = pohmelfs_data_lock(pi, first->index << PAGE_CACHE_SHIFT, -			num * PAGE_SIZE, POHMELFS_READ_LOCK); -	if (err) -		goto err_out_exit; - -	path_len = pohmelfs_path_length(pi); -	if (path_len < 0) { -		err = path_len; -		goto err_out_exit; -	} - -	t = netfs_trans_alloc(psb, path_len, NETFS_TRANS_SINGLE_DST, 0); -	if (!t) { -		err = -ENOMEM; -		goto err_out_exit; -	} - -	cmd = netfs_trans_current(t); -	data = (void *)(cmd + 1); - -	t->complete = pohmelfs_readpages_trans_complete; -	t->private = pi; -	t->page_num = num; -	t->pages = (struct page **)first; - -	err = pohmelfs_construct_path_string(pi, data, path_len); -	if (err < 0) -		goto err_out_put; - -	path_len = err; - -	cmd->cmd = NETFS_READ_PAGES; -	cmd->start = first->index; -	cmd->start <<= PAGE_CACHE_SHIFT; -	cmd->size = (num << 8 | PAGE_CACHE_SHIFT); -	cmd->id = pi->ino; -	cmd->ext = path_len; - -	dprintk("%s: t: %p, gen: %u, path: '%s', path_len: %u, " -			"start: %lu, num: %u.\n", -			__func__, t, t->gen, (char *)data, path_len, -			first->index, num); - -	netfs_convert_cmd(cmd); -	netfs_trans_update(cmd, t, path_len); - -	return netfs_trans_finish(t, psb); - -err_out_put: -	netfs_trans_free(t); -err_out_exit: -	pohmelfs_readpages_trans_complete((struct page **)first, num, pi, err); -	return err; -} - -#define list_to_page(head) (list_entry((head)->prev, struct page, lru)) - -static int pohmelfs_readpages(struct file *file, struct address_space *mapping, -			struct list_head *pages, unsigned nr_pages) -{ -	unsigned int page_idx, num = 0; -	struct page *page = NULL, *first = NULL; - -	for (page_idx = 0; page_idx < nr_pages; page_idx++) { -		page = list_to_page(pages); - -		prefetchw(&page->flags); -		list_del(&page->lru); - -		if (!add_to_page_cache_lru(page, mapping, -					page->index, GFP_KERNEL)) { - -			if (!num) { -				num = 1; -				first = page; -				continue; -			} - -			dprintk("%s: added to lru page: %p, page_index: %lu, first_index: %lu.\n", -					__func__, page, page->index, first->index); - -			if (unlikely(first->index + num != page->index) || (num > 500)) { -				pohmelfs_send_readpages(POHMELFS_I(mapping->host), -						first, num); -				first = page; -				num = 0; -			} - -			num++; -		} -	} -	pohmelfs_send_readpages(POHMELFS_I(mapping->host), first, num); - -	/* -	 * This will be sync read, so when last page is processed, -	 * all previous are alerady unlocked and ready to be used. -	 */ -	return 0; -} - -/* - * Small address space operations for POHMELFS. - */ -const struct address_space_operations pohmelfs_aops = { -	.readpage		= pohmelfs_readpage, -	.readpages		= pohmelfs_readpages, -	.writepages		= pohmelfs_writepages, -	.write_begin		= pohmelfs_write_begin, -	.write_end		= pohmelfs_write_end, -	.set_page_dirty 	= __set_page_dirty_nobuffers, -}; - -static void pohmelfs_i_callback(struct rcu_head *head) -{ -	struct inode *inode = container_of(head, struct inode, i_rcu); -	kmem_cache_free(pohmelfs_inode_cache, POHMELFS_I(inode)); -} - -/* - * ->destroy_inode() callback. Deletes inode from the caches - *  and frees private data. - */ -static void pohmelfs_destroy_inode(struct inode *inode) -{ -	struct super_block *sb = inode->i_sb; -	struct pohmelfs_sb *psb = POHMELFS_SB(sb); -	struct pohmelfs_inode *pi = POHMELFS_I(inode); - -	/* pohmelfs_data_unlock(pi, 0, inode->i_size, POHMELFS_READ_LOCK); */ - -	pohmelfs_inode_del_inode(psb, pi); - -	dprintk("%s: pi: %p, inode: %p, ino: %llu.\n", -		__func__, pi, &pi->vfs_inode, pi->ino); -	atomic_long_dec(&psb->total_inodes); -	call_rcu(&inode->i_rcu, pohmelfs_i_callback); -} - -/* - * ->alloc_inode() callback. Allocates inode and initializes private data. - */ -static struct inode *pohmelfs_alloc_inode(struct super_block *sb) -{ -	struct pohmelfs_inode *pi; - -	pi = kmem_cache_alloc(pohmelfs_inode_cache, GFP_NOIO); -	if (!pi) -		return NULL; - -	pi->hash_root = RB_ROOT; -	mutex_init(&pi->offset_lock); - -	INIT_LIST_HEAD(&pi->sync_create_list); - -	INIT_LIST_HEAD(&pi->inode_entry); - -	pi->lock_type = 0; -	pi->state = 0; -	pi->total_len = 0; -	pi->drop_count = 0; - -	dprintk("%s: pi: %p, inode: %p.\n", __func__, pi, &pi->vfs_inode); - -	atomic_long_inc(&POHMELFS_SB(sb)->total_inodes); - -	return &pi->vfs_inode; -} - -/* - * We want fsync() to work on POHMELFS. - */ -static int pohmelfs_fsync(struct file *file, loff_t start, loff_t end, int datasync) -{ -	struct inode *inode = file->f_mapping->host; -	int err = filemap_write_and_wait_range(inode->i_mapping, start, end); -	if (!err) { -		mutex_lock(&inode->i_mutex); -		err = sync_inode_metadata(inode, 1); -		mutex_unlock(&inode->i_mutex); -	} -	return err; -} - -ssize_t pohmelfs_write(struct file *file, const char __user *buf, -		size_t len, loff_t *ppos) -{ -	struct address_space *mapping = file->f_mapping; -	struct inode *inode = mapping->host; -	struct pohmelfs_inode *pi = POHMELFS_I(inode); -	struct iovec iov = { .iov_base = (void __user *)buf, .iov_len = len }; -	struct kiocb kiocb; -	ssize_t ret; -	loff_t pos = *ppos; - -	init_sync_kiocb(&kiocb, file); -	kiocb.ki_pos = pos; -	kiocb.ki_left = len; - -	dprintk("%s: len: %zu, pos: %llu.\n", __func__, len, pos); - -	mutex_lock(&inode->i_mutex); -	ret = pohmelfs_data_lock(pi, pos, len, POHMELFS_WRITE_LOCK); -	if (ret) -		goto err_out_unlock; - -	ret = __generic_file_aio_write(&kiocb, &iov, 1, &kiocb.ki_pos); -	*ppos = kiocb.ki_pos; - -	mutex_unlock(&inode->i_mutex); -	WARN_ON(ret < 0); - -	if (ret > 0) { -		ssize_t err; - -		err = generic_write_sync(file, pos, ret); -		if (err < 0) -			ret = err; -		WARN_ON(ret < 0); -	} - -	return ret; - -err_out_unlock: -	mutex_unlock(&inode->i_mutex); -	return ret; -} - -static const struct file_operations pohmelfs_file_ops = { -	.open		= generic_file_open, -	.fsync		= pohmelfs_fsync, - -	.llseek		= generic_file_llseek, - -	.read		= do_sync_read, -	.aio_read	= generic_file_aio_read, - -	.mmap		= generic_file_mmap, - -	.splice_read	= generic_file_splice_read, -	.splice_write	= generic_file_splice_write, - -	.write		= pohmelfs_write, -	.aio_write	= generic_file_aio_write, -}; - -const struct inode_operations pohmelfs_symlink_inode_operations = { -	.readlink	= generic_readlink, -	.follow_link	= page_follow_link_light, -	.put_link	= page_put_link, -}; - -int pohmelfs_setattr_raw(struct inode *inode, struct iattr *attr) -{ -	int err; - -	err = inode_change_ok(inode, attr); -	if (err) { -		dprintk("%s: ino: %llu, inode changes are not allowed.\n", __func__, POHMELFS_I(inode)->ino); -		goto err_out_exit; -	} - -	if ((attr->ia_valid & ATTR_SIZE) && -	    attr->ia_size != i_size_read(inode)) { -		err = vmtruncate(inode, attr->ia_size); -		if (err) { -			dprintk("%s: ino: %llu, failed to set the attributes.\n", __func__, POHMELFS_I(inode)->ino); -			goto err_out_exit; -		} -	} - -	setattr_copy(inode, attr); -	mark_inode_dirty(inode); - -	dprintk("%s: ino: %llu, mode: %o -> %o, uid: %u -> %u, gid: %u -> %u, size: %llu -> %llu.\n", -			__func__, POHMELFS_I(inode)->ino, inode->i_mode, attr->ia_mode, -			inode->i_uid, attr->ia_uid, inode->i_gid, attr->ia_gid, inode->i_size, attr->ia_size); - -	return 0; - -err_out_exit: -	return err; -} - -int pohmelfs_setattr(struct dentry *dentry, struct iattr *attr) -{ -	struct inode *inode = dentry->d_inode; -	struct pohmelfs_inode *pi = POHMELFS_I(inode); -	int err; - -	err = pohmelfs_data_lock(pi, 0, ~0, POHMELFS_WRITE_LOCK); -	if (err) -		goto err_out_exit; - -	err = security_inode_setattr(dentry, attr); -	if (err) -		goto err_out_exit; - -	err = pohmelfs_setattr_raw(inode, attr); -	if (err) -		goto err_out_exit; - -	return 0; - -err_out_exit: -	return err; -} - -static int pohmelfs_send_xattr_req(struct pohmelfs_inode *pi, u64 id, u64 start, -		const char *name, const void *value, size_t attrsize, int command) -{ -	struct pohmelfs_sb *psb = POHMELFS_SB(pi->vfs_inode.i_sb); -	int err, path_len, namelen = strlen(name) + 1; /* 0-byte */ -	struct netfs_trans *t; -	struct netfs_cmd *cmd; -	void *data; - -	dprintk("%s: id: %llu, start: %llu, name: '%s', attrsize: %zu, cmd: %d.\n", -			__func__, id, start, name, attrsize, command); - -	path_len = pohmelfs_path_length(pi); -	if (path_len < 0) { -		err = path_len; -		goto err_out_exit; -	} - -	t = netfs_trans_alloc(psb, namelen + path_len + attrsize, 0, 0); -	if (!t) { -		err = -ENOMEM; -		goto err_out_exit; -	} - -	cmd = netfs_trans_current(t); -	data = cmd + 1; - -	path_len = pohmelfs_construct_path_string(pi, data, path_len); -	if (path_len < 0) { -		err = path_len; -		goto err_out_put; -	} -	data += path_len; - -	/* -	 * 'name' is a NUL-terminated string already and -	 * 'namelen' includes 0-byte. -	 */ -	memcpy(data, name, namelen); -	data += namelen; - -	memcpy(data, value, attrsize); - -	cmd->cmd = command; -	cmd->id = id; -	cmd->start = start; -	cmd->size = attrsize + namelen + path_len; -	cmd->ext = path_len; -	cmd->csize = 0; -	cmd->cpad = 0; - -	netfs_convert_cmd(cmd); -	netfs_trans_update(cmd, t, namelen + path_len + attrsize); - -	return netfs_trans_finish(t, psb); - -err_out_put: -	t->result = err; -	netfs_trans_put(t); -err_out_exit: -	return err; -} - -static int pohmelfs_setxattr(struct dentry *dentry, const char *name, -		const void *value, size_t attrsize, int flags) -{ -	struct inode *inode = dentry->d_inode; -	struct pohmelfs_inode *pi = POHMELFS_I(inode); -	struct pohmelfs_sb *psb = POHMELFS_SB(inode->i_sb); - -	if (!(psb->state_flags & POHMELFS_FLAGS_XATTR)) -		return -EOPNOTSUPP; - -	return pohmelfs_send_xattr_req(pi, flags, attrsize, name, -			value, attrsize, NETFS_XATTR_SET); -} - -static ssize_t pohmelfs_getxattr(struct dentry *dentry, const char *name, -		void *value, size_t attrsize) -{ -	struct inode *inode = dentry->d_inode; -	struct pohmelfs_inode *pi = POHMELFS_I(inode); -	struct pohmelfs_sb *psb = POHMELFS_SB(inode->i_sb); -	struct pohmelfs_mcache *m; -	int err; -	long timeout = psb->mcache_timeout; - -	if (!(psb->state_flags & POHMELFS_FLAGS_XATTR)) -		return -EOPNOTSUPP; - -	m = pohmelfs_mcache_alloc(psb, 0, attrsize, value); -	if (IS_ERR(m)) -		return PTR_ERR(m); - -	dprintk("%s: ino: %llu, name: '%s', size: %zu.\n", -			__func__, pi->ino, name, attrsize); - -	err = pohmelfs_send_xattr_req(pi, m->gen, attrsize, name, value, 0, NETFS_XATTR_GET); -	if (err) -		goto err_out_put; - -	do { -		err = wait_for_completion_timeout(&m->complete, timeout); -		if (err) { -			err = m->err; -			break; -		} - -		/* -		 * This loop is a bit ugly, since it waits until reference counter -		 * hits 1 and then puts the object here. Main goal is to prevent race with -		 * the network thread, when it can start processing the given request, i.e. -		 * increase its reference counter but yet not complete it, while -		 * we will exit from ->getxattr() with timeout, and although request -		 * will not be freed (its reference counter was increased by network -		 * thread), data pointer provided by user may be released, so we will -		 * overwrite an already freed area in the network thread. -		 * -		 * Now after timeout we remove request from the cache, so it can not be -		 * found by network thread, and wait for its reference counter to hit 1, -		 * i.e. if network thread already started to process this request, we wait -		 * for it to finish, and then free object locally. If reference counter is -		 * already 1, i.e. request is not used by anyone else, we can free it without -		 * problem. -		 */ -		err = -ETIMEDOUT; -		timeout = HZ; - -		pohmelfs_mcache_remove_locked(psb, m); -	} while (atomic_read(&m->refcnt) != 1); - -	pohmelfs_mcache_put(psb, m); - -	dprintk("%s: ino: %llu, err: %d.\n", __func__, pi->ino, err); - -	return err; - -err_out_put: -	pohmelfs_mcache_put(psb, m); -	return err; -} - -static int pohmelfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) -{ -	struct inode *inode = dentry->d_inode; -#if 0 -	struct pohmelfs_inode *pi = POHMELFS_I(inode); -	int err; - -	err = pohmelfs_data_lock(pi, 0, ~0, POHMELFS_READ_LOCK); -	if (err) -		return err; -	dprintk("%s: ino: %llu, mode: %o, uid: %u, gid: %u, size: %llu.\n", -			__func__, pi->ino, inode->i_mode, inode->i_uid, -			inode->i_gid, inode->i_size); -#endif - -	generic_fillattr(inode, stat); -	return 0; -} - -const struct inode_operations pohmelfs_file_inode_operations = { -	.setattr	= pohmelfs_setattr, -	.getattr	= pohmelfs_getattr, -	.setxattr	= pohmelfs_setxattr, -	.getxattr	= pohmelfs_getxattr, -}; - -/* - * Fill inode data: mode, size, operation callbacks and so on... - */ -void pohmelfs_fill_inode(struct inode *inode, struct netfs_inode_info *info) -{ -	inode->i_mode = info->mode; -	set_nlink(inode, info->nlink); -	inode->i_uid = info->uid; -	inode->i_gid = info->gid; -	inode->i_blocks = info->blocks; -	inode->i_rdev = info->rdev; -	inode->i_size = info->size; -	inode->i_version = info->version; -	inode->i_blkbits = ffs(info->blocksize); - -	dprintk("%s: inode: %p, num: %lu/%llu inode is regular: %d, dir: %d, link: %d, mode: %o, size: %llu.\n", -			__func__, inode, inode->i_ino, info->ino, -			S_ISREG(inode->i_mode), S_ISDIR(inode->i_mode), -			S_ISLNK(inode->i_mode), inode->i_mode, inode->i_size); - -	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC; - -	/* -	 * i_mapping is a pointer to i_data during inode initialization. -	 */ -	inode->i_data.a_ops = &pohmelfs_aops; - -	if (S_ISREG(inode->i_mode)) { -		inode->i_fop = &pohmelfs_file_ops; -		inode->i_op = &pohmelfs_file_inode_operations; -	} else if (S_ISDIR(inode->i_mode)) { -		inode->i_fop = &pohmelfs_dir_fops; -		inode->i_op = &pohmelfs_dir_inode_ops; -	} else if (S_ISLNK(inode->i_mode)) { -		inode->i_op = &pohmelfs_symlink_inode_operations; -		inode->i_fop = &pohmelfs_file_ops; -	} else { -		inode->i_fop = &generic_ro_fops; -	} -} - -static int pohmelfs_drop_inode(struct inode *inode) -{ -	struct pohmelfs_sb *psb = POHMELFS_SB(inode->i_sb); -	struct pohmelfs_inode *pi = POHMELFS_I(inode); - -	spin_lock(&psb->ino_lock); -	list_del_init(&pi->inode_entry); -	spin_unlock(&psb->ino_lock); - -	return generic_drop_inode(inode); -} - -static struct pohmelfs_inode *pohmelfs_get_inode_from_list(struct pohmelfs_sb *psb, -		struct list_head *head, unsigned int *count) -{ -	struct pohmelfs_inode *pi = NULL; - -	spin_lock(&psb->ino_lock); -	if (!list_empty(head)) { -		pi = list_entry(head->next, struct pohmelfs_inode, -					inode_entry); -		list_del_init(&pi->inode_entry); -		*count = pi->drop_count; -		pi->drop_count = 0; -	} -	spin_unlock(&psb->ino_lock); - -	return pi; -} - -static void pohmelfs_flush_transactions(struct pohmelfs_sb *psb) -{ -	struct pohmelfs_config *c; - -	mutex_lock(&psb->state_lock); -	list_for_each_entry(c, &psb->state_list, config_entry) { -		pohmelfs_state_flush_transactions(&c->state); -	} -	mutex_unlock(&psb->state_lock); -} - -/* - * ->put_super() callback. Invoked before superblock is destroyed, - *  so it has to clean all private data. - */ -static void pohmelfs_put_super(struct super_block *sb) -{ -	struct pohmelfs_sb *psb = POHMELFS_SB(sb); -	struct pohmelfs_inode *pi; -	unsigned int count = 0; -	unsigned int in_drop_list = 0; -	struct inode *inode, *tmp; - -	dprintk("%s.\n", __func__); - -	/* -	 * Kill pending transactions, which could affect inodes in-flight. -	 */ -	pohmelfs_flush_transactions(psb); - -	while ((pi = pohmelfs_get_inode_from_list(psb, &psb->drop_list, &count))) { -		inode = &pi->vfs_inode; - -		dprintk("%s: ino: %llu, pi: %p, inode: %p, count: %u.\n", -				__func__, pi->ino, pi, inode, count); - -		if (atomic_read(&inode->i_count) != count) { -			printk("%s: ino: %llu, pi: %p, inode: %p, count: %u, i_count: %d.\n", -					__func__, pi->ino, pi, inode, count, -					atomic_read(&inode->i_count)); -			count = atomic_read(&inode->i_count); -			in_drop_list++; -		} - -		while (count--) -			iput(&pi->vfs_inode); -	} - -	list_for_each_entry_safe(inode, tmp, &sb->s_inodes, i_sb_list) { -		pi = POHMELFS_I(inode); - -		dprintk("%s: ino: %llu, pi: %p, inode: %p, i_count: %u.\n", -				__func__, pi->ino, pi, inode, atomic_read(&inode->i_count)); - -		/* -		 * These are special inodes, they were created during -		 * directory reading or lookup, and were not bound to dentry, -		 * so they live here with reference counter being 1 and prevent -		 * umount from succeed since it believes that they are busy. -		 */ -		count = atomic_read(&inode->i_count); -		if (count) { -			list_del_init(&inode->i_sb_list); -			while (count--) -				iput(&pi->vfs_inode); -		} -	} - -	psb->trans_scan_timeout = psb->drop_scan_timeout = 0; -	cancel_delayed_work_sync(&psb->dwork); -	cancel_delayed_work_sync(&psb->drop_dwork); -	flush_scheduled_work(); - -	dprintk("%s: stopped workqueues.\n", __func__); - -	pohmelfs_crypto_exit(psb); -	pohmelfs_state_exit(psb); - -	bdi_destroy(&psb->bdi); - -	kfree(psb); -	sb->s_fs_info = NULL; -} - -static int pohmelfs_statfs(struct dentry *dentry, struct kstatfs *buf) -{ -	struct super_block *sb = dentry->d_sb; -	struct pohmelfs_sb *psb = POHMELFS_SB(sb); - -	/* -	 * There are no filesystem size limits yet. -	 */ -	memset(buf, 0, sizeof(struct kstatfs)); - -	buf->f_type = POHMELFS_MAGIC_NUM; /* 'POH.' */ -	buf->f_bsize = sb->s_blocksize; -	buf->f_files = psb->ino; -	buf->f_namelen = 255; -	buf->f_files = atomic_long_read(&psb->total_inodes); -	buf->f_bfree = buf->f_bavail = psb->avail_size >> PAGE_SHIFT; -	buf->f_blocks = psb->total_size >> PAGE_SHIFT; - -	dprintk("%s: total: %llu, avail: %llu, inodes: %llu, bsize: %lu.\n", -		__func__, psb->total_size, psb->avail_size, buf->f_files, sb->s_blocksize); - -	return 0; -} - -static int pohmelfs_show_options(struct seq_file *seq, struct dentry *root) -{ -	struct pohmelfs_sb *psb = POHMELFS_SB(root->d_sb); - -	seq_printf(seq, ",idx=%u", psb->idx); -	seq_printf(seq, ",trans_scan_timeout=%u", jiffies_to_msecs(psb->trans_scan_timeout)); -	seq_printf(seq, ",drop_scan_timeout=%u", jiffies_to_msecs(psb->drop_scan_timeout)); -	seq_printf(seq, ",wait_on_page_timeout=%u", jiffies_to_msecs(psb->wait_on_page_timeout)); -	seq_printf(seq, ",trans_retries=%u", psb->trans_retries); -	seq_printf(seq, ",crypto_thread_num=%u", psb->crypto_thread_num); -	seq_printf(seq, ",trans_max_pages=%u", psb->trans_max_pages); -	seq_printf(seq, ",mcache_timeout=%u", jiffies_to_msecs(psb->mcache_timeout)); -	if (psb->crypto_fail_unsupported) -		seq_printf(seq, ",crypto_fail_unsupported"); - -	return 0; -} - -enum { -	pohmelfs_opt_idx, -	pohmelfs_opt_crypto_thread_num, -	pohmelfs_opt_trans_max_pages, -	pohmelfs_opt_crypto_fail_unsupported, - -	/* Remountable options */ -	pohmelfs_opt_trans_scan_timeout, -	pohmelfs_opt_drop_scan_timeout, -	pohmelfs_opt_wait_on_page_timeout, -	pohmelfs_opt_trans_retries, -	pohmelfs_opt_mcache_timeout, -}; - -static struct match_token pohmelfs_tokens[] = { -	{pohmelfs_opt_idx, "idx=%u"}, -	{pohmelfs_opt_crypto_thread_num, "crypto_thread_num=%u"}, -	{pohmelfs_opt_trans_max_pages, "trans_max_pages=%u"}, -	{pohmelfs_opt_crypto_fail_unsupported, "crypto_fail_unsupported"}, -	{pohmelfs_opt_trans_scan_timeout, "trans_scan_timeout=%u"}, -	{pohmelfs_opt_drop_scan_timeout, "drop_scan_timeout=%u"}, -	{pohmelfs_opt_wait_on_page_timeout, "wait_on_page_timeout=%u"}, -	{pohmelfs_opt_trans_retries, "trans_retries=%u"}, -	{pohmelfs_opt_mcache_timeout, "mcache_timeout=%u"}, -}; - -static int pohmelfs_parse_options(char *options, struct pohmelfs_sb *psb, int remount) -{ -	char *p; -	substring_t args[MAX_OPT_ARGS]; -	int option, err; - -	if (!options) -		return 0; - -	while ((p = strsep(&options, ",")) != NULL) { -		int token; -		if (!*p) -			continue; - -		token = match_token(p, pohmelfs_tokens, args); - -		err = match_int(&args[0], &option); -		if (err) -			return err; - -		if (remount && token <= pohmelfs_opt_crypto_fail_unsupported) -			continue; - -		switch (token) { -		case pohmelfs_opt_idx: -			psb->idx = option; -			break; -		case pohmelfs_opt_trans_scan_timeout: -			psb->trans_scan_timeout = msecs_to_jiffies(option); -			break; -		case pohmelfs_opt_drop_scan_timeout: -			psb->drop_scan_timeout = msecs_to_jiffies(option); -			break; -		case pohmelfs_opt_wait_on_page_timeout: -			psb->wait_on_page_timeout = msecs_to_jiffies(option); -			break; -		case pohmelfs_opt_mcache_timeout: -			psb->mcache_timeout = msecs_to_jiffies(option); -			break; -		case pohmelfs_opt_trans_retries: -			psb->trans_retries = option; -			break; -		case pohmelfs_opt_crypto_thread_num: -			psb->crypto_thread_num = option; -			break; -		case pohmelfs_opt_trans_max_pages: -			psb->trans_max_pages = option; -			break; -		case pohmelfs_opt_crypto_fail_unsupported: -			psb->crypto_fail_unsupported = 1; -			break; -		default: -			return -EINVAL; -		} -	} - -	return 0; -} - -static int pohmelfs_remount(struct super_block *sb, int *flags, char *data) -{ -	int err; -	struct pohmelfs_sb *psb = POHMELFS_SB(sb); -	unsigned long old_sb_flags = sb->s_flags; - -	err = pohmelfs_parse_options(data, psb, 1); -	if (err) -		goto err_out_restore; - -	if (!(*flags & MS_RDONLY)) -		sb->s_flags &= ~MS_RDONLY; -	return 0; - -err_out_restore: -	sb->s_flags = old_sb_flags; -	return err; -} - -static void pohmelfs_flush_inode(struct pohmelfs_inode *pi, unsigned int count) -{ -	struct inode *inode = &pi->vfs_inode; - -	dprintk("%s: %p: ino: %llu, owned: %d.\n", -		__func__, inode, pi->ino, test_bit(NETFS_INODE_OWNED, &pi->state)); - -	mutex_lock(&inode->i_mutex); -	if (test_and_clear_bit(NETFS_INODE_OWNED, &pi->state)) { -		filemap_fdatawrite(inode->i_mapping); -		inode->i_sb->s_op->write_inode(inode, 0); -	} - -#ifdef POHMELFS_TRUNCATE_ON_INODE_FLUSH -	truncate_inode_pages(inode->i_mapping, 0); -#endif - -	pohmelfs_data_unlock(pi, 0, ~0, POHMELFS_WRITE_LOCK); -	mutex_unlock(&inode->i_mutex); -} - -static void pohmelfs_put_inode_count(struct pohmelfs_inode *pi, unsigned int count) -{ -	dprintk("%s: ino: %llu, pi: %p, inode: %p, count: %u.\n", -			__func__, pi->ino, pi, &pi->vfs_inode, count); - -	if (test_and_clear_bit(NETFS_INODE_NEED_FLUSH, &pi->state)) -		pohmelfs_flush_inode(pi, count); - -	while (count--) -		iput(&pi->vfs_inode); -} - -static void pohmelfs_drop_scan(struct work_struct *work) -{ -	struct pohmelfs_sb *psb = -		container_of(work, struct pohmelfs_sb, drop_dwork.work); -	struct pohmelfs_inode *pi; -	unsigned int count = 0; - -	while ((pi = pohmelfs_get_inode_from_list(psb, &psb->drop_list, &count))) -		pohmelfs_put_inode_count(pi, count); - -	pohmelfs_check_states(psb); - -	if (psb->drop_scan_timeout) -		schedule_delayed_work(&psb->drop_dwork, psb->drop_scan_timeout); -} - -/* - * Run through all transactions starting from the oldest, - * drop transaction from current state and try to send it - * to all remote nodes, which are currently installed. - */ -static void pohmelfs_trans_scan_state(struct netfs_state *st) -{ -	struct rb_node *rb_node; -	struct netfs_trans_dst *dst; -	struct pohmelfs_sb *psb = st->psb; -	unsigned int timeout = psb->trans_scan_timeout; -	struct netfs_trans *t; -	int err; - -	mutex_lock(&st->trans_lock); -	for (rb_node = rb_first(&st->trans_root); rb_node; ) { -		dst = rb_entry(rb_node, struct netfs_trans_dst, state_entry); -		t = dst->trans; - -		if (timeout && time_after(dst->send_time + timeout, jiffies) -				&& dst->retries == 0) -			break; - -		dprintk("%s: t: %p, gen: %u, st: %p, retries: %u, max: %u.\n", -			__func__, t, t->gen, st, dst->retries, psb->trans_retries); -		netfs_trans_get(t); - -		rb_node = rb_next(rb_node); - -		err = -ETIMEDOUT; -		if (timeout && (++dst->retries < psb->trans_retries)) -			err = netfs_trans_resend(t, psb); - -		if (err || (t->flags & NETFS_TRANS_SINGLE_DST)) { -			if (netfs_trans_remove_nolock(dst, st)) -				netfs_trans_drop_dst_nostate(dst); -		} - -		t->result = err; -		netfs_trans_put(t); -	} -	mutex_unlock(&st->trans_lock); -} - -/* - * Walk through all installed network states and resend all - * transactions, which are old enough. - */ -static void pohmelfs_trans_scan(struct work_struct *work) -{ -	struct pohmelfs_sb *psb = -		container_of(work, struct pohmelfs_sb, dwork.work); -	struct netfs_state *st; -	struct pohmelfs_config *c; - -	mutex_lock(&psb->state_lock); -	list_for_each_entry(c, &psb->state_list, config_entry) { -		st = &c->state; - -		pohmelfs_trans_scan_state(st); -	} -	mutex_unlock(&psb->state_lock); - -	/* -	 * If no timeout specified then system is in the middle of umount process, -	 * so no need to reschedule scanning process again. -	 */ -	if (psb->trans_scan_timeout) -		schedule_delayed_work(&psb->dwork, psb->trans_scan_timeout); -} - -int pohmelfs_meta_command_data(struct pohmelfs_inode *pi, u64 id, unsigned int cmd_op, char *addon, -		unsigned int flags, netfs_trans_complete_t complete, void *priv, u64 start) -{ -	struct inode *inode = &pi->vfs_inode; -	struct pohmelfs_sb *psb = POHMELFS_SB(inode->i_sb); -	int err = 0, sz; -	struct netfs_trans *t; -	int path_len, addon_len = 0; -	void *data; -	struct netfs_inode_info *info; -	struct netfs_cmd *cmd; - -	dprintk("%s: ino: %llu, cmd: %u, addon: %p.\n", __func__, pi->ino, cmd_op, addon); - -	path_len = pohmelfs_path_length(pi); -	if (path_len < 0) { -		err = path_len; -		goto err_out_exit; -	} - -	if (addon) -		addon_len = strlen(addon) + 1; /* 0-byte */ -	sz = addon_len; - -	if (cmd_op == NETFS_INODE_INFO) -		sz += sizeof(struct netfs_inode_info); - -	t = netfs_trans_alloc(psb, sz + path_len, flags, 0); -	if (!t) { -		err = -ENOMEM; -		goto err_out_exit; -	} -	t->complete = complete; -	t->private = priv; - -	cmd = netfs_trans_current(t); -	data = (void *)(cmd + 1); - -	if (cmd_op == NETFS_INODE_INFO) { -		info = (struct netfs_inode_info *)(cmd + 1); -		data = (void *)(info + 1); - -		/* -		 * We are under i_mutex, can read and change whatever we want... -		 */ -		info->mode = inode->i_mode; -		info->nlink = inode->i_nlink; -		info->uid = inode->i_uid; -		info->gid = inode->i_gid; -		info->blocks = inode->i_blocks; -		info->rdev = inode->i_rdev; -		info->size = inode->i_size; -		info->version = inode->i_version; - -		netfs_convert_inode_info(info); -	} - -	path_len = pohmelfs_construct_path_string(pi, data, path_len); -	if (path_len < 0) -		goto err_out_free; - -	dprintk("%s: path_len: %d.\n", __func__, path_len); - -	if (addon) { -		path_len--; /* Do not place null-byte before the addon */ -		path_len += sprintf(data + path_len, "/%s", addon) + 1; /* 0 - byte */ -	} - -	sz += path_len; - -	cmd->cmd = cmd_op; -	cmd->ext = path_len; -	cmd->size = sz; -	cmd->id = id; -	cmd->start = start; - -	netfs_convert_cmd(cmd); -	netfs_trans_update(cmd, t, sz); - -	/* -	 * Note, that it is possible to leak error here: transaction callback will not -	 * be invoked for allocation path failure. -	 */ -	return netfs_trans_finish(t, psb); - -err_out_free: -	netfs_trans_free(t); -err_out_exit: -	if (complete) -		complete(NULL, 0, priv, err); -	return err; -} - -int pohmelfs_meta_command(struct pohmelfs_inode *pi, unsigned int cmd_op, unsigned int flags, -		netfs_trans_complete_t complete, void *priv, u64 start) -{ -	return pohmelfs_meta_command_data(pi, pi->ino, cmd_op, NULL, flags, complete, priv, start); -} - -/* - * Send request and wait for POHMELFS root capabilities response, - * which will update server's informaion about size of the export, - * permissions, number of objects, available size and so on. - */ -static int pohmelfs_root_handshake(struct pohmelfs_sb *psb) -{ -	struct netfs_trans *t; -	struct netfs_cmd *cmd; -	int err = -ENOMEM; - -	t = netfs_trans_alloc(psb, 0, 0, 0); -	if (!t) -		goto err_out_exit; - -	cmd = netfs_trans_current(t); - -	cmd->cmd = NETFS_CAPABILITIES; -	cmd->id = POHMELFS_ROOT_CAPABILITIES; -	cmd->size = 0; -	cmd->start = 0; -	cmd->ext = 0; -	cmd->csize = 0; - -	netfs_convert_cmd(cmd); -	netfs_trans_update(cmd, t, 0); - -	err = netfs_trans_finish(t, psb); -	if (err) -		goto err_out_exit; - -	psb->flags = ~0; -	err = wait_event_interruptible_timeout(psb->wait, -			(psb->flags != ~0), -			psb->wait_on_page_timeout); -	if (!err) -		err = -ETIMEDOUT; -	else if (err > 0) -		err = -psb->flags; - -	if (err) -		goto err_out_exit; - -	return 0; - -err_out_exit: -	return err; -} - -static int pohmelfs_show_stats(struct seq_file *m, struct dentry *root) -{ -	struct netfs_state *st; -	struct pohmelfs_ctl *ctl; -	struct pohmelfs_sb *psb = POHMELFS_SB(root->d_sb); -	struct pohmelfs_config *c; - -	mutex_lock(&psb->state_lock); - -	seq_printf(m, "\nidx addr(:port) socket_type protocol active priority permissions\n"); - -	list_for_each_entry(c, &psb->state_list, config_entry) { -		st = &c->state; -		ctl = &st->ctl; - -		seq_printf(m, "%u ", ctl->idx); -		if (ctl->addr.sa_family == AF_INET) { -			struct sockaddr_in *sin = (struct sockaddr_in *)&st->ctl.addr; -			seq_printf(m, "%pI4:%u", &sin->sin_addr.s_addr, ntohs(sin->sin_port)); -		} else if (ctl->addr.sa_family == AF_INET6) { -			struct sockaddr_in6 *sin = (struct sockaddr_in6 *)&st->ctl.addr; -			seq_printf(m, "%pi6:%u", &sin->sin6_addr, ntohs(sin->sin6_port)); -		} else { -			unsigned int i; -			for (i = 0; i < ctl->addrlen; ++i) -				seq_printf(m, "%02x.", ctl->addr.addr[i]); -		} - -		seq_printf(m, " %u %u %d %u %x\n", -				ctl->type, ctl->proto, -				st->socket != NULL, -				ctl->prio, ctl->perm); -	} -	mutex_unlock(&psb->state_lock); - -	return 0; -} - -static const struct super_operations pohmelfs_sb_ops = { -	.alloc_inode	= pohmelfs_alloc_inode, -	.destroy_inode	= pohmelfs_destroy_inode, -	.drop_inode	= pohmelfs_drop_inode, -	.write_inode	= pohmelfs_write_inode, -	.put_super	= pohmelfs_put_super, -	.remount_fs	= pohmelfs_remount, -	.statfs		= pohmelfs_statfs, -	.show_options	= pohmelfs_show_options, -	.show_stats	= pohmelfs_show_stats, -}; - -/* - * Allocate private superblock and create root dir. - */ -static int pohmelfs_fill_super(struct super_block *sb, void *data, int silent) -{ -	struct pohmelfs_sb *psb; -	int err = -ENOMEM; -	struct inode *root; -	struct pohmelfs_inode *npi; -	struct qstr str; - -	psb = kzalloc(sizeof(struct pohmelfs_sb), GFP_KERNEL); -	if (!psb) -		goto err_out_exit; - -	err = bdi_init(&psb->bdi); -	if (err) -		goto err_out_free_sb; - -	err = bdi_register(&psb->bdi, NULL, "pfs-%d", atomic_inc_return(&psb_bdi_num)); -	if (err) { -		bdi_destroy(&psb->bdi); -		goto err_out_free_sb; -	} - -	sb->s_fs_info = psb; -	sb->s_op = &pohmelfs_sb_ops; -	sb->s_magic = POHMELFS_MAGIC_NUM; -	sb->s_maxbytes = MAX_LFS_FILESIZE; -	sb->s_blocksize = PAGE_SIZE; -	sb->s_bdi = &psb->bdi; - -	psb->sb = sb; - -	psb->ino = 2; -	psb->idx = 0; -	psb->active_state = NULL; -	psb->trans_retries = 5; -	psb->trans_data_size = PAGE_SIZE; -	psb->drop_scan_timeout = msecs_to_jiffies(1000); -	psb->trans_scan_timeout = msecs_to_jiffies(5000); -	psb->wait_on_page_timeout = msecs_to_jiffies(5000); -	init_waitqueue_head(&psb->wait); - -	spin_lock_init(&psb->ino_lock); - -	INIT_LIST_HEAD(&psb->drop_list); - -	mutex_init(&psb->mcache_lock); -	psb->mcache_root = RB_ROOT; -	psb->mcache_timeout = msecs_to_jiffies(5000); -	atomic_long_set(&psb->mcache_gen, 0); - -	psb->trans_max_pages = 100; - -	psb->crypto_align_size = 16; -	psb->crypto_attached_size = 0; -	psb->hash_strlen = 0; -	psb->cipher_strlen = 0; -	psb->perform_crypto = 0; -	psb->crypto_thread_num = 2; -	psb->crypto_fail_unsupported = 0; -	mutex_init(&psb->crypto_thread_lock); -	INIT_LIST_HEAD(&psb->crypto_ready_list); -	INIT_LIST_HEAD(&psb->crypto_active_list); - -	atomic_set(&psb->trans_gen, 1); -	atomic_long_set(&psb->total_inodes, 0); - -	mutex_init(&psb->state_lock); -	INIT_LIST_HEAD(&psb->state_list); - -	err = pohmelfs_parse_options((char *) data, psb, 0); -	if (err) -		goto err_out_free_bdi; - -	err = pohmelfs_copy_crypto(psb); -	if (err) -		goto err_out_free_bdi; - -	err = pohmelfs_state_init(psb); -	if (err) -		goto err_out_free_strings; - -	err = pohmelfs_crypto_init(psb); -	if (err) -		goto err_out_state_exit; - -	err = pohmelfs_root_handshake(psb); -	if (err) -		goto err_out_crypto_exit; - -	str.name = "/"; -	str.hash = jhash("/", 1, 0); -	str.len = 1; - -	npi = pohmelfs_create_entry_local(psb, NULL, &str, 0, 0755|S_IFDIR); -	if (IS_ERR(npi)) { -		err = PTR_ERR(npi); -		goto err_out_crypto_exit; -	} -	set_bit(NETFS_INODE_REMOTE_SYNCED, &npi->state); -	clear_bit(NETFS_INODE_OWNED, &npi->state); - -	root = &npi->vfs_inode; - -	sb->s_root = d_alloc_root(root); -	if (!sb->s_root) -		goto err_out_put_root; - -	INIT_DELAYED_WORK(&psb->drop_dwork, pohmelfs_drop_scan); -	schedule_delayed_work(&psb->drop_dwork, psb->drop_scan_timeout); - -	INIT_DELAYED_WORK(&psb->dwork, pohmelfs_trans_scan); -	schedule_delayed_work(&psb->dwork, psb->trans_scan_timeout); - -	return 0; - -err_out_put_root: -	iput(root); -err_out_crypto_exit: -	pohmelfs_crypto_exit(psb); -err_out_state_exit: -	pohmelfs_state_exit(psb); -err_out_free_strings: -	kfree(psb->cipher_string); -	kfree(psb->hash_string); -err_out_free_bdi: -	bdi_destroy(&psb->bdi); -err_out_free_sb: -	kfree(psb); -err_out_exit: - -	dprintk("%s: err: %d.\n", __func__, err); -	return err; -} - -/* - * Some VFS magic here... - */ -static struct dentry *pohmelfs_mount(struct file_system_type *fs_type, -	int flags, const char *dev_name, void *data) -{ -	return mount_nodev(fs_type, flags, data, pohmelfs_fill_super); -} - -/* - * We need this to sync all inodes earlier, since when writeback - * is invoked from the umount/mntput path dcache is already shrunk, - * see generic_shutdown_super(), and no inodes can access the path. - */ -static void pohmelfs_kill_super(struct super_block *sb) -{ -	sync_inodes_sb(sb); -	kill_anon_super(sb); -} - -static struct file_system_type pohmel_fs_type = { -	.owner		= THIS_MODULE, -	.name		= "pohmel", -	.mount		= pohmelfs_mount, -	.kill_sb 	= pohmelfs_kill_super, -}; - -/* - * Cache and module initializations and freeing routings. - */ -static void pohmelfs_init_once(void *data) -{ -	struct pohmelfs_inode *pi = data; - -	inode_init_once(&pi->vfs_inode); -} - -static int __init pohmelfs_init_inodecache(void) -{ -	pohmelfs_inode_cache = kmem_cache_create("pohmelfs_inode_cache", -				sizeof(struct pohmelfs_inode), -				0, (SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD), -				pohmelfs_init_once); -	if (!pohmelfs_inode_cache) -		return -ENOMEM; - -	return 0; -} - -static void pohmelfs_destroy_inodecache(void) -{ -	kmem_cache_destroy(pohmelfs_inode_cache); -} - -static int __init init_pohmel_fs(void) -{ -	int err; - -	err = pohmelfs_config_init(); -	if (err) -		goto err_out_exit; - -	err = pohmelfs_init_inodecache(); -	if (err) -		goto err_out_config_exit; - -	err = pohmelfs_mcache_init(); -	if (err) -		goto err_out_destroy; - -	err = netfs_trans_init(); -	if (err) -		goto err_out_mcache_exit; - -	err = register_filesystem(&pohmel_fs_type); -	if (err) -		goto err_out_trans; - -	return 0; - -err_out_trans: -	netfs_trans_exit(); -err_out_mcache_exit: -	pohmelfs_mcache_exit(); -err_out_destroy: -	pohmelfs_destroy_inodecache(); -err_out_config_exit: -	pohmelfs_config_exit(); -err_out_exit: -	return err; -} - -static void __exit exit_pohmel_fs(void) -{ -	unregister_filesystem(&pohmel_fs_type); -	pohmelfs_destroy_inodecache(); -	pohmelfs_mcache_exit(); -	pohmelfs_config_exit(); -	netfs_trans_exit(); -} - -module_init(init_pohmel_fs); -module_exit(exit_pohmel_fs); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Evgeniy Polyakov <zbr@ioremap.net>"); -MODULE_DESCRIPTION("Pohmel filesystem"); diff --git a/drivers/staging/pohmelfs/lock.c b/drivers/staging/pohmelfs/lock.c deleted file mode 100644 index 6710114cd42..00000000000 --- a/drivers/staging/pohmelfs/lock.c +++ /dev/null @@ -1,182 +0,0 @@ -/* - * 2007+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net> - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU General Public License for more details. - */ - -#include <linux/module.h> -#include <linux/backing-dev.h> -#include <linux/fs.h> -#include <linux/fsnotify.h> -#include <linux/mempool.h> - -#include "netfs.h" - -static int pohmelfs_send_lock_trans(struct pohmelfs_inode *pi, -		u64 id, u64 start, u32 size, int type) -{ -	struct inode *inode = &pi->vfs_inode; -	struct pohmelfs_sb *psb = POHMELFS_SB(inode->i_sb); -	struct netfs_trans *t; -	struct netfs_cmd *cmd; -	int path_len, err; -	void *data; -	struct netfs_lock *l; -	int isize = (type & POHMELFS_LOCK_GRAB) ? 0 : sizeof(struct netfs_inode_info); - -	err = pohmelfs_path_length(pi); -	if (err < 0) -		goto err_out_exit; - -	path_len = err; - -	err = -ENOMEM; -	t = netfs_trans_alloc(psb, path_len + sizeof(struct netfs_lock) + isize, -			NETFS_TRANS_SINGLE_DST, 0); -	if (!t) -		goto err_out_exit; - -	cmd = netfs_trans_current(t); -	data = cmd + 1; - -	err = pohmelfs_construct_path_string(pi, data, path_len); -	if (err < 0) -		goto err_out_free; -	path_len = err; - -	l = data + path_len; - -	l->start = start; -	l->size = size; -	l->type = type; -	l->ino = pi->ino; - -	cmd->cmd = NETFS_LOCK; -	cmd->start = 0; -	cmd->id = id; -	cmd->size = sizeof(struct netfs_lock) + path_len + isize; -	cmd->ext = path_len; -	cmd->csize = 0; - -	netfs_convert_cmd(cmd); -	netfs_convert_lock(l); - -	if (isize) { -		struct netfs_inode_info *info = (struct netfs_inode_info *)(l + 1); - -		info->mode = inode->i_mode; -		info->nlink = inode->i_nlink; -		info->uid = inode->i_uid; -		info->gid = inode->i_gid; -		info->blocks = inode->i_blocks; -		info->rdev = inode->i_rdev; -		info->size = inode->i_size; -		info->version = inode->i_version; - -		netfs_convert_inode_info(info); -	} - -	netfs_trans_update(cmd, t, path_len + sizeof(struct netfs_lock) + isize); - -	return netfs_trans_finish(t, psb); - -err_out_free: -	netfs_trans_free(t); -err_out_exit: -	printk("%s: err: %d.\n", __func__, err); -	return err; -} - -int pohmelfs_data_lock(struct pohmelfs_inode *pi, u64 start, u32 size, int type) -{ -	struct pohmelfs_sb *psb = POHMELFS_SB(pi->vfs_inode.i_sb); -	struct pohmelfs_mcache *m; -	int err = -ENOMEM; -	struct iattr iattr; -	struct inode *inode = &pi->vfs_inode; - -	dprintk("%s: %p: ino: %llu, start: %llu, size: %u, " -			"type: %d, locked as: %d, owned: %d.\n", -			__func__, &pi->vfs_inode, pi->ino, -			start, size, type, pi->lock_type, -			!!test_bit(NETFS_INODE_OWNED, &pi->state)); - -	if (!pohmelfs_need_lock(pi, type)) -		return 0; - -	m = pohmelfs_mcache_alloc(psb, start, size, NULL); -	if (IS_ERR(m)) -		return PTR_ERR(m); - -	err = pohmelfs_send_lock_trans(pi, m->gen, start, size, -			type | POHMELFS_LOCK_GRAB); -	if (err) -		goto err_out_put; - -	err = wait_for_completion_timeout(&m->complete, psb->mcache_timeout); -	if (err) -		err = m->err; -	else -		err = -ETIMEDOUT; - -	if (err) { -		printk("%s: %p: ino: %llu, mgen: %llu, start: %llu, size: %u, err: %d.\n", -			__func__, &pi->vfs_inode, pi->ino, m->gen, start, size, err); -	} - -	if (err && (err != -ENOENT)) -		goto err_out_put; - -	if (!err) { -		netfs_convert_inode_info(&m->info); - -		iattr.ia_valid = ATTR_MODE | ATTR_UID | ATTR_GID | ATTR_SIZE | ATTR_ATIME; -		iattr.ia_mode = m->info.mode; -		iattr.ia_uid = m->info.uid; -		iattr.ia_gid = m->info.gid; -		iattr.ia_size = m->info.size; -		iattr.ia_atime = CURRENT_TIME; - -		dprintk("%s: %p: ino: %llu, mgen: %llu, start: %llu, isize: %llu -> %llu.\n", -			__func__, &pi->vfs_inode, pi->ino, m->gen, start, inode->i_size, m->info.size); - -		err = pohmelfs_setattr_raw(inode, &iattr); -		if (!err) { -			struct dentry *dentry = d_find_alias(inode); -			if (dentry) { -				fsnotify_change(dentry, iattr.ia_valid); -				dput(dentry); -			} -		} -	} - -	pi->lock_type = type; -	set_bit(NETFS_INODE_OWNED, &pi->state); - -	pohmelfs_mcache_put(psb, m); - -	return 0; - -err_out_put: -	pohmelfs_mcache_put(psb, m); -	return err; -} - -int pohmelfs_data_unlock(struct pohmelfs_inode *pi, u64 start, u32 size, int type) -{ -	dprintk("%s: %p: ino: %llu, start: %llu, size: %u, type: %d.\n", -			__func__, &pi->vfs_inode, pi->ino, start, size, type); -	pi->lock_type = 0; -	clear_bit(NETFS_INODE_REMOTE_DIR_SYNCED, &pi->state); -	clear_bit(NETFS_INODE_OWNED, &pi->state); -	return pohmelfs_send_lock_trans(pi, pi->ino, start, size, type); -} diff --git a/drivers/staging/pohmelfs/mcache.c b/drivers/staging/pohmelfs/mcache.c deleted file mode 100644 index e22665cdd16..00000000000 --- a/drivers/staging/pohmelfs/mcache.c +++ /dev/null @@ -1,171 +0,0 @@ -/* - * 2007+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net> - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU General Public License for more details. - */ - -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/mempool.h> - -#include "netfs.h" - -static struct kmem_cache *pohmelfs_mcache_cache; -static mempool_t *pohmelfs_mcache_pool; - -static inline int pohmelfs_mcache_cmp(u64 gen, u64 new) -{ -	if (gen < new) -		return 1; -	if (gen > new) -		return -1; -	return 0; -} - -struct pohmelfs_mcache *pohmelfs_mcache_search(struct pohmelfs_sb *psb, u64 gen) -{ -	struct rb_root *root = &psb->mcache_root; -	struct rb_node *n = root->rb_node; -	struct pohmelfs_mcache *tmp, *ret = NULL; -	int cmp; - -	while (n) { -		tmp = rb_entry(n, struct pohmelfs_mcache, mcache_entry); - -		cmp = pohmelfs_mcache_cmp(tmp->gen, gen); -		if (cmp < 0) -			n = n->rb_left; -		else if (cmp > 0) -			n = n->rb_right; -		else { -			ret = tmp; -			pohmelfs_mcache_get(ret); -			break; -		} -	} - -	return ret; -} - -static int pohmelfs_mcache_insert(struct pohmelfs_sb *psb, struct pohmelfs_mcache *m) -{ -	struct rb_root *root = &psb->mcache_root; -	struct rb_node **n = &root->rb_node, *parent = NULL; -	struct pohmelfs_mcache *ret = NULL, *tmp; -	int cmp; - -	while (*n) { -		parent = *n; - -		tmp = rb_entry(parent, struct pohmelfs_mcache, mcache_entry); - -		cmp = pohmelfs_mcache_cmp(tmp->gen, m->gen); -		if (cmp < 0) -			n = &parent->rb_left; -		else if (cmp > 0) -			n = &parent->rb_right; -		else { -			ret = tmp; -			break; -		} -	} - -	if (ret) -		return -EEXIST; - -	rb_link_node(&m->mcache_entry, parent, n); -	rb_insert_color(&m->mcache_entry, root); - -	return 0; -} - -static int pohmelfs_mcache_remove(struct pohmelfs_sb *psb, struct pohmelfs_mcache *m) -{ -	if (m && m->mcache_entry.rb_parent_color) { -		rb_erase(&m->mcache_entry, &psb->mcache_root); -		m->mcache_entry.rb_parent_color = 0; -		return 1; -	} -	return 0; -} - -void pohmelfs_mcache_remove_locked(struct pohmelfs_sb *psb, struct pohmelfs_mcache *m) -{ -	mutex_lock(&psb->mcache_lock); -	pohmelfs_mcache_remove(psb, m); -	mutex_unlock(&psb->mcache_lock); -} - -struct pohmelfs_mcache *pohmelfs_mcache_alloc(struct pohmelfs_sb *psb, u64 start, -		unsigned int size, void *data) -{ -	struct pohmelfs_mcache *m; -	int err = -ENOMEM; - -	m = mempool_alloc(pohmelfs_mcache_pool, GFP_KERNEL); -	if (!m) -		goto err_out_exit; - -	init_completion(&m->complete); -	m->err = 0; -	atomic_set(&m->refcnt, 1); -	m->data = data; -	m->start = start; -	m->size = size; -	m->gen = atomic_long_inc_return(&psb->mcache_gen); - -	mutex_lock(&psb->mcache_lock); -	err = pohmelfs_mcache_insert(psb, m); -	mutex_unlock(&psb->mcache_lock); -	if (err) -		goto err_out_free; - -	return m; - -err_out_free: -	mempool_free(m, pohmelfs_mcache_pool); -err_out_exit: -	return ERR_PTR(err); -} - -void pohmelfs_mcache_free(struct pohmelfs_sb *psb, struct pohmelfs_mcache *m) -{ -	pohmelfs_mcache_remove_locked(psb, m); - -	mempool_free(m, pohmelfs_mcache_pool); -} - -int __init pohmelfs_mcache_init(void) -{ -	pohmelfs_mcache_cache = kmem_cache_create("pohmelfs_mcache_cache", -				sizeof(struct pohmelfs_mcache), -				0, (SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD), NULL); -	if (!pohmelfs_mcache_cache) -		goto err_out_exit; - -	pohmelfs_mcache_pool = mempool_create_slab_pool(256, pohmelfs_mcache_cache); -	if (!pohmelfs_mcache_pool) -		goto err_out_free; - -	return 0; - -err_out_free: -	kmem_cache_destroy(pohmelfs_mcache_cache); -err_out_exit: -	return -ENOMEM; -} - -void pohmelfs_mcache_exit(void) -{ -	mempool_destroy(pohmelfs_mcache_pool); -	kmem_cache_destroy(pohmelfs_mcache_cache); -} diff --git a/drivers/staging/pohmelfs/net.c b/drivers/staging/pohmelfs/net.c deleted file mode 100644 index b2e91862208..00000000000 --- a/drivers/staging/pohmelfs/net.c +++ /dev/null @@ -1,1209 +0,0 @@ -/* - * 2007+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net> - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU General Public License for more details. - */ - -#include <linux/fsnotify.h> -#include <linux/jhash.h> -#include <linux/in.h> -#include <linux/in6.h> -#include <linux/kthread.h> -#include <linux/pagemap.h> -#include <linux/poll.h> -#include <linux/slab.h> -#include <linux/swap.h> -#include <linux/syscalls.h> -#include <linux/vmalloc.h> - -#include "netfs.h" - -/* - * Async machinery lives here. - * All commands being sent to server do _not_ require sync reply, - * instead, if it is really needed, like readdir or readpage, caller - * sleeps waiting for data, which will be placed into provided buffer - * and caller will be awakened. - * - * Every command response can come without some listener. For example - * readdir response will add new objects into cache without appropriate - * request from userspace. This is used in cache coherency. - * - * If object is not found for given data, it is discarded. - * - * All requests are received by dedicated kernel thread. - */ - -/* - * Basic network sending/receiving functions. - * Blocked mode is used. - */ -static int netfs_data_recv(struct netfs_state *st, void *buf, u64 size) -{ -	struct msghdr msg; -	struct kvec iov; -	int err; - -	BUG_ON(!size); - -	iov.iov_base = buf; -	iov.iov_len = size; - -	msg.msg_iov = (struct iovec *)&iov; -	msg.msg_iovlen = 1; -	msg.msg_name = NULL; -	msg.msg_namelen = 0; -	msg.msg_control = NULL; -	msg.msg_controllen = 0; -	msg.msg_flags = MSG_DONTWAIT; - -	err = kernel_recvmsg(st->socket, &msg, &iov, 1, iov.iov_len, -			msg.msg_flags); -	if (err <= 0) { -		printk("%s: failed to recv data: size: %llu, err: %d.\n", __func__, size, err); -		if (err == 0) -			err = -ECONNRESET; -	} - -	return err; -} - -static int pohmelfs_data_recv(struct netfs_state *st, void *data, unsigned int size) -{ -	unsigned int revents = 0; -	unsigned int err_mask = POLLERR | POLLHUP | POLLRDHUP; -	unsigned int mask = err_mask | POLLIN; -	int err = 0; - -	while (size && !err) { -		revents = netfs_state_poll(st); - -		if (!(revents & mask)) { -			DEFINE_WAIT(wait); - -			for (;;) { -				prepare_to_wait(&st->thread_wait, &wait, TASK_INTERRUPTIBLE); -				if (kthread_should_stop()) -					break; - -				revents = netfs_state_poll(st); - -				if (revents & mask) -					break; - -				if (signal_pending(current)) -					break; - -				schedule(); -				continue; -			} -			finish_wait(&st->thread_wait, &wait); -		} - -		err = 0; -		netfs_state_lock(st); -		if (st->socket && (st->read_socket == st->socket) && (revents & POLLIN)) { -			err = netfs_data_recv(st, data, size); -			if (err > 0) { -				data += err; -				size -= err; -				err = 0; -			} else if (err == 0) -				err = -ECONNRESET; -		} - -		if (revents & err_mask) { -			printk("%s: revents: %x, socket: %p, size: %u, err: %d.\n", -					__func__, revents, st->socket, size, err); -			err = -ECONNRESET; -		} -		netfs_state_unlock(st); - -		if (err < 0) { -			if (netfs_state_trylock_send(st)) { -				netfs_state_exit(st); -				err = netfs_state_init(st); -				if (!err) -					err = -EAGAIN; -				netfs_state_unlock_send(st); -			} else { -				st->need_reset = 1; -			} -		} - -		if (kthread_should_stop()) -			err = -ENODEV; - -		if (err) -			printk("%s: socket: %p, read_socket: %p, revents: %x, rev_error: %d, " -					"should_stop: %d, size: %u, err: %d.\n", -				__func__, st->socket, st->read_socket, -				revents, revents & err_mask, kthread_should_stop(), size, err); -	} - -	return err; -} - -int pohmelfs_data_recv_and_check(struct netfs_state *st, void *data, unsigned int size) -{ -	struct netfs_cmd *cmd = &st->cmd; -	int err; - -	err = pohmelfs_data_recv(st, data, size); -	if (err) -		return err; - -	return pohmelfs_crypto_process_input_data(&st->eng, cmd->iv, data, NULL, size); -} - -/* - * Polling machinery. - */ - -struct netfs_poll_helper { -	poll_table 		pt; -	struct netfs_state	*st; -}; - -static int netfs_queue_wake(wait_queue_t *wait, unsigned mode, int sync, void *key) -{ -	struct netfs_state *st = container_of(wait, struct netfs_state, wait); - -	wake_up(&st->thread_wait); -	return 1; -} - -static void netfs_queue_func(struct file *file, wait_queue_head_t *whead, -				 poll_table *pt) -{ -	struct netfs_state *st = container_of(pt, struct netfs_poll_helper, pt)->st; - -	st->whead = whead; -	init_waitqueue_func_entry(&st->wait, netfs_queue_wake); -	add_wait_queue(whead, &st->wait); -} - -static void netfs_poll_exit(struct netfs_state *st) -{ -	if (st->whead) { -		remove_wait_queue(st->whead, &st->wait); -		st->whead = NULL; -	} -} - -static int netfs_poll_init(struct netfs_state *st) -{ -	struct netfs_poll_helper ph; - -	ph.st = st; -	init_poll_funcptr(&ph.pt, &netfs_queue_func); - -	st->socket->ops->poll(NULL, st->socket, &ph.pt); -	return 0; -} - -/* - * Get response for readpage command. We search inode and page in its mapping - * and copy data into. If it was async request, then we queue page into shared - * data and wakeup listener, who will copy it to userspace. - * - * There is a work in progress of allowing to call copy_to_user() directly from - * async receiving kernel thread. - */ -static int pohmelfs_read_page_response(struct netfs_state *st) -{ -	struct pohmelfs_sb *psb = st->psb; -	struct netfs_cmd *cmd = &st->cmd; -	struct inode *inode; -	struct page *page; -	int err = 0; - -	if (cmd->size > PAGE_CACHE_SIZE) { -		err = -EINVAL; -		goto err_out_exit; -	} - -	inode = ilookup(st->psb->sb, cmd->id); -	if (!inode) { -		printk("%s: failed to find inode: id: %llu.\n", __func__, cmd->id); -		err = -ENOENT; -		goto err_out_exit; -	} - -	page = find_get_page(inode->i_mapping, cmd->start >> PAGE_CACHE_SHIFT); -	if (!page || !PageLocked(page)) { -		printk("%s: failed to find/lock page: page: %p, id: %llu, start: %llu, index: %llu.\n", -				__func__, page, cmd->id, cmd->start, cmd->start >> PAGE_CACHE_SHIFT); - -		while (cmd->size) { -			unsigned int sz = min(cmd->size, st->size); - -			err = pohmelfs_data_recv(st, st->data, sz); -			if (err) -				break; - -			cmd->size -= sz; -		} - -		err = -ENODEV; -		if (page) -			goto err_out_page_put; -		goto err_out_put; -	} - -	if (cmd->size) { -		void *addr; - -		addr = kmap(page); -		err = pohmelfs_data_recv(st, addr, cmd->size); -		kunmap(page); - -		if (err) -			goto err_out_page_unlock; -	} - -	dprintk("%s: page: %p, start: %llu, size: %u, locked: %d.\n", -		__func__, page, cmd->start, cmd->size, PageLocked(page)); - -	SetPageChecked(page); -	if ((psb->hash_string || psb->cipher_string) && psb->perform_crypto && cmd->size) { -		err = pohmelfs_crypto_process_input_page(&st->eng, page, cmd->size, cmd->iv); -		if (err < 0) -			goto err_out_page_unlock; -	} else { -		SetPageUptodate(page); -		unlock_page(page); -		page_cache_release(page); -	} - -	pohmelfs_put_inode(POHMELFS_I(inode)); -	wake_up(&st->psb->wait); - -	return 0; - -err_out_page_unlock: -	SetPageError(page); -	unlock_page(page); -err_out_page_put: -	page_cache_release(page); -err_out_put: -	pohmelfs_put_inode(POHMELFS_I(inode)); -err_out_exit: -	wake_up(&st->psb->wait); -	return err; -} - -static int pohmelfs_check_name(struct pohmelfs_inode *parent, struct qstr *str, -		struct netfs_inode_info *info) -{ -	struct inode *inode; -	struct pohmelfs_name *n; -	int err = 0; -	u64 ino = 0; - -	mutex_lock(&parent->offset_lock); -	n = pohmelfs_search_hash(parent, str->hash); -	if (n) -		ino = n->ino; -	mutex_unlock(&parent->offset_lock); - -	if (!ino) -		goto out; - -	inode = ilookup(parent->vfs_inode.i_sb, ino); -	if (!inode) -		goto out; - -	dprintk("%s: parent: %llu, inode: %llu.\n", __func__, parent->ino, ino); - -	pohmelfs_fill_inode(inode, info); -	pohmelfs_put_inode(POHMELFS_I(inode)); -	err = -EEXIST; -out: -	return err; -} - -/* - * Readdir response from server. If special field is set, we wakeup - * listener (readdir() call), which will copy data to userspace. - */ -static int pohmelfs_readdir_response(struct netfs_state *st) -{ -	struct inode *inode; -	struct netfs_cmd *cmd = &st->cmd; -	struct netfs_inode_info *info; -	struct pohmelfs_inode *parent = NULL, *npi; -	int err = 0, last = cmd->ext; -	struct qstr str; - -	if (cmd->size > st->size) -		return -EINVAL; - -	inode = ilookup(st->psb->sb, cmd->id); -	if (!inode) { -		printk("%s: failed to find inode: id: %llu.\n", __func__, cmd->id); -		return -ENOENT; -	} -	parent = POHMELFS_I(inode); - -	if (!cmd->size && cmd->start) { -		err = -cmd->start; -		goto out; -	} - -	if (cmd->size) { -		char *name; - -		err = pohmelfs_data_recv_and_check(st, st->data, cmd->size); -		if (err) -			goto err_out_put; - -		info = (struct netfs_inode_info *)(st->data); - -		name = (char *)(info + 1); -		str.len = cmd->size - sizeof(struct netfs_inode_info) - 1 - cmd->cpad; -		name[str.len] = 0; -		str.name = name; -		str.hash = jhash(str.name, str.len, 0); - -		netfs_convert_inode_info(info); - -		if (parent) { -			err = pohmelfs_check_name(parent, &str, info); -			if (err) { -				if (err == -EEXIST) -					err = 0; -				goto out; -			} -		} - -		info->ino = cmd->start; -		if (!info->ino) -			info->ino = pohmelfs_new_ino(st->psb); - -		dprintk("%s: parent: %llu, ino: %llu, name: '%s', hash: %x, len: %u, mode: %o.\n", -				__func__, parent->ino, info->ino, str.name, str.hash, str.len, -				info->mode); - -		npi = pohmelfs_new_inode(st->psb, parent, &str, info, 0); -		if (IS_ERR(npi)) { -			err = PTR_ERR(npi); - -			if (err != -EEXIST) -				goto err_out_put; -		} else { -			struct dentry *dentry, *alias, *pd; - -			set_bit(NETFS_INODE_REMOTE_SYNCED, &npi->state); -			clear_bit(NETFS_INODE_OWNED, &npi->state); - -			pd = d_find_alias(&parent->vfs_inode); -			if (pd) { -				str.hash = full_name_hash(str.name, str.len); -				dentry = d_alloc(pd, &str); -				if (dentry) { -					alias = d_materialise_unique(dentry, &npi->vfs_inode); -					if (alias) -						dput(alias); -				} - -				dput(dentry); -				dput(pd); -			} -		} -	} -out: -	if (last) { -		set_bit(NETFS_INODE_REMOTE_DIR_SYNCED, &parent->state); -		set_bit(NETFS_INODE_REMOTE_SYNCED, &parent->state); -		wake_up(&st->psb->wait); -	} -	pohmelfs_put_inode(parent); - -	return err; - -err_out_put: -	clear_bit(NETFS_INODE_REMOTE_DIR_SYNCED, &parent->state); -	printk("%s: parent: %llu, ino: %llu, cmd_id: %llu.\n", __func__, parent->ino, cmd->start, cmd->id); -	pohmelfs_put_inode(parent); -	wake_up(&st->psb->wait); -	return err; -} - -/* - * Lookup command response. - * It searches for inode to be looked at (if it exists) and substitutes - * its inode information (size, permission, mode and so on), if inode does - * not exist, new one will be created and inserted into caches. - */ -static int pohmelfs_lookup_response(struct netfs_state *st) -{ -	struct inode *inode = NULL; -	struct netfs_cmd *cmd = &st->cmd; -	struct netfs_inode_info *info; -	struct pohmelfs_inode *parent = NULL, *npi; -	int err = -EINVAL; -	char *name; - -	inode = ilookup(st->psb->sb, cmd->id); -	if (!inode) { -		printk("%s: lookup response: id: %llu, start: %llu, size: %u.\n", -				__func__, cmd->id, cmd->start, cmd->size); -		err = -ENOENT; -		goto err_out_exit; -	} -	parent = POHMELFS_I(inode); - -	if (!cmd->size) { -		err = -cmd->start; -		goto err_out_put; -	} - -	if (cmd->size < sizeof(struct netfs_inode_info)) { -		printk("%s: broken lookup response: id: %llu, start: %llu, size: %u.\n", -				__func__, cmd->id, cmd->start, cmd->size); -		err = -EINVAL; -		goto err_out_put; -	} - -	err = pohmelfs_data_recv_and_check(st, st->data, cmd->size); -	if (err) -		goto err_out_put; - -	info = (struct netfs_inode_info *)(st->data); -	name = (char *)(info + 1); - -	netfs_convert_inode_info(info); - -	info->ino = cmd->start; -	if (!info->ino) -		info->ino = pohmelfs_new_ino(st->psb); - -	dprintk("%s: parent: %llu, ino: %llu, name: '%s', start: %llu.\n", -			__func__, parent->ino, info->ino, name, cmd->start); - -	if (cmd->start) -		npi = pohmelfs_new_inode(st->psb, parent, NULL, info, 0); -	else { -		struct qstr str; - -		str.name = name; -		str.len = cmd->size - sizeof(struct netfs_inode_info) - 1 - cmd->cpad; -		str.hash = jhash(name, str.len, 0); - -		npi = pohmelfs_new_inode(st->psb, parent, &str, info, 0); -	} -	if (IS_ERR(npi)) { -		err = PTR_ERR(npi); - -		if (err != -EEXIST) -			goto err_out_put; -	} else { -		set_bit(NETFS_INODE_REMOTE_SYNCED, &npi->state); -		clear_bit(NETFS_INODE_OWNED, &npi->state); -	} - -	clear_bit(NETFS_COMMAND_PENDING, &parent->state); -	pohmelfs_put_inode(parent); - -	wake_up(&st->psb->wait); - -	return 0; - -err_out_put: -	pohmelfs_put_inode(parent); -err_out_exit: -	clear_bit(NETFS_COMMAND_PENDING, &parent->state); -	wake_up(&st->psb->wait); -	printk("%s: inode: %p, id: %llu, start: %llu, size: %u, err: %d.\n", -			__func__, inode, cmd->id, cmd->start, cmd->size, err); -	return err; -} - -/* - * Create response, just marks local inode as 'created', so that writeback - * for any of its children (or own) would not try to sync it again. - */ -static int pohmelfs_create_response(struct netfs_state *st) -{ -	struct inode *inode; -	struct netfs_cmd *cmd = &st->cmd; -	struct pohmelfs_inode *pi; - -	inode = ilookup(st->psb->sb, cmd->id); -	if (!inode) { -		printk("%s: failed to find inode: id: %llu, start: %llu.\n", -				__func__, cmd->id, cmd->start); -		goto err_out_exit; -	} - -	pi = POHMELFS_I(inode); - -	/* -	 * To lock or not to lock? -	 * We actually do not care if it races... -	 */ -	if (cmd->start) -		make_bad_inode(inode); -	set_bit(NETFS_INODE_REMOTE_SYNCED, &pi->state); - -	pohmelfs_put_inode(pi); - -	wake_up(&st->psb->wait); -	return 0; - -err_out_exit: -	wake_up(&st->psb->wait); -	return -ENOENT; -} - -/* - * Object remove response. Just says that remove request has been received. - * Used in cache coherency protocol. - */ -static int pohmelfs_remove_response(struct netfs_state *st) -{ -	struct netfs_cmd *cmd = &st->cmd; -	int err; - -	err = pohmelfs_data_recv_and_check(st, st->data, cmd->size); -	if (err) -		return err; - -	dprintk("%s: parent: %llu, path: '%s'.\n", __func__, cmd->id, (char *)st->data); - -	return 0; -} - -/* - * Transaction reply processing. - * - * Find transaction based on its generation number, bump its reference counter, - * so that none could free it under us, drop from the trees and lists and - * drop reference counter. When it hits zero (when all destinations replied - * and all timeout handled by async scanning code), completion will be called - * and transaction will be freed. - */ -static int pohmelfs_transaction_response(struct netfs_state *st) -{ -	struct netfs_trans_dst *dst; -	struct netfs_trans *t = NULL; -	struct netfs_cmd *cmd = &st->cmd; -	short err = (signed)cmd->ext; - -	mutex_lock(&st->trans_lock); -	dst = netfs_trans_search(st, cmd->start); -	if (dst) { -		netfs_trans_remove_nolock(dst, st); -		t = dst->trans; -	} -	mutex_unlock(&st->trans_lock); - -	if (!t) { -		printk("%s: failed to find transaction: start: %llu: id: %llu, size: %u, ext: %u.\n", -				__func__, cmd->start, cmd->id, cmd->size, cmd->ext); -		err = -EINVAL; -		goto out; -	} - -	t->result = err; -	netfs_trans_drop_dst_nostate(dst); - -out: -	wake_up(&st->psb->wait); -	return err; -} - -/* - * Inode metadata cache coherency message. - */ -static int pohmelfs_page_cache_response(struct netfs_state *st) -{ -	struct netfs_cmd *cmd = &st->cmd; -	struct inode *inode; - -	dprintk("%s: st: %p, id: %llu, start: %llu, size: %u.\n", __func__, st, cmd->id, cmd->start, cmd->size); - -	inode = ilookup(st->psb->sb, cmd->id); -	if (!inode) { -		printk("%s: failed to find inode: id: %llu.\n", __func__, cmd->id); -		return -ENOENT; -	} - -	set_bit(NETFS_INODE_NEED_FLUSH, &POHMELFS_I(inode)->state); -	pohmelfs_put_inode(POHMELFS_I(inode)); - -	return 0; -} - -/* - * Root capabilities response: export statistics - * like used and available size, number of files and dirs, - * permissions. - */ -static int pohmelfs_root_cap_response(struct netfs_state *st) -{ -	struct netfs_cmd *cmd = &st->cmd; -	struct netfs_root_capabilities *cap; -	struct pohmelfs_sb *psb = st->psb; - -	if (cmd->size != sizeof(struct netfs_root_capabilities)) { -		psb->flags = EPROTO; -		wake_up(&psb->wait); -		return -EPROTO; -	} - -	cap = st->data; - -	netfs_convert_root_capabilities(cap); - -	if (psb->total_size < cap->used + cap->avail) -		psb->total_size = cap->used + cap->avail; -	if (cap->avail) -		psb->avail_size = cap->avail; -	psb->state_flags = cap->flags; - -	if (psb->state_flags & POHMELFS_FLAGS_RO) { -		psb->sb->s_flags |= MS_RDONLY; -		printk(KERN_INFO "Mounting POHMELFS (%d) read-only.\n", psb->idx); -	} - -	if (psb->state_flags & POHMELFS_FLAGS_XATTR) -		printk(KERN_INFO "Mounting POHMELFS (%d) " -			"with extended attributes support.\n", psb->idx); - -	if (atomic_long_read(&psb->total_inodes) <= 1) -		atomic_long_set(&psb->total_inodes, cap->nr_files); - -	dprintk("%s: total: %llu, avail: %llu, flags: %llx, inodes: %llu.\n", -		__func__, psb->total_size, psb->avail_size, psb->state_flags, cap->nr_files); - -	psb->flags = 0; -	wake_up(&psb->wait); -	return 0; -} - -/* - * Crypto capabilities of the server, where it says that - * it supports or does not requested hash/cipher algorithms. - */ -static int pohmelfs_crypto_cap_response(struct netfs_state *st) -{ -	struct netfs_cmd *cmd = &st->cmd; -	struct netfs_crypto_capabilities *cap; -	struct pohmelfs_sb *psb = st->psb; -	int err = 0; - -	if (cmd->size != sizeof(struct netfs_crypto_capabilities)) { -		psb->flags = EPROTO; -		wake_up(&psb->wait); -		return -EPROTO; -	} - -	cap = st->data; - -	dprintk("%s: cipher '%s': %s, hash: '%s': %s.\n", -			__func__, -			psb->cipher_string, (cap->cipher_strlen) ? "SUPPORTED" : "NOT SUPPORTED", -			psb->hash_string, (cap->hash_strlen) ? "SUPPORTED" : "NOT SUPPORTED"); - -	if (!cap->hash_strlen) { -		if (psb->hash_strlen && psb->crypto_fail_unsupported) -			err = -ENOTSUPP; -		psb->hash_strlen = 0; -		kfree(psb->hash_string); -		psb->hash_string = NULL; -	} - -	if (!cap->cipher_strlen) { -		if (psb->cipher_strlen && psb->crypto_fail_unsupported) -			err = -ENOTSUPP; -		psb->cipher_strlen = 0; -		kfree(psb->cipher_string); -		psb->cipher_string = NULL; -	} - -	return err; -} - -/* - * Capabilities handshake response. - */ -static int pohmelfs_capabilities_response(struct netfs_state *st) -{ -	struct netfs_cmd *cmd = &st->cmd; -	int err = 0; - -	err = pohmelfs_data_recv(st, st->data, cmd->size); -	if (err) -		return err; - -	switch (cmd->id) { -	case POHMELFS_CRYPTO_CAPABILITIES: -			return pohmelfs_crypto_cap_response(st); -	case POHMELFS_ROOT_CAPABILITIES: -			return pohmelfs_root_cap_response(st); -	default: -			break; -	} -	return -EINVAL; -} - -/* - * Receiving extended attribute. - * Does not work properly if received size is more than requested one, - * it should not happen with current request/reply model though. - */ -static int pohmelfs_getxattr_response(struct netfs_state *st) -{ -	struct pohmelfs_sb *psb = st->psb; -	struct netfs_cmd *cmd = &st->cmd; -	struct pohmelfs_mcache *m; -	short error = (signed short)cmd->ext, err; -	unsigned int sz, total_size; - -	m = pohmelfs_mcache_search(psb, cmd->id); - -	dprintk("%s: id: %llu, gen: %llu, err: %d.\n", -		__func__, cmd->id, (m) ? m->gen : 0, error); - -	if (!m) { -		printk("%s: failed to find getxattr cache entry: id: %llu.\n", __func__, cmd->id); -		return -ENOENT; -	} - -	if (cmd->size) { -		sz = min_t(unsigned int, cmd->size, m->size); -		err = pohmelfs_data_recv_and_check(st, m->data, sz); -		if (err) { -			error = err; -			goto out; -		} - -		m->size = sz; -		total_size = cmd->size - sz; - -		while (total_size) { -			sz = min(total_size, st->size); - -			err = pohmelfs_data_recv_and_check(st, st->data, sz); -			if (err) { -				error = err; -				break; -			} - -			total_size -= sz; -		} -	} - -out: -	m->err = error; -	complete(&m->complete); -	pohmelfs_mcache_put(psb, m); - -	return error; -} - -int pohmelfs_data_lock_response(struct netfs_state *st) -{ -	struct pohmelfs_sb *psb = st->psb; -	struct netfs_cmd *cmd = &st->cmd; -	struct pohmelfs_mcache *m; -	short err = (signed short)cmd->ext; -	u64 id = cmd->id; - -	m = pohmelfs_mcache_search(psb, id); - -	dprintk("%s: id: %llu, gen: %llu, err: %d.\n", -		__func__, cmd->id, (m) ? m->gen : 0, err); - -	if (!m) { -		pohmelfs_data_recv(st, st->data, cmd->size); -		printk("%s: failed to find data lock response: id: %llu.\n", __func__, cmd->id); -		return -ENOENT; -	} - -	if (cmd->size) -		err = pohmelfs_data_recv_and_check(st, &m->info, cmd->size); - -	m->err = err; -	complete(&m->complete); -	pohmelfs_mcache_put(psb, m); - -	return err; -} - -static void __inline__ netfs_state_reset(struct netfs_state *st) -{ -	netfs_state_lock_send(st); -	netfs_state_exit(st); -	netfs_state_init(st); -	netfs_state_unlock_send(st); -} - -/* - * Main receiving function, called from dedicated kernel thread. - */ -static int pohmelfs_recv(void *data) -{ -	int err = -EINTR; -	struct netfs_state *st = data; -	struct netfs_cmd *cmd = &st->cmd; - -	while (!kthread_should_stop()) { -		/* -		 * If socket will be reset after this statement, then -		 * pohmelfs_data_recv() will just fail and loop will -		 * start again, so it can be done without any locks. -		 * -		 * st->read_socket is needed to prevents state machine -		 * breaking between this data reading and subsequent one -		 * in protocol specific functions during connection reset. -		 * In case of reset we have to read next command and do -		 * not expect data for old command to magically appear in -		 * new connection. -		 */ -		st->read_socket = st->socket; -		err = pohmelfs_data_recv(st, cmd, sizeof(struct netfs_cmd)); -		if (err) { -			msleep(1000); -			continue; -		} - -		netfs_convert_cmd(cmd); - -		dprintk("%s: cmd: %u, id: %llu, start: %llu, size: %u, " -				"ext: %u, csize: %u, cpad: %u.\n", -				__func__, cmd->cmd, cmd->id, cmd->start, -				cmd->size, cmd->ext, cmd->csize, cmd->cpad); - -		if (cmd->csize) { -			struct pohmelfs_crypto_engine *e = &st->eng; - -			if (unlikely(cmd->csize > e->size/2)) { -				netfs_state_reset(st); -				continue; -			} - -			if (e->hash && unlikely(cmd->csize != st->psb->crypto_attached_size)) { -				dprintk("%s: cmd: cmd: %u, id: %llu, start: %llu, size: %u, " -						"csize: %u != digest size %u.\n", -						__func__, cmd->cmd, cmd->id, cmd->start, cmd->size, -						cmd->csize, st->psb->crypto_attached_size); -				netfs_state_reset(st); -				continue; -			} - -			err = pohmelfs_data_recv(st, e->data, cmd->csize); -			if (err) { -				netfs_state_reset(st); -				continue; -			} - -#ifdef CONFIG_POHMELFS_DEBUG -			{ -				unsigned int i; -				unsigned char *hash = e->data; - -				dprintk("%s: received hash: ", __func__); -				for (i = 0; i < cmd->csize; ++i) -					printk("%02x ", hash[i]); - -				printk("\n"); -			} -#endif -			cmd->size -= cmd->csize; -		} - -		/* -		 * This should catch protocol breakage and random garbage instead of commands. -		 */ -		if (unlikely((cmd->size > st->size) && (cmd->cmd != NETFS_XATTR_GET))) { -			netfs_state_reset(st); -			continue; -		} - -		switch (cmd->cmd) { -		case NETFS_READ_PAGE: -				err = pohmelfs_read_page_response(st); -				break; -		case NETFS_READDIR: -				err = pohmelfs_readdir_response(st); -				break; -		case NETFS_LOOKUP: -				err = pohmelfs_lookup_response(st); -				break; -		case NETFS_CREATE: -				err = pohmelfs_create_response(st); -				break; -		case NETFS_REMOVE: -				err = pohmelfs_remove_response(st); -				break; -		case NETFS_TRANS: -				err = pohmelfs_transaction_response(st); -				break; -		case NETFS_PAGE_CACHE: -				err = pohmelfs_page_cache_response(st); -				break; -		case NETFS_CAPABILITIES: -				err = pohmelfs_capabilities_response(st); -				break; -		case NETFS_LOCK: -				err = pohmelfs_data_lock_response(st); -				break; -		case NETFS_XATTR_GET: -				err = pohmelfs_getxattr_response(st); -				break; -		default: -				printk("%s: wrong cmd: %u, id: %llu, start: %llu, size: %u, ext: %u.\n", -					__func__, cmd->cmd, cmd->id, cmd->start, cmd->size, cmd->ext); -				netfs_state_reset(st); -				break; -		} -	} - -	while (!kthread_should_stop()) -		schedule_timeout_uninterruptible(msecs_to_jiffies(10)); - -	return err; -} - -int netfs_state_init(struct netfs_state *st) -{ -	int err; -	struct pohmelfs_ctl *ctl = &st->ctl; - -	err = sock_create(ctl->addr.sa_family, ctl->type, ctl->proto, &st->socket); -	if (err) { -		printk("%s: failed to create a socket: family: %d, type: %d, proto: %d, err: %d.\n", -				__func__, ctl->addr.sa_family, ctl->type, ctl->proto, err); -		goto err_out_exit; -	} - -	st->socket->sk->sk_allocation = GFP_NOIO; -	st->socket->sk->sk_sndtimeo = st->socket->sk->sk_rcvtimeo = msecs_to_jiffies(60000); - -	err = kernel_connect(st->socket, (struct sockaddr *)&ctl->addr, ctl->addrlen, 0); -	if (err) { -		printk("%s: failed to connect to server: idx: %u, err: %d.\n", -				__func__, st->psb->idx, err); -		goto err_out_release; -	} -	st->socket->sk->sk_sndtimeo = st->socket->sk->sk_rcvtimeo = msecs_to_jiffies(60000); - -	err = netfs_poll_init(st); -	if (err) -		goto err_out_release; - -	if (st->socket->ops->family == AF_INET) { -		struct sockaddr_in *sin = (struct sockaddr_in *)&ctl->addr; -		printk(KERN_INFO "%s: (re)connected to peer %pi4:%d.\n", __func__, -			&sin->sin_addr.s_addr, ntohs(sin->sin_port)); -	} else if (st->socket->ops->family == AF_INET6) { -		struct sockaddr_in6 *sin = (struct sockaddr_in6 *)&ctl->addr; -		printk(KERN_INFO "%s: (re)connected to peer %pi6:%d", __func__, -				&sin->sin6_addr, ntohs(sin->sin6_port)); -	} - -	return 0; - -err_out_release: -	sock_release(st->socket); -err_out_exit: -	st->socket = NULL; -	return err; -} - -void netfs_state_exit(struct netfs_state *st) -{ -	if (st->socket) { -		netfs_poll_exit(st); -		st->socket->ops->shutdown(st->socket, 2); - -		if (st->socket->ops->family == AF_INET) { -			struct sockaddr_in *sin = (struct sockaddr_in *)&st->ctl.addr; -			printk(KERN_INFO "%s: disconnected from peer %pi4:%d.\n", __func__, -				&sin->sin_addr.s_addr, ntohs(sin->sin_port)); -		} else if (st->socket->ops->family == AF_INET6) { -			struct sockaddr_in6 *sin = (struct sockaddr_in6 *)&st->ctl.addr; -			printk(KERN_INFO "%s: disconnected from peer %pi6:%d", __func__, -				&sin->sin6_addr, ntohs(sin->sin6_port)); -		} - -		sock_release(st->socket); -		st->socket = NULL; -		st->read_socket = NULL; -		st->need_reset = 0; -	} -} - -int pohmelfs_state_init_one(struct pohmelfs_sb *psb, struct pohmelfs_config *conf) -{ -	struct netfs_state *st = &conf->state; -	int err = -ENOMEM; - -	mutex_init(&st->__state_lock); -	mutex_init(&st->__state_send_lock); -	init_waitqueue_head(&st->thread_wait); - -	st->psb = psb; -	st->trans_root = RB_ROOT; -	mutex_init(&st->trans_lock); - -	st->size = psb->trans_data_size; -	st->data = kmalloc(st->size, GFP_KERNEL); -	if (!st->data) -		goto err_out_exit; - -	if (psb->perform_crypto) { -		err = pohmelfs_crypto_engine_init(&st->eng, psb); -		if (err) -			goto err_out_free_data; -	} - -	err = netfs_state_init(st); -	if (err) -		goto err_out_free_engine; - -	st->thread = kthread_run(pohmelfs_recv, st, "pohmelfs/%u", psb->idx); -	if (IS_ERR(st->thread)) { -		err = PTR_ERR(st->thread); -		goto err_out_netfs_exit; -	} - -	if (!psb->active_state) -		psb->active_state = conf; - -	dprintk("%s: conf: %p, st: %p, socket: %p.\n", -			__func__, conf, st, st->socket); -	return 0; - -err_out_netfs_exit: -	netfs_state_exit(st); -err_out_free_engine: -	pohmelfs_crypto_engine_exit(&st->eng); -err_out_free_data: -	kfree(st->data); -err_out_exit: -	return err; - -} - -void pohmelfs_state_flush_transactions(struct netfs_state *st) -{ -	struct rb_node *rb_node; -	struct netfs_trans_dst *dst; - -	mutex_lock(&st->trans_lock); -	for (rb_node = rb_first(&st->trans_root); rb_node; ) { -		dst = rb_entry(rb_node, struct netfs_trans_dst, state_entry); -		rb_node = rb_next(rb_node); - -		dst->trans->result = -EINVAL; -		netfs_trans_remove_nolock(dst, st); -		netfs_trans_drop_dst_nostate(dst); -	} -	mutex_unlock(&st->trans_lock); -} - -static void pohmelfs_state_exit_one(struct pohmelfs_config *c) -{ -	struct netfs_state *st = &c->state; - -	dprintk("%s: exiting, st: %p.\n", __func__, st); -	if (st->thread) { -		kthread_stop(st->thread); -		st->thread = NULL; -	} - -	netfs_state_lock_send(st); -	netfs_state_exit(st); -	netfs_state_unlock_send(st); - -	pohmelfs_state_flush_transactions(st); - -	pohmelfs_crypto_engine_exit(&st->eng); -	kfree(st->data); - -	kfree(c); -} - -/* - * Initialize network stack. It searches for given ID in global - * configuration table, this contains information of the remote server - * (address (any supported by socket interface) and port, protocol and so on). - */ -int pohmelfs_state_init(struct pohmelfs_sb *psb) -{ -	int err = -ENOMEM; - -	err = pohmelfs_copy_config(psb); -	if (err) { -		pohmelfs_state_exit(psb); -		return err; -	} - -	return 0; -} - -void pohmelfs_state_exit(struct pohmelfs_sb *psb) -{ -	struct pohmelfs_config *c, *tmp; - -	list_for_each_entry_safe(c, tmp, &psb->state_list, config_entry) { -		list_del(&c->config_entry); -		pohmelfs_state_exit_one(c); -	} -} - -void pohmelfs_switch_active(struct pohmelfs_sb *psb) -{ -	struct pohmelfs_config *c = psb->active_state; - -	if (!list_empty(&psb->state_list)) { -		if (c->config_entry.next != &psb->state_list) { -			psb->active_state = list_entry(c->config_entry.next, -				struct pohmelfs_config, config_entry); -		} else { -			psb->active_state = list_entry(psb->state_list.next, -				struct pohmelfs_config, config_entry); -		} - -		dprintk("%s: empty: %d, active %p -> %p.\n", -			__func__, list_empty(&psb->state_list), c, -			psb->active_state); -	} else -		psb->active_state = NULL; -} - -void pohmelfs_check_states(struct pohmelfs_sb *psb) -{ -	struct pohmelfs_config *c, *tmp; -	LIST_HEAD(delete_list); - -	mutex_lock(&psb->state_lock); -	list_for_each_entry_safe(c, tmp, &psb->state_list, config_entry) { -		if (pohmelfs_config_check(c, psb->idx)) { - -			if (psb->active_state == c) -				pohmelfs_switch_active(psb); -			list_move(&c->config_entry, &delete_list); -		} -	} -	pohmelfs_copy_config(psb); -	mutex_unlock(&psb->state_lock); - -	list_for_each_entry_safe(c, tmp, &delete_list, config_entry) { -		list_del(&c->config_entry); -		pohmelfs_state_exit_one(c); -	} -} diff --git a/drivers/staging/pohmelfs/netfs.h b/drivers/staging/pohmelfs/netfs.h deleted file mode 100644 index f26894f2a57..00000000000 --- a/drivers/staging/pohmelfs/netfs.h +++ /dev/null @@ -1,919 +0,0 @@ -/* - * 2007+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net> - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU General Public License for more details. - */ - -#ifndef __NETFS_H -#define __NETFS_H - -#include <linux/types.h> -#include <linux/connector.h> -#include <linux/backing-dev.h> - -#define POHMELFS_CN_IDX			5 -#define POHMELFS_CN_VAL			0 - -#define POHMELFS_CTLINFO_ACK		1 -#define POHMELFS_NOINFO_ACK		2 - -#define POHMELFS_NULL_IDX		65535 - -/* - * Network command structure. - * Will be extended. - */ -struct netfs_cmd { -	__u16			cmd;	/* Command number */ -	__u16			csize;	/* Attached crypto information size */ -	__u16			cpad;	/* Attached padding size */ -	__u16			ext;	/* External flags */ -	__u32			size;	/* Size of the attached data */ -	__u32			trans;	/* Transaction id */ -	__u64			id;	/* Object ID to operate on. Used for feedback.*/ -	__u64			start;	/* Start of the object. */ -	__u64			iv;	/* IV sequence */ -	__u8			data[0]; -}; - -static inline void netfs_convert_cmd(struct netfs_cmd *cmd) -{ -	cmd->id = __be64_to_cpu(cmd->id); -	cmd->start = __be64_to_cpu(cmd->start); -	cmd->iv = __be64_to_cpu(cmd->iv); -	cmd->cmd = __be16_to_cpu(cmd->cmd); -	cmd->ext = __be16_to_cpu(cmd->ext); -	cmd->csize = __be16_to_cpu(cmd->csize); -	cmd->cpad = __be16_to_cpu(cmd->cpad); -	cmd->size = __be32_to_cpu(cmd->size); -} - -#define NETFS_TRANS_SINGLE_DST		(1<<0) - -enum { -	NETFS_READDIR	= 1,	/* Read directory for given inode number */ -	NETFS_READ_PAGE,	/* Read data page from the server */ -	NETFS_WRITE_PAGE,	/* Write data page to the server */ -	NETFS_CREATE,		/* Create directory entry */ -	NETFS_REMOVE,		/* Remove directory entry */ - -	NETFS_LOOKUP,		/* Lookup single object */ -	NETFS_LINK,		/* Create a link */ -	NETFS_TRANS,		/* Transaction */ -	NETFS_OPEN,		/* Open intent */ -	NETFS_INODE_INFO,	/* Metadata cache coherency synchronization message */ - -	NETFS_PAGE_CACHE,	/* Page cache invalidation message */ -	NETFS_READ_PAGES,	/* Read multiple contiguous pages in one go */ -	NETFS_RENAME,		/* Rename object */ -	NETFS_CAPABILITIES,	/* Capabilities of the client, for example supported crypto */ -	NETFS_LOCK,		/* Distributed lock message */ - -	NETFS_XATTR_SET,	/* Set extended attribute */ -	NETFS_XATTR_GET,	/* Get extended attribute */ -	NETFS_CMD_MAX -}; - -enum { -	POHMELFS_FLAGS_ADD = 0, /* Network state control message for ADD */ -	POHMELFS_FLAGS_DEL,     /* Network state control message for DEL */ -	POHMELFS_FLAGS_SHOW,    /* Network state control message for SHOW */ -	POHMELFS_FLAGS_CRYPTO,	/* Crypto data control message */ -	POHMELFS_FLAGS_MODIFY,	/* Network state modification message */ -	POHMELFS_FLAGS_DUMP,	/* Network state control message for SHOW ALL */ -	POHMELFS_FLAGS_FLUSH,	/* Network state control message for FLUSH */ -}; - -/* - * Always wanted to copy it from socket headers into public one, - * since they are __KERNEL__ protected there. - */ -#define _K_SS_MAXSIZE	128 - -struct saddr { -	unsigned short		sa_family; -	char			addr[_K_SS_MAXSIZE]; -}; - -enum { -	POHMELFS_CRYPTO_HASH = 0, -	POHMELFS_CRYPTO_CIPHER, -}; - -struct pohmelfs_crypto { -	unsigned int		idx;		/* Config index */ -	unsigned short		strlen;		/* Size of the attached crypto string including 0-byte -						 * "cbc(aes)" for example */ -	unsigned short		type;		/* HMAC, cipher, both */ -	unsigned int		keysize;	/* Key size */ -	unsigned char		data[0];	/* Algorithm string, key and IV */ -}; - -#define POHMELFS_IO_PERM_READ		(1<<0) -#define POHMELFS_IO_PERM_WRITE		(1<<1) - -/* - * Configuration command used to create table of different remote servers. - */ -struct pohmelfs_ctl { -	__u32			idx;		/* Config index */ -	__u32			type;		/* Socket type */ -	__u32			proto;		/* Socket protocol */ -	__u16			addrlen;	/* Size of the address */ -	__u16			perm;		/* IO permission */ -	__u16			prio;		/* IO priority */ -	struct saddr		addr;		/* Remote server address */ -}; - -/* - * Ack for userspace about requested command. - */ -struct pohmelfs_cn_ack { -	struct cn_msg		msg; -	int			error; -	int			msg_num; -	int			unused[3]; -	struct pohmelfs_ctl	ctl; -}; - -/* - * Inode info structure used to sync with server. - * Check what stat() returns. - */ -struct netfs_inode_info { -	unsigned int		mode; -	unsigned int		nlink; -	unsigned int		uid; -	unsigned int		gid; -	unsigned int		blocksize; -	unsigned int		padding; -	__u64			ino; -	__u64			blocks; -	__u64			rdev; -	__u64			size; -	__u64			version; -}; - -static inline void netfs_convert_inode_info(struct netfs_inode_info *info) -{ -	info->mode = __cpu_to_be32(info->mode); -	info->nlink = __cpu_to_be32(info->nlink); -	info->uid = __cpu_to_be32(info->uid); -	info->gid = __cpu_to_be32(info->gid); -	info->blocksize = __cpu_to_be32(info->blocksize); -	info->blocks = __cpu_to_be64(info->blocks); -	info->rdev = __cpu_to_be64(info->rdev); -	info->size = __cpu_to_be64(info->size); -	info->version = __cpu_to_be64(info->version); -	info->ino = __cpu_to_be64(info->ino); -} - -/* - * Cache state machine. - */ -enum { -	NETFS_COMMAND_PENDING = 0,	/* Command is being executed */ -	NETFS_INODE_REMOTE_SYNCED,	/* Inode was synced to server */ -	NETFS_INODE_REMOTE_DIR_SYNCED,	/* Inode (directory) was synced from the server */ -	NETFS_INODE_OWNED,		/* Inode is owned by given host */ -	NETFS_INODE_NEED_FLUSH,		/* Inode has to be flushed to the server */ -}; - -/* - * POHMELFS capabilities: information about supported - * crypto operations (hash/cipher, modes, key sizes and so on), - * root information (used/available size, number of objects, permissions) - */ -enum pohmelfs_capabilities { -	POHMELFS_CRYPTO_CAPABILITIES = 0, -	POHMELFS_ROOT_CAPABILITIES, -}; - -/* Read-only mount */ -#define POHMELFS_FLAGS_RO		(1<<0) -/* Extended attributes support on/off */ -#define POHMELFS_FLAGS_XATTR		(1<<1) - -struct netfs_root_capabilities { -	__u64			nr_files; -	__u64			used, avail; -	__u64			flags; -}; - -static inline void netfs_convert_root_capabilities(struct netfs_root_capabilities *cap) -{ -	cap->nr_files = __cpu_to_be64(cap->nr_files); -	cap->used = __cpu_to_be64(cap->used); -	cap->avail = __cpu_to_be64(cap->avail); -	cap->flags = __cpu_to_be64(cap->flags); -} - -struct netfs_crypto_capabilities { -	unsigned short		hash_strlen;	/* Hash string length, like "hmac(sha1) including 0 byte "*/ -	unsigned short		cipher_strlen;	/* Cipher string length with the same format */ -	unsigned int		cipher_keysize;	/* Cipher key size */ -}; - -static inline void netfs_convert_crypto_capabilities(struct netfs_crypto_capabilities *cap) -{ -	cap->hash_strlen = __cpu_to_be16(cap->hash_strlen); -	cap->cipher_strlen = __cpu_to_be16(cap->cipher_strlen); -	cap->cipher_keysize = __cpu_to_be32(cap->cipher_keysize); -} - -enum pohmelfs_lock_type { -	POHMELFS_LOCK_GRAB	= (1<<15), - -	POHMELFS_READ_LOCK	= 0, -	POHMELFS_WRITE_LOCK, -}; - -struct netfs_lock { -	__u64			start; -	__u64			ino; -	__u32			size; -	__u32			type; -}; - -static inline void netfs_convert_lock(struct netfs_lock *lock) -{ -	lock->start = __cpu_to_be64(lock->start); -	lock->ino = __cpu_to_be64(lock->ino); -	lock->size = __cpu_to_be32(lock->size); -	lock->type = __cpu_to_be32(lock->type); -} - -#ifdef __KERNEL__ - -#include <linux/kernel.h> -#include <linux/completion.h> -#include <linux/rbtree.h> -#include <linux/net.h> -#include <linux/poll.h> - -/* - * Private POHMELFS cache of objects in directory. - */ -struct pohmelfs_name { -	struct rb_node		hash_node; - -	struct list_head	sync_create_entry; - -	u64			ino; - -	u32			hash; -	u32			mode; -	u32			len; - -	char			*data; -}; - -/* - * POHMELFS inode. Main object. - */ -struct pohmelfs_inode { -	struct list_head	inode_entry;		/* Entry in superblock list. -							 * Objects which are not bound to dentry require to be dropped -							 * in ->put_super() -							 */ -	struct rb_root		hash_root;		/* The same, but indexed by name hash and len */ -	struct mutex		offset_lock;		/* Protect both above trees */ - -	struct list_head	sync_create_list;	/* List of created but not yet synced to the server children */ - -	unsigned int		drop_count; - -	int			lock_type;		/* How this inode is locked: read or write */ - -	int			error;			/* Transaction error for given inode */ - -	long			state;			/* State machine above */ - -	u64			ino;			/* Inode number */ -	u64			total_len;		/* Total length of all children names, used to create offsets */ - -	struct inode		vfs_inode; -}; - -struct netfs_trans; -typedef int (*netfs_trans_complete_t)(struct page **pages, unsigned int page_num, -		void *private, int err); - -struct netfs_state; -struct pohmelfs_sb; - -struct netfs_trans { -	/* -	 * Transaction header and attached contiguous data live here. -	 */ -	struct iovec			iovec; - -	/* -	 * Pages attached to transaction. -	 */ -	struct page			**pages; - -	/* -	 * List and protecting lock for transaction destination -	 * network states. -	 */ -	spinlock_t			dst_lock; -	struct list_head		dst_list; - -	/* -	 * Number of users for given transaction. -	 * For example each network state attached to transaction -	 * via dst_list increases it. -	 */ -	atomic_t			refcnt; - -	/* -	 * Number of pages attached to given transaction. -	 * Some slots in above page array can be NULL, since -	 * for example page can be under writeback already, -	 * so we skip it in this transaction. -	 */ -	unsigned int			page_num; - -	/* -	 * Transaction flags: single dst or broadcast and so on. -	 */ -	unsigned int			flags; - -	/* -	 * Size of the data, which can be placed into -	 * iovec.iov_base area. -	 */ -	unsigned int			total_size; - -	/* -	 * Number of pages to be sent to remote server. -	 * Usually equal to above page_num, but in case of partial -	 * writeback it can accumulate only pages already completed -	 * previous writeback. -	 */ -	unsigned int			attached_pages; - -	/* -	 * Attached number of bytes in all above pages. -	 */ -	unsigned int			attached_size; - -	/* -	 * Unique transacton generation number. -	 * Used as identity in the network state tree of transactions. -	 */ -	unsigned int			gen; - -	/* -	 * Transaction completion status. -	 */ -	int				result; - -	/* -	 * Superblock this transaction belongs to -	 */ -	struct pohmelfs_sb		*psb; - -	/* -	 * Crypto engine, which processed this transaction. -	 * Can be not NULL only if crypto engine holds encrypted pages. -	 */ -	struct pohmelfs_crypto_engine	*eng; - -	/* Private data */ -	void				*private; - -	/* Completion callback, invoked just before transaction is destroyed */ -	netfs_trans_complete_t		complete; -}; - -static inline int netfs_trans_cur_len(struct netfs_trans *t) -{ -	return (signed)(t->total_size - t->iovec.iov_len); -} - -static inline void *netfs_trans_current(struct netfs_trans *t) -{ -	return t->iovec.iov_base + t->iovec.iov_len; -} - -struct netfs_trans *netfs_trans_alloc(struct pohmelfs_sb *psb, unsigned int size, -		unsigned int flags, unsigned int nr); -void netfs_trans_free(struct netfs_trans *t); -int netfs_trans_finish(struct netfs_trans *t, struct pohmelfs_sb *psb); -int netfs_trans_finish_send(struct netfs_trans *t, struct pohmelfs_sb *psb); - -static inline void netfs_trans_reset(struct netfs_trans *t) -{ -	t->complete = NULL; -} - -struct netfs_trans_dst { -	struct list_head		trans_entry; -	struct rb_node			state_entry; - -	unsigned long			send_time; - -	/* -	 * Times this transaction was resent to its old or new, -	 * depending on flags, destinations. When it reaches maximum -	 * allowed number, specified in superblock->trans_retries, -	 * transaction will be freed with ETIMEDOUT error. -	 */ -	unsigned int			retries; - -	struct netfs_trans		*trans; -	struct netfs_state		*state; -}; - -struct netfs_trans_dst *netfs_trans_search(struct netfs_state *st, unsigned int gen); -void netfs_trans_drop_dst(struct netfs_trans_dst *dst); -void netfs_trans_drop_dst_nostate(struct netfs_trans_dst *dst); -void netfs_trans_drop_trans(struct netfs_trans *t, struct netfs_state *st); -void netfs_trans_drop_last(struct netfs_trans *t, struct netfs_state *st); -int netfs_trans_resend(struct netfs_trans *t, struct pohmelfs_sb *psb); -int netfs_trans_remove_nolock(struct netfs_trans_dst *dst, struct netfs_state *st); - -int netfs_trans_init(void); -void netfs_trans_exit(void); - -struct pohmelfs_crypto_engine { -	u64				iv;		/* Crypto IV for current operation */ -	unsigned long			timeout;	/* Crypto waiting timeout */ -	unsigned int			size;		/* Size of crypto scratchpad */ -	void				*data;		/* Temporal crypto scratchpad */ -	/* -	 * Crypto operations performed on objects. -	 */ -	struct crypto_hash		*hash; -	struct crypto_ablkcipher	*cipher; - -	struct pohmelfs_crypto_thread	*thread;	/* Crypto thread which hosts this engine */ - -	struct page			**pages; -	unsigned int			page_num; -}; - -struct pohmelfs_crypto_thread { -	struct list_head		thread_entry; - -	struct task_struct		*thread; -	struct pohmelfs_sb		*psb; - -	struct pohmelfs_crypto_engine	eng; - -	struct netfs_trans		*trans; - -	wait_queue_head_t		wait; -	int				error; - -	unsigned int			size; -	struct page			*page; -}; - -void pohmelfs_crypto_thread_make_ready(struct pohmelfs_crypto_thread *th); - -/* - * Network state, attached to one server. - */ -struct netfs_state { -	struct mutex		__state_lock;		/* Can not allow to use the same socket simultaneously */ -	struct mutex		__state_send_lock; -	struct netfs_cmd	cmd;			/* Cached command */ -	struct netfs_inode_info	info;			/* Cached inode info */ - -	void			*data;			/* Cached some data */ -	unsigned int		size;			/* Size of that data */ - -	struct pohmelfs_sb	*psb;			/* Superblock */ - -	struct task_struct	*thread;		/* Async receiving thread */ - -	/* Waiting/polling machinery */ -	wait_queue_t		wait; -	wait_queue_head_t	*whead; -	wait_queue_head_t	thread_wait; - -	struct mutex		trans_lock; -	struct rb_root		trans_root; - -	struct pohmelfs_ctl	ctl;			/* Remote peer */ - -	struct socket		*socket;		/* Socket object */ -	struct socket		*read_socket;		/* Cached pointer to socket object. -							 * Used to determine if between lock drops socket was changed. -							 * Never used to read data or any kind of access. -							 */ -	/* -	 * Crypto engines to process incoming data. -	 */ -	struct pohmelfs_crypto_engine	eng; - -	int			need_reset; -}; - -int netfs_state_init(struct netfs_state *st); -void netfs_state_exit(struct netfs_state *st); - -static inline void netfs_state_lock_send(struct netfs_state *st) -{ -	mutex_lock(&st->__state_send_lock); -} - -static inline int netfs_state_trylock_send(struct netfs_state *st) -{ -	return mutex_trylock(&st->__state_send_lock); -} - -static inline void netfs_state_unlock_send(struct netfs_state *st) -{ -	BUG_ON(!mutex_is_locked(&st->__state_send_lock)); - -	mutex_unlock(&st->__state_send_lock); -} - -static inline void netfs_state_lock(struct netfs_state *st) -{ -	mutex_lock(&st->__state_lock); -} - -static inline void netfs_state_unlock(struct netfs_state *st) -{ -	BUG_ON(!mutex_is_locked(&st->__state_lock)); - -	mutex_unlock(&st->__state_lock); -} - -static inline unsigned int netfs_state_poll(struct netfs_state *st) -{ -	unsigned int revents = POLLHUP | POLLERR; - -	netfs_state_lock(st); -	if (st->socket) -		revents = st->socket->ops->poll(NULL, st->socket, NULL); -	netfs_state_unlock(st); - -	return revents; -} - -struct pohmelfs_config; - -struct pohmelfs_sb { -	struct rb_root		mcache_root; -	struct mutex		mcache_lock; -	atomic_long_t		mcache_gen; -	unsigned long		mcache_timeout; - -	unsigned int		idx; - -	unsigned int		trans_retries; - -	atomic_t		trans_gen; - -	unsigned int		crypto_attached_size; -	unsigned int		crypto_align_size; - -	unsigned int		crypto_fail_unsupported; - -	unsigned int		crypto_thread_num; -	struct list_head	crypto_active_list, crypto_ready_list; -	struct mutex		crypto_thread_lock; - -	unsigned int		trans_max_pages; -	unsigned long		trans_data_size; -	unsigned long		trans_timeout; - -	unsigned long		drop_scan_timeout; -	unsigned long		trans_scan_timeout; - -	unsigned long		wait_on_page_timeout; - -	struct list_head	flush_list; -	struct list_head	drop_list; -	spinlock_t		ino_lock; -	u64			ino; - -	/* -	 * Remote nodes POHMELFS connected to. -	 */ -	struct list_head	state_list; -	struct mutex		state_lock; - -	/* -	 * Currently active state to request data from. -	 */ -	struct pohmelfs_config	*active_state; - - -	wait_queue_head_t	wait; - -	/* -	 * Timed checks: stale transactions, inodes to be freed and so on. -	 */ -	struct delayed_work	dwork; -	struct delayed_work	drop_dwork; - -	struct super_block	*sb; - -	struct backing_dev_info	bdi; - -	/* -	 * Algorithm strings. -	 */ -	char			*hash_string; -	char			*cipher_string; - -	u8			*hash_key; -	u8			*cipher_key; - -	/* -	 * Algorithm string lengths. -	 */ -	unsigned int		hash_strlen; -	unsigned int		cipher_strlen; -	unsigned int		hash_keysize; -	unsigned int		cipher_keysize; - -	/* -	 * Controls whether to perfrom crypto processing or not. -	 */ -	int			perform_crypto; - -	/* -	 * POHMELFS statistics. -	 */ -	u64			total_size; -	u64			avail_size; -	atomic_long_t		total_inodes; - -	/* -	 * Xattr support, read-only and so on. -	 */ -	u64			state_flags; - -	/* -	 * Temporary storage to detect changes in the wait queue. -	 */ -	long			flags; -}; - -static inline void netfs_trans_update(struct netfs_cmd *cmd, -		struct netfs_trans *t, unsigned int size) -{ -	unsigned int sz = ALIGN(size, t->psb->crypto_align_size); - -	t->iovec.iov_len += sizeof(struct netfs_cmd) + sz; -	cmd->cpad = __cpu_to_be16(sz - size); -} - -static inline struct pohmelfs_sb *POHMELFS_SB(struct super_block *sb) -{ -	return sb->s_fs_info; -} - -static inline struct pohmelfs_inode *POHMELFS_I(struct inode *inode) -{ -	return container_of(inode, struct pohmelfs_inode, vfs_inode); -} - -static inline u64 pohmelfs_new_ino(struct pohmelfs_sb *psb) -{ -	u64 ino; - -	spin_lock(&psb->ino_lock); -	ino = psb->ino++; -	spin_unlock(&psb->ino_lock); - -	return ino; -} - -static inline void pohmelfs_put_inode(struct pohmelfs_inode *pi) -{ -	struct pohmelfs_sb *psb = POHMELFS_SB(pi->vfs_inode.i_sb); - -	spin_lock(&psb->ino_lock); -	list_move_tail(&pi->inode_entry, &psb->drop_list); -	pi->drop_count++; -	spin_unlock(&psb->ino_lock); -} - -struct pohmelfs_config { -	struct list_head	config_entry; - -	struct netfs_state	state; -}; - -struct pohmelfs_config_group { -	/* -	 * Entry in the global config group list. -	 */ -	struct list_head	group_entry; - -	/* -	 * Index of the current group. -	 */ -	unsigned int		idx; -	/* -	 * Number of config_list entries in this group entry. -	 */ -	unsigned int		num_entry; -	/* -	 * Algorithm strings. -	 */ -	char			*hash_string; -	char			*cipher_string; - -	/* -	 * Algorithm string lengths. -	 */ -	unsigned int		hash_strlen; -	unsigned int		cipher_strlen; - -	/* -	 * Key and its size. -	 */ -	unsigned int		hash_keysize; -	unsigned int		cipher_keysize; -	u8			*hash_key; -	u8			*cipher_key; - -	/* -	 * List of config entries (network state info) for given idx. -	 */ -	struct list_head	config_list; -}; - -int __init pohmelfs_config_init(void); -void pohmelfs_config_exit(void); -int pohmelfs_copy_config(struct pohmelfs_sb *psb); -int pohmelfs_copy_crypto(struct pohmelfs_sb *psb); -int pohmelfs_config_check(struct pohmelfs_config *config, int idx); -int pohmelfs_state_init_one(struct pohmelfs_sb *psb, struct pohmelfs_config *conf); - -extern const struct file_operations pohmelfs_dir_fops; -extern const struct inode_operations pohmelfs_dir_inode_ops; - -int pohmelfs_state_init(struct pohmelfs_sb *psb); -void pohmelfs_state_exit(struct pohmelfs_sb *psb); -void pohmelfs_state_flush_transactions(struct netfs_state *st); - -void pohmelfs_fill_inode(struct inode *inode, struct netfs_inode_info *info); - -void pohmelfs_name_del(struct pohmelfs_inode *parent, struct pohmelfs_name *n); -void pohmelfs_free_names(struct pohmelfs_inode *parent); -struct pohmelfs_name *pohmelfs_search_hash(struct pohmelfs_inode *pi, u32 hash); - -void pohmelfs_inode_del_inode(struct pohmelfs_sb *psb, struct pohmelfs_inode *pi); - -struct pohmelfs_inode *pohmelfs_create_entry_local(struct pohmelfs_sb *psb, -	struct pohmelfs_inode *parent, struct qstr *str, u64 start, umode_t mode); - -int pohmelfs_write_create_inode(struct pohmelfs_inode *pi); - -int pohmelfs_write_inode_create(struct inode *inode, struct netfs_trans *trans); -int pohmelfs_remove_child(struct pohmelfs_inode *parent, struct pohmelfs_name *n); - -struct pohmelfs_inode *pohmelfs_new_inode(struct pohmelfs_sb *psb, -		struct pohmelfs_inode *parent, struct qstr *str, -		struct netfs_inode_info *info, int link); - -int pohmelfs_setattr(struct dentry *dentry, struct iattr *attr); -int pohmelfs_setattr_raw(struct inode *inode, struct iattr *attr); - -int pohmelfs_meta_command(struct pohmelfs_inode *pi, unsigned int cmd_op, unsigned int flags, -		netfs_trans_complete_t complete, void *priv, u64 start); -int pohmelfs_meta_command_data(struct pohmelfs_inode *pi, u64 id, unsigned int cmd_op, char *addon, -		unsigned int flags, netfs_trans_complete_t complete, void *priv, u64 start); - -void pohmelfs_check_states(struct pohmelfs_sb *psb); -void pohmelfs_switch_active(struct pohmelfs_sb *psb); - -int pohmelfs_construct_path_string(struct pohmelfs_inode *pi, void *data, int len); -int pohmelfs_path_length(struct pohmelfs_inode *pi); - -struct pohmelfs_crypto_completion { -	struct completion	complete; -	int			error; -}; - -int pohmelfs_trans_crypt(struct netfs_trans *t, struct pohmelfs_sb *psb); -void pohmelfs_crypto_exit(struct pohmelfs_sb *psb); -int pohmelfs_crypto_init(struct pohmelfs_sb *psb); - -int pohmelfs_crypto_engine_init(struct pohmelfs_crypto_engine *e, struct pohmelfs_sb *psb); -void pohmelfs_crypto_engine_exit(struct pohmelfs_crypto_engine *e); - -int pohmelfs_crypto_process_input_data(struct pohmelfs_crypto_engine *e, u64 iv, -		void *data, struct page *page, unsigned int size); -int pohmelfs_crypto_process_input_page(struct pohmelfs_crypto_engine *e, -		struct page *page, unsigned int size, u64 iv); - -static inline u64 pohmelfs_gen_iv(struct netfs_trans *t) -{ -	u64 iv = t->gen; - -	iv <<= 32; -	iv |= ((unsigned long)t) & 0xffffffff; - -	return iv; -} - -int pohmelfs_data_lock(struct pohmelfs_inode *pi, u64 start, u32 size, int type); -int pohmelfs_data_unlock(struct pohmelfs_inode *pi, u64 start, u32 size, int type); -int pohmelfs_data_lock_response(struct netfs_state *st); - -static inline int pohmelfs_need_lock(struct pohmelfs_inode *pi, int type) -{ -	if (test_bit(NETFS_INODE_OWNED, &pi->state)) { -		if (type == pi->lock_type) -			return 0; -		if ((type == POHMELFS_READ_LOCK) && (pi->lock_type == POHMELFS_WRITE_LOCK)) -			return 0; -	} - -	if (!test_bit(NETFS_INODE_REMOTE_SYNCED, &pi->state)) -		return 0; - -	return 1; -} - -int __init pohmelfs_mcache_init(void); -void pohmelfs_mcache_exit(void); - -/* #define CONFIG_POHMELFS_DEBUG */ - -#ifdef CONFIG_POHMELFS_DEBUG -#define dprintka(f, a...) printk(f, ##a) -#define dprintk(f, a...) printk("%d: " f, task_pid_vnr(current), ##a) -#else -#define dprintka(f, a...) do {} while (0) -#define dprintk(f, a...) do {} while (0) -#endif - -static inline void netfs_trans_get(struct netfs_trans *t) -{ -	atomic_inc(&t->refcnt); -} - -static inline void netfs_trans_put(struct netfs_trans *t) -{ -	if (atomic_dec_and_test(&t->refcnt)) { -		dprintk("%s: t: %p, gen: %u, err: %d.\n", -			__func__, t, t->gen, t->result); -		if (t->complete) -			t->complete(t->pages, t->page_num, -				t->private, t->result); -		netfs_trans_free(t); -	} -} - -struct pohmelfs_mcache { -	struct rb_node			mcache_entry; -	struct completion		complete; - -	atomic_t			refcnt; - -	u64				gen; - -	void				*data; -	u64				start; -	u32				size; -	int				err; - -	struct netfs_inode_info		info; -}; - -struct pohmelfs_mcache *pohmelfs_mcache_alloc(struct pohmelfs_sb *psb, u64 start, -		unsigned int size, void *data); -void pohmelfs_mcache_free(struct pohmelfs_sb *psb, struct pohmelfs_mcache *m); -struct pohmelfs_mcache *pohmelfs_mcache_search(struct pohmelfs_sb *psb, u64 gen); -void pohmelfs_mcache_remove_locked(struct pohmelfs_sb *psb, struct pohmelfs_mcache *m); - -static inline void pohmelfs_mcache_get(struct pohmelfs_mcache *m) -{ -	atomic_inc(&m->refcnt); -} - -static inline void pohmelfs_mcache_put(struct pohmelfs_sb *psb, -		struct pohmelfs_mcache *m) -{ -	if (atomic_dec_and_test(&m->refcnt)) -		pohmelfs_mcache_free(psb, m); -} - -/*#define POHMELFS_TRUNCATE_ON_INODE_FLUSH - */ - -#endif /* __KERNEL__*/ - -#endif /* __NETFS_H */ diff --git a/drivers/staging/pohmelfs/path_entry.c b/drivers/staging/pohmelfs/path_entry.c deleted file mode 100644 index 400a9fc386a..00000000000 --- a/drivers/staging/pohmelfs/path_entry.c +++ /dev/null @@ -1,120 +0,0 @@ -/* - * 2007+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net> - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU General Public License for more details. - */ - -#include <linux/module.h> -#include <linux/fs.h> -#include <linux/ktime.h> -#include <linux/fs_struct.h> -#include <linux/pagemap.h> -#include <linux/writeback.h> -#include <linux/mount.h> -#include <linux/mm.h> - -#include "netfs.h" - -#define UNHASHED_OBSCURE_STRING_SIZE		sizeof(" (deleted)") - -/* - * Create path from root for given inode. - * Path is formed as set of stuctures, containing name of the object - * and its inode data (mode, permissions and so on). - */ -int pohmelfs_construct_path_string(struct pohmelfs_inode *pi, void *data, int len) -{ -	struct path path; -	struct dentry *d; -	char *ptr; -	int err = 0, strlen, reduce = 0; - -	d = d_find_alias(&pi->vfs_inode); -	if (!d) { -		printk("%s: no alias, list_empty: %d.\n", __func__, list_empty(&pi->vfs_inode.i_dentry)); -		return -ENOENT; -	} - -	spin_lock(¤t->fs->lock); -	path.mnt = mntget(current->fs->root.mnt); -	spin_unlock(¤t->fs->lock); - -	path.dentry = d; - -	if (!IS_ROOT(d) && d_unhashed(d)) -		reduce = 1; - -	ptr = d_path(&path, data, len); -	if (IS_ERR(ptr)) { -		err = PTR_ERR(ptr); -		goto out; -	} - -	if (reduce && len >= UNHASHED_OBSCURE_STRING_SIZE) { -		char *end = data + len - UNHASHED_OBSCURE_STRING_SIZE; -		*end = '\0'; -	} - -	strlen = len - (ptr - (char *)data); -	memmove(data, ptr, strlen); -	ptr = data; - -	err = strlen; - -	dprintk("%s: dname: '%s', len: %u, maxlen: %u, name: '%s', strlen: %d.\n", -			__func__, d->d_name.name, d->d_name.len, len, ptr, strlen); - -out: -	dput(d); -	mntput(path.mnt); - -	return err; -} - -int pohmelfs_path_length(struct pohmelfs_inode *pi) -{ -	struct dentry *d, *root, *first; -	int len; -	unsigned seq; - -	first = d_find_alias(&pi->vfs_inode); -	if (!first) { -		dprintk("%s: ino: %llu, mode: %o.\n", __func__, pi->ino, pi->vfs_inode.i_mode); -		return -ENOENT; -	} - -	spin_lock(¤t->fs->lock); -	root = dget(current->fs->root.dentry); -	spin_unlock(¤t->fs->lock); - -rename_retry: -	len = 1; /* Root slash */ -	d = first; -	seq = read_seqbegin(&rename_lock); -	rcu_read_lock(); - -	if (!IS_ROOT(d) && d_unhashed(d)) -		len += UNHASHED_OBSCURE_STRING_SIZE; /* Obscure " (deleted)" string */ - -	while (d && d != root && !IS_ROOT(d)) { -		len += d->d_name.len + 1; /* Plus slash */ -		d = d->d_parent; -	} -	rcu_read_unlock(); -	if (read_seqretry(&rename_lock, seq)) -		goto rename_retry; - -	dput(root); -	dput(first); - -	return len + 1; /* Including zero-byte */ -} diff --git a/drivers/staging/pohmelfs/trans.c b/drivers/staging/pohmelfs/trans.c deleted file mode 100644 index 06c1a7451b1..00000000000 --- a/drivers/staging/pohmelfs/trans.c +++ /dev/null @@ -1,706 +0,0 @@ -/* - * 2007+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net> - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU General Public License for more details. - */ - -#include <linux/module.h> -#include <linux/crypto.h> -#include <linux/fs.h> -#include <linux/jhash.h> -#include <linux/hash.h> -#include <linux/ktime.h> -#include <linux/mempool.h> -#include <linux/mm.h> -#include <linux/mount.h> -#include <linux/pagemap.h> -#include <linux/parser.h> -#include <linux/poll.h> -#include <linux/swap.h> -#include <linux/slab.h> -#include <linux/statfs.h> -#include <linux/writeback.h> - -#include "netfs.h" - -static struct kmem_cache *netfs_trans_dst; -static mempool_t *netfs_trans_dst_pool; - -static void netfs_trans_init_static(struct netfs_trans *t, int num, int size) -{ -	t->page_num = num; -	t->total_size = size; -	atomic_set(&t->refcnt, 1); - -	spin_lock_init(&t->dst_lock); -	INIT_LIST_HEAD(&t->dst_list); -} - -static int netfs_trans_send_pages(struct netfs_trans *t, struct netfs_state *st) -{ -	int err = 0; -	unsigned int i, attached_pages = t->attached_pages, ci; -	struct msghdr msg; -	struct page **pages = (t->eng) ? t->eng->pages : t->pages; -	struct page *p; -	unsigned int size; - -	msg.msg_name = NULL; -	msg.msg_namelen = 0; -	msg.msg_control = NULL; -	msg.msg_controllen = 0; -	msg.msg_flags = MSG_WAITALL | MSG_MORE; - -	ci = 0; -	for (i = 0; i < t->page_num; ++i) { -		struct page *page = pages[ci]; -		struct netfs_cmd cmd; -		struct iovec io; - -		p = t->pages[i]; - -		if (!p) -			continue; - -		size = page_private(p); - -		io.iov_base = &cmd; -		io.iov_len = sizeof(struct netfs_cmd); - -		cmd.cmd = NETFS_WRITE_PAGE; -		cmd.ext = 0; -		cmd.id = 0; -		cmd.size = size; -		cmd.start = p->index; -		cmd.start <<= PAGE_CACHE_SHIFT; -		cmd.csize = 0; -		cmd.cpad = 0; -		cmd.iv = pohmelfs_gen_iv(t); - -		netfs_convert_cmd(&cmd); - -		msg.msg_iov = &io; -		msg.msg_iovlen = 1; -		msg.msg_flags = MSG_WAITALL | MSG_MORE; - -		err = kernel_sendmsg(st->socket, &msg, (struct kvec *)msg.msg_iov, 1, sizeof(struct netfs_cmd)); -		if (err <= 0) { -			printk("%s: %d/%d failed to send transaction header: t: %p, gen: %u, err: %d.\n", -					__func__, i, t->page_num, t, t->gen, err); -			if (err == 0) -				err = -ECONNRESET; -			goto err_out; -		} - -		msg.msg_flags = MSG_WAITALL | (attached_pages == 1 ? 0 : -				MSG_MORE); - -		err = kernel_sendpage(st->socket, page, 0, size, msg.msg_flags); -		if (err <= 0) { -			printk("%s: %d/%d failed to send transaction page: t: %p, gen: %u, size: %u, err: %d.\n", -					__func__, i, t->page_num, t, t->gen, size, err); -			if (err == 0) -				err = -ECONNRESET; -			goto err_out; -		} - -		dprintk("%s: %d/%d sent t: %p, gen: %u, page: %p/%p, size: %u.\n", -			__func__, i, t->page_num, t, t->gen, page, p, size); - -		err = 0; -		attached_pages--; -		if (!attached_pages) -			break; -		ci++; - -		continue; - -err_out: -		printk("%s: t: %p, gen: %u, err: %d.\n", __func__, t, t->gen, err); -		netfs_state_exit(st); -		break; -	} - -	return err; -} - -int netfs_trans_send(struct netfs_trans *t, struct netfs_state *st) -{ -	int err; -	struct msghdr msg; - -	BUG_ON(!t->iovec.iov_len); -	BUG_ON(t->iovec.iov_len > 1024*1024*1024); - -	netfs_state_lock_send(st); -	if (!st->socket) { -		err = netfs_state_init(st); -		if (err) -			goto err_out_unlock_return; -	} - -	msg.msg_iov = &t->iovec; -	msg.msg_iovlen = 1; -	msg.msg_name = NULL; -	msg.msg_namelen = 0; -	msg.msg_control = NULL; -	msg.msg_controllen = 0; -	msg.msg_flags = MSG_WAITALL; - -	if (t->attached_pages) -		msg.msg_flags |= MSG_MORE; - -	err = kernel_sendmsg(st->socket, &msg, (struct kvec *)msg.msg_iov, 1, t->iovec.iov_len); -	if (err <= 0) { -		printk("%s: failed to send contig transaction: t: %p, gen: %u, size: %zu, err: %d.\n", -				__func__, t, t->gen, t->iovec.iov_len, err); -		if (err == 0) -			err = -ECONNRESET; -		goto err_out_unlock_return; -	} - -	dprintk("%s: sent %s transaction: t: %p, gen: %u, size: %zu, page_num: %u.\n", -			__func__, (t->page_num) ? "partial" : "full", -			t, t->gen, t->iovec.iov_len, t->page_num); - -	err = 0; -	if (t->attached_pages) -		err = netfs_trans_send_pages(t, st); - -err_out_unlock_return: - -	if (st->need_reset) -		netfs_state_exit(st); - -	netfs_state_unlock_send(st); - -	dprintk("%s: t: %p, gen: %u, err: %d.\n", -		__func__, t, t->gen, err); - -	t->result = err; -	return err; -} - -static inline int netfs_trans_cmp(unsigned int gen, unsigned int new) -{ -	if (gen < new) -		return 1; -	if (gen > new) -		return -1; -	return 0; -} - -struct netfs_trans_dst *netfs_trans_search(struct netfs_state *st, unsigned int gen) -{ -	struct rb_root *root = &st->trans_root; -	struct rb_node *n = root->rb_node; -	struct netfs_trans_dst *tmp, *ret = NULL; -	struct netfs_trans *t; -	int cmp; - -	while (n) { -		tmp = rb_entry(n, struct netfs_trans_dst, state_entry); -		t = tmp->trans; - -		cmp = netfs_trans_cmp(t->gen, gen); -		if (cmp < 0) -			n = n->rb_left; -		else if (cmp > 0) -			n = n->rb_right; -		else { -			ret = tmp; -			break; -		} -	} - -	return ret; -} - -static int netfs_trans_insert(struct netfs_trans_dst *ndst, struct netfs_state *st) -{ -	struct rb_root *root = &st->trans_root; -	struct rb_node **n = &root->rb_node, *parent = NULL; -	struct netfs_trans_dst *ret = NULL, *tmp; -	struct netfs_trans *t = NULL, *new = ndst->trans; -	int cmp; - -	while (*n) { -		parent = *n; - -		tmp = rb_entry(parent, struct netfs_trans_dst, state_entry); -		t = tmp->trans; - -		cmp = netfs_trans_cmp(t->gen, new->gen); -		if (cmp < 0) -			n = &parent->rb_left; -		else if (cmp > 0) -			n = &parent->rb_right; -		else { -			ret = tmp; -			break; -		} -	} - -	if (ret) { -		printk("%s: exist: old: gen: %u, flags: %x, send_time: %lu, " -				"new: gen: %u, flags: %x, send_time: %lu.\n", -			__func__, t->gen, t->flags, ret->send_time, -			new->gen, new->flags, ndst->send_time); -		return -EEXIST; -	} - -	rb_link_node(&ndst->state_entry, parent, n); -	rb_insert_color(&ndst->state_entry, root); -	ndst->send_time = jiffies; - -	return 0; -} - -int netfs_trans_remove_nolock(struct netfs_trans_dst *dst, struct netfs_state *st) -{ -	if (dst && dst->state_entry.rb_parent_color) { -		rb_erase(&dst->state_entry, &st->trans_root); -		dst->state_entry.rb_parent_color = 0; -		return 1; -	} -	return 0; -} - -static int netfs_trans_remove_state(struct netfs_trans_dst *dst) -{ -	int ret; -	struct netfs_state *st = dst->state; - -	mutex_lock(&st->trans_lock); -	ret = netfs_trans_remove_nolock(dst, st); -	mutex_unlock(&st->trans_lock); - -	return ret; -} - -/* - * Create new destination for given transaction associated with given network state. - * Transaction's reference counter is bumped and will be dropped when either - * reply is received or when async timeout detection task will fail resending - * and drop transaction. - */ -static int netfs_trans_push_dst(struct netfs_trans *t, struct netfs_state *st) -{ -	struct netfs_trans_dst *dst; -	int err; - -	dst = mempool_alloc(netfs_trans_dst_pool, GFP_KERNEL); -	if (!dst) -		return -ENOMEM; - -	dst->retries = 0; -	dst->send_time = 0; -	dst->state = st; -	dst->trans = t; -	netfs_trans_get(t); - -	mutex_lock(&st->trans_lock); -	err = netfs_trans_insert(dst, st); -	mutex_unlock(&st->trans_lock); - -	if (err) -		goto err_out_free; - -	spin_lock(&t->dst_lock); -	list_add_tail(&dst->trans_entry, &t->dst_list); -	spin_unlock(&t->dst_lock); - -	return 0; - -err_out_free: -	t->result = err; -	netfs_trans_put(t); -	mempool_free(dst, netfs_trans_dst_pool); -	return err; -} - -static void netfs_trans_free_dst(struct netfs_trans_dst *dst) -{ -	netfs_trans_put(dst->trans); -	mempool_free(dst, netfs_trans_dst_pool); -} - -static void netfs_trans_remove_dst(struct netfs_trans_dst *dst) -{ -	if (netfs_trans_remove_state(dst)) -		netfs_trans_free_dst(dst); -} - -/* - * Drop destination transaction entry when we know it. - */ -void netfs_trans_drop_dst(struct netfs_trans_dst *dst) -{ -	struct netfs_trans *t = dst->trans; - -	spin_lock(&t->dst_lock); -	list_del_init(&dst->trans_entry); -	spin_unlock(&t->dst_lock); - -	netfs_trans_remove_dst(dst); -} - -/* - * Drop destination transaction entry when we know it and when we - * already removed dst from state tree. - */ -void netfs_trans_drop_dst_nostate(struct netfs_trans_dst *dst) -{ -	struct netfs_trans *t = dst->trans; - -	spin_lock(&t->dst_lock); -	list_del_init(&dst->trans_entry); -	spin_unlock(&t->dst_lock); - -	netfs_trans_free_dst(dst); -} - -/* - * This drops destination transaction entry from appropriate network state - * tree and drops related reference counter. It is possible that transaction - * will be freed here if its reference counter hits zero. - * Destination transaction entry will be freed. - */ -void netfs_trans_drop_trans(struct netfs_trans *t, struct netfs_state *st) -{ -	struct netfs_trans_dst *dst, *tmp, *ret = NULL; - -	spin_lock(&t->dst_lock); -	list_for_each_entry_safe(dst, tmp, &t->dst_list, trans_entry) { -		if (dst->state == st) { -			ret = dst; -			list_del(&dst->trans_entry); -			break; -		} -	} -	spin_unlock(&t->dst_lock); - -	if (ret) -		netfs_trans_remove_dst(ret); -} - -/* - * This drops destination transaction entry from appropriate network state - * tree and drops related reference counter. It is possible that transaction - * will be freed here if its reference counter hits zero. - * Destination transaction entry will be freed. - */ -void netfs_trans_drop_last(struct netfs_trans *t, struct netfs_state *st) -{ -	struct netfs_trans_dst *dst, *tmp, *ret; - -	spin_lock(&t->dst_lock); -	ret = list_entry(t->dst_list.prev, struct netfs_trans_dst, trans_entry); -	if (ret->state != st) { -		ret = NULL; -		list_for_each_entry_safe(dst, tmp, &t->dst_list, trans_entry) { -			if (dst->state == st) { -				ret = dst; -				list_del_init(&dst->trans_entry); -				break; -			} -		} -	} else { -		list_del(&ret->trans_entry); -	} -	spin_unlock(&t->dst_lock); - -	if (ret) -		netfs_trans_remove_dst(ret); -} - -static int netfs_trans_push(struct netfs_trans *t, struct netfs_state *st) -{ -	int err; - -	err = netfs_trans_push_dst(t, st); -	if (err) -		return err; - -	err = netfs_trans_send(t, st); -	if (err) -		goto err_out_free; - -	if (t->flags & NETFS_TRANS_SINGLE_DST) -		pohmelfs_switch_active(st->psb); - -	return 0; - -err_out_free: -	t->result = err; -	netfs_trans_drop_last(t, st); - -	return err; -} - -int netfs_trans_finish_send(struct netfs_trans *t, struct pohmelfs_sb *psb) -{ -	struct pohmelfs_config *c; -	int err = -ENODEV; -	struct netfs_state *st; -#if 0 -	dprintk("%s: t: %p, gen: %u, size: %u, page_num: %u, active: %p.\n", -		__func__, t, t->gen, t->iovec.iov_len, t->page_num, psb->active_state); -#endif -	mutex_lock(&psb->state_lock); -	list_for_each_entry(c, &psb->state_list, config_entry) { -		st = &c->state; - -		if (t->flags & NETFS_TRANS_SINGLE_DST) { -			if (!(st->ctl.perm & POHMELFS_IO_PERM_READ)) -				continue; -		} else { -			if (!(st->ctl.perm & POHMELFS_IO_PERM_WRITE)) -				continue; -		} - -		if (psb->active_state && (psb->active_state->state.ctl.prio >= st->ctl.prio) && -				(t->flags & NETFS_TRANS_SINGLE_DST)) -			st = &psb->active_state->state; - -		err = netfs_trans_push(t, st); -		if (!err && (t->flags & NETFS_TRANS_SINGLE_DST)) -			break; -	} - -	mutex_unlock(&psb->state_lock); -#if 0 -	dprintk("%s: fully sent t: %p, gen: %u, size: %u, page_num: %u, err: %d.\n", -		__func__, t, t->gen, t->iovec.iov_len, t->page_num, err); -#endif -	if (err) -		t->result = err; -	return err; -} - -int netfs_trans_finish(struct netfs_trans *t, struct pohmelfs_sb *psb) -{ -	int err; -	struct netfs_cmd *cmd = t->iovec.iov_base; - -	t->gen = atomic_inc_return(&psb->trans_gen); - -	cmd->size = t->iovec.iov_len - sizeof(struct netfs_cmd) + -		t->attached_size + t->attached_pages * sizeof(struct netfs_cmd); -	cmd->cmd = NETFS_TRANS; -	cmd->start = t->gen; -	cmd->id = 0; - -	if (psb->perform_crypto) { -		cmd->ext = psb->crypto_attached_size; -		cmd->csize = psb->crypto_attached_size; -	} - -	dprintk("%s: t: %u, size: %u, iov_len: %zu, attached_size: %u, attached_pages: %u.\n", -			__func__, t->gen, cmd->size, t->iovec.iov_len, t->attached_size, t->attached_pages); -	err = pohmelfs_trans_crypt(t, psb); -	if (err) { -		t->result = err; -		netfs_convert_cmd(cmd); -		dprintk("%s: trans: %llu, crypto_attached_size: %u, attached_size: %u, attached_pages: %d, trans_size: %u, err: %d.\n", -			__func__, cmd->start, psb->crypto_attached_size, t->attached_size, t->attached_pages, cmd->size, err); -	} -	netfs_trans_put(t); -	return err; -} - -/* - * Resend transaction to remote server(s). - * If new servers were added into superblock, we can try to send data - * to them too. - * - * It is called under superblock's state_lock, so we can safely - * dereference psb->state_list. Also, transaction's reference counter is - * bumped, so it can not go away under us, thus we can safely access all - * its members. State is locked. - * - * This function returns 0 if transaction was successfully sent to at - * least one destination target. - */ -int netfs_trans_resend(struct netfs_trans *t, struct pohmelfs_sb *psb) -{ -	struct netfs_trans_dst *dst; -	struct netfs_state *st; -	struct pohmelfs_config *c; -	int err, exist, error = -ENODEV; - -	list_for_each_entry(c, &psb->state_list, config_entry) { -		st = &c->state; - -		exist = 0; -		spin_lock(&t->dst_lock); -		list_for_each_entry(dst, &t->dst_list, trans_entry) { -			if (st == dst->state) { -				exist = 1; -				break; -			} -		} -		spin_unlock(&t->dst_lock); - -		if (exist) { -			if (!(t->flags & NETFS_TRANS_SINGLE_DST) || -					(c->config_entry.next == &psb->state_list)) { -				dprintk("%s: resending st: %p, t: %p, gen: %u.\n", -						__func__, st, t, t->gen); -				err = netfs_trans_send(t, st); -				if (!err) -					error = 0; -			} -			continue; -		} - -		dprintk("%s: pushing/resending st: %p, t: %p, gen: %u.\n", -				__func__, st, t, t->gen); -		err = netfs_trans_push(t, st); -		if (err) -			continue; -		error = 0; -		if (t->flags & NETFS_TRANS_SINGLE_DST) -			break; -	} - -	t->result = error; -	return error; -} - -void *netfs_trans_add(struct netfs_trans *t, unsigned int size) -{ -	struct iovec *io = &t->iovec; -	void *ptr; - -	if (size > t->total_size) { -		ptr = ERR_PTR(-EINVAL); -		goto out; -	} - -	if (io->iov_len + size > t->total_size) { -		dprintk("%s: too big size t: %p, gen: %u, iov_len: %zu, size: %u, total: %u.\n", -				__func__, t, t->gen, io->iov_len, size, t->total_size); -		ptr = ERR_PTR(-E2BIG); -		goto out; -	} - -	ptr = io->iov_base + io->iov_len; -	io->iov_len += size; - -out: -	dprintk("%s: t: %p, gen: %u, size: %u, total: %zu.\n", -		__func__, t, t->gen, size, io->iov_len); -	return ptr; -} - -void netfs_trans_free(struct netfs_trans *t) -{ -	if (t->eng) -		pohmelfs_crypto_thread_make_ready(t->eng->thread); -	kfree(t); -} - -struct netfs_trans *netfs_trans_alloc(struct pohmelfs_sb *psb, unsigned int size, -		unsigned int flags, unsigned int nr) -{ -	struct netfs_trans *t; -	unsigned int num, cont, pad, size_no_trans; -	unsigned int crypto_added = 0; -	struct netfs_cmd *cmd; - -	if (psb->perform_crypto) -		crypto_added = psb->crypto_attached_size; - -	/* -	 * |sizeof(struct netfs_trans)| -	 * |sizeof(struct netfs_cmd)| - transaction header -	 * |size| - buffer with requested size -	 * |padding| - crypto padding, zero bytes -	 * |nr * sizeof(struct page *)| - array of page pointers -	 * -	 * Overall size should be less than PAGE_SIZE for guaranteed allocation. -	 */ - -	cont = size; -	size = ALIGN(size, psb->crypto_align_size); -	pad = size - cont; - -	size_no_trans = size + sizeof(struct netfs_cmd) * 2 + crypto_added; - -	cont = sizeof(struct netfs_trans) + size_no_trans; - -	num = (PAGE_SIZE - cont)/sizeof(struct page *); - -	if (nr > num) -		nr = num; - -	t = kzalloc(cont + nr*sizeof(struct page *), GFP_NOIO); -	if (!t) -		goto err_out_exit; - -	t->iovec.iov_base = (void *)(t + 1); -	t->pages = (struct page **)(t->iovec.iov_base + size_no_trans); - -	/* -	 * Reserving space for transaction header. -	 */ -	t->iovec.iov_len = sizeof(struct netfs_cmd) + crypto_added; - -	netfs_trans_init_static(t, nr, size_no_trans); - -	t->flags = flags; -	t->psb = psb; - -	cmd = (struct netfs_cmd *)t->iovec.iov_base; - -	cmd->size = size; -	cmd->cpad = pad; -	cmd->csize = crypto_added; - -	dprintk("%s: t: %p, gen: %u, size: %u, padding: %u, align_size: %u, flags: %x, " -			"page_num: %u, base: %p, pages: %p.\n", -			__func__, t, t->gen, size, pad, psb->crypto_align_size, flags, nr, -			t->iovec.iov_base, t->pages); - -	return t; - -err_out_exit: -	return NULL; -} - -int netfs_trans_init(void) -{ -	int err = -ENOMEM; - -	netfs_trans_dst = kmem_cache_create("netfs_trans_dst", sizeof(struct netfs_trans_dst), -			0, 0, NULL); -	if (!netfs_trans_dst) -		goto err_out_exit; - -	netfs_trans_dst_pool = mempool_create_slab_pool(256, netfs_trans_dst); -	if (!netfs_trans_dst_pool) -		goto err_out_free; - -	return 0; - -err_out_free: -	kmem_cache_destroy(netfs_trans_dst); -err_out_exit: -	return err; -} - -void netfs_trans_exit(void) -{ -	mempool_destroy(netfs_trans_dst_pool); -	kmem_cache_destroy(netfs_trans_dst); -} diff --git a/drivers/staging/rtl8712/drv_types.h b/drivers/staging/rtl8712/drv_types.h index 9b5d771e650..ed85b441520 100644 --- a/drivers/staging/rtl8712/drv_types.h +++ b/drivers/staging/rtl8712/drv_types.h @@ -37,6 +37,8 @@ struct _adapter;  #include "wlan_bssdef.h"  #include "rtl8712_spec.h"  #include "rtl8712_hal.h" +#include <linux/mutex.h> +#include <linux/completion.h>  enum _NIC_VERSION {  	RTL8711_NIC, @@ -168,6 +170,7 @@ struct _adapter {  	s32	bSurpriseRemoved;  	u32	IsrContent;  	u32	ImrContent; +	bool	fw_found;  	u8	EepromAddressSize;  	u8	hw_init_completed;  	struct task_struct *cmdThread; @@ -184,6 +187,10 @@ struct _adapter {  	_workitem wkFilterRxFF0;  	u8 blnEnableRxFF0Filter;  	spinlock_t lockRxFF0Filter; +	const struct firmware *fw; +	struct usb_interface *pusb_intf; +	struct mutex mutex_start; +	struct completion rtl8712_fw_ready;  };  static inline u8 *myid(struct eeprom_priv *peepriv) diff --git a/drivers/staging/rtl8712/hal_init.c b/drivers/staging/rtl8712/hal_init.c index d0029aa4cd3..cc893c0f5ad 100644 --- a/drivers/staging/rtl8712/hal_init.c +++ b/drivers/staging/rtl8712/hal_init.c @@ -42,29 +42,56 @@  #define FWBUFF_ALIGN_SZ 512  #define MAX_DUMP_FWSZ	49152 /*default = 49152 (48k)*/ -static u32 rtl871x_open_fw(struct _adapter *padapter, void **pphfwfile_hdl, -		    const u8 **ppmappedfw) +static void rtl871x_load_fw_cb(const struct firmware *firmware, void *context)  { +	struct _adapter *padapter = context; + +	complete(&padapter->rtl8712_fw_ready); +	if (!firmware) { +		struct usb_device *udev = padapter->dvobjpriv.pusbdev; +		struct usb_interface *pusb_intf = padapter->pusb_intf; +		printk(KERN_ERR "r8712u: Firmware request failed\n"); +		padapter->fw_found = false; +		usb_put_dev(udev); +		usb_set_intfdata(pusb_intf, NULL); +		return; +	} +	padapter->fw = firmware; +	padapter->fw_found = true; +	/* firmware available - start netdev */ +	register_netdev(padapter->pnetdev); +} + +static const char firmware_file[] = "rtlwifi/rtl8712u.bin"; + +int rtl871x_load_fw(struct _adapter *padapter) +{ +	struct device *dev = &padapter->dvobjpriv.pusbdev->dev;  	int rc; -	const char firmware_file[] = "rtlwifi/rtl8712u.bin"; -	const struct firmware **praw = (const struct firmware **) -				       (pphfwfile_hdl); -	struct dvobj_priv *pdvobjpriv = (struct dvobj_priv *) -					(&padapter->dvobjpriv); -	struct usb_device *pusbdev = pdvobjpriv->pusbdev; +	init_completion(&padapter->rtl8712_fw_ready);  	printk(KERN_INFO "r8712u: Loading firmware from \"%s\"\n",  	       firmware_file); -	rc = request_firmware(praw, firmware_file, &pusbdev->dev); -	if (rc < 0) { -		printk(KERN_ERR "r8712u: Unable to load firmware\n"); -		printk(KERN_ERR "r8712u: Install latest linux-firmware\n"); +	rc = request_firmware_nowait(THIS_MODULE, 1, firmware_file, dev, +				     GFP_KERNEL, padapter, rtl871x_load_fw_cb); +	if (rc) +		printk(KERN_ERR "r8712u: Firmware request error %d\n", rc); +	return rc; +} +MODULE_FIRMWARE("rtlwifi/rtl8712u.bin"); + +static u32 rtl871x_open_fw(struct _adapter *padapter, const u8 **ppmappedfw) +{ +	const struct firmware **praw = &padapter->fw; + +	if (padapter->fw->size > 200000) { +		printk(KERN_ERR "r8172u: Badfw->size of %d\n", +		       (int)padapter->fw->size);  		return 0;  	}  	*ppmappedfw = (u8 *)((*praw)->data);  	return (*praw)->size;  } -MODULE_FIRMWARE("rtlwifi/rtl8712u.bin");  static void fill_fwpriv(struct _adapter *padapter, struct fw_priv *pfwpriv)  { @@ -142,18 +169,17 @@ static u8 rtl8712_dl_fw(struct _adapter *padapter)  	uint dump_imem_sz, imem_sz, dump_emem_sz, emem_sz; /* max = 49152; */  	struct fw_hdr fwhdr;  	u32 ulfilelength;	/* FW file size */ -	void *phfwfile_hdl = NULL;  	const u8 *pmappedfw = NULL;  	u8 *ptmpchar = NULL, *ppayload, *ptr;  	struct tx_desc *ptx_desc;  	u32 txdscp_sz = sizeof(struct tx_desc);  	u8 ret = _FAIL; -	ulfilelength = rtl871x_open_fw(padapter, &phfwfile_hdl, &pmappedfw); +	ulfilelength = rtl871x_open_fw(padapter, &pmappedfw);  	if (pmappedfw && (ulfilelength > 0)) {  		update_fwhdr(&fwhdr, pmappedfw);  		if (chk_fwhdr(&fwhdr, ulfilelength) == _FAIL) -			goto firmware_rel; +			return ret;  		fill_fwpriv(padapter, &fwhdr.fwpriv);  		/* firmware check ok */  		maxlen = (fwhdr.img_IMEM_size > fwhdr.img_SRAM_size) ? @@ -161,7 +187,7 @@ static u8 rtl8712_dl_fw(struct _adapter *padapter)  		maxlen += txdscp_sz;  		ptmpchar = _malloc(maxlen + FWBUFF_ALIGN_SZ);  		if (ptmpchar == NULL) -			goto firmware_rel; +			return ret;  		ptx_desc = (struct tx_desc *)(ptmpchar + FWBUFF_ALIGN_SZ -  			    ((addr_t)(ptmpchar) & (FWBUFF_ALIGN_SZ - 1))); @@ -297,8 +323,6 @@ static u8 rtl8712_dl_fw(struct _adapter *padapter)  exit_fail:  	kfree(ptmpchar); -firmware_rel: -	release_firmware((struct firmware *)phfwfile_hdl);  	return ret;  } diff --git a/drivers/staging/rtl8712/os_intfs.c b/drivers/staging/rtl8712/os_intfs.c index 9a75c6dbe50..98a3d684f9b 100644 --- a/drivers/staging/rtl8712/os_intfs.c +++ b/drivers/staging/rtl8712/os_intfs.c @@ -31,6 +31,7 @@  #include <linux/module.h>  #include <linux/init.h>  #include <linux/kthread.h> +#include <linux/firmware.h>  #include "osdep_service.h"  #include "drv_types.h"  #include "xmit_osdep.h" @@ -264,12 +265,12 @@ static void start_drv_timers(struct _adapter *padapter)  void r8712_stop_drv_timers(struct _adapter *padapter)  {  	_cancel_timer_ex(&padapter->mlmepriv.assoc_timer); -	_cancel_timer_ex(&padapter->mlmepriv.sitesurveyctrl. -			 sitesurvey_ctrl_timer);  	_cancel_timer_ex(&padapter->securitypriv.tkip_timer);  	_cancel_timer_ex(&padapter->mlmepriv.scan_to_timer);  	_cancel_timer_ex(&padapter->mlmepriv.dhcp_timer);  	_cancel_timer_ex(&padapter->mlmepriv.wdg_timer); +	_cancel_timer_ex(&padapter->mlmepriv.sitesurveyctrl. +			 sitesurvey_ctrl_timer);  }  static u8 init_default_value(struct _adapter *padapter) @@ -347,7 +348,8 @@ u8 r8712_free_drv_sw(struct _adapter *padapter)  	r8712_free_mlme_priv(&padapter->mlmepriv);  	r8712_free_io_queue(padapter);  	_free_xmit_priv(&padapter->xmitpriv); -	_r8712_free_sta_priv(&padapter->stapriv); +	if (padapter->fw_found) +		_r8712_free_sta_priv(&padapter->stapriv);  	_r8712_free_recv_priv(&padapter->recvpriv);  	mp871xdeinit(padapter);  	if (pnetdev) @@ -388,6 +390,7 @@ static int netdev_open(struct net_device *pnetdev)  {  	struct _adapter *padapter = (struct _adapter *)netdev_priv(pnetdev); +	mutex_lock(&padapter->mutex_start);  	if (padapter->bup == false) {  		padapter->bDriverStopped = false;  		padapter->bSurpriseRemoved = false; @@ -435,11 +438,13 @@ static int netdev_open(struct net_device *pnetdev)  	/* start driver mlme relation timer */  	start_drv_timers(padapter);  	padapter->ledpriv.LedControlHandler(padapter, LED_CTL_NO_LINK); +	mutex_unlock(&padapter->mutex_start);  	return 0;  netdev_open_error:  	padapter->bup = false;  	netif_carrier_off(pnetdev);  	netif_stop_queue(pnetdev); +	mutex_unlock(&padapter->mutex_start);  	return -1;  } @@ -473,6 +478,9 @@ static int netdev_close(struct net_device *pnetdev)  	r8712_free_network_queue(padapter);  	/* The interface is no longer Up: */  	padapter->bup = false; +	release_firmware(padapter->fw); +	/* never exit with a firmware callback pending */ +	wait_for_completion(&padapter->rtl8712_fw_ready);  	return 0;  } diff --git a/drivers/staging/rtl8712/rtl8712_hal.h b/drivers/staging/rtl8712/rtl8712_hal.h index 665e7183817..d19865a5a50 100644 --- a/drivers/staging/rtl8712/rtl8712_hal.h +++ b/drivers/staging/rtl8712/rtl8712_hal.h @@ -145,5 +145,6 @@ struct hal_priv {  };  uint	 rtl8712_hal_init(struct _adapter *padapter); +int rtl871x_load_fw(struct _adapter *padapter);  #endif diff --git a/drivers/staging/rtl8712/rtl871x_sta_mgt.c b/drivers/staging/rtl8712/rtl871x_sta_mgt.c index 64f56961883..81bde803c59 100644 --- a/drivers/staging/rtl8712/rtl871x_sta_mgt.c +++ b/drivers/staging/rtl8712/rtl871x_sta_mgt.c @@ -43,6 +43,7 @@ static void _init_stainfo(struct sta_info *psta)  	_r8712_init_sta_xmit_priv(&psta->sta_xmitpriv);  	_r8712_init_sta_recv_priv(&psta->sta_recvpriv);  #ifdef CONFIG_R8712_AP +	_init_listhead(&psta->asoc_list);  	_init_listhead(&psta->auth_list);  #endif  } diff --git a/drivers/staging/rtl8712/usb_intf.c b/drivers/staging/rtl8712/usb_intf.c index 5385da2e9cd..9bade184883 100644 --- a/drivers/staging/rtl8712/usb_intf.c +++ b/drivers/staging/rtl8712/usb_intf.c @@ -89,6 +89,7 @@ static struct usb_device_id rtl871x_usb_id_tbl[] = {  	{USB_DEVICE(0x0DF6, 0x0045)},  	{USB_DEVICE(0x0DF6, 0x0059)}, /* 11n mode disable */  	{USB_DEVICE(0x0DF6, 0x004B)}, +	{USB_DEVICE(0x0DF6, 0x005B)},  	{USB_DEVICE(0x0DF6, 0x005D)},  	{USB_DEVICE(0x0DF6, 0x0063)},  	/* Sweex */ @@ -389,6 +390,7 @@ static int r871xu_drv_init(struct usb_interface *pusb_intf,  	pdvobjpriv = &padapter->dvobjpriv;  	pdvobjpriv->padapter = padapter;  	padapter->dvobjpriv.pusbdev = udev; +	padapter->pusb_intf = pusb_intf;  	usb_set_intfdata(pusb_intf, pnetdev);  	SET_NETDEV_DEV(pnetdev, &pusb_intf->dev);  	/* step 2. */ @@ -595,10 +597,11 @@ static int r871xu_drv_init(struct usb_interface *pusb_intf,  			       "%pM\n", mac);  		memcpy(pnetdev->dev_addr, mac, ETH_ALEN);  	} -	/* step 6. Tell the network stack we exist */ -	if (register_netdev(pnetdev) != 0) +	/* step 6. Load the firmware asynchronously */ +	if (rtl871x_load_fw(padapter))  		goto error;  	spin_lock_init(&padapter->lockRxFF0Filter); +	mutex_init(&padapter->mutex_start);  	return 0;  error:  	usb_put_dev(udev); @@ -629,7 +632,8 @@ static void r871xu_dev_remove(struct usb_interface *pusb_intf)  		flush_scheduled_work();  		udelay(1);  		/*Stop driver mlme relation timer */ -		r8712_stop_drv_timers(padapter); +		if (padapter->fw_found) +			r8712_stop_drv_timers(padapter);  		r871x_dev_unload(padapter);  		r8712_free_drv_sw(padapter);  	} diff --git a/drivers/staging/tidspbridge/core/tiomap3430.c b/drivers/staging/tidspbridge/core/tiomap3430.c index e1c4492a710..dde559d06c4 100644 --- a/drivers/staging/tidspbridge/core/tiomap3430.c +++ b/drivers/staging/tidspbridge/core/tiomap3430.c @@ -1046,8 +1046,6 @@ static int bridge_dev_destroy(struct bridge_dev_context *dev_ctxt)  	/* Free the driver's device context: */  	kfree(drv_datap->base_img); -	kfree(drv_datap); -	dev_set_drvdata(bridge, NULL);  	kfree((void *)dev_ctxt);  	return status;  } diff --git a/drivers/staging/tidspbridge/rmgr/drv_interface.c b/drivers/staging/tidspbridge/rmgr/drv_interface.c index 76cfc6edecd..385740bad0d 100644 --- a/drivers/staging/tidspbridge/rmgr/drv_interface.c +++ b/drivers/staging/tidspbridge/rmgr/drv_interface.c @@ -410,6 +410,9 @@ static int __devexit omap34_xx_bridge_remove(struct platform_device *pdev)  		DBC_ASSERT(ret == true);  	} +	kfree(drv_datap); +	dev_set_drvdata(bridge, NULL); +  func_cont:  	mem_ext_phys_pool_release(); @@ -500,35 +503,42 @@ static int bridge_open(struct inode *ip, struct file *filp)  	}  #endif  	pr_ctxt = kzalloc(sizeof(struct process_context), GFP_KERNEL); -	if (pr_ctxt) { -		pr_ctxt->res_state = PROC_RES_ALLOCATED; -		spin_lock_init(&pr_ctxt->dmm_map_lock); -		INIT_LIST_HEAD(&pr_ctxt->dmm_map_list); -		spin_lock_init(&pr_ctxt->dmm_rsv_lock); -		INIT_LIST_HEAD(&pr_ctxt->dmm_rsv_list); +	if (!pr_ctxt) +		return -ENOMEM; -		pr_ctxt->node_id = kzalloc(sizeof(struct idr), GFP_KERNEL); -		if (pr_ctxt->node_id) { -			idr_init(pr_ctxt->node_id); -		} else { -			status = -ENOMEM; -			goto err; -		} +	pr_ctxt->res_state = PROC_RES_ALLOCATED; +	spin_lock_init(&pr_ctxt->dmm_map_lock); +	INIT_LIST_HEAD(&pr_ctxt->dmm_map_list); +	spin_lock_init(&pr_ctxt->dmm_rsv_lock); +	INIT_LIST_HEAD(&pr_ctxt->dmm_rsv_list); -		pr_ctxt->stream_id = kzalloc(sizeof(struct idr), GFP_KERNEL); -		if (pr_ctxt->stream_id) -			idr_init(pr_ctxt->stream_id); -		else -			status = -ENOMEM; -	} else { +	pr_ctxt->node_id = kzalloc(sizeof(struct idr), GFP_KERNEL); +	if (!pr_ctxt->node_id) {  		status = -ENOMEM; +		goto err1;  	} -err: + +	idr_init(pr_ctxt->node_id); + +	pr_ctxt->stream_id = kzalloc(sizeof(struct idr), GFP_KERNEL); +	if (!pr_ctxt->stream_id) { +		status = -ENOMEM; +		goto err2; +	} + +	idr_init(pr_ctxt->stream_id); +  	filp->private_data = pr_ctxt; +  #ifdef CONFIG_TIDSPBRIDGE_RECOVERY -	if (!status) -		atomic_inc(&bridge_cref); +	atomic_inc(&bridge_cref);  #endif +	return 0; + +err2: +	kfree(pr_ctxt->node_id); +err1: +	kfree(pr_ctxt);  	return status;  } @@ -550,6 +560,8 @@ static int bridge_release(struct inode *ip, struct file *filp)  	flush_signals(current);  	drv_remove_all_resources(pr_ctxt);  	proc_detach(pr_ctxt); +	kfree(pr_ctxt->node_id); +	kfree(pr_ctxt->stream_id);  	kfree(pr_ctxt);  	filp->private_data = NULL; diff --git a/drivers/staging/usbip/stub_main.c b/drivers/staging/usbip/stub_main.c index 2d631785006..705a9e530a1 100644 --- a/drivers/staging/usbip/stub_main.c +++ b/drivers/staging/usbip/stub_main.c @@ -246,8 +246,9 @@ static int __init usbip_host_init(void)  {  	int ret; -	stub_priv_cache = KMEM_CACHE(stub_priv, SLAB_HWCACHE_ALIGN); +	init_busid_table(); +	stub_priv_cache = KMEM_CACHE(stub_priv, SLAB_HWCACHE_ALIGN);  	if (!stub_priv_cache) {  		pr_err("kmem_cache_create failed\n");  		return -ENOMEM; @@ -266,7 +267,6 @@ static int __init usbip_host_init(void)  		goto err_create_file;  	} -	init_busid_table();  	pr_info(DRIVER_DESC " v" USBIP_VERSION "\n");  	return ret; diff --git a/drivers/staging/zcache/zcache-main.c b/drivers/staging/zcache/zcache-main.c index 642840c612a..ef7c52bb1df 100644 --- a/drivers/staging/zcache/zcache-main.c +++ b/drivers/staging/zcache/zcache-main.c @@ -358,8 +358,8 @@ static struct zbud_hdr *zbud_create(uint16_t client_id, uint16_t pool_id,  	if (unlikely(zbpg == NULL))  		goto out;  	/* ok, have a page, now compress the data before taking locks */ -	spin_lock(&zbpg->lock);  	spin_lock(&zbud_budlists_spinlock); +	spin_lock(&zbpg->lock);  	list_add_tail(&zbpg->bud_list, &zbud_unbuddied[nchunks].list);  	zbud_unbuddied[nchunks].count++;  	zh = &zbpg->buddy[0]; @@ -389,12 +389,11 @@ init_zh:  	zh->oid = *oid;  	zh->pool_id = pool_id;  	zh->client_id = client_id; -	/* can wait to copy the data until the list locks are dropped */ -	spin_unlock(&zbud_budlists_spinlock); -  	to = zbud_data(zh, size);  	memcpy(to, cdata, size);  	spin_unlock(&zbpg->lock); +	spin_unlock(&zbud_budlists_spinlock); +  	zbud_cumul_chunk_counts[nchunks]++;  	atomic_inc(&zcache_zbud_curr_zpages);  	zcache_zbud_cumul_zpages++; @@ -655,8 +654,8 @@ static unsigned int zv_max_zsize = (PAGE_SIZE / 8) * 7;   */  static unsigned int zv_max_mean_zsize = (PAGE_SIZE / 8) * 5; -static unsigned long zv_curr_dist_counts[NCHUNKS]; -static unsigned long zv_cumul_dist_counts[NCHUNKS]; +static atomic_t zv_curr_dist_counts[NCHUNKS]; +static atomic_t zv_cumul_dist_counts[NCHUNKS];  static struct zv_hdr *zv_create(struct xv_pool *xvpool, uint32_t pool_id,  				struct tmem_oid *oid, uint32_t index, @@ -675,8 +674,8 @@ static struct zv_hdr *zv_create(struct xv_pool *xvpool, uint32_t pool_id,  			&page, &offset, ZCACHE_GFP_MASK);  	if (unlikely(ret))  		goto out; -	zv_curr_dist_counts[chunks]++; -	zv_cumul_dist_counts[chunks]++; +	atomic_inc(&zv_curr_dist_counts[chunks]); +	atomic_inc(&zv_cumul_dist_counts[chunks]);  	zv = kmap_atomic(page, KM_USER0) + offset;  	zv->index = index;  	zv->oid = *oid; @@ -698,7 +697,7 @@ static void zv_free(struct xv_pool *xvpool, struct zv_hdr *zv)  	ASSERT_SENTINEL(zv, ZVH);  	BUG_ON(chunks >= NCHUNKS); -	zv_curr_dist_counts[chunks]--; +	atomic_dec(&zv_curr_dist_counts[chunks]);  	size -= sizeof(*zv);  	BUG_ON(size == 0);  	INVERT_SENTINEL(zv, ZVH); @@ -738,7 +737,7 @@ static int zv_curr_dist_counts_show(char *buf)  	char *p = buf;  	for (i = 0; i < NCHUNKS; i++) { -		n = zv_curr_dist_counts[i]; +		n = atomic_read(&zv_curr_dist_counts[i]);  		p += sprintf(p, "%lu ", n);  		chunks += n;  		sum_total_chunks += i * n; @@ -754,7 +753,7 @@ static int zv_cumul_dist_counts_show(char *buf)  	char *p = buf;  	for (i = 0; i < NCHUNKS; i++) { -		n = zv_cumul_dist_counts[i]; +		n = atomic_read(&zv_cumul_dist_counts[i]);  		p += sprintf(p, "%lu ", n);  		chunks += n;  		sum_total_chunks += i * n; @@ -1782,9 +1781,9 @@ static int zcache_frontswap_poolid = -1;   * Swizzling increases objects per swaptype, increasing tmem concurrency   * for heavy swaploads.  Later, larger nr_cpus -> larger SWIZ_BITS   * Setting SWIZ_BITS to 27 basically reconstructs the swap entry from - * frontswap_get_page() + * frontswap_get_page(), but has side-effects. Hence using 8.   */ -#define SWIZ_BITS		27 +#define SWIZ_BITS		8  #define SWIZ_MASK		((1 << SWIZ_BITS) - 1)  #define _oswiz(_type, _ind)	((_type << SWIZ_BITS) | (_ind & SWIZ_MASK))  #define iswiz(_ind)		(_ind >> SWIZ_BITS) diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index ac44af165b2..44262908def 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -1061,7 +1061,7 @@ attach_cmd:  	if (ret < 0)  		return iscsit_add_reject_from_cmd(  				ISCSI_REASON_BOOKMARK_NO_RESOURCES, -				1, 1, buf, cmd); +				1, 0, buf, cmd);  	/*  	 * Check the CmdSN against ExpCmdSN/MaxCmdSN here if  	 * the Immediate Bit is not set, and no Immediate @@ -3164,6 +3164,30 @@ static int iscsit_send_task_mgt_rsp(  	return 0;  } +static bool iscsit_check_inaddr_any(struct iscsi_np *np) +{ +	bool ret = false; + +	if (np->np_sockaddr.ss_family == AF_INET6) { +		const struct sockaddr_in6 sin6 = { +			.sin6_addr = IN6ADDR_ANY_INIT }; +		struct sockaddr_in6 *sock_in6 = +			 (struct sockaddr_in6 *)&np->np_sockaddr; + +		if (!memcmp(sock_in6->sin6_addr.s6_addr, +				sin6.sin6_addr.s6_addr, 16)) +			ret = true; +	} else { +		struct sockaddr_in * sock_in = +			(struct sockaddr_in *)&np->np_sockaddr; + +		if (sock_in->sin_addr.s_addr == INADDR_ANY) +			ret = true; +	} + +	return ret; +} +  static int iscsit_build_sendtargets_response(struct iscsi_cmd *cmd)  {  	char *payload = NULL; @@ -3213,12 +3237,17 @@ static int iscsit_build_sendtargets_response(struct iscsi_cmd *cmd)  			spin_lock(&tpg->tpg_np_lock);  			list_for_each_entry(tpg_np, &tpg->tpg_gnp_list,  						tpg_np_list) { +				struct iscsi_np *np = tpg_np->tpg_np; +				bool inaddr_any = iscsit_check_inaddr_any(np); +  				len = sprintf(buf, "TargetAddress="  					"%s%s%s:%hu,%hu", -					(tpg_np->tpg_np->np_sockaddr.ss_family == AF_INET6) ? -					"[" : "", tpg_np->tpg_np->np_ip, -					(tpg_np->tpg_np->np_sockaddr.ss_family == AF_INET6) ? -					"]" : "", tpg_np->tpg_np->np_port, +					(np->np_sockaddr.ss_family == AF_INET6) ? +					"[" : "", (inaddr_any == false) ? +						np->np_ip : conn->local_ip, +					(np->np_sockaddr.ss_family == AF_INET6) ? +					"]" : "", (inaddr_any == false) ? +						np->np_port : conn->local_port,  					tpg->tpgt);  				len += 1; diff --git a/drivers/target/iscsi/iscsi_target_configfs.c b/drivers/target/iscsi/iscsi_target_configfs.c index 3468caab47a..6b35b37988e 100644 --- a/drivers/target/iscsi/iscsi_target_configfs.c +++ b/drivers/target/iscsi/iscsi_target_configfs.c @@ -21,6 +21,7 @@  #include <linux/configfs.h>  #include <linux/export.h> +#include <linux/inet.h>  #include <target/target_core_base.h>  #include <target/target_core_fabric.h>  #include <target/target_core_fabric_configfs.h> diff --git a/drivers/target/iscsi/iscsi_target_core.h b/drivers/target/iscsi/iscsi_target_core.h index f1a02dad05a..0ec3b77a0c2 100644 --- a/drivers/target/iscsi/iscsi_target_core.h +++ b/drivers/target/iscsi/iscsi_target_core.h @@ -508,6 +508,7 @@ struct iscsi_conn {  	u16			cid;  	/* Remote TCP Port */  	u16			login_port; +	u16			local_port;  	int			net_size;  	u32			auth_id;  #define CONNFLAG_SCTP_STRUCT_FILE			0x01 @@ -527,6 +528,7 @@ struct iscsi_conn {  	unsigned char		bad_hdr[ISCSI_HDR_LEN];  #define IPV6_ADDRESS_SPACE				48  	unsigned char		login_ip[IPV6_ADDRESS_SPACE]; +	unsigned char		local_ip[IPV6_ADDRESS_SPACE];  	int			conn_usage_count;  	int			conn_waiting_on_uc;  	atomic_t		check_immediate_queue; @@ -561,8 +563,8 @@ struct iscsi_conn {  	struct hash_desc	conn_tx_hash;  	/* Used for scheduling TX and RX connection kthreads */  	cpumask_var_t		conn_cpumask; -	int			conn_rx_reset_cpumask:1; -	int			conn_tx_reset_cpumask:1; +	unsigned int		conn_rx_reset_cpumask:1; +	unsigned int		conn_tx_reset_cpumask:1;  	/* list_head of struct iscsi_cmd for this connection */  	struct list_head	conn_cmd_list;  	struct list_head	immed_queue_list; diff --git a/drivers/target/iscsi/iscsi_target_erl1.c b/drivers/target/iscsi/iscsi_target_erl1.c index 255c0d67e89..27901e37c12 100644 --- a/drivers/target/iscsi/iscsi_target_erl1.c +++ b/drivers/target/iscsi/iscsi_target_erl1.c @@ -1238,7 +1238,7 @@ void iscsit_mod_dataout_timer(struct iscsi_cmd *cmd)  {  	struct iscsi_conn *conn = cmd->conn;  	struct iscsi_session *sess = conn->sess; -	struct iscsi_node_attrib *na = na = iscsit_tpg_get_node_attrib(sess); +	struct iscsi_node_attrib *na = iscsit_tpg_get_node_attrib(sess);  	spin_lock_bh(&cmd->dataout_timeout_lock);  	if (!(cmd->dataout_timer_flags & ISCSI_TF_RUNNING)) { @@ -1261,7 +1261,7 @@ void iscsit_start_dataout_timer(  	struct iscsi_conn *conn)  {  	struct iscsi_session *sess = conn->sess; -	struct iscsi_node_attrib *na = na = iscsit_tpg_get_node_attrib(sess); +	struct iscsi_node_attrib *na = iscsit_tpg_get_node_attrib(sess);  	if (cmd->dataout_timer_flags & ISCSI_TF_RUNNING)  		return; diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c index 373b0cc6abd..38cb7ce8469 100644 --- a/drivers/target/iscsi/iscsi_target_login.c +++ b/drivers/target/iscsi/iscsi_target_login.c @@ -615,8 +615,8 @@ static int iscsi_post_login_handler(  		}  		pr_debug("iSCSI Login successful on CID: %hu from %s to" -			" %s:%hu,%hu\n", conn->cid, conn->login_ip, np->np_ip, -				np->np_port, tpg->tpgt); +			" %s:%hu,%hu\n", conn->cid, conn->login_ip, +			conn->local_ip, conn->local_port, tpg->tpgt);  		list_add_tail(&conn->conn_list, &sess->sess_conn_list);  		atomic_inc(&sess->nconn); @@ -658,7 +658,8 @@ static int iscsi_post_login_handler(  	sess->session_state = TARG_SESS_STATE_LOGGED_IN;  	pr_debug("iSCSI Login successful on CID: %hu from %s to %s:%hu,%hu\n", -		conn->cid, conn->login_ip, np->np_ip, np->np_port, tpg->tpgt); +		conn->cid, conn->login_ip, conn->local_ip, conn->local_port, +		tpg->tpgt);  	spin_lock_bh(&sess->conn_lock);  	list_add_tail(&conn->conn_list, &sess->sess_conn_list); @@ -841,6 +842,14 @@ int iscsi_target_setup_login_socket(  		goto fail;  	} +	ret = kernel_setsockopt(sock, IPPROTO_IP, IP_FREEBIND, +			(char *)&opt, sizeof(opt)); +	if (ret < 0) { +		pr_err("kernel_setsockopt() for IP_FREEBIND" +			" failed\n"); +		goto fail; +	} +  	ret = kernel_bind(sock, (struct sockaddr *)&np->np_sockaddr, len);  	if (ret < 0) {  		pr_err("kernel_bind() failed: %d\n", ret); @@ -1020,6 +1029,18 @@ static int __iscsi_target_login_thread(struct iscsi_np *np)  		snprintf(conn->login_ip, sizeof(conn->login_ip), "%pI6c",  				&sock_in6.sin6_addr.in6_u);  		conn->login_port = ntohs(sock_in6.sin6_port); + +		if (conn->sock->ops->getname(conn->sock, +				(struct sockaddr *)&sock_in6, &err, 0) < 0) { +			pr_err("sock_ops->getname() failed.\n"); +			iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR, +					ISCSI_LOGIN_STATUS_TARGET_ERROR); +			goto new_sess_out; +		} +		snprintf(conn->local_ip, sizeof(conn->local_ip), "%pI6c", +				&sock_in6.sin6_addr.in6_u); +		conn->local_port = ntohs(sock_in6.sin6_port); +  	} else {  		memset(&sock_in, 0, sizeof(struct sockaddr_in)); @@ -1032,6 +1053,16 @@ static int __iscsi_target_login_thread(struct iscsi_np *np)  		}  		sprintf(conn->login_ip, "%pI4", &sock_in.sin_addr.s_addr);  		conn->login_port = ntohs(sock_in.sin_port); + +		if (conn->sock->ops->getname(conn->sock, +				(struct sockaddr *)&sock_in, &err, 0) < 0) { +			pr_err("sock_ops->getname() failed.\n"); +			iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR, +					ISCSI_LOGIN_STATUS_TARGET_ERROR); +			goto new_sess_out; +		} +		sprintf(conn->local_ip, "%pI4", &sock_in.sin_addr.s_addr); +		conn->local_port = ntohs(sock_in.sin_port);  	}  	conn->network_transport = np->np_network_transport; @@ -1039,7 +1070,7 @@ static int __iscsi_target_login_thread(struct iscsi_np *np)  	pr_debug("Received iSCSI login request from %s on %s Network"  			" Portal %s:%hu\n", conn->login_ip,  		(conn->network_transport == ISCSI_TCP) ? "TCP" : "SCTP", -			np->np_ip, np->np_port); +			conn->local_ip, conn->local_port);  	pr_debug("Moving to TARG_CONN_STATE_IN_LOGIN.\n");  	conn->conn_state	= TARG_CONN_STATE_IN_LOGIN; diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c index a05ca1c4f01..11287e1ece1 100644 --- a/drivers/target/iscsi/iscsi_target_util.c +++ b/drivers/target/iscsi/iscsi_target_util.c @@ -849,6 +849,17 @@ void iscsit_free_cmd(struct iscsi_cmd *cmd)  	case ISCSI_OP_SCSI_TMFUNC:  		transport_generic_free_cmd(&cmd->se_cmd, 1);  		break; +	case ISCSI_OP_REJECT: +		/* +		 * Handle special case for REJECT when iscsi_add_reject*() has +		 * overwritten the original iscsi_opcode assignment, and the +		 * associated cmd->se_cmd needs to be released. +		 */ +		if (cmd->se_cmd.se_tfo != NULL) { +			transport_generic_free_cmd(&cmd->se_cmd, 1); +			break; +		} +		/* Fall-through */  	default:  		iscsit_release_cmd(cmd);  		break; diff --git a/drivers/target/target_core_alua.c b/drivers/target/target_core_alua.c index 1b1edd14f4b..01a2691dfb4 100644 --- a/drivers/target/target_core_alua.c +++ b/drivers/target/target_core_alua.c @@ -78,7 +78,7 @@ int target_emulate_report_target_port_groups(struct se_task *task)  		return -EINVAL;  	} -	buf = transport_kmap_first_data_page(cmd); +	buf = transport_kmap_data_sg(cmd);  	spin_lock(&su_dev->t10_alua.tg_pt_gps_lock);  	list_for_each_entry(tg_pt_gp, &su_dev->t10_alua.tg_pt_gps_list, @@ -163,7 +163,7 @@ int target_emulate_report_target_port_groups(struct se_task *task)  	buf[2] = ((rd_len >> 8) & 0xff);  	buf[3] = (rd_len & 0xff); -	transport_kunmap_first_data_page(cmd); +	transport_kunmap_data_sg(cmd);  	task->task_scsi_status = GOOD;  	transport_complete_task(task, 1); @@ -194,7 +194,7 @@ int target_emulate_set_target_port_groups(struct se_task *task)  		cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;  		return -EINVAL;  	} -	buf = transport_kmap_first_data_page(cmd); +	buf = transport_kmap_data_sg(cmd);  	/*  	 * Determine if explict ALUA via SET_TARGET_PORT_GROUPS is allowed @@ -351,7 +351,7 @@ int target_emulate_set_target_port_groups(struct se_task *task)  	}  out: -	transport_kunmap_first_data_page(cmd); +	transport_kunmap_data_sg(cmd);  	task->task_scsi_status = GOOD;  	transport_complete_task(task, 1);  	return 0; diff --git a/drivers/target/target_core_cdb.c b/drivers/target/target_core_cdb.c index 2f2235edeff..f3d71fa88a2 100644 --- a/drivers/target/target_core_cdb.c +++ b/drivers/target/target_core_cdb.c @@ -83,7 +83,7 @@ target_emulate_inquiry_std(struct se_cmd *cmd)  		return -EINVAL;  	} -	buf = transport_kmap_first_data_page(cmd); +	buf = transport_kmap_data_sg(cmd);  	if (dev == tpg->tpg_virt_lun0.lun_se_dev) {  		buf[0] = 0x3f; /* Not connected */ @@ -134,7 +134,7 @@ target_emulate_inquiry_std(struct se_cmd *cmd)  	buf[4] = 31; /* Set additional length to 31 */  out: -	transport_kunmap_first_data_page(cmd); +	transport_kunmap_data_sg(cmd);  	return 0;  } @@ -698,6 +698,13 @@ int target_emulate_inquiry(struct se_task *task)  	int p, ret;  	if (!(cdb[1] & 0x1)) { +		if (cdb[2]) { +			pr_err("INQUIRY with EVPD==0 but PAGE CODE=%02x\n", +			       cdb[2]); +			cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; +			return -EINVAL; +		} +  		ret = target_emulate_inquiry_std(cmd);  		goto out;  	} @@ -716,7 +723,7 @@ int target_emulate_inquiry(struct se_task *task)  		return -EINVAL;  	} -	buf = transport_kmap_first_data_page(cmd); +	buf = transport_kmap_data_sg(cmd);  	buf[0] = dev->transport->get_device_type(dev); @@ -729,11 +736,11 @@ int target_emulate_inquiry(struct se_task *task)  	}  	pr_err("Unknown VPD Code: 0x%02x\n", cdb[2]); -	cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE; +	cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;  	ret = -EINVAL;  out_unmap: -	transport_kunmap_first_data_page(cmd); +	transport_kunmap_data_sg(cmd);  out:  	if (!ret) {  		task->task_scsi_status = GOOD; @@ -755,7 +762,7 @@ int target_emulate_readcapacity(struct se_task *task)  	else  		blocks = (u32)blocks_long; -	buf = transport_kmap_first_data_page(cmd); +	buf = transport_kmap_data_sg(cmd);  	buf[0] = (blocks >> 24) & 0xff;  	buf[1] = (blocks >> 16) & 0xff; @@ -771,7 +778,7 @@ int target_emulate_readcapacity(struct se_task *task)  	if (dev->se_sub_dev->se_dev_attrib.emulate_tpu || dev->se_sub_dev->se_dev_attrib.emulate_tpws)  		put_unaligned_be32(0xFFFFFFFF, &buf[0]); -	transport_kunmap_first_data_page(cmd); +	transport_kunmap_data_sg(cmd);  	task->task_scsi_status = GOOD;  	transport_complete_task(task, 1); @@ -785,7 +792,7 @@ int target_emulate_readcapacity_16(struct se_task *task)  	unsigned char *buf;  	unsigned long long blocks = dev->transport->get_blocks(dev); -	buf = transport_kmap_first_data_page(cmd); +	buf = transport_kmap_data_sg(cmd);  	buf[0] = (blocks >> 56) & 0xff;  	buf[1] = (blocks >> 48) & 0xff; @@ -806,7 +813,7 @@ int target_emulate_readcapacity_16(struct se_task *task)  	if (dev->se_sub_dev->se_dev_attrib.emulate_tpu || dev->se_sub_dev->se_dev_attrib.emulate_tpws)  		buf[14] = 0x80; -	transport_kunmap_first_data_page(cmd); +	transport_kunmap_data_sg(cmd);  	task->task_scsi_status = GOOD;  	transport_complete_task(task, 1); @@ -1019,9 +1026,9 @@ int target_emulate_modesense(struct se_task *task)  			offset = cmd->data_length;  	} -	rbuf = transport_kmap_first_data_page(cmd); +	rbuf = transport_kmap_data_sg(cmd);  	memcpy(rbuf, buf, offset); -	transport_kunmap_first_data_page(cmd); +	transport_kunmap_data_sg(cmd);  	task->task_scsi_status = GOOD;  	transport_complete_task(task, 1); @@ -1043,7 +1050,7 @@ int target_emulate_request_sense(struct se_task *task)  		return -ENOSYS;  	} -	buf = transport_kmap_first_data_page(cmd); +	buf = transport_kmap_data_sg(cmd);  	if (!core_scsi3_ua_clear_for_request_sense(cmd, &ua_asc, &ua_ascq)) {  		/* @@ -1051,11 +1058,8 @@ int target_emulate_request_sense(struct se_task *task)  		 */  		buf[0] = 0x70;  		buf[SPC_SENSE_KEY_OFFSET] = UNIT_ATTENTION; -		/* -		 * Make sure request data length is enough for additional -		 * sense data. -		 */ -		if (cmd->data_length <= 18) { + +		if (cmd->data_length < 18) {  			buf[7] = 0x00;  			err = -EINVAL;  			goto end; @@ -1072,11 +1076,8 @@ int target_emulate_request_sense(struct se_task *task)  		 */  		buf[0] = 0x70;  		buf[SPC_SENSE_KEY_OFFSET] = NO_SENSE; -		/* -		 * Make sure request data length is enough for additional -		 * sense data. -		 */ -		if (cmd->data_length <= 18) { + +		if (cmd->data_length < 18) {  			buf[7] = 0x00;  			err = -EINVAL;  			goto end; @@ -1089,7 +1090,7 @@ int target_emulate_request_sense(struct se_task *task)  	}  end: -	transport_kunmap_first_data_page(cmd); +	transport_kunmap_data_sg(cmd);  	task->task_scsi_status = GOOD;  	transport_complete_task(task, 1);  	return 0; @@ -1123,7 +1124,7 @@ int target_emulate_unmap(struct se_task *task)  	dl = get_unaligned_be16(&cdb[0]);  	bd_dl = get_unaligned_be16(&cdb[2]); -	buf = transport_kmap_first_data_page(cmd); +	buf = transport_kmap_data_sg(cmd);  	ptr = &buf[offset];  	pr_debug("UNMAP: Sub: %s Using dl: %hu bd_dl: %hu size: %hu" @@ -1147,7 +1148,7 @@ int target_emulate_unmap(struct se_task *task)  	}  err: -	transport_kunmap_first_data_page(cmd); +	transport_kunmap_data_sg(cmd);  	if (!ret) {  		task->task_scsi_status = GOOD;  		transport_complete_task(task, 1); diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c index 0955bb8979f..6e043eeb1db 100644 --- a/drivers/target/target_core_configfs.c +++ b/drivers/target/target_core_configfs.c @@ -1704,13 +1704,15 @@ static ssize_t target_core_store_dev_alias(  		return -EINVAL;  	} -	se_dev->su_dev_flags |= SDF_USING_ALIAS;  	read_bytes = snprintf(&se_dev->se_dev_alias[0], SE_DEV_ALIAS_LEN,  			"%s", page); - +	if (!read_bytes) +		return -EINVAL;  	if (se_dev->se_dev_alias[read_bytes - 1] == '\n')  		se_dev->se_dev_alias[read_bytes - 1] = '\0'; +	se_dev->su_dev_flags |= SDF_USING_ALIAS; +  	pr_debug("Target_Core_ConfigFS: %s/%s set alias: %s\n",  		config_item_name(&hba->hba_group.cg_item),  		config_item_name(&se_dev->se_dev_group.cg_item), @@ -1753,13 +1755,15 @@ static ssize_t target_core_store_dev_udev_path(  		return -EINVAL;  	} -	se_dev->su_dev_flags |= SDF_USING_UDEV_PATH;  	read_bytes = snprintf(&se_dev->se_dev_udev_path[0], SE_UDEV_PATH_LEN,  			"%s", page); - +	if (!read_bytes) +		return -EINVAL;  	if (se_dev->se_dev_udev_path[read_bytes - 1] == '\n')  		se_dev->se_dev_udev_path[read_bytes - 1] = '\0'; +	se_dev->su_dev_flags |= SDF_USING_UDEV_PATH; +  	pr_debug("Target_Core_ConfigFS: %s/%s set udev_path: %s\n",  		config_item_name(&hba->hba_group.cg_item),  		config_item_name(&se_dev->se_dev_group.cg_item), diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index 0c5992f0d94..edbcabbf85f 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -320,11 +320,12 @@ int core_free_device_list_for_node(  void core_dec_lacl_count(struct se_node_acl *se_nacl, struct se_cmd *se_cmd)  {  	struct se_dev_entry *deve; +	unsigned long flags; -	spin_lock_irq(&se_nacl->device_list_lock); +	spin_lock_irqsave(&se_nacl->device_list_lock, flags);  	deve = &se_nacl->device_list[se_cmd->orig_fe_lun];  	deve->deve_cmds--; -	spin_unlock_irq(&se_nacl->device_list_lock); +	spin_unlock_irqrestore(&se_nacl->device_list_lock, flags);  }  void core_update_device_list_access( @@ -656,7 +657,7 @@ int target_report_luns(struct se_task *se_task)  	unsigned char *buf;  	u32 cdb_offset = 0, lun_count = 0, offset = 8, i; -	buf = transport_kmap_first_data_page(se_cmd); +	buf = (unsigned char *) transport_kmap_data_sg(se_cmd);  	/*  	 * If no struct se_session pointer is present, this struct se_cmd is @@ -694,7 +695,7 @@ int target_report_luns(struct se_task *se_task)  	 * See SPC3 r07, page 159.  	 */  done: -	transport_kunmap_first_data_page(se_cmd); +	transport_kunmap_data_sg(se_cmd);  	lun_count *= 8;  	buf[0] = ((lun_count >> 24) & 0xff);  	buf[1] = ((lun_count >> 16) & 0xff); @@ -1294,24 +1295,26 @@ struct se_lun *core_dev_add_lun(  {  	struct se_lun *lun_p;  	u32 lun_access = 0; +	int rc;  	if (atomic_read(&dev->dev_access_obj.obj_access_count) != 0) {  		pr_err("Unable to export struct se_device while dev_access_obj: %d\n",  			atomic_read(&dev->dev_access_obj.obj_access_count)); -		return NULL; +		return ERR_PTR(-EACCES);  	}  	lun_p = core_tpg_pre_addlun(tpg, lun); -	if ((IS_ERR(lun_p)) || !lun_p) -		return NULL; +	if (IS_ERR(lun_p)) +		return lun_p;  	if (dev->dev_flags & DF_READ_ONLY)  		lun_access = TRANSPORT_LUNFLAGS_READ_ONLY;  	else  		lun_access = TRANSPORT_LUNFLAGS_READ_WRITE; -	if (core_tpg_post_addlun(tpg, lun_p, lun_access, dev) < 0) -		return NULL; +	rc = core_tpg_post_addlun(tpg, lun_p, lun_access, dev); +	if (rc < 0) +		return ERR_PTR(rc);  	pr_debug("%s_TPG[%u]_LUN[%u] - Activated %s Logical Unit from"  		" CORE HBA: %u\n", tpg->se_tpg_tfo->get_fabric_name(), @@ -1348,11 +1351,10 @@ int core_dev_del_lun(  	u32 unpacked_lun)  {  	struct se_lun *lun; -	int ret = 0; -	lun = core_tpg_pre_dellun(tpg, unpacked_lun, &ret); -	if (!lun) -		return ret; +	lun = core_tpg_pre_dellun(tpg, unpacked_lun); +	if (IS_ERR(lun)) +		return PTR_ERR(lun);  	core_tpg_post_dellun(tpg, lun); diff --git a/drivers/target/target_core_fabric_configfs.c b/drivers/target/target_core_fabric_configfs.c index 4f77cce2264..9a2ce11e1a6 100644 --- a/drivers/target/target_core_fabric_configfs.c +++ b/drivers/target/target_core_fabric_configfs.c @@ -766,9 +766,9 @@ static int target_fabric_port_link(  	lun_p = core_dev_add_lun(se_tpg, dev->se_hba, dev,  				lun->unpacked_lun); -	if (IS_ERR(lun_p) || !lun_p) { +	if (IS_ERR(lun_p)) {  		pr_err("core_dev_add_lun() failed\n"); -		ret = -EINVAL; +		ret = PTR_ERR(lun_p);  		goto out;  	} diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c index cc8e6b58ef2..8572eae62da 100644 --- a/drivers/target/target_core_iblock.c +++ b/drivers/target/target_core_iblock.c @@ -129,7 +129,7 @@ static struct se_device *iblock_create_virtdevice(  	/*  	 * These settings need to be made tunable..  	 */ -	ib_dev->ibd_bio_set = bioset_create(32, 64); +	ib_dev->ibd_bio_set = bioset_create(32, 0);  	if (!ib_dev->ibd_bio_set) {  		pr_err("IBLOCK: Unable to create bioset()\n");  		return ERR_PTR(-ENOMEM); @@ -181,7 +181,7 @@ static struct se_device *iblock_create_virtdevice(  		 */  		dev->se_sub_dev->se_dev_attrib.max_unmap_block_desc_count = 1;  		dev->se_sub_dev->se_dev_attrib.unmap_granularity = -				q->limits.discard_granularity; +				q->limits.discard_granularity >> 9;  		dev->se_sub_dev->se_dev_attrib.unmap_granularity_alignment =  				q->limits.discard_alignment; @@ -488,6 +488,13 @@ iblock_get_bio(struct se_task *task, sector_t lba, u32 sg_num)  	struct iblock_req *ib_req = IBLOCK_REQ(task);  	struct bio *bio; +	/* +	 * Only allocate as many vector entries as the bio code allows us to, +	 * we'll loop later on until we have handled the whole request. +	 */ +	if (sg_num > BIO_MAX_PAGES) +		sg_num = BIO_MAX_PAGES; +  	bio = bio_alloc_bioset(GFP_NOIO, sg_num, ib_dev->ibd_bio_set);  	if (!bio) {  		pr_err("Unable to allocate memory for bio\n"); diff --git a/drivers/target/target_core_internal.h b/drivers/target/target_core_internal.h index 26f135e94f6..45001364788 100644 --- a/drivers/target/target_core_internal.h +++ b/drivers/target/target_core_internal.h @@ -90,7 +90,7 @@ void	core_tpg_wait_for_nacl_pr_ref(struct se_node_acl *);  struct se_lun *core_tpg_pre_addlun(struct se_portal_group *, u32);  int	core_tpg_post_addlun(struct se_portal_group *, struct se_lun *,  		u32, void *); -struct se_lun *core_tpg_pre_dellun(struct se_portal_group *, u32, int *); +struct se_lun *core_tpg_pre_dellun(struct se_portal_group *, u32 unpacked_lun);  int	core_tpg_post_dellun(struct se_portal_group *, struct se_lun *);  /* target_core_transport.c */ diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index 429ad729166..b7c779389ee 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c @@ -478,6 +478,7 @@ static int core_scsi3_pr_seq_non_holder(  	case READ_MEDIA_SERIAL_NUMBER:  	case REPORT_LUNS:  	case REQUEST_SENSE: +	case PERSISTENT_RESERVE_IN:  		ret = 0; /*/ Allowed CDBs */  		break;  	default: @@ -1534,7 +1535,7 @@ static int core_scsi3_decode_spec_i_port(  	tidh_new->dest_local_nexus = 1;  	list_add_tail(&tidh_new->dest_list, &tid_dest_list); -	buf = transport_kmap_first_data_page(cmd); +	buf = transport_kmap_data_sg(cmd);  	/*  	 * For a PERSISTENT RESERVE OUT specify initiator ports payload,  	 * first extract TransportID Parameter Data Length, and make sure @@ -1785,7 +1786,7 @@ static int core_scsi3_decode_spec_i_port(  	} -	transport_kunmap_first_data_page(cmd); +	transport_kunmap_data_sg(cmd);  	/*  	 * Go ahead and create a registrations from tid_dest_list for the @@ -1833,7 +1834,7 @@ static int core_scsi3_decode_spec_i_port(  	return 0;  out: -	transport_kunmap_first_data_page(cmd); +	transport_kunmap_data_sg(cmd);  	/*  	 * For the failure case, release everything from tid_dest_list  	 * including *dest_pr_reg and the configfs dependances.. @@ -3120,7 +3121,7 @@ static int core_scsi3_pro_preempt(  			if (!calling_it_nexus)  				core_scsi3_ua_allocate(pr_reg_nacl,  					pr_res_mapped_lun, 0x2A, -					ASCQ_2AH_RESERVATIONS_PREEMPTED); +					ASCQ_2AH_REGISTRATIONS_PREEMPTED);  		}  		spin_unlock(&pr_tmpl->registration_lock);  		/* @@ -3233,7 +3234,7 @@ static int core_scsi3_pro_preempt(  		 *    additional sense code set to REGISTRATIONS PREEMPTED;  		 */  		core_scsi3_ua_allocate(pr_reg_nacl, pr_res_mapped_lun, 0x2A, -				ASCQ_2AH_RESERVATIONS_PREEMPTED); +				ASCQ_2AH_REGISTRATIONS_PREEMPTED);  	}  	spin_unlock(&pr_tmpl->registration_lock);  	/* @@ -3410,14 +3411,14 @@ static int core_scsi3_emulate_pro_register_and_move(  	 * will be moved to for the TransportID containing SCSI initiator WWN  	 * information.  	 */ -	buf = transport_kmap_first_data_page(cmd); +	buf = transport_kmap_data_sg(cmd);  	rtpi = (buf[18] & 0xff) << 8;  	rtpi |= buf[19] & 0xff;  	tid_len = (buf[20] & 0xff) << 24;  	tid_len |= (buf[21] & 0xff) << 16;  	tid_len |= (buf[22] & 0xff) << 8;  	tid_len |= buf[23] & 0xff; -	transport_kunmap_first_data_page(cmd); +	transport_kunmap_data_sg(cmd);  	buf = NULL;  	if ((tid_len + 24) != cmd->data_length) { @@ -3469,7 +3470,7 @@ static int core_scsi3_emulate_pro_register_and_move(  		return -EINVAL;  	} -	buf = transport_kmap_first_data_page(cmd); +	buf = transport_kmap_data_sg(cmd);  	proto_ident = (buf[24] & 0x0f);  #if 0  	pr_debug("SPC-3 PR REGISTER_AND_MOVE: Extracted Protocol Identifier:" @@ -3503,7 +3504,7 @@ static int core_scsi3_emulate_pro_register_and_move(  		goto out;  	} -	transport_kunmap_first_data_page(cmd); +	transport_kunmap_data_sg(cmd);  	buf = NULL;  	pr_debug("SPC-3 PR [%s] Extracted initiator %s identifier: %s" @@ -3768,13 +3769,13 @@ after_iport_check:  					" REGISTER_AND_MOVE\n");  	} -	transport_kunmap_first_data_page(cmd); +	transport_kunmap_data_sg(cmd);  	core_scsi3_put_pr_reg(dest_pr_reg);  	return 0;  out:  	if (buf) -		transport_kunmap_first_data_page(cmd); +		transport_kunmap_data_sg(cmd);  	if (dest_se_deve)  		core_scsi3_lunacl_undepend_item(dest_se_deve);  	if (dest_node_acl) @@ -3848,7 +3849,7 @@ int target_scsi3_emulate_pr_out(struct se_task *task)  	scope = (cdb[2] & 0xf0);  	type = (cdb[2] & 0x0f); -	buf = transport_kmap_first_data_page(cmd); +	buf = transport_kmap_data_sg(cmd);  	/*  	 * From PERSISTENT_RESERVE_OUT parameter list (payload)  	 */ @@ -3866,7 +3867,7 @@ int target_scsi3_emulate_pr_out(struct se_task *task)  		aptpl = (buf[17] & 0x01);  		unreg = (buf[17] & 0x02);  	} -	transport_kunmap_first_data_page(cmd); +	transport_kunmap_data_sg(cmd);  	buf = NULL;  	/* @@ -3966,7 +3967,7 @@ static int core_scsi3_pri_read_keys(struct se_cmd *cmd)  		return -EINVAL;  	} -	buf = transport_kmap_first_data_page(cmd); +	buf = transport_kmap_data_sg(cmd);  	buf[0] = ((su_dev->t10_pr.pr_generation >> 24) & 0xff);  	buf[1] = ((su_dev->t10_pr.pr_generation >> 16) & 0xff);  	buf[2] = ((su_dev->t10_pr.pr_generation >> 8) & 0xff); @@ -4000,7 +4001,7 @@ static int core_scsi3_pri_read_keys(struct se_cmd *cmd)  	buf[6] = ((add_len >> 8) & 0xff);  	buf[7] = (add_len & 0xff); -	transport_kunmap_first_data_page(cmd); +	transport_kunmap_data_sg(cmd);  	return 0;  } @@ -4026,7 +4027,7 @@ static int core_scsi3_pri_read_reservation(struct se_cmd *cmd)  		return -EINVAL;  	} -	buf = transport_kmap_first_data_page(cmd); +	buf = transport_kmap_data_sg(cmd);  	buf[0] = ((su_dev->t10_pr.pr_generation >> 24) & 0xff);  	buf[1] = ((su_dev->t10_pr.pr_generation >> 16) & 0xff);  	buf[2] = ((su_dev->t10_pr.pr_generation >> 8) & 0xff); @@ -4085,7 +4086,7 @@ static int core_scsi3_pri_read_reservation(struct se_cmd *cmd)  err:  	spin_unlock(&se_dev->dev_reservation_lock); -	transport_kunmap_first_data_page(cmd); +	transport_kunmap_data_sg(cmd);  	return 0;  } @@ -4109,7 +4110,7 @@ static int core_scsi3_pri_report_capabilities(struct se_cmd *cmd)  		return -EINVAL;  	} -	buf = transport_kmap_first_data_page(cmd); +	buf = transport_kmap_data_sg(cmd);  	buf[0] = ((add_len << 8) & 0xff);  	buf[1] = (add_len & 0xff); @@ -4141,7 +4142,7 @@ static int core_scsi3_pri_report_capabilities(struct se_cmd *cmd)  	buf[4] |= 0x02; /* PR_TYPE_WRITE_EXCLUSIVE */  	buf[5] |= 0x01; /* PR_TYPE_EXCLUSIVE_ACCESS_ALLREG */ -	transport_kunmap_first_data_page(cmd); +	transport_kunmap_data_sg(cmd);  	return 0;  } @@ -4171,7 +4172,7 @@ static int core_scsi3_pri_read_full_status(struct se_cmd *cmd)  		return -EINVAL;  	} -	buf = transport_kmap_first_data_page(cmd); +	buf = transport_kmap_data_sg(cmd);  	buf[0] = ((su_dev->t10_pr.pr_generation >> 24) & 0xff);  	buf[1] = ((su_dev->t10_pr.pr_generation >> 16) & 0xff); @@ -4292,7 +4293,7 @@ static int core_scsi3_pri_read_full_status(struct se_cmd *cmd)  	buf[6] = ((add_len >> 8) & 0xff);  	buf[7] = (add_len & 0xff); -	transport_kunmap_first_data_page(cmd); +	transport_kunmap_data_sg(cmd);  	return 0;  } diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c index d35467d42e1..8d4def30e9e 100644 --- a/drivers/target/target_core_pscsi.c +++ b/drivers/target/target_core_pscsi.c @@ -693,7 +693,7 @@ static int pscsi_transport_complete(struct se_task *task)  		if (task->task_se_cmd->se_deve->lun_flags &  				TRANSPORT_LUNFLAGS_READ_ONLY) { -			unsigned char *buf = transport_kmap_first_data_page(task->task_se_cmd); +			unsigned char *buf = transport_kmap_data_sg(task->task_se_cmd);  			if (cdb[0] == MODE_SENSE_10) {  				if (!(buf[3] & 0x80)) @@ -703,7 +703,7 @@ static int pscsi_transport_complete(struct se_task *task)  					buf[2] |= 0x80;  			} -			transport_kunmap_first_data_page(task->task_se_cmd); +			transport_kunmap_data_sg(task->task_se_cmd);  		}  	}  after_mode_sense: diff --git a/drivers/target/target_core_tpg.c b/drivers/target/target_core_tpg.c index b7668029bb3..06336ecd872 100644 --- a/drivers/target/target_core_tpg.c +++ b/drivers/target/target_core_tpg.c @@ -807,8 +807,7 @@ static void core_tpg_shutdown_lun(  struct se_lun *core_tpg_pre_dellun(  	struct se_portal_group *tpg, -	u32 unpacked_lun, -	int *ret) +	u32 unpacked_lun)  {  	struct se_lun *lun; diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index d3ddd136194..58cea07b12f 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -1255,32 +1255,34 @@ static void core_setup_task_attr_emulation(struct se_device *dev)  static void scsi_dump_inquiry(struct se_device *dev)  {  	struct t10_wwn *wwn = &dev->se_sub_dev->t10_wwn; +	char buf[17];  	int i, device_type;  	/*  	 * Print Linux/SCSI style INQUIRY formatting to the kernel ring buffer  	 */ -	pr_debug("  Vendor: ");  	for (i = 0; i < 8; i++)  		if (wwn->vendor[i] >= 0x20) -			pr_debug("%c", wwn->vendor[i]); +			buf[i] = wwn->vendor[i];  		else -			pr_debug(" "); +			buf[i] = ' '; +	buf[i] = '\0'; +	pr_debug("  Vendor: %s\n", buf); -	pr_debug("  Model: ");  	for (i = 0; i < 16; i++)  		if (wwn->model[i] >= 0x20) -			pr_debug("%c", wwn->model[i]); +			buf[i] = wwn->model[i];  		else -			pr_debug(" "); +			buf[i] = ' '; +	buf[i] = '\0'; +	pr_debug("  Model: %s\n", buf); -	pr_debug("  Revision: ");  	for (i = 0; i < 4; i++)  		if (wwn->revision[i] >= 0x20) -			pr_debug("%c", wwn->revision[i]); +			buf[i] = wwn->revision[i];  		else -			pr_debug(" "); - -	pr_debug("\n"); +			buf[i] = ' '; +	buf[i] = '\0'; +	pr_debug("  Revision: %s\n", buf);  	device_type = dev->transport->get_device_type(dev);  	pr_debug("  Type:   %s ", scsi_device_type(device_type)); @@ -1655,7 +1657,7 @@ EXPORT_SYMBOL(transport_handle_cdb_direct);   * This may only be called from process context, and also currently   * assumes internal allocation of fabric payload buffer by target-core.   **/ -int target_submit_cmd(struct se_cmd *se_cmd, struct se_session *se_sess, +void target_submit_cmd(struct se_cmd *se_cmd, struct se_session *se_sess,  		unsigned char *cdb, unsigned char *sense, u32 unpacked_lun,  		u32 data_length, int task_attr, int data_dir, int flags)  { @@ -1688,15 +1690,21 @@ int target_submit_cmd(struct se_cmd *se_cmd, struct se_session *se_sess,  	/*  	 * Locate se_lun pointer and attach it to struct se_cmd  	 */ -	if (transport_lookup_cmd_lun(se_cmd, unpacked_lun) < 0) -		goto out_check_cond; +	if (transport_lookup_cmd_lun(se_cmd, unpacked_lun) < 0) { +		transport_send_check_condition_and_sense(se_cmd, +				se_cmd->scsi_sense_reason, 0); +		target_put_sess_cmd(se_sess, se_cmd); +		return; +	}  	/*  	 * Sanitize CDBs via transport_generic_cmd_sequencer() and  	 * allocate the necessary tasks to complete the received CDB+data  	 */  	rc = transport_generic_allocate_tasks(se_cmd, cdb); -	if (rc != 0) -		goto out_check_cond; +	if (rc != 0) { +		transport_generic_request_failure(se_cmd); +		return; +	}  	/*  	 * Dispatch se_cmd descriptor to se_lun->lun_se_dev backend  	 * for immediate execution of READs, otherwise wait for @@ -1704,12 +1712,7 @@ int target_submit_cmd(struct se_cmd *se_cmd, struct se_session *se_sess,  	 * when fabric has filled the incoming buffer.  	 */  	transport_handle_cdb_direct(se_cmd); -	return 0; - -out_check_cond: -	transport_send_check_condition_and_sense(se_cmd, -				se_cmd->scsi_sense_reason, 0); -	return 0; +	return;  }  EXPORT_SYMBOL(target_submit_cmd); @@ -2694,7 +2697,7 @@ static int transport_generic_cmd_sequencer(  			cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;  			if (target_check_write_same_discard(&cdb[10], dev) < 0) -				goto out_invalid_cdb_field; +				goto out_unsupported_cdb;  			if (!passthrough)  				cmd->execute_task = target_emulate_write_same;  			break; @@ -2977,7 +2980,7 @@ static int transport_generic_cmd_sequencer(  		cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;  		if (target_check_write_same_discard(&cdb[1], dev) < 0) -			goto out_invalid_cdb_field; +			goto out_unsupported_cdb;  		if (!passthrough)  			cmd->execute_task = target_emulate_write_same;  		break; @@ -3000,7 +3003,7 @@ static int transport_generic_cmd_sequencer(  		 * of byte 1 bit 3 UNMAP instead of original reserved field  		 */  		if (target_check_write_same_discard(&cdb[1], dev) < 0) -			goto out_invalid_cdb_field; +			goto out_unsupported_cdb;  		if (!passthrough)  			cmd->execute_task = target_emulate_write_same;  		break; @@ -3082,11 +3085,6 @@ static int transport_generic_cmd_sequencer(  	     (cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB)))  		goto out_unsupported_cdb; -	/* Let's limit control cdbs to a page, for simplicity's sake. */ -	if ((cmd->se_cmd_flags & SCF_SCSI_CONTROL_SG_IO_CDB) && -	    size > PAGE_SIZE) -		goto out_invalid_cdb_field; -  	transport_set_supported_SAM_opcode(cmd);  	return ret; @@ -3490,9 +3488,11 @@ int transport_generic_map_mem_to_cmd(  }  EXPORT_SYMBOL(transport_generic_map_mem_to_cmd); -void *transport_kmap_first_data_page(struct se_cmd *cmd) +void *transport_kmap_data_sg(struct se_cmd *cmd)  {  	struct scatterlist *sg = cmd->t_data_sg; +	struct page **pages; +	int i;  	BUG_ON(!sg);  	/* @@ -3500,15 +3500,41 @@ void *transport_kmap_first_data_page(struct se_cmd *cmd)  	 * tcm_loop who may be using a contig buffer from the SCSI midlayer for  	 * control CDBs passed as SGLs via transport_generic_map_mem_to_cmd()  	 */ -	return kmap(sg_page(sg)) + sg->offset; +	if (!cmd->t_data_nents) +		return NULL; +	else if (cmd->t_data_nents == 1) +		return kmap(sg_page(sg)) + sg->offset; + +	/* >1 page. use vmap */ +	pages = kmalloc(sizeof(*pages) * cmd->t_data_nents, GFP_KERNEL); +	if (!pages) +		return NULL; + +	/* convert sg[] to pages[] */ +	for_each_sg(cmd->t_data_sg, sg, cmd->t_data_nents, i) { +		pages[i] = sg_page(sg); +	} + +	cmd->t_data_vmap = vmap(pages, cmd->t_data_nents,  VM_MAP, PAGE_KERNEL); +	kfree(pages); +	if (!cmd->t_data_vmap) +		return NULL; + +	return cmd->t_data_vmap + cmd->t_data_sg[0].offset;  } -EXPORT_SYMBOL(transport_kmap_first_data_page); +EXPORT_SYMBOL(transport_kmap_data_sg); -void transport_kunmap_first_data_page(struct se_cmd *cmd) +void transport_kunmap_data_sg(struct se_cmd *cmd)  { -	kunmap(sg_page(cmd->t_data_sg)); +	if (!cmd->t_data_nents) +		return; +	else if (cmd->t_data_nents == 1) +		kunmap(sg_page(cmd->t_data_sg)); + +	vunmap(cmd->t_data_vmap); +	cmd->t_data_vmap = NULL;  } -EXPORT_SYMBOL(transport_kunmap_first_data_page); +EXPORT_SYMBOL(transport_kunmap_data_sg);  static int  transport_generic_get_mem(struct se_cmd *cmd) @@ -3516,6 +3542,7 @@ transport_generic_get_mem(struct se_cmd *cmd)  	u32 length = cmd->data_length;  	unsigned int nents;  	struct page *page; +	gfp_t zero_flag;  	int i = 0;  	nents = DIV_ROUND_UP(length, PAGE_SIZE); @@ -3526,9 +3553,11 @@ transport_generic_get_mem(struct se_cmd *cmd)  	cmd->t_data_nents = nents;  	sg_init_table(cmd->t_data_sg, nents); +	zero_flag = cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB ? 0 : __GFP_ZERO; +  	while (length) {  		u32 page_len = min_t(u32, length, PAGE_SIZE); -		page = alloc_page(GFP_KERNEL | __GFP_ZERO); +		page = alloc_page(GFP_KERNEL | zero_flag);  		if (!page)  			goto out; @@ -3756,6 +3785,11 @@ transport_allocate_control_task(struct se_cmd *cmd)  	struct se_task *task;  	unsigned long flags; +	/* Workaround for handling zero-length control CDBs */ +	if ((cmd->se_cmd_flags & SCF_SCSI_CONTROL_SG_IO_CDB) && +	    !cmd->data_length) +		return 0; +  	task = transport_generic_get_task(cmd, cmd->data_direction);  	if (!task)  		return -ENOMEM; @@ -3827,6 +3861,14 @@ int transport_generic_new_cmd(struct se_cmd *cmd)  	else if (!task_cdbs && (cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB)) {  		cmd->t_state = TRANSPORT_COMPLETE;  		atomic_set(&cmd->t_transport_active, 1); + +		if (cmd->t_task_cdb[0] == REQUEST_SENSE) { +			u8 ua_asc = 0, ua_ascq = 0; + +			core_scsi3_ua_clear_for_request_sense(cmd, +					&ua_asc, &ua_ascq); +		} +  		INIT_WORK(&cmd->work, target_complete_ok_work);  		queue_work(target_completion_wq, &cmd->work);  		return 0; @@ -4448,8 +4490,8 @@ int transport_send_check_condition_and_sense(  		/* CURRENT ERROR */  		buffer[offset] = 0x70;  		buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10; -		/* ABORTED COMMAND */ -		buffer[offset+SPC_SENSE_KEY_OFFSET] = ABORTED_COMMAND; +		/* ILLEGAL REQUEST */ +		buffer[offset+SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;  		/* INVALID FIELD IN CDB */  		buffer[offset+SPC_ASC_KEY_OFFSET] = 0x24;  		break; @@ -4457,8 +4499,8 @@ int transport_send_check_condition_and_sense(  		/* CURRENT ERROR */  		buffer[offset] = 0x70;  		buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10; -		/* ABORTED COMMAND */ -		buffer[offset+SPC_SENSE_KEY_OFFSET] = ABORTED_COMMAND; +		/* ILLEGAL REQUEST */ +		buffer[offset+SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;  		/* INVALID FIELD IN PARAMETER LIST */  		buffer[offset+SPC_ASC_KEY_OFFSET] = 0x26;  		break; diff --git a/drivers/target/tcm_fc/tfc_cmd.c b/drivers/target/tcm_fc/tfc_cmd.c index addc18f727e..9e7e26c74c7 100644 --- a/drivers/target/tcm_fc/tfc_cmd.c +++ b/drivers/target/tcm_fc/tfc_cmd.c @@ -540,7 +540,6 @@ static void ft_send_work(struct work_struct *work)  	int data_dir = 0;  	u32 data_len;  	int task_attr; -	int ret;  	fcp = fc_frame_payload_get(cmd->req_frame, sizeof(*fcp));  	if (!fcp) @@ -603,14 +602,10 @@ static void ft_send_work(struct work_struct *work)  	 * Use a single se_cmd->cmd_kref as we expect to release se_cmd  	 * directly from ft_check_stop_free callback in response path.  	 */ -	ret = target_submit_cmd(&cmd->se_cmd, cmd->sess->se_sess, cmd->cdb, +	target_submit_cmd(&cmd->se_cmd, cmd->sess->se_sess, cmd->cdb,  				&cmd->ft_sense_buffer[0], cmd->lun, data_len,  				task_attr, data_dir, 0); -	pr_debug("r_ctl %x alloc target_submit_cmd %d\n", fh->fh_r_ctl, ret); -	if (ret < 0) { -		ft_dump_cmd(cmd, __func__); -		return; -	} +	pr_debug("r_ctl %x alloc target_submit_cmd\n", fh->fh_r_ctl);  	return;  err: diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c index 9f50c4e3c2b..9b7336fcfbb 100644 --- a/drivers/tty/serial/8250/8250.c +++ b/drivers/tty/serial/8250/8250.c @@ -45,7 +45,7 @@  #include "8250.h"  #ifdef CONFIG_SPARC -#include "suncore.h" +#include "../suncore.h"  #endif  /* diff --git a/drivers/tty/serial/8250/m32r_sio.c b/drivers/tty/serial/m32r_sio.c index 94a6792bf97..94a6792bf97 100644 --- a/drivers/tty/serial/8250/m32r_sio.c +++ b/drivers/tty/serial/m32r_sio.c diff --git a/drivers/tty/serial/8250/m32r_sio.h b/drivers/tty/serial/m32r_sio.h index e9b7e11793b..e9b7e11793b 100644 --- a/drivers/tty/serial/8250/m32r_sio.h +++ b/drivers/tty/serial/m32r_sio.h diff --git a/drivers/tty/serial/8250/m32r_sio_reg.h b/drivers/tty/serial/m32r_sio_reg.h index 4671473793e..4671473793e 100644 --- a/drivers/tty/serial/8250/m32r_sio_reg.h +++ b/drivers/tty/serial/m32r_sio_reg.h diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index 1c242693148..f80904145fd 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -46,6 +46,13 @@  #define DEFAULT_CLK_SPEED 48000000 /* 48Mhz*/ +/* SCR register bitmasks */ +#define OMAP_UART_SCR_RX_TRIG_GRANU1_MASK		(1 << 7) + +/* FCR register bitmasks */ +#define OMAP_UART_FCR_RX_FIFO_TRIG_SHIFT		6 +#define OMAP_UART_FCR_RX_FIFO_TRIG_MASK			(0x3 << 6) +  static struct uart_omap_port *ui[OMAP_MAX_HSUART_PORTS];  /* Forward declaration of functions */ @@ -129,6 +136,7 @@ static void serial_omap_enable_ms(struct uart_port *port)  static void serial_omap_stop_tx(struct uart_port *port)  {  	struct uart_omap_port *up = (struct uart_omap_port *)port; +	struct omap_uart_port_info *pdata = up->pdev->dev.platform_data;  	if (up->use_dma &&  		up->uart_dma.tx_dma_channel != OMAP_UART_DMA_CH_FREE) { @@ -151,6 +159,9 @@ static void serial_omap_stop_tx(struct uart_port *port)  		serial_out(up, UART_IER, up->ier);  	} +	if (!up->use_dma && pdata->set_forceidle) +		pdata->set_forceidle(up->pdev); +  	pm_runtime_mark_last_busy(&up->pdev->dev);  	pm_runtime_put_autosuspend(&up->pdev->dev);  } @@ -279,6 +290,7 @@ static inline void serial_omap_enable_ier_thri(struct uart_omap_port *up)  static void serial_omap_start_tx(struct uart_port *port)  {  	struct uart_omap_port *up = (struct uart_omap_port *)port; +	struct omap_uart_port_info *pdata = up->pdev->dev.platform_data;  	struct circ_buf *xmit;  	unsigned int start;  	int ret = 0; @@ -286,6 +298,8 @@ static void serial_omap_start_tx(struct uart_port *port)  	if (!up->use_dma) {  		pm_runtime_get_sync(&up->pdev->dev);  		serial_omap_enable_ier_thri(up); +		if (pdata->set_noidle) +			pdata->set_noidle(up->pdev);  		pm_runtime_mark_last_busy(&up->pdev->dev);  		pm_runtime_put_autosuspend(&up->pdev->dev);  		return; @@ -726,8 +740,7 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,  	quot = serial_omap_get_divisor(port, baud);  	/* calculate wakeup latency constraint */ -	up->calc_latency = (1000000 * up->port.fifosize) / -				(1000 * baud / 8); +	up->calc_latency = (USEC_PER_SEC * up->port.fifosize) / (baud / 8);  	up->latency = up->calc_latency;  	schedule_work(&up->qos_work); @@ -811,14 +824,21 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,  	up->mcr = serial_in(up, UART_MCR);  	serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR);  	/* FIFO ENABLE, DMA MODE */ -	serial_out(up, UART_FCR, up->fcr); -	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); + +	up->scr |= OMAP_UART_SCR_RX_TRIG_GRANU1_MASK;  	if (up->use_dma) {  		serial_out(up, UART_TI752_TLR, 0); -		up->scr |= (UART_FCR_TRIGGER_4 | UART_FCR_TRIGGER_8); +		up->scr |= UART_FCR_TRIGGER_4; +	} else { +		/* Set receive FIFO threshold to 1 byte */ +		up->fcr &= ~OMAP_UART_FCR_RX_FIFO_TRIG_MASK; +		up->fcr |= (0x1 << OMAP_UART_FCR_RX_FIFO_TRIG_SHIFT);  	} +	serial_out(up, UART_FCR, up->fcr); +	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); +  	serial_out(up, UART_OMAP_SCR, up->scr);  	serial_out(up, UART_EFR, up->efr); diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c index f96f37b5fec..c55e5fb16fa 100644 --- a/drivers/tty/serial/samsung.c +++ b/drivers/tty/serial/samsung.c @@ -1593,7 +1593,8 @@ static struct s3c24xx_serial_drv_data s5pv210_serial_drv_data = {  #define S5PV210_SERIAL_DRV_DATA	(kernel_ulong_t)NULL  #endif -#ifdef CONFIG_CPU_EXYNOS4210 +#if defined(CONFIG_CPU_EXYNOS4210) || defined(CONFIG_SOC_EXYNOS4212) || \ +	defined(CONFIG_SOC_EXYNOS4412) || defined(CONFIG_SOC_EXYNOS5250)  static struct s3c24xx_serial_drv_data exynos4210_serial_drv_data = {  	.info = &(struct s3c24xx_uart_info) {  		.name		= "Samsung Exynos4 UART", diff --git a/drivers/tty/vt/vt_ioctl.c b/drivers/tty/vt/vt_ioctl.c index 5e096f43bce..65447c5f91d 100644 --- a/drivers/tty/vt/vt_ioctl.c +++ b/drivers/tty/vt/vt_ioctl.c @@ -1463,7 +1463,6 @@ compat_kdfontop_ioctl(struct compat_console_font_op __user *fontop,  	if (!perm && op->op != KD_FONT_OP_GET)  		return -EPERM;  	op->data = compat_ptr(((struct compat_console_font_op *)op)->data); -	op->flags |= KD_FONT_FLAG_OLD;  	i = con_font_op(vc, op);  	if (i)  		return i; diff --git a/drivers/usb/gadget/f_loopback.c b/drivers/usb/gadget/f_loopback.c index 6d87f288df4..2c0cd824c66 100644 --- a/drivers/usb/gadget/f_loopback.c +++ b/drivers/usb/gadget/f_loopback.c @@ -418,7 +418,7 @@ int __init loopback_add(struct usb_composite_dev *cdev, bool autoresume)  	/* support autoresume for remote wakeup testing */  	if (autoresume) -		sourcesink_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP; +		loopback_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;  	/* support OTG systems */  	if (gadget_is_otg(cdev->gadget)) { diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 91413cac97b..353cdd488b9 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -130,7 +130,7 @@ config USB_FSL_MPH_DR_OF  	tristate  config USB_EHCI_FSL -	bool "Support for Freescale on-chip EHCI USB controller" +	bool "Support for Freescale PPC on-chip EHCI USB controller"  	depends on USB_EHCI_HCD && FSL_SOC  	select USB_EHCI_ROOT_HUB_TT  	select USB_FSL_MPH_DR_OF if OF @@ -138,7 +138,7 @@ config USB_EHCI_FSL  	  Variation of ARC USB block used in some Freescale chips.  config USB_EHCI_MXC -	bool "Support for Freescale on-chip EHCI USB controller" +	bool "Support for Freescale i.MX on-chip EHCI USB controller"  	depends on USB_EHCI_HCD && ARCH_MXC  	select USB_EHCI_ROOT_HUB_TT  	---help--- @@ -546,7 +546,7 @@ config USB_RENESAS_USBHS_HCD  config USB_WHCI_HCD  	tristate "Wireless USB Host Controller Interface (WHCI) driver (EXPERIMENTAL)"  	depends on EXPERIMENTAL -	depends on PCI && USB +	depends on PCI && USB && UWB  	select USB_WUSB  	select UWB_WHCI  	help @@ -559,7 +559,7 @@ config USB_WHCI_HCD  config USB_HWA_HCD  	tristate "Host Wire Adapter (HWA) driver (EXPERIMENTAL)"  	depends on EXPERIMENTAL -	depends on USB +	depends on USB && UWB  	select USB_WUSB  	select UWB_HWA  	help diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index b556a72264d..c26a82e83f6 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c @@ -239,7 +239,7 @@ static void ehci_fsl_setup_phy(struct ehci_hcd *ehci,  	ehci_writel(ehci, portsc, &ehci->regs->port_status[port_offset]);  } -static void ehci_fsl_usb_setup(struct ehci_hcd *ehci) +static int ehci_fsl_usb_setup(struct ehci_hcd *ehci)  {  	struct usb_hcd *hcd = ehci_to_hcd(ehci);  	struct fsl_usb2_platform_data *pdata; @@ -299,12 +299,19 @@ static void ehci_fsl_usb_setup(struct ehci_hcd *ehci)  #endif  		out_be32(non_ehci + FSL_SOC_USB_SICTRL, 0x00000001);  	} + +	if (!(in_be32(non_ehci + FSL_SOC_USB_CTRL) & CTRL_PHY_CLK_VALID)) { +		printk(KERN_WARNING "fsl-ehci: USB PHY clock invalid\n"); +		return -ENODEV; +	} +	return 0;  }  /* called after powerup, by probe or system-pm "wakeup" */  static int ehci_fsl_reinit(struct ehci_hcd *ehci)  { -	ehci_fsl_usb_setup(ehci); +	if (ehci_fsl_usb_setup(ehci)) +		return -ENODEV;  	ehci_port_power(ehci, 0);  	return 0; diff --git a/drivers/usb/host/ehci-fsl.h b/drivers/usb/host/ehci-fsl.h index 49180622116..bdf43e2adc5 100644 --- a/drivers/usb/host/ehci-fsl.h +++ b/drivers/usb/host/ehci-fsl.h @@ -45,5 +45,6 @@  #define FSL_SOC_USB_PRICTRL	0x40c	/* NOTE: big-endian */  #define FSL_SOC_USB_SICTRL	0x410	/* NOTE: big-endian */  #define FSL_SOC_USB_CTRL	0x500	/* NOTE: big-endian */ +#define CTRL_PHY_CLK_VALID	(1 << 17)  #define SNOOP_SIZE_2GB		0x1e  #endif				/* _EHCI_FSL_H */ diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index caf87428ca4..ac53a662a6a 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c @@ -867,6 +867,12 @@ hc_init:  static void __devinit quirk_usb_early_handoff(struct pci_dev *pdev)  { +	/* Skip Netlogic mips SoC's internal PCI USB controller. +	 * This device does not need/support EHCI/OHCI handoff +	 */ +	if (pdev->vendor == 0x184e)	/* vendor Netlogic */ +		return; +  	if (pdev->class == PCI_CLASS_SERIAL_USB_UHCI)  		quirk_usb_handoff_uhci(pdev);  	else if (pdev->class == PCI_CLASS_SERIAL_USB_OHCI) diff --git a/drivers/usb/musb/musb_io.h b/drivers/usb/musb/musb_io.h index e61aa95f2d2..1d5eda26fbd 100644 --- a/drivers/usb/musb/musb_io.h +++ b/drivers/usb/musb/musb_io.h @@ -39,7 +39,8 @@  #if !defined(CONFIG_ARM) && !defined(CONFIG_SUPERH) \  	&& !defined(CONFIG_AVR32) && !defined(CONFIG_PPC32) \ -	&& !defined(CONFIG_PPC64) && !defined(CONFIG_BLACKFIN) +	&& !defined(CONFIG_PPC64) && !defined(CONFIG_BLACKFIN) \ +	&& !defined(CONFIG_MIPS)  static inline void readsl(const void __iomem *addr, void *buf, int len)  	{ insl((unsigned long)addr, buf, len); }  static inline void readsw(const void __iomem *addr, void *buf, int len) diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig index 76d62934541..735ef4c2339 100644 --- a/drivers/usb/otg/Kconfig +++ b/drivers/usb/otg/Kconfig @@ -118,7 +118,7 @@ config FSL_USB2_OTG  config USB_MV_OTG  	tristate "Marvell USB OTG support" -	depends on USB_MV_UDC && USB_SUSPEND +	depends on USB_EHCI_MV && USB_MV_UDC && USB_SUSPEND  	select USB_OTG  	select USB_OTG_UTILS  	help diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index ad654f8208e..f770415305f 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -839,6 +839,7 @@ static struct usb_device_id id_table_combined [] = {  	{ USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_LOGBOOKML_PID) },  	{ USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_LS_LOGBOOK_PID) },  	{ USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_HS_LOGBOOK_PID) }, +	{ USB_DEVICE(FTDI_VID, FTDI_CINTERION_MC55I_PID) },  	{ USB_DEVICE(FTDI_VID, FTDI_DOTEC_PID) },  	{ USB_DEVICE(QIHARDWARE_VID, MILKYMISTONE_JTAGSERIAL_PID),  		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index f994503df2d..6f6058f0db1 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -1187,3 +1187,10 @@   */  /* ZigBee controller */  #define FTDI_RF_R106		0x8A28 + +/* + * Product: HCP HIT GPRS modem + * Manufacturer: HCP d.o.o. + * ATI command output: Cinterion MC55i + */ +#define FTDI_CINTERION_MC55I_PID	0xA951 diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index ea126a4490c..39ed1f46cec 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -855,6 +855,18 @@ static const struct usb_device_id option_ids[] = {  	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0083, 0xff, 0xff, 0xff) },  	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0086, 0xff, 0xff, 0xff) },  	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0087, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0088, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0089, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0090, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0091, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0092, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0093, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0094, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0095, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0096, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0097, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0098, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0099, 0xff, 0xff, 0xff) },  	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0104, 0xff, 0xff, 0xff),  		.driver_info = (kernel_ulong_t)&net_intf4_blacklist },  	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0105, 0xff, 0xff, 0xff) }, @@ -883,7 +895,6 @@ static const struct usb_device_id option_ids[] = {  	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0151, 0xff, 0xff, 0xff) },  	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0152, 0xff, 0xff, 0xff) },  	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0153, 0xff, 0xff, 0xff) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0154, 0xff, 0xff, 0xff) },  	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0155, 0xff, 0xff, 0xff) },  	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0156, 0xff, 0xff, 0xff) },  	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0157, 0xff, 0xff, 0xff) }, @@ -892,6 +903,12 @@ static const struct usb_device_id option_ids[] = {  	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0160, 0xff, 0xff, 0xff) },  	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0161, 0xff, 0xff, 0xff) },  	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0162, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0164, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0165, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0168, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0170, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0176, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0178, 0xff, 0xff, 0xff) },  	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1008, 0xff, 0xff, 0xff) },  	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1010, 0xff, 0xff, 0xff) },  	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1012, 0xff, 0xff, 0xff) }, @@ -1066,6 +1083,116 @@ static const struct usb_device_id option_ids[] = {  	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1298, 0xff, 0xff, 0xff) },  	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1299, 0xff, 0xff, 0xff) },  	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1300, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1401, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1402, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1403, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1404, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1405, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1406, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1407, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1408, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1409, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1410, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1411, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1412, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1413, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1414, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1415, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1416, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1417, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1418, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1419, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1420, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1421, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1422, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1423, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1424, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1425, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1426, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1427, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1428, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1429, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1430, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1431, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1432, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1433, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1434, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1435, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1436, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1437, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1438, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1439, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1440, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1441, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1442, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1443, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1444, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1445, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1446, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1447, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1448, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1449, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1450, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1451, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1452, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1453, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1454, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1455, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1456, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1457, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1458, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1459, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1460, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1461, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1462, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1463, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1464, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1465, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1466, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1467, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1468, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1469, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1470, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1471, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1472, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1473, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1474, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1475, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1476, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1477, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1478, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1479, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1480, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1481, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1482, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1483, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1484, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1485, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1486, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1487, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1488, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1489, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1490, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1491, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1492, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1493, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1494, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1495, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1496, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1497, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1498, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1499, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1500, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1501, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1502, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1503, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1504, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1505, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1506, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1507, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1508, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1509, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1510, 0xff, 0xff, 0xff) },  	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0014, 0xff, 0xff, 0xff) }, /* ZTE CDMA products */  	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0027, 0xff, 0xff, 0xff) },  	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0059, 0xff, 0xff, 0xff) }, diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c index 1d5deee3be5..f98800f2324 100644 --- a/drivers/usb/serial/qcserial.c +++ b/drivers/usb/serial/qcserial.c @@ -36,6 +36,11 @@ static const struct usb_device_id id_table[] = {  	{USB_DEVICE(0x413c, 0x8171)},	/* Dell Gobi QDL device */  	{USB_DEVICE(0x1410, 0xa001)},	/* Novatel Gobi Modem device */  	{USB_DEVICE(0x1410, 0xa008)},	/* Novatel Gobi QDL device */ +	{USB_DEVICE(0x1410, 0xa010)},	/* Novatel Gobi QDL device */ +	{USB_DEVICE(0x1410, 0xa011)},	/* Novatel Gobi QDL device */ +	{USB_DEVICE(0x1410, 0xa012)},	/* Novatel Gobi QDL device */ +	{USB_DEVICE(0x1410, 0xa013)},	/* Novatel Gobi QDL device */ +	{USB_DEVICE(0x1410, 0xa014)},	/* Novatel Gobi QDL device */  	{USB_DEVICE(0x0b05, 0x1776)},	/* Asus Gobi Modem device */  	{USB_DEVICE(0x0b05, 0x1774)},	/* Asus Gobi QDL device */  	{USB_DEVICE(0x19d2, 0xfff3)},	/* ONDA Gobi Modem device */ @@ -86,7 +91,16 @@ static const struct usb_device_id id_table[] = {  	{USB_DEVICE(0x16d8, 0x8002)},	/* CMDTech Gobi 2000 Modem device (VU922) */  	{USB_DEVICE(0x05c6, 0x9204)},	/* Gobi 2000 QDL device */  	{USB_DEVICE(0x05c6, 0x9205)},	/* Gobi 2000 Modem device */ + +	{USB_DEVICE(0x05c6, 0x920c)},	/* Gobi 3000 QDL */ +	{USB_DEVICE(0x05c6, 0x920d)},	/* Gobi 3000 Composite */ +	{USB_DEVICE(0x1410, 0xa020)},   /* Novatel Gobi 3000 QDL */ +	{USB_DEVICE(0x1410, 0xa021)},	/* Novatel Gobi 3000 Composite */ +	{USB_DEVICE(0x413c, 0x8193)},	/* Dell Gobi 3000 QDL */ +	{USB_DEVICE(0x413c, 0x8194)},	/* Dell Gobi 3000 Composite */  	{USB_DEVICE(0x1199, 0x9013)},	/* Sierra Wireless Gobi 3000 Modem device (MC8355) */ +	{USB_DEVICE(0x12D1, 0x14F0)},	/* Sony Gobi 3000 QDL */ +	{USB_DEVICE(0x12D1, 0x14F1)},	/* Sony Gobi 3000 Composite */  	{ }				/* Terminating entry */  };  MODULE_DEVICE_TABLE(usb, id_table); @@ -123,8 +137,6 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)  	spin_lock_init(&data->susp_lock); -	usb_enable_autosuspend(serial->dev); -  	switch (nintf) {  	case 1:  		/* QDL mode */ diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c index 0d7b20d4285..e40c00f2c2b 100644 --- a/drivers/video/atmel_lcdfb.c +++ b/drivers/video/atmel_lcdfb.c @@ -1108,7 +1108,7 @@ static int atmel_lcdfb_suspend(struct platform_device *pdev, pm_message_t mesg)  	 */  	lcdc_writel(sinfo, ATMEL_LCDC_IDR, ~0UL); -	sinfo->saved_lcdcon = lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_VAL); +	sinfo->saved_lcdcon = lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_CTR);  	lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, 0);  	if (sinfo->atmel_lcdfb_power_control)  		sinfo->atmel_lcdfb_power_control(0); diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c index acf292bfba0..6af3f16754f 100644 --- a/drivers/video/fsl-diu-fb.c +++ b/drivers/video/fsl-diu-fb.c @@ -1432,7 +1432,7 @@ static int fsl_diu_suspend(struct platform_device *ofdev, pm_message_t state)  	struct fsl_diu_data *data;  	data = dev_get_drvdata(&ofdev->dev); -	disable_lcdc(data->fsl_diu_info[0]); +	disable_lcdc(data->fsl_diu_info);  	return 0;  } @@ -1442,7 +1442,7 @@ static int fsl_diu_resume(struct platform_device *ofdev)  	struct fsl_diu_data *data;  	data = dev_get_drvdata(&ofdev->dev); -	enable_lcdc(data->fsl_diu_info[0]); +	enable_lcdc(data->fsl_diu_info);  	return 0;  } diff --git a/drivers/video/intelfb/intelfbdrv.c b/drivers/video/intelfb/intelfbdrv.c index c6afa33a453..02fd2263610 100644 --- a/drivers/video/intelfb/intelfbdrv.c +++ b/drivers/video/intelfb/intelfbdrv.c @@ -529,7 +529,6 @@ static int __devinit intelfb_pci_register(struct pci_dev *pdev,  	if (fb_alloc_cmap(&info->cmap, 256, 1) < 0) {  		ERR_MSG("Could not allocate cmap for intelfb_info.\n");  		goto err_out_cmap; -		return -ENODEV;  	}  	dinfo = info->par; diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index a5ec7f37c18..e1626a1d5c4 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -401,7 +401,7 @@ void dispc_runtime_put(void)  	DSSDBG("dispc_runtime_put\n"); -	r = pm_runtime_put(&dispc.pdev->dev); +	r = pm_runtime_put_sync(&dispc.pdev->dev);  	WARN_ON(r < 0);  } diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c index 395d658a94f..faaf305fda2 100644 --- a/drivers/video/omap2/dss/dpi.c +++ b/drivers/video/omap2/dss/dpi.c @@ -180,6 +180,11 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)  {  	int r; +	if (cpu_is_omap34xx() && !dpi.vdds_dsi_reg) { +		DSSERR("no VDSS_DSI regulator\n"); +		return -ENODEV; +	} +  	if (dssdev->manager == NULL) {  		DSSERR("failed to enable display: no manager\n");  		return -ENODEV; diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index d4d676c82c1..52f36ec1c8b 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -1079,7 +1079,7 @@ void dsi_runtime_put(struct platform_device *dsidev)  	DSSDBG("dsi_runtime_put\n"); -	r = pm_runtime_put(&dsi->pdev->dev); +	r = pm_runtime_put_sync(&dsi->pdev->dev);  	WARN_ON(r < 0);  } diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index 17033457ee8..77c2b5a32b5 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c @@ -720,7 +720,7 @@ void dss_runtime_put(void)  	DSSDBG("dss_runtime_put\n"); -	r = pm_runtime_put(&dss.pdev->dev); +	r = pm_runtime_put_sync(&dss.pdev->dev);  	WARN_ON(r < 0);  } diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c index b4c270edb91..d7aa3b05652 100644 --- a/drivers/video/omap2/dss/hdmi.c +++ b/drivers/video/omap2/dss/hdmi.c @@ -176,7 +176,7 @@ static void hdmi_runtime_put(void)  	DSSDBG("hdmi_runtime_put\n"); -	r = pm_runtime_put(&hdmi.pdev->dev); +	r = pm_runtime_put_sync(&hdmi.pdev->dev);  	WARN_ON(r < 0);  } @@ -497,6 +497,7 @@ bool omapdss_hdmi_detect(void)  int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev)  { +	struct omap_dss_hdmi_data *priv = dssdev->data;  	int r = 0;  	DSSDBG("ENTER hdmi_display_enable\n"); @@ -509,6 +510,8 @@ int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev)  		goto err0;  	} +	hdmi.ip_data.hpd_gpio = priv->hpd_gpio; +  	r = omap_dss_start_device(dssdev);  	if (r) {  		DSSERR("failed to start device\n"); diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c index 814bb9500dc..55f398014f3 100644 --- a/drivers/video/omap2/dss/rfbi.c +++ b/drivers/video/omap2/dss/rfbi.c @@ -140,7 +140,7 @@ static void rfbi_runtime_put(void)  	DSSDBG("rfbi_runtime_put\n"); -	r = pm_runtime_put(&rfbi.pdev->dev); +	r = pm_runtime_put_sync(&rfbi.pdev->dev);  	WARN_ON(r < 0);  } diff --git a/drivers/video/omap2/dss/ti_hdmi.h b/drivers/video/omap2/dss/ti_hdmi.h index 7503f7f619a..50dadba5070 100644 --- a/drivers/video/omap2/dss/ti_hdmi.h +++ b/drivers/video/omap2/dss/ti_hdmi.h @@ -126,6 +126,10 @@ struct hdmi_ip_data {  	const struct ti_hdmi_ip_ops *ops;  	struct hdmi_config cfg;  	struct hdmi_pll_info pll_data; + +	/* ti_hdmi_4xxx_ip private data. These should be in a separate struct */ +	int hpd_gpio; +	bool phy_tx_enabled;  };  int ti_hdmi_4xxx_phy_enable(struct hdmi_ip_data *ip_data);  void ti_hdmi_4xxx_phy_disable(struct hdmi_ip_data *ip_data); diff --git a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c index 9af81f18f16..2d72334ca3d 100644 --- a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c +++ b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c @@ -28,6 +28,7 @@  #include <linux/delay.h>  #include <linux/string.h>  #include <linux/seq_file.h> +#include <linux/gpio.h>  #include "ti_hdmi_4xxx_ip.h"  #include "dss.h" @@ -223,6 +224,49 @@ void ti_hdmi_4xxx_pll_disable(struct hdmi_ip_data *ip_data)  	hdmi_set_pll_pwr(ip_data, HDMI_PLLPWRCMD_ALLOFF);  } +static int hdmi_check_hpd_state(struct hdmi_ip_data *ip_data) +{ +	unsigned long flags; +	bool hpd; +	int r; +	/* this should be in ti_hdmi_4xxx_ip private data */ +	static DEFINE_SPINLOCK(phy_tx_lock); + +	spin_lock_irqsave(&phy_tx_lock, flags); + +	hpd = gpio_get_value(ip_data->hpd_gpio); + +	if (hpd == ip_data->phy_tx_enabled) { +		spin_unlock_irqrestore(&phy_tx_lock, flags); +		return 0; +	} + +	if (hpd) +		r = hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_TXON); +	else +		r = hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_LDOON); + +	if (r) { +		DSSERR("Failed to %s PHY TX power\n", +				hpd ? "enable" : "disable"); +		goto err; +	} + +	ip_data->phy_tx_enabled = hpd; +err: +	spin_unlock_irqrestore(&phy_tx_lock, flags); +	return r; +} + +static irqreturn_t hpd_irq_handler(int irq, void *data) +{ +	struct hdmi_ip_data *ip_data = data; + +	hdmi_check_hpd_state(ip_data); + +	return IRQ_HANDLED; +} +  int ti_hdmi_4xxx_phy_enable(struct hdmi_ip_data *ip_data)  {  	u16 r = 0; @@ -232,10 +276,6 @@ int ti_hdmi_4xxx_phy_enable(struct hdmi_ip_data *ip_data)  	if (r)  		return r; -	r = hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_TXON); -	if (r) -		return r; -  	/*  	 * Read address 0 in order to get the SCP reset done completed  	 * Dummy access performed to make sure reset is done @@ -257,12 +297,32 @@ int ti_hdmi_4xxx_phy_enable(struct hdmi_ip_data *ip_data)  	/* Write to phy address 3 to change the polarity control */  	REG_FLD_MOD(phy_base, HDMI_TXPHY_PAD_CFG_CTRL, 0x1, 27, 27); +	r = request_threaded_irq(gpio_to_irq(ip_data->hpd_gpio), +			NULL, hpd_irq_handler, +			IRQF_DISABLED | IRQF_TRIGGER_RISING | +			IRQF_TRIGGER_FALLING, "hpd", ip_data); +	if (r) { +		DSSERR("HPD IRQ request failed\n"); +		hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_OFF); +		return r; +	} + +	r = hdmi_check_hpd_state(ip_data); +	if (r) { +		free_irq(gpio_to_irq(ip_data->hpd_gpio), ip_data); +		hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_OFF); +		return r; +	} +  	return 0;  }  void ti_hdmi_4xxx_phy_disable(struct hdmi_ip_data *ip_data)  { +	free_irq(gpio_to_irq(ip_data->hpd_gpio), ip_data); +  	hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_OFF); +	ip_data->phy_tx_enabled = false;  }  static int hdmi_core_ddc_init(struct hdmi_ip_data *ip_data) diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c index b3e9f909158..5c3d0f90151 100644 --- a/drivers/video/omap2/dss/venc.c +++ b/drivers/video/omap2/dss/venc.c @@ -401,7 +401,7 @@ static void venc_runtime_put(void)  	DSSDBG("venc_runtime_put\n"); -	r = pm_runtime_put(&venc.pdev->dev); +	r = pm_runtime_put_sync(&venc.pdev->dev);  	WARN_ON(r < 0);  } @@ -505,13 +505,9 @@ EXPORT_SYMBOL(bio_clone);  int bio_get_nr_vecs(struct block_device *bdev)  {  	struct request_queue *q = bdev_get_queue(bdev); -	int nr_pages; - -	nr_pages = ((queue_max_sectors(q) << 9) + PAGE_SIZE - 1) >> PAGE_SHIFT; -	if (nr_pages > queue_max_segments(q)) -		nr_pages = queue_max_segments(q); - -	return nr_pages; +	return min_t(unsigned, +		     queue_max_segments(q), +		     queue_max_sectors(q) / (PAGE_SIZE >> 9) + 1);  }  EXPORT_SYMBOL(bio_get_nr_vecs); diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c index b60fc8bfb3e..620daad201d 100644 --- a/fs/ceph/caps.c +++ b/fs/ceph/caps.c @@ -641,10 +641,10 @@ static int __cap_is_valid(struct ceph_cap *cap)  	unsigned long ttl;  	u32 gen; -	spin_lock(&cap->session->s_cap_lock); +	spin_lock(&cap->session->s_gen_ttl_lock);  	gen = cap->session->s_cap_gen;  	ttl = cap->session->s_cap_ttl; -	spin_unlock(&cap->session->s_cap_lock); +	spin_unlock(&cap->session->s_gen_ttl_lock);  	if (cap->cap_gen < gen || time_after_eq(jiffies, ttl)) {  		dout("__cap_is_valid %p cap %p issued %s " diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c index 618246bc219..3e8094be460 100644 --- a/fs/ceph/dir.c +++ b/fs/ceph/dir.c @@ -975,10 +975,10 @@ static int dentry_lease_is_valid(struct dentry *dentry)  	di = ceph_dentry(dentry);  	if (di->lease_session) {  		s = di->lease_session; -		spin_lock(&s->s_cap_lock); +		spin_lock(&s->s_gen_ttl_lock);  		gen = s->s_cap_gen;  		ttl = s->s_cap_ttl; -		spin_unlock(&s->s_cap_lock); +		spin_unlock(&s->s_gen_ttl_lock);  		if (di->lease_gen == gen &&  		    time_before(jiffies, dentry->d_time) && diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index 23ab6a3f182..866e8d7ca37 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c @@ -262,6 +262,7 @@ static int parse_reply_info(struct ceph_msg *msg,  	/* trace */  	ceph_decode_32_safe(&p, end, len, bad);  	if (len > 0) { +		ceph_decode_need(&p, end, len, bad);  		err = parse_reply_info_trace(&p, p+len, info, features);  		if (err < 0)  			goto out_bad; @@ -270,6 +271,7 @@ static int parse_reply_info(struct ceph_msg *msg,  	/* extra */  	ceph_decode_32_safe(&p, end, len, bad);  	if (len > 0) { +		ceph_decode_need(&p, end, len, bad);  		err = parse_reply_info_extra(&p, p+len, info, features);  		if (err < 0)  			goto out_bad; @@ -398,9 +400,11 @@ static struct ceph_mds_session *register_session(struct ceph_mds_client *mdsc,  	s->s_con.peer_name.type = CEPH_ENTITY_TYPE_MDS;  	s->s_con.peer_name.num = cpu_to_le64(mds); -	spin_lock_init(&s->s_cap_lock); +	spin_lock_init(&s->s_gen_ttl_lock);  	s->s_cap_gen = 0;  	s->s_cap_ttl = 0; + +	spin_lock_init(&s->s_cap_lock);  	s->s_renew_requested = 0;  	s->s_renew_seq = 0;  	INIT_LIST_HEAD(&s->s_caps); @@ -2326,10 +2330,10 @@ static void handle_session(struct ceph_mds_session *session,  	case CEPH_SESSION_STALE:  		pr_info("mds%d caps went stale, renewing\n",  			session->s_mds); -		spin_lock(&session->s_cap_lock); +		spin_lock(&session->s_gen_ttl_lock);  		session->s_cap_gen++;  		session->s_cap_ttl = 0; -		spin_unlock(&session->s_cap_lock); +		spin_unlock(&session->s_gen_ttl_lock);  		send_renew_caps(mdsc, session);  		break; diff --git a/fs/ceph/mds_client.h b/fs/ceph/mds_client.h index a50ca0e3947..8c7c04ebb59 100644 --- a/fs/ceph/mds_client.h +++ b/fs/ceph/mds_client.h @@ -117,10 +117,13 @@ struct ceph_mds_session {  	void             *s_authorizer_buf, *s_authorizer_reply_buf;  	size_t            s_authorizer_buf_len, s_authorizer_reply_buf_len; -	/* protected by s_cap_lock */ -	spinlock_t        s_cap_lock; +	/* protected by s_gen_ttl_lock */ +	spinlock_t        s_gen_ttl_lock;  	u32               s_cap_gen;  /* inc each time we get mds stale msg */  	unsigned long     s_cap_ttl;  /* when session caps expire */ + +	/* protected by s_cap_lock */ +	spinlock_t        s_cap_lock;  	struct list_head  s_caps;     /* all caps issued by this session */  	int               s_nr_caps, s_trim_caps;  	int               s_num_cap_releases; diff --git a/fs/ceph/xattr.c b/fs/ceph/xattr.c index 857214ae8c0..a76f697303d 100644 --- a/fs/ceph/xattr.c +++ b/fs/ceph/xattr.c @@ -111,8 +111,10 @@ static size_t ceph_vxattrcb_layout(struct ceph_inode_info *ci, char *val,  }  static struct ceph_vxattr_cb ceph_file_vxattrs[] = { +	{ true, "ceph.file.layout", ceph_vxattrcb_layout}, +	/* The following extended attribute name is deprecated */  	{ true, "ceph.layout", ceph_vxattrcb_layout}, -	{ NULL, NULL } +	{ true, NULL, NULL }  };  static struct ceph_vxattr_cb *ceph_inode_vxattrs(struct inode *inode) diff --git a/fs/cifs/Kconfig b/fs/cifs/Kconfig index 0554b00a7b3..2b243af70aa 100644 --- a/fs/cifs/Kconfig +++ b/fs/cifs/Kconfig @@ -139,7 +139,7 @@ config CIFS_DFS_UPCALL  	    points. If unsure, say N.  config CIFS_FSCACHE -	  bool "Provide CIFS client caching support (EXPERIMENTAL)" +	  bool "Provide CIFS client caching support"  	  depends on CIFS=m && FSCACHE || CIFS=y && FSCACHE=y  	  help  	    Makes CIFS FS-Cache capable. Say Y here if you want your CIFS data @@ -147,7 +147,7 @@ config CIFS_FSCACHE  	    manager. If unsure, say N.  config CIFS_ACL -	  bool "Provide CIFS ACL support (EXPERIMENTAL)" +	  bool "Provide CIFS ACL support"  	  depends on CIFS_XATTR && KEYS  	  help  	    Allows to fetch CIFS/NTFS ACL from the server.  The DACL blob diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 986709a8d90..602f77c304c 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -773,10 +773,11 @@ standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid)  		cifs_dump_mem("Bad SMB: ", buf,  			min_t(unsigned int, server->total_read, 48)); -	if (mid) -		handle_mid(mid, server, smb_buffer, length); +	if (!mid) +		return length; -	return length; +	handle_mid(mid, server, smb_buffer, length); +	return 0;  }  static int @@ -2125,7 +2126,7 @@ cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses)  	down_read(&key->sem);  	upayload = key->payload.data;  	if (IS_ERR_OR_NULL(upayload)) { -		rc = PTR_ERR(key); +		rc = upayload ? PTR_ERR(upayload) : -EINVAL;  		goto out_key_put;  	} @@ -2142,14 +2143,14 @@ cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses)  	len = delim - payload;  	if (len > MAX_USERNAME_SIZE || len <= 0) { -		cFYI(1, "Bad value from username search (len=%ld)", len); +		cFYI(1, "Bad value from username search (len=%zd)", len);  		rc = -EINVAL;  		goto out_key_put;  	}  	vol->username = kstrndup(payload, len, GFP_KERNEL);  	if (!vol->username) { -		cFYI(1, "Unable to allocate %ld bytes for username", len); +		cFYI(1, "Unable to allocate %zd bytes for username", len);  		rc = -ENOMEM;  		goto out_key_put;  	} @@ -2157,7 +2158,7 @@ cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses)  	len = key->datalen - (len + 1);  	if (len > MAX_PASSWORD_SIZE || len <= 0) { -		cFYI(1, "Bad len for password search (len=%ld)", len); +		cFYI(1, "Bad len for password search (len=%zd)", len);  		rc = -EINVAL;  		kfree(vol->username);  		vol->username = NULL; @@ -2167,7 +2168,7 @@ cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses)  	++delim;  	vol->password = kstrndup(delim, len, GFP_KERNEL);  	if (!vol->password) { -		cFYI(1, "Unable to allocate %ld bytes for password", len); +		cFYI(1, "Unable to allocate %zd bytes for password", len);  		rc = -ENOMEM;  		kfree(vol->username);  		vol->username = NULL; @@ -3857,10 +3858,8 @@ cifs_construct_tcon(struct cifs_sb_info *cifs_sb, uid_t fsuid)  	struct smb_vol *vol_info;  	vol_info = kzalloc(sizeof(*vol_info), GFP_KERNEL); -	if (vol_info == NULL) { -		tcon = ERR_PTR(-ENOMEM); -		goto out; -	} +	if (vol_info == NULL) +		return ERR_PTR(-ENOMEM);  	vol_info->local_nls = cifs_sb->local_nls;  	vol_info->linux_uid = fsuid; diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index df8fecb5b99..63a196b97d5 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -492,7 +492,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,  {  	int xid;  	int rc = 0; /* to get around spurious gcc warning, set to zero here */ -	__u32 oplock = 0; +	__u32 oplock = enable_oplocks ? REQ_OPLOCK : 0;  	__u16 fileHandle = 0;  	bool posix_open = false;  	struct cifs_sb_info *cifs_sb; diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c index d85efad5765..551d0c2b973 100644 --- a/fs/cifs/sess.c +++ b/fs/cifs/sess.c @@ -246,16 +246,15 @@ static void ascii_ssetup_strings(char **pbcc_area, struct cifs_ses *ses,  	/* copy user */  	/* BB what about null user mounts - check that we do this BB */  	/* copy user */ -	if (ses->user_name != NULL) +	if (ses->user_name != NULL) {  		strncpy(bcc_ptr, ses->user_name, MAX_USERNAME_SIZE); +		bcc_ptr += strnlen(ses->user_name, MAX_USERNAME_SIZE); +	}  	/* else null user mount */ - -	bcc_ptr += strnlen(ses->user_name, MAX_USERNAME_SIZE);  	*bcc_ptr = 0;  	bcc_ptr++; /* account for null termination */  	/* copy domain */ -  	if (ses->domainName != NULL) {  		strncpy(bcc_ptr, ses->domainName, 256);  		bcc_ptr += strnlen(ses->domainName, 256); @@ -395,6 +394,10 @@ static int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len,  	ses->ntlmssp->server_flags = le32_to_cpu(pblob->NegotiateFlags);  	tioffset = le32_to_cpu(pblob->TargetInfoArray.BufferOffset);  	tilen = le16_to_cpu(pblob->TargetInfoArray.Length); +	if (tioffset > blob_len || tioffset + tilen > blob_len) { +		cERROR(1, "tioffset + tilen too high %u + %u", tioffset, tilen); +		return -EINVAL; +	}  	if (tilen) {  		ses->auth_key.response = kmalloc(tilen, GFP_KERNEL);  		if (!ses->auth_key.response) { diff --git a/fs/exec.c b/fs/exec.c index aeb135c7ff5..92ce83a11e9 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -1071,6 +1071,21 @@ void set_task_comm(struct task_struct *tsk, char *buf)  	perf_event_comm(tsk);  } +static void filename_to_taskname(char *tcomm, const char *fn, unsigned int len) +{ +	int i, ch; + +	/* Copies the binary name from after last slash */ +	for (i = 0; (ch = *(fn++)) != '\0';) { +		if (ch == '/') +			i = 0; /* overwrite what we wrote */ +		else +			if (i < len - 1) +				tcomm[i++] = ch; +	} +	tcomm[i] = '\0'; +} +  int flush_old_exec(struct linux_binprm * bprm)  {  	int retval; @@ -1085,6 +1100,7 @@ int flush_old_exec(struct linux_binprm * bprm)  	set_mm_exe_file(bprm->mm, bprm->file); +	filename_to_taskname(bprm->tcomm, bprm->filename, sizeof(bprm->tcomm));  	/*  	 * Release all of the old mmap stuff  	 */ @@ -1116,10 +1132,6 @@ EXPORT_SYMBOL(would_dump);  void setup_new_exec(struct linux_binprm * bprm)  { -	int i, ch; -	const char *name; -	char tcomm[sizeof(current->comm)]; -  	arch_pick_mmap_layout(current->mm);  	/* This is the point of no return */ @@ -1130,18 +1142,7 @@ void setup_new_exec(struct linux_binprm * bprm)  	else  		set_dumpable(current->mm, suid_dumpable); -	name = bprm->filename; - -	/* Copies the binary name from after last slash */ -	for (i=0; (ch = *(name++)) != '\0';) { -		if (ch == '/') -			i = 0; /* overwrite what we wrote */ -		else -			if (i < (sizeof(tcomm) - 1)) -				tcomm[i++] = ch; -	} -	tcomm[i] = '\0'; -	set_task_comm(current, tcomm); +	set_task_comm(current, bprm->tcomm);  	/* Set the new mm task size. We have to do that late because it may  	 * depend on TIF_32BIT which is only updated in flush_thread() on diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index f855916657b..5b4a9362d5a 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -53,14 +53,6 @@ struct wb_writeback_work {  };  /* - * Include the creation of the trace points after defining the - * wb_writeback_work structure so that the definition remains local to this - * file. - */ -#define CREATE_TRACE_POINTS -#include <trace/events/writeback.h> - -/*   * We don't actually have pdflush, but this one is exported though /proc...   */  int nr_pdflush_threads; @@ -92,6 +84,14 @@ static inline struct inode *wb_inode(struct list_head *head)  	return list_entry(head, struct inode, i_wb_list);  } +/* + * Include the creation of the trace points after defining the + * wb_writeback_work structure and inline functions so that the definition + * remains local to this file. + */ +#define CREATE_TRACE_POINTS +#include <trace/events/writeback.h> +  /* Wakeup flusher thread or forker thread to fork it. Requires bdi->wb_lock. */  static void bdi_wakeup_flusher(struct backing_dev_info *bdi)  { diff --git a/fs/ioprio.c b/fs/ioprio.c index f84b380d65e..0f1b9515213 100644 --- a/fs/ioprio.c +++ b/fs/ioprio.c @@ -51,7 +51,7 @@ int set_task_ioprio(struct task_struct *task, int ioprio)  	ioc = get_task_io_context(task, GFP_ATOMIC, NUMA_NO_NODE);  	if (ioc) {  		ioc_ioprio_changed(ioc, ioprio); -		put_io_context(ioc, NULL); +		put_io_context(ioc);  	}  	return err; diff --git a/fs/jffs2/erase.c b/fs/jffs2/erase.c index a01cdad6aad..eafb8d37a6f 100644 --- a/fs/jffs2/erase.c +++ b/fs/jffs2/erase.c @@ -335,7 +335,7 @@ static int jffs2_block_check_erase(struct jffs2_sb_info *c, struct jffs2_erasebl  	void *ebuf;  	uint32_t ofs;  	size_t retlen; -	int ret = -EIO; +	int ret;  	unsigned long *wordebuf;  	ret = mtd_point(c->mtd, jeb->offset, c->sector_size, &retlen, diff --git a/fs/logfs/dev_mtd.c b/fs/logfs/dev_mtd.c index e97404d611e..9c501449450 100644 --- a/fs/logfs/dev_mtd.c +++ b/fs/logfs/dev_mtd.c @@ -152,9 +152,6 @@ static struct page *logfs_mtd_find_first_sb(struct super_block *sb, u64 *ofs)  	filler_t *filler = logfs_mtd_readpage;  	struct mtd_info *mtd = super->s_mtd; -	if (!mtd_can_have_bb(mtd)) -		return NULL; -  	*ofs = 0;  	while (mtd_block_isbad(mtd, *ofs)) {  		*ofs += mtd->erasesize; @@ -172,9 +169,6 @@ static struct page *logfs_mtd_find_last_sb(struct super_block *sb, u64 *ofs)  	filler_t *filler = logfs_mtd_readpage;  	struct mtd_info *mtd = super->s_mtd; -	if (!mtd_can_have_bb(mtd)) -		return NULL; -  	*ofs = mtd->size - mtd->erasesize;  	while (mtd_block_isbad(mtd, *ofs)) {  		*ofs -= mtd->erasesize; diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c index 886649627c3..2a70fce70c6 100644 --- a/fs/nilfs2/ioctl.c +++ b/fs/nilfs2/ioctl.c @@ -603,6 +603,8 @@ static int nilfs_ioctl_clean_segments(struct inode *inode, struct file *filp,  	nsegs = argv[4].v_nmembs;  	if (argv[4].v_size != argsz[4])  		goto out; +	if (nsegs > UINT_MAX / sizeof(__u64)) +		goto out;  	/*  	 * argv[4] points to segment numbers this ioctl cleans.  We diff --git a/fs/proc/base.c b/fs/proc/base.c index 9cde9edf9c4..d4548dd49b0 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -198,26 +198,6 @@ static int proc_root_link(struct dentry *dentry, struct path *path)  	return result;  } -static struct mm_struct *mm_access(struct task_struct *task, unsigned int mode) -{ -	struct mm_struct *mm; -	int err; - -	err =  mutex_lock_killable(&task->signal->cred_guard_mutex); -	if (err) -		return ERR_PTR(err); - -	mm = get_task_mm(task); -	if (mm && mm != current->mm && -			!ptrace_may_access(task, mode)) { -		mmput(mm); -		mm = ERR_PTR(-EACCES); -	} -	mutex_unlock(&task->signal->cred_guard_mutex); - -	return mm; -} -  struct mm_struct *mm_for_maps(struct task_struct *task)  {  	return mm_access(task, PTRACE_MODE_READ); @@ -711,6 +691,13 @@ static int mem_open(struct inode* inode, struct file* file)  	if (IS_ERR(mm))  		return PTR_ERR(mm); +	if (mm) { +		/* ensure this mm_struct can't be freed */ +		atomic_inc(&mm->mm_count); +		/* but do not pin its memory */ +		mmput(mm); +	} +  	/* OK to pass negative loff_t, we can catch out-of-range */  	file->f_mode |= FMODE_UNSIGNED_OFFSET;  	file->private_data = mm; @@ -718,57 +705,13 @@ static int mem_open(struct inode* inode, struct file* file)  	return 0;  } -static ssize_t mem_read(struct file * file, char __user * buf, -			size_t count, loff_t *ppos) +static ssize_t mem_rw(struct file *file, char __user *buf, +			size_t count, loff_t *ppos, int write)  { -	int ret; -	char *page; -	unsigned long src = *ppos;  	struct mm_struct *mm = file->private_data; - -	if (!mm) -		return 0; - -	page = (char *)__get_free_page(GFP_TEMPORARY); -	if (!page) -		return -ENOMEM; - -	ret = 0; -  -	while (count > 0) { -		int this_len, retval; - -		this_len = (count > PAGE_SIZE) ? PAGE_SIZE : count; -		retval = access_remote_vm(mm, src, page, this_len, 0); -		if (!retval) { -			if (!ret) -				ret = -EIO; -			break; -		} - -		if (copy_to_user(buf, page, retval)) { -			ret = -EFAULT; -			break; -		} -  -		ret += retval; -		src += retval; -		buf += retval; -		count -= retval; -	} -	*ppos = src; - -	free_page((unsigned long) page); -	return ret; -} - -static ssize_t mem_write(struct file * file, const char __user *buf, -			 size_t count, loff_t *ppos) -{ -	int copied; +	unsigned long addr = *ppos; +	ssize_t copied;  	char *page; -	unsigned long dst = *ppos; -	struct mm_struct *mm = file->private_data;  	if (!mm)  		return 0; @@ -778,31 +721,54 @@ static ssize_t mem_write(struct file * file, const char __user *buf,  		return -ENOMEM;  	copied = 0; +	if (!atomic_inc_not_zero(&mm->mm_users)) +		goto free; +  	while (count > 0) { -		int this_len, retval; +		int this_len = min_t(int, count, PAGE_SIZE); -		this_len = (count > PAGE_SIZE) ? PAGE_SIZE : count; -		if (copy_from_user(page, buf, this_len)) { +		if (write && copy_from_user(page, buf, this_len)) {  			copied = -EFAULT;  			break;  		} -		retval = access_remote_vm(mm, dst, page, this_len, 1); -		if (!retval) { + +		this_len = access_remote_vm(mm, addr, page, this_len, write); +		if (!this_len) {  			if (!copied)  				copied = -EIO;  			break;  		} -		copied += retval; -		buf += retval; -		dst += retval; -		count -= retval;			 + +		if (!write && copy_to_user(buf, page, this_len)) { +			copied = -EFAULT; +			break; +		} + +		buf += this_len; +		addr += this_len; +		copied += this_len; +		count -= this_len;  	} -	*ppos = dst; +	*ppos = addr; +	mmput(mm); +free:  	free_page((unsigned long) page);  	return copied;  } +static ssize_t mem_read(struct file *file, char __user *buf, +			size_t count, loff_t *ppos) +{ +	return mem_rw(file, buf, count, ppos, 0); +} + +static ssize_t mem_write(struct file *file, const char __user *buf, +			 size_t count, loff_t *ppos) +{ +	return mem_rw(file, (char __user*)buf, count, ppos, 1); +} +  loff_t mem_lseek(struct file *file, loff_t offset, int orig)  {  	switch (orig) { @@ -822,8 +788,8 @@ loff_t mem_lseek(struct file *file, loff_t offset, int orig)  static int mem_release(struct inode *inode, struct file *file)  {  	struct mm_struct *mm = file->private_data; - -	mmput(mm); +	if (mm) +		mmdrop(mm);  	return 0;  } diff --git a/fs/xfs/kmem.h b/fs/xfs/kmem.h index 292eff19803..ab7c53fe346 100644 --- a/fs/xfs/kmem.h +++ b/fs/xfs/kmem.h @@ -110,10 +110,4 @@ kmem_zone_destroy(kmem_zone_t *zone)  extern void *kmem_zone_alloc(kmem_zone_t *, unsigned int __nocast);  extern void *kmem_zone_zalloc(kmem_zone_t *, unsigned int __nocast); -static inline int -kmem_shake_allow(gfp_t gfp_mask) -{ -	return ((gfp_mask & __GFP_WAIT) && (gfp_mask & __GFP_FS)); -} -  #endif /* __XFS_SUPPORT_KMEM_H__ */ diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c index b4ff40b5f91..cbcb7bea38e 100644 --- a/fs/xfs/xfs_dquot.c +++ b/fs/xfs/xfs_dquot.c @@ -63,82 +63,6 @@ int xfs_dqerror_mod = 33;  static struct lock_class_key xfs_dquot_other_class;  /* - * Allocate and initialize a dquot. We don't always allocate fresh memory; - * we try to reclaim a free dquot if the number of incore dquots are above - * a threshold. - * The only field inside the core that gets initialized at this point - * is the d_id field. The idea is to fill in the entire q_core - * when we read in the on disk dquot. - */ -STATIC xfs_dquot_t * -xfs_qm_dqinit( -	xfs_mount_t  *mp, -	xfs_dqid_t   id, -	uint	     type) -{ -	xfs_dquot_t	*dqp; -	boolean_t	brandnewdquot; - -	brandnewdquot = xfs_qm_dqalloc_incore(&dqp); -	dqp->dq_flags = type; -	dqp->q_core.d_id = cpu_to_be32(id); -	dqp->q_mount = mp; - -	/* -	 * No need to re-initialize these if this is a reclaimed dquot. -	 */ -	if (brandnewdquot) { -		INIT_LIST_HEAD(&dqp->q_freelist); -		mutex_init(&dqp->q_qlock); -		init_waitqueue_head(&dqp->q_pinwait); - -		/* -		 * Because we want to use a counting completion, complete -		 * the flush completion once to allow a single access to -		 * the flush completion without blocking. -		 */ -		init_completion(&dqp->q_flush); -		complete(&dqp->q_flush); - -		trace_xfs_dqinit(dqp); -	} else { -		/* -		 * Only the q_core portion was zeroed in dqreclaim_one(). -		 * So, we need to reset others. -		 */ -		dqp->q_nrefs = 0; -		dqp->q_blkno = 0; -		INIT_LIST_HEAD(&dqp->q_mplist); -		INIT_LIST_HEAD(&dqp->q_hashlist); -		dqp->q_bufoffset = 0; -		dqp->q_fileoffset = 0; -		dqp->q_transp = NULL; -		dqp->q_gdquot = NULL; -		dqp->q_res_bcount = 0; -		dqp->q_res_icount = 0; -		dqp->q_res_rtbcount = 0; -		atomic_set(&dqp->q_pincount, 0); -		dqp->q_hash = NULL; -		ASSERT(list_empty(&dqp->q_freelist)); - -		trace_xfs_dqreuse(dqp); -	} - -	/* -	 * In either case we need to make sure group quotas have a different -	 * lock class than user quotas, to make sure lockdep knows we can -	 * locks of one of each at the same time. -	 */ -	if (!(type & XFS_DQ_USER)) -		lockdep_set_class(&dqp->q_qlock, &xfs_dquot_other_class); - -	/* -	 * log item gets initialized later -	 */ -	return (dqp); -} - -/*   * This is called to free all the memory associated with a dquot   */  void @@ -567,7 +491,32 @@ xfs_qm_dqread(  	int			error;  	int			cancelflags = 0; -	dqp = xfs_qm_dqinit(mp, id, type); + +	dqp = kmem_zone_zalloc(xfs_Gqm->qm_dqzone, KM_SLEEP); + +	dqp->dq_flags = type; +	dqp->q_core.d_id = cpu_to_be32(id); +	dqp->q_mount = mp; +	INIT_LIST_HEAD(&dqp->q_freelist); +	mutex_init(&dqp->q_qlock); +	init_waitqueue_head(&dqp->q_pinwait); + +	/* +	 * Because we want to use a counting completion, complete +	 * the flush completion once to allow a single access to +	 * the flush completion without blocking. +	 */ +	init_completion(&dqp->q_flush); +	complete(&dqp->q_flush); + +	/* +	 * Make sure group quotas have a different lock class than user +	 * quotas. +	 */ +	if (!(type & XFS_DQ_USER)) +		lockdep_set_class(&dqp->q_qlock, &xfs_dquot_other_class); + +	atomic_inc(&xfs_Gqm->qm_totaldquots);  	trace_xfs_dqread(dqp); diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index 541a508adea..15ff5392fb6 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c @@ -1489,7 +1489,7 @@ xlog_recover_add_to_cont_trans(  	old_ptr = item->ri_buf[item->ri_cnt-1].i_addr;  	old_len = item->ri_buf[item->ri_cnt-1].i_len; -	ptr = kmem_realloc(old_ptr, len+old_len, old_len, 0u); +	ptr = kmem_realloc(old_ptr, len+old_len, old_len, KM_SLEEP);  	memcpy(&ptr[old_len], dp, len); /* d, s, l */  	item->ri_buf[item->ri_cnt-1].i_len += len;  	item->ri_buf[item->ri_cnt-1].i_addr = ptr; diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c index 671f37eae1c..c436def733b 100644 --- a/fs/xfs/xfs_qm.c +++ b/fs/xfs/xfs_qm.c @@ -50,7 +50,6 @@   */  struct mutex	xfs_Gqm_lock;  struct xfs_qm	*xfs_Gqm; -uint		ndquot;  kmem_zone_t	*qm_dqzone;  kmem_zone_t	*qm_dqtrxzone; @@ -93,7 +92,6 @@ xfs_Gqm_init(void)  		goto out_free_udqhash;  	hsize /= sizeof(xfs_dqhash_t); -	ndquot = hsize << 8;  	xqm = kmem_zalloc(sizeof(xfs_qm_t), KM_SLEEP);  	xqm->qm_dqhashmask = hsize - 1; @@ -137,7 +135,6 @@ xfs_Gqm_init(void)  		xqm->qm_dqtrxzone = qm_dqtrxzone;  	atomic_set(&xqm->qm_totaldquots, 0); -	xqm->qm_dqfree_ratio = XFS_QM_DQFREE_RATIO;  	xqm->qm_nrefs = 0;  	return xqm; @@ -1600,216 +1597,150 @@ xfs_qm_init_quotainos(  	return 0;  } +STATIC void +xfs_qm_dqfree_one( +	struct xfs_dquot	*dqp) +{ +	struct xfs_mount	*mp = dqp->q_mount; +	struct xfs_quotainfo	*qi = mp->m_quotainfo; +	mutex_lock(&dqp->q_hash->qh_lock); +	list_del_init(&dqp->q_hashlist); +	dqp->q_hash->qh_version++; +	mutex_unlock(&dqp->q_hash->qh_lock); -/* - * Pop the least recently used dquot off the freelist and recycle it. - */ -STATIC struct xfs_dquot * -xfs_qm_dqreclaim_one(void) +	mutex_lock(&qi->qi_dqlist_lock); +	list_del_init(&dqp->q_mplist); +	qi->qi_dquots--; +	qi->qi_dqreclaims++; +	mutex_unlock(&qi->qi_dqlist_lock); + +	xfs_qm_dqdestroy(dqp); +} + +STATIC void +xfs_qm_dqreclaim_one( +	struct xfs_dquot	*dqp, +	struct list_head	*dispose_list)  { -	struct xfs_dquot	*dqp; -	int			restarts = 0; +	struct xfs_mount	*mp = dqp->q_mount; +	int			error; -	mutex_lock(&xfs_Gqm->qm_dqfrlist_lock); -restart: -	list_for_each_entry(dqp, &xfs_Gqm->qm_dqfrlist, q_freelist) { -		struct xfs_mount *mp = dqp->q_mount; +	if (!xfs_dqlock_nowait(dqp)) +		goto out_busy; -		if (!xfs_dqlock_nowait(dqp)) -			continue; +	/* +	 * This dquot has acquired a reference in the meantime remove it from +	 * the freelist and try again. +	 */ +	if (dqp->q_nrefs) { +		xfs_dqunlock(dqp); -		/* -		 * This dquot has already been grabbed by dqlookup. -		 * Remove it from the freelist and try again. -		 */ -		if (dqp->q_nrefs) { -			trace_xfs_dqreclaim_want(dqp); -			XQM_STATS_INC(xqmstats.xs_qm_dqwants); +		trace_xfs_dqreclaim_want(dqp); +		XQM_STATS_INC(xqmstats.xs_qm_dqwants); -			list_del_init(&dqp->q_freelist); -			xfs_Gqm->qm_dqfrlist_cnt--; -			restarts++; -			goto dqunlock; -		} +		list_del_init(&dqp->q_freelist); +		xfs_Gqm->qm_dqfrlist_cnt--; +		return; +	} -		ASSERT(dqp->q_hash); -		ASSERT(!list_empty(&dqp->q_mplist)); +	ASSERT(dqp->q_hash); +	ASSERT(!list_empty(&dqp->q_mplist)); -		/* -		 * Try to grab the flush lock. If this dquot is in the process -		 * of getting flushed to disk, we don't want to reclaim it. -		 */ -		if (!xfs_dqflock_nowait(dqp)) -			goto dqunlock; +	/* +	 * Try to grab the flush lock. If this dquot is in the process of +	 * getting flushed to disk, we don't want to reclaim it. +	 */ +	if (!xfs_dqflock_nowait(dqp)) +		goto out_busy; + +	/* +	 * We have the flush lock so we know that this is not in the +	 * process of being flushed. So, if this is dirty, flush it +	 * DELWRI so that we don't get a freelist infested with +	 * dirty dquots. +	 */ +	if (XFS_DQ_IS_DIRTY(dqp)) { +		trace_xfs_dqreclaim_dirty(dqp);  		/* -		 * We have the flush lock so we know that this is not in the -		 * process of being flushed. So, if this is dirty, flush it -		 * DELWRI so that we don't get a freelist infested with -		 * dirty dquots. +		 * We flush it delayed write, so don't bother releasing the +		 * freelist lock.  		 */ -		if (XFS_DQ_IS_DIRTY(dqp)) { -			int	error; - -			trace_xfs_dqreclaim_dirty(dqp); - -			/* -			 * We flush it delayed write, so don't bother -			 * releasing the freelist lock. -			 */ -			error = xfs_qm_dqflush(dqp, SYNC_TRYLOCK); -			if (error) { -				xfs_warn(mp, "%s: dquot %p flush failed", -					__func__, dqp); -			} -			goto dqunlock; +		error = xfs_qm_dqflush(dqp, 0); +		if (error) { +			xfs_warn(mp, "%s: dquot %p flush failed", +				 __func__, dqp);  		} -		xfs_dqfunlock(dqp);  		/* -		 * Prevent lookup now that we are going to reclaim the dquot. -		 * Once XFS_DQ_FREEING is set lookup won't touch the dquot, -		 * thus we can drop the lock now. +		 * Give the dquot another try on the freelist, as the +		 * flushing will take some time.  		 */ -		dqp->dq_flags |= XFS_DQ_FREEING; -		xfs_dqunlock(dqp); - -		mutex_lock(&dqp->q_hash->qh_lock); -		list_del_init(&dqp->q_hashlist); -		dqp->q_hash->qh_version++; -		mutex_unlock(&dqp->q_hash->qh_lock); +		goto out_busy; +	} +	xfs_dqfunlock(dqp); -		mutex_lock(&mp->m_quotainfo->qi_dqlist_lock); -		list_del_init(&dqp->q_mplist); -		mp->m_quotainfo->qi_dquots--; -		mp->m_quotainfo->qi_dqreclaims++; -		mutex_unlock(&mp->m_quotainfo->qi_dqlist_lock); +	/* +	 * Prevent lookups now that we are past the point of no return. +	 */ +	dqp->dq_flags |= XFS_DQ_FREEING; +	xfs_dqunlock(dqp); -		ASSERT(dqp->q_nrefs == 0); -		list_del_init(&dqp->q_freelist); -		xfs_Gqm->qm_dqfrlist_cnt--; +	ASSERT(dqp->q_nrefs == 0); +	list_move_tail(&dqp->q_freelist, dispose_list); +	xfs_Gqm->qm_dqfrlist_cnt--; -		mutex_unlock(&xfs_Gqm->qm_dqfrlist_lock); -		return dqp; -dqunlock: -		xfs_dqunlock(dqp); -		if (restarts >= XFS_QM_RECLAIM_MAX_RESTARTS) -			break; -		goto restart; -	} +	trace_xfs_dqreclaim_done(dqp); +	XQM_STATS_INC(xqmstats.xs_qm_dqreclaims); +	return; -	mutex_unlock(&xfs_Gqm->qm_dqfrlist_lock); -	return NULL; -} - -/* - * Traverse the freelist of dquots and attempt to reclaim a maximum of - * 'howmany' dquots. This operation races with dqlookup(), and attempts to - * favor the lookup function ... - */ -STATIC int -xfs_qm_shake_freelist( -	int	howmany) -{ -	int		nreclaimed = 0; -	xfs_dquot_t	*dqp; +out_busy: +	xfs_dqunlock(dqp); -	if (howmany <= 0) -		return 0; +	/* +	 * Move the dquot to the tail of the list so that we don't spin on it. +	 */ +	list_move_tail(&dqp->q_freelist, &xfs_Gqm->qm_dqfrlist); -	while (nreclaimed < howmany) { -		dqp = xfs_qm_dqreclaim_one(); -		if (!dqp) -			return nreclaimed; -		xfs_qm_dqdestroy(dqp); -		nreclaimed++; -	} -	return nreclaimed; +	trace_xfs_dqreclaim_busy(dqp); +	XQM_STATS_INC(xqmstats.xs_qm_dqreclaim_misses);  } -/* - * The kmem_shake interface is invoked when memory is running low. - */ -/* ARGSUSED */  STATIC int  xfs_qm_shake( -	struct shrinker	*shrink, -	struct shrink_control *sc) +	struct shrinker		*shrink, +	struct shrink_control	*sc)  { -	int	ndqused, nfree, n; -	gfp_t gfp_mask = sc->gfp_mask; - -	if (!kmem_shake_allow(gfp_mask)) -		return 0; -	if (!xfs_Gqm) -		return 0; - -	nfree = xfs_Gqm->qm_dqfrlist_cnt; /* free dquots */ -	/* incore dquots in all f/s's */ -	ndqused = atomic_read(&xfs_Gqm->qm_totaldquots) - nfree; - -	ASSERT(ndqused >= 0); +	int			nr_to_scan = sc->nr_to_scan; +	LIST_HEAD		(dispose_list); +	struct xfs_dquot	*dqp; -	if (nfree <= ndqused && nfree < ndquot) +	if ((sc->gfp_mask & (__GFP_FS|__GFP_WAIT)) != (__GFP_FS|__GFP_WAIT))  		return 0; +	if (!nr_to_scan) +		goto out; -	ndqused *= xfs_Gqm->qm_dqfree_ratio;	/* target # of free dquots */ -	n = nfree - ndqused - ndquot;		/* # over target */ - -	return xfs_qm_shake_freelist(MAX(nfree, n)); -} - - -/*------------------------------------------------------------------*/ - -/* - * Return a new incore dquot. Depending on the number of - * dquots in the system, we either allocate a new one on the kernel heap, - * or reclaim a free one. - * Return value is B_TRUE if we allocated a new dquot, B_FALSE if we managed - * to reclaim an existing one from the freelist. - */ -boolean_t -xfs_qm_dqalloc_incore( -	xfs_dquot_t **O_dqpp) -{ -	xfs_dquot_t	*dqp; - -	/* -	 * Check against high water mark to see if we want to pop -	 * a nincompoop dquot off the freelist. -	 */ -	if (atomic_read(&xfs_Gqm->qm_totaldquots) >= ndquot) { -		/* -		 * Try to recycle a dquot from the freelist. -		 */ -		if ((dqp = xfs_qm_dqreclaim_one())) { -			XQM_STATS_INC(xqmstats.xs_qm_dqreclaims); -			/* -			 * Just zero the core here. The rest will get -			 * reinitialized by caller. XXX we shouldn't even -			 * do this zero ... -			 */ -			memset(&dqp->q_core, 0, sizeof(dqp->q_core)); -			*O_dqpp = dqp; -			return B_FALSE; -		} -		XQM_STATS_INC(xqmstats.xs_qm_dqreclaim_misses); +	mutex_lock(&xfs_Gqm->qm_dqfrlist_lock); +	while (!list_empty(&xfs_Gqm->qm_dqfrlist)) { +		if (nr_to_scan-- <= 0) +			break; +		dqp = list_first_entry(&xfs_Gqm->qm_dqfrlist, struct xfs_dquot, +				       q_freelist); +		xfs_qm_dqreclaim_one(dqp, &dispose_list);  	} +	mutex_unlock(&xfs_Gqm->qm_dqfrlist_lock); -	/* -	 * Allocate a brand new dquot on the kernel heap and return it -	 * to the caller to initialize. -	 */ -	ASSERT(xfs_Gqm->qm_dqzone != NULL); -	*O_dqpp = kmem_zone_zalloc(xfs_Gqm->qm_dqzone, KM_SLEEP); -	atomic_inc(&xfs_Gqm->qm_totaldquots); - -	return B_TRUE; +	while (!list_empty(&dispose_list)) { +		dqp = list_first_entry(&dispose_list, struct xfs_dquot, +				       q_freelist); +		list_del_init(&dqp->q_freelist); +		xfs_qm_dqfree_one(dqp); +	} +out: +	return (xfs_Gqm->qm_dqfrlist_cnt / 100) * sysctl_vfs_cache_pressure;  } -  /*   * Start a transaction and write the incore superblock changes to   * disk. flags parameter indicates which fields have changed. diff --git a/fs/xfs/xfs_qm.h b/fs/xfs/xfs_qm.h index 9b4f3adefbc..9a9b997e1a0 100644 --- a/fs/xfs/xfs_qm.h +++ b/fs/xfs/xfs_qm.h @@ -26,24 +26,12 @@  struct xfs_qm;  struct xfs_inode; -extern uint		ndquot;  extern struct mutex	xfs_Gqm_lock;  extern struct xfs_qm	*xfs_Gqm;  extern kmem_zone_t	*qm_dqzone;  extern kmem_zone_t	*qm_dqtrxzone;  /* - * Ditto, for xfs_qm_dqreclaim_one. - */ -#define XFS_QM_RECLAIM_MAX_RESTARTS	4 - -/* - * Ideal ratio of free to in use dquots. Quota manager makes an attempt - * to keep this balance. - */ -#define XFS_QM_DQFREE_RATIO		2 - -/*   * Dquot hashtable constants/threshold values.   */  #define XFS_QM_HASHSIZE_LOW		(PAGE_SIZE / sizeof(xfs_dqhash_t)) @@ -74,7 +62,6 @@ typedef struct xfs_qm {  	int		 qm_dqfrlist_cnt;  	atomic_t	 qm_totaldquots; /* total incore dquots */  	uint		 qm_nrefs;	 /* file systems with quota on */ -	int		 qm_dqfree_ratio;/* ratio of free to inuse dquots */  	kmem_zone_t	*qm_dqzone;	 /* dquot mem-alloc zone */  	kmem_zone_t	*qm_dqtrxzone;	 /* t_dqinfo of transactions */  } xfs_qm_t; @@ -143,7 +130,6 @@ extern int		xfs_qm_quotacheck(xfs_mount_t *);  extern int		xfs_qm_write_sb_changes(xfs_mount_t *, __int64_t);  /* dquot stuff */ -extern boolean_t	xfs_qm_dqalloc_incore(xfs_dquot_t **);  extern int		xfs_qm_dqpurge_all(xfs_mount_t *, uint);  extern void		xfs_qm_dqrele_all_inodes(xfs_mount_t *, uint); diff --git a/fs/xfs/xfs_qm_stats.c b/fs/xfs/xfs_qm_stats.c index 8671a0b3264..5729ba57087 100644 --- a/fs/xfs/xfs_qm_stats.c +++ b/fs/xfs/xfs_qm_stats.c @@ -42,9 +42,9 @@ static int xqm_proc_show(struct seq_file *m, void *v)  {  	/* maximum; incore; ratio free to inuse; freelist */  	seq_printf(m, "%d\t%d\t%d\t%u\n", -			ndquot, +			0,  			xfs_Gqm? atomic_read(&xfs_Gqm->qm_totaldquots) : 0, -			xfs_Gqm? xfs_Gqm->qm_dqfree_ratio : 0, +			0,  			xfs_Gqm? xfs_Gqm->qm_dqfrlist_cnt : 0);  	return 0;  } diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index 6b6df5802e9..bb134a81993 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -733,11 +733,10 @@ DEFINE_EVENT(xfs_dquot_class, name, \  DEFINE_DQUOT_EVENT(xfs_dqadjust);  DEFINE_DQUOT_EVENT(xfs_dqreclaim_want);  DEFINE_DQUOT_EVENT(xfs_dqreclaim_dirty); -DEFINE_DQUOT_EVENT(xfs_dqreclaim_unlink); +DEFINE_DQUOT_EVENT(xfs_dqreclaim_busy); +DEFINE_DQUOT_EVENT(xfs_dqreclaim_done);  DEFINE_DQUOT_EVENT(xfs_dqattach_found);  DEFINE_DQUOT_EVENT(xfs_dqattach_get); -DEFINE_DQUOT_EVENT(xfs_dqinit); -DEFINE_DQUOT_EVENT(xfs_dqreuse);  DEFINE_DQUOT_EVENT(xfs_dqalloc);  DEFINE_DQUOT_EVENT(xfs_dqtobp_read);  DEFINE_DQUOT_EVENT(xfs_dqread); diff --git a/include/asm-generic/pci_iomap.h b/include/asm-generic/pci_iomap.h index 8de4b73e19e..e58fcf89137 100644 --- a/include/asm-generic/pci_iomap.h +++ b/include/asm-generic/pci_iomap.h @@ -15,6 +15,16 @@ struct pci_dev;  #ifdef CONFIG_PCI  /* Create a virtual mapping cookie for a PCI BAR (memory or IO) */  extern void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max); +/* Create a virtual mapping cookie for a port on a given PCI device. + * Do not call this directly, it exists to make it easier for architectures + * to override */ +#ifdef CONFIG_NO_GENERIC_PCI_IOPORT_MAP +extern void __iomem *__pci_ioport_map(struct pci_dev *dev, unsigned long port, +				      unsigned int nr); +#else +#define __pci_ioport_map(dev, port, nr) ioport_map((port), (nr)) +#endif +  #else  static inline void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max)  { diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h index fd88a3945aa..0092102db2d 100644 --- a/include/linux/binfmts.h +++ b/include/linux/binfmts.h @@ -18,7 +18,7 @@ struct pt_regs;  #define BINPRM_BUF_SIZE 128  #ifdef __KERNEL__ -#include <linux/list.h> +#include <linux/sched.h>  #define CORENAME_MAX_SIZE 128 @@ -58,6 +58,7 @@ struct linux_binprm {  	unsigned interp_flags;  	unsigned interp_data;  	unsigned long loader, exec; +	char tcomm[TASK_COMM_LEN];  };  #define BINPRM_FLAGS_ENFORCE_NONDUMP_BIT 0 diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 6c6a1f00806..606cf339bb5 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -399,9 +399,6 @@ struct request_queue {  	/* Throttle data */  	struct throtl_data *td;  #endif -#ifdef CONFIG_LOCKDEP -	int			ioc_release_depth; -#endif  };  #define QUEUE_FLAG_QUEUED	1	/* uses generic tag queueing */ diff --git a/include/linux/cdrom.h b/include/linux/cdrom.h index 35eae4b6750..7c48029dffe 100644 --- a/include/linux/cdrom.h +++ b/include/linux/cdrom.h @@ -952,7 +952,8 @@ struct cdrom_device_info {      	char name[20];                  /* name of the device type */  /* per-device flags */          __u8 sanyo_slot		: 2;	/* Sanyo 3 CD changer support */ -        __u8 reserved		: 6;	/* not used yet */ +        __u8 keeplocked		: 1;	/* CDROM_LOCKDOOR status */ +        __u8 reserved		: 5;	/* not used yet */  	int cdda_method;		/* see flags */  	__u8 last_sense;  	__u8 media_written;		/* dirty flag, DVD+RW bookkeeping */ diff --git a/include/linux/elevator.h b/include/linux/elevator.h index c24f3d7fbf1..7d4e0356f32 100644 --- a/include/linux/elevator.h +++ b/include/linux/elevator.h @@ -42,12 +42,6 @@ struct elevator_ops  	elevator_merged_fn *elevator_merged_fn;  	elevator_merge_req_fn *elevator_merge_req_fn;  	elevator_allow_merge_fn *elevator_allow_merge_fn; - -	/* -	 * Used for both plugged list and elevator merging and in the -	 * former case called without queue_lock.  Read comment on top of -	 * attempt_plug_merge() for details. -	 */  	elevator_bio_merged_fn *elevator_bio_merged_fn;  	elevator_dispatch_fn *elevator_dispatch_fn; @@ -122,7 +116,6 @@ extern void elv_dispatch_add_tail(struct request_queue *, struct request *);  extern void elv_add_request(struct request_queue *, struct request *, int);  extern void __elv_add_request(struct request_queue *, struct request *, int);  extern int elv_merge(struct request_queue *, struct request **, struct bio *); -extern int elv_try_merge(struct request *, struct bio *);  extern void elv_merge_requests(struct request_queue *, struct request *,  			       struct request *);  extern void elv_merged_request(struct request_queue *, struct request *, int); @@ -155,7 +148,7 @@ extern ssize_t elv_iosched_store(struct request_queue *, const char *, size_t);  extern int elevator_init(struct request_queue *, char *);  extern void elevator_exit(struct elevator_queue *);  extern int elevator_change(struct request_queue *, const char *); -extern int elv_rq_merge_ok(struct request *, struct bio *); +extern bool elv_rq_merge_ok(struct request *, struct bio *);  /*   * Helper functions. diff --git a/include/linux/gpio_keys.h b/include/linux/gpio_keys.h index b5ca4b2c08e..004ff33ab38 100644 --- a/include/linux/gpio_keys.h +++ b/include/linux/gpio_keys.h @@ -1,6 +1,8 @@  #ifndef _GPIO_KEYS_H  #define _GPIO_KEYS_H +struct device; +  struct gpio_keys_button {  	/* Configuration parameters */  	unsigned int code;	/* input event code (KEY_*, SW_*) */ diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h index 62b908e0e59..0ae065a5fcb 100644 --- a/include/linux/hyperv.h +++ b/include/linux/hyperv.h @@ -35,7 +35,7 @@  #include <linux/mod_devicetable.h> -#define MAX_PAGE_BUFFER_COUNT				18 +#define MAX_PAGE_BUFFER_COUNT				19  #define MAX_MULTIPAGE_BUFFER_COUNT			32 /* 128K */  #pragma pack(push, 1) diff --git a/include/linux/iocontext.h b/include/linux/iocontext.h index 7e1371c4bcc..119773eebe3 100644 --- a/include/linux/iocontext.h +++ b/include/linux/iocontext.h @@ -133,7 +133,7 @@ static inline struct io_context *ioc_task_link(struct io_context *ioc)  struct task_struct;  #ifdef CONFIG_BLOCK -void put_io_context(struct io_context *ioc, struct request_queue *locked_q); +void put_io_context(struct io_context *ioc);  void exit_io_context(struct task_struct *task);  struct io_context *get_task_io_context(struct task_struct *task,  				       gfp_t gfp_flags, int node); @@ -141,8 +141,7 @@ void ioc_ioprio_changed(struct io_context *ioc, int ioprio);  void ioc_cgroup_changed(struct io_context *ioc);  #else  struct io_context; -static inline void put_io_context(struct io_context *ioc, -				  struct request_queue *locked_q) { } +static inline void put_io_context(struct io_context *ioc) { }  static inline void exit_io_context(struct task_struct *task) { }  #endif diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h index bd4272b61a1..ead4a421579 100644 --- a/include/linux/irqdomain.h +++ b/include/linux/irqdomain.h @@ -9,99 +9,182 @@   * representation into a hardware irq number that can be mapped back to a   * Linux irq number without any extra platform support code.   * - * irq_domain is expected to be embedded in an interrupt controller's private - * data structure. + * Interrupt controller "domain" data structure. This could be defined as a + * irq domain controller. That is, it handles the mapping between hardware + * and virtual interrupt numbers for a given interrupt domain. The domain + * structure is generally created by the PIC code for a given PIC instance + * (though a domain can cover more than one PIC if they have a flat number + * model). It's the domain callbacks that are responsible for setting the + * irq_chip on a given irq_desc after it's been mapped. + * + * The host code and data structures are agnostic to whether or not + * we use an open firmware device-tree. We do have references to struct + * device_node in two places: in irq_find_host() to find the host matching + * a given interrupt controller node, and of course as an argument to its + * counterpart domain->ops->match() callback. However, those are treated as + * generic pointers by the core and the fact that it's actually a device-node + * pointer is purely a convention between callers and implementation. This + * code could thus be used on other architectures by replacing those two + * by some sort of arch-specific void * "token" used to identify interrupt + * controllers.   */ +  #ifndef _LINUX_IRQDOMAIN_H  #define _LINUX_IRQDOMAIN_H -#include <linux/irq.h> -#include <linux/mod_devicetable.h> +#include <linux/types.h> +#include <linux/radix-tree.h> -#ifdef CONFIG_IRQ_DOMAIN  struct device_node;  struct irq_domain; +struct of_device_id; + +/* Number of irqs reserved for a legacy isa controller */ +#define NUM_ISA_INTERRUPTS	16 + +/* This type is the placeholder for a hardware interrupt number. It has to + * be big enough to enclose whatever representation is used by a given + * platform. + */ +typedef unsigned long irq_hw_number_t;  /**   * struct irq_domain_ops - Methods for irq_domain objects - * @to_irq: (optional) given a local hardware irq number, return the linux - *          irq number.  If to_irq is not implemented, then the irq_domain - *          will use this translation: irq = (domain->irq_base + hwirq) - * @dt_translate: Given a device tree node and interrupt specifier, decode - *                the hardware irq number and linux irq type value. + * @match: Match an interrupt controller device node to a host, returns + *         1 on a match + * @map: Create or update a mapping between a virtual irq number and a hw + *       irq number. This is called only once for a given mapping. + * @unmap: Dispose of such a mapping + * @xlate: Given a device tree node and interrupt specifier, decode + *         the hardware irq number and linux irq type value. + * + * Functions below are provided by the driver and called whenever a new mapping + * is created or an old mapping is disposed. The driver can then proceed to + * whatever internal data structures management is required. It also needs + * to setup the irq_desc when returning from map().   */  struct irq_domain_ops { -	unsigned int (*to_irq)(struct irq_domain *d, unsigned long hwirq); - -#ifdef CONFIG_OF -	int (*dt_translate)(struct irq_domain *d, struct device_node *node, -			    const u32 *intspec, unsigned int intsize, -			    unsigned long *out_hwirq, unsigned int *out_type); -#endif /* CONFIG_OF */ +	int (*match)(struct irq_domain *d, struct device_node *node); +	int (*map)(struct irq_domain *d, unsigned int virq, irq_hw_number_t hw); +	void (*unmap)(struct irq_domain *d, unsigned int virq); +	int (*xlate)(struct irq_domain *d, struct device_node *node, +		     const u32 *intspec, unsigned int intsize, +		     unsigned long *out_hwirq, unsigned int *out_type);  };  /**   * struct irq_domain - Hardware interrupt number translation object - * @list: Element in global irq_domain list. + * @link: Element in global irq_domain list. + * @revmap_type: Method used for reverse mapping hwirq numbers to linux irq. This + *               will be one of the IRQ_DOMAIN_MAP_* values. + * @revmap_data: Revmap method specific data. + * @ops: pointer to irq_domain methods + * @host_data: private data pointer for use by owner.  Not touched by irq_domain + *             core code.   * @irq_base: Start of irq_desc range assigned to the irq_domain.  The creator   *            of the irq_domain is responsible for allocating the array of   *            irq_desc structures.   * @nr_irq: Number of irqs managed by the irq domain   * @hwirq_base: Starting number for hwirqs managed by the irq domain - * @ops: pointer to irq_domain methods - * @priv: private data pointer for use by owner.  Not touched by irq_domain - *        core code.   * @of_node: (optional) Pointer to device tree nodes associated with the   *           irq_domain.  Used when decoding device tree interrupt specifiers.   */  struct irq_domain { -	struct list_head list; -	unsigned int irq_base; -	unsigned int nr_irq; -	unsigned int hwirq_base; +	struct list_head link; + +	/* type of reverse mapping_technique */ +	unsigned int revmap_type; +	union { +		struct { +			unsigned int size; +			unsigned int first_irq; +			irq_hw_number_t first_hwirq; +		} legacy; +		struct { +			unsigned int size; +			unsigned int *revmap; +		} linear; +		struct radix_tree_root tree; +	} revmap_data;  	const struct irq_domain_ops *ops; -	void *priv; +	void *host_data; +	irq_hw_number_t inval_irq; + +	/* Optional device node pointer */  	struct device_node *of_node;  }; -/** - * irq_domain_to_irq() - Translate from a hardware irq to a linux irq number - * - * Returns the linux irq number associated with a hardware irq.  By default, - * the mapping is irq == domain->irq_base + hwirq, but this mapping can - * be overridden if the irq_domain implements a .to_irq() hook. - */ -static inline unsigned int irq_domain_to_irq(struct irq_domain *d, -					     unsigned long hwirq) +#ifdef CONFIG_IRQ_DOMAIN +struct irq_domain *irq_domain_add_legacy(struct device_node *of_node, +					 unsigned int size, +					 unsigned int first_irq, +					 irq_hw_number_t first_hwirq, +					 const struct irq_domain_ops *ops, +					 void *host_data); +struct irq_domain *irq_domain_add_linear(struct device_node *of_node, +					 unsigned int size, +					 const struct irq_domain_ops *ops, +					 void *host_data); +struct irq_domain *irq_domain_add_nomap(struct device_node *of_node, +					 const struct irq_domain_ops *ops, +					 void *host_data); +struct irq_domain *irq_domain_add_tree(struct device_node *of_node, +					 const struct irq_domain_ops *ops, +					 void *host_data); + +extern struct irq_domain *irq_find_host(struct device_node *node); +extern void irq_set_default_host(struct irq_domain *host); +extern void irq_set_virq_count(unsigned int count); + +static inline struct irq_domain *irq_domain_add_legacy_isa( +				struct device_node *of_node, +				const struct irq_domain_ops *ops, +				void *host_data)  { -	if (d->ops->to_irq) -		return d->ops->to_irq(d, hwirq); -	if (WARN_ON(hwirq < d->hwirq_base)) -		return 0; -	return d->irq_base + hwirq - d->hwirq_base; +	return irq_domain_add_legacy(of_node, NUM_ISA_INTERRUPTS, 0, 0, ops, +				     host_data);  } +extern struct irq_domain *irq_find_host(struct device_node *node); +extern void irq_set_default_host(struct irq_domain *host); +extern void irq_set_virq_count(unsigned int count); -#define irq_domain_for_each_hwirq(d, hw) \ -	for (hw = d->hwirq_base; hw < d->hwirq_base + d->nr_irq; hw++) -#define irq_domain_for_each_irq(d, hw, irq) \ -	for (hw = d->hwirq_base, irq = irq_domain_to_irq(d, hw); \ -	     hw < d->hwirq_base + d->nr_irq; \ -	     hw++, irq = irq_domain_to_irq(d, hw)) +extern unsigned int irq_create_mapping(struct irq_domain *host, +				       irq_hw_number_t hwirq); +extern void irq_dispose_mapping(unsigned int virq); +extern unsigned int irq_find_mapping(struct irq_domain *host, +				     irq_hw_number_t hwirq); +extern unsigned int irq_create_direct_mapping(struct irq_domain *host); +extern void irq_radix_revmap_insert(struct irq_domain *host, unsigned int virq, +				    irq_hw_number_t hwirq); +extern unsigned int irq_radix_revmap_lookup(struct irq_domain *host, +					    irq_hw_number_t hwirq); +extern unsigned int irq_linear_revmap(struct irq_domain *host, +				      irq_hw_number_t hwirq); -extern void irq_domain_add(struct irq_domain *domain); -extern void irq_domain_del(struct irq_domain *domain); +extern const struct irq_domain_ops irq_domain_simple_ops; -extern struct irq_domain_ops irq_domain_simple_ops; -#endif /* CONFIG_IRQ_DOMAIN */ +/* stock xlate functions */ +int irq_domain_xlate_onecell(struct irq_domain *d, struct device_node *ctrlr, +			const u32 *intspec, unsigned int intsize, +			irq_hw_number_t *out_hwirq, unsigned int *out_type); +int irq_domain_xlate_twocell(struct irq_domain *d, struct device_node *ctrlr, +			const u32 *intspec, unsigned int intsize, +			irq_hw_number_t *out_hwirq, unsigned int *out_type); +int irq_domain_xlate_onetwocell(struct irq_domain *d, struct device_node *ctrlr, +			const u32 *intspec, unsigned int intsize, +			irq_hw_number_t *out_hwirq, unsigned int *out_type); -#if defined(CONFIG_IRQ_DOMAIN) && defined(CONFIG_OF_IRQ) -extern void irq_domain_add_simple(struct device_node *controller, int irq_base); +#if defined(CONFIG_OF_IRQ)  extern void irq_domain_generate_simple(const struct of_device_id *match,  					u64 phys_base, unsigned int irq_start); -#else /* CONFIG_IRQ_DOMAIN && CONFIG_OF_IRQ */ +#else /* CONFIG_OF_IRQ */  static inline void irq_domain_generate_simple(const struct of_device_id *match,  					u64 phys_base, unsigned int irq_start) { } -#endif /* CONFIG_IRQ_DOMAIN && CONFIG_OF_IRQ */ +#endif /* !CONFIG_OF_IRQ */ + +#else /* CONFIG_IRQ_DOMAIN */ +static inline void irq_dispose_mapping(unsigned int virq) { } +#endif /* !CONFIG_IRQ_DOMAIN */  #endif /* _LINUX_IRQDOMAIN_H */ diff --git a/include/linux/lp8727.h b/include/linux/lp8727.h index d21fa2865bf..d21fa2865bf 100755..100644 --- a/include/linux/lp8727.h +++ b/include/linux/lp8727.h diff --git a/include/linux/mfd/twl6040.h b/include/linux/mfd/twl6040.h index 2463c261959..9bc9ac651da 100644 --- a/include/linux/mfd/twl6040.h +++ b/include/linux/mfd/twl6040.h @@ -187,8 +187,10 @@ struct twl6040 {  	int rev;  	u8 vibra_ctrl_cache[2]; +	/* PLL configuration */  	int pll;  	unsigned int sysclk; +	unsigned int mclk;  	unsigned int irq;  	unsigned int irq_base; diff --git a/include/linux/mpi.h b/include/linux/mpi.h index 06f88994cca..d02cca6cc8c 100644 --- a/include/linux/mpi.h +++ b/include/linux/mpi.h @@ -57,8 +57,6 @@ struct gcry_mpi {  typedef struct gcry_mpi *MPI; -#define MPI_NULL NULL -  #define mpi_get_nlimbs(a)     ((a)->nlimbs)  #define mpi_is_neg(a)	      ((a)->sign) diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h index 221295208fd..d43dc25af82 100644 --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h @@ -427,9 +427,7 @@ static inline int mtd_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len)  static inline int mtd_suspend(struct mtd_info *mtd)  { -	if (!mtd->suspend) -		return -EOPNOTSUPP; -	return mtd->suspend(mtd); +	return mtd->suspend ? mtd->suspend(mtd) : 0;  }  static inline void mtd_resume(struct mtd_info *mtd) @@ -489,7 +487,7 @@ static inline int mtd_has_oob(const struct mtd_info *mtd)  static inline int mtd_can_have_bb(const struct mtd_info *mtd)  { -	return 0; +	return !!mtd->block_isbad;  }  	/* Kernel-side ioctl definitions */ diff --git a/include/linux/of_address.h b/include/linux/of_address.h index 3118623c2c1..01b925ad8d7 100644 --- a/include/linux/of_address.h +++ b/include/linux/of_address.h @@ -4,6 +4,7 @@  #include <linux/errno.h>  #include <linux/of.h> +#ifdef CONFIG_OF_ADDRESS  extern u64 of_translate_address(struct device_node *np, const __be32 *addr);  extern int of_address_to_resource(struct device_node *dev, int index,  				  struct resource *r); @@ -25,12 +26,37 @@ static inline unsigned long pci_address_to_pio(phys_addr_t addr) { return -1; }  #define pci_address_to_pio pci_address_to_pio  #endif -#ifdef CONFIG_PCI +#else /* CONFIG_OF_ADDRESS */ +static inline int of_address_to_resource(struct device_node *dev, int index, +					 struct resource *r) +{ +	return -EINVAL; +} +static inline struct device_node *of_find_matching_node_by_address( +					struct device_node *from, +					const struct of_device_id *matches, +					u64 base_address) +{ +	return NULL; +} +static inline void __iomem *of_iomap(struct device_node *device, int index) +{ +	return NULL; +} +static inline const u32 *of_get_address(struct device_node *dev, int index, +					u64 *size, unsigned int *flags) +{ +	return NULL; +} +#endif /* CONFIG_OF_ADDRESS */ + + +#if defined(CONFIG_OF_ADDRESS) && defined(CONFIG_PCI)  extern const __be32 *of_get_pci_address(struct device_node *dev, int bar_no,  			       u64 *size, unsigned int *flags);  extern int of_pci_address_to_resource(struct device_node *dev, int bar,  				      struct resource *r); -#else /* CONFIG_PCI */ +#else /* CONFIG_OF_ADDRESS && CONFIG_PCI */  static inline int of_pci_address_to_resource(struct device_node *dev, int bar,  				             struct resource *r)  { @@ -42,8 +68,7 @@ static inline const __be32 *of_get_pci_address(struct device_node *dev,  {  	return NULL;  } -#endif /* CONFIG_PCI */ - +#endif /* CONFIG_OF_ADDRESS && CONFIG_PCI */  #endif /* __OF_ADDRESS_H */ diff --git a/include/linux/of_irq.h b/include/linux/of_irq.h index d0307eed20c..d229ad3edee 100644 --- a/include/linux/of_irq.h +++ b/include/linux/of_irq.h @@ -6,6 +6,7 @@ struct of_irq;  #include <linux/types.h>  #include <linux/errno.h>  #include <linux/irq.h> +#include <linux/irqdomain.h>  #include <linux/ioport.h>  #include <linux/of.h> @@ -65,9 +66,6 @@ extern int of_irq_map_one(struct device_node *device, int index,  extern unsigned int irq_create_of_mapping(struct device_node *controller,  					  const u32 *intspec,  					  unsigned int intsize); -#ifdef CONFIG_IRQ_DOMAIN -extern void irq_dispose_mapping(unsigned int irq); -#endif  extern int of_irq_to_resource(struct device_node *dev, int index,  			      struct resource *r);  extern int of_irq_count(struct device_node *dev); diff --git a/include/linux/of_platform.h b/include/linux/of_platform.h index 040ce2f6e8d..242fa3563e2 100644 --- a/include/linux/of_platform.h +++ b/include/linux/of_platform.h @@ -81,7 +81,7 @@ extern struct platform_device *of_device_alloc(struct device_node *np,  					 struct device *parent);  extern struct platform_device *of_find_device_by_node(struct device_node *np); -#if !defined(CONFIG_SPARC) /* SPARC has its own device registration method */ +#ifdef CONFIG_OF_ADDRESS /* device reg helpers depend on OF_ADDRESS */  /* Platform devices and busses creation */  extern struct platform_device *of_platform_device_create(struct device_node *np,  						   const char *bus_id, @@ -94,7 +94,15 @@ extern int of_platform_populate(struct device_node *root,  				const struct of_device_id *matches,  				const struct of_dev_auxdata *lookup,  				struct device *parent); -#endif /* !CONFIG_SPARC */ +#else +static inline int of_platform_populate(struct device_node *root, +					const struct of_device_id *matches, +					const struct of_dev_auxdata *lookup, +					struct device *parent) +{ +	return -ENODEV; +} +#endif /* !CONFIG_OF_ADDRESS */  #endif /* CONFIG_OF_DEVICE */ diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index 08855613ceb..abb2776be1b 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -587,6 +587,7 @@ struct hw_perf_event {  	u64				sample_period;  	u64				last_period;  	local64_t			period_left; +	u64                             interrupts_seq;  	u64				interrupts;  	u64				freq_time_stamp; diff --git a/include/linux/pm_qos.h b/include/linux/pm_qos.h index e5bbcbaa6f5..4d99e4e6ef8 100644 --- a/include/linux/pm_qos.h +++ b/include/linux/pm_qos.h @@ -110,7 +110,19 @@ static inline void pm_qos_remove_request(struct pm_qos_request *req)  			{ return; }  static inline int pm_qos_request(int pm_qos_class) -			{ return 0; } +{ +	switch (pm_qos_class) { +	case PM_QOS_CPU_DMA_LATENCY: +		return PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE; +	case PM_QOS_NETWORK_LATENCY: +		return PM_QOS_NETWORK_LAT_DEFAULT_VALUE; +	case PM_QOS_NETWORK_THROUGHPUT: +		return PM_QOS_NETWORK_THROUGHPUT_DEFAULT_VALUE; +	default: +		return PM_QOS_DEFAULT_VALUE; +	} +} +  static inline int pm_qos_add_notifier(int pm_qos_class,  				      struct notifier_block *notifier)  			{ return 0; } diff --git a/include/linux/proportions.h b/include/linux/proportions.h index ef35bb73f69..26a8a4ed9b0 100644 --- a/include/linux/proportions.h +++ b/include/linux/proportions.h @@ -81,7 +81,11 @@ void prop_inc_percpu(struct prop_descriptor *pd, struct prop_local_percpu *pl)   * Limit the time part in order to ensure there are some bits left for the   * cycle counter and fraction multiply.   */ +#if BITS_PER_LONG == 32  #define PROP_MAX_SHIFT (3*BITS_PER_LONG/4) +#else +#define PROP_MAX_SHIFT (BITS_PER_LONG/2) +#endif  #define PROP_FRAC_SHIFT		(BITS_PER_LONG - PROP_MAX_SHIFT - 1)  #define PROP_FRAC_BASE		(1UL << PROP_FRAC_SHIFT) diff --git a/include/linux/sched.h b/include/linux/sched.h index 2234985a5e6..7d379a6bfd8 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -2259,6 +2259,12 @@ static inline void mmdrop(struct mm_struct * mm)  extern void mmput(struct mm_struct *);  /* Grab a reference to a task's mm, if it is not already going away */  extern struct mm_struct *get_task_mm(struct task_struct *task); +/* + * Grab a reference to a task's mm, if it is not already going away + * and ptrace_may_access with the mode parameter passed to it + * succeeds. + */ +extern struct mm_struct *mm_access(struct task_struct *task, unsigned int mode);  /* Remove the current tasks stale references to the old mm_struct */  extern void mm_release(struct task_struct *, struct mm_struct *);  /* Allocate a new mm structure and copy contents from tsk->mm */ diff --git a/include/linux/sh_dma.h b/include/linux/sh_dma.h index 8cd7fe59cf1..425450b980b 100644 --- a/include/linux/sh_dma.h +++ b/include/linux/sh_dma.h @@ -70,6 +70,7 @@ struct sh_dmae_pdata {  	unsigned int needs_tend_set:1;  	unsigned int no_dmars:1;  	unsigned int chclr_present:1; +	unsigned int slave_only:1;  };  /* DMA register */ diff --git a/include/linux/usb/ch9.h b/include/linux/usb/ch9.h index 61b29057b05..3b6f628880f 100644 --- a/include/linux/usb/ch9.h +++ b/include/linux/usb/ch9.h @@ -589,7 +589,7 @@ static inline int usb_endpoint_is_isoc_out(   */  static inline int usb_endpoint_maxp(const struct usb_endpoint_descriptor *epd)  { -	return le16_to_cpu(epd->wMaxPacketSize); +	return __le16_to_cpu(epd->wMaxPacketSize);  }  /*-------------------------------------------------------------------------*/ diff --git a/include/net/flow.h b/include/net/flow.h index 9b582437fbe..6c469dbdb91 100644 --- a/include/net/flow.h +++ b/include/net/flow.h @@ -93,6 +93,16 @@ static inline void flowi4_init_output(struct flowi4 *fl4, int oif,  	fl4->fl4_dport = dport;  	fl4->fl4_sport = sport;  } + +/* Reset some input parameters after previous lookup */ +static inline void flowi4_update_output(struct flowi4 *fl4, int oif, __u8 tos, +					__be32 daddr, __be32 saddr) +{ +	fl4->flowi4_oif = oif; +	fl4->flowi4_tos = tos; +	fl4->daddr = daddr; +	fl4->saddr = saddr; +}  struct flowi6 { diff --git a/include/net/netprio_cgroup.h b/include/net/netprio_cgroup.h index 7b2d43139c8..d58fdec4759 100644 --- a/include/net/netprio_cgroup.h +++ b/include/net/netprio_cgroup.h @@ -37,19 +37,51 @@ extern int net_prio_subsys_id;  extern void sock_update_netprioidx(struct sock *sk); -static inline struct cgroup_netprio_state -		*task_netprio_state(struct task_struct *p) +#if IS_BUILTIN(CONFIG_NETPRIO_CGROUP) + +static inline u32 task_netprioidx(struct task_struct *p)  { -#if IS_ENABLED(CONFIG_NETPRIO_CGROUP) -	return container_of(task_subsys_state(p, net_prio_subsys_id), -			    struct cgroup_netprio_state, css); -#else -	return NULL; -#endif +	struct cgroup_netprio_state *state; +	u32 idx; + +	rcu_read_lock(); +	state = container_of(task_subsys_state(p, net_prio_subsys_id), +			     struct cgroup_netprio_state, css); +	idx = state->prioidx; +	rcu_read_unlock(); +	return idx; +} + +#elif IS_MODULE(CONFIG_NETPRIO_CGROUP) + +static inline u32 task_netprioidx(struct task_struct *p) +{ +	struct cgroup_netprio_state *state; +	int subsys_id; +	u32 idx = 0; + +	rcu_read_lock(); +	subsys_id = rcu_dereference_index_check(net_prio_subsys_id, +						rcu_read_lock_held()); +	if (subsys_id >= 0) { +		state = container_of(task_subsys_state(p, subsys_id), +				     struct cgroup_netprio_state, css); +		idx = state->prioidx; +	} +	rcu_read_unlock(); +	return idx;  }  #else +static inline u32 task_netprioidx(struct task_struct *p) +{ +	return 0; +} + +#endif /* CONFIG_NETPRIO_CGROUP */ + +#else  #define sock_update_netprioidx(sk)  #endif diff --git a/include/net/route.h b/include/net/route.h index 91855d185b5..b1c0d5b564c 100644 --- a/include/net/route.h +++ b/include/net/route.h @@ -270,6 +270,7 @@ static inline struct rtable *ip_route_connect(struct flowi4 *fl4,  		if (IS_ERR(rt))  			return rt;  		ip_rt_put(rt); +		flowi4_update_output(fl4, oif, tos, fl4->daddr, fl4->saddr);  	}  	security_sk_classify_flow(sk, flowi4_to_flowi(fl4));  	return ip_route_output_flow(net, fl4, sk); @@ -284,6 +285,9 @@ static inline struct rtable *ip_route_newports(struct flowi4 *fl4, struct rtable  		fl4->fl4_dport = dport;  		fl4->fl4_sport = sport;  		ip_rt_put(rt); +		flowi4_update_output(fl4, sk->sk_bound_dev_if, +				     RT_CONN_FLAGS(sk), fl4->daddr, +				     fl4->saddr);  		security_sk_classify_flow(sk, flowi4_to_flowi(fl4));  		return ip_route_output_flow(sock_net(sk), fl4, sk);  	} diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h index f6bb08b73ca..55ce96b53b0 100644 --- a/include/net/sch_generic.h +++ b/include/net/sch_generic.h @@ -220,9 +220,16 @@ struct tcf_proto {  struct qdisc_skb_cb {  	unsigned int		pkt_len; -	long			data[]; +	unsigned char		data[24];  }; +static inline void qdisc_cb_private_validate(const struct sk_buff *skb, int sz) +{ +	struct qdisc_skb_cb *qcb; +	BUILD_BUG_ON(sizeof(skb->cb) < sizeof(unsigned int) + sz); +	BUILD_BUG_ON(sizeof(qcb->data) < sz); +} +  static inline int qdisc_qlen(const struct Qdisc *q)  {  	return q->q.qlen; diff --git a/include/net/tcp.h b/include/net/tcp.h index d49db0113a0..42c29bfbcee 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -273,6 +273,14 @@ static inline int between(__u32 seq1, __u32 seq2, __u32 seq3)  	return seq3 - seq2 >= seq1 - seq2;  } +static inline bool tcp_out_of_memory(struct sock *sk) +{ +	if (sk->sk_wmem_queued > SOCK_MIN_SNDBUF && +	    sk_memory_allocated(sk) > sk_prot_mem_limits(sk, 2)) +		return true; +	return false; +} +  static inline bool tcp_too_many_orphans(struct sock *sk, int shift)  {  	struct percpu_counter *ocp = sk->sk_prot->orphan_count; @@ -283,13 +291,11 @@ static inline bool tcp_too_many_orphans(struct sock *sk, int shift)  		if (orphans << shift > sysctl_tcp_max_orphans)  			return true;  	} - -	if (sk->sk_wmem_queued > SOCK_MIN_SNDBUF && -	    sk_memory_allocated(sk) > sk_prot_mem_limits(sk, 2)) -		return true;  	return false;  } +extern bool tcp_check_oom(struct sock *sk, int shift); +  /* syncookies: remember time of last synqueue overflow */  static inline void tcp_synq_overflow(struct sock *sk)  { diff --git a/include/sound/core.h b/include/sound/core.h index 5ab255f196c..cea1b5426df 100644 --- a/include/sound/core.h +++ b/include/sound/core.h @@ -417,6 +417,7 @@ static inline int __snd_bug_on(int cond)  #define gameport_get_port_data(gp) (gp)->port_data  #endif +#ifdef CONFIG_PCI  /* PCI quirk list helper */  struct snd_pci_quirk {  	unsigned short subvendor;	/* PCI subvendor ID */ @@ -456,5 +457,6 @@ snd_pci_quirk_lookup(struct pci_dev *pci, const struct snd_pci_quirk *list);  const struct snd_pci_quirk *  snd_pci_quirk_lookup_id(u16 vendor, u16 device,  			const struct snd_pci_quirk *list); +#endif  #endif /* __SOUND_CORE_H */ diff --git a/include/target/target_core_backend.h b/include/target/target_core_backend.h index 4866499bdee..e5e6ff98f0f 100644 --- a/include/target/target_core_backend.h +++ b/include/target/target_core_backend.h @@ -59,7 +59,7 @@ int	transport_set_vpd_ident_type(struct t10_vpd *, unsigned char *);  int	transport_set_vpd_ident(struct t10_vpd *, unsigned char *);  /* core helpers also used by command snooping in pscsi */ -void	*transport_kmap_first_data_page(struct se_cmd *); -void	transport_kunmap_first_data_page(struct se_cmd *); +void	*transport_kmap_data_sg(struct se_cmd *); +void	transport_kunmap_data_sg(struct se_cmd *);  #endif /* TARGET_CORE_BACKEND_H */ diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index daf532bc721..dc4e345a016 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -582,6 +582,7 @@ struct se_cmd {  	struct scatterlist	*t_data_sg;  	unsigned int		t_data_nents; +	void			*t_data_vmap;  	struct scatterlist	*t_bidi_data_sg;  	unsigned int		t_bidi_data_nents; diff --git a/include/target/target_core_fabric.h b/include/target/target_core_fabric.h index 523e8bc104d..d36fad317e7 100644 --- a/include/target/target_core_fabric.h +++ b/include/target/target_core_fabric.h @@ -114,7 +114,7 @@ void	transport_init_se_cmd(struct se_cmd *, struct target_core_fabric_ops *,  		struct se_session *, u32, int, int, unsigned char *);  int	transport_lookup_cmd_lun(struct se_cmd *, u32);  int	transport_generic_allocate_tasks(struct se_cmd *, unsigned char *); -int	target_submit_cmd(struct se_cmd *, struct se_session *, unsigned char *, +void	target_submit_cmd(struct se_cmd *, struct se_session *, unsigned char *,  		unsigned char *, u32, u32, int, int, int);  int	transport_handle_cdb_direct(struct se_cmd *);  int	transport_generic_handle_cdb_map(struct se_cmd *); diff --git a/include/trace/events/writeback.h b/include/trace/events/writeback.h index 8588a891802..5973410e8f8 100644 --- a/include/trace/events/writeback.h +++ b/include/trace/events/writeback.h @@ -47,7 +47,10 @@ DECLARE_EVENT_CLASS(writeback_work_class,  		__field(int, reason)  	),  	TP_fast_assign( -		strncpy(__entry->name, dev_name(bdi->dev), 32); +		struct device *dev = bdi->dev; +		if (!dev) +			dev = default_backing_dev_info.dev; +		strncpy(__entry->name, dev_name(dev), 32);  		__entry->nr_pages = work->nr_pages;  		__entry->sb_dev = work->sb ? work->sb->s_dev : 0;  		__entry->sync_mode = work->sync_mode; @@ -426,7 +429,7 @@ DECLARE_EVENT_CLASS(writeback_single_inode_template,  	TP_fast_assign(  		strncpy(__entry->name, -			dev_name(inode->i_mapping->backing_dev_info->dev), 32); +			dev_name(inode_to_bdi(inode)->dev), 32);  		__entry->ino		= inode->i_ino;  		__entry->state		= inode->i_state;  		__entry->dirtied_when	= inode->dirtied_when; diff --git a/include/video/omapdss.h b/include/video/omapdss.h index 062b3b24ff1..483f67caa7a 100644 --- a/include/video/omapdss.h +++ b/include/video/omapdss.h @@ -590,6 +590,11 @@ struct omap_dss_device {  	int (*get_backlight)(struct omap_dss_device *dssdev);  }; +struct omap_dss_hdmi_data +{ +	int hpd_gpio; +}; +  struct omap_dss_driver {  	struct device_driver driver; diff --git a/kernel/events/core.c b/kernel/events/core.c index 32b48c88971..1b5c081d8b9 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -2300,7 +2300,10 @@ do {					\  	return div64_u64(dividend, divisor);  } -static void perf_adjust_period(struct perf_event *event, u64 nsec, u64 count) +static DEFINE_PER_CPU(int, perf_throttled_count); +static DEFINE_PER_CPU(u64, perf_throttled_seq); + +static void perf_adjust_period(struct perf_event *event, u64 nsec, u64 count, bool disable)  {  	struct hw_perf_event *hwc = &event->hw;  	s64 period, sample_period; @@ -2319,22 +2322,40 @@ static void perf_adjust_period(struct perf_event *event, u64 nsec, u64 count)  	hwc->sample_period = sample_period;  	if (local64_read(&hwc->period_left) > 8*sample_period) { -		event->pmu->stop(event, PERF_EF_UPDATE); +		if (disable) +			event->pmu->stop(event, PERF_EF_UPDATE); +  		local64_set(&hwc->period_left, 0); -		event->pmu->start(event, PERF_EF_RELOAD); + +		if (disable) +			event->pmu->start(event, PERF_EF_RELOAD);  	}  } -static void perf_ctx_adjust_freq(struct perf_event_context *ctx, u64 period) +/* + * combine freq adjustment with unthrottling to avoid two passes over the + * events. At the same time, make sure, having freq events does not change + * the rate of unthrottling as that would introduce bias. + */ +static void perf_adjust_freq_unthr_context(struct perf_event_context *ctx, +					   int needs_unthr)  {  	struct perf_event *event;  	struct hw_perf_event *hwc; -	u64 interrupts, now; +	u64 now, period = TICK_NSEC;  	s64 delta; -	if (!ctx->nr_freq) +	/* +	 * only need to iterate over all events iff: +	 * - context have events in frequency mode (needs freq adjust) +	 * - there are events to unthrottle on this cpu +	 */ +	if (!(ctx->nr_freq || needs_unthr))  		return; +	raw_spin_lock(&ctx->lock); +	perf_pmu_disable(ctx->pmu); +  	list_for_each_entry_rcu(event, &ctx->event_list, event_entry) {  		if (event->state != PERF_EVENT_STATE_ACTIVE)  			continue; @@ -2344,13 +2365,8 @@ static void perf_ctx_adjust_freq(struct perf_event_context *ctx, u64 period)  		hwc = &event->hw; -		interrupts = hwc->interrupts; -		hwc->interrupts = 0; - -		/* -		 * unthrottle events on the tick -		 */ -		if (interrupts == MAX_INTERRUPTS) { +		if (needs_unthr && hwc->interrupts == MAX_INTERRUPTS) { +			hwc->interrupts = 0;  			perf_log_throttle(event, 1);  			event->pmu->start(event, 0);  		} @@ -2358,14 +2374,30 @@ static void perf_ctx_adjust_freq(struct perf_event_context *ctx, u64 period)  		if (!event->attr.freq || !event->attr.sample_freq)  			continue; -		event->pmu->read(event); +		/* +		 * stop the event and update event->count +		 */ +		event->pmu->stop(event, PERF_EF_UPDATE); +  		now = local64_read(&event->count);  		delta = now - hwc->freq_count_stamp;  		hwc->freq_count_stamp = now; +		/* +		 * restart the event +		 * reload only if value has changed +		 * we have stopped the event so tell that +		 * to perf_adjust_period() to avoid stopping it +		 * twice. +		 */  		if (delta > 0) -			perf_adjust_period(event, period, delta); +			perf_adjust_period(event, period, delta, false); + +		event->pmu->start(event, delta > 0 ? PERF_EF_RELOAD : 0);  	} + +	perf_pmu_enable(ctx->pmu); +	raw_spin_unlock(&ctx->lock);  }  /* @@ -2388,16 +2420,13 @@ static void rotate_ctx(struct perf_event_context *ctx)   */  static void perf_rotate_context(struct perf_cpu_context *cpuctx)  { -	u64 interval = (u64)cpuctx->jiffies_interval * TICK_NSEC;  	struct perf_event_context *ctx = NULL; -	int rotate = 0, remove = 1, freq = 0; +	int rotate = 0, remove = 1;  	if (cpuctx->ctx.nr_events) {  		remove = 0;  		if (cpuctx->ctx.nr_events != cpuctx->ctx.nr_active)  			rotate = 1; -		if (cpuctx->ctx.nr_freq) -			freq = 1;  	}  	ctx = cpuctx->task_ctx; @@ -2405,37 +2434,26 @@ static void perf_rotate_context(struct perf_cpu_context *cpuctx)  		remove = 0;  		if (ctx->nr_events != ctx->nr_active)  			rotate = 1; -		if (ctx->nr_freq) -			freq = 1;  	} -	if (!rotate && !freq) +	if (!rotate)  		goto done;  	perf_ctx_lock(cpuctx, cpuctx->task_ctx);  	perf_pmu_disable(cpuctx->ctx.pmu); -	if (freq) { -		perf_ctx_adjust_freq(&cpuctx->ctx, interval); -		if (ctx) -			perf_ctx_adjust_freq(ctx, interval); -	} - -	if (rotate) { -		cpu_ctx_sched_out(cpuctx, EVENT_FLEXIBLE); -		if (ctx) -			ctx_sched_out(ctx, cpuctx, EVENT_FLEXIBLE); +	cpu_ctx_sched_out(cpuctx, EVENT_FLEXIBLE); +	if (ctx) +		ctx_sched_out(ctx, cpuctx, EVENT_FLEXIBLE); -		rotate_ctx(&cpuctx->ctx); -		if (ctx) -			rotate_ctx(ctx); +	rotate_ctx(&cpuctx->ctx); +	if (ctx) +		rotate_ctx(ctx); -		perf_event_sched_in(cpuctx, ctx, current); -	} +	perf_event_sched_in(cpuctx, ctx, current);  	perf_pmu_enable(cpuctx->ctx.pmu);  	perf_ctx_unlock(cpuctx, cpuctx->task_ctx); -  done:  	if (remove)  		list_del_init(&cpuctx->rotation_list); @@ -2445,10 +2463,22 @@ void perf_event_task_tick(void)  {  	struct list_head *head = &__get_cpu_var(rotation_list);  	struct perf_cpu_context *cpuctx, *tmp; +	struct perf_event_context *ctx; +	int throttled;  	WARN_ON(!irqs_disabled()); +	__this_cpu_inc(perf_throttled_seq); +	throttled = __this_cpu_xchg(perf_throttled_count, 0); +  	list_for_each_entry_safe(cpuctx, tmp, head, rotation_list) { +		ctx = &cpuctx->ctx; +		perf_adjust_freq_unthr_context(ctx, throttled); + +		ctx = cpuctx->task_ctx; +		if (ctx) +			perf_adjust_freq_unthr_context(ctx, throttled); +  		if (cpuctx->jiffies_interval == 1 ||  				!(jiffies % cpuctx->jiffies_interval))  			perf_rotate_context(cpuctx); @@ -4509,6 +4539,7 @@ static int __perf_event_overflow(struct perf_event *event,  {  	int events = atomic_read(&event->event_limit);  	struct hw_perf_event *hwc = &event->hw; +	u64 seq;  	int ret = 0;  	/* @@ -4518,14 +4549,20 @@ static int __perf_event_overflow(struct perf_event *event,  	if (unlikely(!is_sampling_event(event)))  		return 0; -	if (unlikely(hwc->interrupts >= max_samples_per_tick)) { -		if (throttle) { +	seq = __this_cpu_read(perf_throttled_seq); +	if (seq != hwc->interrupts_seq) { +		hwc->interrupts_seq = seq; +		hwc->interrupts = 1; +	} else { +		hwc->interrupts++; +		if (unlikely(throttle +			     && hwc->interrupts >= max_samples_per_tick)) { +			__this_cpu_inc(perf_throttled_count);  			hwc->interrupts = MAX_INTERRUPTS;  			perf_log_throttle(event, 0);  			ret = 1;  		} -	} else -		hwc->interrupts++; +	}  	if (event->attr.freq) {  		u64 now = perf_clock(); @@ -4534,7 +4571,7 @@ static int __perf_event_overflow(struct perf_event *event,  		hwc->freq_time_stamp = now;  		if (delta > 0 && delta < 2*TICK_NSEC) -			perf_adjust_period(event, delta, hwc->last_period); +			perf_adjust_period(event, delta, hwc->last_period, true);  	}  	/* diff --git a/kernel/exit.c b/kernel/exit.c index 294b1709170..4b4042f9bc6 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -1038,6 +1038,22 @@ void do_exit(long code)  	if (tsk->nr_dirtied)  		__this_cpu_add(dirty_throttle_leaks, tsk->nr_dirtied);  	exit_rcu(); + +	/* +	 * The setting of TASK_RUNNING by try_to_wake_up() may be delayed +	 * when the following two conditions become true. +	 *   - There is race condition of mmap_sem (It is acquired by +	 *     exit_mm()), and +	 *   - SMI occurs before setting TASK_RUNINNG. +	 *     (or hypervisor of virtual machine switches to other guest) +	 *  As a result, we may become TASK_RUNNING after becoming TASK_DEAD +	 * +	 * To avoid it, we have to wait for releasing tsk->pi_lock which +	 * is held by try_to_wake_up() +	 */ +	smp_mb(); +	raw_spin_unlock_wait(&tsk->pi_lock); +  	/* causes final put_task_struct in finish_task_switch(). */  	tsk->state = TASK_DEAD;  	tsk->flags |= PF_NOFREEZE;	/* tell freezer to ignore us */ diff --git a/kernel/fork.c b/kernel/fork.c index 051f090d40c..b77fd559c78 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -647,6 +647,26 @@ struct mm_struct *get_task_mm(struct task_struct *task)  }  EXPORT_SYMBOL_GPL(get_task_mm); +struct mm_struct *mm_access(struct task_struct *task, unsigned int mode) +{ +	struct mm_struct *mm; +	int err; + +	err =  mutex_lock_killable(&task->signal->cred_guard_mutex); +	if (err) +		return ERR_PTR(err); + +	mm = get_task_mm(task); +	if (mm && mm != current->mm && +			!ptrace_may_access(task, mode)) { +		mmput(mm); +		mm = ERR_PTR(-EACCES); +	} +	mutex_unlock(&task->signal->cred_guard_mutex); + +	return mm; +} +  /* Please note the differences between mmput and mm_release.   * mmput is called whenever we stop holding onto a mm_struct,   * error success whatever. @@ -890,7 +910,7 @@ static int copy_io(unsigned long clone_flags, struct task_struct *tsk)  			return -ENOMEM;  		new_ioc->ioprio = ioc->ioprio; -		put_io_context(new_ioc, NULL); +		put_io_context(new_ioc);  	}  #endif  	return 0; diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c index 1f9e26526b6..af48e59bc2f 100644 --- a/kernel/irq/irqdomain.c +++ b/kernel/irq/irqdomain.c @@ -1,189 +1,793 @@ +#include <linux/debugfs.h> +#include <linux/hardirq.h> +#include <linux/interrupt.h>  #include <linux/irq.h> +#include <linux/irqdesc.h>  #include <linux/irqdomain.h>  #include <linux/module.h>  #include <linux/mutex.h>  #include <linux/of.h>  #include <linux/of_address.h> +#include <linux/seq_file.h>  #include <linux/slab.h> +#include <linux/smp.h> +#include <linux/fs.h> + +#define IRQ_DOMAIN_MAP_LEGACY 0 /* driver allocated fixed range of irqs. +				 * ie. legacy 8259, gets irqs 1..15 */ +#define IRQ_DOMAIN_MAP_NOMAP 1 /* no fast reverse mapping */ +#define IRQ_DOMAIN_MAP_LINEAR 2 /* linear map of interrupts */ +#define IRQ_DOMAIN_MAP_TREE 3 /* radix tree */  static LIST_HEAD(irq_domain_list);  static DEFINE_MUTEX(irq_domain_mutex); +static DEFINE_MUTEX(revmap_trees_mutex); +static unsigned int irq_virq_count = NR_IRQS; +static struct irq_domain *irq_default_domain; +  /** - * irq_domain_add() - Register an irq_domain - * @domain: ptr to initialized irq_domain structure + * irq_domain_alloc() - Allocate a new irq_domain data structure + * @of_node: optional device-tree node of the interrupt controller + * @revmap_type: type of reverse mapping to use + * @ops: map/unmap domain callbacks + * @host_data: Controller private data pointer   * - * Registers an irq_domain structure.  The irq_domain must at a minimum be - * initialized with an ops structure pointer, and either a ->to_irq hook or - * a valid irq_base value.  Everything else is optional. + * Allocates and initialize and irq_domain structure.  Caller is expected to + * register allocated irq_domain with irq_domain_register().  Returns pointer + * to IRQ domain, or NULL on failure.   */ -void irq_domain_add(struct irq_domain *domain) +static struct irq_domain *irq_domain_alloc(struct device_node *of_node, +					   unsigned int revmap_type, +					   const struct irq_domain_ops *ops, +					   void *host_data)  { -	struct irq_data *d; -	int hwirq, irq; +	struct irq_domain *domain; -	/* -	 * This assumes that the irq_domain owner has already allocated -	 * the irq_descs.  This block will be removed when support for dynamic -	 * allocation of irq_descs is added to irq_domain. -	 */ -	irq_domain_for_each_irq(domain, hwirq, irq) { -		d = irq_get_irq_data(irq); -		if (!d) { -			WARN(1, "error: assigning domain to non existant irq_desc"); -			return; -		} -		if (d->domain) { -			/* things are broken; just report, don't clean up */ -			WARN(1, "error: irq_desc already assigned to a domain"); -			return; +	domain = kzalloc(sizeof(*domain), GFP_KERNEL); +	if (WARN_ON(!domain)) +		return NULL; + +	/* Fill structure */ +	domain->revmap_type = revmap_type; +	domain->ops = ops; +	domain->host_data = host_data; +	domain->of_node = of_node_get(of_node); + +	return domain; +} + +static void irq_domain_add(struct irq_domain *domain) +{ +	mutex_lock(&irq_domain_mutex); +	list_add(&domain->link, &irq_domain_list); +	mutex_unlock(&irq_domain_mutex); +	pr_debug("irq: Allocated domain of type %d @0x%p\n", +		 domain->revmap_type, domain); +} + +static unsigned int irq_domain_legacy_revmap(struct irq_domain *domain, +					     irq_hw_number_t hwirq) +{ +	irq_hw_number_t first_hwirq = domain->revmap_data.legacy.first_hwirq; +	int size = domain->revmap_data.legacy.size; + +	if (WARN_ON(hwirq < first_hwirq || hwirq >= first_hwirq + size)) +		return 0; +	return hwirq - first_hwirq + domain->revmap_data.legacy.first_irq; +} + +/** + * irq_domain_add_legacy() - Allocate and register a legacy revmap irq_domain. + * @of_node: pointer to interrupt controller's device tree node. + * @size: total number of irqs in legacy mapping + * @first_irq: first number of irq block assigned to the domain + * @first_hwirq: first hwirq number to use for the translation. Should normally + *               be '0', but a positive integer can be used if the effective + *               hwirqs numbering does not begin at zero. + * @ops: map/unmap domain callbacks + * @host_data: Controller private data pointer + * + * Note: the map() callback will be called before this function returns + * for all legacy interrupts except 0 (which is always the invalid irq for + * a legacy controller). + */ +struct irq_domain *irq_domain_add_legacy(struct device_node *of_node, +					 unsigned int size, +					 unsigned int first_irq, +					 irq_hw_number_t first_hwirq, +					 const struct irq_domain_ops *ops, +					 void *host_data) +{ +	struct irq_domain *domain; +	unsigned int i; + +	domain = irq_domain_alloc(of_node, IRQ_DOMAIN_MAP_LEGACY, ops, host_data); +	if (!domain) +		return NULL; + +	domain->revmap_data.legacy.first_irq = first_irq; +	domain->revmap_data.legacy.first_hwirq = first_hwirq; +	domain->revmap_data.legacy.size = size; + +	mutex_lock(&irq_domain_mutex); +	/* Verify that all the irqs are available */ +	for (i = 0; i < size; i++) { +		int irq = first_irq + i; +		struct irq_data *irq_data = irq_get_irq_data(irq); + +		if (WARN_ON(!irq_data || irq_data->domain)) { +			mutex_unlock(&irq_domain_mutex); +			of_node_put(domain->of_node); +			kfree(domain); +			return NULL;  		} -		d->domain = domain; -		d->hwirq = hwirq;  	} -	mutex_lock(&irq_domain_mutex); -	list_add(&domain->list, &irq_domain_list); +	/* Claim all of the irqs before registering a legacy domain */ +	for (i = 0; i < size; i++) { +		struct irq_data *irq_data = irq_get_irq_data(first_irq + i); +		irq_data->hwirq = first_hwirq + i; +		irq_data->domain = domain; +	}  	mutex_unlock(&irq_domain_mutex); + +	for (i = 0; i < size; i++) { +		int irq = first_irq + i; +		int hwirq = first_hwirq + i; + +		/* IRQ0 gets ignored */ +		if (!irq) +			continue; + +		/* Legacy flags are left to default at this point, +		 * one can then use irq_create_mapping() to +		 * explicitly change them +		 */ +		ops->map(domain, irq, hwirq); + +		/* Clear norequest flags */ +		irq_clear_status_flags(irq, IRQ_NOREQUEST); +	} + +	irq_domain_add(domain); +	return domain; +} + +/** + * irq_domain_add_linear() - Allocate and register a legacy revmap irq_domain. + * @of_node: pointer to interrupt controller's device tree node. + * @ops: map/unmap domain callbacks + * @host_data: Controller private data pointer + */ +struct irq_domain *irq_domain_add_linear(struct device_node *of_node, +					 unsigned int size, +					 const struct irq_domain_ops *ops, +					 void *host_data) +{ +	struct irq_domain *domain; +	unsigned int *revmap; + +	revmap = kzalloc(sizeof(*revmap) * size, GFP_KERNEL); +	if (WARN_ON(!revmap)) +		return NULL; + +	domain = irq_domain_alloc(of_node, IRQ_DOMAIN_MAP_LINEAR, ops, host_data); +	if (!domain) { +		kfree(revmap); +		return NULL; +	} +	domain->revmap_data.linear.size = size; +	domain->revmap_data.linear.revmap = revmap; +	irq_domain_add(domain); +	return domain; +} + +struct irq_domain *irq_domain_add_nomap(struct device_node *of_node, +					 const struct irq_domain_ops *ops, +					 void *host_data) +{ +	struct irq_domain *domain = irq_domain_alloc(of_node, +					IRQ_DOMAIN_MAP_NOMAP, ops, host_data); +	if (domain) +		irq_domain_add(domain); +	return domain; +} + +/** + * irq_domain_add_tree() + * @of_node: pointer to interrupt controller's device tree node. + * @ops: map/unmap domain callbacks + * + * Note: The radix tree will be allocated later during boot automatically + * (the reverse mapping will use the slow path until that happens). + */ +struct irq_domain *irq_domain_add_tree(struct device_node *of_node, +					 const struct irq_domain_ops *ops, +					 void *host_data) +{ +	struct irq_domain *domain = irq_domain_alloc(of_node, +					IRQ_DOMAIN_MAP_TREE, ops, host_data); +	if (domain) { +		INIT_RADIX_TREE(&domain->revmap_data.tree, GFP_KERNEL); +		irq_domain_add(domain); +	} +	return domain;  }  /** - * irq_domain_del() - Unregister an irq_domain - * @domain: ptr to registered irq_domain. + * irq_find_host() - Locates a domain for a given device node + * @node: device-tree node of the interrupt controller   */ -void irq_domain_del(struct irq_domain *domain) +struct irq_domain *irq_find_host(struct device_node *node)  { -	struct irq_data *d; -	int hwirq, irq; +	struct irq_domain *h, *found = NULL; +	int rc; +	/* We might want to match the legacy controller last since +	 * it might potentially be set to match all interrupts in +	 * the absence of a device node. This isn't a problem so far +	 * yet though... +	 */  	mutex_lock(&irq_domain_mutex); -	list_del(&domain->list); +	list_for_each_entry(h, &irq_domain_list, link) { +		if (h->ops->match) +			rc = h->ops->match(h, node); +		else +			rc = (h->of_node != NULL) && (h->of_node == node); + +		if (rc) { +			found = h; +			break; +		} +	}  	mutex_unlock(&irq_domain_mutex); +	return found; +} +EXPORT_SYMBOL_GPL(irq_find_host); + +/** + * irq_set_default_host() - Set a "default" irq domain + * @domain: default domain pointer + * + * For convenience, it's possible to set a "default" domain that will be used + * whenever NULL is passed to irq_create_mapping(). It makes life easier for + * platforms that want to manipulate a few hard coded interrupt numbers that + * aren't properly represented in the device-tree. + */ +void irq_set_default_host(struct irq_domain *domain) +{ +	pr_debug("irq: Default domain set to @0x%p\n", domain); + +	irq_default_domain = domain; +} + +/** + * irq_set_virq_count() - Set the maximum number of linux irqs + * @count: number of linux irqs, capped with NR_IRQS + * + * This is mainly for use by platforms like iSeries who want to program + * the virtual irq number in the controller to avoid the reverse mapping + */ +void irq_set_virq_count(unsigned int count) +{ +	pr_debug("irq: Trying to set virq count to %d\n", count); -	/* Clear the irq_domain assignments */ -	irq_domain_for_each_irq(domain, hwirq, irq) { -		d = irq_get_irq_data(irq); -		d->domain = NULL; +	BUG_ON(count < NUM_ISA_INTERRUPTS); +	if (count < NR_IRQS) +		irq_virq_count = count; +} + +static int irq_setup_virq(struct irq_domain *domain, unsigned int virq, +			    irq_hw_number_t hwirq) +{ +	struct irq_data *irq_data = irq_get_irq_data(virq); + +	irq_data->hwirq = hwirq; +	irq_data->domain = domain; +	if (domain->ops->map(domain, virq, hwirq)) { +		pr_debug("irq: -> mapping failed, freeing\n"); +		irq_data->domain = NULL; +		irq_data->hwirq = 0; +		return -1;  	} + +	irq_clear_status_flags(virq, IRQ_NOREQUEST); + +	return 0;  } -#if defined(CONFIG_OF_IRQ)  /** - * irq_create_of_mapping() - Map a linux irq number from a DT interrupt spec + * irq_create_direct_mapping() - Allocate an irq for direct mapping + * @domain: domain to allocate the irq for or NULL for default domain   * - * Used by the device tree interrupt mapping code to translate a device tree - * interrupt specifier to a valid linux irq number.  Returns either a valid - * linux IRQ number or 0. + * This routine is used for irq controllers which can choose the hardware + * interrupt numbers they generate. In such a case it's simplest to use + * the linux irq as the hardware interrupt number. + */ +unsigned int irq_create_direct_mapping(struct irq_domain *domain) +{ +	unsigned int virq; + +	if (domain == NULL) +		domain = irq_default_domain; + +	BUG_ON(domain == NULL); +	WARN_ON(domain->revmap_type != IRQ_DOMAIN_MAP_NOMAP); + +	virq = irq_alloc_desc_from(1, 0); +	if (!virq) { +		pr_debug("irq: create_direct virq allocation failed\n"); +		return 0; +	} +	if (virq >= irq_virq_count) { +		pr_err("ERROR: no free irqs available below %i maximum\n", +			irq_virq_count); +		irq_free_desc(virq); +		return 0; +	} + +	pr_debug("irq: create_direct obtained virq %d\n", virq); + +	if (irq_setup_virq(domain, virq, virq)) { +		irq_free_desc(virq); +		return 0; +	} + +	return virq; +} + +/** + * irq_create_mapping() - Map a hardware interrupt into linux irq space + * @domain: domain owning this hardware interrupt or NULL for default domain + * @hwirq: hardware irq number in that domain space   * - * When the caller no longer need the irq number returned by this function it - * should arrange to call irq_dispose_mapping(). + * Only one mapping per hardware interrupt is permitted. Returns a linux + * irq number. + * If the sense/trigger is to be specified, set_irq_type() should be called + * on the number returned from that call.   */ +unsigned int irq_create_mapping(struct irq_domain *domain, +				irq_hw_number_t hwirq) +{ +	unsigned int virq, hint; + +	pr_debug("irq: irq_create_mapping(0x%p, 0x%lx)\n", domain, hwirq); + +	/* Look for default domain if nececssary */ +	if (domain == NULL) +		domain = irq_default_domain; +	if (domain == NULL) { +		printk(KERN_WARNING "irq_create_mapping called for" +		       " NULL domain, hwirq=%lx\n", hwirq); +		WARN_ON(1); +		return 0; +	} +	pr_debug("irq: -> using domain @%p\n", domain); + +	/* Check if mapping already exists */ +	virq = irq_find_mapping(domain, hwirq); +	if (virq) { +		pr_debug("irq: -> existing mapping on virq %d\n", virq); +		return virq; +	} + +	/* Get a virtual interrupt number */ +	if (domain->revmap_type == IRQ_DOMAIN_MAP_LEGACY) +		return irq_domain_legacy_revmap(domain, hwirq); + +	/* Allocate a virtual interrupt number */ +	hint = hwirq % irq_virq_count; +	if (hint == 0) +		hint++; +	virq = irq_alloc_desc_from(hint, 0); +	if (!virq) +		virq = irq_alloc_desc_from(1, 0); +	if (!virq) { +		pr_debug("irq: -> virq allocation failed\n"); +		return 0; +	} + +	if (irq_setup_virq(domain, virq, hwirq)) { +		if (domain->revmap_type != IRQ_DOMAIN_MAP_LEGACY) +			irq_free_desc(virq); +		return 0; +	} + +	pr_debug("irq: irq %lu on domain %s mapped to virtual irq %u\n", +		hwirq, domain->of_node ? domain->of_node->full_name : "null", virq); + +	return virq; +} +EXPORT_SYMBOL_GPL(irq_create_mapping); +  unsigned int irq_create_of_mapping(struct device_node *controller,  				   const u32 *intspec, unsigned int intsize)  {  	struct irq_domain *domain; -	unsigned long hwirq; -	unsigned int irq, type; -	int rc = -EINVAL; +	irq_hw_number_t hwirq; +	unsigned int type = IRQ_TYPE_NONE; +	unsigned int virq; -	/* Find a domain which can translate the irq spec */ -	mutex_lock(&irq_domain_mutex); -	list_for_each_entry(domain, &irq_domain_list, list) { -		if (!domain->ops->dt_translate) -			continue; -		rc = domain->ops->dt_translate(domain, controller, -					intspec, intsize, &hwirq, &type); -		if (rc == 0) -			break; +	domain = controller ? irq_find_host(controller) : irq_default_domain; +	if (!domain) { +#ifdef CONFIG_MIPS +		/* +		 * Workaround to avoid breaking interrupt controller drivers +		 * that don't yet register an irq_domain.  This is temporary +		 * code. ~~~gcl, Feb 24, 2012 +		 * +		 * Scheduled for removal in Linux v3.6.  That should be enough +		 * time. +		 */ +		if (intsize > 0) +			return intspec[0]; +#endif +		printk(KERN_WARNING "irq: no irq domain found for %s !\n", +		       controller->full_name); +		return 0;  	} -	mutex_unlock(&irq_domain_mutex); -	if (rc != 0) -		return 0; +	/* If domain has no translation, then we assume interrupt line */ +	if (domain->ops->xlate == NULL) +		hwirq = intspec[0]; +	else { +		if (domain->ops->xlate(domain, controller, intspec, intsize, +				     &hwirq, &type)) +			return 0; +	} + +	/* Create mapping */ +	virq = irq_create_mapping(domain, hwirq); +	if (!virq) +		return virq; -	irq = irq_domain_to_irq(domain, hwirq); -	if (type != IRQ_TYPE_NONE) -		irq_set_irq_type(irq, type); -	pr_debug("%s: mapped hwirq=%i to irq=%i, flags=%x\n", -		 controller->full_name, (int)hwirq, irq, type); -	return irq; +	/* Set type if specified and different than the current one */ +	if (type != IRQ_TYPE_NONE && +	    type != (irqd_get_trigger_type(irq_get_irq_data(virq)))) +		irq_set_irq_type(virq, type); +	return virq;  }  EXPORT_SYMBOL_GPL(irq_create_of_mapping);  /** - * irq_dispose_mapping() - Discard a mapping created by irq_create_of_mapping() - * @irq: linux irq number to be discarded + * irq_dispose_mapping() - Unmap an interrupt + * @virq: linux irq number of the interrupt to unmap + */ +void irq_dispose_mapping(unsigned int virq) +{ +	struct irq_data *irq_data = irq_get_irq_data(virq); +	struct irq_domain *domain; +	irq_hw_number_t hwirq; + +	if (!virq || !irq_data) +		return; + +	domain = irq_data->domain; +	if (WARN_ON(domain == NULL)) +		return; + +	/* Never unmap legacy interrupts */ +	if (domain->revmap_type == IRQ_DOMAIN_MAP_LEGACY) +		return; + +	irq_set_status_flags(virq, IRQ_NOREQUEST); + +	/* remove chip and handler */ +	irq_set_chip_and_handler(virq, NULL, NULL); + +	/* Make sure it's completed */ +	synchronize_irq(virq); + +	/* Tell the PIC about it */ +	if (domain->ops->unmap) +		domain->ops->unmap(domain, virq); +	smp_mb(); + +	/* Clear reverse map */ +	hwirq = irq_data->hwirq; +	switch(domain->revmap_type) { +	case IRQ_DOMAIN_MAP_LINEAR: +		if (hwirq < domain->revmap_data.linear.size) +			domain->revmap_data.linear.revmap[hwirq] = 0; +		break; +	case IRQ_DOMAIN_MAP_TREE: +		mutex_lock(&revmap_trees_mutex); +		radix_tree_delete(&domain->revmap_data.tree, hwirq); +		mutex_unlock(&revmap_trees_mutex); +		break; +	} + +	irq_free_desc(virq); +} +EXPORT_SYMBOL_GPL(irq_dispose_mapping); + +/** + * irq_find_mapping() - Find a linux irq from an hw irq number. + * @domain: domain owning this hardware interrupt + * @hwirq: hardware irq number in that domain space + * + * This is a slow path, for use by generic code. It's expected that an + * irq controller implementation directly calls the appropriate low level + * mapping function. + */ +unsigned int irq_find_mapping(struct irq_domain *domain, +			      irq_hw_number_t hwirq) +{ +	unsigned int i; +	unsigned int hint = hwirq % irq_virq_count; + +	/* Look for default domain if nececssary */ +	if (domain == NULL) +		domain = irq_default_domain; +	if (domain == NULL) +		return 0; + +	/* legacy -> bail early */ +	if (domain->revmap_type == IRQ_DOMAIN_MAP_LEGACY) +		return irq_domain_legacy_revmap(domain, hwirq); + +	/* Slow path does a linear search of the map */ +	if (hint == 0) +		hint = 1; +	i = hint; +	do { +		struct irq_data *data = irq_get_irq_data(i); +		if (data && (data->domain == domain) && (data->hwirq == hwirq)) +			return i; +		i++; +		if (i >= irq_virq_count) +			i = 1; +	} while(i != hint); +	return 0; +} +EXPORT_SYMBOL_GPL(irq_find_mapping); + +/** + * irq_radix_revmap_lookup() - Find a linux irq from a hw irq number. + * @domain: domain owning this hardware interrupt + * @hwirq: hardware irq number in that domain space   * - * Calling this function indicates the caller no longer needs a reference to - * the linux irq number returned by a prior call to irq_create_of_mapping(). + * This is a fast path, for use by irq controller code that uses radix tree + * revmaps   */ -void irq_dispose_mapping(unsigned int irq) +unsigned int irq_radix_revmap_lookup(struct irq_domain *domain, +				     irq_hw_number_t hwirq)  { +	struct irq_data *irq_data; + +	if (WARN_ON_ONCE(domain->revmap_type != IRQ_DOMAIN_MAP_TREE)) +		return irq_find_mapping(domain, hwirq); + +	/* +	 * Freeing an irq can delete nodes along the path to +	 * do the lookup via call_rcu. +	 */ +	rcu_read_lock(); +	irq_data = radix_tree_lookup(&domain->revmap_data.tree, hwirq); +	rcu_read_unlock(); +  	/* -	 * nothing yet; will be filled when support for dynamic allocation of -	 * irq_descs is added to irq_domain +	 * If found in radix tree, then fine. +	 * Else fallback to linear lookup - this should not happen in practice +	 * as it means that we failed to insert the node in the radix tree.  	 */ +	return irq_data ? irq_data->irq : irq_find_mapping(domain, hwirq);  } -EXPORT_SYMBOL_GPL(irq_dispose_mapping); -int irq_domain_simple_dt_translate(struct irq_domain *d, -			    struct device_node *controller, -			    const u32 *intspec, unsigned int intsize, -			    unsigned long *out_hwirq, unsigned int *out_type) +/** + * irq_radix_revmap_insert() - Insert a hw irq to linux irq number mapping. + * @domain: domain owning this hardware interrupt + * @virq: linux irq number + * @hwirq: hardware irq number in that domain space + * + * This is for use by irq controllers that use a radix tree reverse + * mapping for fast lookup. + */ +void irq_radix_revmap_insert(struct irq_domain *domain, unsigned int virq, +			     irq_hw_number_t hwirq)  { -	if (d->of_node != controller) -		return -EINVAL; -	if (intsize < 1) -		return -EINVAL; -	if (d->nr_irq && ((intspec[0] < d->hwirq_base) || -	    (intspec[0] >= d->hwirq_base + d->nr_irq))) -		return -EINVAL; +	struct irq_data *irq_data = irq_get_irq_data(virq); + +	if (WARN_ON(domain->revmap_type != IRQ_DOMAIN_MAP_TREE)) +		return; + +	if (virq) { +		mutex_lock(&revmap_trees_mutex); +		radix_tree_insert(&domain->revmap_data.tree, hwirq, irq_data); +		mutex_unlock(&revmap_trees_mutex); +	} +} + +/** + * irq_linear_revmap() - Find a linux irq from a hw irq number. + * @domain: domain owning this hardware interrupt + * @hwirq: hardware irq number in that domain space + * + * This is a fast path, for use by irq controller code that uses linear + * revmaps. It does fallback to the slow path if the revmap doesn't exist + * yet and will create the revmap entry with appropriate locking + */ +unsigned int irq_linear_revmap(struct irq_domain *domain, +			       irq_hw_number_t hwirq) +{ +	unsigned int *revmap; + +	if (WARN_ON_ONCE(domain->revmap_type != IRQ_DOMAIN_MAP_LINEAR)) +		return irq_find_mapping(domain, hwirq); + +	/* Check revmap bounds */ +	if (unlikely(hwirq >= domain->revmap_data.linear.size)) +		return irq_find_mapping(domain, hwirq); + +	/* Check if revmap was allocated */ +	revmap = domain->revmap_data.linear.revmap; +	if (unlikely(revmap == NULL)) +		return irq_find_mapping(domain, hwirq); + +	/* Fill up revmap with slow path if no mapping found */ +	if (unlikely(!revmap[hwirq])) +		revmap[hwirq] = irq_find_mapping(domain, hwirq); + +	return revmap[hwirq]; +} + +#ifdef CONFIG_VIRQ_DEBUG +static int virq_debug_show(struct seq_file *m, void *private) +{ +	unsigned long flags; +	struct irq_desc *desc; +	const char *p; +	static const char none[] = "none"; +	void *data; +	int i; + +	seq_printf(m, "%-5s  %-7s  %-15s  %-18s  %s\n", "virq", "hwirq", +		      "chip name", "chip data", "domain name"); + +	for (i = 1; i < nr_irqs; i++) { +		desc = irq_to_desc(i); +		if (!desc) +			continue; + +		raw_spin_lock_irqsave(&desc->lock, flags); + +		if (desc->action && desc->action->handler) { +			struct irq_chip *chip; + +			seq_printf(m, "%5d  ", i); +			seq_printf(m, "0x%05lx  ", desc->irq_data.hwirq); + +			chip = irq_desc_get_chip(desc); +			if (chip && chip->name) +				p = chip->name; +			else +				p = none; +			seq_printf(m, "%-15s  ", p); + +			data = irq_desc_get_chip_data(desc); +			seq_printf(m, "0x%16p  ", data); + +			if (desc->irq_data.domain->of_node) +				p = desc->irq_data.domain->of_node->full_name; +			else +				p = none; +			seq_printf(m, "%s\n", p); +		} + +		raw_spin_unlock_irqrestore(&desc->lock, flags); +	} + +	return 0; +} +static int virq_debug_open(struct inode *inode, struct file *file) +{ +	return single_open(file, virq_debug_show, inode->i_private); +} + +static const struct file_operations virq_debug_fops = { +	.open = virq_debug_open, +	.read = seq_read, +	.llseek = seq_lseek, +	.release = single_release, +}; + +static int __init irq_debugfs_init(void) +{ +	if (debugfs_create_file("virq_mapping", S_IRUGO, powerpc_debugfs_root, +				 NULL, &virq_debug_fops) == NULL) +		return -ENOMEM; + +	return 0; +} +__initcall(irq_debugfs_init); +#endif /* CONFIG_VIRQ_DEBUG */ + +int irq_domain_simple_map(struct irq_domain *d, unsigned int irq, +			  irq_hw_number_t hwirq) +{ +	return 0; +} + +/** + * irq_domain_xlate_onecell() - Generic xlate for direct one cell bindings + * + * Device Tree IRQ specifier translation function which works with one cell + * bindings where the cell value maps directly to the hwirq number. + */ +int irq_domain_xlate_onecell(struct irq_domain *d, struct device_node *ctrlr, +			     const u32 *intspec, unsigned int intsize, +			     unsigned long *out_hwirq, unsigned int *out_type) +{ +	if (WARN_ON(intsize < 1)) +		return -EINVAL;  	*out_hwirq = intspec[0];  	*out_type = IRQ_TYPE_NONE; -	if (intsize > 1) -		*out_type = intspec[1] & IRQ_TYPE_SENSE_MASK;  	return 0;  } +EXPORT_SYMBOL_GPL(irq_domain_xlate_onecell);  /** - * irq_domain_create_simple() - Set up a 'simple' translation range + * irq_domain_xlate_twocell() - Generic xlate for direct two cell bindings + * + * Device Tree IRQ specifier translation function which works with two cell + * bindings where the cell values map directly to the hwirq number + * and linux irq flags.   */ -void irq_domain_add_simple(struct device_node *controller, int irq_base) +int irq_domain_xlate_twocell(struct irq_domain *d, struct device_node *ctrlr, +			const u32 *intspec, unsigned int intsize, +			irq_hw_number_t *out_hwirq, unsigned int *out_type)  { -	struct irq_domain *domain; - -	domain = kzalloc(sizeof(*domain), GFP_KERNEL); -	if (!domain) { -		WARN_ON(1); -		return; -	} +	if (WARN_ON(intsize < 2)) +		return -EINVAL; +	*out_hwirq = intspec[0]; +	*out_type = intspec[1] & IRQ_TYPE_SENSE_MASK; +	return 0; +} +EXPORT_SYMBOL_GPL(irq_domain_xlate_twocell); -	domain->irq_base = irq_base; -	domain->of_node = of_node_get(controller); -	domain->ops = &irq_domain_simple_ops; -	irq_domain_add(domain); +/** + * irq_domain_xlate_onetwocell() - Generic xlate for one or two cell bindings + * + * Device Tree IRQ specifier translation function which works with either one + * or two cell bindings where the cell values map directly to the hwirq number + * and linux irq flags. + * + * Note: don't use this function unless your interrupt controller explicitly + * supports both one and two cell bindings.  For the majority of controllers + * the _onecell() or _twocell() variants above should be used. + */ +int irq_domain_xlate_onetwocell(struct irq_domain *d, +				struct device_node *ctrlr, +				const u32 *intspec, unsigned int intsize, +				unsigned long *out_hwirq, unsigned int *out_type) +{ +	if (WARN_ON(intsize < 1)) +		return -EINVAL; +	*out_hwirq = intspec[0]; +	*out_type = (intsize > 1) ? intspec[1] : IRQ_TYPE_NONE; +	return 0;  } -EXPORT_SYMBOL_GPL(irq_domain_add_simple); +EXPORT_SYMBOL_GPL(irq_domain_xlate_onetwocell); +const struct irq_domain_ops irq_domain_simple_ops = { +	.map = irq_domain_simple_map, +	.xlate = irq_domain_xlate_onetwocell, +}; +EXPORT_SYMBOL_GPL(irq_domain_simple_ops); + +#ifdef CONFIG_OF_IRQ  void irq_domain_generate_simple(const struct of_device_id *match,  				u64 phys_base, unsigned int irq_start)  {  	struct device_node *node; -	pr_info("looking for phys_base=%llx, irq_start=%i\n", +	pr_debug("looking for phys_base=%llx, irq_start=%i\n",  		(unsigned long long) phys_base, (int) irq_start);  	node = of_find_matching_node_by_address(NULL, match, phys_base);  	if (node) -		irq_domain_add_simple(node, irq_start); -	else -		pr_info("no node found\n"); +		irq_domain_add_legacy(node, 32, irq_start, 0, +				      &irq_domain_simple_ops, NULL);  }  EXPORT_SYMBOL_GPL(irq_domain_generate_simple); -#endif /* CONFIG_OF_IRQ */ - -struct irq_domain_ops irq_domain_simple_ops = { -#ifdef CONFIG_OF_IRQ -	.dt_translate = irq_domain_simple_dt_translate, -#endif /* CONFIG_OF_IRQ */ -}; -EXPORT_SYMBOL_GPL(irq_domain_simple_ops); +#endif diff --git a/kernel/kprobes.c b/kernel/kprobes.c index 29f5b65bee2..9788c0ec6f4 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c @@ -1673,8 +1673,12 @@ static int __kprobes pre_handler_kretprobe(struct kprobe *p,  		ri->rp = rp;  		ri->task = current; -		if (rp->entry_handler && rp->entry_handler(ri, regs)) +		if (rp->entry_handler && rp->entry_handler(ri, regs)) { +			raw_spin_lock_irqsave(&rp->lock, flags); +			hlist_add_head(&ri->hlist, &rp->free_instances); +			raw_spin_unlock_irqrestore(&rp->lock, flags);  			return 0; +		}  		arch_prepare_kretprobe(ri, regs); diff --git a/kernel/params.c b/kernel/params.c index 32ee0430828..4bc965d8a1f 100644 --- a/kernel/params.c +++ b/kernel/params.c @@ -97,7 +97,8 @@ static int parse_one(char *param,  	for (i = 0; i < num_params; i++) {  		if (parameq(param, params[i].name)) {  			/* No one handled NULL, so do it here. */ -			if (!val && params[i].ops->set != param_set_bool) +			if (!val && params[i].ops->set != param_set_bool +			    && params[i].ops->set != param_set_bint)  				return -EINVAL;  			pr_debug("They are equal!  Calling %p\n",  			       params[i].ops->set); diff --git a/kernel/power/power.h b/kernel/power/power.h index 0c4defe6d3b..21724eee520 100644 --- a/kernel/power/power.h +++ b/kernel/power/power.h @@ -231,8 +231,28 @@ extern int pm_test_level;  #ifdef CONFIG_SUSPEND_FREEZER  static inline int suspend_freeze_processes(void)  { -	int error = freeze_processes(); -	return error ? : freeze_kernel_threads(); +	int error; + +	error = freeze_processes(); + +	/* +	 * freeze_processes() automatically thaws every task if freezing +	 * fails. So we need not do anything extra upon error. +	 */ +	if (error) +		goto Finish; + +	error = freeze_kernel_threads(); + +	/* +	 * freeze_kernel_threads() thaws only kernel threads upon freezing +	 * failure. So we have to thaw the userspace tasks ourselves. +	 */ +	if (error) +		thaw_processes(); + + Finish: +	return error;  }  static inline void suspend_thaw_processes(void) diff --git a/kernel/power/process.c b/kernel/power/process.c index eeca00311f3..7e426459e60 100644 --- a/kernel/power/process.c +++ b/kernel/power/process.c @@ -143,7 +143,10 @@ int freeze_processes(void)  /**   * freeze_kernel_threads - Make freezable kernel threads go to the refrigerator.   * - * On success, returns 0.  On failure, -errno and system is fully thawed. + * On success, returns 0.  On failure, -errno and only the kernel threads are + * thawed, so as to give a chance to the caller to do additional cleanups + * (if any) before thawing the userspace tasks. So, it is the responsibility + * of the caller to thaw the userspace tasks, when the time is right.   */  int freeze_kernel_threads(void)  { @@ -159,7 +162,7 @@ int freeze_kernel_threads(void)  	BUG_ON(in_atomic());  	if (error) -		thaw_processes(); +		thaw_kernel_threads();  	return error;  } diff --git a/kernel/power/user.c b/kernel/power/user.c index e5a21a85730..3e100075b13 100644 --- a/kernel/power/user.c +++ b/kernel/power/user.c @@ -249,13 +249,15 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd,  		}  		pm_restore_gfp_mask();  		error = hibernation_snapshot(data->platform_support); -		if (!error) { +		if (error) { +			thaw_kernel_threads(); +		} else {  			error = put_user(in_suspend, (int __user *)arg);  			if (!error && !freezer_test_done)  				data->ready = 1;  			if (freezer_test_done) {  				freezer_test_done = false; -				thaw_processes(); +				thaw_kernel_threads();  			}  		}  		break; diff --git a/kernel/relay.c b/kernel/relay.c index 4335e1d7ee2..ab56a1764d4 100644 --- a/kernel/relay.c +++ b/kernel/relay.c @@ -164,10 +164,14 @@ depopulate:   */  static struct rchan_buf *relay_create_buf(struct rchan *chan)  { -	struct rchan_buf *buf = kzalloc(sizeof(struct rchan_buf), GFP_KERNEL); -	if (!buf) +	struct rchan_buf *buf; + +	if (chan->n_subbufs > UINT_MAX / sizeof(size_t *))  		return NULL; +	buf = kzalloc(sizeof(struct rchan_buf), GFP_KERNEL); +	if (!buf) +		return NULL;  	buf->padding = kmalloc(chan->n_subbufs * sizeof(size_t *), GFP_KERNEL);  	if (!buf->padding)  		goto free_buf; @@ -574,6 +578,8 @@ struct rchan *relay_open(const char *base_filename,  	if (!(subbuf_size && n_subbufs))  		return NULL; +	if (subbuf_size > UINT_MAX / n_subbufs) +		return NULL;  	chan = kzalloc(sizeof(struct rchan), GFP_KERNEL);  	if (!chan) diff --git a/kernel/sched/core.c b/kernel/sched/core.c index df00cb09263..5255c9d2e05 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -74,6 +74,7 @@  #include <asm/tlb.h>  #include <asm/irq_regs.h> +#include <asm/mutex.h>  #ifdef CONFIG_PARAVIRT  #include <asm/paravirt.h>  #endif @@ -723,9 +724,6 @@ static void dequeue_task(struct rq *rq, struct task_struct *p, int flags)  	p->sched_class->dequeue_task(rq, p, flags);  } -/* - * activate_task - move a task to the runqueue. - */  void activate_task(struct rq *rq, struct task_struct *p, int flags)  {  	if (task_contributes_to_load(p)) @@ -734,9 +732,6 @@ void activate_task(struct rq *rq, struct task_struct *p, int flags)  	enqueue_task(rq, p, flags);  } -/* - * deactivate_task - remove a task from the runqueue. - */  void deactivate_task(struct rq *rq, struct task_struct *p, int flags)  {  	if (task_contributes_to_load(p)) @@ -4134,7 +4129,7 @@ recheck:  	on_rq = p->on_rq;  	running = task_current(rq, p);  	if (on_rq) -		deactivate_task(rq, p, 0); +		dequeue_task(rq, p, 0);  	if (running)  		p->sched_class->put_prev_task(rq, p); @@ -4147,7 +4142,7 @@ recheck:  	if (running)  		p->sched_class->set_curr_task(rq);  	if (on_rq) -		activate_task(rq, p, 0); +		enqueue_task(rq, p, 0);  	check_class_changed(rq, p, prev_class, oldprio);  	task_rq_unlock(rq, p, &flags); @@ -4998,9 +4993,9 @@ static int __migrate_task(struct task_struct *p, int src_cpu, int dest_cpu)  	 * placed properly.  	 */  	if (p->on_rq) { -		deactivate_task(rq_src, p, 0); +		dequeue_task(rq_src, p, 0);  		set_task_cpu(p, dest_cpu); -		activate_task(rq_dest, p, 0); +		enqueue_task(rq_dest, p, 0);  		check_preempt_curr(rq_dest, p, 0);  	}  done: @@ -7032,10 +7027,10 @@ static void normalize_task(struct rq *rq, struct task_struct *p)  	on_rq = p->on_rq;  	if (on_rq) -		deactivate_task(rq, p, 0); +		dequeue_task(rq, p, 0);  	__setscheduler(rq, p, SCHED_NORMAL, 0);  	if (on_rq) { -		activate_task(rq, p, 0); +		enqueue_task(rq, p, 0);  		resched_task(rq->curr);  	} diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 84adb2d66cb..7c6414fc669 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -4866,6 +4866,15 @@ static void nohz_balancer_kick(int cpu)  	return;  } +static inline void clear_nohz_tick_stopped(int cpu) +{ +	if (unlikely(test_bit(NOHZ_TICK_STOPPED, nohz_flags(cpu)))) { +		cpumask_clear_cpu(cpu, nohz.idle_cpus_mask); +		atomic_dec(&nohz.nr_cpus); +		clear_bit(NOHZ_TICK_STOPPED, nohz_flags(cpu)); +	} +} +  static inline void set_cpu_sd_state_busy(void)  {  	struct sched_domain *sd; @@ -4904,6 +4913,12 @@ void select_nohz_load_balancer(int stop_tick)  {  	int cpu = smp_processor_id(); +	/* +	 * If this cpu is going down, then nothing needs to be done. +	 */ +	if (!cpu_active(cpu)) +		return; +  	if (stop_tick) {  		if (test_bit(NOHZ_TICK_STOPPED, nohz_flags(cpu)))  			return; @@ -4914,6 +4929,18 @@ void select_nohz_load_balancer(int stop_tick)  	}  	return;  } + +static int __cpuinit sched_ilb_notifier(struct notifier_block *nfb, +					unsigned long action, void *hcpu) +{ +	switch (action & ~CPU_TASKS_FROZEN) { +	case CPU_DYING: +		clear_nohz_tick_stopped(smp_processor_id()); +		return NOTIFY_OK; +	default: +		return NOTIFY_DONE; +	} +}  #endif  static DEFINE_SPINLOCK(balancing); @@ -5070,11 +5097,7 @@ static inline int nohz_kick_needed(struct rq *rq, int cpu)  	* busy tick after returning from idle, we will update the busy stats.  	*/  	set_cpu_sd_state_busy(); -	if (unlikely(test_bit(NOHZ_TICK_STOPPED, nohz_flags(cpu)))) { -		clear_bit(NOHZ_TICK_STOPPED, nohz_flags(cpu)); -		cpumask_clear_cpu(cpu, nohz.idle_cpus_mask); -		atomic_dec(&nohz.nr_cpus); -	} +	clear_nohz_tick_stopped(cpu);  	/*  	 * None are in tickless mode and hence no need for NOHZ idle load @@ -5590,6 +5613,7 @@ __init void init_sched_fair_class(void)  #ifdef CONFIG_NO_HZ  	zalloc_cpumask_var(&nohz.idle_cpus_mask, GFP_NOWAIT); +	cpu_notifier(sched_ilb_notifier, 0);  #endif  #endif /* SMP */ diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c index 3640ebbb466..f42ae7fb5ec 100644 --- a/kernel/sched/rt.c +++ b/kernel/sched/rt.c @@ -1587,6 +1587,11 @@ static int push_rt_task(struct rq *rq)  	if (!next_task)  		return 0; +#ifdef __ARCH_WANT_INTERRUPTS_ON_CTXSW +       if (unlikely(task_running(rq, next_task))) +               return 0; +#endif +  retry:  	if (unlikely(next_task == rq->curr)) {  		WARN_ON(1); diff --git a/kernel/watchdog.c b/kernel/watchdog.c index 1d7bca7f4f5..d117262deba 100644 --- a/kernel/watchdog.c +++ b/kernel/watchdog.c @@ -296,7 +296,7 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer)  		if (__this_cpu_read(soft_watchdog_warn) == true)  			return HRTIMER_RESTART; -		printk(KERN_ERR "BUG: soft lockup - CPU#%d stuck for %us! [%s:%d]\n", +		printk(KERN_EMERG "BUG: soft lockup - CPU#%d stuck for %us! [%s:%d]\n",  			smp_processor_id(), duration,  			current->comm, task_pid_nr(current));  		print_modules(); diff --git a/lib/Kconfig b/lib/Kconfig index 169eb7c598e..028aba9e72a 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -19,6 +19,9 @@ config RATIONAL  config GENERIC_FIND_FIRST_BIT  	bool +config NO_GENERIC_PCI_IOPORT_MAP +	bool +  config GENERIC_PCI_IOMAP  	bool @@ -279,6 +282,9 @@ config AVERAGE  	  If unsure, say N. +config CLZ_TAB +	bool +  config CORDIC  	tristate "CORDIC algorithm"  	help @@ -287,6 +293,7 @@ config CORDIC  config MPILIB  	tristate +	select CLZ_TAB  	help  	  Multiprecision maths library from GnuPG.  	  It is used to implement RSA digital signature verification, diff --git a/lib/Makefile b/lib/Makefile index d71aae1b01b..18515f0267c 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -121,6 +121,8 @@ obj-$(CONFIG_DQL) += dynamic_queue_limits.o  obj-$(CONFIG_MPILIB) += mpi/  obj-$(CONFIG_SIGNATURE) += digsig.o +obj-$(CONFIG_CLZ_TAB) += clz_tab.o +  hostprogs-y	:= gen_crc32table  clean-files	:= crc32table.h diff --git a/lib/bug.c b/lib/bug.c index 19552096d16..a28c1415357 100644 --- a/lib/bug.c +++ b/lib/bug.c @@ -169,7 +169,7 @@ enum bug_trap_type report_bug(unsigned long bugaddr, struct pt_regs *regs)  		return BUG_TRAP_TYPE_WARN;  	} -	printk(KERN_EMERG "------------[ cut here ]------------\n"); +	printk(KERN_DEFAULT "------------[ cut here ]------------\n");  	if (file)  		printk(KERN_CRIT "kernel BUG at %s:%u!\n", diff --git a/lib/clz_tab.c b/lib/clz_tab.c new file mode 100644 index 00000000000..7287b4a991a --- /dev/null +++ b/lib/clz_tab.c @@ -0,0 +1,18 @@ +const unsigned char __clz_tab[] = { +	0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, +	    5, 5, 5, 5, 5, 5, 5, 5, +	6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, +	    6, 6, 6, 6, 6, 6, 6, 6, +	7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, +	    7, 7, 7, 7, 7, 7, 7, 7, +	7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, +	    7, 7, 7, 7, 7, 7, 7, 7, +	8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, +	    8, 8, 8, 8, 8, 8, 8, 8, +	8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, +	    8, 8, 8, 8, 8, 8, 8, 8, +	8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, +	    8, 8, 8, 8, 8, 8, 8, 8, +	8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, +	    8, 8, 8, 8, 8, 8, 8, 8, +}; diff --git a/lib/digsig.c b/lib/digsig.c index fd2402f67f8..286d558033e 100644 --- a/lib/digsig.c +++ b/lib/digsig.c @@ -34,14 +34,9 @@ static int pkcs_1_v1_5_decode_emsa(const unsigned char *msg,  			unsigned long  msglen,  			unsigned long  modulus_bitlen,  			unsigned char *out, -			unsigned long *outlen, -			int *is_valid) +			unsigned long *outlen)  {  	unsigned long modulus_len, ps_len, i; -	int result; - -	/* default to invalid packet */ -	*is_valid = 0;  	modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0); @@ -50,39 +45,30 @@ static int pkcs_1_v1_5_decode_emsa(const unsigned char *msg,  		return -EINVAL;  	/* separate encoded message */ -	if ((msg[0] != 0x00) || (msg[1] != (unsigned char)1)) { -		result = -EINVAL; -		goto bail; -	} +	if ((msg[0] != 0x00) || (msg[1] != (unsigned char)1)) +		return -EINVAL;  	for (i = 2; i < modulus_len - 1; i++)  		if (msg[i] != 0xFF)  			break;  	/* separator check */ -	if (msg[i] != 0) { +	if (msg[i] != 0)  		/* There was no octet with hexadecimal value 0x00  		to separate ps from m. */ -		result = -EINVAL; -		goto bail; -	} +		return -EINVAL;  	ps_len = i - 2;  	if (*outlen < (msglen - (2 + ps_len + 1))) {  		*outlen = msglen - (2 + ps_len + 1); -		result = -EOVERFLOW; -		goto bail; +		return -EOVERFLOW;  	}  	*outlen = (msglen - (2 + ps_len + 1));  	memcpy(out, &msg[2 + ps_len + 1], *outlen); -	/* valid packet */ -	*is_valid = 1; -	result    = 0; -bail: -	return result; +	return 0;  }  /* @@ -96,7 +82,7 @@ static int digsig_verify_rsa(struct key *key,  	unsigned long len;  	unsigned long mlen, mblen;  	unsigned nret, l; -	int valid, head, i; +	int head, i;  	unsigned char *out1 = NULL, *out2 = NULL;  	MPI in = NULL, res = NULL, pkey[2];  	uint8_t *p, *datap, *endp; @@ -105,6 +91,10 @@ static int digsig_verify_rsa(struct key *key,  	down_read(&key->sem);  	ukp = key->payload.data; + +	if (ukp->datalen < sizeof(*pkh)) +		goto err1; +  	pkh = (struct pubkey_hdr *)ukp->data;  	if (pkh->version != 1) @@ -117,18 +107,23 @@ static int digsig_verify_rsa(struct key *key,  		goto err1;  	datap = pkh->mpi; -	endp = datap + ukp->datalen; +	endp = ukp->data + ukp->datalen; + +	err = -ENOMEM;  	for (i = 0; i < pkh->nmpi; i++) {  		unsigned int remaining = endp - datap;  		pkey[i] = mpi_read_from_buffer(datap, &remaining); +		if (!pkey[i]) +			goto err;  		datap += remaining;  	}  	mblen = mpi_get_nbits(pkey[0]);  	mlen = (mblen + 7)/8; -	err = -ENOMEM; +	if (mlen == 0) +		goto err;  	out1 = kzalloc(mlen, GFP_KERNEL);  	if (!out1) @@ -167,10 +162,9 @@ static int digsig_verify_rsa(struct key *key,  	memset(out1, 0, head);  	memcpy(out1 + head, p, l); -	err = -EINVAL; -	pkcs_1_v1_5_decode_emsa(out1, len, mblen, out2, &len, &valid); +	err = pkcs_1_v1_5_decode_emsa(out1, len, mblen, out2, &len); -	if (valid && len == hlen) +	if (!err && len == hlen)  		err = memcmp(out2, h, hlen);  err: @@ -178,8 +172,8 @@ err:  	mpi_free(res);  	kfree(out1);  	kfree(out2); -	mpi_free(pkey[0]); -	mpi_free(pkey[1]); +	while (--i >= 0) +		mpi_free(pkey[i]);  err1:  	up_read(&key->sem); diff --git a/lib/kstrtox.c b/lib/kstrtox.c index 7a94c8f14e2..b1dd3e7d88c 100644 --- a/lib/kstrtox.c +++ b/lib/kstrtox.c @@ -44,12 +44,13 @@ const char *_parse_integer_fixup_radix(const char *s, unsigned int *base)   *   * Don't you dare use this function.   */ -unsigned int _parse_integer(const char *s, unsigned int base, unsigned long long *res) +unsigned int _parse_integer(const char *s, unsigned int base, unsigned long long *p)  { +	unsigned long long res;  	unsigned int rv;  	int overflow; -	*res = 0; +	res = 0;  	rv = 0;  	overflow = 0;  	while (*s) { @@ -64,12 +65,19 @@ unsigned int _parse_integer(const char *s, unsigned int base, unsigned long long  		if (val >= base)  			break; -		if (*res > div_u64(ULLONG_MAX - val, base)) -			overflow = 1; -		*res = *res * base + val; +		/* +		 * Check for overflow only if we are within range of +		 * it in the max base we support (16) +		 */ +		if (unlikely(res & (~0ull << 60))) { +			if (res > div_u64(ULLONG_MAX - val, base)) +				overflow = 1; +		} +		res = res * base + val;  		rv++;  		s++;  	} +	*p = res;  	if (overflow)  		rv |= KSTRTOX_OVERFLOW;  	return rv; diff --git a/lib/mpi/longlong.h b/lib/mpi/longlong.h index b87487b40a8..29f98624ef9 100644 --- a/lib/mpi/longlong.h +++ b/lib/mpi/longlong.h @@ -1200,18 +1200,40 @@ do { \  	"r" ((USItype)(v)) \  	: "%g1", "%g2" __AND_CLOBBER_CC)  #define UMUL_TIME 39		/* 39 instructions */ -#endif -#ifndef udiv_qrnnd -#ifndef LONGLONG_STANDALONE +/* It's quite necessary to add this much assembler for the sparc. +   The default udiv_qrnnd (in C) is more than 10 times slower!  */  #define udiv_qrnnd(q, r, n1, n0, d) \ -do { USItype __r; \ -	(q) = __udiv_qrnnd(&__r, (n1), (n0), (d)); \ -	(r) = __r; \ -} while (0) -	extern USItype __udiv_qrnnd(); -#define UDIV_TIME 140 -#endif /* LONGLONG_STANDALONE */ -#endif /* udiv_qrnnd */ +  __asm__ ("! Inlined udiv_qrnnd\n\t"					\ +	   "mov	32,%%g1\n\t"						\ +	   "subcc	%1,%2,%%g0\n\t"					\ +	   "1:	bcs	5f\n\t"						\ +	   "addxcc %0,%0,%0	! shift n1n0 and a q-bit in lsb\n\t"	\ +	   "sub	%1,%2,%1	! this kills msb of n\n\t"		\ +	   "addx	%1,%1,%1	! so this can't give carry\n\t"	\ +	   "subcc	%%g1,1,%%g1\n\t"				\ +	   "2:	bne	1b\n\t"						\ +	   "subcc	%1,%2,%%g0\n\t"					\ +	   "bcs	3f\n\t"							\ +	   "addxcc %0,%0,%0	! shift n1n0 and a q-bit in lsb\n\t"	\ +	   "b		3f\n\t"						\ +	   "sub	%1,%2,%1	! this kills msb of n\n\t"		\ +	   "4:	sub	%1,%2,%1\n\t"					\ +	   "5:	addxcc	%1,%1,%1\n\t"					\ +	   "bcc	2b\n\t"							\ +	   "subcc	%%g1,1,%%g1\n\t"				\ +	   "! Got carry from n.  Subtract next step to cancel this carry.\n\t" \ +	   "bne	4b\n\t"							\ +	   "addcc	%0,%0,%0	! shift n1n0 and a 0-bit in lsb\n\t" \ +	   "sub	%1,%2,%1\n\t"						\ +	   "3:	xnor	%0,0,%0\n\t"					\ +	   "! End of inline udiv_qrnnd\n"				\ +	   : "=&r" ((USItype)(q)),					\ +	     "=&r" ((USItype)(r))					\ +	   : "r" ((USItype)(d)),					\ +	     "1" ((USItype)(n1)),					\ +	     "0" ((USItype)(n0)) : "%g1", "cc") +#define UDIV_TIME (3+7*32)      /* 7 instructions/iteration. 32 iterations.  */ +#endif  #endif /* __sparc__ */  /*************************************** diff --git a/lib/mpi/mpi-bit.c b/lib/mpi/mpi-bit.c index 854c9c6da02..2f526627e4f 100644 --- a/lib/mpi/mpi-bit.c +++ b/lib/mpi/mpi-bit.c @@ -21,25 +21,6 @@  #include "mpi-internal.h"  #include "longlong.h" -const unsigned char __clz_tab[] = { -	0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, -	    5, 5, 5, 5, 5, 5, 5, 5, -	6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, -	    6, 6, 6, 6, 6, 6, 6, 6, -	7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, -	    7, 7, 7, 7, 7, 7, 7, 7, -	7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, -	    7, 7, 7, 7, 7, 7, 7, 7, -	8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, -	    8, 8, 8, 8, 8, 8, 8, 8, -	8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, -	    8, 8, 8, 8, 8, 8, 8, 8, -	8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, -	    8, 8, 8, 8, 8, 8, 8, 8, -	8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, -	    8, 8, 8, 8, 8, 8, 8, 8, -}; -  #define A_LIMB_1 ((mpi_limb_t) 1)  /**************** diff --git a/lib/mpi/mpi-div.c b/lib/mpi/mpi-div.c index c3087d1390c..f68cbbb4d4a 100644 --- a/lib/mpi/mpi-div.c +++ b/lib/mpi/mpi-div.c @@ -149,6 +149,9 @@ int mpi_tdiv_qr(MPI quot, MPI rem, MPI num, MPI den)  	mpi_ptr_t marker[5];  	int markidx = 0; +	if (!dsize) +		return -EINVAL; +  	memset(marker, 0, sizeof(marker));  	/* Ensure space is enough for quotient and remainder. @@ -207,6 +210,8 @@ int mpi_tdiv_qr(MPI quot, MPI rem, MPI num, MPI den)  		 * numerator would be gradually overwritten by the quotient limbs.  */  		if (qp == np) {	/* Copy NP object to temporary space.  */  			np = marker[markidx++] = mpi_alloc_limb_space(nsize); +			if (!np) +				goto nomem;  			MPN_COPY(np, qp, nsize);  		}  	} else			/* Put quotient at top of remainder. */ diff --git a/lib/mpi/mpi-pow.c b/lib/mpi/mpi-pow.c index b04a3cf8008..67f3e79af91 100644 --- a/lib/mpi/mpi-pow.c +++ b/lib/mpi/mpi-pow.c @@ -59,7 +59,7 @@ int mpi_powm(MPI res, MPI base, MPI exp, MPI mod)  	ep = exp->d;  	if (!msize) -		msize = 1 / msize;	/* provoke a signal */ +		return -EINVAL;  	if (!esize) {  		/* Exponent is zero, result is 1 mod MOD, i.e., 1 or 0 diff --git a/lib/mpi/mpicoder.c b/lib/mpi/mpicoder.c index 716802b774e..f26b41fcb48 100644 --- a/lib/mpi/mpicoder.c +++ b/lib/mpi/mpicoder.c @@ -20,78 +20,15 @@  #include "mpi-internal.h" -#define DIM(v) (sizeof(v)/sizeof((v)[0]))  #define MAX_EXTERN_MPI_BITS 16384 -static uint8_t asn[15] =	/* Object ID is 1.3.14.3.2.26 */ -{ 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, -	0x02, 0x1a, 0x05, 0x00, 0x04, 0x14 -}; - -MPI do_encode_md(const void *sha_buffer, unsigned nbits) -{ -	int nframe = (nbits + 7) / 8; -	uint8_t *frame, *fr_pt; -	int i = 0, n; -	size_t asnlen = DIM(asn); -	MPI a = MPI_NULL; - -	if (SHA1_DIGEST_LENGTH + asnlen + 4 > nframe) -		pr_info("MPI: can't encode a %d bit MD into a %d bits frame\n", -		       (int)(SHA1_DIGEST_LENGTH * 8), (int)nbits); - -	/* We encode the MD in this way: -	 * -	 *       0  A PAD(n bytes)   0  ASN(asnlen bytes)  MD(len bytes) -	 * -	 * PAD consists of FF bytes. -	 */ -	frame = kmalloc(nframe, GFP_KERNEL); -	if (!frame) -		return MPI_NULL; -	n = 0; -	frame[n++] = 0; -	frame[n++] = 1;		/* block type */ -	i = nframe - SHA1_DIGEST_LENGTH - asnlen - 3; - -	if (i <= 1) { -		pr_info("MPI: message digest encoding failed\n"); -		kfree(frame); -		return a; -	} - -	memset(frame + n, 0xff, i); -	n += i; -	frame[n++] = 0; -	memcpy(frame + n, &asn, asnlen); -	n += asnlen; -	memcpy(frame + n, sha_buffer, SHA1_DIGEST_LENGTH); -	n += SHA1_DIGEST_LENGTH; - -	i = nframe; -	fr_pt = frame; - -	if (n != nframe) { -		printk -		    ("MPI: message digest encoding failed, frame length is wrong\n"); -		kfree(frame); -		return a; -	} - -	a = mpi_alloc((nframe + BYTES_PER_MPI_LIMB - 1) / BYTES_PER_MPI_LIMB); -	mpi_set_buffer(a, frame, nframe, 0); -	kfree(frame); - -	return a; -} -  MPI mpi_read_from_buffer(const void *xbuffer, unsigned *ret_nread)  {  	const uint8_t *buffer = xbuffer;  	int i, j;  	unsigned nbits, nbytes, nlimbs, nread = 0;  	mpi_limb_t a; -	MPI val = MPI_NULL; +	MPI val = NULL;  	if (*ret_nread < 2)  		goto leave; @@ -108,7 +45,7 @@ MPI mpi_read_from_buffer(const void *xbuffer, unsigned *ret_nread)  	nlimbs = (nbytes + BYTES_PER_MPI_LIMB - 1) / BYTES_PER_MPI_LIMB;  	val = mpi_alloc(nlimbs);  	if (!val) -		return MPI_NULL; +		return NULL;  	i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB;  	i %= BYTES_PER_MPI_LIMB;  	val->nbits = nbits; @@ -212,30 +149,6 @@ int mpi_fromstr(MPI val, const char *str)  EXPORT_SYMBOL_GPL(mpi_fromstr);  /**************** - * Special function to get the low 8 bytes from an mpi. - * This can be used as a keyid; KEYID is an 2 element array. - * Return the low 4 bytes. - */ -u32 mpi_get_keyid(const MPI a, u32 *keyid) -{ -#if BYTES_PER_MPI_LIMB == 4 -	if (keyid) { -		keyid[0] = a->nlimbs >= 2 ? a->d[1] : 0; -		keyid[1] = a->nlimbs >= 1 ? a->d[0] : 0; -	} -	return a->nlimbs >= 1 ? a->d[0] : 0; -#elif BYTES_PER_MPI_LIMB == 8 -	if (keyid) { -		keyid[0] = a->nlimbs ? (u32) (a->d[0] >> 32) : 0; -		keyid[1] = a->nlimbs ? (u32) (a->d[0] & 0xffffffff) : 0; -	} -	return a->nlimbs ? (u32) (a->d[0] & 0xffffffff) : 0; -#else -#error Make this function work with other LIMB sizes -#endif -} - -/****************   * Return an allocated buffer with the MPI (msb first).   * NBYTES receives the length of this buffer. Caller must free the   * return string (This function does return a 0 byte buffer with NBYTES diff --git a/lib/mpi/mpih-div.c b/lib/mpi/mpih-div.c index 87ede162dfa..cde1aaec18d 100644 --- a/lib/mpi/mpih-div.c +++ b/lib/mpi/mpih-div.c @@ -217,6 +217,10 @@ mpihelp_divrem(mpi_ptr_t qp, mpi_size_t qextra_limbs,  	case 0:  		/* We are asked to divide by zero, so go ahead and do it!  (To make  		   the compiler not remove this statement, return the value.)  */ +		/* +		 * existing clients of this function have been modified +		 * not to call it with dsize == 0, so this should not happen +		 */  		return 1 / dsize;  	case 1: diff --git a/lib/mpi/mpiutil.c b/lib/mpi/mpiutil.c index eefc55d6b7f..26e4ed31e25 100644 --- a/lib/mpi/mpiutil.c +++ b/lib/mpi/mpiutil.c @@ -58,6 +58,9 @@ mpi_ptr_t mpi_alloc_limb_space(unsigned nlimbs)  {  	size_t len = nlimbs * sizeof(mpi_limb_t); +	if (!len) +		return NULL; +  	return kmalloc(len, GFP_KERNEL);  } @@ -135,7 +138,7 @@ int mpi_copy(MPI *copied, const MPI a)  	size_t i;  	MPI b; -	*copied = MPI_NULL; +	*copied = NULL;  	if (a) {  		b = mpi_alloc(a->nlimbs); diff --git a/lib/pci_iomap.c b/lib/pci_iomap.c index 4b0fdc22e68..0d83ea8a960 100644 --- a/lib/pci_iomap.c +++ b/lib/pci_iomap.c @@ -34,7 +34,7 @@ void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)  	if (maxlen && len > maxlen)  		len = maxlen;  	if (flags & IORESOURCE_IO) -		return ioport_map(start, len); +		return __pci_ioport_map(dev, start, len);  	if (flags & IORESOURCE_MEM) {  		if (flags & IORESOURCE_CACHEABLE)  			return ioremap(start, len); diff --git a/mm/backing-dev.c b/mm/backing-dev.c index 7ba8feae11b..dd8e2aafb07 100644 --- a/mm/backing-dev.c +++ b/mm/backing-dev.c @@ -318,7 +318,7 @@ static void wakeup_timer_fn(unsigned long data)  	if (bdi->wb.task) {  		trace_writeback_wake_thread(bdi);  		wake_up_process(bdi->wb.task); -	} else { +	} else if (bdi->dev) {  		/*  		 * When bdi tasks are inactive for long time, they are killed.  		 * In this case we have to wake-up the forker thread which @@ -584,6 +584,8 @@ EXPORT_SYMBOL(bdi_register_dev);   */  static void bdi_wb_shutdown(struct backing_dev_info *bdi)  { +	struct task_struct *task; +  	if (!bdi_cap_writeback_dirty(bdi))  		return; @@ -602,8 +604,13 @@ static void bdi_wb_shutdown(struct backing_dev_info *bdi)  	 * Finally, kill the kernel thread. We don't need to be RCU  	 * safe anymore, since the bdi is gone from visibility.  	 */ -	if (bdi->wb.task) -		kthread_stop(bdi->wb.task); +	spin_lock_bh(&bdi->wb_lock); +	task = bdi->wb.task; +	bdi->wb.task = NULL; +	spin_unlock_bh(&bdi->wb_lock); + +	if (task) +		kthread_stop(task);  }  /* @@ -623,7 +630,9 @@ static void bdi_prune_sb(struct backing_dev_info *bdi)  void bdi_unregister(struct backing_dev_info *bdi)  { -	if (bdi->dev) { +	struct device *dev = bdi->dev; + +	if (dev) {  		bdi_set_min_ratio(bdi, 0);  		trace_writeback_bdi_unregister(bdi);  		bdi_prune_sb(bdi); @@ -632,8 +641,12 @@ void bdi_unregister(struct backing_dev_info *bdi)  		if (!bdi_cap_flush_forker(bdi))  			bdi_wb_shutdown(bdi);  		bdi_debug_unregister(bdi); -		device_unregister(bdi->dev); + +		spin_lock_bh(&bdi->wb_lock);  		bdi->dev = NULL; +		spin_unlock_bh(&bdi->wb_lock); + +		device_unregister(dev);  	}  }  EXPORT_SYMBOL(bdi_unregister); diff --git a/mm/compaction.c b/mm/compaction.c index 71a58f67f48..d9ebebe1a2a 100644 --- a/mm/compaction.c +++ b/mm/compaction.c @@ -313,12 +313,34 @@ static isolate_migrate_t isolate_migratepages(struct zone *zone,  		} else if (!locked)  			spin_lock_irq(&zone->lru_lock); +		/* +		 * migrate_pfn does not necessarily start aligned to a +		 * pageblock. Ensure that pfn_valid is called when moving +		 * into a new MAX_ORDER_NR_PAGES range in case of large +		 * memory holes within the zone +		 */ +		if ((low_pfn & (MAX_ORDER_NR_PAGES - 1)) == 0) { +			if (!pfn_valid(low_pfn)) { +				low_pfn += MAX_ORDER_NR_PAGES - 1; +				continue; +			} +		} +  		if (!pfn_valid_within(low_pfn))  			continue;  		nr_scanned++; -		/* Get the page and skip if free */ +		/* +		 * Get the page and ensure the page is within the same zone. +		 * See the comment in isolate_freepages about overlapping +		 * nodes. It is deliberate that the new zone lock is not taken +		 * as memory compaction should not move pages between nodes. +		 */  		page = pfn_to_page(low_pfn); +		if (page_zone(page) != zone) +			continue; + +		/* Skip if free */  		if (PageBuddy(page))  			continue; diff --git a/mm/filemap.c b/mm/filemap.c index 97f49ed35bd..b66275757c2 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -1400,15 +1400,12 @@ generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov,  	unsigned long seg = 0;  	size_t count;  	loff_t *ppos = &iocb->ki_pos; -	struct blk_plug plug;  	count = 0;  	retval = generic_segment_checks(iov, &nr_segs, &count, VERIFY_WRITE);  	if (retval)  		return retval; -	blk_start_plug(&plug); -  	/* coalesce the iovecs and go direct-to-BIO for O_DIRECT */  	if (filp->f_flags & O_DIRECT) {  		loff_t size; @@ -1424,8 +1421,12 @@ generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov,  			retval = filemap_write_and_wait_range(mapping, pos,  					pos + iov_length(iov, nr_segs) - 1);  			if (!retval) { +				struct blk_plug plug; + +				blk_start_plug(&plug);  				retval = mapping->a_ops->direct_IO(READ, iocb,  							iov, pos, nr_segs); +				blk_finish_plug(&plug);  			}  			if (retval > 0) {  				*ppos = pos + retval; @@ -1481,7 +1482,6 @@ generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov,  			break;  	}  out: -	blk_finish_plug(&plug);  	return retval;  }  EXPORT_SYMBOL(generic_file_aio_read); diff --git a/mm/filemap_xip.c b/mm/filemap_xip.c index f91b2f68734..a4eb3113222 100644 --- a/mm/filemap_xip.c +++ b/mm/filemap_xip.c @@ -263,7 +263,12 @@ found:  							xip_pfn);  		if (err == -ENOMEM)  			return VM_FAULT_OOM; -		BUG_ON(err); +		/* +		 * err == -EBUSY is fine, we've raced against another thread +		 * that faulted-in the same page +		 */ +		if (err != -EBUSY) +			BUG_ON(err);  		return VM_FAULT_NOPAGE;  	} else {  		int err, ret = VM_FAULT_OOM; diff --git a/mm/huge_memory.c b/mm/huge_memory.c index b3ffc21ce80..91d3efb25d1 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -2083,7 +2083,7 @@ static void collect_mm_slot(struct mm_slot *mm_slot)  {  	struct mm_struct *mm = mm_slot->mm; -	VM_BUG_ON(!spin_is_locked(&khugepaged_mm_lock)); +	VM_BUG_ON(NR_CPUS != 1 && !spin_is_locked(&khugepaged_mm_lock));  	if (khugepaged_test_exit(mm)) {  		/* free mm_slot */ @@ -2113,7 +2113,7 @@ static unsigned int khugepaged_scan_mm_slot(unsigned int pages,  	int progress = 0;  	VM_BUG_ON(!pages); -	VM_BUG_ON(!spin_is_locked(&khugepaged_mm_lock)); +	VM_BUG_ON(NR_CPUS != 1 && !spin_is_locked(&khugepaged_mm_lock));  	if (khugepaged_scan.mm_slot)  		mm_slot = khugepaged_scan.mm_slot; diff --git a/mm/kmemleak.c b/mm/kmemleak.c index c833addd94d..45eb6217bf3 100644 --- a/mm/kmemleak.c +++ b/mm/kmemleak.c @@ -1036,7 +1036,7 @@ void __ref kmemleak_scan_area(const void *ptr, size_t size, gfp_t gfp)  {  	pr_debug("%s(0x%p)\n", __func__, ptr); -	if (atomic_read(&kmemleak_enabled) && ptr && !IS_ERR(ptr)) +	if (atomic_read(&kmemleak_enabled) && ptr && size && !IS_ERR(ptr))  		add_scan_area((unsigned long)ptr, size, gfp);  	else if (atomic_read(&kmemleak_early_log))  		log_early(KMEMLEAK_SCAN_AREA, ptr, size, 0); @@ -1757,6 +1757,7 @@ void __init kmemleak_init(void)  #ifdef CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF  	if (!kmemleak_skip_disable) { +		atomic_set(&kmemleak_early_log, 0);  		kmemleak_disable();  		return;  	} diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 556859fec4e..6728a7ae6f2 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -776,7 +776,8 @@ static void memcg_check_events(struct mem_cgroup *memcg, struct page *page)  	/* threshold event is triggered in finer grain than soft limit */  	if (unlikely(mem_cgroup_event_ratelimit(memcg,  						MEM_CGROUP_TARGET_THRESH))) { -		bool do_softlimit, do_numainfo; +		bool do_softlimit; +		bool do_numainfo __maybe_unused;  		do_softlimit = mem_cgroup_event_ratelimit(memcg,  						MEM_CGROUP_TARGET_SOFTLIMIT); diff --git a/mm/migrate.c b/mm/migrate.c index 9871a56d82c..df141f60289 100644 --- a/mm/migrate.c +++ b/mm/migrate.c @@ -445,7 +445,6 @@ void migrate_page_copy(struct page *newpage, struct page *page)  	ClearPageSwapCache(page);  	ClearPagePrivate(page);  	set_page_private(page, 0); -	page->mapping = NULL;  	/*  	 * If any waiters have accumulated on the new page then @@ -667,6 +666,7 @@ static int move_to_new_page(struct page *newpage, struct page *page,  	} else {  		if (remap_swapcache)  			remove_migration_ptes(page, newpage); +		page->mapping = NULL;  	}  	unlock_page(newpage); diff --git a/mm/process_vm_access.c b/mm/process_vm_access.c index e920aa3ce10..c20ff48994c 100644 --- a/mm/process_vm_access.c +++ b/mm/process_vm_access.c @@ -298,23 +298,18 @@ static ssize_t process_vm_rw_core(pid_t pid, const struct iovec *lvec,  		goto free_proc_pages;  	} -	task_lock(task); -	if (__ptrace_may_access(task, PTRACE_MODE_ATTACH)) { -		task_unlock(task); -		rc = -EPERM; -		goto put_task_struct; -	} -	mm = task->mm; - -	if (!mm || (task->flags & PF_KTHREAD)) { -		task_unlock(task); -		rc = -EINVAL; +	mm = mm_access(task, PTRACE_MODE_ATTACH); +	if (!mm || IS_ERR(mm)) { +		rc = IS_ERR(mm) ? PTR_ERR(mm) : -ESRCH; +		/* +		 * Explicitly map EACCES to EPERM as EPERM is a more a +		 * appropriate error code for process_vw_readv/writev +		 */ +		if (rc == -EACCES) +			rc = -EPERM;  		goto put_task_struct;  	} -	atomic_inc(&mm->mm_users); -	task_unlock(task); -  	for (i = 0; i < riovcnt && iov_l_curr_idx < liovcnt; i++) {  		rc = process_vm_rw_single_vec(  			(unsigned long)rvec[i].iov_base, rvec[i].iov_len, diff --git a/mm/swap.c b/mm/swap.c index b0f529b3897..fff1ff7fb9a 100644 --- a/mm/swap.c +++ b/mm/swap.c @@ -659,7 +659,7 @@ void lru_add_page_tail(struct zone* zone,  	VM_BUG_ON(!PageHead(page));  	VM_BUG_ON(PageCompound(page_tail));  	VM_BUG_ON(PageLRU(page_tail)); -	VM_BUG_ON(!spin_is_locked(&zone->lru_lock)); +	VM_BUG_ON(NR_CPUS != 1 && !spin_is_locked(&zone->lru_lock));  	SetPageLRU(page_tail); diff --git a/net/caif/caif_socket.c b/net/caif/caif_socket.c index a9862808645..a97d97a3a51 100644 --- a/net/caif/caif_socket.c +++ b/net/caif/caif_socket.c @@ -539,8 +539,10 @@ static int transmit_skb(struct sk_buff *skb, struct caifsock *cf_sk,  	pkt = cfpkt_fromnative(CAIF_DIR_OUT, skb);  	memset(skb->cb, 0, sizeof(struct caif_payload_info)); -	if (cf_sk->layer.dn == NULL) +	if (cf_sk->layer.dn == NULL) { +		kfree_skb(skb);  		return -EINVAL; +	}  	return cf_sk->layer.dn->transmit(cf_sk->layer.dn, pkt);  } @@ -683,10 +685,10 @@ static int caif_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,  		}  		err = transmit_skb(skb, cf_sk,  				msg->msg_flags&MSG_DONTWAIT, timeo); -		if (err < 0) { -			kfree_skb(skb); +		if (err < 0) +			/* skb is already freed */  			goto pipe_err; -		} +  		sent += size;  	} diff --git a/net/caif/cfmuxl.c b/net/caif/cfmuxl.c index b36f24a4c8e..94b08612a4d 100644 --- a/net/caif/cfmuxl.c +++ b/net/caif/cfmuxl.c @@ -248,7 +248,6 @@ static void cfmuxl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl,  {  	struct cfmuxl *muxl = container_obj(layr);  	struct cflayer *layer; -	int idx;  	rcu_read_lock();  	list_for_each_entry_rcu(layer, &muxl->srvl_list, node) { @@ -257,14 +256,9 @@ static void cfmuxl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl,  			if ((ctrl == _CAIF_CTRLCMD_PHYIF_DOWN_IND ||  				ctrl == CAIF_CTRLCMD_REMOTE_SHUTDOWN_IND) && -					layer->id != 0) { +					layer->id != 0) +				cfmuxl_remove_uplayer(layr, layer->id); -				idx = layer->id % UP_CACHE_SIZE; -				spin_lock_bh(&muxl->receive_lock); -				RCU_INIT_POINTER(muxl->up_cache[idx], NULL); -				list_del_rcu(&layer->node); -				spin_unlock_bh(&muxl->receive_lock); -			}  			/* NOTE: ctrlcmd is not allowed to block */  			layer->ctrlcmd(layer, ctrl, phyid);  		} diff --git a/net/ceph/ceph_common.c b/net/ceph/ceph_common.c index 97f70e50ad3..761ad9d6cc3 100644 --- a/net/ceph/ceph_common.c +++ b/net/ceph/ceph_common.c @@ -85,8 +85,6 @@ int ceph_check_fsid(struct ceph_client *client, struct ceph_fsid *fsid)  	} else {  		pr_info("client%lld fsid %pU\n", ceph_client_id(client), fsid);  		memcpy(&client->fsid, fsid, sizeof(*fsid)); -		ceph_debugfs_client_init(client); -		client->have_fsid = true;  	}  	return 0;  } diff --git a/net/ceph/mon_client.c b/net/ceph/mon_client.c index 0b62deae42b..1845cde2622 100644 --- a/net/ceph/mon_client.c +++ b/net/ceph/mon_client.c @@ -8,8 +8,8 @@  #include <linux/ceph/mon_client.h>  #include <linux/ceph/libceph.h> +#include <linux/ceph/debugfs.h>  #include <linux/ceph/decode.h> -  #include <linux/ceph/auth.h>  /* @@ -340,8 +340,19 @@ static void ceph_monc_handle_map(struct ceph_mon_client *monc,  	client->monc.monmap = monmap;  	kfree(old); +	if (!client->have_fsid) { +		client->have_fsid = true; +		mutex_unlock(&monc->mutex); +		/* +		 * do debugfs initialization without mutex to avoid +		 * creating a locking dependency +		 */ +		ceph_debugfs_client_init(client); +		goto out_unlocked; +	}  out:  	mutex_unlock(&monc->mutex); +out_unlocked:  	wake_up_all(&client->auth_wq);  } diff --git a/net/core/dev.c b/net/core/dev.c index 115dee1d985..6ca32f6b310 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -3500,14 +3500,20 @@ static inline gro_result_t  __napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb)  {  	struct sk_buff *p; +	unsigned int maclen = skb->dev->hard_header_len;  	for (p = napi->gro_list; p; p = p->next) {  		unsigned long diffs;  		diffs = (unsigned long)p->dev ^ (unsigned long)skb->dev;  		diffs |= p->vlan_tci ^ skb->vlan_tci; -		diffs |= compare_ether_header(skb_mac_header(p), -					      skb_gro_mac_header(skb)); +		if (maclen == ETH_HLEN) +			diffs |= compare_ether_header(skb_mac_header(p), +						      skb_gro_mac_header(skb)); +		else if (!diffs) +			diffs = memcmp(skb_mac_header(p), +				       skb_gro_mac_header(skb), +				       maclen);  		NAPI_GRO_CB(p)->same_flow = !diffs;  		NAPI_GRO_CB(p)->flush = 0;  	} diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 369b4189452..3f79db1b612 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c @@ -1190,6 +1190,8 @@ static noinline_for_stack int ethtool_flash_device(struct net_device *dev,  	if (!dev->ethtool_ops->flash_device)  		return -EOPNOTSUPP; +	efl.data[ETHTOOL_FLASH_MAX_FILENAME - 1] = 0; +  	return dev->ethtool_ops->flash_device(dev, &efl);  } diff --git a/net/core/netprio_cgroup.c b/net/core/netprio_cgroup.c index 3a9fd4826b7..4dacc44637e 100644 --- a/net/core/netprio_cgroup.c +++ b/net/core/netprio_cgroup.c @@ -58,11 +58,12 @@ static int get_prioidx(u32 *prio)  	spin_lock_irqsave(&prioidx_map_lock, flags);  	prioidx = find_first_zero_bit(prioidx_map, sizeof(unsigned long) * PRIOIDX_SZ); +	if (prioidx == sizeof(unsigned long) * PRIOIDX_SZ) { +		spin_unlock_irqrestore(&prioidx_map_lock, flags); +		return -ENOSPC; +	}  	set_bit(prioidx, prioidx_map);  	spin_unlock_irqrestore(&prioidx_map_lock, flags); -	if (prioidx == sizeof(unsigned long) * PRIOIDX_SZ) -		return -ENOSPC; -  	atomic_set(&max_prioidx, prioidx);  	*prio = prioidx;  	return 0; @@ -107,7 +108,7 @@ static void extend_netdev_table(struct net_device *dev, u32 new_len)  static void update_netdev_tables(void)  {  	struct net_device *dev; -	u32 max_len = atomic_read(&max_prioidx); +	u32 max_len = atomic_read(&max_prioidx) + 1;  	struct netprio_map *map;  	rtnl_lock(); @@ -270,7 +271,6 @@ static int netprio_device_event(struct notifier_block *unused,  {  	struct net_device *dev = ptr;  	struct netprio_map *old; -	u32 max_len = atomic_read(&max_prioidx);  	/*  	 * Note this is called with rtnl_lock held so we have update side @@ -278,11 +278,6 @@ static int netprio_device_event(struct notifier_block *unused,  	 */  	switch (event) { - -	case NETDEV_REGISTER: -		if (max_len) -			extend_netdev_table(dev, max_len); -		break;  	case NETDEV_UNREGISTER:  		old = rtnl_dereference(dev->priomap);  		RCU_INIT_POINTER(dev->priomap, NULL); diff --git a/net/core/sock.c b/net/core/sock.c index 3e81fd2e3c7..02f8dfe320b 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -1171,13 +1171,10 @@ EXPORT_SYMBOL(sock_update_classid);  void sock_update_netprioidx(struct sock *sk)  { -	struct cgroup_netprio_state *state;  	if (in_interrupt())  		return; -	rcu_read_lock(); -	state = task_netprio_state(current); -	sk->sk_cgrp_prioidx = state ? state->prioidx : 0; -	rcu_read_unlock(); + +	sk->sk_cgrp_prioidx = task_netprioidx(current);  }  EXPORT_SYMBOL_GPL(sock_update_netprioidx);  #endif diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig index aa2a2c79776..d183262943d 100644 --- a/net/ipv4/Kconfig +++ b/net/ipv4/Kconfig @@ -409,7 +409,7 @@ config INET_TCP_DIAG  config INET_UDP_DIAG  	tristate "UDP: socket monitoring interface" -	depends on INET_DIAG +	depends on INET_DIAG && (IPV6 || IPV6=n)  	default n  	---help---  	  Support for UDP socket monitoring interface used by the ss tool. diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index 59402be133f..63e49890ad3 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c @@ -863,7 +863,8 @@ static int arp_process(struct sk_buff *skb)  			if (addr_type == RTN_UNICAST  &&  			    (arp_fwd_proxy(in_dev, dev, rt) ||  			     arp_fwd_pvlan(in_dev, dev, rt, sip, tip) || -			     pneigh_lookup(&arp_tbl, net, &tip, dev, 0))) { +			     (rt->dst.dev != dev && +			      pneigh_lookup(&arp_tbl, net, &tip, dev, 0)))) {  				n = neigh_event_ns(&arp_tbl, sha, &sip, dev);  				if (n)  					neigh_release(n); diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c index 1e60f767907..42dd1a90ede 100644 --- a/net/ipv4/ip_options.c +++ b/net/ipv4/ip_options.c @@ -573,8 +573,8 @@ void ip_forward_options(struct sk_buff *skb)  		}  		if (srrptr + 3 <= srrspace) {  			opt->is_changed = 1; -			ip_rt_get_source(&optptr[srrptr-1], skb, rt);  			ip_hdr(skb)->daddr = opt->nexthop; +			ip_rt_get_source(&optptr[srrptr-1], skb, rt);  			optptr[2] = srrptr+4;  		} else if (net_ratelimit())  			printk(KERN_CRIT "ip_forward(): Argh! Destination lost!\n"); diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index 4cb9cd2f2c3..7a7724da9bf 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c @@ -778,7 +778,6 @@ EXPORT_SYMBOL_GPL(net_ipv4_ctl_path);  static __net_init int ipv4_sysctl_init_net(struct net *net)  {  	struct ctl_table *table; -	unsigned long limit;  	table = ipv4_net_table;  	if (!net_eq(net, &init_net)) { @@ -815,11 +814,6 @@ static __net_init int ipv4_sysctl_init_net(struct net *net)  	net->ipv4.sysctl_rt_cache_rebuild_count = 4;  	tcp_init_mem(net); -	limit = nr_free_buffer_pages() / 8; -	limit = max(limit, 128UL); -	net->ipv4.sysctl_tcp_mem[0] = limit / 4 * 3; -	net->ipv4.sysctl_tcp_mem[1] = limit; -	net->ipv4.sysctl_tcp_mem[2] = net->ipv4.sysctl_tcp_mem[0] * 2;  	net->ipv4.ipv4_hdr = register_net_sysctl_table(net,  			net_ipv4_ctl_path, table); diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 06373b4a449..37755ccc0e9 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -1876,6 +1876,20 @@ void tcp_shutdown(struct sock *sk, int how)  }  EXPORT_SYMBOL(tcp_shutdown); +bool tcp_check_oom(struct sock *sk, int shift) +{ +	bool too_many_orphans, out_of_socket_memory; + +	too_many_orphans = tcp_too_many_orphans(sk, shift); +	out_of_socket_memory = tcp_out_of_memory(sk); + +	if (too_many_orphans && net_ratelimit()) +		pr_info("TCP: too many orphaned sockets\n"); +	if (out_of_socket_memory && net_ratelimit()) +		pr_info("TCP: out of memory -- consider tuning tcp_mem\n"); +	return too_many_orphans || out_of_socket_memory; +} +  void tcp_close(struct sock *sk, long timeout)  {  	struct sk_buff *skb; @@ -2015,10 +2029,7 @@ adjudge_to_death:  	}  	if (sk->sk_state != TCP_CLOSE) {  		sk_mem_reclaim(sk); -		if (tcp_too_many_orphans(sk, 0)) { -			if (net_ratelimit()) -				printk(KERN_INFO "TCP: too many of orphaned " -				       "sockets\n"); +		if (tcp_check_oom(sk, 0)) {  			tcp_set_state(sk, TCP_CLOSE);  			tcp_send_active_reset(sk, GFP_ATOMIC);  			NET_INC_STATS_BH(sock_net(sk), @@ -3218,7 +3229,6 @@ __setup("thash_entries=", set_thash_entries);  void tcp_init_mem(struct net *net)  { -	/* Set per-socket limits to no more than 1/128 the pressure threshold */  	unsigned long limit = nr_free_buffer_pages() / 8;  	limit = max(limit, 128UL);  	net->ipv4.sysctl_tcp_mem[0] = limit / 4 * 3; @@ -3287,7 +3297,8 @@ void __init tcp_init(void)  	sysctl_max_syn_backlog = max(128, cnt / 256);  	tcp_init_mem(&init_net); -	limit = nr_free_buffer_pages() / 8; +	/* Set per-socket limits to no more than 1/128 the pressure threshold */ +	limit = nr_free_buffer_pages() << (PAGE_SHIFT - 10);  	limit = max(limit, 128UL);  	max_share = min(4UL*1024*1024, limit); diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 337ba4cca05..94d683a61cb 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -651,6 +651,11 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb)  				      arg.iov[0].iov_len, IPPROTO_TCP, 0);  	arg.csumoffset = offsetof(struct tcphdr, check) / 2;  	arg.flags = (sk && inet_sk(sk)->transparent) ? IP_REPLY_ARG_NOSRCCHECK : 0; +	/* When socket is gone, all binding information is lost. +	 * routing might fail in this case. using iif for oif to +	 * make sure we can deliver it +	 */ +	arg.bound_dev_if = sk ? sk->sk_bound_dev_if : inet_iif(skb);  	net = dev_net(skb_dst(skb)->dev);  	arg.tos = ip_hdr(skb)->tos; diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c index a516d1e399d..cd2e0723266 100644 --- a/net/ipv4/tcp_timer.c +++ b/net/ipv4/tcp_timer.c @@ -77,10 +77,7 @@ static int tcp_out_of_resources(struct sock *sk, int do_reset)  	if (sk->sk_err_soft)  		shift++; -	if (tcp_too_many_orphans(sk, shift)) { -		if (net_ratelimit()) -			printk(KERN_INFO "Out of socket memory\n"); - +	if (tcp_check_oom(sk, shift)) {  		/* Catch exceptional cases, when connection requires reset.  		 *      1. Last segment was sent recently. */  		if ((s32)(tcp_time_stamp - tp->lsndtime) <= TCP_TIMEWAIT_LEN || diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 75140912076..5a5e504a8ff 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -611,7 +611,7 @@ static void ieee80211_sta_reorder_release(struct ieee80211_hw *hw,  	index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) %  						tid_agg_rx->buf_size;  	if (!tid_agg_rx->reorder_buf[index] && -	    tid_agg_rx->stored_mpdu_num > 1) { +	    tid_agg_rx->stored_mpdu_num) {  		/*  		 * No buffers ready to be released, but check whether any  		 * frames in the reorder buffer have timed out. diff --git a/net/sched/sch_choke.c b/net/sched/sch_choke.c index e465064d39a..7e267d7b9c7 100644 --- a/net/sched/sch_choke.c +++ b/net/sched/sch_choke.c @@ -148,8 +148,7 @@ struct choke_skb_cb {  static inline struct choke_skb_cb *choke_skb_cb(const struct sk_buff *skb)  { -	BUILD_BUG_ON(sizeof(skb->cb) < -		sizeof(struct qdisc_skb_cb) + sizeof(struct choke_skb_cb)); +	qdisc_cb_private_validate(skb, sizeof(struct choke_skb_cb));  	return (struct choke_skb_cb *)qdisc_skb_cb(skb)->data;  } diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c index 2776012132e..e83d61ca78c 100644 --- a/net/sched/sch_netem.c +++ b/net/sched/sch_netem.c @@ -130,8 +130,7 @@ struct netem_skb_cb {  static inline struct netem_skb_cb *netem_skb_cb(struct sk_buff *skb)  { -	BUILD_BUG_ON(sizeof(skb->cb) < -		sizeof(struct qdisc_skb_cb) + sizeof(struct netem_skb_cb)); +	qdisc_cb_private_validate(skb, sizeof(struct netem_skb_cb));  	return (struct netem_skb_cb *)qdisc_skb_cb(skb)->data;  } diff --git a/net/sched/sch_sfb.c b/net/sched/sch_sfb.c index 96e42cae4c7..d7eea99333e 100644 --- a/net/sched/sch_sfb.c +++ b/net/sched/sch_sfb.c @@ -94,8 +94,7 @@ struct sfb_skb_cb {  static inline struct sfb_skb_cb *sfb_skb_cb(const struct sk_buff *skb)  { -	BUILD_BUG_ON(sizeof(skb->cb) < -		sizeof(struct qdisc_skb_cb) + sizeof(struct sfb_skb_cb)); +	qdisc_cb_private_validate(skb, sizeof(struct sfb_skb_cb));  	return (struct sfb_skb_cb *)qdisc_skb_cb(skb)->data;  } diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c index 67494aef9ac..60d47180f04 100644 --- a/net/sched/sch_sfq.c +++ b/net/sched/sch_sfq.c @@ -166,9 +166,8 @@ struct sfq_skb_cb {  static inline struct sfq_skb_cb *sfq_skb_cb(const struct sk_buff *skb)  { -       BUILD_BUG_ON(sizeof(skb->cb) < -               sizeof(struct qdisc_skb_cb) + sizeof(struct sfq_skb_cb)); -       return (struct sfq_skb_cb *)qdisc_skb_cb(skb)->data; +	qdisc_cb_private_validate(skb, sizeof(struct sfq_skb_cb)); +	return (struct sfq_skb_cb *)qdisc_skb_cb(skb)->data;  }  static unsigned int sfq_hash(const struct sfq_sched_data *q, diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index e3bfcbe8a52..a3b9782441f 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -1924,6 +1924,12 @@ sub process {  			my $pre_ctx = "$1$2";  			my ($level, @ctx) = ctx_statement_level($linenr, $realcnt, 0); + +			if ($line =~ /^\+\t{6,}/) { +				WARN("DEEP_INDENTATION", +				     "Too many leading tabs - consider code refactoring\n" . $herecurr); +			} +  			my $ctx_cnt = $realcnt - $#ctx - 1;  			my $ctx = join("\n", @ctx); diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c index e8c96957776..d0de2a2c3a2 100644 --- a/scripts/mod/file2alias.c +++ b/scripts/mod/file2alias.c @@ -932,7 +932,7 @@ static int do_isapnp_entry(const char *filename,  		(id->function >> 12) & 0x0f, (id->function >> 8) & 0x0f);  	return 1;  } -ADD_TO_DEVTABLE("isa", struct isapnp_device_id, do_isapnp_entry); +ADD_TO_DEVTABLE("isapnp", struct isapnp_device_id, do_isapnp_entry);  /*   * Append a match expression for a single masked hex digit. diff --git a/sound/isa/sb/emu8000_patch.c b/sound/isa/sb/emu8000_patch.c index e09f144177f..c99c6078be3 100644 --- a/sound/isa/sb/emu8000_patch.c +++ b/sound/isa/sb/emu8000_patch.c @@ -22,7 +22,6 @@  #include "emu8000_local.h"  #include <asm/uaccess.h>  #include <linux/moduleparam.h> -#include <linux/moduleparam.h>  static int emu8000_reset_addr;  module_param(emu8000_reset_addr, int, 0444); diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 4df72c0e8c3..c2c65f63bf0 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -1447,7 +1447,7 @@ void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid,  		for (i = 0; i < c->cvt_setups.used; i++) {  			p = snd_array_elem(&c->cvt_setups, i);  			if (!p->active && p->stream_tag == stream_tag && -			    get_wcaps_type(get_wcaps(codec, p->nid)) == type) +			    get_wcaps_type(get_wcaps(c, p->nid)) == type)  				p->dirty = 1;  		}  	} diff --git a/sound/pci/hda/hda_jack.c b/sound/pci/hda/hda_jack.c index d8a35da0803..9d819c4b492 100644 --- a/sound/pci/hda/hda_jack.c +++ b/sound/pci/hda/hda_jack.c @@ -282,7 +282,8 @@ int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid,  EXPORT_SYMBOL_HDA(snd_hda_jack_add_kctl);  static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid, -			 const struct auto_pin_cfg *cfg) +			 const struct auto_pin_cfg *cfg, +			 char *lastname, int *lastidx)  {  	unsigned int def_conf, conn;  	char name[44]; @@ -298,6 +299,10 @@ static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid,  		return 0;  	snd_hda_get_pin_label(codec, nid, cfg, name, sizeof(name), &idx); +	if (!strcmp(name, lastname) && idx == *lastidx) +		idx++; +	strncpy(lastname, name, 44); +	*lastidx = idx;  	err = snd_hda_jack_add_kctl(codec, nid, name, idx);  	if (err < 0)  		return err; @@ -311,41 +316,42 @@ int snd_hda_jack_add_kctls(struct hda_codec *codec,  			   const struct auto_pin_cfg *cfg)  {  	const hda_nid_t *p; -	int i, err; +	int i, err, lastidx = 0; +	char lastname[44] = "";  	for (i = 0, p = cfg->line_out_pins; i < cfg->line_outs; i++, p++) { -		err = add_jack_kctl(codec, *p, cfg); +		err = add_jack_kctl(codec, *p, cfg, lastname, &lastidx);  		if (err < 0)  			return err;  	}  	for (i = 0, p = cfg->hp_pins; i < cfg->hp_outs; i++, p++) {  		if (*p == *cfg->line_out_pins) /* might be duplicated */  			break; -		err = add_jack_kctl(codec, *p, cfg); +		err = add_jack_kctl(codec, *p, cfg, lastname, &lastidx);  		if (err < 0)  			return err;  	}  	for (i = 0, p = cfg->speaker_pins; i < cfg->speaker_outs; i++, p++) {  		if (*p == *cfg->line_out_pins) /* might be duplicated */  			break; -		err = add_jack_kctl(codec, *p, cfg); +		err = add_jack_kctl(codec, *p, cfg, lastname, &lastidx);  		if (err < 0)  			return err;  	}  	for (i = 0; i < cfg->num_inputs; i++) { -		err = add_jack_kctl(codec, cfg->inputs[i].pin, cfg); +		err = add_jack_kctl(codec, cfg->inputs[i].pin, cfg, lastname, &lastidx);  		if (err < 0)  			return err;  	}  	for (i = 0, p = cfg->dig_out_pins; i < cfg->dig_outs; i++, p++) { -		err = add_jack_kctl(codec, *p, cfg); +		err = add_jack_kctl(codec, *p, cfg, lastname, &lastidx);  		if (err < 0)  			return err;  	} -	err = add_jack_kctl(codec, cfg->dig_in_pin, cfg); +	err = add_jack_kctl(codec, cfg->dig_in_pin, cfg, lastname, &lastidx);  	if (err < 0)  		return err; -	err = add_jack_kctl(codec, cfg->mono_out_pin, cfg); +	err = add_jack_kctl(codec, cfg->mono_out_pin, cfg, lastname, &lastidx);  	if (err < 0)  		return err;  	return 0; diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index 35abe3c6290..21d91d580da 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c @@ -728,18 +728,19 @@ static int ca0132_hp_switch_put(struct snd_kcontrol *kcontrol,  	err = chipio_read(codec, REG_CODEC_MUTE, &data);  	if (err < 0) -		return err; +		goto exit;  	/* *valp 0 is mute, 1 is unmute */  	data = (data & 0x7f) | (*valp ? 0 : 0x80); -	chipio_write(codec, REG_CODEC_MUTE, data); +	err = chipio_write(codec, REG_CODEC_MUTE, data);  	if (err < 0) -		return err; +		goto exit;  	spec->curr_hp_switch = *valp; + exit:  	snd_hda_power_down(codec); -	return 1; +	return err < 0 ? err : 1;  }  static int ca0132_speaker_switch_get(struct snd_kcontrol *kcontrol, @@ -770,18 +771,19 @@ static int ca0132_speaker_switch_put(struct snd_kcontrol *kcontrol,  	err = chipio_read(codec, REG_CODEC_MUTE, &data);  	if (err < 0) -		return err; +		goto exit;  	/* *valp 0 is mute, 1 is unmute */  	data = (data & 0xef) | (*valp ? 0 : 0x10); -	chipio_write(codec, REG_CODEC_MUTE, data); +	err = chipio_write(codec, REG_CODEC_MUTE, data);  	if (err < 0) -		return err; +		goto exit;  	spec->curr_speaker_switch = *valp; + exit:  	snd_hda_power_down(codec); -	return 1; +	return err < 0 ? err : 1;  }  static int ca0132_hp_volume_get(struct snd_kcontrol *kcontrol, @@ -819,25 +821,26 @@ static int ca0132_hp_volume_put(struct snd_kcontrol *kcontrol,  	err = chipio_read(codec, REG_CODEC_HP_VOL_L, &data);  	if (err < 0) -		return err; +		goto exit;  	val = 31 - left_vol;  	data = (data & 0xe0) | val; -	chipio_write(codec, REG_CODEC_HP_VOL_L, data); +	err = chipio_write(codec, REG_CODEC_HP_VOL_L, data);  	if (err < 0) -		return err; +		goto exit;  	val = 31 - right_vol;  	data = (data & 0xe0) | val; -	chipio_write(codec, REG_CODEC_HP_VOL_R, data); +	err = chipio_write(codec, REG_CODEC_HP_VOL_R, data);  	if (err < 0) -		return err; +		goto exit;  	spec->curr_hp_volume[0] = left_vol;  	spec->curr_hp_volume[1] = right_vol; + exit:  	snd_hda_power_down(codec); -	return 1; +	return err < 0 ? err : 1;  }  static int add_hp_switch(struct hda_codec *codec, hda_nid_t nid) @@ -936,6 +939,8 @@ static int ca0132_build_controls(struct hda_codec *codec)  		if (err < 0)  			return err;  		err = add_in_volume(codec, spec->dig_in, "IEC958"); +		if (err < 0) +			return err;  	}  	return 0;  } diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c index 0e99357e822..bc5a993d114 100644 --- a/sound/pci/hda/patch_cirrus.c +++ b/sound/pci/hda/patch_cirrus.c @@ -988,8 +988,10 @@ static void cs_automic(struct hda_codec *codec)  			change_cur_input(codec, !spec->automic_idx, 0);  	} else {  		if (present) { -			spec->last_input = spec->cur_input; -			spec->cur_input = spec->automic_idx; +			if (spec->cur_input != spec->automic_idx) { +				spec->last_input = spec->cur_input; +				spec->cur_input = spec->automic_idx; +			}  		} else  {  			spec->cur_input = spec->last_input;  		} diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 0db1dc49382..1358987c49d 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -177,6 +177,7 @@ struct alc_spec {  	unsigned int detect_lo:1;	/* Line-out detection enabled */  	unsigned int automute_speaker_possible:1; /* there are speakers and either LO or HP */  	unsigned int automute_lo_possible:1;	  /* there are line outs and HP */ +	unsigned int keep_vref_in_automute:1; /* Don't clear VREF in automute */  	/* other flags */  	unsigned int no_analog :1; /* digital I/O only */ @@ -495,13 +496,24 @@ static void do_automute(struct hda_codec *codec, int num_pins, hda_nid_t *pins,  	for (i = 0; i < num_pins; i++) {  		hda_nid_t nid = pins[i]; +		unsigned int val;  		if (!nid)  			break;  		switch (spec->automute_mode) {  		case ALC_AUTOMUTE_PIN: +			/* don't reset VREF value in case it's controlling +			 * the amp (see alc861_fixup_asus_amp_vref_0f()) +			 */ +			if (spec->keep_vref_in_automute) { +				val = snd_hda_codec_read(codec, nid, 0, +					AC_VERB_GET_PIN_WIDGET_CONTROL, 0); +				val &= ~PIN_HP; +			} else +				val = 0; +			val |= pin_bits;  			snd_hda_codec_write(codec, nid, 0,  					    AC_VERB_SET_PIN_WIDGET_CONTROL, -					    pin_bits); +					    val);  			break;  		case ALC_AUTOMUTE_AMP:  			snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0, @@ -1843,6 +1855,8 @@ static const char * const alc_slave_vols[] = {  	"Speaker Playback Volume",  	"Mono Playback Volume",  	"Line-Out Playback Volume", +	"CLFE Playback Volume", +	"Bass Speaker Playback Volume",  	"PCM Playback Volume",  	NULL,  }; @@ -1858,6 +1872,8 @@ static const char * const alc_slave_sws[] = {  	"Mono Playback Switch",  	"IEC958 Playback Switch",  	"Line-Out Playback Switch", +	"CLFE Playback Switch", +	"Bass Speaker Playback Switch",  	"PCM Playback Switch",  	NULL,  }; @@ -2306,7 +2322,7 @@ static int alc_build_pcms(struct hda_codec *codec)  		 "%s Analog", codec->chip_name);  	info->name = spec->stream_name_analog; -	if (spec->multiout.dac_nids > 0) { +	if (spec->multiout.num_dacs > 0) {  		p = spec->stream_analog_playback;  		if (!p)  			p = &alc_pcm_analog_playback; @@ -4358,6 +4374,7 @@ enum {  	ALC882_FIXUP_ACER_ASPIRE_8930G,  	ALC882_FIXUP_ASPIRE_8930G_VERBS,  	ALC885_FIXUP_MACPRO_GPIO, +	ALC889_FIXUP_DAC_ROUTE,  };  static void alc889_fixup_coef(struct hda_codec *codec, @@ -4411,6 +4428,23 @@ static void alc885_fixup_macpro_gpio(struct hda_codec *codec,  	alc882_gpio_mute(codec, 1, 0);  } +/* Fix the connection of some pins for ALC889: + * At least, Acer Aspire 5935 shows the connections to DAC3/4 don't + * work correctly (bko#42740) + */ +static void alc889_fixup_dac_route(struct hda_codec *codec, +				   const struct alc_fixup *fix, int action) +{ +	if (action == ALC_FIXUP_ACT_PRE_PROBE) { +		hda_nid_t conn1[2] = { 0x0c, 0x0d }; +		hda_nid_t conn2[2] = { 0x0e, 0x0f }; +		snd_hda_override_conn_list(codec, 0x14, 2, conn1); +		snd_hda_override_conn_list(codec, 0x15, 2, conn1); +		snd_hda_override_conn_list(codec, 0x18, 2, conn2); +		snd_hda_override_conn_list(codec, 0x1a, 2, conn2); +	} +} +  static const struct alc_fixup alc882_fixups[] = {  	[ALC882_FIXUP_ABIT_AW9D_MAX] = {  		.type = ALC_FIXUP_PINS, @@ -4558,6 +4592,10 @@ static const struct alc_fixup alc882_fixups[] = {  		.type = ALC_FIXUP_FUNC,  		.v.func = alc885_fixup_macpro_gpio,  	}, +	[ALC889_FIXUP_DAC_ROUTE] = { +		.type = ALC_FIXUP_FUNC, +		.v.func = alc889_fixup_dac_route, +	},  };  static const struct snd_pci_quirk alc882_fixup_tbl[] = { @@ -4582,6 +4620,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = {  	SND_PCI_QUIRK(0x1025, 0x0142, "Acer Aspire 7730G",  		      ALC882_FIXUP_ACER_ASPIRE_4930G),  	SND_PCI_QUIRK(0x1025, 0x0155, "Packard-Bell M5120", ALC882_FIXUP_PB_M5210), +	SND_PCI_QUIRK(0x1025, 0x0259, "Acer Aspire 5935", ALC889_FIXUP_DAC_ROUTE),  	SND_PCI_QUIRK(0x1025, 0x0296, "Acer Aspire 7736z", ALC882_FIXUP_ACER_ASPIRE_7736),  	SND_PCI_QUIRK(0x1043, 0x13c2, "Asus A7M", ALC882_FIXUP_EAPD),  	SND_PCI_QUIRK(0x1043, 0x1873, "ASUS W90V", ALC882_FIXUP_ASUS_W90V), @@ -4735,7 +4774,6 @@ enum {  	ALC262_FIXUP_FSC_H270,  	ALC262_FIXUP_HP_Z200,  	ALC262_FIXUP_TYAN, -	ALC262_FIXUP_TOSHIBA_RX1,  	ALC262_FIXUP_LENOVO_3000,  	ALC262_FIXUP_BENQ,  	ALC262_FIXUP_BENQ_T31, @@ -4765,16 +4803,6 @@ static const struct alc_fixup alc262_fixups[] = {  			{ }  		}  	}, -	[ALC262_FIXUP_TOSHIBA_RX1] = { -		.type = ALC_FIXUP_PINS, -		.v.pins = (const struct alc_pincfg[]) { -			{ 0x14, 0x90170110 }, /* speaker */ -			{ 0x15, 0x0421101f }, /* HP */ -			{ 0x1a, 0x40f000f0 }, /* N/A */ -			{ 0x1b, 0x40f000f0 }, /* N/A */ -			{ 0x1e, 0x40f000f0 }, /* N/A */ -		} -	},  	[ALC262_FIXUP_LENOVO_3000] = {  		.type = ALC_FIXUP_VERBS,  		.v.verbs = (const struct hda_verb[]) { @@ -4807,8 +4835,6 @@ static const struct snd_pci_quirk alc262_fixup_tbl[] = {  	SND_PCI_QUIRK(0x10cf, 0x1397, "Fujitsu", ALC262_FIXUP_BENQ),  	SND_PCI_QUIRK(0x10cf, 0x142d, "Fujitsu Lifebook E8410", ALC262_FIXUP_BENQ),  	SND_PCI_QUIRK(0x10f1, 0x2915, "Tyan Thunder n6650W", ALC262_FIXUP_TYAN), -	SND_PCI_QUIRK(0x1179, 0x0001, "Toshiba dynabook SS RX1", -		      ALC262_FIXUP_TOSHIBA_RX1),  	SND_PCI_QUIRK(0x1734, 0x1147, "FSC Celsius H270", ALC262_FIXUP_FSC_H270),  	SND_PCI_QUIRK(0x17aa, 0x384e, "Lenovo 3000", ALC262_FIXUP_LENOVO_3000),  	SND_PCI_QUIRK(0x17ff, 0x0560, "Benq ED8", ALC262_FIXUP_BENQ), @@ -5377,7 +5403,6 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {  	SND_PCI_QUIRK(0x1043, 0x8330, "ASUS Eeepc P703 P900A",  		      ALC269_FIXUP_AMIC),  	SND_PCI_QUIRK(0x1043, 0x1013, "ASUS N61Da", ALC269_FIXUP_AMIC), -	SND_PCI_QUIRK(0x1043, 0x1113, "ASUS N63Jn", ALC269_FIXUP_AMIC),  	SND_PCI_QUIRK(0x1043, 0x1143, "ASUS B53f", ALC269_FIXUP_AMIC),  	SND_PCI_QUIRK(0x1043, 0x1133, "ASUS UJ20ft", ALC269_FIXUP_AMIC),  	SND_PCI_QUIRK(0x1043, 0x1183, "ASUS K72DR", ALC269_FIXUP_AMIC), @@ -5589,6 +5614,25 @@ enum {  	PINFIX_ASUS_A6RP,  }; +/* On some laptops, VREF of pin 0x0f is abused for controlling the main amp */ +static void alc861_fixup_asus_amp_vref_0f(struct hda_codec *codec, +			const struct alc_fixup *fix, int action) +{ +	struct alc_spec *spec = codec->spec; +	unsigned int val; + +	if (action != ALC_FIXUP_ACT_INIT) +		return; +	val = snd_hda_codec_read(codec, 0x0f, 0, +				 AC_VERB_GET_PIN_WIDGET_CONTROL, 0); +	if (!(val & (AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN))) +		val |= AC_PINCTL_IN_EN; +	val |= AC_PINCTL_VREF_50; +	snd_hda_codec_write(codec, 0x0f, 0, +			    AC_VERB_SET_PIN_WIDGET_CONTROL, val); +	spec->keep_vref_in_automute = 1; +} +  static const struct alc_fixup alc861_fixups[] = {  	[PINFIX_FSC_AMILO_PI1505] = {  		.type = ALC_FIXUP_PINS, @@ -5599,17 +5643,14 @@ static const struct alc_fixup alc861_fixups[] = {  		}  	},  	[PINFIX_ASUS_A6RP] = { -		.type = ALC_FIXUP_VERBS, -		.v.verbs = (const struct hda_verb[]) { -			/* node 0x0f VREF seems controlling the master output */ -			{ 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50 }, -			{ } -		}, +		.type = ALC_FIXUP_FUNC, +		.v.func = alc861_fixup_asus_amp_vref_0f,  	},  };  static const struct snd_pci_quirk alc861_fixup_tbl[] = { -	SND_PCI_QUIRK(0x1043, 0x1393, "ASUS A6Rp", PINFIX_ASUS_A6RP), +	SND_PCI_QUIRK_VENDOR(0x1043, "ASUS laptop", PINFIX_ASUS_A6RP), +	SND_PCI_QUIRK(0x1584, 0x0000, "Uniwill ECS M31EI", PINFIX_ASUS_A6RP),	  	SND_PCI_QUIRK(0x1584, 0x2b01, "Haier W18", PINFIX_ASUS_A6RP),  	SND_PCI_QUIRK(0x1734, 0x10c7, "FSC Amilo Pi1505", PINFIX_FSC_AMILO_PI1505),  	{} diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 948f0be2f4f..6345df131a0 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -5078,9 +5078,9 @@ static int stac92xx_update_led_status(struct hda_codec *codec)  				spec->gpio_dir, spec->gpio_data);  	} else {  		notmtd_lvl = spec->gpio_led_polarity ? -				AC_PINCTL_VREF_HIZ : AC_PINCTL_VREF_GRD; +				AC_PINCTL_VREF_50 : AC_PINCTL_VREF_GRD;  		muted_lvl = spec->gpio_led_polarity ? -				AC_PINCTL_VREF_GRD : AC_PINCTL_VREF_HIZ; +				AC_PINCTL_VREF_GRD : AC_PINCTL_VREF_50;  		spec->vref_led = muted ? muted_lvl : notmtd_lvl;  		stac_vrefout_set(codec,	spec->vref_mute_led_nid,  				 spec->vref_led); diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index 03e63fed9ca..dff9a00ee8f 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c @@ -199,6 +199,9 @@ struct via_spec {  	unsigned int no_pin_power_ctl;  	enum VIA_HDA_CODEC codec_type; +	/* analog low-power control */ +	bool alc_mode; +  	/* smart51 setup */  	unsigned int smart51_nums;  	hda_nid_t smart51_pins[2]; @@ -663,6 +666,9 @@ static void via_auto_init_analog_input(struct hda_codec *codec)  	/* init input-src */  	for (i = 0; i < spec->num_adc_nids; i++) {  		int adc_idx = spec->inputs[spec->cur_mux[i]].adc_idx; +		/* secondary ADCs must have the unique MUX */ +		if (i > 0 && !spec->mux_nids[i]) +			break;  		if (spec->mux_nids[adc_idx]) {  			int mux_idx = spec->inputs[spec->cur_mux[i]].mux_idx;  			snd_hda_codec_write(codec, spec->mux_nids[adc_idx], 0, @@ -687,6 +693,15 @@ static void via_auto_init_analog_input(struct hda_codec *codec)  	}  } +static void update_power_state(struct hda_codec *codec, hda_nid_t nid, +			       unsigned int parm) +{ +	if (snd_hda_codec_read(codec, nid, 0, +			       AC_VERB_GET_POWER_STATE, 0) == parm) +		return; +	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_POWER_STATE, parm); +} +  static void set_pin_power_state(struct hda_codec *codec, hda_nid_t nid,  				unsigned int *affected_parm)  { @@ -709,7 +724,7 @@ static void set_pin_power_state(struct hda_codec *codec, hda_nid_t nid,  	} else  		parm = AC_PWRST_D3; -	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_POWER_STATE, parm); +	update_power_state(codec, nid, parm);  }  static int via_pin_power_ctl_info(struct snd_kcontrol *kcontrol, @@ -749,6 +764,7 @@ static int via_pin_power_ctl_put(struct snd_kcontrol *kcontrol,  		return 0;  	spec->no_pin_power_ctl = val;  	set_widgets_power_state(codec); +	analog_low_current_mode(codec);  	return 1;  } @@ -1036,13 +1052,19 @@ static bool is_aa_path_mute(struct hda_codec *codec)  }  /* enter/exit analog low-current mode */ -static void analog_low_current_mode(struct hda_codec *codec) +static void __analog_low_current_mode(struct hda_codec *codec, bool force)  {  	struct via_spec *spec = codec->spec;  	bool enable;  	unsigned int verb, parm; -	enable = is_aa_path_mute(codec) && (spec->opened_streams != 0); +	if (spec->no_pin_power_ctl) +		enable = false; +	else +		enable = is_aa_path_mute(codec) && !spec->opened_streams; +	if (enable == spec->alc_mode && !force) +		return; +	spec->alc_mode = enable;  	/* decide low current mode's verb & parameter */  	switch (spec->codec_type) { @@ -1074,6 +1096,11 @@ static void analog_low_current_mode(struct hda_codec *codec)  	snd_hda_codec_write(codec, codec->afg, 0, verb, parm);  } +static void analog_low_current_mode(struct hda_codec *codec) +{ +	return __analog_low_current_mode(codec, false); +} +  /*   * generic initialization of ADC, input mixers and output mixers   */ @@ -1446,6 +1473,7 @@ static int via_build_controls(struct hda_codec *codec)  	struct snd_kcontrol *kctl;  	int err, i; +	spec->no_pin_power_ctl = 1;  	if (spec->set_widgets_power_state)  		if (!via_clone_control(spec, &via_pin_power_ctl_enum))  			return -ENOMEM; @@ -1499,10 +1527,6 @@ static int via_build_controls(struct hda_codec *codec)  			return err;  	} -	/* init power states */ -	set_widgets_power_state(codec); -	analog_low_current_mode(codec); -  	via_free_kctls(codec); /* no longer needed */  	err = snd_hda_jack_add_kctls(codec, &spec->autocfg); @@ -2295,10 +2319,7 @@ static int via_mux_enum_put(struct snd_kcontrol *kcontrol,  	if (mux) {  		/* switch to D0 beofre change index */ -		if (snd_hda_codec_read(codec, mux, 0, -			       AC_VERB_GET_POWER_STATE, 0x00) != AC_PWRST_D0) -			snd_hda_codec_write(codec, mux, 0, -				    AC_VERB_SET_POWER_STATE, AC_PWRST_D0); +		update_power_state(codec, mux, AC_PWRST_D0);  		snd_hda_codec_write(codec, mux, 0,  				    AC_VERB_SET_CONNECT_SEL,  				    spec->inputs[cur].mux_idx); @@ -2776,6 +2797,10 @@ static int via_init(struct hda_codec *codec)  	for (i = 0; i < spec->num_iverbs; i++)  		snd_hda_sequence_write(codec, spec->init_verbs[i]); +	/* init power states */ +	set_widgets_power_state(codec); +	__analog_low_current_mode(codec, true); +  	via_auto_init_multi_out(codec);  	via_auto_init_hp_out(codec);  	via_auto_init_speaker_out(codec); @@ -2922,9 +2947,9 @@ static void set_widgets_power_state_vt1708B(struct hda_codec *codec)  	if (imux_is_smixer)  		parm = AC_PWRST_D0;  	/* SW0 (17h), AIW 0/1 (13h/14h) */ -	snd_hda_codec_write(codec, 0x17, 0, AC_VERB_SET_POWER_STATE, parm); -	snd_hda_codec_write(codec, 0x13, 0, AC_VERB_SET_POWER_STATE, parm); -	snd_hda_codec_write(codec, 0x14, 0, AC_VERB_SET_POWER_STATE, parm); +	update_power_state(codec, 0x17, parm); +	update_power_state(codec, 0x13, parm); +	update_power_state(codec, 0x14, parm);  	/* outputs */  	/* PW0 (19h), SW1 (18h), AOW1 (11h) */ @@ -2932,8 +2957,8 @@ static void set_widgets_power_state_vt1708B(struct hda_codec *codec)  	set_pin_power_state(codec, 0x19, &parm);  	if (spec->smart51_enabled)  		set_pin_power_state(codec, 0x1b, &parm); -	snd_hda_codec_write(codec, 0x18, 0, AC_VERB_SET_POWER_STATE, parm); -	snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE, parm); +	update_power_state(codec, 0x18, parm); +	update_power_state(codec, 0x11, parm);  	/* PW6 (22h), SW2 (26h), AOW2 (24h) */  	if (is_8ch) { @@ -2941,20 +2966,16 @@ static void set_widgets_power_state_vt1708B(struct hda_codec *codec)  		set_pin_power_state(codec, 0x22, &parm);  		if (spec->smart51_enabled)  			set_pin_power_state(codec, 0x1a, &parm); -		snd_hda_codec_write(codec, 0x26, 0, -				    AC_VERB_SET_POWER_STATE, parm); -		snd_hda_codec_write(codec, 0x24, 0, -				    AC_VERB_SET_POWER_STATE, parm); +		update_power_state(codec, 0x26, parm); +		update_power_state(codec, 0x24, parm);  	} else if (codec->vendor_id == 0x11064397) {  		/* PW7(23h), SW2(27h), AOW2(25h) */  		parm = AC_PWRST_D3;  		set_pin_power_state(codec, 0x23, &parm);  		if (spec->smart51_enabled)  			set_pin_power_state(codec, 0x1a, &parm); -		snd_hda_codec_write(codec, 0x27, 0, -				    AC_VERB_SET_POWER_STATE, parm); -		snd_hda_codec_write(codec, 0x25, 0, -				    AC_VERB_SET_POWER_STATE, parm); +		update_power_state(codec, 0x27, parm); +		update_power_state(codec, 0x25, parm);  	}  	/* PW 3/4/7 (1ch/1dh/23h) */ @@ -2966,17 +2987,13 @@ static void set_widgets_power_state_vt1708B(struct hda_codec *codec)  		set_pin_power_state(codec, 0x23, &parm);  	/* MW0 (16h), Sw3 (27h), AOW 0/3 (10h/25h) */ -	snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_POWER_STATE, -			    imux_is_smixer ? AC_PWRST_D0 : parm); -	snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE, parm); +	update_power_state(codec, 0x16, imux_is_smixer ? AC_PWRST_D0 : parm); +	update_power_state(codec, 0x10, parm);  	if (is_8ch) { -		snd_hda_codec_write(codec, 0x25, 0, -				    AC_VERB_SET_POWER_STATE, parm); -		snd_hda_codec_write(codec, 0x27, 0, -				    AC_VERB_SET_POWER_STATE, parm); +		update_power_state(codec, 0x25, parm); +		update_power_state(codec, 0x27, parm);  	} else if (codec->vendor_id == 0x11064397 && spec->hp_independent_mode) -		snd_hda_codec_write(codec, 0x25, 0, -				    AC_VERB_SET_POWER_STATE, parm); +		update_power_state(codec, 0x25, parm);  }  static int patch_vt1708S(struct hda_codec *codec); @@ -3149,10 +3166,10 @@ static void set_widgets_power_state_vt1702(struct hda_codec *codec)  	if (imux_is_smixer)  		parm = AC_PWRST_D0; /* SW0 (13h) = stereo mixer (idx 3) */  	/* SW0 (13h), AIW 0/1/2 (12h/1fh/20h) */ -	snd_hda_codec_write(codec, 0x13, 0, AC_VERB_SET_POWER_STATE, parm); -	snd_hda_codec_write(codec, 0x12, 0, AC_VERB_SET_POWER_STATE, parm); -	snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_POWER_STATE, parm); -	snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_POWER_STATE, parm); +	update_power_state(codec, 0x13, parm); +	update_power_state(codec, 0x12, parm); +	update_power_state(codec, 0x1f, parm); +	update_power_state(codec, 0x20, parm);  	/* outputs */  	/* PW 3/4 (16h/17h) */ @@ -3160,10 +3177,9 @@ static void set_widgets_power_state_vt1702(struct hda_codec *codec)  	set_pin_power_state(codec, 0x17, &parm);  	set_pin_power_state(codec, 0x16, &parm);  	/* MW0 (1ah), AOW 0/1 (10h/1dh) */ -	snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_POWER_STATE, -			    imux_is_smixer ? AC_PWRST_D0 : parm); -	snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE, parm); -	snd_hda_codec_write(codec, 0x1d, 0, AC_VERB_SET_POWER_STATE, parm); +	update_power_state(codec, 0x1a, imux_is_smixer ? AC_PWRST_D0 : parm); +	update_power_state(codec, 0x10, parm); +	update_power_state(codec, 0x1d, parm);  }  static int patch_vt1702(struct hda_codec *codec) @@ -3228,52 +3244,48 @@ static void set_widgets_power_state_vt1718S(struct hda_codec *codec)  	if (imux_is_smixer)  		parm = AC_PWRST_D0;  	/* MUX6/7 (1eh/1fh), AIW 0/1 (10h/11h) */ -	snd_hda_codec_write(codec, 0x1e, 0, AC_VERB_SET_POWER_STATE, parm); -	snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_POWER_STATE, parm); -	snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE, parm); -	snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE, parm); +	update_power_state(codec, 0x1e, parm); +	update_power_state(codec, 0x1f, parm); +	update_power_state(codec, 0x10, parm); +	update_power_state(codec, 0x11, parm);  	/* outputs */  	/* PW3 (27h), MW2 (1ah), AOW3 (bh) */  	parm = AC_PWRST_D3;  	set_pin_power_state(codec, 0x27, &parm); -	snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_POWER_STATE, parm); -	snd_hda_codec_write(codec, 0xb, 0, AC_VERB_SET_POWER_STATE, parm); +	update_power_state(codec, 0x1a, parm); +	update_power_state(codec, 0xb, parm);  	/* PW2 (26h), AOW2 (ah) */  	parm = AC_PWRST_D3;  	set_pin_power_state(codec, 0x26, &parm);  	if (spec->smart51_enabled)  		set_pin_power_state(codec, 0x2b, &parm); -	snd_hda_codec_write(codec, 0xa, 0, AC_VERB_SET_POWER_STATE, parm); +	update_power_state(codec, 0xa, parm);  	/* PW0 (24h), AOW0 (8h) */  	parm = AC_PWRST_D3;  	set_pin_power_state(codec, 0x24, &parm);  	if (!spec->hp_independent_mode) /* check for redirected HP */  		set_pin_power_state(codec, 0x28, &parm); -	snd_hda_codec_write(codec, 0x8, 0, AC_VERB_SET_POWER_STATE, parm); +	update_power_state(codec, 0x8, parm);  	/* MW9 (21h), Mw2 (1ah), AOW0 (8h) */ -	snd_hda_codec_write(codec, 0x21, 0, AC_VERB_SET_POWER_STATE, -			    imux_is_smixer ? AC_PWRST_D0 : parm); +	update_power_state(codec, 0x21, imux_is_smixer ? AC_PWRST_D0 : parm);  	/* PW1 (25h), AOW1 (9h) */  	parm = AC_PWRST_D3;  	set_pin_power_state(codec, 0x25, &parm);  	if (spec->smart51_enabled)  		set_pin_power_state(codec, 0x2a, &parm); -	snd_hda_codec_write(codec, 0x9, 0, AC_VERB_SET_POWER_STATE, parm); +	update_power_state(codec, 0x9, parm);  	if (spec->hp_independent_mode) {  		/* PW4 (28h), MW3 (1bh), MUX1(34h), AOW4 (ch) */  		parm = AC_PWRST_D3;  		set_pin_power_state(codec, 0x28, &parm); -		snd_hda_codec_write(codec, 0x1b, 0, -				    AC_VERB_SET_POWER_STATE, parm); -		snd_hda_codec_write(codec, 0x34, 0, -				    AC_VERB_SET_POWER_STATE, parm); -		snd_hda_codec_write(codec, 0xc, 0, -				    AC_VERB_SET_POWER_STATE, parm); +		update_power_state(codec, 0x1b, parm); +		update_power_state(codec, 0x34, parm); +		update_power_state(codec, 0xc, parm);  	}  } @@ -3433,8 +3445,8 @@ static void set_widgets_power_state_vt1716S(struct hda_codec *codec)  	if (imux_is_smixer)  		parm = AC_PWRST_D0;  	/* SW0 (17h), AIW0(13h) */ -	snd_hda_codec_write(codec, 0x17, 0, AC_VERB_SET_POWER_STATE, parm); -	snd_hda_codec_write(codec, 0x13, 0, AC_VERB_SET_POWER_STATE, parm); +	update_power_state(codec, 0x17, parm); +	update_power_state(codec, 0x13, parm);  	parm = AC_PWRST_D3;  	set_pin_power_state(codec, 0x1e, &parm); @@ -3442,12 +3454,11 @@ static void set_widgets_power_state_vt1716S(struct hda_codec *codec)  	if (spec->dmic_enabled)  		set_pin_power_state(codec, 0x22, &parm);  	else -		snd_hda_codec_write(codec, 0x22, 0, -				    AC_VERB_SET_POWER_STATE, AC_PWRST_D3); +		update_power_state(codec, 0x22, AC_PWRST_D3);  	/* SW2(26h), AIW1(14h) */ -	snd_hda_codec_write(codec, 0x26, 0, AC_VERB_SET_POWER_STATE, parm); -	snd_hda_codec_write(codec, 0x14, 0, AC_VERB_SET_POWER_STATE, parm); +	update_power_state(codec, 0x26, parm); +	update_power_state(codec, 0x14, parm);  	/* outputs */  	/* PW0 (19h), SW1 (18h), AOW1 (11h) */ @@ -3456,8 +3467,8 @@ static void set_widgets_power_state_vt1716S(struct hda_codec *codec)  	/* Smart 5.1 PW2(1bh) */  	if (spec->smart51_enabled)  		set_pin_power_state(codec, 0x1b, &parm); -	snd_hda_codec_write(codec, 0x18, 0, AC_VERB_SET_POWER_STATE, parm); -	snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE, parm); +	update_power_state(codec, 0x18, parm); +	update_power_state(codec, 0x11, parm);  	/* PW7 (23h), SW3 (27h), AOW3 (25h) */  	parm = AC_PWRST_D3; @@ -3465,12 +3476,12 @@ static void set_widgets_power_state_vt1716S(struct hda_codec *codec)  	/* Smart 5.1 PW1(1ah) */  	if (spec->smart51_enabled)  		set_pin_power_state(codec, 0x1a, &parm); -	snd_hda_codec_write(codec, 0x27, 0, AC_VERB_SET_POWER_STATE, parm); +	update_power_state(codec, 0x27, parm);  	/* Smart 5.1 PW5(1eh) */  	if (spec->smart51_enabled)  		set_pin_power_state(codec, 0x1e, &parm); -	snd_hda_codec_write(codec, 0x25, 0, AC_VERB_SET_POWER_STATE, parm); +	update_power_state(codec, 0x25, parm);  	/* Mono out */  	/* SW4(28h)->MW1(29h)-> PW12 (2ah)*/ @@ -3486,9 +3497,9 @@ static void set_widgets_power_state_vt1716S(struct hda_codec *codec)  			mono_out = 1;  	}  	parm = mono_out ? AC_PWRST_D0 : AC_PWRST_D3; -	snd_hda_codec_write(codec, 0x28, 0, AC_VERB_SET_POWER_STATE, parm); -	snd_hda_codec_write(codec, 0x29, 0, AC_VERB_SET_POWER_STATE, parm); -	snd_hda_codec_write(codec, 0x2a, 0, AC_VERB_SET_POWER_STATE, parm); +	update_power_state(codec, 0x28, parm); +	update_power_state(codec, 0x29, parm); +	update_power_state(codec, 0x2a, parm);  	/* PW 3/4 (1ch/1dh) */  	parm = AC_PWRST_D3; @@ -3496,15 +3507,12 @@ static void set_widgets_power_state_vt1716S(struct hda_codec *codec)  	set_pin_power_state(codec, 0x1d, &parm);  	/* HP Independent Mode, power on AOW3 */  	if (spec->hp_independent_mode) -		snd_hda_codec_write(codec, 0x25, 0, -				    AC_VERB_SET_POWER_STATE, parm); +		update_power_state(codec, 0x25, parm);  	/* force to D0 for internal Speaker */  	/* MW0 (16h), AOW0 (10h) */ -	snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_POWER_STATE, -			    imux_is_smixer ? AC_PWRST_D0 : parm); -	snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE, -			    mono_out ? AC_PWRST_D0 : parm); +	update_power_state(codec, 0x16, imux_is_smixer ? AC_PWRST_D0 : parm); +	update_power_state(codec, 0x10, mono_out ? AC_PWRST_D0 : parm);  }  static int patch_vt1716S(struct hda_codec *codec) @@ -3580,54 +3588,45 @@ static void set_widgets_power_state_vt2002P(struct hda_codec *codec)  	set_pin_power_state(codec, 0x2b, &parm);  	parm = AC_PWRST_D0;  	/* MUX9/10 (1eh/1fh), AIW 0/1 (10h/11h) */ -	snd_hda_codec_write(codec, 0x1e, 0, AC_VERB_SET_POWER_STATE, parm); -	snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_POWER_STATE, parm); -	snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE, parm); -	snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE, parm); +	update_power_state(codec, 0x1e, parm); +	update_power_state(codec, 0x1f, parm); +	update_power_state(codec, 0x10, parm); +	update_power_state(codec, 0x11, parm);  	/* outputs */  	/* AOW0 (8h)*/ -	snd_hda_codec_write(codec, 0x8, 0, AC_VERB_SET_POWER_STATE, parm); +	update_power_state(codec, 0x8, parm);  	if (spec->codec_type == VT1802) {  		/* PW4 (28h), MW4 (18h), MUX4(38h) */  		parm = AC_PWRST_D3;  		set_pin_power_state(codec, 0x28, &parm); -		snd_hda_codec_write(codec, 0x18, 0, -				    AC_VERB_SET_POWER_STATE, parm); -		snd_hda_codec_write(codec, 0x38, 0, -				    AC_VERB_SET_POWER_STATE, parm); +		update_power_state(codec, 0x18, parm); +		update_power_state(codec, 0x38, parm);  	} else {  		/* PW4 (26h), MW4 (1ch), MUX4(37h) */  		parm = AC_PWRST_D3;  		set_pin_power_state(codec, 0x26, &parm); -		snd_hda_codec_write(codec, 0x1c, 0, -				    AC_VERB_SET_POWER_STATE, parm); -		snd_hda_codec_write(codec, 0x37, 0, -				    AC_VERB_SET_POWER_STATE, parm); +		update_power_state(codec, 0x1c, parm); +		update_power_state(codec, 0x37, parm);  	}  	if (spec->codec_type == VT1802) {  		/* PW1 (25h), MW1 (15h), MUX1(35h), AOW1 (9h) */  		parm = AC_PWRST_D3;  		set_pin_power_state(codec, 0x25, &parm); -		snd_hda_codec_write(codec, 0x15, 0, -				    AC_VERB_SET_POWER_STATE, parm); -		snd_hda_codec_write(codec, 0x35, 0, -				    AC_VERB_SET_POWER_STATE, parm); +		update_power_state(codec, 0x15, parm); +		update_power_state(codec, 0x35, parm);  	} else {  		/* PW1 (25h), MW1 (19h), MUX1(35h), AOW1 (9h) */  		parm = AC_PWRST_D3;  		set_pin_power_state(codec, 0x25, &parm); -		snd_hda_codec_write(codec, 0x19, 0, -				    AC_VERB_SET_POWER_STATE, parm); -		snd_hda_codec_write(codec, 0x35, 0, -				    AC_VERB_SET_POWER_STATE, parm); +		update_power_state(codec, 0x19, parm); +		update_power_state(codec, 0x35, parm);  	}  	if (spec->hp_independent_mode) -		snd_hda_codec_write(codec, 0x9, 0, -				    AC_VERB_SET_POWER_STATE, AC_PWRST_D0); +		update_power_state(codec, 0x9, AC_PWRST_D0);  	/* Class-D */  	/* PW0 (24h), MW0(18h/14h), MUX0(34h) */ @@ -3637,12 +3636,10 @@ static void set_widgets_power_state_vt2002P(struct hda_codec *codec)  	set_pin_power_state(codec, 0x24, &parm);  	parm = present ? AC_PWRST_D3 : AC_PWRST_D0;  	if (spec->codec_type == VT1802) -		snd_hda_codec_write(codec, 0x14, 0, -				    AC_VERB_SET_POWER_STATE, parm); +		update_power_state(codec, 0x14, parm);  	else -		snd_hda_codec_write(codec, 0x18, 0, -				    AC_VERB_SET_POWER_STATE, parm); -	snd_hda_codec_write(codec, 0x34, 0, AC_VERB_SET_POWER_STATE, parm); +		update_power_state(codec, 0x18, parm); +	update_power_state(codec, 0x34, parm);  	/* Mono Out */  	present = snd_hda_jack_detect(codec, 0x26); @@ -3650,28 +3647,20 @@ static void set_widgets_power_state_vt2002P(struct hda_codec *codec)  	parm = present ? AC_PWRST_D3 : AC_PWRST_D0;  	if (spec->codec_type == VT1802) {  		/* PW15 (33h), MW8(1ch), MUX8(3ch) */ -		snd_hda_codec_write(codec, 0x33, 0, -				    AC_VERB_SET_POWER_STATE, parm); -		snd_hda_codec_write(codec, 0x1c, 0, -				    AC_VERB_SET_POWER_STATE, parm); -		snd_hda_codec_write(codec, 0x3c, 0, -				    AC_VERB_SET_POWER_STATE, parm); +		update_power_state(codec, 0x33, parm); +		update_power_state(codec, 0x1c, parm); +		update_power_state(codec, 0x3c, parm);  	} else {  		/* PW15 (31h), MW8(17h), MUX8(3bh) */ -		snd_hda_codec_write(codec, 0x31, 0, -				    AC_VERB_SET_POWER_STATE, parm); -		snd_hda_codec_write(codec, 0x17, 0, -				    AC_VERB_SET_POWER_STATE, parm); -		snd_hda_codec_write(codec, 0x3b, 0, -				    AC_VERB_SET_POWER_STATE, parm); +		update_power_state(codec, 0x31, parm); +		update_power_state(codec, 0x17, parm); +		update_power_state(codec, 0x3b, parm);  	}  	/* MW9 (21h) */  	if (imux_is_smixer || !is_aa_path_mute(codec)) -		snd_hda_codec_write(codec, 0x21, 0, -				    AC_VERB_SET_POWER_STATE, AC_PWRST_D0); +		update_power_state(codec, 0x21, AC_PWRST_D0);  	else -		snd_hda_codec_write(codec, 0x21, 0, -				    AC_VERB_SET_POWER_STATE, AC_PWRST_D3); +		update_power_state(codec, 0x21, AC_PWRST_D3);  }  /* patch for vt2002P */ @@ -3731,30 +3720,28 @@ static void set_widgets_power_state_vt1812(struct hda_codec *codec)  	set_pin_power_state(codec, 0x2b, &parm);  	parm = AC_PWRST_D0;  	/* MUX10/11 (1eh/1fh), AIW 0/1 (10h/11h) */ -	snd_hda_codec_write(codec, 0x1e, 0, AC_VERB_SET_POWER_STATE, parm); -	snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_POWER_STATE, parm); -	snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE, parm); -	snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE, parm); +	update_power_state(codec, 0x1e, parm); +	update_power_state(codec, 0x1f, parm); +	update_power_state(codec, 0x10, parm); +	update_power_state(codec, 0x11, parm);  	/* outputs */  	/* AOW0 (8h)*/ -	snd_hda_codec_write(codec, 0x8, 0, -			    AC_VERB_SET_POWER_STATE, AC_PWRST_D0); +	update_power_state(codec, 0x8, AC_PWRST_D0);  	/* PW4 (28h), MW4 (18h), MUX4(38h) */  	parm = AC_PWRST_D3;  	set_pin_power_state(codec, 0x28, &parm); -	snd_hda_codec_write(codec, 0x18, 0, AC_VERB_SET_POWER_STATE, parm); -	snd_hda_codec_write(codec, 0x38, 0, AC_VERB_SET_POWER_STATE, parm); +	update_power_state(codec, 0x18, parm); +	update_power_state(codec, 0x38, parm);  	/* PW1 (25h), MW1 (15h), MUX1(35h), AOW1 (9h) */  	parm = AC_PWRST_D3;  	set_pin_power_state(codec, 0x25, &parm); -	snd_hda_codec_write(codec, 0x15, 0, AC_VERB_SET_POWER_STATE, parm); -	snd_hda_codec_write(codec, 0x35, 0, AC_VERB_SET_POWER_STATE, parm); +	update_power_state(codec, 0x15, parm); +	update_power_state(codec, 0x35, parm);  	if (spec->hp_independent_mode) -		snd_hda_codec_write(codec, 0x9, 0, -				    AC_VERB_SET_POWER_STATE, AC_PWRST_D0); +		update_power_state(codec, 0x9, AC_PWRST_D0);  	/* Internal Speaker */  	/* PW0 (24h), MW0(14h), MUX0(34h) */ @@ -3763,15 +3750,11 @@ static void set_widgets_power_state_vt1812(struct hda_codec *codec)  	parm = AC_PWRST_D3;  	set_pin_power_state(codec, 0x24, &parm);  	if (present) { -		snd_hda_codec_write(codec, 0x14, 0, -				    AC_VERB_SET_POWER_STATE, AC_PWRST_D3); -		snd_hda_codec_write(codec, 0x34, 0, -				    AC_VERB_SET_POWER_STATE, AC_PWRST_D3); +		update_power_state(codec, 0x14, AC_PWRST_D3); +		update_power_state(codec, 0x34, AC_PWRST_D3);  	} else { -		snd_hda_codec_write(codec, 0x14, 0, -				    AC_VERB_SET_POWER_STATE, AC_PWRST_D0); -		snd_hda_codec_write(codec, 0x34, 0, -				    AC_VERB_SET_POWER_STATE, AC_PWRST_D0); +		update_power_state(codec, 0x14, AC_PWRST_D0); +		update_power_state(codec, 0x34, AC_PWRST_D0);  	} @@ -3782,26 +3765,20 @@ static void set_widgets_power_state_vt1812(struct hda_codec *codec)  	parm = AC_PWRST_D3;  	set_pin_power_state(codec, 0x31, &parm);  	if (present) { -		snd_hda_codec_write(codec, 0x1c, 0, -				    AC_VERB_SET_POWER_STATE, AC_PWRST_D3); -		snd_hda_codec_write(codec, 0x3c, 0, -				    AC_VERB_SET_POWER_STATE, AC_PWRST_D3); -		snd_hda_codec_write(codec, 0x3e, 0, -				    AC_VERB_SET_POWER_STATE, AC_PWRST_D3); +		update_power_state(codec, 0x1c, AC_PWRST_D3); +		update_power_state(codec, 0x3c, AC_PWRST_D3); +		update_power_state(codec, 0x3e, AC_PWRST_D3);  	} else { -		snd_hda_codec_write(codec, 0x1c, 0, -				    AC_VERB_SET_POWER_STATE, AC_PWRST_D0); -		snd_hda_codec_write(codec, 0x3c, 0, -				    AC_VERB_SET_POWER_STATE, AC_PWRST_D0); -		snd_hda_codec_write(codec, 0x3e, 0, -				    AC_VERB_SET_POWER_STATE, AC_PWRST_D0); +		update_power_state(codec, 0x1c, AC_PWRST_D0); +		update_power_state(codec, 0x3c, AC_PWRST_D0); +		update_power_state(codec, 0x3e, AC_PWRST_D0);  	}  	/* PW15 (33h), MW15 (1dh), MUX15(3dh) */  	parm = AC_PWRST_D3;  	set_pin_power_state(codec, 0x33, &parm); -	snd_hda_codec_write(codec, 0x1d, 0, AC_VERB_SET_POWER_STATE, parm); -	snd_hda_codec_write(codec, 0x3d, 0, AC_VERB_SET_POWER_STATE, parm); +	update_power_state(codec, 0x1d, parm); +	update_power_state(codec, 0x3d, parm);  } diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index 9f3b01bb72c..e0a4263baa2 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c @@ -2102,6 +2102,12 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = {  	},  	{  		.subvendor = 0x161f, +		.subdevice = 0x202f, +		.name = "Gateway M520", +		.type = AC97_TUNE_INV_EAPD +	}, +	{ +		.subvendor = 0x161f,  		.subdevice = 0x203a,  		.name = "Gateway 4525GZ",		/* AD1981B */  		.type = AC97_TUNE_INV_EAPD diff --git a/sound/pci/oxygen/oxygen_mixer.c b/sound/pci/oxygen/oxygen_mixer.c index 26c7e8bcb22..c0dbb52d45b 100644 --- a/sound/pci/oxygen/oxygen_mixer.c +++ b/sound/pci/oxygen/oxygen_mixer.c @@ -618,9 +618,12 @@ static int ac97_volume_get(struct snd_kcontrol *ctl,  	mutex_lock(&chip->mutex);  	reg = oxygen_read_ac97(chip, codec, index);  	mutex_unlock(&chip->mutex); -	value->value.integer.value[0] = 31 - (reg & 0x1f); -	if (stereo) -		value->value.integer.value[1] = 31 - ((reg >> 8) & 0x1f); +	if (!stereo) { +		value->value.integer.value[0] = 31 - (reg & 0x1f); +	} else { +		value->value.integer.value[0] = 31 - ((reg >> 8) & 0x1f); +		value->value.integer.value[1] = 31 - (reg & 0x1f); +	}  	return 0;  } @@ -636,14 +639,14 @@ static int ac97_volume_put(struct snd_kcontrol *ctl,  	mutex_lock(&chip->mutex);  	oldreg = oxygen_read_ac97(chip, codec, index); -	newreg = oldreg; -	newreg = (newreg & ~0x1f) | -		(31 - (value->value.integer.value[0] & 0x1f)); -	if (stereo) -		newreg = (newreg & ~0x1f00) | -			((31 - (value->value.integer.value[1] & 0x1f)) << 8); -	else -		newreg = (newreg & ~0x1f00) | ((newreg & 0x1f) << 8); +	if (!stereo) { +		newreg = oldreg & ~0x1f; +		newreg |= 31 - (value->value.integer.value[0] & 0x1f); +	} else { +		newreg = oldreg & ~0x1f1f; +		newreg |= (31 - (value->value.integer.value[0] & 0x1f)) << 8; +		newreg |= 31 - (value->value.integer.value[1] & 0x1f); +	}  	change = newreg != oldreg;  	if (change)  		oxygen_write_ac97(chip, codec, index, newreg); diff --git a/sound/soc/codecs/cs42l73.c b/sound/soc/codecs/cs42l73.c index 9d38db8f191..78979b3e0e9 100644 --- a/sound/soc/codecs/cs42l73.c +++ b/sound/soc/codecs/cs42l73.c @@ -1113,7 +1113,7 @@ static int cs42l73_pcm_hw_params(struct snd_pcm_substream *substream,  		priv->config[id].mmcc &= 0xC0;  		priv->config[id].mmcc |= cs42l73_mclk_coeffs[mclk_coeff].mmcc;  		priv->config[id].spc &= 0xFC; -		priv->config[id].spc &= MCK_SCLK_64FS; +		priv->config[id].spc |= MCK_SCLK_MCLK;  	} else {  		/* CS42L73 Slave */  		priv->config[id].spc &= 0xFC; diff --git a/sound/soc/codecs/wm5100.c b/sound/soc/codecs/wm5100.c index 66f0611e68b..89f2af77b1c 100644 --- a/sound/soc/codecs/wm5100.c +++ b/sound/soc/codecs/wm5100.c @@ -1405,6 +1405,7 @@ static int wm5100_set_bias_level(struct snd_soc_codec *codec,  	case SND_SOC_BIAS_OFF:  		regcache_cache_only(wm5100->regmap, true); +		regcache_mark_dirty(wm5100->regmap);  		if (wm5100->pdata.ldo_ena)  			gpio_set_value_cansleep(wm5100->pdata.ldo_ena, 0);  		regulator_bulk_disable(ARRAY_SIZE(wm5100->core_supplies), @@ -2183,6 +2184,7 @@ static void wm5100_micd_irq(struct snd_soc_codec *codec)  		if (wm5100->jack_detecting) {  			dev_dbg(codec->dev, "Microphone detected\n");  			wm5100->jack_mic = true; +			wm5100->jack_detecting = false;  			snd_soc_jack_report(wm5100->jack,  					    SND_JACK_HEADSET,  					    SND_JACK_HEADSET | SND_JACK_BTN_0); @@ -2221,6 +2223,7 @@ static void wm5100_micd_irq(struct snd_soc_codec *codec)  					    SND_JACK_BTN_0);  		} else if (wm5100->jack_detecting) {  			dev_dbg(codec->dev, "Headphone detected\n"); +			wm5100->jack_detecting = false;  			snd_soc_jack_report(wm5100->jack, SND_JACK_HEADPHONE,  					    SND_JACK_HEADPHONE); @@ -2610,6 +2613,13 @@ static const struct regmap_config wm5100_regmap = {  	.cache_type = REGCACHE_RBTREE,  }; +static const unsigned int wm5100_mic_ctrl_reg[] = { +	WM5100_IN1L_CONTROL, +	WM5100_IN2L_CONTROL, +	WM5100_IN3L_CONTROL, +	WM5100_IN4L_CONTROL, +}; +  static __devinit int wm5100_i2c_probe(struct i2c_client *i2c,  				      const struct i2c_device_id *id)  { @@ -2742,7 +2752,7 @@ static __devinit int wm5100_i2c_probe(struct i2c_client *i2c,  	}  	for (i = 0; i < ARRAY_SIZE(wm5100->pdata.in_mode); i++) { -		regmap_update_bits(wm5100->regmap, WM5100_IN1L_CONTROL, +		regmap_update_bits(wm5100->regmap, wm5100_mic_ctrl_reg[i],  				   WM5100_IN1_MODE_MASK |  				   WM5100_IN1_DMIC_SUP_MASK,  				   (wm5100->pdata.in_mode[i] << diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index 296de4e30d2..29c4b02c479 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -96,7 +96,7 @@ static int wm8962_regulator_event_##n(struct notifier_block *nb, \  	struct wm8962_priv *wm8962 = container_of(nb, struct wm8962_priv, \  						  disable_nb[n]); \  	if (event & REGULATOR_EVENT_DISABLE) { \ -		regcache_cache_only(wm8962->regmap, true);	\ +		regcache_mark_dirty(wm8962->regmap);	\  	} \  	return 0; \  } @@ -3159,13 +3159,13 @@ static int wm8962_hw_params(struct snd_pcm_substream *substream,  	case SNDRV_PCM_FORMAT_S16_LE:  		break;  	case SNDRV_PCM_FORMAT_S20_3LE: -		aif0 |= 0x40; +		aif0 |= 0x4;  		break;  	case SNDRV_PCM_FORMAT_S24_LE: -		aif0 |= 0x80; +		aif0 |= 0x8;  		break;  	case SNDRV_PCM_FORMAT_S32_LE: -		aif0 |= 0xc0; +		aif0 |= 0xc;  		break;  	default:  		return -EINVAL; diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 93d27b66025..ec69a6c152f 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -770,6 +770,8 @@ static void vmid_reference(struct snd_soc_codec *codec)  {  	struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); +	pm_runtime_get_sync(codec->dev); +  	wm8994->vmid_refcount++;  	dev_dbg(codec->dev, "Referencing VMID, refcount is now %d\n", @@ -783,7 +785,12 @@ static void vmid_reference(struct snd_soc_codec *codec)  				    WM8994_VMID_RAMP_MASK,  				    WM8994_STARTUP_BIAS_ENA |  				    WM8994_VMID_BUF_ENA | -				    (0x11 << WM8994_VMID_RAMP_SHIFT)); +				    (0x3 << WM8994_VMID_RAMP_SHIFT)); + +		/* Remove discharge for line out */ +		snd_soc_update_bits(codec, WM8994_ANTIPOP_1, +				    WM8994_LINEOUT1_DISCH | +				    WM8994_LINEOUT2_DISCH, 0);  		/* Main bias enable, VMID=2x40k */  		snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1, @@ -837,6 +844,8 @@ static void vmid_dereference(struct snd_soc_codec *codec)  				    WM8994_VMID_BUF_ENA |  				    WM8994_VMID_RAMP_MASK, 0);  	} + +	pm_runtime_put(codec->dev);  }  static int vmid_event(struct snd_soc_dapm_widget *w, @@ -2753,11 +2762,6 @@ static int wm8994_resume(struct snd_soc_codec *codec)  		codec->cache_only = 0;  	} -	/* Restore the registers */ -	ret = snd_soc_cache_sync(codec); -	if (ret != 0) -		dev_err(codec->dev, "Failed to sync cache: %d\n", ret); -  	wm8994_set_bias_level(codec, SND_SOC_BIAS_STANDBY);  	for (i = 0; i < ARRAY_SIZE(wm8994->fll); i++) { diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c index 13aa2bdaa7d..61f7daa4d0e 100644 --- a/sound/soc/codecs/wm8996.c +++ b/sound/soc/codecs/wm8996.c @@ -108,7 +108,7 @@ static int wm8996_regulator_event_##n(struct notifier_block *nb, \  	struct wm8996_priv *wm8996 = container_of(nb, struct wm8996_priv, \  						  disable_nb[n]); \  	if (event & REGULATOR_EVENT_DISABLE) { \ -		regcache_cache_only(wm8996->regmap, true);	\ +		regcache_mark_dirty(wm8996->regmap);	\  	} \  	return 0; \  } diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c index 2a61094075f..8a68cea4a3e 100644 --- a/sound/soc/codecs/wm_hubs.c +++ b/sound/soc/codecs/wm_hubs.c @@ -586,14 +586,14 @@ SOC_DAPM_SINGLE("Left Output Switch", WM8993_LINE_MIXER1, 0, 1, 0),  };  static const struct snd_kcontrol_new line2_mix[] = { -SOC_DAPM_SINGLE("IN2R Switch", WM8993_LINE_MIXER2, 2, 1, 0), -SOC_DAPM_SINGLE("IN2L Switch", WM8993_LINE_MIXER2, 1, 1, 0), +SOC_DAPM_SINGLE("IN1L Switch", WM8993_LINE_MIXER2, 2, 1, 0), +SOC_DAPM_SINGLE("IN1R Switch", WM8993_LINE_MIXER2, 1, 1, 0),  SOC_DAPM_SINGLE("Output Switch", WM8993_LINE_MIXER2, 0, 1, 0),  };  static const struct snd_kcontrol_new line2n_mix[] = { -SOC_DAPM_SINGLE("Left Output Switch", WM8993_LINE_MIXER2, 6, 1, 0), -SOC_DAPM_SINGLE("Right Output Switch", WM8993_LINE_MIXER2, 5, 1, 0), +SOC_DAPM_SINGLE("Left Output Switch", WM8993_LINE_MIXER2, 5, 1, 0), +SOC_DAPM_SINGLE("Right Output Switch", WM8993_LINE_MIXER2, 6, 1, 0),  };  static const struct snd_kcontrol_new line2p_mix[] = { @@ -613,6 +613,8 @@ SND_SOC_DAPM_INPUT("IN2RP:VXRP"),  SND_SOC_DAPM_SUPPLY("MICBIAS2", WM8993_POWER_MANAGEMENT_1, 5, 0, NULL, 0),  SND_SOC_DAPM_SUPPLY("MICBIAS1", WM8993_POWER_MANAGEMENT_1, 4, 0, NULL, 0), +SND_SOC_DAPM_SUPPLY("LINEOUT_VMID_BUF", WM8993_ANTIPOP1, 7, 0, NULL, 0), +  SND_SOC_DAPM_MIXER("IN1L PGA", WM8993_POWER_MANAGEMENT_2, 6, 0,  		   in1l_pga, ARRAY_SIZE(in1l_pga)),  SND_SOC_DAPM_MIXER("IN1R PGA", WM8993_POWER_MANAGEMENT_2, 4, 0, @@ -834,9 +836,11 @@ static const struct snd_soc_dapm_route lineout1_diff_routes[] = {  };  static const struct snd_soc_dapm_route lineout1_se_routes[] = { +	{ "LINEOUT1N Mixer", NULL, "LINEOUT_VMID_BUF" },  	{ "LINEOUT1N Mixer", "Left Output Switch", "Left Output PGA" },  	{ "LINEOUT1N Mixer", "Right Output Switch", "Right Output PGA" }, +	{ "LINEOUT1P Mixer", NULL, "LINEOUT_VMID_BUF" },  	{ "LINEOUT1P Mixer", "Left Output Switch", "Left Output PGA" },  	{ "LINEOUT1N Driver", NULL, "LINEOUT1N Mixer" }, @@ -844,8 +848,8 @@ static const struct snd_soc_dapm_route lineout1_se_routes[] = {  };  static const struct snd_soc_dapm_route lineout2_diff_routes[] = { -	{ "LINEOUT2 Mixer", "IN2L Switch", "IN2L PGA" }, -	{ "LINEOUT2 Mixer", "IN2R Switch", "IN2R PGA" }, +	{ "LINEOUT2 Mixer", "IN1L Switch", "IN1L PGA" }, +	{ "LINEOUT2 Mixer", "IN1R Switch", "IN1R PGA" },  	{ "LINEOUT2 Mixer", "Output Switch", "Right Output PGA" },  	{ "LINEOUT2N Driver", NULL, "LINEOUT2 Mixer" }, @@ -853,9 +857,11 @@ static const struct snd_soc_dapm_route lineout2_diff_routes[] = {  };  static const struct snd_soc_dapm_route lineout2_se_routes[] = { +	{ "LINEOUT2N Mixer", NULL, "LINEOUT_VMID_BUF" },  	{ "LINEOUT2N Mixer", "Left Output Switch", "Left Output PGA" },  	{ "LINEOUT2N Mixer", "Right Output Switch", "Right Output PGA" }, +	{ "LINEOUT2P Mixer", NULL, "LINEOUT_VMID_BUF" },  	{ "LINEOUT2P Mixer", "Right Output Switch", "Right Output PGA" },  	{ "LINEOUT2N Driver", NULL, "LINEOUT2N Mixer" }, diff --git a/sound/soc/samsung/neo1973_wm8753.c b/sound/soc/samsung/neo1973_wm8753.c index 7ac0ba2025c..c6012ff5bd3 100644 --- a/sound/soc/samsung/neo1973_wm8753.c +++ b/sound/soc/samsung/neo1973_wm8753.c @@ -230,8 +230,6 @@ static const struct snd_kcontrol_new neo1973_wm8753_controls[] = {  /* GTA02 specific routes and controls */ -#ifdef CONFIG_MACH_NEO1973_GTA02 -  static int gta02_speaker_enabled;  static int lm4853_set_spk(struct snd_kcontrol *kcontrol, @@ -311,10 +309,6 @@ static int neo1973_gta02_wm8753_init(struct snd_soc_codec *codec)  	return 0;  } -#else -static int neo1973_gta02_wm8753_init(struct snd_soc_code *codec) { return 0; } -#endif -  static int neo1973_wm8753_init(struct snd_soc_pcm_runtime *rtd)  {  	struct snd_soc_codec *codec = rtd->codec; @@ -322,10 +316,6 @@ static int neo1973_wm8753_init(struct snd_soc_pcm_runtime *rtd)  	int ret;  	/* set up NC codec pins */ -	if (machine_is_neo1973_gta01()) { -		snd_soc_dapm_nc_pin(dapm, "LOUT2"); -		snd_soc_dapm_nc_pin(dapm, "ROUT2"); -	}  	snd_soc_dapm_nc_pin(dapm, "OUT3");  	snd_soc_dapm_nc_pin(dapm, "OUT4");  	snd_soc_dapm_nc_pin(dapm, "LINE1"); @@ -370,50 +360,6 @@ static int neo1973_wm8753_init(struct snd_soc_pcm_runtime *rtd)  	return 0;  } -/* GTA01 specific controls */ - -#ifdef CONFIG_MACH_NEO1973_GTA01 - -static const struct snd_soc_dapm_route neo1973_lm4857_routes[] = { -	{"Amp IN", NULL, "ROUT1"}, -	{"Amp IN", NULL, "LOUT1"}, - -	{"Handset Spk", NULL, "Amp EP"}, -	{"Stereo Out", NULL, "Amp LS"}, -	{"Headphone", NULL, "Amp HP"}, -}; - -static const struct snd_soc_dapm_widget neo1973_lm4857_dapm_widgets[] = { -	SND_SOC_DAPM_SPK("Handset Spk", NULL), -	SND_SOC_DAPM_SPK("Stereo Out", NULL), -	SND_SOC_DAPM_HP("Headphone", NULL), -}; - -static int neo1973_lm4857_init(struct snd_soc_dapm_context *dapm) -{ -	int ret; - -	ret = snd_soc_dapm_new_controls(dapm, neo1973_lm4857_dapm_widgets, -			ARRAY_SIZE(neo1973_lm4857_dapm_widgets)); -	if (ret) -		return ret; - -	ret = snd_soc_dapm_add_routes(dapm, neo1973_lm4857_routes, -			ARRAY_SIZE(neo1973_lm4857_routes)); -	if (ret) -		return ret; - -	snd_soc_dapm_ignore_suspend(dapm, "Stereo Out"); -	snd_soc_dapm_ignore_suspend(dapm, "Handset Spk"); -	snd_soc_dapm_ignore_suspend(dapm, "Headphone"); - -	return 0; -} - -#else -static int neo1973_lm4857_init(struct snd_soc_dapm_context *dapm) { return 0; }; -#endif -  static struct snd_soc_dai_link neo1973_dai[] = {  { /* Hifi Playback - for similatious use with voice below */  	.name = "WM8753", @@ -440,11 +386,6 @@ static struct snd_soc_aux_dev neo1973_aux_devs[] = {  		.name = "dfbmcs320",  		.codec_name = "dfbmcs320.0",  	}, -	{ -		.name = "lm4857", -		.codec_name = "lm4857.0-007c", -		.init = neo1973_lm4857_init, -	},  };  static struct snd_soc_codec_conf neo1973_codec_conf[] = { @@ -454,14 +395,10 @@ static struct snd_soc_codec_conf neo1973_codec_conf[] = {  	},  }; -#ifdef CONFIG_MACH_NEO1973_GTA02  static const struct gpio neo1973_gta02_gpios[] = {  	{ GTA02_GPIO_HP_IN, GPIOF_OUT_INIT_HIGH, "GTA02_HP_IN" },  	{ GTA02_GPIO_AMP_SHUT, GPIOF_OUT_INIT_HIGH, "GTA02_AMP_SHUT" },  }; -#else -static const struct gpio neo1973_gta02_gpios[] = {}; -#endif  static struct snd_soc_card neo1973 = {  	.name = "neo1973", @@ -480,7 +417,7 @@ static int __init neo1973_init(void)  {  	int ret; -	if (!machine_is_neo1973_gta01() && !machine_is_neo1973_gta02()) +	if (!machine_is_neo1973_gta02())  		return -ENODEV;  	if (machine_is_neo1973_gta02()) { diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index db6c89a28bd..ea4a82d0116 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c @@ -1152,12 +1152,8 @@ static snd_pcm_uframes_t fsi_pointer(struct snd_pcm_substream *substream)  {  	struct fsi_priv *fsi = fsi_get_priv(substream);  	struct fsi_stream *io = fsi_get_stream(fsi, fsi_is_play(substream)); -	int samples_pos = io->buff_sample_pos - 1; -	if (samples_pos < 0) -		samples_pos = 0; - -	return fsi_sample2frame(fsi, samples_pos); +	return fsi_sample2frame(fsi, io->buff_sample_pos);  }  static struct snd_pcm_ops fsi_pcm_ops = { diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index b5ecf6d2321..92cee24ed2d 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -567,6 +567,17 @@ int snd_soc_suspend(struct device *dev)  		if (!codec->suspended && codec->driver->suspend) {  			switch (codec->dapm.bias_level) {  			case SND_SOC_BIAS_STANDBY: +				/* +				 * If the CODEC is capable of idle +				 * bias off then being in STANDBY +				 * means it's doing something, +				 * otherwise fall through. +				 */ +				if (codec->dapm.idle_bias_off) { +					dev_dbg(codec->dev, +						"idle_bias_off CODEC on over suspend\n"); +					break; +				}  			case SND_SOC_BIAS_OFF:  				codec->driver->suspend(codec);  				codec->suspended = 1; diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index 8edc5035fc8..d89ab4c7d44 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h @@ -1618,6 +1618,14 @@ YAMAHA_DEVICE(0x7010, "UB99"),  	}  },  { +	/* Edirol UM-3G */ +	USB_DEVICE_VENDOR_SPEC(0x0582, 0x0108), +	.driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { +		.ifnum = 0, +		.type = QUIRK_MIDI_STANDARD_INTERFACE +	} +}, +{  	/* Boss JS-8 Jam Station  */  	USB_DEVICE(0x0582, 0x0109),  	.driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { diff --git a/tools/perf/Makefile b/tools/perf/Makefile index ac86d67b636..7c12650165a 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -104,7 +104,7 @@ endif  CFLAGS = -fno-omit-frame-pointer -ggdb3 -Wall -Wextra -std=gnu99 $(CFLAGS_WERROR) $(CFLAGS_OPTIMIZE) -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS) $(EXTRA_CFLAGS)  EXTLIBS = -lpthread -lrt -lelf -lm -ALL_CFLAGS = $(CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 +ALL_CFLAGS = $(CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE  ALL_LDFLAGS = $(LDFLAGS)  STRIP ?= strip @@ -168,10 +168,7 @@ endif  ### --- END CONFIGURATION SECTION --- -# Those must not be GNU-specific; they are shared with perl/ which may -# be built by a different compiler. (Note that this is an artifact now -# but it still might be nice to keep that distinction.) -BASIC_CFLAGS = -Iutil/include -Iarch/$(ARCH)/include +BASIC_CFLAGS = -Iutil/include -Iarch/$(ARCH)/include -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE  BASIC_LDFLAGS =  # Guard against environment variables diff --git a/tools/perf/bench/mem-memcpy-x86-64-asm.S b/tools/perf/bench/mem-memcpy-x86-64-asm.S index a57b66e853c..185a96d66dd 100644 --- a/tools/perf/bench/mem-memcpy-x86-64-asm.S +++ b/tools/perf/bench/mem-memcpy-x86-64-asm.S @@ -1,2 +1,8 @@  #include "../../../arch/x86/lib/memcpy_64.S" +/* + * We need to provide note.GNU-stack section, saying that we want + * NOT executable stack. Otherwise the final linking will assume that + * the ELF stack should not be restricted at all and set it RWX. + */ +.section .note.GNU-stack,"",@progbits diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c index 59d43abfbfe..fb8566181f2 100644 --- a/tools/perf/builtin-probe.c +++ b/tools/perf/builtin-probe.c @@ -20,7 +20,6 @@   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.   *   */ -#define _GNU_SOURCE  #include <sys/utsname.h>  #include <sys/types.h>  #include <sys/stat.h> @@ -31,7 +30,6 @@  #include <stdlib.h>  #include <string.h> -#undef _GNU_SOURCE  #include "perf.h"  #include "builtin.h"  #include "util/util.h" diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 8f80df89603..dd162aa24ba 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -89,8 +89,6 @@ void get_term_dimensions(struct winsize *ws)  static void perf_top__update_print_entries(struct perf_top *top)  { -	top->print_entries = top->winsize.ws_row; -  	if (top->print_entries > 9)  		top->print_entries -= 9;  } @@ -100,6 +98,13 @@ static void perf_top__sig_winch(int sig __used, siginfo_t *info __used, void *ar  	struct perf_top *top = arg;  	get_term_dimensions(&top->winsize); +	if (!top->print_entries +	    || (top->print_entries+4) > top->winsize.ws_row) { +		top->print_entries = top->winsize.ws_row; +	} else { +		top->print_entries += 4; +		top->winsize.ws_row = top->print_entries; +	}  	perf_top__update_print_entries(top);  } @@ -453,8 +458,10 @@ static void perf_top__handle_keypress(struct perf_top *top, int c)  				};  				perf_top__sig_winch(SIGWINCH, NULL, top);  				sigaction(SIGWINCH, &act, NULL); -			} else +			} else { +				perf_top__sig_winch(SIGWINCH, NULL, top);  				signal(SIGWINCH, SIG_DFL); +			}  			break;  		case 'E':  			if (top->evlist->nr_entries > 1) { diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index 73ddaf06b8e..2044324b755 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c @@ -554,7 +554,7 @@ static int perf_event__process_kernel_mmap(struct perf_tool *tool __used,  	is_kernel_mmap = memcmp(event->mmap.filename,  				kmmap_prefix, -				strlen(kmmap_prefix)) == 0; +				strlen(kmmap_prefix) - 1) == 0;  	if (event->mmap.filename[0] == '/' ||  	    (!is_kernel_mmap && event->mmap.filename[0] == '[')) { diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 667f3b78bb2..7132ee834e0 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -463,6 +463,7 @@ int perf_event__parse_sample(const union perf_event *event, u64 type,  	memset(data, 0, sizeof(*data));  	data->cpu = data->pid = data->tid = -1;  	data->stream_id = data->id = data->time = -1ULL; +	data->period = 1;  	if (event->header.type != PERF_RECORD_SAMPLE) {  		if (!sample_id_all) diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 3e7e0b09c12..ecd7f4dd7ee 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -2105,7 +2105,7 @@ int perf_event__synthesize_event_type(struct perf_tool *tool,  	strncpy(ev.event_type.event_type.name, name, MAX_EVENT_NAME - 1);  	ev.event_type.header.type = PERF_RECORD_HEADER_EVENT_TYPE; -	size = strlen(name); +	size = strlen(ev.event_type.event_type.name);  	size = ALIGN(size, sizeof(u64));  	ev.event_type.header.size = sizeof(ev.event_type) -  		(sizeof(ev.event_type.event_type.name) - size); diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index eb25900e221..29cb6545981 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c @@ -19,7 +19,6 @@   *   */ -#define _GNU_SOURCE  #include <sys/utsname.h>  #include <sys/types.h>  #include <sys/stat.h> @@ -33,7 +32,6 @@  #include <limits.h>  #include <elf.h> -#undef _GNU_SOURCE  #include "util.h"  #include "event.h"  #include "string.h" diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 215d50f2042..0975438c3e7 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -1,4 +1,3 @@ -#define _GNU_SOURCE  #include <ctype.h>  #include <dirent.h>  #include <errno.h> diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c index 6c164dc9ee9..1a8d4dc4f38 100644 --- a/tools/perf/util/trace-event-parse.c +++ b/tools/perf/util/trace-event-parse.c @@ -21,14 +21,13 @@   *  The parts for function graph printing was taken and modified from the   *  Linux Kernel that were written by Frederic Weisbecker.   */ -#define _GNU_SOURCE +  #include <stdio.h>  #include <stdlib.h>  #include <string.h>  #include <ctype.h>  #include <errno.h> -#undef _GNU_SOURCE  #include "../perf.h"  #include "util.h"  #include "trace-event.h" diff --git a/tools/perf/util/ui/browsers/hists.c b/tools/perf/util/ui/browsers/hists.c index 1212a386a03..e81aef1f256 100644 --- a/tools/perf/util/ui/browsers/hists.c +++ b/tools/perf/util/ui/browsers/hists.c @@ -1,6 +1,4 @@ -#define _GNU_SOURCE  #include <stdio.h> -#undef _GNU_SOURCE  #include "../libslang.h"  #include <stdlib.h>  #include <string.h> diff --git a/tools/perf/util/ui/helpline.c b/tools/perf/util/ui/helpline.c index 6ef3c569176..4f48f5901b3 100644 --- a/tools/perf/util/ui/helpline.c +++ b/tools/perf/util/ui/helpline.c @@ -1,4 +1,3 @@ -#define _GNU_SOURCE  #include <stdio.h>  #include <stdlib.h>  #include <string.h> diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h index b9c530cce79..ecf9898169c 100644 --- a/tools/perf/util/util.h +++ b/tools/perf/util/util.h @@ -40,7 +40,6 @@  #define decimal_length(x)	((int)(sizeof(x) * 2.56 + 0.5) + 1)  #define _ALL_SOURCE 1 -#define _GNU_SOURCE 1  #define _BSD_SOURCE 1  #define HAS_BOOL diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 7287bf5d1c9..a91f980077d 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -1543,7 +1543,7 @@ void mark_page_dirty_in_slot(struct kvm *kvm, struct kvm_memory_slot *memslot,  	if (memslot && memslot->dirty_bitmap) {  		unsigned long rel_gfn = gfn - memslot->base_gfn; -		if (!__test_and_set_bit_le(rel_gfn, memslot->dirty_bitmap)) +		if (!test_and_set_bit_le(rel_gfn, memslot->dirty_bitmap))  			memslot->nr_dirty_pages++;  	}  }  |